瀏覽代碼

Hide battle log algorithm in spell classes.
* not finished, to be moved to json of splitted between mechanics classes

AlexVinS 10 年之前
父節點
當前提交
832d69ec11

+ 5 - 123
client/battle/CBattleInterface.cpp

@@ -1240,10 +1240,9 @@ void CBattleInterface::displayBattleFinished()
 void CBattleInterface::spellCast( const BattleSpellCast * sc )
 {
 	const SpellID spellID(sc->id);
-	const CSpell &spell = * spellID.toSpell();
-	const std::string & spellName = spell.name;
+	const CSpell & spell = * spellID.toSpell();
 
-	const std::string& castSoundPath = spell.getCastSound();
+	const std::string & castSoundPath = spell.getCastSound();
 
 	std::string casterName("Something");
 
@@ -1334,126 +1333,9 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 
 	//displaying message in console
 	std::vector<std::string> logLines;
-	bool customSpell = false;
-	if(sc->affectedCres.size() == 1)
-	{
-		const CStack * attackedStack = curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false);
-
-		const std::string attackedName = attackedStack->getName();
-		const std::string attackedNameSing = attackedStack->getCreature()->nameSing;
-		const std::string attackedNamePl = attackedStack->getCreature()->namePl;
-
-		if(sc->castedByHero)
-		{
-			const std::string fmt = CGI->generaltexth->allTexts[195];
-			logLines.push_back(boost::to_string(boost::format(fmt) % casterName % spellName % attackedNamePl));
-		}
-		else
-		{
-			auto getPluralFormat = [attackedStack](const int baseTextID) -> boost::format
-			{
-				return boost::format(CGI->generaltexth->allTexts[(attackedStack->count > 1 ? baseTextID+1 : baseTextID)]);
-			};
-
-			auto logSimple = [&logLines, getPluralFormat, attackedName](const int baseTextID)
-			{
-				boost::format fmt = getPluralFormat(baseTextID);
-				fmt % attackedName;
-				logLines.push_back(fmt.str());
-			};
-
-			auto logPlural = [&logLines, attackedNamePl](const int baseTextID)
-			{
-				boost::format fmt(CGI->generaltexth->allTexts[baseTextID]);
-				fmt % attackedNamePl;
-				logLines.push_back(fmt.str());
-			};
-
-			customSpell = true; //in most following cases text is custom
-			switch(sc->id)
-			{
-			case SpellID::STONE_GAZE:
-				logSimple(558);
-				break;
-			case SpellID::POISON:
-				logSimple(561);
-				break;
-			case SpellID::BIND:
-				logPlural(560);//Roots and vines bind the %s to the ground!
-				break;
-			case SpellID::DISEASE:
-				logSimple(553);
-				break;
-			case SpellID::PARALYZE:
-				logSimple(563);
-				break;
-			case SpellID::AGE:
-				{
-					boost::format text = getPluralFormat(551);
-					text % attackedName;
-					//The %s shrivel with age, and lose %d hit points."
-					TBonusListPtr bl = attackedStack->getBonuses(Selector::type(Bonus::STACK_HEALTH));
-					const int fullHP = bl->totalValue();
-					bl->remove_if(Selector::source(Bonus::SPELL_EFFECT, SpellID::AGE));
-					text % (fullHP - bl->totalValue());
-					logLines.push_back(text.str());
-				}
-				break;
-			case SpellID::THUNDERBOLT:
-				{
-					logPlural(367);
-					std::string text = CGI->generaltexth->allTexts[343].substr(1, CGI->generaltexth->allTexts[343].size() - 1); //Does %d points of damage.
-					boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay)); //no more text afterwards
-					logLines.push_back(text);
-				}
-				break;
-			case SpellID::DISPEL_HELPFUL_SPELLS:
-				logPlural(555);
-				break;
-			case SpellID::DEATH_STARE:
-				if (sc->dmgToDisplay)
-				{
-					std::string text;
-					if (sc->dmgToDisplay > 1)
-					{
-						text = CGI->generaltexth->allTexts[119]; //%d %s die under the terrible gaze of the %s.
-						boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay));
-						boost::algorithm::replace_first(text, "%s", attackedNamePl);
-					}
-					else
-					{
-						text = CGI->generaltexth->allTexts[118]; //One %s dies under the terrible gaze of the %s.
-						boost::algorithm::replace_first(text, "%s", attackedNameSing);
-					}
-					boost::algorithm::replace_first(text, "%s", casterName); //casting stack
-					logLines.push_back(text);
-				}
-				break;
-			default:
-				{
-					boost::format text(CGI->generaltexth->allTexts[565]); //The %s casts %s
-					text % casterName % spellName;
-					customSpell = false;
-					logLines.push_back(text.str());
-				}
-				break;
-			}
-		}
-	}
-	else
-	{
-		boost::format text(CGI->generaltexth->allTexts[196]);
-		text % casterName % spellName;
-		logLines.push_back(text.str());
-	}
-
-	if(sc->dmgToDisplay && !customSpell)
-	{
-		boost::format dmgInfo(CGI->generaltexth->allTexts[376]);
-		dmgInfo % spellName % sc->dmgToDisplay;
-		logLines.push_back(dmgInfo.str());
-	}
-
+	
+	spell.prepareBattleLog(curInt->cb.get(), sc, logLines);
+	
 	for(auto line : logLines)
 		console->addText(line);
 

+ 99 - 0
lib/spells/CDefaultSpellMechanics.cpp

@@ -15,6 +15,8 @@
 #include "../NetPacks.h"
 #include "../BattleState.h"
 
+#include "../CGeneralTextHandler.h"
+
 namespace SRSLPraserHelpers
 {
 	static int XYToHex(int x, int y)
@@ -367,6 +369,103 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 	}
 }
 
+void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet, 
+	const std::string & casterName, const CStack * attackedStack, bool & displayDamage) const
+{
+	const std::string attackedName = attackedStack->getName();
+	const std::string attackedNameSing = attackedStack->getCreature()->nameSing;
+	const std::string attackedNamePl = attackedStack->getCreature()->namePl;
+	
+	auto getPluralFormat = [attackedStack](const int baseTextID) -> boost::format
+	{
+		return boost::format(VLC->generaltexth->allTexts[(attackedStack->count > 1 ? baseTextID + 1 : baseTextID)]);
+	};
+
+	auto logSimple = [&logLines, getPluralFormat, attackedName](const int baseTextID)
+	{
+		boost::format fmt = getPluralFormat(baseTextID);
+		fmt % attackedName;
+		logLines.push_back(fmt.str());
+	};
+
+	auto logPlural = [&logLines, attackedNamePl](const int baseTextID)
+	{
+		boost::format fmt(VLC->generaltexth->allTexts[baseTextID]);
+		fmt % attackedNamePl;
+		logLines.push_back(fmt.str());
+	};
+
+	displayDamage = false; //in most following cases damage info text is custom
+	switch(owner->id)
+	{
+	case SpellID::STONE_GAZE:
+		logSimple(558);
+		break;
+	case SpellID::POISON:
+		logSimple(561);
+		break;
+	case SpellID::BIND:
+		logPlural(560);//Roots and vines bind the %s to the ground!
+		break;
+	case SpellID::DISEASE:
+		logSimple(553);
+		break;
+	case SpellID::PARALYZE:
+		logSimple(563);
+		break;
+	case SpellID::AGE:
+		{
+			boost::format text = getPluralFormat(551);
+			text % attackedName;
+			//The %s shrivel with age, and lose %d hit points."
+			TBonusListPtr bl = attackedStack->getBonuses(Selector::type(Bonus::STACK_HEALTH));
+			const int fullHP = bl->totalValue();
+			bl->remove_if(Selector::source(Bonus::SPELL_EFFECT, SpellID::AGE));
+			text % (fullHP - bl->totalValue());
+			logLines.push_back(text.str());
+		}
+		break;
+	case SpellID::THUNDERBOLT:
+		{
+			logPlural(367);
+			std::string text = VLC->generaltexth->allTexts[343].substr(1, VLC->generaltexth->allTexts[343].size() - 1); //Does %d points of damage.
+			boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(packet->dmgToDisplay)); //no more text afterwards
+			logLines.push_back(text);
+		}
+		break;
+	case SpellID::DISPEL_HELPFUL_SPELLS:
+		logPlural(555);
+		break;
+	case SpellID::DEATH_STARE:
+		if (packet->dmgToDisplay > 0)
+		{
+			std::string text;
+			if (packet->dmgToDisplay > 1)
+			{
+				text = VLC->generaltexth->allTexts[119]; //%d %s die under the terrible gaze of the %s.
+				boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(packet->dmgToDisplay));
+				boost::algorithm::replace_first(text, "%s", attackedNamePl);
+			}
+			else
+			{
+				text = VLC->generaltexth->allTexts[118]; //One %s dies under the terrible gaze of the %s.
+				boost::algorithm::replace_first(text, "%s", attackedNameSing);
+			}
+			boost::algorithm::replace_first(text, "%s", casterName); //casting stack
+			logLines.push_back(text);
+		}
+		break;
+	default:
+		{
+			boost::format text(VLC->generaltexth->allTexts[565]); //The %s casts %s
+			text % casterName % owner->name;
+			displayDamage = true;
+			logLines.push_back(text.str());
+		}
+		break;
+	}	
+}
+
 int DefaultSpellMechanics::calculateDuration(const CGHeroInstance * caster, int usedSpellPower) const
 {
 	if(!caster)

+ 2 - 0
lib/spells/CDefaultSpellMechanics.h

@@ -48,6 +48,8 @@ public:
 	bool adventureCast(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override final;
 	void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const override;
 
+	void battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet, 
+		const std::string & casterName, const CStack * attackedStack, bool & displayDamage) const override;	
 protected:
 	virtual void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const;
 

+ 54 - 0
lib/spells/CSpellHandler.cpp

@@ -26,6 +26,7 @@
 #include "../mapObjects/CGHeroInstance.h"
 #include "../BattleState.h"
 #include "../CBattleCallback.h"
+#include "../CGameState.h"
 
 #include "ISpellMechanics.h"
 
@@ -531,6 +532,59 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneByStack(const CGHeroInstanc
 	return ESpellCastProblem::OK;
 }
 
+void CSpell::prepareBattleLog(const CBattleInfoCallback * cb,  const BattleSpellCast * packet, std::vector<std::string> & logLines) const
+{
+	bool displayDamage = true;
+	
+	std::string casterName("Something"); //todo: localize
+	
+	if(packet->castedByHero)
+		casterName = cb->battleGetHeroInfo(packet->side).name;
+
+	{
+		const auto casterStackID = packet->casterStack;
+
+		if(casterStackID > 0)
+		{
+			const CStack * casterStack = cb->battleGetStackByID(casterStackID);
+			if(casterStack != nullptr)
+				casterName = casterStack->type->namePl;
+		}
+	}
+	
+	if(packet->affectedCres.size() == 1)
+	{
+		const CStack * attackedStack = cb->battleGetStackByID(*packet->affectedCres.begin(), false);
+		
+		const std::string attackedNamePl = attackedStack->getCreature()->namePl;
+		
+		if(packet->castedByHero)
+		{
+			const std::string fmt = VLC->generaltexth->allTexts[195];
+			logLines.push_back(boost::to_string(boost::format(fmt) % casterName % this->name % attackedNamePl));
+		}
+		else
+		{
+			mechanics->battleLogSingleTarget(logLines, packet, casterName, attackedStack, displayDamage);		
+		}
+	}
+	else
+	{
+		boost::format text(VLC->generaltexth->allTexts[196]);
+		text % casterName % this->name;
+		logLines.push_back(text.str());		
+	}
+	
+	
+	if(packet->dmgToDisplay > 0 && displayDamage)
+	{
+		boost::format dmgInfo(VLC->generaltexth->allTexts[376]);
+		dmgInfo % this->name % packet->dmgToDisplay;
+		logLines.push_back(dmgInfo.str());
+	}
+}
+
+
 void CSpell::setIsOffensive(const bool val)
 {
 	isOffensive = val;

+ 5 - 0
lib/spells/CSpellHandler.h

@@ -319,6 +319,11 @@ public:
 	///implementation of BattleSpellCast applying
 	void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const;
 
+public:
+	///Client logic.
+	
+	void prepareBattleLog(const CBattleInfoCallback * cb, const BattleSpellCast * packet, std::vector<std::string> & logLines) const;
+
 private:
 	void setIsOffensive(const bool val);
 	void setIsRising(const bool val);

+ 3 - 0
lib/spells/ISpellMechanics.h

@@ -47,6 +47,9 @@ public:
 	virtual bool adventureCast(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const = 0;
 	virtual void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const = 0;
 
+	virtual void battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet, 
+		const std::string & casterName, const CStack * attackedStack, bool & displayDamage) const = 0;
+	
 	static ISpellMechanics * createMechanics(CSpell * s);
 protected:
 	CSpell * owner;