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.
2068 lines
85 KiB
2068 lines
85 KiB
-- WarriorProtection.lua
|
|
-- August 2025
|
|
-- Patch 11.2
|
|
|
|
if UnitClassBase( "player" ) ~= "WARRIOR" then return end
|
|
|
|
local addon, ns = ...
|
|
local Hekili = _G[ addon ]
|
|
local class, state = Hekili.Class, Hekili.State
|
|
local spec = Hekili:NewSpecialization( 73 )
|
|
|
|
---- Local function declarations for increased performance
|
|
-- Strings
|
|
local strformat = string.format
|
|
-- Tables
|
|
local insert, remove, sort, wipe = table.insert, table.remove, table.sort, table.wipe
|
|
-- Math
|
|
local abs, ceil, floor, max, sqrt = math.abs, math.ceil, math.floor, math.max, math.sqrt
|
|
|
|
-- Common WoW APIs, comment out unneeded per-spec
|
|
-- local GetSpellCastCount = C_Spell.GetSpellCastCount
|
|
-- local GetSpellInfo = C_Spell.GetSpellInfo
|
|
-- local GetSpellInfo = ns.GetUnpackedSpellInfo
|
|
-- local GetPlayerAuraBySpellID = C_UnitAuras.GetPlayerAuraBySpellID
|
|
-- local FindUnitBuffByID, FindUnitDebuffByID = ns.FindUnitBuffByID, ns.FindUnitDebuffByID
|
|
-- local IsSpellOverlayed = C_SpellActivationOverlay.IsSpellOverlayed
|
|
-- local IsSpellKnownOrOverridesKnown = C_SpellBook.IsSpellInSpellBook
|
|
-- local IsActiveSpell = ns.IsActiveSpell
|
|
|
|
-- Specialization-specific local functions (if any)
|
|
local FindPlayerAuraByID = ns.FindPlayerAuraByID
|
|
local LSR = LibStub("SpellRange-1.0")
|
|
local base_rage_gen = 2
|
|
|
|
|
|
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.swings.mainhand_speed ) * state.swings.mainhand_speed )
|
|
end,
|
|
|
|
interval = "mainhand_speed",
|
|
|
|
stop = function () return state.time == 0 or state.swings.mainhand == 0 end,
|
|
value = function ()
|
|
return ( base_rage_gen * ( state.talent.war_machine.enabled and 1.5 or 1 ) ) + ( state.talent.instigate.enabled and 2 or 0 ) -- 2 Rage for instigate
|
|
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,
|
|
},
|
|
|
|
ravager = {
|
|
aura = "ravager",
|
|
|
|
last = function ()
|
|
local app = state.buff.ravager.applied
|
|
local t = state.query_time
|
|
|
|
return app + floor( ( t - app ) / state.haste ) * state.haste
|
|
end,
|
|
|
|
interval = function () return state.haste end,
|
|
|
|
value = function () return state.talent.storm_of_steel.enabled and 20 or 10 end,
|
|
},
|
|
} )
|
|
|
|
-- Talents
|
|
spec:RegisterTalents( {
|
|
|
|
-- Warrior
|
|
armored_to_the_teeth = { 90366, 384124, 2 }, -- Gain Strength equal to $s1% of your Armor
|
|
avatar = { 90365, 107574, 1 }, -- Transform into a colossus for $s1 sec, causing you to deal $s2% increased damage and removing all roots and snares. Generates $s3 Rage
|
|
barbaric_training = { 90340, 383082, 1 }, -- Revenge deals $s1% increased damage. Thunder Clap deals $s2% increased damage
|
|
battle_stance = { 90261, 386164, 1 }, -- A balanced combat state that increases the critical strike chance of your abilities by $s1% and reduces the duration of movement impairing effects by $s2%. Lasts until canceled
|
|
berserker_shout = { 90348, 384100, 1 }, -- Go berserk, removing and granting immunity to Fear, Sap, and Incapacitate effects for $s1 sec. Also remove fear effects from group members within $s2 yds
|
|
bitter_immunity = { 90356, 383762, 1 }, -- Restores $s1% health instantly and removes all diseases, poisons, and curses affecting you
|
|
bounding_stride = { 90355, 202163, 1 }, -- Reduces the cooldown of Heroic Leap by $s1 sec and Heroic Leap also increases your movement speed by $s2% for $s3 sec
|
|
cacophonous_roar = { 90383, 382954, 1 }, -- Intimidating Shout can withstand $s1% more damage before breaking
|
|
champions_might = { 90323, 386284, 1 }, -- The duration of Champion's Spear is increased by $s1 sec. You deal $s2% increased critical strike damage to targets chained to your Spear
|
|
champions_spear = { 90380, 376079, 1 }, -- Throw a spear at the target location, dealing $s$s2 Physical damage instantly and an additional $s3 damage over $s4 sec. Deals reduced damage beyond $s5 targets. Enemies hit are chained to the spear's location for the duration. Generates $s6 Rage
|
|
concussive_blows = { 90354, 383115, 1 }, -- Cooldown of Pummel reduced by $s1 sec. Successfully interrupting an enemy increases the damage you deal to them by $s2% for $s3 sec
|
|
crackling_thunder = { 95959, 203201, 1 }, -- Thunder Clap's radius is increased by $s1% and it reduces affected target's movement speed by an additional $s2%
|
|
cruel_strikes = { 90381, 392777, 2 }, -- Critical strike chance increased by $s1% and critical strike damage of Execute increased by $s2%
|
|
crushing_force = { 90347, 382764, 2 }, -- Shield Slam deals an additional $s1% damage and deals $s2% increased critical strike damage
|
|
defensive_stance = { 90330, 386208, 1 }, -- A defensive combat state that reduces all damage you take by $s1% and all magic damage you take by an additional $s2%. Lasts until canceled
|
|
double_time = { 90382, 103827, 1 }, -- Charge gains $s1 additional charge and its cooldown is reduced by $s2 sec
|
|
fast_footwork = { 90344, 382260, 1 }, -- Movement speed increased by $s1%
|
|
frothing_berserker = { 90352, 392792, 1 }, -- Revenge has a $s1% chance to immediately refund $s2% of the Rage spent
|
|
heroic_leap = { 90346, 6544, 1 }, -- Leap through the air toward a target location, slamming down with destructive force to deal $s$s2 Physical damage to all enemies within $s3 yards and resetting the remaining cooldown on Taunt
|
|
honed_reflexes = { 95956, 391271, 1 }, -- Cooldown of Shield Wall, Pummel, Intervene, Spell Reflection, and Storm Bolt reduced by $s1%
|
|
immovable_object = { 90364, 394307, 1 }, -- Activating Avatar or Shield Wall grants $s1 sec of the other
|
|
impending_victory = { 90326, 202168, 1 }, -- Instantly attack the target, causing $s1 damage and healing you for $s2% of your maximum health. Killing an enemy that yields experience or honor resets the cooldown of Impending Victory and makes it cost no Rage
|
|
intervene = { 90329, 3411, 1 }, -- Run at high speed toward an ally, intercepting all melee and ranged attacks against them for $s1 sec while they remain within $s2 yds
|
|
intimidating_shout = { 90384, 5246, 1 }, -- Causes the targeted enemy to cower in fear and up to $s1 additional enemies within $s2 yards to flee. Targets are disoriented for $s3 sec
|
|
leeching_strikes = { 90371, 382258, 1 }, -- Leech increased by $s1%
|
|
menace = { 90383, 275338, 1 }, -- Intimidating Shout will knock back all nearby enemies except your primary target and cause them all to cower in fear for $s1 sec instead of fleeing
|
|
onehanded_weapon_specialization = { 90324, 382895, 2 }, -- While wielding one-handed weapons your damage is increased by $s1% and Leech increased by $s2%
|
|
overwhelming_rage = { 90378, 382767, 1 }, -- Maximum Rage increased by $s1
|
|
pain_and_gain = { 90353, 382549, 1 }, -- When you take any damage, heal for $s1% of your maximum health. This can only occur once every $s2 sec
|
|
piercing_challenge = { 90379, 382948, 1 }, -- Champion's Spear's damage increased by $s1% and its Rage generation is increased by $s2%
|
|
piercing_howl = { 90348, 12323, 1 }, -- Snares all enemies within $s1 yards, reducing their movement speed by $s2% for $s3 sec
|
|
rallying_cry = { 90331, 97462, 1 }, -- Lets loose a rallying cry, granting all party or raid members within $s1 yards $s2% temporary and maximum health for $s3 sec
|
|
reinforced_plates = { 90368, 382939, 2 }, -- Stamina increased by $s1% and Armor increased by $s2%
|
|
rumbling_earth = { 90374, 275339, 1 }, -- Shockwave's range increased by $s1 yards and when it strikes at least $s2 targets its cooldown is reduced by $s3 sec
|
|
second_wind = { 90332, 29838, 1 }, -- Restores $s1% health every $s2 sec when you have not taken damage for $s3 sec. Restores $s4% health every $s5 sec while you are below $s6% health. The amount restored increases the closer you are to death
|
|
seismic_reverberation = { 90354, 382956, 1 }, -- If Whirlwind or Revenge hits $s1 or more enemies it hits them $s2 additional time for $s3% damage
|
|
shattering_throw = { 90351, 64382, 1 }, -- Hurl your weapon at the enemy, removing any magical immunities and causing $s$s2 Physical damage, ignoring armor. Deals up to $s3% increased damage to absorb shields
|
|
shockwave = { 90375, 46968, 1 }, -- Sends a wave of force in a frontal cone, causing $s1 damage and stunning all enemies within $s2 yards for $s3 sec
|
|
sidearm = { 90340, 384404, 1 }, -- Your auto-attacks have a $s2% chance to hurl weapons at your target and $s3 other enemy in front of you, dealing $s$s4 Physical damage
|
|
spell_reflection = { 90385, 23920, 1 }, -- Raise your shield, reflecting the first spell cast on you and reducing magic damage you take by $s1% for $s2 sec
|
|
storm_bolt = { 90337, 107570, 1 }, -- Hurls your weapon at an enemy, causing $s$s2 Physical damage and stunning for $s3 sec
|
|
thunder_clap = { 90343, 6343, 1 }, -- Blasts all enemies within $s2 yards for $s$s3 Physical damage and reduces their movement speed by $s4% for $s5 sec. Deals reduced damage beyond $s6 targets. Generates $s7 Rage. If you have Rend, Thunder Clap affects $s8 nearby targets with Rend
|
|
thunderous_roar = { 90359, 384318, 1 }, -- Roar explosively, dealing $s$s3 Physical damage to enemies within $s4 yds and cause them to bleed for $s$s5 physical damage over $s6 sec. Deals reduced damage beyond $s7 targets
|
|
thunderous_words = { 90358, 384969, 1 }, -- Increases the duration of Thunderous Roar's Bleed effect by $s1 sec and Thunderous Roar's Bleed effect causes enemies to take $s2% increased damage from all your bleeds
|
|
unstoppable_force = { 90364, 275336, 1 }, -- Avatar increases the damage of Thunder Clap and Shockwave by $s1% and reduces the cooldown of Thunder Clap by $s2%
|
|
uproar = { 90357, 391572, 1 }, -- Thunderous Roar's cooldown reduced by $s1 sec
|
|
war_machine = { 90328, 262231, 1 }, -- Your auto-attacks generate $s1% more Rage. Killing an enemy instantly generates $s2 Rage and increases your movement speed by $s3% for $s4 sec
|
|
wild_strikes = { 90360, 382946, 2 }, -- Haste increased by $s1% and your auto-attack critical strikes increase your auto-attack speed by $s2% for $s3 sec
|
|
wrecking_throw = { 90351, 384110, 1 }, -- Hurl your weapon at the enemy, causing $s$s2 Physical damage, ignoring armor. Deals up to $s3% increased damage to absorb shields
|
|
|
|
-- Protection
|
|
anger_management = { 90433, 152278, 1 }, -- Every $s1 Rage you spend reduces the remaining cooldown on Avatar and Shield Wall by $s2 sec
|
|
armor_specialization = { 90306, 1234769, 1 }, -- Armor increased by $s1%
|
|
battlescarred_veteran = { 90435, 386394, 1 }, -- When your health is brought below $s1%, you take $s2% less damage for $s3 sec and healing you receive is increased by $s4%. Cannot occur more than once every $s5 min
|
|
best_served_cold = { 90296, 202560, 1 }, -- Your dodges and parries make your Revenge cost no Rage $s1% more frequently and increase the damage your free Revenges deal by $s2%. Revenge increases the damage of your next Thunder Clap by $s3%
|
|
bloodborne = { 90264, 385704, 1 }, -- Your Deep Wounds and Rend deal $s1% increased damage
|
|
bloodsurge = { 90300, 384361, 1 }, -- Damage from Deep Wounds has a chance to generate $s1 Rage
|
|
bolster = { 90320, 280001, 1 }, -- Last Stand's cooldown is reduced by $s1 sec and it grants you the Shield Block effect for its duration
|
|
booming_voice = { 90314, 202743, 1 }, -- Demoralizing Shout also generates $s1 Rage and increases damage you deal to affected targets by $s2%
|
|
brace_for_impact = { 90304, 386030, 1 }, -- Using Shield Slam increases the damage of Shield Slam by $s1% and the block value of your shield by $s2% for $s3 sec. Stacking up to $s4 times
|
|
brutal_vitality = { 90451, 384036, 1 }, -- $s1% of damage you deal adds to your active Ignore Pain or the next Ignore Pain you activate. Your next Ignore Pain can be increased by up to $s2
|
|
defenders_aegis = { 90318, 397103, 1 }, -- Shield Wall gains $s1 additional charge and its cooldown is reduced by $s2 sec
|
|
demoralizing_shout = { 90305, 1160, 1 }, -- Demoralizes all enemies within $s1 yards, reducing the damage they deal to you by $s2% for $s3 sec. Generates $s4 Rage
|
|
devastator = { 90297, 236279, 1 }, -- Your auto-attacks deal an additional $s$s2 Physical damage and have a $s3% chance to reset the remaining cooldown on Shield Slam
|
|
disrupting_shout = { 107579, 386071, 1 }, -- Taunts all enemies within $s1 yds to attack you for $s2 sec, interrupts all spellcasting within $s3 yds and prevents any spell in that school from being cast for $s4 sec
|
|
enduring_alacrity = { 107577, 384063, 1 }, -- Increases Stamina by $s1% and your Haste by $s2%
|
|
enduring_defenses = { 90311, 386027, 2 }, -- Shield Block lasts $s1 sec longer
|
|
fight_through_the_flames = { 90299, 452494, 1 }, -- Defensive Stance additionally reduces magic damage you take by $s1%
|
|
focused_vigor = { 107578, 384067, 1 }, -- Increases Strength by $s1% and your critical strike chance by $s2%
|
|
fueled_by_violence = { 90451, 383103, 1 }, -- You are healed for $s1% of the damage dealt by Deep Wounds
|
|
heavy_handed = { 107575, 1235088, 1 }, -- Execute hits up to $s1 additional targets for $s2% damage
|
|
heavy_repercussions = { 90312, 203177, 1 }, -- Shield Slam generates $s1 more Rage and extends the duration of Shield Block by $s2 sec
|
|
hunker_down = { 90450, 1235022, 1 }, -- Damage you take from area of effect attacks is reduced by $s1%. Spell Reflection reduces magic damage taken by an additional $s2%
|
|
ignore_pain = { 90295, 190456, 1 }, -- Fight through the pain, ignoring $s2% of damage taken until $s3 damage has been prevented. Repeated uses of Ignore Pain accumulate, up to $s$s4 total damage prevented
|
|
impenetrable_wall = { 90318, 384072, 1 }, -- Shield Slam reduces the remaining cooldown of Shield Wall by $s1 sec
|
|
indomitable = { 90434, 202095, 1 }, -- Your maximum health is increased by $s1% and every $s2 Rage you spend heals you for $s3% of your maximum health
|
|
instigate = { 90301, 394311, 1 }, -- Devastate deals $s1% increased damage and generates $s2 Rage. Devastator deals $s3% increased damage and generates $s4 Rage
|
|
into_the_fray = { 90312, 202603, 1 }, -- You gain $s1% Haste for each enemy or ally within $s2 yards, up to $s3% Haste
|
|
last_stand = { 90309, 12975, 1 }, -- Increases maximum health by $s1% for $s2 sec and instantly heals you for that amount
|
|
massacre = { 107576, 281001, 1 }, -- Execute is usable on targets below $s1% health
|
|
punish = { 90448, 275334, 1 }, -- Shield Slam deals $s1% increased damage and reduces enemies' damage against you by $s2% for $s3 sec. Multiple punishments may overlap
|
|
ravager = { 90432, 228920, 1 }, -- Throws a whirling weapon at the target location that chases nearby enemies, inflicting $s$s2 Physical damage to all enemies over $s3 sec. Deals reduced damage beyond $s4 targets. Generates $s5 Rage each time it deals damage
|
|
red_right_hand = { 90310, 1235038, 1 }, -- Execute damage increased by $s1%
|
|
rend = { 90302, 394062, 1 }, -- Wounds the target, causing $s$s3 Physical damage instantly and an additional $s$s4 Bleed damage over $s5 sec. Thunder Clap affects $s6 nearby targets with Rend
|
|
revenge = { 90298, 6572, 1 }, -- Swing in a wide arc, dealing $s$s2 Physical damage to all enemies in front of you. Deals reduced damage beyond $s3 targets. Your successful dodges and parries have a chance to make your next Revenge cost no Rage
|
|
shield_charge = { 90317, 385952, 1 }, -- Charge to an enemy with your shield, granting you Shield Block and dealing $s$s3 Physical damage to it and $s$s4 Physical damage to all enemies within $s5 yards. Also stuns the primary target for $s6 sec. Generates $s7 Rage
|
|
shield_specialization = { 90315, 386011, 1 }, -- Increases Block chance by $s1% and your Block value by $s2%
|
|
shield_wall = { 90319, 871, 1 }, -- Reduces all damage you take by $s1% for $s2 sec
|
|
spellbreaker = { 90450, 1235023, 1 }, -- You have a $s1% chance to disrupt magic damage dealt to you, reducing the damage it deals by $s2%
|
|
strategist = { 90303, 384041, 1 }, -- Devastate, Thunder Clap, Revenge, and Execute have a $s1% chance to reset the remaining cooldown on Shield Slam
|
|
sudden_death = { 90264, 29725, 1 }, -- Your attacks have a chance to make your next Execute cost no Rage, be usable on any target regardless of their health, and deal damage as if you spent $s1 Rage
|
|
thunderlord = { 90308, 385840, 1 }, -- Increases the radius of Demoralizing Shout by $s1 yards. Each enemy hit by Thunder Clap reduces the remaining cooldown on Demoralizing Shout by $s2 sec, up to $s3 sec
|
|
tough_as_nails = { 90313, 385888, 1 }, -- Blocking an attack deals $s$s2 Physical damage to the attacker. Critical blocks deal double damage. Generates high threat
|
|
unnerving_focus = { 90320, 384042, 1 }, -- Last Stand increases your Rage generation by $s1%
|
|
unyielding_stance = { 90449, 1235047, 1 }, -- Defensive Stance reduces damage taken by an additional $s1%
|
|
violent_outburst = { 90265, 386477, 1 }, -- Every $s1 rage you spend triggers a Violent Outburst, causing your next Shield Slam or Thunder Clap to deal $s2% increased damage, generate $s3% more Rage and grant Ignore Pain
|
|
whirling_blade = { 90432, 1235113, 1 }, -- Your attacks have a chance to target a nearby enemy with Ravager for $s1 sec
|
|
|
|
-- Colossus
|
|
arterial_bleed = { 94799, 440995, 1 }, -- Colossal Might increases the damage of your Rend and Deep Wounds by $s1% per stack
|
|
boneshaker = { 94789, 429639, 1 }, -- Shockwave's stun duration is increased by $s1 sec and reduces the movement speed of affected enemies by $s2% for $s3 sec after the stun ends
|
|
colossal_might = { 94819, 429634, 1 }, -- Colossal Might increases damage dealt by your next Demolish by $s1%, stacking up to $s2 times. Shield Slam grants a stack of Colossal Might and Revenge grants a stack of Colossal Might when it strikes $s3 or more targets
|
|
demolish = { 94818, 436358, 1 }, -- Unleash a series of precise and powerful strikes against your target, dealing $s1 damage to it, and $s2 damage to enemies within $s3 yds of it. Deals reduced damage beyond $s4 targets. While channeling Demolish, you take $s5% less damage and are immune to stuns, knockbacks, and forced movement effects. You can block, parry, dodge, and use certain defensive abilities while channeling Demolish
|
|
dominance_of_the_colossus = { 94793, 429636, 1 }, -- Colossal Might now stacks up to $s1 times. If you would gain a stack of Colossal Might and are at max stacks, the cooldown of Demolish is reduced by $s2 sec. Enemies affected by Demolish take up to $s3% more damage from you and deal up to $s4% less damage to you for $s5 sec based on the number of stacks of Colossal Might consumed by Demolish
|
|
earthquaker = { 94789, 440992, 1 }, -- Shockwave also knocks enemies into the air and its cooldown is reduced by $s1 sec
|
|
martial_expert = { 94812, 429638, 1 }, -- Critical strike damage of your abilities is increased by $s1% and the amount of damage blocked by your critical blocks is increased by $s2%
|
|
mountain_of_muscle_and_scars = { 94806, 429642, 1 }, -- You deal $s1% more damage and take $s2% less damage. Size increased by $s3%
|
|
no_stranger_to_pain = { 94815, 429644, 1 }, -- Damage prevented by each use of Ignore Pain is increased by $s1%
|
|
one_against_many = { 94799, 429637, 1 }, -- Shockwave, Revenge, and Whirlwind deal $s1% more damage per target affected up to $s2
|
|
practiced_strikes = { 94796, 429647, 1 }, -- Shield Slam and Revenge damage increased by $s1%. Shield Slam generates an additional $s2 Rage
|
|
precise_might = { 94794, 431548, 1 }, -- Shield Slam critical strikes grant an additional stack of Colossal Might
|
|
tide_of_battle = { 94811, 429641, 1 }, -- Colossal Might increases the damage of your Revenge by $s1% per stack
|
|
veteran_vitality = { 94815, 440993, 1 }, -- When your health is brought below $s1%, you gain a Second Wind, healing you for $s2% of your max health over $s3 sec. This effect cannot occur more than once every $s4 sec
|
|
|
|
-- Mountain Thane
|
|
avatar_of_the_storm = { 94805, 437134, 1 }, -- Casting Avatar grants you $s1 charges of Thunder Blast and resets the cooldown of Thunder Clap. While Avatar is not active, Lightning Strikes have a $s2% chance to grant you Avatar for $s3 secs. Thunder Blast Your next Thunder Clap becomes a Thunder Blast that deals Stormstrike damage
|
|
burst_of_power = { 94807, 437118, 1 }, -- Lightning Strikes have a $s1% chance to make your next $s2 Shield Slams have no cooldown
|
|
crashing_thunder = { 94816, 436707, 1 }, -- Stormstrike or Nature damage your abilities deal is increased by $s2%$s$s3 Stormstrike damage ignores Armor. Thunder Clap damage increased by $s4%. Seismic Reverberations now affects Thunder Clap in addition to Whirlwind
|
|
flashing_skies = { 94797, 437079, 1 }, -- Thunder Blast calls down a Lightning Strike on an enemy it hits
|
|
gathering_clouds = { 94792, 436201, 1 }, -- Your attacks trigger Lightning Strikes $s1% more often
|
|
ground_current = { 94800, 436148, 1 }, -- Lightning Strikes also deal $s$s2 Nature damage to enemies near their target. Damage reduced beyond $s3 targets
|
|
keep_your_feet_on_the_ground = { 94798, 438590, 1 }, -- Physical damage taken reduced by $s1%. Thunder Blast reduces damage you take by $s2% for $s3 sec
|
|
lightning_strikes = { 94803, 434969, 1 }, -- Damaging enemies with Thunder Clap, Revenge, or Execute has a $s2% chance to also strike one with a lightning bolt, dealing $s$s3 Nature damage. Lightning Strikes occur $s4% more often during Avatar
|
|
snap_induction = { 94797, 456270, 1 }, -- Activating Demoralizing Shout grants a charge of Thunder Blast
|
|
steadfast_as_the_peaks = { 94798, 434970, 1 }, -- Stamina increased by $s1%. Impending Victory increases your maximum health by $s2% for $s3 sec. When this health increase expires, you heal for any amount of the original Impending Victory that healed you in excess of your full health
|
|
storm_bolts = { 94817, 436162, 1 }, -- Storm Bolt also hits $s1 additional nearby targets, stunning them for $s2 sec, but its cooldown is increased by $s3 sec
|
|
storm_shield = { 94817, 438597, 1 }, -- Intervening a target grants them a shield for $s1 sec that absorbs magic damage equal to $s2 times your Armor
|
|
strength_of_the_mountain = { 94808, 437068, 1 }, -- Shield Slam damage increased by $s1%. Demoralizing Shout reduces damage enemies deal to you by an additional $s2%
|
|
thorims_might = { 94792, 436152, 1 }, -- Lightning Strikes generate $s1 Rage. Revenge and Execute damage increased by $s2%
|
|
thunder_blast = { 94785, 435607, 1 }, -- Shield Slam and Bloodthirst have a $s1% chance to grant you Thunder Blast, stacking up to $s2 charges. Thunder Blast Your next Thunder Clap becomes a Thunder Blast that deals $s5% increased damage as Stormstrike and generates $s6 Rage
|
|
} )
|
|
|
|
-- PvP Talents
|
|
spec:RegisterPvpTalents( {
|
|
battlefield_commander = 5629, -- (424742) Your Shout abilities have additional effects. Battle Shout: Increases Stamina by $s3%. Piercing Howl: Radius increased by $s6% Berserker Shout: Range increased by $s9 yds. Intimidating Shout: Cooldown reduced by $s12 sec. Rallying Cry: Removes movement impairing effects and grants $s15% movement speed to allies. Thunderous Roar: Targets receive $s18% more damage from all sources while bleeding
|
|
berserker_roar = 5703, -- (1227751)
|
|
bodyguard = 168, -- (213871) Protect an ally, causing $s1% of all Physical damage they take to be transfered to you. When the target takes Physical damage, your Shield Slam cooldown has a $s2% chance to be reset. Bodyguard is cancelled if the target is further than $s3 yards from you. Lasts $s4 min. Only one target can be Bodyguarded at a time
|
|
demolition = 5374, -- (329033) Reduces the cooldown of your Shattering Throw or Wrecking Throw by $s1% and increases its damage to absorb shields by an additional $s2%
|
|
disarm = 24, -- (236077) Disarm the enemy's weapons and shield for $s1 sec. Disarmed creatures deal significantly reduced damage
|
|
dragon_charge = 831, -- (206572) Run at high speed at a distance in front of you. All enemies in your path will take $s$s2 Physical damage and be knocked back
|
|
morale_killer = 171, -- (199023) Reduces the cooldown of Demoralizing Shout by $s1 sec, and Demoralizing Shout now reduces the damage enemies deal to all targets, not just you
|
|
oppressor = 845, -- (205800) You focus the assault on this target, increasing their damage taken by $s1% for $s2 sec. Each unique player that attacks the target increases the damage taken by an additional $s3%, stacking up to $s4 times. Your melee attacks refresh the duration of Focused Assault
|
|
power_through_adversity = 5715, -- (1234791) Second Wind reduces damage taken by $s1% to $s2%, with larger attacks being reduced by more. While Shield Wall or Last Stand are active, healing reductions do not apply to you
|
|
rebound = 833, -- (213915) Spell Reflection reflects the next $s1 incoming spells cast on you and reflected spells deal $s2% extra damage to the attacker. Spell Reflection's cooldown is increased by $s3 sec
|
|
safeguard = 5626, -- (424654) Intervene now has $s1 charges and reduces the ally's damage taken by $s2% for $s3 sec. Intervene's cooldown is increased by $s4 sec
|
|
shield_bash = 173, -- (198912) When Shield Slam is used on targets that are casting, it reduces their damage done by $s1% for $s2 sec and the cooldown is instantly reset
|
|
storm_of_destruction = 5627, -- (236308) Bladestorm, Ravager, and Demolish now snare all targets you hit by $s1% for $s2 sec and decrease their healing taken by $s3% for $s4 sec
|
|
thunderstruck = 175, -- (199045) After casting Avatar, Shockwave, or Stormbolt, your next Thunder Clap roots all targets it damages for $s1 sec
|
|
} )
|
|
|
|
-- Auras
|
|
spec:RegisterAuras( {
|
|
avatar = {
|
|
id = 107574,
|
|
duration = 20,
|
|
max_stack = 1,
|
|
copy = 107574
|
|
},
|
|
battering_ram = {
|
|
id = 394313,
|
|
duration = 20,
|
|
max_stack = 1,
|
|
},
|
|
battle_stance = {
|
|
id = 386164,
|
|
duration = 3600,
|
|
max_stack = 1
|
|
},
|
|
battlescarred_veteran = {
|
|
id = 386397,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
berserker_rage = {
|
|
id = 18499,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
berserker_shout = {
|
|
id = 384100,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
best_served_cold = {
|
|
id = 1234772,
|
|
duration = 12,
|
|
max_stack = 1
|
|
},
|
|
bodyguard = {
|
|
id = 213871,
|
|
duration = 60,
|
|
tick_time = 1,
|
|
max_stack = 1
|
|
},
|
|
bounding_stride = {
|
|
id = 202164,
|
|
duration = 3,
|
|
max_stack = 1,
|
|
},
|
|
brace_for_impact = {
|
|
id = 386029,
|
|
duration = 16,
|
|
max_stack = 3
|
|
},
|
|
burst_of_power = {
|
|
id = 437121,
|
|
duration = 12,
|
|
max_stack = 2,
|
|
},
|
|
challenging_shout = {
|
|
id = 1161,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
charge = {
|
|
id = 105771,
|
|
duration = 1,
|
|
max_stack = 1,
|
|
},
|
|
colossal_might = {
|
|
id = 440989,
|
|
duration = 24,
|
|
max_stack = function() return 5 + ( talent.dominance_of_the_colossus.enabled and 5 or 10 ) end
|
|
},
|
|
concussive_blows = {
|
|
id = 383116,
|
|
duration = 10,
|
|
max_stack = 1
|
|
},
|
|
dance_of_death = {
|
|
id = 393966,
|
|
duration = 120,
|
|
max_stack = 1,
|
|
},
|
|
deep_wounds = {
|
|
id = 115767,
|
|
duration = 15,
|
|
tick_time = 3,
|
|
max_stack = 1
|
|
},
|
|
defensive_stance = {
|
|
id = 386208,
|
|
duration = 3600,
|
|
max_stack = 1
|
|
},
|
|
demoralizing_shout = {
|
|
id = 1160,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
disarm = {
|
|
id = 236077,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
disrupting_shout = {
|
|
id = 386071,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
dragon_charge = {
|
|
id = 206572,
|
|
duration = 1.2,
|
|
max_stack = 1
|
|
},
|
|
champions_spear = {
|
|
id = 376080,
|
|
duration = function() return 4 + ( talent.champions_might.enabled and 2 or 0 ) end,
|
|
max_stack = 1
|
|
},
|
|
champions_might = {
|
|
id = 386286,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
-- Target Swapping
|
|
execute_ineligible = {
|
|
duration = 3600,
|
|
max_stack = 1,
|
|
generate = function( t )
|
|
if buff.sudden_death.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
|
|
},
|
|
focused_assault = {
|
|
id = 206891,
|
|
duration = 6,
|
|
max_stack = 5
|
|
},
|
|
hamstring = {
|
|
id = 1715,
|
|
duration = 15,
|
|
max_stack = 1
|
|
},
|
|
ignore_pain = {
|
|
id = 190456,
|
|
duration = 12,
|
|
max_stack = 100
|
|
},
|
|
indelible_victory = {
|
|
id = 336642,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
intimidating_shout = {
|
|
id = function () return talent.menace.enabled and 316593 or 5246 end,
|
|
duration = function () return talent.menace.enabled and 15 or 8 end,
|
|
max_stack = 1
|
|
},
|
|
into_the_fray = {
|
|
id = 202602,
|
|
duration = 3600,
|
|
max_stack = 5
|
|
},
|
|
|
|
keep_your_feet_on_the_ground = {
|
|
id = 438591,
|
|
duration = 5,
|
|
max_stack = 1
|
|
},
|
|
last_stand = {
|
|
id = 12975,
|
|
duration = 15,
|
|
max_stack = 1
|
|
},
|
|
piercing_howl = {
|
|
id = 12323,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
punish = {
|
|
id = 275335,
|
|
duration = 9,
|
|
max_stack = 5
|
|
},
|
|
rallying_cry = {
|
|
id = 97463,
|
|
duration = 10,
|
|
max_stack = 1,
|
|
shared = "player",
|
|
},
|
|
ravager = {
|
|
id = 228920,
|
|
duration = function () return ( buff.dance_of_death.up and 14 or 12 ) * haste end,
|
|
tick_time = 2,
|
|
max_stack = 1
|
|
},
|
|
rend = {
|
|
id = 388539,
|
|
duration = 15,
|
|
tick_time = 3,
|
|
max_stack = 1
|
|
},
|
|
revenge = {
|
|
id = 5302,
|
|
duration = 6,
|
|
max_stack = 1
|
|
},
|
|
-- Damage taken reduced by $w1%.
|
|
safeguard = {
|
|
id = 424655,
|
|
duration = 5.0,
|
|
max_stack = 1,
|
|
},
|
|
seeing_red = {
|
|
id = 386486,
|
|
duration = 30,
|
|
max_stack = 100
|
|
},
|
|
shield_bash = {
|
|
id = 198912,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
shield_block = {
|
|
id = 132404,
|
|
duration = function () return 6 + talent.enduring_defenses.rank end,
|
|
max_stack = 1
|
|
},
|
|
shield_charge = {
|
|
id = 385954,
|
|
duration = 4,
|
|
max_stack = 1,
|
|
},
|
|
shield_wall = {
|
|
id = 871,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
shockwave = {
|
|
id = 132168,
|
|
duration = function() return 2 + ( talent.boneshaker.enabled and 1 or 0 ) end,
|
|
max_stack = 1
|
|
},
|
|
spell_reflection = {
|
|
id = 23920,
|
|
duration = function () return legendary.misshapen_mirror.enabled and 8 or 5 end,
|
|
max_stack = 1
|
|
},
|
|
spell_reflection_defense = {
|
|
id = 385391,
|
|
duration = 5,
|
|
max_stack = 1
|
|
},
|
|
stance = {
|
|
alias = { "battle_stance", "berserker_stance", "defensive_stance" },
|
|
aliasMode = "first",
|
|
aliasType = "buff",
|
|
duration = 3600,
|
|
},
|
|
storm_bolt = {
|
|
id = 107570,
|
|
duration = 4,
|
|
max_stack = 1
|
|
},
|
|
-- Movement slowed by $s1%.
|
|
storm_of_destruction = {
|
|
id = 424597,
|
|
duration = 6.0,
|
|
max_stack = 1,
|
|
},
|
|
sudden_death = {
|
|
id = 52437,
|
|
duration = 10,
|
|
max_stack = 2
|
|
},
|
|
taunt = {
|
|
id = 355,
|
|
duration = 3,
|
|
max_stack = 1
|
|
},
|
|
thunder_blast = {
|
|
id = 435615,
|
|
duration = 15,
|
|
max_stack = 2
|
|
},
|
|
thunder_clap = {
|
|
id = 6343,
|
|
duration = 10,
|
|
max_stack = 1
|
|
},
|
|
thunderous_roar = {
|
|
id = 397364,
|
|
duration = function () return talent.thunderous_words.enabled and 10 or 8 end,
|
|
tick_time = 2,
|
|
max_stack = 1
|
|
},
|
|
unnerving_focus = {
|
|
id = 384043,
|
|
duration = 15,
|
|
max_stack = 1
|
|
},
|
|
victorious = {
|
|
id = 32216,
|
|
duration = 20,
|
|
max_stack = 1
|
|
},
|
|
violent_outburst = { -- Renamed from Outburst to violent Outburst in build 45779
|
|
id = 386478,
|
|
duration = 30,
|
|
max_stack = 1
|
|
},
|
|
war_machine = {
|
|
id = 262232,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
wild_strikes = {
|
|
id = 392778,
|
|
duration = 10,
|
|
max_stack = 1
|
|
},
|
|
wrecked = {
|
|
id = 447513,
|
|
duration = 10,
|
|
max_stack = 1
|
|
}
|
|
} )
|
|
|
|
spec:RegisterGear({
|
|
-- The War Within
|
|
tww3 = {
|
|
items = { 237610, 237608, 237613, 237611, 237609 },
|
|
auras = {
|
|
-- Colossus
|
|
critical_conclusion = {
|
|
id = 1239144,
|
|
duration = 12, -- 8 for arms?
|
|
max_stack = 1
|
|
},
|
|
deeper_wounds = {
|
|
id = 1239153,
|
|
duration = 8,
|
|
max_stack = 1
|
|
},
|
|
-- Mountain Thane
|
|
severe_thunder = {
|
|
id = 1252096,
|
|
duration = 12,
|
|
max_stack = 1
|
|
},
|
|
}
|
|
},
|
|
tww2 = {
|
|
items = { 229235, 229233, 229238, 229236, 229234 },
|
|
auras = {
|
|
luck_of_the_draw = {
|
|
id = 1218163,
|
|
duration = 10,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
},
|
|
-- Dragonflight
|
|
tier31 = {
|
|
items = { 207180, 207181, 207182, 207183, 207185, 217218, 217220, 217216, 217217, 217219 },
|
|
setBonuses = {
|
|
tier31_2pc = 422927,
|
|
tier31_4pc = 422928
|
|
},
|
|
auras = {
|
|
fervid = {
|
|
id = 425517,
|
|
duration = 10,
|
|
max_stack = 1
|
|
},
|
|
fervid_opposition = {
|
|
id = 427413,
|
|
duration = 5,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
},
|
|
tier30 = {
|
|
items = { 202446, 202444, 202443, 202442, 202441 },
|
|
setBonuses = {
|
|
tier30_2pc = 405581,
|
|
tier30_4pc = 405582
|
|
},
|
|
auras = {
|
|
earthen_tenacity = {
|
|
id = 410218,
|
|
duration = 5,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
},
|
|
tier29 = {
|
|
items = { 200426, 200428, 200423, 200425, 200427 },
|
|
setBonuses = {
|
|
tier29_2pc = 393710,
|
|
tier29_4pc = 393711
|
|
},
|
|
auras = {
|
|
vanguards_determination = {
|
|
id = 394056,
|
|
duration = 5,
|
|
max_stack = 1
|
|
}
|
|
}
|
|
}
|
|
} )
|
|
|
|
local rageSpent_10 = 0
|
|
local rageSpent_20 = 0
|
|
|
|
spec:RegisterStateExpr( "rageSpent_10", function () return rageSpent_10 end ) -- Glory (Shadowlands) and Anger Management talent
|
|
spec:RegisterStateExpr( "rageSpent_20", function () return rageSpent_20 end ) -- Indomitable talent
|
|
|
|
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 - 3 then -- Spent Rage, -3 is used as a Hack to avoid Rage decaying
|
|
if state.talent.anger_management.enabled or ( state.legendary.glory.enabled and FindPlayerAuraByID( 324143 ) ) then -- Glory and Anger Management
|
|
rageSpent_10 = ( rageSpent_10 + lastRage - current ) % 10
|
|
end
|
|
if state.talent.indomitable.enabled then -- Indomitable
|
|
rageSpent_20 = ( rageSpent_20 + lastRage - current ) % 20
|
|
end
|
|
end
|
|
lastRage = current
|
|
end
|
|
end )
|
|
|
|
-- model rage expenditure and special effects
|
|
spec:RegisterHook( "spend", function( amt, resource )
|
|
if resource == "rage" and amt > 0 then
|
|
if talent.anger_management.enabled or ( legendary.glory.enabled and buff.conquerors_banner.up ) then
|
|
rageSpent_10 = rageSpent_10 + amt
|
|
local rage10activations = floor( rageSpent_10 / 10 )
|
|
rageSpent_10 = rageSpent_10 % 10
|
|
|
|
if rage10activations > 0 then
|
|
if legendary.glory.enabled and buff.conquerors_banner.up then
|
|
buff.conquerors_banner.expires = buff.conquerors_banner.expires + ( rage10activations * 0.5 )
|
|
end
|
|
if talent.anger_management.enabled then
|
|
if talent.shield_wall.enabled then cooldown.shield_wall.expires = cooldown.shield_wall.expires - rage10activations end
|
|
if talent.avatar.enabled then cooldown.avatar.expires = cooldown.avatar.expires - rage10activations end
|
|
end
|
|
end
|
|
end
|
|
|
|
if talent.indomitable.enabled then
|
|
rageSpent_20 = rageSpent_20 + amt
|
|
local rage20activations = floor( rageSpent_20 / 20 )
|
|
rageSpent_20 = rageSpent_20 % 20
|
|
|
|
if rage20activations > 0 then
|
|
gain( ( 0.01 * rage20activations ) * health.max, "health" ) -- Restores 1% max health
|
|
end
|
|
end
|
|
|
|
if talent.violent_outburst.enabled then
|
|
buff.seeing_red.v1 = buff.seeing_red.v1 + amt
|
|
if buff.seeing_red.v1 >= 250 then
|
|
applyBuff( "violent_outburst" )
|
|
end
|
|
buff.seeing_red.v1 = buff.seeing_red.v1 % 250
|
|
if buff.seeing_red.v1 == 0 then
|
|
removeBuff( "seeing_red" )
|
|
else
|
|
applyBuff( "seeing_red", nil, floor( buff.seeing_red.v1 / 250 * 100 ), buff.seeing_red.v1)
|
|
end
|
|
end
|
|
end
|
|
end )
|
|
|
|
spec:RegisterCombatLogEvent( function( _, subtype, _, sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, school, amount, interrupt, a, b, c, d, critical )
|
|
--TODO: Deepdive to see if beneficial or not.
|
|
if sourceGUID == state.GUID then
|
|
if state.talent.colossal_might.enabled and spellID == 440989 and ( subtype == "SPELL_AURA_APPLIED" or subtype == "SPELL_AURA_REMOVED" or subtype == "SPELL_AURA_REFRESH" or subtype == "SPELL_AURA_APPLIED_DOSE" or subtype == "SPELL_AURA_REMOVED_DOSE" ) then
|
|
Hekili:ForceUpdate( "COLOSSALMIGHT_CHANGED", true )
|
|
elseif state.talent.thunder_blast.enabled and spellID == 435615 and ( subtype == "SPELL_AURA_APPLIED" or subtype == "SPELL_AURA_REMOVED" or subtype == "SPELL_AURA_REFRESH" or subtype == "SPELL_AURA_APPLIED_DOSE" or subtype == "SPELL_AURA_REMOVED_DOSE" ) then
|
|
Hekili:ForceUpdate( "THUNDERBLAST_CHANGED", true )
|
|
elseif state.talent.burst_of_power.enabled and spellID == 437121 and ( subtype == "SPELL_AURA_APPLIED" or subtype == "SPELL_AURA_REMOVED" or subtype == "SPELL_AURA_REFRESH" or subtype == "SPELL_AURA_APPLIED_DOSE" or subtype == "SPELL_AURA_REMOVED_DOSE" ) then
|
|
Hekili:ForceUpdate( "BURSTOFPOWER_CHANGED", true )
|
|
end
|
|
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 )
|
|
|
|
local TriggerEarthenTenacity = setfenv( function()
|
|
applyBuff( "earthen_tenacity" )
|
|
end, state )
|
|
|
|
spec:RegisterHook( "reset_precast", function ()
|
|
if set_bonus.tier30_4pc > 0 and buff.last_stand.up then
|
|
state:QueueAuraExpiration( "last_stand_earthen_tenacity", TriggerEarthenTenacity, buff.last_stand.expires )
|
|
end
|
|
end )
|
|
|
|
spec:RegisterStateExpr( "last_stand_damage_taken", function ()
|
|
return ( settings.last_stand_amount or 0 ) * health.max * 0.01
|
|
end )
|
|
spec:RegisterStateExpr( "last_stand_health_pct", function ()
|
|
return ( settings.last_stand_health or 0 )
|
|
end )
|
|
spec:RegisterStateExpr( "rallying_cry_damage_taken", function ()
|
|
return ( settings.rallying_cry_amount or 0 ) * health.max * 0.01
|
|
end )
|
|
spec:RegisterStateExpr( "rallying_cry_health_pct", function ()
|
|
return ( settings.rallying_cry_health or 0 )
|
|
end )
|
|
spec:RegisterStateExpr( "shield_wall_damage_taken", function ()
|
|
return ( settings.shield_wall_amount or 0 ) * health.max * 0.01
|
|
end )
|
|
spec:RegisterStateExpr( "shield_wall_health_pct", function ()
|
|
return ( settings.shield_wall_health or 0 )
|
|
end )
|
|
spec:RegisterStateExpr( "victory_rush_health_pct", function ()
|
|
return ( settings.victory_rush_health or 0 )
|
|
end )
|
|
|
|
-- Abilities
|
|
spec:RegisterAbilities( {
|
|
avatar = {
|
|
id = 107574,
|
|
cast = 0,
|
|
cooldown = 90,
|
|
gcd = "off",
|
|
|
|
spend = function () return buff.unnerving_focus.up and -15 or -10 end,
|
|
spendType = "rage",
|
|
|
|
talent = "avatar",
|
|
startsCombat = false,
|
|
texture = 613534,
|
|
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
applyBuff( "avatar" )
|
|
if talent.immovable_object.enabled then
|
|
applyBuff( "shield_wall", 4 )
|
|
end
|
|
if talent.avatar_of_the_storm.enabled then
|
|
setCooldown( "thunder_clap", 0 )
|
|
setCooldown( "thunder_blast", 0 )
|
|
applyBuff( "thunder_blast", 15, 2 )
|
|
end
|
|
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,
|
|
},
|
|
|
|
|
|
battle_stance = {
|
|
id = 386164,
|
|
cast = 0,
|
|
cooldown = 3,
|
|
gcd = "off",
|
|
|
|
talent = "battle_stance",
|
|
startsCombat = false,
|
|
nobuff = function() return settings.stance_weaving and "battle_stance" or "stance" end,
|
|
|
|
handler = function ()
|
|
applyBuff( "battle_stance" )
|
|
removeBuff( "defensive_stance" )
|
|
end,
|
|
},
|
|
|
|
|
|
berserker_rage = {
|
|
id = 18499,
|
|
cast = 0,
|
|
cooldown = 60,
|
|
gcd = "off",
|
|
|
|
startsCombat = false,
|
|
texture = 136009,
|
|
|
|
--Not yet Implemented in LossOfControl via Classes.lua
|
|
--toggle = "defensives",
|
|
--usable = function () return ( debuff.sap.up or debuff.incapacitate.up or debuff.fear.up ) , "requires fear/incapacitate/sap debuff" end,
|
|
|
|
handler = function ()
|
|
applyBuff( "berserker_rage" )
|
|
end,
|
|
},
|
|
|
|
|
|
berserker_shout = {
|
|
id = 384100,
|
|
cast = 0,
|
|
cooldown = 60,
|
|
gcd = "off",
|
|
|
|
talent = "berserker_shout",
|
|
startsCombat = false,
|
|
texture = 136009,
|
|
|
|
--Not yet Implemented in LossOfControl via Classes.lua
|
|
--toggle = "defensives",
|
|
--usable = function () return ( debuff.sap.up or debuff.incapacitate.up or debuff.fear.up ) , "requires fear/incapacitate/sap debuff" end,
|
|
|
|
handler = function ()
|
|
applyBuff( "berserker_shout" )
|
|
end,
|
|
},
|
|
|
|
|
|
bitter_immunity = {
|
|
id = 383762,
|
|
cast = 0,
|
|
cooldown = 180,
|
|
gcd = "off",
|
|
|
|
talent = "bitter_immunity",
|
|
startsCombat = false,
|
|
texture = 136088,
|
|
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
removeBuff( "dispellable_disease" )
|
|
removeBuff( "dispellable_poison" )
|
|
removeBuff( "dispellable_curse" )
|
|
gain( 0.2 * health.max, "health" )
|
|
end,
|
|
},
|
|
|
|
|
|
bodyguard = {
|
|
id = 213871,
|
|
cast = 0,
|
|
cooldown = 15,
|
|
gcd = "spell",
|
|
|
|
pvptalent = "bodyguard",
|
|
startsCombat = false,
|
|
texture = 132359,
|
|
|
|
handler = function ()
|
|
applyBuff( "bodyguard" )
|
|
end,
|
|
},
|
|
|
|
|
|
challenging_shout = {
|
|
id = 1161,
|
|
cast = 0,
|
|
cooldown = 120,
|
|
gcd = "off",
|
|
|
|
notalent = "disrupting_shout",
|
|
startsCombat = true,
|
|
texture = 132091,
|
|
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "challenging_shout" )
|
|
active_dot.challenging_shout = active_enemies
|
|
end,
|
|
},
|
|
|
|
champions_spear = {
|
|
id = function() return talent.champions_spear.enabled and 376079 or 307865 end,
|
|
cast = 0,
|
|
cooldown = 90,
|
|
gcd = "spell",
|
|
|
|
spend = function () return ( -10 * ( talent.piercing_challenge.enabled and 2 or 1 ) ) * ( 1 + conduit.piercing_verdict.mod * 0.01 ) end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
toggle = "cooldowns",
|
|
velocity = 30,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "champions_spear" )
|
|
if talent.champions_might.enabled or legendary.elysian_might.enabled then applyBuff( "champions_might" ) end
|
|
end,
|
|
|
|
copy = { "spear_of_bastion", 307865, 376079 }
|
|
},
|
|
|
|
charge = {
|
|
id = 100,
|
|
cast = 0,
|
|
charges = function () return talent.double_time.enabled and 2 or 1 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",
|
|
icd = 1,
|
|
|
|
spend = function () return -20 * ( buff.unnerving_focus.up and 1.5 or 1 ) end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132337,
|
|
|
|
usable = function () return target.minR > 10 and ( query_time - action.charge.lastCast > gcd.execute ), "target too close" end,
|
|
handler = function ()
|
|
setDistance( 5 )
|
|
applyDebuff( "target", "charge" )
|
|
if legendary.reprisal.enabled then
|
|
applyBuff( "shield_block", buff.shield_block.remains + 4 )
|
|
applyBuff( "revenge" )
|
|
gain( 20, "rage" )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
defensive_stance = {
|
|
id = 386208,
|
|
cast = 0,
|
|
cooldown = 3,
|
|
gcd = "off",
|
|
|
|
talent = "defensive_stance",
|
|
startsCombat = false,
|
|
essential = true,
|
|
nobuff = function() return settings.stance_weaving and "defensive_stance" or "stance" end,
|
|
|
|
handler = function ()
|
|
removeBuff( "battle_stance" )
|
|
applyBuff( "defensive_stance" )
|
|
end,
|
|
},
|
|
|
|
demolish = {
|
|
id = 436358,
|
|
cast = function () return 2 * haste end,
|
|
channeled = true,
|
|
breakable = false,
|
|
cooldown = 45,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
|
|
handler = function()
|
|
removeBuff( "colossal_might" )
|
|
active_dot.wrecked = active_enemies
|
|
end,
|
|
},
|
|
|
|
|
|
demoralizing_shout = {
|
|
id = 1160,
|
|
cast = 0,
|
|
cooldown = 45,
|
|
gcd = "spell",
|
|
|
|
spend = function () return ( talent.booming_voice.enabled and -20 or 0 ) * ( buff.unnerving_focus.up and 1.5 or 1 ) end,
|
|
spendType = "rage",
|
|
|
|
talent = "demoralizing_shout",
|
|
startsCombat = false,
|
|
texture = 132366,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "demoralizing_shout" )
|
|
active_dot.demoralizing_shout = max( active_dot.demoralizing_shout, active_enemies )
|
|
end,
|
|
},
|
|
|
|
|
|
devastate = {
|
|
id = 20243,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = function() return ( talent.instigate.enabled and -2 or 0 ) * ( buff.unnerving_focus.up and 1.5 or 1) end,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
notalent = "devastator",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "deep_wounds" )
|
|
end,
|
|
},
|
|
|
|
|
|
disarm = {
|
|
id = 236077,
|
|
cast = 0,
|
|
cooldown = 45,
|
|
gcd = "spell",
|
|
|
|
pvptalent = "disarm",
|
|
startsCombat = false,
|
|
texture = 132343,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "disarm" )
|
|
end,
|
|
},
|
|
|
|
|
|
disrupting_shout = {
|
|
id = 386071,
|
|
cast = 0,
|
|
cooldown = 90,
|
|
gcd = "off",
|
|
|
|
talent = "disrupting_shout",
|
|
startsCombat = false,
|
|
texture = 132091,
|
|
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "disrupting_shout" )
|
|
active_dot.disrupting_shout = active_enemies
|
|
end,
|
|
},
|
|
|
|
|
|
dragon_charge = {
|
|
id = 206572,
|
|
cast = 0,
|
|
cooldown = 20,
|
|
gcd = "off",
|
|
|
|
pvptalent = "dragon_charge",
|
|
startsCombat = false,
|
|
texture = 1380676,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
execute = {
|
|
id = function () return talent.massacre.enabled and 281000 or 163201 end,
|
|
known = 163201,
|
|
copy = { 163201, 281000 },
|
|
noOverride = 317485, -- Condemn
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
hasteCD = true,
|
|
|
|
spend = 0,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 135358,
|
|
|
|
usable = function ()
|
|
if buff.sudden_death.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()
|
|
if buff.sudden_death.up then return 0 end
|
|
local threshold = settings.reserve_rage + 40
|
|
return ( tanking and rage.current < threshold ) and rage[ "time_to_" .. threshold ] or 0
|
|
end,
|
|
|
|
handler = function()
|
|
if not buff.sudden_death.up then
|
|
local cost = min( rage.current, 40 )
|
|
spend( cost, "rage", nil, true )
|
|
else
|
|
removeBuff( "sudden_death" )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
hamstring = {
|
|
id = 1715,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = 10,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132316,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "hamstring" )
|
|
setCooldown( "global_cooldown", 0.75 )
|
|
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",
|
|
icd = 0.8,
|
|
|
|
talent = "heroic_leap",
|
|
startsCombat = false,
|
|
texture = 236171,
|
|
|
|
handler = function ()
|
|
if talent.bounding_stride.enabled then applyBuff( "bounding_stride" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
heroic_throw = {
|
|
id = 57755,
|
|
cast = 0,
|
|
cooldown = 1,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
|
|
usable = function () return target.minR > 7, "requires 8 yard range or more" end,
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
|
|
ignore_pain = {
|
|
id = 190456,
|
|
cast = 0,
|
|
cooldown = 1,
|
|
gcd = "off",
|
|
|
|
spend = 35,
|
|
spendType = "rage",
|
|
|
|
talent = "ignore_pain",
|
|
startsCombat = false,
|
|
texture = 1377132,
|
|
|
|
toggle = "defensives",
|
|
|
|
handler = function ()
|
|
-- Magic constants from Wowhead 2025-04-22.
|
|
local onCastAbsorb = stat.attack_power * 5.75 * ( 1 + 0.2 * talent.no_stranger_to_pain.rank ) * ( 1 + stat.versatility_atk_mod ) * 2
|
|
local maxAbsorb = 0.3 * health.max
|
|
buff.ignore_pain.v1 = min( maxAbsorb, buff.ignore_pain.v1 + onCastAbsorb )
|
|
-- The stack count for Ignore Pain is the percent of the maximum absorb.
|
|
applyBuff( "ignore_pain", nil, floor( buff.ignore_pain.v1 / maxAbsorb * 100 ), buff.ignore_pain.v1 )
|
|
end,
|
|
},
|
|
|
|
|
|
impending_victory = {
|
|
id = 202168,
|
|
cast = 0,
|
|
cooldown = 25,
|
|
gcd = "spell",
|
|
|
|
spend = function() return buff.victorious.up and 0 or 10 end,
|
|
spendType = "rage",
|
|
|
|
talent = "impending_victory",
|
|
startsCombat = true,
|
|
|
|
handler = function ()
|
|
removeBuff( "victorious" )
|
|
gain( health.max * 0.2, "health" )
|
|
if conduit.indelible_victory.enabled then applyBuff( "indelible_victory" ) end
|
|
if talent.steadfast_as_the_peaks.enabled then
|
|
gain( health.max * 0.1, "health" )
|
|
applyBuff( "steadfast_as_the_peaks" )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
intervene = {
|
|
id = 3411,
|
|
cast = 0,
|
|
cooldown = function ()
|
|
if pvptalent.safeguard.enabled then return 40 - ( talent.honed_reflexes.enabled and 40*0.05 or 0 ) end
|
|
return 30 - ( talent.honed_reflexes.enabled and 30*0.05 or 0 )
|
|
end,
|
|
charges = function () if pvptalent.safeguard.enabled then return 2 end end,
|
|
recharge = function () if pvptalent.safeguard.enabled then return 40 - ( talent.honed_reflexes.enabled and 40*0.05 or 0 ) end end,
|
|
gcd = "off",
|
|
icd = 1.5,
|
|
|
|
talent = "intervene",
|
|
startsCombat = false,
|
|
|
|
handler = function ()
|
|
if legendary.reprisal.enabled then
|
|
applyBuff( "shield_block", buff.shield_block.remains + 4 )
|
|
applyBuff( "revenge" )
|
|
gain( 20, "rage" )
|
|
end
|
|
|
|
if pvptalent.safeguard.enabled then
|
|
applyBuff( "safeguard" )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
intimidating_shout = {
|
|
id = function() return talent.menace.enabled and 316593 or 5246 end,
|
|
cast = 0,
|
|
cooldown = 90,
|
|
gcd = "spell",
|
|
|
|
talent = "intimidating_shout",
|
|
startsCombat = true,
|
|
texture = 132154,
|
|
|
|
toggle = "interrupts",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "intimidating_shout" )
|
|
active_dot.intimidating_shout = max( active_dot.intimidating_shout, active_enemies )
|
|
end,
|
|
|
|
copy = { 316593, 5246 },
|
|
},
|
|
|
|
|
|
last_stand = {
|
|
id = 12975,
|
|
cast = 0,
|
|
cooldown = function() return 180 - ( talent.bolster.enabled and 60 or 0 ) end,
|
|
gcd = "off",
|
|
|
|
talent = "last_stand",
|
|
startsCombat = false,
|
|
texture = 135871,
|
|
|
|
toggle = function()
|
|
if talent.unnerving_focus.enabled or conduit.unnerving_focus.enabled or set_bonus.tier30_2pc > 0 then
|
|
return "cooldowns"
|
|
end
|
|
return "defensives"
|
|
end,
|
|
|
|
handler = function ()
|
|
applyBuff( "last_stand" )
|
|
|
|
if talent.bolster.enabled then
|
|
applyBuff( "shield_block", buff.shield_block.remains + buff.last_stand.duration )
|
|
end
|
|
|
|
if talent.unnerving_focus.enabled then
|
|
applyBuff( "unnerving_focus" )
|
|
end
|
|
|
|
if set_bonus.tier30_4pc > 0 then
|
|
state:QueueAuraExpiration( "last_stand_earthen_tenacity", TriggerEarthenTenacity, buff.last_stand.expires )
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
oppressor = {
|
|
id = 205800,
|
|
cast = 0,
|
|
cooldown = 20,
|
|
gcd = "spell",
|
|
|
|
pvptalent = "oppressor",
|
|
startsCombat = false,
|
|
texture = 136080,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "focused_assault" )
|
|
end
|
|
},
|
|
|
|
|
|
piercing_howl = {
|
|
id = 12323,
|
|
cast = 0,
|
|
cooldown = 30,
|
|
gcd = "spell",
|
|
|
|
talent = "piercing_howl",
|
|
startsCombat = false,
|
|
texture = 136147,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "piercing_howl" )
|
|
active_dot.piercing_howl = max( active_dot.piercing_howl, active_enemies )
|
|
end,
|
|
},
|
|
|
|
|
|
pummel = {
|
|
id = 6552,
|
|
cast = 0,
|
|
cooldown = function () return 15 - ( talent.concussive_blows.enabled and 1 or 0 ) - ( talent.honed_reflexes.enabled and 15*0.05 or 0 ) end,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 132938,
|
|
|
|
toggle = "interrupts",
|
|
interrupt = true,
|
|
|
|
debuff = "casting",
|
|
readyTime = state.timeToInterrupt,
|
|
|
|
handler = function ()
|
|
interrupt()
|
|
if talent.concussive_blows.enabled then applyDebuff( "target", "concussive_blows" ) end
|
|
end,
|
|
},
|
|
|
|
|
|
rallying_cry = {
|
|
id = 97462,
|
|
cast = 0,
|
|
cooldown = 180,
|
|
gcd = "spell",
|
|
|
|
talent = "rallying_cry",
|
|
startsCombat = false,
|
|
texture = 132351,
|
|
|
|
toggle = "defensives",
|
|
|
|
handler = function ()
|
|
applyBuff( "rallying_cry" )
|
|
gain( 0.10 * health.max, "health" )
|
|
end,
|
|
},
|
|
|
|
|
|
ravager = {
|
|
id = 228920,
|
|
cast = 0,
|
|
charges = function () return ( talent.storm_of_steel.enabled and 2 or 1 ) end,
|
|
cooldown = 90,
|
|
recharge = 90,
|
|
gcd = "spell",
|
|
|
|
talent = "ravager",
|
|
startsCombat = true,
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
applyBuff( "ravager" )
|
|
end,
|
|
},
|
|
|
|
|
|
rend = {
|
|
id = 394062,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = 20,
|
|
spendType = "rage",
|
|
|
|
talent = "rend",
|
|
startsCombat = true,
|
|
texture = 132155,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "rend" )
|
|
end,
|
|
},
|
|
|
|
|
|
revenge = {
|
|
id = 6572,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
if buff.revenge.up then return 0 end
|
|
return 20
|
|
end,
|
|
spendType = "rage",
|
|
|
|
talent = "revenge",
|
|
startsCombat = true,
|
|
texture = 132353,
|
|
|
|
readyTime = function()
|
|
if buff.revenge.up then return 0 end
|
|
local threshold = settings.reserve_rage + 20
|
|
return ( tanking and rage.current < threshold ) and rage[ "time_to_" .. threshold ] or 0
|
|
end,
|
|
|
|
handler = function ()
|
|
if set_bonus.tier29_2pc > 0 then applyBuff( "vanguards_determination" ) end
|
|
if buff.revenge.up then removeBuff( "revenge" ) end
|
|
applyDebuff( "target", "deep_wounds" )
|
|
if talent.best_served_cold.enabled then applyBuff( "best_served_cold" ) end
|
|
|
|
if talent.demolish.enabled and active_enemies > 2 then
|
|
if talent.dominance_of_the_colossus.enabled and buff.colossal_might.stack == 10 then reduceCooldown( "demolish", 2 ) end
|
|
if talent.colossal_might.enabled then addStack( "colossal_might" ) end
|
|
end
|
|
end,
|
|
},
|
|
|
|
|
|
shattering_throw = {
|
|
id = 64382,
|
|
cast = 1.5,
|
|
cooldown = 180,
|
|
gcd = "spell",
|
|
|
|
talent = "shattering_throw",
|
|
startsCombat = true,
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
removeDebuff( "target", "all_absorbs" )
|
|
end,
|
|
},
|
|
|
|
|
|
shield_bash = {
|
|
id = 198912,
|
|
cast = 0,
|
|
cooldown = 10,
|
|
gcd = "spell",
|
|
spend = -3,
|
|
spendType = "rage",
|
|
|
|
pvptalent = "shield_bash",
|
|
startsCombat = false,
|
|
texture = 132357,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "shield_bash" )
|
|
end,
|
|
},
|
|
|
|
|
|
shield_block = {
|
|
id = 2565,
|
|
cast = 0,
|
|
charges = 2,
|
|
cooldown = 16,
|
|
recharge = 16,
|
|
hasteCD = true,
|
|
gcd = "off",
|
|
|
|
toggle = "defensives",
|
|
equipped = "shield",
|
|
defensive = true,
|
|
|
|
spend = 30,
|
|
spendType = "rage",
|
|
|
|
startsCombat = false,
|
|
texture = 132110,
|
|
|
|
nobuff = function()
|
|
if not settings.stack_shield_block then return "shield_block" end
|
|
end,
|
|
|
|
handler = function ()
|
|
applyBuff( "shield_block", buff.shield_block.remains + buff.shield_block.duration )
|
|
end,
|
|
},
|
|
|
|
|
|
shield_charge = {
|
|
id = 385952,
|
|
cast = 0,
|
|
cooldown = 45,
|
|
gcd = "spell",
|
|
|
|
spend = -20,
|
|
spendType = "rage",
|
|
|
|
talent = "shield_charge",
|
|
equipped = "shield",
|
|
startsCombat = true,
|
|
|
|
handler = function ()
|
|
applyBuff( "shield_block", buff.shield_block.remains + buff.shield_block.duration )
|
|
end,
|
|
},
|
|
|
|
|
|
shield_slam = {
|
|
id = 23922,
|
|
cast = 0,
|
|
cooldown = function () return 9 - ( talent.honed_reflexes.enabled and 1 or 0 ) end,
|
|
hasteCD = true,
|
|
gcd = "spell",
|
|
|
|
spend = function ()
|
|
local reduction = 0
|
|
-- The Wall Legendary overtakes the new Impenetrable Wall talent, they do not stack in 10.0
|
|
if legendary.the_wall.enabled then reduction = reduction - 5
|
|
end
|
|
|
|
return
|
|
( -15 + reduction + ( talent.heavy_repercussions.enabled and -2 or 0 ) - ( 3 * talent.practiced_strikes.rank ) )
|
|
* ( buff.violent_outburst.up and 1.5 or 1 ) -- Build 45969
|
|
* ( buff.unnerving_focus.up and 1.5 or 1 )
|
|
end,
|
|
spendType = "rage",
|
|
|
|
equipped = "shield",
|
|
startsCombat = true,
|
|
texture = 134951,
|
|
|
|
readyTime = function()
|
|
if buff.burst_of_power.up then return 0 end
|
|
end,
|
|
|
|
handler = function ()
|
|
|
|
-- Core
|
|
if buff.violent_outburst.up then
|
|
class.abilities.ignore_pain.handler()
|
|
removeBuff( "violent_outburst" )
|
|
end
|
|
if talent.brace_for_impact.enabled then applyBuff( "brace_for_impact" ) end
|
|
if talent.heavy_repercussions.enabled and buff.shield_block.up then
|
|
buff.shield_block.expires = buff.shield_block.expires + 1
|
|
end
|
|
if talent.punish.enabled then applyDebuff( "target", "punish" ) end
|
|
|
|
-- Hero / TWW
|
|
if talent.dominance_of_the_colossus.enabled and buff.colossal_might.stack == 10 then reduceCooldown( "demolish", 2 ) end
|
|
if talent.colossal_might then addStack( "colossal_might" ) end
|
|
if set_bonus.tww3_colossus >= 4 then removeStack( "critical_conclusion" ) end
|
|
|
|
-- Legacy
|
|
|
|
if ( legendary.the_wall.enabled or talent.impenetrable_wall.enabled ) and cooldown.shield_wall.remains > 0 then
|
|
reduceCooldown( "shield_wall", 6 )
|
|
end
|
|
if set_bonus.tier30_2pc > 0 then
|
|
reduceCooldown( "last_stand", buff.last_stand.up and 4 or 2 )
|
|
end
|
|
if buff.fervid.up then
|
|
removeDebuff( "target", "deep_wounds" )
|
|
removeDebuff( "target", "rend" )
|
|
removeDebuff( "target", "thunderous_roar" )
|
|
if set_bonus.tier31_4pc > 0 then applyBuff( "fervid_opposition" ) end
|
|
end
|
|
|
|
|
|
end,
|
|
},
|
|
|
|
|
|
shield_wall = {
|
|
id = 871,
|
|
cast = 0,
|
|
charges = function () return 1 + ( talent.defenders_aegis.enabled and 1 or 0 ) + ( legendary.unbreakable_will.enabled and 1 or 0 ) end,
|
|
cooldown = function() return 180 - ( talent.honed_reflexes.enabled and 210*0.05 or 0 ) - ( conduit.stalwart_guardian.enabled and 20 or 0 ) - ( talent.defenders_aegis.enabled and 60 or 0 ) end,
|
|
recharge = function() return 180 - ( talent.honed_reflexes.enabled and 210*0.05 or 0 ) - ( conduit.stalwart_guardian.enabled and 20 or 0 ) - ( talent.defenders_aegis.enabled and 60 or 0 ) end,
|
|
gcd = "off",
|
|
|
|
talent = "shield_wall",
|
|
startsCombat = false,
|
|
texture = 132362,
|
|
|
|
toggle = "defensives",
|
|
|
|
handler = function ()
|
|
applyBuff( "shield_wall" )
|
|
if talent.immovable_object.enabled then applyBuff( "avatar", 4 ) end
|
|
end,
|
|
},
|
|
|
|
|
|
shockwave = {
|
|
id = 46968,
|
|
cast = 0,
|
|
cooldown = function () return
|
|
( ( ( talent.rumbling_earth.enabled and active_enemies >= 3 ) and 25 or 40 )
|
|
- ( conduit.disturb_the_peace.enabled and 5 or 0 )
|
|
- ( talent.earthquaker.enabled and 5 or 0 )
|
|
) end,
|
|
gcd = "spell",
|
|
|
|
talent = "shockwave",
|
|
startsCombat = true,
|
|
texture = 236312,
|
|
|
|
toggle = "interrupts",
|
|
debuff = function () return settings.shockwave_interrupt and "casting" or nil end,
|
|
readyTime = function () return settings.shockwave_interrupt and timeToInterrupt() or nil end,
|
|
|
|
usable = function () return not target.is_boss end,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "shockwave" )
|
|
active_dot.shockwave = max( active_dot.shockwave, active_enemies )
|
|
if not target.is_boss then interrupt() end
|
|
end,
|
|
},
|
|
|
|
slam = {
|
|
id = 1464,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = 20,
|
|
spendType = "rage",
|
|
|
|
startsCombat = true,
|
|
texture = 132340,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
spell_reflection = {
|
|
id = 23920,
|
|
cast = 0,
|
|
cooldown = function() return 25 - ( talent.honed_reflexes.enabled and 25 * 0.05 or 0 ) end,
|
|
gcd = "off",
|
|
|
|
talent = "spell_reflection",
|
|
|
|
toggle = "defensives",
|
|
debuff = "casting",
|
|
|
|
usable = function()
|
|
if not settings.spell_reflection_filter then return true end
|
|
|
|
local zone = state.instance_id
|
|
local npcid = target.npcid or -1
|
|
local t = debuff.casting
|
|
|
|
-- Only use on a reflectable spell targeted at the player.
|
|
if not t.up then
|
|
return false, "Target is not casting"
|
|
end
|
|
if not state.target.is_dummy and not class.reflectableFilters[ t.v1 ] then
|
|
return false, "spell[" .. t.v1 .. "] in zone[" .. zone .. "] by npc[" .. npcid .. "] is not reflectable"
|
|
end
|
|
if not UnitIsUnit( "player", t.caster .. "target" ) then
|
|
return false, "Player is not target of cast"
|
|
end
|
|
return true
|
|
end,
|
|
|
|
handler = function()
|
|
applyBuff( "spell_reflection" )
|
|
applyBuff( "spell_reflection_defense" )
|
|
end,
|
|
},
|
|
|
|
storm_bolt = {
|
|
id = 107570,
|
|
cast = 0,
|
|
cooldown = function() return 30 - ( talent.honed_reflexes.enabled and 30 * 0.05 or 0 ) + ( talent.storm_bolts.enabled and 10 or 0 ) end,
|
|
gcd = "spell",
|
|
|
|
talent = "storm_bolt",
|
|
startsCombat = true,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "storm_bolt" )
|
|
end,
|
|
},
|
|
|
|
|
|
taunt = {
|
|
id = 355,
|
|
cast = 0,
|
|
cooldown = 8,
|
|
gcd = "off",
|
|
|
|
startsCombat = true,
|
|
texture = 136080,
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "taunt" )
|
|
end,
|
|
},
|
|
|
|
|
|
thunder_clap = {
|
|
id = 6343,
|
|
cast = 0,
|
|
cooldown = function () return haste * ( ( buff.avatar.up and talent.unstoppable_force.enabled ) and 3 or 6 ) end,
|
|
gcd = "spell",
|
|
hasteCD = true,
|
|
|
|
spend = function () return -5
|
|
* ( buff.violent_outburst.up and 1.5 or 1 )
|
|
* ( buff.unnerving_focus.up and 1.5 or 1 ) end,
|
|
spendType = "rage",
|
|
|
|
talent = "thunder_clap",
|
|
nobuff = "thunder_blast",
|
|
startsCombat = true,
|
|
texture = 136105,
|
|
bind = "thunder_blast",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "thunder_clap" )
|
|
active_dot.thunder_clap = max( active_dot.thunder_clap, active_enemies )
|
|
|
|
if ( talent.thunderlord.enabled or legendary.thunderlord.enabled ) and cooldown.demoralizing_shout.remains > 0 then
|
|
reduceCooldown( "demoralizing_shout", 1.5 * min( 3, active_enemies ) )
|
|
end
|
|
|
|
if talent.rend.enabled then
|
|
applyDebuff( "target", "rend" )
|
|
active_dot.rend = min( active_enemies, 5 )
|
|
end
|
|
|
|
if buff.violent_outburst.up then
|
|
class.abilities.ignore_pain.handler()
|
|
removeBuff( "violent_outburst" )
|
|
end
|
|
|
|
removeBuff( "best_served_cold" )
|
|
end,
|
|
},
|
|
|
|
thunder_blast = {
|
|
id = 435222,
|
|
flash = 6343,
|
|
cast = 0,
|
|
cooldown = function () return haste * ( ( buff.avatar.up and talent.unstoppable_force.enabled ) and 3 or 6 ) end,
|
|
gcd = "spell",
|
|
hasteCD = true,
|
|
|
|
spend = function () return ( ( talent.thorims_might.enabled and talent.flashing_skies.enabled ) and -11 or -8 )
|
|
* ( buff.violent_outburst.up and 1.5 or 1 )
|
|
* ( buff.unnerving_focus.up and 1.5 or 1 ) end,
|
|
spendType = "rage",
|
|
|
|
talent = "thunder_clap",
|
|
buff = "thunder_blast",
|
|
startsCombat = true,
|
|
texture = 460957,
|
|
bind = "thunder_clap",
|
|
|
|
handler = function ()
|
|
removeStack( "thunder_blast" )
|
|
applyDebuff( "target", "thunder_clap" )
|
|
active_dot.thunder_clap = max( active_dot.thunder_clap, active_enemies )
|
|
|
|
if ( talent.thunderlord.enabled or legendary.thunderlord.enabled ) and cooldown.demoralizing_shout.remains > 0 then
|
|
reduceCooldown( "demoralizing_shout", 1.5 * min( 3, active_enemies ) )
|
|
end
|
|
|
|
if talent.rend.enabled then
|
|
applyDebuff( "target", "rend" )
|
|
active_dot.rend = min( active_enemies, 5 )
|
|
end
|
|
|
|
if buff.violent_outburst.up then
|
|
class.abilities.ignore_pain.handler()
|
|
removeBuff( "violent_outburst" )
|
|
end
|
|
|
|
removeBuff( "best_served_cold" )
|
|
|
|
if set_bonus.tww3 >= 4 then removeBuff( "severe_thunder" ) end
|
|
end,
|
|
copy = { 6343 }
|
|
},
|
|
|
|
|
|
thunderous_roar = {
|
|
id = 384318,
|
|
cast = 0,
|
|
cooldown = function() return talent.uproar.enabled and 90 or 45 end,
|
|
gcd = "spell",
|
|
|
|
spend = 0,
|
|
spendType = "rage",
|
|
|
|
talent = "thunderous_roar",
|
|
startsCombat = true,
|
|
|
|
toggle = "cooldowns",
|
|
|
|
handler = function ()
|
|
applyDebuff( "target", "thunderous_roar" )
|
|
active_dot.thunderous_roar = max( active_dot.thunderous_roar, active_enemies )
|
|
end,
|
|
},
|
|
|
|
victory_rush = {
|
|
id = 34428,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
startsCombat = true,
|
|
buff = "victorious",
|
|
|
|
handler = function ()
|
|
removeBuff( "victorious" )
|
|
gain( health.max * 0.2, "health" )
|
|
if conduit.indelible_victory.enabled then applyBuff( "indelible_victory" ) end
|
|
end,
|
|
},
|
|
|
|
whirlwind = {
|
|
id = 1680,
|
|
cast = 0,
|
|
cooldown = 0,
|
|
gcd = "spell",
|
|
|
|
spend = 20,
|
|
spendType = "rage",
|
|
|
|
startsCombat = false,
|
|
texture = 132369,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
|
|
wrecking_throw = {
|
|
id = 384110,
|
|
cast = 0,
|
|
cooldown = 45,
|
|
gcd = "spell",
|
|
|
|
talent = "wrecking_throw",
|
|
startsCombat = true,
|
|
|
|
handler = function ()
|
|
end,
|
|
},
|
|
} )
|
|
|
|
local NewFeature = "|TInterface\\OptionsFrame\\UI-OptionsFrame-NewFeatureIcon:0|t"
|
|
|
|
spec:RegisterSetting( "spell_reflection_filter", true, {
|
|
name = format( "%s Filter M+ |T132361:0|t Spell Reflection", NewFeature ),
|
|
desc = "If checked, then the addon will only suggest |T132361:0|t Spell Reflection on reflectable spells that target the player.",
|
|
type = "toggle",
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "shockwave_interrupt", true, {
|
|
name = "Only |T236312:0|t Shockwave as Interrupt",
|
|
desc = "If checked, |T236312:0|t Shockwave will only be recommended when your target is casting (and talented).",
|
|
type = "toggle",
|
|
width = "full"
|
|
} )
|
|
|
|
spec:RegisterSetting( "stack_shield_block", false, {
|
|
name = "Overlap |T132110:0|t Shield Block",
|
|
desc = function()
|
|
return "If checked, the addon can recommend overlapping |T132110:0|t Shield Block usage. \n\n" ..
|
|
"This setting avoids leaving Shield Block at 2 charges, which wastes cooldown recovery time."
|
|
end,
|
|
type = "toggle",
|
|
width = "full"
|
|
} )
|
|
|
|
spec:RegisterSetting( "stance_weaving", false, {
|
|
name = "Allow Stance Changes",
|
|
desc = function()
|
|
return "If checked, custom priorities can be written to recommend changing between stances. For example, Battle Stance could be recommended when "
|
|
.. "using offensive cooldowns, then Defensive Stance can be recommended when tanking resumes.\n\n"
|
|
.. "If left unchecked, the addon will not recommend changing your stance as long as you are already in a stance. This choice prevents the addon "
|
|
.. "from endlessly recommending that you change your stance when you do not want to change it."
|
|
end,
|
|
type = "toggle",
|
|
width = "full"
|
|
} )
|
|
|
|
spec:RegisterSetting( "reserve_rage", 35, { -- Ignore Pain cost is 35, Shield Block is 30.
|
|
name = "|T135726:0|t Reserve Rage for Mitigation",
|
|
desc = "When set above zero, the addon will not recommend |T132353:0|t Revenge or |T135358:0|t Execute unless you'll be still have this much Rage afterward.\n\n"
|
|
.. "When set to |cFFFFD10035|r or higher, this feature ensures that you can always use |T1377132:0|t Ignore Pain and |T132110:0|t Shield Block when following recommendations for damage and threat.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 100,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "shield_wall_amount", 20, {
|
|
name = "|T132362:0|t Shield Wall Damage Required",
|
|
desc = "When set above zero, the priority can recommend |T132362:0|t Shield Wall if you have taken this much damage in the past 5 seconds, as a percentage of your maximum health.\n\n"
|
|
.. "If set to |cFFFFD10050%|r and your maximum health is 50,000, then Shield Wall can be recommended when you've taken 25,000 damage in the past 5 seconds.\n\n"
|
|
.. "By default, your Defensives toggle must also be enabled.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 200,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "shield_wall_health", 75, {
|
|
name = "|T132362:0|t Shield Wall Health Percentage",
|
|
desc = "When set above zero, the priority can recommend |T132362:0|t Shield Wall if your current health has fallen below this percentage.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 100,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "rallying_cry_amount", 25, {
|
|
name = "|T132351:0|t Rallying Cry Damage Required",
|
|
desc = "When set above zero, the priority can recommend |T132351:0|t Rallying Cry if you have taken this much damage in the past 5 seconds, as a percentage of your maximum health.\n\n"
|
|
.. "If set to |cFFFFD10050%|r and your maximum health is 50,000, then Rallying Cry can be recommended when you've taken 25,000 damage in the past 5 seconds.\n\n"
|
|
.. "By default, your Defensives toggle must also be enabled.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 200,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "rallying_cry_health", 80, {
|
|
name = "|T132351:0|t Rallying Cry Health Percentage",
|
|
desc = "When set above zero, the priority can recommend |T132351:0|t Rallying Cry if your current health has fallen below this percentage.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 100,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "last_stand_amount", 25, {
|
|
name = "|T135871:0|t Last Stand Damage Required",
|
|
desc = "When set above zero, the priority can recommend |T135871:0|t Last Stand if you have taken this much damage in the past 5 seconds, as a percentage of your maximum health.\n\n"
|
|
.. "If set to |cFFFFD10050%|r and your maximum health is 50,000, then Last Stand can be recommended when you've taken 25,000 damage in the past 5 seconds.\n\n"
|
|
.. "By default, your Defensives toggle must also be enabled.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 200,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "last_stand_health", 70, {
|
|
name = "|T135871:0|t Last Stand Health Percentage",
|
|
desc = "When set above zero, the priority can recommend |T135871:0|t Last Stand if your current health has fallen below this percentage.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 100,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterSetting( "victory_rush_health", 75, {
|
|
name = "|T589768:0|t Victory Rush Health Threshold",
|
|
desc = "When set above zero, the addon may recommend |T589768:0|t Victory Rush when your health falls below this percentage.",
|
|
type = "range",
|
|
min = 0,
|
|
max = 100,
|
|
step = 1,
|
|
width = "full",
|
|
} )
|
|
|
|
spec:RegisterRanges( "hamstring", "devastate", "execute", "storm_bolt", "charge", "heroic_throw", "taunt" )
|
|
|
|
spec:RegisterRangeFilter( strformat( "Can %s but cannot %s (8 yards)", Hekili:GetSpellLinkWithTexture( spec.abilities.taunt.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.charge.id ) ), function()
|
|
return LSR.IsSpellInRange( spec.abilities.taunt.name ) == 1 and LSR.IsSpellInRange( class.abilities.charge.name ) ~= 0
|
|
end )
|
|
|
|
spec:RegisterOptions( {
|
|
enabled = true,
|
|
|
|
aoe = 2,
|
|
|
|
nameplates = true,
|
|
nameplateRange = 10,
|
|
rangeFilter = true,
|
|
|
|
damage = true,
|
|
damageExpiration = 8,
|
|
|
|
potion = "tempered_potion",
|
|
|
|
package = "Protection Warrior",
|
|
} )
|
|
|
|
spec:RegisterPack( "Protection Warrior", 20240926, [[Hekili:nV1wVnUUr4FlNxmIrZ64RXzpiopCoafyxGUTa(G23KeTeTTA0nqr5CsrG(T3HK6cjnj9LKnTal2KinCMV5cNzi9yVjE)H36ief79JPJNoF8xNE)Oj3pDXCV10xlWERlqHpJ2b)sgkf())bjNIdPX5z1b)leHeNty08AsokIXQY8ksiq3EkTO8xV7UDX09vBgfMNExzCAvcIT0qcAlL93H35TEtvCc9BzEBmIJjlaEwGd9(XYzaxJJIWcsXLHERzK(LXF9ltV)xRdwxGtsQd(TK8WNRdqaLr1FV(7D0mhO5VftJ3XXqjqswuDW3slWrXz7Qd(NXH0CYR1b)14)uEPp8LjlUToayX4VYetC6VxhuW08ykqDvbd2L90VuiQ)ypMBIG)dSbXzGzIKVnobmoiUbSCubbdgMni6Fz1DW)ttW(Luuwi(wA(UDj4vGv(7UiEFEfLj4gAG3uuLMItKFs4Eezh(24TROXP4vJF7T08d4uCgDuuSqCp9G8cQkX(XuCAP8drhqueHXLnvB3ocCQzryI)MeujWN8xYE7ndVayF4ZpUAQmNkzUj49Gx6wMOY3U1Fxy0QjCiIYEgCgdIZaDf(f)u0U4q)ie8tS)IYNKwD7tPONXzd2Jrj09JkcPpUsMiXZ9HNp4xUHdrXBj4TjIaz)i8wCwjEuvXqfGUpgNe5)ckj5maQee7xNdikrKbi2)wavnMwMfLhFe1)mcqXRmXhsET)Pf5mDqxFa7rEK)2kiex(PysjMW0ff3njeLb4oNqGaf53KeVBpT0)FxfTlv7vBJjyUqu4eeFvsbC6hcyvrYODGn1NsIdFwjwta)UynrOxV2193dOSiB6iz760XYCkExwob7xGIZeonn6FcOFWneWfncccIdJbomzXGW88ewmDRFOmbLoIGrrV(2BQepF8rel2VjihqycBJg8S0cgM83uL8cI88iCgAtcosNFtDZpDYNjrEeonhmZX)hw4apZGkg2KlcupKhhIph53yNnR3lENcEWXH0T0xLLHjhyRyBEyvPnOoZcuF)CE64ZWn3htie4H4CMm8b1FtfbY91lwiE7WRqcNcmbKAjpBERzOHKyOkugg2MapuST3c2w4k60osUyBYpdSpzPlSFAbEe)E4m4Nv0n8T3478FA1YXnzwkXyMHGGJevUwTCGGIzlgAtuPqULsaldKtCZl90(YNwnFqjM6VjpdSV0ymz2e)PfHQfvuYX25OUOcp9lZEDhjA(Kk7it7juazsTRcku9jPehe9g6tQk3Zucj8i)kz4ih)fXZ)jiK11fpauPqLovVxH0eKR6ioaguI8Joo1TWdzpVTwNLnv1GwQqkmwPnqgpfnDjkaxQ2LiueEGTEhvBDKb3KyHhGVIW8K8YsO3IuwxjILa7wnGK8QsFsUkivkWA4fIEuBLLPT2W(EL(nivz(I)YhWj9w2zMwHYX3wY6YHk2bB2ueMGk0GoRHPJz3oiDgWmP2(hbsWKnpkNvjgc57rRT1WK(fUKoXyTOJrfvONnEC5w5AQgvsZlk4jR3Mtme3zb4xdiMFPGORDoccIgGTgnSRVa1vaJ7VuuOBki4d4mXj8ARN1YJsCCzkC(jgjeOtF(jF70gvm1Wg5yWgbivWRvipU6(XxJ2cTsDkJOZ4nxHbN0UmRPVUNy9Z1MKdrG)bMiOdH4mao9WONFnB5mf8FJ9mxc)k3MWoNtr(lGs2CI4jxQtFOj0O5yUXQaDKHfWIDh5qHb7rPqQ2CWh7U6Xf(pXHvuLiYUMTS3knpHJnX065w4E5dB7KRIDrrWj7rqb0EZRYJDOasC(SIcooT5ul9IZaUlwApr81YX(qvhfEGyaNELFXAeY5OmFEswApFt82dJp(AcEAABYRg6TEzcdeH)2pPbhKNbZar2FGdJyA2IZGnWXEx8XHj2XAA2zKIG(OcjgkYC02Ah293DC4QtfoCrrdxsC4hRKJWhaTLDD2RHkVStX2FV2ERFbryLAk9w)T0ICcfm3bZRdeSPoG1Rx5O6V7TM)BSRvhQOb)4h8BRVXd59BERdjXuqIiV165lQdECvDWK27A2BTIBWJcW59ZlMHJXQzwzLnJwDWG6aRDjuh8eiWPCIuRtYF0PQv6qPN)tbPZVwKktK1(HcE7TgMFnWRo4(RfD2D4lSAgz5MegLLJLfIZornOeTju4SAwpsAEode3FcqWcAVF87Z89yN39eEPEekL7GHYL8TVgJhLapq4dMiKBWvP7RNHTFwJA3)K5kEdRD9AYqdaTjXM7uq30yMn0KzDG6(zt9O2KL5AdwRdgEvj7UXjKuHTrnRb1UJYgk7pE8ODh6D7AnAYEMw1nEmHDJb)VRkCUaKE40IZHDdLSkAnKRKAWqt59gGMMo6sEBYWOUbXEYjZf2KCWgBU2ryL9uqFuIQnJ7sxbW2BRHxaOj68K((FXzeSdZWd)Fi4AnC2txQS)4H29JA9iZX4u5Qi9DuBBfCpTGF9B4N8WzSJ5cesdSgAyVUtDz2IlsmmOZwYpBDHjJHYzf0pqIXwaMmwoLqBQc10btMitt7I1OXz9bNrWRo)q4lk(TBZ1e758)Ff2A3BnrjJS0zEKnUu2B2IQsODTp0UcXWQO5lS7kyZVcVKCZ2XJMJfEK0d98xCZ(D1nBFC3aUOj5tC4a1Q)8RDPpi3ARbt7LROHMUsusF0Em7IfDw8PLX9r2gkgUABBWy4RuFhT5bKPnpBBlrogugLWcjU1vu86von1Q)tZ7muljIDOwkFaHs(qLpKq5eyQFqHsVP7dlu1E0lGJobq)q44Q9)(HYXuZ)DXtkdPJEknLuJAtTJZuKDJXJXKKDcxzUE0jvz)MYG(Ot5j20jDiGoRU(bdSuawkpd3nXf3P251UePjhsnI94Ix9v7BQc3oHcnflx4Qyjk61(ERvxOLw2LNhi5cMwNXiB8F65WFZlDM2sTncqY4Z8hN8zIn5b8XQ9AXhgOgyoJWaPJHACQzox7LQ68rlTPJVWqk5yrN9c0djhJPJmzwN(gBiCXP3TCkeEL2YF(62KLNJUDoGWc)D2wUg)DGEtNPyP8rG0NtkEtzcLt6oO66O3DZNA36tdnkJzH8TSAAsQ4z2)qB7WYOuXxIELgJJufNYpZMo65d3Ay)(codT36Cyzu)TmpwF6waz652a7xlHIkuhyz6QoA7IXX4QhaYSHda739WhbaAzCFpl6KWpoLsFGnZaM(rUSFPUUQtkF0p9sTC2Q0WO20IPdb7NY1XOJD0huK17E2XbSNEIwqnnKzh95s0EHPCgUqwVBKx7aOPR33ltRsly6uAFlTJeN8SRJpscDhwBQ9njN6QfaTxmwB8mTDryQJaN4ZW0x8LhI9PyYKP((IUqeTbEtzXTFge8BuO7ldt3Dki(gZ4TMF2KUdEi9DQX01mOtipYv72lOSxxIJ(7zw(2pHQO7z)CD33VPFN99BIVuV)l]] )
|
|
|