Files
BlizzNameplatesPlus/modules/classcolors.lua
T
2026-09-04 20:52:41 +02:00

170 lines
4.3 KiB
Lua

BNP = BNP or {}
local fallbackColors = {
WARRIOR = { 0.78, 0.61, 0.43 },
MAGE = { 0.41, 0.80, 0.94 },
ROGUE = { 1.00, 0.96, 0.41 },
DRUID = { 1.00, 0.49, 0.04 },
HUNTER = { 0.67, 0.83, 0.45 },
SHAMAN = { 0.00, 0.44, 0.87 },
PRIEST = { 1.00, 1.00, 1.00 },
WARLOCK = { 0.58, 0.51, 0.79 },
PALADIN = { 0.96, 0.55, 0.73 },
}
local function GetColor(class)
if RAID_CLASS_COLORS and RAID_CLASS_COLORS[class] then
local c = RAID_CLASS_COLORS[class]
return c.r, c.g, c.b
end
local c = fallbackColors[class]
if c then return c[1], c[2], c[3] end
end
local function Enabled()
if BNP.AreClassColorsEnabled then return BNP:AreClassColorsEnabled() end
return not BNP_DB or BNP_DB.classColors ~= false
end
local function ClearClassCache(plate)
if not plate then return end
plate.BNPClassColorApplied = nil
plate.BNPClassColorToken = nil
plate.BNPClassGUID = nil
plate.BNPClassR = nil
plate.BNPClassG = nil
plate.BNPClassB = nil
end
local function ResolvePlateUnit(plate)
if not plate or not plate.GetName then return nil, nil end
local token = plate:GetName(1)
if not token or not UnitExists(token) then
return token, nil
end
local exists, guid = UnitExists(token)
if exists then
return token, guid
end
return token, nil
end
local function ApplyClassColor(plate)
if not Enabled() then
ClearClassCache(plate)
return false
end
if not plate or not plate.healthbar then return false end
local token, guid = ResolvePlateUnit(plate)
-- BNP only owns PLAYER class colors.
-- NPC/neutral/friendly-NPC colors stay completely under Blizzard control.
if not token or not guid or not UnitIsPlayer(token) then
ClearClassCache(plate)
return false
end
local _, class = UnitClass(token)
local r, g, b = GetColor(class)
if not r then
ClearClassCache(plate)
return false
end
plate.BNPClassColorApplied = true
plate.BNPClassColorToken = token
plate.BNPClassGUID = guid
plate.BNPClassR = r
plate.BNPClassG = g
plate.BNPClassB = b
plate.healthbar:SetStatusBarColor(r, g, b)
return true
end
BNP.ApplyClassColor = ApplyClassColor
local function EnforceClassColor(plate)
if not Enabled() then return end
if not plate or not plate.healthbar or not plate.BNPClassGUID then return end
local token, guid = ResolvePlateUnit(plate)
-- Never enforce a cached color after Blizzard recycled the frame.
if not token or not guid or guid ~= plate.BNPClassGUID or not UnitIsPlayer(token) then
ClearClassCache(plate)
return
end
local r, g, b = plate.healthbar:GetStatusBarColor()
if math.abs(r - plate.BNPClassR) > 0.01
or math.abs(g - plate.BNPClassG) > 0.01
or math.abs(b - plate.BNPClassB) > 0.01 then
plate.healthbar:SetStatusBarColor(
plate.BNPClassR,
plate.BNPClassG,
plate.BNPClassB
)
end
end
if BNP.libnameplate then
table.insert(BNP.libnameplate.OnInit, function(plate)
local current = plate or this
if not current then return end
ClearClassCache(current)
ApplyClassColor(current)
local bar = current.healthbar
if bar and not current.BNPClassColorHooked then
local oldValueChanged = bar:GetScript("OnValueChanged")
bar:SetScript("OnValueChanged", function()
if oldValueChanged then oldValueChanged() end
EnforceClassColor(current)
end)
current.BNPClassColorHooked = true
end
end)
table.insert(BNP.libnameplate.OnShow, function(plate)
local current = plate or this
if not current then return end
ClearClassCache(current)
ApplyClassColor(current)
end)
end
-- Blizzard may rewrite player colors during combat/threat updates.
-- Re-apply only while the plate still resolves to the SAME player GUID.
-- If a recycled frame now represents an NPC/neutral unit, drop the cache
-- immediately and never touch its Blizzard color.
local elapsed = 0
local updater = CreateFrame("Frame")
updater:SetScript("OnUpdate", function()
elapsed = elapsed + arg1
if elapsed < 0.10 then return end
elapsed = 0
if not Enabled() then return end
local plate
for plate in pairs(BNP.plates) do
if plate:IsShown() and plate.healthbar then
local token, guid = ResolvePlateUnit(plate)
if plate.BNPClassGUID then
EnforceClassColor(plate)
elseif token and guid and UnitIsPlayer(token) then
ApplyClassColor(plate)
end
end
end
end)