diff --git a/sql/updates/world/custom/custom_2019_11_08_00_world.sql b/sql/updates/world/custom/custom_2019_11_08_00_world.sql new file mode 100644 index 00000000000..955d704c0a5 --- /dev/null +++ b/sql/updates/world/custom/custom_2019_11_08_00_world.sql @@ -0,0 +1,7 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`= 'spell_warr_devastate'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(20243, 'spell_warr_devastate'); + +DELETE FROM `spell_bonus_data` WHERE `entry`= 53351; +INSERT INTO `spell_bonus_data` (`entry`, `ap_bonus`, `comments`) VALUES +(53351, 0.45, 'Hunter - Kill Shot'); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2e95e5f8758..9ae316a99fa 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -7929,7 +7929,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit return false; } -uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto) +uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto /*= nullptr*/, bool useSpellBonusData /*= true*/) { if (!victim || pdamage == 0) return 0; @@ -7969,7 +7969,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType DoneFlatBenefit += int32(APbonus / 14.0f * GetAPMultiplier(attType, normalized)); } - if (spellProto) + if (spellProto && useSpellBonusData) { // Check for table values if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) @@ -8021,8 +8021,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType // Add SPELL_AURA_MOD_AUTOATTACK_DAMAGE percent bonus if (!spellProto) - for (AuraEffect const* meleeBonusEff : GetAuraEffectsByType(SPELL_AURA_MOD_AUTOATTACK_DAMAGE)) - AddPct(DoneTotalMod, meleeBonusEff->GetAmount()); + AddPct(DoneTotalMod, GetTotalAuraModifier(SPELL_AURA_MOD_AUTOATTACK_DAMAGE)); // done scripted mod (take it from owner) // Unit* owner = GetOwner() ? GetOwner() : this; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index ddc8cfc2277..f78fc107a40 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1718,7 +1718,7 @@ class TC_GAME_API Unit : public WorldObject float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const; uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const; - uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr); + uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr, bool useSpellBonusData = true); uint32 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr); bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 11569818b03..0bd333884d9 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2758,42 +2758,44 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) if (!unitTarget || !unitTarget->IsAlive()) return; - // multiple weapon dmg effect workaround - // execute only the last weapon damage - // and handle all effects at once - for (uint8 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + uint32 effectType = m_spellInfo->Effects[effIndex].Effect; + bool useWeaponDamage = true; + + /* + Multiple weapon damage effect case. SPELL_EFFECT_WEAPON_PERCENT_DAMAGE is being prioritized for calculating weapon damage values. + The other effects only add their fixed bonus to the damage sum. + */ + if (m_spellInfo->HasEffect(SPELL_EFFECT_WEAPON_PERCENT_DAMAGE) && effectType != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE) + useWeaponDamage = false; + + // some spell specific modifiers + float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage + int32 fixed_bonus = 0; + + bool normalized = false; + float weaponDamagePercentMod = 1.0f; + for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) { switch (m_spellInfo->Effects[j].Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + fixed_bonus += damage; + break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + fixed_bonus += damage; + normalized = true; + break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - return; // we must calculate only at last weapon effect - break; + ApplyPct(weaponDamagePercentMod, damage); + break; + default: + break; // not weapon damage effect, just skip } } - // some spell specific modifiers - float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage - int32 fixed_bonus = 0; - int32 spell_bonus = 0; // bonus specific for spell - switch (m_spellInfo->SpellFamilyName) { - case SPELLFAMILY_WARRIOR: - { - // Devastate - if (m_spellInfo->SpellFamilyFlags[1] & 0x40 && effIndex == EFFECT_1) - { - if (Aura* aur = unitTarget->GetAura(58567, m_caster->GetGUID())) - fixed_bonus += aur->GetStackAmount() * CalculateDamage(EFFECT_1, unitTarget); - - // Devastate applies Sunder Armor on the target - m_caster->CastSpell(unitTarget, 58567, true); - } - break; - } case SPELLFAMILY_ROGUE: { // Hemorrhage @@ -2833,13 +2835,6 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) } break; } - case SPELLFAMILY_HUNTER: - { - // Kill Shot - bonus damage from Ranged Attack Power - if (m_spellInfo->SpellFamilyFlags[1] & 0x800000) - spell_bonus += int32(0.45f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)); - break; - } case SPELLFAMILY_DEATHKNIGHT: { // Death Strike @@ -2851,6 +2846,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) if (uint32 runic = std::min(uint32(m_caster->GetPower(POWER_RUNIC_POWER) / 2.5f), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster))) AddPct(totalDamagePercentMod, runic); } + // Obliterate / Blood Strike / Blood-Caked Strike (12.5% more damage per disease) / Heart Strike (15% more damage per disease) if (m_spellInfo->SpellFamilyFlags[1] & 0x20000 || m_spellInfo->SpellFamilyFlags[0] & 0x400000 || m_spellInfo->SpellFamilyFlags[0] & 0x1000000 || m_spellInfo->Id == 50463) @@ -2858,7 +2854,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster); uint8 diseaseCount = unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), false); - if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) // Obliterate - Half amount of Basepoints as bonus + if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) // Obliterate - 50% of Basepoints as bonus bonusPct *= 0.5f; else if (m_spellInfo->SpellFamilyFlags[0] & 0x400000) // Blood Strike - 10% of Basepoints as bonus bonusPct *= 0.1f; @@ -2867,6 +2863,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Death Knight T8 Melee 4P Bonus if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) AddPct(bonusAmount, aurEff->GetAmount()); + AddPct(totalDamagePercentMod, bonusAmount); } @@ -2883,44 +2880,26 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) } case SPELLFAMILY_WARLOCK: { - // Felstorm and Legion Strike - if (m_spellInfo->Id == 89753) + if (useWeaponDamage) { - if (m_caster->IsPet()) - if (Unit* owner = m_caster->GetOwner()) - m_damage += ((owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.5f) * 2) * 0.231f; - } - else if (m_spellInfo->Id == 30213) - { - if (m_caster->IsPet()) - if (Unit* owner = m_caster->GetOwner()) - m_damage += ((owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.5f) * 2) * 0.264f; + // Felstorm and Legion Strike + if (m_spellInfo->Id == 89753) + { + if (m_caster->IsPet()) + if (Unit* owner = m_caster->GetOwner()) + m_damage += ((owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.5f) * 2) * 0.231f; + } + else if (m_spellInfo->Id == 30213) + { + if (m_caster->IsPet()) + if (Unit* owner = m_caster->GetOwner()) + m_damage += ((owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.5f) * 2) * 0.264f; + } } break; } } - bool normalized = false; - float weaponDamagePercentMod = 1.0f; - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) - { - switch (m_spellInfo->Effects[j].Effect) - { - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(j, unitTarget); - break; - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(j, unitTarget); - normalized = true; - break; - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget)); - break; - default: - break; // not weapon damage effect, just skip - } - } // if (addPctMods) { percent mods are added in Unit::CalculateDamage } else { percent mods are added in Unit::MeleeDamageBonusDone } // this distinction is neccessary to properly inform the client about his autoattack damage values from Script_UnitDamage @@ -2939,33 +2918,24 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT); if (fixed_bonus) fixed_bonus = int32(fixed_bonus * weapon_total_pct); - if (spell_bonus) - spell_bonus = int32(spell_bonus * weapon_total_pct); } - int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, addPctMods); + int32 weaponDamage = useWeaponDamage ? m_caster->CalculateDamage(m_attackType, normalized, addPctMods) : 0; - // Sequence is important - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + switch (effectType) { - // We assume that a spell have at most one fixed_bonus - // and at most one weaponDamagePercentMod - switch (m_spellInfo->Effects[j].Effect) - { - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - weaponDamage += fixed_bonus; - break; - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - weaponDamage = int32(weaponDamage * weaponDamagePercentMod); - break; - default: - break; // not weapon damage effect, just skip - } + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + weaponDamage += fixed_bonus; + break; + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + weaponDamage = int32(weaponDamage * weaponDamagePercentMod); + break; + default: + break; } - weaponDamage += spell_bonus; weaponDamage = int32(weaponDamage * totalDamagePercentMod); // apply spellmod to Done damage @@ -2976,7 +2946,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) weaponDamage = std::max(weaponDamage, 0); // Add melee damage bonuses (also check for negative) - weaponDamage = m_caster->MeleeDamageBonusDone(unitTarget, weaponDamage, m_attackType, m_spellInfo); + weaponDamage = m_caster->MeleeDamageBonusDone(unitTarget, weaponDamage, m_attackType, m_spellInfo, !useWeaponDamage); m_damage += unitTarget->MeleeDamageBonusTaken(m_caster, weaponDamage, m_attackType, m_spellInfo); } diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index d2b794f87c9..1093801e37f 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -1196,6 +1196,35 @@ class spell_warr_shockwave : public SpellScript } }; +class spell_warr_devastate : public SpellScript +{ + PrepareSpellScript(spell_warr_devastate); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_WARRIOR_SUNDER_ARMOR }); + } + + void HandleDamageBonus(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + if (Aura* sunder = GetHitUnit()->GetAura(SPELL_WARRIOR_SUNDER_ARMOR, caster->GetGUID())) + SetEffectValue(GetEffectValue() + GetEffectValue() * sunder->GetStackAmount()); + } + + void HandleSunderArmor(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetHitUnit(), SPELL_WARRIOR_SUNDER_ARMOR, true); + } + + void Register() override + { + OnEffectLaunchTarget += SpellEffectFn(spell_warr_devastate::HandleDamageBonus, EFFECT_1, SPELL_EFFECT_NORMALIZED_WEAPON_DMG); + OnEffectHitTarget += SpellEffectFn(spell_warr_devastate::HandleSunderArmor, EFFECT_1, SPELL_EFFECT_NORMALIZED_WEAPON_DMG); + } +}; + void AddSC_warrior_spell_scripts() { RegisterAuraScript(spell_warr_blood_craze); @@ -1204,6 +1233,7 @@ void AddSC_warrior_spell_scripts() new spell_warr_charge(); RegisterSpellScript(spell_warr_concussion_blow); new spell_warr_deep_wounds(); + RegisterSpellScript(spell_warr_devastate); new spell_warr_execute(); new spell_warr_glyph_of_sunder_armor(); new spell_warr_intimidating_shout();