Prechádzať zdrojové kódy

Use BattleSpellCastParameters for spell parameters override

AlexVinS 10 rokov pred
rodič
commit
e454649886

+ 8 - 8
lib/spells/BattleSpellMechanics.cpp

@@ -17,7 +17,7 @@
 ///HealingSpellMechanics
 void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters, SpellCastContext& ctx) const
 {
-	EHealLevel healLevel = getHealLevel(ctx.effectLevel);
+	EHealLevel healLevel = getHealLevel(parameters.effectLevel);
 	int hpGained = calculateHealedHP(env, parameters, ctx);
 	StacksHealedOrResurrected shr;
 	shr.lifeDrain = false;
@@ -39,9 +39,9 @@ void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment* env,
 
 int HealingSpellMechanics::calculateHealedHP(const SpellCastEnvironment* env, const BattleSpellCastParameters& parameters, SpellCastContext& ctx) const
 {
-	if(ctx.effectValue != 0)
-		return ctx.effectValue; //Archangel
-	return owner->calculateRawEffectValue(ctx.effectLevel, ctx.effectPower); //???
+	if(parameters.effectValue != 0)
+		return parameters.effectValue; //Archangel
+	return owner->calculateRawEffectValue(parameters.effectLevel, parameters.effectPower); //???
 }
 
 ///AntimagicMechanics
@@ -390,8 +390,8 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, Bat
 		obstacle->pos = pos;
 		obstacle->casterSide = parameters.casterSide;
 		obstacle->ID = owner->id;
-		obstacle->spellLevel = parameters.spellLvl;
-		obstacle->casterSpellPower = ctx.effectPower;
+		obstacle->spellLevel = parameters.effectLevel;
+		obstacle->casterSpellPower = parameters.effectPower;
 		obstacle->uniqueID = obstacleIdToGive++;
 
 		BattleObstaclePlaced bop;
@@ -569,7 +569,7 @@ int SacrificeMechanics::calculateHealedHP(const SpellCastEnvironment* env, const
 	if(nullptr == parameters.selectedStack)
 		env->complain("No stack to sacrifice.");
 	else
-		res = (ctx.effectPower + parameters.selectedStack->MaxHealth() + owner->getPower(ctx.effectLevel)) * parameters.selectedStack->count;
+		res = (parameters.effectPower + parameters.selectedStack->MaxHealth() + owner->getPower(parameters.effectLevel)) * parameters.selectedStack->count;
 	return res;
 }
 
@@ -624,7 +624,7 @@ void SummonMechanics::applyBattleEffects(const SpellCastEnvironment * env, Battl
 	//TODO stack casting -> probably power will be zero; set the proper number of creatures manually
 	int percentBonus = parameters.casterHero ? parameters.casterHero->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, owner->id.toEnum()) : 0;
 
-	bsa.amount = ctx.effectPower
+	bsa.amount = parameters.effectPower
 		* owner->getPower(parameters.spellLvl)
 		* (100 + percentBonus) / 100.0; //new feature - percentage bonus
 	if(bsa.amount)

+ 40 - 50
lib/spells/CDefaultSpellMechanics.cpp

@@ -223,7 +223,38 @@ ESpellCastResult DefaultSpellMechanics::applyAdventureEffects(const SpellCastEnv
 
 void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
 {
-	logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode:"<<parameters.mode<<"; level: "<<parameters.spellLvl<<"; SP: "<<parameters.usedSpellPower;
+	logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode:"<<parameters.mode<<"; level: "<<parameters.spellLvl;
+
+
+	parameters.effectLevel = calculateEffectLevel(parameters);	
+	
+	if(parameters.casterStack)
+	{
+		if(parameters.enchantPower == 0)
+			parameters.enchantPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_ENCHANT_POWER);;
+		if(parameters.enchantPower == 0)
+			parameters.enchantPower = 3; //default for creatures
+		//Fairy Dragon, etc.	
+		int effectPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * parameters.casterStack->count / 100;
+		if(parameters.effectPower == 0)
+			parameters.effectPower = effectPower;
+		//Archangel, etc 
+		int unitSpellPower = parameters.casterStack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, owner->id.toEnum());
+		if(parameters.effectValue == 0)
+			parameters.effectValue = parameters.casterStack->count * unitSpellPower; 						
+	}
+	else if (parameters.casterHero)
+	{
+		if(parameters.enchantPower == 0)
+			parameters.enchantPower = parameters.casterHero->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + parameters.casterHero->valOfBonuses(Bonus::SPELL_DURATION);	
+		if(parameters.effectPower == 0)
+			parameters.effectPower = parameters.casterHero->getPrimSkillLevel(PrimarySkill::SPELL_POWER);
+	}
+	else
+	{
+		env->complain("No spell-caster provided.");
+		return;		
+	}
 
 	BattleSpellCast sc;
 	prepareBattleCast(parameters, sc);
@@ -299,37 +330,13 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 
 	StacksInjured si;
 	SpellCastContext ctx(attackedCres, sc, si);
-	ctx.effectLevel = calculateEffectLevel(parameters);
-	ctx.effectPower = parameters.usedSpellPower;
-	ctx.enchantPower = parameters.usedSpellPower;
-	ctx.effectValue = 0;
+
+
 	if(parameters.casterStack)
 		ctx.caster = parameters.casterStack;
 	else if(parameters.casterHero)
 		ctx.caster = parameters.casterHero;
-	else if(parameters.mode == ECastingMode::HERO_CASTING)
-		ctx.caster = parameters.cb->battleGetFightingHero(parameters.casterSide);
 	
-	if(ctx.caster == nullptr)
-	{
-		env->complain("No spell-caster provided.");
-		return;
-	}
-
-	if(parameters.casterStack)
-	{
-		auto enchantPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_ENCHANT_POWER);
-		if(ctx.enchantPower == 0)
-			ctx.enchantPower = enchantPower;
-		//Fairy Dragon, etc.	
-		int effectPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * parameters.casterStack->count / 100;
-		if(ctx.effectPower == 0)
-			ctx.effectPower = effectPower;
-		//Archangel, etc 
-		int unitSpellPower = parameters.casterStack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, owner->id.toEnum());
-		if(unitSpellPower != 0)
-			ctx.effectValue = parameters.casterStack->count * unitSpellPower; 						
-	}
 	applyBattleEffects(env, parameters, ctx);
 
 	env->sendAndApply(&sc);
@@ -396,7 +403,7 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
 			mirrorParameters.casterStack = (attackedCre);
 			mirrorParameters.selectedStack = nullptr;
 
-			castMagicMirror(env, mirrorParameters, ctx);
+			castMagicMirror(env, mirrorParameters);
 		}
 	}
 }
@@ -498,19 +505,6 @@ void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & log
 	}	
 }
 
-int DefaultSpellMechanics::calculateDuration(const CGHeroInstance * caster, int usedSpellPower) const
-{
-	if(caster == nullptr)
-	{
-		if (!usedSpellPower)
-			return 3; //default duration of all creature spells
-		else
-			return usedSpellPower; //use creature spell power			
-	}
-	else
-		return caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + caster->valOfBonuses(Bonus::SPELL_DURATION);
-}
-
 int DefaultSpellMechanics::calculateEffectLevel(const BattleSpellCastParameters& parameters) const
 {
 	int effectLevel = parameters.spellLvl;
@@ -530,7 +524,7 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env,
 	//applying effects
 	if(owner->isOffensiveSpell())
 	{
-		int spellDamage = ctx.effectValue;
+		int spellDamage = parameters.effectValue;
 		
 		int chainLightningModifier = 0;
 		for(auto & attackedCre : ctx.attackedCres)
@@ -539,7 +533,7 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env,
 			if(spellDamage != 0)
 				bsa.damageAmount = owner->adjustRawDamage(ctx.caster, attackedCre, spellDamage) >> chainLightningModifier;
 			else
-				bsa.damageAmount = owner->calculateDamage(ctx.caster, attackedCre, ctx.effectLevel, ctx.effectPower) >> chainLightningModifier;
+				bsa.damageAmount = owner->calculateDamage(ctx.caster, attackedCre, parameters.effectLevel, parameters.effectPower) >> chainLightningModifier;
 
 			ctx.sc.dmgToDisplay += bsa.damageAmount;
 
@@ -560,12 +554,12 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env,
 	{
 		SetStackEffect sse;
 		//get default spell duration (spell power with bonuses for heroes)
-		int duration = calculateDuration(parameters.casterHero, ctx.enchantPower);
+		int duration = parameters.enchantPower;
 		//generate actual stack bonuses
 		{
 			int maxDuration = 0;
 			std::vector<Bonus> tmp;
-			owner->getEffects(tmp, ctx.effectLevel);
+			owner->getEffects(tmp, parameters.effectLevel);
 			for(Bonus& b : tmp)
 			{
 				//use configured duration if present
@@ -810,7 +804,7 @@ void DefaultSpellMechanics::doDispell(BattleInfo * battle, const BattleSpellCast
 	}	
 }
 
-void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters, const SpellCastContext& originalContext) const
+void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters) const
 {
 	logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode: MAGIC_MIRROR";
 	if(parameters.mode != ECastingMode::MAGIC_MIRROR)
@@ -845,10 +839,6 @@ void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, Bat
 	
 	StacksInjured si;
 	SpellCastContext ctx(attackedCres, sc, si);
-	ctx.effectLevel = originalContext.effectLevel;
-	ctx.effectPower = originalContext.effectPower;
-	ctx.enchantPower = originalContext.enchantPower;
-	ctx.effectValue = originalContext.effectValue;
 	ctx.caster = parameters.casterStack;
 	applyBattleEffects(env, parameters, ctx);
 

+ 3 - 12
lib/spells/CDefaultSpellMechanics.h

@@ -19,21 +19,13 @@ class StacksInjured;
 struct SpellCastContext
 {
 	SpellCastContext(std::vector<const CStack *> & attackedCres, BattleSpellCast & sc, StacksInjured & si):
-		attackedCres(attackedCres), sc(sc), si(si), 
-		effectLevel(0),effectPower(0),enchantPower(0),effectValue(0)		
+		attackedCres(attackedCres), sc(sc), si(si)	
 	{
 	};
 	std::vector<const CStack *> & attackedCres;
 	BattleSpellCast & sc;
 	StacksInjured & si;
-	///spell school level to use for effects
-	int effectLevel;
-	///actual spell-power affecting effect values
-	int effectPower;
-	///actual spell-power affecting effect duration	
-	int enchantPower;
-	///for FairyDragon-like casting, if !=0 ignores effectPower
-	int effectValue;
+
 	///stack or hero
 	const ISpellCaster * caster;
 };
@@ -66,7 +58,6 @@ public:
 protected:
 	virtual void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const;
 
-	virtual int calculateDuration(const CGHeroInstance * caster, int usedSpellPower) const;
 	int calculateEffectLevel(const BattleSpellCastParameters & parameters) const;
 	
 	///actual adventure cast implementation
@@ -74,7 +65,7 @@ protected:
 	
 	void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
 private:
-	void castMagicMirror(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, const SpellCastContext & originalContext) const;
+	void castMagicMirror(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const;
 	void handleResistance(const SpellCastEnvironment * env, std::vector<const CStack*> & attackedCres, BattleSpellCast & sc) const;
 	void prepareBattleCast(const BattleSpellCastParameters & parameters, BattleSpellCast & sc) const;
 };

+ 5 - 4
lib/spells/CreatureSpellMechanics.cpp

@@ -18,15 +18,16 @@
 ///AcidBreathDamageMechanics
 void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
 {
+	//todo: this should be effectValue
 	//calculating dmg to display
-	ctx.sc.dmgToDisplay = ctx.effectPower;
+	ctx.sc.dmgToDisplay = parameters.effectPower;
 
 	for(auto & attackedCre : ctx.attackedCres) //no immunities
 	{
 		BattleStackAttacked bsa;
 		bsa.flags |= BattleStackAttacked::SPELL_EFFECT;
 		bsa.spellID = owner->id;
-		bsa.damageAmount = ctx.effectPower; //damage times the number of attackers
+		bsa.damageAmount = parameters.effectPower; //damage times the number of attackers
 		bsa.stackAttacked = (attackedCre)->ID;
 		bsa.attackerID = -1;
 		(attackedCre)->prepareAttacked(bsa, env->getRandomGenerator());
@@ -38,7 +39,7 @@ void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment *
 void DeathStareMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
 {
 	//calculating dmg to display
-	ctx.sc.dmgToDisplay = ctx.effectPower;
+	ctx.sc.dmgToDisplay = parameters.effectPower;
 	if(!ctx.attackedCres.empty())
 		vstd::amin(ctx.sc.dmgToDisplay, (*ctx.attackedCres.begin())->count); //stack is already reduced after attack
 
@@ -47,7 +48,7 @@ void DeathStareMechanics::applyBattleEffects(const SpellCastEnvironment * env, B
 		BattleStackAttacked bsa;
 		bsa.flags |= BattleStackAttacked::SPELL_EFFECT;
 		bsa.spellID = owner->id;
-		bsa.damageAmount = ctx.effectPower * (attackedCre)->valOfBonuses(Bonus::STACK_HEALTH);//todo: move here all DeathStare calculation 
+		bsa.damageAmount = parameters.effectPower * (attackedCre)->valOfBonuses(Bonus::STACK_HEALTH);//todo: move here all DeathStare calculation 
 		bsa.stackAttacked = (attackedCre)->ID;
 		bsa.attackerID = -1;
 		(attackedCre)->prepareAttacked(bsa, env->getRandomGenerator());

+ 2 - 1
lib/spells/ISpellMechanics.cpp

@@ -19,7 +19,8 @@
 
 BattleSpellCastParameters::BattleSpellCastParameters(const BattleInfo* cb)
 	: spellLvl(0), destination(BattleHex::INVALID), casterSide(0),casterColor(PlayerColor::CANNOT_DETERMINE),casterHero(nullptr),
-	usedSpellPower(0),mode(ECastingMode::HERO_CASTING), casterStack(nullptr), selectedStack(nullptr), cb(cb)
+	mode(ECastingMode::HERO_CASTING), casterStack(nullptr), selectedStack(nullptr), cb(cb),
+	effectLevel(0), effectPower(0), enchantPower(0), effectValue(0)
 {
 
 }

+ 10 - 1
lib/spells/ISpellMechanics.h

@@ -36,16 +36,25 @@ struct DLL_LINKAGE BattleSpellCastParameters
 {
 public:
 	BattleSpellCastParameters(const BattleInfo * cb);
+	///spell school level , 0-use default
 	int spellLvl;
 	BattleHex destination;
 	ui8 casterSide;
 	PlayerColor casterColor;
 	const CGHeroInstance * casterHero; //deprecated
-	int usedSpellPower;
 	ECastingMode::ECastingMode mode;
 	const CStack * casterStack;
 	const CStack * selectedStack;
 	const BattleInfo * cb;
+	
+	///spell school level to use for effects, 0-use spellLvl
+	int effectLevel;
+	///actual spell-power affecting effect values, 0-use default
+	int effectPower;
+	///actual spell-power affecting effect duration, 0-use default
+	int enchantPower;
+	///for Archangel-like casting, 0-use default
+	int effectValue;	
 };
 
 struct DLL_LINKAGE AdventureSpellCastParameters

+ 17 - 20
server/CGameHandler.cpp

@@ -3868,26 +3868,25 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 				complain("That stack can't cast spells!");
 			else
 			{
-				BattleSpellCastParameters p(gs->curB);				
+				BattleSpellCastParameters parameters(gs->curB);				
 				
-				p.spellLvl = 0;
+				parameters.spellLvl = 0;
 				if (spellcaster)
-					vstd::amax(p.spellLvl, spellcaster->val);
+					vstd::amax(parameters.spellLvl, spellcaster->val);
 				if (randSpellcaster)
-					vstd::amax(p.spellLvl, randSpellcaster->val);
-				vstd::amin (p.spellLvl, 3);
-
-				p.casterSide = gs->curB->whatSide(stack->owner);
-				p.mode = ECastingMode::CREATURE_ACTIVE_CASTING;
-				p.destination = destination;
-				p.casterColor = stack->owner;	
-				p.casterHero = nullptr;
-				p.usedSpellPower = 0;	
-				p.casterStack = stack;	
-				p.selectedStack = nullptr;				
+					vstd::amax(parameters.spellLvl, randSpellcaster->val);
+				vstd::amin (parameters.spellLvl, 3);
+
+				parameters.casterSide = gs->curB->whatSide(stack->owner);
+				parameters.mode = ECastingMode::CREATURE_ACTIVE_CASTING;
+				parameters.destination = destination;
+				parameters.casterColor = stack->owner;	
+				parameters.casterHero = nullptr;
+				parameters.casterStack = stack;	
+				parameters.selectedStack = nullptr;				
 
 				const CSpell * spell = SpellID(spellID).toSpell();
-				spell->battleCast(spellEnv, p);
+				spell->battleCast(spellEnv, parameters);
 			}
 			sendAndApply(&end_action);
 			break;
@@ -4081,7 +4080,6 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			parameters.casterSide = ba.side;
 			parameters.casterColor =  h->tempOwner;	
 			parameters.casterHero = h;
-			parameters.usedSpellPower = h->getPrimSkillLevel(PrimarySkill::SPELL_POWER);	
 			parameters.mode = ECastingMode::HERO_CASTING;
 			parameters.casterStack = nullptr;	
 			parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false);			
@@ -4238,13 +4236,13 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
 					parameters.casterSide = side;
 					parameters.casterColor = st->owner;	
 					parameters.casterHero = nullptr;
-					parameters.usedSpellPower = 0;	
 					parameters.mode = ECastingMode::ENCHANTER_CASTING;
 					parameters.casterStack = st;	
 					parameters.selectedStack = nullptr;
 					
 					spell->battleCast(spellEnv, parameters);				
 
+					//todo: move to mechanics
 					BattleSetStackProperty ssp;
 					ssp.which = BattleSetStackProperty::ENCHANTER_COUNTER;
 					ssp.absolute = false;
@@ -4950,7 +4948,6 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
 				parameters.casterSide = !attacker->attackerOwned;
 				parameters.casterColor = attacker->owner;	
 				parameters.casterHero = nullptr;
-				parameters.usedSpellPower = 0;	
 				parameters.mode = ECastingMode::AFTER_ATTACK_CASTING;
 				parameters.casterStack = attacker;	
 				parameters.selectedStack = nullptr;
@@ -4983,7 +4980,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
 		parameters.casterSide = !attacker->attackerOwned;
 		parameters.casterColor = attacker->owner;	
 		parameters.casterHero = nullptr;
-		parameters.usedSpellPower = power;	
+		parameters.effectPower = power;	
 		parameters.mode = ECastingMode::AFTER_ATTACK_CASTING;
 		parameters.casterStack = attacker;	
 		parameters.selectedStack = nullptr;
@@ -5297,7 +5294,7 @@ void CGameHandler::runBattle()
 					
 			for (Bonus *b : *bl)
 			{
-				parameters.usedSpellPower = b->val;	
+				parameters.enchantPower = b->val;	
 				
 				const CSpell * spell = SpellID(b->subtype).toSpell();