2
0
Эх сурвалжийг харах

Merge pull request #3726 from IvanSavenko/fix_summon

Block spellcasting if 0 creatures will be raised
Ivan Savenko 1 жил өмнө
parent
commit
ede69ca58b

+ 26 - 18
lib/spells/effects/DemonSummon.cpp

@@ -25,6 +25,30 @@ namespace spells
 namespace effects
 {
 
+int DemonSummon::raisedCreatureAmount(const Mechanics * m, const battle::Unit * unit) const
+{
+	if(!unit || unit->alive() || unit->isGhost())
+		return 0;
+
+	const auto *creatureType = creature.toEntity(m->creatures());
+
+	int32_t deadCount         = unit->unitBaseAmount();
+	int32_t deadTotalHealth   = unit->getTotalHealth();
+	int32_t raisedMaxHealth   = creatureType->getMaxHealth();
+	int32_t raisedTotalHealth = m->applySpellBonus(m->getEffectValue(), unit);
+
+	// Can't raise stack with more HP than original stack
+	int32_t maxAmountFromHealth     = deadTotalHealth / raisedMaxHealth;
+	// Can't raise stack with more creatures than original stack
+	int32_t maxAmountFromAmount     = deadCount;
+	// Can't raise stack with more HP than our spellpower
+	int32_t maxAmountFromSpellpower = raisedTotalHealth / raisedMaxHealth;
+
+	int32_t finalAmount = std::min( { maxAmountFromHealth, maxAmountFromAmount, maxAmountFromSpellpower } );
+
+	return finalAmount;
+}
+
 void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
 {
 	BattleUnitsChanged pack;
@@ -49,21 +73,7 @@ void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const Effe
 			break;
 		}
 
-		const auto *creatureType = creature.toEntity(m->creatures());
-
-		int32_t deadCount         = targetStack->unitBaseAmount();
-		int32_t deadTotalHealth   = targetStack->getTotalHealth();
-		int32_t raisedMaxHealth   = creatureType->getMaxHealth();
-		int32_t raisedTotalHealth = m->applySpellBonus(m->getEffectValue(), targetStack);
-
-		// Can't raise stack with more HP than original stack
-		int32_t maxAmountFromHealth     = deadTotalHealth / raisedMaxHealth;
-		// Can't raise stack with more creatures than original stack
-		int32_t maxAmountFromAmount     = deadCount;
-		// Can't raise stack with more HP than our spellpower
-		int32_t maxAmountFromSpellpower = raisedTotalHealth / raisedMaxHealth;
-
-		int32_t finalAmount = std::min( { maxAmountFromHealth, maxAmountFromAmount, maxAmountFromSpellpower } );
+		int32_t finalAmount = raisedCreatureAmount(m, targetStack);
 
 		if(finalAmount < 1)
 		{
@@ -111,9 +121,7 @@ bool DemonSummon::isValidTarget(const Mechanics * m, const battle::Unit * unit)
 	if (unit->isGhost())
 		return false;
 
-	const auto *creatureType = creature.toEntity(m->creatures());
-
-	if (unit->getTotalHealth() < creatureType->getMaxHealth())
+	if (raisedCreatureAmount(m, unit) == 0)
 		return false;
 
 	return m->isReceptive(unit);

+ 3 - 1
lib/spells/effects/DemonSummon.h

@@ -30,7 +30,9 @@ protected:
 	void serializeJsonUnitEffect(JsonSerializeFormat & handler) override final;
 
 private:
-	CreatureID creature = CreatureID(0);
+	int32_t raisedCreatureAmount(const Mechanics * m, const battle::Unit * unit) const;
+
+	CreatureID creature;
 
 	bool permanent = false;
 };

+ 34 - 16
lib/spells/effects/Summon.cpp

@@ -48,6 +48,12 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const
 		return m->adaptGenericProblem(problem);
 	}
 
+	if (summonedCreatureAmount(m) == 0)
+	{
+		logMod->debug("Attempt to summon zero creatures!");
+		return m->adaptGenericProblem(problem);
+	}
+
 	if(exclusive)
 	{
 		//check if there are summoned creatures of other type
@@ -88,11 +94,34 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const
 	return true;
 }
 
-void Summon::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
+int32_t Summon::summonedCreatureHealth(const Mechanics * m, const battle::Unit * unit) const
+{
+	auto valueWithBonus = m->applySpecificSpellBonus(m->calculateRawEffectValue(0, m->getEffectPower()));
+
+	if(summonByHealth)
+		return valueWithBonus;
+	else
+		return valueWithBonus * unit->getMaxHealth();
+}
+
+int32_t Summon::summonedCreatureAmount(const Mechanics * m) const
 {
-	//new feature - percentage bonus
-	auto valueWithBonus = m->applySpecificSpellBonus(m->calculateRawEffectValue(0, m->getEffectPower()));//TODO: consider use base power too
+	auto valueWithBonus = m->applySpecificSpellBonus(m->calculateRawEffectValue(0, m->getEffectPower()));
+
+	if(summonByHealth)
+	{
+		const auto *creatureType = creature.toEntity(m->creatures());
+		auto creatureMaxHealth = creatureType->getMaxHealth();
+		return valueWithBonus / creatureMaxHealth;
+	}
+	else
+	{
+		return valueWithBonus;
+	}
+}
 
+void Summon::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
+{
 	BattleUnitsChanged pack;
 	pack.battleID = m->battle()->getBattle()->getBattleID();
 
@@ -102,25 +131,14 @@ void Summon::apply(ServerCallback * server, const Mechanics * m, const EffectTar
 		{
 			const battle::Unit * summoned = dest.unitValue;
 			std::shared_ptr<battle::Unit> state = summoned->acquire();
-			int64_t healthValue = (summonByHealth ? valueWithBonus : (valueWithBonus * summoned->getMaxHealth()));
+			int64_t healthValue = summonedCreatureHealth(m, summoned);
 			state->heal(healthValue, EHealLevel::OVERHEAL, (permanent ? EHealPower::PERMANENT : EHealPower::ONE_BATTLE));
 			pack.changedStacks.emplace_back(summoned->unitId(), UnitChanges::EOperation::RESET_STATE);
 			state->save(pack.changedStacks.back().data);
 		}
 		else
 		{
-			int32_t amount = 0;
-
-			if(summonByHealth)
-			{
-				const auto *creatureType = creature.toEntity(m->creatures());
-				auto creatureMaxHealth = creatureType->getMaxHealth();
-				amount = static_cast<int32_t>(valueWithBonus / creatureMaxHealth);
-			}
-			else
-			{
-				amount = static_cast<int32_t>(valueWithBonus);
-			}
+			int32_t amount = summonedCreatureAmount(m);
 
 			if(amount < 1)
 			{

+ 3 - 0
lib/spells/effects/Summon.h

@@ -38,6 +38,9 @@ protected:
 	void serializeJsonEffect(JsonSerializeFormat & handler) override final;
 
 private:
+	int32_t summonedCreatureAmount(const Mechanics * m) const;
+	int32_t summonedCreatureHealth(const Mechanics * m, const battle::Unit * unit) const;
+
 	CreatureID creature;
 
 	bool permanent = false;