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.
This commit is contained in:
Lefteris Notas
2026-05-21 22:27:57 +03:00
parent c515920eea
commit 040db37720
17 changed files with 6795 additions and 43 deletions

View File

@@ -0,0 +1,387 @@
# Save System & Checkpoints — Persistence, Death, Void Space
**Game:** Project Void | **Build Phases:** 15
**Framework Systems:** 35_SS_SaveManager, 36_I_Persistable, 37_BP_Checkpoint, 38_BPC_AltDeathSpaceSystem, 39_BPC_DeathHandlingSystem, 40_BPC_PersistentCorpseSystem, 41_BPC_PersistentWorldStateRecorder, 42_BPC_PlayerRespawnSystem, 43_BPC_RunHistoryTracker
---
## Purpose
Defines the complete save/load, checkpoint, death handling, and void space systems. Every framework save system is demonstrated.
---
## Save Slots & Save Manager
### SS_SaveManager Configuration
```
SS_SaveManager (35) — initialized by GI_HorrorGame on boot
Save Slots:
├─ SaveSlot_1 → AutoSave (checkpoint-based)
├─ SaveSlot_2 → QuickSave (pause menu quick save)
├─ SaveSlot_3 → ManualSave (pause menu manual save)
└─ (Up to 10 slots configurable via DA_SaveSettings)
Save Structure (per slot):
├─ SaveHeader
│ ├─ SlotName (Text)
│ ├─ TimeStamp (DateTime)
│ ├─ PlaytimeSeconds (Float)
│ ├─ ChapterTag (GameplayTag)
│ ├─ PlayerTransform (Transform)
│ ├─ Thumbnail (Texture2D*) — screenshot at save time
│ └─ VersionNumber (Int32)
├─ PlayerState (PS_HorrorPlayerState)
│ ├─ Health (Float)
│ ├─ Stamina (Float)
│ ├─ Stress (Float)
│ ├─ InventorySlots (Array<FInventorySlot>)
│ ├─ AmmoPool (Map<GameplayTag, Int32>)
│ ├─ EquipmentState (Map<GameplayTag, DA_ItemData*>)
│ ├─ NarrativeFlags (Map<GameplayTag, Boolean>)
│ ├─ Objectives (Array<ObjectiveState>)
│ ├─ DeathsThisChapter (Int32)
│ └─ FearHistory (Array<GameplayTag>)
└─ WorldState (BPC_PersistentWorldStateRecorder)
├─ DoorStates (Array<FDoorState>) — position, locked, barricaded
├─ PickupStates (Array<FPickupState>) — collected or not
├─ EnemyStates (Array<FEnemyState>) — alive/dead, position
├─ PuzzleStates (Array<FPuzzleState>) — solved/unsolved, progress
└─ GlobalFlags (Map<GameplayTag, Boolean>)
```
### Save Trigger Points
| Trigger | Save Type | When |
|---------|----------|------|
| `BP_Checkpoint` overlap | AutoSave (Slot 1) | Player touches checkpoint |
| `PauseMenu → Save` | ManualSave (Slot 3) | Player manually saves |
| `GM_HorrorGameMode.HandlePlayerDead` | AutoSave (Slot 1) | Death → respawn |
| `TransitionToChapter` | AutoSave (Slot 1) | Level transition |
| `GI_HorrorGame.QuitToDesktop` | QuickSave (Slot 2) | Clean shutdown |
| `SS_SettingsSystem.OnSettingsChanged` | — | Settings saved separately (not slot-based) |
---
## Checkpoint System
### BP_Checkpoint Actors
| Checkpoint | Level | Location | Features |
|-----------|-------|----------|----------|
| `BP_Checkpoint_SafeRoom` | Entry, WardA, WardB, Basement | Safe rooms | Full restore, safe zone, stress decay |
| `BP_Checkpoint_Mirror` | WardA (Nurses Station) | Thematic | Also stores reflection (visual) |
| `BP_Checkpoint_BasementGate` | Basement | Before Shade zone | Warning: "Danger ahead" |
| `BP_Checkpoint_VoidThreshold` | Void Space | One-time save | Disappears after first use |
### Checkpoint Blueprint Flow
```
BP_Checkpoint — Event ActorBeginOverlap (Player)
├─ [Already Activated?]
│ └─ bActivated AND not bReusable? → Return
├─ [Activation]
│ ├─ Set bActivated = true
│ ├─ Play activation effect:
│ │ ├─ Light pulse (warm amber glow)
│ │ ├─ Sound: soft chime
│ │ └─ Particle: floating dust motes
│ │
│ ├─ [Save State]
│ │ ├─ SS_SaveManager.CreateAutoSave(SlotName = ChapterTag)
│ │ ├─ BPC_PersistentWorldStateRecorder.SaveWorldState()
│ │ └─ Store player transform + all state data
│ │
│ ├─ [Restore Player]
│ │ ├─ BPC_HealthSystem.RestoreFullHealth()
│ │ ├─ BPC_StaminaSystem.RestoreFullStamina()
│ │ └─ (Stress is NOT restored — checkpoint only saves, doesn't heal stress)
│ │
│ ├─ [Notify Player]
│ │ ├─ WBP_NotificationToast.Show("Checkpoint Reached")
│ │ ├─ WBP_ScreenEffectController.PulseVignette(0.3s)
│ │ └─ SS_AudioManager.PlaySFX("checkpoint")
│ │
│ └─ [Update Run History]
│ ├─ BPC_RunHistoryTracker.RecordCheckpoint(ChapterTag)
│ └─ Set GS_HorrorGameState → SaveGlobalFlag("Checkpoint_Entered", true)
└─ (Safe Room only) → BPC_StressSystem.StartRapidStressDecay()
└─ 5× normal decay rate while in safe room
```
---
## Death Handling System
### Death Flow (Complete)
```
BPC_HealthSystem.Health <= 0
├─ BPC_DeathHandlingSystem.TriggerDeath(DeathCause, Killer)
├─ [Immediate Effects]
│ ├─ BPC_StateManager.ForcePushState(Death)
│ ├─ Play death animation montage (GASP)
│ │ └─ Duration: 2.0 seconds
│ ├─ BPC_CameraStateLayer.SetDeathCamera()
│ │ └─ Camera falls to floor, tilts, fades to black
│ ├─ WBP_ScreenEffectController.PlayDeathFade()
│ │ └─ Red vignette fades in → black
│ └─ SS_AudioManager.TriggerDeathAudio(DeathCause)
│ ├─ SFX: heartbeat flatline
│ ├─ Music: fade out over 2s
│ └─ Ambience: dampen to near-silence
├─ [Death Classification]
│ │
│ ├─ Determine DeathCause from damage info:
│ │ ├─ "Physical" → Patient/Orderly melee
│ │ ├─ "Void" → Shade touch, void fall
│ │ ├─ "Environmental" → Falling debris, trap
│ │ └─ "Self" → (future: suicide? sanity loss?)
│ │
│ ├─ DeathCause == "Void" AND NOT GI_HorrorGame.GetSessionFlag("VoidSpaceVisited")?
│ │ ├─ True → [VOID DEATH] — redirect to void space (see below)
│ │ └─ False → [NORMAL DEATH] — respawn at checkpoint
│ │
│ └─ [Normal Death → Respawn]
│ │
│ ├─ Increment PS_HorrorPlayerState.DeathsThisChapter
│ ├─ Increment GI_HorrorGame.TotalDeaths
│ ├─ BPC_RunHistoryTracker.LogDeath(DeathCause, Location, Time)
│ │
│ ├─ BPC_PersistentCorpseSystem.LeaveCorpse(Location, DeathCause)
│ │ └─ Spawns ragdoll corpse at death location
│ │ └─ Persists until level transition or save clear
│ │
│ ├─ [Lose Items?]
│ │ ├─ Check DA_GameSettings.bLoseItemsOnDeath
│ │ └─ If true: remove random 1-3 non-key items from inventory
│ │
│ ├─ [Show Death Screen]
│ │ └─ WBP_DeathScreen.ShowDeathScreen(DeathCause, bVoidQualified=false)
│ │ └─ Player clicks "Continue" → respawn
│ │
│ ├─ [Respawn]
│ │ ├─ SS_SaveManager.LoadSaveSlot(SaveSlot_1) // auto-save
│ │ ├─ BPC_PlayerRespawnSystem.RespawnAtCheckpoint()
│ │ │ ├─ Load last checkpoint location
│ │ │ ├─ Restore health (checkpoint value, not full)
│ │ │ ├─ Restore inventory (minus death losses)
│ │ │ └─ Restore world state (doors, items, enemies)
│ │ │
│ │ ├─ WBP_DeathScreen.HideDeathScreen()
│ │ ├─ WBP_ScreenEffectController.PlayRespawnFadeIn()
│ │ └─ BPC_StateManager.RestorePreviousState()
│ │
│ └─ BPC_NarrativeStateSystem.SetFlag("PlayerDied")
```
---
## Void Space / Alt Death Space
### Entry Conditions
```
Player dies with DeathCause == "Void" (killed by Shade)
OR
Player interacts with void portal in Basement
AND
GI_HorrorGame.GetSessionFlag("VoidSpaceVisited") == false (first time only)
→ BPC_AltDeathSpaceSystem.EnterVoidSpace()
```
### Void Space Flow
```
EnterVoidSpace()
├─ BPC_StateManager.ForcePushState(AltDeathSpace)
├─ GM_HorrorGameMode → Set bVoidSpaceActive = true
├─ GS_HorrorGameState → SetVoidActive(true)
├─ [Transition]
│ ├─ SS_SaveManager.QuickSave("PreVoid") // save real-world state
│ ├─ GM_HorrorGameMode.TransitionToChapter(Chapter.VoidSpace)
│ └─ Level loads: L_Asylum_VoidSpace
├─ [Void Space Gameplay]
│ ├─ Environment: inverted lighting, non-Euclidean geometry
│ ├─ No map/HUD compass
│ ├─ Objective: "Find the light. Escape the void."
│ │
│ ├─ Puzzle: Activate 3 Memory Shrines
│ │ ├─ Shrine 1: Reflection shows death moment
│ │ ├─ Shrine 2: Voice whispers memory fragment
│ │ └─ Shrine 3: Touch the light
│ │
│ ├─ Threat: Shade pursues (same entity, void-empowered)
│ │ └─ Contact = restart at Shrine 1
│ │
│ └─ Timer: 5 minutes (Trial Scenario System)
│ └─ If time expires: Shade becomes unavoidable → restart
└─ [Exit Void Space]
├─ Player reaches exit portal (all 3 shrines activated)
├─ BPC_AltDeathSpaceSystem.ExitVoidSpace()
├─ [Return to Real World]
│ ├─ SS_SaveManager.LoadSaveSlot("PreVoid") // restore pre-void state
│ ├─ TransitionToChapter(OriginalChapter)
│ ├─ Spawn player at original death location (or nearest safe spot)
│ │
│ ├─ [Void-Touched Benefits]
│ │ ├─ GI_HorrorGame.SetSessionFlag("VoidSpaceVisited", true)
│ │ ├─ Player gains passive: +10% damage vs enemies
│ │ ├─ Player can see hidden void objects in real world
│ │ └─ New dialogue option: "I've touched the void"
│ │
│ ├─ Health/Inventory restored to pre-death state
│ └─ WBP_NotificationToast.Show("You are now Void-Touched")
└─ Achievement: "Touched the Void" unlocked
```
---
## I_Persistable Implementation
Every actor that needs to save/restore its state implements `I_Persistable`:
### Persistent Actor Types
| Actor | Saved Data | Restored On |
|-------|-----------|------------|
| `BP_Door_*` | bIsOpen, bIsLocked, bIsBarricaded, DoorRotation | Level load, death respawn |
| `BP_Pickup_*` | bIsCollected (if true → destroy on load) | Level load, death respawn |
| `BP_Enemy_*` | bIsDead, CorpseLocation, CorpseRotation | Level load, death respawn |
| `BP_Checkpoint_*` | bActivated, ActivationCount | Level load |
| `BP_PuzzleDeviceActor_*` | bIsSolved, CurrentStep, PuzzleStateData | Level load, death respawn |
| `BP_ContainerInventory` (chests/desks) | IsOpen, LootedItems, ContainerState | Level load, death respawn |
| `BP_NPC_Survivor` | Location, bIsFollowing, bIsAlive | Level load |
### I_Persistable Interface Functions
```
SaveState() → FPersistentData
├─ Actor serializes its current state into a struct
└─ Returns FPersistentData (includes ActorClass, ActorName, StatePayload)
LoadState(FPersistentData)
├─ Actor restores its state from saved data
└─ Returns Boolean (success/fail)
GetPersistenceID() → FName
└─ Returns unique ID for this actor instance (level name + actor name)
```
---
## Run History Tracker
### BPC_RunHistoryTracker Data
```
Current Run Stats:
├─ TotalDeaths (Int32)
├─ DeathLocations (Array<FDeathRecord>)
│ └─ { Location, Cause, Chapter, Timestamp }
├─ CheckpointsActivated (Array<GameplayTag>)
├─ TimePerChapter (Map<GameplayTag, Float>)
├─ ItemsFound (Int32 / TotalItems)
├─ EnemiesKilled (Int32)
├─ ScaresExperienced (Int32)
└─ PlaystyleTag (GameplayTag)
Displayed on:
├─ WBP_DeathScreen → Deaths + Chapter + Time
├─ WBP_GamePauseMenu → Chapter + Deaths + Time
└─ WBP_DeathScreen (post-credits) → Full summary
```
---
## Save/Load UI Flow
### Save Game Menu
```
SS_UIManager.PushMenu(SaveLoadMenu)
├─ [Display Save Slots]
│ └─ For each slot in SS_SaveManager.GetAllSlots():
│ ├─ Show slot thumbnail, chapter, playtime, timestamp
│ ├─ Empty slot → "Empty — [Create New Save]"
│ └─ Occupied slot → [Load] [Delete (hold to confirm)]
├─ [Load Game]
│ ├─ Selected slot → SS_SaveManager.LoadSaveSlot(SlotIndex)
│ ├─ Get SaveHeader.ChapterTag
│ ├─ TransitionToChapter(ChapterTag)
│ └─ On level loaded: BPC_PlayerRespawnSystem.RestoreState()
├─ [Delete Save]
│ ├─ Hold button for 1.5s to confirm (prevents accidental deletion)
│ ├─ SS_SaveManager.DeleteSaveSlot(SlotIndex)
│ └─ Refresh slot list
└─ [New Save — Manual]
└─ SS_SaveManager.CreateManualSave(SlotIndex, "Manual")
```
---
## Blueprint Wiring Checklist
### Save System
- [ ] Configure `SS_SaveManager` with 3 default save slots
- [ ] Implement `I_Persistable` on all 7 persistent actor types
- [ ] Wire `BPC_PersistentWorldStateRecorder` to capture world state at checkpoints/death
- [ ] Wire save/load UI through `WBP_GamePauseMenu` and `WBP_GameMainMenu`
### Checkpoints
- [ ] Create `BP_Checkpoint_SafeRoom`, `BP_Checkpoint_Mirror`, `BP_Checkpoint_BasementGate`, `BP_Checkpoint_VoidThreshold`
- [ ] Wire overlap → auto-save + health/stamina restore + notification
### Death
- [ ] Wire `BPC_DeathHandlingSystem` → death animation → death screen → respawn
- [ ] Wire `BPC_PersistentCorpseSystem` → leave corpse at death location
- [ ] Wire `BPC_PlayerRespawnSystem` → load checkpoint + restore state
- [ ] Wire `WBP_DeathScreen` with Continue/MainMenu/Void options
### Void Space
- [ ] Wire `BPC_AltDeathSpaceSystem` → enter void on Shade death
- [ ] Create void puzzle (3 memory shrines) in `L_Asylum_VoidSpace`
- [ ] Wire exit → restore pre-void state + void-touched benefits
### Run History
- [ ] Wire `BPC_RunHistoryTracker` to log deaths, checkpoints, chapter times
- [ ] Display stats on death screen + post-credits summary
---
## Notes for Expansion
- Add **cloud saves** (platform-specific: Steam Cloud, PSN, Xbox Live)
- Add **save file encryption** to prevent tampering (anti-cheat)
- Add **ironman/permadeath mode**: disable all saves except checkpoint auto-save, one life only
- Add **save transfer**: export/import saves for cross-platform
- Add **death replay**: camera pans to show how you died (like a replay of last 5 seconds)
- Void Space could have **multiple exits** that lead to different real-world locations
- Multiplayer: save states must be server-authoritative, replicated to joining clients
---
*Save System & Checkpoints for Project Void. See [GAMEINDEX.md](GAMEINDEX.md) for full game structure. See [35_SS_SaveManager.md](../blueprints/05-saveload/35_SS_SaveManager.md) for save subsystem spec.*