Do not add scripts from levelled creatures twice (Bug #2806)

Do not insert objects from within a CellStore visitor
coverity_scan
scrawl 9 years ago
parent 8e5398d85b
commit c9a67ab423

@ -246,6 +246,7 @@ namespace MWWorld
/// Call visitor (MWWorld::Ptr) for each reference. visitor must return a bool. Returning
/// false will abort the iteration.
/// \note Prefer using forEachConst when possible.
/// \note Do not modify this cell (i.e. remove/add objects) during the forEach, doing this may result in unintended behaviour.
/// \attention This function also lists deleted (count 0) objects!
/// \return Iteration completed?
template<class Visitor>
@ -269,6 +270,7 @@ namespace MWWorld
/// Call visitor (MWWorld::ConstPtr) for each reference. visitor must return a bool. Returning
/// false will abort the iteration.
/// \note Do not modify this cell (i.e. remove/add objects) during the forEach, doing this may result in unintended behaviour.
/// \attention This function also lists deleted (count 0) objects!
/// \return Iteration completed?
template<class Visitor>
@ -291,6 +293,7 @@ namespace MWWorld
/// Call visitor (ref) for each reference of given type. visitor must return a bool. Returning
/// false will abort the iteration.
/// \note Do not modify this cell (i.e. remove/add objects) during the forEach, doing this may result in unintended behaviour.
/// \attention This function also lists deleted (count 0) objects!
/// \return Iteration completed?
template <class T, class Visitor>

@ -86,10 +86,13 @@ namespace
MWPhysics::PhysicsSystem& mPhysics;
MWRender::RenderingManager& mRendering;
std::vector<MWWorld::Ptr> mToInsert;
InsertVisitor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener,
MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering);
bool operator() (const MWWorld::Ptr& ptr);
void insert();
};
InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, bool rescale,
@ -102,6 +105,17 @@ namespace
bool InsertVisitor::operator() (const MWWorld::Ptr& ptr)
{
// do not insert directly as we can't modify the cell from within the visitation
// CreatureLevList::insertObjectRendering may spawn a new creature
mToInsert.push_back(ptr);
return true;
}
void InsertVisitor::insert()
{
for (std::vector<MWWorld::Ptr>::iterator it = mToInsert.begin(); it != mToInsert.end(); ++it)
{
MWWorld::Ptr ptr = *it;
if (mRescale)
{
if (ptr.getCellRef().getScale()<0.5)
@ -125,8 +139,7 @@ namespace
}
mLoadingListener.increaseProgress (1);
return true;
}
}
struct AdjustPositionVisitor
@ -248,6 +261,10 @@ namespace MWWorld
cell->respawn();
// register local scripts
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
// ... then references. This is important for adjustPosition to work correctly.
/// \todo rescale depending on the state of a new GMST
insertCell (*cell, true, loadingListener);
@ -267,10 +284,6 @@ namespace MWWorld
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
mRendering.configureAmbient(cell->getCell());
}
// register local scripts
// ??? Should this go into the above if block ???
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
}
void Scene::changeToVoid()
@ -534,6 +547,7 @@ namespace MWWorld
{
InsertVisitor insertVisitor (cell, rescale, *loadingListener, *mPhysics, mRendering);
cell.forEach (insertVisitor);
insertVisitor.insert();
// do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
AdjustPositionVisitor adjustPosVisitor;

Loading…
Cancel
Save