From 30d7bdc884c221a24804155070cfb68c30bcf2f3 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 16 Jan 2023 18:28:05 +0200 Subject: [PATCH] Moved tower damage computation to town instance --- lib/battle/DamageCalculator.cpp | 55 +++++++++++-------------------- lib/mapObjects/CGTownInstance.cpp | 36 ++++++++++++++++++++ lib/mapObjects/CGTownInstance.h | 6 ++++ 3 files changed, 61 insertions(+), 36 deletions(-) diff --git a/lib/battle/DamageCalculator.cpp b/lib/battle/DamageCalculator.cpp index d2b50046b..e176e4bde 100644 --- a/lib/battle/DamageCalculator.cpp +++ b/lib/battle/DamageCalculator.cpp @@ -20,38 +20,6 @@ VCMI_LIB_NAMESPACE_BEGIN -namespace SiegeStuffThatShouldBeMovedToHandlers // <=== TODO -{ - -static void retrieveTurretDamageRange(const CGTownInstance * town, const battle::Unit * turret, double & outMinDmg, double & outMaxDmg) -{ - // http://heroes.thelazy.net/wiki/Arrow_tower - assert(turret->creatureIndex() == CreatureID::ARROW_TOWERS); - assert(town); - assert(turret->getPosition() >= -4 && turret->getPosition() <= -2); - - // base damage, irregardless of town level - static const int baseDamageKeep = 10; - static const int baseDamageTower = 6; - - // extra damage, for each building in town - static const int extraDamage = 2; - - const int townLevel = town->getTownLevel(); - - int minDamage; - - if(turret->getPosition() == BattleHex::CASTLE_CENTRAL_TOWER) - minDamage = baseDamageKeep + townLevel * extraDamage; - else - minDamage = baseDamageTower + townLevel / 2 * extraDamage; - - outMinDmg = minDamage; - outMaxDmg = minDamage * 2; -} - -} - TDmgRange DamageCalculator::getBaseDamageSingle() const { double minDmg = 0.0; @@ -61,19 +29,34 @@ TDmgRange DamageCalculator::getBaseDamageSingle() const maxDmg = info.attacker->getMaxDamage(info.shooting); if(info.attacker->creatureIndex() == CreatureID::ARROW_TOWERS) - SiegeStuffThatShouldBeMovedToHandlers::retrieveTurretDamageRange(callback.battleGetDefendedTown(), info.attacker, minDmg, maxDmg); + { + auto town = callback.battleGetDefendedTown(); + assert(town); + + switch(info.attacker->getPosition()) + { + case BattleHex::CASTLE_CENTRAL_TOWER: + return town->getKeepDamageRange(); + case BattleHex::CASTLE_BOTTOM_TOWER: + case BattleHex::CASTLE_UPPER_TOWER: + return town->getTowerDamageRange(); + default: + assert(0); + } + } const std::string cachingStrSiedgeWeapon = "type_SIEGE_WEAPON"; static const auto selectorSiedgeWeapon = Selector::type()(Bonus::SIEGE_WEAPON); - if(info.attacker->hasBonus(selectorSiedgeWeapon, cachingStrSiedgeWeapon) && info.attacker->creatureIndex() != CreatureID::ARROW_TOWERS) //any siege weapon, but only ballista can attack (second condition - not arrow turret) - { //minDmg and maxDmg are multiplied by hero attack + 1 + if(info.attacker->hasBonus(selectorSiedgeWeapon, cachingStrSiedgeWeapon) && info.attacker->creatureIndex() != CreatureID::ARROW_TOWERS) + { auto retrieveHeroPrimSkill = [&](int skill) -> int { std::shared_ptr b = info.attacker->getBonus(Selector::sourceTypeSel(Bonus::HERO_BASE_SKILL).And(Selector::typeSubtype(Bonus::PRIMARY_SKILL, skill))); - return b ? b->val : 0; //if there is no hero or no info on his primary skill, return 0 + return b ? b->val : 0; }; + //minDmg and maxDmg are multiplied by hero attack + 1 minDmg *= retrieveHeroPrimSkill(PrimarySkill::ATTACK) + 1; maxDmg *= retrieveHeroPrimSkill(PrimarySkill::ATTACK) + 1; } diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 65e8f85c6..6317e2425 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -799,6 +799,42 @@ void CGTownInstance::addTownBonuses() } } +TDmgRange CGTownInstance::getTowerDamageRange() const +{ + assert(hasBuilt(BuildingID::CASTLE)); + + // http://heroes.thelazy.net/wiki/Arrow_tower + // base damage, irregardless of town level + static const int baseDamage = 6; + // extra damage, for each building in town + static const int extraDamage = 1; + + const int minDamage = baseDamage + extraDamage * getTownLevel(); + + return { + minDamage, + minDamage * 2 + }; +} + +TDmgRange CGTownInstance::getKeepDamageRange() const +{ + assert(hasBuilt(BuildingID::CITADEL)); + + // http://heroes.thelazy.net/wiki/Arrow_tower + // base damage, irregardless of town level + static const int baseDamage = 10; + // extra damage, for each building in town + static const int extraDamage = 2; + + const int minDamage = baseDamage + extraDamage * getTownLevel(); + + return { + minDamage, + minDamage * 2 + }; +} + void CGTownInstance::deleteTownBonus(BuildingID::EBuildingID bid) { size_t i = 0; diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index 032dfc1e2..bfd8b9052 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -330,6 +330,12 @@ public: void addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID) const; //hero must be visiting or garrisoned in town void deleteTownBonus(BuildingID::EBuildingID bid); + /// Returns damage range for secondary towers of this town + TDmgRange getTowerDamageRange() const; + + /// Returns damage range for central tower(keep) of this town + TDmgRange getKeepDamageRange() const; + const CTown * getTown() const ; CGTownInstance();