-- DruidGuardian.lua -- June 2018 local addon, ns = ... local Hekili = _G[ addon ] local class = Hekili.Class local state = Hekili.State local PTR = ns.PTR -- Conduits -- [x] savage_combatant -- [ ] unchecked_aggression -- Guardian Endurance -- [-] layered_mane -- [x] wellhoned_instincts if UnitClassBase( "player" ) == "DRUID" then local spec = Hekili:NewSpecialization( 104 ) spec:RegisterResource( Enum.PowerType.Rage, { oakhearts_puny_quods = { aura = "oakhearts_puny_quods", last = function () local app = state.buff.oakhearts_puny_quods.applied local t = state.query_time return app + floor( t - app ) end, interval = 1, value = 10 }, raging_frenzy = { aura = "frenzied_regeneration", pvptalent = "raging_frenzy", last = function () local app = state.buff.frenzied_regeneration.applied local t = state.query_time return app + floor( t - app ) end, interval = 1, value = 10 -- tooltip says 60, meaning this would be 20, but NOPE. }, thrash_bear = { aura = "thrash_bear", talent = "blood_frenzy", debuff = true, last = function () return state.debuff.thrash_bear.applied + floor( ( state.query_time - state.debuff.thrash_bear.applied ) / class.auras.thrash_bear.tick_time ) * class.auras.thrash_bear.tick_time end, interval = function () return class.auras.thrash_bear.tick_time end, value = function () return 2 * state.active_dot.thrash_bear end, } } ) spec:RegisterResource( Enum.PowerType.LunarPower ) spec:RegisterResource( Enum.PowerType.Mana ) spec:RegisterResource( Enum.PowerType.ComboPoints ) spec:RegisterResource( Enum.PowerType.Energy ) -- Talents spec:RegisterTalents( { brambles = 22419, -- 203953 blood_frenzy = 22418, -- 203962 bristling_fur = 22420, -- 155835 tiger_dash = 19283, -- 252216 renewal = 18570, -- 108238 wild_charge = 18571, -- 102401 balance_affinity = 22163, -- 197488 feral_affinity = 22156, -- 202155 restoration_affinity = 22159, -- 197492 mighty_bash = 21778, -- 5211 mass_entanglement = 18576, -- 102359 heart_of_the_wild = 18577, -- 319454 soul_of_the_forest = 21709, -- 158477 galactic_guardian = 21707, -- 203964 incarnation = 22388, -- 102558 earthwarden = 22423, -- 203974 survival_of_the_fittest = 21713, -- 203965 guardian_of_elune = 22390, -- 155578 rend_and_tear = 22426, -- 204053 lunar_beam = 22427, -- 204066 pulverize = 22425, -- 80313 } ) -- PvP Talents spec:RegisterPvpTalents( { alpha_challenge = 842, -- 207017 charging_bash = 194, -- 228431 demoralizing_roar = 52, -- 201664 den_mother = 51, -- 236180 emerald_slumber = 197, -- 329042 entangling_claws = 195, -- 202226 freedom_of_the_herd = 3750, -- 213200 grove_protection = 5410, -- 354654 malornes_swiftness = 1237, -- 236147 master_shapeshifter = 49, -- 236144 overrun = 196, -- 202246 raging_frenzy = 192, -- 236153 sharpened_claws = 193, -- 202110 toughness = 50, -- 201259 } ) local mod_circle_hot = setfenv( function( x ) return legendary.circle_of_life_and_death.enabled and ( 0.85 * x ) or x end, state ) local mod_circle_dot = setfenv( function( x ) return legendary.circle_of_life_and_death.enabled and ( 0.75 * x ) or x end, state ) -- Auras spec:RegisterAuras( { aquatic_form = { id = 276012, duration = 3600, max_stack = 1, }, astral_influence = { id = 197524, }, barkskin = { id = 22812, duration = 12, max_stack = 1, }, bear_form = { id = 5487, duration = 3600, max_stack = 1, }, berserk = { id = 50334, duration = 15, max_stack = 1, }, -- Alias for Berserk vs. Incarnation berserk_bear = { alias = { "berserk", "incarnation" }, aliasMode = "first", -- use duration info from the first buff that's up, as they should all be equal. aliasType = "buff", duration = function () return talent.incarnation.enabled and 30 or 15 end, }, bristling_fur = { id = 155835, duration = 8, max_stack = 1, }, cat_form = { id = 768, duration = 3600, max_stack = 1, }, convoke_the_spirits = { id = 323764, duration = 4, max_stack = 1, }, dash = { id = 1850, duration = 10, max_stack = 1, }, earthwarden = { id = 203975, duration = 3600, max_stack = 3, }, entangling_roots = { id = 339, duration = 30, type = "Magic", max_stack = 1, }, feline_swiftness = { id = 131768, }, flight_form = { id = 276029, duration = 3600, max_stack = 1, }, frenzied_regeneration = { id = 22842, duration = 3, max_stack = 1, }, galactic_guardian = { id = 213708, duration = 15, max_stack = 1, }, gore = { id = 93622, duration = 10, max_stack = 1, }, growl = { id = 6795, duration = 3, max_stack = 1, }, guardian_of_elune = { id = 213680, duration = 15, max_stack = 1, }, heart_of_the_wild = { id = 319454, duration = 45, max_stack = 1, copy = { 319451, 319452, 319453 } }, hibernate = { id = 2637, duration = 40, max_stack = 1, }, immobilized = { id = 45334, duration = 4, max_stack = 1, }, incapacitating_roar = { id = 99, duration = 3, max_stack = 1, }, incarnation = { id = 102558, duration = 30, max_stack = 1, copy = "incarnation_guardian_of_ursoc" }, intimidating_roar = { id = 236748, duration = 3, max_stack = 1, }, ironfur = { id = 192081, duration = function () return buff.guardian_of_elune.up and 9 or 7 end, max_stack = 5, }, lightning_reflexes = { id = 231065, }, mass_entanglement = { id = 102359, duration = 30, type = "Magic", max_stack = 1, }, mighty_bash = { id = 5211, duration = 4, max_stack = 1, }, moonfire = { id = 164812, duration = function () return mod_circle_dot( 16 ) end, tick_time = function () return mod_circle_dot( 2 ) * haste end, type = "Magic", max_stack = 1, }, moonkin_form = { id = 197625, duration = 3600, max_stack = 1, }, prowl = { id = 5215, duration = 3600, max_stack = 1, }, pulverize = { id = 80313, duration = 10, max_stack = 1, }, --[[ rake = { id = 155722, duration = 15, max_stack = 1, }, ]] regrowth = { id = 8936, duration = function () return mod_circle_hot( 12 ) end, type = "Magic", max_stack = 1, }, rejuvenation = { id = 774, duration = function () return mod_circle_hot( 15 ) end, tick_time = function () return mod_circle_hot( 3 ) * haste end, max_stack = 1, }, soulshape = { id = 310143, duration = 3600, max_stack = 1, }, stampeding_roar = { id = 77761, duration = 8, max_stack = 1, }, sunfire = { id = 164815, duration = function () return mod_circle_dot( 12 ) end, tick_time = function () return mod_circle_dot( 2 ) * haste end, max_stack = 1, type = "Magic", }, survival_instincts = { id = 61336, duration = 6, max_stack = 1, }, thick_hide = { id = 16931, }, thrash_bear = { id = 192090, duration = function () return mod_circle_dot( 15 ) end, tick_time = function () return mod_circle_dot( 3 ) * haste end, max_stack = function () return legendary.luffainfused_embrace and 4 or 3 end, }, --[[ thrash_cat = { id = 106830, duration = function () return mod_circle_dot( 15 ) end, tick_time = function () return mod_circle_dot( 3 ) * haste end, max_stack = 1, }, ]] tiger_dash = { id = 252216, duration = 5, max_stack = 1, }, tooth_and_claw = { id = 135286, duration = 15, max_stack = 2 }, travel_form = { id = 783, duration = 3600, max_stack = 1, }, typhoon = { id = 61391, duration = 6, max_stack = 1, type = "Magic", }, ursols_vortex = { id = 127797, duration = 3600, max_stack = 1, }, wild_charge = { id = 102401, duration = 0.5, max_stack = 1, }, wild_growth = { id = 48438, duration = 7, max_stack = 1, }, yseras_gift = { id = 145108, }, any_form = { alias = { "bear_form", "cat_form", "moonkin_form" }, duration = 3600, aliasMode = "first", aliasType = "buff", }, -- PvP Talents demoralizing_roar = { id = 201664, duration = 8, max_stack = 1, }, den_mother = { id = 236181, duration = 3600, max_stack = 1, }, focused_assault = { id = 206891, duration = 6, max_stack = 1, }, grove_protection_defense = { id = 354704, duration = 12, max_stack = 1, }, grove_protection_offense = { id = 354789, duration = 12, max_stack = 1, }, master_shapeshifter_feral = { id = 236188, duration = 3600, max_stack = 1, }, overrun = { id = 202244, duration = 3, max_stack = 1, }, protector_of_the_pack = { id = 201940, duration = 3600, max_stack = 1, }, sharpened_claws = { id = 279943, duration = 6, max_stack = 1, }, -- Azerite masterful_instincts = { id = 273349, duration = 30, max_stack = 1, }, -- Legendary lycaras_fleeting_glimpse = { id = 340060, duration = 5, max_stack = 1 }, ursocs_fury_remembered = { id = 345048, duration = 15, max_stack = 1, }, } ) Hekili:EmbedAdaptiveSwarm( spec ) -- Function to remove any form currently active. spec:RegisterStateFunction( "unshift", function() if conduit.tireless_pursuit.enabled and ( buff.cat_form.up or buff.travel_form.up ) then applyBuff( "tireless_pursuit" ) end removeBuff( "cat_form" ) removeBuff( "bear_form" ) removeBuff( "travel_form" ) removeBuff( "moonkin_form" ) removeBuff( "travel_form" ) removeBuff( "aquatic_form" ) removeBuff( "stag_form" ) if legendary.oath_of_the_elder_druid.enabled and debuff.oath_of_the_elder_druid_icd.down and talent.restoration_affinity.enabled then applyBuff( "heart_of_the_wild" ) applyDebuff( "player", "oath_of_the_elder_druid_icd" ) end end ) local affinities = { bear_form = "guardian_affinity", cat_form = "feral_affinity", moonkin_form = "balance_affinity", } -- Function to apply form that is passed into it via string. spec:RegisterStateFunction( "shift", function( form ) if conduit.tireless_pursuit.enabled and ( buff.cat_form.up or buff.travel_form.up ) then applyBuff( "tireless_pursuit" ) end removeBuff( "cat_form" ) removeBuff( "bear_form" ) removeBuff( "travel_form" ) removeBuff( "moonkin_form" ) removeBuff( "travel_form" ) removeBuff( "aquatic_form" ) removeBuff( "stag_form" ) applyBuff( form ) if affinities[ form ] and legendary.oath_of_the_elder_druid.enabled and debuff.oath_of_the_elder_druid_icd.down and talent[ affinities[ form ] ].enabled then applyBuff( "heart_of_the_wild" ) applyDebuff( "player", "oath_of_the_elder_druid_icd" ) end end ) spec:RegisterStateExpr( "ironfur_damage_threshold", function () return ( settings.ironfur_damage_threshold or 0 ) / 100 * ( health.max ) end ) -- Gear. -- Tier 28 spec:RegisterSetBonuses( "tier28_2pc", 364362, "tier28_4pc", 363496 ) -- 2-Set - Architect's Design - Casting Barkskin causes you to Berserk for 4 sec. -- 4-Set - Architect's Aligner - While Berserked, you radiate (45%26.6% of Attack power) Cosmic damage to nearby enemies and heal yourself for (61%39.7% of Attack power) every 1 sec. spec:RegisterAuras( { architects_aligner = { id = 363793, duration = function () return talent.incarnation.enabled and 30 or 15 end, max_stack = 1, }, architects_aligner_heal = { id = 363789, duration = function () return talent.incarnation.enabled and 30 or 15 end, max_stack = 1, } } ) spec:RegisterGear( "class", 139726, 139728, 139723, 139730, 139725, 139729, 139727, 139724 ) spec:RegisterGear( "tier19", 138330, 138336, 138366, 138324, 138327, 138333 ) spec:RegisterGear( "tier20", 147136, 147138, 147134, 147133, 147135, 147137 ) -- Bonuses NYI spec:RegisterGear( "tier21", 152127, 152129, 152125, 152124, 152126, 152128 ) spec:RegisterGear( "ailuro_pouncers", 137024 ) spec:RegisterGear( "behemoth_headdress", 151801 ) spec:RegisterGear( "chatoyant_signet", 137040 ) spec:RegisterGear( "dual_determination", 137041 ) spec:RegisterGear( "ekowraith_creator_of_worlds", 137015 ) spec:RegisterGear( "elizes_everlasting_encasement", 137067 ) spec:RegisterGear( "fiery_red_maimers", 144354 ) spec:RegisterGear( "lady_and_the_child", 144295 ) spec:RegisterGear( "luffa_wrappings", 137056 ) spec:RegisterGear( "oakhearts_puny_quods", 144432 ) spec:RegisterAura( "oakhearts_puny_quods", { id = 236479, duration = 3, max_stack = 1, } ) spec:RegisterGear( "skysecs_hold", 137025 ) spec:RegisterAura( "skysecs_hold", { id = 208218, duration = 3, max_stack = 1, } ) spec:RegisterGear( "the_wildshapers_clutch", 137094 ) spec:RegisterGear( "soul_of_the_archdruid", 151636 ) spec:RegisterStateExpr( "lunar_eclipse", function () return eclipse.wrath_counter end ) spec:RegisterStateExpr( "solar_eclipse", function () return eclipse.starfire_counter end ) local LycarasHandler = setfenv( function () if buff.travel_form.up then state:RunHandler( "stampeding_roar" ) elseif buff.moonkin_form.up then state:RunHandler( "starfall" ) elseif buff.bear_form.up then state:RunHandler( "barkskin" ) elseif buff.cat_form.up then state:RunHandler( "primal_wrath" ) else state:RunHandle( "wild_growth" ) end end, state ) local SinfulHysteriaHandler = setfenv( function () applyBuff( "ravenous_frenzy_sinful_hysteria" ) end, state ) spec:RegisterHook( "reset_precast", function () if azerite.masterful_instincts.enabled and buff.survival_instincts.up and buff.masterful_instincts.down then applyBuff( "masterful_instincts", buff.survival_instincts.remains + 30 ) end if buff.lycaras_fleeting_glimpse.up then state:QueueAuraExpiration( "lycaras_fleeting_glimpse", LycarasHandler, buff.lycaras_fleeting_glimpse.expires ) end if legendary.sinful_hysteria.enabled and buff.ravenous_frenzy.up then state:QueueAuraExpiration( "ravenous_frenzy", SinfulHysteriaHandler, buff.ravenous_frenzy.expires ) end eclipse.reset() -- from Balance. end ) spec:RegisterHook( "runHandler", function( ability ) local a = class.abilities[ ability ] if not a or a.startsCombat then break_stealth() end if buff.ravenous_frenzy.up and ability ~= "ravenous_frenzy" then addStack( "ravenous_frenzy", nil, 1 ) end end ) spec:RegisterStateTable( "druid", setmetatable( { }, { __index = function( t, k ) if k == "catweave_bear" then return talent.feral_affinity.enabled and settings.catweave_bear elseif k == "owlweave_bear" then return talent.balance_affinity.enabled and settings.owlweave_bear elseif k == "no_cds" then return not toggle.cooldowns elseif k == "primal_wrath" then return debuff.rip elseif k == "lunar_inspiration" then return debuff.moonfire_cat end local fallthru = rawget( debuff, k ) if fallthru then return fallthru end end } ) ) -- Abilities spec:RegisterAbilities( { alpha_challenge = { id = 207017, cast = 0, cooldown = 20, gcd = "spell", pvptalent = "alpha_challenge", startsCombat = true, texture = 132270, handler = function () applyDebuff( "target", "focused_assault" ) end, }, barkskin = { id = 22812, cast = 0, cooldown = function () return ( talent.survival_of_the_fittest.enabled and 40 or 60 ) * ( 1 + ( conduit.tough_as_bark.mod * 0.01 ) ) end, gcd = "off", startsCombat = false, texture = 136097, toggle = "defensives", defensive = true, usable = function () if not tanking then return false, "player is not tanking right now" elseif incoming_damage_3s == 0 then return false, "player has taken no damage in 3s" end return true end, handler = function () applyBuff( "barkskin" ) if legendary.the_natural_orders_will.enabled and buff.bear_form.up then applyBuff( "ironfur" ) applyBuff( "frenzied_regeneration" ) end if set_bonus.tier28_2pc > 0 then applyBuff( "berserk", max( buff.berserk.remains, 4 ) ) if set_bonus.tier28_4pc > 0 then applyBuff( "architects_aligner", buff.berserk.remains ) applyBuff( "architects_aligner_heal", buff.berserk.remains ) end end end, }, bear_form = { id = 5487, cast = 0, cooldown = 0, gcd = "spell", spend = -25, spendType = "rage", startsCombat = false, texture = 132276, essential = true, noform = "bear_form", handler = function () shift( "bear_form" ) if conduit.ursine_vigor.enabled then applyBuff( "ursine_vigor" ) end end, }, berserk = { id = 50334, cast = 0, cooldown = function () return legendary.legacy_of_the_sleeper.enabled and 150 or 180 end, gcd = "off", toggle = "cooldowns", startsCombat = true, texture = 236149, notalent = "incarnation", handler = function () applyBuff( "berserk" ) if set_bonus.tier28_4pc > 0 then applyBuff( "architects_aligner", buff.berserk.remains ) applyBuff( "architects_aligner_heal", buff.berserk.remains ) end end, copy = "berserk_bear" }, bristling_fur = { id = 155835, cast = 0, cooldown = 40, gcd = "spell", startsCombat = false, texture = 1033476, talent = "bristling_fur", usable = function () if incoming_damage_3s < health.max * 0.1 then return false, "player has not taken 10% health in dmg in 3s" end return true end, handler = function () applyBuff( "bristling_fur" ) end, }, cat_form = { id = 768, cast = 0, cooldown = 0, gcd = "spell", startsCombat = false, texture = 132115, noform = "cat_form", handler = function () shift( "cat_form" ) if pvptalent.master_shapeshifter.enabled and talent.feral_affinity.enabled then applyBuff( "master_shapeshifter_feral" ) end end, }, cyclone = { id = 33786, cast = 1.7, cooldown = 0, gcd = "spell", spend = 0.1, spendType = "mana", startsCombat = true, texture = 136022, handler = function () applyDebuff( "target", "cyclone" ) end, }, dash = { id = 1850, cast = 0, cooldown = 120, gcd = "spell", startsCombat = false, texture = 132120, handler = function () shift( "cat_form" ) applyBuff( "dash" ) end, }, demoralizing_roar = { id = 201664, cast = 0, cooldown = 30, gcd = "spell", pvptalent = "demoralizing_roar", startsCombat = true, texture = 132117, handler = function () applyDebuff( "demoralizing_roar" ) active_dot.demoralizing_roar = active_enemies end, }, emerald_slumber = { id = 329042, cast = 8, cooldown = 120, channeled = true, gcd = "spell", toggle = "cooldowns", pvptalent = "emerald_slumber", startsCombat = false, texture = 1394953, handler = function () end, }, entangling_roots = { id = 339, cast = function () return pvptalent.entangling_claws.enabled and 0 or 1.7 end, cooldown = function () return pvptalent.entangling_claws.enabled and 6 or 0 end, gcd = "spell", spend = 0.06, spendType = "mana", startsCombat = true, texture = 136100, handler = function () applyDebuff( "target", "entangling_roots" ) end, }, --[[ ferocious_bite = { id = 22568, cast = 0, cooldown = 0, gcd = "spell", spend = function () return args.max_energy == 1 and 50 or 25 end, spendType = "energy", startsCombat = true, texture = 132127, form = "cat_form", usable = function () if combo_points.current == 0 then return false, "player has no combo points" end return true end, handler = function () spend( min( 5, combo_points.current ), "combo_points" ) end, }, ]] frenzied_regeneration = { id = 22842, cast = 0, charges = 2, cooldown = function () return buff.berserk_bear.up and ( level > 57 and 9 or 18 ) or 36 end, recharge = function () return buff.berserk_bear.up and ( level > 57 and 9 or 18 ) or 36 end, hasteCD = true, gcd = "spell", spend = 10, spendType = "rage", startsCombat = false, texture = 132091, toggle = "defensives", defensive = true, form = "bear_form", nobuff = "frenzied_regeneration", handler = function () applyBuff( "frenzied_regeneration" ) gain( health.max * 0.08, "health" ) end, auras = { -- Conduit (ICD) wellhoned_instincts = { id = 340556, duration = function () if conduit.wellhoned_instincts.enabled then return conduit.wellhoned_instincts.mod end return 90 end, max_stack = 1 } } }, grove_protection = { id = 354654, cast = 0, cooldown = 60, gcd = "spell", toggle = "defensives", startsCombat = false, texture = 4067364, handler = function () -- Don't apply auras; position dependent. end, }, growl = { id = 6795, cast = 0, cooldown = function () return buff.berserk_bear.up and ( level > 57 and 2 or 4 ) or 8 end, gcd = "spell", nopvptalent = "alpha_challenge", startsCombat = true, texture = 132270, handler = function () applyDebuff( "target", "growl" ) end, }, heart_of_the_wild = { id = 319454, cast = 0, cooldown = function () return 300 * ( 1 - ( conduit.born_of_the_wilds.mod * 0.01 ) ) end, gcd = "spell", toggle = "cooldowns", startsCombat = false, texture = 135879, handler = function () applyBuff( "heart_of_the_wild" ) if talent.balance_affinity.enabled then shift( "moonkin_form" ) elseif talent.feral_affinity.enabled then shift( "cat_form" ) elseif talent.restoration_affinity.enabled then unshift() end end, }, hibernate = { id = 2637, cast = 1.5, cooldown = 0, gcd = "spell", spend = 0.06, spendType = "mana", startsCombat = false, texture = 136090, handler = function () applyDebuff( "target", "hibernate" ) end, }, incapacitating_roar = { id = 99, cast = 0, cooldown = 30, gcd = "spell", startsCombat = true, texture = 132121, handler = function () applyDebuff( "target", "incapacitating_roar" ) end, }, incarnation = { id = 102558, cast = 0, cooldown = function () return legendary.legacy_of_the_sleeper.enabled and 150 or 180 end, gcd = "off", toggle = "cooldowns", startsCombat = false, texture = 571586, talent = "incarnation", handler = function () applyBuff( "incarnation" ) if set_bonus.tier28_4pc > 0 then applyBuff( "architects_aligner", buff.incarnation.remains ) applyBuff( "architects_aligner_heal", buff.incarnation.remains ) end end, copy = { "incarnation_guardian_of_ursoc", "Incarnation" } }, ironfur = { id = 192081, cast = 0, cooldown = 0.5, gcd = "off", spend = function () return buff.berserk_bear.up and 20 or 40 end, spendType = "rage", startsCombat = false, texture = 1378702, toggle = "defensives", defensive = true, form = "bear_form", usable = function () if not tanking then return false, "player is not tanking right now" elseif incoming_damage_3s == 0 then return false, "player has taken no damage in 3s" end return true end, handler = function () applyBuff( "ironfur" ) removeBuff( "guardian_of_elune" ) end, }, lunar_beam = { id = 204066, cast = 0, cooldown = 75, gcd = "spell", toggle = "defensives", startsCombat = true, texture = 136057, talent = "lunar_beam", handler = function () applyBuff( "lunar_beam" ) end, auras = { lunar_beam = { duration = 8, max_stack = 1, generate = function( t ) local applied = action.lunar_beam.lastCast if not t.name then t.name = class.auras.lunar_beam.name end if applied and now - applied < 8 then t.count = 1 t.expires = applied + 8 t.applied = applied t.caster = "player" return end t.count = 0 t.expires = 0 t.applied = 0 t.caster = "nobody" end, }, } }, maim = { id = 22570, cast = 0, cooldown = 20, gcd = "spell", spend = 30, spendType = "energy", startsCombat = true, texture = 132134, talent = "feral_affinity", form = "cat_form", usable = function () return combo_points.current > 0, "requires combo_points" end, handler = function () applyDebuff( "target", "maim", combo_points.current ) spend( combo_points.current, "combo_points" ) end, }, mangle = { id = 33917, cast = 0, cooldown = function () return ( buff.berserk_bear.up and ( level > 57 and 1.5 or 3 ) or 6 ) * haste end, gcd = "spell", spend = function () return buff.gore.up and -19 or -15 end, spendType = "rage", startsCombat = true, texture = 132135, form = "bear_form", handler = function () if talent.guardian_of_elune.enabled then applyBuff( "guardian_of_elune" ) end removeBuff( "gore" ) if conduit.savage_combatant.enabled then addStack( "savage_combatant", nil, 1 ) end end, auras = { -- Conduit savage_combatant = { id = 340613, duration = 15, max_stack = 3 } } }, mass_entanglement = { id = 102359, cast = 0, cooldown = 30, gcd = "spell", startsCombat = false, texture = 538515, talent = "mass_entanglement", handler = function () applyDebuff( "target", "mass_entanglement" ) end, }, maul = { id = 6807, cast = 0, cooldown = 0, gcd = "spell", spend = 40, spendType = "rage", startsCombat = true, texture = 132136, form = "bear_form", usable = function () if settings.maul_rage > 0 and rage.current - cost < settings.maul_rage then return false, "not enough additional rage" end return true end, handler = function () if pvptalent.sharpened_claws.enabled or essence.conflict_and_strife.major then applyBuff( "sharpened_claws" ) end removeBuff( "savage_combatant" ) end, }, mighty_bash = { id = 5211, cast = 0, cooldown = 60, gcd = "spell", startsCombat = true, texture = 132114, talent = "mighty_bash", handler = function () applyDebuff( "target", "mighty_bash" ) end, }, moonfire = { id = 8921, cast = 0, cooldown = 0, gcd = "spell", spend = 0.06, spendType = "mana", startsCombat = true, texture = 136096, handler = function () applyDebuff( "target", "moonfire" ) if buff.galactic_guardian.up then gain( 8, "rage" ) removeBuff( "galactic_guardian" ) end end, }, moonkin_form = { id = 197625, cast = 0, cooldown = 0, gcd = "spell", startsCombat = false, texture = 136036, noform = "moonkin_form", talent = "balance_affinity", handler = function () shift( "moonkin_form" ) end, }, overrun = { id = 202246, cast = 0, cooldown = 25, gcd = "spell", startsCombat = true, texture = 1408833, pvptalent = "overrun", handler = function () applyDebuff( "target", "overrun" ) setDistance( 5 ) end, }, prowl = { id = 5215, cast = 0, cooldown = 6, gcd = "spell", startsCombat = false, texture = 514640, usable = function () if time > 0 and ( not boss or not buff.shadowmeld.up ) then return false, "cannot stealth in combat" elseif buff.prowl.up then return false, "player is already prowling" end return true end, handler = function () shift( "cat_form" ) applyBuff( "prowl" ) end, }, pulverize = { id = 80313, cast = 0, cooldown = 45, gcd = "spell", startsCombat = true, texture = 1033490, talent = "pulverize", form = "bear_form", usable = function () if debuff.thrash_bear.stack < 2 then return false, "target has fewer than 2 thrash stacks" end return true end, handler = function () if debuff.thrash_bear.count > 2 then debuff.thrash_bear.count = debuff.thrash_bear.count - 2 else removeDebuff( "target", "thrash_bear" ) end applyBuff( "pulverize" ) end, }, --[[ rake = { id = 1822, cast = 0, cooldown = 0, gcd = "spell", spend = 35, spendType = "energy", startsCombat = true, texture = 132122, talent = "feral_affinity", form = "cat_form", handler = function () applyDebuff( "target", "rake" ) debuff.rake.pmultiplier = persistent_multiplier gain( 1, "combo_points" ) end, }, ]] --[[ rebirth = { id = 20484, cast = 2, cooldown = 600, gcd = "spell", spend = 0, spendType = "rage", startsCombat = true, texture = 136080, handler = function () end, }, ]] regrowth = { id = 8936, cast = 1.5, cooldown = 0, gcd = "spell", spend = 0.14, spendType = "mana", startsCombat = false, texture = 136085, talent = "restoration_affinity", usable = function () if not ( buff.bear_form.down and buff.cat_form.down and buff.travel_form.down and buff.moonkin_form.down ) then return false, "player is in a form" end return true end, handler = function () applyBuff( "regrowth" ) end, }, rejuvenation = { id = 774, cast = 0, cooldown = 0, gcd = "spell", spend = 0.1, spendType = "mana", startsCombat = false, texture = 136081, talent = "restoration_affinity", usable = function () if not ( buff.bear_form.down and buff.cat_form.down and buff.travel_form.down and buff.moonkin_form.down ) then return false, "player is in a form" end return true end, handler = function () applyBuff( "rejuvenation" ) end, }, remove_corruption = { id = 2782, cast = 0, cooldown = 8, gcd = "spell", spend = 0.06, spendType = "mana", startsCombat = false, texture = 135952, usable = function () if buff.dispellable_poison.down and buff.dispellable_curse.down then return false, "player has no dispellable auras" end return true end, handler = function () removeBuff( "dispellable_poison" ) removeBuff( "dispellable_curse" ) end, }, renewal = { id = 108238, cast = 0, cooldown = 90, gcd = "spell", toggle = "defensives", defensive = true, startsCombat = true, texture = 136059, talent = "renewal", handler = function () gain( 0.3 * health.max, "health" ) end, }, --[[ revive = { id = 50769, cast = 10, cooldown = 0, gcd = "spell", spend = 0.04, spendType = "mana", startsCombat = true, texture = 132132, handler = function () end, }, ]] --[[ rip = { id = 1079, cast = 0, cooldown = 0, gcd = "spell", spend = 30, spendType = "energy", startsCombat = true, texture = 132152, talent = "feral_affinity", form = "cat_form", usable = function () if combo_points.current == 0 then return false, "player has no combo points" end return true end, handler = function () applyDebuff( "target", "rip" ) end, }, ]] --[[ shred = { id = 5221, cast = 0, cooldown = 0, gcd = "spell", spend = 40, spendType = "energy", startsCombat = true, texture = 136231, handler = function () end, }, ]] skull_bash = { id = 106839, cast = 0, cooldown = 15, gcd = "spell", startsCombat = true, texture = 236946, toggle = "interrupts", debuff = "casting", readyTime = state.timeToInterrupt, handler = function () interrupt() end, }, soothe = { id = 2908, cast = 0, cooldown = 10, gcd = "spell", spend = 0.06, spendType = "mana", startsCombat = true, texture = 132163, debuff = "dispellable_enrage", handler = function () removeDebuff( "target", "dispellable_enrage" ) end, }, stampeding_roar = { id = 106898, cast = 0, cooldown = function () return pvptalent.freedom_of_the_herd.enabled and 0 or 60 end, gcd = "spell", startsCombat = false, texture = 464343, handler = function () applyBuff( "stampeding_roar" ) if buff.bear_form.down and buff.cat_form.down then shift( "bear_form" ) end end, }, --[[ starfire = { id = 197628, cast = 2.5, cooldown = 0, gcd = "spell", spend = 0.03, spendType = "mana", startsCombat = true, texture = 135753, talent = "balance_affinity", form = "moonkin_form", handler = function () end, }, ]] starsurge = { id = 197626, cast = function () return buff.heart_of_the_wild.up and 0 or 2 end, cooldown = 10, gcd = "spell", spend = 0.03, spendType = "mana", startsCombat = true, texture = 135730, talent = "balance_affinity", form = "moonkin_form", handler = function () if buff.eclipse_solar.up then buff.eclipse_solar.empowerTime = query_time; applyBuff( "starsurge_empowerment_solar" ) end if buff.eclipse_lunar.up then buff.eclipse_lunar.empowerTime = query_time; applyBuff( "starsurge_empowerment_lunar" ) end end, }, sunfire = { id = 197630, cast = 0, cooldown = 0, gcd = "spell", spend = 0.12, spendType = "mana", startsCombat = true, texture = 236216, talent = "balance_affinity", form = "moonkin_form", handler = function () applyDebuff( "target", "sunfire" ) active_dot.sunfire = active_enemies end, }, survival_instincts = { id = 61336, cast = 0, charges = 2, cooldown = function () return ( essence.vision_of_perfection.enabled and 0.87 or 1 ) * ( talent.survival_of_the_fittest.enabled and ( 2/3 ) or 1 ) * 180 end, recharge = function () return ( essence.vision_of_perfection.enabled and 0.87 or 1 ) * ( talent.survival_of_the_fittest.enabled and ( 2/3 ) or 1 ) * 180 end, gcd = "off", startsCombat = false, texture = 236169, toggle = "defensives", defensive = true, usable = function () if not tanking then return false, "player is not tanking right now" elseif incoming_damage_3s == 0 then return false, "player has taken no damage in 3s" end return true end, handler = function () applyBuff( "survival_instincts" ) if azerite.masterful_instincts.enabled and buff.survival_instincts.up and buff.masterful_instincts.down then applyBuff( "masterful_instincts", buff.survival_instincts.remains + 30 ) end end, }, swiftmend = { id = 18562, cast = 0, charges = 1, cooldown = 25, recharge = 25, gcd = "spell", spend = 0.14, spendType = "mana", startsCombat = false, texture = 134914, talent = "restoration_affinity", toggle = "defensives", defensive = true, usable = function () return IsSpellUsable( 18562 ) or buff.regrowth.up or buff.wild_growth.up or buff.rejuvenation.up, "requires a HoT" end, handler = function () unshift() if buff.regrowth.up then removeBuff( "regrowth" ) elseif buff.wild_growth.up then removeBuff( "wild_growth" ) elseif buff.rejuvenation.up then removeBuff( "rejuvenation" ) end end, }, swipe_bear = { id = 213771, known = 213764, suffix = "(Bear)", cast = 0, cooldown = 0, gcd = "spell", startsCombat = true, texture = 134296, form = "bear_form", handler = function () end, copy = { "swipe", 213764 }, bind = { "swipe_bear", "swipe_cat", "swipe" } }, --[[ teleport_moonglade = { id = 18960, cast = 10, cooldown = 0, gcd = "spell", spend = 4, spendType = "mana", startsCombat = true, texture = 135758, handler = function () end, }, ]] thrash_bear = { id = 77758, known = 106832, suffix = "(Bear)", cast = 0, cooldown = function () return ( buff.berserk_bear.up and ( level > 57 and 1.5 or 3 ) or 6 ) * haste end, gcd = "spell", spend = -5, spendType = "rage", startsCombat = true, texture = 451161, form = "bear_form", bind = "thrash", handler = function () applyDebuff( "target", "thrash_bear", 15, debuff.thrash_bear.count + 1 ) active_dot.thrash_bear = active_enemies if legendary.ursocs_fury_remembered.enabled then applyBuff( "ursocs_fury_remembered" ) end end, }, tiger_dash = { id = 252216, cast = 0, cooldown = 45, gcd = "spell", startsCombat = false, texture = 1817485, talent = "tiger_dash", handler = function () applyBuff( "tiger_dash" ) end, }, travel_form = { id = 783, cast = 0, cooldown = 0, gcd = "spell", startsCombat = false, texture = 132144, handler = function () shift( "travel_form" ) end, }, typhoon = { id = 132469, cast = 0, cooldown = 30, gcd = "spell", startsCombat = true, texture = 236170, talent = "balance_affinity", handler = function () if target.distance < 15 then applyDebuff( "target", "typhoon" ) end end, }, ursols_vortex = { id = 102793, cast = 0, cooldown = 60, gcd = "spell", talent = "restoration_affinity", startsCombat = true, texture = 571588, handler = function () applyDebuff( "target", "ursols_vortex" ) end, }, wild_charge = { id = function () if buff.bear_form.up then return 16979 elseif buff.cat_form.up then return 49376 elseif buff.moonkin_form.up then return 102383 end return 102401 end, known = 102401, cast = 0, cooldown = 15, gcd = "spell", startsCombat = true, -- texture = 538771, talent = "wild_charge", usable = function () return target.exists and target.distance > 7, "target must be 8+ yards away" end, handler = function () if buff.bear_form.up then target.distance = 5; applyDebuff( "target", "immobilized" ) elseif buff.cat_form.up then target.distance = 5; applyDebuff( "target", "dazed" ) end end, copy = { 49376, 16979, 102401, 102383 } }, wild_growth = { id = 48438, cast = 1.5, cooldown = 10, gcd = "spell", spend = 0.22, spendType = "mana", startsCombat = false, texture = 236153, handler = function () applyBuff( "wild_growth" ) end, }, --[[ wrath = { id = 5176, cast = 1.5, cooldown = 0, gcd = "spell", spend = 0.01, spendType = "mana", startsCombat = true, texture = 535045, handler = function () if buff.moonkin_form.down then unshift() end removeStack( "solar_empowerment" ) end, }, ]] } ) spec:RegisterOptions( { enabled = true, aoe = 3, nameplates = true, nameplateRange = 8, damage = true, damageExpiration = 6, potion = "spectral_agility", package = "Guardian", } ) spec:RegisterSetting( "maul_rage", 20, { name = "Excess Rage for |T132136:0|t Maul", desc = "If set above zero, the addon will recommend |T132136:0|t Maul only if you have at least this much excess Rage.", type = "range", min = 0, max = 60, step = 0.1, width = "full" } ) spec:RegisterSetting( "mangle_more", false, { name = "Use |T132135:0|t Mangle More in Multi-Target", desc = "If checked, the default priority will recommend |T132135:0|t Mangle more often in |cFFFFD100multi-target|r scenarios. This will generate roughly 15% more Rage and allow for more mitigation (or |T132136:0|t Maul) than otherwise, " .. "funnel slightly more damage into your primary target, but will |T134296:0|t Swipe less often, dealing less damage/threat to your secondary targets.", type = "toggle", width = "full", } ) spec:RegisterSetting( "ironfur_damage_threshold", 5, { name = "Required Damage % for |T1378702:0|t Ironfur", desc = "If set above zero, the addon will not recommend |T1378702:0|t Ironfur unless your incoming damage for the past 5 seconds is greater than this percentage of your maximum health.", type = "range", min = 0, max = 100, step = 0.1, width = "full" } ) spec:RegisterSetting( "shift_for_convoke", false, { name = "|T3636839:0|t Powershift for Convoke the Spirits", desc = "If checked and you are a Night Fae, the addon will recommend swapping to your Feral/Balance Affinity specialization before using |T3636839:0|t Convoke the Spirits. " .. "This is a DPS gain unless you die horribly.", type = "toggle", width = "full" } ) spec:RegisterSetting( "catweave_bear", false, { name = "|T132115:0|t Attempt Catweaving (Experimental)", desc = function() local affinity if state.talent.feral_affinity.enabled then affinity = "|cFF00FF00" .. ( GetSpellInfo( 202155 ) ) .. "|r" else affinity = "|cFFFF0000" .. ( GetSpellInfo( 202155 ) ) .. "|r" end return "If checked, the addon will use the experimental |cFFFFD100catweave|r priority included in the default priority pack.\n\nRequires " .. affinity .. "." end, type = "toggle", width = "full", } ) spec:RegisterSetting( "owlweave_bear", false, { name = "|T136036:0|t Attempt Owlweaving (Experimental)", desc = function() local affinity if state.talent.balance_affinity.enabled then affinity = "|cFF00FF00" .. ( GetSpellInfo( 197488 ) ) .. "|r" else affinity = "|cFFFF0000" .. ( GetSpellInfo( 197488 ) ) .. "|r" end return "If checked, the addon will use the experimental |cFFFFD100owlweave|r priority included in the default priority pack.\n\nRequires " .. affinity .. "." end, type = "toggle", width = "full" } ) spec:RegisterPack( "Guardian", 20220911, [[Hekili:T3tApooUX(BXiaAS3PJhF0Eow0Ubs2xqWm4LzbshG8(KLvltBR0Yso6O90lAOF7PksrjEkjF09K3I5l70wKSyXI1nlYDX4f)Jf3TYlJS4RtgnzYOpnE8WXJNmD8I7YEApzXD798FWBd8hrE7G)7Fn3lzvGxe2WtHXERWXNgNN4dnUnlBF6p)U3TjiBB(9d9J39U0GD5HEzbXr(jERZWF7)Uf3DFEqy2NJwCVXjF07xCNxE224Kf3DxWUFbGCWQvew3jP(1OrXY)NK8GvfF5oY(mYU7jjflhp(QILi8k(sXx(LTErBiP)CXx(Jfl)CKFCY(4eyglw(lEzV7Vfhh9qaaL9jbXjbzbK0IL9dwxSmLKLfeTPyza8f)Te)hiRgmuhkX7X1wXYSyymBdwNbJpgqIO4SbflVNSoobNR4OhJFGWg)D57HrdD8p7L8qkD6ZtbsCXYdaDRy5179PZpm84O80HlUlminlfj03t8sG)9R0DnsK39HKvl(ZlUZhWDssG3I76bJkF96HypDHjF3W89aX0hXs24PFDrgqYTcKmVqsu2WTqVZCJx7MTL4EiiC1WYExS0bwMWIM1V79c9I8jUERxhefK9uD3gup1AadrHPkOaVZ7G9L1bjerKQpDkH1xwG)d0Tgh8V3rCZIDxfaKVBH9(j0ptjbBa0cGNV7MsMfGuaOuXYNFMcQeY6es6wCYpDynG2hSThjUKiYokl0nflbwy)N8dbi6LSHaBFWMgSIV(LyfFCRPtaRNzLvHHJiVqsq0dKSHzJhgKo03dKzWDBp))DoSSw5MLq8sZtW5bX1QUpP1UpOEBOQzVVre2bkx89okSWrEaDapQ3Ts8EKefNN6cu7OF7jKe9(MejxHkPaONDGaJ0ffd5iaRP4dHkn9YssRxk(mvtuXY09bawNIlNp00ooG2(XafWde(H)jB7tv48llA3cNq9QkiY3ljIA3bxnF0UQUUJSwM66jTewujMp1(m2(6TRZ4eCghpszkzgS3aCvHC9UGgM0mxVK7rKPgmn0heWQwBya(qI3(uCqKqIFwsCAMhQGCFCgWre4fwd(w7jojQwJytcS(2GJ0pomeac(R15zi1rqy0EFqaBZgZ)kolhCniijXf8Pam2)uQRVxyO4ELkxohTSowCcvvXRBCEFciVt5ADSijD0QYysLMfnCm0w6H4KvwB9Gx0krRLgrCBAb(VgC3SK5y7gZoT9Nojh)sTgpZ9NVR4Uf9y2TKAC5qHUG((HjKDEbraQF7CioGRBPt3GDAwnQaALknAm2UnWmVOkhY0C3M(vW)DxM77qqfjt(Ol1REWdSrcEJx6)pDYSBI6O9FOvJ7JTBDQF5csXdh6YQKttFxyGyegjPKKhOXxOAq6YnlkM3NypEO(vBqu8IsFQMgvUIkV7rHH8K0yFvg1sWa7905LA0I3gz3(4dKeCBFLi2GDu1iKQ7uRIZg6TYBp1H80dEj7Cx5TdckCOOV)9y(SdSVM7BqK76WGnBZeeBnaziuSWA4IecBDQwuQy50kTn2rwWYU)d0ajMsrb79Sw(Ry5Sw6BfQkSri3tkn2UD3gcHZXyyqtneygofQMoQ0FTnXlDBPWx98kfngNYj0xz6vzum27dtvwsEeMvbGUecllGiUopfuRs2DFINpzibuZUFpn4BgivxEOwXRf4)1KmCm1GK(Yn(a4FlOlB4mZXloXUo8eChDfzDGFqglK0rCfMycxshUZlAdaWDXyWWv7c0psbTDTYPX5H3hawx2NNMLdWGKKttpJAEl6JQxIdxfFisIulYUpQ04Fz3yiGApgWHiUPX5uKnanvOxDqFdozw2cKBsNDM1EDeXvKJhJXmWb0J04quBkNCG6rbshsKCdwlq)uhGt)Mix3oYXcz62rdKMJD7iaMMb7RJR3AxhcIi0Kdk23nHX3JXqWyNSBC8crsnkKuJJPhc2xABfrN2nFk6QrPFAw00iXBKfhNT1fCqY1p07ax0N6hJyIom1xrjxLMe11oE4SMXgXPOtgnfwF8XL69iiLdbKT7EVm0gUWczA7tp16F0Q8GmDiPijFsOP1THEIAxPmpGNj5jp5cuqAYLjRe0VksPELwXnXa1Rb959Srpe1WMtdFDAJETDeKhNtCnHMeez2pUP8uPK4g1y5yseSPJ0f7(yAK0AA3AUSNfv20MApv8MOo2XXPI(JwcFzprNAlb07Zbv9jb)MugOT4lcGetmB4F6mrmqYTiz049I9tq9Qs3SBSpHEIj4227hvR5libSbNl600KtNt84LpRrQRNOJuwT2uprMylNkc6ILFSXL7hecsI1iqhblR7cYc2WcyQXZpcyJJ3HPqJ57T7mgpxjS4Ff2ybJ2GnFDur0ydG5)uXYTEPzetOvJNavDa2yKizBhU3pJDefcbRdrnsoWsGO9iS6iSOHGgaEsNq2aGnPk6s7Xv0xic8UgCEJ(LpXs0KznDemnS((al0klBQJgoMTbXg0oVVzo3e2DMNz7lp5XGh9cDHTDWfE)SuvxUkHv9Nv3gg1mAozMv8uFYz87qegGbTmtm74jiNeSNn()Y3i(5zO4lbu)9e7eZG)7wcDhcpkx8eGbH(GqecdfM6hYddDVh0WzIxM3RUKM5UM(UUK(z7YbDFwQ0FlK20JmR2DbUtAMV2w(l7xDqtD5yQPOMExKCA1OemnEDlYVoMs5ATllhLJP2s6KGFDNGgg5JdRoPM2LLByse1WyBxPdlRUei2Lm6CNMIlxihgc2xXSSm6sUEOn1qS6Ibra0EPCiJwH28eZDRzI9gxvjEpGRi5J7N2qWE5VBYv6ypiaXs5bs4kWodB7x1xAkEzRZLOzxq)QCLyrCuk9sJhjI0vCBp8ucTIFe34fTsQaeAhn4PLEK0M1oiVc(0iUmvkO9YhtIUGBi5rUS)2flvhwb74Y0vZfOqHp7EZ2rHVg0h(drMlOiZ3Vf35XGDshIKkH8SWa7PgZwHUOWIFHOZxyHI222e5j3XkQqj(sKllnNlt9APC2Gs0i84HCx7rKx4goOqn1PNe3jF)g5n0QqfdSN68hMOPNhA0yabFEDXYdK3GvTPxXsk5IsT8IwHnGBLrVbcB5aqnzL9jN9)D8j5kHEVf(nSgyvi57wdHvgcTwwOKCxyjRGH8p3ckVEelG1Ynd4pwXI(a3lrGLEiiZFlgOeoV1qbPkCCjfWQGSRWOLW1WoEfUsPCnqSeogf(jXqRNvKK7wHrok(E3qPFY7Snnp6DWOF2xuMxroIYrr5iudE73ZCeaYXA9LHJGUG()H8d(I8d2QzmmiBR6yesXwMHYaRlQPktKBMa7zJzRRtra3Rn3C7ztjlhLnw722tExRWtSHMZzr1rsYQkruRp4dNw89sTkotwkag7jZq401jB88FIVQtdjK9KKkBWTof2ZRbXpmyFkzOx0tUrKVLXmsZ)AACOxc97czAkZlHxdc2dGVz4gMhPb3djGZdvbM00cskT8ae2Nqyza)isWg)YqWgi(7nGe5WIL)jFFY(Su8ste9h36LSBDEiVsxGVghf(KGEkGXzfTkZQP1N)nzOR(g3qAHS4QIqsFm5yy72rBrm0USJXaKmSqfsteMlRULSpKjteU9Bu1Tt3u7BsX(Gc5eRDotHfdhL7bGt5zXS0(B2(LuDGjCrASlQBpEa7lbDK0GaBlPK)yMYMMprfpNvD3CzRhLlrrLGo4u6WqALsSkbbw(sL069vPI97(W44v0JIwPxshbRq5ck3RRf7LxIVxeEnDssOloPEkDGQ0I7l19FLVAZo9UkDMQ42gfjv6KKQEuNdy1eCyJDKes9SLIUPseqYG79jG3mHSAWpP5ec0xjxtsvKicp1Z9MljREQ0LdSgjukpuwCNk7jkl2Xs7)5Pexan3PB4RkxhVI(LjLBM29jtwBUbUZgvSBCY4FSzBd0XZppebhE9yEv30jyEMKRwilh1HEudl1JGTH03Am7Iu3VktijMiXz60e7Yy2Ylj69uS7(yqRwQwDQbdOzzUgxV2QwC7PTXaYqrsH0WotOG3HydJ9dW69gVCryfQ8nxwxllFeTuZiPTOxrxksygRcBk)rDsRxN0Aj74OmK7iXspD2L20Udd63mD2LWiFzK8vUZyRoJA4oB1S8hUROlv3WvmQPHNUfIRP0mZ3HW)psZmNNveP9LUeXzvgCFfPiFFtisfBb4eEAEYg1s577AsmAmXmTc32miB56m1DdY)WAXfYAHQdkvmL5ApxbcAkxyS4qvDlrK7VbGjKbft3HhZZvJoTymlaQPptwaKhfCdEOyjbgnc6Qa6BWQm)CflHIlntEYzwI3en5HdvQSBBU114DsJJYaZpD(SLKsXSZOpgNs8RsfMBPimg9QWczGfITuyYmALIDbGw(ieqh2b2BiZhNaEiaCVr4bwS4U)5F6V)1p)1)6pxSSy5)alQVGDShFL1yP99gu)YBWNnd2Ltf9Kbl)pV8S4DE0Sw6ZEazgw8L)3GiOPz)m75CHKqB(n8Rs74H)FVHDIlVr42pJFR)KVnO1HpXWWNOp83F8Z(4om8gMDXH)HZB2Tn8oo7F88M9pDEZ(4Rp(PxCNB8jVZx8Lpt5zXr9jUTQIL0hfiOzqKzpXh14DnnM)1bO(3)WFOyP2JKe(rBpusyB1pws4VUmpysMG0X(OjvcJJ9HtIUSkwEHobIIVu(7Hvh(XBN)oLtJWCN0Cx8QG1ZBZvvN(gcw3r176NF2GhtoM8285Nn9vNwoaIbMxr0S8GRcv8XXug4ncIQ8hIGPN6Hk40VFptRSEgG)aN(90T8oyWZpFCarhgoD4ObgyHernxvrIuj7grldUpye0CBKhf07kWRJQgbFRPe45NBn4)Rmei)8XxPgYU0NeNAv4Qjx3Xs3VA9oVU09R(gSY5z99k8W4NBRi7Rzx5P6uyJJxxMcqLxe9N44MCSJJD2f0rP2nqOQFRQDSgA8aJAKmQaAGJmgtfflp1aPsIVuPuBLdpkHBsBOjP7bOaj1AgRRuJsIgnrZfHHO2FSkpHpgSgSdYk9V3XoxbyaODcCe(yL4WkguKB6Esy8bSOqHV(BWcPSWEewaLJLvAG0gb7WSWwkwUPYKmUUzGeS6XpVdaOu2weHkl5i0kxvj7qbhp)BuM77JXQjAYmya)kDKIfzevu4x9qBJH4LAALhkMWJ()QYoSIWWLqKFBfZQmE38RWn0dDRZ8ORQNxkcZltB6i(lm39PwKxvxIo1fXehUSt5XJTIxtqVlyyYKHIm3kfpZvSYae0Cqfz5mhiZVr2LYcnvxaYPdSHiI7OZet)C)t(gY7yQERVD(g)vVD0WzoiN3nxp6CXplrpJTHYMAwXz703ozg2QPt3WXW5tG9T7vXAPkc71VQJD0A0aBQPkjG3mF8ieDuU8aonEXbGb5WKd5N74ntQOoM0iYXNpnsWjGlhxQb13)GlJ8AGSN4UPrBuQRAMXPFLzY6fX404zVigNgYnXiBCsQcJlbAz2bzGqyV7L1k1WlTLOs65KkZYvG(RS8bxxhW)IEf6EegUQQt4kvckrgWvjCM88NHcKUiBRfgI5B9Wf2oHKE(6q36s5adA8pgzDXTjJbwAIkqJv53z1qU8TkOjciJUvo30akTwl5ovbNynzeMddO(ZkbHCMSf)(BFZxQ2)BDFZ)i33mx7)VY7A1Rj1Q1NTOQlt)wx)SKxvNMe83ZnK3QQprf3f79PN8V2ef0MhU3DxjDCyZP5DOF)ELh3NJWlc(TJNytTotRQOxxDECdu9H(9xguTzeQltRYRnjB26xNh)MFkuF(56m23Cpldor5TsLMpYEDD2C615ztBDAqgXQ3PgnJ9sqt0WsbVyO7eMYw1laEyzVrd9etBxxrdJW2gKNic52q7Ubz5eyA)v9ULb2271DldpjW27XDldSPmUAnJNM2VusxQgJv3Lc73ZeH3r5R8h8y1Vx(uhdc(TLa3xDuQrUYot)ALT9YGShd97vcL0OF1PDV1ClwN)LjxBTXBMpzM2KWFjLyUqiesOOhioME7PVD0f3mHo2jeVjvLof10FJNHTtvAu7MhohyvFnmQb1jEqeAWwmrIAnkxpvmZCTwrwo9yqPTYrZXiSeldTNFULsq72Pdm2hXcp7MPoTwWz3mRH(uImn4XAq5XyAYFsv36MQR5QotgMCOuWNr2Av7bn8MPLPFuVLRD64ZTmqhLr0BNFDjpLcNMHCZujYxMpwDkfnBm0vJx9ZN8TJh5y6ztwB4h5r6EgPjcpJqJzAE6GY05F6jVYclclHTFhog6Z4vrwBhIwz6vYbNonsJh0aRuEyTwq5xTuTyOMwUPz6DjgSEvL4pT3IyhtFMZMpE4m9zIdQw1ltXtwFn)Q7sz20bFV2EbpDogeqJq1RZVtT8v6fg71366zu9tptRNgvQIClDE15CKi6TJLthCBG)yje3oFSblpv6tnqmuPKZB2Kdae1vKL5t3Nr(BURj7wgniD7KMWfZQvm3u5ZWk3MYTZFp)e1eFtzVzYXUF2nMv2uE9e5P0GkmeCQBOtzd)Jgr4piMWU6C9nxy9Q)oJERT33w5zGRaB6prFtBnnpaLT8rPv0h9TvV3P38(zwgMX3F2JfiIEJw6Uzh9M3GdmtSmjMIcra5(Wmhdu4rdh)tBREaxTaz9xZ1kzulVYSLgcfFHzLiuJmJltMjHm1Ot1DcFolGodTGuGQB)TL2Rc4WC7Y34BZ9r5UEBUtv3YBlZJ0972cUkEJTRi3ilHEkTfhNAaAs(9vfaIMYEhv9A87HstesZnwDlTL2al50NFA5DNzD0yXEWAs6K8vN03wwzSgBHpY6mS0gSWYHOAhP6HM1upV0lwJtIQYLgl1xdldtv4XZpZkcKBUEM5XgSVAOk1bI4vPuYtxrAU5CC0vmx(clFv99vMzIwbd41ZYSrgb2psgGXKbisUpY4uj87k83JO)QMCJlfQNxnknyJv(glaeVCWQmDyFf6Dj3(RRQVYj9iuWjmcDXtXfu8l8csRsnuN43YssfVp1lSUmsl6EA8MZYCNr55m7yGExV6VgHP49kq9olckQ1V8FMas19EWoeQFlY66stIRO0T1xFUIYj(e4kQhz1vH0yRxUD1wHzZpTEMaKz7)wotaHX9ddFgn8jYuKBTEieVi024e7WyltJLX)NGOn2uUQad1JJ2BnOjyuPjWWfBQBqWcRll)zQ3h6YLO6DH2cfxy91x9IlBsxhMLk1(X0w38LB280ZV33zlw8Fo]] ) end