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.

2072 lines
81 KiB

4 years ago
-- 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 ()
4 years ago
local app = state.buff.aspect_of_the_wild.applied
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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
4 years ago
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( {
4 years ago
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 )
4 years ago
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 )
4 years ago
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 )
4 years ago
4 years ago
-- 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
} )
4 years ago
-- 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 )
4 years ago
else
setCooldown( "kill_command", cooldown.kill_command.remains - ( buff.killing_frenzy.up and 1.4 or 1 ) )
removeBuff( "killing_frenzy" )
end
4 years ago
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,
4 years ago
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,
4 years ago
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
4 years ago
if set_bonus.tier28_4pc > 0 and stat.crit + ( buff.frenzy.stack * 0.15 ) >= 100 then
applyBuff( "killing_frenzy" )
end
4 years ago
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,
4 years ago
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
4 years ago
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",
4 years ago
spend = 15,
spendType = "focus",
4 years ago
toggle = "cooldowns",
startsCombat = true,
4 years ago
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", 20220315, [[d8eb)bqiQepsuL4sQsu2evQpbvzuqLofuXQevP6vujnliIBPkHDb8likdtufhJkSmrLNrqLPbrIRPkLTbrsFtuvPXjQsQZbrvTois9ocQQQ5rf19KO2hvK)rqvLdcrvyHqv5HquzIquf5IIQu(ibvXijOQkNKGQ0kjiZuuvUjevj7uvs)uuvXqHOk1sjOQ8ujmvvP6RIQKmwckNvvIQ9QQ(lvnyqhMYIj0JfzYeDzuBgjFgsgns1PLA1quf1RjWSL0Tvf7w43QmCKYXvLilxXZrmDsxhkBhs9DimEOQ68sK1lQQA(IY(v6VJ)7)cPP8)1C5jxU8iCoEd4iVop538Gu)fAjA8VGMLeyO4Fryp8VaFSr0fI8YikpL(f0Ss1ZK)3)fKdBs8VGUQ0iinYqgQwPJjcs3dYi9dw10(I0yukYi9tcz)crSUQcVXx8xinL)VMlp5YLhHZXBah515j)MNC)cdtPFZVOOFqUFb9wk54l(lKmj9lWhBeDHiVmIYtPfk8hwO8ScH8YMe9f64nKSWC5jxUvOviKJUfOycsVc9Ifk8XVGdtSYleF2iYYfwq)0fk8mwIxiYBE6tcwHEXcZRSU2bQfwq)0fIrtAkta)IAtuY)9FHKPmSQ(F))QJ)7)clP9f)I0HfkpEc9t)fCyIvw(X3x)VM7)(VGdtSYYp((fws7l(f6yXlH11o)7aLNq)0FHKjPPPP9f)cHNBHgD2Kl0c5cFFS4LW6AN)8cFf5nYTqo4NMjizHi4fkVapDHYBHk9MSqQBwiTQvIhYcf5KHr4f2kEYfkYluVBHeA2ZtPfAHCHi4fMSapDHdBYUwAHVpw8slKqJtnvNwOigffb8lstR802VWLfQ2GIvqt80QwjE(6)vH7)(VGdtSYYp((fPPvEA7xKo0CyHceuAAlwO7fMURkpebWi04K6pkVsN9i6Qem8J1bzHUxy6UQ8qeGHjxyAhO82mhcWWpwhKfMLTqxwy6qZHfkqqPPTyHUxy6UQ8qeaJqJtQ)O8kD2JORsWWpwhKFbrNoP)xD8lSK2x8lswT6TK2x4Rnr)f1MO(WE4FHoDiGvYx)VIu(V)l4WeRS8JVFHL0(IFrYQvVL0(cFTj6VO2e1h2d)lssYx)V(2)9FbhMyLLF89lstR802VWsAJM9CWpntwOZlm3VGOtN0)Ro(fws7l(fjRw9ws7l81MO)IAtuFyp8VGOF9)ks9)(VGdtSYYp((fPPvEA7xyjTrZEo4NMjl0Pf64xq0Pt6)vh)clP9f)IKvRElP9f(At0FrTjQpSh(xKQSHM)6x)f0goDpIM(F))QJ)7)clP9f)cc2ZZfEAS(l4WeRS8JVV(Fn3)9FHL0(IFH4PALLEQQvILi6aLxp83XVGdtSYYp((6)vH7)(VWsAFXVGQYe6PXO0FbhMyLLF891)RiL)7)comXkl)47xqB4KruV2p8VWb4TFHL0(IFHAJxhJ2VinTYtB)IblyQBqXaYHvPUbf75hrEiaomXklxyw2chSGPUbfdcMq6afcBkr86y0O1bkVrJMnMIraCyIvw(1)RV9F)xWHjwz5hF)cAdNmI61(H)foaV9lSK2x8lezI2w1JymL(VinTYtB)cxwOAvouajXH6pkVy9ojGdtSYYf6EHUSWblyQBqXaYHvPUbf75hrEiaomXkl)6x)f60Hawj)3)V64)(VGdtSYYp((fhTFbH1FHL0(IFbABAtSY)c0wfJ)fIyuuGHjxyAhO82mhcagTfMLTqrmkkGrOXj1FuELo7r0vjaJ2VaTn(WE4FbPuK8y0(6)1C)3)fCyIvw(X3V4O9liS(lSK2x8lqBtBIv(xG2Qy8ViDO5WcfiO00wSq3lueJIcmm5ct7aL3M5qaWOTq3lueJIcyeACs9hLxPZEeDvcWOTWSSf6YcthAoSqbcknTfl09cfXOOagHgNu)r5v6ShrxLamA)c024d7H)feDUaLNuksEmAF9)QW9F)xWHjwz5hF)IJ2VGWAt9lSK2x8lqBtBIv(xG2gFyp8VGOZfO8KsrYp8J1b5xKMw5PTFHigffWi04K6pkVsN9i6QeipeXVaTvXypxj8ViDxvEicGrOXj1FuELo7r0vjy4hRdIhfgti)c0wfJ)fP7QYdragMCHPDGYBZCiad)yDqwOZc)wy6UQ8qeaJqJtQ)O8kD2JORsWWpwhepkmMq(6)vKY)9FbhMyLLF89loA)ccRn1VWsAFXVaTnTjw5FbAB8H9W)cIoxGYtkfj)WpwhKFrAALN2(fIyuuaJqJtQ)O8kD2JORsagTFbARIXEUs4Fr6UQ8qeaJqJtQ)O8kD2JORsWWpwhepkmMq(fOTkg)ls3vLhIamm5ct7aL3M5qag(X6G81)RV9F)xWHjwz5hF)IJ2VGWAt9lSK2x8lqBtBIv(xG2gFyp8VGuks(HFSoi)I00kpT9lshAoSqbcknTf)c0wfJ9CLW)I0Dv5HiagHgNu)r5v6ShrxLGHFSoiEuymH8lqBvm(xKURkpebyyYfM2bkVnZHam8J1bzHoj8BHP7QYdramcnoP(JYR0zpIUkbd)yDq8OWyc5R)xrQ)3)fCyIvw(X3VWsAFXVqNoeWQJFrAALN2(f4UqCxOoDiGvG6aq3iEmc7fXOOwyw2cthAoSqbcknTfl09c1PdbScuha6gXNURkpeXcXzHUxiUleTnTjwzarNlq5jLIKhJ2cDVqCxOllmDO5WcfiO00wSq3l0LfQthcyfO5a0nIhJWErmkQfMLTW0HMdluGGstBXcDVqxwOoDiGvGMdq3i(0Dv5Hiwyw2c1PdbSc0CG0Dv5Hiad)yDqwyw2c1PdbScuha6gXJryVigf1cDVqCxOlluNoeWkqZbOBepgH9IyuulmlBH60HawbQdq6UQ8qeaj2yAFXcDQ8c1PdbSc0CG0Dv5HiasSX0(IfIZcZYwOoDiGvG6aq3i(0Dv5HiwO7f6Yc1PdbSc0Ca6gXJryVigf1cDVqD6qaRa1biDxvEicGeBmTVyHovEH60HawbAoq6UQ8qeaj2yAFXcXzHzzl0LfI2M2eRmGOZfO8KsrYJrBHUxiUl0LfQthcyfO5a0nIhJWErmkQf6EH4UqD6qaRa1biDxvEicGeBmTVyHVyHVTqNxiABAtSYasPi5h(X6GSWSSfI2M2eRmGuks(HFSoil0PfQthcyfOoaP7QYdraKyJP9flezlm3cXzHzzluNoeWkqZbOBepgH9Iyuul09cXDH60HawbQdaDJ4XiSxeJIAHUxOoDiGvG6aKURkpebqInM2xSqNkVqD6qaRanhiDxvEicGeBmTVyHUxiUluNoeWkqDas3vLhIaiXgt7lw4lw4Bl05fI2M2eRmGuks(HFSoilmlBHOTPnXkdiLIKF4hRdYcDAH60HawbQdq6UQ8qeaj2yAFXcr2cZTqCwyw2cXDHUSqD6qaRa1bGUr8ye2lIrrTWSSfQthcyfO5aP7QYdraKyJP9fl0PYluNoeWkqDas3vLhIaiXgt7lwiol09cXDH60HawbAoq6UQ8qeGHnzPf6EH60HawbAoq6UQ8qeaj2yAFXcFXcFBHoTq020MyLbKsrYp8J1bzHUxiABAtSYasPi5h(X6GSqNxOoDiGvGMdKURkpebqInM2xSqKTWClmlBHUSqD6qaRanhiDxvEicWWMS0cDVqCxOoDiGvGMdKURkpeby4hRdYcFXcFBHoVq020MyLbeDUaLNuks(HFSoil09crBtBIvgq05cuEsPi5h(X6GSqNwyU8Sq3le3fQthcyfOoaP7QYdraKyJP9fl8fl8Tf68crBtBIvgqkfj)WpwhKfMLTqD6qaRanhiDxvEicWWpwhKf(If(2cDEHOTPnXkdiLIKF4hRdYcDVqD6qaRanhiDxvEicGeBmTVyHVyHoYZcDDHOTPnXkdiLIKF4hRdYcDEHOTPnXkdi6CbkpPuK8d)yDqwyw2crBtBIvgqkfj)WpwhKf60c1PdbScuhG0Dv5HiasSX0(IfISfMBHzzleTnTjwzaPuK8y0wiolmlBH60HawbAoq6UQ8qeGHFSoil8fl8
4 years ago
end