add blueprints
This commit is contained in:
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.*
|
||||
Reference in New Issue
Block a user