diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 9a19c3e1d6..3ec86df232 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -95,7 +95,7 @@ add_openmw_dir (mwmechanics mechanicsmanagerimp stat creaturestats magiceffects movement actorutil spelllist drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance - disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning + disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction summoning character actors objects aistate trading weaponpriority spellpriority weapontype spellutil spelleffects ) diff --git a/apps/openmw/mwmechanics/actor.cpp b/apps/openmw/mwmechanics/actor.cpp deleted file mode 100644 index d1d37eeb56..0000000000 --- a/apps/openmw/mwmechanics/actor.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "actor.hpp" - -#include "character.hpp" - -namespace MWMechanics -{ - Actor::Actor(const MWWorld::Ptr &ptr, MWRender::Animation *animation) - : mPositionAdjusted(false) - { - mCharacterController.reset(new CharacterController(ptr, animation)); - } - - void Actor::updatePtr(const MWWorld::Ptr &newPtr) - { - mCharacterController->updatePtr(newPtr); - } - - CharacterController* Actor::getCharacterController() - { - return mCharacterController.get(); - } - - int Actor::getGreetingTimer() const - { - return mGreetingTimer; - } - - void Actor::setGreetingTimer(int timer) - { - mGreetingTimer = timer; - } - - float Actor::getAngleToPlayer() const - { - return mTargetAngleRadians; - } - - void Actor::setAngleToPlayer(float angle) - { - mTargetAngleRadians = angle; - } - - GreetingState Actor::getGreetingState() const - { - return mGreetingState; - } - - void Actor::setGreetingState(GreetingState state) - { - mGreetingState = state; - } - - bool Actor::isTurningToPlayer() const - { - return mIsTurningToPlayer; - } - - void Actor::setTurningToPlayer(bool turning) - { - mIsTurningToPlayer = turning; - } - - Misc::TimerStatus Actor::updateEngageCombatTimer(float duration) - { - return mEngageCombat.update(duration, MWBase::Environment::get().getWorld()->getPrng()); - } - - void Actor::setPositionAdjusted(bool adjusted) - { - mPositionAdjusted = adjusted; - } - - bool Actor::getPositionAdjusted() const - { - return mPositionAdjusted; - } -} diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index 231c756810..14f21193ea 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -3,7 +3,8 @@ #include -#include "../mwmechanics/actorutil.hpp" +#include "actorutil.hpp" +#include "character.hpp" #include @@ -18,38 +19,44 @@ namespace MWWorld namespace MWMechanics { - class CharacterController; - /// @brief Holds temporary state for an actor that will be discarded when the actor leaves the scene. class Actor { public: - Actor(const MWWorld::Ptr& ptr, MWRender::Animation* animation); + Actor(const MWWorld::Ptr& ptr, MWRender::Animation* animation) + : mCharacterController(ptr, animation) + , mPositionAdjusted(false) + {} + + const MWWorld::Ptr& getPtr() const { return mCharacterController.getPtr(); } /// Notify this actor of its new base object Ptr, use when the object changed cells - void updatePtr(const MWWorld::Ptr& newPtr); + void updatePtr(const MWWorld::Ptr& newPtr) { mCharacterController.updatePtr(newPtr); } - CharacterController* getCharacterController(); + CharacterController& getCharacterController() { return mCharacterController; } - int getGreetingTimer() const; - void setGreetingTimer(int timer); + int getGreetingTimer() const { return mGreetingTimer; } + void setGreetingTimer(int timer) { mGreetingTimer = timer; } - float getAngleToPlayer() const; - void setAngleToPlayer(float angle); + float getAngleToPlayer() const { return mTargetAngleRadians; } + void setAngleToPlayer(float angle) { mTargetAngleRadians = angle; } - GreetingState getGreetingState() const; - void setGreetingState(GreetingState state); + GreetingState getGreetingState() const { return mGreetingState; } + void setGreetingState(GreetingState state) { mGreetingState = state; } - bool isTurningToPlayer() const; - void setTurningToPlayer(bool turning); + bool isTurningToPlayer() const { return mIsTurningToPlayer; } + void setTurningToPlayer(bool turning) { mIsTurningToPlayer = turning; } - Misc::TimerStatus updateEngageCombatTimer(float duration); + Misc::TimerStatus updateEngageCombatTimer(float duration) + { + return mEngageCombat.update(duration, MWBase::Environment::get().getWorld()->getPrng()); + } - void setPositionAdjusted(bool adjusted); - bool getPositionAdjusted() const; + void setPositionAdjusted(bool adjusted) { mPositionAdjusted = adjusted; } + bool getPositionAdjusted() const { return mPositionAdjusted; } private: - std::unique_ptr mCharacterController; + CharacterController mCharacterController; int mGreetingTimer{0}; float mTargetAngleRadians{0.f}; GreetingState mGreetingState{Greet_None}; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index fb78beb8cf..c063748bdc 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -105,12 +105,12 @@ void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float } template -void forEachFollowingPackage(MWMechanics::Actors::PtrActorMap& actors, const MWWorld::Ptr& actor, const MWWorld::Ptr& player, T&& func) +void forEachFollowingPackage(std::list& actors, const MWWorld::Ptr& actorPtr, const MWWorld::Ptr& player, T&& func) { - for(auto& iter : actors) + for (const MWMechanics::Actor& actor : actors) { - const MWWorld::Ptr &iteratedActor = iter.first; - if (iteratedActor == player || iteratedActor == actor) + const MWWorld::Ptr &iteratedActor = actor.getPtr(); + if (iteratedActor == player || iteratedActor == actorPtr) continue; const MWMechanics::CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor); @@ -121,7 +121,7 @@ void forEachFollowingPackage(MWMechanics::Actors::PtrActorMap& actors, const MWW // or there are only Combat and Wander packages before the AiFollow package for (const auto& package : stats.getAiSequence()) { - if(!func(iter, package)) + if (!func(actor, package)) break; } } @@ -771,32 +771,26 @@ namespace MWMechanics bool Actors::isAttackPreparing(const MWWorld::Ptr& ptr) { - PtrActorMap::iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; - CharacterController* ctrl = it->second->getCharacterController(); - - return ctrl->isAttackPreparing(); + return it->second->getCharacterController().isAttackPreparing(); } bool Actors::isRunning(const MWWorld::Ptr& ptr) { - PtrActorMap::iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; - CharacterController* ctrl = it->second->getCharacterController(); - - return ctrl->isRunning(); + return it->second->getCharacterController().isRunning(); } bool Actors::isSneaking(const MWWorld::Ptr& ptr) { - PtrActorMap::iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; - CharacterController* ctrl = it->second->getCharacterController(); - - return ctrl->isSneaking(); + return it->second->getCharacterController().isSneaking(); } void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration, bool isKnockedOut, bool isPlayer) @@ -1031,11 +1025,6 @@ namespace MWMechanics updateProcessingRange(); } - Actors::~Actors() - { - clear(); - } - float Actors::getProcessingRange() const { return mActorsProcessingRange; @@ -1057,11 +1046,11 @@ namespace MWMechanics MWRender::Animation *anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); if (!anim) return; - mActors.emplace(ptr, new Actor(ptr, anim)); + const auto it = mActors.emplace(mActors.end(), ptr, anim); + mIndex.emplace(ptr.mRef, it); - CharacterController* ctrl = mActors[ptr]->getCharacterController(); if (updateImmediately) - ctrl->update(0); + it->getCharacterController().update(0); // We should initially hide actors outside of processing range. // Note: since we update player after other actors, distance will be incorrect during teleportation. @@ -1069,10 +1058,10 @@ namespace MWMechanics if (MWBase::Environment::get().getWorld()->getPlayer().wasTeleported()) return; - updateVisibility(ptr, ctrl); + updateVisibility(ptr, it->getCharacterController()); } - void Actors::updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl) + void Actors::updateVisibility (const MWWorld::Ptr& ptr, CharacterController& ctrl) { MWWorld::Ptr player = MWMechanics::getPlayer(); if (ptr == player) @@ -1097,26 +1086,26 @@ namespace MWMechanics visibilityRatio = std::min(1.f, visibilityRatio); - ctrl->setVisibility(visibilityRatio); + ctrl.setVisibility(visibilityRatio); } void Actors::removeActor (const MWWorld::Ptr& ptr, bool keepActive) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) + const auto iter = mIndex.find(ptr.mRef); + if (iter != mIndex.end()) { if(!keepActive) - removeTemporaryEffects(iter->first); - delete iter->second; - mActors.erase(iter); + removeTemporaryEffects(iter->second->getPtr()); + mActors.erase(iter->second); + mIndex.erase(iter); } } void Actors::castSpell(const MWWorld::Ptr& ptr, const std::string& spellId, bool manualSpell) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) - iter->second->getCharacterController()->castSpell(spellId, manualSpell); + const auto iter = mIndex.find(ptr.mRef); + if (iter != mIndex.end()) + iter->second->getCharacterController().castSpell(spellId, manualSpell); } bool Actors::isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) @@ -1153,27 +1142,20 @@ namespace MWMechanics void Actors::updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { - PtrActorMap::iterator iter = mActors.find(old); - if(iter != mActors.end()) - { - Actor *actor = iter->second; - mActors.erase(iter); - - actor->updatePtr(ptr); - mActors.insert(std::make_pair(ptr, actor)); - } + const auto iter = mIndex.find(old.mRef); + if (iter != mIndex.end()) + iter->second->updatePtr(ptr); } void Actors::dropActors (const MWWorld::CellStore *cellStore, const MWWorld::Ptr& ignore) { - PtrActorMap::iterator iter = mActors.begin(); - while(iter != mActors.end()) + for (auto iter = mActors.begin(); iter != mActors.end();) { - if((iter->first.isInCell() && iter->first.getCell()==cellStore) && iter->first != ignore) + if ((iter->getPtr().isInCell() && iter->getPtr().getCell() == cellStore) && iter->getPtr() != ignore) { - removeTemporaryEffects(iter->first); - delete iter->second; - mActors.erase(iter++); + removeTemporaryEffects(iter->getPtr()); + mIndex.erase(iter->getPtr().mRef); + iter = mActors.erase(iter); } else ++iter; @@ -1189,14 +1171,14 @@ namespace MWMechanics if (aiActive) { - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - if (iter->first == player) continue; + if (actor.getPtr() == player) continue; - bool inProcessingRange = (playerPos - iter->first.getRefData().getPosition().asVec3()).length2() <= mActorsProcessingRange*mActorsProcessingRange; + bool inProcessingRange = (playerPos - actor.getPtr().getRefData().getPosition().asVec3()).length2() <= mActorsProcessingRange*mActorsProcessingRange; if (inProcessingRange) { - MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first); + MWMechanics::CreatureStats& stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); if (!stats.isDead() && stats.getAiSequence().isInCombat()) { hasHostiles = true; @@ -1235,9 +1217,9 @@ namespace MWMechanics const MWWorld::Ptr player = getPlayer(); const MWBase::World* world = MWBase::Environment::get().getWorld(); - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - const MWWorld::Ptr& ptr = iter->first; + const MWWorld::Ptr& ptr = actor.getPtr(); if (ptr == player) continue; // Don't interfere with player controls. @@ -1297,9 +1279,9 @@ namespace MWMechanics float angleToApproachingActor = 0; // Iterate through all other actors and predict collisions. - for(PtrActorMap::iterator otherIter(mActors.begin()); otherIter != mActors.end(); ++otherIter) + for (const Actor& otherActor : mActors) { - const MWWorld::Ptr& otherPtr = otherIter->first; + const MWWorld::Ptr& otherPtr = otherActor.getPtr(); if (otherPtr == ptr || otherPtr == currentTarget) continue; @@ -1410,49 +1392,49 @@ namespace MWMechanics bool godmode = MWBase::Environment::get().getWorld()->getGodModeState(); // AI and magic effects update - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (Actor& actor : mActors) { - bool isPlayer = iter->first == player; - CharacterController* ctrl = iter->second->getCharacterController(); + const bool isPlayer = actor.getPtr() == player; + CharacterController& ctrl = actor.getCharacterController(); MWBase::LuaManager::ActorControls* luaControls = - MWBase::Environment::get().getLuaManager()->getActorControls(iter->first); + MWBase::Environment::get().getLuaManager()->getActorControls(actor.getPtr()); - float distSqr = (playerPos - iter->first.getRefData().getPosition().asVec3()).length2(); + const float distSqr = (playerPos - actor.getPtr().getRefData().getPosition().asVec3()).length2(); // AI processing is only done within given distance to the player. bool inProcessingRange = distSqr <= mActorsProcessingRange*mActorsProcessingRange; // If dead or no longer in combat, no longer store any actors who attempted to hit us. Also remove for the player. - if (iter->first != player && (iter->first.getClass().getCreatureStats(iter->first).isDead() - || !iter->first.getClass().getCreatureStats(iter->first).getAiSequence().isInCombat() + if (actor.getPtr() != player && (actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDead() + || !actor.getPtr().getClass().getCreatureStats(actor.getPtr()).getAiSequence().isInCombat() || !inProcessingRange)) { - iter->first.getClass().getCreatureStats(iter->first).setHitAttemptActorId(-1); - if (player.getClass().getCreatureStats(player).getHitAttemptActorId() == iter->first.getClass().getCreatureStats(iter->first).getActorId()) + actor.getPtr().getClass().getCreatureStats(actor.getPtr()).setHitAttemptActorId(-1); + if (player.getClass().getCreatureStats(player).getHitAttemptActorId() == actor.getPtr().getClass().getCreatureStats(actor.getPtr()).getActorId()) player.getClass().getCreatureStats(player).setHitAttemptActorId(-1); } - const Misc::TimerStatus engageCombatTimerStatus = iter->second->updateEngageCombatTimer(duration); + const Misc::TimerStatus engageCombatTimerStatus = actor.updateEngageCombatTimer(duration); // For dead actors we need to update looping spell particles - if (iter->first.getClass().getCreatureStats(iter->first).isDead()) + if (actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDead()) { // They can be added during the death animation - if (!iter->first.getClass().getCreatureStats(iter->first).isDeathAnimationFinished()) - adjustMagicEffects(iter->first, duration); - ctrl->updateContinuousVfx(); + if (!actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDeathAnimationFinished()) + adjustMagicEffects(actor.getPtr(), duration); + ctrl.updateContinuousVfx(); } else { bool cellChanged = world->hasCellChanged(); - MWWorld::Ptr actor = iter->first; // make a copy of the map key to avoid it being invalidated when the player teleports - updateActor(actor, duration); + const MWWorld::Ptr actorPtr = actor.getPtr(); // make a copy of the map key to avoid it being invalidated when the player teleports + updateActor(actorPtr, duration); // Looping magic VFX update // Note: we need to do this before any of the animations are updated. // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), // so updating VFX immediately after that would just remove the particle effects instantly. // There needs to be a magic effect update in between. - ctrl->updateContinuousVfx(); + ctrl.updateContinuousVfx(); if (!cellChanged && world->hasCellChanged()) { @@ -1464,13 +1446,13 @@ namespace MWMechanics if (engageCombatTimerStatus == Misc::TimerStatus::Elapsed) { if (!isPlayer) - adjustCommandedActor(iter->first); + adjustCommandedActor(actor.getPtr()); - for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it) + for (const Actor& otherActor : mActors) { - if (it->first == iter->first || isPlayer) // player is not AI-controlled + if (otherActor.getPtr() == actor.getPtr() || isPlayer) // player is not AI-controlled continue; - engageCombat(iter->first, it->first, cachedAllies, it->first == player); + engageCombat(actor.getPtr(), otherActor.getPtr(), cachedAllies, otherActor.getPtr() == player); } } if (mTimerUpdateHeadTrack == 0) @@ -1478,7 +1460,7 @@ namespace MWMechanics float sqrHeadTrackDistance = std::numeric_limits::max(); MWWorld::Ptr headTrackTarget; - MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first); + MWMechanics::CreatureStats& stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); bool firstPersonPlayer = isPlayer && world->isFirstPerson(); // 1. Unconsious actor can not track target @@ -1493,58 +1475,58 @@ namespace MWMechanics if (!activePackageTarget.isEmpty()) { // Track the specified target of package. - updateHeadTracking(iter->first, activePackageTarget, headTrackTarget, sqrHeadTrackDistance, inCombatOrPursue); + updateHeadTracking(actor.getPtr(), activePackageTarget, headTrackTarget, sqrHeadTrackDistance, inCombatOrPursue); } } else { // Find something nearby. - for (auto& [ptr, _] : mActors) + for (const Actor& otherActor : mActors) { - if (ptr == iter->first) + if (otherActor.getPtr() == actor.getPtr()) continue; - updateHeadTracking(iter->first, ptr, headTrackTarget, sqrHeadTrackDistance, inCombatOrPursue); + updateHeadTracking(actor.getPtr(), otherActor.getPtr(), headTrackTarget, sqrHeadTrackDistance, inCombatOrPursue); } } } - ctrl->setHeadTrackTarget(headTrackTarget); + ctrl.setHeadTrackTarget(headTrackTarget); } - if (iter->first.getClass().isNpc() && iter->first != player) - updateCrimePursuit(iter->first, duration); + if (actor.getPtr().getClass().isNpc() && actor.getPtr() != player) + updateCrimePursuit(actor.getPtr(), duration); - if (iter->first != player) + if (actor.getPtr() != player) { - CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first); - if (isConscious(iter->first) && !(luaControls && luaControls->mDisableAI)) + CreatureStats &stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); + if (isConscious(actor.getPtr()) && !(luaControls && luaControls->mDisableAI)) { - stats.getAiSequence().execute(iter->first, *ctrl, duration); - updateGreetingState(iter->first, *iter->second, mTimerUpdateHello > 0); - playIdleDialogue(iter->first); - updateMovementSpeed(iter->first); + stats.getAiSequence().execute(actor.getPtr(), ctrl, duration); + updateGreetingState(actor.getPtr(), actor, mTimerUpdateHello > 0); + playIdleDialogue(actor.getPtr()); + updateMovementSpeed(actor.getPtr()); } } } - else if (aiActive && iter->first != player && isConscious(iter->first) && !(luaControls && luaControls->mDisableAI)) + else if (aiActive && actor.getPtr() != player && isConscious(actor.getPtr()) && !(luaControls && luaControls->mDisableAI)) { - CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first); - stats.getAiSequence().execute(iter->first, *ctrl, duration, /*outOfRange*/true); + CreatureStats &stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); + stats.getAiSequence().execute(actor.getPtr(), ctrl, duration, /*outOfRange*/true); } - if(inProcessingRange && iter->first.getClass().isNpc()) + if (inProcessingRange && actor.getPtr().getClass().isNpc()) { // We can not update drowning state for actors outside of AI distance - they can not resurface to breathe - updateDrowning(iter->first, duration, ctrl->isKnockedOut(), isPlayer); + updateDrowning(actor.getPtr(), duration, ctrl.isKnockedOut(), isPlayer); } - if(mTimerUpdateEquippedLight == 0 && iter->first.getClass().hasInventoryStore(iter->first)) - updateEquippedLight(iter->first, updateEquippedLightInterval, showTorches); + if (mTimerUpdateEquippedLight == 0 && actor.getPtr().getClass().hasInventoryStore(actor.getPtr())) + updateEquippedLight(actor.getPtr(), updateEquippedLightInterval, showTorches); - if (luaControls && isConscious(iter->first)) + if (luaControls && isConscious(actor.getPtr())) { - Movement& mov = iter->first.getClass().getMovementSettings(iter->first); - CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first); + Movement& mov = actor.getPtr().getClass().getMovementSettings(actor.getPtr()); + CreatureStats& stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); float speedFactor = isPlayer ? 1.f : mov.mSpeedFactor; osg::Vec2f movement = osg::Vec2f(mov.mPosition[0], mov.mPosition[1]) * speedFactor; float rotationX = mov.mRotation[0]; @@ -1587,14 +1569,14 @@ namespace MWMechanics // Animation/movement update CharacterController* playerCharacter = nullptr; - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (Actor& actor : mActors) { - const float dist = (playerPos - iter->first.getRefData().getPosition().asVec3()).length(); - bool isPlayer = iter->first == player; - CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first); + const float dist = (playerPos - actor.getPtr().getRefData().getPosition().asVec3()).length(); + const bool isPlayer = actor.getPtr() == player; + CreatureStats &stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); // Actors with active AI should be able to move. bool alwaysActive = false; - if (!isPlayer && isConscious(iter->first) && !stats.isParalyzed()) + if (!isPlayer && isConscious(actor.getPtr()) && !stats.isParalyzed()) { MWMechanics::AiSequence& seq = stats.getAiSequence(); alwaysActive = !seq.isEmpty() && seq.getActivePackage().alwaysActive(); @@ -1605,41 +1587,41 @@ namespace MWMechanics activeFlag = 2; int active = inRange ? activeFlag : 0; - CharacterController* ctrl = iter->second->getCharacterController(); - ctrl->setActive(active); + CharacterController& ctrl = actor.getCharacterController(); + ctrl.setActive(active); if (!inRange) { - iter->first.getRefData().getBaseNode()->setNodeMask(0); - world->setActorCollisionMode(iter->first, false, false); + actor.getPtr().getRefData().getBaseNode()->setNodeMask(0); + world->setActorCollisionMode(actor.getPtr(), false, false); continue; } else if (!isPlayer) { - iter->first.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); - if (!iter->second->getPositionAdjusted()) + actor.getPtr().getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); + if (!actor.getPositionAdjusted()) { - iter->first.getClass().adjustPosition(iter->first, false); - iter->second->setPositionAdjusted(true); + actor.getPtr().getClass().adjustPosition(actor.getPtr(), false); + actor.setPositionAdjusted(true); } } - const bool isDead = iter->first.getClass().getCreatureStats(iter->first).isDead(); - if (!isDead && (!godmode || !isPlayer) && iter->first.getClass().getCreatureStats(iter->first).isParalyzed()) - ctrl->skipAnim(); + const bool isDead = actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDead(); + if (!isDead && (!godmode || !isPlayer) && actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isParalyzed()) + ctrl.skipAnim(); // Handle player last, in case a cell transition occurs by casting a teleportation spell // (would invalidate the iterator) - if (iter->first == getPlayer()) + if (actor.getPtr() == getPlayer()) { - playerCharacter = ctrl; + playerCharacter = &ctrl; continue; } - world->setActorCollisionMode(iter->first, true, !iter->first.getClass().getCreatureStats(iter->first).isDeathAnimationFinished()); - ctrl->update(duration); + world->setActorCollisionMode(actor.getPtr(), true, !actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDeathAnimationFinished()); + ctrl.update(duration); - updateVisibility(iter->first, ctrl); + updateVisibility(actor.getPtr(), ctrl); } if (playerCharacter) @@ -1649,10 +1631,10 @@ namespace MWMechanics playerCharacter->setVisibility(1.f); } - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - const MWWorld::Class &cls = iter->first.getClass(); - CreatureStats &stats = cls.getCreatureStats(iter->first); + const MWWorld::Class &cls = actor.getPtr().getClass(); + CreatureStats &stats = cls.getCreatureStats(actor.getPtr()); //KnockedOutOneFrameLogic //Used for "OnKnockedOut" command @@ -1684,53 +1666,53 @@ namespace MWMechanics void Actors::resurrect(const MWWorld::Ptr &ptr) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) + const auto iter = mIndex.find(ptr.mRef); + if (iter != mIndex.end()) { - if(iter->second->getCharacterController()->isDead()) + if (iter->second->getCharacterController().isDead()) { // Actor has been resurrected. Notify the CharacterController and re-enable collision. - MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true); - iter->second->getCharacterController()->resurrect(); + MWBase::Environment::get().getWorld()->enableActorCollision(iter->second->getPtr(), true); + iter->second->getCharacterController().resurrect(); } } } void Actors::killDeadActors() { - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (Actor& actor : mActors) { - const MWWorld::Class &cls = iter->first.getClass(); - CreatureStats &stats = cls.getCreatureStats(iter->first); + const MWWorld::Class &cls = actor.getPtr().getClass(); + CreatureStats &stats = cls.getCreatureStats(actor.getPtr()); if(!stats.isDead()) continue; - MWBase::Environment::get().getWorld()->removeActorPath(iter->first); - CharacterController::KillResult killResult = iter->second->getCharacterController()->kill(); + MWBase::Environment::get().getWorld()->removeActorPath(actor.getPtr()); + CharacterController::KillResult killResult = actor.getCharacterController().kill(); if (killResult == CharacterController::Result_DeathAnimStarted) { // Play dying words // Note: It's not known whether the soundgen tags scream, roar, and moan are reliable // for NPCs since some of the npc death animation files are missing them. - MWBase::Environment::get().getDialogueManager()->say(iter->first, "hit"); + MWBase::Environment::get().getDialogueManager()->say(actor.getPtr(), "hit"); // Apply soultrap - if (iter->first.getType() == ESM::Creature::sRecordId) - soulTrap(iter->first); + if (actor.getPtr().getType() == ESM::Creature::sRecordId) + soulTrap(actor.getPtr()); - if (cls.isEssential(iter->first)) + if (cls.isEssential(actor.getPtr())) MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } else if (killResult == CharacterController::Result_DeathAnimJustFinished) { - bool isPlayer = iter->first == getPlayer(); - notifyDied(iter->first); + const bool isPlayer = actor.getPtr() == getPlayer(); + notifyDied(actor.getPtr()); // Reset magic effects and recalculate derived effects // One case where we need this is to make sure bound items are removed upon death float vampirism = stats.getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude(); - stats.getActiveSpells().clear(iter->first); + stats.getActiveSpells().clear(actor.getPtr()); // Make sure spell effects are removed purgeSpellEffects(stats.getActorId()); @@ -1746,7 +1728,7 @@ namespace MWMechanics else { // NPC death animation is over, disable actor collision - MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); + MWBase::Environment::get().getWorld()->enableActorCollision(actor.getPtr(), false); } } } @@ -1785,10 +1767,10 @@ namespace MWMechanics void Actors::purgeSpellEffects(int casterActorId) { - for (PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (const Actor& actor : mActors) { - MWMechanics::ActiveSpells& spells = iter->first.getClass().getCreatureStats(iter->first).getActiveSpells(); - spells.purge(iter->first, casterActorId); + MWMechanics::ActiveSpells& spells = actor.getPtr().getClass().getCreatureStats(actor.getPtr()).getActiveSpells(); + spells.purge(actor.getPtr(), casterActorId); } } @@ -1802,28 +1784,28 @@ namespace MWMechanics const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); const osg::Vec3f playerPos = player.getRefData().getPosition().asVec3(); - for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - if (iter->first.getClass().getCreatureStats(iter->first).isDead()) + if (actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDead()) { - adjustMagicEffects (iter->first, duration); + adjustMagicEffects(actor.getPtr(), duration); continue; } - if (!sleep || iter->first == player) - restoreDynamicStats(iter->first, hours, sleep); + if (!sleep || actor.getPtr() == player) + restoreDynamicStats(actor.getPtr(), hours, sleep); - if ((!iter->first.getRefData().getBaseNode()) || - (playerPos - iter->first.getRefData().getPosition().asVec3()).length2() > mActorsProcessingRange*mActorsProcessingRange) + if ((!actor.getPtr().getRefData().getBaseNode()) || + (playerPos - actor.getPtr().getRefData().getPosition().asVec3()).length2() > mActorsProcessingRange*mActorsProcessingRange) continue; - adjustMagicEffects (iter->first, duration); + adjustMagicEffects (actor.getPtr(), duration); - MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first); + MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(actor.getPtr()); if (animation) { animation->removeEffects(); - MWBase::Environment::get().getWorld()->applyLoopingParticles(iter->first); + MWBase::Environment::get().getWorld()->applyLoopingParticles(actor.getPtr()); } } @@ -1935,17 +1917,17 @@ namespace MWMechanics void Actors::forceStateUpdate(const MWWorld::Ptr & ptr) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) - iter->second->getCharacterController()->forceStateUpdate(); + const auto iter = mIndex.find(ptr.mRef); + if (iter != mIndex.end()) + iter->second->getCharacterController().forceStateUpdate(); } bool Actors::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) + const auto iter = mIndex.find(ptr.mRef); + if(iter != mIndex.end()) { - return iter->second->getCharacterController()->playGroup(groupName, mode, number, persist); + return iter->second->getCharacterController().playGroup(groupName, mode, number, persist); } else { @@ -1955,55 +1937,55 @@ namespace MWMechanics } void Actors::skipAnimation(const MWWorld::Ptr& ptr) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) - iter->second->getCharacterController()->skipAnim(); + const auto iter = mIndex.find(ptr.mRef); + if (iter != mIndex.end()) + iter->second->getCharacterController().skipAnim(); } bool Actors::checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName) { - PtrActorMap::iterator iter = mActors.find(ptr); - if(iter != mActors.end()) - return iter->second->getCharacterController()->isAnimPlaying(groupName); + const auto iter = mIndex.find(ptr.mRef); + if(iter != mIndex.end()) + return iter->second->getCharacterController().isAnimPlaying(groupName); return false; } void Actors::persistAnimationStates() { - for (PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter) - iter->second->getCharacterController()->persistAnimationState(); + for (Actor& actor : mActors) + actor.getCharacterController().persistAnimationState(); } void Actors::getObjectsInRange(const osg::Vec3f& position, float radius, std::vector& out) { - for (PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - if ((iter->first.getRefData().getPosition().asVec3() - position).length2() <= radius*radius) - out.push_back(iter->first); + if ((actor.getPtr().getRefData().getPosition().asVec3() - position).length2() <= radius*radius) + out.push_back(actor.getPtr()); } } bool Actors::isAnyObjectInRange(const osg::Vec3f& position, float radius) { - for (PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - if ((iter->first.getRefData().getPosition().asVec3() - position).length2() <= radius*radius) + if ((actor.getPtr().getRefData().getPosition().asVec3() - position).length2() <= radius*radius) return true; } return false; } - std::vector Actors::getActorsSidingWith(const MWWorld::Ptr& actor) + std::vector Actors::getActorsSidingWith(const MWWorld::Ptr& actorPtr) { std::vector list; - for(PtrActorMap::iterator iter = mActors.begin(); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - const MWWorld::Ptr &iteratedActor = iter->first; + const MWWorld::Ptr& iteratedActor = actor.getPtr(); if (iteratedActor == getPlayer()) continue; - const bool sameActor = (iteratedActor == actor); + const bool sameActor = (iteratedActor == actorPtr); const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor); if (stats.isDead()) @@ -2019,7 +2001,7 @@ namespace MWMechanics { list.push_back(package->getTarget()); } - else if (package->getTarget() == actor) + else if (package->getTarget() == actorPtr) { list.push_back(iteratedActor); } @@ -2032,13 +2014,13 @@ namespace MWMechanics return list; } - std::vector Actors::getActorsFollowing(const MWWorld::Ptr& actor) + std::vector Actors::getActorsFollowing(const MWWorld::Ptr& actorPtr) { std::vector list; - forEachFollowingPackage(mActors, actor, getPlayer(), [&] (auto& iter, const std::shared_ptr& package) + forEachFollowingPackage(mActors, actorPtr, getPlayer(), [&] (const Actor& actor, const std::shared_ptr& package) { - if (package->followTargetThroughDoors() && package->getTarget() == actor) - list.push_back(iter.first); + if (package->followTargetThroughDoors() && package->getTarget() == actorPtr) + list.push_back(actor.getPtr()); else if (package->getTypeId() != AiPackageTypeId::Combat && package->getTypeId() != AiPackageTypeId::Wander) return false; return true; @@ -2086,7 +2068,7 @@ namespace MWMechanics std::vector Actors::getActorsFollowingIndices(const MWWorld::Ptr &actor) { std::vector list; - forEachFollowingPackage(mActors, actor, getPlayer(), [&] (auto& iter, const std::shared_ptr& package) + forEachFollowingPackage(mActors, actor, getPlayer(), [&] (const Actor&, const std::shared_ptr& package) { if (package->followTargetThroughDoors() && package->getTarget() == actor) { @@ -2103,12 +2085,12 @@ namespace MWMechanics std::map Actors::getActorsFollowingByIndex(const MWWorld::Ptr &actor) { std::map map; - forEachFollowingPackage(mActors, actor, getPlayer(), [&] (auto& iter, const std::shared_ptr& package) + forEachFollowingPackage(mActors, actor, getPlayer(), [&] (const Actor& otherActor, const std::shared_ptr& package) { if (package->followTargetThroughDoors() && package->getTarget() == actor) { int index = static_cast(package.get())->getFollowIndex(); - map[index] = iter.first; + map[index] = otherActor.getPtr(); return false; } else if (package->getTypeId() != AiPackageTypeId::Combat && package->getTypeId() != AiPackageTypeId::Wander) @@ -2190,12 +2172,7 @@ namespace MWMechanics void Actors::clear() { - PtrActorMap::iterator it(mActors.begin()); - for (; it != mActors.end(); ++it) - { - delete it->second; - it->second = nullptr; - } + mIndex.clear(); mActors.clear(); mDeathCount.clear(); } @@ -2207,36 +2184,35 @@ namespace MWMechanics bool Actors::isReadyToBlock(const MWWorld::Ptr &ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; - return it->second->getCharacterController()->isReadyToBlock(); + return it->second->getCharacterController().isReadyToBlock(); } bool Actors::isCastingSpell(const MWWorld::Ptr &ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; - return it->second->getCharacterController()->isCastingSpell(); + return it->second->getCharacterController().isCastingSpell(); } bool Actors::isAttackingOrSpell(const MWWorld::Ptr& ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; - CharacterController* ctrl = it->second->getCharacterController(); - return ctrl->isAttackingOrSpell(); + return it->second->getCharacterController().isAttackingOrSpell(); } int Actors::getGreetingTimer(const MWWorld::Ptr& ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return 0; return it->second->getGreetingTimer(); @@ -2244,8 +2220,8 @@ namespace MWMechanics float Actors::getAngleToPlayer(const MWWorld::Ptr& ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return 0.f; return it->second->getAngleToPlayer(); @@ -2253,8 +2229,8 @@ namespace MWMechanics GreetingState Actors::getGreetingState(const MWWorld::Ptr& ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return Greet_None; return it->second->getGreetingState(); @@ -2262,8 +2238,8 @@ namespace MWMechanics bool Actors::isTurningToPlayer(const MWWorld::Ptr& ptr) const { - PtrActorMap::const_iterator it = mActors.find(ptr); - if (it == mActors.end()) + const auto it = mIndex.find(ptr.mRef); + if (it == mIndex.end()) return false; return it->second->isTurningToPlayer(); @@ -2274,11 +2250,9 @@ namespace MWMechanics if (!MWBase::Environment::get().getMechanicsManager()->isAIActive()) return; - // making a copy since fast-forward could move actor to a different cell and invalidate the mActors iterator - PtrActorMap map = mActors; - for (PtrActorMap::iterator it = map.begin(); it != map.end(); ++it) + for (const Actor& actor : mActors) { - MWWorld::Ptr ptr = it->first; + const MWWorld::Ptr ptr = actor.getPtr(); if (ptr == getPlayer() || !isConscious(ptr) || ptr.getClass().getCreatureStats(ptr).isParalyzed()) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 1bc45774d0..a1f93a5dc5 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -7,7 +7,8 @@ #include #include -#include "../mwmechanics/actorutil.hpp" +#include "actorutil.hpp" +#include "actor.hpp" namespace ESM { @@ -42,12 +43,9 @@ namespace MWMechanics public: Actors(); - ~Actors(); - typedef std::map PtrActorMap; - - PtrActorMap::const_iterator begin() { return mActors.begin(); } - PtrActorMap::const_iterator end() { return mActors.end(); } + std::list::const_iterator begin() const { return mActors.begin(); } + std::list::const_iterator end() const { return mActors.end(); } std::size_t size() const { return mActors.size(); } void notifyDied(const MWWorld::Ptr &actor); @@ -190,7 +188,8 @@ namespace MWMechanics }; std::map mDeathCount; - PtrActorMap mActors; + std::list mActors; + std::map::iterator> mIndex; float mTimerDisposeSummonsCorpses; float mTimerUpdateHeadTrack = 0; float mTimerUpdateEquippedLight = 0; @@ -201,7 +200,7 @@ namespace MWMechanics bool mSmoothMovement; MusicType mCurrentMusic = MusicType::Explore; - void updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl); + void updateVisibility (const MWWorld::Ptr& ptr, CharacterController& ctrl); void adjustMagicEffects (const MWWorld::Ptr& creature, float duration); diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index e8e7f2b721..38f7a48a2b 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -241,7 +241,10 @@ public: CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); virtual ~CharacterController(); - const MWWorld::Ptr& getPtr() const { return mPtr; }; + CharacterController(const CharacterController&) = delete; + CharacterController(CharacterController&&) = delete; + + const MWWorld::Ptr& getPtr() const { return mPtr; } void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map) override; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 8cf6126cba..2fd5a81f0d 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -30,6 +30,7 @@ #include "npcstats.hpp" #include "actorutil.hpp" #include "combat.hpp" +#include "actor.hpp" namespace { @@ -1599,16 +1600,16 @@ namespace MWMechanics if (ptr.getClass().isClass(ptr, "Guard")) { stats.setHitAttemptActorId(target.getClass().getCreatureStats(target).getActorId()); // Stops guard from ending combat if player is unreachable - for (Actors::PtrActorMap::const_iterator iter = mActors.begin(); iter != mActors.end(); ++iter) + for (const Actor& actor : mActors) { - if (iter->first.getClass().isClass(iter->first, "Guard")) + if (actor.getPtr().getClass().isClass(actor.getPtr(), "Guard")) { - MWMechanics::AiSequence& aiSeq = iter->first.getClass().getCreatureStats(iter->first).getAiSequence(); + MWMechanics::AiSequence& aiSeq = actor.getPtr().getClass().getCreatureStats(actor.getPtr()).getAiSequence(); if (aiSeq.getTypeId() == MWMechanics::AiPackageTypeId::Pursue) { aiSeq.stopPursuit(); aiSeq.stack(MWMechanics::AiCombat(target), ptr); - iter->first.getClass().getCreatureStats(iter->first).setHitAttemptActorId(target.getClass().getCreatureStats(target).getActorId()); // Stops guard from ending combat if player is unreachable + actor.getPtr().getClass().getCreatureStats(actor.getPtr()).setHitAttemptActorId(target.getClass().getCreatureStats(target).getActorId()); // Stops guard from ending combat if player is unreachable } } } diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index c77521d06e..5a474abf1c 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -22,12 +22,12 @@ void Objects::addObject(const MWWorld::Ptr& ptr) return; const auto it = mObjects.emplace(mObjects.end(), ptr, anim); - mIndex.emplace(ptr.getBase(), it); + mIndex.emplace(ptr.mRef, it); } void Objects::removeObject(const MWWorld::Ptr& ptr) { - const auto iter = mIndex.find(ptr.getBase()); + const auto iter = mIndex.find(ptr.mRef); if (iter != mIndex.end()) { mObjects.erase(iter->second); @@ -37,7 +37,7 @@ void Objects::removeObject(const MWWorld::Ptr& ptr) void Objects::updateObject(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { - const auto iter = mIndex.find(old.getBase()); + const auto iter = mIndex.find(old.mRef); if (iter != mIndex.end()) iter->second->updatePtr(ptr); } @@ -48,7 +48,7 @@ void Objects::dropObjects (const MWWorld::CellStore *cellStore) { if (iter->getPtr().getCell() == cellStore) { - mIndex.erase(iter->getPtr().getBase()); + mIndex.erase(iter->getPtr().mRef); iter = mObjects.erase(iter); } else @@ -86,7 +86,7 @@ void Objects::update(float duration, bool paused) bool Objects::onOpen(const MWWorld::Ptr& ptr) { - const auto iter = mIndex.find(ptr.getBase()); + const auto iter = mIndex.find(ptr.mRef); if (iter != mIndex.end()) return iter->second->onOpen(); return true; @@ -94,14 +94,14 @@ bool Objects::onOpen(const MWWorld::Ptr& ptr) void Objects::onClose(const MWWorld::Ptr& ptr) { - const auto iter = mIndex.find(ptr.getBase()); + const auto iter = mIndex.find(ptr.mRef); if (iter != mIndex.end()) iter->second->onClose(); } bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist) { - const auto iter = mIndex.find(ptr.getBase()); + const auto iter = mIndex.find(ptr.mRef); if (iter != mIndex.end()) { return iter->second->playGroup(groupName, mode, number, persist); @@ -114,7 +114,7 @@ bool Objects::playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& gro } void Objects::skipAnimation(const MWWorld::Ptr& ptr) { - const auto iter = mIndex.find(ptr.getBase()); + const auto iter = mIndex.find(ptr.mRef); if (iter != mIndex.end()) iter->second->skipAnim(); }