Skip to content

Supported Ink Syntax

This page documents what the current Ink converter supports when authoring stories for NovyJump.

NovyJump uses standard Ink syntax plus a set of multimedia extensions via Ink’s tag (#) syntax.


Standard Ink Features

Text and Dialogue

Narration and speaker dialogue:

You walk into the room.
ALICE: Hello there.

Speaker detection: a line starting with ALL_CAPS_NAME: (letters, digits, underscores, spaces) is treated as a character speaking. Anything else is narration.

Glue (<>) suppresses line breaks:

The answer is <>
42.

Knots and Stitches

=== start ===
-> chapter_one
=== chapter_one ===
Opening narration.
= scene_two
A new scene begins.
  • === knot_name === — a knot (major section)
  • = stitch_name — a stitch (sub-section within a knot)
  • -> target — a divert to a knot or stitch

Choices

* [Be friendly]
ALICE: Thanks for being kind!
-> next_scene
+ [Ask again]
ALICE: Still here.
  • * — non-sticky choice (removed after selection)
  • + — sticky choice (remains available)
  • Nested choices: **, *** (depth tracking)
  • (label) — optional label on a choice for divert targeting
  • [bracketed text] — choice label shown to the player
  • Guarded choices: * {condition} [text]

Diverts

-> knot_name
-> knot_name.stitch_name
-> END
-> DONE
  • -> END / -> DONE — terminal (end of story or chapter)
  • Inline diverts at end of choice body are resolved to direct connections

Tunnels

-> side_quest ->
->->
  • -> target -> — tunnel call (enter a section and return)
  • ->-> — tunnel return (return from current tunnel)

Gathers

* Option A
* Option B
- You made a choice.
-> END

- gathers collect flow from all branches and continue.

Gather labels: - (label_name) — creates a named gather point.

Variables

VAR score = 0
CONST MAX_SCORE = 100
LIST moods = (happy), sad, angry
~ score = score + 10
~ temp greeting = "Hello"
  • VAR — global variable declaration
  • CONST — immutable constant
  • LIST — enumeration with active/inactive items. Active items are listed in parentheses.
  • ~ — assignment (supports =, +=, -=, *=, /=, %=)
  • ~ temp — temporary variable (scoped to current flow)

Expressions

Full expression support in conditions, assignments, and inline conditionals:

Operator typeOperators
Arithmetic+, -, *, /, %
Comparison==, !=, <, >, <=, >=
Booleanand, or, not
LISThas, hasnt
Grouping()

Conditionals

Multiline:

{ score >= 10:
Great score!
- else:
Keep trying.
}

With elif:

{ score >= 10:
Great score!
- score >= 5:
Medium score.
- else:
Low score.
}

Inline:

You feel {score > 5: confident|nervous}.

Tags

# chapter_one
# unlocked_ending

Tags appear in JumpTree metadata. NovyJump multimedia directives use the tag syntax (see below).

Comments

// This is a comment

NovyJump Multimedia Directives

NovyJump extends Ink with multimedia directives using tag syntax. These produce NovyScript blocks in the output JumpTree.

Background image

bg_tavern.png

Sets the background image asset.

Image (standalone sprite)

overlay_frame.png

Declares an image asset without placing it on screen. Used to preload or reference assets.

Scene

# scene: tavern_night

Sets the current scene by name (must reference a scene defined via # background: or configured in assets).

Clear scene

# clear_scene

Removes all scene elements from the screen.

Music

ambient.mp3
# music: ambient.mp3, channel=bgm, fade=2, loop=true
ParamDefaultDescription
channelbgmAudio channel name
looptrueLoop the track
fadeFade-in duration in seconds
volumeVolume (0.0–1.0)

Use a supported audio format (.mp3, .opus, .wav, .flac, …). Avoid .ogg — the converter currently treats it as video. See Media and Resolution Specs.

Sound effects

footstep.wav
# sfx: footstep.wav, loop=false

Defaults to channel=sfx, loop=false.

Voice

line_001.mp3

Defaults to channel=voice, loop=false.

Stop audio

# stop_audio: bgm
# stop_audio: bgm, fade=1

Stops playback on the named channel, with optional fade-out.

Character sprite

# sprite: alice, alice_happy.png, happy, x=540, y=960
# sprite: alice, alice_sad.png, sad, x=540, y=960, xscale=0.8
Position argDescription
1Character id
2Asset filename
3+Tags (for sprite selection)
Named paramDescription
xHorizontal position in pixels (default: 540, center)
yVertical position in pixels (default: 960, center)
xscaleHorizontal scale (default: 1)
yscaleVertical scale (default: 1)

Clear character

# clear_character

Removes all character sprites from the screen.

Display sprite (standalone)

frame.png
# display_sprite: frame.png, x=100, y=200, xscale=0.5

Displays an image on screen without binding it to a character. Useful for overlays, UI frames, etc.

Tween (animation)

# tween: character/alice, opacity, 0, 1, 0.5, easeOutCubic
# tween: scene/background, opacity, 1, 0, 1, linear
PositionDescription
1Target path: character/<id> or scene/<name>
2Property to animate: opacity, xPos, yPos, xScale, yScale
3Start value
4End value
5Duration in seconds
6Easing type

Supported easing types: linear, easeInCubic, easeOutCubic, easeInElastic, easeOutElastic, easeInOutElastic, easeInBack, easeOutBack, easeInOutBack.

4-argument form omits start value (uses current value):

# tween: character/alice, opacity, 1, 0.5, linear

With delay:

# tween: character/alice, opacity, 0, 1, 0.5, easeOutCubic, delay=0.2

Style

# style: color=#ef7855, fontSize=24

Applies a style to the next dialogue node. Multiple # style: directives are merged.

Supported style properties: color, opacity, fontSize, font, textAlign, backgroundColor, backgroundOpacity, wordWrap, borderColor, borderRadius, borderWidth, padding, margin, width, height.


What’s NOT Supported

The following standard Ink features are not yet converted:

  • Sequences, cycles, and shuffles ({&...}, {!...}, {~...})
  • Named functions (== function_name ==)
  • External functions (EXTERNAL)
  • Multiple files / INCLUDE (multi-file projects are concatenated before parsing)
  • Threads (<- thread_name)
  • Advanced label addressing (beyond knot.stitch)
  • LIST helper functions — LIST_COUNT, LIST_MIN, LIST_MAX, LIST_RANDOM, LIST_VALUE, LIST_INVERT are rejected with an error.

Minimal Example

bg_city.png
VAR trust = 0
=== start ===
# music: city_ambience.mp3, channel=bgm, loop=true
# sprite: alex, alex_neutral.png, neutral, x=540, y=960
ALEX: Welcome to the city.
* Be friendly
~ trust = trust + 1
# sprite: alex, alex_happy.png, happy, x=540, y=960
ALEX: Good to meet you!
-> ending
* Stay quiet
-> ending
=== ending ===
{ trust > 0:
ALEX: I think we'll get along.
- else:
ALEX: Maybe next time.
}
-> END