Register

Leafkiller's MoP Feral/Guardian Ovale Script

Face-rippin fun.

Moderator: Forum Administrators

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Wed Jul 24, 2013 10:45 pm

Wellwow wrote:On my run tonight, on target swapping (in DoC spec) like on horridon and council, it was telling me to FF even though it was on CD. Version 5.3.8.3. Yep, confirmed on target dummies. SR, FF one dummy, target second dummy, it tells you to FF.


Yeah, doesn't currently have a cooldown check. I'll add one later

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Jul 25, 2013 4:29 pm

After trying to apply a fix, there's actually nothing I can do on my end. Ovale hasn't been updated to properly support spells that overwrite other spells. If you are NOT talented with Faerie Swarm, it will work properly. Its Faerie Swarm that's the problem (because the Faerie Swarm spell ID never shows up in the spell book, ovale thinks that you don't have the spell and thus has no valid cooldown data for it).

Posts: 12
Joined: Tue May 28, 2013 9:13 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Wellwow » Thu Jul 25, 2013 7:32 pm

Well, that's odd. The behavior just started and the Leafkiller script doesn't do it.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Jul 25, 2013 10:10 pm

Wellwow wrote:Well, that's odd. The behavior just started and the Leafkiller script doesn't do it.


Ah, ok. With that new tidbit I actually can fix it. While the SpellCooldown() function doesn't work, ovale will innately account for the spell cooldown of the spell itself and not let it be called to use until its off cooldown. As part of my optimization, I removed most of the if/unless logic so it wouldn't have to test things twice. However, since ovale returns "everything" as it relates to spells, when I removed the "isn't speced into Faerie Swarm" check, it would then return faerie fire, which as far as the game is concerned is still a valid call for Faerie Swarm except that a lot of the internal API calls should now be pointing to Faerie Swarm and not Faerie Fire. This would make it return the cooldown for Faerie Fire which was only the GCD since its a separate spell and doesn't share a cooldown with Faerie Swarm.

With that in mind, I've restored that and the savage roar (though I don't think this one was causing problems, though reverting it just the same) to both use if/unless logic to ensure no improper fall throughs.

5.3.8.4 (here if you want it now, will be pushed to Nernian's soon)

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/25/13 version 5.3.8.4
#   Fixed Faerie Swarm asking for Faerie Fire's cooldown data
#   Applied same fix to Savage Roar
# 7/23/13 version 5.3.8.3
#   Fixed Rake ratios
#   Fixed double tanking icons
# 7/23/13 version 5.3.8.2
#   Changed Rake logic back to strict damage and ratio based.
#   Fixed Non-doc predictive box
# 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)
    unless TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if Glyph(GLYPH_OF_SAVAGERY no) and 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)*2&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
{
    #rake,if=action.rake.tick_damage>action.mangle_cat.hit_damage&$(rake_ratio)>=0.99&buff.king_of_the_jungle.down
    #rake,if=action.rake.tick_damage*(1+action.rake.crit_pct_current)>action.ravage.hit_damage*(1+action.ravage.crit_pct_current)&$(rake_ratio)>=0.99&buff.king_of_the_jungle.up
   if FutureRakeTickDamage() >= FillerActionDamagePerEnergyVsRake() and RakeRatio() >= 99
   {
      Spell(RAKE)
   }
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=target.time_to_die-dot.rake.remains>3&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=target.time_to_die-dot.rake.remains>3&($(rake_ratio)>1.12|dot.rake.remains<3)
      if {HasEnergyForRake() and target.DebuffRemains(RAKE) < 3}
         or {not HasEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}
         or RakeRatio() > 112
      {
         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()
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(HEART_OF_THE_WILD_TALENT) and TalentPoints(SOUL_OF_THE_FOREST_TALENT) and not MaxComboPoints() 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 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)
}

#######################
## 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) }


# Fixed Faerie Swarm asking for Faerie Fire's cooldown data
# Applied same fix to Savage Roar

Posts: 12
Joined: Tue May 28, 2013 9:13 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Wellwow » Fri Jul 26, 2013 12:14 am

Thanks once again for prompt attention and quick turnarounds! It is amazing to me, really.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sat Jul 27, 2013 4:17 pm

ShmooDude wrote:After trying to apply a fix, there's actually nothing I can do on my end. Ovale hasn't been updated to properly support spells that overwrite other spells. If you are NOT talented with Faerie Swarm, it will work properly. Its Faerie Swarm that's the problem (because the Faerie Swarm spell ID never shows up in the spell book, ovale thinks that you don't have the spell and thus has no valid cooldown data for it).

There's not too much that Ovale can actually do, unfortunately. It gets data through the API, which is basically what a person can see in the spellbook. I had added a SpellKnown condition for ret pallies though, that might help with what you're doing.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sat Jul 27, 2013 7:28 pm

Jeshu wrote:
ShmooDude wrote:After trying to apply a fix, there's actually nothing I can do on my end. Ovale hasn't been updated to properly support spells that overwrite other spells. If you are NOT talented with Faerie Swarm, it will work properly. Its Faerie Swarm that's the problem (because the Faerie Swarm spell ID never shows up in the spell book, ovale thinks that you don't have the spell and thus has no valid cooldown data for it).

There's not too much that Ovale can actually do, unfortunately. It gets data through the API, which is basically what a person can see in the spellbook. I had added a SpellKnown condition for ret pallies though, that might help with what you're doing.


It actually works innately (ie if you just call it via Spell(faerie_swarm) it will account for the cooldown). You just can't call SpellCooldown(faerie_swarm) because there's an additional check there that requires it to be in the spell book (which seems to be the only place you can't reference it is through the spellbook). The ticket I made has all this and more info in it (a lot of it in the comments).

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sat Jul 27, 2013 8:15 pm

Just as a note, how many of you actually use the predictive box? To those that do, how important is the fluidity of that box (ie that it doesn't jump around on suggestions too much; at least anymore than is already required to do things like overwriting bleeds with stronger ones)?

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Wed Jul 31, 2013 9:06 pm

ShmooDude wrote:Just as a note, how many of you actually use the predictive box? To those that do, how important is the fluidity of that box (ie that it doesn't jump around on suggestions too much; at least anymore than is already required to do things like overwriting bleeds with stronger ones)?


My Ovale is set up with 1 big box for the main rotation with 2 smaller boxes to the left that contain HotW/DoC info and the other contains alternate attack. Although I ignore a lot of what Ovale suggests as I use Bleed Ratios to see when to clip anyway.

I mainly use Ovale to keep me on track if my rotation gets broken up because I need to Tranq or I get Matter Swap or something
Image

Honored
Posts: 145
Joined: Thu Mar 18, 2010 12:33 am
Location: Melbourne, Australia

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Grenache » Wed Jul 31, 2013 11:17 pm

Hi Schmoo - I've been trying out your script now that I finally got RoR to drop for me last week. It's really good at recommending Rakes/Rips/Thrash during the R-O proc however I notice that at other times when my Rip has dropped off a target dummy, and I have 5 combos, and TF is available - I notice it doesn't suggest TF before the Rip/Rake. Are you seeing this behaviour?

I decided to investigate the bleed ratios options too - as there's been a fair bit of talk about optimising them on these forums lately, however I found myself a bit confused by the numbers. The Rake box is on the extreme left and Rip to the right of it. The Rip box shows 20 per combo when building them, which I found a bit distracting at first. Is the intent to view the number just prior to applying a new Rake / Rip to see the likely strength of the bleed? I'm just wondering what decision making I should do based on these numbers. Or does your script already take this into account? How about during BitW?

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Aug 01, 2013 6:19 am

Grenache wrote:Hi Schmoo - I've been trying out your script now that I finally got RoR to drop for me last week. It's really good at recommending Rakes/Rips/Thrash during the R-O proc however I notice that at other times when my Rip has dropped off a target dummy, and I have 5 combos, and TF is available - I notice it doesn't suggest TF before the Rip/Rake. Are you seeing this behaviour?


What's your energy level @ 5 combo points? Tiger's Fury will only be suggested at 35 or less energy to ensure that you don't overcap energy by too much. I'll take a look when servers are back up but pretty sure this works properly.

Grenache wrote:I decided to investigate the bleed ratios options too - as there's been a fair bit of talk about optimising them on these forums lately, however I found myself a bit confused by the numbers. The Rake box is on the extreme left and Rip to the right of it. The Rip box shows 20 per combo when building them, which I found a bit distracting at first. Is the intent to view the number just prior to applying a new Rake / Rip to see the likely strength of the bleed? I'm just wondering what decision making I should do based on these numbers. Or does your script already take this into account? How about during BitW?


Rip is 20 per combo point because that's how much damage it does. A 1 CP rip is 20% of the damage of a 5 CP rip. Theoretically you could change it to always assume a 5 CP rip, but that's pretty dangerous territory as now you're not giving the real number and assumes you only ever use Rip at 5 CP. General rule of thumb is rake at >112 and rip at >115 for overwriting.

Steakbomb wrote:My Ovale is set up with 1 big box for the main rotation with 2 smaller boxes to the left that contain HotW/DoC info and the other contains alternate attack. Although I ignore a lot of what Ovale suggests as I use Bleed Ratios to see when to clip anyway.

I mainly use Ovale to keep me on track if my rotation gets broken up because I need to Tranq or I get Matter Swap or something


First, shouldn't ovale be suggesting the same thing (assuming you use the above values of course) as what you're doing anyhow? (just curious, there's nothing wrong with the way you're doing it, also curious to see if there's any difference between what ovale is setup to suggest and what you feel works best).

Second, you should consider using my ovale script to give you your ratios because they should be generally more accurate than Droodfocus's ratios. There's a desync between what the client sees and what's actually on the server.

I confirmed this by using FRAPS to record myself casting rake at the tail end of a Tiger's Fury (naked so the damage value was either 330 or 380 w/o savage roar). I could hit rake with the tiger's fury buff showing (and not just split second timing either, a good couple hundred milliseconds) and it would not always have the 15% damage buff applied to it. There's then an additional lag time waiting for the character sheet to update (which is where Droodfocus gets its info from). Ovale has some code to attempt to compensate for this but its not perfect.

My script will factor a buff (current tier trinket or tf) out of the ratio at 0.3 seconds by default (I actually upped mine to 0.4 for the moment, I'll explain why in a minute) or if you won't have the energy/gcd to use a bleed before the buff will expire or its within that 0.3 seconds safety margin. This ensures that you don't try to clip a stronger bleed with a weaker one given both player reaction time and the realities of the desync between client and server.

I upped it to 0.4 seconds because ovale seems to be just a bit overly aggressive in determining whether a buff expired before a bleed was applied (at 0.3 it occasionally unapplies a buff that I confirm is there via the damage that's going out; at 0.4 this pretty much never happens except maybe once or twice a raid). Its still a relatively new function so Jeshu is trying to tweak it better.

The ratio will also flash back to its full value shortly after the expiration of a buff but before the character sheet update but I'm hoping to fix this in an upcoming Ovale update that will allow me to track when a buff expired (currently Ovale doesn't cache when a buff expired so its impossible to track).

Even given these caveats, I think my script will give better ratios than Droodfocus at the present time (there's nothing preventing the author from applying the same logic to it, though it has to be done individually for each buff/trinket). Though at this point we're really nitpicking as even "screwing up" is probably a difference of maybe 1% given that simcraft says (for hotw anyhow, didn't try it for doc cuz its harder to factor out and I'm being lazy about it since I don't use DoC all that often) that manipulating ratios results in about a 6% DPS upgrade over simply refreshing at the last tick of Rip/Rake. Then again, most of us wouldn't be here if that 1% wasn't important to us. =) Just thought I'd mention it and see if you wanted to try it out (last Pic I saw of your UI used something else for ratios, maybe you've changed since then I dunno).

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Thu Aug 01, 2013 1:13 pm

Wall of text over a miss understanding I think. I do not use DroodFocus to overwrite my bleeds.

This is my current UI: viewtopic.php?f=11&t=4621 althought I have since changed back to DroodFocus for tracking Bleeds/SR/WA/OoC/PS.

I use Stenhaldi's Weak Auras Bleed Ratio's from here: viewtopic.php?f=11&t=4446#p16467 which updates on every frame.

I actually have never used DroodFocus to track when to overwrite my bleeds.

First off I have my Ovale set at 0.4 as well.

The reason I ignore Ovale so much is because it assumes you are in a Patchwerk type fight all the time and this is rarely the case. It doesn't factor in not being able to attack the boss for a given amount of time or adds coming into play.

There is also something up with Rake at times. It will suggest a Rake anytime it does more damage than Mangle which is fine most of the time but if you just got done with Rune and Renataki's goes to a higher stack(7-10) a lot of times it will suggest a Rake even though you have a Rake that is buffed with Rune + 4-5 stack Renataki's.

Ovale also suggests SR over Rip if they are both falling off within 1 second of each other when you can clearly Rip with less than a second left on SR and then just SR afterwards even though it will only be 11-18 seconds depending if your tier 2p gives you an extra CP.

It also suggests Thrash when Rip is coming close to falling off until Rip actually falls off.

Ovale doesn't factor in adds on fights like Lei Shen when you should at the very least Thrash them if not more.

And it also does not factor in time that you will not be able to attack the boss when it's better to put up a 3-4 CP Rip to overwrite a Rip that's about to fall off. The easiest way to explain it is on Jin'Rokh Heroic. I understand some guilds continue to DPS him during Lightning Storm and just dodge balls. My guild run away from him and spreads out so I am left with a bunch of down time. Right as he is about to Storm if my Rip has less than ~8 seconds left I tend to put up a smaller Rip with a full duration as I am not attacking the boss for a while. Doing so is a DPS increase.

Most of these issues can not be fixed within the script which is fine, I don't expect unrealistic things from Ovale. I just wanted to let you know why I ignore it so much. You did a great job with the script and it works great, it just can't predict things out of the normal from happening.

The only thing I use DroodFocus is stated above, everything else is Weak Auras and the reason for this is because if Im not mistaken, WA is client side, not server side like most addons.
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Aug 01, 2013 3:47 pm

Steakbomb wrote:Wall of text over a miss understanding I think. I do not use DroodFocus to overwrite my bleeds.

This is my current UI: viewtopic.php?f=11&t=4621 althought I have since changed back to DroodFocus for tracking Bleeds/SR/WA/OoC/PS.

I use Stenhaldi's Weak Auras Bleed Ratio's from here: viewtopic.php?f=11&t=4446#p16467 which updates on every frame.

I actually have never used DroodFocus to track when to overwrite my bleeds.


Everything I wrote about DroodFocus is also true of those WeakAura ratios so it all still holds true (imported em and tested). Theoretically, the bleed ratios in WA could be given the same treatment as the ratios in my ovale script, though that's a lot of extra code compared to what it looks like now (that's why my ovale script is like twice as long as leafkiller's) because you're no longer "just" pulling from the character sheet, you're accounting for buffs which you can't pull (the values) from the API and have to include each one manually.

Steakbomb wrote:The reason I ignore Ovale so much is because it assumes you are in a Patchwerk type fight all the time and this is rarely the case. It doesn't factor in not being able to attack the boss for a given amount of time or adds coming into play.


Very true. Though I play choosing when to override ovale based on the non-patchwerk situation more than ignoring it. Probably because I'm just not as good as a lot of players, like my brother has way better reaction times than I do so I gotta rely on ovale more than a lot of people might. Not trying to say that you should switch to relying on Ovale, was just curious.

Steakbomb wrote:There is also something up with Rake at times. It will suggest a Rake anytime it does more damage than Mangle which is fine most of the time but if you just got done with Rune and Renataki's goes to a higher stack(7-10) a lot of times it will suggest a Rake even though you have a Rake that is buffed with Rune + 4-5 stack Renataki's.


I think I've noticed this too. I'm betting its related to ovale guessing that Rune has fallen off when it actually hasn't (because looking at the code that's the only reason it should ever happen). I'll probably push my safety margin to 0.5 and see if it stops happening.

Steakbomb wrote:Ovale also suggests SR over Rip if they are both falling off within 1 second of each other when you can clearly Rip with less than a second left on SR and then just SR afterwards even though it will only be 11-18 seconds depending if your tier 2p gives you an extra CP.


Yeah... This seems to be a side effect of how ovale determines what icon to show. Once its picked an ability, it sticks with it until its invalid and it doesn't matter if something higher up in the list should overwrite it (ovale wasn't initially designed to be a top down list; more of a priority based system). I can probably program around it though. If you can think of any other places it seems to sticky its suggestions too long, please let me know.

Steakbomb wrote:It also suggests Thrash when Rip is coming close to falling off until Rip actually falls off.


If thrash is < 3, Rip is > 2 and CP = 5, it'll suggest thrash. Sounds like I probably need to include time to energy for rip as part of the rip logic so it doesn't switch when you actually shouldn't be thrashing (kind of thing I've taken a lot of care to remove in other places). Good tip.

Steakbomb wrote:Ovale doesn't factor in adds on fights like Lei Shen when you should at the very least Thrash them if not more.


Very true, and probably not the kind of thing ovale will ever handle well. This is the main kind of fight I tend to override ovale on. Best thing I can think of would be to give AoE suggestion boxes, like how many targets to switch from mangle to swipe, how many targets to drop Rake at, how many targets to drop Rip at. Though honestly I don't even know the answers to those questions and so it'd require a LOT of simcrafting...

Steakbomb wrote:And it also does not factor in time that you will not be able to attack the boss when it's better to put up a 3-4 CP Rip to overwrite a Rip that's about to fall off. The easiest way to explain it is on Jin'Rokh Heroic. I understand some guilds continue to DPS him during Lightning Storm and just dodge balls. My guild run away from him and spreads out so I am left with a bunch of down time. Right as he is about to Storm if my Rip has less than ~8 seconds left I tend to put up a smaller Rip with a full duration as I am not attacking the boss for a while. Doing so is a DPS increase.

Most of these issues can not be fixed within the script which is fine, I don't expect unrealistic things from Ovale. I just wanted to let you know why I ignore it so much. You did a great job with the script and it works great, it just can't predict things out of the normal from happening.


Yeah, my guild does Jin the same way (though now I outgear it enough I can cd through the storm even being out of range of the heals, lol) and I did the same thing.

It probably boils down to that you can do the rotation without ovale (barring distractions such as having to tranq etc) while I have to rely on it (much) more and so a difference in philosophy regarding how its used. I could probably eventually get to the point where I could largely not rely on it but eh, what I got works (and I rank pretty much every fight anyhow; though part of that is the low number of 25H ferals).

Steakbomb wrote:The only thing I use DroodFocus is stated above, everything else is Weak Auras and the reason for this is because if Im not mistaken, WA is client side, not server side like most addons.


All addons are client side and all pull from the same data (the WoW API).



If you can think of any other cases that Ovale's suggestions are wrong (that could theoretically be put in; mostly non-multitarget/downtime things), please let me know.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Thu Aug 01, 2013 4:35 pm

ShmooDude wrote:It probably boils down to that you can do the rotation without ovale (barring distractions such as having to tranq etc) while I have to rely on it (much) more and so a difference in philosophy regarding how its used. I could probably eventually get to the point where I could largely not rely on it but eh, what I got works (and I rank pretty much every fight anyhow; though part of that is the low number of 25H ferals).

If you can think of any other cases that Ovale's suggestions are wrong (that could theoretically be put in; mostly non-multitarget/downtime things), please let me know.


Yea I have played a feral/guardian druid since the end of BC. I have played it enough that I can play it in my sleep and actually didn't use Ovale until a couple months ago.

If you think that there aren't many ferals in 25H, look at the later fights in 10H, ferals are basically non-exsistent.

http://www.worldoflogs.com/reports/c1l17ed1ggf5lkdk/

I ranked on our H Ra-den 10 kill and our tank killed me(I think on purpose) at the beginning of phase 2(sub 40%). In P2 Ra-den stays in the mid and doesn't move at all. Tank moved out to attack an orb and Ra-den turned and hit me in the face. I have come to he conclusion that now that he knows how to kill me, he will kill me on that fight every week at like 10% HP.

My raid week is basically over now(only Ra-den left tonight) and I rarely play outside raids so I probably won't find anymore cases of Ovale being wrong but I will pay closer attention to Ovale during next weeks raid on the fights that I actually do(I sit a lot of fights that I don't need) and update you to any issues I find.
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Aug 01, 2013 5:38 pm

Yeah, our spec has the lowest number of parses (not counting specs of classes that can respec w/o changing their primary stat).

No love for the kitties :(

Honored
Posts: 145
Joined: Thu Mar 18, 2010 12:33 am
Location: Melbourne, Australia

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Grenache » Fri Aug 02, 2013 8:02 am

Duplicate.
Last edited by Grenache on Fri Aug 02, 2013 8:09 am, edited 1 time in total.

Honored
Posts: 145
Joined: Thu Mar 18, 2010 12:33 am
Location: Melbourne, Australia

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Grenache » Fri Aug 02, 2013 8:02 am

Grenache wrote:Hi Schmoo - ...however I notice that at other times when my Rip has dropped off a target dummy, and I have 5 combos, and TF is available - I notice it doesn't suggest TF before the Rip/Rake. Are you seeing this behaviour?


ShmooDude wrote:What's your energy level @ 5 combo points? Tiger's Fury will only be suggested at 35 or less energy to ensure that you don't overcap energy by too much. I'll take a look when servers are back up but pretty sure this works properly.


Hi Schmoo, I did this short Youtube clip tonight. You're right, my energy IS above 35 when I hit 5 combos, but instead of recommending another mangle to get the energy down before the TF, and then Rip, it just says Rip. I realise you wrote the script to suit yourself, but coming across from using the LeafKiller script, I noticed it behaves differently in that regard.

See 38 seconds into the vid. My energy looks to be around 45 at the time it suggests Rip. Do you think its worth inserting an extra mangle/shred into the logic to prevent a non buffed Rip from happening?
http://youtu.be/ruX7suB_jmg

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Aug 02, 2013 7:46 pm

# 8/02/13 version 5.3.8.5
# Added TimeToEnergy to end of rip refreshes and added back waiting on TF when the CD is close
# Will allow Rake to expire if the new rake will be significantly weaker than the current Rake
# Increased required duration of Rip/Savage Roar needed to apply Thrash

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
# 8/02/13 version 5.3.8.5
#   Added TimeToEnergy to end of rip refreshes and added back waiting on TF when the CD is close
#   Will allow Rake to expire if the new rake will be significantly weaker than the current Rake
#   Increased required duration of Rip/Savage Roar needed to apply Thrash
# 7/25/13 version 5.3.8.4
#   Fixed Faerie Swarm asking for Faerie Fire's cooldown data
#   Applied same fix to Savage Roar
# 7/23/13 version 5.3.8.3
#   Fixed Rake ratios
#   Fixed double tanking icons
# 7/23/13 version 5.3.8.2
#   Changed Rake logic back to strict damage and ratio based.
#   Fixed Non-doc predictive box
# 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)
    unless TalentPoints(FAERIE_SWARM_TALENT) Spell(FAERIE_FERAL)
}
AddFunction SavageRoar
{
    if Glyph(GLYPH_OF_SAVAGERY) Spell(SAVAGE_ROAR_GLYPHED)
    if Glyph(GLYPH_OF_SAVAGERY no) and 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,slot=hands,if=buff.tigers_fury.up
    #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<=1&combo_points>=3
    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)*2&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&target.health.pct>25
      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.health.pct>25
      if RipRatio() >= 115
      {
         Spell(RIP)
      }
   }
   
   #natures_swiftness,if=talent.natures_swiftness.enabled&talent.dream_of_cenarius.enabled&buff.dream_of_cenarius.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 {{HasEnergyForRip() and {MaxComboPoints() and target.DebuffRemains(RIP) <3 and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <=TigersFuryCooldown()}}}
      or {not HasEnergyForRip() and {MaxComboPoints() and target.DebuffRemains(RIP) <3+TimeToEnergyFor(RIP) and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <=TigersFuryCooldown()+TimeToEnergyFor(RIP)}}}}
   {
      Spell(NATURES_SWIFTNESS)
   }
   
    #rip,if=combo_points>=5&dot.rip.remains<2&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
   if {HasEnergyForRip() and {MaxComboPoints() and target.DebuffRemains(RIP) <2 and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <=TigersFuryCooldown()}}}
      or {not HasEnergyForRip() and {MaxComboPoints() and target.DebuffRemains(RIP) <2+TimeToEnergyFor(RIP) and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <=TigersFuryCooldown()+TimeToEnergyFor(RIP)}}}
    {
        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
   if target.HealthPercent() >25 and MaxComboPoints() and RipRatio() >= 115
   {
      Spell(RIP)
   }
   
   #rip,if=combo_points>=5&dot.rip.remains<2&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
   if {HasEnergyForRip() and {MaxComboPoints() and target.DebuffRemains(RIP) <2 and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <=TigersFuryCooldown()}}}
      or {not HasEnergyForRip() and {MaxComboPoints() and target.DebuffRemains(RIP) <2+TimeTilEnergyForRip() and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <=TigersFuryCooldown()+TimeToEnergyFor(RIP)}}}
   {
      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
{
    #rake,if=action.rake.tick_damage>action.mangle_cat.hit_damage&$(rake_ratio)>=0.99&buff.king_of_the_jungle.down
    #rake,if=action.rake.tick_damage*(1+action.rake.crit_pct_current)>action.ravage.hit_damage*(1+action.ravage.crit_pct_current)&$(rake_ratio)>=0.99&buff.king_of_the_jungle.up
   if FutureRakeTickDamage() >= FillerActionDamagePerEnergyVsRake() and RakeRatio() >= 99
   {
      Spell(RAKE)
   }
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      #rake,if=target.time_to_die-dot.rake.remains>3&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=target.time_to_die-dot.rake.remains>3&($(rake_ratio)>1.12|dot.rake.remains<3&$(rake_ratio)>0.75)
      if RakeRatio() > 75 and {{HasEnergyForRake() and target.DebuffRemains(RAKE) < 3}
         or {not HasEnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}}
         or RakeRatio() > 112
      {
         Spell(RAKE)
      }
      
      #rake if its about to fall off.  Simcraft doesn't require this line but ovale does for the prediction box.
      if {HasEnergyForRake() and target.DebuffRemains(RAKE) < 0.001}
         or {not HasEnergyForRake() and target.DebuffRemains(RAKE) < 0.001 + TimeTilEnergyForRake() and BuffExpires(CLEARCASTING)}
      {
         Spell(RAKE)
      }
   }
}

AddFunction ThrashLogic
{
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=target.time_to_die>=6&dot.thrash_cat.remains<3&(dot.rip.remains>=8&buff.savage_roar.remains>=12|buff.berserk.up)&dot.rip.ticking
   if {HasEnergyForThrash()
      and target.DebuffRemains(THRASH_CAT) < 3
      and target.TimeToDie() >=9
      and {{target.DebuffRemains(RIP) >=8 and BuffRemains(SAVAGE_ROAR) >=12}
         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() >=8 and BuffRemains(SAVAGE_ROAR) - TimeTilEnergyForThrash() >=12}
         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()
   #run_action_list,name=filler,if=combo_points<5
   if TalentPoints(HEART_OF_THE_WILD_TALENT) and TalentPoints(SOUL_OF_THE_FOREST_TALENT) and not MaxComboPoints() 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 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)
}

#######################
## 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) }


Grenache wrote:Hi Schmoo, I did this short Youtube clip tonight. You're right, my energy IS above 35 when I hit 5 combos, but instead of recommending another mangle to get the energy down before the TF, and then Rip, it just says Rip. I realise you wrote the script to suit yourself, but coming across from using the LeafKiller script, I noticed it behaves differently in that regard.

See 38 seconds into the vid. My energy looks to be around 45 at the time it suggests Rip. Do you think its worth inserting an extra mangle/shred into the logic to prevent a non buffed Rip from happening?
http://youtu.be/ruX7suB_jmg


Simcraft shows its probably slightly better to use a filler and then put up a TF rip but its a very small difference. I'm went ahead and added it back because it'll fix another problem as well.


Rip should also now properly be suggested instead of Savage Roar when they're both expiring around the same time (due to how ovale works this was only sometimes true).
Last edited by ShmooDude on Fri Aug 02, 2013 8:37 pm, edited 1 time in total.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Fri Aug 02, 2013 8:18 pm

Can you post the script here or will it be updated in Nerian's Scripts soon?
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Fri Aug 02, 2013 8:37 pm

its in the post now or you can wait for nerien's to update.

Honored
Posts: 67
Joined: Mon Sep 10, 2012 3:12 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Etapicx » Sat Aug 03, 2013 9:47 am

Spoiler: show
Ovale: Aura 135700 not found in state for 0x0100000004B49222
Ovale: GetAura: aura 135700 not found on player filter=HELPFUL mine=true
Ovale: Condition buffpresent(1=135700,filter=buff,) returned nil, nil, nil, nil, nil
Ovale: Aura 106951 not found in state for 0x0100000004B49222
Ovale: GetAura: aura 106951 not found on player filter=HELPFUL mine=true
Ovale: Condition buffpresent(1=106951,filter=buff,) returned nil, nil, nil, nil, nil
Ovale: Condition energyregen() returned 0, nil, 11.632942199707, 0, 0
Ovale: value 15
Ovale: 11.632942+(t-0.000000)*0.000000 >= 15.000000+(t-0.000000)*0.000000
Ovale: and return nil [1406]
Ovale: if return nil [1407]
Ovale: start=101342.247000 attenteFinCast=101340.987 [1382]
Ovale: Action 33876 can start at 101342.247000
Ovale: group best action 33876 remains 101342.247, nil [1408]
Ovale: if return 101342.247, nil [1409]
Ovale: group best action 33876 remains 101342.247, nil [1410]
Ovale: if return 101342.247, nil [1481]
Ovale: if [1482]
Ovale: Condition timetomaxenergy() returned 0, nil, 0, 101340.987, -1
Ovale: value 1
Ovale: 0.000000+(t-101340.987000)*-1.000000 <= 1.000000+(t-0.000000)*0.000000
Ovale: group [1410]
Ovale: if [1401]
Ovale: and [1398]
Ovale: and [1391]
Ovale: Aura 106830 not found in state for nil
Ovale: nil guid does not exist in OvaleAura
Ovale: GetAura: aura 106830 not found on target filter=HARMFUL mine=true
Ovale: Condition debuffremains(1=106830,target=target,filter=debuff,) returned 0, nil, 0, 0, 0
Ovale: value 3
Ovale: 0.000000+(t-0.000000)*0.000000 < 3.000000+(t-0.000000)*0.000000
Ovale: target = nil, health = 0, maxHealth = 0
Ovale: Condition timetodie(target=target,) returned 0, nil, 0, 101340.987, -1
Ovale: value 9
Ovale: 0.000000+(t-101340.987000)*-1.000000 >= 9.000000+(t-0.000000)*0.000000
Ovale: and return 0, 101331.987 [1391]
Ovale: group [132]
Ovale: Condition combopoints() returned 0, nil, 0, 0, 0
Ovale: value 5
Ovale: 0.000000+(t-0.000000)*0.000000 >= 5.000000+(t-0.000000)*0.000000
Ovale: and return nil [1398]


Shows in human form and i get spamed in chat and ovale dissappears in Cat Form. Latest import.

Just never mind me... It's good to update your addons once in a while lol
Image

Posts: 10
Joined: Wed May 22, 2013 3:16 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Raolf » Sat Aug 03, 2013 4:29 pm

I was getting the same thing all the way back to the 5.3.1 script before I decided to check my version of Ovale itself. Sure enough, I was on Ovale 5.3.6, and 5.3.8 is available. All Shmoo's recent scripts seem to be behaving in regards to this error now. :)

Edit: I am still unable to get past the redirect to login loop when using FF* browser, but get normal behavior when using G* browser. I've check all relevant settings, and updated everything I can think of but still no dice.

*Got spam flagged, and I'm guessing it's the trademark names?--nope--apparently I'm not allowed to use the "confused" smiley--no more flag:)

But for real--anyone have a clue? Your Firefox works ok?

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sat Aug 03, 2013 4:59 pm

Yeah the first 3 numbers in my version number match whatever version of ovale it should be paired with (new stuff keeps getting added that I take advantage of). We're currently on 5.3.8.5 so its the 5th version of the script for Ovale 5.3.8.

As far as browsers. JavaScript and Firefox have not been playing well together lately, I'm probably gonna switch to chrome.

Posts: 1
Joined: Sun Aug 11, 2013 9:25 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Pirao » Sun Aug 11, 2013 10:44 am

Hi all, just want to say that I have been following some of you guys back from the EJ forums during BC and Wrath. You all do any awesome job with the scripts, addons and general advice, this kind of community makes me love playing a feral.
I just started using Shmoo's script in Ovale and have been playing with the dummy a bit now that I have RoR (bad bad luck this tier = ( ). I started noticing some funky things with Stenhaldi's WA bleed ratios. The script would call for Rip to be refreshed on the target when I had 5 combo points, high energy (>75), Rip duration >10 and SR duration >10 and the WA bleed ratio was sitting at 106. I quickly took a screenshot and kept going, then noticed it happened again, not every time but enough to make me think about it. I also use Droodfocus for the dot timers and they show the bleed ratio as well, in this case it was grey, so it pretty much matched what WA was showing. So I make sure that I had the latest WA and bleed ratio code but I had the same results. Then I decided to turn on the Ovale ratios and noticed that when Ovale was telling me to overwrite my Rip, even though Droodfocus and WA were saying I shouldn't, according to the Ovale ratios I should have been. I can reproduce this pretty consistently if I bash the dummy for a few minutes.
I started checking the combat logs and it looks like Ovale was right, I was seeing an increase in Rip damage even though WA and Droodfocus were saying different. About 10k per tick when I was checking the logs.
I also had some funkiness once or twice with a Rune proc. I am struggling to reproduce it but it seems to be something like if I pop TF and rake and then rune pops straight away (almost at the same time) Ovale isn't telling me to rake even though Droodfocus and WA are saying it will be a significant increase. The 2 times I noticed this happen I didn't have the Ovale ratios showing so it may have just been a freak accident. I definitely can't reproduce this one like I can the first issue.
Sorry if it has been answered before, I have been going through the various threads but I can't seem to find an answer.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Sun Aug 11, 2013 11:51 am

This is one of the reason's that Shmoodude reccommends using Ovale ratio's over WA or DF. Ovale is very aggressive when overwriting bleeds.

WA and DF waits until the character sheet is updated to update the ratios and Ovale doesn't. If you read the last couple pages of this thread than you will see the convo that Shmoo and I had about this same thing.

I believe(could be wrong) that Ovale will suggest an overwrite at 105 vs DF/WA doesn't turn green until 110.

Personally I use WA Bleed Ratios but this is a personal choice as I don't look at Ovale for my move list most of the time as it is pretty much engraved in my head. It does lag behind a little bit but I'm used to it.

If you want your ratios to be spot on then use Ovale's ratios but set your Ovale delay to at least .3 or .4 so you don't accidentally overwrite something you shouldn't.
Image

PreviousNext

Return to Kitty DPS

Who is online

Users browsing this forum: Google [Bot] and 4 guests