Extensibility

Plotknot has a fixed language and a fixed compiler. All customization happens at runtime through the Lua runtime library.

Why no compiler plugins?

The compiler's job is: parse → validate → emit data. The plotknot language is defined by its grammar. New syntax requires a compiler change — the compiler is small enough (~1500 lines of Nim) to fork if you need custom syntax.

This is the same model used by Yarn Spinner and Loreline: fixed language, extensible runtime.

Runtime extension points

Game function calls (on_call)

Handle call statements in your game code:

story:on_call("play_sound", function(name)
  audio.play(name)
end)

story:on_call("calculate_damage", function(attack, defense)
  return math.max(1, attack - defense)
end)

When the story encounters call play_sound("explosion"), the runtime invokes your handler. If the call has -> result, the return value is stored in a variable.

Custom functions (register_function)

Add functions usable in expressions and conditions:

story:register_function("npc_mood", function(name)
  return game_state.npcs[name].mood
end)

Then in plotknot scripts:

if npc_mood("blacksmith") == "friendly":
  "Good to see you again!"

set best_price = min(price, npc_mood("merchant"))

Custom line types (on_line_type)

Handle custom line types in the compiled output:

story:on_line_type("flashback", function(line, story)
  ui.show_flashback(line.scene)
  return { { type = "text", text = "A memory surfaces..." } }
end)

story:on_line_type("shake", function(line, story)
  camera.shake(line.intensity or 1)
end)

The handler receives the full line table and the story instance. It may return an array of display items to add to the output. If the handler raises an error, the runtime catches it and produces a warning.

Custom line types don't require compiler changes. They appear in the compiled output as {type = "your_type", ...} tables. You can produce them by post-processing the compiler's Lua output or writing a tool that generates plotknot-compatible data.

Built-in functions

The runtime provides these functions automatically (no registration needed):

Category Functions
Math floor, ceil, round, abs, min, max, clamp, pow
Random random, chance, random_float, dice, random_range
String string_upper, string_lower, string_contains, string_length, string_trim
Type int, float, string, bool
Story visited, visited_count

Compiled output format

The compiler produces a Lua table with start, variables, and sections. Each section has title, metadata, and lines. Line types include: text, choice, set, call, if, goto, variation, stop. Unknown types dispatch to on_line_type handlers.

See Runtime API for the full line type reference.