From 4d14f613f3d0dc579e2ca4b8dead65ac6e43965d Mon Sep 17 00:00:00 2001 From: ariel- Date: Mon, 12 Feb 2018 16:52:59 -0300 Subject: Core/Unit: corrected calculation for SPELL_AURA_MOD_DAMAGE_TAKEN/SPELL_AURA_MOD_HEALING auras - Spell bonus calculation and penalty was done twice, but it's simply flat +SP, which should be taken into account before other bonuses - Fixed missing code from SpellDamageBonusDone/SpellHealingBonusDone and killed multiplication by stack amount twice for default coefficient spells (already multiplied on level penalty) --- src/server/game/Entities/Unit/Unit.cpp | 123 ++++++++-------------------- src/server/game/Entities/Unit/Unit.h | 2 - src/server/scripts/Spells/spell_paladin.cpp | 16 +++- src/server/scripts/Spells/spell_shaman.cpp | 20 +++-- 4 files changed, 58 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 34838bd3f67..ee89eab0cbc 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6883,6 +6883,9 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin // Done fixed damage bonus auras int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask()); + // modify spell power by victim's SPELL_AURA_MOD_DAMAGE_TAKEN auras (eg Amplify/Dampen Magic) + DoneAdvertisedBenefit += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, spellProto->GetSchoolMask()); + // Pets just add their bonus damage to their spell damage // note that their spell damage is just gain of their own auras if (HasUnitTypeMask(UNIT_MASK_GUARDIAN)) @@ -6909,10 +6912,19 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus); } } + else + { + // No bonus damage for SPELL_DAMAGE_CLASS_NONE class spells by default + if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE) + return uint32(std::max(pdamage * DoneTotalMod, 0.0f)); + } // Default calculation - if (coeff && DoneAdvertisedBenefit) + if (DoneAdvertisedBenefit) { + if (coeff < 0.f) + coeff = CalculateDefaultCoefficient(spellProto, damagetype); // As wowwiki says: C = (Cast Time / 3.5) + float factorMod = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * stack; if (Player* modOwner = GetSpellModOwner()) { @@ -7247,7 +7259,6 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui if (!spellProto || damagetype == DIRECT_DAMAGE) return pdamage; - int32 TakenTotal = 0; float TakenTotalMod = 1.0f; // Mod damage from spell mechanic @@ -7298,27 +7309,6 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui return false; }); } - - int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask()); - - // Check for table values - 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 (coeff < 0.f) - { - 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 = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * stack; - TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod); - } } // Sanctified Wrath (bypass damage reduction) @@ -7337,7 +7327,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui TakenTotalMod = 1.0f - damageReduction; } - float tmpDamage = float(pdamage + TakenTotal) * TakenTotalMod; + float tmpDamage = pdamage * TakenTotalMod; return uint32(std::max(tmpDamage, 0.0f)); } @@ -7369,11 +7359,6 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const return DoneAdvertisedBenefit; } -int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const -{ - return GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, schoolMask); -} - float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/, bool isPeriodic /*= false*/) const { //! Mobs can't crit with spells. (Except player controlled) @@ -7750,36 +7735,48 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui // Done fixed damage bonus auras int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask()); + // modify spell power by victim's SPELL_AURA_MOD_HEALING auras (eg Amplify/Dampen Magic) + DoneAdvertisedBenefit += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_HEALING, spellProto->GetSchoolMask()); + + // Pets just add their bonus damage to their spell damage + // note that their spell damage is just gain of their own auras + if (HasUnitTypeMask(UNIT_MASK_GUARDIAN)) + DoneAdvertisedBenefit += static_cast(this)->GetBonusDamage(); // Check for table values float coeff = 0.f; 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)); + APbonus += GetTotalAttackPowerValue(attType); + if (damagetype == DOT) { coeff = bonus->dot_damage; if (bonus->ap_dot_bonus > 0) - DoneTotal += int32(bonus->ap_dot_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue( - (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK)); + DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus); } else { coeff = bonus->direct_damage; if (bonus->ap_bonus > 0) - DoneTotal += int32(bonus->ap_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue( - (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK)); + DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus); } } else { // No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE) - return healamount; + return uint32(std::max(healamount * DoneTotalMod, 0.0f)); } // Default calculation - if (coeff && DoneAdvertisedBenefit) + if (DoneAdvertisedBenefit) { + if (coeff < 0.f) + coeff = CalculateDefaultCoefficient(spellProto, damagetype) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells) + float factorMod = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * stack; if (Player* modOwner = GetSpellModOwner()) { @@ -7911,12 +7908,6 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u if (AuraEffect const* Tenacity = GetAuraEffect(58549, 0)) AddPct(TakenTotalMod, Tenacity->GetAmount()); - // Healing Done - int32 TakenTotal = 0; - - // Taken fixed damage bonus auras - int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSchoolMask()); - // Nourish cast if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000) { @@ -7938,34 +7929,6 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u AddPct(TakenTotalMod, maxval_hot); } - // Check for table values - float coeff = 0; - if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) - coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage; - else - { - // No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default - if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE) - { - healamount = uint32(std::max((float(healamount) * TakenTotalMod), 0.0f)); - return healamount; - } - } - - // Default calculation - if (TakenAdvertisedBenefit) - { - if (coeff < 0.f) - { - 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) - } - - // level penalty still applied on Taken bonus - is it blizzlike? - float factorMod = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * int32(stack); - TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod); - } - if (caster) { TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) -> bool @@ -7976,22 +7939,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u }); } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - switch (spellProto->Effects[i].ApplyAuraName) - { - // Bonus healing does not apply to these spells - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: - TakenTotal = 0; - break; - } - if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) - TakenTotal = 0; - } - - float heal = float(int32(healamount) + TakenTotal) * TakenTotalMod; - + float heal = healamount * TakenTotalMod; return uint32(std::max(heal, 0.0f)); } @@ -8028,11 +7976,6 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const return advertisedBenefit; } -int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const -{ - return GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_HEALING, schoolMask); -} - bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const { if (schoolMask == SPELL_SCHOOL_MASK_NONE) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 56883760971..706a2a8cc91 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1514,12 +1514,10 @@ class TC_GAME_API Unit : public WorldObject Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = nullptr); int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const; - int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const; uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, Optional const& donePctTotal, uint32 stack = 1) const; float SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const; uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const; int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const; - int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const; uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, Optional const& donePctTotal, uint32 stack = 1) const; float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const; uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const; diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index c76f0325c29..c8eaa11810b 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -2022,13 +2022,21 @@ class spell_pal_seal_of_righteousness : public SpellScriptLoader { PreventDefaultAction(); + Unit* victim = eventInfo.GetProcTarget(); + float ap = GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = GetTarget()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY); - holy += eventInfo.GetProcTarget()->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY); - int32 bp = int32((ap * 0.022f + 0.044f * holy) * GetTarget()->GetAttackTime(BASE_ATTACK) / 1000); + ap += victim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS); + + int32 sph = GetTarget()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY); + sph += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, SPELL_SCHOOL_MASK_HOLY); + + float mws = GetTarget()->GetAttackTime(BASE_ATTACK); + mws /= 1000.0f; + + int32 bp = int32(mws * (0.022f * ap + 0.044f * sph)); CastSpellExtraArgs args(aurEff); args.AddSpellBP0(bp); - GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS, args); + GetTarget()->CastSpell(victim, SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS, args); } void Register() override diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index a9101e16c46..1b3d63a7ac2 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -715,7 +715,7 @@ class spell_sha_flametongue_weapon : public SpellScriptLoader if (!item || !item->IsEquipped()) return false; - WeaponAttackType attType = static_cast(player->GetAttackBySlot(item->GetSlot())); + WeaponAttackType attType = Player::GetAttackBySlot(item->GetSlot()); if (attType != BASE_ATTACK && attType != OFF_ATTACK) return false; @@ -738,26 +738,32 @@ class spell_sha_flametongue_weapon : public SpellScriptLoader Item* item = ASSERT_NOTNULL(player->GetWeaponForAttack(attType)); - float const basePoints = GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue(); + float basePoints = GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue(); // Flametongue max damage is normalized based on a 4.0 speed weapon // Tooltip says max damage = BasePoints / 25, so BasePoints / 25 / 4 to get base damage per 1.0s AS + float attackSpeed = player->GetAttackTime(attType) / 1000.f; float fireDamage = basePoints / 100.0f; - float const attackSpeed = player->GetAttackTime(attType) / 1000.f; fireDamage *= attackSpeed; // clip value between (BasePoints / 77) and (BasePoints / 25) as the tooltip indicates RoundToInterval(fireDamage, basePoints / 77.0f, basePoints / 25.0f); // Calculate Spell Power scaling - float spellPowerBonus = player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) + target->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE); + float spellPowerBonus = player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE); + spellPowerBonus += target->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, SPELL_SCHOOL_MASK_FIRE); + + // calculate penalty from passive aura as is the one with level + float const factorMod = player->CalculateSpellpowerCoefficientLevelPenalty(GetSpellInfo()); + float const spCoeff = 0.03811f; - spellPowerBonus *= spCoeff * attackSpeed; + spellPowerBonus *= spCoeff * attackSpeed * factorMod; // All done, now proc damage CastSpellExtraArgs args(aurEff); - args.CastItem = item; - args.AddSpellBP0(fireDamage + spellPowerBonus); + args + .SetCastItem(item) + .AddSpellBP0(fireDamage + spellPowerBonus); player->CastSpell(target, SPELL_SHAMAN_FLAMETONGUE_ATTACK, args); } -- cgit v1.2.3