From fe5b3b135b19858d85d4a37d25782436dcb346b7 Mon Sep 17 00:00:00 2001 From: roby-brok Date: Fri, 21 Aug 2026 10:43:11 +0100 Subject: [PATCH] nameplates: use true difficulty colours for level text The level string was brightened by +0.3 on all three channels before display, in the levelFromDB path and again in the OnUpdate colour sync. A flat offset desaturates toward white and costs the high tiers most, because their green/blue channels start near zero: verydifficult 1.00/0.50/0.25 becomes 1.00/0.80/0.55 and reads as yellow, impossible 1.00/0.10/0.10 becomes 1.00/0.40/0.40 and reads as orange. Orange and yellow ended up 0.2 apart on a single channel, so a mob 3-4 levels above the player showed yellow and a skull-range mob showed orange. Both offsets dropped. Ownership of the colour is now explicit through cache.levelfromdb so the two writers no longer race: the sync block stands down on ?? plates, and the DB path clears cache.levelcolor so the sync re-asserts cleanly once the level resolves. That also fixes a stale cache - nameplate.cache is built once at plate creation and survives pool reuse, so a recycled plate could keep the previous unit's colour. Deleting the sync block instead would be wrong: it is the only thing that colours the level on non-?? plates, and plate.level is created with no colour at all. Reported by Iden via Discord. (cherry picked from commit eaa9beac51953d2a959c67d5ff5bc50273a919c3) (cherry picked from commit 3fdb3b23136b260d111509e24e6d7b0d0b9b1b33) --- modules/nameplates.lua | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/modules/nameplates.lua b/modules/nameplates.lua index 3dee7d30..e8c29462 100644 --- a/modules/nameplates.lua +++ b/modules/nameplates.lua @@ -1154,12 +1154,21 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE") plate.level:SetText(string.format("%s%s", level, (elitestrings[elite] or ""))) end - -- Set level color from GetDifficultyColor when using DB level + -- Set level color from GetDifficultyColor when using DB level. + -- No brightening here: adding a flat offset to all three channels + -- desaturates every tier toward white and collapses the boundaries + -- (orange reads as yellow, red reads as orange). Use Blizzard's values. + -- Clearing cache.levelcolor forces the sync block in OnUpdate to + -- re-colour once the ?? resolves and it takes ownership again. if levelFromDB and type(level) == "number" then local color = GetDifficultyColor(level) - plate.level:SetTextColor(color.r + 0.3, color.g + 0.3, color.b + 0.3, 1) + plate.level:SetTextColor(color.r, color.g, color.b, 1) + plate.cache.levelcolor = nil end + -- remember who owns the level colour so the two writers cannot fight + plate.cache.levelfromdb = levelFromDB or nil + if guild and C.nameplates.showguildname == "1" then plate.guild:SetText(guild) if guild == myGuild then @@ -1541,13 +1550,17 @@ nameplates:RegisterEvent("PLAYER_GUILD_UPDATE") update = true end - -- trigger update when level color changed - local r, g, b = original.level:GetTextColor() - r, g, b = r + .3, g + .3, b + .3 - if r + g + b ~= nameplate.cache.levelcolor then - nameplate.cache.levelcolor = r + g + b - nameplate.level:SetTextColor(r,g,b,1) - update = true + -- trigger update when level color changed. Skipped while the level came + -- from the database (?? plates), where OnDataChanged owns the colour -- + -- otherwise both writers race and cache.levelcolor goes stale, which + -- leaves a recycled plate wearing the previous unit's colour. + if not nameplate.cache.levelfromdb then + local r, g, b = original.level:GetTextColor() + if r + g + b ~= nameplate.cache.levelcolor then + nameplate.cache.levelcolor = r + g + b + nameplate.level:SetTextColor(r,g,b,1) + update = true + end end -- use timer based updates