From 0ef914a12f437ec423c3b331ac31307527944b7a Mon Sep 17 00:00:00 2001 From: Krathe Date: Wed, 26 Aug 2026 22:31:03 +0100 Subject: [PATCH 1/4] Aura rows: force and confirm the re-parse on a retarget Field report: a shaman's own Earth Shield stayed on a frame and could not be cleared without a reload. The log's last three entries are buff, debuff and defensive all retargeting party3 -> party2, out of combat, and then nothing at all -- so the stale icon survived a retarget that should have cleared it. NativeBackend:setUnit already does a partition bounce out of combat, which is supposed to make the container drop the previous occupant's parse. The evidence says it does not always land, and a long-lived buff nobody re-casts generates no UNIT_AURA on the new unit, so a missed re-parse has nothing to correct it. The icon then sits there indefinitely, which is exactly the report. Handle:Refresh is the addon-callable re-parse and returns whether a genuine one happened, so this is a fix and an instrument at once: it forces the parse, and a "did NOT happen" line identifies a failed bounce rather than leaving an unexplained icon. Source-confirmed combat-safe, and unreachable in combat anyway since the retarget itself defers to regen. Only fires on an actual unit change, so it costs nothing per pass. --- DandersFrames/Features/Auras.lua | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/DandersFrames/Features/Auras.lua b/DandersFrames/Features/Auras.lua index a45ce454..773db352 100644 --- a/DandersFrames/Features/Auras.lua +++ b/DandersFrames/Features/Auras.lua @@ -2449,6 +2449,33 @@ local function rowTuningSig(cfg) }, "|") end +-- ☠ CONFIRM THE RETARGET ACTUALLY RE-PARSED, AND SAY SO WHEN IT DID NOT. +-- NativeBackend:setUnit already does a partition bounce out of combat, which is SUPPOSED to +-- make the container drop the previous occupant's parse. Field evidence says it does not +-- always land: a shaman's own Earth Shield stayed on a frame after "party3 -> party2", out +-- of combat, with the log showing the three retargets and then nothing at all +-- (2026-08-26 22:14). A buff nobody re-casts generates no UNIT_AURA on the new unit, so a +-- missed re-parse has nothing to correct it and the icon sits there until a reload. +-- +-- Handle:Refresh is the addon-callable re-parse and it RETURNS whether a genuine one +-- happened, so this is a fix and an instrument at once: it forces the parse, and a "did NOT +-- happen" line is the bounce having failed rather than an unexplained icon. +-- ✅ Source-confirmed combat-safe (see the note on Handle:Refresh). No combat gate needed +-- anyway — in combat the retarget itself defers to regen, so this cannot be reached there. +-- ⚠ Cheap: the drives call this only on an ACTUAL unit change, never per pass. +local function confirmRetarget(h, label, unit) + if not (h and h.Refresh) then return end + local ok, reparsed = pcall(h.Refresh, h) + if not ok then + DF:DebugWarn("AURAROW", "%s: retarget re-parse THREW on %s", label, tostring(unit)) + elseif not reparsed then + DF:DebugWarn("AURAROW", "%s: retarget re-parse did NOT happen on %s - the row may " + .. "still be showing the previous occupant", label, tostring(unit)) + else + DF:Debug("AURAROW", "%s: retarget re-parsed on %s", label, tostring(unit)) + end +end + -- Drive the factory buff row for one frame. Creates the container lazily, hides the legacy -- icons (no double row), keeps it on the frame's unit, and applies setting changes. The -- container self-updates from UNIT_AURA, so there is no per-tick render here. @@ -2493,6 +2520,7 @@ function DF:DriveBuffFactory(frame, db) InCombatLockdown() and " (in combat: row hidden until regen)" or "") h:SetUnit(frame.unit) frame.dfBuffFactoryHidden = InCombatLockdown() or nil + if not InCombatLockdown() then confirmRetarget(h, "buff", frame.unit) end elseif frame.dfBuffFactoryHidden and not InCombatLockdown() then DF:Debug("AURAROW", "buff: regen, unhiding row after deferred retarget") frame.dfBuffFactoryHidden = nil @@ -2695,6 +2723,7 @@ function DF:DriveDebuffFactory(frame, db) InCombatLockdown() and " (in combat: row hidden until regen)" or "") h:SetUnit(frame.unit) frame.dfDebuffFactoryHidden = InCombatLockdown() or nil + if not InCombatLockdown() then confirmRetarget(h, "debuff", frame.unit) end elseif frame.dfDebuffFactoryHidden and not InCombatLockdown() then DF:Debug("AURAROW", "debuff: regen, unhiding row after deferred retarget") frame.dfDebuffFactoryHidden = nil @@ -3002,6 +3031,7 @@ function DF:DriveDefensiveFactory(frame, db) InCombatLockdown() and " (in combat: row hidden until regen)" or "") h:SetUnit(frame.unit) frame.dfDefFactoryHidden = InCombatLockdown() or nil + if not InCombatLockdown() then confirmRetarget(h, "defensive", frame.unit) end elseif frame.dfDefFactoryHidden and not InCombatLockdown() then DF:Debug("AURAROW", "defensive: regen, unhiding row after deferred retarget") frame.dfDefFactoryHidden = nil From 7aa7ef329c7cce9904454994aa545c40a394b9ae Mon Sep 17 00:00:00 2001 From: Krathe Date: Wed, 26 Aug 2026 23:46:02 +0100 Subject: [PATCH 2/4] AD indicators: fade the slot anchor at birth, not only on a range edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An indicator stayed at full brightness on a faded frame and nothing ever corrected it. In element-fade mode the slot-owner anchor is the ONLY thing that fades Aura Designer indicators, and the pass that writes it runs on a range EDGE -- but the owner is stood up lazily, on first slot acquisition. An anchor created while the unit is already out of range has missed the only trigger it gets, and UpdateAuraDesignerAppearance skips its whole slot-host block when GetSlotOwnerAlphaHost returns nil: no write, nothing queued, nothing to retry. ⚠ Not a regression, though it looks like one. This area has been fixed three times -- 22086f49 gave the fade a legal target, 2a8507ef stopped the squared fade and retried denied hosts on combat drop, 71163802 hardened the pass against throws and added the restriction-lift retry. All three address a write being ATTEMPTED AND REFUSED. This is the path where it is never attempted, which is why none of them covered it. Diagnosed from the field rather than reasoned: /df debug adalpha showed the pass had run and seen inRange=false, nothing refused, anchor still 1.00 -- and a forced ApplyOORAlpha took it to 0.20 immediately. Writability was never the problem. Applying the appearance at owner creation is idempotent and a no-op in whole-frame mode, where the cascade already covers the anchor. --- DandersFrames/Frames/AuraContainer.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/DandersFrames/Frames/AuraContainer.lua b/DandersFrames/Frames/AuraContainer.lua index 15085fe7..0262cc2d 100644 --- a/DandersFrames/Frames/AuraContainer.lua +++ b/DandersFrames/Frames/AuraContainer.lua @@ -6698,6 +6698,25 @@ local function ensureOwner(frame, unit) owner = { frame = frame, anchor = anchor, container = c, unit = unit, slots = {}, seq = 0 } frame.dfSlotOwner = owner AuraContainer.stats.slotOwners = (AuraContainer.stats.slotOwners or 0) + 1 + + -- ★ SEED THE APPEARANCE AT BIRTH — defensive, not a diagnosis. + -- In element-fade mode this anchor is the only thing that fades slot-backed Aura + -- Designer indicators, the pass that writes it runs on a range EDGE, and the owner is + -- stood up LAZILY on first slot acquisition. An anchor born while its unit is already + -- out of range would therefore start at full alpha with no further edge to correct it; + -- this call closes that ordering hole. Idempotent (the pass recomputes from db + the + -- frame's own range state) and effectively a no-op in whole-frame mode, where the + -- unit-frame cascade covers the anchor anyway. + -- + -- ⚠ HONEST STATUS: this shipped mid-hunt as THE fix for "AD indicators don't fade out + -- of range" (2026-08-26) and it was NOT that bug — the field fault was group + -- containers being absent from ElementAppearance's AD_STORE_KEYS walk entirely, fixed + -- separately. The birth-order hole above is real but was never proven to be biting. + -- Kept because it is one cheap call at a rare event; if it is ever suspected of + -- misbehaving, deleting it outright is safe. + if DF.UpdateAuraDesignerAppearance then + pcall(DF.UpdateAuraDesignerAppearance, DF, frame) + end return owner end From ce93b385c96c80867969239f75d4fa0aad7ff18a Mon Sep 17 00:00:00 2001 From: Krathe Date: Wed, 26 Aug 2026 23:59:01 +0100 Subject: [PATCH 3/4] AD groups fade out of range: the two group stores join the alpha walk Element-mode fade: a layout/filter group's indicators sat at full brightness on a faded frame while a placed indicator next to them faded correctly. Krathe's differential located it -- "my AD single PI is working, it's a group that doesn't fade" -- after four wrong theories from me about the slot-owner anchor path, which was never broken. The Factory keeps one container handle per enabled group in store.fgroups and store.dgroups; its own retarget walk names all eight stores. The alpha walk's AD_STORE_KEYS named six -- groups were absent -- so group containers had NO alpha writer in element mode: the frame is pinned at base there, the cascade that covers them in whole-frame mode never runs, and nothing else touches them. Whole-frame mode working is what proved the containers themselves fade fine. Adding the two keys is the entire fix. Group handles are row handles, so entry.handle.button is nil and the walk's existing callback routes them onto the fade branch -- and base-only in whole-frame mode, where the cascade already fades them, so no squared fade. No competing writer exists on a group wrapper (verified: the Factory's two wrapper-alpha writers are placed indicators, which stamp _dfADBaseAlpha for exactly this composition, and missing badges). If the Factory ever grows a ninth store it goes in BOTH lists -- the comment at the key list says so, naming the retarget walk's location. --- DandersFrames/Features/ElementAppearance.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/DandersFrames/Features/ElementAppearance.lua b/DandersFrames/Features/ElementAppearance.lua index 98eb769f..08b3e390 100644 --- a/DandersFrames/Features/ElementAppearance.lua +++ b/DandersFrames/Features/ElementAppearance.lua @@ -1431,8 +1431,24 @@ end -- regions hangs off — its own anchor frame for a container, dfLevelHost for a -- collapsed slot — so fading it fades the indicator whole. Nil only if host creation -- failed, hence the guard. See SlotHandle:GetAlphaHost. +-- ☠☠ "fgroups"/"dgroups" WERE MISSING FROM THIS LIST, AND THAT WAS THE WHOLE +-- "AD groups don't fade out of range" bug (element mode, 2026-08-26). The Factory's own +-- retarget list names all eight stores; this one named six. Group containers therefore +-- had NO alpha writer at all in element mode — the frame is pinned at base there, so the +-- cascade that covers them in whole-frame mode never runs, and nothing else touches them. +-- Placed indicators kept fading (slot-owner anchor), which made it look like the old +-- anchor fix had regressed. It had not: groups are a different pathway that never had the +-- fade wired. +-- ⚠ Krathe's differential located it — "my AD single PI is working, it's a group that +-- doesn't fade" — after four wrong theories from me about the anchor path. +-- ★ Group handles are ROW handles: entry.handle.button is nil, so the walk's existing +-- callback routes them onto the fade branch (base-only in whole-frame mode, where the +-- cascade already fades them — no squared fade, see [ad_oor_fade_two_layers]). +-- ☠ If the Factory ever grows a ninth store, IT GOES IN BOTH LISTS — this one and the +-- retarget walk at Factory.lua ~5464 — or its containers will silently skip either fades +-- or unit reassignment. local AD_STORE_KEYS = { "healthbar", "background", "border", "placed", - "nametext", "healthtext" } + "nametext", "healthtext", "fgroups", "dgroups" } -- ☠ THE WRITE IS PROTECTED, AND A DENIED HOST IS REMEMBERED. -- GetAlphaHost is supposed to answer with a DF-owned frame, so in principle a tainted From f3453485ec9b7b5ccebbaee7624ceb2cfbf08f77 Mon Sep 17 00:00:00 2001 From: Krathe Date: Thu, 27 Aug 2026 12:24:49 +0100 Subject: [PATCH 4/4] Changelog: AD group indicators fade out of range --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c47d729..5d52e483 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # DandersFrames Changelog +## [Unreleased] + +### Bug Fixes + +* (Aura Designer) Fix layout and filter group indicators staying at full brightness on out-of-range players when element-specific fading is on — placed indicators faded, groups next to them did not. (by Krathe) + ## [5.3.1] ### New Features