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:
local Cooldowns, RecentCasts = {}, {} -- [spellid] = endTime
local f = CreateFrame('frame')
f:SetScript('OnEvent', function(self, event, ...)
if event == 'UNIT_SPELLCAST_SUCCEEDED' then
local _, _, _, _, spellID = ...
local baseCooldown = GetSpellBaseCooldown(spellID) or 0
if baseCooldown > 0 then -- queue it up
RecentCasts[spellID] = true
end
else
local now = GetTime()
for spellID, starTime in pairs(RecentCasts) do
local start, duration = GetSpellCooldown(spellID)
if duration > 2 then
RecentCasts[spellID] = nil
Cooldowns[spellID] = start + duration
end
end
end
end)
f:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED')
f:RegisterEvent('SPELL_UPDATE_COOLDOWN')
f:SetScript('OnUpdate', function()
local now = GetTime()
for spellID, endTime in pairs(Cooldowns) do
if now >= endTime then -- cooldown finished normally
Cooldowns[spellID] = nil
else -- check if there's still a cooldown
local start, duration = GetSpellCooldown(spellID)
if now >= start + duration then -- cooldown finished sooner than expected
Cooldowns[spellID] = nil
print(spellID, (GetSpellLink(spellID)), 'had its cooldown reset?')
end
end
end
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.