mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Magic mirror unified again with normal cast.
This commit is contained in:
parent
686cd00c68
commit
838717dfc1
@ -118,19 +118,8 @@ namespace SRSLPraserHelpers
|
||||
}
|
||||
}
|
||||
|
||||
SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters):
|
||||
mechanics(mechanics_), attackedCres(), sc(), si(), mode(parameters.mode)
|
||||
{
|
||||
prepareBattleCast(parameters);
|
||||
logGlobal->debugStream() << "Started spell cast. Spell: " << mechanics->owner->name << "; mode:" << mode;
|
||||
}
|
||||
|
||||
SpellCastContext::~SpellCastContext()
|
||||
{
|
||||
logGlobal->debugStream() << "Finished spell cast. Spell: " << mechanics->owner->name << "; mode:" << mode;
|
||||
}
|
||||
|
||||
void SpellCastContext::prepareBattleCast(const BattleSpellCastParameters & parameters)
|
||||
SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const SpellCastEnvironment * env_, const BattleSpellCastParameters & parameters_):
|
||||
mechanics(mechanics_), env(env_), attackedCres(), sc(), si(), parameters(parameters_), otherHero(nullptr), spellCost(0)
|
||||
{
|
||||
sc.side = parameters.casterSide;
|
||||
sc.id = mechanics->owner->id;
|
||||
@ -140,6 +129,19 @@ void SpellCastContext::prepareBattleCast(const BattleSpellCastParameters & param
|
||||
sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING;
|
||||
sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1);
|
||||
sc.manaGained = 0;
|
||||
|
||||
//check it there is opponent hero
|
||||
const ui8 otherSide = 1-parameters.casterSide;
|
||||
|
||||
if(parameters.cb->battleHasHero(otherSide))
|
||||
otherHero = parameters.cb->battleGetFightingHero(otherSide);
|
||||
|
||||
logGlobal->debugStream() << "Started spell cast. Spell: " << mechanics->owner->name << "; mode:" << parameters.mode;
|
||||
}
|
||||
|
||||
SpellCastContext::~SpellCastContext()
|
||||
{
|
||||
logGlobal->debugStream() << "Finished spell cast. Spell: " << mechanics->owner->name << "; mode:" << parameters.mode;
|
||||
}
|
||||
|
||||
void SpellCastContext::addDamageToDisplay(const si32 value)
|
||||
@ -152,7 +154,7 @@ void SpellCastContext::setDamageToDisplay(const si32 value)
|
||||
sc.dmgToDisplay = value;
|
||||
}
|
||||
|
||||
void SpellCastContext::sendCastPacket(const SpellCastEnvironment * env)
|
||||
void SpellCastContext::sendCastPacket()
|
||||
{
|
||||
for(auto sta : attackedCres)
|
||||
{
|
||||
@ -162,6 +164,70 @@ void SpellCastContext::sendCastPacket(const SpellCastEnvironment * env)
|
||||
env->sendAndApply(&sc);
|
||||
}
|
||||
|
||||
void SpellCastContext::beforeCast()
|
||||
{
|
||||
//calculate spell cost
|
||||
if(parameters.mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
spellCost = parameters.cb->battleGetSpellCost(mechanics->owner, parameters.casterHero);
|
||||
|
||||
if(nullptr != otherHero) //handle mana channel
|
||||
{
|
||||
int manaChannel = 0;
|
||||
for(const CStack * stack : parameters.cb->battleGetAllStacks(true)) //TODO: shouldn't bonus system handle it somehow?
|
||||
{
|
||||
if(stack->owner == otherHero->tempOwner)
|
||||
{
|
||||
vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING));
|
||||
}
|
||||
}
|
||||
sc.manaGained = (manaChannel * spellCost) / 100;
|
||||
}
|
||||
|
||||
logGlobal->debugStream() << "spellCost: " << spellCost;
|
||||
}
|
||||
}
|
||||
|
||||
void SpellCastContext::afterCast()
|
||||
{
|
||||
sendCastPacket();
|
||||
|
||||
if(parameters.mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
//spend mana
|
||||
SetMana sm;
|
||||
sm.absolute = false;
|
||||
|
||||
sm.hid = parameters.casterHero->id;
|
||||
sm.val = -spellCost;
|
||||
|
||||
env->sendAndApply(&sm);
|
||||
|
||||
if(sc.manaGained > 0)
|
||||
{
|
||||
assert(otherHero);
|
||||
|
||||
sm.hid = otherHero->id;
|
||||
sm.val = sc.manaGained;
|
||||
env->sendAndApply(&sm);
|
||||
}
|
||||
}
|
||||
else if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING)
|
||||
{
|
||||
//reduce number of casts remaining
|
||||
assert(parameters.casterStack);
|
||||
|
||||
BattleSetStackProperty ssp;
|
||||
ssp.stackID = parameters.casterStack->ID;
|
||||
ssp.which = BattleSetStackProperty::CASTS;
|
||||
ssp.val = -1;
|
||||
ssp.absolute = false;
|
||||
env->sendAndApply(&ssp);
|
||||
}
|
||||
if(!si.stacks.empty()) //after spellcast info shows
|
||||
env->sendAndApply(&si);
|
||||
}
|
||||
|
||||
///DefaultSpellMechanics
|
||||
void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const
|
||||
{
|
||||
@ -196,9 +262,9 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector <const CStack*> reflected;//for magic mirror
|
||||
std::vector <const CStack*> reflected, reflectedIgnore;//for magic mirror
|
||||
|
||||
castNormal(env, parameters, reflected);
|
||||
cast(env, parameters, reflected);
|
||||
|
||||
//Magic Mirror effect
|
||||
for(auto & attackedCre : reflected)
|
||||
@ -214,7 +280,6 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B
|
||||
int targetHex = (*RandomGeneratorUtil::nextItem(mirrorTargets, env->getRandomGenerator()))->position;
|
||||
|
||||
BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
|
||||
mirrorParameters.spellLvl = 0;
|
||||
mirrorParameters.aimToHex(targetHex);
|
||||
mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
|
||||
mirrorParameters.spellLvl = parameters.spellLvl;
|
||||
@ -222,41 +287,16 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B
|
||||
mirrorParameters.effectPower = parameters.effectPower;
|
||||
mirrorParameters.effectValue = parameters.effectValue;
|
||||
mirrorParameters.enchantPower = parameters.enchantPower;
|
||||
castMagicMirror(env, mirrorParameters);
|
||||
cast(env, mirrorParameters, reflectedIgnore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const
|
||||
void DefaultSpellMechanics::cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const
|
||||
{
|
||||
SpellCastContext ctx(this, parameters);
|
||||
SpellCastContext ctx(this, env, parameters);
|
||||
|
||||
//check it there is opponent hero
|
||||
const ui8 otherSide = 1-parameters.casterSide;
|
||||
const CGHeroInstance * otherHero = nullptr;
|
||||
if(parameters.cb->battleHasHero(otherSide))
|
||||
otherHero = parameters.cb->battleGetFightingHero(otherSide);
|
||||
int spellCost = 0;
|
||||
|
||||
//calculate spell cost
|
||||
if(parameters.mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
spellCost = parameters.cb->battleGetSpellCost(owner, parameters.casterHero);
|
||||
|
||||
if(nullptr != otherHero) //handle mana channel
|
||||
{
|
||||
int manaChannel = 0;
|
||||
for(const CStack * stack : parameters.cb->battleGetAllStacks(true)) //TODO: shouldn't bonus system handle it somehow?
|
||||
{
|
||||
if(stack->owner == otherHero->tempOwner)
|
||||
{
|
||||
vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING));
|
||||
}
|
||||
}
|
||||
ctx.sc.manaGained = (manaChannel * spellCost) / 100;
|
||||
}
|
||||
}
|
||||
logGlobal->debugStream() << "spellCost: " << spellCost;
|
||||
ctx.beforeCast();
|
||||
|
||||
ctx.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex());
|
||||
|
||||
@ -264,66 +304,12 @@ void DefaultSpellMechanics::castNormal(const SpellCastEnvironment * env, const B
|
||||
|
||||
handleResistance(env, ctx);
|
||||
|
||||
handleMagicMirror(env, ctx, reflected);
|
||||
if(parameters.mode != ECastingMode::MAGIC_MIRROR)
|
||||
handleMagicMirror(env, ctx, reflected);
|
||||
|
||||
applyBattleEffects(env, parameters, ctx);
|
||||
|
||||
ctx.sendCastPacket(env);
|
||||
|
||||
if(parameters.mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
//spend mana
|
||||
SetMana sm;
|
||||
sm.absolute = false;
|
||||
|
||||
sm.hid = parameters.casterHero->id;
|
||||
sm.val = -spellCost;
|
||||
|
||||
env->sendAndApply(&sm);
|
||||
|
||||
if(ctx.sc.manaGained > 0)
|
||||
{
|
||||
assert(otherHero);
|
||||
|
||||
sm.hid = otherHero->id;
|
||||
sm.val = ctx.sc.manaGained;
|
||||
env->sendAndApply(&sm);
|
||||
}
|
||||
}
|
||||
else if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING)
|
||||
{
|
||||
//reduce number of casts remaining
|
||||
assert(parameters.casterStack);
|
||||
|
||||
BattleSetStackProperty ssp;
|
||||
ssp.stackID = parameters.casterStack->ID;
|
||||
ssp.which = BattleSetStackProperty::CASTS;
|
||||
ssp.val = -1;
|
||||
ssp.absolute = false;
|
||||
env->sendAndApply(&ssp);
|
||||
}
|
||||
|
||||
if(!ctx.si.stacks.empty()) //after spellcast info shows
|
||||
env->sendAndApply(&ctx.si);
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const
|
||||
{
|
||||
SpellCastContext ctx(this, parameters);
|
||||
|
||||
//calculating affected creatures for all spells
|
||||
ctx.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex());
|
||||
|
||||
logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks";
|
||||
|
||||
handleResistance(env, ctx);
|
||||
|
||||
applyBattleEffects(env, parameters, ctx);
|
||||
|
||||
ctx.sendCastPacket(env);
|
||||
|
||||
if(!ctx.si.stacks.empty()) //after spellcast info shows
|
||||
env->sendAndApply(&ctx.si);
|
||||
ctx.afterCast();
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet,
|
||||
|
@ -19,20 +19,25 @@ class DLL_LINKAGE SpellCastContext
|
||||
{
|
||||
public:
|
||||
const DefaultSpellMechanics * mechanics;
|
||||
const SpellCastEnvironment * env;
|
||||
std::vector<const CStack *> attackedCres;//must be vector, as in Chain Lightning order matters
|
||||
BattleSpellCast sc;//todo: make private
|
||||
StacksInjured si;
|
||||
ECastingMode::ECastingMode mode;
|
||||
const BattleSpellCastParameters & parameters;
|
||||
|
||||
SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters);
|
||||
SpellCastContext(const DefaultSpellMechanics * mechanics_, const SpellCastEnvironment * env_, const BattleSpellCastParameters & parameters_);
|
||||
virtual ~SpellCastContext();
|
||||
|
||||
void addDamageToDisplay(const si32 value);
|
||||
void setDamageToDisplay(const si32 value);
|
||||
|
||||
void sendCastPacket(const SpellCastEnvironment * env);
|
||||
void beforeCast();
|
||||
void afterCast();
|
||||
private:
|
||||
void prepareBattleCast(const BattleSpellCastParameters & parameters);
|
||||
const CGHeroInstance * otherHero;
|
||||
int spellCost;
|
||||
|
||||
void sendCastPacket();
|
||||
};
|
||||
|
||||
///all combat spells
|
||||
@ -65,8 +70,7 @@ protected:
|
||||
protected:
|
||||
void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
|
||||
private:
|
||||
void castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const;
|
||||
void castMagicMirror(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const;
|
||||
void cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const;
|
||||
|
||||
void handleImmunities(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx, std::vector<const CStack *> & stacks) const;
|
||||
void handleMagicMirror(const SpellCastEnvironment * env, SpellCastContext & ctx, std::vector <const CStack*> & reflected) const;
|
||||
|
Loading…
Reference in New Issue
Block a user