# Game Core — PC_HorrorController, PS_HorrorPlayerState, GS_HorrorGameState

**Game:** Project Void | **Build Phase:** 1

---

This document covers the 3 remaining Core class children:

| Asset | Parent | Purpose |
|-------|--------|---------|
| `PC_HorrorController` | `PC_CoreController` (or `PlayerController`) | Horror-specific input routing, camera, UI injection |
| `PS_HorrorPlayerState` | `PS_CorePlayerState` (or `PlayerState`) | Horror player data: fear history, deaths, sanity |
| `GS_HorrorGameState` | `GS_CoreGameState` (or `GameStateBase`) | Shared session data: global flags, void state, timer |

---

## PC_HorrorController — Player Controller

**Asset Path:** `Content/Game/Core/PC_HorrorController.uasset`

### Purpose

Routes player input through `SS_EnhancedInputManager`, manages camera shake, hit feedback, and UI injection for horror-specific screen effects.

### Creation Steps

#### Step 1 — Create Blueprint

```
Content Browser → Game/Core/
  Right-click → Blueprint Class
  Parent Class: PlayerController (or PC_CoreController if it exists in framework)
  Name: PC_HorrorController
```

#### Step 2 — Variables

| Variable | Type | Default | Category | Purpose |
|----------|------|---------|----------|---------|
| `bGameInputEnabled` | Boolean | `true` | `Input` | Master input toggle (off during cutscenes/death) |
| `CameraShakeIntensity` | Float | `1.0` | `Camera` | Global scalar for camera shake effects |
| `bHeartbeatEnabled` | Boolean | `true` | `UI` | Toggle diegetic heartbeat indicator |

#### Step 3 — Wire Event BeginPlay

```
Event BeginPlay
   │
   ├─ Set Input Mode Game Only (mouse captured, no cursor)
   ├─ Set Show Mouse Cursor → false
   │
   ├─ [Get Enhanced Input Subsystem]
   │    └─ Get Engine Subsystem → UEnhancedInputLocalPlayerSubsystem
   │
   ├─ [Bind to Game Phase Changes]
   │    ├─ Get GI_HorrorGame → Bind to OnGamePhaseChanged
   │    │    └─ On Paused/Cutscene/DeathLoop → Set bGameInputEnabled = false
   │    │    └─ On InGame → Set bGameInputEnabled = true
   │    │
   │    └─ SS_UIManager → Bind to OnInputModeChanged
   │         └─ Update input mode + cursor visibility
   │
   └─ [Start Heartbeat Effect]
        └─ (Timer: every 0.5s) Get BPC_StateManager → GetHeartRate()
             ├─ Normal (60-80) → slight controller pulse
             ├─ Elevated (80-110) → stronger pulse
             └─ Critical (110+) → rapid, intense pulse + screen edge red
```

#### Step 4 — Override: Setup Input Component

```
Setup Input Component
   │
   ├─ Parent: Setup Input Component
   │
   └─ (Input actions are mapped via SS_EnhancedInputManager and IMC_ contexts
       — no manual binding needed here. The subsystem handles context pushes.)
```

#### Step 5 — Functions

| Function | Inputs | Outputs | Description |
|----------|--------|---------|-------------|
| `PlayCameraShake` | ShakeClass, Scale: Float | — | `ClientStartCameraShake(ShakeClass, Scale × CameraShakeIntensity)` |
| `SetGameInputEnabled` | bEnabled: Boolean | — | Master toggle — disables all input processing |
| `OpenPauseMenu` | — | — | `SS_UIManager.PushMenu(PauseMenu)` — bound to IA_PauseMenu |
| `GetInteractionSystem` | — | `BPC_InteractionDetector*` | Quick access to interaction component on pawn |

### Communications With

| Target | Method | Why |
|--------|--------|-----|
| `SS_EnhancedInputManager` | Direct | Context management, input state queries |
| `SS_UIManager` | Direct + Dispatcher | Input mode coordination |
| `GI_HorrorGame` | Dispatcher | Phase change response |
| `BPC_StateManager` | Direct (on pawn) | Heart rate for haptic feedback |
| `BP_HorrorPlayerCharacter` | Owned Pawn | Camera shake routing |

---

## PS_HorrorPlayerState — Player State

**Asset Path:** `Content/Game/Core/PS_HorrorPlayerState.uasset`

### Purpose

Tracks player-specific data that persists across level transitions and death/respawn. Custom data: fear history, death count per chapter, sanity tier.

### Creation Steps

#### Step 1 — Create Blueprint

```
Content Browser → Game/Core/
  Right-click → Blueprint Class
  Parent Class: PlayerState (or PS_CorePlayerState if it exists in framework)
  Name: PS_HorrorPlayerState
```

#### Step 2 — Variables

| Variable | Type | Default | Category | Purpose |
|----------|------|---------|----------|---------|
| `SanityTier` | Integer | `100` | `Player` | 100=Calm, 75=Uneasy, 50=Disturbed, 25=Breaking, 0=Catatonic |
| `FearHistory` | Array\<GameplayTag\> | Empty | `Player` | Tracks fear triggers experienced (for ending calculation) |
| `DeathsThisChapter` | Integer | `0` | `Player` | Resets per chapter; used for difficulty scaling |
| `TotalCollectiblesFound` | Integer | `0` | `Player` | Across all levels |
| `PlaystyleTag` | GameplayTag | `Framework.Playstyle.Balanced` | `Player` | Aggressive / Stealthy / Explorer / Balanced |
| `PlayerName` | Text | "Dr. Eliza Vance" | `Player` | Display name (set by GM on spawn) |

#### Step 3 — Functions

| Function | Inputs | Outputs | Description |
|----------|--------|---------|-------------|
| `RecordFearTrigger` | TriggerTag: GameplayTag | — | Adds tag to FearHistory, notifies BPC_EndingAccumulator |
| `SetSanityTier` | NewTier: Int | — | Updates sanity; clamps 0–100; fires OnSanityChanged dispatcher |
| `IncrementDeaths` | — | — | DeathsThisChapter++, fires OnDeathCountChanged |
| `GetPlaystyle` | — | GameplayTag | Returns PlaystyleTag |
| `GetSanityPercentage` | — | Float | Returns SanityTier as 0.0–1.0 float |

### Replication Notes (Multiplayer)

All variables should be marked `Replicated` with `ReplicatedUsing = OnRep_`.

---

## GS_HorrorGameState — Game State

**Asset Path:** `Content/Game/Core/GS_HorrorGameState.uasset`

### Purpose

Shared session state visible to all players (server + all clients in multiplayer). In single-player, serves as the authoritative session data store.

### Creation Steps

#### Step 1 — Create Blueprint

```
Content Browser → Game/Core/
  Right-click → Blueprint Class
  Parent Class: GameStateBase (or GS_CoreGameState if it exists in framework)
  Name: GS_HorrorGameState
```

#### Step 2 — Variables

| Variable | Type | Default | Category | Purpose |
|----------|------|---------|----------|---------|
| `ActiveChapterTag` | GameplayTag | — | `Session` | Current chapter/level identifier |
| `bIsVoidActive` | Boolean | `false` | `Session` | True when any player is in void space |
| `GlobalFearLevel` | Float | `0.0` | `Session` | 0.0–1.0 — ambient fear level affecting all systems |
| `SessionPlaytime` | Float | `0.0` | `Session` | Accumulated playtime in seconds |
| `bEndingSequenceActive` | Boolean | `false` | `Session` | True during ending cutscene (blocks all gameplay) |
| `GlobalFlags` | Map\<GameplayTag, Boolean\> | Empty | `Session` | Chapter-complete flags, puzzle-solved flags, etc. |

#### Step 3 — Event Graph

```
Event BeginPlay
   │
   ├─ Set GlobalFearLevel = 0.0
   │
   └─ [Start Playtime Timer]
        └─ Set Timer (1.0s, Looping) → SessionPlaytime += 1.0
             └─ Only increment when GamePhase == InGame

Event Tick (or Timer)
   │
   ├─ Get GI_HorrorGame → CurrentGamePhase
   │    └─ If InGame: SessionPlaytime += DeltaTime
   │    └─ Else: don't accumulate
   │
   └─ [Fear Decay]
        ├─ GlobalFearLevel > 0.0?
        │    └─ True: GlobalFearLevel -= 0.001 per second (slow decay)
        │              └─ Clamp to 0.0 minimum
        └─ Broadcast OnGlobalFearChanged(GlobalFearLevel)
```

#### Step 4 — Functions

| Function | Inputs | Outputs | Description |
|----------|--------|---------|-------------|
| `SetGlobalFlag` | FlagTag: GameplayTag, Value: Boolean | — | Sets session flag + broadcasts OnFlagChanged |
| `GetGlobalFlag` | FlagTag: GameplayTag | Boolean | Returns flag value (false if not found) |
| `AddFearLevel` | Amount: Float | — | GlobalFearLevel += Amount, clamped 0.0–1.0 |
| `SetVoidActive` | bActive: Boolean | — | Sets bIsVoidActive, broadcasts OnVoidStateChanged |
| `GetSessionTimeFormatted` | — | Text | Returns "HH:MM:SS" formatted playtime |
| `ResetSession` | — | — | Resets all variables (called by New Game) |

#### Step 5 — Event Dispatchers

| Dispatcher | Parameters | Fired When |
|------------|-----------|------------|
| `OnFlagChanged` | FlagTag: GameplayTag, Value: Boolean | Any global flag changes |
| `OnGlobalFearChanged` | FearLevel: Float | GlobalFearLevel updates |
| `OnVoidStateChanged` | bIsVoidActive: Boolean | Void space active/inactive |
| `OnChapterChanged` | ChapterTag: GameplayTag | Active chapter changes |
| `OnSessionReset` | — | Session data wiped (New Game) |

---

## Combined Wiring — All Core Classes Together

```
[GI_HorrorGame.Init]
   │
   ├─ Initialize subsystems (Audio, Settings, Input)
   └─ OpenLevel → L_SplashScreen
        │
        └─ L_SplashScreen → auto-advance → L_MainMenu
             │
             └─ [Player clicks New Game]
                  │
                  └─ GM_HorrorGameMode starts new session
                       │
                       ├─ Spawn PS_HorrorPlayerState (fresh data)
                       ├─ Spawn GS_HorrorGameState (fresh session)
                       │
                       ├─ Spawn BP_HorrorPlayerCharacter (pawn)
                       │    └─ Auto-added components:
                       │         ├─ BPC_HealthSystem (100 HP)
                       │         ├─ BPC_StaminaSystem (100 stam)
                       │         ├─ BPC_StressSystem (0 stress)
                       │         ├─ BPC_MovementStateSystem
                       │         ├─ BPC_HidingSystem
                       │         ├─ BPC_EmbodimentSystem
                       │         ├─ BPC_CameraStateLayer
                       │         ├─ BPC_PlayerMetricsTracker
                       │         ├─ BPC_InteractionDetector
                       │         ├─ BPC_InventorySystem
                       │         ├─ BPC_EquipmentSlotSystem
                       │         ├─ BPC_ActiveItemSystem
                       │         ├─ BPC_ConsumableSystem
                       │         ├─ BPC_StateManager
                       │         └─ [others as needed]
                       │
                       ├─ Spawn PC_HorrorController
                       │    ├─ Bind input contexts
                       │    └─ Set Input Mode Game Only
                       │
                       └─ Create WBP_GameHUDController
                            ├─ WBP_DiegeticHUDFrame (health, stress, stamina)
                            ├─ WBP_InteractionPromptDisplay
                            ├─ WBP_ObjectiveDisplay
                            ├─ WBP_NotificationToast
                            ├─ WBP_ScreenEffectController
                            └─ WBP_AccessibilityUI (subtitles)
```

---

## Blueprint Wiring Checklist

### PC_HorrorController
- [ ] Create BP child of PlayerController named `PC_HorrorController`
- [ ] Add 3 variables (bGameInputEnabled, CameraShakeIntensity, bHeartbeatEnabled)
- [ ] Wire `Event BeginPlay` — input mode, phase bindings, heartbeat timer
- [ ] Add `PlayCameraShake`, `SetGameInputEnabled`, `OpenPauseMenu`, `GetInteractionSystem`

### PS_HorrorPlayerState
- [ ] Create BP child of PlayerState named `PS_HorrorPlayerState`
- [ ] Add 5 variables (SanityTier, FearHistory, DeathsThisChapter, TotalCollectiblesFound, PlaystyleTag)
- [ ] Add `RecordFearTrigger`, `SetSanityTier`, `IncrementDeaths`, `GetPlaystyle`, `GetSanityPercentage`
- [ ] Mark variables Replicated for multiplayer

### GS_HorrorGameState
- [ ] Create BP child of GameStateBase named `GS_HorrorGameState`
- [ ] Add 6 variables (ActiveChapterTag, bIsVoidActive, GlobalFearLevel, SessionPlaytime, bEndingSequenceActive, GlobalFlags)
- [ ] Add 4 event dispatchers (OnFlagChanged, OnGlobalFearChanged, OnVoidStateChanged, OnChapterChanged, OnSessionReset)
- [ ] Wire `Event BeginPlay` — fear decay timer
- [ ] Add `SetGlobalFlag`, `GetGlobalFlag`, `AddFearLevel`, `SetVoidActive`, `GetSessionTimeFormatted`, `ResetSession`

---

## Notes for Expansion

- The `PS_HorrorPlayerState.SanityTier` maps directly to `BPC_StressSystem` — they should sync via dispatcher
- `GS_HorrorGameState.GlobalFearLevel` could drive `BPC_PacingDirector` to spawn more/less enemies
- In a multiplayer game, `GS_HorrorGameState` is the server-authoritative source for all session data
- Consider adding `PS_HorrorPlayerState.FearHistory` as a debug visualization in `WBP_DebugMenu`
- The heartbeat haptic effect in `PC_HorrorController` requires gamepad support — add a fallback for KB+M

---

*Core controller + state classes for Project Void. See [GAMEINDEX.md](GAMEINDEX.md) for full game structure. See [05_GM_CoreGameMode.md](../blueprints/01-core/05_GM_CoreGameMode.md) and [06_GS_CoreGameState.md](../blueprints/01-core/06_GS_CoreGameState.md) for parent specs.*
