How It Works

When a player interacts with an NPC, QuestLines looks up all quests linked to that NPC and walks through their pages in order. The first page whose requirements all pass is displayed as a dialogue screen. The player sees the NPC's text and response buttons. Choosing a response executes its actions — updating quest state, giving items, running commands, or navigating to another page.

Core Concepts

Quest

A Quest is the top-level container. It has a title, description, and an ordered list of page IDs. When a player interacts with an NPC, the quest's pages are evaluated in the order they appear in this list.

Page

A Page represents one screen of dialogue. It has its own requirements (which must pass for the page to be selected), NPC display name, dialogue text, optional load actions, and any number of responses. Load actions run automatically whenever the page is shown — on initial NPC interaction and on any page: navigation — regardless of which response the player clicks.

Response

A Response is one button on a dialogue screen. It has display text, its own requirements (controlling whether the button appears), and a list of actions executed when clicked.

PlayerData

Each player has a persistent data record storing: started quests, completed quests, custom tags, named tracker progress counters, and timestamps for cooldown checks. This data is stored in players.json and managed automatically.

Data Model

All configuration is stored as JSON files on the server. Below is the structure of each config type.

Quest File — quests/<id>.json

{
  "Title":        "The Lost Sword",
  "Description": "Help the blacksmith retrieve his stolen blade.",
  "Requirements": [],
  "Actions":      [],
  "Pages": [
    "lost_sword_intro",
    "lost_sword_progress",
    "lost_sword_turnin",
    "lost_sword_complete"
  ]
}

Page (in quest JSON under PageData)

{
  "Id":           "lost_sword_intro",
  "Title":       "A Favour to Ask",
  "Name":        "Aldric the Smith",  // NPC display name on this page
  "Requirements": ["questNotStarted:lost_sword"],
  "LoadActions":  [],  // actions run automatically when this page is shown
  "GoalText":     "",  // legacy: free-text HUD goal; overridden when Objectives is non-empty
  "Objectives":  [],  // requirement strings shown as pass/fail objectives in HUD + journal
  "Dialog":      "Ah, {username}! My sword was stolen by goblins. Will you help?",
  "Responses": [
    { "Text": "I'll find it for you.", "Requirements": [], "Actions": ["questStarted:lost_sword", "track:goblin_kills:kill:Goblin*"] },
    { "Text": "Not right now.", "Requirements": [], "Actions": [] }
  ]
}

NPC Config — npcs.json

{
  "Npcs": {
    "citizen_42": "lost_sword,daily_reward",
    "citizen_07": "goblin_king"
  },
  "RandomGroups": {
    "citizen_10": "questA|questB;questC|questD"
  }
}

players.json — auto-managed

{
  "Players": {
    "player-uuid-here": {
      "CompletedQuests": ["tutorial"],
      "StartedQuests":   ["lost_sword"],
      "Tags":           ["vip"],
      "Progress":       { "goblin_kills": 3 },
      "Timestamps":     { "daily_key": 1735000000000 },
      "Variables":      { "score": 7 },
      "TrackedQuests":  ["lost_sword"],
      "PreferredLanguage": "en-US",
      "AutoTrackQuests": true
    }
  }
}

Page Resolution Algorithm

Understanding how QuestLines selects a page is essential for authoring correct quest flows. The algorithm runs every time a player interacts with an NPC:

  1. Look up quests for this NPC.

    The NPC's citizen ID is looked up in npcs.json. The comma-separated list of quest IDs is the evaluation order for that NPC.

  2. For each quest, iterate its Pages list.

    Pages are evaluated in the order they appear in the Quest's Pages array.

  3. Check this page's Requirements.

    All requirements must pass. If any fails, skip to the next page.

  4. Show the first matching page.

    As soon as a page passes all requirements, that dialogue is opened. No further pages are evaluated.

  5. If no page matches, no dialogue opens.

    The player's interaction with the NPC silently does nothing.

Order Matters

Put your most specific pages first. A completed-state page must come before an in-progress page, which must come before the intro page. If the intro page (with questNotStarted) were listed last, it would never match once the quest was started because the in-progress page would match first. See Quest Patterns for full worked examples.

Admin Commands

Command Description
/ql create Open the quest creation wizard to scaffold a new quest and its pages.
/ql quest  (aliases: /ql ui, /ql q) Open the full QuestLines editor UI to browse and edit quests, pages, NPCs, and players.
/ql npc Open the NPC management panel.
/ql wand <questId> Enter wand mode. The next NPC you punch will be linked to the specified quest.
/ql wandcancel Cancel an active wand mode assignment.
/ql reload Reload all config files from disk without restarting the server.
/ql info Show plugin version and dependency information.
/ql help List all available /ql commands.
💡
Tip

Use /ql wand <questId> as the fastest way to link quests to NPCs in-world. See NPC Setup for full details on wand mode and alternative linking methods.

Player Commands

Command Description
/journal  (aliases: /j, /log) Open the Quest Journal. Shows active and completed quests with the last dialogue seen for each, plus objectives (or goal text) for the current page. Players can toggle quest tracking to show objectives/goal text on the HUD.
/qlconfig Open the personal quest settings UI to configure preferred language and auto-track HUD behaviour. Requires the questlines.config.use permission.

Permissions

QuestLines uses the following permission nodes. Admin commands require questlines.admin; it defaults to false (op-only). Player commands have their own nodes that default to true.

Permission Default Description
questlines.admin false Required for all /ql admin commands (quest editor, NPC setup, wand mode, reload, etc.).
questlines.journal.use true Required to open the Quest Journal via /journal.
questlines.config.use true Required to open the player settings UI via /qlconfig.
Multi-Language Support

QuestLines ships with built-in translations for English (en-US), Spanish (es-ES), German (de-DE), French (fr-FR), Portuguese (pt-BR), and Russian (ru-RU). Players can choose their preferred language via /qlconfig. Admins can add or override translations by placing .lang files in {pluginDataDir}/lang/{locale}.lang. The server default locale is set in the plugin config; individual players override it per-player.

What to Read Next