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.
1488 lines
54 KiB
1488 lines
54 KiB
-- 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 ) / class.auras.death_chakram.tick_time ) * class.auras.death_chakram.tick_time
|
|
end,
|
|
|
|
interval = function () return class.auras.death_chakram.tick_time end,
|
|
value = function () return state.conduit.necrotic_barrage.enabled and 5 or 3 end,
|
|
}
|
|
} )
|
|
|
|
-- Talents
|
|
spec:RegisterTalents( {
|
|
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,
|
|
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 )
|
|
|
|
spec:RegisterStateExpr( "check_focus_overcap", function ()
|
|
if settings.allow_focus_overcap then return true end
|
|
if not this_action then return focus.current + focus.regen * gcd.max <= focus.max end
|
|
return focus.current + cast_regen <= focus.max
|
|
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 = 0
|
|
local FindUnitDebuffByID = ns.FindUnitDebuffByID
|
|
|
|
local madBombardierSpent = 0
|
|
local bombImpactIds = {
|
|
[270329] = true, -- Pheromone Bomb
|
|
[270338] = true, -- Shrapnel Bomb
|
|
[271048] = true, -- Volatile Bomb
|
|
[265157] = true, -- Wildfire Bomb
|
|
}
|
|
|
|
spec:RegisterCombatLogEvent( function ( _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName )
|
|
-- Reset Kill Command after
|
|
if sourceGUID == state.GUID then
|
|
if spellID == 259489 and subtype == "SPELL_CAST_SUCCESS" then
|
|
pheromoneReset = FindUnitDebuffByID( "target", 270332 ) and GetTime() or 0
|
|
elseif bombImpactIds[ spellID ] and state.set_bonus.tier28 > 1 and subtype == "SPELL_DAMAGE" then
|
|
-- Mad Bombardier doesn't get removed until even after it impacts the target, but we want to know it should've been consumed.
|
|
madBombardierSpent = GetPlayerAuraBySpellID( 363805 ) and GetTime() or 0
|
|
end
|
|
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,
|
|
} )
|
|
|
|
|
|
-- Create a flag that WfB's CD should reset based on the set bonus, so we can remove the buff to help the addon's priority logic.
|
|
spec:RegisterStateExpr( "will_reset_wildfire_bomb", function ()
|
|
return buff.mad_bombardier.up
|
|
end )
|
|
|
|
|
|
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 now - pheromoneReset < 0.3 then
|
|
setCooldown( "kill_command", 0 )
|
|
end
|
|
|
|
will_reset_wildfire_bomb = nil
|
|
|
|
-- If an actual WfB has cast but not landed, remove the buff but flag WfB to reset upon impact.
|
|
if buff.mad_bombardier.up then
|
|
-- Remove if we just had a bomb impact but the buff didn't wipe yet.
|
|
if now - madBombardierSpent < 0.3 then
|
|
removeBuff( "mad_bombardier" )
|
|
-- Remove if we have a bomb in flight that will consume it, but flag will_reset_wildfire_bomb so the impact event knows what to do.
|
|
elseif ( action.wildfire_bomb.in_flight or action.shrapnel_bomb.in_flight or action.pheromone_bomb.in_flight or action.volatile_bomb.in_flight ) then
|
|
removeBuff( "mad_bombardier" )
|
|
will_reset_wildfire_bomb = true
|
|
end
|
|
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
|
|
gainCharges( "kill_command", 1 )
|
|
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,
|
|
hasteCD = true,
|
|
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
|
|
bind = "wildfire_bomb",
|
|
talent = "wildfire_infusion",
|
|
velocity = 35,
|
|
|
|
usable = function () return current_wildfire_bomb == "pheromone_bomb" end,
|
|
start = function ()
|
|
removeBuff( "flame_infusion" )
|
|
if buff.mad_bombardier.up then
|
|
will_reset_wildfire_bomb = true
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
end,
|
|
impact = function ()
|
|
if will_reset_wildfire_bomb then
|
|
gainCharges( "wildfire_bomb", 1 )
|
|
will_reset_wildfire_bomb = nil
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
applyDebuff( "target", "pheromone_bomb" )
|
|
end,
|
|
|
|
copy = 270329,
|
|
|
|
unlisted = true,
|
|
},
|
|
|
|
|
|
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,
|
|
indicator = function () return debuff.latent_poison_injection.down and active_dot.latent_poison_injection > 0 and "cycle" 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,
|
|
|
|
velocity = 60,
|
|
|
|
start = function ()
|
|
removeBuff( "vipers_venom" )
|
|
end,
|
|
|
|
impact = function ()
|
|
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",
|
|
talent = "wildfire_infusion",
|
|
velocity = 35,
|
|
|
|
usable = function () return current_wildfire_bomb == "shrapnel_bomb" end,
|
|
start = function ()
|
|
removeBuff( "flame_infusion" )
|
|
if buff.mad_bombardier.up then
|
|
will_reset_wildfire_bomb = true
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
end,
|
|
impact = function ()
|
|
if will_reset_wildfire_bomb then
|
|
gainCharges( "wildfire_bomb", 1 )
|
|
will_reset_wildfire_bomb = nil
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
applyDebuff( "target", "shrapnel_bomb" )
|
|
end,
|
|
|
|
copy = 270338,
|
|
|
|
unlisted = true,
|
|
},
|
|
|
|
|
|
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",
|
|
talent = "wildfire_infusion",
|
|
velocity = 35,
|
|
|
|
usable = function () return current_wildfire_bomb == "volatile_bomb" end,
|
|
|
|
start = function ()
|
|
removeBuff( "flame_infusion" )
|
|
if buff.mad_bombardier.up then
|
|
will_reset_wildfire_bomb = true
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
end,
|
|
impact = function ()
|
|
if will_reset_wildfire_bomb then
|
|
gainCharges( "wildfire_bomb", 1 )
|
|
will_reset_wildfire_bomb = nil
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
applyDebuff( "target", "volatile_bomb" )
|
|
if debuff.serpent_sting.up then applyDebuff( "target", "serpent_sting" ) end
|
|
end,
|
|
|
|
copy = 271048,
|
|
|
|
unlisted = true,
|
|
},
|
|
|
|
|
|
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,
|
|
|
|
bind = function () return current_wildfire_bomb end,
|
|
velocity = 35,
|
|
|
|
start = function ()
|
|
removeBuff( "flame_infusion" )
|
|
if buff.mad_bombardier.up then
|
|
will_reset_wildfire_bomb = true
|
|
removeBuff( "mad_bombardier" )
|
|
end
|
|
end,
|
|
|
|
impact = function ()
|
|
if current_wildfire_bomb == "wildfire_bomb" then
|
|
if will_reset_wildfire_bomb then
|
|
gainCharges( "wildfire_bomb", 1 )
|
|
will_reset_wildfire_bomb = nil
|
|
end
|
|
applyDebuff( "target", "wildfire_bomb_dot" )
|
|
else class.abilities[ current_wildfire_bomb ].impact() end
|
|
current_wildfire_bomb = "wildfire_bomb"
|
|
end,
|
|
|
|
impactSpell = function ()
|
|
if not talent.wildfire_infusion.enabled then return "wildfire_bomb" end
|
|
if IsActiveSpell( 270335 ) then return "shrapnel_bomb" end
|
|
if IsActiveSpell( 270323 ) then return "pheromone_bomb" end
|
|
if IsActiveSpell( 271045 ) then return "volatile_bomb" end
|
|
return "wildfire_bomb"
|
|
end,
|
|
|
|
impactSpells = {
|
|
wildfire_bomb = true,
|
|
shrapnel_bomb = true,
|
|
pheromone_bomb = true,
|
|
volatile_bomb = true
|
|
},
|
|
|
|
copy = { 259495, 265157 } -- { 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:RegisterSetting( "allow_focus_overcap", false, {
|
|
name = "Allow Focus Overcap",
|
|
desc = "The default priority tries to avoid overcapping Focus by default. In simulations, this helps to avoid wasting Focus. In actual gameplay, this can " ..
|
|
"result in trying to use Focus spenders when other important buttons (Wildfire Bomb, Kill Command) are available to push. On average, enabling this feature " ..
|
|
"appears to be DPS neutral vs. the default setting, but has higher variance. Your mileage may vary.\n\n" ..
|
|
"The default setting is |cFFFFD100unchecked|r.",
|
|
type = "toggle",
|
|
width = 1.49
|
|
})
|
|
|
|
|
|
spec:RegisterPack( "Survival", 20220911, [[Hekili:T3vBZnooY5FlQ2A1iz7rJPS1mZUXsxT3Ejx2nBMKA9wvUpzkkjklEwIuHVypElv63EAaWxaa7gGKwEM9sDPsYoMKOrJgn6(PB0a6oN7(T7UDLxQ)DFA8LJhF5354mYX5Y3F1K7Un959(3D7EVLp4Dp8pc92b))Vnl(XGh92YEXZBJ8wXiqsuw8s4LFZX5Bst3N89V7D3hKUjBXOLr7ExsWUSTEPbrHlJ9wNY(7LV7UBxKfSn9NcVBbod4C3TEzPBIIH(my3pE3TBcwTYx85(jlR4KJZ)3Zct9Jp(Z36Vp1F3c4Fo3X5IJZze84pF8N)XOWh9JtpoFD0YSKJZJG)AP3(JZxUXF5dWdsJoop2pzV)s4Jc9FcEZwVe4fj(PPbH3d)R3DCEwIFXBzTZLtn3sI5)59ansGH5O7UDBqsAct0eM6b)NpXLZElzcbqCL67V1nn2B)D36h6TyR)Q7(Z3Lcsa2xv9KBxghadSaV7UT3X5lYwVE0tbBx5MSpaErYOy)DEbHaZD4GXx3h44OOTRIEkC0dbB36cZk78cxv8fvC26yF)FhgWcMd4OR(AZrPEXfmtk09B99E0VuGkXyLYw)49(HPUjS5nz(n1Bl88rBEEvSxI7c4XJYBoND4m7Jb79JtCF0pmANcZA4T3CC(9lxb90ZaZ5cS79(WmpWF2MpJ9cw56)iJP8wTkzK)Nz6mcrN(7k7TztbD7lfFeBi)OVRFO)Ua)83P3WLrWAJJZpdwmujJKNtSoj3z28JVqUewmff6XMgD9IJJEIXPx)QWPVybkOlhVkayw)vUGDdVSTmT1pnHKBlv(ztfRdI9DxeTBXO1zWsHy)LByArUPb7adoZooFcxhempbVnxbJ)8RL4aVyyDb0NVVTRlI9Hf9jBynG3nIoyeRZDtJCxfi4bhbte6)5u3NceS7(n(Xr7Ic9vxq3OXe5AMpqk0WOKy1NK9MDER49RhmH4hpkBF(7IseRKxhC)Mux5vVtuxyuY5mM5JTDguWCjURJf0K5Ec6dhKzQVJK2dooVZQZCTLoOmFC(qr7q9T1xWrzH(RJGX3OfE37gT2DxwyaBubm3)BwW(9WaPCCUY3lDJlipEi2BhB86Cj5aUIWHmpOH3)Kx8ZjC7(75R)3V3l2lnRQFeZLc35G89rpGoaDhTBHlyIEzuskZnBCWswhll8bviXF4YCrlCu7kG2WCvZ(CfF15dGenp1o0M2xfLokzdW6HGtEUsrAWYhGHbNNH5w2heWqSaAhUq79bth3pkjfaAXhmJfte1PJMphykRIpxKLcZCXpZzoAd6MzUECepWZdbrDkS(z8hDhVFjIYRdTLySLaGA54rt6GzcnJEVtXSRYy2GX26A0siE26fYg)UmTLheJnkBOYiv0fQL2cRlvXePfIBCBw4wgDOnnYjdmuEMbqzNx8dCIOW3jBI4oLC0TPjjjEg8FX)o8(N2IvpH6Q6uAd0SWTMvyPtSCHqFYz0y(xuZoh4xSWsgrdVMQHxzPHVV0kPb7Z9nqat(AgtBFu4qqX3BXI4s2jhFBjzdcxNXdgPeL7WxZ1FJ1bKB1vzx6Xs7pJ1T)ABnkLBntGke6FD05u5OwjMk8qGkcYrn(PEDRVhIV6D8vYU18aF3XR8JzEXxcGR19Vn2K9DdMtLcTLrfDJYDanQXO2iaR(rcrW7v8SZ1L0g26My7QA1)psV5JYcTkxjAcoDFdTzMgVJVs3EybjbVS3hfL4ZvhiAlv6babqAuCHZES2cJSfr77ukgmNdHbninc5(dLxeqnTCIuu5SeOKyshPiiQbvjeBeaKo6jD6X(OCq5NdQPEjSiTU3pKp84VaW68z(lzXCpSvCqd)0gLyMRAIoDRmbA1zcDeQgWeC6a1Qy6tbQNYyMgIzxmP8QfJMH4YnjxQftkLvlDZeQlXrs3JIgk27LvlDyHcDMb1ZAHktz67lnF50gme1IrUzs30G9mkMUX3fWc6fxez8uaFobBPhVRvXvoScVT7345Up2FLhWqkilkSwxsI1zXpRinvFJSCmxN)DCQGO2FC(BvTooSqStAU3y82KjSrlXd2mpznkotJ7z40hgPovJUg1l9m3r5rGPG5JP8(XIgtsDdgARL(ac)P6tnnyEyqBrKvOfk5nf38jxBHTzyXb7fC7pT(48NJYyYGW3aVFJ3JG05tv94BaI9B595X5)qrNEb4zpy3(Tpl0lpo))ag2hN)JIX9X5bf09jbDlhFrG27)MGhxhhTJ1XCkNen64CjUP5SsEtaFtzBxzMDIlLpbW)3cFarcOxSXNHqM1Qi4Z(pZvIoo)pdtuWZGg9RC7phNFBRt5thM(7WeFdIcyMyb9lXqJTqjovDXa50tufFOQEUHxlZLsV)0YN6lK(Fcs30mT1Oq2QgsfugVcFLxSVyXsXqbwXfbQQXpfW0ntsJ2Z2GzoXjP1YS4y)WQ9X2BNi)9mTFiAIS73i2k7KmWLzqy(AHIVITAqytER)Aoras6f(S4nkClJiGspJLxVUINTKeYwKyaYKqsgBfpX1YVCKEQc6zaLtrem297trvDCaeUP)ozas12btTyMVu(Jv2uwTpKo3AMh0sGQX3HYAPrtdlwD0pQH4jiV6w4lViBMsyFLHazJBvXTvM8QgaLelszAOt1rkOKvcs0cTpVw1J8NqfkLziAnF(bjfeYiy5z(kklnjyLVa7tzW5zGOdaHTpIzXPa3MhV(wkGw77DpyFKVQUK7ZBsz6fkNoY(9FFREQYOMrGL4HqaGBd4ETeHyQyA9Vcgx8247TIz9zf3QAEdy4d(V)rMTmEk5btKp5xcLHHHiDdZuh3W1EXMDWC7V0JxzobPVzf7pzMVygb37TB3Z59bJol940jg65aMjBE)YZ38YG1blfsPKrARUYLZbjUIEelXafd9)EuAw49(bXXUWigMka)8SOzLjj7BL31HPC8XsbCyY8vpjxHgdMtzlV1rkF1LLGOhGUniovkn6MWQ2qDt86WIQfJuIuKBJcrhtJfer12NvDCzY7QaSoYdmM)WZWFhQItWOWr(dRn(0ZKAx7MgMpdWUv4d(IYWHk3ZgjaheHl8gqcILzKgrKLRsWYgcTw7n89kRFPd1fbXRsyMwaFQpx4pT9z3HL4vS0F0agP3PMxssRY4rJyLz8DQQTDtEfTvMUKIg5bWNczlB5q(uxvKQnTRxFHulMOYhttSB1eDEUm4dtSA(PbwhGHim9TKLMuuhHGIc4Snny9D1ZQJc6HkfafNqFfkjuiOK85C5eGwmhueYc7FTnduR2MuIazKckNrIgY)SYVqDmZ)cDV4jz7GVYDVVEoFvsg(IO0u4nUIue)epYZOpheQ1MRLBZ6TaKjET9Q9v0PVUkQ4eioF()YLx6UyLsuAvnGQMhBQcPnvYWkTYdPWphUwx89jpnN8C4s3S9yR8SZby(DO5ktz4vb8abrBWGjnoIHNRAmPdauAjj2OcJqL(kBqISfqvLxC0etsU3NblaLKQw97FZFQzo4ZPmcCWxzbHyE51vmGT4TPdlIXJMU3R)ya8g16PsA4Md4GLZTQmk1z0gVeMZxx28uEzdHS6sRbfCJuUXkZvL6kmPuNHr3EsKECd5L6TPID4jhP6Lscxj4WKJ(QS8zINKAEj9xLfZpziI6tfJdQ(IHOCr1yWIyP)jJd61Kznt8XaBSYB5LXRCw)Lxwj4cIxnZgTFNC1(2CU8Klm)dLCqBodB5T5rJY4fT)gwBiRSoZB1ZQIv0UriqMroQ7t(MBSr63vw5X9SXJKdI8(czARUZonMf7dyHuD5PttPT8SoZADQHvulNBAgW8W9LRnxNc80X04H)mBSyhNkOgTMj0n1oUgw1yo3gnNvJM6A84o3ELMx0(Ff7rr9AAKwTCyJgaeOigy1bWanVDfSUv9jXbrbbLd2cCRuZMzVHOcc8H0Pdgu3DemuBZrR((GKrl9wUXNLalVLqOWXaE1uW0BswSFodGKeSXvXYv2QNy7gtXKfs2QCkuniA2q5K6ZzqlhqRbM1OSIrwF24eIrUP41R3gcLdh7kh2u(ELazGWfvJblIfRo5Amh0omY42CnZk2Cy3qVPgWcHhWHbU8Klm)dLC4ltiE0imqWiBa)XlfJSfV59SXJKdIViyK7SMsB5zsmYutnFzWiBjch7yKPh(TfJCtNkSIrgLqVqmY42LSIrg352R08YRbgzKbqdWiJ7aOryKX0N6og5gQD2amY2tL3ldgu3DeqHrE8FSXipgBx4TSFN23jwKDNxz)m)nELXuu0S8TLuuAFS9j(4CXEQXAkRwdHHcVGFdx6Z2NwwLoMZ8Wt3gXo2L86v0BBU7mVL8BkawjYTokEe2onZ30TelfTKLsK2WfEaYRZrsQ)4kDOZR)YaHfZjLlfAirLxmE9LvJ)AhOeQTyNSWW6LFq)vkTr5QHN4io(bjbNPZFoBqY1DrUym6tFFEmuQLALTw1Qi7NKTEMp97DBKFh9r6crYtEytgKpkmDEtE1fY5YzdxRknMhlTIA)ywlmgEM1tM2rQJJI22)tDAYO3))oVCFq3wXx4bL4gqrufEVeBc5IrQIEXrYOb2fBe9gp2zj1Pum1arWyBIGXsIa9BGk6Ckzz4xIylKdyDTNyrJYAb8BNSEKng3B0lqQE1lxQsWqdTiZVssMVeVeW74rPe5iMQu77wpCG014NDlw9nDBIqzkZM)Ob2pGCgWVOyb)Xi29Dy(jiWStolNRbloh6rC6ek4QtZX1(T2l0)Z4oIgAxJKFUVvneOEq8Oo19uhSDY5tl3kp9O0uW94PwDMuhzCd38sMcUOQA4IFER3dGZ9Tp4ZlrWW1GdQvvRZWkpUMCPmDQ796wzB7f7soOfdxwum9id3xvux(vD8mZRDaLOoqG)d4rkwsz3YL1jr)BcclXQL2EpQy5A4bDMdTJPQ)9UFMZTOisWh01sVbkHRKLIC3qznUYgETo(b648WhygolAe3pv9l1ENrO6EwrUzWCgQKRmvvAZ3vD1p1wkMWjUy)ipPzT4IvHqYrBDUlwGnnqPoEAMV(ioTh2V3kUZqTyeVu5dZYeHCKY0CtolGg386oHHZecTAVJyvXKYldNwRvZUR(wHwL71Cnb)1o(bJXp8EV793XEMS)PQ7AGYPXQ(v)SbI2r8zsK4mgjF4oxSnkAfxhdlTnTKyEHl9HjCVTLPjLEvwJiit2Y5WY8xu8MTSGetC)7zRUNj60SBy6GQLJsszHJPRf3sjL4wwf0Nx(GLWKnm2eQH1WHFLu)a2A8J5UGkciS0Ib2r)K23MHRz3XtKwTBBwyFe))AooXbYQSF4YIecKlTX6IA5OSCdgyNcLfbW8Y(SK0mWUHFCgp16QxtbLFwH1b3KOTpQVqs4nv)le7EIeQv5Jnd)(GL1LU8J00gVqWkbmH0VhjNHgTK9CT3GtEtbGbTlAbz8yfs51B9I9r)Kbu7NctoQ)MYtbRo(Kjk3mofso5dee5TmeN1AIePCKM1sjKgVED1LNem157Y(hGR42fwyLKaFlo7EGayrV2UGg)sWB1G(AiEUVg8NkidSifL97YzJvbaGo(ETX23Z3l58Q(jYN7rND6(aTn23i(rX4JaQ7BFYloKLlN7U9)5h(1p9tF6V(9hNFC(VXUIpc2TpkU4k94nIJu6ByNFrX2vYSBX8V4LLgTZJVnEmlmqC3Jo(Z)sadPIZ1Fp7khHFOizVN9tUb0SNdtzy5(2J8Zd5VK5bqHcEmGXAhNhbHl4XViDg8oqsnW5ZdlP34lpX0Z5urVJ)SfX3IO9Tu2D1PI3YP3ev69Mkds)T3iOM8JkC98gDY8(xoBDLb69MCyLL8uXFlZqJnrGooU(yh4Jgo3NVn4jTtb4eiONinaRjNZR8bhPHyv5v834I5RBq7hJ0(X5T)9sT)dN2HZh6WWXa70OHZ1nB6gICQDZ0oAM1Etj6SsEP6jKRdo12loX2U1T)0D6zDcijTLY)tWsTgYALx)aTKdBVXjpOp)x)V(fjw7N4CcR9FxrAxooN)tkf8A2nJq06awuzFdibQ9RGf7He)qy9nL82xUl(aw)kgcjJkLPNp9Df4VUGvButRaHDr0(P8Jz8f8d6708Sov)co4IQdqCXhv)Es4ILrHR4)gLmf72HaN1QUPeWFp1DKa(xxfMh(7lc)4IG1tBsOh4SC5UxijVNMN0ggL1UVO6JDxr1xuKBe3tuLKf6orAb4kun(6C6F5RY15Kmxx)QPIjz6PFfpj3KIcCtOLsvEEmYOgmYuN(dmKPJdh61KevC4alHk9LIJ5MRUC4Hddu7SzoIzoKRgcGc0CXqSrAcmRctR)fFqwatoEl5z5uC9aUkkBbiZbdnbBZVNofxRN7ZGh)RLD)X5)aR)znqCthglUgdZVBolQK0GK8j3TrS2WS8ScRB)lSUn)(enKNy1ibXs4KlFbEsrvlUyRVGy7yf04tbGAwyEFZ295eFwtsyxdI(p598f5VkjyhVFzbsk1TLg7dyt0ppsiDQeBGnqEk6Dzc)Tp6ZufkHaO)YCDc05jP6Of)(myMZLhoupY2BCEVY8O(TnKqZTaylJ90QY5(nrtSVv2JRs3EcBN1LVQJS)1aKo7FeeI3fIlQPPo1x7EZv9nDvszN8W)1i179YiVi(EdDXSXYer9MKs2D8cURwPD14cL9mrqAYk9mxzg7v3C)YvhoiTfKdv6uGPKZfowVIGQqyJZ6puaG1rtv9YHd8)88Q08Ct5UDCUZLdByV0OptsAGo(zEG0FHY(7qjjQV5bcjorPpP1fALUfrNG0QIQ8u)v4QPaMCfD0wCriNd1PpNHUbltDACGsDy3WbKcyrsnFCpN9jFxXCUZOjNHmVRG(8lvNwRw86MOaVijMEvRhJglvMCZk6BgDF6curSa(BhGON82QL5dzsMA2HA0YTE5B2B)bul86rENZBGVNvNAV15mB0RhnbbKHkad(yFA6WXU)pVU4B)1f)PWt2GEn2yyU)kmJGd5ZH)ZBQCKBQ8tXKuJNIQW5IEz9pBqlSpvrl99FTDKzqVA3O(SGh0EuvVv)I1Vv9xn7Qv0RHEJTId1yHsNBvKkyBuho9R3(AvaLUFsTyFW8Muuet1ajvN34zFWuLBy0XAHBzDMUaHROTuLR1SsuVgtrqRqky15QX7B9wRrup8Jm5SFnccfundy2QcQC8MLsgfsbCuvLlzbPMEdvRsPw24YksQLTtRELQnyKlUirAbAwDkntbHzoXkRGilmPgcLR0jurIfvFQOCG4KMLpmLIl6MXtAOgCU4SmDSxix0ntBun3WybHDXB(WLs5SXeOCH9yssE4azrfjWoIwird1hwYzr2S3mYml3x3LdJ1LCUjxQp8xvlnKhoO(KPoY5UC2eni4ftiaDViVIzMoEc1iqQmDA2OrQNV(meL2YyWRNbfgJxptBn3Hyn1ADl3VUDNQv6x9UdzhdegCJLl)LztFVI1zEwSSN)j6Fby7tNAkJzMsNh0CCZ9kJFMdpCG4S6nBkl5SAlhMIEytpBms)RdSOB8WhFjSaf(KwZfVmjb)WmP4oY2HlA2K(khTOzxJqwRQzYGbRV4yMZK(4f5D)MZN0QEkGKAxY9Y3IivxIt6GGT(jX6gheYultBdATgYKgRFmeCXILpMkZ)5Oy2Lfk2diKTjvsc81lnLvmr(Xob5vfNITYODWoYe9hWEfh5cmf5c9Np74HiYf3nJpCOElLbIysXGUp7HEilnpcQRpnB8OjTy5IYI6VfZwrBtKDzdTLoa6JoAFmjrr0J0jExTNlWCWB1AXoF7UZl(b82iL5D6iUOTNykxIyJM6lCflO7pazk1z04(AlMVMTOf5dVw)dVI4dFpSSNWOsF0gGzUtwvCqp0dHd0l5GlkLobHRZ4vTsoeJHNu9vBMG7erTPl389pQ)Goy7ZCUVOtNfBkU19gM5ldBUrL3)MNnQUIyGeKkcyIpsPBCIME)hY5rKDeTtZfin34gsHHg3CsUQAbGDyQCLxj9CMDBzjj3sm3Gp2jDmhDh2R6JNxg9YNiVpLtdWRs3v1HY1LXuPQhc79N3MkPQjzvz2hMGwCuYmys60MSVW9PrWw7fSupqCbWCE9l)LBMmSUZuesumMU(szMVj699ipyQy2D(amuPH2qfHbrGpdZ)ETeWAo0BqKIdGQDJdnXKX1RCaag3)6tQubelebkAHhAmMGBgFMH4bhQjBqlBdHuRn5CaBLWG2Suy8L1xkWJYBQtBxKGSW3rFLtJtOZlDjo24Ya3pgJ7hRZ9Tnxm1ViRuXTw3(FpKMu3oylLfx1EzbsxoKWWUUADRc9J3idqflvASLkg(Ip0OaPZqdUnpYIjb1hf6DtqFAZMg3UusBu4BdA)oxrDVviFP2eYZUAi2STZL6wXSHcgvaBikERbSx1RiwolJJJ9uLYWUxxUjp0OUCKRNMoORbXIgX)4rtWsYuUKvFIRfrEX)()ax7y9TINgThOak0snCIq2TlrTcoYiUedt1gN5mLoX2cY1sQ5)aoquB22rtjKivUZq0goBmQj18mAl0pmNLuHPJAP)TrZ(2NMRn(6IHI2UyeD1wBR)K36yYGIHqvBJIUnPvB9Vs5bv75A6vtUCiLwsfdwCunMQEc5YVw5ZpvCCHsBpVp17JZ1phEjk)uTK3z6NRdQoNUaLZpXtiK5KWP5kevhDWQt9NwNwoISCAwU5p1KSqi(Hdv(Gi2IwfyOqzuRHXVsYGxHXvZMzFDgoZE1NsrhB5)trEigKwE43L)zxqkcU81gQFxblmS)a0FApyq0RT8QxA5bL3CFP9HfD2Hdvpxs4Md4bFGWQ7uIETQbLeRiwYztr6PIxouVVk(cQby)xqp1Jw8s0zdm0BVDYnO)wCC4a6JNzGuF74HYZhuSWjro8fDmvjy1xsyGdRyFeYoSI)1)XlTVbA(2jZqhb9rF6ngO03oMTZIuSaoZXjQISTUP9(ME5SXx2X5TgYpYmIjXOZLNJlXmX9Ds7rVr8uhzA0mZO0TXspm23qBVrP2CmojEUPLSkKrsdt3c8PrsY)FqpVXO0FindvZX0ak7yd6PZgMMpNnzi1GLLzXgQiipggQSU1OFT25KS1MWgoSVSHrZ)GhPxov3mo)ICq7xROALDLtEkn0)WHMaYmwfiJnWf4ITUbKXgOjTpS(Cu9FTQODQE69lP3xfFb1a0KzwB9udaYOB3WqV1vN(OohRbOdJfojYHVOJPxbKVOUKubYG6RQtaziCm0JKfWzUtlqMwnV1q(bdidMy8vbidbCrdazWgnneiJnPNjGmiTTlazWwYsbKr3c8Prs(caYmUPaz0TJzcit95ZgcKXIIafqgYa07ItYwBctbiJTF5g)cbKPzvIe)Wv)f9NvrJmBYD3YoLnSl3)j8Ri27()(d]] )
|
|
|
|
|
|
end
|