2
0
Эх сурвалжийг харах

+SpecialRisingSpellMechanics::isImmuneByStack

AlexVinS 11 жил өмнө
parent
commit
ddf98a5920

+ 0 - 12
lib/BattleState.cpp

@@ -159,18 +159,6 @@ CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool at
 	return ret;
 }
 
-//All spells casted by hero 9resurrection, cure, sacrifice)
-ui32 CBattleInfoCallback::calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack) const
-{
-	bool resurrect = spell->isRisingSpell();
-	int healedHealth;
-	if (spell->id == SpellID::SACRIFICE && sacrificedStack)
-		healedHealth = (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + sacrificedStack->MaxHealth() + spell->getPower(caster->getSpellSchoolLevel(spell))) * sacrificedStack->count;
-	else
-		healedHealth = caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) * spell->power + spell->getPower(caster->getSpellSchoolLevel(spell)); //???
-	healedHealth = spell->calculateBonus(healedHealth, caster, stack);
-	return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0));
-}
 //Archangel
 ui32 CBattleInfoCallback::calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const
 {

+ 1 - 16
lib/CBattleCallback.cpp

@@ -1627,22 +1627,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleStackIsImmune(co
 		return immuneResult;
 
 	//TODO: move to spellhandler
-    if (spell->isRisingSpell() && spell->id != SpellID::SACRIFICE)
-	{
-        // following does apply to resurrect and animate dead(?) only
-        // for sacrifice health calculation and health limit check don't matter
-
-		if(subject->count >= subject->baseAmount)
-			return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
-		
-		if (caster) //FIXME: Archangels can cast immune stack
-		{
-			auto maxHealth = calculateHealedHP (caster, spell, subject);
-			if (maxHealth < subject->MaxHealth()) //must be able to rise at least one full creature
-				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
-		}
-	}
-	else if(spell->id == SpellID::HYPNOTIZE && caster) //do not resist hypnotize casted after attack, for example
+	if(spell->id == SpellID::HYPNOTIZE && caster) //do not resist hypnotize casted after attack, for example
 	{
 		//TODO: what with other creatures casting hypnotize, Faerie Dragons style?
 		ui64 subjectHealth = (subject->count - 1) * subject->MaxHealth() + subject->firstHPleft;

+ 0 - 1
lib/CBattleCallback.h

@@ -282,7 +282,6 @@ public:
 	ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here
 	std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const;
 	ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
-	ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack = nullptr) const; //Sacrifice
 	ui32 calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const; //for Archangel
 	ui32 calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const; //healing spells casted by stacks
 	std::set<const CStack*> getAffectedCreatures(const CSpell * s, int skillLevel, PlayerColor attackerOwner, BattleHex destinationTile); //calculates stack affected by given spell

+ 55 - 15
lib/CSpellHandler.cpp

@@ -182,6 +182,12 @@ namespace
 		ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, ECastingMode::ECastingMode mode, const CStack * obj) override;						
 	};
 	
+	class SacrificeMechanics: public RisingSpellMechanics
+	{
+	public:
+		
+	};
+	
 	///CloneMechanics
 	ESpellCastProblem::ESpellCastProblem CloneMechnics::isImmuneByStack(const CGHeroInstance* caster, ECastingMode::ECastingMode mode, const CStack * obj)
 	{
@@ -236,18 +242,20 @@ namespace
 	///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;
-//		}		
+        // 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, obj);
+			if (maxHealth < obj->MaxHealth()) //must be able to rise at least one full creature
+				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
+		}	
+		
+		return CSpellMechanics::isImmuneByStack(caster,mode,obj);	
 	}
 	
 	
@@ -321,6 +329,28 @@ ui32 CSpell::calculateBonus(ui32 baseDamage, const CGHeroInstance* caster, const
 	return ret;	
 }
 
+ui32 CSpell::calculateHealedHP(const CGHeroInstance* caster, const CStack* stack, const CStack* sacrificedStack) const
+{
+//todo: use Mechanics class
+	int healedHealth;
+	
+	if(!isHealingSpell())
+	{
+		logGlobal->errorStream() << "calculateHealedHP called for nonhealing spell "<< name;
+		return 0;
+	}		
+	
+	const int spellPowerSkill = caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER);
+	const int levelPower = getPower(caster->getSpellSchoolLevel(this));
+	
+	if (id == SpellID::SACRIFICE && sacrificedStack)
+		healedHealth = (spellPowerSkill + sacrificedStack->MaxHealth() + levelPower) * sacrificedStack->count;
+	else
+		healedHealth = spellPowerSkill * power + levelPower); //???
+	healedHealth = calculateBonus(healedHealth, caster, stack);
+	return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (isRisingSpell() ? stack->baseAmount * stack->MaxHealth() : 0));	
+}
+
 
 std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes) const
 {
@@ -474,6 +504,10 @@ bool CSpell::isNeutral() const
 	return positiveness == NEUTRAL;
 }
 
+bool CSpell::isHealingSpell() const
+{
+	return isRisingSpell() || (id == SpellID::CURE);
+}
 
 bool CSpell::isRisingSpell() const
 {
@@ -691,9 +725,15 @@ void CSpell::setupMechanics()
 		break;
 	case SpellID::DISPEL_HELPFUL_SPELLS:
 		mechanics = new DispellHelpfulMechanics(this);
-		break;	
-	default:
-		mechanics = new CSpellMechanics(this);
+		break;
+	case SpellID::SACRIFICE:
+		mechanics = new SacrificeMechanics(this);
+		break
+	default:		
+		if(isRisingSpell())
+			mechanics = new SpecialRisingSpellMechanics(this);
+		else	
+			mechanics = new CSpellMechanics(this);
 		break;
 	}
 	

+ 5 - 1
lib/CSpellHandler.h

@@ -113,8 +113,9 @@ public:
 	bool isNegative() const;
 	bool isNeutral() const;
 
-	bool isRisingSpell() const;
 	bool isDamageSpell() const;
+	bool isHealingSpell() const;
+	bool isRisingSpell() const;	
 	bool isOffensiveSpell() const;
 
 	bool isSpecialSpell() const;
@@ -130,6 +131,9 @@ public:
 	
 	//applying secondary skills
 	ui32 calculateBonus(ui32 baseDamage, const CGHeroInstance * caster, const CStack * affectedCreature) const;
+	
+	///calculate healed HP for all spells casted by hero
+	ui32 calculateHealedHP(const CGHeroInstance * caster, const CStack * stack, const CStack * sacrificedStack = nullptr) const;
 
 	si32 getCost(const int skillLevel) const;
 

+ 2 - 2
server/CGameHandler.cpp

@@ -4205,7 +4205,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
 
 	}
 	
-	if (spell->isRisingSpell() || spell->id == SpellID::CURE)
+	if(spell->isHealingSpell())
 	{
 			int hpGained = 0;
 			if (stack)
@@ -4233,7 +4233,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
 						hi.healedHP = gs->curB->calculateHealedHP(spell, usedSpellPower, spellLvl, attackedCre); //any typical spell (commander's cure or animate dead)
 				}
 				else
-					hi.healedHP = gs->curB->calculateHealedHP(caster, spell, attackedCre, gs->curB->battleGetStackByID(selectedStack)); //Casted by hero
+					hi.healedHP = spell->calculateHealedHP(caster, attackedCre, gs->curB->battleGetStackByID(selectedStack)); //Casted by hero
 				hi.lowLevelResurrection = spellLvl <= 1;
 				shr.healedStacks.push_back(hi);
 			}