-- 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 )
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 = 18 ,
recharge = 18 ,
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 "
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 = 18 ,
recharge = 18 ,
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 "
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 = 18 ,
recharge = 18 ,
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 "
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 = 18 ,
recharge = 18 ,
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 " )
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 " , 20211123 , [ [ d80xNbqiHqpssK6ssIYMaKpje1OGKCkirRcvQ8kamluj3ssuTlj ( fQOHHkvDmH0YaOEgKqtdGKRbjyBOsHVbqQXjeHZHkL06ai8ouPi08iP6EKK9jeCqjryHKuEiKunrjrKUiQueSruPi5JOsPmsuPi1jfIOvcOEjQuuZuis3useHDkP6NsIiAOOsr0srLs8uGMkKQVIkLQXkjs2lI ) sQbJYHPAXi5XqnzfUmXMv0NrvJwOCArRwse1RrfMTGBJu7wv ) wQHtIJdjLLR0Zvz6uUoeBxs57ssJxs48cvRhGO5dPSFqtIsqNaoCti1bm3d4OrJcyuSayadOqbadycOfxriGkoMdNxiGVtleqqKTwwZdeqfpEO9bbDc41ilwiGvAilMzkhGGto5tlgcvb30CEjnsWTSF86tJZlPXCsaPqYGfjFcfbC4MqQdyUhWrJgfWOybWagqHcrb0eqhXI1lbemPrDcySCmKNqrahYHjGGiBTSMhGmUPrEtwiW17AcnLSqwuuKlidWCpGJsad5zhbDc4BobDs9Oe0jGo2Y ( jGNjsqBRRqaL3PcYGOgXi1bmbDcO8ovqge1iG4nnztNagriJczolvZWqFk5M2vwH2Z ) Gm0qdYOqMZs1mm0NsUPDLvO98pidiid3Dy0v ) chziOXnnT ) JYk0E ( hb0Xw2pbCUIaiZNxBRRqmsDuKGobuENkidIAeq8MMSPtaJiKrHmNLQzyOpLCt7kRq75FqgAObzuiZzPAgg6tj30UYk0E ( hKbeKH7om6QFHJme04MM2 ) rzfAp ) Ja6yl7NaA ( QT1vigXiGdz6ibJGoPEuc6eqhBz ) eqAeajGmieq5DQGmiQrmsDatqNakVtfKbrncOJTSFcOT ( JAizibK5ZRVyTrahYH3uXY ( jGCBnK5XeFaz ( pGm0x ) rnKmKasbYQZnjQdzYl0PCCbzvfiB0FKniB0qMflpiB2lKPe84YEqgLGDKtGS0I8aYOeiZ6gYofNMooK5 ) aYQkqg2 ) iBq2k ( idXHm0x ) rni7ueCotmKrHmNxHaI30KnDcyeHmZxEXk5PvcECzjgPoksqNakVtfKbrncOJTSFcyLCBipVK7QhYz5h ) 0 ypeiG4nnztNasHmNfC37iF3KH2VZrcwbrbYqdniJQVdYacYMjFmtVcTN ) bzQdzOi3taFNwiGvYTH88sUREiNLF8tJ9qGyK6akc6eqhBz ) eqKt0Pj0hbuENkidIAeJuhfiOtaL3PcYGOgb0Xw2pbe7HG2Xw2VoKNrad5z63PfciECeJuNBqqNakVtfKbrnciEtt20jGo2YAIwEHoLdYuhYqridiiZ8G8wHk3XP7PwzL4f5DQGmiGNTj2i1JsaDSL9taXEiODSL9Rd5zeWqEM ( DAHas1keJuhqtqNakVtfKbrnciEtt20jGo2YAIwEHoLdYuhYqridiilIqM5b5TcvUJt3tTYkXlY7ubzqapBtSrQhLa6yl7NaI9qq7yl7xhYZiGH8m970cb8mIrQhjiOtaL3PcYGOgbeVPjB6eqhBznrlVqNYbzraYamb8SnXgPEucOJTSFci2dbTJTSFDipJagYZ0VtleqCq8AcXi15wjOtaDSL9ta9f7VOTEx5ncO8ovqge1igXiGkRGBAk3iOtQhLGobuENkidIAeWwHaEILtciEtt20jGMhK3k09Z39jAQ0KI8ovqgeWHC4nvSSFcy9UMqtjlKfff5cYam3d4OeWA ( QFNwiG0u6904 ( mcOJTSFcynFtNkieWAEar0s4ecOJTS ) Y6kwV6Z2KdPG7ZiG18aIqaDSL9xO7NV7t0uPjfCFgXi1bmbDcOJTSFc4Hqt3VwrmcO8ovqge1igPoksqNa6yl7Nas1MfKHEg84YOA ( 8 ARRiFcO8ovqge1igPoGIGob0Xw2pbCgKlgE9PraL3PcYGOgXi1rbc6eq5DQGmiQraXBAYMobCrEz2lVuUgjm7Lx0cnLSxrqnKurrgeqhBz ) eqZxTTUcXi15ge0jGo2Y ( jGNjsqBRRqaL3PcYGOgXigb8mc6K6rjOtaL3PcYGOgbeVPjB6eWzJroidaid7NPxHxEitDiB2yKRq7vqaDSL9tahIBX04yohRttmsDatqNakVtfKbrncOJTSFc4jRI8M ( S85jG4nnztNagriB0w5KvrEtFw ( 8 flXCKppKbeKz ( YlwXsArBTEKcKfbidqdzOHgKrHmNLAPISNUM8nDbrbYacYOqMZsTur2txt ( MUScTN ) bzQdz84bbehhheT5lVyhPEuIrQJIe0jGo2Y ( jGZGhxg6lwBeq5DQGmiQrmsDafbDcOJTSFc4kx ) ULpV23TRsaL3PcYGOgXi1rbc6eqhBz ) eWQzyOpLCt7iGY7ubzquJyK6Cdc6eqhBz ) eqC37iF3KH2VZrcgbuENkidIAeJuhqtqNa6yl7NaYrgc6lwBeq5DQGmiQrms9ibbDcO8ovqge1iG4nnztNaoBmYbzaazy ) m9k8YdzQdzZgJCfAVccOJTSFc4m4ph5ZRpBtoeIrQZTsqNa6yl7Na6AAKDiRUNA82vpcO8ovqge1igPEuUNGobuENkidIAeq8MMSPtaNiHGEfCmF5fTL0cKPoKXJhqgAObzZgJCqgaqg2ptVcV8qM6q2SXixH2RaYacYqfK9sfMUAQPAAQsTo4wgeidiiB0w5KvrEtFw ( 8 flXCKppKbeKnARCYQiVPplF ( YkZvUyovqGm0qdYEPctxn1unnvrjMSnD ) cKbeKfriJczol09Z39j6jYgVGOazabzZgJCqgaqg2ptVcV8qM6q2SXixH2RaYQCiZXw2FHJme04MM2 ) rb7NPxHxEiJ7GmueYqjKHgAqML0I2A9ifitDilk3taDSL9taRMHXmxrt10ueJupAuc6eq5DQGmiQraXBAYMob0Xwwt0Yl0PCqweGSOqgqqweHSf5LzV8szJhCooZdCi7PX9pBKFKpV ( Sn5qUIGAiPIImiGo2Y ( jGyFRjeJupkGjOtaL3PcYGOgbeVPjB6eqhBznrlVqNYbzraYIczabzreYwKxM9YlLnEW54mpWHSNg3 ) Sr ( r ( 86 Z2Kd5kcQHKkkYaYacYWDhgD1VundJzUIMQPPktKqqVcoMV8I2sAbYIaKDksiOnF5f7GmGGmubz4y ( YlNEUo2Y ( 9 aKfbidWfuaYqdniB0w5ITUYlbnvttvSeZr ( 8 qgkjGo2Y ( jGuigoMSXjgPEuuKGobuENkidIAeq8MMSPtaNng5GmaGmSFMEfE5Hm1HSzJrUcTxbb0Xw2pb8mrcABDfIrQhfqrqNakVtfKbrncOJTSFciD ) 8 DFIMknHaI30KnDcO5b5TIhuI5ALvgU1BrENkididiidvqgfYCwO7NV7t0tKnEbrbYacYOqMZcD ) 8 DFIEISXlRq75FqM6q2SXihKXjKHkiRMVPtfKcnLEpnUpdYQCid7NPxHxEidLqg3bz84bKbeKfriJczolvZWqFk5M2vwH2Z ) Gm0qdYOqMZcD ) 8 DFIEISXlRq75Fqgqq2lvy6QPMQPPkkXKTP7xGmusaXXXbrB ( Yl2rQhLyK6rrbc6eq5DQGmiQraDSL9ta5idbnUPP9FqaXBAYMobCIec6vWX8Lx0wslqM6qgpEazabzZgJCqgaqg2ptVcV8qM6q2SXixH2RGaIJJdI28LxSJupkXi1JYniOtaL3PcYGOgb0Xw2pbCDfRx9zBYHqaXBAYMobKczolwQO7P2Ij6tr8TCMJ5aYubzOiKHgAq2OTYfBDLxcAQMMQyjMJ85jG444GOnF5f7i1Jsms9OaAc6eq5DQGmiQraXBAYMobC0w5ITUYlbnvttvSeZr ( 8 eqhBz ) eq6 ( 57 ( envAcXi1JgjiOtaL3PcYGOgb0Xw2pb8KvrEtFw ( 8 eq8MMSPtaxzUYfZPccKbeKz ( YlwXsArBTEKcKfbidqdzOHgKrHmNLAPISNUM8nDbrHaIJJdI28LxSJupkXi1JYTsqNakVtfKbrnciEtt20jGVuHPRMAQMMQCXwx5LaKbeKnBmYbzraYQ5B6ubPqtP3tJ7ZGmUdYamKbeKnARCYQiVPplF ( Yk0E ( hKfbi
end