$npx -y skills add thedivergentai/GD-Agentic-Skills --skill godot-dialogue-systemExpert patterns for branching dialogue systems including dialogue graphs (Resource-based), character portraits, player choices, conditional dialogue (flags/quests), typewriter effects, localization support, and voice acting integration. Use for narrative games, RPGs, or visual no
| 1 | # Dialogue System |
| 2 | |
| 3 | Expert guidance for building flexible, data-driven dialogue systems. |
| 4 | |
| 5 | ## Available Scripts |
| 6 | |
| 7 | ### [dialogue_resource.gd](scripts/dialogue_resource.gd) |
| 8 | Data-driven conversation tree container using Resources for modular, branching narrative paths. |
| 9 | |
| 10 | ### [dialogue_node_data.gd](scripts/dialogue_node_data.gd) |
| 11 | Serialized data structure for a single line of dialogue, including speaker metadata and portraits. |
| 12 | |
| 13 | ### [dialogue_option_data.gd](scripts/dialogue_option_data.gd) |
| 14 | Interactive player choice definition with branching logic and scriptable availability conditions. |
| 15 | |
| 16 | ### [dialogue_manager_singleton.gd](scripts/dialogue_manager_singleton.gd) |
| 17 | Centralized AutoLoad orchestrator for traversing dialogue trees and broadcasting state signals. |
| 18 | |
| 19 | ### [dialogue_ui_controller.gd](scripts/dialogue_ui_controller.gd) |
| 20 | Reactive UI bridge that maps dialogue data to visual labels and dynamic choice buttons. |
| 21 | |
| 22 | ### [typebox_effect.gd](scripts/typebox_effect.gd) |
| 23 | Polished "Character-by-character" text reveal effect using Godot's built-in Tweens. |
| 24 | |
| 25 | ### [dialogue_event_bridge.gd](scripts/dialogue_event_bridge.gd) |
| 26 | Bridge node for triggering external game events (e.g. starting a quest) from conversation nodes. |
| 27 | |
| 28 | ### [branching_condition_validator.gd](scripts/branching_condition_validator.gd) |
| 29 | Expert logic for evaluating player stats or global flags to toggle dialogue choices. |
| 30 | |
| 31 | ### [localized_dialogue_resource.gd](scripts/localized_dialogue_resource.gd) |
| 32 | Advanced strategy for supporting multi-language conversation text via translation keys. |
| 33 | |
| 34 | ### [dialogue_portrait_manager.gd](scripts/dialogue_portrait_manager.gd) |
| 35 | Visual controller for managing character expressions and entry animations during dialogue. |
| 36 | |
| 37 | ## NEVER Do in Dialogue Systems |
| 38 | |
| 39 | - **NEVER hardcode dialogue text directly in your GDScript files** — This makes translation impossible. Store text in Resources or external JSON/CSV files [12]. |
| 40 | - **NEVER display choices that the player hasn't met the criteria for** — Hidden choices should stay hidden unless they are "grayed out" intentionally to show a missed path [13]. |
| 41 | - **NEVER use loose strings for node transitions without validation** — Typos in `next_node_id` will crash the dialogue mid-convo. Use `assert()` or a central ID registry [14]. |
| 42 | - **NEVER force a typewriter effect without a "Skip" option** — Forcing players to read at a fixed speed leads to frustration. Always allow clicking to finish the line [15]. |
| 43 | - **NEVER store the current dialogue state inside a UI node** — If the UI is closed or the scene changes, the player loses their place. Use an AutoLoad `DialogueManager` [16]. |
| 44 | - **NEVER use `get_node()` to find dialogue UI from the NPC script** — Use signals like `DialogueManager.start_dialogue(res)` to maintain a decoupled architecture. |
| 45 | - **NEVER use complex regex for simple text tags** — Godot's `RichTextLabel` supports BBCode tags natively. Use `[b]`, `[i]`, and `[url]` for formatting. |
| 46 | - **NEVER perform save/load operations inside a dialogue node** — Conversation nodes should be pure data. Delegate persistence to a dedicated `SaveSystem`. |
| 47 | - **NEVER block the main thread for text reveal timing** — Never use `OS.delay_msec()`. Use `create_timer()` or `Tween` to maintain smooth 60fps performance. |
| 48 | - **NEVER hardcode portrait paths** — Assign textures directly to the `DialogueNode` resource in the inspector or use a central `PortraitDatabase`. |
| 49 | --- |
| 50 | |
| 51 | ## Godot 4.7: Dialogue UI |
| 52 | |
| 53 | - RichTextLabel `add_image`/`update_image` use `width_unit`/`height_unit` (`ImageUnit`) — update portrait and inline image helpers. |
| 54 | |
| 55 | ## Available Scripts |
| 56 | |
| 57 | > **MANDATORY**: Read the appropriate script before implementing the corresponding pattern. |
| 58 | |
| 59 | ### [dialogue_engine.gd](scripts/dialogue_engine.gd) |
| 60 | Graph-based dialogue with BBCode signal tags. Parses [trigger:event_id] tags from text, fires signals, and loads external JSON dialogue graphs. |
| 61 | |
| 62 | ### [dialogue_manager.gd](scripts/dialogue_manager.gd) |
| 63 | Data-driven dialogue engine with branching, variable storage, and conditional choices. |
| 64 | |
| 65 | --- |
| 66 | |
| 67 | ## Dialogue Data |
| 68 | |
| 69 | ```gdscript |
| 70 | # dialogue_line.gd |
| 71 | class_name DialogueLine |
| 72 | extends Resource |
| 73 | |
| 74 | @export var speaker: String |
| 75 | @export_multiline var text: String |
| 76 | @export var portrait: Texture2D |
| 77 | @export var choices: Array[DialogueChoice] = [] |
| 78 | @export var conditions: Array[String] = [] # Quest flags, etc. |
| 79 | @export var next_line_id: String = "" |
| 80 | ``` |
| 81 | |
| 82 | ```gdscript |
| 83 | # dialogue_choice.gd |
| 84 | class_name DialogueChoice |
| 85 | extends Resource |
| 86 | |
| 87 | @export var choice_text: String |
| 88 | @export var next_line_id: Strin |