mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 13:19:40 +00:00
Bug #900 fix - only fixed AiWonder, AiCombat, AiTravel and others may need a different strategy to this.
This commit is contained in:
parent
0cd40294a2
commit
d92740efc9
2 changed files with 108 additions and 2 deletions
|
@ -27,6 +27,11 @@ namespace
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
// NOTE: determined empherically 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;
|
||||||
|
|
||||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat):
|
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat):
|
||||||
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
||||||
, mCellX(std::numeric_limits<int>::max())
|
, mCellX(std::numeric_limits<int>::max())
|
||||||
|
@ -36,6 +41,11 @@ namespace MWMechanics
|
||||||
, mX(0)
|
, mX(0)
|
||||||
, mY(0)
|
, mY(0)
|
||||||
, mZ(0)
|
, mZ(0)
|
||||||
|
, mPrevX(0)
|
||||||
|
, mPrevY(0)
|
||||||
|
, mWalkState(State_Norm)
|
||||||
|
, mStuckCount(0)
|
||||||
|
, mEvadeCount(0)
|
||||||
, mSaidGreeting(false)
|
, mSaidGreeting(false)
|
||||||
{
|
{
|
||||||
for(unsigned short counter = 0; counter < mIdle.size(); counter++)
|
for(unsigned short counter = 0; counter < mIdle.size(); counter++)
|
||||||
|
@ -298,9 +308,91 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
/* 1 n
|
||||||
|
* State_Norm <---> State_CheckStuck --> State_Evade
|
||||||
|
* ^ ^ | ^ | ^ | |
|
||||||
|
* | | | | | | | |
|
||||||
|
* | +---+ +---+ +---+ | m
|
||||||
|
* | any < n < m |
|
||||||
|
* +--------------------------------------------+
|
||||||
|
*/
|
||||||
|
bool samePosition = (abs(pos.pos[0] - mPrevX) < 1) && (abs(pos.pos[1] - mPrevY) < 1);
|
||||||
|
switch(mWalkState)
|
||||||
|
{
|
||||||
|
case State_Norm:
|
||||||
|
{
|
||||||
|
if(!samePosition)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
mWalkState = State_CheckStuck;
|
||||||
|
}
|
||||||
|
/* FALL THROUGH */
|
||||||
|
case State_CheckStuck:
|
||||||
|
{
|
||||||
|
if(!samePosition)
|
||||||
|
{
|
||||||
|
mWalkState = State_Norm;
|
||||||
|
// to do this properly need yet another variable, simply don't clear for now
|
||||||
|
//mStuckCount = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// consider stuck only if position unchanges consequitively
|
||||||
|
if((mStuckCount++ % COUNT_BEFORE_STUCK) == 0)
|
||||||
|
mWalkState = State_Evade;
|
||||||
|
// NOTE: mStuckCount is purposely not cleared here
|
||||||
|
else
|
||||||
|
break; // still in the same state, but counter got incremented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FALL THROUGH */
|
||||||
|
case State_Evade:
|
||||||
|
{
|
||||||
|
if(mEvadeCount++ < COUNT_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NO DEFAULT CASE */
|
||||||
|
}
|
||||||
|
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
if(mWalkState == State_Evade)
|
||||||
|
{
|
||||||
|
//std::cout << "Stuck \""<<actor.getClass().getName(actor)<<"\"" << std::endl;
|
||||||
|
|
||||||
|
// diagonal should have same animation as walk forward
|
||||||
|
actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
|
||||||
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.01f;
|
||||||
|
// change the angle a bit, too
|
||||||
|
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
||||||
|
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mStuckCount >= COUNT_BEFORE_RESET) // something has gone wrong, reset
|
||||||
|
{
|
||||||
|
//std::cout << "Reset \""<<actor.getClass().getName(actor)<<"\"" << std::endl;
|
||||||
|
mWalkState = State_Norm;
|
||||||
|
mStuckCount = 0;
|
||||||
|
|
||||||
|
stopWalking(actor);
|
||||||
|
mMoveNow = false;
|
||||||
|
mWalking = false;
|
||||||
|
mChooseAction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update position
|
||||||
|
ESM::Position updatedPos = actor.getRefData().getPosition();
|
||||||
|
mPrevX = pos.pos[0];
|
||||||
|
mPrevY = pos.pos[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,20 @@ namespace MWMechanics
|
||||||
float mXCell;
|
float mXCell;
|
||||||
float mYCell;
|
float mYCell;
|
||||||
|
|
||||||
|
// for checking if we're stuck (but don't check Z axis)
|
||||||
|
enum WalkState
|
||||||
|
{
|
||||||
|
State_Norm,
|
||||||
|
State_CheckStuck,
|
||||||
|
State_Evade
|
||||||
|
};
|
||||||
|
WalkState mWalkState;
|
||||||
|
|
||||||
|
float mPrevX;
|
||||||
|
float mPrevY;
|
||||||
|
int mStuckCount;
|
||||||
|
int mEvadeCount;
|
||||||
|
|
||||||
bool mStoredAvailableNodes;
|
bool mStoredAvailableNodes;
|
||||||
bool mChooseAction;
|
bool mChooseAction;
|
||||||
bool mIdleNow;
|
bool mIdleNow;
|
||||||
|
|
Loading…
Reference in a new issue