mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Use ISpellCaster in battle callback
This commit is contained in:
parent
75c2566410
commit
70d9be8447
@ -2470,10 +2470,16 @@ bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CSta
|
||||
|
||||
if (sp)
|
||||
{
|
||||
if (creatureCasting)
|
||||
isCastingPossible = (curInt->cb->battleCanCreatureCastThisSpell (sp, myNumber) == ESpellCastProblem::OK);
|
||||
const ISpellCaster * caster = creatureCasting ? dynamic_cast<const ISpellCaster *>(sactive) : dynamic_cast<const ISpellCaster *>(curInt->cb->battleGetMyHero());
|
||||
if(caster == nullptr)
|
||||
{
|
||||
isCastingPossible = false;//just in case
|
||||
}
|
||||
else
|
||||
isCastingPossible = (curInt->cb->battleCanCastThisSpell (sp, myNumber) == ESpellCastProblem::OK);
|
||||
{
|
||||
const ECastingMode::ECastingMode mode = creatureCasting ? ECastingMode::CREATURE_ACTIVE_CASTING : ECastingMode::HERO_CASTING;
|
||||
isCastingPossible = (curInt->cb->battleCanCastThisSpellHere(caster, sp, mode, myNumber) == ESpellCastProblem::OK);
|
||||
}
|
||||
}
|
||||
else
|
||||
isCastingPossible = false;
|
||||
|
@ -1592,9 +1592,15 @@ std::vector<BattleHex> CBattleInfoCallback::getAttackableBattleHexes() const
|
||||
return attackableBattleHexes;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell( PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode ) const
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
if(caster == nullptr)
|
||||
{
|
||||
logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpell: no spellcaster.";
|
||||
return ESpellCastProblem::INVALID;
|
||||
}
|
||||
const PlayerColor player = caster->getOwner();
|
||||
const ui8 side = playerToSide(player);
|
||||
if(!battleDoWeKnowAbout(side))
|
||||
return ESpellCastProblem::INVALID;
|
||||
@ -1603,16 +1609,11 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
if(genProblem != ESpellCastProblem::OK)
|
||||
return genProblem;
|
||||
|
||||
//Casting hero, set only if he is an actual caster.
|
||||
const CGHeroInstance *castingHero = mode == ECastingMode::HERO_CASTING
|
||||
? battleGetFightingHero(side)
|
||||
: nullptr;
|
||||
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case ECastingMode::HERO_CASTING:
|
||||
{
|
||||
const CGHeroInstance * castingHero = dynamic_cast<const CGHeroInstance *>(caster);//todo: unify hero|creature spell cost
|
||||
assert(castingHero);
|
||||
if(!castingHero->canCastThisSpell(spell))
|
||||
return ESpellCastProblem::HERO_DOESNT_KNOW_SPELL;
|
||||
@ -1622,7 +1623,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(!spell->combatSpell)
|
||||
return ESpellCastProblem::ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL;
|
||||
|
||||
@ -1639,7 +1639,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
auto stacks = spell->isNegative() ? battleAliveStacks(!side) : battleAliveStacks();
|
||||
for(auto stack : stacks)
|
||||
{
|
||||
if(ESpellCastProblem::OK == spell->isImmuneByStack(castingHero, stack))
|
||||
if(ESpellCastProblem::OK == spell->isImmuneByStack(caster, stack))
|
||||
{
|
||||
allStacksImmune = false;
|
||||
break;
|
||||
@ -1659,7 +1659,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
case CSpell::CREATURE:
|
||||
if(mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
const CGHeroInstance * caster = battleGetFightingHero(side);
|
||||
const CSpell::TargetInfo ti(spell, caster->getSpellSchoolLevel(spell));
|
||||
bool targetExists = false;
|
||||
|
||||
@ -1777,10 +1776,16 @@ ui32 CBattleInfoCallback::battleGetSpellCost(const CSpell * sp, const CGHeroInst
|
||||
return ret - manaReduction + manaIncrease;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpellHere( PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest ) const
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ESpellCastProblem::ESpellCastProblem moreGeneralProblem = battleCanCastThisSpell(player, spell, mode);
|
||||
if(caster == nullptr)
|
||||
{
|
||||
logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpellHere: no spellcaster.";
|
||||
return ESpellCastProblem::INVALID;
|
||||
}
|
||||
const PlayerColor player = caster->getOwner();
|
||||
ESpellCastProblem::ESpellCastProblem moreGeneralProblem = battleCanCastThisSpell(caster, spell, mode);
|
||||
if(moreGeneralProblem != ESpellCastProblem::OK)
|
||||
return moreGeneralProblem;
|
||||
|
||||
@ -1843,11 +1848,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
if(spell->isPositive() && aliveStack->owner != player)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
|
||||
const CGHeroInstance * caster = nullptr;
|
||||
if (mode == ECastingMode::HERO_CASTING)
|
||||
caster = battleGetFightingHero(playerToSide(player));
|
||||
|
||||
return spell->isImmuneAt(this, caster, mode, dest);
|
||||
}
|
||||
|
||||
@ -1930,7 +1930,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co
|
||||
{
|
||||
if (subject->hasBonusFrom(Bonus::SPELL_EFFECT, spellID)
|
||||
//TODO: this ability has special limitations
|
||||
|| battleCanCastThisSpellHere(subject->owner, spellID.toSpell(), ECastingMode::CREATURE_ACTIVE_CASTING, subject->position) != ESpellCastProblem::OK)
|
||||
|| battleCanCastThisSpellHere(subject, spellID.toSpell(), ECastingMode::CREATURE_ACTIVE_CASTING, subject->position) != ESpellCastProblem::OK)
|
||||
continue;
|
||||
|
||||
switch (spellID)
|
||||
@ -2168,21 +2168,12 @@ ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCastThisSpe
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
return CBattleInfoCallback::battleCanCastThisSpell(*player, spell, ECastingMode::HERO_CASTING);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCastThisSpell(const CSpell * spell, BattleHex destination) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
return battleCanCastThisSpellHere(*player, spell, ECastingMode::HERO_CASTING, destination);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
return battleCanCastThisSpellHere(*player, spell, ECastingMode::CREATURE_ACTIVE_CASTING, destination);
|
||||
const ISpellCaster * hero = battleGetMyHero();
|
||||
if(hero == nullptr)
|
||||
return ESpellCastProblem::INVALID;
|
||||
else
|
||||
return CBattleInfoCallback::battleCanCastThisSpell(hero, spell, ECastingMode::HERO_CASTING);
|
||||
}
|
||||
|
||||
bool CPlayerBattleCallback::battleCanFlee() const
|
||||
|
@ -15,6 +15,7 @@ class CGameState;
|
||||
class CGTownInstance;
|
||||
class CGHeroInstance;
|
||||
class CStack;
|
||||
class ISpellCaster;
|
||||
class CSpell;
|
||||
struct BattleInfo;
|
||||
struct CObstacleInstance;
|
||||
@ -280,9 +281,8 @@ public:
|
||||
si8 battleMaxSpellLevel(ui8 side) const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
|
||||
ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastSpell(PlayerColor player, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode
|
||||
std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const;
|
||||
|
||||
SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
|
||||
@ -326,8 +326,7 @@ public:
|
||||
bool battleCanFlee() const; //returns true if caller can flee from the battle
|
||||
TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) const; //returns stacks on battlefield
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) const; //determines if given spell can be cast (and returns problem description)
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell, BattleHex destination) const; //if hero can cast spell here
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here
|
||||
|
||||
int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible
|
||||
|
||||
bool battleCanCastSpell(ESpellCastProblem::ESpellCastProblem *outProblem = nullptr) const; //returns true, if caller can cast a spell. If not, if pointer is given via arg, the reason will be written.
|
||||
|
@ -139,8 +139,6 @@ ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const ISpel
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
if(obj->cloneID != -1)
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
//TODO: how about stacks casting Clone?
|
||||
//currently Clone cast by stack is assumed Expert level
|
||||
ui8 schoolLevel;
|
||||
if(caster)
|
||||
{
|
||||
@ -148,7 +146,7 @@ ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const ISpel
|
||||
}
|
||||
else
|
||||
{
|
||||
schoolLevel = 3;
|
||||
schoolLevel = 3;//todo: remove
|
||||
}
|
||||
|
||||
if(schoolLevel < 3)
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "../CModHandler.h"
|
||||
#include "../StringConstants.h"
|
||||
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../BattleState.h"
|
||||
#include "../CBattleCallback.h"
|
||||
#include "../CGameState.h" //todo: remove
|
||||
@ -303,7 +302,7 @@ void CSpell::getEffects(std::vector<Bonus> & lst, const int level) const
|
||||
}
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const CGHeroInstance * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
|
||||
{
|
||||
// Get all stacks at destination hex. only alive if not rising spell
|
||||
TStacks stacks = cb->battleGetStacksIf([=](const CStack * s){
|
||||
@ -385,9 +384,8 @@ int CSpell::adjustRawDamage(const ISpellCaster * caster, const CStack * affected
|
||||
ret /= 100;
|
||||
}
|
||||
}
|
||||
|
||||
ret = caster->getSpellBonus(this, ret, affectedCreature);
|
||||
|
||||
if(caster != nullptr)
|
||||
ret = caster->getSpellBonus(this, ret, affectedCreature);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -213,8 +213,6 @@ public:
|
||||
bool hasEffects() const;
|
||||
void getEffects(std::vector<Bonus> &lst, const int level) const;
|
||||
|
||||
///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 isImmuneAt(const CBattleInfoCallback * cb, const CGHeroInstance * caster, ECastingMode::ECastingMode mode, BattleHex destination) const;
|
||||
|
||||
///calculate spell damage on stack taking caster`s secondary skills and affectedCreature`s bonuses into account
|
||||
ui32 calculateDamage(const ISpellCaster * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const;
|
||||
@ -271,6 +269,9 @@ public:
|
||||
///Checks general but spell-specific problems for all casting modes. Use only during battle.
|
||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const;
|
||||
|
||||
///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 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:
|
||||
|
@ -4073,7 +4073,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
parameters.mode = ECastingMode::HERO_CASTING;
|
||||
parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false);
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem escp = gs->curB->battleCanCastThisSpell(h->tempOwner, s, ECastingMode::HERO_CASTING);
|
||||
ESpellCastProblem::ESpellCastProblem escp = gs->curB->battleCanCastThisSpell(h, s, ECastingMode::HERO_CASTING);//todo: should we check aimed cast(battleCanCastThisSpellHere)?
|
||||
if(escp != ESpellCastProblem::OK)
|
||||
{
|
||||
logGlobal->warnStream() << "Spell cannot be cast!";
|
||||
@ -4217,7 +4217,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
||||
const CSpell * spell = SpellID(spellID).toSpell();
|
||||
bl.remove_if([&bonus](Bonus * b){return b==bonus;});
|
||||
|
||||
if (gs->curB->battleCanCastThisSpell(st->owner, spell, ECastingMode::ENCHANTER_CASTING) == ESpellCastProblem::OK)
|
||||
if (gs->curB->battleCanCastThisSpell(st, spell, ECastingMode::ENCHANTER_CASTING) == ESpellCastProblem::OK)
|
||||
{
|
||||
BattleSpellCastParameters parameters(gs->curB, st, spell);
|
||||
parameters.spellLvl = bonus->val;
|
||||
@ -4277,7 +4277,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
|
||||
//helper info
|
||||
const SpellCreatedObstacle *spellObstacle = dynamic_cast<const SpellCreatedObstacle*>(&obstacle); //not nice but we may need spell params
|
||||
const ui8 side = !curStack->attackerOwned; //if enemy is defending (false = 0), side of enemy hero is 1 (true)
|
||||
const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side);
|
||||
const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side);//FIXME: there may be no hero - landmines in Tower
|
||||
|
||||
if(obstacle.obstacleType == CObstacleInstance::MOAT)
|
||||
{
|
||||
@ -4916,7 +4916,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
|
||||
int destination = oneOfAttacked->position;
|
||||
|
||||
const CSpell * spell = SpellID(spellID).toSpell();
|
||||
if(gs->curB->battleCanCastThisSpellHere(attacker->owner, spell, ECastingMode::AFTER_ATTACK_CASTING, oneOfAttacked->position) != ESpellCastProblem::OK)
|
||||
if(gs->curB->battleCanCastThisSpellHere(attacker, spell, ECastingMode::AFTER_ATTACK_CASTING, oneOfAttacked->position) != ESpellCastProblem::OK)
|
||||
continue;
|
||||
|
||||
//check if spell should be cast (probability handling)
|
||||
@ -4926,8 +4926,6 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
|
||||
//casting
|
||||
if (castMe) //stacks use 0 spell power. If needed, default = 3 or custom value is used
|
||||
{
|
||||
const CSpell * spell = SpellID(spellID).toSpell();
|
||||
|
||||
BattleSpellCastParameters parameters(gs->curB, attacker, spell);
|
||||
parameters.spellLvl = spellLevel;
|
||||
parameters.effectLevel = spellLevel;
|
||||
|
Loading…
Reference in New Issue
Block a user