add blueprints

This commit is contained in:
Lefteris Notas
2026-05-19 13:22:27 +03:00
parent f71bc678b2
commit 411edea8ce
138 changed files with 23330 additions and 0 deletions

View File

@@ -0,0 +1,382 @@
# 16 — Interaction Detector (`BPC_InteractionDetector`)
## Purpose
The player's "interaction eye" — performs trace-based detection of interactable objects in the world, sorts them by priority/distance, tracks the current best target, and manages the interaction prompt widget. Every interactive system in the game funnels through this component.
## Dependencies
- **Requires:** `I_Interactable` (interface on all interactable actors), `PlayerCameraManager` (for trace origin), `BPC_MovementStateSystem` (block interaction during specific states)
- **Required By:** `WBP_InteractionPrompt` (HUD element), `BPC_PickupComponent`, `BPC_InteractableDoorComponent`, `BPC_LeverPuzzleComponent`
- **Engine/Plugin Requirements:** `LineTraceByChannel` (ECC_GameTraceChannel1 = Interaction), `TimerHandle` for scan interval
## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `ActorComponent` |
| **Class Type** | Blueprint Component |
| **Asset Path** | `Content/Framework/Interaction/BPC_InteractionDetector` |
| **Implements Interfaces** | None |
---
## 1. Enums
### `E_InteractionInputMode`
| Value | Description |
|-------|-------------|
| `Press = 0` | Single press to interact |
| `Hold = 1` | Hold over duration to confirm |
| `DoubleTap = 2` | Two rapid presses |
| `Auto = 3` | Automatic on proximity (no input) |
### `E_InteractionPriority`
| Value | Description |
|-------|-------------|
| `Low = 0` | Ambient / cosmetic items |
| `Normal = 1` | Standard pickups, doors |
| `High = 2` | Story-critical, puzzles |
| `Emergency = 3` | Immediate threat (hide spot, weapon) |
### `E_DetectionState`
| Value | Description |
|-------|-------------|
| `NoTarget = 0` | Nothing in range |
| `TargetInRange = 1` | Potential target found |
| `TargetConfirmed = 2` | Best target selected |
| `Interacting = 3` | Currently performing interaction |
---
## 2. Structs
### `S_InteractableTarget`
| Field | Type | Description |
|-------|------|-------------|
| `TargetActor` | `AActor` | The interactable actor |
| `InterfaceRef` | `I_Interactable` | Cast to interface |
| `Priority` | `E_InteractionPriority` | Priority level |
| `Distance` | `Float` | Distance from player to target |
| `InteractionLabel` | `FText` | Display name (e.g. "Open Door", "Pick Up Key") |
| `InputMode` | `E_InteractionInputMode` | How interaction is triggered |
| `HoldDuration` | `Float` | Seconds required if InputMode is Hold |
| `bIsHighlighted` | `Boolean` | Whether target is visually highlighted |
| `TargetLocation` | `Vector` | World location for UI widget |
### `S_InteractionResult`
| Field | Type | Description |
|-------|------|-------------|
| `bSuccess` | `Boolean` | Whether interaction was successful |
| `FailureReason` | `FText` | Human-readable failure reason |
| `TargetActor` | `AActor` | The interacted actor |
| `ContextTag` | `GameplayTag` | Tag for event recording |
---
## 3. Variables
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `InteractionRange` | `Float` | `250.0` | `Detection Config` | Max trace distance (cm) |
| `DetectionAngle` | `Float` | `45.0` | `Detection Config` | Cone half-angle for detection (degrees) |
| `TraceRadius` | `Float` | `10.0` | `Detection Config` | Sphere trace radius |
| `ScanInterval` | `Float` | `0.1` | `Detection Config` | Seconds between detection scans |
| `MaxTargetsInRange` | `Integer` | `16` | `Detection Config` | Max detected targets per scan |
| `bShowDebugTrace` | `Boolean` | `false` | `Detection Config` | Visualise trace in editor |
| `TraceChannel` | `TEnumAsByte<ECollisionChannel>` | `ECC_GameTraceChannel1` | `Detection Config` | Collision channel for interaction |
| `bBlockDuringDeath` | `Boolean` | `true` | `Detection Config` | Block interaction while dead |
| `bBlockDuringHiding` | `Boolean` | `true` | `Detection Config` | Block interaction while hidden |
| `bBlockDuringCombat` | `Boolean` | `false` | `Detection Config` | Block interaction during combat |
### Internal (Private / Protected, No Expose)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `BestTargetIndex` | `Integer` | `-1` | `Detection State` | Index of currently selected target |
| `DetectedTargets` | `Array<S_InteractableTarget>` | `[]` | `Detection State` | All detected targets this scan |
| `CurrentTarget` | `S_InteractableTarget` | `-` | `Detection State` | Currently selected best target |
| `DetectionState` | `E_DetectionState` | `NoTarget` | `Detection State` | Current state of the detector |
| `bIsPerformingInteraction` | `Boolean` | `false` | `Detection State` | Whether interaction is in progress |
| `HoldInteractionProgress` | `Float` | `0.0` | `Detection State` | Progress for hold-type interactions |
| `OwnerPlayerController` | `APlayerController` | `None` | `Cache` | Cached player controller |
| `OwnerCameraManager` | `APlayerCameraManager` | `None` | `Cache` | Cached camera manager |
| `ScanTimerHandle` | `FTimerHandle` | `-` | `Timing` | Timer for scan interval |
| `DetectedActors_LastFrame` | `Set<AActor>` | `{}` | `Tracking` | Previous frame targets for enter/exit detection |
### Replicated (if multiplayer)
| Variable | Type | Condition | Description |
|----------|------|-----------|-------------|
| `CurrentTarget` | `S_InteractableTarget` | `Replicated` | Synced selected target |
---
## 4. Functions
### Public Functions
#### `StartDetection` → `void`
- **Description:** Begins the scan loop for interactable targets.
- **Parameters:** None
- **Flow:**
1. Get owner Player Controller
2. Get Player Camera Manager
3. Start scan timer (ScanInterval)
4. If bShowDebugTrace: enable debug line visualisation
#### `StopDetection` → `void`
- **Description:** Stops the scan loop and clears detected targets.
- **Parameters:** None
- **Flow:**
1. Clear scan timer
2. Clear DetectedTargets array
3. Set DetectionState = NoTarget
4. Fire OnTargetLost
5. Clear any highlight effects
#### `PerformInteraction` → `S_InteractionResult`
- **Description:** Executes interaction on the current best target.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `InputMode` | `E_InteractionInputMode` | How the input was triggered |
- **Flow:**
1. If not CurrentTarget valid or CurrentTarget actor is None: return failure
2. If bIsPerformingInteraction: return failure (already interacting)
3. If InputMode != CurrentTarget.InputMode: return failure (input mismatch)
4. Set bIsPerformingInteraction = true
5. Set DetectionState = Interacting
6. Fire OnInteractionStarted
7. Call CurrentTarget.InterfaceRef.ExecuteInteraction (owner)
8. Wait for I_Interactable.OnInteractionCompleted or timeout
9. On completion: set bIsPerformingInteraction = false
10. Resume scanning
11. Return S_InteractionResult with success/failure
#### `CancelInteraction` → `void`
- **Description:** Aborts the current interaction if possible.
- **Parameters:** None
- **Flow:**
1. If not bIsPerformingInteraction: return
2. Call CurrentTarget.InterfaceRef.CancelInteraction
3. Set bIsPerformingInteraction = false
4. HoldInteractionProgress = 0.0
5. Set DetectionState = TargetConfirmed
6. Fire OnInteractionCancelled
#### `GetBestTarget` → `S_InteractableTarget`
- **Description:** Returns the current best target.
- **Parameters:** None
- **Flow:** Return CurrentTarget
#### `HasTarget` → `Boolean`
- **Parameters:** None
- **Flow:** Return DetectionState >= TargetInRange
#### `ForceSetTarget` → `void`
- **Description:** Forcefully sets a specific target (for scripted interactions).
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `TargetActor` | `AActor` | The specific actor to target |
- **Flow:**
1. If TargetActor implements I_Interactable:
- Build S_InteractableTarget
- Set CurrentTarget
- Set DetectionState = TargetConfirmed
- Fire OnTargetFound
2. Else: fire OnInteractionError(not interactable)
### Private Functions
#### `ScanForInteractables (Timer)` → `void`
- **Description:** Timer callback — performs trace and sorts targets.
- **Flow:**
1. If DetectionState == Interacting: return (skip scan while interacting)
2. Get camera forward vector and world location
3. Sphere trace forward (TraceRadius, InteractionRange, TraceChannel)
4. For each hit actor:
- If implements I_Interactable: add to DetectedTargets
- If not: skip
5. Remove duplicates by actor reference
6. Sort by Priority (descending), then Distance (ascending)
7. Clamp to MaxTargetsInRange
8. Track enter/exit for each actor — fire OnTargetEntered / OnTargetExited
9. Select BestTarget from sorted list
10. Update DetectionState accordingly
11. Fire OnTargetFound or OnTargetLost
#### `CalculateInteractionScore` → `Float`
- **Description:** Computes a score for a target based on priority, distance, and facing angle.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Target` | `S_InteractableTarget` | The target to score |
- **Flow:**
1. Score = Priority * 100 - Distance * 0.5
2. Facing bonus: if angle < 15 deg, add 50
3. Return Max(0, Score)
#### `HighlightTarget` → `void`
- **Description:** Applies highlight effect to target actor.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Target` | `S_InteractableTarget` | Target to highlight |
| `bHighlighted` | `Boolean` | Whether to enable or disable |
- **Flow:**
1. Call Target.InterfaceRef.SetHighlighted(bHighlighted)
#### `GetViewTraceOrigin` → `Vector, Vector`
- **Description:** Returns camera location and forward direction for trace.
- **Parameters:** None
- **Flow:**
1. If OwnerCameraManager valid:
- Return cam location and forward vector
2. Else: fall back to owner actor location and forward
---
## 5. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnTargetFound` | `S_InteractableTarget NewTarget` | `Public` | New best target selected |
| `OnTargetLost` | `S_InteractableTarget LostTarget` | `Public` | Current target lost from view / range |
| `OnTargetEntered` | `AActor TargetActor` | `Public` | Actor entered detectable range |
| `OnTargetExited` | `AActor TargetActor` | `Public` | Actor left detectable range |
| `OnInteractionStarted` | `S_InteractableTarget Target` | `Public` | Interaction began |
| `OnInteractionCompleted` | `S_InteractionResult Result` | `Public` | Interaction finished |
| `OnInteractionCancelled` | `S_InteractableTarget Target` | `Public` | Interaction was cancelled |
| `OnInteractionError` | `FText ErrorMessage` | `Public` | Interaction blocked or failed |
| `OnHoldProgressUpdated` | `Float Progress`, `S_InteractableTarget Target` | `Public` | Hold interaction progress [0..1] |
---
## 6. Overridden Events / Custom Events
### Event: `BeginPlay`
- **Description:** Cache references, bind to relevant systems, start detection.
- **Flow:**
1. Get owning actor ensure it is a Pawn
2. Get Player Controller from owner
3. Get Player Camera Manager from controller
4. Bind to BPC_MovementStateSystem.OnPostureChanged block when hidden
5. Bind to BPC_HealthSystem.OnDeathStateChanged block when dead
6. StartDetection()
### Custom Event: `OnInputInteractPressed`
- **Description:** Handles press input for interaction.
- **Flow:**
1. If DetectionState < TargetConfirmed: return
2. If CurrentTarget.InputMode == Press:
- PerformInteraction(Press)
3. If CurrentTarget.InputMode == Hold:
- Start hold timer
4. If CurrentTarget.InputMode == DoubleTap:
- Wait for second press within threshold
### Custom Event: `OnHoldProgressTick (Timer)` → `void`
- **Description:** Ticks hold interaction progress and fires progress dispatcher.
- **Flow:**
1. HoldInteractionProgress += DeltaTime / CurrentTarget.HoldDuration
2. Clamp to 1.0
3. Fire OnHoldProgressUpdated
4. If HoldInteractionProgress >= 1.0: PerformInteraction(Hold)
### Custom Event: `OnInputInteractReleased`
- **Description:** Cancels hold interaction if button released early.
- **Flow:**
1. If CurrentTarget.InputMode == Hold and not completed:
- CancelInteraction()
- HoldInteractionProgress = 0.0
---
## 7. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[Scan Timer Fires] --> B[Get Camera Location / Forward]
B --> C[SphereTraceForObjects]
C --> D[Hit actors found?]
D -->|No| E[Clear targets]
E --> F[DetectionState = NoTarget]
F --> G[Fire OnTargetLost]
D -->|Yes| H[Filter by I_Interactable]
H --> I[Sort by Priority then Distance]
I --> J[Select BestTarget]
J --> K{BestTarget changed?}
K -->|Yes| L[Unhighlight old target]
L --> M[Highlight new target]
M --> N[Fire OnTargetFound]
K -->|No| O[Keep current target]
P[OnInputInteractPressed] --> Q{DetectionState >= Confirmed?}
Q -->|No| R[Return]
Q -->|Yes| S{InputMode match?}
S -->|Press| T[PerformInteraction]
S -->|Hold| U[Start hold timer]
S -->|DoubleTap| V[Start double-tap timer]
T --> W[Call ExecuteInteraction on target]
W --> X[Fire OnInteractionStarted]
X --> Y{Interaction succeeded?}
Y -->|Yes| Z[Fire OnInteractionCompleted]
Y -->|No| AA[Fire OnInteractionError]
```
---
## 8. Communication Matrix
| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `BPC_InteractionDetector` | `Dispatcher` | `OnTargetFound` -> `WBP_InteractionPrompt` (show prompt) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnTargetLost` -> `WBP_InteractionPrompt` (hide prompt) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnInteractionStarted` -> `BPC_PlayerMetricsTracker` (log event) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnInteractionCompleted` -> `BPC_PlayerMetricsTracker` (log result) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnHoldProgressUpdated` -> `WBP_InteractionPrompt` (progress bar) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnInteractionCancelled` -> `WBP_InteractionPrompt` (hide) |
| `BPC_InteractionDetector` | `Listener` | Binds to `BPC_MovementStateSystem.OnPostureChanged` |
| `BPC_InteractionDetector` | `Listener` | Binds to `BPC_HealthSystem.OnDeathStateChanged` |
| `BPC_InteractionDetector` | `Direct` | Calls `I_Interactable.ExecuteInteraction` on target |
| `BPC_InteractionDetector` | `Direct` | Calls `I_Interactable.CancelInteraction` on target |
| `BPC_InteractionDetector` | `Direct` | Calls `I_Interactable.SetHighlighted` on target |
| `BPC_InteractionDetector` | `Direct call (other)` | `GetBestTarget` called by `WBP_InteractionPrompt` for name |
| `PC_PlayerController` | `Input Event` | Binds press / release / hold to `OnInputInteractPressed` etc. |
---
## 9. Validation / Testing Checklist
- [ ] Trace detects actors implementing I_Interactable at correct range
- [ ] Priority sorting: Emergency targets always selected over Low
- [ ] Same priority: closest target selected
- [ ] Detection respects blocking states (dead, hiding)
- [ ] Hold interaction progress updates and fires progress dispatcher
- [ ] Double-tap interaction waits for second press within window
- [ ] Cancelling hold interaction resets progress and fires cancelled
- [ ] Interaction blocked during combat if bBlockDuringCombat is true
- [ ] Targeting auto-switches if closer target enters range
- [ ] Target exit detection fires when actor moves beyond max range
- [ ] Edge case: No targets in range — DetectionState stays NoTarget
- [ ] Edge case: Target destroyed mid-interaction — cancels gracefully
- [ ] Edge case: Multiple interactables in trace — selects correctly
- [ ] Debug trace visualisation draws correct sphere/line
- [ ] Scan timer pauses while interacting, resumes after completion
---
## 10. Reuse Notes
- TraceChannel should be set to a custom object channel (ECC_GameTraceChannel1) with only interactable actors responding.
- Priority values can be overridden per actor via the `I_Interactable` interface's `GetInteractionPriority` function.
- The hold interaction progress is designed to drive a radial progress widget in the HUD.
- For controller/console: `E_InteractionInputMode.Hold` is preferred to prevent accidental interactions.
- The same component can be attached to NPCs if they need interaction detection.
- To support networked games: replicate CurrentTarget and have each client run their own trace locally.
---
*Blueprint Spec: Interaction Detector. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework.*

View File

@@ -0,0 +1,286 @@
# 18 — Hiding Spot Interface & Actor (`I_HidingSpot`, `BP_HidingSpotBase`)
## Purpose
Defines the contract for any world actor that can serve as a hiding spot. `I_HidingSpot` is the interface; `BP_HidingSpotBase` is the concrete base actor that designers place in levels. Together they provide the entry/exit points, peek positions, and detection rating that `BPC_HidingSystem` queries during gameplay.
## Dependencies
- **Requires:** `I_Interactable` (so hiding spots appear in interaction detection), `BPC_HidingSystem` (the consumer), `BPC_InteractionDetector` (triggers interaction)
- **Required By:** All custom hiding spot blueprints (e.g., `BP_LockerHideSpot`, `BP_DeskHideSpot`, `BP_CabinetHideSpot`)
- **Engine/Plugin Requirements:** `AI Perception System` (enemy detection vs hide spot quality), `UNavLinkComponent` for AI pathfinding around hides
## Class Info
### Interface
| Property | Value |
|----------|-------|
| **Parent Class** | `Interface` |
| **Asset Path** | `Content/Framework/Interaction/I_HidingSpot` |
### Base Actor
| Property | Value |
|----------|-------|
| **Parent Class** | `Actor` |
| **Class Type** | Blueprint Actor |
| **Asset Path** | `Content/Framework/Interaction/BP_HidingSpotBase` |
| **Implements Interfaces** | `I_HidingSpot`, `I_Interactable`, `I_Persistable` |
---
## 1. Enums
### `E_HideSpotQuality`
| Value | Description |
|-------|-------------|
| `Poor = 0` | Exposed, easily spotted (e.g. behind a thin curtain) |
| `Average = 1` | Standard cover (e.g. behind a desk) |
| `Good = 2` | Well-concealed (e.g. inside a locker) |
| `Excellent = 3` | Nearly invisible (e.g. secret compartment, vent) |
### `E_HideSpotType`
| Value | Description |
|-------|-------------|
| `Locker = 0` | Enclosed, can be locked from inside |
| `UnderObject = 1` | Crawl space (bed, desk) |
| `BehindObject = 2` | Lean against wall/object |
| `Closet = 3` | Walk-in, can close door |
| `Vent = 4` | Crawl space with movement to another location |
| `Shadow = 5` | Stand still in darkness; no physical cover |
---
## 2. Structs
### `S_HideSpotData`
| Field | Type | Description |
|-------|------|-------------|
| `SpotType` | `E_HideSpotType` | Type of hiding spot |
| `Quality` | `E_HideSpotQuality` | Concealment quality |
| `bHasDoor` | `Boolean` | Whether the spot has an openable/closable door |
| `bCanBeLocked` | `Boolean` | Whether the door can be locked from inside |
| `bAllowPeeking` | `Boolean` | Whether player can peek out |
| `MaxPeekAngle` | `Float` | Maximum peek angle left/right (degrees) |
| `bAllowBreathing` | `Boolean` | Whether player can hold breath here |
| `bAllowMovement` | `Boolean` | Whether player can move while inside |
| `DetectionRangeModifier` | `Float` | Multiplier on enemy detection range [0..1] |
| `DetectionSpeedModifier` | `Float` | Multiplier on detection speed [0..1] |
| `bIsOneTimeUse` | `Boolean` | Spot breaks after first use |
| `bIsSavePoint` | `Boolean` | Trigger auto-save on enter |
### `S_HideSpotTransform`
| Field | Type | Description |
|-------|------|-------------|
| `PlayerEnterLocation` | `Transform` | Where player stands to enter |
| `PlayerExitLocation` | `Transform` | Where player appears on exit |
| `PlayerHidingLocation` | `Transform` | Player's transform while hiding |
| `PeekLeftLocation` | `Transform` | Camera location when peeking left |
| `PeekRightLocation` | `Transform` | Camera location when peeking right |
| `EnemyDetectionOrigin` | `Vector` | World location used for line-of-sight checks |
---
## 3. Variables (BP_HidingSpotBase)
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `HideSpotData` | `S_HideSpotData` | `-` | `Hide Spot Config` | Core hiding spot properties |
| `HideSpotTransforms` | `S_HideSpotTransform` | `-` | `Hide Spot Config` | All transform locations |
| `bOccupied` | `Boolean` | `false` | `Hide Spot State` | Whether currently occupied |
| `LockedByPlayer` | `Boolean` | `false` | `Hide Spot State` | Whether player locked door from inside |
| `OccupantPawn` | `APawn` | `None` | `Hide Spot State` | Reference to the occupying pawn |
| `CooldownDuration` | `Float` | `2.0` | `Hide Spot Config` | Seconds before re-usable |
| `DetectionRadiusOverride` | `Float` | `0.0` | `Hide Spot Config` | If > 0, overrides default detection check radius |
| `bRequiresCrouch` | `Boolean` | `false` | `Hide Spot Config` | Player must be crouching to enter |
| `bOnlyAllowSneakEnter` | `Boolean` | `true` | `Hide Spot Config` | Must be walking (not sprinting) to enter |
| `EnterMontage` | `UAnimMontage` | `None` | `Animations` | Player animation for entering |
| `ExitMontage` | `UAnimMontage` | `None` | `Animations` | Player animation for exiting |
| `IdleMontage` | `UAnimMontage` | `None` | `Animations` | Looping idle animation while hiding |
| `bIsPersistent` | `Boolean` | `false` | `Save System` | Whether to save state (door open/closed, locked) |
| `SaveID` | `FName` | `None` | `Save System` | Unique ID for save system |
### Internal (Private / Protected, No Expose)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `SceneComponents` | `Array<USceneComponent>` | `[]` | `Components` | Array of scene comps for editor visualization |
| `bCanUseTimerHandle` | `FTimerHandle` | `-` | `Timing` | Cooldown timer handle |
| `bIsAvailable` | `Boolean` | `true` | `State` | Whether the spot can be entered |
### Replicated (if multiplayer)
| Variable | Type | Condition | Description |
|----------|------|-----------|-------------|
| `bOccupied` | `Boolean` | `Replicated` | Synced occupation state |
| `LockedByPlayer` | `Boolean` | `Replicated` | Synced lock state |
| `OccupantPawn` | `APawn` | `Replicated` | Who is hiding here |
---
## 4. Functions (I_HidingSpot Interface)
#### `CanEnterHideSpot` → `Boolean`
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `RequestingPawn` | `APawn` | The pawn wanting to enter |
- **Flow:**
1. If bOccupied: return false (someone is already hiding)
2. If not bIsAvailable: return false (cooldown or one-time use expired)
3. Validate movement state of requesting pawn
4. Return true
#### `OnEnterHideSpot` → `S_HideSpotData`
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `EnteringPawn` | `APawn` | The pawn entering |
- **Flow:**
1. Set bOccupied = true
2. Set OccupantPawn = EnteringPawn
3. Play EnterMontage on EnteringPawn mesh
4. Move pawn to PlayerHidingLocation
5. Set pawn collision to NoCollision
6. Set pawn visibility to Hidden
7. If bCanBeLocked: enable lock input
8. If bIsSavePoint: trigger auto-save via GM_CoreGameMode
9. Return HideSpotData to BPC_HidingSystem
#### `OnExitHideSpot` → `void`
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `ExitingPawn` | `APawn` | The pawn exiting |
- **Flow:**
1. Move pawn to PlayerExitLocation
2. Restore pawn collision and visibility
3. Set bOccupied = false
4. Set OccupantPawn = None
5. Set LockedByPlayer = false
6. Play ExitMontage
7. If bIsOneTimeUse: set bIsAvailable = false, destroy actor
8. Else: start cooldown timer
#### `GetPeekTransform` → `Transform`
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Direction` | `E_PeekDirection` | Which direction to peek |
- **Flow:**
1. If Direction == Left: return PeekLeftLocation
2. If Direction == Right: return PeekRightLocation
#### `GetDetectionModifier` → `Float, Float`
- **Description:** Returns (range modifier, speed modifier) for enemy AI detection checks.
- **Flow:**
1. Return (DetectionRangeModifier, DetectionSpeedModifier)
#### `IsOccupied` → `Boolean`
- **Flow:** Return bOccupied
### BP_HidingSpotBase — I_Interactable Implementation
#### `ExecuteInteraction` → `void`
- **Flow:**
1. Get interactor pawn
2. Call BPC_HidingSystem.EnterHideSpot on the pawn, passing self reference
#### `GetInteractionLabel` → `FText`
- **Flow:**
1. If bOccupied: return "Occupied"
2. Return "Hide" or "Enter"
#### `CancelInteraction` → `void`
- **Flow:** (no-op for hiding spots)
#### `SetHighlighted` → `void`
- **Flow:**
1. Toggle highlight on door/mesh if bHighlighted
---
## 5. Event Dispatchers (BP_HidingSpotBase)
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnHideSpotEntered` | `APawn Occupant` | `Public` | A pawn entered this spot |
| `OnHideSpotExited` | `APawn PreviousOccupant` | `Public` | A pawn left this spot |
| `OnDoorLocked` | `APawn Occupant` | `Public` | Player locked door from inside |
| `OnDoorUnlocked` | `APawn Occupant` | `Public` | Player unlocked door |
| `OnSpotDestroyed` | `-` | `Public` | Spot used up (one-time) |
---
## 6. Blueprint Graph Logic Flow
```mermaid
sequenceDiagram
participant P as BPC_HidingSystem
participant S as BP_HidingSpotBase
participant I as Interface I_HidingSpot
P->>S: CanEnterHideSpot
S-->>P: Boolean
alt Spot Available
P->>P: RequestCameraState(Hiding)
P->>S: OnEnterHideSpot
S->>S: Set bOccupied = true
S->>S: Move pawn to HideSpotTransform
S->>S: Set pawn collision/visibility
S->>S: Play EnterMontage
S-->>P: Return S_HideSpotData
P->>P: Start Hiding state machine
S->>S: Fire OnHideSpotEntered
else Spot Occupied
P->>P: Show "Occupied" message
end
```
---
## 7. Communication Matrix
| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `I_HidingSpot` / `BP_HidingSpotBase` | `Interface` | `CanEnterHideSpot`, `OnEnterHideSpot`, `OnExitHideSpot` called by `BPC_HidingSystem` |
| `BP_HidingSpotBase` | `I_Interactable` | Implements interface — detected by `BPC_InteractionDetector` |
| `BP_HidingSpotBase` | `Dispatcher` | `OnHideSpotEntered` / `OnHideSpotExited` -> `BPC_PlayerMetricsTracker` |
| `BP_HidingSpotBase` | `Dispatcher` | `OnDoorLocked` -> `BP_AudioManager` (play lock sound) |
| `BP_HidingSpotBase` | `Direct` | Auto-save via `GM_CoreGameMode.RequestAutoSave` |
| `BP_HidingSpotBase` | `I_Persistable` | Save/load `bOccupied`, `LockedByPlayer`, `bIsAvailable` |
---
## 8. Validation / Testing Checklist
- [ ] Player can enter an unoccupied hiding spot
- [ ] Player cannot enter an occupied hiding spot
- [ ] Entering moves pawn to correct transform location
- [ ] Exiting returns pawn to exit transform
- [ ] Collision disabled while hidden, restored on exit
- [ ] Peek transforms position camera correctly
- [ ] Lock/unlock door works and blocks AI detection access
- [ ] One-time use spots are destroyed after exit
- [ ] Cooldown prevents immediate re-entry
- [ ] Auto-save triggers when bIsSavePoint is true
- [ ] AI detection modifiers correctly reduce detection range/speed
- [ ] Player must be crouching to enter if bRequiresCrouch = true
- [ ] Player cannot sprint into hide if bOnlyAllowSneakEnter = true
- [ ] Edge case: Spot destroyed while player inside — player forced out safely
- [ ] Edge case: Player exit blocked by another actor — exit location adjusted
- [ ] Edge case: Re-entering immediately after exit respects cooldown
---
## 9. Reuse Notes
- Create child blueprints of `BP_HidingSpotBase` for specific spot types (locker, desk, vent, closet).
- Override `OnEnterHideSpot` and `OnExitHideSpot` in child blueprints for custom animations and VFX.
- Place `PeekLeftLocation` and `PeekRightLocation` scene components in the child blueprint to visualise peek positions in the editor.
- For open-world spots (shadow hiding): set `SpotType = Shadow`, leave `HideSpotTransforms.PlayerHidingLocation` at the standing position, and do not disable collision.
- The detection modifier system allows designers to create "risky" hiding spots vs completely safe ones.
- Editor visualization: draw debug spheres at each transform location for quick placement validation.
---
*Blueprint Spec: Hiding Spot Interface & Actor. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework.*

View File

@@ -0,0 +1,370 @@
# `BPC_DiegeticDisplay` — Diegetic Display System
**Parent Class:** `ActorComponent`
**Category:** Interaction / UI
**Target UE Version:** 5.55.7
**Build Phase:** 2 — Interaction
---
## 1. Overview
`BPC_DiegeticDisplay` manages any in-world screen that renders game UI directly inside the 3D scene — watches, PDAs, tablets, computer monitors, cockpit screens. Instead of traditional HUD overlays, the player looks down at their character's wrist (watch) or picks up a tablet to see inventory/map/messages rendered as a world-space widget on a static mesh.
The component provides a 6-mode state machine (`Off → Splash → Idle → Menu → Messaging → Mapping/Scanning`), handles input routing to the active widget, manages screen transitions (flicker, boot sequence, static interference), and communicates with other systems via Event Dispatchers.
---
## 2. Mermaid — Display Mode State Machine
```mermaid
flowchart TD
A[Off] --> B{Power On?}
B -->|Yes| C[Splash]
C --> D[Idle]
D --> E{User Input?}
E -->|Open Menu| F[Menu]
E -->|Open Map| G[Mapping]
E -->|Receive Message| H[Messaging]
E -->|Activate Scan| I[Scanning]
F --> J{Close Menu?}
J -->|Yes| D
G --> K{Close Map?}
K -->|Yes| D
H --> L{Message Dismissed?}
L -->|Yes| D
I --> M{Scan Complete?}
M -->|Yes| D
D --> N{Idle Timeout?}
N -->|Yes| A
```
---
## 3. Enums
### `E_DiegeticDisplayMode`
| Value | Description |
|-------|-------------|
| `Off` | Screen completely off (black/no widget). |
| `Splash` | Boot-up animation playing (logo, startup sequence). |
| `Idle` | Default active state. May show time, low-priority info. |
| `Menu` | Full menu — inventory, settings, journal. |
| `Messaging` | Incoming/outgoing message display. |
| `Mapping` | Map or floorplan overlay. |
| `Scanning` | Active scanning mode (environment analysis, entity detection). |
### `E_ScreenEffect`
| Value | Description |
|-------|-------------|
| `None` | No effect — clean image. |
| `Static` | Analog TV static / interference. |
| `Flicker` | Rapid on/off flicker (power fluctuation). |
| `Glitch` | Digital artifact corruption. |
| `ScanLine` | CRT scan lines overlay. |
| `BootSequence` | OS-style boot animation (loading bars, text crawl). |
| `LowBattery` | Dim + pulsing warning overlay. |
### `E_DisplayInputMode`
| Value | Description |
|-------|-------------|
| `Locked` | Display ignores player input. |
| `Passthrough` | Input forwarded to active widget. |
| `Modal` | Input consumed entirely by display (menu open). |
---
## 4. Structs
### `S_DiegeticDisplayConfig`
| Field | Type | Description |
|-------|------|-------------|
| `DisplayName` | `FText` | Human-readable name (e.g., "Wrist Link", "PDA-7"). |
| `DefaultMode` | `E_DiegeticDisplayMode` | Mode to start in at BeginPlay. |
| `bStartPoweredOn` | `bool` | If false, starts in Off mode. |
| `WidgetClass` | `TSubclassOf<UUserWidget>` | World-space widget class to render on the screen. |
| `ScreenMeshComponent` | `FName` | Name of the static mesh component the widget renders on. |
| `ScreenSize` | `FVector2D` | Widget resolution in pixels (e.g., 256x144). |
| `InteractionDistance` | `float` | Max distance to interact with the display (0 = attached to player). |
| `bIsPlayerOwned` | `bool` | If true, attached to player (watch) vs. world object (terminal). |
| `IdleTimeoutSeconds` | `float` | Seconds of inactivity before powering off. 0 = never timeout. |
| `BootDuration` | `float` | Seconds the Splash animation plays. |
| `bHasMapMode` | `bool` | If true, Mapping mode is available. |
| `bHasScanMode` | `bool` | If true, Scanning mode is available. |
| `bReplicates` | `bool` | Whether display state is replicated. |
### `S_ScreenState`
| Field | Type | Description |
|-------|------|-------------|
| `CurrentMode` | `E_DiegeticDisplayMode` | Active display mode. |
| `ActiveEffect` | `E_ScreenEffect` | Currently playing visual effect. |
| `EffectIntensity` | `float` | 01 intensity of the active effect. |
| `InputMode` | `E_DisplayInputMode` | Current input routing mode. |
| `BatteryLevel` | `float` | 01 remaining battery (if applicable). |
| `bIsPoweredOn` | `bool` | Quick check for power state. |
### `S_MessagePayload`
| Field | Type | Description |
|-------|------|-------------|
| `SenderName` | `FText` | Name of message sender. |
| `MessageBody` | `FText` | Message text content. |
| `bIsUrgent` | `bool` | If true, forces display to Messaging mode with priority. |
| `AssociatedQuestTag` | `FGameplayTag` | Quest/objective this message relates to. |
| `AudioAttachment` | `USoundBase*` | Optional audio clip attached to message. |
---
## 5. Variables
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Description |
|----------|------|-------------|
| `DisplayConfig` | `S_DiegeticDisplayConfig` | Primary configuration struct. |
| `IdleWidget` | `TSubclassOf<UUserWidget>` | Widget to display in Idle mode. |
| `MenuWidget` | `TSubclassOf<UUserWidget>` | Widget to display in Menu mode. |
| `MessagingWidget` | `TSubclassOf<UUserWidget>` | Widget for incoming/outgoing messages. |
| `MapWidget` | `TSubclassOf<UUserWidget>` | Widget for mapping overlay. |
| `ScanWidget` | `TSubclassOf<UUserWidget>` | Widget for scanning mode. |
### State (Blueprint Read Only)
| Variable | Type | Description |
|----------|------|-------------|
| `CurrentState` | `S_ScreenState` | Struct holding all current screen state. |
| `ActiveWidget` | `UUserWidget*` | Reference to the currently displayed widget instance. |
| `ScreenMesh` | `UStaticMeshComponent*` | Cached reference to the screen mesh. |
| `IdleTimerHandle` | `FTimerHandle` | Handle for idle power-off timer. |
| `BootTimerHandle` | `FTimerHandle` | Handle for boot-up duration timer. |
| `PendingMessages` | `TArray<S_MessagePayload>` | Queue of messages to display. |
| `CurrentMessageIndex` | `int32` | Index into PendingMessages for cycling. |
### Input Handling (Blueprint Read Only)
| Variable | Type | Description |
|----------|------|-------------|
| `bInputConsumed` | `bool` | Whether the display is currently consuming input. |
| `InputActionBindings` | `TArray<FInputActionBinding>` | Active input bindings for display mode. |
---
## 6. Functions & Events
### Public Functions
| Function | Description |
|----------|-------------|
| `PowerOn` | Boots the display. Plays Splash sequence, then transitions to Idle. |
| `PowerOff` | Immediately turns off display, clears widget, kills idle timer. |
| `SetDisplayMode` | Transitions to any `E_DiegeticDisplayMode`. Plays transition effect. |
| `ApplyScreenEffect` | Applies a temporary `E_ScreenEffect` for a given duration. |
| `ClearScreenEffect` | Immediately clears active effect, returns to clean image. |
| `ReceiveMessage` | Adds a `S_MessagePayload` to the queue. If current mode is Idle, auto-switches to Messaging. |
| `DismissMessage` | Closes current message. If queue has more, shows next; else returns to Idle. |
| `OpenMenu` | Transitions to Menu mode. Locks input to display. |
| `CloseMenu` | Returns to Idle mode. Releases input. |
| `OpenMap` | Transitions to Mapping mode (if `bHasMapMode`). |
| `CloseMap` | Returns to Idle mode. |
| `StartScan` | Begins Scanning mode (if `bHasScanMode`). |
| `StopScan` | Ends Scanning mode, returns to Idle. |
| `ToggleDisplay` | Toggles between current mode and Off/Idle based on power state. |
| `IsDisplayActive` | Returns true if powered on and not Off/Splash/Boot. |
| `GetScreenState` | Returns the `S_ScreenState` struct. |
### Protected Functions
| Function | Description |
|----------|-------------|
| `BeginPlay` | Caches references, creates widget instance if auto-start. |
| `Tick` | If `ActiveEffect != None`, applies effect material parameter animation. |
| `CreateWidgetInstance` | Creates the world-space widget for the given mode class. Attaches to `ScreenMesh`. |
| `DestroyWidgetInstance` | Removes and destroys current widget. |
| `PlayBootSequence` | Timelines splash animation. On complete, calls `OnBootComplete`. |
| `OnBootComplete` | Transitions to Idle, starts idle timeout timer. |
| `StartIdleTimer` | Resets and starts the idle timeout. |
| `OnIdleTimeout` | Powers off the display. |
| `SetupInputForMode` | Binds/unbinds input actions based on `CurrentState.InputMode`. |
| `HandleMenuInput` | Processes navigation/select inputs in Menu mode. |
| `HandleMessageInput` | Processes dismiss/respond inputs in Messaging mode. |
| `HandleMapInput` | Processes pan/zoom inputs in Mapping mode. |
| `HandleScanInput` | Processes scan activation input. |
### Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnDisplayModeChanged` | `E_DiegeticDisplayMode NewMode`, `E_DiegeticDisplayMode PreviousMode` | Fired on any mode transition. |
| `OnDisplayPoweredOn` | — | Fired after boot sequence completes. |
| `OnDisplayPoweredOff` | — | Fired when display is turned off. |
| `OnMessageReceived` | `S_MessagePayload Message` | Fired when a new message enters the queue. |
| `OnMessageDismissed` | `S_MessagePayload Message` | Fired when a message is dismissed. |
| `OnScreenEffectStarted` | `E_ScreenEffect Effect`, `float Duration` | Fired when a screen effect begins. |
| `OnScreenEffectEnded` | `E_ScreenEffect Effect` | Fired when a screen effect ends. |
| `OnDisplayInputLocked` | `bool bIsLocked` | Fired when input mode changes to Locked or unlocked. |
---
## 7. Blueprint Graph Flow
```
Event BeginPlay
→ GetOwner → FindComponentByTag (ScreenMeshComponent name) → Cache ScreenMesh
→ If DisplayConfig.bStartPoweredOn → Call PowerOn
→ Else → Set CurrentState.CurrentMode = Off
PowerOn
→ Set CurrentState.bIsPoweredOn = true
→ Set CurrentState.InputMode = Locked
→ Broadcast OnDisplayModeChanged (Off → Splash)
→ PlayBootSequence
PlayBootSequence
→ ApplyScreenEffect (BootSequence)
→ Set Timer by Event (DisplayConfig.BootDuration, Call OnBootComplete)
OnBootComplete
→ ClearScreenEffect
→ Set CurrentState.CurrentMode = Idle
→ CreateWidgetInstance (IdleWidget)
→ Set CurrentState.InputMode = Passthrough
→ Broadcast OnDisplayPoweredOn
→ Broadcast OnDisplayModeChanged (Splash → Idle)
→ StartIdleTimer
SetDisplayMode
→ Store PreviousMode = CurrentState.CurrentMode
→ If PreviousMode == NewMode → return
→ DestroyWidgetInstance
→ Broadcast OnDisplayModeChanged (PreviousMode → NewMode)
→ Set CurrentState.CurrentMode = NewMode
→ Branch on NewMode:
— Menu → CreateWidgetInstance (MenuWidget), SetupInputForMode (Modal)
— Messaging → CreateWidgetInstance (MessagingWidget), SetupInputForMode (Modal)
— Mapping → CreateWidgetInstance (MapWidget), SetupInputForMode (Modal)
— Scanning → CreateWidgetInstance (ScanWidget), SetupInputForMode (Modal)
— Idle → CreateWidgetInstance (IdleWidget), SetupInputForMode (Passthrough), StartIdleTimer
→ If NewMode != Idle → Clear idle timer
ReceiveMessage
→ PendingMessages.Add(Message)
→ If CurrentState.CurrentMode == Idle:
→ SetDisplayMode (Messaging)
→ If CurrentState.CurrentMode == Messaging:
→ Update widget to show new message count
→ Broadcast OnMessageReceived
DismissMessage
→ Remove CurrentMessage from PendingMessages
→ If PendingMessages.Num() > 0:
→ Show next message
→ Else:
→ SetDisplayMode (Idle)
→ Broadcast OnMessageDismissed
PowerOff
→ ClearScreenEffect
→ DestroyWidgetInstance
→ Clear Input Bindings
→ Set CurrentState.bIsPoweredOn = false
→ Set CurrentState.CurrentMode = Off
→ Clear IdleTimerHandle
→ Broadcast OnDisplayPoweredOff
→ Broadcast OnDisplayModeChanged (previous → Off)
OpenMenu
→ SetDisplayMode (Menu)
CloseMenu
→ SetDisplayMode (Idle)
Event Tick (DeltaTime)
→ If ActiveEffect != None and ActiveEffectDuration > 0:
→ Update material parameter for effect animation (flicker intensity, static noise)
→ Decrement remaining duration
→ If duration expired → ClearScreenEffect
```
---
## 8. Replication
| Variable | Replication | Callback |
|----------|-------------|----------|
| `CurrentState.CurrentMode` | `RepNotify` | `OnRep_DisplayMode` — recreates widget on remote clients |
| `CurrentState.ActiveEffect` | `Replicated` | — |
| `CurrentState.bIsPoweredOn` | `Replicated` | — |
**Authority:** Server controls power/mode transitions. Client predicts input for Menu/Message dismissal, but server validates.
---
## 9. Widget Setup (Per-Mode)
| Mode | Widget Content |
|------|----------------|
| `Idle` | Time display, low-priority notifications, battery indicator. |
| `Menu` | Radial or list menu: Inventory, Journal, Settings, Map, Messages. |
| `Messaging` | Scrolling text log with sender avatar, reply options, audio playback. |
| `Mapping` | 2D floorplan with player position marker, discovered rooms, objective markers. |
| `Scanning` | Overlaid data readouts: entity heat signatures, material composition, structural integrity. |
All widgets are added as `UUserWidget` instances attached to the screen mesh via `AddToViewport`/`SetWidget` on a `UWidgetComponent`. The component handles creation/destruction; individual widgets handle their own internal state.
---
## 10. Dependencies & Communication
| System | Relationship |
|--------|--------------|
| `BPC_InteractionDetector` | Detects world terminals; calls `Interact_Implementation` on the host actor. |
| `BPC_InventoryComponent` | Menu mode reads inventory contents to display in widget. |
| `BPC_MappingSubsystem` | Supplies floorplan data to Map widget. |
| `BPC_ScanningSubsystem` | Supplies scan results to Scan widget. |
| `GI_GameFramework` | Provides game time, date, and phase info for idle widget display. |
| `BPC_StressSystem` | High stress may trigger screen flicker/glitch effects. |
| `BPC_HealthSystem` | Low health may apply low battery / dimming effect. |
| `BPC_PlayerMetricsTracker` | Logs display usage events for analytics. |
| `BPC_AdaptiveDifficulty` | May adjust idle timeout or boot duration based on player performance. |
| `Save/Load System` | Saves `CurrentState` and `PendingMessages` array for restore. |
| `Narrative Subsystem` | Pushes messages via `ReceiveMessage` for story-driven communication. |
---
## 11. Success Criteria
1. Display boots with splash sequence and transitions to idle.
2. Player can open/close menu from idle.
3. Receiving a message from narrative subsystem forces display to Messaging mode.
4. Player dismisses message and display returns to idle.
5. Display powers off after idle timeout; interact to power back on.
6. Screen effects (static, flicker, glitch) play on demand and clear correctly.
7. Stress/health systems trigger appropriate visual feedback on the display.
8. Multiplayer: display mode syncs across clients.
9. Save/load restores display mode, pending messages, and effect state.
10. Multiple displays (watch + terminal) operate independently with separate state.
---
## 12. Data Flow Summary
```
External System (e.g. Narrative)
→ calls ReceiveMessage (S_MessagePayload)
→ BPC_DiegeticDisplay.PendingMessages.Add
→ Auto-switches to Messaging mode if currently Idle
→ Broadcast OnMessageReceived
→ Widget shows message content
→ Player dismisses → DismissMessage
→ Broadcast OnMessageDismissed
→ If queue empty → return to Idle
Player Input (Menu)
→ Input routed via SetupInputForMode (Modal)
→ Widget handles navigation
→ On close → CloseMenu → SetDisplayMode (Idle)

View File

@@ -0,0 +1,339 @@
# `BP_DoorActor` — Door Actor System
**Parent Class:** `Actor`
**Category:** Interaction
**Implements:** `I_Interactable`
**Target UE Version:** 5.55.7
**Build Phase:** 2 — Interaction
---
## 1. Overview
`BP_DoorActor` powers all door-like actors in the game world — standard hinged doors, sliding doors, double doors, and barricaded passages. It manages a discrete 6-state machine (`Closed → Opening → Open → Closing → Locked → Barricaded`), supports key/lock mechanics, item-required unlocking, one-way passage, partial-open positions, and networked replication.
The door state is exposed via Event Dispatchers so other systems (AudioManager, CameraStateLayer, AI, Narrative) can react.
---
## 2. Mermaid — Door State Machine & Interaction Flow
```mermaid
flowchart TD
A[Idle Closed] --> B{Interact?}
B -->|Player presses Interact| C[TryOpen]
C --> D{Is Locked?}
D -->|Yes: Has Required Item?| E{Remove Item?}
D -->|Yes: No Item| F[Play Locked Feedback]
E -->|Yes| G[Unlock & Open]
E -->|No| F
D -->|No| H[Play Open Anim]
H --> I[State = Opening]
I --> J[State = Open]
J --> K{Close Conditions Met?}
K -->|Auto-Close Timer| L[Play Close Anim]
K -->|Player Interact| L
K -->|Manual Call| L
L --> M[State = Closing]
M --> A
N[Locked Entry] --> O[State = Locked]
P[Barricaded Entry] --> Q[State = Barricaded]
Q --> R{Barricade Broken?}
R -->|Yes| A
R -->|No| Q
```
---
## 3. Enums
### `E_DoorState`
Defined in `E_DoorState` enum asset.
| Value | Description |
|-------|-------------|
| `Closed` | Door fully closed, no movement. Can be interacted with. |
| `Opening` | Door playing open animation. Input blocked. |
| `Open` | Door fully open. Can be interacted with to close, or auto-closes. |
| `Closing` | Door playing close animation. Input blocked. |
| `Locked` | Door locked. Cannot be opened unless unlocked via key/item or external trigger. |
| `Barricaded` | Door physically blocked. Must be destroyed/breached. |
### `E_DoorType`
| Value | Description |
|-------|-------------|
| `Hinged` | Standard door that swings open/closed. |
| `Sliding` | Door slides horizontally into a wall pocket. |
| `Double` | Two doors that open outward/inward. |
| `RollUp` | Garage-style door that rolls upward. |
| `TrapDoor` | Floor/ceiling door that opens vertically. |
### `E_LockState`
Optional sub-state for locked doors.
| Value | Description |
|-------|-------------|
| `Unlocked` | Door can be opened normally. |
| `KeyRequired` | Requires a specific key item in inventory. |
| `ItemRequired` | Requires a specific non-key item (crowbar, code). |
| `PuzzleLinked` | Lock is controlled by an external puzzle actor. |
| `Breachable` | Lock can be broken with force (weapon/explosive). |
---
## 4. Structs
### `S_DoorConfig`
| Field | Type | Description |
|-------|------|-------------|
| `DoorType` | `E_DoorType` | Visual/mechanical type of door. |
| `DefaultState` | `E_DoorState` | State the door starts in at BeginPlay. |
| `LockState` | `E_LockState` | Lock type if DefaultState is Locked. |
| `RequiredItemTag` | `FGameplayTag` | Tag of item required to unlock (if KeyRequired/ItemRequired). |
| `RemoveItemOnUse` | `bool` | If true, the key/item is consumed on unlock. |
| `AutoCloseDelay` | `float` | Seconds before door auto-closes. 0 = never auto-close. |
| `OpenAngle` | `float` | Degrees the door opens (default 90). |
| `OpenSpeed` | `float` | Animation play rate / interpolation speed. |
| `CloseSpeed` | `float` | Animation play rate for closing. |
| `IsOneWay` | `bool` | If true, door only opens from one side. |
| `CanBeBarricaded` | `bool` | If true, door can transition to Barricaded state. |
| `BarricadeHealth` | `float` | Damage required to break barricade. |
| `bReplicates` | `bool` | Whether door state is replicated. |
### `S_DoorAudioConfig`
| Field | Type | Description |
|-------|------|-------------|
| `OpenSound` | `USoundBase*` | Sound played when door begins opening. |
| `CloseSound` | `USoundBase*` | Sound played when door begins closing. |
| `LockedSound` | `USoundBase*` | Sound played when player tries to open a locked door. |
| `UnlockSound` | `USoundBase*` | Sound played when door is unlocked. |
| `BarricadeBreakSound` | `USoundBase*` | Sound played when barricade is destroyed. |
| `SqueakInterval` | `float` | Seconds between squeak sounds during movement (0 = no squeak). |
---
## 5. Variables
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Description |
|----------|------|-------------|
| `DoorConfig` | `S_DoorConfig` | Primary configuration struct. |
| `AudioConfig` | `S_DoorAudioConfig` | Audio configuration struct. |
| `LinkedActors` | `TArray<AActor*>` | Actors to notify on door open/close (lights, alarms, traps). |
| `RequiredItemTag` | `FGameplayTag` | Shortcut to DoorConfig.RequiredItemTag (for BP pin). |
### State (Blueprint Read Only, Replicated)
| Variable | Type | Description |
|----------|------|-------------|
| `CurrentState` | `E_DoorState` | Current door state. Replicated using `OnRep_DoorState`. |
| `CurrentLockState` | `E_LockState` | Current lock state. Replicated. |
| `CurrentBarricadeHealth` | `float` | Remaining barricade health. Replicated. |
| `bIsOpenFromFront` | `bool` | Tracks which side the door was opened from (for one-way logic). |
### Internal (Blueprint Read Only, Not Replicated)
| Variable | Type | Description |
|----------|------|-------------|
| `OwningDoorActor` | `AActor*` | Cached reference to owning actor (BP_DoorBase). |
| `DoorMeshComponent` | `UStaticMeshComponent*` | Cached reference to the door's static mesh (if hinged/sliding). |
| `DoorAudioComponent` | `UAudioComponent*` | Cached audio component for spatialized sounds. |
| `AutoCloseTimerHandle` | `FTimerHandle` | Handle for auto-close timer. |
| `AnimationTimeline` | `float` | Internal 0-1 progress of open/close animation. |
---
## 6. Functions & Events
### Public Functions
| Function | Description |
|----------|-------------|
| `Interact_Implementation` | Implements `I_Interactable.ExecuteInteraction`. Routes to `TryOpen` if Closed/Locked/Barricaded, or `TryClose` if Open. |
| `TryOpen` | Checks state: if Locked, attempts unlock (check inventory or puzzle); if Barricaded, plays blocked feedback; if Closed, begins open animation. Returns `E_DoorOperationResult`. |
| `TryClose` | If Open, begins close animation. If Opening/Closing, ignores. Returns bool. |
| `LockDoor` | Transitions to Locked state. Optionally sets lock type and required item. |
| `UnlockDoor` | Removes lock, plays unlock effects. If `bAutoOpenOnUnlock`, begins opening. |
| `BarricadeDoor` | Transitions to Barricaded state, sets health. |
| `DamageBarricade` | Reduces barricade health by damage amount. If health reaches 0, removes barricade and transitions to Closed. |
| `ForceSetState` | Bypasses animation; immediately sets door to any valid state. Used for save/load. |
| `IsDoorUsable` | Returns true if door can be interacted with (not Opening/Closing/Barricaded with health). |
| `GetDoorState` | Returns current `E_DoorState`. |
| `GetDoorType` | Returns `E_DoorType` from config. |
### Protected Functions
| Function | Description |
|----------|-------------|
| `BeginPlay` | Caches references, applies default state, initialises audio component. |
| `PlayOpenAnimation` | Starts timeline/interp for door rotation/slide. Plays open sound. Calls `OnOpenComplete` when finished. |
| `PlayCloseAnimation` | Starts timeline/interp for reverse. Plays close sound. Calls `OnCloseComplete` when finished. |
| `OnOpenComplete` | Sets state to Open, clears auto-close timer if `AutoCloseDelay > 0`, notifies `LinkedActors`. |
| `OnCloseComplete` | Sets state to Closed. |
| `TryUnlockWithItem` | Checks player inventory for `RequiredItemTag`. If found and `RemoveItemOnUse`, consumes the item. Returns bool. |
| `CheckPuzzleUnlockCondition` | Returns true if linked puzzle is solved. |
| `PlayLockedFeedback` | Plays locked sound + optional UI prompt notifying player of required item. |
| `OnRep_DoorState` | RepNotify: when `CurrentState` changes, plays appropriate animation on remote clients. |
### Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnDoorStateChanged` | `E_DoorState NewState`, `AActor* Instigator` | Fired on any state transition. |
| `OnDoorOpened` | `AActor* Instigator`, `bool bFromFront` | Fired when door reaches Open state. |
| `OnDoorClosed` | `AActor* Instigator` | Fired when door reaches Closed state. |
| `OnDoorLocked` | `AActor* Instigator` | Fired when door transitions to Locked. |
| `OnDoorUnlocked` | `AActor* Instigator` | Fired when door is unlocked. |
| `OnBarricadeBroken` | `AActor* Instigator` | Fired when barricade health reaches 0. |
| `OnInteractionFailed` | `E_DoorState CurrentState`, `FText FailReason` | Fired when player cannot interact. |
---
## 7. Blueprint Graph Flow
### Event Graph Flow
```
Event BeginPlay
→ GetOwner → Cast to BP_DoorBase → Cache OwningDoorActor
→ FindComponentByClass UStaticMeshComponent → Cache DoorMeshComponent
→ Create Audio Component → Cache
→ Apply Default State from DoorConfig.DefaultState
→ If Locked → Set CurrentLockState → LockDoor
On Interact_Implementation
→ Branch: CurrentState
— Closed → Call TryOpen
— Locked → Call TryUnlockWithItem → Branch Result
— Success → Play Unlock Effects → Call TryOpen
— Fail → Play LockedFeedback → Broadcast OnInteractionFailed
— Barricaded → Play Blocked Feedback → Broadcast OnInteractionFailed
— Open → Call TryClose
— Opening/Closing → Ignore (return)
TryOpen
→ IsDoorUsable? → If not, return false
→ Set CurrentState = Opening
→ Broadcast OnDoorStateChanged
→ Set bIsOpenFromFront = (player side check)
→ PlayOpenAnimation
TryClose
→ IsDoorUsable? → If not, return false
→ Set CurrentState = Closing
→ Broadcast OnDoorStateChanged
→ Clear AutoCloseTimerHandle
→ PlayCloseAnimation
PlayOpenAnimation
→ Timeline: 0→1 over 1/OpenSpeed seconds
→ Interp: DoorMeshComponent RelativeRotation.Yaw from 0 → OpenAngle (or DoorConfig sign for direction)
→ PlaySound: AudioConfig.OpenSound
→ On Finished → OnOpenComplete
PlayCloseAnimation
→ Timeline: 1→0 over 1/CloseSpeed seconds
→ Interp: DoorMeshComponent RelativeRotation.Yaw from current → 0
→ PlaySound: AudioConfig.CloseSound
→ On Finished → OnCloseComplete
OnOpenComplete
→ Set CurrentState = Open
→ Broadcast OnDoorOpened
→ If AutoCloseDelay > 0 → Set Timer by Event (AutoCloseDelay, Call TryClose)
→ Notify LinkedActors (Open event)
OnCloseComplete
→ Set CurrentState = Closed
→ Broadcast OnDoorClosed
→ Notify LinkedActors (Close event)
LockDoor
→ Set CurrentState = Locked
→ Set CurrentLockState = Input LockState
→ Broadcast OnDoorLocked
UnlockDoor
→ Set CurrentLockState = Unlocked
→ If bAutoOpenOnUnlock → Call TryOpen
→ Broadcast OnDoorUnlocked
DamageBarricade
→ CurrentBarricadeHealth -= Damage
→ If CurrentBarricadeHealth <= 0
→ Set CurrentState = Closed
→ Broadcast OnBarricadeBroken
→ Broadcast OnDoorStateChanged
```
---
## 8. Replication
| Variable | Replication | Callback |
|----------|-------------|----------|
| `CurrentState` | `RepNotify` | `OnRep_DoorState` — plays matching animation on remote |
| `CurrentLockState` | `Replicated` | — |
| `CurrentBarricadeHealth` | `Replicated` | — |
| `bIsOpenFromFront` | `Replicated` | — |
**Server authority:** All state transitions are executed on the server. Clients predict input via `Interact_Implementation`, but the server validates and broadcasts the authoritative state.
---
## 9. Dependencies & Communication
| System | Relationship |
|--------|--------------|
| `BPC_InteractionDetector` | Calls `Interact_Implementation` when player looks at door and presses Interact. |
| `BPC_InventorySystem` | Queried via `TryUnlockWithItem` for item possession and consumption. |
| `BPC_HealthSystem` | Listens to `OnBarricadeBroken` for environmental damage credit. |
| `BPC_CameraStateLayer` | May request FOV push when door opens into a large space. |
| `AudioManager` | Consumes `AudioConfig` and may play ambient/occlusion changes on door state. |
| `AI Perception` | AI listens to `OnDoorOpened`/`OnDoorClosed` to update pathfinding and awareness. |
| `Save/Load System` | Calls `ForceSetState` and `LockDoor`/`UnlockDoor` during restore. |
| `Narrative Subsystem` | May bind to `OnDoorUnlocked` to trigger dialogue when a story-key door is opened. |
| `BP_PuzzleDeviceActor` | `PuzzleLinked` lock type — puzzle completion calls `UnlockDoor`. |
| `BPC_DifficultyManager` | May adjust `AutoCloseDelay` and `BarricadeHealth` based on player performance metrics. |
---
## 10. Success Criteria
1. Player can open/close a hinged door with standard interaction.
2. Locked door plays feedback sound and shows item-required prompt.
3. Player with correct key/item unlocks door; item is consumed if configured.
4. Door auto-closes after configurable delay; auto-close timer resets on re-open.
5. Barricaded door blocks passage until its health reaches 0 via damage.
6. `PuzzleLinked` door unlocks when linked `BP_PuzzleDeviceActor` reports completion.
7. One-way doors only open from the configured side.
8. Double doors open/close in sync as a paired animation.
9. Multiplayer: server-authoritative state syncs to all clients via `OnRep_DoorState`.
10. Save/load correctly restores door state, lock state, and barricade health.
---
## 11. Data Flow Summary
```
Player Presses Interact
→ BPC_InteractionDetector.ScanForInteractables
→ Closest valid target = BP_DoorActor
→ Call I_Interactable.ExecuteInteraction
→ BP_DoorActor.Interact_Implementation
→ State check / lock check / inventory check
→ Play animation / sound
→ Broadcast Event Dispatchers
→ Downstream systems react (AI, Audio, Narrative, Save)
```
## 12. Reuse Notes
- This renamed file (formerly `BPC_InteractableDoorComponent`) is now an Actor-based system (`BP_DoorActor`) as per Master Section 3.5.
- The door actor encapsulates all door logic directly rather than as an ActorComponent.
- Cross-references updated: `BPC_InventoryComponent``BPC_InventorySystem`, `BPC_LeverPuzzleComponent``BP_PuzzleDeviceActor`.

View File

@@ -0,0 +1,97 @@
# BP_PuzzleDeviceActor — Puzzle Device Actor
**Parent Class:** `Actor`
**Category:** Interaction
**Target UE Version:** 5.55.7
**Build Phase:** 2 — Interaction
---
## 1. Overview
`BP_PuzzleDeviceActor` is the base actor for all puzzle devices in the world — levers, pressure plates, valve wheels, keypads, combination locks, circuit boards, and custom logic puzzles. Each instance references a [`DA_PuzzleData`](../14-data-assets/DA_PuzzleData.md) that defines the puzzle rules, solution, and completion effects.
---
## 2. Enums
### `E_PuzzleType`
| Value | Description |
|-------|-------------|
| `Lever` | Single or multi-lever sequence |
| `PressurePlate` | Weight-activated plate |
| `ValveWheel` | Rotate-to-open valve |
| `Keypad` | Numeric code entry |
| `CombinationLock` | Multi-dial combination |
| `CircuitBoard` | Connect-the-pins puzzle |
| `Custom` | Script-driven puzzle |
### `E_PuzzleState`
| Value | Description |
|-------|-------------|
| `Unsolved` | Puzzle not yet completed |
| `InProgress` | Player interacting with puzzle |
| `Solved` | Puzzle completed successfully |
| `Failed` | Puzzle failed (if retryable) |
| `Locked` | Puzzle locked (requires item/flag) |
---
## 3. Variables
| Variable | Type | Description |
|----------|------|-------------|
| `PuzzleData` | `DA_PuzzleData*` | Data asset defining this puzzle |
| `CurrentState` | `E_PuzzleState` | Current puzzle state |
| `bIsInteractable` | `bool` | Can player interact with this puzzle |
| `InteractionPrompt` | `FText` | Prompt text for interaction |
| `LinkedActor` | `AActor*` | Actor to notify on solve (door, gate, etc.) |
| `bResetOnFail` | `bool` | Auto-reset after failure |
| `MaxAttempts` | `int32` | Max attempts before lockout (-1 = unlimited) |
| `CurrentAttempts` | `int32` | Attempts used so far |
| `CooldownSeconds` | `float` | Time before re-interaction allowed |
---
## 4. Functions
| Function | Description |
|----------|-------------|
| `BeginInteraction` | Player starts interacting with puzzle |
| `EndInteraction` | Player exits puzzle UI |
| `CheckSolution` | Validates player input against puzzle data |
| `OnPuzzleSolved` | Processes completion — notifies LinkedActor |
| `OnPuzzleFailed` | Processes failure — resets or locks |
| `ResetPuzzle` | Resets puzzle to default state |
| `GetPuzzleState` | Returns current `E_PuzzleState` |
---
## 5. Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnPuzzleStateChanged` | `E_PuzzleState NewState` | State transition occurred |
| `OnPuzzleSolved` | `AActor* Solver` | Puzzle completed |
| `OnPuzzleFailed` | `int32 AttemptNumber` | Attempt failed |
| `OnPuzzleLinkedActorTriggered` | `AActor* LinkedActor` | Linked actor notified |
---
## 6. Dependencies & Communication
| System | Relationship |
|--------|--------------|
| `DA_PuzzleData` | Defines puzzle rules and solution |
| `BPC_InteractionDetector` | Focus and interaction initiation |
| `BP_DoorActor` | Common linked actor (unlock on solve) |
| `BPC_NarrativeStateSystem` | Set narrative flags on solve |
| `SS_SaveManager` | Persist puzzle state |
---
## 7. Reuse Notes
- All puzzle logic is data-driven via `DA_PuzzleData`
- LinkedActor pattern decouples puzzle from effect

View File

@@ -0,0 +1,88 @@
# BPC_ContextualTraversalSystem — Contextual Traversal System
**Parent Class:** `ActorComponent`
**Category:** Interaction
**Target UE Version:** 5.55.7
**Build Phase:** 2 — Interaction
---
## 1. Overview
`BPC_ContextualTraversalSystem` handles player traversal of environmental obstacles — vaulting, climbing, squeezing through gaps, sliding under obstacles. Uses motion warping and root motion for smooth traversal animations triggered by context-aware detection.
---
## 2. Enums
### `E_TraversalType`
| Value | Description |
|-------|-------------|
| `Vault` | Vault over low obstacles |
| `Mantle` | Climb up onto ledges |
| `Slide` | Slide under low barriers |
| `Squeeze` | Squeeze through narrow gaps |
| `LedgeGrab` | Grab and hang from ledges |
### `E_TraversalHeight`
| Value | Description |
|-------|-------------|
| `Low` | Below knee height (step up) |
| `Medium` | Waist height (vault) |
| `High` | Chest height (mantle) |
---
## 3. Variables
| Variable | Type | Description |
|----------|------|-------------|
| `DetectionRange` | `float` | Max distance to detect traversable surfaces |
| `DetectionHalfAngle` | `float` | Cone angle for forward detection |
| `VaultHeightThreshold` | `float` | Max height for vault vs mantle decision |
| `TraversalSpeed` | `float` | Speed multiplier during traversal anim |
| `bIsTraversing` | `bool` | Currently playing traversal animation |
| `CurrentTraversalType` | `E_TraversalType` | Active traversal type |
| `MotionWarpingTarget` | `FVector` | Target location for motion warping |
| `TraversalCooldown` | `float` | Min time between traversals |
---
## 4. Functions
| Function | Description |
|----------|-------------|
| `DetectTraversableObstacle` | Performs forward trace to detect vault/mantle points |
| `AttemptTraversal` | Initiates traversal to detected point. Returns bool |
| `ExecuteTraversal` | Plays traversal montage with motion warping |
| `OnTraversalComplete` | Callback when montage finishes |
| `CancelTraversal` | Interrupts traversal (damage/player input) |
| `IsTraversing` | Returns `bIsTraversing` |
---
## 5. Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnTraversalStarted` | `E_TraversalType Type`, `FVector Target` | Traversal animation begins |
| `OnTraversalComplete` | `E_TraversalType Type` | Player reaches target position |
| `OnTraversalFailed` | `FText Reason` | Traversal attempt blocked |
---
## 6. Dependencies & Communication
| System | Relationship |
|--------|--------------|
| `BPC_MovementStateSystem` | Movement mode override during traversal |
| `BPC_CameraStateLayer` | Camera FOV adjustment during traversal |
| `BPC_StressSystem` | Stress modifier for close-call traversals |
---
## 7. Reuse Notes
- Uses UE5 Motion Warping for accurate target placement
- Detection uses capsule trace at player height ranges

View File

@@ -0,0 +1,104 @@
# BPC_PhysicsDragSystem — Physics Drag System
**Parent Class:** `ActorComponent`
**Category:** Interaction
**Target UE Version:** 5.55.7
**Build Phase:** 2 — Interaction
---
## 1. Overview
`BPC_PhysicsDragSystem` allows the player to grab and physically drag rigid-body objects in the world. Supports grab-at-distance, hold-to-grab with physics constraints, object rotation, and throw mechanics. Integrates with the interaction detector for grab targeting.
---
## 2. Enums
### `E_DragMode`
| Value | Description |
|-------|-------------|
| `PhysicsConstraint` | Attaches object via physics constraint to player hand |
| `Kinematic` | Sets object to kinematic and parents to hand |
| `Magnetic` | Objects smoothly lerp toward grab point |
---
## 3. Variables
| Name | Type | Description |
|------|------|-------------|
| `DragMode` | `E_DragMode` | Current drag physics mode |
| `GrabbedObject` | `AActor*` | Currently held actor |
| `ConstraintComp` | `UPhysicsConstraintComponent*` | Physics constraint for held object |
| `GrabDistance` | `float` | Max distance to grab (cm) |
| `HoldDistance` | `float` | Distance object is held from camera |
| `ThrowForce` | `float` | Impulse applied on release |
| `RotationSpeed` | `float` | Degrees/sec for object rotation input |
| `bCanThrow` | `bool` | Object can be thrown on release |
| `bIsGrabbing` | `bool` | Currently holding an object |
---
## 4. Functions
| Function | Description |
|----------|-------------|
| `GrabObject` | Attempts to grab targeted physics object. Returns bool. |
| `ReleaseObject` | Releases held object, applies throw force if bCanThrow. |
| `RotateObject` | Rotates held object by input axis values |
| `SetHoldDistance` | Adjusts distance of held object from camera |
| `GetGrabbedObject` | Returns currently held actor (or null) |
| `IsGrabbing` | Returns `bIsGrabbing` |
---
## 5. Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnObjectGrabbed` | `AActor* GrabbedObject` | Object successfully grabbed |
| `OnObjectReleased` | `AActor* ReleasedObject`, `bool bWasThrown` | Object released |
| `OnGrabFailed` | `FText FailReason` | Grab attempt failed |
---
## 6. Blueprint Flow
```
GrabObject:
→ Get targeted object from InteractionDetector
→ Check if object has physics simulation enabled
→ If DragMode == PhysicsConstraint:
→ Create physics constraint between hand socket and object
→ Set constraint limits (linear + angular)
→ If DragMode == Kinematic:
→ Set object simulated physics to false
→ Attach to hand socket
→ Set bIsGrabbing = true
→ Broadcast OnObjectGrabbed
ReleaseObject:
→ If bCanThrow → Apply forward impulse * ThrowForce
→ Destroy constraint / detach
→ Re-enable physics on object
→ Set bIsGrabbing = false
→ Broadcast OnObjectReleased
```
---
## 7. Dependencies & Communication
| System | Relationship |
|--------|--------------|
| `BPC_InteractionDetector` | Provides grab target via focus |
| `BPC_CameraStateLayer` | Camera direction for throw vector |
| `BPC_MovementStateSystem` | Speed modifier while carrying objects |
---
## 8. Reuse Notes
- Physics drag uses UE5 physics constraint system for realistic object handling
- Objects must have `Simulate Physics = true` and `Mass` configured

View File

@@ -0,0 +1,54 @@
# BPC_UsableWorldObjectSystem — Usable World Object System
**Parent Class:** `ActorComponent`
**Category:** Interaction
**Target UE Version:** 5.55.7
**Build Phase:** 2 — Interaction
## 1. Overview
`BPC_UsableWorldObjectSystem` powers generic usable objects in the world — switches, buttons, valves, terminals, readable notes, audio logs. Provides a unified interaction interface for any object the player can "use" via the InteractionDetector.
## 2. Enums
### `E_UsableObjectType`
| Value | Description |
|-------|-------------|
| `Switch` | Toggleable switch |
| `Button` | Pressable button |
| `Valve` | Rotatable valve |
| `Terminal` | Interactive screen |
| `Readable` | Note/book |
| `AudioLog` | Audio playback device |
| `Generic` | Custom interaction |
## 3. Variables
| Variable | Type | Description |
|----------|------|-------------|
| `ObjectType` | `E_UsableObjectType` | Type of usable object |
| `InteractionData` | `DA_InteractionData*` | Interaction definition |
| `bIsActive` | `bool` | Object enabled |
| `bSingleUse` | `bool` | Can only be used once |
| `bHasBeenUsed` | `bool` | Tracked if single-use |
| `CooldownSeconds` | `float` | Reuse cooldown |
## 4. Functions
| Function | Description |
|----------|-------------|
| `OnUse` | Executes interaction logic |
| `SetEnabled` | Enable/disable object |
| `ResetObject` | Return to initial state |
## 5. Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnObjectUsed` | `AActor* User` | Object successfully used |
| `OnObjectStateChanged` | `bool bIsActive` | State toggled |
## 6. Dependencies
| System | Relationship |
|--------|--------------|
| `BPC_InteractionDetector` | Focus and interaction routing |
| `DA_InteractionData` | Data-driven interaction config |
## 7. Reuse Notes
- Generic base for all "press E to use" world objects
- Can be subclassed for specialized behavior