Storylet Studio

Prompts: the quest log

Prompts are an optional, lightweight quest log for your storyworld. A prompt is one line the player can see in a journal - "Find the bear's brass cogs", "Ring the Great Bell" - that opens when your story starts a task and closes when the task ends, however it ends.

If your storyworld does not need a journal, skip this page; nothing else depends on it.

The idea: marked, not derived

You do not describe conditions for when a quest is active. Instead, the outcome that starts the quest opens its prompt, and every outcome that ends the quest - completing it, failing it, making it irrelevant - closes the prompt, right there in that outcome. A quest with five different endings has five outcomes that each close it; no formula anywhere needs to list all five. This scales to large casts of quests without bookkeeping.

There is deliberately no more structure than that: no steps, no sub-objectives, no quest trees.

Variant text: changing the wording without changing the task

Sometimes the line should read differently as things progress - "Find the three cogs" becoming "One cog to go" - while the task itself is unchanged. For that, give the prompt variants: alternative wordings, each with a condition, edited under the prompt in the Prompts panel.

  • While the prompt is open, the first variant (top to bottom) whose condition currently holds supplies the text; if none match, the base title/description shows. Order them most-specific-first.
  • Variants change text only. They never affect when the prompt opens or closes - that stays entirely with your outcomes' flag changes.
  • Each variant has its own small ID (like one-left); a translated game uses it to look up the right string (see below).

Rule of thumb for variants vs separate prompts: if only the wording changes, use a variant. If the task changes - it completes differently, different outcomes end it - close the old prompt and open a new one; each stage is its own line.

Making a prompt bag

  1. Create (or pick) a flags property and tick Prompt bag (quest log) in its editor. Each flag on the property is now one prompt.
  2. Open prompts from outcomes by setting the flag (set_flags(@bag, +my_quest)); close them by clearing it (-my_quest). That is the entire mechanism - the same flag changes you already know.
  3. Write the journal text in the Prompts panel (Properties page): a title and an optional longer description per prompt. A prompt with no text yet falls back to its flag name, so you can wire the logic first and write the copy later.

Choose the bag's scope like you choose a quest's home

The bag can live at any scope, and the right choice is wherever the quest itself lives:

  • A deck-scoped bag keeps a self-contained story arc's journal with the deck that owns it - and two decks can reuse the same flag names without colliding.
  • A zone/site-scoped bag suits an area-local thread.
  • A world-scoped bag is for the big arc that spans everything.

One rule to know: an outcome's deck.bag change writes the bag of the deck the playing storylet belongs to. If outcomes across several decks must close the same prompt, that prompt is not deck-local - put its bag at zone or world scope.

The Prompts panel

The Prompts panel (Properties page) is the one place for everything journal-related. Per prompt it shows:

  • the journal title and description (edit them here);
  • Opened by / Closed by - every outcome that sets or clears the flag, clickable through to the storylet;
  • warnings: never opened (the line can never appear), never closed (once open it never goes away), no journal text (it will show its flag name).

Seeing it in play

Simulate shows a floating Journal button at the top-right of the map - collapsed it reads "Journal: N prompts"; opened it lists the currently open prompts, grouped by their owning deck or area, updating live as you play (with the active variant's ID shown as a small debug chip). It only appears at all when the storyworld has prompt bags. The standalone player has the same journal, minus the debug chips - so playtesters see the quest log a real player would. In a published game, the same journal is available to the host through session.prompts() (JavaScript), or GetOpenPrompts() in the Unreal and Unity plugins - your game renders it however it likes.

Coverage Testing watches the journal too: when your storyworld has prompt bags, the coverage report gains a Prompts tab showing, per journal line, how many simulated runs ever opened it, how many closed it again, and how often it reopened after a close. The Prompts panel's warnings tell you whether an opener or closer exists; the coverage tab tells you whether they actually fire in play - a prompt whose only closer sits on an unreachable storylet looks fine statically but shows up there as "never closed". See Coverage Testing.

A note on translated games

The journal text you write here is the authoring text - it is what Simulate, playtest builds, and an untranslated game show. A localised game does not use your strings directly: it looks up its own translations by the stable keys the engine reports with each open prompt - the flag name, plus the variant ID when a variant is active. Your authored text then serves as the fallback for anything not yet translated. In practice: pick flag names and variant IDs you are happy to keep (they end up in the game's string tables), and let the wording itself evolve freely.

Prompts add a small table to the published bundle. It is purely additive: older players and runtimes that don't know about it simply show no journal, and the story itself plays identically.