mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Allow multiple destinations in BattleSpellCastParameters
This commit is contained in:
parent
a06e34cf61
commit
57e5b768e8
@ -367,7 +367,7 @@ ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const I
|
|||||||
///ObstacleMechanics
|
///ObstacleMechanics
|
||||||
void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||||
{
|
{
|
||||||
auto placeObstacle = [&, this](BattleHex pos)
|
auto placeObstacle = [&, this](const BattleHex & pos)
|
||||||
{
|
{
|
||||||
static int obstacleIdToGive = parameters.cb->obstacles.size()
|
static int obstacleIdToGive = parameters.cb->obstacles.size()
|
||||||
? (parameters.cb->obstacles.back()->uniqueID+1)
|
? (parameters.cb->obstacles.back()->uniqueID+1)
|
||||||
@ -413,6 +413,8 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, con
|
|||||||
env->sendAndApply(&bop);
|
env->sendAndApply(&bop);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BattleHex destination = parameters.getFirstDestinationHex();
|
||||||
|
|
||||||
switch(owner->id)
|
switch(owner->id)
|
||||||
{
|
{
|
||||||
case SpellID::QUICKSAND:
|
case SpellID::QUICKSAND:
|
||||||
@ -437,12 +439,22 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, con
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case SpellID::FORCE_FIELD:
|
case SpellID::FORCE_FIELD:
|
||||||
placeObstacle(parameters.destination);
|
if(!destination.isValid())
|
||||||
|
{
|
||||||
|
env->complain("Invalid destination for FORCE_FIELD");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
placeObstacle(destination);
|
||||||
break;
|
break;
|
||||||
case SpellID::FIRE_WALL:
|
case SpellID::FIRE_WALL:
|
||||||
{
|
{
|
||||||
|
if(!destination.isValid())
|
||||||
|
{
|
||||||
|
env->complain("Invalid destination for FIRE_WALL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
//fire wall is build from multiple obstacles - one fire piece for each affected hex
|
//fire wall is build from multiple obstacles - one fire piece for each affected hex
|
||||||
auto affectedHexes = owner->rangeInHexes(parameters.destination, parameters.spellLvl, parameters.casterSide);
|
auto affectedHexes = owner->rangeInHexes(destination, parameters.spellLvl, parameters.casterSide);
|
||||||
for(BattleHex hex : affectedHexes)
|
for(BattleHex hex : affectedHexes)
|
||||||
placeObstacle(hex);
|
placeObstacle(hex);
|
||||||
}
|
}
|
||||||
@ -493,7 +505,7 @@ std::vector<BattleHex> WallMechanics::rangeInHexes(BattleHex centralHex, ui8 sch
|
|||||||
///RemoveObstacleMechanics
|
///RemoveObstacleMechanics
|
||||||
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||||
{
|
{
|
||||||
if(auto obstacleToRemove = parameters.cb->battleGetObstacleOnPos(parameters.destination, false))
|
if(auto obstacleToRemove = parameters.cb->battleGetObstacleOnPos(parameters.getFirstDestinationHex(), false))
|
||||||
{
|
{
|
||||||
ObstaclesRemoved obr;
|
ObstaclesRemoved obr;
|
||||||
obr.obstacles.insert(obstacleToRemove->uniqueID);
|
obr.obstacles.insert(obstacleToRemove->uniqueID);
|
||||||
@ -659,9 +671,9 @@ void TeleportMechanics::applyBattleEffects(const SpellCastEnvironment * env, con
|
|||||||
|
|
||||||
BattleStackMoved bsm;
|
BattleStackMoved bsm;
|
||||||
bsm.distance = -1;
|
bsm.distance = -1;
|
||||||
bsm.stack = parameters.selectedStack->ID;
|
bsm.stack = parameters.selectedStack->ID;//todo: use destinations
|
||||||
std::vector<BattleHex> tiles;
|
std::vector<BattleHex> tiles;
|
||||||
tiles.push_back(parameters.destination);
|
tiles.push_back(parameters.getFirstDestinationHex());
|
||||||
bsm.tilesToMove = tiles;
|
bsm.tilesToMove = tiles;
|
||||||
bsm.teleporting = true;
|
bsm.teleporting = true;
|
||||||
env->sendAndApply(&bsm);
|
env->sendAndApply(&bsm);
|
||||||
|
@ -265,7 +265,7 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
|||||||
//must be vector, as in Chain Lightning order matters
|
//must be vector, as in Chain Lightning order matters
|
||||||
std::vector<const CStack*> attackedCres; //CStack vector is somewhat more suitable than ID vector
|
std::vector<const CStack*> attackedCres; //CStack vector is somewhat more suitable than ID vector
|
||||||
|
|
||||||
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, parameters.destination, parameters.caster);
|
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, parameters.getFirstDestinationHex(), parameters.caster);
|
||||||
std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres));
|
std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres));
|
||||||
|
|
||||||
logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks";
|
logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks";
|
||||||
@ -363,7 +363,7 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
|||||||
|
|
||||||
BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
|
BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
|
||||||
mirrorParameters.spellLvl = 0;
|
mirrorParameters.spellLvl = 0;
|
||||||
mirrorParameters.destination = targetHex;
|
mirrorParameters.aimToHex(targetHex);
|
||||||
mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
|
mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
|
||||||
mirrorParameters.selectedStack = nullptr;
|
mirrorParameters.selectedStack = nullptr;
|
||||||
mirrorParameters.spellLvl = parameters.spellLvl;
|
mirrorParameters.spellLvl = parameters.spellLvl;
|
||||||
@ -766,7 +766,8 @@ void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, Bat
|
|||||||
env->complain("MagicMirror: invalid mode");
|
env->complain("MagicMirror: invalid mode");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!parameters.destination.isValid())
|
BattleHex destination = parameters.getFirstDestinationHex();
|
||||||
|
if(!destination.isValid())
|
||||||
{
|
{
|
||||||
env->complain("MagicMirror: invalid destination");
|
env->complain("MagicMirror: invalid destination");
|
||||||
return;
|
return;
|
||||||
@ -779,7 +780,7 @@ void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, Bat
|
|||||||
//must be vector, as in Chain Lightning order matters
|
//must be vector, as in Chain Lightning order matters
|
||||||
std::vector<const CStack*> attackedCres; //CStack vector is somewhat more suitable than ID vector
|
std::vector<const CStack*> attackedCres; //CStack vector is somewhat more suitable than ID vector
|
||||||
|
|
||||||
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, parameters.destination, parameters.caster);
|
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, destination, parameters.caster);
|
||||||
std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres));
|
std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres));
|
||||||
|
|
||||||
logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks";
|
logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks";
|
||||||
@ -839,7 +840,7 @@ void DefaultSpellMechanics::prepareBattleCast(const BattleSpellCastParameters& p
|
|||||||
sc.side = parameters.casterSide;
|
sc.side = parameters.casterSide;
|
||||||
sc.id = owner->id;
|
sc.id = owner->id;
|
||||||
sc.skill = parameters.spellLvl;
|
sc.skill = parameters.spellLvl;
|
||||||
sc.tile = parameters.destination;
|
sc.tile = parameters.getFirstDestinationHex();
|
||||||
sc.dmgToDisplay = 0;
|
sc.dmgToDisplay = 0;
|
||||||
sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING;
|
sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING;
|
||||||
sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1);
|
sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1);
|
||||||
|
@ -115,9 +115,13 @@ bool CSpell::adventureCast(const SpellCastEnvironment * env, AdventureSpellCastP
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CSpell::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
|
void CSpell::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
|
||||||
{
|
{
|
||||||
assert(env);
|
assert(env);
|
||||||
|
if(parameters.destinations.size()<1)
|
||||||
|
{
|
||||||
|
env->complain("Spell must have at least one destination");
|
||||||
|
return;
|
||||||
|
}
|
||||||
mechanics->battleCast(env, parameters);
|
mechanics->battleCast(env, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,23 @@
|
|||||||
#include "BattleSpellMechanics.h"
|
#include "BattleSpellMechanics.h"
|
||||||
#include "CreatureSpellMechanics.h"
|
#include "CreatureSpellMechanics.h"
|
||||||
|
|
||||||
|
BattleSpellCastParameters::Destination::Destination(const CStack * destination):
|
||||||
|
stackValue(destination),
|
||||||
|
hexValue(destination->position)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BattleSpellCastParameters::Destination::Destination(const BattleHex & destination):
|
||||||
|
stackValue(nullptr),
|
||||||
|
hexValue(destination)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
BattleSpellCastParameters::BattleSpellCastParameters(const BattleInfo * cb, const ISpellCaster * caster, const CSpell * spell)
|
BattleSpellCastParameters::BattleSpellCastParameters(const BattleInfo * cb, const ISpellCaster * caster, const CSpell * spell)
|
||||||
: cb(cb), caster(caster), casterColor(caster->getOwner()), casterSide(cb->whatSide(casterColor)),
|
: cb(cb), caster(caster), casterColor(caster->getOwner()), casterSide(cb->whatSide(casterColor)),
|
||||||
destination(BattleHex::INVALID),casterHero(nullptr),
|
casterHero(nullptr),
|
||||||
mode(ECastingMode::HERO_CASTING), casterStack(nullptr), selectedStack(nullptr),
|
mode(ECastingMode::HERO_CASTING), casterStack(nullptr), selectedStack(nullptr),
|
||||||
spellLvl(-1), effectLevel(-1), effectPower(0), enchantPower(0), effectValue(0)
|
spellLvl(-1), effectLevel(-1), effectPower(0), enchantPower(0), effectValue(0)
|
||||||
{
|
{
|
||||||
@ -31,6 +45,22 @@ BattleSpellCastParameters::BattleSpellCastParameters(const BattleInfo * cb, cons
|
|||||||
prepare(spell);
|
prepare(spell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleSpellCastParameters::aimToHex(const BattleHex& destination)
|
||||||
|
{
|
||||||
|
destinations.push_back(Destination(destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleSpellCastParameters::aimToStack(const CStack * destination)
|
||||||
|
{
|
||||||
|
destinations.push_back(Destination(destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BattleHex BattleSpellCastParameters::getFirstDestinationHex() const
|
||||||
|
{
|
||||||
|
return destinations.at(0).hexValue;
|
||||||
|
}
|
||||||
|
|
||||||
void BattleSpellCastParameters::prepare(const CSpell * spell)
|
void BattleSpellCastParameters::prepare(const CSpell * spell)
|
||||||
{
|
{
|
||||||
spellLvl = caster->getSpellSchoolLevel(spell);
|
spellLvl = caster->getSpellSchoolLevel(spell);
|
||||||
|
@ -30,21 +30,37 @@ public:
|
|||||||
virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) const =0; //TODO: remove
|
virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) const =0; //TODO: remove
|
||||||
};
|
};
|
||||||
|
|
||||||
///helper struct
|
///all parameters of particular cast event
|
||||||
struct DLL_LINKAGE BattleSpellCastParameters
|
struct DLL_LINKAGE BattleSpellCastParameters
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
///Single spell destination.
|
||||||
|
/// (assumes that anything but battle stack can share same hex)
|
||||||
|
struct DLL_LINKAGE Destination
|
||||||
|
{
|
||||||
|
explicit Destination(const CStack * destination);
|
||||||
|
explicit Destination(const BattleHex & destination);
|
||||||
|
|
||||||
|
const CStack * stackValue;
|
||||||
|
const BattleHex hexValue;
|
||||||
|
};
|
||||||
|
|
||||||
BattleSpellCastParameters(const BattleInfo * cb, const ISpellCaster * caster, const CSpell * spell);
|
BattleSpellCastParameters(const BattleInfo * cb, const ISpellCaster * caster, const CSpell * spell);
|
||||||
|
void aimToHex(const BattleHex & destination);
|
||||||
|
void aimToStack(const CStack * destination);
|
||||||
|
BattleHex getFirstDestinationHex() const;
|
||||||
|
|
||||||
const BattleInfo * cb;
|
const BattleInfo * cb;
|
||||||
const ISpellCaster * caster;
|
const ISpellCaster * caster;
|
||||||
const PlayerColor casterColor;
|
const PlayerColor casterColor;
|
||||||
const ui8 casterSide;
|
const ui8 casterSide;
|
||||||
|
|
||||||
BattleHex destination;
|
std::vector<Destination> destinations;
|
||||||
|
|
||||||
const CGHeroInstance * casterHero; //deprecated
|
const CGHeroInstance * casterHero; //deprecated
|
||||||
ECastingMode::ECastingMode mode;
|
ECastingMode::ECastingMode mode;
|
||||||
const CStack * casterStack; //deprecated
|
const CStack * casterStack; //deprecated
|
||||||
const CStack * selectedStack;
|
const CStack * selectedStack;//deprecated
|
||||||
|
|
||||||
///spell school level
|
///spell school level
|
||||||
int spellLvl;
|
int spellLvl;
|
||||||
|
@ -3878,7 +3878,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
vstd::amin (parameters.spellLvl, 3);
|
vstd::amin (parameters.spellLvl, 3);
|
||||||
parameters.effectLevel = parameters.spellLvl;
|
parameters.effectLevel = parameters.spellLvl;
|
||||||
parameters.mode = ECastingMode::CREATURE_ACTIVE_CASTING;
|
parameters.mode = ECastingMode::CREATURE_ACTIVE_CASTING;
|
||||||
parameters.destination = destination;
|
parameters.aimToHex(destination);//todo: allow multiple destinations
|
||||||
parameters.selectedStack = nullptr;
|
parameters.selectedStack = nullptr;
|
||||||
spell->battleCast(spellEnv, parameters);
|
spell->battleCast(spellEnv, parameters);
|
||||||
}
|
}
|
||||||
@ -4069,7 +4069,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
const CSpell * s = SpellID(ba.additionalInfo).toSpell();
|
const CSpell * s = SpellID(ba.additionalInfo).toSpell();
|
||||||
|
|
||||||
BattleSpellCastParameters parameters(gs->curB, h, s);
|
BattleSpellCastParameters parameters(gs->curB, h, s);
|
||||||
parameters.destination = ba.destinationTile;
|
parameters.aimToHex(ba.destinationTile);//todo: allow multiple destinations
|
||||||
parameters.mode = ECastingMode::HERO_CASTING;
|
parameters.mode = ECastingMode::HERO_CASTING;
|
||||||
parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false);
|
parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false);
|
||||||
|
|
||||||
@ -4222,7 +4222,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
|||||||
BattleSpellCastParameters parameters(gs->curB, st, spell);
|
BattleSpellCastParameters parameters(gs->curB, st, spell);
|
||||||
parameters.spellLvl = bonus->val;
|
parameters.spellLvl = bonus->val;
|
||||||
parameters.effectLevel = bonus->val;//todo: recheck
|
parameters.effectLevel = bonus->val;//todo: recheck
|
||||||
parameters.destination = BattleHex::INVALID;
|
parameters.aimToHex(BattleHex::INVALID);
|
||||||
parameters.mode = ECastingMode::ENCHANTER_CASTING;
|
parameters.mode = ECastingMode::ENCHANTER_CASTING;
|
||||||
parameters.selectedStack = nullptr;
|
parameters.selectedStack = nullptr;
|
||||||
|
|
||||||
@ -4913,7 +4913,6 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
|
|||||||
}
|
}
|
||||||
int chance = attacker->valOfBonuses((Selector::typeSubtype(attackMode, spellID)));
|
int chance = attacker->valOfBonuses((Selector::typeSubtype(attackMode, spellID)));
|
||||||
vstd::amin (chance, 100);
|
vstd::amin (chance, 100);
|
||||||
int destination = oneOfAttacked->position;
|
|
||||||
|
|
||||||
const CSpell * spell = SpellID(spellID).toSpell();
|
const CSpell * spell = SpellID(spellID).toSpell();
|
||||||
if(gs->curB->battleCanCastThisSpellHere(attacker, spell, ECastingMode::AFTER_ATTACK_CASTING, oneOfAttacked->position) != ESpellCastProblem::OK)
|
if(gs->curB->battleCanCastThisSpellHere(attacker, spell, ECastingMode::AFTER_ATTACK_CASTING, oneOfAttacked->position) != ESpellCastProblem::OK)
|
||||||
@ -4929,7 +4928,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
|
|||||||
BattleSpellCastParameters parameters(gs->curB, attacker, spell);
|
BattleSpellCastParameters parameters(gs->curB, attacker, spell);
|
||||||
parameters.spellLvl = spellLevel;
|
parameters.spellLvl = spellLevel;
|
||||||
parameters.effectLevel = spellLevel;
|
parameters.effectLevel = spellLevel;
|
||||||
parameters.destination = destination;
|
parameters.aimToStack(oneOfAttacked);
|
||||||
parameters.mode = ECastingMode::AFTER_ATTACK_CASTING;
|
parameters.mode = ECastingMode::AFTER_ATTACK_CASTING;
|
||||||
parameters.selectedStack = nullptr;
|
parameters.selectedStack = nullptr;
|
||||||
|
|
||||||
@ -4958,7 +4957,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
|||||||
BattleSpellCastParameters parameters(gs->curB, attacker, spell);
|
BattleSpellCastParameters parameters(gs->curB, attacker, spell);
|
||||||
parameters.spellLvl = 0;
|
parameters.spellLvl = 0;
|
||||||
parameters.effectLevel = 0;
|
parameters.effectLevel = 0;
|
||||||
parameters.destination = gs->curB->battleGetStackByID(bat.bsa.at(0).stackAttacked)->position;
|
parameters.aimToStack(gs->curB->battleGetStackByID(bat.bsa.at(0).stackAttacked));
|
||||||
parameters.effectPower = power;
|
parameters.effectPower = power;
|
||||||
parameters.mode = ECastingMode::AFTER_ATTACK_CASTING;
|
parameters.mode = ECastingMode::AFTER_ATTACK_CASTING;
|
||||||
parameters.selectedStack = nullptr;
|
parameters.selectedStack = nullptr;
|
||||||
@ -5266,7 +5265,7 @@ void CGameHandler::runBattle()
|
|||||||
BattleSpellCastParameters parameters(gs->curB, h, spell);
|
BattleSpellCastParameters parameters(gs->curB, h, spell);
|
||||||
parameters.spellLvl = 3;
|
parameters.spellLvl = 3;
|
||||||
parameters.effectLevel = 3;
|
parameters.effectLevel = 3;
|
||||||
parameters.destination = BattleHex::INVALID;
|
parameters.aimToHex(BattleHex::INVALID);
|
||||||
parameters.mode = ECastingMode::PASSIVE_CASTING;
|
parameters.mode = ECastingMode::PASSIVE_CASTING;
|
||||||
parameters.selectedStack = nullptr;
|
parameters.selectedStack = nullptr;
|
||||||
parameters.enchantPower = b->val;
|
parameters.enchantPower = b->val;
|
||||||
|
Loading…
Reference in New Issue
Block a user