Register

Leafkiller's MoP Feral/Guardian Ovale Script

Face-rippin fun.

Moderator: Forum Administrators

Exalted
User avatar
Posts: 894
Joined: Tue Oct 23, 2012 7:15 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby raffy » Thu Jul 18, 2013 4:50 pm

green312 wrote:
Paloro wrote:Mangle is actually the better cp generator outside of Berserk and TF.


Ah ok thanks, noxxic wasnt saying anything about that.

Since these types of questions seem to get asked a lot, it would be cool if someone could maintain a generic PvE Feral thread here at the FluidDruid, that outlines all of the best practices, similar to: http://us.battle.net/wow/en/forum/topic/6471617676 but more focused on the action list and mechanics.

Things like: when to use various cooldowns, how to open, how to AoE, when to AoE, when to tab-Rake, casting during HotW, how snapshotting works, how clipping works, various buff strengths (see Ovale/DroodFocus + Catus Rake/Rip tables), symbiosis overview, critical macros (shiftless-HT, TF+Berserk), etc...

It would be cool to have a breakdown of the Simc/Ovale script with approximate English descriptions, so non-technical Cats can understand what's going on.

I think having a comprehensive and up-to-date Feral Cheat-sheet would be very valuable, as a lot of this information is currently spread across various threads.

Exalted
User avatar
Posts: 1145
Joined: Fri Jun 04, 2010 4:28 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Leafkiller » Thu Jul 18, 2013 7:17 pm

raffy wrote:
green312 wrote:
Paloro wrote:Mangle is actually the better cp generator outside of Berserk and TF.


Ah ok thanks, noxxic wasnt saying anything about that.

Since these types of questions seem to get asked a lot, it would be cool if someone could maintain a generic PvE Feral thread here at the FluidDruid, that outlines all of the best practices, similar to: http://us.battle.net/wow/en/forum/topic/6471617676 but more focused on the action list and mechanics.

Things like: when to use various cooldowns, how to open, how to AoE, when to AoE, when to tab-Rake, casting during HotW, how snapshotting works, how clipping works, various buff strengths (see Ovale/DroodFocus + Catus Rake/Rip tables), symbiosis overview, critical macros (shiftless-HT, TF+Berserk), etc...

It would be cool to have a breakdown of the Simc/Ovale script with approximate English descriptions, so non-technical Cats can understand what's going on.

I think having a comprehensive and up-to-date Feral Cheat-sheet would be very valuable, as a lot of this information is currently spread across various threads.


If one of you wants to start one, I will make it sticky.

Exalted
User avatar
Posts: 1684
Joined: Mon May 24, 2010 10:21 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Tinderhoof » Thu Jul 18, 2013 7:33 pm

I have been wanting to do this, but my life has pretty much been, Work, Raid, Work some more, Sleep. Now that Lei Shen is down and work is starting to quite down I might have the time to pull lots of stuff together. If someone beats me to it that's fine. I think we need to readjust the stickies anyway. They are starting to get out of control.

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Jul 19, 2013 2:31 am

5.3.7 script

Spoiler: show
Code: Select all
# ShmooDude's modified Leafkiller's Feral/Guardian druid script.
# Support/Discussion thread: http://fluiddruid.net/forum/viewtopic.php?f=3&t=857

############################
## Define Spells, Buffs, Items, Talents ##
############################

# Shared spells
Define(BARKSKIN 22812)
    SpellInfo(BARKSKIN cd=60)
Define(FERAL_SPIRIT 110807)
   SpellInfo(FERAL_SPIRIT cd=120)
Define(HEALING_TOUCH 5185)
Define(MARK_OF_THE_WILD 1126)
    SpellInfo(MARK_OF_THE_WILD duration=3600)
    SpellAddBuff(MARK_OF_THE_WILD MARK_OF_THE_WILD=1)
Define(SYMBIOSIS 110309)
    SpellAddBuff(SYMBIOSIS SYMBIOSIS=1)
Define(WRATH 5176)

# Shared buffs
Define(DREAM_OF_CENARIUS_DAMAGE 108381)
    SpellInfo(DREAM_OF_CENARIUS_DAMAGE duration=30 )
    SpellAddBuff(DREAM_OF_CENARIUS_DAMAGE DREAM_OF_CENARIUS_DAMAGE=1)
Define(NATURES_VIGIL 124974)
    SpellInfo(NATURES_VIGIL cd=180)
    SpellAddBuff(NATURES_VIGIL NATURES_VIGIL=1)
Define(PREDATORY_SWIFTNESS 69369)
    SpellAddBuff(PREDATORY_SWIFTNESS PREDATORY_SWIFTNESS=1)
Define(PRIMAL_FURY 16961)
Define(TRICKS 57933)
    SpellAddBuff(TRICKS TRICKS=1)
Define(WEAKENED_ARMOR 113746)
    SpellInfo(WEAKENED_ARMOR duration=30)
Define(WEAKENED_BLOWS 115798)
    SpellInfo(WEAKENED_BLOWS duration=30)
Define(CLEARCASTING 135700)

# Trinket and Weapon Enchant buffs
Define(ROR_CRIT 139117)
    SpellInfo(ROR_CRIT duration=10)
Define(ROR_MASTERY 139120)
    SpellInfo(ROR_MASTERY duration=10)
Define(ROR_HASTE 139121)
    SpellInfo(ROR_HASTE duration=10)
    SpellList(ROR ROR_CRIT ROR_MASTERY ROR_HASTE)
Define(DANCING_STEEL 120032)
   SpellInfo(DANCING_STEEL duration=12)
Define(SOUL_CHARM 138756)
   SpellInfo(SOUL_CHARM duration=20)
Define(BLADES 138737)
Define(BAD_JUJU 138939)
   SpellInfo(BAD_JUJU duration=20)
Define(VICIOUS_TALISMAN 138700)
   SpellInfo(VICIOUS_TALISMAN duration=20)

# Shared items
ItemList(ROR_ITEM 94532 95802 96174 96546 96918)
ItemList(SOUL_CHARM_ITEM 96741 96369 95997 94512 95625)
ItemList(BAD_JUJU_ITEM 96781 96409 96037 94523 95665)
ItemList(VICIOUS_TALISMAN_ITEM 94511)

# Talents
Define(NATURES_SWIFTNESS_TALENT 4)
Define(RENEWAL_TALENT 5)
Define(CENARION_WARD_TALENT 6)
Define(FAERIE_SWARM_TALENT 7)
Define(TYPHOON_TALENT 9)
Define(SOUL_OF_THE_FOREST 10)
Define(INCARNATION_TALENT 11)
Define(FORCE_OF_NATURE_TALENT 12)
Define(MIGHTY_BASH_TALENT 15)
Define(HEART_OF_THE_WILD_TALENT 16)
Define(DREAM_OF_CENARIUS_TALENT 17)
Define(NATURES_VIGIL_TALENT 18)

# Talent spells
Define(CENARION_WARD 102351)
    SpellInfo(CENARION_WARD cd=30)
Define(FORCE_OF_NATURE 106737)
    SpellInfo(FORCE_OF_NATURE duration=15 cd=60)
Define(HEART_OF_THE_WILD 108292)
    SpellInfo(HEART_OF_THE_WILD cd=360)
    SpellAddBuff(HEART_OF_THE_WILD HEART_OF_THE_WILD=1)
Define(INCARNATION 106731)
    SpellInfo(INCARNATION cd=180)
Define(MIGHTY_BASH 5211)
    SpellInfo(MIGHTY_BASH cd=50)
Define(NATURES_SWIFTNESS 132158)
    SpellInfo(NATURES_SWIFTNESS cd=60)
    SpellAddBuff(NATURES_SWIFTNESS NATURES_SWIFTNESS=1)
Define(RENEWAL 108238)
    SpellInfo(RENEWAL cd=120)
Define(TYPHOON 132469)
    SpellInfo(TYPHOON cd=20)
Define(WILD_CHARGE 102401)
    SpellInfo(WILD_CHARGE cd=15)

#Glyphs
Define(GLYPH_OF_SHRED 114234)
Define(GLYPH_OF_SAVAGERY 127540)

# Shared spells
Define(FAERIE_FERAL 770)
    SpellInfo(FAERIE_FERAL duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_FERAL FAERIE_FERAL=1 WEAKENED_ARMOR=1)
Define(FAERIE_SWARM 102355)
    SpellInfo(FAERIE_SWARM duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_SWARM FAERIE_SWARM=1 WEAKENED_ARMOR=1)

# Cat spells
Define(BERSERK_CAT 106951) #cat cd buff
    SpellInfo(BERSERK_CAT duration=15 cd=180)
    SpellAddBuff(BERSERK_CAT BERSERK_CAT=1)
Define(CAT_FORM 768)
    SpellAddBuff(CAT_FORM CAT_FORM=1)
Define(FEROCIOUS_BITE 22568) #cat finish 25-50 energy
    SpellInfo(FEROCIOUS_BITE energy=25 combo=0)
Define(INCARNATION_CAT 102543)
    SpellInfo(INCARNATION_CAT duration=30 cd=180)
Define(MAIM 22570) #cat interrupt
    SpellInfo(MAIM cd=10 energy=35 combo=0)
Define(MANGLE_CAT 33876) #cat bleed+debuff
    SpellInfo(MANGLE_CAT inccounter=ripshreds energy=35 combo=1)
    SpellInfo(MANGLE_CAT critcombo=1 if_spell=PRIMAL_FURY)
Define(RAKE 1822) #cat bleed
    SpellInfo(RAKE combo=1 duration=15 energy=35 tick=3)
    SpellInfo(RAKE critcombo=1 if_spell=PRIMAL_FURY)
    SpellAddTargetDebuff(RAKE RAKE=1)
    SpellDamageBuff(RAKE DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(RAVAGE 6785)
    SpellInfo(RAVAGE inccounter=ripshreds energy=45 combo=1)
    SpellInfo(RAVAGE critcombo=1 if_spell=PRIMAL_FURY)
Define(RAVAGE_BANG 102545)
    SpellInfo(RAVAGE_BANG inccounter=ripshreds energy=0 combo=1)
    SpellInfo(RAVAGE_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(RIP 1079) #cat bleed
    SpellInfo(RIP resetcounter=ripshreds duration=16 energy=30 tick=2 combo=0)
    SpellAddTargetDebuff(RIP RIP=1)
    SpellDamageBuff(RIP DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(SAVAGE_ROAR_OLD 52610)
    SpellInfo(SAVAGE_ROAR_OLD duration=18 combo=0 energy=25)
    SpellAddBuff(SAVAGE_ROAR_OLD SAVAGE_ROAR_OLD=1)
Define(SAVAGE_ROAR_GLYPHED 127538)
    SpellInfo(SAVAGE_ROAR_GLYPHED duration=12 combo=-5 energy=25)
    SpellAddBuff(SAVAGE_ROAR_GLYPHED SAVAGE_ROAR_GLYPHED=1)
    SpellList(SAVAGE_ROAR 52610 127538)
Define(SHRED 5221) #cat behind
    SpellInfo(SHRED inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED critcombo=1 if_spell=PRIMAL_FURY)
Define(SHRED_BANG 114236)
    SpellInfo(SHRED_BANG inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(STAMPEDE 81022)
    SpellAddBuff(STAMPEDE STAMPEDE=1)
Define(SKULL_BASH_CAT 80965) #cat interrupt
    SpellInfo(SKULL_BASH_CAT cd=15 energy=15)
Define(THRASH_CAT 106830)
    SpellInfo(THRASH_CAT duration=15 energy=50 tick=3)
    SpellAddTargetDebuff(THRASH_CAT THRASH_CAT=1 WEAKENED_BLOWS=1)
    SpellDamageBuff(THRASH_CAT DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(TIGERS_FURY 5217) #cat buff
    SpellInfo(TIGERS_FURY duration=6 energy=-60 cd=30)
    SpellAddBuff(TIGERS_FURY TIGERS_FURY=1)

# Bear spells
Define(BEAR_FORM 5487)
    SpellAddBuff(BEAR_FORM BEAR_FORM=1)
Define(BERSERK_BEAR 106952) #cat+bear cd buff
    SpellInfo(BERSERK_BEAR duration=10 cd=180 )
    SpellAddBuff(BERSERK_BEAR BERSERK_BEAR=1)
Define(ENRAGE 5229)
Define(FRENZIED_REGEN 22842)
Define(INCARNATION_BEAR 102558)
    SpellInfo(INCARNATION_BEAR duration=30 cd=180 )
Define(LACERATE 33745)
Define(MANGLE_BEAR 33878)
    SpellInfo(MANGLE_BEAR cd=3 buffnocd=INCARNATION_BEAR buffnocd=BERSERK_BEAR)
Define(MAUL 6807)
Define(MIGHT_OF_URSOC 106922)
Define(SAVAGE_DEFENSE 62606)
Define(SURVIVAL_INSTINCTS 61336)
Define(SWIPE_BEAR 779)
Define(THRASH_BEAR 77758)
Define(TOOTH_AND_CLAW 135286)
    SpellAddBuff(TOOTH_AND_CLAW TOOTH_AND_CLAW=1)
Define(TOOTH_AND_CLAW_DEBUFF 135601)
    SpellAddTargetDebuff(TOOTH_AND_CLAW_DEBUFF TOOTH_AND_CLAW_DEBUFF=1)

###############
## Define Settings ##
###############

AddCheckBox(cooldownsL "Show Left Rotation Boxes" default)
AddCheckBox(cooldownsR "Show Right Cooldown Boxes" default)
AddCheckBox(altpredictive "Alternate predictive box")
AddCheckBox(bearaoe "Bear AOE Rotation")
AddCheckBox(cooldownsRatio "Show Rake and Rip Ratio Boxes" mastery=2)
AddCheckBox(lucioles SpellName(FAERIE_FERAL) default mastery=2)
AddCheckBox(berserk "Cat Berserk" default mastery=2)
AddCheckBox(infront "Frontal attack" mastery=2)
AddCheckBox(predictive "Hide predictive box" mastery=2)
AddCheckBox(nvbounce "Use healing CDs for damage" mastery=2)

################
## Helper Functions ##
################

# Static Variables; Left as functions instead of Defines for added flexibility and consistency in coding (ex: multiple ilvls of trinkets if we can figure that out)
AddFunction ExpiringBuffSafetyMargin { 0.3 }
AddFunction BossArmor { 24835 }
AddFunction WeakenedArmorPercent { 0.04 }
AddFunction TigersFuryMultiplier { 1.15 }
AddFunction RuneMultiplier { 2 } # Not the actual amount like the rest, but given the power of the rune buff the script should still function properly
AddFunction HeartOfTheWildAgiModifier { 1.06 }
AddFunction LeatherSpecAgiModifier { 1.05 }
AddFunction StatsBuffBonus { 0.05 }
AddFunction RakeBaseDamage { 99 }
AddFunction RakeDamagePerAttackPower { 0.3 }
AddFunction RipBaseDamage { 113 }
AddFunction RipDamagePerComboPoint { 320 }
AddFunction RipDamagePerComboPointAttackPower { 0.0484 }
AddFunction ThrashBaseDamage { 4662 }
AddFunction ThrashDamagePerAttackPower { 1.121 }
AddFunction FerociousBiteBaseDamage { 500 }
AddFunction FerociousBiteDamagePerComboPoint { 762 }
AddFunction FerociousBiteDamagePerComboPointAttackPower { 0.196 }
AddFunction FerociousBiteCritChanceBonus { 0.25 }
AddFunction MangleCatBaseDamage { 78 }
AddFunction MangleCatWeaponDamageMultiplier { 5 }
AddFunction CritPerAP { 2519.04 }
AddFunction DancingSteelAttackPower { 3300 }
AddFunction SoulCharmAttackPower
{
   if HasTrinket(96741) 3430 # Heroic TF 2/2 upgrade
   if HasTrinket(96369) 3244 # Heroic 2/2 upgrade
   if HasTrinket(95997) 3038 # Normal TF 2/2 upgrade
   if HasTrinket(94512) 2874 # Normal 2/2 upgrade
   if HasTrinket(95625) 2384 # LFR 2/2 upgrade
}
AddFunction BadJujuAttackPower
{
   if HasTrinket(96781) 18864 # Heroic TF 2/2 upgrade
   if HasTrinket(96409) 17840 # Heroic 2/2 upgrade
   if HasTrinket(96037) 16712 # Normal TF 2/2 upgrade
   if HasTrinket(94523) 15806 # Normal 2/2 upgrade
   if HasTrinket(95665) 13118 # LFR 2/2 upgrade
}
AddFunction ViciousTalismanAttackPower
{
   17600 # 2/2 upgrade
}
AddFunction EnergyForThrash
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction EnergyForRake
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForRip
{
   if BuffExpires(BERSERK_CAT) 30
   15
}
AddFunction EnergyForMangle
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForFerociousBite
{
   if BuffExpires(BERSERK_CAT) 50
   25
}

# Armor Functions
AddFunction ArmorReduction
{
   if target.DebuffPresent(WEAKENED_ARMOR any=1)
   {
      if target.Level(less 1) 0.679
      0.698
   }
   if target.Level(less 1) 0.651
   0.671
}

# Time till energy for abilities functions (must come before Rune functions)
# Moved energy check from functions to main code to fix predictive algorithm bug within ovale
AddFunction TimeTilEnergyForThrash
{
   if { EnergyForThrash() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      { EnergyForThrash() - Energy() } / EnergyRegen()
   SpellCooldown(TIGERS_FURY)
}
AddFunction TimeTilEnergyForRake
{
   if { EnergyForRake() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      { EnergyForRake() - Energy() } / EnergyRegen()
   SpellCooldown(TIGERS_FURY)
}
AddFunction TimeTilEnergyForRip
{
   if { EnergyForRip() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      { EnergyForRip() - Energy() } / EnergyRegen()
   SpellCooldown(TIGERS_FURY)
}

# Ratio Calculation assistnace functions
AddFunction PrimordiusStats # Primordius Stats Buff
{
   {1 + 0.05 * DebuffStacks(136184)} * {1 - 0.1 * DebuffStacks(136185)} # Thick and Fragile bones
}
AddFunction StatsMultiplier
{
   if TalentPoints(HEART_OF_THE_WILD) # Leatherwearer, Heart of the Wild, Mark of the Wild, Primordius Buffs
   {
      LeatherSpecAgiModifier() * HeartOfTheWildAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   }
   LeatherSpecAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
}
AddFunction DancingSteelAttackPowerIncrease
{
   DancingSteelAttackPower()*StatsMultiplier()
}
AddFunction DancingSteelCritChanceIncrease
{
    DancingSteelAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction SoulCharmAttackPowerIncrease
{
   SoulCharmAttackPower()*BuffStacks(BLADES)*StatsMultiplier()
}
AddFunction SoulCharmCritChanceIncrease
{
   SoulCharmAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction BadJujuAttackPowerIncrease
{
   BadJujuAttackPower()*StatsMultiplier()
}
AddFunction BadJujuCritChanceIncrease
{
   BadJujuAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction ViciousTalismanAttackPowerIncrease
{
   ViciousTalismanAttackPower()*StatsMultiplier()
}
AddFunction ViciousTalismanCritChanceIncrease
{
   ViciousTalismanAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}

# Rake functions
AddFunction RakeTickDamage # Switched to raw numbers in place of Damage(RAKE) for 5.3.4+ compatibility
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + AttackPower()*RakeDamagePerAttackPower()} * DamageMultiplier(RAKE) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}
AddFunction LastRakeTickDamage
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + target.DebuffAttackPower(RAKE)*RakeDamagePerAttackPower()} * target.DebuffDamageMultiplier(RAKE) * {1+target.DebuffMeleeCritChance(RAKE)/100} * {1+target.DebuffMastery(RAKE)/100}
}
AddFunction RuneRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RAKE)
   {
      if Energy() >= EnergyForRake()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRakeMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRakeUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RAKE)
   {
      if Energy() >= EnergyForRake()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffRemains(TIGERS_FURY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRakeMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRakeUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRakeUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RAKE)
   {
      if Energy() >= EnergyForRake()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRakeAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRakeUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RAKE)
   {
      if Energy() >= EnergyForRake()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRakeAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRakeUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRakeUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RAKE)
   {
      if Energy() >= EnergyForRake()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRakeAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRakeUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRakeUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RAKE)
   {
      if Energy() >= EnergyForRake()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRakeAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRakeUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRakeMultiplier
{
    RuneExpiresRakeMultiplier()*TigersFuryExpiresRakeMultiplier()
}
AddFunction TotalRakeAttackPower
{
   DancingSteelExpiresRakeAttackPower() + SoulCharmExpiresRakeAttackPower() + BadJujuExpiresRakeAttackPower() + ViciousTalismanExpiresRakeAttackPower()
}
AddFunction FutureRakeTickDamage
{
    {RakeBaseDamage() + {AttackPower() - TotalRakeAttackPower()} * RakeDamagePerAttackPower()}
   * DamageMultiplier(RAKE)
   * {1 + {MeleeCritChance() - TotalRakeAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}} / 100}
   * {1 + Mastery() / 100}
   / TotalRakeMultiplier()
}

# Rip functions
AddFunction RipTickDamage  # Switched to raw numbers in place of Damage(RIP) for 5.3.4+ compatibility
{
    {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * AttackPower()}} * ComboPoints()}} * DamageMultiplier(RIP) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * target.DebuffAttackPower(RIP)}} * target.DebuffComboPoints(RIP)}} * target.DebuffDamageMultiplier(RIP) * {1+target.DebuffMeleeCritChance(RIP)/100} * {1 + target.DebuffMastery(RIP)/100}
}
AddFunction RuneRipUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RIP)
   {
      if Energy() >= EnergyForRip()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRipMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRipUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRipUsableBeforeExpire
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RIP)
   {
      if Energy() >= EnergyForRip()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffPresent(TIGERS_FURY) and BuffRemains(TIGERS_FURY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRipMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRipUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRipUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RIP)
   {
      if Energy() >= EnergyForRip()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRipAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRipUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRipUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RIP)
   {
      if Energy() >= EnergyForRip()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRipAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRipUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRipUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RIP)
   {
      if Energy() >= EnergyForRip()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRipAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRipUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRipUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RIP)
   {
      if Energy() >= EnergyForRip()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRipAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRipUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRipMultiplier
{
    RuneExpiresRipMultiplier()*TigersFuryExpiresRipMultiplier()
}
AddFunction TotalRipAttackPower
{
   DancingSteelExpiresRipAttackPower() + SoulCharmExpiresRipAttackPower() + BadJujuExpiresRipAttackPower() + ViciousTalismanExpiresRipAttackPower()
}
AddFunction FutureRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * {AttackPower() - TotalRipAttackPower()}}} * ComboPoints()}}
   * DamageMultiplier(RIP)
   * {1 + {MeleeCritChance() - TotalRipAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}}/100}
   * {1 + Mastery()/100}
   / TotalRipMultiplier()
}
AddFunction RipDamageTillDead
{
    # The damage from Rip that is cast under the current conditions and lasting till target is dead.
    # Multiply the damage per tick with the number of ticks that can fit into the time to die.
    FutureRipTickDamage() * {target.TimeToDie() / 2}
}
AddFunction ExistingRipDamageTillDead
{
    # The damage from Rip that is already on the target and lasting till target is dead.
    if target.DebuffPresent(RIP)
    {
        # Multiply the damage per tick with the number of ticks that can fit into the time to die.
        LastRipTickDamage() * {target.TimeToDie() / 2}
    }
        0
}

# Ratio functions
AddFunction RakeRatio
{
    if TargetDebuffPresent(RAKE) 100 * FutureRakeTickDamage()/LastRakeTickDamage()
    100.0
}
AddFunction RipRatio
{
    if TargetDebuffPresent(RIP) 100 * FutureRipTickDamage()/LastRipTickDamage()
    100.0
}

# Damage ability functions
AddFunction FerociousBiteDamage # Switched to raw numbers in place of Damage(FEROCIOUS_BITE) for 5.3.4+ compatibility
{
   if {1+FerociousBiteCritChanceBonus()+{MeleeCritChance()/100}} > 100
      {FerociousBiteBaseDamage() + {FerociousBiteDamagePerComboPoint() + FerociousBiteDamagePerComboPointAttackPower() * AttackPower()} * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE) * 2 * 2 * ArmorReduction()
   {FerociousBiteBaseDamage() + {FerociousBiteDamagePerComboPoint() + FerociousBiteDamagePerComboPointAttackPower() * AttackPower()} * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE)  * {1+FerociousBiteCritChanceBonus()+{MeleeCritChance()/100}} * 2 * ArmorReduction()
}
AddFunction MangleCatDamage
{
   {MangleCatBaseDamage() + WeaponDamage(MH) * MangleCatWeaponDamageMultiplier()} * DamageMultiplier(MANGLE_CAT) * {1+MeleeCritChance()/100} * ArmorReduction()
}
AddFunction ThrashCatDamage
{
   {ThrashBaseDamage() + AttackPower()*ThrashDamagePerAttackPower()} * DamageMultiplier(THRASH_CAT) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}

# Misc functions
AddFunction FaerieFire
{
    if TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_SWARM)
    Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if ComboPoints(more 0) Spell(SAVAGE_ROAR_OLD)
}
AddFunction UsePotion
{
    #virmens_bite_potion
    if CheckBoxOn(potions) and target.Classification(worldboss) Item(virmens_bite_potion)
}



#############################
## Feral rotation functions (Mastery=2) ##
#############################

AddFunction NotInCombat
{
    unless InCombat() {
        if BuffExpires(str_agi_int 400 any=1) Spell(MARK_OF_THE_WILD)
        if BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and TalentPoints(DREAM_OF_CENARIUS_TALENT) Spell(HEALING_TOUCH)
        unless Stance(3) Spell(CAT_FORM)
        if Glyph(GLYPH_OF_SAVAGERY) and ComboPoints() ==0 {
            if BuffRemains(SAVAGE_ROAR_GLYPHED) <15 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-11.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <9 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-8.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <6 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-5.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <3 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-2.5
            or BuffExpires(SAVAGE_ROAR_GLYPHED) {
                SavageRoar()
            }
        }
        if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
    }
}

AddFunction FillerActions {
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&combo_points>=5
    if target.DebuffRemains(THRASH_CAT) <3 and target.TimeToDie() >=9 and ComboPoints() >=5 Spell(THRASH_CAT)
    if TalentPoints(INCARNATION_TALENT)
    {
        #ravage
        if BuffPresent(INCARNATION_CAT) Spell(RAVAGE)
    }
    if not TalentPoints(INCARNATION_TALENT) or BuffExpires(INCARNATION_CAT)
    {
        #actions.filler+=/shred,if=(buff.omen_of_clarity.react|buff.berserk.up|energy.regen>=15)&buff.king_of_the_jungle.down
        if BuffPresent(CLEARCASTING) or BuffPresent(BERSERK_CAT) or EnergyRegen() >=15
        and {not CheckBoxOn(infront)
            or {Glyph(GLYPH_OF_SHRED) and {BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT)}}}
        Spell(SHRED)
        #actions.filler+=/mangle_cat,if=buff.king_of_the_jungle.down
        Spell(MANGLE_CAT)
    }
}

AddFunction SpareGcdCooldowns {
    if TalentPoints(FORCE_OF_NATURE_TALENT)
    {
        #treants
        Spell(FORCE_OF_NATURE)
    }
    # Spirit Wolves goes here when symbiosis is supported appropriately.
}

AddFunction SavageRoarOrWeakenedArmorMissing
{
    #savage_roar,if=buff.savage_roar.down
    if BuffExpires(SAVAGE_ROAR) SavageRoar()
   
    #faerie_fire,if=debuff.weakened_armor.stack<3
    if target.DebuffStacks(WEAKENED_ARMOR any=1) <3 and CheckBoxOn(lucioles) FaerieFire()
}

AddFunction RangeCheck
{
   #range check
    unless target.InRange(MANGLE_CAT) Texture(ability_druid_catformattack)
}

AddFunction IncarnationBerserkLogic
{
    #incarnation,if=energy<=35&!buff.omen_of_clarity.react&cooldown.tigers_fury.remains=0&cooldown.berserk.remains=0
    #use_item,name=eternal_blossom_grips,sync=tigers_fury
    #tigers_fury,if=(energy<=35&!buff.omen_of_clarity.react)|buff.king_of_the_jungle.up
    #berserk,if=buff.tigers_fury.up|(target.time_to_die<15&cooldown.tigers_fury.remains>6)
    if {{Energy() <=35 and BuffExpires(CLEARCASTING)} or BuffPresent(INCARNATION_CAT)} and Spell(TIGERS_FURY)
    {
        if CheckBoxOn(berserk) and Spell(BERSERK_CAT)
        {
            if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION)
            if not TalentPoints(INCARNATION_TALENT) or BuffPresent(INCARNATION_CAT) Spell(BERSERK_CAT)
        }
        unless BuffPresent(BERSERK_CAT) Spell(TIGERS_FURY)
    }
    if CheckBoxOn(berserk) and TalentPoints(INCARNATION_TALENT) and BuffPresent(BERSERK_CAT) Spell(INCARNATION_CAT)
}

AddFunction ExecuteRangeRipFerociousBiteLogic # Left one Doc line in here and added a talent check, normally tried to take them out but this one was annoyingly in a bad place so left here for simplicities sake
{
    #ferocious_bite,if=combo_points>=1&dot.rip.ticking&dot.rip.remains<=3&target.health.pct<=25
    if target.HealthPercent() <=25 and ComboPoints() >=1 and target.DebuffPresent(RIP) and target.DebuffRemains(RIP) <=4 Spell(FEROCIOUS_BITE)
   
    #thrash_cat,if=target.time_to_die>=6&buff.omen_of_clarity.react&dot.thrash_cat.remains<3
    if target.TimeToDie() >=9 and BuffPresent(CLEARCASTING) and target.DebuffRemains(THRASH_CAT) <3 Spell(THRASH_CAT)
   
    #ferocious_bite,if=(target.time_to_die<=4&combo_points>=5)|(target.time_to_die<=1&combo_points>=3)
    if target.TimeToDie() <=4 and ComboPoints() >=5 Spell(FEROCIOUS_BITE)
    if target.TimeToDie() <=1 and ComboPoints() >=3 Spell(FEROCIOUS_BITE)
   
    if target.HealthPercent() <=25
    {
        #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&target.health.pct<25
        if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0 SavageRoar()
       
        if ComboPoints() >=5
        {
            #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&target.health.pct<=25
            if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS) and BuffRemains(SAVAGE_ROAR) >5 Spell(NATURES_SWIFTNESS)
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&$(rip_ratio)>=1.15&buff.dream_of_cenarius_damage.up
            # if not HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=115 UsePotion()
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&buff.rune_of_reorigination.up&buff.dream_of_cenarius_damage.up
            # if HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and BuffPresent(ROR_MASTERY) UsePotion()
           
            #virmens_bite_potion,if=target.time_to_die<=40
            # if target.TimeToDie() <=40 UsePotion()
           
            #rip,line_cd=30,if=combo_points>=5&buff.virmens_bite_potion.up&buff.dream_of_cenarius_damage.up&target.health.pct<=25&target.time_to_die>30
            if RipDamageTillDead() > {ExistingRipDamageTillDead() + FerociousBiteDamage()} Spell(RIP)
         
            #pool_resource,wait=0.25,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))
            #ferocious_bite,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25
            if target.DebuffPresent(RIP)
            {
                unless Energy() >= EnergyForFerociousBite() SpareGcdCooldowns()
                wait if Energy() >= EnergyForFerociousBite() Spell(FEROCIOUS_BITE)
            }
        }
    }
}

AddFunction DocRipLogic # If any changes are applicable to NonDoc logic, also make changes there!!!
{
   if target.HealthPercent() >25 and ComboPoints() >=5 and target.TimeToDie() >30 and RipRatio() >=92
   {
      #natures_swiftness,if=enabled&buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&$(rip_ratio)>=0.92&target.time_to_die>30
      if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS) Spell(NATURES_SWIFTNESS)
       
      #rip,if=combo_points>=5&$(rip_ratio)>=1.15&target.time_to_die>30
      if RipRatio() >= 115 Spell(RIP)
   }
   
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2&buff.dream_of_cenarius_damage.up
   if target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <2 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) Spell(RIP)
   
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rip.multiplier<=tick_multiplier
   if target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=100 Spell(RIP)
   
   #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&dot.rip.remains<3&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
   if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE)
      and BuffExpires(PREDATORY_SWIFTNESS) and ComboPoints() >=5 and target.DebuffRemains(RIP) <3
   {
      Spell(NATURES_SWIFTNESS)
   }
   
    #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
    if target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <2
    {
        Spell(RIP)
    }
}

AddFunction NonDocRipLogic # If any changes are applicable to Doc logic, also make changes there!!!
{
   #rip,if=combo_points>=5&$(rip_ratio)>=1.15&target.time_to_die>30
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
   if {target.HealthPercent() >25 and ComboPoints() >=5 and target.TimeToDie() >30 and RipRatio() >= 115} or {target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <2}
      Spell(RIP)
}

AddFunction SavageRoarRefreshLogic
{
    #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&buff.savage_roar.remains+2>dot.rip.remains
    if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0 and {BuffRemains(SAVAGE_ROAR) +2 > target.DebuffRemains(RIP)} SavageRoar()
   
    #savage_roar,if=buff.savage_roar.remains<=6&combo_points>=5&buff.savage_roar.remains+2<=dot.rip.remains
    if BuffRemains(SAVAGE_ROAR) <=6 and ComboPoints() >=5 and {BuffRemains(SAVAGE_ROAR) +2 <= target.DebuffRemains(RIP)} SavageRoar()
}

AddFunction NonExcuteRangeFerociuosBiteLogic
{
    #actions.doc+=/pool_resource,wait=0.1,if=combo_points>=5&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)
    #actions.doc+=/ferocious_bite,if=combo_points>=5&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)&!((buff.savage_roar.remains-6<=energy.time_to_max-1)&buff.savage_roar.remains+2<=$(rip_remains))
    if ComboPoints() >=5 and target.DebuffPresent(RIP) and BuffPresent(SAVAGE_ROAR)
    and not target.DebuffRemains(RIP)-2 <= TimeToMaxEnergy()-1
    and not BuffRemains(SAVAGE_ROAR)-3 <= TimeToMaxEnergy()-1
    and not {BuffRemains(SAVAGE_ROAR)-6 <= TimeToMaxEnergy()-1
        and BuffRemains(SAVAGE_ROAR)+2 <= target.DebuffRemains(RIP)}
    and target.DebuffRemains(RIP) >=5
    {
        unless Energy() >= EnergyForFerociousBite() SpareGcdCooldowns()
        wait if Energy() >= EnergyForFerociousBite() Spell(FEROCIOUS_BITE)
    }
}

AddFunction RakeLogic
{
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=buff.rune_of_reorigination.up&dot.rake.remains<9&(buff.rune_of_reorigination.remains<=1.5)
      if BuffPresent(ROR_MASTERY) and target.DebuffRemains(RAKE) <9 and BuffRemains(ROR_MASTERY) <=1.5 and TimeTilEnergyForRake() + ExpiringBuffSafetyMargin() < BuffRemains(ROR_MASTERY)
         Spell(RAKE)
         
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*6 - LastRakeTickDamage()*5 >= MangleCatDamage()
         Spell(RAKE)
         
      #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<3.0&(buff.berserk.up|(cooldown.tigers_fury.remains+0.8)>=dot.rake.remains|energy>60)
      if {Energy() < EnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake()}
         or target.DebuffRemains(RAKE) < 3
         Spell(RAKE)
   }
   unless target.TimeToDie() - target.DebuffRemains(RAKE) >3
   {
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*{target.TimeToDie()/3+1} - LastRakeTickDamage()*target.TimeToDie()/3 >= MangleCatDamage()
         Spell(RAKE)
   }
}

AddFunction ThrashLogic
{
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&(dot.rip.remains>=4|buff.berserk.up)
   if {Energy() < EnergyForThrash() and target.DebuffRemains(THRASH_CAT) < {3 + TimeTilEnergyForThrash()}
      and target.TimeToDie() - TimeTilEnergyForThrash() >=9
      and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
         or BuffPresent(BERSERK_CAT)}}
   or {target.DebuffRemains(THRASH_CAT) < 3
      and target.TimeToDie() >=9
      and {target.DebuffRemains(RIP) >=4
         or BuffPresent(BERSERK_CAT)}}
    {
        if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
        wait if Energy() >= EnergyForThrash() Spell(THRASH_CAT)
    }
}

# Feral rotation for talent builds with "Dream of Cenarius".

AddFunction FillerConditionsDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=buff.predatory_swiftness.remains>1
    if BuffRemains(PREDATORY_SWIFTNESS) >1 FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
}

AddFunction MainActionsDoC
{
    #healing_touch,if=buff.predatory_swiftness.up&buff.predatory_swiftness.remains<=1.5&buff.dream_of_cenarius_damage.down
    if BuffPresent(PREDATORY_SWIFTNESS) and BuffRemains(PREDATORY_SWIFTNESS) <=1.5 and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) Spell(HEALING_TOUCH)
   
   SavageRoarOrWeakenedArmorMissing()
   
   #healing_touch,if=buff.predatory_swiftness.up&combo_points>=4&buff.dream_of_cenarius_damage.down
   if BuffPresent(PREDATORY_SWIFTNESS) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and ComboPoints() >=4 Spell(HEALING_TOUCH)
   
   #healing_touch,if=buff.natures_swiftness.up
   if BuffPresent(NATURES_SWIFTNESS) Spell(HEALING_TOUCH)

   RangeCheck()
   
   IncarnationBerserkLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   DocRipLogic()
   
   SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociuosBiteLogic()
   
   #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rake.multiplier<=tick_multiplier
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3 and target.DebuffRemains(RAKE) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RakeRatio() >=100 Spell(RAKE)
   
   RakeLogic()

    ThrashLogic()
}

# Feral rotation for talent builds without "Dream of Cenarius".

AddFunction FillerConditionsNonDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(SOUL_OF_THE_FOREST_TALENT) and ComboPoints() <5 FillerActions()

}

AddFunction MainActionsNonDoC
{
   SavageRoarOrWeakenedArmorMissing()
   
   RangeCheck()
   
   #incarnation,if=energy<=35&!buff.omen_of_clarity.react&cooldown.tigers_fury.remains=0&cooldown.berserk.remains=0
    #use_item,name=eternal_blossom_grips,sync=tigers_fury
    #tigers_fury,if=(energy<=35&!buff.omen_of_clarity.react)|buff.king_of_the_jungle.up
    #berserk,if=buff.tigers_fury.up|(target.time_to_die<15&cooldown.tigers_fury.remains>6)
   IncarnationBerserkLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   NonDocRipLogic()
   
    SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociuosBiteLogic()
   
   RakeLogic()
   
   ThrashLogic()
}

AddFunction Prediction
{
    if Stance(3)
   {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
      {
            MainActionsDoC()
      }
        MainActionsNonDoC()
    }
    if Stance(1)
   {
        if BuffPresent(HEART_OF_THE_WILD) Spell(FRENZIED_REGEN)
         Spell(CAT_FORM)
    }
    if Stance(0)
   {
        if BuffPresent(HEART_OF_THE_WILD)
            if BuffExpires(HEART_OF_THE_WILD) Texture(spell_holy_blessingofagility)
        Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

#####################
## Feral icons (Mastery=2) ##
#####################
AddIcon help=Rake size=small mastery=2 checkboxon=cooldownsRatio
{
    RakeRatio()
}

AddIcon help=Rip size=small mastery=2 checkboxon=cooldownsRatio
{
    RipRatio()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL {
    if target.InRange(SKULL_BASH_CAT) Spell(SKULL_BASH_CAT)
    unless target.Classification(worldboss)
    {
        if TalentPoints(MIGHTY_BASH_TALENT) and target.InRange(MIGHTY_BASH) Spell(MIGHTY_BASH)
        if TalentPoints(TYPHOON_TALENT) and target.InRange(SKULL_BASH_CAT) Spell(TYPHOON)
        if ComboPoints() >0 and target.InRange(MAIM) Spell(MAIM)
    }
    Spell(WILD_CHARGE)
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL { # Berserk Icon
    if BuffPresent(TIGERS_FURY) Spell(BERSERK_CAT)
    if 0s before Spell(BERSERK_CAT) Texture(Ability_mount_polarbear_white)
}


# Predictive rotation
AddIcon help=predictive size=small mastery=2 checkboxon=altpredictive {
    Prediction()
}

AddIcon help=extraCD size=small mastery=2 checkboxon=altpredictive {
    if TalentPoints(HEART_OF_THE_WILD_TALENT) Spell(HEART_OF_THE_WILD)
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) {
        if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
        if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
        if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    }
    if TalentPoints(NATURES_VIGIL_TALENT) Spell(NATURES_VIGIL)
}

# Main rotation
AddIcon help=main mastery=2 {
    NotInCombat()
    if Stance(3)
   {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditionsDoC()
            SpareGcdCooldowns()
        }
        MainActionsNonDoC()
        FillerConditionsNonDoC()
        SpareGcdCooldowns()
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CheckBoxOff(bearaoe) BearMain()
            BearMainAOE()
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CastTime(WRATH) <BuffRemains(HEART_OF_THE_WILD) Spell(WRATH)
            Spell(CAT_FORM)
        }
        Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

# Predictive rotation
AddIcon help=predictive mastery=2 checkboxoff=predictive {
    Prediction()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if BuffExpires(SAVAGE_ROAR) Texture(ability_druid_skinteeth)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rip
    if TargetDebuffExpires(RIP) Texture(ability_ghoulfrenzy)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if TargetDebuffExpires(RAKE) Texture(ability_druid_disembowel)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR {
    Spell(TIGERS_FURY)
}
################################
## Guardian rotation functions (Mastery=3) ##
################################

AddFunction BearMain {
    if Threat() <100 and target.DebuffPresent(LACERATE) and target.DebuffRemains(LACERATE) <2 Spell(LACERATE)
    if Threat() <100 and BuffPresent(INCARNATION_BEAR) and target.DebuffRemains(THRASH_BEAR) <2 Spell(THRASH_BEAR)
   
    Spell(MANGLE_BEAR)
   
   
    # Debuff maintenance.
    if target.DebuffRemains(WEAKENED_BLOWS 3 any=1) <=3 Spell(THRASH_BEAR)
    if target.DebuffRemains(WEAKENED_ARMOR 3 any=1) <=3 or target.DebuffStacks(WEAKENED_ARMOR any=1) <3
    {
        FaerieFire()
    }
   
    Spell(LACERATE)
    if target.DebuffPresent(THRASH_BEAR 6) FaerieFire()
    Spell(THRASH_BEAR)
}

AddFunction BearMainAOE {
    Spell(MANGLE_BEAR)
    Spell(THRASH_BEAR)
    Spell(SWIPE_BEAR)
}

#######################
## Guardian icons (Mastery=3) ##
#######################

AddIcon help=Rake size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=Rip size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    Spell(BARKSKIN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
    if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(TOOTH_AND_CLAW)
    Spell(MAUL)
}

# Main rotation
AddIcon help=main mastery=3 {
    if InCombat(no) and BuffRemains(str_agi_int any=1) <400 Spell(MARK_OF_THE_WILD)
    unless Stance(1) Spell(BEAR_FORM)
   
    if CheckBoxOff(bearaoe) BearMain()
    BearMainAOE()
}

AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}


Huge decrease in CPU utilization from some tweaks Jeshu made to ovale. My script still uses about twice what the current official script does but that's more like 2.5% vs 5% instead of the 20-30% it could use before (or 10-20% if you hacked the throttling back into 5.3.6 like I did). My calculation heavy script should perform about equal to what the official script did in 5.3.6.

Not seeing any obvious bugs (not for ferals anyhow, weapon damage doesn't work for non-ferals) and anyone that had to revert back to 5.3.2 should be able to update to 5.3.7 with no problems.

Posts: 29
Joined: Sun Jan 13, 2013 12:11 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Spanja » Fri Jul 19, 2013 4:32 am

I see that sometimes you suggest to cast Savage Roar on 5 cp with a proc of Predatory Swiftness, which will results in a refresh of Predator Swiftness and you'll lose the bonus of a DoC.

I see in the script that everytime you suggest a HT it's because PS is about to expire. Isn't it better to check if there isn't already any PS proc ?

BTW, 3.5.7 seems a lot better, thanks for your work ;)

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Jul 19, 2013 10:01 am

Spanja wrote:I see that sometimes you suggest to cast Savage Roar on 5 cp with a proc of Predatory Swiftness, which will results in a refresh of Predator Swiftness and you'll lose the bonus of a DoC.

I see in the script that everytime you suggest a HT it's because PS is about to expire. Isn't it better to check if there isn't already any PS proc ?

BTW, 3.5.7 seems a lot better, thanks for your work ;)


Hrm, is savage roar completely gone at that point? Because that should be the only case of it suggesting savage roar before healing touch.

The top of the DoC action list is:
Healing Touch if Predatory Swiftness is about to expire and DoCd is down
Savage roar if it is expired
Healing touch at >=4 combo points if PS is up and DoCd is down
Healing touch if Nature's swiftness is up

Your case should only be occurring if either Savage Roar is completely expired or for some reason you still have a DoC buff up (I don't see how barring using Nature's Swiftness as a heal)

This happens so rarely in simcraft (like 25% of attempts) that its pretty much impossible to measure the DPS impact of such a change.

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Fri Jul 19, 2013 10:22 am

ShmooDude wrote:Huge decrease in CPU utilization from some tweaks Jeshu made to ovale. My script still uses about twice what the current official script does but that's more like 2.5% vs 5% instead of the 20-30% it could use before (or 10-20% if you hacked the throttling back into 5.3.6 like I did). My calculation heavy script should perform about equal to what the official script did in 5.3.6.


In Ovale 5.3.7, if you factor out common code into a function, then that function is basically only evaluated once and the results saved for the current run of the script. There are some more caveats in the details, but that's the best way to understand it. The time savings can be quite significant.

I also fixed some code that I broke a while back that throttled the number of times that a script was run. The refresh interval is currently exposed in the new, reorganized configuration panel under "Icon", and can be changed to vary from 0ms to 500ms. The default value is 100ms, which seems about right for catching consecutive game events and factoring in typical latency.

I certainly welcome all the testing and suggested improvements to Ovale to drive development. Ovale started out as a rather simple scripting engine with rather simple scripts, and it has grown quite a lot since Wrath of the Lich King. Leafkiller's original scripts drove a lot of development in the previous patch, and the feral scripts in this thread have continued the trend. I'm looking forward to more feedback.

Exalted
User avatar
Posts: 1437
Joined: Fri Nov 25, 2011 7:49 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby aggixx » Fri Jul 19, 2013 10:42 am

Well I suppose I should say thanks and congratulations on the huge efficiency changes. While it's definitely no excuse to forsake efficiency it does definitely allow for a lot more breathing room in terms of what's possible (or reasonable) to do in the script.
Image

Exalted
User avatar
Posts: 1145
Joined: Fri Jun 04, 2010 4:28 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Leafkiller » Fri Jul 19, 2013 12:53 pm

Jeshu wrote:Leafkiller's original scripts drove a lot of development in the previous patch, and the feral scripts in this thread have continued the trend. I'm looking forward to more feedback.


That is because Feral's are crazy...and optimize/theorycraft as much or more than any other class. I think it started in BC when we became viable tanks for most of the encounters but our kitty dps was 30+% lower than anyone else's. Anyone else remember the power-shifting addon?

The complexity (and efficacy) of the script has made huge leaps forward in MoP, and none of that would have been possible without your support and enhancements to Ovale, Jeshu. Thanks for making it possible :D

======================

Jeshu wrote:In Ovale 5.3.7, if you factor out common code into a function, then that function is basically only evaluated once and the results saved for the current run of the script.


Sounds good - and provides extra incentive to write the scripts in a structured way. The three most common methods of scaling software are introducing parallelism (i.e. multiple instances which is not viable for this use case), cutting down on I/O (including system calls), and fixing expensive algorithms/cutting down on processing. Your changes are attacking a combination of the I/O and processing. Hopefully you can continue to find opportunities in Ovale to further optimize processing time and to cut down on system I/O.

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Jul 19, 2013 12:58 pm

Yeah, the efficiency changes are amazing.

5.3.7 script update
Spoiler: show
Code: Select all
# ShmooDude's modified Leafkiller's Feral/Guardian druid script.
# Support/Discussion thread: http://fluiddruid.net/forum/viewtopic.php?f=3&t=857

############################
## Define Spells, Buffs, Items, Talents ##
############################

# Shared spells
Define(BARKSKIN 22812)
    SpellInfo(BARKSKIN cd=60)
Define(FERAL_SPIRIT 110807)
   SpellInfo(FERAL_SPIRIT cd=120)
Define(HEALING_TOUCH 5185)
Define(MARK_OF_THE_WILD 1126)
    SpellInfo(MARK_OF_THE_WILD duration=3600)
    SpellAddBuff(MARK_OF_THE_WILD MARK_OF_THE_WILD=1)
Define(SYMBIOSIS 110309)
    SpellAddBuff(SYMBIOSIS SYMBIOSIS=1)
Define(WRATH 5176)

# Shared buffs
Define(DREAM_OF_CENARIUS_DAMAGE 108381)
    SpellInfo(DREAM_OF_CENARIUS_DAMAGE duration=30 )
    SpellAddBuff(DREAM_OF_CENARIUS_DAMAGE DREAM_OF_CENARIUS_DAMAGE=1)
Define(NATURES_VIGIL 124974)
    SpellInfo(NATURES_VIGIL cd=180)
    SpellAddBuff(NATURES_VIGIL NATURES_VIGIL=1)
Define(PREDATORY_SWIFTNESS 69369)
    SpellAddBuff(PREDATORY_SWIFTNESS PREDATORY_SWIFTNESS=1)
Define(PRIMAL_FURY 16961)
Define(TRICKS 57933)
    SpellAddBuff(TRICKS TRICKS=1)
Define(WEAKENED_ARMOR 113746)
    SpellInfo(WEAKENED_ARMOR duration=30)
Define(WEAKENED_BLOWS 115798)
    SpellInfo(WEAKENED_BLOWS duration=30)
Define(CLEARCASTING 135700)

# Trinket and Weapon Enchant buffs
Define(ROR_CRIT 139117)
    SpellInfo(ROR_CRIT duration=10)
Define(ROR_MASTERY 139120)
    SpellInfo(ROR_MASTERY duration=10)
Define(ROR_HASTE 139121)
    SpellInfo(ROR_HASTE duration=10)
    SpellList(ROR ROR_CRIT ROR_MASTERY ROR_HASTE)
Define(DANCING_STEEL 120032)
   SpellInfo(DANCING_STEEL duration=12)
Define(SOUL_CHARM 138756)
   SpellInfo(SOUL_CHARM duration=20)
Define(BLADES 138737)
Define(BAD_JUJU 138939)
   SpellInfo(BAD_JUJU duration=20)
Define(VICIOUS_TALISMAN 138700)
   SpellInfo(VICIOUS_TALISMAN duration=20)

# Shared items
ItemList(ROR_ITEM 94532 95802 96174 96546 96918)
ItemList(SOUL_CHARM_ITEM 96741 96369 95997 94512 95625)
ItemList(BAD_JUJU_ITEM 96781 96409 96037 94523 95665)
ItemList(VICIOUS_TALISMAN_ITEM 94511)

# Talents
Define(NATURES_SWIFTNESS_TALENT 4)
Define(RENEWAL_TALENT 5)
Define(CENARION_WARD_TALENT 6)
Define(FAERIE_SWARM_TALENT 7)
Define(TYPHOON_TALENT 9)
Define(SOUL_OF_THE_FOREST 10)
Define(INCARNATION_TALENT 11)
Define(FORCE_OF_NATURE_TALENT 12)
Define(MIGHTY_BASH_TALENT 15)
Define(HEART_OF_THE_WILD_TALENT 16)
Define(DREAM_OF_CENARIUS_TALENT 17)
Define(NATURES_VIGIL_TALENT 18)

# Talent spells
Define(CENARION_WARD 102351)
    SpellInfo(CENARION_WARD cd=30)
Define(FORCE_OF_NATURE 106737)
    SpellInfo(FORCE_OF_NATURE duration=15 cd=60)
Define(HEART_OF_THE_WILD 108292)
    SpellInfo(HEART_OF_THE_WILD cd=360)
    SpellAddBuff(HEART_OF_THE_WILD HEART_OF_THE_WILD=1)
Define(INCARNATION 106731)
    SpellInfo(INCARNATION cd=180)
Define(MIGHTY_BASH 5211)
    SpellInfo(MIGHTY_BASH cd=50)
Define(NATURES_SWIFTNESS 132158)
    SpellInfo(NATURES_SWIFTNESS cd=60)
    SpellAddBuff(NATURES_SWIFTNESS NATURES_SWIFTNESS=1)
Define(RENEWAL 108238)
    SpellInfo(RENEWAL cd=120)
Define(TYPHOON 132469)
    SpellInfo(TYPHOON cd=20)
Define(WILD_CHARGE 102401)
    SpellInfo(WILD_CHARGE cd=15)

#Glyphs
Define(GLYPH_OF_SHRED 114234)
Define(GLYPH_OF_SAVAGERY 127540)

# Shared spells
Define(FAERIE_FERAL 770)
    SpellInfo(FAERIE_FERAL duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_FERAL FAERIE_FERAL=1 WEAKENED_ARMOR=1)
Define(FAERIE_SWARM 102355)
    SpellInfo(FAERIE_SWARM duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_SWARM FAERIE_SWARM=1 WEAKENED_ARMOR=1)

# Cat spells
Define(BERSERK_CAT 106951) #cat cd buff
    SpellInfo(BERSERK_CAT duration=15 cd=180)
    SpellAddBuff(BERSERK_CAT BERSERK_CAT=1)
Define(CAT_FORM 768)
    SpellAddBuff(CAT_FORM CAT_FORM=1)
Define(FEROCIOUS_BITE 22568) #cat finish 25-50 energy
    SpellInfo(FEROCIOUS_BITE energy=25 combo=0)
Define(INCARNATION_CAT 102543)
    SpellInfo(INCARNATION_CAT duration=30 cd=180)
Define(MAIM 22570) #cat interrupt
    SpellInfo(MAIM cd=10 energy=35 combo=0)
Define(MANGLE_CAT 33876) #cat bleed+debuff
    SpellInfo(MANGLE_CAT inccounter=ripshreds energy=35 combo=1)
    SpellInfo(MANGLE_CAT critcombo=1 if_spell=PRIMAL_FURY)
Define(RAKE 1822) #cat bleed
    SpellInfo(RAKE combo=1 duration=15 energy=35 tick=3)
    SpellInfo(RAKE critcombo=1 if_spell=PRIMAL_FURY)
    SpellAddTargetDebuff(RAKE RAKE=1)
    SpellDamageBuff(RAKE DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(RAVAGE 6785)
    SpellInfo(RAVAGE inccounter=ripshreds energy=45 combo=1)
    SpellInfo(RAVAGE critcombo=1 if_spell=PRIMAL_FURY)
Define(RAVAGE_BANG 102545)
    SpellInfo(RAVAGE_BANG inccounter=ripshreds energy=0 combo=1)
    SpellInfo(RAVAGE_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(RIP 1079) #cat bleed
    SpellInfo(RIP resetcounter=ripshreds duration=16 energy=30 tick=2 combo=0)
    SpellAddTargetDebuff(RIP RIP=1)
    SpellDamageBuff(RIP DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(SAVAGE_ROAR_OLD 52610)
    SpellInfo(SAVAGE_ROAR_OLD duration=18 combo=0 energy=25)
    SpellAddBuff(SAVAGE_ROAR_OLD SAVAGE_ROAR_OLD=1)
Define(SAVAGE_ROAR_GLYPHED 127538)
    SpellInfo(SAVAGE_ROAR_GLYPHED duration=12 combo=-5 energy=25)
    SpellAddBuff(SAVAGE_ROAR_GLYPHED SAVAGE_ROAR_GLYPHED=1)
    SpellList(SAVAGE_ROAR 52610 127538)
Define(SHRED 5221) #cat behind
    SpellInfo(SHRED inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED critcombo=1 if_spell=PRIMAL_FURY)
Define(SHRED_BANG 114236)
    SpellInfo(SHRED_BANG inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(STAMPEDE 81022)
    SpellAddBuff(STAMPEDE STAMPEDE=1)
Define(SKULL_BASH_CAT 80965) #cat interrupt
    SpellInfo(SKULL_BASH_CAT cd=15 energy=15)
Define(THRASH_CAT 106830)
    SpellInfo(THRASH_CAT duration=15 energy=50 tick=3)
    SpellAddTargetDebuff(THRASH_CAT THRASH_CAT=1 WEAKENED_BLOWS=1)
    SpellDamageBuff(THRASH_CAT DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(TIGERS_FURY 5217) #cat buff
    SpellInfo(TIGERS_FURY duration=6 energy=-60 cd=30)
    SpellAddBuff(TIGERS_FURY TIGERS_FURY=1)

# Bear spells
Define(BEAR_FORM 5487)
    SpellAddBuff(BEAR_FORM BEAR_FORM=1)
Define(BERSERK_BEAR 106952) #cat+bear cd buff
    SpellInfo(BERSERK_BEAR duration=10 cd=180 )
    SpellAddBuff(BERSERK_BEAR BERSERK_BEAR=1)
Define(ENRAGE 5229)
Define(FRENZIED_REGEN 22842)
Define(INCARNATION_BEAR 102558)
    SpellInfo(INCARNATION_BEAR duration=30 cd=180 )
Define(LACERATE 33745)
Define(MANGLE_BEAR 33878)
    SpellInfo(MANGLE_BEAR cd=3 buffnocd=INCARNATION_BEAR buffnocd=BERSERK_BEAR)
Define(MAUL 6807)
Define(MIGHT_OF_URSOC 106922)
Define(SAVAGE_DEFENSE 62606)
Define(SURVIVAL_INSTINCTS 61336)
Define(SWIPE_BEAR 779)
Define(THRASH_BEAR 77758)
Define(TOOTH_AND_CLAW 135286)
    SpellAddBuff(TOOTH_AND_CLAW TOOTH_AND_CLAW=1)
Define(TOOTH_AND_CLAW_DEBUFF 135601)
    SpellAddTargetDebuff(TOOTH_AND_CLAW_DEBUFF TOOTH_AND_CLAW_DEBUFF=1)

###############
## Define Settings ##
###############

AddCheckBox(cooldownsL "Show Left Rotation Boxes" default)
AddCheckBox(cooldownsR "Show Right Cooldown Boxes" default)
AddCheckBox(altpredictive "Alternate predictive box")
AddCheckBox(bearaoe "Bear AOE Rotation")
AddCheckBox(cooldownsRatio "Show Rake and Rip Ratio Boxes" mastery=2)
AddCheckBox(lucioles SpellName(FAERIE_FERAL) default mastery=2)
AddCheckBox(berserk "Cat Berserk" default mastery=2)
AddCheckBox(infront "Frontal attack" mastery=2)
AddCheckBox(predictive "Hide predictive box" mastery=2)
AddCheckBox(nvbounce "Use healing CDs for damage" mastery=2)

################
## Helper Functions ##
################

# Static Variables; Left as functions instead of Defines for added flexibility and consistency in coding (ex: multiple ilvls of trinkets if we can figure that out)
AddFunction ExpiringBuffSafetyMargin { 0.3 }
AddFunction BossArmor { 24835 }
AddFunction WeakenedArmorPercent { 0.04 }
AddFunction TigersFuryMultiplier { 1.15 }
AddFunction RuneMultiplier { 2 } # Not the actual amount like the rest, but given the power of the rune buff the script should still function properly
AddFunction HeartOfTheWildAgiModifier { 1.06 }
AddFunction LeatherSpecAgiModifier { 1.05 }
AddFunction StatsBuffBonus { 0.05 }
AddFunction RakeBaseDamage { 99 }
AddFunction RakeDamagePerAttackPower { 0.3 }
AddFunction RipBaseDamage { 113 }
AddFunction RipDamagePerComboPoint { 320 }
AddFunction RipDamagePerComboPointAttackPower { 0.0484 }
AddFunction ThrashBaseDamage { 4662 }
AddFunction ThrashDamagePerAttackPower { 1.121 }
AddFunction FerociousBiteBaseDamage { 500 }
AddFunction FerociousBiteDamagePerComboPoint { 762 }
AddFunction FerociousBiteDamagePerComboPointAttackPower { 0.196 }
AddFunction FerociousBiteCritChanceBonus { 0.25 }
AddFunction FerociousBiteCritChanceRaw { FerociousBiteCritChanceBonus()+{MeleeCritChance()/100} }
AddFunction FerociousBiteCritChance { if FerociousBiteCritChanceRaw() > 1 1 FerociousBiteCritChanceRaw() }
AddFunction MangleCatBaseDamage { 78 }
AddFunction MangleCatWeaponDamageMultiplier { 5 }
AddFunction CritPerAP { 2519.04 }
AddFunction DancingSteelAttackPower { 3300 }
AddFunction SoulCharmAttackPower
{
   if HasTrinket(96741) 3430 # Heroic TF 2/2 upgrade
   if HasTrinket(96369) 3244 # Heroic 2/2 upgrade
   if HasTrinket(95997) 3038 # Normal TF 2/2 upgrade
   if HasTrinket(94512) 2874 # Normal 2/2 upgrade
   if HasTrinket(95625) 2384 # LFR 2/2 upgrade
}
AddFunction BadJujuAttackPower
{
   if HasTrinket(96781) 18864 # Heroic TF 2/2 upgrade
   if HasTrinket(96409) 17840 # Heroic 2/2 upgrade
   if HasTrinket(96037) 16712 # Normal TF 2/2 upgrade
   if HasTrinket(94523) 15806 # Normal 2/2 upgrade
   if HasTrinket(95665) 13118 # LFR 2/2 upgrade
}
AddFunction ViciousTalismanAttackPower
{
   17600 # 2/2 upgrade
}
AddFunction EnergyForThrash
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction EnergyForRake
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForRip
{
   if BuffExpires(BERSERK_CAT) 30
   15
}
AddFunction EnergyForMangle
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForFerociousBite
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction HasEnergyForRake
{
   Energy() >= EnergyForRake()
}
AddFunction DoNotHaveEnergyForRake
{
   Energy() < EnergyForRake()
}
AddFunction HasEnergyForRip
{
   Energy() >= EnergyForRip()
}
AddFunction DoNotHaveEnergyForRip
{
   Energy() < EnergyForRip()
}
AddFunction HasEnergyForFerociousBite
{
   Energy() >= EnergyForFerociousBite()
}
AddFunction DoNotHaveEnergyForFerociousBite
{
   Energy() < EnergyForFerociousBite()
}
AddFunction HasEnergyForThrash
{
   Energy() >= EnergyForThrash()
}
AddFunction DoNotHaveEnergyForThrash
{
   Energy() < EnergyForThrash()
}
AddFunction TigersFuryCooldown
{
   if SpellCooldown(TIGERS_FURY) >= 0 SpellCooldown(TIGERS_FURY)
   0
}

# Armor Functions
AddFunction ArmorReduction
{
   if target.DebuffPresent(WEAKENED_ARMOR any=1)
   {
      if target.Level(less 1) 0.679
      0.698
   }
   if target.Level(less 1) 0.651
   0.671
}

# Time till energy for abilities functions (must come before Rune functions)
# Moved energy check from functions to main code to fix predictive algorithm bug within ovale
AddFunction TimeTilEnergyForThrash
{
   if { EnergyForThrash() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForThrash() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRake
{
   if { EnergyForRake() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForRake() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRip
{
   if { EnergyForRip() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForRip() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}

# Ratio Calculation assistnace functions
AddFunction PrimordiusStats # Primordius Stats Buff
{
   {1 + 0.05 * DebuffStacks(136184)} * {1 - 0.1 * DebuffStacks(136185)} # Thick and Fragile bones
}
AddFunction StatsMultiplier
{
   if TalentPoints(HEART_OF_THE_WILD) # Leatherwearer, Heart of the Wild, Mark of the Wild, Primordius Buffs
   {
      LeatherSpecAgiModifier() * HeartOfTheWildAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   }
   LeatherSpecAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
}
AddFunction DancingSteelAttackPowerIncrease
{
   DancingSteelAttackPower()*StatsMultiplier()
}
AddFunction DancingSteelCritChanceIncrease
{
    DancingSteelAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction SoulCharmAttackPowerIncrease
{
   SoulCharmAttackPower()*BuffStacks(BLADES)*StatsMultiplier()
}
AddFunction SoulCharmCritChanceIncrease
{
   SoulCharmAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction BadJujuAttackPowerIncrease
{
   BadJujuAttackPower()*StatsMultiplier()
}
AddFunction BadJujuCritChanceIncrease
{
   BadJujuAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction ViciousTalismanAttackPowerIncrease
{
   ViciousTalismanAttackPower()*StatsMultiplier()
}
AddFunction ViciousTalismanCritChanceIncrease
{
   ViciousTalismanAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}

# Rake functions
AddFunction RakeTickDamage # Switched to raw numbers in place of Damage(RAKE) for 5.3.4+ compatibility
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + AttackPower()*RakeDamagePerAttackPower()} * DamageMultiplier(RAKE) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}
AddFunction LastRakeTickDamage
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + target.DebuffAttackPower(RAKE)*RakeDamagePerAttackPower()} * target.DebuffDamageMultiplier(RAKE) * {1+target.DebuffMeleeCritChance(RAKE)/100} * {1+target.DebuffMastery(RAKE)/100}
}
AddFunction RuneRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRakeMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRakeUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffRemains(TIGERS_FURY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRakeMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRakeUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRakeUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRakeAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRakeUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRakeAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRakeUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRakeUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRakeAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRakeUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRakeUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRakeAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRakeUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRakeMultiplier
{
    RuneExpiresRakeMultiplier()*TigersFuryExpiresRakeMultiplier()
}
AddFunction TotalRakeAttackPower
{
   DancingSteelExpiresRakeAttackPower() + SoulCharmExpiresRakeAttackPower() + BadJujuExpiresRakeAttackPower() + ViciousTalismanExpiresRakeAttackPower()
}
AddFunction FutureRakeTickDamage
{
    {RakeBaseDamage() + {AttackPower() - TotalRakeAttackPower()} * RakeDamagePerAttackPower()}
   * DamageMultiplier(RAKE)
   * {1 + {MeleeCritChance() - TotalRakeAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}} / 100}
   * {1 + Mastery() / 100}
   / TotalRakeMultiplier()
}

# Rip functions
AddFunction RipTickDamage  # Switched to raw numbers in place of Damage(RIP) for 5.3.4+ compatibility
{
    {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * AttackPower()}} * ComboPoints()}} * DamageMultiplier(RIP) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * target.DebuffAttackPower(RIP)}} * target.DebuffComboPoints(RIP)}} * target.DebuffDamageMultiplier(RIP) * {1+target.DebuffMeleeCritChance(RIP)/100} * {1 + target.DebuffMastery(RIP)/100}
}
AddFunction RuneRipUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRipMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRipUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRipUsableBeforeExpire
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffPresent(TIGERS_FURY) and BuffRemains(TIGERS_FURY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRipMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRipUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRipUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRipAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRipUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRipUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRipAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRipUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRipUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRipAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRipUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRipUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRipAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRipUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRipMultiplier
{
    RuneExpiresRipMultiplier()*TigersFuryExpiresRipMultiplier()
}
AddFunction TotalRipAttackPower
{
   DancingSteelExpiresRipAttackPower() + SoulCharmExpiresRipAttackPower() + BadJujuExpiresRipAttackPower() + ViciousTalismanExpiresRipAttackPower()
}
AddFunction FutureRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * {AttackPower() - TotalRipAttackPower()}}} * ComboPoints()}}
   * DamageMultiplier(RIP)
   * {1 + {MeleeCritChance() - TotalRipAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}}/100}
   * {1 + Mastery()/100}
   / TotalRipMultiplier()
}
AddFunction RipDamageTillDead
{
    # The damage from Rip that is cast under the current conditions and lasting till target is dead.
    # Multiply the damage per tick with the number of ticks that can fit into the time to die.
    FutureRipTickDamage() * {target.TimeToDie() / 2}
}
AddFunction ExistingRipDamageTillDead
{
    # The damage from Rip that is already on the target and lasting till target is dead.
    if target.DebuffPresent(RIP)
    {
        # Multiply the damage per tick with the number of ticks that can fit into the time to die.
        LastRipTickDamage() * {target.TimeToDie() / 2}
    }
        0
}

# Ratio functions
AddFunction RakeRatio
{
    if TargetDebuffPresent(RAKE) 100 * FutureRakeTickDamage()/LastRakeTickDamage()
    100.0
}
AddFunction RipRatio
{
    if TargetDebuffPresent(RIP) 100 * FutureRipTickDamage()/LastRipTickDamage()
    100.0
}

# Damage ability functions
AddFunction FerociousBiteDamage # Switched to raw numbers in place of Damage(FEROCIOUS_BITE) for 5.3.4+ compatibility
{
   {FerociousBiteBaseDamage() + {FerociousBiteDamagePerComboPoint() + FerociousBiteDamagePerComboPointAttackPower() * AttackPower()} * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE)  * {1+FerociousBiteCritChance()} * 2 * ArmorReduction()
}
AddFunction MangleCatDamage
{
   {MangleCatBaseDamage() + WeaponDamage(MH) * MangleCatWeaponDamageMultiplier()} * DamageMultiplier(MANGLE_CAT) * {1+MeleeCritChance()/100} * ArmorReduction()
}
AddFunction ThrashCatDamage
{
   {ThrashBaseDamage() + AttackPower()*ThrashDamagePerAttackPower()} * DamageMultiplier(THRASH_CAT) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}

# Misc functions
AddFunction FaerieFire
{
    if TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_SWARM)
    Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if ComboPoints(more 0) Spell(SAVAGE_ROAR_OLD)
}
AddFunction UsePotion
{
    #virmens_bite_potion
    if CheckBoxOn(potions) and target.Classification(worldboss) Item(virmens_bite_potion)
}



#############################
## Feral rotation functions (Mastery=2) ##
#############################

AddFunction NotInCombat
{
    unless InCombat() {
        if BuffExpires(str_agi_int 400 any=1) Spell(MARK_OF_THE_WILD)
        if BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and TalentPoints(DREAM_OF_CENARIUS_TALENT) Spell(HEALING_TOUCH)
        unless Stance(3) Spell(CAT_FORM)
        if Glyph(GLYPH_OF_SAVAGERY) and ComboPoints() ==0 {
            if BuffRemains(SAVAGE_ROAR_GLYPHED) <15 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-11.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <9 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-8.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <6 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-5.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <3 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-2.5
            or BuffExpires(SAVAGE_ROAR_GLYPHED) {
                SavageRoar()
            }
        }
        if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
    }
}

AddFunction FillerActions {
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&combo_points>=5
    if target.DebuffRemains(THRASH_CAT) <3 and target.TimeToDie() >=9 and ComboPoints() >=5 Spell(THRASH_CAT)
    if TalentPoints(INCARNATION_TALENT)
    {
        #ravage
        if BuffPresent(INCARNATION_CAT) Spell(RAVAGE)
    }
    if not TalentPoints(INCARNATION_TALENT) or BuffExpires(INCARNATION_CAT)
    {
        #actions.filler+=/shred,if=(buff.omen_of_clarity.react|buff.berserk.up|energy.regen>=15)&buff.king_of_the_jungle.down
        if BuffPresent(CLEARCASTING) or BuffPresent(BERSERK_CAT) or EnergyRegen() >=15
        and {not CheckBoxOn(infront)
            or {Glyph(GLYPH_OF_SHRED) and {BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT)}}}
        Spell(SHRED)
        #actions.filler+=/mangle_cat,if=buff.king_of_the_jungle.down
        Spell(MANGLE_CAT)
    }
}

AddFunction SpareGcdCooldowns {
    if TalentPoints(FORCE_OF_NATURE_TALENT)
    {
        #treants
        Spell(FORCE_OF_NATURE)
    }
    # Spirit Wolves goes here when symbiosis is supported appropriately.
}

AddFunction SavageRoarOrWeakenedArmorMissing
{
    #savage_roar,if=buff.savage_roar.down
    if BuffExpires(SAVAGE_ROAR) SavageRoar()
   
    #faerie_fire,if=debuff.weakened_armor.stack<3
    if target.DebuffStacks(WEAKENED_ARMOR any=1) <3 and CheckBoxOn(lucioles) FaerieFire()
}

AddFunction RangeCheck
{
   #range check
    unless target.InRange(MANGLE_CAT) Texture(ability_druid_catformattack)
}

AddFunction IncarnationBerserkLogic
{
    #incarnation,if=energy<=35&!buff.omen_of_clarity.react&cooldown.tigers_fury.remains=0&cooldown.berserk.remains=0
    #use_item,name=eternal_blossom_grips,sync=tigers_fury
    #tigers_fury,if=(energy<=35&!buff.omen_of_clarity.react)|buff.king_of_the_jungle.up
    #berserk,if=buff.tigers_fury.up|(target.time_to_die<15&cooldown.tigers_fury.remains>6)
    if {{Energy() <=35 and BuffExpires(CLEARCASTING)} or BuffPresent(INCARNATION_CAT)} and Spell(TIGERS_FURY)
    {
        if CheckBoxOn(berserk) and Spell(BERSERK_CAT)
        {
            if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION)
            if not TalentPoints(INCARNATION_TALENT) or BuffPresent(INCARNATION_CAT) Spell(BERSERK_CAT)
        }
        unless BuffPresent(BERSERK_CAT) Spell(TIGERS_FURY)
    }
    if CheckBoxOn(berserk) and TalentPoints(INCARNATION_TALENT) and BuffPresent(BERSERK_CAT) Spell(INCARNATION_CAT)
}

AddFunction ExecuteRangeRipFerociousBiteLogic # Left one Doc line in here and added a talent check, normally tried to take them out but this one was annoyingly in a bad place so left here for simplicities sake
{
    #ferocious_bite,if=combo_points>=1&dot.rip.ticking&dot.rip.remains<=3&target.health.pct<=25
    if target.HealthPercent() <=25 and ComboPoints() >=1 and target.DebuffPresent(RIP) and target.DebuffRemains(RIP) <=4 Spell(FEROCIOUS_BITE)
   
    #thrash_cat,if=target.time_to_die>=6&buff.omen_of_clarity.react&dot.thrash_cat.remains<3
    if target.TimeToDie() >=9 and BuffPresent(CLEARCASTING) and target.DebuffRemains(THRASH_CAT) <3 Spell(THRASH_CAT)
   
    #ferocious_bite,if=(target.time_to_die<=4&combo_points>=5)|(target.time_to_die<=1&combo_points>=3)
    if target.TimeToDie() <=4 and ComboPoints() >=5 Spell(FEROCIOUS_BITE)
    if target.TimeToDie() <=1 and ComboPoints() >=3 Spell(FEROCIOUS_BITE)
   
    if target.HealthPercent() <=25
    {
        #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&target.health.pct<25
        if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0 SavageRoar()
       
        if ComboPoints() >=5
        {
            #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&target.health.pct<=25
            if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS) and BuffRemains(SAVAGE_ROAR) >5 Spell(NATURES_SWIFTNESS)
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&$(rip_ratio)>=1.15&buff.dream_of_cenarius_damage.up
            # if not HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=115 UsePotion()
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&buff.rune_of_reorigination.up&buff.dream_of_cenarius_damage.up
            # if HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and BuffPresent(ROR_MASTERY) UsePotion()
           
            #virmens_bite_potion,if=target.time_to_die<=40
            # if target.TimeToDie() <=40 UsePotion()
           
            #rip,line_cd=30,if=combo_points>=5&buff.virmens_bite_potion.up&buff.dream_of_cenarius_damage.up&target.health.pct<=25&target.time_to_die>30
            if RipDamageTillDead() > {ExistingRipDamageTillDead() + FerociousBiteDamage()} Spell(RIP)
         
            #pool_resource,wait=0.25,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))
            #ferocious_bite,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25
            if target.DebuffPresent(RIP)
            {
                if DoNotHaveEnergyForFerociousBite() SpareGcdCooldowns()
                wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
            }
        }
    }
}

AddFunction DocRipLogic # If any changes are applicable to NonDoc logic, also make changes there!!!
{
   if target.HealthPercent() >25 and ComboPoints() >=5 and RipRatio() >=92
   {
      #natures_swiftness,if=enabled&buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&$(rip_ratio)>=0.92&target.time_to_die>30
      if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS) Spell(NATURES_SWIFTNESS)
       
      #rip,if=combo_points>=5&$(rip_ratio)>=1.15
      if RipRatio() >= 115 Spell(RIP)
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<2&buff.dream_of_cenarius_damage.up
   if ComboPoints() >=5 and target.DebuffRemains(RIP) <2 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) Spell(RIP)
   
   #rip,if=combo_points>=5&dot.rip.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rip.multiplier<=tick_multiplier
   if ComboPoints() >=5 and target.DebuffRemains(RIP) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=100 Spell(RIP)
   
   #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&dot.rip.remains<3
   if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE)
      and BuffExpires(PREDATORY_SWIFTNESS) and ComboPoints() >=5 and target.DebuffRemains(RIP) <3
   {
      Spell(NATURES_SWIFTNESS)
   }
   
    #rip,if=combo_points>=5&dot.rip.remains<2
    if ComboPoints() >=5 and target.DebuffRemains(RIP) <2
    {
        Spell(RIP)
    }
}

AddFunction NonDocRipLogic # If any changes are applicable to Doc logic, also make changes there!!!
{
   #rip,if=combo_points>=5&$(rip_ratio)>=1.15
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2
   if {target.HealthPercent() >25 and ComboPoints() >=5 and RipRatio() >= 115} or {ComboPoints() >=5 and target.DebuffRemains(RIP) <2}
      Spell(RIP)
}

AddFunction SavageRoarRefreshLogic
{
    #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&buff.savage_roar.remains+2>dot.rip.remains
    if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0 and {BuffRemains(SAVAGE_ROAR) +2 > target.DebuffRemains(RIP)} SavageRoar()
   
    #savage_roar,if=buff.savage_roar.remains<=6&combo_points>=5&buff.savage_roar.remains+2<=dot.rip.remains
    if BuffRemains(SAVAGE_ROAR) <=6 and ComboPoints() >=5 and {BuffRemains(SAVAGE_ROAR) +2 <= target.DebuffRemains(RIP)} SavageRoar()
}

AddFunction NonExcuteRangeFerociousBiteLogic
{
    #actions.doc+=/pool_resource,wait=0.1,if=combo_points>=5&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)
    #actions.doc+=/ferocious_bite,if=combo_points>=5&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)&!((buff.savage_roar.remains-6<=energy.time_to_max-1)&buff.savage_roar.remains+2<=$(rip_remains))
    if ComboPoints() >=5 and target.DebuffPresent(RIP) and BuffPresent(SAVAGE_ROAR)
    and not target.DebuffRemains(RIP)-2 <= TimeToMaxEnergy()-1
    and not BuffRemains(SAVAGE_ROAR)-3 <= TimeToMaxEnergy()-1
    and not {BuffRemains(SAVAGE_ROAR)-6 <= TimeToMaxEnergy()-1
    and BuffRemains(SAVAGE_ROAR)+2 <= target.DebuffRemains(RIP)}
    and target.DebuffRemains(RIP) >=5
    {
        if DoNotHaveEnergyForFerociousBite() SpareGcdCooldowns()
        wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
    }
}

AddFunction RakeLogic
{
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=buff.rune_of_reorigination.up&dot.rake.remains<9&(buff.rune_of_reorigination.remains<=1.5)
      if BuffPresent(ROR_MASTERY) and target.DebuffRemains(RAKE) <9 and BuffRemains(ROR_MASTERY) <=1.5 and TimeTilEnergyForRake() + ExpiringBuffSafetyMargin() < BuffRemains(ROR_MASTERY)
         Spell(RAKE)
         
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*6 - LastRakeTickDamage()*5 >= MangleCatDamage()
         Spell(RAKE)
         
      #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<3.0
      if {HasEnergyForRake() and target.DebuffRemains(RAKE) < 3}
         or {DoNotHaveEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}
         Spell(RAKE)
   }
   unless target.TimeToDie() - target.DebuffRemains(RAKE) >3
   {
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*{target.TimeToDie()/3+1} - LastRakeTickDamage()*target.TimeToDie()/3 >= MangleCatDamage()
         Spell(RAKE)
   }
}

AddFunction ThrashLogic
{
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&(dot.rip.remains>=4|buff.berserk.up)
   if {HasEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3
      and target.TimeToDie() >=9
      and {target.DebuffRemains(RIP) >=4
         or BuffPresent(BERSERK_CAT)}}
   or {DoNotHaveEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3 + TimeTilEnergyForThrash() and BuffExpires(CLEARCASTING)
      and target.TimeToDie() - TimeTilEnergyForThrash() >=9
      and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
         or BuffPresent(BERSERK_CAT)}}
         {
            if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
            Spell(THRASH_CAT)
         }
}

# Feral rotation for talent builds with "Dream of Cenarius".

AddFunction FillerConditionsDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=buff.predatory_swiftness.remains>1
    if BuffRemains(PREDATORY_SWIFTNESS) >1 FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
}

AddFunction MainActionsDoC
{
    #healing_touch,if=buff.predatory_swiftness.up&buff.predatory_swiftness.remains<=1.5&buff.dream_of_cenarius_damage.down
    if BuffPresent(PREDATORY_SWIFTNESS) and BuffRemains(PREDATORY_SWIFTNESS) <=1.5 and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) Spell(HEALING_TOUCH)
   
   SavageRoarOrWeakenedArmorMissing()
   
   #healing_touch,if=buff.predatory_swiftness.up&combo_points>=4&buff.dream_of_cenarius_damage.down
   if BuffPresent(PREDATORY_SWIFTNESS) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and ComboPoints() >=4 Spell(HEALING_TOUCH)
   
   #healing_touch,if=buff.natures_swiftness.up
   if BuffPresent(NATURES_SWIFTNESS) Spell(HEALING_TOUCH)

   RangeCheck()
   
   IncarnationBerserkLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   DocRipLogic()
   
   SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rake.multiplier<=tick_multiplier
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3 and target.DebuffRemains(RAKE) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RakeRatio() >=100 Spell(RAKE)
   
   RakeLogic()

    ThrashLogic()
}

# Feral rotation for talent builds without "Dream of Cenarius".

AddFunction FillerConditionsNonDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(SOUL_OF_THE_FOREST_TALENT) and ComboPoints() <5 FillerActions()

}

AddFunction MainActionsNonDoC
{
   SavageRoarOrWeakenedArmorMissing()
   
   RangeCheck()
   
   IncarnationBerserkLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   NonDocRipLogic()
   
    SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   RakeLogic()
   
   ThrashLogic()
}

AddFunction Prediction
{
    if Stance(3)
   {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
      {
            MainActionsDoC()
      }
        MainActionsNonDoC()
    }
    if Stance(1)
   {
        if BuffPresent(HEART_OF_THE_WILD) Spell(FRENZIED_REGEN)
         Spell(CAT_FORM)
    }
    if Stance(0)
   {
        if BuffPresent(HEART_OF_THE_WILD)
            if BuffExpires(HEART_OF_THE_WILD) Texture(spell_holy_blessingofagility)
        Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

#####################
## Feral icons (Mastery=2) ##
#####################
AddIcon help=Rake size=small mastery=2 checkboxon=cooldownsRatio
{
    RakeRatio()
}

AddIcon help=Rip size=small mastery=2 checkboxon=cooldownsRatio
{
    RipRatio()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL {
    if target.InRange(SKULL_BASH_CAT) Spell(SKULL_BASH_CAT)
    unless target.Classification(worldboss)
    {
        if TalentPoints(MIGHTY_BASH_TALENT) and target.InRange(MIGHTY_BASH) Spell(MIGHTY_BASH)
        if TalentPoints(TYPHOON_TALENT) and target.InRange(SKULL_BASH_CAT) Spell(TYPHOON)
        if ComboPoints() >0 and target.InRange(MAIM) Spell(MAIM)
    }
    Spell(WILD_CHARGE)
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL { # Berserk Icon
    if BuffPresent(TIGERS_FURY) Spell(BERSERK_CAT)
    if 0s before Spell(BERSERK_CAT) Texture(Ability_mount_polarbear_white)
}


# Predictive rotation
AddIcon help=predictive size=small mastery=2 checkboxon=altpredictive {
    Prediction()
}

AddIcon help=extraCD size=small mastery=2 checkboxon=altpredictive {
    if TalentPoints(HEART_OF_THE_WILD_TALENT) Spell(HEART_OF_THE_WILD)
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) {
        if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
        if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
        if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    }
    if TalentPoints(NATURES_VIGIL_TALENT) Spell(NATURES_VIGIL)
}

# Main rotation
AddIcon help=main mastery=2 {
    NotInCombat()
    if Stance(3)
   {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditionsDoC()
            SpareGcdCooldowns()
        }
        MainActionsNonDoC()
        FillerConditionsNonDoC()
        SpareGcdCooldowns()
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CheckBoxOff(bearaoe) BearMain()
            BearMainAOE()
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CastTime(WRATH) <BuffRemains(HEART_OF_THE_WILD) Spell(WRATH)
            Spell(CAT_FORM)
        }
        Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

# Predictive rotation
AddIcon help=predictive mastery=2 checkboxoff=predictive {
    Prediction()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if BuffExpires(SAVAGE_ROAR) Texture(ability_druid_skinteeth)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rip
    if TargetDebuffExpires(RIP) Texture(ability_ghoulfrenzy)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if TargetDebuffExpires(RAKE) Texture(ability_druid_disembowel)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR {
    Spell(TIGERS_FURY)
}
################################
## Guardian rotation functions (Mastery=3) ##
################################

AddFunction BearMain {
    if Threat() <100 and target.DebuffPresent(LACERATE) and target.DebuffRemains(LACERATE) <2 Spell(LACERATE)
    if Threat() <100 and BuffPresent(INCARNATION_BEAR) and target.DebuffRemains(THRASH_BEAR) <2 Spell(THRASH_BEAR)
   
    Spell(MANGLE_BEAR)
   
   
    # Debuff maintenance.
    if target.DebuffRemains(WEAKENED_BLOWS 3 any=1) <=3 Spell(THRASH_BEAR)
    if target.DebuffRemains(WEAKENED_ARMOR 3 any=1) <=3 or target.DebuffStacks(WEAKENED_ARMOR any=1) <3
    {
        FaerieFire()
    }
   
    Spell(LACERATE)
    if target.DebuffPresent(THRASH_BEAR 6) FaerieFire()
    Spell(THRASH_BEAR)
}

AddFunction BearMainAOE {
    Spell(MANGLE_BEAR)
    Spell(THRASH_BEAR)
    Spell(SWIPE_BEAR)
}

#######################
## Guardian icons (Mastery=3) ##
#######################

AddIcon help=Rake size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=Rip size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    Spell(BARKSKIN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
    if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(TOOTH_AND_CLAW)
    Spell(MAUL)
}

# Main rotation
AddIcon help=main mastery=3 {
    if InCombat(no) and BuffRemains(str_agi_int any=1) <400 Spell(MARK_OF_THE_WILD)
    unless Stance(1) Spell(BEAR_FORM)
   
    if CheckBoxOff(bearaoe) BearMain()
    BearMainAOE()
}

AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}


A few more optimizations based on the new efficiency of functions
Removed the timetodie operators from Rip since the execute range stuff will catch anything <25%. Helps on megera where the heads are usually ~60-70 seconds for my guild. Let me know if this has issues with ultra low hp mobs but I don't think it should.
Removed wait from thrash as it wasn't actually doing anything (wait in ovale only seems to do anything if you want the energy used for an ability to be higher than its energy cost as in pooling to 50 for ferocious bite since it doesn't let you fall down when the buff conditions are true like simcraft does)
A couple of bug fixes related to energy comparisons bug. See Ticket 275
A couple of bug fixes related to clearcasting and low energy situations

Posts: 1
Joined: Fri Jul 19, 2013 2:20 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Allarius » Fri Jul 19, 2013 3:28 pm

Ovale keeps telling me to mangle instead of shred. It randomly throw in FF and rake, despite them being on the mob already and keeps telling me to use Thrash(Which I thought was only for OOC procs). Other times it just seems to spaz out like it's trying to pick something but can't. It just shows a dark box with the gcd constantly trying to go off, but gets stuck. A few seconds later it fixes itself. I haven't touched any settings besides the placement.

Any help with this?
Last edited by Allarius on Fri Jul 19, 2013 3:43 pm, edited 1 time in total.

Honored
Posts: 51
Joined: Wed May 25, 2011 3:12 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Kihrawr » Fri Jul 19, 2013 3:35 pm

Hey Shmoodude, I had one other strange behavior that I'm not sure is correct. I am using the 5.3.6 script.

I use 543 Rune and 543 Renataki. One behavior I was seeing that seemed wrong to me (but may not be, hence me posting), is that if the two trinkets had overlapping procs with Rune's proc finishing first, the script would suggest that I keep Raking right after Rune expired. I find it hard to believe that this is correct, since it didn't seem like a Renataki Rake would surpass the Rune-buffed Rake, at least not immediately.

I also had a couple of situations in my last raid where I had a DoC and Rune-buffed Rip on the target and below sub-25% the script was suggesting that I re-apply Rip instead of using Ferocious Bite when the Rip was unquestionably weaker than the one I had up, e.g., not backed by Rune or DoC.

Other than those glitches I find the current script to be really good at both Rune and Renataki handling, so yay! :)

Revered
User avatar
Posts: 288
Joined: Fri Dec 24, 2010 1:57 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Fri Jul 19, 2013 4:04 pm

Allarius wrote:Ovale keeps telling me to mangle instead of shred. It randomly throw in FF and rake, despite them being on the mob already and keeps telling me to use Thrash(Which I thought was only for OOC procs). Other times it just seems to spaz out like it's trying to pick something but can't. It just shows a dark box with the gcd constantly trying to go off, but gets stuck. A few seconds later it fixes itself. I haven't touched any settings besides the placement.

Any help with this?


Mangle has been the new CP generator over Shred most of this teir. Shred is only used during OoC procs or berserk/bloodlust.

The FF thing you can avoid by clicking on Ovale and unchecking the FF box. The Rake reasoning is Ovale will tell you to overwrite a bleed with a stronger one at anytime. This happens a lot with Renataki's.

Thrash needs to be up on a target all the time. It is now part of our single target rotation regardless of OoC procs.

The reason behind it bugging out like that is at times it is trying to figure out what to suggest next. My suggestion is don't listen to it all the time. Grab some WA Bleed Ratios and that will help a lot.
Image

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Jul 19, 2013 4:21 pm

5.3.7.2

Spoiler: show
Code: Select all
# ShmooDude's modified Leafkiller's Feral/Guardian druid script.
# Support/Discussion thread: http://fluiddruid.net/forum/viewtopic.php?f=3&t=857
# 7/19/13 Version 5.3.7.2

############################
## Define Spells, Buffs, Items, Talents ##
############################

# Shared spells
Define(BARKSKIN 22812)
    SpellInfo(BARKSKIN cd=60)
Define(FERAL_SPIRIT 110807)
   SpellInfo(FERAL_SPIRIT cd=120)
Define(HEALING_TOUCH 5185)
Define(MARK_OF_THE_WILD 1126)
    SpellInfo(MARK_OF_THE_WILD duration=3600)
    SpellAddBuff(MARK_OF_THE_WILD MARK_OF_THE_WILD=1)
Define(SYMBIOSIS 110309)
    SpellAddBuff(SYMBIOSIS SYMBIOSIS=1)
Define(WRATH 5176)

# Shared buffs
Define(DREAM_OF_CENARIUS_DAMAGE 108381)
    SpellInfo(DREAM_OF_CENARIUS_DAMAGE duration=30 )
    SpellAddBuff(DREAM_OF_CENARIUS_DAMAGE DREAM_OF_CENARIUS_DAMAGE=1)
Define(NATURES_VIGIL 124974)
    SpellInfo(NATURES_VIGIL cd=180)
    SpellAddBuff(NATURES_VIGIL NATURES_VIGIL=1)
Define(PREDATORY_SWIFTNESS 69369)
    SpellAddBuff(PREDATORY_SWIFTNESS PREDATORY_SWIFTNESS=1)
Define(PRIMAL_FURY 16961)
Define(TRICKS 57933)
    SpellAddBuff(TRICKS TRICKS=1)
Define(WEAKENED_ARMOR 113746)
    SpellInfo(WEAKENED_ARMOR duration=30)
Define(WEAKENED_BLOWS 115798)
    SpellInfo(WEAKENED_BLOWS duration=30)
Define(CLEARCASTING 135700)

# Trinket and Weapon Enchant buffs
Define(ROR_CRIT 139117)
    SpellInfo(ROR_CRIT duration=10)
Define(ROR_MASTERY 139120)
    SpellInfo(ROR_MASTERY duration=10)
Define(ROR_HASTE 139121)
    SpellInfo(ROR_HASTE duration=10)
    SpellList(ROR ROR_CRIT ROR_MASTERY ROR_HASTE)
Define(DANCING_STEEL 120032)
   SpellInfo(DANCING_STEEL duration=12)
Define(SOUL_CHARM 138756)
   SpellInfo(SOUL_CHARM duration=20)
Define(BLADES 138737)
Define(BAD_JUJU 138939)
   SpellInfo(BAD_JUJU duration=20)
Define(VICIOUS_TALISMAN 138700)
   SpellInfo(VICIOUS_TALISMAN duration=20)

# Shared items
ItemList(ROR_ITEM 94532 95802 96174 96546 96918)
ItemList(SOUL_CHARM_ITEM 96741 96369 95997 94512 95625)
ItemList(BAD_JUJU_ITEM 96781 96409 96037 94523 95665)
ItemList(VICIOUS_TALISMAN_ITEM 94511)

# Talents
Define(NATURES_SWIFTNESS_TALENT 4)
Define(RENEWAL_TALENT 5)
Define(CENARION_WARD_TALENT 6)
Define(FAERIE_SWARM_TALENT 7)
Define(TYPHOON_TALENT 9)
Define(SOUL_OF_THE_FOREST 10)
Define(INCARNATION_TALENT 11)
Define(FORCE_OF_NATURE_TALENT 12)
Define(MIGHTY_BASH_TALENT 15)
Define(HEART_OF_THE_WILD_TALENT 16)
Define(DREAM_OF_CENARIUS_TALENT 17)
Define(NATURES_VIGIL_TALENT 18)

# Talent spells
Define(CENARION_WARD 102351)
    SpellInfo(CENARION_WARD cd=30)
Define(FORCE_OF_NATURE 106737)
    SpellInfo(FORCE_OF_NATURE duration=15 cd=60)
Define(HEART_OF_THE_WILD 108292)
    SpellInfo(HEART_OF_THE_WILD cd=360)
    SpellAddBuff(HEART_OF_THE_WILD HEART_OF_THE_WILD=1)
Define(INCARNATION 106731)
    SpellInfo(INCARNATION cd=180)
Define(MIGHTY_BASH 5211)
    SpellInfo(MIGHTY_BASH cd=50)
Define(NATURES_SWIFTNESS 132158)
    SpellInfo(NATURES_SWIFTNESS cd=60)
    SpellAddBuff(NATURES_SWIFTNESS NATURES_SWIFTNESS=1)
Define(RENEWAL 108238)
    SpellInfo(RENEWAL cd=120)
Define(TYPHOON 132469)
    SpellInfo(TYPHOON cd=20)
Define(WILD_CHARGE 102401)
    SpellInfo(WILD_CHARGE cd=15)

#Glyphs
Define(GLYPH_OF_SHRED 114234)
Define(GLYPH_OF_SAVAGERY 127540)

# Shared spells
Define(FAERIE_FERAL 770)
    SpellInfo(FAERIE_FERAL duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_FERAL FAERIE_FERAL=1 WEAKENED_ARMOR=1)
Define(FAERIE_SWARM 102355)
    SpellInfo(FAERIE_SWARM duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_SWARM FAERIE_SWARM=1 WEAKENED_ARMOR=1)

# Cat spells
Define(BERSERK_CAT 106951) #cat cd buff
    SpellInfo(BERSERK_CAT duration=15 cd=180)
    SpellAddBuff(BERSERK_CAT BERSERK_CAT=1)
Define(CAT_FORM 768)
    SpellAddBuff(CAT_FORM CAT_FORM=1)
Define(FEROCIOUS_BITE 22568) #cat finish 25-50 energy
    SpellInfo(FEROCIOUS_BITE energy=25 combo=0)
Define(INCARNATION_CAT 102543)
    SpellInfo(INCARNATION_CAT duration=30 cd=180)
Define(MAIM 22570) #cat interrupt
    SpellInfo(MAIM cd=10 energy=35 combo=0)
Define(MANGLE_CAT 33876) #cat bleed+debuff
    SpellInfo(MANGLE_CAT inccounter=ripshreds energy=35 combo=1)
    SpellInfo(MANGLE_CAT critcombo=1 if_spell=PRIMAL_FURY)
Define(RAKE 1822) #cat bleed
    SpellInfo(RAKE combo=1 duration=15 energy=35 tick=3)
    SpellInfo(RAKE critcombo=1 if_spell=PRIMAL_FURY)
    SpellAddTargetDebuff(RAKE RAKE=1)
    SpellDamageBuff(RAKE DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(RAVAGE 6785)
    SpellInfo(RAVAGE inccounter=ripshreds energy=45 combo=1)
    SpellInfo(RAVAGE critcombo=1 if_spell=PRIMAL_FURY)
Define(RAVAGE_BANG 102545)
    SpellInfo(RAVAGE_BANG inccounter=ripshreds energy=0 combo=1)
    SpellInfo(RAVAGE_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(RIP 1079) #cat bleed
    SpellInfo(RIP resetcounter=ripshreds duration=16 energy=30 tick=2 combo=0)
    SpellAddTargetDebuff(RIP RIP=1)
    SpellDamageBuff(RIP DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(SAVAGE_ROAR_OLD 52610)
    SpellInfo(SAVAGE_ROAR_OLD duration=18 combo=0 energy=25)
    SpellAddBuff(SAVAGE_ROAR_OLD SAVAGE_ROAR_OLD=1)
Define(SAVAGE_ROAR_GLYPHED 127538)
    SpellInfo(SAVAGE_ROAR_GLYPHED duration=12 combo=-5 energy=25)
    SpellAddBuff(SAVAGE_ROAR_GLYPHED SAVAGE_ROAR_GLYPHED=1)
    SpellList(SAVAGE_ROAR 52610 127538)
Define(SHRED 5221) #cat behind
    SpellInfo(SHRED inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED critcombo=1 if_spell=PRIMAL_FURY)
Define(SHRED_BANG 114236)
    SpellInfo(SHRED_BANG inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(STAMPEDE 81022)
    SpellAddBuff(STAMPEDE STAMPEDE=1)
Define(SKULL_BASH_CAT 80965) #cat interrupt
    SpellInfo(SKULL_BASH_CAT cd=15 energy=15)
Define(THRASH_CAT 106830)
    SpellInfo(THRASH_CAT duration=15 energy=50 tick=3)
    SpellAddTargetDebuff(THRASH_CAT THRASH_CAT=1 WEAKENED_BLOWS=1)
    SpellDamageBuff(THRASH_CAT DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(TIGERS_FURY 5217) #cat buff
    SpellInfo(TIGERS_FURY duration=6 energy=-60 cd=30)
    SpellAddBuff(TIGERS_FURY TIGERS_FURY=1)

# Bear spells
Define(BEAR_FORM 5487)
    SpellAddBuff(BEAR_FORM BEAR_FORM=1)
Define(BERSERK_BEAR 106952) #cat+bear cd buff
    SpellInfo(BERSERK_BEAR duration=10 cd=180 )
    SpellAddBuff(BERSERK_BEAR BERSERK_BEAR=1)
Define(ENRAGE 5229)
Define(FRENZIED_REGEN 22842)
Define(INCARNATION_BEAR 102558)
    SpellInfo(INCARNATION_BEAR duration=30 cd=180 )
Define(LACERATE 33745)
Define(MANGLE_BEAR 33878)
    SpellInfo(MANGLE_BEAR cd=3 buffnocd=INCARNATION_BEAR buffnocd=BERSERK_BEAR)
Define(MAUL 6807)
Define(MIGHT_OF_URSOC 106922)
Define(SAVAGE_DEFENSE 62606)
Define(SURVIVAL_INSTINCTS 61336)
Define(SWIPE_BEAR 779)
Define(THRASH_BEAR 77758)
Define(TOOTH_AND_CLAW 135286)
    SpellAddBuff(TOOTH_AND_CLAW TOOTH_AND_CLAW=1)
Define(TOOTH_AND_CLAW_DEBUFF 135601)
    SpellAddTargetDebuff(TOOTH_AND_CLAW_DEBUFF TOOTH_AND_CLAW_DEBUFF=1)

###############
## Define Settings ##
###############

AddCheckBox(cooldownsL "Show Left Rotation Boxes" default)
AddCheckBox(cooldownsR "Show Right Cooldown Boxes" default)
AddCheckBox(altpredictive "Alternate predictive box")
AddCheckBox(bearaoe "Bear AOE Rotation")
AddCheckBox(cooldownsRatio "Show Rake and Rip Ratio Boxes" mastery=2)
AddCheckBox(lucioles SpellName(FAERIE_FERAL) default mastery=2)
AddCheckBox(berserk "Cat Berserk" default mastery=2)
AddCheckBox(infront "Frontal attack" mastery=2)
AddCheckBox(predictive "Hide predictive box" mastery=2)
AddCheckBox(nvbounce "Use healing CDs for damage" mastery=2)

################
## Helper Functions ##
################

# Static Variables; Left as functions instead of Defines for added flexibility and consistency in coding (ex: multiple ilvls of trinkets if we can figure that out)
AddFunction ExpiringBuffSafetyMargin { 0.3 }
AddFunction BossArmor { 24835 }
AddFunction WeakenedArmorPercent { 0.04 }
AddFunction TigersFuryMultiplier { 1.15 }
AddFunction RuneMultiplier { 2 } # Not the actual amount like the rest, but given the power of the rune buff the script should still function properly
AddFunction HeartOfTheWildAgiModifier { 1.06 }
AddFunction LeatherSpecAgiModifier { 1.05 }
AddFunction StatsBuffBonus { 0.05 }
AddFunction RakeBaseDamage { 99 }
AddFunction RakeDamagePerAttackPower { 0.3 }
AddFunction RipBaseDamage { 113 }
AddFunction RipDamagePerComboPoint { 320 }
AddFunction RipDamagePerComboPointAttackPower { 0.0484 }
AddFunction ThrashBaseDamage { 4662 }
AddFunction ThrashDamagePerAttackPower { 1.121 }
AddFunction FerociousBiteBaseDamage { 500 }
AddFunction FerociousBiteDamagePerComboPoint { 762 }
AddFunction FerociousBiteDamagePerComboPointAttackPower { 0.196 }
AddFunction FerociousBiteCritChanceBonus { 0.25 }
AddFunction FerociousBiteCritChanceRaw { FerociousBiteCritChanceBonus()+{MeleeCritChance()/100} }
AddFunction FerociousBiteCritChance { if FerociousBiteCritChanceRaw() > 1 1 FerociousBiteCritChanceRaw() }
AddFunction MangleCatBaseDamage { 78 }
AddFunction MangleCatWeaponDamageMultiplier { 5 }
AddFunction CritPerAP { 2519.04 }
AddFunction DancingSteelAttackPower { 3300 }
AddFunction SoulCharmAttackPower
{
   if HasTrinket(96741) 3430 # Heroic TF 2/2 upgrade
   if HasTrinket(96369) 3244 # Heroic 2/2 upgrade
   if HasTrinket(95997) 3038 # Normal TF 2/2 upgrade
   if HasTrinket(94512) 2874 # Normal 2/2 upgrade
   if HasTrinket(95625) 2384 # LFR 2/2 upgrade
}
AddFunction BadJujuAttackPower
{
   if HasTrinket(96781) 18864 # Heroic TF 2/2 upgrade
   if HasTrinket(96409) 17840 # Heroic 2/2 upgrade
   if HasTrinket(96037) 16712 # Normal TF 2/2 upgrade
   if HasTrinket(94523) 15806 # Normal 2/2 upgrade
   if HasTrinket(95665) 13118 # LFR 2/2 upgrade
}
AddFunction ViciousTalismanAttackPower
{
   17600 # 2/2 upgrade
}
AddFunction EnergyForThrash
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction EnergyForRake
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForRip
{
   if BuffExpires(BERSERK_CAT) 30
   15
}
AddFunction EnergyForMangle
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForFerociousBite
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction HasEnergyForRake
{
   Energy() >= EnergyForRake()
}
AddFunction DoNotHaveEnergyForRake
{
   Energy() < EnergyForRake()
}
AddFunction HasEnergyForRip
{
   Energy() >= EnergyForRip()
}
AddFunction DoNotHaveEnergyForRip
{
   Energy() < EnergyForRip()
}
AddFunction HasEnergyForFerociousBite
{
   Energy() >= EnergyForFerociousBite()
}
AddFunction DoNotHaveEnergyForFerociousBite
{
   Energy() < EnergyForFerociousBite()
}
AddFunction HasEnergyForThrash
{
   Energy() >= EnergyForThrash()
}
AddFunction DoNotHaveEnergyForThrash
{
   Energy() < EnergyForThrash()
}
AddFunction TigersFuryCooldown
{
   if SpellCooldown(TIGERS_FURY) >= 0 SpellCooldown(TIGERS_FURY)
   0
}

# Armor Functions
AddFunction ArmorReduction
{
   if target.DebuffPresent(WEAKENED_ARMOR any=1)
   {
      if target.Level(less 1) 0.679
      0.698
   }
   if target.Level(less 1) 0.651
   0.671
}

# Time till energy for abilities functions (must come before Rune functions)
# Moved energy check from functions to main code to fix predictive algorithm bug within ovale
AddFunction TimeTilEnergyForThrash
{
   if { EnergyForThrash() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForThrash() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRake
{
   if { EnergyForRake() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForRake() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRip
{
   if { EnergyForRip() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForRip() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}

# Ratio Calculation assistnace functions
AddFunction PrimordiusStats # Primordius Stats Buff
{
   {1 + 0.05 * DebuffStacks(136184)} * {1 - 0.1 * DebuffStacks(136185)} # Thick and Fragile bones
}
AddFunction StatsMultiplier
{
   if TalentPoints(HEART_OF_THE_WILD) # Leatherwearer, Heart of the Wild, Mark of the Wild, Primordius Buffs
   {
      LeatherSpecAgiModifier() * HeartOfTheWildAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   }
   LeatherSpecAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
}
AddFunction DancingSteelAttackPowerIncrease
{
   DancingSteelAttackPower()*StatsMultiplier()
}
AddFunction DancingSteelCritChanceIncrease
{
    DancingSteelAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction SoulCharmAttackPowerIncrease
{
   SoulCharmAttackPower()*BuffStacks(BLADES)*StatsMultiplier()
}
AddFunction SoulCharmCritChanceIncrease
{
   SoulCharmAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction BadJujuAttackPowerIncrease
{
   BadJujuAttackPower()*StatsMultiplier()
}
AddFunction BadJujuCritChanceIncrease
{
   BadJujuAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction ViciousTalismanAttackPowerIncrease
{
   ViciousTalismanAttackPower()*StatsMultiplier()
}
AddFunction ViciousTalismanCritChanceIncrease
{
   ViciousTalismanAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}

# Rake functions
AddFunction RakeTickDamage # Switched to raw numbers in place of Damage(RAKE) for 5.3.4+ compatibility
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + AttackPower()*RakeDamagePerAttackPower()} * DamageMultiplier(RAKE) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}
AddFunction LastRakeTickDamage
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + target.DebuffAttackPower(RAKE)*RakeDamagePerAttackPower()} * target.DebuffDamageMultiplier(RAKE) * {1+target.DebuffMeleeCritChance(RAKE)/100} * {1+target.DebuffMastery(RAKE)/100}
}
AddFunction RuneRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRakeMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRakeUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffRemains(TIGERS_FURY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRakeMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRakeUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRakeUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRakeAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRakeUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRakeAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRakeUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRakeUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRakeAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRakeUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRakeUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRakeAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRakeUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRakeMultiplier
{
    RuneExpiresRakeMultiplier()*TigersFuryExpiresRakeMultiplier()
}
AddFunction TotalRakeAttackPower
{
   DancingSteelExpiresRakeAttackPower() + SoulCharmExpiresRakeAttackPower() + BadJujuExpiresRakeAttackPower() + ViciousTalismanExpiresRakeAttackPower()
}
AddFunction FutureRakeTickDamage
{
    {RakeBaseDamage() + {AttackPower() - TotalRakeAttackPower()} * RakeDamagePerAttackPower()}
   * DamageMultiplier(RAKE)
   * {1 + {MeleeCritChance() - TotalRakeAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}} / 100}
   * {1 + Mastery() / 100}
   / TotalRakeMultiplier()
}

# Rip functions
AddFunction RipTickDamage  # Switched to raw numbers in place of Damage(RIP) for 5.3.4+ compatibility
{
    {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * AttackPower()}} * ComboPoints()}} * DamageMultiplier(RIP) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * target.DebuffAttackPower(RIP)}} * target.DebuffComboPoints(RIP)}} * target.DebuffDamageMultiplier(RIP) * {1+target.DebuffMeleeCritChance(RIP)/100} * {1 + target.DebuffMastery(RIP)/100}
}
AddFunction RuneRipUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRipMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRipUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRipUsableBeforeExpire
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffPresent(TIGERS_FURY) and BuffRemains(TIGERS_FURY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRipMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRipUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRipUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRipAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRipUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRipUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRipAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRipUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRipUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRipAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRipUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRipUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRipAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRipUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRipMultiplier
{
    RuneExpiresRipMultiplier()*TigersFuryExpiresRipMultiplier()
}
AddFunction TotalRipAttackPower
{
   DancingSteelExpiresRipAttackPower() + SoulCharmExpiresRipAttackPower() + BadJujuExpiresRipAttackPower() + ViciousTalismanExpiresRipAttackPower()
}
AddFunction FutureRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * {AttackPower() - TotalRipAttackPower()}}} * ComboPoints()}}
   * DamageMultiplier(RIP)
   * {1 + {MeleeCritChance() - TotalRipAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}}/100}
   * {1 + Mastery()/100}
   / TotalRipMultiplier()
}
AddFunction RipDamageTillDead
{
    # The damage from Rip that is cast under the current conditions and lasting till target is dead.
    # Multiply the damage per tick with the number of ticks that can fit into the time to die.
    FutureRipTickDamage() * {target.TimeToDie() / 2}
}
AddFunction ExistingRipDamageTillDead
{
    # The damage from Rip that is already on the target and lasting till target is dead.
    if target.DebuffPresent(RIP)
    {
        # Multiply the damage per tick with the number of ticks that can fit into the time to die.
        LastRipTickDamage() * {target.TimeToDie() / 2}
    }
        0
}

# Ratio functions
AddFunction RakeRatio
{
    if TargetDebuffPresent(RAKE) 100 * FutureRakeTickDamage()/LastRakeTickDamage()
    100.0
}
AddFunction RipRatio
{
    if TargetDebuffPresent(RIP) 100 * FutureRipTickDamage()/LastRipTickDamage()
    100.0
}

# Damage ability functions
AddFunction FerociousBiteDamage # Switched to raw numbers in place of Damage(FEROCIOUS_BITE) for 5.3.4+ compatibility
{
   {FerociousBiteBaseDamage() + {FerociousBiteDamagePerComboPoint() + FerociousBiteDamagePerComboPointAttackPower() * AttackPower()} * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE)  * {1+FerociousBiteCritChance()} * 2 * ArmorReduction()
}
AddFunction MangleCatDamage
{
   {MangleCatBaseDamage() + WeaponDamage(MH) * MangleCatWeaponDamageMultiplier()} * DamageMultiplier(MANGLE_CAT) * {1+MeleeCritChance()/100} * ArmorReduction()
}
AddFunction ThrashCatDamage
{
   {ThrashBaseDamage() + AttackPower()*ThrashDamagePerAttackPower()} * DamageMultiplier(THRASH_CAT) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}

# Misc functions
AddFunction FaerieFire
{
    if TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_SWARM)
    Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if ComboPoints(more 0) Spell(SAVAGE_ROAR_OLD)
}
AddFunction UsePotion
{
    #virmens_bite_potion
    if CheckBoxOn(potions) and target.Classification(worldboss) Item(virmens_bite_potion)
}



#############################
## Feral rotation functions (Mastery=2) ##
#############################

AddFunction NotInCombat
{
    unless InCombat() {
        if BuffExpires(str_agi_int 400 any=1) Spell(MARK_OF_THE_WILD)
        if BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and TalentPoints(DREAM_OF_CENARIUS_TALENT) Spell(HEALING_TOUCH)
        unless Stance(3) Spell(CAT_FORM)
        if Glyph(GLYPH_OF_SAVAGERY) and ComboPoints() ==0 {
            if BuffRemains(SAVAGE_ROAR_GLYPHED) <15 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-11.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <9 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-8.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <6 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-5.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <3 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-2.5
            or BuffExpires(SAVAGE_ROAR_GLYPHED) {
                SavageRoar()
            }
        }
        if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
    }
}

AddFunction SavageRoarOrWeakenedArmorMissing
{
    #savage_roar,if=buff.savage_roar.down
    if BuffExpires(SAVAGE_ROAR) SavageRoar()
   
    #faerie_fire,if=debuff.weakened_armor.stack<3
    if target.DebuffStacks(WEAKENED_ARMOR any=1) <3 and CheckBoxOn(lucioles) FaerieFire()
}

AddFunction RangeCheck
{
   #range check
    unless target.InRange(MANGLE_CAT) Texture(ability_druid_catformattack)
}

AddFunction IncarnationBerserkTigersFuryLogic
{
    #incarnation,if=energy<=35&!buff.omen_of_clarity.react&cooldown.tigers_fury.remains=0&cooldown.berserk.remains=0
    #use_item,name=eternal_blossom_grips,sync=tigers_fury
    #tigers_fury,if=(energy<=35&!buff.omen_of_clarity.react)|buff.king_of_the_jungle.up
    #berserk,if=buff.tigers_fury.up|(target.time_to_die<15&cooldown.tigers_fury.remains>6)
    if {{Energy() <=35 and BuffExpires(CLEARCASTING)} or BuffPresent(INCARNATION_CAT)} and Spell(TIGERS_FURY)
    {
        if CheckBoxOn(berserk) and Spell(BERSERK_CAT)
        {
            if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION)
            if not TalentPoints(INCARNATION_TALENT) or BuffPresent(INCARNATION_CAT) Spell(BERSERK_CAT)
        }
        unless BuffPresent(BERSERK_CAT) Spell(TIGERS_FURY)
    }
    if CheckBoxOn(berserk) and TalentPoints(INCARNATION_TALENT) and BuffPresent(BERSERK_CAT) Spell(INCARNATION_CAT)
}

AddFunction ExecuteRangeRipFerociousBiteLogic # Left one Doc line in here and added a talent check, normally tried to take them out but this one was annoyingly in a bad place so left here for simplicities sake
{
    #ferocious_bite,if=combo_points>=1&dot.rip.ticking&dot.rip.remains<=3&target.health.pct<=25
    if target.HealthPercent() <=25 and ComboPoints() >=1
      and target.DebuffPresent(RIP) and target.DebuffRemains(RIP) <=4
   {
      Spell(FEROCIOUS_BITE)
   }
   
    #thrash_cat,if=target.time_to_die>=6&buff.omen_of_clarity.react&dot.thrash_cat.remains<3
    if target.TimeToDie() >=9 and BuffPresent(CLEARCASTING)
      and target.DebuffRemains(THRASH_CAT) <3
   {
      Spell(THRASH_CAT)
   }
   
    #ferocious_bite,if=(target.time_to_die<=4&combo_points>=5)|(target.time_to_die<=1&combo_points>=3)
    if target.TimeToDie() <=4 and ComboPoints() >=5 Spell(FEROCIOUS_BITE)
    if target.TimeToDie() <=1 and ComboPoints() >=3 Spell(FEROCIOUS_BITE)
   
    if target.HealthPercent() <=25
    {
        #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&target.health.pct<25
        if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0
      {
         SavageRoar()
      }
       
        if ComboPoints() >=5
        {
            #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&target.health.pct<=25
            if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT)
            and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS)
            and BuffRemains(SAVAGE_ROAR) >5
         {
            Spell(NATURES_SWIFTNESS)
         }
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&$(rip_ratio)>=1.15&buff.dream_of_cenarius_damage.up
            # if not HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=115 UsePotion()
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&buff.rune_of_reorigination.up&buff.dream_of_cenarius_damage.up
            # if HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and BuffPresent(ROR_MASTERY) UsePotion()
           
            #virmens_bite_potion,if=target.time_to_die<=40
            # if target.TimeToDie() <=40 UsePotion()
           
            #rip,line_cd=30,if=combo_points>=5&buff.virmens_bite_potion.up&buff.dream_of_cenarius_damage.up&target.health.pct<=25&target.time_to_die>30
            if RipDamageTillDead() > {ExistingRipDamageTillDead() + FerociousBiteDamage()}
         {
            Spell(RIP)
         }
         
            #pool_resource,wait=0.25,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))
            #ferocious_bite,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25
            if target.DebuffPresent(RIP)
            {
                if DoNotHaveEnergyForFerociousBite() SpareGcdCooldowns()
                wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
            }
        }
    }
}

AddFunction DocRipLogic # If any changes are applicable to NonDoc logic, also make changes there!!!
{
   if target.HealthPercent() >25 and ComboPoints() >=5 and RipRatio() >=92
   {
      #natures_swiftness,if=enabled&buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&$(rip_ratio)>=0.92
      if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS)
      {
         Spell(NATURES_SWIFTNESS)
      }
       
      #rip,if=combo_points>=5&$(rip_ratio)>=1.15
      if RipRatio() >= 115
      {
         Spell(RIP)
      }
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<2&buff.dream_of_cenarius_damage.up
   if ComboPoints() >=5 and target.DebuffRemains(RIP) <2
      and BuffPresent(DREAM_OF_CENARIUS_DAMAGE)
   {
      Spell(RIP)
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rip.multiplier<=tick_multiplier
   if ComboPoints() >=5 and target.DebuffRemains(RIP) <6
      and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=100
   {
      Spell(RIP)
   }
   
   #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&dot.rip.remains<3
   if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE)
      and BuffExpires(PREDATORY_SWIFTNESS) and ComboPoints() >=5 and target.DebuffRemains(RIP) <3
   {
      Spell(NATURES_SWIFTNESS)
   }
   
    #rip,if=combo_points>=5&dot.rip.remains<2
    if ComboPoints() >=5 and target.DebuffRemains(RIP) <2
    {
        Spell(RIP)
    }
}

AddFunction NonDocRipLogic # If any changes are applicable to Doc logic, also make changes there!!!
{
   #rip,if=combo_points>=5&$(rip_ratio)>=1.15
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2
   if {target.HealthPercent() >25 and ComboPoints() >=5 and RipRatio() >= 115}
      or {ComboPoints() >=5 and target.DebuffRemains(RIP) <2}
   {
      Spell(RIP)
   }
}

AddFunction SavageRoarRefreshLogic
{
    #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&buff.savage_roar.remains+2>dot.rip.remains
   #savage_roar,if=buff.savage_roar.remains<=6&combo_points>=5&buff.savage_roar.remains+2<=dot.rip.remains
    if {BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0} or {BuffRemains(SAVAGE_ROAR) <=6 and ComboPoints() >=5}
      and {BuffRemains(SAVAGE_ROAR) +2 > target.DebuffRemains(RIP)}
   {
      SavageRoar()
   }
}

AddFunction NonExcuteRangeFerociousBiteLogic
{
    #actions.doc+=/pool_resource,wait=0.1,if=combo_points>=5&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)
    #actions.doc+=/ferocious_bite,if=combo_points>=5&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)&!((buff.savage_roar.remains-6<=energy.time_to_max-1)&buff.savage_roar.remains+2<=$(rip_remains))
    if ComboPoints() >=5 and target.DebuffPresent(RIP) and BuffPresent(SAVAGE_ROAR)
      and not target.DebuffRemains(RIP)-2 <= TimeToMaxEnergy()-1
      and not BuffRemains(SAVAGE_ROAR)-3 <= TimeToMaxEnergy()-1
      and not {BuffRemains(SAVAGE_ROAR)-6 <= TimeToMaxEnergy()-1
      and BuffRemains(SAVAGE_ROAR)+2 <= target.DebuffRemains(RIP)}
      and target.DebuffRemains(RIP) >=5
    {
        if DoNotHaveEnergyForFerociousBite() SpareGcdCooldowns()
        wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
    }
}

AddFunction RakeLogic
{
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=buff.rune_of_reorigination.up&dot.rake.remains<9&(buff.rune_of_reorigination.remains<=1.5)
      if BuffPresent(ROR_MASTERY) and target.DebuffRemains(RAKE) <9
         and BuffRemains(ROR_MASTERY) <=1.5
         and TimeTilEnergyForRake() + ExpiringBuffSafetyMargin() < BuffRemains(ROR_MASTERY)
      {
         Spell(RAKE)
      }
         
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*6 - LastRakeTickDamage()*5 >= MangleCatDamage()
      {
         Spell(RAKE)
      }
         
      #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<3.0
      if {HasEnergyForRake() and target.DebuffRemains(RAKE) < 3}
         or {DoNotHaveEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}
      {
         Spell(RAKE)
      }
   }
   unless target.TimeToDie() - target.DebuffRemains(RAKE) >3
   {
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*{target.TimeToDie()/3+1} - LastRakeTickDamage()*target.TimeToDie()/3 >= MangleCatDamage()
      {
         Spell(RAKE)
      }
   }
}

AddFunction ThrashLogic
{
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&(dot.rip.remains>=4|buff.berserk.up)
   if {HasEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3
      and target.TimeToDie() >=9
      and {target.DebuffRemains(RIP) >=4
         or BuffPresent(BERSERK_CAT)}}
   or {DoNotHaveEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3 + TimeTilEnergyForThrash() and BuffExpires(CLEARCASTING)
      and target.TimeToDie() - TimeTilEnergyForThrash() >=9
      and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
         or BuffPresent(BERSERK_CAT)}}
   {
      if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
      Spell(THRASH_CAT)
   }
}

AddFunction FillerActions {
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&combo_points>=5
    if target.DebuffRemains(THRASH_CAT) <3 and target.TimeToDie() >=9 and ComboPoints() >=5 Spell(THRASH_CAT)
    if TalentPoints(INCARNATION_TALENT)
    {
        #ravage
        if BuffPresent(INCARNATION_CAT) Spell(RAVAGE)
    }
    if not TalentPoints(INCARNATION_TALENT) or BuffExpires(INCARNATION_CAT)
    {
        #actions.filler+=/shred,if=(buff.omen_of_clarity.react|buff.berserk.up|energy.regen>=15)&buff.king_of_the_jungle.down
        if BuffPresent(CLEARCASTING) or BuffPresent(BERSERK_CAT) or EnergyRegen() >=15
        and {not CheckBoxOn(infront)
            or {Glyph(GLYPH_OF_SHRED) and {BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT)}}}
        Spell(SHRED)
        #actions.filler+=/mangle_cat,if=buff.king_of_the_jungle.down
        Spell(MANGLE_CAT)
    }
}

AddFunction SpareGcdCooldowns {
    if TalentPoints(FORCE_OF_NATURE_TALENT)
    {
        #treants
        Spell(FORCE_OF_NATURE)
    }
    # Spirit Wolves goes here when symbiosis is supported appropriately.
}

# Feral rotation for talent builds with "Dream of Cenarius".

AddFunction FillerConditionsDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=buff.predatory_swiftness.remains>1
    if BuffRemains(PREDATORY_SWIFTNESS) >1 FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
}

AddFunction MainActionsDoC
{
    #healing_touch,if=buff.predatory_swiftness.up&buff.predatory_swiftness.remains<=1.5&buff.dream_of_cenarius_damage.down
    if BuffPresent(PREDATORY_SWIFTNESS) and BuffRemains(PREDATORY_SWIFTNESS) <=1.5 and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) Spell(HEALING_TOUCH)
   
   SavageRoarOrWeakenedArmorMissing()
   
   #healing_touch,if=buff.predatory_swiftness.up&combo_points>=4&buff.dream_of_cenarius_damage.down
   if BuffPresent(PREDATORY_SWIFTNESS) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and ComboPoints() >=4 Spell(HEALING_TOUCH)
   
   #healing_touch,if=buff.natures_swiftness.up
   if BuffPresent(NATURES_SWIFTNESS) Spell(HEALING_TOUCH)

   RangeCheck()
   
   IncarnationBerserkTigersFuryLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   DocRipLogic()
   
   SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rake.multiplier<=tick_multiplier
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3 and target.DebuffRemains(RAKE) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RakeRatio() >=100 Spell(RAKE)
   
   RakeLogic()

    ThrashLogic()
}

# Feral rotation for talent builds without "Dream of Cenarius".

AddFunction FillerConditionsNonDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(SOUL_OF_THE_FOREST_TALENT) and ComboPoints() <5 FillerActions()

}

AddFunction MainActionsNonDoC
{
   SavageRoarOrWeakenedArmorMissing()
   
   RangeCheck()
   
   IncarnationBerserkTigersFuryLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   NonDocRipLogic()
   
    SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   RakeLogic()
   
   ThrashLogic()
}

AddFunction Prediction
{
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsNonDoC()
        }
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) Spell(FRENZIED_REGEN)
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if BuffExpires(HEART_OF_THE_WILD) Texture(spell_holy_blessingofagility)
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

#####################
## Feral icons (Mastery=2) ##
#####################

AddIcon help=Rake size=small mastery=2 checkboxon=cooldownsRatio
{
    RakeRatio()
}

AddIcon help=Rip size=small mastery=2 checkboxon=cooldownsRatio
{
    RipRatio()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL {
    if target.InRange(SKULL_BASH_CAT) Spell(SKULL_BASH_CAT)
    unless target.Classification(worldboss)
    {
        if TalentPoints(MIGHTY_BASH_TALENT) and target.InRange(MIGHTY_BASH) Spell(MIGHTY_BASH)
        if TalentPoints(TYPHOON_TALENT) and target.InRange(SKULL_BASH_CAT) Spell(TYPHOON)
        if ComboPoints() >0 and target.InRange(MAIM) Spell(MAIM)
    }
    Spell(WILD_CHARGE)
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL { # Berserk Icon
    if BuffPresent(TIGERS_FURY) Spell(BERSERK_CAT)
    if 0s before Spell(BERSERK_CAT) Texture(Ability_mount_polarbear_white)
}


# Predictive rotation
AddIcon help=predictive size=small mastery=2 checkboxon=altpredictive {
    Prediction()
}

AddIcon help=extraCD size=small mastery=2 checkboxon=altpredictive {   
    if TalentPoints(HEART_OF_THE_WILD_TALENT) Spell(HEART_OF_THE_WILD)
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) {
        if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
        if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
        if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    }
    if TalentPoints(NATURES_VIGIL_TALENT) Spell(NATURES_VIGIL)
}

# Main rotation
AddIcon help=main mastery=2 {
    NotInCombat()
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditionsDoC()
            SpareGcdCooldowns()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsNonDoC()
            FillerConditionsNonDoC()
            SpareGcdCooldowns()
        }
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CheckBoxOff(bearaoe) BearMain()
            if CheckBoxOn(bearaoe) BearMainAOE()
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CastTime(WRATH) <BuffRemains(HEART_OF_THE_WILD) Spell(WRATH)
            Spell(CAT_FORM)
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

# Predictive rotation
AddIcon help=predictive mastery=2 checkboxoff=predictive {
    Prediction()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if BuffExpires(SAVAGE_ROAR) Texture(ability_druid_skinteeth)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rip
    if TargetDebuffExpires(RIP) Texture(ability_ghoulfrenzy)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if TargetDebuffExpires(RAKE) Texture(ability_druid_disembowel)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR {
    Spell(TIGERS_FURY)
}

################################
## Guardian rotation functions (Mastery=3) ##
################################

AddFunction BearMain {
    if Threat() <100 and target.DebuffPresent(LACERATE) and target.DebuffRemains(LACERATE) <2 Spell(LACERATE)
    if Threat() <100 and BuffPresent(INCARNATION_BEAR) and target.DebuffRemains(THRASH_BEAR) <2 Spell(THRASH_BEAR)
   
    Spell(MANGLE_BEAR)
   
   
    # Debuff maintenance.
    if target.DebuffRemains(WEAKENED_BLOWS 3 any=1) <=3 Spell(THRASH_BEAR)
    if target.DebuffRemains(WEAKENED_ARMOR 3 any=1) <=3 or target.DebuffStacks(WEAKENED_ARMOR any=1) <3
    {
        FaerieFire()
    }
   
    Spell(LACERATE)
    if target.DebuffPresent(THRASH_BEAR 6) FaerieFire()
    Spell(THRASH_BEAR)
}

AddFunction BearMainAOE {
    Spell(MANGLE_BEAR)
    Spell(THRASH_BEAR)
    Spell(SWIPE_BEAR)
}

#######################
## Guardian icons (Mastery=3) ##
#######################

AddIcon help=Rake size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=Rip size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    Spell(BARKSKIN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
    if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(TOOTH_AND_CLAW)
    unless BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(MAUL)
}

# Main rotation
AddIcon help=main mastery=3 {
    if InCombat(no) and BuffRemains(str_agi_int any=1) <400 Spell(MARK_OF_THE_WILD)
    unless Stance(1) Spell(BEAR_FORM)
   
    if CheckBoxOff(bearaoe) BearMain()
    if CheckBoxOn(bearaoe) BearMainAOE()
}

AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}
AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}


Fixed Doc code and should hopefully have fixed any flow problems

Kihrawr wrote:Hey Shmoodude, I had one other strange behavior that I'm not sure is correct. I am using the 5.3.6 script.

I use 543 Rune and 543 Renataki. One behavior I was seeing that seemed wrong to me (but may not be, hence me posting), is that if the two trinkets had overlapping procs with Rune's proc finishing first, the script would suggest that I keep Raking right after Rune expired. I find it hard to believe that this is correct, since it didn't seem like a Renataki Rake would surpass the Rune-buffed Rake, at least not immediately.

I also had a couple of situations in my last raid where I had a DoC and Rune-buffed Rip on the target and below sub-25% the script was suggesting that I re-apply Rip instead of using Ferocious Bite when the Rip was unquestionably weaker than the one I had up, e.g., not backed by Rune or DoC.

Other than those glitches I find the current script to be really good at both Rune and Renataki handling, so yay! :)


Are you using 5.3.6 with it? There's a pretty serious bug in 5.3.6 where Ovale will "forget" the values for Rip on a target (only seems to happen in raids for me, i can do target dummies all day long and not run into the bug) and thus anytime that happens it will always think a new rip is better. Jeshu thinks he has this fixed for 5.3.7 but I haven't had an opportunity to test it yet.

Rune logic I got messed up and it wasn't actually fixing the recommendations close to expiring so in newer versions I simply made it match the rest of them (with an "assumed" ratio of 2.0, which while not mathematically perfect, should still generate the correct recommendations)

Spanja wrote:I see that sometimes you suggest to cast Savage Roar on 5 cp with a proc of Predatory Swiftness, which will results in a refresh of Predator Swiftness and you'll lose the bonus of a DoC.

I see in the script that everytime you suggest a HT it's because PS is about to expire. Isn't it better to check if there isn't already any PS proc ?

BTW, 3.5.7 seems a lot better, thanks for your work ;)


I think leafkiller found the problem with this. It was me not understanding the intricacies of how ovale evaluates all valid nodes and then picks the one it thinks is best (based on soonest occuring I believe). DoC was evaluating both the DoC and Non-Doc code and so was probably getting a valid Savage Roar call from the non-doc code. Should be fixed in 5.3.7 version above.

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Fri Jul 19, 2013 4:26 pm

ShmooDude wrote:Removed wait from thrash as it wasn't actually doing anything (wait in ovale only seems to do anything if you want the energy used for an ability to be higher than its energy cost as in pooling to 50 for ferocious bite since it doesn't let you fall down when the buff conditions are true like simcraft does)

Could you elaborate on this? The way I implemented wait in Ovale was based on the documentation for SimC's pool_resource. What were you trying to do with Thrash and wait?

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Fri Jul 19, 2013 4:42 pm

ShmooDude wrote:Are you using 5.3.6 with it? There's a pretty serious bug in 5.3.6 where Ovale will "forget" the values for Rip on a target (only seems to happen in raids for me, i can do target dummies all day long and not run into the bug) and thus anytime that happens it will always think a new rip is better. Jeshu thinks he has this fixed for 5.3.7 but I haven't had an opportunity to test it yet.

If the changes in 5.3.7 don't fix it, then I have another solution in mind that I was trying to avoid but will likely fix it definitively. The problem is that it can make Ovale's memory usage grow and it would rely on the Lua garbage collector instead of the pool code I had implemented into various modules to bound memory usage. However, if it's needed for correctness, then there's not much choice -- DoT snapshotting is too important of a feature to roll back as it's needed for many class's optimal action lists (pretty much every DoT class).

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Jul 19, 2013 8:16 pm

Jeshu wrote:
ShmooDude wrote:Removed wait from thrash as it wasn't actually doing anything (wait in ovale only seems to do anything if you want the energy used for an ability to be higher than its energy cost as in pooling to 50 for ferocious bite since it doesn't let you fall down when the buff conditions are true like simcraft does)

Could you elaborate on this? The way I implemented wait in Ovale was based on the documentation for SimC's pool_resource. What were you trying to do with Thrash and wait?


Basically, the way it was coded (this is from the official script) there was no need for the "wait"

Code: Select all
    if target.DebuffRemains(THRASH_CAT) < {3 + TimeTilEnergyForThrash()}
    and target.TimeToDie() - TimeTilEnergyForThrash() >=9
    and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
        or BuffPresent(BERSERK_CAT)}
    {
        if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
        wait if {BuffExpires(BERSERK_CAT) and Energy() >=50} or {BuffPresent(BERSERK_CAT) and Energy() >=25} Spell(THRASH_CAT)
    }
    Spell(MANGLE_CAT) #added to illustrate, code afterward is actually slightly more complex but essentially functions like this


Since as soon as all the conditions become true, the icon will change from Mangle to Thrash regardless of energy level (assuming there wasn't something higher up in the list needed to be done).
However, in Simcraft, if you don't use wait, it will fall past Thrash and actually use mangle, thus never having enough energy to use Thrash (50 energy for thrash vs 35 energy for Mangle).
I don't think its a problem. I think its just a case of the wait being put in to match simcraft when its simply not necessary in ovale unless the amount of energy you want to use it at is greater than the energy cost of the ability (as with Ferocious Bite where we use it at 50 energy when it costs 25), and so I went ahead and removed it (it functions exactly the same both with and without the wait).

Jeshu wrote:
ShmooDude wrote:Huge decrease in CPU utilization from some tweaks Jeshu made to ovale. My script still uses about twice what the current official script does but that's more like 2.5% vs 5% instead of the 20-30% it could use before (or 10-20% if you hacked the throttling back into 5.3.6 like I did). My calculation heavy script should perform about equal to what the official script did in 5.3.6.


In Ovale 5.3.7, if you factor out common code into a function, then that function is basically only evaluated once and the results saved for the current run of the script. There are some more caveats in the details, but that's the best way to understand it. The time savings can be quite significant.

I also fixed some code that I broke a while back that throttled the number of times that a script was run. The refresh interval is currently exposed in the new, reorganized configuration panel under "Icon", and can be changed to vary from 0ms to 500ms. The default value is 100ms, which seems about right for catching consecutive game events and factoring in typical latency.

I certainly welcome all the testing and suggested improvements to Ovale to drive development. Ovale started out as a rather simple scripting engine with rather simple scripts, and it has grown quite a lot since Wrath of the Lich King. Leafkiller's original scripts drove a lot of development in the previous patch, and the feral scripts in this thread have continued the trend. I'm looking forward to more feedback.


I had a thought on another optimization, though I don't know how easy/difficult it would be to implement.

Would it be possible to extend the current logic of only evaluating a function once to any matching nodes/node comparison?

Here's an example of what I mean. Compare the following:

Code: Select all
AddFunction HasEnergy { Energy() >= 50 }
AddIcon
{
   if HasEnergy()
   if HasEnergy()
   # repeated * 3000 to get an idea of the CPU usage
   if HasEnergy()
   if HasEnergy()
      Spell(1822)
}

vs.
Code: Select all
AddIcon
{
   if Energy() >= 50
   if Energy() >= 50
   # repeated * 3000 to get an idea of the difference in CPU usage
   if Energy() >= 50
   if Energy() >= 50
      Spell(1822)
}


The first runs at about half the CPU utilization of the second showing that its more efficient if you have any sections that repeat to throw them into a function. What I was thinking was if ovale could recognize that the code sections are identical, to just run the comparison once and save the value.

Not sure how well this would work (if the extra overhead in looking for like comparisons would nullify the savings from saving it for example) or how easy it would be to implement, but I figured it couldn't hurt throwing the idea out there.

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Jul 19, 2013 11:28 pm

5.3.7.3

Spoiler: show
Code: Select all
# ShmooDude's modified Leafkiller's Feral/Guardian druid script.
# Support/Discussion thread: http://fluiddruid.net/forum/viewtopic.php?f=3&t=857
# 7/19/13 Version 5.3.7.3

############################
## Define Spells, Buffs, Items, Talents ##
############################

# Shared spells
Define(BARKSKIN 22812)
    SpellInfo(BARKSKIN cd=60)
Define(FERAL_SPIRIT 110807)
   SpellInfo(FERAL_SPIRIT cd=120)
Define(HEALING_TOUCH 5185)
Define(MARK_OF_THE_WILD 1126)
    SpellInfo(MARK_OF_THE_WILD duration=3600)
    SpellAddBuff(MARK_OF_THE_WILD MARK_OF_THE_WILD=1)
Define(SYMBIOSIS 110309)
    SpellAddBuff(SYMBIOSIS SYMBIOSIS=1)
Define(WRATH 5176)

# Shared buffs
Define(DREAM_OF_CENARIUS_DAMAGE 108381)
    SpellInfo(DREAM_OF_CENARIUS_DAMAGE duration=30 )
    SpellAddBuff(DREAM_OF_CENARIUS_DAMAGE DREAM_OF_CENARIUS_DAMAGE=1)
Define(NATURES_VIGIL 124974)
    SpellInfo(NATURES_VIGIL cd=180)
    SpellAddBuff(NATURES_VIGIL NATURES_VIGIL=1)
Define(PREDATORY_SWIFTNESS 69369)
    SpellAddBuff(PREDATORY_SWIFTNESS PREDATORY_SWIFTNESS=1)
Define(PRIMAL_FURY 16961)
Define(TRICKS 57933)
    SpellAddBuff(TRICKS TRICKS=1)
Define(WEAKENED_ARMOR 113746)
    SpellInfo(WEAKENED_ARMOR duration=30)
Define(WEAKENED_BLOWS 115798)
    SpellInfo(WEAKENED_BLOWS duration=30)
Define(CLEARCASTING 135700)

# Trinket and Weapon Enchant buffs
Define(ROR_CRIT 139117)
    SpellInfo(ROR_CRIT duration=10)
Define(ROR_MASTERY 139120)
    SpellInfo(ROR_MASTERY duration=10)
Define(ROR_HASTE 139121)
    SpellInfo(ROR_HASTE duration=10)
    SpellList(ROR ROR_CRIT ROR_MASTERY ROR_HASTE)
Define(DANCING_STEEL 120032)
   SpellInfo(DANCING_STEEL duration=12)
Define(SOUL_CHARM 138756)
   SpellInfo(SOUL_CHARM duration=20)
Define(BLADES 138737)
Define(BAD_JUJU 138939)
   SpellInfo(BAD_JUJU duration=20)
Define(VICIOUS_TALISMAN 138700)
   SpellInfo(VICIOUS_TALISMAN duration=20)

# Shared items
ItemList(ROR_ITEM 94532 95802 96174 96546 96918)
ItemList(SOUL_CHARM_ITEM 96741 96369 95997 94512 95625)
ItemList(BAD_JUJU_ITEM 96781 96409 96037 94523 95665)
ItemList(VICIOUS_TALISMAN_ITEM 94511)

# Talents
Define(NATURES_SWIFTNESS_TALENT 4)
Define(RENEWAL_TALENT 5)
Define(CENARION_WARD_TALENT 6)
Define(FAERIE_SWARM_TALENT 7)
Define(TYPHOON_TALENT 9)
Define(SOUL_OF_THE_FOREST 10)
Define(INCARNATION_TALENT 11)
Define(FORCE_OF_NATURE_TALENT 12)
Define(MIGHTY_BASH_TALENT 15)
Define(HEART_OF_THE_WILD_TALENT 16)
Define(DREAM_OF_CENARIUS_TALENT 17)
Define(NATURES_VIGIL_TALENT 18)

# Talent spells
Define(CENARION_WARD 102351)
    SpellInfo(CENARION_WARD cd=30)
Define(FORCE_OF_NATURE 106737)
    SpellInfo(FORCE_OF_NATURE duration=15 cd=60)
Define(HEART_OF_THE_WILD 108292)
    SpellInfo(HEART_OF_THE_WILD cd=360)
    SpellAddBuff(HEART_OF_THE_WILD HEART_OF_THE_WILD=1)
Define(INCARNATION 106731)
    SpellInfo(INCARNATION cd=180)
Define(MIGHTY_BASH 5211)
    SpellInfo(MIGHTY_BASH cd=50)
Define(NATURES_SWIFTNESS 132158)
    SpellInfo(NATURES_SWIFTNESS cd=60)
    SpellAddBuff(NATURES_SWIFTNESS NATURES_SWIFTNESS=1)
Define(RENEWAL 108238)
    SpellInfo(RENEWAL cd=120)
Define(TYPHOON 132469)
    SpellInfo(TYPHOON cd=20)
Define(WILD_CHARGE 102401)
    SpellInfo(WILD_CHARGE cd=15)

#Glyphs
Define(GLYPH_OF_SHRED 114234)
Define(GLYPH_OF_SAVAGERY 127540)

# Shared spells
Define(FAERIE_FERAL 770)
    SpellInfo(FAERIE_FERAL duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_FERAL FAERIE_FERAL=1 WEAKENED_ARMOR=1)
Define(FAERIE_SWARM 102355)
    SpellInfo(FAERIE_SWARM duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_SWARM FAERIE_SWARM=1 WEAKENED_ARMOR=1)

# Cat spells
Define(BERSERK_CAT 106951) #cat cd buff
    SpellInfo(BERSERK_CAT duration=15 cd=180)
    SpellAddBuff(BERSERK_CAT BERSERK_CAT=1)
Define(CAT_FORM 768)
    SpellAddBuff(CAT_FORM CAT_FORM=1)
Define(FEROCIOUS_BITE 22568) #cat finish 25-50 energy
    SpellInfo(FEROCIOUS_BITE energy=25 combo=0)
Define(INCARNATION_CAT 102543)
    SpellInfo(INCARNATION_CAT duration=30 cd=180)
Define(MAIM 22570) #cat interrupt
    SpellInfo(MAIM cd=10 energy=35 combo=0)
Define(MANGLE_CAT 33876) #cat bleed+debuff
    SpellInfo(MANGLE_CAT inccounter=ripshreds energy=35 combo=1)
    SpellInfo(MANGLE_CAT critcombo=1 if_spell=PRIMAL_FURY)
Define(RAKE 1822) #cat bleed
    SpellInfo(RAKE combo=1 duration=15 energy=35 tick=3)
    SpellInfo(RAKE critcombo=1 if_spell=PRIMAL_FURY)
    SpellAddTargetDebuff(RAKE RAKE=1)
    SpellDamageBuff(RAKE DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(RAVAGE 6785)
    SpellInfo(RAVAGE inccounter=ripshreds energy=45 combo=1)
    SpellInfo(RAVAGE critcombo=1 if_spell=PRIMAL_FURY)
Define(RAVAGE_BANG 102545)
    SpellInfo(RAVAGE_BANG inccounter=ripshreds energy=0 combo=1)
    SpellInfo(RAVAGE_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(RIP 1079) #cat bleed
    SpellInfo(RIP resetcounter=ripshreds duration=16 energy=30 tick=2 combo=0)
    SpellAddTargetDebuff(RIP RIP=1)
    SpellDamageBuff(RIP DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(SAVAGE_ROAR_OLD 52610)
    SpellInfo(SAVAGE_ROAR_OLD duration=18 combo=0 energy=25)
    SpellAddBuff(SAVAGE_ROAR_OLD SAVAGE_ROAR_OLD=1)
Define(SAVAGE_ROAR_GLYPHED 127538)
    SpellInfo(SAVAGE_ROAR_GLYPHED duration=12 combo=-5 energy=25)
    SpellAddBuff(SAVAGE_ROAR_GLYPHED SAVAGE_ROAR_GLYPHED=1)
    SpellList(SAVAGE_ROAR 52610 127538)
Define(SHRED 5221) #cat behind
    SpellInfo(SHRED inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED critcombo=1 if_spell=PRIMAL_FURY)
Define(SHRED_BANG 114236)
    SpellInfo(SHRED_BANG inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(STAMPEDE 81022)
    SpellAddBuff(STAMPEDE STAMPEDE=1)
Define(SKULL_BASH_CAT 80965) #cat interrupt
    SpellInfo(SKULL_BASH_CAT cd=15 energy=15)
Define(THRASH_CAT 106830)
    SpellInfo(THRASH_CAT duration=15 energy=50 tick=3)
    SpellAddTargetDebuff(THRASH_CAT THRASH_CAT=1 WEAKENED_BLOWS=1)
    SpellDamageBuff(THRASH_CAT DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(TIGERS_FURY 5217) #cat buff
    SpellInfo(TIGERS_FURY duration=6 energy=-60 cd=30)
    SpellAddBuff(TIGERS_FURY TIGERS_FURY=1)

# Bear spells
Define(BEAR_FORM 5487)
    SpellAddBuff(BEAR_FORM BEAR_FORM=1)
Define(BERSERK_BEAR 106952) #cat+bear cd buff
    SpellInfo(BERSERK_BEAR duration=10 cd=180 )
    SpellAddBuff(BERSERK_BEAR BERSERK_BEAR=1)
Define(ENRAGE 5229)
Define(FRENZIED_REGEN 22842)
Define(INCARNATION_BEAR 102558)
    SpellInfo(INCARNATION_BEAR duration=30 cd=180 )
Define(LACERATE 33745)
Define(MANGLE_BEAR 33878)
    SpellInfo(MANGLE_BEAR cd=3 buffnocd=INCARNATION_BEAR buffnocd=BERSERK_BEAR)
Define(MAUL 6807)
Define(MIGHT_OF_URSOC 106922)
Define(SAVAGE_DEFENSE 62606)
Define(SURVIVAL_INSTINCTS 61336)
Define(SWIPE_BEAR 779)
Define(THRASH_BEAR 77758)
Define(TOOTH_AND_CLAW 135286)
    SpellAddBuff(TOOTH_AND_CLAW TOOTH_AND_CLAW=1)
Define(TOOTH_AND_CLAW_DEBUFF 135601)
    SpellAddTargetDebuff(TOOTH_AND_CLAW_DEBUFF TOOTH_AND_CLAW_DEBUFF=1)

###############
## Define Settings ##
###############

AddCheckBox(cooldownsL "Show Left Rotation Boxes" default)
AddCheckBox(cooldownsR "Show Right Cooldown Boxes" default)
AddCheckBox(altpredictive "Alternate predictive box")
AddCheckBox(bearaoe "Bear AOE Rotation")
AddCheckBox(cooldownsRatio "Show Rake and Rip Ratio Boxes" mastery=2)
AddCheckBox(lucioles SpellName(FAERIE_FERAL) default mastery=2)
AddCheckBox(berserk "Cat Berserk" default mastery=2)
AddCheckBox(infront "Frontal attack" mastery=2)
AddCheckBox(predictive "Hide predictive box" mastery=2)
AddCheckBox(nvbounce "Use healing CDs for damage" mastery=2)

################
## Helper Functions ##
################

# Static Variables; Left as functions instead of Defines for added flexibility and consistency in coding (ex: multiple ilvls of trinkets if we can figure that out)
AddFunction ExpiringBuffSafetyMargin { 0.3 }
AddFunction BossArmor { 24835 }
AddFunction WeakenedArmorPercent { 0.04 }
AddFunction TigersFuryMultiplier { 1.15 }
AddFunction RuneMultiplier { 2 } # Not the actual amount like the rest, but given the power of the rune buff the script should still function properly
AddFunction HeartOfTheWildAgiModifier { 1.06 }
AddFunction LeatherSpecAgiModifier { 1.05 }
AddFunction StatsBuffBonus { 0.05 }
AddFunction RakeBaseDamage { 99 }
AddFunction RakeDamagePerAttackPower { 0.3 }
AddFunction RipBaseDamage { 113 }
AddFunction RipDamagePerComboPoint { 320 }
AddFunction RipDamagePerComboPointAttackPower { 0.0484 }
AddFunction ThrashBaseDamage { 4662 }
AddFunction ThrashDamagePerAttackPower { 1.121 }
AddFunction FerociousBiteBaseDamage { 500 }
AddFunction FerociousBiteDamagePerComboPoint { 762 }
AddFunction FerociousBiteDamagePerComboPointAttackPower { 0.196 }
AddFunction FerociousBiteCritChanceBonus { 0.25 }
AddFunction FerociousBiteCritChanceRaw { FerociousBiteCritChanceBonus()+{MeleeCritChance()/100} }
AddFunction FerociousBiteCritChance { if FerociousBiteCritChanceRaw() > 1 1 FerociousBiteCritChanceRaw() }
AddFunction MangleCatBaseDamage { 78 }
AddFunction MangleCatWeaponDamageMultiplier { 5 }
AddFunction CritPerAP { 2519.04 }
AddFunction DancingSteelAttackPower { 3300 }
AddFunction SoulCharmAttackPower
{
   if HasTrinket(96741) 3430 # Heroic TF 2/2 upgrade
   if HasTrinket(96369) 3244 # Heroic 2/2 upgrade
   if HasTrinket(95997) 3038 # Normal TF 2/2 upgrade
   if HasTrinket(94512) 2874 # Normal 2/2 upgrade
   if HasTrinket(95625) 2384 # LFR 2/2 upgrade
}
AddFunction BadJujuAttackPower
{
   if HasTrinket(96781) 18864 # Heroic TF 2/2 upgrade
   if HasTrinket(96409) 17840 # Heroic 2/2 upgrade
   if HasTrinket(96037) 16712 # Normal TF 2/2 upgrade
   if HasTrinket(94523) 15806 # Normal 2/2 upgrade
   if HasTrinket(95665) 13118 # LFR 2/2 upgrade
}
AddFunction ViciousTalismanAttackPower
{
   17600 # 2/2 upgrade
}
AddFunction EnergyForThrash
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction EnergyForRake
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForRip
{
   if BuffExpires(BERSERK_CAT) 30
   15
}
AddFunction EnergyForMangle
{
   if BuffExpires(BERSERK_CAT) 35
   18
}
AddFunction EnergyForFerociousBite
{
   if BuffExpires(BERSERK_CAT) 50
   25
}
AddFunction HasEnergyForRake
{
   Energy() >= EnergyForRake()
}
AddFunction DoNotHaveEnergyForRake
{
   Energy() < EnergyForRake()
}
AddFunction HasEnergyForRip
{
   Energy() >= EnergyForRip()
}
AddFunction DoNotHaveEnergyForRip
{
   Energy() < EnergyForRip()
}
AddFunction HasEnergyForFerociousBite
{
   Energy() >= EnergyForFerociousBite()
}
AddFunction DoNotHaveEnergyForFerociousBite
{
   Energy() < EnergyForFerociousBite()
}
AddFunction HasEnergyForThrash
{
   Energy() >= EnergyForThrash()
}
AddFunction DoNotHaveEnergyForThrash
{
   Energy() < EnergyForThrash()
}
AddFunction TigersFuryCooldown
{
   if SpellCooldown(TIGERS_FURY) >= 0 SpellCooldown(TIGERS_FURY)
   0
}

# Armor Functions
AddFunction ArmorReduction
{
   if target.DebuffPresent(WEAKENED_ARMOR any=1)
   {
      if target.Level(less 1) 0.679
      0.698
   }
   if target.Level(less 1) 0.651
   0.671
}

# Time till energy for abilities functions (must come before Rune functions)
# Moved energy check from functions to main code to fix predictive algorithm bug within ovale
AddFunction TimeTilEnergyForThrash
{
   if { EnergyForThrash() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForThrash() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRake
{
   if { EnergyForRake() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForRake() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRip
{
   if { EnergyForRip() - Energy() } / EnergyRegen() < TigersFuryCooldown()
      { EnergyForRip() - Energy() } / EnergyRegen()
   TigersFuryCooldown()
}

# Ratio Calculation assistnace functions
AddFunction PrimordiusStats # Primordius Stats Buff
{
   {1 + 0.05 * DebuffStacks(136184)} * {1 - 0.1 * DebuffStacks(136185)} # Thick and Fragile bones
}
AddFunction StatsMultiplier
{
   if TalentPoints(HEART_OF_THE_WILD) # Leatherwearer, Heart of the Wild, Mark of the Wild, Primordius Buffs
   {
      LeatherSpecAgiModifier() * HeartOfTheWildAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   }
   LeatherSpecAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
}
AddFunction DancingSteelAttackPowerIncrease
{
   DancingSteelAttackPower()*StatsMultiplier()
}
AddFunction DancingSteelCritChanceIncrease
{
    DancingSteelAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction SoulCharmAttackPowerIncrease
{
   SoulCharmAttackPower()*BuffStacks(BLADES)*StatsMultiplier()
}
AddFunction SoulCharmCritChanceIncrease
{
   SoulCharmAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction BadJujuAttackPowerIncrease
{
   BadJujuAttackPower()*StatsMultiplier()
}
AddFunction BadJujuCritChanceIncrease
{
   BadJujuAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}
AddFunction ViciousTalismanAttackPowerIncrease
{
   ViciousTalismanAttackPower()*StatsMultiplier()
}
AddFunction ViciousTalismanCritChanceIncrease
{
   ViciousTalismanAttackPowerIncrease()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}
}

# Rake functions
AddFunction RakeTickDamage # Switched to raw numbers in place of Damage(RAKE) for 5.3.4+ compatibility
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + AttackPower()*RakeDamagePerAttackPower()} * DamageMultiplier(RAKE) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}
AddFunction LastRakeTickDamage
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {RakeBaseDamage() + target.DebuffAttackPower(RAKE)*RakeDamagePerAttackPower()} * target.DebuffDamageMultiplier(RAKE) * {1+target.DebuffMeleeCritChance(RAKE)/100} * {1+target.DebuffMastery(RAKE)/100}
}
AddFunction RuneRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRakeMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRakeUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffRemains(TIGERS_FURY) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRakeMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRakeUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRakeUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRakeAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRakeUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRakeAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRakeUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRakeUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRakeAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRakeUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRakeUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RAKE)
   {
      if HasEnergyForRake()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRake()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRakeAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRakeUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRakeMultiplier
{
    RuneExpiresRakeMultiplier()*TigersFuryExpiresRakeMultiplier()
}
AddFunction TotalRakeAttackPower
{
   DancingSteelExpiresRakeAttackPower() + SoulCharmExpiresRakeAttackPower() + BadJujuExpiresRakeAttackPower() + ViciousTalismanExpiresRakeAttackPower()
}
AddFunction FutureRakeTickDamage
{
    {RakeBaseDamage() + {AttackPower() - TotalRakeAttackPower()} * RakeDamagePerAttackPower()}
   * DamageMultiplier(RAKE)
   * {1 + {MeleeCritChance() - TotalRakeAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}} / 100}
   * {1 + Mastery() / 100}
   / TotalRakeMultiplier()
}

# Rip functions
AddFunction RipTickDamage  # Switched to raw numbers in place of Damage(RIP) for 5.3.4+ compatibility
{
    {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * AttackPower()}} * ComboPoints()}} * DamageMultiplier(RIP) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * target.DebuffAttackPower(RIP)}} * target.DebuffComboPoints(RIP)}} * target.DebuffDamageMultiplier(RIP) * {1+target.DebuffMeleeCritChance(RIP)/100} * {1 + target.DebuffMastery(RIP)/100}
}
AddFunction RuneRipUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if BuffRemains(ROR_MASTERY) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction RuneExpiresRipMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRipUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRipUsableBeforeExpire
{
   if BuffRemains(TIGERS_FURY) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffPresent(TIGERS_FURY) and BuffRemains(TIGERS_FURY) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction TigersFuryExpiresRipMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRipUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRipUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction DancingSteelExpiresRipAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRipUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRipUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction SoulCharmExpiresRipAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRipUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRipUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction BadJujuExpiresRipAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRipUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRipUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > SpellCooldown(RIP)
   {
      if HasEnergyForRip()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > TimeTilEnergyForRip()+ExpiringBuffSafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRipAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRipUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}
AddFunction TotalRipMultiplier
{
    RuneExpiresRipMultiplier()*TigersFuryExpiresRipMultiplier()
}
AddFunction TotalRipAttackPower
{
   DancingSteelExpiresRipAttackPower() + SoulCharmExpiresRipAttackPower() + BadJujuExpiresRipAttackPower() + ViciousTalismanExpiresRipAttackPower()
}
AddFunction FutureRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * {AttackPower() - TotalRipAttackPower()}}} * ComboPoints()}}
   * DamageMultiplier(RIP)
   * {1 + {MeleeCritChance() - TotalRipAttackPower()/CritPerAP()/{1+0.1*BuffStacks(attack_power_multiplier any=1)}}/100}
   * {1 + Mastery()/100}
   / TotalRipMultiplier()
}
AddFunction RipDamageTillDead
{
    # The damage from Rip that is cast under the current conditions and lasting till target is dead.
    # Multiply the damage per tick with the number of ticks that can fit into the time to die.
    FutureRipTickDamage() * {target.TimeToDie() / 2}
}
AddFunction ExistingRipDamageTillDead
{
    # The damage from Rip that is already on the target and lasting till target is dead.
    if target.DebuffPresent(RIP)
    {
        # Multiply the damage per tick with the number of ticks that can fit into the time to die.
        LastRipTickDamage() * {target.TimeToDie() / 2}
    }
        0
}

# Ratio functions
AddFunction RakeRatio
{
    if TargetDebuffPresent(RAKE) 100 * FutureRakeTickDamage()/LastRakeTickDamage()
    100.0
}
AddFunction RipRatio
{
    if TargetDebuffPresent(RIP) 100 * FutureRipTickDamage()/LastRipTickDamage()
    100.0
}

# Damage ability functions
AddFunction FerociousBiteDamage # Switched to raw numbers in place of Damage(FEROCIOUS_BITE) for 5.3.4+ compatibility
{
   {FerociousBiteBaseDamage() + {FerociousBiteDamagePerComboPoint() + FerociousBiteDamagePerComboPointAttackPower() * AttackPower()} * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE)  * {1+FerociousBiteCritChance()} * 2 * ArmorReduction()
}
AddFunction MangleCatDamage
{
   {MangleCatBaseDamage() + WeaponDamage(MH) * MangleCatWeaponDamageMultiplier()} * DamageMultiplier(MANGLE_CAT) * {1+MeleeCritChance()/100} * ArmorReduction()
}
AddFunction ThrashCatDamage
{
   {ThrashBaseDamage() + AttackPower()*ThrashDamagePerAttackPower()} * DamageMultiplier(THRASH_CAT) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}

# Misc functions
AddFunction FaerieFire
{
    if TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_SWARM)
    Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if ComboPoints(more 0) Spell(SAVAGE_ROAR_OLD)
}
AddFunction UsePotion
{
    #virmens_bite_potion
    if CheckBoxOn(potions) and target.Classification(worldboss) Item(virmens_bite_potion)
}



#############################
## Feral rotation functions (Mastery=2) ##
#############################

AddFunction NotInCombat
{
    unless InCombat() {
        if BuffExpires(str_agi_int 400 any=1) Spell(MARK_OF_THE_WILD)
        if BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and TalentPoints(DREAM_OF_CENARIUS_TALENT) Spell(HEALING_TOUCH)
        unless Stance(3) Spell(CAT_FORM)
        if Glyph(GLYPH_OF_SAVAGERY) and ComboPoints() ==0 {
            if BuffRemains(SAVAGE_ROAR_GLYPHED) <15 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-11.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <9 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-8.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <6 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-5.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <3 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-2.5
            or BuffExpires(SAVAGE_ROAR_GLYPHED) {
                SavageRoar()
            }
        }
        if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
    }
}

AddFunction SpareGcdCooldowns {
    if TalentPoints(FORCE_OF_NATURE_TALENT)
    {
        #treants
        Spell(FORCE_OF_NATURE)
    }
    # Spirit Wolves goes here when symbiosis is supported appropriately.
}

AddFunction SavageRoarOrWeakenedArmorMissing
{
    #savage_roar,if=buff.savage_roar.down
    if BuffExpires(SAVAGE_ROAR) SavageRoar()
   
    #faerie_fire,if=debuff.weakened_armor.stack<3
    if target.DebuffStacks(WEAKENED_ARMOR any=1) <3 and CheckBoxOn(lucioles) FaerieFire()
}

AddFunction RangeCheck
{
   #range check
    unless target.InRange(MANGLE_CAT) Texture(ability_druid_catformattack)
}

AddFunction IncarnationBerserkTigersFuryLogic
{
    #incarnation,if=energy<=35&!buff.omen_of_clarity.react&cooldown.tigers_fury.remains=0&cooldown.berserk.remains=0
    #use_item,name=eternal_blossom_grips,sync=tigers_fury
    #tigers_fury,if=(energy<=35&!buff.omen_of_clarity.react)|buff.king_of_the_jungle.up
    #berserk,if=buff.tigers_fury.up|(target.time_to_die<15&cooldown.tigers_fury.remains>6)
    if {{Energy() <=35 and BuffExpires(CLEARCASTING)} or BuffPresent(INCARNATION_CAT)} and Spell(TIGERS_FURY)
    {
        if CheckBoxOn(berserk) and Spell(BERSERK_CAT)
        {
            if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION)
            if not TalentPoints(INCARNATION_TALENT) or BuffPresent(INCARNATION_CAT) Spell(BERSERK_CAT)
        }
        unless BuffPresent(BERSERK_CAT) Spell(TIGERS_FURY)
    }
    if CheckBoxOn(berserk) and TalentPoints(INCARNATION_TALENT) and BuffPresent(BERSERK_CAT) Spell(INCARNATION_CAT)
}

AddFunction ExecuteRangeRipFerociousBiteLogic # Left one Doc line in here and added a talent check, normally tried to take them out but this one was annoyingly in a bad place so left here for simplicities sake
{
    #ferocious_bite,if=combo_points>=1&dot.rip.ticking&dot.rip.remains<=3&target.health.pct<=25
    if target.HealthPercent() <=25 and ComboPoints() >=1
      and target.DebuffPresent(RIP) and target.DebuffRemains(RIP) <=4
   {
      Spell(FEROCIOUS_BITE)
   }
   
    #thrash_cat,if=target.time_to_die>=6&buff.omen_of_clarity.react&dot.thrash_cat.remains<3
    if target.TimeToDie() >=9 and BuffPresent(CLEARCASTING)
      and target.DebuffRemains(THRASH_CAT) <3
   {
      Spell(THRASH_CAT)
   }
   
    #ferocious_bite,if=(target.time_to_die<=4&combo_points>=5)|(target.time_to_die<=1&combo_points>=3)
    if target.TimeToDie() <=4 and ComboPoints() >=5 Spell(FEROCIOUS_BITE)
    if target.TimeToDie() <=1 and ComboPoints() >=3 Spell(FEROCIOUS_BITE)
   
    if target.HealthPercent() <=25
    {
        #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&target.health.pct<25
        if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0
      {
         SavageRoar()
      }
       
        if ComboPoints() >=5
        {
            #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&target.health.pct<=25
            if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT)
            and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS)
            and BuffRemains(SAVAGE_ROAR) >5
         {
            Spell(NATURES_SWIFTNESS)
         }
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&$(rip_ratio)>=1.15&buff.dream_of_cenarius_damage.up
            # if not HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=115 UsePotion()
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&buff.rune_of_reorigination.up&buff.dream_of_cenarius_damage.up
            # if HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and BuffPresent(ROR_MASTERY) UsePotion()
           
            #virmens_bite_potion,if=target.time_to_die<=40
            # if target.TimeToDie() <=40 UsePotion()
           
            #rip,line_cd=30,if=combo_points>=5&buff.virmens_bite_potion.up&buff.dream_of_cenarius_damage.up&target.health.pct<=25&target.time_to_die>30
            if RipDamageTillDead() > {ExistingRipDamageTillDead() + FerociousBiteDamage()}
         {
            Spell(RIP)
         }
         
            #pool_resource,wait=0.25,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))
            #ferocious_bite,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25
            if target.DebuffPresent(RIP)
            {
                if DoNotHaveEnergyForFerociousBite() SpareGcdCooldowns()
                wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
            }
        }
    }
}

AddFunction DocRipLogic # If any changes are applicable to NonDoc logic, also make changes there!!!
{
   if target.HealthPercent() >25 and ComboPoints() >=5 and RipRatio() >=92
   {
      #natures_swiftness,if=enabled&buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&$(rip_ratio)>=0.92
      if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS)
      {
         Spell(NATURES_SWIFTNESS)
      }
       
      #rip,if=combo_points>=5&$(rip_ratio)>=1.15
      if RipRatio() >= 115
      {
         Spell(RIP)
      }
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<2&buff.dream_of_cenarius_damage.up
   if ComboPoints() >=5 and target.DebuffRemains(RIP) <2
      and BuffPresent(DREAM_OF_CENARIUS_DAMAGE)
   {
      Spell(RIP)
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rip.multiplier<=tick_multiplier
   if ComboPoints() >=5 and target.DebuffRemains(RIP) <6
      and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=100
   {
      Spell(RIP)
   }
   
   #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&dot.rip.remains<3
   if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE)
      and BuffExpires(PREDATORY_SWIFTNESS) and ComboPoints() >=5 and target.DebuffRemains(RIP) <3
   {
      Spell(NATURES_SWIFTNESS)
   }
   
    #rip,if=combo_points>=5&dot.rip.remains<2
    if ComboPoints() >=5 and target.DebuffRemains(RIP) <2
    {
        Spell(RIP)
    }
}

AddFunction NonDocRipLogic # If any changes are applicable to Doc logic, also make changes there!!!
{
   #rip,if=combo_points>=5&$(rip_ratio)>=1.15
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2
   if {target.HealthPercent() >25 and ComboPoints() >=5 and RipRatio() >= 115}
      or {ComboPoints() >=5 and target.DebuffRemains(RIP) <2}
   {
      Spell(RIP)
   }
}

AddFunction SavageRoarRefreshLogic
{
    #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&buff.savage_roar.remains+2>dot.rip.remains
   #savage_roar,if=buff.savage_roar.remains<=6&combo_points>=5&buff.savage_roar.remains+2<=dot.rip.remains
    if {BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0} or {BuffRemains(SAVAGE_ROAR) <=6 and ComboPoints() >=5}
      and {BuffRemains(SAVAGE_ROAR) +2 > target.DebuffRemains(RIP)}
   {
      SavageRoar()
   }
}

AddFunction NonExcuteRangeFerociousBiteLogic
{
    #actions.doc+=/pool_resource,wait=0.1,if=combo_points>=5&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)
    #actions.doc+=/ferocious_bite,if=combo_points>=5&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)&!((buff.savage_roar.remains-6<=energy.time_to_max-1)&buff.savage_roar.remains+2<=$(rip_remains))
    if ComboPoints() >=5 and target.DebuffPresent(RIP) and BuffPresent(SAVAGE_ROAR)
      and not target.DebuffRemains(RIP)-2 <= TimeToMaxEnergy()-1
      and not BuffRemains(SAVAGE_ROAR)-3 <= TimeToMaxEnergy()-1
      and not {BuffRemains(SAVAGE_ROAR)-6 <= TimeToMaxEnergy()-1
      and BuffRemains(SAVAGE_ROAR)+2 <= target.DebuffRemains(RIP)}
      and target.DebuffRemains(RIP) >=5
    {
        if DoNotHaveEnergyForFerociousBite() SpareGcdCooldowns()
        wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
    }
}

AddFunction RakeLogic
{
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=buff.rune_of_reorigination.up&dot.rake.remains<9&(buff.rune_of_reorigination.remains<=1.5)
      if BuffPresent(ROR_MASTERY) and target.DebuffRemains(RAKE) <9
         and BuffRemains(ROR_MASTERY) <=1.5
         and TimeTilEnergyForRake() + ExpiringBuffSafetyMargin() < BuffRemains(ROR_MASTERY)
      {
         Spell(RAKE)
      }
         
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*6 - LastRakeTickDamage()*5 >= MangleCatDamage()
      {
         Spell(RAKE)
      }
         
      #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<3.0
      if {HasEnergyForRake() and target.DebuffRemains(RAKE) < 3}
         or {DoNotHaveEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}
      {
         Spell(RAKE)
      }
   }
   unless target.TimeToDie() - target.DebuffRemains(RAKE) >3
   {
      #rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
      if FutureRakeTickDamage()*{target.TimeToDie()/3+1} - LastRakeTickDamage()*target.TimeToDie()/3 >= MangleCatDamage()
      {
         Spell(RAKE)
      }
   }
}

AddFunction ThrashLogic
{
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&(dot.rip.remains>=4|buff.berserk.up)
   if {HasEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3
      and target.TimeToDie() >=9
      and {target.DebuffRemains(RIP) >=4
         or BuffPresent(BERSERK_CAT)}}
   or {DoNotHaveEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3 + TimeTilEnergyForThrash() and BuffExpires(CLEARCASTING)
      and target.TimeToDie() - TimeTilEnergyForThrash() >=9
      and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
         or BuffPresent(BERSERK_CAT)}}
   {
      if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
      Spell(THRASH_CAT)
   }
}

AddFunction FillerActions {
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&combo_points>=5
    if target.DebuffRemains(THRASH_CAT) <3 and target.TimeToDie() >=9 and ComboPoints() >=5 Spell(THRASH_CAT)
    if TalentPoints(INCARNATION_TALENT)
    {
        #ravage
        if BuffPresent(INCARNATION_CAT) Spell(RAVAGE)
    }
    if not TalentPoints(INCARNATION_TALENT) or BuffExpires(INCARNATION_CAT)
    {
        #actions.filler+=/shred,if=(buff.omen_of_clarity.react|buff.berserk.up|energy.regen>=15)&buff.king_of_the_jungle.down
        if BuffPresent(CLEARCASTING) or BuffPresent(BERSERK_CAT) or EnergyRegen() >=15
        and {not CheckBoxOn(infront)
            or {Glyph(GLYPH_OF_SHRED) and {BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT)}}}
        Spell(SHRED)
        #actions.filler+=/mangle_cat,if=buff.king_of_the_jungle.down
        Spell(MANGLE_CAT)
    }
}

# Feral rotation for talent builds with "Dream of Cenarius".

AddFunction FillerConditionsDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=buff.predatory_swiftness.remains>1
    if BuffRemains(PREDATORY_SWIFTNESS) >1 FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
}

AddFunction MainActionsDoC
{
    #healing_touch,if=buff.predatory_swiftness.up&buff.predatory_swiftness.remains<=1.5&buff.dream_of_cenarius_damage.down
    if BuffPresent(PREDATORY_SWIFTNESS) and BuffRemains(PREDATORY_SWIFTNESS) <=1.5 and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) Spell(HEALING_TOUCH)
   
   SavageRoarOrWeakenedArmorMissing()
   
   #healing_touch,if=buff.predatory_swiftness.up&combo_points>=4&buff.dream_of_cenarius_damage.down
   if BuffPresent(PREDATORY_SWIFTNESS) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and ComboPoints() >=4 Spell(HEALING_TOUCH)
   
   #healing_touch,if=buff.natures_swiftness.up
   if BuffPresent(NATURES_SWIFTNESS) Spell(HEALING_TOUCH)

   RangeCheck()
   
   IncarnationBerserkTigersFuryLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   DocRipLogic()
   
   SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rake.multiplier<=tick_multiplier
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3 and target.DebuffRemains(RAKE) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RakeRatio() >=100 Spell(RAKE)
   
   RakeLogic()

    ThrashLogic()
}

# Feral rotation for talent builds without "Dream of Cenarius".

AddFunction FillerConditionsNonDoC
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {ComboPoints() <5 and target.DebuffRemains(RIP) <3} or {ComboPoints() ==0 and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if SpellCooldown(TIGERS_FURY) <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(SOUL_OF_THE_FOREST_TALENT) and ComboPoints() <5 FillerActions()

}

AddFunction MainActionsNonDoC
{
   SavageRoarOrWeakenedArmorMissing()
   
   RangeCheck()
   
   IncarnationBerserkTigersFuryLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   NonDocRipLogic()
   
    SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   RakeLogic()
   
   ThrashLogic()
}

AddFunction Prediction
{
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsNonDoC()
        }
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) Spell(FRENZIED_REGEN)
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if BuffExpires(HEART_OF_THE_WILD) Texture(spell_holy_blessingofagility)
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

#####################
## Feral icons (Mastery=2) ##
#####################

AddIcon help=Rake size=small mastery=2 checkboxon=cooldownsRatio
{
    RakeRatio()
}

AddIcon help=Rip size=small mastery=2 checkboxon=cooldownsRatio
{
    RipRatio()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL {
    if target.InRange(SKULL_BASH_CAT) Spell(SKULL_BASH_CAT)
    unless target.Classification(worldboss)
    {
        if TalentPoints(MIGHTY_BASH_TALENT) and target.InRange(MIGHTY_BASH) Spell(MIGHTY_BASH)
        if TalentPoints(TYPHOON_TALENT) and target.InRange(SKULL_BASH_CAT) Spell(TYPHOON)
        if ComboPoints() >0 and target.InRange(MAIM) Spell(MAIM)
    }
    Spell(WILD_CHARGE)
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL { # Berserk Icon
    if BuffPresent(TIGERS_FURY) Spell(BERSERK_CAT)
    if 0s before Spell(BERSERK_CAT) Texture(Ability_mount_polarbear_white)
}


# Predictive rotation
AddIcon help=predictive size=small mastery=2 checkboxon=altpredictive {
    Prediction()
}

AddIcon help=extraCD size=small mastery=2 checkboxon=altpredictive {   
    if TalentPoints(HEART_OF_THE_WILD_TALENT) Spell(HEART_OF_THE_WILD)
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) {
        if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
        if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
        if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    }
    if TalentPoints(NATURES_VIGIL_TALENT) Spell(NATURES_VIGIL)
}

# Main rotation
AddIcon help=main mastery=2 {
    NotInCombat()
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditionsDoC()
            SpareGcdCooldowns()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsNonDoC()
            FillerConditionsNonDoC()
            SpareGcdCooldowns()
        }
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CheckBoxOff(bearaoe) BearMain()
            if CheckBoxOn(bearaoe) BearMainAOE()
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CastTime(WRATH) <BuffRemains(HEART_OF_THE_WILD) Spell(WRATH)
            Spell(CAT_FORM)
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

# Predictive rotation
AddIcon help=predictive mastery=2 checkboxoff=predictive {
    Prediction()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if BuffExpires(SAVAGE_ROAR) Texture(ability_druid_skinteeth)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rip
    if TargetDebuffExpires(RIP) Texture(ability_ghoulfrenzy)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if TargetDebuffExpires(RAKE) Texture(ability_druid_disembowel)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR {
    Spell(TIGERS_FURY)
}

################################
## Guardian rotation functions (Mastery=3) ##
################################

AddFunction BearMain {
    if Threat() <100 and target.DebuffPresent(LACERATE) and target.DebuffRemains(LACERATE) <2 Spell(LACERATE)
    if Threat() <100 and BuffPresent(INCARNATION_BEAR) and target.DebuffRemains(THRASH_BEAR) <2 Spell(THRASH_BEAR)
   
    Spell(MANGLE_BEAR)
   
   
    # Debuff maintenance.
    if target.DebuffRemains(WEAKENED_BLOWS 3 any=1) <=3 Spell(THRASH_BEAR)
    if target.DebuffRemains(WEAKENED_ARMOR 3 any=1) <=3 or target.DebuffStacks(WEAKENED_ARMOR any=1) <3
    {
        FaerieFire()
    }
   
    Spell(LACERATE)
    if target.DebuffPresent(THRASH_BEAR 6) FaerieFire()
    Spell(THRASH_BEAR)
}

AddFunction BearMainAOE {
    Spell(MANGLE_BEAR)
    Spell(THRASH_BEAR)
    Spell(SWIPE_BEAR)
}

#######################
## Guardian icons (Mastery=3) ##
#######################

AddIcon help=Rake size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=Rip size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    Spell(BARKSKIN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
    if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(TOOTH_AND_CLAW)
    unless BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(MAUL)
}

# Main rotation
AddIcon help=main mastery=3 {
    if InCombat(no) and BuffRemains(str_agi_int any=1) <400 Spell(MARK_OF_THE_WILD)
    unless Stance(1) Spell(BEAR_FORM)
   
    if CheckBoxOff(bearaoe) BearMain()
    if CheckBoxOn(bearaoe) BearMainAOE()
}

AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}
AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}


Fixed an out of order function.

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sat Jul 20, 2013 2:23 am

ShmooDude wrote:The first runs at about half the CPU utilization of the second showing that its more efficient if you have any sections that repeat to throw them into a function. What I was thinking was if ovale could recognize that the code sections are identical, to just run the comparison once and save the value.


I looked at implementing this originally, but the problem with this approach is that the standard conditions can have parameters, which changes the total function signature. For example, target.Casting() is different from player.Casting() but it's the same base Casting() call, just with different target parameters. It's possible to create a hash of the function name and the entire parameter list and use that hash as a key to a table of cached values and then to use that to auto-optimize the script evaluation. I did take a stab at quickly implementing that; however, the implementation is tricky and rather than spending time on getting that working, I just went with the simpler change for now just so I could release at least this improvement for complex scripts.

Exalted
User avatar
Posts: 1145
Joined: Fri Jun 04, 2010 4:28 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Leafkiller » Sat Jul 20, 2013 4:00 am

@Jeshu,

In the spirit of looking for ways to do less processing here is an idea for you to consider:

Currently, (as I understand it) for each icon, Ovale will do a complete walkthrough of the script calculating the time when every node will be ready. If any nodes have time zero, then the highest priority node that is earliest in the script is displayed to the user. If no nodes have a zero time, then the one that will be ready the soonest will be shown with a cooldown.

Because it is possible to specify different priorities for spells, even when the script comes across a node that has a time of zero, it needs to continue to evaluate the rest of the nodes in the script.

So - if Ovale knew that there are no nodes later in a script with a higher priority (something that is characteristic of the simc scripts) it could stop building the node list anytime it found a node with a time of zero since no future nodes would ever replace that node as the one to be displayed.

This could be determined programmatically, or via a setting by the script writer.

Is my understanding correct, or are there other reasons that require a full scan of the script even when a node with time zero has been found?

Revered
Posts: 430
Joined: Tue Feb 08, 2011 5:51 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sat Jul 20, 2013 11:50 pm

5.3.8.1

Spoiler: show
Code: Select all
# ShmooDude's modified Leafkiller's Feral/Guardian druid script.
# Support/Discussion thread: http://fluiddruid.net/forum/viewtopic.php?f=3&t=857
# 7/20/13 version 5.3.8.1
#   Switched from berserk testing to the new built in EnergyCost(ability) function for determining the energy for abilities.
#   Switched from (EnergyCost - CurrentEnergy) / EnergyRegen to the new built in function TimeToEnergyFor(ability).
#   Slight code reorganization to make it easier to browse.
#   More things in functions for better efficiency.
#   Allowed the user to customize the safety margin around expiring buffs via a list item.
#   Removed the "Use Healing CDs for damage" checkbox as its not currently used.
#   Rake will now compare with ravage instead of mangle if incarnation is up (modified by the difference in energy cost).
#   Added bug catching code for target based rip damage.
#   Added a "Debug Mode" checkbox for testing the target.Debuff data vs the LastSpell data.
# 7/19/13 Version 5.3.7.3


############################
## Define Spells, Buffs, Items, Talents ##
############################

# Shared spells
Define(BARKSKIN 22812)
    SpellInfo(BARKSKIN cd=60)
Define(FERAL_SPIRIT 110807)
   SpellInfo(FERAL_SPIRIT cd=120)
Define(HEALING_TOUCH 5185)
Define(MARK_OF_THE_WILD 1126)
    SpellInfo(MARK_OF_THE_WILD duration=3600)
    SpellAddBuff(MARK_OF_THE_WILD MARK_OF_THE_WILD=1)
Define(SYMBIOSIS 110309)
    SpellAddBuff(SYMBIOSIS SYMBIOSIS=1)
Define(WRATH 5176)

# Shared buffs
Define(DREAM_OF_CENARIUS_DAMAGE 108381)
    SpellInfo(DREAM_OF_CENARIUS_DAMAGE duration=30 )
    SpellAddBuff(DREAM_OF_CENARIUS_DAMAGE DREAM_OF_CENARIUS_DAMAGE=1)
Define(NATURES_VIGIL 124974)
    SpellInfo(NATURES_VIGIL cd=180)
    SpellAddBuff(NATURES_VIGIL NATURES_VIGIL=1)
Define(PREDATORY_SWIFTNESS 69369)
    SpellAddBuff(PREDATORY_SWIFTNESS PREDATORY_SWIFTNESS=1)
Define(PRIMAL_FURY 16961)
Define(TRICKS 57933)
    SpellAddBuff(TRICKS TRICKS=1)
Define(WEAKENED_ARMOR 113746)
    SpellInfo(WEAKENED_ARMOR duration=30)
Define(WEAKENED_BLOWS 115798)
    SpellInfo(WEAKENED_BLOWS duration=30)
Define(CLEARCASTING 135700)

# Trinket and Weapon Enchant buffs
Define(ROR_CRIT 139117)
    SpellInfo(ROR_CRIT duration=10)
Define(ROR_MASTERY 139120)
    SpellInfo(ROR_MASTERY duration=10)
Define(ROR_HASTE 139121)
    SpellInfo(ROR_HASTE duration=10)
    SpellList(ROR ROR_CRIT ROR_MASTERY ROR_HASTE)
Define(DANCING_STEEL 120032)
   SpellInfo(DANCING_STEEL duration=12)
Define(SOUL_CHARM 138756)
   SpellInfo(SOUL_CHARM duration=20)
Define(BLADES 138737)
Define(BAD_JUJU 138939)
   SpellInfo(BAD_JUJU duration=20)
Define(VICIOUS_TALISMAN 138700)
   SpellInfo(VICIOUS_TALISMAN duration=20)

# Shared items
ItemList(ROR_ITEM 94532 95802 96174 96546 96918)
ItemList(SOUL_CHARM_ITEM 96741 96369 95997 94512 95625)
ItemList(BAD_JUJU_ITEM 96781 96409 96037 94523 95665)
ItemList(VICIOUS_TALISMAN_ITEM 94511)

# Talents
Define(NATURES_SWIFTNESS_TALENT 4)
Define(RENEWAL_TALENT 5)
Define(CENARION_WARD_TALENT 6)
Define(FAERIE_SWARM_TALENT 7)
Define(TYPHOON_TALENT 9)
Define(SOUL_OF_THE_FOREST 10)
Define(INCARNATION_TALENT 11)
Define(FORCE_OF_NATURE_TALENT 12)
Define(MIGHTY_BASH_TALENT 15)
Define(HEART_OF_THE_WILD_TALENT 16)
Define(DREAM_OF_CENARIUS_TALENT 17)
Define(NATURES_VIGIL_TALENT 18)

# Talent spells
Define(CENARION_WARD 102351)
    SpellInfo(CENARION_WARD cd=30)
Define(FORCE_OF_NATURE 106737)
    SpellInfo(FORCE_OF_NATURE duration=15 cd=60)
Define(HEART_OF_THE_WILD 108292)
    SpellInfo(HEART_OF_THE_WILD cd=360)
    SpellAddBuff(HEART_OF_THE_WILD HEART_OF_THE_WILD=1)
Define(INCARNATION 106731)
    SpellInfo(INCARNATION cd=180)
Define(MIGHTY_BASH 5211)
    SpellInfo(MIGHTY_BASH cd=50)
Define(NATURES_SWIFTNESS 132158)
    SpellInfo(NATURES_SWIFTNESS cd=60)
    SpellAddBuff(NATURES_SWIFTNESS NATURES_SWIFTNESS=1)
Define(RENEWAL 108238)
    SpellInfo(RENEWAL cd=120)
Define(TYPHOON 132469)
    SpellInfo(TYPHOON cd=20)
Define(WILD_CHARGE 102401)
    SpellInfo(WILD_CHARGE cd=15)

#Glyphs
Define(GLYPH_OF_SHRED 114234)
Define(GLYPH_OF_SAVAGERY 127540)

# Shared spells
Define(FAERIE_FERAL 770)
    SpellInfo(FAERIE_FERAL duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_FERAL FAERIE_FERAL=1 WEAKENED_ARMOR=1)
Define(FAERIE_SWARM 102355)
    SpellInfo(FAERIE_SWARM duration=300 cd=6)
    SpellAddTargetDebuff(FAERIE_SWARM FAERIE_SWARM=1 WEAKENED_ARMOR=1)

# Cat spells
Define(BERSERK_CAT 106951) #cat cd buff
    SpellInfo(BERSERK_CAT duration=15 cd=180)
    SpellAddBuff(BERSERK_CAT BERSERK_CAT=1)
Define(CAT_FORM 768)
    SpellAddBuff(CAT_FORM CAT_FORM=1)
Define(FEROCIOUS_BITE 22568) #cat finish 25-50 energy
    SpellInfo(FEROCIOUS_BITE energy=25 combo=0)
Define(INCARNATION_CAT 102543)
    SpellInfo(INCARNATION_CAT duration=30 cd=180)
Define(MAIM 22570) #cat interrupt
    SpellInfo(MAIM cd=10 energy=35 combo=0)
Define(MANGLE_CAT 33876) #cat bleed+debuff
    SpellInfo(MANGLE_CAT inccounter=ripshreds energy=35 combo=1)
    SpellInfo(MANGLE_CAT critcombo=1 if_spell=PRIMAL_FURY)
Define(RAKE 1822) #cat bleed
    SpellInfo(RAKE combo=1 duration=15 energy=35 tick=3)
    SpellInfo(RAKE critcombo=1 if_spell=PRIMAL_FURY)
    SpellAddTargetDebuff(RAKE RAKE=1)
    SpellDamageBuff(RAKE DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(RAVAGE 6785)
    SpellInfo(RAVAGE inccounter=ripshreds energy=45 combo=1)
    SpellInfo(RAVAGE critcombo=1 if_spell=PRIMAL_FURY)
Define(RAVAGE_BANG 102545)
    SpellInfo(RAVAGE_BANG inccounter=ripshreds energy=0 combo=1)
    SpellInfo(RAVAGE_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(RIP 1079) #cat bleed
    SpellInfo(RIP resetcounter=ripshreds duration=16 energy=30 tick=2 combo=0)
    SpellAddTargetDebuff(RIP RIP=1)
    SpellDamageBuff(RIP DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(SAVAGE_ROAR_OLD 52610)
    SpellInfo(SAVAGE_ROAR_OLD duration=18 combo=0 energy=25)
    SpellAddBuff(SAVAGE_ROAR_OLD SAVAGE_ROAR_OLD=1)
Define(SAVAGE_ROAR_GLYPHED 127538)
    SpellInfo(SAVAGE_ROAR_GLYPHED duration=12 combo=-5 energy=25)
    SpellAddBuff(SAVAGE_ROAR_GLYPHED SAVAGE_ROAR_GLYPHED=1)
    SpellList(SAVAGE_ROAR 52610 127538)
Define(SHRED 5221) #cat behind
    SpellInfo(SHRED inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED critcombo=1 if_spell=PRIMAL_FURY)
Define(SHRED_BANG 114236)
    SpellInfo(SHRED_BANG inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(STAMPEDE 81022)
    SpellAddBuff(STAMPEDE STAMPEDE=1)
Define(SKULL_BASH_CAT 80965) #cat interrupt
    SpellInfo(SKULL_BASH_CAT cd=15 energy=15)
Define(THRASH_CAT 106830)
    SpellInfo(THRASH_CAT duration=15 energy=50 tick=3)
    SpellAddTargetDebuff(THRASH_CAT THRASH_CAT=1 WEAKENED_BLOWS=1)
    SpellDamageBuff(THRASH_CAT DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(TIGERS_FURY 5217) #cat buff
    SpellInfo(TIGERS_FURY duration=6 energy=-60 cd=30)
    SpellAddBuff(TIGERS_FURY TIGERS_FURY=1)

# Bear spells
Define(BEAR_FORM 5487)
    SpellAddBuff(BEAR_FORM BEAR_FORM=1)
Define(BERSERK_BEAR 106952) #cat+bear cd buff
    SpellInfo(BERSERK_BEAR duration=10 cd=180 )
    SpellAddBuff(BERSERK_BEAR BERSERK_BEAR=1)
Define(ENRAGE 5229)
Define(FRENZIED_REGEN 22842)
Define(INCARNATION_BEAR 102558)
    SpellInfo(INCARNATION_BEAR duration=30 cd=180 )
Define(LACERATE 33745)
Define(MANGLE_BEAR 33878)
    SpellInfo(MANGLE_BEAR cd=3 buffnocd=INCARNATION_BEAR buffnocd=BERSERK_BEAR)
Define(MAUL 6807)
Define(MIGHT_OF_URSOC 106922)
Define(SAVAGE_DEFENSE 62606)
Define(SURVIVAL_INSTINCTS 61336)
Define(SWIPE_BEAR 779)
Define(THRASH_BEAR 77758)
Define(TOOTH_AND_CLAW 135286)
    SpellAddBuff(TOOTH_AND_CLAW TOOTH_AND_CLAW=1)
Define(TOOTH_AND_CLAW_DEBUFF 135601)
    SpellAddTargetDebuff(TOOTH_AND_CLAW_DEBUFF TOOTH_AND_CLAW_DEBUFF=1)

###############
## Define Settings ##
###############

AddCheckBox(cooldownsL "Show Left Rotation Boxes" default)
AddCheckBox(cooldownsR "Show Right Cooldown Boxes" default)
AddCheckBox(altpredictive "Alternate predictive box")
AddCheckBox(bearaoe "Bear AOE Rotation")
AddCheckBox(cooldownsRatio "Show Rake and Rip Ratio Boxes" mastery=2)
AddCheckBox(lucioles SpellName(FAERIE_FERAL) default mastery=2)
AddCheckBox(berserk "Cat Berserk" default mastery=2)
AddCheckBox(infront "Frontal attack" mastery=2)
AddCheckBox(predictive "Hide predictive box" mastery=2)
AddCheckBox(zdebugmode "Debug Mode" mastery=2)
# AddCheckBox(nvbounce "Use healing CDs for damage" mastery=2) # Currently unused
AddListItem(expbuffsafetymargin point0 "0.0 seconds")
AddListItem(expbuffsafetymargin point1 "0.1 seconds")
AddListItem(expbuffsafetymargin point2 "0.2 seconds")
AddListItem(expbuffsafetymargin point3 "0.3 seconds" default)
AddListItem(expbuffsafetymargin point4 "0.4 seconds")
AddListItem(expbuffsafetymargin point5 "0.5 seconds")

################
# Static Variables
################
AddFunction HeartOfTheWildAgiModifier { 1.06 }
AddFunction LeatherSpecAgiModifier { 1.05 }
AddFunction StatsBuffBonus { 0.05 }
AddFunction RakeBaseDamage { 99 }
AddFunction RakeDamagePerAttackPower { 0.3 }
AddFunction RipBaseDamage { 113 }
AddFunction RipDamagePerComboPoint { 320 }
AddFunction RipDamagePerComboPointAttackPower { 0.0484 }
AddFunction ThrashBaseDamage { 4662 }
AddFunction ThrashDamagePerAttackPower { 1.121 }
AddFunction FerociousBiteBaseDamage { 500 }
AddFunction FerociousBiteDamagePerComboPoint { 762 }
AddFunction FerociousBiteDamagePerComboPointAttackPower { 0.196 }
AddFunction FerociousBiteCritChanceBonus { 25 }
AddFunction MangleCatBaseDamage { 78 }
AddFunction MangleCatWeaponDamageMultiplier { 5 }
AddFunction RavageBaseDamage { 78 }
AddFunction RavageWeaponDamageMultiplier { 9.5 }
AddFunction RavageCritChanceBonus { 50 }
AddFunction CritPerAttackPower { 2519.04 }
AddFunction ExpiringBuffSafetyMargin
{
   if List(expbuffsafetymargin point0) 0.0
   if List(expbuffsafetymargin point1) 0.1
   if List(expbuffsafetymargin point2) 0.2
   if List(expbuffsafetymargin point3) 0.3
   if List(expbuffsafetymargin point4) 0.4
   if List(expbuffsafetymargin point5) 0.5
   0.3
}

################
# Trinket/Proc values
################
AddFunction TigersFuryMultiplier { 1.15 }
AddFunction RuneMultiplier { 2 } # Not the actual amount like the rest, but given the power of the rune buff the script should still function properly
AddFunction DancingSteelAttackPower { 3300 }
AddFunction SoulCharmAttackPower
{
   if HasTrinket(96741) 3430 # Heroic TF 2/2 upgrade
   if HasTrinket(96369) 3244 # Heroic 2/2 upgrade
   if HasTrinket(95997) 3038 # Normal TF 2/2 upgrade
   if HasTrinket(94512) 2874 # Normal 2/2 upgrade
   if HasTrinket(95625) 2384 # LFR 2/2 upgrade
}
AddFunction BadJujuAttackPower
{
   if HasTrinket(96781) 18864 # Heroic TF 2/2 upgrade
   if HasTrinket(96409) 17840 # Heroic 2/2 upgrade
   if HasTrinket(96037) 16712 # Normal TF 2/2 upgrade
   if HasTrinket(94523) 15806 # Normal 2/2 upgrade
   if HasTrinket(95665) 13118 # LFR 2/2 upgrade
}
AddFunction ViciousTalismanAttackPower
{
   17600 # 2/2 upgrade
}

################
# Energy related functions
################
AddFunction EnergyForThrash { EnergyCost(THRASH_CAT) }
AddFunction EnergyForRake { EnergyCost(RAKE) }
AddFunction EnergyForRip { EnergyCost(RIP) }
AddFunction EnergyForMangle { EnergyCost(MANGLE_CAT) }
AddFunction EnergyForShred { EnergyCost(SHRED) }
AddFunction EnergyForRavage { EnergyCost(RAVAGE) }
AddFunction EnergyForFerociousBite { EnergyCost(FEROCIOUS_BITE)*2 }
AddFunction HasEnergyForRake { Energy() >= EnergyForRake() }
AddFunction HasEnergyForRip { Energy() >= EnergyForRip() }
AddFunction HasEnergyForFerociousBite { Energy() >= EnergyForFerociousBite() }
AddFunction HasEnergyForThrash { Energy() >= EnergyForThrash() }

################
# Combo Point related functions
################
AddFunction MaxComboPoints { ComboPoints() >= 5 }
AddFunction HasAnyComboPoints { ComboPoints() > 0 }
AddFunction NoComboPoints { ComboPoints() == 0 }

################
# Armor Functions
################
AddFunction ArmorReduction
{
   if target.DebuffPresent(WEAKENED_ARMOR any=1)
   {
      if target.Level(less 1) 0.679
      0.698
   }
   if target.Level(less 1) 0.651
   0.671
}

################
# Time till energy for abilities functions (must come before Rune functions)
# Moved energy check from functions to main code to fix predictive algorithm bug within ovale
# Always use an energy check when utilizing these functions or you will have a disappearing icon problem
# Example:
# if HasEnergyForRake() and target.DebuffRemains(RAKE) < 3
#     or not HasEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake()
################
AddFunction TigersFuryCooldown { if SpellCooldown(TIGERS_FURY) >= 0 SpellCooldown(TIGERS_FURY) 0 }
AddFunction TimeTilEnergyForThrash
{
   if TimeToEnergyFor(THRASH_CAT) < TigersFuryCooldown()
      TimeToEnergyFor(THRASH_CAT)
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRake
{
   if TimeToEnergyFor(RAKE) < TigersFuryCooldown()
      TimeToEnergyFor(RAKE)
   TigersFuryCooldown()
}
AddFunction TimeTilEnergyForRip
{
   if TimeToEnergyFor(RIP) < TigersFuryCooldown()
      TimeToEnergyFor(RIP)
   TigersFuryCooldown()
}

################
# Buff Calculation assistnace functions
################
AddFunction AttackPowerToCrit { 1/CritPerAttackPower()/{1+0.1*BuffStacks(attack_power_multiplier any=1)} }
AddFunction PrimordiusStats { {1 + 0.05 * DebuffStacks(136184)} * {1 - 0.1 * DebuffStacks(136185)} } # Thick and Fragile bones
AddFunction StatsMultiplier # Leatherwearer, Heart of the Wild, Mark of the Wild/Blessing of Kings, Primordius Buffs
{
   if TalentPoints(HEART_OF_THE_WILD)
      LeatherSpecAgiModifier() * HeartOfTheWildAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   LeatherSpecAgiModifier() * {1 + StatsBuffBonus() * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
}
AddFunction DancingSteelAttackPowerIncrease { DancingSteelAttackPower()*StatsMultiplier() }
AddFunction SoulCharmAttackPowerIncrease { SoulCharmAttackPower()*BuffStacks(BLADES)*StatsMultiplier() }
AddFunction BadJujuAttackPowerIncrease { BadJujuAttackPower()*StatsMultiplier() }
AddFunction ViciousTalismanAttackPowerIncrease { ViciousTalismanAttackPower()*StatsMultiplier() }

################
# Rake Buff related functions; Checks to ensure you can use a Rake before a buff expires
################
AddFunction RakeCooldownSafetyMargin { SpellCooldown(RAKE)+ExpiringBuffSafetyMargin() }
AddFunction RakeEnergySafetyMargin { TimeTilEnergyForRake()+ExpiringBuffSafetyMargin() }
AddFunction RuneRakeUsableBeforeExpire
{
   if BuffRemains(ROR_MASTERY) > RakeCooldownSafetyMargin()
   {
      if HasEnergyForRake()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > RakeEnergySafetyMargin()
   }
}
AddFunction RuneExpiresRakeMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRakeUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRakeUsableBeforeExpire
{
   if BuffRemains(TIGERS_FURY) > RakeCooldownSafetyMargin()
   {
      if HasEnergyForRake()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffRemains(TIGERS_FURY) > RakeEnergySafetyMargin()
   }
}
AddFunction TigersFuryExpiresRakeMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRakeUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRakeUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > RakeCooldownSafetyMargin()
   {
      if HasEnergyForRake()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > RakeEnergySafetyMargin()
   }
}
AddFunction DancingSteelExpiresRakeAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRakeUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > RakeCooldownSafetyMargin()
   {
      if HasEnergyForRake()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > RakeEnergySafetyMargin()
   }
}
AddFunction SoulCharmExpiresRakeAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRakeUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRakeUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > RakeCooldownSafetyMargin()
   {
      if HasEnergyForRake()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > RakeEnergySafetyMargin()
   }
}
AddFunction BadJujuExpiresRakeAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRakeUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRakeUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > RakeCooldownSafetyMargin()
   {
      if HasEnergyForRake()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > RakeEnergySafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRakeAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRakeUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0
}

################
# Rip Buff related functions; Checks to ensure you can use a Rip before a buff expires
################
AddFunction RipCooldownSafetyMargin { SpellCooldown(RIP)+ExpiringBuffSafetyMargin() }
AddFunction RipEnergySafetyMargin { TimeTilEnergyForRip()+ExpiringBuffSafetyMargin() }
AddFunction RuneRipUsableBeforeExpire
{
   if BuffRemains(ROR_MASTERY) > RipCooldownSafetyMargin()
   {
      if HasEnergyForRip()
         BuffRemains(ROR_MASTERY) > ExpiringBuffSafetyMargin()
      BuffRemains(ROR_MASTERY) > RipEnergySafetyMargin()
   }
}
AddFunction RuneExpiresRipMultiplier
{
    if BuffPresent(ROR_MASTERY)
   {
      if RuneRipUsableBeforeExpire() 1
      RuneMultiplier()
   }
      1
}
AddFunction TigersFuryRipUsableBeforeExpire
{
   if BuffRemains(TIGERS_FURY) > RipCooldownSafetyMargin()
   {
      if HasEnergyForRip()
         BuffRemains(TIGERS_FURY) > ExpiringBuffSafetyMargin()
      BuffPresent(TIGERS_FURY) and BuffRemains(TIGERS_FURY) > RipEnergySafetyMargin()
   }
}
AddFunction TigersFuryExpiresRipMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRipUsableBeforeExpire() 1
      TigersFuryMultiplier()
   }
      1
}
AddFunction DancingSteelRipUsableBeforeExpire
{
   if BuffRemains(DANCING_STEEL any=1) > RipCooldownSafetyMargin()
   {
      if HasEnergyForRip()
         BuffRemains(DANCING_STEEL any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(DANCING_STEEL any=1) > RipEnergySafetyMargin()
   }
}
AddFunction DancingSteelExpiresRipAttackPower
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRipUsableBeforeExpire() 0
      DancingSteelAttackPowerIncrease()
   }
      0
}
AddFunction SoulCharmRipUsableBeforeExpire
{
   if BuffRemains(SOUL_CHARM any=1) > RipCooldownSafetyMargin()
   {
      if HasEnergyForRip()
         BuffRemains(SOUL_CHARM any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(SOUL_CHARM any=1) > RipEnergySafetyMargin()
   }
}
AddFunction SoulCharmExpiresRipAttackPower
{
   if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRipUsableBeforeExpire() 0
      SoulCharmAttackPowerIncrease()
   }
      0
}
AddFunction BadJujuRipUsableBeforeExpire
{
   if BuffRemains(BAD_JUJU any=1) > RipCooldownSafetyMargin()
   {
      if HasEnergyForRip()
         BuffRemains(BAD_JUJU any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(BAD_JUJU any=1) > RipEnergySafetyMargin()
   }
}
AddFunction BadJujuExpiresRipAttackPower
{
   if BuffPresent(BAD_JUJU any=1)
   {
      if BadJujuRipUsableBeforeExpire() 0
      BadJujuAttackPowerIncrease()
   }
      0
}
AddFunction ViciousTalismanRipUsableBeforeExpire
{
   if BuffRemains(VICIOUS_TALISMAN any=1) > RipCooldownSafetyMargin()
   {
      if HasEnergyForRip()
         BuffRemains(VICIOUS_TALISMAN any=1) > ExpiringBuffSafetyMargin()
      BuffRemains(VICIOUS_TALISMAN any=1) > RipEnergySafetyMargin()
   }
}
AddFunction ViciousTalismanExpiresRipAttackPower
{
   if BuffPresent(VICIOUS_TALISMAN any=1)
   {
      if ViciousTalismanRipUsableBeforeExpire() 0
      ViciousTalismanAttackPowerIncrease()
   }
      0

}

################
# Rake Damage functions
################
AddFunction RakeTickDamage # Switched to raw numbers in place of Damage(RAKE) for 5.3.4+ compatibility
{
    {RakeBaseDamage() + AttackPower()*RakeDamagePerAttackPower()} * DamageMultiplier(RAKE) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
}
AddFunction LastRakeTickDamage
{
    {RakeBaseDamage() + target.DebuffAttackPower(RAKE)*RakeDamagePerAttackPower()} * target.DebuffDamageMultiplier(RAKE) * {1+target.DebuffMeleeCritChance(RAKE)/100} * {1+target.DebuffMastery(RAKE)/100}
}
AddFunction TotalRakeMultiplier
{
    RuneExpiresRakeMultiplier()*TigersFuryExpiresRakeMultiplier()
}
AddFunction TotalRakeAttackPower
{
   DancingSteelExpiresRakeAttackPower() + SoulCharmExpiresRakeAttackPower() + BadJujuExpiresRakeAttackPower() + ViciousTalismanExpiresRakeAttackPower()
}
AddFunction FutureRakeTickDamage
{
    {RakeBaseDamage() + {AttackPower() - TotalRakeAttackPower()} * RakeDamagePerAttackPower()}
   * DamageMultiplier(RAKE) / TotalRakeMultiplier()
   * {1 + {MeleeCritChance() - TotalRakeAttackPower()*AttackPowerToCrit()} / 100}
   * {1 + Mastery() / 100}
}
AddFunction RakeRatio
{
    if TargetDebuffPresent(RAKE) 100 * FutureRakeTickDamage()/LastRakeTickDamage()
    100.0
}

################
# Rip Damage functions
################
AddFunction RipTickDamage
{
    {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * AttackPower()}} * ComboPoints()}} * DamageMultiplier(RIP) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRipTickDamage
{
   if target.DebuffAttackPower(RIP) > 0 # catches ovale forgetting target.Debuff values
   {
      if target.DebuffComboPoints(RIP) > 1 # catches when DebuffComboPoints is fixed (broken as of 5.3.8)
         {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * target.DebuffAttackPower(RIP)}} * target.DebuffComboPoints(RIP)}} * target.DebuffDamageMultiplier(RIP) * {1+target.DebuffMeleeCritChance(RIP)/100} * {1 + target.DebuffMastery(RIP)/100}
      {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * target.DebuffAttackPower(RIP)}} * LastComboPoints(RIP)}} * target.DebuffDamageMultiplier(RIP) * {1+target.DebuffMeleeCritChance(RIP)/100} * {1 + target.DebuffMastery(RIP)/100}
   }
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * LastAttackPower(RIP)}} * LastComboPoints(RIP)}} * LastDamageMultiplier(RIP) * {1+LastMeleeCritChance(RIP)/100} * {1 + LastMastery(RIP)/100}
}
AddFunction TotalRipMultiplier
{
    RuneExpiresRipMultiplier()*TigersFuryExpiresRipMultiplier()
}
AddFunction TotalRipAttackPower
{
   DancingSteelExpiresRipAttackPower() + SoulCharmExpiresRipAttackPower() + BadJujuExpiresRipAttackPower() + ViciousTalismanExpiresRipAttackPower()
}
AddFunction FutureRipTickDamage
{
   {RipBaseDamage() + {{RipDamagePerComboPoint() + {RipDamagePerComboPointAttackPower() * {AttackPower() - TotalRipAttackPower()}}} * ComboPoints()}}
   * DamageMultiplier(RIP) / TotalRipMultiplier()
   * {1 + {MeleeCritChance() - TotalRipAttackPower()*AttackPowerToCrit() }/100}
   * {1 + Mastery()/100}
}
AddFunction RipDamageTillDead
{
    # The damage from Rip that is cast under the current conditions and lasting till target is dead.
    # Multiply the damage per tick with the number of ticks that can fit into the time to die.
    FutureRipTickDamage() * {target.TimeToDie() / 2}
}
AddFunction ExistingRipDamageTillDead
{
    # The damage from Rip that is already on the target and lasting till target is dead.
    if target.DebuffPresent(RIP)
    {
        # Multiply the damage per tick with the number of ticks that can fit into the time to die.
        LastRipTickDamage() * {target.TimeToDie() / 2}
    }
        0
}
AddFunction RipRatio
{
    if TargetDebuffPresent(RIP) 100 * FutureRipTickDamage()/LastRipTickDamage()
    100.0
}

################
# Ability damage functions
################
AddFunction FerociousBiteCritChanceRaw { FerociousBiteCritChanceBonus()+MeleeCritChance() }
AddFunction FerociousBiteCritChance { if FerociousBiteCritChanceRaw() > 100 100 FerociousBiteCritChanceRaw() }
AddFunction FerociousBiteDamage # Switched to raw numbers in place of Damage(FEROCIOUS_BITE) for 5.3.4+ compatibility
{
   {FerociousBiteBaseDamage() + {FerociousBiteDamagePerComboPoint() + FerociousBiteDamagePerComboPointAttackPower() * AttackPower()} * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE)  * {1+FerociousBiteCritChance()/100} * 2 * ArmorReduction()
}
AddFunction MangleCatDamage
{
   {{MangleCatBaseDamage() + WeaponDamage(MH)} * MangleCatWeaponDamageMultiplier()} * DamageMultiplier(MANGLE_CAT) * {1+MeleeCritChance()/100} * ArmorReduction()
}
#AddFunction ThrashCatDamage # Currently unused
#{
#   {ThrashBaseDamage() + AttackPower()*ThrashDamagePerAttackPower()} * DamageMultiplier(THRASH_CAT) * {1+MeleeCritChance()/100} * {1+Mastery()/100}
#}
AddFunction ShredDamage
{
   MangleCatDamage()*1.2
}
AddFunction RavageCritChanceRaw { RavageCritChanceBonus()+MeleeCritChance() }
AddFunction RavageCritChance
{
   if target.HealthPercent() >=80
   {
      if RavageCritChanceRaw() > 100 100
   RavageCritChanceRaw()
   }
   MeleeCritChance()
}
AddFunction RavageDamage
{
   {{RavageBaseDamage() + WeaponDamage(MH)} * RavageWeaponDamageMultiplier()} * DamageMultiplier(RAVAGE) * {1+RavageCritChance()/100} * ArmorReduction()
}
AddFunction FillerActionDamagePerEnergyVsRake
{
    if BuffPresent(INCARNATION_CAT)
      RavageDamage() * EnergyForRake() / EnergyForRavage()
   MangleCatDamage()
}

################
# Misc functions
################
AddFunction FaerieFire
{
    if TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_SWARM)
    Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if ComboPoints(more 0) Spell(SAVAGE_ROAR_OLD)
}
AddFunction UsePotion
{
    #virmens_bite_potion
    if CheckBoxOn(potions) and target.Classification(worldboss) Item(virmens_bite_potion)
}

#############################
## Feral rotation functions (Mastery=2) ##
#############################

AddFunction NotInCombat
{
    unless InCombat() {
        if BuffExpires(str_agi_int 400 any=1) Spell(MARK_OF_THE_WILD)
        if BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and TalentPoints(DREAM_OF_CENARIUS_TALENT) Spell(HEALING_TOUCH)
        unless Stance(3) Spell(CAT_FORM)
        if Glyph(GLYPH_OF_SAVAGERY) and NoComboPoints() {
            if BuffRemains(SAVAGE_ROAR_GLYPHED) <15 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-11.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <9 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-8.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <6 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-5.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <3 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-2.5
            or BuffExpires(SAVAGE_ROAR_GLYPHED) {
                SavageRoar()
            }
        }
        if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
    }
}

AddFunction SpareGcdCooldowns {
    if TalentPoints(FORCE_OF_NATURE_TALENT)
    {
        #treants
        Spell(FORCE_OF_NATURE)
    }
    # Spirit Wolves goes here when symbiosis is supported appropriately.
}

AddFunction SavageRoarOrWeakenedArmorMissing
{
    #savage_roar,if=buff.savage_roar.down
    if BuffExpires(SAVAGE_ROAR) SavageRoar()
   
    #faerie_fire,if=debuff.weakened_armor.stack<3
    if target.DebuffStacks(WEAKENED_ARMOR any=1) <3 and CheckBoxOn(lucioles) FaerieFire()
}

AddFunction RangeCheck
{
   #range check
    unless target.InRange(MANGLE_CAT) Texture(ability_druid_catformattack)
}

AddFunction IncarnationBerserkTigersFuryLogic
{
    #incarnation,if=energy<=35&!buff.omen_of_clarity.react&cooldown.tigers_fury.remains=0&cooldown.berserk.remains=0
    #use_item,name=eternal_blossom_grips,sync=tigers_fury
    #tigers_fury,if=(energy<=35&!buff.omen_of_clarity.react)|buff.king_of_the_jungle.up
    #berserk,if=buff.tigers_fury.up|(target.time_to_die<15&cooldown.tigers_fury.remains>6)
    if {{Energy() <=35 and BuffExpires(CLEARCASTING)} or BuffPresent(INCARNATION_CAT)} and Spell(TIGERS_FURY)
    {
        if CheckBoxOn(berserk) and Spell(BERSERK_CAT)
        {
            if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION)
            if not TalentPoints(INCARNATION_TALENT) or BuffPresent(INCARNATION_CAT) Spell(BERSERK_CAT)
        }
        unless BuffPresent(BERSERK_CAT) Spell(TIGERS_FURY)
    }
    if CheckBoxOn(berserk) and TalentPoints(INCARNATION_TALENT) and BuffPresent(BERSERK_CAT) Spell(INCARNATION_CAT)
}

AddFunction ExecuteRangeRipFerociousBiteLogic # Left one Doc line in here and added a talent check, normally tried to take them out but this one was annoyingly in a bad place so left here for simplicities sake
{
    #ferocious_bite,if=combo_points>=1&dot.rip.ticking&dot.rip.remains<=3&target.health.pct<=25
    if target.HealthPercent() <=25 and HasAnyComboPoints()
      and target.DebuffPresent(RIP) and target.DebuffRemains(RIP) <=4 # is 4 instead of 3 because the remaining time on rip can be inaccurate upto 2 seconds
   {
      Spell(FEROCIOUS_BITE)
   }
   
    #thrash_cat,if=target.time_to_die>=6&buff.omen_of_clarity.react&dot.thrash_cat.remains<3
    if target.TimeToDie() >=9 and BuffPresent(CLEARCASTING)
      and target.DebuffRemains(THRASH_CAT) <3
   {
      Spell(THRASH_CAT)
   }
   
    #ferocious_bite,if=(target.time_to_die<=4&combo_points>=5)|(target.time_to_die<=1&combo_points>=3)
    if target.TimeToDie() <=4 and MaxComboPoints() Spell(FEROCIOUS_BITE)
    if target.TimeToDie() <=1 and ComboPoints() >=3 Spell(FEROCIOUS_BITE)
   
    if target.HealthPercent() <=25
    {
        #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&target.health.pct<25
        if BuffRemains(SAVAGE_ROAR) <=3 and HasAnyComboPoints()
      {
         SavageRoar()
      }
       
        if MaxComboPoints()
        {
            #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&target.health.pct<=25
            if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT)
            and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS)
            and BuffRemains(SAVAGE_ROAR) >5
         {
            Spell(NATURES_SWIFTNESS)
         }
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&$(rip_ratio)>=1.15&buff.dream_of_cenarius_damage.up
            # if not HasTrinket(ROR_ITEM) and MaxComboPoints() and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=115 UsePotion()
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&buff.rune_of_reorigination.up&buff.dream_of_cenarius_damage.up
            # if HasTrinket(ROR_ITEM) and MaxComboPoints() and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and BuffPresent(ROR_MASTERY) UsePotion()
           
            #virmens_bite_potion,if=target.time_to_die<=40
            # if target.TimeToDie() <=40 UsePotion()
           
            #rip,if=combo_points>=5&(tick_damage*(1+crit_pct_current)-tick_dmg*(1+crit_pct))*target.time_to_die%2>=action.ferocious_bite.hit_damage*(1+action.ferocious_bite.crit_pct_current)&target.health.pct<=25
            if RipDamageTillDead() > {ExistingRipDamageTillDead() + FerociousBiteDamage()}
         {
            Spell(RIP)
         }
         
            #pool_resource,wait=0.25,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))
            #ferocious_bite,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25
            if target.DebuffPresent(RIP)
            {
                if not HasEnergyForFerociousBite() SpareGcdCooldowns()
                wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
            }
        }
    }
}

AddFunction DocRipLogic ##### If any changes are applicable to NonDoc logic, also make changes there!!!
{
   if target.HealthPercent() >25 and MaxComboPoints() and RipRatio() >=92
   {
      #natures_swiftness,if=enabled&buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&$(rip_ratio)>=0.92
      if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS)
      {
         Spell(NATURES_SWIFTNESS)
      }
       
      #rip,if=combo_points>=5&$(rip_ratio)>=1.15
      if RipRatio() >= 115
      {
         Spell(RIP)
      }
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<2&buff.dream_of_cenarius_damage.up
   if MaxComboPoints() and target.DebuffRemains(RIP) <2
      and BuffPresent(DREAM_OF_CENARIUS_DAMAGE)
   {
      Spell(RIP)
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rip.multiplier<=tick_multiplier
   if MaxComboPoints() and target.DebuffRemains(RIP) <6
      and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=100
   {
      Spell(RIP)
   }
   
   #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&dot.rip.remains<3
   if TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE)
      and BuffExpires(PREDATORY_SWIFTNESS) and MaxComboPoints() and target.DebuffRemains(RIP) <3
   {
      Spell(NATURES_SWIFTNESS)
   }
   
    #rip,if=combo_points>=5&dot.rip.remains<2
    if MaxComboPoints() and target.DebuffRemains(RIP) <2
    {
        Spell(RIP)
    }
} ##### If any changes are applicable to NonDoc logic, also make changes there!!!

AddFunction NonDocRipLogic ##### If any changes are applicable to Doc logic, also make changes there!!!
{
   #rip,if=combo_points>=5&$(rip_ratio)>=1.15
   #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2
   if {target.HealthPercent() >25 and MaxComboPoints() and RipRatio() >= 115}
      or {MaxComboPoints() and target.DebuffRemains(RIP) <2}
   {
      Spell(RIP)
   }
} ##### If any changes are applicable to Doc logic, also make changes there!!!

AddFunction SavageRoarRefreshLogic
{
    #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&buff.savage_roar.remains+2>dot.rip.remains
   #savage_roar,if=buff.savage_roar.remains<=6&combo_points>=5&buff.savage_roar.remains+2<=dot.rip.remains
    if {BuffRemains(SAVAGE_ROAR) <=3 and HasAnyComboPoints()} or {BuffRemains(SAVAGE_ROAR) <=6 and MaxComboPoints()}
      and {BuffRemains(SAVAGE_ROAR) +2 > target.DebuffRemains(RIP)}
   {
      SavageRoar()
   }
}

AddFunction NonExcuteRangeFerociousBiteLogic
{
    #actions.doc+=/pool_resource,wait=0.1,if=combo_points>=5&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)
    #actions.doc+=/ferocious_bite,if=combo_points>=5&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)&!((buff.savage_roar.remains-6<=energy.time_to_max-1)&buff.savage_roar.remains+2<=$(rip_remains))
    if MaxComboPoints() and target.DebuffPresent(RIP) and BuffPresent(SAVAGE_ROAR)
      and not target.DebuffRemains(RIP)-2 <= TimeToMaxEnergy()-1
      and not BuffRemains(SAVAGE_ROAR)-3 <= TimeToMaxEnergy()-1
      and not {BuffRemains(SAVAGE_ROAR)-6 <= TimeToMaxEnergy()-1
      and BuffRemains(SAVAGE_ROAR)+2 <= target.DebuffRemains(RIP)}
      and target.DebuffRemains(RIP) >=5
    {
        if not HasEnergyForFerociousBite() SpareGcdCooldowns()
        wait if HasEnergyForFerociousBite() Spell(FEROCIOUS_BITE)
    }
}

AddFunction RakeLogic
{
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=buff.rune_of_reorigination.up&dot.rake.remains<9&(buff.rune_of_reorigination.remains<=1.5)
      if BuffPresent(ROR_MASTERY) and target.DebuffRemains(RAKE) <9
         and BuffRemains(ROR_MASTERY) <=1.5
         and RakeEnergySafetyMargin() < BuffRemains(ROR_MASTERY)
      {
         Spell(RAKE)
      }
         
      #rake,if=(action.rake.tick_damage*(1+action.rake.crit_pct_current)*6-dot.rake.tick_dmg*(1+dot.rake.crit_pct)*5)>action.mangle_cat.hit_damage*(1+action.mangle_cat.crit_pct_current)&buff.king_of_the_jungle.down&target.time_to_die-remains>3
      #rake,if=(action.rake.tick_damage*(1+action.rake.crit_pct_current)*6-dot.rake.tick_dmg*(1+dot.rake.crit_pct)*5)>action.ravage.hit_damage*(1+action.ravage.crit_pct_current)*35%45&buff.king_of_the_jungle.up&target.time_to_die-remains>3
      if FutureRakeTickDamage()*6 - LastRakeTickDamage()*5 >= FillerActionDamagePerEnergyVsRake()
      {
         Spell(RAKE)
      }
         
      #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<3.0
      if {HasEnergyForRake() and target.DebuffRemains(RAKE) < 3}
         or {not HasEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}
      {
         Spell(RAKE)
      }
   }
   unless target.TimeToDie() - target.DebuffRemains(RAKE) >3
   {
      #rake,if=(action.rake.tick_damage*(1+action.rake.crit_pct_current)*(remains%3+1)-dot.rake.tick_dmg*(1+dot.rake.crit_pct)*remains%3)>(1+action.mangle_cat.crit_pct_current)*(1+action.mangle_cat.crit_pct_current)&buff.king_of_the_jungle.down&target.time_to_die-remains<=3
      #rake,if=(action.rake.tick_damage*(1+action.rake.crit_pct_current)*(remains%3+1)-dot.rake.tick_dmg*(1+dot.rake.crit_pct)*remains%3)>action.ravage.hit_damage*(1+action.ravage.crit_pct_current)*35%45&buff.king_of_the_jungle.up&target.time_to_die-remains<=3
      if FutureRakeTickDamage()*{target.TimeToDie()/3+1} - LastRakeTickDamage()*target.TimeToDie()/3 >= FillerActionDamagePerEnergyVsRake()
      {
         Spell(RAKE)
      }
   }
}

AddFunction ThrashLogic
{
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&(dot.rip.remains>=4|buff.berserk.up)
   if {HasEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3
      and target.TimeToDie() >=9
      and {target.DebuffRemains(RIP) >=4
         or BuffPresent(BERSERK_CAT)}}
   or {not HasEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3 + TimeTilEnergyForThrash() and BuffExpires(CLEARCASTING)
      and target.TimeToDie() - TimeTilEnergyForThrash() >=9
      and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
         or BuffPresent(BERSERK_CAT)}}
   {
      if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
      Spell(THRASH_CAT)
   }
}

AddFunction FillerActions
{
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&combo_points>=5
    if target.DebuffRemains(THRASH_CAT) <3 and target.TimeToDie() >=9 and MaxComboPoints() Spell(THRASH_CAT)
    if TalentPoints(INCARNATION_TALENT)
    {
        #ravage
        if BuffPresent(INCARNATION_CAT) Spell(RAVAGE)
    }
    if not TalentPoints(INCARNATION_TALENT) or BuffExpires(INCARNATION_CAT)
    {
        #actions.filler+=/shred,if=(buff.omen_of_clarity.react|buff.berserk.up|energy.regen>=15)&buff.king_of_the_jungle.down
        if BuffPresent(CLEARCASTING) or BuffPresent(BERSERK_CAT) or EnergyRegen() >=15
        and {not CheckBoxOn(infront)
            or {Glyph(GLYPH_OF_SHRED) and {BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT)}}}
        Spell(SHRED)
        #actions.filler+=/mangle_cat,if=buff.king_of_the_jungle.down
        Spell(MANGLE_CAT)
    }
}

# Feral rotation for talent builds with "Dream of Cenarius".

AddFunction MainActionsDoC
{
    #healing_touch,if=buff.predatory_swiftness.up&buff.predatory_swiftness.remains<=1.5&buff.dream_of_cenarius_damage.down
    if BuffPresent(PREDATORY_SWIFTNESS) and BuffRemains(PREDATORY_SWIFTNESS) <=1.5 and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) Spell(HEALING_TOUCH)
   
   SavageRoarOrWeakenedArmorMissing()
   
   #healing_touch,if=buff.predatory_swiftness.up&combo_points>=4&buff.dream_of_cenarius_damage.down
   if BuffPresent(PREDATORY_SWIFTNESS) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and ComboPoints() >=4 Spell(HEALING_TOUCH)
   
   #healing_touch,if=buff.natures_swiftness.up
   if BuffPresent(NATURES_SWIFTNESS) Spell(HEALING_TOUCH)

   RangeCheck()
   
   IncarnationBerserkTigersFuryLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   DocRipLogic()
   
   SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rake.multiplier<=tick_multiplier
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3 and target.DebuffRemains(RAKE) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RakeRatio() >=100 Spell(RAKE)
   
   RakeLogic()

    ThrashLogic()
   
   #run_action_list,name=filler,if=buff.predatory_swiftness.remains>1
    if BuffRemains(PREDATORY_SWIFTNESS) >1 FillerActions()
}

# Feral rotation for talent builds without "Dream of Cenarius".

AddFunction FillerConditions
{
    #run_action_list,name=filler,if=buff.omen_of_clarity.react
    if BuffPresent(CLEARCASTING) FillerActions()
    #run_action_list,name=filler,if=(combo_points<5&dot.rip.remains<3)|(combo_points=0&buff.savage_roar.remains<2)
    if {not MaxComboPoints() and target.DebuffRemains(RIP) <3} or {NoComboPoints() and BuffRemains(SAVAGE_ROAR) <2} FillerActions()
    #run_action_list,name=filler,if=target.time_to_die<=8.5
    if target.TimeToDie() <=8.5 FillerActions()
    #run_action_list,name=filler,if=buff.tigers_fury.up|buff.berserk.up
    if BuffPresent(TIGERS_FURY) or BuffPresent(BERSERK_CAT) FillerActions()
    #run_action_list,name=filler,if=cooldown.tigers_fury.remains<=3
    if TigersFuryCooldown() <=3 FillerActions()
    #run_action_list,name=filler,if=energy.time_to_max<=1
    if TimeToMaxEnergy() <=1 FillerActions()
}

AddFunction MainActionsNonDoC
{
   SavageRoarOrWeakenedArmorMissing()
   
   RangeCheck()
   
   IncarnationBerserkTigersFuryLogic()
   
   #Also includes Clearcasting Thrash and end of fight Ferocious Bite
   ExecuteRangeRipFerociousBiteLogic()
   
   NonDocRipLogic()
   
    SavageRoarRefreshLogic()
   
   NonExcuteRangeFerociousBiteLogic()
   
   RakeLogic()
   
   ThrashLogic()
   
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(SOUL_OF_THE_FOREST_TALENT) and not MaxComboPoints() FillerActions()
}

AddFunction Prediction
{
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsNonDoC()
        }
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) Spell(FRENZIED_REGEN)
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if BuffExpires(HEART_OF_THE_WILD) Texture(spell_holy_blessingofagility)
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

#####################
## Feral icons (Mastery=2) ##
#####################

AddIcon help=Rake size=small mastery=2 checkboxon=cooldownsRatio
{
    RakeRatio()
}

AddIcon help=Rip size=small mastery=2 checkboxon=cooldownsRatio
{
    RipRatio()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL {
    if target.InRange(SKULL_BASH_CAT) Spell(SKULL_BASH_CAT)
    unless target.Classification(worldboss)
    {
        if TalentPoints(MIGHTY_BASH_TALENT) and target.InRange(MIGHTY_BASH) Spell(MIGHTY_BASH)
        if TalentPoints(TYPHOON_TALENT) and target.InRange(SKULL_BASH_CAT) Spell(TYPHOON)
        if HasAnyComboPoints() and target.InRange(MAIM) Spell(MAIM)
    }
    Spell(WILD_CHARGE)
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsL { # Berserk Icon
    if BuffPresent(TIGERS_FURY) Spell(BERSERK_CAT)
    if 0s before Spell(BERSERK_CAT) Texture(Ability_mount_polarbear_white)
}


# Predictive rotation
AddIcon help=predictive size=small mastery=2 checkboxon=altpredictive {
    Prediction()
}

AddIcon help=extraCD size=small mastery=2 checkboxon=altpredictive {   
    if TalentPoints(HEART_OF_THE_WILD_TALENT) Spell(HEART_OF_THE_WILD)
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) {
        if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
        if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
        if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    }
    if TalentPoints(NATURES_VIGIL_TALENT) Spell(NATURES_VIGIL)
}

# Main rotation
AddIcon help=main mastery=2 {
    NotInCombat()
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditions()
            SpareGcdCooldowns()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsNonDoC()
            FillerConditions()
            SpareGcdCooldowns()
        }
    }
    if Stance(1) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CheckBoxOff(bearaoe) BearMain()
            if CheckBoxOn(bearaoe) BearMainAOE()
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(0) {
        if BuffPresent(HEART_OF_THE_WILD) {
            if CastTime(WRATH) <BuffRemains(HEART_OF_THE_WILD) Spell(WRATH)
            Spell(CAT_FORM)
        }
        unless BuffPresent(HEART_OF_THE_WILD) Spell(CAT_FORM)
    }
    if Stance(4) or Stance(2) Spell(CAT_FORM)
}

# Predictive rotation
AddIcon help=predictive mastery=2 checkboxoff=predictive {
    Prediction()
}

AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if BuffExpires(SAVAGE_ROAR) Texture(ability_druid_skinteeth)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rip
    if TargetDebuffExpires(RIP) Texture(ability_ghoulfrenzy)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR { # Rake
    if TargetDebuffExpires(RAKE) Texture(ability_druid_disembowel)
}
AddIcon help=cd size=small mastery=2 checkboxon=cooldownsR {
    Spell(TIGERS_FURY)
}

################################
## Guardian rotation functions (Mastery=3) ##
################################

AddFunction BearMain {
    if Threat() <100 and target.DebuffPresent(LACERATE) and target.DebuffRemains(LACERATE) <2 Spell(LACERATE)
    if Threat() <100 and BuffPresent(INCARNATION_BEAR) and target.DebuffRemains(THRASH_BEAR) <2 Spell(THRASH_BEAR)
   
    Spell(MANGLE_BEAR)
   
   
    # Debuff maintenance.
    if target.DebuffRemains(WEAKENED_BLOWS 3 any=1) <=3 Spell(THRASH_BEAR)
    if target.DebuffRemains(WEAKENED_ARMOR 3 any=1) <=3 or target.DebuffStacks(WEAKENED_ARMOR any=1) <3
    {
        FaerieFire()
    }
   
    Spell(LACERATE)
    if target.DebuffPresent(THRASH_BEAR 6) FaerieFire()
    Spell(THRASH_BEAR)
}

AddFunction BearMainAOE {
    Spell(MANGLE_BEAR)
    Spell(THRASH_BEAR)
    Spell(SWIPE_BEAR)
}

#######################
## Guardian icons (Mastery=3) ##
#######################

AddIcon help=Rake size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=Rip size=small mastery=3 checkboxon=cooldownsRatio
{
    # Offset the guardian icons if the user has bleed ratios enabled
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    Spell(BARKSKIN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsL {
    if TalentPoints(NATURES_SWIFTNESS_TALENT) Spell(NATURES_SWIFTNESS)
    if TalentPoints(RENEWAL_TALENT) Spell(RENEWAL)
    if TalentPoints(CENARION_WARD_TALENT) Spell(CENARION_WARD)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon mastery=3 size=small checkboxon=altpredictive checkboxoff=cooldownsL {
    if BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(TOOTH_AND_CLAW)
    unless BuffPresent(TOOTH_AND_CLAW) and target.DebuffExpires(TOOTH_AND_CLAW_DEBUFF) Spell(MAUL)
}

# Main rotation
AddIcon help=main mastery=3 {
    if InCombat(no) and BuffRemains(str_agi_int any=1) <400 Spell(MARK_OF_THE_WILD)
    unless Stance(1) Spell(BEAR_FORM)
   
    if CheckBoxOff(bearaoe) BearMain()
    if CheckBoxOn(bearaoe) BearMainAOE()
}

AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}
AddIcon help=defense mastery=3 checkboxoff=altpredictive {
    if Rage(less 11) Spell(ENRAGE useable=1)
    Spell(SAVAGE_DEFENSE usable=1)
    Spell(FRENZIED_REGEN)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(SURVIVAL_INSTINCTS)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(MIGHT_OF_URSOC)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    if TalentPoints(INCARNATION_TALENT) Spell(INCARNATION_BEAR)
    if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
}

AddIcon help=cd size=small mastery=3 checkboxon=cooldownsR {
    Spell(BERSERK_BEAR)
}

#######################
## Debug Icons
#######################
AddIcon size=small checkboxon=zdebugmode { target.DebuffAttackPower(RIP) }
AddIcon size=small checkboxon=zdebugmode { LastAttackPower(RIP) }
AddIcon size=small checkboxon=zdebugmode { target.DebuffMeleeCritChance(RIP) }
AddIcon size=small checkboxon=zdebugmode { LastMeleeCritChance(RIP) }
AddIcon size=small checkboxon=zdebugmode { target.DebuffDamageMultiplier(RIP) }
AddIcon size=small checkboxon=zdebugmode { LastDamageMultiplier(RIP) }
AddIcon size=small checkboxon=zdebugmode { target.DebuffComboPoints(RIP) }
AddIcon size=small checkboxon=zdebugmode { LastComboPoints(RIP) }
AddIcon size=small checkboxon=zdebugmode { target.DebuffMastery(RIP) }
AddIcon size=small checkboxon=zdebugmode { LastMastery(RIP) }


- Switched from berserk testing to the now built in EnergyCost(ability) function for determining the energy for abilities.
- Switched from (EnergyCost - CurrentEnergy) / EnergyRegen to the new built in function TimeToEnergyFor(ability)
- Slight code reorganization to make it easier to browse.
- More things in functions for better efficiency (though realistically its pretty close to as efficient as it can get without changing the logic).
- Allowed the user to customize the safety margin around expiring buffs via a list item.
- Removed the "Use Healing CDs for damage" checkbox as its not currently used.
- Rake will now compare with ravage instead of mangle if incarnation is up (modified by the difference in energy cost). Small DPS up for incarnation builds.
- Added bug catching code for target based rip damage. It will try to use target based data but if that data is invalid it will revert back to the old last spell functions (which are working fine). This ensures accuracy on single target fights, might be slightly inaccurate if you're multi-ripping on something like council but still no worse than the old method which always used your last cast's data.
- Added a "Debug Mode" checkbox for testing the target.Debuff data vs the LastSpell data when Jeshu makes another update to see if its working (should always match on a single target fight). Wouldn't bother with this unless you wanna help with the testing next version.
- Fully reconsiled with simcraft to be DPS neutral or DPS gain.

Next (and probably last till next patch) I think I want to add an aoe rotation. I recently found that you can set a keybind to manipulate checkboxes in ovale so I figured an aoe rotation could be implemented pretty easily with the checkbox/keybind to allow you to swap mid fight.

@Jeshu
Would it be possible to have access to sliders? If its something that's easy to add, that'd be a better option than the list box for what I'm using it for, if not that's fine too. Alternatively, is there a way to add a label/description to a list box? Right now my list box just says "0.X seconds" which doesn't particularly tell the user what its for but I haven't found a way to label it aside from maybe putting something short as the top list item. Access to a tooltip style description would be the best as if possible I'd like to give a detailed explanation of what its for (so there's no confusion, though probably most people reading this thread know what its for).

Also, how would I go about adding it as a separate script to the Nernian's addon?

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sun Jul 21, 2013 3:02 pm

ShmooDude wrote:- Added bug catching code for target based rip damage. It will try to use target based data but if that data is invalid it will revert back to the old last spell functions (which are working fine). This ensures accuracy on single target fights, might be slightly inaccurate if you're multi-ripping on something like council but still no worse than the old method which always used your last cast's data.

I should have something to fix this issue in the next few days. Just needs a lot of testing on my end to check for memory leaks.

ShmooDude wrote:@Jeshu
Would it be possible to have access to sliders? If its something that's easy to add, that'd be a better option than the list box for what I'm using it for, if not that's fine too. Alternatively, is there a way to add a label/description to a list box? Right now my list box just says "0.X seconds" which doesn't particularly tell the user what its for but I haven't found a way to label it aside from maybe putting something short as the top list item. Access to a tooltip style description would be the best as if possible I'd like to give a detailed explanation of what its for (so there's no confusion, though probably most people reading this thread know what its for).

A list box just uses the text you put there, so you can put a short description there for now. I can add a tooltip description, which shouldn't be too difficult. Just submit an enhancement ticket for it so I don't forget. I'm old so I'm forgetful :-P

ShmooDude wrote:Also, how would I go about adding it as a separate script to the Nernian's addon?

If you'd like to add it, it's as simple as just letting me know. If you're familiar with using GitHub, that's the simplest way for you to maintain it and letting me easily pull in changes (this is how @aggixx does it). If not, then just submit a ticket for that addon with a script update and I'll update it manually. For now, I can put this latest version of your script verbatim into the addon so it'll show up on GitHub if you want to play around with maintaining it there.

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sun Jul 21, 2013 3:37 pm

Leafkiller wrote:Currently, (as I understand it) for each icon, Ovale will do a complete walkthrough of the script calculating the time when every node will be ready. If any nodes have time zero, then the highest priority node that is earliest in the script is displayed to the user. If no nodes have a zero time, then the one that will be ready the soonest will be shown with a cooldown.

Because it is possible to specify different priorities for spells, even when the script comes across a node that has a time of zero, it needs to continue to evaluate the rest of the nodes in the script.

So - if Ovale knew that there are no nodes later in a script with a higher priority (something that is characteristic of the simc scripts) it could stop building the node list anytime it found a node with a time of zero since no future nodes would ever replace that node as the one to be displayed.

This is basically right. All nodes are represent by time intervals. Think of them as mathematical sets {t: start < t < end}. Every node evaluates to a time interval, and once the entire script is seen, then Ovale picks the highest priority node whose time interval overlaps "now", or else picks the node with the lowest start time. There's some fudge factor there with priorities where if a node is available now, but there's a higher priority node that's available a short time in the future, then Ovale will pick the higher priority node.

Your idea has merit, and it's easy to check programatically -- I could keep track of the maximum priority found in a script when compiling the script and later during the execution while keeping track of the best node found so far, if the priority is the same as the maximum priority, then we don't need to keep looking.

As an aside, I don't think priorities work well for classes using cast-time spells, but it might be something worth looking into classes for instant-cast spells such as for melee classes. The way the engine works, it'll pick a higher priority node if it occurs less than 0.75 of a GCD ahead of a node that's available now. This might be another way to express "use these CPs to refresh Rip", although the way it's currently done meshes better with cross-translation to a SimC action list.

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sun Jul 21, 2013 4:41 pm

Jeshu wrote:
ShmooDude wrote:Also, how would I go about adding it as a separate script to the Nernian's addon?

If you'd like to add it, it's as simple as just letting me know. If you're familiar with using GitHub, that's the simplest way for you to maintain it and letting me easily pull in changes (this is how @aggixx does it). If not, then just submit a ticket for that addon with a script update and I'll update it manually. For now, I can put this latest version of your script verbatim into the addon so it'll show up on GitHub if you want to play around with maintaining it there.

I just went ahead and released a new version of Nerien's Ovale Scripts with your script in it.

Revered
Posts: 217
Joined: Tue Dec 14, 2010 5:34 pm

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sun Jul 21, 2013 4:47 pm

The Curse.com packager seems to not be working quite right today. I'll try again later today.

PreviousNext

Return to Kitty DPS

Who is online

Users browsing this forum: Google Feedfetcher, RareBeast, Yahoo [Bot] and 12 guests