- Created a comprehensive implementation checklist for the Planar Capture System (Systems 136-147) detailing tasks across multiple phases including C++ core, material foundation, Blueprint actors, data assets, integration, and performance testing. - Added a developer reference document outlining the architecture, data flow, state machine, budget enforcement, render target pooling, horror features, integration points, multiplayer networking, performance characteristics, debugging methods, and build order for the capture systems. - Introduced examples of capture surface usage in the Project Void horror game, including specific implementations for mirrors, monitors, portals, and fake windows, along with a checklist for integration tasks.
16 KiB
Planar Capture System Examples — Project Void Horror Game
Game: Project Void | Build Phase: 17e (Capture System Integration) Framework Systems: 136-147 (12 Planar Capture systems)
Purpose
Defines how the Planar Capture System is used in the Project Void horror game — mirrors that show wrong reflections, security monitors that display camera feeds, and void portals that warp reality. Every capture surface mode is demonstrated.
Capture Surface Placement Map
| Surface | Level | Location | Mode | Purpose |
|---|---|---|---|---|
BP_Mirror_NurseStation |
WardA | Nurses Station | Mirror | Checkpoint mirror, also shows player reflection |
BP_HorrorMirror_Morgue |
WardB | Morgue | HorrorMirror | Wrong reflection scare (face appears behind player) |
BP_HorrorMirror_WardensOffice |
WardensOffice | Above desk | HorrorMirror | Final confrontation — entity speaks through mirror |
BP_Monitor_Security |
WardA | Security Office | Monitor | Shows hallway camera feed (live) |
BP_Monitor_Morgue |
WardB | Morgue office | Monitor | Shows morgue interior (static noise, flicker) |
BP_Portal_VoidEntrance |
Basement | Crematorium | Portal | Void portal — links to BP_Portal_VoidExit in VoidSpace |
BP_Portal_VoidExit |
VoidSpace | Memory Shrine 3 | Portal | Exit portal back to Basement |
BP_FakeWindow_WardensOffice |
WardensOffice | Window behind desk | FakeWindow | Shows "outside" view (rain, night, distant asylum) |
1. BP_Mirror_NurseStation — Standard Mirror
Asset Path: Content/Game/Actors/BP_Mirror_NurseStation.uasset
Parent: BP_Mirror (139)
Framework Systems: 136-139, 144-147
Level Placement
L_Asylum_WardA → Nurses Station
├─ BP_Mirror_NurseStation (640×320 plane, wall-mounted)
├─ Position: Above sink counter, eye-level
├─ Material: MI_Mirror_Dirty (aged, slight oxidation)
├─ MPC params: DirtOpacity=0.3, SurfaceAge=0.2
└─ ProximityTrigger: 1000uu radius
Gameplay Integration
- Checkpoint: This mirror doubles as
BP_Checkpoint_Mirror— player touches it to save - Reflection quality: Player is in a small room → mirror stays at High/Medium tier (close proximity)
- No horror features — this is a normal mirror at this point in the game
- Easter egg: Player's reflection blinks slightly out of sync (1 in 100 chance, very subtle)
Blueprint Setup
BP_Mirror_NurseStation (child of BP_Mirror)
│
├─ Class Defaults:
│ ├─ CaptureComponent.CaptureMode = Mirror
│ ├─ CaptureComponent.QualityProfiles[1] = Medium (512px, 15fps, shadows)
│ ├─ CaptureComponent.QualityProfiles[2] = High (1024px, 30fps, Lumen)
│ ├─ SurfaceMesh → SM_WallMirror_640x320
│ └─ SurfaceMaterial → MI_Mirror_Dirty
│
└─ Event BeginPlay:
├─ SetSurfaceMPCParameter("DirtOpacity", 0.3)
├─ SetSurfaceMPCParameter("SurfaceAge", 0.2)
└─ EnableSurface()
2. BP_HorrorMirror_Morgue — Wrong Reflection Scare
Asset Path: Content/Game/Actors/BP_HorrorMirror_Morgue.uasset
Parent: BP_HorrorMirror (142)
Framework Systems: 136-138, 142, 144-147 + 101_BPC_ScareEventSystem
Level Placement
L_Asylum_WardB → Morgue
├─ BP_HorrorMirror_Morgue (800×600 plane)
├─ Position: On morgue wall, facing dissection table
├─ Material: MI_Mirror_Horror (horror layers enabled)
├─ WrongReflectionActor: BP_Enemy_Shade placed behind camera (hidden)
└─ Trigger: Player looks at mirror > 2 seconds
Scare Sequence
Trigger: BPC_InteractionDetector focus remains on mirror for 2+ seconds
│
├─ [Anticipation Phase] (5 seconds)
│ ├─ Steam slowly fogs mirror:
│ │ └─ Timeline: SteamIntensity MPC 0.0 → 0.4 over 3s
│ ├─ Audio: SS_AudioManager.PlaySFX("mirror_steam_hiss")
│ ├─ BPC_StressSystem.AddStress(+3) — subtle unease
│ └─ Player is still watching their reflection
│
├─ [Payoff Phase] (3 seconds)
│ ├─ BPC_ScareEventSystem.TriggerScareEvent("MirrorApparition")
│ │ └─ Coordinates with lights (flicker), audio (stinger)
│ │
│ ├─ CaptureComponent.ActivateHorrorReflection()
│ │ └─ Swaps ShowOnly list from Self to WrongReflectionActor
│ │ └─ Next capture frame: Shade appears in mirror instead of player
│ │
│ ├─ Timeline: WrongReflectionBlend MPC 0.0 → 1.0 over 0.5s (instant crossfade)
│ ├─ Timeline: MirrorDarkness MPC 0.0 → 0.6 (mirror darkens)
│ ├─ Timeline: DistortionAmplitude MPC 0.0 → 0.3 (mirror "breathes")
│ │
│ ├─ Steam text reveal: TextRevealProgress MPC 0.0 → 1.0
│ │ └─ Text "JOIN ME" appears in steam on mirror surface
│ │
│ └─ Audio: SS_AudioManager.PlaySFX("mirror_scare_stinger")
│ └─ Loud glass crack + whisper voice
│
└─ [Recovery Phase] (3 seconds)
├─ CaptureComponent.DeactivateHorrorReflection()
│ └─ Restores player's reflection
├─ All MPC params return to 0.0 over 1.5s
├─ BPC_StressSystem.AddStress(+15) — spike
└─ Mirror returns to normal (player can continue)
Blueprint Setup
BP_HorrorMirror_Morgue (child of BP_HorrorMirror)
│
├─ Class Defaults:
│ ├─ CaptureComponent.CaptureMode = HorrorMirror
│ ├─ CaptureComponent.WrongReflectionActor = BP_Enemy_Shade_Reflection
│ │ └─ (This Shade instance is placed behind a wall — invisible to player
│ │ but visible to the capture camera due to ShowOnly list)
│ ├─ CaptureComponent.QualityProfiles[2].DelayedFrameCount = 3
│ │ └─ Reflection lags 3 frames at High tier
│ ├─ ScareEventTag = "Game.Environment.Scare.MirrorApparition"
│ └─ ScareDuration = 8.0
│
├─ Curves:
│ ├─ Curve_WrongReflectionBlend: (0,0) → (0.5,1.0) → (2.5,1.0) → (3.0,0)
│ ├─ Curve_MirrorDarkness: (0,0) → (0.5,0.6) → (2.0,0.4) → (3.0,0)
│ ├─ Curve_UVDistortion: (0,0) → (0.5,0.3) → (1.5,0.15) → (3.0,0)
│ └─ Curve_SteamTextReveal: (1.0,0) → (2.0,1.0) → (3.0,1.0)
│
└─ Event Graph:
├─ Bind to BPC_InteractionDetector.OnFocusGained
│ └─ If FocusedActor == Self → Start LookTimer (2.0s)
│ └─ On Timer Complete → TriggerHorrorScare()
│
└─ TriggerHorrorScare() (implemented as described above)
3. BP_Monitor_Security — Security Camera Display
Asset Path: Content/Game/Actors/BP_Monitor_Security.uasset
Parent: BP_Monitor (141)
Framework Systems: 136-138, 141, 144-147
Level Placement
L_Asylum_WardA → Security Office
├─ BP_Monitor_Security (screen quad on desk)
├─ FixedCameraActor: SecurityCamera_HallwayA (placed in hallway)
├─ Shows live feed of hallway → player can see enemies patrolling
└─ Power: ON by default
Monitor Behavior
BP_Monitor_Security
│
├─ Class Defaults:
│ ├─ CaptureComponent.CaptureMode = Monitor
│ ├─ CaptureComponent.CaptureFOV = 70
│ ├─ CaptureComponent.QualityProfiles[0].CaptureInterval = 0.2 (5fps)
│ │ └─ Security monitors don't need high FPS
│ ├─ CaptureComponent.FixedCameraActor = SecurityCamera_HallwayA
│ └─ SurfaceMaterial → MI_Monitor_Security
│
├─ Features:
│ ├─ Static noise overlay: StaticNoiseIntensity = 0.1 (subtle grain)
│ ├─ Scanline effect: bShowScanlines = true (CRT-like lines)
│ └─ Power state reacts to fusebox puzzle:
│ ├─ Fusebox power OFF → Monitor flickers and dies (PowerOff)
│ └─ Fusebox power ON → Monitor boots up with flicker (PowerOn)
│
└─ Narrative hook:
└─ At specific narrative flag ("ShadeEncountered"):
└─ Shade briefly appears on monitor for 1 frame (rare event)
└─ BPC_RareEventSystem check every 30s, 2% chance
Blueprint Setup
BP_Monitor_Security (child of BP_Monitor)
│
├─ Class Defaults:
│ ├─ CaptureComponent.CaptureMode = Monitor
│ ├─ CaptureComponent.CaptureFOV = 70
│ ├─ bPoweredOn = true
│ ├─ bShowScanlines = true
│ ├─ StaticNoiseIntensity = 0.1
│ └─ SurfaceMaterial = MI_Monitor_Security
│
└─ Event Graph:
├─ Event BeginPlay → EnableSurface
│
├─ [Bind to fusebox puzzle]
│ ├─ Listen for BPC_UsableWorldObjectSystem.OnActivated (fusebox power)
│ │ └─ PowerOn() (with 1s flicker delay)
│ └─ Listen for BPC_UsableWorldObjectSystem.OnDeactivated
│ └─ PowerOff() (immediate)
│
└─ [Rare event: Shade on monitor]
└─ Timer (30s loop) → Check narrative flag "ShadeEncountered"
└─ If true → Random Float 0-1 < 0.02
└─ True: Show Shade frame (capture swap to Shade actor for 0.2s)
4. BP_Portal_VoidEntrance / BP_Portal_VoidExit — Void Portal
Asset Path: Content/Game/Actors/BP_Portal_VoidEntrance.uasset
Parent: BP_Portal (140)
Framework Systems: 136-138, 140, 144-147 + 130_BPC_StateManager
Level Placement
L_Asylum_Basement → Crematorium
├─ BP_Portal_VoidEntrance (wall-mounted portal frame)
├─ LinkedTargetSurface: BP_Portal_VoidExit in L_Asylum_VoidSpace
├─ TeleportOnOverlap: true
├─ Appearance: Shimmering purple-black void surface
└─ Trigger: Player walks into it
L_Asylum_VoidSpace → Exit Chamber (behind Memory Shrine 3)
├─ BP_Portal_VoidExit (floating portal in void)
├─ LinkedTargetSurface: BP_Portal_VoidEntrance (back to Basement)
├─ Shows: Basement Crematorium view (player's return destination)
└─ Only visible after all 3 Memory Shrines activated
Portal Teleport Flow
Player overlaps BP_Portal_VoidEntrance.TeleportTrigger
│
├─ [Server-authoritative check]
│ └─ Switch HasAuthority
│ ├─ Authority:
│ │ ├─ BPC_StateManager.IsActionPermitted(Framework.Action.Teleport)?
│ │ │ └─ True → proceed
│ │ │ └─ False → Show blocked feedback, return
│ │ │
│ │ ├─ Get LinkedTargetSurface → Get ActorTransform
│ │ ├─ Teleport player: SetActorLocation + SetActorRotation
│ │ │ └─ Offset: targetForward * 300 (spawn 3m in front of exit)
│ │ │
│ │ ├─ [Transition Effects]
│ │ │ ├─ WBP_ScreenEffectController.Flash(purple, 0.5s)
│ │ │ ├─ BPC_CameraStateLayer.PushLayer("PortalTransition", 1.0s)
│ │ │ │ └─ FOV 120 → 90 over 1s, chromatic aberration
│ │ │ └─ SS_AudioManager.PlaySFX("portal_travel")
│ │ │
│ │ └─ Multicast_OnPlayerTeleported (visual feedback for all clients)
│ │
│ └─ Remote (client):
│ └─ Call Server_TeleportThroughPortal RPC
└─
Blueprint Setup
BP_Portal_VoidEntrance (child of BP_Portal)
│
├─ Class Defaults:
│ ├─ CaptureComponent.CaptureMode = Portal
│ ├─ bTeleportOnOverlap = true
│ ├─ bOneWay = false (two-way — player can return)
│ ├─ SurfaceMaterial = MI_Portal_Standard
│ └─ CaptureComponent.QualityProfiles[2].bEnableClipPlane = true
│ └─ Clip plane prevents geometry behind portal from clipping in
│
├─ Components:
│ ├─ SurfaceMesh (portal plane)
│ ├─ ProximityTrigger (quality scoring, large: 2000uu)
│ └─ TeleportTrigger (overlap detection, same size as surface)
│
└─ Event Graph:
├─ BeginPlay → EnableSurface → RegisterWithManager
│
├─ TeleportTrigger.OnComponentBeginOverlap
│ └─ Cast to PlayerCharacter → If valid:
│ └─ HasAuthority → Teleport player
│ └─ Client → Server_TeleportThroughPortal RPC
│
└─ Server_TeleportThroughPortal (RPC, Reliable, Server)
├─ Validate portal still active
├─ Get LinkedTargetSurface
├─ Teleport player to exit location
└─ Multicast_OnPlayerTeleported (play FX on all clients)
5. BP_FakeWindow_WardensOffice — Atmospheric Window
Asset Path: Content/Game/Actors/BP_FakeWindow_WardensOffice.uasset
Parent: BP_FakeWindow (143)
Framework Systems: 136-138, 143, 144-147
Level Placement
L_Asylum_WardensOffice → Behind Warden's desk
├─ BP_FakeWindow_WardensOffice (large window frame)
├─ Shows: "Outside" view — rain, night sky, distant asylum building
├─ Weather: Rain overlay based on game state
└─ Parallax: Slight depth effect when player moves
Behavior
BP_FakeWindow_WardensOffice
│
├─ Class Defaults:
│ ├─ CaptureComponent.CaptureMode = FakeWindow
│ ├─ CaptureComponent.CaptureFOV = 100 (wide window view)
│ ├─ CaptureComponent.QualityProfiles[0] = Low (256px, 4fps)
│ │ └─ Window is far from action — low priority
│ └─ SurfaceMaterial → MI_FakeWindow_Interior
│
├─ Weather Integration:
│ └─ Listen to GS_HorrorGameState.OnGlobalFearChanged
│ ├─ Fear < 0.3: Clear night, distant lights
│ ├─ Fear 0.3-0.6: Light rain, overcast
│ └─ Fear > 0.6: Heavy rain, lightning flashes, dark
│
└─ Sublevel Streaming:
└─ bStreamSublevelOnProximity = true
├─ Stream in when player within 3000uu
└─ Stream out when player beyond 4000uu
Capture Integration Checklist (for Project Void)
Mirrors
- Create
BP_Mirror_NurseStationin WardA Nurses Station - Create
BP_HorrorMirror_Morguein WardB Morgue - Create
BP_HorrorMirror_WardensOfficein WardensOffice - Place
BP_Enemy_Shade_Reflection(hidden) for morgue horror mirror - Create
DA_Scare_MirrorApparitionData Asset (references BPC_ScareEventSystem) - Wire morgue mirror scare to BPC_ScareEventSystem.TriggerScareEvent()
- Wire audio through SS_AudioManager for mirror crack/steam/whisper sounds
Monitors
- Create
BP_Monitor_Securityin WardA Security Office - Create
BP_Monitor_Morguein WardB Morgue office - Place
SecurityCamera_HallwayACameraActor in WardA hallway - Wire monitor power to fusebox puzzle completion
Portals
- Create
BP_Portal_VoidEntrancein Basement Crematorium - Create
BP_Portal_VoidExitin VoidSpace (behind Memory Shrine 3) - Wire portal visibility to Memory Shrine 3 completion
- Add BPC_StateManager.IsActionPermitted(Teleport) check before teleport
Fake Windows
- Create
BP_FakeWindow_WardensOfficein WardensOffice - Create sublevel with window view room + camera
- Wire weather overlay to GS_HorrorGameState.GlobalFearLevel
Quality & Performance
- Test 8 capture surfaces active simultaneously → verify budget enforcement
- Monitor GPU cost with
stat GPUin PIE - Verify mirrors go Off when player is far away
- Verify Hero tier assigned to mirror player is looking directly at
Notes for Expansion
- Add mirror puzzle: player must look at specific angle in mirror to see hidden key reflected
- Add portal network: multiple interconnected portals create non-Euclidean maze
- Add monitor hacking: player can switch security cameras to find hidden items
- Add weather system: fake windows sync weather with game narrative progression
- Add mirror memory: some mirrors show "echoes" of past events (scripted timeline sequences)
- Multiplayer: portals teleport all players; mirrors render each client's own reflection
Planar Capture Examples for Project Void. See GAMEINDEX.md for full game structure. See planar-capture-system.md for architecture spec.