Phaser AE

Quests

Free packv3.0.0-0Logic

A quest log that tracks quests of ordered steps from the offer to the reward. What counts as doing a step is a rule in a registry, so a new kind of step is data, and everything that changes comes back as an event for your game to show.

This is a Free pack. Every phaser.io account can use it in their games.

Released October 19, 2026

Quests: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

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-read held steps (after the bag changed).
  • event(key: string, id: string): { quest: string; step: number; itemId: string | null }[] — An event named a target (talk with an npc id): every active quest whose current step is a mark step 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, for held steps. Default none.
  • take?(itemId: string): boolean — Take an item for a hands step; false when it is not held. Default: whatever held says, nothing taken.
  • deliverItem?(quest: QuestDef, step: number): string | null — The item a hands step 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, over STEP_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, keyed questId#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, keyed questId#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's deliverItem, else the nearest earlier held step'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; hands makes 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 — A mark step that hands the item over: it is done only when the host takes it.

  • lifetime?: boolean — A count step counts every kill ever, not only those after acceptance. Default false.