diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index 5a9e3d6d8..5a96f4cdb 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -34,7 +34,7 @@ namespace MWMechanics void writeState(ESM::AiSequence::AiSequence& sequence) const final; private: - std::string mObjectId; + const std::string mObjectId; }; } #endif // GAME_MWMECHANICS_AIACTIVATE_H diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index cc02c4de1..fdbf7ebc7 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -33,7 +33,7 @@ namespace MWMechanics private: float mDuration; - MWWorld::ConstPtr mDoorPtr; + const MWWorld::ConstPtr mDoorPtr; osg::Vec3f mLastPos; int mDirection; diff --git a/apps/openmw/mwmechanics/aicast.cpp b/apps/openmw/mwmechanics/aicast.cpp index de61851cd..cc4c03bf1 100644 --- a/apps/openmw/mwmechanics/aicast.cpp +++ b/apps/openmw/mwmechanics/aicast.cpp @@ -10,12 +10,22 @@ #include "creaturestats.hpp" #include "steering.hpp" +namespace MWMechanics +{ + namespace + { + float getInitialDistance(const std::string& spellId) + { + ActionSpell action = ActionSpell(spellId); + bool isRanged; + return action.getCombatRange(isRanged); + } + } +} + MWMechanics::AiCast::AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell) - : mTargetId(targetId), mSpellId(spellId), mCasting(false), mManual(manualSpell), mDistance(0) + : mTargetId(targetId), mSpellId(spellId), mCasting(false), mManual(manualSpell), mDistance(getInitialDistance(spellId)) { - ActionSpell action = ActionSpell(spellId); - bool isRanged; - mDistance = action.getCombatRange(isRanged); } bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::CharacterController& characterController, MWMechanics::AiState& state, float duration) diff --git a/apps/openmw/mwmechanics/aicast.hpp b/apps/openmw/mwmechanics/aicast.hpp index 21b629f24..cdf7db2bf 100644 --- a/apps/openmw/mwmechanics/aicast.hpp +++ b/apps/openmw/mwmechanics/aicast.hpp @@ -27,11 +27,11 @@ namespace MWMechanics bool shouldCancelPreviousAi() const final { return false; } private: - std::string mTargetId; - std::string mSpellId; + const std::string mTargetId; + const std::string mSpellId; bool mCasting; - bool mManual; - float mDistance; + const bool mManual; + const float mDistance; }; } diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 5e1d38331..216547f58 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -26,7 +26,6 @@ namespace MWMechanics , mCellY(std::numeric_limits::max()) { mTargetActorRefId = actorId; - mMaxDist = 450; } AiEscort::AiEscort(const std::string &actorId, const std::string &cellId, int duration, float x, float y, float z) @@ -35,24 +34,20 @@ namespace MWMechanics , mCellY(std::numeric_limits::max()) { mTargetActorRefId = actorId; - mMaxDist = 450; } AiEscort::AiEscort(const ESM::AiSequence::AiEscort *escort) : mCellId(escort->mCellId), mX(escort->mData.mX), mY(escort->mData.mY), mZ(escort->mData.mZ) - , mMaxDist(450) + // mDuration isn't saved in the save file, so just giving it "1" for now if the package has a duration. + // The exact value of mDuration only matters for repeating packages. + // Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves. + , mDuration(escort->mRemainingDuration > 0) , mRemainingDuration(escort->mRemainingDuration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) { mTargetActorRefId = escort->mTargetId; mTargetActorId = escort->mTargetActorId; - // mDuration isn't saved in the save file, so just giving it "1" for now if the package has a duration. - // The exact value of mDuration only matters for repeating packages. - if (mRemainingDuration > 0) // Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves. - mDuration = 1; - else - mDuration = 0; } bool AiEscort::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index 9f5ac2f42..c12de1fac 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -45,16 +45,16 @@ namespace MWMechanics osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); } private: - std::string mCellId; - float mX; - float mY; - float mZ; - float mMaxDist; - float mDuration; // In hours + const std::string mCellId; + const float mX; + const float mY; + const float mZ; + float mMaxDist = 450; + const float mDuration; // In hours float mRemainingDuration; // In hours - int mCellX; - int mCellY; + const int mCellX; + const int mCellY; }; } #endif diff --git a/apps/openmw/mwmechanics/aiface.hpp b/apps/openmw/mwmechanics/aiface.hpp index ce1c9847b..516dd18dc 100644 --- a/apps/openmw/mwmechanics/aiface.hpp +++ b/apps/openmw/mwmechanics/aiface.hpp @@ -20,7 +20,8 @@ namespace MWMechanics bool shouldCancelPreviousAi() const final { return false; } private: - float mTargetX, mTargetY; + const float mTargetX; + const float mTargetY; }; } diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index bffa238d5..eb5b595ab 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -58,18 +58,17 @@ AiFollow::AiFollow(const MWWorld::Ptr& actor, bool commanded) } AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow) - : mAlwaysFollow(follow->mAlwaysFollow), mCommanded(follow->mCommanded), mRemainingDuration(follow->mRemainingDuration) + : mAlwaysFollow(follow->mAlwaysFollow), mCommanded(follow->mCommanded) + // mDuration isn't saved in the save file, so just giving it "1" for now if the package had a duration. + // The exact value of mDuration only matters for repeating packages. + // Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves. + , mDuration(follow->mRemainingDuration) + , mRemainingDuration(follow->mRemainingDuration) , mX(follow->mData.mX), mY(follow->mData.mY), mZ(follow->mData.mZ) , mCellId(follow->mCellId), mActive(follow->mActive), mFollowIndex(mFollowIndexCounter++) { mTargetActorRefId = follow->mTargetId; mTargetActorId = follow->mTargetActorId; - // mDuration isn't saved in the save file, so just giving it "1" for now if the package had a duration. - // The exact value of mDuration only matters for repeating packages. - if (mRemainingDuration > 0) // Previously mRemainingDuration could be negative even when mDuration was 0. Checking for > 0 should fix old saves. - mDuration = 1; - else - mDuration = 0; } bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 39a10294b..865f4171b 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -86,16 +86,16 @@ namespace MWMechanics private: /// This will make the actor always follow. /** Thus ignoring mDuration and mX,mY,mZ (used for summoned creatures). **/ - bool mAlwaysFollow; - bool mCommanded; - float mDuration; // Hours + const bool mAlwaysFollow; + const bool mCommanded; + const float mDuration; // Hours float mRemainingDuration; // Hours - float mX; - float mY; - float mZ; - std::string mCellId; + const float mX; + const float mY; + const float mZ; + const std::string mCellId; bool mActive; // have we spotted the target? - int mFollowIndex; + const int mFollowIndex; static int mFollowIndexCounter; }; diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index beaf2819f..4f785e237 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -37,11 +37,11 @@ namespace MWMechanics osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); } private: - float mX; - float mY; - float mZ; + const float mX; + const float mY; + const float mZ; - bool mHidden; + const bool mHidden; }; } diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 50a46432b..584131bbe 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -1,5 +1,7 @@ #include "aiwander.hpp" +#include + #include #include #include @@ -33,6 +35,8 @@ namespace MWMechanics // distance must be long enough that NPC will need to move to get there. static const int MINIMUM_WANDER_DISTANCE = DESTINATION_TOLERANCE * 2; + static const std::size_t MAX_IDLE_SIZE = 8; + const std::string AiWander::sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1] = { std::string("idle2"), @@ -94,25 +98,28 @@ namespace MWMechanics { actor.getClass().getMovementSettings(actor).mPosition[1] = 0; } + + std::vector getInitialIdle(const std::vector& idle) + { + std::vector result(MAX_IDLE_SIZE, 0); + std::copy_n(idle.begin(), std::min(MAX_IDLE_SIZE, idle.size()), result.begin()); + return result; + } + + std::vector getInitialIdle(const unsigned char (&idle)[MAX_IDLE_SIZE]) + { + return std::vector(std::begin(idle), std::end(idle)); + } } AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat): - mDistance(distance), mDuration(duration), mRemainingDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), + mDistance(std::max(0, distance)), + mDuration(std::max(0, duration)), + mRemainingDuration(duration), mTimeOfDay(timeOfDay), + mIdle(getInitialIdle(idle)), mRepeat(repeat), mStoredInitialActorPosition(false), mInitialActorPosition(osg::Vec3f(0, 0, 0)), mHasDestination(false), mDestination(osg::Vec3f(0, 0, 0)), mUsePathgrid(false) { - mIdle.resize(8, 0); - init(); - } - - void AiWander::init() - { - // NOTE: mDistance and mDuration must be set already - - if(mDistance < 0) - mDistance = 0; - if(mDuration < 0) - mDuration = 0; } /* @@ -235,7 +242,6 @@ namespace MWMechanics stopWalking(actor); // Reset package so it can be used again mRemainingDuration=mDuration; - init(); return true; } @@ -879,10 +885,11 @@ namespace MWMechanics } AiWander::AiWander (const ESM::AiSequence::AiWander* wander) - : mDistance(wander->mData.mDistance) - , mDuration(wander->mData.mDuration) + : mDistance(std::max(static_cast(0), wander->mData.mDistance)) + , mDuration(std::max(static_cast(0), wander->mData.mDuration)) , mRemainingDuration(wander->mDurationData.mRemainingDuration) , mTimeOfDay(wander->mData.mTimeOfDay) + , mIdle(getInitialIdle(wander->mData.mIdle)) , mRepeat(wander->mData.mShouldRepeat != 0) , mStoredInitialActorPosition(wander->mStoredInitialActorPosition) , mHasDestination(false) @@ -891,11 +898,7 @@ namespace MWMechanics { if (mStoredInitialActorPosition) mInitialActorPosition = wander->mInitialActorPosition; - for (int i=0; i<8; ++i) - mIdle.push_back(wander->mData.mIdle[i]); if (mRemainingDuration <= 0 || mRemainingDuration >= 24) mRemainingDuration = mDuration; - - init(); } } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index bb5872eef..8eb735205 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -114,8 +114,6 @@ namespace MWMechanics } private: - // NOTE: mDistance and mDuration must be set already - void init(); void stopWalking(const MWWorld::Ptr& actor); /// Have the given actor play an idle animation @@ -136,12 +134,12 @@ namespace MWMechanics bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination); void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage); - int mDistance; // how far the actor can wander from the spawn point - int mDuration; + const int mDistance; // how far the actor can wander from the spawn point + const int mDuration; float mRemainingDuration; - int mTimeOfDay; - std::vector mIdle; - bool mRepeat; + const int mTimeOfDay; + const std::vector mIdle; + const bool mRepeat; bool mStoredInitialActorPosition; osg::Vec3f mInitialActorPosition; // Note: an original engine does not reset coordinates even when actor changes a cell