Quests
Quests
Section titled “Quests”TalesMUD’s quest system is data-driven. Every quest is a JSON/YAML document with objectives, rewards, prerequisites, and optional Lua completion scripts. Progress is tracked automatically for Kill, Collect, Deliver, Visit, and Talk objectives.
Quick Start: Minimal Quest
Section titled “Quick Start: Minimal Quest”curl -X POST http://localhost:8010/api/quests \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Rat Problem", "description": "The cellars are overrun with rats. Clear them out.", "category": "side", "level": 1, "source": { "type": "npc", "npcId": "NPC0001" }, "objectives": [ { "id": "obj1", "type": "kill", "description": "Kill 5 Catacomb Rats", "targetId": "ENM0001", "targetName": "Catacomb Rat", "amount": 5, "order": 1 } ], "rewards": { "xp": 50, "gold": 10 }, "acceptDialogText": "Those rats are getting bold. Kill five of them.", "completeDialogText": "Good work. Here is your payment." }'Quest Fields
Section titled “Quest Fields”| Field | Required | Description |
|---|---|---|
name | Yes | Display name in quest log |
description | Yes | Journal text describing the quest |
category | No | main, side, or daily |
level | No | Recommended level (display only) |
repeatable | No | If true, can be accepted again after completion |
source | Yes | How the quest is obtained |
objectives | Yes | Array of objectives (at least one) |
rewards | No | XP, gold, and item rewards |
requiredQuestIds | No | Quest IDs that must be completed first |
requiredLevel | No | Minimum character level |
onCompleteScriptId | No | Lua script ID to run on completion |
acceptDialogText | No | NPC speech when offering the quest |
progressDialogText | No | NPC speech while quest is in progress |
completeDialogText | No | NPC speech when turning in the quest |
Objective Types
Section titled “Objective Types”Track how many NPCs matching a template are killed:
{ "id": "kill_rats", "type": "kill", "description": "Kill 5 Catacomb Rats", "targetId": "ENM0001", "targetName": "Catacomb Rat", "amount": 5, "order": 1}targetId must be the template ID (e.g., ENM0001), not a spawned instance ID.
Collect
Section titled “Collect”Track how many items matching a template are picked up:
{ "id": "collect_pelts", "type": "collect", "description": "Collect 3 Wolf Pelts", "targetId": "ITM0013", "targetName": "Wolf Pelt", "amount": 3, "order": 1}Note: The tracker counts pickup events, not current inventory. Items dropped and re-picked still count.
Deliver
Section titled “Deliver”Bring an item to a specific NPC:
{ "id": "deliver_letter", "type": "deliver", "description": "Deliver the Sealed Letter to Captain Aldric", "targetId": "ITM0025", "targetName": "Sealed Letter", "deliverToNpcId": "NPC0004", "deliverToNpcName": "Captain Aldric", "amount": 1, "order": 1}Enter a specific room:
{ "id": "visit_marsh", "type": "visit", "description": "Travel to Gloomfen Marsh", "targetId": "R0301", "targetName": "Marsh Gate Trail", "amount": 1, "order": 1}Talk to an NPC (optionally reaching a specific dialog node):
{ "id": "talk_archivist", "type": "talk", "description": "Speak with Archivist Maren", "targetId": "NPC0007", "targetName": "Archivist Maren", "dialogNodeId": "ruins_info", "amount": 1, "order": 1}Custom Lua
Section titled “Custom Lua”Progress managed by a Lua script:
{ "id": "solve_puzzle", "type": "custom", "description": "Solve the Ancient Rune Puzzle", "checkScriptId": "SCR0007", "amount": 1, "order": 1}In your script:
local charID = ctx.character.idif tales.quests.isActive(charID, "QST0005") then tales.quests.setProgress(charID, "QST0005", "solve_puzzle", 1)endQuest Sources
Section titled “Quest Sources”| Source | Description |
|---|---|
npc + npcId | Quest offered by an NPC via auto-injected dialog |
item + itemId | Quest granted via item pickup/use (needs Lua script) |
auto | Quest is always available in the player’s quest list |
script | Quest granted via tales.quests.grantQuest() from any script |
NPC Dialog Integration
Section titled “NPC Dialog Integration”When source.type = "npc", dialog options are automatically injected when players talk
to the source NPC:
| State | Injected Option |
|---|---|
| Available (not started) | [Quest] {quest name} using acceptDialogText |
| Active (in progress) | [Quest] {quest name} (in progress) using progressDialogText |
| Active (objectives complete) | [Quest] Turn in: {quest name} using completeDialogText |
| Completed (non-repeatable) | Nothing injected |
Prerequisites
Section titled “Prerequisites”"requiredQuestIds": ["quest-uuid-1", "quest-uuid-2"],"requiredLevel": 5All listed quests must have completed status. Use captured UUIDs when creating chains programmatically.
Rewards
Section titled “Rewards”"rewards": { "xp": 100, "gold": 25, "itemTemplateIds": ["ITM0012", "ITM0015"]}Items are created from templates and added to the player’s inventory on completion.
YAML Format
Section titled “YAML Format”Quests can be authored as YAML files in data/quests/QST####.yaml:
id: QST0201name: Sewer Sweepdescription: > Clear the creatures from Oldtown's sewer system.category: sidelevel: 2source: type: npc npcId: NPC0004objectives: - id: kill_rats type: kill description: Kill 8 Sewer Rats targetId: ENM0001 amount: 8 order: 1rewards: xp: 75 gold: 25acceptDialogText: Clear out whatever is in the sewers. I'll pay.completeDialogText: Good work. Here's your payment.Next Steps
Section titled “Next Steps”- NPCs & Spawners — Creating quest-giver NPCs
- Dialog Trees — Manual dialog authoring
- Lua Scripting — Custom quest objectives and completion effects