瀏覽代碼

Factored out battleCanCastThisSpellHere

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

+ 1 - 27
lib/CBattleCallback.cpp

@@ -1773,38 +1773,12 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
 		logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpellHere: no spellcaster.";
 		return ESpellCastProblem::INVALID;
 	}
-	const PlayerColor player = caster->getOwner();
 
 	ESpellCastProblem::ESpellCastProblem problem = battleCanCastThisSpell(caster, spell, mode);
 	if(problem != ESpellCastProblem::OK)
 		return problem;
 
-	problem = spell->canBeCastAt(this, caster, mode, dest);
-	if(problem != ESpellCastProblem::OK)
-		return problem;
-
-	//get dead stack if we cast resurrection or animate dead
-	const CStack *deadStack = getStackIf([dest](const CStack *s) { return !s->alive() && s->coversPos(dest); });
-	const CStack *aliveStack = getStackIf([dest](const CStack *s) { return s->alive() && s->coversPos(dest);});
-
-
-	if(spell->isRisingSpell())
-	{
-		if(!deadStack && !aliveStack)
-			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
-		if(deadStack && deadStack->owner != player) //you can resurrect only your own stacks //FIXME: it includes alive stacks as well
-			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
-	}
-	else if(spell->getTargetType() == CSpell::CREATURE)
-	{
-		if(!aliveStack)
-			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
-		if(spell->isNegative() && aliveStack->owner == player)
-			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
-		if(spell->isPositive() && aliveStack->owner != player)
-			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
-	}
-	return spell->isImmuneAt(this, caster, mode, dest);
+	return spell->canBeCastAt(this, caster, mode, dest);
 }
 
 const CStack * CBattleInfoCallback::getStackIf(std::function<bool(const CStack*)> pred) const

+ 15 - 6
lib/spells/BattleSpellMechanics.cpp

@@ -573,12 +573,6 @@ bool RemoveObstacleMechanics::canRemove(const CObstacleInstance * obstacle, cons
 }
 
 ///RisingSpellMechanics
-ESpellCastProblem::ESpellCastProblem RisingSpellMechanics::canBeCast(const SpellTargetingContext & ctx) const
-{
-	//todo: RisingSpellMechanics::canBeCast
-	return ESpellCastProblem::OK;
-}
-
 HealingSpellMechanics::EHealLevel RisingSpellMechanics::getHealLevel(int effectLevel) const
 {
 	//this may be even distinct class
@@ -673,6 +667,21 @@ int SacrificeMechanics::calculateHealedHP(const SpellCastEnvironment* env, const
 }
 
 ///SpecialRisingSpellMechanics
+ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(const SpellTargetingContext & ctx) const
+{
+	const CStack * stack = ctx.cb->getStackIf([ctx](const CStack * s)
+	{
+		const bool ownerMatches = !ctx.ti.smart || s->getOwner() == ctx.caster->getOwner();
+
+		return ownerMatches && s->isValidTarget(true) && s->coversPos(ctx.destination);
+	});
+
+	if(nullptr == stack)
+		return ESpellCastProblem::NO_APPROPRIATE_TARGET;
+
+	return ESpellCastProblem::OK;
+}
+
 ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
 {
 	// following does apply to resurrect and animate dead(?) only

+ 3 - 2
lib/spells/BattleSpellMechanics.h

@@ -125,7 +125,7 @@ class DLL_LINKAGE RisingSpellMechanics : public HealingSpellMechanics
 {
 public:
 	RisingSpellMechanics(CSpell * s): HealingSpellMechanics(s){};
-	ESpellCastProblem::ESpellCastProblem canBeCast(const SpellTargetingContext & ctx) const override;
+
 	EHealLevel getHealLevel(int effectLevel) const override;
 };
 
@@ -140,11 +140,12 @@ protected:
 	int calculateHealedHP(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
 };
 
-///all rising spells but SACRIFICE
+///ANIMATE_DEAD and RESURRECTION
 class DLL_LINKAGE SpecialRisingSpellMechanics : public RisingSpellMechanics
 {
 public:
 	SpecialRisingSpellMechanics(CSpell * s): RisingSpellMechanics(s){};
+	ESpellCastProblem::ESpellCastProblem canBeCast(const SpellTargetingContext & ctx) const override;
 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
 };
 

+ 22 - 8
lib/spells/CSpellHandler.cpp

@@ -222,11 +222,6 @@ bool CSpell::isNeutral() const
 	return positiveness == NEUTRAL;
 }
 
-bool CSpell::isHealingSpell() const
-{
-	return isRisingSpell() || (id == SpellID::CURE);
-}
-
 bool CSpell::isRisingSpell() const
 {
 	return isRising;
@@ -307,12 +302,31 @@ void CSpell::getEffects(std::vector<Bonus> & lst, const int level) const
 
 ESpellCastProblem::ESpellCastProblem CSpell::canBeCastAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
 {
+	ISpellMechanics::SpellTargetingContext ctx(this, cb, mode, caster, caster->getSpellSchoolLevel(this), destination);
 
-	//todo: CSpell::canBeCastAt check common problems
 
-	ISpellMechanics::SpellTargetingContext ctx(this, cb, mode, caster, caster->getSpellSchoolLevel(this), destination);
+	ESpellCastProblem::ESpellCastProblem specific = mechanics->canBeCast(ctx);
+
+	if(specific != ESpellCastProblem::OK)
+		return specific;
+
+	//todo: this should be moved to mechanics
+	if(ctx.ti.onlyAlive && ctx.ti.smart && getTargetType() == CSpell::CREATURE)
+	{
+		const CStack * aliveStack = cb->getStackIf([destination](const CStack * s)
+		{
+			return s->isValidTarget(false) && s->coversPos(destination);
+		});
+
+		if(!aliveStack)
+			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
+		if(isNegative() && aliveStack->owner == caster->getOwner())
+			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
+		if(isPositive() && aliveStack->owner != caster->getOwner())
+			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
+	}
 
-	return mechanics->canBeCast(ctx);
+	return isImmuneAt(cb, caster, mode, destination);
 }
 
 ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const

+ 4 - 4
lib/spells/CSpellHandler.h

@@ -204,7 +204,6 @@ public:
 	bool isNeutral() const;
 
 	bool isDamageSpell() const;
-	bool isHealingSpell() const;
 	bool isRisingSpell() const;
 	bool isOffensiveSpell() const;
 
@@ -272,9 +271,6 @@ public:
 	///checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into account general problems such as not having spellbook or mana points etc.
 	ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const;
 
-	///checks for creature immunity *at given hex*.
-	ESpellCastProblem::ESpellCastProblem isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const;
-
 	///checks for creature immunity / anything that prevent casting *at given target* - doesn't take into account general problems such as not having spellbook or mana points etc.
 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const;
 public:
@@ -303,6 +299,10 @@ public://internal, for use only by Mechanics classes
 	ESpellCastProblem::ESpellCastProblem internalIsImmune(const ISpellCaster * caster, const CStack *obj) const;
 
 private:
+
+	///checks for creature immunity *at given hex*.
+	ESpellCastProblem::ESpellCastProblem isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const;
+
 	void setIsOffensive(const bool val);
 	void setIsRising(const bool val);