# BPC_LightEventController — Light Event Controller

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- [`BPC_AtmosphereStateController`](BPC_AtmosphereStateController.md) — Atmosphere state receiver
- [`BPC_FearSystem`](90_BPC_FearSystem.md) — Fear-driven lighting modulation
- [`BPC_PerformanceScaler`](91_BPC_PerformanceScaler.md) — Performance budget input

### Purpose
Manages all dynamic lighting in the game world including global color grading, fog, shadows, emissive materials, point light intensity modulation, and lighting transitions. Receives preset keys from AtmosphereStateController and applies them with smooth crossfades. Supports fear-reactive lighting effects (flicker, desaturation, shadow intensity) based on the player's fear state.

### Variables

| Name | Type | Description |
|------|------|-------------|
| `ActivePresetKey` | FName | Currently applied lighting preset |
| `TargetPresetKey` | FName | Preset being transitioned to |
| `CurrentColorGrading` | FPostProcessSettings | Active post-process |
| `CurrentFogDensity` | Float | Active exponential fog density |
| `CurrentShadowIntensity` | Float | Shadow darkness bias |
| `LightFlickerIntensity` | Float (0.0–1.0) | Fear-driven flicker effect |
| `LightFlickerFrequency` | Float | Flicker speed |
| `bEnableFearReactiveLights` | Bool | Fear modulation toggle |
| `TransitionDuration` | Float | Current crossfade duration |
| `TransitionProgress` | Float (0.0–1.0) | Crossfade interpolation |
| `RegisteredLights` | TArray<ULightComponent> | Dynamic lights to modulate |
| `DesaturationAmount` | Float (0.0–1.0) | Fear-driven color loss |
| `VignetteIntensity` | Float | Post-process vignette |
| `bIsInDarkVolume` | Bool | Inside darkness volume |

### Functions

| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `Initialize` | — | — | Cache references, bind events |
| `SetLightingPreset` | PresetKey: FName, TransitionTime: Float | — | Queue preset transition |
| `ApplyPresetDirect` | PresetKey: FName | — | Instant preset application |
| `GetCurrentPresetKey` | — | FName | Current active preset |
| `RegisterDynamicLight` | Light: ULightComponent | — | Add to modulation list |
| `UnregisterDynamicLight` | Light: ULightComponent | — | Remove from modulation list |
| `SetFearFlicker` | Intensity: Float, Frequency: Float | — | Apply flicker to all registered lights |
| `SetDesaturation` | Amount: Float | — | Post-process color loss |
| `SetVignette` | Intensity: Float | — | Post-process vignette |
| `SetShadowIntensity` | Intensity: Float | — | Global shadow bias |
| `SetFogDensity` | Density: Float | — | Exponential fog density |
| `EnterDarkVolume` | — | — | Enter darkness zone |
| `ExitDarkVolume` | — | — | Leave darkness zone |
| `FearReactiveUpdate` | FearLevel: Float, Threshold: EFearThreshold | — | Per-tick fear modulation |

### Blueprint Flow

```
[Tick]
  └─► If TransitionProgress < 1.0:
         TransitionProgress += DeltaTime / TransitionDuration
         Lerp all lighting properties between current and target
         On complete: ActivePresetKey = TargetPresetKey
  └─► If bEnableFearReactiveLights:
         FearReactiveUpdate(CurrentFearLevel, CurrentThreshold)

[SetLightingPreset]
  └─► If TransitionTime > 0:
         TargetPresetKey = PresetKey
         TransitionDuration = TransitionTime
         TransitionProgress = 0.0
         Begin lerp from current to target
  └─► Else:
         ApplyPresetDirect(PresetKey)

[FearReactiveUpdate]
  └─► Based on fear threshold:
         Calm:      No lighting change
         Uneasy:    Subtle light flicker (intensity 0.1), no color change
         Nervous:   Light flicker (0.3), slight desaturation (0.1)
         Afraid:    Heavy flicker (0.6), desaturation (0.3), vignette (0.2)
         Terrified: Max flicker (0.8), desaturation (0.5), vignette (0.4), shadow intensify
         Panic:     Strobe flicker, heavy desaturation (0.7), max vignette
  └─► Apply to all RegisteredLights:
         For each ULightComponent: 
              If flicker enabled: randomize Intensity between 0..Original* (1 - LightFlickerIntensity)
  └─► Apply post-process:
         SetDesaturation(DesaturationAmount)
         SetVignette(VignetteIntensity)

[EnterDarkVolume]
  └─► bIsInDarkVolume = true
  └─► Override current preset with Darkness preset
  └─► Disable fear-reactive lights during dark volume
  └─► DarkVolume exclusive: very low ambient, high fog, long shadows

[ExitDarkVolume]
  └─► bIsInDarkVolume = false
  └─► Restore previous lighting preset
  └─► Re-enable fear-reactive lights
```

### Communications With

| Target | Method | Why |
|--------|--------|-----|
| [`BPC_AtmosphereStateController`](BPC_AtmosphereStateController.md) | Called by | Receive lighting preset keys |
| [`BPC_FearSystem`](90_BPC_FearSystem.md) | Get Owner Component | Fear level for reactive lighting |
| [`BPC_PerformanceScaler`](91_BPC_PerformanceScaler.md) | Direct call | Reduce light quality on low spec |
| [`BP_Checkpoint`](../05-saveload/BP_Checkpoint.md) | Event | Restore lighting on load |

### Reuse Notes
- Works with any ULightComponent (point, spot, directional, rect)
- Post-process settings are blended, not stomped
- Dark volumes override atmosphere-driven lighting
- Fear-reactive lighting is additive on top of current preset
- PerformanceScaler can disable dynamic lighting and fear flicker on low-end hardware
- Renamed from `BPC_LightingManager` to `BPC_LightEventController` per Master naming convention.
- Cross-references updated: `BPC_AtmosphereController` → `BPC_AtmosphereStateController`, `BPC_CheckpointSystem` → `BP_Checkpoint`.