From 1d840a33a5ff7d571972802733f1d541070a2b44 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Tue, 6 Sep 2016 04:11:30 +0300 Subject: [PATCH] Started SpellCastContext rework --- lib/spells/BattleSpellMechanics.cpp | 2 - lib/spells/CDefaultSpellMechanics.cpp | 117 +++++++++++--------------- lib/spells/CDefaultSpellMechanics.h | 25 +++--- 3 files changed, 65 insertions(+), 79 deletions(-) diff --git a/lib/spells/BattleSpellMechanics.cpp b/lib/spells/BattleSpellMechanics.cpp index db7f37540..94f8eabee 100644 --- a/lib/spells/BattleSpellMechanics.cpp +++ b/lib/spells/BattleSpellMechanics.cpp @@ -225,8 +225,6 @@ ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const ISp void DispellMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const { - DefaultSpellMechanics::applyBattleEffects(env, parameters, ctx); - if(parameters.spellLvl > 2) { //expert DISPELL also removes spell-created obstacles diff --git a/lib/spells/CDefaultSpellMechanics.cpp b/lib/spells/CDefaultSpellMechanics.cpp index 185e4935d..86e070f91 100644 --- a/lib/spells/CDefaultSpellMechanics.cpp +++ b/lib/spells/CDefaultSpellMechanics.cpp @@ -12,7 +12,6 @@ #include "CDefaultSpellMechanics.h" -#include "../NetPacks.h" #include "../BattleState.h" #include "../CGeneralTextHandler.h" @@ -119,6 +118,24 @@ namespace SRSLPraserHelpers } } +SpellCastContext::SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters): + mechanics(mechanics_), attackedCres(), sc(), si() +{ + prepareBattleCast(parameters); +} + +void SpellCastContext::prepareBattleCast(const BattleSpellCastParameters & parameters) +{ + sc.side = parameters.casterSide; + sc.id = mechanics->owner->id; + sc.skill = parameters.spellLvl; + sc.tile = parameters.getFirstDestinationHex(); + sc.dmgToDisplay = 0; + sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING; + sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1); + sc.manaGained = 0; +} + ///DefaultSpellMechanics void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const { @@ -155,8 +172,7 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS return; } - BattleSpellCast sc; - prepareBattleCast(parameters, sc); + SpellCastContext ctx(this, parameters); //check it there is opponent hero const ui8 otherSide = 1-parameters.casterSide; @@ -180,35 +196,31 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING)); } } - sc.manaGained = (manaChannel * spellCost) / 100; + ctx.sc.manaGained = (manaChannel * spellCost) / 100; } } logGlobal->debugStream() << "spellCost: " << spellCost; - //calculating affected creatures for all spells - //must be vector, as in Chain Lightning order matters - std::vector attackedCres; //CStack vector is somewhat more suitable than ID vector - auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, parameters.getFirstDestinationHex()); - std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres)); + std::copy(creatures.begin(), creatures.end(), std::back_inserter(ctx.attackedCres)); - logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks"; + logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks"; std::vector reflected;//for magic mirror //checking if creatures resist - handleResistance(env, attackedCres, sc); + handleResistance(env, ctx.attackedCres, ctx.sc); //it is actual spell and can be reflected to single target, no recurrence const bool tryMagicMirror = owner->isNegative() && owner->level && owner->getLevelInfo(0).range == "0"; if(tryMagicMirror) { - for(auto s : attackedCres) + for(auto s : ctx.attackedCres) { const int mirrorChance = (s)->valOfBonuses(Bonus::MAGIC_MIRROR); if(env->getRandomGenerator().nextInt(99) < mirrorChance) reflected.push_back(s); } - vstd::erase_if(attackedCres, [&reflected](const CStack * s) + vstd::erase_if(ctx.attackedCres, [&reflected](const CStack * s) { return vstd::contains(reflected, s); }); @@ -218,24 +230,21 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS BattleSpellCast::CustomEffect effect; effect.effect = 3; effect.stack = s->ID; - sc.customEffects.push_back(effect); + ctx.sc.customEffects.push_back(effect); } } - for(auto cre : attackedCres) + for(auto cre : ctx.attackedCres) { - sc.affectedCres.insert(cre->ID); + ctx.sc.affectedCres.insert(cre->ID); } - StacksInjured si; - SpellCastContext ctx(attackedCres, sc, si); applyBattleEffects(env, parameters, ctx); + env->sendAndApply(&ctx.sc); - env->sendAndApply(&sc); - - //spend mana if(parameters.mode == ECastingMode::HERO_CASTING) { + //spend mana SetMana sm; sm.absolute = false; @@ -244,22 +253,18 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS env->sendAndApply(&sm); - if(sc.manaGained > 0) + if(ctx.sc.manaGained > 0) { assert(otherHero); sm.hid = otherHero->id; - sm.val = sc.manaGained; + sm.val = ctx.sc.manaGained; env->sendAndApply(&sm); } } - - if(!si.stacks.empty()) //after spellcast info shows - env->sendAndApply(&si); - - //reduce number of casts remaining - if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING) + else if (parameters.mode == ECastingMode::CREATURE_ACTIVE_CASTING || parameters.mode == ECastingMode::ENCHANTER_CASTING) { + //reduce number of casts remaining assert(parameters.casterStack); BattleSetStackProperty ssp; @@ -269,6 +274,11 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS ssp.absolute = false; env->sendAndApply(&ssp); } + + if(!ctx.si.stacks.empty()) //after spellcast info shows + env->sendAndApply(&ctx.si); + + logGlobal->debugStream() << "Finished spell cast. Spell: "<name<<"; mode:"<debugStream() << "Started spell cast. Spell: "<name<<"; mode: MAGIC_MIRROR"; - if(parameters.mode != ECastingMode::MAGIC_MIRROR) - { - env->complain("MagicMirror: invalid mode"); - return; - } - BattleHex destination = parameters.getFirstDestinationHex(); - if(!destination.isValid()) - { - env->complain("MagicMirror: invalid destination"); - return; - } - BattleSpellCast sc; - prepareBattleCast(parameters, sc); + BattleHex destination = parameters.getFirstDestinationHex(); + SpellCastContext ctx(this, parameters); //calculating affected creatures for all spells - //must be vector, as in Chain Lightning order matters - std::vector attackedCres; //CStack vector is somewhat more suitable than ID vector - auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.caster, parameters.spellLvl, destination); - std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres)); + std::copy(creatures.begin(), creatures.end(), std::back_inserter(ctx.attackedCres)); - logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks"; + logGlobal->debugStream() << "will affect: " << ctx.attackedCres.size() << " stacks"; - handleResistance(env, attackedCres, sc); + handleResistance(env, ctx.attackedCres, ctx.sc); - for(auto cre : attackedCres) + for(auto cre : ctx.attackedCres) { - sc.affectedCres.insert(cre->ID); + ctx.sc.affectedCres.insert(cre->ID); } - StacksInjured si; - SpellCastContext ctx(attackedCres, sc, si); applyBattleEffects(env, parameters, ctx); - env->sendAndApply(&sc); - if(!si.stacks.empty()) //after spellcast info shows - env->sendAndApply(&si); + env->sendAndApply(&ctx.sc); + if(!ctx.si.stacks.empty()) //after spellcast info shows + env->sendAndApply(&ctx.si); + logGlobal->debugStream() << "Finished spell cast. Spell: "<name<<"; mode: MAGIC_MIRROR"; } @@ -772,18 +767,6 @@ void DefaultSpellMechanics::handleResistance(const SpellCastEnvironment * env, s } } -void DefaultSpellMechanics::prepareBattleCast(const BattleSpellCastParameters& parameters, BattleSpellCast& sc) const -{ - sc.side = parameters.casterSide; - sc.id = owner->id; - sc.skill = parameters.spellLvl; - sc.tile = parameters.getFirstDestinationHex(); - sc.dmgToDisplay = 0; - sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING; - sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1); - sc.manaGained = 0; -} - bool DefaultSpellMechanics::requiresCreatureTarget() const { //most spells affects creatures somehow regardless of Target Type diff --git a/lib/spells/CDefaultSpellMechanics.h b/lib/spells/CDefaultSpellMechanics.h index 2f36cdfe1..63b03ace9 100644 --- a/lib/spells/CDefaultSpellMechanics.h +++ b/lib/spells/CDefaultSpellMechanics.h @@ -11,20 +11,24 @@ #pragma once #include "ISpellMechanics.h" +#include "../NetPacks.h" -struct StacksInjured; +class DefaultSpellMechanics; -struct SpellCastContext +class SpellCastContext { - SpellCastContext(std::vector & attackedCres, BattleSpellCast & sc, StacksInjured & si): - attackedCres(attackedCres), sc(sc), si(si) - { - }; - std::vector & attackedCres; - BattleSpellCast & sc; - StacksInjured & si; +public: + const DefaultSpellMechanics * mechanics; + std::vector attackedCres;//must be vector, as in Chain Lightning order matters + BattleSpellCast sc; + StacksInjured si; + + SpellCastContext(const DefaultSpellMechanics * mechanics_, const BattleSpellCastParameters & parameters); +private: + void prepareBattleCast(const BattleSpellCastParameters & parameters); }; +///all combat spells class DLL_LINKAGE DefaultSpellMechanics : public ISpellMechanics { public: @@ -53,5 +57,6 @@ protected: private: void castMagicMirror(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const; void handleResistance(const SpellCastEnvironment * env, std::vector & attackedCres, BattleSpellCast & sc) const; - void prepareBattleCast(const BattleSpellCastParameters & parameters, BattleSpellCast & sc) const; + + friend class SpellCastContext; };