-- Hunter Beast Mastery
-- May 2018
local addon , ns = ...
local Hekili = _G [ addon ]
local class = Hekili.Class
local state = Hekili.State
local PTR = ns.PTR
-- Shadowlands
-- Legendaries
-- [x] Call of the Wild
-- [-] Nessingwary's Trapping Apparatus (leave as reactive)
-- [x] Soulforge Embers
-- [x] Craven Strategem
-- [-] Dire Command (passive/reactive)
-- [x] Flamewaker's Cobra Sting
-- [x] Qa'pla, Eredun War Order
-- [-] Rylakstalker's Piercing Fangs (passive/reactive)
-- Conduits
-- [x] Bloodletting
-- [-] Echoing Call
-- [x] Ferocious Appetite
-- [-] One with the Beast
-- Covenants
-- [-] Enfeebled Mark
-- [-] Empowered Release
-- [x] Necrotic Barrage
-- [x] Spirit Attunement
-- Endurance
-- [x] Harmony of the Tortollan
-- [-] Markman's Advantage (sp)
-- [x] Rejuvenating Wind
-- [-] Resilience of the Hunter
-- Finesse
-- [x] cheetahs_vigor
-- [x] reversal_of_fortune
-- [x] tactical_retreat
-- needed for Frenzy.
local FindUnitBuffByID , FindUnitDebuffByID = ns.FindUnitBuffByID , ns.FindUnitDebuffByID
if UnitClassBase ( " player " ) == " HUNTER " then
local spec = Hekili : NewSpecialization ( 253 , true )
spec : RegisterResource ( Enum.PowerType . Focus , {
aspect_of_the_wild = {
resource = " focus " ,
aura = " aspect_of_the_wild " ,
last = function ( )
local app = state.buff . aspect_of_the_wild.applied
local t = state.query_time
return app + floor ( t - app )
end ,
interval = 1 ,
value = 5 ,
} ,
barbed_shot = {
resource = " focus " ,
aura = " barbed_shot " ,
last = function ( )
local app = state.buff . barbed_shot.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_2 = {
resource = " focus " ,
aura = " barbed_shot_2 " ,
last = function ( )
local app = state.buff . barbed_shot_2.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_3 = {
resource = " focus " ,
aura = " barbed_shot_3 " ,
last = function ( )
local app = state.buff . barbed_shot_3.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_4 = {
resource = " focus " ,
aura = " barbed_shot_4 " ,
last = function ( )
local app = state.buff . barbed_shot_4.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_5 = {
resource = " focus " ,
aura = " barbed_shot_5 " ,
last = function ( )
local app = state.buff . barbed_shot_5.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_6 = {
resource = " focus " ,
aura = " barbed_shot_6 " ,
last = function ( )
local app = state.buff . barbed_shot_6.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_7 = {
resource = " focus " ,
aura = " barbed_shot_7 " ,
last = function ( )
local app = state.buff . barbed_shot_7.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
barbed_shot_8 = {
resource = " focus " ,
aura = " barbed_shot_8 " ,
last = function ( )
local app = state.buff . barbed_shot_8.applied
local t = state.query_time
return app + floor ( ( t - app ) / 2 ) * 2
end ,
interval = 2 ,
value = 5 ,
} ,
death_chakram = {
resource = " focus " ,
aura = " death_chakram " ,
last = function ( )
return state.buff . death_chakram.applied + floor ( ( state.query_time - state.buff . death_chakram.applied ) / class.auras . death_chakram.tick_time ) * class.auras . death_chakram.tick_time
end ,
interval = function ( ) return class.auras . death_chakram.tick_time end ,
value = function ( ) return state.conduit . necrotic_barrage.enabled and 5 or 3 end ,
}
} )
-- Talents
spec : RegisterTalents ( {
killer_instinct = 22291 , -- 273887
animal_companion = 22280 , -- 267116
dire_beast = 22282 , -- 120679
scent_of_blood = 22500 , -- 193532
one_with_the_pack = 22266 , -- 199528
chimaera_shot = 22290 , -- 53209
trailblazer = 19347 , -- 199921
natural_mending = 19348 , -- 270581
camouflage = 23100 , -- 199483
spitting_cobra = 22441 , -- 257891
thrill_of_the_hunt = 22347 , -- 257944
a_murder_of_crows = 22269 , -- 131894
born_to_be_wild = 22268 , -- 266921
posthaste = 22276 , -- 109215
binding_shot = 22499 , -- 109248
stomp = 19357 , -- 199530
barrage = 22002 , -- 120360
stampede = 23044 , -- 201430
aspect_of_the_beast = 22273 , -- 191384
killer_cobra = 21986 , -- 199532
bloodshed = 22295 , -- 321530
} )
-- PvP Talents
spec : RegisterPvpTalents ( {
dire_beast_basilisk = 825 , -- 205691
dire_beast_hawk = 824 , -- 208652
dragonscale_armor = 3600 , -- 202589
hiexplosive_trap = 3605 , -- 236776
hunting_pack = 3730 , -- 203235
interlope = 1214 , -- 248518
roar_of_sacrifice = 3612 , -- 53480
scorpid_sting = 3604 , -- 202900
spider_sting = 3603 , -- 202914
survival_tactics = 3599 , -- 202746
the_beast_within = 693 , -- 212668
viper_sting = 3602 , -- 202797
wild_protector = 821 , -- 204190
} )
local tar_trap_targets = { }
-- Auras
spec : RegisterAuras ( {
a_murder_of_crows = {
id = 131894 ,
duration = 15 ,
max_stack = 1 ,
} ,
aspect_of_the_cheetah = {
id = 186258 ,
duration = function ( ) return conduit.cheetahs_vigor . enabled and 12 or 9 end ,
max_stack = 1 ,
} ,
aspect_of_the_cheetah_sprint = {
id = 186257 ,
duration = 3 ,
max_stack = 1 ,
} ,
aspect_of_the_turtle = {
id = 186265 ,
duration = 8 ,
max_stack = 1 ,
} ,
aspect_of_the_wild = {
id = 193530 ,
duration = 20 ,
max_stack = 1 ,
} ,
barbed_shot = {
id = 246152 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_2 = {
id = 246851 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_3 = {
id = 246852 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_4 = {
id = 246853 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_5 = {
id = 246854 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_6 = {
id = 284255 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_7 = {
id = 284257 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_8 = {
id = 284258 ,
duration = 8 ,
max_stack = 1 ,
} ,
barbed_shot_dot = {
id = 217200 ,
duration = 8 ,
max_stack = 1 ,
} ,
barrage = {
id = 120360 ,
} ,
beast_cleave = {
id = 118455 ,
duration = 4 ,
max_stack = 1 ,
generate = function ( )
local bc = buff.beast_cleave
local name , _ , count , _ , duration , expires , caster = FindUnitBuffByID ( " pet " , 118455 )
if name then
bc.name = name
bc.count = 1
bc.expires = expires
bc.applied = expires - duration
bc.caster = caster
return
end
bc.count = 0
bc.expires = 0
bc.applied = 0
bc.caster = " nobody "
end ,
} ,
bestial_wrath = {
id = 19574 ,
duration = 15 ,
max_stack = 1 ,
} ,
binding_shot = {
id = 117405 ,
duration = 3600 ,
max_stack = 1 ,
} ,
bloodshed = {
id = 321538 ,
duration = 18 ,
max_stack = 1 ,
generate = function ( t )
local name , count , duration , expires , caster , _
for i = 1 , 40 do
name , _ , count , _ , duration , expires , caster = UnitDebuff ( " target " , 321538 )
if not name then break end
if name and UnitIsUnit ( caster , " pet " ) then break end
end
if name then
t.name = name
t.count = count
t.expires = expires
t.applied = expires - duration
t.caster = " player "
return
end
t.count = 0
t.expires = 0
t.applied = 0
t.caster = " nobody "
end ,
} ,
camouflage = {
id = 199483 ,
duration = 60 ,
max_stack = 1 ,
} ,
concussive_shot = {
id = 5116 ,
duration = 6 ,
max_stack = 1 ,
} ,
dire_beast = {
id = 281036 ,
duration = 8 ,
max_stack = 1 ,
} ,
dire_beast_basilisk = {
id = 209967 ,
duration = 30 ,
max_stack = 1 ,
} ,
dire_beast_hawk = {
id = 208684 ,
duration = 3600 ,
max_stack = 1 ,
} ,
eagle_eye = {
id = 6197 ,
duration = 60 ,
} ,
exotic_beasts = {
id = 53270 ,
} ,
feign_death = {
id = 5384 ,
duration = 360 ,
max_stack = 1 ,
} ,
freezing_trap = {
id = 3355 ,
duration = 60 ,
type = " Magic " ,
max_stack = 1 ,
} ,
frenzy = {
id = 272790 ,
duration = function ( ) return azerite.feeding_frenzy . enabled and 9 or 8 end ,
max_stack = 3 ,
generate = function ( )
local fr = buff.frenzy
local name , _ , count , _ , duration , expires , caster = FindUnitBuffByID ( " pet " , 272790 )
if name then
fr.name = name
fr.count = count
fr.expires = expires
fr.applied = expires - duration
fr.caster = caster
return
end
fr.count = 0
fr.expires = 0
fr.applied = 0
fr.caster = " nobody "
end ,
} ,
growl = {
id = 2649 ,
duration = 3 ,
max_stack = 1 ,
} ,
hunters_mark = {
id = 257284 ,
duration = 3600 ,
type = " Magic " ,
max_stack = 1 ,
} ,
intimidation = {
id = 24394 ,
duration = 5 ,
max_stack = 1 ,
} ,
kindred_spirits = {
id = 56315 ,
} ,
masters_call = {
id = 54216 ,
duration = 4 ,
type = " Magic " ,
max_stack = 1 ,
} ,
misdirection = {
id = 35079 ,
duration = 8 ,
max_stack = 1 ,
} ,
parsels_tongue = {
id = 248085 ,
duration = 8 ,
max_stack = 4 ,
} ,
posthaste = {
id = 118922 ,
duration = 4 ,
max_stack = 1 ,
} ,
predators_thirst = {
id = 264663 ,
duration = 3600 ,
max_stack = 1 ,
} ,
spitting_cobra = {
id = 194407 ,
duration = 20 ,
max_stack = 1 ,
} ,
stampede = {
id = 201430 ,
} ,
tar_trap = {
id = 135299 ,
duration = 30 ,
max_stack = 1 ,
} ,
thrill_of_the_hunt = {
id = 257946 ,
duration = 8 ,
max_stack = 3 ,
} ,
trailblazer = {
id = 231390 ,
duration = 3600 ,
max_stack = 1 ,
} ,
wild_call = {
id = 185789 ,
} ,
-- PvP Talents
hiexplosive_trap = {
id = 236777 ,
duration = 0.1 ,
max_stack = 1 ,
} ,
interlope = {
id = 248518 ,
duration = 45 ,
max_stack = 1 ,
} ,
roar_of_sacrifice = {
id = 53480 ,
duration = 12 ,
max_stack = 1 ,
} ,
scorpid_sting = {
id = 202900 ,
duration = 8 ,
type = " Poison " ,
max_stack = 1 ,
} ,
spider_sting = {
id = 202914 ,
duration = 4 ,
type = " Poison " ,
max_stack = 1 ,
} ,
the_beast_within = {
id = 212704 ,
duration = 15 ,
max_stack = 1 ,
} ,
viper_sting = {
id = 202797 ,
duration = 6 ,
type = " Poison " ,
max_stack = 1 ,
} ,
wild_protector = {
id = 204205 ,
duration = 3600 ,
max_stack = 1 ,
} ,
-- Azerite Powers
dance_of_death = {
id = 274443 ,
duration = 8 ,
max_stack = 1
} ,
primal_instincts = {
id = 279810 ,
duration = 20 ,
max_stack = 1
} ,
-- Utility
mend_pet = {
id = 136 ,
duration = 10 ,
max_stack = 1
} ,
-- Conduits
resilience_of_the_hunter = {
id = 339461 ,
duration = 8 ,
max_stack = 1
} ,
-- Legendaries
nessingwarys_trapping_apparatus = {
id = 336744 ,
duration = 5 ,
max_stack = 1 ,
copy = { " nesingwarys_trapping_apparatus " , " nesingwarys_apparatus " , " nessingwarys_apparatus " }
}
} )
spec : RegisterStateExpr ( " barbed_shot_grace_period " , function ( )
return ( settings.barbed_shot_grace_period or 0 ) * gcd.max
end )
spec : RegisterHook ( " spend " , function ( amt , resource )
if amt < 0 and resource == " focus " and buff.nessingwarys_trapping_apparatus . up then
amt = amt * 2
end
return amt , resource
end )
local ExpireNesingwarysTrappingApparatus = setfenv ( function ( )
focus.regen = focus.regen * 0.5
forecastResources ( " focus " )
end , state )
spec : RegisterHook ( " reset_precast " , function ( )
if debuff.tar_trap . up then
debuff.tar_trap . expires = debuff.tar_trap . applied + 30
end
if buff.nesingwarys_apparatus . up then
state : QueueAuraExpiration ( " nesingwarys_apparatus " , ExpireNesingwarysTrappingApparatus , buff.nesingwarys_apparatus . expires )
end
if now - action.resonating_arrow . lastCast < 6 then applyBuff ( " resonating_arrow " , 10 - ( now - action.resonating_arrow . lastCast ) ) end
end )
local trapUnits = { " target " , " focus " }
local trappableClassifications = {
rare = true ,
elite = true ,
normal = true ,
trivial = true ,
minus = true
}
for i = 1 , 5 do
trapUnits [ # trapUnits + 1 ] = " boss " .. i
end
for i = 1 , 40 do
trapUnits [ # trapUnits + 1 ] = " nameplate " .. i
end
spec : RegisterHook ( " COMBAT_LOG_EVENT_UNFILTERED " , function ( _ , subtype , _ , sourceGUID , sourceName , _ , _ , destGUID , destName , destFlags , _ , spellID , spellName )
if subtype == " SPELL_CAST_SUCCESS " and sourceGUID == GUID and spellID == 187698 and legendary.soulforge_embers . enabled then
-- Capture all boss/elite targets present at this time as valid trapped targets.
table.wipe ( tar_trap_targets )
for _ , unit in ipairs ( trapUnits ) do
if UnitExists ( unit ) and UnitCanAttack ( " player " , unit ) and not trappableClassifications [ UnitClassification ( unit ) ] then
tar_trap_targets [ UnitGUID ( unit ) ] = true
end
end
end
end , false )
-- Tier 28
spec : RegisterGear ( " tier28 " , 188861 , 188860 , 188859 , 188858 , 188856 )
spec : RegisterSetBonuses ( " tier28_2pc " , 364492 , " tier28_4pc " , 363665 )
-- 2-Set - Killing Frenzy - Your Kill Command critical strike chance is increased by 15% for each stack of Frenzy your pet has.
-- 4-Set - Killing Frenzy - Kill Command critical hits increase the damage and cooldown reduction of your next Cobra Shot by 40%.
spec : RegisterAura ( " killing_frenzy " , {
id = 363760 ,
duration = 8 ,
max_stack = 1
} )
-- Abilities
spec : RegisterAbilities ( {
a_murder_of_crows = {
id = 131894 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
spend = 30 ,
spendType = " focus " ,
talent = " a_murder_of_crows " ,
startsCombat = true ,
texture = 645217 ,
handler = function ( )
applyDebuff ( " target " , " a_murder_of_crows " )
end ,
} ,
arcane_shot = {
id = 185358 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = 40 ,
spendType = " focus " ,
startsCombat = true ,
texture = 132218 ,
handler = function ( )
end ,
} ,
aspect_of_the_cheetah = {
id = 186257 ,
cast = 0 ,
cooldown = function ( ) return ( ( pvptalent.hunting_pack . enabled and 0.5 or 1 ) * ( legendary.call_of_the_wild . enabled and 0.75 or 1 ) * 180 ) + ( conduit.cheetahs_vigor . mod * 0.001 ) end ,
gcd = " spell " ,
startsCombat = false ,
texture = 132242 ,
handler = function ( )
applyBuff ( " aspect_of_the_cheetah " )
applyBuff ( " aspect_of_the_cheetah_sprint " )
end ,
} ,
aspect_of_the_turtle = {
id = 186265 ,
cast = 8 ,
cooldown = function ( ) return ( ( legendary.call_of_the_wild . enabled and 0.75 or 1 ) * 180 ) + ( conduit.harmony_of_the_tortollan . mod * 0.001 ) end ,
gcd = " spell " ,
channeled = true ,
startsCombat = false ,
texture = 132199 ,
start = function ( )
applyBuff ( " aspect_of_the_turtle " )
end ,
} ,
aspect_of_the_wild = {
id = 193530 ,
cast = 0 ,
cooldown = function ( ) return ( essence.vision_of_perfection . enabled and 0.87 or 1 ) * ( legendary.call_of_the_wild . enabled and 0.75 or 1 ) * 120 end ,
gcd = " off " ,
toggle = " cooldowns " ,
startsCombat = false ,
texture = 136074 ,
nobuff = function ( )
if settings.aspect_vop_overlap then return end
return " aspect_of_the_wild "
end ,
handler = function ( )
applyBuff ( " aspect_of_the_wild " )
if azerite.primal_instincts . enabled then gainCharges ( " barbed_shot " , 1 ) end
end ,
} ,
barbed_shot = {
id = 217200 ,
cast = 0 ,
charges = 2 ,
cooldown = function ( ) return ( conduit.bloodletting . enabled and 11 or 12 ) * haste end ,
recharge = function ( ) return ( conduit.bloodletting . enabled and 11 or 12 ) * haste end ,
gcd = " spell " ,
velocity = 50 ,
startsCombat = true ,
texture = 2058007 ,
cycle = " barbed_shot " ,
handler = function ( )
if buff.barbed_shot . down then applyBuff ( " barbed_shot " )
else
for i = 2 , 8 do
if buff [ " barbed_shot_ " .. i ] . down then applyBuff ( " barbed_shot_ " .. i ) ; break end
end
end
addStack ( " frenzy " , 8 , 1 )
if level > 33 then
setCooldown ( " bestial_wrath " , cooldown.bestial_wrath . remains - 12 )
end
applyDebuff ( " target " , " barbed_shot_dot " )
if legendary.qapla_eredun_war_order . enabled then
setCooldown ( " kill_command " , 0 )
end
end ,
} ,
barrage = {
id = 120360 ,
cast = function ( ) return 3 * haste end ,
cooldown = 20 ,
gcd = " spell " ,
channeled = true ,
spend = 60 ,
spendType = " focus " ,
startsCombat = true ,
texture = 236201 ,
start = function ( )
end ,
} ,
bestial_wrath = {
id = 19574 ,
cast = 0 ,
cooldown = 90 ,
gcd = " spell " ,
startsCombat = true ,
texture = 132127 ,
nobuff = function ( ) return settings.avoid_bw_overlap and " bestial_wrath " or nil , " avoid_bw_overlap is checked and bestial_wrath is up " end ,
handler = function ( )
applyBuff ( " bestial_wrath " )
if pvptalent.the_beast_within . enabled then applyBuff ( " the_beast_within " ) end
if talent.scent_of_blood . enabled then gainCharges ( " barbed_shot " , 2 ) end
end ,
} ,
binding_shot = {
id = 109248 ,
cast = 0 ,
cooldown = 45 ,
gcd = " spell " ,
talent = " binding_shot " ,
startsCombat = true ,
texture = 462650 ,
handler = function ( )
applyDebuff ( " target " , " binding_shot " )
end ,
} ,
bloodshed = {
id = 321530 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
toggle = " cooldowns " ,
startsCombat = true ,
texture = 132139 ,
handler = function ( )
applyDebuff ( " target " , " bloodshed " )
end ,
} ,
camouflage = {
id = 199483 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
startsCombat = false ,
texture = 461113 ,
handler = function ( )
applyBuff ( " camouflage " )
end ,
} ,
chimaera_shot = {
id = 53209 ,
cast = 0 ,
cooldown = 15 ,
gcd = " spell " ,
velocity = 50 ,
talent = " chimaera_shot " ,
startsCombat = true ,
texture = 236176 ,
handler = function ( )
gain ( 10 * min ( 2 , active_enemies ) , " focus " )
end ,
} ,
cobra_shot = {
id = 193455 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
velocity = 45 ,
spend = 35 ,
spendType = " focus " ,
startsCombat = true ,
texture = 461114 ,
handler = function ( )
if talent.killer_cobra . enabled and buff.bestial_wrath . up then setCooldown ( " kill_command " , 0 )
else
setCooldown ( " kill_command " , cooldown.kill_command . remains - ( buff.killing_frenzy . up and 1.4 or 1 ) )
removeBuff ( " killing_frenzy " )
end
end ,
} ,
concussive_shot = {
id = 5116 ,
cast = 0 ,
cooldown = 5 ,
gcd = " spell " ,
velocity = 50 ,
startsCombat = true ,
texture = 135860 ,
handler = function ( )
applyDebuff ( " target " , " concussive_shot " )
end ,
} ,
counter_shot = {
id = 147362 ,
cast = 0 ,
cooldown = 24 ,
gcd = " off " ,
toggle = " interrupts " ,
startsCombat = true ,
texture = 249170 ,
debuff = " casting " ,
readyTime = state.timeToInterrupt ,
handler = function ( )
if conduit.reversal_of_fortune . enabled then
gain ( conduit.reversal_of_fortune . mod , " focus " )
end
interrupt ( )
end ,
} ,
dire_beast = {
id = 120679 ,
cast = 0 ,
cooldown = 15 ,
gcd = " spell " ,
spend = 25 ,
spendType = " focus " ,
startsCombat = true ,
texture = 236186 ,
handler = function ( )
summonPet ( " dire_beast " , 8 )
end ,
} ,
dire_beast_basilisk = {
id = 205691 ,
cast = 0 ,
cooldown = 120 ,
gcd = " spell " ,
spend = 60 ,
spendType = " focus " ,
toggle = " cooldowns " ,
pvptalent = " dire_beast_basilisk " ,
startsCombat = true ,
texture = 1412204 ,
handler = function ( )
applyDebuff ( " target " , " dire_beast_basilisk " )
end ,
} ,
dire_beast_hawk = {
id = 208652 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
spend = 30 ,
spendType = " focus " ,
pvptalent = " dire_beast_hawk " ,
startsCombat = true ,
texture = 612363 ,
handler = function ( )
applyDebuff ( " target " , " dire_beast_hawk " )
end ,
} ,
disengage = {
id = 781 ,
cast = 0 ,
charges = 1 ,
cooldown = 20 ,
recharge = 20 ,
gcd = " off " ,
startsCombat = false ,
texture = 132294 ,
handler = function ( )
if talent.posthaste . enabled then applyBuff ( " posthaste " ) end
if conduit.tactical_retreat . enabled and target.within8 then applyDebuff ( " target " , " tactical_retreat " ) end
end ,
auras = {
-- Conduits
tactical_retreat = {
id = 339654 ,
duration = 3 ,
max_stack = 1
}
}
} ,
eagle_eye = {
id = 6197 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
startsCombat = false ,
texture = 132172 ,
handler = function ( )
applyBuff ( " eagle_eye " , 60 )
end ,
} ,
exhilaration = {
id = 109304 ,
cast = 0 ,
cooldown = 120 ,
gcd = " spell " ,
startsCombat = false ,
texture = 461117 ,
handler = function ( )
gain ( 0.3 * health.max , " health " )
if conduit.rejuvenating_wind . enabled then applyBuff ( " rejuvenating_wind " ) end
end ,
auras = {
-- Conduit
rejuvenating_wind = {
id = 339400 ,
duration = 8 ,
max_stack = 1
}
}
} ,
feign_death = {
id = 5384 ,
cast = 0 ,
cooldown = function ( ) return legendary.craven_stategem . enabled and 15 or 30 end ,
gcd = " spell " ,
startsCombat = false ,
texture = 132293 ,
handler = function ( )
applyBuff ( " feign_death " )
if legendary.craven_strategem . enabled then
removeDebuff ( " player " , " dispellable_curse " )
removeDebuff ( " player " , " dispellable_disease " )
removeDebuff ( " player " , " dispellable_magic " )
removeDebuff ( " player " , " dispellable_poison " )
end
end ,
} ,
flare = {
id = 1543 ,
cast = 0 ,
cooldown = 20 ,
gcd = " spell " ,
startsCombat = true ,
texture = 135815 ,
handler = function ( )
if legendary.soulforge_embers . enabled and debuff.tar_trap . up then
applyDebuff ( " target " , " soulforge_embers " )
active_dot.soulforge_embers = max ( 1 , min ( 5 , active_dot.tar_trap ) )
end
end ,
auras = {
soulforge_embers = {
id = 336746 ,
duration = 12 ,
max_stack = 1
}
}
} ,
freezing_trap = {
id = 187650 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
spend = function ( )
if legendary.nessingwarys_trapping_apparatus . enabled then
return - 45 , " focus "
end
end ,
startsCombat = true ,
texture = 135834 ,
handler = function ( )
applyDebuff ( " target " , " freezing_trap " )
end ,
} ,
hiexplosive_trap = {
id = 236776 ,
cast = 0 ,
cooldown = 40 ,
gcd = " spell " ,
spend = function ( )
if legendary.nessingwarys_trapping_apparatus . enabled then
return - 45 , " focus "
end
end ,
pvptalent = " hiexplosive_trap " ,
startsCombat = false ,
texture = 135826 ,
handler = function ( )
end ,
} ,
hunters_mark = {
id = 257284 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
startsCombat = true ,
texture = 236188 ,
handler = function ( )
applyDebuff ( " target " , " hunters_mark " )
end ,
} ,
interlope = {
id = 248518 ,
cast = 0 ,
cooldown = 45 ,
gcd = " spell " ,
pvptalent = " interlope " ,
startsCombat = false ,
texture = 132180 ,
handler = function ( )
end ,
} ,
intimidation = {
id = 19577 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
startsCombat = true ,
texture = 132111 ,
handler = function ( )
applyDebuff ( " target " , " intimidation " )
end ,
} ,
kill_command = {
id = 34026 ,
cast = 0 ,
cooldown = function ( ) return 7.5 * haste end ,
gcd = " spell " ,
spend = function ( ) return buff.flamewakers_cobra_sting . up and 0 or 30 end ,
spendType = " focus " ,
startsCombat = true ,
texture = 132176 ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return true
end ,
disabled = function ( )
if settings.check_pet_range and Hekili : PetBasedTargetDetectionIsReady ( true ) and not Hekili : TargetIsNearPet ( " target " ) then return true , " not in-range of pet " end
end ,
handler = function ( )
removeBuff ( " flamewakers_cobra_sting " )
if conduit.ferocious_appetite . enabled and stat.crit >= 100 then
reduceCooldown ( " aspect_of_the_wild " , conduit.ferocious_appetite . mod / 10 )
end
if set_bonus.tier28_4pc > 0 and stat.crit + ( buff.frenzy . stack * 0.15 ) >= 100 then
applyBuff ( " killing_frenzy " )
end
end ,
auras = {
flamewakers_cobra_sting = {
id = 336826 ,
duration = 15 ,
max_stack = 1 ,
}
}
} ,
kill_shot = {
id = 53351 ,
cast = 0 ,
charges = 1 ,
cooldown = 10 ,
recharge = 10 ,
gcd = " spell " ,
spend = function ( ) return buff.flayers_mark . up and 0 or 10 end ,
spendType = " focus " ,
startsCombat = true ,
texture = 236174 ,
usable = function ( ) return buff.flayers_mark . up or target.health_pct < 20 end ,
handler = function ( )
if buff.flayers_mark . up and legendary.pouch_of_razor_fragments . enabled then
applyDebuff ( " target " , " pouch_of_razor_fragments " )
removeBuff ( " flayers_mark " )
end
end ,
} ,
masters_call = {
id = 272682 ,
cast = 0 ,
cooldown = 45 ,
gcd = " spell " ,
startsCombat = true ,
texture = 236189 ,
handler = function ( )
end ,
} ,
misdirection = {
id = 34477 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
nopvptalent = " interlope " ,
startsCombat = true ,
texture = 132180 ,
handler = function ( )
end ,
} ,
multishot = {
id = 2643 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = 40 ,
spendType = " focus " ,
startsCombat = true ,
texture = 132330 ,
velocity = 40 ,
handler = function ( )
applyBuff ( " beast_cleave " )
end ,
} ,
primal_rage = {
id = 272678 ,
cast = 0 ,
cooldown = 360 ,
gcd = " spell " ,
toggle = " cooldowns " ,
startsCombat = true ,
texture = 136224 ,
usable = function ( ) return pet.alive and pet.ferocity , " requires a living ferocity pet " end ,
handler = function ( )
applyBuff ( " primal_rage " )
applyBuff ( " bloodlust " )
stat.haste = stat.haste + 0.4
applyDebuff ( " player " , " exhaustion " )
end ,
} ,
roar_of_sacrifice = {
id = 53480 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
pvptalent = " roar_of_sacrifice " ,
startsCombat = false ,
texture = 464604 ,
handler = function ( )
applyBuff ( " roar_of_sacrifice " )
end ,
} ,
scorpid_sting = {
id = 202900 ,
cast = 0 ,
cooldown = 24 ,
gcd = " spell " ,
pvptalent = " scorpid_sting " ,
startsCombat = true ,
texture = 132169 ,
handler = function ( )
applyDebuff ( " target " , " scorpid_sting " )
setCooldown ( " spider_sting " , max ( 8 , cooldown.spider_sting . remains ) )
setCooldown ( " viper_sting " , max ( 8 , cooldown.viper_sting . remains ) )
end ,
} ,
spider_sting = {
id = 202914 ,
cast = 0 ,
cooldown = 45 ,
gcd = " spell " ,
pvptalent = " spider_sting " ,
startsCombat = true ,
texture = 1412206 ,
handler = function ( )
applyDebuff ( " target " , " spider_sting " )
setCooldown ( " scorpid_sting " , max ( 8 , cooldown.scorpid_sting . remains ) )
setCooldown ( " viper_sting " , max ( 8 , cooldown.viper_sting . remains ) )
end ,
} ,
spitting_cobra = {
id = 194407 ,
cast = 0 ,
cooldown = 90 ,
gcd = " spell " ,
talent = " spitting_cobra " ,
toggle = " cooldowns " ,
startsCombat = true ,
texture = 236177 ,
handler = function ( )
summonPet ( " spitting_cobra " , 20 )
applyBuff ( " spitting_cobra " , 20 )
end ,
} ,
stampede = {
id = 201430 ,
cast = 0 ,
cooldown = 120 ,
gcd = " spell " ,
toggle = " cooldowns " ,
talent = " stampede " ,
startsCombat = true ,
texture = 461112 ,
handler = function ( )
end ,
} ,
summon_pet = {
id = 883 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = 0 ,
spendType = " focus " ,
startsCombat = false ,
texture = ' Interface \\ ICONS \\ Ability_Hunter_BeastCall ' ,
essential = true ,
nomounted = true ,
usable = function ( ) return not pet.exists , " requires no active pet " end ,
handler = function ( )
summonPet ( " made_up_pet " , 3600 , " ferocity " )
end ,
} ,
tar_trap = {
id = 187698 ,
cast = 0 ,
cooldown = function ( ) return level > 55 and 25 or 30 end ,
gcd = " spell " ,
spend = function ( )
if legendary.nessingwarys_trapping_apparatus . enabled then
return - 45 , " focus "
end
end ,
startsCombat = false ,
texture = 576309 ,
-- Let's not recommend Tar Trap if Flare is on CD.
timeToReady = function ( ) return max ( 0 , cooldown.flare . remains - gcd.max ) end ,
handler = function ( )
applyDebuff ( " target " , " tar_trap " )
end ,
} ,
tranquilizing_shot = {
id = 19801 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
startsCombat = true ,
texture = 136020 ,
toggle = " interrupts " ,
usable = function ( ) return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic effect " end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
if level > 53 then gain ( 10 , " focus " ) end
end ,
} ,
viper_sting = {
id = 202797 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
pvptalent = " viper_sting " ,
startsCombat = true ,
texture = 236200 ,
handler = function ( )
applyDebuff ( " target " , " spider_sting " )
setCooldown ( " scorpid_sting " , max ( 8 , cooldown.scorpid_sting . remains ) )
setCooldown ( " viper_sting " , max ( 8 , cooldown.viper_sting . remains ) )
end ,
} ,
--[[ wartime_ability = {
id = 264739 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
startsCombat = true ,
texture = 1518639 ,
handler = function ( )
end ,
} , ] ]
--[[ Pet Abilities
-- Moths
serenity_dust = {
id = 264055 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Sporebats
spore_cloud = {
id = 264056 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Water Striders
soothing_water = {
id = 264262 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Bats
sonic_blast = {
id = 264263 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Nether Rays
nether_shock = {
id = 264264 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Cranes
chijis_tranquility = {
id = 264028 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Spirit Beasts
spirit_shock = {
id = 264265 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} ,
-- Stags
natures_grace = {
id = 264266 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
toggle = " interrupts " ,
startsCombat = true ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return buff.dispellable_enrage . up or buff.dispellable_magic . up , " requires enrage or magic debuff "
end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
end ,
} , ] ]
-- Utility
mend_pet = {
id = 136 ,
cast = 0 ,
cooldown = 10 ,
gcd = " spell " ,
startsCombat = false ,
usable = function ( )
if not pet.alive then return false , " requires a living pet " end
return true
end ,
} ,
-- Hunter - Kyrian - 308491 - resonating_arrow (Resonating Arrow)
resonating_arrow = {
id = 308491 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
startsCombat = true ,
texture = 3565445 ,
handler = function ( )
applyDebuff ( " target " , " resonating_arrow " )
active_dot.resonating_arrow = active_enemies
applyBuff ( " resonating_arrow " )
if legendary.pact_of_the_soulstalkers . enabled then applyBuff ( " pact_of_the_soulstalkers " ) end
end ,
toggle = " essences " ,
auras = {
resonating_arrow = {
id = 308498 ,
duration = 10 ,
max_stack = 1 ,
} ,
pact_of_the_soulstalkers = {
id = 356263 ,
duration = 10 ,
max_stack = 1 ,
}
}
} ,
-- Hunter - Necrolord - 325028 - death_chakram (Death Chakram)
death_chakram = {
id = 325028 ,
cast = 0 ,
cooldown = 45 ,
gcd = " spell " ,
startsCombat = true ,
texture = 3578207 ,
toggle = " essences " ,
handler = function ( )
applyBuff ( " death_chakram " )
if soulbind.kevins_oozeling . enabled then applyBuff ( " kevins_oozeling " ) end
end ,
auras = {
death_chakram = {
duration = 3.5 ,
tick_time = 0.5 ,
max_stack = 1 ,
generate = function ( t , auraType )
local cast = action.death_chakram . lastCast or 0
if cast + class.auras . death_chakram.duration >= query_time then
t.name = class.abilities . death_chakram.name
t.count = 1
t.applied = cast
t.expires = cast + duration
t.caster = " player "
return
end
t.count = 0
t.applied = 0
t.expires = 0
t.caster = " nobody "
end
}
}
} ,
-- Hunter - Night Fae - 328231 - wild_spirits (Wild Spirits)
wild_spirits = {
id = 328231 ,
cast = 0 ,
cooldown = 120 ,
gcd = " spell " ,
startsCombat = true ,
texture = 3636840 ,
spend = 0 ,
spendType = " focus " ,
toggle = " essences " ,
handler = function ( )
applyDebuff ( " target " , " wild_mark " )
applyBuff ( " wild_spirits " )
end ,
disabled = function ( )
return covenant.night_fae and not IsSpellKnownOrOverridesKnown ( 328231 ) , " you have not finished your night_fae covenant intro "
end ,
auras = {
wild_mark = {
id = 328275 ,
duration = function ( ) return conduit.spirit_attunement . enabled and 18 or 15 end ,
max_stack = 1
} ,
wild_spirits = {
duration = function ( ) return conduit.spirit_attunement . enabled and 18 or 15 end ,
max_stack = 1 ,
generate = function ( t )
local cast = action.wild_spirits . lastCast or 0
local up = cast + t.duration > state.query_time
t.name = t.name or class.abilities . wild_spirits.name
t.count = up and 1 or 0
t.expires = up and cast + t.duration or 0
t.applied = up and cast or 0
t.caster = " player "
end ,
}
}
} ,
-- Hunter - Venthyr - 324149 - flayed_shot (Flayed Shot)
flayed_shot = {
id = 324149 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
startsCombat = true ,
texture = 3565719 ,
toggle = " essences " ,
handler = function ( )
applyDebuff ( " target " , " flayed_shot " )
end ,
auras = {
flayed_shot = {
id = 324149 ,
duration = 20 ,
max_stack = 1 ,
} ,
flayers_mark = {
id = 324156 ,
duration = 12 ,
max_stack = 1
} ,
pouch_of_razor_fragments = {
id = 356620 ,
duration = 6 ,
max_stack = 1 ,
}
}
} ,
-- Wailing Arrow (Sylvanas Legendary)
wailing_arrow = {
id = 355589 ,
cast = 1.9 ,
cooldown = 60 ,
gcd = " spell " ,
spend = 15 ,
spendType = " focus " ,
toggle = " cooldowns " ,
startsCombat = true ,
handler = function ( )
interrupt ( )
applyDebuff ( " target " , " wailing_arrow " )
end ,
auras = {
wailing_arrow = {
id = 355589 ,
duration = 5 ,
max_stack = 1 ,
}
}
} ,
} )
spec : RegisterOptions ( {
enabled = true ,
potion = " spectral_agility " ,
buffPadding = 0 ,
nameplates = false ,
nameplateRange = 8 ,
aoe = 3 ,
damage = true ,
damageExpiration = 3 ,
package = " Beast Mastery " ,
} )
spec : RegisterSetting ( " barbed_shot_grace_period " , 0.5 , {
name = " |T2058007:0|t Barbed Shot Grace Period " ,
desc = " If set above zero, the addon (using the default priority or |cFFFFD100barbed_shot_grace_period|r expression) will recommend |T2058007:0|t Barbed Shot up to 1 global cooldown earlier. " ,
icon = 2058007 ,
iconCoords = { 0.1 , 0.9 , 0.1 , 0.9 } ,
type = " range " ,
min = 0 ,
max = 1 ,
step = 0.01 ,
width = " full "
} )
spec : RegisterSetting ( " avoid_bw_overlap " , false , {
name = " Avoid |T132127:0|t Bestial Wrath Overlap " ,
desc = " If checked, the addon will not recommend |T132127:0|t Bestial Wrath if the buff is already applied. " ,
type = " toggle " ,
width = " full "
} )
spec : RegisterSetting ( " check_pet_range " , true , {
name = " Check Pet Range for |T132176:0|t Kill Command " ,
desc = function ( )
return " If checked, the addon will not recommend |T132176:0|t Kill Command if your pet is not in range of your target. \n \n " ..
" Requires |c " .. ( state.settings . petbased and " FF00FF00 " or " FFFF0000 " ) .. " Pet-Based Target Detection "
end ,
type = " toggle " ,
width = " full "
} )
spec : RegisterPack ( " Beast Mastery " , 20220821 , [ [ Hekili : LZ1 ) ZTTTs ( ) w80PksXomM0rP19S0BETVB61m9Y9M6oZ7UFru0uqw8cfPkjvCChp8V9Bxa ( fqWfGuuYj59U2m2wIal2DX ( LpayjwyV43xC7kVm2I37CPJZLFVJTL912FV91lUn7XDSf3UZZ ) dE3d ) rK3w4N ) iZlnlF5 ) j8twYJ4JFmm2BfsM049j ( qt ( M8LBYY2L ( dV ( 13 hKTz ) Dw ( XBFDAW29HEzbXr ( jERZWp7 ) 6 f3E3 ( GWSFjAXD0SX0f36TpBtCYIBVny7pT42nbRwXenNL6RYp5l ) p2hb ) r ( 7 ( R7VFp ( aNlVa ) HJt ( 7 YF3pTXl6Ew6pK ) UxLV83yVIf5DxilF5p6LChBv ( YB3edD5Nt88HV8VZscIxzXB7 ) Wlimi6 ( YwSFhYRPwlUnminlff ( 4 SnSe34i39Pm4ZVNRyf0F1IFCXT ( jbaFf4Hs861w3XsZc8cDFiXlBJ1 ( DGy6J6Mf3c93fA620fzW ) ds5AV9HzvKSSz ( XCb1nfyi5bkd0GkdDzxYs8I ( dqDh8NGOu0rujMeSt0GFooFP3gMhOj8IGF87vDauhV ) V ) t5lzrSTbSuqL ( a8vRIJErg ( R8LzBcsZxUoojF5UqVhzjWNUJ57bst ( YGSxSc ) i0SyOTP782U9XIXaPJVhNojWihe ( yX4ITJ5hSoWh6kOYqTDTs8mGwEj3ZYScsDfJik6xPvR7h ) r47JYS ( WJWNJYxocg344WvXpez5HdvMB8Axyw09HGWvwjSTEbrPnBxclnocSHb1Nxss8d1T6PNYxEg2YbnkGVtwsGFgohxpd7fg6k ( GlAMjm2CfUHqZJ ( aldnsE ) B0mFBKanSxbImDieXFfNbERwTo2XpYClmBYxEd4lE4cBk6j8 ( VR3JY88L2h ( O4hY8 ( it41TlHbXSUZRTFx6 ( TBHEVJr61v2Q7IZYGN4UgTmx9aAWKf ) PGiL ( CLCFwhYs3WJnQ0k15xK5GWDUzbiBBBnvYf3lXfCZ3jRDs2hXahZ7zwqa6q ( F5Y2Eh4IAvquH5BD7IyPPal ) GxYJPCYTJBXVBNheTAFv3OmBmWBnc51YxoKbEnP ( WprhK7cJHqVvS3iUZv3cIyYdTkngbUYJSzu4kNzW ( 5 QlRzCViFODjq7q7hQiSdM0RdsyCz1CWRXIqGwymd30DbWdsHKgTd7efC ) Mm31EmUoJ3hIOoyplFSAIO8Lt4pegY1CIjZ6ssxskl5dGzH1Q9j8S65lphsfu9bKZgxfKgsQecKFNFgpgWvtRy9Iz ( peegcXJGbcIU6Nvp1pH ) pSX3fNkchRWxa9SVs2mRK1O8D ( AwNI2bUR3N84xh603kPtRyTkF ( YhfIDm19 ) D ) Q73cdQsOl9zgmPh7GZCK4SDX8FZ97RYjs48hdHetXy2LD8JEaBapf ) RW9ScgQvc ( k2rl7YjvzIQhJ8DHVIier3maf2b9mvhMIgWJ0trjljgrjwlrQHNkKOG10YefHQG70TDa6suOACzHPmPqR6Xr5E ) Ei1LKgTtCB38x6faTccteq55vliMtEw1buzX7RqPrAuS6E2fbio6HonQpW0yrmwrSeRmBRnEPiizxCos4yr5vP0HsMrk0FPg0QPRv5J14TEMePD6jV0Up1Sd2hPhkPBLwjJwPVIvnYtsDVI ( 1 zXMpJMdQBXesUOwg6qTm6KXbN1Nznt8X4UyLxLVCkpPw94i5uj4cnpAEx0 ( 1 qQY2kZo5YtUY8Rk9GYCgL7TzPPH8soEtAjYn8Z8w9yt1k5WiuiZ1k1J0 ( KB6I0c9rjwrJ8OwHOySiM2ANOtHzPAWCCp6oDwkhkpRYSDo1yFjhAU ( zaZI7XBn3McflZONI ) 8 UyXbovOtAntOBAbZVtlMZ7IMZBrtvlE6KBptZlk ) JRteRJd3Qe3Sy3vbmtMLt6LaObfX4otamwjBxjR3P90CUrabkhkh8oPwxH9MqQiOfPthmOHNiyIKQP5uxqQLVNpaqfWP65 ) h7dsyRCZGqVP7tyfma12NkTgUYE9Gxu9Q ( O2m0stdnDBI8zeWzqBZB46yZwuDIrwD24eIrUV41B3hngh2DBC0LX3ZeidcUOwg6qT0zsUEZbhggz6yUMzLUsy3ZSPgWcrVGddC5jxz ( vLE4ZZs80JWGaJSb8hhlg5oYMFwx8OwH4Zcg5bBPCO8SwmY6MA ( 8 GrUJv40ngz9I ) HIrUVtfDIrMKqhjgz64sDIrMo52Z08YZbgzcbOhyKPta0lmYu2tdhJCpTo7bg5U3kVJdg0WteOdJSZx3yKDqmYFVcg5g1tZVZlkM0nX7dxLVKxkmErqsdETxKVKbJXUDyxHgLbd7fWVdIWAp6oOjvAc4BdJZak5LGuiSi1JNVOgGwXR7glTvquAM5tdxbxT0XDkWoxmL14CsvTzLN ) s8cw5Y ( iEcKERwLAX ( ewJuvgKQpUgNO6tQnsoV9ddeHelDyi6ox7KVCw5CBlF ( A ) en8K6xll12x3WMO9zoyUob4wzRtyr ) 5 JnooVIVQonjW ( 37 VIRcUJxLA8c3Y9ESg1C3XlrnHmW7ERdZgL7nym0u31jcM1luiawVriKvvvb0a ( z4MwkgSWvSexqLfkxJf1NkCn ) yU8f6UWneikkkEflzqcCHFKKD46qWnqTjevaJHcJItczgSAKlN47KHXd ( oI5IJSZ0whko ) 8 Yt3GnRNhh ( G9BogNMEsYMM91sPSXw1 ( fiPJFS04OPs47LBgwJcun66E55iZzSpX83NX4vEuzefPuwApa4AtSI0pIING9PDHXPywcK7AwPuCwGphhUpnZscvjf0cZizKkqQhefzQGdrLG9LdUoJWc4asd ( sA3 ) ZRf6oQ8kKZxVhMJsyccvOFP8m1Wkge ( R1gmXwF ( Q1X ( 7 fGB5vAwc7Ewb8y8bwB9 ( unvxXawXf48pK4TLt3ocjBOCk0id2sZGPzEB3XwXlOs7gf3NN729jy0uGY ( W0BQI9UD3fQu7QkYex91qszJzKpzPEv9T5Qt1kAOH6SBmn2tlr ) qUoH ( fxzQcckdLVqfkkJgAvqD0GxtZABM8 ) BmfAwIPODWBLDc93eS1JL4rLWX ( 7 ALwYpE7wa ( VAdvH8BSY ( RxjLHcAtUiz9UNh8jjW ) d8KQ2xlZxRGfL4Eh ( kpOWvo6tvmUiYiFHJ ( X4lfX5LbllcE ( YMw1YsFJLDkMRMlwavSsdfKUHfpnHeR2Qmhu9EoAikh ) rDvwYf5HfEb1q4 ( dVDHEUmy1C7JG1ZbHGXaXkz01p5ivAP ( X3vA8GQ8oEfpilSuTGXDkYLgTAFqwb4cwggSOtG3oDKt74Si9s89aKU72hkErbCooC ( Ch9dUsZjH37OpN5rmca0sg ) fKPAymMlPgnsdpQZfXRNOdysHwnlojbRAwrDRlEbemUy9oIFRpw5mbMaSrT29JzAJp ) s ( 7 RXHTixkR0 ) fzLV ( pcZrUI8ZP40KXL9Y5 ( xvfxdbRkMIBek8slNPsYbgYeT ( i0q0K4MgtrB3hMfugyOp ( h7I37Vbf7eV ) moXTst0yL5IjiX71L7wVKpyj ) gRvVgoIsjDiJj9QinU ( 5 ( e655ylg0Fg5dzpfKe7e2cITx8eTki9RU ( lA8f1nuO16F7i0YjyHQD1MI1v33fqthYWWIBpg9 ) 0 Ju93g9SEGfFj5tYf8PpmCxRR307aJU12RpYAF2EQfg2YNg7JO ( nrR5cB0TlAnxuJXL ) 0 yx50T ) Lnxmsx7PHH1KCyAjWDpbFf0nd6UiI4CPf5iiGvvsr ( AuwqVkVNDG0TwANZv9BPD62gBnrb1TxBNGfGqfmZa8yrQOsgbsjvhoUPhTYcRoU08NYvyOp9 ( rmcTxHH ( 08 gxHXvxEyRWamt ( iOQWhxCnlC51ymOKiGBaV3 ) XF93E ) V8 ( F ( hYxMV833GV4 ( B3fNKv8E9 ) IIJJm9fG ( LjoF08LPXywwV9zXB94NfPV4owWk ) D ) Aqe8O3cK7NIJGbM ) y8wCa61JrzO5W3c5pJZx ( R79YxUk4JbiVLVmgq37LHJ54xdY34PFAIoYvYuw2w ) 3 VqqSxiDK043n25n9O ) oe93PO ) VvQ ) F3PvC ( UbiogyNEjoc1r ( 76 y6U6DG ) WMVFJc
end