-- HunterSurvival.lua
-- June 2018
local addon , ns = ...
local Hekili = _G [ addon ]
local class = Hekili.Class
local state = Hekili.State
local PTR = ns.PTR
-- Shadowlands Legendaries
-- [x] Wildfire Cluster
-- [-] Rylakstalker's Confounding Strikes (passive/reactive)
-- [x] Latent Poison Injectors
-- [x] Butcher's Bone Fragments
-- Conduits
-- [x] Deadly Tandem
-- [x] Flame Infusion
-- [-] Stinging Strike
-- [-] Strength of the Pack
if UnitClassBase ( " player " ) == " HUNTER " then
local spec = Hekili : NewSpecialization ( 255 )
spec : RegisterResource ( Enum.PowerType . Focus , {
terms_of_engagement = {
aura = " terms_of_engagement " ,
last = function ( )
local app = state.buff . terms_of_engagement.applied
local t = state.query_time
return app + floor ( t - app )
end ,
interval = 1 ,
value = 2 ,
} ,
death_chakram = {
resource = " focus " ,
aura = " death_chakram " ,
last = function ( )
return state.buff . death_chakram.applied + floor ( state.query_time - state.buff . death_chakram.applied )
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 ( {
vipers_venom = 22275 , -- 268501
terms_of_engagement = 22283 , -- 265895
alpha_predator = 22296 , -- 269737
guerrilla_tactics = 21997 , -- 264332
hydras_bite = 22769 , -- 260241
butchery = 22297 , -- 212436
trailblazer = 19347 , -- 199921
natural_mending = 19348 , -- 270581
camouflage = 23100 , -- 199483
bloodseeker = 22277 , -- 260248
steel_trap = 19361 , -- 162488
a_murder_of_crows = 22299 , -- 131894
born_to_be_wild = 22268 , -- 266921
posthaste = 22276 , -- 109215
binding_shot = 22499 , -- 109248
tip_of_the_spear = 22300 , -- 260285
mongoose_bite = 22278 , -- 259387
flanking_strike = 22271 , -- 269751
birds_of_prey = 22272 , -- 260331
wildfire_infusion = 22301 , -- 271014
chakrams = 23105 , -- 259391
} )
-- PvP Talents
spec : RegisterPvpTalents ( {
chimaeral_sting = 3609 , -- 356719
diamond_ice = 686 , -- 203340
dragonscale_armor = 3610 , -- 202589
hiexplosive_trap = 3606 , -- 236776
hunting_pack = 661 , -- 203235
mending_bandage = 662 , -- 212640
roar_of_sacrifice = 663 , -- 53480
sticky_tar = 664 , -- 203264
survival_tactics = 3607 , -- 202746
trackers_net = 665 , -- 212638
tranquilizing_darts = 5420 , -- 356015
wild_kingdom = 5443 , -- 356707
} )
-- Auras
spec : RegisterAuras ( {
a_murder_of_crows = {
id = 131894 ,
duration = 15 ,
max_stack = 1 ,
} ,
aspect_of_the_eagle = {
id = 186289 ,
duration = 15 ,
max_stack = 1 ,
} ,
aspect_of_the_turtle = {
id = 186265 ,
duration = 8 ,
max_stack = 1 ,
} ,
binding_shot = {
id = 117405 ,
duration = 3600 ,
max_stack = 1 ,
} ,
camouflage = {
id = 199483 ,
duration = 60 ,
max_stack = 1 ,
} ,
coordinated_assault = {
id = 266779 ,
duration = function ( ) return 20 + ( conduit.deadly_tandem . mod * 0.001 ) end ,
max_stack = 1 ,
} ,
eagle_eye = {
id = 6197 ,
} ,
feign_death = {
id = 5384 ,
duration = 360 ,
max_stack = 1 ,
} ,
freezing_trap = {
id = 3355 ,
duration = 60 ,
type = " Magic " ,
max_stack = 1 ,
} ,
growl = {
id = 2649 ,
duration = 3 ,
max_stack = 1 ,
} ,
harpoon = {
id = 190927 ,
duration = 3 ,
max_stack = 1 ,
} ,
hunters_mark = {
id = 257284 ,
duration = 3600 ,
type = " Magic " ,
max_stack = 1 ,
} ,
internal_bleeding = {
id = 270343 ,
duration = 9 ,
max_stack = 3
} ,
intimidation = {
id = 24394 ,
duration = 5 ,
max_stack = 1 ,
} ,
kill_command = {
id = 259277 ,
duration = 8 ,
max_stack = 1 ,
generate = function ( t )
local name , _ , count , _ , duration , expires , caster = FindUnitDebuffByID ( " target " , 259277 , " PLAYER " )
if name then
t.name = name
t.count = 1
t.expires = expires
t.applied = expires - duration
t.caster = caster
return
end
t.count = 0
t.expires = 0
t.applied = 0
t.caster = " nobody "
end ,
copy = " bloodseeker "
} ,
masters_call = {
id = 54216 ,
duration = 4 ,
type = " Magic " ,
max_stack = 1 ,
} ,
misdirection = {
id = 35079 ,
duration = 8 ,
max_stack = 1 ,
} ,
mongoose_fury = {
id = 259388 ,
duration = 14 ,
max_stack = 5 ,
} ,
pathfinding = {
id = 264656 ,
duration = 3600 ,
max_stack = 1 ,
} ,
pheromone_bomb = {
id = 270332 ,
duration = 6 ,
max_stack = 1 ,
} ,
posthaste = {
id = 118922 ,
duration = 4 ,
max_stack = 1 ,
} ,
predator = {
id = 260249 ,
duratinon = 3600 ,
max_stack = 10 ,
} ,
serpent_sting = {
id = 259491 ,
duration = function ( ) return 12 * haste end ,
tick_time = function ( ) return 3 * haste end ,
type = " Poison " ,
max_stack = 1 ,
} ,
shrapnel_bomb = {
id = 270339 ,
duration = 6 ,
max_stack = 1 ,
} ,
steel_trap = {
id = 162487 ,
duration = 20 ,
max_stack = 1 ,
} ,
steel_trap_immobilize = {
id = 162480 ,
duration = 20 ,
max_stack = 1 ,
} ,
tar_trap = {
id = 135299 ,
duration = 3600 ,
max_stack = 1 ,
} ,
terms_of_engagement = {
id = 265898 ,
duration = 10 ,
max_stack = 1 ,
} ,
tip_of_the_spear = {
id = 260286 ,
duration = 10 ,
max_stack = 3 ,
} ,
trailblazer = {
id = 231390 ,
duration = 3600 ,
max_stack = 1 ,
} ,
vipers_venom = {
id = 268552 ,
duration = 8 ,
max_stack = 1 ,
} ,
volatile_bomb = {
id = 271049 ,
duration = 6 ,
max_stack = 1 ,
} ,
wildfire_bomb_dot = {
id = 269747 ,
duration = 6 ,
max_stack = 1 ,
} ,
wildfire_bomb = {
alias = { " wildfire_bomb_dot " , " shrapnel_bomb " , " pheromone_bomb " , " volatile_bomb " } ,
aliasType = " debuff " ,
aliasMode = " longest "
} ,
wing_clip = {
id = 195645 ,
duration = 15 ,
max_stack = 1 ,
} ,
-- AZERITE POWERS
blur_of_talons = {
id = 277969 ,
duration = 6 ,
max_stack = 5 ,
} ,
latent_poison = {
id = 273286 ,
duration = 20 ,
max_stack = 10
} ,
primeval_intuition = {
id = 288573 ,
duration = 12 ,
max_stack = 5 ,
} ,
-- Legendaries
latent_poison_injection = {
id = 336903 ,
duration = 15 ,
max_stack = 10
} ,
nessingwarys_trapping_apparatus = {
id = 336744 ,
duration = 5 ,
max_stack = 1 ,
copy = { " nesingwarys_trapping_apparatus " , " nesingwarys_apparatus " , " nessingwarys_apparatus " }
} ,
-- Conduits
strength_of_the_pack = {
id = 341223 ,
duration = 4 ,
max_stack = 1
}
} )
spec : RegisterHook ( " runHandler " , function ( action , pool )
if buff.camouflage . up and action ~= " camouflage " then removeBuff ( " camouflage " ) end
if buff.feign_death . up and action ~= " feign_death " then removeBuff ( " feign_death " ) end
end )
spec : RegisterStateExpr ( " current_wildfire_bomb " , function ( ) return " wildfire_bomb " end )
local function IsActiveSpell ( id )
local slot = FindSpellBookSlotBySpellID ( id )
if not slot then return false end
local _ , _ , spellID = GetSpellBookItemName ( slot , " spell " )
return id == spellID
end
state.IsActiveSpell = IsActiveSpell
local pheromoneReset = false
local FindUnitDebuffByID = ns.FindUnitDebuffByID
spec : RegisterEvent ( " COMBAT_LOG_EVENT_UNFILTERED " , function ( )
local _ , subtype , _ , sourceGUID , sourceName , _ , _ , destGUID , destName , destFlags , _ , spellID , spellName = CombatLogGetCurrentEventInfo ( )
if sourceGUID == state.GUID and spellID == 259489 and subtype == " SPELL_CAST_SUCCESS " then
pheromoneReset = FindUnitDebuffByID ( " target " , 270332 ) and true or false
end
end )
local ExpireNesingwarysTrappingApparatus = setfenv ( function ( )
focus.regen = focus.regen * 0.5
forecastResources ( " focus " )
end , state )
-- Tier 28
spec : RegisterSetBonuses ( " tier28_2pc " , 364490 , " tier28_4pc " , 363667 )
-- 2-Set - Mad Bombardier - When Kill Command resets, it has a 40% chance to make your next Wildfire Bomb incur no cooldown.
-- 4-Set - Mad Bombardier - Your Wildfire Bombs deal 30% additional damage. This bonus is increased to 80% for bombs empowered by Mad Bombardier.
spec : RegisterAura ( " mad_bombardier " , {
id = 363805 ,
duration = 20 ,
max_stack = 1 ,
} )
spec : RegisterHook ( " reset_precast " , function ( )
if talent.wildfire_infusion . enabled then
if IsActiveSpell ( 270335 ) then current_wildfire_bomb = " shrapnel_bomb "
elseif IsActiveSpell ( 270323 ) then current_wildfire_bomb = " pheromone_bomb "
elseif IsActiveSpell ( 271045 ) then current_wildfire_bomb = " volatile_bomb "
else current_wildfire_bomb = " wildfire_bomb " end
else
current_wildfire_bomb = " wildfire_bomb "
end
if prev_gcd [ 1 ] . kill_command and pheromoneReset and cooldown.kill_command . remains > 0 and ( now - action.kill_command . lastCast < 0.25 ) then
setCooldown ( " kill_command " , 0 )
end
if now - action.harpoon . lastCast < 1.5 then
setDistance ( 5 )
end
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 )
spec : RegisterHook ( " specializationChanged " , function ( )
current_wildfire_bomb = nil
end )
spec : RegisterStateTable ( " next_wi_bomb " , setmetatable ( { } , {
__index = function ( t , k )
if k == " shrapnel " then return current_wildfire_bomb == " shrapnel_bomb "
elseif k == " pheromone " then return current_wildfire_bomb == " pheromone_bomb "
elseif k == " volatile " then return current_wildfire_bomb == " volatile_bomb " end
return false
end
} ) )
spec : RegisterStateTable ( " bloodseeker " , setmetatable ( { } , {
__index = function ( t , k )
if k == " count " then
return active_dot.kill_command
end
return debuff.kill_command [ k ]
end ,
} ) )
spec : RegisterStateExpr ( " bloodseeker " , function ( ) return debuff.bloodseeker end )
-- Abilities
spec : RegisterAbilities ( {
a_murder_of_crows = {
id = 131894 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
spend = 30 ,
spendType = " focus " ,
toggle = " cooldowns " ,
startsCombat = true ,
texture = 645217 ,
talent = " a_murder_of_crows " ,
handler = function ( )
applyDebuff ( " target " , " a_murder_of_crows " )
end ,
} ,
aspect_of_the_cheetah = {
id = 186257 ,
cast = 0 ,
cooldown = function ( ) return ( 180 * ( legendary.call_of_the_wild . enabled and 0.75 or 1 ) * ( talent.born_to_be_wild . enabled and 0.8 or 1 ) ) + ( conduit.cheetahs_vigor . mod * 0.001 ) end ,
gcd = " spell " ,
startsCombat = false ,
texture = 132242 ,
handler = function ( )
applyBuff ( " aspect_of_the_cheetah_sprint " )
applyBuff ( " aspect_of_the_cheetah " )
end ,
} ,
aspect_of_the_eagle = {
id = 186289 ,
cast = 0 ,
cooldown = function ( ) return 90 * ( legendary.call_of_the_wild . enabled and 0.75 or 1 ) * ( talent.born_to_be_wild . enabled and 0.8 or 1 ) end ,
gcd = " off " ,
toggle = " cooldowns " ,
startsCombat = false ,
texture = 612363 ,
handler = function ( )
applyBuff ( " aspect_of_the_eagle " )
end ,
} ,
aspect_of_the_turtle = {
id = 186265 ,
cast = 0 ,
cooldown = function ( ) return ( 180 * ( legendary.call_of_the_wild . enabled and 0.75 or 1 ) * ( talent.born_to_be_wild . enabled and 0.8 or 1 ) ) + ( conduit.harmony_of_the_tortollan . mod * 0.001 ) end ,
gcd = " spell " ,
toggle = " defensives " ,
startsCombat = false ,
texture = 132199 ,
handler = function ( )
applyBuff ( " aspect_of_the_turtle " )
setCooldown ( " global_cooldown " , 8 )
end ,
} ,
binding_shot = {
id = 109248 ,
cast = 0 ,
cooldown = 45 ,
gcd = " spell " ,
startsCombat = false ,
texture = 462650 ,
handler = function ( )
applyDebuff ( " target " , " binding_shot " )
end ,
} ,
butchery = {
id = 212436 ,
cast = 0 ,
charges = 3 ,
cooldown = 9 ,
recharge = 9 ,
hasteCD = true ,
gcd = " spell " ,
spend = 30 ,
spendType = " focus " ,
startsCombat = true ,
texture = 999948 ,
aura = function ( ) return debuff.shrapnel_bomb . up and " internal_bleeding " or nil end ,
cycle = function ( ) return debuff.shrapnel_bomb . up and " internal_bleeding " or nil end ,
talent = " butchery " ,
usable = function ( ) return charges > 1 or active_enemies > 1 or target.time_to_die < ( 9 * haste ) end ,
handler = function ( )
gainChargeTime ( " wildfire_bomb " , min ( 5 , active_enemies ) )
gainChargeTime ( " shrapnel_bomb " , min ( 5 , active_enemies ) )
gainChargeTime ( " volatile_bomb " , min ( 5 , active_enemies ) )
gainChargeTime ( " pheromone_bomb " , min ( 5 , active_enemies ) )
if talent.birds_of_prey . enabled and buff.coordinated_assault . up and UnitIsUnit ( " pettarget " , " target " ) then
buff.coordinated_assault . expires = buff.coordinated_assault . expires + 1.5
end
if debuff.shrapnel_bomb . up then applyDebuff ( " target " , " internal_bleeding " , 9 , min ( 3 , debuff.internal_bleeding . stack + 1 ) ) end
removeBuff ( " butchers_bone_fragments " )
if conduit.flame_infusion . enabled then
addStack ( " flame_infusion " , nil , 1 )
end
end ,
} ,
camouflage = {
id = 199483 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
startsCombat = false ,
texture = 461113 ,
talent = " camouflage " ,
usable = function ( ) return time == 0 end ,
handler = function ( )
applyBuff ( " camouflage " )
end ,
} ,
carve = {
id = 187708 ,
cast = 0 ,
cooldown = 6 ,
hasteCD = true ,
gcd = " spell " ,
spend = 35 ,
spendType = " focus " ,
startsCombat = true ,
texture = 1376039 ,
-- aura = function () return debuff.shrapnel_bomb.up and "internal_bleeding" or nil end,
-- cycle = function () return debuff.shrapnel_bomb.up and "internal_bleeding" or nil end,
notalent = " butchery " ,
handler = function ( )
gainChargeTime ( " wildfire_bomb " , min ( 5 , active_enemies ) )
gainChargeTime ( " shrapnel_bomb " , min ( 5 , active_enemies ) )
gainChargeTime ( " volatile_bomb " , min ( 5 , active_enemies ) )
gainChargeTime ( " pheromone_bomb " , min ( 5 , active_enemies ) )
if debuff.shrapnel_bomb . up then applyDebuff ( " target " , " internal_bleeding " , 9 , min ( 3 , debuff.internal_bleeding . stack + 1 ) ) end
if talent.birds_of_prey . enabled and buff.coordinated_assault . up and UnitIsUnit ( " pettarget " , " target " ) then
buff.coordinated_assault . expires = buff.coordinated_assault . expires + 1.5
end
removeBuff ( " butchers_bone_fragments " )
if conduit.flame_infusion . enabled then
addStack ( " flame_infusion " , nil , 1 )
end
end ,
auras = {
-- Conduit
flame_infusion = {
id = 341401 ,
duration = 8 ,
max_stack = 2 ,
}
}
} ,
chakrams = {
id = 259391 ,
cast = 0 ,
cooldown = 20 ,
gcd = " spell " ,
spend = 15 ,
spendType = " focus " ,
startsCombat = true ,
texture = 648707 ,
talent = " chakrams " ,
handler = function ( )
end ,
} ,
coordinated_assault = {
id = 266779 ,
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 = " spell " ,
toggle = " cooldowns " ,
startsCombat = false ,
texture = 2065565 ,
nobuff = function ( )
if settings.ca_vop_overlap then return end
return " coordinated_assault "
end ,
usable = function ( ) return pet.alive end ,
handler = function ( )
applyBuff ( " coordinated_assault " )
end ,
} ,
disengage = {
id = 781 ,
cast = 0 ,
cooldown = 20 ,
gcd = " off " ,
startsCombat = false ,
texture = 132294 ,
handler = function ( )
setDistance ( 15 )
if talent.posthaste . enabled then applyBuff ( " posthaste " ) end
if conduit.tactical_retreat . enabled and target.within8 then applyDebuff ( " target " , " tactical_retreat " ) end
end ,
} ,
--[[ eagle_eye = {
id = 6197 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
startsCombat = true ,
texture = 132172 ,
handler = function ( )
end ,
} , ] ]
exhilaration = {
id = 109304 ,
cast = 0 ,
cooldown = 120 ,
gcd = " spell " ,
toggle = " defensives " ,
startsCombat = false ,
texture = 461117 ,
handler = function ( )
gain ( 0.3 * health.max , " health " )
if conduit.rejuvenating_wind . enabled then applyBuff ( " rejuvenating_wind " ) end
end ,
} ,
--[[ Using from BM module.
feign_death = {
id = 5384 ,
cast = 0 ,
cooldown = 30 ,
gcd = " off " ,
startsCombat = false ,
texture = 132293 ,
handler = function ( )
applyBuff ( " feign_death " )
end ,
} , ] ]
flanking_strike = {
id = 269751 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
spend = - 30 ,
spendType = " focus " ,
startsCombat = true ,
texture = 236184 ,
talent = " flanking_strike " ,
usable = function ( ) return pet.alive end ,
} ,
--[[ flare = {
id = 1543 ,
cast = 0 ,
cooldown = 20 ,
gcd = " spell " ,
startsCombat = true ,
texture = 135815 ,
handler = function ( )
applyDebuff ( " target " , " flare " )
end ,
} , ] ]
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 = false ,
texture = 135834 ,
handler = function ( )
applyDebuff ( " target " , " freezing_trap " )
end ,
} ,
harpoon = {
id = 190925 ,
cast = 0 ,
charges = 1 ,
cooldown = 20 ,
recharge = 20 ,
gcd = " spell " ,
startsCombat = true ,
texture = 1376040 ,
usable = function ( ) return settings.use_harpoon and target.distance > 8 , " harpoon disabled or target too close " end ,
handler = function ( )
applyDebuff ( " target " , " harpoon " )
if talent.terms_of_engagement . enabled then applyBuff ( " terms_of_engagement " ) end
setDistance ( 5 )
end ,
} ,
hunters_mark = {
id = 257284 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
startsCombat = false ,
texture = 236188 ,
handler = function ( )
applyDebuff ( " target " , " hunters_mark " )
end ,
} ,
intimidation = {
id = 19577 ,
cast = 0 ,
cooldown = 60 ,
gcd = " spell " ,
startsCombat = true ,
texture = 132111 ,
usable = function ( ) return pet.alive , " requires a living pet " end ,
handler = function ( )
applyDebuff ( " target " , " intimidation " )
end ,
} ,
kill_command = {
id = 259489 ,
cast = 0 ,
charges = function ( ) return talent.alpha_predator . enabled and 2 or nil end ,
cooldown = 6 ,
recharge = 6 ,
hasteCD = true ,
gcd = " spell " ,
spend = - 15 ,
spendType = " focus " ,
startsCombat = true ,
texture = 132176 ,
cycle = function ( ) return talent.bloodseeker . enabled and " kill_command " or nil end ,
usable = function ( ) return pet.alive , " requires a living pet " end ,
handler = function ( )
if talent.bloodseeker . enabled then
applyBuff ( " predator " , 8 )
applyDebuff ( " target " , " kill_command " , 8 )
end
if talent.tip_of_the_spear . enabled then addStack ( " tip_of_the_spear " , 20 , 1 ) end
if debuff.pheromone_bomb . up then
if talent.alpha_predator . enabled then gainCharges ( " kill_command " , 1 )
else setCooldown ( " kill_command " , 0 ) end
end
if debuff.shrapnel_bomb . up then applyDebuff ( " target " , " internal_bleeding " , 9 , min ( 3 , debuff.internal_bleeding . stack + 1 ) ) end
end ,
} ,
kill_shot = {
id = 320976 ,
cast = 0 ,
cooldown = 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 , " requires target health below 20 percent " 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 = " off " ,
startsCombat = false ,
texture = 236189 ,
usable = function ( ) return pet.alive , " requires a living pet " end ,
handler = function ( )
applyBuff ( " masters_call " )
end ,
} ,
misdirection = {
id = 34477 ,
cast = 0 ,
cooldown = 30 ,
gcd = " off " ,
startsCombat = false ,
texture = 132180 ,
usable = function ( ) return pet.alive or group , " requires a living pet or ally " end ,
handler = function ( )
applyBuff ( " misdirection " )
end ,
} ,
mongoose_bite = {
id = 259387 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = 30 ,
spendType = " focus " ,
startsCombat = true ,
texture = 1376044 ,
aura = function ( ) return debuff.shrapnel_bomb . up and " internal_bleeding " or nil end ,
cycle = function ( ) return debuff.shrapnel_bomb . up and " internal_bleeding " or nil end ,
talent = " mongoose_bite " ,
handler = function ( )
if buff.mongoose_fury . down then applyBuff ( " mongoose_fury " )
else applyBuff ( " mongoose_fury " , buff.mongoose_fury . remains , min ( 5 , buff.mongoose_fury . stack + 1 ) ) end
if debuff.shrapnel_bomb . up then
if debuff.internal_bleeding . up then applyDebuff ( " target " , " internal_bleeding " , 9 , debuff.internal_bleeding . stack + 1 ) end
end
removeDebuff ( " target " , " latent_poison " )
removeDebuff ( " target " , " latent_poison_injection " )
if azerite.wilderness_survival . enabled then
gainChargeTime ( " wildfire_bomb " , 1 )
if talent.wildfire_infusion . enabled then
gainChargeTime ( " shrapnel_bomb " , 1 )
gainChargeTime ( " pheromone_bomb " , 1 )
gainChargeTime ( " volatile_bomb " , 1 )
end
end
if azerite.primeval_intuition . enabled then
addStack ( " primeval_intuition " , nil , 1 )
end
if azerite.blur_of_talons . enabled and buff.coordinated_assault . up then
addStack ( " blur_of_talons " , nil , 1 )
end
if legendary.butchers_bone_fragments . enabled then
addStack ( " butchers_bone_fragments " , nil , 1 )
end
end ,
copy = { 265888 , " mongoose_bite_eagle " }
} ,
muzzle = {
id = 187707 ,
cast = 0 ,
cooldown = 15 ,
gcd = " off " ,
startsCombat = true ,
texture = 1376045 ,
toggle = " interrupts " ,
debuff = " casting " ,
readyTime = state.timeToInterrupt ,
handler = function ( )
if conduit.reversal_of_fortune . enabled then
gain ( conduit.reversal_of_fortune . mod , " focus " )
end
interrupt ( )
end ,
} ,
pheromone_bomb = {
-- id = 270323,
known = 259495 ,
cast = 0 ,
charges = function ( ) return talent.guerrilla_tactics . enabled and 2 or nil end ,
cooldown = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
recharge = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
gcd = " spell " ,
startsCombat = true ,
bind = " wildfire_bomb " ,
talent = " wildfire_infusion " ,
usable = function ( ) return current_wildfire_bomb == " pheromone_bomb " end ,
handler = function ( )
applyDebuff ( " target " , " pheromone_bomb " )
current_wildfire_bomb = " wildfire_bomb "
removeBuff ( " mad_bombardier " )
end ,
} ,
raptor_strike = {
id = 186270 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = 30 ,
spendType = " focus " ,
startsCombat = true ,
texture = 1376046 ,
aura = function ( ) return debuff.shrapnel_bomb . up and " internal_bleeding " or nil end ,
cycle = function ( ) return debuff.shrapnel_bomb . up and " internal_bleeding " or nil end ,
notalent = " mongoose_bite " ,
handler = function ( )
removeBuff ( " tip_of_the_spear " )
if debuff.shrapnel_bomb . up then
if debuff.internal_bleeding . up then applyDebuff ( " target " , " internal_bleeding " , 9 , debuff.internal_bleeding . stack + 1 ) end
end
if talent.birds_of_prey . enabled and buff.coordinated_assault . up and UnitIsUnit ( " pettarget " , " target " ) then
buff.coordinated_assault . expires = buff.coordinated_assault . expires + 1.5
end
removeDebuff ( " target " , " latent_poison " )
removeDebuff ( " target " , " latent_poison_injection " )
if azerite.wilderness_survival . enabled then
gainChargeTime ( " wildfire_bomb " , 1 )
if talent.wildfire_infusion . enabled then
gainChargeTime ( " shrapnel_bomb " , 1 )
gainChargeTime ( " pheromone_bomb " , 1 )
gainChargeTime ( " volatile_bomb " , 1 )
end
end
if azerite.primeval_intuition . enabled then
addStack ( " primeval_intuition " , nil , 1 )
end
if azerite.blur_of_talons . enabled and buff.coordinated_assault . up then
addStack ( " blur_of_talons " , nil , 1 )
end
if legendary.butchers_bone_fragments . enabled then
addStack ( " butchers_bone_fragments " , nil , 1 )
end
end ,
copy = { " raptor_strike_eagle " , 265189 } ,
auras = {
butchers_bone_fragments = {
id = 336908 ,
duration = 12 ,
max_stack = 6 ,
} ,
}
} ,
serpent_sting = {
id = 259491 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = function ( ) return buff.vipers_venom . up and 0 or 20 end ,
spendType = " focus " ,
startsCombat = true ,
texture = 1033905 ,
handler = function ( )
removeBuff ( " vipers_venom " )
applyDebuff ( " target " , " serpent_sting " )
if azerite.latent_poison . enabled then
applyDebuff ( " target " , " latent_poison " )
end
if legendary.latent_poison_injectors . enabled then
applyDebuff ( " target " , " latent_poison_injection " , nil , debuff.latent_poison_injection . stack + 1 )
end
end ,
} ,
shrapnel_bomb = {
-- id = 270335,
known = 259495 ,
cast = 0 ,
charges = function ( ) return talent.guerrilla_tactics . enabled and 2 or nil end ,
cooldown = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
recharge = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
hasteCD = true ,
gcd = " spell " ,
startsCombat = true ,
bind = " wildfire_bomb " ,
usable = function ( ) return current_wildfire_bomb == " shrapnel_bomb " end ,
handler = function ( )
applyDebuff ( " target " , " shrapnel_bomb " )
current_wildfire_bomb = " wildfire_bomb "
removeBuff ( " mad_bombardier " )
end ,
} ,
steady_shot = {
id = 56641 ,
cast = 1.75 ,
cooldown = 0 ,
gcd = " spell " ,
startsCombat = true ,
texture = 132213 ,
handler = function ( )
end ,
} ,
steel_trap = {
id = 162488 ,
cast = 0 ,
cooldown = 30 ,
gcd = " spell " ,
spend = function ( )
if legendary.nessingwarys_trapping_apparatus . enabled then
return - 45 , " focus "
end
end ,
startsCombat = false ,
texture = 1467588 ,
handler = function ( )
applyDebuff ( " target " , " steel_trap " )
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 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 ,
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 dispellable_enrage or dispellable_magic " end ,
handler = function ( )
removeBuff ( " dispellable_enrage " )
removeBuff ( " dispellable_magic " )
if level > 53 then gain ( 10 , " focus " ) end
end ,
} ,
volatile_bomb = {
-- id = 271045,
known = 259495 ,
cast = 0 ,
charges = function ( ) return talent.guerrilla_tactics . enabled and 2 or nil end ,
cooldown = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
recharge = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
hasteCD = true ,
gcd = " spell " ,
startsCombat = true ,
bind = " wildfire_bomb " ,
usable = function ( ) return current_wildfire_bomb == " volatile_bomb " end ,
handler = function ( )
if debuff.serpent_sting . up then applyDebuff ( " target " , " serpent_sting " ) end
current_wildfire_bomb = " wildfire_bomb "
removeBuff ( " mad_bombardier " )
end ,
} ,
wildfire_bomb = {
id = function ( )
if current_wildfire_bomb == " wildfire_bomb " then return 259495
elseif current_wildfire_bomb == " pheromone_bomb " then return 270323
elseif current_wildfire_bomb == " shrapnel_bomb " then return 270335
elseif current_wildfire_bomb == " volatile_bomb " then return 271045 end
return 259495
end ,
flash = { 270335 , 270323 , 271045 , 259495 } ,
known = 259495 ,
cast = 0 ,
charges = function ( ) return talent.guerrilla_tactics . enabled and 2 or nil end ,
cooldown = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
recharge = function ( ) return buff.mad_bombardier . up and 0 or 18 end ,
hasteCD = true ,
gcd = " spell " ,
startsCombat = true ,
--[[ texture = function ()
local a = current_wildfire_bomb and current_wildfire_bomb or " wildfire_bomb "
if a == " wildfire_bomb " or not action [ a ] then return 2065634 end
return action [ a ] . texture
end , ] ]
aura = " wildfire_bomb " ,
bind = function ( ) return current_wildfire_bomb end ,
handler = function ( )
if current_wildfire_bomb ~= " wildfire_bomb " then
runHandler ( current_wildfire_bomb )
current_wildfire_bomb = " wildfire_bomb "
return
end
applyDebuff ( " target " , " wildfire_bomb_dot " )
removeBuff ( " flame_infusion " )
removeBuff ( " mad_bombardier " )
end ,
copy = { 271045 , 270335 , 270323 , 259495 }
} ,
wing_clip = {
id = 195645 ,
cast = 0 ,
cooldown = 0 ,
gcd = " spell " ,
spend = 20 ,
spendType = " focus " ,
startsCombat = true ,
texture = 132309 ,
handler = function ( )
applyDebuff ( " target " , " wing_clip " )
end ,
} ,
} )
spec : RegisterOptions ( {
enabled = true ,
aoe = 2 ,
nameplates = true ,
nameplateRange = 8 ,
damage = true ,
damageExpiration = 8 ,
potion = " spectral_agility " ,
package = " Survival "
} )
spec : RegisterSetting ( " use_harpoon " , true , {
name = " |T1376040:0|t Use Harpoon " ,
desc = " If checked, the addon will recommend |T1376040:0|t Harpoon when you are out of range and Harpoon is available. " ,
type = " toggle " ,
width = 1.49
} )
spec : RegisterSetting ( " ca_vop_overlap " , false , {
name = " |T2065565:0|t Coordinated Assault Overlap (Vision of Perfection) " ,
desc = " If checked, the addon will recommend |T2065565:0|t Coordinated Assault even if the buff is already applied due to a Vision of Perfection proc. \n " ..
" This may be preferred when delaying Coordinated Assault would cost you one or more uses of Coordinated Assault in a given fight. " ,
type = " toggle " ,
width = " full "
} )
spec : RegisterPack ( " Survival " , 20220226 , [ [ d8Kv5bqiPs9iIa5sqjQnjf ( KukgLujNskvRsQQ6vqHzrKClPQu7Is ) IOQHrrPJjLSmIupdkHPreW1KQITjvv8nIq14OOW5icuRtQQ07OOOQMhfX9ik7dkPdkvLyHuKEiritKIIkxKIIQSrPQK6JuuugjffHoPukLvcL6LeHIzkLsUjffb7ek6Nuue1qPOiYsjcLEkunvIkFLII0yLsPAVe ( lPgmKdt1Ir4XinzrUmQndYNPWOLkoTKvlvLKxtenBrDBeTBv9BfdNehNiOLRYZvA6cxhuBNK8DPkJNIQZlfTEOez ( Ku7hyrlHCc8KhSatPnR0sBwPLUFSslnw0pslWJMkSaxXPs6gSa ) DswGJdFQkvEwGR4nZJNeYjW3b ( OSaxccG6eHY2VYlVrfDGjS0Hu ( TiHZEuZtphkKFlsQ8cCc4khTTxqiWtEWcmL2SslTzLw6 ( XkT0yr ) 0 cle4oC0zoboErkrc8ovkXVGqGN4LkWXHpvLkpdqMjc ) bFaS7RzId2VMaK09rkasAZkT0c8CTXkKtG ) HlKtGzlHCcCNg18c8nyoRJZve487ezojmvecmLwiNaNFNiZjHPcC6vbFLlW7gGiGHGS9QCsVk1vXApM0RFbi1QbicyiiBVkN0RsDvS2Jj96xaQbarNjNMEVvYkN10HK0 ) K9ysV ( vG70OMxGdDmJLQ3qhNRicbMyHqobo ) orMtctf40Rc ( kxG3naradbz7v5KEvQRI1EmPx ) cqQvdqeWqq2EvoPxL6QyTht61VaudaIoton9ERKvoRPdjP ) j7XKE9Ra3PrnVap8thNRicriWtmKdNdHCcmBjKtG70OMxGtcJLWszwGZVtK5KWuriWuAHCcC ( DImNeMkWDAuZlWJZFjeUYfwQEd92zcbEIx6vkrnVa3mBaiVd7jaY ) eaj35Vecx5clXaeMMjjrae ) mzXRuaupgGsZ3MaGsdafDQfGGMdGuYEt ( waIGPo8YaufTjbqemafZaqRIts2eG8pbq9yaI6FBca6ypv5MaKCN ) siaTkmTGkkaradbTwbo9QGVYf4DdqHFgCyRvRK9M8jcbMyHqobo ) orMtctf4onQ5f49vta ) gCDNoXBuFZvt9CwGtVk4RCbUtJsfR5NjlEbizaulaQba1faradbzPZCP69GtAFxhohwyfasTAaQBaIoton9ElDMlvVhCs776W5WEmPx ) cqQvdqeZUaudakkswhJovmazcaHfMfGAhGuRgG6cGCAuQyn ) mzXlaHvaQfa1aGiGHGShVZ7r9gA ) UPNfwbGuRgGiGHGS0zUu9EWjTVRdNdlSca1Ua ) DswG3xnb8BW1D6eVr9nxn1ZzriWuciKtG70OMxGdVSUcMCf487ezojmvecm7Jqobo ) orMtctf4onQ5f4upN1onQ515AdbEU2q ) ojlWPPvecm7hHCcC ( DImNeMkWPxf8vUa3PrPI18ZKfVaKjaewaqnaOWZ8hwI6sREG0kh30YVtK5KaFJROHaZwcCNg18cCQNZANg186CTHapxBOFNKf4eJIieykXfYjW53jYCsyQaNEvWx5cCNgLkwZptw8cqMaqyba1aG6gGcpZFyjQlT6bsRCCtl ) orMtc8nUIgcmBjWDAuZlWPEoRDAuZRZ1gc8CTH ( DswGVHieyAgc5e487ezojmvGtVk4RCbUtJsfR5NjlEbiScqslW34kAiWSLa3PrnVaN65S2PrnVoxBiWZ1g63jzbonZUkwecmLGfYjWDAuZlW9J6pRJ5o ( dbo ) orMtctfHie4khthscpeYjWSLqobo ) orMtctf4JIaF5OGe40Rc ( kxGhEM ) WsoVXmlRjQGT87ezojWt8sVsjQ5f491mXb7xtas6 ( ifajTzLwAbUk ) 0 VtYcCsc9TA6SHa3PrnVaxLFLtKzbUkpdZAoVSa3PrnV9CLyo9gxjjBPZgcCvEgMf4onQ5TKZBmZYAIkylD2qecmLwiNa3PrnVaFHjjNxRWHaNFNiZjHPIqGjwiKtG70OMxGtmrK5Kgk7n5uV6n0XyE9cC ( DImNeMkcbMsaHCcCNg18cCOmVDONdfcC ( DImNeMkcbM9riNaNFNiZjHPcC6vbFLlWp4NHMZGT7aNHMZG1mjbFRLLq4srHtcCNg18c8WpDCUIiey2pc5e4onQ5f4BWCwhNRiW53jYCsyQieHaFdHCcmBjKtGZVtK5KWubo9QGVYf4qdfEbimaiQVH ( yd ( bitaiOHcVws3CaQba1fa1naDEL0Sk ( dRNsRLnV2ybi1QbOUbOZRKMvXFy9uATWkauda68kPzv8hwpLwBc ( 8 OMhGWaGoVsAwf ) H1tP1wpazca1haQDasTAa68kPzv8hwpLwlSca1aGoVsAwf ) H1tP1EmPx ) cqyfGKaMvG70OMxGNyp6OPDCjpNuecmLwiNaNFNiZjHPcCNg18c8Lpf ( d9g1BiWPxf8vUaVBaknHD5tH ) qVr9g2OOswVba1aGc ) m4WgfjRJrNkgGWkajXbi1QbicyiiRQsHVvRI ) H0cRaqnaicyiiRQsHVvRI ) H0EmPx ) cqMaqg0KaN2KMzD4NbhRaZwIqGjwiKtG70OMxGdL9MCsVDMqGZVtK5KWuriWuciKtGZVtK5KWubo9QGVYf4DdqNxjnRI ) W6P0AzZRnwasTAaQBa68kPzv8hwpLwlSca1aG6cGoVsAwf ) H1tP1MGppQ5bimaOZRKMvXFy9uAT1dqMaqsBwasTAa68kPzv8hwpLwlDG ) aGKbqTaO2bi1QbOZRKMvXFy9uATWkauda68kPzv8hwpLw7XKE9laHvascywasTAaIy2fGAaqrrY6y0PIbitaOwMvG70OMxGF8oVh1BO97MEIqGzFeYjW53jYCsyQaNEvWx5c8UbOZRKMvXFy9uATS51glaPwna1naDEL0Sk ( dRNsRfwbGAaqNxjnRI ) W6P0AtWNh18aega05vsZQ4pSEkT26bitaiPnlaPwnaDEL0Sk ( dRNsRfwbGAaqNxjnRI ) W6P0ApM0RFbiScqsBwasTAaIy2fGAaqrrY6y0PIbitaiPnRa3PrnVaVxLt6vPUkwriWSFeYjW53jYCsyQaNEvWx5c8UbOZRKMvXFy9uATS51glaPwnarhv87Fy ) YOtOHCgGAaq0zYPP3B7v5KEvQRI1EmPx ) cqQvdqDdq0rf ) ( h2Vm6eAiNbOgauxau3a05vsZQ4pSEkTwyfaQbaDEL0Sk ( dRNsRnbFEuZdqyaqNxjnRI ) W6P0ARhGmbGWcZcqQvdqNxjnRI ) W6P0AHvaOga05vsZQ4pSEkT2Jj96xacRaK0MfGuRgG6gGoVsAwf ) H1tP1cRaqTdqQvdqeZUaudakkswhJovmazcaHfMvG70OMxGtN5s17bN0 ( UoCoeHatjUqobUtJAEbUKvoR3otiW53jYCsyQieyAgc5e487ezojmvGtVk4RCbo0qHxacdaI6BOp2GFaYeacAOWRL0nxG70OMxGdL9xY6n0BCLKSieykblKtG70OMxG7As4lXNEG00B6TcC ( DImNeMkcbMTmRqobo ) orMtctf40Rc ( kxGdbNZ6JPD8ZG1rrYaKjaK0au ) bidAcGAaqlhAI5HxBu8jTzOLwHcqQvdqeWqqwspPjgsc ) sfFwyfasTAaQBaA5qtmp8AJIpPndT0kuaQba1fabbNZ6JPD8ZG1rrYaKjaKbnbqQvdqqdfEbimaiQVH ( yd ( bitaiOHcVws3CaQba1fa9S5HUxPjgscRQj7rLzaQbaLMWU8PWFO3OEdBuujR3aGAaqPjSlFk8h6nQ3WEm0XBhNiZaKA1a0ZMh6ELMyijSkD4BiNNbOgau3aebmeKLCEJzwwdbFnTWkaudacAOWlaHbar9n0hBWpazcabnu41s6Mdq9na50OM3kzLZA6qs6FYs9n0hBWpa1FaclaO2bi1QbiIzxaQbaffjRJrNkgGmbGAzwaQDbUtJAEbEVkNGQJ1edjHiey2QLqobo ) orMtctf4onQ5f4sw5SMoKK ( Ne40Rc ( kxGVCOjMhETrXN0MHwAfka1aGstyv6W3qopRjgscBuujR3aGAaqDdqeWqqwspP
end