Aura Designer: the Power Infusion Helper - #253
Open
Maelareth wants to merge 5 commits into
Open
Conversation
added 5 commits
August 27, 2026 11:09
…, both container lanes Adds the machinery that lets a feature darken its own aura displays on a switch - built for the Power Infusion Helper (following PR) but written as engine capability. The chokepoint: every engine write of candidate filters funnels through one of two lanes. Group/overlay/row containers pass recordCandidateFilters, which substitutes a populated match-nothing map when the config carries the ownership mark and the gate is shut (or the unit's role is excluded). Stored config is never touched: a rebuild produces something already gated rather than something corrected afterwards, which removes the re-assert race a config-swapping design would carry against every future rebuild path. The slot lane: placed indicators (AcquireSlot) never passed that funnel - their map went straight from config into the engine at six sites, so a gated placed indicator was gated when it fell back to the per-indicator container (in combat) and ungated when the slot path served it. SlotHandle:_cf() derives the same substitution at read time; routed through it are the create-time declare, the tuning push, the cine and death latch re-parses, the recovery re-push, and the combat-exit replay. The one deliberate exception is the identity-gate vulnerability recompute, which must see the real selection or gated slots would leave the cinematic-latch population and return from a cutscene fail-open. The accessor is nil-faithful: never nil for a real selection (the recovery edge burns once and treats nil as nothing-to-repair), never a value for a nil one. Ownership is config.dfGate, stamped by whoever builds a config - one stampGate helper at every call site so a missed site reads as an absent line in a known list, plus self-stamps in the builders that already hold the effect config. A gateOwns predicate centralises which marks the gate owns. An earlier design carried a synthetic spell id in real filter data; rejected because profiles travel and get decoded, the resolved maps are cached and shared between consumers, and debuff groups carry no config-wide candidate set to mark. The broadcast walks both registries narrowed to owned entries - the native setters have no equality guard, so an unnarrowed walk would re-parse every container in the addon per flip. In lockdown the slot lane defers through the standard regen replay. Role exclusion resolves per unit at the same chokepoint (player's own role from spec, others from the group, failing open on NONE), with an exported predicate so non-container consumers (sound) can give the same answer.
A priest-only recipe in the Aura Designer, added from the Other Buffs tab. One click marks the group members worth infusing; everything it shows goes dark while the player's own Power Infusion is on cooldown (with a switch to keep it always on), so it only speaks up when they can act on it. Three signals, each an ordinary frame-level effect the user can move between Border, Health Bar, Background, the two text colours, a placed Icon or Square, or None: - Big cooldown: a curated offensive-cooldown list (plus four offensive racials), others-only so a group member's own press lights their frame. - Big cooldown with a trinket or potion: the same list AND an amplifier (combat potions / on-use trinkets, opt-in ticks) via a two-group condition chain - the one signal that judges a combination, so the one that can only be a colour. - Already has active Power Infusion: marks where the buff went. Its caster rule is inverted (PI on a teammate is always the priest's own cast) and it is exempt from the gate - its subject is created by the gate's own trigger, so gated it could never show. Both were field-found: the signal had never rendered anywhere until they were fixed. Icons: each signal can also render as a Filter Group - one icon per matching aura, the aura's own artwork. Cooldowns and amplifiers share a row (others-only); the infused icon is its own one-icon group with the opposite caster rule. State derives from the groups' own selections, so hand-editing them on the Layout Groups tab and the panel ticks can never disagree. The gate: cast-driven shut (the only unambiguous "it just went down"), flag- driven reopen with an unreadable state resolved from charges, a 0.5s poll only while dark (nothing fires when a cooldown quietly expires), and a diagnostic at /df debug pi showing intent, the chokepoint's answer, per-frame sound registrations and live gated containers. Events register only while a helper exists, so non-priests pay nothing. Sound: per-unit, class-narrowed registrations riding the gate's edges plus roster changes (debounced) - never for the player's own unit, and never for a role the exclusions hide, so a cue cannot fire for a unit nothing marks. Role exclusion (tanks and healers by default, untickable) resolves at the container chokepoint per unit. Settings live on the helper, not per effect: one copy of the roles, the amplifiers, the gate switch and the sound, applied by the resident half on login, profile switch, and every panel change - the addon stays correct with the settings panel never opened. Removing the helper removes everything it built; the shared spell lists are only deleted when no helper mark remains in either mode. Field-verified across two group sessions and extensive solo rounds: every signal, every surface, the cold start, the profile lifecycle, mid-combat deferred builds arriving gated, and the leak check. Depends on the candidate-filter gate machinery (previous PR): this is the feature that stamps config.dfGate.
- The gate broadcast skips parked slots: a parked slot renders nothing, so pushing candidates at it is pure work, and it stays in the registry by necessity because Restore has to find it again. Restore now re-pushes candidates through the accessor, so a gate edge that flipped while the slot was parked is picked up on un-park rather than lost. - The container debug dump reports the raw selection instead of the gated one. It read through the gating accessor, so a gated row logged the dead match-nothing placeholder rather than the user's real filter - on the one diagnostic line most likely to be read while debugging that exact gate. - The gate's combat-exit backstop registers its five events only while a consumer exists, matching the pattern its sibling watcher already used. Driven by a single "does a consumer exist" test so the two registrations cannot disagree.
…ive more - BLOCKER: the signal's display name was written onto the effect config, which lives in the profile - a translated string turned into saved data. Built on an English client and switched to German, the stored row name stays English while the surface dropdown resolves live and shows German. The mark is the stored truth; the label derives from it at render, through one exported resolver so the panel and the effects list cannot disagree. Placed rows gain the same derivation, which they never had. - The secret guard was defeated by its own evaluation order: `and` runs left to right, so the nil comparison ran before the check meant to prevent it, and comparing against a sealed value is what throws. - Refusals reach the debug log; they returned a reason nothing read, so a failure looked exactly like a dead control. - The surface dropdown greys in place instead of vanishing - it belongs to a feature toggle. The Trinkets and Potions group stays hidden, with its existing rationale. - Unticking the last signal re-derives the way Remove does, and "does a helper exist" is now one question answered from the marks - the same derivation the panel uses. It was two: the engine counted a recorded list id that outlives the signals, so emptying the helper left its events registered and its sound armed while the panel correctly showed it gone. - The Filter Designer button uses the shared disabled treatment, and the changelog entry is trimmed to four sentences.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The Power Infusion Helper: a priest-only recipe in the Aura Designer (Other Buffs tab). One click marks the group members worth infusing; everything it shows goes dark while the player's own Power Infusion is on cooldown, with a switch to keep it always on. CHANGELOG entry included.
Three signals, each an ordinary frame-level effect movable between the five colour surfaces, a placed Icon or Square, or None — plus per-signal icon rows (Filter Groups showing one icon per matching aura). Sound rides the gate's edges and roster changes, per-unit and class-narrowed, never for the player's own unit and never for an excluded role. Settings live once on the helper and are applied by the resident half on login, profile switch and every panel change — correct with the settings panel never opened.
Depends on #252 (this branch stacks on it; review the second commit only — the first is #252 verbatim). This is the feature that stamps
config.dfGate.⚠ One design decision taken on our side, flagged for your eye
The already-infused signal is exempt from the gate (
gateOwnsskips it). Field history: the signal had never rendered anywhere — its caster rule filtered out the priest's own casts (and PI on a teammate is always the priest's own cast), and behind that, casting PI is what starts the cooldown that darkens the helper, so the mark turned on and was hidden in the same instant, structurally. Its caster rule is now inverted and it ignores the gate: the violet shows where the buff went for its duration while everything else stays hidden. The exemption also skips role exclusion — "genuinely has Power Infusion" is true whatever the role. Full reasoning in batch 5 on the thread; if you'd draw the line elsewhere, it's one small isolated change.Testing
Two group sessions (thanks again to Aphoex) plus extensive solo rounds on PTR and retail: every signal on every surface, the strong window's two-condition judgement firing only on both halves, icons-only setups end to end, cold start, profile lifecycle (incl. switch-away teardown of sound registrations), mid-combat deferred builds arriving gated, role exclusion on visuals and sound, rejoiner arming, leak check on removal. The one thing no session can reach is raid-scale cost on the gate edge — flagged for the feature's first raid night. Full history and the open items (15–21) on lab thread
d04fe999.