diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 642fdeb94..69017b115 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -168,7 +168,7 @@ ui32 CBattleInfoCallback::calculateHealedHP(const CGHeroInstance * caster, const healedHealth = (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + sacrificedStack->MaxHealth() + spell->getPower(caster->getSpellSchoolLevel(spell))) * sacrificedStack->count; else healedHealth = caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) * spell->power + spell->getPower(caster->getSpellSchoolLevel(spell)); //??? - healedHealth = calculateSpellBonus(healedHealth, spell, caster, stack); + healedHealth = spell->calculateBonus(healedHealth, caster, stack); return std::min(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0)); } //Archangel diff --git a/lib/CBattleCallback.cpp b/lib/CBattleCallback.cpp index c0a40825d..185337efa 100644 --- a/lib/CBattleCallback.cpp +++ b/lib/CBattleCallback.cpp @@ -1647,8 +1647,8 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleStackIsImmune(co //TODO: what with other creatures casting hypnotize, Faerie Dragons style? ui64 subjectHealth = (subject->count - 1) * subject->MaxHealth() + subject->firstHPleft; //apply 'damage' bonus for hypnotize, including hero specialty - ui64 maxHealth = calculateSpellBonus (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) - * spell->power + spell->getPower(caster->getSpellSchoolLevel(spell)), spell, caster, subject); + ui64 maxHealth = spell->calculateBonus (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + * spell->power + spell->getPower(caster->getSpellSchoolLevel(spell)), caster, subject); if (subjectHealth > maxHealth) return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; } @@ -1945,30 +1945,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell return battleIsImmune(nullptr, spell, mode, dest); } -ui32 CBattleInfoCallback::calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const -{ - ui32 ret = baseDamage; - //applying sorcery secondary skill - if(caster) - { - ret *= (100.0 + caster->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::SORCERY)) / 100.0; - ret *= (100.0 + caster->valOfBonuses(Bonus::SPELL_DAMAGE) + caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, sp->id.toEnum())) / 100.0; - - if(sp->air) - ret *= (100.0 + caster->valOfBonuses(Bonus::AIR_SPELL_DMG_PREMY)) / 100.0; - else if(sp->fire) //only one type of bonus for Magic Arrow - ret *= (100.0 + caster->valOfBonuses(Bonus::FIRE_SPELL_DMG_PREMY)) / 100.0; - else if(sp->water) - ret *= (100.0 + caster->valOfBonuses(Bonus::WATER_SPELL_DMG_PREMY)) / 100.0; - else if(sp->earth) - ret *= (100.0 + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0; - - if (affectedCreature && affectedCreature->getCreature()->level) //Hero specials like Solmyr, Deemer - ret *= (100. + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, sp->id.toEnum()) * caster->level) / affectedCreature->getCreature()->level)) / 100.0; - } - return ret; -} - ui32 CBattleInfoCallback::calculateSpellDmg( const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower ) const { ui32 ret = 0; //value to return @@ -2018,7 +1994,7 @@ ui32 CBattleInfoCallback::calculateSpellDmg( const CSpell * sp, const CGHeroInst ret /= 100; } } - ret = calculateSpellBonus(ret, sp, caster, affectedCreature); + ret = sp->calculateBonus(ret, caster, affectedCreature); return ret; } diff --git a/lib/CBattleCallback.h b/lib/CBattleCallback.h index 7ab326620..5d8a653e5 100644 --- a/lib/CBattleCallback.h +++ b/lib/CBattleCallback.h @@ -281,7 +281,6 @@ public: ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here std::vector battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const; - ui32 calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const; ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack = nullptr) const; //Sacrifice ui32 calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const; //for Archangel diff --git a/lib/CSpellHandler.cpp b/lib/CSpellHandler.cpp index 5245e2836..f2e4c7171 100644 --- a/lib/CSpellHandler.cpp +++ b/lib/CSpellHandler.cpp @@ -297,6 +297,30 @@ const CSpell::LevelInfo & CSpell::getLevelInfo(const int level) const return levels.at(level); } +ui32 CSpell::calculateBonus(ui32 baseDamage, const CGHeroInstance* caster, const CStack* affectedCreature) const +{ + ui32 ret = baseDamage; + //applying sorcery secondary skill + if(caster) + { + ret *= (100.0 + caster->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::SORCERY)) / 100.0; + ret *= (100.0 + caster->valOfBonuses(Bonus::SPELL_DAMAGE) + caster->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, id.toEnum())) / 100.0; + + if(air) + ret *= (100.0 + caster->valOfBonuses(Bonus::AIR_SPELL_DMG_PREMY)) / 100.0; + else if(fire) //only one type of bonus for Magic Arrow + ret *= (100.0 + caster->valOfBonuses(Bonus::FIRE_SPELL_DMG_PREMY)) / 100.0; + else if(water) + ret *= (100.0 + caster->valOfBonuses(Bonus::WATER_SPELL_DMG_PREMY)) / 100.0; + else if(earth) + ret *= (100.0 + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0; + + if (affectedCreature && affectedCreature->getCreature()->level) //Hero specials like Solmyr, Deemer + ret *= (100. + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, id.toEnum()) * caster->level) / affectedCreature->getCreature()->level)) / 100.0; + } + return ret; +} + std::vector CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes) const { diff --git a/lib/CSpellHandler.h b/lib/CSpellHandler.h index b72626659..35472f7ff 100644 --- a/lib/CSpellHandler.h +++ b/lib/CSpellHandler.h @@ -127,6 +127,9 @@ public: //checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into acount general problems such as not having spellbook or mana points etc. ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, ECastingMode::ECastingMode mode, const CStack * obj) const; + + //applying secondary skills + ui32 calculateBonus(ui32 baseDamage, const CGHeroInstance * caster, const CStack * affectedCreature) const; si32 getCost(const int skillLevel) const;