From 08fe41d2966832472e781112f7cfbe4bbd2e2416 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 19 May 2026 10:18:28 +0000 Subject: [PATCH] add checklists --- docs/checklists/bpc-statemanager.md | 272 ++++++++++++++++++ docs/checklists/clean-slate-refactor.md | 346 +++++++++++++++++++++++ docs/checklists/enhanced-input-system.md | 170 +++++++++++ 3 files changed, 788 insertions(+) create mode 100644 docs/checklists/bpc-statemanager.md create mode 100644 docs/checklists/clean-slate-refactor.md create mode 100644 docs/checklists/enhanced-input-system.md diff --git a/docs/checklists/bpc-statemanager.md b/docs/checklists/bpc-statemanager.md new file mode 100644 index 0000000..9b38157 --- /dev/null +++ b/docs/checklists/bpc-statemanager.md @@ -0,0 +1,272 @@ +# BPC_StateManager — Implementation Checklist + +**Target:** Code Agent (Game Dev mode) +**Architecture Doc:** [`docs/architecture/bpc-statemanager.md`](../architecture/bpc-statemanager.md) +**Parent System:** Player Character (sits alongside BPC_MovementStateSystem, BPC_HealthSystem, etc.) + +--- + +## Pre-Implementation Verification + +- [ ] Read [`docs/architecture/bpc-statemanager.md`](../architecture/bpc-statemanager.md) — Sections 4–7 (Enums, Structs, Variables, Functions) +- [ ] Read [`CONTEXT.md`](../../CONTEXT.md) — Sections "State Management Conventions" and "Animation Notify Contract" +- [ ] Confirm GASP AnimBP (`ABP_GASP`) has variable `OverlayState` (enum), `bIsInAction` (bool), `ActionIntensity` (float 0–1) +- [ ] Confirm `BPC_MovementStateSystem` (11) fires dispatchers `OnMovementModeChanged`, `OnPostureChanged`, `OnSprintStateChanged` +- [ ] Confirm `BPC_HealthSystem` (08) fires dispatcher `OnDeath` with death context +- [ ] Confirm `GI_GameFramework` (04) has `E_GamePhase` enum and fires `OnGamePhaseChanged` + +--- + +## Phase 1 — Enum & Struct Creation (Core/) + +### Step 1.1: Create `E_PlayerActionState` Enum +- [ ] Asset path: `Content/Framework/Core/E_PlayerActionState` +- [ ] 42 values per [Section 4.1](../architecture/bpc-statemanager.md#41-e_playeractionstate--exclusive-action-states) +- [ ] Display names match exactly + +### Step 1.2: Create `E_OverlayState` Enum +- [ ] Asset path: `Content/Framework/Core/E_OverlayState` +- [ ] 18 values per [Section 4.2](../architecture/bpc-statemanager.md#42-e_overlaystate--upper-body-overlay-for-gasp-animbp) +- [ ] Display names match exactly + +### Step 1.3: Create `E_ActionRequestResult` Enum +- [ ] Asset path: `Content/Framework/Core/E_ActionRequestResult` +- [ ] 7 values per [Section 4.3](../architecture/bpc-statemanager.md#43-e_actionrequestresult) + +### Step 1.4: Create Structs +- [ ] `S_StateChangeRequest` — fields per [Section 5.1](../architecture/bpc-statemanager.md#51-s_statechangerequest) +- [ ] `S_StateGatingRule` — fields per [Section 5.2](../architecture/bpc-statemanager.md#52-s_stategatingrule) +- [ ] `S_ActionPermissionResult` — fields per [Section 5.3](../architecture/bpc-statemanager.md#53-s_actionpermissionresult) + +### Step 1.5: Create `DA_StateGatingTable` Data Asset +- [ ] Parent class: `PrimaryDataAsset` +- [ ] Asset path: `Content/Framework/Core/DA_StateGatingTable` +- [ ] Variable: `GatingRules: Array` +- [ ] Populate with [Section 9 gating rules](../architecture/bpc-statemanager.md#9-state-gating-function-table) (25+ rules) + +--- + +## Phase 2 — BPC_StateManager Component Creation + +### Step 2.1: Create Blueprint Component +- [ ] Asset path: `Content/Framework/Player/BPC_StateManager` +- [ ] Parent class: `ActorComponent` +- [ ] Network: Check `bReplicates = true` if multiplayer planned + +### Step 2.2: Add Configuration Variables +Per [Section 6 — Configuration Variables](../architecture/bpc-statemanager.md#6-variables): +- [ ] `GatingRules: Array` — Expose On Spawn +- [ ] `DefaultState: E_PlayerActionState` — default `Idle` +- [ ] `bLogStateTransitions: Boolean` — default `false` +- [ ] `StateTransitionDelay: Float` — default `0.0` +- [ ] `DefaultOverlay: E_OverlayState` — default `Empty` + +### Step 2.3: Add Internal Variables +Per [Section 6 — Internal Variables](../architecture/bpc-statemanager.md#6-variables): +- [ ] `CurrentState: E_PlayerActionState` — default `Idle` +- [ ] `PreviousState: E_PlayerActionState` — default `Idle` +- [ ] `CurrentOverlay: E_OverlayState` — default `Empty` +- [ ] `LastStateChangeTime: Float` +- [ ] `StateHistory: Array` +- [ ] `ForceStack: Array` +- [ ] `bIsTransitioning: Boolean` +- [ ] `PendingRequests: Array` +- [ ] `CachedABPRef: ABP_GASP` (soft object reference) +- [ ] `CurrentActionFlags: Map` + +--- + +## Phase 3 — Event Dispatchers + +Create all 8 dispatchers per [Section 8](../architecture/bpc-statemanager.md#8-event-dispatchers): +- [ ] `OnStateChanged` → `OldState: E_PlayerActionState`, `NewState: E_PlayerActionState` +- [ ] `OnStateChangeRequested` → `Request: S_StateChangeRequest` +- [ ] `OnStateChangeDenied` → `Request: S_StateChangeRequest`, `Result: E_ActionRequestResult`, `Reason: Text` +- [ ] `OnOverlayStateChanged` → `OldOverlay: E_OverlayState`, `NewOverlay: E_OverlayState` +- [ ] `OnActionFlagRegistered` → `Tag: GameplayTag`, `Duration: Float` +- [ ] `OnActionFlagExpired` → `Tag: GameplayTag` +- [ ] `OnForceOverridePushed` → `ForcedState: E_PlayerActionState`, `PoppedState: E_PlayerActionState` +- [ ] `OnForceOverridePopped` → `RestoredState: E_PlayerActionState` + +--- + +## Phase 4 — Core Functions + +### Step 4.1: `BeginPlay` (Override) +Per [Section 7.13](../architecture/bpc-statemanager.md#713-initialize-beginplay-override): +- [ ] Get Owner as Character +- [ ] Cache `ABP_GASP` from character's skeletal mesh `->GetAnimInstance()` +- [ ] Set `CurrentState = DefaultState`, `CurrentOverlay = DefaultOverlay` +- [ ] Load `GatingRules` from `DA_StateGatingTable` if assigned +- [ ] Bind to `GI_GameFramework.OnGamePhaseChanged` +- [ ] Bind to `BPC_HealthSystem.OnDeath` → call `ForceStateChange(Dead, "Death")` + +### Step 4.2: `RequestStateChange` +Per [Section 7.1](../architecture/bpc-statemanager.md#71-requeststatechange): +- [ ] **Priority 100 check:** If `Priority == 100` → bypass gating → go to transition +- [ ] **Transition guard:** If `bIsTransitioning` → queue request → return `Blocked_CurrentState` +- [ ] **Cooldown check:** If `GameTime - LastStateChangeTime < StateTransitionDelay` → return `Blocked_Cooldown` +- [ ] **Dead check:** If `CurrentState == Dead` AND `NewState != Idle` → return `Blocked_Dead` +- [ ] **Gating evaluation:** Iterate `GatingRules` matching `RequesterTag`: + - BlockedStates contains NewState → return `Blocked_CurrentState` with reason + - BlockedGamePhases contains CurrentGamePhase → return `Blocked_GamePhase` + - RequiredTags missing or BlockedTags present → return appropriate result +- [ ] **Transition:** Call `ExecuteStateTransition(NewState)` +- [ ] Return `Permitted` + +### Step 4.3: `ExecuteStateTransition` (Private) +- [ ] Set `bIsTransitioning = true` +- [ ] `PreviousState = CurrentState` +- [ ] `CurrentState = NewState` +- [ ] `LastStateChangeTime = GameTime` +- [ ] Push `NewState` onto `StateHistory` (max 20 entries) +- [ ] Update GASP: `ABP_GASP.bIsInAction = (NewState in action states)` +- [ ] Update GASP: `ABP_GASP.ActionIntensity` per state mapping +- [ ] Fire `OnStateChanged` dispatcher +- [ ] Notify `SS_EnhancedInputManager` of context change +- [ ] If `bLogStateTransitions` → print transition to log +- [ ] Set `bIsTransitioning = false` +- [ ] Process `PendingRequests` queue + +### Step 4.4: `ForceStateChange` +Per [Section 7.2](../architecture/bpc-statemanager.md#72-forcestatechange): +- [ ] If `ForceStack` top == `NewState` → return (no-op) +- [ ] Push `CurrentState` onto `ForceStack` +- [ ] Fire `OnForceOverridePushed(NewState, CurrentState)` +- [ ] Call `ExecuteStateTransition(NewState)` +- [ ] Log reason if `bLogStateTransitions` + +### Step 4.5: `RestorePreviousState` +Per [Section 7.3](../architecture/bpc-statemanager.md#73-restorepreviousstate): +- [ ] If `ForceStack` is empty → set `NewState = Idle` +- [ ] Else → Pop `ForceStack` → `NewState = popped` +- [ ] Fire `OnForceOverridePopped(NewState)` +- [ ] Call `ExecuteStateTransition(NewState)` + +### Step 4.6: `IsActionPermitted` +Per [Section 7.6](../architecture/bpc-statemanager.md#76-isactionpermitted): +- [ ] Find all `GatingRules` where `ActionTag` matches +- [ ] Check CurrentState, GamePhase, RequiredTags, BlockedTags +- [ ] Return `S_ActionPermissionResult` with bool, reason, result code + +### Step 4.7: `SetOverlayState` +Per [Section 7.7](../architecture/bpc-statemanager.md#77-setoverlaystate): +- [ ] If `Overlay == CurrentOverlay` → return +- [ ] `CurrentOverlay = Overlay` +- [ ] Set `ABP_GASP.OverlayState = Overlay` if cached ref valid +- [ ] Fire `OnOverlayStateChanged` +- [ ] Notify `BPC_EmbodimentSystem` (if on same actor) + +### Step 4.8: Convenience Functions +- [ ] `GetCurrentState()` → pure getter +- [ ] `GetPreviousState()` → pure getter +- [ ] `CanTransitionTo(TargetState)` → pre-flight check (calls gating, no transition) +- [ ] `IsInCombat()` → CurrentState in `[SwingMelee, AimingFirearm, FiringFirearm, Reloading, DeployingShield]` +- [ ] `IsMovementBlocked()` → CurrentState in blocking list per Section 7.10 +- [ ] `CanEquipWeapon()` → delegates to `IsActionPermitted(Action.Weapon.Equip)` + +### Step 4.9: Action Flag Functions +- [ ] `RegisterActionFlag(Tag, Duration)` → add to `CurrentActionFlags` map, start timer if Duration > 0 +- [ ] `UnregisterActionFlag(Tag)` → remove from map, clear timer +- [ ] `HasActionFlag(Tag)` → lookup in map + +--- + +## Phase 5 — GASP Integration + +Per [Section 10](../architecture/bpc-statemanager.md#10-gasp-integration-notes): + +- [ ] **Read from GASP:** Subscribe to `ABP_GASP` dispatchers for `bStrafing`, `bSprinting`, `MovementMode`, `GroundState` +- [ ] **Write to GASP:** Set `OverlayState`, `bIsInAction`, `ActionIntensity` as variables on cached AnimBP ref +- [ ] **Never touch:** Motion Matching database, Camera Manager, GASP internal state machine, root motion +- [ ] **Overlay pipeline:** Verify `SetOverlayState(Pistol)` → blends upper body correctly + +--- + +## Phase 6 — System Integration (Bind Other Systems) + +- [ ] **`BPC_HealthSystem` (08):** Bind `OnDeath` → `ForceStateChange(Dead)`. Bind `OnRespawn` → `RestorePreviousState()` +- [ ] **`BPC_MovementStateSystem` (11):** `OnMovementModeChanged` sets walking/jogging/sprinting state. `OnPostureChanged` sets crouching/crawling +- [ ] **`BPC_HidingSystem` (12):** `OnHideStateChanged` → Hidden triggers `RequestStateChange(Hiding)`; Exposed triggers restore +- [ ] **`BPC_ContextualTraversalSystem` (21):** Traversal start → `RequestStateChange(Vaulting/Climbing/Sliding)`; end → restore +- [ ] **`BPC_InteractionDetector` (16):** Interaction start → `RequestStateChange(Interacting)`; end → restore +- [ ] **`BPC_MeleeSystem` (76):** StartSwing → `RequestStateChange(SwingMelee)`; OnSwingComplete → restore +- [ ] **`BPC_FirearmSystem` (74):** Fire → `RequestStateChange(FiringFirearm)` (transient, auto-restore) +- [ ] **`BPC_ReloadSystem` (78):** StartReload → `RequestStateChange(Reloading)`; Complete → restore +- [ ] **`BPC_DeathHandlingSystem` (39):** OnPlayerDeath → `ForceStateChange(Dead)`. OnRespawn → `RestorePreviousState()` +- [ ] **`SS_UIManager` (44):** Inventory open → `RequestStateChange(InInventory)`; close → restore. Pause → `InPauseMenu` +- [ ] **`BPC_DialoguePlaybackSystem` (60):** Dialogue start → `RequestStateChange(InDialogue)`; end → restore +- [ ] **`BPC_CutsceneBridge` (64):** PlayCutscene → `ForceStateChange(InCutscene)`. OnCutsceneCompleted → `RestorePreviousState()` +- [ ] **`BPC_AltDeathSpaceSystem` (38):** Enter → `ForceStateChange(InVoidSpace)`. Exit → `RestorePreviousState()` +- [ ] **`SS_EnhancedInputManager` (128):** Bind to `OnStateChanged` → switch `IMC_` contexts based on state +- [ ] **`BPC_CameraStateLayer` (14):** Bind to `OnStateChanged` → adjust FOV/offset per state + +--- + +## Phase 7 — Integration Pattern (Replace Hardcoded State Checks) + +For each of the 36+ state-gated actions: + +**OLD pattern (remove):** +``` +If (PlayerState != Dead && PlayerState != Hiding && PlayerState != Cutscene...) + → Execute Action +``` + +**NEW pattern (replace with):** +``` +If (BPC_StateManager.IsActionPermitted(ActionTag).bPermitted) + → Execute Action +Else + → Show blocked feedback using result.BlockReason +``` + +### Systems to Update: +- [ ] `BPC_HidingSystem.EnterHideSpot` → check `Action.Hide.Enter` +- [ ] `BPC_FirearmSystem.Fire` → check `Action.Weapon.Fire` +- [ ] `BPC_ReloadSystem.StartReload` → check `Action.Weapon.Reload` +- [ ] `BPC_MeleeSystem.StartSwing` → check `Action.Weapon.Melee` +- [ ] `SS_UIManager.OpenInventory` → check `Action.Inventory.Open` +- [ ] `BPC_InteractionDetector.PerformInteraction` → check `Action.Interact.Hold` +- [ ] `BPC_ContextualTraversalSystem.AttemptTraversal` → check `Action.Traversal.*` +- [ ] `BPC_EquipmentSlotSystem.EquipItem` → check `Action.Inventory.Equip` +- [ ] `BPC_ConsumableSystem.UseConsumable` → check `Action.Consumable.Use` +- [ ] `BPC_PhysicsDragSystem.GrabObject` → check `Action.Grab.PhysicsObject` +- [ ] `BPC_DialoguePlaybackSystem.StartDialogue` → check `Action.Dialogue.Start` +- [ ] `WBP_PauseMenu.OpenPause` → check `Action.Pause.Open` + +--- + +## Phase 8 — Testing + +Per [Section 13 Testing Checklist](../architecture/bpc-statemanager.md#13-testing-checklist): +- [ ] Valid state changes return `Permitted` +- [ ] Dead blocks all actions except respawn +- [ ] Force bypasses all gating +- [ ] ForceStack push/pop restores correct state +- [ ] Overlay state correctly writes to GASP +- [ ] Game phase changes gate actions correctly +- [ ] Rapid requests are throttled by `StateTransitionDelay` +- [ ] 25+ action gating rules all work +- [ ] Edge case: double Force same state = no-op +- [ ] Edge case: RestorePreviousState with empty stack = Idle +- [ ] Edge case: Owner destroyed during transition = graceful null check + +--- + +## Files Created (Summary) + +| File | Type | Path | +|------|------|------| +| `E_PlayerActionState` | Enum | `Content/Framework/Core/` | +| `E_OverlayState` | Enum | `Content/Framework/Core/` | +| `E_ActionRequestResult` | Enum | `Content/Framework/Core/` | +| `S_StateChangeRequest` | Struct | (Blueprint-internal) | +| `S_StateGatingRule` | Struct | (Blueprint-internal) | +| `S_ActionPermissionResult` | Struct | (Blueprint-internal) | +| `DA_StateGatingTable` | Data Asset | `Content/Framework/Core/` | +| `BPC_StateManager` | Blueprint Component | `Content/Framework/Player/` | + +--- + +*Checklist v1.0 — Aligned with [`docs/architecture/bpc-statemanager.md`](../architecture/bpc-statemanager.md). Ready for Code agent implementation.* \ No newline at end of file diff --git a/docs/checklists/clean-slate-refactor.md b/docs/checklists/clean-slate-refactor.md new file mode 100644 index 0000000..97ecf64 --- /dev/null +++ b/docs/checklists/clean-slate-refactor.md @@ -0,0 +1,346 @@ +# Clean Slate Refactoring — Implementation Checklist + +**Source Plan:** [`docs/architecture/CLEAN_SLATE_PLAN.md`](../architecture/CLEAN_SLATE_PLAN.md) +**Master Document:** [`UE5_Modular_Game_Framework.md`](../../UE5_Modular_Game_Framework.md) +**Audit:** [`docs/blueprints/AUDIT_REPORT.md`](../../docs/blueprints/AUDIT_REPORT.md) +**Template:** [`docs/blueprints/TEMPLATE.md`](../../docs/blueprints/TEMPLATE.md) + +--- + +## Phase 0 — Setup + +- [ ] 0.1 Verify current `git status` is clean (commit any pending changes first) +- [ ] 0.2 Create branch `refactor/clean-slate` from `main` +- [ ] 0.3 Confirm all 83 blueprint files are readable and not corrupted + +--- + +## Phase 1 — Rename 18 Files to Match Master Naming + +Each task: delete old file, create new file at same location with corrected name, update internal header line. + +### 03-interaction/ +- [ ] 1.1 Rename `20_BPC_InteractableDoorComponent.md` → `BP_DoorActor.md` + +### 04-inventory/ +- [ ] 1.2 Rename `22_BPC_InventoryComponent.md` → `BPC_InventorySystem.md` +- [ ] 1.3 Rename `25_BPC_EquipmentSystem.md` → `BPC_EquipmentSlotSystem.md` + +### 05-saveload/ +- [ ] 1.4 Rename `30_BPC_CheckpointSystem.md` → `BP_Checkpoint.md` (if Master uses BP_ prefix; verify against Master line) + +### 06-ui/ +- [ ] 1.5 Rename `33_WBP_HUD.md` → `WBP_HUDController.md` +- [ ] 1.6 Rename `34_WBP_InventoryUI.md` → `WBP_InventoryMenu.md` +- [ ] 1.7 Rename `35_WBP_InteractionUI.md` → `WBP_InteractionPromptDisplay.md` + +### 07-narrative/ +- [ ] 1.8 Rename `45_BPC_EndingAccumulatorSystem.md` → `BPC_EndingAccumulator.md` +- [ ] 1.9 Rename `47_BPC_NarrativeTriggerVolume.md` → `BP_NarrativeTriggerVolume.md` + +### 08-weapons/ +- [ ] 1.10 Rename `50_BP_RangedWeapon.md` → `BPC_FirearmSystem.md` +- [ ] 1.11 Rename `51_BP_MeleeWeapon.md` → `BPC_MeleeSystem.md` +- [ ] 1.12 Rename `53_BPC_DamageHandlerComponent.md` → `BPC_DamageReceptionSystem.md` + +### 09-ai/ +- [ ] 1.13 Rename `55_BPC_AIControllerBase.md` → `AI_BaseAgentController.md` +- [ ] 1.14 Rename `56_BPC_PerceptionComponent.md` → `BPC_AIPerceptionSystem.md` + +### 10-adaptive/ +- [ ] 1.15 Rename `64_BPC_AtmosphereController.md` → `BPC_AtmosphereStateController.md` +- [ ] 1.16 Rename `65_BPC_LightingManager.md` → `BPC_LightEventController.md` +- [ ] 1.17 Rename `66_BPC_AudioManager.md` → `BPC_AudioAtmosphereController.md` + +### Verify +- [ ] 1.18 Verify all 18 renamed files exist and old files are deleted + +--- + +## Phase 2 — Split Two Bundled Files + +### 2.1 Split DeathHandlingSystem (1 file → 5 files) + +**Read source:** `05-saveload/31_BPC_DeathHandlingSystem.md` (311 lines) + +- [ ] 2.1.1 Create `05-saveload/BPC_DeathHandlingSystem.md` — Core orchestrator content (lines 1-64 enums/structs + 206-311 core vars/fns/flow/matrix + header section) +- [ ] 2.1.2 Create `05-saveload/BPC_AltDeathSpaceSystem.md` — Alt death space sub-system (lines 65-99) +- [ ] 2.1.3 Create `05-saveload/BPC_PersistentCorpseSystem.md` — Corpse sub-system (lines 102-132) +- [ ] 2.1.4 Create `05-saveload/BPC_PlayerRespawnSystem.md` — Respawn sub-system (lines 136-167) +- [ ] 2.1.5 Create `05-saveload/BPC_RunHistoryTracker.md` — Run history sub-system (lines 171-203) + +**Each split file must:** +- Include a `Depends On:` section referencing the orchestrator and relevant systems +- Include a `Purpose:` header describing its standalone role +- Follow TEMPLATE.md format with complete sections + +- [ ] 2.1.6 Delete original `05-saveload/31_BPC_DeathHandlingSystem.md` +- [ ] 2.1.7 Verify all 5 new files are self-contained and valid + +### 2.2 Split MenuWidgets (1 file → 7 files) + +**Read source:** `06-ui/36_WBP_MenuWidgets.md` (353 lines) + +- [ ] 2.2.1 Create `06-ui/WBP_MainMenu.md` — Main menu widget (lines 15-48) +- [ ] 2.2.2 Create `06-ui/WBP_PauseMenu.md` — Pause menu widget (lines 51-94) +- [ ] 2.2.3 Create `06-ui/WBP_SettingsMenu.md` — Settings menu widget (lines 99-188) +- [ ] 2.2.4 Create `06-ui/WBP_NotificationToast.md` — Toast notification widget (lines 191-230) +- [ ] 2.2.5 Create `06-ui/WBP_ScreenEffectController.md` — Screen effects widget (lines 233-261) +- [ ] 2.2.6 Create `06-ui/WBP_MenuFlowController.md` — Menu flow widget (lines 264-353) +- [ ] 2.2.7 Create `06-ui/WBP_ObjectiveDisplay.md` — New file (not in bundled source; Master Sec 6.6) + +**Note for 2.2.7:** `WBP_ObjectiveDisplay` is listed in Master Section 6.6 but was NOT in the bundled `WBP_MenuWidgets.md`. Create from scratch using TEMPLATE.md. It displays current objectives as an overlay. + +- [ ] 2.2.8 Delete original `06-ui/36_WBP_MenuWidgets.md` +- [ ] 2.2.9 Verify all 7 new files are self-contained and valid + +--- + +## Phase 3 — Create 12 Data Asset Spec Files (new `14-data-assets/` directory) + +All DA files should follow this structure: +``` +# DA_ — Data Asset +**Parent Class:** `UDataAsset` +**Dependencies:** (systems that consume this data) +**Purpose:** (what content this data asset defines) + +## Variables / Structure +(complete row structure definition) + +## Gameplay Tags +(tag namespace this DA operates in) + +## Validation Rules +(editor-time validation logic) + +## Example Data +(1-2 example rows) + +## Consumed By +(systems that read this DA) + +## Reuse Notes +``` + +- [ ] 3.0 Create directory `docs/blueprints/14-data-assets/` +- [ ] 3.1 Create `14-data-assets/DA_DataAssetArchitecture.md` — overview of all 20 DA types, naming conventions, dependency rules +- [ ] 3.2 Create `14-data-assets/DA_InteractionData.md` +- [ ] 3.3 Create `14-data-assets/DA_ObjectiveData.md` +- [ ] 3.4 Create `14-data-assets/DA_EncounterData.md` +- [ ] 3.5 Create `14-data-assets/DA_AtmosphereProfile.md` +- [ ] 3.6 Create `14-data-assets/DA_ScareEvent.md` +- [ ] 3.7 Create `14-data-assets/DA_RoomMutation.md` +- [ ] 3.8 Create `14-data-assets/DA_BehaviourVariant.md` +- [ ] 3.9 Create `14-data-assets/DA_HapticProfile.md` +- [ ] 3.10 Create `14-data-assets/DA_AdaptationRule.md` +- [ ] 3.11 Create `14-data-assets/DA_EquipmentConfig.md` +- [ ] 3.12 Create `14-data-assets/DA_PuzzleData.md` +- [ ] 3.13 Create `14-data-assets/DA_RareEvent.md` + +--- + +## Phase 4 — Create 30 Runtime System Spec Files + +### 03-interaction/ (4 files) +- [ ] 4.1 Create `03-interaction/BPC_PhysicsDragSystem.md` +- [ ] 4.2 Create `03-interaction/BPC_ContextualTraversalSystem.md` +- [ ] 4.3 Create `03-interaction/BP_PuzzleDeviceActor.md` +- [ ] 4.4 Create `03-interaction/BPC_UsableWorldObjectSystem.md` + +### 04-inventory/ (7 files) +- [ ] 4.5 Create `04-inventory/BPC_ActiveItemSystem.md` +- [ ] 4.6 Create `04-inventory/BPC_ItemCombineSystem.md` +- [ ] 4.7 Create `04-inventory/BPC_DocumentArchiveSystem.md` +- [ ] 4.8 Create `04-inventory/BPC_JournalSystem.md` +- [ ] 4.9 Create `04-inventory/BPC_CollectibleTracker.md` +- [ ] 4.10 Create `04-inventory/BPC_ConsumableSystem.md` +- [ ] 4.11 Create `04-inventory/BPC_KeyItemSystem.md` + +### 05-saveload/ (1 file) +- [ ] 4.12 Create `05-saveload/BPC_PersistentWorldStateRecorder.md` + +### 06-ui/ (3 files) +- [ ] 4.13 Create `06-ui/WBP_DiegeticHUDFrame.md` +- [ ] 4.14 Create `06-ui/WBP_JournalDocumentViewer.md` +- [ ] 4.15 Create `06-ui/WBP_ObjectiveDisplay.md` (already created in Phase 2.2.7) + +### 08-weapons/ (5 files) +- [ ] 4.16 Create `08-weapons/BPC_RecoilSystem.md` +- [ ] 4.17 Create `08-weapons/BPC_ReloadSystem.md` +- [ ] 4.18 Create `08-weapons/BPC_ShieldDefenseSystem.md` +- [ ] 4.19 Create `08-weapons/BPC_HitReactionSystem.md` +- [ ] 4.20 Create `08-weapons/BPC_DeathCauseTracker.md` + +### 09-ai/ (3 files) +- [ ] 4.21 Create `09-ai/BB_AgentBoard.md` +- [ ] 4.22 Create `09-ai/BPC_AIMemorySystem.md` +- [ ] 4.23 Create `09-ai/BPC_BehaviourVariantSelector.md` + +### 10-adaptive/ (6 files) +- [ ] 4.24 Create `10-adaptive/BPC_PlaystyleClassifier.md` +- [ ] 4.25 Create `10-adaptive/BPC_AdaptiveEnvironmentDirector.md` +- [ ] 4.26 Create `10-adaptive/BPC_MemoryDriftSystem.md` +- [ ] 4.27 Create `10-adaptive/BPC_ScareEventSystem.md` +- [ ] 4.28 Create `10-adaptive/BPC_PacingDirector.md` +- [ ] 4.29 Create `10-adaptive/BPC_RareEventSystem.md` + +--- + +## Phase 5 — Reorganize 11-polish/ into 3 New Directories + +### 5.1 Create new directories +- [ ] 5.1.1 Create `docs/blueprints/11-meta/` +- [ ] 5.1.2 Create `docs/blueprints/12-settings/` +- [ ] 5.1.3 Create `docs/blueprints/13-polish/` + +### 5.2 Move files to 11-meta/ (3 files) +- [ ] 5.2.1 Move `11-polish/74_BPC_AchievementManager.md` → `11-meta/SS_AchievementSystem.md` +- [ ] 5.2.2 Move `11-polish/75_BPC_StatsTracker.md` → `11-meta/BPC_ProgressStatTracker.md` +- [ ] 5.2.3 Create `11-meta/BPC_EndingCompletionTracker.md` (new) +- [ ] 5.2.4 Create `11-meta/BPC_MetaProgressionSystem.md` (new) +- [ ] 5.2.5 Create `11-meta/BPC_RunSummarySystem.md` (new) + +### 5.3 Move files to 12-settings/ (4 files) +- [ ] 5.3.1 Move `11-polish/71_SS_SettingsManager.md` → `12-settings/SS_SettingsSystem.md` +- [ ] 5.3.2 Move `11-polish/72_BPC_AccessibilitySettings.md` → `12-settings/BPC_AccessibilitySettings.md` +- [ ] 5.3.3 Create `12-settings/BPC_HapticsController.md` (new) +- [ ] 5.3.4 Create `12-settings/BPC_PlatformServiceAbstraction.md` (new) + +### 5.4 Move remaining files to 13-polish/ (9 files) +- [ ] 5.4.1 Move `11-polish/73_BPC_TutorialSystem.md` → `13-polish/BPC_TutorialSystem.md` +- [ ] 5.4.2 Move `11-polish/76_BPC_LoadingScreen.md` → `13-polish/BPC_LoadingScreen.md` +- [ ] 5.4.3 Move `11-polish/77_WBP_CreditsScreen.md` → `13-polish/WBP_CreditsScreen.md` +- [ ] 5.4.4 Move `11-polish/78_WBP_SplashScreen.md` → `13-polish/WBP_SplashScreen.md` +- [ ] 5.4.5 Move `11-polish/79_BPC_FPSCounter.md` → `13-polish/BPC_FPSCounter.md` +- [ ] 5.4.6 Move `11-polish/80_BPC_DevCheatManager.md` → `13-polish/BPC_DevCheatManager.md` +- [ ] 5.4.7 Move `11-polish/81_WBP_DebugMenu.md` → `13-polish/WBP_DebugMenu.md` +- [ ] 5.4.8 Move `11-polish/82_BPC_AnalyticsTracker.md` → `13-polish/BPC_AnalyticsTracker.md` +- [ ] 5.4.9 Move `11-polish/83_BPC_ErrorHandler.md` → `13-polish/BPC_ErrorHandler.md` + +### 5.5 Clean up +- [ ] 5.5.1 Delete empty `11-polish/` directory + +--- + +## Phase 6 — Delete Extra/Unmatched Files (7 files) + +These files define systems not present in the Master document or are replaced by split/new files: + +- [ ] 6.1 Delete `03-interaction/17_BPC_PickupComponent.md` (covered by ItemPickup + InteractionExecutor) +- [ ] 6.2 Delete `03-interaction/19_BPC_LeverPuzzleComponent.md` (covered by BP_PuzzleDeviceActor) +- [ ] 6.3 Delete `04-inventory/23_BPC_InventoryWeightSystem.md` (sub-feature of InventorySystem) +- [ ] 6.4 Delete `04-inventory/24_BPC_InventoryQuickSlot.md` (sub-feature of ActiveItemSystem) +- [ ] 6.5 Delete `09-ai/57_BPC_BehaviorTreeManager.md` (covered by BB_AgentBoard + BehaviourVariantSelector) +- [ ] 6.6 Delete `10-adaptive/68_BP_DynamicEvent.md` (covered by BPC_RareEventSystem) +- [ ] 6.7 Delete `10-adaptive/67_BPC_VFXManager.md` (not in Master; VFX controlled by AtmosphereController) + +--- + +## Phase 7 — Renumber All Files Sequentially + +After all renames/splits/creates/moves/deletes, renumber every file prefixed with `XX_` (where XX is the existing number). + +**New numbering order:** +1. 01-core/ → 01–12 +2. 02-player/ → 13–21 +3. 03-interaction/ → 22–32 +4. 04-inventory/ → 33–44 +5. 05-saveload/ → 45–53 +6. 06-ui/ → 54–66 +7. 07-narrative/ → 67–77 +8. 08-weapons/ → 78–89 +9. 09-ai/ → 90–98 +10. 10-adaptive/ → 99–107 +11. 11-meta/ → 108–113 +12. 12-settings/ → 114–118 +13. 13-polish/ → 119–128 +14. 14-data-assets/ → 129–141 + +**Renumbering rules:** +- Each file gets prefix `XX_` where XX is zero-padded to 2 digits +- The prefix matches the directory's slot in the numbering order +- Example: `01-core/01_GI_GameFramework.md` stays `01_`. `06-ui/` files get `54_` through `66_`. +- Internal cross-references in each file must be updated to new filenames + +- [ ] 7.1 Renumber 01-core/ files (7 files → verify, may need expansion to 12) +- [ ] 7.2 Renumber 02-player/ files (9 files → 13–21) +- [ ] 7.3 Renumber 03-interaction/ files (11 files → 22–32) +- [ ] 7.4 Renumber 04-inventory/ files (12 files → 33–44) +- [ ] 7.5 Renumber 05-saveload/ files (9 files → 45–53) +- [ ] 7.6 Renumber 06-ui/ files (13 files → 54–66) +- [ ] 7.7 Renumber 07-narrative/ files (11 files → 67–77) +- [ ] 7.8 Renumber 08-weapons/ files (12 files → 78–89) +- [ ] 7.9 Renumber 09-ai/ files (9 files → 90–98) +- [ ] 7.10 Renumber 10-adaptive/ files (9 files → 99–107) +- [ ] 7.11 Renumber 11-meta/ files (6 files → 108–113) +- [ ] 7.12 Renumber 12-settings/ files (5 files → 114–118) +- [ ] 7.13 Renumber 13-polish/ files (10 files → 119–128) +- [ ] 7.14 Renumber 14-data-assets/ files (13 files → 129–141) + +--- + +## Phase 8 — Update Cross-References + +After renumbering, every internal cross-reference in every file must point to the correct filename. + +- [ ] 8.1 Search all `.md` files for `](XX_` patterns +- [ ] 8.2 Verify each link target exists at the referenced path +- [ ] 8.3 Fix any broken or stale links + +--- + +## Phase 9 — Update AUDIT_REPORT.md + +- [ ] 9.1 Update all status columns to ✅ for previously missing/bundled systems +- [ ] 9.2 Update file counts (final: ~141 files, 0 missing) +- [ ] 9.3 Remove "Recommendations" section (all completed) +- [ ] 9.4 Add "Resolved" section documenting what was done + +--- + +## Phase 10 — Update CONTEXT.md + +- [ ] 10.1 Update directory structure to reflect all 14 directories +- [ ] 10.2 Update file count to ~141 +- [ ] 10.3 Update build order to 14 phases +- [ ] 10.4 Update naming conventions reference +- [ ] 10.5 Mark Clean Slate refactoring as complete + +--- + +## Phase 11 — Final Verification + +- [ ] 11.1 Run `list_files` recursively on `docs/blueprints/` — verify 14 directories, ~141 files +- [ ] 11.2 Cross-reference: every Master system (Section 1–12) should have exactly 1 file +- [ ] 11.3 Cross-reference: all 20 Data Asset types from Section 13 have a spec +- [ ] 11.4 Verify no duplicate system names across directories +- [ ] 11.5 Verify all files follow TEMPLATE.md format (header, enums, structs, variables, functions, dispatchers, flow, communications, reuse) +- [ ] 11.6 Verify sequential numbering from 01 to 141 +- [ ] 11.7 Run `git status` — should show renames, new files, deleted files, no orphaned files + +--- + +## Phase 12 — Git Commit + +- [ ] 12.1 Stage all changes +- [ ] 12.2 Commit with message: `refactor: clean slate — 1:1 master-to-file mapping for all 141 systems` +- [ ] 12.3 Verify commit is clean +- [ ] 12.4 (Optional) Create PR to main + +--- + +## Notes for Execution Agent + +1. **Use `apply_diff` for renaming file header lines** — change the `# XX_SystemName` line only +2. **Use `write_to_file` for creating new files** (always with complete content) +3. **Use `delete_file` for removing obsolete files** +4. **NEVER use `sed`, `awk`, or `cat >`** for file operations +5. **Read the Master document section** for each new file before writing it to get accurate variable/function definitions +6. **Follow TEMPLATE.md religiously** — every new file must have all required sections +7. **Commit after each Phase** (not after every file) to keep git history reasonable +8. **If a Master section is unclear on a detail**, use the conventions from nearby systems and document the assumption in Reuse Notes + +--- + +*Checklist created 2026-05-18* \ No newline at end of file diff --git a/docs/checklists/enhanced-input-system.md b/docs/checklists/enhanced-input-system.md new file mode 100644 index 0000000..24c7b05 --- /dev/null +++ b/docs/checklists/enhanced-input-system.md @@ -0,0 +1,170 @@ +# Enhanced Input System — Implementation Checklist + +## Phase 1: Asset Creation (Game Dev / Code Agent) + +- [ ] **1.1** Create directory `Content/Framework/Input/Actions/` +- [ ] **1.2** Create directory `Content/Framework/Input/Contexts/` +- [ ] **1.3** Create all 30+ Input Action assets (`IA_*`) with correct Value Types: + - [ ] `IA_Move` (Axis2D) + - [ ] `IA_Look` (Axis2D) + - [ ] `IA_Inspect_Rotate` (Axis2D) + - [ ] `IA_UI_Navigate` (Axis2D) + - [ ] `IA_Hide_Look` (Axis2D) + - [ ] `IA_Inspect_Zoom` (Axis1D) + - [ ] `IA_Hide_Peek` (Axis1D) + - [ ] `IA_QuickSlotScroll` (Axis1D) + - [ ] `IA_Interact` (Digital/Bool) + - [ ] `IA_PrimaryAction` (Digital/Bool) + - [ ] `IA_SecondaryAction` (Digital/Bool) + - [ ] `IA_Sprint` (Digital/Bool) + - [ ] `IA_Crouch` (Digital/Bool) + - [ ] `IA_Vault_Climb` (Digital/Bool) + - [ ] `IA_Jump` (Digital/Bool) + - [ ] `IA_Flashlight` (Digital/Bool) + - [ ] `IA_QuickHeal` (Digital/Bool) + - [ ] `IA_Reload` (Digital/Bool) + - [ ] `IA_OpenWatch` (Digital/Bool) + - [ ] `IA_PauseMenu` (Digital/Bool) + - [ ] `IA_QuickSlot1` through `IA_QuickSlot8` (Digital/Bool) + - [ ] `IA_Inspect_Flip` (Digital/Bool) + - [ ] `IA_Cancel_Drop` (Digital/Bool) + - [ ] `IA_UI_Select` (Digital/Bool) + - [ ] `IA_UI_Combine` (Digital/Bool) + - [ ] `IA_UI_DropItem` (Digital/Bool) + - [ ] `IA_CloseWatch` (Digital/Bool) + - [ ] `IA_UI_Back` (Digital/Bool) + - [ ] `IA_Hide_HoldBreath` (Digital/Bool) + - [ ] `IA_Exit_Hide` (Digital/Bool) + - [ ] `IA_ToggleAccessibility` (Digital/Bool) + - [ ] `IA_SkipCutscene` (Digital/Bool) +- [ ] **1.4** Create all 5 Input Mapping Context assets (`IMC_*`): + - [ ] `IMC_Default` + - [ ] `IMC_Hiding` + - [ ] `IMC_WristwatchUI` + - [ ] `IMC_Inspection` + - [ ] `IMC_UI` +- [ ] **1.5** Create `DA_InputMappingProfile` Data Asset at `Content/Framework/DataAssets/` +- [ ] **1.6** Populate `DA_InputMappingProfile` with all 3 platform profiles per the spec + +--- + +## Phase 2: IMC Binding Setup + +- [ ] **2.1** `IMC_Default` — Map all 28 actions to PC, Xbox, and PS5 bindings +- [ ] **2.2** `IMC_Default` — Apply W/A/S/D modifiers (S=Negate, D=Swizzle, A=Swizzle+Negate) +- [ ] **2.3** `IMC_Default` — Set analog stick dead zones (0.15) +- [ ] **2.4** `IMC_Default` — Configure hold triggers (Interact 0.3s, Sprint 0s, SkipCutscene 2.0s) +- [ ] **2.5** `IMC_Hiding` — Map 4 actions with clamped look angles +- [ ] **2.6** `IMC_WristwatchUI` — Map 5 UI navigation actions +- [ ] **2.7** `IMC_Inspection` — Map 4 inspection actions +- [ ] **2.8** `IMC_UI` — Map 5 full-screen UI actions +- [ ] **2.9** Configure chord actions (HoldBreath = LT+RT, ToggleAccessibility = View+Menu) + +--- + +## Phase 3: Subsystem Implementation (Code Agent) + +- [ ] **3.1** Create `SS_EnhancedInputManager` Game Instance Subsystem +- [ ] **3.2** Implement `Initialize(Profile)` — load DA, cache EnhancedInputLocalPlayerSubsystem +- [ ] **3.3** Implement `PushContext(ContextType, PriorityOverride)` — AddMappingContext with priority +- [ ] **3.4** Implement `PopContext(ContextType)` — RemoveMappingContext +- [ ] **3.5** Implement `SetContextPriority(ContextType, NewPriority)` — remove + re-add +- [ ] **3.6** Implement `IsActionPressed(ActionName)` → Bool +- [ ] **3.7** Implement `GetActionValue1D(ActionName)` → Float +- [ ] **3.8** Implement `GetActionValue2D(ActionName)` → FVector2D +- [ ] **3.9** Implement `RebindKey(ActionName, NewKey, Platform)` → Bool +- [ ] **3.10** Implement `ResetToDefaultBindings(Platform)` +- [ ] **3.11** Implement `GetCurrentBindings(Platform)` → TMap +- [ ] **3.12** Implement `GetActiveContexts()` → TArray +- [ ] **3.13** Implement `IsContextActive(ContextType)` → Bool +- [ ] **3.14** Implement `SetInputModeUIOnly()` / `SetInputModeGameOnly()` / `SetInputModeGameAndUI()` +- [ ] **3.15** Wire up Event Dispatchers: OnContextPushed, OnContextPopped, OnInputModeChanged, OnKeyRebound, OnPlatformChanged +- [ ] **3.16** Register self with `GI_GameFramework` for static access via `FL_GameUtilities::GetInputManager()` + +--- + +## Phase 4: Integration — Init Sequence (Code Agent) + +- [ ] **4.1** In `GI_GameFramework::Startup`, call `SS_EnhancedInputManager::Initialize(DA_InputMappingProfile)` +- [ ] **4.2** In `GM_CoreGameMode::OnPlayerPossess`, call `PushContext(Default)` with Priority 0 +- [ ] **4.3** In `GM_CoreGameMode::OnPlayerUnPossess`, call `PopContext(Default)` + +--- + +## Phase 5: Integration — Context Switches (Code Agent) + +- [ ] **5.1** `BPC_HidingSystem::EnterHiding` → `PushContext(Hiding, 5)` +- [ ] **5.2** `BPC_HidingSystem::ExitHiding` → `PopContext(Hiding)` +- [ ] **5.3** `IA_OpenWatch` triggered → `PushContext(WristwatchUI, 10)` +- [ ] **5.4** `IA_CloseWatch` triggered → `PopContext(WristwatchUI)` +- [ ] **5.5** `BP_PuzzleDeviceActor / BPC_InteractionDetector` pickup 3D item → `PushContext(Inspection, 20)` +- [ ] **5.6** `IA_Cancel_Drop` → `PopContext(Inspection)` +- [ ] **5.7** `WBP_PauseMenu / SS_UIManager::ShowMenu` → `PushContext(UI, 100)` + `SetInputModeUIOnly()` +- [ ] **5.8** `WBP_PauseMenu::Close` → `PopContext(UI)` + `SetInputModeGameOnly()` +- [ ] **5.9** `BPC_CutsceneBridge::OnCutsceneStarted` → `PushContext(UI, 100)` + `SetInputModeUIOnly()` +- [ ] **5.10** `BPC_CutsceneBridge::RestoreGameplayState` → `PopContext(UI)` + restore + +--- + +## Phase 6: Integration — Gameplay Systems Read Input (Code Agent) + +- [ ] **6.1** `BPC_MovementStateSystem` → read `IA_Move` (Axis2D) and `IA_Sprint` (Bool) via `SS_EnhancedInputManager` +- [ ] **6.2** `BPC_CameraStateLayer` → read `IA_Look` (Axis2D) via `SS_EnhancedInputManager` +- [ ] **6.3** `BPC_InteractionDetector` → bind to `IA_Interact` press/release/hold events via `SS_EnhancedInputManager` +- [ ] **6.4** `BPC_FirearmSystem` → read `IA_PrimaryAction` (Bool) and `IA_Reload` (Bool) +- [ ] **6.5** `BPC_MeleeSystem` → read `IA_PrimaryAction` (Bool) for melee attacks +- [ ] **6.6** `BPC_ShieldDefenseSystem` → read `IA_SecondaryAction` (Bool) +- [ ] **6.7** `BPC_StaminaSystem` → listen to `IA_Sprint` state for continuous drain +- [ ] **6.8** `BPC_StressSystem` → listen to `IA_Sprint` for breathing/stress effects +- [ ] **6.9** `BPC_ActiveItemSystem` → read `IA_QuickSlot1-8` and `IA_QuickSlotScroll` +- [ ] **6.10** `BPC_ConsumableSystem` → listen to `IA_QuickHeal` +- [ ] **6.11** `BPC_Flashlight` (light system) → listen to `IA_Flashlight` toggle +- [ ] **6.12** `BPC_ContextualTraversalSystem` → listen to `IA_Vault_Climb` and `IA_Jump` + +--- + +## Phase 7: Settings & Rebind Integration + +- [ ] **7.1** `SS_SettingsSystem::ApplyControlSettings` → calls `SS_EnhancedInputManager::RebindKey` +- [ ] **7.2** `WBP_SettingsMenu` Controls tab → reads `GetCurrentBindings()` to populate rebind UI +- [ ] **7.3** Settings save/load → persist CurrentBindings in save file (controls section) +- [ ] **7.4** `BPC_AccessibilitySettings` → reads `AxisInvertSettings` from `DA_InputMappingProfile` +- [ ] **7.5** `WBP_InteractionPromptDisplay` → listens to `OnKeyRebound` to update displayed key icons +- [ ] **7.6** Controller glyph switching → on `OnPlatformChanged`, update all `WBP_InteractionPromptDisplay` icons + +--- + +## Phase 8: Existing Docs Update (Cross-Reference Pass) + +All existing specs that reference `BPC_InputManager` must be updated to reference `SS_EnhancedInputManager`: + +- [ ] **8.1** `docs/blueprints/13-polish/114_WBP_SplashScreen.md` — change `BPC_InputManager` references +- [ ] **8.2** `docs/blueprints/13-polish/112_WBP_CreditsScreen.md` — change `BPC_InputManager` references +- [ ] **8.3** `docs/blueprints/13-polish/111_BPC_TutorialSystem.md` — change `InputActionShown` to reference IA_ names +- [ ] **8.4** `docs/blueprints/07-narrative/64_BPC_CutsceneBridge.md` — change input suppression references +- [ ] **8.5** `docs/blueprints/02-player/11_BPC_MovementStateSystem.md` — change input note +- [ ] **8.6** `docs/blueprints/02-player/09_BPC_StaminaSystem.md` — change input note +- [ ] **8.7** `docs/blueprints/02-player/12_BPC_HidingSystem.md` — change input binding references +- [ ] **8.8** `docs/blueprints/03-interaction/16_BPC_InteractionDetector.md` — change input event references +- [ ] **8.9** `docs/blueprints/06-ui/44_SS_UIManager.md` — add `SS_EnhancedInputManager` coordination note +- [ ] **8.10** `docs/blueprints/12-settings/105_SS_SettingsSystem.md` — change `UPlayerInput` references + +--- + +## Phase 9: Testing (QA Engineer) + +- [ ] **9.1** Context priority: verify `IMC_WristwatchUI` (Priority 10) overrides `IMC_Default` WASD movement +- [ ] **9.2** Context pop: verify exiting wristwatch restores WASD movement +- [ ] **9.3** Hold vs Tap: verify `IA_Interact` tap = pickup, hold = physics drag +- [ ] **9.4** Modifiers: verify A/D produce correct ±X axis values +- [ ] **9.5** Dead zone: verify analog stick drift does not trigger movement +- [ ] **9.6** Key rebind: rebind `IA_Reload` from R to T, verify T now reloads +- [ ] **9.7** Reset defaults: reset bindings, verify R reloads again +- [ ] **9.8** Platform hot-swap: unplug controller, verify KB+M profile loads +- [ ] **9.9** Input mode: pause game, verify cursor visible and movement blocked +- [ ] **9.10** Quick slots: verify 1-8 on keyboard selects items, scroll wheel cycles +- [ ] **9.11** Cutscene skip: hold Spacebar 2.0s, verify skip triggers +- [ ] **9.12** Hiding hold breath: hold Spacebar (PC) / LT+RT (controller), verify breath suppressed +- [ ] **9.13** Edge case: spam-context-switch (open/close inventory rapidly) doesn't crash +- [ ] **9.14** Edge case: disconnect controller mid-combat, auto-switches to KB+M +- [ ] **9.15** Edge case: rebind to already-bound key, system rejects with warning \ No newline at end of file