1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-28 03:57:02 +02:00

Factored out battleCanCastThisSpellHere

This commit is contained in:
AlexVinS 2016-03-04 16:42:55 +03:00
parent 0d5eaa1183
commit b09f150e7b
5 changed files with 46 additions and 48 deletions

View File

@ -1773,38 +1773,12 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpellHere: no spellcaster."; logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpellHere: no spellcaster.";
return ESpellCastProblem::INVALID; return ESpellCastProblem::INVALID;
} }
const PlayerColor player = caster->getOwner();
ESpellCastProblem::ESpellCastProblem problem = battleCanCastThisSpell(caster, spell, mode); ESpellCastProblem::ESpellCastProblem problem = battleCanCastThisSpell(caster, spell, mode);
if(problem != ESpellCastProblem::OK) if(problem != ESpellCastProblem::OK)
return problem; return problem;
problem = spell->canBeCastAt(this, caster, mode, dest); return 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);
} }
const CStack * CBattleInfoCallback::getStackIf(std::function<bool(const CStack*)> pred) const const CStack * CBattleInfoCallback::getStackIf(std::function<bool(const CStack*)> pred) const

View File

@ -573,12 +573,6 @@ bool RemoveObstacleMechanics::canRemove(const CObstacleInstance * obstacle, cons
} }
///RisingSpellMechanics ///RisingSpellMechanics
ESpellCastProblem::ESpellCastProblem RisingSpellMechanics::canBeCast(const SpellTargetingContext & ctx) const
{
//todo: RisingSpellMechanics::canBeCast
return ESpellCastProblem::OK;
}
HealingSpellMechanics::EHealLevel RisingSpellMechanics::getHealLevel(int effectLevel) const HealingSpellMechanics::EHealLevel RisingSpellMechanics::getHealLevel(int effectLevel) const
{ {
//this may be even distinct class //this may be even distinct class
@ -673,6 +667,21 @@ int SacrificeMechanics::calculateHealedHP(const SpellCastEnvironment* env, const
} }
///SpecialRisingSpellMechanics ///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 ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
{ {
// following does apply to resurrect and animate dead(?) only // following does apply to resurrect and animate dead(?) only

View File

@ -125,7 +125,7 @@ class DLL_LINKAGE RisingSpellMechanics : public HealingSpellMechanics
{ {
public: public:
RisingSpellMechanics(CSpell * s): HealingSpellMechanics(s){}; RisingSpellMechanics(CSpell * s): HealingSpellMechanics(s){};
ESpellCastProblem::ESpellCastProblem canBeCast(const SpellTargetingContext & ctx) const override;
EHealLevel getHealLevel(int effectLevel) 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; 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 class DLL_LINKAGE SpecialRisingSpellMechanics : public RisingSpellMechanics
{ {
public: public:
SpecialRisingSpellMechanics(CSpell * s): RisingSpellMechanics(s){}; SpecialRisingSpellMechanics(CSpell * s): RisingSpellMechanics(s){};
ESpellCastProblem::ESpellCastProblem canBeCast(const SpellTargetingContext & ctx) const override;
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override; ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
}; };

View File

@ -222,11 +222,6 @@ bool CSpell::isNeutral() const
return positiveness == NEUTRAL; return positiveness == NEUTRAL;
} }
bool CSpell::isHealingSpell() const
{
return isRisingSpell() || (id == SpellID::CURE);
}
bool CSpell::isRisingSpell() const bool CSpell::isRisingSpell() const
{ {
return isRising; 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 ESpellCastProblem::ESpellCastProblem CSpell::canBeCastAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
{ {
//todo: CSpell::canBeCastAt check common problems
ISpellMechanics::SpellTargetingContext ctx(this, cb, mode, caster, caster->getSpellSchoolLevel(this), destination); ISpellMechanics::SpellTargetingContext ctx(this, cb, mode, caster, caster->getSpellSchoolLevel(this), destination);
return mechanics->canBeCast(ctx);
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 isImmuneAt(cb, caster, mode, destination);
} }
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const

View File

@ -204,7 +204,6 @@ public:
bool isNeutral() const; bool isNeutral() const;
bool isDamageSpell() const; bool isDamageSpell() const;
bool isHealingSpell() const;
bool isRisingSpell() const; bool isRisingSpell() const;
bool isOffensiveSpell() 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. ///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; 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. ///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; ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const;
public: public:
@ -303,6 +299,10 @@ public://internal, for use only by Mechanics classes
ESpellCastProblem::ESpellCastProblem internalIsImmune(const ISpellCaster * caster, const CStack *obj) const; ESpellCastProblem::ESpellCastProblem internalIsImmune(const ISpellCaster * caster, const CStack *obj) const;
private: 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 setIsOffensive(const bool val);
void setIsRising(const bool val); void setIsRising(const bool val);