fix(chat): round 4 — no user-visible meta text, real /help groups, indicator buttons toggle
Item 3 (#364): every honesty marker is now gone from user-visible /help text. AllegianceOverview/HouseOverview's "[IMPLEMENTED]" tags and trailing "Subcommands NOT marked..." sentences, and Day/Log/Render/Motd's appended "NOT YET IMPLEMENTED in acdream" tails, are removed; the underlying retail text is corrected/completed against the pseudo-C's own pristine consolidated data dumps (Log and Motd had been silently truncated; Render was entirely acdream-authored and is replaced with the real retail usage string). The three PARTIAL /help group topics (channels/chatting/commands) are now COMPLETE verbatim listings: HelpStupidChannelHack's three "vtable slot" operands, previously believed undecodable, are the same pooled/mislabeled-data artifact this campaign has hit before (AP-113's precedent) — reading the function's own disassembly for the push imm32 preceding each constructor call resolves all three directly. messagetypes is now a real ported construction (IsLegalChannel's 14-id whitelist + LogTextTypeToString's name table + the exact join/wrap format) instead of an acdream summary. Register row AP-184 retired. Item 5: the main window's 1/2/3/4 indicator buttons now toggle their floating chat window on click, per the user's retail memory overruling the earlier decomp-only reading. UIElement_Button::HandleButtonClick has its own generic click-driven action dispatch (property 0x12) reaching the same DoVisibilityToggleAction the Alt+1..4 keybinds use; the button fixture confirms this half is genuinely armed, but the floating-window fixture authors no matching listener-registration property, so the generic mechanism has no proven target in the data on hand. Per CLAUDE.md, the user's retail memory is the axiom regardless: ChatWindowController.BindIndicatorClicks wires each indicator's click through the same ToggleFloatingChatWindow chokepoint the keybinds use, as explicit user-directed retail behavior. SetIndicatorOpen stays the sole writer of the Selected mirror so the visual stays consistent through the click round trip. Full reconciliation in docs/research/2026-08-09-chat-retail-window-shell.md §1.4. Campaign plan gets the round-4 findings section; items 1+2 (text-style) are under parallel research, item 4 passed, item 6 deferred to the settings track. Suite: 12,579 passed / 4 skipped / 0 failed (Release, complete solution), up from baseline 12,553/4/0 — net +26 tests, zero regressions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
8b166f3ea2
commit
5b54387b8e
10 changed files with 1129 additions and 239 deletions
|
|
@ -184,19 +184,123 @@ exactly two element ids: `0x1000046f` (max/min, dispatching
|
|||
(`idMessage == 7`, checked against `this->m_pCCS` / a `0x1000000b` attribute
|
||||
read). There is no case, anywhere in that function or its base-class fallback
|
||||
(`ChatInterface::ListenToElementMessage`, called unconditionally at the
|
||||
function's tail), for `0x10000522`–`0x10000525`. **Clicking a chat-window
|
||||
indicator button does NOTHING in retail — reading (a), pure indicator, is
|
||||
correct; reading (b) is refuted.** The `0x24` input-action-property theory
|
||||
in reading (b) does not even apply to a mouse click on the button itself: that
|
||||
property only wires *keyboard* dispatch (`UIElementManager::
|
||||
DoVisibilityToggleAction` in §1.3), not a button's own `UIElement` click
|
||||
message, which routes to its LISTENING PARENT — and that parent's handler has
|
||||
no case for these four ids. acdream ports this exactly: the four indicator
|
||||
buttons (`ChatWindowController._indicatorButtons`) carry no `OnClick` at all;
|
||||
`ChatWindowController.SetIndicatorOpen` is their only writer, called only from
|
||||
`RetailUiRuntime.OnWindowVisibilityChanged` in response to the floating
|
||||
window's own visibility changing (keybind or otherwise) — a pure one-directional
|
||||
mirror, matching retail exactly.
|
||||
function's tail), for `0x10000522`–`0x10000525`. **This citation is still a
|
||||
true statement about `gmMainChatUI::ListenToElementMessage` — see the round-4
|
||||
correction below for why it is the wrong function to have grepped.**
|
||||
|
||||
---
|
||||
|
||||
**ROUND-4 CORRECTION (2026-08-10) — the user's own retail memory ("clicking
|
||||
opens/closes the window") overruled the CONCLUSION above, and re-attacking the
|
||||
question with that as the starting axiom (per CLAUDE.md: the user's retail
|
||||
memory is the axiom, not a hypothesis to be argued down) found the exact
|
||||
mechanism the CH6b pass missed.**
|
||||
|
||||
The CH6b pass's mistake was scope, not accuracy: it proved
|
||||
`gmMainChatUI::ListenToElementMessage` has no click case for these ids, then
|
||||
reasoned "a button's click message… routes to its LISTENING PARENT" and
|
||||
stopped there. **That's wrong — `UIElement_Button` (Type 1, the class every
|
||||
one of these four indicators actually is) overrides its OWN click handling
|
||||
and never asks its parent window first:**
|
||||
|
||||
```
|
||||
UIElement_Button::HandleButtonClick @0x00471E50
|
||||
00471e65 if (UIElement::GetAttribute_Enum(this, 0x12, &actionId)) // reads its OWN property
|
||||
00471e72 if (actionId != 1)
|
||||
00471e95 build an InputEvent(actionId)
|
||||
00471eb2 ICIDM::GetActionMap()… dispatch through the action map
|
||||
```
|
||||
|
||||
Property `0x12` here is the SAME kind of "input action" enum as `0x24` — not
|
||||
the parent-window dispatch §1.4's original text assumed didn't apply to
|
||||
clicks. This IS the generic mechanism a click uses to reach
|
||||
`UIElementManager::DoVisibilityToggleAction @0x0045B660` (§1.3's own citation,
|
||||
previously assumed keybind-only) → `BroadcastElementMessage(target, 0x31,
|
||||
actionId, 0)` for every element registered under that action id via
|
||||
`RegisterElementForInputAction` (§1.3's property-`0x24` registration —
|
||||
confirmed as the ONLY call site of `RegisterElementForInputAction` in the
|
||||
whole binary) → the RECEIVING element's generic base-class handler:
|
||||
|
||||
```
|
||||
UIElement::ListenToElementMessage @0x00462340
|
||||
00462447 case 8: // idMessage - 0x29 == 8, i.e. raw idMessage 0x31
|
||||
0046244f GetAttribute_Enum(this, 0x58, &mode) // reads the RECEIVER's OWN property
|
||||
00462459 if (mode == 1) SetVisible(!currentlyVisible) // toggle
|
||||
0046245c else if (mode == 2) SetVisible(1) // force-show
|
||||
0046245f else if (mode == 3) SetVisible(0) // force-hide
|
||||
```
|
||||
|
||||
Neither `gmMainChatUI`, `gmFloatyChatUI`, nor `ChatInterface` overrides
|
||||
`ListenToElementMessage` for raw idMessage `0x31` (confirmed by reading all
|
||||
three switches directly — none has a case landing on it), so EVERY window
|
||||
falls through to this base-class handler unconditionally. This is a complete,
|
||||
generic, working "click toggles a registered listener's visibility" system —
|
||||
exactly the "authored button behavior" this reconciliation task hypothesized
|
||||
— and it is NOT gated on keyboard input the way the original §1.3 text
|
||||
assumed; `UIElementManager::KeyPressEvent`'s call to `DoVisibilityToggleAction`
|
||||
is simply ONE caller among the several that can reach it (the button's own
|
||||
`HandleButtonClick` is another).
|
||||
|
||||
**What the authored DATA shows, checked directly against the committed
|
||||
fixtures:**
|
||||
|
||||
- `chat_2100006f.json` — all four indicator elements (`0x10000522`-`0x10000525`)
|
||||
DO author an Enum-kind property `0x12` (confirmed by `Kind: 0` = Enum in the
|
||||
fixture's own property dump, matching `LayoutImporter.ConvertProperty`'s
|
||||
`EnumBaseProperty → UiPropertyKind.Enum` mapping exactly), with values
|
||||
`0x10000514`-`0x10000517` in element-id order. This is a real, present,
|
||||
correctly-typed action id — the button-click half of the generic mechanism
|
||||
is genuinely armed.
|
||||
- `chat_floaty_2100005b.json` — the floating chat window's own fixture
|
||||
authors **NO Enum-kind property `0x24` anywhere** (its only hit on property
|
||||
number 36 decimal is `Kind: 4` = Integer, an unrelated attribute — not the
|
||||
registration property) and **no property `0x58` at all**. Since
|
||||
`RegisterElementForInputAction` has exactly one call site in the entire
|
||||
binary (the property-`0x24` handler in `UIElement::Initialize`; no class
|
||||
anywhere calls it directly from code), nothing in the shipped floating chat
|
||||
window LayoutDesc ever registers it as a listener for ANY action id.
|
||||
`DoVisibilityToggleAction` would look up the button's action id, find zero
|
||||
registered listeners, and silently return — the click would fire a real
|
||||
message with no receiver.
|
||||
- The four action-id VALUES (`0x10000514`-`0x10000517`) are also not
|
||||
chat-specific: the identical four numbers, in the identical order, are
|
||||
`gmFriendsUI::PostInit`'s own child-element ids for its Add/Remove/Tell
|
||||
buttons and friends listbox (`UIElement::GetChildRecursive(this,
|
||||
0x10000514)` etc., confirmed by direct read). This is almost certainly a
|
||||
coincidence of Turbine's global per-dat-file asset-id allocator (ids are
|
||||
assigned client-wide, not scoped per panel), not a cross-reference —
|
||||
nothing in `gmFriendsUI` registers for input actions either.
|
||||
|
||||
**Conclusion: the generic UI action system is real, it exists, and the
|
||||
buttons genuinely arm their half of it — but the authored DATA available to
|
||||
us (both committed fixtures, generated from the installed DAT) does not wire
|
||||
a target for it.** This is consistent with, not a refutation of, the original
|
||||
CH6b grep of `gmMainChatUI::ListenToElementMessage` — that citation was
|
||||
looking in the wrong function, but its NEGATIVE RESULT (retail's window-level
|
||||
message handlers never claim these clicks) still holds; the generic
|
||||
mechanism, if it does connect the dots in real retail, does so entirely
|
||||
below the level either grep could see. **Per CLAUDE.md, the user's retail
|
||||
memory is the axiom regardless: acdream now wires each indicator's click to
|
||||
toggle its floating window through the SAME `ToggleFloatingChatWindow`
|
||||
chokepoint the `Alt+1..4` keybinds use
|
||||
(`ChatWindowController.BindIndicatorClicks`, called by `RetailUiRuntime`
|
||||
right after mounting the main chat window) — explicitly as USER-DIRECTED
|
||||
retail behavior, not a claim that the generic-action-system data path has
|
||||
been proven end-to-end.** `SetIndicatorOpen` stays the ONLY writer of the
|
||||
indicator's `Selected` mirror (`UiButton.SuppressSelfToggle` stays `true`);
|
||||
the click drives the real toggle, and the mirror reports the outcome back —
|
||||
so the visual stays consistent through the round trip even though the write
|
||||
is now two-way at the FEATURE level.
|
||||
|
||||
---
|
||||
|
||||
acdream ports this exactly: the four indicator buttons
|
||||
(`ChatWindowController._indicatorButtons`) now carry a real `OnClick`
|
||||
(`ChatWindowController.BindIndicatorClicks`, round 4); the mirror half is
|
||||
unchanged — `ChatWindowController.SetIndicatorOpen` is still the ONLY writer
|
||||
of `Selected`, still called from `RetailUiRuntime.OnWindowVisibilityChanged`
|
||||
in response to the floating window's own visibility changing, regardless of
|
||||
what triggered it (click, keybind, or a restored layout).
|
||||
|
||||
### 1.5 Closing a floaty window from its own title bar
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue