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
actions.precombat+=/variable,name=trinket_1_buffs,value=trinket.1.has_buff.agility|trinket.1.has_buff.mastery|trinket.1.has_buff.versatility|trinket.1.has_buff.haste|trinket.1.has_buff.crit
actions.precombat+=/variable,name=trinket_2_buffs,value=trinket.2.has_buff.agility|trinket.2.has_buff.mastery|trinket.2.has_buff.versatility|trinket.2.has_buff.haste|trinket.2.has_buff.crit
# if we are playing 2 minute convoke, we prefer 2 minute on-use over 3 minute on-use even with 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+=/tigers_fury,if=energy.deficit>35|combo_points=5
actions+=/rake,cycle_targets=1,if=buff.shadowmeld.up|buff.prowl.up
actions+=/natures_vigil,if=spell_targets.swipe_cat>0
actions+=/renewal,if=health.pct<60&variable.regrowth
actions+=/ferocious_bite,if=buff.apex_predators_craving.up&!(variable.need_bt&active_bt_triggers=2)
actions+=/adaptive_swarm,cycle_targets=1,if=(!dot.adaptive_swarm_damage.ticking|dot.adaptive_swarm_damage.remains<2)&dot.adaptive_swarm_damage.stack<3&!action.adaptive_swarm_damage.in_flight&!action.adaptive_swarm.in_flight&target.time_to_die>5&(buff.cat_form.up&!talent.unbridled_swarm.enabled|spell_targets.swipe_cat=1)
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
actions+=/call_action_list,name=cooldown,strict=1,if=dot.rip.ticking
actions+=/run_action_list,name=berserk,strict=1,if=buff.bs_inc.up
actions+=/call_action_list,name=finisher,if=combo_points=5
actions+=/call_action_list,name=builder,if=spell_targets.swipe_cat=1&combo_points<5&(variable.time_to_pool<=0|!variable.need_bt|variable.proccing_bt)
actions+=/call_action_list,name=aoe_builder,if=spell_targets.swipe_cat>=2&combo_points<5&(variable.time_to_pool<=0|!variable.need_bt|variable.proccing_bt)
actions+=/regrowth,if=buff.predatory_swiftness.up&variable.regrowth
actions.aoe_builder+=/rake,cycle_targets=1,if=!dot.rake.ticking&buff.sudden_ambush.up&!(variable.need_bt&buff.bt_rake.up)
actions.aoe_builder+=/brutal_slash,cycle_targets=1,if=!(variable.need_bt&buff.bt_swipe.up)&(cooldown.brutal_slash.full_recharge_time<4|time_to_die<4|raid_event.adds.remains<4)
actions.aoe_builder+=/thrash_cat,if=refreshable&!talent.thrashing_claws
actions.aoe_builder+=/prowl,if=!(buff.bt_rake.up&active_bt_triggers=2)&action.rake.ready&gcd.remains=0&!buff.sudden_ambush.up&(dot.rake.refreshable|dot.rake.pmultiplier<1.4)
actions.aoe_builder+=/shadowmeld,if=!(buff.bt_rake.up&active_bt_triggers=2)&action.rake.ready&gcd.remains=0&!buff.sudden_ambush.up&(dot.rake.refreshable|dot.rake.pmultiplier<1.4)
# maximize rake uptime while avoiding rake-downgrades
actions.aoe_builder+=/rake,cycle_targets=1,if=(refreshable|(dot.rake.pmultiplier<persistent_multiplier))&!(buff.bt_rake.up&active_bt_triggers=2)
actions.aoe_builder+=/brutal_slash,if=!(buff.bt_swipe.up&active_bt_triggers=2)
actions.aoe_builder+=/moonfire_cat,cycle_targets=1,if=refreshable&(spell_targets.swipe_cat<4|talent.brutal_slash)&!(buff.bt_moonfire.up&active_bt_triggers=2)
actions.aoe_builder+=/swipe_cat,if=!(buff.bt_swipe.up&active_bt_triggers=2)
actions.aoe_builder+=/moonfire_cat,cycle_targets=1,if=refreshable&!(buff.bt_moonfire.up&active_bt_triggers=2)
actions.aoe_builder+=/rake,cycle_targets=1,if=(refreshable|(dot.rake.pmultiplier<persistent_multiplier))&!(buff.bt_rake.up&active_bt_triggers=2)
# fill with shred if sudden ambush is not up. If easy swipe is enabled, skip this line. Thrashing instead is net-neutral up to at least 10t, but we prefer shred for priority damage.
actions.aoe_builder+=/shred,if=!(buff.bt_shred.up&active_bt_triggers=2)&!variable.easy_swipe&!buff.sudden_ambush.up
actions.aoe_builder+=/thrash_cat,if=!(buff.bt_thrash.up&active_bt_triggers=2)&!talent.thrashing_claws
# fallback bloodtalons actions below this point
actions.aoe_builder+=/moonfire_cat,cycle_targets=1,if=variable.need_bt&buff.bt_moonfire.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.berserk+=/call_action_list,name=finisher,if=combo_points=5
actions.berserk+=/run_action_list,name=aoe_builder,strict=1,if=spell_targets.swipe_cat>=2
actions.berserk+=/prowl,if=!(buff.bt_rake.up&active_bt_triggers=2)&action.rake.ready&gcd.remains=0&!buff.sudden_ambush.up&(dot.rake.refreshable|dot.rake.pmultiplier<1.4)&!buff.shadowmeld.up
actions.berserk+=/shadowmeld,if=!(buff.bt_rake.up&active_bt_triggers=2)&action.rake.ready&!buff.sudden_ambush.up&(dot.rake.refreshable|dot.rake.pmultiplier<1.4)&!buff.prowl.up
# rake if bt doesnt need proc and rake can be upgraded. Fish for sudden ambush procs unless rake will fall off otherwise.
actions.berserk+=/rake,if=!(buff.bt_rake.up&active_bt_triggers=2)&(dot.rake.remains<3|buff.sudden_ambush.up&persistent_multiplier>dot.rake.pmultiplier)
actions.berserk+=/moonfire_cat,if=refreshable
actions.berserk+=/thrash_cat,if=!talent.thrashing_claws&refreshable
# proc bt when an opportunity arises
actions.berserk+=/shred,if=active_bt_triggers=2&buff.bt_shred.down
actions.berserk+=/brutal_slash,if=active_bt_triggers=2&buff.bt_swipe.down
actions.berserk+=/swipe_cat,if=active_bt_triggers=2&buff.bt_swipe.down&talent.wild_slashes
# alternate brs and shred to create bt opportunities
actions.berserk+=/brutal_slash,if=cooldown.brutal_slash.charges>1&buff.bt_swipe.down
actions.berserk+=/shred,if=buff.bt_shred.down
actions.berserk+=/brutal_slash,if=cooldown.brutal_slash.charges>1
actions.berserk+=/swipe_cat,if=buff.bt_swipe.down&talent.wild_slashes
actions.berserk+=/shred
# this variable tracks whether or not we've started our bt sequence
actions.builder+=/shadowmeld,if=gcd=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
# 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)|buff.sudden_ambush.up&persistent_multiplier>dot.rake.pmultiplier)&!(variable.need_bt&buff.bt_rake.up)
actions.builder+=/brutal_slash,if=cooldown.brutal_slash.full_recharge_time<4&!(variable.need_bt&buff.bt_swipe.up)
actions.builder+=/thrash_cat,if=refreshable
actions.builder+=/shred,if=buff.clearcasting.react
actions.builder+=/moonfire_cat,if=refreshable
actions.builder+=/brutal_slash,if=!(variable.need_bt&buff.bt_swipe.up)
actions.builder+=/swipe_cat,if=talent.wild_slashes&!(variable.need_bt&buff.bt_swipe.up)
actions.builder+=/shred,if=!(variable.need_bt&buff.bt_shred.up)
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
actions.cooldown+=/berserk
actions.cooldown+=/berserking,if=buff.bs_inc.up|cooldown.bs_inc.remains>50
actions.cooldown+=/potion,if=buff.bs_inc.up|fight_remains<32|(!variable.lastzerk&variable.lastconvoke&cooldown.convoke_the_spirits.remains<10)
actions.cooldown+=/feral_frenzy,if=combo_points<=1|buff.bs_inc.up&combo_points<=2
# non trinket gear-on-uses have variable rules on whether or not they trigger the trinket ICD. 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. reads like this: berserk is up OR if tigers fury up & convoke is either ready, wont be for the next tf, or the other trinket will be ready in time for convoke. If we dont have convoke, then we use if berserk wont be up for next tf or other trinket will be up for berserk.
actions.cooldown+=/use_item,slot=trinket1,if=(buff.bs_inc.up|((buff.tigers_fury.up&cooldown.tigers_fury.remains>20)&(cooldown.convoke_the_spirits.remains<4|cooldown.convoke_the_spirits.remains>45|cooldown.convoke_the_spirits.remains-trinket.2.cooldown.remains>0|!talent.convoke_the_spirits&(cooldown.bs_inc.remains>40|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
actions.cooldown+=/use_item,slot=trinket2,if=(buff.bs_inc.up|((buff.tigers_fury.up&cooldown.tigers_fury.remains>20)&(cooldown.convoke_the_spirits.remains<4|cooldown.convoke_the_spirits.remains>45|cooldown.convoke_the_spirits.remains-trinket.1.cooldown.remains>0|!talent.convoke_the_spirits&(cooldown.bs_inc.remains>40|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
# 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=!variable.trinket_1_buffs&(trinket.2.cooldown.remains>20|!variable.trinket_2_buffs|trinket.2.cooldown.remains&cooldown.tigers_fury.remains>20)
actions.cooldown+=/use_item,slot=trinket2,if=!variable.trinket_2_buffs&(trinket.1.cooldown.remains>20|!variable.trinket_1_buffs|trinket.1.cooldown.remains&cooldown.tigers_fury.remains>20)
actions.cooldown+=/use_item,slot=main_hand
actions.cooldown+=/convoke_the_spirits,if=boss&fight_remains<5|(buff.tigers_fury.up&(combo_points<=2|buff.bs_inc.up&combo_points<=3)&(target.time_to_die>5-talent.ashamanes_guidance.rank|target.time_to_die=fight_remains))
# 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 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))|dot.primal_wrath.pmultiplier<persistent_multiplier)
# 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)
actions.finisher+=/pool_resource,for_next=1
actions.finisher+=/ferocious_bite,max_energy=1,cycle_targets=1,if=!buff.bs_inc.up|!talent.soul_of_the_forest.enabled
actions.finisher+=/ferocious_bite,cycle_targets=1,if=dot.bloodseeker_vines.ticking
# most expensive bt cycle is Shred + Thrash + Rake, 40+40+35 for 115 energy. During incarn it is 32+32+28 for 92energy
actions.variable+=/variable,name=effective_energy,op=set,value=energy+(40*buff.clearcasting.stack)+(3*energy.regen)+(50*cooldown.tigers_fury.remains<3.5)
# estimated time until we have enough energy to proc bloodtalons.
actions.variable+=/variable,name=time_to_pool,op=set,value=((115-variable.effective_energy-(23*buff.incarnation.up))%energy.regen)
# try to proc bt if we have 1 or 0 stacks of bloodtalons
actions.variable+=/variable,name=need_bt,value=talent.bloodtalons&buff.bloodtalons.stack<=1
# 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
# 300-(time+300)%%300 roughly gives us potion cd remaining, pot cd=300, in other words this is the same cd_pot.remains+cd_pot.duration+15>fight_remains&cd_pot.remains+15<fight_remains
actions.variable+=/variable,name=lastpotion,value=(300-((time+300)%%300)+300+15)>fight_remains&300-((time+300)%%300)+15<fight_remains
# optional variable that alternates bite/pw during berserk regardless of talent setup. Off by default
actions.variable+=/variable,name=zerk_biteweave,op=reset
# optional variable that sends regrowth and renewal casts. Turned off by default
actions.variable+=/variable,name=regrowth,op=reset
# optional variable that forgoes shredding in AoE. Turned off by default
actions.variable+=/variable,name=easy_swipe,op=reset
actions.variable+=/variable,name=proccing_bt,op=set,value=variable.need_bt