Forráskód Böngészése

WIP on SpellCastContext

AlexVinS 9 éve
szülő
commit
18fc94d709

+ 6 - 6
lib/spells/BattleSpellMechanics.cpp

@@ -62,9 +62,9 @@ void AntimagicMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast
 }
 
 ///ChainLightningMechanics
-std::set<const CStack *> ChainLightningMechanics::getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const
+std::vector<const CStack *> ChainLightningMechanics::getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const
 {
-	std::set<const CStack* > attackedCres;
+	std::vector<const CStack *> res;
 
 	std::set<BattleHex> possibleHexes;
 	for(auto stack : cb->battleGetAllStacks())
@@ -85,17 +85,17 @@ std::set<const CStack *> ChainLightningMechanics::getAffectedStacks(const CBattl
 		auto stack = cb->battleGetStackByPos(lightningHex, true);
 		if(!stack)
 			break;
-		attackedCres.insert (stack);
+		res.push_back(stack);
 		for(auto hex : stack->getHexes())
 		{
-			possibleHexes.erase(hex); //can't hit same place twice
+			possibleHexes.erase(hex); //can't hit same stack twice
 		}
 		if(possibleHexes.empty()) //not enough targets
 			break;
-		lightningHex = BattleHex::getClosestTile(stack->attackerOwned, ctx.destination, possibleHexes);
+		lightningHex = BattleHex::getClosestTile(stack->attackerOwned, lightningHex, possibleHexes);
 	}
 
-	return attackedCres;
+	return res;
 }
 
 ///CloneMechanics

+ 1 - 1
lib/spells/BattleSpellMechanics.h

@@ -44,7 +44,7 @@ class DLL_LINKAGE ChainLightningMechanics : public DefaultSpellMechanics
 {
 public:
 	ChainLightningMechanics(CSpell * s): DefaultSpellMechanics(s){};
-	std::set<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const override;
+	std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const override;
 };
 
 class DLL_LINKAGE CloneMechanics : public DefaultSpellMechanics

+ 64 - 59
lib/spells/CDefaultSpellMechanics.cpp

@@ -119,9 +119,15 @@ namespace SRSLPraserHelpers
 }
 
 SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters):
-	mechanics(mechanics_), attackedCres(), sc(), si()
+	mechanics(mechanics_), attackedCres(), sc(), si(), mode(parameters.mode)
 {
 	prepareBattleCast(parameters);
+	logGlobal->debugStream() << "Started spell cast. Spell: " << mechanics->owner->name << "; mode:" << mode;
+}
+
+SpellCastContext::~SpellCastContext()
+{
+	logGlobal->debugStream() << "Finished spell cast. Spell: " << mechanics->owner->name << "; mode:" << mode;
 }
 
 void SpellCastContext::prepareBattleCast(const BattleSpellCastParameters & parameters)
@@ -182,16 +188,48 @@ void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCa
 	}
 }
 
-void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
+void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const
 {
-	logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode:"<<parameters.mode;
-
 	if(nullptr == parameters.caster)
 	{
 		env->complain("No spell-caster provided.");
 		return;
 	}
 
+	std::vector <const CStack*> reflected;//for magic mirror
+
+	castNormal(env, parameters, reflected);
+
+	//Magic Mirror effect
+	for(auto & attackedCre : reflected)
+	{
+		TStacks mirrorTargets = parameters.cb->battleGetStacksIf([this, parameters](const CStack * battleStack)
+		{
+			//Get all enemy stacks. Magic mirror can reflect to immune creature (with no effect)
+			return battleStack->owner == parameters.casterColor && battleStack->isValidTarget(false);
+		});
+
+		if(!mirrorTargets.empty())
+		{
+			int targetHex = (*RandomGeneratorUtil::nextItem(mirrorTargets, env->getRandomGenerator()))->position;
+
+			BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
+			mirrorParameters.spellLvl = 0;
+			mirrorParameters.aimToHex(targetHex);
+			mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
+			mirrorParameters.selectedStack = nullptr;
+			mirrorParameters.spellLvl = parameters.spellLvl;
+			mirrorParameters.effectLevel = parameters.effectLevel;
+			mirrorParameters.effectPower = parameters.effectPower;
+			mirrorParameters.effectValue = parameters.effectValue;
+			mirrorParameters.enchantPower = parameters.enchantPower;
+			castMagicMirror(env, mirrorParameters);
+		}
+	}
+}
+
+void DefaultSpellMechanics::castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const
+{
 	SpellCastContext ctx(this, parameters);
 
 	//check it there is opponent hero
@@ -221,12 +259,11 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 	}
 	logGlobal->debugStream() << "spellCost: " << spellCost;
 
-	auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex());
-	std::copy(creatures.begin(), creatures.end(), std::back_inserter(ctx.attackedCres));
+	ctx.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex());
 
 	logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks";
 
-	std::vector <const CStack*> reflected;//for magic mirror
+
 	//checking if creatures resist
 	handleResistance(env, ctx.attackedCres, ctx.sc);
 	//it is actual spell and can be reflected to single target, no recurrence
@@ -293,35 +330,25 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 
 	if(!ctx.si.stacks.empty()) //after spellcast info shows
 		env->sendAndApply(&ctx.si);
+}
 
+void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const
+{
+	SpellCastContext ctx(this, parameters);
 
-	logGlobal->debugStream() << "Finished spell cast. Spell: "<<owner->name<<"; mode:"<<parameters.mode;
-	//Magic Mirror effect
-	for(auto & attackedCre : reflected)
-	{
-		TStacks mirrorTargets = parameters.cb->battleGetStacksIf([this, parameters](const CStack * battleStack)
-		{
-			//Get all enemy stacks. Magic mirror can reflect to immune creature (with no effect)
-			return battleStack->owner == parameters.casterColor && battleStack->isValidTarget(false);
-		});
+	//calculating affected creatures for all spells
+	ctx.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex());
 
-		if(!mirrorTargets.empty())
-		{
-			int targetHex = (*RandomGeneratorUtil::nextItem(mirrorTargets, env->getRandomGenerator()))->position;
+	logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks";
 
-			BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
-			mirrorParameters.spellLvl = 0;
-			mirrorParameters.aimToHex(targetHex);
-			mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
-			mirrorParameters.selectedStack = nullptr;
-			mirrorParameters.spellLvl = parameters.spellLvl;
-			mirrorParameters.effectLevel = parameters.effectLevel;
-			mirrorParameters.effectPower = parameters.effectPower;
-			mirrorParameters.effectValue = parameters.effectValue;
-			mirrorParameters.enchantPower = parameters.enchantPower;
-			castMagicMirror(env, mirrorParameters);
-		}
-	}
+	handleResistance(env, ctx.attackedCres, ctx.sc);
+
+	applyBattleEffects(env, parameters, ctx);
+
+	ctx.sendCastPacket(env);
+
+	if(!ctx.si.stacks.empty()) //after spellcast info shows
+		env->sendAndApply(&ctx.si);
 }
 
 void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet,
@@ -610,7 +637,7 @@ std::vector<BattleHex> DefaultSpellMechanics::rangeInHexes(BattleHex centralHex,
 	return ret;
 }
 
-std::set<const CStack *> DefaultSpellMechanics::getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const
+std::vector<const CStack *> DefaultSpellMechanics::getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const
 {
 	std::set<const CStack* > attackedCres;//std::set to exclude multiple occurrences of two hex creatures
 
@@ -678,7 +705,10 @@ std::set<const CStack *> DefaultSpellMechanics::getAffectedStacks(const CBattleI
 		}
 	}
 
-	return attackedCres;
+	std::vector<const CStack *> res;
+	std::copy(attackedCres.begin(), attackedCres.end(), std::back_inserter(res));
+
+	return res;
 }
 
 ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const
@@ -721,31 +751,6 @@ void DefaultSpellMechanics::doDispell(BattleInfo * battle, const BattleSpellCast
 	}
 }
 
-void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters) const
-{
-	logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode: MAGIC_MIRROR";
-
-	BattleHex destination = parameters.getFirstDestinationHex();
-	SpellCastContext ctx(this, parameters);
-
-	//calculating affected creatures for all spells
-	auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, destination);
-	std::copy(creatures.begin(), creatures.end(), std::back_inserter(ctx.attackedCres));
-
-	logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks";
-
-	handleResistance(env, ctx.attackedCres, ctx.sc);
-
-	applyBattleEffects(env, parameters, ctx);
-
-	ctx.sendCastPacket(env);
-
-	if(!ctx.si.stacks.empty()) //after spellcast info shows
-		env->sendAndApply(&ctx.si);
-
-	logGlobal->debugStream() << "Finished spell cast. Spell: "<<owner->name<<"; mode: MAGIC_MIRROR";
-}
-
 void DefaultSpellMechanics::handleResistance(const SpellCastEnvironment * env, std::vector<const CStack* >& attackedCres, BattleSpellCast& sc) const
 {
 	//checking if creatures resist

+ 6 - 3
lib/spells/CDefaultSpellMechanics.h

@@ -22,8 +22,10 @@ public:
 	std::vector<const CStack *> attackedCres;//must be vector, as in Chain Lightning order matters
 	BattleSpellCast sc;//todo: make private
 	StacksInjured si;
+	ECastingMode::ECastingMode mode;
 
 	SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters);
+	virtual ~SpellCastContext();
 
 	void addDamageToDisplay(const si32 value);
 	void setDamageToDisplay(const si32 value);
@@ -40,7 +42,7 @@ public:
 	DefaultSpellMechanics(CSpell * s): ISpellMechanics(s){};
 
 	std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const override;
-	std::set<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const override;
+	std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const override;
 
 	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const override;
 	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
@@ -49,7 +51,7 @@ public:
 
 	virtual void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override;
 
-	void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const override final;
+	void battleCast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const override final;
 
 	void battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet,
 		const std::string & casterName, const CStack * attackedStack, bool & displayDamage) const override;
@@ -60,7 +62,8 @@ protected:
 
 	void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
 private:
-	void castMagicMirror(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const;
+	void castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const;
+	void castMagicMirror(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const;
 	void handleResistance(const SpellCastEnvironment * env, std::vector<const CStack*> & attackedCres, BattleSpellCast & sc) const;
 
 	friend class SpellCastContext;

+ 3 - 3
lib/spells/CSpellHandler.cpp

@@ -119,7 +119,7 @@ bool CSpell::adventureCast(const SpellCastEnvironment * env, AdventureSpellCastP
 	return adventureMechanics->adventureCast(env, parameters);
 }
 
-void CSpell::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
+void CSpell::battleCast(const SpellCastEnvironment * env,  const BattleSpellCastParameters & parameters) const
 {
 	assert(env);
 	if(parameters.destinations.size()<1)
@@ -211,11 +211,11 @@ std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl,
 	return mechanics->rangeInHexes(centralHex,schoolLvl,side,outDroppedHexes);
 }
 
-std::set<const CStack *> CSpell::getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
+std::vector<const CStack *> CSpell::getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
 {
 	SpellTargetingContext ctx(this, mode, caster, spellLvl, destination);
 
-	std::set<const CStack* > attackedCres = mechanics->getAffectedStacks(cb, ctx);
+	std::vector<const CStack *> attackedCres = mechanics->getAffectedStacks(cb, ctx);
 
 	//now handle immunities
 	auto predicate = [&, this](const CStack * s)->bool

+ 2 - 2
lib/spells/CSpellHandler.h

@@ -218,7 +218,7 @@ public:
 	ui32 calculateDamage(const ISpellCaster * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const;
 
 	///selects from allStacks actually affected stacks
-	std::set<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const;
+	std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const;
 
 	si32 getCost(const int skillLevel) const;
 
@@ -279,7 +279,7 @@ public:
 	///May be executed on client side by (future) non-cheat-proof scripts.
 
 	bool adventureCast(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const;
-	void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const;
+	void battleCast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const;
 
 public:
 	///Client-server logic. Has direct write access to GameState.

+ 2 - 2
lib/spells/ISpellMechanics.h

@@ -97,7 +97,7 @@ public:
 	virtual ~ISpellMechanics(){};
 
 	virtual std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const = 0;
-	virtual std::set<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const = 0;
+	virtual std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const = 0;
 
 	virtual ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const = 0;
 
@@ -106,7 +106,7 @@ public:
 	virtual ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const = 0;
 
 	virtual void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const = 0;
-	virtual void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const = 0;
+	virtual void battleCast(const SpellCastEnvironment * env, const 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;

+ 1 - 1
server/CGameHandler.cpp

@@ -842,7 +842,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
 
 		//TODO: should spell override creature`s projectile?
 
-		std::set<const CStack*> attackedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att, bonus->val, targetHex);
+		auto attackedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att, bonus->val, targetHex);
 
 		//TODO: get exact attacked hex for defender