Add files via upload

This commit is contained in:
Wurmschwanz
2026-10-04 18:28:30 +02:00
committed by GitHub
parent 53788c18f3
commit c4e47573e1
7 changed files with 72 additions and 24 deletions
+1 -1
View File
@@ -1465,7 +1465,7 @@ function BNP:CreateOptions()
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText("Inactive Combat Color", 1, 0.82, 0)
GameTooltip:AddLine("Uses a third color only for enemies in combat that are temporarily unable to attack (fear, sheep, stuns or fleeing). Idle enemies are excluded.", 1, 1, 1, true)
GameTooltip:AddLine("Requires a confirmed CC or fleeing state, even if the enemy still has a target. Losing a target alone does not change the color. Independent of Invert Tank Colors.", 0.8, 0.8, 0.8, true)
GameTooltip:AddLine("Detects active CC and fleeing states. Also treats living enemies in combat at 30% health or less with no target as likely fleeing. Idle enemies and corpses are excluded. Independent of Invert Tank Colors.", 0.8, 0.8, 0.8, true)
GameTooltip:Show()
end)
noTarget:SetScript("OnLeave", function() GameTooltip:Hide() end)
+7 -3
View File
@@ -2340,7 +2340,7 @@ local function CaptureLiveDebuffSnapshot(unit, now)
local auraName, texture, stacks, dtype, duration, expirationTime, source,
isStealable, nameplateShowPersonal, auraSpellID =
BNP._ClassicUnitAuraBySlot(unit, slots[i])
if auraName then
if auraName or (auraSpellID and auraSpellID > 0) then
count = count + 1
local entry = entries[count]
if not entry then
@@ -2937,20 +2937,24 @@ function BNP:CacheTankControlSnapshot(plate, guid, snapshot)
or not self:IsTankModeEnabled() then
plate.BNPTankControlGUID = nil
plate.BNPTankControlled = nil
plate.BNPTankChargeStun = nil
return
end
local controlled = false
local controlled, chargeStun = false, false
local i
for i = 1, snapshot.count do
local entry = snapshot.entries[i]
local def = ResolveGlobalCCDef(entry[4], entry[10])
if def and self.TankDisablingCC and self.TankDisablingCC[def.key] then
controlled = true
break
-- The applied Charge stun can arrive before the combat flag. It is
-- itself evidence of an opening attack; a cast attempt alone is not.
if def.key == "charge_stun" then chargeStun = true; break end
end
end
plate.BNPTankControlGUID = guid
plate.BNPTankControlled = controlled
plate.BNPTankChargeStun = chargeStun
end
-- One initial read when enabling the option on an already visible plate.
+6 -4
View File
@@ -967,14 +967,16 @@ local function InstallAlphaGuard(plate)
-- query inside ApplyForeignTagVisual is already cached to 10 Hz.
ApplyForeignTagVisual(current)
-- Native projection can reset the raid icon anchor on any frame. Correct
-- visible marks before rendering; the Y-offset loop leaves their anchors
-- to raidmarks.lua. This only compares existing geometry, with no unit or
-- aura queries, and skips plates whose native raid icon is hidden.
if BNP.MaintainRaidMarkPosition then BNP:MaintainRaidMarkPosition(current) end
current.BNPVisualGuardElapsed = (current.BNPVisualGuardElapsed or 0) + (arg1 or 0)
if current.BNPVisualGuardElapsed >= 0.05 then
current.BNPVisualGuardElapsed = 0
-- Blizzard and the scale/Y-offset wrapper may restore the native raid icon
-- anchor while the plate is being projected. Reapply the optional custom
-- Raid Mark position on the throttled safety pass.
if BNP.MaintainRaidMarkPosition then BNP:MaintainRaidMarkPosition(current) end
if BNP.MaintainTargetScale then BNP:MaintainTargetScale(current) end
ApplyTargetGlow(current)
ApplyTargetArrows(current)
+10 -1
View File
@@ -47,6 +47,13 @@ function BNP:ApplyRaidMarkPosition(plate)
local point, relativeTo, relativePoint, x, y = GetCustomAnchor(plate, position)
if not point or not relativeTo then return end
-- Keep the native icon with the scaled plate visuals if the client restores
-- its parent. This preserves the same scaling and alpha as the healthbar.
local wrapper = plate.BNPScaleWrapper
if wrapper and icon.GetParent and icon.SetParent and icon:GetParent() ~= wrapper then
icon:SetParent(wrapper)
end
if not PointMatches(icon, point, relativeTo, relativePoint, x, y) then
if not icon.ClearAllPoints or not icon.SetPoint then return end
icon:ClearAllPoints()
@@ -60,7 +67,9 @@ function BNP:MaintainRaidMarkPosition(plate)
if not plate or not plate.IsShown or not plate:IsShown() then return end
local icon = plate.raidicon
if not icon then return end
-- This path runs from the per-frame plate guard. Most plates have no active
-- This path runs after native/offset updates on EVERY rendered frame. A
-- throttled repair leaves the native anchor visible between repairs.
-- Most plates have no active
-- raid mark, so avoid GetPoint/anchor comparisons until Blizzard actually
-- shows the icon. The first visible frame will still be corrected instantly.
if icon.IsShown and not icon:IsShown() then return end
+7 -1
View File
@@ -604,7 +604,13 @@ function BNP:MaintainNameplateYOffset(plate)
local states = wrapper.BNPAnchorStates or {}
local i
for i = 1, table.getn(states) do
RestoreAnchorState(states[i], wrapper)
local state = states[i]
-- Raid marks own their custom Top/Left/Right anchor. Restoring the native
-- anchor here every frame fights raidmarks.lua and makes the icon jump
-- between both positions whenever the nameplate Y offset is enabled.
if state.object ~= plate.raidicon or not self.MaintainRaidMarkPosition then
RestoreAnchorState(state, wrapper)
end
end
ApplyWrapperOffset(plate, wrapper)
+38 -14
View File
@@ -35,27 +35,32 @@ local function HasCachedControl(plate, guid, now)
BNP:PrimeTankControlSnapshot(plate, guid, now)
end
if plate.BNPTankControlGUID == guid and plate.BNPClassicAuraEventDriven then
return plate.BNPTankControlled and true or false
return plate.BNPTankControlled and true or false, plate.BNPTankChargeStun and true or false
end
local cache = BNP.guidAuras and BNP.guidAuras[guid]
local controlled = false
local key, aura
if cache then
for key, aura in pairs(cache) do
if BNP.TankDisablingCC[key] and aura.expires and aura.expires > now then return true end
if BNP.TankDisablingCC[key] and aura.expires and aura.expires > now then
controlled = true
if key == "charge_stun" then return true, true end
end
end
end
cache = BNP.guidLiveCCs and BNP.guidLiveCCs[guid]
if cache then
for key, aura in pairs(cache) do
if BNP.TankDisablingCC[key] and (aura.eventDriven or now - (aura.lastSeen or 0) <= 0.60) then
return true
controlled = true
if key == "charge_stun" and aura.expires and aura.expires > now then return true, true end
end
end
end
return false
return controlled, false
end
local function IsTemporarilyInactive(plate, guid, now)
local function IsTemporarilyInactive(plate, guid, now, targetExists)
-- One optional descriptor read covers combat, stun, confusion and fleeing,
-- including low-health fleeing with a retained target. No tooltip/aura scan.
local flags
@@ -66,13 +71,29 @@ local function IsTemporarilyInactive(plate, guid, now)
local inCombat
if flags then inCombat = HasFlag(flags, 524288)
else inCombat = UnitAffectingCombat and UnitAffectingCombat(guid) end
if not inCombat then return false end
if not inCombat then
-- Do not wait for the combat flag when the actual opening Charge stun
-- is already in the harmful-aura snapshot. Pre-pull sheep/sap stay out.
local controlled, chargeStun = HasCachedControl(plate, guid, now)
return controlled and chargeStun
end
if flags and (HasFlag(flags, 262144) or HasFlag(flags, 4194304) or HasFlag(flags, 8388608)) then
return true
end
-- A missing target alone is not evidence of CC or fleeing. It also occurs
-- during death, pet return and ordinary target switches.
return HasCachedControl(plate, guid, now)
if HasCachedControl(plate, guid, now) then return true end
-- Fleeing to seek assistance can clear the target without a CC aura or a
-- fleeing flag, and GetUnitField is optional (Nampower). Keep this fallback
-- deliberately narrow: in combat, no target, alive, <= 30% HP, not casting.
-- This is a heuristic, not proof of fleeing. No per-frame scan or timer.
if targetExists or not UnitHealth or not UnitHealthMax then return false end
local health = UnitHealth(guid)
if not health or health <= 0 then return false end
local maximum = UnitHealthMax(guid)
if not maximum or maximum <= 0 or health / maximum > 0.30 then return false end
if UnitCastingInfo and UnitCastingInfo(guid) then return false end
if UnitChannelInfo and UnitChannelInfo(guid) then return false end
return true
end
local playerGUID = nil
@@ -99,10 +120,11 @@ local function GetPlateGUID(plate)
end
local function GetTargetGUID(guid)
if not guid then return nil end
if not guid then return nil, false end
local exists, targetGUID = UnitExists(guid .. "target")
if exists then return targetGUID end
return nil
-- An existing target whose GUID is temporarily unavailable is not "none".
if exists then return targetGUID, true end
return nil, false
end
local function GetBar(plate)
@@ -246,9 +268,9 @@ function BNP:UpdateTankModePlate(plate)
local myGUID = GetPlayerGUID()
if not myGUID then return end
local targetGUID = GetTargetGUID(guid)
local targetGUID, targetExists = GetTargetGUID(guid)
local now = thirdColor and GetTime()
if thirdColor and IsTemporarilyInactive(plate, guid, now) then
if thirdColor and IsTemporarilyInactive(plate, guid, now, targetExists) then
local r, g, b = self:GetTankNoTargetColor()
ApplyTankColor(plate, bar, r, g, b)
plate.BNPTankNoTargetActive = true
@@ -298,6 +320,7 @@ function BNP:UpdateTankMode()
for plate in pairs(self.plates or {}) do
plate.BNPTankControlGUID = nil
plate.BNPTankControlled = nil
plate.BNPTankChargeStun = nil
end
end
self:RefreshTankMode()
@@ -339,6 +362,7 @@ function BNP:InstallTankMode()
ClearTankState(current)
current.BNPTankControlGUID = nil
current.BNPTankControlled = nil
current.BNPTankChargeStun = nil
BNP:UpdateTankModePlate(current)
end)
+3
View File
@@ -78,6 +78,9 @@ BNP.WarriorAuras = {
{
key = "charge_stun",
names = { "Charge Stun" },
-- The harmful stun, not the Charge cast (100 / 6178 / 11578).
-- Match even before a localized aura name is available.
spellIDs = { 7922 },
duration = 1,
},
{