147 lines
7.1 KiB
Markdown
147 lines
7.1 KiB
Markdown
# 60 — BPC_AlertSystem
|
||
|
||
## Blueprint Spec — UE 5.5–5.7
|
||
|
||
---
|
||
|
||
### Parent Class
|
||
`ActorComponent`
|
||
|
||
### Dependencies
|
||
- [`BPC_AIControllerBase`](55_BPC_AIControllerBase.md) — Owner controller
|
||
- [`BP_EnemyBase`](58_BP_EnemyBase.md) — Pawn that receives commands
|
||
- [`DA_AIProfile`](../12-content/63_DA_AIProfileDataAsset.md) — Alert thresholds and response times
|
||
- [`BPC_PerceptionComponent`](56_BPC_PerceptionComponent.md) — Stimulus input source
|
||
- [`BPC_AIStateMachine`](61_BPC_AIStateMachine.md) — State transition triggers
|
||
- [`I_Damageable`](../01-foundation/05_I_Damageable.md) — Damage stimulus source
|
||
|
||
### Purpose
|
||
Manages AI threat levels, alert escalation, and reinforcement propagation. Receives stimuli from perception and damage systems, evaluates threat severity, escalates through alert levels (Unaware → Suspicious → Alert → Combat), and notifies nearby AI units. Acts as the central threat-response coordinator for each AI.
|
||
|
||
### Enums
|
||
|
||
| Enum | Values | Description |
|
||
|------|--------|-------------|
|
||
| `EAlertLevel` | Unaware, Suspicious, Alert, Combat | Current alert tier |
|
||
| `EAlertCause` | SightStimulus, HearingStimulus, DamageTaken, AllyAlert, Environmental | What triggered the alert |
|
||
|
||
### Structs
|
||
|
||
| Struct | Fields | Description |
|
||
|--------|--------|-------------|
|
||
| `FAlertState` | AlertLevel: EAlertLevel, AlertCause: EAlertCause, LastAlertTime: Float, SourceLocation: FVector, KnownTarget: AActor, bHasValidTarget: Bool, SuspicionValue: Float, CombatTimer: Float | Snapshot of current alert status |
|
||
| `FAlertPropagationInfo` | AlertLevel: EAlertLevel, SourceLocation: FVector, Target: AActor, PropagationRadius: Float, Timestamp: Float | Data sent to nearby AI |
|
||
|
||
### Variables
|
||
|
||
| Name | Type | Description |
|
||
|------|------|-------------|
|
||
| `CurrentAlertState` | FAlertState | Live alert tracking |
|
||
| `AlertThresholds` | FVector2D | Suspicion threshold X, Combat threshold Y |
|
||
| `SuspicionDecayRate` | Float | Points per second lost when no stimulus |
|
||
| `SuspicionGrowthRate` | Float | Points per second gained on stimulus |
|
||
| `CombatExitDelay` | Float | Time without combat before dropping to Alert |
|
||
| `ReinforcementRadius` | Float | Max distance to notify allies |
|
||
| `bCanCallReinforcements` | Bool | Permission to propagate |
|
||
| `ReinforcementCooldown` | Float | Min seconds between calls |
|
||
| `LastReinforcementTime` | Float | Cooldown tracker |
|
||
| `bIsInCombat` | Bool | Fast check for combat state |
|
||
| `InvestigationTimer` | Float | Time spent investigating last known position |
|
||
| `MaxInvestigationTime` | Float | Give up after this long |
|
||
|
||
### Functions
|
||
|
||
| Name | Inputs | Outputs | Description |
|
||
|------|--------|---------|-------------|
|
||
| `EvaluateStimulus` | StimulusType: EAlertCause, Intensity: Float, Location: FVector, Instigator: AActor | — | Process incoming stimulus |
|
||
| `CalculateThreatScore` | StimulusType: EAlertCause, Intensity: Float, Distance: Float | Float | Compute weighted threat value |
|
||
| `EscalateAlert` | NewLevel: EAlertLevel, Cause: EAlertCause | — | Raise alert level |
|
||
| `DeescalateAlert` | — | — | Lower alert level (decay timer) |
|
||
| `UpdateSuspicion` | DeltaTime: Float | — | Tick suspicion up/down |
|
||
| `CheckAlertTransition` | — | EAlertLevel | Determine if threshold crossed |
|
||
| `EnterCombat` | Target: AActor | — | Transition to combat state |
|
||
| `ExitCombat` | — | — | Transition out of combat |
|
||
| `CallReinforcements` | — | — | Broadcast alert to allies |
|
||
| `ReceiveReinforcementCall` | Info: FAlertPropagationInfo | — | Handle ally alert broadcast |
|
||
| `GetCurrentAlertLevel` | — | EAlertLevel | Getter for blackboard updates |
|
||
| `GetKnownTarget` | — | AActor | Current combat target |
|
||
| `IsInCombat` | — | Bool | Combat state check |
|
||
| `SetInvestigationPoint` | Location: FVector | — | Mark last known target position |
|
||
| `ClearInvestigationPoint` | — | — | Reset investigation |
|
||
| `ShouldGiveUpSearch` | — | Bool | Timeout check for investigation |
|
||
|
||
### Blueprint Flow
|
||
|
||
```
|
||
[EvaluateStimulus]
|
||
└─► Calculate Threat Score
|
||
└─► If Score > AlertThresholds.Y --> Escalate to Combat
|
||
└─► Else If Score > AlertThresholds.X --> Escalate to Suspicious
|
||
└─► Else --> Update SuspicionValue (accumulate)
|
||
└─► If AlertLevel >= Suspicious:
|
||
Set Investigation Point
|
||
If AlertLevel == Combat:
|
||
Set KnownTarget
|
||
EnterCombat
|
||
If bCanCallReinforcements:
|
||
CallReinforcements
|
||
|
||
[Event Tick]
|
||
└─► UpdateSuspicion(DeltaTime):
|
||
If no stimulus:
|
||
SuspicionValue -= SuspicionDecayRate * DeltaTime
|
||
If SuspicionValue <= 0:
|
||
DeescalateAlert (back to Unaware)
|
||
If AlertLevel == Combat:
|
||
CombatTimer += DeltaTime
|
||
If CombatTimer > CombatExitDelay && no damage/stimulus:
|
||
ExitCombat -> set AlertLevel = Alert
|
||
If AlertLevel == Suspicious:
|
||
InvestigationTimer += DeltaTime
|
||
If InvestigationTimer > MaxInvestigationTime:
|
||
ClearInvestigationPoint
|
||
DeescalateAlert
|
||
|
||
[CallReinforcements]
|
||
└─► If (Time - LastReinforcementTime) < ReinforcementCooldown: return
|
||
└─► Get all AI controllers within ReinforcementRadius
|
||
└─► For each:
|
||
Call ReceiveReinforcementCall with current alert info
|
||
└─► LastReinforcementTime = CurrentTime
|
||
|
||
[ReceiveReinforcementCall]
|
||
└─► If CurrentAlertLevel >= Info.AlertLevel: ignore (already higher)
|
||
└─► Else: EscalateAlert(Info.AlertLevel, Environmental)
|
||
Set InvestigationPoint = Info.SourceLocation
|
||
If Info.AlertLevel == Combat:
|
||
Set KnownTarget = Info.Target
|
||
```
|
||
|
||
### Event Dispatchers
|
||
|
||
| Name | Delegate Signature | Purpose |
|
||
|------|-------------------|---------|
|
||
| `OnAlertLevelChanged` | EAlertLevel, EAlertCause | UI, sound, state machine listeners |
|
||
| `OnCombatEntered` | AActor Target | Combat music, HUD, behavior tree |
|
||
| `OnCombatExited` | — | Combat cleanup |
|
||
| `OnReinforcementCalled` | FAlertPropagationInfo | Debug logging, analytics |
|
||
| `OnInvestigationStarted` | FVector Location | Sound/investigation music |
|
||
| `OnInvestigationEnded` | — | Return to patrol |
|
||
|
||
### Communications With
|
||
|
||
| Target | Method | Why |
|
||
|--------|--------|-----|
|
||
| [`BPC_AIStateMachine`](61_BPC_AIStateMachine.md) | Call | Request state change |
|
||
| [`BPC_AIControllerBase`](55_BPC_AIControllerBase.md) | Owner reference | Coordinate BB values |
|
||
| [`BPC_PerceptionComponent`](56_BPC_PerceptionComponent.md) | Direct call | Get stimulus data |
|
||
| [`BP_EnemyBase`](58_BP_EnemyBase.md) | Owner reference | Trigger combat animations |
|
||
| [`WBP_HUD`](../06-ui/36_WBP_HUD.md) | Event dispatcher | Show combat indicator |
|
||
| [`BPC_CombatFeedback`](../08-combat/54_BPC_CombatFeedbackComponent.md) | Event dispatcher | Combat music/vignette |
|
||
|
||
### Reuse Notes
|
||
- Attached to AIControllerBase; profiles tune thresholds per enemy type
|
||
- Works with any perception system that produces EAlertCause stimuli
|
||
- Reinforcement chain prevents infinite loops by comparing alert levels
|
||
- Investigation system handles "last seen" behavior without combat
|
||
- Decay system ensures AI eventually returns to patrol state |