prepare LibGroupTalents, fix broken rebase

This commit is contained in:
NoM0Re
2025-01-27 18:40:55 +01:00
parent 31bcef0dc7
commit a99f7bd323
11 changed files with 2893 additions and 8 deletions
+166
View File
@@ -0,0 +1,166 @@
if not WeakAuras.IsLibsOK() then return end
local AddonName, Private = ...
local timer = WeakAuras.timer;
local eventLock = false
local nameToGlyphs = {}
local nameToSpecMap = {}
local nameToUnitMap = {
[UnitName("player")] = "player"
}
local subscribers = {}
Private.LibGroupTalentsWrapper = {
Register = function(callback) end,
SpecForUnit = function(unit) end,
SpecRolePositionForUnit = function(unit) end,
CheckTalentForUnit = function(unit, talentId) end,
CheckGlyphForUnit = function(unit, glyphId) end,
}
local LibGroupTalents = LibStub("LibGroupTalents-1.0")
if LibGroupTalents then
local frame = CreateFrame("Frame")
frame:RegisterEvent("PLAYER_LOGIN")
frame:RegisterEvent("RAID_ROSTER_UPDATE")
frame:RegisterEvent("PARTY_MEMBERS_CHANGED")
local function ProcessEvent()
local ownName = UnitName("player")
nameToUnitMap = {}
nameToUnitMap[ownName] = "player"
local numMembers
local units
if IsInRaid() then
numMembers = GetNumGroupMembers()
units = WeakAuras.raidUnits
else
numMembers = GetNumPartyMembers()
units = WeakAuras.partyUnits
end
for i = 1, numMembers do
local unit = units[i]
local name = UnitName(unit)
nameToUnitMap[name] = unit
end
for name in pairs(nameToSpecMap) do
if not nameToUnitMap[name] then
nameToSpecMap[name] = nil
nameToGlyphs[name] = nil
end
end
eventLock = false
end
frame:SetScript("OnEvent", function()
if not eventLock then
eventLock = true
timer:ScheduleTimer(ProcessEvent, 1)
end
end)
--- LibGroupTalents callback for talents and glyphs
local function LibGroupTalentsCallback(guid, unit)
local unitName = UnitName(unit)
-- Update specialization data
local specInfo = { LibGroupTalents:GetUnitTalentSpec(unit) }
if specInfo and #specInfo > 0 then
nameToSpecMap[unitName] = specInfo
end
-- Update glyphs
local glyphs = { LibGroupTalents:GetUnitGlyphs(unit) }
if glyphs and #glyphs > 0 then
nameToGlyphs[unitName] = {}
for _, glyphId in ipairs(glyphs) do
nameToGlyphs[unitName][glyphId] = true
end
end
-- Notify subscribers
for _, f in ipairs(subscribers) do
f(nameToUnitMap[unitName])
end
end
LibGroupTalents:RegisterCallback("LibGroupTalents_Update", LibGroupTalentsCallback)
function Private.LibGroupTalentsWrapper.Register(f)
table.insert(subscribers, f)
end
function Private.LibGroupTalentsWrapper.SpecForUnit(unit)
if UnitIsUnit(unit, "player") then
return LibGroupTalents:GetUnitTalentSpec(unit)
end
local unitName = UnitName(unit)
return nameToSpecMap[unitName] and nameToSpecMap[unitName][1] or nil
end
function Private.LibGroupTalentsWrapper.SpecRolePositionForUnit(unit)
if UnitIsUnit(unit, "player") then
return LibGroupTalents:GetUnitTalentSpec(unit)
end
local data = nameToSpecMap[UnitName(unit)]
if data then
return unpack(data)
else
return nil
end
end
function Private.LibGroupTalentsWrapper.CheckTalentForUnit(unit, talentId)
if UnitIsUnit(unit, "player") then
return select(4, WeakAuras.GetTalentById(talentId))
end
local unitName = UnitName(unit)
if not nameToSpecMap[unitName] then
return nil
end
return LibGroupTalents:UnitHasTalent(unit, talentId) and true or false
end
function Private.LibGroupTalentsWrapper.CheckGlyphForUnit(unit, glyphId)
if UnitIsUnit(unit, "player") then
local glyphs = { LibGroupTalents:GetUnitGlyphs(unit) }
for _, id in ipairs(glyphs) do
if id == glyphId then
return true
end
end
return false
end
local unitName = UnitName(unit)
if nameToGlyphs[unitName] then
return nameToGlyphs[unitName][glyphId] or false
end
return false
end
else
function Private.LibGroupTalentsWrapper.Register(f) end
function Private.LibGroupTalentsWrapper.SpecForUnit(unit) return nil end
function Private.LibGroupTalentsWrapper.SpecRolePositionForUnit(unit) return nil end
function Private.LibGroupTalentsWrapper.CheckTalentForUnit(unit) return nil end
function Private.LibGroupTalentsWrapper.CheckGlyphForUnit(unit) return nil end
end
-- Export for GenericTrigger
WeakAuras.SpecForUnit = Private.LibGroupTalentsWrapper.SpecForUnit
WeakAuras.SpecRolePositionForUnit = Private.LibGroupTalentsWrapper.SpecRolePositionForUnit
WeakAuras.CheckTalentForUnit = Private.LibGroupTalentsWrapper.CheckTalentForUnit
WeakAuras.CheckGlyphForUnit = Private.LibGroupTalentsWrapper.CheckGlyphForUnit
@@ -0,0 +1,292 @@
-- LibBabble-3.0 is hereby placed in the Public Domain
-- Credits: ckknight
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR)
if not LibBabble then
return
end
local data = LibBabble.data or {}
for k,v in pairs(LibBabble) do
LibBabble[k] = nil
end
LibBabble.data = data
local tablesToDB = {}
for namespace, db in pairs(data) do
for k,v in pairs(db) do
tablesToDB[v] = db
end
end
local function warn(message)
local _, ret = pcall(error, message, 3)
geterrorhandler()(ret)
end
local lookup_mt = { __index = function(self, key)
local db = tablesToDB[self]
local current_key = db.current[key]
if current_key then
self[key] = current_key
return current_key
end
local base_key = db.base[key]
local real_MAJOR_VERSION
for k,v in pairs(data) do
if v == db then
real_MAJOR_VERSION = k
break
end
end
if not real_MAJOR_VERSION then
real_MAJOR_VERSION = LIBBABBLE_MAJOR
end
if base_key then
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GetLocale()))
rawset(self, key, base_key)
return base_key
end
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key))
rawset(self, key, key)
return key
end }
local function initLookup(module, lookup)
local db = tablesToDB[module]
for k in pairs(lookup) do
lookup[k] = nil
end
setmetatable(lookup, lookup_mt)
tablesToDB[lookup] = db
db.lookup = lookup
return lookup
end
local function initReverse(module, reverse)
local db = tablesToDB[module]
for k in pairs(reverse) do
reverse[k] = nil
end
for k,v in pairs(db.current) do
reverse[v] = k
end
tablesToDB[reverse] = db
db.reverse = reverse
db.reverseIterators = nil
return reverse
end
local prototype = {}
local prototype_mt = {__index = prototype}
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will warn but allow the code to pass through.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BL = B:GetLookupTable()
assert(BL["Some english word"] == "Some localized word")
DoSomething(BL["Some english word that doesn't exist"]) -- warning!
-----------------------------------------------------------------------------]]
function prototype:GetLookupTable()
local db = tablesToDB[self]
local lookup = db.lookup
if lookup then
return lookup
end
return initLookup(self, {})
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_has = B:GetUnstrictLookupTable()
assert(B_has["Some english word"] == "Some localized word")
assert(B_has["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetUnstrictLookupTable()
local db = tablesToDB[self]
return db.current
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_hasBase = B:GetBaseLookupTable()
assert(B_hasBase["Some english word"] == "Some english word")
assert(B_hasBase["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetBaseLookupTable()
local db = tablesToDB[self]
return db.base
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word")
Returns:
A lookup table for localized to english words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BR = B:GetReverseLookupTable()
assert(BR["Some localized word"] == "Some english word")
assert(BR["Some localized word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetReverseLookupTable()
local db = tablesToDB[self]
local reverse = db.reverse
if reverse then
return reverse
end
return initReverse(self, {})
end
local blank = {}
local weakVal = {__mode='v'}
--[[---------------------------------------------------------------------------
Arguments:
string - the localized word to chek for.
Returns:
An iterator to traverse all English words that map to the given key
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for word in B:GetReverseIterator("Some localized word") do
DoSomething(word)
end
-----------------------------------------------------------------------------]]
function prototype:GetReverseIterator(key)
local db = tablesToDB[self]
local reverseIterators = db.reverseIterators
if not reverseIterators then
reverseIterators = setmetatable({}, weakVal)
db.reverseIterators = reverseIterators
elseif reverseIterators[key] then
return pairs(reverseIterators[key])
end
local t
for k,v in pairs(db.current) do
if v == key then
if not t then
t = {}
end
t[k] = true
end
end
reverseIterators[key] = t or blank
return pairs(reverseIterators[key])
end
--[[---------------------------------------------------------------------------
Returns:
An iterator to traverse all translations English to localized.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for english, localized in B:Iterate() do
DoSomething(english, localized)
end
-----------------------------------------------------------------------------]]
function prototype:Iterate()
local db = tablesToDB[self]
return pairs(db.current)
end
-- #NODOC
-- modules need to call this to set the base table
function prototype:SetBaseTranslations(base)
local db = tablesToDB[self]
local oldBase = db.base
if oldBase then
for k in pairs(oldBase) do
oldBase[k] = nil
end
for k, v in pairs(base) do
oldBase[k] = v
end
base = oldBase
else
db.base = base
end
for k,v in pairs(base) do
if v == true then
base[k] = k
end
end
end
local function init(module)
local db = tablesToDB[module]
if db.lookup then
initLookup(module, db.lookup)
end
if db.reverse then
initReverse(module, db.reverse)
end
db.reverseIterators = nil
end
-- #NODOC
-- modules need to call this to set the current table. if current is true, use the base table.
function prototype:SetCurrentTranslations(current)
local db = tablesToDB[self]
if current == true then
db.current = db.base
else
local oldCurrent = db.current
if oldCurrent then
for k in pairs(oldCurrent) do
oldCurrent[k] = nil
end
for k, v in pairs(current) do
oldCurrent[k] = v
end
current = oldCurrent
else
db.current = current
end
end
init(self)
end
for namespace, db in pairs(data) do
setmetatable(db.module, prototype_mt)
init(db.module)
end
-- #NODOC
-- modules need to call this to create a new namespace.
function LibBabble:New(namespace, minor)
local module, oldminor = LibStub:NewLibrary(namespace, minor)
if not module then
return
end
if not oldminor then
local db = {
module = module,
}
data[namespace] = db
tablesToDB[module] = db
else
for k,v in pairs(module) do
module[k] = nil
end
end
setmetatable(module, prototype_mt)
return module
end
@@ -0,0 +1,295 @@
--[[
Name: LibBabble-TalentTree-3.0
Revision: $Rev: 26 $
Maintainers: ckknight, nevcairiel, Ackis
Website: http://www.wowace.com/projects/libbabble-talenttree-3-0/
Dependencies: None
License: MIT
]]
local MAJOR_VERSION = "LibBabble-TalentTree-3.0"
local MINOR_VERSION = 90000 + tonumber(("$Rev: 26 $"):match("%d+"))
if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
local lib = LibStub("LibBabble-3.0"):New(MAJOR_VERSION, MINOR_VERSION)
if not lib then return end
local GAME_LOCALE = GetLocale()
lib:SetBaseTranslations {
Affliction = "Affliction",
Arcane = "Arcane",
Arms = "Arms",
Assassination = "Assassination",
Balance = "Balance",
["Beast Mastery"] = "Beast Mastery",
Blood = "Blood",
Combat = "Combat",
Demonology = "Demonology",
Destruction = "Destruction",
Discipline = "Discipline",
Elemental = "Elemental",
Enhancement = "Enhancement",
["Feral Combat"] = "Feral Combat",
Fire = "Fire",
Frost = "Frost",
Fury = "Fury",
Holy = "Holy",
Hybrid = "Hybrid",
Marksmanship = "Marksmanship",
Protection = "Protection",
Restoration = "Restoration",
Retribution = "Retribution",
Shadow = "Shadow",
Subtlety = "Subtlety",
Survival = "Survival",
Unholy = "Unholy",
}
if GAME_LOCALE == "enUS" then
lib:SetCurrentTranslations(true)
elseif GAME_LOCALE == "deDE" then
lib:SetCurrentTranslations {
Affliction = "Gebrechen",
Arcane = "Arkan",
Arms = "Waffen",
Assassination = "Meucheln",
Balance = "Gleichgewicht",
["Beast Mastery"] = "Tierherrschaft",
Blood = "Blut",
Combat = "Kampf",
Demonology = "Dämonologie",
Destruction = "Zerstörung",
Discipline = "Disziplin",
Elemental = "Elementar",
Enhancement = "Verstärkung",
["Feral Combat"] = "Wilder Kampf",
Fire = "Feuer",
Frost = "Frost",
Fury = "Furor",
Holy = "Heilig",
Hybrid = "Hybride",
Marksmanship = "Treffsicherheit",
Protection = "Schutz",
Restoration = "Wiederherstellung",
Retribution = "Vergeltung",
Shadow = "Schatten",
Subtlety = "Täuschung",
Survival = "Überleben",
Unholy = "Unheilig",
}
elseif GAME_LOCALE == "frFR" then
lib:SetCurrentTranslations {
Affliction = "Affliction",
Arcane = "Arcane",
Arms = "Armes",
Assassination = "Assassinat",
Balance = "Equilibre",
["Beast Mastery"] = "Maîtrise des bêtes",
Blood = "Sang",
Combat = "Combat",
Demonology = "Démonologie",
Destruction = "Destruction",
Discipline = "Discipline",
Elemental = "Elémentaire",
Enhancement = "Amélioration",
["Feral Combat"] = "Combat farouche",
Fire = "Feu",
Frost = "Givre",
Fury = "Fureur",
Holy = "Sacré",
Hybrid = "Hybride",
Marksmanship = "Précision",
Protection = "Protection",
Restoration = "Restauration",
Retribution = "Vindicte",
Shadow = "Ombre",
Subtlety = "Finesse",
Survival = "Survie",
Unholy = "Impie",
}
elseif GAME_LOCALE == "koKR" then
lib:SetCurrentTranslations {
Affliction = "고통",
Arcane = "비전",
Arms = "무기",
Assassination = "암살",
Balance = "조화",
["Beast Mastery"] = "야수",
Blood = "혈기",
Combat = "전투",
Demonology = "악마",
Destruction = "파괴",
Discipline = "수양",
Elemental = "정기",
Enhancement = "고양",
["Feral Combat"] = "야성",
Fire = "화염",
Frost = "냉기",
Fury = "분노",
Holy = "신성",
Hybrid = "하이브리드",
Marksmanship = "사격",
Protection = "방어",
Restoration = "복원",
Retribution = "징벌",
Shadow = "암흑",
Subtlety = "잠행",
Survival = "생존",
Unholy = "부정",
}
elseif GAME_LOCALE == "esES" then
lib:SetCurrentTranslations {
Affliction = "Aflicción",
Arcane = "Arcano",
Arms = "Armas",
Assassination = "Asesinato",
Balance = "Equilibrio",
["Beast Mastery"] = "Dominio de bestias",
Blood = "Sangre",
Combat = "Combate",
Demonology = "Demonología",
Destruction = "Destrucción",
Discipline = "Disciplina",
Elemental = "Elemental",
Enhancement = "Mejora",
["Feral Combat"] = "Combate Feral",
Fire = "Fuego",
Frost = "Escarcha",
Fury = "Furia",
Holy = "Sagrado",
Hybrid = "Híbrido",
Marksmanship = "Puntería",
Protection = "Protección",
Restoration = "Restauración",
Retribution = "Reprensión",
Shadow = "Sombras",
Subtlety = "Sutileza",
Survival = "Supervivencia",
Unholy = "Profano",
}
elseif GAME_LOCALE == "esMX" then
lib:SetCurrentTranslations {
Affliction = "Aflicción",
Arcane = "Arcano",
Arms = "Armas",
Assassination = "Asesinato",
Balance = "Balance",
["Beast Mastery"] = "Bestias",
Blood = "Sangre",
Combat = "Combate",
Demonology = "Demonología",
Destruction = "Destrucción",
Discipline = "Disciplina",
Elemental = "Elemental",
Enhancement = "Mejora",
["Feral Combat"] = "Combate feral",
Fire = "Fuego",
Frost = "Escarcha",
Fury = "Furia",
Holy = "Sagrado",
Hybrid = "Híbrido",
Marksmanship = "Puntería",
Protection = "Protección",
Restoration = "Restauración",
Retribution = "Reprensión",
Shadow = "Sombra",
Subtlety = "Sutileza",
Survival = "Supervivencia",
Unholy = "Profano",
}
elseif GAME_LOCALE == "ruRU" then
lib:SetCurrentTranslations {
Affliction = "Колдовство",
Arcane = "Тайная магия",
Arms = "Оружие",
Assassination = "Убийство",
Balance = "Баланс",
["Beast Mastery"] = "Чувство зверя",
Blood = "Кровь",
Combat = "Бой",
Demonology = "Демонология",
Destruction = "Разрушение",
Discipline = "Послушание",
Elemental = "Укрощение стихии",
Enhancement = "Совершенствование",
["Feral Combat"] = "Сила зверя",
Fire = "Огонь",
Frost = "Лед",
Fury = "Неистовство",
Holy = "Свет",
Hybrid = "Гибрид",
Marksmanship = "Стрельба",
Protection = "Защита",
Restoration = "Исцеление",
Retribution = "Возмездие",
Shadow = "Темная магия",
Subtlety = "Скрытность",
Survival = "Выживание",
Unholy = "Нечестивость",
}
elseif GAME_LOCALE == "zhCN" then
lib:SetCurrentTranslations {
Affliction = "痛苦",
Arcane = "奥术",
Arms = "武器",
Assassination = "刺杀",
Balance = "平衡",
["Beast Mastery"] = "野兽控制",
Blood = "鲜血",
Combat = "战斗",
Demonology = "恶魔学识",
Destruction = "毁灭",
Discipline = "戒律",
Elemental = "元素战斗",
Enhancement = "增强",
["Feral Combat"] = "野性战斗",
Fire = "火焰",
Frost = "冰霜",
Fury = "狂怒",
Holy = "神圣",
Hybrid = "混合",
Marksmanship = "射击",
Protection = "防护",
Restoration = "恢复",
Retribution = "惩戒",
Shadow = "暗影魔法",
Subtlety = "敏锐",
Survival = "生存技能",
Unholy = "邪恶",
}
elseif GAME_LOCALE == "zhTW" then
lib:SetCurrentTranslations {
Affliction = "痛苦",
Arcane = "秘法",
Arms = "武器",
Assassination = "刺殺",
Balance = "平衡",
["Beast Mastery"] = "野獸控制",
Blood = "血魄",
Combat = "戰鬥",
Demonology = "惡魔學識",
Destruction = "毀滅",
Discipline = "戒律",
Elemental = "元素",
Enhancement = "增強",
["Feral Combat"] = "野性戰鬥",
Fire = "火焰",
Frost = "冰霜",
Fury = "狂怒",
Holy = "神聖",
Hybrid = "混合",
Marksmanship = "射擊",
Protection = "防護",
Restoration = "恢復",
Retribution = "懲戒",
Shadow = "暗影",
Subtlety = "敏銳",
Survival = "生存",
Unholy = "穢邪",
}
else
error(("%s: Locale %q not supported"):format(MAJOR_VERSION, GAME_LOCALE))
end
@@ -0,0 +1,21 @@
## Interface: 30300
## LoadOnDemand: 1
## Title: Lib: Babble-TalentTree-3.0
## Notes: A library to help with localization of talent trees.
## Notes-deDE: BabbleLib ist eine Bibliothek, die bei der Lokalisierung helfen soll.
## Notes-esES: Una biblioteca para ayudar con las localizaciones.
## Notes-frFR: Une bibliothèque d'aide à la localisation.
## Notes-ruRU: Библиотека для локализации аддонов.
## Notes-zhCN: 为本地化服务的支持库[声望阵营]
## Notes-zhTW: 為本地化服務的函式庫[聲望陣營]
## Author: Pneumatus
## X-Category: Library
## X-License: MIT
## X-Curse-Packaged-Version: 3.3-release39
## X-Curse-Project-Name: LibBabble-TalentTree-3.0
## X-Curse-Project-ID: libbabble-talenttree-3-0
## X-Curse-Repository-ID: wow/libbabble-talenttree-3-0/mainline
LibStub\LibStub.lua
lib.xml
@@ -0,0 +1,5 @@
<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">
<Script file="LibBabble-3.0.lua" />
<Script file="LibBabble-TalentTree-3.0.lua" />
</Ui>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,358 @@
--[[
Name: LibTalentQuery-1.0
Revision: $Rev: 84 $
Author: Rich Martel (richmartel@gmail.com)
Documentation: http://wowace.com/wiki/LibTalentQuery-1.0
SVN: svn://svn.wowace.com/wow/libtalentquery-1-0/mainline/trunk
Description: Library to help with querying unit talents
Dependancies: LibStub, CallbackHandler-1.0
License: LGPL v2.1
Example Usage:
local TalentQuery = LibStub:GetLibrary("LibTalentQuery-1.0")
TalentQuery.RegisterCallback(self, "TalentQuery_Ready")
local raidTalents = {}
...
TalentQuery:Query(unit)
...
function MyAddon:TalentQuery_Ready(e, name, realm, unitid)
local isnotplayer = not UnitIsUnit(unitid, "player")
local spec = {}
for tab = 1, GetNumTalentTabs(isnotplayer) do
local treename, _, pointsspent = GetTalentTabInfo(tab, isnotplayer)
tinsert(spec, pointsspent)
end
raidTalents[UnitGUID(unitid)] = spec
end
]]
local MAJOR, MINOR = "LibTalentQuery-1.0", 90000 + tonumber(("$Rev: 84 $"):match("(%d+)"))
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
local INSPECTDELAY = 1
local INSPECTTIMEOUT = 5
if not lib.events then
lib.events = LibStub("CallbackHandler-1.0"):New(lib)
end
local validateTrees
local enteredWorld = IsLoggedIn()
local frame = lib.frame
if not frame then
frame = CreateFrame("Frame", MAJOR .. "_Frame")
lib.frame = frame
end
frame:UnregisterAllEvents()
frame:RegisterEvent("INSPECT_TALENT_READY")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("PLAYER_LEAVING_WORLD")
frame:RegisterEvent("PLAYER_LOGIN")
frame:SetScript("OnEvent", function(this, event, ...)
return lib[event](lib, ...)
end)
do
local lastUpdateTime = 0
frame:SetScript("OnUpdate", function(this, elapsed)
lastUpdateTime = lastUpdateTime + elapsed
if lastUpdateTime > INSPECTDELAY then
lib:CheckInspectQueue()
lastUpdateTime = 0
end
end)
frame:Hide()
end
local inspectQueue = lib.inspectQueue or {}
lib.inspectQueue = inspectQueue
local garbageQueue = lib.garbageQueue or {} -- Added a second queue to things. Inspects that initially fail are now
lib.garbageQueue = garbageQueue -- thrown into second queue will will be processed once main queue is empty
if next(inspectQueue) then
frame:Show()
end
local UnitIsPlayer = _G.UnitIsPlayer
local UnitName = _G.UnitName
local UnitExists = _G.UnitExists
local UnitGUID = _G.UnitGUID
local GetNumRaidMembers = _G.GetNumRaidMembers
local GetNumPartyMembers = _G.GetNumPartyMembers
local UnitIsVisible = _G.UnitIsVisible
local UnitIsConnected = _G.UnitIsConnected
local UnitCanAttack = _G.UnitCanAttack
local CanInspect = _G.CanInspect
local function UnitFullName(unit)
local name, realm = UnitName(unit)
local namerealm = realm and realm ~= "" and name .. "-" .. realm or name
return namerealm
end
-- GuidToUnitID
local function GuidToUnitID(guid)
local prefix, min, max = "raid", 1, GetNumRaidMembers()
if max == 0 then
prefix, min, max = "party", 0, GetNumPartyMembers()
end
-- Prioritise getting direct units first because other players targets
-- can change between notify and event which can bugger things up
for i = min, max do
local unit = i == 0 and "player" or prefix .. i
if (UnitGUID(unit) == guid) then
return unit
end
end
-- This properly detects target units
if (UnitGUID("target") == guid) then
return "target"
elseif (UnitGUID("focus") == guid) then
return "focus"
elseif (UnitGUID("mouseover") == guid) then
return "mouseover"
end
for i = min, max + 3 do
local unit
if i == 0 then
unit = "player"
elseif i == max + 1 then
unit = "target"
elseif i == max + 2 then
unit = "focus"
elseif i == max + 3 then
unit = "mouseover"
else
unit = prefix .. i
end
if (UnitGUID(unit .. "target") == guid) then
return unit .. "target"
elseif (i <= max and UnitGUID(unit.."pettarget") == guid) then
return unit .. "pettarget"
end
end
return nil
end
-- Query
function lib:Query(unit)
if (UnitLevel(unit) < 10 or UnitName(unit) == UNKNOWN) then
return
end
self.lastQueuedInspectReceived = nil
if UnitIsUnit(unit, "player") then
self.events:Fire("TalentQuery_Ready", UnitName("player"), nil, "player")
else
if type(unit) ~= "string" then
error(("Bad argument #2 to 'Query'. Expected %q, received %q (%s)"):format("string", type(unit), tostring(unit)), 2)
elseif not UnitExists(unit) or not UnitIsPlayer(unit) then
error(("Bad argument #2 to 'Query'. %q is not a valid player unit"):format(tostring(unit)), 2)
elseif not UnitExists(unit) or not UnitIsPlayer(unit) then
error(("Bad argument #2 to 'Query'. %q does not require a server query before reading talents"):format("player"), 2)
else
local name = UnitFullName(unit)
if (not inspectQueue[name]) then
inspectQueue[name] = UnitGUID(unit)
garbageQueue[name] = nil
end
frame:Show()
end
end
end
-- CheckInspectQueue
-- Originally, it would wait until no pending NotifyInspect() were expected, and then do it's own.
-- It was also only bother looking at ready results if it had triggered the Notify for that occasion.
-- For the changes I've done, no assumption is made about which mod is performing NotifyInspect().
-- We note the name, unit, time of any inspects done whether from this queue or any other source,
-- we remove from our queue any we were expecting, and use a seperate event in case extra talent
-- info is any time wanted (opportunistic refreshes etc) - Zeksie, 20th May 2009
function lib:CheckInspectQueue()
if (_G.InspectFrame and _G.InspectFrame:IsShown()) then
return
end
if (not self.lastInspectTime or self.lastInspectTime < GetTime() - INSPECTTIMEOUT) then
self.lastInspectPending = 0
end
if (self.lastInspectPending > 0 or not enteredWorld) then
return
end
if (self.lastQueuedInspectReceived and self.lastQueuedInspectReceived < GetTime() - 60) then
-- No queued results received for a minute, so purge the queue as invalid and move on with our lives
self.lastQueuedInspectReceived = nil
inspectQueue = {}
lib.inspectQueue = inspectQueue
garbageQueue = {}
lib.garbageQueue = garbageQueue
frame:Hide()
return
end
for name,guid in pairs(inspectQueue) do
local unit = GuidToUnitID(guid)
if (not unit) then
inspectQueue[name] = nil
else
if (UnitIsVisible(unit) and UnitIsConnected(unit) and not UnitCanAttack("player", unit) and not UnitCanAttack(unit, "player") and CanInspect(unit) and UnitClass(unit)) then
NotifyInspect(unit)
break
else
garbageQueue[name] = guid -- Not available, throw into secondary queue and continue
inspectQueue[name] = nil
end
end
end
if (not next(inspectQueue)) then
if (next(garbageQueue)) then
-- Retry initially failed inspects
lib.inspectQueue = garbageQueue
inspectQueue = lib.inspectQueue
lib.garbageQueue = {}
garbageQueue = lib.garbageQueue
else
frame:Hide()
end
end
end
-- NotifyInspect
if not lib.NotifyInspect then -- don't hook twice
hooksecurefunc("NotifyInspect", function(...) return lib:NotifyInspect(...) end)
end
function lib:NotifyInspect(unit)
if (not (UnitExists(unit) and UnitIsVisible(unit) and UnitIsConnected(unit) and CheckInteractDistance(unit, 4))) then
return
end
self.lastInspectUnit = unit
self.lastInspectGUID = UnitGUID(unit)
self.lastInspectTime = GetTime()
self.lastInspectName = UnitFullName(unit)
self.lastInspectPending = self.lastInspectPending + 1
local isnotplayer = not UnitIsUnit("player", unit)
self.lastInspectTree = GetTalentTabInfo(1, isnotplayer) -- Talent tree names are available immediately
end
-- Reset
function lib:Reset()
self.lastInspectPending = 0
self.lastInspectUnit = nil
self.lastInspectTime = nil
self.lastInspectName = nil
self.lastInspectGUID = nil
self.lastInspectTree = nil
end
-- INSPECT_TALENT_READY
function lib:INSPECT_TALENT_READY()
self.lastInspectPending = self.lastInspectPending - 1
-- Results are valid only when we have received as many events as we have posted notifies
if (self.lastInspectName and self.lastInspectPending == 0) then
-- Check unit ID is still pointing to same actual unit
if (UnitGUID(self.lastInspectUnit) == self.lastInspectGUID) then
local guid = inspectQueue[self.lastInspectName]
inspectQueue[self.lastInspectName] = nil
local name, realm = strsplit("-", self.lastInspectName)
self.lastQueuedInspectReceived = GetTime()
-- Notify of expected talent results
local isnotplayer = not UnitIsUnit("player", self.lastInspectName)
local group = GetActiveTalentGroup(isnotplayer)
local tree1, _, spent1 = GetTalentTabInfo(1, isnotplayer, nil, group)
if (tree1 ~= self.lastInspectTree) then
-- Expected talent tree name to be the same as it was when we triggered the NotifyInspect()
garbageQueue[self.lastInspectName] = self.lastInspectGUID
self:Reset()
self:CheckInspectQueue()
return
elseif (validateTrees) then
-- Double checking here. Check the tree name matches what we expect for this class
local _, class = UnitClass(self.lastInspectUnit)
if (tree1 ~= validateTrees[class]) then
garbageQueue[self.lastInspectName] = self.lastInspectGUID
self:Reset()
self:CheckInspectQueue()
return
end
end
local tree2, _, spent2 = GetTalentTabInfo(2, isnotplayer, nil, group)
local tree3, _, spent3 = GetTalentTabInfo(3, isnotplayer, nil, group)
if ((spent1 or 0) + (spent2 or 0) + (spent3 or 0) > 0) then
if (guid) then
-- It was in our queue
self.events:Fire("TalentQuery_Ready", name, realm, self.lastInspectUnit)
else
-- Also notify of non-expected ones, as it's entirely useful to refresh them if they're there
-- It is up to the receiving applicating to determine whether they want to receive the information
self.events:Fire("TalentQuery_Ready_Outsider", name, realm, self.lastInspectUnit)
end
else
-- Tree came back with zero points spent, probably an issue while logging in
garbageQueue[self.lastInspectName] = guid
end
end
self:Reset()
self:CheckInspectQueue()
end
end
function lib:PLAYER_ENTERING_WORLD()
-- We can't inspect other's talents until now
-- We just get 0/0/0 back even though we get an INSPECT_TALENT_READY event
enteredWorld = true
end
function lib:PLAYER_LEAVING_WORLD()
enteredWorld = nil
end
function lib:PLAYER_LOGIN()
validateTrees = {
DRUID = "Balance",
PRIEST = "Discipline",
ROGUE = "Assassination",
HUNTER = "Beast Mastery",
WARLOCK = "Affliction",
WARRIOR = "Arms",
DEATHKNIGHT = "Blood",
PALADIN = "Holy",
SHAMAN = "Elemental",
MAGE = "Arcane",
}
if (GetLocale() ~= "enUS" and GetLocale() ~= "enGB") then
-- LibBabble-TalentTree-3.0 only loaded if present and not enUS
local LBT = LibStub("LibBabble-TalentTree-3.0", true)
if (not LBT) then
LoadAddOn("LibBabble-TalentTree-3.0")
LBT = LibStub("LibBabble-TalentTree-3.0", true)
end
LBT = LBT and LBT:GetLookupTable()
if (LBT) then
for class,tree1 in pairs(validateTrees) do
validateTrees[class] = LBT[tree1]
end
else
validateTrees = nil
end
end
self.PLAYER_LOGIN = nil
end
lib:Reset()
@@ -0,0 +1,5 @@
<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">
<Script file="LibTalentQuery-1.0.lua"/>
<Script file="LibGroupTalents-1.0.lua"/>
</Ui>
+21 -8
View File
@@ -2438,14 +2438,27 @@ local function validateUserConfig(data, options, config)
end
end
local function removeNameplateUnits(data)
for _, triggerData in ipairs(data.triggers) do
local trigger = triggerData.trigger
if trigger and trigger.type == "unit" then
if trigger.unit == "nameplate" then
trigger.unit = "target"
end
end
local function removeNameplateUnitsAndAnchors(data)
-- Dynamic Group Anchor
if data.useAnchorPerUnit == true and data.anchorPerUnit == "NAMEPLATE" then
data.useAnchorPerUnit = false
data.anchorPerUnit = "CUSTOM"
end
-- Aura Anchor
if data.anchorFrameType == "NAMEPLATE" then
data.anchorFrameType = "SCREEN"
end
-- Action Glow Anchor
if data.actions and data.actions.start and data.actions.start.glow_frame_type == "NAMEPLATE" then
data.actions.start.glow_frame_type = "FRAMESELECTOR"
end
-- Trigger units
for _, triggerData in ipairs(data.triggers) do
local trigger = triggerData.trigger
if trigger and trigger.type == "unit" then
if trigger.unit == "nameplate" then
trigger.unit = "target"
end
end
end
end
+1
View File
@@ -42,6 +42,7 @@ Conditions.lua
AnchorToWeakAuras.lua
# Trigger systems
LibGroupTalentsWrapper.lua
BuffTrigger2.lua
GenericTrigger.lua
BossMods.lua
+2
View File
@@ -16,4 +16,6 @@
<Script file="Libs\LibGetFrame-1.0\LibGetFrame-1.0.lua"/>
<Include file="Libs\Archivist\Archivist.xml"/>
<Include file="Libs\LibSerialize\lib.xml"/>
<Include file="Libs\LibGroupTalents-1.0\lib.xml"/>
<Include file="Libs\LibBabble-TalentTree-3.0\lib.xml"/>
</Ui>