← SableCraft Chronicler

Writing quests

A quest is a file. Who offers it, what it asks, how it is told, what it pays and what it changes are all data - and ZARP uses every piece of it, in readable JSON, if you would rather learn from a working example.

Where files go

YAML in a folder, or JSON in a datapack.

Drop a chapter and a quest into config/chronicler/chapters/ and config/chronicler/quests/ as YAML, or into any datapack at data/<pack>/chronicler/{chapter,quest}/<name>.json.

# config/chronicler/quests/things_in_the_dark.yml
name: Things in the Dark
description: They come out at night. Make it fewer of them.
chapter: prologue
requires: [first_steps]
objectives:
  - { type: kill, target: minecraft:zombie, count: 5 }
rewards:
  - { type: item, item: minecraft:iron_sword }
  - { type: money, amount: 25 }

Restart the server to apply content. Chapters and quests are a frozen registry, the same as vanilla's data-driven content, so /reload will not pick them up. /chronicler reload reloads messages only, and says so.

Givers

Given by someone, somewhere.

A right-click makes the offer, with Accept and Info buttons; a second click accepts. A hidden quest with a giver is found by walking up to it. An admin can make any block, or any Cast NPC, a giver by looking at it: /quest giver set <quest>.

giver: { type: position, at: [120, 64, -40], label: "the vault door" }
giver: { type: place, biome: "#minecraft:is_jungle" }
giver: { type: npc, name: "Dr Okafor", skin: Sablednah, near_spawn: [6, 0],
         greeting: "You look like you can hold a torch.",
         equipment: { head: minecraft:iron_helmet } }
Type Options What it is
position at · label
near_spawn · block · decor
A block. near_spawn places it relative to spawn on any seed, and block plus decor build it there once - a campfire with a camp around it.
place biome · structure · dimension · lot A kind of place, offered the moment a player is in one - no coordinate written down. lot is a CityWorld lot.
npc name · skin · entity · greeting
at · near_spawn · of
equipment · defy_gravity
A person, through Cast: a human with that account's skin, or entity for a creature. of lets one person give several quests.

Stages, choices and deadlines

Told in beats.

A quest can be told in stages: ordered beats, each with its own narrated text, objectives, and on_enter / on_complete effects. A quest with plain objectives is one stage.

stages:
  - text: Get a light. The dark is not empty.
    objectives: [ { type: collect, item: minecraft:torch, consume: false } ]
  - text: They found you. Hold until it is quiet.
    on_enter:
      - { type: title, title: "&cThey are here", subtitle: "&7Hold the line" }
      - { type: spawn, entity: minecraft:zombie, count: 2, radius: 6 }
    objectives: [ { type: kill, target: minecraft:zombie, count: 2 } ]
  - text: A stranger asks for your torch.
    choices:
      - { label: Give it, effects: [ { type: karma, delta: 5 } ], end: true }
      - { label: Keep it, effects: [ { type: karma, delta: -5 } ], end: true }

A stage with choices and no objectives is a decision. The options arrive as clickable buttons in chat and in the journal, each with its own text and effects, and either next: <stage>, end: true, or nothing to carry on to the following stage.

A stage with a deadline (seconds) counts down on the action bar, and when it runs out fires on_fail and falls back to a fail stage, or drops the quest.

Endings. ending: cure on a stage or a choice records an ending for the chapter. A chapter with replayable: true can be started over with /quest replay - endings stay, so players can go back for the others.

Refusals are story first. locked on a quest is the in-character line for a refusal, spoken by its NPC if there is one; what it really means follows in grey brackets, generated from the requirements - "finish The Camp; be Immune".

Objectives

Measured on real events.

Type Options What it measures
kill target · count · tag
drop · own_kill
An entity id, a #tag, any, or a ZombieMod genus - or a list, so a file names the genus first and a vanilla stand-in second. tag counts anything a spawn effect tagged; drop makes counted kills drop a quest item. A quest-spawned mob that dies to something else still counts, unless own_kill: true.
collect item · tag · quest_item
count · consume
Items in your pack. consume: false only requires carrying them.
deliver quest_item · count · to · radius The hand-over: complete by clicking the giver of quest to while holding the items, or standing within radius. The items go then.
visit x · z · y · radius
dimension · label
Reach a spot. label is how the text names it.
place biome · structure
dimension · lot · any
Be in a kind of place. any takes alternatives, so a CityWorld lot can have a vanilla fallback.
ritual block · pattern · item · consume A multiblock: right-click block while every pattern entry (offset and block) is in place, holding item. A wrong pattern says which block is missing where.
wait seconds Let time pass from entering the beat - "come back later".
flag name · value Wait for a world flag.
reputation standing · at_least Wait on a Standards standing.

Rewards and effects

What it pays, and what it does.

Rewards pay out on completion; effects run on entering or completing a stage, or on a choice. Effects use the whole reward vocabulary too. Anything that needs a companion mod says so plainly when it is not there.

Type Through What it does
item vanilla An item, or a quest_item.
xp vanilla Experience.
command vanilla Run a command with gamemaster permission. Substitutes {player}, {uuid}, {quest}, {x}, {y} and {z}.
money Standards Through its economy.
reputation Standards Move a standing by a delta.
karma · class_xp · levels · skill_points LegendQuest Through its own API.
flag Chronicler Set a world flag, or the player's own with player: true.
title · message effect A title card, or a line in chat - action_bar: true for the bar.
spawn effect An entity or a ZombieMod genus, with name, tag, health and equipment. Give both a genus and an entity and the entity stands in when ZombieMod is absent - one file, two servers.
npc_say · npc_remove effect Make a quest's NPC speak, or leave.
ending effect Record an ending for the chapter.

Availability and consequences

Offered to the right people, and remembered.

Beyond requires, a quest can carry availability conditions - so a Mechanic and a Paramedic are offered different work, and unmet lines are told to the player rather than the quest silently not appearing.

availability:
  karma_min: 20                        # LegendQuest karma (also karma_max, level_min, level_max)
  race: [immune]                       # LegendQuest ids, any of the list
  class: [doc, combat_medic]
  flags: { bridge_repaired: true }     # world flags a questline set
  player_flags: { chose_mercy: true }  # this player's own choices
  reputation: { survivors: 10 }        # a Standards standing

World flags are named facts a quest sets and anything can read. ZombieMod genus files can gate spawning on one, so finishing a questline changes what spawns:

{ "type": "chronicler:flag", "flag": "hospital_cleared", "value": false }

Party quests. scope: party on a chapter, or overridden on a quest, pools progress across the party, scales targets to its size, and pays everyone. Membership comes through Standards' groups seam.

Bounties. A repeatable quest with a cooldown in seconds can be done again and again, but not at once.

Progress. /quests and the journal show a percentage, moved only by quests that count - counts: true|false, and unsaid means "main chapter and not repeatable", so bounties and side lines never hold anyone short of 100%.

Quest items

Named, marked, and not renameable into.

Quest items live in their own registry and are marked invisibly in the item's data, so renaming an ordinary item in an anvil does not make one. They are not eaten or drunk unless the entry says usable: true.

# data/<pack>/chronicler/item/origin_sample.json, or config/chronicler/items/
{ item: minecraft:nether_star, name: "&5The Origin Sample", lore: [...], glint: true, max_stack: 1 }

# reward one, or drop one from a loot table
{ type: item, quest_item: zarp:origin_sample }
{ "function": "chronicler:quest_item", "id": "zarp:ember_heart" }