1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-25 12:41:01 +00:00

move start attack logic to AiCombatStorage.

Basically, copied from mrchenko's 1d4be08f6e4c2dbd89cc0c3408a8231ee4497277
This commit is contained in:
dteviot 2015-08-09 14:08:42 +12:00
parent 1676bf917e
commit 0735e3e06e

View File

@ -114,6 +114,8 @@ namespace MWMechanics
void startCombatMove(bool isNpc, bool isDistantCombat, float distToTarget, float rangeAttack); void startCombatMove(bool isNpc, bool isDistantCombat, float distToTarget, float rangeAttack);
void updateCombatMove(float duration); void updateCombatMove(float duration);
void stopCombatMove(); void stopCombatMove();
void startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController,
const ESM::Weapon* weapon, bool distantCombat);
}; };
AiCombat::AiCombat(const MWWorld::Ptr& actor) : AiCombat::AiCombat(const MWWorld::Ptr& actor) :
@ -194,7 +196,6 @@ namespace MWMechanics
|| target.getClass().getCreatureStats(target).isDead()) || target.getClass().getCreatureStats(target).isDead())
return true; return true;
//Update every frame //Update every frame
storage.updateCombatMove(duration); storage.updateCombatMove(duration);
MWMechanics::Movement& movement = storage.mMovement; MWMechanics::Movement& movement = storage.mMovement;
@ -318,41 +319,9 @@ namespace MWMechanics
} }
float& strength = storage.mStrength;
bool& readyToAttack = storage.mReadyToAttack; bool& readyToAttack = storage.mReadyToAttack;
// start new attack // start new attack
if(readyToAttack && characterController.readyToStartAttack()) storage.startAttackIfReady(actor, characterController, weapon, distantCombat);
{
if (storage.mAttackCooldown <= 0)
{
storage.mAttack = true; // attack starts just now
characterController.setAttackingOrSpell(true);
if (!distantCombat)
chooseBestAttack(weapon, movement);
strength = Misc::Rng::rollClosedProbability();
const MWWorld::ESMStore &store = world->getStore();
//say a provoking combat phrase
if (actor.getClass().isNpc())
{
int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->getInt();
if (Misc::Rng::roll0to99() < chance)
{
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
}
}
float baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayCreature")->getFloat();
if (actor.getClass().isNpc())
baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayNPC")->getFloat();
storage.mAttackCooldown = std::min(baseDelay + 0.01 * Misc::Rng::roll0to99(), baseDelay + 0.9);
}
else
storage.mAttackCooldown -= REACTION_INTERVAL;
}
/* /*
* Some notes on meanings of variables: * Some notes on meanings of variables:
@ -403,9 +372,6 @@ namespace MWMechanics
bool canMoveByZ = (actorClass.canSwim(actor) && world->isSwimming(actor)) bool canMoveByZ = (actorClass.canSwim(actor) && world->isSwimming(actor))
|| world->isFlying(actor); || world->isFlying(actor);
// for distant combat we should know if target is in LOS even if distToTarget < rangeAttack
bool inLOS = distantCombat ? world->getLOS(actor, target) : true;
// can't fight if attacker can't go where target is. E.g. A fish can't attack person on land. // can't fight if attacker can't go where target is. E.g. A fish can't attack person on land.
if (distToTarget >= rangeAttack if (distToTarget >= rangeAttack
&& !actorClass.isNpc() && !MWMechanics::isEnvironmentCompatible(actor, target)) && !actorClass.isNpc() && !MWMechanics::isEnvironmentCompatible(actor, target))
@ -419,6 +385,9 @@ namespace MWMechanics
return false; return false;
} }
// for distant combat we should know if target is in LOS even if distToTarget < rangeAttack
bool inLOS = distantCombat ? world->getLOS(actor, target) : true;
// (within attack dist) || (not quite attack dist while following) // (within attack dist) || (not quite attack dist while following)
if(inLOS && (distToTarget < rangeAttack || (distToTarget <= rangeFollow && followTarget && !isStuck))) if(inLOS && (distToTarget < rangeAttack || (distToTarget <= rangeFollow && followTarget && !isStuck)))
{ {
@ -432,7 +401,8 @@ namespace MWMechanics
if (distantCombat) if (distantCombat)
{ {
osg::Vec3f& lastTargetPos = storage.mLastTargetPos; osg::Vec3f& lastTargetPos = storage.mLastTargetPos;
osg::Vec3f vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype, strength); osg::Vec3f vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype,
storage.mStrength);
lastTargetPos = vTargetPos; lastTargetPos = vTargetPos;
movement.mRotation[0] = getXAngleToDir(vAimDir); movement.mRotation[0] = getXAngleToDir(vAimDir);
movement.mRotation[2] = getZAngleToDir(vAimDir); movement.mRotation[2] = getZAngleToDir(vAimDir);
@ -680,6 +650,42 @@ namespace MWMechanics
mMovement.mPosition[1] = mMovement.mPosition[0] = 0; mMovement.mPosition[1] = mMovement.mPosition[0] = 0;
mCombatMove = false; mCombatMove = false;
} }
void AiCombatStorage::startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController,
const ESM::Weapon* weapon, bool distantCombat)
{
if (mReadyToAttack && characterController.readyToStartAttack())
{
if (mAttackCooldown <= 0)
{
mAttack = true; // attack starts just now
characterController.setAttackingOrSpell(true);
if (!distantCombat)
chooseBestAttack(weapon, mMovement);
mStrength = Misc::Rng::rollClosedProbability();
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
float baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayCreature")->getFloat();
if (actor.getClass().isNpc())
{
baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayNPC")->getFloat();
//say a provoking combat phrase
int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->getInt();
if (Misc::Rng::roll0to99() < chance)
{
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
}
}
mAttackCooldown = std::min(baseDelay + 0.01 * Misc::Rng::roll0to99(), baseDelay + 0.9);
}
else
mAttackCooldown -= REACTION_INTERVAL;
}
}
} }