Thread Tools Display Modes
10-21-14, 11:02 AM   #1
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
Efficient Table Wiping

Good afternoon, I'm creating a function that will essentially, every 2.6s, determine how many targets have been hit by blade flurry. The text value will update every .25s, but every 2.6s the table will wipe to ensure the value is as accurate as possible with mobs moving in/out of range or dying.

This is dry coded, so I don't even know if this works, my main question revolves on methods of efficiently clearing all the table keys and values of bladeflurrytargets, is table.wipe() the best option? At the very most, I would expect <20 keys and values in the table at a time. Would it be more efficient to do a k,v delete?

Lua Code:
  1. local bftcf = CreateFrame('Button', 'BladeFlurryTargetCountFrame', UIParent)
  2.         bftcf:SetSize(50,50)
  3.         bftcf:SetPoint('CENTER', UIParent, 'CENTER')
  4.     local bftcftext = bftcf:CreateFontString(nil, 'OVERLAY')
  5.         bftcftext:SetFont(FONTSTRINGHERE, 11, 'OUTLINE')
  6.         bftcftext:SetAllPoints()
  7.        
  8.         bftcf:SetScript('OnUpdate', function(self, elapsed, bladeflurrytargets)
  9.             if (elapsed > 0.25 and < 2.6) then --update the text value every 1/4 second to give ~real time analysis
  10.                 bftcftext:SetText(#bladeflurrytargets)
  11.             elseif elapsed >= 2.6 then  --update every main hand attack base line speed interval(way faster than this with slice and dice, but just to make sure) to be sure every target that's going to be hit has been hit
  12.                 bftcftext:SetText(#bladeflurrytargets)
  13.                 table.wipe(bladeflurrytargets)
  14.                 elapsed = 0
  15.             end
  16.         end)
  Reply With Quote
10-21-14, 12:16 PM   #2
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
I would just call wipe() on the table.

Also, "elapsed" from OnUpdate is the amount of time that has passed since the last frame/OnUpdate call.

To make a timer you need to create a variable outside of the OnUpdate function that you add the elapsed time to until it is greater than 2.6 or whatever and set it back to 0.

Checking if the elapsed time is > 0.25 and < 2.6 will have that executing every frame after 0.25 seconds has been reached until 2.6 seconds has elapsed, you should make 2 separate variables if you want something happening every 0.25 seconds and every 2.6 seconds.

Alternatively, you can use the C_Timer functions to execute something at periodic intervals.

Last edited by semlar : 10-21-14 at 01:05 PM.
  Reply With Quote
10-21-14, 03:34 PM   #3
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
Heh, I was just reading examples of OnUpdate and noticed that no one changed elapsed and were doing just as you described instead. I was about to ask if I can even alter elapsed's value but you already answered that.

Thanks!

e: I also changed the if's to while's to ensure the checks are as accurate as possible.

Last edited by sirann : 10-21-14 at 03:41 PM.
  Reply With Quote
10-21-14, 04:04 PM   #4
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
So here's a follow up question. Can I do a rolling table check? I plan on doing it like this:

Combat log event fires, first argument is time


Lua Code:
  1. table[arg1] = GUIDofTargetHitByBladeFlurry aka arg6
  2.  
  3. for k, v in pairs(table) do
  4.      if GetTime() > k + 2.6 then
  5.           k, v = nil, nil
  6.      end
  7. end

I may have to do arithmetic on the return of GetTime() so the equation essentially checks if more than 2.6s has past since that key was created, and it can check this because the value of the key is the timestamp at which it was created.

Is that possible/an efficient way to do more of a rolling check of blade flurry targets being hit instead of a blanket table wipe every 2.6s?

e: I'd have to check the table to see if value is unique for when I hit the target a 2nd, 3rd, or nth time after the initial key was made. If the GUID is already in the table, delete the old key, since this target his been more recently hit, and set the new k,v as the current time and the target's GUID respectively.

Last edited by sirann : 10-21-14 at 04:06 PM.
  Reply With Quote
10-21-14, 04:21 PM   #5
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Initialize as such:
Code:
local bladeFlurryTargets, numBladeFlurryTargets = { }, 0
To add or update a target:
Code:
bladeFlurryTargets[guid] = arg1 + 2.6
To update the count and purge old targets:
Code:
local time = GetTime()
numBladeFlurryTargets = 0
for guid, decayTime in next, bladeFlurryTargets, nil do
	if decayTime < time then
		numBladeFlurryTargets = numBladeFlurryTargets + 1
	else
		bladeFlurryTargets[guid] = nil
	end
end
  Reply With Quote
10-21-14, 04:31 PM   #6
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
Heh, much more elegant than this monstrosity I created:

Lua Code:
  1. local function handlebladeflurryevent(self, bladeflurrytargets, a6)
  2.     for k, v in pairs(bladeflurrytargets) do
  3.         if GetTime() > k + 2.6 then
  4.              k, v = nil, nil
  5.         else
  6.             for i = 1,#bladeflurrytargets do
  7.                 for k,v in pairs(bladeflurry) do
  8.                     if a6 == v then
  9.                         k, v = nil, nil
  10.                     else
  11.                         bladeflurrytargets[a1] = a6
  12.                     end
  13.                 end
  14.             end
  15.         end
  16.     end
  17. end

Thanks!
  Reply With Quote
10-22-14, 10:05 PM   #7
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,323
Originally Posted by sirann View Post
Heh, I was just reading examples of OnUpdate and noticed that no one changed elapsed and were doing just as you described instead. I was about to ask if I can even alter elapsed's value but you already answered that.
Changing the value of elapsed doesn't do anything outside the scope of the function itself. Lua doesn't support sending values back through a function's parameters.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
10-24-14, 04:32 PM   #8
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
So as you might have been able to elucidate, I am coding a scrolling combat text addon, and figured this would be a decent time to finally make a blade flurry tracker.

Please find here: http://pastebin.com/aJMpCy4t my code thus far. So far I just have the blade flurry handler and the outgoing dmg section completed.

I still need to do incoming dmg and a special frame for blocks, dodges, immunes, and parries (indicative I'm not behind the boss or hitting something I shouldn't be.)

If anyone wants to comment on efficiency and optimization, I'd greatly appreciate it.

Last edited by sirann : 10-24-14 at 04:37 PM.
  Reply With Quote
10-24-14, 08:12 PM   #9
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I'll look at the actual code shortly, but:

Originally Posted by sirann View Post
So as you might have been able to elucidate....
This is not the droid you are looking for!

elucidate
1. To make clear; to clarify; to shed light upon.
__________________
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
10-24-14, 08:29 PM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Okay, on to the actual code. First of all, your indentation is weird. These are at the same heirarchical level; why are they indented differently?

Code:
local bftcf = CreateFrame('Button', 'BladeFlurryTargetCountFrame', UIParent)
        bftcf:SetSize(50,50)
        bftcf:SetPoint('CENTER', UIParent, 'CENTER')
        bftcf:Hide()
        bftcf:RegisterEvent('PLAYER_ENTERING_WORLD')
        bftcf:RegisterUnitEvent('UNIT_AURA', 'player')
Unless you want to wrap all but the first line there in a do/end block, those lines shouldn't be indented.

Secondly, your code in its current state won't work at all, and should throw errors. For example:

Code:
bftcf:SetScript('OnEvent', function(self, elapsed, unit)
                if (event == 'PLAYER_ENTERING_WORLD' and InCombatLockdown()) or (event == 'UNIT_AURA' and InCombatLockdown()) then
                        if UnitBuff('player', 'Blade Flurry') then
                                bftcf:Show()
                                bftcf:SetScript('OnUpdate', bftcupdater)

...

local bftcupdater = function('OnUpdate', self, elapsed, updater, cleaner, bladeflurrytargets)
        updater = updater + elapsed
        cleaner = cleaner + elapsed
#1 - You're naming the second value passed into your OnEvent script "elapsed" and then referring to a variable "event" that isn't defined. The checks against "event" will always fail, either because "event" is nil, or because "event" is some random unknown value leaked by another addon. You should change "elapsed" to "event" here, because the second value passed into an OnEvent script is a string containing the name of the event being handled.

#2 - There's also no need to check the events, because those are the only events you're registered for. Your frame cannot receive any events other than those two.

#3 - Checking InCombatLockdown() here is very inefficient. If you don't want to handle aura events out of combat, you should register for PLAYER_REGEN_DISABLED (entering combat) and PLAYER_REGEN_ENABLED (leaving combat) and register/unregister UNIT_AURA as needed. If you do this then you will need to check the event in your OnEvent handler after all.

#4 - In the scope where you're setting your OnUpdate script, "bftcupdater" is nil, because it's not defined until about 20 lines further down in the file, and is defined as a local. Unless you're creating globals (don't) you must define your variables closer to the top of the file than where you use them.

#5 - When you define "bftcupdater" you wrote "OnUpdate" inside the parenthesis. This should generate an error, because you cannot write strings, numbers, etc. there -- you're defining a function, not calling it. When your function is called, each of the things you wrote there is assigned as a variable, and given a value according to what's passed into the function. What you wrote would be like trying to do local "OnUpdate" = 5 which just doesn't work.

#6 - If you're setting this as an OnUpdate script, then it will only ever receive two arguments. The first argument is a reference to the frame the script is set on, and is typically named "self". The second is a number describing how many seconds have passed since the last time the OnUpdate script was run, and is typically named "elapsed". You are assigning two variables with those names, but in the wrong positions, and you're also assigning three more variables ("updater", "cleaner", and "bladeflurrytargets") which will always be given nil values. The next two lines will fail and throw errors about attempting to perform arithmetic on nil values. I'm guessing you actually want to use the variables with the same names that you defined at the top of your file, in which case you need to remove them from the list of function arguments.

There's probably more, but there's no point in looking at anything else at this point. There's just no way this code could ever work as written. You should really at least load your code in-game and try to fix the errors before you ask for advice on optimization. Remember:

The First Rule of Program Optimization: Don't do it.
The Second Rule of Program Optimization (for experts only!): Don't do it yet.
__________________
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
10-24-14, 09:37 PM   #11
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by Phanx View Post
Okay, on to the actual code. First of all, your indentation is weird. These are at the same heirarchical level; why are they indented differently?

Code:
local bftcf = CreateFrame('Button', 'BladeFlurryTargetCountFrame', UIParent)
        bftcf:SetSize(50,50)
        bftcf:SetPoint('CENTER', UIParent, 'CENTER')
        bftcf:Hide()
        bftcf:RegisterEvent('PLAYER_ENTERING_WORLD')
        bftcf:RegisterUnitEvent('UNIT_AURA', 'player')
Unless you want to wrap all but the first line there in a do/end block, those lines shouldn't be indented.
I indent like that sometimes if I'm creating a bunch of frames/objects in a function. Helps to see where each one begins and which methods are being performed on that object. Either that or line breaks. If it helps him keep his code organized for his purposes, there's no harm in it.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
10-24-14, 10:54 PM   #12
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
Perhaps I'm just dumb, but I'm trying to compare time of an event that was stored via the first argument of CLEU with the current time. GetTime() doesn't seem to the the way to do it as it reports a number several thousand fold higher than the arg1 value.

BTW thank you for elucidating the definition of elucidate for me phanx. I still think it fits, deduce may have been better!
  Reply With Quote
10-24-14, 11:53 PM   #13
Choonstertwo
A Chromatic Dragonspawn
 
Choonstertwo's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2011
Posts: 194
Originally Posted by sirann View Post
Perhaps I'm just dumb, but I'm trying to compare time of an event that was stored via the first argument of CLEU with the current time. GetTime() doesn't seem to the the way to do it as it reports a number several thousand fold higher than the arg1 value.

BTW thank you for elucidating the definition of elucidate for me phanx. I still think it fits, deduce may have been better!
GetTime() returns the time since your computer booted up in milliseconds.

The first argument of CLEU is the number of seconds (with milliseconds) since the Unix epoch. The time() function also returns the number of seconds since the Unix epoch (without milliseconds), so this is what you'll want to use to get the current time rather than GetTime.

This is specifically mentioned in the Base Parameters section of the CLE/CLEU page on Wowpedia.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Efficient Table Wiping

Thread Tools
Display Modes

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