View Single Post
02/21/14, 12:05 PM   #4
Wykkyd
Are you Wykkyd Gaming?
 
Wykkyd's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 107
Originally Posted by zork View Post
Are there any arguments that allow throttling like elapsed?
Cross posting this from something I posted somewhere else I can't talk about

Events in this game can trigger really, really... really fast. If you want to know how fast you can easily dump a counter to your chat window when that event triggers and watch as it fliiieeeeesssss by. This can cause issues when your update script has to parse something or do any heavy lifting. In fact, it can cause a problem at times when your update script isn't really doing much.

The safe way to handle this is to buffer your event handling so that you're only processing updates at set intervals, instead of nearly instantaneously. And yes, some things are fine at lightening speed but I've found that most work just fine between 0.33 and 3 seconds.

In the case of my War Tools addon (found within my [MH] Addon Suite) I parse Cyrodiil rather extensively. When I first drafted the addon I walked into Cyrodiil, the events registered and I instantly entered stutter-frame, stop-motion TESO. It... was... bad...

The simple fact was that events were triggering too quickly for the Cyrodiil parser to constantly run the way it was. In fact, it was running in layers on top of itself because the events fired so fast.

I also use this trick in Gear Tools (also in the Addon Suite) to build a queuing system to handle gear moves because items can't all be unequipped all at once. You have to trigger those moves one at a time. So, I pile the "these things need to happen" gear moves into a table and I execute anything pending in the table, 1 item per iteration, as the OnUpdate event triggers in the addon... at a 0.33 buffer. Because anything faster than 1/3rd of a second doesn't allow time for gear to move properly and register with your UI.

This is the basic buffer I use, modified for "generic and global" application:
Code:
local BufferTable = {}
function BufferReached(key, buffer)
	if key == nil then return end
	if BufferTable[key] == nil then BufferTable[key] = {} end
	BufferTable[key].buffer = buffer or 3
	BufferTable[key].now = GetFrameTimeSeconds()
	if BufferTable[key].last == nil then BufferTable[key].last = BufferTable[key].now end
	BufferTable[key].diff = BufferTable[key].now - BufferTable[key].last
	BufferTable[key].eval = BufferTable[key].diff >= BufferTable[key].buffer
	if BufferTable[key].eval then BufferTable[key].last = BufferTable[key].now end
	return BufferTable[key].eval
end
This is how you would consume that buffer in an event/update handler:
Code:
function OnUpdateHandler()
	if not BufferReached("myaddonupdatebuffer", 1) then return; end
	--[[ process your update here ]]--
end
Hopefully this little tidbit helps someone.
Cairenn it might be good to have tips like this in your wiki, since OnUpdate fires so quickly it's likely to crash a LOT of people if addons are written that don't know how to buffer properly.
  Reply With Quote