fix: social panel completion batch (user gate 2026-08-13, "fix all")
One user-ordered batch across the FA social panel + world selection.
Every root cause was probe-proven before the fix (new
ProbeSocialClickRouting in SocialPanelLiveMountProbeTests - production
window mount + real UiRoot hit-tests + a synthetic click):
1. STUCK CHECKBOXES (fellowship x4, allegiance x1, "always checked /
can't change any options"): the authored checkboxes carry DAT
ToggleBehavior, so UiButton SELF-FLIPS Selected at MouseUp - the old
handlers read the flipped value and wrote the ORIGINAL back, snapping
every click to where it started (the probe recorded (id, oldValue)).
Fix: SuppressSelfToggle (the CH6a/b mirror discipline) + derive the
next value from the STORE; the per-tick seeding mirrors it back.
2. UNCLICKABLE ROSTER ROWS ("only get the move window cursor"): the row
name text is display-text ClickThrough=true, which the hit-test walk
skips regardless of HandlesClick - the wired OnClick was unreachable.
Fix: UiText.OnClick assignment now clears ClickThrough (central,
documented); the stats text gains the same select handler so most of
the row's width selects the fellow.
3. TRUNCATED EMPTY-STATE ("You do not belong... To create MISSING"):
the authored string resolves COMPLETE (three sentences) but embedded
'\n's rendered as one clipped line. DatWidgetFactory now splits
authored strings into one Line per newline, with the provider still
re-reading DefaultColor live (the state-color contract - caught by
BuildText_AuthoredLineTracksStateFontColor).
4. FELLOW NAMES WHITE (user-directed): the AD-82 invented leader-gold +
selection-blue tints are deleted; names always white (register row
narrowed).
5. ALLEGIANCE HEADER LABELS: bare "0"/"0" -> "Followers: N" / "Rank: [N]"
(user-specified format; the full retail StringInfo composition stays
AD-85's gap), monarch block matching.
6. FRIENDS/SQUELCH LIVE (AD-79 mostly retired): Add friend (name box ->
0x0018, retail clears the box - Request_AddFriend @0x0048D240),
Remove (row-click selection -> 0x0017), Appear Offline (CharacterOption
0x27 via the immediate 0x0005 auto-save, ACE pushes FriendStatusChanged
to your friend-of list), Squelch Character/Account add-by-name
(0x0058 guid0/type AllChannels + 0x0059) and Remove for the selected
row. The wire beneath (builders, WorldSession sends, Runtime commands,
parsers) existed end-to-end since J4.1/FA1 - this is panel wiring only
(docs/research/2026-08-13-social-wire-completion.md, committed here).
Send Tell stays inert (not in the order; AD-79's remainder).
7. WORLD SELF-SELECTION ("clicking my own char should select myself"):
retail has NO self-exclusion (CPhysicsPart::Draw @0x0050D823 arms
every physobj; RecvNotice_SmartBoxObjectFound @0x004E5BAE selects
unconditionally) - the includeSelf gate was an unregistered
divergence, now removed on both the left-click and right-click paths.
Element roles were probe-measured, never guessed (Add 0x10000514 /
Remove 0x10000515 / Send Tell 0x10000516 / Appear Offline 0x1000052C /
name field 0x1000051B; Squelch: field 0x10000540, Remove 0x10000547,
Squelch Character 0x1000054B, Squelch Account 0x1000054C).
Register: AD-79 mostly retired, AD-82 narrowed. Known remainder, filed
not hidden: the fellowship page's authored 600px content vs the 362px
viewport leaves Dismiss/Assign-Leader below the fold until the window is
resized taller (probe-measured; candidate follow-up).
Tests: Checkbox_Click fact rewritten to the mirror contract (both
directions), monarch-followers label updated, includeSelf expectation
updated, probe extended (click routing, synthetic click, action-widget
role dump). App suite 4,976/3 skips.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ec2a7b0cce
commit
72ceddce2e
15 changed files with 1018 additions and 65 deletions
|
|
@ -58,11 +58,11 @@ namespace AcDream.App.UI.Layout;
|
|||
/// <b>Leader marker.</b> Lane A's row-template inventory names no dedicated
|
||||
/// "this fellow is the leader" element (the 8-child row is name / stats /
|
||||
/// three meter+text pairs, nothing else) — retail may simply not mark
|
||||
/// leadership in the row at all. Lacking a decompiled anchor either way,
|
||||
/// this controller tints the leader's name text a distinct gold
|
||||
/// (<see cref="LeaderNameColor"/>) as a minimal, clearly-adaptive visual
|
||||
/// cue rather than inventing a DAT mechanism that was not found — register
|
||||
/// row AD-82.
|
||||
/// leadership in the row at all. The earlier gold leader tint and blue
|
||||
/// selection tint this controller invented for that gap were RETIRED at the
|
||||
/// 2026-08-13 gate by user direction: names render white, always
|
||||
/// (<see cref="MemberNameColor"/>), and selection feedback is the in-game
|
||||
/// selection itself — register row AD-82 updated accordingly.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
|
|
@ -126,18 +126,12 @@ public sealed class SocialFellowshipPageController
|
|||
/// <c>_currNum >= 9</c> (lane B §7.1).</summary>
|
||||
private const int MaxFellowshipSize = 9;
|
||||
|
||||
private static readonly Vector4 LeaderNameColor = new(1f, 0.84f, 0f, 1f);
|
||||
/// <summary>2026-08-13 gate (user-directed): fellow names are WHITE,
|
||||
/// always — the earlier AD-82 leader-gold and selection-blue tints are
|
||||
/// retired (no decompiled anchor ever existed for either); the in-game
|
||||
/// selection ring is the selection feedback.</summary>
|
||||
private static readonly Vector4 MemberNameColor = Vector4.One;
|
||||
|
||||
/// <summary>Fix-round MUST-FIX 4 — the panel-local "this row is selected"
|
||||
/// visual cue (see the class doc's world→panel selection note).
|
||||
/// Same disposition as <see cref="LeaderNameColor"/>: no decompiled
|
||||
/// anchor for a per-row selection sprite/marker was found, so this is a
|
||||
/// minimal, clearly-adaptive tint rather than an invented DAT mechanism
|
||||
/// — register row AD-82. Takes priority over <see cref="LeaderNameColor"/>
|
||||
/// when a row is both the leader and the current selection.</summary>
|
||||
private static readonly Vector4 SelectedNameColor = new(0.45f, 0.85f, 1f, 1f);
|
||||
|
||||
/// <summary>Cached per <see cref="RefreshFellowshipName"/> — only
|
||||
/// reassigned when the fellowship name actually changes (fix-round SF-1,
|
||||
/// the same zero-allocation-while-idle discipline
|
||||
|
|
@ -455,10 +449,19 @@ public sealed class SocialFellowshipPageController
|
|||
if (tooltip is not null)
|
||||
checkbox.TooltipText = tooltip;
|
||||
|
||||
// 2026-08-13 gate fix ("I can't change any options"): these authored
|
||||
// checkboxes carry DAT ToggleBehavior, so the button SELF-FLIPS
|
||||
// Selected at MouseUp — the old `!checkbox.Selected` here then read
|
||||
// the ALREADY-FLIPPED value and wrote the ORIGINAL back, visually
|
||||
// snapping every click to where it started (probe-proven:
|
||||
// ProbeSocialClickRouting recorded (id, oldValue)). Same CH6a/b
|
||||
// mirror discipline as the chat indicators: suppress the blind
|
||||
// self-flip, derive the next value from the STORE, and let the
|
||||
// per-tick seeding mirror the outcome back onto Selected.
|
||||
checkbox.SuppressSelfToggle = true;
|
||||
checkbox.OnClick = () =>
|
||||
{
|
||||
bool next = !checkbox.Selected;
|
||||
checkbox.Selected = next;
|
||||
bool next = !_bindings.CurrentCharacterOption(id);
|
||||
_bindings.SetCharacterOption(id, next);
|
||||
};
|
||||
}
|
||||
|
|
@ -725,6 +728,15 @@ public sealed class SocialFellowshipPageController
|
|||
uint guid = member.Guid;
|
||||
nameText.OnClick = () => SelectFellow(guid);
|
||||
}
|
||||
// 2026-08-13 gate fix ("I only get the move window cursor"):
|
||||
// give the STATS text the same click target so most of the row's
|
||||
// width selects the fellow (UiText.OnClick now clears the
|
||||
// display-text ClickThrough default — see UiText.OnClick's doc).
|
||||
if (widgets.Stats is { } statsText)
|
||||
{
|
||||
uint guid = member.Guid;
|
||||
statsText.OnClick = () => SelectFellow(guid);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (RuntimeFellowMemberSnapshot member in members)
|
||||
|
|
@ -738,13 +750,11 @@ public sealed class SocialFellowshipPageController
|
|||
if (widgets.Name is { } nameText)
|
||||
{
|
||||
string name = member.Name;
|
||||
// MUST-FIX 4 (fix round): selection takes priority over the
|
||||
// leader tint when a row is both — it's the more immediate,
|
||||
// user-driven state (see SelectedNameColor's own doc).
|
||||
Vector4 color = _selectedFellowGuid == member.Guid
|
||||
? SelectedNameColor
|
||||
: snapshot.LeaderGuid == member.Guid ? LeaderNameColor : MemberNameColor;
|
||||
nameText.LinesProvider = () => [new UiText.Line(name, color)];
|
||||
// 2026-08-13 gate (user-directed): fellow names render WHITE,
|
||||
// always — the AD-82 invented leader/selection tints are retired;
|
||||
// selection feedback is the in-game selection itself
|
||||
// (SelectFellow drives the world selection ring).
|
||||
nameText.LinesProvider = () => [new UiText.Line(name, MemberNameColor)];
|
||||
}
|
||||
|
||||
if (widgets.Stats is { } statsText)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue