Thread Tools Display Modes
05-27-13, 07:52 PM   #1
Brusalk
An Aku'mai Servant
 
Brusalk's Avatar
AddOn Author - Click to view addons
Join Date: May 2010
Posts: 32
Help with filtering cooldown events.

Heya!

I've been stuck on this problem for a really long time now and I'm starting to get quite frustrated with this.

Basically, I want to (for ease of example) print to the chat frame when the following happens for a given spell:
1. Spell goes on cooldown (not GCD)
2. Spell's cooldown is reset (E. G: Mind Blast reset on Divine Insight proc)


I've been using the SPELL_COOLDOWN_UPDATE and SPELL_COOLDOWN_USABLE events to attempt to do this, but I can't get the cooldown reset part to function as I'd expect.

Does anyone have some code they've used in the past for this purpose, or know of an easy way to do this? I can share the code I have, but it's a bit complicated as it's for my real project and not this example functionality.

Thanks!
-Brusalk
  Reply With Quote
05-27-13, 08:45 PM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I don't have any code for you, but reset detection seems pretty straightforward... when the spell goes on cooldown, record the expected time the cooldown will finish. If it comes off cooldown before that time, it was reset by something. Granted, I don't do anything with cooldowns in any of my addons, but I can't think of any reason why that wouldn't work. If it doesn't, can you be more specific about what you've already tried, what worked, and what didn't?
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
05-27-13, 09:12 PM   #3
Brusalk
An Aku'mai Servant
 
Brusalk's Avatar
AddOn Author - Click to view addons
Join Date: May 2010
Posts: 32
Originally Posted by Phanx View Post
I don't have any code for you, but reset detection seems pretty straightforward... when the spell goes on cooldown, record the expected time the cooldown will finish. If it comes off cooldown before that time, it was reset by something. Granted, I don't do anything with cooldowns in any of my addons, but I can't think of any reason why that wouldn't work. If it doesn't, can you be more specific about what you've already tried, what worked, and what didn't?
Part of the problem is that it seems that COOLDOWN_USABLE doesn't always fire for a cooldown reset. I guess I may have to do an update script which is partially what I was trying to avoid.

We're raiding atm. I'll try and get some of my code readable/applicable to the example, or explain what I have after raid.

Last edited by Brusalk : 05-27-13 at 09:35 PM.
  Reply With Quote
05-27-13, 09:35 PM   #4
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
I don't know what SPELL_UPDATE_USABLE and SPELL_UPDATE_COOLDOWN actually represent, but NOTHING fires when a spell comes off of cooldown. There is no event you can watch for this.

Your options are either use an OnUpdate script or if you're only concerned about spells bound to action buttons you could probably get away with hooking the cooldown spinner being hidden before it completes.

Here's a not-that-small script that might help you with whatever it is you're doing.
Lua Code:
  1. local Cooldowns, RecentCasts = {}, {} -- [spellid] = endTime
  2. local f = CreateFrame('frame')
  3. f:SetScript('OnEvent', function(self, event, ...)
  4.     if event == 'UNIT_SPELLCAST_SUCCEEDED' then
  5.         local _, _, _, _, spellID = ...
  6.         local baseCooldown = GetSpellBaseCooldown(spellID) or 0
  7.         if baseCooldown > 0 then -- queue it up
  8.             RecentCasts[spellID] = true
  9.         end
  10.     else
  11.         local now = GetTime()
  12.         for spellID, starTime in pairs(RecentCasts) do
  13.             local start, duration = GetSpellCooldown(spellID)
  14.             if duration > 2 then
  15.                 RecentCasts[spellID] = nil
  16.                 Cooldowns[spellID] = start + duration
  17.             end
  18.         end
  19.     end
  20. end)
  21. f:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED')
  22. f:RegisterEvent('SPELL_UPDATE_COOLDOWN')
  23.  
  24. f:SetScript('OnUpdate', function()
  25.     local now = GetTime()
  26.     for spellID, endTime in pairs(Cooldowns) do
  27.         if now >= endTime then -- cooldown finished normally
  28.             Cooldowns[spellID] = nil
  29.         else -- check if there's still a cooldown
  30.             local start, duration = GetSpellCooldown(spellID)
  31.             if now >= start + duration then -- cooldown finished sooner than expected
  32.                 Cooldowns[spellID] = nil
  33.                 print(spellID, (GetSpellLink(spellID)), 'had its cooldown reset?')
  34.             end
  35.         end
  36.     end
  37. end)

It watches for spell casts and puts them in a table to check on the next SPELL_UPDATE_COOLDOWN event, since the cooldown isn't available when UNIT_SPELLCAST_SUCCEEDED fires. Then it just loops through the cooldowns OnUpdate to see if they've ended early.

I thought it might be somewhat more efficient than just looping through the entire spellbook checking cooldown durations but I don't know, maybe you can come up with something better.

Last edited by semlar : 05-27-13 at 10:21 PM.
  Reply With Quote
05-27-13, 10:32 PM   #5
Brusalk
An Aku'mai Servant
 
Brusalk's Avatar
AddOn Author - Click to view addons
Join Date: May 2010
Posts: 32
Originally Posted by semlar View Post
I don't know what SPELL_UPDATE_USABLE and SPELL_UPDATE_COOLDOWN actually represent, but NOTHING fires when a spell comes off of cooldown. There is no event you can watch for this.

Your options are either use an OnUpdate script or if you're only concerned about spells bound to action buttons you could probably get away with hooking the cooldown spinner being hidden before it completes.

Here's a not-that-small script that might help you with whatever it is you're doing.
Lua Code:
  1. local Cooldowns, RecentCasts = {}, {} -- [spellid] = endTime
  2. local f = CreateFrame('frame')
  3. f:SetScript('OnEvent', function(self, event, ...)
  4.     if event == 'UNIT_SPELLCAST_SUCCEEDED' then
  5.         local _, _, _, _, spellID = ...
  6.         local baseCooldown = GetSpellBaseCooldown(spellID) or 0
  7.         if baseCooldown > 0 then -- queue it up
  8.             RecentCasts[spellID] = true
  9.         end
  10.     else
  11.         local now = GetTime()
  12.         for spellID, starTime in pairs(RecentCasts) do
  13.             local start, duration = GetSpellCooldown(spellID)
  14.             if duration > 2 then
  15.                 RecentCasts[spellID] = nil
  16.                 Cooldowns[spellID] = start + duration
  17.             end
  18.         end
  19.     end
  20. end)
  21. f:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED')
  22. f:RegisterEvent('SPELL_UPDATE_COOLDOWN')
  23.  
  24. f:SetScript('OnUpdate', function()
  25.     local now = GetTime()
  26.     for spellID, endTime in pairs(Cooldowns) do
  27.         if now >= endTime then -- cooldown finished normally
  28.             Cooldowns[spellID] = nil
  29.         else -- check if there's still a cooldown
  30.             local start, duration = GetSpellCooldown(spellID)
  31.             if now >= start + duration then -- cooldown finished sooner than expected
  32.                 Cooldowns[spellID] = nil
  33.                 print(spellID, (GetSpellLink(spellID)), 'had its cooldown reset?')
  34.             end
  35.         end
  36.     end
  37. end)

It watches for spell casts and puts them in a table to check on the next SPELL_UPDATE_COOLDOWN event, since the cooldown isn't available when UNIT_SPELLCAST_SUCCEEDED fires. Then it just loops through the cooldowns OnUpdate to see if they've ended early.

I thought it might be somewhat more efficient than just looping through the entire spellbook checking cooldown durations but I don't know, maybe you can come up with something better.
I'll have to take a looksee a bit later on tonight.

I actually know the spellID to keep track of ahead of time so no looping is required.
  Reply With Quote
05-28-13, 09:30 AM   #6
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
I had this script start acting up after a while on my hunter, but I didn't have time to look into it too much. There might be a flaw in the logic somewhere.

It should be simpler if you already know which spells you want to watch though.

Strictly speaking, it should only require an OnUpdate script checking when the spell goes on cooldown and then keeping track of whether that cooldown changes.

Last edited by semlar : 05-28-13 at 09:35 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Help with filtering cooldown events.


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off