瀏覽代碼

Unified Dispell-related bonus selectors

AlexVinS 9 年之前
父節點
當前提交
f6bfba0ced

+ 0 - 10
lib/HeroBonus.cpp

@@ -1188,16 +1188,6 @@ namespace Selector
 		dummy.subtype = subtype;
 		return sel(&dummy);
 	}
-
-	bool DLL_LINKAGE positiveSpellEffects(const Bonus *b)
-	{
-		if(b->source == Bonus::SPELL_EFFECT)
-		{
-			CSpell *sp = SpellID(b->sid).toSpell();
-			return sp->isPositive();
-		}
-		return false; //not a spell effect
-	}
 }
 
 const CStack * retreiveStackBattle(const CBonusSystemNode *node)

+ 9 - 1
lib/HeroBonus.h

@@ -965,12 +965,20 @@ namespace Selector
 	CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID);
 	CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source);
 
+	/**
+	 * Selects all bonuses
+	 * Usage example: Selector::all.And(<functor>).And(<functor>)...)
+	 */
 	extern DLL_LINKAGE CSelector all;
+
+	/**
+	 * Selects nothing
+	 * Usage example: Selector::none.Or(<functor>).Or(<functor>)...)
+	 */
 	extern DLL_LINKAGE CSelector none;
 
 	bool DLL_LINKAGE matchesType(const CSelector &sel, Bonus::BonusType type);
 	bool DLL_LINKAGE matchesTypeSubtype(const CSelector &sel, Bonus::BonusType type, TBonusSubtype subtype);
-	bool DLL_LINKAGE positiveSpellEffects(const Bonus *b);
 }
 
 extern DLL_LINKAGE const std::map<std::string, Bonus::BonusType> bonusNameMap;

+ 3 - 3
lib/spells/BattleSpellMechanics.cpp

@@ -203,7 +203,7 @@ bool CureMechanics::dispellSelector(const Bonus * b)
 ESpellCastProblem::ESpellCastProblem CureMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
 {
 	//Selector method name is ok as cashing string. --AVS
-	if(!obj->canBeHealed() && !obj->hasBonus(CSelector(DefaultSpellMechanics::dispellSelector).And(CSelector(CureMechanics::dispellSelector)), Selector::all, "CureMechanics::dispellSelector"))
+	if(!obj->canBeHealed() && !canDispell(obj, dispellSelector, "CureMechanics::dispellSelector"))
 		return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 
 	return DefaultSpellMechanics::isImmuneByStack(caster, obj);
@@ -213,7 +213,7 @@ ESpellCastProblem::ESpellCastProblem CureMechanics::isImmuneByStack(const ISpell
 void DispellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const
 {
 	DefaultSpellMechanics::applyBattle(battle, packet);
-	doDispell(battle, packet, Selector::sourceType(Bonus::SPELL_EFFECT));
+	doDispell(battle, packet, Selector::all);
 }
 
 ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
@@ -231,7 +231,7 @@ ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const ISp
 			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
-	if(obj->hasBonus(CSelector(DefaultSpellMechanics::dispellSelector), Selector::all, "DefaultSpellMechanics::dispellSelector"))
+	if(canDispell(obj, Selector::all, "DefaultSpellMechanics::dispellSelector"))
 		return ESpellCastProblem::OK;
 	else
 		return ESpellCastProblem::WRONG_SPELL_TARGET;

+ 6 - 1
lib/spells/CDefaultSpellMechanics.cpp

@@ -745,10 +745,15 @@ void DefaultSpellMechanics::doDispell(BattleInfo * battle, const BattleSpellCast
 	for(auto stackID : packet->affectedCres)
 	{
 		CStack *s = battle->getStack(stackID);
-		s->popBonuses(CSelector(dispellSelector).And(selector));
+		s->popBonuses(selector.And(dispellSelector));
 	}
 }
 
+bool DefaultSpellMechanics::canDispell(const IBonusBearer * obj, const CSelector & selector, const std::string & cachingStr/* = "" */) const
+{
+	return obj->hasBonus(selector.And(dispellSelector), Selector::all, cachingStr);
+}
+
 void DefaultSpellMechanics::handleImmunities(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx, std::vector<const CStack*> & stacks) const
 {
 	auto predicate = [&, this](const CStack * s)->bool

+ 3 - 1
lib/spells/CDefaultSpellMechanics.h

@@ -72,8 +72,8 @@ protected:
 	virtual std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const;
 
 protected:
-	static bool dispellSelector(const Bonus * bonus);
 	void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
+	bool canDispell(const IBonusBearer * obj, const CSelector & selector, const std::string &cachingStr = "") const;
 private:
 	void cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const;
 
@@ -81,6 +81,8 @@ private:
 	void handleMagicMirror(const SpellCastEnvironment * env, SpellCastContext & ctx, std::vector <const CStack*> & reflected) const;
 	void handleResistance(const SpellCastEnvironment * env, SpellCastContext & ctx) const;
 
+	static bool dispellSelector(const Bonus * bonus);
+
 	friend class SpellCastContext;
 };
 

+ 12 - 2
lib/spells/CreatureSpellMechanics.cpp

@@ -83,14 +83,24 @@ void DispellHelpfulMechanics::applyBattle(BattleInfo * battle, const BattleSpell
 {
 	DefaultSpellMechanics::applyBattle(battle, packet);
 
-	doDispell(battle, packet, Selector::positiveSpellEffects);
+	doDispell(battle, packet, positiveSpellEffects);
 }
 
 ESpellCastProblem::ESpellCastProblem DispellHelpfulMechanics::isImmuneByStack(const ISpellCaster * caster,  const CStack * obj) const
 {
-	if(!obj->hasBonus(Selector::positiveSpellEffects, Selector::all, "Selector::positiveSpellEffects"))
+	if(!canDispell(obj, positiveSpellEffects, "DispellHelpfulMechanics::positiveSpellEffects"))
 		return ESpellCastProblem::NO_SPELLS_TO_DISPEL;
 
 	//use default algorithm only if there is no mechanics-related problem
 	return DefaultSpellMechanics::isImmuneByStack(caster,obj);
 }
+
+bool DispellHelpfulMechanics::positiveSpellEffects(const Bonus *b)
+{
+	if(b->source == Bonus::SPELL_EFFECT)
+	{
+		CSpell *sp = SpellID(b->sid).toSpell();
+		return sp->isPositive();
+	}
+	return false; //not a spell effect
+}

+ 2 - 0
lib/spells/CreatureSpellMechanics.h

@@ -40,4 +40,6 @@ public:
 	void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
 
 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
+private:
+	 static bool positiveSpellEffects(const Bonus * b);
 };