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.

1433 lines
50 KiB

5 years ago
-- MageFrost.lua
-- June 2018
local addon, ns = ...
local Hekili = _G[ addon ]
local class = Hekili.Class
local state = Hekili.State
local PTR = ns.PTR
local FindUnitBuffByID = ns.FindUnitBuffByID
local abs = math.abs
-- Conduits
-- [-] ice_bite
-- [-] icy_propulsion
-- [-] shivering_core
-- [-] unrelenting_cold
if UnitClassBase( 'player' ) == 'MAGE' then
local spec = Hekili:NewSpecialization( 64, true )
-- spec:RegisterResource( Enum.PowerType.ArcaneCharges )
spec:RegisterResource( Enum.PowerType.Mana )
-- Talents
spec:RegisterTalents( {
bone_chilling = 22457, -- 205027
lonely_winter = 22460, -- 205024
ice_nova = 22463, -- 157997
glacial_insulation = 22442, -- 235297
shimmer = 22443, -- 212653
ice_floes = 23073, -- 108839
incanters_flow = 22444, -- 1463
focus_magic = 22445, -- 321358
rune_of_power = 22447, -- 116011
frozen_touch = 22452, -- 205030
chain_reaction = 22466, -- 278309
ebonbolt = 22469, -- 257537
frigid_winds = 22446, -- 235224
ice_ward = 22448, -- 205036
ring_of_frost = 22471, -- 113724
freezing_rain = 22454, -- 270233
splitting_ice = 23176, -- 56377
comet_storm = 22473, -- 153595
thermal_void = 21632, -- 155149
ray_of_frost = 22309, -- 205021
glacial_spike = 21634, -- 199786
} )
-- PvP Talents
spec:RegisterPvpTalents( {
burst_of_cold = 633, -- 206431
chilled_to_the_bone = 66, -- 198126
concentrated_coolness = 632, -- 198148
deep_shatter = 68, -- 198123
frostbite = 67, -- 198120
ice_form = 634, -- 198144
ice_wall = 5390, -- 352278
netherwind_armor = 3443, -- 198062
prismatic_cloak = 3532, -- 198064
} )
-- Auras
spec:RegisterAuras( {
alter_time = {
id = 110909,
duration = 10,
type = "Magic",
max_stack = 1,
},
active_blizzard = {
duration = function () return 8 * haste end,
max_stack = 1,
generate = function( t )
if query_time - action.blizzard.lastCast < 8 * haste then
t.count = 1
t.applied = action.blizzard.lastCast
t.expires = t.applied + ( 8 * haste )
t.caster = "player"
return
end
t.count = 0
t.applied = 0
t.expires = 0
t.caster = "nobody"
end,
},
arcane_intellect = {
id = 1459,
duration = 3600,
type = "Magic",
max_stack = 1,
shared = "player", -- use anyone's buff on the player, not just player's.
},
blink = {
id = 1953,
},
blizzard = {
id = 12486,
duration = 3,
max_stack = 1,
},
bone_chilling = {
id = 205766,
duration = 8,
max_stack = 10,
},
brain_freeze = {
id = 190446,
duration = 15,
max_stack = 1,
},
chain_reaction = {
id = 278310,
duration = 10,
max_stack = 5,
},
chilled = {
id = 205708,
duration = 8,
type = "Magic",
max_stack = 1,
},
cone_of_cold = {
id = 212792,
duration = 5,
type = "Magic",
max_stack = 1,
},
fingers_of_frost = {
id = 44544,
duration = 15,
max_stack = 2,
},
flurry = {
id = 228354,
duration = 1,
type = "Magic",
max_stack = 1,
},
focus_magic = {
id = 321358,
duration = 1800,
max_stack = 1,
friendly = true,
},
focus_magic_buff = {
id = 321363,
duration = 10,
max_stack = 1,
},
freezing_rain = {
id = 270232,
duration = 12,
max_stack = 1,
},
freeze = {
id = 33395,
duration = 8,
max_stack = 1
},
frost_nova = {
id = 122,
duration = 10,
type = "Magic",
max_stack = 1,
},
frostbolt = {
id = 59638,
duration = 4,
type = "Magic",
max_stack = 1,
},
frozen_orb = {
duration = 10,
max_stack = 1,
generate = function ()
local fo = buff.frozen_orb
if query_time - action.frozen_orb.lastCast < 10 then
fo.count = 1
fo.applied = action.frozen_orb.lastCast
fo.expires = fo.applied + 10
fo.caster = "player"
return
end
fo.count = 0
fo.applied = 0
fo.expires = 0
fo.caster = "nobody"
end,
},
frozen_orb_snare = {
id = 289308,
duration = 3,
max_stack = 1,
},
glacial_spike = {
id = 228600,
duration = 4,
max_stack = 1,
},
hypothermia = {
id = 41425,
duration = 30,
max_stack = 1,
},
ice_barrier = {
id = 11426,
duration = 60,
type = "Magic",
max_stack = 1,
},
ice_block = {
id = 45438,
duration = 10,
type = "Magic",
max_stack = 1,
},
ice_floes = {
id = 108839,
duration = 15,
type = "Magic",
max_stack = 1,
},
ice_nova = {
id = 157997,
duration = 2,
type = "Magic",
max_stack = 1,
},
icicles = {
id = 205473,
duration = 60,
max_stack = 5,
},
icy_veins = {
id = 12472,
duration = function () return talent.thermal_void.enabled and 30 or 20 + ( level > 55 and 3 or 0 ) end,
type = "Magic",
max_stack = 1,
},
incanters_flow = {
id = 116267,
duration = 3600,
max_stack = 5,
meta = {
stack = function() return state.incanters_flow_stacks end,
stacks = function() return state.incanters_flow_stacks end,
}
},
preinvisibility = {
id = 66,
duration = 3,
max_stack = 1,
},
invisibility = {
id = 32612,
duration = 20,
max_stack = 1
},
mirror_image = {
id = 55342,
duration = 40,
max_stack = 3,
generate = function ()
local mi = buff.mirror_image
if action.mirror_image.lastCast > 0 and query_time < action.mirror_image.lastCast + 40 then
mi.count = 1
mi.applied = action.mirror_image.lastCast
mi.expires = mi.applied + 40
mi.caster = "player"
return
end
mi.count = 0
mi.applied = 0
mi.expires = 0
mi.caster = "nobody"
end,
},
polymorph = {
id = 118,
duration = 60,
max_stack = 1
},
ray_of_frost = {
id = 205021,
duration = 5,
max_stack = 1,
},
rune_of_power = {
id = 116014,
duration = 12,
max_stack = 1,
},
shatter = {
id = 12982,
},
shimmer = {
id = 212653,
},
slow_fall = {
id = 130,
duration = 30,
max_stack = 1,
},
temporal_displacement = {
id = 80354,
duration = 600,
max_stack = 1,
},
winters_chill = {
id = 228358,
duration = 6,
type = "Magic",
max_stack = 2,
},
frozen = {
duration = 1,
meta = {
spell = function( t )
if debuff.winters_chill.up and remaining_winters_chill > 0 then return debuff.winters_chill end
return debuff.frost_nova
end,
up = function( t )
return t.spell.up
end,
down = function( t )
return t.spell.down
end,
applied = function( t )
return t.spell.applied
end,
remains = function( t )
return t.spell.remains
end,
count = function(t )
return t.spell.count
end,
stack = function( t )
return t.spell.stack
end,
stacks = function( t )
return t.spell.stacks
end,
}
},
roll_the_bones = {
alias = rtb_buff_list,
aliasMode = "first", -- use duration info from the first buff that's up, as they should all be equal.
aliasType = "buff",
duration = 30,
},
-- Azerite Powers (overrides)
frigid_grasp = {
id = 279684,
duration = 20,
max_stack = 1,
},
overwhelming_power = {
id = 266180,
duration = 25,
max_stack = 25,
},
tunnel_of_ice = {
id = 277904,
duration = 300,
max_stack = 3
},
-- Legendaries
cold_front = {
id = 327327,
duration = 30,
max_stack = 30
},
cold_front_ready = {
id = 327330,
duration = 30,
max_stack = 1
},
expanded_potential = {
id = 327495,
duration = 300,
max_stack = 1
},
freezing_winds = {
id = 327478,
duration = 30,
max_stack = 1
},
slick_ice = {
id = 327509,
duration = 60,
max_stack = 10
}
} )
spec:RegisterTotem( "rune_of_power", 609815 )
spec:RegisterStateExpr( "fingers_of_frost_active", function ()
return false
end )
spec:RegisterStateFunction( "fingers_of_frost", function( active )
fingers_of_frost_active = active
end )
spec:RegisterStateExpr( "remaining_winters_chill", function ()
if debuff.winters_chill.down then return 0 end
return max( 0, debuff.winters_chill.stack - ( state:IsInFlight( "ice_lance" ) and 1 or 0 ) )
end )
spec:RegisterStateTable( "ground_aoe", {
frozen_orb = setmetatable( {}, {
__index = setfenv( function( t, k )
if k == "remains" then
return buff.frozen_orb.remains
end
end, state )
} ),
blizzard = setmetatable( {}, {
__index = setfenv( function( t, k )
if k == "remains" then return buff.active_blizzard.remains end
end, state )
} )
} )
spec:RegisterStateTable( "frost_info", {
last_target_actual = "nobody",
last_target_virtual = "nobody",
watching = true,
real_brain_freeze = false,
virtual_brain_freeze = false
} )
local brain_freeze_removed = 0
spec:RegisterHook( "COMBAT_LOG_EVENT_UNFILTERED", function( event, _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName )
if sourceGUID == GUID then
if subtype == "SPELL_CAST_SUCCESS" then
if spellID == 116 then
frost_info.last_target_actual = destGUID
end
if spellID == 44614 then
frost_info.real_brain_freeze = FindUnitBuffByID( "player", 190446 ) ~= nil
end
elseif subtype == "SPELL_AURA_REMOVED" and spellID == 190446 then
brain_freeze_removed = GetTime()
end
end
end )
spec:RegisterStateExpr( "brain_freeze_active", function ()
return frost_info.virtual_brain_freeze
end )
spec:RegisterStateTable( "rotation", setmetatable( {},
{
__index = function( t, k )
if k == "standard" then return true end
return false
end,
} ) )
spec:RegisterStateTable( "incanters_flow", {
changed = 0,
count = 0,
direction = 0,
startCount = 0,
startTime = 0,
startIndex = 0,
values = {
[0] = { 0, 1 },
{ 1, 1 },
{ 2, 1 },
{ 3, 1 },
{ 4, 1 },
{ 5, 0 },
{ 5, -1 },
{ 4, -1 },
{ 3, -1 },
{ 2, -1 },
{ 1, 0 }
},
f = CreateFrame("Frame"),
fRegistered = false,
reset = setfenv( function ()
if talent.incanters_flow.enabled then
if not incanters_flow.fRegistered then
-- One-time setup.
incanters_flow.f:RegisterUnitEvent( "UNIT_AURA", "player" )
incanters_flow.f:SetScript( "OnEvent", function ()
-- Check to see if IF changed.
if state.talent.incanters_flow.enabled then
local flow = state.incanters_flow
local name, _, count = FindUnitBuffByID( "player", 116267, "PLAYER" )
local now = GetTime()
if name then
if count ~= flow.count then
if count == 1 then flow.direction = 0
elseif count == 5 then flow.direction = 0
else flow.direction = ( count > flow.count ) and 1 or -1 end
flow.changed = GetTime()
flow.count = count
end
else
flow.count = 0
flow.changed = GetTime()
flow.direction = 0
end
end
end )
incanters_flow.fRegistered = true
end
if now - incanters_flow.changed >= 1 then
if incanters_flow.count == 1 and incanters_flow.direction == 0 then
incanters_flow.direction = 1
incanters_flow.changed = incanters_flow.changed + 1
elseif incanters_flow.count == 5 and incanters_flow.direction == 0 then
incanters_flow.direction = -1
incanters_flow.changed = incanters_flow.changed + 1
end
end
if incanters_flow.count == 0 then
incanters_flow.startCount = 0
incanters_flow.startTime = incanters_flow.changed + floor( now - incanters_flow.changed )
incanters_flow.startIndex = 0
else
incanters_flow.startCount = incanters_flow.count
incanters_flow.startTime = incanters_flow.changed + floor( now - incanters_flow.changed )
incanters_flow.startIndex = 0
for i, val in ipairs( incanters_flow.values ) do
if val[1] == incanters_flow.count and val[2] == incanters_flow.direction then incanters_flow.startIndex = i; break end
end
end
else
incanters_flow.count = 0
incanters_flow.changed = 0
incanters_flow.direction = 0
end
end, state ),
} )
spec:RegisterStateExpr( "bf_flurry", function () return false end )
spec:RegisterHook( "reset_precast", function ()
if pet.rune_of_power.up then applyBuff( "rune_of_power", pet.rune_of_power.remains )
else removeBuff( "rune_of_power" ) end
frost_info.last_target_virtual = frost_info.last_target_actual
frost_info.virtual_brain_freeze = frost_info.real_brain_freeze
-- Icicles take a second to get used.
if now - action.ice_lance.lastCast < gcd.execute then removeBuff( "icicles" ) end
if abs( now - brain_freeze_removed ) < 1 then applyDebuff( "target", "winters_chill" ) end
if prev_gcd[1].flurry and now - action.flurry.lastCast < gcd.execute and debuff.winters_chill.up then debuff.winters_chill.count = 2 end
incanters_flow.reset()
if Hekili.ActiveDebug then
Hekili:Debug( "Ice Lance in-flight? %s\nWinter's Chill Actual Stacks? %d\nremaining_winters_chill: %d", state:IsInFlight( "ice_lance" ) and "Yes" or "No", state.debuff.winters_chill.stack, state.remaining_winters_chill )
end
end )
Hekili:EmbedDisciplinaryCommand( spec )
-- Abilities
spec:RegisterAbilities( {
arcane_intellect = {
id = 1459,
cast = 0,
cooldown = 0,
gcd = "spell",
discipline = "arcane",
spend = 0.04,
spendType = "mana",
nobuff = "arcane_intellect",
essential = true,
startsCombat = false,
texture = 135932,
handler = function ()
applyBuff( "arcane_intellect" )
end,
},
blink = {
id = function () return talent.shimmer.enabled and 212653 or 1953 end,
cast = 0,
charges = function () return talent.shimmer.enabled and 2 or nil end,
cooldown = function () return ( talent.shimmer.enabled and 20 or 15 ) - conduit.flow_of_time.mod * 0.001 end,
recharge = function () return ( talent.shimmer.enabled and ( 20 - conduit.flow_of_time.mod * 0.001 ) or nil ) end,
gcd = "off",
discipline = "arcane",
spend = function () return 0.02 * ( buff.arcane_power.up and ( talent.overpowered.enabled and 0.4 or 0.7 ) or 1 ) end,
spendType = "mana",
startsCombat = false,
texture = function () return talent.shimmer.enabled and 135739 or 135736 end,
handler = function ()
if talent.displacement.enabled then applyBuff( "displacement_beacon" ) end
end,
copy = { 212653, 1953, "shimmer" }
},
blizzard = {
id = 190356,
cast = function () return buff.freezing_rain.up and 0 or 2 * haste end,
cooldown = 8,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 135857,
velocity = 20,
handler = function ()
applyDebuff( "target", "blizzard" )
applyBuff( "active_blizzard" )
end,
},
cold_snap = {
id = 235219,
cast = 0,
cooldown = function () return leel > 53 and 270 or 300 end,
gcd = "spell",
toggle = "cooldowns",
startsCombat = false,
texture = 135865,
handler = function ()
setCooldown( "ice_barrier", 0 )
setCooldown( "frost_nova", 0 )
setCooldown( "cone_of_cold", 0 )
setCooldown( "ice_block", 0 )
end,
},
comet_storm = {
id = 153595,
cast = 0,
cooldown = 30,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 2126034,
talent = "comet_storm",
handler = function ()
end,
},
cone_of_cold = {
id = 120,
cast = 0,
cooldown = 12,
gcd = "spell",
spend = 0.04,
spendType = "mana",
startsCombat = true,
texture = 135852,
usable = function ()
return target.distance <= 12
end,
handler = function ()
applyDebuff( "target", "cone_of_cold" )
active_dot.cone_of_cold = max( active_enemies, active_dot.cone_of_cold )
end,
},
--[[ conjure_refreshment = {
id = 190336,
cast = 3,
cooldown = 15,
gcd = "spell",
spend = 0.03,
spendType = "mana",
startsCombat = false,
texture = 134029,
handler = function ()
end,
}, ]]
counterspell = {
id = 2139,
cast = 0,
cooldown = function () return 24 - ( conduit.grounding_surge.mod * 0.1 ) end,
gcd = "off",
discipline = "arcane",
interrupt = true,
toggle = function ()
if runeforge.disciplinary_command.enabled then return end
return "interrupts"
end,
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 135856,
debuff = function ()
if runeforge.disciplinary_command.enabled then return end
return "casting"
end,
readyTime = function ()
if runeforge.disciplinary_command.enabled then return end
return state.timeToInterrupt()
end,
handler = function ()
interrupt()
end,
},
ebonbolt = {
id = 257537,
cast = 2.5,
cooldown = 45,
gcd = "spell",
startsCombat = true,
texture = 1392551,
velocity = 30,
handler = function ()
applyBuff( "brain_freeze" )
end,
},
flurry = {
id = 44614,
cast = function ()
if buff.brain_freeze.up then return 0 end
return 3 * haste
end,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 1506795,
velocity = 50,
handler = function ()
if buff.brain_freeze.up then
if buff.expanded_potential.up then removeBuff( "expanded_potential" )
else
if legendary.sinful_delight.enabled then gainChargeTime( "mirrors_of_torment", 4 ) end
5 years ago
removeBuff( "brain_freeze" )
end
frost_info.virtual_brain_freeze = true
else
frost_info.virtual_brain_freeze = false
end
removeBuff( "cold_front_ready" )
if legendary.cold_front.enabled then
addStack( "cold_front" )
if buff.cold_front.stack == 30 then
removeBuff( "cold_front" )
applyBuff( "cold_front_ready" )
end
end
applyDebuff( "target", "flurry" )
addStack( "icicles", nil, 1 )
if talent.bone_chilling.enabled then addStack( "bone_chilling", nil, 1 ) end
removeBuff( "ice_floes" )
end,
impact = function ()
if frost_info.virtual_brain_freeze then
applyDebuff( "target", "winters_chill", nil, 2 )
frost_info.virtual_brain_freeze = false
end
end,
copy = 228354 -- ID of the Flurry impact.
},
focus_magic = {
id = 321358,
cast = 0,
cooldown = 0,
gcd = "spell",
discipline = "arcane",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 135754,
talent = "focus_magic",
usable = function () return active_dot.focus_magic == 0 and group, "can apply one in a group" end,
handler = function ()
applyBuff( "focus_magic" )
end,
},
frost_nova = {
id = 122,
cast = 0,
charges = function () return talent.ice_ward.enabled and 2 or nil end,
cooldown = 30,
recharge = 30,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 135848,
handler = function ()
applyDebuff( "target", "frost_nova" )
if legendary.grisly_icicle.enabled then applyDebuff( "target", "grisly_icicle" ) end
end,
},
frostbolt = {
id = 116,
cast = function () return 2 * ( 1 - 0.02 * buff.slick_ice.stack ) * haste end,
cooldown = 0,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 135846,
handler = function ()
addStack( "icicles", nil, 1 )
applyDebuff( "target", "chilled" )
if talent.bone_chilling.enabled then addStack( "bone_chilling", nil, 1 ) end
removeBuff( "ice_floes" )
removeBuff( "cold_front_ready" )
if legendary.cold_front.enabled then
addStack( "cold_front" )
if buff.cold_front.stack == 15 then
removeBuff( "cold_front" )
applyBuff( "cold_front_ready" )
end
end
if legendary.slick_ice.enabled then
addStack( "slick_ice", nil, 1 )
end
if azerite.tunnel_of_ice.enabled then
if frost_info.last_target_virtual == target.unit then
addStack( "tunnel_of_ice", nil, 1 )
else
removeBuff( "tunnel_of_ice" )
end
frost_info.last_target_virtual = target.unit
end
end,
},
frozen_orb = {
id = 84714,
cast = 0,
cooldown = 60,
gcd = "spell",
spend = 0.01,
spendType = "mana",
-- toggle = "cooldowns",
startsCombat = true,
texture = 629077,
velocity = 20,
handler = function ()
if talent.freezing_rain.enabled then applyBuff( "freezing_rain" ) end
applyBuff( "frozen_orb" )
end,
--[[ Not modeling because you can throw it off in a random direction and get no procs. Just react.
impact = function ()
addStack( "fingers_of_frost", nil, 1 )
applyDebuff( "target", "frozen_orb_snare" )
end, ]]
copy = 198149
},
glacial_spike = {
id = 199786,
cast = 3,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 1698699,
talent = "glacial_spike",
velocity = 40,
usable = function () return buff.icicles.stack >= 5 end,
handler = function ()
removeBuff( "icicles" )
applyDebuff( "target", "glacial_spike" )
end,
},
ice_barrier = {
id = 11426,
cast = 0,
cooldown = 25,
gcd = "spell",
defensive = true,
spend = 0.03,
spendType = "mana",
startsCombat = false,
texture = 135988,
handler = function ()
applyBuff( "ice_barrier" )
if legendary.triune_ward.enabled then
applyBuff( "blazing_barrier" )
applyBuff( "prismatic_barrier" )
end
end,
},
ice_block = {
id = 45438,
cast = 0,
cooldown = function () return 240 + ( conduit.winters_protection.mod * 0.001 ) end,
gcd = "spell",
toggle = "defensives",
defensive = true,
startsCombat = false,
texture = 135841,
handler = function ()
applyBuff( "ice_block" )
applyDebuff( "player", "hypothermia" )
end,
},
ice_floes = {
id = 108839,
cast = 0,
charges = 3,
cooldown = 20,
recharge = 20,
gcd = "spell",
startsCombat = false,
texture = 610877,
talent = "ice_floes",
handler = function ()
applyBuff( "ice_floes" )
end,
},
ice_lance = {
id = 30455,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 135844,
velocity = 47,
handler = function ()
if not talent.glacial_spike.enabled then removeStack( "icicles" ) end
if buff.fingers_of_frost.up or debuff.frozen.up then
if talent.chain_reaction.enabled then addStack( "chain_reaction", nil, 1 ) end
if talent.thermal_void.enabled and buff.icy_veins.up then buff.icy_veins.expires = buff.icy_veins.expires + 1 end
end
removeStack( "fingers_of_frost" )
applyDebuff( "target", "chilled" )
if talent.bone_chilling.enabled then addStack( "bone_chilling", nil, 1 ) end
if azerite.whiteout.enabled then
cooldown.frozen_orb.expires = max( 0, cooldown.frozen_orb.expires - 0.5 )
end
end,
impact = function ()
if debuff.winters_chill.up then
if debuff.winters_chill.stack > 1 then removeDebuffStack( "target", "winters_chill", 1 )
else removeDebuff( "target", "winters_chill" ) end
end
end,
copy = 228598
},
ice_nova = {
id = 157997,
cast = 0,
cooldown = 25,
gcd = "spell",
startsCombat = true,
texture = 1033909,
talent = "ice_nova",
handler = function ()
applyDebuff( "target", "ice_nova" )
end,
},
icy_veins = {
id = 12472,
cast = 0,
cooldown = function () return ( essence.vision_of_perfection.enabled and 0.87 or 1 ) * 180 end,
gcd = "off",
toggle = "cooldowns",
startsCombat = true,
texture = 135838,
handler = function ()
applyBuff( "icy_veins" )
stat.haste = stat.haste + 0.30
if azerite.frigid_grasp.enabled then
applyBuff( "frigid_grasp", 10 )
addStack( "fingers_of_frost", nil, 1 )
end
if talent.rune_of_power.enabled then
applyBuff( "rune_of_power" )
end
end,
},
invisibility = {
id = 66,
cast = 0,
cooldown = 300,
gcd = "spell",
discipline = "arcane",
spend = 0.03,
spendType = "mana",
toggle = "defensives",
defensive = true,
startsCombat = false,
texture = 132220,
handler = function ()
applyBuff( "preinvisibility" )
applyBuff( "invisibility", 23 )
if conduit.incantation_of_swiftness.enabled then applyBuff( "incantation_of_swiftness" ) end
end,
},
mirror_image = {
id = 55342,
cast = 0,
cooldown = 120,
gcd = "spell",
discipline = "arcane",
spend = 0.02,
spendType = "mana",
toggle = "cooldowns",
startsCombat = false,
texture = 135994,
handler = function ()
applyBuff( "mirror_image", nil, 3 )
end,
},
polymorph = {
id = 118,
cast = 1.7,
cooldown = 0,
gcd = "spell",
discipline = "arcane",
spend = 0.04,
spendType = "mana",
startsCombat = false,
texture = 136071,
handler = function ()
applyDebuff( "target", "polymorph" )
end,
},
ray_of_frost = {
id = 205021,
cast = 5,
channeled = true,
cooldown = 75,
gcd = "spell",
spend = 0.02,
spendType = "mana",
toggle = "cooldowns",
startsCombat = true,
texture = 1698700,
talent = "ray_of_frost",
start = function ()
applyDebuff( "target", "ray_of_frost" )
end,
},
remove_curse = {
id = 475,
cast = 0,
cooldown = 8,
gcd = "spell",
discipline = "arcane",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 136082,
debuff = "dispellable_curse",
handler = function ()
removeDebuff( "player", "dispellable_curse" )
end,
},
ring_of_frost = {
id = 113724,
cast = 2,
cooldown = 45,
gcd = "spell",
spend = 0.08,
spendType = "mana",
startsCombat = true,
texture = 464484,
talent = "ring_of_frost",
handler = function ()
end,
},
rune_of_power = {
id = 116011,
cast = 1.5,
charges = 2,
cooldown = 40,
recharge = 40,
gcd = "spell",
discipline = "arcane",
startsCombat = false,
texture = 609815,
nobuff = "rune_of_power",
talent = "rune_of_power",
handler = function ()
applyBuff( "rune_of_power" )
end,
},
slow_fall = {
id = 130,
cast = 0,
cooldown = 0,
gcd = "spell",
discipline = "arcane",
spend = 0.01,
spendType = "mana",
startsCombat = false,
texture = 135992,
handler = function ()
applyBuff( "slow_fall" )
end,
},
spellsteal = {
id = 30449,
cast = 0,
cooldown = 0,
gcd = "spell",
discipline = "arcane",
spend = 0.21,
spendType = "mana",
startsCombat = true,
texture = 135729,
debuff = "stealable_magic",
handler = function ()
removeDebuff( "target", "stealable_magic" )
end,
},
water_elemental = {
id = 31687,
cast = 1.5,
cooldown = 30,
gcd = "spell",
spend = 0.03,
spendType = "mana",
startsCombat = false,
texture = 135862,
notalent = "lonely_winter",
nomounted = true,
usable = function () return not pet.alive end,
handler = function ()
summonPet( "water_elemental" )
end,
copy = "summon_water_elemental"
},
time_warp = {
id = 80353,
cast = 0,
cooldown = 300,
gcd = "off",
discipline = "arcane",
spend = 0.04,
spendType = "mana",
toggle = "cooldowns",
startsCombat = true,
texture = 458224,
handler = function ()
applyBuff( "time_warp" )
applyDebuff( "player", "temporal_displacement" )
end,
},
} )
spec:RegisterOptions( {
enabled = true,
aoe = 3,
nameplates = false,
nameplateRange = 8,
damage = true,
damageExpiration = 6,
potion = "phantom_fire",
package = "Frost Mage",
} )
spec:RegisterSetting( "ignore_freezing_rain_st", true, {
name = "Ignore |T629077:0|t Freezing Rain in Single-Target",
desc = "If checked, the default action list will not recommend using |T135857:0|t Blizzard in single-target due to the |T629077:0|t Freezing Rain talent proc.",
type = "toggle",
width = "full",
} )
spec:RegisterPack( "Frost Mage", 20210707, [[dO0G3aqijr5rQsYMKK(KizuscNse1RqQAwQcDlvrk7IOFHuAyQI6yIultvINPkIPPkPUgPIyBsIQVjIKXjIuDorKY6ivyEif19qI9HK4GKkklePYdLezIQIKCrsfjBKurQpIueoPQiXkjfZueXnjvuTtqPFQksvdvvKulfPi1tbzQGIVIuenwvb7fXFf1Gr1HLAXQQhJYKL4YqBMsFwsnAvPoTWQvfPYRrsA2uCBc2nv)wPHdQoosrYYv55KmDfxNqBNu67KQgpsHZJKA9KknFry)atstGHav6bjW(YZVK(5K65Ks(CslD60jfbAOgosGG3mQ21ibYBbKaPtFRAaCDExJei4n1MTleyiqQv8yib69mWv6GwARJ5T4xYwbAvHGOPNyD212HwviWOLa9fdZ8uCYNav6bjW(YZVK(5K65Ks(CslD60VqGAX59EeiOqOseO3rPGo5tGkOIrG05Dnc4603QgGgnIgQb8K6ra)LNFjnqdqtLE3EnQ0bqZtdWFQwp1a4HZmIfeWPZeovb8WbCD(QffqFaCD2tDsa8kGVQyI1dVgWdfG3aoCttnEaEbzHkwpzGMNgGRZBQIaUAfqapLnQFp5df6WvPaC0NlqfG3WHBOgWNfW)Rsb42O(9Oa81nuljqMqnkcmeOcABrZqGHaBAcmei07Vble6iqSlg8IMavza(j6ODVAuwcflGBcVpQZSvqO9Ie9(BWcGxfWl4x0ALSwnHxlfHd4vb8c(fTwjRvt41Ydf6Wvaond4Pb8ejaC2UMYQ3LFrRnxcflGBcVpQZSvqO9I8WUqnGxfW)IwRSekwa3eEFuNzRGq7LCFS2rzz17eOMnX6ei2k6dEk4OXqgcSVqGHaHE)nyHqhbQztSobI1gtUztSE2eQHazc1K9wajqSIImeyFcbgce693GfcDeOMnX6eiwBm5MnX6ztOgcKjut2BbKaHkf6murgcSVMadbc9(BWcHoce7IbVOjqnBcTygDuiqfGtfka(tiqnBI1jqS2yYnBI1ZMqneitOMS3cibQxKmey1jeyiqO3Fdwi0rGyxm4fnbQztOfZOJcbQaCAgWFcbQztSobI1gtUztSE2eQHazc1K9wajqQHmeyRCcmei07Vble6iqnBI1jqS2yYnBI1ZMqneitOMS3cibsy1IcOpKHmei4hYwHFpeyiWMMadbQztSobQpw7yo8bngKnei07Vble6idb2xiWqGA2eRtG03dEz0GcOpTHaHE)nyHqhziW(ecmei07Vble6iqSlg8IMa1Sj0Iz0rHavaovOa4VqGA2eRtG(MqxD7RqgcSVMadbc9(BWcHoce7IbVOjqnBcTygDuiqfGtbWttGA2eRtGS3QM)AgYqgcuVibgcSPjWqGA2eRtGS3Ql659(ei07Vble6idb2xiWqGA2eRtG(MqxD7RqGqV)gSqOJmeyFcbgce693GfcDei2fdErtGQaWpuOdp86S(Wh8uz27WyaCka(ZaEIeaEb)IwRuF4dEQm7DymYYQ3b8Kb8QaEfao8d1MRzfzAj(x)VMbWtKaW)IwR8FD4z7HOUO8WMnaEva)lATsB414PYRnBVvnYdB2a4ua8Nb8KjqnBI1jqwJ4DutgcSVMadbQztSobkyy2xTnbc9(BWcHoYqGvNqGHa1SjwNaXwbCYQzpbce693GfcDKHaBLtGHaHE)nyHqhbIDXGx0eOVO1kTHxJNkV2S9w1ipSzdGNibGxWVO1kT3Ql6Ydf6Wvaova85ATOjpHac4jsa4hk0HhEDwF4dEQm7DymaEvaVGFrRvQp8bpvM9omg5HcD4kaNka(CTw0KNqajqnBI1jqbdZM2ziziWMueyiqO3Fdwi0rGyxm4fnbsTIMF4fjBf(9KfWsm9eRlrV)gSqGA2eRtGUUeTpzf8(OkziWM0jWqGA2eRtGeI72tLxBE2ta9HaHE)nyHqhziWM0iWqGA2eRtGuVd7eEDg(Qhpce693GfcDKHaB6NjWqGqV)gSqOJaXUyWlAc0j6ODVAuwFHYqDoybZGs07VblaEvaF6RghPb1IgaNMPa4gulAa8QaEb)IwR0ERUOllRENa1SjwNazVvnzF12KHaB60eyiqO3Fdwi0rGyxm4fnb6eD0UxnklHIfWnH3h1z2ki0ErIE)nybWRc4SDnLvVl)IwBUekwa3eEFuNzRGq7f5HDHAaVkG)fTwzjuSaUj8(OoZwbH2lzBCOSS6DcuZMyDcKnom)nTAidb20VqGHaHE)nyHqhbIDXGx0eiH2BjC2a4ubWFYZaEvaVztOfZOJcbQaCQqbWRCaVkGxza(j6ODVAuwBAw0MS96Ab0hLe9(BWcbQztSobQpw7ygPbCZQI1jdb20pHadbQztSobc)R)xZqGqV)gSqOJmeyt)Acmei07Vble6iqSlg8IMaDIoA3RgL1MMfTjBVUwa9rjrV)gSa4vb8PnOpsfCtmt415GHs07VblaEvaFUwlAYtiGaond413k6LCVO8BcD1TVI8qHoCfbQztSobkyy20odjdb206ecmeOMnX6ei7TQ5VMHaHE)nyHqhzidbIvueyiWMMadbc9(BWcHocuZMyDcK6Dxw9yjV3pV28SNa6dbIDXGx0eOVO1kprhZRndF1JNSS6DcK3cibs9UlRESK37NxBE2ta9HmeyFHadbc9(BWcHoce7IbVOjqWpuBET2CnRidg1zTy4kaprca)VkfGxfWTr97jFOqhUcWPza)jptGA2eRtGGVtSoziW(ecmeOMnX6eOc2Z7)EosGqV)gSqOJmeyFnbgce693GfcDei2fdErtGA2eAXm6OqGkaNMb8Na4vb8kaC26fXyKQa(71XswOnbdLO3Fdwa8ejaC1kA(HxK6B1GM2lz43c)cCOwIE)nybWtgWRc4FrRv(Vo8S9quxuEyZgaNcG)mbQztSobsiUBpvET5zpb0hYqGvNqGHaHE)nyHqhbIDXGx0ei2UMYQ3LbJ6SwmCL8qHoCfGtfap9laEva)lATYt0X8AZWx94jlRENa1SjwNaDIoMxBg(QhpYqGTYjWqGqV)gSqOJaXUyWlAc0x0ALNOJ51MHV6Xtww9oGxfWRaW)IwRmyuN1IHRKLvVd4jsa4tBqFKNOJ51MHV6XtIE)nybWtgWRc4va4FrRvQmbJQ5GHYYQ3b8eja8MnHwmJokeOcWPcfa)fapzcuZMyDcuWOoRfdxrgcSjfbgce693GfcDei2fdErtGorhT7vJYbfGVxBY67dUe9(BWcGxfW)IwRePX7wunX6sr4aEvaVcah(HAZR1MRzfzWOoRfdxb4jsa4)vPa8QaUnQFp5df6Wvaond4V(zapzcuZMyDc0ecywFFWjdb2KobgcuZMyDcKOcZXGckce693GfcDKHaBsJadbQztSob6B2TKTIh1ei07Vble6idb20ptGHa1SjwNa9XtHhvdVMaHE)nyHqhziWMonbgcuZMyDcKjQFpQ8tNyPwa9HaHE)nyHqhziWM(fcmeOMnX6eiBC43SBHaHE)nyHqhziWM(jeyiqnBI1jqTZq1CTjZAJHaHE)nyHqhziWM(1eyiqnBI1jq)UoV28CbJQkce693GfcDKHmei1qGHaBAcmei07Vble6iqSlg8IMavbGFOqhE41z9Hp4PYS3HXa4ua8Nb8eja8c(fTwP(Wh8uz27WyKLvVd4jd4vb8kaC4hQnxZkY0s8V(FndGNibG)fTw5)6WZ2drDr5HnBa8QaEfao8d1MRzfzAzTPzrBYk4bvraprcah(HAZ1SImT0ERA(Rza8QaEfaELb4S1lIXiJdZRnpVXCRyOxWIe9(BWcGNibGZ21uw9U86s0(KvW7JQYdf6WvaEIea(j6ODVAuApe1n86S(Wlkj693Gfapzaprcah(HAZ1SImT86s0(KvW7JQaEIea(x0AL2WRXtLxB2ERAKh2SbWPa4pd4vb8ka8c(fTwPqC3EQ8AZZEcOpsr4aEIea(x0AL2drDdVoRp8IskchWtKaW)IwRePb82lyjdFh0NOnYdB2a4jd4jd4jtGA2eRtGSgX7OMmeyFHadbQztSobYER
end