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.

1848 lines
87 KiB

5 years ago
-- WarlockAffliction.lua
-- June 2018
local addon, ns = ...
local Hekili = _G[ addon ]
local class = Hekili.Class
local state = Hekili.State
-- Conduits
-- [-] cold_embrace
-- [-] corrupting_leer
-- [-] focused_malignancy
-- [x] rolling_agony
-- Covenants
-- [x] soul_tithe
-- [x] catastrophic_origin
-- [-] prolonged_decimation
-- [-] soul_eater
-- Endurance
-- [x] accrued_vitality
-- [-] diabolic_bloodstone
-- [-] resolute_barrier
-- Finesse
-- [x] demonic_momentum
-- [x] fel_celerity
-- [-] shade_of_terror
if UnitClassBase( 'player' ) == 'WARLOCK' then
local spec = Hekili:NewSpecialization( 265, true )
spec:RegisterResource( Enum.PowerType.SoulShards, {
-- regen effects.
}, setmetatable( {
actual = nil,
max = 5,
active_regen = 0,
inactive_regen = 0,
forecast = {},
times = {},
values = {},
fcount = 0,
regen = 0,
regenerates = false,
}, {
__index = function( t, k )
if k == 'count' or k == 'current' then return t.actual
elseif k == 'actual' then
t.actual = UnitPower( "player", Enum.PowerType.SoulShards )
return t.actual
end
end
} ) )
spec:RegisterResource( Enum.PowerType.Mana )
-- Talents
spec:RegisterTalents( {
nightfall = 22039, -- 108558
inevitable_demise = 23140, -- 334319
drain_soul = 23141, -- 198590
writhe_in_agony = 22044, -- 196102
absolute_corruption = 21180, -- 196103
siphon_life = 22089, -- 63106
demon_skin = 19280, -- 219272
burning_rush = 19285, -- 111400
dark_pact = 19286, -- 108416
sow_the_seeds = 19279, -- 196226
phantom_singularity = 19292, -- 205179
vile_taint = 22046, -- 278350
darkfury = 22047, -- 264874
mortal_coil = 19291, -- 6789
howl_of_terror = 23465, -- 5484
shadow_embrace = 23139, -- 32388
haunt = 23159, -- 48181
grimoire_of_sacrifice = 19295, -- 108503
soul_conduit = 19284, -- 215941
creeping_death = 19281, -- 264000
dark_soul_misery = 19293, -- 113860
} )
-- PvP Talents
spec:RegisterPvpTalents( {
amplify_curse = 5370, -- 328774
bane_of_fragility = 11, -- 199954
bane_of_shadows = 17, -- 234877
casting_circle = 20, -- 221703
deathbolt = 12, -- 264106
demon_armor = 3740, -- 285933
essence_drain = 19, -- 221711
gateway_mastery = 15, -- 248855
nether_ward = 18, -- 212295
rampant_afflictions = 5379, -- 335052
rapid_contagion = 5386, -- 344566
rot_and_decay = 16, -- 212371
shadow_rift = 5392, -- 353294
} )
-- Auras
spec:RegisterAuras( {
agony = {
id = 980,
duration = function () return ( 18 + conduit.rolling_agony.mod * 0.001 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) * haste end,
type = "Curse",
max_stack = function () return ( talent.writhe_in_agony.enabled and 18 or 10 ) end,
meta = {
stack = function( t )
if t.down then return 0 end
if t.count >= 10 then return t.count end
local app = t.applied
local tick = t.tick_time
local last_real_tick = now + ( floor( ( now - app ) / tick ) * tick )
local ticks_since = floor( ( query_time - last_real_tick ) / tick )
return min( talent.writhe_in_agony.enabled and 18 or 10, t.count + ticks_since )
end,
}
},
burning_rush = {
id = 111400,
duration = 3600,
max_stack = 1,
},
corruption = {
id = 146739,
duration = function () return ( talent.absolute_corruption.enabled and ( target.is_player and 24 or 3600 ) or 14 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) * haste end,
type = "Magic",
max_stack = 1,
},
curse_of_exhaustion = {
id = 334275,
duration = 8,
max_stack = 1,
},
curse_of_tongues = {
id = 1714,
duration = 60,
type = "Curse",
max_stack = 1,
},
curse_of_weakness = {
id = 702,
duration = 120,
type = "Curse",
max_stack = 1,
},
dark_pact = {
id = 108416,
duration = 20,
max_stack = 1,
},
dark_soul_misery = {
id = 113860,
duration = 20,
max_stack = 1,
},
decimating_bolt = {
id = 325299,
duration = 3600,
max_stack = 1,
},
demonic_circle = {
id = 48018,
duration = 900,
max_stack = 1,
},
demonic_circle_teleport = {
id = 48020,
},
drain_life = {
id = 234153,
duration = function () return 5 * haste * ( legendary.claw_of_endereth.enabled and 0.5 or 1 ) end,
max_stack = 1,
tick_time = function () return haste * ( legendary.claw_of_endereth.enabled and 0.5 or 1 ) end,
},
drain_soul = {
id = 198590,
duration = function () return 5 * haste end,
max_stack = 1,
tick_time = function ()
if not settings.manage_ds_ticks then return nil end
return haste
end,
},
eye_of_kilrogg = {
id = 126,
duration = 45,
max_stack = 1,
},
fear = {
id = 118699,
duration = 20,
type = "Magic",
max_stack = 1,
},
fel_domination = {
id = 333889,
duration = 15,
type = "Magic",
max_stack = 1,
},
grimoire_of_sacrifice = {
id = 196099,
duration = 3600,
max_stack = 1,
},
haunt = {
id = 48181,
duration = 18,
type = "Magic",
max_stack = 1,
},
howl_of_terror = {
id = 5484,
duration = 20,
max_stack = 1,
},
inevitable_demise = {
id = 334320,
duration = 20,
type = "Magic",
max_stack = 50,
copy = 273525
},
mortal_coil = {
id = 6789,
duration = 3,
type = "Magic",
max_stack = 1,
},
nightfall = {
id = 264571,
duration = 12,
max_stack = 1,
},
phantom_singularity = {
id = 205179,
duration = 16,
max_stack = 1,
},
ritual_of_summoning = {
id = 698,
},
seed_of_corruption = {
id = 27243,
duration = 12,
type = "Magic",
max_stack = 1,
},
shadow_embrace = {
id = 32390,
duration = 16,
type = "Magic",
max_stack = 3,
},
shadowfury = {
id = 30283,
duration = 3,
type = "Magic",
max_stack = 1,
},
siphon_life = {
id = 63106,
duration = function () return 15 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 3 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
type = "Magic",
max_stack = 1,
},
soul_leech = {
id = 108366,
duration = 15,
max_stack = 1,
},
soul_shards = {
id = 246985,
},
soulstone = {
id = 20707,
duration = 900,
max_stack = 1,
},
summon_darkglare = {
id = 205180,
},
unending_breath = {
id = 5697,
duration = 600,
max_stack = 1,
},
unending_resolve = {
id = 104773,
duration = 8,
max_stack = 1,
},
unstable_affliction = {
id = function () return pvptalent.rampant_afflictions.enabled and 342938 or 316099 end,
duration = function () return level > 55 and 21 or 16 end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) * haste end,
type = "Magic",
max_stack = 1,
copy = { 342938, 316099 }
},
--[[ OLD UAs:
unstable_affliction = {
id = 233490,
duration = function () return ( pvptalent.endless_affliction.enabled and 14 or 8 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
type = "Magic",
max_stack = 1,
copy = "unstable_affliction_1"
},
unstable_affliction_2 = {
id = 233496,
duration = function () return ( pvptalent.endless_affliction.enabled and 14 or 8 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
type = "Magic",
max_stack = 1,
},
unstable_affliction_3 = {
id = 233497,
duration = function () return ( pvptalent.endless_affliction.enabled and 14 or 8 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
type = "Magic",
max_stack = 1,
},
unstable_affliction_4 = {
id = 233498,
duration = function () return ( pvptalent.endless_affliction.enabled and 14 or 8 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
type = "Magic",
max_stack = 1,
},
unstable_affliction_5 = {
id = 233499,
duration = function () return ( pvptalent.endless_affliction.enabled and 14 or 8 ) * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
tick_time = function () return 2 * ( talent.creeping_death.enabled and 0.85 or 1 ) end,
type = "Magic",
max_stack = 1,
},
active_uas = {
alias = { "unstable_affliction_1", "unstable_affliction_2", "unstable_affliction_3", "unstable_affliction_4", "unstable_affliction_5" },
aliasMode = 'longest',
aliasType = 'debuff',
duration = 8
}, ]]
vile_taint = {
id = 278350,
duration = 10,
type = "Magic",
max_stack = 1,
},
-- PvP Talents
casting_circle = {
id = 221705,
duration = 3600,
max_stack = 1,
},
curse_of_fragility = {
id = 199954,
duration = 10,
max_stack = 1,
},
curse_of_shadows = {
id = 234877,
duration = 10,
type = "Curse",
max_stack = 1,
},
curse_of_weakness = {
id = 199892,
duration = 10,
type = "Curse",
max_stack = 1,
copy = 702,
},
demon_armor = {
id = 285933,
duration = 3600,
max_stack = 1,
},
essence_drain = {
id = 221715,
duration = 10,
type = "Magic",
max_stack = 5,
},
nether_ward = {
id = 212295,
duration = 3,
type = "Magic",
max_stack = 1,
},
soulshatter = {
id = 236471,
duration = 8,
max_stack = 5,
},
-- Conduit
diabolic_bloodstone = {
id = 340563,
duration = 8,
max_stack = 1
},
-- Legendaries
malefic_wrath = {
id = 337125,
duration = 8,
max_stack = 1
},
relic_of_demonic_synergy = {
id = 337060,
duration = 15,
max_stack = 1
},
wrath_of_consumption = {
id = 337130,
duration = 20,
max_stack = 5
}
} )
spec:RegisterHook( "TimeToReady", function( wait, action )
local ability = action and class.abilities[ action ]
if ability and ability.spend and ability.spendType == "soul_shards" and ability.spend > soul_shard then
wait = 3600
end
return wait
end )
spec:RegisterStateExpr( "soul_shard", function () return soul_shards.current end )
state.sqrt = math.sqrt
spec:RegisterStateExpr( "time_to_shard", function ()
local num_agony = active_dot.agony
if num_agony == 0 then return 3600 end
return 1 / ( 0.16 / sqrt( num_agony ) * ( num_agony == 1 and 1.15 or 1 ) * num_agony / debuff.agony.tick_time )
end )
spec:RegisterHook( "COMBAT_LOG_EVENT_UNFILTERED", function( event, _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName, _, amount, interrupt, a, b, c, d, offhand, multistrike, ... )
if sourceGUID == GUID and spellName == class.abilities.seed_of_corruption.name then
if subtype == "SPELL_CAST_SUCCESS" then
action.seed_of_corruption.flying = GetTime()
elseif subtype == "SPELL_AURA_APPLIED" or subtype == "SPELL_AURA_REFRESH" then
action.seed_of_corruption.flying = 0
end
end
end )
spec:RegisterGear( 'tier21', 152174, 152177, 152172, 152176, 152173, 152175 )
spec:RegisterGear( 'tier20', 147183, 147186, 147181, 147185, 147182, 147184 )
spec:RegisterGear( 'tier19', 138314, 138323, 138373, 138320, 138311, 138317 )
spec:RegisterGear( 'class', 139765, 139768, 139767, 139770, 139764, 139769, 139766, 139763 )
spec:RegisterGear( 'amanthuls_vision', 154172 )
spec:RegisterGear( 'hood_of_eternal_disdain', 132394 )
spec:RegisterGear( 'norgannons_foresight', 132455 )
spec:RegisterGear( 'pillars_of_the_dark_portal', 132357 )
spec:RegisterGear( 'power_cord_of_lethtendris', 132457 )
spec:RegisterGear( 'reap_and_sow', 144364 )
spec:RegisterGear( 'sacrolashs_dark_strike', 132378 )
spec:RegisterGear( 'soul_of_the_netherlord', 151649 )
spec:RegisterGear( 'stretens_sleepless_shackles', 132381 )
spec:RegisterGear( 'the_master_harvester', 151821 )
--[[ spec:RegisterStateFunction( "applyUnstableAffliction", function( duration )
for i = 1, 5 do
local aura = "unstable_affliction_" .. i
if debuff[ aura ].down then
applyDebuff( 'target', aura, duration or 8 )
break
end
end
end ) ]]
spec:RegisterHook( "reset_preauras", function ()
if class.abilities.summon_darkglare.realCast and state.now - class.abilities.summon_darkglare.realCast < 20 then
target.updated = true
end
end )
spec:RegisterHook( "reset_precast", function ()
soul_shards.actual = nil
local icd = 25
if debuff.drain_soul.up then
local ticks = debuff.drain_soul.ticks_remain
if pvptalent.rot_and_decay.enabled then
if debuff.agony.up then debuff.agony.expires = debuff.agony.expires + 1 end
if debuff.corruption.up then debuff.corruption.expires = debuff.corruption.expires + 1 end
if debuff.unstable_affliction.up then debuff.unstable_affliction.expires = debuff.unstable_affliction.expires + 1 end
end
if pvptalent.essence_drain.enabled and health.pct < 100 then
addStack( "essence_drain", debuff.drain_soul.remains, debuff.essence_drain.stack + ticks )
end
end
-- Can't trust Agony stacks/duration to refresh.
local name, _, count, _, duration, expires, caster = FindUnitDebuffByID( "target", 980 )
if name then
debuff.agony.expires = expires
debuff.agony.duration = duration
debuff.agony.applied = max( 0, expires - duration )
debuff.agony.count = expires > 0 and max( 1, count ) or 0
debuff.agony.caster = caster
else
debuff.agony.expires = 0
debuff.agony.duration = 0
debuff.agony.applied = 0
debuff.agony.count = 0
debuff.agony.caster = "nobody"
end
if buff.casting.up and buff.casting.v1 == 234153 then
removeBuff( "inevitable_demise" )
removeBuff( "inevitable_demise_az" )
end
if buff.casting_circle.up then
applyBuff( "casting_circle", action.casting_circle.lastCast + 8 - query_time )
end
end )
spec:RegisterHook( "spend", function( amt, resource )
if resource == "soul_shards" and amt > 0 then
if legendary.wilfreds_sigil_of_superior_summoning.enabled then
reduceCooldown( "summon_darkglare", amt * 2 )
end
end
end )
spec:RegisterStateExpr( "target_uas", function ()
return active_dot.unstable_affliction
end )
spec:RegisterStateExpr( "contagion", function ()
return active_dot.unstable_affliction > 0
end )
spec:RegisterStateExpr( "can_seed", function ()
local seed_targets = min( active_enemies, Hekili:GetNumTTDsAfter( action.seed_of_corruption.cast + ( 6 * haste ) ) )
if active_dot.seed_of_corruption < seed_targets - ( state:IsInFlight( "seed_of_corruption" ) and 1 or 0 ) then return true end
return false
end )
local Glyphed = IsSpellKnownOrOverridesKnown
-- Fel Imp 58959
spec:RegisterPet( "imp",
function() return Glyphed( 112866 ) and 58959 or 416 end,
"summon_imp",
3600 )
-- Voidlord 58960
spec:RegisterPet( "voidwalker",
function() return Glyphed( 112867 ) and 58960 or 1860 end,
"summon_voidwalker",
3600 )
-- Observer 58964
spec:RegisterPet( "felhunter",
function() return Glyphed( 112869 ) and 58964 or 417 end,
"summon_felhunter",
3600 )
-- Fel Succubus 120526
-- Shadow Succubus 120527
-- Shivarra 58963
spec:RegisterPet( "succubus",
function()
if Glyphed( 240263 ) then return 120526
elseif Glyphed( 240266 ) then return 120527
elseif Glyphed( 112868 ) then return 58963 end
return 1863
end,
3600 )
-- Wrathguard 58965
spec:RegisterPet( "felguard",
function() return Glyphed( 112870 ) and 58965 or 17252 end,
"summon_felguard",
3600 )
-- Abilities
spec:RegisterAbilities( {
agony = {
id = 980,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 136139,
handler = function ()
applyDebuff( "target", "agony", nil, max( ( talent.writhe_in_agony.enabled or azerite.sudden_onset.enabled ) and 4 or 1, debuff.agony.stack ) )
end,
},
--[[ banish = {
id = 710,
cast = 1.5,
cooldown = 0,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
}, ]]
burning_rush = {
id = 111400,
cast = 0,
cooldown = 0,
gcd = function () return buff.burning_rush.up and "off" or "spell" end,
startsCombat = true,
talent = "burning_rush",
texture = 538043,
handler = function ()
if buff.burning_rush.down then applyBuff( "burning_rush" )
else removeBuff( "burning_rush" ) end
end,
},
casting_circle = {
id = 221703,
cast = 0.5,
cooldown = 60,
gcd = "spell",
spend = 0.02,
spendType = "mana",
pvptalent = "casting_circle",
startsCombat = false,
texture = 1392953,
handler = function ()
applyBuff( "casting_circle", 8 )
end,
},
--[[ command_demon = {
id = 119898,
cast = 0,
cooldown = 0,
gcd = "spell",
startsCombat = true,
handler = function ()
end,
}, ]]
corruption = {
id = 172,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 136118,
handler = function ()
applyDebuff( "target", "corruption" )
end,
},
--[[ create_healthstone = {
id = 6201,
cast = 3,
cooldown = 0,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
},
create_soulwell = {
id = 29893,
cast = 3,
cooldown = 120,
gcd = "spell",
spend = 0.05,
spendType = "mana",
toggle = "cooldowns",
startsCombat = true,
handler = function ()
end,
}, ]]
curse_of_exhaustion = {
id = 334275,
cast = 0,
cooldown = 0,
gcd = "spell",
startsCombat = true,
texture = 136162,
handler = function ()
applyDebuff( "target", "curse_of_exhaustion" )
removeDebuff( "target", "curse_of_tongues" )
removeDebuff( "target", "curse_of_weakness" )
end,
},
curse_of_fragility = {
id = 199954,
cast = 0,
cooldown = 45,
gcd = "spell",
spend = 0.01,
spendType = "mana",
pvptalent = "curse_of_fragility",
startsCombat = true,
texture = 132097,
usable = function () return target.is_player end,
handler = function ()
applyDebuff( "target", "curse_of_fragility" )
setCooldown( "curse_of_tongues", max( 6, cooldown.curse_of_tongues.remains ) )
setCooldown( "curse_of_weakness", max( 6, cooldown.curse_of_weakness.remains ) )
end,
},
curse_of_tongues = {
id = 1714,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
pvptalent = "curse_of_tongues",
startsCombat = true,
texture = 136140,
handler = function ()
applyDebuff( "target", "curse_of_tongues" )
removeDebuff( "target", "curse_of_exhaustion" )
removeDebuff( "target", "curse_oF_weakness" )
setCooldown( "curse_of_fragility", max( 6, cooldown.curse_of_fragility.remains ) )
setCooldown( "curse_of_weakness", max( 6, cooldown.curse_of_weakness.remains ) )
end,
},
curse_of_weakness = {
id = 702,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 615101,
handler = function ()
applyDebuff( "target", "curse_of_weakness" )
removeDebuff( "target", "curse_of_exhaustion" )
removeDebuff( "target", "curse_oF_tongues" )
setCooldown( "curse_of_fragility", max( 6, cooldown.curse_of_fragility.remains ) )
setCooldown( "curse_of_tongues", max( 6, cooldown.curse_of_tongues.remains ) )
end,
},
dark_pact = {
id = 108416,
cast = 0,
cooldown = 60,
gcd = "spell",
toggle = "defensives",
startsCombat = false,
texture = 538538,
talent = "dark_pact",
handler = function ()
spend( 0.2 * health.current, "health" )
applyBuff( "dark_pact" )
end,
},
dark_soul = {
id = 113860,
cast = 0,
cooldown = 120,
gcd = "off",
toggle = "cooldowns",
spend = 0.01,
spendType = "mana",
startsCombat = false,
texture = 463286,
talent = "dark_soul_misery",
handler = function ()
applyBuff( "dark_soul_misery" )
stat.haste = stat.haste + 0.3
end,
copy = "dark_soul_misery"
},
deathbolt = {
id = 264106,
cast = 1,
cooldown = 30,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
pvptalent = "deathbolt",
handler = function ()
end,
},
demon_armor = {
id = 285933,
cast = 0,
cooldown = 0,
gcd = "spell",
pvptalent = "demon_armor",
startsCombat = false,
texture = 136185,
handler = function ()
applyBuff( "demon_armor" )
end,
},
--[[ demonic_circle = {
id = 48018,
cast = 0.5,
cooldown = 10,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
},
demonic_circle_teleport = {
id = 48020,
cast = 0,
cooldown = 30,
gcd = "spell",
spend = 0.03,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
-- Conduit in WarlockDemonology.lua
},
demonic_gateway = {
id = 111771,
cast = 2,
cooldown = 10,
gcd = "spell",
spend = 0.2,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
}, ]]
devour_magic = {
id = 19505,
cast = 0,
cooldown = 15,
gcd = "off",
spend = 0,
spendType = "mana",
startsCombat = true,
toggle = "interrupts",
usable = function ()
if buff.dispellable_magic.down then return false, "no dispellable magic aura" end
return true
end,
handler = function()
removeBuff( "dispellable_magic" )
end,
},
drain_life = {
id = 234153,
cast = function () return 5 * haste * ( legendary.claw_of_endereth.enabled and 0.5 or 1 ) end,
channeled = true,
breakable = true,
cooldown = 0,
gcd = "spell",
spend = function () return active_dot.soul_rot == 1 and 0 or 0.03 end,
spendType = "mana",
startsCombat = true,
texture = 136169,
tick_time = function () return class.auras.drain_life.tick_time end,
start = function ()
removeBuff( "inevitable_demise" )
removeBuff( "inevitable_demise_az" )
end,
finish = function ()
if conduit.accrued_vitality.enabled then applyBuff( "accrued_vitality" ) end
end,
auras = {
-- Conduit
accrued_vitality = {
id = 339298,
duration = 10,
max_stack = 1
},
-- Azerite
inevitable_demise_az = {
id = 273525,
duration = 20,
max_stack = 50
}
}
},
drain_soul = {
id = 198590,
cast = 5,
channeled = true,
cooldown = 0,
gcd = "spell",
prechannel = true,
breakable = true,
breakchannel = function () removeDebuff( "target", "drain_soul" ) end,
spend = 0.01,
spendType = "mana",
startsCombat = true,
talent = "drain_soul",
texture = 136163,
break_any = function ()
if not settings.manage_ds_ticks then return true end
return nil
end,
tick_time = function ()
if not talent.shadow_embrace.enabled or not settings.manage_ds_ticks then return nil end
return class.auras.drain_soul.tick_time
end,
start = function ()
applyDebuff( "target", "drain_soul" )
applyBuff( "casting", 5 * haste )
channelSpell( "drain_soul" )
removeStack( "decimating_bolt" )
removeBuff( "malefic_wrath" )
if talent.shadow_embrace.enabled then applyDebuff( "target", "shadow_embrace", nil, debuff.shadow_embrace.stack + 1 ) end
end,
tick = function ()
if not settings.manage_ds_ticks or not talent.shadow_embrace.enabled then return end
applyDebuff( "target", "shadow_embrace", nil, debuff.shadow_embrace.stack + 1 )
end,
},
--[[ enslave_demon = {
id = 1098,
cast = 3,
cooldown = 0,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
},
eye_of_kilrogg = {
id = 126,
cast = 2,
cooldown = 0,
gcd = "spell",
spend = 0.03,
spendType = "mana",
startsCombat = true,
handler = function ()
end,
}, ]]
fear = {
id = 5782,
cast = 1.7,
cooldown = 0,
gcd = "spell",
spend = 0.05,
spendType = "mana",
startsCombat = true,
handler = function ()
applyDebuff( "target", "fear" )
end,
},
fel_domination = {
id = 333889,
cast = 0,
cooldown = function () return 180 + conduit.fel_celerity.mod * 0.001 end,
gcd = "spell",
startsCombat = false,
texture = 237564,
essential = true,
nomounted = true,
nobuff = "grimoire_of_sacrifice",
handler = function ()
applyBuff( "fel_domination" )
end,
},
grimoire_of_sacrifice = {
id = 108503,
cast = 0,
cooldown = 30,
gcd = "spell",
startsCombat = false,
texture = 538443,
usable = function () return pet.exists and buff.grimoire_of_sacrifice.down end,
handler = function ()
applyBuff( "grimoire_of_sacrifice" )
end,
},
haunt = {
id = 48181,
cast = 1.5,
cooldown = 15,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 236298,
talent = "haunt",
handler = function ()
applyDebuff( "target", "haunt" )
if level > 51 then applyDebuff( "target", "shadow_embrace", nil, debuff.shadow_embrace.stack + 1 ) end
end,
},
health_funnel = {
id = 755,
cast = 5,
channeled = true,
breakable = true,
cooldown = 0,
gcd = "spell",
startsCombat = false,
texture = 136168,
start = function ()
end,
},
howl_of_terror = {
id = 5484,
cast = 0,
cooldown = 40,
gcd = "spell",
startsCombat = true,
texture = 607852,
talent = "howl_of_terror",
handler = function ()
applyDebuff( "target", "howl_of_terror" )
end,
},
malefic_rapture = {
id = 324536,
cast = 1.5,
cooldown = 0,
gcd = "spell",
spend = 1,
spendType = "soul_shards",
startsCombat = true,
texture = 236296,
handler = function ()
if legendary.malefic_wrath.enabled then addStack( "malefic_wrath", nil, 1 ) end
end,
},
mortal_coil = {
id = 6789,
cast = 0,
cooldown = 45,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 607853,
talent = "mortal_coil",
handler = function ()
applyDebuff( "target", "mortal_coil" )
gain( 0.2 * health.max, "health" )
end,
},
nether_ward = {
id = 212295,
cast = 0,
cooldown = 45,
gcd = "spell",
pvptalent = "nether_ward",
startsCombat = false,
texture = 135796,
handler = function ()
applyBuff( "nether_ward" )
end,
},
phantom_singularity = {
id = 205179,
cast = 0,
cooldown = 45,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 132886,
talent = "phantom_singularity",
handler = function ()
applyDebuff( "target", "phantom_singularity" )
end,
},
--[[ ritual_of_summoning = {
id = 698,
cast = 0,
cooldown = 120,
gcd = "spell",
spend = 0,
spendType = "mana",
toggle = "cooldowns",
startsCombat = true,
handler = function ()
end,
}, ]]
seed_of_corruption = {
id = 27243,
cast = 2.5,
cooldown = 0,
gcd = "spell",
spend = 1,
spendType = "soul_shards",
startsCombat = true,
texture = 136193,
velocity = 30,
usable = function () return dot.seed_of_corruption.down end,
impact = function ()
applyDebuff( "target", "seed_of_corruption" )
if active_enemies > 1 and talent.sow_the_seeds.enabled then
active_dot.seed_of_corruption = min( active_enemies, active_dot.seed_of_corruption + 2 )
end
end,
},
shadow_bolt = {
id = 686,
cast = 2,
cooldown = 0,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 136197,
velocity = 20,
notalent = "drain_soul",
cycle = function () return talent.shadow_embrace.enabled and "shadow_embrace" or nil end,
handler = function ()
removeBuff( "malefic_wrath" )
end,
impact = function ()
if talent.shadow_embrace.enabled then applyDebuff( "target", "shadow_embrace", nil, debuff.shadow_embrace.stack + 1 ) end
end,
},
shadowfury = {
id = 30283,
cast = 1.5,
cooldown = 60,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 607865,
handler = function ()
applyDebuff( "target", "shadowfury" )
end,
},
siphon_life = {
id = 63106,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 136188,
talent = "siphon_life",
handler = function ()
applyDebuff( "target", "siphon_life" )
end,
},
soulstone = {
id = 20707,
cast = 3,
cooldown = 600,
gcd = "spell",
startsCombat = false,
handler = function ()
applyBuff( "soulstone" )
end,
},
spell_lock = {
id = 19647,
known = function () return IsSpellKnownOrOverridesKnown( 119910 ) or IsSpellKnownOrOverridesKnown( 132409 ) end,
cast = 0,
cooldown = 24,
gcd = "off",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 136174,
toggle = "interrupts",
debuff = "casting",
readyTime = state.timeToInterrupt,
handler = function ()
interrupt()
end,
},
summon_darkglare = {
id = 205180,
cast = 0,
cooldown = function () return ( essence.vision_of_perfection.enabled and 0.87 or 1 ) * ( level > 57 and 120 or 180 ) end,
gcd = "spell",
spend = 0.02,
spendType = "mana",
toggle = "cooldowns",
startsCombat = true,
texture = 1416161,
handler = function ()
summonPet( "darkglare", 20 )
if debuff.agony.up then debuff.agony.expires = debuff.agony.expires + 8 end
if debuff.corruption.up then debuff.corruption.expires = debuff.corruption.expires + 8 end
-- if debuff.impending_catastrophe.up then debuff.impending_catastrophe.expires = debuff.impending_catastrophe.expires + 8 end
if debuff.scouring_tithe.up then debuff.scouring_tithe.expires = debuff.scouring_tithe.expires + 8 end
if debuff.siphon_life.up then debuff.siphon_life.expires = debuff.siphon_life.expires + 8 end
if debuff.soul_rot.up then debuff.soul_rot.expires = debuff.soul_rot.expires + 8 end
if debuff.unstable_affliction.up then debuff.unstable_affliction.expires = debuff.unstable_affliction.expires + 8 end
end,
},
summon_imp = {
id = 688,
cast = 2.5,
cooldown = 0,
gcd = "spell",
spend = function () return buff.fel_domination.up and 0 or 1 end,
spendType = "soul_shards",
usable = function () return not pet.alive end,
handler = function () summonPet( "imp" ) end,
},
summon_voidwalker = {
id = 697,
cast = 2.5,
cooldown = 0,
gcd = "spell",
spend = function () return buff.fel_domination.up and 0 or 1 end,
spendType = "soul_shards",
usable = function () return not pet.alive end,
handler = function () summonPet( "voidwalker" ) end,
},
summon_felhunter = {
id = 691,
cast = function () return ( buff.fel_domination.up and 0.5 or 6 ) * haste end,
cooldown = 0,
gcd = "spell",
spend = function () return buff.fel_domination.up and 0 or 1 end,
spendType = "soul_shards",
essential = true,
nomounted = true,
bind = "summon_pet",
usable = function ()
if pet.alive then return false, "pet is alive"
elseif buff.grimoire_of_sacrifice.up then return false, "grimoire_of_sacrifice is up" end
return true
end,
handler = function ()
removeBuff( "fel_domination" )
summonPet( "felhunter" )
end,
copy = { "summon_pet", 112869 }
},
summon_succubus = {
id = 712,
cast = 2.5,
cooldown = 0,
gcd = "spell",
spend = function () return buff.fel_domination.up and 0 or 1 end,
spendType = "soul_shards",
usable = function () return not pet.alive end,
handler = function () summonPet( "succubus" ) end,
},
unending_breath = {
id = 5697,
cast = 0,
cooldown = 0,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = false,
texture = 136148,
handler = function ()
applyBuff( "unending_breath" )
end,
},
unending_resolve = {
id = 104773,
cast = 0,
cooldown = 180,
gcd = "spell",
spend = 0.02,
spendType = "mana",
toggle = "defensives",
startsCombat = true,
handler = function ()
applyBuff( "unending_resolve" )
end,
},
unstable_affliction = {
id = function () return pvptalent.rampant_afflictions.enabled and 342938 or 316099 end,
cast = 1.5,
cooldown = 0,
gcd = "spell",
spend = 0.01,
spendType = "mana",
startsCombat = true,
texture = 136228,
handler = function ()
if azerite.cascading_calamity.enabled and debuff.unstable_affliction.up then
applyBuff( "cascading_calamity" )
end
applyDebuff( "target", "unstable_affliction" )
if azerite.dreadful_calling.enabled then
gainChargeTime( "summon_darkglare", 1 )
end
end,
copy = { 342938, 316099 },
auras = {
-- Azerite
cascading_calamity = {
id = 275378,
duration = 15,
max_stack = 1
}
}
},
vile_taint = {
id = 278350,
cast = 1.5,
cooldown = 20,
gcd = "spell",
spend = 1,
spendType = "soul_shards",
startsCombat = true,
texture = 1391774,
handler = function ()
applyDebuff( "target", "vile_taint" )
end,
},
-- Warlock - Kyrian - 312321 - scouring_tithe (Scouring Tithe)
scouring_tithe = {
id = 312321,
cast = 2,
cooldown = 40,
gcd = "spell",
spend = 0.02,
spendType = "mana",
startsCombat = true,
texture = 3565452,
toggle = "essences",
handler = function ()
applyDebuff( "target", "scouring_tithe" )
end,
auras = {
scouring_tithe = {
id = 312321,
duration = 18,
max_stack = 1,
},
-- Conduit
soul_tithe = {
id = 340238,
duration = 10,
max_stack = 1
},
-- Legendary
languishing_soul_detritus = {
id = 356255,
duration = 8,
max_stack = 1,
},
},
},
-- Warlock - Necrolord - 325289 - decimating_bolt (Decimating Bolt)
decimating_bolt = {
id = 325289,
cast = 2.5,
cooldown = 45,
gcd = "spell",
spend = 0.04,
spendType = "mana",
startsCombat = true,
texture = 3578232,
toggle = "essences",
handler = function ()
applyBuff( "decimating_bolt", nil, 3 )
if legendary.shard_of_annihilation.enabled then
applyBuff( "shard_of_annihilation" )
end
end,
auras = {
decimating_bolt = {
id = 325299,
duration = 3600,
max_stack = 3,
},
shard_of_annihilation = {
id = 356342,
duration = 44,
max_stack = 1,
}
}
},
-- Warlock - Night Fae - 325640 - soul_rot (Soul Rot)
soul_rot = {
id = 325640,
cast = 1.5,
cooldown = 60,
gcd = "spell",
spend = 0.005,
spendType = "mana",
startsCombat = true,
texture = 3636850,
toggle = "essences",
handler = function ()
applyDebuff( "target", "soul_rot" )
active_dot.soul_rot = min( 4, active_enemies )
if legendary.decaying_soul_satchel.enabled then
applyBuff( "decaying_soul_satchel", nil, active_dot.soul_rot )
end
end,
auras = {
soul_rot = {
id = 325640,
duration = 8,
max_stack = 1
},
decaying_soul_satchel = {
id = 356369,
duration = 8,
max_stack = 4,
}
}
},
-- Warlock - Venthyr - 321792 - impending_catastrophe (Impending Catastrophe)
impending_catastrophe = {
id = 321792,
cast = 2,
cooldown = 60,
gcd = "spell",
spend = 0.04,
spendType = "mana",
startsCombat = true,
texture = 3565726,
toggle = "essences",
velocity = 30,
impact = function ()
applyDebuff( "target", "impending_catastrophe" )
end,
auras = {
impending_catastrophe = {
id = 322170,
duration = function () return 12 * ( 1 + conduit.catastrophic_origin.mod * 0.01 ) end,
max_stack = 1,
copy = "impending_catastrophe_dot"
},
}
},
} )
spec:RegisterSetting( "manage_ds_ticks", false, {
name = "Model |T136163:0|t Drain Soul Ticks",
desc = "If checked, the addon will expend |cFFFF0000more CPU|r determining when to break |T136163:0|t Drain Soul channels in favor of " ..
"other spells. This is generally not worth it, but is technically more accurate.",
type = "toggle",
width = "full"
} )
spec:RegisterSetting( "agony_macro", nil, {
name = "|T136139:0|t Agony Macro",
desc = "Using a macro makes it easier to apply your DOT effects to other targets without switching targets.",
type = "input",
width = "full",
multiline = true,
get = function () return "#showtooltip\n/use [@mouseover,harm,nodead][] " .. class.abilities.agony.name end,
set = function () end,
} )
spec:RegisterSetting( "corruption_macro", nil, {
name = "|T136118:0|t Corruption Macro",
desc = "Using a macro makes it easier to apply your DOT effects to other targets without switching targets.",
type = "input",
width = "full",
multiline = true,
get = function () return "#showtooltip\n/use [@mouseover,harm,nodead][] " .. class.abilities.corruption.name end,
set = function () end,
} )
spec:RegisterSetting( "sl_macro", nil, {
name = "|T136188:0|t Siphon Life Macro",
desc = "Using a macro makes it easier to apply your DOT effects to other targets without switching targets.",
type = "input",
width = "full",
multiline = true,
get = function () return "#showtooltip\n/use [@mouseover,harm,nodead][] " .. class.abilities.siphon_life.name end,
set = function () end,
} )
spec:RegisterOptions( {
enabled = true,
aoe = 3,
nameplates = false,
nameplateRange = 8,
damage = true,
damageExpiration = 6,
potion = "spectral_intellect",
package = "Affliction",
} )
spec:RegisterPack( "Affliction", 20210707, [[davLZcqiqvTiqKqpcfHnPu6tOOgfO4uGuRIQsvVceAwuvClvsyxc9lvsnmqehduzzsHEMkjnnPiDnuKABGOY3OQuACGOQZrvjP1HIO5bk5Ekf7duLdsvjSqqWdbrzIGi1frrI2ivLe9ruKaNKQsXkbjVefjiZeuk3KQs0oLc(jisAOOiPLsvj1trPPkf1vbrI2kksOVsvPYyLIyVc(RkgSQomLfRs9yQmzLCzKnlv(SuA0kvNw0QPQKWRHKzd1THy3K(TKHlvDCvs0YbEoQMoX1PkBhs9DvIXdkvNNQQ1dIemFu4(Oib1(vCaUqZb2LjuOHgHKgHds8TqIVncjqEMUr4AAGv83tb2EZHYAPaRAiuG1x01HtNKLgy7n)4YwHMdS8Yd4Oa7Ui9CM86RBtz37o6kKR5jIh2KSuhW6KR5jI76a7TxIfFJgUdSltOqdncjnchK4BHeFBesG8mDJqIVAGL3tUqdnc5y6a7EUwKgUdSlI7cS(IUoC6KS059Dgaxouduq5H9pVV1N5BesAeUbQbkiB30wIZKduxX8(I1IwZZ2ty88Ww5qfhOUI59fRfTMhstOlpW8(sRnDXbQRyEFXArR5VbKHYTBQs45XvB6MVRaZdPbwQZZwE44a1vmFZxid18(sdtDPBEFT1lEaAEC1MU5LA(lfa18z38(lpMb08ijNNA7828IHjvMp15LDtMhuxIduxX8mLQDJP591gsVPY8(IUoC6KSu(8mv0m15fdtQehOUI5B(czO4Zl18g6kxZFJRlP2opK2aOAXgGMp15r8WsEfIbAjz(lxxZdPHuBMpVxFCG6kMhYkDrkNMNxi08qAdGQfBaAEMkG6N3zymFEPMhqlphnVRq69etYsNxsekoqDfZZsY88cHM3zy8XCsw6bNCzEsfqs85LAEUasNmVuZBORCnVBNCOsTDECYf(8YUjZFPuML5VP5bK52P18WyTwQWh64a1vmpKQI9pplrR5l1rZ3dORO3dJJduxX8(ILVcpUmpKI3EaDEidsZN)M6kanpPR5RU57Y2DbsX5XvB6MxQ5T(ES)5lf7FEPM)U4857Y2DHppmAjZlaJVpFV5qXHooqDfZ7Ret8DhW6KRzkwytsmnpBHrtQmVZuhHpz38UDtBP18snFQcbaE9Yj7Ib2Eq1LykWYemX8(IUoC6KS059DgaxoudumbtmpuEy)Z7B9z(gHKgHBGAGIjyI5HSDtBjotoqXemX8xX8(I1IwZZ2ty88Ww5qfhOycMy(RyEFXArR5H0e6YdmVV0AtxCGIjyI5VI59fRfTM)gqgk3UPkHNhxTPB(UcmpKgyPopB5HJdumbtm)vmFZxid18(sdtDPBEFT1lEaAEC1MU5LA(lfa18z38(lpMb08ijNNA7828IHjvMp15LDtMhuxIdumbtm)vmptPA3yAEFTH0BQmVVORdNojlLpptfntDEXWKkXbkMGjM)kMV5lKHIpVuZBORCn)nUUKA78qAdGQfBaA(uNhXdl5vigOLK5VCDnpKgsTz(8E9XbkMGjM)kMhYkDrkNMNxi08qAdGQfBaAEMkG6N3zymFEPMhqlphnVRq69etYsNxsekoqXemX8xX8SKmpVqO5DggFmNKLEWjxMNubKeFEPMNlG0jZl18g6kxZ72jhQuBNhNCHpVSBY8xkLzz(BAEazUDAnpmwRLk8HooqXemX8xX8qQk2)8SeTMVuhnFpGUIEpmooqXemX8xX8(ILVcpUmpKI3EaDEidsZN)M6kanpPR5RU57Y2DbsX5XvB6MxQ5T(ES)5lf7FEPM)U4857Y2DHppmAjZlaJVpFV5qXHooqXemX8xX8(kXeF3bSo5AMIf2KetZZwy0KkZ7m1r4t2nVB30wAnVuZNQqaGxVCYU4a1aL5KSuEShqUc52KnDe(SkKunjl1NSBJKie8GKTWVNKOHt00w4F711fBbjsLa6uDhU5azx6OOx)aL5KSuEShqUc52eiU5AUhcsPNEsgOmNKLYJ9aYvi3MaXnx7XPtkeIpQHqBKcHov3bPuUakp(XvkxaEojlLpqzojlLh7bKRqUnbIBU2JtNuieFudH2Wlmz78dNCasoc5218k9ObkZjzP8ypGCfYTjqCZ1TGePsaDQUd3CGSlDKpz3gXWKkXwqIujGov3HBoq2LoksQDJP1aL5KSuEShqUc52eiU56omX3DaRtgOmNKLYJ9aYvi3MaXnxJ2aPDJjFudH2SkHFaKT87dAd7rBmNKOPZQKORaaVEjlfEqYwZjjA6SkjATL6hEqYwZjjA6Skj6PCXUX0X66WPtYsHhKSfg4lgMujYZ(9sp4SJIKA3yAXGH5KenDwLe5z)EPhC2rWdsGElmRsI97MkfYHNARh2aP4pkPdvQTmyaFXWKkX(DtLc5WtT1dBGu8hj1UX0c6bkZjzP8ypGCfYTjqCZ1EC6KcH4JAi0gdsb(Ubm(PRu5uDN(6cbgOmNKLYJ9aYvi3MaXnxZjADQUJRaaVEjl1hCQ0XT2ahK4t2TH3ty8rmqlj8iNO1P6oUca86LS0Jve82C1bkZjzP8ypGCfYTjqCZ17MNkduMtYs5XEa5kKBtG4MR9uUy3y6yDD40jzPdudumbtmptjStopHwZtOjG)5LeHMx2P5nNuG5t(8gAlX2nMIduMtYs5B49egFWLd1aL5KSuoe3C9IqxEGdI1MUbkZjzPCiU5ANHXhZjzPhCYfFudH2yf5dxaPt2aNpz3gZjjA6qkHKehExDGIjM3x4KS05Xjx4Z3vG5fqQOiz(BA3qNfiopRycFEdqZZn00A(Ucm)n1vaAE2YdpVVUKR9ni9KUsTDEiZeJlGQFNUMPUBQuiZZMARh2aP43N5lzNaxsonFPZ7QcVQl6aL5KSuoe3CTZW4J5KS0do5IpQHqBeqQOi5W7XPCC7Kd1aL5KSuoe3CTZW4J5KS0do5IpQHqBwe28tRJasffj8bkZjzPCiU5ANHXhZjzPhCYfFudH2WftocivuKW9HlG0jBGZNSBdmRsI8YdFaLeL0Hk1wgmwLetKEsxP2ECMyCbu970zvsushQuBzWyvsSF3uPqo8uB9Wgif)rjDOsTf6T8YdF47gybVRYGXQKi6ethXsvIs6qLAldgIHjvI86Yr2PdNOfFGYCswkhIBU2zy8XCsw6bNCXh1qOnldXAPJasffjCFYUnUcnPMkrnB3LtNrBHb(OnqA3ykkGurrYH3JtHbdxv4vDrJ8YdFaLebeILkhEncjmyadAdK2nMIcivuKCkL26QcVQlAKxE4dOKiGqSu5WsaPIIKiCrxv4vDrJacXsLdndgWG2aPDJPOasffjh5sT1vfEvx0iV8WhqjraHyPYHLasffjXgJUQWR6IgbeILkhAOzWWvOj1ujIMuz3pylmWhTbs7gtrbKkkso8ECkmy4QcVQlAmr6jDLA7XzIXfq1VtraHyPYHxJqcdgWG2aPDJPOasffjNsPTUQWR6IgtKEsxP2ECMyCbu97ueqiwQCyjGurrseUORk8QUOraHyPYHMbdyqBG0UXuuaPIIKJCP26QcVQlAmr6jDLA7XzIXfq1VtraHyPYHLasffjXgJUQWR6IgbeILkhAOzWagxHMutLOsoqHlWIbdxHMutLik)G0ugmCfAsnvIAPe0BHb(OnqA3ykkGurrYH3JtHbdxv4vDrJ97MkfYHNARh2aP4pcielvo8AesyWag0giTBmffqQOi5ukT1vfEvx0y)UPsHC4P26Hnqk(JacXsLdlbKkksIWfDvHx1fncielvo0myadAdK2nMIcivuKCKl1wxv4vDrJ97MkfYHNARh2aP4pcielvoSeqQOij2y0vfEvx0iGqSu5qdndgWxmmPsSF3uPqo8uB9Wgif)rsTBmT2cd8rBG0UXuuaPIIKdVhNcdgUQWR6Ig5EiiLEwgavl2aueqiwQC41iKWGbmOnqA3ykkGurrYPuARRk8QUOrUhcsPNLbq1InafbeILkhwcivuKeHl6QcVQlAeqiwQCOzWag0giTBmffqQOi5ixQTUQWR6Ig5EiiLEwgavl2aueqiwQCyjGurrs
end