From 5dac8e2bbf21362068ca4fecdd0bbd7da4dd497f Mon Sep 17 00:00:00 2001 From: Dydzio Date: Sun, 7 Jan 2024 21:05:55 +0100 Subject: [PATCH] Extract spell layers processing into separate method --- server/battles/BattleActionProcessor.cpp | 108 ++++++++++++----------- server/battles/BattleActionProcessor.h | 3 + 2 files changed, 60 insertions(+), 51 deletions(-) diff --git a/server/battles/BattleActionProcessor.cpp b/server/battles/BattleActionProcessor.cpp index e225d95fc..6d268fd6f 100644 --- a/server/battles/BattleActionProcessor.cpp +++ b/server/battles/BattleActionProcessor.cpp @@ -1123,58 +1123,8 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo { if(attacker->hasBonusOfType(attackMode)) { - std::set spellsToCast; - - const int unlayeredItemsInternalLayer = -1; TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode)); - - std::map>> spellsWithBackupLayers; - - for(int i = 0; i < spells->size(); i++) - { - std::shared_ptr bonus = spells->operator[](i); - int layer = bonus->additionalInfo[2]; - vstd::amax(layer, -1); - spellsWithBackupLayers[layer].push_back(bonus); - } - - auto addSpellsFromLayer = [&](int layer) -> void - { - assert(spellsWithBackupLayers.find(layer) != spellsWithBackupLayers.end()); - - for(const auto & spell : spellsWithBackupLayers[layer]) - { - if (spell->subtype.as() != SpellID()) - spellsToCast.insert(spell->subtype.as()); - else - logGlobal->error("Invalid spell to cast during attack!"); - } - }; - - if(spellsWithBackupLayers.find(unlayeredItemsInternalLayer) != spellsWithBackupLayers.end()) - { - addSpellsFromLayer(unlayeredItemsInternalLayer); - spellsWithBackupLayers.erase(unlayeredItemsInternalLayer); - } - - for(auto item : spellsWithBackupLayers) - { - if(item.first < spellsWithBackupLayers.rbegin()->first) - { - bool areCurrentLayerSpellsApplied = std::all_of(item.second.begin(), item.second.end(), - [&](const std::shared_ptr spell) - { - std::vector activeSpells = defender->activeSpells(); - return vstd::find(activeSpells, spell->subtype.as()) != activeSpells.end(); - }); - - if(areCurrentLayerSpellsApplied) - continue; - } - - addSpellsFromLayer(item.first); - break; - } + std::set spellsToCast = getSpellsForAttackCasting(spells, defender); for(SpellID spellID : spellsToCast) { @@ -1234,6 +1184,62 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo } } +std::set BattleActionProcessor::getSpellsForAttackCasting(TConstBonusListPtr spells, const CStack *defender) +{ + std::set spellsToCast; + constexpr int unlayeredItemsInternalLayer = -1; + + std::map>> spellsWithBackupLayers; + + for(int i = 0; i < spells->size(); i++) + { + std::shared_ptr bonus = spells->operator[](i); + int layer = bonus->additionalInfo[2]; + vstd::amax(layer, -1); + spellsWithBackupLayers[layer].push_back(bonus); + } + + auto addSpellsFromLayer = [&](int layer) -> void + { + assert(spellsWithBackupLayers.find(layer) != spellsWithBackupLayers.end()); + + for(const auto & spell : spellsWithBackupLayers[layer]) + { + if (spell->subtype.as() != SpellID()) + spellsToCast.insert(spell->subtype.as()); + else + logGlobal->error("Invalid spell to cast during attack!"); + } + }; + + if(spellsWithBackupLayers.find(unlayeredItemsInternalLayer) != spellsWithBackupLayers.end()) + { + addSpellsFromLayer(unlayeredItemsInternalLayer); + spellsWithBackupLayers.erase(unlayeredItemsInternalLayer); + } + + for(auto item : spellsWithBackupLayers) + { + if(item.first < spellsWithBackupLayers.rbegin()->first) + { + bool areCurrentLayerSpellsApplied = std::all_of(item.second.begin(), item.second.end(), + [&](const std::shared_ptr spell) + { + std::vector activeSpells = defender->activeSpells(); + return vstd::find(activeSpells, spell->subtype.as()) != activeSpells.end(); + }); + + if(areCurrentLayerSpellsApplied) + continue; + } + + addSpellsFromLayer(item.first); + break; + } + + return spellsToCast; +} + void BattleActionProcessor::handleAttackBeforeCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender) { attackCasting(battle, ranged, BonusType::SPELL_BEFORE_ATTACK, attacker, defender); //no death stare / acid breath needed? diff --git a/server/battles/BattleActionProcessor.h b/server/battles/BattleActionProcessor.h index 01cf5d307..85585b7e7 100644 --- a/server/battles/BattleActionProcessor.h +++ b/server/battles/BattleActionProcessor.h @@ -8,6 +8,7 @@ * */ #pragma once +#include "bonuses/BonusList.h" VCMI_LIB_NAMESPACE_BEGIN @@ -45,6 +46,8 @@ class BattleActionProcessor : boost::noncopyable void handleAttackBeforeCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender); void handleAfterAttackCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender); void attackCasting(const CBattleInfoCallback & battle, bool ranged, BonusType attackMode, const battle::Unit * attacker, const CStack * defender); + + std::set getSpellsForAttackCasting(TConstBonusListPtr spells, const CStack *defender); // damage, drain life & fire shield; returns amount of drained life int64_t applyBattleEffects(const CBattleInfoCallback & battle, BattleAttack & bat, std::shared_ptr attackerState, FireShieldInfo & fireShield, const CStack * def, int distance, bool secondary);