Objectives
Every dialogue page can declare an Objectives list — the strings it
contains drive the live pass/fail goal display shown in the HUD and the Quest
Journal. Objectives are purely for display: they show players what
to do and how close they are to doing it, but they do not gate page navigation.
Overview
Objectives is an optional JSON array on each Page. Each
entry is either a requirement string (same format as the
Requirements list) or a plain-text
text: entry. When the list is
non-empty, the Quest Goal HUD and Journal detail panel
render each entry as its own line with a live pass/fail icon and, where
applicable, a progress counter.
// Rendered HUD / journal output
✓ Kill zombie: 5/5
· Break oak_log: 2/10
· Have iron_sword x1
The pass indicator is ✓ (green checkmark) when the requirement
passes for the player and · (grey dot) when it does not.
Requirements that carry a tracked progress count (kills, breaks, places, talk,
travel, fish, crafts, harvest, named trackers) show
current/required after the label. Requirements with no natural counter
(e.g. item:, questCompleted:) show only the label.
Objectives are display only — they do not
block page navigation or response selection. If you also want to gate the
page on the same conditions, copy the strings into the page's
Requirements list or the relevant response's
Requirements.
Which Page Is Shown
The HUD and journal always show objectives for the player's
current page, which is determined by the standard page
resolution rules: the engine walks the quest's Pages list in order
and picks the first page whose Requirements all pass for that
player. That page's Objectives are what appear on screen.
As the player completes work and their requirement state changes, page
resolution advances automatically and the displayed objectives switch to the
next page — no additional wiring is needed. Structuring a quest as a
chain of pages each with their own Objectives is the idiomatic way
to build a multi-step goal.
Objectives defaults to an empty list if the JSON field is
missing. Pages without objectives simply render nothing in the HUD goal
area for that entry.
Label Override (::)
Raw IDs are rarely player-friendly — item:*Ore_Copper*:10
would render as "Have *Ore_Copper* x10" by default. Append a
::label suffix to replace the target identifier with any text you
want, while keeping the surrounding wording and progress counter intact:
"Objectives": [
"item:*Ore_Copper*:10::Copper Ore",
"track:goblin_kills:10::Goblin (any type)",
"cooldown:daily_reward:86400::Daily stipend ready"
]
The :: separator is parsed only on objective strings — not on
ordinary page or response requirements. The label text supports icon tags
(e.g. {icon:Ore_Copper}) and
TextFormatter variables, so you can mix
coloured text, icons, and dynamic values into the displayed label.
Icon Override (::icon:)
Every objective row leads with a 16×16 bullet icon. When you don't supply
one, the HUD and journal pick a sensible default based on the requirement type
— a sword for kill, a pickaxe for break, a
sickle for harvest, leather gloves for place, a
hammer for craft, the HyFishing rod for catchfish*,
the HyFishing fish bag for releasefish, and so on. For
item:/questitem: the concrete item ID is used directly
(wildcards fall back to a backpack). For track: the tracker's own
type drives the default.
Append ::icon:incompleteId or ::icon:incompleteId|completeId
to override the default:
- One value sets the icon shown while the objective is not yet satisfied. The completed state falls back to the usual checkmark.
-
Two values (separated by
|) swap both icons: the first is the incomplete-state icon, the second replaces the checkmark when the objective passes.
"Objectives": [
"track:goblin_kills:10::icon:Weapon_Sword_Bone::Goblin hunt",
"item:Ore_Copper:20::icon:Ore_Copper|Ingredient_Bar_Copper::Smelting prep"
]
::icon: and ::label segments may appear in any order
and are independent — either, both, or neither can be present.
Plain Text Objectives (text:)
An objective string that begins with text: is rendered as a plain
informational line — no pass/fail icon, no progress counter, no
evaluation. Everything after the text: prefix is passed through
the TextFormatter and drawn directly as the objective row. Use this to add
flavour, hints, countdown timers, or context that doesn't correspond to a
single requirement.
"Objectives": [
"text:Meet the courier at the north gate before sundown.",
"text:Time remaining: {timeleft:courier_timer}::icon:Tool_Map",
"track:courier_deliveries:1::Deliver the package"
]
Supported features
-
TextFormatter variables — anything documented in
text-variables.mdworks here, including player vars ({playerName}), tracker counts ({track:id}), timed values ({timeleft:id},{cooldown:id}), and colour/style tags. -
Icon tags —
{icon:ItemId}renders the matching in-game item icon inline with the text. -
Multi-line text — in the HUD, a single
text:entry can span multiple lines by embedding\nor a real newline. Each line is rendered as its own row. -
Leading icon — append
::icon:ItemIdto draw a 16×16 ItemIcon bullet in front of the text.text:entries never "complete", so any second ID after|is ignored and there is no default — without::icon:the line renders flush-left with no bullet, unchanged from the pre-existing layout. -
Timer tick — when a
text:objective contains{timeleft:}or{cooldown:}, the HUD automatically re-renders on every second so the displayed time updates live.
Freely mix text: entries with requirement-based objectives
in the same list. A common pattern is to put a one-line description at
the top followed by the tracked requirements beneath it — the text
line provides narrative context and the requirement lines show progress.
Because text: entries are not requirements, they are never
evaluated for pass/fail and they are ignored by the quest engine when
deciding which page is active. They are a pure display device.
Contextual Requirements
A small number of requirements only make sense during an active NPC
interaction — for example npcname:, which tests which NPC
opened the dialogue. The HUD and journal do not have an active NPC context, so
contextual requirements are skipped when used as objectives
and always render as unchecked.
This keeps them from misbehaving in the goal display, but it also means
contextual requirements are effectively useless as objectives. Use them only
on Requirements and Responses.
Full JSON Example
A single page that combines a narrative text: hint, a labelled
tracker objective, and an item check — plus the matching page
Requirements that actually gate the page:
{
"Id": "lumber_run_active",
"Requirements": [
"questStarted:lumber_run",
"notTag:lumber_run_complete"
],
"Objectives": [
"text:The foreman wants oak logs and a sturdy axe.",
"track:oak_broken:10::Oak logs chopped",
"item:iron_axe:1::Iron Axe in inventory"
],
"Dialog": "Come back when you have the wood and the axe."
}
See Quest Patterns for more complete examples
combining Objectives with trackers, timed quests, daily
cooldowns, and multi-step ritual flows.