1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Extract spell layers processing into separate method

This commit is contained in:
Dydzio 2024-01-07 21:05:55 +01:00
parent 310802ed87
commit 5dac8e2bbf
2 changed files with 60 additions and 51 deletions

View File

@ -1123,58 +1123,8 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
{
if(attacker->hasBonusOfType(attackMode))
{
std::set<SpellID> spellsToCast;
const int unlayeredItemsInternalLayer = -1;
TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
std::map<int, std::vector<std::shared_ptr<Bonus>>> spellsWithBackupLayers;
for(int i = 0; i < spells->size(); i++)
{
std::shared_ptr<Bonus> 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>() != SpellID())
spellsToCast.insert(spell->subtype.as<SpellID>());
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<Bonus> spell)
{
std::vector<SpellID> activeSpells = defender->activeSpells();
return vstd::find(activeSpells, spell->subtype.as<SpellID>()) != activeSpells.end();
});
if(areCurrentLayerSpellsApplied)
continue;
}
addSpellsFromLayer(item.first);
break;
}
std::set<SpellID> spellsToCast = getSpellsForAttackCasting(spells, defender);
for(SpellID spellID : spellsToCast)
{
@ -1234,6 +1184,62 @@ void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bo
}
}
std::set<SpellID> BattleActionProcessor::getSpellsForAttackCasting(TConstBonusListPtr spells, const CStack *defender)
{
std::set<SpellID> spellsToCast;
constexpr int unlayeredItemsInternalLayer = -1;
std::map<int, std::vector<std::shared_ptr<Bonus>>> spellsWithBackupLayers;
for(int i = 0; i < spells->size(); i++)
{
std::shared_ptr<Bonus> 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>() != SpellID())
spellsToCast.insert(spell->subtype.as<SpellID>());
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<Bonus> spell)
{
std::vector<SpellID> activeSpells = defender->activeSpells();
return vstd::find(activeSpells, spell->subtype.as<SpellID>()) != 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?

View File

@ -8,6 +8,7 @@
*
*/
#pragma once
#include "bonuses/BonusList.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -46,6 +47,8 @@ class BattleActionProcessor : boost::noncopyable
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<SpellID> 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<battle::CUnitState> attackerState, FireShieldInfo & fireShield, const CStack * def, int distance, bool secondary);