Files
Microchip-chat/MicrochipClassColors.lua
2026-10-30 18:27:26 -04:00

182 lines
6.1 KiB
Lua

-- Microchip-chat: player-name class colors for vanilla 1.12 (Lua 5.0).
-- Chat events do not contain reliable class metadata. Cache classes learned
-- from native unit, raid, guild, friend and /who information; do not guess.
MCClassColors = {}
local colors = {
PALADIN="F58CBA", SHAMAN="0070DE", HUNTER="ABD473",
WARLOCK="9482C9", WARRIOR="C79C6E", ROGUE="FFF569",
PRIEST="FFFFFF", DRUID="FF7D0A", MAGE="69CCF0"
}
local known = {}
local localized = {}
local function normalizeClass(value)
if type(value)~="string" then return nil end
local english=string.upper(value)
if colors[english] then return english end
return localized[value] or localized[english]
end
local function playerKey(name)
if type(name)~="string" or name=="" then return nil end
return string.lower(name)
end
local function learn(name,class)
local key=playerKey(name)
local token=normalizeClass(class)
if not key or not token or known[key]==token then return false end
known[key]=token
return true
end
-- Prat keeps its own class cache. Reuse it when Prat is already installed,
-- but never require Prat (or any of its Ace libraries) to be present.
-- Native unit/roster information takes priority over this optional cache.
local function learnPrat()
local prat=Prat_PlayerNames
if type(prat)~="table" then return false end
local changed=false
local function import(source)
if type(source)~="table" then return end
local name,class
for name,class in pairs(source) do
if type(name)=="string" and not known[playerKey(name)] then
if learn(name,class) then changed=true end
end
end
end
import(prat.Classes)
if prat.db and prat.db.profile then import(prat.db.profile.classes) end
return changed
end
local function learnUnit(unit)
if not UnitExists or not UnitName or not UnitClass or not UnitExists(unit) then return false end
local name=UnitName(unit)
local localizedClass,englishClass=UnitClass(unit)
return learn(name,englishClass or localizedClass)
end
function MCClassColors.Initialize(saved)
known=type(saved)=="table" and saved or {}
if type(LOCALIZED_CLASS_NAMES_MALE)=="table" then
for token,name in pairs(LOCALIZED_CLASS_NAMES_MALE) do
if colors[token] then localized[name]=token end
end
end
if type(LOCALIZED_CLASS_NAMES_FEMALE)=="table" then
for token,name in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do
if colors[token] then localized[name]=token end
end
end
-- Keep the saved table in place so new class discoveries are persisted.
-- Prat cache is an optional bootstrap source, not a dependency.
learnPrat()
local changed=MCClassColors.RefreshUnits()
return known,changed
end
function MCClassColors.Remember(name,class)
return learn(name,class)
end
function MCClassColors.Get(name)
local key=playerKey(name)
if not key then return nil end
if known[key] then return known[key] end
-- An unknown chat sender can be discovered by Prat after our most recent
-- roster event. Look up only this sender to avoid rescanning large caches
-- for every World message.
local prat=Prat_PlayerNames
if type(prat)=="table" then
local value=prat.Classes and prat.Classes[name]
if not value and prat.db and prat.db.profile and prat.db.profile.classes then
value=prat.db.profile.classes[name]
end
if value then learn(name,value) end
end
return known[key]
end
function MCClassColors.RefreshPrat()
return learnPrat()
end
function MCClassColors.Link(name,enabled)
if type(name)~="string" or name=="" then return "" end
local class=enabled and MCClassColors.Get(name)
local hex=(class and colors[class]) or "D4DDE5"
-- Keep native hyperlinks intact: left click whispers; right click uses
-- the client's standard player context menu via SetItemRef.
return "|cff"..hex.."|Hplayer:"..name.."|h["..name.."]|h|r"
end
function MCClassColors.RefreshUnits()
local changed=learnPrat()
if learnUnit("player") then changed=true end
if learnUnit("target") then changed=true end
if learnUnit("mouseover") then changed=true end
local i
for i=1,4 do
if learnUnit("party"..i) then changed=true end
end
local count=GetNumRaidMembers and GetNumRaidMembers() or 0
if count>0 then
for i=1,math.min(count,40) do
if learnUnit("raid"..i) then changed=true end
-- Prat also learns from GetRaidRosterInfo. The roster is useful
-- when the client has not instantiated the matching unit token.
if GetRaidRosterInfo then
local name,_,_,_,class=GetRaidRosterInfo(i)
if learn(name,class) then changed=true end
end
end
end
return changed
end
function MCClassColors.RefreshGuild()
if not GetNumGuildMembers or not GetGuildRosterInfo then return false end
local changed=false
local count=math.min(GetNumGuildMembers() or 0,1000)
local i
for i=1,count do
-- 1.12: name, rank, rankIndex, level, class (localized), ...
local name,_,_,_,class=GetGuildRosterInfo(i)
if learn(name,class) then changed=true end
end
return changed
end
function MCClassColors.RefreshFriends()
if not GetNumFriends or not GetFriendInfo then return false end
local changed=false
local count=math.min(GetNumFriends() or 0,200)
local i
for i=1,count do
-- 1.12: name, level, class, area, online
local name,_,class=GetFriendInfo(i)
if learn(name,class) then changed=true end
end
return changed
end
function MCClassColors.RefreshWho()
if not GetNumWhoResults or not GetWhoInfo then return false end
local changed=false
local count=math.min(GetNumWhoResults() or 0,100)
local i
for i=1,count do
-- 1.12: name, guild, level, race, class, zone
local name,_,_,_,class=GetWhoInfo(i)
if learn(name,class) then changed=true end
end
return changed
end
function MCClassColors.Colors()
return colors
end