Thread Tools Display Modes
09-30-07, 01:22 PM   #1
Tatheltek
A Cyclonian
AddOn Author - Click to view addons
Join Date: Dec 2006
Posts: 43
Triggering alerts for your target only

I have an addon ive been working on that alerts you when your target gains Cloak of Shadows, Nether Protection or Divine Sheild, becomes Disarmed Silenced or Immobilized etc.

It parses the combat log for phrases such as:

if (strfind(msg,"is afflicted by Blackout.") ) then... <or>

if (strfind(msg,"gains Divine Shield.")) then...


Right now the code tells me when anyone in range enough to trigger combat messages gains or becomes afflicted by one of these abilities. I would like it to trigger only if my current target is the one gaining or becoming afflicted by the ability. Is that possible?

So basically, sometimes it alerts me that the mage 30 yards away had chilled his target...and really i only want to know if my target becomes chilled.

Last edited by Tatheltek : 09-30-07 at 05:39 PM.
  Reply With Quote
10-04-07, 04:58 AM   #2
Teif
A Deviate Faerie Dragon
Join Date: May 2006
Posts: 12
Provided there's always a message in the combat log, you'd have something along the lines of "Soandso gains Divine Shield" in your combat log, where Soandso would be the name of the character/mob.

So in your code, you would probably be able to do something like this (assuming arg1 is the combat text for the event you need to catch):

Code:
   
   if (arg1:find("gains Divine Shield")) then
      -- find out who gained Divine Shield
      local nameEnd    = arg1:find("gains") -- the actual index might be one less
      local name       = arg1:sub(1, nameEnd)
      local targetName = UnitName("target")
      if (name == targetName) then
         -- your target was affected
      end
   end
Hope this helps
  Reply With Quote
10-08-07, 10:07 AM   #3
Tatheltek
A Cyclonian
AddOn Author - Click to view addons
Join Date: Dec 2006
Posts: 43
I think I understand what your having me do here...match UnitName(target) to the name from the argument from the combat log. So if they are equal then trigger the function of the addon.

But whats going on in this part:

Originally Posted by Teif
local nameEnd = arg1:find("gains") -- the actual index might be one less
local name = arg1:sub(1, nameEnd)
Heres what I did for example with pallys bubbling:

if (strfind(msg,"gains Divine Shield.")) then
if (targetClass == "Paladin") then
ProcAlertSplashFrame:SetTimeVisible(1)
ProcAlertSplashFrame:AddMessage("|CFFFFFF33" .. targetName.. ": |CFFFF99CCBubbled!");
DEFAULT_CHAT_FRAME:AddMessage(PROCALERT_MSGTITLE .. " |CFFFFFFFF" .. targetName .. " bubbled! (Immune to |CFFFF0000All |CFFFFFFFFDamage)");
PlaySound("igQuestFailed");
end
end

Which works great because only paladins can bubble...
But in a case such a below, i only wanted to know if my target is affected...

if (strfind(msg,"is afflicted by Blackout.") ) then
ProcAlertSplashFrame:SetTimeVisible(1)
ProcAlertSplashFrame:AddMessage("|CFFFFFF33" .. targetName.. ": |CFF990099Blackout!");
DEFAULT_CHAT_FRAME:AddMessage(PROCALERT_MSGTITLE .. " |CFFFFFFFF" .. targetName .. " is Stunned for 3 sec!");
end

but this was actually telling me when anyone in range was afflicted by blackout instead of just my target so with your advice I gather I can modify it to...

if (strfind(arg1,"is afflicted by Blackout.") ) then
local nameEnd = arg1:find("afflicted")
local name = arg1:sub(1, nameEnd)
local targetName = UnitName("target")
if (name == targetName) then
ProcAlertSplashFrame:SetTimeVisible(1)
ProcAlertSplashFrame:AddMessage("|CFFFFFF33" .. targetName.. ": |CFF990099Blackout!");
DEFAULT_CHAT_FRAME:AddMessage(PROCALERT_MSGTITLE .. " |CFFFFFFFF" .. targetName .. " is Stunned for 3 sec!");
end

correct?

Again, if someone wants to take the time to explain this part to me so i can learn whats going on i would appreciate it

Originally Posted by Teif
local nameEnd = arg1:find("gains") -- the actual index might be one less
local name = arg1:sub(1, nameEnd)
  Reply With Quote
10-09-07, 01:48 AM   #4
Teif
A Deviate Faerie Dragon
Join Date: May 2006
Posts: 12
Originally Posted by Teif
local nameEnd = arg1:find("gains") -- the actual index might be one less
local name = arg1:sub(1, nameEnd)
These two lines of code has to do with extracting the name from the combat log message - you have: "Soandso gains abuff" showing up in the combat log and now you want to extract the name - Soandso.

When a combat log event is triggered, for instance CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS, the first argument, arg1, contains the full combat log entry text - in this case maybe "Soandso gains abuff".

arg1:find("gains") will return the start and end index of the word "gains" from the input string - in this case arg1. For the case of "Soandso gains abuff", the return values would be 9 and 13. Since we're only interested in knowing where the word starts we only save the first return value in the variable nameEnd. However because the start index points to the position of the letter 'g' in gains, we might need to subtract one from the variable and instead use nameEnd - 1 as our argument for the sub function - which is explained in the following.

we then use arg1:sub(1, nameEnd) to return a substring created from the input string - and the parameters we pass along tell the function that we want the characters from index 1 to nameEnd - meaning we should get "Soandso" as our string which is stored in the variable name.

*EDIT:* I'm wrong here actually - (nameEnd-1) would result in the substring being "Soandso " (with a space at the end). I'd suggest implementing something like the solution mentioned a bit further down in this post as it will be a much more "solid" way of doing the name extraction.

It's all just put in to be able to extract the name from the combat message, since it's not present on it's own in the event arguments for combat log entries.

---

What you could do instead, which might be a better solution could be to implement this small function:

Code:
function myString_findPattern(text, pattern, start)
   return text:sub(text:find(pattern, start))
end
which will do the above steps in one go - look for a match for the input pattern, and return a substring using the start and end indices for the given pattern match.

Using this method, we should be able to extract the name by doing:
Code:
local name = myString_findPattern(arg1, "%a*") 
-- the pattern "%a*" means 0 or more repetitions of a letter,
-- which in this case would give us the name
The reason I would do this extra bit of processing is that the code you have listed:
Code:
if (strfind(msg,"gains Divine Shield.")) then
   if (targetClass == "Paladin") then
      ProcAlertSplashFrame:SetTimeVisible(1)
      ProcAlertSplashFrame:AddMessage("|CFFFFFF33" .. targetName.. ": |CFFFF99CCBubbled!");
      DEFAULT_CHAT_FRAME:AddMessage(PROCALERT_MSGTITLE .. " |CFFFFFFFF" .. targetName .. " bubbled! (Immune to |CFFFF0000All |CFFFFFFFFDamage)");
      PlaySound("igQuestFailed");
   end
end
will mean that although it will only trigger whenever you have a paladin on target, it will still trigger for any paladin within the range during this time (depending on the event you are using to trigger the method).

Example:
You have Paladin A on target
Paladin B casts divine Shield

Combat log: "Paladin B gains Divine Shield"
Your mod is triggered and you test if your target's class is paladin

Your mod reports that Paladin A has gained divine shield.

Which is why you would probably need to do the check for the name to find out if the event really did trigger for your target or just someone of the same class.

I hope that helped clarify, and that I haven't just added more confusion

Last edited by Teif : 10-09-07 at 01:51 AM.
  Reply With Quote
10-09-07, 08:08 AM   #5
Tatheltek
A Cyclonian
AddOn Author - Click to view addons
Join Date: Dec 2006
Posts: 43
Cool

Let me see if I understand...with what you've said I should be able to:

Code:
function myString_findPattern(text, pattern, start)
   return text:sub(text:find(pattern, start))
end

local targetName = UnitName("target")
local name = myString_findPattern(arg1, "%a*") 

if (strfind(arg1,"gains Divine Shield.")) then
   if (name == targetName) then
      ProcAlertSplashFrame:SetTimeVisible(1)
      ProcAlertSplashFrame:AddMessage("|CFFFFFF33" .. targetName.. ": |CFFFF99CCBubbled!");
      DEFAULT_CHAT_FRAME:AddMessage(PROCALERT_MSGTITLE .. " |CFFFFFFFF" .. targetName .. " bubbled! (Immune to |CFFFF0000All |CFFFFFFFFDamage)");
      PlaySound("igQuestFailed");
   end
end
I've been reading as much about API as I can on wowwiki between our posts back and forth. I have 1 question about what you've added...

Does "%a*" return just the first letter of the name? Or will it return the full name prior to the event arguments for the combat log entries because of the *.

I saw on lua-users.org that
> = findpattern('The quick brown fox', '%a') -- %a is all letters
returns T

and
a single character class followed by '*', which matches 0 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence;

I may have just answered my own question...

btw, thanks for all this help

Last edited by Tatheltek : 10-09-07 at 08:17 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Triggering alerts for your target only


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