Commits

Anonymous committed 2bf74c6

Fixing Tiger's Fury CD display to not include lag.

  • Participants
  • Parent commits 7ce35e1
  • Tags v5.1.0.2

Comments (0)

Files changed (1)

-
    local cost = FBNLite.cost
    local OoC = 0;
    local lgcd = st.lag + st.GCD
    -- not feral
    if (cost.sr == nil) then
        return "empty"
    end
    local berserkAndRipCheck = (st.berserk > lgcd or st.rip + 1.9 < st.tfCd)
    local maxExtendedRip = 0
    if (st.rip > lgcd) then
        maxExtendedRip = st.rip + 2 * st.canExtendRip
    end
    if (st.OoC > lgcd) then OoC = 1 end
    if (st.docEnabled and st.ps < 1.5 + lgcd and st.ps > lgcd and st.docStacks < 2) then
        return "Healing Touch"
    elseif (st.sr < 1 + lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.docEnabled and st.ps > lgcd and st.cp > 3 and st.docStacks < 2) then
        return "Healing Touch"
    elseif (st.docEnabled and st.nsActive and st.docStacks < 2) then
        return "Healing Touch"
    elseif (st.energy <= 35 and OoC == 0 and st.tfCd < st.lag and st.berserk < st.lag) then
        return "Tiger's Fury"
    -- below 25%, rip about to fall off, at least 1 cp --> FB
    elseif (st.cp > 0 and st.bitwActive and st.rip < lgcd + 2 and st.rip > lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    -- keep Faerie Fire up only on targets that are at least one level above you
    elseif (st.bossTarget and (st.weakenedArmor < lgcd or st.weakenedArmorStacks < 3) and st.ffCd < lgcd) then
        return "Faerie Fire"
    elseif (OoC == 1 and st.thrashCat < 3 + lgcd and st.docStacks == 0) then
        return "Thrash (Cat)"
    elseif (st.sr < 3 + lgcd and st.cp > 0 and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.docEnabled and st.docStacks == 0 and st.ps < lgcd and st.cp == 5 and st.bitwActive and st.nsCd < lgcd) then
        return "Nature's Swiftness"
    elseif (st.bossTarget and (st.agiPotCd < lgcd and st.bitwActive) and ((st.docStacks > 0 and st.cp == 5) or (not st.docEnabled and st.berserk > lgcd))) then
        return "Agility Potion"
    elseif (st.cp == 5 and st.agiPot > lgcd and st.docStacks > 0 and st.ripPower < st.predictedRipPower and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.cp == 5 and (st.predictedRipPower / st.ripPower) > 1.14 and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.cp == 5 and st.rip > lgcd and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    elseif (st.cp == 5 and st.rip < 2 + lgcd and st.docStacks > 0) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.cp == 5 and st.rip < 6 + lgcd and st.docStacks > 0 and st.ripPower < st.predictedRipPower and not st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.sr < 3 + lgcd and st.cp > 0 and ((st.docEnabled and st.docStacks == 0) or (not st.docEnabled and not (st.rip < 2 + lgcd and st.cp == 5 and berserkAndRipCheck)))) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.docEnabled and st.docStacks == 0 and st.nsCd < lgcd and st.ps < lgcd and st.cp == 5 and st.rip < 3 + lgcd and not st.bitwActive and berserkAndRipCheck) then
        return "Nature's Swiftness"
    elseif (st.cp == 5 and st.rip < 2 + lgcd and berserkAndRipCheck) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (OoC == 1 and st.thrashCat < 3 + lgcd) then
        return "Thrash (Cat)"
    elseif (st.canExtendRip > 0 and st.rip < 4 + lgcd and st.rip > lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    elseif (st.sr < 6 + lgcd and st.cp == 5 and ((maxExtendedRip > 6 + lgcd and (st.sotfEnabled or st.berserk > lgcd)) or maxExtendedRip > 10) and st.rip > lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.cp == 5 and maxExtendedRip > 6 + lgcd and (st.sotfEnabled or st.berserk > lgcd)) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    elseif (st.cp == 5 and maxExtendedRip > 10 + lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    elseif (st.rake < 6 + lgcd and st.docStacks > 0 and st.rakePower < st.predictedRakePower) then
        return FBNLite:HaveEnoughEnergyFor("Rake", st, cost.rake)
    elseif (st.predictedRakePower / st.rakePower > 1.12) then
        return FBNLite:HaveEnoughEnergyFor("Rake", st, cost.rake)
    elseif (st.rake < 3 + lgcd and (st.berserk > lgcd or st.tfCd + 0.8 > st.rake or st.energy > 60)) then
        return FBNLite:HaveEnoughEnergyFor("Rake", st, cost.rake)
    elseif (OoC == 1) then
        return "Shred"
    elseif (st.ps > 1 + lgcd and not (st.energy + st.eps * (st.ps - 1) < (4 - st.cp) * 20)) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    elseif ((st.cp < 5 and st.rip < 3 + lgcd) or (st.cp == 0 and st.sr < 2 + lgcd)) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    elseif (st.cp == 5 and st.thrashCat < 6 + lgcd and (st.tf > lgcd or st.berserk > lgcd or st.tfCd < 3 or st.energy + st.eps * (1 + lgcd) > 100)) then
        return FBNLite:HaveEnoughEnergyFor("Thrash (Cat)", st, cost.thrashCat)
    elseif (st.tf > lgcd or st.berserk > lgcd or st.tfCd < 3 or st.energy + st.eps * (1 + lgcd) > 100) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    else
        return "empty"
    end
    local lgcd = st.lag + st.GCD
    local spellToReturn
    if (st.energy + lgcd * st.eps >= spellCost or (spellCost == 0 and (st.OoC > lgcd))) then
        spellToReturn = spell
    else
        spellToReturn = "empty"
    end
    myDebug("Spell: ", spell, "SpellToReturn: ", spellToReturn)
    return spellToReturn
    local st = table.copy(state)
    local targetGuid = UnitGUID("target")
    local ripStats = FBNLite.Rips[targetGuid]
    if ripStats then
        st.canExtendRip = 3 - ripStats.shredsOnRip
        st.ripPower = ripStats.power
    else
        st.ripPower = 1
        st.canExtendRip = 0
    end
    local rakePower = FBNLite.Rakes[targetGuid]
    if rakePower then
        st.rakePower = rakePower
    else
        st.rakePower = 1
    end
    st.predictedRipPower = FBNLite:GetRipPower()
    st.predictedRakePower = FBNLite:GetRakePower()
    
    st.energy = UnitPower("player", 3)
    st.cp = GetComboPoints("player")
    st.rake = FBNLite:GetRemainingDebuffTimeAndStacks(true, "Rake")
    st.rip = FBNLite:GetRemainingDebuffTimeAndStacks(true, "Rip")
    st.sr = FBNLite:GetRemainingBuffTime("Savage Roar")
    st.tfCd = FBNLite:GetSpellCD("Tiger's Fury")
    st.tf = FBNLite:GetRemainingBuffTime("Tiger's Fury")
    st.eps = 10 * (1 + GetCombatRating(18) / 3279)
    st.thrashCat = FBNLite:GetRemainingDebuffTimeAndStacks(true, "Thrash (Cat)")
    st.ps = FBNLite:GetRemainingBuffTime("Predatory Swiftness")
    st.agiPot = FBNLite:GetRemainingBuffTime("Agility Potion")
    st.agiPotCd = FBNLite:GetItemCD("Agility Potion")
    -- get suggested spell
    spell = FBNLite:NextCatformSpell(st)
    local dbg = FBNLite.debug
    FBNLite.debug = false
    -- get +1 move prediction
    if FBNLiteDB.showPrediction then
        -- a special case for TF since it is off GCD and adds energy
        if spell == "Agility Potion" then
            -- First slot shows suggestion if we decide to use agi potion
            st.agiPot = 25
            st.agiPotCd = 60
            nextSpell1CP = FBNLite:NextCatformSpell(st)
            -- Second slot show suggestion if we decide not to use agi potion
            st.agiPot = 0
            nextSpell2CP = FBNLite:NextCatformSpell(st)
        elseif spell == "Tiger's Fury" then
            -- Add energy and adjust timers by a reaction time (well, by a lag since that is bigger factor...)
            FBNLite:AdjustKeys(st, 60 + st.lag * st.eps, "energy")
            FBNLite:AdjustKeys(st, 30 - st.tfCd, "tfCd")
            FBNLite:AdjustKeys(st, 6 - st.tf, "tf")
            FBNLite:AdjustKeys(st, -st.lag, "rake", "rip", "sr", "tfCd", "tf", "ffCd", "weakenedArmor", "berserkCd", "berserk", "OoC", "thrashCat", "ps", "agiPot", "agiPotCd")
            nextSpell1CP = FBNLite:NextCatformSpell(st)
            nextSpell2CP = nextSpell1CP
        elseif (spell == "Healing Touch") then
            st.energy = st.energy + st.eps
            if (st.docEnabled) then
                st.docStacks = 2
            end
            FBNLite:AdjustKeys(st, -1, "rake", "rip", "sr", "tfCd", "tf", "ffCd", "weakenedArmor", "berserkCd", "berserk", "OoC", "thrashCat", "ps", "agiPot", "agiPotCd")
        elseif (spell == "Nature's Swiftness") then
            st.nsActive = true
        else
            -- compute energy discount coefficient
            local OoC = 1
            if (st.OoC > 0) then OoC = 0 end
            -- We are 1 second (= 1 GCD) ahead, decrease remaining time on buffs,
            -- debuffs and CDs by 1 second and increase available energy by 10.
            FBNLite:AdjustKeys(st, -1, "rake", "rip", "sr", "tfCd", "tf", "ffCd", "weakenedArmor", "berserkCd", "berserk", "OoC", "thrashCat", "ps", "agiPot", "agiPotCd")
            FBNLite:AdjustKeys(st, st.eps, "energy")
            FBNLite:AdjustKeys(st, -st.OoC, "OoC")
            
            if (st.rake <= 0) then
                st.rakePower = 1
            end
            
            if (st.rip <= 0) then
                st.ripPower = 1
            end
            
            -- cp generators
            if spell == "Shred" or spell == "Rake" then
                if spell == "Shred" then
                    if (st.canExtendRip > 0) then
                        st.rip = st.rip + 2
                        st.canExtendRip = st.canExtendRip - 1
                    end
                    st.energy = st.energy - FBNLite.cost.shred * OoC
                elseif spell == "Rake" then
                    st.rake = st.rake + 15
                    st.energy = st.energy - FBNLite.cost.rake * OoC
                    st.rakePower = st.predictedRakePower
                end
                if (st.docStacks > 0) then
                    st.docStacks = st.docStacks - 1
                end
                -- 1 cp
                st.cp = st.cp + 1
                nextSpell1CP = FBNLite:NextCatformSpell(st)
                -- 2 cps
                st.cp = st.cp + 1
                nextSpell2CP = FBNLite:NextCatformSpell(st)
            -- non-cp generating abilities: finishers, energy pooling and faerie fire
            else
                if spell == "Faerie Fire" then
                    st.weakenedArmor = 30
                    st.weakenedArmorStacks = 3
                    st.ffCd = 6
                -- finishers, no need to do anything special for energy pooling ("empty")
                elseif spell ~= "empty" then
                    -- Set cp to 0 or < 0 if we did sr with less than 5cps.
                    local energyRefund = st.cp * 4
                    st.cp = 0
                    if spell == "Rip" then
                        st.rip = 16
                        st.energy = st.energy - FBNLite.cost.rip * OoC + energyRefund
                        st.ripPower = st.predictedRipPower
                        if (st.docStacks > 0) then
                            st.docStacks = st.docStacks - 1
                        end
                    elseif spell == "Savage Roar" then
                        st.sr = 12 + st.cp * 6
                        -- no OoC discount since Savage Roar ignores OoC!
                        st.energy = st.energy - FBNLite.cost.sr + energyRefund
                    elseif spell == "Ferocious Bite" then
                           if (st.docStacks > 0) then
                            st.docStacks = st.docStacks - 1
                        end
                        st.energy = st.energy -(FBNLite.cost.fb * OoC + math.min(25, st.energy - FBNLite.cost.fb * OoC)) + energyRefund
                    end
                end
                -- Get next ability. Maybe it would look better if the second was empty?
                nextSpell1CP = FBNLite:NextCatformSpell(st)
                nextSpell2CP = nextSpell1CP
            end
        end
    end
    FBNLite.debug = dbg
    -- update textures
    FBNLite:SetSpellTexture("topleft", "Tiger's Fury", st.tfCd < st.lag)
    FBNLite:SetSpellTexture("bottomleft", "Berserk", st.berserkCd < st.lag + st.GCD)
    SetSpellOrItemTexture("middle", spell, spell ~= "empty")
    SetSpellOrItemTexture("topright", nextSpell1CP, nextSpell1CP ~= "empty")
    SetSpellOrItemTexture("bottomright", nextSpell2CP, nextSpell2CP ~= "empty")
    FBNLite:UpdateGcdFrame(spell)
    if (FBNLite.Items[spellOrItem] ~= nil) then
        FBNLite:SetItemTexture(frame, spellOrItem, condition)
    else
        FBNLite:SetSpellTexture(frame, spellOrItem, condition)
    end
+
    local cost = FBNLite.cost
    local OoC = 0;
    local lgcd = st.lag + st.GCD
    -- not feral
    if (cost.sr == nil) then
        return "empty"
    end
    local berserkAndRipCheck = (st.berserk > lgcd or st.rip + 1.9 < st.tfCd)
    local maxExtendedRip = 0
    if (st.rip > lgcd) then
        maxExtendedRip = st.rip + 2 * st.canExtendRip
    end
    if (st.OoC > lgcd) then OoC = 1 end
    if (st.docEnabled and st.ps < 1.5 + lgcd and st.ps > lgcd and st.docStacks < 2) then
        return "Healing Touch"
    elseif (st.sr < 1 + lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.docEnabled and st.ps > lgcd and st.cp > 3 and st.docStacks < 2) then
        return "Healing Touch"
    elseif (st.docEnabled and st.nsActive and st.docStacks < 2) then
        return "Healing Touch"
    elseif (st.energy <= 35 and OoC == 0 and st.tfCd < st.lag and st.berserk < st.lag) then
        return "Tiger's Fury"
    -- below 25%, rip about to fall off, at least 1 cp --> FB
    elseif (st.cp > 0 and st.bitwActive and st.rip < lgcd + 2 and st.rip > lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    -- keep Faerie Fire up only on targets that are at least one level above you
    elseif (st.bossTarget and (st.weakenedArmor < lgcd or st.weakenedArmorStacks < 3) and st.ffCd < lgcd) then
        return "Faerie Fire"
    elseif (OoC == 1 and st.thrashCat < 3 + lgcd and st.docStacks == 0) then
        return "Thrash (Cat)"
    elseif (st.sr < 3 + lgcd and st.cp > 0 and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.docEnabled and st.docStacks == 0 and st.ps < lgcd and st.cp == 5 and st.bitwActive and st.nsCd < lgcd) then
        return "Nature's Swiftness"
    elseif (st.bossTarget and (st.agiPotCd < lgcd and st.bitwActive) and ((st.docStacks > 0 and st.cp == 5) or (not st.docEnabled and st.berserk > lgcd))) then
        return "Agility Potion"
    elseif (st.cp == 5 and st.agiPot > lgcd and st.docStacks > 0 and st.ripPower < st.predictedRipPower and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.cp == 5 and (st.predictedRipPower / st.ripPower) > 1.14 and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.cp == 5 and st.rip > lgcd and st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    elseif (st.cp == 5 and st.rip < 2 + lgcd and st.docStacks > 0) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.cp == 5 and st.rip < 6 + lgcd and st.docStacks > 0 and st.ripPower < st.predictedRipPower and not st.bitwActive) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (st.sr < 3 + lgcd and st.cp > 0 and ((st.docEnabled and st.docStacks == 0) or (not st.docEnabled and not (st.rip < 2 + lgcd and st.cp == 5 and berserkAndRipCheck)))) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.docEnabled and st.docStacks == 0 and st.nsCd < lgcd and st.ps < lgcd and st.cp == 5 and st.rip < 3 + lgcd and not st.bitwActive and berserkAndRipCheck) then
        return "Nature's Swiftness"
    elseif (st.cp == 5 and st.rip < 2 + lgcd and berserkAndRipCheck) then
        return FBNLite:HaveEnoughEnergyFor("Rip", st, cost.rip)
    elseif (OoC == 1 and st.thrashCat < 3 + lgcd) then
        return "Thrash (Cat)"
    elseif (st.canExtendRip > 0 and st.rip < 4 + lgcd and st.rip > lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    elseif (st.sr < 6 + lgcd and st.cp == 5 and ((maxExtendedRip > 6 + lgcd and (st.sotfEnabled or st.berserk > lgcd)) or maxExtendedRip > 10) and st.rip > lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Savage Roar", st, cost.sr)
    elseif (st.cp == 5 and maxExtendedRip > 6 + lgcd and (st.sotfEnabled or st.berserk > lgcd)) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    elseif (st.cp == 5 and maxExtendedRip > 10 + lgcd) then
        return FBNLite:HaveEnoughEnergyFor("Ferocious Bite", st, cost.fb)
    elseif (st.rake < 6 + lgcd and st.docStacks > 0 and st.rakePower < st.predictedRakePower) then
        return FBNLite:HaveEnoughEnergyFor("Rake", st, cost.rake)
    elseif (st.predictedRakePower / st.rakePower > 1.12) then
        return FBNLite:HaveEnoughEnergyFor("Rake", st, cost.rake)
    elseif (st.rake < 3 + lgcd and (st.berserk > lgcd or st.tfCd + 0.8 > st.rake or st.energy > 60)) then
        return FBNLite:HaveEnoughEnergyFor("Rake", st, cost.rake)
    elseif (OoC == 1) then
        return "Shred"
    elseif (st.ps > 1 + lgcd and not (st.energy + st.eps * (st.ps - 1) < (4 - st.cp) * 20)) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    elseif ((st.cp < 5 and st.rip < 3 + lgcd) or (st.cp == 0 and st.sr < 2 + lgcd)) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    elseif (st.cp == 5 and st.thrashCat < 6 + lgcd and (st.tf > lgcd or st.berserk > lgcd or st.tfCd < 3 or st.energy + st.eps * (1 + lgcd) > 100)) then
        return FBNLite:HaveEnoughEnergyFor("Thrash (Cat)", st, cost.thrashCat)
    elseif (st.tf > lgcd or st.berserk > lgcd or st.tfCd < 3 or st.energy + st.eps * (1 + lgcd) > 100) then
        return FBNLite:HaveEnoughEnergyFor("Shred", st, cost.shred)
    else
        return "empty"
    end
    local lgcd = st.lag + st.GCD
    local spellToReturn
    if (st.energy + lgcd * st.eps >= spellCost or (spellCost == 0 and (st.OoC > lgcd))) then
        spellToReturn = spell
    else
        spellToReturn = "empty"
    end
    myDebug("Spell: ", spell, "SpellToReturn: ", spellToReturn)
    return spellToReturn
    local st = table.copy(state)
    local targetGuid = UnitGUID("target")
    local ripStats = FBNLite.Rips[targetGuid]
    if ripStats then
        st.canExtendRip = 3 - ripStats.shredsOnRip
        st.ripPower = ripStats.power
    else
        st.ripPower = 1
        st.canExtendRip = 0
    end
    local rakePower = FBNLite.Rakes[targetGuid]
    if rakePower then
        st.rakePower = rakePower
    else
        st.rakePower = 1
    end
    st.predictedRipPower = FBNLite:GetRipPower()
    st.predictedRakePower = FBNLite:GetRakePower()
    
    st.energy = UnitPower("player", 3)
    st.cp = GetComboPoints("player")
    st.rake = FBNLite:GetRemainingDebuffTimeAndStacks(true, "Rake")
    st.rip = FBNLite:GetRemainingDebuffTimeAndStacks(true, "Rip")
    st.sr = FBNLite:GetRemainingBuffTime("Savage Roar")
    st.tfCd = FBNLite:GetSpellCD("Tiger's Fury")
    st.tf = FBNLite:GetRemainingBuffTime("Tiger's Fury")
    st.eps = 10 * (1 + GetCombatRating(18) / 3279)
    st.thrashCat = FBNLite:GetRemainingDebuffTimeAndStacks(true, "Thrash (Cat)")
    st.ps = FBNLite:GetRemainingBuffTime("Predatory Swiftness")
    st.agiPot = FBNLite:GetRemainingBuffTime("Agility Potion")
    st.agiPotCd = FBNLite:GetItemCD("Agility Potion")
    -- get suggested spell
    spell = FBNLite:NextCatformSpell(st)
    local dbg = FBNLite.debug
    FBNLite.debug = false
    -- get +1 move prediction
    if FBNLiteDB.showPrediction then
        -- a special case for TF since it is off GCD and adds energy
        if spell == "Agility Potion" then
            -- First slot shows suggestion if we decide to use agi potion
            st.agiPot = 25
            st.agiPotCd = 60
            nextSpell1CP = FBNLite:NextCatformSpell(st)
            -- Second slot show suggestion if we decide not to use agi potion
            st.agiPot = 0
            nextSpell2CP = FBNLite:NextCatformSpell(st)
        elseif spell == "Tiger's Fury" then
            -- Add energy and adjust timers by a reaction time (well, by a lag since that is bigger factor...)
            FBNLite:AdjustKeys(st, 60 + st.lag * st.eps, "energy")
            FBNLite:AdjustKeys(st, 30 - st.tfCd, "tfCd")
            FBNLite:AdjustKeys(st, 6 - st.tf, "tf")
            FBNLite:AdjustKeys(st, -st.lag, "rake", "rip", "sr", "tfCd", "tf", "ffCd", "weakenedArmor", "berserkCd", "berserk", "OoC", "thrashCat", "ps", "agiPot", "agiPotCd")
            nextSpell1CP = FBNLite:NextCatformSpell(st)
            nextSpell2CP = nextSpell1CP
        elseif (spell == "Healing Touch") then
            st.energy = st.energy + st.eps
            if (st.docEnabled) then
                st.docStacks = 2
            end
            FBNLite:AdjustKeys(st, -1, "rake", "rip", "sr", "tfCd", "tf", "ffCd", "weakenedArmor", "berserkCd", "berserk", "OoC", "thrashCat", "ps", "agiPot", "agiPotCd")
        elseif (spell == "Nature's Swiftness") then
            st.nsActive = true
        else
            -- compute energy discount coefficient
            local OoC = 1
            if (st.OoC > 0) then OoC = 0 end
            -- We are 1 second (= 1 GCD) ahead, decrease remaining time on buffs,
            -- debuffs and CDs by 1 second and increase available energy by 10.
            FBNLite:AdjustKeys(st, -1, "rake", "rip", "sr", "tfCd", "tf", "ffCd", "weakenedArmor", "berserkCd", "berserk", "OoC", "thrashCat", "ps", "agiPot", "agiPotCd")
            FBNLite:AdjustKeys(st, st.eps, "energy")
            FBNLite:AdjustKeys(st, -st.OoC, "OoC")
            
            if (st.rake <= 0) then
                st.rakePower = 1
            end
            
            if (st.rip <= 0) then
                st.ripPower = 1
            end
            
            -- cp generators
            if spell == "Shred" or spell == "Rake" then
                if spell == "Shred" then
                    if (st.canExtendRip > 0) then
                        st.rip = st.rip + 2
                        st.canExtendRip = st.canExtendRip - 1
                    end
                    st.energy = st.energy - FBNLite.cost.shred * OoC
                elseif spell == "Rake" then
                    st.rake = st.rake + 15
                    st.energy = st.energy - FBNLite.cost.rake * OoC
                    st.rakePower = st.predictedRakePower
                end
                if (st.docStacks > 0) then
                    st.docStacks = st.docStacks - 1
                end
                -- 1 cp
                st.cp = st.cp + 1
                nextSpell1CP = FBNLite:NextCatformSpell(st)
                -- 2 cps
                st.cp = st.cp + 1
                nextSpell2CP = FBNLite:NextCatformSpell(st)
            -- non-cp generating abilities: finishers, energy pooling and faerie fire
            else
                if spell == "Faerie Fire" then
                    st.weakenedArmor = 30
                    st.weakenedArmorStacks = 3
                    st.ffCd = 6
                -- finishers, no need to do anything special for energy pooling ("empty")
                elseif spell ~= "empty" then
                    -- Set cp to 0 or < 0 if we did sr with less than 5cps.
                    local energyRefund = st.cp * 4
                    st.cp = 0
                    if spell == "Rip" then
                        st.rip = 16
                        st.energy = st.energy - FBNLite.cost.rip * OoC + energyRefund
                        st.ripPower = st.predictedRipPower
                        if (st.docStacks > 0) then
                            st.docStacks = st.docStacks - 1
                        end
                    elseif spell == "Savage Roar" then
                        st.sr = 12 + st.cp * 6
                        -- no OoC discount since Savage Roar ignores OoC!
                        st.energy = st.energy - FBNLite.cost.sr + energyRefund
                    elseif spell == "Ferocious Bite" then
                           if (st.docStacks > 0) then
                            st.docStacks = st.docStacks - 1
                        end
                        st.energy = st.energy -(FBNLite.cost.fb * OoC + math.min(25, st.energy - FBNLite.cost.fb * OoC)) + energyRefund
                    end
                end
                -- Get next ability. Maybe it would look better if the second was empty?
                nextSpell1CP = FBNLite:NextCatformSpell(st)
                nextSpell2CP = nextSpell1CP
            end
        end
    end
    FBNLite.debug = dbg
    -- update textures
    FBNLite:SetSpellTexture("topleft", "Tiger's Fury", st.tfCd <= 0)
    FBNLite:SetSpellTexture("bottomleft", "Berserk", st.berserkCd < st.lag + st.GCD)
    SetSpellOrItemTexture("middle", spell, spell ~= "empty")
    SetSpellOrItemTexture("topright", nextSpell1CP, nextSpell1CP ~= "empty")
    SetSpellOrItemTexture("bottomright", nextSpell2CP, nextSpell2CP ~= "empty")
    FBNLite:UpdateGcdFrame(spell)
    if (FBNLite.Items[spellOrItem] ~= nil) then
        FBNLite:SetItemTexture(frame, spellOrItem, condition)
    else
        FBNLite:SetSpellTexture(frame, spellOrItem, condition)
    end