/*
* 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_HUNTER, SPELLFAMILY_PET and SPELLFAMILY_GENERIC spells used by hunter players.
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "spell_hun_".
*/
#include "ScriptMgr.h"
#include "AreaTriggerAI.h"
#include "CellImpl.h"
#include "GridNotifiersImpl.h"
#include "ObjectAccessor.h"
#include "Pet.h"
#include "SpellAuraEffects.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
enum HunterSpells
{
SPELL_HUNTER_A_MURDER_OF_CROWS_DAMAGE = 131900,
SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_1 = 131637,
SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_2 = 131951,
SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_3 = 131952,
SPELL_HUNTER_AIMED_SHOT = 19434,
SPELL_HUNTER_ASPECT_CHEETAH_SLOW = 186258,
SPELL_HUNTER_ASPECT_OF_THE_FOX = 1219162,
SPELL_HUNTER_ASPECT_OF_THE_TURTLE_PACIFY_AURA = 205769,
SPELL_HUNTER_BINDING_SHOT = 109248,
SPELL_HUNTER_BINDING_SHOT_IMMUNE = 117553,
SPELL_HUNTER_BINDING_SHOT_MARKER = 117405,
SPELL_HUNTER_BINDING_SHOT_STUN = 117526,
SPELL_HUNTER_BINDING_SHOT_VISUAL = 117614,
SPELL_HUNTER_BINDING_SHOT_VISUAL_ARROW = 118306,
SPELL_HUNTER_CONCUSSIVE_SHOT = 5116,
SPELL_HUNTER_EMERGENCY_SALVE_TALENT = 459517,
SPELL_HUNTER_EMERGENCY_SALVE_DISPEL = 459521,
SPELL_HUNTER_ENTRAPMENT_TALENT = 393344,
SPELL_HUNTER_ENTRAPMENT_ROOT = 393456,
SPELL_HUNTER_EXHILARATION = 109304,
SPELL_HUNTER_EXHILARATION_PET = 128594,
SPELL_HUNTER_EXHILARATION_R2 = 231546,
SPELL_HUNTER_EXPLOSIVE_SHOT_DAMAGE = 212680,
SPELL_HUNTER_GREVIOUS_INJURY = 1217789,
SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP = 236775,
SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP_DAMAGE = 236777,
SPELL_HUNTER_IMPLOSIVE_TRAP = 462032,
SPELL_HUNTER_IMPLOSIVE_TRAP_DAMAGE = 462033,
SPELL_HUNTER_INTIMIDATION = 19577,
SPELL_HUNTER_INTIMIDATION_MARKSMANSHIP = 474421,
SPELL_HUNTER_LATENT_POISON_STACK = 378015,
SPELL_HUNTER_LATENT_POISON_DAMAGE = 378016,
SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK = 336903,
SPELL_HUNTER_LATENT_POISON_INJECTORS_DAMAGE = 336904,
SPELL_HUNTER_LOCK_AND_LOAD = 194594,
SPELL_HUNTER_LONE_WOLF = 155228,
SPELL_HUNTER_MARKSMANSHIP_HUNTER_AURA = 137016,
SPELL_HUNTER_MASTER_MARKSMAN = 269576,
SPELL_HUNTER_MASTERS_CALL_TRIGGERED = 62305,
SPELL_HUNTER_MISDIRECTION = 34477,
SPELL_HUNTER_MISDIRECTION_PROC = 35079,
SPELL_HUNTER_MULTI_SHOT_FOCUS = 213363,
SPELL_HUNTER_PET_LAST_STAND_TRIGGERED = 53479,
SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED = 54114,
SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF = 55711,
SPELL_HUNTER_POSTHASTE_INCREASE_SPEED = 118922,
SPELL_HUNTER_POSTHASTE_TALENT = 109215,
SPELL_HUNTER_PRECISE_SHOTS = 260242,
SPELL_HUNTER_RAPID_FIRE = 257044,
SPELL_HUNTER_RAPID_FIRE_DAMAGE = 257045,
SPELL_HUNTER_RAPID_FIRE_ENERGIZE = 263585,
SPELL_HUNTER_REJUVENATING_WIND_HEAL = 385540,
SPELL_HUNTER_SCOUTS_INSTINCTS = 459455,
SPELL_HUNTER_SHRAPNEL_SHOT_TALENT = 473520,
SPELL_HUNTER_SHRAPNEL_SHOT_DEBUFF = 474310,
SPELL_HUNTER_STEADY_SHOT = 56641,
SPELL_HUNTER_STEADY_SHOT_FOCUS = 77443,
SPELL_HUNTER_STREAMLINE_TALENT = 260367,
SPELL_HUNTER_STREAMLINE_BUFF = 342076,
SPELL_HUNTER_T9_4P_GREATNESS = 68130,
SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE = 394371,
SPELL_HUNTER_TAR_TRAP = 187699,
SPELL_HUNTER_TAR_TRAP_AREATRIGGER = 187700,
SPELL_HUNTER_TAR_TRAP_SLOW = 135299,
SPELL_HUNTER_WILDERNESS_MEDICINE_TALENT = 343242,
SPELL_HUNTER_WILDERNESS_MEDICINE_DISPEL = 384784,
SPELL_ROAR_OF_SACRIFICE_TRIGGERED = 67481
};
enum MiscSpells
{
SPELL_DRAENEI_GIFT_OF_THE_NAARU = 59543,
};
// 131894 - A Murder of Crows
class spell_hun_a_murder_of_crows : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_HUNTER_A_MURDER_OF_CROWS_DAMAGE,
SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_1,
SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_2,
SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_3
});
}
void HandleDummyTick(AuraEffect const* /*aurEff*/)
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
caster->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_DAMAGE, true);
target->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_1, true);
target->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_2, true);
target->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_3, true);
target->CastSpell(target, SPELL_HUNTER_A_MURDER_OF_CROWS_VISUAL_3, true); // not a mistake, it is intended to cast twice
}
void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
if (Unit* caster = GetCaster())
caster->GetSpellHistory()->ResetCooldown(GetId(), true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_a_murder_of_crows::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
OnEffectRemove += AuraEffectRemoveFn(spell_hun_a_murder_of_crows::RemoveEffect, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 186257 - Aspect of the Cheetah
class spell_hun_aspect_cheetah : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_HUNTER_ASPECT_CHEETAH_SLOW
});
}
void HandleOnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_ASPECT_CHEETAH_SLOW, true);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_hun_aspect_cheetah::HandleOnRemove, EFFECT_0, SPELL_AURA_MOD_INCREASE_SPEED, AURA_EFFECT_HANDLE_REAL);
}
};
// 1219162 - Aspect of the Fox (attached to 186257 - Aspect of the Cheetah)
class spell_hun_aspect_of_the_fox : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_HUNTER_ASPECT_OF_THE_FOX })
&& ValidateSpellEffect({ { spellInfo->Id, EFFECT_2 } })
&& spellInfo->GetEffect(EFFECT_2).IsAura(SPELL_AURA_CAST_WHILE_WALKING);
}
bool Load() override
{
return !GetCaster()->HasAura(SPELL_HUNTER_ASPECT_OF_THE_FOX);
}
static void HandleCastWhileWalking(SpellScript const&, WorldObject*& target)
{
target = nullptr;
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_hun_aspect_of_the_fox::HandleCastWhileWalking, EFFECT_2, TARGET_UNIT_CASTER);
}
};
// 186265 - Aspect of the Turtle
class spell_hun_aspect_of_the_turtle : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_ASPECT_OF_THE_TURTLE_PACIFY_AURA });
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_ASPECT_OF_THE_TURTLE_PACIFY_AURA, true);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_HUNTER_ASPECT_OF_THE_TURTLE_PACIFY_AURA);
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_hun_aspect_of_the_turtle::OnApply, EFFECT_0, SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_hun_aspect_of_the_turtle::OnRemove, EFFECT_0, SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE, AURA_EFFECT_HANDLE_REAL);
}
};
// 109248 - Binding Shot
class spell_hun_binding_shot : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_BINDING_SHOT_VISUAL_ARROW });
}
void HandleCast()
{
GetCaster()->CastSpell(GetExplTargetDest()->GetPosition(), SPELL_HUNTER_BINDING_SHOT_VISUAL_ARROW, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
void Register() override
{
OnCast += SpellCastFn(spell_hun_binding_shot::HandleCast);
}
};
// 109248 - Binding Shot
// Id - 1524
struct at_hun_binding_shot : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_BINDING_SHOT))
other->SetDuration(0);
}
void OnCreate(Spell const* /*creatingSpell*/) override
{
_scheduler.Schedule(1s, [this](TaskContext task)
{
for (ObjectGuid const& guid : at->GetInsideUnits())
{
Unit* unit = ObjectAccessor::GetUnit(*at, guid);
if (!unit->HasAura(SPELL_HUNTER_BINDING_SHOT_MARKER))
continue;
unit->CastSpell(at->GetPosition(), SPELL_HUNTER_BINDING_SHOT_VISUAL, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
task.Repeat(1s);
});
}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit) && !unit->HasAura(SPELL_HUNTER_BINDING_SHOT_IMMUNE, caster->GetGUID()))
{
caster->CastSpell(unit, SPELL_HUNTER_BINDING_SHOT_MARKER, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
unit->CastSpell(at->GetPosition(), SPELL_HUNTER_BINDING_SHOT_VISUAL, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
}
}
void OnUnitExit(Unit* unit, AreaTriggerExitReason /*reason*/) override
{
unit->RemoveAurasDueToSpell(SPELL_HUNTER_BINDING_SHOT_MARKER, at->GetCasterGuid());
if (at->IsRemoved())
return;
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit) && !unit->HasAura(SPELL_HUNTER_BINDING_SHOT_IMMUNE, caster->GetGUID()))
{
caster->CastSpell(unit, SPELL_HUNTER_BINDING_SHOT_STUN, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
caster->CastSpell(unit, SPELL_HUNTER_BINDING_SHOT_IMMUNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
}
}
void OnUpdate(uint32 diff) override
{
_scheduler.Update(diff);
}
private:
TaskScheduler _scheduler;
};
// 204089 - Bullseye
class spell_hun_bullseye : public AuraScript
{
static bool CheckEffectProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
return eventInfo.GetActionTarget()->HealthBelowPct(aurEff->GetAmount());
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_hun_bullseye::CheckEffectProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 378750 - Cobra Sting
class spell_hun_cobra_sting : public AuraScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
bool RollProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*procInfo*/)
{
return roll_chance_i(GetEffect(EFFECT_1)->GetAmount());
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_hun_cobra_sting::RollProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 5116 - Concussive Shot (attached to 193455 - Cobra Shot and 56641 - Steady Shot)
class spell_hun_concussive_shot : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo ({ SPELL_HUNTER_CONCUSSIVE_SHOT, })
&& ValidateSpellEffect({ { SPELL_HUNTER_STEADY_SHOT, EFFECT_2 } });
}
void HandleDuration(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
if (Aura* concussiveShot = GetHitUnit()->GetAura(SPELL_HUNTER_CONCUSSIVE_SHOT, caster->GetGUID()))
{
SpellInfo const* steadyShot = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_STEADY_SHOT, GetCastDifficulty());
Milliseconds extraDuration = Seconds(steadyShot->GetEffect(EFFECT_2).CalcValue(caster) / 10);
Milliseconds newDuration = Milliseconds(concussiveShot->GetDuration()) + extraDuration;
concussiveShot->SetDuration(newDuration.count());
concussiveShot->SetMaxDuration(newDuration.count());
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_hun_concussive_shot::HandleDuration, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 459517 - Concussive Shot (attached to 186265 - Aspect of the Turtle and 5384 - Feign Death)
class spell_hun_emergency_salve : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_EMERGENCY_SALVE_TALENT, SPELL_HUNTER_EMERGENCY_SALVE_DISPEL });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_HUNTER_EMERGENCY_SALVE_TALENT);
}
void HandleAfterCast() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_HUNTER_EMERGENCY_SALVE_DISPEL, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_hun_emergency_salve::HandleAfterCast);
}
};
// 109304 - Exhilaration
class spell_hun_exhilaration : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_EXHILARATION_R2, SPELL_HUNTER_LONE_WOLF });
}
void HandleOnHit()
{
if (GetCaster()->HasAura(SPELL_HUNTER_EXHILARATION_R2) && !GetCaster()->HasAura(SPELL_HUNTER_LONE_WOLF))
GetCaster()->CastSpell(nullptr, SPELL_HUNTER_EXHILARATION_PET, true);
}
void Register() override
{
OnHit += SpellHitFn(spell_hun_exhilaration::HandleOnHit);
}
};
// 212431 - Explosive Shot
class spell_hun_explosive_shot : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_EXPLOSIVE_SHOT_DAMAGE });
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
caster->CastSpell(GetTarget(), SPELL_HUNTER_EXPLOSIVE_SHOT_DAMAGE, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_explosive_shot::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 236775 - High Explosive Trap
// 9810 - AreatriggerId
struct areatrigger_hun_high_explosive_trap : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP))
other->SetDuration(0);
}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit))
{
caster->CastSpell(at->GetPosition(), SPELL_HUNTER_HIGH_EXPLOSIVE_TRAP_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
at->Remove();
}
}
}
};
// 212658 - Hunting Party
class spell_hun_hunting_party : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_HUNTER_EXHILARATION,
SPELL_HUNTER_EXHILARATION_PET
});
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_HUNTER_EXHILARATION, -Seconds(aurEff->GetAmount()));
GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_HUNTER_EXHILARATION_PET, -Seconds(aurEff->GetAmount()));
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_hun_hunting_party::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 462032 - Implosive Trap
// 34378 - AreatriggerId
struct areatrigger_hun_implosive_trap : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_IMPLOSIVE_TRAP))
other->SetDuration(0);
}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit))
{
caster->CastSpell(at->GetPosition(), SPELL_HUNTER_IMPLOSIVE_TRAP_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
at->Remove();
}
}
}
};
// 53478 - Last Stand Pet
class spell_hun_last_stand_pet : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_PET_LAST_STAND_TRIGGERED });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.AddSpellBP0(caster->CountPctFromMaxHealth(30));
caster->CastSpell(caster, SPELL_HUNTER_PET_LAST_STAND_TRIGGERED, args);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_hun_last_stand_pet::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 378016 - Latent Poison
class spell_hun_latent_poison_damage : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_LATENT_POISON_STACK });
}
void CalculateDamage()
{
if (Aura* stack = GetHitUnit()->GetAura(SPELL_HUNTER_LATENT_POISON_STACK, GetCaster()->GetGUID()))
{
SetHitDamage(GetHitDamage() * stack->GetStackAmount());
stack->Remove();
}
}
void Register() override
{
OnHit += SpellHitFn(spell_hun_latent_poison_damage::CalculateDamage);
}
};
// 19434 - Aimed Shot
// 186270 - Raptor Strike
// 217200 - Barbed Shot
// 259387 - Mongoose Bite
class spell_hun_latent_poison_trigger : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_LATENT_POISON_STACK, SPELL_HUNTER_LATENT_POISON_DAMAGE });
}
void TriggerDamage()
{
if (GetHitUnit()->HasAura(SPELL_HUNTER_LATENT_POISON_STACK, GetCaster()->GetGUID()))
GetCaster()->CastSpell(GetHitUnit(), SPELL_HUNTER_LATENT_POISON_DAMAGE, GetSpell());
}
void Register() override
{
AfterHit += SpellHitFn(spell_hun_latent_poison_trigger::TriggerDamage);
}
};
// 336904 - Latent Poison Injectors
class spell_hun_latent_poison_injectors_damage : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK });
}
void CalculateDamage()
{
if (Aura* stack = GetHitUnit()->GetAura(SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK, GetCaster()->GetGUID()))
{
SetHitDamage(GetHitDamage() * stack->GetStackAmount());
stack->Remove();
}
}
void Register() override
{
OnHit += SpellHitFn(spell_hun_latent_poison_injectors_damage::CalculateDamage);
}
};
// 186270 - Raptor Strike
// 259387 - Mongoose Bite
class spell_hun_latent_poison_injectors_trigger : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK, SPELL_HUNTER_LATENT_POISON_INJECTORS_DAMAGE });
}
void TriggerDamage()
{
if (GetHitUnit()->HasAura(SPELL_HUNTER_LATENT_POISON_INJECTORS_STACK, GetCaster()->GetGUID()))
GetCaster()->CastSpell(GetHitUnit(), SPELL_HUNTER_LATENT_POISON_INJECTORS_DAMAGE, GetSpell());
}
void Register() override
{
AfterHit += SpellHitFn(spell_hun_latent_poison_injectors_trigger::TriggerDamage);
}
};
// 194595 - Lock and Load
class spell_hun_lock_and_load : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_LOCK_AND_LOAD });
}
static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/)
{
return roll_chance_i(aurEff->GetAmount());
}
static void HandleProc(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo)
{
Unit* caster = eventInfo.GetActor();
caster->CastSpell(caster, SPELL_HUNTER_LOCK_AND_LOAD, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR
});
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_hun_lock_and_load::CheckProc, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_hun_lock_and_load::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 1217788 - Manhunter
class spell_hun_manhunter : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_GREVIOUS_INJURY });
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return eventInfo.GetProcTarget()->IsPlayer();
}
static void HandleEffectProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
eventInfo.GetActor()->CastSpell(eventInfo.GetActionTarget(), SPELL_HUNTER_GREVIOUS_INJURY, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_hun_manhunter::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_hun_manhunter::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 260309 - Master Marksman
class spell_hun_master_marksman : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_MASTER_MARKSMAN });
}
static void HandleProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
uint32 ticks = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_MASTER_MARKSMAN, DIFFICULTY_NONE)->GetMaxTicks();
if (!ticks)
return;
int32 damage = CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()) / ticks;
eventInfo.GetActor()->CastSpell(eventInfo.GetActionTarget(), SPELL_HUNTER_MASTER_MARKSMAN, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.SpellValueOverrides = { { SPELLVALUE_BASE_POINT0, damage } }
});
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_hun_master_marksman::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 53271 - Masters Call
class spell_hun_masters_call : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } })
&& ValidateSpellInfo({ SPELL_HUNTER_MASTERS_CALL_TRIGGERED, uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
SpellCastResult DoCheckCast()
{
Guardian* pet = GetCaster()->ToPlayer()->GetGuardianPet();
ASSERT(pet); // checked in Spell::CheckCast
if (!pet->IsPet() || !pet->IsAlive())
return SPELL_FAILED_NO_PET;
// Do a mini Spell::CheckCasterAuras on the pet, no other way of doing this
SpellCastResult result = SPELL_CAST_OK;
uint32 const unitflag = pet->m_unitData->Flags;
if (!pet->GetCharmerGUID().IsEmpty())
result = SPELL_FAILED_CHARMED;
else if (unitflag & UNIT_FLAG_STUNNED)
result = SPELL_FAILED_STUNNED;
else if (unitflag & UNIT_FLAG_FLEEING)
result = SPELL_FAILED_FLEEING;
else if (unitflag & UNIT_FLAG_CONFUSED)
result = SPELL_FAILED_CONFUSED;
if (result != SPELL_CAST_OK)
return result;
Unit* target = GetExplTargetUnit();
if (!target)
return SPELL_FAILED_BAD_TARGETS;
if (!pet->IsWithinLOSInMap(target))
return SPELL_FAILED_LINE_OF_SIGHT;
return SPELL_CAST_OK;
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
GetCaster()->ToPlayer()->GetPet()->CastSpell(GetHitUnit(), GetEffectValue(), true);
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->CastSpell(nullptr, SPELL_HUNTER_MASTERS_CALL_TRIGGERED, true);
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_hun_masters_call::DoCheckCast);
OnEffectHitTarget += SpellEffectFn(spell_hun_masters_call::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
OnEffectHitTarget += SpellEffectFn(spell_hun_masters_call::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 34477 - Misdirection
class spell_hun_misdirection : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_MISDIRECTION_PROC });
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEFAULT || GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_INTERRUPT)
return;
if (!GetTarget()->HasAura(SPELL_HUNTER_MISDIRECTION_PROC))
GetTarget()->GetThreatManager().UnregisterRedirectThreat(SPELL_HUNTER_MISDIRECTION);
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_MISDIRECTION_PROC, aurEff);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_hun_misdirection::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectProc += AuraEffectProcFn(spell_hun_misdirection::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
}
};
// 35079 - Misdirection (Proc)
class spell_hun_misdirection_proc : public AuraScript
{
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->GetThreatManager().UnregisterRedirectThreat(SPELL_HUNTER_MISDIRECTION);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_hun_misdirection_proc::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 2643 - Multi-Shot
class spell_hun_multi_shot : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_MULTI_SHOT_FOCUS });
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void HandleOnHit()
{
// We need to check hunter's spec because it doesn't generate focus on other specs than MM
if (GetCaster()->ToPlayer()->GetPrimarySpecialization() == ChrSpecialization::HunterMarksmanship)
GetCaster()->CastSpell(GetCaster(), SPELL_HUNTER_MULTI_SHOT_FOCUS, true);
}
void Register() override
{
OnHit += SpellHitFn(spell_hun_multi_shot::HandleOnHit);
}
};
// 459783 - Penetrating Shots
class spell_hun_penetrating_shots : public AuraScript
{
void CalcAmount(AuraEffect const* /*aurEff*/, int32& amount, bool const& /*canBeRecalculated*/) const
{
if (AuraEffect const* amountHolder = GetEffect(EFFECT_1))
{
float critChanceDone = GetUnitOwner()->GetUnitCriticalChanceDone(BASE_ATTACK);
amount = CalculatePct(critChanceDone, amountHolder->GetAmount());
}
}
void UpdatePeriodic(AuraEffect const* aurEff) const
{
if (AuraEffect* bonus = GetEffect(EFFECT_0))
bonus->RecalculateAmount(aurEff);
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_penetrating_shots::CalcAmount, EFFECT_0, SPELL_AURA_MOD_CRIT_DAMAGE_BONUS);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_penetrating_shots::UpdatePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 55709 - Pet Heart of the Phoenix
class spell_hun_pet_heart_of_the_phoenix : public SpellScript
{
bool Load() override
{
if (!GetCaster()->IsPet())
return false;
return true;
}
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF });
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Unit* owner = caster->GetOwner())
{
if (!caster->HasAura(SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF))
{
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.AddSpellBP0(100);
owner->CastSpell(caster, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED, args);
caster->CastSpell(caster, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF, true);
}
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_hun_pet_heart_of_the_phoenix::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 781 - Disengage
class spell_hun_posthaste : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_POSTHASTE_TALENT, SPELL_HUNTER_POSTHASTE_INCREASE_SPEED });
}
void HandleAfterCast()
{
if (GetCaster()->HasAura(SPELL_HUNTER_POSTHASTE_TALENT))
{
GetCaster()->RemoveMovementImpairingAuras(true);
GetCaster()->CastSpell(GetCaster(), SPELL_HUNTER_POSTHASTE_INCREASE_SPEED, GetSpell());
}
}
void Register() override
{
AfterCast += SpellCastFn(spell_hun_posthaste::HandleAfterCast);
}
};
// 260240 - Precise Shots
class spell_hun_precise_shots : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_PRECISE_SHOTS });
}
void HandleProc(ProcEventInfo const& eventInfo) const
{
eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_HUNTER_PRECISE_SHOTS, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = eventInfo.GetProcSpell()
});
}
void Register() override
{
OnProc += AuraProcFn(spell_hun_precise_shots::HandleProc);
}
};
// 257044 - Rapid Fire
class spell_hun_rapid_fire : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_RAPID_FIRE_DAMAGE });
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
caster->CastSpell(GetTarget(), SPELL_HUNTER_RAPID_FIRE_DAMAGE, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_rapid_fire::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 257045 - Rapid Fire Damage
class spell_hun_rapid_fire_damage : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_RAPID_FIRE_ENERGIZE });
}
void HandleHit(SpellEffIndex /*effIndex*/)
{
GetCaster()->CastSpell(nullptr, SPELL_HUNTER_RAPID_FIRE_ENERGIZE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_hun_rapid_fire_damage::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 385539 - Rejuvenating Wind
class spell_hun_rejuvenating_wind : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_REJUVENATING_WIND_HEAL })
&& sSpellMgr->AssertSpellInfo(SPELL_HUNTER_REJUVENATING_WIND_HEAL, DIFFICULTY_NONE)->GetMaxTicks() > 0;
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& /*procEvent*/)
{
PreventDefaultAction();
Unit* caster = GetTarget();
uint32 ticks = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_REJUVENATING_WIND_HEAL, DIFFICULTY_NONE)->GetMaxTicks();
int32 heal = CalculatePct(caster->GetMaxHealth(), aurEff->GetAmount()) / ticks;
caster->CastSpell(caster, SPELL_HUNTER_REJUVENATING_WIND_HEAL, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.SpellValueOverrides = { { SPELLVALUE_BASE_POINT0, heal } }
});
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_hun_rejuvenating_wind::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 53480 - Roar of Sacrifice
class spell_hun_roar_of_sacrifice : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_ROAR_OF_SACRIFICE_TRIGGERED });
}
bool CheckProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
if (!damageInfo || !(damageInfo->GetSchoolMask() & aurEff->GetMiscValue()))
return false;
if (!GetCaster())
return false;
return true;
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
CastSpellExtraArgs args(aurEff);
args.AddSpellBP0(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()));
eventInfo.GetActor()->CastSpell(GetCaster(), SPELL_ROAR_OF_SACRIFICE_TRIGGERED, args);
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_hun_roar_of_sacrifice::CheckProc, EFFECT_1, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_hun_roar_of_sacrifice::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
}
};
// 37506 - Scatter Shot
class spell_hun_scatter_shot : public SpellScript
{
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Player* caster = GetCaster()->ToPlayer();
// break Auto Shot and autohit
caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
caster->AttackStop();
caster->SendAttackSwingCancelAttack();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_hun_scatter_shot::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 459455 - Scout's Instincts (attached to 186257 - Aspect of the Cheetah)
class spell_hun_scouts_instincts : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_HUNTER_SCOUTS_INSTINCTS })
&& ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
&& spellInfo->GetEffect(EFFECT_1).IsAura(SPELL_AURA_MOD_MINIMUM_SPEED);
}
bool Load() override
{
return !GetCaster()->HasAura(SPELL_HUNTER_SCOUTS_INSTINCTS);
}
static void HandleMinSpeed(SpellScript const&, WorldObject*& target)
{
target = nullptr;
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_hun_scouts_instincts::HandleMinSpeed, EFFECT_1, TARGET_UNIT_CASTER);
}
};
// 459533 - Scrappy
class spell_hun_scrappy : public AuraScript
{
static constexpr std::array AffectedSpellIds = { SPELL_HUNTER_BINDING_SHOT, SPELL_HUNTER_INTIMIDATION, SPELL_HUNTER_INTIMIDATION_MARKSMANSHIP };
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(AffectedSpellIds);
}
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/) const
{
for (uint32 spellId : AffectedSpellIds)
GetTarget()->GetSpellHistory()->ModifyCooldown(spellId, -Milliseconds(aurEff->GetAmount()));
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_hun_scrappy::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 473520 - Shrapnel Shot
class spell_hun_shrapnel_shot : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_LOCK_AND_LOAD });
}
void HandleProc(ProcEventInfo const& /*eventInfo*/) const
{
if (!roll_chance_i(GetEffect(EFFECT_0)->GetAmount()))
return;
GetCaster()->CastSpell(GetCaster(), SPELL_HUNTER_LOCK_AND_LOAD, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR
});
}
void Register() override
{
OnProc += AuraProcFn(spell_hun_shrapnel_shot::HandleProc);
}
};
// 56641 - Steady Shot
class spell_hun_steady_shot : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_STEADY_SHOT_FOCUS, SPELL_HUNTER_AIMED_SHOT, SPELL_HUNTER_MARKSMANSHIP_HUNTER_AURA });
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void HandleOnHit() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_HUNTER_STEADY_SHOT_FOCUS, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
if (GetCaster()->HasAura(SPELL_HUNTER_MARKSMANSHIP_HUNTER_AURA))
GetCaster()->GetSpellHistory()->ModifyCooldown(SPELL_HUNTER_AIMED_SHOT, Milliseconds(-GetEffectInfo(EFFECT_1).CalcValue()));
}
void Register() override
{
OnHit += SpellHitFn(spell_hun_steady_shot::HandleOnHit);
}
};
// 260367 - Streamline (attached to 257044 - Rapid Fire)
class spell_hun_streamline : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_STREAMLINE_TALENT, SPELL_HUNTER_STREAMLINE_BUFF });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_HUNTER_STREAMLINE_TALENT);
}
void HandleAfterCast() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_HUNTER_STREAMLINE_BUFF, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_hun_streamline::HandleAfterCast);
}
};
// 391559 - Surging Shots
class spell_hun_surging_shots : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_RAPID_FIRE });
}
void HandleProc(ProcEventInfo const& /*eventInfo*/) const
{
GetTarget()->GetSpellHistory()->ResetCooldown(SPELL_HUNTER_RAPID_FIRE, true);
}
void Register() override
{
OnProc += AuraProcFn(spell_hun_surging_shots::HandleProc);
}
};
// 1515 - Tame Beast
class spell_hun_tame_beast : public SpellScript
{
static constexpr uint32 CallPetSpellIds[MAX_ACTIVE_PETS] =
{
883,
83242,
83243,
83244,
83245,
};
SpellCastResult CheckCast()
{
Player* caster = GetCaster()->ToPlayer();
if (!caster)
return SPELL_FAILED_DONT_REPORT;
if (!GetExplTargetUnit())
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
if (Creature* target = GetExplTargetUnit()->ToCreature())
{
if (target->GetLevelForTarget(caster) > caster->GetLevel())
return SPELL_FAILED_HIGHLEVEL;
// use SMSG_PET_TAME_FAILURE?
if (!target->GetCreatureTemplate()->IsTameable(caster->CanTameExoticPets(), target->GetCreatureDifficulty()))
return SPELL_FAILED_BAD_TARGETS;
if (PetStable const* petStable = caster->GetPetStable())
{
if (petStable->CurrentPetIndex)
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
auto freeSlotItr = std::find_if(petStable->ActivePets.begin(), petStable->ActivePets.end(), [](Optional const& petInfo)
{
return !petInfo.has_value();
});
if (freeSlotItr == petStable->ActivePets.end())
{
caster->SendTameFailure(PetTameResult::TooMany);
return SPELL_FAILED_DONT_REPORT;
}
// Check for known Call Pet X spells
std::size_t freeSlotIndex = std::distance(petStable->ActivePets.begin(), freeSlotItr);
if (!caster->HasSpell(CallPetSpellIds[freeSlotIndex]))
{
caster->SendTameFailure(PetTameResult::TooMany);
return SPELL_FAILED_DONT_REPORT;
}
}
if (!caster->GetCharmedGUID().IsEmpty())
return SPELL_FAILED_ALREADY_HAVE_CHARM;
if (!target->GetOwnerGUID().IsEmpty())
{
caster->SendTameFailure(PetTameResult::CreatureAlreadyOwned);
return SPELL_FAILED_DONT_REPORT;
}
}
else
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_hun_tame_beast::CheckCast);
}
};
// 187700 - Tar Trap
// 4436 - AreatriggerId
struct areatrigger_hun_tar_trap : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnCreate(Spell const* /*creatingSpell*/) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->HasAura(SPELL_HUNTER_ENTRAPMENT_TALENT))
caster->CastSpell(at->GetPosition(), SPELL_HUNTER_ENTRAPMENT_ROOT, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit))
caster->CastSpell(unit, SPELL_HUNTER_TAR_TRAP_SLOW, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
}
void OnUnitExit(Unit* unit, AreaTriggerExitReason /*reason*/) override
{
unit->RemoveAurasDueToSpell(SPELL_HUNTER_TAR_TRAP_SLOW, at->GetCasterGuid());
}
};
// 187699 - Tar Trap
// 4435 - AreatriggerId
struct areatrigger_hun_tar_trap_activate : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
for (AreaTrigger* other : caster->GetAreaTriggers(SPELL_HUNTER_TAR_TRAP))
other->SetDuration(0);
}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit))
{
caster->CastSpell(at->GetPosition(), SPELL_HUNTER_TAR_TRAP_AREATRIGGER, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
at->Remove();
}
}
}
};
// 67151 - Item - Hunter T9 4P Bonus (Steady Shot)
class spell_hun_t9_4p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_T9_4P_GREATNESS });
}
bool CheckProc(ProcEventInfo& eventInfo)
{
if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER && eventInfo.GetActor()->ToPlayer()->GetPet())
return true;
return false;
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
caster->CastSpell(caster->ToPlayer()->GetPet(), SPELL_HUNTER_T9_4P_GREATNESS, aurEff);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_hun_t9_4p_bonus::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_hun_t9_4p_bonus::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 394366 - Find The Mark
class spell_hun_t29_2p_marksmanship_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE, EFFECT_0 } })
&& sSpellMgr->AssertSpellInfo(SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE, DIFFICULTY_NONE)->GetMaxTicks();
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
uint32 ticks = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE, DIFFICULTY_NONE)->GetMaxTicks();
uint32 damage = CalculatePct(eventInfo.GetDamageInfo()->GetOriginalDamage(), aurEff->GetAmount()) / ticks;
caster->CastSpell(eventInfo.GetActionTarget(), SPELL_HUNTER_T29_2P_MARKSMANSHIP_DAMAGE, CastSpellExtraArgs(aurEff)
.SetTriggeringSpell(eventInfo.GetProcSpell())
.AddSpellMod(SPELLVALUE_BASE_POINT0, damage));
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_hun_t29_2p_marksmanship_bonus::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// Called by 136 - Mend Pet
class spell_hun_wilderness_medicine : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_WILDERNESS_MEDICINE_TALENT, SPELL_HUNTER_WILDERNESS_MEDICINE_DISPEL });
}
bool Load() override
{
Unit const* caster = GetCaster();
if (!caster)
return false;
AuraEffect const* wildernessMedicine = GetCaster()->GetAuraEffect(SPELL_HUNTER_WILDERNESS_MEDICINE_TALENT, EFFECT_1);
if (!wildernessMedicine)
return false;
_dispelChance = wildernessMedicine->GetAmount();
return true;
}
void OnPeriodic(AuraEffect const* aurEff) const
{
if (Unit* caster = GetCaster())
if (roll_chance_i(_dispelChance))
caster->CastSpell(GetTarget(), SPELL_HUNTER_WILDERNESS_MEDICINE_DISPEL, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_wilderness_medicine::OnPeriodic, EFFECT_0, SPELL_AURA_OBS_MOD_HEALTH);
}
int32 _dispelChance = 0;
};
void AddSC_hunter_spell_scripts()
{
RegisterSpellScript(spell_hun_a_murder_of_crows);
RegisterSpellScript(spell_hun_aspect_cheetah);
RegisterSpellScript(spell_hun_aspect_of_the_fox);
RegisterSpellScript(spell_hun_aspect_of_the_turtle);
RegisterSpellScript(spell_hun_binding_shot);
RegisterAreaTriggerAI(at_hun_binding_shot);
RegisterSpellScript(spell_hun_bullseye);
RegisterSpellScript(spell_hun_cobra_sting);
RegisterSpellScript(spell_hun_concussive_shot);
RegisterSpellScript(spell_hun_emergency_salve);
RegisterSpellScript(spell_hun_exhilaration);
RegisterSpellScript(spell_hun_explosive_shot);
RegisterAreaTriggerAI(areatrigger_hun_high_explosive_trap);
RegisterSpellScript(spell_hun_hunting_party);
RegisterAreaTriggerAI(areatrigger_hun_implosive_trap);
RegisterSpellScript(spell_hun_last_stand_pet);
RegisterSpellScript(spell_hun_latent_poison_damage);
RegisterSpellScript(spell_hun_latent_poison_trigger);
RegisterSpellScript(spell_hun_latent_poison_injectors_damage);
RegisterSpellScript(spell_hun_latent_poison_injectors_trigger);
RegisterSpellScript(spell_hun_lock_and_load);
RegisterSpellScript(spell_hun_manhunter);
RegisterSpellScript(spell_hun_master_marksman);
RegisterSpellScript(spell_hun_masters_call);
RegisterSpellScript(spell_hun_misdirection);
RegisterSpellScript(spell_hun_misdirection_proc);
RegisterSpellScript(spell_hun_multi_shot);
RegisterSpellScript(spell_hun_penetrating_shots);
RegisterSpellScript(spell_hun_pet_heart_of_the_phoenix);
RegisterSpellScript(spell_hun_posthaste);
RegisterSpellScript(spell_hun_precise_shots);
RegisterSpellScript(spell_hun_rapid_fire);
RegisterSpellScript(spell_hun_rapid_fire_damage);
RegisterSpellScript(spell_hun_rejuvenating_wind);
RegisterSpellScript(spell_hun_roar_of_sacrifice);
RegisterSpellScript(spell_hun_scatter_shot);
RegisterSpellScript(spell_hun_scouts_instincts);
RegisterSpellScript(spell_hun_scrappy);
RegisterSpellScript(spell_hun_shrapnel_shot);
RegisterSpellScript(spell_hun_steady_shot);
RegisterSpellScript(spell_hun_streamline);
RegisterSpellScript(spell_hun_surging_shots);
RegisterSpellScript(spell_hun_tame_beast);
RegisterAreaTriggerAI(areatrigger_hun_tar_trap);
RegisterAreaTriggerAI(areatrigger_hun_tar_trap_activate);
RegisterSpellScript(spell_hun_t9_4p_bonus);
RegisterSpellScript(spell_hun_t29_2p_marksmanship_bonus);
RegisterSpellScript(spell_hun_wilderness_medicine);
}