Thread Tools Display Modes
10-22-09, 03:57 PM   #1
AJSTITAN14
A Murloc Raider
Join Date: Oct 2009
Posts: 8
Need Help Pulling Rogue Energy into a Font String

i've decided to write my own Rogue frame because I have not found one I like and I wanted to get back into writing code a bit anyway.

I spent most of the day today reading up on LUA and Widgets in the API so I managed to figure out how to create a frame with LUA and register some events. I can get as far sending a message to the chat window that I have gained energy but when I try to send that data to a FontString the entire frame disappears. Most likely I am approaching the problem the wrong way and/or using the wrong types of attributes or something.

How do I display energy in a FontString is at all? Should I be constructing this a different way? I think my construction in the Energy:SetText() is completely wrong.

Below is the code I came up with. Thanks in advance.

MyFrame = CreateFrame("Frame","MyFrame",UIParent)
MyFrame:SetPoint("CENTER",0,-300)
MyFrame:SetWidth(200)
MyFrame:SetHeight(100)
MyFrame.texture = MyFrame:CreateTexture()
MyFrame.texture:SetAllPoints(MyFrame)
MyFrame.texture:SetTexture(0,0,0,.75)
Energy = MyFrame:CreateFontString("ABF_PlayerEnergy", "ARTWORK", "GameFontNormalHuge")
Energy:SetPoint("CENTER", MyFrame, "CENTER", 0, 0)
Energy:SetText("|cffffffffLOADED|r")

--MyFrame:RegisterEvent("ADDON_LOADED")
MyFrame:RegisterEvent("UNIT_ENERGY")

MyFrame:SetScript("OnEvent", function(self)
if event == "UNIT_ENERGY" then
--DEFAULT_CHAT_FRAME:AddMessage("Gained Energy");
--if event == "UNIT_ENERGY" then
Energy:SetText("|cffffffff"UnitPower("player")"|r")
end
end)
  Reply With Quote
10-22-09, 04:13 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
1. Always try to limit your usage of global variables. If you have to use a global, then make sure that it does not have a generic name (such as "MyFrame" or "Energy". If another addon happened to also have a generically named global variable (such as MyFrame) then they will overwrite and conflict with eachother.

2. If you are just registering for one event, then you don't need to check if the event return matches your event.

3. If you do want to compare events in your event handler script, then you need to pass that arg through the function. f:SetScript("OnEvent", function(self,event) blah end)

4. When putting a variable into a fontstring, you need to either use concatenation or use string formatting.

If you need further help after these tips, we'll write it out for you.



/edit: also, make sure that you do not have Lua errors disabled in your Interface Options.
__________________
"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-22-09, 08:08 PM   #3
AJSTITAN14
A Murloc Raider
Join Date: Oct 2009
Posts: 8
Thank you for the reply.

In re #1: Thank you for the sound advice. In this particular piece I was really just trying to create an environment in which I could attempt to print out the energy variable. I promise you will see better code from me in the final.

2: in other words I can just write out the code to display the value of the energy variable and be done with it? I inferred that you needed to be listening for events in order to gather the data in the first place, but I'm ok with being totally wrong about that.

3. I think I understand what you are saying but I will need to take a look at some examples.

4. I looked into this. Essentially I was trying to print a number straight out to text and LUA.org says something about coercing a number into a FontString with the concatenation operator. I think I can manage that i'm going to take another crack at it. Thanks for pointing me in the right direction I really appreciate it.

I will be back either way Im sure with mor problems and question. Appreaciate your time. Thanks again.
  Reply With Quote
10-22-09, 08:58 PM   #4
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 648
Code:
local playerEnergy = UnitPower("player")

MyFrame = CreateFrame("Frame","MyFrame",UIParent)
MyFrame:SetPoint("CENTER",0,-300)
MyFrame:SetWidth(200)
MyFrame:SetHeight(100)
MyFrame.texture = MyFrame:CreateTexture()
MyFrame.texture:SetAllPoints(MyFrame)
MyFrame.texture:SetTexture(0,0,0,.75)

Energy = MyFrame:CreateFontString("ABF_PlayerEnergy", "ARTWORK", "GameFontNormalHuge")
Energy:SetPoint("CENTER", MyFrame, "CENTER", 0, 0)
Energy:SetText("|cffffffffLOADED|r")

--MyFrame:RegisterEvent("ADDON_LOADED")
MyFrame:RegisterEvent("UNIT_ENERGY")

MyFrame:SetScript("OnEvent", function(self)
	Energy:SetText("|cffffffff"..playerEnergy.."|r")
end)
Does this do it?
__________________
All I see is strobe lights blinding me in my hindsight.
  Reply With Quote
10-22-09, 09:29 PM   #5
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by AJSTITAN14 View Post
In re #1: Thank you for the sound advice. In this particular piece I was really just trying to create an environment in which I could attempt to print out the energy variable. I promise you will see better code from me in the final.
I wasn't scolding you, was just mentioning it because it's a common beginner oversight, and it *may* have been cause of an issue.

2: in other words I can just write out the code to display the value of the energy variable and be done with it? I inferred that you needed to be listening for events in order to gather the data in the first place, but I'm ok with being totally wrong about that.
Ah, no. You just don't need to do the if event == "UNIT_ENERGY" bit.

3. I think I understand what you are saying but I will need to take a look at some examples.
You just passed the arg "self" to your OnEvent function. This means that your function does not have reference to that variable. "event" is the second arg to that script function. By doing function(self,event) then you have a reference to that arg called "event". (You could even do function(s,e) or function(frame,trigger), etc. The variable name doesn't matter, as long as the arg is passed through to the code that needs to reference it.)

4. I looked into this. Essentially I was trying to print a number straight out to text and LUA.org says something about coercing a number into a FontString with the concatenation operator. I think I can manage that i'm going to take another crack at it. Thanks for pointing me in the right direction I really appreciate it.
Use two periods ( .. ) to concat two things together. Here are some examples.
print("Name: "..UnitName("player"))
>> Name: Seerah
level = UnitLevel("player")
print("Level: "..level)
>> Level: 72
print(UnitName("player").." is level "..level..".")
>> Seerah is level 72.
You can also use string.format for this. %s is for text, while %d is for a number.
print(string.format("%s is level %d.", UnitName("player"), level))
>> Seerah is level 72.
__________________
"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-22-09, 09:36 PM   #6
AJSTITAN14
A Murloc Raider
Join Date: Oct 2009
Posts: 8
Talking

To Wimpface: Thank you for tring to give me a hand with this. When I drop that code into my LUA it doesn't work. Just shows a zero and never updates.

To Seerah: Thanks again. #3 is the part i'm having the most difficulty understanding. I'll take a look at it again tomorrow.

Below is what I came up with and I tried to imlement some of Seerah's suggestion in the naming and variable scope.

The code works but it's too slow . So that was what I was trying to accomplish today but it's not exactly what I had in mind. The default UI and other mods update the text value much faster. I guess my first question is:

Is that an actual stream of data that I can capture somehow or is it interpolated?

Number two: if I don't need to check the event return how do I kick off the mod to update the data in the frame?

code:
------------------------------------------------------
ABFrame = CreateFrame("Frame","ABFrame",UIParent)
ABFrame:SetPoint("CENTER",0,-300)
ABFrame:SetWidth(200)
ABFrame:SetHeight(100)
ABFrame.texture = ABFrame:CreateTexture()
ABFrame.texture:SetAllPoints(ABFrame)
ABFrame.texture:SetTexture(0,0,0,.75)
EnergyString = ABFrame:CreateFontString("ABF_PlayerEnergy", "ARTWORK", "GameFontNormalHuge")
EnergyString:SetPoint("CENTER", ABFrame, "CENTER", 0, 0)
Energy:SetText("LOADED")

MyFrame:RegisterEvent("ADDON_LOADED")
MyFrame:RegisterEvent("UNIT_ENERGY")

MyFrame:SetScript("OnEvent", function(self)
if event == "UNIT_ENERGY" then
local PlayerEnergy = UnitPower("player");
DEFAULT_CHAT_FRAME:AddMessage("Gained Energy:"..PlayerEnergy);
Energy:SetText(UnitPower("player"))
end
end)

Last edited by AJSTITAN14 : 10-22-09 at 09:42 PM.
  Reply With Quote
10-23-09, 09:18 AM   #7
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
To fasten up the refresh, you could use OnUpdate instead of OnEvent. OnUpdate triggers about every 0.17 second(atleast at my computer). But, later today I will be releasing my addon ncDatatext in which it is VERY easy to create this fontstring, plus many more with less than 20kB memory usage. Anyway, here is your modified code, I didn't test it out, but it should work.

Code:
local f = CreateFrame("Frame", "ABFrame", UIParent)
local e = f:CreateFontString()
local t = f:CreateTexture()
f:SetPoint("CENTER", 0, -300)
f:SetWidth(200)
f:SetHeight(100)
t:SetAllPoints(f)
t:SetTexture(0, 0, 0, .75)
e:SetPoint("CENTER", f, "CENTER", 0, 0)
e:SetFont("FRIZQT__.ttf", 9)
f:SetScript("OnUpdate", function() e:SetText(UnitPower("player")) end)
  Reply With Quote
10-23-09, 09:22 AM   #8
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by AJSTITAN14 View Post
To Seerah: Thanks again. #3 is the part i'm having the most difficulty understanding. I'll take a look at it again tomorrow.
lua Code:
  1. function PrintStuff(thing, otherthing)
  2.      print(thing, otherthing)
  3. end
  4. PrintStuff("hello", "world")
This prints out hello world
lua Code:
  1. function PrintStuff(thing)
  2.      print(thing, otherthing)
  3. end
  4. PrintStuff("hello", "world")
This prints out hello nil because the function is not passing through the second argument (otherthing). It's just looking for the first.
lua Code:
  1. frame:SetScript("OnEvent", function(self)
  2.           print(event)
  3.      end)
This would print out nil because event is not defined in the function. Remember, I said that the variables could be called whatever you wanted. Lua is not psychic, and can't assume what you're looking for.
lua Code:
  1. frame:SetScript("OnEvent", function(event,self)
  2.           print(event, self)
  3.      end)
This prints out "FrameName", NAME_OF_EVENT.


Below is what I came up with and I tried to imlement some of Seerah's suggestion in the naming and variable scope.

The code works but it's too slow . So that was what I was trying to accomplish today but it's not exactly what I had in mind. The default UI and other mods update the text value much faster. I guess my first question is:

Is that an actual stream of data that I can capture somehow or is it interpolated?
irt your most recent block of code, you're using ABFrame, but registering events via a second frame, MyFrame. While this doesn't hurt anything, it's best to follow the K.I.S.S. principle. Though I don't know why your code is executing slowly... It may be that you're calling UnitPower() twice instead of just using the PlayerEnergy variable that you just set... /shrug

Number two: if I don't need to check the event return how do I kick off the mod to update the data in the frame?
Picture this. You are waiting for your number to be called. You tell a friend to tap you on the shoulder if they hear it. If your friend taps you on the shoulder, you know that your number has been called - they don't need to say anything. Now, picture that you ask your friend to tap you on the shoulder if either your number gets called or if they see a cute girl. This time when your friend taps you on the shoulder, they need to tell you why they did - you're waiting for two taps.

Obviously, if your code gets more complex and you wait for multiple events, you'll want to check to see which one fired before you execute your code. But if you're only waiting for one, or you want to do the same thing for both/multiple events, then it doesn't matter. A tap on the shoulder means the same thing. Checking for your event (by doing if event == "MY_EVENT"), like the above ABFrame vs. MyFrame stuff, doesn't hurt anything at all. It's just a way to save on an "if statement".

One thing to note, however, is that the "UNIT_ENERGY" event fires whenever *any* unit's energy changes. You'll want to check to make sure it's yours before running code, else you'll be doing stuff when you don't need to. This may also be the cause of the "slowness" you mentioned. Since the event returns a value of the unit, your code will look like this.
lua Code:
  1. ABFrame:RegisterEvent("UNIT_ENERGY")
  2. ABFrame:SetScript("OnEvent", function(self, event, unit)
  3.           if unit == "player" then
  4.                Energy:SetText(UnitPower("player"))
  5.           end
  6.      end)

There are some other optimizations, etc. that we can do with your code, but we won't worry about them now.
__________________
"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-23-09, 09:24 AM   #9
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by nightcracker View Post
To fasten up the refresh, you could use OnUpdate instead of OnEvent. OnUpdate triggers about every 0.17 second(atleast at my computer). But, later today I will be releasing my addon ncDatatext in which it is VERY easy to create this fontstring, plus many more with less than 20kB memory usage. Anyway, here is your modified code, I didn't test it out, but it should work.
OnUpdate is not such a good idea. If an event is available it's *always* better to use an event. Doing something only when you need it is cheaper and faster than doing it 60 times per second (assuming your framerate is 60 at the time).
__________________
"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-23-09, 08:06 PM   #10
AJSTITAN14
A Murloc Raider
Join Date: Oct 2009
Posts: 8
I think you are right but I don't know how to get the data to display fast that way. I have looked at two mods that display energy and they both use OnUpdate. I rewrote my code to use the OnUpdate and I am getting exactly the results I was looking for now.

I'm open to being shown a better way if we can find one but for this specific case as a rogue I need information as fast as I can get it when it comes to energy.

Thanks everyone, I'm going to sit down and decide exactly what features I absolutely need and which ones I can hold off on. I'm already starting to get that "well this feature would be nice" thing going so I'm going to draw up a plan on what I absolutely need and then come back and start a new thread and hopefully we can discuss how to build this project to do the essentials within a framework that will leave it open to more easily add new features. I will also probably need to talk about the kinds of data verifications I should do to make sure I'm reporting the data I want to see. For instance I will need to restart counters for deadly poison, combo points or rupture when I change targets or reset data when my target dies etc...

code:
---------------------------------------------------------------
ABFrame = CreateFrame("Frame","ABFrame",UIParent)
ABFrame:SetPoint("CENTER",0,-300)
ABFrame:SetWidth(200)
ABFrame:SetHeight(100)
ABFrame.texture = ABFrame:CreateTexture()
ABFrame.texture:SetAllPoints(ABFrame)
ABFrame.texture:SetTexture(0,0,0,.75)
EnergyString = ABFrame:CreateFontString("ABF_PlayerEnergy", "ARTWORK", "GameFontNormalHuge")
EnergyString:SetPoint("CENTER", ABFrame, "CENTER", 0, 0)
EnergyString:SetText("LOADED")

ABFrame:SetScript("OnUpdate", function()
EnergyString:SetText(UnitPower("player")) end)

Last edited by AJSTITAN14 : 10-23-09 at 08:12 PM.
  Reply With Quote
10-24-09, 10:43 PM   #11
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
Originally Posted by AJSTITAN14 View Post

Code:
ABFrame:SetScript("OnUpdate", function()
EnergyString:SetText(UnitPower("player")) end)
You need to throttle this. OnUpdate is called every time your screen refreshes, which means if you are running at 120FPS this is executed 120 times every second. Not only is this completely unnecessary, but having several AddOns which do this unthrottled will severely degrade performance, if it doesn't simply drag your client to a halt.
__________________
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
10-26-09, 05:50 PM   #12
AJSTITAN14
A Murloc Raider
Join Date: Oct 2009
Posts: 8
Thanks.

I don't have the first idea how to throttle the updating. Can you point me in the right direction?
  Reply With Quote
10-26-09, 08:59 PM   #13
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
This will throttle it to once every quarter of a second.

Code:
local last_update = 0

ABFrame:SetScript("OnUpdate",
        function(self, elapsed)
                last_update = last_update + elapsed

                if last_update >= 0.25 then
                        EnergyString:SetText(UnitPower("player"))
                        last_update = 0
                end
        end)
__________________
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

WoWInterface » Developer Discussions » Lua/XML Help » Need Help Pulling Rogue Energy into a Font String


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