Files
UE5-Modular-Game-Framework/docs/game/core-controller-state.md
Lefteris Notas 040db37720 Add UI Overrides and Weapons Index documentation for Project Void
- Created ui-overrides.md detailing game-specific Widget Blueprint overrides, including purpose, widget index, visual styling, and accessibility requirements.
- Established weapons-index.md outlining all held weapon actors, including their components, logic, and comparisons for gameplay mechanics.
2026-05-21 22:27:57 +03:00

309 lines
13 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.

# 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 0100; fires OnSanityChanged dispatcher |
| `IncrementDeaths` | — | — | DeathsThisChapter++, fires OnDeathCountChanged |
| `GetPlaystyle` | — | GameplayTag | Returns PlaystyleTag |
| `GetSanityPercentage` | — | Float | Returns SanityTier as 0.01.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.01.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.01.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.*