The pack
quests
function quests(): Pack<{ quests: typeof api }>
Install the quests API (game.quests): the quest log and its step rules.
Helpers
createQuestLog
const createQuestLog = (quests: readonly QuestDef[], o?: QuestLogOptions): QuestLog=> …
A quest log over a set of quests.
STEP_RULES
const STEP_RULES: Readonly<Record<string, StepRule>>
The built-in step kinds: talk to, kill, fetch (hold), reach, deliver to (talk, handing the item over).
Classes
QuestLog
class QuestLog
A quest log over a fixed set of quests.
readonly quests: readonly QuestDef[]— The quests, in the order given.readonly acts: number— How many acts there are.state: QuestState— The state.constructor(quests: readonly QuestDef[], o: QuestLogOptions = {})quest(id: string): QuestDef | undefined— A quest by id.drain(): QuestEvent[]— Every event since the last call.stepDone(q: QuestDef, i: number): boolean— Is one step done on its own terms (ignoring order).steps(q: QuestDef): boolean[]— Which steps are done, in order: a step counts only once every step before it is done. A finished quest is all done.current(q: QuestDef): number— The first step not yet done, or -1.complete(q: QuestDef): boolean— Every step is done (a quest with no steps is done at once).isActive(id: string): boolean— Accepted and not finished.isDone(id: string): boolean— Finished.act(): number— The act the game is in: 1, and one more for every act whose main quests are all done (an act with none ends nothing).available(q: QuestDef): boolean— Can this quest be offered now: not taken, and its act reached.offers(giverId: string): QuestDef[]— Quests a giver could offer now.ready(giverId: string): QuestDef[]— A giver's active quests whose steps are all done: ready to turn in.waiting(giverId: string): QuestDef[]— A giver's active quests still being worked on.activeQuests(): QuestDef[]— The active quests, as definitions.doneQuests(): QuestDef[]— The finished quests, as definitions.accept(q: QuestDef): boolean— Accept a quest: counters start from now. False when it is already taken or done.turnIn(q: QuestDef): { gold: number; itemId: string | null } | null— Turn a quest in: it moves to done and the reward is reported (the game pays it). Null when it is not active.count(key: string, id: string, n = 1): void— Count something (a kill):count('kill', 'wolf').flag(key: string, id: string): void— Set a flag (a region reached):flag('reach', 'stonereach').mark(q: QuestDef, step: number): void— Mark one step done by hand (a scripted moment); the steps before it stay done from then on.refresh(): void— Re-readheldsteps (after the bag changed).event(key: string, id: string): { quest: string; step: number; itemId: string | null }[]— An event named a target (talkwith an npc id): every active quest whose current step is amarkstep of that event and target is marked, handing its item over where the rule says so, and again while that unlocks the next. Returns the steps it completed.talk(npcId: string): { quest: string; step: number; itemId: string | null }[]— Talking to an npc:event('talk', npcId).snapshot(): QuestState— The state, as plain data.restore(data: unknown): boolean— Read saved state defensively: unknown quests are dropped, a quest is never both active and done. False when it is not a quest state.
Types
QuestDef
interface QuestDef
A quest.
id: string— Unique among the quests.title?: string— Its title.act?: number— The act it belongs to: it is offered from that act on. Default 1.main?: boolean— Whether it is a main quest: an act ends when all its main quests are done.giverId?: string— Who offers it and takes it back.steps: readonly QuestStepDef[]— The steps, in order: a step counts only once every step before it is done.rewardGold?: number— Gold paid on completion.rewardItemId?: string | null— An item given on completion.
QuestEvent
type QuestEvent = /** A quest was accepted. */ | { type: 'accepted'; quest: string } /** A step was completed. */ | { type: 'step'; quest: string; step: number } /** An item was handed over for a step. */ | { type: 'handed'; quest: string; step: number; itemId: string } /** Every step is done: the quest can be turned in. */ | { type: 'ready'; quest: string } /** A quest was turned in. */ | { type: 'done'; quest: string; gold: number; itemId: string | null } /** A new act began. */ | { type: 'act'; act: number }
What the log reports.
QuestHost
interface QuestHost
What a log asks of its game.
held?(itemId: string): number— How many of an item are held, forheldsteps. Default none.take?(itemId: string): boolean— Take an item for ahandsstep; false when it is not held. Default: whateverheldsays, nothing taken.deliverItem?(quest: QuestDef, step: number): string | null— The item ahandsstep hands over when the step names none; null for a plain talk.
QuestLogOptions
interface QuestLogOptions
What a log is made with.
rules?: Readonly<Record<string, StepRule>>— Step rules, overSTEP_RULES.acts?: number— How many acts there are. Default the highest act any quest names, at least 1.host?: QuestHost— The game.
QuestState
interface QuestState
The log's state, as plain data.
active: string[]— Accepted quest ids, in order.done: string[]— Finished quest ids, in order.counts: Record<string, Record<string, number>>— Counters by name, then target id (kills).flags: Record<string, Record<string, boolean>>— Flags by name, then target id (regions reached).marks: Record<string, boolean>— Marked steps, keyedquestId#step: done for good, whatever their rule (a step is marked when a later one is).base: Record<string, number>— Counter values when a quest was accepted, keyedquestId#step.
QuestStepDef
interface QuestStepDef
One step of a quest.
kind: string— What counts as doing it: a key of the log's step rules (built in: talk, kill, fetch, reach, deliver).targetId: string— What the step names (an npc, a monster, an item, a region); '' for a step that names nothing, which is done at once unless its rule says otherwise.count?: number— How many times (kills, items held). Default 1.text?: string— What the player is told.itemId?: string | null— For a step that hands something over: the item. Default the host'sdeliverItem, else the nearest earlierheldstep's target.
StepRule
interface StepRule
How a step kind is judged:
-
count: a counter (key, default the kind) for the target reaches the step's count, counted from acceptance; -
flag: a flag (key) for the target has been set; -
held: the host holds the step's count of the target (or the step was marked); -
mark: an event (key) named the target while this was the current step;handsmakes it take an item. -
by: 'count' | 'flag' | 'held' | 'mark'— How it is judged. -
key?: string— The counter, flag or event name. Default the step kind. -
hands?: boolean— Amarkstep that hands the item over: it is done only when the host takes it. -
lifetime?: boolean— Acountstep counts every kill ever, not only those after acceptance. Default false.


