-- 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
else
local amount = k : match ( " time_to_(%d+) " )
amount = amount and tonumber ( amount )
if amount then return state : TimeToResource ( t , amount ) end
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 ,
} ,
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 ( _ , 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 , false )
spec : RegisterGear ( " tier28 " , 188884 , 188887 , 188888 , 188889 , 188890 )
-- Tier 28
spec : RegisterSetBonuses ( " tier28_2pc " , 364437 , " tier28_4pc " , 363953 )
-- 2-Set - Deliberate Malice - Malefic Rapture's damage is increased by 15% and each cast extends the duration of Corruption, Agony, and Unstable Affliction by 2 sec.
-- 4-Set - Calamitous Crescendo - While Agony, Corruption, and Unstable Affliction are active, your Drain Soul has a 10% chance / Shadow Bolt has a 20% chance to make your next Malefic Rapture cost no Soul Shards and cast instantly.
spec : RegisterAura ( " calamitous_crescendo " , {
id = 364322 ,
duration = 10 ,
max_stack = 1 ,
} )
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
class.abilities . summon_pet = class.abilities . summon_felhunter
if not SUMMON_DEMON_TEXT then
SUMMON_DEMON_TEXT = GetSpellInfo ( 180284 )
class.abilityList . summon_pet = " |T136082:0|t |cff00ccff[ " .. ( SUMMON_DEMON_TEXT or " Summon Demon " ) .. " ]|r "
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 ( " sayaad " ,
function ( )
if Glyphed ( 240263 ) then return 120526
elseif Glyphed ( 240266 ) then return 120527
elseif Glyphed ( 112868 ) then return 58963
elseif Glyphed ( 365349 ) then return 184600
end
return 1863
end ,
" summon_sayaad " ,
3600 ,
" incubus " , " succubus " )
-- 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 = function ( ) return buff.calamitous_crescendo . up and 0 or 1.5 end ,
cooldown = 0 ,
gcd = " spell " ,
spend = function ( ) return buff.calamitous_crescendo . up and 0 or 1 end ,
spendType = " soul_shards " ,
startsCombat = true ,
texture = 236296 ,
handler = function ( )
if legendary.malefic_wrath . enabled then addStack ( " malefic_wrath " , nil , 1 ) end
if set_bonus.tier28_2pc > 0 then
if debuff.corruption . up then debuff.corruption . expires = debuff.corruption . expires + 2 end
if debuff.agony . up then debuff.agony . expires = debuff.agony . expires + 2 end
if debuff.unstable_affliction . up then debuff.unstable_affliction . expires = debuff.unstable_affliction . expires + 2 end
end
if buff.calamitous_crescendo . up then removeBuff ( " calamitous_crescendo " ) 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 = 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 " ,
usable = function ( ) return not pet.alive end ,
handler = function ( ) summonPet ( " imp " ) end ,
} ,
summon_voidwalker = {
id = 697 ,
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 " ,
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_sayaad = {
id = 366222 ,
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 " ,
usable = function ( ) return not pet.alive end ,
handler = function ( ) summonPet ( " sayaad " ) end ,
copy = { " summon_incubus " , " summon_succubus " }
} ,
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 " ,
indicator = function ( )
if active_enemies > 1 and settings.cycle and target.time_to_die > shortest_ttd then return " cycle " end
end ,
handler = function ( )
applyBuff ( " decimating_bolt " , nil , 3 )
if legendary.shard_of_annihilation . enabled then
applyBuff ( " shard_of_annihilation " )
end
if soulbind.kevins_oozeling . enabled then applyBuff ( " kevins_oozeling " ) 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 " , 20220327 , [ [ dq1xQdqiQQ0IiaHEeKO2ei5tekJcs1PGuwLkPsVsLOzrGUfic7sIFPsYWGe6yqslts4zsIAAQKY1OQI2giI ( gKinoibDoqQsRJa4DGufAEGuUNq1 ( iGoivvWcvj8qquMOkPQlcsvzJGuf9rvsfAKQKkYjja1kbHxQsQGmtquDtqKStcv ) eKQQHcIulLQk0tHyQuv1vjaPTsaI ( kKaJvsK3sacURkPcSxb ) vfdwvhMYIvPEmvMSsDzKnlKplPgTsCArRgKQGxtqZgQBdQDt63kgUs64qIy5apNOPJ66uLTtiFxsA8Gu58cL1RsQOMpvL7RsQGA ) sDa1G ) bKTXuq8kqXkQafRCfO0cQO0kqruVwaHJTsbKvZj0QPaIAWuaXpefHthNJgqwTy4X2b ) diYXd4OaYcZRsb4QRQtEX7U4g4RKjSh24CuhWI4RKjS7QaYTxIzbSgUdiBJPG4vGIvubkw5kqPfurPvGIOwrarUsUG4vaj9ZaYsU3KgUdiBs6ci ( HOiC64C0 ( rbgapoHneqkd4w6VcuQG9xbkwrfneneq2IP1KuaAiGe97h2BA3pYkHX9d5JtyPHas0VFyVPD ) xpjA8a9dPS60vAiGe97h2BA3 ) nGmHUftvc3pEQtx ) rdO ) RhyP2pY4HlneqI ( 9 Vkzc7hszykkD97hTv2dq9JN601pp9xDac7pJ6p24jgG6hoLYuR736NnmPC ) P2pVyC ) GPAPHas0p0NA3yQF ) ObVAk3VFikcNoohv2pKweKUF2WKYLgcir ) ( xLmHY ( 5 PFt0K7 ( VXt1uR7 ) 6 nGWASbO ( tTFypmNqc2a1e3F1RM ( VEOF ) L97TwAiGe9dzJUjvs9lhyQ ) R3acRXgG6hsdO1 ( Dggl7NN ( b02Zr97g4vp24C0 ( 5 eMkneqI ( riUF5at97mm ( yooh9Gtj3pPmijz ) 80 VKbPJ7NN ( nrtU73TqoHPw3poLSSFEX4 ( RoQyC ) 3 u ) aYCl0UF0TAlv ) IwPHas0p0VIJ1pcr7 ( h1r9VciiXQhgxAiGe97h2qp4j5 ( fq82dO9dzxVS ) BkAau ) KU7FI6pkRxybe7hp1PRFE63wxXX6FuCS ( 5 P ) 7 rk7pkRxyz ) ORd3pdm5s ) RMtOeTsdbKOFONysU4aweFLaYbBCIP ( rgSis5 ( DM6i8jJ63TyAnT7NN ( tLjaWBLpzuPHas0VawzQgym1V4Kdm9dPqb9VcYbKCS ( XPKlbKvWeLykGGYOC ) ( HOiC64C0 ( rbgapoHneOmk3pKYaUL ( RaLky ) vGIvurdrdbkJY9dzlMwtsbOHaLr5 ( He97h2BA3pYkHX9d5JtyPHaLr5 ( He97h2BA3 ) 1 tIgpq ) qkRoDLgcugL7hs0VFyVPD ) 3 aYe6wmvjC ) 4 PoD9hnG ( VEGLA ) iJhU0qGYOC ) qI ( 9 Vkzc7hszykkD97hTv2dq9JN601pp9xDac7pJ6p24jgG6hoLYuR736NnmPC ) P2pVyC ) GPAPHaLr5 ( He9d9P2nM63pAWRMY97hIIWPJZrL9dPfbP7NnmPCPHaLr5 ( He97FvYek7NN ( nrtU7 ) gpvtTU ) R3acRXgG6p1 ( H9WCcjydutC ) vVA6 ) 6 H ( 9 x2V3APHaLr5 ( He9dzJUjvs9lhyQ ) R3acRXgG6hsdO1 ( Dggl7NN ( b02Zr97g4vp24C0 ( 5 eMkneOmk3pKOFeI7xoWu ) odJpMJZrp4uY9tkdss2pp9lzq64 ( 5 PFt0K7 ( DlKtyQ19Jtjl7NxmU ) QJkg3 ) n1pGm3cT7hDR2s1VOvAiqzuUFir ) q ) kow ) ieT7Fuh1 ) kGGeREyCPHaLr5 ( He97h2qp4j5 ( fq82dO9dzxVS ) BkAau ) KU7FI6pkRxybe7hp1PRFE63wxXX6FuCS ( 5 P ) 7 rk7pkRxyz ) ORd3pdm5s ) RMtOeTsdbkJY9dj6h6jMKloGfXxjGCWgNyQFKblIuUFNPocFYO ( DlMwt7 ( 5 P ) uzca8w5tgvAiqzuUFir ) cyLPAGXu ) ItoW0pKcf0 ) kihqYX6hNsU0q0qyoohvwwbKBGVnoEeHp7bovJZrfmJIZjmjquek ) UsCXWPick ) E7ffvQbj8Ka6mrhP5azu6OI3AdH54CuzzfqUb ( 24 lJFL0dgE0ZkXneMJZrLLva5g4BJVm ( vEs6KmblOAWuCEGPZeDGhvYGXtECJkzGNJZrLneMJZrLLva5g4BJVm ( vEs6KmblOAWuC5GjBrEKKdq8Hj3IMOepQHWCCoQSSci3aFB8LXVQgKWtcOZeDKMdKrPJemJIZgMuUuds4jb0zIosZbYO0rfsTBmTBimhNJklRaYnW3gFz8RIWKCXbSiUHWCCoQSSci3aFB8LXVsKbs7gtcQgmfFpS8aiBhtqrg2JIBoofrN9Wf3aaERCoQarrOmhNIOZE4IvpAmbIIqzoofrN9WfpvY2nMowueoDCoQarrOq3VSHjLlYCDz0doJOcP2nM2 ( 8 zoofrN9WfzUUm6bNrKarr0Gc99WL1ft5b ( itT2dBGKJv40jm1AF ( 8 lBys5Y6IP8aFKPw7HnqYXkKA3yAJwdH54CuzzfqUb ( 24 lJFLKO9zIoUba8w5CubXPsh3ooQOOGzuC5kHXh2a1ellsI2Nj64gaWBLZrp2qcmELBimhNJklRaYnW3gFz8RwmpLBimhNJklRaYnW3gFz8R8ujB3y6yrr40X5OneneOmk3p0h0ropM29tIiqS ( 5 eM6NxO ( nhpG ( tz ) MilX2nMkneMJZrLXLRegFWJtydH54Cu5LXVAtIgpWb2QtxdH54Cu5LXVYzy8XCCo6bNswq1GP42qckzq644Okygf3CCkIoKsWjjfyLBimhNJkVm ( vWgMIs3byRShGemJIF7ffvCg2GtE8KhhGKos3tXBTHaL7hYmmUFjTAaJP ( nhNJ2poLC ) rdOFXjhyWdy3pKcf0FQ9J4FPFiZdaiLXX6FuCS ( NvoHZRZ0U ) Ob0VNK6VAYl9dPrkneMJZrLxg ) kGNEmhNJEWPKfunykUsoWCGRkOKbPJJJQGzuC3iIut5IsoWGhWgkGNsrdOMkWgMIs3PkW4fOmhNIOdPeCsY4OcfBys5Y6IP8aFKPw7HnqYXAiq5 ( 9 doohTFCkzz ) rdOFgKQqI7 ) Mwmr5ak9JWgl73au ) steT7pAa9FtrdG6hz8W97hh ( kbm8kP7uR7hYm2KmywxORG0lMYdC ) iPw7HnqYXeS ) Hxiq1us9pA ) UzW7PQwAimhNJkVm ( vodJpMJZrp4uYcQgmfNbPkK4JCfN8XTqoHneMJZrLxg ) kNHXhZX5OhCkzbvdMIVjSfJ2hgKQqILneMJZrLxg ) kNHXhZX5OhCkzbvdMIlzJpmivHelfuYG0XXrvWmko67HlYXdFadx40jm1AF ( 2 dxs4vs3PwFCgBsgmRl0zpCHtNWuR95BpCzDXuEGpYuR9Wgi5yfoDctTgnOKJh ( ixmWwGv2NV9WfrjMoSLkx40jm1AF ( ydtkxKt1dVqhjrBzdH54Cu5LXVYzy8XCCo6bNswq1GP4Bd2QPddsviXsbZO4UrePMYfnRx4tKrqHUFfzG0UXuHbPkK4JCfNSpFUzW7PQwKJh ( agUaiylvPaRaf95dDrgiTBmvyqQcj ( mkbLBg8EQQf54HpGHlac2svcngKQqIlOwCZG3tvTaiylvjA ( 8 HUidK2nMkmivHeF4QduUzW7PQwKJh ( agUaiylvj0yqQcjUurXndEpv1cGGTuLOHMpFUrePMYfrKYlXaqHUFfzG0UXuHbPkK4JCfNSpFUzW7PQws4vs3PwFCgBsgmRlubqWwQsbwbk6Zh6ImqA3yQWGufs8zuck3m49uvlj8kP7uRpoJnjdM1fQaiylvj0yqQcjUGAXndEpv1cGGTuLO5Zh6ImqA3yQWGufs8HRoq5MbVNQAjHxjDNA9XzSjzWSUqfabBPkHgdsviXLkkUzW7PQwaeSLQen085dD3iIut5IsoWGhW2Np3iIut5IWyG0uF ( CJisnLl6OeAqHUFfzG0UXuHbPkK4JCfNSpFUzW7PQwwxmLh4Jm1ApSbsowbqWwQsbwbk6Zh6ImqA3yQWGufs8zuck3m49uvlRlMYd8rMATh2ajhRaiylvj0
end