Dialog System
Dialog System
Section titled “Dialog System”The dialog system lets you create branching conversations with NPCs. Dialogs are defined as JSON files and support multiple node types, conditional branching, command macros and localization.
How Dialogs Work
Section titled “How Dialogs Work”When a player presses F on an NPC, the system follows this priority chain:
- Quest NPC Profile — If the Quest mod has a profile for this citizen, the quest dialog system takes over.
- Citizen Dialogs — The
dialogsarray in the citizen config is checked. The first dialog whose condition matches is opened. - Messages — If no dialog matches, simple chat messages are sent.
- Shop / Commands — If no dialog or messages exist, the shop or command actions are executed.
Quest NPC Profiles always take priority. If a citizen has both a quest profile and legacy dialogs, only the quest profile dialog is shown. Do not mix both on the same NPC.
Dialog File Structure
Section titled “Dialog File Structure”Dialog files live in configs/kyuubisoft_core/dialogs/ as individual JSON files.
{ "id": "example_dialog", "speakerName": "dialog.example.speaker", "startNode": "greeting", "nodes": [ { "nodeId": "greeting", "type": "TEXT", "lines": ["dialog.example.greeting.line1", "dialog.example.greeting.line2"], "next": "ask_help" }, { "nodeId": "ask_help", "type": "CHOICE", "lines": ["dialog.example.ask_help"], "choices": [ { "text": "dialog.example.choice.yes", "next": "accepted" }, { "text": "dialog.example.choice.no", "next": "declined" }, { "text": "dialog.example.choice.later", "next": null } ] }, { "nodeId": "accepted", "type": "TEXT", "lines": ["dialog.example.accepted.line1"], "next": null }, { "nodeId": "declined", "type": "TEXT", "lines": ["dialog.example.declined.line1"], "next": null } ]}Top-Level Fields
Section titled “Top-Level Fields”| Field | Required | Description |
|---|---|---|
id | Yes | Unique dialog ID. Referenced from citizen config. |
speakerName | No | Display name for the speaker. Can be an i18n key or plain text. Falls back to the citizen’s name if omitted. |
startNode | Yes | ID of the first node to display. |
nodes | Yes | Array of dialog nodes. |
Node Types
Section titled “Node Types”TEXT Node
Section titled “TEXT Node”Displays one or more lines of text. The player clicks to advance to the next node.
{ "nodeId": "greeting", "type": "TEXT", "lines": ["Hello, traveler!", "Welcome to our village."], "next": "ask_help"}lines— Array of text strings or i18n keys (1-4 lines recommended).next— ID of the next node. Set tonullto end the dialog.
CHOICE Node
Section titled “CHOICE Node”Displays text with selectable response options.
{ "nodeId": "ask_help", "type": "CHOICE", "lines": ["Can you help me gather some herbs?"], "choices": [ { "text": "Sure, I will help!", "next": "accepted" }, { "text": "Not right now.", "next": null } ]}Each choice has:
text— Display text or i18n key.next— Node to jump to.nullcloses the dialog.condition— Optional condition to show/hide this choice (see below).macro— Optional commands to execute when this choice is selected.
INPUT Node
Section titled “INPUT Node”Prompts the player for text input. The input is dispatched to the citizen listeners.
{ "nodeId": "name_input", "type": "INPUT", "lines": ["What is your name, adventurer?"], "next": "response"}Conditions
Section titled “Conditions”Conditions control which dialogs or choices are available based on the player’s state.
On Citizens (Conditional Dialogs)
Section titled “On Citizens (Conditional Dialogs)”The citizen’s dialogs array supports conditions to select which dialog opens:
{ "dialogs": [ { "dialogId": "quest_complete_dialog", "condition": { "type": "quest_completed", "value": "intro_quest" } }, { "dialogId": "quest_active_dialog", "condition": { "type": "quest_active", "value": "intro_quest" } }, { "dialogId": "default_greeting" } ]}The system checks conditions top to bottom. The first matching dialog is opened. An entry without a condition acts as a fallback.
On Choices
Section titled “On Choices”Individual choices can be shown or hidden based on conditions:
{ "choices": [ { "text": "I have completed the trial.", "next": "reward", "condition": { "type": "quest_completed", "value": "trial_quest" } }, { "text": "Tell me about the trial.", "next": "explain" } ]}Available Condition Types
Section titled “Available Condition Types”| Type | Value | Description |
|---|---|---|
permission | Permission string | Player has the specified permission. |
quest_active | Quest ID | Player has this quest active. |
quest_completed | Quest ID | Player has completed this quest. |
achievement_unlocked | Achievement ID | Player has unlocked this achievement. |
has_item | Item ID | Player has this item in their inventory. |
All conditions support a negate flag. Set "negate": true to invert the result (e.g. show only if the quest is NOT completed).
Macros (Commands)
Section titled “Macros (Commands)”Macros let you execute commands when a dialog node is reached or a choice is selected.
{ "nodeId": "reward_node", "type": "TEXT", "lines": ["Here is your reward!"], "next": null, "macro": { "commands": [ "give {player} Coin_Gold 50", "ksquestadmin complete {player} intro_quest" ], "runAsServer": true }}| Field | Default | Description |
|---|---|---|
commands | — | List of commands to execute. |
runAsServer | false | true = run as server console, false = run as the player. |
Placeholders:
{player}— replaced with the player’s username.{citizen}— replaced with the citizen’s ID.
Commands in macros use the ks-prefixed command names (e.g. ksquestadmin, ksachievementadmin). Make sure you use the correct prefix.
Localization (i18n)
Section titled “Localization (i18n)”All text fields (lines, choices.text, speakerName) support i18n keys. Define translations in the core mod’s localization files:
{ "dialog.example.speaker": "Elder Willowbark", "dialog.example.greeting.line1": "Greetings, young adventurer.", "dialog.example.greeting.line2": "The forest whispers of your arrival.", "dialog.example.choice.yes": "I am ready to help!", "dialog.example.choice.no": "Maybe later."}If a key is not found in the localization file, the raw key string is displayed as-is. This lets you use plain text directly in the JSON without needing a translation file.
Linking Dialogs to Quest NPC Profiles
Section titled “Linking Dialogs to Quest NPC Profiles”For quest-related NPCs, the recommended approach is to use the Quest mod’s NPC Profile system instead of the core dialog system. Quest NPC Profiles provide specialized dialogs for quest offer, active and complete states with built-in macros like start_quest and complete_quest.
See the Quest System documentation for details on quest NPC profiles.