acdream/docs/research/2026-08-26-retail-keyboard-routing-audit.md
Erik f6fe0f2a4f
All checks were successful
CI / linux-portable (push) Successful in 3m27s
CI / windows-gate (push) Successful in 6m42s
CI / release (push) Successful in 2m12s
fix(client): restore retail interaction parity
Harden keyboard and camera routing, inventory and vendor interactions, chat/emotes, relog portal flow, and paperdoll rendering. Add retail research, connected gate coverage, and release-gate validation.
2026-08-26 20:45:11 +02:00

115 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Retail keyboard defaults and routing audit — 2026-08-26
## Verdict
The code gate for #446 now covers all 306 user-bindable rows in the installed
Sept-2013 EoR ActionMap. Each row has a distinct `InputAction`, appears enabled
in Configure Keyboard, persists through retail-compatible named `.keymap`
profiles, and reaches
a concrete subsystem consumer. The exact installed-DAT default chord set has
zero exceptions. The remaining gate is a connected visual/behavior pass and a
fresh-process persistence check.
The approved acdream extension is deliberately retained: mouse-wheel chase
zoom may pull back to 40 m. It does not change the retail keyboard defaults or
the keypad camera actions.
## Oracles
- `docs/research/named-retail/retail-default.keymap.txt` and installed
`client_portal.dat` ActionMap DID `0x26000000`: the 306 rows, default chords,
activation types, input contexts, and `ConflictingMaps` relationships.
- Installed MasterInputMaps `0x14000000` and `0x14000002`: non-bindable system
and mouse commands.
- `ClientUISystem::OnAction @0x00564B90`: Escape priority.
- `CInputManager_WIN32::GetNameFromKey_Internal @0x00687800` and
`ControlNameMapper::LoadSemantics`: displayed keyboard/mouse names.
- `ACCmdInterp::InitializeEmoteInputActionHash @0x0058B510`: all 87 emote
action-to-motion mappings.
- `CPlayerSystem::SelectNext @0x0055F9A0`: selection-cycle filtering and
opened-corpse behavior.
## Exact ActionMap coverage
| Retail input map | Rows | Consumer |
|---|---:|---|
| Movement | 14 | Runtime movement owner, including four postures |
| Camera + alternate camera | 22 | Held camera input, presets, alternate-scope modifier, instant mouse look |
| Combat + melee + missile + magic | 32 | Runtime combat attack owner and spellcasting controller, including spell slots 112 |
| Emotes | 87 | Exact retail raw-motion table and Runtime `ExecuteMotion` |
| Item selection | 26 | Selection controller/query and canonical inventory interaction state |
| UI | 42 | Retained panels, screenshot, help/plugin result, logout, and selection commands |
| Chat + chat-entry toggle | 7 | Retained chat entry/reply/command routes |
| Quickslots | 28 | Toolbar use/select/create routes, including slots 1018 |
| Character settings | 48 | Exact `CharacterOptionId` bit toggle through Runtime |
| **Total** | **306** | **306 distinct live identities** |
The low MasterInputMap entries such as bare Escape and raw mouse event
commands are intentionally not Configure Keyboard rows in retail and are not
counted among the 306. Unknown rows from a future DAT can still round-trip in
the compatibility sibling store, but the installed EoR DAT has no such row and
shows no dimmed/store-only keyboard entry.
## Behavior completed
- Defaults are an exact installed-DAT transcription, including bare
`LeftShift`; device, modifier, activation, and scope all match.
- Primary and alternate camera maps remain distinct rebind targets even where
retail reuses an action id. The alternate modifier changes the active camera
scope without aliasing saved bindings.
- Same physical chord may fire each distinct retail action allowed by the
ActionMap. In particular, the authored Alt+1..4 chat/UI and quickslot rows
multicast instead of one silently replacing the other.
- Rebind conflicts use the DAT `ConflictingMaps` table. The shared melee,
missile, and magic key cluster remains legal; true conflicts still prompt.
- Capture accepts keyboard keys, modifier-only bindings, and mouse buttons.
Physical modifier self-bits are normalized, so binding LeftShift does not
accidentally become Shift+LeftShift. Mouse button names use retail's
`DIMOFS_BUTTON0..7` semantics table. Unsupported joystick and left/right
mouse inputs keep the instruction dialog open and re-arm capture.
- Setting the chord already present on the same row is a no-op. New chords use
retail's dense two-slot insertion rule, and conflicts use priority dialogs
with the exact installed-DAT singular/plural and non-bindable text.
- Apply/OK, Revert, Defaults, Cancel, explicit unbinding, schema migration,
and startup persistence are covered. Revert is enabled only while dirty;
OK avoids rewriting an unchanged file.
- Load File and Save As use retail's type-7 menu/type-5 text-entry dialogs,
PFile bracket-text grammar, filename normalization, overwrite/read-only
handling, `Documents\Asheron's Call\*.keymap` directory, selected-profile
preference, startup load, and graceful-shutdown rewrite. The portable JSON
file remains only as an acdream-host-command compatibility mirror.
- Escape follows retail's priority: finish jump charge, release focused UI,
stop movement/repeat attack, cancel target mode, clear selection, then
toggle the authored Gameplay Options page. It never exits player mode or
exposes the orbit/developer camera. Shift+Escape reaches the normal logout
gate.
- Selection cycling applies retail's containment, cloaking, radar, attackable,
fellow, vendor, environment, combat-mode, and opened-corpse rules.
Opened-corpse history lives for the session and retires on object deletion.
- Screenshot, help, and plugin actions are consumed. Missing separately
shipped retail help/plugin surfaces report an honest chat/system result
rather than doing nothing.
## Automated verification
- App: 6,413/6,413 passed.
- Core: 4,713/4,713 passed.
- Runtime: 1,849/1,849 passed.
- UI.Abstractions: 879/879 passed.
- Installed-DAT identity/default conformance and the authored Configure
Keyboard mount pin all 306 rows.
The `.keymap` codec parses the committed real retail file and round-trips all
306 user-bindable identities, including low-bit Shift/Ctrl/Alt/Win modifiers,
DirectInput controls, fixed Escape/system/edit/pointer maps, and the 48
CharacterOption action names. AP-202 is retired. The connected gate could not
be run because no local ACE endpoint was listening on UDP port 9000.
## Connected acceptance gate
Use the installed EoR DATs and the normal owner-gate pak. In Configure
Keyboard, verify that all rows are enabled and that a key, modifier-only chord,
and mouse button can each be rebound. Exercise representative movement,
camera, melee/missile/magic, emote, selection, panel, chat, quickslot, and
character-option actions. Verify conflict prompt, Cancel, Revert, Defaults,
Apply, and OK, then restart the process and confirm the applied bindings remain.