AppleyAppley Docs
Docs/API Reference

Quest Systems

Build quest tracking with objectives, progress, and rewards.

30 min read Intermediate Updated 2026-07-01 v2.0 ~107 min to complete

Introduction

Quest systems give players goals and direction. This guide covers quest definitions, objective tracking, progress updates, completion, and rewards.

Guide 19 of 25

This is part of the Intermediate Guides collection. Category: Gameplay Systems. Estimated completion: 107 minutes. Difficulty: Intermediate.

Screenshot

Quest Systems
Quest Systems

Step-by-Step Guide

1

Define quest structure

Each quest has: ID, title, description, objectives (array), rewards, prerequisites, and state (inactive, active, completed, failed).

2

Create objective types

Support multiple objective types: collect items, kill enemies, reach location, talk to NPC. Each tracks progress differently.

3

Track progress

Update objective progress when relevant events fire. Use the event system: enemyKilled, itemCollected, locationReached.

4

Show quest UI

Display active quests in a quest log. Show objective progress (3/10 enemies defeated). Update in real-time.

5

Handle completion

When all objectives complete, mark quest done, give rewards (items, XP, gold), show completion notification.

6

Chain quests

Use prerequisites to chain quests. Quest B requires Quest A completed. Creates narrative progression and gates content.

FluxScript Example

Here is a complete FluxScript implementation for this guide:

Quest Systems — FluxScript
const QUESTS = {
  rescue_daughter: {
    title: "Rescue Borin Daughter",
    objectives: [
      { id: "reach_cave", type: "location", target: "goblin_cave" },
      { id: "kill_goblins", type: "kill", target: "goblin", count: 5 },
      { id: "find_daughter", type: "interact", target: "borin_daughter" }
    ],
    rewards: { gold: 100, xp: 500, items: [{ id: "steel_armor", count: 1 }] }
  }
}

questStates = {}

on start {
  for questId in QUESTS {
    questStates[questId] = { state: "inactive", progress: {} }
  }
}

func startQuest(questId) {
  questStates[questId].state = "active"
  for i = 0 to QUESTS[questId].objectives.length {
    obj = QUESTS[questId].objectives[i]
    questStates[questId].progress[obj.id] = 0
  }
  ui.toast("New Quest: " + QUESTS[questId].title)
  audio.play("quest_start")
}

on event("enemyKilled", data) {
  for questId in QUESTS {
    if questStates[questId].state != "active" continue
    for obj in QUESTS[questId].objectives {
      if obj.type == "kill" && obj.target == data.enemyType {
        questStates[questId].progress[obj.id] += 1
        checkObjective(questId, obj)
      }
    }
  }
}

func checkObjective(questId, obj) {
  progress = questStates[questId].progress[obj.id]
  target = obj.count || 1
  if progress >= target {
    ui.toast("Objective Complete: " + obj.text)
    checkQuestComplete(questId)
  }
}

func checkQuestComplete(questId) {
  allDone = true
  for obj in QUESTS[questId].objectives {
    target = obj.count || 1
    if questStates[questId].progress[obj.id] < target allDone = false
  }
  if allDone completeQuest(questId)
}

func completeQuest(questId) {
  questStates[questId].state = "completed"
  r = QUESTS[questId].rewards
  if r.gold player.gold += r.gold
  if r.xp player.addXP(r.xp)
  if r.items for item in r.items inventory.addItem(item.id, item.count)
  ui.show("questCompletePanel")
  audio.play("quest_complete")
}

Node Graph Example

Prefer visual programming? Here is the equivalent Node Graph:

Quest Systems — Node Graph
[On Start] --> [Init: quest states (all inactive)]

[Function: startQuest] --> [Set: active] --> [Init: progress]
   --> [Toast + Audio]

[On Event "enemyKilled"] --> [For Each Active Quest]
   --> [For Each Kill Objective] --> [Branch: target matches]
        --> [progress += 1] --> [checkObjective]

[Function: checkObjective] --> [Branch: progress >= target]
   +-- True --> [Toast] --> [checkQuestComplete]

[Function: completeQuest] --> [Set: completed]
   --> [Give: gold, XP, items] --> [Show: completion panel]

Optimization Tips

Keep your implementation fast and efficient with these optimization tips:

  • Use event-driven objective tracking. Instead of polling every frame, subscribe to events (enemyKilled, itemCollected).
  • Limit active quests to 5-10. More active quests clutter the quest log and overwhelm players.
  • Save quest states to cloud. Quest progress is critical — players expect to resume after closing the game.
  • Use prerequisites for quest chains. Gate content behind completed quests for narrative progression.

Common Mistakes

Polling for objective completion every frame

Use events instead. Polling 50 objectives per frame is wasteful.

No quest abandonment option

Let players abandon quests they cannot complete. Stuck quests frustrate players.