Thread Tools Display Modes
02-17-10, 11:27 AM   #1
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
UnitAura and GUID's

Hi all!

I track UNIT_AURA for my debufftracker to start the timer bars. The problem is, UNIT_AURA is limited to units relative to you. So if I click on a mob, cast fear, then tab to an other mob there is no bar shown(because UNIT_AURA doesn't fire at all). So, I thought, easy solve, I'll just hook "COMBAT_LOG_EVENT_UNFILTERED" and watch "SPELL_AURA_APPLIED". Works like a charm for getting the events, there is just one problem. The combat log returns a GUID and a name. The name can't be trusted on whatsoever, because if I'm fighting two Hath'ar Skimmer's at a time then I'm screwed(even if the second is just close). Well, that leaves me with the GUID. Next I want to know when the debuff expires. I need UnitAura for that to be accurate(talents, etc). Works perfect, except one thing. UnitAura doesn't take a GUID. It only wants names or relative units. Does that mean I'm left with target debuff timers only? Or is there an alternative function/way? Please help me out!
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-17-10, 11:43 AM   #2
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
Cache the timers

Btw, paragraphs are awesome
  Reply With Quote
02-17-10, 12:00 PM   #3
acapela
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 241
Originally Posted by nightcracker View Post
UnitAura doesn't take a GUID. It only wants names or relative units. Does that mean I'm left with target debuff timers only? Or is there an alternative function/way? Please help me out!
yes and no. you will require a unitid, but that unitid does not literally need to be "target".

Aloft engages in an elaborate target tracking exercise, based on UNIT_TARGET, PLAYER_TARGET_CHANGED, and PLAYER_FOCUS_CHANGED events. Aloft effectively collects and caches the GUIDs of everything player/pets/groupmembers have targeted, at all times. as well, the whole GUID map is tossed and rebuilt when the group manifest changes.

due to my own ignorance and the experimental nature of its development, it is not a very clean/modular system at the moment (for instance, Aloft also has to be able to identify nameplates, so it can add display elements to them, and that nameplate identification is currently all garbled together with the GUID tracking), so i don't know if you would be happy just trying to lift the code (i need to do some more work on it, i but have had other fish to fry). there is probably some utility for a layered library here. as well, i wanted to try LibUnitID, but it seemed development had stopped on that, so i didn't use it.

anyway, given this GUID tracking, when Aloft sees an event in the combat log, based on the GUID, it can look to see whether a groupmember has that GUID targeted. if a groupmember does, it can generate a target unitid, constructed from the groupmember unitid, and (try to) collect whatever information it wants (currently, this is used for animating cast bars and collecting AOE threat on non-targets; Aloft will probably add a buff/debuff bar, sunder/lacerate counts, and etc, for non-targets as well).

there is always the possibility for race conditions between target changes and combat log events, but you can take that into account (by continuously spot-checking that the unitid you use still targets the GUID you are interested in, etc, as you invoke UnitAura() or whatever).

so, having crossed this bridge before, that was what i came up with. hope it helps.
__________________
Retired author/maintainer of Aloft (the nameplate addon)
http://www.wowinterface.com/download...AloftBeta.html
-----
Zippy said it best: "All life is a BLUR of Republicans and Meat!"
  Reply With Quote
02-17-10, 01:42 PM   #4
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
I have no idea how to do all of this caching and such, could someone please help me on the way?
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-17-10, 02:04 PM   #5
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,935
Did you check to see if this one helps you in anyway ? It seems to break down the GUID into a unitID and spawnID. http://www.wowwiki.com/API_UnitGUID

Edit: Actually that command doesn't do that function but it explains how you break the GUID down.
__________________


Characters:
Gwynedda - 70 - Demon Warlock
Galaviel - 65 - Resto Druid
Gamaliel - 61 - Disc Priest
Gwynytha - 60 - Survival Hunter
Lienae - 60 - Resto Shaman
Plus several others below level 60

Info Panel IDs : http://www.wowinterface.com/forums/s...818#post136818

Last edited by Xrystal : 02-17-10 at 02:09 PM.
  Reply With Quote
02-17-10, 02:22 PM   #6
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by Xrystal View Post
Did you check to see if this one helps you in anyway ? It seems to break down the GUID into a unitID and spawnID. http://www.wowwiki.com/API_UnitGUID

Edit: Actually that command doesn't do that function but it explains how you break the GUID down.
Well, UnitAura doesn't take any of those
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-17-10, 07:25 PM   #7
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
Originally Posted by nightcracker View Post
I have no idea how to do all of this caching and such, could someone please help me on the way?
Grab any modern UnitFrame AddOn and do a search for those events. Study the code - they all use caching.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
02-17-10, 07:45 PM   #8
Shadowed
...
Premium Member
Featured
Join Date: Feb 2006
Posts: 387
There's multiple ways of doing caching, but pretty much all it comes down to is storing data you know is generally nonvolatile in a hash table and pulling data out of it, instead of rescanning/rechecking every time.
  Reply With Quote
02-17-10, 09:02 PM   #9
acapela
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 241
Originally Posted by nightcracker View Post
I have no idea how to do all of this caching and such, could someone please help me on the way?
sorry. you were talking about using the combat log (which is about as crazy as it gets in addon development), and GUIDs, and etc, so i guess i assumed i just needed to nudge you in the right direction.

and yeah, you are correct. things like UnitAura() require a "unitid". in fact, while GUIDs might have a structure, i would say that structure doesn't really help you much when interacting with the rest of the Blizzard API. GUIDs are most useful as "cookies" (i.e. wads of anonymous data).

this is more like a (quick) tutorial:

UnitGUID() is how you obtain a GUID from a unitid (a unitid like "target" or "focus" or "party11target" etc).

so, your addon would watch the events i mentioned before (UNIT_TARGET, etc). every time a groupmember/player/etc changes targets, you will receive an event. collect the associated unitid from the event (the PLAYER_TARGET_CHANGED event implies the "target" unitid), if necessary add the string "target" to it (to generate a new "target" unitid), invoke UnitGUID() on the result, and then cross-reference that GUID and the target unitid you created (and used to obtain the GUID). you would use LUA tables for this cross-referencing (this assumes you understand how to do basic data structures in LUA; you will be mapping unitids to GUIDs and GUIDs to unitids, etc, to form a "cache" of associations between the two that you maintain continuously by handling those events).

given that more than one groupmember could have a GUID targeted, the GUID->unitid mapping could/would include more than one unitid (though you only need one; Aloft tracks all of them, iterates through all of them, tries to collect its information with each one, and as soon as it is successful it terminates the loop; generally, this means only the first unitid is ever used). on the other hand, the unitid->GUID tracking would be one-to-one (i.e. a groupmember can only have one target at a time).

if you are doing all this tracking, when you see a GUID in the combat log, you can use it to look up a unitid. if at least one groupmember has that GUID targeted, the lookup will succeed, and you will have at least one unitid you can use to call UnitAura() and/or anything else you want.

that should allow you to obtain arbitrarily detailed information on that target.
__________________
Retired author/maintainer of Aloft (the nameplate addon)
http://www.wowinterface.com/download...AloftBeta.html
-----
Zippy said it best: "All life is a BLUR of Republicans and Meat!"
  Reply With Quote
02-17-10, 11:13 PM   #10
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,935
Nice and concise Acapela .. *bookmarks thread for future reading*
__________________


Characters:
Gwynedda - 70 - Demon Warlock
Galaviel - 65 - Resto Druid
Gamaliel - 61 - Disc Priest
Gwynytha - 60 - Survival Hunter
Lienae - 60 - Resto Shaman
Plus several others below level 60

Info Panel IDs : http://www.wowinterface.com/forums/s...818#post136818
  Reply With Quote
02-19-10, 01:48 PM   #11
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
OK, the caching works now, I have now one new problem that occurred by using COMBAT_LOG_EVENT_UNFILTERED. I track SPELL_AURA_REMOVED to stop a timer when a unit dies, when a spell is dispelled, etc. The problem is, if a spell like Fear, with an diminishing return, gets refreshed, then sometimes this is the order of events:

SPELL_AURA_APPLIED
SPELL_AURA_REFRESH
SPELL_AURA_REMOVED

which causes the timer to hide(since stop was called as the last one). How can I find a workaround for this?
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-19-10, 04:15 PM   #12
acapela
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 241
Originally Posted by nightcracker View Post
which causes the timer to hide(since stop was called as the last one). How can I find a workaround for this?
if i were doing this in Aloft (or, as i PLAN to do this in Aloft, someday ), i would not necessarily "trust" the event stream. i would use the event stream purely as a series of "hints" or "clues" for when to invoke UnitAura(), and "rebuild" or "update" my timers based on the results of UnitAura(). in fact, i would set something up to invoke UnitAura() regardless of the event stream, when any sort of cooldown or timer was normally scheduled to end (in case that final event never arrived; set this up at the beginning to go off a configurable fraction of a second after the timer should end, etc). dunno if you are using it, but this would be easy to do with Ace.

(you can also look at the UNIT_DIED event, if you also want to take that class of activity into account.)

so, when the SPELL_AURA_REMOVED event arrives, i would do my GUID->unitid lookup. if, at that moment, i had a valid unitid to use, i would invoke UnitAura(), "trust" those results, and refresh all my timers accordingly.

for nameplates, if i found i had no valid unitid to use, i would drop the buff/debuff/timer display from the associated nameplate (in fact, i would drop the buff/debuff/timer display from the nameplate as soon as the UNIT_TARGET event arrived that took away my last valid unitid, or at the very least, i would make the user enable a configuration option to "keep stale timers", i.e. timers i could not actively validate using UnitAura()). if i were doing some sort of centralized-display "cooldown" addon, i would probably allow the timer to finish running (i.e. default to "keep stale timers", and make the user enable a configuration option to get rid of them), based on the updated data from the most recent UnitAura() call that succeeded.
__________________
Retired author/maintainer of Aloft (the nameplate addon)
http://www.wowinterface.com/download...AloftBeta.html
-----
Zippy said it best: "All life is a BLUR of Republicans and Meat!"

Last edited by acapela : 02-19-10 at 04:22 PM.
  Reply With Quote
02-19-10, 04:25 PM   #13
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by acapela View Post
if i were doing this in Aloft (or, as i PLAN to do this in Aloft, someday ), i would not necessarily "trust" the event stream. i would use the event stream purely as a series of "hints" or "clues" for when to invoke UnitAura(), and "rebuild" or "update" my timers based on the results of UnitAura(). in fact, i would set something up to invoke UnitAura() regardless of the event stream, when any sort of cooldown or timer was normally scheduled to end (in case that final event never arrived; set this up at the beginning to go off a configurable fraction of a second after the timer should end, etc). dunno if you are using it, but this would be easy to do with Ace.

(you can also look at the UNIT_DIED event, if you also want to take that class of activity into account.)

so, when the SPELL_AURA_REMOVED event arrives, i would do my GUID->unitid lookup. if, at that moment, i had a valid unitid to use, i would invoke UnitAura(), "trust" those results, and refresh all my timers accordingly.

for nameplates, if i found i had no valid unitid to use, i would drop the buff/debuff/timer display from the associated nameplate (in fact, i would drop the buff/debuff/timer display from the nameplate as soon as the UNIT_TARGET event arrived that took away my last valid unitid, or at the very least, i would make the user enable a configuration option to "keep stale timers", i.e. timers i could not actively validate using UnitAura()). if i were doing some sort of centralized-display "cooldown" addon, i would probably allow the timer to finish running (i.e. default to "keep stale timers", and make the user enable a configuration option to get rid of them), based on the updated data from the most recent UnitAura() call that succeeded.
Hmm, I guess I'll loop the 40 indexes of UnitAura, temporarily save the ones found, then loop the database holding current timers, and if a timer is found without a legit index of UnitAura connect to I destroy it.

EDIT:

I found a way efficienter way, instead of looping 40 slots I use this(unitid and spellid are passed with the function):
Code:
local spellname, rank = GetSpellInfo(spellid)
if not string.match(rank, "%d") then rank = nil end
local name, _, icon, count, debufftype, duration, expires, caster, _, _, spell = UnitDebuff(unitid, spellname, rank)
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.

Last edited by nightcracker : 02-19-10 at 04:29 PM.
  Reply With Quote
02-19-10, 04:36 PM   #14
acapela
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 241
Originally Posted by nightcracker View Post
I found a way efficienter way, instead of looping 40 slots I use this(unitid and spellid are passed with the function)...
i assume you mean "unitid, spell name, and spell rank".

anyway, yeah, if you are just using UnitAura() to validate whether something you already know about (i.e. from the combat log) is still there, i expect that is a better way to go.

however, i don't know if UnitAura() is "intrinsic" to the WoW client, or if it has some sort of implementation in the LUA that is buried down in the MPQs. does anyone know? if it is in the MPQs, you could probably dig it out and see if all it does is a loop as well (in which case maybe it doesn't matter who does the loop, the addon author or Blizzard ).
__________________
Retired author/maintainer of Aloft (the nameplate addon)
http://www.wowinterface.com/download...AloftBeta.html
-----
Zippy said it best: "All life is a BLUR of Republicans and Meat!"

Last edited by acapela : 02-19-10 at 04:38 PM.
  Reply With Quote
02-19-10, 04:55 PM   #15
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by acapela View Post
i assume you mean "unitid, spell name, and spell rank".
Well, that's a wrong assumption then. First 2 lines of my above script:
Code:
local spellname, rank = GetSpellInfo(spellid)
if not string.match(rank, "%d") then rank = nil end
So only spellid and unitid are given, the rest does the script itself.
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-19-10, 05:36 PM   #16
acapela
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 241
Originally Posted by nightcracker View Post
Well, that's a wrong assumption then.
my mistake. i looked at the code, and assumed it was "inline". sorry about that.
__________________
Retired author/maintainer of Aloft (the nameplate addon)
http://www.wowinterface.com/download...AloftBeta.html
-----
Zippy said it best: "All life is a BLUR of Republicans and Meat!"
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » UnitAura and GUID's


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