1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-01 01:39:41 +00:00

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

This commit is contained in:
Evil Eye 2021-08-28 14:36:30 +02:00
parent 161e042e2a
commit b8e4f18751
12 changed files with 31 additions and 19 deletions

View file

@ -56,6 +56,7 @@
Feature #4595: Unique object identifier Feature #4595: Unique object identifier
Feature #4737: Handle instance move from one cell to another Feature #4737: Handle instance move from one cell to another
Feature #5198: Implement "Magic effect expired" event 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 #5489: MCP: Telekinesis fix for activators
Feature #5996: Support Lua scripts in OpenMW Feature #5996: Support Lua scripts in OpenMW
Feature #6017: Separate persistent and temporary cell references when saving Feature #6017: Separate persistent and temporary cell references when saving

View file

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

View file

@ -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; 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 ///< @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 ///< @return an updated Ptr
virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, const osg::Vec3f& vec, bool moveToActive, bool ignoreCollisions) = 0; virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, const osg::Vec3f& vec, bool moveToActive, bool ignoreCollisions) = 0;

View file

@ -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 namespace MWMechanics
@ -1050,7 +1058,7 @@ namespace MWMechanics
void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately) void Actors::addActor (const MWWorld::Ptr& ptr, bool updateImmediately)
{ {
removeActor(ptr); removeActor(ptr, true);
MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr);
if (!anim) if (!anim)
@ -1098,11 +1106,13 @@ namespace MWMechanics
ctrl->setVisibility(visibilityRatio); 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); PtrActorMap::iterator iter = mActors.find(ptr);
if(iter != mActors.end()) if(iter != mActors.end())
{ {
if(!keepActive)
removeTemporaryEffects(iter->first);
delete iter->second; delete iter->second;
mActors.erase(iter); mActors.erase(iter);
} }
@ -1167,6 +1177,7 @@ namespace MWMechanics
{ {
if((iter->first.isInCell() && iter->first.getCell()==cellStore) && iter->first != ignore) if((iter->first.isInCell() && iter->first.getCell()==cellStore) && iter->first != ignore)
{ {
removeTemporaryEffects(iter->first);
delete iter->second; delete iter->second;
mActors.erase(iter++); mActors.erase(iter++);
} }

View file

@ -90,7 +90,7 @@ namespace MWMechanics
/// ///
/// \note Dead actors are ignored. /// \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 ///< Deregister an actor for stats management
/// ///
/// \note Ignored, if \a ptr is not a registered actor. /// \note Ignored, if \a ptr is not a registered actor.

View file

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

View file

@ -45,7 +45,7 @@ namespace MWMechanics
void add (const MWWorld::Ptr& ptr) override; void add (const MWWorld::Ptr& ptr) override;
///< Register an object for management ///< 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 ///< Deregister an object for management
void updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) override; void updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) override;

View file

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

View file

@ -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().getSoundManager()->stopSound3D (ptr);
MWBase::Environment::get().getLuaManager()->objectRemovedFromScene(ptr); MWBase::Environment::get().getLuaManager()->objectRemovedFromScene(ptr);
if (const auto object = mPhysics->getObject(ptr)) if (const auto object = mPhysics->getObject(ptr))

View file

@ -161,7 +161,7 @@ namespace MWWorld
void addObjectToScene (const Ptr& ptr); void addObjectToScene (const Ptr& ptr);
///< Add an object that already exists in the world model to the scene. ///< 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. ///< Remove an object from the scene, but not from the world model.
void removeFromPagedRefs(const Ptr &ptr); void removeFromPagedRefs(const Ptr &ptr);

View file

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

View file

@ -373,7 +373,7 @@ namespace MWWorld
MWWorld::Ptr moveObject (const Ptr& ptr, const osg::Vec3f& position, bool movePhysics=true, bool moveToActive=false) override; 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 ///< @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 ///< @return an updated Ptr
MWWorld::Ptr moveObjectBy(const Ptr& ptr, const osg::Vec3f& vec, bool moveToActive, bool ignoreCollisions) override; MWWorld::Ptr moveObjectBy(const Ptr& ptr, const osg::Vec3f& vec, bool moveToActive, bool ignoreCollisions) override;