diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 873d5fa7c1..4fdacfd05c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -112,11 +112,11 @@ void adjustCommandedActor (const MWWorld::Ptr& actor) bool hasCommandPackage = false; - std::list::const_iterator it; - for (it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) + auto it = stats.getAiSequence().begin(); + for (; it != stats.getAiSequence().end(); ++it) { if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow && - static_cast(*it)->isCommanded()) + static_cast(it->get())->isCommanded()) { hasCommandPackage = true; break; @@ -419,7 +419,7 @@ namespace MWMechanics if (world->isSwimming(actor) || (playerPos - actorPos).length2() >= 3000 * 3000) return; - // Our implementation is not FPS-dependent unlike Morrowind's so it needs to be recalibrated. + // Our implementation is not FPS-dependent unlike Morrowind's so it needs to be recalibrated. // We chose to use the chance MW would have when run at 60 FPS with the default value of the GMST. const float delta = MWBase::Environment::get().getFrameDuration() * 6.f; static const float fVoiceIdleOdds = world->getStore().get().find("fVoiceIdleOdds")->mValue.getFloat(); @@ -435,9 +435,9 @@ namespace MWMechanics CreatureStats &stats = actor.getClass().getCreatureStats(actor); MWMechanics::AiSequence& seq = stats.getAiSequence(); - if (!seq.isEmpty() && seq.getActivePackage()->useVariableSpeed()) + if (!seq.isEmpty() && seq.getActivePackage().useVariableSpeed()) { - osg::Vec3f targetPos = seq.getActivePackage()->getDestination(); + osg::Vec3f targetPos = seq.getActivePackage().getDestination(); osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3(); float distance = (targetPos - actorPos).length(); if (distance < DECELERATE_DISTANCE) @@ -604,7 +604,7 @@ namespace MWMechanics bool isPlayerFollowerOrEscorter = playerAllies.find(actor1) != playerAllies.end(); // If actor2 and at least one actor2 are in combat with actor1, actor1 and its allies start combat with them - // Doesn't apply for player followers/escorters + // Doesn't apply for player followers/escorters if (!aggressive && !isPlayerFollowerOrEscorter) { // Check that actor2 is in combat with actor1 @@ -673,7 +673,7 @@ namespace MWMechanics return; bool followerOrEscorter = false; - for (const AiPackage* package : creatureStats2.getAiSequence()) + for (const auto& package : creatureStats2.getAiSequence()) { // The follow package must be first or have nothing but combat before it if (package->sideWithTarget()) @@ -1738,7 +1738,7 @@ namespace MWMechanics if (!isPlayer && isConscious(iter->first) && !stats.isParalyzed()) { MWMechanics::AiSequence& seq = stats.getAiSequence(); - alwaysActive = !seq.isEmpty() && seq.getActivePackage()->alwaysActive(); + alwaysActive = !seq.isEmpty() && seq.getActivePackage().alwaysActive(); } bool inRange = isPlayer || dist <= mActorsProcessingRange || alwaysActive; int activeFlag = 1; // Can be changed back to '2' to keep updating bounding boxes off screen (more accurate, but slower) @@ -2158,7 +2158,7 @@ namespace MWMechanics // An actor counts as siding with this actor if Follow or Escort is the current AI package, or there are only Combat and Wander packages before the Follow/Escort package // Actors that are targeted by this actor's Follow or Escort packages also side with them - for (const AiPackage* package : stats.getAiSequence()) + for (const auto& package : stats.getAiSequence()) { if (package->sideWithTarget() && !package->getTarget().isEmpty()) { @@ -2192,9 +2192,9 @@ namespace MWMechanics if (stats.isDead()) continue; - // An actor counts as following if AiFollow is the current AiPackage, + // An actor counts as following if AiFollow is the current AiPackage, // or there are only Combat and Wander packages before the AiFollow package - for (const AiPackage* package : stats.getAiSequence()) + for (const auto& package : stats.getAiSequence()) { if (package->followTargetThroughDoors() && package->getTarget() == actor) list.push_back(iteratedActor); @@ -2257,11 +2257,11 @@ namespace MWMechanics // An actor counts as following if AiFollow is the current AiPackage, // or there are only Combat and Wander packages before the AiFollow package - for (AiPackage* package : stats.getAiSequence()) + for (const auto& package : stats.getAiSequence()) { if (package->followTargetThroughDoors() && package->getTarget() == actor) { - list.push_back(static_cast(package)->getFollowIndex()); + list.push_back(static_cast(package.get())->getFollowIndex()); break; } else if (package->getTypeId() != AiPackage::TypeIdCombat && package->getTypeId() != AiPackage::TypeIdWander) diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 8ed1f0beec..9f5d4ccaff 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -25,9 +25,8 @@ namespace MWMechanics void AiSequence::copy (const AiSequence& sequence) { - for (std::list::const_iterator iter (sequence.mPackages.begin()); - iter!=sequence.mPackages.end(); ++iter) - mPackages.push_back ((*iter)->clone().release()); + for (const auto& package : sequence.mPackages) + mPackages.push_back(package->clone()); // We need to keep an AiWander storage, if present - it has a state machine. // Not sure about another temporary storages @@ -74,7 +73,7 @@ bool AiSequence::getCombatTarget(MWWorld::Ptr &targetActor) const { if (getTypeId() != AiPackage::TypeIdCombat) return false; - + targetActor = mPackages.front()->getTarget(); return !targetActor.isEmpty(); @@ -82,7 +81,7 @@ bool AiSequence::getCombatTarget(MWWorld::Ptr &targetActor) const bool AiSequence::getCombatTargets(std::vector &targetActors) const { - for (std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for (auto it = mPackages.begin(); it != mPackages.end(); ++it) { if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdCombat) targetActors.push_back((*it)->getTarget()); @@ -91,24 +90,23 @@ bool AiSequence::getCombatTargets(std::vector &targetActors) const return !targetActors.empty(); } -std::list::const_iterator AiSequence::begin() const +std::list>::const_iterator AiSequence::begin() const { return mPackages.begin(); } -std::list::const_iterator AiSequence::end() const +std::list>::const_iterator AiSequence::end() const { return mPackages.end(); } -void AiSequence::erase(std::list::const_iterator package) +void AiSequence::erase(std::list>::const_iterator package) { // Not sure if manually terminated packages should trigger mDone, probably not? - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for(auto it = mPackages.begin(); it != mPackages.end(); ++it) { if (package == it) { - delete *it; mPackages.erase(it); return; } @@ -118,7 +116,7 @@ void AiSequence::erase(std::list::const_iterator package) bool AiSequence::isInCombat() const { - for(std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for (auto it = mPackages.begin(); it != mPackages.end(); ++it) { if ((*it)->getTypeId() == AiPackage::TypeIdCombat) return true; @@ -128,7 +126,7 @@ bool AiSequence::isInCombat() const bool AiSequence::isEngagedWithActor() const { - for (std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for (auto it = mPackages.begin(); it != mPackages.end(); ++it) { if ((*it)->getTypeId() == AiPackage::TypeIdCombat) { @@ -142,7 +140,7 @@ bool AiSequence::isEngagedWithActor() const bool AiSequence::hasPackage(int typeId) const { - for (std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for (auto it = mPackages.begin(); it != mPackages.end(); ++it) { if ((*it)->getTypeId() == typeId) return true; @@ -152,7 +150,7 @@ bool AiSequence::hasPackage(int typeId) const bool AiSequence::isInCombat(const MWWorld::Ptr &actor) const { - for(std::list::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for (auto it = mPackages.begin(); it != mPackages.end(); ++it) { if ((*it)->getTypeId() == AiPackage::TypeIdCombat) { @@ -165,11 +163,10 @@ bool AiSequence::isInCombat(const MWWorld::Ptr &actor) const void AiSequence::stopCombat() { - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ) + for(auto it = mPackages.begin(); it != mPackages.end(); ) { if ((*it)->getTypeId() == AiPackage::TypeIdCombat) { - delete *it; it = mPackages.erase(it); } else @@ -179,11 +176,10 @@ void AiSequence::stopCombat() void AiSequence::stopPursuit() { - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ) + for(auto it = mPackages.begin(); it != mPackages.end(); ) { if ((*it)->getTypeId() == AiPackage::TypeIdPursue) { - delete *it; it = mPackages.erase(it); } else @@ -213,7 +209,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac } auto packageIt = mPackages.begin(); - MWMechanics::AiPackage* package = *packageIt; + MWMechanics::AiPackage* package = packageIt->get(); if (!package->alwaysActive() && outOfRange) return; @@ -231,7 +227,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac float bestRating = 0.f; - for(std::list::iterator it = mPackages.begin(); it != mPackages.end();) + for (auto it = mPackages.begin(); it != mPackages.end();) { if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break; @@ -240,7 +236,6 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac // target disappeared (e.g. summoned creatures) if (target.isEmpty()) { - delete *it; it = mPackages.erase(it); } else @@ -276,24 +271,23 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac } packageIt = mPackages.begin(); - package = *packageIt; + package = packageIt->get(); packageTypeId = package->getTypeId(); } try { - if (package->execute (actor, characterController, mAiState, duration)) + if (package->execute(actor, characterController, mAiState, duration)) { // Put repeating noncombat AI packages on the end of the stack so they can be used again if (isActualAiPackage(packageTypeId) && (mRepeat || package->getRepeat())) { package->reset(); - mPackages.push_back(package->clone().release()); + mPackages.push_back(package->clone()); } // To account for the rare case where AiPackage::execute() queued another AI package // (e.g. AiPursue executing a dialogue script that uses startCombat) mPackages.erase(packageIt); - delete package; if (isActualAiPackage(packageTypeId)) mDone = true; } @@ -311,9 +305,6 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac void AiSequence::clear() { - for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) - delete *iter; - mPackages.clear(); } @@ -340,8 +331,7 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo osg::Vec3f dest; if (currentTypeId == MWMechanics::AiPackage::TypeIdWander) { - AiPackage* activePackage = getActivePackage(); - dest = activePackage->getDestination(actor); + dest = getActivePackage().getDestination(actor); } else { @@ -355,11 +345,10 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo // remove previous packages if required if (cancelOther && package.shouldCancelPreviousAi()) { - for(std::list::iterator it = mPackages.begin(); it != mPackages.end();) + for (auto it = mPackages.begin(); it != mPackages.end();) { if((*it)->canCancel()) { - delete *it; it = mPackages.erase(it); } else @@ -369,7 +358,7 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo } // insert new package in correct place depending on priority - for(std::list::iterator it = mPackages.begin(); it != mPackages.end(); ++it) + for (auto it = mPackages.begin(); it != mPackages.end(); ++it) { // We should keep current AiCast package, if we try to add a new one. if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdCast && @@ -380,12 +369,12 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor, boo if((*it)->getPriority() <= package.getPriority()) { - mPackages.insert(it,package.clone().release()); + mPackages.insert(it, package.clone()); return; } } - mPackages.push_back (package.clone().release()); + mPackages.push_back(package.clone()); // Make sure that temporary storage is empty if (cancelOther) @@ -401,12 +390,11 @@ bool MWMechanics::AiSequence::isEmpty() const return mPackages.empty(); } -AiPackage* MWMechanics::AiSequence::getActivePackage() +const AiPackage& MWMechanics::AiSequence::getActivePackage() { if(mPackages.empty()) throw std::runtime_error(std::string("No AI Package!")); - else - return mPackages.front(); + return *mPackages.front(); } void AiSequence::fill(const ESM::AIPackageList &list) @@ -417,7 +405,7 @@ void AiSequence::fill(const ESM::AIPackageList &list) for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) { - MWMechanics::AiPackage* package; + std::unique_ptr package; if (it->mType == ESM::AI_Wander) { ESM::AIWander data = it->mWander; @@ -425,38 +413,36 @@ void AiSequence::fill(const ESM::AIPackageList &list) idles.reserve(8); for (int i=0; i<8; ++i) idles.push_back(data.mIdle[i]); - package = new MWMechanics::AiWander(data.mDistance, data.mDuration, data.mTimeOfDay, idles, data.mShouldRepeat != 0); + package = std::make_unique(data.mDistance, data.mDuration, data.mTimeOfDay, idles, data.mShouldRepeat != 0); } else if (it->mType == ESM::AI_Escort) { ESM::AITarget data = it->mTarget; - package = new MWMechanics::AiEscort(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); + package = std::make_unique(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); } else if (it->mType == ESM::AI_Travel) { ESM::AITravel data = it->mTravel; - package = new MWMechanics::AiTravel(data.mX, data.mY, data.mZ); + package = std::make_unique(data.mX, data.mY, data.mZ); } else if (it->mType == ESM::AI_Activate) { ESM::AIActivate data = it->mActivate; - package = new MWMechanics::AiActivate(data.mName.toString()); + package = std::make_unique(data.mName.toString()); } else //if (it->mType == ESM::AI_Follow) { ESM::AITarget data = it->mTarget; - package = new MWMechanics::AiFollow(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); + package = std::make_unique(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); } - mPackages.push_back(package); + mPackages.push_back(std::move(package)); } } void AiSequence::writeState(ESM::AiSequence::AiSequence &sequence) const { - for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) - { - (*iter)->writeState(sequence); - } + for (const auto& package : mPackages) + package->writeState(sequence); sequence.mLastAiPackage = mLastAiPackage; } @@ -527,7 +513,7 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence) if (!package.get()) continue; - mPackages.push_back(package.release()); + mPackages.push_back(std::move(package)); } mLastAiPackage = sequence.mLastAiPackage; @@ -537,8 +523,7 @@ void AiSequence::fastForward(const MWWorld::Ptr& actor) { if (!mPackages.empty()) { - MWMechanics::AiPackage* package = mPackages.front(); - package->fastForward(actor, mAiState); + mPackages.front()->fastForward(actor, mAiState); } } diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index 7f07d5aae3..12b837d87a 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -2,6 +2,7 @@ #define GAME_MWMECHANICS_AISEQUENCE_H #include +#include #include "aistate.hpp" @@ -36,7 +37,7 @@ namespace MWMechanics class AiSequence { ///AiPackages to run though - std::list mPackages; + std::list> mPackages; ///Finished with top AIPackage, set for one frame bool mDone; @@ -64,10 +65,10 @@ namespace MWMechanics virtual ~AiSequence(); /// Iterator may be invalidated by any function calls other than begin() or end(). - std::list::const_iterator begin() const; - std::list::const_iterator end() const; + std::list>::const_iterator begin() const; + std::list>::const_iterator end() const; - void erase (std::list::const_iterator package); + void erase(std::list>::const_iterator package); /// Returns currently executing AiPackage type /** \see enum AiPackage::TypeId **/ @@ -125,7 +126,7 @@ namespace MWMechanics /// Return the current active package. /** If there is no active package, it will throw an exception **/ - AiPackage* getActivePackage(); + const AiPackage& getActivePackage(); /// Fills the AiSequence with packages /** Typically used for loading from the ESM diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b7a1d22bf0..4a513e98f5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3063,7 +3063,7 @@ namespace MWWorld { if (actor != MWMechanics::getPlayer()) { - for (const MWMechanics::AiPackage* package : stats.getAiSequence()) + for (const auto& package : stats.getAiSequence()) { if (package->getTypeId() == MWMechanics::AiPackage::TypeIdCast) {