# 41 — BPC_DialogueChoiceSystem ## Blueprint Spec — UE 5.5–5.7 --- ### Parent Class `ActorComponent` ### Dependencies - [`BPC_NarrativeStateSystem`](58_BPC_NarrativeStateSystem.md) - [`BPC_DialoguePlaybackSystem`](40_BPC_DialoguePlaybackSystem.md) - [`WBP_DialogueChoiceDisplay`](../06-ui/46_WBP_DialogueChoiceDisplay.md) - [`DA_DialogueSequence`](48_DA_NarrativeDataAssets.md) ### Purpose Presents branching dialogue choices to the player and routes the selected response back to the narrative system. Manages choice availability based on narrative flags and time limits. ### Responsibilities - Receive choice set from dialogue flow (via dispatcher from `BPC_DialoguePlaybackSystem`) - Filter choices by required flags (only show choices player qualifies for) - Display choices via `WBP_DialogueChoiceDisplay` - Apply time limit if configured (auto-select default on expiry) - Route selected choice tag to `BPC_NarrativeStateSystem` - Trigger consequence dialogue branches by returning next sequence tag ### Does NOT Handle - Playing dialogue lines (that is `BPC_DialoguePlaybackSystem`) - Evaluating narrative consequences beyond setting choice flag (that is `BPC_BranchingConsequenceSystem`) - UI visual styling (that is `WBP_DialogueChoiceDisplay`) ### Variables | Name | Type | Description | |------|------|-------------| | `CurrentChoices` | Array of S_DialogueChoice | Available options for active choice | | `DefaultChoiceIndex` | Integer | Auto-selected if timer expires | | `ChoiceTimeLimit` | Float | Seconds before auto-select (0 = no limit) | | `ChoiceTimer` | TimerHandle | Countdown timer | | `bChoiceActive` | Bool | Player is currently choosing | | `TimeRemaining` | Float | Remaining time for UI display | ### Structs | Struct | Fields | Description | |--------|--------|-------------| | `S_DialogueChoice` | ChoiceText: FText, ResultFlagTag: GameplayTag, NextSequenceTag: GameplayTag, RequiredFlagTag: GameplayTag, bIsHidden: Bool, Priority: Integer, FlavorText: FText (tooltip/thought) | One choice option | ### Functions / Events | Name | Inputs | Outputs | Description | |------|--------|---------|-------------| | `PresentChoices` | Choices: Array of S_DialogueChoice, TimeLimit: Float | — | Opens choice UI and starts timer | | `SelectChoice` | ChoiceIndex: Integer | — | Player or system selects a choice | | `GetValidChoices` | Choices: Array of S_DialogueChoice | Array of S_DialogueChoice | Filters choices by RequiredFlagTag against narrative state | | `HasValidChoices` | Choices: Array | Bool | At least one choice available? | | `OnChoiceTimedOut` | — | — | Default choice auto-selected | | `CancelChoice` | — | — | Exits choice without selecting | | `ProcessSelectedChoice` | Choice: S_DialogueChoice | GameplayTag (NextSequenceTag) | Sets narrative flag and returns next sequence | | `IsChoiceActive` | — | Bool | Query | ### Event Dispatchers | Name | Parameters | Fired When | |------|-----------|-----------| | `OnChoicesPresented` | Choices: Array of S_DialogueChoice | Choice UI opens | | `OnChoiceSelected` | SelectedChoice: S_DialogueChoice, ChoiceIndex: Integer | Player makes selection | | `OnChoiceTimedOut` | DefaultChoiceIndex: Integer | Timer expired | | `OnChoiceCancelled` | — | Choice dismissed without selection | | `OnChoiceCompleted` | NextSequenceTag: GameplayTag | Choice processed, ready for next dialogue | ### Blueprint Flow ``` [PresentChoices called] └─► Call GetValidChoices (filter by narrative flags) └─► If no valid choices → skip (choose default or cancel) └─► Set CurrentChoices to valid set └─► Set bChoiceActive = true └─► Broadcast OnChoicesPresented to WBP_DialogueChoiceDisplay └─► If TimeLimit > 0 → start ChoiceTimer [SelectChoice called] └─► Validate ChoiceIndex is in range └─► Get selected S_DialogueChoice └─► Clear ChoiceTimer └─► Broadcast OnChoiceSelected └─► Call ProcessSelectedChoice [ProcessSelectedChoice] └─► If ResultFlagTag is valid → BPC_NarrativeStateSystem.SetFlag(ResultFlagTag) └─► Set bChoiceActive = false └─► Broadcast OnChoiceCompleted with NextSequenceTag └─► Hand NextSequenceTag back to BPC_DialoguePlaybackSystem ``` ### Communications With | Target System | Method | Why | |---------------|--------|-----| | [`BPC_NarrativeStateSystem`](58_BPC_NarrativeStateSystem.md) | Direct | Set choice flag, check required flags | | [`BPC_DialoguePlaybackSystem`](40_BPC_DialoguePlaybackSystem.md) | Dispatcher (receives) + Direct (returns) | Receives choice points, returns next sequence | | [`WBP_DialogueChoiceDisplay`](../06-ui/46_WBP_DialogueChoiceDisplay.md) | Dispatcher | Opens/closes choice UI | | [`BPC_BranchingConsequenceSystem`](42_BPC_BranchingConsequenceSystem.md) | Dispatcher | Choice flag changes trigger consequence evaluation | ### Reuse Notes Choice filtering by RequiredFlagTag allows context-sensitive dialogue without branching logic in the system. Choices can be hidden (e.g., secret dialogue options only appear if player has a specific lore unlock). The system handles all choice patterns: timed, untimed, locked, hidden, and priority-sorted. --- ## Manual Implementation Guide ### Class Setup 1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_DialogueChoiceSystem` 2. Add to Player Character 3. Define struct `S_DialogueChoice`: ChoiceText (Text), ResultFlagTag (GameplayTag), NextSequenceTag (GameplayTag), RequiredFlagTag (GameplayTag), Priority (Integer) ### Variable Init (BeginPlay) ``` Event BeginPlay ├─ Set CurrentChoices = empty array ├─ Set bChoiceActive = false ├─ Set ChoiceTimeLimit = 0.0 └─ Cache: BPC_NarrativeStateSystem, BPC_DialoguePlaybackSystem ``` ### Function Node-by-Node #### `PresentChoices(Choices: Array, TimeLimit: Float)` → `void` ``` Step 1: Filtered = GetValidChoices(Choices) ← filter by narrative flags Step 2: If Filtered.Length == 0: auto-cancel (or select hidden default) Step 3: Sort Filtered by Priority (descending) Step 4: Set CurrentChoices = Filtered Step 5: Set bChoiceActive = true Step 6: Fire OnChoicesPresented(CurrentChoices) → WBP_DialogueChoiceDisplay shows UI Step 7: If TimeLimit > 0: Set ChoiceTimeLimit = TimeLimit, TimeRemaining = TimeLimit Start looping timer (0.1s): TimeRemaining -= 0.1 → update UI If TimeRemaining <= 0 → Call OnChoiceTimedOut ``` #### `GetValidChoices(Choices)` → `Array` ``` ForEach Choices: If Choice.RequiredFlagTag valid: Call BPC_NarrativeStateSystem.GetFlag(Choice.RequiredFlagTag) If flag is true → Add to results Else: Add to results (no requirement) Return results ``` #### `SelectChoice(ChoiceIndex: Integer)` → `void` ``` Step 1: Validate ChoiceIndex < CurrentChoices.Length Step 2: Selected = CurrentChoices[ChoiceIndex] Step 3: Clear ChoiceTimer Step 4: Fire OnChoiceSelected(Selected, ChoiceIndex) Step 5: Call ProcessSelectedChoice(Selected) ``` #### `ProcessSelectedChoice(Choice)` → `GameplayTag` (NextSequenceTag) ``` Step 1: If Choice.ResultFlagTag valid: BPC_NarrativeStateSystem.SetFlag(Choice.ResultFlagTag, true) Step 2: Set bChoiceActive = false Step 3: Fire OnChoiceCompleted(Choice.NextSequenceTag) Step 4: Return Choice.NextSequenceTag ← caller (DialoguePlayback) plays this sequence ``` ### Build Checklist - [ ] Create BPC_DialogueChoiceSystem, add to Player Character - [ ] Define S_DialogueChoice struct - [ ] Implement PresentChoices with flag filtering + timer - [ ] Implement GetValidChoices with RequiredFlagTag check - [ ] Implement SelectChoice with timer clear - [ ] Implement ProcessSelectedChoice: set flag → return next sequence - [ ] Wire to WBP_DialogueChoiceDisplay via dispatcher - [ ] Test: dialogue choice appears → player selects → flag set → next dialogue plays