# 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` | `[]` | `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.*