瀏覽代碼

Use ESpellCastProblem inside SpellHandler

AlexVinS 11 年之前
父節點
當前提交
a49da360d2
共有 6 個文件被更改,包括 37 次插入22 次删除
  1. 5 5
      lib/CBattleCallback.cpp
  2. 8 0
      lib/CModHandler.cpp
  3. 2 0
      lib/CModHandler.h
  4. 20 16
      lib/CSpellHandler.cpp
  5. 1 1
      lib/CSpellHandler.h
  6. 1 0
      lib/GameConstants.h

+ 5 - 5
lib/CBattleCallback.cpp

@@ -1621,12 +1621,12 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C
 
 ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleStackIsImmune(const CGHeroInstance * caster, const CSpell * spell, ECastingMode::ECastingMode mode, const CStack * subject) const
 {
-	if (spell->isPositive() && subject->hasBonusOfType(Bonus::RECEPTIVE)) //accept all positive spells
-		return ESpellCastProblem::OK;
-
-	if (spell->isImmuneBy(subject)) //TODO: move all logic to spellhandler
-		return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
+	const auto immuneResult = spell->isImmuneBy(subject);
+	
+	if (ESpellCastProblem::NOT_DECIDED != immuneResult) 
+		return immuneResult;
 
+	//TODO: move all logic to spellhandler
 	switch (spell->id) //TODO: more general logic for new spells?
 	{
 	case SpellID::CLONE:

+ 8 - 0
lib/CModHandler.cpp

@@ -99,6 +99,14 @@ void CIdentifierStorage::requestIdentifier(std::string scope, std::string type,
 	requestIdentifier(ObjectCallback(scope, pair.first, type, pair.second, callback, false));
 }
 
+void CIdentifierStorage::requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)>& callback)
+{
+	auto scopeAndFullName = splitString(fullName, ':');	
+	auto typeAndName = splitString(scopeAndFullName.second, '.');	
+	
+	requestIdentifier(ObjectCallback(scope, scopeAndFullName.first, typeAndName.first, typeAndName.second, callback, false));
+}
+
 void CIdentifierStorage::requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback)
 {
 	auto pair = splitString(name.String(), ':'); // remoteScope:name

+ 2 - 0
lib/CModHandler.h

@@ -72,6 +72,8 @@ public:
 	/// request identifier for specific object name.
 	/// Function callback will be called during ID resolution phase of loading
 	void requestIdentifier(std::string scope, std::string type, std::string name, const std::function<void(si32)> & callback);
+	///fullName = [remoteScope:]type.name
+	void requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)> & callback);	
 	void requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback);
 	void requestIdentifier(const JsonNode & name, const std::function<void(si32)> & callback);
 

+ 20 - 16
lib/CSpellHandler.cpp

@@ -408,33 +408,37 @@ void CSpell::getEffects(std::vector<Bonus>& lst, const int level) const
 	}
 }
 
-bool CSpell::isImmuneBy(const IBonusBearer* obj) const
+ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj) const
 {
+	//0. check receptivity
+	if (isPositive() && obj->hasBonusOfType(Bonus::RECEPTIVE)) //accept all positive spells
+		return ESpellCastProblem::OK;	
+	
 	//todo: use new bonus API
 	//1. Check absolute limiters
 	for(auto b : absoluteLimiters)
 	{
 		if (!obj->hasBonusOfType(b))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
 	//2. Check absolute immunities
 	for(auto b : absoluteImmunities)
 	{
 		if (obj->hasBonusOfType(b))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
 	//3. Check negation
 	//FIXME: Orb of vulnerability mechanics is not such trivial
 	if(obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES)) //Orb of vulnerability
-		return false;
+		return ESpellCastProblem::NOT_DECIDED;
 		
 	//4. Check negatable limit
 	for(auto b : limiters)
 	{
 		if (!obj->hasBonusOfType(b))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
 
@@ -442,42 +446,42 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
 	for(auto b : immunities)
 	{
 		if (obj->hasBonusOfType(b))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
 	auto battleTestElementalImmunity = [&,this](Bonus::BonusType element) -> bool
 	{
 		if(obj->hasBonusOfType(element, 0)) //always resist if immune to all spells altogether
-				return true;
+				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 		else if(!isPositive()) //negative or indifferent
 		{
 			if((isDamageSpell() && obj->hasBonusOfType(element, 2)) || obj->hasBonusOfType(element, 1))
-				return true;
+				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 		}
-		return false;
+		return ESpellCastProblem::NOT_DECIDED;
 	};
 
 	//6. Check elemental immunities
 	if(fire)
 	{
 		if(battleTestElementalImmunity(Bonus::FIRE_IMMUNITY))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 	if(water)
 	{
 		if(battleTestElementalImmunity(Bonus::WATER_IMMUNITY))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
 	if(earth)
 	{
 		if(battleTestElementalImmunity(Bonus::EARTH_IMMUNITY))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 	if(air)
 	{
 		if(battleTestElementalImmunity(Bonus::AIR_IMMUNITY))
-			return true;
+			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
 	TBonusListPtr levelImmunities = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
@@ -485,10 +489,10 @@ bool CSpell::isImmuneBy(const IBonusBearer* obj) const
 	if(obj->hasBonusOfType(Bonus::SPELL_IMMUNITY, id)
 		|| ( levelImmunities->size() > 0  &&  levelImmunities->totalValue() >= level  &&  level))
 	{
-		return true;
+		return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 	}
 
-	return false;
+	return ESpellCastProblem::NOT_DECIDED;
 }
 
 void CSpell::setIsOffensive(const bool val)
@@ -719,7 +723,7 @@ CSpell * CSpellHandler::loadFromJson(const JsonNode& json)
 	for(const auto & counteredSpell: json["counters"].Struct())
 		if (counteredSpell.second.Bool())
 		{
-			VLC->modh->identifiers.requestIdentifier(json.meta, "spell", counteredSpell.first, [=](si32 id)
+			VLC->modh->identifiers.requestIdentifier(json.meta, counteredSpell.first, [=](si32 id)
 			{
 				spell->counteredSpells.push_back(SpellID(id));
 			});

+ 1 - 1
lib/CSpellHandler.h

@@ -108,7 +108,7 @@ public:
 	bool hasEffects() const;
 	void getEffects(std::vector<Bonus> &lst, const int level) const;
 
-	bool isImmuneBy(const IBonusBearer *obj) const;
+	ESpellCastProblem::ESpellCastProblem isImmuneBy(const IBonusBearer *obj) const;
 
 	si32 getCost(const int skillLevel) const;
 

+ 1 - 0
lib/GameConstants.h

@@ -395,6 +395,7 @@ namespace ESpellCastProblem
 		SECOND_HEROS_SPELL_IMMUNITY, SPELL_LEVEL_LIMIT_EXCEEDED, NO_SPELLS_TO_DISPEL,
 		NO_APPROPRIATE_TARGET, STACK_IMMUNE_TO_SPELL, WRONG_SPELL_TARGET, ONGOING_TACTIC_PHASE,
 		MAGIC_IS_BLOCKED, //For Orb of Inhibition and similar - no casting at all
+		NOT_DECIDED,
 		INVALID
 	};
 }