Ver código fonte

Demon summon is now a spell. DEMON_SUMMONING bonus has been removed

Ivan Savenko 2 anos atrás
pai
commit
9248e06ae0

+ 0 - 22
client/battle/BattleActionsController.cpp

@@ -171,8 +171,6 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
 			break;
 		case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
 			return 2; break;
-		case PossiblePlayerBattleAction::RISE_DEMONS:
-			return 3; break;
 		case PossiblePlayerBattleAction::SHOOT:
 			return 4; break;
 		case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
@@ -374,19 +372,6 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
 				if (shere && ourStack && shere->canBeHealed())
 					legalAction = true;
 				break;
-			case PossiblePlayerBattleAction::RISE_DEMONS:
-				if (shere && ourStack && !shere->alive())
-				{
-					if (!(shere->hasBonusOfType(Bonus::UNDEAD)
-						|| shere->hasBonusOfType(Bonus::NON_LIVING)
-						|| shere->hasBonusOfType(Bonus::GARGOYLE)
-						|| shere->summoned
-						|| shere->isClone()
-						|| shere->hasBonusOfType(Bonus::SIEGE_WEAPON)
-						))
-						legalAction = true;
-				}
-				break;
 		}
 		if (legalAction)
 			localActions.push_back (action);
@@ -542,13 +527,6 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
 				newConsoleMsg = (boost::format(CGI->generaltexth->allTexts[419]) % shere->getName()).str(); //Apply first aid to the %s
 				realizeAction = [=](){ owner.giveCommand(EActionType::STACK_HEAL, myNumber); }; //command healing
 				break;
-			case PossiblePlayerBattleAction::RISE_DEMONS:
-				spellcastingCursor = true;
-				realizeAction = [=]()
-				{
-					owner.giveCommand(EActionType::DAEMON_SUMMONING, myNumber);
-				};
-				break;
 			case PossiblePlayerBattleAction::CATAPULT:
 				cursorFrame = Cursor::Combat::SHOOT_CATAPULT;
 				realizeAction = [=](){ owner.giveCommand(EActionType::CATAPULT, myNumber); };

+ 1 - 1
client/battle/BattleStacksController.cpp

@@ -847,7 +847,7 @@ void BattleStacksController::updateHoveredStacks()
 			continue;
 
 		stackAnimation[stack->ID]->setBorderColor(AnimationControls::getBlueBorder());
-		if (stackAnimation[stack->ID]->framesInGroup(ECreatureAnimType::MOUSEON) > 0)
+		if (stackAnimation[stack->ID]->framesInGroup(ECreatureAnimType::MOUSEON) > 0 && stack->alive())
 			stackAnimation[stack->ID]->playOnce(ECreatureAnimType::MOUSEON);
 
 	}

+ 2 - 0
cmake_modules/VCMI_lib.cmake

@@ -139,6 +139,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/spells/effects/Catapult.cpp
 		${MAIN_LIB_DIR}/spells/effects/Clone.cpp
 		${MAIN_LIB_DIR}/spells/effects/Damage.cpp
+		${MAIN_LIB_DIR}/spells/effects/DemonSummon.cpp
 		${MAIN_LIB_DIR}/spells/effects/Dispel.cpp
 		${MAIN_LIB_DIR}/spells/effects/Effect.cpp
 		${MAIN_LIB_DIR}/spells/effects/Effects.cpp
@@ -374,6 +375,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/spells/effects/Catapult.h
 		${MAIN_LIB_DIR}/spells/effects/Clone.h
 		${MAIN_LIB_DIR}/spells/effects/Damage.h
+		${MAIN_LIB_DIR}/spells/effects/DemonSummon.h
 		${MAIN_LIB_DIR}/spells/effects/Dispel.h
 		${MAIN_LIB_DIR}/spells/effects/Effect.h
 		${MAIN_LIB_DIR}/spells/effects/Effects.h

+ 0 - 6
config/artifacts.json

@@ -2240,12 +2240,6 @@
 				"val" : 0,
 				"valueType" : "BASE_NUMBER"
 			},
-			{
-				"subtype" : "creature.vampireLord",
-				"type" : "DAEMON_SUMMONING",
-				"val" : 10,
-				"valueType" : "BASE_NUMBER"
-			},
 			{
 				"addInfo" : 2,
 				"subtype" : "spell.lightningBolt",

+ 0 - 8
config/bonuses.json

@@ -84,14 +84,6 @@
 		}
 	},
 
-	"DAEMON_SUMMONING":
-	{
-		"graphics":
-		{
-			"icon":  "zvs/Lib1.res/RiseDemons"
-		}
-	},
-
 	"DARKNESS":
 	{
 	},

+ 0 - 6
config/bonuses_texts.json

@@ -72,12 +72,6 @@
 		"description": "Immune to Champion charge"
 	},
 
-	"DAEMON_SUMMONING":
-	{
-		"name": "Summoner (${subtype.creature})",
-		"description": "Can rise creatures from corpses"
-	},
-
 	"DARKNESS":
 	{
 		"name": "Darkness cover",

+ 9 - 3
config/creatures/inferno.json

@@ -216,12 +216,18 @@
 		"faction": "inferno",
 		"abilities":
 		{
-			"demonSummon" :
+			"summons50HP" : 
 			{
-				"type" : "DAEMON_SUMMONING",
-				"subtype" : "creature.demon",
+				"type" : "SPECIFIC_SPELL_POWER",
+				"subtype" : "spell.summonDemons",
 				"val" : 50
 			},
+			"resurrects" :
+			{
+				"type" : "SPELLCASTER",
+				"subtype" : "spell.summonDemons",
+				"val" : 0
+			},
 			"castsAmount" :
 			{
 				"type" : "CASTS",

+ 48 - 1
config/spells/ability.json

@@ -430,5 +430,52 @@
 				"bonus.DIRECT_DAMAGE_IMMUNITY" : "normal"
 			}
 		}
-	}
+	},
+	"summonDemons" : {
+		"type": "ability",
+		"targetType" : "CREATURE",
+		"name": "Summon Demons",
+		"school" : {},
+		"level": 2,
+		"power": 50,
+		"defaultGainChance": 0,
+		"gainChance": {},
+		"animation":{
+		},
+		"sounds": {
+			"cast": "RESURECT"
+		},
+		"levels" : {
+			"base": {
+				"description" : "",
+				"aiValue" : 0,
+				"power" : 40,
+				"cost" : 1,
+				"range" : "0",
+				"battleEffects":{
+					"demonSummon":{
+						"id":"demon",
+						"permanent":true,
+						"type":"core:demonSummon"
+					}
+				}
+			},
+			"none" :{},
+			"basic" :{},
+			"advanced" :{},
+			"expert" :{}
+		},
+		"flags" : {
+			"rising": true,
+			"positive": true
+		},
+		"targetCondition" : {
+			"noneOf" : {
+				"bonus.NON_LIVING" : "absolute",
+				"bonus.SIEGE_WEAPON" : "absolute",
+				"bonus.UNDEAD" : "absolute",
+				"bonus.GARGOYLE" : "absolute"
+			}
+		}
+	},
 }

+ 0 - 1
lib/GameConstants.cpp

@@ -232,7 +232,6 @@ std::ostream & operator<<(std::ostream & os, const EActionType actionType)
 		{EActionType::MONSTER_SPELL, "Monster spell"},
 		{EActionType::BAD_MORALE, "Bad morale"},
 		{EActionType::STACK_HEAL, "Stack heal"},
-		{EActionType::DAEMON_SUMMONING, "Daemon summoning"}
 	};
 
 	auto it = actionTypeToString.find(actionType);

+ 0 - 1
lib/GameConstants.h

@@ -922,7 +922,6 @@ enum class EActionType : int32_t
 	MONSTER_SPELL,
 	BAD_MORALE,
 	STACK_HEAL,
-	DAEMON_SUMMONING
 };
 
 DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EActionType actionType);

+ 0 - 1
lib/HeroBonus.h

@@ -237,7 +237,6 @@ public:
 	BONUS_NAME(MANA_CHANNELING) /*value in %, eg. familiar*/ \
 	BONUS_NAME(SPELL_LIKE_ATTACK) /*subtype - spell, value - spell level; range is taken from spell, but damage from creature; eg. magog*/ \
 	BONUS_NAME(THREE_HEADED_ATTACK) /*eg. cerberus*/	\
-	BONUS_NAME(DAEMON_SUMMONING) /*pit lord, subtype - type of creatures, val - hp per unit*/			\
 	BONUS_NAME(FIRE_IMMUNITY)	/*subtype 0 - all, 1 - all except positive, 2 - only damage spells*/						\
 	BONUS_NAME(WATER_IMMUNITY)							\
 	BONUS_NAME(EARTH_IMMUNITY)							\

+ 0 - 2
lib/battle/CBattleInfoCallback.cpp

@@ -230,8 +230,6 @@ std::vector<PossiblePlayerBattleAction> CBattleInfoCallback::getClientActionsFor
 			}
 			if(stack->hasBonusOfType(Bonus::RANDOM_SPELLCASTER))
 				allowedActionList.push_back(PossiblePlayerBattleAction::RANDOM_GENIE_SPELL);
-			if(stack->hasBonusOfType(Bonus::DAEMON_SUMMONING))
-				allowedActionList.push_back(PossiblePlayerBattleAction::RISE_DEMONS);
 		}
 		if(stack->canShoot())
 			allowedActionList.push_back(PossiblePlayerBattleAction::SHOOT);

+ 1 - 1
lib/battle/CBattleInfoCallback.h

@@ -49,7 +49,7 @@ enum class PossiblePlayerBattleAction // actions performed at l-click
 	MOVE_STACK, ATTACK, WALK_AND_ATTACK, ATTACK_AND_RETURN, SHOOT, //OPEN_GATE, //we can open castle gate during siege
 	NO_LOCATION, ANY_LOCATION, OBSTACLE, TELEPORT, SACRIFICE, RANDOM_GENIE_SPELL,
 	FREE_LOCATION, //used with Force Field and Fire Wall - all tiles affected by spell must be free
-	CATAPULT, HEAL, RISE_DEMONS,
+	CATAPULT, HEAL,
 	AIMED_SPELL_CREATURE
 };
 

+ 3 - 3
lib/spells/BattleSpellMechanics.cpp

@@ -608,9 +608,9 @@ std::vector<Destination> BattleSpellMechanics::getPossibleDestinations(size_t in
 				Target tmp = current;
 				tmp.emplace_back(dest);
 
-				detail::ProblemImpl ingored;
+				detail::ProblemImpl ignored;
 
-				if(canBeCastAt(tmp, ingored))
+				if(canBeCastAt(tmp, ignored))
 					ret.emplace_back(dest);
 			}
 		}
@@ -630,7 +630,7 @@ bool BattleSpellMechanics::isReceptive(const battle::Unit * target) const
 	return targetCondition->isReceptive(this, target);
 }
 
-std::vector<BattleHex> BattleSpellMechanics::rangeInHexes(BattleHex centralHex, bool * outDroppedHexes) const
+std::vector<BattleHex> BattleSpellMechanics::rangeInHexes(BattleHex centralHex) const
 {
 	if(isMassive() || !centralHex.isValid())
 		return std::vector<BattleHex>(1, BattleHex::INVALID);

+ 15 - 1
lib/spells/BattleSpellMechanics.h

@@ -27,22 +27,36 @@ public:
 	BattleSpellMechanics(const IBattleCast * event, std::shared_ptr<effects::Effects> effects_, std::shared_ptr<IReceptiveCheck> targetCondition_);
 	virtual ~BattleSpellMechanics();
 
+	// TODO: ??? (what's the difference compared to cast?)
 	void applyEffects(ServerCallback * server, const Target & targets, bool indirect, bool ignoreImmunity) const override;
 
+	/// Returns false if spell can not be cast at all, e.g. due to not having any possible target on battlefield
 	bool canBeCast(Problem & problem) const override;
+
+	/// Returns false if spell can not be cast at specifid target
 	bool canBeCastAt(const Target & target, Problem & problem) const override;
 
+	// TODO: ??? (what's the difference compared to applyEffects?)
 	void cast(ServerCallback * server, const Target & target) override final;
+	// TODO: ??? (what's the difference compared to cast?)
 	void castEval(ServerCallback * server, const Target & target) override final;
 
+	/// Returns list of affected stack using currently configured target
 	std::vector<const CStack *> getAffectedStacks(const Target & target) const override final;
 
+	/// Returns list of target types that can be targeted by spell
 	std::vector<AimType> getTargetTypes() const override final;
+
+	/// Returns vector of all possible destinations for specified aim type
+	/// index - ???
+	/// current - ???
 	std::vector<Destination> getPossibleDestinations(size_t index, AimType aimType, const Target & current) const override final;
 
+	/// Returns true if spell can be cast on unit
 	bool isReceptive(const battle::Unit * target) const override;
 
-	std::vector<BattleHex> rangeInHexes(BattleHex centralHex, bool * outDroppedHexes = nullptr) const override;
+	/// Returns list of hexes that are affected by spell assuming cast at centralHex
+	std::vector<BattleHex> rangeInHexes(BattleHex centralHex) const override;
 
 	const Spell * getSpell() const override;
 

+ 2 - 2
lib/spells/ISpellMechanics.cpp

@@ -701,9 +701,9 @@ PlayerColor BaseMechanics::getCasterColor() const
 std::vector<AimType> BaseMechanics::getTargetTypes() const
 {
 	std::vector<AimType> ret;
-	detail::ProblemImpl ingored;
+	detail::ProblemImpl ignored;
 
-	if(canBeCast(ingored))
+	if(canBeCast(ignored))
 	{
 		auto spellTargetType = owner->getTargetType();
 

+ 1 - 1
lib/spells/ISpellMechanics.h

@@ -183,7 +183,7 @@ public:
 	virtual bool adaptProblem(ESpellCastProblem::ESpellCastProblem source, Problem & target) const = 0;
 	virtual bool adaptGenericProblem(Problem & target) const = 0;
 
-	virtual std::vector<BattleHex> rangeInHexes(BattleHex centralHex, bool * outDroppedHexes = nullptr) const = 0;
+	virtual std::vector<BattleHex> rangeInHexes(BattleHex centralHex) const = 0;
 	virtual std::vector<const CStack *> getAffectedStacks(const Target & target) const = 0;
 
 	virtual bool canBeCast(Problem & problem) const = 0;

+ 130 - 0
lib/spells/effects/DemonSummon.cpp

@@ -0,0 +1,130 @@
+/*
+ * DemonSummon.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+
+#include "DemonSummon.h"
+#include "Registry.h"
+#include "../ISpellMechanics.h"
+#include "../../NetPacks.h"
+#include "../../battle/CBattleInfoCallback.h"
+#include "../../battle/CUnitState.h"
+#include "../../serializer/JsonSerializeFormat.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+static const std::string EFFECT_NAME = "core:demonSummon";
+
+namespace spells
+{
+namespace effects
+{
+
+VCMI_REGISTER_SPELL_EFFECT(DemonSummon, EFFECT_NAME);
+
+DemonSummon::DemonSummon()
+	: UnitEffect()
+	, creature(0)
+	, permanent(false)
+{
+}
+
+DemonSummon::~DemonSummon() = default;
+
+void DemonSummon::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
+{
+	BattleUnitsChanged pack;
+
+	for(const Destination & dest : target)
+	{
+		const battle::Unit * targetStack = dest.unitValue;
+
+		//we shall have all targets to be stacks
+		if(!targetStack || targetStack->alive() || targetStack->isGhost())
+		{
+			server->complain("No corpse to demonize! Invalid effect target transformation.");
+			continue;
+		}
+
+		auto hex = m->battle()->getAvaliableHex(targetStack->creatureId(), m->casterSide, targetStack->getPosition());
+
+		if(!hex.isValid())
+		{
+			server->complain("No place to put new summon!");
+			break;
+		}
+
+		auto creatureType = creature.toCreature(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 } );
+
+		if(finalAmount < 1)
+		{
+			server->complain("Summoning didn't summon any!");
+			continue;
+		}
+
+		battle::UnitInfo info;
+		info.id       = m->battle()->battleNextUnitId();
+		info.count    = finalAmount;
+		info.type     = creature;
+		info.side     = m->casterSide;
+		info.position = dest.hexValue;
+		info.summoned = !permanent;
+
+		// add newly created creature
+		pack.changedStacks.emplace_back(info.id, UnitChanges::EOperation::ADD);
+		info.save(pack.changedStacks.back().data);
+
+		// and remove corpse to prevent second raising or resurrection
+		pack.changedStacks.emplace_back(targetStack->unitId(), UnitChanges::EOperation::REMOVE);
+	}
+
+	if(!pack.changedStacks.empty())
+		server->apply(&pack);
+}
+
+bool DemonSummon::isValidTarget(const Mechanics * m, const battle::Unit * s) const
+{
+	if(!s->isDead())
+		return false;
+
+	if (s->isGhost())
+		return false;
+
+	auto creatureType = creature.toCreature(m->creatures());
+
+	if (s->getTotalHealth() < creatureType->getMaxHealth())
+		return false;
+
+	return m->isReceptive(s);
+}
+
+void DemonSummon::serializeJsonUnitEffect(JsonSerializeFormat & handler)
+{
+	handler.serializeId("id", creature, CreatureID());
+	handler.serializeBool("permanent", permanent, false);
+}
+
+}
+}
+
+VCMI_LIB_NAMESPACE_END

+ 44 - 0
lib/spells/effects/DemonSummon.h

@@ -0,0 +1,44 @@
+/*
+ * DemonSummon.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include "UnitEffect.h"
+#include "../../GameConstants.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+namespace spells
+{
+namespace effects
+{
+
+class DemonSummon : public UnitEffect
+{
+public:
+	DemonSummon();
+	virtual ~DemonSummon();
+
+	void apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const override;
+protected:
+	bool isValidTarget(const Mechanics * m, const battle::Unit * s) const override;
+
+	void serializeJsonUnitEffect(JsonSerializeFormat & handler) override final;
+
+private:
+	CreatureID creature;
+
+	bool permanent;
+};
+
+}
+}
+
+VCMI_LIB_NAMESPACE_END

+ 8 - 0
lib/spells/effects/Effect.h

@@ -51,19 +51,27 @@ public:
 	Effect();
 	virtual ~Effect();
 
+	// TODO: document me
 	virtual void adjustTargetTypes(std::vector<TargetType> & types) const = 0;
 
+	/// Generates list of hexes affected by spell, if spell were to cast at specified target
 	virtual void adjustAffectedHexes(std::set<BattleHex> & hexes, const Mechanics * m, const Target & spellTarget) const = 0;
 
+	/// Returns whether effect has any valid targets on the battlefield
 	virtual bool applicable(Problem & problem, const Mechanics * m) const;
+
+	/// Returns whether effect is valid and can be applied onto selected target
 	virtual bool applicable(Problem & problem, const Mechanics * m, const EffectTarget & target) const;
 
 	virtual void apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const = 0;
 
+	/// Processes input target and generates subset-result that contains only valid targets
 	virtual EffectTarget filterTarget(const Mechanics * m, const EffectTarget & target) const = 0;
 
+	// TODO: document me
 	virtual EffectTarget transformTarget(const Mechanics * m, const Target & aimPoint, const Target & spellTarget) const = 0;
 
+	/// Serializes (or deserializes) parameters of Effect
 	void serializeJson(JsonSerializeFormat & handler);
 
 	static std::shared_ptr<Effect> create(const Registry * registry, const std::string & type);

+ 3 - 3
lib/spells/effects/Heal.cpp

@@ -63,14 +63,14 @@ bool Heal::isValidTarget(const Mechanics * m, const battle::Unit * unit) const
 	if(!validInGenaral)
 		return false;
 
-	auto insuries = unit->getTotalHealth() - unit->getAvailableHealth();
+	auto injuries = unit->getTotalHealth() - unit->getAvailableHealth();
 
-	if(insuries == 0)
+	if(injuries == 0)
 		return false;
 
 	if(minFullUnits > 0)
 	{
-		auto hpGained = std::min(m->getEffectValue(), insuries);
+		auto hpGained = std::min(m->getEffectValue(), injuries);
 		if(hpGained < minFullUnits * unit->MaxHealth())
 			return false;
 	}

+ 1 - 54
server/CGameHandler.cpp

@@ -4472,7 +4472,6 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 	case EActionType::SHOOT: //shoot
 	case EActionType::CATAPULT: //catapult
 	case EActionType::STACK_HEAL: //healing with First Aid Tent
-	case EActionType::DAEMON_SUMMONING:
 	case EActionType::MONSTER_SPELL:
 
 		if (!stack)
@@ -5006,58 +5005,6 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 			}
 			break;
 		}
-		case EActionType::DAEMON_SUMMONING:
-			//TODO: From Strategija:
-			//Summon Demon is a level 2 spell.
-		{
-			if(target.size() < 1)
-			{
-				complain("Destination required for summon action.");
-				ok = false;
-				break;
-			}
-
-			const CStack * summoner = gs->curB->battleGetStackByID(ba.stackNumber);
-			const CStack * destStack = gs->curB->battleGetStackByPos(target.at(0).hexValue, false);
-
-			CreatureID summonedType(summoner->getBonusLocalFirst(Selector::type()(Bonus::DAEMON_SUMMONING))->subtype);//in case summoner can summon more than one type of monsters... scream!
-
-			ui64 risedHp = summoner->getCount() * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, summonedType.toEnum());
-			ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;
-
-			ui64 canRiseHp = std::min(targetHealth, risedHp);
-			ui32 canRiseAmount = static_cast<ui32>(canRiseHp / summonedType.toCreature()->MaxHealth());
-
-			battle::UnitInfo info;
-			info.id = gs->curB->battleNextUnitId();
-			info.count = std::min(canRiseAmount, destStack->baseAmount);
-			info.type = summonedType;
-			info.side = summoner->side;
-			info.position = gs->curB->getAvaliableHex(summonedType, summoner->side, destStack->getPosition());
-			info.summoned = false;
-
-			BattleUnitsChanged addUnits;
-			addUnits.changedStacks.emplace_back(info.id, UnitChanges::EOperation::ADD);
-			info.save(addUnits.changedStacks.back().data);
-
-			if(info.count > 0) //there's rare possibility single creature cannot rise desired type
-			{
-				auto wrapper = wrapAction(ba);
-
-				BattleUnitsChanged removeUnits;
-				removeUnits.changedStacks.emplace_back(destStack->unitId(), UnitChanges::EOperation::REMOVE);
-				sendAndApply(&removeUnits);
-				sendAndApply(&addUnits);
-
-				BattleSetStackProperty ssp;
-				ssp.stackID = ba.stackNumber;
-				ssp.which = BattleSetStackProperty::CASTS; //reduce number of casts
-				ssp.val = -1;
-				ssp.absolute = false;
-				sendAndApply(&ssp);
-			}
-			break;
-		}
 		case EActionType::MONSTER_SPELL:
 		{
 			auto wrapper = wrapAction(ba);
@@ -5089,7 +5036,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
 			break;
 		}
 	}
-	if(ba.actionType == EActionType::DAEMON_SUMMONING || ba.actionType == EActionType::WAIT || ba.actionType == EActionType::DEFEND
+	if(ba.actionType == EActionType::WAIT || ba.actionType == EActionType::DEFEND
 			|| ba.actionType == EActionType::SHOOT || ba.actionType == EActionType::MONSTER_SPELL)
 		handleDamageFromObstacle(stack);
 	if(ba.stackNumber == gs->curB->activeStack || battleResult.get()) //active stack has moved or battle has finished