Require line of sight for AI attacks (Fixes #3646)

pull/120/head
Allofich 8 years ago committed by scrawl
parent e5c9a82a29
commit 19143f9bc7

@ -60,30 +60,30 @@ namespace MWMechanics
FleeState_RunToDestination
};
FleeState mFleeState;
bool mFleeLOS;
float mFleeUpdateLOSTimer;
bool mLOS;
float mUpdateLOSTimer;
float mFleeBlindRunTimer;
ESM::Pathgrid::Point mFleeDest;
AiCombatStorage():
mAttackCooldown(0),
mAttackCooldown(0.0f),
mTimerReact(AI_REACTION_TIME),
mTimerCombatMove(0),
mTimerCombatMove(0.0f),
mReadyToAttack(false),
mAttack(false),
mAttackRange(0),
mAttackRange(0.0f),
mCombatMove(false),
mLastTargetPos(0,0,0),
mCell(NULL),
mCurrentAction(),
mActionCooldown(0),
mActionCooldown(0.0f),
mStrength(),
mForceNoShortcut(false),
mShortcutFailPos(),
mMovement(),
mFleeState(FleeState_None),
mFleeLOS(false),
mFleeUpdateLOSTimer(0.0f),
mLOS(false),
mUpdateLOSTimer(0.0f),
mFleeBlindRunTimer(0.0f)
{}
@ -181,10 +181,14 @@ namespace MWMechanics
if (!storage.isFleeing())
{
if (storage.mCurrentAction.get()) // need to wait to init action with it's attack range
if (storage.mCurrentAction.get()) // need to wait to init action with its attack range
{
//Update every frame
bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, storage.mAttackRange);
//Update every frame. UpdateLOS uses a timer, so the LOS check does not happen every frame.
updateLOS(actor, target, duration, storage);
float targetReachedTolerance = 0.0f;
if (storage.mLOS)
targetReachedTolerance = storage.mAttackRange;
bool is_target_reached = pathTo(actor, target.getRefData().getPosition().pos, duration, targetReachedTolerance);
if (is_target_reached) storage.mReadyToAttack = true;
}
@ -283,7 +287,7 @@ namespace MWMechanics
osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target);
storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack);
storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS);
if (storage.mReadyToAttack)
{
@ -309,18 +313,23 @@ namespace MWMechanics
}
}
void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
void MWMechanics::AiCombat::updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
{
static const float LOS_UPDATE_DURATION = 0.5f;
static const float BLIND_RUN_DURATION = 1.0f;
if (storage.mFleeUpdateLOSTimer <= 0.f)
if (storage.mUpdateLOSTimer <= 0.f)
{
storage.mFleeLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target);
storage.mFleeUpdateLOSTimer = LOS_UPDATE_DURATION;
storage.mLOS = MWBase::Environment::get().getWorld()->getLOS(actor, target);
storage.mUpdateLOSTimer = LOS_UPDATE_DURATION;
}
else
storage.mFleeUpdateLOSTimer -= duration;
storage.mUpdateLOSTimer -= duration;
}
void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
{
static const float BLIND_RUN_DURATION = 1.0f;
updateLOS(actor, target, duration, storage);
AiCombatStorage::FleeState& state = storage.mFleeState;
switch (state)
@ -332,7 +341,7 @@ namespace MWMechanics
{
float triggerDist = getMaxAttackDistance(target);
if (storage.mFleeLOS &&
if (storage.mLOS &&
(triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist))
{
const ESM::Pathgrid* pathgrid =
@ -399,7 +408,7 @@ namespace MWMechanics
static const float fFleeDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFleeDistance")->getFloat();
float dist = (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length();
if ((dist > fFleeDistance && !storage.mFleeLOS)
if ((dist > fFleeDistance && !storage.mLOS)
|| pathTo(actor, storage.mFleeDest, duration))
{
state = AiCombatStorage::FleeState_Idle;
@ -602,9 +611,6 @@ namespace MWMechanics
mMovement.mPosition[2] = 0;
mFleeState = FleeState_None;
mFleeDest = ESM::Pathgrid::Point(0, 0, 0);
mFleeLOS = false;
mFleeUpdateLOSTimer = 0.0f;
mFleeUpdateLOSTimer = 0.0f;
}
bool AiCombatStorage::isFleeing()

@ -61,6 +61,8 @@ namespace MWMechanics
void attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController);
void updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage);
void updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage);
/// Transfer desired movement (from AiCombatStorage) to Actor

Loading…
Cancel
Save