- 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.
13 KiB
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.SanityTiermaps directly toBPC_StressSystem— they should sync via dispatcher GS_HorrorGameState.GlobalFearLevelcould driveBPC_PacingDirectorto spawn more/less enemies- In a multiplayer game,
GS_HorrorGameStateis the server-authoritative source for all session data - Consider adding
PS_HorrorPlayerState.FearHistoryas a debug visualization inWBP_DebugMenu - The heartbeat haptic effect in
PC_HorrorControllerrequires gamepad support — add a fallback for KB+M
Core controller + state classes for Project Void. See GAMEINDEX.md for full game structure. See 05_GM_CoreGameMode.md and 06_GS_CoreGameState.md for parent specs.