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.
1643 lines
70 KiB
1643 lines
70 KiB
|
5 years ago
|
-- ShamanElemental.lua
|
||
|
|
-- 09.2020
|
||
|
|
|
||
|
|
local addon, ns = ...
|
||
|
|
local Hekili = _G[ addon ]
|
||
|
|
|
||
|
|
local class = Hekili.Class
|
||
|
|
local state = Hekili.State
|
||
|
|
|
||
|
|
local PTR = ns.PTR
|
||
|
|
|
||
|
|
|
||
|
|
-- Conduits
|
||
|
|
-- [x] Call of Flame
|
||
|
|
-- [-] High Voltage
|
||
|
|
-- [-] Pyroclastic Shock
|
||
|
|
-- [-] Shake the Foundations
|
||
|
|
|
||
|
|
-- Covenants
|
||
|
|
-- [-] Elysian Dirge
|
||
|
|
-- [-] Lavish Harvest
|
||
|
|
-- [-] Tumbling Waves
|
||
|
|
-- [x] Essential Extraction
|
||
|
|
|
||
|
|
-- Endurance
|
||
|
|
-- [-] Astral Protection
|
||
|
|
-- [-] Refreshing Waters
|
||
|
|
-- [x] Vital Accretion
|
||
|
|
|
||
|
|
-- Finesse
|
||
|
|
-- [x] Crippling Hex
|
||
|
|
-- [x] Spiritual Resonance
|
||
|
|
-- [x] Thunderous Paws
|
||
|
|
-- [x] Totemic Surge
|
||
|
|
|
||
|
|
|
||
|
|
if UnitClassBase( "player" ) == "SHAMAN" then
|
||
|
|
local spec = Hekili:NewSpecialization( 262, true )
|
||
|
|
|
||
|
|
spec:RegisterResource( Enum.PowerType.Maelstrom )
|
||
|
|
spec:RegisterResource( Enum.PowerType.Mana )
|
||
|
|
|
||
|
|
-- Talents
|
||
|
|
spec:RegisterTalents( {
|
||
|
|
earthen_rage = 22356, -- 170374
|
||
|
|
echo_of_the_elements = 22357, -- 333919
|
||
|
|
static_discharge = 22358, -- 342243
|
||
|
|
|
||
|
|
aftershock = 23108, -- 273221
|
||
|
|
echoing_shock = 23460, -- 320125
|
||
|
|
elemental_blast = 23190, -- 117014
|
||
|
|
|
||
|
|
spirit_wolf = 23162, -- 260878
|
||
|
|
earth_shield = 23163, -- 974
|
||
|
|
static_charge = 23164, -- 265046
|
||
|
|
|
||
|
|
master_of_the_elements = 19271, -- 16166
|
||
|
|
storm_elemental = 19272, -- 192249
|
||
|
|
liquid_magma_totem = 19273, -- 192222
|
||
|
|
|
||
|
|
natures_guardian = 22144, -- 30884
|
||
|
|
ancestral_guidance = 22172, -- 108281
|
||
|
|
wind_rush_totem = 21966, -- 192077
|
||
|
|
|
||
|
|
surge_of_power = 22145, -- 262303
|
||
|
|
primal_elementalist = 19266, -- 117013
|
||
|
|
icefury = 23111, -- 210714
|
||
|
|
|
||
|
|
unlimited_power = 21198, -- 260895
|
||
|
|
stormkeeper = 22153, -- 191634
|
||
|
|
ascendance = 21675, -- 114050
|
||
|
|
} )
|
||
|
|
|
||
|
|
-- PvP Talents
|
||
|
|
spec:RegisterPvpTalents( {
|
||
|
|
control_of_lava = 728, -- 204393
|
||
|
|
counterstrike_totem = 3490, -- 204331
|
||
|
|
grounding_totem = 3620, -- 204336
|
||
|
|
lightning_lasso = 731, -- 305483
|
||
|
|
seasoned_winds = 5415, -- 355630
|
||
|
|
skyfury_totem = 3488, -- 204330
|
||
|
|
spectral_recovery = 3062, -- 204261
|
||
|
|
static_field_totem = 727, -- 355580
|
||
|
|
swelling_waves = 3621, -- 204264
|
||
|
|
traveling_storms = 730, -- 204403
|
||
|
|
unleash_shield = 3491, -- 356736
|
||
|
|
} )
|
||
|
|
|
||
|
|
-- Auras
|
||
|
|
spec:RegisterAuras( {
|
||
|
|
ancestral_guidance = {
|
||
|
|
id = 108281,
|
||
|
|
duration = 10,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
ascendance = {
|
||
|
|
id = 114050,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
astral_shift = {
|
||
|
|
id = 108271,
|
||
|
|
duration = function () return level > 53 and 12 or 8 end,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
celestial_guidance = {
|
||
|
|
id = 324748,
|
||
|
|
duration = 10,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
earth_shield = {
|
||
|
|
id = 974,
|
||
|
|
duration = 600,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 9,
|
||
|
|
},
|
||
|
|
|
||
|
|
earthbind = {
|
||
|
|
id = 3600,
|
||
|
|
duration = 5,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
-- might be the debuff on targets
|
||
|
|
earthquake = {
|
||
|
|
id = 61882,
|
||
|
|
duration = 3600,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
echoing_shock = {
|
||
|
|
id = 320125,
|
||
|
|
duration = 8,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_blast = {
|
||
|
|
duration = 10,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 3,
|
||
|
|
generate = function ()
|
||
|
|
local eb = buff.elemental_blast
|
||
|
|
|
||
|
|
local count = ( buff.elemental_blast_critical_strike.up and 1 or 0 ) +
|
||
|
|
( buff.elemental_blast_haste.up and 1 or 0 ) +
|
||
|
|
( buff.elemental_blast_mastery.up and 1 or 0 )
|
||
|
|
local applied = max( buff.elemental_blast_critical_strike.applied,
|
||
|
|
buff.elemental_blast_haste.applied,
|
||
|
|
buff.elemental_blast_mastery.applied )
|
||
|
|
|
||
|
|
eb.name = class.abilities.elemental_blast.name or "Elemental Blast"
|
||
|
|
eb.count = count
|
||
|
|
eb.applied = applied
|
||
|
|
eb.expires = applied + 15
|
||
|
|
eb.caster = count > 0 and "player" or "nobody"
|
||
|
|
end
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_blast_critical_strike = {
|
||
|
|
id = 118522,
|
||
|
|
duration = 10,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_blast_haste = {
|
||
|
|
id = 173183,
|
||
|
|
duration = 10,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_blast_mastery = {
|
||
|
|
id = 173184,
|
||
|
|
duration = 10,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_fury = {
|
||
|
|
id = 60188,
|
||
|
|
},
|
||
|
|
|
||
|
|
far_sight = {
|
||
|
|
id = 6196,
|
||
|
|
duration = 60,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
flame_shock = {
|
||
|
|
id = 188389,
|
||
|
|
duration = function () return level > 58 and ( fire_elemental.up or storm_elemental.up ) and 36 or 18 end,
|
||
|
|
tick_time = function () return 3 * haste end,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
fleshcraft = {
|
||
|
|
id = 324631,
|
||
|
|
duration = 120,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
frost_shock = {
|
||
|
|
id = 196840,
|
||
|
|
duration = 6,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
ghost_wolf = {
|
||
|
|
id = 2645,
|
||
|
|
duration = 3600,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
icefury = {
|
||
|
|
id = 210714,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 4,
|
||
|
|
},
|
||
|
|
|
||
|
|
lava_surge = {
|
||
|
|
id = 77762,
|
||
|
|
duration = 10,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
lightning_lasso = {
|
||
|
|
id = 305484,
|
||
|
|
duration = 5,
|
||
|
|
max_stack = 1
|
||
|
|
},
|
||
|
|
|
||
|
|
lightning_shield = {
|
||
|
|
id = 192106,
|
||
|
|
duration = 1800,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
master_of_the_elements = {
|
||
|
|
id = 260734,
|
||
|
|
duration = 15,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
primordial_wave = {
|
||
|
|
id = 327164,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
reincarnation = {
|
||
|
|
id = 20608,
|
||
|
|
},
|
||
|
|
|
||
|
|
spirit_wolf = {
|
||
|
|
id = 260881,
|
||
|
|
duration = 3600,
|
||
|
|
max_stack = 4,
|
||
|
|
},
|
||
|
|
|
||
|
|
spiritwalkers_grace = {
|
||
|
|
id = 79206,
|
||
|
|
duration = 15,
|
||
|
|
type = "Magic",
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
static_discharge = {
|
||
|
|
id = 342243,
|
||
|
|
duration = 3,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
stormkeeper = {
|
||
|
|
id = 191634,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 2,
|
||
|
|
},
|
||
|
|
|
||
|
|
surge_of_power = {
|
||
|
|
id = 285514,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
surge_of_power_debuff = {
|
||
|
|
id = 285515,
|
||
|
|
duration = 6,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
thunderstorm = {
|
||
|
|
id = 51490,
|
||
|
|
duration = 5,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
unlimited_power = {
|
||
|
|
id = 272737,
|
||
|
|
duration = 10,
|
||
|
|
max_stack = 20, -- good luck reaching this...
|
||
|
|
},
|
||
|
|
|
||
|
|
water_walking = {
|
||
|
|
id = 546,
|
||
|
|
duration = 600,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
wind_rush = {
|
||
|
|
id = 192082,
|
||
|
|
duration = 5,
|
||
|
|
max_stack = 1,
|
||
|
|
},
|
||
|
|
|
||
|
|
wind_gust = {
|
||
|
|
id = 263806,
|
||
|
|
duration = 30,
|
||
|
|
max_stack = 20
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
-- Pet aura.
|
||
|
|
call_lightning = {
|
||
|
|
duration = 15,
|
||
|
|
generate = function( t, db )
|
||
|
|
if storm_elemental.up then
|
||
|
|
local name, _, count, _, duration, expires = FindUnitBuffByID( "pet", 157348 )
|
||
|
|
|
||
|
|
if name then
|
||
|
|
t.count = count
|
||
|
|
t.expires = expires
|
||
|
|
t.applied = expires - duration
|
||
|
|
t.caster = "pet"
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
t.count = 0
|
||
|
|
t.expires = 0
|
||
|
|
t.applied = 0
|
||
|
|
t.caster = "nobody"
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
-- Legendaries
|
||
|
|
-- TODO: Implement like Bloodtalons, but APL doesn't really require it mechanically.
|
||
|
|
elemental_equilibrium = {
|
||
|
|
id = 347348,
|
||
|
|
duration = 10,
|
||
|
|
max_stack = 1
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_equilibrium_debuff = {
|
||
|
|
id = 347349,
|
||
|
|
duration = 30,
|
||
|
|
max_stack = 1
|
||
|
|
}
|
||
|
|
} )
|
||
|
|
|
||
|
|
|
||
|
|
-- Pets
|
||
|
|
spec:RegisterPet( "primal_storm_elemental", 77942, "storm_elemental", 30 )
|
||
|
|
spec:RegisterTotem( "greater_storm_elemental", 1020304 ) -- Texture ID
|
||
|
|
|
||
|
|
spec:RegisterPet( "primal_fire_elemental", 61029, "fire_elemental", 30 )
|
||
|
|
spec:RegisterTotem( "greater_fire_elemental", 135790 ) -- Texture ID
|
||
|
|
|
||
|
|
spec:RegisterPet( "primal_earth_elemental", 61056, "earth_elemental", 60 )
|
||
|
|
spec:RegisterTotem( "greater_earth_elemental", 136024 ) -- Texture ID
|
||
|
|
|
||
|
|
spec:RegisterTotem( "liquid_magma_totem", 971079 )
|
||
|
|
spec:RegisterTotem( "tremor_totem", 136108 )
|
||
|
|
spec:RegisterTotem( "vesper_totem", 3565451 )
|
||
|
|
spec:RegisterTotem( "wind_rush_totem", 538576 )
|
||
|
|
|
||
|
|
|
||
|
|
spec:RegisterStateTable( "fire_elemental", setmetatable( { onReset = function( self ) self.cast_time = nil end }, {
|
||
|
|
__index = function( t, k )
|
||
|
|
if k == "cast_time" then
|
||
|
|
t.cast_time = class.abilities.fire_elemental.lastCast or 0
|
||
|
|
return t.cast_time
|
||
|
|
end
|
||
|
|
|
||
|
|
local elem = talent.primal_elementalist.enabled and pet.primal_fire_elemental or pet.greater_fire_elemental
|
||
|
|
|
||
|
|
if k == "active" or k == "up" then
|
||
|
|
return elem.up
|
||
|
|
|
||
|
|
elseif k == "down" then
|
||
|
|
return not elem.up
|
||
|
|
|
||
|
|
elseif k == "remains" then
|
||
|
|
return max( 0, elem.remains )
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
} ) )
|
||
|
|
|
||
|
|
spec:RegisterStateTable( "storm_elemental", setmetatable( { onReset = function( self ) self.cast_time = nil end }, {
|
||
|
|
__index = function( t, k )
|
||
|
|
if k == "cast_time" then
|
||
|
|
t.cast_time = class.abilities.storm_elemental.lastCast or 0
|
||
|
|
return t.cast_time
|
||
|
|
end
|
||
|
|
|
||
|
|
local elem = talent.primal_elementalist.enabled and pet.primal_storm_elemental or pet.greater_storm_elemental
|
||
|
|
|
||
|
|
if k == "active" or k == "up" then
|
||
|
|
return elem.up
|
||
|
|
|
||
|
|
elseif k == "down" then
|
||
|
|
return not elem.up
|
||
|
|
|
||
|
|
elseif k == "remains" then
|
||
|
|
return max( 0, elem.remains )
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
} ) )
|
||
|
|
|
||
|
|
spec:RegisterStateTable( "earth_elemental", setmetatable( { onReset = function( self ) self.cast_time = nil end }, {
|
||
|
|
__index = function( t, k )
|
||
|
|
if k == "cast_time" then
|
||
|
|
t.cast_time = class.abilities.earth_elemental.lastCast or 0
|
||
|
|
return t.cast_time
|
||
|
|
end
|
||
|
|
|
||
|
|
local elem = talent.primal_elementalist.enabled and pet.primal_earth_elemental or pet.greater_earth_elemental
|
||
|
|
|
||
|
|
if k == "active" or k == "up" then
|
||
|
|
return elem.up
|
||
|
|
|
||
|
|
elseif k == "down" then
|
||
|
|
return not elem.up
|
||
|
|
|
||
|
|
elseif k == "remains" then
|
||
|
|
return max( 0, elem.remains )
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
} ) )
|
||
|
|
|
||
|
|
|
||
|
|
spec:RegisterHook( "reset_precast", function ()
|
||
|
|
if talent.master_of_the_elements.enabled and action.lava_burst.in_flight and buff.master_of_the_elements.down then
|
||
|
|
applyBuff( "master_of_the_elements" )
|
||
|
|
end
|
||
|
|
|
||
|
|
rawset( state.pet, "earth_elemental", talent.primal_elementalist.enabled and state.pet.primal_earth_elemental or state.pet.greater_earth_elemental )
|
||
|
|
rawset( state.pet, "fire_elemental", talent.primal_elementalist.enabled and state.pet.primal_fire_elemental or state.pet.greater_fire_elemental )
|
||
|
|
rawset( state.pet, "storm_elemental", talent.primal_elementalist.enabled and state.pet.primal_storm_elemental or state.pet.greater_storm_elemental )
|
||
|
|
end )
|
||
|
|
|
||
|
|
|
||
|
|
-- Abilities
|
||
|
|
spec:RegisterAbilities( {
|
||
|
|
ancestral_guidance = {
|
||
|
|
id = 108281,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 120,
|
||
|
|
gcd = "off",
|
||
|
|
|
||
|
|
talent = "ancestral_guidance",
|
||
|
|
toggle = "defensives",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 538564,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "ancestral_guidance" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
ancestral_spirit = {
|
||
|
|
id = 2008,
|
||
|
|
cast = 10,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.04,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136077,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
ascendance = {
|
||
|
|
id = 114050,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 180,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
talent = "ascendance",
|
||
|
|
toggle = "cooldowns",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 135791,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "ascendance" )
|
||
|
|
gainCharges( "lava_burst", 2 )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
astral_recall = {
|
||
|
|
id = 556,
|
||
|
|
cast = function () return 10 * haste end,
|
||
|
|
cooldown = 600,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136010,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
astral_shift = {
|
||
|
|
id = 108271,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 90,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
toggle = "defensives",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 538565,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "astral_shift" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
bloodlust = {
|
||
|
|
id = 2825,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 300,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.22,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
toggle = "cooldowns",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136012,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "bloodlust" )
|
||
|
|
applyDebuff( "player", "sated" )
|
||
|
|
if conduit.spiritual_resonance.enabled then
|
||
|
|
applyBuff( "spiritwalkers_grace", conduit.spiritual_resonance.mod * 0.001 )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
capacitor_totem = {
|
||
|
|
id = 192058,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = function () return 60 + ( conduit.totemic_surge.mod * 0.001 ) end,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.1,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136013,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
--[[ chain_harvest = {
|
||
|
|
id = 320674,
|
||
|
|
cast = function () return 2.5 * haste end,
|
||
|
|
cooldown = 90,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
toggle = "covenant",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 3565725,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
}, ]]
|
||
|
|
|
||
|
|
chain_heal = {
|
||
|
|
id = 1064,
|
||
|
|
cast = function ()
|
||
|
|
if buff.chains_of_devastation_ch.up then return 0 end
|
||
|
|
return 2.5 * haste
|
||
|
|
end,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.3,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136042,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "chains_of_devastation_ch" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
|
||
|
|
if legendary.chains_of_devastation.enabled then
|
||
|
|
applyBuff( "chains_of_devastation_cl" )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
chain_lightning = {
|
||
|
|
id = 188443,
|
||
|
|
cast = function () return ( buff.stormkeeper.up or buff.chains_of_devastation_cl.up ) and 0 or ( 2 * haste ) end,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
nobuff = "ascendance",
|
||
|
|
bind = "lava_beam",
|
||
|
|
|
||
|
|
spend = 0.01,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136015,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "master_of_the_elements" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
removeBuff( "chains_of_devastation_cl" )
|
||
|
|
|
||
|
|
if legendary.chains_of_devastation.enabled then
|
||
|
|
applyBuff( "chains_of_devastation_ch" )
|
||
|
|
end
|
||
|
|
|
||
|
|
-- 4 MS per target, direct.
|
||
|
|
-- 3 MS per target, overload.
|
||
|
|
|
||
|
|
gain( ( buff.stormkeeper.up and 7 or 4 ) * min( 5, active_enemies ), "maelstrom" )
|
||
|
|
removeStack( "stormkeeper" )
|
||
|
|
|
||
|
|
if pet.storm_elemental.up then
|
||
|
|
addStack( "wind_gust", nil, 1 )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
cleanse_spirit = {
|
||
|
|
id = 51886,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 8,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.06,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 236288,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
earth_elemental = {
|
||
|
|
id = 198103,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 300,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
toggle = "defensives",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136024,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonPet( talent.primal_elementalist.enabled and "primal_earth_elemental" or "greater_earth_elemental", 60 )
|
||
|
|
if conduit.vital_accretion.enabled then
|
||
|
|
applyBuff( "vital_accretion" )
|
||
|
|
health.max = health.max * ( 1 + ( conduit.vital_accretion.mod * 0.01 ) )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
|
||
|
|
usable = function ()
|
||
|
|
return max( cooldown.fire_elemental.true_remains, cooldown.storm_elemental.true_remains ) > 0, "DPS elementals must be on CD first"
|
||
|
|
end,
|
||
|
|
|
||
|
|
timeToReady = function ()
|
||
|
|
return max( pet.fire_elemental.remains, pet.storm_elemental.remains, pet.primal_fire_elemental.remains, pet.primal_storm_elemental.remains )
|
||
|
|
end,
|
||
|
|
|
||
|
|
auras = {
|
||
|
|
-- Conduit
|
||
|
|
vital_accretion = {
|
||
|
|
id = 337984,
|
||
|
|
duration = 60,
|
||
|
|
max_stack = 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
earth_shield = {
|
||
|
|
id = 974,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.1,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
talent = "earth_shield",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136089,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "earth_shield" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
earth_shock = {
|
||
|
|
id = 8042,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 60,
|
||
|
|
spendType = "maelstrom",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136026,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
if talent.surge_of_power.enabled then
|
||
|
|
applyBuff( "surge_of_power" )
|
||
|
|
end
|
||
|
|
|
||
|
|
if runeforge.echoes_of_great_sundering.enabled then
|
||
|
|
applyBuff( "echoes_of_great_sundering" )
|
||
|
|
end
|
||
|
|
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
earthbind_totem = {
|
||
|
|
id = 2484,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 30,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.02,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136102,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
earthquake = {
|
||
|
|
id = 61882,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 60,
|
||
|
|
spendType = "maelstrom",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 451165,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "echoes_of_great_sundering" )
|
||
|
|
removeBuff( "master_of_the_elements" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
end,
|
||
|
|
|
||
|
|
auras = {
|
||
|
|
echoes_of_great_sundering = {
|
||
|
|
id = 336217,
|
||
|
|
duration = 25,
|
||
|
|
max_stack = 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
echoing_shock = {
|
||
|
|
id = 320125,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 30,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.03,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 1603013,
|
||
|
|
|
||
|
|
talent = "echoing_shock",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "echoing_shock" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
elemental_blast = {
|
||
|
|
id = 117014,
|
||
|
|
cast = function () return 2 * haste end,
|
||
|
|
cooldown = 12,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = -30,
|
||
|
|
spendType = "maelstrom",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 651244,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "elemental_blast" )
|
||
|
|
|
||
|
|
if talent.surge_of_power.enabled then
|
||
|
|
applyBuff( "surge_of_power" )
|
||
|
|
end
|
||
|
|
|
||
|
|
if runeforge.echoes_of_great_sundering.enabled then
|
||
|
|
applyBuff( "echoes_of_great_sundering" )
|
||
|
|
end
|
||
|
|
|
||
|
|
removeBuff( "master_of_the_elements" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
far_sight = {
|
||
|
|
id = 6196,
|
||
|
|
cast = function () return 2 * haste end,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136034,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
fire_elemental = {
|
||
|
|
id = 198067,
|
||
|
|
cast = 0,
|
||
|
|
charges = 1,
|
||
|
|
cooldown = 150,
|
||
|
|
recharge = 150,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.05,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
toggle = "cooldowns",
|
||
|
|
notalent = "storm_elemental",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 135790,
|
||
|
|
|
||
|
|
|
||
|
|
timeToReady = function ()
|
||
|
|
return max( pet.earth_elemental.remains, pet.primal_earth_elemental.remains, pet.storm_elemental.remains, pet.primal_storm_elemental.remains )
|
||
|
|
end,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonPet( talent.primal_elementalist.enabled and "primal_fire_elemental" or "greater_fire_elemental", 30 * ( 1 + ( 0.01 * conduit.call_of_flame.mod ) ) )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
flame_shock = {
|
||
|
|
id = 188389,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 6,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.02,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 135813,
|
||
|
|
|
||
|
|
cycle = "flame_shock",
|
||
|
|
min_ttd = function () return debuff.flame_shock.duration / 3 end,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyDebuff( "target", "flame_shock" )
|
||
|
|
|
||
|
|
if buff.surge_of_power.up then
|
||
|
|
active_dot.surge_of_power = min( active_enemies, active_dot.flame_shock + 1 )
|
||
|
|
removeBuff( "surge_of_power" )
|
||
|
|
end
|
||
|
|
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
frost_shock = {
|
||
|
|
id = 196840,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.02,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 135849,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "master_of_the_elements" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
|
||
|
|
applyDebuff( "target", "frost_shock" )
|
||
|
|
|
||
|
|
if buff.icefury.up then
|
||
|
|
gain( 8, "maelstrom" )
|
||
|
|
removeStack( "icefury", 1 )
|
||
|
|
end
|
||
|
|
|
||
|
|
if buff.surge_of_power.up then
|
||
|
|
applyDebuff( "target", "surge_of_power_debuff" )
|
||
|
|
removeBuff( "surge_of_power" )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
ghost_wolf = {
|
||
|
|
id = 2645,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136095,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "ghost_wolf" )
|
||
|
|
if talent.spirit_wolf.enabled then applyBuff( "spirit_wolf" ) end
|
||
|
|
if conduit.thunderous_paws.enabled then applyBuff( "thunderous_paws" ) end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
healing_stream_totem = {
|
||
|
|
id = 5394,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 30,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.09,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 135127,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
healing_surge = {
|
||
|
|
id = 8004,
|
||
|
|
cast = function () return 1.5 * haste end,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.24,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 136044,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
hex = {
|
||
|
|
id = 51514,
|
||
|
|
cast = function () return 1.7 * haste end,
|
||
|
|
cooldown = function () return level > 55 and 20 or 30 end,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 237579,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyDebuff( "target", "hex" )
|
||
|
|
end,
|
||
|
|
|
||
|
|
auras = {
|
||
|
|
-- Conduit
|
||
|
|
crippling_hex = {
|
||
|
|
id = 338055,
|
||
|
|
duration = 8,
|
||
|
|
max_stack = 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
icefury = {
|
||
|
|
id = 210714,
|
||
|
|
cast = 2,
|
||
|
|
cooldown = 30,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.03,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 135855,
|
||
|
|
|
||
|
|
talent = "icefury",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "master_of_the_elements" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
|
||
|
|
applyBuff( "icefury", 15, 4 )
|
||
|
|
gain( 25, "maelstrom" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
lava_beam = {
|
||
|
|
id = 114074,
|
||
|
|
cast = function () return 2 * haste end,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
buff = "ascendance",
|
||
|
|
bind = "chain_lightning",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 236216,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
|
||
|
|
-- 4 MS per target, direct.
|
||
|
|
-- 3 MS per target, overload.
|
||
|
|
|
||
|
|
gain( ( buff.stormkeeper.up and 7 or 4 ) * min( 5, active_enemies ), "maelstrom" )
|
||
|
|
removeStack( "stormkeeper" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
lava_burst = {
|
||
|
|
id = 51505,
|
||
|
|
cast = function () return buff.lava_surge.up and 0 or ( 2 * haste ) end,
|
||
|
|
charges = function () return talent.echo_of_the_elements.enabled and 2 or nil end,
|
||
|
|
cooldown = function () return buff.ascendance.up and 0 or ( 8 * haste ) end,
|
||
|
|
recharge = function () return buff.ascendance.up and 0 or ( 8 * haste ) end,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.06,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 237582,
|
||
|
|
|
||
|
|
velocity = 30,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "lava_surge" )
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
|
||
|
|
gain( 10, "maelstrom" )
|
||
|
|
|
||
|
|
if talent.master_of_the_elements.enabled then applyBuff( "master_of_the_elements" ) end
|
||
|
|
|
||
|
|
if talent.surge_of_power.enabled then
|
||
|
|
gainChargeTime( "fire_elemental", 6 )
|
||
|
|
removeBuff( "surge_of_power" )
|
||
|
|
end
|
||
|
|
|
||
|
|
if buff.primordial_wave.up and state.spec.elemental and legendary.splintered_elements.enabled then
|
||
|
|
applyBuff( "splintered_elements", nil, active_dot.flame_shock )
|
||
|
|
end
|
||
|
|
removeBuff( "primordial_wave" )
|
||
|
|
end,
|
||
|
|
|
||
|
|
impact = function () end, -- This + velocity makes action.lava_burst.in_flight work in APL logic.
|
||
|
|
},
|
||
|
|
|
||
|
|
lightning_bolt = {
|
||
|
|
id = 188196,
|
||
|
|
cast = function () return buff.stormkeeper.up and 0 or ( 2 * haste ) end,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
essential = true,
|
||
|
|
|
||
|
|
spend = 0.02,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136048,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
|
||
|
|
gain( ( buff.stormkeeper.up and 11 or 8 ) + ( buff.surge_of_power.up and 3 or 0 ), "maelstrom" )
|
||
|
|
|
||
|
|
removeBuff( "master_of_the_elements" )
|
||
|
|
removeBuff( "surge_of_power" )
|
||
|
|
|
||
|
|
removeStack( "stormkeeper" )
|
||
|
|
|
||
|
|
if pet.storm_elemental.up then
|
||
|
|
addStack( "wind_gust", nil, 1 )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
lightning_lasso = {
|
||
|
|
id = 305483,
|
||
|
|
cast = function () return 5 * haste end,
|
||
|
|
channeled = true,
|
||
|
|
cooldown = 30,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 1385911,
|
||
|
|
|
||
|
|
pvptalent = function ()
|
||
|
|
if essence.conflict_and_strife.major then return end
|
||
|
|
return "lightning_lasso"
|
||
|
|
end,
|
||
|
|
|
||
|
|
start = function ()
|
||
|
|
removeBuff( "echoing_shock" )
|
||
|
|
applyDebuff( "target", "lightning_lasso" )
|
||
|
|
end,
|
||
|
|
|
||
|
|
copy = 305485
|
||
|
|
},
|
||
|
|
|
||
|
|
lightning_shield = {
|
||
|
|
id = 192106,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.02,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136051,
|
||
|
|
|
||
|
|
readyTime = function () return buff.lightning_shield.remains - 120 end,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "lightning_shield" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
liquid_magma_totem = {
|
||
|
|
id = 192222,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 60,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
toggle = "cooldowns",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 971079,
|
||
|
|
|
||
|
|
talent = "liquid_magma_totem",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonTotem( "liquid_magma_totem" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
primal_strike = {
|
||
|
|
id = 73899,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.09,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 460956,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
purge = {
|
||
|
|
id = 370,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.1,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136075,
|
||
|
|
|
||
|
|
toggle = "interrupts",
|
||
|
|
interrupt = true,
|
||
|
|
|
||
|
|
buff = "dispellable_magic",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "dispellable_magic" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
spiritwalkers_grace = {
|
||
|
|
id = 79206,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 120,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.14,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 451170,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "spiritwalkers_grace" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
static_discharge = {
|
||
|
|
id = 342243,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 30,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.03,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = off,
|
||
|
|
texture = 135845,
|
||
|
|
|
||
|
|
talent = "static_discharge",
|
||
|
|
buff = "lightning_shield",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "static_discharge" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
storm_elemental = {
|
||
|
|
id = 192249,
|
||
|
|
cast = 0,
|
||
|
|
charges = 1,
|
||
|
|
cooldown = 150,
|
||
|
|
recharge = 150,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
toggle = "cooldowns",
|
||
|
|
talent = "storm_elemental",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 2065626,
|
||
|
|
|
||
|
|
timeToReady = function ()
|
||
|
|
return max( pet.earth_elemental.remains, pet.primal_earth_elemental.remains, pet.fire_elemental.remains, pet.primal_fire_elemental.remains )
|
||
|
|
end,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonPet( talent.primal_elementalist.enabled and "primal_storm_elemental" or "greater_storm_elemental", 30 * ( 1 + ( 0.01 * conduit.call_of_flame.mod ) ) )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
stormkeeper = {
|
||
|
|
id = 191634,
|
||
|
|
cast = function () return 1.5 * haste end,
|
||
|
|
cooldown = 60,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
toggle = "cooldowns",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 839977,
|
||
|
|
|
||
|
|
talent = "stormkeeper",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "stormkeeper", 20, 2 )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
thunderstorm = {
|
||
|
|
id = 51490,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 45,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 237589,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
if target.within10 then applyDebuff( "target", "thunderstorm" ) end
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
tremor_totem = {
|
||
|
|
id = 8143,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = function () return 60 + ( conduit.totemic_surge.mod * 0.001 ) end,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.02,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136108,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonTotem( "tremor_totem" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
water_walking = {
|
||
|
|
id = 546,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 135863,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyBuff( "water_walking" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
wind_rush_totem = {
|
||
|
|
id = 192077,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 120,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 538576,
|
||
|
|
|
||
|
|
talent = "wind_rush_totem",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonTotem( "wind_rush_totem" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
wind_shear = {
|
||
|
|
id = 57994,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 12,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 136018,
|
||
|
|
|
||
|
|
toggle = "interrupts",
|
||
|
|
|
||
|
|
debuff = "casting",
|
||
|
|
readyTime = state.timeToInterrupt,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
interrupt()
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
-- Pet Abilities
|
||
|
|
meteor = {
|
||
|
|
id = 117588,
|
||
|
|
known = function () return talent.primal_elementalist.enabled and not talent.storm_elemental.enabled and fire_elemental.up end,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 60,
|
||
|
|
gcd = "off",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 1033911,
|
||
|
|
|
||
|
|
talent = "primal_elementalist",
|
||
|
|
|
||
|
|
usable = function () return fire_elemental.up end,
|
||
|
|
handler = function () end,
|
||
|
|
},
|
||
|
|
|
||
|
|
eye_of_the_storm = {
|
||
|
|
id = 157375,
|
||
|
|
known = function () return talent.primal_elementalist.enabled and talent.storm_elemental.enabled and storm_elemental.up end,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 40,
|
||
|
|
gcd = "off",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
-- texture = ,
|
||
|
|
|
||
|
|
talent = "primal_elementalist",
|
||
|
|
|
||
|
|
usable = function () return storm_elemental.up end,
|
||
|
|
handler = function () end,
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
-- Shaman - Kyrian - 324386 - vesper_totem (Vesper Totem)
|
||
|
|
vesper_totem = {
|
||
|
|
id = 324386,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 60,
|
||
|
|
gcd = "totem",
|
||
|
|
|
||
|
|
spend = 0.1,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 3565451,
|
||
|
|
|
||
|
|
toggle = "essences",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
summonPet( "vesper_totem", 30 )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
-- Shaman - Necrolord - 326059 - primordial_wave (Primordial Wave)
|
||
|
|
primordial_wave = {
|
||
|
|
id = 326059,
|
||
|
|
cast = 0,
|
||
|
|
cooldown = 45,
|
||
|
|
recharge = 45,
|
||
|
|
charges = 1,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.1,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 3578231,
|
||
|
|
|
||
|
|
toggle = "essences",
|
||
|
|
|
||
|
|
cycle = "flame_shock",
|
||
|
|
velocity = 45,
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
applyDebuff( "target", "flame_shock" )
|
||
|
|
applyBuff( "primordial_wave" )
|
||
|
|
end,
|
||
|
|
|
||
|
|
auras = {
|
||
|
|
primordial_wave = {
|
||
|
|
id = 327164,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 1
|
||
|
|
},
|
||
|
|
splintered_elements = {
|
||
|
|
id = 354648,
|
||
|
|
duration = 10,
|
||
|
|
max_stack = 10,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
-- Shaman - Night Fae - 328923 - fae_transfusion (Fae Transfusion)
|
||
|
|
fae_transfusion = {
|
||
|
|
id = 328923,
|
||
|
|
cast = function () return haste * 3 * ( 1 + ( conduit.essential_extraction.mod * 0.01 ) ) end,
|
||
|
|
channeled = true,
|
||
|
|
cooldown = 120,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.075,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 3636849,
|
||
|
|
|
||
|
|
toggle = "essences",
|
||
|
|
nobuff = "fae_transfusion",
|
||
|
|
|
||
|
|
start = function ()
|
||
|
|
applyBuff( "fae_transfusion" )
|
||
|
|
end,
|
||
|
|
|
||
|
|
tick = function ()
|
||
|
|
if legendary.seeds_of_rampant_growth.enabled then
|
||
|
|
if state.spec.enhancement then reduceCooldown( "feral_spirit", 7 )
|
||
|
|
elseif state.spec.elemental then reduceCooldown( talent.storm_elemental.enabled and "storm_elemental" or "fire_elemental", 6 )
|
||
|
|
else reduceCooldown( "healing_tide_totem", 5 ) end
|
||
|
|
addStack( "seeds_of_rampant_growth" )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
|
||
|
|
finish = function ()
|
||
|
|
if state.spec.enhancement then addStack( "maelstrom_weapon", nil, 3 ) end
|
||
|
|
end,
|
||
|
|
|
||
|
|
auras = {
|
||
|
|
fae_transfusion = {
|
||
|
|
id = 328933,
|
||
|
|
duration = 20,
|
||
|
|
max_stack = 1
|
||
|
|
},
|
||
|
|
seeds_of_rampant_growth = {
|
||
|
|
id = 358945,
|
||
|
|
duration = 15,
|
||
|
|
max_stack = 5
|
||
|
|
}
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
fae_transfusion_heal = {
|
||
|
|
id = 328930,
|
||
|
|
cast = 0,
|
||
|
|
channeled = true,
|
||
|
|
cooldown = 0,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
startsCombat = false,
|
||
|
|
texture = 3636849,
|
||
|
|
|
||
|
|
buff = "fae_transfusion",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
removeBuff( "fae_transfusion" )
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
|
||
|
|
-- Shaman - Venthyr - 320674 - chain_harvest (Chain Harvest)
|
||
|
|
chain_harvest = {
|
||
|
|
id = 320674,
|
||
|
|
cast = 2.5,
|
||
|
|
cooldown = 90,
|
||
|
|
gcd = "spell",
|
||
|
|
|
||
|
|
spend = 0.1,
|
||
|
|
spendType = "mana",
|
||
|
|
|
||
|
|
startsCombat = true,
|
||
|
|
texture = 3565725,
|
||
|
|
|
||
|
|
toggle = "essences",
|
||
|
|
|
||
|
|
handler = function ()
|
||
|
|
if legendary.elemental_conduit.enabled then
|
||
|
|
applyDebuff( "target", "flame_shock" )
|
||
|
|
active_dot.flame_shock = min( active_enemies, active_dot.flame_shock + min( 5, active_enemies ) )
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
} )
|
||
|
|
|
||
|
|
|
||
|
|
--[[ spec:RegisterSetting( "funnel_damage", false, {
|
||
|
|
name = "Funnel AOE -> Target",
|
||
|
|
desc = function ()
|
||
|
|
local s = "If checked, the addon's default priority will encourage you to spread |T135813:0|t Flame Shock but will focus damage on your current target, using |T136026:0|t Earth Shock rather than |T451165:0|t Earthquake."
|
||
|
|
|
||
|
|
if not Hekili.DB.profile.specs[ state.spec.id ].cycle then
|
||
|
|
s = s .. "\n\n|cFFFF0000Requires 'Recommend Target Swaps' on Targeting tab.|r"
|
||
|
|
end
|
||
|
|
|
||
|
|
return s
|
||
|
|
end,
|
||
|
|
type = "toggle",
|
||
|
|
width = 1.5
|
||
|
|
} ) ]]
|
||
|
|
|
||
|
|
|
||
|
|
spec:RegisterStateExpr( "funneling", function ()
|
||
|
|
return false
|
||
|
|
-- return active_enemies > 1 and settings.cycle and settings.funnel_damage
|
||
|
|
end )
|
||
|
|
|
||
|
|
|
||
|
|
spec:RegisterSetting( "stack_buffer", 1.1, {
|
||
|
|
name = "|T135855:0|t Icefury and |T839977:0|t Stormkeeper Padding",
|
||
|
|
desc = "The default priority tries to avoid wasting |T839977:0|t Stormkeeper and |T135855:0|t Icefury stacks with a grace period of 1.1 GCD per stack.\n\n" ..
|
||
|
|
"Increasing this number will reduce the likelihood of wasted Icefury / Stormkeeper stacks due to other procs taking priority, and leave you with more time to react.",
|
||
|
|
type = "range",
|
||
|
|
min = 1,
|
||
|
|
max = 2,
|
||
|
|
step = 0.01,
|
||
|
|
width = "full"
|
||
|
|
} )
|
||
|
|
|
||
|
|
|
||
|
|
spec:RegisterOptions( {
|
||
|
|
enabled = true,
|
||
|
|
|
||
|
|
aoe = 3,
|
||
|
|
|
||
|
|
nameplates = false,
|
||
|
|
nameplateRange = 8,
|
||
|
|
|
||
|
|
damage = true,
|
||
|
|
damageDots = true,
|
||
|
|
damageExpiration = 8,
|
||
|
|
|
||
|
|
potion = "potion_of_spectral_intellect",
|
||
|
|
|
||
|
|
package = "Elemental",
|
||
|
|
} )
|
||
|
|
|
||
|
|
--[[ spec:RegisterSetting( "micromanage_pets", true, {
|
||
|
|
name = "Micromanage Primal Elemental Pets",
|
||
|
|
desc = "If checked, Meteor, Eye of the Storm, etc. will appear in your recommendations.",
|
||
|
|
type = "toggle",
|
||
|
|
width = 1.5
|
||
|
|
} ) ]]
|
||
|
|
|
||
|
|
spec:RegisterPack( "Elemental", 20210707, [[dGeDecqiKkpsqPAtiXNakYOevCkrQwLGIELiLzjIClGOODHYVernmGshtqAzIk9mGitdOQUgqHTjOKVbevJdOkoNGcTobfyEaH7HK2hqYbbkQAHcIhkOGMiqrLUiqvYhbkQ4KafLvIumtGO0nfukXork9tGOqlvqPupfrtvq1vfukPVcefmwbLI9sXFjAWcDyQwmKEmLMmcxwzZs5ZagTaNwLxlcZwv3gIDl53OA4IYXbQSCOEoOPt66s12fv9DGuJhOk15rQA(IK9tytOMWnKeUodT5c2CdfSGCWcYzGf8agGpiLRHuPpBgYm3MWbMHSCKzibV(HSs93qM50)CNWeUHeY7y7mKbQMbddsozGtd6Omlhjz4H0FxpEzXEttgEi2KnKO97vWSYGAijCDgAZfS5gkyb5GfKZal4bma)Cb5gsy2SgAZnSY1qgCeeRmOgsIbTgsWRFiRu)frYahXlbn00F6frqEsIyUGn3qf0iOjmmWlGbdde0aYuebZklhNXXUoreovVcaYGQBtir7T2WIyJJfrWm7ADm9jjIKkhJKylByMGgqMIiyEccrmSLPJJfrVierWl6NiYBIOgmrKu5yer0b8RygYmmVD)mKH9WUicE9dzL6Visg4iEjOjSh2frA6p9IiipjrmxWMBOcAe0e2d7IyyyGxadggiOjSh2frqMIiywz54mo21jIWP6vaqguDBcjAV1gweBCSicMzxRJPpjrKu5yKeBzdZe0e2d7IiitrempbHig2Y0XXIOxeIi4f9te5nrudMisQCmIi6a(vmbncAc7Ii4f49SDDeI4Ypm9IOEite1GjIUv5yr8GION3V3r)Xe04w94fKLHNLJG6k15ynqUFiRu)t6AuPt9FLYYWhI)Y9dzL6)bv2kh9hHGMWUig2kCIiPYXij2YgweZWZYrqDve71piueHCKjIobbueb99VicZCqxIiKZlMGg3QhVGSm8SCeuxtJAYTFWal2BAsxJkK3F0RiyzDO2)jhUNPhVsLcY7p6veS88317NeY)8RubnUvpEbzz4z5iOUMg1KHkhJKylB4KUgv1)vkdQCmsITSHzRC0FeuYb7hHC5xPmNGaYS8EPGaKsLc7hHC5xPmNGaYUcuGbytxqJB1JxqwgEwocQRPrn52HNC)qwP(lOXT6Xlildplhb110OM8(HSs9xI(out6Auv)xPS9dzL6Ve9DOYw5O)iOaZ2)s1XatHmBGFL8pGaTUcaeGKGMWUigYSEhoreKnFiIyGdfrxevSNFViQhYsse1GjIobbVeXS3TdkIHPgCqrCLIPpmfrEjIHHG5kInowebjreolViGIOYfrpp)iercEh9hitq28HiI8seZ6)Ze04w94fKLHNLJG6AAut(98UeTJHAs)vtAjOcsjDnQ0P(Vsz7hYk1Fj67qLTYr)rqbMT)LQJbMcz2a)k5FabADfaiaPuPq7TgdQCmsITSHz9mbnUvpEbzz4z5iOUMg1KTb(vY)ac06kGKUgv6u)xPS9dzL6Ve9DOYw5O)iOaZ2)s1XatHmBGFL8pGaTUcauubjk0H2Bngu5yKeBzdZ6zcACRE8cYYWZYrqDnnQjNX1JxcAe0e2frWSshg3ZurK3erRdvitqJB1JxW0OMmOVIqcdMJf04w94fmnQjdZo8PG2)eddLay3UKq45VcGAOcACRE8cMg1KZ46XlbnUvpEbtJAYD4KNoeOGg3QhVGPrn527itcd42ejDnQ5qN6)kLTFiRu)LOVdv2kh9hr6uOtpBIRaOqx2ugu5ye5(HSs9N5w9Ypk5aZ2)s1XatHmBGFL8pGaTUcaeGuQuQ)RugId1HL8MudMC)qwPq2kh9hrQu4ETghdmgmb9O45jggkB3W0ljgYbhBGRFzzJiDbnUvpEbtJAYz4dHJjo)LG2ZVKS0B)jvhdmfsn0KUgv6q7TgldFiCmX5Ve0E(X6zuYHUSPmOYXiY9dzL6pZT6LFPsbZ2)s1XatHmBGFL8pGaTUcaeGef0ERXa9vesGouzq1TjarUGnvkiV)OxrW(5esu6Ld82rY(Xw5O)isNsoWS9VuDmWuiZg4xj)diqRRaabyKkL6)kLH4qDyjVj1Gj3pKvkKTYr)rKkfUxRXXaJbtqpkEEIHHY2nm9sIHCWXg46xw2isLcY7p6veSFoHeLE5aVDKSFSvo6pI0f04w94fmnQj3Ehzsya3MiPRrLo9SjUcGso0LnLbvogrUFiRu)zUvV8lvky2(xQogykKzd8RK)beO1vaGaKOG2BngOVIqc0HkdQUnbiYfSPtjhy2(xQogykKzd8RK)beO1vaGaKsLs9FLYqCOoSK3KAWK7hYkfYw5O)isLc3R14yGXGjOhfppXWqz7gMEjXqo4ydC9llBePlOXT6XlyAutUD4j3pKvQ)cACRE8cMg1KrMoowqJB1JxW0OMm6Z5eYwhtFsxJkDQ)RuMdTRi8Yo2kh9hrQuO9wJ5q7kcVSJ1ZsLYY5pbh0fZH2veEzhdpe)kiOadWkOXT6XlyAutgDy4WjUciPRrLo1)vkZH2veEzhBLJ(Jivk0ERXCODfHx2X6zcACRE8cMg1KBhEOpNtK01OsN6)kL5q7kcVSJTYr)rKkfAV1yo0UIWl7y9SuPSC(tWbDXCODfHx2XWdXVcckWaScACRE8cMg1K9YoOI9xA9)t6AuPt9FLYCODfHx2Xw5O)isLcT3AmhAxr4LDSEwQuwo)j4GUyo0UIWl7y4H4xbbfyawbnUvpEbtJAYOoGK3Kk(SjGjDnQ0P(Vszo0UIWl7yRC0FePsrhAV1yo0UIWl7y9mbnUvpEbtJAY5hmByPY1HiOXT6XlyAutU5tQyVGTo84vsxJQLNFLxkRoGav28rHoCVwJJbgdUraL8Me7izEPsamh0AaBGRFzzJGso0P(VsziouhwYBsnyY9dzLczRC0FePsH2BngId1HL8MudMC)qwPqwplDkWS9VuDmWuiZg4xj)diqRRaabijOXT6XlyAutU5tQyVGTo84vsxJQLNFLxkRoGav28rb3R14yGXGBeqjVjXosMxQeaZbTgWg46xw2iOKdDQ)RugId1HL8MudMC)qwPq2kh9hrQuO9wJH4qDyjVj1Gj3pKvkK1ZsLcMT)LQJbMcz2a)k5FabADfaOOcsPtjhlN)eCqxS2HNC)qwP(ZWdXVccQCbBQuwo)j4GUyqLJrK7hYk1FgEi(vqqLlytxqJB1JxW0OMmUxs3QhVK)b1KkhzuD(s6AuDRE5NC1qUbbvUuYbMT)LQJbMcz2a)k5FabADfaOYnvky2(xQogykK9EExIohbu5MUGg3QhVGPrnzCVKUvpEj)dQjvoYOcVc4NuDmW0KGk(Sk1qt6AuPt9FLYGkhJi3pKvQ)Svo6pckUvV8tUAi3GGGAUcACRE8cMg1KX9s6w94L8pOMu5iJkCs4va)KQJbMMeuXNvPgAsxJQ6)kLbvogrUFiRu)zRC0FeuCRE5NC1qUbbb1Cf0iOXT6XliZ5Jku5ye5(HSs9xqJB1JxqMZxAutE0pjVj1GjHkhJK01OI2BnM1)x(hqGwxbWWdXVcckQHcwbnUvpEbzoFPrn55ynaCDpXs6Aur7TgB2a(vasya3MG1Ze04w94fK58Lg1KTb(vYahNFqvqJB1JxqMZxAutgQCmsITSHt6Auv)xPmOYXij2YgMTYr)riOXT6XliZ5lnQj3Ehzsya3Mijl92Fs1XatHudnPRrfVgEWah9hLCYXT6LFscUYAVJmjmGBtaICP4w9Yp5QHCdccQGeflN)eCqxSm8HWXeN)sq75hdpe)kiicnSOy55x5LYQzX8NJjOqx2ugu5ye5(HSs9N5w9YVuPCRE5NKGRS27itcd42eGiukUvV8tUAi3GGIk4tHUSPmOYXiY9dzL6pZT6LFuu)xPmehQdl5nPgm5(HSsHSvo6pI0tLkhCVwJJbgdMGEu88eddLTBy6Led5GJnW1VSSrqHUSPmOYXiY9dzL6pZT6LFPNUGg3QhVGmNV0OMC7DKjHbCBIKUgv6CRE5NKGRS27itcd42euOlBkdQCmIC)qwP(Z
|
||
|
|
|
||
|
|
end
|