You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1560 lines
48 KiB
1560 lines
48 KiB
-- WarriorArms.lua
|
|
-- June 2018
|
|
|
|
local addon, ns = ...
|
|
local Hekili = _G[ addon ]
|
|
|
|
local class = Hekili.Class
|
|
local state = Hekili.State
|
|
|
|
local FindUnitBuffByID = ns.FindUnitBuffByID
|
|
|
|
local PTR = ns.PTR
|
|
|
|
|
|
-- Conduits
|
|
--[-] crash_the_ramparts
|
|
--[-] merciless_bonegrinder
|
|
--[-] mortal_combo
|
|
--[x] ashen_juggernaut
|
|
|
|
-- Covenants
|
|
--[x] piercing_verdict
|
|
--[-] harrowing_punishment
|
|
--[x] veterans_repute
|
|
--[x] destructive_reverberations
|
|
|
|
-- Endurance
|
|
--[-] iron_maiden
|
|
--[x] indelible_victory
|
|
--[x] stalwart_guardian
|
|
|
|
-- Finesse
|
|
--[-] cacophonous_roar
|
|
--[x] disturb_the_peace
|
|
--[x] inspiring_presence
|
|
--[-] safeguard
|
|
|
|
|
|
if UnitClassBase( 'player' ) == 'WARRIOR' then
|
|
local spec = Hekili:NewSpecialization( 71 )
|
|
|
|
local base_rage_gen, arms_rage_mult = 1.75, 4.000
|
|
|
|
spec:RegisterResource( Enum.PowerType.Rage, {
|
|
mainhand = {
|
|
swing = "mainhand",
|
|
|
|
last = function ()
|
|
local swing = state.swings.mainhand
|
|
local t = state.query_time
|
|
|
|
return swing + floor( ( t - swing ) / state.mainhand_speed ) * state.mainhand_speed
|
|
end,
|
|
|
|
interval = "mainhand_speed",
|
|
|
|
stop = function () return state.swings.mainhand == 0 end,
|
|
value = function ()
|
|
return ( state.talent.war_machine.enabled and 1.1 or 1 ) * base_rage_gen * arms_rage_mult * state.mainhand_speed / state.haste
|
|
end,
|
|
},
|
|
|
|
conquerors_banner = {
|
|
aura = "conquerors_banner",
|
|
|
|
last = function ()
|
|
local app = state.buff.conquerors_banner.applied
|
|
local t = state.query_time
|
|
|
|
return app + floor( t - app )
|
|
end,
|
|
|
|
interval = 1,
|
|
value = 4,
|
|
},
|
|
} )
|
|
|
|
-- Talents
|
|
spec:RegisterTalents( {
|
|
war_machine = 22624, -- 262231
|
|
sudden_death = 22360, -- 29725
|
|
skullsplitter = 22371, -- 260643
|
|
|
|
double_time = 19676, -- 103827
|
|
impending_victory = 22372, -- 202168
|
|
storm_bolt = 22789, -- 107570
|
|
|
|
massacre = 22380, -- 281001
|
|
fervor_of_battle = 22489, -- 202316
|
|
rend = 19138, -- 772
|
|
|
|
second_wind = 15757, -- 29838
|
|
bounding_stride = 22627, -- 202163
|
|
defensive_stance = 22628, -- 197690
|
|
|
|
collateral_damage = 22392, -- 334779
|
|
warbreaker = 22391, -- 262161
|
|
cleave = 22362, -- 845
|
|
|
|
in_for_the_kill = 22394, -- 248621
|
|
avatar = 22397, -- 107574
|
|
deadly_calm = 22399, -- 262228
|
|
|
|
anger_management = 21204, -- 152278
|
|
dreadnaught = 22407, -- 262150
|
|
ravager = 21667, -- 152277
|
|
} )
|
|
|
|
-- PvP Talents
|
|
spec:RegisterPvpTalents( {
|
|
death_sentence = 3522, -- 198500
|
|
demolition = 5372, -- 329033
|
|
disarm = 3534, -- 236077
|
|
duel = 34, -- 236273
|
|
master_and_commander = 28, -- 235941
|
|
shadow_of_the_colossus = 29, -- 198807
|
|
sharpen_blade = 33, -- 198817
|
|
storm_of_destruction = 31, -- 236308
|
|
war_banner = 32, -- 236320
|
|
warbringer = 5376, -- 356353
|
|
} )
|
|
|
|
-- Auras
|
|
spec:RegisterAuras( {
|
|
avatar = {
|
|
id = 107574,
|
|
duration = 20,
|
|
max_stack = 1,
|
|
},
|
|
battle_shout = {
|
|
id = 6673,
|
|
duration = 3600,
|
|
max_stack = 1,
|
|
shared = "player", -- check for anyone's buff on the player.
|
|
},
|
|
berserker_rage = {
|
|
id = 18499,
|
|
duration = 6,
|
|
type = "",
|
|
max_stack = 1,
|
|
},
|
|
bladestorm = {
|
|
id = 227847,
|
|
duration = function () return 6 * haste end,
|
|
max_stack = 1,
|
|
onCancel = function()
|
|
setCooldown( "global_cooldown", 0 )
|
|
end,
|
|
},
|
|
bounding_stride = {
|
|
id = 202164,
|
|
duration = 3,
|
|
max_stack = 1,
|
|
},
|
|
challenging_shout = {
|
|
id = 1161,
|
|
duration = 6,
|
|
max_stack = 1,
|
|
},
|
|
charge = {
|
|
id = 105771,
|
|
duration = 1,
|
|
max_stack = 1,
|
|
},
|
|
collateral_damage = {
|
|
id = 334783,
|
|
duration = 30,
|
|
max_stack = 8,
|
|
},
|
|
colossus_smash = {
|
|
id = 208086,
|
|
duration = function () return set_bonus.tier28_2pc > 0 and 13 or 10 end,
|
|
max_stack = 1,
|
|
},
|
|
deadly_calm = {
|
|
id = 262228,
|
|
duration = 20,
|
|
max_stack = 4,
|
|
},
|
|
deep_wounds = {
|
|
id = 262115,
|
|
duration = 12,
|
|
max_stack = 1,
|
|
},
|
|
defensive_stance = {
|
|
id = 197690,
|
|
duration = 3600,
|
|
max_stack = 1,
|
|
},
|
|
die_by_the_sword = {
|
|
id = 118038,
|
|
duration = 8,
|
|
max_stack = 1,
|
|
},
|
|
hamstring = {
|
|
id = 1715,
|
|
duration = 15,
|
|
max_stack = 1,
|
|
},
|
|
ignore_pain = {
|
|
id = 190456,
|
|
duration = 12,
|
|
max_stack = 1,
|
|
},
|
|
in_for_the_kill = {
|
|
id = 248622,
|
|
duration = 10,
|
|
max_stack = 1,
|
|
},
|
|
intimidating_shout = {
|
|
id = 5246,
|
|
duration = 8,
|
|
max_stack = 1,
|
|
},
|
|
mortal_wounds = {
|
|
id = 115804,
|
|
duration = 10,
|
|
max_stack = 1,
|
|
},
|
|
overpower = {
|
|
id = 7384,
|
|
duration = 15,
|
|
max_stack = 2,
|
|
},
|
|
piercing_howl = {
|
|
id = 12323,
|
|
duration = 8,
|
|
max_stack = 1,
|
|
},
|
|
rallying_cry = {
|
|
id = 97463,
|
|
duration = function () return 10 * ( 1 + conduit.inspiring_presence.mod * 0.01 ) end,
|
|
max_stack = 1,
|
|
},
|
|
--[[ ravager = {
|
|
id = 152277,
|
|
}, ]]
|
|
rend = {
|
|
id = 772,
|
|
duration = 15,
|
|
tick_time = 3,
|
|
max_stack = 1,
|
|
},
|
|
--[[ seasoned_soldier = {
|
|
id = 279423,
|
|
}, ]]
|
|
stone_heart = {
|
|
id = 225947,
|
|
duration = 10,
|
|
},
|
|
sudden_death = {
|
|
id = 52437,
|
|
duration = 10,
|
|
max_stack = 1,
|
|
},
|
|
spell_reflection = {
|
|
id = 23920,
|
|
duration = function () return legendary.misshapen_mirror.enabled and 8 or 5 end,
|
|
max_stack = 1,
|
|
},
|
|
storm_bolt = {
|
|
id = 132169,
|
|
duration = 4,
|
|
max_stack = 1,
|
|
},
|
|
sweeping_strikes = {
|
|
id = 260708,
|
|
duration = function () return level > 57 and 15 or 12 end,
|
|
max_stack = 1,
|
|
},
|
|
--[[ tactician = {
|
|
id = 184783,
|
|
}, ]]
|
|
taunt = {
|
|
id = 355,
|
|
duration = 3,
|
|
max_stack = 1,
|
|
},
|
|
victorious = {
|
|
id = 32216,
|
|
duration = 20,
|
|
max_stack = 1,
|
|
},
|
|
|
|
-- Azerite Powers
|
|
crushing_assault = {
|
|
id = 278826,
|
|
duration = 10,
|
|
max_stack = 1
|
|
},
|
|
|
|
gathering_storm = {
|
|
id = 273415,
|
|
duration = 6,
|
|
max_stack = 5,
|
|
},
|
|
|
|
intimidating_presence = {
|
|
id = 288644,
|
|
duration = 12,
|
|
max_stack = 1,
|
|
},
|
|
|
|
striking_the_anvil = {
|
|
id = 288455,
|
|
duration = 15,
|
|
max_stack = 1,
|
|
},
|
|
|
|
test_of_might = {
|
|
id = 275540,
|
|
duration = 12,
|
|
max_stack = 1
|
|
},
|
|
} )
|
|
|
|
|
|
local rageSpent = 0
|
|
local gloryRage = 0
|
|
|
|
spec:RegisterStateExpr( "rage_spent", function ()
|
|
return rageSpent
|
|
end )
|
|
|
|
spec:RegisterStateExpr( "glory_rage", function ()
|
|
return gloryRage
|
|
end )
|
|
|
|
spec:RegisterHook( "spend", function( amt, resource )
|
|
if resource == "rage" then
|
|
if talent.anger_management.enabled then
|
|
rage_spent = rage_spent + amt
|
|
local reduction = floor( rage_spent / 20 )
|
|
rage_spent = rage_spent % 20
|
|
|
|
if reduction > 0 then
|
|
cooldown.colossus_smash.expires = cooldown.colossus_smash.expires - reduction
|
|
cooldown.bladestorm.expires = cooldown.bladestorm.expires - reduction
|
|
cooldown.warbreaker.expires = cooldown.warbreaker.expires - reduction
|
|
end
|
|
end
|
|
|
|
if legendary.glory.enabled and buff.conquerors_banner.up then
|
|
glory_rage = glory_rage + amt
|
|
local reduction = floor( glory_rage / 20 ) * 0.5
|
|
glory_rage = glory_rage % 20
|
|
|
|
buff.conquerors_banner.expires = buff.conquerors_banner.expires + reduction
|
|
end
|
|
end
|
|
end )
|
|
|
|
local last_cs_target = nil
|
|
|
|
spec:RegisterCombatLogEvent( function( _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName )
|
|
if sourceGUID == state.GUID and subtype == "SPELL_CAST_SUCCESS" then
|
|
if ( spellName == class.abilities.colossus_smash.name or spellName == class.abilities.warbreaker.name ) then
|
|
last_cs_target = destGUID
|
|
end
|
|
end
|
|
end )
|
|
|
|
|
|
local RAGE = Enum.PowerType.Rage
|
|
local lastRage = -1
|
|
|
|
spec:RegisterUnitEvent( "UNIT_POWER_FREQUENT", "player", nil, function( event, unit, powerType )
|
|
if powerType == "RAGE" then
|
|
local current = UnitPower( "player", RAGE )
|
|
|
|
if current < lastRage then
|
|
rageSpent = ( rageSpent + lastRage - current ) % 20 -- Anger Mgmt.
|
|
|
|
if state.legendary.glory.enabled and GetPlayerAuraBySpellID( 324143 ) then
|
|
gloryRage = ( gloryRage + lastRage - current ) % 20 -- Glory.
|
|
end
|
|
end
|
|
|
|
lastRage = current
|
|
end
|
|
end )
|
|
|
|
|
|
spec:RegisterHook( "TimeToReady", function( wait, action )
|
|
local id = class.abilities[ action ].id
|
|
if buff.bladestorm.up and ( id < -99 or id > 0 ) then
|
|
wait = max( wait, buff.bladestorm.remains )
|
|
end
|
|
return wait
|
|
end )
|
|
|
|
|
|
local cs_actual
|
|
|
|
spec:RegisterHook( "reset_precast", function ()
|
|
rage_spent = nil
|
|
|
|
if not cs_actual then cs_actual = cooldown.colossus_smash end
|
|
|
|
if talent.warbreaker.enabled and cs_actual then
|
|
cooldown.colossus_smash = cooldown.warbreaker
|
|
else
|
|
cooldown.colossus_smash = cs_actual
|
|
end
|
|
|
|
|
|
if prev_gcd[1].colossus_smash and time - action.colossus_smash.lastCast < 1 and last_cs_target == target.unit and debuff.colossus_smash.down then
|
|
-- Apply Colossus Smash early because its application is delayed for some reason.
|
|
applyDebuff( "target", "colossus_smash", 10 )
|
|
elseif prev_gcd[1].warbreaker and time - action.warbreaker.lastCast < 1 and last_cs_target == target.unit and debuff.colossus_smash.down then
|
|
applyDebuff( "target", "colossus_smash", 10 )
|
|
end
|
|
end )
|
|
|
|
|
|
spec:RegisterStateExpr( "cycle_for_execute", function ()
|
|
if active_enemies == 1 or target.health_pct < ( talent.massacre.enabled and 35 or 20 ) or not settings.cycle or buff.execute_ineligible.down or buff.sudden_death.up then return false end
|
|
return Hekili:GetNumTargetsBelowHealthPct( talent.massacre.enabled and 35 or 20, false, max( settings.cycle_min, offset + delay ) ) > 0
|
|
end )
|
|
|
|
|
|
spec:RegisterStateExpr( "cycle_for_condemn", function ()
|
|
if active_enemies == 1 or target.health_pct < ( talent.massacre.enabled and 35 or 20 ) or target.health_pct > 80 or not settings.cycle or not covenant.venthyr or buff.condemn_ineligible.down or buff.sudden_death.up then return false end
|
|
return Hekili:GetNumTargetsBelowHealthPct( talent.massacre.enabled and 35 or 20, false, max( settings.cycle_min, offset + delay ) ) > 0 or Hekili:GetNumTargetsAboveHealthPct( 80, false, max( settings.cycle_min, offset + delay ) ) > 0
|
|
end )
|
|
|
|
|
|
-- Tier 28
|
|
spec:RegisterGear( 'tier28', 188942, 188941, 188940, 188938, 188937 )
|
|
spec:RegisterSetBonuses( "tier28_2pc", 364553, "tier28_4pc", 363913 )
|
|
-- 2-Set - Pile On - Colossus Smash / Warbreaker lasts 3 sec longer and increases your damage dealt to affected enemies by an additional 5%.
|
|
-- 4-Set - Pile On - Tactician has a 50% increased chance to proc against enemies with Colossus Smash and causes your next Overpower to grant 2% Strength, up to 20% for 15 sec.
|
|
spec:RegisterAuras( {
|
|
pile_on_ready = {
|
|
id = 363917,
|
|
duration = 15,
|
|
max_stack = 1,
|
|
},
|
|
pile_on_str = {
|
|
id = 366769,
|
|
duration = 15,
|
|
max_stack = 4,
|
|
copy = "pile_on"
|
|
}
|
|
})
|
|
|
|
|
|
spec:RegisterGear( 'tier20', 147187, 147188, 147189, 147190, 147191, 147192 )
|
|
spec:RegisterAura( "raging_thirst", {
|
|
id = 242300,
|
|
duration = 8
|
|
} ) -- fury 2pc.
|
|
spec:RegisterAura( "bloody_rage", {
|
|
id = 242952,
|
|
duration = 10,
|
|
max_stack = 10
|
|
} ) -- fury 4pc.
|
|
|
|
spec:RegisterGear( 'tier21', 152178, 152179, 152180, 152181, 152182, 152183 )
|
|
spec:RegisterAura( "war_veteran", {
|
|
id = 253382,
|
|
duration = 8
|
|
} ) -- arms 2pc.
|
|
spec:RegisterAura( "weighted_blade", {
|
|
id = 253383,
|
|
duration = 1,
|
|
max_stack = 3
|
|
} ) -- arms 4pc.
|
|
|
|
spec:RegisterGear( "ceannar_charger", 137088 )
|
|
spec:RegisterGear( "timeless_stratagem", 143728 )
|
|
spec:RegisterGear( "kazzalax_fujiedas_fury", 137053 )
|
|
spec:RegisterAura( "fujiedas_fury", {
|
|
id = 207776,
|
|
duration = 10,
|
|
max_stack = 4
|
|
} )
|
|
spec:RegisterGear( "mannoroths_bloodletting_manacles", 137107 ) -- NYI.
|
|
spec:RegisterGear( "najentuss_vertebrae", 137087 )
|
|
spec:RegisterGear( "valarjar_berserkers", 151824 )
|
|
spec:RegisterGear( "ayalas_stone_heart", 137052 )
|
|
spec:RegisterAura( "stone_heart", { id = 225947,
|
|
duration = 10
|
|
} )
|
|
spec:RegisterGear( "the_great_storms_eye", 151823 )
|
|
spec:RegisterAura( "tornados_eye", {
|
|
id = 248142,
|
|
duration = 6,
|
|
max_stack = 6
|
|
} )
|
|
spec:RegisterGear( "archavons_heavy_hand", 137060 )
|
|
spec:RegisterGear( "weight_of_the_earth", 137077 ) -- NYI.
|
|
|
|
|
|
spec:RegisterGear( "soul_of_the_battlelord", 151650 )
|
|
|
|
|
|
|
|
-- Abilities
|
|
spec:RegisterAbilities( {
|
|
avatar = {
|
|
id = 107574,
|
|
cast = 0,
|
|
cooldown = 90,
|
|
gcd = "off",
|
|
|
|
spend = -20,
|
|
spendType = "rage",
|
|
|
|
toggle = "cooldowns",
|
|
|
|
startsCombat = false,
|
|
texture = 613534,
|
|
|
|
talent = "avatar",
|
|
|
|
handler = function ()
|
|
applyBuff( "avatar" )
|
|
end,
|
|
},
|
|
|
|
|
|
battle_shout = {
|
|
id = 6673,
|
|
cast = 0,
|
|
cooldown = 15,
|
|
gcd = "spell",
|
|
|
|
startsCombat = false,
|
|
texture = 132333,
|
|
|
|
nobuff = "battle_shout",
|
|
essential = true,
|
|
|
|
handler = function ()
|
|
applyBuff( "battle_shout" )
|
|
end,
|
|
},
|
|
|
|
|
|
berserker_rage = {
|
|
id = 18499,
|
|
cast = 0,
|
|
cooldown = 60,
|
|
gcd = "off",
|
|
|
|
toggle = "cooldowns",
|
|
|
|
startsCombat = true,
|
|
texture = 136009,
|
|
|
|
handler = function ()
|
|
applyBuff( "berserker_rage" )
|
|
end,
|
|
},
|
|
|
|
|
|
bladestorm = {
|
|
id = 227847,
|
|
cast = 0,
|
|
cooldown = function () return ( essence.vision_of_perfection.enabled and 0.85 or 1 ) * 90 end,
|
|
gcd = "spell",
|
|
|
|
toggle = "cooldowns",
|
|
|
|
startsCombat = true,
|
|
texture = 236303,
|
|
|
|
notalent = "ravager",
|
|
range = 8,
|
|
|
|
handler = function ()
|
|
applyBuff( "bladestorm" )
|
|
setCooldown( "global_cooldown", 6 * haste )
|
|
|
|
if azerite.gathering_storm.enabled then
|
|
applyBuff( "gathering_storm", 6 + ( 4 * haste ), 4 )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
challenging_shout = {
|
|
id = 1161,
|
|
cast = 0,
|
|
cooldown = 240,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 132091,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "challenging_shout" )
|
|
end,
|
|
},
|
|
|
|
|
|
charge = {
|
|
id = 100,
|
|
cast = 0,
|
|
charges = function () return talent.double_time.enabled and 2 or nil end,
|
|
cooldown = function () return talent.double_time.enabled and 17 or 20 end,
|
|
recharge = function () return talent.double_time.enabled and 17 or 20 end,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 132337,
|
|
|
|
usable = function () return target.distance > 10 and ( query_time - action.charge.lastCast > gcd.execute ) end,
|
|
handler = function ()
|
|
setDistance( 5 )
|
|
applyDebuff( "target", "charge" )
|
|
end,
|
|
},
|
|
|
|
|
|
cleave = {
|
|
id = 845,
|
|
cast = 0,
|
|
cooldown = 6,
|
|
hasteCD = true,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
return 20
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132338,
|
|
|
|
talent = "cleave",
|
|
|
|
handler = function ()
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" ) end
|
|
if active_enemies >= 3 then applyDebuff( "target", "deep_wounds" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
colossus_smash = {
|
|
id = 167105,
|
|
cast = 0,
|
|
cooldown = 45,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 464973,
|
|
|
|
notalent = "warbreaker",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "colossus_smash" )
|
|
applyDebuff( "target", "deep_wounds" )
|
|
|
|
if talent.in_for_the_kill.enabled then
|
|
applyBuff( "in_for_the_kill" )
|
|
stat.haste = state.haste + ( target.health.pct < 20 and 0.2 or 0.1 )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
deadly_calm = {
|
|
id = 262228,
|
|
cast = 0,
|
|
cooldown = 60,
|
|
gcd = "off",
|
|
|
|
toggle = "cooldowns",
|
|
|
|
startsCombat = false,
|
|
texture = 298660,
|
|
|
|
handler = function ()
|
|
applyBuff( "deadly_calm" )
|
|
end,
|
|
},
|
|
|
|
|
|
defensive_stance = {
|
|
id = 197690,
|
|
cast = 0,
|
|
cooldown = 6,
|
|
gcd = "off",
|
|
|
|
startsCombat = false,
|
|
texture = 132349,
|
|
|
|
talent = "defensive_stance",
|
|
toggle = "defensives",
|
|
|
|
handler = function ()
|
|
if buff.defensive_stance.up then removeBuff( "defensive_stance" )
|
|
else applyBuff( "defensive_stance" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
die_by_the_sword = {
|
|
id = 118038,
|
|
cast = 0,
|
|
cooldown = function () return ( level > 51 and 120 or 180 ) - conduit.stalwart_guardian.mod * 0.001 end,
|
|
gcd = "spell",
|
|
|
|
startsCombat = false,
|
|
texture = 132336,
|
|
|
|
toggle = "defensives",
|
|
|
|
handler = function ()
|
|
applyBuff( "die_by_the_sword" )
|
|
end,
|
|
},
|
|
|
|
|
|
execute = {
|
|
id = function () return talent.massacre.enabled and 281000 or 163201 end,
|
|
known = 163201,
|
|
noOverride = 317485,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = 0,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 135358,
|
|
|
|
usable = function ()
|
|
if buff.sudden_death.up or buff.stone_heart.up then return true end
|
|
if cycle_for_execute then return true end
|
|
return target.health_pct < ( talent.massacre.enabled and 35 or 20 ), "requires < " .. ( talent.massacre.enabled and 35 or 20 ) .. "% health"
|
|
end,
|
|
|
|
cycle = "execute_ineligible",
|
|
|
|
indicator = function () if cycle_for_execute then return "cycle" end end,
|
|
|
|
timeToReady = function()
|
|
-- Instead of using regular resource requirements, we'll use timeToReady to support the spend system.
|
|
if rage.current >= 20 then return 0 end
|
|
return rage.time_to_20
|
|
end,
|
|
|
|
handler = function ()
|
|
if not buff.sudden_death.up and not buff.stone_heart.up then
|
|
local cost = min( rage.current, 40 )
|
|
spend( cost, "rage", nil, true )
|
|
gain( 0.2 * cost, "rage" )
|
|
end
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" )
|
|
elseif buff.stone_heart.up then removeBuff( "stone_heart" )
|
|
else removeBuff( "sudden_death" ) end
|
|
|
|
if legendary.exploiter.enabled then applyDebuff( "target", "exploiter", nil, min( 2, debuff.exploiter.stack + 1 ) ) end
|
|
|
|
if conduit.ashen_juggernaut.enabled then addStack( "ashen_juggernaut", nil, 1 ) end
|
|
end,
|
|
|
|
copy = { 163201, 281000, 281000 },
|
|
|
|
auras = {
|
|
-- Conduit
|
|
ashen_juggernaut = {
|
|
id = 335234,
|
|
duration = 8,
|
|
max_stack = function () return max( 8, conduit.ashen_juggernaut.mod ) end
|
|
},
|
|
-- Legendary
|
|
exploiter = {
|
|
id = 335452,
|
|
duration = 30,
|
|
max_stack = 2,
|
|
},
|
|
-- Target Swapping
|
|
execute_ineligible = {
|
|
duration = 3600,
|
|
max_stack = 1,
|
|
generate = function( t, auraType )
|
|
if buff.sudden_death.down and buff.stone_heart.down and target.health_pct > ( talent.massacre.enabled and 35 or 20 ) then
|
|
t.count = 1
|
|
t.expires = query_time + 3600
|
|
t.applied = query_time
|
|
t.duration = 3600
|
|
t.caster = "player"
|
|
return
|
|
end
|
|
t.count = 0
|
|
t.expires = 0
|
|
t.applied = 0
|
|
t.caster = "nobody"
|
|
end
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
hamstring = {
|
|
id = 1715,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
return 10
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132316,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "hamstring" )
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
heroic_leap = {
|
|
id = 6544,
|
|
cast = 0,
|
|
cooldown = function () return talent.bounding_stride.enabled and 30 or 45 end,
|
|
charges = function () return legendary.leaper.enabled and 3 or nil end,
|
|
recharge = function () return legendary.leaper.enabled and ( talent.bounding_stride.enabled and 30 or 45 ) or nil end,
|
|
gcd = "off",
|
|
|
|
startsCombat = false,
|
|
texture = 236171,
|
|
|
|
usable = function () return query_time - action.heroic_leap.lastCast > gcd.execute * 2 end,
|
|
handler = function ()
|
|
setDistance( 15 )
|
|
if talent.bounding_stride.enabled then applyBuff( "bounding_stride" ) end
|
|
end,
|
|
|
|
copy = 52174
|
|
},
|
|
|
|
|
|
heroic_throw = {
|
|
id = 57755,
|
|
cast = 0,
|
|
cooldown = 6,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 132453,
|
|
|
|
usable = function () return target.distance > 10 end,
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
ignore_pain = {
|
|
id = 190456,
|
|
cast = 0,
|
|
cooldown = 12,
|
|
gcd = "off",
|
|
|
|
spend = 0,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 1377132,
|
|
|
|
handler = function ()
|
|
applyBuff( "ignore_pain" )
|
|
end,
|
|
},
|
|
|
|
|
|
impending_victory = {
|
|
id = 202168,
|
|
cast = 0,
|
|
cooldown = 30,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
return 10
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 589768,
|
|
|
|
talent = "impending_victory",
|
|
|
|
handler = function ()
|
|
removeBuff( "victorious" )
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" ) end
|
|
if conduit.indelible_victory.enabled then applyBuff( "indelible_victory" ) end
|
|
end,
|
|
|
|
auras = {
|
|
-- Conduit
|
|
indelible_victory = {
|
|
id = 336642,
|
|
duration = 8,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
intervene = {
|
|
id = 3411,
|
|
cast = 0,
|
|
cooldown = 30,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 132365,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
intimidating_shout = {
|
|
id = 5246,
|
|
cast = 0,
|
|
cooldown = 90,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 132154,
|
|
|
|
handler = function ()
|
|
applyBuff( "intimidating_shout" )
|
|
if azerite.intimidating_presence.enabled then applyDebuff( "target", "intimidating_presence" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
mortal_strike = {
|
|
id = 12294,
|
|
cast = 0,
|
|
cooldown = 6,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
return buff.battlelord.up and 15 or 30
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132355,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "mortal_wounds" )
|
|
applyDebuff( "target", "deep_wounds" )
|
|
removeBuff( "overpower" )
|
|
removeBuff( "exploiter" )
|
|
removeBuff( "sharpen_blade" )
|
|
|
|
if buff.deadly_calm.up then
|
|
removeStack( "deadly_calm" )
|
|
else
|
|
removeBuff( "battlelord" )
|
|
end
|
|
end,
|
|
|
|
auras = {
|
|
battlelord = {
|
|
id = 346369,
|
|
duration = 10,
|
|
max_stack = 1
|
|
},
|
|
}
|
|
},
|
|
|
|
|
|
overpower = {
|
|
id = 7384,
|
|
cast = 0,
|
|
charges = function () return talent.dreadnaught.enabled and 2 or nil end,
|
|
cooldown = 12,
|
|
recharge = 12,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 132223,
|
|
|
|
handler = function ()
|
|
addStack( "overpower", 15, 1 )
|
|
|
|
if buff.striking_the_anvil.up then
|
|
removeBuff( "striking_the_anvil" )
|
|
gainChargeTime( "mortal_strike", 1.5 )
|
|
end
|
|
|
|
if buff.pile_on_ready.up then
|
|
addStack( "pile_on_str", nil, 1 )
|
|
removeBuff( "pile_on_ready" )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
pummel = {
|
|
id = 6552,
|
|
cast = 0,
|
|
cooldown = 15,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 132938,
|
|
|
|
toggle = "interrupts",
|
|
|
|
debuff = "casting",
|
|
readyTime = state.timeToInterrupt,
|
|
|
|
handler = function ()
|
|
interrupt()
|
|
end,
|
|
},
|
|
|
|
|
|
rallying_cry = {
|
|
id = 97462,
|
|
cast = 0,
|
|
cooldown = 180,
|
|
gcd = "spell",
|
|
|
|
startsCombat = false,
|
|
texture = 132351,
|
|
|
|
toggle = "defensives",
|
|
|
|
handler = function ()
|
|
applyBuff( "rallying_cry" )
|
|
end,
|
|
},
|
|
|
|
|
|
ravager = {
|
|
id = 152277,
|
|
cast = 0,
|
|
cooldown = function () return ( essence.vision_of_perfection.enabled and 0.87 or 1 ) * 45 end,
|
|
gcd = "spell",
|
|
|
|
spend = -7,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 970854,
|
|
|
|
talent = "ravager",
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
rend = {
|
|
id = 772,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
return 30
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132155,
|
|
|
|
talent = "rend",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "rend" )
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
sharpen_blade = {
|
|
id = 198817,
|
|
cast = 0,
|
|
cooldown = 25,
|
|
gcd = "off",
|
|
|
|
startsCombat = false,
|
|
pvptalent = "sharpen_blade",
|
|
|
|
handler = function ()
|
|
applyBuff( "sharpen_blade" )
|
|
end,
|
|
|
|
auras = {
|
|
sharpen_blade = {
|
|
id = 198817,
|
|
duration = 3600,
|
|
max_stack = 1,
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
shattering_throw = {
|
|
id = 64382,
|
|
cast = 1.5,
|
|
cooldown = 180,
|
|
gcd = "spell",
|
|
|
|
toggle = "cooldowns",
|
|
|
|
startsCombat = true,
|
|
texture = 311430,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
shield_block = {
|
|
id = 2565,
|
|
cast = 0,
|
|
cooldown = 16,
|
|
gcd = "off",
|
|
|
|
spend = 30,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132110,
|
|
|
|
nobuff = "shield_block",
|
|
|
|
handler = function ()
|
|
applyBuff( "shield_block" )
|
|
end,
|
|
},
|
|
|
|
|
|
shield_slam = {
|
|
id = 23922,
|
|
cast = 0,
|
|
cooldown = 9,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 134951,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
skullsplitter = {
|
|
id = 260643,
|
|
cast = 0,
|
|
cooldown = 21,
|
|
hasteCD = true,
|
|
gcd = "spell",
|
|
|
|
spend = -20,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 2065621,
|
|
|
|
talent = "skullsplitter",
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
slam = {
|
|
id = 1464,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
if buff.crushing_assault.up then return 0 end
|
|
return 20
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132340,
|
|
|
|
handler = function ()
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" ) end
|
|
removeBuff( "crushing_assault" )
|
|
end,
|
|
},
|
|
|
|
|
|
spell_reflection = {
|
|
id = 23920,
|
|
cast = 0,
|
|
cooldown = 25,
|
|
gcd = "off",
|
|
|
|
startsCombat = false,
|
|
texture = 132361,
|
|
|
|
toggle = "interrupts",
|
|
|
|
handler = function ()
|
|
applyBuff( "spell_reflection" )
|
|
end,
|
|
},
|
|
|
|
|
|
storm_bolt = {
|
|
id = 107570,
|
|
cast = 0,
|
|
cooldown = 30,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 613535,
|
|
|
|
talent = "storm_bolt",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "storm_bolt" )
|
|
end,
|
|
},
|
|
|
|
|
|
sweeping_strikes = {
|
|
id = 260708,
|
|
cast = 0,
|
|
cooldown = 30,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 132306,
|
|
|
|
handler = function ()
|
|
applyBuff( "sweeping_strikes" )
|
|
setCooldown( "global_cooldown", 0.75 ) -- Might work?
|
|
end,
|
|
},
|
|
|
|
|
|
taunt = {
|
|
id = 355,
|
|
cast = 0,
|
|
cooldown = 8,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 136080,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "taunt" )
|
|
end,
|
|
},
|
|
|
|
|
|
victory_rush = {
|
|
id = 34428,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 132342,
|
|
|
|
notalent = "impending_victory",
|
|
|
|
buff = "victorious",
|
|
|
|
handler = function ()
|
|
removeBuff( "victorious" )
|
|
if conduit.indelible_victory.enabled then applyBuff( "indelible_victory" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
warbreaker = {
|
|
id = 262161,
|
|
cast = 0,
|
|
cooldown = 45,
|
|
velocity = 25,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 2065633,
|
|
|
|
talent = "warbreaker",
|
|
|
|
handler = function ()
|
|
if talent.in_for_the_kill.enabled then
|
|
if buff.in_for_the_kill.down then
|
|
stat.haste = stat.haste + ( target.health.pct < 0.2 and 0.2 or 0.1 )
|
|
end
|
|
applyBuff( "in_for_the_kill" )
|
|
end
|
|
|
|
applyDebuff( "target", "colossus_smash" )
|
|
applyDebuff( "target", "deep_wounds" )
|
|
end,
|
|
},
|
|
|
|
|
|
whirlwind = {
|
|
id = 1680,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.deadly_calm.up then return 0 end
|
|
return 30
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132369,
|
|
|
|
handler = function ()
|
|
if buff.deadly_calm.up then removeStack( "deadly_calm" ) end
|
|
if talent.fervor_of_battle.enabled and buff.crushing_assault.up then removeBuff( "crushing_assault" ) end
|
|
removeBuff( "collateral_damage" )
|
|
end,
|
|
|
|
auras = {
|
|
merciless_bonegrinder = {
|
|
id = 346574,
|
|
duration = 9,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
-- Warrior - Kyrian - 307865 - spear_of_bastion (Spear of Bastion)
|
|
spear_of_bastion = {
|
|
id = 307865,
|
|
cast = 0,
|
|
cooldown = 60,
|
|
gcd = "spell",
|
|
|
|
spend = function () return -25 * ( 1 + conduit.piercing_verdict.mod * 0.01 ) end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 3565453,
|
|
|
|
toggle = "essences",
|
|
|
|
velocity = 30,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "spear_of_bastion" )
|
|
if legendary.elysian_might.enabled then applyBuff( "elysian_might" ) end
|
|
end,
|
|
|
|
auras = {
|
|
spear_of_bastion = {
|
|
id = 307871,
|
|
duration = function () return legendary.elysian_might.enabled and 8 or 4 end,
|
|
max_stack = 1
|
|
},
|
|
elysian_might = {
|
|
id = 311193,
|
|
duration = 8,
|
|
max_stack = 1,
|
|
},
|
|
}
|
|
},
|
|
|
|
-- Warrior - Necrolord - 324143 - conquerors_banner (Conqueror's Banner)
|
|
conquerors_banner = {
|
|
id = 324143,
|
|
cast = 0,
|
|
cooldown = 180,
|
|
gcd = "spell",
|
|
|
|
startsCombat = false,
|
|
texture = 3578234,
|
|
|
|
toggle = "essences",
|
|
|
|
handler = function ()
|
|
applyBuff( "conquerors_banner" )
|
|
if conduit.veterans_repute.enabled then
|
|
applyBuff( "veterans_repute" )
|
|
end
|
|
if soulbind.kevins_oozeling.enabled then applyBuff( "kevins_oozeling" ) end
|
|
end,
|
|
|
|
auras = {
|
|
conquerors_banner = {
|
|
id = 324143,
|
|
duration = 20,
|
|
max_stack = 1
|
|
},
|
|
-- Conduit
|
|
veterans_repute = {
|
|
id = 339267,
|
|
duration = 30,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
},
|
|
|
|
-- Warrior - Night Fae - 325886 - ancient_aftershock (Ancient Aftershock)
|
|
ancient_aftershock = {
|
|
id = 325886,
|
|
cast = 0,
|
|
cooldown = function () return 90 - conduit.destructive_reverberations.mod * 0.001 end,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
texture = 3636851,
|
|
|
|
toggle = "essences",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "ancient_aftershock" )
|
|
-- Rage gain will be reactive, can't tell what is going to get hit.
|
|
end,
|
|
|
|
auras = {
|
|
ancient_aftershock = {
|
|
id = 325886,
|
|
duration = 1,
|
|
max_stack = 1,
|
|
},
|
|
}
|
|
},
|
|
|
|
-- Warrior - Venthyr - 317320 - condemn (Condemn)
|
|
condemn = {
|
|
id = function () return talent.massacre.enabled and 330325 or 317485 end,
|
|
known = 317349,
|
|
cast = 0,
|
|
cooldown = function () return state.spec.fury and ( 4.5 * haste ) or 0 end,
|
|
hasteCD = true,
|
|
gcd = "spell",
|
|
|
|
rangeSpell = function () return class.abilities.execute and class.abilities.execute.id end,
|
|
|
|
spend = function ()
|
|
if state.spec.fury then return -20 end
|
|
return buff.sudden_death.up and 0 or 20
|
|
end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 3565727,
|
|
|
|
-- toggle = "essences", -- no need to toggle.
|
|
|
|
usable = function ()
|
|
if buff.sudden_death.up then return true end
|
|
if cycle_for_condemn then return true end
|
|
return target.health_pct < ( talent.massacre.enabled and 35 or 20 ) or target.health_pct > 80, "requires > 80% or < " .. ( talent.massacre.enabled and 35 or 20 ) .. "% health"
|
|
end,
|
|
|
|
cycle = "condemn_ineligible",
|
|
|
|
indicator = function () if cycle_for_condemn then return "cycle" end end,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "condemned" )
|
|
|
|
if not state.spec.fury and buff.sudden_death.down then
|
|
local extra = min( 20, rage.current )
|
|
|
|
if extra > 0 then spend( extra, "rage" ) end
|
|
gain( 4 + floor( 0.2 * extra ), "rage" )
|
|
end
|
|
|
|
if legendary.sinful_surge.enabled then
|
|
if state.spec.protection and buff.last_stand.up then buff.last_stand.expires = buff.last_stand.expires + 3
|
|
elseif state.spec.arms and debuff.colossus_smash.up then debuff.colossus_smash.expires = debuff.colossus_smash.expires + 1.5
|
|
elseif state.spec.fury and buff.recklessness.up then buff.recklessness.expires = buff.recklessness.expires + 1.5 end
|
|
end
|
|
|
|
if legendary.exploiter.enabled then applyDebuff( "target", "exploiter", nil, min( 2, debuff.exploiter.stack + 1 ) ) end
|
|
|
|
removeBuff( "sudden_death" )
|
|
|
|
if conduit.ashen_juggernaut.enabled then addStack( "ashen_juggernaut", nil, 1 ) end
|
|
end,
|
|
|
|
auras = {
|
|
condemned = {
|
|
id = 317491,
|
|
duration = 10,
|
|
max_stack = 1,
|
|
},
|
|
-- Target Swapping
|
|
condemn_ineligible = {
|
|
duration = 3600,
|
|
max_stack = 1,
|
|
generate = function( t, auraType )
|
|
if buff.sudden_death.up or not covenant.venthyr or ( target.health_pct > ( talent.massacre.enabled and 35 or 20 ) and target.health_pct < 80 ) then
|
|
t.count = 1
|
|
t.expires = query_time + 3600
|
|
t.applied = query_time
|
|
t.duration = 3600
|
|
t.caster = "player"
|
|
return
|
|
end
|
|
t.count = 0
|
|
t.expires = 0
|
|
t.applied = 0
|
|
t.caster = "nobody"
|
|
end
|
|
}
|
|
},
|
|
|
|
copy = { 317485, 330325, 317349, 330334 }
|
|
}
|
|
} )
|
|
|
|
|
|
--[[ spec:RegisterSetting( "heroic_charge", false, {
|
|
name = "Use Heroic Charge Combo",
|
|
desc = "If checked, the default priority will check |cFFFFD100settings.heroic_charge|r to determine whether to use Heroic Leap + Charge together.\n\n" ..
|
|
"This is generally a DPS increase but the erratic movement can be disruptive to smooth gameplay.",
|
|
type = "toggle",
|
|
width = "full",
|
|
} ) ]]
|
|
|
|
|
|
spec:RegisterOptions( {
|
|
enabled = true,
|
|
|
|
aoe = 2,
|
|
|
|
nameplates = true,
|
|
nameplateRange = 8,
|
|
|
|
damage = true,
|
|
damageDots = false,
|
|
damageExpiration = 8,
|
|
|
|
potion = "spectral_strength",
|
|
|
|
package = "Arms",
|
|
} )
|
|
|
|
|
|
spec:RegisterPack( "Arms", 20220723, [[Hekili:nRvBpUnUX)plloaNDVUrRLFyZdDTbsdkAZI)nVO(kU(klrlrBRBLL8rrLnlGH(S3HKIsKuKs2x2I)9fxUyPHdhoCMFZm)uw7V(xwVkgrXR)6KXtMm(DtM6nzQV)8pSEf9LJ41RoIIEcTd(lzOdWF(jYHc2dFjnhfZwCrEjjcEXEk9yXhV7UDj09LB8IYpCxrYHYuenjplIG2sz)o6U1R2uMKs)s26n235zRxHkP7ZjRxTQrbFMPaytsIJXIvIlIewtv4VIiKKCs1JpwM(sv4KP3c)bOZQhRE8Z7rz7WfFS6X3wf(VoY2WQWTGWHFWBYFUkefhxfsrKDyAvyXZOJhtY2vlXF974Osk(UpNNfJpK5j0rbOG)XQQWd5e4Vfxs4l4VJJOjrvHFko(TFofJ(g2B9Q0KcAb3jbYKIde7d8GVY974m0MuC86)Y6vrKekMKGwVIGpGsYGt1dlQc3ffdEJiMhG9MS41uWD5CTBt2TNg0OHLvH(Zg3QGO8SFVetYjfbBqzzyctBtzAtkb6BiWgv1oiXmvjiGi7WMImxvKNrKnem6PosDVQur5P5ffLfbfhqf7nK8DAgvwucoJgaraysX(8ONmK(9QsxCeJib5BHJyH4jAY(bNoVO9SBhWTb(9jT6l)ByYX8Nfol)XUV3kZWquZoShCnXdkc2KM)SxTWvHNovf2k0geLMItZjX6sSPC7wVM90RGcPFWnPUnbHEuuAqbLK8eMBxUJN4kSOKL3eeJr09EWDtevlQGfDZvJ7qRbvdwKSWvZu3Eji4XlgVnjkHYdqNnVkCu9Xg0BC6lbrO0dEX5pNPCP(uzAAXX0ekT(Iyw)wQPQ4BcBZH8QQWPkjfBsrawcnNCGRxTizfTyeg5Rfl3gJyiLwCS(TMHKV)mae4OnC4WQWFUkCS30UGd(UdWHmJ00AmOcVN3NqsFojlwGtOepWrV4anUJ2HdcKs6Tft(wED2glEwpwUVnC2WImPnYO4zmMbmx78kmcpAwh3QDNlCfdQFadh2YRLHkGrmFSWqJXCdrh1YR8O4TxPMA7i))gLW5uelAJYIW2IktBlj0CjWbJmcsMOkXXYdhWPgs4oXdQK41ejbOjJ5Nu7Nk1ciVVgwcEpFfgLyGyYjZvmQC()xw0WQL4YtQMsMNhhSTK8stTLlqtQw)9kkfQDGjpb3lnLISxgippLfD5PLUQPvFV564jZvWtqKiuguQpNaPK0MIzxWbObVQFtPDltz3jfb)wz8Ud17PB4KHD)Btiy(vq)1lhwrqHBazLawoGGMoq9ZxjFXg0owwn82ONkSwAu0hBrecAdcKClGOIjz1QClwjl1Pi2kvku7oa6mLBa7XbGJSaABHSHDgB1BpY0u8ukBzboaEdRNB96fUZV6fMxIV14oBl)PhIpxK3xdxw31NDWmdS52YO9v5aUDlqreDGxHr7ThJsHgmogrfvRBSfBVDsnaDeueodbAg(F09VqCPqgMMCjVa16caq7G6MxmFSS1OvSJwe7CPGqdH0bIFeW6Zx0TFGimqTzi3qneusCaMzVEWyifnvtgOq9LAm7rrTnJOyiN1I1NCPPtf5A)gyj5KxciLD6Hx0jIuWKdhH6ISWK6LOlnSPhjyyOrOCCNIHIs0bqR)L0olt6QnxK7E30kJ2DMOZTIQZBPfY8m71Cv7U4D1H2ATBiB6b8hpLIlkYG)JhBCJ6DgGTMgWKt0XB91LE3SUbjSyAkPy0KdSkybXj46CmfqDXiIwkmR4sfzng9Kd45WWd)w5UDmW0sk)mjpSDEPAlgG1wxeaATkHAryu2tY0dr6B99clOWs5EPPkdE(FitvBKb7tBFoZkSO1uUM3FAnUB7W5AiVn1dC1m1dnTSFMks59gk5gvOzTqnMxrzmx5mnAajozxq0BrBqyp0l4RHumi)c(AigdqWqNHF7jTODMHIKDzykVPai3fSgCCaRx1cBdM0oanV97HgqzKc(YSXk0m0DCELxQobDn4JTW1EAe5SiuXDJcd3htCofmt8XGNZlZG6Ng5HkU(MrA7PASBTjZL0zWPhAEStIZc5iT1xv4VFmnNT76c0OafkIu7QUl5polSBjIZv4JL7Chx49G(iNhAMYiHDPUX9ifUPU5ALPTKD8Pn0n0NY2sWRukUAAZzugstRcQELYjAGhU4ZPd1cD90w8ytmhvOB1NURIk6BRFQILhT7h)hIeTxPgHoNAh(2AGy2zHRp)SH1)JNBBdQ4)YCqBjoSV6z27eyqEFn5ntoIXaqN8WP2MgeofzAvFqrUjqwZLBYJzpm9Pc91qYP2mY1xzgEg31LQpuXq0wm0s2U90UNSZTi1W285nk4frV(fYQ8qOA6dQ1YLQMuCejqbfmHeFXUPWczPTzS(uwV6x)0)8RF5R)Tpwfwf(l7bGjyKpW2Q)wAVrBqY3a4Y4FVmHWaPlYpasd9gNFarzpis8n78QE8)ljdEL)yqPFopd2E(7FtlS))g0enx)rYBt4vx7)9BETvZe)Fq1u94aUQ676l0jn9h0SQvZ9VoQ5d)GQP6XVW9jSfdTOiIoRc5Frv41m6cY3MKcr8)0pvfA8DGzpYY3cM942Vhm7xVgFtyPEo7VlS0uQvfSxBy(bmB4jg)hSFVdGk9GvffHpsHJwwE2BH2Ppa94iDgWtZZsFbux9V9Ayq5pT4ovot6UHy4Eb8oSHVG)KfbIyKYabIGwHknjPSRJwvVq0lFZVHnq89h0EcN8)Bt2UqHDHfJh1ln9lF)PtSpUWiTpSWdqBPkAU9dcW0UZjDuxrdB)UxH0cUxDH603ZwC)mpV03B(iwJypa9xQOhdo5DBfmvpAGp6GIEBiN)C9e6KWFURsJg9xnJxYM9TmYQw4KFD3lXn152wJ2EBwKMDOCmI5s)rx3db5l9NF6KDIXVrDhn5vvCeQb3VvWI7cFMD4Gt8rDOV(HP8T28PtgF6Kj)3Dx8Y3ZeZKZB1hvpgZWhcy0eTdqxMSpDYPZDy1R1RGQ4Q0nR(8oSlZG8KWI1h0fktg15LmtXCaiRc1Y7QWuBdp6jGAH)iDiXRziglFhCzY)lZhpYgJV3yZceJp1bLTjSqHqniUWXbLDlFR2uNI7rxKFoQxIpFaSKr9s4PYLUIHitf()DdPol26RG4kEeE9oW86JU(kNKGoAGPHFywd2rFlUl7Ppm7MrDVIx6pXMv3UC7baQwM1GSoJ7AtkZXCVWGTZG9trIIKWkORGtNCv9IxeE5mirWXSu1VqNJlRPyndkXl)lyXCHv)Sy0Z(lL4yuBwSQnvQveLx51X6zrIa(HD(iRpSgCqUyYi7CpUys9c04C8sVpnVQSXJSTWivEPKk6HzZTjRoCRvcVeXm8AIxzNFqz)A9F5FbN(laCtTWeufDH9d)91fe6WfQ6A7VMLqG2QfdHl5BUuByiYD1o(r9BBYj6lYTJH2dIJqc3OnI33gAy(MoW7Ih3jtZfzoaOJ7C4rxzLKSo2GzDejfy)8yVPJCswNvFR5t1WRCZUL5YKrO9CYhCjD)cs95KDA4DI9A(ApkPlADfUWwHzhYAlrHTuTrox6pBS71lYJC)(oHyMcylBQRrApVQJX0tUIPSUZAmLCOQEMY3j9XzPiB)RE2EbQL9THsW3Zj4ZCTxsGBhxOniAzHULZMpeuTP(oNAy8Qat7jG06WmoVspZBXEIVnY2urV65gB42J6jJrkKcQMR)z76EAZzUF1ehWU9F7X(3UlZIUAatQEgV5JD3YQwdkA5m3W)gsrR)67eFlW1)N]] )
|
|
|
|
|
|
end
|
|
|