diff options
author | ariel- <ariel-@users.noreply.github.com> | 2018-01-13 19:57:20 -0300 |
---|---|---|
committer | ariel- <ariel-@users.noreply.github.com> | 2018-01-13 20:49:44 -0300 |
commit | d570e2af3e7bcb625d8941397d55972d49319a8f (patch) | |
tree | d1f0e8cfa2651b34b808255b3a03260182ae0ba3 | |
parent | a3056617854ec3957ed57126e27c6b3bea066448 (diff) |
Core/Unit: simplified and arranged spell bonus calculation
- Remove duplicated SPELLMOD_BONUS_MULTIPLIER handling (both on done and taken)
- Handle properly bonus data, don't apply bonus by default, only player spells should take into account spell power
- Moved Earthliving Weapon coefficient to DB
- Refactored Avenging Wrath handling
Closes #13287
Closes #21230
-rw-r--r-- | sql/updates/world/3.3.5/2018_01_13_01_world_335.sql | 8 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 159 |
2 files changed, 73 insertions, 94 deletions
diff --git a/sql/updates/world/3.3.5/2018_01_13_01_world_335.sql b/sql/updates/world/3.3.5/2018_01_13_01_world_335.sql new file mode 100644 index 00000000000..9672b738d25 --- /dev/null +++ b/sql/updates/world/3.3.5/2018_01_13_01_world_335.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_bonus_data` WHERE `entry` IN (51945, 51990, 51997, 51998, 51999, 52000); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(51945, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 1)'), +(51990, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 2)'), +(51997, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 3)'), +(51998, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 4)'), +(51999, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 5)'), +(52000, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 6)'); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 620cbc31555..2082b974ef6 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6771,8 +6771,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin // Check for table values float coeff = 0.f; - SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); - if (bonus) + if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) { WeaponAttackType const attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); @@ -6793,19 +6792,16 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin } // Default calculation - if (DoneAdvertisedBenefit) + if (coeff && DoneAdvertisedBenefit) { - if (!bonus || coeff < 0) - coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack); - float factorMod = CalculateLevelPenalty(spellProto) * stack; - if (Player* modOwner = GetSpellModOwner()) { coeff *= 100.0f; modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); coeff /= 100.0f; } + DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); } @@ -7134,7 +7130,6 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui int32 TakenTotal = 0; float TakenTotalMod = 1.0f; - float TakenTotalCasterMod = 0.0f; // Mod damage from spell mechanic if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask()) @@ -7166,67 +7161,64 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui break; } } - // Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras. + + // Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras. if (!spellProto->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) { - // get all auras from caster that allow the spell to ignore resistance (sanctified wrath) - TakenTotalCasterMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, spellProto->GetSchoolMask()); - // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085) TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto->GetSchoolMask()); // From caster spells - TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_FROM_CASTER, [caster, spellProto](AuraEffect const* aurEff) -> bool + if (caster) { - if (aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectedOnSpell(spellProto)) - return true; - return false; - }); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_FROM_CASTER, [caster, spellProto](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectedOnSpell(spellProto)) + return true; + return false; + }); + } int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask()); // Check for table values - float coeff = 0; - SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); - if (bonus) + float coeff = 0.f; + if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage; // Default calculation if (TakenAdvertisedBenefit) { - if (!bonus || coeff < 0) - coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack); - - float factorMod = CalculateLevelPenalty(spellProto) * stack; - // level penalty still applied on Taken bonus - is it blizzlike? - if (Player* modOwner = GetSpellModOwner()) + if (coeff < 0.f) { - coeff *= 100.0f; - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); - coeff /= 100.0f; + Unit const* calc = caster ? caster : this; + coeff = calc->CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack); } + + // level penalty still applied on Taken bonus - is it blizzlike? + float factorMod = CalculateLevelPenalty(spellProto) * stack; TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod); } } - float tmpDamage = 0.0f; - - if (TakenTotalCasterMod) + // Sanctified Wrath (bypass damage reduction) + if (caster && TakenTotalMod < 1.0f) { - if (TakenTotal < 0) + float damageReduction = 1.0f - TakenTotalMod; + Unit::AuraEffectList const& casterIgnoreResist = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffect const* aurEff : casterIgnoreResist) { - if (TakenTotalMod < 1) - tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenTotal) * TakenTotalMod) + CalculatePct(pdamage, TakenTotalCasterMod)); - else - tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenTotal) + CalculatePct(pdamage, TakenTotalCasterMod)) * TakenTotalMod); + if (!(aurEff->GetMiscValue() & spellProto->GetSchoolMask())) + continue; + + ApplyPct(damageReduction, aurEff->GetAmount()); } - else if (TakenTotalMod < 1) - tmpDamage = ((CalculatePct(float(pdamage) + TakenTotal, TakenTotalCasterMod) * TakenTotalMod) + CalculatePct(float(pdamage) + TakenTotal, TakenTotalCasterMod)); + + TakenTotalMod = 1.0f - damageReduction; } - if (!tmpDamage) - tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod; + float tmpDamage = float(pdamage + TakenTotal) * TakenTotalMod; return uint32(std::max(tmpDamage, 0.0f)); } @@ -7641,10 +7633,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask()); // Check for table values - SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); - float coeff = 0; - float factorMod = 1.0f; - if (bonus) + float coeff = 0.f; + if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) { if (damagetype == DOT) { @@ -7669,13 +7659,9 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui } // Default calculation - if (DoneAdvertisedBenefit) + if (coeff && DoneAdvertisedBenefit) { - if (!bonus || coeff < 0) - coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells) - - factorMod *= CalculateLevelPenalty(spellProto) * stack; - + float factorMod = CalculateLevelPenalty(spellProto) * stack; if (Player* modOwner = GetSpellModOwner()) { coeff *= 100.0f; @@ -7683,10 +7669,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui coeff /= 100.0f; } - // Earthliving - 0.45% of normal hot coeff - if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000) - factorMod *= 0.45f; - DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); } @@ -7838,10 +7820,8 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u } // Check for table values - SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); float coeff = 0; - float factorMod = 1.0f; - if (bonus) + if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage; else { @@ -7856,30 +7836,26 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u // Default calculation if (TakenAdvertisedBenefit) { - if (!bonus || coeff < 0) - coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells) - - factorMod *= CalculateLevelPenalty(spellProto) * int32(stack); - if (Player* modOwner = GetSpellModOwner()) + if (coeff < 0.f) { - coeff *= 100.0f; - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); - coeff /= 100.0f; + Unit const* calc = caster ? caster : this; + coeff = calc->CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells) } - // Earthliving - 0.45% of normal hot coeff - if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000) - factorMod *= 0.45f; - + // level penalty still applied on Taken bonus - is it blizzlike? + float factorMod = CalculateLevelPenalty(spellProto) * int32(stack); TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod); } - TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) -> bool + if (caster) { - if (caster->GetGUID() == aurEff->GetCasterGUID() && aurEff->IsAffectedOnSpell(spellProto)) - return true; - return false; - }); + TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) -> bool + { + if (caster->GetGUID() == aurEff->GetCasterGUID() && aurEff->IsAffectedOnSpell(spellProto)) + return true; + return false; + }); + } for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { @@ -8299,11 +8275,6 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT return 0; int32 TakenFlatBenefit = 0; - float TakenTotalCasterMod = 0.0f; - - // get all auras from caster that allow the spell to ignore resistance (sanctified wrath) - SpellSchoolMask const attackSchoolMask = spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL; - TakenTotalCasterMod += attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, attackSchoolMask); // ..taken TakenFlatBenefit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, attacker->GetMeleeDamageSchoolMask()); @@ -8382,24 +8353,25 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT else TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); - float tmpDamage = 0.0f; - - if (TakenTotalCasterMod) + // Sanctified Wrath (bypass damage reduction) + if (attacker && TakenTotalMod < 1.0f) { - if (TakenFlatBenefit < 0) + SpellSchoolMask const attackSchoolMask = spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL; + + float damageReduction = 1.0f - TakenTotalMod; + Unit::AuraEffectList const& casterIgnoreResist = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffect const* aurEff : casterIgnoreResist) { - if (TakenTotalMod < 1) - tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) * TakenTotalMod) + CalculatePct(pdamage, TakenTotalCasterMod)); - else - tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) + CalculatePct(pdamage, TakenTotalCasterMod)) * TakenTotalMod); + if (!(aurEff->GetMiscValue() & attackSchoolMask)) + continue; + + ApplyPct(damageReduction, aurEff->GetAmount()); } - else if (TakenTotalMod < 1) - tmpDamage = ((CalculatePct(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod) * TakenTotalMod) + CalculatePct(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod)); + + TakenTotalMod = 1.0f - damageReduction; } - if (!tmpDamage) - tmpDamage = (float(pdamage) + TakenFlatBenefit) * TakenTotalMod; - // bonus result can be negative + float tmpDamage = float(pdamage + TakenFlatBenefit) * TakenTotalMod; return uint32(std::max(tmpDamage, 0.0f)); } @@ -11505,7 +11477,6 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect float DotFactor = 1.0f; if (damagetype == DOT) { - int32 DotDuration = spellInfo->GetDuration(); if (!spellInfo->IsChanneled() && DotDuration > 0) DotFactor = DotDuration / 15000.0f; |