LibGroupInSpecT
Summary
A small library which keeps track of group members and keeps an up-to-date cache of their specialization and talents.
It's similar to the old LibGroupTalents/LibTalentQuery and the LibRaidInspect libraries, but unlike the former it's actually working on 7.0, and unlike the latter it works properly in Battlegrounds. Additionally it has the feature where it communicates spec/talent updates to other LibGroupInSpecT users. This is an important point as of the writing of this there is no way to detect when another player re-specs/talents.
This library started out as a part of RaidChecklist as replacement for LibGroupTalents, but has since been split off into its own project as its usefulness increases the more widespread it is.
To make use of this library you'll need to also have the usual LibStub and LibCallbackHandler libs.
For a real usage example, take a look at the RaidChecklist project.
Events
These events can be registered for using the regular CallbackHandler ways.
Reference
event | args |
---|---|
"GroupInSpecT_Update" | guid, unit, info |
"GroupInSpecT_Remove" | guid |
"GroupInSpecT_InspectReady" | guid, unit |
Description
-
"GroupInSpecT_Update"
- Fires when info is ready or has been modified.
-
"GroupInSpecT_Remove"
- Fires when a member leaves the group.
-
"GroupInSpecT_InspectReady"
- Fires during INSPECT_READY so that clients can perform supplemental inspection handling (as of r78).
Example
local LGIST = LibStub:GetLibrary("LibGroupInSpecT-1.1") LGIST.RegisterCallback(addonObject, "GroupInSpecT_Remove", "UnitRemoved") function addonObject:UnitRemoved(event, guid) -- unit with guid removed end
API
Functions for external use:
-
lib:Rescan (guid or nil)
- Force a fresh inspection of all group members. As of r76 it accepts an optional guid parameter, to rescan only a particular GUID rather than all group members.
-
lib:QueuedInspections ()
- Returns an array of GUIDs of outstanding inspects.
-
lib:StaleInspections ()
- Returns an array of GUIDs for which the data has been deemed stale and is awaiting an update (no action required, the refresh happens internally).
-
lib:GetCachedInfo (guid)
- Returns the cached info for the given GUID, if available, nil otherwise. Information is cached for current group members only.
-
lib:GuidToUnit (guid)
- Returns the unit id for the given GUID, provided said GUID represents a current group member, else nil.
info table structure
The fields of the table passed as an argument for "GroupInSpecT_Update" callback or returned by one of the API functions (eg. :GetCachedInfo(guid) ). A list of all the global specialization IDs is available here.
Note: Not all fields may be available at all times due to the Blizz API not returning the info at that point. Incremental updates will be sent, so coding with the possibility of nil in mind is highly advised.
Info structure
.guid .name .realm .race .race_localized .class .class_localized .class_id .gender -- 2 = male, 3 = female .global_spec_id .spec_index .spec_name_localized .spec_description .spec_icon .spec_background .spec_role .spec_role_detailed -- "tank", "melee", "ranged" or "healer" (introduced in 1.0.2) .spec_group -- active spec group (1/2/nil), introduced in 1.1 .talents = { [<talent_id>] = { -- Note: Since 1.1 this is a talent_id, not a spell_id .talent_id -- Introduced in 1.1. This replaces the old 1.0.x .idx entry .tier .column .name_localized .icon .spell_id } ... }
.pvp_talents = {
[<talent_id>] = {
.talent_id
.name_localized
.icon
.spell_id
}
...
} .lku -- last known unit id
Usage
Typical usage example.
.pkgmeta
Libs/LibGroupInSpecT-1.1: svn://svn.wowace.com/wow/libgroupinspect/mainline/trunk
.toc
## X-Embeds: LibGroupInSpecT-1.1 ## OptionalDeps: LibGroupInSpecT-1.1 #@no-lib-strip@ Libs\LibStub\LibStub.lua Libs\CallbackHandler-1.0\CallbackHandler-1.0.lua Libs\LibGroupInSpecT-1.1\LibGroupInSpecT-1.1.lua #@end-no-lib-strip@
alternatively embeds.xml (referenced in .toc)
<ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd"> <!--@no-lib-strip@--> <script file="Libs\LibStub\LibStub.lua"/> <include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/> <include file="Libs\LibGroupInSpecT-1.1\lib.xml"/> <!--@end-no-lib-strip@--> </ui>
.lua
local LGIST=LibStub:GetLibrary("LibGroupInSpecT-1.1") LGIST.RegisterCallback(addonObject, "GroupInSpecT_Update", "UpdateHandler") LGIST.Registercallback(addonObject, "GroupInSpecT_Remove", "RemoveHandler") function addonObject:UpdateHandler(event, guid, unit, info) if info.class and info.class == "DEATHKNIGHT" and info.spec_role and info.spec_role == "TANK" then print(UnitName(unit).." is now "..info.spec_name_localized) -- info.name may also be available end end function addonObject:RemoveHandler(event, guid) -- guid no longer a group member end local info = LGIST:GetCachedInfo(guid) local hasFocusingShot = info and next(info.talents) and info.talents[21729] -- focusing shot talent_id
<sub>Main page formatting by Dridzt. Much obliged!</sub>
"apart from the convenience factor none of the other concerns stand."
Right - Convenience is the entire reason I'd consider using a library in the first place. If I didn't care about convenience I'd just code all of my group inspection monolithically into each addon and duplicate the code everywhere. A library should go out of its way to provide all the information that any addon finds useful and convenient (provided it doesn't seriously impact performance), and functionality like translating one type of id into another type of id belongs encapsulated in a library, not duplicated in every client.
I understand the voodoo specid values are tokens that can be passed to a handful of Blizzard functions, so I'm not suggesting the library remove those. However, those ids have no intrinsic meaning in and of themselves, which makes them not terribly useful as the primary key for manipulating specs in my addons. What I'm saying is the library should ADDITIONALLY provide the mapping into the spec index 1,2,3 which have a permanent, human-level meaning of the specific talent trees, independent of any functions that may or may not accept them. I have two addons already written that use spec indexes, so I'm not just blowing smoke here.
When my addon wants to look for a Blood DK I find it's less error-prone and more readable to say:
instead of
because "DK talent tree 1" makes more sense to me as a human programmer than "toon spec 250". Taking it a step further and providing locale-independent spec names would be even better, because then I could directly write what I REALLY mean which is :
So that would work for me as well. Tweaking the library to providing these additional, translated bits of information should have no noticable impact on clients that prefer raw specids, but adds the convenience of naming them different ways for addons who prefer that.
@oscarucb
In came here intending to post the same issues more or less a day ago but I changed my mind because apart from the convenience factor none of the other concerns stand.
The global_spec_id hasn't changed across expansions, much less patches.
The SpellBookFrame.lua SPEC_CORE_ABILITY_TEXT or Blizzard_TalentUI.lua SPEC_SPELLS_DISPLAY global tables especially the first one, currently hold a non-localized reference between globalid and class/spec.
Getting specName as well as icon, background etc is trivial with GetSpecializationInfoByID.
Also the specIndex of 1-4 is only used in the "player" versions of the talent functions (GetSpecialization|GetSpecializationRole|GetSpecializationInfo) which won't work for other players, while the inspect API works with globalid (GetInspectSpecialization|GetSpecializationInfoByID|GetSpecializationRoleByID) which also work for the "player" unit.
If anything I see blizzard deprecating the specIndex functions easier than their globalid counterparts.
If you actually think about it, coding an addon around specIndex is much worse than global_spec_id, since you need to build lookups to class/role for everyone but the player anyway.
We can also build a map between specIndex and global_spec_id for each class with for specIndex = 1, GetNumSpecializationsForClassID(class_id) do local global_spec_id, specName = GetSpecializationInfoForClassID(class_id,specIndex) end
New Talent API Cheatsheet:
Final edit:
I do agree that LibGroupInSpecT-1.0 could be using these functions to provide us those mappings as part of the info structure returned so we don't have to replicate it in our addons.
I like the idea of this library, but given it's a library designed to make group talent management easier, it should not force the client to embed that giant table of specialization IDs into my addon in order to decode the .global_spec_id value returned by the library. Those IDs are reverse engineered and there's no reason to believe they will even remain the same across patches.
What I REALLY want is for the library to return me a .spec_index = 1..4, which is the index returned by GetSpecialization(), and is also the order used to display the specs in-game. These indexes and their meaning are far less likely to break in future patches.
It would also be nice to return a .spec_name_localized that gives the localized name of the spec for display and a .spec_role = "TANK"/"HEALER"/"DAMAGER" as a convenience, although I can get also get that info myself with GetSpecializationInfoByID(.global_spec_id ), so this is a lower priority.
Also, do I need to build my own map of global_spec_id -> spec_localized (eg. "Balance", "Unholy" etc) Like the returns from GetSpecializationInfo(specIndex) but for other players.
Edit: Look at my newest post for how this is solved with API.
Are you sure Paladin Retribution is 70 and not 67?
Edit: Checked Blizzard_TalentUI, 70 is indeed correct for some strange reason.