forked from Dusk/ShaguTweaks-ClassicAPI
WorldMap Class Colors assumed WorldMapRaidN shows raidN. In a raid the map packs its icons and stores the real unit on each icon, so icons showed other players' class colors. Use the icon's unit, or its name for battleground team members outside the raid. The updaters are now children of the maps, so they only run while a map is open. Class Portraits checked the target-of-target GUID on every frame. Check when the stock handler reports a new name, and otherwise five times a second. Enlarged Minimap is unchanged: the stock UI re-anchors the buff frame every frame, so its check has to as well. Documented in Docs/PERFORMANCE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019W3rwusM4i1CYaHQAYixJ7
122 lines
4.2 KiB
Lua
122 lines
4.2 KiB
Lua
local _G = ShaguTweaks.GetGlobalEnv()
|
|
local T = ShaguTweaks.T
|
|
local API = ShaguTweaks.API or {}
|
|
|
|
local addonpath
|
|
local tocs = { "", "-master", "-tbc", "-wotlk" }
|
|
for _, name in pairs(tocs) do
|
|
local current = string.format("ShaguTweaks%s", name)
|
|
local _, title = GetAddOnInfo(current)
|
|
if title then
|
|
addonpath = "Interface\\AddOns\\" .. current
|
|
break
|
|
end
|
|
end
|
|
|
|
local CLASS_ICON_TCOORDS = {
|
|
["WARRIOR"] = { 0, 0.25, 0, 0.25 },
|
|
["MAGE"] = { 0.25, 0.49609375, 0, 0.25 },
|
|
["ROGUE"] = { 0.49609375, 0.7421875, 0, 0.25 },
|
|
["DRUID"] = { 0.7421875, 0.98828125, 0, 0.25 },
|
|
["HUNTER"] = { 0, 0.25, 0.25, 0.5 },
|
|
["SHAMAN"] = { 0.25, 0.49609375, 0.25, 0.5 },
|
|
["PRIEST"] = { 0.49609375, 0.7421875, 0.25, 0.5 },
|
|
["WARLOCK"] = { 0.7421875, 0.98828125, 0.25, 0.5 },
|
|
["PALADIN"] = { 0, 0.25, 0.5, 0.75 },
|
|
["DEATHKNIGHT"] = { 0.25, .5, 0.5, .75 },
|
|
}
|
|
|
|
local module = ShaguTweaks:register({
|
|
title = T["Unit Frame Class Portraits"],
|
|
description = T["Replace unitframe portraits with class icons."],
|
|
expansions = { ["vanilla"] = true },
|
|
category = T["Unit Frames"],
|
|
enabled = nil,
|
|
})
|
|
|
|
local function UpdatePortraits(frame)
|
|
if not frame or not frame.unit or not frame.portrait then return end
|
|
|
|
-- detect unit class or remove for non-player units
|
|
local _, class = UnitClass(frame.unit)
|
|
class = UnitIsPlayer(frame.unit) and class or nil
|
|
|
|
-- Reapply after Blizzard's UnitFrame_Update: that function can replace the
|
|
-- portrait texture even when the new target has the same class.
|
|
if class then
|
|
local iconCoords = CLASS_ICON_TCOORDS[class]
|
|
if iconCoords then
|
|
frame.portrait:SetTexture(addonpath .. "\\img\\UI-Classes-Circles")
|
|
frame.portrait:SetTexCoord(unpack(iconCoords))
|
|
end
|
|
else
|
|
frame.portrait:SetTexCoord(0, 1, 0, 1)
|
|
end
|
|
end
|
|
|
|
module.enable = function(self)
|
|
-- overwrite portraits set by the game
|
|
local original = UnitFrame_Update
|
|
UnitFrame_Update = function(arg1, arg2, arg3)
|
|
original(arg1, arg2, arg3)
|
|
UpdatePortraits(this)
|
|
end
|
|
|
|
-- handle portrait update events
|
|
local events = CreateFrame("Frame")
|
|
events:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
events:RegisterEvent("UNIT_PORTRAIT_UPDATE")
|
|
events:SetScript("OnEvent", function()
|
|
UpdatePortraits(PlayerFrame)
|
|
UpdatePortraits(TargetFrame)
|
|
UpdatePortraits(PartyMemberFrame1)
|
|
UpdatePortraits(PartyMemberFrame2)
|
|
UpdatePortraits(PartyMemberFrame3)
|
|
UpdatePortraits(PartyMemberFrame4)
|
|
end)
|
|
|
|
-- Turtle/Vanilla already runs TargetofTarget_OnUpdate for the target-of-target
|
|
-- frame. Reuse that existing update path instead of adding a second poller.
|
|
-- Keep a GUID cache when ClassicAPI is available so two units with the same
|
|
-- display name are still detected as different units.
|
|
local lasttotguid = nil
|
|
if type(TargetofTarget_OnUpdate) == "function" then
|
|
local originalTargetofTargetOnUpdate = TargetofTarget_OnUpdate
|
|
-- The stock handler replaces the portrait when CURRENT_TARGETTARGET (the
|
|
-- target-of-target's name) changes; reapply the class icon in that same
|
|
-- frame. A GUID check five times a second covers same-name units and
|
|
-- clients whose handler does not track that global, instead of calling
|
|
-- UnitGUID on every frame.
|
|
local totelapsed = 0
|
|
TargetofTarget_OnUpdate = function(elapsed)
|
|
local before = CURRENT_TARGETTARGET
|
|
originalTargetofTargetOnUpdate(elapsed)
|
|
|
|
totelapsed = totelapsed + (elapsed or arg1 or 0)
|
|
if CURRENT_TARGETTARGET == before and totelapsed < .2 then return end
|
|
totelapsed = 0
|
|
|
|
local guid = API.UnitGUID and API.UnitGUID("targettarget") or UnitName("targettarget")
|
|
if guid ~= lasttotguid or CURRENT_TARGETTARGET ~= before then
|
|
lasttotguid = guid
|
|
UpdatePortraits(TargetofTargetFrame)
|
|
end
|
|
end
|
|
else
|
|
-- Compatibility fallback for clients that do not expose the stock handler.
|
|
local tot = CreateFrame("Frame", nil, TargetFrame)
|
|
tot.elapsed = 0
|
|
tot:SetScript("OnUpdate", function()
|
|
this.elapsed = this.elapsed + arg1
|
|
if this.elapsed < .2 then return end
|
|
this.elapsed = 0
|
|
|
|
local guid = API.UnitGUID and API.UnitGUID("targettarget") or UnitName("targettarget")
|
|
if guid ~= lasttotguid then
|
|
lasttotguid = guid
|
|
UpdatePortraits(TargetofTargetFrame)
|
|
end
|
|
end)
|
|
end
|
|
end
|