Thread Tools Display Modes
08-21-14, 07:36 PM   #1
darrare
A Defias Bandit
Join Date: Aug 2014
Posts: 3
Help with an addon i am making.

Im making an addon that tracks combat stats for a hunter such as agility, ap, crit, mastery, haste, etc.

i have it displaying correctly, but my only problem is i have no way for it to update at a reasonable rate.

local function updateFunction()
AgilityLine.text:SetText("Agility = ".. getRangedAgility())
AttackPowerLine.text:SetText("AP = ".. getRangedAttackPower())
CritLine.text:SetText("Crit = ".. getRangedCrit() .."%")
MasteryLine.text:SetText("Mastery = ".. getRangedMastery())
HasteLine.text:SetText("Haste = ".. getHaste() .."%")
end

i have this function that updates it correctly, but i have no idea how to impliment a way to make it only update when it should, and not 60 times a second.

any help would be appreciated
  Reply With Quote
08-21-14, 07:40 PM   #2
Yafis
A Fallenroot Satyr
 
Yafis's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 29
You have update on OnUpdate?
  Reply With Quote
08-21-14, 08:01 PM   #3
darrare
A Defias Bandit
Join Date: Aug 2014
Posts: 3
Originally Posted by Yafis View Post
You have update on OnUpdate?
not sure i understand, is OnUpdate some sort of built in function?
  Reply With Quote
08-21-14, 08:29 PM   #4
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
For now, you need to create a frame that'll run the code in its OnUpdate handler.
lua Code:
  1. local lastupdate=0;--   Local storing how long since our last update
  2. local frame=CreateFrame("Frame");-- Our frame
  3.  
  4. frame:SetScript("OnUpdate",function(self,elapsed)
  5.     lastupdate=lastupdate+elapsed;--    Add elapsed to update local
  6.     if lastupdate>1 then--  If it's been a second, update
  7.         AgilityLine.text:SetText("Agility = ".. getRangedAgility());
  8.         AttackPowerLine.text:SetText("AP = ".. getRangedAttackPower());
  9.         CritLine.text:SetText("Crit = ".. getRangedCrit() .."%");
  10.         MasteryLine.text:SetText("Mastery = ".. getRangedMastery());
  11.         HasteLine.text:SetText("Haste = ".. getHaste() .."%");
  12.  
  13.         lastupdate=0;-- Reset to zero
  14.     end
  15. end);



In WoD, we'll be getting a new C_Timer system to handle this.
When this happens, your code would look like this.
lua Code:
  1. C_Timer.NewTicker(1,function()--    Register a function to update every second
  2.     AgilityLine.text:SetText("Agility = ".. getRangedAgility());
  3.     AttackPowerLine.text:SetText("AP = ".. getRangedAttackPower());
  4.     CritLine.text:SetText("Crit = ".. getRangedCrit() .."%");
  5.     MasteryLine.text:SetText("Mastery = ".. getRangedMastery());
  6.     HasteLine.text:SetText("Haste = ".. getHaste() .."%");
  7. end);



Note: To enable Lua syntax highlighting on these forums, surround the code with [highlight=lua] [/highlight].
This is also visible as a Lua button on the right side of the formatting toolbar in the message editor.
__________________
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)

Last edited by SDPhantom : 08-21-14 at 08:39 PM.
  Reply With Quote
08-21-14, 09:03 PM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I'm pretty sure there are events that fire when these stats changed, so there's no reason to use an OnUpdate script here. Just register for the event(s) that tell you when your stats change, and update when they fire:

Code:
local f = CreateFrame("Frame")
f:RegisterEvent("HEY_YOUR_STATS_CHANGED") -- not the real event name
f:RegisterEvent("SOME_OTHER_EVENT")
f:SetScript("OnEvent", function(self, event, ...)
     -- update the display here
end)
Use the /eventtrace command in-game, do something that changes your stats, and look in the window to see which event fired. I recommend either doing this far away from other players, or leaving /eventtrace open for a minute beforehand and removing all the irrelevant events that are filling the window (hover and click the X).
__________________
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
08-22-14, 02:24 AM   #6
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
The event you looking for is "UNIT_STATS".
  Reply With Quote
08-23-14, 03:25 PM   #7
Cybeloras
A Fallenroot Satyr
 
Cybeloras's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 28
You will also need COMBAT_RATING_UPDATE since UNIT_STATS will only cover changes in agility.
  Reply With Quote
08-24-14, 10:14 AM   #8
MaLarsson
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 13
I feel that it is a good practice to always check which events you want to listen to before beginning with the code.
Wowwiki has a list of all the events: http://www.wowwiki.com/Events_A-Z_(Full_List)
You can try adding something like this to your code:
Lua Code:
  1. local frame, events = CreateFrame("Frame", nil, UIParent), {}
  2.  
  3. function events:UNIT_STATS(unitID)
  4.    if unitID == "player" then
  5.       updateFunction()
  6.    end
  7. end
  8.  
  9. function events:COMBAT_RATING_UPDATE()
  10.    updateFunction()
  11. end
  12.  
  13. for k, v in pairs(events) do
  14.    frame:RegisterEvent(k)
  15. end
  Reply With Quote
08-25-14, 12:01 AM   #9
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
That code is incomplete, as you didn't actually tell the frame what to do in response to events. Also:

- There's no need to use separate functions for the two events, as you want to do the same thing in response to both.

- You should use RegisterUnitEvent instead of RegisterEvent with UNIT_STATS so you don't have to manually filter out all other units.

- If your frame isn't a UI object shown the user, there's no need to give it a parent.

- A frame is already a table, so there's no need to create a separate table to hold functions.

Code:
-- updateFunction here

local frame = CreateFrame("Frame")
-- ^ If you already have a frame, you can register events on that instead of creating a new one here.
frame:RegisterEvent("COMBAT_RATING_UPDATE")
frame:RegisterUnitEvent("UNIT_STATS", "player")
frame:SetScript("OnEvent", updateFunction)
(On a side note, I really hope those "AgilityLine" etc. values are not globals. )
__________________
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
08-25-14, 08:39 AM   #10
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
Originally Posted by Phanx View Post
- A frame is already a table, so there's no need to create a separate table to hold functions.
There can be collisions in key names though, depending on the AddOn, so I prefer having my AddOn specific code in its own table (the private one passed as an argument to each file).

For a small AddOn like this I guess it doesn't really matter though.
  Reply With Quote
08-25-14, 09:01 AM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Sharparam View Post
There can be collisions in key names though...
I'm not sure how, since the key names are 100% under your control. It's not like you're forced to give two methods the same name...
__________________
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
08-25-14, 09:32 AM   #12
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
What I mean is you could have something in your table named the same as an existing function or value, which means what was previously defined is overwritten with your stuff. That could lead to bugs or unexpected behaviour. What if you make a SetScript method in your AddOn that is used for something, which then overrides Frame's SetScript method?
  Reply With Quote
08-25-14, 11:42 AM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Sharparam View Post
What if you make a SetScript method in your AddOn that is used for something, which then overrides Frame's SetScript method?
But why would you do that? There are literally infinite options for naming your methods. It's not any more difficult to avoid overwriting a frame's default SetScript method than it is to avoid overwriting your own DoThings method or overwriting the global CreateFrame function. This is quite possibly the most contrived excuse for overcomplicating addon code that I've ever heard.
__________________
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
08-25-14, 12:01 PM   #14
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
It's still not exactly good practice I'd say to just modify a table from CreateFrame with your own methods, at least for addons larger than a single file. I've never really come across a design pattern like that outside of WoW addon development (granted, most of my experience is with OOP languages where you typically place your code in a namespace/package named after you or a company).

Keeping it separated in that way makes it more clear what code is yours and what code comes from default libraries, and can in some cases also make code more readable for an outside developer, they wouldn't have to check if the method someframe:SomeMethod() that is defined in file1.lua and used in file2.lua comes from the WoW Frame or a custom method in file1.lua.
  Reply With Quote
08-25-14, 12:18 PM   #15
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
I'm guessing you've never heard of Monkeypatching.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
08-25-14, 12:30 PM   #16
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
Well monkeypatching isn't exactly a good thing most of the time is it? :P
  Reply With Quote
08-25-14, 01:28 PM   #17
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
If you're a code slob it can be bad, but that's true with any software technique.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
08-25-14, 02:50 PM   #18
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Sharparam View Post
IKeeping it separated in that way makes it more clear what code is yours and what code comes from default libraries, and can in some cases also make code more readable for an outside developer, they wouldn't have to check if the method someframe:SomeMethod() that is defined in file1.lua and used in file2.lua comes from the WoW Frame or a custom method in file1.lua.
But why are you giving your custom methods the same names as default methods in the first place? This is just as bad an idea as naming a table table or naming a local function tostring -- there's just no reason to do it. If you see a SetScript method in a WoW addon, it should always be the SetScript method that comes with the given object type, period, just like if you see a call to a function named tostring it should be the Lua language function. Anything else is just confusing for no reason.
__________________
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
08-25-14, 03:12 PM   #19
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
One reason could be if you make something that you want to behave like a Frame's event/script system. Say you want custom callbacks for some object you have, like:

lua Code:
  1. local object = {callbacks={}}
  2.  
  3. function object:SetScript(typ, func)
  4.   if not self.callbacks[typ] then self.callbacks[typ] = {} end
  5.   table.insert(self.callbacks[typ], func)
  6. end
  7.  
  8. function object:Fire(typ, ...)
  9.   if not self.callbacks[typ] then return end
  10.   for _, f in pairs(self.callbacks[typ]) do f(...) end
  11. end
  12.  
  13. object:SetScript("MyCustomTrigger", function() print("foo bar baz") end)
  14.  
  15. -- Some code that does stuff and triggers the callbacks
  16. object:Fire("MyCustomTrigger")

Yes, there's CallbackHandler lib for this kind of stuff, but sometimes you just want to roll your own when you don't utilize near half the features of an existing library or don't like the particular way they implemented things.

Implementing the above on a Frame wouldn't really work while making sure there aren't any problems with the Frame's own SetScript and related types of events/triggers. Forwards compatibility can also be a concern, why put your addon at risk of being made incompatible with a future patch when it's preventable with little effort? Using different names would work, but why not choose a method that lets you use whatever name you feel fits best.

And if you're just blindly using a Frame to put all your methods in, you could be unknowingly replacing something that the Frame actually uses for whatever purpose if you don't check the documentation before implementing a method.

I like to have the comfort of knowing that whatever I'm putting in my tables, won't directly conflict with anything and lives in its own space. I do sometimes put things in Frames, but mostly for one-off objects. An example being in the options file of one of my addons (code is in MoonScript, but should be relatively readable I hope).
  Reply With Quote
08-25-14, 05:22 PM   #20
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Sharparam View Post
One reason could be if you make something that you want to behave like a Frame's event/script system.
So... either use the normal Frame event/script system, or name your method something else? Still not seeing how this is leading to using a default API method name for your own custom method is in any way beneficial, regardless of whether you're defining it on a Frame object or a plain table. If I see "object:SetScript" in WoW addon code, the only reasonable assumption to make is that "object" is a frame of some type, and "SetScript" is the standard "SetScript" method that comes with a frame object.

Originally Posted by Sharparam View Post
And if you're just blindly using a Frame to put all your methods in, you could be unknowingly replacing something that the Frame actually uses for whatever purpose if you don't check the documentation before implementing a method.
If you have no idea what methods a Frame object comes with, you should take your hands off the keyboard and go look at some API documentation before proceeding.

Originally Posted by Sharparam View Post
An example being in the options file of one of my addons (code is in MoonScript, but should be relatively readable I hope).
Ugh, MoonScript. Someone (maybe you) posted a link to that recently, and the official examples of Lua code it generates about made me vomit. It's horrible.... but I guess if you're not actually programming in Lua, and you're writing your addons in some Python-like pseudo-code that generates Lua code on par with the HTML generated by MS Front Page circa 1997, that probably explains why you're arguing in favor or something that makes no sense.
__________________
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

WoWInterface » Developer Discussions » Lua/XML Help » Help with an addon i am making.

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