/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ /* * Scripts for spells with SPELLFAMILY_WARRIOR and SPELLFAMILY_GENERIC spells used by warrior players. * Ordered alphabetically using scriptname. * Scriptnames of files in this file should be prefixed with "spell_warr_". */ #include "ScriptMgr.h" #include "Map.h" #include "MoveSpline.h" #include "ObjectAccessor.h" #include "PathGenerator.h" #include "Player.h" #include "Spell.h" #include "SpellMgr.h" #include "SpellAuraEffects.h" #include "SpellHistory.h" #include "SpellScript.h" enum WarriorSpells { SPELL_WARRIOR_AVATAR = 107574, SPELL_WARRIOR_BLADESTORM = 227847, SPELL_WARRIOR_BLADESTORM_PERIODIC_WHIRLWIND = 50622, SPELL_WARRIOR_BLOODTHIRST_HEAL = 117313, SPELL_WARRIOR_BOUNDING_STRIDE_AURA = 202163, SPELL_WARRIOR_BOUNDING_STRIDE = 202164, SPELL_WARRIOR_CHARGE = 34846, SPELL_WARRIOR_CHARGE_DROP_FIRE_PERIODIC = 126661, SPELL_WARRIOR_CHARGE_EFFECT = 198337, SPELL_WARRIOR_CHARGE_ROOT_EFFECT = 105771, SPELL_WARRIOR_COLD_STEEL_HOT_BLOOD_TALENT = 383959, SPELL_WARRIOR_COLOSSUS_SMASH = 167105, 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_FRENZIED_ENRAGE = 383848, SPELL_WARRIOR_FRENZY_TALENT = 335077, SPELL_WARRIOR_FRENZY_BUFF = 335082, SPELL_WARRIOR_FRESH_MEAT_DEBUFF = 316044, SPELL_WARRIOR_FRESH_MEAT_TALENT = 215568, SPELL_WARRIOR_FUELED_BY_VIOLENCE_HEAL = 383104, SPELL_WARRIOR_GLYPH_OF_THE_BLAZING_TRAIL = 123779, SPELL_WARRIOR_GLYPH_OF_HEROIC_LEAP = 159708, SPELL_WARRIOR_GLYPH_OF_HEROIC_LEAP_BUFF = 133278, SPELL_WARRIOR_GUSHING_WOUND = 385042, SPELL_WARRIOR_HEROIC_LEAP_JUMP = 178368, SPELL_WARRIOR_HEROIC_LEAP_DAMAGE = 52174, SPELL_WARRIOR_IGNORE_PAIN = 190456, SPELL_WARRIOR_IMPROVED_RAGING_BLOW = 383854, SPELL_WARRIOR_IMPROVED_WHIRLWIND = 12950, SPELL_WARRIOR_INTIMIDATING_SHOUT_MENACE_AOE = 316595, SPELL_WARRIOR_INVIGORATING_FURY = 385174, SPELL_WARRIOR_INVIGORATING_FURY_TALENT = 383468, SPELL_WARRIOR_IN_FOR_THE_KILL = 248621, SPELL_WARRIOR_IN_FOR_THE_KILL_HASTE = 248622, SPELL_WARRIOR_IMPENDING_VICTORY = 202168, SPELL_WARRIOR_IMPENDING_VICTORY_HEAL = 202166, SPELL_WARRIOR_IMPROVED_HEROIC_LEAP = 157449, SPELL_WARRIOR_MORTAL_STRIKE = 12294, SPELL_WARRIOR_MORTAL_WOUNDS = 115804, SPELL_WARRIOR_POWERFUL_ENRAGE = 440277, SPELL_WARRIOR_RALLYING_CRY = 97463, SPELL_WARRIOR_RAVAGER = 228920, SPELL_WARRIOR_RECKLESSNESS = 1719, SPELL_WARRIOR_RUMBLING_EARTH = 275339, SPELL_WARRIOR_SHIELD_BLOCK_AURA = 132404, SPELL_WARRIOR_SHIELD_CHARGE_EFFECT = 385953, SPELL_WARRIOR_SHIELD_SLAM = 23922, SPELL_WARRIOR_SHIELD_SLAM_MARKER = 224324, SPELL_WARRIOR_SHIELD_WALL = 871, SPELL_WARRIOR_SHOCKWAVE = 46968, SPELL_WARRIOR_SHOCKWAVE_STUN = 132168, SPELL_WARRIOR_SLAUGHTERING_STRIKES = 388004, SPELL_WARRIOR_SLAUGHTERING_STRIKES_BUFF = 393931, SPELL_WARRIOR_STOICISM = 70845, SPELL_WARRIOR_STORM_BOLT_STUN = 132169, SPELL_WARRIOR_STORM_BOLTS = 436162, SPELL_WARRIOR_STRATEGIST = 384041, SPELL_WARRIOR_SUDDEN_DEATH = 280721, SPELL_WARRIOR_SUDDEN_DEATH_BUFF = 280776, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1 = 12723, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2 = 26654, SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_TITANIC_RAGE = 394329, SPELL_WARRIOR_TRAUMA_EFFECT = 215537, SPELL_WARRIOR_VICIOUS_CONTEMPT = 383885, SPELL_WARRIOR_VICTORIOUS = 32216, SPELL_WARRIOR_VICTORY_RUSH_HEAL = 118779, SPELL_WARRIOR_WARBREAKER = 262161, SPELL_WARRIOR_WHIRLWIND_CLEAVE_AURA = 85739, SPELL_WARRIOR_WHIRLWIND_ENERGIZE = 280715, SPELL_WARRIOR_WRATH_AND_FURY = 392936 }; enum WarriorMisc { SPELL_VISUAL_BLAZING_CHARGE = 26423 }; static void ApplyWhirlwindCleaveAura(Player* caster, Difficulty difficulty, Spell const* triggeringSpell) { SpellInfo const* whirlwindCleaveAuraInfo = sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_WHIRLWIND_CLEAVE_AURA, difficulty); int32 stackAmount = static_cast(whirlwindCleaveAuraInfo->StackAmount); caster->ApplySpellMod(whirlwindCleaveAuraInfo, SpellModOp::MaxAuraStacks, stackAmount); caster->CastSpell(nullptr, SPELL_WARRIOR_WHIRLWIND_CLEAVE_AURA, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = triggeringSpell, .SpellValueOverrides = { { SPELLVALUE_AURA_STACK, stackAmount } } }); } // 152278 - Anger Management class spell_warr_anger_management_proc : public AuraScript { static bool ValidateProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo, ChrSpecialization spec) { if (aurEff->GetAmount() == 0) return false; Player const* player = eventInfo.GetActor()->ToPlayer(); if (!player) return false; Spell const* procSpell = eventInfo.GetProcSpell(); if (!procSpell) return false; if (procSpell->GetPowerTypeCostAmount(POWER_RAGE) <= 0) return false; return player->GetPrimarySpecialization() == spec; } static bool CheckArmsProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo) { if (!ValidateProc(aurEff, eventInfo, ChrSpecialization::WarriorArms)) return false; // exclude non-attacks such as Ignore Pain if (!eventInfo.GetSpellInfo()->IsAffected(SPELLFAMILY_WARRIOR, { 0x100, 0x0, 0x0, 0x0 })) return false; return true; } static bool CheckFuryProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo) { return ValidateProc(aurEff, eventInfo, ChrSpecialization::WarriorFury); } static bool CheckProtectionProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo) { return ValidateProc(aurEff, eventInfo, ChrSpecialization::WarriorProtection); } bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo( { SPELL_WARRIOR_COLOSSUS_SMASH, SPELL_WARRIOR_BLADESTORM, SPELL_WARRIOR_RAVAGER, SPELL_WARRIOR_WARBREAKER, SPELL_WARRIOR_RECKLESSNESS, SPELL_WARRIOR_AVATAR, SPELL_WARRIOR_SHIELD_WALL }); } void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo, std::span spellIds) const { int32 rageCost = *eventInfo.GetProcSpell()->GetPowerTypeCostAmount(POWER_RAGE) / 10; // db values are 10x the actual rage cost float multiplier = static_cast(rageCost) / static_cast(aurEff->GetAmount()); Milliseconds cooldownMod = -duration_cast(multiplier * CooldownReduction); for (int32 spellId : spellIds) GetTarget()->GetSpellHistory()->ModifyCooldown(spellId, cooldownMod); } void OnProcArms(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const { HandleProc(aurEff, eventInfo, ArmsSpellIds); } void OnProcFury(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const { HandleProc(aurEff, eventInfo, FurySpellIds); } void OnProcProtection(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const { HandleProc(aurEff, eventInfo, ProtectionSpellIds); } void Register() override { DoCheckEffectProc += AuraCheckEffectProcFn(spell_warr_anger_management_proc::CheckArmsProc, EFFECT_0, SPELL_AURA_DUMMY); DoCheckEffectProc += AuraCheckEffectProcFn(spell_warr_anger_management_proc::CheckProtectionProc, EFFECT_1, SPELL_AURA_DUMMY); DoCheckEffectProc += AuraCheckEffectProcFn(spell_warr_anger_management_proc::CheckFuryProc, EFFECT_2, SPELL_AURA_DUMMY); OnEffectProc += AuraEffectProcFn(spell_warr_anger_management_proc::OnProcArms, EFFECT_0, SPELL_AURA_DUMMY); OnEffectProc += AuraEffectProcFn(spell_warr_anger_management_proc::OnProcProtection, EFFECT_1, SPELL_AURA_DUMMY); OnEffectProc += AuraEffectProcFn(spell_warr_anger_management_proc::OnProcFury, EFFECT_2, SPELL_AURA_DUMMY); } static constexpr FloatMilliseconds CooldownReduction = 1s; static constexpr std::array ArmsSpellIds = { SPELL_WARRIOR_COLOSSUS_SMASH, SPELL_WARRIOR_WARBREAKER, SPELL_WARRIOR_BLADESTORM, SPELL_WARRIOR_RAVAGER }; static constexpr std::array FurySpellIds = { SPELL_WARRIOR_RECKLESSNESS, SPELL_WARRIOR_BLADESTORM, SPELL_WARRIOR_RAVAGER }; static constexpr std::array ProtectionSpellIds = { SPELL_WARRIOR_AVATAR, SPELL_WARRIOR_SHIELD_WALL }; }; // 392536 - Ashen Juggernaut class spell_warr_ashen_juggernaut : public AuraScript { static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo) { // should only proc on primary target return eventInfo.GetActionTarget() == eventInfo.GetProcSpell()->m_targets.GetUnitTarget(); } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_ashen_juggernaut::CheckProc); } }; // 107574 - Avatar class spell_warr_avatar : public SpellScript { void HandleRemoveImpairingAuras(SpellEffIndex /*effIndex*/) const { GetCaster()->RemoveMovementImpairingAuras(true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_avatar::HandleRemoveImpairingAuras, EFFECT_5, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 23881 - Bloodthirst // 335096 - Bloodbath class spell_warr_bloodthirst : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_BLOODTHIRST_HEAL }); } void CastHeal(SpellEffIndex /*effIndex*/) const { if (GetHitUnit() != GetExplTargetUnit()) return; GetCaster()->CastSpell(GetCaster(), SPELL_WARRIOR_BLOODTHIRST_HEAL, CastSpellExtraArgsInit { .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst::CastHeal, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 384036 - Brutal Vitality class spell_warr_brutal_vitality : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_IGNORE_PAIN }); } void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) { _damageAmount += CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()); } void HandleDummyTick(AuraEffect const* /*aurEff*/) { if (_damageAmount == 0) return; if (AuraEffect* ignorePainAura = GetTarget()->GetAuraEffect(SPELL_WARRIOR_IGNORE_PAIN, EFFECT_0)) ignorePainAura->ChangeAmount(ignorePainAura->GetAmount() + _damageAmount); _damageAmount = 0; } void Register() override { AfterEffectProc += AuraEffectProcFn(spell_warr_brutal_vitality::HandleProc, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); OnEffectPeriodic += AuraEffectPeriodicFn(spell_warr_brutal_vitality::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } private: uint32 _damageAmount = 0; }; // 100 - Charge class spell_warr_charge : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_CHARGE_EFFECT }); } void HandleDummy(SpellEffIndex /*effIndex*/) const { GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_CHARGE_EFFECT, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_charge::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 126661 - Warrior Charge Drop Fire Periodic class spell_warr_charge_drop_fire_periodic : public AuraScript { void DropFireVisual(AuraEffect const* aurEff) { PreventDefaultAction(); Unit* target = GetTarget(); if (target->IsSplineEnabled()) { Movement::Location from = target->movespline->ComputePosition(); Movement::Location to = target->movespline->ComputePosition(aurEff->GetPeriod()); int32 fireCount = std::lround((to - from).length()); for (int32 i = 0; i < fireCount; ++i) { int32 timeOffset = i * aurEff->GetPeriod() / fireCount; Movement::Location loc = target->movespline->ComputePosition(timeOffset); target->SendPlaySpellVisual(Position(loc.x, loc.y, loc.z), SPELL_VISUAL_BLAZING_CHARGE, 0, 0, 1.f, true); } } } void Register() override { OnEffectPeriodic += AuraEffectPeriodicFn(spell_warr_charge_drop_fire_periodic::DropFireVisual, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; // 198337 - Charge Effect class spell_warr_charge_effect : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo ({ SPELL_WARRIOR_CHARGE_ROOT_EFFECT, SPELL_WARRIOR_CHARGE_DROP_FIRE_PERIODIC }); } void HandleCharge(SpellEffIndex /*effIndex*/) const { Unit* caster = GetCaster(); Unit* target = GetHitUnit(); CastSpellExtraArgs const args = CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_FULL_MASK & ~TRIGGERED_CAST_DIRECTLY, .TriggeringSpell = GetSpell() }; if (caster->HasAura(SPELL_WARRIOR_GLYPH_OF_THE_BLAZING_TRAIL)) caster->CastSpell(target, SPELL_WARRIOR_CHARGE_DROP_FIRE_PERIODIC, args); caster->CastSpell(target, SPELL_WARRIOR_CHARGE_ROOT_EFFECT, args); } void Register() override { OnEffectLaunchTarget += SpellEffectFn(spell_warr_charge_effect::HandleCharge, EFFECT_0, SPELL_EFFECT_CHARGE); } }; // 23881 - Bloodthirst // 335096 - Bloodbath class spell_warr_cold_steel_hot_blood_bloodthirst : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_GUSHING_WOUND, SPELL_WARRIOR_COLD_STEEL_HOT_BLOOD_TALENT }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_COLD_STEEL_HOT_BLOOD_TALENT); } void CastGushingWound(SpellEffIndex /*effIndex*/) const { if (!IsHitCrit()) return; GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_GUSHING_WOUND, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR }); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_cold_steel_hot_blood_bloodthirst::CastGushingWound, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 167105 - Colossus Smash // 262161 - Warbreaker class spell_warr_colossus_smash : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_COLOSSUS_SMASH_AURA, SPELL_WARRIOR_IN_FOR_THE_KILL, SPELL_WARRIOR_IN_FOR_THE_KILL_HASTE }) && ValidateSpellEffect({ { SPELL_WARRIOR_IN_FOR_THE_KILL, EFFECT_2 } }); } void HandleHit() { Unit* target = GetHitUnit(); Unit* caster = GetCaster(); GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_COLOSSUS_SMASH_AURA, true); if (caster->HasAura(SPELL_WARRIOR_IN_FOR_THE_KILL)) { if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_IN_FOR_THE_KILL, DIFFICULTY_NONE)) { if (target->HealthBelowPct(spellInfo->GetEffect(EFFECT_2).CalcValue(caster))) _bonusHaste = true; } } } void HandleAfterCast() { Unit* caster = GetCaster(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_IN_FOR_THE_KILL, DIFFICULTY_NONE); if (!spellInfo) return; CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellBP0(spellInfo->GetEffect(EFFECT_0).CalcValue(caster)); if (_bonusHaste) args.AddSpellBP0(spellInfo->GetEffect(EFFECT_1).CalcValue(caster)); caster->CastSpell(caster, SPELL_WARRIOR_IN_FOR_THE_KILL_HASTE, args); } void Register() override { OnHit += SpellHitFn(spell_warr_colossus_smash::HandleHit); AfterCast += SpellCastFn(spell_warr_colossus_smash::HandleAfterCast); } private: bool _bonusHaste = false; }; // 389306 - Critical Thinking class spell_warr_critical_thinking : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_CRITICAL_THINKING_ENERGIZE }); } void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) { if (Optional rageCost = eventInfo.GetProcSpell()->GetPowerTypeCostAmount(POWER_RAGE)) GetTarget()->CastSpell(nullptr, SPELL_WARRIOR_CRITICAL_THINKING_ENERGIZE, CastSpellExtraArgs(TRIGGERED_FULL_MASK) .AddSpellBP0(CalculatePct(*rageCost, aurEff->GetAmount()))); } void Register() override { AfterEffectProc += AuraEffectProcFn(spell_warr_critical_thinking::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); } }; // 383295 - Deft Experience (attached to 23881 - Bloodthirst) // 383295 - Deft Experience (attached to 335096 - Bloodbath) class spell_warr_deft_experience : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellEffect({ { SPELL_WARRIOR_DEFT_EXPERIENCE, EFFECT_1 } }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_DEFT_EXPERIENCE); } void HandleDeftExperience(SpellEffIndex /*effIndex*/) const { if (GetHitUnit() != GetExplTargetUnit()) return; Unit const* caster = GetCaster(); if (Aura* enrageAura = caster->GetAura(SPELL_WARRIOR_ENRAGE)) if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_WARRIOR_DEFT_EXPERIENCE, EFFECT_1)) enrageAura->SetDuration(enrageAura->GetDuration() + aurEff->GetAmount()); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_deft_experience::HandleDeftExperience, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 236279 - Devastator class spell_warr_devastator : public AuraScript { bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } }) && ValidateSpellInfo({ SPELL_WARRIOR_SHIELD_SLAM, SPELL_WARRIOR_SHIELD_SLAM_MARKER }); } void OnProc(AuraEffect const* /*aurEff*/, ProcEventInfo const& /*eventInfo*/) const { if (GetTarget()->GetSpellHistory()->HasCooldown(SPELL_WARRIOR_SHIELD_SLAM)) { if (roll_chance_i(GetEffectInfo(EFFECT_1).CalcValue())) { GetTarget()->GetSpellHistory()->ResetCooldown(SPELL_WARRIOR_SHIELD_SLAM, true); GetTarget()->CastSpell(GetTarget(), SPELL_WARRIOR_SHIELD_SLAM_MARKER, TRIGGERED_IGNORE_CAST_IN_PROGRESS); } } } void Register() override { OnEffectProc += AuraEffectProcFn(spell_warr_devastator::OnProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } }; // 184361 - Enrage class spell_warr_enrage_proc : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_FRESH_MEAT_TALENT, SPELL_WARRIOR_FRESH_MEAT_DEBUFF }); } static bool CheckRampageProc(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo) { SpellInfo const* spellInfo = eventInfo.GetSpellInfo(); if (!spellInfo || !spellInfo->IsAffected(SPELLFAMILY_WARRIOR, { 0x0, 0x0, 0x0, 0x8000000 })) // Rampage return false; return true; } static bool IsBloodthirst(SpellInfo const* spellInfo) { // Bloodthirst/Bloodbath return spellInfo->IsAffected(SPELLFAMILY_WARRIOR, { 0x0, 0x400 }); } static bool CheckBloodthirstProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo) { SpellInfo const* spellInfo = eventInfo.GetSpellInfo(); if (!spellInfo || !IsBloodthirst(spellInfo)) return false; // Fresh Meat talent handling if (Unit const* actor = eventInfo.GetActor()) { if (actor->HasAura(SPELL_WARRIOR_FRESH_MEAT_TALENT)) { Spell const* procSpell = eventInfo.GetProcSpell(); if (!procSpell) return false; Unit const* target = procSpell->m_targets.GetUnitTarget(); if (!target) return false; if (!target->HasAura(SPELL_WARRIOR_FRESH_MEAT_DEBUFF, actor->GetGUID())) return true; } } return roll_chance_i(aurEff->GetAmount()); } void HandleProc(ProcEventInfo const& eventInfo) { PreventDefaultAction(); Unit* auraTarget = GetTarget(); auraTarget->CastSpell(nullptr, SPELL_WARRIOR_ENRAGE, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = eventInfo.GetProcSpell() }); // Fresh Meat talent handling if (auraTarget->HasAura(SPELL_WARRIOR_FRESH_MEAT_TALENT)) { Spell const* procSpell = eventInfo.GetProcSpell(); if (!procSpell) return; if (!IsBloodthirst(procSpell->GetSpellInfo())) return; if (Unit* bloodthirstTarget = procSpell->m_targets.GetUnitTarget()) if (!bloodthirstTarget->HasAura(SPELL_WARRIOR_FRESH_MEAT_DEBUFF, auraTarget->GetGUID())) auraTarget->CastSpell(bloodthirstTarget, SPELL_WARRIOR_FRESH_MEAT_DEBUFF, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR }); } } void Register() override { DoCheckEffectProc += AuraCheckEffectProcFn(spell_warr_enrage_proc::CheckRampageProc, EFFECT_0, SPELL_AURA_DUMMY); DoCheckEffectProc += AuraCheckEffectProcFn(spell_warr_enrage_proc::CheckBloodthirstProc, EFFECT_1, SPELL_AURA_DUMMY); OnProc += AuraProcFn(spell_warr_enrage_proc::HandleProc); } }; // 260798 - Execute (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) { // tooltip has 2 multiplier hardcoded in it $damage=${2.0*$260798s1} pctMod *= 2.0f; } void Register() override { CalcDamage += SpellCalcDamageFn(spell_warr_execute_damage::CalculateExecuteDamage); } }; // 383848 - Frenzied Enrage (attached to 184362 - Enrage) class spell_warr_frenzied_enrage : public SpellScript { bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellInfo({ SPELL_WARRIOR_FRENZIED_ENRAGE }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } }) && spellInfo->GetEffect(EFFECT_0).IsAura(SPELL_AURA_MELEE_SLOW) && spellInfo->GetEffect(EFFECT_1).IsAura(SPELL_AURA_MOD_INCREASE_SPEED); } bool Load() override { return !GetCaster()->HasAura(SPELL_WARRIOR_FRENZIED_ENRAGE); } static void HandleFrenziedEnrage(SpellScript const&, WorldObject*& target) { target = nullptr; } void Register() override { OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_warr_frenzied_enrage::HandleFrenziedEnrage, EFFECT_0, TARGET_UNIT_CASTER); OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_warr_frenzied_enrage::HandleFrenziedEnrage, EFFECT_1, TARGET_UNIT_CASTER); } }; // 335082 - frenzy class spell_warr_frenzy : public AuraScript { public: void SetTargetGUID(ObjectGuid const& guid) { _targetGUID = guid; } ObjectGuid const& GetTargetGUID() const { return _targetGUID; } private: void Register() override { } ObjectGuid _targetGUID; }; // 335077 - Frenzy (attached to 184367 - Rampage) class spell_warr_frenzy_rampage : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_FRENZY_BUFF, SPELL_WARRIOR_FRENZY_TALENT }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_FRENZY_TALENT); } void HandleAfterCast(SpellEffIndex /*effIndex*/) const { Unit* caster = GetCaster(); Unit* hitUnit = GetHitUnit(); if (hitUnit != GetExplTargetUnit()) return; caster->CastSpell(nullptr, SPELL_WARRIOR_FRENZY_BUFF, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }); if (Aura* frenzyAura = caster->GetAura(SPELL_WARRIOR_FRENZY_BUFF)) { if (spell_warr_frenzy* script = frenzyAura->GetScript()) { if (!script->GetTargetGUID().IsEmpty() && script->GetTargetGUID() != hitUnit->GetGUID()) frenzyAura->SetStackAmount(1); script->SetTargetGUID(hitUnit->GetGUID()); } } } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_frenzy_rampage::HandleAfterCast, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 440277 - Powerful Enrage (attached to 184362 - Enrage) class spell_warr_powerful_enrage : public SpellScript { bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellInfo({ SPELL_WARRIOR_POWERFUL_ENRAGE }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_4 } }) && spellInfo->GetEffect(EFFECT_3).IsAura(SPELL_AURA_ADD_PCT_MODIFIER) && spellInfo->GetEffect(EFFECT_3).MiscValue == int32(SpellModOp::HealingAndDamage) && spellInfo->GetEffect(EFFECT_4).IsAura(SPELL_AURA_ADD_PCT_MODIFIER) && spellInfo->GetEffect(EFFECT_4).MiscValue == int32(SpellModOp::PeriodicHealingAndDamage); } bool Load() override { return !GetCaster()->HasAura(SPELL_WARRIOR_POWERFUL_ENRAGE); } static void HandlePowerfulEnrage(SpellScript const&, WorldObject*& target) { target = nullptr; } void Register() override { OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_warr_powerful_enrage::HandlePowerfulEnrage, EFFECT_3, TARGET_UNIT_CASTER); OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_warr_powerful_enrage::HandlePowerfulEnrage, EFFECT_4, TARGET_UNIT_CASTER); } }; // 383103 - Fueled by Violence class spell_warr_fueled_by_violence : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_FUELED_BY_VIOLENCE_HEAL }); } void HandleProc(ProcEventInfo& eventInfo) { PreventDefaultAction(); _nextHealAmount += CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), GetEffectInfo(EFFECT_0).CalcValue(GetTarget())); } void HandlePeriodic(AuraEffect const* /*aurEff*/) { if (_nextHealAmount == 0) return; Unit* target = GetTarget(); CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellBP0(_nextHealAmount); target->CastSpell(target, SPELL_WARRIOR_FUELED_BY_VIOLENCE_HEAL, args); _nextHealAmount = 0; } void Register() override { OnProc += AuraProcFn(spell_warr_fueled_by_violence::HandleProc); OnEffectPeriodic += AuraEffectPeriodicFn(spell_warr_fueled_by_violence::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } private: uint32 _nextHealAmount = 0; }; // 6544 - Heroic leap class spell_warr_heroic_leap : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_HEROIC_LEAP_DAMAGE, SPELL_WARRIOR_TAUNT }); } SpellCastResult CheckElevation() const { if (WorldLocation const* dest = GetExplTargetDest()) { if (GetCaster()->HasUnitMovementFlag(MOVEMENTFLAG_ROOT)) return SPELL_FAILED_ROOTED; if (GetCaster()->GetMap()->Instanceable()) { float range = GetSpellInfo()->GetMaxRange(true, GetCaster()) * 1.5f; PathGenerator generatedPath(GetCaster()); generatedPath.SetPathLengthLimit(range); bool result = generatedPath.CalculatePath(dest->GetPositionX(), dest->GetPositionY(), dest->GetPositionZ(), false); if (generatedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; if (!result || generatedPath.GetPathType() & PATHFIND_NOPATH) return SPELL_FAILED_NOPATH; } else if (dest->GetPositionZ() > GetCaster()->GetPositionZ() + 4.0f) return SPELL_FAILED_NOPATH; return SPELL_CAST_OK; } return SPELL_FAILED_NO_VALID_TARGETS; } void HandleCast() const { if (Player* playerCaster = GetCaster()->ToPlayer()) if (playerCaster->GetPrimarySpecialization() == ChrSpecialization::WarriorProtection) playerCaster->GetSpellHistory()->ResetCooldown(SPELL_WARRIOR_TAUNT); } void Register() override { OnCast += SpellCastFn(spell_warr_heroic_leap::HandleCast); OnCheckCast += SpellCheckCastFn(spell_warr_heroic_leap::CheckElevation); } }; // 52174 - Heroic Leap (Damage) class spell_warr_heroic_leap_damage : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo( { SPELL_WARRIOR_BOUNDING_STRIDE_AURA, SPELL_WARRIOR_BOUNDING_STRIDE }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_BOUNDING_STRIDE_AURA); } void HandleCast() const { GetCaster()->CastSpell(GetCaster(), SPELL_WARRIOR_BOUNDING_STRIDE, CastSpellExtraArgsInit{ .TriggeringSpell = GetSpell() }); } void Register() override { OnCast += SpellCastFn(spell_warr_heroic_leap_damage::HandleCast); } }; // 202168 - Impending Victory class spell_warr_impending_victory : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_IMPENDING_VICTORY_HEAL }); } void HandleAfterCast() { Unit* caster = GetCaster(); caster->CastSpell(caster, SPELL_WARRIOR_IMPENDING_VICTORY_HEAL, true); caster->RemoveAurasDueToSpell(SPELL_WARRIOR_VICTORIOUS); } void Register() override { AfterCast += SpellCastFn(spell_warr_impending_victory::HandleAfterCast); } }; // 12950 - Improved Whirlwind (attached to 190411 - Whirlwind) class spell_improved_whirlwind : public SpellScript { bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellInfo({ SPELL_WARRIOR_IMPROVED_WHIRLWIND, SPELL_WARRIOR_WHIRLWIND_CLEAVE_AURA }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_2 }, { SPELL_WARRIOR_WHIRLWIND_ENERGIZE, EFFECT_0 } }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_IMPROVED_WHIRLWIND); } void HandleHit(SpellEffIndex /*effIndex*/) const { int64 const targetsHit = GetUnitTargetCountForEffect(EFFECT_0); if (!targetsHit) return; Player* caster = GetCaster()->ToPlayer(); if (!caster) return; int32 const ragePerTarget = GetEffectValue(); int32 const baseRage = GetEffectInfo(EFFECT_0).CalcValue(); int32 const maxRage = baseRage + (ragePerTarget * GetEffectInfo(EFFECT_2).CalcValue()); int32 const rageGained = std::min(baseRage + (targetsHit * ragePerTarget), maxRage); caster->CastSpell(nullptr, SPELL_WARRIOR_WHIRLWIND_ENERGIZE, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell(), .SpellValueOverrides = {{ SPELLVALUE_BASE_POINT0, rageGained * 10 } } }); ApplyWhirlwindCleaveAura(caster, GetCastDifficulty(), GetSpell()); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_improved_whirlwind::HandleHit, EFFECT_1, SPELL_EFFECT_DUMMY); } }; // 5246 - Intimidating Shout class spell_warr_intimidating_shout : public SpellScript { void FilterTargets(std::list& unitList) const { unitList.remove(GetExplTargetWorldObject()); } static void ClearTargets(SpellScript const&, std::list& unitList) { // This is used in effect 3, which is an AOE Root effect. // This doesn't seem to be a thing anymore, so we clear the targets list here. unitList.clear(); } void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout::ClearTargets, EFFECT_3, TARGET_UNIT_SRC_AREA_ENEMY); } }; // 316594 - Intimidating Shout (Menace Talent, knock back -> root) class spell_warr_intimidating_shout_menace_knock_back : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_INTIMIDATING_SHOUT_MENACE_AOE }); } void FilterTargets(std::list& unitList) const { unitList.remove(GetExplTargetWorldObject()); } void HandleRoot(SpellEffIndex /*effIndex*/) const { CastSpellExtraArgs args = CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }; GetCaster()->m_Events.AddEventAtOffset([caster = GetCaster(), targetGUID = GetHitUnit()->GetGUID(), castArgs = std::move(args)]() { if (Unit* targetUnit = ObjectAccessor::GetUnit(*caster, targetGUID)) caster->CastSpell(targetUnit, SPELL_WARRIOR_INTIMIDATING_SHOUT_MENACE_AOE, castArgs); }, 500ms); } void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout_menace_knock_back::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_warr_intimidating_shout_menace_knock_back::HandleRoot, EFFECT_0, SPELL_EFFECT_KNOCK_BACK); } }; // 385174 - Invigorating Fury (attached to 184364 - Enraged Regeneration) class spell_warr_invigorating_fury : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_INVIGORATING_FURY, SPELL_WARRIOR_INVIGORATING_FURY_TALENT }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_INVIGORATING_FURY_TALENT); } void CastHeal() const { GetCaster()->CastSpell(nullptr, SPELL_WARRIOR_INVIGORATING_FURY, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }); } void Register() override { AfterCast += SpellCastFn(spell_warr_invigorating_fury::CastHeal); } }; // 70844 - Item - Warrior T10 Protection 4P Bonus class spell_warr_item_t10_prot_4p_bonus : public AuraScript { bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellInfo({ SPELL_WARRIOR_STOICISM }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } }); } void HandleProc(ProcEventInfo& eventInfo) { PreventDefaultAction(); Unit* target = eventInfo.GetActionTarget(); int32 bp0 = CalculatePct(target->GetMaxHealth(), GetEffectInfo(EFFECT_1).CalcValue()); CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellBP0(bp0); target->CastSpell(nullptr, SPELL_WARRIOR_STOICISM, args); } void Register() override { OnProc += AuraProcFn(spell_warr_item_t10_prot_4p_bonus::HandleProc); } }; // 12294 - Mortal Strike class spell_warr_mortal_strike : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_MORTAL_WOUNDS }); } void HandleMortalWounds(SpellEffIndex /*effIndex*/) const { GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_MORTAL_WOUNDS, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_mortal_strike::HandleMortalWounds, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 383854 - Improved Raging Blow (attached to 85288 - Raging Blow, 335097 - Crushing Blow) // 392936 - Wrath and Fury (attached to 85288 - Raging Blow, 335097 - Crushing Blow) class spell_warr_raging_blow_cooldown_reset : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_IMPROVED_RAGING_BLOW }) && ValidateSpellEffect({{ SPELL_WARRIOR_WRATH_AND_FURY, EFFECT_0 }}); } bool Load() override { Unit const* caster = GetCaster(); return caster->HasAura(SPELL_WARRIOR_IMPROVED_RAGING_BLOW) || caster->HasAuraEffect(SPELL_WARRIOR_WRATH_AND_FURY, EFFECT_0); } void HandleResetCooldown(SpellEffIndex /*effIndex*/) const { // it is currently impossible to have Wrath and Fury without having Improved Raging Blow, but we will check it anyway Unit* caster = GetCaster(); int32 value = 0; if (caster->HasAura(SPELL_WARRIOR_IMPROVED_RAGING_BLOW)) value = GetEffectValue(); if (AuraEffect const* auraEffect = caster->GetAuraEffect(SPELL_WARRIOR_WRATH_AND_FURY, EFFECT_0)) value += auraEffect->GetAmount(); if (roll_chance_i(value)) caster->GetSpellHistory()->RestoreCharge(GetSpellInfo()->ChargeCategoryId); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_raging_blow_cooldown_reset::HandleResetCooldown, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 97462 - Rallying Cry class spell_warr_rallying_cry : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_RALLYING_CRY }); } bool Load() override { return GetCaster()->GetTypeId() == TYPEID_PLAYER; } void HandleScript(SpellEffIndex /*effIndex*/) { CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellMod(SPELLVALUE_BASE_POINT0, int32(GetHitUnit()->CountPctFromMaxHealth(GetEffectValue()))); GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_RALLYING_CRY, args); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_rallying_cry::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 275339 - (attached to 46968 - Shockwave) class spell_warr_rumbling_earth : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellEffect({ { SPELL_WARRIOR_RUMBLING_EARTH, EFFECT_1 } }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_RUMBLING_EARTH); } void HandleCooldownReduction(SpellEffIndex /*effIndex*/) const { Unit* caster = GetCaster(); Aura const* rumblingEarth = caster->GetAura(SPELL_WARRIOR_RUMBLING_EARTH); if (!rumblingEarth) return; AuraEffect const* minTargetCount = rumblingEarth->GetEffect(EFFECT_0); AuraEffect const* cooldownReduction = rumblingEarth->GetEffect(EFFECT_1); if (!minTargetCount || !cooldownReduction) return; if (GetUnitTargetCountForEffect(EFFECT_0) >= minTargetCount->GetAmount()) GetCaster()->GetSpellHistory()->ModifyCooldown(GetSpellInfo()->Id, Seconds(-cooldownReduction->GetAmount())); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_rumbling_earth::HandleCooldownReduction, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 2565 - Shield Block class spell_warr_shield_block : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SHIELD_BLOCK_AURA }); } void HandleHitTarget(SpellEffIndex /*effIndex*/) { GetCaster()->CastSpell(nullptr, SPELL_WARRIOR_SHIELD_BLOCK_AURA, true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_shield_block::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 385952 - Shield Charge class spell_warr_shield_charge : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SHIELD_CHARGE_EFFECT }); } void HandleDummy(SpellEffIndex /*effIndex*/) { GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_SHIELD_CHARGE_EFFECT, true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_shield_charge::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 46968 - Shockwave class spell_warr_shockwave : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SHOCKWAVE_STUN }); } void HandleStun(SpellEffIndex /*effIndex*/) const { GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_SHOCKWAVE_STUN, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = GetSpell() }); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_shockwave::HandleStun, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 107570 - Storm Bolt class spell_warr_storm_bolt : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_STORM_BOLT_STUN }); } void HandleOnHit(SpellEffIndex /*effIndex*/) const { GetCaster()->CastSpell(GetHitUnit(), SPELL_WARRIOR_STORM_BOLT_STUN, true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_storm_bolt::HandleOnHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; // 107570 - Storm Bolt class spell_warr_storm_bolts: public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_STORM_BOLTS }); } bool Load() override { return !GetCaster()->HasAura(SPELL_WARRIOR_STORM_BOLTS); } void FilterTargets(std::list& targets) const { targets.clear(); if (Unit* target = GetExplTargetUnit()) targets.push_back(target); } void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_storm_bolts::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; // 384041 - Strategist class spell_warr_strategist : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SHIELD_SLAM, SPELL_WARRIOR_SHIELD_SLAM_MARKER }) && ValidateSpellEffect({ { SPELL_WARRIOR_STRATEGIST, EFFECT_0 } }); } static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& /*procEvent*/) { return roll_chance_i(aurEff->GetAmount()); } void HandleCooldown(AuraEffect const* /*aurEff*/, ProcEventInfo const& /*procEvent*/) const { Unit* caster = GetTarget(); caster->GetSpellHistory()->ResetCooldown(SPELL_WARRIOR_SHIELD_SLAM, true); caster->CastSpell(caster, SPELL_WARRIOR_SHIELD_SLAM_MARKER, TRIGGERED_IGNORE_CAST_IN_PROGRESS); } void Register() override { DoCheckEffectProc += AuraCheckEffectProcFn(spell_warr_strategist::CheckProc, EFFECT_0, SPELL_AURA_DUMMY); OnEffectProc += AuraEffectProcFn(spell_warr_strategist::HandleCooldown, EFFECT_0, SPELL_AURA_DUMMY); } }; // 280776 - Sudden Death class spell_warr_sudden_death : public AuraScript { static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo) { // should only proc on primary target return eventInfo.GetActionTarget() == eventInfo.GetProcSpell()->m_targets.GetUnitTarget(); } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_sudden_death::CheckProc); } }; // 280721 - Sudden Death class spell_warr_sudden_death_proc : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SUDDEN_DEATH_BUFF }); } void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& /*eventInfo*/) const { GetTarget()->CastSpell(nullptr, SPELL_WARRIOR_SUDDEN_DEATH_BUFF, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR }); } void Register() override { OnEffectProc += AuraEffectProcFn(spell_warr_sudden_death_proc::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; // 12328, 18765, 35429 - Sweeping Strikes class spell_warr_sweeping_strikes : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2 }); } bool CheckProc(ProcEventInfo& eventInfo) { _procTarget = eventInfo.GetActor()->SelectNearbyTarget(eventInfo.GetProcTarget()); return _procTarget != nullptr; } void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); if (DamageInfo* damageInfo = eventInfo.GetDamageInfo()) { SpellInfo const* spellInfo = damageInfo->GetSpellInfo(); if (spellInfo && (spellInfo->Id == SPELL_WARRIOR_BLADESTORM_PERIODIC_WHIRLWIND || (spellInfo->Id == SPELL_WARRIOR_EXECUTE && !_procTarget->HasAuraState(AURA_STATE_WOUNDED_20_PERCENT)))) { // If triggered by Execute (while target is not under 20% hp) or Bladestorm deals normalized weapon damage GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2, aurEff); } else { CastSpellExtraArgs args(aurEff); args.AddSpellMod(SPELLVALUE_BASE_POINT0, damageInfo->GetDamage()); GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, args); } } } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_sweeping_strikes::CheckProc); OnEffectProc += AuraEffectProcFn(spell_warr_sweeping_strikes::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } Unit* _procTarget = nullptr; }; // 388933 - Tenderize class spell_warr_tenderize : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_ENRAGE, SPELL_WARRIOR_SLAUGHTERING_STRIKES_BUFF, SPELL_WARRIOR_SLAUGHTERING_STRIKES }); } void HandleProc(ProcEventInfo const& eventInfo) const { GetTarget()->CastSpell(nullptr, SPELL_WARRIOR_ENRAGE, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = eventInfo.GetProcSpell() }); } void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const { Unit* target = GetTarget(); if (!target->HasAura(SPELL_WARRIOR_SLAUGHTERING_STRIKES)) return; target->CastSpell(nullptr, SPELL_WARRIOR_SLAUGHTERING_STRIKES_BUFF, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = eventInfo.GetProcSpell(), .SpellValueOverrides = { { SPELLVALUE_AURA_STACK, aurEff->GetAmount() } } }); } void Register() override { OnProc += AuraProcFn(spell_warr_tenderize::HandleProc); OnEffectProc += AuraEffectProcFn(spell_warr_tenderize::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY); } }; // 394329 - Titanic Rage class spell_warr_titanic_rage : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_WHIRLWIND_CLEAVE_AURA }); } void HandleProc(ProcEventInfo const& eventInfo) const { Player* target = GetTarget()->ToPlayer(); if (!target) return; target->CastSpell(nullptr, SPELL_WARRIOR_ENRAGE, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, .TriggeringSpell = eventInfo.GetProcSpell() }); ApplyWhirlwindCleaveAura(target, GetCastDifficulty(), nullptr); } void Register() override { OnProc += AuraProcFn(spell_warr_titanic_rage::HandleProc); } }; // 215538 - Trauma class spell_warr_trauma : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_TRAUMA_EFFECT }); } void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) { Unit* target = eventInfo.GetActionTarget(); //Get 25% of damage from the spell casted (Slam & Whirlwind) plus Remaining Damage from Aura int32 damage = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()) / sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_TRAUMA_EFFECT, GetCastDifficulty())->GetMaxTicks()); CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); GetCaster()->CastSpell(target, SPELL_WARRIOR_TRAUMA_EFFECT, args); } void Register() override { OnEffectProc += AuraEffectProcFn(spell_warr_trauma::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; // 28845 - Cheat Death class spell_warr_t3_prot_8p_bonus : public AuraScript { bool CheckProc(ProcEventInfo& eventInfo) { if (eventInfo.GetActionTarget()->HealthBelowPct(20)) return true; DamageInfo* damageInfo = eventInfo.GetDamageInfo(); if (damageInfo && damageInfo->GetDamage()) if (GetTarget()->HealthBelowPctDamaged(20, damageInfo->GetDamage())) return true; return false; } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_t3_prot_8p_bonus::CheckProc); } }; // 389603 - Unbridled Ferocity class spell_warr_unbridled_ferocity : public AuraScript { bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellInfo({ SPELL_WARRIOR_RECKLESSNESS }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } }) && spellInfo->GetEffect(EFFECT_0).IsAura(SPELL_AURA_DUMMY) && spellInfo->GetEffect(EFFECT_1).IsAura(SPELL_AURA_DUMMY); } void HandleProc(ProcEventInfo& /*eventInfo*/) const { int32 durationMs = GetEffect(EFFECT_1)->GetAmount(); GetTarget()->CastSpell(nullptr, SPELL_WARRIOR_RECKLESSNESS, CastSpellExtraArgsInit{ .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR | TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD, .SpellValueOverrides = { { SPELLVALUE_DURATION, durationMs } } }); } bool CheckProc(ProcEventInfo& /*eventInfo*/) const { return roll_chance_i(GetEffect(EFFECT_0)->GetAmount()); } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_unbridled_ferocity::CheckProc); OnProc += AuraProcFn(spell_warr_unbridled_ferocity::HandleProc); } }; // 383885 - Vicious Contempt (attached to 23881 - Bloodthirst) // 383885 - Vicious Contempt (attached to 335096 - Bloodbath) class spell_warr_vicious_contempt : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellEffect({ { SPELL_WARRIOR_VICIOUS_CONTEMPT, EFFECT_0 } }); } bool Load() override { return GetCaster()->HasAura(SPELL_WARRIOR_VICIOUS_CONTEMPT); } void CalculateDamage(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* victim, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) const { if (!victim->HasAuraState(AURA_STATE_WOUNDED_35_PERCENT)) return; if (AuraEffect const* aurEff = GetCaster()->GetAuraEffect(SPELL_WARRIOR_VICIOUS_CONTEMPT, EFFECT_0)) AddPct(pctMod, aurEff->GetAmount()); } void Register() override { CalcDamage += SpellCalcDamageFn(spell_warr_vicious_contempt::CalculateDamage); } }; // 32215 - Victorious State class spell_warr_victorious_state : public AuraScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_IMPENDING_VICTORY }); } void HandleOnProc(AuraEffect* /*aurEff*/, ProcEventInfo& procInfo) { if (procInfo.GetActor()->GetTypeId() == TYPEID_PLAYER && procInfo.GetActor()->ToPlayer()->GetPrimarySpecialization() == ChrSpecialization::WarriorFury) PreventDefaultAction(); procInfo.GetActor()->GetSpellHistory()->ResetCooldown(SPELL_WARRIOR_IMPENDING_VICTORY, true); } void Register() override { OnEffectProc += AuraEffectProcFn(spell_warr_victorious_state::HandleOnProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } }; // 34428 - Victory Rush class spell_warr_victory_rush : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo ({ SPELL_WARRIOR_VICTORIOUS, SPELL_WARRIOR_VICTORY_RUSH_HEAL }); } void HandleHeal() { Unit* caster = GetCaster(); caster->CastSpell(caster, SPELL_WARRIOR_VICTORY_RUSH_HEAL, true); caster->RemoveAurasDueToSpell(SPELL_WARRIOR_VICTORIOUS); } void Register() override { AfterCast += SpellCastFn(spell_warr_victory_rush::HandleHeal); } }; void AddSC_warrior_spell_scripts() { RegisterSpellScript(spell_warr_anger_management_proc); RegisterSpellScript(spell_warr_ashen_juggernaut); RegisterSpellScript(spell_warr_avatar); RegisterSpellScript(spell_warr_bloodthirst); RegisterSpellScript(spell_warr_brutal_vitality); RegisterSpellScript(spell_warr_charge); RegisterSpellScript(spell_warr_charge_drop_fire_periodic); RegisterSpellScript(spell_warr_charge_effect); RegisterSpellScript(spell_warr_cold_steel_hot_blood_bloodthirst); RegisterSpellScript(spell_warr_colossus_smash); RegisterSpellScript(spell_warr_critical_thinking); RegisterSpellScript(spell_warr_deft_experience); RegisterSpellScript(spell_warr_devastator); RegisterSpellScript(spell_warr_enrage_proc); RegisterSpellScript(spell_warr_execute_damage); RegisterSpellScript(spell_warr_frenzied_enrage); RegisterSpellScript(spell_warr_frenzy); RegisterSpellScript(spell_warr_frenzy_rampage); RegisterSpellScript(spell_warr_fueled_by_violence); RegisterSpellScript(spell_warr_heroic_leap); RegisterSpellScript(spell_warr_heroic_leap_damage); RegisterSpellScript(spell_warr_impending_victory); RegisterSpellScript(spell_improved_whirlwind); RegisterSpellScript(spell_warr_intimidating_shout); RegisterSpellScript(spell_warr_intimidating_shout_menace_knock_back); RegisterSpellScript(spell_warr_invigorating_fury); RegisterSpellScript(spell_warr_item_t10_prot_4p_bonus); RegisterSpellScript(spell_warr_mortal_strike); RegisterSpellScript(spell_warr_powerful_enrage); RegisterSpellScript(spell_warr_raging_blow_cooldown_reset); RegisterSpellScript(spell_warr_rallying_cry); RegisterSpellScript(spell_warr_rumbling_earth); RegisterSpellScript(spell_warr_shield_block); RegisterSpellScript(spell_warr_shield_charge); RegisterSpellScript(spell_warr_shockwave); RegisterSpellScript(spell_warr_storm_bolt); RegisterSpellScript(spell_warr_storm_bolts); RegisterSpellScript(spell_warr_strategist); RegisterSpellScript(spell_warr_sudden_death); RegisterSpellScript(spell_warr_sudden_death_proc); RegisterSpellScript(spell_warr_sweeping_strikes); RegisterSpellScript(spell_warr_tenderize); RegisterSpellScript(spell_warr_titanic_rage); RegisterSpellScript(spell_warr_trauma); RegisterSpellScript(spell_warr_t3_prot_8p_bonus); RegisterSpellScript(spell_warr_unbridled_ferocity); RegisterSpellScript(spell_warr_vicious_contempt); RegisterSpellScript(spell_warr_victorious_state); RegisterSpellScript(spell_warr_victory_rush); }