diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 1fc6c52a4..48d30f3e7 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -72,7 +72,11 @@ namespace MWMechanics { mRemainingDuration -= duration; if (duration <= 0) + { + // Reset mStarted to false so that package can be repeated again + mStarted = false; return true; + } } if (!mCellId.empty() && mCellId != actor.getCell()->getCell()->getCellId().mWorldspace) @@ -100,7 +104,11 @@ namespace MWMechanics point.mConnectionNum = 0; point.mUnknown = 0; if(pathTo(actor,point,duration)) //Returns true on path complete + { + // Reset mStarted to false so that package can be repeated again + mStarted = false; return true; + } mMaxDist = 450; } else diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 863fe05ef..b08f92276 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -45,7 +45,12 @@ bool MWMechanics::AiPackage::shouldCancelPreviousAi() const return true; } -MWMechanics::AiPackage::AiPackage() : mTimer(0.26f) { //mTimer starts at .26 to force initial pathbuild +bool MWMechanics::AiPackage::getRepeat() const +{ + return true; +} + +MWMechanics::AiPackage::AiPackage() : mTimer(0.26f), mStarted(false) { //mTimer starts at .26 to force initial pathbuild } @@ -74,7 +79,13 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po if(mTimer > 0.25) { const ESM::Cell *cell = actor.getCell()->getCell(); - if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved + // If repeating an AI package (mStarted has been set to false again), build a new path if needed so package doesn't immediately end + if (!mStarted && distance(pos.pos, dest) > 10) { + mStarted = true; + mPathFinder.buildSyncedPath(pos.pos, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + mPrevDest = dest; + } + else if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved mPathFinder.buildSyncedPath(pos.pos, dest, actor.getCell(), true); //Rebuild path, in case the target has moved mPrevDest = dest; } @@ -94,7 +105,11 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po /// Checks if you aren't moving; attempts to unstick you //************************ if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1])) //Path finished? + { + // Reset mTimer so that path will be built right away when a package is repeated + mTimer = 0.26f; return true; + } else { evadeObstacles(actor, duration, pos); diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index aa689f189..0cf285479 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -87,6 +87,10 @@ namespace MWMechanics /// Upon adding this Ai package, should the Ai Sequence attempt to cancel previous Ai packages (default true)? virtual bool shouldCancelPreviousAi() const; + /// Return true if this package should repeat. Can only be false for AIWander, if AIWander is assigned + /// assigned through the console or script. + virtual bool getRepeat() const; + bool isTargetMagicallyHidden(const MWWorld::Ptr& target); protected: @@ -104,6 +108,9 @@ namespace MWMechanics float mTimer; + // Set to true once package starts actually being executed + bool mStarted; + ESM::Pathgrid::Point mPrevDest; private: diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 13c368f74..11f390854 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -230,6 +230,11 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac if (package->execute (actor,characterController,state,duration)) { + // Put repeating noncombat AI packages on the end of the stack so they can be used again + if (isActualAiPackage(packageTypeId) && package->getRepeat()) + { + 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) std::list::iterator toRemove = diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 1585a3007..3026b4393 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -58,9 +58,13 @@ namespace MWMechanics if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), pos.asVec3())) return false; + if (!mStarted) + mStarted = true; + if (pathTo(actor, ESM::Pathgrid::Point(static_cast(mX), static_cast(mY), static_cast(mZ)), duration)) { actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + mStarted = false; return true; } return false; diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 99a278232..beb975cc4 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -123,8 +123,6 @@ namespace MWMechanics if(mDuration == 0) mTimeOfDay = 0; - mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp(); - mPopulateAvailableNodes = true; } @@ -202,6 +200,13 @@ namespace MWMechanics mPopulateAvailableNodes = true; } + if (!mStarted) + { + // Set mStartTime once this package starts being executed + mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp(); + mStarted = true; + } + cStats.setDrawState(DrawState_Nothing); cStats.setMovementFlag(CreatureStats::Flag_Run, false); @@ -230,6 +235,8 @@ namespace MWMechanics if (isPackageCompleted(actor, storage)) { + // Reset mStarted so that package will get a new mStarttime when it repeats + mStarted = false; return true; } @@ -301,6 +308,11 @@ namespace MWMechanics return false; // AiWander package not yet completed } + bool AiWander::getRepeat() const + { + return mRepeat; + } + bool AiWander::isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage) { if (mDuration) @@ -310,15 +322,8 @@ namespace MWMechanics if ((currentTime.getHour() >= mStartTime.getHour() + mDuration) || (int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay())) { - if (!mRepeat) - { stopWalking(actor, storage); return true; - } - else - { - mStartTime = currentTime; - } } } // if get here, not yet completed @@ -501,8 +506,7 @@ namespace MWMechanics } } } - // Recreate vanilla (broken?) behavior of resetting start time of AIWander: - mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp(); + storage.setState(Wander_IdleNow); } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 1155100b8..026febb02 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -58,6 +58,8 @@ namespace MWMechanics virtual void fastForward(const MWWorld::Ptr& actor, AiState& state); + bool getRepeat() const; + enum GreetingState { Greet_None, Greet_InProgress,