Johnny C. Lam [12-09-13 - 02:14]
diff --git a/OvaleAura.lua b/OvaleAura.lua
index c8ccc43..517844a 100644
--- a/OvaleAura.lua
+++ b/OvaleAura.lua
@@ -277,7 +277,7 @@ function OvaleAura:COMBAT_LOG_EVENT_UNFILTERED(event, ...)
if CLEU_AURA_EVENTS[event] then
local unitId = OvaleGUID:GetUnitId(destGUID)
- if unitId and not OvaleGUID.UNIT_AURA_UNITS[unitId] then
+ if unitId and not OvaleGUID.UNIT_AURA_UNIT[unitId] then
Ovale:DebugPrintf(OVALE_AURA_DEBUG, "%s: %s", event, unitId)
self:ScanAurasOnGUID(destGUID)
end
@@ -335,7 +335,7 @@ end
function OvaleAura:ScanAllUnitAuras()
-- Update auras on all visible units.
- for unitId in pairs(OvaleGUID.UNIT_AURA_UNITS) do
+ for unitId in pairs(OvaleGUID.UNIT_AURA_UNIT) do
self:ScanAuras(unitId)
end
end
diff --git a/OvaleGUID.lua b/OvaleGUID.lua
index 0396bd0..f32bd5c 100644
--- a/OvaleGUID.lua
+++ b/OvaleGUID.lua
@@ -8,66 +8,116 @@
file accompanying this program.
--]]--------------------------------------------------------------------
--- This addon translates a GUID to a target name
--- Usage: OvaleGUID:GetUnitId(guid)
+--[[
+ This addon manages mappings between GUID <--> unit ID <--> unit name.
+
+ A GUID can have multiple unit IDs.
+ A unit ID can only have one GUID.
+ A unit ID may not exist.
+
+ All primary unit IDs receive events.
+ No <unit>target IDs receive events.
+ No "mouseover" unit IDs receive events.
+--]]
local _, Ovale = ...
-local OvaleGUID = Ovale:NewModule("OvaleGUID", "AceEvent-3.0", "AceConsole-3.0")
+local OvaleGUID = Ovale:NewModule("OvaleGUID", "AceEvent-3.0")
Ovale.OvaleGUID = OvaleGUID
--<private-static-properties>
-local strfind = string.find
-local strsub = string.sub
+local ipairs = ipairs
+local tinsert = table.insert
local API_GetNumGroupMembers = GetNumGroupMembers
-local API_UnitExists = UnitExists
local API_UnitGUID = UnitGUID
local API_UnitName = UnitName
local OVALE_GUID_DEBUG = "guid"
---</private-static-properties>
---<public-static-properties>
-OvaleGUID.unitId = {}
-OvaleGUID.guid = {}
-OvaleGUID.nameToGUID = {}
-OvaleGUID.nameToUnit = {}
+--[[
+ Unit IDs for which UNIT_AURA events are known to fire.
--- Units for which UNIT_AURA is known to fire.
--- These are unit IDs that correspond to unit frames in the default WoW UI.
-OvaleGUID.UNIT_AURA_UNITS = {}
+ UNIT_AURA_UNITS is an ordered list of unit ID priority.
+ UNIT_AURA_UNIT is a table that holds the reverse mapping of UNIT_AURA_UNITS.
+--]]
+local UNIT_AURA_UNITS = {}
do
- local self = OvaleGUID
- self.UNIT_AURA_UNITS["focus"] = true
- self.UNIT_AURA_UNITS["pet"] = true
- self.UNIT_AURA_UNITS["player"] = true
- self.UNIT_AURA_UNITS["target"] = true
-
+ tinsert(UNIT_AURA_UNITS, "player")
+ tinsert(UNIT_AURA_UNITS, "pet")
+ tinsert(UNIT_AURA_UNITS, "vehicle")
+ tinsert(UNIT_AURA_UNITS, "npc")
+ tinsert(UNIT_AURA_UNITS, "target")
+ tinsert(UNIT_AURA_UNITS, "focus")
for i = 1, 5 do
- self.UNIT_AURA_UNITS["arena" .. i] = true
- self.UNIT_AURA_UNITS["arenapet" .. i] = true
+ tinsert(UNIT_AURA_UNITS, "arena" .. i)
+ tinsert(UNIT_AURA_UNITS, "arenapet" .. i)
+ end
+ for i = 1, 40 do
+ tinsert(UNIT_AURA_UNITS, "raid" .. i)
+ tinsert(UNIT_AURA_UNITS, "raidpet" .. i)
end
for i = 1, 4 do
- self.UNIT_AURA_UNITS["boss" .. i] = true
+ tinsert(UNIT_AURA_UNITS, "party" .. i)
+ tinsert(UNIT_AURA_UNITS, "partypet" .. i)
+ end
+ for i = 1, 4 do
+ tinsert(UNIT_AURA_UNITS, "boss" .. i)
+ end
+end
+
+local UNIT_AURA_UNIT = {}
+do
+ for i, unitId in ipairs(UNIT_AURA_UNITS) do
+ UNIT_AURA_UNIT[unitId] = i
+ end
+end
+
+-- PET_UNIT[unitId] = pet's unit ID
+local PET_UNIT = {}
+do
+ PET_UNIT["player"] = "pet"
+ for i = 1, 5 do
+ PET_UNIT["arena" .. i] = "arenapet" .. i
end
for i = 1, 4 do
- self.UNIT_AURA_UNITS["party" .. i] = true
- self.UNIT_AURA_UNITS["partypet" .. i] = true
+ PET_UNIT["party" .. i] = "partypet" .. i
end
for i = 1, 40 do
- self.UNIT_AURA_UNITS["raid" .. i] = true
- self.UNIT_AURA_UNITS["raidpet" .. i] = true
+ PET_UNIT["raid" .. i] = "raidpet" .. i
end
end
+--</private-static-properties>
+
+--<public-static-properties>
+--[[
+ Unit ID --> GUID mapping.
+ unit ID can only have one GUID.
+ self.unitIdToGUID[unitId] = GUID
+--]]
+OvaleGUID.unitIdToGUID = {}
+
+--[[
+ GUID --> unit ID mapping.
+ A GUID can have multiple unit IDs.
+ self.GUIDtoUnitId[guid] = { unitId = true if it exists and points to guid; nil otherwise }
+--]]
+OvaleGUID.GUIDtoUnitId = {}
+
+--[[
+--]]
+OvaleGUID.nameToGUID = {}
+
+-- Export UNIT_AURA_UNIT table of units that receive UNIT_AURA events.
+OvaleGUID.UNIT_AURA_UNIT = UNIT_AURA_UNIT
--</public-static-properties>
--<public-static-methods>
function OvaleGUID:OnEnable()
- self:Update("player")
self:RegisterEvent("ARENA_OPPONENT_UPDATE")
self:RegisterEvent("GROUP_ROSTER_UPDATE")
self:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT")
+ self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateAllUnits")
self:RegisterEvent("PLAYER_FOCUS_CHANGED")
- self:RegisterEvent("PLAYER_LOGIN")
+ self:RegisterEvent("PLAYER_LOGIN", "UpdateAllUnits")
self:RegisterEvent("PLAYER_TARGET_CHANGED")
self:RegisterEvent("UNIT_PET")
self:RegisterEvent("UNIT_TARGET")
@@ -78,6 +128,7 @@ function OvaleGUID:OnDisable()
self:UnregisterEvent("ARENA_OPPONENT_UPDATE")
self:UnregisterEvent("GROUP_ROSTER_UPDATE")
self:UnregisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT")
+ self:UnregisterEvent("PLAYER_ENTERING_WORLD")
self:UnregisterEvent("PLAYER_FOCUS_CHANGED")
self:UnregisterEvent("PLAYER_LOGIN")
self:UnregisterEvent("PLAYER_TARGET_CHANGED")
@@ -86,144 +137,136 @@ function OvaleGUID:OnDisable()
self:UnregisterEvent("UPDATE_MOUSEOVER_UNIT")
end
-function OvaleGUID:Update(unitId)
- local guid = API_UnitGUID(unitId)
- local previousGuid = self.guid[unitId]
- if previousGuid ~= guid then
- if previousGuid and self.unitId[previousGuid] then
- self.unitId[previousGuid][unitId] = nil
- if not next(self.unitId[previousGuid]) then
- self.unitId[previousGuid] = nil
- end
- end
- self.guid[unitId] = guid
- if guid then
- if not self.unitId[guid] then
- self.unitId[guid] = {}
- end
- Ovale:DebugPrintf(OVALE_GUID_DEBUG, "GUID %s is %s", guid, unitId)
- self.unitId[guid][unitId] = true
- end
- end
- local name = API_UnitName(unitId)
- if name and (not self.nameToGUID[name] or unitId == "target"
- or self.nameToUnit[name] == "mouseover") then
- self.nameToGUID[name] = guid
- self.nameToUnit[name] = unitId
+function OvaleGUID:ARENA_OPPONENT_UPDATE(event, unitId, eventType)
+ for i = 1, 5 do
+ local unit = "arena" .. i
+ self:UpdateUnitWithTarget(unit)
+ local pet = PET_UNIT[unit] or (unit .. "pet")
+ self:UpdateUnitWithTarget(pet)
end
end
-function OvaleGUID:GetGUID(unitId)
- if not unitId then return nil end
- local guid = self.guid[unitId]
- if not guid or strfind(unitId, "mouseover") == 1 then
- self.guid[unitId] = API_UnitGUID(unitId)
- guid = self.guid[unitId]
- end
- return guid
+function OvaleGUID:GROUP_ROSTER_UPDATE(event)
+ self:UpdateAllUnits()
+ self:SendMessage("Ovale_GroupChanged")
end
-function OvaleGUID:GetGUIDForName(name)
- return self.nameToGUID[name]
+function OvaleGUID:INSTANCE_ENCOUNTER_ENGAGE_UNIT(event)
+ for i= 1, 4 do
+ self:UpdateUnitWithTarget("boss" .. i)
+ end
end
--- Return a unit Id associated with guid.
--- Prefer to return a unit Id for which the WoW servers fire UNIT_AURA events.
-function OvaleGUID:GetUnitId(guid)
- local unitIdFound = nil
- local unitIdTable = self.unitId[guid]
- if unitIdTable then
- for unitId in pairs(unitIdTable) do
- if self.UNIT_AURA_UNITS[unitId] then
- return unitId
- elseif not unitIdFound then
- if strfind(unitId, "mouseover") == 1 then
- if API_UnitExists(unitId) then
- unitIdFound = unitId
- else
- unitIdTable[unitId] = nil
- self.guid[unitId] = nil
- end
- else
- unitIdFound = unitId
- end
- end
- end
- end
- return unitIdFound
+function OvaleGUID:PLAYER_FOCUS_CHANGED(event)
+ self:UpdateUnitWithTarget("focus")
end
-function OvaleGUID:GetUnitIdForName(name)
- local unitId = self.nameToUnit[name]
- if strfind(unitId, "mouseover") == 1 then
- if API_UnitExists("mouseover") then
- return unitId
- else
- self.nameToUnit[name] = nil
- return nil
- end
- end
- return unitId
+function OvaleGUID:PLAYER_TARGET_CHANGED(event, cause)
+ self:UNIT_TARGET(event, "player")
end
-function OvaleGUID:UpdateWithTarget(unitId)
- self:Update(unitId)
- self:Update(unitId.."target")
+function OvaleGUID:UNIT_PET(event, unitId)
+ local pet = PET_UNIT[unitiD] or (unitId .. "pet")
+ self:UpdateUnitWithTarget(pet)
+ self:SendMessage("Ovale_GroupChanged")
end
-function OvaleGUID:PLAYER_LOGIN(event)
- self:Update("player")
+function OvaleGUID:UNIT_TARGET(event, unitId)
+ local target = (unitId == "player") and "target" or (unitId .. "target")
+ self:UpdateUnit(target)
end
-function OvaleGUID:PLAYER_TARGET_CHANGED(event)
- self:UNIT_TARGET(event, "player")
+function OvaleGUID:UPDATE_MOUSEOVER_UNIT(event)
+ self:UpdateUnitWithTarget("mouseover")
end
-function OvaleGUID:UNIT_TARGET(event, unitId)
- self:Update(unitId .. "target")
- if unitId == "player" then
- self:Update("target")
+function OvaleGUID:UpdateAllUnits()
+ for _, unitId in pairs(UNIT_AURA_UNITS) do
+ self:UpdateUnitWithTarget(unitId)
end
end
-function OvaleGUID:GROUP_ROSTER_UPDATE(event)
- for i=1, API_GetNumGroupMembers() do
- self:UpdateWithTarget("raid"..i)
- self:UpdateWithTarget("raidpet"..i)
- end
- self:SendMessage("Ovale_GroupChanged")
+function OvaleGUID:UpdateUnitWithTarget(unitId)
+ self:UpdateUnit(unitId)
+ self:UpdateUnit(unitId .. "target")
end
-function OvaleGUID:UNIT_PET(event, unitId)
- if strfind(unitId, "party") == 0 then
- local petId = "partypet" .. strsub(unitId, 6)
- self:UpdateWithTarget(petId)
- elseif strfind(unitId, "raid") == 0 then
- local petId = "raidpet" .. strsub(unitId, 5)
- self:UpdateWithTarget(petId)
- elseif unitId == "player" then
- self:UpdateWithTarget("pet")
+function OvaleGUID:UpdateUnit(unitId)
+ local guid = API_UnitGUID(unitId)
+ if guid then
+ local previousGUID = self.unitIdToGUID[unitId]
+ if previousGUID ~= guid then
+ -- Remove previous mappings for this unit ID.
+ if previousGUID and self.GUIDtoUnitId[previousGUID] then
+ self.GUIDtoUnitId[previousGUID][unitId] = nil
+ if not next(self.GUIDtoUnitId[previousGUID]) then
+ self.GUIDtoUnitId[previousGUID] = nil
+ end
+ end
+ -- Create new mappings this unit ID to the GUID.
+ self.unitIdToGUID[unitId] = guid
+ self.GUIDtoUnitId[guid] = self.GUIDtoUnitId[guid] or {}
+ self.GUIDtoUnitId[guid][unitId] = true
+
+ Ovale:DebugPrintf(OVALE_GUID_DEBUG, "GUID %s is %s", guid, unitId)
+
+ if unitId == "target" or self.unitIdToGUID.target ~= guid then
+ local name = API_UnitName(unitId)
+ self.nameToGUID[name] = self.nameToGUID[name] or guid
+ end
+ end
+ else
+ -- This unit ID doesn't point to a valid GUID.
+ self.unitIdToGUID[unitId] = nil
+ if self.GUIDtoUnitId[guid] then
+ self.GUIDtoUnitId[guid][unitId] = nil
+ if not next(self.GUIDtoUnitId[guid]) then
+ self.GUIDtoUnitId[guid] = nil
+ end
+ end
end
- self:SendMessage("Ovale_GroupChanged")
end
-function OvaleGUID:ARENA_OPPONENT_UPDATE(event)
- for i=1, 5 do
- self:UpdateWithTarget("arena"..i)
+function OvaleGUID:GetGUID(unitId)
+ if unitId then
+ -- If the unit ID doesn't receive events, then refresh it now.
+ if not UNIT_AURA_UNIT[unitId] then
+ self:UpdateUnit(unitId)
+ end
+ return self.unitIdToGUID[unitId]
end
+ return nil
end
-function OvaleGUID:PLAYER_FOCUS_CHANGED(event)
- self:UpdateWithTarget("focus")
+function OvaleGUID:GetUnitId(guid)
+ if self.GUIDtoUnitId[guid] then
+ -- Find the unit ID with the best (lowest) priority.
+ local bestUnitId, bestPriority
+ for unitId in pairs(self.GUIDtoUnitId[guid]) do
+ local priority = UNIT_AURA_UNIT[unitId]
+ if priority then
+ if not bestPriority or priority < bestPriority then
+ bestUnitId, bestPriority = unitId, priority
+ end
+ else
+ -- This isn't a unit ID that receives events, so refresh it to make
+ -- sure it still points to this GUID.
+ self:UpdateUnit(unitId)
+ if not bestPriority and self.unitIdToGUID[unitId] == guid then
+ bestUnitId = unitId
+ end
+ end
+ end
+ return bestUnitId
+ end
+ return nil
end
-function OvaleGUID:UPDATE_MOUSEOVER_UNIT(event)
- self:UpdateWithTarget("mouseover")
+function OvaleGUID:GetGUIDForName(name)
+ return self.nameToGUID[name]
end
-function OvaleGUID:INSTANCE_ENCOUNTER_ENGAGE_UNIT(event)
- for i=1, 4 do
- self:UpdateWithTarget("boss"..i)
- end
+function OvaleGUID:GetUnitIdForName(name)
+ return self:GetUnitId(self:GetGUIDForName(name))
end
--</public-static-methods>