Introduction
plotknot is a minimal, extensible narrative scripting tool for game developers. It provides a clean, Markdown-like language for writing branching stories, dialogue trees, and interactive narratives — then compiles them to engine-ready data files.
Why plotknot?
Existing narrative tools (Yarn Spinner, Ink, Loreline) each make strong choices about syntax, runtime coupling, and extensibility. plotknot takes a different approach:
- Minimal core. The base language covers 80% of narrative scripting needs: sections, choices, variables, conditions, and game interop. No feature bloat.
- Extensible at runtime. Need character portraits? Variation modes? Custom functions? The Lua runtime provides
on_call,register_function, andon_line_typehooks for game integration. - Engine-agnostic. The compiler produces data, not code. The runtime is a thin library you drop into your engine. Today: Defold (Lua). Tomorrow: Godot, Unity, or anything else.
- Human-readable output. Compiled files are plain Lua tables you can read, diff, and debug.
How it works
.plotknot source → Compiler (Nim) → .lua data file → Runtime (Lua) → Your game
- You write narrative content in
.plotknotfiles - The compiler lexes, parses, validates, and generates output
- The runtime loads the data and drives the story at game time
- Your game code calls the runtime API to advance dialogue and respond to choices
Philosophy
- Data over code. Compiled output is a data description of your story, not executable logic. The runtime interprets it.
- The runtime is the extension point. The compiler produces data; the runtime provides hooks for custom functions, call handlers, and line types.
- No hidden state. Variables, visited sections, and story position are explicit and inspectable.
Feature overview
| Feature | Description |
|---|---|
| Sections | Organize narrative into named nodes with headings |
| Choices | Branching with optional conditions |
| Variables | Set and use variables with expressions |
| Conditions | if/else blocks for dynamic content |
| Game interop | Call game functions, receive results |
| Localization | Tag lines with localization keys |
| Extensibility | Runtime hooks: on_call, register_function, on_line_type |
| LSP | Language server for editor integration |
| CLI | Compile, validate, and watch commands |
Next steps
- Getting Started — install and compile your first story
- Language Guide — learn the syntax by example
- Runtime API — integrate with your game