Reply
 
Thread Tools Display Modes
Old 05-21-13, 10:29 AM   #1
Rusken
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Dec 2009
Posts: 61
Lua code help (stuf text)

Evening, i got this custom lua code from a fella over at mmo a couple of months back and what it does is that it shortens name like "Raider's Training Dummy" in to "R.T.Dummy".
What i need help with is to change the code so it still does what it does but i want it to look like this ->

"R.T.Dummy | 100", 100 being perchp and i want it to be colored by "hpthreshold", the name and the "|" should be white.

So, is this possible and is there any kind soul here with the knowledge on how to do this that could give me a hand?
Thanks in advance.
Rusken is offline   Reply With Quote
Old 05-21-13, 04:01 PM   #2
SDPhantom
A Molten Giant
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 941
It would be easier if you posted a copy of the working code as-is. Be sure to encase it in [code] tags.
__________________
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
SDPhantom is offline   Reply With Quote
Old 05-22-13, 06:32 AM   #3
ravagernl
Macro Murloc mgrlglrgl!
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,136
Originally Posted by SDPhantom View Post
It would be easier if you posted a copy of the working code as-is. Be sure to encase it in [code] tags.
I'm thinking it's something like
Code:
function(unit)
	local name = UnitName(unit) or unit
	name = name:gsub('(%S+) ',function(t) return t:sub(1,1)..'.' end)
	return name
end
ravagernl is offline   Reply With Quote
Old 05-22-13, 10:26 AM   #4
Rusken
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Dec 2009
Posts: 61
Oh snap, forgot to do that, its the one ravagernl posted.

Code:
function(unit)
	local name = UnitName(unit) or unit
	name = name:gsub('(%S+) ',function(t) return t:sub(1,1)..'.' end)
	return name
end
Rusken is offline   Reply With Quote
Old 05-22-13, 12:44 PM   #5
SDPhantom
A Molten Giant
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 941
This has an improvement over the unit's name conversion as it doesn't allocate a dynamic function to handle the string.gsub() call and it's kept on C side. The way I have the coloring work is it starts as green at 100%, moves to yellow at 50% and red at 0%. The way text colors work is they use UI escape sequences. The one for colors is in the format |cAARRGGBB in which AA, RR, GG, and BB represent hex values for Alpha, Red, Green, and Blue respectively. Although it should be customary to use |r as an end tag for colored text, it's not necessary if you're immediately changing to another color for following text. The purpose of |r is to reset the color of following text to what is set by the object that is given the string to display. The use of || is to print a literal pipe character "|" as this is used for the UI escape sequences.
Code:
function(unit)
	local short=(UnitName(unit) or unit):gsub("(%S)%S*%s+","%1%.");
	local pcnt=math.min(1,UnitHealth(unit)/UnitHealthMax(unit));-- If max is zero (it happens) assume 100%
	local r,g=math.max(0,2-pcnt*2)*255,math.min(1,pcnt*2)*255;

	return ("|cffffffff%s || |cff%02x%02x00%.0f|r"):format(short,r,g,pcnt*100));
end

This is to get dynamic text colors to work in a string-only standpoint, but it'll be much better to leave the static colors in the string and control the dynamic color from a FontString object. The following code makes use of this.
Code:
function(obj,unit)
	local short=(UnitName(unit) or unit):gsub("(%S)%S*%s+","%1%.");
	local pcnt=math.min(1,UnitHealth(unit)/UnitHealthMax(unit));-- If max is zero (it happens) assume 100%
	obj:SetTextColor(math.max(0,2-pcnt*2),math.min(1,pcnt*2),0);
	obj:SetFormattedText("|cffffffff%s |||r %.0f",short,pcnt*100));
end

UI Escapes (WoWPedia)
__________________
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
SDPhantom is offline   Reply With Quote
Old 05-23-13, 05:52 PM   #6
Rusken
A Theradrim Guardian
AddOn Compiler - Click to view compilations
Join Date: Dec 2009
Posts: 61
Originally Posted by SDPhantom View Post
This has an improvement over the unit's name conversion as it doesn't allocate a dynamic function to handle the string.gsub() call and it's kept on C side. The way I have the coloring work is it starts as green at 100%, moves to yellow at 50% and red at 0%. The way text colors work is they use UI escape sequences. The one for colors is in the format |cAARRGGBB in which AA, RR, GG, and BB represent hex values for Alpha, Red, Green, and Blue respectively. Although it should be customary to use |r as an end tag for colored text, it's not necessary if you're immediately changing to another color for following text. The purpose of |r is to reset the color of following text to what is set by the object that is given the string to display. The use of || is to print a literal pipe character "|" as this is used for the UI escape sequences.
Code:
function(unit)
	local short=(UnitName(unit) or unit):gsub("(%S)%S*%s+","%1%.");
	local pcnt=math.min(1,UnitHealth(unit)/UnitHealthMax(unit));-- If max is zero (it happens) assume 100%
	local r,g=math.max(0,2-pcnt*2)*255,math.min(1,pcnt*2)*255;

	return ("|cffffffff%s || |cff%02x%02x00%.0f|r"):format(short,r,g,pcnt*100));
end

This is to get dynamic text colors to work in a string-only standpoint, but it'll be much better to leave the static colors in the string and control the dynamic color from a FontString object. The following code makes use of this.
Code:
function(obj,unit)
	local short=(UnitName(unit) or unit):gsub("(%S)%S*%s+","%1%.");
	local pcnt=math.min(1,UnitHealth(unit)/UnitHealthMax(unit));-- If max is zero (it happens) assume 100%
	obj:SetTextColor(math.max(0,2-pcnt*2),math.min(1,pcnt*2),0);
	obj:SetFormattedText("|cffffffff%s |||r %.0f",short,pcnt*100));
end

UI Escapes (WoWPedia)
Thanks but none of them seem to work when i paste them in to "use custom lua" in stuf, is it something i need to add to the actual .lua?
As you might have noticed, my lua skills are worse then worse
Rusken is offline   Reply With Quote
Old 05-24-13, 10:07 PM   #7
Rainrider
A Rage Talon Dragon Guard
Join Date: Nov 2008
Posts: 312
I have a very similar issue I posted about here and Phanx pointed me to this thread as it closely relates to my problem.

What SDPhantom suggested (unit:gsub("(%S)%S*%s+","%1%.")) is what I looked for, but I need to make this work with languages other than english. The string I test with is "Echo of a Pandaren Monk" and the single 'a' appears to be the problem if I use the following:

Code:
unit:gsub("(.[\128-\191]*)%S+%s", "%1. ")
.
I get "E. o. a . Monk" instead of "E. o. a P. Monk".

I also don't understand what exactly is .[\128-\191]* supposed to mean but it makes it work for non-english characters (haven't tested chinese and korean though, but I do not look for such functionality).

Sorry for writing in between.
Rainrider is offline   Reply With Quote
Old 05-25-13, 02:04 AM   #8
ravagernl
Macro Murloc mgrlglrgl!
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,136
Originally Posted by Rainrider View Post
I also don't understand what exactly is .[\128-\191]* supposed to mean but it makes it work for non-english characters (haven't tested chinese and korean though, but I do not look for such functionality).

Sorry for writing in between.
I think range 128 - 191 match the diacritic characters used to compose a unicode character (first 128 are basically ascii characters).

EDIT: Found this on http://lua-users.org/wiki/LuaUnicode:
Happily UTF-8 is designed so that it is relatively easy to count the number of unicode symbols in a string: simply count the number of octets that are in the ranges 0x00 to 0x7f (inclusive) or 0xC2 to 0xF4 (inclusive). (In decimal, 0-127 and 194-244.) These are the codes which can start a UTF-8 character code. Octets 0xC0, 0xC1 and 0xF5 to 0xFF (192, 193 and 245-255) cannot appear in a conforming UTF-8 sequence; octets in the range 0x80 to 0xBF (128-191) can only appear in the second and subsequent octets of a multi-octet encoding. Remember that you cannot use \0 in a Lua pattern.

Last edited by ravagernl : 05-25-13 at 02:45 AM.
ravagernl is offline   Reply With Quote
Old 05-25-13, 07:41 PM   #9
Rainrider
A Rage Talon Dragon Guard
Join Date: Nov 2008
Posts: 312
Oh, I actually read your quoted link before and now it makes sense. Thank you.

I also found the solution to the other issue: just use '%S' instead of '.':
Code:
string.gsub("Echo of a Pandaren Monk", "(%S[\128-191]*)%S+%s", "%1. ")
Is there any way to make this work for the Russian client too?

Edit: It actually works for Russian with the exception that it also matches the single 'a'. This is a cool page to look up uft8 characters as you can read the corresponding lua excape sequence from it. So for cyrillic 'a' it would be \208\176. I still don't get why this is a match, as I require one or more non-space characters after what's in my capture.
Attached Thumbnails
Click image for larger version

Name:	WoWScrnShot_052613_044615.jpg
Views:	161
Size:	50.2 KB
ID:	7737  

Last edited by Rainrider : 05-25-13 at 08:50 PM.
Rainrider is offline   Reply With Quote
Old 05-27-13, 12:36 AM   #10
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 3,942
You're getting that ? character because you're actually breaking the Russian character \208\176 (а) in half, keeping only \208 which is not a valid Unicode character by itself. The string functions in WoW are not Unicode aware; they only look at bytes. If you want to support languages with multi-byte characters, you can either use the UTF8 library which provides UTF8-aware versions of some string functions, or you can split it up, count bytes, etc. yourself.

Either way it's going to take more than a simple gsub. You'd probably want to just split it up into "Russian clients use this code path" and "everyone else use this code path" since Korean and Chinese (the other WoW locales with multi-byte characters) generally don't use spaces between words, and cannot be meaningfully abbreviated anyway.

Code:
local old, new = "Echo of a Pandaren Monk"
if GetLocale() == "ruRU" then
    -- complicated version
    new = ""
    for word in string.gmatch(old, "(%S+)%s") do
        new = new .. string.utf8sub(word, 1, 1), " " -- uses UTF8 lib function
    end
    new = new .. strmatch(old, "%S+$")
else
    -- simple version
    new = gsub(old, "(%S[\128-191]*)%S+%s", "%1. ")
end
-- do something with new here
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Old 05-27-13, 01:25 PM   #11
Rainrider
A Rage Talon Dragon Guard
Join Date: Nov 2008
Posts: 312
I just still wonder why it is a match. The representation of the 'a ' as lua escape sequence is \208\176\32. One can verify that by:
lua Code:
  1. local str = "Ецхо оф а Пандарен Монк"
  2.  
  3. for i=1, #str do
  4.    print(i, str:byte(i))
  5. end

In my match pattern I demand a non-space character, followed by zero or more characters from the range between \128 and \191, followed by one or more non-space characters, followed by a space character. \32 is a space character, but there is nothing else between \176 and \32, so the match should actually fail. As it appears, it matches the \208 in my capture, the \176 as the non-space char and the \32 as the space char. So why does it skip the \176 in the capture, when '*' means zero or more and the longest possible match of that?

Appart from that, I don't believe single characters would occur in unit names in the russian locale. The translation for 'a' is 'один'/'одна'/'одно' (they decline those depending on gender). Is there a way to verify that on wowhead?
Rainrider is offline   Reply With Quote
Old 05-27-13, 02:32 PM   #12
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 3,942
Code:
string.gsub("Echo of a Pandaren Monk", "(%S[\128-191]*)%S+%s", "%1. ")
That pattern doesn't require one or more non-whitespace characters. It requires one or more non-whitespace bytes (eg. \32 is flagged as "whitespace"). In the case of multi-byte characters, the extra bytes per character are matched. In the case of \208\176, neither \208 nor \176 by themselves are "whitespace" so string.gsub sees them as separate non-whitespace entities, since it is not Unicode-aware.

As for your other question, "Echo of a Pandaren Monk" [url="http://ru.wowhead.com/npc=58669"]in Russian[/b] is "Эхо пандарена-монаха". The preposition "of" is generally not used directly in Russian (the declension of the relevant noun changes instead) and articles like "a" and "the" are generally omitted. There are one-character words in Russian that are used often -- в, с, к, у are several that spring to mind -- but I don't know if any of them appear in NPC names.

Edit: A quick scan of Wowhead in Russian finds at least one NPC name with a single-character word -- Эрунак Говорящий с Камнем. There are likely more, but I quit looking after spotting the first one on page 2.
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!

Last edited by Phanx : 05-27-13 at 02:40 PM.
Phanx is offline   Reply With Quote
Old 05-27-13, 04:40 PM   #13
Rainrider
A Rage Talon Dragon Guard
Join Date: Nov 2008
Posts: 312
Wow, I've learnt russian for 7 years, but haven't spoken it for the last 15 years now. And you beat me to it, your explanations are perfectly right. Shame on me

You are also right about character vs word, I worded it incorrectly, but I think my previous post still holds true.

Code:
(%S[\128-191]*)%S+%s
The part of my transliterated name for the pandaren monk (just the 'a' and the whitespace after it:
Code:
\208\176\32
There isn't a match for the red part, is it? I'm sorry, I still don't understand why it matches the way it does. Thank you very much for trying to explain it to me that persistently.
Rainrider is offline   Reply With Quote
Reply

Go BackWoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » Lua code help (stuf text)

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