Thread Tools Display Modes
07-23-13, 10:49 AM   #1
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
3 Questions

http://i.imgur.com/zI9jLCR.jpg

1.
How do I change the value for health to be shortened?
For example, in the screenshot my health is 113k and my target is 2482.
How do I change it so it shortens from 999 and up?

2.
As seen on the screenshot the texture on the EXP bar is thicker on the bottom of it compared to the top.
Can I either make it as thin as on the top side or simply remove the border completely?

Last edited by laukond : 07-23-13 at 12:09 PM. Reason: Found the answer to the 3. question
  Reply With Quote
07-23-13, 01:34 PM   #2
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Can you provide some info about what UI this is, and/or if you are writing some addon yourself, please provide code to look at
  Reply With Quote
07-23-13, 01:37 PM   #3
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
Originally Posted by ravagernl View Post
Can you provide some info about what UI this is, and/or if you are writing some addon yourself, please provide code to look at
It's blizzard UI with lots of zzzz:SetAlpha(0);

As for the health text I use this code currently:
Code:
	hooksecurefunc("TextStatusBar_UpdateTextStringWithValues", function()
        PlayerFrameHealthBar.TextString:SetText(AbbreviateLargeNumbers(UnitHealth("player")))
        PlayerFrameManaBar.TextString:SetText(AbbreviateLargeNumbers(UnitMana("player")))
		-- PlayerFrameAlternateManaBar.TextString:SetText(AbbreviateLargeNumbers(UnitPower("player")))
		
        TargetFrameHealthBar.TextString:SetText(AbbreviateLargeNumbers(UnitHealth("target")))
        TargetFrameManaBar.TextString:SetText(AbbreviateLargeNumbers(UnitMana("target")))

        FocusFrameHealthBar.TextString:SetText(AbbreviateLargeNumbers(UnitHealth("focus")))
        FocusFrameManaBar.TextString:SetText(AbbreviateLargeNumbers(UnitMana("focus")))
		
		
	end)
  Reply With Quote
07-23-13, 04:31 PM   #4
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
1. You will have to write your own AbbreviateLargeNumbers function for it.
lua Code:
  1. local SiValue = function(val)
  2.     if (val >= 1e6) then
  3.         return ("%.1fm"):format(val / 1e6)
  4.     elseif (val >= 1e3) then
  5.         return ("%.1fk"):format(val / 1e3)
  6.     else
  7.         return val
  8.     end
  9. end
would be a simple example without using blizzard's separators.

2. I'm not sure what's the texture shown there, but it might be these:
MainMenuXPBarTextureLeftCap
MainMenuXPBarTextureRightCap
MainMenuXPBarTextureMid
(Those are global names)
If so, you could use MainMenuXPBarTextureLeftCap:SetTexture(nil) and so on or play with SetTexCoords to make the border suit your needs. You might have to hook MainMenuExpBar_SetWidth as well.

Apart from that, when you use hooksecurefunc, your hook will be called with the same arguments as the function you hook to. In the case of TextStatusBar_UpdateTextStringWithValues those are:
statusFrame - StatusBar - the status bar the text is being changed on (i.e. PlayerFrameHealthBar)
textString - FontString - the text being changed (i.e. PlayerFrameHealthBar.TextString)
value - number - the current value of the statusbar (probably the same as the return of UnitHealth("player") +/- some negligible lag, if the func is being called for the player)
valueMin - number - the min value of the statusbar (probably 0)
valueMax - number - the max value of the statusbar (probably the same as the return of UnitMaxHealth("player") +/- some negligible lag, if the func is being called for the player)

By using those you could spare yourself some global look-ups and only update when there is need to and not all player, target and focus every time TextStatusBar_UpdateTextStringWithValues has been called.

Edit: By the way, what is the third question?

Last edited by Rainrider : 07-23-13 at 04:33 PM.
  Reply With Quote
07-23-13, 10:56 PM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Rainrider View Post
lua Code:
  1. local SiValue = function(val)
  2.     if (val >= 1e6) then
  3.         return ("%.1fm"):format(val / 1e6)
  4.     elseif (val >= 1e3) then
  5.         return ("%.1fk"):format(val / 1e3)
  6.     else
  7.         return val
  8.     end
  9. end
would be a simple example without using blizzard's separators.
Just FYI, ("%d"):format(5) is slower than format("%d", 5) even if you don't upvalue format. If you do upvalue the global format, then format("%d", 5) is faster by a huge margin.

The only time you should use slower method syntax is if you're chaining a lot of operations together and want to keep it more human-readable, eg. ("blah blah %d blah"):format(5):upper():sub(8):gsub("a", "x")

Even small differences in speed can really add up in code that's run often, like inside a function that's formatting text every time a unit's health changes.
__________________
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
07-24-13, 05:18 PM   #6
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Oh, thank you, Phanx. Is there a good resource for all this stuff? I always suck at efficiency.
  Reply With Quote
07-24-13, 05:29 PM   #7
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
How do I use the code you wrote?
I'm pretty new to Lua.
  Reply With Quote
07-24-13, 07:45 PM   #8
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
1. Go to http://addon.bool.no/

2. Copy this code and paste it in the box on that page:
Code:
hooksecurefunc("TextStatusBar_UpdateTextStringWithValues", function(statusBar, fontString, value, valueMin, valueMax)
	local str, val
	if value >= 1e10 then
		-- Shorten 10,000,000,000+ like 12b
		str, val = "%.0fb", value / 1e9
	elseif value >= 1e9 then
		-- Shorten 1,000,000,000+ like 8.3b
		str, val = "%.1fb", value / 1e9
	elseif value >= 1e7 then
		-- Shorten 10,000,000+ like 14m
		str, val = "%.1fm", value / 1e6
	elseif value >= 1e6 then
		-- Shorten 1,000,000+ like 7.4m
		str, val = "%.2fm", value / 1e6
	elseif value >= 1e5 then
		-- Shorten 100,000+ like 84k
		str, val = "%.0fk", value / 1e3
	elseif value >= 1e3 then
		-- Shorten 1,000+ like 2.5k
		str, val = "%.1fk", value / 1e3
	else
		-- Don't shorten under 1,000
		str, val = "%d", value
	end
	fontString:SetFormattedText(str, val)
end)
3. Download the resulting addon and install it like any other addon.

You can remove the comments in the above code if you want to keep it shorter. If you only want to see whole numbers (eg. 157k or 12m) and never decimals (eg. 12.8m or 13.4k) use this code instead:

Code:
hooksecurefunc("TextStatusBar_UpdateTextStringWithValues", function(statusBar, fontString, value, valueMin, valueMax)
	local str, val
	if value >= 1e9 then
		-- 1,000,000,000+ like 8b
		str, val = "%.0fb", value / 1e9
	elseif value >= 1e6 then
		-- 1,000,000+ like 14m
		str, val = "%.0fm", value / 1e6
	elseif value >= 1e3 then
		-- 1,000+ like 2k
		str, val = "%.0fk", value / 1e3
	else
		-- Don't shorten numbers under 1,000
		str, val = "%d", value
	end
	fontString:SetFormattedText(str, val)
end)
Also, in this case there's no need to call string.format directly anyway, since it's even more efficient to use the fontstring's SetFormattedText method and offload the string processing into C code.
__________________
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.

Last edited by Phanx : 07-24-13 at 10:34 PM.
  Reply With Quote
07-24-13, 07:47 PM   #9
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Rainrider View Post
Oh, thank you, Phanx. Is there a good resource for all this stuff? I always suck at efficiency.
Not really. I've thought about putting one together, I'm not really sure how you'd organize a collection of random Lua tips, or whether anyone would really bother reading an unorganized list of tips. The best way to do it might be just compiling a list of links to forum threads with good explanations.
__________________
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
07-24-13, 08:45 PM   #10
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
18x hbitUI\hbitUI.lua:585: attempt to compare number with nil
hbitUI\hbitUI.lua:585: in function <hbitUI\hbitUI.lua:583>
<in C code>
FrameXML\TextStatusBar.lua:37: in function "TextStatusBar_UpdateTextString"
FrameXML\ReputationFrame.lua:424: in function "ReputationWatchBar_Update"
<string>:"*:OnEvent":6: in function <string>:"*:OnEvent":1

Locals:
(*temporary) = <func> =[C]:-1
= <func> @FrameXML\TextStatusBar.lua:41
= <func> @..\hbitUI.lua:583
I get this error in what is line 3 of your code with absvalue.
  Reply With Quote
07-24-13, 10:34 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Fixed; I'd copied the code from my unitframes addon, but forgot to change that variable 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
07-24-13, 10:50 PM   #12
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
It works, thanks you very much :-D
Sometimes I raid, and then percentage hp is very useful. So I thought of making a slashcommand: /pct to turn on percentage hp, since this can't be done in the interface options because this code disregards those settings. So current hp is default and when /pct is run it will run for the session only (until /reload etc.)
Is this possible to do?
  Reply With Quote
07-25-13, 01:53 PM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
1. Add this line to your addon's TOC file:

Code:
## SavedVariables: MyCustomTextFormat
2. Modify your addon's Lua code like so:

Code:
MyCustomTextFormat = "VALUE"

hooksecurefunc("TextStatusBar_UpdateTextStringWithValues", function(statusBar, fontString, value, valueMin, valueMax)
	local str, val
	if MyCustomTextFormat == "PERCENT" then
		-- Show the value as a percent
		str, val = "%.0f%%", value / valueMax * 100
	elseif value >= 1e10 then
		-- Shorten 10,000,000,000+ like 12b
		str, val = "%.0fb", value / 1e9
	elseif value >= 1e9 then
		-- Shorten 1,000,000,000+ like 8.3b
		str, val = "%.1fb", value / 1e9
	elseif value >= 1e7 then
		-- Shorten 10,000,000+ like 14m
		str, val = "%.1fm", value / 1e6
	elseif value >= 1e6 then
		-- Shorten 1,000,000+ like 7.4m
		str, val = "%.2fm", value / 1e6
	elseif value >= 1e5 then
		-- Shorten 100,000+ like 84k
		str, val = "%.0fk", value / 1e3
	elseif value >= 1e3 then
		-- Shorten 1,000+ like 2.5k
		str, val = "%.1fk", value / 1e3
	else
		-- Don't shorten under 1,000
		str, val = "%d", value
	end
	fontString:SetFormattedText(str, val)
end)

SLASH_CUSTOMSHORTTEXT1 = "/pct"
SlashCmdList.CUSTOMSHORTTEXT = function()
	MyCustomTextFormat = MyCustomTextFormat == "VALUE" and "PERCENT" or "VALUE"
	print("Short text now showing", strlower(MyCustomTextFormat))
end
If you don't want it to remember your preference between reloads or logouts, just skip Step 1.
__________________
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.

Last edited by Phanx : 07-25-13 at 01:56 PM.
  Reply With Quote
07-25-13, 02:08 PM   #14
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
Thank you Phanx you're very helpful
Can you make it update the values when you run the command somehow? Else you need to /rl, lose health, or gain health for it to update with your new setting (at least for your own frame).
  Reply With Quote
07-25-13, 02:51 PM   #15
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
I would just modify it to use the setting from the interface by checking if GetCVar("statusTextDisplay") is "PERCENT", "NUMERIC" or "BOTH".
  Reply With Quote
07-25-13, 09:01 PM   #16
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Here's a version that will use your CVar setting instead, as suggested by Semlar. I also converted the growing if-else chain into an easier-to-maintain indexed table loop:

Code:
local shorts = {
	{ 1e10, 1e9, "%.0fb" }, --  10b+ as  12b
	{  1e9, 1e9, "%.1fb" }, --   1b+ as 8.3b
	{  1e7, 1e6, "%.0fm" }, --  10m+ as  14m
	{  1e6, 1e6, "%.1fm" }, --   1m+ as 7.4m
	{  1e5, 1e3, "%.0fk" }, -- 100k+ as 840k
	{  1e3, 1e3, "%.1fk" }, --   1k+ as 2.5k
	{    0,   1,    "%d" }, -- < 1k  as  974
}
for i = 1, #shorts do
	shorts[i][4] = shorts[i][3] .. " (%.0f%%)"
end

hooksecurefunc("TextStatusBar_UpdateTextStringWithValues", function(statusBar, fontString, value, valueMin, valueMax)
	local style = GetCVar("statusTextDisplay")
	if style == "PERCENT" then
		return fontString:SetFormattedText("%.0f%%", value / valueMax * 100)
	end
	for i = 1, #shorts do
		local t = shorts[i]
		if value >= t[1] then
			return style == "BOTH"
				and fontString:SetFormattedText(t[4], value / t[2], value / valueMax * 100)
				or  fontString:SetFormattedText(t[3], value / t[2])
		end
	end
end)
__________________
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
07-26-13, 06:35 AM   #17
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
I changed a little bit:

Code:
local shorts = {
	{ 1e10, 1e9, "%.0fb" }, --  10b+ as  12b
	{  1e9, 1e9, "%.1fb" }, --   1b+ as 8.3b
	{  1e7, 1e6, "%.0fm" }, --  10m+ as  14m
	{  1e6, 1e6, "%.1fm" }, --   1m+ as 7.4m
	{  1e5, 1e3, "%.0fk" }, -- 100k+ as 840k
	{  1e3, 1e3, "%.1fk" }, --   1k+ as 2.5k
	{    0,   1,    "%d" }, -- < 1k  as  974
}
for i = 1, #shorts do
	shorts[i][4] = shorts[i][3] .. " (%.0f%%)"
end

local style = GetCVar("statusTextDisplay")

hooksecurefunc("TextStatusBar_UpdateTextStringWithValues", function(statusBar, fontString, value, valueMin, valueMax)
	if style == "PERCENT" then
		return fontString:SetFormattedText("%.0f%%", value / valueMax * 100)
	end
	for i = 1, #shorts do
		local t = shorts[i]
		if value >= t[1] then
			return style == "BOTH"
				and fontString:SetFormattedText(t[4], value / t[2], value / valueMax * 100)
				or  fontString:SetFormattedText(t[3], value / t[2])
		end
	end
end)

SLASH_HP1 = "/hp"
SlashCmdList.HP = function()
	if style == "NUMERIC" then
		SetCVar("statusTextDisplay", "PERCENT")
		print("You are now displaying percentage health.")
	elseif style == "PERCENT" then
		SetCVar("statusTextDisplay", "NUMERIC")
		print("You are now displaying numeric health.")
	else 
		print("You are displaying both current and percentage health.")
	end
end
I moved the local style = GetCVar("statusTextDisplay") out so I can use it in the main code and the slash command, and I tried to make a slash command that doesn't work as intended.

I can't get the SetCVar to work, it doesn't change the CVar.
It displays numeric health when it is set to BOTH I don't know if this is intentional, since I do not understand what this line:

Code:
if value >= t[1] then
Specifically the t[1] which really is shorts[1], I'm guessing it will show both if the target has more than 10 billion health because that is the first line of the shorts array?

I also tried changing:

Code:
{  1e9, 1e9, "%.1fb" }, --   1b+ as 8.3b
To:
Code:
{  1e9, 1e9, "% . 1fb" }, --   1b+ as 8 . 3b
To make it a little easier to read, but it doesn't work that way.

Also, in my country we use comma, I know of :gsub('%.', ',') but can it be used here?

Last edited by laukond : 07-26-13 at 06:58 AM.
  Reply With Quote
07-26-13, 08:15 AM   #18
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
t[1] equals shorts[i][1] (i.e. 1e10, 1e9 and so on) where i is the running index in the for loop. The meaning is to compare your current health value with t[1] so you don't end with 0.9k instead of 900.

SetFormattedText works just like lua's own format which in turn is based of C's printf. http://www.cplusplus.com/reference/cstdio/printf/ is a good reference. In order to produce language dependant output, you'll have to use gsub I believe

Something like that should work:
Code:
fontString:SetText(format(t[3], value/t[2]):gsub("%.", " , "))
(this would also add spaces before and after the decimal seperator)

As for your slash command:
The upvalue style is initialized when the file is first processed by the game. It takes the value of statusTextDisplay at this time and does not change later. You either have to call GetCVar("statusTextDisplay") in your slash command function or reassign style after calling SetCVar("statusTextDisplay", "whatever")
  Reply With Quote
07-26-13, 01:44 PM   #19
laukond
A Black Drake
Join Date: Dec 2011
Posts: 87
Okay it is more readable now and the CVar actually does change.
I still have the problem from earlier though: By changing the CVar this way the frames do not update in order to reflect the new change, so you have to re-target, lose/gain hp, etc.

If I do change it through the Interface menu it does update.


Edit: I am onto something!
Code:
/click InterfaceOptionsStatusTextPanelDisplayDropDownButton
/click DropDownList1Button2
In-game changes it to percentage now I'm trying to find out how to do it in Lua.

Edit2: It works!

Code:
SLASH_HP1 = "/hp"
SlashCmdList.HP = function()
	local style = GetCVar("statusTextDisplay")
	if style == "NUMERIC" then
		InterfaceOptionsStatusTextPanelDisplayDropDownButton:Click();
		DropDownList1Button2:Click();
		print("You are now displaying percentage health.")
	elseif style == "PERCENT" then
		InterfaceOptionsStatusTextPanelDisplayDropDownButton:Click();
		DropDownList1Button1:Click();
		print("You are now displaying numeric health.")
	else 
		print("You are displaying both current and percentage health.")
	end
end

Last edited by laukond : 07-26-13 at 01:57 PM.
  Reply With Quote
07-26-13, 07:50 PM   #20
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
The reason for this behavior is that Blizzard updates the status texts when CVAR_UPDATE fires. This event does not (always?) fire when using SetCVar, unless you provide a third argument, typically your addon name. You could skip the
Code:
InterfaceOptionsStatusTextPanelDisplayDropDownButton:Click();
DropDownList1Button2:Click();
part and just use SetCVar calls instead:
Code:
SetCVar("statusTextDisplay", "whatever_value_you_need", "HP")
This will trigger TextStatusBar_OnEvent which will call TextStatusBar_UpdateTextString, which will call TextStatusBar_UpdateTextStringWithValues, which will trigger your hook and alter the display.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » 3 Questions

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