From 44fc0cb57b732729c4fb775a4d6482afc22d0dc2 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Sun, 9 Jul 2017 19:49:52 +0300 Subject: [PATCH] Broken CHealth dependency on CStack --- lib/CStack.cpp | 72 ++++++++++++++++++----------- lib/CStack.h | 22 +++++++-- lib/spells/BattleSpellMechanics.cpp | 1 + server/CGameHandler.cpp | 5 +- 4 files changed, 69 insertions(+), 31 deletions(-) diff --git a/lib/CStack.cpp b/lib/CStack.cpp index e376981ca..9c4a58a02 100644 --- a/lib/CStack.cpp +++ b/lib/CStack.cpp @@ -108,7 +108,7 @@ void CRetaliations::reset() } ///CHealth -CHealth::CHealth(const CStack * Owner): +CHealth::CHealth(const IUnitHealthInfo * Owner): owner(Owner) { reset(); @@ -123,11 +123,11 @@ CHealth::CHealth(const CHealth & other): } -void CHealth::init(const int32_t baseAmount) +void CHealth::init() { reset(); - fullUnits = baseAmount > 1 ? baseAmount - 1 : 0; - firstHPleft = baseAmount > 0 ? owner->MaxHealth() : 0; + fullUnits = owner->unitBaseAmount() > 1 ? owner->unitBaseAmount() - 1 : 0; + firstHPleft = owner->unitBaseAmount() > 0 ? owner->unitMaxHealth() : 0; } void CHealth::addResurrected(int32_t amount) @@ -138,24 +138,16 @@ void CHealth::addResurrected(int32_t amount) int64_t CHealth::available() const { - return static_cast(firstHPleft) + owner->MaxHealth() * fullUnits; + return static_cast(firstHPleft) + owner->unitMaxHealth() * fullUnits; } int64_t CHealth::total() const { - return static_cast(owner->MaxHealth()) * owner->baseAmount; + return static_cast(owner->unitMaxHealth()) * owner->unitBaseAmount(); } void CHealth::damage(int32_t & amount) { - if(owner->isClone()) - { - // block ability should not kill clone (0 damage) - if(amount > 0) - reset(); - return; - } - const int32_t oldCount = getCount(); const bool withKills = amount >= firstHPleft; @@ -186,7 +178,7 @@ void CHealth::damage(int32_t & amount) void CHealth::heal(int32_t & amount, EHealLevel level, EHealPower power) { - const int32_t unitHealth = owner->MaxHealth(); + const int32_t unitHealth = owner->unitMaxHealth(); const int32_t oldCount = getCount(); int32_t maxHeal = std::numeric_limits::max(); @@ -223,7 +215,7 @@ void CHealth::heal(int32_t & amount, EHealLevel level, EHealPower power) void CHealth::setFromTotal(const int64_t totalHealth) { - const int32_t unitHealth = owner->MaxHealth(); + const int32_t unitHealth = owner->unitMaxHealth(); firstHPleft = totalHealth % unitHealth; fullUnits = totalHealth / unitHealth; @@ -265,7 +257,6 @@ void CHealth::fromInfo(const CHealthInfo & info) void CHealth::toInfo(CHealthInfo & info) const { - info.stackId = owner->ID; info.firstHPleft = firstHPleft; info.fullUnits = fullUnits; info.resurrected = resurrected; @@ -275,7 +266,7 @@ void CHealth::takeResurrected() { int64_t totalHealth = total(); - totalHealth -= resurrected * owner->MaxHealth(); + totalHealth -= resurrected * owner->unitMaxHealth(); vstd::amax(totalHealth, 0); setFromTotal(totalHealth); resurrected = 0; @@ -290,7 +281,7 @@ CStack::CStack(const CStackInstance * Base, PlayerColor O, int I, ui8 Side, Slot assert(base); type = base->type; baseAmount = base->count; - health.init(baseAmount); //??? + health.init(); //??? setNodeType(STACK_BATTLE); } @@ -308,7 +299,7 @@ CStack::CStack(const CStackBasicDescriptor * stack, PlayerColor O, int I, ui8 Si { type = stack->type; baseAmount = stack->count; - health.init(baseAmount); //??? + health.init(); //??? setNodeType(STACK_BATTLE); } @@ -350,6 +341,7 @@ void CStack::init() void CStack::localInit(BattleInfo * battleInfo) { battle = battleInfo; + cloneID = -1; assert(type); exportBonuses(); @@ -367,8 +359,7 @@ void CStack::localInit(BattleInfo * battleInfo) shots.reset(); counterAttacks.reset(); casts.reset(); - health.init(baseAmount); - cloneID = -1; + health.init(); } ui32 CStack::level() const @@ -620,8 +611,27 @@ std::string CStack::nodeName() const CHealth CStack::healthAfterAttacked(int32_t & damage) const { - CHealth res = health; - res.damage(damage); + return healthAfterAttacked(damage, health); +} + +CHealth CStack::healthAfterAttacked(int32_t & damage, const CHealth & customHealth) const +{ + CHealth res = customHealth; + + if(isClone()) + { + // block ability should not kill clone (0 damage) + if(damage > 0) + { + damage = 1;//??? what should be actual damage against clone? + res.reset(); + } + } + else + { + res.damage(damage); + } + return res; } @@ -646,11 +656,11 @@ void CStack::prepareAttacked(BattleStackAttacked & bsa, CRandomGenerator & rand) void CStack::prepareAttacked(BattleStackAttacked & bsa, CRandomGenerator & rand, const CHealth & customHealth) const { - CHealth afterAttack = customHealth; - afterAttack.damage(bsa.damageAmount); + CHealth afterAttack = healthAfterAttacked(bsa.damageAmount, customHealth); bsa.killedAmount = customHealth.getCount() - afterAttack.getCount(); afterAttack.toInfo(bsa.newHealth); + bsa.newHealth.stackId = ID; bsa.newHealth.delta = -bsa.damageAmount; if(afterAttack.available() <= 0 && isClone()) @@ -824,6 +834,16 @@ void CStack::getCastDescription(const CSpell * spell, const std::vectorid.toEnum()); } +int32_t CStack::unitMaxHealth() const +{ + return MaxHealth(); +} + +int32_t CStack::unitBaseAmount() const +{ + return baseAmount; +} + void CStack::addText(MetaString & text, ui8 type, int32_t serial, const boost::logic::tribool & plural) const { if(boost::logic::indeterminate(plural)) diff --git a/lib/CStack.h b/lib/CStack.h index 0ba1ab741..5633eb37c 100644 --- a/lib/CStack.h +++ b/lib/CStack.h @@ -81,13 +81,20 @@ private: mutable int32_t totalCache; }; +class DLL_LINKAGE IUnitHealthInfo +{ +public: + virtual int32_t unitMaxHealth() const = 0; + virtual int32_t unitBaseAmount() const = 0; +}; + class DLL_LINKAGE CHealth { public: - CHealth(const CStack * Owner); + CHealth(const IUnitHealthInfo * Owner); CHealth(const CHealth & other); - void init(const int32_t baseAmount); + void init(); void reset(); void damage(int32_t & amount); @@ -114,14 +121,14 @@ public: private: void addResurrected(int32_t amount); void setFromTotal(const int64_t totalHealth); - const CStack * owner; + const IUnitHealthInfo * owner; int32_t firstHPleft; int32_t fullUnits; int32_t resurrected; }; -class DLL_LINKAGE CStack : public CBonusSystemNode, public ISpellCaster +class DLL_LINKAGE CStack : public CBonusSystemNode, public ISpellCaster, public IUnitHealthInfo { public: const CStackInstance * base; //garrison slot from which stack originates (nullptr for war machines, summoned cres, etc) @@ -195,6 +202,8 @@ public: BattleHex::EDir destShiftDir() const; CHealth healthAfterAttacked(int32_t & damage) const; + CHealth healthAfterAttacked(int32_t & damage, const CHealth & customHealth) const; + CHealth healthAfterHealed(int32_t & toHeal, EHealLevel level, EHealPower power) const; void prepareAttacked(BattleStackAttacked & bsa, CRandomGenerator & rand) const; //requires bsa.damageAmout filled @@ -221,6 +230,11 @@ public: void getCasterName(MetaString & text) const override; void getCastDescription(const CSpell * spell, const std::vector & attacked, MetaString & text) const override; + ///IUnitHealthInfo + + int32_t unitMaxHealth() const override; + int32_t unitBaseAmount() const override; + ///MetaStrings void addText(MetaString & text, ui8 type, int32_t serial, const boost::logic::tribool & plural = boost::logic::indeterminate) const; diff --git a/lib/spells/BattleSpellMechanics.cpp b/lib/spells/BattleSpellMechanics.cpp index b40e6bd0d..9a2867737 100644 --- a/lib/spells/BattleSpellMechanics.cpp +++ b/lib/spells/BattleSpellMechanics.cpp @@ -43,6 +43,7 @@ void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, CHealthInfo hi; health.toInfo(hi); + hi.stackId = attackedCre->ID; hi.delta = stackHPgained; shr.healedStacks.push_back(hi); } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 7200410cc..428be196d 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -965,6 +965,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons CHealthInfo hi; health.toInfo(hi); + hi.stackId = att->ID; hi.delta = toHeal; shi.healedStacks.push_back(hi); @@ -989,6 +990,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons CHealth health = att->healthAfterHealed(toHeal, EHealLevel::OVERHEAL, ((i == 0) ? EHealPower::ONE_BATTLE : EHealPower::PERMANENT)); CHealthInfo hi; health.toInfo(hi); + hi.stackId = att->ID; hi.delta = toHeal; if(hi.delta > 0) shi.healedStacks.push_back(hi); @@ -4242,7 +4244,8 @@ bool CGameHandler::makeBattleAction(BattleAction &ba) CHealthInfo hi; health.toInfo(hi); - + hi.stackId = destStack->ID; + hi.delta = toHeal; shr.healedStacks.push_back(hi); sendAndApply(&shr); }