/* * This file is part of the AzerothCore 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 Affero General Public License as published by the * Free Software Foundation; either version 3 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 Affero 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 . */ #include "CreatureScript.h" #include "Player.h" #include "SpellAuraEffects.h" #include "SpellInfo.h" #include "SpellMgr.h" #include "SpellScript.h" #include "SpellScriptLoader.h" /* * 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_". */ enum WarriorSpells { SPELL_WARRIOR_INTERVENE_TRIGGER = 59667, SPELL_WARRIOR_SPELL_REFLECTION = 23920, SPELL_WARRIOR_IMPROVED_SPELL_REFLECTION_TRIGGER = 59725, SPELL_WARRIOR_BLOODTHIRST = 23885, SPELL_WARRIOR_BLOODTHIRST_DAMAGE = 23881, SPELL_WARRIOR_CHARGE = 34846, SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE = 59653, SPELL_WARRIOR_DEEP_WOUNDS_RANK_1 = 12162, SPELL_WARRIOR_DEEP_WOUNDS_RANK_2 = 12850, SPELL_WARRIOR_DEEP_WOUNDS_RANK_3 = 12868, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC = 12721, SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_GLYPH_OF_EXECUTION = 58367, SPELL_WARRIOR_GLYPH_OF_VIGILANCE = 63326, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF = 65156, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976, SPELL_WARRIOR_LAST_STAND_TRIGGERED = 12976, SPELL_WARRIOR_RETALIATION_DAMAGE = 22858, SPELL_WARRIOR_SLAM = 50783, SPELL_WARRIOR_SUNDER_ARMOR = 58567, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1 = 12723, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2 = 26654, SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2 = 46860, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1 = 64849, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2 = 64850, SPELL_WARRIOR_VIGILANCE_PROC = 50725, SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665, SPELL_WARRIOR_WHIRLWIND_MAIN = 50622, SPELL_WARRIOR_WHIRLWIND_OFF = 44949, SPELL_WARRIOR_EXECUTE_R1 = 5308, }; enum WarriorSpellIcons { WARRIOR_ICON_ID_SUDDEN_DEATH = 1989 }; enum MiscSpells { SPELL_PALADIN_BLESSING_OF_SANCTUARY = 20911, SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY = 25899, SPELL_PRIEST_RENEWED_HOPE = 63944, SPELL_GEN_DAMAGE_REDUCTION_AURA = 68066, }; class spell_warr_mocking_blow : public SpellScript { PrepareSpellScript(spell_warr_mocking_blow); void HandleOnHit() { if (Unit* target = GetHitUnit()) if (target->IsImmunedToSpellEffect(GetSpellInfo(), EFFECT_1)) SetHitDamage(0); } void Register() override { OnHit += SpellHitFn(spell_warr_mocking_blow::HandleOnHit); } }; enum VictoryRushEnum { SPELL_VICTORIOUS = 32216 }; class spell_warr_victory_rush : public SpellScript { PrepareSpellScript(spell_warr_victory_rush); void HandleCast() { if (Unit* caster = GetCaster()) caster->RemoveAurasDueToSpell(SPELL_VICTORIOUS); } void Register() override { OnCast += SpellCastFn(spell_warr_victory_rush::HandleCast); } }; class spell_warr_intervene : public SpellScript { PrepareSpellScript(spell_warr_intervene); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_INTERVENE_TRIGGER }); } void HandleApplyAura(SpellEffIndex /*effIndex*/) { if (Unit* target = GetHitUnit()) target->CastSpell((Unit*)nullptr, SPELL_WARRIOR_INTERVENE_TRIGGER, true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_intervene::HandleApplyAura, EFFECT_1, SPELL_EFFECT_APPLY_AURA); } }; class spell_warr_improved_spell_reflection : public AuraScript { PrepareAuraScript(spell_warr_improved_spell_reflection); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SPELL_REFLECTION, SPELL_WARRIOR_IMPROVED_SPELL_REFLECTION_TRIGGER }); } bool CheckProc(ProcEventInfo& eventInfo) { return eventInfo.GetSpellInfo() && eventInfo.GetActor() && eventInfo.GetSpellInfo()->Id == SPELL_WARRIOR_SPELL_REFLECTION; } void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); CustomSpellValues values; values.AddSpellMod(SPELLVALUE_MAX_TARGETS, aurEff->GetAmount()); values.AddSpellMod(SPELLVALUE_RADIUS_MOD, 2000); // Base range = 100, final range = 20 value / 10000.0f = 0.2f eventInfo.GetActor()->CastCustomSpell(SPELL_WARRIOR_IMPROVED_SPELL_REFLECTION_TRIGGER, values, eventInfo.GetActor(), TRIGGERED_FULL_MASK, nullptr); } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_improved_spell_reflection::CheckProc); OnEffectProc += AuraEffectProcFn(spell_warr_improved_spell_reflection::OnProc, EFFECT_1, SPELL_AURA_DUMMY); } }; class spell_warr_improved_spell_reflection_trigger : public SpellScript { PrepareSpellScript(spell_warr_improved_spell_reflection_trigger); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SPELL_REFLECTION }); } void FilterTargets(std::list& unitList) { GetCaster()->RemoveAurasDueToSpell(SPELL_WARRIOR_SPELL_REFLECTION); unitList.sort(Acore::ObjectDistanceOrderPred(GetCaster())); while (unitList.size() > GetSpellValue()->MaxAffectedTargets) unitList.pop_back(); } void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_improved_spell_reflection_trigger::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY); } }; class spell_warr_improved_spell_reflection_trigger_aura : public AuraScript { PrepareAuraScript(spell_warr_improved_spell_reflection_trigger_aura); void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (!IsExpired()) { // aura remove - remove auras from all party members std::list PartyMembers; GetUnitOwner()->GetPartyMembers(PartyMembers); for (std::list::iterator itr = PartyMembers.begin(); itr != PartyMembers.end(); ++itr) { if ((*itr)->GetGUID() != GetOwner()->GetGUID()) if (Aura* aur = (*itr)->GetAura(59725, GetCasterGUID())) { aur->SetDuration(0); aur->Remove(); } } } } void Register() override { AfterEffectRemove += AuraEffectRemoveFn(spell_warr_improved_spell_reflection_trigger_aura::HandleRemove, EFFECT_0, SPELL_AURA_REFLECT_SPELLS, AURA_EFFECT_HANDLE_REAL); } }; // 12975 - Last Stand class spell_warr_last_stand : public SpellScript { PrepareSpellScript(spell_warr_last_stand); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_LAST_STAND_TRIGGERED }); } void HandleDummy(SpellEffIndex /*effIndex*/) { Unit* caster = GetCaster(); int32 healthModSpellBasePoints0 = int32(caster->CountPctFromMaxHealth(GetEffectValue())); caster->CastCustomSpell(caster, SPELL_WARRIOR_LAST_STAND_TRIGGERED, &healthModSpellBasePoints0, nullptr, nullptr, true, nullptr); } void Register() override { OnEffectHit += SpellEffectFn(spell_warr_last_stand::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // -12162 - Deep Wounds class spell_warr_deep_wounds : public SpellScript { PrepareSpellScript(spell_warr_deep_wounds); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC }); } void HandleDummy(SpellEffIndex /*effIndex*/) { int32 damage = std::max(GetEffectValue(), 0); Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) { // include target dependant auras damage = target->MeleeDamageBonusTaken(caster, damage, BASE_ATTACK, GetSpellInfo()); // apply percent damage mods ApplyPct(damage, 16.0f * GetSpellInfo()->GetRank() / 6.0f); target->CastDelayedSpellWithPeriodicAmount(caster, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC, SPELL_AURA_PERIODIC_DAMAGE, damage, EFFECT_0); //caster->CastCustomSpell(target, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC, &damage, nullptr, nullptr, true); } } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_deep_wounds::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // -100 - Charge class spell_warr_charge : public SpellScript { PrepareSpellScript(spell_warr_charge); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo( { SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF, SPELL_WARRIOR_CHARGE }); } void HandleDummy(SpellEffIndex /*effIndex*/) { int32 chargeBasePoints0 = GetEffectValue(); Unit* caster = GetCaster(); caster->CastCustomSpell(caster, SPELL_WARRIOR_CHARGE, &chargeBasePoints0, nullptr, nullptr, true); // Juggernaut crit bonus if (caster->HasAura(SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT)) caster->CastSpell(caster, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF, true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_charge::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); } }; // -1464 - Slam class spell_warr_slam : public SpellScript { PrepareSpellScript(spell_warr_slam); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SLAM }); } void SendMiss(SpellMissInfo missInfo) { if (missInfo != SPELL_MISS_NONE) { if (Unit* caster = GetCaster()) { if (Unit* target = GetHitUnit()) { caster->SendSpellMiss(target, SPELL_WARRIOR_SLAM, missInfo); } } } } void HandleDummy(SpellEffIndex /*effIndex*/) { if (GetHitUnit()) GetCaster()->CastCustomSpell(SPELL_WARRIOR_SLAM, SPELLVALUE_BASE_POINT0, GetEffectValue(), GetHitUnit(), TRIGGERED_FULL_MASK); } void Register() override { BeforeHit += BeforeSpellHitFn(spell_warr_slam::SendMiss); OnEffectHitTarget += SpellEffectFn(spell_warr_slam::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // -58872 - Damage Shield class spell_warr_damage_shield : public AuraScript { PrepareAuraScript(spell_warr_damage_shield); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE }); } void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); // % of amount blocked int32 damage = CalculatePct(int32(GetTarget()->GetShieldBlockValue()), aurEff->GetAmount()); GetTarget()->CastCustomSpell(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetProcTarget(), true, nullptr, aurEff); } void Register() override { OnEffectProc += AuraEffectProcFn(spell_warr_damage_shield::OnProc, EFFECT_0, SPELL_AURA_DUMMY); } }; // -5308 - Execute class spell_warr_execute : public SpellScript { PrepareSpellScript(spell_warr_execute); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_EXECUTE, SPELL_WARRIOR_GLYPH_OF_EXECUTION }); } void SendMiss(SpellMissInfo missInfo) { if (missInfo != SPELL_MISS_NONE) { if (Unit* caster = GetCaster()) { if (Unit* target = GetHitUnit()) { caster->SendSpellMiss(target, SPELL_WARRIOR_EXECUTE, missInfo); } } } } void HandleEffect(SpellEffIndex effIndex) { Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) { SpellInfo const* spellInfo = GetSpellInfo(); int32 rageUsed = std::min(300 - spellInfo->CalcPowerCost(caster, SpellSchoolMask(spellInfo->SchoolMask)), caster->GetPower(POWER_RAGE)); int32 newRage = std::max(0, caster->GetPower(POWER_RAGE) - rageUsed); // Sudden Death rage save if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_GENERIC, WARRIOR_ICON_ID_SUDDEN_DEATH, EFFECT_0)) { int32 ragesave = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue() * 10; newRage = std::max(newRage, ragesave); } caster->SetPower(POWER_RAGE, uint32(newRage)); // Glyph of Execution bonus if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_WARRIOR_GLYPH_OF_EXECUTION, EFFECT_0)) rageUsed += aurEff->GetAmount() * 10; int32 bp = GetEffectValue() + int32(rageUsed * spellInfo->Effects[effIndex].DamageMultiplier + caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.2f); caster->CastCustomSpell(target, SPELL_WARRIOR_EXECUTE, &bp, nullptr, nullptr, true, nullptr, nullptr, GetOriginalCaster()->GetGUID()); } } void Register() override { BeforeHit += BeforeSpellHitFn(spell_warr_execute::SendMiss); OnEffectHitTarget += SpellEffectFn(spell_warr_execute::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY); } }; // 12809 - Concussion Blow class spell_warr_concussion_blow : public SpellScript { PrepareSpellScript(spell_warr_concussion_blow); void HandleDummy(SpellEffIndex /*effIndex*/) { SetHitDamage(CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetEffectValue())); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_concussion_blow::HandleDummy, EFFECT_2, SPELL_EFFECT_DUMMY); } }; // 23881 - Bloodthirst class spell_warr_bloodthirst : public SpellScript { PrepareSpellScript(spell_warr_bloodthirst); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_BLOODTHIRST }); } void HandleDamage(SpellEffIndex effIndex) { int32 damage = GetEffectValue(); ApplyPct(damage, GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK)); if (Unit* target = GetHitUnit()) { damage = GetCaster()->SpellDamageBonusDone(target, GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE, effIndex); damage = target->SpellDamageBonusTaken(GetCaster(), GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE); } SetHitDamage(damage); } void HandleDummy(SpellEffIndex /*effIndex*/) { int32 damage = GetEffectValue(); GetCaster()->CastCustomSpell(GetCaster(), SPELL_WARRIOR_BLOODTHIRST, &damage, nullptr, nullptr, true, nullptr); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); OnEffectHit += SpellEffectFn(spell_warr_bloodthirst::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); } }; // 23880 - Bloodthirst (Heal) class spell_warr_bloodthirst_heal : public SpellScript { PrepareSpellScript(spell_warr_bloodthirst_heal); void HandleHeal(SpellEffIndex /*effIndex*/) { if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_BLOODTHIRST_DAMAGE)) SetEffectValue(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster()))); } void Register() override { OnEffectLaunchTarget += SpellEffectFn(spell_warr_bloodthirst_heal::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); } }; // 7384, 7887, 11584, 11585 - Overpower class spell_warr_overpower : public SpellScript { PrepareSpellScript(spell_warr_overpower); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2 }); } void HandleEffect(SpellEffIndex /*effIndex*/) { uint32 spellId = 0; if (GetCaster()->HasAura(SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1)) spellId = SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1; else if (GetCaster()->HasAura(SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2)) spellId = SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2; if (!spellId) return; if (Player* target = GetHitPlayer()) if (target->HasUnitState(UNIT_STATE_CASTING)) target->CastSpell(target, spellId, true, 0, 0, GetCaster()->GetGUID()); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_overpower::HandleEffect, EFFECT_0, SPELL_EFFECT_ANY); } }; // 5246 - Intimidating Shout class spell_warr_intimidating_shout : public SpellScript { PrepareSpellScript(spell_warr_intimidating_shout); void FilterTargets(std::list& targets) { targets.remove(GetExplTargetWorldObject()); uint32 maxTargets = GetSpellInfo()->MaxAffectedTargets; if (targets.size() > maxTargets) targets.resize(maxTargets); } void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); } }; // -772 - Rend class spell_warr_rend : public AuraScript { PrepareAuraScript(spell_warr_rend); void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) { if (Unit* caster = GetCaster()) { canBeRecalculated = false; // $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); int32 mws = caster->GetAttackTime(BASE_ATTACK); float mwbMin = 0.f; float mwbMax = 0.f; for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) { mwbMin += caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE, i); mwbMax += caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE, i); } float mwb = ((mwbMin + mwbMax) / 2 + ap * mws / 14000) * 0.2f; amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb)); // "If used while your target is above 75% health, Rend does 35% more damage." // as for 3.1.3 only ranks above 9 (wrong tooltip?) if (GetSpellInfo()->GetRank() >= 9) { if (GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetSpellInfo(), caster)) AddPct(amount, GetSpellInfo()->Effects[EFFECT_2].CalcValue(caster)); } } } void Register() override { DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warr_rend::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); } }; // 64380, 65941 - Shattering Throw class spell_warr_shattering_throw : public SpellScript { PrepareSpellScript(spell_warr_shattering_throw); void HandleScript(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); // remove shields, will still display immune to damage part if (Unit* target = GetHitUnit()) target->RemoveAurasWithMechanic(1 << MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_shattering_throw::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 12328, 18765, 35429 - Sweeping Strikes class spell_warr_sweeping_strikes : public AuraScript { PrepareAuraScript(spell_warr_sweeping_strikes); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2 }); } bool Load() override { _procTarget = nullptr; return true; } bool CheckProc(ProcEventInfo& eventInfo) { Unit* actor = eventInfo.GetActor(); if (!actor) { return false; } if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo()) { switch (spellInfo->Id) { case SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1: case SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2: case SPELL_WARRIOR_WHIRLWIND_OFF: return false; case SPELL_WARRIOR_WHIRLWIND_MAIN: if (actor->HasSpellCooldown(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1)) { return false; } break; default: break; } } _procTarget = actor->SelectNearbyNoTotemTarget(eventInfo.GetProcTarget()); return _procTarget != nullptr; } void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); if (DamageInfo* damageInfo = eventInfo.GetDamageInfo()) { SpellInfo const* spellInfo = damageInfo->GetSpellInfo(); if (spellInfo && spellInfo->Id == SPELL_WARRIOR_EXECUTE && !_procTarget->HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT)) { // If triggered by Execute (while target is not under 20% hp) deals normalized weapon damage GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2, aurEff); } else { if (spellInfo && spellInfo->Id == SPELL_WARRIOR_WHIRLWIND_MAIN) { eventInfo.GetActor()->AddSpellCooldown(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, 0, 500); } int32 damage = damageInfo->GetUnmitigatedDamage(); GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, &damage, 0, 0, true, nullptr, aurEff); } } } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_sweeping_strikes::CheckProc); OnEffectProc += AuraEffectProcFn(spell_warr_sweeping_strikes::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } private: Unit* _procTarget = nullptr; }; // 50720 - Vigilance class spell_warr_vigilance : public AuraScript { PrepareAuraScript(spell_warr_vigilance); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo( { SPELL_WARRIOR_GLYPH_OF_VIGILANCE, SPELL_WARRIOR_VIGILANCE_PROC, SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT, SPELL_GEN_DAMAGE_REDUCTION_AURA, SPELL_PALADIN_BLESSING_OF_SANCTUARY, SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY, SPELL_PRIEST_RENEWED_HOPE }); } bool Load() override { _procTarget = nullptr; return true; } void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Unit* target = GetTarget(); target->CastSpell(target, SPELL_GEN_DAMAGE_REDUCTION_AURA, true); if (Unit* caster = GetCaster()) target->CastSpell(caster, SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT, true); } void HandleAfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { //! WORKAROUND //! this glyph is a proc if (Unit* caster = GetCaster()) { if (AuraEffect const* glyph = caster->GetAuraEffect(SPELL_WARRIOR_GLYPH_OF_VIGILANCE, EFFECT_0)) GetTarget()->ModifyRedirectThreat(glyph->GetAmount()); } } void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Unit* target = GetTarget(); if (target->HasAura(SPELL_GEN_DAMAGE_REDUCTION_AURA) && !(target->HasAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY) || target->HasAura(SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY) || target->HasAura(SPELL_PRIEST_RENEWED_HOPE))) { target->RemoveAurasDueToSpell(SPELL_GEN_DAMAGE_REDUCTION_AURA); } target->ResetRedirectThreat(); } bool CheckProc(ProcEventInfo& /*eventInfo*/) { _procTarget = GetCaster(); return _procTarget; } void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) { PreventDefaultAction(); GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_VIGILANCE_PROC, true, nullptr, aurEff); } void Register() override { OnEffectApply += AuraEffectApplyFn(spell_warr_vigilance::HandleApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); AfterEffectApply += AuraEffectApplyFn(spell_warr_vigilance::HandleAfterApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); OnEffectRemove += AuraEffectRemoveFn(spell_warr_vigilance::HandleRemove, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); DoCheckProc += AuraCheckProcFn(spell_warr_vigilance::CheckProc); OnEffectProc += AuraEffectProcFn(spell_warr_vigilance::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } private: Unit* _procTarget; }; // 50725 - Vigilance class spell_warr_vigilance_trigger : public SpellScript { PrepareSpellScript(spell_warr_vigilance_trigger); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_TAUNT }); } void HandleScript(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); // Remove Taunt cooldown if (Player* target = GetHitPlayer()) target->RemoveSpellCooldown(SPELL_WARRIOR_TAUNT, true); } void Register() override { OnEffectHitTarget += SpellEffectFn(spell_warr_vigilance_trigger::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 58387 - Glyph of Sunder Armor class spell_warr_glyph_of_sunder_armor : public AuraScript { PrepareAuraScript(spell_warr_glyph_of_sunder_armor); void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) { if (!spellMod) { spellMod = new SpellModifier(aurEff->GetBase()); spellMod->op = SpellModOp(aurEff->GetMiscValue()); spellMod->type = SPELLMOD_FLAT; spellMod->spellId = GetId(); spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; } spellMod->value = aurEff->GetAmount(); } void Register() override { DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_warr_glyph_of_sunder_armor::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); } }; // Spell 28845 - Cheat Death enum CheatDeath { SPELL_CHEAT_DEATH_TRIGGER = 28846 }; class spell_warr_t3_prot_8p_bonus : public AuraScript { PrepareAuraScript(spell_warr_t3_prot_8p_bonus); bool CheckProc(ProcEventInfo& eventInfo) { return eventInfo.GetActionTarget() && eventInfo.GetActionTarget()->GetHealthPct() <= 20.0f; } void HandleEffectProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) { PreventDefaultAction(); if (Unit* target = eventInfo.GetActionTarget()) { target->CastSpell(target, SPELL_CHEAT_DEATH_TRIGGER, true); } } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_t3_prot_8p_bonus::CheckProc); OnEffectProc += AuraEffectProcFn(spell_warr_t3_prot_8p_bonus::HandleEffectProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } }; // 20230 - Retaliation class spell_warr_retaliation : public AuraScript { PrepareAuraScript(spell_warr_retaliation); bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_RETALIATION_DAMAGE }); } bool CheckProc(ProcEventInfo& eventInfo) { if (!eventInfo.GetActor() || !eventInfo.GetProcTarget()) { return false; } // check attack comes not from behind and warrior is not stunned return GetTarget()->isInFront(eventInfo.GetActor(), M_PI) && !GetTarget()->HasUnitState(UNIT_STATE_STUNNED); } void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_WARRIOR_RETALIATION_DAMAGE, true, nullptr, aurEff); } void Register() override { DoCheckProc += AuraCheckProcFn(spell_warr_retaliation::CheckProc); OnEffectProc += AuraEffectProcFn(spell_warr_retaliation::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY); } }; // 29707 - Heroic Strike (Rank 10) // 30324 - Heroic Strike (Rank 11) // 47449 - Heroic Strike (Rank 12) // 47450 - Heroic Strike (Rank 13) enum DazeSpells { ICON_GENERIC_DAZE = 15, SPELL_GENERIC_AFTERMATH = 18118, }; class spell_warr_heroic_strike : public SpellScript { PrepareSpellScript(spell_warr_heroic_strike); void HandleOnHit() { Unit* target = GetHitUnit(); if (!target) return; Unit::AuraEffectList const& AuraEffectList = target->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED); bool bonusDamage = false; for (AuraEffect* eff : AuraEffectList) { const SpellInfo* spellInfo = eff->GetSpellInfo(); if (!spellInfo) continue; // Warrior Spells: Piercing Howl or Dazed (29703) if (spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && (spellInfo->SpellFamilyFlags[1] & (0x20 | 0x200000))) { bonusDamage = true; break; } // Generic Daze: icon 15 with mechanic daze or snare if ((spellInfo->SpellIconID == ICON_GENERIC_DAZE) && ((spellInfo->Mechanic == MECHANIC_DAZE || spellInfo->HasEffectMechanic(MECHANIC_DAZE)) || (spellInfo->Mechanic == MECHANIC_SNARE || spellInfo->HasEffectMechanic(MECHANIC_SNARE)) ) ) { bonusDamage = true; break; } if ((spellInfo->Id == SPELL_GENERIC_AFTERMATH) || (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfo->SpellFamilyFlags[1] & 0x40)) // Blast Wave || (spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && (spellInfo->SpellFamilyFlags[2] & 0x4000)) // Avenger's Shield ) { bonusDamage = true; break; } } if (bonusDamage) { int32 damage = GetHitDamage(); AddPct(damage, 35); // "Causes ${0.35*$m1} additional damage against Dazed targets." SetHitDamage(damage); } } void Register() override { OnHit += SpellHitFn(spell_warr_heroic_strike::HandleOnHit); } }; class spell_war_sudden_death_aura : public AuraScript { PrepareAuraScript(spell_war_sudden_death_aura); bool AfterCheckProc(ProcEventInfo& eventInfo, bool isTriggeredAtSpellProcEvent) { // Check PROC_SPELL_PHASE_FINISH only for Execute if (eventInfo.GetSpellPhaseMask() != PROC_SPELL_PHASE_FINISH) return isTriggeredAtSpellProcEvent; if (Spell const* procSpell = eventInfo.GetProcSpell()) if (procSpell->GetSpellInfo()->GetFirstRankSpell()->Id == SPELL_WARRIOR_EXECUTE_R1) return isTriggeredAtSpellProcEvent; return false; } void Register() override { DoAfterCheckProc += AuraAfterCheckProcFn(spell_war_sudden_death_aura::AfterCheckProc); } }; void AddSC_warrior_spell_scripts() { RegisterSpellScript(spell_warr_mocking_blow); RegisterSpellScript(spell_warr_intervene); RegisterSpellScript(spell_warr_improved_spell_reflection); RegisterSpellAndAuraScriptPair(spell_warr_improved_spell_reflection_trigger, spell_warr_improved_spell_reflection_trigger_aura); RegisterSpellScript(spell_warr_victory_rush); RegisterSpellScript(spell_warr_bloodthirst); RegisterSpellScript(spell_warr_bloodthirst_heal); RegisterSpellScript(spell_warr_charge); RegisterSpellScript(spell_warr_concussion_blow); RegisterSpellScript(spell_warr_damage_shield); RegisterSpellScript(spell_warr_deep_wounds); RegisterSpellScript(spell_warr_execute); RegisterSpellScript(spell_warr_glyph_of_sunder_armor); RegisterSpellScript(spell_warr_intimidating_shout); RegisterSpellScript(spell_warr_last_stand); RegisterSpellScript(spell_warr_overpower); RegisterSpellScript(spell_warr_rend); RegisterSpellScript(spell_warr_retaliation); RegisterSpellScript(spell_warr_shattering_throw); RegisterSpellScript(spell_warr_slam); RegisterSpellScript(spell_warr_sweeping_strikes); RegisterSpellScript(spell_warr_vigilance); RegisterSpellScript(spell_warr_vigilance_trigger); RegisterSpellScript(spell_warr_t3_prot_8p_bonus); RegisterSpellScript(spell_warr_heroic_strike); RegisterSpellScript(spell_war_sudden_death_aura); }