Refactor to reuse existing obstacle detection

pull/1/head
Austin Salgat 9 years ago
parent 34726c24d9
commit fc03216d48

@ -69,11 +69,7 @@ namespace MWMechanics
// AiWander states
AiWander::WanderState mState;
// Wandering near spawn logic
bool mIsWanderingManually;
ESM::Pathgrid::Point mPreviousWanderingNearSpawnLocation;
int mStuckTimer;
bool mCanWanderAlongPathGrid;
unsigned short mIdleAnimation;
@ -90,7 +86,6 @@ namespace MWMechanics
mCell(NULL),
mState(AiWander::Wander_ChooseAction),
mIsWanderingManually(false),
mStuckTimer(0),
mCanWanderAlongPathGrid(true),
mIdleAnimation(0),
mBadIdles()
@ -222,14 +217,14 @@ namespace MWMechanics
if (REACTION_INTERVAL <= lastReaction)
{
lastReaction = 0;
return reactionTimeActions(actor, storage, currentCell, cellChange, pos);
return reactionTimeActions(actor, storage, currentCell, cellChange, pos, duration);
}
else
return false;
}
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos)
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration)
{
if (mDistance <= 0)
storage.mCanWanderAlongPathGrid = false;
@ -263,9 +258,9 @@ namespace MWMechanics
storage.mCanWanderAlongPathGrid = false;
}
// Detect obstacles if wandering manually
if (storage.mIsWanderingManually) {
detectManualWanderingObstacles(actor, storage);
// If Wandering manually and hit an obstacle, stop
if (storage.mIsWanderingManually && mObstacleCheck.check(actor, duration*10.0f, 2.5f)) {
stopWalking(actor, storage);
}
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
@ -348,10 +343,6 @@ namespace MWMechanics
/*
* Commands actor to walk to a random location near original spawn location.
*
* Creatures simply wander a certain distance from their starting location, while NPCs wander a scripted
* distance (mDistance) from the position where they started the wander package.
* http://www.uesp.net/wiki/Tes3Mod:AIWander
*/
void AiWander::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance) {
const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos;
@ -366,32 +357,9 @@ namespace MWMechanics
storage.mPathFinder.buildSyncedPath(currentPosition, destinationPosition, actor.getCell(), true);
storage.mPathFinder.addPointToPath(destinationPosition);
storage.mPreviousWanderingNearSpawnLocation = currentPosition;
storage.mStuckTimer = 0;
storage.setState(Wander_Walking, true);
}
/*
* Detects if a manually wandering actor has spent too much time at one spot (stuck by an obstacle)
* and stops wandering when that occurs. Uses the unit's speed to help determine how long they should
* not be in one spot.
*/
void AiWander::detectManualWanderingObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage) {
const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos;
const float actorSpeed = actor.getClass().getSpeed(actor);
const float minimumDistanceTraveled = actorSpeed / 5.0f;
if (distanceApart2d(storage.mPreviousWanderingNearSpawnLocation, currentPosition) < minimumDistanceTraveled) {
// Hit an obstacle and haven't moved much
if (++(storage.mStuckTimer) > 8) {
// Stuck too long, wander elsewhere
storage.setState(Wander_ChooseAction);
wanderNearStart(actor, storage, mDistance);
}
} else {
storage.mPreviousWanderingNearSpawnLocation = currentPosition;
}
}
void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos)
{
switch (storage.mState)

@ -91,11 +91,10 @@ namespace MWMechanics
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos);
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos);
const MWWorld::CellStore*& currentCell, bool cellChange, ESM::Position& pos, float duration);
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
void returnToStartLocation(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
void detectManualWanderingObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
int mDistance; // how far the actor can wander from the spawn point
int mDuration;
@ -160,12 +159,6 @@ namespace MWMechanics
static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1];
static int OffsetToPreventOvercrowding();
float distanceApart2d(const ESM::Pathgrid::Point& first, const ESM::Pathgrid::Point& second) {
const float deltaX = second.mX - first.mX;
const float deltaY = second.mY - first.mY;
return std::sqrt(deltaX*deltaX + deltaY*deltaY);
}
};

@ -115,13 +115,13 @@ namespace MWMechanics
* u = how long to move sideways
*
*/
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration)
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance)
{
const MWWorld::Class& cls = actor.getClass();
ESM::Position pos = actor.getRefData().getPosition();
if(mDistSameSpot == -1)
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor);
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor) * scaleMinimumDistance;
float distSameSpot = mDistSameSpot * duration;

@ -36,7 +36,7 @@ namespace MWMechanics
// Returns true if there is an obstacle and an evasive action
// should be taken
bool check(const MWWorld::Ptr& actor, float duration);
bool check(const MWWorld::Ptr& actor, float duration, float scaleMinimumDistance = 1.0f);
// change direction to try to fix "stuck" actor
void takeEvasiveAction(MWMechanics::Movement& actorMovement);

Loading…
Cancel
Save