# 63 — BPC_FearSystem

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- [`GI_GameFramework`](../01-core/04_GI_GameFramework.md) — Central game instance access
- [`BPC_PlayerMetricsTracker`](../02-player/15_BPC_PlayerMetricsTracker.md) — Player anxiety/stress metrics
- [`BPC_DifficultyManager`](89_BPC_DifficultyManager.md) — Fear intensity modifier
- [`BPC_StressSystem`](../02-player/10_BPC_StressSystem.md) — Player stress level
- [`BPC_AtmosphereController`](64_BPC_AtmosphereController.md) — Atmosphere response
- [`BPC_AudioManager`](66_BPC_AudioManager.md) — Audio feedback
- [`BPC_VFXManager`](67_BPC_VFXManager.md) — Visual feedback
- [`BPC_LightingManager`](65_BPC_LightingManager.md) — Lighting response
- [`BPC_NarrativeStateSystem`](../07-narrative/38_BPC_NarrativeStateSystem.md) — Story-aware fear triggers

### Purpose
Core fear and anxiety system that manages the player's fear level, fear sources, fear decay, and fear-induced gameplay effects. Acts as the central orchestrator for all horror-related feedback loops — audio, visual, AI behavior, and UI — driven by the player's current fear state and environmental context.

### Variables

| Name | Type | Description |
|------|------|-------------|
| `CurrentFearLevel` | Float (0–100) | Current fear value |
| `MaxFearLevel` | Float | Cap for fear (default 100) |
| `FearDecayRate` | Float | Passive fear reduction per second |
| `FearThresholds` | TMap\<EFearThreshold, Float\> | Threshold values for each fear tier |
| `ActiveFearSources` | TArray\<FFearSource\> | Currently contributing fear sources |
| `FearMultiplier` | Float | Global multiplier (from DifficultyManager) |
| `bIsInPanicState` | Bool | Overwhelmed by fear |
| `PanicDuration` | Float | Seconds of panic state |
| `PanicTimer` | Float | Panic countdown |
| `LastIncreaseTime` | Float | When fear last increased |
| `bFearDecayPaused` | Bool | Freeze decay |
| `EnvironmentalFearModifier` | Float | Ambient fear from atmosphere |
| `DarknessFearMultiplier` | Float | Extra fear in dark areas |
| `IsolatedFearMultiplier` | Float | Extra fear when alone |
| `ProximityFearMultiplier` | Float | Extra fear from nearby threats |
| `bIsInSafeZone` | Bool | Safe zone overrides fear |

### Enums

| Enum | Values | Description |
|------|--------|-------------|
| `EFearThreshold` | Calm, Uneasy, Nervous, Afraid, Terrified, Panic | Fear tiers |

### Structs

| Struct | Fields | Description |
|--------|--------|-------------|
| `FFearSource` | SourceName: FName, BaseValue: Float, CurrentValue: Float, DecayDelay: Float, bIsDecaying: Bool, TimeSinceTrigger: Float, Tag: FGameplayTag | Active fear contributor |
| `FFearEvent` | Source: FName, Value: Float, Duration: Float, bInstant: Bool, bStack: Bool, AssociatedTag: FGameplayTag | Incoming fear impulse |

### Functions

| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `Initialize` | — | — | Setup thresholds, bind events |
| `AddFear` | Event: FFearEvent | — | Add fear from any source |
| `RemoveFearSource` | SourceName: FName | — | Remove specific fear source |
| `ClearAllFear` | — | — | Reset fear to baseline |
| `GetFearLevel` | — | Float | Current fear value |
| `GetFearThreshold` | — | EFearThreshold | Current fear tier |
| `IsInPanic` | — | Bool | Panic state check |
| `SetFearDecayRate` | NewRate: Float | — | Override decay speed |
| `PauseFearDecay` | bPaused: Bool | — | Freeze/unfreeze decay |
| `UpdateEnvironmentalFear` | Modifier: Float | — | Ambient fear contribution |
| `CalculateFearTier` | FearValue: Float | EFearThreshold | Determine current tier |
| `TriggerPanic` | Duration: Float | — | Force panic state |
| `ResolvePanic` | — | — | End panic state early |
| `ApplyFearEffect` | Effect: EFearEffect | — | Gameplay consequences of fear |

### Event Dispatchers

| Name | Parameters | Fired When |
|------|-----------|-----------|
| `OnFearLevelChanged` | NewFear: Float, Threshold: EFearThreshold | Any fear change |
| `OnFearThresholdReached` | Threshold: EFearThreshold | Cross a fear tier boundary |
| `OnPanicStarted` | — | Panic state entered |
| `OnPanicEnded` | — | Panic state ended |
| `OnFearSourceAdded` | Source: FFearSource | New fear source registered |
| `OnFearSourceRemoved` | SourceName: FName | Fear source expired |

### Blueprint Flow

```
[Tick — every frame]
  └─► If not bFearDecayPaused AND not bIsInPanicState:
         CurrentFearLevel -= FearDecayRate * DeltaTime
         Clamp CurrentFearLevel to 0..MaxFearLevel
  └─► Process active fear sources:
         For each FFearSource in ActiveFearSources:
              Source.TimeSinceTrigger += DeltaTime
              If Source.TimeSinceTrigger > Source.DecayDelay:
                   Source.bIsDecaying = true
                   Source.CurrentValue -= DecayRate * DeltaTime
              If Source.CurrentValue <= 0:
                   Remove from ActiveFearSources
                   Fire OnFearSourceRemoved
  └─► If bIsInPanicState:
         PanicTimer -= DeltaTime
         If PanicTimer <= 0:
              ResolvePanic()
  └─► CalculateFearTier(CurrentFearLevel)
  └─► If tier changed since last frame:
         Fire OnFearThresholdReached(NewThreshold)

[AddFear]
  └─► Apply modifiers:
         EffectiveValue = Event.Value * FearMultiplier
         EffectiveValue *= EnvironmentalFearModifier
         EffectiveValue *= DarknessFearModifier (if in dark volume)
         EffectiveValue *= IsolatedFearModifier (if no allies)
         EffectiveValue *= ProximityFearModifier (if enemies nearby)
  └─► If Event.bStack:
         Find existing source by Event.Source
         If found: Stack.Value += EffectiveValue
         Else: Create new FFearSource
  └─► Else:
         Create new FFearSource with Event parameters
  └─► CurrentFearLevel += EffectiveValue
  └─► Clamp to MaxFearLevel
  └─► Check if panic threshold crossed:
         If CurrentFearLevel >= FearThresholds[Panic]:
              TriggerPanic(PanicDuration)
  └─► Fire OnFearLevelChanged(CurrentFearLevel, CurrentThreshold)
  └─► Fire OnFearSourceAdded(NewSource)

[TriggerPanic]
  └─► bIsInPanicState = true
  └─► PanicTimer = Duration (or PanicDuration default)
  └─► ApplyFearEffect(EPanicEffects)
  └─► BPC_AtmosphereController.TriggerPanicMode()
  └─► BPC_AudioManager.PlayPanicAudio()
  └─► BPC_VFXManager.TriggerPanicVFX()
  └─► UI: Show panic overlay
  └─► Fire OnPanicStarted

[ResolvePanic]
  └─► bIsInPanicState = false
  └─► CurrentFearLevel = FearThresholds[Terrified] * 0.8
  └─► BPC_AtmosphereController.EndPanicMode()
  └─► BPC_AudioManager.StopPanicAudio()
  └─► Fire OnPanicEnded

[ApplyFearEffect — based on current threshold]
  └─► EFearThreshold.Calm: No effects
  └─► EFearThreshold.Uneasy: Subtle audio cues, slight camera sway
  └─► EFearThreshold.Nervous: UI vignette, breathing sounds, reduced stamina regen
  └─► EFearThreshold.Afraid: Visibility distortion, movement speed penalty, aim shake
  └─► EFearThreshold.Terrified: Severe vignette, stammering audio, weapon sway
  └─► EFearThreshold.Panic: Tunnel vision, audio distortion, sprint penalty, AI gets buffs
```

### Communications With

| Target | Method | Why |
|--------|--------|-----|
| [`BPC_PlayerMetricsTracker`](../02-player/15_BPC_PlayerMetricsTracker.md) | Get Owner Component | Track fear history for metrics |
| [`BPC_StressSystem`](../02-player/10_BPC_StressSystem.md) | Get Owner Component | Stress/fear feedback loop |
| [`BPC_DifficultyManager`](89_BPC_DifficultyManager.md) | Get Owner Component | Fear intensity modifier |
| [`BPC_AtmosphereController`](64_BPC_AtmosphereController.md) | Direct call | Atmosphere panic mode |
| [`BPC_AudioManager`](66_BPC_AudioManager.md) | Direct call | Panic audio, fear ambience |
| [`BPC_VFXManager`](67_BPC_VFXManager.md) | Direct call | Visual effects per tier |
| [`BPC_LightingManager`](65_BPC_LightingManager.md) | Direct call | Dynamic lighting response |
| [`SS_UIManager`](../06-ui/32_SS_UIManager.md) | Subsystem | HUD fear indicator, panic overlay |
| [`BPC_NarrativeStateSystem`](../07-narrative/38_BPC_NarrativeStateSystem.md) | Get Owner Component | Story-aware fear modifiers |
| [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) | Get Owner Component | Panic damage if health low |
| [`AI_EnemyControllers`](../09-ai/55_BPC_AIControllerBase.md) | Event Dispatcher | AI aggression rise with player fear |

### Reuse Notes
- Single instance on player character (or PlayerController)
- All fear sources are stackable and independently decayable
- Thresholds are designer-configurable at runtime
- Fear multiplier from DifficultyManager allows difficulty to scale horror
- Safe zones (checkpoints, safe rooms) pause fear accumulation and decay
- Panic state is a temporary debuff with full cleanup on resolve
- UI reads OnFearLevelChanged dispatcher, never polls