# BPC_ScareEventSystem — Scare Event System

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- **Requires:** [`BPC_StressSystem`](../02-player/10_BPC_StressSystem.md) — Reads current stress tier to set ActiveScareTier
- **Requires:** [`DA_ScareEvent`](../14-data-assets/DA_ScareEvent.md) — Scare event definitions
- **Required By:** [`SS_AudioManager`](../10-adaptive/132_SS_AudioManager.md) — Trigger stingers (via `PlayMusicStinger()`)
- **Required By:** [`BPC_LightEventController`](BPC_LightEventController.md) — Trigger scare lighting
- **Required By:** `I_ScareTarget` actors — Broadcast scare events to world actors
- **Required By:** [`WBP_ScreenEffectController`](../06-ui/WBP_ScreenEffectController.md) — Jump scare flash
- **Engine/Plugin Requirements:** GameplayTags, Audio, Timer system

### Purpose
Manages the scheduling and firing of scare events: jump scares, ambient scares, audio stingers, and environmental anomalies. Enforces scare cooldowns to prevent scare saturation, selects appropriate scare tier from player stress level, and tracks scare history to avoid repetition.

---

## 1. Enums

```text
Enum Name: E_ScareTier
(DisplayName = "Scare Tier")

Values:
  Ambient        = 0    // Background unease: creaks, whispers, distant sounds
  Minor          = 1    // Small startle: object falls, door creaks nearby
  Moderate       = 2    // Noticeable scare: shadow figure, loud noise
  Major          = 3    // Intense scare: entity appears, lights fail
  JumpScare      = 4    // Full jump scare: flash, stinger, entity lunge
  Cinematic      = 5    // Scripted cinematic scare sequence
```

---

## 2. Structs

*No new structs defined. Uses [`DA_ScareEvent`](../14-data-assets/DA_ScareEvent.md) for event definitions.*

---

## 3. Variables

### Configuration (Instance Editable, Expose On Spawn)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `ScareEventPool` | Array of DA_ScareEvent | Empty | ScareConfig | All available scare events for this level |
| `ScareCooldownMin` | Float | 30.0 | ScareConfig | Minimum seconds between scare events |

### Internal (Private / Protected, No Expose)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `LastScareTime` | Float | 0.0 | Internal | Game time of last scare event |
| `ActiveScareTier` | E_ScareTier | Ambient | Internal | Current scare tier matched to stress tier |
| `ScareHistory` | Array of GameplayTag | Empty | Internal | Recently fired scare event tags (avoid repeat) |
| `ScareHistoryMaxSize` | Integer | 10 | Internal | Max history entries before oldest are removed |

---

## 4. Functions

### Public Functions

#### `RequestScareEvent` → `Bool`
- **Description:** Checks conditions and fires a scare event if cooldown passed and valid events available. Returns true if a scare was fired.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `TargetTier` | E_ScareTier | Desired scare intensity (None = use ActiveScareTier) |
- **Blueprint Authority:** Any
- **Flow:** Check cooldown → filter pool by tier → exclude history → select event → execute → add to history → update timer

#### `SetActiveScareTier` → `void`
- **Description:** Updates the active scare tier. Called when stress tier changes.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Tier` | E_ScareTier | New active scare tier |
- **Blueprint Authority:** Any

#### `GetActiveScareTier` → `E_ScareTier`
- **Description:** Returns the currently active scare tier.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `ExecuteScareEvent` → `void`
- **Description:** Executes a specific scare event immediately, bypassing cooldown and history checks.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `ScareEvent` | DA_ScareEvent | Specific event to fire |
- **Blueprint Authority:** Any
- **Flow:** Route to audio → route to lighting → route to screen effects → broadcast I_ScareTarget

#### `GetEligibleScares` → `Array of DA_ScareEvent`
- **Description:** Returns all scare events eligible for the current tier, excluding recently fired ones.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Tier` | E_ScareTier | Filter tier |
- **Blueprint Authority:** Any

#### `ResetScareHistory` → `void`
- **Description:** Clears scare history, allowing all events to be eligible again. Called on level load.
- **Parameters:** None
- **Blueprint Authority:** Any

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnScareEventFired` | EventTag: GameplayTag, Tier: E_ScareTier | Public | Scare event executed |
| `OnScareTierChanged` | OldTier: E_ScareTier, NewTier: E_ScareTier | Public | Active scare tier changed |
| `OnScareCooldownExpired` | — | Public | Cooldown period elapsed, scares available again |
| `OnJumpScareTriggered` | EventTag: GameplayTag | Public | Jump scare specifically fired |

---

## 6. Overridden Events / Custom Events

### Event: `BeginPlay`
- **Description:** Subscribes to [`BPC_StressSystem`](../02-player/10_BPC_StressSystem.md)`OnStressTierChanged` to map stress to scare tier.
- **Flow:**
  1. Find BPC_StressSystem and subscribe
  2. Map initial stress tier to scare tier
  3. Set ActiveScareTier

### Event: `OnStressTierChanged`
- **Description:** Called when player stress tier changes. Remaps stress tier to scare tier.
- **Flow:**
  1. Map: Calm→Ambient, Low→Minor, Mid→Moderate, High→Major, Critical→JumpScare
  2. SetActiveScareTier(mapped tier)
  3. Broadcast OnScareTierChanged

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[BeginPlay] --> B[Subscribe to StressSystem.OnStressTierChanged]
    B --> C[Set initial ActiveScareTier from stress]
    C --> D[Idle]

    D --> E{AdaptiveDirector requests scare?}
    E --> F{ScareCooldown elapsed?}
    F -->|No| G[Skip — on cooldown]
    F -->|Yes| H[GetEligibleScares ActiveScareTier]
    H --> I{Any eligible events?}
    I -->|No| G
    I -->|Yes| J[Select random from eligible]
    J --> K[ExecuteScareEvent]
    K --> L[Audio → SS_AudioManager.PlayMusicStinger]
    K --> M[Visual → BPC_LightEventController + WBP_ScreenEffectController]
    K --> N[World → Broadcast I_ScareTarget to tagged actors]
    L --> O[Add to ScareHistory]
    M --> O
    N --> O
    O --> P[Update LastScareTime]
    P --> Q[Broadcast OnScareEventFired]
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| [`BPC_StressSystem`](../02-player/10_BPC_StressSystem.md) | Dispatcher (`OnStressTierChanged`) | `NewTier: E_StressTier` — maps to E_ScareTier |
| [`BPC_AdaptiveEnvironmentDirector`](BPC_AdaptiveEnvironmentDirector.md) | Direct call | `RequestScareEvent(E_ScareTier)` |
| [`SS_AudioManager`](../10-adaptive/132_SS_AudioManager.md) | Direct call | `PlayMusicStinger(StingerAsset)` |
| [`BPC_LightEventController`](BPC_LightEventController.md) | Direct call | `TriggerLightEvent(EventTag)` |
| [`WBP_ScreenEffectController`](../06-ui/WBP_ScreenEffectController.md) | Direct call | `TriggerJumpScareFlash()` or `TriggerDamageFlash()` |
| `I_ScareTarget` actors | Interface broadcast | `OnScareEventFired(ScareTag)` |
| [`DA_ScareEvent`](../14-data-assets/DA_ScareEvent.md) | Data asset read | Event def: tier, tags, audio, visual, actor targets |

---

## 9. Validation / Testing Checklist

- [ ] E_ScareTier enum has all 6 values
- [ ] RequestScareEvent respects ScareCooldownMin
- [ ] ActiveScareTier correctly mapped from E_StressTier
- [ ] Eligible scares filtered by tier and excluded from history
- [ ] ExecuteScareEvent routes to audio, lighting, screen effects, and I_ScareTarget
- [ ] ScareHistory prevents repeating recent events
- [ ] OnJumpScareTriggered fires for E_ScareTier::JumpScare events
- [ ] Edge case: no eligible scares → RequestScareEvent returns false
- [ ] Edge case: all scares in pool exhausted → reset history or allow repeats
- [ ] Edge case: cooldown active during cinematic → scripted scares bypass cooldown via ExecuteScareEvent

---

## 10. Reuse Notes

- ScareEventPool is populated per level — different levels have different scare content
- ScareCooldownMin prevents scare saturation; tune per project for desired horror intensity
- Stress-to-scare mapping is configurable: calm games can cap at Minor tier
- For non-horror games, leave ScareEventPool empty to disable the system
- I_ScareTarget interface lets any actor react to scares without coupling to this system

---

*Specification based on Master Section 9.5, line 2812.*