mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 16:49:54 +00:00
Merge remote-tracking branch 'dteviot/refactoringAiWander'
This commit is contained in:
commit
f3d3cbc58b
6 changed files with 67 additions and 81 deletions
|
@ -36,13 +36,13 @@ namespace
|
||||||
|
|
||||||
float getZAngleToDir(const osg::Vec3f& dir)
|
float getZAngleToDir(const osg::Vec3f& dir)
|
||||||
{
|
{
|
||||||
return osg::RadiansToDegrees(std::atan2(dir.x(), dir.y()));
|
return std::atan2(dir.x(), dir.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
float getXAngleToDir(const osg::Vec3f& dir, float dirLen = 0.0f)
|
float getXAngleToDir(const osg::Vec3f& dir, float dirLen = 0.0f)
|
||||||
{
|
{
|
||||||
float len = (dirLen > 0.0f)? dirLen : dir.length();
|
float len = (dirLen > 0.0f)? dirLen : dir.length();
|
||||||
return osg::RadiansToDegrees(-std::asin(dir.z() / len));
|
return -std::asin(dir.z() / len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,12 +221,12 @@ namespace MWMechanics
|
||||||
|
|
||||||
if(movement.mRotation[2] != 0)
|
if(movement.mRotation[2] != 0)
|
||||||
{
|
{
|
||||||
if(zTurn(actor, osg::DegreesToRadians(movement.mRotation[2]))) movement.mRotation[2] = 0;
|
if(zTurn(actor, movement.mRotation[2])) movement.mRotation[2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(movement.mRotation[0] != 0)
|
if(movement.mRotation[0] != 0)
|
||||||
{
|
{
|
||||||
if(smoothTurn(actor, osg::DegreesToRadians(movement.mRotation[0]), 0)) movement.mRotation[0] = 0;
|
if(smoothTurn(actor, movement.mRotation[0], 0)) movement.mRotation[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool& attack = storage.mAttack;
|
bool& attack = storage.mAttack;
|
||||||
|
|
|
@ -104,7 +104,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
|
actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
||||||
// change the angle a bit, too
|
// change the angle a bit, too
|
||||||
zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
|
zTurn(actor, mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { //Not stuck, so reset things
|
else { //Not stuck, so reset things
|
||||||
|
@ -117,7 +117,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time
|
||||||
}
|
}
|
||||||
|
|
||||||
zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
zTurn(actor, mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,10 @@ namespace MWMechanics
|
||||||
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
||||||
struct AiWanderStorage : AiTemporaryBase
|
struct AiWanderStorage : AiTemporaryBase
|
||||||
{
|
{
|
||||||
// the z rotation angle (degrees) we want to reach
|
// the z rotation angle to reach
|
||||||
// used every frame when mRotate is true
|
// when mTurnActorGivingGreetingToFacePlayer is true
|
||||||
float mTargetAngleRadians;
|
float mTargetAngleRadians;
|
||||||
bool mRotate;
|
bool mTurnActorGivingGreetingToFacePlayer;
|
||||||
float mReaction; // update some actions infrequently
|
float mReaction; // update some actions infrequently
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,27 +64,21 @@ namespace MWMechanics
|
||||||
const MWWorld::CellStore* mCell; // for detecting cell change
|
const MWWorld::CellStore* mCell; // for detecting cell change
|
||||||
|
|
||||||
// AiWander states
|
// AiWander states
|
||||||
bool mChooseAction;
|
AiWander::WanderState mState;
|
||||||
bool mIdleNow;
|
|
||||||
bool mMoveNow;
|
|
||||||
bool mWalking;
|
|
||||||
|
|
||||||
unsigned short mPlayedIdle;
|
unsigned short mIdleAnimation;
|
||||||
|
|
||||||
PathFinder mPathFinder;
|
PathFinder mPathFinder;
|
||||||
|
|
||||||
AiWanderStorage():
|
AiWanderStorage():
|
||||||
mTargetAngleRadians(0),
|
mTargetAngleRadians(0),
|
||||||
mRotate(false),
|
mTurnActorGivingGreetingToFacePlayer(false),
|
||||||
mReaction(0),
|
mReaction(0),
|
||||||
mSaidGreeting(AiWander::Greet_None),
|
mSaidGreeting(AiWander::Greet_None),
|
||||||
mGreetingTimer(0),
|
mGreetingTimer(0),
|
||||||
mCell(NULL),
|
mCell(NULL),
|
||||||
mChooseAction(true),
|
mState(AiWander::Wander_ChooseAction),
|
||||||
mIdleNow(false),
|
mIdleAnimation(0)
|
||||||
mMoveNow(false),
|
|
||||||
mWalking(false),
|
|
||||||
mPlayedIdle(0)
|
|
||||||
{};
|
{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,88 +194,77 @@ namespace MWMechanics
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
|
|
||||||
|
|
||||||
bool& idleNow = storage.mIdleNow;
|
WanderState& wanderState = storage.mState;
|
||||||
bool& moveNow = storage.mMoveNow;
|
|
||||||
bool& walking = storage.mWalking;
|
|
||||||
// Check if an idle actor is too close to a door - if so start walking
|
// Check if an idle actor is too close to a door - if so start walking
|
||||||
mDoorCheckDuration += duration;
|
mDoorCheckDuration += duration;
|
||||||
if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL)
|
if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL)
|
||||||
{
|
{
|
||||||
mDoorCheckDuration = 0; // restart timer
|
mDoorCheckDuration = 0; // restart timer
|
||||||
if(mDistance && // actor is not intended to be stationary
|
if(mDistance && // actor is not intended to be stationary
|
||||||
idleNow && // but is in idle
|
(wanderState == Wander_IdleNow) && // but is in idle
|
||||||
!walking && // FIXME: some actors are idle while walking
|
|
||||||
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only
|
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6f*1.6f)) // NOTE: checks interior cells only
|
||||||
{
|
{
|
||||||
idleNow = false;
|
wanderState = Wander_MoveNow;
|
||||||
moveNow = true;
|
|
||||||
mTrimCurrentNode = false; // just in case
|
mTrimCurrentNode = false; // just in case
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we there yet?
|
// Are we there yet?
|
||||||
bool& chooseAction = storage.mChooseAction;
|
if ((wanderState == Wander_Walking) &&
|
||||||
if(walking &&
|
|
||||||
storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DESTINATION_TOLERANCE))
|
storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], DESTINATION_TOLERANCE))
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
chooseAction = true;
|
wanderState = Wander_ChooseAction;
|
||||||
mHasReturnPosition = false;
|
mHasReturnPosition = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(walking) // have not yet reached the destination
|
if (wanderState == Wander_Walking) // have not yet reached the destination
|
||||||
{
|
{
|
||||||
// turn towards the next point in mPath
|
// turn towards the next point in mPath
|
||||||
zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
zTurn(actor, storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]));
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
|
||||||
|
|
||||||
evadeObstacles(actor, storage, duration);
|
evadeObstacles(actor, storage, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool& rotate = storage.mTurnActorGivingGreetingToFacePlayer;
|
||||||
float& targetAngleRadians = storage.mTargetAngleRadians;
|
|
||||||
bool& rotate = storage.mRotate;
|
|
||||||
if (rotate)
|
if (rotate)
|
||||||
{
|
{
|
||||||
// Reduce the turning animation glitch by using a *HUGE* value of
|
// Reduce the turning animation glitch by using a *HUGE* value of
|
||||||
// epsilon... TODO: a proper fix might be in either the physics or the
|
// epsilon... TODO: a proper fix might be in either the physics or the
|
||||||
// animation subsystem
|
// animation subsystem
|
||||||
if (zTurn(actor, targetAngleRadians, osg::DegreesToRadians(5.f)))
|
if (zTurn(actor, storage.mTargetAngleRadians, osg::DegreesToRadians(5.f)))
|
||||||
rotate = false;
|
rotate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if idle animation finished
|
// Check if idle animation finished
|
||||||
short unsigned& playedIdle = storage.mPlayedIdle;
|
short unsigned& idleAnimation = storage.mIdleAnimation;
|
||||||
GreetingState& greetingState = storage.mSaidGreeting;
|
GreetingState& greetingState = storage.mSaidGreeting;
|
||||||
if(idleNow && !checkIdle(actor, playedIdle) && (greetingState == Greet_Done || greetingState == Greet_None))
|
if ((wanderState == Wander_IdleNow) &&
|
||||||
|
!checkIdle(actor, idleAnimation) && (greetingState == Greet_Done || greetingState == Greet_None))
|
||||||
{
|
{
|
||||||
playedIdle = 0;
|
wanderState = Wander_ChooseAction;
|
||||||
idleNow = false;
|
|
||||||
chooseAction = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
if(chooseAction)
|
if (wanderState == Wander_ChooseAction)
|
||||||
{
|
{
|
||||||
playedIdle = 0;
|
idleAnimation = getRandomIdle();
|
||||||
getRandomIdle(playedIdle); // NOTE: sets mPlayedIdle with a random selection
|
|
||||||
|
|
||||||
if(!playedIdle && mDistance)
|
if(!idleAnimation && mDistance)
|
||||||
{
|
{
|
||||||
chooseAction = false;
|
wanderState = Wander_MoveNow;
|
||||||
moveNow = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
|
// Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
|
||||||
MWWorld::TimeStamp currentTime = world->getTimeStamp();
|
MWWorld::TimeStamp currentTime = world->getTimeStamp();
|
||||||
mStartTime = currentTime;
|
mStartTime = currentTime;
|
||||||
playIdle(actor, playedIdle);
|
playIdle(actor, idleAnimation);
|
||||||
chooseAction = false;
|
wanderState = Wander_IdleNow;
|
||||||
idleNow = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,9 +317,6 @@ namespace MWMechanics
|
||||||
mHasReturnPosition = false;
|
mHasReturnPosition = false;
|
||||||
if (mDistance == 0 && mHasReturnPosition && (pos.asVec3() - mReturnPosition).length2() > 20*20)
|
if (mDistance == 0 && mHasReturnPosition && (pos.asVec3() - mReturnPosition).length2() > 20*20)
|
||||||
{
|
{
|
||||||
chooseAction = false;
|
|
||||||
idleNow = false;
|
|
||||||
|
|
||||||
if (!storage.mPathFinder.isPathConstructed())
|
if (!storage.mPathFinder.isPathConstructed())
|
||||||
{
|
{
|
||||||
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mReturnPosition));
|
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(mReturnPosition));
|
||||||
|
@ -349,19 +329,18 @@ namespace MWMechanics
|
||||||
|
|
||||||
if(storage.mPathFinder.isPathConstructed())
|
if(storage.mPathFinder.isPathConstructed())
|
||||||
{
|
{
|
||||||
moveNow = false;
|
wanderState = Wander_Walking;
|
||||||
walking = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow interrupting a walking actor to trigger a greeting
|
// Allow interrupting a walking actor to trigger a greeting
|
||||||
if(idleNow || walking)
|
if ((wanderState == Wander_IdleNow) || (wanderState == Wander_Walking))
|
||||||
{
|
{
|
||||||
playGreetingIfPlayerGetsTooClose(actor, storage);
|
playGreetingIfPlayerGetsTooClose(actor, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(moveNow && mDistance)
|
if ((wanderState == Wander_MoveNow) && mDistance)
|
||||||
{
|
{
|
||||||
// Construct a new path if there isn't one
|
// Construct a new path if there isn't one
|
||||||
if(!storage.mPathFinder.isPathConstructed())
|
if(!storage.mPathFinder.isPathConstructed())
|
||||||
|
@ -388,8 +367,7 @@ namespace MWMechanics
|
||||||
trimAllowedNodes(mAllowedNodes, storage.mPathFinder);
|
trimAllowedNodes(mAllowedNodes, storage.mPathFinder);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
storage.mPathFinder.clearPath();
|
storage.mPathFinder.clearPath();
|
||||||
storage.mWalking = false;
|
storage.mState = Wander_MoveNow;
|
||||||
storage.mMoveNow = true;
|
|
||||||
}
|
}
|
||||||
else // probably walking into another NPC
|
else // probably walking into another NPC
|
||||||
{
|
{
|
||||||
|
@ -399,7 +377,7 @@ namespace MWMechanics
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
|
||||||
// change the angle a bit, too
|
// change the angle a bit, too
|
||||||
const ESM::Position& pos = actor.getRefData().getPosition();
|
const ESM::Position& pos = actor.getRefData().getPosition();
|
||||||
zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
|
zTurn(actor, storage.mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]));
|
||||||
}
|
}
|
||||||
mStuckCount++; // TODO: maybe no longer needed
|
mStuckCount++; // TODO: maybe no longer needed
|
||||||
}
|
}
|
||||||
|
@ -411,7 +389,7 @@ namespace MWMechanics
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
|
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
storage.mChooseAction = true;
|
storage.mState = Wander_ChooseAction;
|
||||||
mStuckCount = 0;
|
mStuckCount = 0;
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
@ -483,22 +461,14 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
greetingTimer++;
|
greetingTimer++;
|
||||||
|
|
||||||
if (storage.mWalking)
|
if (storage.mState == Wander_Walking)
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
storage.mIdleNow = true;
|
storage.mState = Wander_IdleNow;
|
||||||
getRandomIdle(storage.mPlayedIdle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!storage.mRotate)
|
turnActorToFacePlayer(actorPos, playerPos, storage);
|
||||||
{
|
|
||||||
osg::Vec3f dir = playerPos - actorPos;
|
|
||||||
|
|
||||||
float faceAngleRadians = std::atan2(dir.x(), dir.y());
|
|
||||||
storage.mTargetAngleRadians = faceAngleRadians;
|
|
||||||
storage.mRotate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (greetingTimer >= GREETING_SHOULD_END)
|
if (greetingTimer >= GREETING_SHOULD_END)
|
||||||
{
|
{
|
||||||
|
@ -515,6 +485,15 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AiWander::turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage)
|
||||||
|
{
|
||||||
|
osg::Vec3f dir = playerPosition - actorPosition;
|
||||||
|
|
||||||
|
float faceAngleRadians = std::atan2(dir.x(), dir.y());
|
||||||
|
storage.mTargetAngleRadians = faceAngleRadians;
|
||||||
|
storage.mTurnActorGivingGreetingToFacePlayer = true;
|
||||||
|
}
|
||||||
|
|
||||||
void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
|
void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
|
||||||
{
|
{
|
||||||
unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size());
|
unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size());
|
||||||
|
@ -539,8 +518,7 @@ namespace MWMechanics
|
||||||
mAllowedNodes.push_back(mCurrentNode);
|
mAllowedNodes.push_back(mCurrentNode);
|
||||||
mCurrentNode = temp;
|
mCurrentNode = temp;
|
||||||
|
|
||||||
storage.mMoveNow = false;
|
storage.mState = Wander_Walking;
|
||||||
storage.mWalking = true;
|
|
||||||
}
|
}
|
||||||
// Choose a different node and delete this one from possible nodes because it is uncreachable:
|
// Choose a different node and delete this one from possible nodes because it is uncreachable:
|
||||||
else
|
else
|
||||||
|
@ -591,8 +569,6 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
storage.mPathFinder.clearPath();
|
storage.mPathFinder.clearPath();
|
||||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||||
storage.mMoveNow = false;
|
|
||||||
storage.mWalking = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||||
|
@ -626,9 +602,10 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::getRandomIdle(short unsigned& playedIdle)
|
short unsigned AiWander::getRandomIdle()
|
||||||
{
|
{
|
||||||
unsigned short idleRoll = 0;
|
unsigned short idleRoll = 0;
|
||||||
|
short unsigned selectedAnimation = 0;
|
||||||
|
|
||||||
for(unsigned int counter = 0; counter < mIdle.size(); counter++)
|
for(unsigned int counter = 0; counter < mIdle.size(); counter++)
|
||||||
{
|
{
|
||||||
|
@ -639,10 +616,11 @@ namespace MWMechanics
|
||||||
unsigned short randSelect = (int)(Misc::Rng::rollProbability() * int(100 / fIdleChanceMultiplier));
|
unsigned short randSelect = (int)(Misc::Rng::rollProbability() * int(100 / fIdleChanceMultiplier));
|
||||||
if(randSelect < idleChance && randSelect > idleRoll)
|
if(randSelect < idleChance && randSelect > idleRoll)
|
||||||
{
|
{
|
||||||
playedIdle = counter+2;
|
selectedAnimation = counter + GroupIndex_MinIdle;
|
||||||
idleRoll = randSelect;
|
idleRoll = randSelect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return selectedAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::fastForward(const MWWorld::Ptr& actor, AiState &state)
|
void AiWander::fastForward(const MWWorld::Ptr& actor, AiState &state)
|
||||||
|
|
|
@ -63,6 +63,13 @@ namespace MWMechanics
|
||||||
Greet_InProgress,
|
Greet_InProgress,
|
||||||
Greet_Done
|
Greet_Done
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum WanderState {
|
||||||
|
Wander_ChooseAction,
|
||||||
|
Wander_IdleNow,
|
||||||
|
Wander_MoveNow,
|
||||||
|
Wander_Walking
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
// NOTE: mDistance and mDuration must be set already
|
// NOTE: mDistance and mDuration must be set already
|
||||||
void init();
|
void init();
|
||||||
|
@ -70,11 +77,12 @@ namespace MWMechanics
|
||||||
void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
void stopWalking(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
|
void playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
|
||||||
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
|
bool checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect);
|
||||||
void getRandomIdle(unsigned short& playedIdle);
|
short unsigned getRandomIdle();
|
||||||
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
||||||
void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
void playGreetingIfPlayerGetsTooClose(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration);
|
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration);
|
||||||
void playIdleDialogueRandomly(const MWWorld::Ptr& actor);
|
void playIdleDialogueRandomly(const MWWorld::Ptr& actor);
|
||||||
|
void turnActorToFacePlayer(const osg::Vec3f& actorPosition, const osg::Vec3f& playerPosition, AiWanderStorage& storage);
|
||||||
|
|
||||||
int mDistance; // how far the actor can wander from the spawn point
|
int mDistance; // how far the actor can wander from the spawn point
|
||||||
int mDuration;
|
int mDuration;
|
||||||
|
|
|
@ -264,7 +264,7 @@ namespace MWMechanics
|
||||||
float directionX = nextPoint.mX - x;
|
float directionX = nextPoint.mX - x;
|
||||||
float directionY = nextPoint.mY - y;
|
float directionY = nextPoint.mY - y;
|
||||||
|
|
||||||
return osg::RadiansToDegrees(std::atan2(directionX, directionY));
|
return std::atan2(directionX, directionY);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathFinder::checkPathCompleted(float x, float y, float tolerance)
|
bool PathFinder::checkPathCompleted(float x, float y, float tolerance)
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace MWMechanics
|
||||||
bool checkPathCompleted(float x, float y, float tolerance = PathTolerance);
|
bool checkPathCompleted(float x, float y, float tolerance = PathTolerance);
|
||||||
///< \Returns true if we are within \a tolerance units of the last path point.
|
///< \Returns true if we are within \a tolerance units of the last path point.
|
||||||
|
|
||||||
/// In degrees
|
/// In radians
|
||||||
float getZAngleToNext(float x, float y) const;
|
float getZAngleToNext(float x, float y) const;
|
||||||
|
|
||||||
bool isPathConstructed() const
|
bool isPathConstructed() const
|
||||||
|
|
Loading…
Reference in a new issue