# 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.*