# 11 — Movement State System (`BPC_MovementStateSystem`)

> **⚡ C++ Status: Stub** — `Source/PG_Framework/Public/Player/BPC_MovementStateSystem.h` provides the UCLASS shell, `CurrentMovementMode` GameplayTag variable, and `OnMovementModeChanged` dispatcher. **The C++ stub has NO gameplay logic.** **Create a BP child** and build ALL logic: CMC reads, posture detection (standing/crouching/prone), sprint state, footstep events, GASP ABP variable bridge. See `docs/developer/cpp-integration-guide.md`.
>
> ---

## Purpose
Tracks the player's current movement mode and posture state. Acts as a central query point for other systems (animations, stamina, audio, camera) to react to how the player is moving. Does not control movement input — only reports and reacts to state changes.

## Dependencies
- **Requires:** `FL_GameUtilities` (tag queries)
- **Required By:** `ABP_GASP` (animations), `BPC_StaminaSystem` (regen blocking), `BPC_CameraStateLayer` (FOV changes), `BPC_AudioManager` (footstep type), `BPC_InteractionDetector` (range scaling)
- **Engine/Plugin Requirements:** GameplayTags, GASP (ground/animation/strafing platform)

## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `ActorComponent` |
| **Class Type** | Blueprint Component |
| **Asset Path** | `Content/Framework/Player/BPC_MovementStateSystem` |
| **Implements Interfaces** | None |

---

## 1. Enums

### `E_PostureState`
| Value | Description |
|-------|-------------|
| `Standing = 0` | Full height, normal locomotion |
| `Crouching = 1` | Reduced height, slower speed |
| `Prone = 2` | Fully prone, crawling (horror immersion) |
| `Sliding = 3` | Transient — while sliding downhill or under obstacles |
| `Climbing = 4` | Ledge or ladder climbing |
| `Vaulting = 5` | Transient — while vaulting over obstacles |

### `E_MovementMode`
| Value | Description |
|-------|-------------|
| `Idle = 0` | Standing still |
| `Walking = 1` | Slow, careful movement |
| `Jogging = 2` | Normal movement speed |
| `Sprinting = 3` | Fast movement, stamina drain |
| `CrouchWalk = 4` | Slow crouch movement |
| `Sneaking = 5` | Ultra-slow, near-silent movement (special) |

### `E_StanceTransition`
| Value | Description |
|-------|-------------|
| `Instant = 0` | Immediate transition (no animation blend) |
| `Smooth = 1` | Smooth blend over TransitionBlendTime |
| `Forced = 2` | External force (knocked down, pushed) |

---

## 2. Structs

### `S_MovementSettings`
| Field | Type | Description |
|-------|------|-------------|
| `MovementMode` | `E_MovementMode` | Which mode this applies to |
| `MaxWalkSpeed` | `Float` | Max speed in this mode (cm/s) |
| `Acceleration` | `Float` | Acceleration rate |
| `Deceleration` | `Float` | Deceleration rate |
| `GroundFriction` | `Float` | Friction modifier |
| `bCanSprint` | `Boolean` | Can the player sprint from this mode? |
| `bCanCrouch` | `Boolean` | Can the player crouch from this mode? |
| `StaminaDrainMultiplier` | `Float` | Multiplier on stamina drain while in this mode |

### `S_FootstepProfile`
| Field | Type | Description |
|-------|------|-------------|
| `SurfaceType` | `EPhysicalSurface` | Surface being stepped on |
| `MovementMode` | `E_MovementMode` | Player's current movement mode |
| `SoundSoft` | `SoundBase` | Footstep sound at low velocity |
| `SoundHard` | `SoundBase` | Footstep sound at high velocity |
| `VelocityThreshold` | `Float` | Speed at which to switch from Soft to Hard |
| `Decal` | `MaterialInterface` | Footprint decal (mud, snow, blood) |

---

## 3. Variables

### Configuration (Instance Editable, Expose On Spawn)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `MovementSettings` | `Map<E_MovementMode, S_MovementSettings>` | `all modes` | `Movement Config` | Speed/accel values per movement mode |
| `TransitionBlendTime` | `Float` | `0.2` | `Movement Config` | Blend duration for smooth stance transitions |
| `bApplyMovementPenalties` | `Boolean` | `true` | `Movement Config` | Allow stress/health to affect movement speed |
| `CrouchHeight` | `Float` | `60.0` | `Movement Config` | Capsule half-height while crouching |
| `ProneHeight` | `Float` | `30.0` | `Movement Config` | Capsule half-height while prone |
| `StandingHeight` | `Float` | `96.0` | `Movement Config` | Capsule half-height while standing |
| `bUseVelocityBasedFootsteps` | `Boolean` | `true` | `Movement Config` | Auto-select footstep sound based on velocity |
| `DefaultFootstepProfile` | `S_FootstepProfile` | `-` | `Movement Config` | Fallback footstep when no surface match |

### Internal (Private / Protected, No Expose)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `CurrentPosture` | `E_PostureState` | `Standing` | `Movement State` | Current posture |
| `PreviousPosture` | `E_PostureState` | `Standing` | `Movement State` | Previous posture (for transition detection) |
| `CurrentMovementMode` | `E_MovementMode` | `Idle` | `Movement State` | Current movement mode |
| `PreviousMovementMode` | `E_MovementMode` | `Idle` | `Movement State` | Previous movement mode |
| `bIsOnGround` | `Boolean` | `true` | `Movement State` | Whether the player is grounded |
| `bIsMoving` | `Boolean` | `false` | `Movement State` | Whether the player is currently moving |
| `CurrentSpeed` | `Float` | `0.0` | `Movement State` | Current character speed (cm/s) |
| `bIsClimbing` | `Boolean` | `false` | `Movement State` | Whether currently climbing |
| `LastValidFloorNormal` | `Vector` | `(0,0,1)` | `Movement State` | Last valid ground normal |
| `CapsuleRef` | `UCapsuleComponent` | `None` | `Movement State` | Cached reference to capsule component |

### Replicated (if multiplayer)

| Variable | Type | Condition | Description |
|----------|------|-----------|-------------|
| `CurrentPosture` | `E_PostureState` | `RepNotify` | Replicated posture state |
| `CurrentMovementMode` | `E_MovementMode` | `RepNotify` | Replicated movement mode |

---

## 4. Functions

### Public Functions

#### `SetMovementMode` → `void`
- **Description:** Sets the current movement mode and applies corresponding movement settings to the CharacterMovementComponent.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `NewMode` | `E_MovementMode` | Desired movement mode |
  | `Transition` | `E_StanceTransition` | How to handle the transition |
- **Blueprint Authority:** Server (if MP), Any (single-player)
- **Flow:**
  1. If NewMode == CurrentMovementMode: return
  2. PreviousMovementMode = CurrentMovementMode
  3. CurrentMovementMode = NewMode
  4. Apply MovementSettings[NewMode] to CharacterMovementComponent
  5. Fire OnMovementModeChanged
  6. If transition is Forced: apply impulse or knockback
  7. Notify ABP_GASP via interface or direct cast

#### `SetPosture` → `void`
- **Description:** Sets the current posture and adjusts capsule size accordingly.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `NewPosture` | `E_PostureState` | Desired posture |
  | `Transition` | `E_StanceTransition` | How to handle the transition |
- **Flow:**
  1. If NewPosture == CurrentPosture: return
  2. If NewPosture == Prone and CurrentPosture == Standing: must go through Crouching first
  3. PreviousPosture = CurrentPosture
  4. CurrentPosture = NewPosture
  5. Update capsule height based on NewPosture
  6. Fire OnPostureChanged
  7. Notify ABP_GASP

#### `GetCurrentSpeedNormalised` → `Float [0.0 - 1.0]`
- **Description:** Returns speed as fraction of CurrentMovementMode's MaxWalkSpeed.
- **Flow:** Return CurrentSpeed / MovementSettings[CurrentMovementMode].MaxWalkSpeed

#### `CanTransitionToPosture` → `Boolean`
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `TargetPosture` | `E_PostureState` | Desired posture |
- **Flow:**
  1. Check ceiling clearance for upright transitions
  2. Check if MovementSettings allows this posture from current mode
  3. Return clearance OK and setting allows

#### `SetSprinting` → `void`
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `bSprinting` | `Boolean` | Whether to sprint |
- **Flow:**
  1. If bSprinting and CanSprint(): SetMovementMode(Sprinting)
  2. If !bSprinting: restore previous movement mode
  3. Fire OnSprintStateChanged

#### `SetCrouching` → `void`
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `bCrouching` | `Boolean` | Whether to crouch |
- **Flow:**
  1. If bCrouching: SetPosture(Crouching), SetMovementMode(CrouchWalk)
  2. If !bCrouching: SetPosture(Standing), restore previous walk mode

#### `ApplyMovementPenalty` → `void`
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Multiplier` | `Float` | Speed multiplier [0.0 - 1.0] |
  | `Duration` | `Float` | How long the penalty lasts |
  | `PenaltyTag` | `GameplayTag` | Identifier (e.g. Injury, Fear, SlowEffect) |
- **Flow:**
  1. Modify current MovementSettings[CurrentMovementMode].MaxWalkSpeed *= Multiplier
  2. Start timer for Duration
  3. On timer end: restore original MaxWalkSpeed for this mode

### Protected / Private Functions

#### `OnMovementUpdated (Tick)` → `void`
- **Description:** Called each tick. Updates speed tracking, detects movement start/stop, checks ground state.
- **Flow:**
  1. Get velocity from CharacterMovementComponent
  2. CurrentSpeed = velocity.Size()
  3. OldMoving = bIsMoving
  4. bIsMoving = CurrentSpeed > 10.0
  5. If bIsMoving != OldMoving: fire OnMovementStart or OnMovementStop
  6. Check bIsOnGround from movement component

#### `CalculateFootstep` → `S_FootstepProfile`
- **Description:** Selects the correct footstep sound based on surface and movement mode.
- **Flow:**
  1. Perform line trace from foot location downward
  2. Get surface type from physical material
  3. Look up S_FootstepProfile matching SurfaceType and CurrentMovementMode
  4. If no match: return DefaultFootstepProfile

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnMovementModeChanged` | `E_MovementMode OldMode`, `E_MovementMode NewMode` | `Public` | Fired when movement mode changes |
| `OnPostureChanged` | `E_PostureState OldPosture`, `E_PostureState NewPosture` | `Public` | Fired when posture changes |
| `OnMovementStart` | `none` | `Public` | Fired when the player starts moving from idle |
| `OnMovementStop` | `none` | `Public` | Fired when the player stops moving |
| `OnSprintStateChanged` | `bool bIsSprinting` | `Public` | Fired when sprint state toggles |
| `OnJumped` | `none` | `Public` | Fired when the player jumps |
| `OnLanded` | `float FallVelocity` | `Public` | Fired when the player lands after a fall |
| `OnClimbStarted` | `AActor ClimbableActor` | `Public` | Fired when climbing begins |
| `OnClimbEnded` | `none` | `Public` | Fired when climbing ends |
| `OnFootstep` | `E_MovementMode Mode`, `EPhysicalSurface Surface` | `Public` | Fired on each footstep for audio |

---

## 6. Overridden Events / Custom Events

### Event: `BeginPlay`
- **Description:** Initialises state, caches references, binds to owner's character movement events.
- **Flow:**
  1. Get Owner as Character
  2. Cache CharacterMovementComponent and CapsuleComponent
  3. Bind to Character's OnJumped and OnLanded delegates
  4. Set initial MovementMode = Idle, Posture = Standing
  5. Apply default MovementSettings to movement component

### Event: `Tick (if enabled)`
- **Description:** Updates speed tracking and detects transitions.
- **Flow:**
  1. Call OnMovementUpdated
  2. Check for automatic posture transitions (e.g., falling -> standing on land)

### Custom Event: `OnTakeDamageAffectsMovement`
- **Description:** Listener bound to BPC_HealthSystem.OnDamageTaken.
- **Flow:**
  1. If damage was significant (> 20% health): apply brief movement penalty
  2. Penalty severity scales with damage amount

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[SetMovementMode called] --> B{Valid transition?}
    B -->|No| C[Return]
    B -->|Yes| D[Store PreviousMode]
    D --> E[Set CurrentMode = NewMode]
    E --> F[Apply MovementSettings to CharMoveComp]
    F --> G[Fire OnMovementModeChanged]
    G --> H{NewMode == Sprinting?}
    H -->|Yes| I[Notify BPC_StaminaSystem: StartContinuousDrain]
    H -->|No| J{PreviousMode == Sprinting?}
    J -->|Yes| K[Notify BPC_StaminaSystem: StopContinuousDrain]
    J -->|No| L[Update ABP_GASP blend values]
    I --> L
    K --> L
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `BPC_MovementStateSystem` | `Dispatcher` | `OnMovementModeChanged` -> `ABP_GASP`, `BPC_StaminaSystem`, `BPC_CameraStateLayer` |
| `BPC_MovementStateSystem` | `Dispatcher` | `OnPostureChanged` -> `ABP_GASP`, `BPC_InteractionDetector`, `BP_AudioManager` |
| `BPC_MovementStateSystem` | `Dispatcher` | `OnFootstep` -> `BP_AudioManager` (footstep SFX) |
| `BPC_MovementStateSystem` | `Dispatcher` | `OnJumped` / `OnLanded` -> `BPC_StaminaSystem` (landing drain) |
| `BPC_MovementStateSystem` | `Dispatcher` | `OnSprintStateChanged` -> `BPC_StaminaSystem`, `BPC_CameraStateLayer` (FOV) |
| `External (Input)` | `Direct` | `PC_PlayerController` calls SetMovementMode / SetPosture |
| `BPC_MovementStateSystem` | `Listener` | Binds to `BPC_HealthSystem.OnDamageTaken` for injury penalties |

---

## 9. Validation / Testing Checklist

- [ ] Movement mode changes correctly apply speed/accel values to CharacterMovementComponent
- [ ] Posture changes correctly adjust capsule height and collision
- [ ] Prone requires crouch intermediate transition
- [ ] Sprinting auto-stops when stamina hits 0 (via stamina listener)
- [ ] Movement penalties correctly modify MaxWalkSpeed and restore after duration
- [ ] OnMovementStart/OnMovementStop fire correctly at speed thresholds
- [ ] Footstep profile selection works for all surface types
- [ ] Edge case: Forced transition (knockback) applies impulse regardless of state
- [ ] Edge case: CanTransitionToPosture returns false when ceiling is too low
- [ ] Edge case: Rapid mode switching does not cause animation glitches (blend time enforced)

---

## 10. Reuse Notes

- This component is the central "movement oracle" — other systems query posture/mode instead of polling the CharacterMovementComponent.
- Footstep profiles should be defined in a Data Asset (DA_FootstepProfileTable) for easy content team iteration.
- The component does NOT handle input — that remains in PC_PlayerController.
- For AI characters, a simplified version can expose only Walking and Sprinting modes with no posture system.
- GASP integration: set GASP-specific variables (bStrafing, bSprinting) in the AnimationBlueprint on each mode change.

---

## 11. Multiplayer Networking (Expanded)

### Replication
Movement state is natively handled by `CharacterMovementComponent` replication. `BPC_MovementStateSystem` replicates state enums for non-movement consumers (UI, camera, audio).

| Variable | Condition | Notes |
|----------|-----------|-------|
| `CurrentPosture` | `Replicated Using OnRep_Posture` | Synced posture for other players' animation |
| `CurrentMovementMode` | `Replicated Using OnRep_MovementMode` | Synced mode for audio/camera systems |
| CMC velocity | Native replication | Position/velocity handled by CharacterMovementComponent |

### Server RPCs
| RPC | Direction | Description |
|-----|-----------|-------------|
| `Server_SetMovementMode` | Client→Server | Client requests mode change. Server validates against MovementSettings. |
| `Server_SetPosture` | Client→Server | Client requests posture change. Server validates ceiling clearance. |
| `Server_SetSprinting` | Client→Server | Client toggles sprint. Server checks stamina before authorizing. |

### Authority
- `SetMovementMode` and `SetPosture` check `HasAuthority()` before modifying state.
- Movement penalties (`ApplyMovementPenalty`) are server-authoritative.
- `CanTransitionToPosture` is read-only; clients can call for local prediction.

### Client Prediction
- Posture/mode transitions: client predicts movement locally; server validates.
- Footstep sounds: local calculation based on replicated state.

---

*Blueprint Spec: Movement State System. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework.*