Posted by Drunk Cadaver on Wed, 15 Dec 2010 21:33:20
I'm working on a project that takes system chat messages that contain a hyperlink for a player and pulls the player's name from the message. I've looked at a number of different sites doing my best to figure out the patterns and I thought I had come up with a solution. Using one of my characters as an example, here is my basic code.
local hyperlink = "|Hplayer :Roheit|h[Roheit]|h" local _,_,name = string.find(hyperlink,"|Hplayer :(%a+)|?h?[?%a+]?|?h?") print(name)
This prints "Roheit". When I tested the code with my character Räude, all I get is "R". I know it has to do with "ä" but I can't figure out how to find the full name with a pattern.
Once I get this worked out, I'll be able to cut one of my mods down drastically. Any help provided will be greatly appreciated.
Posted by jnwhiteh on Fri, 17 Dec 2010 14:59:48
%a won't match ä because its not an alphabetic ASCII character, based on the character classes. What you can use is [^|] which means 'any character that isn't the pipe character' and use + on that.
Posted by Drunk Cadaver on Fri, 17 Dec 2010 17:18:35
Thank you so much. That worked beautifully. This pattern stuff gives me some serious brain pain. :)
Posted by Drunk Cadaver on Fri, 17 Dec 2010 19:56:43
Well that worked in wowlua, but when I put the code into my mod, it doesn't seem to work the way I was expecting. Here is the code I am using in the mod once my frame registers the event.
if event == "CHAT_MSG_SYSTEM" then local total_friends = GetNumFriends() if (social_info:find("online") ~= nil) then print("Online found.") local _,_,hyperlink,_ = string.find(social_info,"(%S+)[%s]*(.*)") print(hyperlink .. " found.") local _,_,playername = string.find(hyperlink,"|Hplayer :([^|]+)|?h?[?[^|]+]?|?h?") for i=1,total_friends do name,_,_,_,_,_,_,_ = GetFriendInfo(i) if playername == name then print(playername .. " found! ONLINE!") social_info = " " break end end end end
"Online found." and "[hyperlink] found." print as expected but the player's name is not pulled form the hyperlink. Is there something I'm missing?
I have another question that could make all this unnecessary . I found the WoW Constants/Errors page on wowpedia. Is it possible to find ERRFRIENDONLINE_SS specifically? If it is possible, can I also find "%s" inside "|Hplayer :%s|h[%s]|h has come online."?
Posted by jnwhiteh on Sat, 18 Dec 2010 14:53:30
You don't need Wowpedia to find those, they're all in GlobalStrings.lua in the FrameXML code. Using them directly is not completely trivial to make them work on all locales. There is a library called Deformat that can take a global string like that and turn it into a pattern that you can use to re-extract the arguments out of the actual message.
Additionally, if the string you want to match is:
"|Hplayer :%s|h[%s]|h has come online."
Then you should be able to extract it with:
"|Hplayer :%s|h%[%s%]|h has come online%."
Posted by Drunk Cadaver on Sat, 18 Dec 2010 17:50:41
I looked through the book reading about GlobalStrings and I downloaded the library LibDeformat-3.0. I understand how the GlobalStrings work now after doing a couple simple print() tests in wowlua
and I can see how that will be used in LibDeformat,
LibDeformat(social_msg, "|Hplayer :%s|h[%s]|h has come online.") == "playername", "playername"
I don't understand how to use the global string with LibDeformat though. If I use "|Hplayer :%s|h%[%s%]|h has come online%." will it work regardless of localization? Or do I use the following:
LibDeformat(social_msg, ERR_FRIEND_ONLINE_SS) == "playername", "playername"
Thank you for your time and patience.
Posted by jnwhiteh on Sun, 19 Dec 2010 00:40:47
The last is correct if you want this to work for all locales, that's the beauty (and complexity) of LibDeformat. You may be able to 'reverse' format strings for very simple cases, but if you consider non-English locales where even the order of the arguments may be reversed (I discuss this in the book, where the actor and object are sometimes reversed) then you need LibDeformat or something like it in order to work correctly. Using the symbolic constant name is the correct way to make this work.