1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 21:49:55 +00:00

Fix movement glitches for actors with low speeds (e.g. a rat). Was caused by false detection of being stuck.

This commit is contained in:
cc9cii 2014-04-13 07:35:26 +10:00
parent 65161c3e24
commit 1ceeeb4a22
2 changed files with 22 additions and 11 deletions

View file

@ -35,6 +35,7 @@ namespace MWMechanics
, mPrevX(0) , mPrevX(0)
, mPrevY(0) , mPrevY(0)
, mWalkState(State_Norm) , mWalkState(State_Norm)
, mDistSameSpot(0)
, mStuckCount(0) , mStuckCount(0)
, mEvadeDuration(0) , mEvadeDuration(0)
, mStuckDuration(0) , mStuckDuration(0)
@ -71,7 +72,6 @@ namespace MWMechanics
return new AiWander(*this); return new AiWander(*this);
} }
// TODO: duration is passed in but never used, check if it is needed
bool AiWander::execute (const MWWorld::Ptr& actor,float duration) bool AiWander::execute (const MWWorld::Ptr& actor,float duration)
{ {
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
@ -113,7 +113,9 @@ namespace MWMechanics
mCellX = actor.getCell()->getCell()->mData.mX; mCellX = actor.getCell()->getCell()->mData.mX;
mCellY = actor.getCell()->getCell()->mData.mY; mCellY = actor.getCell()->getCell()->mData.mY;
// TODO: If there is no path does this actor get stuck forever? // If there is no path this actor doesn't go anywhere. See:
// https://forum.openmw.org/viewtopic.php?t=1556
// http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833
if(!mPathgrid) if(!mPathgrid)
mDistance = 0; mDistance = 0;
else if(mPathgrid->mPoints.empty()) else if(mPathgrid->mPoints.empty())
@ -166,7 +168,7 @@ namespace MWMechanics
} }
} }
// TODO: Does this actor stay in one spot forever while in AiWander? // Actor becomes stationary - see above URL's for previous research
if(mAllowedNodes.empty()) if(mAllowedNodes.empty())
mDistance = 0; mDistance = 0;
@ -277,8 +279,10 @@ namespace MWMechanics
{ {
assert(mAllowedNodes.size()); assert(mAllowedNodes.size());
unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size()); unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size());
// NOTE: destNodePos initially constructed with local (i.e. cell) co-ordinates
Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ); Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ);
// convert dest to use world co-ordinates
ESM::Pathgrid::Point dest; ESM::Pathgrid::Point dest;
dest.mX = destNodePos[0] + mXCell; dest.mX = destNodePos[0] + mXCell;
dest.mY = destNodePos[1] + mYCell; dest.mY = destNodePos[1] + mYCell;
@ -338,9 +342,15 @@ namespace MWMechanics
* f = one frame * f = one frame
* t = how long before considered stuck * t = how long before considered stuck
* u = how long to move sideways * u = how long to move sideways
*
* DIST_SAME_SPOT is calibrated for movement speed of around 150.
* A rat has walking speed of around 30, so we need to adjust for
* that.
*/ */
bool samePosition = (abs(pos.pos[0] - mPrevX) < DIST_SAME_SPOT) && if(!mDistSameSpot)
(abs(pos.pos[1] - mPrevY) < DIST_SAME_SPOT); mDistSameSpot = DIST_SAME_SPOT * (actor.getClass().getSpeed(actor) / 150);
bool samePosition = (abs(pos.pos[0] - mPrevX) < mDistSameSpot) &&
(abs(pos.pos[1] - mPrevY) < mDistSameSpot);
switch(mWalkState) switch(mWalkState)
{ {
@ -364,14 +374,14 @@ namespace MWMechanics
{ {
mStuckDuration += duration; mStuckDuration += duration;
// consider stuck only if position unchanges for a period // consider stuck only if position unchanges for a period
if(mStuckDuration > DURATION_SAME_SPOT) if(mStuckDuration < DURATION_SAME_SPOT)
break; // still checking, note duration added to timer
else
{ {
mWalkState = State_Evade;
mStuckDuration = 0; mStuckDuration = 0;
mStuckCount++; mStuckCount++;
mWalkState = State_Evade;
} }
else
break; // still in the same state, but duration added to timer
} }
} }
/* FALL THROUGH */ /* FALL THROUGH */
@ -395,7 +405,7 @@ namespace MWMechanics
// diagonal should have same animation as walk forward // diagonal should have same animation as walk forward
actor.getClass().getMovementSettings(actor).mPosition[0] = 1; actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.01f; actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
// change the angle a bit, too // change the angle a bit, too
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
} }

View file

@ -58,8 +58,9 @@ namespace MWMechanics
WalkState mWalkState; WalkState mWalkState;
int mStuckCount; int mStuckCount;
float mStuckDuration; float mStuckDuration; // accumulate time here while in same spot
float mEvadeDuration; float mEvadeDuration;
float mDistSameSpot; // take account of actor's speed
bool mStoredAvailableNodes; bool mStoredAvailableNodes;
bool mChooseAction; bool mChooseAction;