You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2071 lines
61 KiB
2071 lines
61 KiB
-- 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(13hKTz)Dw(XBFDAW29HEzbXr(jERZWp7)6f3E3(GWSFjAXD0SX0f36TpBtCYIBVny7pT42nbRwXenNL6RYp5l)p2hb)r(7(R7VFp(aNlVa)HJt(7YF3pTXl6Ew6pK)UxLV83yVIf5DxilF5p6LChBv(YB3edD5Nt88HV8VZscIxzXB7)Wlimi6(YwSFhYRPwlUnminlff(4SnSe34i39Pm4ZVNRyf0F1IFCXT(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(5QlRzCViFODjq7q7hQiSdM0RdsyCz1CWRXIqGwymd30DbWdsHKgTd7efC)Mm31EmUoJ3hIOoyplFSAIO8Lt4pegY1CIjZ6ssxskl5dGzH1Q9j8S65lphsfu9bKZgxfKgsQecKFNFgpgWvtRy9Iz(peegcXJGbcIU6Nvp1pH)pSX3fNkchRWxa9SVs2mRK1O8D(AwNI2bUR3N84xh603kPtRyTkF(YhfIDm19)D)Q73cdQsOl9zgmPh7GZCK4SDX8FZ97RYjs48hdHetXy2LD8JEaBapf)RW9ScgQvc(k2rl7YjvzIQhJ8DHVIier3maf2b9mvhMIgWJ0trjljgrjwlrQHNkKOG10YefHQG70TDa6suOACzHPmPqR6Xr5E)Ei1LKgTtCB38x6faTccteq55vliMtEw1buzX7RqPrAuS6E2fbio6HonQpW0yrmwrSeRmBRnEPiizxCos4yr5vP0HsMrk0FPg0QPRv5J14TEMePD6jV0Up1Sd2hPhkPBLwjJwPVIvnYtsDVI(1zXMpJMdQBXesUOwg6qTm6KXbN1Nznt8X4UyLxLVCkpPw94i5uj4cnpAEx0(1qQY2kZo5YtUY8Rk9GYCgL7TzPPH8soEtAjYn8Z8w9yt1k5WiuiZ1k1J0(KB6I0c9rjwrJ8OwHOySiM2ANOtHzPAWCCp6oDwkhkpRYSDo1yFjhAU(zaZI7XBn3McflZONI)8UyXbovOtAntOBAbZVtlMZ7IMZBrtvlE6KBptZlk)JRteRJd3Qe3Sy3vbmtMLt6LaObfX4otamwjBxjR3P90CUrabkhkh8oPwxH9MqQiOfPthmOHNiyIKQP5uxqQLVNpaqfWP65)h7dsyRCZGqVP7tyfma12NkTgUYE9Gxu9Q(O2m0stdnDBI8zeWzqBZB46yZwuDIrwD24eIrUV41B3hngh2DBC0LX3ZeidcUOwg6qT0zsUEZbhggz6yUMzLUsy3ZSPgWcrVGddC5jxz(vLE4ZZs80JWGaJSb8hhlg5oYMFwx8OwH4Zcg5bBPCO8SwmY6MA(8GrUJv40ngz9I)HIrUVtfDIrMKqhjgz64sDIrMo52Z08YZbgzcbOhyKPta0lmYu2tdhJCpTo7bg5U3kVJdg0WteOdJSZx3yKDqmYFVcg5g1tZVZlkM0nX7dxLVKxkmErqsdETxKVKbJXUDyxHgLbd7fWVdIWAp6oOjvAc4BdJZak5LGuiSi1JNVOgGwXR7glTvquAM5tdxbxT0XDkWoxmL14CsvTzLN)s8cw5Y(iEcKERwLAX(ewJuvgKQpUgNO6tQnsoV9ddeHelDyi6ox7KVCw5CBlF(A)en8K6xll12x3WMO9zoyUob4wzRtyr)5JnooVIVQonjW(37VIRcUJxLA8c3Y9ESg1C3XlrnHmW7ERdZgL7nym0u31jcM1luiawVriKvvvb0a(z4MwkgSWvSexqLfkxJf1NkCn)yU8f6UWneikkkEflzqcCHFKKD46qWnqTjevaJHcJItczgSAKlN47KHXd(oI5IJSZ0whko)8Yt3GnRNhh(G9BogNMEsYMM91sPSXw1(fiPJFS04OPs47LBgwJcun66E55iZzSpX83NX4vEuzefPuwApa4AtSI0pIING9PDHXPywcK7AwPuCwGphhUpnZscvjf0cZizKkqQhefzQGdrLG9LdUoJWc4asd(sA3)ZRf6oQ8kKZxVhMJsyccvOFP8m1Wkge(R1gmXwF(Q1X(7fGB5vAwc7Ewb8y8bwB9(unvxXawXf48pK4TLt3ocjBOCk0id2sZGPzEB3XwXlOs7gf3NN729jy0uGY(W0BQI9UD3fQu7QkYex91qszJzKpzPEv9T5Qt1kAOH6SBmn2tlr)qUoH(fxzQcckdLVqfkkJgAvqD0GxtZABM8)BmfAwIPODWBLDc93eS1JL4rLWX(7ALwYpE7wa(VAdvH8BSY(RxjLHcAtUiz9UNh8jjW)d8KQ2xlZxRGfL4Eh(kpOWvo6tvmUiYiFHJ(X4lfX5LbllcE(YMw1YsFJLDkMRMlwavSsdfKUHfpnHeR2Qmhu9EoAikh)rDvwYf5HfEb1q4(dVDHEUmy1C7JG1ZbHGXaXkz01p5ivAP(X3vA8GQ8oEfpilSuTGXDkYLgTAFqwb4cwggSOtG3oDKt74Si9s89aKU72hkErbCooC(Ch9dUsZjH37OpN5rmca0sg)fKPAymMlPgnsdpQZfXRNOdysHwnlojbRAwrDRlEbemUy9oIFRpw5mbMaSrT29JzAJp)s(7RXHTixkR0)fzLV(pcZrUI8ZP40KXL9Y5(xvfxdbRkMIBek8slNPsYbgYeT(i0q0K4MgtrB3hMfugyOp(h7I37Vbf7eV)moXTst0yL5IjiX71L7wVKpyj)gRvVgoIsjDiJj9QinU(5(e655ylg0Fg5dzpfKe7e2cITx8eTki9RU(lA8f1nuO16F7i0YjyHQD1MI1v33fqthYWWIBpg9)0Ju93g9SEGfFj5tYf8PpmCxRR307aJU12RpYAF2EQfg2YNg7JO(nrR5cB0TlAnxuJXL)0yx50T)Lnxmsx7PHH1KCyAjWDpbFf0nd6UiI4CPf5iiGvvsr(AuwqVkVNDG0TwANZv9BPD62gBnrb1TxBNGfGqfmZa8yrQOsgbsjvhoUPhTYcRoU08NYvyOp9(rmcTxHH(08gxHXvxEyRWamt(iOQWhxCnlC51ymOKiGBaV3)XF93E)V8(F(hYxMV833GV4(B3fNKv8E9)IIJJm9fG(LjoF08LPXywwV9zXB94NfPV4owWk)D)Aqe8O3cK7NIJGbM)y8wCa61JrzO5W3c5pJZx(R79YxUk4JbiVLVmgq37LHJ54xdY34PFAIoYvYuw2w)3VqqSxiDK043n25n9O)oe93PO)VvQ)F3PvC(UbiogyNEjoc1r(76y6U6DG)WMVFJchv7OuXrsFvP3b8ipyK)3)V(vGdTLeWbtUguzQQAsaARwhv85(2)EZfQcvNAD)vhO)1vhPOPQG7F)7uwspqthNtLwMMC7yOy8)yzzvsTI)ESJuVu1N9MjonMT0IY1dEsIU)6vfY9Y(YJCyDujqVvdnjJTczkrPurKQVOtnPZGNFp10RjzozgmD6vk2aP)fWZSF9AWk2NNea0Oq6n5Aqf1K)9Mk0m1qC31qjvLE)I30kCrp7M6ODmHhg8mZPMEnjZjBQo)D)cpAasLVRCfY5l53JzWJXBWN41b475)38n5l1D7QHpJ8gwdFq9TSg(Pd5MwRO9AUT1q6l43uRkWPZQVqMiE65ZETURIj6wxFjmr)8YvhEH8fD0mBRPxeSEw9mG6QtF6P6N1X6f1ifYB9a5GFg5gro6m9mLK(egb5luoyMaMCaJQEDBW9V9f52GtM3BFZ2vOrsACdXjmW(Bm4da355ZTXEmEFcY17Vdn1IYcc5Fx(YnqwsG)3NHgWL74iy2JBvh2HhIa7EuedwJsmREZJHVkTq6cJX(G(NROg2)goSw5l)fGerXONESGyPmXEXeWfXYs)L7cHeBlwvWpea65OIXg389ug2fO1Hm2dEpErXJsd2YhxCtwLg2Qe(b41A1JfUF1k1i2dRbBIvU4(Tg(rgQsrtO7cIwzP(WrJ57qgXvvZtp1zbWm3(YNEQ92wDJ9BN0Wcv52B7c8wizw5UsCH4(EBMnYNk1aZOkwq)DdYOozZNE6Sbq3ULa5RIVUBnSaXUBe8Bz1b(86TA)gNUjGaKObIm3woCmWuZAEnPjMfmDykZV6YgeaJ(wEDOnOExFZFHDFm1Xclpfwv4uJ0FcbJiRjLjJg3yNENlXQTUx0oV8pE6PXTU5UU5QPalrFFDnzYtpH7S8OgJ1n2x1sURUDU(Yj3TV7Yo5Y9BvLBLREm1hlUAWqvIE5KCKCEBdtBUNWS2DNNIH(qWG090ha28zyOofpPzKN61lDu5bCQUEl)VOXMXlCrr8Y44y1Silgr(9LI7S79xDUUkSauqeMtJAFkcZTTEZOASgMROccjR6mAq5a4Ox1KNPQ9H5yPtuWGTkBIrD3)BO0WvhLwtaD6kzHruLgbbzLojV(rycAuH90iuZrQ14WnG2CeDTnGpIMzt4P7LQHHrMWr2IcnQ4aKs8dO486sv4MQtSGO3YwBFf6L1UmdAQIjZxjbdI853y7Cosfsu8u8yJfemiL00JrhPcs6laluEI8dieV9ukZo5dJxB40sEVX7BIrhEtrziEwJJPNAMV8W5jEwRJKN26gpn9JvaLp88kp854bSFUOTkh7ojNiDI4vZITpLDYPqQzW6Zq)W9Qjw)X1GtlvIoNruhto1uz15AxPHKpoCmSbPLD)I0pOnvO2av(uOBoqhoXAEyZCyOIi(shz95xD5e5W(1KrEbqZQE7v1yqGPxR7AAMgKzJja8kfdM6n)yUZLacxTbXA9aiP4yDVteN3(9H4ghiPuRoWdVnZEKYklrqWeJNUaP2xprwNOyT)pLidtZ6TJWWH8KMvb3P495CMZ0HG8rOZBhzM)99gpdLj2HAH1dsuB10wt0oPf)jejSeI2GZzoACNB4cFAC8zKVrMfMFYVfMtAVbnti3xPPM9v6eO2lBBKRh72tpnq8IujKuy8bbZM3Z(IDIAx5uvFgaDWFofuXXKr2PhVN)OYAckF0XGvXOp2C(h7PygQggW9XlzAF2Ivi3MMztiPe1Md1Yv6FwNf0GNUoSwbi2wbfonGtfoQeatfmxdeIcqtVIdIwc50lhB8nQ7v2tMxa5U1lKNKPbvxNBJbUanSo)r(x3vfoI7mO05mr)c3rQNUYCKy6TYCqyYfrQKEx2o2P0(bnzqy0f5Ipb4ZLfAZyZTNQbBE5XRmR8YgQ4age39rxWVI2NP)SF0NBP9qa8QYG046eSySudqQBSnS72ehKZjJplmxUiE3m(nO)fvNINkNxjpDfF)V0JtzsCZ2Fr9fT)S(3jdqa4NM5xAfWjxQ63K6ZJWm)zE2KuYk(t((CmECDnglFJG1g6rZ2vYbaman33NJg3YT6S66r28yP0WYbdGSu99sQ2seYKccUIbnJADhQiwjOK5ZigPYhorDSkBHobC0rmsNPx9QzWgBy0E10BiVM4E6jYVEUbs9TotKNp0XcNe9WNvzQwXQ6syGdRzFcYoPM)vVx9hzGMVA6Csjye53EJbk9To45RQJfOzobyszDB7W6Jm9qyrgdCERN8JmJysnAF550AmtC)GSEu7eFximjnZnQD7T2JI9n03BAGL14K45MCzBqgjlm1iWNgnj))ix1kj9NONHALyASU4yJptLnmnFoF6eDclUI2EAiildtA43AmV2HLK8GdHXxWFDdmFxCQEoE34uaPw5I0S159zp6mYgoXeqgNMaz6cCbTAByaz6c0KsdBph1(IuvFs1tFEj1XQSf6eqtHz7AK6bqg14gggTHM0Nm5ylaDuSWjrp8zvMEgq(sMsQjqgYCvdciJMedNPLfOzUtlqMdAERN8dfqgk14ZcqgnWfnaKHsA6jqMU0EMaYq03HaKHYLvhqg1iWNgn5raKXPVazuJJzcit75ZEcKPddbDaz0Ua9HKK8GdH1aitxxQ4phaz(g89W7Z4vboj0P6Bf8BXTqcV4gUIFNaS4)l]] )
|
|
|
|
end
|
|
|