Skip to content

Tutorial Writing Text

johnjohto edited this page Jul 28, 2026 · 3 revisions

Tutorial: Writing Text

Write prose. The engine wraps. Every box in the engine — dialogue, battle messages, the narration band, Pokédex descriptions — renders through one text pipeline that word-wraps to the classic 18-column measure and pages automatically. You never hand-break lines to fit the screen.

{"cmd": "say", "text": "The old keeper looks up from the ledger and studies you for a long moment before speaking."}

That's one sentence, no line breaks — the box wraps it to 18 columns, shows two lines at a time, and pages with the ▼ prompt, exactly like the classics did.

Deliberate breaks

Break Meaning
\n force a line break here
blank line (\n\n) start a new page (the ▼ pause) — the natural way to page prose
\f page break, the classic escape (still works everywhere)
{"cmd": "say", "text": "I have three rules.\n\nNo running.\nNo shouting.\nNo shortcuts."}

The blank line ends the first page; the second page lists the rules on their own lines (two visible at a time).

Data tags

Drop live values into any text with {...} tags:

Tag Shows
{player} / {rival} the saved names
{var:name} an event variable (0 if never set)
{item:id} an item's display name — {item:town_map}TOWN MAP
{mon:slot} the nickname of party slot 1–6
{"cmd": "say", "text": "So, {player} — {mon:1} looks happy.\n\nBring {var:owed} coins next time."}

Tags are data only — there are no pacing or sound tags, on purpose: strings stay pure content, which is also why translators can never break your game. A misspelled tag won't fail silently: --validate errors naming the record and the tag, and the engine refuses to load the project until it's fixed.

Where it applies

  • say / notice / ask / show_text — the dialogue box: 18 columns, 2 lines per page.
  • Battle messages — same box, same measure.
  • narrate — the walk-through band wraps to the same 18 columns but shows at most 2 lines and never pages (the player is walking; there is no ▼). Keep narration short. If it wraps past two lines, the rest is cut — and --validate warns you before a player ever sees it.
  • Pokédex descriptions (desc in a species file) — 18 columns, 3 lines per page, and long prose now pages automatically: write the whole flavor text as one string and the dex screen deals it out.

The safety net

Three things can still go wrong in text, and all of them are loud at --validate time instead of silent on screen:

  • A single word wider than 18 characters can't wrap (words are never hyphenated). It draws clamped at the box border, and text.unbreakable_word warns naming the word.
  • A character with no glyph in your project's charmap draws nothing. lang.missing_glyph warns naming the exact characters — this now covers all your text, not just language packs.
  • A narrate longer than two wrapped lines truncates; text.narrate_overflow warns with the offending text.

Each warning is reviewable: if it's deliberate, suppress it with a reason in data/lint_suppressions.json and your project validates clean.

See it before you play it

Studio previews every text field live, with the game's own font: under each say-family command in the event editor, under the dex description field in the species editor, and under the story-text rows of the translation workspace (source and target side by side). The preview runs the exact engine pipeline — tags filled with sample names, pages dealt at 18 columns, a page count, and a red note the moment something would clamp, cut, or fail validation. It updates when you commit an edit (Enter or clicking away), so long texts never make typing sluggish.

Translations get it free

Language packs ride the same pipeline: a translated string re-wraps to the measure on its own, so translators write natural prose too — no mirroring the source's line breaks. See Language Packs.

Clone this wiki locally