mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
Moved all variables in temporary storage for AiCombat and some more for AiWander.
+Buxfix for previous AiWander changes
This commit is contained in:
parent
cae948df96
commit
730abf6841
4 changed files with 159 additions and 155 deletions
|
@ -81,6 +81,48 @@ namespace MWMechanics
|
||||||
static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander
|
static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander
|
||||||
// NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp
|
// NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp
|
||||||
|
|
||||||
|
|
||||||
|
/// \brief This class holds the variables AiCombat needs which are deleted if the package becomes inactive.
|
||||||
|
struct AiCombatStorage : AiTemporaryBase
|
||||||
|
{
|
||||||
|
float mTimerAttack;
|
||||||
|
float mTimerReact;
|
||||||
|
float mTimerCombatMove;
|
||||||
|
bool mReadyToAttack;
|
||||||
|
bool mAttack;
|
||||||
|
bool mFollowTarget;
|
||||||
|
bool mCombatMove;
|
||||||
|
Ogre::Vector3 mLastTargetPos;
|
||||||
|
const MWWorld::CellStore* mCell;
|
||||||
|
boost::shared_ptr<Action> mCurrentAction;
|
||||||
|
float mActionCooldown;
|
||||||
|
float mStrength;
|
||||||
|
float mMinMaxAttackDuration[3][2];
|
||||||
|
bool mMinMaxAttackDurationInitialised;
|
||||||
|
bool mForceNoShortcut;
|
||||||
|
ESM::Position mShortcutFailPos;
|
||||||
|
Ogre::Vector3 mLastActorPos;
|
||||||
|
MWMechanics::Movement mMovement;
|
||||||
|
|
||||||
|
AiCombatStorage():
|
||||||
|
mTimerAttack(0),
|
||||||
|
mTimerReact(0),
|
||||||
|
mTimerCombatMove(0),
|
||||||
|
mAttack(false),
|
||||||
|
mFollowTarget(false),
|
||||||
|
mCombatMove(false),
|
||||||
|
mReadyToAttack(false),
|
||||||
|
mForceNoShortcut(false),
|
||||||
|
mCell(NULL),
|
||||||
|
mCurrentAction(),
|
||||||
|
mActionCooldown(0),
|
||||||
|
mStrength(),
|
||||||
|
mMinMaxAttackDurationInitialised(false),
|
||||||
|
mLastTargetPos(0,0,0),
|
||||||
|
mLastActorPos(0,0,0),
|
||||||
|
mMovement(){}
|
||||||
|
};
|
||||||
|
|
||||||
AiCombat::AiCombat(const MWWorld::Ptr& actor) :
|
AiCombat::AiCombat(const MWWorld::Ptr& actor) :
|
||||||
mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId())
|
mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId())
|
||||||
{}
|
{}
|
||||||
|
@ -157,8 +199,8 @@ namespace MWMechanics
|
||||||
Ogre::Vector3& lastTargetPos = storage.mLastTargetPos;
|
Ogre::Vector3& lastTargetPos = storage.mLastTargetPos;
|
||||||
const MWWorld::CellStore*& currentCell = storage.mCell;
|
const MWWorld::CellStore*& currentCell = storage.mCell;
|
||||||
boost::shared_ptr<Action>& currentAction = storage.mCurrentAction;
|
boost::shared_ptr<Action>& currentAction = storage.mCurrentAction;
|
||||||
float actionCooldown = storage.mActionCooldown;
|
float& actionCooldown = storage.mActionCooldown;
|
||||||
float strength = storage.mStrength;
|
float& strength = storage.mStrength;
|
||||||
float (&minMaxAttackDuration)[3][2] = storage.mMinMaxAttackDuration;
|
float (&minMaxAttackDuration)[3][2] = storage.mMinMaxAttackDuration;
|
||||||
bool& minMaxAttackDurationInitialised = storage.mMinMaxAttackDurationInitialised;
|
bool& minMaxAttackDurationInitialised = storage.mMinMaxAttackDurationInitialised;
|
||||||
bool& forceNoShortcut = storage.mForceNoShortcut;
|
bool& forceNoShortcut = storage.mForceNoShortcut;
|
||||||
|
|
|
@ -61,56 +61,7 @@ namespace MWMechanics
|
||||||
void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
void buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AiCombatStorage : AiTemporaryBase
|
|
||||||
{
|
|
||||||
// controls duration of the actual strike
|
|
||||||
float mTimerAttack;
|
|
||||||
float mTimerReact;
|
|
||||||
// controls duration of the sideway & forward moves
|
|
||||||
// when mCombatMove is true
|
|
||||||
float mTimerCombatMove;
|
|
||||||
|
|
||||||
// AiCombat states
|
|
||||||
bool mReadyToAttack, mAttack;
|
|
||||||
bool mFollowTarget;
|
|
||||||
bool mCombatMove;
|
|
||||||
|
|
||||||
Ogre::Vector3 mLastTargetPos;
|
|
||||||
|
|
||||||
const MWWorld::CellStore* mCell;
|
|
||||||
|
|
||||||
boost::shared_ptr<Action> mCurrentAction;
|
|
||||||
float mActionCooldown;
|
|
||||||
|
|
||||||
float mStrength; // this is actually make sense only in ranged combat
|
|
||||||
float mMinMaxAttackDuration[3][2]; // slash, thrust, chop has different durations
|
|
||||||
bool mMinMaxAttackDurationInitialised;
|
|
||||||
|
|
||||||
bool mForceNoShortcut;
|
|
||||||
ESM::Position mShortcutFailPos;
|
|
||||||
|
|
||||||
Ogre::Vector3 mLastActorPos;
|
|
||||||
MWMechanics::Movement mMovement;
|
|
||||||
|
|
||||||
AiCombatStorage()
|
|
||||||
{
|
|
||||||
mActionCooldown = 0;
|
|
||||||
mTimerAttack = 0;
|
|
||||||
mTimerReact = 0;
|
|
||||||
mTimerCombatMove = 0;
|
|
||||||
mFollowTarget = false;
|
|
||||||
mReadyToAttack = false;
|
|
||||||
mAttack = false;
|
|
||||||
mCombatMove = false;
|
|
||||||
mForceNoShortcut = false;
|
|
||||||
mStrength = 0;
|
|
||||||
mCell = NULL;
|
|
||||||
mLastTargetPos = Ogre::Vector3(0,0,0);
|
|
||||||
mLastActorPos = Ogre::Vector3(0,0,0);
|
|
||||||
mMinMaxAttackDurationInitialised = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,6 +28,55 @@ namespace MWMechanics
|
||||||
static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player
|
static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player
|
||||||
static const int GREETING_SHOULD_END = 10;
|
static const int GREETING_SHOULD_END = 10;
|
||||||
|
|
||||||
|
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
||||||
|
struct AiWanderStorage : AiTemporaryBase
|
||||||
|
{
|
||||||
|
// the z rotation angle (degrees) we want to reach
|
||||||
|
// used every frame when mRotate is true
|
||||||
|
float mTargetAngle;
|
||||||
|
bool mRotate;
|
||||||
|
float mReaction; // update some actions infrequently
|
||||||
|
|
||||||
|
|
||||||
|
AiWander::GreetingState mSaidGreeting;
|
||||||
|
int mGreetingTimer;
|
||||||
|
|
||||||
|
// Cached current cell location
|
||||||
|
int mCellX;
|
||||||
|
int mCellY;
|
||||||
|
// Cell location multiplied by ESM::Land::REAL_SIZE
|
||||||
|
float mXCell;
|
||||||
|
float mYCell;
|
||||||
|
|
||||||
|
const MWWorld::CellStore* mCell; // for detecting cell change
|
||||||
|
|
||||||
|
// AiWander states
|
||||||
|
bool mChooseAction;
|
||||||
|
bool mIdleNow;
|
||||||
|
bool mMoveNow;
|
||||||
|
bool mWalking;
|
||||||
|
|
||||||
|
unsigned short mPlayedIdle;
|
||||||
|
|
||||||
|
AiWanderStorage():
|
||||||
|
mTargetAngle(0),
|
||||||
|
mRotate(false),
|
||||||
|
mReaction(0),
|
||||||
|
mSaidGreeting(AiWander::Greet_None),
|
||||||
|
mGreetingTimer(0),
|
||||||
|
mCellX(std::numeric_limits<int>::max()),
|
||||||
|
mCellY(std::numeric_limits<int>::max()),
|
||||||
|
mXCell(0),
|
||||||
|
mYCell(0),
|
||||||
|
mCell(NULL),
|
||||||
|
mChooseAction(true),
|
||||||
|
mIdleNow(false),
|
||||||
|
mMoveNow(false),
|
||||||
|
mWalking(false),
|
||||||
|
mPlayedIdle(0)
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
||||||
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
|
||||||
{
|
{
|
||||||
|
@ -55,13 +104,9 @@ namespace MWMechanics
|
||||||
mTimeOfDay = 0;
|
mTimeOfDay = 0;
|
||||||
|
|
||||||
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
mStartTime = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
mPlayedIdle = 0;
|
|
||||||
|
|
||||||
mStoredAvailableNodes = false;
|
mStoredAvailableNodes = false;
|
||||||
mChooseAction = true;
|
|
||||||
mIdleNow = false;
|
|
||||||
mMoveNow = false;
|
|
||||||
mWalking = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AiPackage * MWMechanics::AiWander::clone() const
|
AiPackage * MWMechanics::AiWander::clone() const
|
||||||
|
@ -131,9 +176,14 @@ namespace MWMechanics
|
||||||
int& greetingTimer = storage.mGreetingTimer;
|
int& greetingTimer = storage.mGreetingTimer;
|
||||||
int& cachedCellX = storage.mCellX;
|
int& cachedCellX = storage.mCellX;
|
||||||
int& cachedCellY = storage.mCellY;
|
int& cachedCellY = storage.mCellY;
|
||||||
float& cachedCellXf = storage.mXCell;
|
float& cachedCellXposition = storage.mXCell;
|
||||||
float& cachedCellYf = storage.mYCell;
|
float& cachedCellYposition = storage.mYCell;
|
||||||
const MWWorld::CellStore*& currentCell = storage.mCell;
|
const MWWorld::CellStore*& currentCell = storage.mCell;
|
||||||
|
bool& chooseAction = storage.mChooseAction;
|
||||||
|
bool& idleNow = storage.mIdleNow;
|
||||||
|
bool& moveNow = storage.mMoveNow;
|
||||||
|
bool& walking = storage.mWalking;
|
||||||
|
short unsigned& playedIdle = storage.mPlayedIdle;
|
||||||
|
|
||||||
|
|
||||||
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
||||||
|
@ -159,28 +209,28 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
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
|
||||||
mIdleNow && // but is in idle
|
idleNow && // but is in idle
|
||||||
!mWalking && // FIXME: some actors are idle while walking
|
!walking && // FIXME: some actors are idle while walking
|
||||||
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6*1.6)) // NOTE: checks interior cells only
|
proximityToDoor(actor, MIN_DIST_TO_DOOR_SQUARED*1.6*1.6)) // NOTE: checks interior cells only
|
||||||
{
|
{
|
||||||
mIdleNow = false;
|
idleNow = false;
|
||||||
mMoveNow = true;
|
moveNow = true;
|
||||||
mTrimCurrentNode = false; // just in case
|
mTrimCurrentNode = false; // just in case
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we there yet?
|
// Are we there yet?
|
||||||
if(mWalking &&
|
if(walking &&
|
||||||
mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
|
mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
|
||||||
{
|
{
|
||||||
stopWalking(actor);
|
stopWalking(actor);
|
||||||
mMoveNow = false;
|
moveNow = false;
|
||||||
mWalking = false;
|
walking = false;
|
||||||
mChooseAction = true;
|
chooseAction = true;
|
||||||
mHasReturnPosition = false;
|
mHasReturnPosition = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mWalking) // have not yet reached the destination
|
if(walking) // have not yet reached the destination
|
||||||
{
|
{
|
||||||
// turn towards the next point in mPath
|
// turn towards the next point in mPath
|
||||||
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
||||||
|
@ -197,8 +247,8 @@ namespace MWMechanics
|
||||||
trimAllowedNodes(mAllowedNodes, mPathFinder);
|
trimAllowedNodes(mAllowedNodes, mPathFinder);
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
mPathFinder.clearPath();
|
mPathFinder.clearPath();
|
||||||
mWalking = false;
|
walking = false;
|
||||||
mMoveNow = true;
|
moveNow = true;
|
||||||
}
|
}
|
||||||
else // probably walking into another NPC
|
else // probably walking into another NPC
|
||||||
{
|
{
|
||||||
|
@ -219,9 +269,9 @@ namespace MWMechanics
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
|
|
||||||
stopWalking(actor);
|
stopWalking(actor);
|
||||||
mMoveNow = false;
|
moveNow = false;
|
||||||
mWalking = false;
|
walking = false;
|
||||||
mChooseAction = true;
|
chooseAction = true;
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
@ -295,12 +345,12 @@ namespace MWMechanics
|
||||||
// destinations within the allowed set of pathgrid points (nodes).
|
// destinations within the allowed set of pathgrid points (nodes).
|
||||||
if(mDistance)
|
if(mDistance)
|
||||||
{
|
{
|
||||||
cachedCellXf = 0;
|
cachedCellXposition = 0;
|
||||||
cachedCellYf = 0;
|
cachedCellYposition = 0;
|
||||||
if(cell->isExterior())
|
if(cell->isExterior())
|
||||||
{
|
{
|
||||||
cachedCellXf = cachedCellX * ESM::Land::REAL_SIZE;
|
cachedCellXposition = cachedCellX * ESM::Land::REAL_SIZE;
|
||||||
cachedCellYf = cachedCellYf * ESM::Land::REAL_SIZE;
|
cachedCellYposition = cachedCellY * ESM::Land::REAL_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: There might be a bug here. The allowed node points are
|
// FIXME: There might be a bug here. The allowed node points are
|
||||||
|
@ -310,8 +360,8 @@ namespace MWMechanics
|
||||||
//
|
//
|
||||||
// convert npcPos to local (i.e. cell) co-ordinates
|
// convert npcPos to local (i.e. cell) co-ordinates
|
||||||
Ogre::Vector3 npcPos(pos.pos);
|
Ogre::Vector3 npcPos(pos.pos);
|
||||||
npcPos[0] = npcPos[0] - cachedCellXf;
|
npcPos[0] = npcPos[0] - cachedCellXposition;
|
||||||
npcPos[1] = npcPos[1] - cachedCellYf;
|
npcPos[1] = npcPos[1] - cachedCellYposition;
|
||||||
|
|
||||||
// mAllowedNodes for this actor with pathgrid point indexes based on mDistance
|
// mAllowedNodes for this actor with pathgrid point indexes based on mDistance
|
||||||
// NOTE: mPoints and mAllowedNodes are in local co-ordinates
|
// NOTE: mPoints and mAllowedNodes are in local co-ordinates
|
||||||
|
@ -356,8 +406,8 @@ namespace MWMechanics
|
||||||
mHasReturnPosition = false;
|
mHasReturnPosition = false;
|
||||||
if (mDistance == 0 && mHasReturnPosition && Ogre::Vector3(pos.pos).squaredDistance(mReturnPosition) > 20*20)
|
if (mDistance == 0 && mHasReturnPosition && Ogre::Vector3(pos.pos).squaredDistance(mReturnPosition) > 20*20)
|
||||||
{
|
{
|
||||||
mChooseAction = false;
|
chooseAction = false;
|
||||||
mIdleNow = false;
|
idleNow = false;
|
||||||
|
|
||||||
if (!mPathFinder.isPathConstructed())
|
if (!mPathFinder.isPathConstructed())
|
||||||
{
|
{
|
||||||
|
@ -379,30 +429,30 @@ namespace MWMechanics
|
||||||
|
|
||||||
if(mPathFinder.isPathConstructed())
|
if(mPathFinder.isPathConstructed())
|
||||||
{
|
{
|
||||||
mMoveNow = false;
|
moveNow = false;
|
||||||
mWalking = true;
|
walking = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mChooseAction)
|
if(chooseAction)
|
||||||
{
|
{
|
||||||
mPlayedIdle = 0;
|
playedIdle = 0;
|
||||||
getRandomIdle(); // NOTE: sets mPlayedIdle with a random selection
|
getRandomIdle(playedIdle); // NOTE: sets mPlayedIdle with a random selection
|
||||||
|
|
||||||
if(!mPlayedIdle && mDistance)
|
if(!playedIdle && mDistance)
|
||||||
{
|
{
|
||||||
mChooseAction = false;
|
chooseAction = false;
|
||||||
mMoveNow = true;
|
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, mPlayedIdle);
|
playIdle(actor, playedIdle);
|
||||||
mChooseAction = false;
|
chooseAction = false;
|
||||||
mIdleNow = true;
|
idleNow = true;
|
||||||
|
|
||||||
// Play idle voiced dialogue entries randomly
|
// Play idle voiced dialogue entries randomly
|
||||||
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
||||||
|
@ -426,7 +476,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow interrupting a walking actor to trigger a greeting
|
// Allow interrupting a walking actor to trigger a greeting
|
||||||
if(mIdleNow || mWalking)
|
if(idleNow || walking)
|
||||||
{
|
{
|
||||||
// Play a random voice greeting if the player gets too close
|
// Play a random voice greeting if the player gets too close
|
||||||
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
int hello = cStats.getAiSetting(CreatureStats::AI_Hello).getModified();
|
||||||
|
@ -460,23 +510,21 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
greetingTimer++;
|
greetingTimer++;
|
||||||
|
|
||||||
if(mWalking)
|
if(walking)
|
||||||
{
|
{
|
||||||
stopWalking(actor);
|
stopWalking(actor);
|
||||||
mMoveNow = false;
|
moveNow = false;
|
||||||
mWalking = false;
|
walking = false;
|
||||||
mObstacleCheck.clear();
|
mObstacleCheck.clear();
|
||||||
mIdleNow = true;
|
idleNow = true;
|
||||||
getRandomIdle();
|
getRandomIdle(playedIdle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!rotate)
|
if(!rotate)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 dir = playerPos - actorPos;
|
Ogre::Vector3 dir = playerPos - actorPos;
|
||||||
float length = dir.length();
|
|
||||||
|
|
||||||
float faceAngle = Ogre::Radian(Ogre::Math::ACos(dir.y / length) *
|
float faceAngle = Ogre::Math::ATan2(dir.x,dir.y).valueDegrees();
|
||||||
((Ogre::Math::ASin(dir.x / length).valueRadians()>0)?1.0:-1.0)).valueDegrees();
|
|
||||||
float actorAngle = actor.getRefData().getBaseNode()->getOrientation().getRoll().valueDegrees();
|
float actorAngle = actor.getRefData().getBaseNode()->getOrientation().getRoll().valueDegrees();
|
||||||
// an attempt at reducing the turning animation glitch
|
// an attempt at reducing the turning animation glitch
|
||||||
if(abs(abs(faceAngle) - abs(actorAngle)) >= 5) // TODO: is there a better way?
|
if(abs(abs(faceAngle) - abs(actorAngle)) >= 5) // TODO: is there a better way?
|
||||||
|
@ -503,15 +551,15 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if idle animation finished
|
// Check if idle animation finished
|
||||||
if(!checkIdle(actor, mPlayedIdle) && (playerDistSqr > helloDistance*helloDistance || greetingState == MWMechanics::AiWander::Greet_Done))
|
if(!checkIdle(actor, playedIdle) && (playerDistSqr > helloDistance*helloDistance || greetingState == MWMechanics::AiWander::Greet_Done))
|
||||||
{
|
{
|
||||||
mPlayedIdle = 0;
|
playedIdle = 0;
|
||||||
mIdleNow = false;
|
idleNow = false;
|
||||||
mChooseAction = true;
|
chooseAction = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mMoveNow && mDistance)
|
if(moveNow && mDistance)
|
||||||
{
|
{
|
||||||
// Construct a new path if there isn't one
|
// Construct a new path if there isn't one
|
||||||
if(!mPathFinder.isPathConstructed())
|
if(!mPathFinder.isPathConstructed())
|
||||||
|
@ -525,8 +573,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
// convert dest to use world co-ordinates
|
// convert dest to use world co-ordinates
|
||||||
ESM::Pathgrid::Point dest;
|
ESM::Pathgrid::Point dest;
|
||||||
dest.mX = destNodePos[0] + cachedCellXf;
|
dest.mX = destNodePos[0] + cachedCellXposition;
|
||||||
dest.mY = destNodePos[1] + cachedCellYf;
|
dest.mY = destNodePos[1] + cachedCellYposition;
|
||||||
dest.mZ = destNodePos[2];
|
dest.mZ = destNodePos[2];
|
||||||
|
|
||||||
// actor position is already in world co-ordinates
|
// actor position is already in world co-ordinates
|
||||||
|
@ -557,8 +605,8 @@ namespace MWMechanics
|
||||||
mAllowedNodes.push_back(mCurrentNode);
|
mAllowedNodes.push_back(mCurrentNode);
|
||||||
mCurrentNode = temp;
|
mCurrentNode = temp;
|
||||||
|
|
||||||
mMoveNow = false;
|
moveNow = false;
|
||||||
mWalking = true;
|
walking = 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
|
||||||
|
@ -657,7 +705,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::getRandomIdle()
|
void AiWander::getRandomIdle(short unsigned& playedIdle)
|
||||||
{
|
{
|
||||||
unsigned short idleRoll = 0;
|
unsigned short idleRoll = 0;
|
||||||
|
|
||||||
|
@ -670,7 +718,7 @@ namespace MWMechanics
|
||||||
unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / fIdleChanceMultiplier));
|
unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / fIdleChanceMultiplier));
|
||||||
if(randSelect < idleChance && randSelect > idleRoll)
|
if(randSelect < idleChance && randSelect > idleRoll)
|
||||||
{
|
{
|
||||||
mPlayedIdle = counter+2;
|
playedIdle = counter+2;
|
||||||
idleRoll = randSelect;
|
idleRoll = randSelect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace MWMechanics
|
||||||
void stopWalking(const MWWorld::Ptr& actor);
|
void stopWalking(const MWWorld::Ptr& actor);
|
||||||
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();
|
void getRandomIdle(unsigned short& playedIdle);
|
||||||
|
|
||||||
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;
|
||||||
|
@ -88,13 +88,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
// if false triggers calculating allowed nodes based on mDistance
|
// if false triggers calculating allowed nodes based on mDistance
|
||||||
bool mStoredAvailableNodes;
|
bool mStoredAvailableNodes;
|
||||||
// AiWander states
|
|
||||||
bool mChooseAction;
|
|
||||||
bool mIdleNow;
|
|
||||||
bool mMoveNow;
|
|
||||||
bool mWalking;
|
|
||||||
|
|
||||||
unsigned short mPlayedIdle;
|
|
||||||
|
|
||||||
|
|
||||||
MWWorld::TimeStamp mStartTime;
|
MWWorld::TimeStamp mStartTime;
|
||||||
|
|
||||||
|
@ -105,49 +101,16 @@ namespace MWMechanics
|
||||||
void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
||||||
const PathFinder& pathfinder);
|
const PathFinder& pathfinder);
|
||||||
|
|
||||||
PathFinder mPathFinder;
|
// PathFinder mPathFinder;
|
||||||
|
|
||||||
ObstacleCheck mObstacleCheck;
|
// ObstacleCheck mObstacleCheck;
|
||||||
float mDoorCheckDuration;
|
float mDoorCheckDuration;
|
||||||
int mStuckCount;
|
int mStuckCount;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Temporary values used by AiWander
|
|
||||||
struct AiWanderStorage : AiTemporaryBase
|
|
||||||
{
|
|
||||||
// the z rotation angle (degrees) we want to reach
|
|
||||||
// used every frame when mRotate is true
|
|
||||||
float mTargetAngle;
|
|
||||||
bool mRotate;
|
|
||||||
float mReaction; // update some actions infrequently
|
|
||||||
|
|
||||||
|
|
||||||
AiWander::GreetingState mSaidGreeting;
|
|
||||||
int mGreetingTimer;
|
|
||||||
|
|
||||||
// Cached current cell location
|
|
||||||
int mCellX;
|
|
||||||
int mCellY;
|
|
||||||
// Cell location multiplied by ESM::Land::REAL_SIZE
|
|
||||||
float mXCell;
|
|
||||||
float mYCell;
|
|
||||||
|
|
||||||
const MWWorld::CellStore* mCell; // for detecting cell change
|
|
||||||
|
|
||||||
AiWanderStorage():mTargetAngle(0),mRotate(false),mReaction(0)
|
|
||||||
{
|
|
||||||
mSaidGreeting = AiWander::Greet_None;
|
|
||||||
mGreetingTimer = 0;
|
|
||||||
|
|
||||||
mCellX = std::numeric_limits<int>::max();
|
|
||||||
mCellY = std::numeric_limits<int>::max();
|
|
||||||
mXCell = 0;
|
|
||||||
mYCell = 0;
|
|
||||||
mCell = NULL;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue