1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

refactor BattleFlowProcessor

This commit is contained in:
Opuszek
2025-07-10 13:27:29 +02:00
parent ac06f3d557
commit 8e6af8ed78
2 changed files with 80 additions and 47 deletions

View File

@@ -342,6 +342,21 @@ void BattleFlowProcessor::activateNextStack(const CBattleInfoCallback & battle)
bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & battle, const CStack * next) bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & battle, const CStack * next)
{ {
bool actionPerformed = tryActivateMoralePenalty(battle, next) || tryActivateBerserkPenalty(battle, next) || tryAutomaticActionOfWarMachines(battle, next);
if (!actionPerformed) {
stackTurnTrigger(battle, next); //various effects
if(next->fear)
{
makeStackDoNothing(battle, next); //end immediately if stack was affected by fear
return true;
}
}
return actionPerformed;
}
bool BattleFlowProcessor::tryActivateMoralePenalty(const CBattleInfoCallback & battle, const CStack * next) {
// check for bad morale => freeze // check for bad morale => freeze
int nextStackMorale = next->moraleVal(); int nextStackMorale = next->moraleVal();
if(!next->hadMorale && !next->waited() && nextStackMorale < 0) if(!next->hadMorale && !next->waited() && nextStackMorale < 0)
@@ -359,36 +374,46 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
return true; return true;
} }
} }
return false;
}
bool BattleFlowProcessor::tryActivateBerserkPenalty(const CBattleInfoCallback & battle, const CStack * next) {
if (next->hasBonusOfType(BonusType::ATTACKS_NEAREST_CREATURE)) //while in berserk if (next->hasBonusOfType(BonusType::ATTACKS_NEAREST_CREATURE)) //while in berserk
{
logGlobal->trace("Handle Berserk effect");
std::pair<const battle::Unit *, BattleHex> attackInfo = battle.getNearestStack(next);
if (attackInfo.first != nullptr)
{ {
BattleAction attack; logGlobal->trace("Handle Berserk effect");
attack.actionType = EActionType::WALK_AND_ATTACK; std::pair<const battle::Unit *, BattleHex> attackInfo = battle.getNearestStack(next);
attack.side = next->unitSide(); if (attackInfo.first != nullptr)
attack.stackNumber = next->unitId(); {
attack.aimToHex(attackInfo.second); BattleAction attack;
attack.aimToUnit(attackInfo.first); attack.actionType = EActionType::WALK_AND_ATTACK;
attack.side = next->unitSide();
attack.stackNumber = next->unitId();
attack.aimToHex(attackInfo.second);
attack.aimToUnit(attackInfo.first);
makeAutomaticAction(battle, next, attack); makeAutomaticAction(battle, next, attack);
logGlobal->trace("Attacked nearest target %s", attackInfo.first->getDescription()); logGlobal->trace("Attacked nearest target %s", attackInfo.first->getDescription());
}
else
{
makeStackDoNothing(battle, next);
logGlobal->trace("No target found");
}
return true;
} }
else return false;
{ }
makeStackDoNothing(battle, next);
logGlobal->trace("No target found");
}
return true;
}
bool BattleFlowProcessor::tryAutomaticActionOfWarMachines(const CBattleInfoCallback & battle, const CStack * next) {
return tryMakeAutomaticActionOfBallistaOrTowers(battle, next) || tryMakeAutomaticActionOfCatapult(battle, next) || tryMakeAutomaticActionOfFirstAidTent(battle, next);
}
bool BattleFlowProcessor::tryMakeAutomaticActionOfBallistaOrTowers(const CBattleInfoCallback & battle, const CStack * next) {
const CGHeroInstance * curOwner = battle.battleGetOwnerHero(next); const CGHeroInstance * curOwner = battle.battleGetOwnerHero(next);
const CreatureID stackCreatureId = next->unitType()->getId(); const CreatureID stackCreatureId = next->unitType()->getId();
if ((stackCreatureId == CreatureID::ARROW_TOWERS || stackCreatureId == CreatureID::BALLISTA) if ((stackCreatureId == CreatureID::ARROW_TOWERS || stackCreatureId == CreatureID::BALLISTA)
&& (!curOwner || !gameHandler->randomizer->rollCombatAbility(curOwner->id, curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(stackCreatureId))))) && (!curOwner || !gameHandler->randomizer->rollCombatAbility(curOwner->id, curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(stackCreatureId)))))
{ {
BattleAction attack; BattleAction attack;
attack.actionType = EActionType::SHOOT; attack.actionType = EActionType::SHOOT;
@@ -449,29 +474,37 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
} }
return true; return true;
} }
return false;
}
bool BattleFlowProcessor::tryMakeAutomaticActionOfCatapult(const CBattleInfoCallback & battle, const CStack * next) {
const CGHeroInstance * curOwner = battle.battleGetOwnerHero(next);
if (next->unitType()->getId() == CreatureID::CATAPULT) if (next->unitType()->getId() == CreatureID::CATAPULT)
{
const auto & attackableBattleHexes = battle.getAttackableBattleHexes();
if (attackableBattleHexes.empty())
{ {
makeStackDoNothing(battle, next); const auto & attackableBattleHexes = battle.getAttackableBattleHexes();
return true;
if (attackableBattleHexes.empty())
{
makeStackDoNothing(battle, next);
return true;
}
if (!curOwner || !gameHandler->randomizer->rollCombatAbility(curOwner->id, curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(CreatureID(CreatureID::CATAPULT)))))
{
BattleAction attack;
attack.actionType = EActionType::CATAPULT;
attack.side = next->unitSide();
attack.stackNumber = next->unitId();
makeAutomaticAction(battle, next, attack);
return true;
}
} }
return false;
}
if (!curOwner || !gameHandler->randomizer->rollCombatAbility(curOwner->id, curOwner->valOfBonuses(BonusType::MANUAL_CONTROL, BonusSubtypeID(CreatureID(CreatureID::CATAPULT))))) bool BattleFlowProcessor::tryMakeAutomaticActionOfFirstAidTent(const CBattleInfoCallback & battle, const CStack * next) {
{ const CGHeroInstance * curOwner = battle.battleGetOwnerHero(next);
BattleAction attack;
attack.actionType = EActionType::CATAPULT;
attack.side = next->unitSide();
attack.stackNumber = next->unitId();
makeAutomaticAction(battle, next, attack);
return true;
}
}
if (next->unitType()->getId() == CreatureID::FIRST_AID_TENT) if (next->unitType()->getId() == CreatureID::FIRST_AID_TENT)
{ {
TStacks possibleStacks = battle.battleGetStacksIf([&next](const CStack * s) TStacks possibleStacks = battle.battleGetStacksIf([&next](const CStack * s)
@@ -500,17 +533,10 @@ bool BattleFlowProcessor::tryMakeAutomaticAction(const CBattleInfoCallback & bat
return true; return true;
} }
} }
stackTurnTrigger(battle, next); //various effects
if(next->fear)
{
makeStackDoNothing(battle, next); //end immediately if stack was affected by fear
return true;
}
return false; return false;
} }
bool BattleFlowProcessor::rollGoodMorale(const CBattleInfoCallback & battle, const CStack * next) bool BattleFlowProcessor::rollGoodMorale(const CBattleInfoCallback & battle, const CStack * next)
{ {
//check for good morale //check for good morale
@@ -539,7 +565,7 @@ bool BattleFlowProcessor::rollGoodMorale(const CBattleInfoCallback & battle, con
return false; return false;
} }
void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const BattleAction &ba) void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const BattleAction &ba) //here
{ {
const auto * actedStack = battle.battleGetStackByID(ba.stackNumber, false); const auto * actedStack = battle.battleGetStackByID(ba.stackNumber, false);
const auto * activeStack = battle.battleActiveUnit(); const auto * activeStack = battle.battleActiveUnit();

View File

@@ -38,6 +38,12 @@ class BattleFlowProcessor : boost::noncopyable
bool rollGoodMorale(const CBattleInfoCallback & battle, const CStack * stack); bool rollGoodMorale(const CBattleInfoCallback & battle, const CStack * stack);
bool tryMakeAutomaticAction(const CBattleInfoCallback & battle, const CStack * stack); bool tryMakeAutomaticAction(const CBattleInfoCallback & battle, const CStack * stack);
bool tryActivateMoralePenalty(const CBattleInfoCallback & battle, const CStack * stack);
bool tryActivateBerserkPenalty(const CBattleInfoCallback & battle, const CStack * stack);
bool tryAutomaticActionOfWarMachines(const CBattleInfoCallback & battle, const CStack * stack);
bool tryMakeAutomaticActionOfBallistaOrTowers(const CBattleInfoCallback & battle, const CStack * stack);
bool tryMakeAutomaticActionOfCatapult(const CBattleInfoCallback & battle, const CStack * stack);
bool tryMakeAutomaticActionOfFirstAidTent(const CBattleInfoCallback & battle, const CStack * stack);
void summonGuardiansHelper(const CBattleInfoCallback & battle, BattleHexArray & output, const BattleHex & targetPosition, BattleSide side, bool targetIsTwoHex); void summonGuardiansHelper(const CBattleInfoCallback & battle, BattleHexArray & output, const BattleHex & targetPosition, BattleSide side, bool targetIsTwoHex);
void trySummonGuardians(const CBattleInfoCallback & battle, const CStack * stack); void trySummonGuardians(const CBattleInfoCallback & battle, const CStack * stack);
@@ -54,6 +60,7 @@ class BattleFlowProcessor : boost::noncopyable
void makeStackDoNothing(const CBattleInfoCallback & battle, const CStack * next); void makeStackDoNothing(const CBattleInfoCallback & battle, const CStack * next);
bool makeAutomaticAction(const CBattleInfoCallback & battle, const CStack * stack, const BattleAction & ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack) bool makeAutomaticAction(const CBattleInfoCallback & battle, const CStack * stack, const BattleAction & ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack)
public: public:
explicit BattleFlowProcessor(BattleProcessor * owner, CGameHandler * newGameHandler); explicit BattleFlowProcessor(BattleProcessor * owner, CGameHandler * newGameHandler);