diff --git a/apps/openmw/mwmechanics/actor.cpp b/apps/openmw/mwmechanics/actor.cpp index 675bd160a..f7c6b7f1c 100644 --- a/apps/openmw/mwmechanics/actor.cpp +++ b/apps/openmw/mwmechanics/actor.cpp @@ -4,7 +4,6 @@ namespace MWMechanics { - Actor::Actor(const MWWorld::Ptr &ptr, MWRender::Animation *animation) { mCharacterController.reset(new CharacterController(ptr, animation)); @@ -19,10 +18,4 @@ namespace MWMechanics { return mCharacterController.get(); } - - AiState& Actor::getAiState() - { - return mAiState; - } - } diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index b8e114ead..119527b64 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -3,8 +3,6 @@ #include -#include "aistate.hpp" - namespace MWRender { class Animation; @@ -29,12 +27,8 @@ namespace MWMechanics CharacterController* getCharacterController(); - AiState& getAiState(); - private: std::unique_ptr mCharacterController; - - AiState mAiState; }; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ec256a321..a225014b4 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1365,7 +1365,7 @@ namespace MWMechanics { CreatureStats &stats = iter->first.getClass().getCreatureStats(iter->first); if (isConscious(iter->first)) - stats.getAiSequence().execute(iter->first, *iter->second->getCharacterController(), iter->second->getAiState(), duration); + stats.getAiSequence().execute(iter->first, *iter->second->getCharacterController(), duration); } } @@ -1993,7 +1993,7 @@ namespace MWMechanics || ptr.getClass().getCreatureStats(ptr).isParalyzed()) continue; MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - seq.fastForward(ptr, it->second->getAiState()); + seq.fastForward(ptr); } } } diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 06248fa10..bc6d22326 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -35,74 +35,6 @@ namespace namespace MWMechanics { - - /// \brief This class holds the variables AiCombat needs which are deleted if the package becomes inactive. - struct AiCombatStorage : AiTemporaryBase - { - float mAttackCooldown; - float mTimerReact; - float mTimerCombatMove; - bool mReadyToAttack; - bool mAttack; - float mAttackRange; - bool mCombatMove; - osg::Vec3f mLastTargetPos; - const MWWorld::CellStore* mCell; - std::shared_ptr mCurrentAction; - float mActionCooldown; - float mStrength; - bool mForceNoShortcut; - ESM::Position mShortcutFailPos; - MWMechanics::Movement mMovement; - - enum FleeState - { - FleeState_None, - FleeState_Idle, - FleeState_RunBlindly, - FleeState_RunToDestination - }; - FleeState mFleeState; - bool mLOS; - float mUpdateLOSTimer; - float mFleeBlindRunTimer; - ESM::Pathgrid::Point mFleeDest; - - AiCombatStorage(): - mAttackCooldown(0.0f), - mTimerReact(AI_REACTION_TIME), - mTimerCombatMove(0.0f), - mReadyToAttack(false), - mAttack(false), - mAttackRange(0.0f), - mCombatMove(false), - mLastTargetPos(0,0,0), - mCell(NULL), - mCurrentAction(), - mActionCooldown(0.0f), - mStrength(), - mForceNoShortcut(false), - mShortcutFailPos(), - mMovement(), - mFleeState(FleeState_None), - mLOS(false), - mUpdateLOSTimer(0.0f), - mFleeBlindRunTimer(0.0f) - {} - - void startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target); - void updateCombatMove(float duration); - void stopCombatMove(); - void startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController, - const ESM::Weapon* weapon, bool distantCombat); - void updateAttack(CharacterController& characterController); - void stopAttack(); - - void startFleeing(); - void stopFleeing(); - bool isFleeing(); - }; - AiCombat::AiCombat(const MWWorld::Ptr& actor) { mTargetActorId = actor.getClass().getCreatureStats(actor).getActorId(); @@ -115,7 +47,7 @@ namespace MWMechanics void AiCombat::init() { - + } /* diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 6e1f0c623..7c9891bcc 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -23,7 +23,72 @@ namespace MWMechanics { class Action; - struct AiCombatStorage; + /// \brief This class holds the variables AiCombat needs which are deleted if the package becomes inactive. + struct AiCombatStorage : AiTemporaryBase + { + float mAttackCooldown; + float mTimerReact; + float mTimerCombatMove; + bool mReadyToAttack; + bool mAttack; + float mAttackRange; + bool mCombatMove; + osg::Vec3f mLastTargetPos; + const MWWorld::CellStore* mCell; + std::shared_ptr mCurrentAction; + float mActionCooldown; + float mStrength; + bool mForceNoShortcut; + ESM::Position mShortcutFailPos; + MWMechanics::Movement mMovement; + + enum FleeState + { + FleeState_None, + FleeState_Idle, + FleeState_RunBlindly, + FleeState_RunToDestination + }; + FleeState mFleeState; + bool mLOS; + float mUpdateLOSTimer; + float mFleeBlindRunTimer; + ESM::Pathgrid::Point mFleeDest; + + AiCombatStorage(): + mAttackCooldown(0.0f), + mTimerReact(AI_REACTION_TIME), + mTimerCombatMove(0.0f), + mReadyToAttack(false), + mAttack(false), + mAttackRange(0.0f), + mCombatMove(false), + mLastTargetPos(0,0,0), + mCell(NULL), + mCurrentAction(), + mActionCooldown(0.0f), + mStrength(), + mForceNoShortcut(false), + mShortcutFailPos(), + mMovement(), + mFleeState(FleeState_None), + mLOS(false), + mUpdateLOSTimer(0.0f), + mFleeBlindRunTimer(0.0f) + {} + + void startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target); + void updateCombatMove(float duration); + void stopCombatMove(); + void startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController, + const ESM::Weapon* weapon, bool distantCombat); + void updateAttack(CharacterController& characterController); + void stopAttack(); + + void startFleeing(); + void stopFleeing(); + bool isFleeing(); + }; /// \brief Causes the actor to fight another actor class AiCombat : public AiPackage diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 13de01f9a..a8f071310 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -17,22 +17,6 @@ namespace MWMechanics { - -struct AiFollowStorage : AiTemporaryBase -{ - float mTimer; - bool mMoving; - float mTargetAngleRadians; - bool mTurnActorToTarget; - - AiFollowStorage() : - mTimer(0.f), - mMoving(false), - mTargetAngleRadians(0.f), - mTurnActorToTarget(false) - {} -}; - int AiFollow::mFollowIndexCounter = 0; AiFollow::AiFollow(const std::string &actorId, float duration, float x, float y, float z) diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index f0d43c9a7..96249e28c 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -19,6 +19,21 @@ namespace AiSequence namespace MWMechanics { + struct AiFollowStorage : AiTemporaryBase + { + float mTimer; + bool mMoving; + float mTargetAngleRadians; + bool mTurnActorToTarget; + + AiFollowStorage() : + mTimer(0.f), + mMoving(false), + mTargetAngleRadians(0.f), + mTurnActorToTarget(false) + {} + }; + /// \brief AiPackage for an actor to follow another actor/the PC /** The AI will follow the target until a condition (time, or position) are set. Both can be disabled to cause the actor to follow the other indefinitely **/ diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 85afbc453..e3b7c63fc 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -188,7 +188,7 @@ bool isActualAiPackage(int packageTypeId) && packageTypeId != AiPackage::TypeIdInternalTravel); } -void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) +void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& characterController, float duration) { if(actor != getPlayer()) { @@ -262,7 +262,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac try { - if (package->execute (actor,characterController,state,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())) @@ -494,12 +494,12 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence) mLastAiPackage = sequence.mLastAiPackage; } -void AiSequence::fastForward(const MWWorld::Ptr& actor, AiState& state) +void AiSequence::fastForward(const MWWorld::Ptr& actor) { if (!mPackages.empty()) { MWMechanics::AiPackage* package = mPackages.front(); - package->fastForward(actor, state); + package->fastForward(actor, mAiState); } } diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index d725409de..5c72bcc4c 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -3,6 +3,8 @@ #include +#include "aistate.hpp" + #include namespace MWWorld @@ -47,6 +49,7 @@ namespace MWMechanics /// The type of AI package that ran last int mLastAiPackage; + AiState mAiState; public: ///Default constructor @@ -104,10 +107,10 @@ namespace MWMechanics void stopPursuit(); /// Execute current package, switching if needed. - void execute (const MWWorld::Ptr& actor, CharacterController& characterController, MWMechanics::AiState& state, float duration); + void execute (const MWWorld::Ptr& actor, CharacterController& characterController, float duration); /// Simulate the passing of time using the currently active AI package - void fastForward(const MWWorld::Ptr &actor, AiState &state); + void fastForward(const MWWorld::Ptr &actor); /// Remove all packages. void clear(); diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index ee680159e..928b09cf9 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -51,67 +51,6 @@ namespace MWMechanics std::string("idle9"), }; - /// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive. - struct AiWanderStorage : AiTemporaryBase - { - // the z rotation angle to reach - // when mTurnActorGivingGreetingToFacePlayer is true - float mTargetAngleRadians; - bool mTurnActorGivingGreetingToFacePlayer; - float mReaction; // update some actions infrequently - - AiWander::GreetingState mSaidGreeting; - int mGreetingTimer; - - const MWWorld::CellStore* mCell; // for detecting cell change - - // AiWander states - AiWander::WanderState mState; - - bool mIsWanderingManually; - bool mCanWanderAlongPathGrid; - - unsigned short mIdleAnimation; - std::vector mBadIdles; // Idle animations that when called cause errors - - // do we need to calculate allowed nodes based on mDistance - bool mPopulateAvailableNodes; - - // allowed pathgrid nodes based on mDistance from the spawn point - // in local coordinates of mCell - std::vector mAllowedNodes; - - ESM::Pathgrid::Point mCurrentNode; - bool mTrimCurrentNode; - - float mDoorCheckDuration; - int mStuckCount; - - AiWanderStorage(): - mTargetAngleRadians(0), - mTurnActorGivingGreetingToFacePlayer(false), - mReaction(0), - mSaidGreeting(AiWander::Greet_None), - mGreetingTimer(0), - mCell(NULL), - mState(AiWander::Wander_ChooseAction), - mIsWanderingManually(false), - mCanWanderAlongPathGrid(true), - mIdleAnimation(0), - mBadIdles(), - mPopulateAvailableNodes(true), - mAllowedNodes(), - mTrimCurrentNode(false), - mDoorCheckDuration(0), // TODO: maybe no longer needed - mStuckCount(0) - {}; - - void setState(const AiWander::WanderState wanderState, const bool isManualWander = false) { - mState = wanderState; - mIsWanderingManually = isManualWander; - } - }; - AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat): mDistance(distance), mDuration(duration), mRemainingDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat), mStoredInitialActorPosition(false), mInitialActorPosition(osg::Vec3f(0, 0, 0)), mHasDestination(false), mDestination(osg::Vec3f(0, 0, 0)) @@ -221,7 +160,7 @@ namespace MWMechanics mPathFinder.buildSyncedPath(start, dest, actor.getCell(), getPathGridGraph(actor.getCell())); if (mPathFinder.isPathConstructed()) - storage.setState(Wander_Walking); + storage.setState(AiWanderStorage::Wander_Walking); } doPerFrameActionsForState(actor, duration, storage, pos); @@ -270,7 +209,7 @@ namespace MWMechanics if(actorCanMoveByZ && mDistance > 0) { // Typically want to idle for a short time before the next wander - if (Misc::Rng::rollDice(100) >= 92 && storage.mState != Wander_Walking) { + if (Misc::Rng::rollDice(100) >= 92 && storage.mState != AiWanderStorage::Wander_Walking) { wanderNearStart(actor, storage, mDistance); } @@ -283,7 +222,7 @@ namespace MWMechanics if (Misc::Rng::rollDice(100) >= 96) { wanderNearStart(actor, storage, mDistance); } else { - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } } else if (storage.mAllowedNodes.empty() && !storage.mIsWanderingManually) { storage.mCanWanderAlongPathGrid = false; @@ -299,13 +238,13 @@ namespace MWMechanics mDistance = 0; // Allow interrupting a walking actor to trigger a greeting - WanderState& wanderState = storage.mState; - if ((wanderState == Wander_IdleNow) || (wanderState == Wander_Walking)) + AiWanderStorage::WanderState& wanderState = storage.mState; + if ((wanderState == AiWanderStorage::Wander_IdleNow) || (wanderState == AiWanderStorage::Wander_Walking)) { playGreetingIfPlayerGetsTooClose(actor, storage); } - if ((wanderState == Wander_MoveNow) && storage.mCanWanderAlongPathGrid) + if ((wanderState == AiWanderStorage::Wander_MoveNow) && storage.mCanWanderAlongPathGrid) { // Construct a new path if there isn't one if(!mPathFinder.isPathConstructed()) @@ -381,7 +320,7 @@ namespace MWMechanics if (mPathFinder.isPathConstructed()) { - storage.setState(Wander_Walking, true); + storage.setState(AiWanderStorage::Wander_Walking, true); mHasDestination = true; } return; @@ -410,26 +349,26 @@ namespace MWMechanics void AiWander::completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage) { stopWalking(actor, storage); mObstacleCheck.clear(); - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos) { switch (storage.mState) { - case Wander_IdleNow: + case AiWanderStorage::Wander_IdleNow: onIdleStatePerFrameActions(actor, duration, storage); break; - case Wander_Walking: + case AiWanderStorage::Wander_Walking: onWalkingStatePerFrameActions(actor, duration, storage, pos); break; - case Wander_ChooseAction: + case AiWanderStorage::Wander_ChooseAction: onChooseActionStatePerFrameActions(actor, storage); break; - case Wander_MoveNow: + case AiWanderStorage::Wander_MoveNow: break; // nothing to do default: @@ -451,7 +390,7 @@ namespace MWMechanics if (mDistance && // actor is not intended to be stationary proximityToDoor(actor, distance*1.6f)) { - storage.setState(Wander_MoveNow); + storage.setState(AiWanderStorage::Wander_MoveNow); storage.mTrimCurrentNode = false; // just in case return; } @@ -468,13 +407,13 @@ namespace MWMechanics } // Check if idle animation finished - GreetingState& greetingState = storage.mSaidGreeting; - if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None)) + AiWanderStorage::GreetingState& greetingState = storage.mSaidGreeting; + if (!checkIdle(actor, storage.mIdleAnimation) && (greetingState == AiWanderStorage::Greet_Done || greetingState == AiWanderStorage::Greet_None)) { if (mPathFinder.isPathConstructed()) - storage.setState(Wander_Walking); + storage.setState(AiWanderStorage::Wander_Walking); else - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); } } @@ -485,7 +424,7 @@ namespace MWMechanics if ((!mPathFinder.isPathConstructed()) || pathTo(actor, ESM::Pathgrid::Point(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE)) { stopWalking(actor, storage); - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); } else { @@ -502,7 +441,7 @@ namespace MWMechanics if (!idleAnimation && mDistance) { - storage.setState(Wander_MoveNow); + storage.setState(AiWanderStorage::Wander_MoveNow); return; } if(idleAnimation) @@ -512,13 +451,13 @@ namespace MWMechanics if(!playIdle(actor, idleAnimation)) { storage.mBadIdles.push_back(idleAnimation); - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); return; } } } - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos) @@ -534,7 +473,7 @@ namespace MWMechanics trimAllowedNodes(storage.mAllowedNodes, mPathFinder); mObstacleCheck.clear(); stopWalking(actor, storage); - storage.setState(Wander_MoveNow); + storage.setState(AiWanderStorage::Wander_MoveNow); } storage.mStuckCount++; // TODO: maybe no longer needed @@ -545,7 +484,7 @@ namespace MWMechanics { mObstacleCheck.clear(); stopWalking(actor, storage); - storage.setState(Wander_ChooseAction); + storage.setState(AiWanderStorage::Wander_ChooseAction); storage.mStuckCount = 0; } } @@ -596,8 +535,8 @@ namespace MWMechanics float playerDistSqr = (playerPos - actorPos).length2(); int& greetingTimer = storage.mGreetingTimer; - GreetingState& greetingState = storage.mSaidGreeting; - if (greetingState == Greet_None) + AiWanderStorage::GreetingState& greetingState = storage.mSaidGreeting; + if (greetingState == AiWanderStorage::Greet_None) { if ((playerDistSqr <= helloDistance*helloDistance) && !player.getClass().getCreatureStats(player).isDead() && MWBase::Environment::get().getWorld()->getLOS(player, actor) @@ -606,37 +545,37 @@ namespace MWMechanics if (greetingTimer >= GREETING_SHOULD_START) { - greetingState = Greet_InProgress; + greetingState = AiWanderStorage::Greet_InProgress; MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); greetingTimer = 0; } } - if (greetingState == Greet_InProgress) + if (greetingState == AiWanderStorage::Greet_InProgress) { greetingTimer++; - if (storage.mState == Wander_Walking) + if (storage.mState == AiWanderStorage::Wander_Walking) { stopWalking(actor, storage, false); mObstacleCheck.clear(); - storage.setState(Wander_IdleNow); + storage.setState(AiWanderStorage::Wander_IdleNow); } turnActorToFacePlayer(actorPos, playerPos, storage); if (greetingTimer >= GREETING_SHOULD_END) { - greetingState = Greet_Done; + greetingState = AiWanderStorage::Greet_Done; greetingTimer = 0; } } - if (greetingState == MWMechanics::AiWander::Greet_Done) + if (greetingState == AiWanderStorage::Greet_Done) { float resetDist = 2 * helloDistance; if (playerDistSqr >= resetDist*resetDist) - greetingState = Greet_None; + greetingState = AiWanderStorage::Greet_None; } } @@ -676,7 +615,7 @@ namespace MWMechanics storage.mAllowedNodes.push_back(storage.mCurrentNode); storage.mCurrentNode = temp; - storage.setState(Wander_Walking); + storage.setState(AiWanderStorage::Wander_Walking); } // Choose a different node and delete this one from possible nodes because it is uncreachable: else diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index d96d93165..4a0811f50 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -21,8 +21,81 @@ namespace ESM } namespace MWMechanics -{ - struct AiWanderStorage; +{ + /// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive. + struct AiWanderStorage : AiTemporaryBase + { + // the z rotation angle to reach + // when mTurnActorGivingGreetingToFacePlayer is true + float mTargetAngleRadians; + bool mTurnActorGivingGreetingToFacePlayer; + float mReaction; // update some actions infrequently + + enum GreetingState + { + Greet_None, + Greet_InProgress, + Greet_Done + }; + GreetingState mSaidGreeting; + int mGreetingTimer; + + const MWWorld::CellStore* mCell; // for detecting cell change + + // AiWander states + enum WanderState + { + Wander_ChooseAction, + Wander_IdleNow, + Wander_MoveNow, + Wander_Walking + }; + WanderState mState; + + bool mIsWanderingManually; + bool mCanWanderAlongPathGrid; + + unsigned short mIdleAnimation; + std::vector mBadIdles; // Idle animations that when called cause errors + + // do we need to calculate allowed nodes based on mDistance + bool mPopulateAvailableNodes; + + // allowed pathgrid nodes based on mDistance from the spawn point + // in local coordinates of mCell + std::vector mAllowedNodes; + + ESM::Pathgrid::Point mCurrentNode; + bool mTrimCurrentNode; + + float mDoorCheckDuration; + int mStuckCount; + + AiWanderStorage(): + mTargetAngleRadians(0), + mTurnActorGivingGreetingToFacePlayer(false), + mReaction(0), + mSaidGreeting(Greet_None), + mGreetingTimer(0), + mCell(NULL), + mState(Wander_ChooseAction), + mIsWanderingManually(false), + mCanWanderAlongPathGrid(true), + mIdleAnimation(0), + mBadIdles(), + mPopulateAvailableNodes(true), + mAllowedNodes(), + mTrimCurrentNode(false), + mDoorCheckDuration(0), // TODO: maybe no longer needed + mStuckCount(0) + {}; + + void setState(const WanderState wanderState, const bool isManualWander = false) + { + mState = wanderState; + mIsWanderingManually = isManualWander; + } + }; /// \brief Causes the Actor to wander within a specified range class AiWander : public AiPackage @@ -52,19 +125,6 @@ namespace MWMechanics osg::Vec3f getDestination(const MWWorld::Ptr& actor) const; - enum GreetingState { - Greet_None, - Greet_InProgress, - Greet_Done - }; - - enum WanderState { - Wander_ChooseAction, - Wander_IdleNow, - Wander_MoveNow, - Wander_Walking - }; - private: // NOTE: mDistance and mDuration must be set already void init();