data schema
Guide for data schema
Quest Data Schema
quests.json Structure
The quest data file uses a HashMap structure where keys are quest IDs and values are quest definitions.
Root Structure
{
"quest_id_1": { /* QuestDefinition */ },
"quest_id_2": { /* QuestDefinition */ },
...
}QuestDefinition Schema
interface QuestDefinition {
id: string; // Quest identifier (matches key)
name: string; // Display name
description: string; // Quest description
category?: string; // e.g., "tutorial", "main", "side"
difficulty?: string; // e.g., "novice", "intermediate", "master"
start_npc?: string; // NPC ID who gives the quest
rewards?: QuestRewards; // Completion rewards
steps: { [stepId: string]: QuestStep }; // Step definitions
}
interface QuestRewards {
xp?: number; // Experience points
items?: ItemReward[]; // Item rewards
}
interface ItemReward {
item_id: string; // Item identifier
quantity: number; // Amount to grant
}
interface QuestStep {
description: string; // Step objective description
type?: string; // "dialogue", "interaction", "kill"
target_npc?: string; // For dialogue steps
target_object?: string; // For interaction steps
target_creature?: string; // For kill steps
required_count?: number; // For kill steps (how many to kill)
next_step?: number; // Next step ID (null for terminal)
finish?: boolean; // True if this completes the quest
}Step Types
1. Dialogue Steps
Completed when player talks to specified NPC.
{
"0": {
"description": "Speak to Guard Captain at the training grounds.",
"type": "dialogue",
"target_npc": "npc_custom_1",
"next_step": 10
}
}Listener:
track_quest_dialogue in quest_listeners.rs- Listens to
NPCInteractionEvent - Matches
event.npc_idwithstep.target_npc
2. Interaction Steps
Completed when player interacts with object/entity.
{
"10": {
"description": "Search the Ancient Bookshelf for the scroll.",
"type": "interaction",
"target_object": "obj_bookshelf_ancient",
"next_step": 20
}
}Listener:
track_quest_dialogue (reused)- Uses
NPCcomponent on objects withnpc_idmatchingtarget_object - Triggered by
NPCInteractionEvent
3. Kill Steps
Completed when player defeats specified creatures.
{
"10": {
"description": "Defeat 5 goblins in the forest.",
"type": "kill",
"target_creature": "goblin",
"required_count": 5,
"next_step": 20
}
}Listener:
track_quest_kills in quest_listeners.rs- Listens to
EnemyDefeatedEvent - Increments kill count (tracked separately)
- Advances when count reaches
required_count
Step Progression
Linear Progression
{
"steps": {
"0": { "next_step": 10 },
"10": { "next_step": 20 },
"20": { "finish": true }
}
}Terminal Steps
Two ways to mark a step as terminal:
- Using finish flag:
{
"20": {
"description": "Return to quest giver.",
"type": "dialogue",
"target_npc": "npc_id",
"finish": true
}
}- Using null next_step:
{
"20": {
"description": "Return to quest giver.",
"type": "dialogue",
"target_npc": "npc_id",
"next_step": null
}
}Step ID Conventions
Recommended Pattern
Use increments of 10 for step IDs to allow insertion of intermediate steps:
{
"steps": {
"0": { "next_step": 10 },
"10": { "next_step": 20 },
"20": { "next_step": 30 },
"30": { "finish": true }
}
}If you need to add a step between 10 and 20 later:
{
"steps": {
"0": { "next_step": 10 },
"10": { "next_step": 15 }, // Modified
"15": { "next_step": 20 }, // New step inserted
"20": { "next_step": 30 },
"30": { "finish": true }
}
}Alternative: Semantic IDs
{
"steps": {
"intro": { "next_step": "gather_items" },
"gather_items": { "next_step": "return" },
"return": { "finish": true }
}
}Note: Current implementation expects numeric IDs for
stage_id conversion in Plugin API.Complete Example
{
"the_lost_scroll": {
"id": "the_lost_scroll",
"name": "The Lost Scroll",
"category": "tutorial",
"difficulty": "novice",
"description": "Scholar Vyasa seeks an ancient scroll lost in the palace library.",
"start_npc": "npc_vyasa",
"rewards": {
"xp": 100,
"items": [
{
"item_id": "ancient_scroll",
"quantity": 1
},
{
"item_id": "coins",
"quantity": 50
}
]
},
"steps": {
"0": {
"description": "Speak to Scholar Vyasa at the Palace.",
"type": "dialogue",
"target_npc": "npc_vyasa",
"next_step": 10
},
"10": {
"description": "Search the Ancient Bookshelf for the scroll.",
"type": "interaction",
"target_object": "obj_bookshelf_ancient",
"next_step": 20
},
"20": {
"description": "Return the scroll to Scholar Vyasa.",
"type": "dialogue",
"target_npc": "npc_vyasa",
"finish": true
}
}
}
}NPC Integration
Quest NPCs must be defined in
npcs.json:{
"npc_vyasa": {
"id": "npc_vyasa",
"name": "Scholar Vyasa",
"type": "npc",
"examine": "A wise scholar studying ancient texts.",
"left_click_action": "talk",
"context_menu_options": ["Talk-to", "Examine"],
"model_id": "npcs/scholar"
}
}And spawned in world with appropriate components:
commands.spawn((
Name::new("Scholar Vyasa"),
NPC {
npc_id: "npc_vyasa".to_string(),
dialogue_id: "dialogue_vyasa_intro".to_string(),
},
QuestTarget {
target_name: "npc_vyasa".to_string(),
},
// ... other components
));Validation Rules
- Step IDs must be unique within a quest
- next_step must reference existing step or be null
- At least one terminal step (finish: true or next_step: null)
- No circular references in step progression
- target_npc/target_object/target_creature must exist in respective data files
- Step type should match target field (dialogue→target_npc, kill→target_creature)
Migration from Old Schema
Old Format (Objective-based)
{
"quests": [
{
"id": "quest_1",
"objectives": [
{"type": "talk", "target": "npc_1", "count": 1},
{"type": "kill", "target": "goblin", "count": 5}
]
}
]
}New Format (Step-based)
{
"quest_1": {
"id": "quest_1",
"steps": {
"0": {
"description": "Talk to NPC",
"type": "dialogue",
"target_npc": "npc_1",
"next_step": 10
},
"10": {
"description": "Defeat 5 goblins",
"type": "kill",
"target_creature": "goblin",
"required_count": 5,
"finish": true
}
}
}
}Best Practices
- Use descriptive step descriptions - Players see these in the HUD
- Increment step IDs by 10 - Allows future insertions
- Always specify step type - Helps with debugging and validation
- Include quest category - Useful for filtering/organization
- Test quest flow - Ensure all steps are reachable and complete properly
- Document complex quests - Add comments in separate design docs