|
|
|
|
-- HunterMarksmanship.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] Eagletalon's True Focus
|
|
|
|
|
-- [-] Surging Shots (passive/reactive)
|
|
|
|
|
-- [-] Serpentstalker's Trickery (passive/reactive)
|
|
|
|
|
-- [-] Secrets of the Unblinking Vigil (passive/reactive)
|
|
|
|
|
|
|
|
|
|
-- Conduits
|
|
|
|
|
-- [x] Brutal Projectiles
|
|
|
|
|
-- [-] Deadly Chain
|
|
|
|
|
-- [-] Powerful Precision
|
|
|
|
|
-- [x] Sharpshooter's Focus
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if UnitClassBase( "player" ) == "HUNTER" then
|
|
|
|
|
local spec = Hekili:NewSpecialization( 254, true )
|
|
|
|
|
|
|
|
|
|
spec:RegisterResource( Enum.PowerType.Focus, {
|
|
|
|
|
death_chakram = {
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
rapid_fire = {
|
|
|
|
|
channel = "rapid_fire",
|
|
|
|
|
|
|
|
|
|
last = function ()
|
|
|
|
|
local app = state.buff.casting.applied
|
|
|
|
|
local t = state.query_time
|
|
|
|
|
|
|
|
|
|
return app + floor( ( t - app ) / class.auras.rapid_fire.tick_time ) * class.auras.rapid_fire.tick_time
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
interval = function () return class.auras.rapid_fire.tick_time * ( state.buff.trueshot.up and 0.667 or 1 ) end,
|
|
|
|
|
value = 1,
|
|
|
|
|
}
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
-- Talents
|
|
|
|
|
spec:RegisterTalents( {
|
|
|
|
|
master_marksman = 22279, -- 260309
|
|
|
|
|
serpent_sting = 22501, -- 271788
|
|
|
|
|
a_murder_of_crows = 22289, -- 131894
|
|
|
|
|
|
|
|
|
|
careful_aim = 22495, -- 260228
|
|
|
|
|
barrage = 22497, -- 120360
|
|
|
|
|
explosive_shot = 22498, -- 212431
|
|
|
|
|
|
|
|
|
|
trailblazer = 19347, -- 199921
|
|
|
|
|
natural_mending = 19348, -- 270581
|
|
|
|
|
camouflage = 23100, -- 199483
|
|
|
|
|
|
|
|
|
|
steady_focus = 22267, -- 193533
|
|
|
|
|
streamline = 22286, -- 260367
|
|
|
|
|
chimaera_shot = 21998, -- 342049
|
|
|
|
|
|
|
|
|
|
born_to_be_wild = 22268, -- 266921
|
|
|
|
|
posthaste = 22276, -- 109215
|
|
|
|
|
binding_shackles = 23463, -- 321468
|
|
|
|
|
|
|
|
|
|
lethal_shots = 23063, -- 260393
|
|
|
|
|
dead_eye = 23104, -- 321460
|
|
|
|
|
double_tap = 22287, -- 260402
|
|
|
|
|
|
|
|
|
|
calling_the_shots = 22274, -- 260404
|
|
|
|
|
lock_and_load = 22308, -- 194595
|
|
|
|
|
volley = 22288, -- 260243
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
-- PvP Talents
|
|
|
|
|
spec:RegisterPvpTalents( {
|
|
|
|
|
dire_beast_basilisk = 825, -- 205691
|
|
|
|
|
dire_beast_hawk = 824, -- 208652
|
|
|
|
|
dragonscale_armor = 3600, -- 202589
|
|
|
|
|
hiexplosive_trap = 3605, -- 236776
|
|
|
|
|
hunting_pack = 3730, -- 203235
|
|
|
|
|
interlope = 1214, -- 248518
|
|
|
|
|
roar_of_sacrifice = 3612, -- 53480
|
|
|
|
|
scorpid_sting = 3604, -- 202900
|
|
|
|
|
spider_sting = 3603, -- 202914
|
|
|
|
|
survival_tactics = 3599, -- 202746
|
|
|
|
|
the_beast_within = 693, -- 212668
|
|
|
|
|
viper_sting = 3602, -- 202797
|
|
|
|
|
wild_protector = 821, -- 204190
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
-- Auras
|
|
|
|
|
spec:RegisterAuras( {
|
|
|
|
|
a_murder_of_crows = {
|
|
|
|
|
id = 131894,
|
|
|
|
|
duration = 15,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
aspect_of_the_turtle = {
|
|
|
|
|
id = 186265,
|
|
|
|
|
duration = 8,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
binding_shot = {
|
|
|
|
|
id = 117526,
|
|
|
|
|
duration = 8,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
bursting_shot = {
|
|
|
|
|
id = 186387,
|
|
|
|
|
duration = 6,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
camouflage = {
|
|
|
|
|
id = 199483,
|
|
|
|
|
duration = 60,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
concussive_shot = {
|
|
|
|
|
id = 5116,
|
|
|
|
|
duration = 6,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
dead_eye = {
|
|
|
|
|
id = 321461,
|
|
|
|
|
duration = 3,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
double_tap = {
|
|
|
|
|
id = 260402,
|
|
|
|
|
duration = 15,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
eagle_eye = {
|
|
|
|
|
id = 6197,
|
|
|
|
|
},
|
|
|
|
|
explosive_shot = {
|
|
|
|
|
id = 212431,
|
|
|
|
|
duration = 3,
|
|
|
|
|
type = "Magic",
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
feign_death = {
|
|
|
|
|
id = 5384,
|
|
|
|
|
duration = 360,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
freezing_trap = {
|
|
|
|
|
id = 3355,
|
|
|
|
|
duration = 60,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
hunters_mark = {
|
|
|
|
|
id = 257284,
|
|
|
|
|
duration = 3600,
|
|
|
|
|
type = "Magic",
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
lethal_shots = {
|
|
|
|
|
id = 260393,
|
|
|
|
|
duration = 3600,
|
|
|
|
|
},
|
|
|
|
|
lock_and_load = {
|
|
|
|
|
id = 194594,
|
|
|
|
|
duration = 15,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
lone_wolf = {
|
|
|
|
|
id = 164273,
|
|
|
|
|
duration = 3600,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
master_marksman = {
|
|
|
|
|
id = 269576,
|
|
|
|
|
duration = 12,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
misdirection = {
|
|
|
|
|
id = 34477,
|
|
|
|
|
duration = 8,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
pathfinding = {
|
|
|
|
|
id = 264656,
|
|
|
|
|
duration = 3600,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
posthaste = {
|
|
|
|
|
id = 118922,
|
|
|
|
|
duration = 4,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
precise_shots = {
|
|
|
|
|
id = 260242,
|
|
|
|
|
duration = 15,
|
|
|
|
|
max_stack = 2,
|
|
|
|
|
},
|
|
|
|
|
rapid_fire = {
|
|
|
|
|
id = 257044,
|
|
|
|
|
duration = function () return 2 * haste end,
|
|
|
|
|
tick_time = function ()
|
|
|
|
|
return ( 2 * haste ) / ( buff.double_tap.up and 14 or 7 )
|
|
|
|
|
end,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
serpent_sting = {
|
|
|
|
|
id = 271788,
|
|
|
|
|
duration = 18,
|
|
|
|
|
type = "Poison",
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
steady_focus = {
|
|
|
|
|
id = 193534,
|
|
|
|
|
duration = 15,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
streamline = {
|
|
|
|
|
id = 342076,
|
|
|
|
|
duration = 15,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
survival_of_the_fittest = {
|
|
|
|
|
id = 281195,
|
|
|
|
|
duration = 6,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
tar_trap = {
|
|
|
|
|
id = 135299,
|
|
|
|
|
duration = 30,
|
|
|
|
|
max_stack = 1
|
|
|
|
|
},
|
|
|
|
|
trailblazer = {
|
|
|
|
|
id = 231390,
|
|
|
|
|
duration = 3600,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
trick_shots = {
|
|
|
|
|
id = 257622,
|
|
|
|
|
duration = 20,
|
|
|
|
|
max_stack = 2,
|
|
|
|
|
},
|
|
|
|
|
trueshot = {
|
|
|
|
|
id = 288613,
|
|
|
|
|
duration = function () return ( legendary.eagletalons_true_focus.enabled and 18 or 15 ) * ( 1 + ( conduit.sharpshooters_focus.mod * 0.01 ) ) end,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
volley = {
|
|
|
|
|
id = 260243,
|
|
|
|
|
duration = 6,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Legendaries
|
|
|
|
|
nessingwarys_trapping_apparatus = {
|
|
|
|
|
id = 336744,
|
|
|
|
|
duration = 5,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
copy = { "nesingwarys_trapping_apparatus", "nesingwarys_apparatus", "nessingwarys_apparatus" }
|
|
|
|
|
},
|
|
|
|
|
secrets_of_the_unblinking_vigil = {
|
|
|
|
|
id = 336892,
|
|
|
|
|
duration = 20,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
-- stub.
|
|
|
|
|
eagletalons_true_focus_stub = {
|
|
|
|
|
duration = 10,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
copy = "eagletalons_true_focus"
|
|
|
|
|
}
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spec:RegisterStateExpr( "ca_execute", function ()
|
|
|
|
|
return talent.careful_aim.enabled and ( target.health.pct > 70 )
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
spec:RegisterStateExpr( "ca_active", function ()
|
|
|
|
|
return talent.careful_aim.enabled and ( target.health.pct > 70 )
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local steady_focus_applied = 0
|
|
|
|
|
|
|
|
|
|
spec:RegisterCombatLogEvent( function( _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName )
|
|
|
|
|
|
|
|
|
|
if sourceGUID == state.GUID and ( subtype == "SPELL_AURA_APPLIED" or subtype == "SPELL_AURA_REFRESH" or subtype == "SPELL_AURA_APPLIED_DOSE" ) and spellID == 193534 then -- Steady Aim.
|
|
|
|
|
steady_focus_applied = GetTime()
|
|
|
|
|
end
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
spec:RegisterStateExpr( "last_steady_focus", function ()
|
|
|
|
|
return steady_focus_applied
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local ExpireNesingwarysTrappingApparatus = setfenv( function()
|
|
|
|
|
focus.regen = focus.regen * 0.5
|
|
|
|
|
forecastResources( "focus" )
|
|
|
|
|
end, state )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spec:RegisterStateTable( "tar_trap", setmetatable( {}, {
|
|
|
|
|
__index = function( t, k )
|
|
|
|
|
return state.debuff.tar_trap[ k ]
|
|
|
|
|
end
|
|
|
|
|
} ) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Tier 28
|
|
|
|
|
spec:RegisterSetBonuses( "tier28_2pc", 364491, "tier28_4pc", 363666 )
|
|
|
|
|
-- 2-Set - Focused Trickery - Trick Shots now also increases the damage of the affected shot by 30%.
|
|
|
|
|
-- 4-Set - Focused Trickery - Spending 40 Focus grants you 1 charge of Trick Shots.
|
|
|
|
|
|
|
|
|
|
local focusSpent = 0
|
|
|
|
|
|
|
|
|
|
local FOCUS = Enum.PowerType.Focus
|
|
|
|
|
local lastFocus = -1
|
|
|
|
|
|
|
|
|
|
spec:RegisterUnitEvent( "UNIT_POWER_FREQUENT", "player", nil, function( event, unit, powerType )
|
|
|
|
|
if powerType == "FOCUS" and state.set_bonus.tier28_4pc > 0 then
|
|
|
|
|
local current = UnitPower( "player", FOCUS )
|
|
|
|
|
|
|
|
|
|
if current < lastFocus then
|
|
|
|
|
focusSpent = ( focusSpent + lastFocus - current ) % 40
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
lastFocus = current
|
|
|
|
|
end
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
spec:RegisterStateExpr( "focused_trickery_count", function ()
|
|
|
|
|
return focusSpent
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
spec:RegisterHook( "spend", function( amt, resource )
|
|
|
|
|
if set_bonus.tier28_4pc > 0 and resource == "focus" then
|
|
|
|
|
focused_trickery_count = focused_trickery_count + amt
|
|
|
|
|
if focused_trickery_count >= 40 then
|
|
|
|
|
applyBuff( "trick_shots" )
|
|
|
|
|
focused_trickery_count = focused_trickery_count % 40
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
local initialized = false
|
|
|
|
|
local setActive = false
|
|
|
|
|
local wasOutdoors = false
|
|
|
|
|
local focusedTrickeryCount = 0
|
|
|
|
|
|
|
|
|
|
local tricksApplied = 0
|
|
|
|
|
local tricksRemoved = 0
|
|
|
|
|
|
|
|
|
|
local vigilApplied = 0
|
|
|
|
|
local vigilRemoved = 0
|
|
|
|
|
|
|
|
|
|
local doubleApplied = 0
|
|
|
|
|
local doubleRemoved = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local gearCheck = {
|
|
|
|
|
PLAYER_ENTERING_WORLD = 1,
|
|
|
|
|
PLAYER_EQUIPMENT_CHANGED = 1,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local resets = {
|
|
|
|
|
PLAYER_ENTERING_WORLD = 1,
|
|
|
|
|
ZONE_CHANGED_NEW_AREA = 1,
|
|
|
|
|
FOG_OF_WAR_UPDATED = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local cleuEvents = {
|
|
|
|
|
SPELL_AURA_APPLIED = 1,
|
|
|
|
|
SPELL_AURA_APPLIED_DOSE = 1,
|
|
|
|
|
SPELL_AURA_REMOVED_DOSE = 1,
|
|
|
|
|
SPELL_CAST_START = 1,
|
|
|
|
|
SPELL_CAST_SUCCESS = 1,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local ft = CreateFrame( "Frame" )
|
|
|
|
|
|
|
|
|
|
ft:SetScript( "OnEvent", function( self, event, ... )
|
|
|
|
|
if gearCheck[ event ] then
|
|
|
|
|
if not initialized then
|
|
|
|
|
gearCheck.PLAYER_ENTERING_WORLD = nil
|
|
|
|
|
initialized = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local hasSet = GetPlayerAuraBySpellID( 363666 ) ~= nil
|
|
|
|
|
|
|
|
|
|
if hasSet ~= setActive then
|
|
|
|
|
setActive = hasSet
|
|
|
|
|
focusedTrickeryCount = 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if not setActive then return end
|
|
|
|
|
|
|
|
|
|
if event == "UNIT_DIED" then
|
|
|
|
|
if UnitIsUnit( ..., "player" ) then
|
|
|
|
|
focusedTrickeryCount = 0
|
|
|
|
|
end
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if resets[ event ] then
|
|
|
|
|
local isOutdoors = IsOutdoors()
|
|
|
|
|
|
|
|
|
|
if event == "FOG_OF_WAR_UPDATED" then
|
|
|
|
|
if isOutdoors ~= wasOutdoors then
|
|
|
|
|
wasOutdoors = isOutdoors
|
|
|
|
|
focusedTrickeryCount = 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wasOutdoors = isOutdoors
|
|
|
|
|
focusedTrickeryCount = 0
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if event == "COMBAT_LOG_EVENT_UNFILTERED" then
|
|
|
|
|
local _, subtype, _, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName, _, amount, interrupt, a, b, c, d, offhand, multistrike = CombatLogGetCurrentEventInfo()
|
|
|
|
|
|
|
|
|
|
if subtype == "UNIT_DIED" and destGUID == state.GUID then
|
|
|
|
|
focusedTrickeryCount = 0
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local now = GetTime()
|
|
|
|
|
end
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
spec:RegisterHook( "reset_precast", function ()
|
|
|
|
|
if now - action.serpent_sting.lastCast < gcd.execute * 2 and target.unit == action.serpent_sting.lastUnit then
|
|
|
|
|
applyDebuff( "target", "serpent_sting" )
|
|
|
|
|
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 legendary.eagletalons_true_focus.enabled then
|
|
|
|
|
rawset( buff, "eagletalons_true_focus", buff.trueshot_aura )
|
|
|
|
|
else
|
|
|
|
|
rawset( buff, "eagletalons_true_focus", buff.eagletalons_true_focus_stub )
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if now - action.volley.lastCast < 6 then applyBuff( "volley", 6 - ( now - action.volley.lastCast ) ) end
|
|
|
|
|
|
|
|
|
|
if now - action.resonating_arrow.lastCast < 6 then applyBuff( "resonating_arrow", 10 - ( now - action.resonating_arrow.lastCast ) ) end
|
|
|
|
|
|
|
|
|
|
last_steady_focus = nil
|
|
|
|
|
focused_trickery_count = nil
|
|
|
|
|
end )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Abilities
|
|
|
|
|
spec:RegisterAbilities( {
|
|
|
|
|
a_murder_of_crows = {
|
|
|
|
|
id = 131894,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 60,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 20 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 645217,
|
|
|
|
|
|
|
|
|
|
talent = "a_murder_of_crows",
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "a_murder_of_crows" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
aimed_shot = {
|
|
|
|
|
id = 19434,
|
|
|
|
|
cast = function ()
|
|
|
|
|
if buff.lock_and_load.up then return 0 end
|
|
|
|
|
return 2.5 * haste * ( buff.trueshot.up and 0.5 or 1 ) * ( buff.streamline.up and 0.7 or 1 )
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
charges = 2,
|
|
|
|
|
cooldown = function () return haste * ( buff.trueshot.up and 4.8 or 12 ) end,
|
|
|
|
|
recharge = function () return haste * ( buff.trueshot.up and 4.8 or 12 ) end,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function ()
|
|
|
|
|
if buff.lock_and_load.up or buff.secrets_of_the_unblinking_vigil.up then return 0 end
|
|
|
|
|
return ( ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 35 )
|
|
|
|
|
end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 135130,
|
|
|
|
|
|
|
|
|
|
cycle = function () return runeforge.serpentstalkers_trickery.enabled and "serpent_sting" or nil end,
|
|
|
|
|
|
|
|
|
|
usable = function ()
|
|
|
|
|
if action.aimed_shot.cast > 0 and moving and settings.prevent_hardcasts then return false, "prevent_hardcasts is checked and player is moving" end
|
|
|
|
|
return true
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "precise_shots" )
|
|
|
|
|
removeBuff( "double_tap" )
|
|
|
|
|
if buff.volley.down and buff.trick_shots.up then removeBuff( "trick_shots" ) end
|
|
|
|
|
if action.aimed_shot.cost == 0 and set_bonus.tier28_4pc > 0 then
|
|
|
|
|
focused_trickery_count = focused_trickery_count + ( ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 35 )
|
|
|
|
|
if focused_trickery_count >= 40 then
|
|
|
|
|
applyBuff( "trick_shots" )
|
|
|
|
|
focused_trickery_count = focused_trickery_count % 40
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if buff.lock_and_load.up then removeBuff( "lock_and_load" )
|
|
|
|
|
elseif buff.secrets_of_the_unblinking_vigil.up then removeBuff( "secrets_of_the_unblinking_vigil" ) end
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
arcane_shot = {
|
|
|
|
|
id = 185358,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 20 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 132218,
|
|
|
|
|
|
|
|
|
|
notalent = "chimaera_shot",
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
if talent.calling_the_shots.enabled then cooldown.trueshot.expires = max( 0, cooldown.trueshot.expires - 2.5 ) end
|
|
|
|
|
removeStack( "precise_shots" )
|
|
|
|
|
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 = "off",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 132242,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "aspect_of_the_cheetah" )
|
|
|
|
|
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 = "off",
|
|
|
|
|
|
|
|
|
|
toggle = "defensives",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 132199,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "aspect_of_the_turtle" )
|
|
|
|
|
setCooldown( "global_cooldown", 5 )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
barrage = {
|
|
|
|
|
id = 120360,
|
|
|
|
|
cast = 3,
|
|
|
|
|
channeled = true,
|
|
|
|
|
cooldown = 20,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 30 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 236201,
|
|
|
|
|
|
|
|
|
|
talent = "barrage",
|
|
|
|
|
|
|
|
|
|
start = function ()
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
binding_shot = {
|
|
|
|
|
id = 109248,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 45,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 462650,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "binding_shot" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bursting_shot = {
|
|
|
|
|
id = 186387,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 30,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 10 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 1376038,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "bursting_shot" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
camouflage = {
|
|
|
|
|
id = 199483,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 60,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 461113,
|
|
|
|
|
|
|
|
|
|
usable = function () return time == 0 end,
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "camouflage" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
concussive_shot = {
|
|
|
|
|
id = 5116,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 5,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 135860,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "concussive_shot" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
chimaera_shot = {
|
|
|
|
|
id = 342049,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 20 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 236176,
|
|
|
|
|
|
|
|
|
|
talent = "chimaera_shot",
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
if talent.calling_the_shots.enabled then cooldown.trueshot.expires = max( 0, cooldown.trueshot.expires - 2.5 ) end
|
|
|
|
|
removeStack( "precise_shots" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
counter_shot = {
|
|
|
|
|
id = 147362,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 24,
|
|
|
|
|
gcd = "off",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 249170,
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
disengage = {
|
|
|
|
|
id = 781,
|
|
|
|
|
cast = 0,
|
|
|
|
|
charges = 1,
|
|
|
|
|
cooldown = 20,
|
|
|
|
|
recharge = 20,
|
|
|
|
|
gcd = "off",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 132294,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
if talent.posthaste.enabled then applyBuff( "posthaste" ) end
|
|
|
|
|
if conduit.tactical_retreat.enabled and target.within8 then applyDebuff( "target", "tactical_retreat" ) end
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double_tap = {
|
|
|
|
|
id = 260402,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 60,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
toggle = "cooldowns",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 537468,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "double_tap" )
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
explosive_shot = {
|
|
|
|
|
id = 212431,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 30,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 20 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 236178,
|
|
|
|
|
|
|
|
|
|
talent = "explosive_shot",
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "explosive_shot" )
|
|
|
|
|
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,
|
|
|
|
|
}, ]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--[[ flare = {
|
|
|
|
|
id = 1543,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 20,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 135815,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
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 = true,
|
|
|
|
|
texture = 135834,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "freezing_trap" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hunters_mark = {
|
|
|
|
|
id = 257284,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 236188,
|
|
|
|
|
|
|
|
|
|
usable = function () return debuff.hunters_mark.down end,
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "hunters_mark" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
masters_call = {
|
|
|
|
|
id = 272682,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 45,
|
|
|
|
|
gcd = "off",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 236189,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "masters_call" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
misdirection = {
|
|
|
|
|
id = 34477,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 30,
|
|
|
|
|
gcd = "off",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 132180,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "misdirection" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
multishot = {
|
|
|
|
|
id = 257620,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 20 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 132330,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
if talent.calling_the_shots.enabled then cooldown.trueshot.expires = max( 0, cooldown.trueshot.expires - 2.5 ) end
|
|
|
|
|
if active_enemies > 2 then applyBuff( "trick_shots" ) end
|
|
|
|
|
removeStack( "precise_shots" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rapid_fire = {
|
|
|
|
|
id = 257044,
|
|
|
|
|
cast = function () return ( 2 * haste ) end,
|
|
|
|
|
channeled = true,
|
|
|
|
|
cooldown = function () return ( buff.trueshot.up and 8 or 20 ) * haste end,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = 0,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 461115,
|
|
|
|
|
|
|
|
|
|
start = function ()
|
|
|
|
|
applyBuff( "rapid_fire" )
|
|
|
|
|
if talent.streamline.enabled then applyBuff( "streamline" ) end
|
|
|
|
|
removeBuff( "brutal_projectiles" )
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
finish = function ()
|
|
|
|
|
if buff.volley.down then removeBuff( "trick_shots" ) end
|
|
|
|
|
removeBuff( "double_tap" )
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
auras = {
|
|
|
|
|
-- Conduit
|
|
|
|
|
brutal_projectiles = {
|
|
|
|
|
id = 339929,
|
|
|
|
|
duration = 3600,
|
|
|
|
|
max_stack = 1,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serpent_sting = {
|
|
|
|
|
id = 271788,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return ( legendary.eagletalons_true_focus.enabled and buff.trueshot.up and 0.75 or 1 ) * 10 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 1033905,
|
|
|
|
|
|
|
|
|
|
velocity = 45,
|
|
|
|
|
|
|
|
|
|
talent = "serpent_sting",
|
|
|
|
|
|
|
|
|
|
impact = function ()
|
|
|
|
|
applyDebuff( "target", "serpent_sting" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
steady_shot = {
|
|
|
|
|
id = 56641,
|
|
|
|
|
cast = 1.8,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = function () return buff.trueshot.up and -15 or -10 end,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 132213,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
if talent.steady_focus.enabled and prev[1].steady_shot and action.steady_shot.lastCast > last_steady_focus then
|
|
|
|
|
applyBuff( "steady_focus" )
|
|
|
|
|
last_steady_focus = query_time
|
|
|
|
|
end
|
|
|
|
|
if debuff.concussive_shot.up then debuff.concussive_shot.expires = debuff.concussive_shot.expires + 3 end
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
summon_pet = {
|
|
|
|
|
id = 883,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 0,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
essential = true,
|
|
|
|
|
|
|
|
|
|
texture = function () return GetStablePetInfo(1) or 'Interface\\ICONS\\Ability_Hunter_BeastCall' end,
|
|
|
|
|
nomounted = true,
|
|
|
|
|
|
|
|
|
|
usable = function () return false and not pet.exists end, -- turn this into a pref!
|
|
|
|
|
handler = function ()
|
|
|
|
|
summonPet( "made_up_pet", 3600, "ferocity" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
survival_of_the_fittest = {
|
|
|
|
|
id = function () return pet.exists and 264735 or 281195 end,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 180,
|
|
|
|
|
gcd = "off",
|
|
|
|
|
known = function ()
|
|
|
|
|
if not pet.exists then return 155228 end
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
toggle = "defensives",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
|
|
|
|
|
usable = function ()
|
|
|
|
|
return not pet.exists or pet.alive, "requires either no pet or a living pet"
|
|
|
|
|
end,
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "survival_of_the_fittest" )
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
copy = { 264735, 281195, 155228 }
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = true,
|
|
|
|
|
texture = 576309,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyDebuff( "target", "tar_trap" )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trueshot = {
|
|
|
|
|
id = 288613,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 120,
|
|
|
|
|
gcd = "off",
|
|
|
|
|
|
|
|
|
|
spend = 0,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
toggle = "cooldowns",
|
|
|
|
|
|
|
|
|
|
startsCombat = false,
|
|
|
|
|
texture = 132329,
|
|
|
|
|
|
|
|
|
|
nobuff = function ()
|
|
|
|
|
if settings.trueshot_vop_overlap then return end
|
|
|
|
|
return "trueshot"
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
focus.regen = focus.regen * 1.5
|
|
|
|
|
reduceCooldown( "aimed_shot", ( 1 - 0.3077 ) * 12 * haste )
|
|
|
|
|
reduceCooldown( "rapid_fire", ( 1 - 0.3077 ) * 20 * haste )
|
|
|
|
|
applyBuff( "trueshot" )
|
|
|
|
|
|
|
|
|
|
if azerite.unerring_vision.enabled then
|
|
|
|
|
applyBuff( "unerring_vision" )
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
meta = {
|
|
|
|
|
duration_guess = function( t )
|
|
|
|
|
return talent.calling_the_shots.enabled and 90 or t.duration
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
volley = {
|
|
|
|
|
id = 260243,
|
|
|
|
|
cast = 0,
|
|
|
|
|
cooldown = 45,
|
|
|
|
|
gcd = "spell",
|
|
|
|
|
|
|
|
|
|
spend = 0,
|
|
|
|
|
spendType = "focus",
|
|
|
|
|
|
|
|
|
|
startsCombat = true,
|
|
|
|
|
texture = 132205,
|
|
|
|
|
|
|
|
|
|
talent = "volley",
|
|
|
|
|
|
|
|
|
|
handler = function ()
|
|
|
|
|
applyBuff( "volley" )
|
|
|
|
|
applyBuff( "trick_shots", 6 )
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spec:RegisterOptions( {
|
|
|
|
|
enabled = true,
|
|
|
|
|
|
|
|
|
|
aoe = 3,
|
|
|
|
|
|
|
|
|
|
nameplates = false,
|
|
|
|
|
nameplateRange = 8,
|
|
|
|
|
|
|
|
|
|
damage = true,
|
|
|
|
|
damageExpiration = 6,
|
|
|
|
|
|
|
|
|
|
potion = "spectral_agility",
|
|
|
|
|
|
|
|
|
|
package = "Marksmanship",
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spec:RegisterSetting( "prevent_hardcasts", false, {
|
|
|
|
|
name = "Prevent Hardcasts of |T135130:0|t Aimed Shot During Movement",
|
|
|
|
|
desc = "If checked, the addon will not recommend |T135130:0|t Aimed Shot if it has a cast time and you are moving.",
|
|
|
|
|
type = "toggle",
|
|
|
|
|
width = "full"
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
spec:RegisterSetting( "eagletalon_swap", false, {
|
|
|
|
|
name = "Use |T132329:0|t Trueshot with Eagletalon's True Focus Runeforge",
|
|
|
|
|
desc = "If checked, the default priority includes usage of |T132329:0|t Trueshot pre-pull, assuming you will successfully swap " ..
|
|
|
|
|
"your legendary on your own. The addon will not tell you to swap your gear.",
|
|
|
|
|
type = "toggle",
|
|
|
|
|
width = "full",
|
|
|
|
|
} )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spec:RegisterPack( "Marksmanship", 20220821, [[Hekili:D3ZAtoUnY9BzkxMRONXAL48y31rsx5yN6I3SzZv34QY9jjXHcAeZkrQJpMzLlv83EAa(caSXd9y2XjPsDRhsGUB0VrZgqtho93NE)c)mY0p7nWZBW79g2F4hg((BF307Z2TLm9(T(bFX)r4)iYFd8)(F6N8L0n(rPRc3sF5U1X(lOajnopjagW3vmFvw220F6TV9XWSv5p0piEZBtd3KV2plmokiXFzg9VdE707FipCD2Vfn9bCI4MP37NNTkoz693hU5xME)QWfliLdNKgisnfZ)3ZJYijfF8NZFmpnRyU3GRO)pEEfFS4J)Yk)OhjP)uXh)XI5FM88Y48OffZ)7K041prkMhMwmpkgMLFX8nKay0HbfZZwbVYFXI4OI5b(rV95W1RH37hbSK(mqbayxuazrZW2MegNeMTRy(ZW6VyoLYlM)Z)Tpvo(praC8FSljeO6I5lyZMHNWKI5)YVcplnEdjlCdjT)07xhMMLszVzjHbFjDvm7V(mtSrI8FynzX0)1P3haiKaGegN)Asuw)0mI)IDZwghKN2VAGfZDGLz0SLRdFCvg7VEiF5sXXMq24hsPSrfZVfy)buzgiDlhdLaMMbIjL4pjpISmob4oBJZdwnlE5Se))ioz2Ye)h3aKMi5WiGLR93rssNTbKM9Z32I1VaC7gCE9zaNTGMHZfna)gLaVhi4JFcEfWv)ctSXi8G441lIFocyyPXrGMD0JZ8tsIFwGd(yaSm3VVy(f4qH)XruPYSL(KYzG9Cyg94qnOmcRGTHaTMIJwddDsX8Rhum3TCWz(almRpv1Bww8SfHegWgoqcwQxXtkhnqMu28tKzKiYMqsfMyiQCjaR7e)WfZiprvwbdhqc9vQQEjQKFhpc(GAgQBR4DrCoikNL5VLkDV1cvhW)1A2)1mYMhaTrb1uG1mllXFBxUmVQaOtLqKhslnvdekfDNefXPwMqeTNRWC(wgYmtWuNgrKzum7DlfxVJIRAeq(621XPuzdt1NJgGr(E(rYRYinUpOKFAHschNRutOYLLiL1Y(PsBMBIhwhhVyn4zNXlCvRhCyARm4hNMYOOLmJnfobF2pCDdCO8HHd072OIeEkE9AYoLogQw)vJsyDRYK07SAl1XyDC3PfaHlHyg)aeqvWqtM9YylQdpXeKDeju5jUWSfrLShg494vtFaabl)ebn0HQJwG5hUxLkMskZE1jxTUVzyrWzClgQMaLNVAxImyibjXRJtwyuH1JtJnljNuhIBO6yCCovYtEKU2yzAi4cS3HWe0zz2QX36KUftUTSjwkpvuslcaDtYxjb5zWedPzK2Oj6Vfuzxgc(pPRwzF(1dZhMuvCFrZv7Xz56GLVeak2uij7MvzIaSGbCMNmWUnHeeMsQamLhwbJCibNeA2Mu)4LWEentZ0SQ)6soFfvuyPiTrXjLKn7H4ii3TSqsI37NDZ2a5qfGYdjlLMyeKO5S8Oha)yFHk(Ek8XW1CCFGNSlGjtOoEsPzAszMYHRAzCmUaJmzeDc5rseBnuMo5g)VYfuM4NTAgSy)sI)ggCFNv(pnQUjUyXvHnOsA78)wO6(E9Up5bERQeIEwvkdvIOj0fpDBrxw6XpoQFRTq)Yxjhtoyv4gFsIpsizfz41UOGn8Lf248rDkdNlcxMGaDWBAPgHvcBlmQJDZOiqzfcaUJWyXk2sI3q(ir(Z2KNSGKqnZaN1plN1KNqCl(nGino5yxnBcJKSfKkZsPMcc(VjlbBKv0jGBa7P23)HXKT2S8wRstxqhXZM00JiPPagF2pzxklX4Tm8VDRFIFwoYg94Z62tTFStadaVN8h0X0Gg1U1eDHlQA9G)Jmp0SD6ZGJAhb0K)FimAr)Tq(W5G8MKKVLj14JzRdBlxdpLvmggQ(aVUj)U9f0nZOoXx6dsTMQq0yGfZQ(cQcTc9zXPGMocz7Q8)iD22K4G1(B8fxHSOF1mIOWD(G8cuoHHhhMkpqMMB0I8Wmqp9jy)s(RPCBapza6eyBIHd0scUC7266byLPOnvm)O)zoSbI)Oo4szrSsc3woG)Amy5Tcy8W)qRm1V3mbinGp)3(fi4rPRTRkM)m8OfXrVjJ(p0QhrREfqVfZ3wwlfq2tc8H8tkMhM9Mf0)egwmm20T(B2SRchu4e4ZGtcG5W17QWlDCGh5L0AGr1IO1IQvaDrZotcbgddJ6lII2kO0OG24)WU6ROY)IoyZP85doYl)Jz0QSvwRTzLv5eSbJ(c19jsXdScaXqEwqGGOzGiq3(91cKGfPn7FhLTIeY7AQ1l4bHgZ1s0KM1S3FRWc4D37WXcxbmz(rOr8J38GFxpjpeNLbeXSYiKpZ8Sg)1WimVkiEZehLnvnuDLuWcIiRLtxi15Rp9(Hd4Y3TTiu6zNd1QmRQebykN61n4sW7qqeEcFJKlfa3oRq041RpX5Jgj)CfuLlAEFJzQNyHYy6DuJkTvqVh2gTC0vGahSKCAwrQbwN6a4Gx3a3UChJfjWfjbG6DmQP4bdVwTKWepOl0EN4ocO2wKe6(oXYkqvssDkbt34fv1X20A7oosHwlXzlZt2P3jX3asXpkGaotH0rO(p1hh9fIC(aNJuytOmMJEVl6YSK95LsN9)KVG9Xx07ma16OhAfFl9eWs7astAD2Q(BdYk9d1w3nDfg7UZQUTOZVTXS)L5IPj7be)mXBP7JlRDIp5duWd0nU9K)6CIPsKkZVyaOoq(UOGz5BXmUmJ2dMLGRlQi0IwYoljMMsCl1lBpwr9HlXPFma1KVNEDw2IFgzDkJdOWmA2JWFNYXPmMA6O)IgRYkWHyO)sSol51VaRsmhe2Uauq5Dk()lcHdEfTt8O2RvpMxKk78(zd7Vc27jKQ)mkVxkOmNvG0eQjbUQfxZT6lAuyrIB1G2ZsAP7CAjhMN22xYXr526LYvFdPQLM4MEd8xKNW2FDzTsXOG2r4IsfTRbdSfNZgfCHnsnD0rptKYpYkN2iE8WzavsfkE1etW(TLzX3rMBGkp7mZ)uXhKKzyM36xncRxu852zjlyNb7zrKTIIMsgYeLRAhLVzKjq)2MnLDHjAu5IOcxiITUbWKiwSbmPmrVZLMYHsZYeRrrd9ltDPojG(L7PRn3fcCnoHfl)jMiXJuuOA1QhqJ6KfUrnMlnbZjDGPSgpEWTxi5I0)p3gEK7aefeGRvlafzr0ZyaGEsr7QjDJ6tLFqiKSCWmWncntU9Crze4lPZxAqhFGa3cHU5HB8HP9d8dwrOFPc)G)zoS5CAdhq8tZtiTARSm(BE)Z(rlkBrk(V(adMd1xp5E6vcmMwRmd8mMwRTPy3DokKNdnlpnPV8cLxacv0UgmWwmgxYAk4WsRf3nPEsXumwldaQj9f89iOHkp7mZ)uXh(2SRm1jfGKwRMugo10Anea(ct0OYfX3K0ApAnLdLMvMwRkrZ3M0AnSPeZP1QE5FOP1AROWyATOa6etRf3VKX0AXdU9cjxEjsRfzbyrAT4baSkTwm9PJpTwl1oTiTwZvF70sd64deOkTwVZEATEynWGqZ187SoKjDvC(6ffZz9fJFe4NN1NgfZjao2ULovyqzaAVc(3WOac9dkrpexvicE66yAN17NqHW6QOf(bLTY0cwt40VL(OIfi56nv98qAM(p9SPdVvp6PlJ80Shdw0FyFUpTn7Tm2L6dZvjBT7GkvkAKuSb0P05TAoywzUQ(E7InPrBVtABpA0tPjnNwRPdAIRAcxYRXR(rWs3Nm(wrZPd5mFiz1iE4Ou)1MpMZEuBd54x2nZ20uNVcN9Q6xO98qzx7P39RUpsBt7BRue51TB(s(nTEEVS7ldJA(m5yQhHLPmCxREOc8Q7Senu1HjI1EtM1V94ACkHJEwM05stDJtRUhZpTtPWaE0BQlV1C4NoaFwTrnFLoCCgKwApvCQ7SN64lChFcUghqZzRWKZXd4aXD2nRgQ3S6gfVU64cnM3(4iS70B21kMqpOEgA8Pd4G6jK(GQJ7uRm(aoyjJQlHHSnHk9KlqotuE0Zef9L4NwQgZijfto(h35p8W6ZzZ(E42hIfwM1Ui(bXg6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end
|