Register

Leafkiller's MoP Feral/Guardian Ovale Script

Face-rippin fun.

Moderator: Forum Administrators

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sun Jul 07, 2013 12:30 pm

Jeshu wrote:I accidentally pushed out a new release of Ovale instead of a beta. If you're interested, please download 5.3.3 and let me know if there are any bugs in the new features. I have been testing changes on a balance druid and brewmaster monk thus far.


I couldn't get the damage=function to work in 5.3.4 but I don't know if its in there or not (if its only in 5.3.3?). I didn't mess around with it too awful much because it broke my script (not your fault I don't believe, just because I have to update it to the new code style for snapshotting which will take a while) and I wanna go with what I know works for raid tonight.

Also just in case you missed it in my previous post (I know there was a lot of talking about that weird bug) I would *really* love to be able to define functions that can take variables. I'm having to repeat a lot of code just to essentially change the spell ID in a function and it'd be way easier if I could just send that spell id to the function and just have one.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Sun Jul 07, 2013 6:29 pm

ShmooDude wrote:Also just in case you missed it in my previous post (I know there was a lot of talking about that weird bug) I would *really* love to be able to define functions that can take variables. I'm having to repeat a lot of code just to essentially change the spell ID in a function and it'd be way easier if I could just send that spell id to the function and just have one.


No, that is too complicated to implement in the current parser. Eventually, the parser will be re-written but that's a long-term project with an active ticket.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sun Jul 07, 2013 7:20 pm

Jeshu wrote:
ShmooDude wrote:Also just in case you missed it in my previous post (I know there was a lot of talking about that weird bug) I would *really* love to be able to define functions that can take variables. I'm having to repeat a lot of code just to essentially change the spell ID in a function and it'd be way easier if I could just send that spell id to the function and just have one.


No, that is too complicated to implement in the current parser. Eventually, the parser will be re-written but that's a long-term project with an active ticket.


Fair enough.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Mon Jul 08, 2013 8:19 am

Hmm, while the weapon damage function technically works, its pulling the wrong numbers for use in formulas. The number we really need to work with is the weapon damage per second listed on the item itself. Now, I as a druid can get to this number from the information provided:

Code: Select all
    WeaponDamage(MH) / 2 - AttackPower() / 14 # Divided by 2 because of 100% increased auto attack damage that shows up on the character sheet


However, most classes would also need their weapon swing speed as well (this will still be true even if you make changes I put below).


You can pull the weapon DPS directly from the item itself. I modified my local copy to the following:

Code: Select all
function OvalePaperDoll:Ovale_EquipmentChanged(event)
   local mainHand = API_GetItemStats(API_GetInventoryItemLink("player", 16))
   self.stat.mainHandWeaponDamage = mainHand["ITEM_MOD_DAMAGE_PER_SECOND_SHORT"]
   if API_IsDualWielding() then
      local offHand = API_GetItemStats(API_GetInventoryItemLink("player", 17))
      self.stat.offHandWeaponDamage = offHand["ITEM_MOD_DAMAGE_PER_SECOND_SHORT"]
   else
      self.stat.offHandWeaponDamage = 0
   end
end


The problem with this is it doesn't account for item upgrades until Blizzard updates it (it will however be far simpler than trying to modify the data from UnitDamage() because there's a lot of things that can modify that). There's a couple ways to get around this, but I think both are a bit beyond my programming level at the moment.

There's a discussion here about the problem: http://www.wowinterface.com/forums/show ... hp?t=45388

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Mon Jul 08, 2013 2:53 pm

On my druid and my monk, UnitDamage("player") returns the correct results. The weapon damage matches the item tooltips for the monk, and the weapon damage is auto-scaled based on stance for the druid.

You can test this in-game by entering the following in your chat window:
Code: Select all
/dump UnitDamage("player")

I don't think you should need a more complicated way of getting data from item tooltips.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Mon Jul 08, 2013 7:40 pm

Jeshu wrote:On my druid and my monk, UnitDamage("player") returns the correct results. The weapon damage matches the item tooltips for the monk, and the weapon damage is auto-scaled based on stance for the druid.

You can test this in-game by entering the following in your chat window:
Code: Select all
/dump UnitDamage("player")

I don't think you should need a more complicated way of getting data from item tooltips.


That's weird... That's 100% inconsistent with what I'm getting.

I have: http://www.wowhead.com/item=96763 upgraded twice (damage range 19328-28994)

/dump UnitDamage("player") returns:
[18:56:58] Dump: value=UnitDamage("player")
[18:56:58] [1]=18976.87890625,
[18:56:58] [2]=24834.03125,
[18:56:58] [3]=3632.2861328125,
[18:56:58] [4]=3632.2861328125,
[18:56:58] [5]=0,
[18:56:58] [6]=0,
[18:56:58] [7]=1

My character sheet says 18,976-24,835 so that's clearly where its pulling the damage from. I logged onto my other characters and its consistent across all of them (its pulling the numbers from whatever is stated under the "Melee" - "Damage:" section on the damage sheet). Is this not the number you're getting?


(I apologize if you already knew this, just wanna make sure we're 100% on the same page) Generally speaking, the damage formula for X% weapon damage is:

X * (Weapon Damage [as listed on the item; or * DruidFormSpeed/WeaponSpeed for druids in forms] + Attack Power / 14 * Item Type Speed [3.3 for 2hers; 2.4 for 1hers; 1.7 for daggers; 1.0 for cats; 2.5 for bears])

Monks don't seem to use this formula and all their attacks are weapon speed independent. They essentially function like a cat form druid except without modifying the autoattack. (which is ironic since this would allow them to be a second class to use daggers except that they're not allowed...)




Like I said, I can pull the right number from what ovale is giving me (actually now that I think about it, other classes can too though its a little more complicated for them, so technically speaking even if it functions like I think it does, it doesn't require a change, especially since the other method is either bugged or requires some complex tooltip parsing). Though a note should probably be made in the documentation assuming I'm not mistaken or my game's not giving me different information than yours.

EDIT: @aggixx I found a small bug with the Rake logic (cut down to better illustrate the problem)
Code: Select all
AddIcon
{
   if {SpellCooldown(TIGERS_FURY)+4.8} >=target.DebuffRemains(RAKE)}
            Spell(RAKE)      
         Spell(MANGLE_CAT)
}

will always suggest Rake unless TF is off cooldown and then it suggests Mangle (should suggest rake until TF cooldown comes to 4.8 and then suggest mangle). However, if you move the 4.8 (I set it higher than normal so it was more obvious during testing) to the other side, it works. Probably something to do with the fact that when Tigers Fury is off cooldown, SpellCooldown(TIGERS_FURY) is some really large negative number where as if there's no Rake on the target, target.DebuffRemains(RAKE) is 0.

EDIT2: Actually, that whole test after screwing around in simcraft appears to be negligible (for me anyhow, within the margin of error). Its probably technically better, but honestly not worth worrying about.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Tue Jul 09, 2013 11:01 am

Okay, I think I understand how the formula is supposed to work now. It's not supposed to auto-scale with melee attack speed, which is the melee damage value from UnitDamage(), but rather directly use the weapon damage without scaling. That could be done by either scanning the tooltips of the weapons or by rescaling the UnitDamage() results by attack speed. I'm leaning toward the latter so as to avoid problems with forms with fixed attack speeds.

Regarding SpellCooldown, the implementation is slightly naive and should probably be improved to match expectations, i.e., if a spell is ready, I would expect its cooldown to be zero. Currently, it only makes sense to use SpellCooldown() if you can be sure that its value is greater than zero. I'll probably make that change in the next release of Ovale in the next few days once I get more feedback on the current release.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Tue Jul 09, 2013 1:53 pm

Jeshu wrote:Okay, I think I understand how the formula is supposed to work now. It's not supposed to auto-scale with melee attack speed, which is the melee damage value from UnitDamage(), but rather directly use the weapon damage without scaling. That could be done by either scanning the tooltips of the weapons or by rescaling the UnitDamage() results by attack speed. I'm leaning toward the latter so as to avoid problems with forms with fixed attack speeds.

Regarding SpellCooldown, the implementation is slightly naive and should probably be improved to match expectations, i.e., if a spell is ready, I would expect its cooldown to be zero. Currently, it only makes sense to use SpellCooldown() if you can be sure that its value is greater than zero. I'll probably make that change in the next release of Ovale in the next few days once I get more feedback on the current release.


Honestly not sure which would be easier. The UnitDamage method formula:

weapon damage = (charsheet damage / autoattack modifier - attack power / 14 * swing speed / haste) / percentmod [from the UnitDamage() function, to take out things like Savage Roar]

As far as I know, autoattack modifier = 2 for cat form druids and 1.4 for dual-wielding monks (though my monk is only 8 so i can't verify). There may be others but I didn't see anything searching wowhead. If those are the only exceptions than the above formula should then work for all classes. This is essentially the same thing I did only within the ovale script to arrive at the proper number. In addition, you'd have to update this on druids changing forms (as currently ovale only updates on equipment change).

If you can figure out an easy way to pull the correct weapon dps number from the tooltip (I couldn't figure out the upgraded items thing), then I think that would be the way to go as it has way less exceptions and potential problems than the UnitDamage() method (only have to account for cat and bear form, which you have to anyhow in the other method in addition to monks and a bunch of other stuff). For this method it'd be:

weapon damage = weapon DPS * weapon speed (both pulled from the tooltip, just make an exception for cat and bear form which are the only fixed attack speed forms as far as I know)

Again though, that's if you can figure out how to do upgraded items. Hopefully all this helps.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Tue Jul 09, 2013 5:41 pm

My final 5.3.2 Script:

Spoiler: show
Code: Select all
# Leafkiller's Feral/Guardian druid script.
# Support/Discussion thread: http://fluiddruid.net/forum/viewtopic.php?f=3&t=857
# Cat Rotation based on Simulationcraft single target default script. Contributions to that have come from many ferals.
# Guardian rotation based on the guide at theincbear.com
# Lots of input and constructs from jlam aka Nerien
# Currently maintained by aggixx and Tinderhoof
# Revision History
# 5.3.1 06/24/2013 Update RoR item list to include TF versions, fix Rip not clipping during Rune.
# 5.2.4 04/18/2013 Better RoR code, better rake code, some DPS oriented changes for Guardian while not tanking
# 5.2.3 03/18/2013 Use Mangle to generate combo points except for high energy situations. Fix issue with misplaced NSs.
# 5.2.2 03/09/2013 Smarter FB logic, fix Faerie Fire, fix mastery assumption for RoR, better Thrash logic, better precombat SR logic
# 5.2.1 02/25/2013 Support for 5.2 changes, rough support for Rune of Reorigination
# 5.1.8 02/16/2013 Fix TF not displaying with berserk checked and TF displaying while Berserk is active, fix lookahead issue with Ravage.
# 5.1.7 02/12/2013 Fix FF option, fix WEAKENED_ARMOR.
# 5.1.6 02/10/2013 Fix frontal attack and talent conditional in main button (dream_of_cenarius_talent should be DREAM_OF_CENARIUS_TALENT)
# 5.1.5 02/09/2013 Update to SimC (Base code from Nerien), code consistency and formatting
# 5.1.4 12/07/2012 Tooth and Claw
# 5.1.3 12/07/2012 Tweak for Bear display with alternate setup selected
# 5.1.2 12/07/2012 Misc changes including SR, Ravage!, alternate layout for Aggixx and some script reconciliation
# 5.1.1 11/30/2012 Ravage fix for PVP 4 set and support for faster combo points on crits
# 5.05.14 11/09/2012 New spell ID for clearcasting
# 5.05.14 11/09/2012 Only suggest Feral_spirit if the symbiosis buff is present - otherwise it suggests symbiosis even when the buff is not up
# 5.05.13 10/23/2012 Don't pool during NV
# 5.05.12 10/22/2012 Fix bad spell name in Rake conditional (TIGERS_FURY should be TIGERSFURY)
# 5.05.11 10/22/2012 Fix for energy pooling for non-DoC specs. Small updates based on most recent sim script for TTD. FFF() added. TTD updated.
# 5.05.10 10/21/2012 4 Piece PvP gear support and Nature's Vigil HT code
# 5.05.9 10/16/2012 Feral Spirit support
# 5.05.8 10/14/2012 Fix 3 second SR to interfere less with Rip for HotW (and NV). 60 seconds for Rake.
# 5.05.7 10/14/2012 Update to latest version of sim script - small changes and Rake improvements
# 5.05.6 10/11/2012 Heart of the Wild support, add out of combat support
# 5.05.6 10/10/2012 Update to limit SR using comb points when DoC is up
# 5.05.5a 10/08/2012 Update to include optimizations in simc script
# 5.05.5 09/24/2012 Multiply damage ratios by 100 to avoid rounding issues, put in variable Rip overwriting during BitW, tweak numbers slightly (TF is 14% not 15% for example).
# 5.05.4 09/23/2012 Level 90 script - First complete version
# 5.05.2 09/20/2012 Level 90 script - WiP
# 5.05.1 09/08/2012 First version in Nerien's addon

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

# Shared items
ItemList(ROR_ITEM 94532 95802 96174 96546 96918)

# 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)
   SpellInfo(FEROCIOUS_BITE base=500 bonuscp=762 bonusapcp=0.196)
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 base=98.13 bonusap=0.31453)
    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)
    SpellInfo(RIP base=112.76 bonuscp=320 bonusapcp=0.0484) # damage coefficients
    SpellAddTargetDebuff(RIP RIP=1)
    SpellDamageBuff(RIP DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(SAVAGE_ROAR_OLD 52610)
    SpellInfo(SAVAGE_ROAR_OLD duration=18 combo=0 energy=25)
    SpellAddBuff(SAVAGE_ROAR_OLD SAVAGE_ROAR_OLD=1)
Define(SAVAGE_ROAR_GLYPHED 127538)
    SpellInfo(SAVAGE_ROAR_GLYPHED duration=12 combo=-5 energy=25)
    SpellAddBuff(SAVAGE_ROAR_GLYPHED SAVAGE_ROAR_GLYPHED=1)
    SpellList(SAVAGE_ROAR 52610 127538)
Define(SHRED 5221) #cat behind
    SpellInfo(SHRED inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED critcombo=1 if_spell=PRIMAL_FURY)
Define(SHRED_BANG 114236)
    SpellInfo(SHRED_BANG inccounter=ripshreds energy=40 combo=1)
    SpellInfo(SHRED_BANG critcombo=1 if_spell=PRIMAL_FURY)
Define(STAMPEDE 81022)
    SpellAddBuff(STAMPEDE STAMPEDE=1)
Define(SKULL_BASH_CAT 80965) #cat interrupt
    SpellInfo(SKULL_BASH_CAT cd=15 energy=15)
Define(THRASH_CAT 106830)
    SpellInfo(THRASH_CAT duration=15 energy=50 tick=3)
    SpellAddTargetDebuff(THRASH_CAT THRASH_CAT=1 WEAKENED_BLOWS=1)
    SpellDamageBuff(THRASH_CAT DREAM_OF_CENARIUS_DAMAGE=1.25)
Define(TIGERS_FURY 5217) #cat buff
    SpellInfo(TIGERS_FURY duration=6 energy=-60 cd=30)
    SpellAddBuff(TIGERS_FURY TIGERS_FURY=1)

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

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

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

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

# CritChance and Armor Functions
AddFunction MeleeCritChanceNoCap
{
    if BuffPresent(attack_power_multiplier any=1)
   {
       {CritChance() + {{{AttackPower()-240}/2770.9} + 5.44}}
   }
   unless BuffPresent(attack_power_multiplier any=1)
   {
       {CritChance() + {{{AttackPower()-218}/2519} + 5.44}}
   }
}
AddFunction MeleeCritChance
{
   if MeleeCritChanceNoCap() > 100
      100
   if MeleeCritChanceNoCap() < 0
      0
   unless MeleeCritChanceNoCap() > 100 and MeleeCritChanceNoCap() < 0
      MeleeCritChanceNoCap()
}
AddFunction LastRakeCritChanceNoCap
{
    if BuffPresent(attack_power_multiplier any=1)
   {
       {LastSpellCritChance(RAKE) + {{{LastSpellAttackPower(RAKE)-240}/2770.9} + 5.44}}
   }
   unless BuffPresent(attack_power_multiplier any=1)
   {
       {LastSpellCritChance(RAKE) + {{{LastSpellAttackPower(RAKE)-218}/2519} + 5.44}}
   }
}
AddFunction LastRakeCritChance
{
   if LastRakeCritChanceNoCap() > 100
      100
   if LastRakeCritChanceNoCap() < 0
      0
   unless LastRakeCritChanceNoCap() > 100 and LastRakeCritChanceNoCap() < 0
      LastRakeCritChanceNoCap()
}
AddFunction LastRipCritChanceNoCap
{
    if BuffPresent(attack_power_multiplier any=1)
   {
       {LastSpellCritChance(RIP) + {{{LastSpellAttackPower(RIP)-240}/2770.9} + 5.44}}
   }
   unless BuffPresent(attack_power_multiplier any=1)
   {
       {LastSpellCritChance(RIP) + {{{LastSpellAttackPower(RIP)-218}/2519} + 5.44}}
   }
}
AddFunction LastRipCritChance
{
   if LastRipCritChanceNoCap() > 100
      100
   if LastRipCritChanceNoCap() < 0
      0
   unless LastRipCritChanceNoCap() > 100 and LastRipCritChanceNoCap() < 0
      LastRipCritChanceNoCap()
}
AddFunction ArmorReduction # Calculates armor for level 88 and higher mobs;  Only verified accurate with bosses and 90 target dummies
{
   if target.Level(more 87) or target.Level(less 1)
   {
      if target.Level(less 1)
         {24835*{1-target.DebuffStacks(WEAKENED_ARMOR any=1)*0.04} / {24835*{1-target.DebuffStacks(WEAKENED_ARMOR any=1)*0.04} + 4037.5*90 - 317117.5}}
      unless target.Level(less 1)
         {{24835*{1-{93-target.Level()}*0.0691}*{1-target.DebuffStacks(WEAKENED_ARMOR any=1)*0.04}} / {{24835*{1-{93-target.Level()}*0.0691}*{1-target.DebuffStacks(WEAKENED_ARMOR any=1)*0.04}} + 4037.5*90 - 317117.5}}
         }
}

# Time till energy for abilities functions (must come before Rune functions)
# Moved check from functions to main code to fix predictive algorithm bug within ovale
AddFunction EnergyForThrash
{
   if BuffExpires(BERSERK_CAT) 50
   unless BuffExpires(BERSERK_CAT) 25
}
AddFunction TimeTilEnergyForThrash
{
   if { EnergyForThrash() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      { EnergyForThrash() - Energy() } / EnergyRegen()
   unless { EnergyForThrash() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      SpellCooldown(TIGERS_FURY)
}
AddFunction EnergyForRake
{
   if BuffExpires(BERSERK_CAT) 35
   unless BuffExpires(BERSERK_CAT) 18
}
AddFunction TimeTilEnergyForRake
{
   if { EnergyForRake() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      { EnergyForRake() - Energy() } / EnergyRegen()
   unless { EnergyForRake() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      SpellCooldown(TIGERS_FURY)
}
AddFunction TempTimeTilEnergyForRake
{
   if TimeTilEnergyForRake() > 0
      TimeTilEnergyForRake()
   unless TimeTilEnergyForRake() > 0
      0
}
AddFunction EnergyForRip
{
   if BuffExpires(BERSERK_CAT) 30
   unless BuffExpires(BERSERK_CAT) 15
}
AddFunction TimeTilEnergyForRip
{
   if { EnergyForRip() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      { EnergyForRip() - Energy() } / EnergyRegen()
   unless { EnergyForRip() - Energy() } / EnergyRegen() < SpellCooldown(TIGERS_FURY)
      SpellCooldown(TIGERS_FURY)
}

# Ratio Calculation assistnace functions
AddFunction PrimordiusStats # Primordius Stats Buff
{
   {1 + 0.05 * DebuffStacks(136184)} * {1 - 0.1 * DebuffStacks(136185)} # Thick and Fragile bones
}
AddFunction StatsMultiplier
{
   if TalentPoints(HEART_OF_THE_WILD) # Leatherwearer, Heart of the Wild, Mark of the Wild, Primordius Buffs
   {
      1.05 * 1.06 * {1 + 0.05 * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   }
   unless TalentPoints(HEART_OF_THE_WILD) # Leatherwearer, Mark of the Wild, Primordius Buffs
      {
      1.05 * {1 + 0.05 * BuffStacks(str_agi_int any=1)} * PrimordiusStats()
   }
}
AddFunction DancingSteelAttackPowerIncrease
{
   {3300*StatsMultiplier()} # 2*1750 agi
}
AddFunction DancingSteelCritChanceIncrease
{
   if BuffPresent(attack_power_multiplier any=1)
   {
       {DancingSteelAttackPowerIncrease()}/2770.9
   }
   unless BuffPresent(attack_power_multiplier any=1)
   {
       {DancingSteelAttackPowerIncrease()}/2519
   }
}
AddFunction SoulCharmAttackPowerIncrease
{
   {3430*BuffStacks(BLADES)*StatsMultiplier()} #2*1715*stacks agility; Heroic TF + 2/2 upgrade
}
AddFunction SoulCharmCritChanceIncrease
{
   if BuffPresent(attack_power_multiplier any=1)
   {
       {SoulCharmAttackPowerIncrease()}/2770.9
   }
   unless BuffPresent(attack_power_multiplier any=1)
   {
       {SoulCharmAttackPowerIncrease()}/2519
   }
}

# Rake functions
AddFunction RakeTickDamage # Switched to raw numbers in place of Damage(RAKE) for 5.3.4+ compatibility
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {98.13 + AttackPower()*0.31453} * DamageMultiplier(RAKE) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRakeTickDamage
{
    # rake_tick_damage = (tick_damage + coeff * AP) * damage_multiplier * crit_multiplier * bleed_multiplier
    {98.13 + LastSpellAttackPower(RAKE)*0.31453} * LastSpellDamageMultiplier(RAKE) * {1+{LastRakeCritChance()/100}} * {1 + LastSpellMastery(RAKE)/100}
}
AddFunction RuneRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if Energy() >= EnergyForRake()
      HasTrinket(ROR_ITEM) and BuffPresent(ROR_MASTERY) and {BuffRemains(ROR_MASTERY) > {0.2}} and BuffRemains(ROR_MASTERY) > {SpellCooldown(RAKE)+0.2}
   unless Energy() >= EnergyForRake()
      HasTrinket(ROR_ITEM) and BuffPresent(ROR_MASTERY) and {BuffRemains(ROR_MASTERY) > {TimeTilEnergyForRake()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(ROR_MASTERY) > {SpellCooldown(RAKE)+0.2}
}
AddFunction TigersFuryRakeUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
   if Energy() >= EnergyForRake()
      BuffPresent(TIGERS_FURY) and {BuffRemains(TIGERS_FURY) > {0.2}} and BuffRemains(TIGERS_FURY) > {SpellCooldown(RAKE)+0.2}
   unless Energy() >= EnergyForRake()
      BuffPresent(TIGERS_FURY) and {BuffRemains(TIGERS_FURY) > {TimeTilEnergyForRake()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(TIGERS_FURY) > {SpellCooldown(RAKE)+0.2}
}
AddFunction TigersFuryExpiresRakeMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRakeUsableBeforeExpire() 1
   unless TigersFuryRakeUsableBeforeExpire() 1.15
   }
   unless BuffPresent(TIGERS_FURY)
   {
      1
   }
}
AddFunction DancingSteelRakeUsableBeforeExpire
{
   if Energy() >= EnergyForRake()
      BuffPresent(DANCING_STEEL any=1) and {BuffRemains(DANCING_STEEL any=1) > {0.2}} and BuffRemains(DANCING_STEEL any=1) > {SpellCooldown(RAKE)+0.2}
   unless Energy() >= EnergyForRake()
      BuffPresent(DANCING_STEEL any=1) and {BuffRemains(DANCING_STEEL any=1) > {TimeTilEnergyForRake()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(DANCING_STEEL any=1) > {SpellCooldown(RAKE)+0.2}
}
AddFunction DancingSteelExpiresRakeMultiplier
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 1
      unless DancingSteelRakeUsableBeforeExpire() {RakeTickDamage() / {{{98.13 + {0.31453 * {AttackPower()-DancingSteelAttackPowerIncrease()}}} * DamageMultiplier(RAKE) * {1+{{MeleeCritChance()-DancingSteelCritChanceIncrease()}/100}}} * {1 + Mastery()/100}}}
   }
   unless BuffPresent(DANCING_STEEL any=1)
   {
      1
   }   
}
AddFunction SoulCharmRakeUsableBeforeExpire
{
   if Energy() >= EnergyForRake()
      BuffPresent(SOUL_CHARM any=1) and {BuffRemains(SOUL_CHARM any=1) > {0.2}} and BuffRemains(SOUL_CHARM any=1) > {SpellCooldown(RAKE)+0.2}
   unless Energy() >= EnergyForRake()
      BuffPresent(SOUL_CHARM any=1) and {BuffRemains(SOUL_CHARM any=1) > {TimeTilEnergyForRake()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(SOUL_CHARM any=1) > {SpellCooldown(RAKE)+0.2}
}
AddFunction SoulCharmExpiresRakeMultiplier
{
    if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRakeUsableBeforeExpire() 1
      unless SoulCharmRakeUsableBeforeExpire() {RakeTickDamage() / {{{98.13 + {0.31453 * {AttackPower()-SoulCharmAttackPowerIncrease()}}} * DamageMultiplier(RAKE) * {1+{{MeleeCritChance()-SoulCharmCritChanceIncrease()}/100}}} * {1 + Mastery()/100}}}
   }
   unless BuffPresent(SOUL_CHARM any=1)
   {
      1
   }   
}
AddFunction TotalRakeMultiplier
{
    TigersFuryExpiresRakeMultiplier()*DancingSteelExpiresRakeMultiplier()*SoulCharmExpiresRakeMultiplier()
}

# Rip functions
AddFunction RipTickDamage  # Switched to raw numbers in place of Damage(RIP) for 5.3.4+ compatibility
{
    # Damage(rip) == { 113 + (320 * CP) + (0.3872 * AP * CP) } * DamageMultiplier(rip)
    {112.76 + {320 * ComboPoints()} + {0.0484 * AttackPower()} * ComboPoints()} * DamageMultiplier(RIP) * {1+MeleeCritChance()/100} * {1 + Mastery()/100}
}
AddFunction LastRipTickDamage
{
    # Damage(rip) == { 113 + (320 * CP) + (0.3872 * AP * CP) } * DamageMultiplier(rip)
    {112.76 + {320 * LastSpellComboPoints(RIP)} + {0.0484 * LastSpellAttackPower(RIP)} * LastSpellComboPoints(RIP)} * LastSpellDamageMultiplier(RIP) * {1+LastRipCritChance()/100} * {1 + LastSpellMastery(RIP)/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.
    # XXX Should factor in crit somehow.
    {{112.76 + {320 * ComboPoints()} + {0.0484 * AttackPower()} * ComboPoints()} * DamageMultiplier(RIP) * {1+{MeleeCritChance()/100}}} * {1 + Mastery() / 100} * {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.
        {{112.76 + {320 * LastSpellComboPoints(RIP)} + {0.0484 * LastSpellAttackPower(RIP)} * LastSpellComboPoints(RIP)} * LastSpellDamageMultiplier(RIP) * {1+{LastRipCritChance()/100}}} * {1 + LastSpellMastery(RIP) / 100} * {target.TimeToDie() / 2}
    }
    unless target.DebuffPresent(RIP)
    {
        0
    }
}
AddFunction RuneRipUsableBeforeExpire # Checks to make sure you have the energy/cooldown to use a bleed before the Rune buff expires
{
    if Energy() >= EnergyForRip()
      HasTrinket(ROR_ITEM) and BuffPresent(ROR_MASTERY) and {BuffRemains(ROR_MASTERY) > {0.2}} and BuffRemains(ROR_MASTERY) > {SpellCooldown(RIP)+0.2}
   unless Energy() >= EnergyForRip()
      HasTrinket(ROR_ITEM) and BuffPresent(ROR_MASTERY) and {BuffRemains(ROR_MASTERY) > {TimeTilEnergyForRip()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(ROR_MASTERY) > {SpellCooldown(RIP)+0.2}
}
AddFunction TigersFuryRipUsableBeforeExpire
{
    if Energy() >= EnergyForRip()
      BuffPresent(TIGERS_FURY) and {BuffRemains(TIGERS_FURY) > {0.2}} and BuffRemains(TIGERS_FURY) > {SpellCooldown(RIP)+0.2}
   unless Energy() >= EnergyForRip()
      BuffPresent(TIGERS_FURY) and {BuffRemains(TIGERS_FURY) > {TimeTilEnergyForRip()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(TIGERS_FURY) > {SpellCooldown(RIP)+0.2}
}
AddFunction TigersFuryExpiresRipMultiplier
{
    if BuffPresent(TIGERS_FURY)
   {
      if TigersFuryRipUsableBeforeExpire() 1
      unless TigersFuryRipUsableBeforeExpire() 1.15
   }
   unless BuffPresent(TIGERS_FURY)
   {
      1
   }
}
AddFunction DancingSteelRipUsableBeforeExpire
{
    if Energy() >= EnergyForRip()
      BuffPresent(DANCING_STEEL any=1) and {BuffRemains(DANCING_STEEL any=1) > {0.2}} and BuffRemains(DANCING_STEEL any=1) > {SpellCooldown(RIP)+0.2}
   unless Energy() >= EnergyForRip()
      BuffPresent(DANCING_STEEL any=1) and {BuffRemains(DANCING_STEEL any=1) > {TimeTilEnergyForRip()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(DANCING_STEEL any=1) > {SpellCooldown(RIP)+0.2}
}
AddFunction DancingSteelExpiresRipMultiplier
{
    if BuffPresent(DANCING_STEEL any=1)
   {
      if DancingSteelRakeUsableBeforeExpire() 1
      unless DancingSteelRakeUsableBeforeExpire() {RipTickDamage() / {{{112.76 + {320 * ComboPoints()} + {0.0484 * {AttackPower()-DancingSteelAttackPowerIncrease()}} * ComboPoints()} * DamageMultiplier(RIP) * {1+{{MeleeCritChance()-DancingSteelCritChanceIncrease()}/100}}} * {1 + Mastery()/100}}}
   }
   unless BuffPresent(DANCING_STEEL any=1)
   {
      1
   }   
}
AddFunction SoulCharmRipUsableBeforeExpire
{
    if Energy() >= EnergyForRip()
      BuffPresent(SOUL_CHARM any=1) and {BuffRemains(SOUL_CHARM any=1) > {0.2}} and BuffRemains(SOUL_CHARM any=1) > {SpellCooldown(RIP)+0.2}
   unless Energy() >= EnergyForRip()
      BuffPresent(SOUL_CHARM any=1) and {BuffRemains(SOUL_CHARM any=1) > {TimeTilEnergyForRip()+0.2} or BuffPresent(CLEARCASTING)} and BuffRemains(SOUL_CHARM any=1) > {SpellCooldown(RIP)+0.2}
}
AddFunction SoulCharmExpiresRipMultiplier
{
    if BuffPresent(SOUL_CHARM any=1)
   {
      if SoulCharmRipUsableBeforeExpire() 1
      unless SoulCharmRipUsableBeforeExpire() {RipTickDamage() / {{{112.76 + {320 * ComboPoints()} + {0.0484 * {AttackPower()-SoulCharmAttackPowerIncrease()}} * ComboPoints()} * DamageMultiplier(RIP) * {1+{{MeleeCritChance()-SoulCharmCritChanceIncrease()}/100}}} * {1 + Mastery()/100}}}
   }
   unless BuffPresent(SOUL_CHARM any=1)
   {
      1
   }   
}
AddFunction TotalRipMultiplier
{
    TigersFuryExpiresRipMultiplier()*DancingSteelExpiresRipMultiplier()*SoulCharmExpiresRipMultiplier()
}

# Ratio functions
AddFunction RakeRatio
{
    if TargetDebuffPresent(RAKE) {{100 * RakeTickDamage()/LastRakeTickDamage()}/TotalRakeMultiplier()}
    unless TargetDebuffPresent(RAKE) 100.0
}
AddFunction RipRatio
{
    if TargetDebuffPresent(RIP) {{100 * RipTickDamage()/LastRipTickDamage()}/TotalRipMultiplier()}
    unless TargetDebuffPresent(RIP) 100.0
}

# Ferocious Bite function
AddFunction FerociousBiteDamage # Switched to raw numbers in place of Damage(FEROCIOUS_BITE) for 5.3.4+ compatibility
{
   if {1.25+{MeleeCritChance()/100}} > 100
      {500 + 762 * ComboPoints() + 0.196 * AttackPower() * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE) * 2 * 2 * {1-ArmorReduction()}
   unless {1.25+{MeleeCritChance()/100}} > 100
      {500 + 762 * ComboPoints() + 0.196 * AttackPower() * ComboPoints()} * DamageMultiplier(FEROCIOUS_BITE)  * {1.25+{MeleeCritChance()/100}} * 2 * {1-ArmorReduction()}
}


# 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 ComboPoints() ==0 {
            if BuffRemains(SAVAGE_ROAR_GLYPHED) <15 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-11.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <9 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-8.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <6 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-5.5
            or BuffRemains(SAVAGE_ROAR_GLYPHED) <3 and TimeToMaxEnergy() < BuffRemains(SAVAGE_ROAR_GLYPHED)-2.5
            or BuffExpires(SAVAGE_ROAR_GLYPHED) {
                SavageRoar()
            }
        }
        if TalentPoints(FORCE_OF_NATURE_TALENT) Spell(FORCE_OF_NATURE)
    }
}

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

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

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

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

AddFunction MainActionsDoC
{
    #auto_attack
   
    #healing_touch,if=buff.predatory_swiftness.up&buff.predatory_swiftness.remains<=1.5&buff.dream_of_cenarius_damage.down
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) and BuffPresent(PREDATORY_SWIFTNESS) and BuffRemains(PREDATORY_SWIFTNESS) <=1.5 and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) Spell(HEALING_TOUCH)
   
    #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()
   
    #healing_touch,if=buff.predatory_swiftness.up&combo_points>=4&buff.dream_of_cenarius_damage.down
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) and BuffPresent(PREDATORY_SWIFTNESS) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and ComboPoints() >=4 Spell(HEALING_TOUCH)
   
    #healing_touch,if=buff.natures_swiftness.up
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) and BuffPresent(NATURES_SWIFTNESS) Spell(HEALING_TOUCH)
   
    unless target.InRange(MANGLE_CAT) Texture(ability_druid_catformattack)
   
    #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)
   
    #ferocious_bite,if=combo_points>=1&dot.rip.ticking&dot.rip.remains<=3&target.health.pct<=25
    if target.HealthPercent() <=25 and ComboPoints() >=1 and target.DebuffPresent(RIP) and target.DebuffRemains(RIP) <=4 Spell(FEROCIOUS_BITE)
   
    #thrash_cat,if=target.time_to_die>=6&buff.omen_of_clarity.react&dot.thrash_cat.remains<3
    if target.TimeToDie() >=9 and BuffPresent(CLEARCASTING) and target.DebuffRemains(THRASH_CAT) <3 Spell(THRASH_CAT)
   
    #ferocious_bite,if=(target.time_to_die<=4&combo_points>=5)|(target.time_to_die<=1&combo_points>=3)
    if target.TimeToDie() <=4 and ComboPoints() >=5 Spell(FEROCIOUS_BITE)
    if target.TimeToDie() <=1 and ComboPoints() >=3 Spell(FEROCIOUS_BITE)
   
    if target.HealthPercent() <=25
    {
        #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&target.health.pct<25
        if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0 SavageRoar()
       
        if ComboPoints() >=5
        {
            #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&target.health.pct<=25
            if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS) and BuffRemains(SAVAGE_ROAR) >5 Spell(NATURES_SWIFTNESS)
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&$(rip_ratio)>=1.15&buff.dream_of_cenarius_damage.up
            if not HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=115 UsePotion()
           
            #virmens_bite_potion,if=combo_points>=5&$(time_til_bitw)<15&buff.rune_of_reorigination.up&buff.dream_of_cenarius_damage.up
            if HasTrinket(ROR_ITEM) and ComboPoints() >=5 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and BuffPresent(ROR_MASTERY) UsePotion()
           
            #virmens_bite_potion,if=target.time_to_die<=40
            if target.TimeToDie() <=40 UsePotion()
           
            #rip,line_cd=30,if=combo_points>=5&buff.virmens_bite_potion.up&buff.dream_of_cenarius_damage.up&target.health.pct<=25&target.time_to_die>30
            # Assume that FB will be 400% normal damage (100% increased damage + crit) to decide if we should overwrite Rip.
            if RipDamageTillDead() > {ExistingRipDamageTillDead() + FerociousBiteDamage()} Spell(RIP)
         
         
           
            #pool_resource,wait=0.25,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))
            #ferocious_bite,if=combo_points>=5&dot.rip.ticking&target.health.pct<=25
            if target.DebuffPresent(RIP)
            {
                unless {{BuffExpires(BERSERK_CAT) and Energy() >=50} or {BuffPresent(BERSERK_CAT) and Energy() >=25}} SpareGcdCooldowns()
                wait if {BuffExpires(BERSERK_CAT) and Energy() >=50} or {BuffPresent(BERSERK_CAT) and Energy() >=25} Spell(FEROCIOUS_BITE)
            }
        }
    }
   
    if RuneRipUsableBeforeExpire() and target.HealthPercent() >25 and ComboPoints() >=5 and target.TimeToDie() >30 and RipRatio() >=92
    {
        #natures_swiftness,if=enabled&buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&$(rip_ratio)>=0.92&target.time_to_die>30
        if TalentPoints(DREAM_OF_CENARIUS_TALENT) and BuffRemains(ROR_MASTERY) >1.5 and TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE) and BuffExpires(PREDATORY_SWIFTNESS) Spell(NATURES_SWIFTNESS)
     
        #rip,if=combo_points>=5&$(rip_ratio)>=1.15&target.time_to_die>30
        if RipRatio() >= 115 Spell(RIP)
   }
   
    #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2&buff.dream_of_cenarius_damage.up
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) and target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <2 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) Spell(RIP)
   
    #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<6.0&buff.dream_of_cenarius_damage.up&dot.rip.multiplier<=tick_multiplier
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) and target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RipRatio() >=100 Spell(RIP)
   
    #natures_swiftness,if=buff.dream_of_cenarius_damage.down&buff.predatory_swiftness.down&combo_points>=5&dot.rip.remains<3&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
    if TalentPoints(DREAM_OF_CENARIUS_TALENT) and TalentPoints(NATURES_SWIFTNESS_TALENT) and BuffExpires(DREAM_OF_CENARIUS_DAMAGE)
    and BuffExpires(PREDATORY_SWIFTNESS) and ComboPoints() >=5 and target.DebuffRemains(RIP) <3
    and {BuffPresent(BERSERK_CAT) or {target.DebuffRemains(RIP)+1.9} <= SpellCooldown(TIGERS_FURY)}
    {
        Spell(NATURES_SWIFTNESS)
    }
   
    #rip,if=combo_points>=5&target.time_to_die>=6&dot.rip.remains<2&(buff.berserk.up|dot.rip.remains+1.9<=cooldown.tigers_fury.remains)
    if target.TimeToDie() >=6 and ComboPoints() >=5 and target.DebuffRemains(RIP) <2
    {
        Spell(RIP)
    }
   
    #savage_roar,if=buff.savage_roar.remains<=3&combo_points>0&buff.savage_roar.remains+2>dot.rip.remains
    if BuffRemains(SAVAGE_ROAR) <=3 and ComboPoints() >0 and {BuffRemains(SAVAGE_ROAR) +2 > target.DebuffRemains(RIP)} SavageRoar()
   
    #savage_roar,if=buff.savage_roar.remains<=6&combo_points>=5&buff.savage_roar.remains+2<=dot.rip.remains
    if BuffRemains(SAVAGE_ROAR) <=6 and ComboPoints() >=5 and {BuffRemains(SAVAGE_ROAR) +2 <= target.DebuffRemains(RIP)} SavageRoar()
   
    #actions.doc+=/pool_resource,wait=0.1,if=combo_points>=5&((energy<50&buff.berserk.down)|(energy<25&buff.berserk.remains>1))&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)
    #actions.doc+=/ferocious_bite,if=combo_points>=5&dot.rip.ticking&!(dot.rip.remains-2<=energy.time_to_max-1)&!(buff.savage_roar.remains-3<=energy.time_to_max-1)&!((buff.savage_roar.remains-6<=energy.time_to_max-1)&buff.savage_roar.remains+2<=$(rip_remains))
    if ComboPoints() >=5 and target.DebuffPresent(RIP) and BuffPresent(SAVAGE_ROAR)
    and not target.DebuffRemains(RIP)-2 <= TimeToMaxEnergy()-1
    and not BuffRemains(SAVAGE_ROAR)-3 <= TimeToMaxEnergy()-1
    and not {BuffRemains(SAVAGE_ROAR)-6 <= TimeToMaxEnergy()-1
        and BuffRemains(SAVAGE_ROAR)+2 <= target.DebuffRemains(RIP)}
    and target.DebuffRemains(RIP) >=5
    {
        unless {{BuffExpires(BERSERK_CAT) and Energy() >=50} or {BuffPresent(BERSERK_CAT) and Energy() >=25}} SpareGcdCooldowns()
        wait if {BuffExpires(BERSERK_CAT) and Energy() >=50} or {BuffPresent(BERSERK_CAT) and Energy() >=25} Spell(FEROCIOUS_BITE)
    }
   
    if target.TimeToDie() - target.DebuffRemains(RAKE) >3
    {
      if RuneRakeUsableBeforeExpire()
      {
         #rake,if=buff.rune_of_reorigination.up&$(rake_ratio)>=1
            if RakeRatio() >=100 Spell(RAKE)
      
            #rake,if=buff.rune_of_reorigination.up&dot.rake.remains<9&(buff.rune_of_reorigination.remains<=1.5)
            if target.DebuffRemains(RAKE) <9 and BuffRemains(ROR_MASTERY) <=1.5 Spell(RAKE)
      }
      if {RuneRakeUsableBeforeExpire() or not BuffPresent(ROR_MASTERY)}
      {
         #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 TalentPoints(DREAM_OF_CENARIUS_TALENT) and target.DebuffRemains(RAKE) <6 and BuffPresent(DREAM_OF_CENARIUS_DAMAGE) and RakeRatio() >=100 Spell(RAKE)
         
         #rake,if=target.time_to_die-dot.rake.remains>3&tick_multiplier%dot.rake.multiplier>1.12
         if RakeRatio() >=112 Spell(RAKE)
      }
         #rake,if=target.time_to_die-dot.rake.remains>3&dot.rake.remains<3.0&(buff.berserk.up|(cooldown.tigers_fury.remains+0.8)>=dot.rake.remains|energy>60)
         if {Energy() < EnergyForRake() and target.DebuffRemains(RAKE) < 3 + TimeTilEnergyForRake()}
            or {Energy() >= EnergyForRake() and target.DebuffRemains(RAKE) < 3}
            Spell(RAKE)
   }
   
    #pool_resource,wait=0.25,for_next=1
    #thrash_cat,if=dot.thrash_cat.remains<3&target.time_to_die>=6&(dot.rip.remains>=4|buff.berserk.up)
   if {Energy() < EnergyForThrash() and target.DebuffRemains(THRASH_CAT) < {3 + TimeTilEnergyForThrash()}
      and target.TimeToDie() - TimeTilEnergyForThrash() >=9
      and {target.DebuffRemains(RIP) - TimeTilEnergyForThrash() >=4
         or BuffPresent(BERSERK_CAT)}}
   or {Energy() >= EnergyForThrash() and target.DebuffRemains(THRASH_CAT) < {3}
      and target.TimeToDie() >=9
      and {target.DebuffRemains(RIP) >=4
         or BuffPresent(BERSERK_CAT)}}
    {
        #if TimeTilEnergyForThrash() >=1.5 SpareGcdCooldowns()
        wait if {BuffExpires(BERSERK_CAT) and Energy() >=50} or {BuffPresent(BERSERK_CAT) and Energy() >=25} Spell(THRASH_CAT)
    }
}

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

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

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

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

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


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

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

# Main rotation
AddIcon help=main mastery=2 {
    NotInCombat()
    if Stance(3) {
        if TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditionsDoC()
            SpareGcdCooldowns()
        }
        unless TalentPoints(DREAM_OF_CENARIUS_TALENT)
        {
            MainActionsDoC()
            FillerConditionsDoC()
            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)
}



Of note vs the base leafkiller's script:

- Buff Expiration support (Rune, heroic TF Renataki's, Dancing Steel and Tiger's Fury)
For everything but the rune, the script calculates the benefits of the buff, and if its going to expire before you can use a bleed, take the buff out of the appropriate ratio. For the Rune anywhere we'd test for the buff before now has an additional check to ensure we can use a bleed before rune expires. The logic should work for any trinket really but every trinket must be added manually. Not sure if its worth it for a general purpose script (maybe just use Rune, TF and Dancing Steel since those are all unaffected by ilvl of the trinket).
Example: If Tiger's Fury has 1 second left and you have only 5 energy, the Rip/Rake ratios will be as if you do not have the Tiger's Fury buff
- CritChance functions (this has been added to base ovale so I'll be removing these once there's a stable release [I can't get the bleed snapshots to work so I can't use that version yet])
Used for bleed snapshotting as well as estimating 50 energy Ferocious Bite damage
- Armor function (note I had used target dummies as my level 90 armor point last time and they do NOT have the same armor as typical level 90 mobs so if you used it before, its inaccurate)
Accurate for level 90 and boss level enemies, everything else is estimated linearly from those two data points. Used for Ferocious Bite damage calculations currently and Mangle/Shred calculations in the future.
- Smoother Prediction box (Thrash will now actually show up)
Ovale has some peculiarities where some calculations seem to interfere with it displaying the icon at times. Of note I moved the energy check out of the TimeTilEnergy functions and instead tested for it everytime they are used within the main function. The reason for this is the icon would only properly show if you did NOT have the energy for the appropriate ability but would show if you did. By testing for it outside and then not using the TimeTilEnergy functions (since we know they would be zero in this case) it fixes this problem. Should make more sense when you look at the code as I did a crummy job explaining.
- Removed waiting for TF logic from Rip/Rake
While mathematically a DPS upgrade, Simcraft showed that these are <100 DPS each (actually within the margin of error) and so I removed them rather than trying to fix their functionality (where it'd show Rip and then switch away from it while TF was coming off cooldown due to not having energy to Rip in time before you reached 1.9 seconds on the cooldown).
- DoC and non-DoC merged under one script.
May need to be re-split in the future, but at the moment a simple talent check in front of all DoC specific lines suffices. Allowed me to tinker with stuff without having to go and update and test within two scripts. Changes to the MainActions portion of the script were actually fairly minimal, mostly to do with the updated Rune functionality and Thrash

EDIT: Was a brace out of place before 7:22 pm eastern. Fixed now

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Tue Jul 09, 2013 11:55 pm

Schmoo that script for some reason outputs into my general chat log, drops my fps to 4, and then breaks. IDK what it wrong
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Tinderhoof » Wed Jul 10, 2013 12:14 am

I have seen no issues with it so far.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Wed Jul 10, 2013 12:57 am

EDIT: Reverting to 5.3.2 of Ovale fixed the issue. Thanks for the hard work Schmoo. Won't be able to test it fully until raid tomorrow night but looks good.
Image

Honored
Posts: 62
Joined: Fri May 28, 2010 5:44 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Andanas » Wed Jul 10, 2013 12:09 pm

While running Shmoo's script, in LFR, I noticed something that was odd, at least to me. I don't think it ever suggested overwriting a current bleed with a better one, even during a rune proc. It would only suggest a new rake (for example) when the current one was about to expire. Now this could be an issue on my end. I use DroodFocus to track my bleeds, and dots power to track the potential strength of a bleed. I have my threshold set at the default of 12%. Is this to low? I'm not sure how Smoo has it set up in the script.

Other than that, I didn't notice any other issues.

EDIT: I tried it again (on a training dummy this time) using 15%, and 17% dots power threshold, and I didn't notice any difference.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Wed Jul 10, 2013 3:48 pm

I had issues last night but that was tied to using 5.3.5 of Ovale. Make sure you are using 5.3.2 here http://www.curse.com/addons/wow/ovale/716353

I just tested on a dummy and it was suggesting a new rake everytime i got another Renataki's stack if I didn't have TF up for the previous stacks and suggested a new Rip if Rune proc'd
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Wed Jul 10, 2013 4:34 pm

Steakbomb wrote:I had issues last night but that was tied to using 5.3.5 of Ovale. Make sure you are using 5.3.2 here http://www.curse.com/addons/wow/ovale/716353

I just tested on a dummy and it was suggesting a new rake everytime i got another Renataki's stack if I didn't have TF up for the previous stacks and suggested a new Rip if Rune proc'd


Yeah, it has to be 5.3.2, the bleed snapshotting calls don't seem to work in 5.3.4 (not for me anyhow) and so the ratios will always be 100% which virtually disables half the script.

Honored
Posts: 62
Joined: Fri May 28, 2010 5:44 am

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Andanas » Wed Jul 10, 2013 5:31 pm

yea reverting 5.3.2 made the difference. Thanks.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Jeshu » Thu Jul 11, 2013 3:21 pm

ShmooDude wrote:
Steakbomb wrote:I had issues last night but that was tied to using 5.3.5 of Ovale. Make sure you are using 5.3.2 here http://www.curse.com/addons/wow/ovale/716353

I just tested on a dummy and it was suggesting a new rake everytime i got another Renataki's stack if I didn't have TF up for the previous stacks and suggested a new Rip if Rune proc'd


Yeah, it has to be 5.3.2, the bleed snapshotting calls don't seem to work in 5.3.4 (not for me anyhow) and so the ratios will always be 100% which virtually disables half the script.


The LastSpell* conditions were not working properly because the stat snapshots for the spellcasts were not being saved properly. This should be fixed in the next release of Ovale later today.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Jul 11, 2013 4:12 pm

Jeshu wrote:The LastSpell* conditions were not working properly because the stat snapshots for the spellcasts were not being saved properly. This should be fixed in the next release of Ovale later today.


Awesome, thanks. Lookin' forward to taking advantage of that and the weapondamage functions.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Steakbomb » Thu Jul 11, 2013 8:28 pm

ShmooDude wrote:
Jeshu wrote:The LastSpell* conditions were not working properly because the stat snapshots for the spellcasts were not being saved properly. This should be fixed in the next release of Ovale later today.


Awesome, thanks. Lookin' forward to taking advantage of that and the weapondamage functions.


Does this mean you will be updating your script to reflect changes or is your script good to go with the extra features?
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Thu Jul 11, 2013 9:59 pm

Steakbomb wrote:Does this mean you will be updating your script to reflect changes or is your script good to go with the extra features?


Probably will require updating as the bleed snapshotting is now target based instead of last spell based (though it may still function with the old method, depends on if those functions were left in for backwards compatability), shouldn't take too much work overall.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby aggixx » Fri Jul 12, 2013 5:24 am

Just wanted to say thanks for implementing those changes Jeshu, and I appreciate your work on the script as well ShmooDude. I've been very busy the past week or two and haven't had a ton of time to work on looking the stuff over. I hope to get some/all of the changes included in the official version sometime this weekend.
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby ShmooDude » Sat Jul 13, 2013 9:55 am

Now that weapon damage is able to be calculated (its off by like <0.3% so I'm not gonna worry about it, probably due to some truncation somewhere), I replaced both ratio based rake lines with the following (as I saw it in simcraft under the non-doc section; tested it and it works maybe a smidge better in the doc section too):

#rake,if=(tick_damage-tick_dmg)*5+tick_damage>action.mangle_cat.hit_damage
if RakeTickDamage()*6 - LastRakeTickDamage()*5 >= MangleCatDamage()

Would people prefer it this way (tiny dps up, ~100 dps) or would the ratios be better because its what we're looking at/used to? (at least I have the ratio boxes open)

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby aggixx » Sat Jul 13, 2013 11:38 am

ShmooDude wrote:Would people prefer it this way (tiny dps up, ~100 dps) or would the ratios be better because its what we're looking at/used to? (at least I have the ratio boxes open)

The difference should be pretty negligible, on both counts.
Image

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Kihrawr » Sat Jul 13, 2013 12:00 pm

I started experimenting with Shmoodude's version of the script. One question I had about its behavior is with Thrash. One of the things that seems to be happening is that I get a Rune proc, and I would have just enough time to get a Rip up, but the script suggests that I Thrash instead of building combo points. This is presumably because Clearcasting is up, so it doesn't waste Energy, but it does cost a GCD. I then don't have time to get the Rip off before the Rune proc fades.

Basically I'm wondering if the script is taking into account the time remaining on the Rune proc before suggesting Thrash, since it pushes back your ability to get Rip up. I'm also assuming getting a Rip up would be more of a DPS gain than Thrashing for single target, but maybe I'm wrong about that.

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

Re: Leafkiller's MoP Feral/Guardian Ovale Script

Postby Kihrawr » Sat Jul 13, 2013 12:06 pm

Another question I had. Why do all of these scripts suggest Healing Touch after Tiger's Fury instead of before? I would have thought that Healing Touch first would be better so you don't waste the GCD while Tiger's Fury is up?

PreviousNext

Return to Kitty DPS

Who is online

Users browsing this forum: Bing [Bot], Google Adsense [Bot], Kraineth, óak and 7 guests