diff --git a/lib/spells/BattleSpellMechanics.cpp b/lib/spells/BattleSpellMechanics.cpp index 6a6a62172..2a80762ce 100644 --- a/lib/spells/BattleSpellMechanics.cpp +++ b/lib/spells/BattleSpellMechanics.cpp @@ -341,8 +341,14 @@ void EarthquakeMechanics::applyBattleEffects(const SpellCastEnvironment * env, c env->sendAndApply(&ca); } -ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const +ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const { + if(mode == ECastingMode::AFTER_ATTACK_CASTING || mode == ECastingMode::SPELL_LIKE_ATTACK || mode == ECastingMode::MAGIC_MIRROR) + { + logGlobal->warn("Invalid spell cast attempt: spell %s, mode %d", owner->name, mode); //should not even try to do it + return ESpellCastProblem::INVALID; + } + if(nullptr == cb->battleGetDefendedTown()) { return ESpellCastProblem::NO_APPROPRIATE_TARGET; @@ -592,8 +598,14 @@ void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * en env->complain("There's no obstacle to remove!"); } -ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const +ESpellCastProblem::ESpellCastProblem RemoveObstacleMechanics::canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const { + if(mode == ECastingMode::AFTER_ATTACK_CASTING || mode == ECastingMode::SPELL_LIKE_ATTACK || mode == ECastingMode::MAGIC_MIRROR) + { + logGlobal->warn("Invalid spell cast attempt: spell %s, mode %d", owner->name, mode); //should not even try to do it + return ESpellCastProblem::INVALID; + } + const int spellLevel = caster->getSpellSchoolLevel(owner); for(auto obstacle : cb->battleGetAllObstacles()) @@ -653,8 +665,14 @@ HealingSpellMechanics::EHealLevel RisingSpellMechanics::getHealLevel(int effectL } ///SacrificeMechanics -ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const +ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const { + if(mode == ECastingMode::AFTER_ATTACK_CASTING || mode == ECastingMode::SPELL_LIKE_ATTACK || mode == ECastingMode::MAGIC_MIRROR) + { + logGlobal->warn("Invalid spell cast attempt: spell %s, mode %d", owner->name, mode); //should not even try to do it + return ESpellCastProblem::INVALID; + } + // for sacrifice we have to check for 2 targets (one dead to resurrect and one living to destroy) bool targetExists = false; @@ -767,8 +785,14 @@ ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStac } ///SummonMechanics -ESpellCastProblem::ESpellCastProblem SummonMechanics::canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const +ESpellCastProblem::ESpellCastProblem SummonMechanics::canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const { + if(mode == ECastingMode::AFTER_ATTACK_CASTING || mode == ECastingMode::SPELL_LIKE_ATTACK || mode == ECastingMode::MAGIC_MIRROR) + { + logGlobal->warn("Invalid spell cast attempt: spell %s, mode %d", owner->name, mode); //should not even try to do it + return ESpellCastProblem::INVALID; + } + //check if there are summoned elementals of other type auto otherSummoned = cb->battleGetStacksIf([caster, this](const CStack * st) @@ -848,4 +872,13 @@ void TeleportMechanics::applyBattleEffects(const SpellCastEnvironment * env, con } } +ESpellCastProblem::ESpellCastProblem TeleportMechanics::canBeCast(const CBattleInfoCallback* cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const +{ + if(mode == ECastingMode::AFTER_ATTACK_CASTING || mode == ECastingMode::SPELL_LIKE_ATTACK || mode == ECastingMode::MAGIC_MIRROR) + { + logGlobal->warn("Invalid spell cast attempt: spell %s, mode %d", owner->name, mode); //should not even try to do it + return ESpellCastProblem::INVALID; + } + return DefaultSpellMechanics::canBeCast(cb, mode, caster); +} diff --git a/lib/spells/BattleSpellMechanics.h b/lib/spells/BattleSpellMechanics.h index 8c2064f42..acf12f3b6 100644 --- a/lib/spells/BattleSpellMechanics.h +++ b/lib/spells/BattleSpellMechanics.h @@ -85,7 +85,7 @@ class DLL_LINKAGE EarthquakeMechanics : public SpecialSpellMechanics { public: EarthquakeMechanics(CSpell * s): SpecialSpellMechanics(s){}; - ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const override; + ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const override; bool requiresCreatureTarget() const override; protected: void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override; @@ -165,7 +165,7 @@ class DLL_LINKAGE RemoveObstacleMechanics : public SpecialSpellMechanics { public: RemoveObstacleMechanics(CSpell * s): SpecialSpellMechanics(s){}; - ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const override; + 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; bool requiresCreatureTarget() const override; protected: @@ -188,7 +188,7 @@ class DLL_LINKAGE SacrificeMechanics : public RisingSpellMechanics public: SacrificeMechanics(CSpell * s): RisingSpellMechanics(s){}; - ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const override; + ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const override; bool requiresCreatureTarget() const override; protected: void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override; @@ -209,7 +209,7 @@ class DLL_LINKAGE SummonMechanics : public SpecialSpellMechanics public: SummonMechanics(CSpell * s, CreatureID cre): SpecialSpellMechanics(s), creatureToSummon(cre){}; - ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const override; + ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const override; bool requiresCreatureTarget() const override; protected: void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override; @@ -221,6 +221,8 @@ class DLL_LINKAGE TeleportMechanics: public DefaultSpellMechanics { public: TeleportMechanics(CSpell * s): DefaultSpellMechanics(s){}; + + ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const override; protected: void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override; }; diff --git a/lib/spells/CDefaultSpellMechanics.cpp b/lib/spells/CDefaultSpellMechanics.cpp index 156fe55ef..2d48b8cd3 100644 --- a/lib/spells/CDefaultSpellMechanics.cpp +++ b/lib/spells/CDefaultSpellMechanics.cpp @@ -700,7 +700,7 @@ std::vector DefaultSpellMechanics::calculateAffectedStacks(const return res; } -ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const +ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBattleInfoCallback * cb, const ECastingMode::ECastingMode mode, const ISpellCaster * caster) const { //no problems by default, this method is for spell-specific problems return ESpellCastProblem::OK; diff --git a/lib/spells/CDefaultSpellMechanics.h b/lib/spells/CDefaultSpellMechanics.h index 4f097bfca..38914ff17 100644 --- a/lib/spells/CDefaultSpellMechanics.h +++ b/lib/spells/CDefaultSpellMechanics.h @@ -50,7 +50,7 @@ public: std::vector rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const override; std::vector getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const override final; - ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) const override; + 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 isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override; diff --git a/lib/spells/CSpellHandler.cpp b/lib/spells/CSpellHandler.cpp index 16c601c3e..c33d523fd 100644 --- a/lib/spells/CSpellHandler.cpp +++ b/lib/spells/CSpellHandler.cpp @@ -151,7 +151,7 @@ ui32 CSpell::calculateDamage(const ISpellCaster * caster, const CStack * affecte ESpellCastProblem::ESpellCastProblem CSpell::canBeCast(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, const ISpellCaster * caster) const { - const ESpellCastProblem::ESpellCastProblem generalProblem = mechanics->canBeCast(cb, caster); + const ESpellCastProblem::ESpellCastProblem generalProblem = mechanics->canBeCast(cb, mode, caster); if(generalProblem != ESpellCastProblem::OK) return generalProblem; diff --git a/lib/spells/ISpellMechanics.h b/lib/spells/ISpellMechanics.h index f7463344c..11aafe856 100644 --- a/lib/spells/ISpellMechanics.h +++ b/lib/spells/ISpellMechanics.h @@ -109,7 +109,7 @@ public: virtual std::vector rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const = 0; virtual std::vector getAffectedStacks(const CBattleInfoCallback * cb, SpellTargetingContext & ctx) const = 0; - virtual ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, const ISpellCaster * caster) 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;