mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Magic mirror unified again with normal cast.
This commit is contained in:
		| @@ -118,19 +118,8 @@ namespace SRSLPraserHelpers | ||||
| 	} | ||||
| } | ||||
|  | ||||
| SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters): | ||||
| 	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) | ||||
| SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const SpellCastEnvironment * env_, const BattleSpellCastParameters & parameters_): | ||||
| 	mechanics(mechanics_), env(env_), attackedCres(), sc(), si(), parameters(parameters_), otherHero(nullptr), spellCost(0) | ||||
| { | ||||
| 	sc.side = parameters.casterSide; | ||||
| 	sc.id = mechanics->owner->id; | ||||
| @@ -140,6 +129,19 @@ void SpellCastContext::prepareBattleCast(const BattleSpellCastParameters & param | ||||
| 	sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING; | ||||
| 	sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1); | ||||
| 	sc.manaGained = 0; | ||||
|  | ||||
| 	//check it there is opponent hero | ||||
| 	const ui8 otherSide = 1-parameters.casterSide; | ||||
|  | ||||
| 	if(parameters.cb->battleHasHero(otherSide)) | ||||
| 		otherHero = parameters.cb->battleGetFightingHero(otherSide); | ||||
|  | ||||
| 	logGlobal->debugStream() << "Started spell cast. Spell: " << mechanics->owner->name << "; mode:" << parameters.mode; | ||||
| } | ||||
|  | ||||
| SpellCastContext::~SpellCastContext() | ||||
| { | ||||
| 	logGlobal->debugStream() << "Finished spell cast. Spell: " << mechanics->owner->name << "; mode:" << parameters.mode; | ||||
| } | ||||
|  | ||||
| void SpellCastContext::addDamageToDisplay(const si32 value) | ||||
| @@ -152,7 +154,7 @@ void SpellCastContext::setDamageToDisplay(const si32 value) | ||||
| 	sc.dmgToDisplay = value; | ||||
| } | ||||
|  | ||||
| void SpellCastContext::sendCastPacket(const SpellCastEnvironment * env) | ||||
| void SpellCastContext::sendCastPacket() | ||||
| { | ||||
| 	for(auto sta : attackedCres) | ||||
| 	{ | ||||
| @@ -162,6 +164,70 @@ void SpellCastContext::sendCastPacket(const SpellCastEnvironment * env) | ||||
| 	env->sendAndApply(&sc); | ||||
| } | ||||
|  | ||||
| void SpellCastContext::beforeCast() | ||||
| { | ||||
| 	//calculate spell cost | ||||
| 	if(parameters.mode == ECastingMode::HERO_CASTING) | ||||
| 	{ | ||||
| 		spellCost = parameters.cb->battleGetSpellCost(mechanics->owner, parameters.casterHero); | ||||
|  | ||||
| 		if(nullptr != otherHero) //handle mana channel | ||||
| 		{ | ||||
| 			int manaChannel = 0; | ||||
| 			for(const CStack * stack : parameters.cb->battleGetAllStacks(true)) //TODO: shouldn't bonus system handle it somehow? | ||||
| 			{ | ||||
| 				if(stack->owner == otherHero->tempOwner) | ||||
| 				{ | ||||
| 					vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING)); | ||||
| 				} | ||||
| 			} | ||||
| 			sc.manaGained = (manaChannel * spellCost) / 100; | ||||
| 		} | ||||
|  | ||||
| 		logGlobal->debugStream() << "spellCost: " << spellCost; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SpellCastContext::afterCast() | ||||
| { | ||||
| 	sendCastPacket(); | ||||
|  | ||||
| 	if(parameters.mode == ECastingMode::HERO_CASTING) | ||||
| 	{ | ||||
| 		//spend mana | ||||
| 		SetMana sm; | ||||
| 		sm.absolute = false; | ||||
|  | ||||
| 		sm.hid = parameters.casterHero->id; | ||||
| 		sm.val = -spellCost; | ||||
|  | ||||
| 		env->sendAndApply(&sm); | ||||
|  | ||||
| 		if(sc.manaGained > 0) | ||||
| 		{ | ||||
| 			assert(otherHero); | ||||
|  | ||||
| 			sm.hid = otherHero->id; | ||||
| 			sm.val = sc.manaGained; | ||||
| 			env->sendAndApply(&sm); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING) | ||||
| 	{ | ||||
| 		//reduce number of casts remaining | ||||
| 		assert(parameters.casterStack); | ||||
|  | ||||
| 		BattleSetStackProperty ssp; | ||||
| 		ssp.stackID = parameters.casterStack->ID; | ||||
| 		ssp.which = BattleSetStackProperty::CASTS; | ||||
| 		ssp.val = -1; | ||||
| 		ssp.absolute = false; | ||||
| 		env->sendAndApply(&ssp); | ||||
| 	} | ||||
| 	if(!si.stacks.empty()) //after spellcast info shows | ||||
| 		env->sendAndApply(&si); | ||||
| } | ||||
|  | ||||
| ///DefaultSpellMechanics | ||||
| void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const | ||||
| { | ||||
| @@ -196,9 +262,9 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	std::vector <const CStack*> reflected;//for magic mirror | ||||
| 	std::vector <const CStack*> reflected, reflectedIgnore;//for magic mirror | ||||
|  | ||||
| 	castNormal(env, parameters, reflected); | ||||
| 	cast(env, parameters, reflected); | ||||
|  | ||||
| 	//Magic Mirror effect | ||||
| 	for(auto & attackedCre : reflected) | ||||
| @@ -214,7 +280,6 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B | ||||
| 			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.spellLvl = parameters.spellLvl; | ||||
| @@ -222,41 +287,16 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B | ||||
| 			mirrorParameters.effectPower = parameters.effectPower; | ||||
| 			mirrorParameters.effectValue = parameters.effectValue; | ||||
| 			mirrorParameters.enchantPower = parameters.enchantPower; | ||||
| 			castMagicMirror(env, mirrorParameters); | ||||
| 			cast(env, mirrorParameters, reflectedIgnore); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void DefaultSpellMechanics::castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const | ||||
| void DefaultSpellMechanics::cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const | ||||
| { | ||||
| 	SpellCastContext ctx(this, parameters); | ||||
| 	SpellCastContext ctx(this, env, parameters); | ||||
|  | ||||
| 	//check it there is opponent hero | ||||
| 	const ui8 otherSide = 1-parameters.casterSide; | ||||
| 	const CGHeroInstance * otherHero = nullptr; | ||||
| 	if(parameters.cb->battleHasHero(otherSide)) | ||||
| 		otherHero = parameters.cb->battleGetFightingHero(otherSide); | ||||
| 	int spellCost = 0; | ||||
|  | ||||
| 	//calculate spell cost | ||||
| 	if(parameters.mode == ECastingMode::HERO_CASTING) | ||||
| 	{ | ||||
| 		spellCost = parameters.cb->battleGetSpellCost(owner, parameters.casterHero); | ||||
|  | ||||
| 		if(nullptr != otherHero) //handle mana channel | ||||
| 		{ | ||||
| 			int manaChannel = 0; | ||||
| 			for(const CStack * stack : parameters.cb->battleGetAllStacks(true)) //TODO: shouldn't bonus system handle it somehow? | ||||
| 			{ | ||||
| 				if(stack->owner == otherHero->tempOwner) | ||||
| 				{ | ||||
| 					vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING)); | ||||
| 				} | ||||
| 			} | ||||
| 			ctx.sc.manaGained = (manaChannel * spellCost) / 100; | ||||
| 		} | ||||
| 	} | ||||
| 	logGlobal->debugStream() << "spellCost: " << spellCost; | ||||
| 	ctx.beforeCast(); | ||||
|  | ||||
| 	ctx.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex()); | ||||
|  | ||||
| @@ -264,66 +304,12 @@ void DefaultSpellMechanics::castNormal(const SpellCastEnvironment * env, const B | ||||
|  | ||||
| 	handleResistance(env, ctx); | ||||
|  | ||||
| 	handleMagicMirror(env, ctx, reflected); | ||||
| 	if(parameters.mode != ECastingMode::MAGIC_MIRROR) | ||||
| 		handleMagicMirror(env, ctx, reflected); | ||||
|  | ||||
| 	applyBattleEffects(env, parameters, ctx); | ||||
|  | ||||
| 	ctx.sendCastPacket(env); | ||||
|  | ||||
| 	if(parameters.mode == ECastingMode::HERO_CASTING) | ||||
| 	{ | ||||
| 		//spend mana | ||||
| 		SetMana sm; | ||||
| 		sm.absolute = false; | ||||
|  | ||||
| 		sm.hid = parameters.casterHero->id; | ||||
| 		sm.val = -spellCost; | ||||
|  | ||||
| 		env->sendAndApply(&sm); | ||||
|  | ||||
| 		if(ctx.sc.manaGained > 0) | ||||
| 		{ | ||||
| 			assert(otherHero); | ||||
|  | ||||
| 			sm.hid = otherHero->id; | ||||
| 			sm.val = ctx.sc.manaGained; | ||||
| 			env->sendAndApply(&sm); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING) | ||||
| 	{ | ||||
| 		//reduce number of casts remaining | ||||
| 		assert(parameters.casterStack); | ||||
|  | ||||
| 		BattleSetStackProperty ssp; | ||||
| 		ssp.stackID = parameters.casterStack->ID; | ||||
| 		ssp.which = BattleSetStackProperty::CASTS; | ||||
| 		ssp.val = -1; | ||||
| 		ssp.absolute = false; | ||||
| 		env->sendAndApply(&ssp); | ||||
| 	} | ||||
|  | ||||
| 	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); | ||||
|  | ||||
| 	//calculating affected creatures for all spells | ||||
| 	ctx.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex()); | ||||
|  | ||||
| 	logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks"; | ||||
|  | ||||
| 	handleResistance(env, ctx); | ||||
|  | ||||
| 	applyBattleEffects(env, parameters, ctx); | ||||
|  | ||||
| 	ctx.sendCastPacket(env); | ||||
|  | ||||
| 	if(!ctx.si.stacks.empty()) //after spellcast info shows | ||||
| 		env->sendAndApply(&ctx.si); | ||||
| 	ctx.afterCast(); | ||||
| } | ||||
|  | ||||
| void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet, | ||||
|   | ||||
| @@ -19,20 +19,25 @@ class DLL_LINKAGE SpellCastContext | ||||
| { | ||||
| public: | ||||
| 	const DefaultSpellMechanics * mechanics; | ||||
| 	const SpellCastEnvironment * env; | ||||
| 	std::vector<const CStack *> attackedCres;//must be vector, as in Chain Lightning order matters | ||||
| 	BattleSpellCast sc;//todo: make private | ||||
| 	StacksInjured si; | ||||
| 	ECastingMode::ECastingMode mode; | ||||
| 	const BattleSpellCastParameters & parameters; | ||||
|  | ||||
| 	SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters); | ||||
| 	SpellCastContext(const DefaultSpellMechanics * mechanics_, const SpellCastEnvironment * env_, const BattleSpellCastParameters & parameters_); | ||||
| 	virtual ~SpellCastContext(); | ||||
|  | ||||
| 	void addDamageToDisplay(const si32 value); | ||||
| 	void setDamageToDisplay(const si32 value); | ||||
|  | ||||
| 	void sendCastPacket(const SpellCastEnvironment * env); | ||||
| 	void beforeCast(); | ||||
| 	void afterCast(); | ||||
| private: | ||||
| 	void prepareBattleCast(const BattleSpellCastParameters & parameters); | ||||
| 	const CGHeroInstance * otherHero; | ||||
| 	int spellCost; | ||||
|  | ||||
| 	void sendCastPacket(); | ||||
| }; | ||||
|  | ||||
| ///all combat spells | ||||
| @@ -65,8 +70,7 @@ protected: | ||||
| protected: | ||||
| 	void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const; | ||||
| private: | ||||
| 	void castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const; | ||||
| 	void castMagicMirror(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const; | ||||
| 	void cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const; | ||||
|  | ||||
| 	void handleImmunities(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx, std::vector<const CStack *> & stacks) const; | ||||
| 	void handleMagicMirror(const SpellCastEnvironment * env, SpellCastContext & ctx, std::vector <const CStack*> & reflected) const; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user