Dialogues

A comprehensive guide to the dialogue system, covering all component types, conditional logic, variables, triggers, and sounds with full examples.


How a Dialogue Works

A dialogue is a tree of components. Each component is a step in the conversation. The flow looks like this:

graph TD
    Start["start: NPC says 'Hello'
owner: npc"] -->|"jumpTo: main"| Main["main: Player picks option
owner: player"] Main -->|"'Quests?'"| Quests["quests: trigger openquests
owner: npc"] Main -->|"'Bye'"| Close["close: NPC says goodbye
owner: npc"]

Key concepts:

  • owner: "npc" — NPC speaks, then auto-advances via jumpTo
  • owner: "player" — Each text entry becomes a clickable button the player can choose
  • jumpTo — Tells the dialogue which component comes next
  • trigger — Executes a quest action (this is how you connect dialogue to quests!)

The most important trigger is "openquests" — it opens the quest selection menu, showing all available quests from this NPC.


Minimal Dialogue Template

A dialogue with one greeting and one quest option:

{
  "components": [
    {
      "code": "greeting",
      "owner": "npc",
      "type": "talk",
      "text": [{ "value": "yourmod:greeting" }],
      "jumpTo": "choices"
    },
    {
      "code": "choices",
      "owner": "player",
      "type": "talk",
      "text": [
        { "value": "yourmod:option-quests", "jumpTo": "questmenu" },
        { "value": "yourmod:option-leave", "jumpTo": "close" }
      ]
    },
    {
      "code": "questmenu",
      "owner": "npc",
      "type": "talk",
      "trigger": "openquests",
      "text": [{ "value": "yourmod:opening" }]
    },
    {
      "code": "close",
      "owner": "npc",
      "type": "talk",
      "text": [{ "value": "yourmod:goodbye" }]
    }
  ]
}

The trigger: "openquests" on the questmenu component is what opens the quest selection UI. You don't need to write any code — the framework handles it.


File Location

Dialogue files are placed in:

assets/yourmod/config/dialogue/name.json

Each file contains a components array — the individual steps in a conversation flow.

Component Types

NPC Speech

When owner is npc, the component displays the NPC's lines and automatically jumps to the next component:

{
  "code": "greeting",
  "owner": "npc",
  "type": "talk",
  "text": [
    { "value": "modid:dialogue-greeting" }
  ],
  "jumpTo": "main"
}

Player Choices

When owner is player, the text entries become clickable options. Each option can have its own jumpTo:

{
  "code": "main",
  "owner": "player",
  "type": "talk",
  "text": [
    { "value": "modid:option-quests", "jumpTo": "openquests" },
    { "value": "modid:option-shop", "jumpTo": "shop" },
    { "value": "modid:option-gossip", "jumpTo": "gossip" },
    { "value": "modid:option-leave", "jumpTo": "close" }
  ]
}

Condition Check

When type is condition, the component checks a variable and branches:

{
  "code": "checkfirstmeet",
  "owner": "npc",
  "type": "condition",
  "variable": "entity.hasmet",
  "isNotValue": "true",
  "thenJumpTo": "firstmeet",
  "elseJumpTo": "welcomeback"
}

💡 Use isValue to check if a variable equals a value, or isNotValue to check if it does NOT equal a value.

Conditional Choices

Player choices can be shown or hidden based on conditions. Add a conditions array to any text entry — all conditions must be met for the option to appear:

{
  "code": "main",
  "owner": "player",
  "type": "talk",
  "text": [
    { "value": "modid:option-quests", "jumpTo": "openquests" },
    {
      "value": "modid:secret-option",
      "jumpTo": "secret",
      "conditions": [
{ "variable": "entity.unlocked", "isValue": "true" },
{ "variable": "player.haskey", "isValue": "true" }
      ]
    },
    { "value": "modid:option-leave", "jumpTo": "close" }
  ]
}

In this example, the "secret-option" only appears if both entity.unlocked and player.haskey are set to "true".

Variables & Scopes

Variables are stored with different scopes:

  • entity. — Stored on the NPC entity (unique per NPC instance)
  • player. — Stored on the player entity (unique per player)
  • global. — Global scope (shared across all entities and players)

Setting Variables

Use the setVariables property on any component to set variables when that component is entered:

{
  "code": "firstmeet",
  "owner": "npc",
  "type": "talk",
  "text": [{ "value": "modid:first-meeting-text" }],
  "setVariables": {
    "entity.hasmet": "true",
    "player.metinnkeeper": "true"
  },
  "jumpTo": "main"
}

Checking Variables

Variables can be checked via:

  • Condition components — Branch the entire dialogue flow
  • Text entry conditions — Show/hide individual player choices

Action Triggers

The trigger property executes Alegacy VS Quest action strings when the component is entered. This is how dialogues connect to the quest system:

{
  "code": "openquests",
  "owner": "npc",
  "type": "talk",
  "trigger": "openquests",
  "text": [{ "value": "modid:dialogue-quests-opening" }]
}

Multiple actions are separated by ; (semicolon):

{
  "code": "reward",
  "owner": "npc",
  "type": "talk",
  "trigger": "playsound 'sounds/effect/receptionbell' 0.5;addreputation npc innkeeper 10;notify 'modid:rep-gained'",
  "text": [{ "value": "modid:reward-text" }],
  "jumpTo": "main"
}

⚠️ Action string arguments with spaces must be wrapped in single quotes: 'argument with spaces'

Per-Entry Triggers

Individual player choices can have their own trigger field, executed when that specific option is selected:

{
  "code": "choices",
  "owner": "player",
  "type": "talk",
  "text": [
    {
      "value": "modid:accept-quest",
      "jumpTo": "accepted",
      "trigger": "playsound 'sounds/effect/writing' 0.5"
    },
    {
      "value": "modid:ask-about-reward",
      "jumpTo": "reward-info"
    },
    {
      "value": "modid:decline",
      "jumpTo": "close",
      "trigger": "closedialogue"
    }
  ]
}

Sounds

The sound property plays a sound effect when the component is entered:

{
  "code": "dramatic-reveal",
  "owner": "npc",
  "type": "talk",
  "sound": "sounds/effect/deepbell",
  "text": [{ "value": "modid:dramatic-text" }],
  "jumpTo": "next"
}

Full Example

A complete dialogue flow showing greeting, condition check, first meet/welcome back, and player choices with triggers:

{
  "components": [
    {
      "code": "start",
      "owner": "npc",
      "type": "condition",
      "variable": "entity.hasmet",
      "isNotValue": "true",
      "thenJumpTo": "firstmeet",
      "elseJumpTo": "welcomeback"
    },
    {
      "code": "firstmeet",
      "owner": "npc",
      "type": "talk",
      "text": [{ "value": "modid:first-greeting" }],
      "setVariables": { "entity.hasmet": "true" },
      "jumpTo": "main"
    },
    {
      "code": "welcomeback",
      "owner": "npc",
      "type": "talk",
      "text": [{ "value": "modid:welcome-back" }],
      "jumpTo": "main"
    },
    {
      "code": "main",
      "owner": "player",
      "type": "talk",
      "text": [
{ "value": "modid:option-quests", "jumpTo": "questopen" },
{ "value": "modid:option-gossip", "jumpTo": "gossip" },
{ "value": "modid:option-leave", "jumpTo": "close" }
      ]
    },
    {
      "code": "questopen",
      "owner": "npc",
      "type": "talk",
      "trigger": "openquests",
      "text": [{ "value": "modid:quest-intro" }]
    },
    {
      "code": "gossip",
      "owner": "npc",
      "type": "talk",
      "text": [{ "value": "modid:gossip-text" }],
      "jumpTo": "main"
    },
    {
      "code": "close",
      "owner": "npc",
      "type": "talk",
      "trigger": "closedialogue",
      "text": [{ "value": "modid:goodbye" }]
    }
  ]
}

Press ESC to close