- 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.
11 KiB
Game Core — GM_HorrorGameMode (Game Mode)
Game: Project Void | Asset: GM_HorrorGameMode | Parent: GM_CoreGameMode
Asset Path: Content/Game/Core/GM_HorrorGameMode.uasset
Build Phase: 1 | Framework System: 05_GM_CoreGameMode
Purpose
The game-specific Game Mode. Inherits all core rules from GM_CoreGameMode (player spawn, chapter transitions, death handling, pause control). This BP child configures the horror-specific pawn, controller, state classes, and adds game-over routing, void-space transitions, and ending triggers.
Dependencies
| System | Type | Why |
|---|---|---|
GM_CoreGameMode (05) |
Parent class | Inherits TransitionToChapter, HandlePlayerDead, etc. |
BP_HorrorPlayerCharacter |
Spawned | Default pawn class |
PC_HorrorController |
Spawned | Default player controller |
PS_HorrorPlayerState |
Managed | Default player state |
GS_HorrorGameState |
Managed | Default game state |
WBP_GameHUDController |
Created | Default HUD class |
BPC_DeathHandlingSystem (39) |
Dispatcher | Receive death events |
BPC_EndingAccumulator (68) |
Dispatcher | Trigger ending evaluation |
BPC_NarrativeStateSystem (58) |
Interface | Chapter flag coordination |
SS_SaveManager (35) |
Direct | Checkpoint data on level transitions |
Creation Steps
Step 1 — Create Blueprint Child
Content Browser → Game/Core/
Right-click → Blueprint Class
Parent Class: GM_CoreGameMode (from Framework/Core/)
Name: GM_HorrorGameMode
Step 2 — Configure Class Defaults
Open GM_HorrorGameMode → Class Defaults → Classes section:
| Property | Value | Notes |
|---|---|---|
Default Pawn Class |
BP_HorrorPlayerCharacter |
GASP-based horror player |
Player Controller Class |
PC_HorrorController |
Custom input routing |
Player State Class |
PS_HorrorPlayerState |
Player data |
Game State Class |
GS_HorrorGameState |
Shared session data |
HUD Class |
WBP_GameHUDController |
Horror-themed HUD |
Default Player Name |
"Dr. Eliza Vance" | In-game display name |
bPauseAllowed |
true (default) |
Set false during scripted sequences |
Step 3 — Add Game-Specific Variables
| Variable | Type | Default | Category | Purpose |
|---|---|---|---|---|
bVoidSpaceActive |
Boolean | false |
Game |
True when player is in void/alt-death space |
bEndingTriggered |
Boolean | false |
Game |
Prevents multiple ending triggers |
GameDifficulty |
Float | 1.0 |
Game |
0.5–2.0 scalar for all difficulty systems |
HorrorLevelNames |
Map (GameplayTag → Name) | — | Levels |
ChapterTag → Level name for transitions |
Step 4 — Populate HorrorLevelNames Map
| Key (GameplayTag) | Value (Level Name) | Description |
|---|---|---|
Chapter.Entry |
L_Asylum_Entry |
Tutorial zone |
Chapter.WardA |
L_Asylum_WardA |
First major area |
Chapter.WardB |
L_Asylum_WardB |
Second major area |
Chapter.Basement |
L_Asylum_Basement |
Dark horror area |
Chapter.VoidSpace |
L_Asylum_VoidSpace |
Reality-shift zone |
Chapter.WardensOffice |
L_Asylum_WardensOffice |
Climax |
Chapter.Ending |
L_Ending_Truth |
Final cutscene |
Chapter.Credits |
L_Credits |
Credits roll |
Step 5 — Wire Event Graph
Override: Event OnPostLogin
Event OnPostLogin (NewPlayer: PlayerController*)
│
├─ Parent: Event OnPostLogin (call parent first)
│
├─ Get GI_HorrorGame → GetSessionFlag("HasSeenIntro")?
│ ├─ False → (first time in level)
│ │ ├─ Set bPauseAllowed = false
│ │ ├─ BPC_CutsceneBridge → PlayCutscene("Opening")
│ │ │ └─ Player wakes in padded cell (3-5 second sequence)
│ │ ├─ GI_HorrorGame → SetSessionFlag("HasSeenIntro", true)
│ │ ├─ BPC_TutorialSystem → StartTutorial("Controls")
│ │ └─ Set bPauseAllowed = true (after cutscene)
│ │
│ └─ True → (returning from death, reload, or later visit)
│ └─ BPC_PlayerRespawnSystem → RestoreState()
│ └─ Restore health, inventory, position from last checkpoint
│
├─ BPC_NarrativeStateSystem → SetChapterFlag("Entry")
└─ GI_GameFramework → SetGamePhase(InGame)
Override: HandlePlayerDead
HandlePlayerDead (CalledBy: BPC_DeathHandlingSystem dispatcher)
│ Player: Pawn, DeathCause: E_DeathCause, KillerLocation: Vector
│
├─ Set bPauseAllowed = false
├─ Increment GI_HorrorGame.TotalDeaths
│
├─ [Check Void Space Conditions]
│ ├─ GI_HorrorGame → GetSessionFlag("VoidSpaceVisited")? → Branch
│ │ ├─ False AND DeathCause == "Void"?
│ │ │ └─ True:
│ │ │ ├─ Set bVoidSpaceActive = true
│ │ │ ├─ BPC_AltDeathSpaceSystem → EnterVoidSpace()
│ │ │ ├─ Transition To Chapter (Chapter.VoidSpace)
│ │ │ └─ Return (void space handles own exit)
│ │ │
│ │ └─ False → [Normal Death — Respawn]
│ │
│ └─ [Normal Death Flow]
│ │
│ ├─ BPC_PersistentCorpseSystem → Leave Corpse (Pawn, DeathCause)
│ ├─ BPC_RunHistoryTracker → Log Death (DeathCause, CurrentChapterTag)
│ │
│ ├─ BPC_PlayerRespawnSystem → Get Respawn Chapter
│ │ └─ Returns last checkpoint's chapter tag
│ │
│ ├─ BPC_PersistentWorldStateRecorder → Save World State
│ │ └─ Capture door states, item pickup flags, enemy states
│ │
│ ├─ SS_SaveManager → Create Auto Save ("DeathRespawn")
│ │
│ ├─ Transition To Chapter (RespawnChapterTag)
│ │ └─ Parent function loads the level
│ │
│ └─ (On level loaded) BPC_PlayerRespawnSystem → RestoreState()
│ ├─ Restore inventory (minus items lost on death)
│ ├─ Restore health to checkpoint value
│ └─ Restore world state (doors, items, enemies)
│
└─ Set bPauseAllowed = true
Override: TriggerEnding
TriggerEnding (EndingTag: GameplayTag)
│
├─ bEndingTriggered? → True → Return (already triggered)
│
├─ Set bEndingTriggered = true
├─ Set bPauseAllowed = false
│
├─ GI_HorrorGame → ActiveEndingTag = EndingTag
│
├─ BPC_EndingAccumulator → Evaluate Ending (EndingTag)
│ └─ Returns: EndingResult (which final cinematic to play)
│
├─ BPC_CutsceneBridge → Play Final Cutscene (EndingResult)
│ └─ Cutscene duration: 30-60 seconds
│
├─ (After cutscene completes):
│ ├─ SS_AchievementSystem → Unlock ("CompletedGame")
│ ├─ SS_AchievementSystem → Unlock (EndingTag-specific achievement)
│ └─ BPC_ProgressStatTracker → Log Completion (EndingTag, playtime, deaths)
│
├─ Transition To Chapter (Chapter.Credits)
└─ (After credits) OpenLevel → "L_MainMenu"
Custom Function: GetDifficultyScalar
GetDifficultyScalar() → Float
│
├─ Return GameDifficulty × GI_HorrorGame → FearIntensityMultiplier
└─ Clamp result between 0.5 and 2.0
Custom Function: IsChapterUnlocked
IsChapterUnlocked (ChapterTag: GameplayTag) → Boolean
│
├─ BPC_NarrativeStateSystem → GetChapterFlag (ChapterTag) → Check "IsCompleted"
└─ Return result
Key Differences from GM_CoreGameMode Parent
| Aspect | GM_CoreGameMode (Framework) | GM_HorrorGameMode (Game) |
|---|---|---|
| Default Pawn | Not set (abstract) | BP_HorrorPlayerCharacter |
| Player Controller | PC_CoreController |
PC_HorrorController |
| Player State | PS_CorePlayerState |
PS_HorrorPlayerState |
| Game State | GS_CoreGameState |
GS_HorrorGameState |
| HUD | WBP_HUDController |
WBP_GameHUDController |
| Death Handling | Generic respawn | Void space branching, corpse persistence |
| Level Map | Abstract | HorrorLevelNames map (tag → level name) |
| Post-login | Generic setup | Opening cutscene + tutorial trigger |
Level Override Configuration
When creating each .umap level, open World Settings:
Window → World Settings
Game Mode Override: GM_HorrorGameMode
(This ensures all levels use the horror game mode)
Optionally, set chapter-specific settings per level in World Settings:
| Level | World Settings Override |
|---|---|
L_Asylum_Entry |
bPauseAllowed: true (after cutscene) |
L_Asylum_VoidSpace |
bPauseAllowed: false (pressing ESC shows "No escape from the void") |
L_MainMenu |
bPauseAllowed: false (main menu has its own pause equivalent via UI) |
L_Ending_Truth |
bPauseAllowed: false (cutscene lock) |
Blueprint Wiring Checklist
- Create BP child of
GM_CoreGameModenamedGM_HorrorGameModeinGame/Core/ - Set all 5 Default Classes in Class Defaults
- Add 4 game-specific variables (bVoidSpaceActive, bEndingTriggered, GameDifficulty, HorrorLevelNames)
- Populate
HorrorLevelNamesmap with all 8 chapter → level mappings - Override
Event OnPostLogin→ opener cutscene + tutorial - Override
HandlePlayerDead→ void space branch + corpse + respawn - Override
TriggerEnding→ cutscene → credits → menu - Add
GetDifficultyScalarfunction - Add
IsChapterUnlockedfunction - Set
GM_HorrorGameModeas GameMode Override in each level's World Settings
Communications With
| Target System | Method | Why |
|---|---|---|
GI_HorrorGame |
GetGameInstance → Cast to GI_HorrorGame | Session data, fear intensity, ending tag |
BP_HorrorPlayerCharacter |
Spawned by engine | Player pawn |
PC_HorrorController |
Spawned by engine | Input routing |
BPC_DeathHandlingSystem |
Dispatcher (receives) | Death events |
BPC_AltDeathSpaceSystem |
Direct | Void space entry |
BPC_PlayerRespawnSystem |
Direct | Respawn restore |
BPC_CutsceneBridge |
Direct | Play/end cutscenes |
BPC_EndingAccumulator |
Direct | Evaluate ending |
BPC_TutorialSystem |
Direct | Start tutorials |
SS_SaveManager |
GetSubsystem | Auto-save on death/respawn |
SS_AchievementSystem |
GetSubsystem | Unlock achievements on completion |
Notes for Expansion
- To add permadeath mode: override
HandlePlayerDead→ skip void space → wipe save → restart - To add co-op support: the horror game mode would need to handle multiple player spawns and sync void space
- To add New Game+: in
Event OnPostLogin, checkbIsNewGamePlusflag → increaseGameDifficulty→ spawn harder enemies - The
HorrorLevelNamesmap approach allows designers to reorder chapters without touching blueprint logic - Consider adding
OnPreDeathandOnPostRespawnevent dispatchers for other systems to bind
GM_HorrorGameMode — Core game mode for Project Void. See GAMEINDEX.md for full game structure. See 05_GM_CoreGameMode.md for parent class spec.