CT6 (Campaign CT slice 6): the resize clamp source is the SHARED gmPanelUI host (0x100005FE in LayoutDesc 0x2100006E), not 0x2100002E's own root and not the Character/Skills slot 0x1000018E either — live probe confirmed the host authors MinWidth=MaxWidth=310 (fixed — no horizontal Resizebar authored), MinHeight=372, MaxHeight=1000, and that the bottom Resizebar (0x10000660) and top Dragbar (0x1000065C) are direct children of the host, not the content parent. Decomp chain: UIElement_Resizebar::StartMouseResizing @0x0046B7E0 calls UIElement::StartResizing(this->GetParent(), ...), stashing drag state on that parent; UIElement::MouseResizeElement @0x00461130 then reads GetAttribute_Int(this, 0x3C..0x3F) off that same element every mouse-move. RetailUiRuntime.MountCharacter now imports the host element and passes it as RetailWindowFrame.Options.DatConstraintSource, matching the existing MountSideVitals pattern. CharacterStatController.RebuildActiveList now wraps BOTH the Attributes and Skills tabs' rows in the same UiScrollablePanel viewport (previously only Skills got one; Attributes rows had no clipping/scrolling and the shared scrollbar was force-hidden — owner report item 2). The shared scrollbar is now always bound + visible; UiScrollbar's own IsPresentationVisible/IsModelDisabled already draw the correct full-track "disabled" thumb when content fits. This surfaced and fixed a real #372/#412-class anchor-baseline bug: the viewport's Left|Top|Bottom anchor was capturing its baseline margins lazily on its own first ApplyAnchor call, which happens AFTER the ListBox has already grown from its raw DAT height to its mounted height, permanently capping the viewport short on every later resize. Fixed with an eager CaptureCurrentAnchorBaseline() call, mirroring UiTemplateListBox .Viewport's own lazy getter. CharacterTitlesController.Bind gained the same defensive Anchors = Left|Top|Bottom fallback for the Titles ListBox that CharacterStatController already had (a no-op on the real DAT — both the Titles page and its ListBox already carry a real authored LayoutPolicy that stretches correctly). Standardization audit: UiElement.MinWidth/MinHeight/MaxWidth/MaxHeight, set once at RetailWindowFrame.Mount, are the ONLY clamp fields — read identically by interactive drag, RetailWindowManager.ResizeTo, and RetailWindowLayoutPersistence's restore clamp. No gaps found; no register row (every number is a live-probed authored DAT value or a structural correctness fix, nothing inferred). Tests: CharacterStatControllerTests .CharacterWindow_ResizesYWithinAuthoredHostClamp_AndReflowsListAndScrollbar, CharacterTitlesControllerTests .TitlesList_ReflowsWithWindowResize_AndScrollbarOverflowFlips, RetailWindowFrameTests .NineSlice_ChatShapedConstraints_ClampProgrammaticResizeAtAuthoredBounds (shared-mechanism regression pin), CharacterPanelLiveDatTests .PanelHost_AuthorsFixedWidthAndBottomOnlyResizeContract (InstalledDat pin). Existing attribute-row tests updated from list.Children to Descendants(list) for the new nested-viewport shape (the pattern skill rows already needed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
143 lines
7.4 KiB
Markdown
143 lines
7.4 KiB
Markdown
# Campaign CT — connected gate script (CT7, user-driven)
|
||
|
||
**Purpose:** live verification of the character-panel parity campaign
|
||
(CT1–CT6) against ACE. Launch: the normal connected launch
|
||
(`ACDREAM_RETAIL_UI=1`, live ACE at `127.0.0.1:9000`,
|
||
`ACDREAM_PAK_PATH=<worktree>\artifacts\owner-gate\acdream-v5.pak`).
|
||
Open the character panel (F9 / toolbar). Retail side-by-side comparison
|
||
is the oracle for every visual item.
|
||
|
||
Useful ACE console helpers: title grants come from quests/admin — check
|
||
`@acecommands` for a title-grant command; `@grantxp` for levels.
|
||
|
||
---
|
||
|
||
## 1. Header identity block (CT4) — Attributes AND Skills tabs
|
||
|
||
1. **Name line**: the plain character name (rankless characters — the
|
||
allegiance rank prefix is a registered deferral, AP-109).
|
||
2. **Heritage line**: "<Gender> <Heritage> <DisplayTitle>" — e.g.
|
||
"Female Aluvian War Mage" when a display title is set; just
|
||
"Female Aluvian" when none. PASS: matches retail's composition and
|
||
spacing exactly; a title beginning with "The" shows unmangled.
|
||
3. **PK line**: "Non-Player Killer" (or "Player Killer" / "Player
|
||
Killer Lite" on a PK/PKL character) in PURE WHITE. PASS: correct
|
||
text + color on BOTH the Attributes and Skills tabs.
|
||
4. **Level number**: pale gold with outline (authored color — compare
|
||
against retail's level display side-by-side; the owner reported ours
|
||
was previously off).
|
||
5. **Luminance pair**: on a sub-200 character, NO luminance caption or
|
||
value renders. (A level ≥ 200 character with MaximumLuminance shows
|
||
"Luminance:" and "<available> / <maximum>" — verify only if such a
|
||
character is available.)
|
||
6. **Live update**: set a display title (see §2) — the heritage line
|
||
updates the moment the server confirms, with no relog and no panel
|
||
re-open.
|
||
|
||
## 2. Titles tab (CT3)
|
||
|
||
1. Click the **Titles** tab. PASS: the page shows "Current Display
|
||
Title:" + the current title (or "Unknown" only when the server's
|
||
title id fails to resolve — normally a real title or the authored
|
||
empty state), the "All Available Titles:" list, and the
|
||
"Set as Display Title" button.
|
||
2. **List content**: every earned title, alphabetically sorted,
|
||
readable rows. With few titles the scrollbar shows retail's
|
||
full-track thumb; with many (if available) the thumb sizes
|
||
proportionally and scrolls.
|
||
3. **Ghost rule**: with NOTHING selected the button is ghosted. Select
|
||
the title that IS the current display title — button stays ghosted.
|
||
Select a DIFFERENT title — button un-ghosts.
|
||
4. **Set round trip**: click Set as Display Title. PASS: the display
|
||
title text updates on the server's confirmation, the selection
|
||
CLEARS (row highlight goes dark — retail behavior), the button
|
||
re-ghosts, and the §1 heritage line updates live.
|
||
5. **Row selection visual**: the selected row highlights with retail's
|
||
row highlight art (full-row background swap), not a synthesized bar.
|
||
|
||
## 3. Attribute/skill rows (CT5)
|
||
|
||
1. **Icon alignment**: row icons sit flush left (20x20 at the row's
|
||
left edge), matching retail — the previous inset/smaller icons are
|
||
gone. Compare a few rows side-by-side against retail.
|
||
2. **Value gutter**: the numbers column ends with a visible margin
|
||
before the panel border (the scrollbar band) — retail's 7px gutter.
|
||
3. **Row height**: rows are retail-height (slightly tighter than
|
||
before); section headers (Trained/Untrained/Unusable) unchanged.
|
||
4. **Selection highlight**: clicking a row highlights with the retail
|
||
full-row art; the spellbook's selection visuals are UNCHANGED
|
||
(regression check — open the spellbook and select a spell).
|
||
5. **Raise buttons / tooltips / footer**: regression sweep — raise ×1
|
||
and ×10 still work with correct ghosting, skill tooltips still show
|
||
formula + description wrapped correctly, the footer numbers update.
|
||
|
||
## 4. Resize + scrollbar (CT6)
|
||
|
||
Ground truth (2026-08-25 live probe against layout `0x2100006E`, host
|
||
`0x100005FE` — `docs/research/2026-08-24-campaign-ct-dat-ground-truth.md`
|
||
§CT6): the resize clamp is authored on the SHARED `gmPanelUI` host, not
|
||
the character content itself. Host authors **MinWidth=MaxWidth=310**
|
||
(fixed width — no horizontal Resizebar) and **MinHeight=372,
|
||
MaxHeight=1000**. With the NineSlice chrome's 10px inset, the MOUNTED
|
||
window's outer bounds are MinHeight≈382px, MaxHeight≈1010px, width
|
||
fixed ≈320px.
|
||
|
||
1. **Grab the bottom edge and drag up (shrink).** PASS: the window
|
||
stops shrinking at its authored floor (≈382px outer / the point where
|
||
further dragging has no visible effect) — it does NOT collapse
|
||
arbitrarily small, and it does NOT refuse to shrink at all (the
|
||
pre-CT6 bug). Retail comparison: drag retail's own Character/Skills
|
||
window to its floor side-by-side; both should bottom out at
|
||
proportionally the same point relative to their starting size.
|
||
2. **Keep dragging down (grow).** PASS: the window keeps growing until
|
||
its authored ceiling (≈1010px outer) — same side-by-side comparison
|
||
against retail's own ceiling.
|
||
3. **Left/right edges do not resize.** Only the bottom edge (and top
|
||
Dragbar for moving, not resizing) responds — matches retail's
|
||
fixed-width authoring (no horizontal Resizebar).
|
||
4. **Scrollbar hand-off, Attributes tab.** At the default window size
|
||
the 9 attribute/vital rows fit without a visible scroll gap (bar
|
||
shows retail's full-track "disabled" thumb — present, not hidden,
|
||
per the 2026-08-24 scrollbar work's contract). Shrink the window
|
||
until the rows overflow: the bar's thumb shrinks proportionally and
|
||
becomes interactive (drag, click-to-page, wheel-scroll all move the
|
||
list). PASS: this is the owner's item 2 fix — previously the
|
||
scrollbar never appeared on Attributes at all.
|
||
5. **Scrollbar hand-off, Skills tab.** Same shrink/overflow check —
|
||
should already have worked pre-CT6; confirm no regression.
|
||
6. **Scrollbar hand-off, Titles tab.** With several earned titles,
|
||
shrink the window until the Titles list (authored 455px, inside the
|
||
575px page) overflows its available space — the list's own scrollbar
|
||
(`0x10000533`) takes over the same way.
|
||
7. **Footer stays bottom-docked.** While shrinking/growing on the
|
||
Attributes/Skills tabs, the footer (raise buttons / selected-stat
|
||
info) stays pinned to the bottom edge — it does not float mid-window
|
||
or get clipped early.
|
||
8. **Grow back restores.** Drag back to the original size: the lists
|
||
return to showing all rows without scrolling (scrollbar reverts to
|
||
the full-track disabled state) and the window returns to its
|
||
original proportions.
|
||
9. Other windows (chat, social) still clamp at their own authored
|
||
minimums — regression check (chat: min 300×100, max 2000×2000 per
|
||
`CharacterPanelLiveDatTests.ChatWindowRoot_AuthorsExplicitSizeConstraints`).
|
||
|
||
## 5. Regression sweep (5 minutes)
|
||
|
||
- Attributes/Skills tab switching unaffected; CA5 behaviors intact
|
||
(raise round trips, live run-speed update on Quickness).
|
||
- Logout/login: titles and display title persist; the header matches
|
||
PlayerDescription's values.
|
||
- Chat window: the CH-round fixes hold (input rails on focus, "Gen"
|
||
caption, button flick, no vibrating text while dragging).
|
||
|
||
---
|
||
|
||
## Report back
|
||
|
||
Per section: PASS/FAIL plus anything odd. The three answers that matter
|
||
most:
|
||
1. §2.4 — does the set-title round trip clear the selection and update
|
||
the header live?
|
||
2. §3.1/§3.2 — do icons and the value gutter now match retail
|
||
side-by-side?
|
||
3. §1.3 — is the PK line present, white, and correct on both tabs?
|