瀏覽代碼

Broken CHealth dependency on CStack

AlexVinS 8 年之前
父節點
當前提交
44fc0cb57b
共有 4 個文件被更改,包括 69 次插入31 次删除
  1. 46 26
      lib/CStack.cpp
  2. 18 4
      lib/CStack.h
  3. 1 0
      lib/spells/BattleSpellMechanics.cpp
  4. 4 1
      server/CGameHandler.cpp

+ 46 - 26
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<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))

+ 18 - 4
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<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;

+ 1 - 0
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);
 	}

+ 4 - 1
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);
 				}