Преглед на файлове

[Spells] Get rid of SpellTargetingContext.

AlexVinS преди 8 години
родител
ревизия
f1a4831813

+ 25 - 29
lib/spells/BattleSpellMechanics.cpp

@@ -93,34 +93,27 @@ ChainLightningMechanics::ChainLightningMechanics(const CSpell * s):
 {
 }
 
-std::vector<const CStack *> ChainLightningMechanics::calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+std::vector<const CStack *> ChainLightningMechanics::calculateAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
 {
 	std::vector<const CStack *> res;
-
 	std::set<BattleHex> possibleHexes;
 	for(auto stack : cb->battleGetAllStacks())
 	{
 		if(stack->isValidTarget())
-		{
 			for(auto hex : stack->getHexes())
-			{
-				possibleHexes.insert (hex);
-			}
-		}
+				possibleHexes.insert(hex);
 	}
-	int targetsOnLevel[4] = {4, 4, 5, 5};
+	static const std::array<int, 4> targetsOnLevel = {4, 4, 5, 5};
 
-	BattleHex lightningHex = ctx.destination;
-	for(int i = 0; i < targetsOnLevel[ctx.schoolLvl]; ++i)
+	BattleHex lightningHex = destination;
+	for(int i = 0; i < targetsOnLevel.at(spellLvl); ++i)
 	{
 		auto stack = cb->battleGetStackByPos(lightningHex, true);
 		if(!stack)
 			break;
 		res.push_back(stack);
 		for(auto hex : stack->getHexes())
-		{
 			possibleHexes.erase(hex); //can't hit same stack twice
-		}
 		if(possibleHexes.empty()) //not enough targets
 			break;
 		lightningHex = BattleHex::getClosestTile(stack->side, lightningHex, possibleHexes);
@@ -137,12 +130,10 @@ CloneMechanics::CloneMechanics(const CSpell * s):
 
 void CloneMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
 {
-	const CStack * clonedStack = nullptr;
-	if(ctx.attackedCres.size())
-		clonedStack = *ctx.attackedCres.begin();
+	const CStack * clonedStack = vstd::frontOrNull(ctx.attackedCres);
 	if(!clonedStack)
 	{
-		env->complain ("No target stack to clone!");
+		env->complain("No target stack to clone!");
 		return;
 	}
 
@@ -457,18 +448,19 @@ ObstacleMechanics::ObstacleMechanics(const CSpell * s):
 {
 }
 
-ESpellCastProblem::ESpellCastProblem ObstacleMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+ESpellCastProblem::ESpellCastProblem ObstacleMechanics::canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const
 {
-	const auto side = cb->playerToSide(ctx.caster->getOwner());
+	const auto side = cb->playerToSide(caster->getOwner());
+	const auto level = caster->getSpellSchoolLevel(owner);
 	if(!side)
 		return ESpellCastProblem::INVALID;
 
 	bool hexesOutsideBattlefield = false;
 
-	auto tilesThatMustBeClear = owner->rangeInHexes(ctx.destination, ctx.schoolLvl, side.get(), &hexesOutsideBattlefield);
-
+	auto tilesThatMustBeClear = owner->rangeInHexes(destination, level, side.get(), &hexesOutsideBattlefield);
+	const CSpell::TargetInfo ti(owner, level, mode);
 	for(const BattleHex & hex : tilesThatMustBeClear)
-		if(!isHexAviable(cb, hex, ctx.ti.clearAffected))
+		if(!isHexAviable(cb, hex, ti.clearAffected))
 			return ESpellCastProblem::NO_APPROPRIATE_TARGET;
 
 	if(hexesOutsideBattlefield)
@@ -757,14 +749,16 @@ ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCast(const CB
 	return ESpellCastProblem::NO_APPROPRIATE_TARGET;
 }
 
-ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const
 {
-	auto obstacles = cb->battleGetAllObstaclesOnPos(ctx.destination, false);
+	const auto level = caster->getSpellSchoolLevel(owner);
+	auto obstacles = cb->battleGetAllObstaclesOnPos(destination, false);
 	if(!obstacles.empty())
+	{
 		for(auto & i : obstacles)
-			if(canRemove(i.get(), ctx.schoolLvl))
+			if(canRemove(i.get(), level))
 				return ESpellCastProblem::OK;
-
+	}
 	return ESpellCastProblem::NO_APPROPRIATE_TARGET;
 }
 
@@ -914,12 +908,14 @@ SpecialRisingSpellMechanics::SpecialRisingSpellMechanics(const CSpell * s):
 {
 }
 
-ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const
 {
-	auto mainFilter = [cb, ctx, this](const CStack * s) -> bool
+	const auto level = caster->getSpellSchoolLevel(owner);
+	const CSpell::TargetInfo ti(owner, level, mode);
+	auto mainFilter = [cb, ti, caster, destination, this](const CStack * s) -> bool
 	{
-		const bool ownerMatches = !ctx.ti.smart || cb->battleMatchOwner(ctx.caster->getOwner(), s, owner->getPositiveness());
-		return ownerMatches && s->coversPos(ctx.destination) && ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s);
+		const bool ownerMatches = !ti.smart || cb->battleMatchOwner(caster->getOwner(), s, owner->getPositiveness());
+		return ownerMatches && s->coversPos(destination) && ESpellCastProblem::OK == owner->isImmuneByStack(caster, s);
 	};
 	//find alive possible target
 	const CStack * stackToHeal = cb->getStackIf([mainFilter](const CStack * s)

+ 4 - 4
lib/spells/BattleSpellMechanics.h

@@ -38,7 +38,7 @@ class DLL_LINKAGE ChainLightningMechanics : public DefaultSpellMechanics
 public:
 	ChainLightningMechanics(const CSpell * s);
 protected:
-	std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
+	std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const override;
 };
 
 class DLL_LINKAGE CloneMechanics : public DefaultSpellMechanics
@@ -93,7 +93,7 @@ class DLL_LINKAGE ObstacleMechanics : public SpecialSpellMechanics
 {
 public:
 	ObstacleMechanics(const CSpell * s);
-	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
+	ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const override;
 protected:
 	static bool isHexAviable(const CBattleInfoCallback * cb, const BattleHex & hex, const bool mustBeClear);
 	void placeObstacle(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, const BattleHex & pos) const;
@@ -159,7 +159,7 @@ class DLL_LINKAGE RemoveObstacleMechanics : public SpecialSpellMechanics
 public:
 	RemoveObstacleMechanics(const CSpell * s);
 	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const override;
-	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
+	ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const override;
 	bool requiresCreatureTarget() const	override;
 protected:
 	void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
@@ -192,8 +192,8 @@ class DLL_LINKAGE SpecialRisingSpellMechanics : public RisingSpellMechanics
 {
 public:
 	SpecialRisingSpellMechanics(const CSpell * s);
-	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
+	ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const override;
 };
 
 class DLL_LINKAGE SummonMechanics : public SpecialSpellMechanics

+ 32 - 36
lib/spells/CDefaultSpellMechanics.cpp

@@ -630,36 +630,45 @@ std::vector<BattleHex> DefaultSpellMechanics::rangeInHexes(BattleHex centralHex,
 	return ret;
 }
 
-std::vector<const CStack *> DefaultSpellMechanics::getAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+std::vector<const CStack *> DefaultSpellMechanics::getAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
 {
-	std::vector<const CStack *> attackedCres = calculateAffectedStacks(cb, ctx);
-	handleImmunities(cb, ctx, attackedCres);
-	return attackedCres;
+	std::vector<const CStack *> result = calculateAffectedStacks(cb, mode, caster, spellLvl, destination);
+	CSpell::TargetInfo ti(owner, spellLvl, mode);
+
+	auto predicate = [&, this](const CStack * s)->bool
+	{
+		const bool hitDirectly = ti.alwaysHitDirectly && s->coversPos(destination);
+		const bool immune = (ESpellCastProblem::OK != owner->isImmuneByStack(caster, s));
+		return !hitDirectly && immune;
+	};
+	vstd::erase_if(result, predicate);
+	return result;
 }
 
-std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
 {
 	std::set<const CStack *> attackedCres;//std::set to exclude multiple occurrences of two hex creatures
+	CSpell::TargetInfo ti(owner, spellLvl, mode);
 
-	const auto side = cb->playerToSide(ctx.caster->getOwner());
+	const auto side = cb->playerToSide(caster->getOwner());
 	if(!side)
 		return std::vector<const CStack *>();
-	auto attackedHexes = rangeInHexes(ctx.destination, ctx.schoolLvl, side.get());
+	auto attackedHexes = rangeInHexes(destination, spellLvl, side.get());
 
 	//hackfix for banned creature massive spells
-	if(!ctx.ti.massive && owner->getLevelInfo(ctx.schoolLvl).range == "X")
-		attackedHexes.push_back(ctx.destination);
+	if(!ti.massive && owner->getLevelInfo(spellLvl).range == "X")
+		attackedHexes.push_back(destination);
 
-	auto mainFilter = [=](const CStack * s)
+	auto mainFilter = [&](const CStack * s)
 	{
-		const bool ownerMatches = cb->battleMatchOwner(ctx.caster->getOwner(), s, owner->getPositiveness());
-		const bool validTarget = s->isValidTarget(!ctx.ti.onlyAlive); //todo: this should be handled by spell class
-		const bool positivenessFlag = !ctx.ti.smart || ownerMatches;
+		const bool ownerMatches = cb->battleMatchOwner(caster->getOwner(), s, owner->getPositiveness());
+		const bool validTarget = s->isValidTarget(!ti.onlyAlive); //todo: this should be handled by spell class
+		const bool positivenessFlag = !ti.smart || ownerMatches;
 
 		return positivenessFlag && validTarget;
 	};
 
-	if(ctx.ti.type == CSpell::CREATURE && attackedHexes.size() == 1)
+	if(ti.type == CSpell::CREATURE && attackedHexes.size() == 1)
 	{
 		//for single target spells we must select one target. Alive stack is preferred (issue #1763)
 
@@ -680,11 +689,9 @@ std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const
 		}
 
 		if(attackedCres.empty() && !stacks.empty())
-		{
 			attackedCres.insert(stacks.front());
-		}
 	}
-	else if(ctx.ti.massive)
+	else if(ti.massive)
 	{
 		TStacks stacks = cb->battleGetStacksIf(mainFilter);
 		for(auto stack : stacks)
@@ -694,7 +701,7 @@ std::vector<const CStack *> DefaultSpellMechanics::calculateAffectedStacks(const
 	{
 		for(BattleHex hex : attackedHexes)
 		{
-			if(const CStack * st = cb->battleGetStackByPos(hex, ctx.ti.onlyAlive))
+			if(const CStack * st = cb->battleGetStackByPos(hex, ti.onlyAlive))
 				if(mainFilter(st))
 					attackedCres.insert(st);
 		}
@@ -712,18 +719,19 @@ ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBat
 	return ESpellCastProblem::OK;
 }
 
-ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const
 {
-	if(ctx.mode == ECastingMode::CREATURE_ACTIVE_CASTING || ctx.mode == ECastingMode::HERO_CASTING)
+	if(mode == ECastingMode::CREATURE_ACTIVE_CASTING || mode == ECastingMode::HERO_CASTING)
 	{
-		std::vector<const CStack *> affected = getAffectedStacks(cb, ctx);
+		const auto level = caster->getSpellSchoolLevel(owner);
+		std::vector<const CStack *> affected = getAffectedStacks(cb, mode, caster, level, destination);
 
 		//allow to cast spell if it affects at least one smart target
 		bool targetExists = false;
 
 		for(const CStack * stack : affected)
 		{
-			targetExists = cb->battleMatchOwner(ctx.caster->getOwner(), stack, owner->getPositiveness());
+			targetExists = cb->battleMatchOwner(caster->getOwner(), stack, owner->getPositiveness());
 			if(targetExists)
 				break;
 		}
@@ -778,18 +786,6 @@ bool DefaultSpellMechanics::canDispell(const IBonusBearer * obj, const CSelector
 	return obj->hasBonus(selector.And(dispellSelector), Selector::all, cachingStr);
 }
 
-void DefaultSpellMechanics::handleImmunities(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx, std::vector<const CStack*> & stacks) const
-{
-	auto predicate = [&, this](const CStack * s)->bool
-	{
-		bool hitDirectly = ctx.ti.alwaysHitDirectly && s->coversPos(ctx.destination);
-		bool notImmune = (ESpellCastProblem::OK == owner->isImmuneByStack(ctx.caster, s));
-
-		return !(hitDirectly || notImmune);
-	};
-	vstd::erase_if(stacks, predicate);
-}
-
 void DefaultSpellMechanics::handleMagicMirror(const SpellCastEnvironment * env, SpellCastContext & ctx, std::vector <const CStack*> & reflected) const
 {
 	//reflection is applied only to negative spells
@@ -865,14 +861,14 @@ SpecialSpellMechanics::SpecialSpellMechanics(const CSpell * s):
 {
 }
 
-ESpellCastProblem::ESpellCastProblem SpecialSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+ESpellCastProblem::ESpellCastProblem SpecialSpellMechanics::canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const
 {
 	//no problems by default
 	//common problems handled by CSpell
 	return ESpellCastProblem::OK;
 }
 
-std::vector<const CStack *> SpecialSpellMechanics::calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const
+std::vector<const CStack *> SpecialSpellMechanics::calculateAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
 {
 	return std::vector<const CStack *>();
 }

+ 5 - 6
lib/spells/CDefaultSpellMechanics.h

@@ -48,10 +48,10 @@ public:
 	DefaultSpellMechanics(const CSpell * s);
 
 	std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const override;
-	std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override final;
+	std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const override final;
 
 	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const override;
-	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
+	ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const override;
 
 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
 
@@ -70,7 +70,7 @@ public:
 protected:
 	virtual void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const;
 
-	virtual std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const;
+	virtual std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const;
 
 protected:
 	void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
@@ -81,7 +81,6 @@ protected:
 private:
 	void cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const;
 
-	void handleImmunities(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx, std::vector<const CStack *> & stacks) const;
 	void handleMagicMirror(const SpellCastEnvironment * env, SpellCastContext & ctx, std::vector <const CStack*> & reflected) const;
 	void handleResistance(const SpellCastEnvironment * env, SpellCastContext & ctx) const;
 
@@ -96,7 +95,7 @@ class DLL_LINKAGE SpecialSpellMechanics : public DefaultSpellMechanics
 public:
 	SpecialSpellMechanics(const CSpell * s);
 
-	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
+	ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const override;
 protected:
-	std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const override;
+	std::vector<const CStack *> calculateAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const override;
 };

+ 2 - 5
lib/spells/CSpellHandler.cpp

@@ -243,8 +243,7 @@ std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl,
 
 std::vector<const CStack *> CSpell::getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const
 {
-	SpellTargetingContext ctx(this, mode, caster, spellLvl, destination);
-	return mechanics->getAffectedStacks(cb, ctx);
+	return mechanics->getAffectedStacks(cb, mode, caster, spellLvl, destination);
 }
 
 CSpell::ETargetType CSpell::getTargetType() const
@@ -405,9 +404,7 @@ ESpellCastProblem::ESpellCastProblem CSpell::canBeCastAt(const CBattleInfoCallba
 	if(problem != ESpellCastProblem::OK)
 		return problem;
 
-	SpellTargetingContext ctx(this, mode, caster, caster->getSpellSchoolLevel(this), destination);
-
-	return mechanics->canBeCast(cb, ctx);
+	return mechanics->canBeCastAt(cb, mode, caster, destination);
 }
 
 int CSpell::adjustRawDamage(const ISpellCaster * caster, const CStack * affectedCreature, int rawDamage) const

+ 2 - 15
lib/spells/ISpellMechanics.h

@@ -93,19 +93,6 @@ private:
 	int effectValue;
 };
 
-struct DLL_LINKAGE SpellTargetingContext
-{
-	CSpell::TargetInfo ti;
-	ECastingMode::ECastingMode mode;
-	BattleHex destination;
-	const ISpellCaster * caster;
-	int schoolLvl;
-
-	SpellTargetingContext(const CSpell * s, ECastingMode::ECastingMode mode_, const ISpellCaster * caster_, int schoolLvl_, BattleHex destination_)
-		: ti(s,schoolLvl_, mode_), mode(mode_), destination(destination_), caster(caster_), schoolLvl(schoolLvl_)
-	{};
-};
-
 class DLL_LINKAGE ISpellMechanics
 {
 public:
@@ -113,11 +100,11 @@ public:
 	virtual ~ISpellMechanics(){};
 
 	virtual std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const = 0;
-	virtual std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const = 0;
+	virtual std::vector<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, int spellLvl, BattleHex destination) const = 0;
 
 	virtual ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const = 0;
 
-	virtual ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx) const = 0;
+	virtual ESpellCastProblem::ESpellCastProblem canBeCastAt(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster, BattleHex destination) const = 0;
 
 	virtual ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const = 0;