Thread Tools Display Modes
04-16-11, 08:12 AM   #1
Folji
A Flamescale Wyrmkin
 
Folji's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 136
Addon to split *emotes* out of messages

Basically, I'm looking for an addon that'll let me write *asterisk emotes* in a chat message and have those split into separate /emotes once the message is posted.

If I, for instance, write a message that goes:
Some message. *some emote.*
It'll be output in the chat as:
<Player> says: Some message.
<Player> some emote.
________________________
Vice versa, if I write the emote before the message, like this:
*some emote.* Some message.
It'll appear as:
<Player> some emote.
<Player> says: Some message.
________________________
Or if I do both several times within a message:
Some message. *some emote.* Some message. *some emote.*
That'll work too:
<Player> says: Some message.
<Player> some emote.
<Player> says: Some message.
<Player> some emote.
________________________
Support for the game's built-in emotes would also be nice:
Some message. *openfire* (or */openfire*)
Becomes:
<Player> says: Some message.
<Player> gives the order to open fire.
I had something that did this some time ago, but it was part of a bigger addon together with lots of other integrated features. It's been a while since I used that addon, it's been a while since last time there was much word from the developer, and it seems a bit crude to seek him out just to ask if he can extract that feature and make it an independent addon. So if there are anyone here with the time and energy to whip up an addon like this (can't imagine it being that hard), that'd be totally awesome (alternatively, if anyone knows of an addon that already does this, that'd be even more awesome).
  Reply With Quote
04-16-11, 10:16 AM   #2
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
I think I see what you mean, basically something like this I guess?


It should be possible by pre-hooking SendChatMessage I reckon.

Code:
local orig = SendChatMessage
function SendChatMessage(text, chan, ...)
  if chan ~= "EMOTE" then
    local emote = text:match("*(.+)*")
    if emote then
      text = text:gsub("*(.+)*", "")
      orig(text, chan, ...)
      return DoEmote(emote)
    end
  end
  return orig(text, chan, ...)
end
It's just an example, haven't tested it and there may be an easier way to do this. In short what I tried to do is match the "*string*" remove it from the message then send the message and finally the emote in the ** tags.
  Reply With Quote
04-16-11, 11:57 AM   #3
Folji
A Flamescale Wyrmkin
 
Folji's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 136
Yeah, that's pretty much exactly what I'm after, though I'm judging by the third line that it would kick in whenever the channel is not EMOTE (I've programmed in AS3, but never in Lua). The best way would be if it only does its work when it's posted to the SAY channel. Still, that is pretty much what I'm after.
  Reply With Quote
04-16-11, 03:39 PM   #4
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,326
Originally Posted by Vladinator View Post
Code:
local orig = SendChatMessage
function SendChatMessage(text, chan, ...)
  if chan ~= "EMOTE" then
    local emote = text:match("*(.+)*")
    if emote then
      text = text:gsub("*(.+)*", "")
      orig(text, chan, ...)
      return DoEmote(emote)
    end
  end
  return orig(text, chan, ...)
end
There's a couple errors in the pattern. The asterisk is a magic character that needs to be escaped. Also, you need the capture to match as little as possible so it doesn't try to overflow outside the terminating asterisk if another one exists in the message or multiple emotes are in the message. You should use either "%*([^%*]-)%*" or "%*(.-)%*".
__________________
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)
  Reply With Quote
04-16-11, 03:46 PM   #5
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
The Lua patterns gods have spoken

Sorry, couldn't keep it down
  Reply With Quote
04-16-11, 04:48 PM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,326
I put together some code to do exactly what was described. It only operates on /say and it will attempt to use the emote slash command if it finds one that matches, otherwise, it'll send the emote out through the emote channel. Theoreticly, the slash command emotes support a target argument that lets you specify what UnitID to target. This option has been added in to this code as well.
lua Code:
  1. local Send=SendChatMessage;
  2. local pieces={};
  3. function SendChatMessage(msg,chan,...)
  4.     chan=chan:upper();--    Convert to make checks easier (channel is case-insensitive)
  5.     if chan=="SAY" then
  6. --      Clear our piece table
  7.         table.wipe(pieces);
  8.  
  9. --      Remove empty emotes and strip all spaces around "*" (try to replace empty emotes with a single space)
  10.         msg=strtrim(msg):gsub("%s*%*%s*%*%s*"," "):gsub("%s*%*%s*","%*");
  11.  
  12. --      Split string (strsplit() isn't working the way we need it to)
  13.         for i in msg:gmatch("[^%*]+") do pieces[#pieces+1]=i; end
  14.         if msg:sub(1,1)=="*" then table.insert(pieces,1,""); end
  15.  
  16. --      Iterate through pieces
  17.         for i,j in ipairs(pieces) do
  18.             if #j>0 then--  Don't do anything if string is empty
  19.                 if i%2>0 then-- Evaluates to 1 if say, 0 if emote
  20.                     Send(j,chan);
  21.                 else
  22. --                  Try to separate command and args
  23.                     local cmd,arg=j:match("(%S+) (.+)");
  24.                     if not cmd then cmd=j; end
  25.  
  26. --                  This is tricky, we need to check if the emote slash command exists
  27.                     local token;
  28.                     local tokencheck,tokenid=EMOTE1_TOKEN,1;
  29.                     while tokencheck do
  30.                         local cmdcheck,cmdid=_G["EMOTE"..tokenid.."_CMD1"],1;
  31.                         while cmdcheck do
  32.                             local slashcmd=cmdcheck:sub(2):lower();--   Skip the slash for the emote command
  33.                             if slashcmd==cmd:lower() then-- Command matches, token found
  34.                                 token=tokencheck;
  35.                                 break;
  36.                             end
  37.  
  38. --                          Increment command
  39.                             cmdcheck,cmdid=_G["EMOTE"..tokenid.."_CMD"..(cmdid+1)],cmdid+1;
  40.                         end
  41.  
  42. --                      Break if token found
  43.                         if token then break; end
  44.  
  45. --                      Increment token
  46.                         tokencheck,tokenid=_G["EMOTE"..(tokenid+1).."_TOKEN"],tokenid+1;
  47.                     end
  48.  
  49.                     if token then
  50.                         DoEmote(token,arg);--   Performs the same emote operation as supported by chat
  51.                     else
  52.                         Send(j,"EMOTE");
  53.                     end
  54.                 end
  55.             end
  56.         end
  57.     else
  58.         Send(msg,chan,...);
  59.     end
  60. end
__________________
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 : 04-19-11 at 12:35 PM.
  Reply With Quote
04-16-11, 07:09 PM   #7
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Take a look on what I wrote and give me some feedback:

lua Code:
  1. local trim = function(str)
  2.   return str:trim(" \t\r\n")
  3. end
  4.  
  5. local match = function(str)
  6.   local ret = {}
  7.   for msg, emote in str:gmatch("(.-)%*(.-)%*") do
  8.     str = str:replace(msg, "")
  9.     str = str:replace("*"..emote.."*", "")
  10.     msg = trim(msg)
  11.     emote = trim(emote)
  12.     table.insert(ret, {
  13.       msg:len() > 0 and msg or nil,
  14.       emote:len() > 0 and emote or nil,
  15.     })
  16.   end
  17.   str = trim(str)
  18.   if str:len() > 0 then
  19.     table.insert(ret, {str, nil})
  20.   end
  21.   return #ret > 0 and ret or nil
  22. end

In short, match("message") will return either nil if nothing matched or a table containing {message, emote} that you can go trough each one, unpack each entry and send the message in the /say or /emote channels depending if it's a string or nil.

Far better than my first sketch, aye?

Last edited by Vlad : 04-16-11 at 07:34 PM.
  Reply With Quote
04-16-11, 08:29 PM   #8
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,326
string.trim() does not exist in the Lua core, however, the WoW API supplies strtrim() to do this and the default character string is " \t\r\n" if left undefined.

I still prefer my string splitting approach plus the added features the OP requested. Also to note, DoEmote() requires an emote token to run, you need to send it through the EMOTE channel with SendChatMessage() for custom emotes.
__________________
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)
  Reply With Quote
04-17-11, 02:16 AM   #9
Folji
A Flamescale Wyrmkin
 
Folji's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 136
Originally Posted by SDPhantom View Post
I put together some code to do exactly what was described. It only operates on /say and it will attempt to use the emote slash command if it finds one that matches, otherwise, it'll send the emote out through the emote channel. Theoreticly, the slash command emotes support a target argument that lets you specify what UnitID to target. This option has been added in to this code as well.
lua Code:
  1. local Send=SendChatMessage;
  2. function SendChatMessage(msg,chan,...);
  3.     chan=chan:upper();--    Convert to make checks easier (channel is case-insensitive)
  4.     if chan=="SAY" then
  5. --      Strip all spaces around "*" and split into segments
  6.         local pieces={strsplit("*",msg:gsub("%s*%*%s*","%*"))};
  7.  
  8. --      Iterate through pieces
  9.         for i,j in ipairs(pieces) do
  10.             if #j>0 then--  Don't do anything if string is empty
  11.                 if i%2>0 then-- Evaluates to 1 if say, 0 if emote
  12.                     Send(j,chan);
  13.                 else
  14. --                  Try to separate command and args
  15.                     local cmd,arg=j:match("(%S+) (.+)");
  16.                     if not cmd then cmd=j; end
  17.  
  18. --                  This is tricky, we need to check if the emote slash command exists
  19.                     local token;
  20.                     local tokencheck,tokenid=EMOTE1_TOKEN,1;
  21.                     while tokencheck do
  22.                         local cmdcheck,cmdid=_G["EMOTE"..tokenid.."_CMD1"],1;
  23.                         while cmdcheck do
  24.                             local slashcmd=cmdcheck:sub(2):lower();--   Skip the slash for the emote command
  25.                             if slashcmd==cmd:lower() then-- Command matches, token found
  26.                                 token=tokencheck;
  27.                                 break;
  28.                             end
  29.  
  30. --                          Increment command
  31.                             cmdcheck,cmdid=_G["EMOTE"..tokenid.."_CMD"..(cmdid+1)],cmdid+1;
  32.                         end
  33.  
  34. --                      Break if token found
  35.                         if token then break; end
  36.  
  37. --                      Increment token
  38.                         tokencheck,tokenid=_G["EMOTE"..(tokenid+1)"_TOKEN",tokenid+1;
  39.                     end
  40.  
  41.                     if token then
  42.                         DoEmote(token,arg);--   Performs the same emote operation as supported by chat
  43.                     else
  44.                         Send(j,"EMOTE");
  45.                     end
  46.                 end
  47.             end
  48.         end
  49.     else
  50.         Send(msg,chan,...);
  51.     end
  52. end
So basically, I could take that code, put it in a .lua file, write a .toc file for it, put them in a folder and place it in the AddOns folder, and it'll work right out of the box? (Though it'd probably be better if someone who knows their way around the stuff does it, so that more people than just myself can benefit from it. )
  Reply With Quote
04-17-11, 04:07 AM   #10
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Yes, you just gotta write it a .toc and put it in a folder so it becomes an addon.

Anyway gonna put this here http://pastey.net/149152 and now I can delete the local file from my PC, hehe.

Both will work, you pick what ever you like.
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Search/Requests » Addon to split *emotes* out of messages


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