Browse Source

Use range limit selector when modifying bonus lists and checking for spell bonuses
* fixes http://bugs.vcmi.eu/view.php?id=2532

AlexVinS 9 years ago
parent
commit
2f7e10a06f
3 changed files with 18 additions and 26 deletions
  1. 12 23
      lib/HeroBonus.cpp
  2. 4 1
      lib/HeroBonus.h
  3. 2 2
      lib/spells/BattleSpellMechanics.cpp

+ 12 - 23
lib/HeroBonus.cpp

@@ -331,6 +331,11 @@ bool IBonusBearer::hasBonus(const CSelector &selector, const std::string &cachin
 	return getBonuses(selector, cachingStr)->size() > 0;
 }
 
+bool IBonusBearer::hasBonus(const CSelector &selector, const CSelector &limit, const std::string &cachingStr /*= ""*/) const
+{
+	return getBonuses(selector, limit, cachingStr)->size() > 0;
+}
+
 bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
 {
 	std::stringstream cachingStr;
@@ -369,7 +374,7 @@ bool IBonusBearer::hasBonusFrom(Bonus::BonusSource source, ui32 sourceID) const
 {
 	std::stringstream cachingStr;
 	cachingStr << "source_" << source << "id_" << sourceID;
-	return hasBonus(Selector::source(source,sourceID), cachingStr.str());
+	return hasBonus(Selector::source(source,sourceID), Selector::all, cachingStr.str());
 }
 
 int IBonusBearer::MoraleVal() const
@@ -521,28 +526,9 @@ const std::shared_ptr<Bonus> IBonusBearer::getEffect(ui16 id, int turn /*= 0*/)
 	return nullptr;
 }
 
-ui8 IBonusBearer::howManyEffectsSet(ui16 id) const
-{
-	//TODO should check only local bonuses?
-	ui8 ret = 0;
-
-	auto bonuses = getAllBonuses();
-	for(auto& it : *bonuses)
-	{
-		if(it->source == Bonus::SPELL_EFFECT && it->sid == id) //effect found
-		{
-			++ret;
-		}
-	}
-
-	return ret;
-}
-
 const TBonusListPtr IBonusBearer::getAllBonuses() const
 {
-	auto matchAll  = [] (const Bonus *) { return true; };
-	auto matchNone = [] (const Bonus *) { return true; };
-	return getAllBonuses(matchAll, matchNone);
+	return getAllBonuses(Selector::all, Selector::all);
 }
 
 const std::shared_ptr<Bonus> IBonusBearer::getBonus(const CSelector &selector) const
@@ -778,7 +764,7 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
 void CBonusSystemNode::popBonuses(const CSelector &s)
 {
 	BonusList bl;
-	exportedBonuses.getBonuses(bl, s);
+	exportedBonuses.getBonuses(bl, s, Selector::all);
 	for(auto b : bl)
 		removeBonus(b);
 
@@ -789,7 +775,7 @@ void CBonusSystemNode::popBonuses(const CSelector &s)
 void CBonusSystemNode::updateBonuses(const CSelector &s)
 {
 	BonusList bl;
-	exportedBonuses.getBonuses(bl, s);
+	exportedBonuses.getBonuses(bl, s, Selector::all);
 	for(auto b : bl)
 	{
 		b->turnsRemain--;
@@ -1237,6 +1223,9 @@ namespace Selector
 		return CSelectFieldEqual<Bonus::BonusSource>(&Bonus::source)(source);
 	}
 
+	DLL_LINKAGE CSelector all([](const Bonus * b){return true;});
+	DLL_LINKAGE CSelector none([](const Bonus * b){return false;});
+
 	bool DLL_LINKAGE matchesType(const CSelector &sel, Bonus::BonusType type)
 	{
 		Bonus dummy;

+ 4 - 1
lib/HeroBonus.h

@@ -582,6 +582,7 @@ public:
 	int getBonusesCount(const CSelector &selector, const std::string &cachingStr = "") const;
 	int valOfBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
 	bool hasBonus(const CSelector &selector, const std::string &cachingStr = "") const;
+	bool hasBonus(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const;
 	const TBonusListPtr getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const;
 	const TBonusListPtr getBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
 
@@ -607,7 +608,6 @@ public:
 	virtual si32 magicResistance() const;
 	ui32 Speed(int turn = 0, bool useBind = false) const; //get speed of creature with all modificators
 	const std::shared_ptr<Bonus> getEffect(ui16 id, int turn = 0) const; //effect id (SP)
-	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 
 	si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
 	int getPrimSkillLevel(PrimarySkill::PrimarySkill id) const;
@@ -991,6 +991,9 @@ namespace Selector
 	CSelector DLL_LINKAGE source(Bonus::BonusSource source, ui32 sourceID);
 	CSelector DLL_LINKAGE sourceTypeSel(Bonus::BonusSource source);
 
+	extern DLL_LINKAGE CSelector all;
+	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);

+ 2 - 2
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)), "CureMechanics::dispellSelector"))
+	if(!obj->canBeHealed() && !obj->hasBonus(CSelector(DefaultSpellMechanics::dispellSelector).And(CSelector(CureMechanics::dispellSelector)), Selector::all, "CureMechanics::dispellSelector"))
 		return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 
 	return DefaultSpellMechanics::isImmuneByStack(caster, obj);
@@ -231,7 +231,7 @@ ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const ISp
 			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
-	if(obj->hasBonus(CSelector(DefaultSpellMechanics::dispellSelector), "DefaultSpellMechanics::dispellSelector"))
+	if(obj->hasBonus(CSelector(DefaultSpellMechanics::dispellSelector), Selector::all, "DefaultSpellMechanics::dispellSelector"))
 		return ESpellCastProblem::OK;
 	else
 		return ESpellCastProblem::WRONG_SPELL_TARGET;