mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Centralize dispell mechanics
This commit is contained in:
		| @@ -101,6 +101,12 @@ CSpell::~CSpell() | |||||||
| 	delete mechanics; | 	delete mechanics; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void CSpell::afterCast(BattleInfo * battle, const BattleSpellCast * packet) const | ||||||
|  | { | ||||||
|  | 	mechanics->afterCast(battle, packet); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void CSpell::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const | void CSpell::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const | ||||||
| { | { | ||||||
| 	assert(env); | 	assert(env); | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ class BattleInfo; | |||||||
|  |  | ||||||
| struct CPackForClient; | struct CPackForClient; | ||||||
| struct BattleSpellCast; | struct BattleSpellCast; | ||||||
|  |  | ||||||
| class CRandomGenerator; | class CRandomGenerator; | ||||||
|  |  | ||||||
| struct SpellSchoolInfo | struct SpellSchoolInfo | ||||||
| @@ -256,6 +257,10 @@ public: | |||||||
| 	} | 	} | ||||||
| 	friend class CSpellHandler; | 	friend class CSpellHandler; | ||||||
| 	friend class Graphics; | 	friend class Graphics; | ||||||
|  | public:	 | ||||||
|  | 	///Client-Server events. Shall be called only when applying packets	 | ||||||
|  | 	void afterCast(BattleInfo * battle, const BattleSpellCast * packet) const; | ||||||
|  | 		 | ||||||
| private: | private: | ||||||
| 	void setIsOffensive(const bool val); | 	void setIsOffensive(const bool val); | ||||||
| 	void setIsRising(const bool val); | 	void setIsRising(const bool val); | ||||||
| @@ -323,10 +328,7 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		h & objects ; | 		h & objects ; | ||||||
| 	} | 	} | ||||||
| public:	 | 		 | ||||||
| 	///Client-Server events. Shall be called only when applying packets	 |  | ||||||
| 	//void afterSpellCast(BattleInfo * battle, BattleSpellCast * packet) const; |  | ||||||
| 	 |  | ||||||
| protected: | protected: | ||||||
| 	CSpell * loadFromJson(const JsonNode & json) override; | 	CSpell * loadFromJson(const JsonNode & json) override; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1343,29 +1343,9 @@ DLL_LINKAGE void BattleSpellCast::applyGs( CGameState *gs ) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	//Handle spells removing effects from stacks | 	const CSpell * spell = SpellID(id).toSpell(); | ||||||
| 	const CSpell *spell = SpellID(id).toSpell(); | 	 | ||||||
| 	const bool removeAllSpells = id == SpellID::DISPEL; | 	spell->afterCast(gs->curB, this); | ||||||
| 	const bool removeHelpful = id == SpellID::DISPEL_HELPFUL_SPELLS; |  | ||||||
|  |  | ||||||
| 	for(auto stackID : affectedCres) |  | ||||||
| 	{ |  | ||||||
| 		if(vstd::contains(resisted, stackID)) |  | ||||||
| 			continue; |  | ||||||
|  |  | ||||||
| 		CStack *s = gs->curB->getStack(stackID); |  | ||||||
| 		s->popBonuses([&](const Bonus *b) -> bool |  | ||||||
| 		{ |  | ||||||
| 			//check for each bonus if it should be removed |  | ||||||
| 			const bool isSpellEffect = Selector::sourceType(Bonus::SPELL_EFFECT)(b); |  | ||||||
| 			const bool isPositiveSpell = Selector::positiveSpellEffects(b); |  | ||||||
| 			const int spellID = isSpellEffect ? b->sid : -1; |  | ||||||
|  |  | ||||||
| 			return (removeHelpful && isPositiveSpell) |  | ||||||
| 				|| (removeAllSpells && isSpellEffect) |  | ||||||
| 				|| vstd::contains(spell->counteredSpells, spellID); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void actualizeEffect(CStack * s, const std::vector<Bonus> & ef) | void actualizeEffect(CStack * s, const std::vector<Bonus> & ef) | ||||||
|   | |||||||
| @@ -141,6 +141,8 @@ public: | |||||||
| 	 | 	 | ||||||
| 	//bool adventureCast(const SpellCastContext & context) const override;  | 	//bool adventureCast(const SpellCastContext & context) const override;  | ||||||
| 	void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const override; | 	void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const override; | ||||||
|  | 	 | ||||||
|  | 	void afterCast(BattleInfo * battle, const BattleSpellCast * packet) const override; | ||||||
| protected: | protected: | ||||||
| 	 | 	 | ||||||
| 	virtual void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const; | 	virtual void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const; | ||||||
| @@ -173,6 +175,14 @@ protected: | |||||||
| 	void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;	 | 	void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;	 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class CureMechanics: public DefaultSpellMechanics | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	CureMechanics(CSpell * s): DefaultSpellMechanics(s){};	 | ||||||
|  | 	 | ||||||
|  | 	void afterCast(BattleInfo * battle, const BattleSpellCast * packet) const override;	 | ||||||
|  | }; | ||||||
|  |  | ||||||
| class DeathStareMechnics: public DefaultSpellMechanics | class DeathStareMechnics: public DefaultSpellMechanics | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @@ -185,9 +195,20 @@ class DispellHelpfulMechanics: public DefaultSpellMechanics | |||||||
| { | { | ||||||
| public: | public: | ||||||
| 	DispellHelpfulMechanics(CSpell * s): DefaultSpellMechanics(s){}; | 	DispellHelpfulMechanics(CSpell * s): DefaultSpellMechanics(s){}; | ||||||
|  | 	 | ||||||
|  | 	void afterCast(BattleInfo * battle, const BattleSpellCast * packet) const override; | ||||||
|  | 	 | ||||||
| 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;	 | 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;	 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class DispellMechanics: public DefaultSpellMechanics | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	DispellMechanics(CSpell * s): DefaultSpellMechanics(s){}; | ||||||
|  | 	 | ||||||
|  | 	void afterCast(BattleInfo * battle, const BattleSpellCast * packet) const override;	 | ||||||
|  | }; | ||||||
|  |  | ||||||
| class HypnotizeMechanics: public DefaultSpellMechanics | class HypnotizeMechanics: public DefaultSpellMechanics | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @@ -270,33 +291,39 @@ ISpellMechanics * ISpellMechanics::createMechanics(CSpell * s) | |||||||
| { | { | ||||||
| 	switch (s->id) | 	switch (s->id) | ||||||
| 	{ | 	{ | ||||||
| 	case SpellID::CLONE: | 	case SpellID::ACID_BREATH_DAMAGE: | ||||||
| 		return new CloneMechanics(s); | 		return new AcidBreathDamageMechnics(s); | ||||||
| 	case SpellID::DISPEL_HELPFUL_SPELLS: |  | ||||||
| 		return new DispellHelpfulMechanics(s); |  | ||||||
| 	case SpellID::SACRIFICE: |  | ||||||
| 		return new SacrificeMechanics(s); |  | ||||||
| 	case SpellID::CHAIN_LIGHTNING: | 	case SpellID::CHAIN_LIGHTNING: | ||||||
| 		return new ChainLightningMechanics(s);		 | 		return new ChainLightningMechanics(s);		 | ||||||
|  | 	case SpellID::CLONE: | ||||||
|  | 		return new CloneMechanics(s); | ||||||
|  | 	case SpellID::CURE: | ||||||
|  | 		return new CureMechanics(s); | ||||||
|  | 	case SpellID::DEATH_STARE: | ||||||
|  | 		return new DeathStareMechnics(s);			 | ||||||
|  | 	case SpellID::DISPEL: | ||||||
|  | 		return new DispellMechanics(s);	 | ||||||
|  | 	case SpellID::DISPEL_HELPFUL_SPELLS: | ||||||
|  | 		return new DispellHelpfulMechanics(s); | ||||||
| 	case SpellID::FIRE_WALL: | 	case SpellID::FIRE_WALL: | ||||||
| 	case SpellID::FORCE_FIELD: | 	case SpellID::FORCE_FIELD: | ||||||
| 		return new WallMechanics(s);		 | 		return new WallMechanics(s);		 | ||||||
|  | 	case SpellID::HYPNOTIZE: | ||||||
|  | 		return new HypnotizeMechanics(s); | ||||||
| 	case SpellID::LAND_MINE: | 	case SpellID::LAND_MINE: | ||||||
| 	case SpellID::QUICKSAND: | 	case SpellID::QUICKSAND: | ||||||
| 		return new ObstacleMechanics(s); | 		return new ObstacleMechanics(s); | ||||||
| 	case SpellID::TELEPORT: | 	case SpellID::REMOVE_OBSTACLE: | ||||||
| 		return new TeleportMechanics(s); | 		return new RemoveObstacleMechanics(s); | ||||||
|  | 	case SpellID::SACRIFICE: | ||||||
|  | 		return new SacrificeMechanics(s); | ||||||
| 	case SpellID::SUMMON_FIRE_ELEMENTAL: | 	case SpellID::SUMMON_FIRE_ELEMENTAL: | ||||||
| 	case SpellID::SUMMON_EARTH_ELEMENTAL: | 	case SpellID::SUMMON_EARTH_ELEMENTAL: | ||||||
| 	case SpellID::SUMMON_WATER_ELEMENTAL: | 	case SpellID::SUMMON_WATER_ELEMENTAL: | ||||||
| 	case SpellID::SUMMON_AIR_ELEMENTAL: | 	case SpellID::SUMMON_AIR_ELEMENTAL: | ||||||
| 		return new SummonMechanics(s); | 		return new SummonMechanics(s); | ||||||
| 	case SpellID::REMOVE_OBSTACLE: | 	case SpellID::TELEPORT: | ||||||
| 		return new RemoveObstacleMechanics(s); | 		return new TeleportMechanics(s); | ||||||
| 	case SpellID::DEATH_STARE: |  | ||||||
| 		return new DeathStareMechnics(s); |  | ||||||
| 	case SpellID::ACID_BREATH_DAMAGE: |  | ||||||
| 		return new AcidBreathDamageMechnics(s); |  | ||||||
| 	default:		 | 	default:		 | ||||||
| 		if(s->isRisingSpell()) | 		if(s->isRisingSpell()) | ||||||
| 			return new SpecialRisingSpellMechanics(s); | 			return new SpecialRisingSpellMechanics(s); | ||||||
| @@ -307,11 +334,28 @@ ISpellMechanics * ISpellMechanics::createMechanics(CSpell * s) | |||||||
|  |  | ||||||
|  |  | ||||||
| ///DefaultSpellMechanics | ///DefaultSpellMechanics | ||||||
|  | void DefaultSpellMechanics::afterCast(BattleInfo * battle, const BattleSpellCast * packet) const | ||||||
|  | { | ||||||
|  | 	//TODO: may be move all from BattleSpellCast::applyGs here  | ||||||
|  | 	 | ||||||
|  | 	//handle countering spells | ||||||
|  | 	for(auto stackID : packet->affectedCres) | ||||||
|  | 	{ | ||||||
|  | 		if(vstd::contains(packet->resisted, stackID)) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		CStack * s = battle->getStack(stackID); | ||||||
|  | 		s->popBonuses([&](const Bonus * b) -> bool | ||||||
|  | 		{ | ||||||
|  | 			//check for each bonus if it should be removed | ||||||
|  | 			const bool isSpellEffect = Selector::sourceType(Bonus::SPELL_EFFECT)(b); | ||||||
|  | 			const int spellID = isSpellEffect ? b->sid : -1; | ||||||
|  |  | ||||||
|  | 			return isSpellEffect && vstd::contains(owner->counteredSpells, spellID); | ||||||
|  | 		}); | ||||||
|  | 	}	 | ||||||
|  | } | ||||||
|  |  | ||||||
| //bool DefaultSpellMechanics::adventureCast(const SpellCastContext& context) const |  | ||||||
| //{ |  | ||||||
| //	return false; //there is no general algorithm for casting adventure spells |  | ||||||
| //} |  | ||||||
|  |  | ||||||
| void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const | void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const | ||||||
| { | { | ||||||
| @@ -893,6 +937,33 @@ ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const CGHer | |||||||
| 	return DefaultSpellMechanics::isImmuneByStack(caster, obj);	 | 	return DefaultSpellMechanics::isImmuneByStack(caster, obj);	 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | ///CureMechanics | ||||||
|  | void CureMechanics::afterCast(BattleInfo * battle, const BattleSpellCast * packet) const | ||||||
|  | { | ||||||
|  | 	DefaultSpellMechanics::afterCast(battle, packet); | ||||||
|  | 	 | ||||||
|  | 	for(auto stackID : packet->affectedCres) | ||||||
|  | 	{ | ||||||
|  | 		if(vstd::contains(packet->resisted, stackID)) | ||||||
|  | 		{ | ||||||
|  | 			logGlobal->errorStream() << "Resistance to positive spell CURE"; | ||||||
|  | 			continue; | ||||||
|  | 		}			 | ||||||
|  |  | ||||||
|  | 		CStack *s = battle->getStack(stackID); | ||||||
|  | 		s->popBonuses([&](const Bonus *b) -> bool | ||||||
|  | 		{ | ||||||
|  | 			if(b->source == Bonus::SPELL_EFFECT) | ||||||
|  | 			{ | ||||||
|  | 				CSpell * sp = SpellID(b->sid).toSpell(); | ||||||
|  | 				return sp->isNegative(); | ||||||
|  | 			} | ||||||
|  | 			return false; //not a spell effect | ||||||
|  | 		}); | ||||||
|  | 	}		 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| ///DeathStareMechnics | ///DeathStareMechnics | ||||||
| void DeathStareMechnics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const | void DeathStareMechnics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const | ||||||
| { | { | ||||||
| @@ -915,6 +986,24 @@ void DeathStareMechnics::applyBattleEffects(const SpellCastEnvironment * env, Ba | |||||||
|  |  | ||||||
|  |  | ||||||
| ///DispellHelpfulMechanics | ///DispellHelpfulMechanics | ||||||
|  | void DispellHelpfulMechanics::afterCast(BattleInfo * battle, const BattleSpellCast * packet) const | ||||||
|  | { | ||||||
|  | 	DefaultSpellMechanics::afterCast(battle, packet); | ||||||
|  | 	 | ||||||
|  | 	for(auto stackID : packet->affectedCres) | ||||||
|  | 	{ | ||||||
|  | 		if(vstd::contains(packet->resisted, stackID)) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		CStack *s = battle->getStack(stackID); | ||||||
|  | 		s->popBonuses([&](const Bonus *b) -> bool | ||||||
|  | 		{ | ||||||
|  | 			return Selector::positiveSpellEffects(b); | ||||||
|  | 		}); | ||||||
|  | 	}	 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| ESpellCastProblem::ESpellCastProblem DispellHelpfulMechanics::isImmuneByStack(const CGHeroInstance * caster,  const CStack * obj) const | ESpellCastProblem::ESpellCastProblem DispellHelpfulMechanics::isImmuneByStack(const CGHeroInstance * caster,  const CStack * obj) const | ||||||
| { | { | ||||||
| 	TBonusListPtr spellBon = obj->getSpellBonuses(); | 	TBonusListPtr spellBon = obj->getSpellBonuses(); | ||||||
| @@ -936,6 +1025,25 @@ ESpellCastProblem::ESpellCastProblem DispellHelpfulMechanics::isImmuneByStack(co | |||||||
| 	return DefaultSpellMechanics::isImmuneByStack(caster,obj);	 | 	return DefaultSpellMechanics::isImmuneByStack(caster,obj);	 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | ///DispellMechanics | ||||||
|  | void DispellMechanics::afterCast(BattleInfo * battle, const BattleSpellCast * packet) const | ||||||
|  | { | ||||||
|  | 	DefaultSpellMechanics::afterCast(battle, packet); | ||||||
|  | 	 | ||||||
|  | 	for(auto stackID : packet->affectedCres) | ||||||
|  | 	{ | ||||||
|  | 		if(vstd::contains(packet->resisted, stackID)) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		CStack *s = battle->getStack(stackID); | ||||||
|  | 		s->popBonuses([&](const Bonus *b) -> bool | ||||||
|  | 		{ | ||||||
|  | 			return Selector::sourceType(Bonus::SPELL_EFFECT)(b); | ||||||
|  | 		}); | ||||||
|  | 	}	 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| ///HypnotizeMechanics | ///HypnotizeMechanics | ||||||
| ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const | ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const | ||||||
| { | { | ||||||
|   | |||||||
| @@ -46,6 +46,8 @@ public: | |||||||
| 	 | 	 | ||||||
| 	static ISpellMechanics * createMechanics(CSpell * s); | 	static ISpellMechanics * createMechanics(CSpell * s); | ||||||
| 	 | 	 | ||||||
|  | 	virtual void afterCast(BattleInfo * battle, const BattleSpellCast * packet) const = 0; | ||||||
|  | 	 | ||||||
| protected: | protected: | ||||||
| 	CSpell * owner;	 | 	CSpell * owner;	 | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user