12 — Hiding System (BPC_HidingSystem)
Purpose
Manages the player's ability to hide inside, behind, or under environmental objects. Handles entering/exiting hiding spots, line-of-sight checks against enemies, peeking, and stress reduction while concealed. The central component for stealth gameplay.
Dependencies
- Requires:
FL_GameUtilities (interface casts), I_HidingSpot (interface on world actors)
- Required By:
AI_EnemyController (query hiding state for awareness), BPC_StressSystem (stress decay while hidden), BPC_PlayerController (movement/input restriction)
- Engine/Plugin Requirements: GameplayTags, LineTraceByChannel (LOS checks)
Class Info
| Property |
Value |
| Parent Class |
ActorComponent |
| Class Type |
Blueprint Component |
| Asset Path |
Content/Framework/Player/BPC_HidingSystem |
| Implements Interfaces |
None |
1. Enums
E_HideState
| Value |
Description |
Exposed = 0 |
Not hiding, fully visible |
Entering = 1 |
Transient — animation playing to enter hide spot |
Hidden = 2 |
Inside hide spot, concealed |
Peeking = 3 |
Partially visible, can look around |
Exiting = 4 |
Transient — animation playing to exit hide spot |
E_HideType
| Value |
Description |
Locker = 0 |
Fully enclosed (locker, wardrobe) |
BehindCover = 1 |
Behind low wall, crate, counter |
Under = 2 |
Under bed, table, porch |
InShadow = 3 |
Standing in a shadow volume |
TallGrass = 4 |
Crouch-moving through vegetation |
E_PeekDirection
| Value |
Description |
Left = 0 |
Peek left from behind cover |
Right = 1 |
Peek right from behind cover |
Over = 2 |
Peek over low cover |
2. Structs
S_HideSpotInfo
| Field |
Type |
Description |
HidingActor |
AActor |
The hide spot actor |
HideType |
E_HideType |
Type of hiding |
SlotCount |
Integer |
How many can hide here (-1 = infinite) |
bHasPeekAbility |
Boolean |
Can player peek from this spot? |
PeekSocketLeft |
FName |
Socket name for left peek camera |
PeekSocketRight |
FName |
Socket name for right peek camera |
PeekSocketOver |
FName |
Socket name for over peek camera |
ExitLocation |
Vector |
World location to place player on exit |
ExitRotation |
Rotator |
Rotation to face on exit |
bBlocksStress |
Boolean |
Whether this spot reduces stress gain |
HideTags |
GameplayTagContainer |
Tags for filtering |
LOSTraceChannel |
TEnumAsByte<ETraceTypeQuery> |
Trace channel for LOS checks from this spot |
3. Variables
Configuration (Instance Editable, Expose On Spawn)
| Variable |
Type |
Default |
Category |
Description |
bCanHide |
Boolean |
true |
Hiding Config |
Can this player hide at all? |
StressDecayWhileHidden |
Float |
5.0 |
Hiding Config |
Stress lost per second while hidden |
bEnemyCanFindHidingSpot |
Boolean |
true |
Hiding Config |
Can enemies discover this spot |
MaxPeekDuration |
Float |
3.0 |
Hiding Config |
Max seconds player can peek before forced back |
PeekCooldown |
Float |
1.5 |
Hiding Config |
Seconds before player can peek again |
CapsuleCheckRadius |
Float |
50.0 |
Hiding Config |
Radius for capsule trace when finding hide spots |
Internal (Private / Protected, No Expose)
| Variable |
Type |
Default |
Category |
Description |
CurrentHideState |
E_HideState |
Exposed |
Hiding State |
Current hiding state |
PreviousHideState |
E_HideState |
Exposed |
Hiding State |
Previous state for transition detection |
CurrentHideSpot |
S_HideSpotInfo |
- |
Hiding State |
Active hide spot data |
PendingHideSpot |
AActor |
None |
Hiding State |
Hide spot being entered |
PeekTimerHandle |
FTimerHandle |
- |
Hiding State |
Timer for max peek duration |
PeekCooldownTimerHandle |
FTimerHandle |
- |
Hiding State |
Timer for peek cooldown |
bCanPeek |
Boolean |
true |
Hiding State |
Whether peeking is allowed |
LastLOSCheckTime |
Float |
0.0 |
Hiding State |
World time of last LOS check |
LOSTimerHandle |
FTimerHandle |
- |
Hiding State |
Timer for periodic LOS checks |
BreathHeldTimer |
FTimerHandle |
- |
Hiding State |
Timer for breath-hold mechanic |
bIsHoldingBreath |
Boolean |
false |
Hiding State |
Whether player is holding breath |
Replicated (if multiplayer)
| Variable |
Type |
Condition |
Description |
CurrentHideState |
E_HideState |
RepNotify |
Replicated hide state |
CurrentHideSpot |
S_HideSpotInfo |
Replicated |
Replicated spot reference |
4. Functions
Public Functions
EnterHideSpot → Boolean
- Description: Attempts to enter a hiding spot. Returns true if successful.
- Parameters:
| Param |
Type |
Description |
HideSpotActor |
AActor |
The hide spot to enter |
- Blueprint Authority: Server (if MP), Any (single-player)
- Flow:
- Early-out if CurrentHideState != Exposed or !bCanHide
- Validate that HideSpotActor implements I_HidingSpot
- Check slot availability (I_HidingSpot.Execute_HasAvailableSlots)
- If available:
- Set CurrentHideState = Entering
- Store HideSpotActor info in CurrentHideSpot
- Disable player movement input
- Play entering animation (via ABP_GASP)
- On animation complete: Set CurrentHideState = Hidden
- Fire OnHideStateChanged
- Start stress decay timer
- Start periodic LOS check timer
- Return true
- If full: return false
ExitHideSpot → void
- Description: Exits the current hiding spot.
- Parameters:
| Param |
Type |
Description |
bForceExit |
Boolean |
If true, skip exit animation |
- Flow:
- If CurrentHideState != Hidden and CurrentHideState != Peeking: return
- Set CurrentHideState = Exiting
- If bForceExit: skip animation, immediately set Exposed
- Else: play exiting animation
- On animation complete or bForceExit:
- Teleport player to CurrentHideSpot.ExitLocation with ExitRotation
- Re-enable movement input
- Set CurrentHideState = Exposed
- Clear CurrentHideSpot
- Stop stress decay and LOS timers
- Fire OnHideStateChanged
- Fire OnExitedHidingSpot
StartPeek → void
- Description: Begins peeking from behind cover.
- Parameters:
| Param |
Type |
Description |
Direction |
E_PeekDirection |
Which direction to peek |
- Flow:
- Early-out if CurrentHideState != Hidden or !bCanPeek or !CurrentHideSpot.bHasPeekAbility
- Set CurrentHideState = Peeking
- Move camera to peek socket location
- Start MaxPeekDuration timer
- Start PeekCooldown timer (bCanPeek = false during cooldown)
- Fire OnPeekStarted
StopPeek → void
- Description: Ends the peek and returns to Hidden state.
- Flow:
- If CurrentHideState != Peeking: return
- Set CurrentHideState = Hidden
- Return camera to default hide position
- Fire OnPeekEnded
IsPlayerDetectable → Boolean
- Description: Checks if the player is detectable from a given enemy location, considering hide type and edges.
- Parameters:
| Param |
Type |
Description |
EnemyLocation |
Vector |
Location of the enemy |
DetectionRange |
Float |
Max range for detection check |
- Flow:
- If CurrentHideState != Hidden: return true (fully detectable)
- If EnemyLocation distance > DetectionRange: return false
- Perform line trace from enemy to player's approximate position
- If trace hits CurrentHideSpot.HidingActor before player: return false (blocked by cover)
- If trace hits player directly: return true (cover not fully effective)
- Edge case: peek state increases detection radius
TryBreathHold → void
- Description: Player holds breath to reduce noise/detectability for a short time.
- Flow:
- bIsHoldingBreath = true
- Start breath-hold timer (e.g., 8 seconds)
- On timer end: forced exhale, brief noise event, bIsHoldingBreath = false
- Fire OnBreathHoldChanged
Protected / Private Functions
PerformLOSCheck → void
- Description: Timer callback — checks if any enemy has line of sight to this hide spot.
- Flow:
- Get all AI_EnemyController instances within detection range
- For each enemy: call IsPlayerDetectable(EnemyLocation)
- If any enemy has LOS:
- Fire OnHideSpotCompromised
- If CurrentHideSpot.bEnemyCanFindHidingSpot: fire OnForcedExitWarning
OnAnimationHideEnterComplete → void
- Description: Animation notify callback when enter animation finishes.
- Flow:
- Set CurrentHideState = Hidden
- Attach player to hide spot socket if applicable
- Fire OnHideStateChanged
- Start stress decay loop
OnAnimationHideExitComplete → void
- Description: Animation notify callback when exit animation finishes.
- Flow:
- Perform final exit steps already queued in ExitHideSpot
5. Event Dispatchers
| Dispatcher |
Parameters |
Bind Access |
Description |
OnHideStateChanged |
E_HideState OldState, E_HideState NewState |
Public |
Fired on any hide state change |
OnEnteredHidingSpot |
AActor HideSpot, E_HideType HideType |
Public |
Fired when player successfully hides |
OnExitedHidingSpot |
AActor HideSpot |
Public |
Fired when player leaves hiding |
OnPeekStarted |
E_PeekDirection Direction |
Public |
Fired when player starts peeking |
OnPeekEnded |
none |
Public |
Fired when player stops peeking |
OnHideSpotCompromised |
AActor EnemyActor |
Public |
Fired when an enemy sees the player's spot |
OnForcedExitWarning |
float TimeUntilDiscovered |
Public |
Fired when enemy is approaching known spot |
OnBreathHoldChanged |
bool bIsHoldingBreath |
Public |
Fired when breath hold toggles |
6. Overridden Events / Custom Events
Event: BeginPlay
- Description: Initialises state, binds to input actions.
- Flow:
- Set CurrentHideState = Exposed
- Register with GI_GameTagRegistry if needed
- Cache reference to CharacterMovementComponent for disabling during hide
Custom Event: ForceKickFromHide
- Description: Called externally (e.g., by enemy discovery) to force player out of hiding.
- Flow:
- Call ExitHideSpot(bForceExit = true)
- Apply brief stun or camera shake
- Fire OnForcedExitWarning with 0 seconds
Custom Event: OnDamageWhileHiding
- Description: Listener for when damage is taken while hidden.
- Flow:
- If damage source penetrates cover: force exit
- Else: reduce stress instead of health (environmental damage)
7. Blueprint Graph Logic Flow
8. Communication Matrix
| Who Talks |
How |
What Is Sent |
BPC_HidingSystem |
Dispatcher |
OnHideStateChanged -> BPC_PlayerController (input), ABP_GASP (anim), BPC_StressSystem (decay), AI_EnemyController (awareness reset) |
BPC_HidingSystem |
Dispatcher |
OnHideSpotCompromised -> BPC_StressSystem (stress spike), BP_AudioManager (tension music) |
BPC_HidingSystem |
Dispatcher |
OnForcedExitWarning -> WBP_HUD (hide icon flash), BP_AudioManager (heartbeat) |
External (AI) |
Query |
IsPlayerDetectable called by AI_EnemyController for LOS checks |
External (World) |
Interface |
I_HidingSpot on BP_Locker, BP_Wardrobe, BP_Cover |
BPC_HidingSystem |
Dispatcher |
OnPeekStarted/Ended -> BPC_CameraStateLayer (FOV/position) |
9. Validation / Testing Checklist
10. Reuse Notes
- Enemy AI characters can use a simplified version to find and occupy hide spots.
- Hide spots can be pre-placed (lockers, beds) or dynamic (shadow volumes, tall grass).
- The LOS trace channel should be custom (e.g., DetectionChannel) to ignore small props.
- Breath-hold mechanic adds depth to stealth gameplay near enemies.
- For multiplayer: only the hiding player knows their state; other players see a generic "occupado" on the spot.
11. Multiplayer Networking (Expanded)
Server RPCs
| RPC |
Direction |
Description |
Server_EnterHideSpot |
Client→Server |
Client requests entering hide spot. Server validates slot availability, proximity. |
Server_ExitHideSpot |
Client→Server |
Client requests exiting. Server validates, teleports player, replicates. |
Server_StartPeek |
Client→Server |
Client starts peeking. Server validates peek ability, starts duration timer. |
Server_StopPeek |
Client→Server |
Client stops peeking. Server returns to Hidden state. |
Server_TryBreathHold |
Client→Server |
Client holds breath. Server validates, applies noise reduction on server. |
Authority
EnterHideSpot, ExitHideSpot are server-authoritative.
IsPlayerDetectable is server-only — AI runs on server.
PerformLOSCheck runs on server; results multicast to clients for UI feedback.
ForceKickFromHide is server-only (triggered by enemy discovery / damage).
Client Prediction
- Enter/exit animations: client predicts; server confirms via replicated
CurrentHideState.
- Peek: camera offset is local; state replicated.
- Hide spot occupation:
I_HidingSpot.OccupantPawn is replicated — other clients see "Occupied".
- Hide spots with bBlocksStress = true can double as narrative safe rooms.
Blueprint Spec: Hiding System. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework.