From b31ed0e4ea3a19c78cbd3e5134c4b77643965ca2 Mon Sep 17 00:00:00 2001
From: AlexVinS <alexvins@users.noreply.github.com>
Date: Wed, 26 Nov 2014 13:30:55 +0300
Subject: [PATCH] Use SetMana packet in battle

---
 lib/NetPacks.h          |  8 ++++----
 lib/NetPacksLib.cpp     | 20 ++++++++++----------
 lib/SpellMechanics.cpp  | 30 +++++++++++++++++++++++++++---
 server/CGameHandler.cpp |  5 ++++-
 4 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/lib/NetPacks.h b/lib/NetPacks.h
index a931983a1..b82e6188a 100644
--- a/lib/NetPacks.h
+++ b/lib/NetPacks.h
@@ -274,17 +274,18 @@ struct ChangeSpells : public CPackForClient //109
 
 struct SetMana : public CPackForClient //110
 {
-	SetMana(){type = 110;};
+	SetMana(){type = 110;absolute=true;};
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 
 	ObjectInstanceID hid;
 	si32 val;
+	bool absolute;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & val & hid;
+		h & val & hid & absolute;
 	}
 };
 
@@ -1447,7 +1448,6 @@ struct BattleSpellCast : public CPackForClient//3009
 	ui8 side; //which hero did cast spell: 0 - attacker, 1 - defender
 	ui32 id; //id of spell
 	ui8 skill; //caster's skill level
-	ui8 spellCost;
 	ui8 manaGained; //mana channeling ability
 	BattleHex tile; //destination tile (may not be set in some global/mass spells
 	std::vector<ui32> resisted; //ids of creatures that resisted this spell
@@ -1456,7 +1456,7 @@ struct BattleSpellCast : public CPackForClient//3009
 	bool castedByHero; //if true - spell has been casted by hero, otherwise by a creature
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & dmgToDisplay & side & id & skill & spellCost & manaGained & tile & resisted & affectedCres & attackerType & castedByHero;
+		h & dmgToDisplay & side & id & skill & tile & resisted & affectedCres & attackerType & castedByHero;
 	}
 };
 
diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp
index 60538d031..c6c6a992c 100644
--- a/lib/NetPacksLib.cpp
+++ b/lib/NetPacksLib.cpp
@@ -184,9 +184,16 @@ DLL_LINKAGE void ChangeSpells::applyGs( CGameState *gs )
 
 DLL_LINKAGE void SetMana::applyGs( CGameState *gs )
 {
-	CGHeroInstance *hero = gs->getHero(hid);
-	vstd::amax(val, 0); //not less than 0
-	hero->mana = val;
+	CGHeroInstance * hero = gs->getHero(hid);
+	
+	assert(hero);
+	
+	if(absolute)
+		hero->mana = val;		
+	else
+		hero->mana += val;
+
+	vstd::amax(hero->mana, 0); //not less than 0
 }
 
 DLL_LINKAGE void SetMovePoints::applyGs( CGameState *gs )
@@ -1330,13 +1337,6 @@ DLL_LINKAGE void BattleSpellCast::applyGs( CGameState *gs )
 	assert(gs->curB);
 	if (castedByHero)
 	{
-		CGHeroInstance * h = gs->curB->battleGetFightingHero(side);
-		CGHeroInstance * enemy = gs->curB->battleGetFightingHero(!side);
-
-		h->mana -= spellCost;
-			vstd::amax(h->mana, 0);
-		if (enemy && manaGained)
-			enemy->mana += manaGained;
 		if (side < 2)
 		{
 			gs->curB->sides[side].castSpellsCount++;
diff --git a/lib/SpellMechanics.cpp b/lib/SpellMechanics.cpp
index 66dd9700a..01ba77432 100644
--- a/lib/SpellMechanics.cpp
+++ b/lib/SpellMechanics.cpp
@@ -368,12 +368,13 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 	sc.castedByHero = nullptr != parameters.caster;
 	sc.attackerType = (parameters.casterStack ? parameters.casterStack->type->idNumber : CreatureID(CreatureID::NONE));
 	sc.manaGained = 0;
-	sc.spellCost = 0;	
+	
+	int spellCost = 0;	
 	
 	//calculate spell cost
 	if(parameters.caster) 
 	{
-		sc.spellCost = parameters.cb->battleGetSpellCost(owner, parameters.caster);
+		spellCost = parameters.cb->battleGetSpellCost(owner, parameters.caster);
 
 		if(parameters.secHero && parameters.mode == ECastingMode::HERO_CASTING) //handle mana channel
 		{
@@ -385,7 +386,7 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 					vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING));
 				}
 			}
-			sc.manaGained = (manaChannel * sc.spellCost) / 100;
+			sc.manaGained = (manaChannel * spellCost) / 100;
 		}
 	}	
 	
@@ -423,6 +424,29 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 	applyBattleEffects(env, parameters, ctx);
 	
 	env->sendAndApply(&sc);
+	
+
+	//spend mana
+	if(parameters.caster) 
+	{
+		SetMana sm;
+		sm.absolute = false;
+		
+		sm.hid = parameters.caster->id;
+		sm.val = -spellCost;
+		
+		env->sendAndApply(&sm);
+		
+		if(sc.manaGained > 0)
+		{
+			assert(parameters.secHero);
+			
+			sm.hid = parameters.secHero->id;
+			sm.val = sc.manaGained;
+			env->sendAndApply(&sm);
+		}		
+	}
+	
 	if(!si.stacks.empty()) //after spellcast info shows
 		env->sendAndApply(&si);
 	
diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp
index b731ae897..7363af610 100644
--- a/server/CGameHandler.cpp
+++ b/server/CGameHandler.cpp
@@ -2045,6 +2045,7 @@ void CGameHandler::setManaPoints( ObjectInstanceID hid, int val )
 	SetMana sm;
 	sm.hid = hid;
 	sm.val = val;
+	sm.absolute = true;
 	sendAndApply(&sm);
 }
 
@@ -3830,6 +3831,7 @@ void CGameHandler::playerMessage( PlayerColor player, const std::string &message
 
 		//give mana
 		sm.val = 999;
+		sm.absolute = true;
 
 		if(!h->hasSpellbook()) //hero doesn't have spellbook
 			giveHeroNewArtifact(h, VLC->arth->artifacts.at(0), ArtifactPosition::SPELLBOOK); //give spellbook
@@ -5146,7 +5148,8 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int
 
 	SetMana sm;
 	sm.hid = h->id;
-	sm.val = h->mana - cost;
+	sm.absolute = false;
+	sm.val = -cost;
 	sendAndApply(&sm);
 
 	return true;