This runbook covers TODOS.phase-72.72.13.2.4: full gameplay control schemes
for left-hand-only and right-hand-only controller use.
Runtime Surface#
One-handed controls extend the V2Input accessibility profile model:
- profile:
FV2OneHandedInputProfile - side enum:
EV2OneHandedInputSide - scheme row:
FV2OneHandedInputScheme - action mapping row:
FV2OneHandedInputActionMapping - resolved scheme:
FV2ResolvedOneHandedInputScheme - source library:
UV2InputBlueprintLibrary - config asset:
UV2InputConfigAsset - UI scheme:
FV2OneHandedControlSchemeSpec - persistence snapshot:
FV2PlayerSettingsSnapshot - save game:
UV2SaveGame - persistence subsystem:
UV2PersistenceSubsystem - contract:
V2/ue/Content/V2/Input/Accessibility/OneHandedControlSchemes_V2_Contract.json - focused checker:
V2/ue/Tools/check-v2-one-handed-control-schemes.py
Behavior#
Profiles default to Controls.OneHanded.Off. Players can select
Controls.OneHanded.Left or Controls.OneHanded.Right; each enabled scheme
must map all 33 V2 gameplay actions with stable OneHanded.Left.* or
OneHanded.Right.* binding tokens scoped to a single controller hand surface.
The UI keeps the existing Controls row and pause-flow selector, but each visible left/right choice now references the matching input scheme id and advertises full gameplay coverage.
Validation#
The scheme table must include exactly the canonical off, left, and right ids.
The off scheme carries no remapped gameplay actions. Left and right schemes must
each cover every EV2InputActionId, including movement, attacks, defense,
grapple, team, presentation, environment, and ruleset-specific actions. Mapping
slots must match the action catalog and binding tokens must be single-hand
scoped and unique within the scheme.
Persistence#
FV2PlayerSettingsSnapshot stores OneHandedInputProfile with startup flags.
UV2SaveGame::SaveOneHandedInputProfile persists a validated profile per
player, GetStartupOneHandedInputProfile resolves it on startup, and
MarkOneHandedInputAppliedOnStartup records the before-gameplay apply time.
ValidateSave rejects profiles whose account id does not match the save header.
Verification#
Run these checks after changing one-handed control schemes:
python3 V2/ue/Tools/check-v2-one-handed-control-schemes.py
python3 V2/ue/Tools/check-v2-input-module.py
python3 V2/ue/Tools/check-v2-profile-save-game.py
python3 V2/ue/Tools/check-v2-persistence-module.py
python3 V2/ue/Tools/check-v2-accessibility-feature-set.py
python3 V2/ue/Tools/check-v2-ui-module.py
python3 V2/ue/Tools/check-v2-settings-ui.py
python3 V2/ue/Tools/check-v2-pause-practice-flow.py
python3 V2/ue/Tools/check-v2-ci-workflow.py
python3 V2/tools/validate-v2-docs.py
python3 -m py_compile V2/ue/Tools/check-v2-one-handed-control-schemes.py V2/ue/Tools/check-v2-ci-workflow.py
python3 -m json.tool V2/ue/Content/V2/Input/Accessibility/OneHandedControlSchemes_V2_Contract.json
Automation coverage:
V2.Input.ModuleV2.Persistence.ModuleV2.Persistence.ProfileSave.AssetContractV2.UI.ModuleV2.UI.PausePracticeFlow.AssetContract
Horde Gates#
one-handed-input-sourceone-handed-full-gameplay-coverageone-handed-ui-selectionone-handed-per-player-persistenceone-handed-startup-applyone-handed-ci-wired