1
0
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:
AlexVinS 2016-09-06 13:05:33 +03:00
parent 686cd00c68
commit 838717dfc1
2 changed files with 99 additions and 109 deletions

View File

@ -118,19 +118,8 @@ namespace SRSLPraserHelpers
} }
} }
SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters): SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const SpellCastEnvironment * env_, const BattleSpellCastParameters & parameters_):
mechanics(mechanics_), attackedCres(), sc(), si(), mode(parameters.mode) mechanics(mechanics_), env(env_), attackedCres(), sc(), si(), parameters(parameters_), otherHero(nullptr), spellCost(0)
{
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)
{ {
sc.side = parameters.casterSide; sc.side = parameters.casterSide;
sc.id = mechanics->owner->id; sc.id = mechanics->owner->id;
@ -140,6 +129,19 @@ void SpellCastContext::prepareBattleCast(const BattleSpellCastParameters & param
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);
sc.manaGained = 0; 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) void SpellCastContext::addDamageToDisplay(const si32 value)
@ -152,7 +154,7 @@ void SpellCastContext::setDamageToDisplay(const si32 value)
sc.dmgToDisplay = value; sc.dmgToDisplay = value;
} }
void SpellCastContext::sendCastPacket(const SpellCastEnvironment * env) void SpellCastContext::sendCastPacket()
{ {
for(auto sta : attackedCres) for(auto sta : attackedCres)
{ {
@ -162,6 +164,70 @@ void SpellCastContext::sendCastPacket(const SpellCastEnvironment * env)
env->sendAndApply(&sc); 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 ///DefaultSpellMechanics
void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const
{ {
@ -196,9 +262,9 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B
return; 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 //Magic Mirror effect
for(auto & attackedCre : reflected) for(auto & attackedCre : reflected)
@ -214,7 +280,6 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B
int targetHex = (*RandomGeneratorUtil::nextItem(mirrorTargets, env->getRandomGenerator()))->position; int targetHex = (*RandomGeneratorUtil::nextItem(mirrorTargets, env->getRandomGenerator()))->position;
BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner); BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
mirrorParameters.spellLvl = 0;
mirrorParameters.aimToHex(targetHex); mirrorParameters.aimToHex(targetHex);
mirrorParameters.mode = ECastingMode::MAGIC_MIRROR; mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
mirrorParameters.spellLvl = parameters.spellLvl; mirrorParameters.spellLvl = parameters.spellLvl;
@ -222,41 +287,16 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, const B
mirrorParameters.effectPower = parameters.effectPower; mirrorParameters.effectPower = parameters.effectPower;
mirrorParameters.effectValue = parameters.effectValue; mirrorParameters.effectValue = parameters.effectValue;
mirrorParameters.enchantPower = parameters.enchantPower; 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 ctx.beforeCast();
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.attackedCres = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex()); 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); handleResistance(env, ctx);
handleMagicMirror(env, ctx, reflected); if(parameters.mode != ECastingMode::MAGIC_MIRROR)
handleMagicMirror(env, ctx, reflected);
applyBattleEffects(env, parameters, ctx); applyBattleEffects(env, parameters, ctx);
ctx.sendCastPacket(env); ctx.afterCast();
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);
} }
void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet, void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet,

View File

@ -19,20 +19,25 @@ class DLL_LINKAGE SpellCastContext
{ {
public: public:
const DefaultSpellMechanics * mechanics; const DefaultSpellMechanics * mechanics;
const SpellCastEnvironment * env;
std::vector<const CStack *> attackedCres;//must be vector, as in Chain Lightning order matters std::vector<const CStack *> attackedCres;//must be vector, as in Chain Lightning order matters
BattleSpellCast sc;//todo: make private BattleSpellCast sc;//todo: make private
StacksInjured si; 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(); virtual ~SpellCastContext();
void addDamageToDisplay(const si32 value); void addDamageToDisplay(const si32 value);
void setDamageToDisplay(const si32 value); void setDamageToDisplay(const si32 value);
void sendCastPacket(const SpellCastEnvironment * env); void beforeCast();
void afterCast();
private: private:
void prepareBattleCast(const BattleSpellCastParameters & parameters); const CGHeroInstance * otherHero;
int spellCost;
void sendCastPacket();
}; };
///all combat spells ///all combat spells
@ -65,8 +70,7 @@ protected:
protected: protected:
void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const; void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
private: private:
void castNormal(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const; void cast(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, std::vector <const CStack*> & reflected) const;
void castMagicMirror(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters) const;
void handleImmunities(const CBattleInfoCallback * cb, const SpellTargetingContext & ctx, std::vector<const CStack *> & stacks) 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; void handleMagicMirror(const SpellCastEnvironment * env, SpellCastContext & ctx, std::vector <const CStack*> & reflected) const;