Gameplay — Quests
QuestManager handles multi-phase quests with typed objectives. Quests are defined as data, registered at game startup, and tracked through phases as the player completes objectives.
Include
<script src="/js/dn/gameplay/questState.js"></script>
Quest Definition
const QUESTS = {
goblin_bounty: {
id: 'goblin_bounty',
title: 'Goblin Problem',
phases: [
{
description: 'Kill 3 goblins threatening the village.',
objectives: [
{
type: 'kill',
targetId: 'goblin', // matches entity tags
count: 3,
label: 'Goblins killed',
}
]
}
],
rewards: {
gold: 50,
items: [{ itemId: 'iron_bar', count: 2 }],
xp: 100,
}
}
};
API
const quests = new QuestManager(QUESTS);
// Register and start a quest
quests.startQuest('goblin_bounty');
// Report a kill — automatically advances kill objectives
quests.reportKill('goblin');
// Check quest status
quests.getStatus('goblin_bounty'); // 'available' | 'active' | 'complete' | 'turned_in'
// Check phase progress
const q = quests.getQuest('goblin_bounty');
q.currentPhase; // 0-based index
q.phases[0].objectives[0].current; // kill count so far
q.phases[0].objectives[0].count; // kill count target
// Turn in (call from dialogue side effect or directly)
quests.turnIn('goblin_bounty'); // grants rewards, sets status to 'turned_in'
advancePhase Behavior
advancePhase() increments currentPhase and:
- If advancing to the last phase: sets
status = 'complete'— the quest is ready to turn in. - If advancing an earlier phase: just increments
currentPhase, status stays'active'.
This means the final objective must be on the last phase. If you add a trailing “return to NPC” phase after a kill phase, the kill completion will advance to the return phase (status stays 'active') — the player won’t be able to turn in until they interact with the NPC a second time.
Recommended pattern: Collapse kill-and-return into a single phase with the kill objective. The kill meeting the count auto-advances the last phase to 'complete', which unlocks questStatus: 'complete' dialogue conditions immediately.
// ✅ One phase — kill count completes it, quest becomes 'complete' instantly
phases: [
{
description: 'Kill 3 goblins.',
objectives: [{ type: 'kill', targetId: 'goblin', count: 3, label: 'Goblins killed' }]
}
]
// ❌ Two phases — kill advances to phase 1 (status stays 'active'),
// player must return and interact to turn in
phases: [
{
description: 'Kill 3 goblins.',
objectives: [{ type: 'kill', targetId: 'goblin', count: 3, label: 'Goblins killed' }]
},
{
description: 'Return to the Elder.',
objectives: [{ type: 'interact', targetId: 'bjorn' }] // creates the off-by-one
}
]
Multi-Phase Quests
For quests that genuinely need multiple phases (e.g., gather → craft → deliver), use them:
phases: [
{
description: 'Gather 5 iron ore.',
objectives: [{ type: 'gather', itemId: 'iron_ore', count: 5, label: 'Iron ore gathered' }]
},
{
description: 'Smelt 3 iron bars.',
objectives: [{ type: 'gather', itemId: 'iron_bar', count: 3, label: 'Iron bars smelted' }]
},
{
description: 'Deliver the bars to the Blacksmith.',
objectives: [] // last phase — completing this phase triggers 'complete'
}
]
Phase 0 auto-advances when iron_ore count reaches 5 (via reportGather() or inventory tracking). Phase 2 (last) gets triggered by the interaction with the Blacksmith NPC — which calls quests.advancePhase('mining_quest') directly.
Mission Tracker HUD
The gameplay framework includes a MissionTrackerModule that renders active + completable quests top-left on screen. It automatically interpolates kill counts:
[!] Goblin Problem
Goblins killed: 2/3
When a quest is completable, it shows with a ✓ indicator and the NPC name to return to.
Quest Conditions in Dialogue
Use quest status as a dialogue condition to gate choices:
condition: { type: 'questStatus', questId: 'goblin_bounty', status: 'complete' }
Valid status values: 'available' (registered, not started), 'active' (in progress), 'complete' (objectives met, not yet turned in), 'turned_in' (rewarded and closed).