Files
Lefteris Notas 8bc731e5ae feat: Add multiplayer networking architecture and documentation updates
- Updated Master Blueprint Index to include Multiplayer Networking support.
- Added detailed Multiplayer Networking sections across all developer documentation (01-11).
- Introduced authority maps, key patterns, and RPC guidelines for each system.
- Established a comprehensive multiplayer networking architecture document outlining core principles, replication strategies, and anti-cheat considerations.
- Enhanced UI documentation to clarify local-only behavior and binding to replicated dispatchers.
- Implemented client prediction strategies and RPC naming conventions for consistency across the framework.
2026-05-19 17:15:57 +03:00

308 lines
13 KiB
Markdown

# 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.
---
## 10. Multiplayer Networking
### Replicated Variables
| Variable | Condition | Purpose |
|----------|-----------|---------|
| `bOccupied` | `Replicated` | Other clients see spot as occupied |
| `LockedByPlayer` | `Replicated` | Synced lock state |
| `OccupantPawn` | `Replicated` | Who is hiding here (for third-person visibility) |
| `bIsVisible` | `Replicated` | Spot availability synced |
### Authority
- `OnPlayerEntered`/`OnPlayerExited` are called by the server-authoritative `BPC_HidingSystem`.
- `LockSpot`/`UnlockSpot` are server-only.
- `GetOccupancyStatus` is read-only, safe for any side.
### Server RPCs
| RPC | Direction | Description |
|-----|-----------|-------------|
| `Server_ClaimSpot` | Client→Server | Client requests occupying spot. Server validates availability. |
---
*Blueprint Spec: Hiding Spot Interface & Actor. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework.*