From 0fecb40039e2b9ab4867861ac3894ee30385668a Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Wed, 16 Sep 2015 07:33:36 +0300 Subject: [PATCH] Extract HealingSpellMechanics * healing effects are too specific to be allowed for any spell * mixing heal with direct damage does not make sence * mixing heal with timed effect can be easy allowed if needed --- lib/spells/BattleSpellMechanics.cpp | 54 +++++++++++++++++++++++++ lib/spells/BattleSpellMechanics.h | 16 ++++++-- lib/spells/CDefaultSpellMechanics.cpp | 58 +++++---------------------- lib/spells/CDefaultSpellMechanics.h | 5 ++- 4 files changed, 78 insertions(+), 55 deletions(-) diff --git a/lib/spells/BattleSpellMechanics.cpp b/lib/spells/BattleSpellMechanics.cpp index 07f24382f..2f4a3c32e 100644 --- a/lib/spells/BattleSpellMechanics.cpp +++ b/lib/spells/BattleSpellMechanics.cpp @@ -14,6 +14,60 @@ #include "../NetPacks.h" #include "../BattleState.h" +///HealingSpellMechanics +void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters, SpellCastContext& ctx) const +{ + int effectLevel = calculateEffectLevel(parameters); + int hpGained = 0; + + if(owner->id == SpellID::SACRIFICE) + { + if(nullptr == parameters.selectedStack) + env->complain("No stack to sacrifice."); + else + hpGained = (parameters.usedSpellPower + parameters.selectedStack->MaxHealth() + owner->getPower(effectLevel)) * parameters.selectedStack->count; + } + else if(parameters.casterStack) + { + int unitSpellPower = parameters.casterStack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, owner->id.toEnum()); + if(unitSpellPower) + hpGained = parameters.casterStack->count * unitSpellPower; //Archangel + else //Faerie Dragon-like effect - commanders(?) + { + parameters.usedSpellPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * parameters.casterStack->count / 100; + hpGained = parameters.usedSpellPower * owner->power + owner->getPower(effectLevel); + } + } + else + { + hpGained = parameters.usedSpellPower * owner->power + owner->getPower(effectLevel); //??? + } + StacksHealedOrResurrected shr; + shr.lifeDrain = false; + shr.tentHealing = false; + + const bool resurrect = owner->isRisingSpell(); + for(auto & attackedCre : ctx.attackedCres) + { + StacksHealedOrResurrected::HealInfo hi; + hi.stackID = (attackedCre)->ID; + if (parameters.casterStack) //casted by creature + { + hi.healedHP = attackedCre->calculateHealedHealthPoints(hpGained, resurrect); + } + else + { + int stackHPgained = parameters.casterHero->getSpellBonus(owner, hpGained, attackedCre); + hi.healedHP = attackedCre->calculateHealedHealthPoints(stackHPgained, resurrect); + } + + hi.lowLevelResurrection = (effectLevel <= 1) && (owner->id == SpellID::RESURRECTION); + shr.healedStacks.push_back(hi); + } + if(!shr.healedStacks.empty()) + env->sendAndApply(&shr); +} + ///AntimagicMechanics void AntimagicMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const { diff --git a/lib/spells/BattleSpellMechanics.h b/lib/spells/BattleSpellMechanics.h index a64044480..a21c3680f 100644 --- a/lib/spells/BattleSpellMechanics.h +++ b/lib/spells/BattleSpellMechanics.h @@ -12,6 +12,14 @@ #include "CDefaultSpellMechanics.h" +class DLL_LINKAGE HealingSpellMechanics : public DefaultSpellMechanics +{ +public: + HealingSpellMechanics(CSpell * s): DefaultSpellMechanics(s){}; +protected: + void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override; +}; + class DLL_LINKAGE AntimagicMechanics : public DefaultSpellMechanics { public: @@ -36,10 +44,10 @@ protected: void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override; }; -class DLL_LINKAGE CureMechanics : public DefaultSpellMechanics +class DLL_LINKAGE CureMechanics : public HealingSpellMechanics { public: - CureMechanics(CSpell * s): DefaultSpellMechanics(s){}; + CureMechanics(CSpell * s): HealingSpellMechanics(s){}; void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final; }; @@ -96,10 +104,10 @@ protected: }; ///all rising spells -class DLL_LINKAGE RisingSpellMechanics : public DefaultSpellMechanics +class DLL_LINKAGE RisingSpellMechanics : public HealingSpellMechanics { public: - RisingSpellMechanics(CSpell * s): DefaultSpellMechanics(s){}; + RisingSpellMechanics(CSpell * s): HealingSpellMechanics(s){}; }; diff --git a/lib/spells/CDefaultSpellMechanics.cpp b/lib/spells/CDefaultSpellMechanics.cpp index 1a2de536a..d17f27492 100644 --- a/lib/spells/CDefaultSpellMechanics.cpp +++ b/lib/spells/CDefaultSpellMechanics.cpp @@ -499,7 +499,7 @@ int DefaultSpellMechanics::calculateDuration(const CGHeroInstance * caster, int return caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + caster->valOfBonuses(Bonus::SPELL_DURATION); } -void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const +int DefaultSpellMechanics::calculateEffectLevel(const BattleSpellCastParameters& parameters) const { int effectLevel = parameters.spellLvl; { @@ -508,7 +508,14 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, if(parameters.casterHero->hasBonusOfType(Bonus::MAXED_SPELL, owner->id)) effectLevel = 3; } + + return effectLevel; +} + +void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const +{ + int effectLevel = calculateEffectLevel(parameters); //applying effects if(owner->isOffensiveSpell()) { @@ -642,54 +649,7 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, if(!sse.stacks.empty()) env->sendAndApply(&sse); - } - - if(owner->isHealingSpell()) - { - int hpGained = 0; - if(parameters.casterStack) - { - int unitSpellPower = parameters.casterStack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, owner->id.toEnum()); - if(unitSpellPower) - hpGained = parameters.casterStack->count * unitSpellPower; //Archangel - else //Faerie Dragon-like effect - commanders(?) - { - parameters.usedSpellPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * parameters.casterStack->count / 100; - hpGained = parameters.usedSpellPower * owner->power + owner->getPower(effectLevel); - } - } - else - { - if (owner->id == SpellID::SACRIFICE && parameters.selectedStack) - hpGained = (parameters.usedSpellPower + parameters.selectedStack->MaxHealth() + owner->getPower(effectLevel)) * parameters.selectedStack->count; - else - hpGained = parameters.usedSpellPower * owner->power + owner->getPower(effectLevel); //??? - } - StacksHealedOrResurrected shr; - shr.lifeDrain = false; - shr.tentHealing = false; - - const bool resurrect = owner->isRisingSpell(); - for(auto & attackedCre : ctx.attackedCres) - { - StacksHealedOrResurrected::HealInfo hi; - hi.stackID = (attackedCre)->ID; - if (parameters.casterStack) //casted by creature - { - hi.healedHP = attackedCre->calculateHealedHealthPoints(hpGained, resurrect); - } - else - { - int stackHPgained = parameters.casterHero->getSpellBonus(owner, hpGained, attackedCre); - hi.healedHP = attackedCre->calculateHealedHealthPoints(stackHPgained, resurrect); - } - - hi.lowLevelResurrection = (effectLevel <= 1) && (owner->id == SpellID::RESURRECTION); - shr.healedStacks.push_back(hi); - } - if(!shr.healedStacks.empty()) - env->sendAndApply(&shr); - } + } } std::vector DefaultSpellMechanics::rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes) const diff --git a/lib/spells/CDefaultSpellMechanics.h b/lib/spells/CDefaultSpellMechanics.h index 95da4d8b0..6aa865450 100644 --- a/lib/spells/CDefaultSpellMechanics.h +++ b/lib/spells/CDefaultSpellMechanics.h @@ -54,9 +54,10 @@ protected: virtual void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const; virtual int calculateDuration(const CGHeroInstance * caster, int usedSpellPower) const; - + int calculateEffectLevel(const BattleSpellCastParameters & parameters) const; + ///actual adventure cast implementation virtual ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const; - void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const; + void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const; };