add blueprints
This commit is contained in:
382
docs/blueprints/03-interaction/16_BPC_InteractionDetector.md
Normal file
382
docs/blueprints/03-interaction/16_BPC_InteractionDetector.md
Normal 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.*
|
||||
286
docs/blueprints/03-interaction/17_I_HidingSpot.md
Normal file
286
docs/blueprints/03-interaction/17_I_HidingSpot.md
Normal 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.*
|
||||
370
docs/blueprints/03-interaction/18_BPC_DiegeticDisplay.md
Normal file
370
docs/blueprints/03-interaction/18_BPC_DiegeticDisplay.md
Normal file
@@ -0,0 +1,370 @@
|
||||
# `BPC_DiegeticDisplay` — Diegetic Display System
|
||||
|
||||
**Parent Class:** `ActorComponent`
|
||||
**Category:** Interaction / UI
|
||||
**Target UE Version:** 5.5–5.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` | 0–1 intensity of the active effect. |
|
||||
| `InputMode` | `E_DisplayInputMode` | Current input routing mode. |
|
||||
| `BatteryLevel` | `float` | 0–1 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)
|
||||
339
docs/blueprints/03-interaction/19_BP_DoorActor.md
Normal file
339
docs/blueprints/03-interaction/19_BP_DoorActor.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# `BP_DoorActor` — Door Actor System
|
||||
|
||||
**Parent Class:** `Actor`
|
||||
**Category:** Interaction
|
||||
**Implements:** `I_Interactable`
|
||||
**Target UE Version:** 5.5–5.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`.
|
||||
97
docs/blueprints/03-interaction/20_BP_PuzzleDeviceActor.md
Normal file
97
docs/blueprints/03-interaction/20_BP_PuzzleDeviceActor.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# BP_PuzzleDeviceActor — Puzzle Device Actor
|
||||
|
||||
**Parent Class:** `Actor`
|
||||
**Category:** Interaction
|
||||
**Target UE Version:** 5.5–5.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
|
||||
@@ -0,0 +1,88 @@
|
||||
# BPC_ContextualTraversalSystem — Contextual Traversal System
|
||||
|
||||
**Parent Class:** `ActorComponent`
|
||||
**Category:** Interaction
|
||||
**Target UE Version:** 5.5–5.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
|
||||
104
docs/blueprints/03-interaction/22_BPC_PhysicsDragSystem.md
Normal file
104
docs/blueprints/03-interaction/22_BPC_PhysicsDragSystem.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# BPC_PhysicsDragSystem — Physics Drag System
|
||||
|
||||
**Parent Class:** `ActorComponent`
|
||||
**Category:** Interaction
|
||||
**Target UE Version:** 5.5–5.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
|
||||
@@ -0,0 +1,54 @@
|
||||
# BPC_UsableWorldObjectSystem — Usable World Object System
|
||||
|
||||
**Parent Class:** `ActorComponent`
|
||||
**Category:** Interaction
|
||||
**Target UE Version:** 5.5–5.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
|
||||
Reference in New Issue
Block a user