瀏覽代碼

Use CLONE and DISPEL_HELPFUL_SPELLS Mechanics classes in immunity caculation

AlexVinS 11 年之前
父節點
當前提交
059698217c
共有 3 個文件被更改,包括 42 次插入61 次删除
  1. 2 50
      lib/CBattleCallback.cpp
  2. 38 10
      lib/CSpellHandler.cpp
  3. 2 1
      lib/CSpellHandler.h

+ 2 - 50
lib/CBattleCallback.cpp

@@ -1621,60 +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
 {
-	const auto immuneResult = spell->isImmuneBy(subject);
+	const auto immuneResult = spell->isImmuneByStack(caster, mode, 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:
-		{
-			//can't clone already cloned creature
-			if (vstd::contains(subject->state, EBattleStackState::CLONED))
-				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
-			//TODO: how about stacks casting Clone?
-			//currently Clone casted by stack is assumed Expert level
-			ui8 schoolLevel;
-			if (caster)
-			{
-				schoolLevel = caster->getSpellSchoolLevel(spell);
-			}
-			else
-			{
-				schoolLevel = 3;
-			}
-
-			if (schoolLevel < 3)
-			{
-				int maxLevel = (std::max(schoolLevel, (ui8)1) + 4);
-				int creLevel = subject->getCreature()->level;
-				if (maxLevel < creLevel) //tier 1-5 for basic, 1-6 for advanced, any level for expert
-					return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
-			}
-		}
-		break;
-	case SpellID::DISPEL_HELPFUL_SPELLS:
-		{
-			TBonusListPtr spellBon = subject->getSpellBonuses();
-			bool hasPositiveSpell = false;
-			for(const Bonus * b : *spellBon)
-			{
-				if(SpellID(b->sid).toSpell()->isPositive())
-				{
-					hasPositiveSpell = true;
-					break;
-				}
-			}
-			if(!hasPositiveSpell)
-			{
-				return ESpellCastProblem::NO_SPELLS_TO_DISPEL;
-			}
-		}
-		break;
-	}
-
+	//TODO: move to spellhandler
     if (spell->isRisingSpell() && spell->id != SpellID::SACRIFICE)
 	{
         // following does apply to resurrect and animate dead(?) only

+ 38 - 10
lib/CSpellHandler.cpp

@@ -146,8 +146,8 @@ CSpellMechanics::~CSpellMechanics()
 
 ESpellCastProblem::ESpellCastProblem CSpellMechanics::isImmuneByStack(const CGHeroInstance * caster, ECastingMode::ECastingMode mode, const CStack * obj)
 {
-	//by default no immunity
-	return ESpellCastProblem::OK;
+	//by default use general algorithm
+	return owner->isImmuneBy(obj);
 }
 
 namespace
@@ -166,6 +166,21 @@ namespace
 		ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, ECastingMode::ECastingMode mode, const CStack * obj) override;	
 	};
 	
+	///all rising spells
+	class RisingSpellMechanics: public CSpellMechanics
+	{
+	public:
+		RisingSpellMechanics(CSpell * s): CSpellMechanics(s){};		
+		
+	};
+	
+	///all rising spells but SACRIFICE
+	class SpecialRisingSpellMechanics: public RisingSpellMechanics
+	{
+	public:
+		SpecialRisingSpellMechanics(CSpell * s): RisingSpellMechanics(s){};
+		ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, ECastingMode::ECastingMode mode, const CStack * obj) override;						
+	};
 	
 	///CloneMechanics
 	ESpellCastProblem::ESpellCastProblem CloneMechnics::isImmuneByStack(const CGHeroInstance* caster, ECastingMode::ECastingMode mode, const CStack * obj)
@@ -192,7 +207,7 @@ namespace
 			if (maxLevel < creLevel) //tier 1-5 for basic, 1-6 for advanced, any level for expert
 				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
 		}
-		
+		//use default algorithm only if there is no mechanics-related problem		
 		return CSpellMechanics::isImmuneByStack(caster,mode,obj);	
 	}
 	
@@ -212,10 +227,29 @@ namespace
 		if(!hasPositiveSpell)
 		{
 			return ESpellCastProblem::NO_SPELLS_TO_DISPEL;
-		}		
+		}
+		
+		//use default algorithm only if there is no mechanics-related problem		
 		return CSpellMechanics::isImmuneByStack(caster,mode,obj);	
 	}
 	
+	///SpecialRisingSpellMechanics
+	ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStack(const CGHeroInstance* caster, ECastingMode::ECastingMode mode, const CStack* obj)
+	{
+//        // following does apply to resurrect and animate dead(?) only
+//        // for sacrifice health calculation and health limit check don't matter
+//
+//		if(obj->count >= obj->baseAmount)
+//			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
+//		
+//		if (caster) //FIXME: Archangels can cast immune stack
+//		{
+//			auto maxHealth = calculateHealedHP (caster, spell, obj);
+//			if (maxHealth < obj->MaxHealth()) //must be able to rise at least one full creature
+//				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
+//		}		
+	}
+	
 	
 }
 
@@ -592,13 +626,7 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj)
 
 ESpellCastProblem::ESpellCastProblem CSpell::isImmuneByStack(const CGHeroInstance* caster, ECastingMode::ECastingMode mode, const CStack* obj) const
 {
-	const auto immuneResult = isImmuneBy(obj);
-	
-	if (ESpellCastProblem::NOT_DECIDED != immuneResult) 
-		return immuneResult;
-		
 	return mechanics->isImmuneByStack(caster,mode,obj);
-
 }
 
 

+ 2 - 1
lib/CSpellHandler.h

@@ -121,7 +121,8 @@ public:
 
 	bool hasEffects() const;
 	void getEffects(std::vector<Bonus> &lst, const int level) const;
-
+	
+	//internal, for use only by Mechanics classes
 	ESpellCastProblem::ESpellCastProblem isImmuneBy(const IBonusBearer *obj) const;
 	
 	//checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into acount general problems such as not having spellbook or mana points etc.