1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-16 05:43:08 +00:00

Add more evade directions and order them to make a circle

This commit is contained in:
elsid 2023-07-01 18:28:09 +02:00
parent 19940987a3
commit 579e533621
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
3 changed files with 30 additions and 43 deletions

View file

@ -63,6 +63,7 @@
Bug #7413: Generated wilderness cells don't spawn fish Bug #7413: Generated wilderness cells don't spawn fish
Bug #7415: Unbreakable lock discrepancies Bug #7415: Unbreakable lock discrepancies
Bug #7428: AutoCalc flag is not used to calculate enchantment costs Bug #7428: AutoCalc flag is not used to calculate enchantment costs
Bug #7450: Evading obstacles does not work for actors missing certain animations
Bug #7459: Icons get stacked on the cursor when picking up multiple items simultaneously Bug #7459: Icons get stacked on the cursor when picking up multiple items simultaneously
Feature #3537: Shader-based water ripples Feature #3537: Shader-based water ripples
Feature #5492: Let rain and snow collide with statics Feature #5492: Let rain and snow collide with statics

View file

@ -15,17 +15,23 @@
namespace MWMechanics namespace MWMechanics
{ {
// NOTE: determined empirically but probably need further tweaking namespace
static const float DIST_SAME_SPOT = 0.5f; {
static const float DURATION_SAME_SPOT = 1.5f; // NOTE: determined empirically but probably need further tweaking
static const float DURATION_TO_EVADE = 0.4f; constexpr float distanceSameSpot = 0.5f;
constexpr float durationSameSpot = 1.5f;
constexpr float durationToEvade = 1;
const float ObstacleCheck::evadeDirections[NUM_EVADE_DIRECTIONS][2] = { constexpr float evadeDirections[][2] = {
{ 1.0f, 0.0f }, // move to side { 1.0f, 1.0f }, // move to side and forward
{ 1.0f, -1.0f }, // move to side and backwards { 1.0f, 0.0f }, // move to side
{ -1.0f, 0.0f }, // move to other side { 1.0f, -1.0f }, // move to side and backwards
{ -1.0f, -1.0f } // move to side and backwards { 0.0f, -1.0f }, // move backwards
}; { -1.0f, -1.0f }, // move to other side and backwards
{ -1.0f, 0.0f }, // move to other side
{ -1.0f, 1.0f }, // move to other side and forward
};
}
bool proximityToDoor(const MWWorld::Ptr& actor, float minDist) bool proximityToDoor(const MWWorld::Ptr& actor, float minDist)
{ {
@ -94,9 +100,7 @@ namespace MWMechanics
} }
ObstacleCheck::ObstacleCheck() ObstacleCheck::ObstacleCheck()
: mWalkState(WalkState::Initial) : mEvadeDirectionIndex(std::size(evadeDirections) - 1)
, mStateDuration(0)
, mEvadeDirectionIndex(0)
{ {
} }
@ -150,7 +154,7 @@ namespace MWMechanics
mDestination = destination; mDestination = destination;
} }
const float distSameSpot = DIST_SAME_SPOT * actor.getClass().getCurrentSpeed(actor) * duration; const float distSameSpot = distanceSameSpot * actor.getClass().getCurrentSpeed(actor) * duration;
const float prevDistance = (destination - mPrev).length(); const float prevDistance = (destination - mPrev).length();
const float currentDistance = (destination - position).length(); const float currentDistance = (destination - position).length();
const float movedDistance = prevDistance - currentDistance; const float movedDistance = prevDistance - currentDistance;
@ -174,19 +178,20 @@ namespace MWMechanics
} }
mStateDuration += duration; mStateDuration += duration;
if (mStateDuration < DURATION_SAME_SPOT) if (mStateDuration < durationSameSpot)
{ {
return; return;
} }
mWalkState = WalkState::Evade; mWalkState = WalkState::Evade;
mStateDuration = 0; mStateDuration = 0;
chooseEvasionDirection(); if (++mEvadeDirectionIndex == std::size(evadeDirections))
mEvadeDirectionIndex = 0;
return; return;
} }
mStateDuration += duration; mStateDuration += duration;
if (mStateDuration >= DURATION_TO_EVADE) if (mStateDuration >= durationToEvade)
{ {
// tried to evade, assume all is ok and start again // tried to evade, assume all is ok and start again
mWalkState = WalkState::Norm; mWalkState = WalkState::Norm;
@ -200,15 +205,4 @@ namespace MWMechanics
actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex][0]; actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex][0];
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1]; actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1];
} }
void ObstacleCheck::chooseEvasionDirection()
{
// change direction if attempt didn't work
++mEvadeDirectionIndex;
if (mEvadeDirectionIndex == NUM_EVADE_DIRECTIONS)
{
mEvadeDirectionIndex = 0;
}
}
} }

View file

@ -15,8 +15,6 @@ namespace MWMechanics
{ {
struct Movement; struct Movement;
static constexpr int NUM_EVADE_DIRECTIONS = 4;
/// tests actor's proximity to a closed door by default /// tests actor's proximity to a closed door by default
bool proximityToDoor(const MWWorld::Ptr& actor, float minDist); bool proximityToDoor(const MWWorld::Ptr& actor, float minDist);
@ -41,29 +39,23 @@ namespace MWMechanics
void update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration); void update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration);
// change direction to try to fix "stuck" actor // change direction to try to fix "stuck" actor
void takeEvasiveAction(MWMechanics::Movement& actorMovement) const; void takeEvasiveAction(Movement& actorMovement) const;
private: private:
osg::Vec3f mPrev;
osg::Vec3f mDestination;
// directions to try moving in when get stuck
static const float evadeDirections[NUM_EVADE_DIRECTIONS][2];
enum class WalkState enum class WalkState
{ {
Initial, Initial,
Norm, Norm,
CheckStuck, CheckStuck,
Evade Evade,
}; };
WalkState mWalkState;
float mStateDuration; WalkState mWalkState = WalkState::Initial;
int mEvadeDirectionIndex; float mStateDuration = 0;
float mInitialDistance = 0; float mInitialDistance = 0;
std::size_t mEvadeDirectionIndex;
void chooseEvasionDirection(); osg::Vec3f mPrev;
osg::Vec3f mDestination;
}; };
} }