1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Broken CHealth dependency on CStack

This commit is contained in:
AlexVinS 2017-07-09 19:49:52 +03:00
parent f0713c1d36
commit 44fc0cb57b
4 changed files with 69 additions and 31 deletions

View File

@ -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<int64_t>(firstHPleft) + owner->MaxHealth() * fullUnits;
return static_cast<int64_t>(firstHPleft) + owner->unitMaxHealth() * fullUnits;
}
int64_t CHealth::total() const
{
return static_cast<int64_t>(owner->MaxHealth()) * owner->baseAmount;
return static_cast<int64_t>(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<int32_t>::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::vector<const CS
text.addReplacement(MetaString::SPELL_NAME, spell->id.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))

View File

@ -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<const CStack *> & 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;

View File

@ -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);
}

View File

@ -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);
}