Files

5.4 KiB

Markup Guidelines

This file documents author-facing Ink tag conventions. The active parser normalizes tags into structured StoryTag objects before they reach the UI.

Implemented Tag Forms

Use bracket tags for titles, filenames, and longer text:

#chapter[Eibenreith]
#image[statue.png](square)
#music[Kaiserpunk Waltz.mp3](crossfade, loop, lead=8)
#sfx[church-bells.ogg](max=8, fade)
#score[You reached an ending.]
#achievement[First Steps]
#alert[Try examining the room.]

Use colon tags for short identifiers, categories, and choice keys:

#action:movement
#key:l
#sort:last
#gated:noble

Bare flags are accepted as tags with no value:

#optional

Right-Page Glossary Notes

Glossary notes are story tags scoped to the paragraph/block they belong to. They affect only the right-page story rendering, never choice text or command history.

The conductor points toward Eibenreith.
#gloss[Eibenreith](A fictional alpine town in the Kaiserpunk setting.)

The bracket value is the visible term to find. The parenthesized value is the note shown on hover/focus. The renderer marks every matching instance of the term in the same right-page block. The tag is not displayed and is not sent to TTS. Avoid raw Ink control characters in the explanation; |, {, and } must be escaped in Ink as \|, \{, and \} if they are needed literally.

TTS Reading Instructions

TTS instruction tags are story tags scoped to the paragraph/block they belong to. They are not rendered, and they are only sent to TTS providers that support per-request reading instructions. Currently this means OpenAI with gpt-4o-mini-tts.

„Ich habe nichts gesehen“, sagt Viktor.
#tts[Read softly, with controlled unease.]

The default form omits a provider and is the preferred authoring style. Providers that support instructions may consume it; providers that do not support instructions silently ignore it. Provider-specific instructions are only needed when two providers should receive different direction, or when an instruction must be hidden from all but one provider. They use the tag parameter position:

„Ich habe nichts gesehen“, sagt Viktor.
#tts[openai](Read softly, with controlled unease.)

The shorthand #tts-openai[...] is also accepted. #tts(...) is equivalent to providerless #tts[...] if parentheses read better in a local context. tts-1 and tts-1-hd ignore these instructions because the OpenAI speech endpoint only supports the instructions request parameter for gpt-4o-mini-tts.

Keep instructions short and describe performance rather than content. OpenAI's TTS guide recommends using gpt-4o-mini-tts when you need controllable delivery; useful instruction targets include tone, emotional range, intonation, speaking speed, accent, impressions, and whispering. Good examples:

#tts[Speak with restrained concern and a slower pace.]
#tts[Whisper the line with controlled urgency.]
#tts-openai[Use a dry, formal tone; avoid melodrama.]

Avoid repeating the full dialogue in the instruction. Put the words to be spoken in the story text, and use #tts only to describe how the provider should read that block.

Choice Metadata

Choice tags are placed on the Ink choice they belong to:

* [__Schaue__: Aus dem Fenster.]
  #action:orientation
  #key:l

Implemented choice metadata:

  • #key:x: reserves keyboard key X for the choice.
  • #letter[x]: older equivalent for reserving keyboard key X.
  • #action:group or #action[group]: assigns the choice to an invisible action group.

The current UI renders all choices in one visible list. Choices are first grouped by #action in the order each new action group appears in the authored choice list. Choices inside each group are randomized. Choices without #action form one final unlabelled group shown after all tagged groups. Explicit keys are assigned before automatic keys; choices without explicit keys receive 1 through 0, then A through Z in final visible order while skipping explicit keys. #optional choices are displayed italic. Grouping columns, #gated[...], and #sort[...] are documented authoring conventions or future metadata, not fully implemented UI behavior yet.

Popup And End-State Tags

These tags may appear as Ink global tags, paragraph tags, or empty tag-only lines. They are dispatched through the same tag channel as media tags.

#score[You reached the quiet ending.]
#error[The story ended unexpectedly.]
#achievement[First Steps]
#alert[Try examining objects before using them.]
  • #score[...]: intended ending. When the turn reaches inputMode: end, the UI shows a localized ending popup with the tag value as the optional message.
  • #error[...]: unrecoverable ending. The UI shows a localized error popup with the tag value as the optional message. The Ink engine emits this automatically if Ink runs out of content without an explicit #score[...] or #error[...].
  • #achievement[...]: queued localized achievement popup while the game continues.
  • #alert[...]: queued localized player hint/tutorial popup while the game continues.

Existing Media And Structure Tags

#chapter[Title]
#section
#textblock
#image[filename.png](landscape)
#image[filename.png](portrait pause=2)
#image[filename.png](square lead=1.5)
#music[track.mp3](crossfade, loop, lead=4)
#sfx[file.ogg](max=8 fade fade-duration=2)

Asset filenames resolve relative to the configured image, music, and sound folders.