mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 06:15:32 +00:00
Refactor to reuse existing obstacle detection
This commit is contained in:
parent
34726c24d9
commit
fc03216d48
4 changed files with 9 additions and 48 deletions
|
@ -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…
Reference in a new issue