- 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.
14 KiB
Narrative & Progression — Objectives, Dialogue, Cutscenes, Endings
Game: Project Void | Build Phase: 13 Framework Systems: 58_BPC_NarrativeStateSystem, 59_BPC_ObjectiveSystem, 60_BPC_DialoguePlaybackSystem, 61_BPC_DialogueChoiceSystem, 62_BPC_BranchingConsequenceSystem, 63_BPC_TrialScenarioSystem, 64_BPC_CutsceneBridge, 65_BPC_LoreUnlockSystem, 66_DA_NarrativeDataAssets, 67_BP_NarrativeTriggerVolume, 68_BPC_EndingAccumulator
Purpose
Defines the complete narrative structure: objectives, dialogue, cutscenes, lore, and the multiple-ending system. Every narrative system from the framework is demonstrated.
Objective Flow
Main Objectives (Required for Completion)
OBJ_1: "Find a way out of this wing"
├─ Chapter: Entry
├─ Trigger: After opening cutscene
├─ Completion: Reach Nurses Station → interact with exit door
└─ Reward: Unlocks WardA + first checkpoint
OBJ_2: "Restore power to the asylum"
├─ Chapter: WardA
├─ Trigger: Enter WardA
├─ Sub-objectives:
│ ├─ "Find the fusebox" → Locate utility closet
│ ├─ "Reset the circuit breakers" → Solve fusebox puzzle
│ └─ "Access the treatment room" → Unlocked door
├─ Completion: Fusebox puzzle solved + door opened
└─ Reward: Treatment room access (lore + photo collectible)
OBJ_3: "Find the Warden's Key"
├─ Chapter: WardB → Basement
├─ Trigger: Read patient file mentioning "Warden's Master Key"
├─ Sub-objectives:
│ ├─ "Find the morgue" → Navigate WardB to morgue
│ ├─ "Search the morgue drawers" → Solve morgue puzzle
│ └─ "Retrieve the key" → Open correct drawer
├─ Completion: Morgue puzzle solved
└─ Reward: Warden's Key + Void Shard (crematorium access)
OBJ_4: "Confront the truth"
├─ Chapter: WardensOffice
├─ Trigger: Enter Warden's Office
├─ Sub-objectives:
│ ├─ "Read the Warden's journal" → Find and read journal
│ └─ "Face the entity" → Trigger dialogue choice
├─ Completion: Dialogue choice made
└─ Reward: Ending triggered
Optional / Side Objectives
SIDE_1: "Find the survivors"
├─ Trigger: Find first Patient File mentioning "Subject 77 escaped"
├─ Objective: Locate BP_NPC_Survivor in WardB
└─ Reward: Lore, possible ending flag (SurvivorSaved), item gift
SIDE_2: "Collect the memories"
├─ Trigger: Find first Old Photo
├─ Objective: Find all 4 Old Photos
└─ Reward: Achievement "Photographer", lore about asylum history
SIDE_3: "Touch the void"
├─ Trigger: Find first Void Shard
├─ Objective: Collect all 3 Void Shards
└─ Reward: Unlocks Ending C (Sacrifice), achievement "Void Touched"
Objective Data Assets
Each objective has a DA_ObjectiveData (123):
| DA_Objective_* | Type | Prerequisites | Completion | Chapter |
|---|---|---|---|---|
DA_Objective_FindKeys |
Main | None | Has item: Keycard Alpha | WardA |
DA_Objective_RestorePower |
Main | OBJ_1 complete | Flag: PowerRestored | WardA |
DA_Objective_FindWardenKey |
Main | OBJ_2 complete | Has item: Warden's Key | Basement |
DA_Objective_ConfrontTruth |
Main | OBJ_3 complete | DialogueChoice made | WardensOffice |
DA_Objective_FindSurvivors |
Side | Find PatientFile #2 | NPC Interacted | WardB |
DA_Objective_CollectMemories |
Side | Find Photo #1 | All 4 photos found | Any |
DA_Objective_TouchVoid |
Side | Find Shard #1 | All 3 shards found | Any |
Dialogue System
Dialogue Data Assets (DA_Dialogue_*)
| DA_Dialogue_ | Speaker | Lines | Location |
|---|---|---|---|
DA_Dialogue_Intro |
Player (internal monologue) | 3 lines | L_Asylum_Entry — wake up |
DA_Dialogue_SurvivorEncounter |
NPC Survivor | 8 lines + 3 player choices | WardB — hidden room |
DA_Dialogue_VoidWhispers |
Void Entity | 12 lines (random) | Throughout — triggered by stress |
DA_Dialogue_EndingTruth |
Void Entity | 15 lines + 3 player choices | WardensOffice — final |
Dialogue Playback (BPC_DialoguePlaybackSystem)
PlayDialogue(DialogueData)
│
├─ [Queue Lines]
│ └─ For each line in DialogueData.Lines:
│ ├─ Show speaker name (WBP_AccessibilityUI)
│ ├─ Play VO audio (SS_AudioManager.PlayDialogue)
│ ├─ Show subtitle text
│ ├─ Wait(DialogueData.LineDuration)
│ └─ Auto-advance to next line
│
├─ [On Line Change]
│ ├─ BPC_LoreUnlockSystem → auto-unlock if line contains lore reference
│ └─ WBP_NotificationToast → "New Lore Entry: [Name]" if lore unlocked
│
└─ [On Dialogue Complete]
├─ If has choices → BPC_DialogueChoiceSystem.PresentChoices()
└─ If no choices → Broadcast OnDialogueCompleted
Dialogue Choices (BPC_DialogueChoiceSystem)
Example: Final confrontation — "Accept / Resist / Sacrifice"
PresentChoices(ChoiceSet, Options[])
│
├─ [Display] Show 3 buttons on WBP_JournalHorror:
│ ├─ "Accept the entity's offer" (Option A)
│ ├─ "Resist and fight" (Option B)
│ └─ "Sacrifice yourself to seal it" (Option C)
│
├─ [Conditions] Show/hide options based on flags:
│ ├─ Option C (Sacrifice) → requires all 3 VoidShards collected
│ ├─ Option A (Accept) → requires Sanity < 50% (broken enough)
│ └─ Option B (Resist) → always available
│
├─ [Player Selects]
│ │
│ ├─ BPC_BranchingConsequenceSystem.ExecuteConsequence(Choice)
│ │ ├─ Record choice on PS_HorrorPlayerState
│ │ ├─ Set narrative flag: "ChoseAccept" / "ChoseResist" / "ChoseSacrifice"
│ │ └─ BPC_EndingAccumulator.SubmitChoice(Choice)
│ │
│ └─ Play consequence dialogue/cutscene
│
└─ [Consequence Results]
├─ Accept → Entity possesses player → Ending B
├─ Resist → Entity attacks → Chase sequence → Ending A
└─ Sacrifice → Entity sealed → Player dies → Ending C
Cutscene System (BPC_CutsceneBridge)
Cutscenes
| DA_Cutscene_ | Type | Duration | Trigger |
|---|---|---|---|
DA_Cutscene_Opening |
In-engine | 5s | OnPostLogin in L_Asylum_Entry |
DA_Cutscene_ShadeFirstAppearance |
In-engine | 8s | Enter WardB courtyard |
DA_Cutscene_VoidFirstShift |
In-engine | 12s | Enter WardB morgue |
DA_Cutscene_Ending |
Pre-rendered or in-engine | 30-60s | Dialogue choice resolution |
Cutscene Bridge Flow
PlayCutscene(CutsceneData)
│
├─ [Pre-Cutscene]
│ ├─ BPC_StateManager.ForcePushState(Cutscene)
│ ├─ SS_EnhancedInputManager.PopAllContexts → PushContext(UI)
│ └─ WBP_HUDController.HideAllDiegetic()
│
├─ [Play]
│ ├─ If CutsceneData.Type == InEngine:
│ │ ├─ Spawn cutscene actors from CutsceneData.ActorList
│ │ ├─ Sequencer → Play Level Sequence
│ │ └─ Camera transfer → BPC_CameraStateLayer.SetSequenceCamera()
│ │
│ └─ If CutsceneData.Type == PreRendered:
│ ├─ Load video file
│ └─ Play on full-screen media texture
│
├─ [Skip Detection]
│ ├─ Listen for IA_SkipCutscene (Hold for 1.5s)
│ └─ OR: Any key press if CutsceneData.bAllowSkip
│
├─ [Post-Cutscene]
│ ├─ BPC_StateManager.RestorePreviousState()
│ ├─ Restore input context
│ ├─ BPC_NarrativeStateSystem.SetFlag(CutsceneData.CompletionFlag)
│ └─ WBP_HUDController.ShowAllDiegetic()
│
└─ Broadcast OnCutsceneCompleted
Lore System (BPC_LoreUnlockSystem)
Lore entries unlock as the player discovers documents, patient files, and experiences events:
| Lore Entry | Unlock Method | Category |
|---|---|---|
| "The Founding of Blackwood" | Read Journal Page #1 | History |
| "Patient Zero" | Read Patient File #3 | Patients |
| "The Void Breach" | Experience first void shift | Events |
| "Dr. Blackwood's Descent" | Read Warden's Journal | Characters |
| "The Entity's Origin" | Collect all 3 VoidShards | Secrets |
| "Treatment Methods" | Read Patient File #2 | Patients |
| "Asylum Layout" | Find Map item (optional) | World |
Each unlocked entry:
- Appears in WBP_JournalHorror → "Lore" tab
- Grants small stress reduction (-5) when read (understanding = comfort)
- May contain clues for puzzles (e.g., morgue drawer order hidden in Patient File)
Ending Accumulator (BPC_EndingAccumulator)
The system that determines which ending the player receives.
Input Factors
| Factor | Source | Possible Values |
|---|---|---|
| VoidShards collected | BPC_CollectibleTracker | 0, 1, 2, 3 |
| Survivor saved | Narrative flag | true / false |
| Final Sanity | PS_HorrorPlayerState | 0-100 (Low <33, Med 33-66, High >66) |
| Dialogue choice | BPC_DialogueChoiceSystem | Accept / Resist / Sacrifice |
| Playstyle | BPC_PlayerMetricsTracker | Aggressive / Stealthy / Balanced |
| Enemies killed | BPC_ProgressStatTracker | Count (0, 1-5, 6-15, 16+) |
Ending Determination
EvaluateEnding(FinalChoice)
│
├─ [Check Sacrifice Qualification]
│ └─ FinalChoice == Sacrifice AND VoidShards >= 3?
│ ├─ True → ENDING C: "The Seal" (Sacrifice)
│ └─ False → "You lack the void-touched knowledge to seal it."
│ └─ Force player to choose Accept or Resist
│
├─ [Evaluate Accept vs Resist]
│ │
│ ├─ Score "Accept" based on:
│ │ ├─ VoidShards (×10 each)
│ │ ├─ Sanity < 50 (+20)
│ │ ├─ Playstyle == Aggressive (+10)
│ │ └─ EnemiesKilled > 10 (+10)
│ │
│ ├─ Score "Resist" based on:
│ │ ├─ Sanity > 50 (+20)
│ │ ├─ SurvivorSaved (+25)
│ │ ├─ Playstyle == Stealthy (+10)
│ │ └─ EnemiesKilled == 0 (+15 — Pacifist bonus)
│ │
│ └─ Higher score wins:
│ ├─ Accept > Resist → ENDING B: "The Merge" (Become)
│ └─ Resist ≥ Accept → ENDING A: "The Escape" (Flee)
│
├─ [Record Result]
│ ├─ GS_HorrorGameState → SetGlobalFlag("EndingAchieved", EndingTag)
│ ├─ BPC_ProgressStatTracker.RecordEnding(EndingTag)
│ └─ Broadcast OnEndingDetermined(EndingTag)
│
└─ → GM_HorrorGameMode.TriggerEnding(EndingTag)
Ending Variants Summary
| Ending | Name | Conditions | Cutscene Description |
|---|---|---|---|
| A | "The Escape" | Resist + low void influence | Player flees collapsing asylum, emerges into daylight. Free, but haunted. |
| B | "The Merge" | Accept + high void influence | Entity merges with player. Asylum calms. Patients bow. Player's eyes glow void-purple. |
| C | "The Seal" | Sacrifice + 3 VoidShards | Player walks into void. Light fades. Entity sealed. Player's sacrifice remembered in credits. |
Narrative Trigger Volumes (BP_NarrativeTriggerVolume)
| Volume | Level | Trigger | Action |
|---|---|---|---|
BP_NarrativeTrigger_Intro |
L_Asylum_Entry | OnBeginOverlap (player) | Play opening cutscene |
BP_NarrativeTrigger_WardA_Enter |
L_Asylum_WardA | OnBeginOverlap | Set flag "WardA_Entered", update objective |
BP_NarrativeTrigger_VoidFirst |
L_Asylum_WardB (morgue) | OnBeginOverlap | Trigger first void shift event |
BP_NarrativeTrigger_ShadeAppear |
L_Asylum_WardB (courtyard) | OnBeginOverlap | Spawn Shade teaser |
BP_NarrativeTrigger_Ending |
L_Asylum_WardensOffice | OnBeginOverlap | Start final dialogue + ending evaluation |
Narrative Flow Diagram
Player → ENTRY CHAPTER
│ "Dr. Eliza Vance wakes in a padded cell."
│ "Her memory is fragmented. Voices whisper from the dark."
│
▼
Player → WARDA CHAPTER
│ "The asylum is a maze. Patients roam, their minds hollowed."
│ "A security office. A pistol. A guarded corridor."
│ "A nurse's station. A keycard. A way forward."
│
▼
Player → WARDB CHAPTER
│ "The high-security ward. Orderlies patrol. Something watches."
│ "A morgue. A shotgun. A void that shifts reality."
│ "A courtyard. A shadow that moves wrong. First contact."
│ "A chapel. An organ. A melody that opens sealed doors."
│
▼
Player → BASEMENT CHAPTER
│ "Absolute darkness. The Shade hunts. Every sound is death."
│ "Morgue drawers. A puzzle. A key belonging to the warden."
│ "A crematorium. A void shard. Memories of fire."
│
▼
Player → WARDEN'S OFFICE
│ "The warden's final journal. The truth laid bare."
│ "The entity speaks through the mirror."
│ "A choice that determines everything."
│
▼
┌─────────┼─────────┐
▼ ▼ ▼
ENDING A ENDING B ENDING C
Escape Merge Sacrifice
Notes for Expansion
- Add branching mid-game: saving survivor opens alternate route through WardB
- Add multiple NPC dialogues: more survivors with different agendas
- Add mystery documentation: some patient files have blacked-out text → find "decoder lens" item
- Add trial scenarios: timed escape sequences where player must reach exit before Shade
- Add New Game+ lore: after first completion, new documents appear that explain the entity's origin
- Add voice acting support: hook VO audio clips to dialogue lines
- Add dialogue history: player can review past dialogue in journal
- Multiplayer: narrative flags must be server-authoritative and replicated to joining clients
Narrative & Progression for Project Void. See GAMEINDEX.md for full game structure. See 07-narrative/ for framework narrative system specs.