# BPC_RareEventSystem — Rare Event System

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- **Requires:** [`DA_RareEvent`](../14-data-assets/DA_RareEvent.md) — Rare event definitions with probability and conditions
- **Requires:** [`BPC_NarrativeStateSystem`](../07-narrative/38_BPC_NarrativeStateSystem.md) — Reads narrative flags for eligibility conditions
- **Required By:** [`BPC_AdaptiveEnvironmentDirector`](BPC_AdaptiveEnvironmentDirector.md) — Requests rare event roll
- **Engine/Plugin Requirements:** GameplayTags, Timer system, Random stream

### Purpose
Controls ultra-rare, randomised world events that can occur once per session or with very low probability: hidden messages, brief hallucinations, entity sightings, environmental easter eggs. Tracks which rare events have already fired to prevent repeats and evaluates complex eligibility conditions.

---

## 1. Enums

*No new enums defined. Uses GameplayTags for event and condition identification.*

---

## 2. Structs

### `S_RareEventCondition`
| Field | Type | Description |
|-------|------|-------------|
| `RequiredFlags` | Array of GameplayTag | All must be true for eligibility |
| `ForbiddenFlags` | Array of GameplayTag | None must be true for eligibility |
| `RequiredPlaystyleTag` | GameplayTag | Player must currently have this playstyle |
| `MinSessionTime` | Float | Minimum session elapsed seconds |
| `MinDeathCount` | Integer | Minimum player deaths this session |
| `RequiredChapterTag` | GameplayTag | Current chapter must match |

---

## 3. Variables

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

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `RareEventPool` | Array of DA_RareEvent | Empty | RareEventConfig | All available rare events for this session |

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

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `FiredRareEvents` | Set of GameplayTag | Empty | Internal | Already triggered rare events (prevent repeat) |
| `EligibilityConditions` | Map (GameplayTag → S_RareEventCondition) | Empty | Internal | Resolved eligibility conditions per event |
| `RollTimer` | TimerHandle | — | Internal | Periodic roll timer |
| `RollInterval` | Float | 60.0 | Internal | Seconds between rare event roll checks |

---

## 4. Functions

### Public Functions

#### `RollForRareEvent` → `DA_RareEvent`
- **Description:** Evaluates all eligible rare events, rolls probability, and returns a selected event (or None). Fires the event if one is selected.
- **Parameters:** None
- **Blueprint Authority:** Any
- **Flow:** Filter pool by eligibility → exclude fired events → for each eligible, roll probability → if roll passes, select and fire → add to FiredRareEvents → broadcast OnRareEventFired → return selected event

#### `IsEventEligible` → `Bool`
- **Description:** Checks if a specific rare event's conditions are currently met.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `EventTag` | GameplayTag | Rare event identifier |
- **Blueprint Authority:** Any
- **Flow:** Read S_RareEventCondition from map → check RequiredFlags against narrative state → check ForbiddenFlags → check playstyle match → check session time → check death count → check chapter → return true if all pass

#### `ForceRareEvent` → `void`
- **Description:** Fires a specific rare event immediately, bypassing probability and eligibility checks.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `EventTag` | GameplayTag | Rare event to fire |
- **Blueprint Authority:** Any

#### `GetFiredEvents` → `Set of GameplayTag`
- **Description:** Returns all rare events that have already fired this session.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `GetEligibleEvents` → `Array of DA_RareEvent`
- **Description:** Returns all rare events that are currently eligible (conditions met, not yet fired).
- **Parameters:** None
- **Blueprint Authority:** Any

#### `ResetSession` → `void`
- **Description:** Clears fired events and resets eligibility. Called on new game.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `SetRollInterval` → `void`
- **Description:** Adjusts the periodic roll check interval.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Interval` | Float | New interval in seconds |
- **Blueprint Authority:** Any

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnRareEventFired` | EventTag: GameplayTag | Public | A rare event was triggered |
| `OnRareEventFailed` | EventTag: GameplayTag | Public | Probability roll failed for an eligible event |
| `OnAllRareEventsFired` | — | Public | All events in pool have been fired |

---

## 6. Overridden Events / Custom Events

### Event: `BeginPlay`
- **Description:** Initialises the rare event pool and starts the periodic roll timer.
- **Flow:**
  1. Build EligibilityConditions map from RareEventPool entries
  2. Start RollTimer with RollInterval
  3. Perform initial roll check

### Event: `TickRoll`
- **Description:** Timer callback. Performs a rare event roll check.
- **Flow:**
  1. Call RollForRareEvent
  2. If event fired → broadcast OnRareEventFired
  3. If all events in pool are fired → stop timer and broadcast OnAllRareEventsFired

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[BeginPlay] --> B[Build EligibilityConditions map]
    B --> C[Start RollTimer at RollInterval]
    C --> D[Timer fires]
    D --> E[GetEligibleEvents]
    E --> F{Any eligible events?}
    F -->|No| G[Wait for next tick]
    F -->|Yes| H[For each eligible event:]
    H --> I[Roll random against DA_RareEvent.Probability]
    I --> J{Roll <= Probability?}
    J -->|Yes| K[Fire the rare event]
    J -->|No| L[Broadcast OnRareEventFailed]
    K --> M[Add to FiredRareEvents]
    M --> N[Broadcast OnRareEventFired]
    N --> O{All events fired?}
    O -->|Yes| P[Stop RollTimer]
    O -->|No| G
    L --> H
    P --> Q[Broadcast OnAllRareEventsFired]
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| [`BPC_AdaptiveEnvironmentDirector`](BPC_AdaptiveEnvironmentDirector.md) | Direct call | `RollForRareEvent()` |
| [`BPC_NarrativeStateSystem`](../07-narrative/38_BPC_NarrativeStateSystem.md) | Direct read | Narrative flags for eligibility condition checks |
| [`BPC_PlaystyleClassifier`](BPC_PlaystyleClassifier.md) | Direct read | `CurrentPlaystyleTag` for playstyle-gated events |
| [`GS_CoreGameState`](../01-core/06_GS_CoreGameState.md) | Direct read | `ElapsedPlayTime`, `ActiveChapterTag` |
| [`DA_RareEvent`](../14-data-assets/DA_RareEvent.md) | Data asset read | Event def: tag, probability, conditions, actions |

---

## 9. Validation / Testing Checklist

- [ ] S_RareEventCondition struct has all 6 fields
- [ ] RareEventPool is populated with DA_RareEvent assets
- [ ] IsEventEligible correctly checks all condition types
- [ ] RollForRareEvent respects probability values (0.0 = never, 1.0 = always)
- [ ] FiredRareEvents prevents repeat triggering
- [ ] ForceRareEvent bypasses all checks for scripted/debug use
- [ ] RollTimer stops when all events exhausted
- [ ] Edge case: RareEventPool empty → no errors, timer still runs harmlessly
- [ ] Edge case: all events fired → OnAllRareEventsFired broadcasts once
- [ ] Edge case: rapid probability rolls don't fire same event twice (FiredRareEvents set check)

---

## 10. Reuse Notes

- RareEventPool is population-defined — populate per project with unique events
- Probability values in DA_RareEvent are designer-tuned per event (0.001 for ultra-rare, 0.1 for uncommon)
- Eligibility conditions support complex gating (chapter, playstyle, time, death count)
- For non-horror games, fill pool with easter eggs and hidden secrets instead of scary events
- Extend S_RareEventCondition with project-specific gates (e.g., specific item held, specific ending achieved)

---

*Specification based on Master Section 9.9, line 2922.*