diff --git a/TheWarWithin/DruidFeral.lua b/TheWarWithin/DruidFeral.lua index 4312627bb..dd02e86f0 100644 --- a/TheWarWithin/DruidFeral.lua +++ b/TheWarWithin/DruidFeral.lua @@ -337,10 +337,9 @@ spec:RegisterAuras( { }, overflowing_power = { id = 405189, - duration = function () return talent.incarnation.enabled and 30 or 20 end, + duration = 10, max_stack = 3, - copy = "berserk_overflow", - meta = { + --[[meta = { stack = function( t ) if buff.bs_inc.down then return 0 end local deficit = combo_points.deficit @@ -350,7 +349,7 @@ spec:RegisterAuras( { stacks = function( t ) return t.stack end - } + }--]] }, -- Alias for Berserk vs. Incarnation @@ -358,7 +357,7 @@ spec:RegisterAuras( { 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 20 end, + duration = function () return talent.incarnation.enabled and 20 or 15 end, }, bloodtalons = { id = 145152, @@ -432,9 +431,10 @@ spec:RegisterAuras( { -- Bleeding for $w1 damage every $t1 seconds. Weakened, dealing $w2% less damage to $@auracaster. dreadful_wound = { id = 451177, - duration = mod_circle_dot( 6.0 ), - tick_time = mod_circle_dot( 2.0 ), + duration = 6, + tick_time = 2, pandemic = true, + mechanic = "bleed", max_stack = 1, -- Affected by: @@ -532,7 +532,7 @@ spec:RegisterAuras( { -- https://wowhead.com/beta/spell=102543 incarnation_avatar_of_ashamane = { id = 102543, - duration = 30, + duration = 20, max_stack = 1, copy = { "incarnation", "incarnation_king_of_the_jungle" } }, @@ -701,6 +701,10 @@ spec:RegisterAuras( { max_stack = 1, copy = "ravage_fb" }, + ravage_upon_combat = { + duration = 3600, + max_stack = 1 + }, -- Heals $w2 every $t2 sec. -- https://wowhead.com/beta/spell=8936 regrowth = { @@ -875,7 +879,7 @@ spec:RegisterAuras( { -- https://wowhead.com/beta/spell=5217 tigers_fury = { id = 5217, - duration = function() return ( talent.predator.enabled and 15 or 10 ) + ( talent.raging_fury.enabled and 5 or 0 ) end, + duration = function() return 10 + ( talent.predator.enabled and 5 or 0 ) + ( talent.raging_fury.enabled and 5 or 0 ) end, multiplier = function() return 1.15 + state.conduit.carnivorous_instinct.mod * 0.01 + state.talent.carnivorous_instinct.rank * 0.06 end, }, -- Talent: Your next finishing move restores $391874s1 combo $Lpoint:points;. @@ -1050,9 +1054,9 @@ spec:RegisterEvent( "PLAYER_REGEN_ENABLED", function () rip_applied = false end ) -spec:RegisterStateExpr( "opener_done", function () +--[[spec:RegisterStateExpr( "opener_done", function () return rip_applied -end ) +end )--]] local last_bloodtalons_proc = 0 @@ -1154,6 +1158,9 @@ spec:RegisterStateFunction( "shift", function( form ) end end ) +spec:RegisterHook( "runHandler_startCombat", function() + if talent.killing_strikes.enabled then applyBuff( "ravage_upon_combat" ) end +end ) spec:RegisterHook( "runHandler", function( ability ) local a = class.abilities[ ability ] @@ -1162,10 +1169,15 @@ spec:RegisterHook( "runHandler", function( ability ) break_stealth() end - if buff.ravenous_frenzy.up and ability ~= "ravenous_frenzy" then + if talent.aggravate_wounds.enabled and debuff.dreadful_wound.up and a.spendType == "energy" and a.spend > 0 then + debuff.dreadful_wound.expires = debuff.dreadful_wound.expires + 0.6 + end + + if covenant.venthyr and buff.ravenous_frenzy.up and ability ~= "ravenous_frenzy" then stat.haste = stat.haste + 0.01 addStack( "ravenous_frenzy", nil, 1 ) end + end ) @@ -1260,6 +1272,10 @@ local SinfulHysteriaHandler = setfenv( function () end, state ) +local IncarnationComboPointPeriodic = setfenv( function() + gain( 1, "combo_point" ) +end, state ) + spec:RegisterHook( "reset_precast", function () if buff.cat_form.down then energy.regen = 10 + ( stat.haste * 10 ) @@ -1287,15 +1303,23 @@ spec:RegisterHook( "reset_precast", function () gain( 5, "combo_points" ) end - opener_done = nil + -- opener_done = nil last_bloodtalons = nil if buff.jungle_stalker.up then buff.jungle_stalker.expires = buff.bs_inc.expires end - if talent.ashamanes_guidance.enabled and buff.incarnation.up then buff.ashamanes_frenzy.expires = buff.bs_inc.expires + 40 end - --[[ if buff.lycaras_fleeting_glimpse.up then - state:QueueAuraExpiration( "lycaras_fleeting_glimpse", LycarasHandler, buff.lycaras_fleeting_glimpse.expires ) - end ]] + if buff.bs_inc.up then + if talent.ashamanes_guidance.enabled then buff.ashamanes_frenzy.expires = buff.bs_inc.expires + 40 end + + -- Queue combo point gain events every 1.5 seconds while Incarnation/Berserk is active, starting 1.5 seconds after cast + local tick, expires = buff.bs_inc.applied, buff.bs_inc.expires + for i = 1.5, expires - query_time, 1.5 do + tick = query_time + i + if tick < expires then + state:QueueAuraEvent( "incarnation_combo_point_perodic", IncarnationComboPointPeriodic, tick, "AURA_TICK" ) + end + end + end if legendary.sinful_hysteria.enabled and buff.ravenous_frenzy.up then state:QueueAuraExpiration( "ravenous_frenzy", SinfulHysteriaHandler, buff.ravenous_frenzy.expires ) @@ -1303,22 +1327,25 @@ spec:RegisterHook( "reset_precast", function () end ) spec:RegisterHook( "gain", function( amt, resource ) - if amt > 0 and resource == "combo_points" and buff.bs_inc.up and buff.overflowing_power.applied == 0 and combo_points.deficit - amt <= 0 then - local partial = max( 0, ( query_time - buff.bs_inc.applied ) % 1.5 ) - applyBuff( "overflowing_power", buff.bs_inc.remains + partial, 0, nil, nil, nil, query_time - partial ) + if amt > 0 and resource == "combo_points" then + if combo_points.deficit < amt then -- excess points + local combo_points_to_store = amt - combo_points.deficit + if buff.overflowing_power.stack > ( 3 - combo_points_to_store ) or buff.bs_inc.down then -- unable to store them all + applyBuff( "coiled_to_spring" ) + end + if buff.bs_inc.up then addStack( "overflowing_power", nil, combo_points_to_store ) end -- store as many as possible + end end - -- TODO: Proc Coiled to Spring if Overflowing Power is maxed. if azerite.untamed_ferocity.enabled and amt > 0 and resource == "combo_points" then if talent.incarnation.enabled then gainChargeTime( "incarnation", 0.2 ) else gainChargeTime( "berserk", 0.3 ) end end end ) - local function comboSpender( a, r ) if r == "combo_points" and a > 0 then if talent.soul_of_the_forest.enabled then - gain( a * 3, "energy" ) + gain( a * 2, "energy" ) end if buff.overflowing_power.up then @@ -1326,27 +1353,20 @@ local function comboSpender( a, r ) removeBuff( "overflowing_power" ) end - if legendary.frenzyband.enabled then - reduceCooldown( talent.incarnation.enabled and "incarnation" or "berserk", 0.3 ) - end - - if talent.berserk_heart_of_the_lion.enabled and buff.bs_inc.up then - reduceCooldown( talent.incarnation.enabled and "incarnation" or "berserk", 0.5 ) - end - - if talent.raging_fury.enabled and buff.tigers_fury.up then - buff.tigers_fury.expires = buff.tigers_fury.expires + 0.4 * a - end - if buff.tigers_tenacity.up then removeStack( "tigers_tenacity" ) gain( 1, "combo_points" ) end - if a >= 5 then + if talent.predatory_swiftness.enabled and a >= 5 then applyBuff( "predatory_swiftness" ) end + -- Legacy + if legendary.frenzyband.enabled then + reduceCooldown( talent.incarnation.enabled and "incarnation" or "berserk", 0.3 ) + end + if set_bonus.tier29_4pc > 0 then applyBuff( "sharpened_claws", nil, a ) end @@ -1589,7 +1609,9 @@ spec:RegisterAbilities( { handler = function () if buff.cat_form.down then shift( "cat_form" ) end applyBuff( "berserk" ) - applyBuff( "overflowing_power", nil, 0 ) + for i = 1.5, spec.auras.berserk.duration, 1.5 do + state:QueueAuraEvent( "incarnation_combo_point_periodic", IncarnationComboPointPeriodic, query_time + i, "AURA_TICK" ) + end end, copy = { "berserk_cat", "bs_inc" } @@ -1608,7 +1630,7 @@ spec:RegisterAbilities( { spend = function () if buff.clearcasting.up then return 0 end - return max( 0, 25 * ( buff.incarnation.up and 0.75 or 1 ) + buff.scent_of_blood.v1 ) + return 25 * ( buff.incarnation.up and 0.75 or 1 ) end, spendType = "energy", @@ -1627,7 +1649,7 @@ spec:RegisterAbilities( { cost = function () return max( 1, class.abilities.brutal_slash.spend ) end, handler = function () - gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1, "combo_points" ) + gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1 + ( allow_crit_prediction and crit_pct_current * active_enemies >= 230 and 1 or 0 ), "combo_points" ) if buff.bs_inc.up and talent.berserk_frenzy.enabled then applyDebuff( "target", "frenzied_assault" ) end if talent.bloodtalons.enabled then @@ -1635,9 +1657,11 @@ spec:RegisterAbilities( { check_bloodtalons() end - if talent.cats_curiosity.enabled and buff.clearcasting.up then - gain( 25 * 0.25, "energy" ) + if talent.thrashing_claws.enabled and talent.thrash.enabled then + applyDebuff( "target", "thrash_cat" ) + active_dot.thrash_cat = min( true_active_enemies, active_dot.thrash_cat + active_enemies ) end + removeStack( "clearcasting" ) end, }, @@ -1807,9 +1831,9 @@ spec:RegisterAbilities( { cycle_to = true, -- Use maximum damage. - damage = function () -- TODO: Taste For Blood soulbind conduit + damage = function () return calculate_damage( 1.45 * 2 , true, true ) * ( buff.bloodtalons.up and class.auras.bloodtalons.multiplier or 1 ) * ( talent.sabertooth.enabled and 1.15 or 1 ) * ( talent.soul_of_the_forest.enabled and 1.05 or 1 ) * ( talent.lions_strength.enabled and 1.15 or 1 ) * - ( 1 + 0.05 * talent.taste_for_blood.rank * ( ( debuff.rip.up and 1 or 0 ) + ( debuff.tear.up and 1 or 0 ) + ( debuff.thrash_cat.up and 1 or 0 ) + ( debuff.sickle_of_the_lion.up and 1 or 0 ) ) ) + ( 1 + ( talent.taste_for_blood.enabled and ( buff.tigers_fury.up and 0.24 or 0.12 ) or 0 ) ) * ( talent.bestial_strength.enabled and 1.1 or 1 ) * ( buff.coiled_to_spring.up and 1.1 or 1 ) end, -- This will override action.X.cost to avoid a non-zero return value, as APL compares damage/cost with Shred. @@ -1818,12 +1842,10 @@ spec:RegisterAbilities( { usable = function () return buff.apex_predator.up or buff.apex_predators_craving.up or combo_points.current > 0 end, handler = function () - removeBuff( "coiled_to_spring" ) - removeBuff( "ravage" ) - - if pvptalent.ferocious_wound.enabled and combo_points.current >= 5 then - applyDebuff( "target", "ferocious_wound", nil, min( 2, debuff.ferocious_wound.stack + 1 ) ) - end + if talent.coiled_to_spring.enabled then removeBuff( "coiled_to_spring" ) end + if talent.ravage.enabled then removeBuff( "ravage" ) end + if talent.bloodtalons.enabled then removeStack( "bloodtalons" ) end + if talent.sabertooth.enabled then applyDebuff( "target", "sabertooth" ) end if buff.apex_predator.up or buff.apex_predators_craving.up then applyBuff( "predatory_swiftness" ) @@ -1833,16 +1855,15 @@ spec:RegisterAbilities( { spend( min( 5, combo_points.current ), "combo_points" ) end - removeStack( "bloodtalons" ) - - if buff.eye_of_fearful_symmetry.up then + --Legacy / PvP + if legendary.eye_of_fearful_symmetry.enabled and buff.eye_of_fearful_symmetry.up then gain( 2, "combo_points" ) removeStack( "eye_of_fearful_symmetry" ) end - - if talent.sabertooth.enabled then applyDebuff( "target", "sabertooth" ) end - - opener_done = true + if pvptalent.ferocious_wound.enabled and combo_points.current >= 5 then + applyDebuff( "target", "ferocious_wound", nil, min( 2, debuff.ferocious_wound.stack + 1 ) ) + end + -- opener_done = true end, copy = { 22568, "ferocious_bite_max", 441591, "ravage" } @@ -1965,8 +1986,11 @@ spec:RegisterAbilities( { applyBuff( "jungle_stalker" ) if talent.ashamanes_guidance.enabled then applyBuff( "ashamanes_guidance", buff.incarnation.remains + 40 ) end setCooldown( "prowl", 0 ) - applyBuff( "overflowing_power", nil, 0 ) - energy.max = energy.max + 50 + + for i = 1.5, spec.auras.incarnation.duration, 1.5 do + state:QueueAuraEvent( "incarnation_combo_point_periodic", IncarnationComboPointPeriodic, query_time + i, "AURA_TICK" ) + end + end, copy = { "incarnation_avatar_of_ashamane", "Incarnation" } @@ -2015,12 +2039,12 @@ spec:RegisterAbilities( { removeBuff( "iron_jaws" ) - if buff.eye_of_fearful_symmetry.up then + if legendary.eye_of_fearful_symmetry.enabled and buff.eye_of_fearful_symmetry.up then gain( 2, "combo_points" ) removeStack( "eye_of_fearful_symmetry" ) end - opener_done = true + -- opener_done = true end, }, @@ -2128,7 +2152,7 @@ spec:RegisterAbilities( { handler = function () applyDebuff( "target", "lunar_inspiration" ) debuff.lunar_inspiration.pmultiplier = persistent_multiplier - gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1, "combo_points" ) + gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1 + ( allow_crit_prediction and crit_pct_current >= 95 and 1 or 0 ), "combo_points" ) if buff.bs_inc.up and talent.berserk_frenzy.enabled then applyDebuff( "target", "frenzied_assault" ) end if talent.bloodtalons.enabled then @@ -2217,24 +2241,20 @@ spec:RegisterAbilities( { usable = function () return combo_points.current > 0, "no combo points" end, handler = function () - if talent.tear_open_wounds.enabled and debuff.rip.up then - debuff.rip.expires = debuff.rip.expires - 4 - end applyDebuff( "target", "rip", action.primal_wrath.apply_duration ) active_dot.rip = active_enemies spend( combo_points.current, "combo_points" ) - removeStack( "bloodtalons" ) - removeBuff( "coiled_to_spring" ) + if talent.bloodtalons.enabled then removeStack( "bloodtalons" ) end + if talent.coiled_to_spring.enabled then removeBuff( "coiled_to_spring" ) end + if talent.rip_and_tear.enabled then applyDebuff( "target", "tear" ) end - if buff.eye_of_fearful_symmetry.up then + if legendary.eye_of_fearful_symmetry.enabled and buff.eye_of_fearful_symmetry.up then gain( 2, "combo_points" ) removeStack( "eye_of_fearful_symmetry" ) end - if talent.rip_and_tear.enabled then applyDebuff( "target", "tear" ) end - - opener_done = true + -- opener_done = true end, }, @@ -2278,7 +2298,7 @@ spec:RegisterAbilities( { school = "physical", spend = function () - return 35 * ( buff.incarnation.up and 0.75 or 1 ), "energy" + return 35 * ( buff.incarnation.up and talent.incarnation_avatar_of_ashamane.enabled and 0.75 or 1 ), "energy" end, spendType = "energy", @@ -2289,13 +2309,13 @@ spec:RegisterAbilities( { min_ttd = 6, damage = function () - return calculate_damage( 0.16, true ) * ( effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.infected_wounds.enabled and 1.3 or 1 ) + return calculate_damage( 0.16, true ) * ( effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.infected_wounds.enabled and 1.3 or 1 ) * ( 1 + 0.05 * talent.instincts_of_the_claw.rank ) end, tick_damage = function () - return calculate_damage( 0.2311, true ) * ( effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.infected_wounds.enabled and 1.3 or 1 ) + return calculate_damage( 0.2311, true ) * ( effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.infected_wounds.enabled and 1.3 or 1 ) * ( 1 + 0.05 * talent.instincts_of_the_claw.rank ) end, tick_dmg = function () - return calculate_damage( 0.2311, true ) * ( effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.infected_wounds.enabled and 1.3 or 1 ) + return calculate_damage( 0.2311, true ) * ( effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.infected_wounds.enabled and 1.3 or 1 ) * ( 1 + 0.05 * talent.instincts_of_the_claw.rank ) end, -- This will override action.X.cost to avoid a non-zero return value, as APL compares damage/cost with Shred. @@ -2311,19 +2331,18 @@ spec:RegisterAbilities( { applyDebuff( "target", "rake" ) debuff.rake.pmultiplier = persistent_multiplier - removeBuff( "sudden_ambush" ) - - if talent.doubleclawed_rake.enabled and active_dot.rake < true_active_enemies then active_dot.rake = active_dot.rake + 1 end + if talent.sudden_ambush.enabled then removeBuff( "sudden_ambush" ) end + if talent.doubleclawed_rake.enabled then active_dot.rake = min( true_active_enemies, active_dot.rake + 1 ) end if talent.infected_wounds.enabled then applyDebuff( "target", "infected_wounds" ) end - - gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1, "combo_points" ) - + if buff.bs_inc.up and talent.berserk_frenzy.enabled then applyDebuff( "target", "frenzied_assault" ) end if talent.bloodtalons.enabled then applyBuff( "bt_rake" ) check_bloodtalons() end - if buff.bs_inc.up and talent.berserk_frenzy.enabled then applyDebuff( "target", "frenzied_assault" ) end + gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1 + ( allow_crit_prediction and crit_pct_current >= 95 and 1 or 0 ), "combo_points" ) + + end, copy = "rake_bleed" @@ -2432,7 +2451,7 @@ spec:RegisterAbilities( { gcd = "totem", school = "physical", - spend = function () return 30 * ( buff.incarnation.up and 0.75 or 1 ) end, + spend = function () return 20 * ( buff.incarnation.up and 0.75 or 1 ) end, spendType = "energy", talent = "rip", @@ -2472,12 +2491,17 @@ spec:RegisterAbilities( { debuff.rip.pmultiplier = persistent_multiplier spend( combo_points.current, "combo_points" ) - removeStack( "bloodtalons" ) - - if buff.eye_of_fearful_symmetry.up then gain( 2, "combo_points" ) end + if talent.bloodtalons.enabled then removeStack( "bloodtalons" ) end if talent.rip_and_tear.enabled then applyDebuff( "target", "tear" ) end - opener_done = true + if legendary.eye_of_fearful_symmetry.enabled and buff.eye_of_fearful_symmetry.up then + gain( 2, "combo_points" ) + removeStack( "eye_of_fearful_symmetry" ) + end + + + + -- opener_done = true end, }, @@ -2491,7 +2515,7 @@ spec:RegisterAbilities( { spend = function () if buff.clearcasting.up then return 0 end - return 40 * ( buff.incarnation.up and 0.75 or 1 ) + return 40 * ( buff.incarnation.up and talent.incarnation_avatar_of_ashamane.enabled and 0.75 or 1 ) end, spendType = "energy", @@ -2502,7 +2526,7 @@ spec:RegisterAbilities( { end, damage = function () - return calculate_damage( 1.025, false, true, ( talent.pouncing_strikes.enabled and effective_stealth and class.auras.prowl.multiplier or 1 ) * ( talent.merciless_claws.enabled and bleeding and 1.2 or 1 ) * ( buff.clearcasting.up and class.auras.clearcasting.multiplier or 1 ) * ( talent.berserk.enabled and buff.bs_inc.up and class.auras.berserk.multiplier or 1 ) ) + return calculate_damage( 1.025, false, true, ( talent.pouncing_strikes.enabled and effective_stealth and class.auras.prowl.multiplier or 1 ) * ( 1 + ( talent.instincts_of_the_claw.rank * 0.05 ) ) * ( talent.empowered_shapeshifting and 1.06 or 1 ) * ( talent.merciless_claws.enabled and bleeding and 1.2 or 1 ) * ( buff.clearcasting.up and class.auras.clearcasting.multiplier or 1 ) * ( talent.berserk.enabled and buff.bs_inc.up and class.auras.berserk.multiplier or 1 ) ) end, -- This will override action.X.cost to avoid a non-zero return value, as APL compares damage/cost with Shred. @@ -2510,18 +2534,14 @@ spec:RegisterAbilities( { handler = function () if talent.fluid_form.enabled and buff.cat_form.down then shift( "cat_form" ) end - - removeBuff( "sudden_ambush" ) - gain( 1 + ( talent.berserk.enabled and buff.bs_inc.up and 1 or 0 ) + ( talent.pouncing_strikes.enabled and buff.prowl.up and 1 or 0 ), "combo_points" ) - + if talent.thrashing_claws.enabled and talent.thrash.enabled then applyDebuff( "target", "thrash_cat" ) end if talent.bloodtalons.enabled then applyBuff( "bt_shred" ) check_bloodtalons() end - if talent.cats_curiosity.enabled and buff.clearcasting.up then - gain( 40 * 0.25, "energy" ) - end + gain( 1 + ( talent.berserk.enabled and buff.bs_inc.up and 1 or 0 ) + ( talent.pouncing_strikes.enabled and buff.prowl.up and 1 or 0 ) + ( allow_crit_prediction and crit_pct_current >= 95 and 1 or 0 ), "combo_points" ) + removeStack( "clearcasting" ) end, }, @@ -2648,7 +2668,7 @@ spec:RegisterAbilities( { cost = function () return max( 1, class.abilities.swipe_cat.spend ) end, handler = function () - gain( talent.berserk.enabled and 2 or 1, "combo_points" ) + gain( talent.berserk.enabled and 2 or 1 + ( allow_crit_prediction and crit_pct_current * active_enemies >= 230 and 1 or 0 ), "combo_points" ) if talent.bloodtalons.enabled then applyBuff( "bt_swipe_cat" ) @@ -2739,7 +2759,7 @@ spec:RegisterAbilities( { end -- if target.within8 then - gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1, "combo_points" ) + gain( talent.berserk.enabled and buff.bs_inc.up and 2 or 1 + ( allow_crit_prediction and crit_pct_current * active_enemies >= 230 and 1 or 0 ), "combo_points" ) -- end if talent.bloodtalons.enabled then @@ -2787,36 +2807,41 @@ spec:RegisterAbilities( { handler = function () shift( "cat_form" ) applyBuff( "tigers_fury" ) - if azerite.jungle_fury.enabled then applyBuff( "jungle_fury" ) end if talent.savage_fury.enabled then applyBuff( "savage_fury" ) end if talent.tigers_tenacity.enabled then addStack( "tigers_tenacity", nil, 3 ) end + if talent.killing_strikes.enabled and buff.ravage_upon_combat.up then + applyBuff( "ravage" ) + removeBuff( "ravage_upon_combat" ) + end + -- Legacy if legendary.eye_of_fearful_symmetry.enabled then applyBuff( "eye_of_fearful_symmetry", nil, 2 ) end + if azerite.jungle_fury.enabled then applyBuff( "jungle_fury" ) end end, }, } ) +spec:RegisterRanges( "rake", "shred", "skull_bash", "growl", "moonfire" ) ---[[ spec:RegisterSetting( "owlweave_cat", false, { - name = "|T136036:0|t Attempt Owlweaving (Experimental)", - desc = "If checked, the addon will swap to Moonkin Form based on the default priority.", - type = "toggle", - width = "full" -} ) ]] +spec:RegisterOptions( { + enabled = true, -spec:RegisterSetting( "frenzy_cp", 2, { - name = strformat( "%s: Combo Point Cap", Hekili:GetSpellLinkWithTexture( spec.abilities.feral_frenzy.id ) ), - desc = strformat( "In the default priority, %s will only be recommended if you have fewer than the specified number of Combo Points. " - .. "When %s (or %s) is active, this cap is raised by one point.\n\n" - .. "Default: |cFF00B4FF2|r", Hekili:GetSpellLinkWithTexture( spec.abilities.feral_frenzy.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.berserk.id ), - Hekili:GetSpellLinkWithTexture( spec.abilities.incarnation.id ) ), - type = "range", - min = 1, - max = 5, - step = 1, - width = "full", + aoe = 3, + cycle = false, + + nameplates = true, + nameplateRange = 10, + rangeFilter = false, + + damage = true, + damageDots = false, + damageExpiration = 3, + + potion = "tempered_potion", + + package = "Feral" } ) --[[ TODO: Revisit due to removal of Relentless Predator. @@ -2840,10 +2865,7 @@ spec:RegisterSetting( "use_funnel", false, { width = "full" } ) ]] -spec:RegisterStateExpr( "funneling", function() - return settings.use_funnel and talent.taste_for_blood.enabled and talent.relentless_predator.enabled and not talent.tear_open_wounds.enabled -end ) - +--[[ Currently handled by the APL spec:RegisterSetting( "zerk_biteweave", false, { name = strformat( "%s Biteweave", Hekili:GetSpellLinkWithTexture( spec.abilities.berserk.id ) ), desc = function() @@ -2857,6 +2879,65 @@ spec:RegisterSetting( "zerk_biteweave", false, { spec:RegisterVariable( "zerk_biteweave", function() return settings.zerk_biteweave ~= false +end )--]] + +--[[ spec:RegisterSetting( "owlweave_cat", false, { + name = "|T136036:0|t Attempt Owlweaving (Experimental)", + desc = "If checked, the addon will swap to Moonkin Form based on the default priority.", + type = "toggle", + width = "full" +} ) ]] + +spec:RegisterSetting( "rip_duration", 9, { + name = strformat( "%s Duration", Hekili:GetSpellLinkWithTexture( spec.abilities.rip.id ) ), + desc = strformat( "If set above |cFFFFD1000|r, %s will not be recommended if the target will die within the specified timeframe.", + Hekili:GetSpellLinkWithTexture( spec.abilities.rip.id ) ), + type = "range", + min = 0, + max = 18, + step = 0.1, + width = 1.5 +} ) + +spec:RegisterSetting( "frenzy_cp", 2, { + name = strformat( "%s: Combo Point Cap", Hekili:GetSpellLinkWithTexture( spec.abilities.feral_frenzy.id ) ), + desc = strformat( "In the default priority, %s will only be recommended if you have fewer than the specified number of Combo Points. " + .. "When |W%s|w or |W%s|w is active, this cap is raised by one point.\n\nDefault: |cFFFFD1002|r", + Hekili:GetSpellLinkWithTexture( spec.abilities.feral_frenzy.id ), + Hekili:GetSpellLinkWithTexture( spec.abilities.berserk.id ), + Hekili:GetSpellLinkWithTexture( spec.abilities.incarnation.id ) ), + type = "range", + min = 1, + max = 5, + step = 1, + width = 1.5 +} ) + +spec:RegisterSetting( "vigil_damage", 50, { + name = strformat( "%s Damage Threshold", Hekili:GetSpellLinkWithTexture( class.specs[ 102 ].abilities.natures_vigil.id ) ), + desc = strformat( "If set below |cFFFFD100100%%|r, %s may only be recommended if your health has dropped below the specified percentage.\n\n" + .. "By default, |W%s|w also requires the |cFFFFD100Defensives|r toggle to be active.", + Hekili:GetSpellLinkWithTexture( class.specs[ 102 ].abilities.natures_vigil.id ), + class.specs[ 102 ].abilities.natures_vigil.name ), + type = "range", + min = 1, + max = 100, + step = 1, + width = 1.5 +} ) + +spec:RegisterSetting( "allow_crit_prediction", true, { + name = strformat( "%s Combo Point Prediction", Hekili:GetSpellLinkWithTexture( 159286 ) ), -- Primal Fury + desc = strformat( "This setting enables prediction of an additional combo point on critical strikes when talented into %s.\n\n" .. + "This prediction activates only when it is |cFFFFD10095%%|r certain a critical strike will occur based on your critical strike chance and the number of targets the spell will hit.", + Hekili:GetSpellLinkWithTexture( 159286 ) + ), + type = "toggle", + width = "full", +} ) + +spec:RegisterVariable( "allow_crit_prediction", function() + return settings.allow_crit_prediction ~= false end ) spec:RegisterSetting( "lazy_swipe", false, { @@ -2864,7 +2945,8 @@ spec:RegisterSetting( "lazy_swipe", false, { desc = function() return strformat( "If checked, when %s is talented, the use of %s will be minimized in multi-target situations even if " .. "%s is talented.\n\nThis option is a DPS loss but can be easier to execute correctly.", - Hekili:GetSpellLinkWithTexture( spec.talents.wild_slashes[2] ), Hekili:GetSpellLinkWithTexture( spec.abilities.shred.id ), + Hekili:GetSpellLinkWithTexture( spec.talents.wild_slashes[2] ), + Hekili:GetSpellLinkWithTexture( spec.abilities.shred.id ), Hekili:GetSpellLinkWithTexture( spec.talents.bloodtalons[2] ) ) end, type = "toggle", @@ -2878,7 +2960,8 @@ end ) spec:RegisterSetting( "regrowth", true, { name = strformat( "Filler %s", Hekili:GetSpellLinkWithTexture( spec.abilities.regrowth.id ) ), desc = strformat( "If checked, %s may be recommended when higher priority abilities are not available or recommended.\n\n" - .. "This recommendation generally occurs at very low energy, regardless of your current health.", Hekili:GetSpellLinkWithTexture( spec.abilities.regrowth.id ) ), + .. "This recommendation generally occurs at very low energy, regardless of your current health.", + Hekili:GetSpellLinkWithTexture( spec.abilities.regrowth.id ) ), type = "toggle", width = "full", } ) @@ -2891,33 +2974,13 @@ spec:RegisterStateExpr( "filler_regrowth", function() return settings.regrowth ~= false end ) -spec:RegisterSetting( "rip_duration", 9, { - name = strformat( "%s Duration", Hekili:GetSpellLinkWithTexture( spec.abilities.rip.id ) ), - desc = strformat( "If set above 0, %s will not be recommended if the target will die within the timeframe specified.", - Hekili:GetSpellLinkWithTexture( spec.abilities.rip.id ) ), - type = "range", - min = 0, - max = 18, - step = 0.1, - width = "full", -} ) - -spec:RegisterSetting( "vigil_damage", 50, { - name = strformat( "%s Damage Threshold", Hekili:GetSpellLinkWithTexture( class.specs[ 102 ].abilities.natures_vigil.id ) ), - desc = strformat( "If set below 100%%, %s may only be recommended if your health has dropped below the specified percentage.\n\n" - .. "By default, |W%s|w also requires the |cFFFFD100Defensives|r toggle to be active.", class.specs[ 102 ].abilities.natures_vigil.name, class.specs[ 102 ].abilities.natures_vigil.name ), - type = "range", - min = 1, - max = 100, - step = 1, - width = "full" -} ) - spec:RegisterSetting( "solo_prowl", false, { - name = strformat( "Solo %s in Combat", Hekili:GetSpellLinkWithTexture( spec.abilities.prowl.id ) ), - desc = strformat( "If checked, %s can be recommended in combat when %s is active when you are solo.\n\n" - .. "This option is off by default because %s may cause you to drop combat outside of a group/encounter sitation.", - Hekili:GetSpellLinkWithTexture( spec.abilities.prowl.id ), Hekili:GetSpellLinkWithTexture( spec.auras.jungle_stalker.id ), spec.abilities.prowl.name ), + name = strformat( "Allow %s in Combat When Solo", Hekili:GetSpellLinkWithTexture( spec.abilities.prowl.id ) ), + desc = strformat( "If checked, %s can be recommended in combat when %s is active and you are solo.\n\n" + .. "This option is off by default because |cFFFF0000it may drop combat|r outside of a group/encounter situation.", + Hekili:GetSpellLinkWithTexture( spec.abilities.prowl.id ), + Hekili:GetSpellLinkWithTexture( spec.auras.jungle_stalker.id ), + spec.abilities.prowl.name ), type = "toggle", width = "full", } ) @@ -2926,8 +2989,11 @@ spec:RegisterSetting( "allow_shadowmeld", nil, { name = strformat( "Use %s", Hekili:GetSpellLinkWithTexture( spec.auras.shadowmeld.id ) ), desc = strformat( "If checked, %s can be recommended for |W%s|w players if its conditions for use are met.\n\n" .. "Your stealth-based abilities can be used in |W%s|w, even if your action bar does not change. |W%s|w can only be recommended in boss fights or when you " - .. "are in a group (to avoid resetting combat).", Hekili:GetSpellLinkWithTexture( spec.auras.shadowmeld.id ), C_CreatureInfo.GetRaceInfo(4).raceName, - spec.auras.shadowmeld.name, spec.auras.shadowmeld.name ), + .. "are in a group (to avoid resetting combat).", + Hekili:GetSpellLinkWithTexture( spec.auras.shadowmeld.id ), + C_CreatureInfo.GetRaceInfo(4).raceName, + spec.auras.shadowmeld.name, + spec.auras.shadowmeld.name ), type = "toggle", width = "full", get = function () return not Hekili.DB.profile.specs[ 103 ].abilities.shadowmeld.disabled end, @@ -2937,26 +3003,4 @@ spec:RegisterSetting( "allow_shadowmeld", nil, { } ) -spec:RegisterRanges( "rake", "shred", "skull_bash", "growl", "moonfire" ) - -spec:RegisterOptions( { - enabled = true, - - aoe = 3, - cycle = false, - - nameplates = true, - nameplateRange = 10, - rangeFilter = false, - - damage = true, - damageDots = false, - damageExpiration = 3, - - potion = "spectral_agility", - - package = "Feral" -} ) - - -spec:RegisterPack( "Feral", 20241022, [[Hekili:T3ZFVnUnY(zzrr9A3K4yPeVBBXMa0R9vCT4U(o0uG7poCXwXMorVil5tsoEtrG)S)MH)sKuKu0o2B337o0I2yjQHdho)MdjVn62F72BMNutU9xIhfFz0O44Hrxo(9xm(2BQFEf52BwLm7XK7H)ipzj8F)rszsg(0NZksMJFDvX6YzWBU9M7wNMv)t53ENDqEb02vKz3(lrJG)8H05ZjS2sQMD7nyBplA0zXXF72PrrdhnC82FE7ptF8OV5S4i4X3KU873oD9ke6QVmAe8YFm9JW)HuwmlTyD12P)PuOrtxM8XjKCs59pR(bJU80TtX))x7bQJUaE5VTHK842P1jL3tQtZVVPbF9zXxk)6vLPfLP1p3goF9zrJHM9DZ)FwxvBbbxuuUD6FpnBEvDs2JKsTVeh0)1KsabkwaiXdewtp1Fhshv)uEnPSC9kOptYNd4zrb(9YM9Eg6)BuyMqXH6hsZHP2YIfPzWeAYS60I8QHRkjZkwExs9jxD(sazMuSycaQjBamz7pBRvai2KDA6IREZDRxSyi9NdxVYEJNLupbiclBAV4j0p5l2oD2dKzajifjbLP5psGXuvwb8FNvKxNKMdeZe4r1jWJkYbssfmO6)uszAYDzWFMcnGr(FKGeKuOnZsWgXiRW8k0IS0hrgM0YsCkjhH)MIYhXj9PBaIZ2PpKunbG9eelhyF0i60trXLR4O7Ki6NuD6tjzRLpDy0qva27nnppTAy6YvKYfKz1tsQMrYNNKp75jvKY1lnAyXtP5jFSAYss5S1qNNnHC)9gTbOtZkOy7KhtRQWzW5KeyiTdJHyRJHyhJH4qhdXbmgI9pg(cgVXgy2lPe(pRYsEMoRfJtN5RrXm4RFQ4rYPSMbJ2fGOMAdkYpJY2u8e(IlA)cYtKCgJqXAG14osjmsEeeHEGKuwRiHMbO4UqyJMu9C(StlwDvfOIzbNahX()tizvKRaLHNcJG5PimVcuuqYRhYhsuzXQvPG2GkGKXExs1djltYjvtUFDks3j9eD(qdMYE9ByvMvuKnVyt(W5RltW(6l)YO4rxn6LxG)3x(LEA4vJ2jbI4)GgZXh8XSoZx(BR7I)dq9Cw7NLa)bsh043MnVsOVHZJbnkb1X9qrD2UqK3zgR30FViZd2xEl5JURAsA(mfc7lV46DDmJ8YlH1JwgH27EFnSBUJWNS2zjId3KvlHI4d)KLfqQoz5VhpWtwwXfMOm3TQ0FNi91OcfzrplYsZjNbUKWfob50ZUEj49XzAoEapmRi)E0iYS5na5SRREOOSgFSOpv6HDGpr44NjNsSkNsKkFItHtxmcV8IBweV8inVdC5B2WK8NNmFvZmWGVQF0WXN00k01bQhFj3NMbJjAdIT1GLjvaTdBGfudfCgm46(Ev208UqWTOUWTOGWTioUHUDZNIvDpM(5crgaB75WF5U8swkUVidKYPpv9BRECDw2K7aDbApLhqWxaS9)fG1gJKy70paos)a4D0vV9H66vvF75NVzZMHBk2aE5mhiRlphIHll7QOrJE3OZxvSHuEwA(I1vauF71)n83yShSh8HZtUwiU8Ny2YgY6Wg0iLjXs(iqdZbh)WXgJJNc8jcGBsVwV6LxedBUDYjupXeHNO5ggLcceb2pH3vvZ6ezqcgOvvDXQjlr)sVh757NnFyjbL2RUAupY)AD6QvK529BvTtRtbnbvtwSU8zem9zHIoCozr6S06RVymQ8A5DftwvKMxxDLXVV(Ql6nVOEyz6kO7xusa15aY2JriYkkMduauVX6vd61)UIQQElsV)H6jCC9dxfbqSVP6z(BVoEKEZVE8aRToz(Zgnmk(LxWUBWa1rBzc4HZSNNLbAGPbmxbAIeZBaQdqDjjBoDUZjNEEs9AyGo5PuqWd)APuvj5EO91p0dMNZQFyieCbevr9hE)iySBWAq)Tc1hPqAOkmtSjju4R(LjZtwvN(eyGztcipAz4IZy6TAYCWk89KHGLIzp(Hl61)nUBtD6mmMZxEXDteZUXd69ggIz0WHP5twKHZy96tLxBqWgPM153vMopJmN9nadKGvtIcpqklMuxsidNxIAw4IwZYs2my3OjTuz1nrYoAoKKJtwZ7PnUgwTjDfGyj1xh1ZyyOIOlePFzYDP1ejILSI8rWYkzEsDbWWmRmbf8PAwBuQNtaC4U6Ei0aC(UAGYKEpYHDv8GU10ieRoTc(Sz1nSkAO6xi0xUrjLqSm4qZiXDf4llbJsyagiN92PNSD6tK08suNujeHrwXgW5dqzo8KkEgMQYtwbEGaqaeNRkWWjWSISb8jrZQa8jiEzW00RHrqbV6jDbLHpubnX0wdgnqiDQPVsr7DZZv4bf84J71suwQeAupdLLG2R(UAoWrPRQDGfTen6nh0UFb2btLZI2l1zAbybWBSinpTcOXiPxhj7(BXSUoN9PoejG5pvGcKufpvsxcsQ4RkY(a6l9Bm53v8ge9CAgorFxDadQKcmPqDHCxFv8rg7eQ1Ls7cb9NbnkPlQHOJqgYETTdurYiSrfIixJobSm5JkoZnuzm2YJDf8H7So3vDZXavQhzvWCzIrBuIUQn9bq)nbtAj6YVRUK1yKqIdpvFeeIxSwG4bQ2UYMgnM4jOpJ2uMPs0BONksNJPPy1kQ2M7kRWKXIZGvd3o97YQkafleu30DLRHUdtllaas15BGwsNIzjBfW5tfzqtKTeSZHbBbo(kMbGOrnWP0GKy9P0Tr7JFwhpH2V2S7O4nJslhUa9igI1IoyOZUF4siAuo728u6pltatEisJwQMxjvoaVYWFdDJrGIHZ8z5CGV5akvdbzFZOdE5fTE5dD0jUOysjpK8W5rqL6t4ZD96hoz41qf(ere0mOkzqzSGCoum69XNiwKNkroGbVzbwWZxwuKViTKeg9uN013g91LIWldHI4EEvgvj1ck4jUAedmVjPpD1Y1z1PRYsjLFiAO3oL2Em0cUtMCOIHdOhqelI0Q14s6njz5DRPAr61OTE2SjOAeYCNurz0bFYgcUqATitSpgaMQ5ZySia)deJBxmjUImsvHnNxzEXA4xi7lmsWVlOHNl0e5TVO2QmWPnQORqfT10Stv)aMvA(4b5)rlq0Xzq8)7a)ECq870rrwQcj2c6MxKFMYec3KJlmwajks3XKIhuuag30)9Nx41mLVinldSAgKftmBsbnjeWC)Rcqpa(K1KBlpAsGOxEMbpVSpi881H6(n969vAb4c8Dj4YuFxTmps7khGtna2jk(zrqRL7Req388(GU)0aD4gfsMMoydyPw1ch0UoaCya6DVIXGoFyade1OpSy83irL00ncEIn2L1U(7MP2bFviAMOpWiYzE)RMeqBdeD)a(mF00K(YVaZE(9LjZjSqAQQPPqKzqcT0I5AVCtkwibCuJzMAvs(CYY0zq8u)ajl5zHjSeSGukWiGW)Avrvv6D0szbIEkLwzkRrt5ihbRBTqlPSXymq9vnTScghqm6GIMjnuJRTYBRq5KjrzOmVjTO(2HSna715FbH32qY04v4r3fOZgT7snDL6MPT18DoGC7sbCnBume0dLuolPQ2DojTy3dxntG6aHDZk)nlbEl5eNxWRkkAbSKt(i8ZOHJboV)XFM8yAw6)C70F7)(h(Vz17gljaawtDaJMdacwDcBaZGLK)1AyqM9mTUQWSpcKoAa9eO5lPRZeIit3KKwpD7uAgrai8aJF(oK1NwQCWWWQIoyibtTSIo8ueixnAySMUtyWmHpYMubtE9mw0L3pQxR0iXfOBcL1xc9U(Iqyn3x(TgxHcAA2cauDkRdCGzrbRXUS0vcDp0egJUX0OSjVwvxd8WkLuk7r1t3gg3f9rHiEURUUSZMI5o(zAlwWWCcUKMZskZPlRmcjJvo79SvoJs1X4wmkBXMQo4ESohHNnN9w56hau(cvJdnZqPynFUGGXiXI3tPQiptf6wrBSi(sRjlpfRTsr9gW8lvBrVX2XwQgRvmsZIlQMUwJcjyq4yqSkge7edIcfdIKyWxOuHvm6ftyNVUk2WqE7LQMnClOVJvj1hS4RWSU(hkYvxmVatmmktcAvWQELWl0qArILjx1(K7PzoohvbZkwfur)J0FVQG1ZCKIf(mvpF1Z51y6STGBSpQnEXgpglY8fWWSFdHgr1Fhgy90EcV0C65TwDeqmIxoo5kvjdkqKuEgJtgRgUKNiO9dwFa6UwNHpg)Inpqq3TGFikKx4NptH093ZYAarTwIbRzOu23)dGxy)yH49yfcxj(uCMydvUkltycfRM9uWMY2PF3F7VG2zbisZm(pY63nIQoMvyPkYWd9Y(Z0nyvWT6urXRwPma4vNmUEbLnLgU)oPTuUljL2lUULfzRltMXJh0RFqZ9VdGVl1gbX9CMhLsJg0SUJ2QBohvkHFqoagAVrxdLOvwRWn(xAPmRetDxfnqTqgTwXsxRByPhZOsOZ4XwNXJ)8zgpAFMXTye41oJBfKAZ4roMXB)L(MXJhOYRSdZ4k1TK6S(C6IIKmdxEK1vWFNKxTmftA6K6KkxwWE5fDv7XXwzPwG7cOjGl25)(ZSWWuwaxSgtA5nT67JzzMoBtYZAwX4tpTQ(z0n0NlwZkyABOJL5v64RTPkFvd1LJnX7aQWmrXny6iG(iU9sLP)(laWWY00qLvq66XN5SmEfLbttzyPTkYNlZgXQnOndrSFmJMVB44tqkpzb3ZZvBov18gqnQjjy4y0TOK(hxMSCvc6TjRwAWTGedlXi2O7Ii6(JG3mn4Yah4u6tWC(CXcUjMVFhZE9ccTgcfRxW2P)Kw3)Rjpb(9Xbl10OWmCsgg1j79Sf(492HOKfsu2f0eOLUeyP3asA0O30x0c13EDuV(08mP(WgDzdhBgljllkgTwMwaSI7EJSmAO0SjckRSwN67fDOftgD5ZHaXFeeWrYBLOMI4OtjLUqrhpa7DNirfS5d4RGAjgCiYgubaeD2smZHK3vBqFkroI1RGPRFnvwI0klPpF7B1WOGZQAUBl4r4kdUJaHHs4DnMDD03UflKBGI58SLXtHHT5uSwM6yDwKKEvQGbfcRfODPcMSQw1SSM8z6eGHOzAAVE5fXJVSN(C6a780fQ5kbiNtWm7CvK1gBuzCn7BsSyYBteFJz8kDdsxRiGcqy6WkqFMjFCfjVkff5Xurq)ywSl38a1B9tWnViRszobf7PBUMlhDc8VxmMNeJOOXI8FHjyLxtjS4ZzboJa8I4tG)n(R5F03el2WOIXKWQ9jML4dzbU72WQbK9j615d7zN0)YrFfDGQLhpAvoo4K(x8vC8RKCpjhEW4rFvFFCh0uWYeljaOwMutvLcMnabN860mvTLK8I13)qtoaTwUnddyKQwjw6JY(9bQ8znRUIbj5S(XxWg(kPfbzzh8LAdCweV0ugwsQxxMtdWzDlZpj8SvMd0s6SPid6OjN87jbmwmtqOyG4AvaPA7BYoK0frJhlCt7Rgn8cWjNbdAQ)JS15jyPSJoNqBddMQ5UsdQAVWgC77APOCKB(bAlnsthXsdNzhWMlk15xQnNjIyQ)hHBpTzpwXsmHQk)UNj45wtSNsBPnTxl1USIdg1H9fSkttMEmfHlAWZik1ngix6Coo4qq9Q(rclJllwI5Qe8be4oqx3zKl6MuwyMd0)HPoG8rO)rNsIuCULr(5kIqlQldanvYGIGBnKaJoXBJK79LR1JRieiRBzkikG0F(z0CzzHomTR)5Bz(1btpieW1NOAfDl)UGNXLtLRtbFtJ)fHWeiYyvlsREecNy(Cbb8KXhisiWjww8rQoDpeswY5SqhzEDPS)YkeeOWOb8S(zsfmYG4jTEHKoe5MqycKOXwg)fRWgHfsAtE9y5ZelZuQPbwP5YljE(U4GrkWyf(nWWbvJWcuxeM3oYIeqbzaeazzcdw3asU0(g8xOEaeZ59TFmfyfVVaNYOlsZCjd(3v8F96qWM6wqIIb8v7wvixxsRHLMATQ9I84SNKgTeFtTUwvDxIfid4f4QsYtTnrE7npHRme8h0ZrKrFtC0T3Sb8GaNmU9g6bxr6YvfL1CX)3QuzfVf5n(xRtPEkwvG(gLSUUG7S0Shqpfq)EyB8n8ih57bbvsj91V1UFaVLjq54TIy1Gw1p6JdKW(s7WwTc5maS6RCb1XhfO(12HAR6rYa0TEVl4)nhfSoYbX4Gm9f9UJgnz7pBHhMRo4GW)2SBqnqUMx4CypYoin2mwgW1Xw1QfWDitOSlImaSYB2vG2SpKmGzZl2vqQ4pQbmv9unS5B5g(E3MXBHzTwHwuLRe74VTU1R9RQscuVNLlw6LUAF4DR1DyR9E0vtdVZCDeZyV)80A)6Q1wPiNZvTEDGaTlAVzV0v7dVBdBUYBtdVZcEUQRwR1Lo02BXlEdjFB(57qTIJ(ODo(n6c3lcqN9q7vKs4YUfwBBT5Oc(JgG)dcVlaPjAlQyE(hapINdSfztCUeP99HL2pnJS1YRgniCM6JicRGVDHUYzG3)jqU1rFCaLBB1dVsg0Jm4pAa(pi8(tLCBRZBPp3LBddH3h5whrCEqLBD0hhq52w9WRKb9id(JgG)p49)wG3T0t67OOBhu8eY5iODvLYhTxNnD21s1uowD0N(wAL940PRdv8)rtR3ls9RIshe9lCcDx0zjxVJSvEqTn5OpoG2MA1d8HVLZVVwkfS3MJk4pAa()G3)BbE)j02uBVIpcNBQ2GPMgZpPNCQ2XMpb2McJwVxK6xfLoi6x4e6UOZsU(2RpZRuEYCPpo0WpeiBTO3TaDxTl0rqO9dYYnzpGV5rhRfqBPjhyO7AHdcbY8t0wF4DttoWqFNX79n6MJn8dbYHXj6UDHoccTF2po(2hwYwa9EZXhm03doNo5jT2Kdm0dfVB7AJZq4Cz)mOt2BRg6CPw04CZ2qi24qZU9BTGoTonVTguOlMwt8jYl(06TwOOm8r6IZNoA(5FMrZp)tonFOJIMyVkYlhl76RSkHSIFIr0UHGXDiUFGk0EXiCVb356GtI)xCuiWEHDRIg0a6TEVl4FyR0hgmDuwATQFCdi369bY0jKxFvmDgwVAoOf8y7s2aTrVla3EFq3c0wBYre4U5YKGTdIHLg4N9vsL7eFT2KJiWLG11QjSF04axQI9d4Ub7riLThwu)Oc8aalY3QO5WgBTYRpI46rf4Dc2WdrkOqXE9DJ3iXCLm19tI)OcC3G9iiAEyr9JkWdaSEfnB96JiUEubENGn881fKO5RVB8NKKihEs66aKWGB3z7c0lqX2V(T7KxGoqA2(l3ad5B6ChIGo2kcQBVEd4PDWiSBqDpDpF7p)tuAgcQ3lo8uWdIe6Ei7NV9g6FH3TXk7Oi4N)c92sMdUB)t3EtXQBVPIulUQCV9gr0u4FLTM08aXMSI(KjSRszLDM1T13(lXgaxaZMDym7QsUmDf7fO8JNBmIBVbAAnb6)BVr9mRCAVTtFZ2P(J)s0Q(n7Vn5(edFfnWq1tb5TthGdIlCmiupCebet9KaajRkOAFLtjRooup3o9dqKBBN(YlBNQCSPO(yh3DbQnPVy0ipgcWbO2jaX2PxFf9o68m82E151naqdO)ByKoXHaj9Hgibo6zyNbE8HGrddMLpNUlpqgLlnyuAya4mM225xcs1(pzFiNP)mzAwiIjp2prY7yhYHnnsN94WCfzOnnAFoQVuZJZjyh3xa07zHl3DY(aUQP35KJZ2HgndBTEiKIJMOHbJj8JZybldBMq5EOG(uLd66TtVIEOkWGofkMNMdIxk7x5PyqZmn9SPgh3V)Z5XDxJq6lLhZ2bmSBo)WXX(x7qmaXc)MHmTyYzADUTo3tQIJrJMSP9BAeC49n7Ou(H7Yazxuy7tEoou6MI8moYJg5yOBzBKVltZbGjkx7h7YS4(DfMqhRMUDAWf)AgmHXo2IcIyLl)v1D1tJgWVzsuX5aWrZPEtFm3BGz30zKBxt6sBvZIP0Cfte4eH4e9whVWhsXjt75A40rWvEBrFG4HPr0WvOgKcu3u3U5IrNPm53SDPSqhhMgf9P(qoectTadpSkY0H5izh96jdw7EtZfboYuU7rCZNBHPn2LoAZHRhVnE3REuhBQ9CNh1oegOgxPhwd2snGXKPMd)9A7AJf)2m1V2wn0SMRtxbq5szTpGhA6aXxjdxxoXjVMWv7xrSAYwrV2WnAHRWnmVyqzPwHN)dzYs86CEF5b4h)(BG63aEc)HoQQEmQsDC26Z5X01J7yR(LPTYSU2X7OWMigZgEq7I)T(jw00pCfE6JidSPjVfAhBumhDgzdaxtr4bEGGWr52FyumpKwkYPhlOYrTJTqa8R3r7k6PjQ5gwvBIzMQ2SiL1C2n1ddSv9k2MkT)(rs6Tru6sCq)iesBiRDTHBZ549cJuOvSJAkVoFQFFwBQIZZTDTiIF2W)nm(uVxp4nXP59kcNc4yf374HH566cxGcg5J4k65og2Jn6yCCyVOi2ie20qz)z0WHLlxEa7MGBvbz4ZcDng75pSMinLn8XFG(rBmgCE1K3LFDins)AkNopgRj1OFeT2H71TgpSBYCQJEbPXxOEZQB2sbT0voto1NOleD1bTvjHEQ8XAiMCorUAjTo5IuzWAFiePA2XMrjDHqlRZHfbqvLbJBS3z5WLLX9YueB1gk3qvFFGqkfzZ68ahQZ1nQkgew167c36jomez4G0yQ1UzqhXv1g3dKjxScCwJxYbFLQ6djhMogiN6uL3vpvEzuUrsoK2kfWxiFQYQpPPrW7ytSwy2cHkGH21xjY4ZNHJn116ZwWAg6LTFjYthf29Vq)YKNkOXVq5vDYG9bSWlKNnyYameTBzs5JclNO6hd3X7o0bpXD4n9kMMvThwHPQ9UxNuJ6AquDWc9PkV27XvL92B9WMYEtDDorzyrIF4YspGwzFpMiv0ycaGAMcgL7El(fvGSsNzMAy3nqpswvZs3hEFdXoeLRXS4uHRinMkWLPLLYlYiW(0JkN1RALsT6IlZrlr1PBliTDywj2)SshhIy2BFyZkEp9USnGJBgWMkF5d40f32oVuEQYijoXAP79TOUWVXmGq)MTAHrumjBN(LyCDJelbeQuJ(ZVSRVJ1EZf9vS8S0Ji5vzjpt5CIrwQ814vXbFuZVnnyxSuAnqC9tXwUVlA)c26aVrCRFWxI3VLgofwvkm2zcYlZzXAXGIf7VtMWjKSk4VhnCSKRmYwiTkZT2GuBUewV(jKpi(tkFGxINPPnRcgAUXEyildomsiMzjXC4ZsaKR2einKwujbJj(2vVwrl)FqG4Oh5983w3LiFn9EubBpEVkH3gGZ0eXP3XGgxftvjOPniSPSdOSSzMAE1YYF6yDDjuBz7CDGzDT2dwyD7etoISUEWXUur1khBU0r5vBI75lT4fCmB25e65Ana)2jnVe4y(kkmIgoMMscNEtP0Y4aBPfuNj)YQaTRBH)w1ICUwdcg)n9r3n(7SLwM1AWFdTA8RiV0FNiHC1w(HTpE5XDgg2ftpfOY6SRXa81VvDHhIxxUOlmZM3aKZUU6bSmql1UZe4V0MMgXL1xxA4IK8YXSi58udPnmZ2RbiXn3dnhhJfASyzQ32ke2xP6D2X66Hn7eWsfBu1aUssJepvxrHDALU()TKK2XFRx4sUQJw2k2OjEiVP)WYVeV3(Yyje9rAr9Glwx5Mu0vD5T9ogSP4wtcVwS43KA06obVqPBUAPxvuvLsjvnxf407PDurcTBVvFP66l7ggfggYwVFVztE2P9AZkAjvCOr(dToB7Q)C1DYLgj8PyB54qnZH7w5lhwVBTWv0Q1glH43GukZknFE7QDW7sXUZvrUYcsQvgjUtDil)sQx)sDVqhskK3sOXmMhDtm0Cmk0R0UQMLIo0REmwj3tBWhRP2hb(Z)XFM8yAw6)uEbeDdEHgHt3aQqlZlAbwtqVN3SD6cC3zaKo8k9HDRNHfpcTAPjqZxs32diImDtsA9uCONHxgAGflQaiEnjMmhtHemMv0PwOCL)DRT1808YptrJQ2kS)EzjOALO)M2RsBVUs5oUU94v4sAn6WxS)fPnKj8qejA5i5U1f(llR9T2sOi(CTAlrVg0CvCDw0)pldVHmzAVPRSf2znQRXLYwQTgFyvZAFfmclRXM9rJEhRQO3o2OQQ8Q4YtH75Tp4f(MEpywQpsh92RTbKqZYjuoUlhr9QOTUo(Qqpq0WlOTt94wq5LJhjCM2VuNIHttpR)C5M2u1xBZZHcBoi2nbN5kcfPotTE1mao9TqdJVOzgr)4Uqer15TMhmOLhQ7ItT4ouwcmBEfgeDOtR0Q(i3(wUKsICCtxsjAJgEbB55If0k(AeZ7vNNbhQ9RTBctzpB92W0FF33RJ9VZRpKdSe0GocXuh6drmyooa3RPQ8fM2W3Z1CZtjeivpAE1BYxFEZX3R9UcvD0X1rVFlzLtLQxX0iWYpbBK78KwP9eyx30OQ4FtHZ7EnO8lY6nvBsMXtcoNCSmczucH9cTF(GXNABTqR2Upx8PQunLB4upRVtG0nZcW8eFzv9erDP8hhn6pORgvt6pEhO6z9HcK4BCtFQt9nVYqPVnke6VnWIFyhK(J1vQQjTJbbxlNb9260d9R1LmQXO4ODXOQomuQ(e75F3ZOq6(MYociWrW(DHPAn(RUzunJeqf3n2q(TccZl0faX2TGQAOiUUStnSN64Ayv3oNEcgzbQiKx8NRzlLt(7BkN8MrOIZW2CexgTelb5GBbyvWO(7MU0YIcWk(wH7w2wRfvmm2s9F1ALBmnCJBRoJYWPzneUhRBh4zcd78Ef3lKfQPbTjs608ASixWPeMMbLQ85mvO7ljU8MeBL6yEuI1I60(muPtQtKc1rBck2MNJYmPWmkzqqLMQyJFgliRWBBLipljaVFaBLb)zYupTtTqxSWKT43vtcYSjUvmhMVxstHsg1caE3kt9rLUi4z0SXHJGK7tqvt5yk8yAVqFCFK(7wgOqF(P5jS658ASm)Cniuh99AVltW4MLr2Oo)kSzt)kTNkD6Ax8GjAeN4B68LPe12MQE7EWx4Zy8(vcN9BuWxUodFm(fBEGGgEzXbqlLn4NptH093Z2gSef4w9qcn3dF)pa2a(XcX7XAKRs8P4K2gQKywMiBTvRiZsxGrn9D)T)cgRnar6jCXpYDdsu3DSYAsrQxjlQO0hmtTSYMZq7Iop3sImrbBSb9BEJ1cFUJmSgpwjc2GN6FNSVDRAnywPZ6wx(izW6nPNORc1WP39b3Fduin6fzO6HPL7cOqcrRvpGy1HfLW9GwfresivwHDmHPTD4LzawtKZQfgCTcyvSxLICdVSqXdcOs25aenWwB(L6ZCKxUG)pcJB0RIX1Hz2JgJR3(ZfJBKpgxBqSBg342mUTkTfFmUT9VWZkWySnaUsUnZSU2sMTnUHhgKcsYMSac753F2AKbIgAzUYmGXSnjpRz0xAm1Oy4WGjFUynAvkxZ4UBd5HTzrVCSDQGoBxNhvCkmnEChRnD19zLu72EHsNW2Xhd1o5Fy7W1Z2gsn2P4ciZrKALDtJLWzK(0PCcYzUchjSZiTZLvjXQnOIt9St(UHJpbNXjl4XjSAZPQUwaZl1KeCvxtXcJu)JltwUkbJnGTx6qXi2yLmhC74VlQmAEZ0GldCqiepLsJXLraf8zVJ5R0cYgQ7r8TtZ2P)Kw3)R0JJpoyP2heUaLKHj3G9EwYHEVviQY6QV1DujSk7RXM8RRD29PPwEOED5yWeB5BvkTGbQo7k3hDuY3ebr2CreccXFdRNP5DUIqEKuobP8vn7qvfuMFohkq5o6G3PMyz9JirPgCFrqt31J7YjvJg1X2zOOf0wXZevZ4VIDyOv9kIzyZTEOFxaKWu9tm0GIqw91SQNXC6YmhaL4cKJcTvWCmnVtC5muyy1gmqnu(D9kq46xX2Y1Z3mY5joSrSgLbvd9vkrZnzChzrbMKaAxJhdjv0myjR6658AUInPAlzbW3pbRVeTDxRE5D4j2DJ91RxoRwYOOAZpkw(v2Uu21b8qR(Xzy6w27Zuf8jRbfKL3EZFn5XKhsFmL(0B)F)]] ) \ No newline at end of file +spec:RegisterPack( "Feral", 20241022, [[Hekili:T3ZFVnUnY(zzrr9A3K4yPeVBBXMa0R9vCT4U(o0uG7poCXwXMorVil5tsoEtrG)S)MH)sKuKu0o2B337o0I2yjQHdho)MdjVn62F72BMNutU9xIhfFz0O44Hrxo(9xm(2BQFEf52BwLm7XK7H)ipzj8F)rszsg(0NZksMJFDvX6YzWBU9M7wNMv)t53ENDqEb02vKz3(lrJG)8H05ZjS2sQMD7nyBplA0zXXF72PrrdhnC82FE7ptF8OV5S4i4X3KU873oD9ke6QVmAe8YFm9JW)HuwmlTyD12P)PuOrtxM8XjKCs59pR(bJU80TtX))x7bQJUaE5VTHK842P1jL3tQtZVVPbF9zXxk)6vLPfLP1p3goF9zrJHM9DZ)FwxvBbbxuuUD6FpnBEvDs2JKsTVeh0)1KsabkwaiXdewtp1Fhshv)uEnPSC9kOptYNd4zrb(9YM9Eg6)BuyMqXH6hsZHP2YIfPzWeAYS60I8QHRkjZkwExs9jxD(sazMuSycaQjBamz7pBRvai2KDA6IREZDRxSyi9NdxVYEJNLupbiclBAV4j0p5l2oD2dKzajifjbLP5psGXuvwb8FNvKxNKMdeZe4r1jWJkYbssfmO6)uszAYDzWFMcnGr(FKGeKuOnZsWgXiRW8k0IS0hrgM0YsCkjhH)MIYhXj9PBaIZ2PpKunbG9eelhyF0i60trXLR4O7Ki6NuD6tjzRLpDy0qva27nnppTAy6YvKYfKz1tsQMrYNNKp75jvKY1lnAyXtP5jFSAYss5S1qNNnHC)9gTbOtZkOy7KhtRQWzW5KeyiTdJHyRJHyhJH4qhdXbmgI9pg(cgVXgy2lPe(pRYsEMoRfJtN5RrXm4RFQ4rYPSMbJ2fGOMAdkYpJY2u8e(IlA)cYtKCgJqXAG14osjmsEeeHEGKuwRiHMbO4UqyJMu9C(StlwDvfOIzbNahX()tizvKRaLHNcJG5PimVcuuqYRhYhsuzXQvPG2GkGKXExs1djltYjvtUFDks3j9eD(qdMYE9ByvMvuKnVyt(W5RltW(6l)YO4rxn6LxG)3x(LEA4vJ2jbI4)GgZXh8XSoZx(BR7I)dq9Cw7NLa)bsh043MnVsOVHZJbnkb1X9qrD2UqK3zgR30FViZd2xEl5JURAsA(mfc7lV46DDmJ8YlH1JwgH27EFnSBUJWNS2zjId3KvlHI4d)KLfqQoz5VhpWtwwXfMOm3TQ0FNi91OcfzrplYsZjNbUKWfob50ZUEj49XzAoEapmRi)E0iYS5na5SRREOOSgFSOpv6HDGpr44NjNsSkNsKkFItHtxmcV8IBweV8inVdC5B2WK8NNmFvZmWGVQF0WXN00k01bQhFj3NMbJjAdIT1GLjvaTdBGfudfCgm46(Ev208UqWTOUWTOGWTioUHUDZNIvDpM(5crgaB75WF5U8swkUVidKYPpv9BRECDw2K7aDbApLhqWxaS9)fG1gJKy70paos)a4D0vV9H66vvF75NVzZMHBk2aE5mhiRlphIHll7QOrJE3OZxvSHuEwA(I1vauF71)n83yShSh8HZtUwiU8Ny2YgY6Wg0iLjXs(iqdZbh)WXgJJNc8jcGBsVwV6LxedBUDYjupXeHNO5ggLcceb2pH3vvZ6ezqcgOvvDXQjlr)sVh757NnFyjbL2RUAupY)AD6QvK529BvTtRtbnbvtwSU8zem9zHIoCozr6S06RVymQ8A5DftwvKMxxDLXVV(Ql6nVOEyz6kO7xusa15aY2JriYkkMduauVX6vd61)UIQQElsV)H6jCC9dxfbqSVP6z(BVoEKEZVE8aRToz(Zgnmk(LxWUBWa1rBzc4HZSNNLbAGPbmxbAIeZBaQdqDjjBoDUZjNEEs9AyGo5PuqWd)APuvj5EO91p0dMNZQFyieCbevr9hE)iySBWAq)Tc1hPqAOkmtSjju4R(LjZtwvN(eyGztcipAz4IZy6TAYCWk89KHGLIzp(Hl61)nUBtD6mmMZxEXDteZUXd69ggIz0WHP5twKHZy96tLxBqWgPM153vMopJmN9nadKGvtIcpqklMuxsidNxIAw4IwZYs2my3OjTuz1nrYoAoKKJtwZ7PnUgwTjDfGyj1xh1ZyyOIOlePFzYDP1ejILSI8rWYkzEsDbWWmRmbf8PAwBuQNtaC4U6Ei0aC(UAGYKEpYHDv8GU10ieRoTc(Sz1nSkAO6xi0xUrjLqSm4qZiXDf4llbJsyagiN92PNSD6tK08suNujeHrwXgW5dqzo8KkEgMQYtwbEGaqaeNRkWWjWSISb8jrZQa8jiEzW00RHrqbV6jDbLHpubnX0wdgnqiDQPVsr7DZZv4bf84J71suwQeAupdLLG2R(UAoWrPRQDGfTen6nh0UFb2btLZI2l1zAbybWBSinpTcOXiPxhj7(BXSUoN9PoejG5pvGcKufpvsxcsQ4RkY(a6l9Bm53v8ge9CAgorFxDadQKcmPqDHCxFv8rg7eQ1Ls7cb9NbnkPlQHOJqgYETTdurYiSrfIixJobSm5JkoZnuzm2YJDf8H7So3vDZXavQhzvWCzIrBuIUQn9bq)nbtAj6YVRUK1yKqIdpvFeeIxSwG4bQ2UYMgnM4jOpJ2uMPs0BONksNJPPy1kQ2M7kRWKXIZGvd3o97YQkafleu30DLRHUdtllaas15BGwsNIzjBfW5tfzqtKTeSZHbBbo(kMbGOrnWP0GKy9P0Tr7JFwhpH2V2S7O4nJslhUa9igI1IoyOZUF4siAuo728u6pltatEisJwQMxjvoaVYWFdDJrGIHZ8z5CGV5akvdbzFZOdE5fTE5dD0jUOysjpK8W5rqL6t4ZD96hoz41qf(ere0mOkzqzSGCoum69XNiwKNkroGbVzbwWZxwuKViTKeg9uN013g91LIWldHI4EEvgvj1ck4jUAedmVjPpD1Y1z1PRYsjLFiAO3oL2Em0cUtMCOIHdOhqelI0Q14s6njz5DRPAr61OTE2SjOAeYCNurz0bFYgcUqATitSpgaMQ5ZySia)deJBxmjUImsvHnNxzEXA4xi7lmsWVlOHNl0e5TVO2QmWPnQORqfT10Stv)aMvA(4b5)rlq0Xzq8)7a)ECq870rrwQcj2c6MxKFMYec3KJlmwajks3XKIhuuag30)9Nx41mLVinldSAgKftmBsbnjeWC)Rcqpa(K1KBlpAsGOxEMbpVSpi881H6(n969vAb4c8Dj4YuFxTmps7khGtna2jk(zrqRL7Req388(GU)0aD4gfsMMoydyPw1ch0UoaCya6DVIXGoFyade1OpSy83irL00ncEIn2L1U(7MP2bFviAMOpWiYzE)RMeqBdeD)a(mF00K(YVaZE(9LjZjSqAQQPPqKzqcT0I5AVCtkwibCuJzMAvs(CYY0zq8u)ajl5zHjSeSGukWiGW)Avrvv6D0szbIEkLwzkRrt5ihbRBTqlPSXymq9vnTScghqm6GIMjnuJRTYBRq5KjrzOmVjTO(2HSna715FbH32qY04v4r3fOZgT7snDL6MPT18DoGC7sbCnBume0dLuolPQ2DojTy3dxntG6aHDZk)nlbEl5eNxWRkkAbSKt(i8ZOHJboV)XFM8yAw6)C70F7)(h(Vz17gljaawtDaJMdacwDcBaZGLK)1AyqM9mTUQWSpcKoAa9eO5lPRZeIit3KKwpD7uAgrai8aJF(oK1NwQCWWWQIoyibtTSIo8ueixnAySMUtyWmHpYMubtE9mw0L3pQxR0iXfOBcL1xc9U(Iqyn3x(TgxHcAA2cauDkRdCGzrbRXUS0vcDp0egJUX0OSjVwvxd8WkLuk7r1t3gg3f9rHiEURUUSZMI5o(zAlwWWCcUKMZskZPlRmcjJvo79SvoJs1X4wmkBXMQo4ESohHNnN9w56hau(cvJdnZqPynFUGGXiXI3tPQiptf6wrBSi(sRjlpfRTsr9gW8lvBrVX2XwQgRvmsZIlQMUwJcjyq4yqSkge7edIcfdIKyWxOuHvm6ftyNVUk2WqE7LQMnClOVJvj1hS4RWSU(hkYvxmVatmmktcAvWQELWl0qArILjx1(K7PzoohvbZkwfur)J0FVQG1ZCKIf(mvpF1Z51y6STGBSpQnEXgpglY8fWWSFdHgr1Fhgy90EcV0C65TwDeqmIxoo5kvjdkqKuEgJtgRgUKNiO9dwFa6UwNHpg)Inpqq3TGFikKx4NptH093ZYAarTwIbRzOu23)dGxy)yH49yfcxj(uCMydvUkltycfRM9uWMY2PF3F7VG2zbisZm(pY63nIQoMvyPkYWd9Y(Z0nyvWT6urXRwPma4vNmUEbLnLgU)oPTuUljL2lUULfzRltMXJh0RFqZ9VdGVl1gbX9CMhLsJg0SUJ2QBohvkHFqoagAVrxdLOvwRWn(xAPmRetDxfnqTqgTwXsxRByPhZOsOZ4XwNXJ)8zgpAFMXTye41oJBfKAZ4roMXB)L(MXJhOYRSdZ4k1TK6S(C6IIKmdxEK1vWFNKxTmftA6K6KkxwWE5fDv7XXwzPwG7cOjGl25)(ZSWWuwaxSgtA5nT67JzzMoBtYZAwX4tpTQ(z0n0NlwZkyABOJL5v64RTPkFvd1LJnX7aQWmrXny6iG(iU9sLP)(laWWY00qLvq66XN5SmEfLbttzyPTkYNlZgXQnOndrSFmJMVB44tqkpzb3ZZvBov18gqnQjjy4y0TOK(hxMSCvc6TjRwAWTGedlXi2O7Ii6(JG3mn4Yah4u6tWC(CXcUjMVFhZE9ccTgcfRxW2P)Kw3)Rjpb(9Xbl10OWmCsgg1j79Sf(492HOKfsu2f0eOLUeyP3asA0O30x0c13EDuV(08mP(WgDzdhBgljllkgTwMwaSI7EJSmAO0SjckRSwN67fDOftgD5ZHaXFeeWrYBLOMI4OtjLUqrhpa7DNirfS5d4RGAjgCiYgubaeD2smZHK3vBqFkroI1RGPRFnvwI0klPpF7B1WOGZQAUBl4r4kdUJaHHs4DnMDD03UflKBGI58SLXtHHT5uSwM6yDwKKEvQGbfcRfODPcMSQw1SSM8z6eGHOzAAVE5fXJVSN(C6a780fQ5kbiNtWm7CvK1gBuzCn7BsSyYBteFJz8kDdsxRiGcqy6WkqFMjFCfjVkff5Xurq)ywSl38a1B9tWnViRszobf7PBUMlhDc8VxmMNeJOOXI8FHjyLxtjS4ZzboJa8I4tG)n(R5F03el2WOIXKWQ9jML4dzbU72WQbK9j615d7zN0)YrFfDGQLhpAvoo4K(x8vC8RKCpjhEW4rFvFFCh0uWYeljaOwMutvLcMnabN860mvTLK8I13)qtoaTwUnddyKQwjw6JY(9bQ8znRUIbj5S(XxWg(kPfbzzh8LAdCweV0ugwsQxxMtdWzDlZpj8SvMd0s6SPid6OjN87jbmwmtqOyG4AvaPA7BYoK0frJhlCt7Rgn8cWjNbdAQ)JS15jyPSJoNqBddMQ5UsdQAVWgC77APOCKB(bAlnsthXsdNzhWMlk15xQnNjIyQ)hHBpTzpwXsmHQk)UNj45wtSNsBPnTxl1USIdg1H9fSkttMEmfHlAWZik1ngix6Coo4qq9Q(rclJllwI5Qe8be4oqx3zKl6MuwyMd0)HPoG8rO)rNsIuCULr(5kIqlQldanvYGIGBnKaJoXBJK79LR1JRieiRBzkikG0F(z0CzzHomTR)5Bz(1btpieW1NOAfDl)UGNXLtLRtbFtJ)fHWeiYyvlsREecNy(Cbb8KXhisiWjww8rQoDpeswY5SqhzEDPS)YkeeOWOb8S(zsfmYG4jTEHKoe5MqycKOXwg)fRWgHfsAtE9y5ZelZuQPbwP5YljE(U4GrkWyf(nWWbvJWcuxeM3oYIeqbzaeazzcdw3asU0(g8xOEaeZ59TFmfyfVVaNYOlsZCjd(3v8F96qWM6wqIIb8v7wvixxsRHLMATQ9I84SNKgTeFtTUwvDxIfid4f4QsYtTnrE7npHRme8h0ZrKrFtC0T3Sb8GaNmU9g6bxr6YvfL1CX)3QuzfVf5n(xRtPEkwvG(gLSUUG7S0Shqpfq)EyB8n8ih57bbvsj91V1UFaVLjq54TIy1Gw1p6JdKW(s7WwTc5maS6RCb1XhfO(12HAR6rYa0TEVl4)nhfSoYbX4Gm9f9UJgnz7pBHhMRo4GW)2SBqnqUMx4CypYoin2mwgW1Xw1QfWDitOSlImaSYB2vG2SpKmGzZl2vqQ4pQbmv9unS5B5g(E3MXBHzTwHwuLRe74VTU1R9RQscuVNLlw6LUAF4DR1DyR9E0vtdVZCDeZyV)80A)6Q1wPiNZvTEDGaTlAVzV0v7dVBdBUYBtdVZcEUQRwR1Lo02BXlEdjFB(57qTIJ(ODo(n6c3lcqN9q7vKs4YUfwBBT5Oc(JgG)dcVlaPjAlQyE(hapINdSfztCUeP99HL2pnJS1YRgniCM6JicRGVDHUYzG3)jqU1rFCaLBB1dVsg0Jm4pAa(pi8(tLCBRZBPp3LBddH3h5whrCEqLBD0hhq52w9WRKb9id(JgG)p49)wG3T0t67OOBhu8eY5iODvLYhTxNnD21s1uowD0N(wAL940PRdv8)rtR3ls9RIshe9lCcDx0zjxVJSvEqTn5OpoG2MA1d8HVLZVVwkfS3MJk4pAa()G3)BbE)j02uBVIpcNBQ2GPMgZpPNCQ2XMpb2McJwVxK6xfLoi6x4e6UOZsU(2RpZRuEYCPpo0WpeiBTO3TaDxTl0rqO9dYYnzpGV5rhRfqBPjhyO7AHdcbY8t0wF4DttoWqFNX79n6MJn8dbYHXj6UDHoccTF2po(2hwYwa9EZXhm03doNo5jT2Kdm0dfVB7AJZq4Cz)mOt2BRg6CPw04CZ2qi24qZU9BTGoTonVTguOlMwt8jYl(06TwOOm8r6IZNoA(5FMrZp)tonFOJIMyVkYlhl76RSkHSIFIr0UHGXDiUFGk0EXiCVb356GtI)xCuiWEHDRIg0a6TEVl4FyR0hgmDuwATQFCdi369bY0jKxFvmDgwVAoOf8y7s2aTrVla3EFq3c0wBYre4U5YKGTdIHLg4N9vsL7eFT2KJiWLG11QjSF04axQI9d4Ub7riLThwu)Oc8aalY3QO5WgBTYRpI46rf4Dc2WdrkOqXE9DJ3iXCLm19tI)OcC3G9iiAEyr9JkWdaSEfnB96JiUEubENGn881fKO5RVB8NKKihEs66aKWGB3z7c0lqX2V(T7KxGoqA2(l3ad5B6ChIGo2kcQBVEd4PDWiSBqDpDpF7p)tuAgcQ3lo8uWdIe6Ei7NV9g6FH3TXk7Oi4N)c92sMdUB)t3EtXQBVPIulUQCV9gr0u4FLTM08aXMSI(KjSRszLDM1T13(lXgaxaZMDym7QsUmDf7fO8JNBmIBVbAAnb6)BVr9mRCAVTtFZ2P(J)s0Q(n7Vn5(edFfnWq1tb5TthGdIlCmiupCebet9KaajRkOAFLtjRooup3o9dqKBBN(YlBNQCSPO(yh3DbQnPVy0ipgcWbO2jaX2PxFf9o68m82E151naqdO)ByKoXHaj9Hgibo6zyNbE8HGrddMLpNUlpqgLlnyuAya4mM225xcs1(pzFiNP)mzAwiIjp2prY7yhYHnnsN94WCfzOnnAFoQVuZJZjyh3xa07zHl3DY(aUQP35KJZ2HgndBTEiKIJMOHbJj8JZybldBMq5EOG(uLd66TtVIEOkWGofkMNMdIxk7x5PyqZmn9SPgh3V)Z5XDxJq6lLhZ2bmSBo)WXX(x7qmaXc)MHmTyYzADUTo3tQIJrJMSP9BAeC49n7Ou(H7Yazxuy7tEoou6MI8moYJg5yOBzBKVltZbGjkx7h7YS4(DfMqhRMUDAWf)AgmHXo2IcIyLl)v1D1tJgWVzsuX5aWrZPEtFm3BGz30zKBxt6sBvZIP0Cfte4eH4e9whVWhsXjt75A40rWvEBrFG4HPr0WvOgKcu3u3U5IrNPm53SDPSqhhMgf9P(qoectTadpSkY0H5izh96jdw7EtZfboYuU7rCZNBHPn2LoAZHRhVnE3REuhBQ9CNh1oegOgxPhwd2snGXKPMd)9A7AJf)2m1V2wn0SMRtxbq5szTpGhA6aXxjdxxoXjVMWv7xrSAYwrV2WnAHRWnmVyqzPwHN)dzYs86CEF5b4h)(BG63aEc)HoQQEmQsDC26Z5X01J7yR(LPTYSU2X7OWMigZgEq7I)T(jw00pCfE6JidSPjVfAhBumhDgzdaxtr4bEGGWr52FyumpKwkYPhlOYrTJTqa8R3r7k6PjQ5gwvBIzMQ2SiL1C2n1ddSv9k2MkT)(rs6Tru6sCq)iesBiRDTHBZ549cJuOvSJAkVoFQFFwBQIZZTDTiIF2W)nm(uVxp4nXP59kcNc4yf374HH566cxGcg5J4k65og2Jn6yCCyVOi2ie20qz)z0WHLlxEa7MGBvbz4ZcDng75pSMinLn8XFG(rBmgCE1K3LFDins)AkNopgRj1OFeT2H71TgpSBYCQJEbPXxOEZQB2sbT0voto1NOleD1bTvjHEQ8XAiMCorUAjTo5IuzWAFiePA2XMrjDHqlRZHfbqvLbJBS3z5WLLX9YueB1gk3qvFFGqkfzZ68ahQZ1nQkgew167c36jomez4G0yQ1UzqhXv1g3dKjxScCwJxYbFLQ6djhMogiN6uL3vpvEzuUrsoK2kfWxiFQYQpPPrW7ytSwy2cHkGH21xjY4ZNHJn116ZwWAg6LTFjYthf29Vq)YKNkOXVq5vDYG9bSWlKNnyYameTBzs5JclNO6hd3X7o0bpXD4n9kMMvThwHPQ9UxNuJ6AquDWc9PkV27XvL92B9WMYEtDDorzyrIF4YspGwzFpMiv0ycaGAMcgL7El(fvGSsNzMAy3nqpswvZs3hEFdXoeLRXS4uHRinMkWLPLLYlYiW(0JkN1RALsT6IlZrlr1PBliTDywj2)SshhIy2BFyZkEp9USnGJBgWMkF5d40f32oVuEQYijoXAP79TOUWVXmGq)MTAHrumjBN(LyCDJelbeQuJ(ZVSRVJ1EZf9vS8S0Ji5vzjpt5CIrwQ814vXbFuZVnnyxSuAnqC9tXwUVlA)c26aVrCRFWxI3VLgofwvkm2zcYlZzXAXGIf7VtMWjKSk4VhnCSKRmYwiTkZT2GuBUewV(jKpi(tkFGxINPPnRcgAUXEyildomsiMzjXC4ZsaKR2einKwujbJj(2vVwrl)FqG4Oh5983w3LiFn9EubBpEVkH3gGZ0eXP3XGgxftvjOPniSPSdOSSzMAE1YYF6yDDjuBz7CDGzDT2dwyD7etoISUEWXUur1khBU0r5vBI75lT4fCmB25e65Ana)2jnVe4y(kkmIgoMMscNEtP0Y4aBPfuNj)YQaTRBH)w1ICUwdcg)n9r3n(7SLwM1AWFdTA8RiV0FNiHC1w(HTpE5XDgg2ftpfOY6SRXa81VvDHhIxxUOlmZM3aKZUU6bSmql1UZe4V0MMgXL1xxA4IK8YXSi58udPnmZ2RbiXn3dnhhJfASyzQ32ke2xP6D2X66Hn7eWsfBu1aUssJepvxrHDALU()TKK2XFRx4sUQJw2k2OjEiVP)WYVeV3(Yyje9rAr9Glwx5Mu0vD5T9ogSP4wtcVwS43KA06obVqPBUAPxvuvLsjvnxf407PDurcTBVvFP66l7ggfggYwVFVztE2P9AZkAjvCOr(dToB7Q)C1DYLgj8PyB54qnZH7w5lhwVBTWv0Q1glH43GukZknFE7QDW7sXUZvrUYcsQvgjUtDil)sQx)sDVqhskK3sOXmMhDtm0Cmk0R0UQMLIo0REmwj3tBWhRP2hb(Z)XFM8yAw6)uEbeDdEHgHt3aQqlZlAbwtqVN3SD6cC3zaKo8k9HDRNHfpcTAPjqZxs32diImDtsA9uCONHxgAGflQaiEnjMmhtHemMv0PwOCL)DRT1808YptrJQ2kS)EzjOALO)M2RsBVUs5oUU94v4sAn6WxS)fPnKj8qejA5i5U1f(llR9T2sOi(CTAlrVg0CvCDw0)pldVHmzAVPRSf2znQRXLYwQTgFyvZAFfmclRXM9rJEhRQO3o2OQQ8Q4YtH75Tp4f(MEpywQpsh92RTbKqZYjuoUlhr9QOTUo(Qqpq0WlOTt94wq5LJhjCM2VuNIHttpR)C5M2u1xBZZHcBoi2nbN5kcfPotTE1mao9TqdJVOzgr)4Uqer15TMhmOLhQ7ItT4ouwcmBEfgeDOtR0Q(i3(wUKsICCtxsjAJgEbB55If0k(AeZ7vNNbhQ9RTBctzpB92W0FF33RJ9VZRpKdSe0GocXuh6drmyooa3RPQ8fM2W3Z1CZtjeivpAE1BYxFEZX3R9UcvD0X1rVFlzLtLQxX0iWYpbBK78KwP9eyx30OQ4FtHZ7EnO8lY6nvBsMXtcoNCSmczucH9cTF(GXNABTqR2Upx8PQunLB4upRVtG0nZcW8eFzv9erDP8hhn6pORgvt6pEhO6z9HcK4BCtFQt9nVYqPVnke6VnWIFyhK(J1vQQjTJbbxlNb9260d9R1LmQXO4ODXOQomuQ(e75F3ZOq6(MYociWrW(DHPAn(RUzunJeqf3n2q(TccZl0faX2TGQAOiUUStnSN64Ayv3oNEcgzbQiKx8NRzlLt(7BkN8MrOIZW2CexgTelb5GBbyvWO(7MU0YIcWk(wH7w2wRfvmm2s9F1ALBmnCJBRoJYWPzneUhRBh4zcd78Ef3lKfQPbTjs608ASixWPeMMbLQ85mvO7ljU8MeBL6yEuI1I60(muPtQtKc1rBck2MNJYmPWmkzqqLMQyJFgliRWBBLipljaVFaBLb)zYupTtTqxSWKT43vtcYSjUvmhMVxstHsg1caE3kt9rLUi4z0SXHJGK7tqvt5yk8yAVqFCFK(7wgOqF(P5jS658ASm)Cniuh99AVltW4MLr2Oo)kSzt)kTNkD6Ax8GjAeN4B68LPe12MQE7EWx4Zy8(vcN9BuWxUodFm(fBEGGgEzXbqlLn4NptH093Z2gSef4w9qcn3dF)pa2a(XcX7XAKRs8P4K2gQKywMiBTvRiZsxGrn9D)T)cgRnar6jCXpYDdsu3DSYAsrQxjlQO0hmtTSYMZq7Iop3sImrbBSb9BEJ1cFUJmSgpwjc2GN6FNSVDRAnywPZ6wx(izW6nPNORc1WP39b3Fduin6fzO6HPL7cOqcrRvpGy1HfLW9GwfresivwHDmHPTD4LzawtKZQfgCTcyvSxLICdVSqXdcOs25aenWwB(L6ZCKxUG)pcJB0RIX1Hz2JgJR3(ZfJBKpgxBqSBg342mUTkTfFmUT9VWZkWySnaUsUnZSU2sMTnUHhgKcsYMSac753F2AKbIgAzUYmGXSnjpRz0xAm1Oy4WGjFUynAvkxZ4UBd5HTzrVCSDQGoBxNhvCkmnEChRnD19zLu72EHsNW2Xhd1o5Fy7W1Z2gsn2P4ciZrKALDtJLWzK(0PCcYzUchjSZiTZLvjXQnOIt9St(UHJpbNXjl4XjSAZPQUwaZl1KeCvxtXcJu)JltwUkbJnGTx6qXi2yLmhC74VlQmAEZ0GldCqiepLsJXLraf8zVJ5R0cYgQ7r8TtZ2P)Kw3)R0JJpoyP2heUaLKHj3G9EwYHEVviQY6QV1DujSk7RXM8RRD29PPwEOED5yWeB5BvkTGbQo7k3hDuY3ebr2CreccXFdRNP5DUIqEKuobP8vn7qvfuMFohkq5o6G3PMyz9JirPgCFrqt31J7YjvJg1X2zOOf0wXZevZ4VIDyOv9kIzyZTEOFxaKWu9tm0GIqw91SQNXC6YmhaL4cKJcTvWCmnVtC5muyy1gmqnu(D9kq46xX2Y1Z3mY5joSrSgLbvd9vkrZnzChzrbMKaAxJhdjv0myjR6658AUInPAlzbW3pbRVeTDxRE5D4j2DJ91RxoRwYOOAZpkw(v2Uu21b8qR(Xzy6w27Zuf8jRbfKL3EZFn5XKhsFmL(0B)F)]] ) diff --git a/TheWarWithin/DruidGuardian.lua b/TheWarWithin/DruidGuardian.lua index 18e5a7ed4..558e4866b 100644 --- a/TheWarWithin/DruidGuardian.lua +++ b/TheWarWithin/DruidGuardian.lua @@ -51,7 +51,7 @@ spec:RegisterResource( Enum.PowerType.Rage, { end, interval = function () return class.auras.thrash_bear.tick_time end, - value = function () return 2 * state.active_dot.thrash_bear end, + value = function () return min( 15, 3 * state.active_dot.thrash_bear ) end, } } ) spec:RegisterResource( Enum.PowerType.LunarPower ) @@ -489,7 +489,7 @@ spec:RegisterAuras( { ironfur = { id = 192081, duration = function() return 7 + ( buff.guardian_of_elune.up and 3 or 0 ) + ( talent.ursocs_endurance.enabled and 2 or 0 ) end, - max_stack = 5, + max_stack = 20, }, -- Agility increased by $w1% and armor granted by Ironfur increased by $w2%. killing_strikes = { @@ -577,6 +577,11 @@ spec:RegisterAuras( { duration = 20, max_stack = 1 }, + -- fake buff for killing strikes "next mangle after entering combat grants ravage" + ravage_upon_combat = { + duration = 3600, + max_stack = 1 + }, -- Heals $w2 every $t2 sec. -- https://wowhead.com/beta/spell=8936 regrowth = { @@ -703,7 +708,7 @@ spec:RegisterAuras( { id = 192090, duration = function () return mod_circle_dot( 15 ) * haste end, tick_time = function () return mod_circle_dot( 3 ) * haste end, - max_stack = function () return 3 + talent.untamed_savagery.rank end, + max_stack = function () return 3 + talent.flashing_claws.rank end, copy = "thrash" }, -- Talent: Increased movement speed by $s1% while in Cat Form, reducing gradually over time. @@ -1038,7 +1043,6 @@ spec:RegisterHook( "reset_precast", function () eclipse.reset() -- from Balance. end ) - spec:RegisterHook( "runHandler", function( ability ) local a = class.abilities[ ability ] @@ -1051,6 +1055,12 @@ spec:RegisterHook( "runHandler", function( ability ) end end ) +-- local ursocRageSpend + +spec:RegisterHook( "runHandler_startCombat", function() + if talent.killing_strikes.enabled then applyBuff( "ravage_upon_combat") end + ursocRageSpend = 0 -- reset upon entering combat +end ) spec:RegisterHook( "spend", function( amt, resource ) if resource == "rage" and amt > 0 then @@ -1061,6 +1071,14 @@ spec:RegisterHook( "spend", function( amt, resource ) buff.after_the_wildfire.v1 = buff.after_the_wildfire.v1 + 200 end end + --[[ To be revisited using warrior Anger Management as an example + if talent.ursocs_guidance.enabled then + ursocRageSpend = ursocRageSpend + amt + if ursocRageSpend >= 25 then + reduceCooldown( "incarnation", floor( ursocRageSpend / 25 ) ) + ursocRageSpend = ursocRageSpend % 25 + end + end--]] end end ) @@ -1175,6 +1193,7 @@ spec:RegisterAbilities( { handler = function () applyBuff( "berserk" ) + if talent.berserk_persistence.enabled then setCooldown( "frenzied_regeneration", 0 ) end end, copy = "berserk_bear" @@ -1316,9 +1335,9 @@ spec:RegisterAbilities( { frenzied_regeneration = { id = 22842, cast = 0, - charges = function () return talent.innate_resolve.enabled and 2 or nil end, - cooldown = function () return 36 * ( buff.berserk.up and talent.berserk_persistence.enabled and 0 or 1 ) * ( 1 - 0.1 * talent.reinvigoration.rank ) end, - recharge = function () return talent.innate_resolve.enabled and ( 36 * ( buff.berserk.up and talent.berserk_persistence.enabled and 0 or 1 ) ) or nil end, + charges = function () if talent.innate_resolve.enabled then return 2 end end, + cooldown = function () return 36 * ( buff.berserk.up and talent.berserk_persistence.enabled and 0 or 1 ) * ( 1 - 0.1 * talent.reinvigoration.rank ) * haste end, + recharge = function () if talent.innate_resolve.enabled then return 36 * ( buff.berserk.up and talent.berserk_persistence.enabled and 0 or 1 ) * ( 1 - 0.1 * talent.reinvigoration.rank ) * haste end end, gcd = "spell", school = "physical", @@ -1446,6 +1465,7 @@ spec:RegisterAbilities( { handler = function () applyBuff( "incarnation" ) + if talent.berserk_persistence.enabled then setCooldown( "frenzied_regeneration", 0 ) end end, copy = { "incarnation_guardian_of_ursoc", "Incarnation" } @@ -1478,7 +1498,7 @@ spec:RegisterAbilities( { icd = function() return 7 / ( max_ironfur or 1 ) end, school = "nature", - spend = function () return ( buff.berserk_bear.up and talent.berserk_persistence.enabled and 20 or 40 ) * ( buff.gory_fur.up and 0.85 or 1 ) end, + spend = function () return ( buff.berserk_bear.up and talent.berserk_persistence.enabled and 20 or 40 ) * ( buff.gory_fur.up and 0.75 or 1 ) end, spendType = "rage", talent = "ironfur", @@ -1500,7 +1520,7 @@ spec:RegisterAbilities( { end, handler = function () - applyBuff( "ironfur" ) + addStack( "ironfur", 1 ) removeBuff( "gory_fur" ) removeBuff( "guardian_of_elune" ) if set_bonus.tier30_4pc > 0 then addStack( "indomitable_guardian" ) end @@ -1565,21 +1585,28 @@ spec:RegisterAbilities( { end, handler = function () + + -- Regular talents if talent.fluid_form.enabled and buff.bear_form.down then shift( "bear_form" ) end - if talent.wildpower_surge.enabled then addStack( "feline_potential_counter" ) end - - removeBuff( "vicious_cycle_mangle" ) - addStack( "vicious_cycle_maul" ) + if talent.infected_wounds.enabled then applyDebuff( "target", "infected_wounds" ) end + if talent.vicious_cycle.enabled then + removeBuff( "vicious_cycle_mangle" ) + addStack( "vicious_cycle_maul" ) + end if talent.guardian_of_elune.enabled then applyBuff( "guardian_of_elune" ) end if buff.gore.up then - gain( 4, "rage" ) removeBuff( "gore" ) - if set_bonus.tier29_4pc > 0 then applyBuff( "bloody_healing" ) end end - if talent.infected_wounds.enabled then applyDebuff( "target", "infected_wounds" ) end + -- Hero talents + if talent.wildpower_surge.enabled then addStack( "feline_potential_counter" ) end + if talent.killing_strikes.enabled and buff.ravage_upon_combat.up then + applyBuff( "ravage" ) + removeBuff( "ravage_upon_combat" ) + end + -- Legacy / PvP if conduit.savage_combatant.enabled then addStack( "savage_combatant", nil, 1 ) end end, }, @@ -1626,19 +1653,33 @@ spec:RegisterAbilities( { end, handler = function () - addStack( "vicious_cycle_mangle" ) - removeBuff( "savage_combatant" ) - removeBuff( "vicious_cycle_maul" ) - removeBuff( "ravage" ) + -- Interactions for both Maul and Ravage + if talent.vicious_cycle.enabled then + removeBuff( "vicious_cycle_maul" ) + addStack( "vicious_cycle_mangle" ) + end + if talent.infected_wounds.enabled then applyDebuff( "target", "infected_wounds" ) end + if talent.ursocs_fury.enabled then applyBuff( "ursocs_fury" ) end if buff.tooth_and_claw.up then removeStack( "tooth_and_claw" ) applyDebuff( "target", "tooth_and_claw_debuff" ) end + + -- Ravage specific interactions + if talent.ravage.enabled and buff.ravage.up then + removeBuff( "ravage" ) + if talent.dreadful_wound.enabled then applyDebuff( "target", "dreadful_wound" ) end + if talent.ruthless_aggression.enabled then applyBuff( "ruthless_aggression" ) end + if talent.killing_strikes.enabled then applyBuff( "killing_strikes" ) end + + end + + -- Legacy / PvP + if conduit.savage_combatant.enabled then removeBuff( "savage_combatant" ) end if set_bonus.tier30_4pc > 0 then addStack( "indomitable_guardian" ) end - if talent.infected_wounds.enabled then applyDebuff( "target", "infected_wounds" ) end - if talent.ursocs_fury.enabled then applyBuff( "ursocs_fury" ) end if pvptalent.sharpened_claws.enabled or essence.conflict_and_strife.major then applyBuff( "sharpened_claws" ) end + end, copy = { 6807, "ravage", 441605} @@ -1686,6 +1727,8 @@ spec:RegisterAbilities( { if talent.twin_moonfire.enabled then active_dot.moonfire = min( true_active_enemies, active_dot.moonfire + 1 ) end + + if talent.lunation.enabled then reduceCooldown( "lunar_beam", 3 ) end end, copy = 155625 @@ -1700,8 +1743,8 @@ spec:RegisterAbilities( { school = "physical", talent = "moonkin_form", - startsCombat = false, noform = "moonkin_form", + startsCombat = false, handler = function () shift( "moonkin_form" ) @@ -1730,27 +1773,26 @@ spec:RegisterAbilities( { pulverize = { id = 80313, cast = 0, - cooldown = function() return 45 - 5 * talent.tear_down_the_mighty.rank end, + cooldown = function() return 45 - 10 * talent.tear_down_the_mighty.rank end, gcd = "spell", school = "physical", talent = "pulverize", + form = "bear_form", startsCombat = true, - form = "bear_form", + cycle = "thrash_bear", + cycle_to = true, usable = function () if debuff.thrash_bear.stack < 2 then return false, "target has fewer than 2 thrash stacks" end return true end, - cycle = "thrash_bear", - cycle_to = true, - 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" ) + applyDebuff( "target", "pulverize" ) end, }, @@ -1790,8 +1832,8 @@ spec:RegisterAbilities( { spendType = "rage", talent = "raze", - startsCombat = true, form = "bear_form", + startsCombat = true, usable = function () if action.raze.spend > 0 and ( settings.maul_rage or 0 ) > 0 and rage.current - action.raze.spend < ( settings.maul_rage or 0 ) then return false, "not enough additional rage" end @@ -1799,17 +1841,26 @@ spec:RegisterAbilities( { end, handler = function () - addStack( "vicious_cycle_mangle" ) - removeBuff( "savage_combatant" ) - removeBuff( "vicious_cycle_maul" ) + + if talent.vicious_cycle.enabled then + addStack( "vicious_cycle_mangle" ) + removeBuff( "vicious_cycle_maul" ) + end if buff.tooth_and_claw.up then removeStack( "tooth_and_claw" ) applyDebuff( "target", "tooth_and_claw_debuff" ) end - if set_bonus.tier30_4pc > 0 then addStack( "indomitable_guardian" ) end + + if talent.aggravate_wounds.enabled and debuff.dreadful_wound.up then + debuff.dreadful_wound.expires = debuff.dreadful_wound.expires + 0.6 + end if talent.infected_wounds.enabled then applyDebuff( "target", "infected_wounds" ) end if talent.ursocs_fury.enabled then applyBuff( "ursocs_fury" ) end + + -- Legacy / PvP if pvptalent.sharpened_claws.enabled or essence.conflict_and_strife.major then applyBuff( "sharpened_claws" ) end + if set_bonus.tier30_4pc > 0 then addStack( "indomitable_guardian" ) end + if conduit.savage_combatant.enabled then removeBuff( "savage_combatant" ) end end, }, @@ -2058,14 +2109,16 @@ spec:RegisterAbilities( { cooldown = 0, gcd = "totem", school = "physical", + form = "bear_form", startsCombat = true, handler = function () + if talent.aggravate_wounds.enabled and debuff.dreadful_wound.up then + debuff.dreadful_wound.expires = debuff.dreadful_wound.expires + 0.6 + end end, - form = "bear_form", - copy = { "swipe", 213764 }, bind = { "swipe_bear", "swipe_cat", "swipe" } }, @@ -2076,30 +2129,38 @@ spec:RegisterAbilities( { known = 106832, suffix = "(Bear)", cast = 0, - cooldown = function () return ( buff.berserk_bear.up and talent.berserk_ravage.enabled and 0 or 6 ) * haste end, + cooldown = function () return 6 * ( buff.berserk_bear.up and talent.berserk_ravage.enabled and 0.5 or 1 ) * haste end, gcd = "spell", - school = "physical", + school = function() return talent.lunar_calling.enabled and "arcane" or "physical" end, spend = function() return -5 * ( buff.furious_regeneration.up and 1.15 or 1 ) end, spendType = "rage", talent = "thrash", - startsCombat = true, - form = "bear_form", - bind = "thrash", + startsCombat = true, handler = function () applyDebuff( "target", "thrash_bear", 15, debuff.thrash_bear.count + 1 ) active_dot.thrash_bear = active_enemies if talent.ursocs_fury.enabled then applyBuff( "ursocs_fury" ) end + if talent.aggravate_wounds.enabled and debuff.dreadful_wound.up then + debuff.dreadful_wound.expires = debuff.dreadful_wound.expires + 0.6 + end + if talent.earthwarden.enabled then addStack( "earthwarden", nil, ( min( 3, active_enemies ) ) ) end + + if talent.bloody_frenzy.enabled then gain( min( 15, 3 * active_enemies ), rage ) end + if legendary.ursocs_fury_remembered.enabled then applyBuff( "ursocs_fury_remembered" ) end - if talent.earthwarden.enabled then addStack( "earthwarden", nil, 1 ) end + if talent.lunation.enabled and talent.lunar_calling.enabled then reduceCooldown( "lunar_beam", 3 ) end + end, + + bind = "thrash", }, -- Talent: Shift into Cat Form and increase your movement speed by $s1%, reducing gradually over $d. @@ -2207,17 +2268,39 @@ spec:RegisterOptions( { cycle = false, nameplates = true, - nameplateRange = 10, + nameplateRange = 8, rangeFilter = false, damage = true, damageExpiration = 6, - potion = "spectral_agility", + potion = "tempered_potion", package = "Guardian", } ) +spec:RegisterSetting( "catweave_bear", false, { + name = strformat( "Weave %s and %s", Hekili:GetSpellLinkWithTexture( spec.abilities.cat_form.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.bear_form.id ) ), + desc = strformat( "If checked, shifting between %s and %s may be recommended based on whether you're actively tanking and other conditions. These swaps may occur " + .. "very frequently.\n\n" + .. "If unchecked, |W%s|w and |W%s|w abilities will be recommended based on your selected form, but swapping between forms will not be recommended.", + Hekili:GetSpellLinkWithTexture( spec.abilities.cat_form.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.bear_form.id ), + spec.abilities.cat_form.name, spec.abilities.bear_form.name ), + type = "toggle", + width = "full", +} ) + +spec:RegisterSetting( "maul_anyway", true, { + name = strformat( "Use %s and %s in %s Build", Hekili:GetSpellLinkWithTexture( spec.abilities.maul.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.raze.id ), + Hekili:GetSpellLinkWithTexture( spec.abilities.ironfur.id ) ), + desc = strformat( "If checked, %s and %s are recommended more frequently even if you have talented %s or %s.\n\n" + .. "This differs from the default SimulationCraft priority as of February 2023.", + Hekili:GetSpellLinkWithTexture( spec.abilities.maul.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.raze.id ), + Hekili:GetSpellLinkWithTexture( spec.talents.layered_mane[2] ), Hekili:GetSpellLinkWithTexture( spec.talents.reinforced_fur[2] ) ), + type = "toggle", + width = "full", +} ) + spec:RegisterSetting( "maul_rage", 20, { name = strformat( "%s (or %s) Rage Threshold", Hekili:GetSpellLinkWithTexture( spec.abilities.maul.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.raze.id ) ), desc = strformat( "If set above zero, %s and %s can be recommended only if you'll still have this much Rage after use.\n\n" @@ -2228,36 +2311,19 @@ spec:RegisterSetting( "maul_rage", 20, { min = 0, max = 60, step = 0.1, - width = "full" -} ) - -spec:RegisterSetting( "maul_anyway", true, { - name = strformat( "Use %s and %s in %s Build", Hekili:GetSpellLinkWithTexture( spec.abilities.maul.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.raze.id ), - Hekili:GetSpellLinkWithTexture( spec.abilities.ironfur.id ) ), - desc = strformat( "If checked, %s and %s are recommended more frequently even if you have talented %s or %s.\n\n" - .. "This differs from the default SimulationCraft priority as of February 2023.", Hekili:GetSpellLinkWithTexture( spec.abilities.maul.id ), - Hekili:GetSpellLinkWithTexture( spec.abilities.raze.id ), Hekili:GetSpellLinkWithTexture( spec.talents.layered_mane[2] ), Hekili:GetSpellLinkWithTexture( spec.talents.reinforced_fur[2] ) ), - type = "toggle", - width = "full", + width = 1.5 } ) ---[[ 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.\n\nThis 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( "vigil_damage", 50, { name = strformat( "%s Damage Threshold", Hekili:GetSpellLinkWithTexture( class.specs[ 102 ].abilities.natures_vigil.id ) ), desc = strformat( "If set below 100%%, %s may only be recommended if your health has dropped below the specified percentage.\n\n" - .. "By default, |W%s|w also requires the |cFFFFD100Defensives|r toggle to be active.", class.specs[ 102 ].abilities.natures_vigil.name, class.specs[ 102 ].abilities.natures_vigil.name ), + .. "By default, |W%s|w also requires the |cFFFFD100Defensives|r toggle to be active.", + class.specs[ 102 ].abilities.natures_vigil.name, class.specs[ 102 ].abilities.natures_vigil.name ), type = "range", min = 1, max = 100, step = 1, - width = "full" + width = 1.5 } ) spec:RegisterSetting( "ironfur_damage_threshold", 5, { @@ -2265,13 +2331,14 @@ spec:RegisterSetting( "ironfur_damage_threshold", 5, { desc = strformat( "If set above zero, %s will not be recommended for mitigation purposes unless you've taken this much damage in the past 5 seconds (as a percentage " .. "of your total health).\n\n" .. "This value is halved when playing solo.\n\n" - .. "Taking %s and %s will result in |W%s|w recommendations for offensive purposes.", Hekili:GetSpellLinkWithTexture( spec.abilities.ironfur.id ), - Hekili:GetSpellLinkWithTexture( spec.talents.thorns_of_iron[2] ), Hekili:GetSpellLinkWithTexture( spec.talents.reinforced_fur[2] ), spec.abilities.ironfur.name ), + .. "Taking %s and %s will result in |W%s|w recommendations for offensive purposes.", + Hekili:GetSpellLinkWithTexture( spec.abilities.ironfur.id ), Hekili:GetSpellLinkWithTexture( spec.talents.thorns_of_iron[2] ), + Hekili:GetSpellLinkWithTexture( spec.talents.reinforced_fur[2] ), spec.abilities.ironfur.name ), type = "range", min = 0, max = 200, step = 0.1, - width = "full" + width = 1.5 } ) spec:RegisterSetting( "max_ironfur", 1, { @@ -2279,42 +2346,31 @@ spec:RegisterSetting( "max_ironfur", 1, { desc = strformat( "When set above zero, %s will not be recommended for mitigation purposes if you already have this many stacks.", Hekili:GetSpellLinkWithTexture( spec.abilities.ironfur.id ) ), type = "range", - min = 1, + min = 0, max = 14, step = 1, - width = "full" + width = 1.5 } ) - spec:RegisterStateExpr( "max_ironfur", function() - return settings.max_ironfur or 1 - end ) +spec:RegisterStateExpr( "max_ironfur", function() + return settings.max_ironfur or 1 +end ) ---[[ spec:RegisterSetting( "shift_for_convoke", false, { - name = "|T3636839:0|t Powershift for Convoke the Spirits", - desc = "If checked, the addon will recommend swapping to Cat Form before using |T3636839:0|t Convoke the Spirits.\n\n" .. - "This is a DPS gain unless you die horribly.", +--[[ 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.\n\nThis 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" + width = "full", } ) ]] -spec:RegisterSetting( "catweave_bear", false, { - name = strformat( "Weave %s and %s", Hekili:GetSpellLinkWithTexture( spec.abilities.cat_form.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.bear_form.id ) ), - desc = strformat( "If checked, shifting between %s and %s may be recommended based on whether you're actively tanking and other conditions. These swaps may occur " - .. "very frequently.\n\n" - .. "If unchecked, |W%s|w and |W%s|w abilities will be recommended based on your selected form, but swapping between forms will not be recommended.", - Hekili:GetSpellLinkWithTexture( spec.abilities.cat_form.id ), Hekili:GetSpellLinkWithTexture( spec.abilities.bear_form.id ), - spec.abilities.cat_form.name, spec.abilities.bear_form.name ), - type = "toggle", - width = "full", -} ) ---[[ Retired 2023-02-21 -spec:RegisterSetting( "owlweave_bear", false, { - name = "|T136036:0|t Attempt Owlweaving (Experimental)", - desc = "If checked, the addon will use the experimental |cFFFFD100owlweave|r priority included in the default priority pack.", +--[[ spec:RegisterSetting( "shift_for_convoke", false, { + name = "|T3636839:0|t Powershift for Convoke the Spirits", + desc = "If checked, the addon will recommend swapping to Cat Form before using |T3636839:0|t Convoke the Spirits.\n\n" .. + "This is a DPS gain unless you die horribly.", type = "toggle", width = "full" } ) ]] - spec:RegisterPack( "Guardian", 20241011, [[Hekili:vZ1wpkoUs4Fl8ccMPhMKa0xwb8WEK2JM5HDLoSs7Becbde1HeuIt3B3cLF7NY25IJVKyO7P3zLwTZqID566xv2UMSYE1FUA5wpmA1V7y5mX2Y2EK1d2tg7SAj(LtOvlp55)O3E4Ve5De())3mVKTbErKx8syS3wcbsJZs8HxEaJpL(lF9R7dWhY2mYp(4xtdoMf6HdIJ8t82Hj)2)RRwUjlie)TOvBuV6Rw6LHpeNSA5YGJ)hGWbB3IyJgL6VAjz0FX26l22)s(6Fl4VZx)TK4ODzj5RXErpgeTpFT)bK)J5Fp)70bB9WxCid()HEcLG)6oyoCVYEk8QFf5bZ)3ItoMVook8L81b7YxhfNVEh9zbP5R98XbpHQN69FXzYn5Rj)jHeeUnFD2jImvpO7(IZy4L)5bu(6)ISg)fOFcavyyqkoLOapgGd2t1sWV(DQrbf5TjeTD1VUAPFsagLe4bMKsHRF(6E5RFYdEkmQrb7CjA0T0xeebkEyuUB9ocwo3PaFVaEmtdv(u8Heu6H4I5SjB3UrfJyuc6OxqemRz5RhNV(t5Rp4LccK0atXGZbDytblMpL)xw8YvyWOQvqoG8cXhgDYhtN(TCZpbTpj(z8bcbgFDeic9Sxiz(tmst2cT2be71a0wxGRaYMWSraLNEnu(UPTzGSgzZu2SjD07VR5JnEjpMcKLS03QDPPgN0SKNcEYl0fmHyyPWPJ2g)CuT1RKw1pwuby1oB6mvlFkV4ahJbodITA31MYAjEpbR0OStugGfS5c69Jbi2IBxVuh9YcB3jBabniefHhbSAc2nEh41JCFgcugvmHYiPIXLeCQ(ndZxF(SHKGY97qHbri3tXyycbGsWpolc4LY4K5GQvPGrIZQfmPvsvKqLwigI2csqsQsIg3LaCvQnhu(FeXnWVYhf7LShHhHdocGcXUBdqmnTtLgaMtcAhbUGS8gmPH6KY7kMmvJcGeVqeZipCwcssV)Za)orW)qlldQ)x8dbAtxNuIJERWpn4VcEEBmWGhs8sp4smE8ORnuBHWiiHL(HEpNcHmrmxlhgH0tLjMqf7UOYyrvstcXRsk9r5iK5qN(XqUjaGcyna7PiAineHoH4Yqb2W75qjtGeQHeMPibuhqL8XiQXAVJqGYxeMfbJhM0rEIcJ6EdGGibYNIFgL4cyK7rYOh(E4gXRkHuOVSWnVxx0UMZ9JJEk(rethEkaypcU8V)aV0TbLKIsEuq0ST4hdGO7LeXsckmo9i7vbYSAhQjH7(IIjjM3SK0y)6usvM)2hpVJajTvHQPW6sfiMdmJWSaDIhfDgtSkrgR1LkuvQGMmqwiMk1mtHr8DIvmC0IRgxaQIqmQnT1uRQfRkbUBDZqjFpiYLUU6l7ZGQeamkh5QeS1Jfxkl44y8bxVOTuOSsiVfvyIQgeFPYWW(C(69(BjLevQYvuIodLTZ6Bs8Efr5C94LseyUqUcgILVxibuugwqay2weUuSKEULg8s3IuPrkSk9e2QqXJR8aNAvWN1i(QvvwniNQKbLUDv0(bR2Pxb45pp8V6QhSVtRHVMC8rcmuwriL28anoj7yEVkvdUcPrd(4LHg68pgRBMtKDPrTSiisH(e6MIHnmUh2vKAIAB3nvnJKFeQ4wJ4muNoSbop3zdyRVOP3lV7EMXIFuQZ)DYo6nGp0zgvZlPTV6nfxA4VkLrp22yi7PVX2T4eNDOKy)G4Su3naVtpnbRpoPQxlcwVwKnHQqF34NRslRt1cQDQ(u)(c6e65PaMTHLCKujh3jPmwP4SqL3nffrQ4NY6RC0xLlLl2hN0wTM22xurV6SpINv0SYZkY0T4D0lAFitG0x(CBLOmqN2K3xtrXsQp8eHYMVAt5qfgm9LYBwrbZiLj7yUTO6C76PjIRePX7r0iXtEsBax15NKfSLrnjBA6Hee90)C0VhG)He53Iyr0tuPQJJNrCnnG0Crb6REUnGNMhwXpKTekP6Q21gpO1R6or0pogtSK0FkykJ0wdvCnb6R3SduXwW(Uw(Rdi1RXwOsKBTcTlNX73YECRfQlJZnGMxBcKUeizf2y9f)jLDAEJl9u4Kug36PHQSolncWej)fftSq4sJZclZaaWJOuCd9Sg9tJ4y2giGyX7VxBaiRMhntBChtZmUDOke9X6lutvTd6no6UlTtzHpb07vK6ZJz8e(JcNNOnpk8X6twZkO0lKqe)QkeBuyO092vOU2ajO3gIstDjx5xyW(dyfoYL3giHn0ND9IRzOY(wSRBTz)7jC0JaH4502tJtFlqZK9VqnH3XwmXkQQWlGTy8mY7j65Vnx4StzvymwFra)7sh015FAMAPQEYX6tg2AbUWwP5VkwTQad4LI9howFokvROF8XnXqzRbrywy(K3mJiFgat0NgOe7cqgKVgVkpehloDE5qPuU18cD61OaMRo)qNUDKbDXlrZBtj95GtOkG0jM06fMVufB4tnuOsmomPFW2bjVXRk7TKko9XSWq3naeTa6StJrrQ9cjIFRj9aoji6regCDsdJXC)glFt)cZXryooK5OpnXaDh5YfCqdCPqHD5r(tS89HxocYne5Y(HlPP0yTMMlRL)4AonCXnIRGejzrAPqHdd8WtjisiSNSb7OhiO8n9IcZg3YgdEePiC98lJ0P)TI1TSGsfrWKUlmkLSGKJ0uf2CckicC(8rBjDtqDU2N8cZaV2WuybSk(5QL2Q8CmIjRrMuWMNscoc7oN03jxq(JUoZOweH26yokrVIwPQw(v2AtT0pibhrcxANbNbqfSb1Ld0(qrDPK3qBYuRhCGi4NHOhqJNUA53oEkobty)jmiP4O810gZCu(3joSX7cigm2Rshv5b)55Fv0Nn)7QgvPr)gI9EEPp5nuT(C7BQngZTUjy38wDq73QZPjRFT7wxCGcFV(Av)9B3NtnNj5oWT6A9Z63t2dtn5RCeOKf8LMBD(Cp9HoFVImWKRtG04P0eg8pjlf5c(RhVHaWpVmNqNJWHFemaAcxoqfU)5ZgH5pKNKIi6mJFnuo)yfGUzdLS2CAeAYyQlFwiHrlQgT4c663mx(cBP5P0up4AS1dpFUZPzWzCo)wbME2yzHTOuJBASDqiIPubWxHs)bdg0ROw1(Y9B4cBhGZhWTzgndAOiFDxvuNYUpKq1FqR8Kk9VMLwsJXTRyIsIBnboqztfoBAnOIuljo358z1ZAsBZYw3SgxlqkBBrzbQrlfYGNOD8rFt2)4I7LPxrZfQ0fsA01DCO0Ru0Ux8HuAWH7lU9o1Hke0KAOYoX0lLnoylPxYHEj9ofQqQSmyGbaFeJq)lRDbxCR1WcqvPMeCyFc3SyIv)bLYFlDwhjWYaEScdxaz)Yxmdgvjnv4mx1MDVF5AUOedZCuy7FfvZnQUcHf2fmL6RoyM9N37dsT0Xip3U70sc4vcJFEf2KYgPt2hN1DeQsx0tx3M1VhtHx1NzmZ3uR(LinYcMvXKuFAqNptPWdwQMjev)XXjAvqefIGJYGbLHcQmKgH2oUQ6y9n0II41UIoD(HZs6Tx21jS01pyft32w987E6VxkKwCemqlmugs5Q9w619Y9(j2)STykuKnpIZA0wtQdqQk5(xIS0trhyjZFWaEZmvpLCvpLSvvw7RCTUafq7YDrUpTrt6U1Z5JLsTX5AW3VtkYttUpTQm1fD3KOqABByHaMSvRz3A8Pd0PIbQusuYlnMsj0e3ptvHexGAv2OrVefcZzscGzZN6yIkc2nApjpYEQAQiz3Xwoqdj16JOpeo)nWJc(N8u9sicRyuvbwL7Q4nuQPG4bLjwh89AZnM)(Uu15Z)bVqALj9f(RmwvtKPPRM2qBZ0l6z2bMXaQQ4LWuMS6AM7LbaPJXU4nY0sCMQ0zsSXev70LlOuF3Cilru)vc0ZS7VxYXZ2M71Jv86UxXopwkrqEPXx1jiIBLRnkR)4dRs2QOZp6xu3a3bjwiGT0XhVDKDQ(fkFwcPUxJD8kCVTTC()iAplS4ol(sE6R4(3vOeV8uQ)az)22qRHYtr9SAsOx3sdYSVz0xUEErcZ3NelMCTRtvVlWo4twyNyRpWSfowYZUQzb4pys1ggHiYjCN(OYjuDhaMqofN6eFO5fXz2dLdy5VMK6Byzo32xlpaLEs5e6hi9v2yHUVulSvw4R0YSXFI(1zP5lloADv8fX)S4tScH1Q)2Fm7w9JN(fvX0HR8JMcVAWeIWFq5kM3DtvP5Sgz)P6pljAOS83OKQGvnF7ukm58F3uAidwQ5fNPFI)BKYgVu02)iI)BOu6jKp5FJ9tOxu9Q))]] ) \ No newline at end of file