Quest Structure
Quests are the core of the framework. This page covers the JSON structure, action hooks, rewards, and chaining. For objectives, actions, and stages see their dedicated pages.
💡 See also: Objectives — Actions — Stages
Anatomy of a Quest
Every quest follows this structure:
graph TD
A([Player accepts quest]) --> B[onAcceptedActions
playsound, journal entry,
set attributes]
B --> C[Objectives
kill / gather / reach / interact]
C --> D{All objectives
completed?}
D -->|NO| C
D -->|YES| E[itemRewards
gear, items, loot]
E --> F[actionRewards
notify, reputation,
next quest trigger]
F --> G([Quest Complete])
C -->|Player dies / abandons| I([Quest remains active
or is abandoned])How to read this flowchart:
- Start — Player accepts the quest (via NPC dialogue or auto-assign)
- onAcceptedActions — Fire immediately: play sound, add journal entry, set attributes
- Objectives — The quest tracks player progress. This loops until all objectives are met
- Rewards — When all objectives are done,
itemRewards(gear/items) andactionRewards(notify, reputation, next quest trigger) execute - Quest Complete — The quest is marked finished
- Abandon — If the player dies or abandons the quest, it either stays active (permanent) or is dropped. There is no automatic failure reward path.
Copy-Paste Templates
Here are three minimal quest templates. Each is a complete working quest — just adjust the IDs and values.
Gather Quest (collect items)
{
"id": "yourmod:gather-herbs",
"cooldown": -1,
"perPlayer": true,
"onAcceptedActions": [
{ "id": "playsound", "args": ["sounds/effect/writing", "0.5"] }
],
"gatherObjectives": [
{ "validCodes": ["game:herb*"], "demand": 10 }
],
"itemRewards": [
{ "itemCode": "game:gear-rusty", "amount": 3 }
],
"actionRewards": [
{ "id": "notify", "args": ["yourmod:gather-done"] }
]
}Kill Quest (slay creatures)
{
"id": "yourmod:kill-wolves",
"cooldown": 48,
"perPlayer": true,
"onAcceptedActions": [
{ "id": "playsound", "args": ["sounds/effect/writing", "0.5"] }
],
"killObjectives": [
{ "validCodes": ["wolf-male", "wolf-female"], "demand": 5 }
],
"itemRewards": [
{ "itemCode": "game:ingot-gold", "amount": 2 }
],
"actionRewards": [
{ "id": "notify", "args": ["yourmod:kill-done"] }
]
}Chain Quest (requires another quest first)
{
"id": "yourmod:deliver-herbs",
"cooldown": -1,
"perPlayer": true,
"predecessor": "yourmod:gather-herbs",
"onAcceptedActions": [
{ "id": "playsound", "args": ["sounds/effect/writing", "0.5"] }
],
"actionObjectives": [
{
"id": "reach_village",
"objectiveId": "reachwaypoint",
"args": ["5000,70,3000", "5"]
}
],
"actionRewards": [
{ "id": "notify", "args": ["yourmod:delivery-done"] },
{ "id": "questitem", "args": ["yourmod:delivery-receipt"] }
]
}The predecessor field links quests. Quest 2 only appears after Quest 1 is completed.
Quest Structure
Quests are JSON files in config/quests/<folder>/<name>.json:
{
"id": "yourmod:collect-herbs",
"cooldown": 48,
"perPlayer": true,
"predecessor": "yourmod:intro-quest",
"onAcceptedActions": [...],
"actionObjectives": [...],
"killObjectives": [...],
"gatherObjectives": [...],
"itemRewards": [...],
"actionRewards": [...],
"onFailedActions": [...],
"stages": [...]
}Core Fields
id— Unique quest identifier (e.g.yourmod:quest-name)cooldown— Hours before quest can be retaken (-1= one-time only)perPlayer— Whether quest progress is per-playerpredecessor— Quest ID that must be completed first (chains quests)
Action Hook Arrays
| Property | When it triggers |
|---|---|
onAcceptedActions | When the player accepts the quest |
actionRewards | When the quest is completed successfully |
onStageCompleteActions | When a stage completes (multi-stage quests) |
onCompleteActions | When a specific action-objective completes |
💡 For the full list of action IDs (giveitem, playsound, setattribute, addreputation, etc.), see the Actions page.
Each array contains action objects with id and args:
"onAcceptedActions": [
{ "id": "playsound", "args": ["game:sounds/quest-accept", "0.8"] },
{ "id": "setattribute", "args": ["questStarted", "true"] }
]Rewards
Item Rewards
"itemRewards": [
{ "itemCode": "game:ingot-gold", "amount": 5 },
{ "itemCode": "game:bread-spelt", "amount": 10 }
]Random Item Rewards
"randomItemRewards": [
{
"lootTable": "yourmod:boss-loot",
"count": 1
}
]Action Rewards
"actionRewards": [
{ "id": "questitem", "args": ["yourmod:shadow-earring"] },
{ "id": "addreputation", "args": ["guild", "guild-npc", "10"] },
{ "id": "playsound", "args": ["game:sounds/quest-complete"] }
]Quest Chains
Use the predecessor field to create linear quest chains:
// Quest 1: intro-quest (no predecessor)
{ "id": "yourmod:intro-quest", "cooldown": -1 }
// Quest 2: requires intro-quest
{ "id": "yourmod:gather-herbs", "predecessor": "yourmod:intro-quest" }
// Quest 3: requires gather-herbs
{ "id": "yourmod:deliver-herbs", "predecessor": "yourmod:gather-herbs" }A quest with a predecessor will only appear in quest giver dialogues after the predecessor is completed.
Action String Format
Action strings are a compact way to specify actions in dialogues and onCompleteActions:
actionId arg1 arg2 'argument with spaces'; anotherActionId arg1Parsing Rules
- Split by
;(semicolon) into individual action commands - Each command is tokenized — first token is the action ID, rest are arguments
- Arguments wrapped in single quotes
'...'preserve spaces inside them - The action ID is looked up in the action registry and executed
// Examples:
playsound 'game:sounds/effect' 0.8
giveitem 'game:ingot-gold' 5; playsound 'game:sounds/reward'
setattribute questProgress 3; completequest