Slightly modify aicombat to make it more difficult to get around an enemy. The difference is visible only if turning is slow (i.e. if smooth movement enabled).

pull/593/head
Petr Mikheev 4 years ago
parent 6a75942907
commit 79a72e4b44

@ -5,6 +5,8 @@
#include <components/esm/aisequence.hpp> #include <components/esm/aisequence.hpp>
#include <components/misc/mathutil.hpp>
#include <components/sceneutil/positionattitudetransform.hpp> #include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwphysics/collisiontype.hpp" #include "../mwphysics/collisiontype.hpp"
@ -240,10 +242,6 @@ namespace MWMechanics
if (storage.mReadyToAttack) if (storage.mReadyToAttack)
{ {
storage.startCombatMove(isRangedCombat, distToTarget, rangeAttack, actor, target);
// start new attack
storage.startAttackIfReady(actor, characterController, weapon, isRangedCombat);
if (isRangedCombat) if (isRangedCombat)
{ {
// rotate actor taking into account target movement direction and projectile speed // rotate actor taking into account target movement direction and projectile speed
@ -259,6 +257,10 @@ namespace MWMechanics
storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir);
storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated
} }
storage.startCombatMove(isRangedCombat, distToTarget, rangeAttack, actor, target);
// start new attack
storage.startAttackIfReady(actor, characterController, weapon, isRangedCombat);
} }
return false; return false;
} }
@ -372,9 +374,13 @@ namespace MWMechanics
void AiCombat::updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage) void AiCombat::updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage)
{ {
// apply combat movement // apply combat movement
float deltaAngle = storage.mMovement.mRotation[2] - actor.getRefData().getPosition().rot[2];
osg::Vec2f movement = Misc::rotateVec2f(
osg::Vec2f(storage.mMovement.mPosition[0], storage.mMovement.mPosition[1]), -deltaAngle);
MWMechanics::Movement& actorMovementSettings = actor.getClass().getMovementSettings(actor); MWMechanics::Movement& actorMovementSettings = actor.getClass().getMovementSettings(actor);
actorMovementSettings.mPosition[0] = storage.mMovement.mPosition[0]; actorMovementSettings.mPosition[0] = movement.x();
actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1]; actorMovementSettings.mPosition[1] = movement.y();
actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2]; actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2];
rotateActorOnAxis(actor, 2, actorMovementSettings, storage); rotateActorOnAxis(actor, 2, actorMovementSettings, storage);
@ -385,26 +391,11 @@ namespace MWMechanics
MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage) MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage)
{ {
actorMovementSettings.mRotation[axis] = 0; actorMovementSettings.mRotation[axis] = 0;
float& targetAngleRadians = storage.mMovement.mRotation[axis]; bool isRangedCombat = false;
if (targetAngleRadians != 0) storage.mCurrentAction->getCombatRange(isRangedCombat);
{ float eps = isRangedCombat ? osg::DegreesToRadians(0.5) : osg::DegreesToRadians(3.f);
// Some attack animations contain small amount of movement. float targetAngleRadians = storage.mMovement.mRotation[axis];
// Since we use cone shapes for melee, we can use a threshold to avoid jittering smoothTurn(actor, targetAngleRadians, axis, eps);
std::shared_ptr<Action>& currentAction = storage.mCurrentAction;
bool isRangedCombat = false;
currentAction->getCombatRange(isRangedCombat);
// Check if the actor now facing desired direction, no need to turn any more
if (isRangedCombat)
{
if (smoothTurn(actor, targetAngleRadians, axis))
targetAngleRadians = 0;
}
else
{
if (smoothTurn(actor, targetAngleRadians, axis, osg::DegreesToRadians(3.f)))
targetAngleRadians = 0;
}
}
} }
MWWorld::Ptr AiCombat::getTarget() const MWWorld::Ptr AiCombat::getTarget() const
@ -489,12 +480,19 @@ namespace MWMechanics
// Note: do not use for ranged combat yet since in couple with back up behaviour can move actor out of cliff // Note: do not use for ranged combat yet since in couple with back up behaviour can move actor out of cliff
else if (actor.getClass().isBipedal(actor)) else if (actor.getClass().isBipedal(actor))
{ {
// apply sideway movement (kind of dodging) with some probability float moveDuration = 0;
// if actor is within range of target's weapon float angleToTarget = Misc::normalizeAngle(mMovement.mRotation[2] - actor.getRefData().getPosition().rot[2]);
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25) // Apply a big side step if enemy tries to get around and come from behind.
// Otherwise apply a random side step (kind of dodging) with some probability
// if actor is within range of target's weapon.
if (std::abs(angleToTarget) > osg::PI / 4)
moveDuration = 0.2;
else if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
moveDuration = 0.1f + 0.1f * Misc::Rng::rollClosedProbability();
if (moveDuration > 0)
{ {
mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right
mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability(); mTimerCombatMove = moveDuration;
mCombatMove = true; mCombatMove = true;
} }
} }

Loading…
Cancel
Save