Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

char

Shows, changes, moves, or hides a character.

{ "type": "char", "name": "hana", "expression": "happy", "position": "left", "transition": "fade", "duration": 0.4 }

In script.txt:

[hana happy left fade 0.4]
[hana]                        # default expression, current or auto-assigned slot
[hana hide]
Hana [happy]: Good morning.   # implicit char command before the line

Usually you need

FieldTypeDefaultEffect
namestring—Character folder under characters/. Empty or missing hides whoever is in the resolved slot
expressionstring"default"Expression key in the pack. Unknown keys fall back to default
positionstringsee slot resolutionSlot alias (left, center, right, …)
showbooltruefalse hides the character in the resolved slot
transitiontransition kind"instant"Enter and leave
durationnumber ≥ 00Seconds when transition_duration is absent

That is enough for most stories. Everything below is the full surface.

All fields

FieldTypeDefaultEffect
namestring—Character folder under characters/. An empty or missing name hides whoever is in the resolved slot
expressionstring"default"Expression key in the pack. Unknown keys fall back to default
packstringactive packPack file to read the expression from, without .json
positionstringsee belowSlot alias from the active layout profile
showbooltruefalse hides the character in the resolved slot
draw_layer"behind_panel" | "above_panel"pack, then slot, then behind_panelWhich plane the character draws on
transitiontransition kind"instant"Applies to both entering and leaving
transition_intransition kind—Overrides transition when appearing
transition_outtransition kind—Overrides transition when hiding
transition_durationnumber ≥ 00Seconds. Takes priority over duration
durationnumber ≥ 00Seconds, when transition_duration is absent
swap_modeswap modefrom the packForces how an expression change is blended
modulateHTML color#ffffffTint
opacitynumber 0–11Alpha
scalenumber or [sx, sy]1Scale
shaderstring, null, or shader objectkeep currentShader for this character
shader_paramsobject{}Uniform values, when shader is a plain name
bindobject—Live property binding to flags
interactionobject—Hooks fired when this command runs
whenexpression—Skip the whole command when the expression is falsy

Transition kinds are instant, fade, slide_up, slide_down, slide_left, slide_right, or "" to mean “not specified”. Swap modes are auto, in_only, crossfade, out_in, cross_slide.

Which slot the character lands in

position takes a slot alias — whatever the active layout profile defines, such as left or center by default, or your own names in a custom profile. See Planes and slots.

Omit position and the engine resolves it:

  1. The character’s current slot, if they are already on screen.
  2. Otherwise the first free alias, in the profile’s auto_selection_policy order.
  3. If every slot is taken, nothing happens and a warning is logged.

Showing a character also clears them from any other slot immediately, so the same character can never occupy two slots.

Visual fields are not sticky

modulate, opacity, and scale apply only to commands that mention them. Any char command that leaves one out clears the previous value for that slot.

[hana happy]                  # tinted
[hana sad]                    # tint is gone

Repeat the value on every command that should keep it, or move it into a pack drive rule instead.

The final look of a slot multiplies four sources in this order: the slot’s own modulate/scale from the layout profile, the command’s values, any matching pack drive rules, and finally bind. opacity and a bound opacity replace the alpha rather than multiplying it.

Transitions and expression changes

The command’s transition is used whenever the command names one, meaning a non-empty transition, transition_in, or transition_out, or any transition_duration or duration.

When the command says nothing about transitions:

  • Changing expression on a character who is already on screen uses the pack’s composition_transitions policy for that expression pair.
  • Anything else is instant.

swap_mode decides how the outgoing and incoming art overlap during an expression change. Without it, the pack policy chooses, and auto resolves to crossfade for a fade and in_only for a slide.

Shaders

shader valueResult
absentKeeps whatever shader the slot already has
nullClears the shader
"drop_shadow"Loads shaders/drop_shadow.gdshader, with shader_params as uniforms
{ "name": …, "params": …, "target": …, "pass": …, "margin": … }Full shader object; use margin to grow the render area so effects are not clipped

Binding to flags

bind drives a property from a flag while the character is on screen.

{
  "type": "char",
  "name": "hana",
  "bind": {
    "opacity": { "flag": "trust", "linear": [0, 0.3, 10, 1.0] },
    "modulate": { "flag": "mood", "map": { "angry": "#ffbbbb" }, "default": "#ffffff" }
  }
}

Bindable properties are opacity, modulate, scale, and shader:<uniform> for any uniform of the current shader. Full modes and surfaces: Binds.

Hooks

interaction.hooks fires when the command runs, not when the player clicks the character. Available events are on_show, on_hide, and on_change as a fallback for either. on_hide is chosen when show is false, otherwise on_show. Actions run in the gameplay UI context.

{ "type": "char", "name": "hana", "show": false,
  "interaction": { "hooks": { "on_hide": { "type": "set_flag", "values": { "hana_gone": true } } } } }