diff --git a/Classes.lua b/Classes.lua index 83dd5157d..59a710ea4 100644 --- a/Classes.lua +++ b/Classes.lua @@ -584,8 +584,6 @@ local HekiliSpecMixin = { end end, - - RegisterPotion = function( self, potion, data ) self.potions[ potion ] = data @@ -1017,16 +1015,17 @@ local HekiliSpecMixin = { RegisterPet = function( self, token, id, spell, duration, ... ) CommitKey( token ) - + + -- Register the main pet. self.pets[ token ] = { id = type( id ) == "function" and setfenv( id, state ) or id, token = token, spell = spell, duration = type( duration ) == "function" and setfenv( duration, state ) or duration } - + + -- Process copies. local n = select( "#", ... ) - if n and n > 0 then for i = 1, n do local copy = select( i, ... ) @@ -1034,14 +1033,70 @@ local HekiliSpecMixin = { end end end, + + + RegisterPets = function( self, pets ) + for token, data in pairs( pets ) do + -- Extract fields from the pet definition. + local id = data.id + local spell = data.spell + local duration = data.duration + local copy = data.copy + + -- Register the pet and handle the copy field if it exists. + if copy then + self:RegisterPet( token, id, spell, duration, copy ) + else + self:RegisterPet( token, id, spell, duration ) + end + end + end, - RegisterTotem = function( self, token, id ) + + RegisterTotem = function( self, token, id, ... ) + -- Register the primary totem. self.totems[ token ] = id self.totems[ id ] = token - + + -- Handle copies if provided. + local n = select( "#", ... ) + if n and n > 0 then + for i = 1, n do + local copy = select( i, ... ) + self.totems[ copy ] = id + self.totems[ id ] = copy + end + end + + -- Commit the primary token. CommitKey( token ) end, + RegisterTotems = function( self, totems ) + for token, data in pairs( totems ) do + local id = data.id + local copy = data.copy + + -- Register the primary totem. + self.totems[ token ] = id + self.totems[ id ] = token + + -- Register any copies (aliases). + if copy then + if type( copy ) == "string" then + self.totems[ copy ] = id + self.totems[ id ] = copy + elseif type( copy ) == "table" then + for _, alias in ipairs( copy ) do + self.totems[ alias ] = id + self.totems[ id ] = alias + end + end + end + + CommitKey( token ) + end + end, GetSetting = function( self, info ) local setting = info[ #info ] diff --git a/State.lua b/State.lua index c21cf504e..194283bd2 100644 --- a/State.lua +++ b/State.lua @@ -1175,18 +1175,21 @@ state.removeDebuff = removeDebuff local function removeDebuffStack( unit, aura, stacks ) stacks = stacks or 1 - local d = state.debuff[ aura ] + if not d then return 0 end - if not d then return end + local removed = min( stacks, d.count ) if d.count > stacks then d.lastCount = d.count - d.count = max( 1, d.count - stacks ) + d.count = max( 0, d.count - stacks ) else removeDebuff( unit, aura ) end + + return removed end + state.removeDebuffStack = removeDebuffStack diff --git a/TheWarWithin/DeathKnightUnholy.lua b/TheWarWithin/DeathKnightUnholy.lua index b76dccb57..854e8bb58 100644 --- a/TheWarWithin/DeathKnightUnholy.lua +++ b/TheWarWithin/DeathKnightUnholy.lua @@ -13,8 +13,8 @@ local PTR = ns.PTR local strformat = string.format -local me = Hekili:NewSpecialization( 252 ) -me:RegisterResource( Enum.PowerType.Runes, { +local spec = Hekili:NewSpecialization( 252 ) +spec:RegisterResource( Enum.PowerType.Runes, { rune_regen = { last = function () return state.query_time end, @@ -151,19 +151,7 @@ me:RegisterResource( Enum.PowerType.Runes, { end })) - -me:RegisterResource( Enum.PowerType.RunicPower ) - - -me:RegisterStateFunction( "apply_festermight", function( n ) - if azerite.festermight.enabled or talent.festermight.enabled then - if buff.festermight.up then - addStack( "festermight", buff.festermight.remains, n ) - else - applyBuff( "festermight", nil, n ) - end - end -end ) +spec:RegisterResource( Enum.PowerType.RunicPower ) local spendHook = function( amt, resource, noHook ) @@ -172,11 +160,11 @@ local spendHook = function( amt, resource, noHook ) end end -me:RegisterHook( "spend", spendHook ) +spec:RegisterHook( "spend", spendHook ) -- Talents -me:RegisterTalents( { +spec:RegisterTalents( { -- DeathKnight abomination_limb = { 76049, 383269, 1 }, -- Sprout an additional limb, dealing 75,598 Shadow damage over 12 sec to all nearby enemies. Deals reduced damage beyond 5 targets. Every 1 sec, an enemy is pulled to your location if they are further than 8 yds from you. The same enemy can only be pulled once every 4 sec. antimagic_barrier = { 76046, 205727, 1 }, -- Reduces the cooldown of Anti-Magic Shell by 20 sec and increases its duration and amount absorbed by 40%. @@ -305,7 +293,7 @@ me:RegisterTalents( { -- PvP Talents -me:RegisterPvpTalents( { +spec:RegisterPvpTalents( { bloodforged_armor = 5585, -- (410301) Death Strike reduces all Physical damage taken by 20% for 3 sec. dark_simulacrum = 41, -- (77606) Places a dark ward on an enemy player that persists for 12 sec, triggering when the enemy next spends mana on a spell, and allowing the Death Knight to unleash an exact duplicate of that spell. doomburst = 5436, -- (356512) Sudden Doom also causes your next Death Coil to burst up to 2 Festering Wounds and reduce the target's movement speed by 45% per burst. Lasts 3 sec. @@ -318,24 +306,33 @@ me:RegisterPvpTalents( { strangulate = 5430, -- (47476) Shadowy tendrils constrict an enemy's throat, silencing them for 4 sec. } ) - -- Auras -me:RegisterAuras( { +spec:RegisterAuras( { -- Your Runic Power spending abilities deal $w1% increased damage. a_feast_of_souls = { id = 440861, duration = 3600, max_stack = 1, }, + abomination_limb = { + id = 383269, + duration = 12, + max_stack = 1, + }, -- Talent: Absorbing up to $w1 magic damage. Immune to harmful magic effects. - -- https://wowhead.com/beta/spell=48707 + -- https://wowhead.com/spell=48707 antimagic_shell = { id = 48707, duration = 5, max_stack = 1 }, + apocalyptic_conquest = { + id = 444763, + duration = 3600, + max_stack = 1, + }, -- Talent: Summoning ghouls. - -- https://wowhead.com/beta/spell=42650 + -- https://wowhead.com/spell=42650 army_of_the_dead = { id = 42650, duration = 4, @@ -343,7 +340,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Talent: Stunned. - -- https://wowhead.com/beta/spell=221562 + -- https://wowhead.com/spell=221562 asphyxiate = { id = 108194, duration = 4.0, @@ -352,7 +349,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Talent: Disoriented. - -- https://wowhead.com/beta/spell=207167 + -- https://wowhead.com/spell=207167 blinding_sleet = { id = 207167, duration = 5, @@ -366,18 +363,19 @@ me:RegisterAuras( { max_stack = 1 }, -- You may not benefit from the effects of Blood Draw. - -- https://wowhead.com/beta/spell=374609 + -- https://wowhead.com/spell=374609 blood_draw_cd = { id = 374609, duration = 120, max_stack = 1 }, -- Draining $w1 health from the target every $t1 sec. - -- https://wowhead.com/beta/spell=55078 + -- https://wowhead.com/spell=55078 blood_plague = { id = 55078, duration = function() return 24 * ( talent.ebon_fever.enabled and 0.5 or 1 ) end, tick_time = function() return 3 * ( talent.ebon_fever.enabled and 0.5 or 1 ) * ( buff.plaguebringer.up and 0.5 or 1 ) end, + type = "Disease", max_stack = 1, copy = "blood_plague_superstrain" }, @@ -387,8 +385,14 @@ me:RegisterAuras( { duration = 3600, max_stack = 1, }, + -- https://www.wowhead.com/spell=374557 + brittle = { + id = 374557, + duration = 5, + max_stack = 1, + }, -- Talent: Movement slowed $w1% $?$w5!=0[and Haste reduced $w5% ][]by frozen chains. - -- https://wowhead.com/beta/spell=45524 + -- https://wowhead.com/spell=45524 chains_of_ice = { id = 45524, duration = 8, @@ -409,6 +413,12 @@ me:RegisterAuras( { type = "Magic", max_stack = 1 }, + coil_of_devastation = { + id = 390271, + duration = 5, + type = "Disease", + max_stack = 1, + }, commander_of_the_dead = { -- 10.0.7 PTR id = 390260, duration = 30, @@ -416,7 +426,7 @@ me:RegisterAuras( { copy = "commander_of_the_dead_window" }, -- Talent: Controlled. - -- https://wowhead.com/beta/spell=111673 + -- https://wowhead.com/spell=111673 control_undead = { id = 111673, duration = 300, @@ -425,7 +435,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Taunted. - -- https://wowhead.com/beta/spell=56222 + -- https://wowhead.com/spell=56222 dark_command = { id = 56222, duration = 3, @@ -433,14 +443,14 @@ me:RegisterAuras( { max_stack = 1 }, -- Your next Death Strike is free and heals for an additional $s1% of maximum health. - -- https://wowhead.com/beta/spell=101568 + -- https://wowhead.com/spell=101568 dark_succor = { id = 101568, duration = 20, max_stack = 1 }, -- Talent: $?$w2>0[Transformed into an undead monstrosity.][Gassy.] Damage dealt increased by $w1%. - -- https://wowhead.com/beta/spell=63560 + -- https://wowhead.com/spell=63560 dark_transformation = { id = 63560, duration = 15, @@ -468,7 +478,7 @@ me:RegisterAuras( { end, }, -- Reduces healing done by $m1%. - -- https://wowhead.com/beta/spell=327095 + -- https://wowhead.com/spell=327095 death = { id = 327095, duration = 6, @@ -488,6 +498,13 @@ me:RegisterAuras( { -- blood_death_knight[137008] #14: { 'type': APPLY_AURA, 'subtype': ADD_PCT_MODIFIER, 'points': 48.2, 'target': TARGET_UNIT_CASTER, 'modifies': DAMAGE_HEALING, } -- death_rot[377540] #0: { 'type': APPLY_AURA, 'subtype': MOD_SPELL_DAMAGE_FROM_CASTER, 'points': 1.0, 'target': TARGET_UNIT_TARGET_ENEMY, } }, + death_and_decay_cleave_buff = { + id = 188290, + duration = 10, + type = "None", + max_stack = 1, + copy = "death_and_decay" + }, -- [444347] $@spelldesc444010 death_charge = { id = 444347, @@ -495,7 +512,7 @@ me:RegisterAuras( { max_stack = 1, }, -- Talent: The next $w2 healing received will be absorbed. - -- https://wowhead.com/beta/spell=48743 + -- https://wowhead.com/spell=48743 death_pact = { id = 48743, duration = 15, @@ -504,7 +521,7 @@ me:RegisterAuras( { death_rot = { id = 377540, duration = 10, - max_stack = 2, + max_stack = 10, }, -- Your movement speed is increased by $w1%, you cannot be slowed below $s2% of normal speed, and you are immune to forced movement effects and knockbacks. deaths_advance = { @@ -532,17 +549,16 @@ me:RegisterAuras( { duration = 20.0, max_stack = function() return 5 + ( talent.frenzied_bloodthirst.enabled and 2 or 0 ) end, }, - festering_scythe = { + festering_scythe_ready = { id = 458123, duration = 15, max_stack = 1, - copy = "festering_scythe_buff" + copy = "festering_scythe" }, - festering_scythe_stacking_buff = { + festering_scythe_stack = { id = 459238, duration = 3600, max_stack = 20, - copy = "festering_scythe_stack" }, -- Suffering from a wound that will deal [(20.7% of Attack power) / 1] Shadow damage when damaged by Scourge Strike. festering_wound = { @@ -551,30 +567,37 @@ me:RegisterAuras( { max_stack = 6, }, -- Reduces damage dealt to $@auracaster by $m1%. - -- https://wowhead.com/beta/spell=327092 + -- https://wowhead.com/spell=327092 famine = { id = 327092, duration = 6, max_stack = 3 }, -- Strength increased by $w1%. - -- https://wowhead.com/beta/spell=377591 + -- https://wowhead.com/spell=377591 festermight = { id = 377591, duration = 20, max_stack = 20 }, -- Suffering $w1 Frost damage every $t1 sec. - -- https://wowhead.com/beta/spell=55095 + -- https://wowhead.com/spell=55095 frost_fever = { id = 55095, duration = function() return 24 * ( talent.ebon_fever.enabled and 0.5 or 1 ) end, tick_time = function() return 3 * ( talent.ebon_fever.enabled and 0.5 or 1 ) * ( buff.plaguebringer.up and 0.5 or 1 ) end, max_stack = 1, + type = "Disease", copy = "frost_fever_superstrain" }, + frost_shield = { + id = 207203, + duration = 10, + type = "None", + max_stack = 1, + }, -- Movement speed slowed by $s2%. - -- https://wowhead.com/beta/spell=279303 + -- https://wowhead.com/spell=279303 frostwyrms_fury = { id = 279303, duration = 10, @@ -582,20 +605,22 @@ me:RegisterAuras( { max_stack = 1, }, -- Damage and attack speed increased by $s1%. - -- https://wowhead.com/beta/spell=377588 + -- https://wowhead.com/spell=377588 ghoulish_frenzy = { id = 377588, duration = 15, max_stack = 1, copy = 377589 }, + -- https://www.wowhead.com/spell=434153 + -- Gift of the San'layn The effectiveness of Essence of the Blood Queen is increased by 100%. Scourge Strike has been replaced with Vampiric Strike. gift_of_the_sanlayn = { id = 434153, - duration = 10, + duration = 15, max_stack = 1 }, -- Dealing $w1 Frost damage every $t1 sec. - -- https://wowhead.com/beta/spell=274074 + -- https://wowhead.com/spell=274074 glacial_contagion = { id = 274074, duration = 14, @@ -609,7 +634,7 @@ me:RegisterAuras( { max_stack = 1, }, -- Dealing $w1 Shadow damage every $t1 sec. - -- https://wowhead.com/beta/spell=275931 + -- https://wowhead.com/spell=275931 harrowing_decay = { id = 275931, duration = 4, @@ -624,30 +649,34 @@ me:RegisterAuras( { max_stack = 1, }, -- Talent: Damage taken reduced by $w3%. Immune to Stun effects. - -- https://wowhead.com/beta/spell=48792 + -- https://wowhead.com/spell=48792 icebound_fortitude = { id = 48792, duration = 8, max_stack = 1 }, - -- Attack speed increased by $w1%$?a436687[, and Runic Power spending abilities deal Shadowfrost damage.][.] + -- https://www.wowhead.com/spell=194879 + -- Icy Talons Attack speed increased by 18%. icy_talons = { id = 194879, - duration = 6, - max_stack = 3 + duration = 10, + max_stack = 3, }, -- Taking $w1% increased Shadow damage from $@auracaster. incite_terror = { id = 458478, duration = 15.0, - max_stack = 1, + max_stack = 5, }, + -- https://www.wowhead.com/spell=460049 + -- Infliction of Sorrow Scourge Strike consumes your Virulent Plague to deal 100% of their remaining damage to the target. infliction_of_sorrow = { id = 460049, duration = 15, - max_stack = 1 + max_stack = 1, }, -- Time between auto-attacks increased by $w1%. + -- https://www.wowhead.com/spell=391568 insidious_chill = { id = 391568, duration = 30, @@ -660,14 +689,14 @@ me:RegisterAuras( { max_stack = 1, }, -- Casting speed reduced by $w1%. - -- https://wowhead.com/beta/spell=326868 + -- https://wowhead.com/spell=326868 lethargy = { id = 326868, duration = 6, max_stack = 1 }, -- Leech increased by $s1%$?a389682[, damage taken reduced by $s8%][] and immune to Charm, Fear and Sleep. Undead. - -- https://wowhead.com/beta/spell=49039 + -- https://wowhead.com/spell=49039 lichborne = { id = 49039, duration = 10, @@ -680,8 +709,13 @@ me:RegisterAuras( { duration = 3, max_stack = 1 }, + mograines_might = { + id = 444505, + duration = 3600, + max_stack = 1, + }, -- Grants the ability to walk across water. - -- https://wowhead.com/beta/spell=3714 + -- https://wowhead.com/spell=3714 path_of_frost = { id = 3714, duration = 600, @@ -689,6 +723,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Disease damage occurring ${100*(1/(1+$s1/100)-1)}% more quickly. + -- https://www.wowhead.com/spell=390178 plaguebringer = { id = 390178, duration = 10, @@ -710,7 +745,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Frost damage taken from the Death Knight's abilities increased by $s1%. - -- https://wowhead.com/beta/spell=51714 + -- https://wowhead.com/spell=51714 razorice = { id = 51714, duration = 20, @@ -718,41 +753,42 @@ me:RegisterAuras( { type = "Magic", max_stack = 5 }, + -- https://www.wowhead.com/spell=390276 rotten_touch = { id = 390276, duration = 10, max_stack = 1 }, -- Strength increased by $w1% - -- https://wowhead.com/beta/spell=374585 + -- https://wowhead.com/spell=374585 rune_mastery = { id = 374585, duration = 8, max_stack = 1 }, -- Runic Power generation increased by $s1%. - -- https://wowhead.com/beta/spell=326918 + -- https://wowhead.com/spell=326918 rune_of_hysteria = { id = 326918, duration = 8, max_stack = 1 }, -- Healing for $s1% of your maximum health every $t sec. - -- https://wowhead.com/beta/spell=326808 + -- https://wowhead.com/spell=326808 rune_of_sanguination = { id = 326808, duration = 8, max_stack = 1 }, -- Absorbs $w1 magic damage. When an enemy damages the shield, their cast speed is reduced by $w2% for $326868d. - -- https://wowhead.com/beta/spell=326867 + -- https://wowhead.com/spell=326867 rune_of_spellwarding = { id = 326867, duration = 8, max_stack = 1 }, -- Haste and Movement Speed increased by $s1%. - -- https://wowhead.com/beta/spell=326984 + -- https://wowhead.com/spell=326984 rune_of_unending_thirst = { id = 326984, duration = 10, @@ -771,7 +807,7 @@ me:RegisterAuras( { max_stack = 1, }, -- Talent: Afflicted by Soul Reaper, if the target is below $s3% health this effect will explode dealing an additional $343295s1 Shadowfrost damage. - -- https://wowhead.com/beta/spell=343294 + -- https://wowhead.com/spell=343294 soul_reaper = { id = 448229, duration = 5, @@ -795,10 +831,12 @@ me:RegisterAuras( { sudden_doom = { id = 81340, duration = 10, - max_stack = function () return talent.harbinger_of_doom.enabled and 2 or 1 end, + max_stack = function () + if talent.harbinger_of_doom.enabled then return 2 end + return 1 end, }, -- Runic Power is being fed to the Gargoyle. - -- https://wowhead.com/beta/spell=61777 + -- https://wowhead.com/spell=61777 summon_gargoyle = { id = 61777, duration = 25, @@ -829,7 +867,7 @@ me:RegisterAuras( { max_stack = 1, }, -- Talent: Haste increased by $s1%. - -- https://wowhead.com/beta/spell=207289 + -- https://wowhead.com/spell=207289 unholy_assault = { id = 207289, duration = 20, @@ -837,7 +875,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Talent: Surrounded by a vile swarm of insects, infecting enemies within $115994a1 yds with Virulent Plague and an unholy disease that deals damage to enemies. - -- https://wowhead.com/beta/spell=115989 + -- https://wowhead.com/spell=115989 unholy_blight_buff = { id = 115989, duration = 6, @@ -866,7 +904,7 @@ me:RegisterAuras( { end, }, -- Suffering $s1 Shadow damage every $t1 sec. - -- https://wowhead.com/beta/spell=115994 + -- https://wowhead.com/spell=115994 unholy_blight = { id = 115994, duration = 14, @@ -887,7 +925,7 @@ me:RegisterAuras( { max_stack = 1, }, -- Strength increased by $s1%. - -- https://wowhead.com/beta/spell=53365 + -- https://wowhead.com/spell=53365 unholy_strength = { id = 53365, duration = 15, @@ -911,7 +949,7 @@ me:RegisterAuras( { max_stack = 1 }, -- Suffering $w1 Shadow damage every $t1 sec. Erupts for $191685s1 damage split among all nearby enemies when the infected dies. - -- https://wowhead.com/beta/spell=191587 + -- https://wowhead.com/spell=191587 virulent_plague = { id = 191587, duration = function () return 27 * ( talent.ebon_fever.enabled and 0.5 or 1 ) end, @@ -921,14 +959,14 @@ me:RegisterAuras( { copy = 441277, }, -- The touch of the spirit realm lingers.... - -- https://wowhead.com/beta/spell=97821 + -- https://wowhead.com/spell=97821 voidtouched = { id = 97821, duration = 300, max_stack = 1 }, -- Increases damage taken from $@auracaster by $m1%. - -- https://wowhead.com/beta/spell=327096 + -- https://wowhead.com/spell=327096 war = { id = 327096, duration = 6, @@ -936,7 +974,7 @@ me:RegisterAuras( { max_stack = 3 }, -- Talent: Movement speed increased by $w1%. Cannot be slowed below $s2% of normal movement speed. Cannot attack. - -- https://wowhead.com/beta/spell=212552 + -- https://wowhead.com/spell=212552 wraith_walk = { id = 212552, duration = 4, @@ -968,11 +1006,72 @@ me:RegisterAuras( { }, } ) +-- Pets +spec:RegisterPets({ + apoc_ghoul = { + id = 24207, + spell = "apocalypse", + duration = 15, + copy = "army_ghoul", + }, + magus_of_the_dead = { + id = 148797, + spell = "apocalypse", + duration = 15, + copy = "t31_magus", + }, + ghoul = { + id = 26125, + spell = "raise_dead", + duration = function() return talent.raise_dead_2.enabled and 3600 or 60 end + }, + highlord_darion_mograine = { + id = 221632, + spell = "army_of_the_dead", + duration = 20, + }, + king_thoras_trollbane = { + id = 221635, + spell = "army_of_the_dead", + duration = 20, + }, + nazgrim = { + id = 221634, + spell = "army_of_the_dead", + duration = 20, + }, + high_inquisitor_whitemane = { + id = 221633, + spell = "army_of_the_dead", + duration = 20, + }, + risen_skulker = { + id = 99541, + spell = "raise_dead", + duration = function() return talent.raise_dead_2.enabled and 3600 or 60 end, + }, +}) + +-- Totems (which are sometimes pets) +spec:RegisterTotems({ + gargoyle = { + id = 458967, + copy = "dark_arbiter", + }, + dark_arbiter = { + id = 298674, + copy = "gargoyle", + }, + abomination = { + id = 298667, + }, +}) -me:RegisterStateTable( "death_and_decay", +spec:RegisterStateTable( "death_and_decay", setmetatable( { onReset = function( self ) end }, { __index = function( t, k ) if k == "ticking" then + if state.query_time - class.abilities.any_dnd.lastCast < 10 then return true end return buff.death_and_decay.up elseif k == "remains" then @@ -983,10 +1082,11 @@ setmetatable( { onReset = function( self ) end }, return false end } ) ) -me:RegisterStateTable( "defile", +spec:RegisterStateTable( "defile", setmetatable( { onReset = function( self ) end }, { __index = function( t, k ) if k == "ticking" then + if state.query_time - class.abilities.any_dnd.lastCast < 10 then return true end return buff.death_and_decay.up elseif k == "remains" then @@ -997,25 +1097,25 @@ setmetatable( { onReset = function( self ) end }, return false end } ) ) -me:RegisterStateExpr( "dnd_ticking", function () +spec:RegisterStateExpr( "dnd_ticking", function () return death_and_decay.ticking end ) -me:RegisterStateExpr( "dnd_remains", function () +spec:RegisterStateExpr( "dnd_remains", function () return death_and_decay.remains end ) -me:RegisterStateExpr( "spreading_wounds", function () - if talent.infected_claws.enabled and buff.dark_transformation.up then return false end -- Ghoul is dumping wounds for us, don't bother. +spec:RegisterStateExpr( "spreading_wounds", function () + if talent.infected_claws.enabled and pet.ghoul.up then return false end -- Ghoul is dumping wounds for us, don't bother. return azerite.festermight.enabled and settings.cycle and settings.festermight_cycle and cooldown.death_and_decay.remains < 9 and active_dot.festering_wound < spell_targets.festering_strike end ) -me:RegisterStateFunction( "time_to_wounds", function( x ) +spec:RegisterStateFunction( "time_to_wounds", function( x ) if debuff.festering_wound.stack >= x then return 0 end return 3600 - --[[ No timeable wounds mechanic in SL? + --[[No timeable wounds mechanic in SL? if buff.unholy_frenzy.down then return 3600 end local deficit = x - debuff.festering_wound.stack @@ -1025,29 +1125,19 @@ me:RegisterStateFunction( "time_to_wounds", function( x ) local fw = last + ( speed * deficit ) - query_time if fw > buff.unholy_frenzy.remains then return 3600 end - return fw ]] + return fw--]] end ) -me:RegisterHook( "step", function ( time ) - if Hekili.ActiveDebug then Hekili:Debug( "Rune Regeneration Time: 1=%.2f, 2=%.2f, 3=%.2f, 4=%.2f, 5=%.2f, 6=%.2f\n", runes.time_to_1, runes.time_to_2, runes.time_to_3, runes.time_to_4, runes.time_to_5, runes.time_to_6 ) end + +spec:RegisterHook( "step", function ( time ) + if Hekili.ActiveDebug then Hekili:Debug( "Rune Regeneration Tispec: 1=%.2f, 2=%.2f, 3=%.2f, 4=%.2f, 5=%.2f, 6=%.2f\n", runes.time_to_1, runes.time_to_2, runes.time_to_3, runes.time_to_4, runes.time_to_5, runes.time_to_6 ) end end ) local Glyphed = IsSpellKnownOrOverridesKnown -me:RegisterPet( "ghoul", 26125, "raise_dead", 3600 ) - -me:RegisterTotem( "gargoyle", 458967 ) -me:RegisterTotem( "dark_arbiter", 298674 ) - -me:RegisterTotem( "abomination", 298667 ) -me:RegisterPet( "apoc_ghoul", 24207, "apocalypse", 15 ) -me:RegisterPet( "army_ghoul", 24207, "army_of_the_dead", 30 ) -me:RegisterPet( "magus_of_the_dead", 148797, "apocalypse", 15 ) -me:RegisterPet( "t31_magus", 148797, "apocalypse", 15 ) - -- Tier 29 -me:RegisterGear( "tier29", 200405, 200407, 200408, 200409, 200410 ) -me:RegisterAuras( { +spec:RegisterGear( "tier29", 200405, 200407, 200408, 200409, 200410 ) +spec:RegisterAuras( { vile_infusion = { id = 3945863, duration = 5, @@ -1062,33 +1152,33 @@ me:RegisterAuras( { } ) -- Tier 30 -me:RegisterGear( "tier30", 202464, 202462, 202461, 202460, 202459 ) +spec:RegisterGear( "tier30", 202464, 202462, 202461, 202460, 202459 ) -- 2 pieces (Unholy) : Death Coil and Epidemic damage increased by 10%. Casting Death Coil or Epidemic grants a stack of Master of Death, up to 20. Dark Transformation consumes Master of Death and grants 1% Mastery for each stack for 20 sec. -me:RegisterAura( "master_of_death", { +spec:RegisterAura( "master_of_death", { id = 408375, duration = 30, max_stack = 20 } ) -me:RegisterAura( "death_dealer", { +spec:RegisterAura( "death_dealer", { id = 408376, duration = 20, max_stack = 1 } ) -- 4 pieces (Unholy) : Army of the Dead grants 20 stacks of Master of Death. When Death Coil or Epidemic consumes Sudden Doom gain 2 extra stacks of Master of Death and 10% Mastery for 6 sec. -me:RegisterAura( "lingering_chill", { +spec:RegisterAura( "lingering_chill", { id = 410879, duration = 12, max_stack = 1 } ) -me:RegisterGear( "tier31", 207198, 207199, 207200, 207201, 207203, 217223, 217225, 217221, 217222, 217224 ) +spec:RegisterGear( "tier31", 207198, 207199, 207200, 207201, 207203, 217223, 217225, 217221, 217222, 217224 ) -- (2) Apocalypse summons an additional Magus of the Dead. Your Magus of the Dead Shadow Bolt now fires a volley of Shadow Bolts at up to $s2 nearby enemies. -- (4) Each Rune you spend increases the duration of your active Magi by ${$s1/1000}.1 sec and your Magi will now also cast Amplify Damage, increasing the damage you deal by $424949s2% for $424949d. local any_dnd_set, wound_spender_set = false, false -local ExpireRunicCorruption = setfenv( function() +--[[local ExpireRunicCorruption = setfenv( function() local debugstr local mod = ( 2 + 0.1 * talent.runic_mastery.rank ) @@ -1111,25 +1201,54 @@ local ExpireRunicCorruption = setfenv( function() forecastResources( "runes" ) if Hekili.ActiveDebug then debugstr = format( "%s\n - %d, %.2f %.2f %.2f %.2f %.2f %.2f.", debugstr, rune.current, rune.expiry[1] - query_time, rune.expiry[2] - query_time, rune.expiry[3] - query_time, rune.expiry[4] - query_time, rune.expiry[5] - query_time, rune.expiry[6] - query_time ) end if debugstr then Hekili:Debug( debugstr ) end -end, state ) +end, state )--]] local TriggerInflictionOfSorrow = setfenv( function () applyBuff( "infliction_of_sorrow" ) end, state ) -me:RegisterHook( "reset_precast", function () - if buff.runic_corruption.up then - state:QueueAuraExpiration( "runic_corruption", ExpireRunicCorruption, buff.runic_corruption.expires ) +local ApplyFestermight = setfenv( function ( woundsPopped ) + if woundsPopped > 0 and talent.festermight.enabled or azerite.festermight.enabled then + if buff.festermight.up then + addStack( "festermight", buff.festermight.remains, woundsPopped ) + else + applyBuff( "festermight", nil, woundsPopped ) + end + end + + return woundsPopped -- Needs to be returned into the gain() function for runic power + +end, state ) + +local PopWounds = setfenv( function ( attemptedPop, targetCount ) + targetCount = targetCount or 1 + local realPop = targetCount + realPop = ApplyFestermight( removeDebuffStack( "target", "festering_wound", attemptedPop ) * targetCount ) + gain( realPop * 3, "runic_power" ) + + if talent.festering_scythe.enabled then + if realPop + buff.festering_scythe_stack.stack >= 20 then -- overflow stacks don't carry over + removeBuff( "festering_scythe_stack" ) + applyBuff( "festering_scythe" ) + else + addStack( "festering_scythe_stack", nil, realPop ) + end end +end, state ) + +spec:RegisterHook( "reset_precast", function () + --[[if buff.runic_corruption.up then + state:QueueAuraExpiration( "runic_corruption", ExpireRunicCorruption, buff.runic_corruption.expires ) + end--]] + if totem.dark_arbiter.remains > 0 then summonPet( "dark_arbiter", totem.dark_arbiter.remains ) - summonTotem( "gargoyle", nil, totem.dark_arbiter.remains ) - summonPet( "gargoyle", totem.dark_arbiter.remains ) elseif totem.gargoyle.remains > 0 then summonPet( "gargoyle", totem.gargoyle.remains ) end + local control_expires = action.control_undead.lastCast + 300 if control_expires > now and pet.up and not pet.ghoul.up then @@ -1154,14 +1273,6 @@ me:RegisterHook( "reset_precast", function () summonPet( "army_ghoul", army_expires - now ) end - if talent.all_will_serve.enabled and pet.ghoul.up then - summonPet( "skeleton" ) - end - - if query_time - action.outbreak.lastCast < 2 and debuff.virulent_plague.down then - applyDebuff( "target", "virulent_plague" ) - end - if state:IsKnown( "deaths_due" ) then class.abilities.any_dnd = class.abilities.deaths_due cooldown.any_dnd = cooldown.deaths_due @@ -1200,19 +1311,15 @@ me:RegisterHook( "reset_precast", function () if state:IsKnown( "deaths_due" ) and cooldown.deaths_due.remains then setCooldown( "death_and_decay", cooldown.deaths_due.remains ) elseif talent.defile.enabled and cooldown.defile.remains then setCooldown( "death_and_decay", cooldown.defile.remains ) end - -- Reset CDs on any Rune abilities that do not have an actual cooldown. - for action in pairs( class.abilityList ) do - local data = class.abilities[ action ] - if data and data.cooldown == 0 and data.spendType == "runes" then - setCooldown( action, 0 ) - end - end - if talent.infliction_of_sorrow.enabled and buff.gift_of_the_sanlayn.up then state:QueueAuraExpiration( "gift_of_the_sanlayn", TriggerInflictionOfSorrow, buff.gift_of_the_sanlayn.expires ) end if Hekili.ActiveDebug then Hekili:Debug( "Pet is %s.", pet.alive and "alive" or "dead" ) end + + if IsSpellKnownOrOverridesKnown( 458128 ) then applyBuff( "festering_scythe" ) end + if IsSpellKnownOrOverridesKnown( 433895 ) then applyBuff( "vampiric_strike" ) end + end ) local mt_runeforges = { @@ -1222,7 +1329,7 @@ local mt_runeforges = { } -- Not actively supporting this since we just respond to the player precasting AOTD as they see fit. -me:RegisterStateTable( "death_knight", setmetatable( { +spec:RegisterStateTable( "death_knight", setmetatable( { disable_aotd = false, delay = 6, runeforge = setmetatable( {}, mt_runeforges ) @@ -1276,7 +1383,7 @@ Hekili:RegisterGearHook( ResetRuneforges, UpdateRuneforge ) -- Abilities -me:RegisterAbilities( { +spec:RegisterAbilities( { -- Talent: Surrounds you in an Anti-Magic Shell for $d, absorbing up to $ magic ... antimagic_shell = { id = 48707, @@ -1336,21 +1443,7 @@ me:RegisterAbilities( { if set_bonus.tww1_4pc > 0 then addStack( "unholy_commander" ) end end - if debuff.festering_wound.stack > 4 then - applyDebuff( "target", "festering_wound", debuff.festering_wound.remains, debuff.festering_wound.remains - 4 ) - apply_festermight( 4 ) - if conduit.convocation_of_the_dead.enabled and cooldown.apocalypse.remains > 0 then - reduceCooldown( "apocalypse", 4 * conduit.convocation_of_the_dead.mod * 0.1 ) - end - gain( 12, "runic_power" ) - else - gain( 3 * debuff.festering_wound.stack, "runic_power" ) - apply_festermight( debuff.festering_wound.stack ) - if conduit.convocation_of_the_dead.enabled and cooldown.apocalypse.remains > 0 then - reduceCooldown( "apocalypse", debuff.festering_wound.stack * conduit.convocation_of_the_dead.mod * 0.1 ) - end - removeDebuff( "target", "festering_wound" ) - end + PopWounds( 4, 1 ) if level > 57 then gain( 2, "runes" ) end if set_bonus.tier29_2pc > 0 then applyBuff( "vile_infusion" ) end @@ -1379,11 +1472,19 @@ me:RegisterAbilities( { if set_bonus.tww1_4pc > 0 then addStack( "unholy_commander" ) end if talent.raise_abomination.enabled then - summonPet( "abomination" ) + summonPet( "abomination", 30 ) else applyBuff( "army_of_the_dead", 4 ) summonPet( "army_ghoul", 30 ) end + + if talent.apocalypse_now.enabled then + summonPet( "highlord_darion_mograine", 20 ) + summonPet( "king_thoras_trollbane", 20 ) + summonPet( "nazgrim", 20 ) + summonPet( "high_inquisitor_whitemane", 20 ) + end + end, copy = { 455395, 42650, "army_of_the_dead", "raise_abomination" } @@ -1459,24 +1560,25 @@ me:RegisterAbilities( { talent = "clawing_shadows", startsCombat = true, + max_targets = function() + if talent.cleaving_strikes.enabled and buff.death_and_decay_cleave_buff.up then return 8 end + return 1 end, texture = function() return ( buff.vampiric_strike.up or buff.gift_of_the_sanlayn.up ) and 5927645 or 615099 end, - --[[ cycle = "festering_wound", - cycle_to = true, ]] + cycle = function() + if debuff.festering_wound.down and active_dot.festering_wound > 0 then return "festering_wound" end + if debuff.chains_of_ice_trollbane_slow.down and active_dot.chains_of_ice_trollbane_slow > 0 then return "chains_of_ice_trollbane_slow" end + end, + min_ttd = function () return min( cooldown.death_and_decay.remains + 3, 8 ) end, -- don't try to cycle onto targets that will die too fast to get consumed. + cycle_to = true, handler = function () - if debuff.festering_wound.up then - if debuff.festering_wound.stack > 1 then - applyDebuff( "target", "festering_wound", debuff.festering_wound.remains, debuff.festering_wound.stack - 1 ) - else removeDebuff( "target", "festering_wound" ) end + PopWounds( 1, min( action.clawing_shadows.max_targets, active_enemies, active_dot.festering_wound ) ) - if conduit.convocation_of_the_dead.enabled and cooldown.apocalypse.remains > 0 then - reduceCooldown( "apocalypse", conduit.convocation_of_the_dead.mod * 0.1 ) - end - - apply_festermight( 1 ) - if set_bonus.tier29_2pc > 0 then applyBuff( "vile_infusion" ) end + if debuff.undeath.up then + applyDebuff( "target", "undeath", debuff.undeath.stack + 1 ) + active_dot.undeath = min( active_enemies, active_dot.undeath + 1 ) end if buff.vampiric_strike.up or buff.gift_of_the_sanlayn.up then @@ -1494,7 +1596,12 @@ me:RegisterAbilities( { removeDebuff( "target", "virulent_plague" ) removeBuff( "infliction_of_sorrow" ) end - -- gain( 3, "runic_power" ) -- ? + + -- Legacy + if conduit.convocation_of_the_dead.enabled and cooldown.apocalypse.remains > 0 then + reduceCooldown( "apocalypse", conduit.convocation_of_the_dead.mod * 0.1 ) + end + end, bind = { "scourge_strike", "wound_spender" }, @@ -1586,10 +1693,11 @@ me:RegisterAbilities( { applyDebuff( "target", "unholy_blight" ) applyDebuff( "target", "virulent_plague" ) active_dot.virulent_plague = active_enemies - if talent.superstrain.enabled then - applyDebuff( "target", "blood_plague_superstrain" ) - applyDebuff( "target", "frost_fever_superstrain" ) + applyDebuff( "target", "frost_fever" ) + active_dot.frost_fever = active_enemies + applyDebuff( "target", "blood_plague" ) + active_dot.blood_plague = active_enemies end end @@ -1624,9 +1732,9 @@ me:RegisterAbilities( { id = 43265, noOverride = 324128, cast = 0, - charges = function() if talent.deaths_echo.enabled then return 2 end end, + charges = function () if talent.deaths_echo.enabled then return 2 end end, cooldown = 30, - recharge = function() if talent.deaths_echo.enabled then return 30 end end, + recharge = function () if talent.deaths_echo.enabled then return 30 end end, gcd = "spell", spend = 1, @@ -1636,7 +1744,7 @@ me:RegisterAbilities( { notalent = "defile", handler = function () - applyBuff( "death_and_decay" ) + applyBuff( "death_and_decay", 10 ) if talent.grip_of_the_dead.enabled then applyDebuff( "target", "grip_of_the_dead" ) end end, @@ -1656,41 +1764,34 @@ me:RegisterAbilities( { return 30 - ( buff.sudden_doom.up and 10 or 0 ) - ( legendary.deadliest_coil.enabled and 10 or 0 ) end, spendType = "runic_power", - startsCombat = false, + startsCombat = true, handler = function () - if set_bonus.tier30_2pc > 0 then addStack( "master_of_death" ) end - - if pvptalent.doomburst.enabled and buff.sudden_doom.up and debuff.festering_wound.up then - if debuff.festering_wound.stack > 2 then - applyDebuff( "target", "festering_wound", debuff.festering_wound.remains, debuff.festering_wound.stack - 2 ) - applyDebuff( "target", "doomburst", debuff.doomburst.up and debuff.doomburst.remains or nil, 2 ) - else - removeDebuff( "target", "festering_wound" ) - applyDebuff( "target", "doomburst", debuff.doomburst.up and debuff.doomburst.remains or nil, debuff.doomburst.stack + 1 ) - end - if set_bonus.tier29_2pc > 0 then applyBuff( "vile_infusion" ) end - end - + if buff.sudden_doom.up then + PopWounds( 1 + ( 1 * pvptalent.doomburst.rank ) ) removeStack( "sudden_doom" ) - if set_bonus.tier30_4pc > 0 then - addStack( "master_of_death", nil, 2 ) - applyBuff( "doom_dealer" ) - end - if buff.master_of_death.up then - removeBuff( "master_of_death" ) - applyBuff( "death_dealer" ) - end if talent.rotten_touch.enabled then applyDebuff( "target", "rotten_touch" ) end if talent.death_rot.enabled then applyDebuff( "target", "death_rot", nil, 2 ) end - elseif talent.death_rot.enabled then applyDebuff( "target", "death_rot" ) end - if cooldown.dark_transformation.remains > 0 then setCooldown( "dark_transformation", max( 0, cooldown.dark_transformation.remains - 1 ) ) end + elseif talent.death_rot.enabled then applyDebuff( "target", "death_rot", nil, 1 ) end + if buff.dark_transformation.up then buff.dark_transformation.expires = buff.dark_transformation.expires + 1 end + if buff.gift_of_the_sanlayn.up then buff.gift_of_the_sanlayn.expires = buff.gift_of_the_sanlayn.expires + 1 end + + -- Legacy if legendary.deadliest_coil.enabled and buff.dark_transformation.up then buff.dark_transformation.expires = buff.dark_transformation.expires + 2 end if legendary.deaths_certainty.enabled then local spell = action.deaths_due.known and "deaths_due" or ( talent.defile.enabled and "defile" or "death_and_decay" ) if cooldown[ spell ].remains > 0 then reduceCooldown( spell, 2 ) end end + if set_bonus.tier30_2pc > 0 then addStack( "master_of_death" ) end + if set_bonus.tier30_4pc > 0 then + addStack( "master_of_death", nil, 2 ) + applyBuff( "doom_dealer" ) + end + if set_bonus.tier30_2pc > 0 and buff.master_of_death.up then + removeBuff( "master_of_death" ) + applyBuff( "death_dealer" ) + end end, }, @@ -1822,33 +1923,33 @@ me:RegisterAbilities( { cooldown = 0, gcd = "spell", - spend = function () return 30 - ( buff.sudden_doom.up and 10 or 0 ) end, + spend = function() return 30 - ( buff.sudden_doom.up and 10 or 0 ) end, spendType = "runic_power", startsCombat = false, targets = { - count = function () return active_dot.virulent_plague end, + count = function() return active_dot.virulent_plague end, }, - usable = function () return active_dot.virulent_plague > 0, "requires active virulent_plague dots" end, + usable = function() return active_dot.virulent_plague > 0, "requires active virulent_plague dots" end, handler = function () - if set_bonus.tier30_2pc > 0 then addStack( "master_of_death" ) end if buff.sudden_doom.up then removeStack( "sudden_doom" ) - if set_bonus.tier30_4pc > 0 then - addStack( "master_of_death", nil, 2 ) - applyBuff( "doom_dealer" ) - end if talent.death_rot.enabled then applyDebuff( "target", "death_rot", nil, 2 ) end - elseif talent.death_rot.enabled then applyDebuff( "target", "death_rot" ) end + elseif talent.death_rot.enabled then applyDebuff( "target", "death_rot", nil, 1 ) end + if buff.dark_transformation.up then buff.dark_transformation.expires = buff.dark_transformation.expires + 1 end + if buff.gift_of_the_sanlayn.up then buff.gift_of_the_sanlayn.expires = buff.gift_of_the_sanlayn.expires + 1 end + if set_bonus.tier30_2pc > 0 then addStack( "master_of_death" ) end end, }, -- Talent: Strikes for $s1 Physical damage and infects the target with $m2-$M2 Festering... festering_strike = { - id = function() return buff.festering_scythe.up and 458128 or 85948 end, + id = function () + if IsSpellKnownOrOverridesKnown( 458128 ) or buff.festering_scythe.up then return 458128 end + return 85948 end, known = 85948, cast = 0, cooldown = 0, @@ -1859,13 +1960,21 @@ me:RegisterAbilities( { talent = "festering_strike", startsCombat = true, + texture = function () + if IsSpellKnownOrOverridesKnown( 458128 ) or buff.festering_scythe.up then return 3997563 end + return 879926 end, cycle = function() if debuff.festering_wound.stack_pct > 60 then return "festering_wound" end end, - min_ttd = function () return min( cooldown.death_and_decay.remains + 3, 8 ) end, -- don't try to cycle onto targets that will die too fast to get consumed. + min_ttd = function() return min( cooldown.death_and_decay.remains + 3, 8 ) end, -- don't try to cycle onto targets that will die too fast to get consumed. handler = function () + + if buff.festering_scythe.up then + active_dot.festering_wound = active_enemies + end removeBuff( "festering_scythe" ) - applyDebuff( "target", "festering_wound", nil, debuff.festering_wound.stack + 2 ) + + applyDebuff( "target", "festering_wound", nil, min( 6, debuff.festering_wound.stack + 2 ) ) end, copy = { 85948, 458128 } @@ -1875,7 +1984,7 @@ me:RegisterAbilities( { icebound_fortitude = { id = 48792, cast = 0, - cooldown = function () return 180 - ( azerite.cold_hearted.enabled and 15 or 0 ) + ( conduit.chilled_resilience.mod * 0.001 ) end, + cooldown = function() return 180 - ( azerite.cold_hearted.enabled and 15 or 0 ) + ( conduit.chilled_resilience.mod * 0.001 ) end, gcd = "off", talent = "icebound_fortitude", @@ -1944,10 +2053,11 @@ me:RegisterAbilities( { handler = function () applyDebuff( "target", "virulent_plague" ) active_dot.virulent_plague = active_enemies - - if legendary.superstrain.enabled or talent.superstrain.enabled then - applyDebuff( "target", "blood_plague_superstrain" ) - applyDebuff( "target", "frost_fever_superstrain" ) + if talent.superstrain.enabled then + applyDebuff( "target", "frost_fever" ) + active_dot.frost_fever = active_enemies + applyDebuff( "target", "blood_plague" ) + active_dot.blood_plague = active_enemies end end, }, @@ -2004,10 +2114,10 @@ me:RegisterAbilities( { essential = true, -- new flag, will allow recasting even in precombat APL. nomounted = true, - usable = function () return not pet.alive end, + usable = function() return not pet.alive end, handler = function () - summonPet( "ghoul", talent.raise_dead_2.enabled and 3600 or 30 ) - if talent.all_will_serve.enabled then summonPet( "skeleton", talent.raise_dead_2.enabled and 3600 or 30 ) end + summonPet( "ghoul", talent.raise_dead_2.enabled and 3600 or 60 ) + if talent.all_will_serve.enabled then summonPet( "risen_skulker", talent.raise_dead_2.enabled and 3600 or 60 ) end if set_bonus.tww1_4pc > 0 then addStack( "unholy_commander" ) end end, @@ -2048,7 +2158,7 @@ me:RegisterAbilities( { toggle = "cooldowns", - usable = function () return pet.alive, "requires an undead pet" end, + usable = function() return pet.alive, "requires an undead pet" end, handler = function () dismissPet( "ghoul" ) @@ -2058,7 +2168,7 @@ me:RegisterAbilities( { -- Talent: An unholy strike that deals $s2 Physical damage and $70890sw2 Shadow damage, ... scourge_strike = { - id = function() + id = function () if buff.vampiric_strike.up or buff.gift_of_the_sanlayn.up then return 433895 end return 55090 end, @@ -2073,29 +2183,24 @@ me:RegisterAbilities( { talent = "scourge_strike", texture = function() return ( buff.vampiric_strike.up or buff.gift_of_the_sanlayn.up ) and 5927645 or 237530 end, startsCombat = true, + max_targets = function () + if talent.cleaving_strikes.enabled and buff.death_and_decay_cleave_buff.up then return 8 end + return 1 end, notalent = function () if buff.vampiric_strike.up or buff.gift_of_the_sanlayn.up then return end return "clawing_shadows" end, - cycle = function() + cycle = function () if debuff.festering_wound.down and active_dot.festering_wound > 0 then return "festering_wound" end if debuff.chains_of_ice_trollbane_slow.down and active_dot.chains_of_ice_trollbane_slow > 0 then return "chains_of_ice_trollbane_slow" end end, - min_ttd = function () return min( cooldown.death_and_decay.remains + 3, 8 ) end, -- don't try to cycle onto targets that will die too fast to get consumed. + min_ttd = function() return min( cooldown.death_and_decay.remains + 3, 8 ) end, -- don't try to cycle onto targets that will die too fast to get consumed. cycle_to = true, handler = function () - if debuff.festering_wound.up then - if debuff.festering_wound.stack > 1 then - applyDebuff( "target", "festering_wound", debuff.festering_wound.remains, debuff.festering_wound.stack - 1 ) - else - removeDebuff( "target", "festering_wound" ) - end - apply_festermight( 1 ) - if set_bonus.tier29_2pc > 0 then applyBuff( "vile_infusion" ) end - end + PopWounds( 1, min( action.scourge_strike.max_targets, active_enemies, active_dot.festering_wound ) ) if buff.vampiric_strike.up or buff.gift_of_the_sanlayn.up then gain( 0.01 * health.max, "health" ) @@ -2110,7 +2215,6 @@ me:RegisterAbilities( { end if talent.plaguebringer.enabled then - removeBuff( "plaguebringer" ) applyBuff( "plaguebringer" ) end @@ -2212,36 +2316,8 @@ me:RegisterAbilities( { handler = function () applyDebuff( "target", "festering_wound", nil, min( 6, debuff.festering_wound.stack + 4 ) ) applyBuff( "unholy_frenzy" ) - stat.haste = stat.haste + 0.1 end, }, - - --[[ Talent: Surrounds yourself with a vile swarm of insects for $d, stinging all nearby e... - unholy_blight = { - id = 115989, - cast = 0, - cooldown = 45, - gcd = "spell", - - spend = 1, - spendType = "runes", - - talent = "unholy_blight", - startsCombat = false, - - handler = function () - applyBuff( "unholy_blight_buff" ) - applyDebuff( "target", "unholy_blight" ) - applyDebuff( "target", "virulent_plague" ) - active_dot.virulent_plague = active_enemies - - if talent.superstrain.enabled then - applyDebuff( "target", "blood_plague_superstrain" ) - applyDebuff( "target", "frost_fever_superstrain" ) - end - end, - }, ]] - -- Talent: Inflict disease upon your enemies spreading Festering Wounds equal to the amount currently active on your target to $s1 nearby enemies. vile_contagion = { id = 390279, @@ -2255,6 +2331,10 @@ me:RegisterAbilities( { talent = "vile_contagion", startsCombat = false, + -- usable = function() return debuff.festering_wound.up, "requires active festering wounds" end, + cycle = function() if debuff.festering_wound.down and active_dot.festering_wound > 0 then return "festering_wound" end end, + cycle_to = true, + toggle = "cooldowns", debuff = "festering_wound", @@ -2284,7 +2364,7 @@ me:RegisterAbilities( { -- Stub. any_dnd = { - name = function () return "|T136144:0|t |cff00ccff[Any " .. ( class.abilities.death_and_decay and class.abilities.death_and_decay.name or "Death and Decay" ) .. "]|r" end, + name = function() return "|T136144:0|t |cff00ccff[Any " .. ( class.abilities.death_and_decay and class.abilities.death_and_decay.name or "Death and Decay" ) .. "]|r" end, cast = 0, cooldown = 0, copy = "any_dnd_stub" @@ -2299,9 +2379,9 @@ me:RegisterAbilities( { } ) -me:RegisterRanges( "festering_strike", "mind_freeze", "death_coil" ) +spec:RegisterRanges( "festering_strike", "mind_freeze", "death_coil" ) -me:RegisterOptions( { +spec:RegisterOptions( { enabled = true, aoe = 2, @@ -2322,23 +2402,23 @@ me:RegisterOptions( { } ) -me:RegisterSetting( "dps_shell", false, { - name = strformat( "Use %s Offensively", Hekili:GetSpellLinkWithTexture( me.abilities.antimagic_shell.id ) ), - desc = strformat( "If checked, %s will not be on the Defensives toggle by default.", Hekili:GetSpellLinkWithTexture( me.abilities.antimagic_shell.id ) ), +spec:RegisterSetting( "dps_shell", false, { + name = strformat( "Use %s Offensively", Hekili:GetSpellLinkWithTexture( spec.abilities.antimagic_shell.id ) ), + desc = strformat( "If checked, %s will not be on the Defensives toggle by default.", Hekili:GetSpellLinkWithTexture( spec.abilities.antimagic_shell.id ) ), type = "toggle", width = "full", } ) -me:RegisterSetting( "ob_macro", nil, { - name = strformat( "%s Macro", Hekili:GetSpellLinkWithTexture( me.abilities.outbreak.id ) ), +spec:RegisterSetting( "ob_macro", nil, { + name = strformat( "%s Macro", Hekili:GetSpellLinkWithTexture( spec.abilities.outbreak.id ) ), desc = strformat( "Using a mouseover macro makes it easier to apply %s and %s to other enemies without retargeting.", - Hekili:GetSpellLinkWithTexture( me.abilities.outbreak.id ), Hekili:GetSpellLinkWithTexture( me.auras.virulent_plague.id ) ), + Hekili:GetSpellLinkWithTexture( spec.abilities.outbreak.id ), Hekili:GetSpellLinkWithTexture( spec.auras.virulent_plague.id ) ), type = "input", width = "full", multiline = true, - get = function () return "#showtooltip\n/use [@mouseover,harm,nodead][] " .. class.abilities.outbreak.name end, - set = function () end, + get = function() return "#showtooltip\n/use [@mouseover,harm,nodead][] " .. class.abilities.outbreak.name end, + set = function() end, } ) -me:RegisterPack( "Unholy", 20241109, [[Hekili:S3ZApUTn2(BjyrCS7K4yPzM0j9oEa6MBxGnOOlqNwSFZYASKT1gzlVsYPDkg4F73dPErsXdj1RjzYDakAsmPo88(C4HVwyT43wCRNBQ)IFXEM9fwwZE)0zxn7sRZxCB69h8xC7b3vFYDd8x27Ud())((TrH3t(57dJC9iFEs0X4vqtBttpK8dV9TBcs3E8UPRI292KGDhdDtdI2Vk2DDk5FV6TlU9UJbHP)Z9lUt(yBdW8G)k4NVe(RBd888Z6RFYQf3s67BSSEZS3)dNw(R(FoiX)0Yp7gh4ExOFYPpE6JL94sOh3gS7dNwE8azGoTC8)RVB62tl)quq4KQ(o7n2N)6tlj)zTVHTt2qJwwtNn9s2F2Ys4B(FoT8F4NK6hhSFd0YQ7t36ldEZEh8H)ob))9F80YDrXWFly)PL)4)6N46Mi8lBC2vVX(kaXN9EGyZ(tluca68SVN2jcPsG5Vt7G3PLhIdIIdsV)0Y1Xr7Y)(YV77bUd07FJqe)B3y4)bs4G9lUnmijnHQc4U3zDqc8JBG)5Vq1Q83teiEl(7lU1Dfrfa(Z9Pb7C3eSYjzRFyyMeno4qwRqZVk09EG()h5G6wOrcx0L0tqU58P9bB2Mo1DxIJ7DjrX35CWh092NEA5naHDA5OtlJpUhgGdr)HpGPxFA5fZwKcQscOufKFXPL3DC96PzJG7Ephp)vU3p94bk4kA(ZU7oeetq904Gp5dnZsx374T3JmoNJoouOKCKOm74ffTRyasDdbcyk5N89CUd02bsFAbikhJm0BfO3sgMlqhMu34n(Pt367gMUD6HvaR565NwE(L0bBnH)5e7VZnyFcLPDz1qagYHqBUapLmgxQLLPINWJVVdfwJpT0ZNcT1fMmo)r0X9EttsbxpaosW(tlFdOLc0L7Dr7c2tDPmLmuF2NsxRIIc9I(d43oeTYn8(dj(tzPYc)d02DaTqQL5KtlF4bdOfk(4a(K27LXA(EuYrnTCTAsPAeR((m0bg0uO1iFNe)ua1uyKv7t5TY(XOFcSVParu5K5lPUSi8aDMoIwnPbR(eL3ccLXuRNC977ogNKsHn4MlPq)UWelVtFoi0h0z2NcojaUszNisjopaRPSvWEjtDpjtnz19RGV3FV)UaisGPF1vz9m2nWZX)Ze0W1ZdWW)K4DlZLIqtLAwellll19HyJLncA80u4iWFnWfQO9jn0ptUg4QTKH3jATtWkFN04OWW7C3d6pHr)HALBrFl4kwCAckfHqFPYMCgpr7vIhgtgPslDHbQsMuYVnq2lOXmsNZiIa)c5edUlUxW4)5aG(eOYfLAuUIbB0bWpmX3n0uMVHkK8AgW5FiWd(5vL4cI)xChwTc5y1FkqbYWCvxeOYCDd06MvEt35(NgiCMttbWaj)1ccE5c033jEwFi1SM1wuqQ4bIGSYdYCkYxv8JJ0m8DCtsCpgMYoMIKe4zZQWrVjMLNNjC021BijTv6YutOHjYfEIbTkOoEWyEKBIZIlkiwv(6VOeXveqPEAyxqZgro4BsKiogCE8czcbvbImItKN7eQoHwt13jxWHhyRtQFCrHnoBdj51WXGf7LaJMj0TNB8NGOWU7twhfVJM0N6849Iiiy8rcM6Ci0DZrFksKKR2ueOlJ(L17y)1qMwBjWodTZjByEMWSmGz7jMegvGTjyDkjRbi)phyADKjKjKGsYryccGFCaj4GabhGPpMK6Sg0qJ5h)82VlmkYtkcoPEkJ5EIUlK6gNt8OUhStiqcJVsmjzqbYkX3Hn3CzdSIEXo417w1qxPBeDm9oiC)NuLsuvWrJmjGqb(5t8RPzRidMm4rfT4egS7oUWkefgvHwKzeGvda68u(qoJmrhcwLMsDFAQchmCb7E3GeSl35DuI04iWWApZm3Qphp8js8q8iep72VTU9jcfi05BPdm8F2Nw(DQPtanpREx9Vd8cMr1A6zgPFhrWl05jFrJc91gN4BPGIjPQIfYwSvHyGaRHyA8BUaQDA5VeT)nfHfx0Pc9QSwEDUSr4jUZB1UjM64tMtie)VJZRxkP0TB2c8TYk)sSfWQkCrBBa(u09Ks)M3G8cQH7N1Kz7x2bkdXj(G2a1WC7rM1pED31wC5ly8KWGZhY6yctOoj16LJZiPa0kmpKmwk0uADXOW4yILDcdGv8bTbKVjRqFy0qA2AEP2eVq7cZ8oMAFlZ2wtH11AqzwyWR16uaBnRqtzOe2zQHkxBl(qzrPPWGKgDC12A57M74MMSgJ7ImnJvrXXhP8wfR)KMLLtr2piloehYl7Zzfhzo3KikyhdDIQ86GQWUQTlkOb5a2pRBikV0iZrlfKEhwFX5flCSUcrRCnehBSYGoUn)mbvcTYehXDPNvllLHnMtZpsJVFCF2C5TYW64SYB96ZMrF6vouVcXLH9KP8nrHELPrwKNvqoAN5kc8WjFDnYvFW81QN2Te8sAZx5rohH4lQHMXrz4WEzLk4q08Ik1JfuYSAjnVyYcITmNP(pku2hPmxv1gkgvDhLXRvH09sqilBdrtSkS1Ok8xPBREmyMhOKWGf9QCgL1dmcoCGj7e54f4tv1LxxLQuBESlopv2eSFDyaLwibesG0EOtjJnJWVHQrZxWIIGSKI4510cVi6YcGPly5FN5PEhL)AuScsKE7shr6gEjtz1wBjpG5ebbw3)jF6(cSMFBoxZ)wEhzNcu2MmD99XUHKGbe0YdSz3fNfPry9X2ruGaSVO)I7(irUF1wdPMed4mwA9RXwuADLDWnE39kJaOwpLjsbbq5IiiePNGsp45QSmES5WHXcvSyiPK9CYwFy6KjzML7cGjLflKSNewNLCMAEILnWOpVUizAbyOJIvZix3ZsATjYB0XYHO6N0RXfLmiEhJP9Jw8Zzt)(ZlgWA9TA33wfWlVTPP2tRCzvmGfksv9zRBItr)kkMkPxkXlIBkbL8rz6)GLCyukd)ury18(yRKNB)yWZTBlp3wGNBzap3YCEUDB452Yc5Osp)fsL2CSDwc0fsgO05XmJIjvNfudktQXW9C35UX3zW015DQMCC3oiIuznFBQl1rg6H28r1KH00SCy9JwdGStN2EwpNsuomN0ekVp53ghbPoXRcflHPyNeHxgEkF5e0M2G1LY8NkwYkv(tLzBBJyBB3l22sGsZST7dFQFz01mFunziF22UjO5tFBB7YIx1TcxXUSVgw8Q5Y2IsifZ(krPnwLBrMBREotxQvLoSVS2PFh7mABbLythrLPJAeL(C5UAx5UWky1yn1SIacTfTQv1TcF)P0aN59T)z9cGVRydh3TkxvR(usk(0y86pv73Rw9GAoCy7wD2Sqr0znfQTpUrQL(OgupmvE41w1lp)1uJ9c)9f9g6QNdOs6)x(SSFjEfJoarr8tR(0IuSO)nNS6HWS0ySIqD(kV0eorHyVey8(X4ugVKGuHhbTMqYgVAw()CXTNlZDNssJ(z683JU8GMQfy0ciAi9FDzod8Euk6iRXnU)9C0HBtpyujCVPgmuVRuvSMOtWc1yIct(6XxPCYSXFKetsVsqo3eBJppYGDsDjQlEcWpFgpMwFniL4JmhLdwRwZLjCG0DWcBKaPDiZxlMcb5Zzqu6HdDvqAPEyPcE1QsgS7qC0N9j7BOI1tvm0QeftBouL8rKK698)mmlqHWws2uoK)T0eOP(wLfhj32TdBoRt5By0kjBXEVt2SR1RbEoD7QAct8mw2n4FF)Ffq2DtKurs3gaPZWXVPeIFsI)(v(ftuklTL)7rF)9mHiVKssCqF7rsAiegGeix0h347OzRqLyegCTHxK7ZX2QDAeLSDp4MAYhCddpT8hPmYtl)z6LarjFf8bh6K9pCi3peK9bBCWkYEeGpt0m7DH9JrXqsVAjkeRSlQKU9KHo4YGm4ymZGZoWI7DIYScIxr2ISPrXGUqQaZ6xDxf4gYnVnr)t2LxCf57Fdn7OIIeWY0IwFm((Pvfy(mQbjXcHZGKnDEvt1DSrvaG0tJMF97MjMtx9LfBuTwQCPpxpPw47rYwUyKI8ineY4tAeDdAQBcJAh5knRQUqvjeRMGevcy2u(Xe84BFvcCsTRQeQH8qQsGnYmQeLDHQsOzV7MNDk41ZF)M0TmtHtZeXkdCZ2kBQwYkLq5hjoS6(qMfUMoZ8eN)ZrVn7iEtjejEjuacX6QVP0TTUQl6VfF9WOJADftqpiDgsHBcDiXpPIj89Fmc6Klbib(QYSL0wT845BMYMRf)9WXWSkIzHxVJYAxee7tDU(nVBsCkT9Azga4Hrbu5axPqu2dQ2G5NQR5IBxszUpvIJzjXZ4T2DdnN)ysX6OyJyM1f98qu2FYV7vHC7jAngv()Byr)btvuzTYhrMSDgMG2VsixQ)1yf7ZN1fTxUVwsHrgvVPAFVb6QNtx)dl8zRmMz62725s2DwOlKMzlqMSIJQh2i6r6irYXhH1hm)YasP93Zwn0A9qOKO6NVJCsP(zMyajzB2J9cVjZIBpMqMG)ANnR8kUfAWZy3R1xOHNxB6ImbL5VGfjOaEgIQNRmkJYU5ZIM9(HGGt4j0PDk8daArrjvhEQgJpZPvhTnOtbhs5LV4JjgrXMgfcTncIqF3pNjhWpOrYe6LhiqvhxYkNNkUUEyppUkX1QlHrc6I7EhhDhRaDlNcLypkxEaT3PDK1tH)ATJUziVSOGPnv4qiy6T3iLGXparTr(yokqxBj8yeY03PJDUTIbNkpnXyD9UVONubKUZmQIs(YQ3zwK9Z4CZdU(rzvSxfVewgEeiDSSERgQ5NuAc20ITdIw)DTaHiid8thI9HCfUZT(s3MTC8YstbTgWIz3ucC6MOBXT0Q628vhvyZXrYXGOEL5PGPXGKP7cIJJOj9SogG3XyINHOD0dkuISpaDd)xT4aP87Kycn0If3JFZ7Iqd2nLgSBinyxrdnC1(QZnkM6jxIcdM0OA12z(ecXWGh586STDfYYFzk9zRM(6DjLe6Zwj9jMLqdPplNTqauNCqIjbncHTQWmcIjMpqdrmBDiM5CsbetmUDdrmlNK73VIfL0EydW3wgJojDFbxvoNxkFlHu1H5Lx1R5dJSONTB8KbjXbEsRTFH8WkLl0PiwBD(AOGXwVGrCNIBMGXwhJQNfmAhV2iym3CPUGrmZPgkyk2n8cZDtPzJwrhFG067u(kfYANojsx0b)X6KhVvZXBAcDYgKvLHmFJZQHXvH(l7Pe4r0Ov3JkVKSJzXMNGNmcc)CiDNqXAUs)TjucYAwMIt2)Dtnii1JHmgHLrmcX84WjtlTmcRgWiSKWiSrzekJLuBvhn00a58I0elezTZQexJ0iZcvGhOI2sZMSzhEFf(x)0cXvHvYnZIQ5sWF7AWvZqbWHSlgvvaHC3YkEogAZMXCHrx6OYfZd5nOERVv3Qai79Bp25XuNet7TQNj3gH4kGvJNUndSmzhtrNKPOkf3Wwflv4M2TGST8Xc7rfqhtxRzIofDUBOhkiXU7Qq2E(yggPm7RmZVLe4ViiF(MsOQYDfz0(8nLWGEtjuRDzhM7xOjlvz5xYA0LVzihRBR9psZsr3(1hwzEDk(2YDW7eXzA1hhrY2Ts5grls(wIQAtoNPTDT0nc)qouuciiIsYaOdCwX6AOwtOLoXAPUUs7Q8P)jzxkOta8yCBGO2VIT(z3kulMNk(vS)gYVImA5Rj)kYWVVg8Ry)KXVIm7Qg4xXwRFLH4gVPS9NVgA0pKJnCuh98vvHU0ZFsCvvmexdngzW98DdZZgCnNYF6BWvC3WKTB3A8lhWhY(oEdsSnwLKQx0IIF6P8w03KQ(Xpun4q(ED5BhvZknzBE(ABxztnIeKJK4BVtjmlSsEw(MqNT786WAwqER1(7uG0YLUGtElTuPT79STUBsSfUGXYxXABOz7tEDDSRvFeDdxM9ySqzgsEyFlvSL)O)wnlpShpJQym7GFBfHEHiUhLZsWVCcm7oQFYj8RuELRYJQYM)OkxL9spR7BAIyT8ObjRHmIL2KRZAFYnRxe5k8(yys5hAMGqApzUfxMjkRyx(kmxJ6wjLwT8vTDTY0FZNGOtz2QOvnEnXpeMUpDDWQXQzgpfRFvhwRS5Olwg2DuGixx2IsbE))SFCcP))I9m7lSSMbzW8hUX7bmayb)2wiTNGDhIIbFuqoyNw(kMDB8RoTm2))EmGEG1sIil2I7X0iirnYpaQq73agTN(4phqo3kN)dKt12Ey8On)kPo7aqMgH1yH9p0PXw)5eaYN(OemSC763m8Zwo(X7csa)K7FQc)ucz(B1gbil)AXXqito6SH(I8s6pIbPlgaCuQ0j)e40mzJ1aGDk1k7biJWrlFUheaATNbcdHhZ9PNaeLCt7zim5UZ8eGQ07tVVWWT20jfGn60nF8GVkBbYHjPz2ddNhLN1AF0G7qWdQEvwfaz9NRvdHi3TJPaqLEZzAiC7bBQVOW))Fk9IasJYTGSNjxcPVASM7(1hEaZtXOxqt4v(HQBeoVCKIRj2rQUHyNmA8luz2wIQsBDKjvL8gRlF54X2Fho2p5SQMRlvzBvQ4zYegQavfUKsq7Xi9Lc(XGwk0iFwlsGZ)2HMZ)iQfn40YRWYVkVi8jnl5kKjB0BbuqGV4sNiaESvwre61Mqt(YPXV81Lax(QBBoqfxgpjawsxgqGRBMDv17xKbxB7sOfrhwbxpR29fc(9p)(Peg3jv5bf44zoM)rwQDyuRz1PJwcuT4Q0UmGaxxk0DqDadI9JdJVqt8zOHF)ZVFkHXDsvEqbEjyVSx9djGZ9lWnaSDiROAantQlSdte0jq2Kkgc7EY1bc07ndLN5mFLb)N58dkN5D9QN2bf4ga2oK3xnGoKm5Ev9db69M63ZCMVYG)ZC(bIZGUPmO7wIx1OAX9OVPmgoi3Pn6IsiZVBafGS8TkOHqMDtekQKjz)fkcvKcS0d84HaYs1BBQclcILVyaBIjBklb8IRntrlMxiNMHGFRwDBT5cPFUN9lWnaSDyUN97C7huGBay7qgNyZSN5PQxgsY02xcW1ovQbf4ga2oOVoKZ(655L2qy)0MZm0W)zo)GYzWQ7GTcpS24EyFKax7c9nOa3aW2H4QdZCdvc7EY44P5SM)gMZm0W)zo)aXzqN6ztNvmYKc7WSIZG7JEPwgMcIiz3lkaCfpMfgQk8KBm(EedY2Sy7svKZFe)BMM8JWEgIt)p)vMxUXHWtqViKr2Uc9WPebl)ZUzD8OcvjV33caxXlcUHJHKhvDHXqXZUUH2C9kDGmgYEXZfgevpk6gokIV85cJa2dJUPqx8ntxe8yVP6g6xs40jlAwj)HSre2xnGW2A2GKJqoWrIW3pahjymZdvSO2y9h44AafXVB)GXd5eOTq0a7hGJOck9fwSMZmfVcJFXgiBe9((FGWovM9H1Rn2bvUxaowMc9cWrSf6fGFoIWTxZe9CSJFEVqbdJwJ0mElFGYEv3Y5LR(sfVRfLyiF9LyAwDAVLav3lnLKbYGpX8bh5U1w(WI3z1PIZTMkOSWAnBiqnGFioqg8jMp4MYc10z15yxkZG0BxnLEbQDiP8bBrI4cRF98Wqevonh8gia6QAVYb3uzwtu7XloVzmt8(1ZdJszgo4nqa0v7mLdUPYSMyNvl7YHwjPwIGdnf(E5rC7qnCQbXsEw5Q2OWHHS(mOGxhNqYztwGLO4nEBOr(bg8ga4gOw2e7aHbS2vTa2nF9OXO6PJurQV8LL)eZxw068zLN)BfcBthavVKFZNnbgkd5yu2BVZjgAgrFZhk1zWkQth8LvhKL(J1BrjVpdl81Ym6v3z9o6p0W3eiR3KRvbAfhr9U0SBGHSeITFDPPEam3u2e(BVZjgAgrFZhQuAQvTLs10oS)drHAN2KmkW12zSo0W3eiti4S70wqwTFt6wewTyFmfZnf(yL9qbOjV1NY8yL9ZMbfl5qXQPqrVaYGSB7D4BcK1lGK3htXCtHFJva6hrxNuJQfI7fOjRQWLVCFAp8Wlq8lbEzXH2yvEeEPINTNjF3yRPxEgIzj0QKVL8(flVLQ3TycCpJdTiC23iiVM8sRzZMmzYnm9uwU1kEpZejalTeGfkbyPGaSeiaBocOqt6RCnH3(1RMWBnstOob8vJMqobW49T2Q(K)fnZ5dgum0ri2j18vnA5HgItsj21LBZWmSZIw7NCmcT2bi(iE9IouxKT99LmAX32B7o2Hg(iRWDN2FkyhGK2OPHE5t34lE6(3IQ)HiI0(5RW6(hU9Mf0Wb)tF8Fsv7jGL8oGN98yCAzyqskrVEXTG6(2O4f3EBWUJHuO8Hy31PlU9qCe5jtO4j1izA5(N4S5VnBOj7hOtFuw7INmGxx2i9Chn3w(NvKTXRjVZ3Zfsu810CoMxfLNnjMQcTOFHHf6lsnzAcgAlfdTrWq9ldQqF7bmSkzWxhDyEIFAW6CS1Ew2FXXpmHL7kDXJF9QO9G3c4Vn)ll)UzudYsHlHA(YiBQsPUg9WsowyS)EajS7cs0FCcY0oehEl2HF20lzqGgSwyJQ4y9ALZneUgxO4(tG2vEjEr4hvj4hgEzpT4d9LEzXR5QXggDPAhOf7On16OBf9ss5Q7TYDiuTd0YE1TQEjPER9w9oek3bFDVmr9c5ndUh0YQ3sHQbp2EZCEIHKXyoEdylKxPhec03)V8p9X)2FRi9XKAesc9zlyp5Dtlh5ZrD(3CU5wQbJRhmRSSd4TkWCJflskaIdLpyP8G4CohFmmrzERYpK5xF5ivpmDxBv9eaiCM0YbWnxIJPvV3P8i6yfi0nLIvg6K4Hq0b9KrJvH53mxlQFT9Sr8ZrkVdJeLPp8q(qXDE0oEqjV7gMVdPdx8gY7qm70BYgzWXh3BpSgP0nZvOUi5XaMxAKZc4pyGv8oHdmyfgXaWRpFgocqFHcDIpiAZx9avWWuREtky(XrVqo7)HhyWb67F3QGuqQoHeDidmsoBCJgliETlhujNwVj0bX)6ZF4bjVz0p8qMFxUhhuqBTujUYeqJe8cg)P1yHIVDLfg8NHtLNvWbKDW9grXe)Ke)9R8lMeB2dIY)9OV)(CK6YjLqr8W5vy4u7u1nscdbOmWL4hCddpT8hZNE(ptMEolfdM1Hoz)thYC3ZvEyUh0En5SqSkfIpeSUuRL)CsOhGsb2lWGgG2)Q7Qa3qou1nEf5TsnfMTe8veaWAlaEvOAm2SFsgZD9X47jDFmLjv9BLH9p78BMZPMLBUnsIUhOzwAcjC4VE4HsZxXJfwHB23rSsOEFi1XyZ2OJH5WDKWVwyXphhPZSnOoSRdPQF1iijeiCU9ip5Vh6a9tEP2hX7PubS5Kh(Xj(XeWWipk)TNsYdziD7KhYHu)ipKbBw5bT4Kjo)NJEB2LBtr)W8aZfj2sI5wYKzkYEUFy2YUxGazUmNsQjhyX64fu40we04FaNNzxWLjP2VHoehmuThRR(kwlX6QMQnq(IUk1TUsIdZdhHmtjCSAqhykeFMfXWVzox6fv)mq)SWDDqSp1uVYiU8NEczdldNBQqlhq)FT316VPXrq8)wIQkbSJTpoaNKk4KsBtR6xARus)AamCyqgdwC4qSue)T3z39ESpMzFCGtSuSYxCU72DND2z(TZRDbRJo01sYUwbqD81CdjGDpVjZCngSgVjHcn6G2tyZWha7lyb2)3Yz9kBdF3A2FHjp1UXHUkYPvSGWaaqDIsgq((8EjF5ZB5GorHUGx2cdVhAO)yP2qSeZSFN526)LLUFu)X7hnFt6SbVC(2T3L9lxCXUD7oF36DZzhoAWr)lat6xUCq7OOlJUGRHE2IvZUN9Zm(lt(x2)F)O)k)b9VyCY(r7MdEr4Fp39TXrxEHyb6SYZ7EYFM)xI(Cr2(r3F3RaFTH)yxkZ4s2F57ye)6Ex(23EHuEitEx5FlgbwAu3Ty7C)70l70dyjm5IZ0Qh9KFhE4(rFu5P5tKz(paEs1(2DEXObvW9JwTE7(rcDkqHulghlw9513a6FFb29DfSZit7OW7tqAyyH0bHUkcqCdme7(dIJRcfGM(BHhj65LRm2Ug5s0qpXH6dBFrYFuf11SDURCl6zYlOMkwqLO7n7ncJ37cI802rjLFd2A)q1L9YTmm3lQJvOww8tW3Ps1Km9uXYSgO0LEKB4bV(v6SFVkEkEVyikJJU2rjezgsoYVuJH)kwMvxd8ZRNmv4PQGBHFTvileCqeCCpvdEbtHhFnZR45PclEfRk3SIBO94BZGPt26nxn8U0ntGrpjsl4qioeJ7DU0py6E4TVX8X)rWh3)RB3xlIxneEKDEnOBV65LPJ)SktrRt8yUZx4s3c7jJaZ3HfepuDzjLrTpOe4nYVbNx0HwMeC4gcQi3Pq93YJXRKW(mEq7yjlN7Li0LnN8aW9kgItIoVNk4ej5ggxsbc5(v4rkB2IS55H0qxgOy7rKRfLgVWbC44Ppy)NHzxHtSyH0hy3t9qstCfvAtCTC(gCacD1VKXkK7WY7(N3xoeNdlYmNuld4R4llJTH0lM8aWYaoPEB5sBd5rqpDZResA5sEcYZvkqOeQZNeQLPBJqZlJo5wf(zo8KuuWnYbHgiv)YVvpw36JrX7Doc1LxozoB(YeJxmHL5Y1lxEfl6fzlxVdzjYy5fPNTLao88D5RaIpJU1e8fxx2K7SUHieb2XKp30VGJyaTi)gXxI(j0Uw)(9J(vMmRcvla(pevTYEqtcgLuzfBHEocPLFRcfHQYwzsN00bTUDtF1rnOpg2AQRz2z4tgK0yjMKfwrREN6wGEO(tpeAQ7kZaQGsHxvk4dYcY1qG8QGIooL4YrLVQSj(rGTYdRL5dZ92z8WzPSlOEaJjdClml3vhAgfYBZZpFefp0x94qG7cUZPtmoXQQpAL(Q5zx2YteKaNB9hexdoMm82hywqR2hCJQpi4TIEGxEOR4oitAooHEvLHpkfeqHl6K2hROz58RFZx)k4G80HPFMhaKPtZop9lSuf3q)XvHsPn17syEW7WciwQfwM2cNDPUOjiYH1u1HCrercdNvx)(ZzXC4CDrhF0MgqxCcneJdj2oQEA(feG3woIbNFey(ig)bq7wzMSAjnGnUoCg)3ioCoG3FVE1zFy8QxY8JeljpNpzkZrneVfrDnZwDL1)nyfrMzajPcjwKorPwYyHtpWs)jX(rtX2IHRV0B1aGrR6fCMz7xF)2RaTWBWeXntzEcMX85DoPH(fvgz)EnAI3(zWgrZzcvLw5jDwSenA2M1GLvZGDd2O2a2lfbLWS7A1QABpLZlv54OCohL(AJW5wzgSrkckfhmpwtf7y5I1CsNwglSvDZWLlU9k8OwqBmQCrtuelh5NjSzts9r6Lf572m)K9WRzth2oHkl3oMdx8tgagC7LWrngkCMvtjfr0vtxtwPLyZYos5qg)ts6gvn7v)KwyuP6NeQjNjd62OjLfqDbcHWGkfMCs3wMDIBlVKyf5MwkZMOm9YvLqAGa22(MKxIXu9AtdpwVt6rTwsMDkjUcviT7GkiuIXYwYpIGKLhbw7HXfbs1cIAdRaQUWtvEQx5J7rd0fDPqA7sFqn4j4Aqh0EYj(CsHdGEdTXw1cqgNqrKQBFmqnV8Gqn9XghPjWZaQhBa1CgRma1pwOpjT79ZnBgFIjv260QhNEfOKZPv5NQA7yRhnGSJjnsjbCKWfl6T6GnsalgcKiyrSP3AgMRQx7DIMGAyRxauOOROooAXFpAFbRSxoeY5G8luhw4PLVHvapCE2IvZwUGt7IaVZoR7p9bEE0qlAHkn4wHet3XkWoQVNyUE605qRddQtJaAbV0wKMR8)VFXchPvbemnKw7t8cd(WJ1VRp5loiAi0ew7G(qOc1qRddjYS2a5)pe13sv3jv0lNEeQuTUr0DDLWcLvyuzQKQpvfLWusY1UvZ(kv3XYKii(p(ob)mh3DE64LBNF(Dt2cBd3tZg1E(rAHoXmwBDCsD7qCmydUEuA5rEfvjvSuQzvwMIwlKvHVNvP7FKZ9LKDvgFEgb9a)r74jl(TY1RDn63dzeDlWrIVwS9mEbbGM6)YtoBUIHqrBcST793LBldcnAi7ydYNyXUKCWk2TdY0QRNmfHM9sZZ)9U0vlTWxWQIgppO4vDnMoGvn2br20mr3GGDWQSSOyJ5uzVnY7BPeeBLT(SF47bNTB5dBUjwcAcgxY1DvafQcjEggThGPjnSxSjnXWgCwshII82lUQ1(Q7Hn3YrI)4gXb9McdEB(7zEKbgiVyB6TIcaD2dBgVKnA8YMhuRVDtfDdCQBz4dSloR8VRQWjunlMLcentNJBJ6yw3I0OGS(JESsSDouOo8iaOi4cwsB(jRR607OZlMUEiXTjeyHy2nMNib(cz6g472o82XRgdGMxdZ4BxKL5cvTSYHjBDPBN5kct28aS3XKHWZ2U5(8zGpdbAd17DyEd(LXUIxgUk9l3ZUiIy3yHxZlR5Plk(tVgqF7RsAWtPtIfhouLM0wBD5paYZpJhAh5MAYwUEBXTPqBfd4ZFy1fvMtMLnAbPBloorNeD(R70W8cnQ4wgIbkL)m5BjQ8Ew6ANs9(OQf29ov1OMmqr7TbtHom2vmk7k(XHDf7p7kw(kAZc7QTB2v8rKDP5vSH4LenZkQsomxKttkWAuljUdXnxvnLPQXH9ZsuFO6lQUIocssgYP1OsdAIJoOWmbTVoh1rpOyBrRxIO1hYY2tDaWJbHh87gaSItOxycZX4cZixrE1qyoouH56PXFmxoFwy(jMWSwym4rXqPSBQe3923xA3BT5DG3LxRE4uqJAczy70RGjflVjSixNBQrlb4Ts1TLzX9Kg(ktK2qeCGR6ckoiXyLo0X6tk)IyBD5dUgSGJkEcRoK18eexogdY(hrpbL4dpcEbsPMzgFfxv7QnhbpUJIVoXD8gypKk)M7bOltAC49Nv3ZinxM2gB2wAirLZ(9Cry3Tow8(JOnj9yL1r47)h2TgIt6YOnjTTzWtGxakUhFSAsPIaCvzf1z940oKRiEHn6P8dT4OXD1QvUKQ3VU0SCeOaREYtA7oTb)Fp0SIFIQzPtxFR1S0h)VvAwXFV0Smfh9qZkUUAwUIPKtpNFomqp75mryGCj75keqoL9EoQnpl7Pi79PTW)(0))]] ) \ No newline at end of file +spec:RegisterPack( "Unholy", 20241109, [[Hekili:S3ZApUTn2(BjyrCS7K4yPzM0j9oEa6MBxGnOOlqNwSFZYASKT1gzlVsYPDkg4F73dPErsXdj1RjzYDakAsmPo88(C4HVwyT43wCRNBQ)IFXEM9fwwZE)0zxn7sRZxCB69h8xC7b3vFYDd8x27Ud())((TrH3t(57dJC9iFEs0X4vqtBttpK8dV9TBcs3E8UPRI292KGDhdDtdI2Vk2DDk5FV6TlU9UJbHP)Z9lUt(yBdW8G)k4NVe(RBd888Z6RFYQf3s67BSSEZS3)dNw(R(FoiX)0Yp7gh4ExOFYPpE6JL94sOh3gS7dNwE8azGoTC8)RVB62tl)quq4KQ(o7n2N)6tlj)zTVHTt2qJwwtNn9s2F2Ys4B(FoT8F4NK6hhSFd0YQ7t36ldEZEh8H)ob))9F80YDrXWFly)PL)4)6N46Mi8lBC2vVX(kaXN9EGyZ(tluca68SVN2jcPsG5Vt7G3PLhIdIIdsV)0Y1Xr7Y)(YV77bUd07FJqe)B3y4)bs4G9lUnmijnHQc4U3zDqc8JBG)5Vq1Q83teiEl(7lU1Dfrfa(Z9Pb7C3eSYjzRFyyMeno4qwRqZVk09EG()h5G6wOrcx0L0tqU58P9bB2Mo1DxIJ7DjrX35CWh092NEA5naHDA5OtlJpUhgGdr)HpGPxFA5fZwKcQscOufKFXPL3DC96PzJG7Ephp)vU3p94bk4kA(ZU7oeetq904Gp5dnZsx374T3JmoNJoouOKCKOm74ffTRyasDdbcyk5N89CUd02bsFAbikhJm0BfO3sgMlqhMu34n(Pt367gMUD6HvaR565NwE(L0bBnH)5e7VZnyFcLPDz1qagYHqBUapLmgxQLLPINWJVVdfwJpT0ZNcT1fMmo)r0X9EttsbxpaosW(tlFdOLc0L7Dr7c2tDPmLmuF2NsxRIIc9I(d43oeTYn8(dj(tzPYc)d02DaTqQL5KtlF4bdOfk(4a(K27LXA(EuYrnTCTAsPAeR((m0bg0uO1iFNe)ua1uyKv7t5TY(XOFcSVParu5K5lPUSi8aDMoIwnPbR(eL3ccLXuRNC977ogNKsHn4MlPq)UWelVtFoi0h0z2NcojaUszNisjopaRPSvWEjtDpjtnz19RGV3FV)UaisGPF1vz9m2nWZX)Ze0W1ZdWW)K4DlZLIqtLAwellll19HyJLncA80u4iWFnWfQO9jn0ptUg4QTKH3jATtWkFN04OWW7C3d6pHr)HALBrFl4kwCAckfHqFPYMCgpr7vIhgtgPslDHbQsMuYVnq2lOXmsNZiIa)c5edUlUxW4)5aG(eOYfLAuUIbB0bWpmX3n0uMVHkK8AgW5FiWd(5vL4cI)xChwTc5y1FkqbYWCvxeOYCDd06MvEt35(NgiCMttbWaj)1ccE5c033jEwFi1SM1wuqQ4bIGSYdYCkYxv8JJ0m8DCtsCpgMYoMIKe4zZQWrVjMLNNjC021BijTv6YutOHjYfEIbTkOoEWyEKBIZIlkiwv(6VOeXveqPEAyxqZgro4BsKiogCE8czcbvbImItKN7eQoHwt13jxWHhyRtQFCrHnoBdj51WXGf7LaJMj0TNB8NGOWU7twhfVJM0N6849Iiiy8rcM6Ci0DZrFksKKR2ueOlJ(L17y)1qMwBjWodTZjByEMWSmGz7jMegvGTjyDkjRbi)phyADKjKjKGsYryccGFCaj4GabhGPpMK6Sg0qJ5h)82VlmkYtkcoPEkJ5EIUlK6gNt8OUhStiqcJVsmjzqbYkX3Hn3CzdSIEXo417w1qxPBeDm9oiC)NuLsuvWrJmjGqb(5t8RPzRidMm4rfT4egS7oUWkefgvHwKzeGvda68u(qoJmrhcwLMsDFAQchmCb7E3GeSl35DuI04iWWApZm3Qphp8js8q8iep72VTU9jcfi05BPdm8F2Nw(DQPtanpREx9Vd8cMr1A6zgPFhrWl05jFrJc91gN4BPGIjPQIfYwSvHyGaRHyA8BUaQDA5VeT)nfHfx0Pc9QSwEDUSr4jUZB1UjM64tMtie)VJZRxkP0TB2c8TYk)sSfWQkCrBBa(u09Ks)M3G8cQH7N1Kz7x2bkdXj(G2a1WC7rM1pED31wC5ly8KWGZhY6yctOoj16LJZiPa0kmpKmwk0uADXOW4yILDcdGv8bTbKVjRqFy0qA2AEP2eVq7cZ8oMAFlZ2wtH11AqzwyWR16uaBnRqtzOe2zQHkxBl(qzrPPWGKgDC12A57M74MMSgJ7ImnJvrXXhP8wfR)KMLLtr2piloehYl7Zzfhzo3KikyhdDIQ86GQWUQTlkOb5a2pRBikV0iZrlfKEhwFX5flCSUcrRCnehBSYGoUn)mbvcTYehXDPNvllLHnMtZpsJVFCF2C5TYW64SYB96ZMrF6vouVcXLH9KP8nrHELPrwKNvqoAN5kc8WjFDnYvFW81QN2Te8sAZx5rohH4lQHMXrz4WEzLk4q08Ik1JfuYSAjnVyYcITmNP(pku2hPmxv1gkgvDhLXRvH09sqilBdrtSkS1Ok8xPBREmyMhOKWGf9QCgL1dmcoCGj7e54f4tv1LxxLQuBESlopv2eSFDyaLwibesG0EOtjJnJWVHQrZxWIIGSKI4510cVi6YcGPly5FN5PEhL)AuScsKE7shr6gEjtz1wBjpG5ebbw3)jF6(cSMFBoxZ)wEhzNcu2MmD99XUHKGbe0YdSz3fNfPry9X2ruGaSVO)I7(irUF1wdPMed4mwA9RXwuADLDWnE39kJaOwpLjsbbq5IiiePNGsp45QSmES5WHXcvSyiPK9CYwFy6KjzML7cGjLflKSNewNLCMAEILnWOpVUizAbyOJIvZix3ZsATjYB0XYHO6N0RXfLmiEhJP9Jw8Zzt)(ZlgWA9TA33wfWlVTPP2tRCzvmGfksv9zRBItr)kkMkPxkXlIBkbL8rz6)GLCyukd)ury18(yRKNB)yWZTBlp3wGNBzap3YCEUDB452Yc5Osp)fsL2CSDwc0fsgO05XmJIjvNfudktQXW9C35UX3zW015DQMCC3oiIuznFBQl1rg6H28r1KH00SCy9JwdGStN2EwpNsuomN0ekVp53ghbPoXRcflHPyNeHxgEkF5e0M2G1LY8NkwYkv(tLzBBJyBB3l22sGsZST7dFQFz01mFunziF22UjO5tFBB7YIx1TcxXUSVgw8Q5Y2IsifZ(krPnwLBrMBREotxQvLoSVS2PFh7mABbLythrLPJAeL(C5UAx5UWky1yn1SIacTfTQv1TcF)P0aN59T)z9cGVRydh3TkxvR(usk(0y86pv73Rw9GAoCy7wD2Sqr0znfQTpUrQL(OgupmvE41w1lp)1uJ9c)9f9g6QNdOs6)x(SSFjEfJoarr8tR(0IuSO)nNS6HWS0ySIqD(kV0eorHyVey8(X4ugVKGuHhbTMqYgVAw()CXTNlZDNssJ(z683JU8GMQfy0ciAi9FDzod8Euk6iRXnU)9C0HBtpyujCVPgmuVRuvSMOtWc1yIct(6XxPCYSXFKetsVsqo3eBJppYGDsDjQlEcWpFgpMwFniL4JmhLdwRwZLjCG0DWcBKaPDiZxlMcb5Zzqu6HdDvqAPEyPcE1QsgS7qC0N9j7BOI1tvm0QeftBouL8rKK698)mmlqHWws2uoK)T0eOP(wLfhj32TdBoRt5By0kjBXEVt2SR1RbEoD7QAct8mw2n4FF)Ffq2DtKurs3gaPZWXVPeIFsI)(v(ftuklTL)7rF)9mHiVKssCqF7rsAiegGeix0h347OzRqLyegCTHxK7ZX2QDAeLSDp4MAYhCddpT8hPmYtl)z6LarjFf8bh6K9pCi3peK9bBCWkYEeGpt0m7DH9JrXqsVAjkeRSlQKU9KHo4YGm4ymZGZoWI7DIYScIxr2ISPrXGUqQaZ6xDxf4gYnVnr)t2LxCf57Fdn7OIIeWY0IwFm((Pvfy(mQbjXcHZGKnDEvt1DSrvaG0tJMF97MjMtx9LfBuTwQCPpxpPw47rYwUyKI8ineY4tAeDdAQBcJAh5knRQUqvjeRMGevcy2u(Xe84BFvcCsTRQeQH8qQsGnYmQeLDHQsOzV7MNDk41ZF)M0TmtHtZeXkdCZ2kBQwYkLq5hjoS6(qMfUMoZ8eN)ZrVn7iEtjejEjuacX6QVP0TTUQl6VfF9WOJADftqpiDgsHBcDiXpPIj89Fmc6Klbib(QYSL0wT845BMYMRf)9WXWSkIzHxVJYAxee7tDU(nVBsCkT9Azga4Hrbu5axPqu2dQ2G5NQR5IBxszUpvIJzjXZ4T2DdnN)ysX6OyJyM1f98qu2FYV7vHC7jAngv()Byr)btvuzTYhrMSDgMG2VsixQ)1yf7ZN1fTxUVwsHrgvVPAFVb6QNtx)dl8zRmMz62725s2DwOlKMzlqMSIJQh2i6r6irYXhH1hm)YasP93Zwn0A9qOKO6NVJCsP(zMyajzB2J9cVjZIBpMqMG)ANnR8kUfAWZy3R1xOHNxB6ImbL5VGfjOaEgIQNRmkJYU5ZIM9(HGGt4j0PDk8daArrjvhEQgJpZPvhTnOtbhs5LV4JjgrXMgfcTncIqF3pNjhWpOrYe6LhiqvhxYkNNkUUEyppUkX1QlHrc6I7EhhDhRaDlNcLypkxEaT3PDK1tH)ATJUziVSOGPnv4qiy6T3iLGXparTr(yokqxBj8yeY03PJDUTIbNkpnXyD9UVONubKUZmQIs(YQ3zwK9Z4CZdU(rzvSxfVewgEeiDSSERgQ5NuAc20ITdIw)DTaHiid8thI9HCfUZT(s3MTC8YstbTgWIz3ucC6MOBXT0Q628vhvyZXrYXGOEL5PGPXGKP7cIJJOj9SogG3XyINHOD0dkuISpaDd)xT4aP87Kycn0If3JFZ7Iqd2nLgSBinyxrdnC1(QZnkM6jxIcdM0OA12z(ecXWGh586STDfYYFzk9zRM(6DjLe6Zwj9jMLqdPplNTqauNCqIjbncHTQWmcIjMpqdrmBDiM5CsbetmUDdrmlNK73VIfL0EydW3wgJojDFbxvoNxkFlHu1H5Lx1R5dJSONTB8KbjXbEsRTFH8WkLl0PiwBD(AOGXwVGrCNIBMGXwhJQNfmAhV2iym3CPUGrmZPgkyk2n8cZDtPzJwrhFG067u(kfYANojsx0b)X6KhVvZXBAcDYgKvLHmFJZQHXvH(l7Pe4r0Ov3JkVKSJzXMNGNmcc)CiDNqXAUs)TjucYAwMIt2)Dtnii1JHmgHLrmcX84WjtlTmcRgWiSKWiSrzekJLuBvhn00a58I0elezTZQexJ0iZcvGhOI2sZMSzhEFf(x)0cXvHvYnZIQ5sWF7AWvZqbWHSlgvvaHC3YkEogAZMXCHrx6OYfZd5nOERVv3Qai79Bp25XuNet7TQNj3gH4kGvJNUndSmzhtrNKPOkf3Wwflv4M2TGST8Xc7rfqhtxRzIofDUBOhkiXU7Qq2E(yggPm7RmZVLe4ViiF(MsOQYDfz0(8nLWGEtjuRDzhM7xOjlvz5xYA0LVzihRBR9psZsr3(1hwzEDk(2YDW7eXzA1hhrY2Ts5grls(wIQAtoNPTDT0nc)qouuciiIsYaOdCwX6AOwtOLoXAPUUs7Q8P)jzxkOta8yCBGO2VIT(z3kulMNk(vS)gYVImA5Rj)kYWVVg8Ry)KXVIm7Qg4xXwRFLH4gVPS9NVgA0pKJnCuh98vvHU0ZFsCvvmexdngzW98DdZZgCnNYF6BWvC3WKTB3A8lhWhY(oEdsSnwLKQx0IIF6P8w03KQ(Xpun4q(ED5BhvZknzBE(ABxztnIeKJK4BVtjmlSsEw(MqNT786WAwqER1(7uG0YLUGtElTuPT79STUBsSfUGXYxXABOz7tEDDSRvFeDdxM9ySqzgsEyFlvSL)O)wnlpShpJQym7GFBfHEHiUhLZsWVCcm7oQFYj8RuELRYJQYM)OkxL9spR7BAIyT8ObjRHmIL2KRZAFYnRxe5k8(yys5hAMGqApzUfxMjkRyx(kmxJ6wjLwT8vTDTY0FZNGOtz2QOvnEnXpeMUpDDWQXQzgpfRFvhwRS5Olwg2DuGixx2IsbE))SFCcP))I9m7lSSMbzW8hUX7bmayb)2wiTNGDhIIbFuqoyNw(kMDB8RoTm2))EmGEG1sIil2I7X0iirnYpaQq73agTN(4phqo3kN)dKt12Ey8On)kPo7aqMgH1yH9p0PXw)5eaYN(OemSC763m8Zwo(X7csa)K7FQc)ucz(B1gbil)AXXqito6SH(I8s6pIbPlgaCuQ0j)e40mzJ1aGDk1k7biJWrlFUheaATNbcdHhZ9PNaeLCt7zim5UZ8eGQ07tVVWWT20jfGn60nF8GVkBbYHjPz2ddNhLN1AF0G7qWdQEvwfaz9NRvdHi3TJPaqLEZzAiC7bBQVOW))Fk9IasJYTGSNjxcPVASM7(1hEaZtXOxqt4v(HQBeoVCKIRj2rQUHyNmA8luz2wIQsBDKjvL8gRlF54X2Fho2p5SQMRlvzBvQ4zYegQavfUKsq7Xi9Lc(XGwk0iFwlsGZ)2HMZ)iQfn40YRWYVkVi8jnl5kKjB0BbuqGV4sNiaESvwre61Mqt(YPXV81Lax(QBBoqfxgpjawsxgqGRBMDv17xKbxB7sOfrhwbxpR29fc(9p)(Peg3jv5bf44zoM)rwQDyuRz1PJwcuT4Q0UmGaxxk0DqDadI9JdJVqt8zOHF)ZVFkHXDsvEqbEjyVSx9djGZ9lWnaSDiROAantQlSdte0jq2Kkgc7EY1bc07ndLN5mFLb)N58dkN5D9QN2bf4ga2oK3xnGoKm5Ev9db69M63ZCMVYG)ZC(bIZGUPmO7wIx1OAX9OVPmgoi3Pn6IsiZVBafGS8TkOHqMDtekQKjz)fkcvKcS0d84HaYs1BBQclcILVyaBIjBklb8IRntrlMxiNMHGFRwDBT5cPFUN9lWnaSDyUN97C7huGBay7qgNyZSN5PQxgsY02xcW1ovQbf4ga2oOVoKZ(655L2qy)0MZm0W)zo)GYzWQ7GTcpS24EyFKax7c9nOa3aW2H4QdZCdvc7EY44P5SM)gMZm0W)zo)aXzqN6ztNvmYKc7WSIZG7JEPwgMcIiz3lkaCfpMfgQk8KBm(EedY2Sy7svKZFe)BMM8JWEgIt)p)vMxUXHWtqViKr2Uc9WPebl)ZUzD8OcvjV33caxXlcUHJHKhvDHXqXZUUH2C9kDGmgYEXZfgevpk6gokIV85cJa2dJUPqx8ntxe8yVP6g6xs40jlAwj)HSre2xnGW2A2GKJqoWrIW3pahjymZdvSO2y9h44AafXVB)GXd5eOTq0a7hGJOck9fwSMZmfVcJFXgiBe9((FGWovM9H1Rn2bvUxaowMc9cWrSf6fGFoIWTxZe9CSJFEVqbdJwJ0mElFGYEv3Y5LR(sfVRfLyiF9LyAwDAVLav3lnLKbYGpX8bh5U1w(WI3z1PIZTMkOSWAnBiqnGFioqg8jMp4MYc10z15yxkZG0BxnLEbQDiP8bBrI4cRF98Wqevonh8gia6QAVYb3uzwtu7XloVzmt8(1ZdJszgo4nqa0v7mLdUPYSMyNvl7YHwjPwIGdnf(E5rC7qnCQbXsEw5Q2OWHHS(mOGxhNqYztwGLO4nEBOr(bg8ga4gOw2e7aHbS2vTa2nF9OXO6PJurQV8LL)eZxw068zLN)BfcBthavVKFZNnbgkd5yu2BVZjgAgrFZhk1zWkQth8LvhKL(J1BrjVpdl81Ym6v3z9o6p0W3eiR3KRvbAfhr9U0SBGHSeITFDPPEam3u2e(BVZjgAgrFZhQuAQvTLs10oS)drHAN2KmkW12zSo0W3eiti4S70wqwTFt6wewTyFmfZnf(yL9qbOjV1NY8yL9ZMbfl5qXQPqrVaYGSB7D4BcK1lGK3htXCtHFJva6hrxNuJQfI7fOjRQWLVCFAp8Wlq8lbEzXH2yvEeEPINTNjF3yRPxEgIzj0QKVL8(flVLQ3TycCpJdTiC23iiVM8sRzZMmzYnm9uwU1kEpZejalTeGfkbyPGaSeiaBocOqt6RCnH3(1RMWBnstOob8vJMqobW49T2Q(K)fnZ5dgum0ri2j18vnA5HgItsj21LBZWmSZIw7NCmcT2bi(iE9IouxKT99LmAX32B7o2Hg(iRWDN2FkyhGK2OPHE5t34lE6(3IQ)HiI0(5RW6(hU9Mf0Wb)tF8Fsv7jGL8oGN98yCAzyqskrVEXTG6(2O4f3EBWUJHuO8Hy31PlU9qCe5jtO4j1izA5(N4S5VnBOj7hOtFuw7INmGxx2i9Chn3w(NvKTXRjVZ3Zfsu810CoMxfLNnjMQcTOFHHf6lsnzAcgAlfdTrWq9ldQqF7bmSkzWxhDyEIFAW6CS1Ew2FXXpmHL7kDXJF9QO9G3c4Vn)ll)UzudYsHlHA(YiBQsPUg9WsowyS)EajS7cs0FCcY0oehEl2HF20lzqGgSwyJQ4y9ALZneUgxO4(tG2vEjEr4hvj4hgEzpT4d9LEzXR5QXggDPAhOf7On16OBf9ss5Q7TYDiuTd0YE1TQEjPER9w9oek3bFDVmr9c5ndUh0YQ3sHQbp2EZCEIHKXyoEdylKxPhec03)V8p9X)2FRi9XKAesc9zlyp5Dtlh5ZrD(3CU5wQbJRhmRSSd4TkWCJflskaIdLpyP8G4CohFmmrzERYpK5xF5ivpmDxBv9eaiCM0YbWnxIJPvV3P8i6yfi0nLIvg6K4Hq0b9KrJvH53mxlQFT9Sr8ZrkVdJeLPp8q(qXDE0oEqjV7gMVdPdx8gY7qm70BYgzWXh3BpSgP0nZvOUi5XaMxAKZc4pyGv8oHdmyfgXaWRpFgocqFHcDIpiAZx9avWWuREtky(XrVqo7)HhyWb67F3QGuqQoHeDidmsoBCJgliETlhujNwVj0bX)6ZF4bjVz0p8qMFxUhhuqBTujUYeqJe8cg)P1yHIVDLfg8NHtLNvWbKDW9grXe)Ke)9R8lMeB2dIY)9OV)(CK6YjLqr8W5vy4u7u1nscdbOmWL4hCddpT8hZNE(ptMEolfdM1Hoz)thYC3ZvEyUh0En5SqSkfIpeSUuRL)CsOhGsb2lWGgG2)Q7Qa3qou1nEf5TsnfMTe8veaWAlaEvOAm2SFsgZD9X47jDFmLjv9BLH9p78BMZPMLBUnsIUhOzwAcjC4VE4HsZxXJfwHB23rSsOEFi1XyZ2OJH5WDKWVwyXphhPZSnOoSRdPQF1iijeiCU9ip5Vh6a9tEP2hX7PubS5Kh(Xj(XeWWipk)TNsYdziD7KhYHu)ipKbBw5bT4Kjo)NJEB2LBtr)W8aZfj2sI5wYKzkYEUFy2YUxGazUmNsQjhyX64fu40we04FaNNzxWLjP2VHoehmuThRR(kwlX6QMQnq(IUk1TUsIdZdhHmtjCSAqhykeFMfXWVzox6fv)mq)SWDDqSp1uVYiU8NEczdldNBQqlhq)FT316VPXrq8)wIQkbSJTpoaNKk4KsBtR6xARus)AamCyqgdwC4qSue)T3z39ESpMzFCGtSuSYxCU72DND2z(TZRDbRJo01sYUwbqD81CdjGDpVjZCngSgVjHcn6G2tyZWha7lyb2)3Yz9kBdF3A2FHjp1UXHUkYPvSGWaaqDIsgq((8EjF5ZB5GorHUGx2cdVhAO)yP2qSeZSFN526)LLUFu)X7hnFt6SbVC(2T3L9lxCXUD7oF36DZzhoAWr)lat6xUCq7OOlJUGRHE2IvZUN9Zm(lt(x2)F)O)k)b9VyCY(r7MdEr4Fp39TXrxEHyb6SYZ7EYFM)xI(Cr2(r3F3RaFTH)yxkZ4s2F57ye)6Ex(23EHuEitEx5FlgbwAu3Ty7C)70l70dyjm5IZ0Qh9KFhE4(rFu5P5tKz(paEs1(2DEXObvW9JwTE7(rcDkqHulghlw9513a6FFb29DfSZit7OW7tqAyyH0bHUkcqCdme7(dIJRcfGM(BHhj65LRm2Ug5s0qpXH6dBFrYFuf11SDURCl6zYlOMkwqLO7n7ncJ37cI802rjLFd2A)q1L9YTmm3lQJvOww8tW3Ps1Km9uXYSgO0LEKB4bV(v6SFVkEkEVyikJJU2rjezgsoYVuJH)kwMvxd8ZRNmv4PQGBHFTvileCqeCCpvdEbtHhFnZR45PclEfRk3SIBO94BZGPt26nxn8U0ntGrpjsl4qioeJ7DU0py6E4TVX8X)rWh3)RB3xlIxneEKDEnOBV65LPJ)SktrRt8yUZx4s3c7jJaZ3HfepuDzjLrTpOe4nYVbNx0HwMeC4gcQi3Pq93YJXRKW(mEq7yjlN7Li0LnN8aW9kgItIoVNk4ej5ggxsbc5(v4rkB2IS55H0qxgOy7rKRfLgVWbC44Ppy)NHzxHtSyH0hy3t9qstCfvAtCTC(gCacD1VKXkK7WY7(N3xoeNdlYmNuld4R4llJTH0lM8aWYaoPEB5sBd5rqpDZResA5sEcYZvkqOeQZNeQLPBJqZlJo5wf(zo8KuuWnYbHgiv)YVvpw36JrX7Doc1LxozoB(YeJxmHL5Y1lxEfl6fzlxVdzjYy5fPNTLao88D5RaIpJU1e8fxx2K7SUHieb2XKp30VGJyaTi)gXxI(j0Uw)(9J(vMmRcvla(pevTYEqtcgLuzfBHEocPLFRcfHQYwzsN00bTUDtF1rnOpg2AQRz2z4tgK0yjMKfwrREN6wGEO(tpeAQ7kZaQGsHxvk4dYcY1qG8QGIooL4YrLVQSj(rGTYdRL5dZ92z8WzPSlOEaJjdClml3vhAgfYBZZpFefp0x94qG7cUZPtmoXQQpAL(Q5zx2YteKaNB9hexdoMm82hywqR2hCJQpi4TIEGxEOR4oitAooHEvLHpkfeqHl6K2hROz58RFZx)k4G80HPFMhaKPtZop9lSuf3q)XvHsPn17syEW7WciwQfwM2cNDPUOjiYH1u1HCrercdNvx)(ZzXC4CDrhF0MgqxCcneJdj2oQEA(feG3woIbNFey(ig)bq7wzMSAjnGnUoCg)3ioCoG3FVE1zFy8QxY8JeljpNpzkZrneVfrDnZwDL1)nyfrMzajPcjwKorPwYyHtpWs)jX(rtX2IHRV0B1aGrR6fCMz7xF)2RaTWBWeXntzEcMX85DoPH(fvgz)EnAI3(zWgrZzcvLw5jDwSenA2M1GLvZGDd2O2a2lfbLWS7A1QABpLZlv54OCohL(AJW5wzgSrkckfhmpwtf7y5I1CsNwglSvDZWLlU9k8OwqBmQCrtuelh5NjSzts9r6Lf572m)K9WRzth2oHkl3oMdx8tgagC7LWrngkCMvtjfr0vtxtwPLyZYos5qg)ts6gvn7v)KwyuP6NeQjNjd62OjLfqDbcHWGkfMCs3wMDIBlVKyf5MwkZMOm9YvLqAGa22(MKxIXu9AtdpwVt6rTwsMDkjUcviT7GkiuIXYwYpIGKLhbw7HXfbs1cIAdRaQUWtvEQx5J7rd0fDPqA7sFqn4j4Aqh0EYj(CsHdGEdTXw1cqgNqrKQBFmqnV8Gqn9XghPjWZaQhBa1CgRma1pwOpjT79ZnBgFIjv260QhNEfOKZPv5NQA7yRhnGSJjnsjbCKWfl6T6GnsalgcKiyrSP3AgMRQx7DIMGAyRxauOOROooAXFpAFbRSxoeY5G8luhw4PLVHvapCE2IvZwUGt7IaVZoR7p9bEE0qlAHkn4wHet3XkWoQVNyUE605qRddQtJaAbV0wKMR8)VFXchPvbemnKw7t8cd(WJ1VRp5loiAi0ew7G(qOc1qRddjYS2a5)pe13sv3jv0lNEeQuTUr0DDLWcLvyuzQKQpvfLWusY1UvZ(kv3XYKii(p(ob)mh3DE64LBNF(Dt2cBd3tZg1E(rAHoXmwBDCsD7qCmydUEuA5rEfvjvSuQzvwMIwlKvHVNvP7FKZ9LKDvgFEgb9a)r74jl(TY1RDn63dzeDlWrIVwS9mEbbGM6)YtoBUIHqrBcST793LBldcnAi7ydYNyXUKCWk2TdY0QRNmfHM9sZZ)9U0vlTWxWQIgppO4vDnMoGvn2br20mr3GGDWQSSOyJ5uzVnY7BPeeBLT(SF47bNTB5dBUjwcAcgxY1DvafQcjEggThGPjnSxSjnXWgCwshII82lUQ1(Q7Hn3YrI)4gXb9McdEB(7zEKbgiVyB6TIcaD2dBgVKnA8YMhuRVDtfDdCQBz4dSloR8VRQWjunlMLcentNJBJ6yw3I0OGS(JESsSDouOo8iaOi4cwsB(jRR607OZlMUEiXTjeyHy2nMNib(cz6g472o82XRgdGMxdZ4BxKL5cvTSYHjBDPBN5kct28aS3XKHWZ2U5(8zGpdbAd17DyEd(LXUIxgUk9l3ZUiIy3yHxZlR5Plk(tVgqF7RsAWtPtIfhouLM0wBD5paYZpJhAh5MAYwUEBXTPqBfd4ZFy1fvMtMLnAbPBloorNeD(R70W8cnQ4wgIbkL)m5BjQ8Ew6ANs9(OQf29ov1OMmqr7TbtHom2vmk7k(XHDf7p7kw(kAZc7QTB2v8rKDP5vSH4LenZkQsomxKttkWAuljUdXnxvnLPQXH9ZsuFO6lQUIocssgYP1OsdAIJoOWmbTVoh1rpOyBrRxIO1hYY2tDaWJbHh87gaSItOxycZX4cZixrE1qyoouH56PXFmxoFwy(jMWSwym4rXqPSBQe3923xA3BT5DG3LxRE4uqJAczy70RGjflVjSixNBQrlb4Ts1TLzX9Kg(ktK2qeCGR6ckoiXyLo0X6tk)IyBD5dUgSGJkEcRoK18eexogdY(hrpbL4dpcEbsPMzgFfxv7QnhbpUJIVoXD8gypKk)M7bOltAC49Nv3ZinxM2gB2wAirLZ(9Cry3Tow8(JOnj9yL1r47)h2TgIt6YOnjTTzWtGxakUhFSAsPIaCvzf1z940oKRiEHn6P8dT4OXD1QvUKQ3VU0SCeOaREYtA7oTb)Fp0SIFIQzPtxFR1S0h)VvAwXFV0Smfh9qZkUUAwUIPKtpNFomqp75mryGCj75keqoL9EoQnpl7Pi79PTW)(0))]] )