1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +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.";
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

View File

@ -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

View File

@ -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;
};

View File

@ -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
{
//todo: CSpell::canBeCastAt check common problems
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

View File

@ -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);