Thread Tools Display Modes
02-25-13, 05:47 AM   #1
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
quick noob question about strings and unitID

Hey can someone answer a quick question for me, I am looking to filter the speaker in CHAT_MSG by unitID rather than semantic STRING match.

for example let's say my friend's name is Coolguy (he's in my party in the 2nd slot) and I'm listening for anything he said in chat

local f = CreateFrame("Frame")

f:RegisterEvent("CHAT_MSG_SAY")

f:SetScript("OnEvent", function(self, event, msg, sender, ...)
if (event == "CHAT_MSG_SAY" and sender == "Coolguy" ) then
print("Coolguy said something")
end
end)

that works.

but I'm wondering if I can use a unitID (party1 or player for example). in the API reference for CHAT_MSG, author is indicated as string but wondering if

if (event == "CHAT_MSG_SAY" and sender == party1 ) then

does not work/


also if someone can point me to a reference of how to check for words in a whole msg string... for example if I'm looking to flag any time someone says Blizzard in a sentence... I'm guessing I stick the thing in an array and search each element or something. but I'm a nob

thanks in advance
  Reply With Quote
02-25-13, 06:06 AM   #2
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
well it's UnitName("party1") :/

found the syntax under the reference for SendChatMessage. look for it for an hour... then post for help and find it in 5 min lol

if anyone can point me in the direction for my 2nd question, would appreciate it.

Last edited by shalom69 : 02-25-13 at 06:10 AM.
  Reply With Quote
02-25-13, 06:10 AM   #3
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
You'd have to do something like:

Code:
if sender == UnitName("party1") then
To check for a certain word in a string you need to use strfind:

Code:
if strfind(strlower(msg), "blizzard") then
You'll probably want to use strlower or strupper on msg, like I did in the example, so that you can search for a pattern regardless of upper and lower case.
  Reply With Quote
02-25-13, 06:50 AM   #4
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
cool thanks man.

Last edited by shalom69 : 02-25-13 at 07:00 AM.
  Reply With Quote
02-25-13, 01:29 PM   #5
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
Or just
Lua Code:
  1. if msg:lower():find("blizzard") then
:)

Edit: They do the same thing really, it's just different ways to do it.
  Reply With Quote
02-25-13, 09:59 PM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
strfind(strlower(msg), "blizzard") is significantly faster than msg:lower():find("blizzard") though, especially if you upvalue strfind and strlower. I only use the metamethod notation when I'm chaining a lot of string operations and the former would make it too annoying to read, like msg:trim():lower():gsub("a", "b"):gsub("x", "y"):match("blah"). Granted, for single operations in actual usage the speed isn't really important, but if you're doing a lot of string operations, or you're working inside an OnUpdate script or CLEU handler, every little bit counts, and I find it helpful to be in the habit of using the faster notation anyway.
__________________
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
02-26-13, 07:31 AM   #7
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
Originally Posted by F16Gaming View Post
Or just
Lua Code:
  1. if msg:lower():find("blizzard") then


Edit: They do the same thing really, it's just different ways to do it.
Hmm I'm not familiar with that syntax. The strfind entry was on the WOW API reference so I could see how Haleth's example worked. I guess in this example "find("string") is a command native to lua for the msg argument?

It's good to know different ways to do stuff I'll file that somewhere in the "look up later" bin in case I need it sometime.

BTW can anyone explain to me why nesting IFs doesn't work in the following code?

I actually was using the code in the first post to test if I had the semantics right for handling and sorting through chat events. I'm practicing writing a noob addon that gives me alerts on my main while multiboxing. It's rudimentary code including the /say and raid alerts but wondering why if-if-if doesn't work in the following code. if-elseif-elseif works. is it because CHAT_MSG_SAY is and can only be 1 incident? if someone could take a min and explain why I can't use if-if that would be awesome. The chat messages received in the code are generated in another frame that registers events (autofollow_end, player_regen_disbled etc)

Code:
LeaderMessageHandlerFrame = CreateFrame("Frame")
LeaderMessageHandlerFrame:RegisterEvent("CHAT_MSG_SAY")
LeaderMessageHandlerFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
  if thisIsLeadWindow then
    if (msg == "NO LONGER FOLLOWING")  then
      RaidNotice_AddMessage(RaidWarningFrame, sender .." NO LONGER FOLLOWING", ChatTypeInfo["RAID_WARNING"])
    elseif (msg == "AGRO" and notUnitAffectingCombat("player"))  then
      RaidNotice_AddMessage(RaidWarningFrame, sender .." HAS AGRO", ChatTypeInfo["RAID_WARNING"])
    elseif (strfind(strlower(msg), "target is")) then
      local _,_,_, cloneTargetName = strsplit(" ", msg, 4)
       local myTargetName = (UnitName("playertarget"))
       if (cloneTargetName  ~= myTargetName and UnitIsFriend("player",cloneTargetName)==nil) then
         RaidNotice_AddMessage(RaidWarningFrame, sender .." IS ON DIFFERENT TARGET (".. cloneTargetName..")", ChatTypeInfo["RAID_WARNING"])
       end
    elseif (msg == "I AM UNDER ATTACK" and sender ~=UnitName("player"))  then
      print(sender)
      RaidNotice_AddMessage(RaidWarningFrame, sender .." IS UNDER ATTACK", ChatTypeInfo["RAID_WARNING"])
    end
  end
end)
also the following function for that thisIsLeadWindow check (I have LeaderFlagToggle function bound to a key through bindings.xml to tell the addon if it's running on a clone or the main window)

Code:
function LeaderFlagToggle()
  if not thisIsLeadWindow then
   thisIsLeadWindow = "true"
  else
   thisIsLeadWindow = "nil"
  end
end

BINDING_HEADER_CLONESTATES = "CloneStates"
BINDING_NAME_TOGGLELEADERSTATUS = "Toggle CloneStates Leader Flag"
I'm sure there's better ways to program the above which I'll learn as I go but it seems like I should be able to use if-if-if since all those are discrete incidents. On the subject, can anyone explain the usage of if-then statement around my command to register events? something like:

Code:
if thisIsLeadWindow then
  LeaderMessageHandlerFrame:RegisterEvent("CHAT_MSG_SAY")
end
I didn't get an error but nothing registered. I'm guessing that the RegisterEvent has to happen onload or something else I'm not familiar with

thanks in advance

Last edited by shalom69 : 02-26-13 at 09:13 PM.
  Reply With Quote
02-26-13, 09:56 AM   #8
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
Originally Posted by shalom69 View Post
Code:
LeaderMessageHandlerFrame = CreateFrame("Frame")
LeaderMessageHandlerFrame:RegisterEvent("CHAT_MSG_SAY")
LeaderMessageHandlerFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
    if (msg == "NO LONGER FOLLOWING")  then
      RaidNotice_AddMessage(RaidWarningFrame, sender .." NO LONGER FOLLOWING", ChatTypeInfo["RAID_WARNING"])
    elseif (msg == "AGRO" and notUnitAffectingCombat("player"))  then
      RaidNotice_AddMessage(RaidWarningFrame, sender .." HAS AGRO", ChatTypeInfo["RAID_WARNING"])
    elseif (strfind(strlower(msg), "target is")) then
      local _,_,_, cloneTargetName = strsplit(" ", msg, 4)
       local myTargetName = (UnitName("playertarget"))
       if (cloneTargetName  ~= myTargetName and UnitIsFriend("player",cloneTargetName)==nil) then
         RaidNotice_AddMessage(RaidWarningFrame, sender .." IS ON DIFFERENT TARGET (".. cloneTargetName..")", ChatTypeInfo["RAID_WARNING"])
       end
    elseif (msg == "I AM UNDER ATTACK" and sender ~=UnitName("player"))  then
      print(sender)
      RaidNotice_AddMessage(RaidWarningFrame, sender .." IS UNDER ATTACK", ChatTypeInfo["RAID_WARNING"])
    end
  end
end)
You have an extra "end" at the end, if you used proper indentation you would've noticed this immediately:

Lua Code:
  1. LeaderMessageHandlerFrame = CreateFrame("Frame")
  2. LeaderMessageHandlerFrame:RegisterEvent("CHAT_MSG_SAY")
  3. LeaderMessageHandlerFrame:SetScript("OnEvent",
  4. function(self, event, msg, sender, ...)
  5.     if (msg == "NO LONGER FOLLOWING")  then
  6.         RaidNotice_AddMessage(RaidWarningFrame, sender .." NO LONGER FOLLOWING", ChatTypeInfo["RAID_WARNING"])
  7.     elseif (msg == "AGRO" and notUnitAffectingCombat("player"))  then
  8.         RaidNotice_AddMessage(RaidWarningFrame, sender .." HAS AGRO", ChatTypeInfo["RAID_WARNING"])
  9.     elseif (strfind(strlower(msg), "target is")) then
  10.         local _,_,_, cloneTargetName = strsplit(" ", msg, 4)
  11.         local myTargetName = (UnitName("playertarget"))
  12.         if (cloneTargetName  ~= myTargetName and UnitIsFriend("player",cloneTargetName)==nil) then
  13.             RaidNotice_AddMessage(RaidWarningFrame, sender .." IS ON DIFFERENT TARGET (".. cloneTargetName..")", ChatTypeInfo["RAID_WARNING"])
  14.         end
  15.     elseif (msg == "I AM UNDER ATTACK" and sender ~=UnitName("player"))  then
  16.         print(sender)
  17.         RaidNotice_AddMessage(RaidWarningFrame, sender .." IS UNDER ATTACK", ChatTypeInfo["RAID_WARNING"])
  18.     end
  19.     end -- This end needs to be removed
  20. end)

Originally Posted by shalom69 View Post
also the following function for that thisIsLeadWindow check (I have LeaderFlagToggle function bound to a key through bindings.xml to tell the addon if it's running on a clone or the main window)

Code:
function LeaderFlagToggle()
  if not thisIsLeadWindow then
   thisIsLeadWindow = "true"
  else
   thisIsLeadWindow = "nil"
  end
end

BINDING_HEADER_CLONESTATES = "CloneStates"
BINDING_NAME_TOGGLELEADERSTATUS = "Toggle CloneStates Leader Flag"
I'm sure there's better ways to program the above which I'll learn as I go but it seems like I should be able to use if-if-if since all those are discrete incidents. On the subject, can anyone explain the usage of if-then statement around my command to register events? something like:

Code:
if thisIsLeadWindow then
  LeaderMessageHandlerFrame:RegisterEvent("CHAT_MSG_SAY")
end
I didn't get an error but nothing registered. I'm guessing that the RegisterEvent has to happen onload or something else I'm not familiar with

thanks in advance
Not sure why you are using "true" and "nil", you should be using true/nil or true/false, setting thisIsLeadWindow to the string value "nil" means it will always evaluate to true if you're checking it in "if thisIsLeadWindow". If you set it to the actual value nil: "thisIsLeadWindow = nil" it would evaluate to false.

Not sure why the event registering isn't working though, maybe someone else can shed some more light on it.
  Reply With Quote
02-26-13, 09:09 PM   #9
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
first of all F16Gaming thanks for the replies, I appreciate it

I actually had some code in there to check whether the WOW instance was the lead instance (had it print out a statement on the lead intance), when I removed it to post it here I also misclicked and removed an if-then statement at the top, that's why you saw an extra "end" in the code. I edited the code in the prior post to reflect the proper code...

the code works on my end.

That wasn't my issue, my question was a theoretical question why if-if structure wasn't working and a question about nesting a RegisterEvent within a if-then structure.

as for the first, see how my noob code is structured (ignoring the larger if-end instruction that frames the other statements because that isn't the issue)

function
if
elseif
elseif
elseif

I had the logic written as the following which did not work

function
if
if
if
if


it seems like if-if-if-if should work since they are all mutually exclusive instructions but it doesn't work. I was hoping someone could tell me why. Not just for this code but for when I try to map out the logic for other uses.

as for the later. I am wondering why I can't move my "if thisIsLeadWindow" outside the function. for example to

Code:
if thisIsLeadWindow then
    LeaderMessageHandlerFrame:RegisterEvent("CHAT_MSG_SAY")
end
or even

Code:
if thisIsLeadWindow then
   LeaderMessageHandlerFrame = CreateFrame("Frame")
end

To F16Gaming specifically, so you are telling me that I should indent 4 spaces when I go down one level in the code? Lol okay man I actually appreciate the pointers on the indents and things, because I am learning this on my own I don't know all the conventions and things. Which I actually do agree I should try to follow.

Finally, as I understand it, you are saying that variable = "nil" is a string and variable = nil is nil value. Right?

Last edited by shalom69 : 02-26-13 at 09:12 PM.
  Reply With Quote
02-26-13, 09:23 PM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
1. Please use [code] tags around anything code-like, including psuedo-code and other code-like things. It's really hard to read otherwise.

2. Without seeing your original if-if-if code I can't tell you why it doesn't work, but perhaps you had literally:

Code:
if A then
   X
if B then
   Y
if C then
   Z
end
...without the required "end" for each "if" statement?

3. As for your event question, I can't answer that either because you didn't post complete code. Did you set an OnEvent script for the same frame you registered the event on? How do you know the event didn't register?

4. Do you have BugSack installed and enabled? If not, go get it. Without something showing you Lua errors, you are totally in the dark when it comes to trying to figure out why your code isn't working, and the default error display is a useless for developers because it can't show errors that occur during the initial loading process (which is where most errors happen during addon writing).

Originally Posted by shalom69 View Post
Finally, as I understand it, you are saying that variable = "nil" is a string and variable = nil is nil value. Right?
Yes. Anything enclosed in "quotes" or [[double square brackets]] or [=[double square brackets with equals signs in between them]=] is a string value in Lua. The only actual nil value is nil, but both nil and false are equivalent when performing a simple "if X then" boolean check, so nil and false are only different if you explicitly check "if X == nil then" or "if X == false then", or if you are checking the return value from "type(X)".
__________________
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 : 02-26-13 at 09:26 PM.
  Reply With Quote
02-26-13, 10:06 PM   #11
Sharparam
A Flamescale Wyrmkin
 
Sharparam's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2011
Posts: 102
Originally Posted by shalom69 View Post
To F16Gaming specifically, so you are telling me that I should indent 4 spaces when I go down one level in the code? Lol okay man I actually appreciate the pointers on the indents and things, because I am learning this on my own I don't know all the conventions and things. Which I actually do agree I should try to follow.
Not necessarily 4 spaces (though that is the most common), but just use consistent indentation (e.g: if you choose to indent with 2 spaces, then follow that and don't suddenly change to 3 or 4 spaces on some lines). It makes reading code that much easier :)
  Reply With Quote
02-26-13, 11:07 PM   #12
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
Originally Posted by Phanx View Post
3. As for your event question, I can't answer that either because you didn't post complete code. Did you set an OnEvent script for the same frame you registered the event on? How do you know the event didn't register?

4. Do you have BugSack installed and enabled? If not, go get it. Without something showing you Lua errors, you are totally in the dark when it comes to trying to figure out why your code isn't working, and the default error display is a useless for developers because it can't show errors that occur during the initial loading process (which is where most errors happen during addon writing).



Yes. Anything enclosed in "quotes" or [[double square brackets]] or [=[double square brackets with equals signs in between them]=] is a string value in Lua. The only actual nil value is nil, but both nil and false are equivalent when performing a simple "if X then" boolean check, so nil and false are only different if you explicitly check "if X == nil then" or "if X == false then", or if you are checking the return value from "type(X)".
Ok good information man! It's useful to know what the difference between nil and false is. I was using "nil" and nil interchangeably, just being careless because I didn't clearly delineate the difference in my mind. Although if someone had called me on it long enough for me to think about it, as F16 did I probably would have seen the difference.

Lol dude, my code actually worked with my nil set to "nil" string... because the value was in fact nil on bootup before I iterated thisIsLeadWindow function. So it would work the first 2 times before it got stuck. And I was checking it twice per instance so it never got stuck. Hahaha wotanoob. When I checked it was actually spitting out "nil" as the string for thisIsLeadWindow (when it should just be blank if it's nil value) and I wasn't noticing it.

I'll download and learn BugSack. I did have the OnEvent script in the same frame, but maybe BugSack can help me figure out what is wrong. I'm just kind of learning WOW LUA semantically... monkey see monkey do basically what I see in other scripts and tutorials, Phanx, is there a way to call 2 OnEvent scripts in the same frame?

for example in my script

Code:
LeaderMessageHandlerFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
if I wanted to SetScript("OnEvent", function(...)) I'd have to make a new frame for it, correct? I can't regsiter more OnEvent scripts to the same frame...
  Reply With Quote
02-26-13, 11:23 PM   #13
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Lua Code:
  1. myFrame:SetScript("OnEvent", function(self,event,...)
  2.      if event == "THIS_EVENT" then
  3.           --do stuff
  4.      elseif event == "A_DIFFERENT_EVENT" then
  5.           --do something else
  6.      elseif event == "RANDOM_EVENT_3" then
  7.           --do this stuff
  8.      end
  9. end)
__________________
"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
02-27-13, 04:53 AM   #14
shalom69
A Fallenroot Satyr
Join Date: Feb 2013
Posts: 22
thanks for the replies. got some simple but key hints in this thread

Last edited by shalom69 : 02-27-13 at 07:21 AM.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » quick noob question about strings and unitID


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