You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
18 KiB

## https://github.com/simulationcraft/simc/blob/thewarwithin/ActionPriorityLists/default/druid_feral.simc
## Up to date with SimC: April 12 2025 - d935a4a
actions.precombat+=/mark_of_the_wild
actions.precombat+=/prowl,if=!buff.prowl.up
actions.precombat+=/cat_form,if=!buff.cat_form.up
# check if trinket slot contains a stat on use (variable is just kept in case of things like mirror not working with has_use_buff)
actions.precombat+=/variable,name=trinket_1_buffs,value=trinket.1.has_use_buff&!trinket.1.is.imperfect_ascendancy_serum&!trinket.1.is.ovinaxs_mercurial_egg&!trinket.1.is.concoction_kiss_of_death
actions.precombat+=/variable,name=trinket_2_buffs,value=trinket.2.has_use_buff&!trinket.2.is.imperfect_ascendancy_serum&!trinket.2.is.ovinaxs_mercurial_egg&!trinket.2.is.concoction_kiss_of_death
# if we are playing 2 minute convoke, we prefer 2 minute on-use over 3 minute on-use even without berserk: heart of the lion
actions.precombat+=/variable,name=trinket_1_sync,op=setif,value=1,value_else=0.5,condition=talent.convoke_the_spirits&!talent.ashamanes_guidance&variable.trinket_1_buffs&(trinket.1.cooldown.duration%%120=0|120%%trinket.1.cooldown.duration=0)
actions.precombat+=/variable,name=trinket_2_sync,op=setif,value=1,value_else=0.5,condition=talent.convoke_the_spirits&!talent.ashamanes_guidance&variable.trinket_2_buffs&(trinket.1.cooldown.duration%%120=0|120%%trinket.1.cooldown.duration=0)
# if we aren't playing 2 minute convoke, then we can sync 3 minute cds with berserk sans hotl
actions.precombat+=/variable,name=trinket_1_sync,op=setif,value=1,value_else=0.5,condition=!(talent.convoke_the_spirits&!talent.ashamanes_guidance)&variable.trinket_1_buffs&(trinket.1.cooldown.duration%%cooldown.bs_inc.duration=0|cooldown.bs_inc.duration%%trinket.1.cooldown.duration=0|trinket.1.cooldown.duration%%cooldown.convoke_the_spirits.duration=0|cooldown.convoke_the_spirits.duration%%trinket.1.cooldown.duration=0)
actions.precombat+=/variable,name=trinket_2_sync,op=setif,value=1,value_else=0.5,condition=!(talent.convoke_the_spirits&!talent.ashamanes_guidance)&variable.trinket_2_buffs&(trinket.2.cooldown.duration%%cooldown.bs_inc.duration=0|cooldown.bs_inc.duration%%trinket.2.cooldown.duration=0|trinket.2.cooldown.duration%%cooldown.convoke_the_spirits.duration=0|cooldown.convoke_the_spirits.duration%%trinket.2.cooldown.duration=0)
# prioritize trinkets that line-up with cds->main-stat on uses->longer cd trinkets->shorter duration trinkets
actions.precombat+=/variable,name=trinket_priority,op=setif,value=2,value_else=1,condition=!variable.trinket_1_buffs&variable.trinket_2_buffs|variable.trinket_2_buffs&((trinket.2.cooldown.duration%trinket.2.proc.any_dps.duration)*(1.5+trinket.2.has_buff.agility)*(1.2+trinket.2.has_buff.mastery)*(variable.trinket_2_sync))>((trinket.1.cooldown.duration%trinket.1.proc.any_dps.duration)*(1.5+trinket.1.has_buff.agility)*(1.2+trinket.1.has_buff.mastery)*(variable.trinket_1_sync))
actions+=/prowl,if=buff.bs_inc.down&!buff.prowl.up
actions+=/cat_form,if=!buff.cat_form.up&!talent.fluid_form
actions+=/skull_bash
actions+=/soothe
## Line up <a href='https://www.wowhead.com/spell=10060/power-infusion'>Power Infusion</a> with Berserk.
## actions+=/invoke_external_buff,name=power_infusion,if=buff.bs_inc.up|!talent.berserk_heart_of_the_lion
actions+=/call_action_list,name=variable
## actions+=/stop_moving,if=gcd.remains=0&equipped.ovinaxs_mercurial_egg
actions+=/tigers_fury,if=(energy.deficit>35|combo_points=5|combo_points>=3&dot.rip.refreshable&buff.bloodtalons.up&hero_tree.wildstalker)&(boss&fight_remains<=15|(cooldown.bs_inc.remains>20&fight_remains>5)|(cooldown.bs_inc.ready&fight_remains>12|boss))
actions+=/rake,cycle_targets=1,if=buff.shadowmeld.up|buff.prowl.up
actions+=/natures_vigil,if=variable.regrowth&health.percent<70&(buff.bs_inc.up|buff.tigers_fury.up)
actions+=/renewal,if=variable.regrowth&health.percent<70
actions+=/adaptive_swarm,cycle_targets=1,if=dot.adaptive_swarm_damage.stack<3&(!dot.adaptive_swarm_damage.ticking|dot.adaptive_swarm_damage.remains<2)&!action.adaptive_swarm.in_flight&(spell_targets=1|!talent.unbridled_swarm)&(dot.rip.ticking|hero_tree.druid_of_the_claw)
actions+=/adaptive_swarm,cycle_targets=1,if=buff.cat_form.up&dot.adaptive_swarm_damage.stack<3&talent.unbridled_swarm.enabled&spell_targets.swipe_cat>1&dot.rip.ticking
actions+=/ferocious_bite,if=buff.apex_predators_craving.up&!(variable.need_bt&active_bt_triggers=2)
actions+=/call_action_list,name=cooldown,strict=1,if=dot.rip.ticking
# keep using this archaic 'nonsense' for veinripper because its better idk ill fix soon tm
actions+=/rip,if=talent.veinripper&spell_targets=1&hero_tree.wildstalker&!(talent.raging_fury&talent.veinripper)&(buff.bloodtalons.up|!talent.bloodtalons)&(dot.rip.remains<5&buff.tigers_fury.remains>10&combo_points>=3|((buff.tigers_fury.remains<3&combo_points=5)|buff.tigers_fury.remains<=1)&buff.tigers_fury.up&combo_points>=3&remains<cooldown.tigers_fury.remains)
# fix to work with veinripper idk
actions+=/rip,if=!talent.veinripper&spell_targets=1&hero_tree.wildstalker&buff.tigers_fury.up&(buff.bloodtalons.up|!talent.bloodtalons)&(combo_points>=3&refreshable&cooldown.tigers_fury.remains>25|buff.tigers_fury.remains<5&variable.rip_duration>cooldown.tigers_fury.remains&cooldown.tigers_fury.remains>=dot.rip.remains)
actions+=/call_action_list,name=builder,if=(buff.bs_inc.up&!buff.ravage.up&!buff.coiled_to_spring.up&hero_tree.druid_of_the_claw&talent.coiled_to_spring&spell_targets<=2)|buff.bloodtalons.stack=0&active_bt_triggers=2
actions+=/wait,sec=action.tigers_fury.ready,if=combo_points=5&cooldown.tigers_fury.remains<3&spell_targets=1
actions+=/call_action_list,name=finisher,if=combo_points=5
## [Syrif] - combo_points<5 added to stop from sending generators inappropriately
actions+=/call_action_list,name=builder,if=spell_targets.swipe_cat=1&combo_points<5
actions+=/call_action_list,name=aoe_builder,if=spell_targets.swipe_cat>=2&combo_points<5
actions+=/regrowth,if=buff.predatory_swiftness.up&variable.regrowth&selection_time>gcd.max
# maintain thrash highest prio
actions.aoe_builder+=/thrash_cat,if=refreshable&!talent.thrashing_claws&!(variable.need_bt&buff.bt_thrash.up)
# avoid capping brs charges. Also send brutal slashes/ws swipe in aoe, even if we need to proc bloodtalons, during berserk.
actions.aoe_builder+=/brutal_slash,cycle_targets=1,if=(cooldown.brutal_slash.full_recharge_time<4|time_to_die<4|raid_event.adds.remains<4|(buff.bs_inc.up&spell_targets>=3-hero_tree.druid_of_the_claw))&!(variable.need_bt&buff.bt_swipe.up&(buff.bs_inc.down|spell_targets<3-hero_tree.druid_of_the_claw))
actions.aoe_builder+=/swipe_cat,if=talent.wild_slashes&(time_to_die<4|raid_event.adds.remains<4|buff.bs_inc.up&spell_targets>=3-hero_tree.druid_of_the_claw)&!(variable.need_bt&buff.bt_swipe.up&(buff.bs_inc.down|spell_targets<3-hero_tree.druid_of_the_claw))
# with wild slashes we swipe at 5+ targets over raking/moonfire
actions.aoe_builder+=/swipe_cat,if=time_to_die<4|(talent.wild_slashes&spell_targets.swipe_cat>4&!(variable.need_bt&buff.bt_swipe.up))
actions.aoe_builder+=/prowl,if=dot.rake.refreshable|dot.rake.pmultiplier<1.4&!(variable.need_bt&buff.bt_rake.up)&action.rake.ready&gcd.remains=0&!buff.sudden_ambush.up&!variable.cc_capped
actions.aoe_builder+=/shadowmeld,if=dot.rake.refreshable|dot.rake.pmultiplier<1.4&!(variable.need_bt&buff.bt_rake.up)&action.rake.ready&!buff.sudden_ambush.up&!buff.prowl.up&!variable.cc_capped
# dcr rake > moonfire
actions.aoe_builder+=/rake,cycle_targets=1,if=refreshable&talent.doubleclawed_rake&!(variable.need_bt&buff.bt_rake.up)&!variable.cc_capped
# at 3t with wild slashes, swipe is better than moonfiring/st rake
actions.aoe_builder+=/swipe_cat,if=talent.wild_slashes&spell_targets.swipe_cat>2&!(variable.need_bt&buff.bt_swipe.up)
# if wildstalker make sure you have at least one rake up
actions.aoe_builder+=/rake,cycle_targets=1,if=!dot.rake.ticking&hero_tree.wildstalker
# li moonfire is better than non-dcr rake in aoe if we already have 1 rake
actions.aoe_builder+=/moonfire_cat,cycle_targets=1,if=refreshable&!(variable.need_bt&buff.bt_moonfire.up)&!variable.cc_capped
actions.aoe_builder+=/rake,cycle_targets=1,if=refreshable&!(variable.need_bt&buff.bt_rake.up)&!variable.cc_capped
# fillers
actions.aoe_builder+=/brutal_slash,if=!(variable.need_bt&buff.bt_swipe.up)
actions.aoe_builder+=/swipe_cat,if=!(variable.need_bt&buff.bt_swipe.up)
actions.aoe_builder+=/shred,if=!buff.sudden_ambush.up&!variable.easy_swipe&!(variable.need_bt&buff.bt_shred.up)
actions.aoe_builder+=/thrash_cat,if=!talent.thrashing_claws&!(variable.need_bt&buff.bt_thrash.up)
# fallback bt actions
actions.aoe_builder+=/rake,cycle_targets=1,if=talent.doubleclawed_rake&buff.sudden_ambush.up&variable.need_bt&buff.bt_rake.down
actions.aoe_builder+=/moonfire_cat,cycle_targets=1,if=variable.need_bt&buff.bt_moonfire.down
actions.aoe_builder+=/rake,cycle_targets=1,if=buff.sudden_ambush.up&variable.need_bt&buff.bt_rake.down
actions.aoe_builder+=/shred,if=variable.need_bt&buff.bt_shred.down&!variable.easy_swipe
actions.aoe_builder+=/rake,cycle_targets=1,if=dot.rake.pmultiplier<1.6&variable.need_bt&buff.bt_rake.down
actions.aoe_builder+=/thrash_cat,if=variable.need_bt&buff.bt_shred.down
actions.builder+=/prowl,if=gcd.remains=0&energy>=35&!buff.sudden_ambush.up&(dot.rake.refreshable|dot.rake.pmultiplier<1.4)*!(variable.need_bt&buff.bt_rake.up)&buff.tigers_fury.up&!buff.shadowmeld.up
actions.builder+=/shadowmeld,if=gcd.remains=0&energy>=35&!buff.sudden_ambush.up&(dot.rake.refreshable|dot.rake.pmultiplier<1.4)*!(variable.need_bt&buff.bt_rake.up)&buff.tigers_fury.up&!buff.prowl.up
# upgrade to stealth rakes, otherwise refresh in pandemic. Delay rake as long as possible if it would downgrade
actions.builder+=/rake,if=((refreshable&persistent_multiplier>=dot.rake.pmultiplier|dot.rake.remains<3.5)|buff.sudden_ambush.up&persistent_multiplier>dot.rake.pmultiplier)&!(variable.need_bt&buff.bt_rake.up)&(hero_tree.wildstalker|!buff.bs_inc.up)
# bt check is due to the overcap line, comes up with convoke/apex bites
actions.builder+=/shred,if=buff.sudden_ambush.up&buff.bs_inc.up&!(variable.need_bt&buff.bt_shred.up&active_bt_triggers=2)
actions.builder+=/brutal_slash,if=cooldown.brutal_slash.full_recharge_time<4&!(variable.need_bt&buff.bt_swipe.up)
actions.builder+=/moonfire_cat,if=refreshable
actions.builder+=/thrash_cat,if=refreshable&!talent.thrashing_claws&!buff.bs_inc.up
actions.builder+=/shred,if=buff.clearcasting.up&!(variable.need_bt&buff.bt_shred.up)
# pool energy if we need to refresh dot in the next 1.5s [Hekili] TODO: Sim character to see how frequently this fires, determine if `wait` value should be adjusted.
actions.builder+=/pool_resource,if=variable.dot_refresh_soon&energy.deficit>70&!variable.need_bt&!buff.bs_inc.up&cooldown.tigers_fury.remains>3
actions.builder+=/brutal_slash,if=!(variable.need_bt&buff.bt_swipe.up)
actions.builder+=/shred,if=!(variable.need_bt&buff.bt_shred.up)
actions.builder+=/rake,if=refreshable
actions.builder+=/thrash_cat,if=refreshable&!talent.thrashing_claws
actions.builder+=/swipe_cat,if=variable.need_bt&buff.bt_swipe.down
# clip rake for bt if it wont downgrade its snapshot
actions.builder+=/rake,if=variable.need_bt&buff.bt_rake.down&persistent_multiplier>=dot.rake.pmultiplier
actions.builder+=/moonfire_cat,if=variable.need_bt&buff.bt_moonfire.down
actions.builder+=/thrash_cat,if=variable.need_bt&buff.bt_thrash.down
actions.cooldown+=/incarnation,if=fight_remains>17|boss
# non-stat on use trinkets get used on cooldown, so long as it wont interfere with a stat on-use trinket
actions.cooldown+=/use_item,slot=trinket1,if=trinket.1.has_use_damage&(trinket.2.cooldown.remains>20&(!trinket.1.is.junkmaestros_mega_magnet|cooldown.bestinslots.remains>20|!equipped.bestinslots)|!trinket.2.has_use_buff&(cooldown.bestinslots.remains>20|!equipped.bestinslots)|cooldown.tigers_fury.remains<25&cooldown.tigers_fury.remains>20)|boss&fight_remains<5
actions.cooldown+=/use_item,slot=trinket2,if=trinket.2.has_use_damage&(trinket.1.cooldown.remains>20&(!trinket.2.is.junkmaestros_mega_magnet|cooldown.bestinslots.remains>20|!equipped.bestinslots)|!trinket.1.has_use_buff&(cooldown.bestinslots.remains>20|!equipped.bestinslots)|cooldown.tigers_fury.remains<25&cooldown.tigers_fury.remains>20)|boss&fight_remains<5
# berserk with tigers fury
actions.cooldown+=/berserk,if=buff.tigers_fury.up&(fight_remains>12|boss)
actions.cooldown+=/berserking,if=buff.bs_inc.up
# todo make last set of cds line up again now that we know potions.remains is the syntax
actions.cooldown+=/potion,if=buff.bs_inc.up|boss&fight_remains<32|(!variable.lastzerk&variable.lastconvoke&cooldown.convoke_the_spirits.remains<10)
# non trinket gear-on-uses have variable rules on whether or not they trigger the trinket shared CD. For the cases they do we will need specific APL entries. For now just use on cooldown.
actions.cooldown+=/use_items
# stat on-use trinkets, prefers trinket with higher priority.
actions.cooldown+=/use_item,slot=trinket1,if=variable.trinket_1_buffs&(buff.bs_inc.up|((buff.tigers_fury.up&cooldown.tigers_fury.remains>25)&(cooldown.convoke_the_spirits.remains<6|(variable.trinket_2_buffs&cooldown.convoke_the_spirits.remains-trinket.2.cooldown.remains>0)|!talent.convoke_the_spirits&cooldown.bs_inc.remains-trinket.2.cooldown.remains>0)))&(!trinket.2.has_cooldown|trinket.2.cooldown.remains|variable.trinket_priority=1)|trinket.1.proc.any_dps.duration>=fight_remains&boss
actions.cooldown+=/use_item,slot=trinket2,if=variable.trinket_2_buffs&(buff.bs_inc.up|((buff.tigers_fury.up&cooldown.tigers_fury.remains>25)&(cooldown.convoke_the_spirits.remains<6|(variable.trinket_1_buffs&cooldown.convoke_the_spirits.remains-trinket.1.cooldown.remains>0)|!talent.convoke_the_spirits&cooldown.bs_inc.remains-trinket.1.cooldown.remains>0)))&(!trinket.1.has_cooldown|trinket.1.cooldown.remains|variable.trinket_priority=2)|trinket.2.proc.any_dps.duration>=fight_remains&boss
## actions.cooldown+=/do_treacherous_transmitter_task,if=buff.tigers_fury.up|fight_remains<22
actions.cooldown+=/feral_frenzy,if=combo_points<=1+buff.bs_inc.up&(buff.tigers_fury.up|!talent.savage_fury|!hero_tree.wildstalker|boss&fight_remains<cooldown.tigers_fury.remains)
# always line up convoke with berserk if you can
actions.cooldown+=/convoke_the_spirits,if=boss&fight_remains<5|(cooldown.bs_inc.remains>45|buff.bs_inc.up|!talent.berserk_heart_of_the_lion)&(buff.tigers_fury.up&(combo_points<=4|buff.bs_inc.up&combo_points<=3)&(target.time_to_die>5-talent.ashamanes_guidance.enabled|boss))
# maintain/upgrade pws, if we have 6.5+s left on pw, we will instead bite if we have rampant ferocity talented. Without rampant, we will bite a vined target with 6 or fewer targets. If we have Ravage, we use specifically Ravage at 7 or fewer targets.
actions.finisher+=/primal_wrath,if=spell_targets.primal_wrath>1&((dot.primal_wrath.remains<6.5&!buff.bs_inc.up|dot.primal_wrath.refreshable)|(!talent.rampant_ferocity.enabled&(spell_targets.primal_wrath>1&!dot.bloodseeker_vines.ticking&!buff.ravage.up|spell_targets.primal_wrath>6+talent.ravage)))
# rip if single target or pw isnt up. Rip with bloodtalons if talented. If tigers fury will be up before rip falls off, then delay refresh
actions.finisher+=/rip,cycle_targets=1,if=refreshable&(!talent.primal_wrath|spell_targets=1)&(buff.bloodtalons.up|!talent.bloodtalons)&(buff.tigers_fury.up|dot.rip.remains<cooldown.tigers_fury.remains)&(remains<fight_remains|remains<4&buff.ravage.up)
actions.finisher+=/pool_resource,for_next=1
actions.finisher+=/ferocious_bite,max_energy=1,cycle_targets=1,if=!buff.bs_inc.up
actions.finisher+=/pool_resource,for_next=1
actions.finisher+=/ferocious_bite,cycle_targets=1,if=buff.bs_inc.up
# what rips new duration would be if applied in current state
actions.variable+=/variable,name=rip_duration,value=((4+(4*combo_points))*(1-(0.2*talent.circle_of_life_and_death))*(1+(0.25*talent.veinripper)))+(variable.rip_max_pandemic_duration>?dot.rip.remains)
actions.variable+=/variable,name=rip_max_pandemic_duration,value=((4+(4*combo_points))*(1-(0.2*talent.circle_of_life_and_death))*(1+(0.25*talent.veinripper)))*0.3
# this returns true if we have a dot nearing pandemic range
actions.variable+=/variable,name=dot_refresh_soon,value=(!talent.thrashing_claws&(dot.thrash_cat.remains-dot.thrash_cat.duration*0.3<=2))|(talent.lunar_inspiration&(dot.moonfire_cat.remains-dot.moonfire_cat.duration*0.3<=2))|((dot.rake.pmultiplier<1.6|buff.sudden_ambush.up)&(dot.rake.remains-dot.rake.duration*0.3<=2))
# try to proc bt if we have 1 or 0 sacks of bloodtalons
actions.variable+=/variable,name=need_bt,value=talent.bloodtalons&buff.bloodtalons.stack<=1
# capped on clearcasting stacks
actions.variable+=/variable,name=cc_capped,value=buff.clearcasting.stack=(1+talent.moment_of_clarity)
# checks if theres exactly 1 convoke remaining in sim
actions.variable+=/variable,name=lastconvoke,value=(cooldown.convoke_the_spirits.remains+cooldown.convoke_the_spirits.duration)>fight_remains&cooldown.convoke_the_spirits.remains<fight_remains
# checks if theres exactly 1 berserk cast remaining in sim : at least 5s spare for now, TODO: check #s
actions.variable+=/variable,name=lastzerk,value=(cooldown.bs_inc.remains+cooldown.bs_inc.duration+5)>fight_remains&cooldown.convoke_the_spirits.remains<fight_remains
# approximates if theres exactly 1 potion cast remaining with duration to spare
actions.variable+=/variable,name=lastpotion,value=(cooldown.potions.remains+cooldown.potions.duration+15)>fight_remains&cooldown.potions.remains+15<fight_remains
# optional variable that sends regrowth and renewal casts. Turned off by default
actions.variable+=/variable,name=regrowth,op=reset,value=settings.regrowth
# optional variable that forgoes shredding in AoE. Turned off by default
actions.variable+=/variable,name=easy_swipe,op=reset
# track moonfire snapshot
actions.variable+=/variable,name=moonfire_snapshotted,value=buff.tigers_fury.up,op=set,if=prev.lunar_inspiration