From f597d3e88bc85208681b74d5c72579a6e81488d3 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 3 Apr 2014 07:46:26 +1100 Subject: [PATCH] Use duration rather than frame counts. Stops false detection of being "stuck" with high frame rates (e.g. indoors). --- apps/openmw/mwmechanics/aiwander.cpp | 43 +++++++++++++++++----------- apps/openmw/mwmechanics/aiwander.hpp | 3 +- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index a3286b8c0..e89d43ca4 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -18,9 +18,10 @@ namespace MWMechanics { // NOTE: determined empirically but probably need further tweaking - static const int COUNT_BEFORE_STUCK = 20; static const int COUNT_BEFORE_RESET = 200; - static const int COUNT_EVADE = 7; + static const float DIST_SAME_SPOT = 1.8f; + static const float DURATION_SAME_SPOT = 1.0f; + static const float DURATION_TO_EVADE = 0.4f; AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat): mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat) @@ -35,7 +36,8 @@ namespace MWMechanics , mPrevY(0) , mWalkState(State_Norm) , mStuckCount(0) - , mEvadeCount(0) + , mEvadeDuration(0) + , mStuckDuration(0) , mSaidGreeting(false) { for(unsigned short counter = 0; counter < mIdle.size(); counter++) @@ -325,15 +327,21 @@ namespace MWMechanics } else { - /* 1 n + /* f t * State_Norm <---> State_CheckStuck --> State_Evade * ^ ^ | ^ | ^ | | * | | | | | | | | - * | +---+ +---+ +---+ | m - * | any < n < m | + * | +---+ +---+ +---+ | u + * | any < t < u | * +--------------------------------------------+ + * + * f = one frame + * t = how long before considered stuck + * u = how long to move sideways */ - bool samePosition = (abs(pos.pos[0] - mPrevX) < 1) && (abs(pos.pos[1] - mPrevY) < 1); + bool samePosition = (abs(pos.pos[0] - mPrevX) < DIST_SAME_SPOT) && + (abs(pos.pos[1] - mPrevY) < DIST_SAME_SPOT); + switch(mWalkState) { case State_Norm: @@ -349,30 +357,33 @@ namespace MWMechanics if(!samePosition) { mWalkState = State_Norm; - // to do this properly need yet another variable, simply don't clear for now - //mStuckCount = 0; + mStuckDuration = 0; break; } else { - // consider stuck only if position unchanges consecutively - if((mStuckCount++ % COUNT_BEFORE_STUCK) == 0) + mStuckDuration += duration; + // consider stuck only if position unchanges for a period + if(mStuckDuration > DURATION_SAME_SPOT) + { mWalkState = State_Evade; - // NOTE: mStuckCount is purposely not cleared here + mStuckDuration = 0; + mStuckCount++; + } else - break; // still in the same state, but counter got incremented + break; // still in the same state, but duration added to timer } } /* FALL THROUGH */ case State_Evade: { - if(mEvadeCount++ < COUNT_EVADE) + mEvadeDuration += duration; + if(mEvadeDuration < DURATION_TO_EVADE) break; else { mWalkState = State_Norm; // tried to evade, assume all is ok and start again - // NOTE: mStuckCount is purposely not cleared here - mEvadeCount = 0; + mEvadeDuration = 0; } } /* NO DEFAULT CASE */ diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index ca6e546ed..75621911e 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -58,7 +58,8 @@ namespace MWMechanics WalkState mWalkState; int mStuckCount; - int mEvadeCount; + float mStuckDuration; + float mEvadeDuration; bool mStoredAvailableNodes; bool mChooseAction;