mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:53:51 +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 states
|
||||||
AiWander::WanderState mState;
|
AiWander::WanderState mState;
|
||||||
|
|
||||||
// Wandering near spawn logic
|
|
||||||
bool mIsWanderingManually;
|
bool mIsWanderingManually;
|
||||||
ESM::Pathgrid::Point mPreviousWanderingNearSpawnLocation;
|
|
||||||
int mStuckTimer;
|
|
||||||
|
|
||||||
bool mCanWanderAlongPathGrid;
|
bool mCanWanderAlongPathGrid;
|
||||||
|
|
||||||
unsigned short mIdleAnimation;
|
unsigned short mIdleAnimation;
|
||||||
|
@ -90,7 +86,6 @@ namespace MWMechanics
|
||||||
mCell(NULL),
|
mCell(NULL),
|
||||||
mState(AiWander::Wander_ChooseAction),
|
mState(AiWander::Wander_ChooseAction),
|
||||||
mIsWanderingManually(false),
|
mIsWanderingManually(false),
|
||||||
mStuckTimer(0),
|
|
||||||
mCanWanderAlongPathGrid(true),
|
mCanWanderAlongPathGrid(true),
|
||||||
mIdleAnimation(0),
|
mIdleAnimation(0),
|
||||||
mBadIdles()
|
mBadIdles()
|
||||||
|
@ -222,14 +217,14 @@ namespace MWMechanics
|
||||||
if (REACTION_INTERVAL <= lastReaction)
|
if (REACTION_INTERVAL <= lastReaction)
|
||||||
{
|
{
|
||||||
lastReaction = 0;
|
lastReaction = 0;
|
||||||
return reactionTimeActions(actor, storage, currentCell, cellChange, pos);
|
return reactionTimeActions(actor, storage, currentCell, cellChange, pos, duration);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage,
|
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)
|
if (mDistance <= 0)
|
||||||
storage.mCanWanderAlongPathGrid = false;
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
|
@ -263,9 +258,9 @@ namespace MWMechanics
|
||||||
storage.mCanWanderAlongPathGrid = false;
|
storage.mCanWanderAlongPathGrid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect obstacles if wandering manually
|
// If Wandering manually and hit an obstacle, stop
|
||||||
if (storage.mIsWanderingManually) {
|
if (storage.mIsWanderingManually && mObstacleCheck.check(actor, duration*10.0f, 2.5f)) {
|
||||||
detectManualWanderingObstacles(actor, storage);
|
stopWalking(actor, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
|
// 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.
|
* 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) {
|
void AiWander::wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance) {
|
||||||
const ESM::Pathgrid::Point currentPosition = actor.getRefData().getPosition().pos;
|
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.buildSyncedPath(currentPosition, destinationPosition, actor.getCell(), true);
|
||||||
storage.mPathFinder.addPointToPath(destinationPosition);
|
storage.mPathFinder.addPointToPath(destinationPosition);
|
||||||
storage.mPreviousWanderingNearSpawnLocation = currentPosition;
|
|
||||||
storage.mStuckTimer = 0;
|
|
||||||
storage.setState(Wander_Walking, true);
|
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)
|
void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos)
|
||||||
{
|
{
|
||||||
switch (storage.mState)
|
switch (storage.mState)
|
||||||
|
|
|
@ -91,11 +91,10 @@ namespace MWMechanics
|
||||||
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos);
|
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage, ESM::Position& pos);
|
||||||
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
bool reactionTimeActions(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);
|
bool isPackageCompleted(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||||
void returnToStartLocation(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
void returnToStartLocation(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
||||||
void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance);
|
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 mDistance; // how far the actor can wander from the spawn point
|
||||||
int mDuration;
|
int mDuration;
|
||||||
|
@ -160,12 +159,6 @@ namespace MWMechanics
|
||||||
static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1];
|
static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1];
|
||||||
|
|
||||||
static int OffsetToPreventOvercrowding();
|
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
|
* 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();
|
const MWWorld::Class& cls = actor.getClass();
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
|
|
||||||
if(mDistSameSpot == -1)
|
if(mDistSameSpot == -1)
|
||||||
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor);
|
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor) * scaleMinimumDistance;
|
||||||
|
|
||||||
float distSameSpot = mDistSameSpot * duration;
|
float distSameSpot = mDistSameSpot * duration;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
// Returns true if there is an obstacle and an evasive action
|
// Returns true if there is an obstacle and an evasive action
|
||||||
// should be taken
|
// 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
|
// change direction to try to fix "stuck" actor
|
||||||
void takeEvasiveAction(MWMechanics::Movement& actorMovement);
|
void takeEvasiveAction(MWMechanics::Movement& actorMovement);
|
||||||
|
|
Loading…
Reference in a new issue