|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
#include "obstacle.hpp"
|
|
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <span>
|
|
|
|
|
|
|
|
|
|
#include <components/detournavigator/agentbounds.hpp>
|
|
|
|
|
#include <components/esm3/loaddoor.hpp>
|
|
|
|
@ -15,17 +16,30 @@
|
|
|
|
|
|
|
|
|
|
namespace MWMechanics
|
|
|
|
|
{
|
|
|
|
|
// NOTE: determined empirically but probably need further tweaking
|
|
|
|
|
static const float DIST_SAME_SPOT = 0.5f;
|
|
|
|
|
static const float DURATION_SAME_SPOT = 1.5f;
|
|
|
|
|
static const float DURATION_TO_EVADE = 0.4f;
|
|
|
|
|
|
|
|
|
|
const float ObstacleCheck::evadeDirections[NUM_EVADE_DIRECTIONS][2] = {
|
|
|
|
|
{ 1.0f, 0.0f }, // move to side
|
|
|
|
|
{ 1.0f, -1.0f }, // move to side and backwards
|
|
|
|
|
{ -1.0f, 0.0f }, // move to other side
|
|
|
|
|
{ -1.0f, -1.0f } // move to side and backwards
|
|
|
|
|
};
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
// NOTE: determined empirically but probably need further tweaking
|
|
|
|
|
constexpr float distanceSameSpot = 0.5f;
|
|
|
|
|
constexpr float durationSameSpot = 1.5f;
|
|
|
|
|
constexpr float durationToEvade = 1;
|
|
|
|
|
|
|
|
|
|
struct EvadeDirection
|
|
|
|
|
{
|
|
|
|
|
float mMovementX;
|
|
|
|
|
float mMovementY;
|
|
|
|
|
MWWorld::MovementDirectionFlag mRequiredAnimation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr EvadeDirection evadeDirections[] = {
|
|
|
|
|
{ 1.0f, 1.0f, MWWorld::MovementDirectionFlag_Forward }, // move to right and forward
|
|
|
|
|
{ 1.0f, 0.0f, MWWorld::MovementDirectionFlag_Right }, // move to right
|
|
|
|
|
{ 1.0f, -1.0f, MWWorld::MovementDirectionFlag_Back }, // move to right and backwards
|
|
|
|
|
{ 0.0f, -1.0f, MWWorld::MovementDirectionFlag_Back }, // move backwards
|
|
|
|
|
{ -1.0f, -1.0f, MWWorld::MovementDirectionFlag_Back }, // move to left and backwards
|
|
|
|
|
{ -1.0f, 0.0f, MWWorld::MovementDirectionFlag_Left }, // move to left
|
|
|
|
|
{ -1.0f, 1.0f, MWWorld::MovementDirectionFlag_Forward }, // move to left and forward
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool proximityToDoor(const MWWorld::Ptr& actor, float minDist)
|
|
|
|
|
{
|
|
|
|
@ -94,9 +108,7 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ObstacleCheck::ObstacleCheck()
|
|
|
|
|
: mWalkState(WalkState::Initial)
|
|
|
|
|
, mStateDuration(0)
|
|
|
|
|
, mEvadeDirectionIndex(0)
|
|
|
|
|
: mEvadeDirectionIndex(std::size(evadeDirections) - 1)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -128,7 +140,8 @@ namespace MWMechanics
|
|
|
|
|
* u = how long to move sideways
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void ObstacleCheck::update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration)
|
|
|
|
|
void ObstacleCheck::update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration,
|
|
|
|
|
MWWorld::MovementDirectionFlags supportedMovementDirection)
|
|
|
|
|
{
|
|
|
|
|
const auto position = actor.getRefData().getPosition().asVec3();
|
|
|
|
|
|
|
|
|
@ -150,7 +163,7 @@ namespace MWMechanics
|
|
|
|
|
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 currentDistance = (destination - position).length();
|
|
|
|
|
const float movedDistance = prevDistance - currentDistance;
|
|
|
|
@ -174,19 +187,27 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mStateDuration += duration;
|
|
|
|
|
if (mStateDuration < DURATION_SAME_SPOT)
|
|
|
|
|
if (mStateDuration < durationSameSpot)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mWalkState = WalkState::Evade;
|
|
|
|
|
mStateDuration = 0;
|
|
|
|
|
chooseEvasionDirection();
|
|
|
|
|
std::size_t newEvadeDirectionIndex = mEvadeDirectionIndex;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
++newEvadeDirectionIndex;
|
|
|
|
|
if (newEvadeDirectionIndex == std::size(evadeDirections))
|
|
|
|
|
newEvadeDirectionIndex = 0;
|
|
|
|
|
if ((evadeDirections[newEvadeDirectionIndex].mRequiredAnimation & supportedMovementDirection) != 0)
|
|
|
|
|
break;
|
|
|
|
|
} while (mEvadeDirectionIndex != newEvadeDirectionIndex);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mStateDuration += duration;
|
|
|
|
|
if (mStateDuration >= DURATION_TO_EVADE)
|
|
|
|
|
if (mStateDuration >= durationToEvade)
|
|
|
|
|
{
|
|
|
|
|
// tried to evade, assume all is ok and start again
|
|
|
|
|
mWalkState = WalkState::Norm;
|
|
|
|
@ -197,18 +218,7 @@ namespace MWMechanics
|
|
|
|
|
|
|
|
|
|
void ObstacleCheck::takeEvasiveAction(MWMechanics::Movement& actorMovement) const
|
|
|
|
|
{
|
|
|
|
|
actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex][0];
|
|
|
|
|
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1];
|
|
|
|
|
actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex].mMovementX;
|
|
|
|
|
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex].mMovementY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ObstacleCheck::chooseEvasionDirection()
|
|
|
|
|
{
|
|
|
|
|
// change direction if attempt didn't work
|
|
|
|
|
++mEvadeDirectionIndex;
|
|
|
|
|
if (mEvadeDirectionIndex == NUM_EVADE_DIRECTIONS)
|
|
|
|
|
{
|
|
|
|
|
mEvadeDirectionIndex = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|