Thread Tools Display Modes
02-04-14, 03:07 PM   #1
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
Question Target NPC

Hi everyone,

This is my first thread here so forgive me if it's in the wrong section. I've been a WoW player for a long time and have always enjoyed writing little macros to make life easier but I've never really been compelled (until now) to dive into addons.

I guess there really hasn't been a need to as the likes of Curse pretty much has everything we need for day to day playing. Or so I thought.... I won't waffle though. On to business.

We have an alt raid group banging through SoO flex and always seem to have a problem on Nazgrim. It's the add priority of course. A combination of dodging the ravagers, the yellow **** on the ground and trying to pick out those shamans is a real pain. I'm sure you all know the score :P

I started writing out a little macro to check for each add by name, target it and set a raid icon i.e.

Code:
/target [@Kor'kron Warshaman,nodead] Kor'kron Warshaman; SetRaidTarget("target", 8)
but ran out of characters to cover all the permutations of the adds that can spawn.

So now I've been looking at an addon as an alternative. I was devastated to discover that the one api function that would make this all possible for me, TargetUnit, is protected

I've seen mentions here and there regarding using a "secure frame" to achieve this but unfortunately I haven't been able to find a working example or any other references. Obviously I wouldn't expect any of you to write it out for me but unfortunately my ninja Google skills are letting me down on this occasion and would really appreciate a little direction. Has anyone seen this or something similar?

If you've taken the time to read this I hope you enjoyed the read and really appreciate any help you can offer

Edit: Sorry I forgot to mention. If this has been covered elsewhere on the forums and I've simply failed to find it, massive apologies.
  Reply With Quote
02-04-14, 03:27 PM   #2
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
Getting easy-to-understand documentation on how to make a "secure" macro in Lua is not easy, so here we go:
Same macro as the one you provided, written in Lua

Lua Code:
  1. local button = CreateFrame("Button", "MyButton", UIParent, "SecureActionButtonTemplate")
  2. button:Hide()
  3. button:SetAttribute("type", "macro")
  4. button:SetAttribute("macrotext", "/target [@Kor'kron Warshaman,nodead] Kor'kron Warshaman; SetRaidTarget('target', 8)")

Now you can make a new macro (ingame) that does this:
Code:
/click MyButton
  Reply With Quote
02-04-14, 04:09 PM   #3
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Also, the syntax in your macro is not quite correct -- you can't add arbitrary Lua code on a /target line; you need a second line beginning with /run. Here's a better way to write that:

Code:
/cleartarget
/targettexact Kor'kron War Shaman
/run SetRaidTarget("target", 8)
/targetlasttarget
This will (1) clear your current target, (2) target the Kor'kron War Shaman, but not target anything else with a similar name if it's not spawned, (3) set an icon on your current target, which will do nothing if you didn't successfully target the shaman, and (4) go back to your previous target.

Other than that, as I'm not familiar with the fight in question, I'm not entirely clear on what you're actually looking to do, overall. You mention that you ran out of space in your macro, but the example you posted is nowhere near the 255 character limit. Without more details I can't really offer any advice on how to write an addon to solve the problem.

If there are multiple adds, and you want to mark each with a different icon, your boss mod (assuming you're using one) may already have options to do that, or you could also try one of the automatic marking addons that already exist, such as MagicMarker.
__________________
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-04-14, 04:59 PM   #4
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
You can give my addon priority Target a try.
It was made for exactly those types of scenarios and you can customize / create priority lists so you can adapt it to your needs.
  Reply With Quote
02-04-14, 06:58 PM   #5
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
Following Phanx, if you want to use that macro in my example, you have to use \n instead of newlines, like so:

Lua Code:
  1. button:SetAttribute("macrotext", "/cleartarget\n/targettexact Kor'kron War Shaman\n/run SetRaidTarget('target', 8)\n/targetlasttarget")
  Reply With Quote
02-04-14, 07:40 PM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
You can also use [[ double square brackets ]] to form a literal string.

Code:
button:SetAttribute("macrotext", [[
/cleartarget
/targettexact Kor'kron War Shaman
/run SetRaidTarget("target", 8)
/targetlasttarget]])
Apparently the forum's Lua highlighting doesn't recognize this syntax -- tsk tsk Dolby! -- so here is some manual highlighting.

Anyway, this is often more convenient for writing multi-line strings than mashing it all together, using the \n escape code, and escaping quotation marks or replacing them with single quotes. Literal strings don't interpret escape codes (so you can't use \n inside one) and the first linebreak is ignored if it's the first character in the string, so the above example doesn't actually start with a blank line.
__________________
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-05-14, 01:19 PM   #7
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
Thanks for the replies everyone. Seen them this morning but was in work so I've been dying to get home and give this a try all day

I'll let you all know how it goes.
  Reply With Quote
02-05-14, 02:20 PM   #8
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
Is there any way to debug as you go? Right now when I type the slash command for my addon and press return nothing seems to happen. The /command remains and the only way to get rid of it is press ESC. Any thoughts?
  Reply With Quote
02-05-14, 03:16 PM   #9
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
To see errorlogs make sure you have Lua errors enabled in the interface options under help.
I'd also recommend using BugSack, it makes everything better.

For in-line debugging use print, it will print whatever to the default chatwindow.

Last edited by p3lim : 02-05-14 at 03:19 PM.
  Reply With Quote
02-05-14, 04:08 PM   #10
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
BugSack is all kinds of awesome. Thanks for that. Just working through a few silly scoping issues and fencing some stuff off then I'll be happy to share my code so far since it's really a joint effort :P
  Reply With Quote
02-05-14, 06:22 PM   #11
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
UnitExists doesn't seem to work with an NPC name e.g. UnitExists("Garrosh Hellscream"). Whats up with that?
  Reply With Quote
02-05-14, 06:26 PM   #12
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Originally Posted by urbley View Post
UnitExists doesn't seem to work with an NPC name e.g. UnitExists("Garrosh Hellscream"). Whats up with that?
Unit names only work for grouped people, i.e. players and their pets. Otherwise this can be abused to check for any unit and see if it exists in the world around you - Blizzard doesn't want that. It's that simple. :P
__________________
Profile: Curse | Wowhead
  Reply With Quote
02-05-14, 06:34 PM   #13
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
How does NPCScan do it?
  Reply With Quote
02-05-14, 06:39 PM   #14
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
Originally Posted by urbley View Post
How does NPCScan do it?
NPCScan and similar addons use /target macros for the actual targeting and they detect mobs indirectly by their presence in the cache.


I'm curious, before trying to make a new addon, did you try the one I linked in the 4th post?
  Reply With Quote
02-05-14, 06:43 PM   #15
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
Hi Dridzt. I haven't tried it yet as I've kind of set my mind on doing it myself I've wanted to write something for a long time but never really had the motivation until now. I think I'll have a look at yours though. Maybe it'll give me some inspiration!
  Reply With Quote
02-05-14, 06:48 PM   #16
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
NPCScan doesn't use UnitExists or any other Unit* API functions. Instead, it repeatedly scans the unit model cache to see if a particular model has been loaded yet. The downside of this method -- as you may have noticed if you've ever used NPCScan -- is that it can only detect the first time each model is seen. If you want to detect it again, you have to exit the game and manually delete the cache file. This method will not work for detecting adds in a boss encounter.

Other similar addons (eg. SilverDragon) also watch the combat log for the first time a particular mobID appears in an action. This method could be used to detect adds in a boss encounter, assuming they do something when they spawn, such as cast a spell or attack players. You would want to check both the mobID (derived from the GUID) to see if the mob in question was a Kor'kron Dark Shaman, and the whole GUID to see if the mob was a new spawn or one you'd already seen.

However, since you still cannot target mobs automatically, you may be better off just watching the targets of your raid members, and setting the target icon automatically whenever anyone targets a Kor'kron Dark Shaman. Otherwise the only thing detecting the spawn will do is remind you to push your button.
__________________
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-06-14, 04:54 PM   #17
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
Thumbs down

Thanks for the extended reply Phanx. It's appreciated. Looks like I'll just have to find another way to do it. I've considered just using a little grid with the 11 different permutations of the mobs that can spawn. It will require a little more thought but still achieve what I'm after. I might as well share the logic I was working on. Maybe it will inspire someone

Code:
-- Table containing the bad guys.  the headers are Index, Name, Priority
badGuys = {
    {1, "Kor'kron Ironblade", 1},
    {2, "Kor'kron Arcweaver", 2},
    {3, "Kor'kron Assassin", 3},
    {4, "Kor'kron Warshaman", 4}
}
 
-- Var to contain the final macro text code
macroText = ""
 
function FindBaddies( badGuys )
    -- Initialise now so we can check if it's
    -- empty later if nothing gets found now!
    badGuysToTarget = {}
   
    i = 1
    for i, baddy in pairs(badGuys) do
        if( UnitExists( baddy[2] ) ) then
            badGuysToTarget[i] = { baddy[2], baddy[3] }
            i = i + 1
        end
    end
    return badGuysToTarget
end
 
-- Overriding API function for testing
function UnitExists( baddyToFind )
   if ( baddyToFind == "Kor'kron Warshaman" ) then return true end
   if ( baddyToFind == "Kor'kron Assassin" ) then return true end
   if ( baddyToFind == "Kor'kron Arcweaver" ) then return true end
   if ( baddyToFind == "Kor'kron Ironblade" ) then return true end
end
 
-- Iterates through the table of bad guys that were found
-- and builds target macro text.
function BuildMacroText()
    badGuysToTarget = FindBaddies( badGuys )
    if ( next( badGuysToTarget ) == nil ) then
        print( "No baddies found :D" )
    else
        -- work out which raid icon to start with.  This is so
        -- we can finish on the skull and it can remain targeted
        tarPrio = 9
        for _ in pairs(badGuysToTarget) do tarPrio = tarPrio - 1 end
       
        for i, baddy in pairs( badGuysToTarget ) do
            macroText = macroText .. [[
/cleartarget
/tar [@]] .. baddy[1] .. [[,nodead] ]] .. baddy[1] .. [[
 
/script SetRaidTarget['target', ]] .. tarPrio .. [[]
]]
        tarPrio = tarPrio + 1
        end
    end
    print( macroText )
end
 
BuildMacroText()
Probably best to start a new thread for the next attempt? Thanks again everyone for your replies and hopefully I'll see you all on the next thread for the next attempt
  Reply With Quote
02-06-14, 05:28 PM   #18
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
(1) Please don't make all those things globals. Add a "local" keyword in front of each one. >_<

(2) Rather than messy string concatenation, you may find it more readable to use string.format to build your macro, eg:

Code:
-- Generic base macro:
local macroBase = [[
/cleartarget
/targettexact %s
/run if UnitExists("target") and not UnitIsDead("target") then SetRaidTarget("target", %d) end
/targetlasttarget]]

-- Personalize it for each mob with the name and icon index:
local macroText = format(macroBase, "Kor'kron War Shaman", 8)
__________________
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-06-14, 05:45 PM   #19
urbley
A Deviate Faerie Dragon
Join Date: Feb 2014
Posts: 10
String.format does look like the way forward! Yeah I was using local in my actual addon code but that script above was me testing logic on repl.it as I don't have a local lua interpreter yet . So tomorrow night I will be investigating the UI to set up a little grid as follows with each space being a button that will have macro code attached. Should be fun.

Edit: had to delete the grid. Looked rubbish :P three rows. Top row 6 buttons, second row 4 buttons, bottom row 1 button.

Last edited by urbley : 02-06-14 at 05:47 PM. Reason: Grid was rubbish
  Reply With Quote
02-06-14, 06:30 PM   #20
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by urbley View Post
... I don't have a local lua interpreter yet
Sure you do, it's called World of Warcraft, and that's why Blizzard created ReloadUI().
__________________
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

WoWInterface » Developer Discussions » Lua/XML Help » Target NPC

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