# BP_NarrativeTriggerVolume — Actor (with BoxComponent as root)

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`Actor` (with `BoxComponent` as root)

### Dependencies
- [`BPC_NarrativeStateSystem`](58_BPC_NarrativeStateSystem.md)
- [`BPC_DialoguePlaybackSystem`](40_BPC_DialoguePlaybackSystem.md)
- [`BPC_CutsceneBridge`](44_BPC_CutsceneBridge.md)
- [`BPC_TrialScenarioSystem`](43_BPC_TrialScenarioSystem.md)
- [`BPC_LoreUnlockSystem`](46_BPC_LoreUnlockSystem.md)
- [`I_NarrativeActor`](../01-core/03_I_NarrativeActor.md)

### Purpose
A level-placed trigger volume that detects player overlap and fires narrative actions. Supports one-shot / reusable / conditional modes, with optional prerequisite flags and cooldown timers. The primary way for level designers to trigger narrative events without blueprint logic.

### Responsibilities
- Detect player BeginOverlap / EndOverlap
- Check prerequisite flags (required and exclusive)
- Execute configured actions on trigger (fire-and-forget)
- Support trigger types: Once, Reusable, Conditional, TimedAutoReset
- Broadcast onset / offset variants if configured
- Prevent re-trigger during cooldown

### Does NOT Handle
- Playing dialogue or cutscenes directly (calls the relevant system)
- Setting flags on the NarrativeState (that is what the actions do)
- UI display (that is UI layer)

### Variables

| Name | Type | Description |
|------|------|-------------|
| `TriggerTag` | GameplayTag | Unique identifier for this trigger |
| `TriggerType` | ETriggerType | How the trigger behaves |
| `TriggerActions` | Array of FTriggerActionEntry | Actions to fire when triggered |
| `bAlsoFireOnExit` | Bool | Fire separate actions when player exits |
| `ExitActions` | Array of FTriggerActionEntry | Actions fired on exit (if enabled) |
| `RequiredFlags` | Array of GameplayTag | All must be set to enable |
| `ExclusiveFlags` | Array of GameplayTag | If any are set, trigger is disabled |
| `CooldownSeconds` | Float | Time before reusable triggers can re-fire |
| `bHasTriggered` | Bool | Has fired at least once |
| `bIsEnabled` | Bool | Can be toggled on/off by external systems |
| `LastTriggerTime` | Float | World time of last trigger |
| `CollisionBox` | BoxComponent | The overlap volume |
| `TriggerDisplayName` | FText | Editor-friendly name |
| `bDebugMode` | Bool | Print trigger events to screen |

### Enums

| Enum | Values | Description |
|------|--------|-------------|
| `ETriggerType` | Once, Reusable, ConditionalOnce, ConditionalReusable, TimedAutoReset | Once: fires first time only. Reusable: fires every time with cooldown. Conditional*: checks flags each time. TimedAutoReset: resets after cooldown. |
| `ENarrativeActionType` | SetFlag, ClearFlag, PlayDialogue, StartCutscene, BeginScenario, UnlockLore, UpdateObjective, PlaySound, ExecuteConsoleCommand, ToggleActorEnabled, CustomEvent | Types of actions a trigger can perform |

### Structs

| Struct | Fields | Description |
|--------|--------|-------------|
| `FTriggerActionEntry` | ActionType: ENarrativeActionType, TargetTag: GameplayTag, FloatParam: Float (delay), StringParam: FString (for console commands), bBlocking: Bool (wait for completion), DelayBeforeFire: Float | One action entry in the trigger action list |
| `FTriggerConditionState` | bMetRequirements: Bool, bBlockedByExclusive: Bool, bOnCooldown: Bool, bAlreadyTriggered: Bool | Debug state of trigger conditions |

### Functions / Events

| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `OnPlayerEntered` | OverlappedComp: PrimitiveComponent, OtherActor: Actor | — | BeginOverlap event |
| `OnPlayerExited` | OverlappedComp: PrimitiveComponent, OtherActor: Actor | — | EndOverlap event (if bAlsoFireOnExit) |
| `EvaluateTriggerConditions` | — | Bool (can fire) | Check all conditions |
| `FireTrigger` | — | — | Execute all trigger actions |
| `ExecuteActionEntry` | Entry: FTriggerActionEntry | — | Perform one action |
| `ResetTrigger` | — | — | Reset bHasTriggered (for TimedAutoReset) |
| `SetTriggerEnabled` | bEnabled: Bool | — | External toggle |
| `GetTriggerState` | — | FTriggerConditionState | Debug info |
| `ManualTrigger` | — | — | Force trigger from external BP |
| `PreviewActions` | — | — | Editor preview of what this trigger does |

### Event Dispatchers

| Name | Parameters | Fired When |
|------|-----------|-----------|
| `OnTriggerPrepared` | TriggerTag: GameplayTag | Conditions met, about to fire |
| `OnTriggerFired` | TriggerTag: GameplayTag, ActionCount: Integer | All actions executed |
| `OnTriggerBlocked` | TriggerTag: GameplayTag, Reason: FName | Conditions not met |
| `OnTriggerCooldown` | TriggerTag: GameplayTag, RemainingCooldown: Float | Cooldown active |
| `OnTriggerReset` | TriggerTag: GameplayTag | Trigger reset for reuse |

### Blueprint Flow

```
[OnPlayerEntered]
  └─► If !bIsEnabled → return
  └─► If EvaluateTriggerConditions == false → broadcast OnTriggerBlocked → return
  └─► FireTrigger

[EvaluateTriggerConditions]
  └─► If TriggerType == Once && bHasTriggered → return false (already fired)
  └─► If TriggerType == ConditionalOnce && bHasTriggered → return false
  └─► If TriggerType == TimedAutoReset && !bHasTriggered → skip (but can fire if reset)
  └─► Check RequiredFlags: all must be set in BPC_NarrativeStateSystem
  └─► Check ExclusiveFlags: none must be set
  └─► If TriggerType == Reusable || ConditionalReusable:
      └─► Check LastTriggerTime + CooldownSeconds < CurrentTime
      └─► If on cooldown → broadcast OnTriggerCooldown → return false
  └─► Return true (all conditions pass)

[FireTrigger]
  └─► Broadcast OnTriggerPrepared
  └─► Set bHasTriggered = true
  └─► Set LastTriggerTime = CurrentTime
  └─► For each FTriggerActionEntry in TriggerActions (in order):
      └─► If entry.DelayBeforeFire > 0 → delay via timer
      └─► ExecuteActionEntry(Entry)
  └─► If bAlsoFireOnExit → bind OnPlayerExited to execute ExitActions
  └─► Broadcast OnTriggerFired
  └─► If TriggerType == TimedAutoReset → start timer for ResetTrigger after CooldownSeconds

[ExecuteActionEntry: Entry]
  └─► Switch on Entry.ActionType:
      SetFlag → BPC_NarrativeStateSystem.SetFlag(Entry.TargetTag)
      ClearFlag → BPC_NarrativeStateSystem.ClearFlag(Entry.TargetTag)
      PlayDialogue → Get BPC_DialoguePlaybackSystem → PlaySequence(Entry.TargetTag)
      StartCutscene → Get BPC_CutsceneBridge → PlayCutscene(Entry.TargetTag as DA_CutsceneData)
      BeginScenario → Get BPC_TrialScenarioSystem → BeginScenario(Entry.TargetTag as DA_ScenarioData)
      UnlockLore → Get BPC_LoreUnlockSystem → UnlockLoreByTag(Entry.TargetTag)
      UpdateObjective → Get BPC_ObjectiveSystem → AddOrUpdateObjective(...)
      PlaySound → Play sound at volume location
      ExecuteConsoleCommand → Exec(Entry.StringParam)
      ToggleActorEnabled → Find actor by tag, toggle set actor hidden / disable collision
      CustomEvent → Dispatch custom gameplay event tag (listeners in level blueprint)
```

### Communications With

| Target System | Method | Why |
|---------------|--------|-----|
| [`BPC_NarrativeStateSystem`](58_BPC_NarrativeStateSystem.md) | Direct | Check/set flags for conditions and actions |
| [`BPC_DialoguePlaybackSystem`](40_BPC_DialoguePlaybackSystem.md) | Direct | Trigger dialogue sequences |
| [`BPC_CutsceneBridge`](44_BPC_CutsceneBridge.md) | Direct | Start cutscenes |
| [`BPC_TrialScenarioSystem`](43_BPC_TrialScenarioSystem.md) | Direct | Begin trial scenarios |
| [`BPC_LoreUnlockSystem`](46_BPC_LoreUnlockSystem.md) | Direct | Unlock lore |
| [`BPC_ObjectiveSystem`](39_BPC_ObjectiveSystem.md) | Direct | Update objectives |
| Level Blueprint | Dispatcher (CustomEvent) | Layer for designer-specific logic |

### Placement in Level
- Drag into level from Content Browser
- Scale BoxComponent to desired trigger area
- Configure TriggerActions array in Details panel
- Tag with TriggerTag for save/load identification
- Optional: set PrerequisiteFlags to gate the trigger

### Reuse Notes
This is the primary level-design tool for narrative gating. Designers place volumes, configure action lists, and set prerequisite flags — no blueprint editing required. Supports all narrative action types. The `CustomEvent` action type allows designers to bind custom level blueprint logic when no predefined action fits.

- Renamed from `47_BPC_NarrativeTriggerVolume` to `BP_NarrativeTriggerVolume` per Master naming convention.

---

## Manual Implementation Guide

### Class Setup
1. Create Blueprint Class: Parent = `Actor`, Name = `BP_NarrativeTriggerVolume`
2. Add `BoxComponent` as Root (name: `CollisionBox`)
3. Set Collision Preset = `OverlapOnlyPawn`

### Function Node-by-Node

#### `Event ActorBeginOverlap(OtherActor)` → `void`
```
Step 1: If NOT bIsEnabled → Return
Step 2: Cast OtherActor to Player Character → if fail, Return
Step 3: Check RequiredFlags → if any missing, Return
Step 4: Check ExclusiveFlags → if any set, Return
Step 5: TriggerType == Once AND bHasTriggered? → Return
Step 6: Cooldown active? → Return
Step 7: Call ExecuteActions(TriggerActions)
Step 8: Set bHasTriggered = true, LastTriggerTime = Now
```

#### `ExecuteActions(Actions: Array<FTriggerActionEntry>)` → `void`
```
ForEach Actions → Switch on ActionType:
  SetFlag → NarrativeState.SetFlag(Tag, true)
  PlayDialogue → DialoguePlayback.PlaySequence(Asset)
  PlayCutscene → CutsceneBridge.PlayCutscene(Asset)
  ActivateObjective → ObjectiveSystem.ActivateObjective(Tag)
  StartTrial → TrialScenario.StartScenario(Asset)
  UnlockLore → LoreUnlock.UnlockLoreByTag(Tag)
  GrantItem → Inventory.AddItem(Asset, 1)
```

### Build Checklist
- [ ] Create BP_NarrativeTriggerVolume with BoxComponent
- [ ] Define ETriggerActionType enum and FTriggerActionEntry struct
- [ ] Bind ActorBeginOverlap → check conditions → ExecuteActions
- [ ] Test: walk into volume → dialogue plays → flag sets → one-shot prevents re-fire