Clear temporary effects before unloading actors to prevent absorb effects becoming permanent

pull/3145/head
Evil Eye 3 years ago
parent 161e042e2a
commit b8e4f18751

@ -56,6 +56,7 @@
Feature #4595: Unique object identifier
Feature #4737: Handle instance move from one cell to another
Feature #5198: Implement "Magic effect expired" event
Feature #5454: Clear active spells from actor when he disappears from scene
Feature #5489: MCP: Telekinesis fix for activators
Feature #5996: Support Lua scripts in OpenMW
Feature #6017: Separate persistent and temporary cell references when saving

@ -58,7 +58,7 @@ namespace MWBase
virtual void add (const MWWorld::Ptr& ptr) = 0;
///< Register an object for management
virtual void remove (const MWWorld::Ptr& ptr) = 0;
virtual void remove (const MWWorld::Ptr& ptr, bool keepActive) = 0;
///< Deregister an object for management
virtual void updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) = 0;

@ -286,7 +286,7 @@ namespace MWBase
virtual MWWorld::Ptr moveObject (const MWWorld::Ptr& ptr, const osg::Vec3f& position, bool movePhysics=true, bool moveToActive=false) = 0;
///< @return an updated Ptr in case the Ptr's cell changes
virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, const osg::Vec3f& position, bool movePhysics=true) = 0;
virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, const osg::Vec3f& position, bool movePhysics=true, bool keepActive=false) = 0;
///< @return an updated Ptr
virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, const osg::Vec3f& vec, bool moveToActive, bool ignoreCollisions) = 0;

@ -210,6 +210,14 @@ void soulTrap(const MWWorld::Ptr& creature)
}
}
}
void removeTemporaryEffects(const MWWorld::Ptr& ptr)
{
ptr.getClass().getCreatureStats(ptr).getActiveSpells().purge([] (const auto& spell)
{
return spell.getType() == ESM::ActiveSpells::Type_Consumable || spell.getType() == ESM::ActiveSpells::Type_Temporary;
}, ptr);
}
}
namespace MWMechanics
@ -1050,7 +1058,7 @@ namespace MWMechanics
void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately)
{
removeActor(ptr);
removeActor(ptr, true);
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
if (!anim)
@ -1098,11 +1106,13 @@ namespace MWMechanics
ctrl->setVisibility(visibilityRatio);
}
void Actors::removeActor (const MWWorld::Ptr& ptr)
void Actors::removeActor (const MWWorld::Ptr& ptr, bool keepActive)
{
PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end())
{
if(!keepActive)
removeTemporaryEffects(iter->first);
delete iter->second;
mActors.erase(iter);
}
@ -1167,6 +1177,7 @@ namespace MWMechanics
{
if((iter->first.isInCell() && iter->first.getCell()==cellStore) && iter->first != ignore)
{
removeTemporaryEffects(iter->first);
delete iter->second;
mActors.erase(iter++);
}

@ -90,7 +90,7 @@ namespace MWMechanics
///
/// \note Dead actors are ignored.
void removeActor (const MWWorld::Ptr& ptr);
void removeActor (const MWWorld::Ptr& ptr, bool keepActive);
///< Deregister an actor for stats management
///
/// \note Ignored, if \a ptr is not a registered actor.

@ -259,11 +259,11 @@ namespace MWMechanics
mActors.castSpell(ptr, spellId, manualSpell);
}
void MechanicsManager::remove(const MWWorld::Ptr& ptr)
void MechanicsManager::remove(const MWWorld::Ptr& ptr, bool keepActive)
{
if(ptr == MWBase::Environment::get().getWindowManager()->getWatchedActor())
MWBase::Environment::get().getWindowManager()->watchActor(MWWorld::Ptr());
mActors.removeActor(ptr);
mActors.removeActor(ptr, keepActive);
mObjects.removeObject(ptr);
}
@ -317,7 +317,7 @@ namespace MWMechanics
// HACK? The player has been changed, so a new Animation object may
// have been made for them. Make sure they're properly updated.
mActors.removeActor(ptr);
mActors.removeActor(ptr, true);
mActors.addActor(ptr, true);
}

@ -45,7 +45,7 @@ namespace MWMechanics
void add (const MWWorld::Ptr& ptr) override;
///< Register an object for management
void remove (const MWWorld::Ptr& ptr) override;
void remove (const MWWorld::Ptr& ptr, bool keepActive) override;
///< Deregister an object for management
void updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) override;

@ -55,10 +55,10 @@ namespace MWWorld
int cellY;
world->positionToIndex(mPosition.pos[0],mPosition.pos[1],cellX,cellY);
world->moveObject(actor,world->getExterior(cellX,cellY),
mPosition.asVec3());
mPosition.asVec3(), true, true);
}
else
world->moveObject(actor,world->getInterior(mCellName),mPosition.asVec3());
world->moveObject(actor,world->getInterior(mCellName),mPosition.asVec3(), true, true);
}
}

@ -1010,9 +1010,9 @@ namespace MWWorld
}
}
void Scene::removeObjectFromScene (const Ptr& ptr)
void Scene::removeObjectFromScene (const Ptr& ptr, bool keepActive)
{
MWBase::Environment::get().getMechanicsManager()->remove (ptr);
MWBase::Environment::get().getMechanicsManager()->remove (ptr, keepActive);
MWBase::Environment::get().getSoundManager()->stopSound3D (ptr);
MWBase::Environment::get().getLuaManager()->objectRemovedFromScene(ptr);
if (const auto object = mPhysics->getObject(ptr))

@ -161,7 +161,7 @@ namespace MWWorld
void addObjectToScene (const Ptr& ptr);
///< Add an object that already exists in the world model to the scene.
void removeObjectFromScene (const Ptr& ptr);
void removeObjectFromScene (const Ptr& ptr, bool keepActive = false);
///< Remove an object from the scene, but not from the world model.
void removeFromPagedRefs(const Ptr &ptr);

@ -1114,7 +1114,7 @@ namespace MWWorld
}
}
MWWorld::Ptr World::moveObject(const Ptr &ptr, CellStore* newCell, const osg::Vec3f& position, bool movePhysics)
MWWorld::Ptr World::moveObject(const Ptr &ptr, CellStore* newCell, const osg::Vec3f& position, bool movePhysics, bool keepActive)
{
ESM::Position pos = ptr.getRefData().getPosition();
std::memcpy(pos.pos, &position, sizeof(osg::Vec3f));
@ -1171,7 +1171,7 @@ namespace MWWorld
}
else if (!newCellActive && currCellActive)
{
mWorldScene->removeObjectFromScene(ptr);
mWorldScene->removeObjectFromScene(ptr, keepActive);
mLocalScripts.remove(ptr);
removeContainerScripts (ptr);
haveToMove = false;
@ -2433,7 +2433,7 @@ namespace MWWorld
else
{
// Remove the old CharacterController
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr());
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr(), true);
mNavigator->removeAgent(getPathfindingHalfExtents(getPlayerConstPtr()));
mPhysics->remove(getPlayerPtr());
mRendering->removePlayer(getPlayerPtr());
@ -2449,7 +2449,7 @@ namespace MWWorld
void World::renderPlayer()
{
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr());
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr(), true);
MWWorld::Ptr player = getPlayerPtr();

@ -373,7 +373,7 @@ namespace MWWorld
MWWorld::Ptr moveObject (const Ptr& ptr, const osg::Vec3f& position, bool movePhysics=true, bool moveToActive=false) override;
///< @return an updated Ptr in case the Ptr's cell changes
MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, const osg::Vec3f& position, bool movePhysics=true) override;
MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, const osg::Vec3f& position, bool movePhysics=true, bool keepActive=false) override;
///< @return an updated Ptr
MWWorld::Ptr moveObjectBy(const Ptr& ptr, const osg::Vec3f& vec, bool moveToActive, bool ignoreCollisions) override;

Loading…
Cancel
Save