Files
BlizzNameplatesPlus/modules/fullalpha.lua
T
2026-08-19 00:01:17 +02:00

325 lines
8.9 KiB
Lua

BNP = BNP or {}
local NON_TARGET_ALPHA = 0.55
local function GetPlateGUID(plate)
if not plate or not plate.GetName then return nil end
local token = plate:GetName(1)
if not token then return nil end
local exists, guid = UnitExists(token)
if exists and guid then return guid end
return token
end
local function GetTargetGUID()
local exists, guid = UnitExists("target")
if exists and guid then return guid end
return nil
end
local function IsForeignTagged(plate)
if not plate or not plate.GetName then return false end
local token = plate:GetName(1)
if not token then return false end
local exists = UnitExists(token)
if not exists then return false end
if UnitCanAttack and not UnitCanAttack("player", token) then
return false
end
if not UnitIsTapped or not UnitIsTapped(token) then
return false
end
if UnitIsTappedByPlayer and UnitIsTappedByPlayer(token) then
return false
end
return true
end
local function DesiredAlpha(plate)
-- No selected target: keep all nameplates fully visible.
local targetGUID = GetTargetGUID()
if not targetGUID then return 1 end
-- Current target always stays fully visible.
local plateGUID = GetPlateGUID(plate)
if plateGUID and plateGUID == targetGUID then
return 1
end
-- Only non-target plates use the configured alpha.
if BNP.GetNonTargetAlpha then
return BNP:GetNonTargetAlpha()
end
return 1
end
local function SetLevelSafe(frame, level)
if frame and frame.SetFrameLevel and level then
if frame:GetFrameLevel() ~= level then
frame:SetFrameLevel(level)
end
end
end
local function ApplyTargetFrameLevel(plate)
if not plate or not plate:IsShown() then return end
-- IMPORTANT:
-- Never change the FrameStrata of projected Vanilla nameplates.
-- Their native client/world layer keeps them behind Blizzard UI frames.
-- Target Plate on Top is therefore implemented only with FrameLevel.
if plate.BNPBaseFrameLevel == nil then
plate.BNPBaseFrameLevel = plate:GetFrameLevel() or 0
end
local wrapper = plate.BNPScaleWrapper
if wrapper and plate.BNPBaseWrapperLevel == nil then
plate.BNPBaseWrapperLevel = wrapper:GetFrameLevel() or plate.BNPBaseFrameLevel
end
local target = false
if BNP.IsTargetOnTopEnabled and BNP:IsTargetOnTopEnabled() then
local targetGUID = GetTargetGUID()
local plateGUID = GetPlateGUID(plate)
target = targetGUID and plateGUID and targetGUID == plateGUID
end
local plateLevel = plate.BNPBaseFrameLevel
local wrapperLevel = plate.BNPBaseWrapperLevel or plateLevel
if target then
-- Raise the target only relative to other nameplates while preserving the
-- native projected-nameplate strata beneath the Blizzard interface.
plateLevel = plateLevel + 50
wrapperLevel = wrapperLevel + 50
end
SetLevelSafe(plate, plateLevel)
if wrapper then
SetLevelSafe(wrapper, wrapperLevel)
end
end
local function ApplyForeignTagVisual(plate)
if not plate or not plate:IsShown() then return end
local bar = plate.healthbar
if not bar or not bar.SetStatusBarColor then return end
local foreign = IsForeignTagged(plate)
if foreign then
if not plate.BNPForeignTagGrey then
local r, g, b, a = bar:GetStatusBarColor()
plate.BNPForeignTagOldR = r
plate.BNPForeignTagOldG = g
plate.BNPForeignTagOldB = b
plate.BNPForeignTagOldA = a
plate.BNPForeignTagGrey = true
end
-- Neutral grey: visually distinct from Target Focus transparency.
bar:SetStatusBarColor(0.45, 0.45, 0.45, plate.BNPForeignTagOldA or 1)
elseif plate.BNPForeignTagGrey then
-- Restore the color that BNP/Shagu/class-color logic had before the mob
-- became foreign-tagged. Clear state so future color changes can be learned.
bar:SetStatusBarColor(
plate.BNPForeignTagOldR or 1,
plate.BNPForeignTagOldG or 0,
plate.BNPForeignTagOldB or 0,
plate.BNPForeignTagOldA or 1
)
plate.BNPForeignTagGrey = nil
plate.BNPForeignTagOldR = nil
plate.BNPForeignTagOldG = nil
plate.BNPForeignTagOldB = nil
plate.BNPForeignTagOldA = nil
end
end
local function GetGlowVisualParent(plate)
if not plate then return nil end
local anchor = plate.healthbar or plate
local visualParent = plate.BNPScaleWrapper
if not visualParent and anchor and anchor.GetParent then
visualParent = anchor:GetParent()
end
return visualParent or plate
end
local function KeepShaguGlowLayering(plate)
if not plate then return end
local anchor = plate.healthbar
local visualParent = GetGlowVisualParent(plate)
if not anchor or not visualParent then return end
-- ShaguPlates creates its health StatusBar at FrameLevel 4 specifically
-- "to keep above glow". Reproduce that relationship relative to BNP's
-- visual wrapper, including when Target Plate on Top changes its level.
if anchor.SetFrameLevel and visualParent.GetFrameLevel then
local wanted = (visualParent:GetFrameLevel() or 0) + 4
if anchor:GetFrameLevel() ~= wanted then
anchor:SetFrameLevel(wanted)
end
end
end
local function EnsureTargetGlow(plate)
if not plate then return nil end
if plate.BNPTargetGlow then return plate.BNPTargetGlow end
local anchor = plate.healthbar or plate
local visualParent = GetGlowVisualParent(plate)
if not anchor or not visualParent then return nil end
-- Direct port of ShaguPlates' target glow:
-- nameplate.glow = nameplate:CreateTexture(nil, "BACKGROUND")
-- glow anchored to health CENTER
-- width = health width + 60
-- height = health height + 30
--
-- BNP's only intentional visual change is +3 px on X.
local glow = visualParent:CreateTexture(nil, "BACKGROUND")
glow:SetTexture("Interface\\AddOns\\BlizzNameplatesPlus\\media\\shagu_target_glow.tga")
glow:SetPoint("CENTER", anchor, "CENTER", 3, 0)
local width = anchor.GetWidth and anchor:GetWidth() or 120
local height = anchor.GetHeight and anchor:GetHeight() or 8
glow:SetWidth(width + 60)
glow:SetHeight(height + 30)
local r, g, b = 1, 1, 1
if BNP.GetTargetGlowColor then
r, g, b = BNP:GetTargetGlowColor()
end
glow:SetVertexColor(r, g, b, 1)
glow:Hide()
plate.BNPTargetGlow = glow
KeepShaguGlowLayering(plate)
return glow
end
local function ApplyTargetGlow(plate)
if not plate or not plate:IsShown() then return end
local glow = EnsureTargetGlow(plate)
if not glow then return end
local enabled = BNP.IsTargetFocusEnabled and BNP:IsTargetFocusEnabled()
if not enabled then
glow:Hide()
return
end
local targetGUID = GetTargetGUID()
local plateGUID = GetPlateGUID(plate)
if targetGUID and plateGUID and targetGUID == plateGUID then
local anchor = plate.healthbar or plate
local width = anchor.GetWidth and anchor:GetWidth() or 120
local height = anchor.GetHeight and anchor:GetHeight() or 8
KeepShaguGlowLayering(plate)
glow:ClearAllPoints()
glow:SetPoint("CENTER", anchor, "CENTER", 3, 0)
glow:SetWidth(width + 60)
glow:SetHeight(height + 30)
if BNP.GetTargetGlowColor then
local r, g, b = BNP:GetTargetGlowColor()
glow:SetVertexColor(r, g, b, 1)
end
glow:SetAlpha(1)
glow:Show()
else
glow:Hide()
end
end
local function ApplyTargetAlpha(plate)
if not plate or not plate:IsShown() then return end
local wanted = DesiredAlpha(plate)
if plate:GetAlpha() ~= wanted then
plate:SetAlpha(wanted)
end
end
local function InstallAlphaGuard(plate)
plate = plate or this
if not plate or plate.BNPFullAlphaGuard then return end
local oldOnUpdate = plate:GetScript("OnUpdate")
plate:SetScript("OnUpdate", function()
if oldOnUpdate then oldOnUpdate() end
local current = this or plate
-- Apply the optional Y-offset after Blizzard has had a chance to update
-- the projected nameplate for this frame. This uses the OnUpdate BNP
-- already needs for alpha/glow/target-level handling.
if BNP.MaintainNameplateYOffset then
BNP:MaintainNameplateYOffset(current)
end
ApplyTargetAlpha(current)
ApplyTargetGlow(current)
ApplyForeignTagVisual(current)
ApplyTargetFrameLevel(current)
end)
plate.BNPFullAlphaGuard = true
ApplyTargetAlpha(plate)
end
if BNP.libnameplate then
table.insert(BNP.libnameplate.OnInit, function(plate)
InstallAlphaGuard(plate or this)
end)
table.insert(BNP.libnameplate.OnShow, function(plate)
local current = plate or this
if not current then return end
InstallAlphaGuard(current)
ApplyTargetAlpha(current)
ApplyTargetGlow(current)
ApplyForeignTagVisual(current)
ApplyTargetFrameLevel(current)
end)
end
function BNP:RefreshTargetFocus()
local plate
for plate in pairs(self.plates or {}) do
ApplyTargetAlpha(plate)
ApplyTargetGlow(plate)
ApplyForeignTagVisual(plate)
end
end
function BNP:RefreshNonTargetAlpha()
local plate
for plate in pairs(self.plates or {}) do
ApplyTargetAlpha(plate)
end
end
function BNP:RefreshTargetOnTop()
local plate
for plate in pairs(self.plates or {}) do
ApplyTargetFrameLevel(plate)
end
end