From cde7258411a9ca5328ab2404ccf1b9bb809458d9 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 23 Feb 2026 22:38:34 +0100 Subject: [PATCH] Scripts/Spells: Implement Execute damage and Improved Execute (arms) (#31658) --- .../world/master/2026_02_23_03_world.sql | 9 ++ src/server/scripts/Spells/spell_warrior.cpp | 117 +++++++++++++++++- 2 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 sql/updates/world/master/2026_02_23_03_world.sql diff --git a/sql/updates/world/master/2026_02_23_03_world.sql b/sql/updates/world/master/2026_02_23_03_world.sql new file mode 100644 index 0000000000..cc72d8dc25 --- /dev/null +++ b/sql/updates/world/master/2026_02_23_03_world.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warr_execute', 'spell_warr_execute_refund_rage'); +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warr_execute_damage') AND `spell_id` IN (317483); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(163201, 'spell_warr_execute'), +(281000, 'spell_warr_execute'), +(330334, 'spell_warr_execute'), +(317349, 'spell_warr_execute'), +(317483, 'spell_warr_execute_damage'), +(260798, 'spell_warr_execute_refund_rage'); diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 8e762327b9..f182286e34 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -53,8 +53,8 @@ enum WarriorSpells SPELL_WARRIOR_COLOSSUS_SMASH_AURA = 208086, SPELL_WARRIOR_CRITICAL_THINKING_ENERGIZE = 392776, SPELL_WARRIOR_DEFT_EXPERIENCE = 383295, - SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_ENRAGE = 184362, + SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_FRENZIED_ENRAGE = 383848, SPELL_WARRIOR_FRENZY_TALENT = 335077, SPELL_WARRIOR_FRENZY_BUFF = 335082, @@ -69,6 +69,7 @@ enum WarriorSpells SPELL_WARRIOR_HEROIC_LEAP_JUMP = 178368, SPELL_WARRIOR_HEROIC_LEAP_DAMAGE = 52174, SPELL_WARRIOR_IGNORE_PAIN = 190456, + SPELL_WARRIOR_IMPROVED_EXECUTE_ARMS = 316405, SPELL_WARRIOR_IMPROVED_RAGING_BLOW = 383854, SPELL_WARRIOR_IMPROVED_WHIRLWIND = 12950, SPELL_WARRIOR_INTERVENE_CHARGE = 316531, @@ -699,13 +700,91 @@ class spell_warr_enrage_proc : public AuraScript } }; +// 163201 - Execute (Arms, Protection) +// 281000 - Massacre +// 330334 - Condemn (Venthyr) (Arms) +// 317349 - Condemn (Venthyr) (Protection) +class spell_warr_execute : public SpellScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellEffect({ + { SPELL_WARRIOR_SUDDEN_DEATH, EFFECT_0 }, + { spellInfo->Id, EFFECT_0 } + }) && ValidateSpellInfo({ + SPELL_WARRIOR_SUDDEN_DEATH_BUFF, + spellInfo->GetEffect(EFFECT_0).TriggerSpell + }); + } + + Optional GetSuddenDeathRageCost() const + { + if (Aura* suddenDeathAura = GetCaster()->GetAura(SPELL_WARRIOR_SUDDEN_DEATH_BUFF)) + if (GetSpell()->m_appliedMods.contains(suddenDeathAura)) + if (AuraEffect const* suddenDeathTalentAura = GetCaster()->GetAuraEffect(SPELL_WARRIOR_SUDDEN_DEATH, EFFECT_0)) + return suddenDeathTalentAura->GetAmount() * 10; + + return {}; + } + + std::pair GetRageCost() const + { + for (SpellPowerEntry const* powerCost : GetSpellInfo()->PowerCosts) + if (powerCost->PowerType == POWER_RAGE) + return { powerCost->ManaCost, powerCost->OptionalCost }; + + return { 0, 0 }; + } + + void HandleExecuteCast(SpellEffIndex spellEffIndex) + { + PreventHitDefaultEffect(spellEffIndex); + + // Can't use SpellInfo::CalcPowerCost here since Sudden Death modifies the costs so it's free. + auto [baseCost, optionalCost] = GetRageCost(); + int32 rageSpent = GetSpell()->GetPowerTypeCostAmount(POWER_RAGE).value_or(0); + + GetCaster()->CastSpell(GetHitUnit(), GetEffectInfo(spellEffIndex).TriggerSpell, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell(), + .CustomArg = TriggerArgs{ + .BaseRageCost = baseCost, + .OptionalRageCost = optionalCost, + .DamageRageSpent = GetSuddenDeathRageCost().value_or(rageSpent), + .RefundRage = CalculatePct(rageSpent, GetEffectInfo(EFFECT_1).CalcValue()) + } + }); + } + + void Register() override + { + OnEffectLaunchTarget += SpellEffectFn(spell_warr_execute::HandleExecuteCast, EFFECT_0, SPELL_EFFECT_TRIGGER_SPELL); + } + +public: + struct TriggerArgs + { + int32 BaseRageCost; + int32 OptionalRageCost; + int32 DamageRageSpent; + int32 RefundRage; + }; +}; + // 260798 - Execute (Arms, Protection) +// 317483 - Condemn (Venthyr) (Arms, Protection) class spell_warr_execute_damage : public SpellScript { - static void CalculateExecuteDamage(SpellScript const&, SpellEffectInfo const& /*spellEffectInfo*/, Unit const* /*victim*/, int32 const& /*damageOrHealing*/, int32 const& /*flatMod*/, float& pctMod) + void CalculateExecuteDamage(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* /*victim*/, int32 const& /*damageOrHealing*/, int32 const& /*flatMod*/, float& pctMod) const { - // tooltip has 2 multiplier hardcoded in it $damage=${2.0*$260798s1} - pctMod *= 2.0f; + spell_warr_execute::TriggerArgs const* triggerArgs = std::any_cast(&GetSpell()->m_customArg); + if (!triggerArgs) + return; + + if (triggerArgs->OptionalRageCost <= 0) + return; + + pctMod *= (static_cast(triggerArgs->DamageRageSpent - triggerArgs->BaseRageCost) / static_cast(triggerArgs->OptionalRageCost) + 1.0f); } void Register() override @@ -714,6 +793,34 @@ class spell_warr_execute_damage : public SpellScript } }; +// 260798 - Execute -> 316405 (Improved Execute (Arms)) +class spell_warr_execute_refund_rage : public SpellScript +{ + bool Load() override + { + return GetCaster()->HasAura(SPELL_WARRIOR_IMPROVED_EXECUTE_ARMS); + } + + void DetermineKillStatus(DamageInfo const& damageInfo, uint32& /*resistAmount*/, int32& /*absorbAmount*/) const + { + bool killed = damageInfo.GetDamage() >= damageInfo.GetVictim()->GetHealth(); + if (killed) + return; + + spell_warr_execute::TriggerArgs const* triggerArgs = std::any_cast(&GetSpell()->m_customArg); + if (!triggerArgs) + return; + + GetCaster()->ModifyPower(POWER_RAGE, triggerArgs->RefundRage, false); + } + + void Register() override + { + // abuse OnCalculateResistAbsorb to determine if this spell will kill target or not (its still not perfect - happens before absorbs are applied) + OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(spell_warr_execute_refund_rage::DetermineKillStatus); + } +}; + // 383848 - Frenzied Enrage (attached to 184362 - Enrage) class spell_warr_frenzied_enrage : public SpellScript { @@ -1850,7 +1957,9 @@ void AddSC_warrior_spell_scripts() RegisterSpellScript(spell_warr_deft_experience); RegisterSpellScript(spell_warr_devastator); RegisterSpellScript(spell_warr_enrage_proc); + RegisterSpellScript(spell_warr_execute); RegisterSpellScript(spell_warr_execute_damage); + RegisterSpellScript(spell_warr_execute_refund_rage); RegisterSpellScript(spell_warr_frenzied_enrage); RegisterSpellScript(spell_warr_frothing_berserker); RegisterSpellScript(spell_warr_fueled_by_violence);