Studio

FolioTier 1

when

Conditionally run a body of inline steps in place; chain `else when <condition>:` arms and a final `else:` for first-match branching, or end a body with `jump` to route.

Use when to gate a whole run of steps on a single condition instead of tagging every line with its own if. It reads like a normal branch in the script: the condition is checked once, and if it holds, the indented body plays start to finish before the scene continues; if it doesn't, Folio skips straight past the whole block. Reach for it whenever a chunk of dialogue, staging, or audio only makes sense in one state of the story - a callback line that should only fire if the player saw an earlier scene, an alternate sprite/frame pairing for a route flag, that sort of thing.

Chain else when and else off the same when to get first-match branching across mutually exclusive arms, checked top to bottom - the moment one condition is true, later arms are skipped even if their own condition would also hold. else has no condition of its own; it catches whatever every arm above it missed, so it always has to come last.

Under the hood each line in a body gets the block's condition (or accumulated negations, for else when/else) stamped onto it, which is why a body line can carry its own if tail and still be doubly gated - but you rarely want that; write the gate once at the header and let the body inherit it.

If nothing matches and there's no else, the scene simply continues after the block - there's no error for an unhandled case, so double check whether you actually want a fallback arm. End a body with a jump when the branches should route to different labels rather than just play different inline steps in the same scene.

Parameters

ParameterKindRequiredDefaultNotes
conditionexpressionyes-Bounded expression evaluated against project state - bare identifier, `not <ident>`, comparison, `and` / `or` (see the `variables` reference for the full grammar). When the condition is true, the body runs in order; when false, the body is skipped and the scene continues past the `when` block.
bodyidentifieryes-One or more indented Folio statements (say / narrate / show / hide / bg / set / music / sound / ...). Each line inherits the `when`'s condition under the hood, so a body line with its own `if` tail evaluates both - but in practice you write the gate once at the `when` header.
else whenidentifierno-Optional chained arms: any number of `else when <condition>:` lines at the same indent as the `when` header, each followed by its own indented statements. Arms are checked first-match, top to bottom - an arm runs only while every condition above it failed AND its own condition holds (the accumulated negations are stamped on each line under the hood). The final `else:` (if any) must come after every arm.
elseidentifierno-Optional otherwise-branch: an `else:` line at the same indent as the `when` header, after the body and any `else when` arms, followed by its own indented statements. Those run only while every condition above failed - the negated gates are stamped on each line the same way the body inherits the positive one. No condition of its own; nesting follows indent.

Canonical example

Folio
when day2-basketball:
  sprite show day20-dylan-amber frame "189"
  say "Sa": "I just can't approve that."
  sprite show day20-dylan-amber frame "190"
  say "Dy": "She wouldn't have missed a basket."
Ren'Py
if day2_basketball:
    show day20_Dylan_Amber 189
    sa "I just can't approve that."
    show day20_Dylan_Amber 190
    dy "She wouldn't have missed a basket."

when is Folio's conditional block. The header when <condition>: opens a block; each indented line is a step that runs only when the condition evaluates truthy. The scene continues past the when block either way - falsy conditions skip the body without branching anywhere.

An optional else: at the same indent opens the otherwise-branch: its indented lines run only while the condition is false. Both branches stay inline - the scene flows on past the whole construct.

when gasp:
  narrate "You heard it too."
else:
  narrate "The room stays quiet."

To make the conditional outcome a jump to a different scene, put a jump inside the body - and, for a two-way branch, another jump under else::

when has-key:
  jump unlock-door
else:
  jump rattle-door

Equivalently, pair a guarded jump <a> if <cond> with a plain jump <b>. Either shape replaces the old standalone routing conditional.

Notes

The condition follows the same closed grammar as any Folio guard (see variables) - bare identifier, not <ident>, comparison with a bool/numeric literal, or and / or combinations. The importer's deterministic stage only translates the conservative subset (no compound and / or, no method calls, no dotted accessors); unsupported shapes fall through to the AI lane rather than dropping the guard.

Nesting works the same way a nested Ren'Py if would: a when inside a when evaluates both conditions before running the inner body. The runtime expands these at scene-load time so the player's step cursor never has to descend - each child step's effective condition is the AND of every surrounding when; an else: line's children get the NOT of their when's condition (AND-combined with any outer gates). else: takes no condition, must sit at the same indent as its when, and belongs to the nearest when at that indent.

when day-saturday:
  when invited-to-party:
    bg bg-party-night
    say "Emma": "I made it."

The importer maps Ren'Py's if <expr>: with an inline body (no elif / no else) to a Folio when block on a per-fragment basis (Gap 1, Phase 8). Ren'Py's if/elif/else chains lower to first-match guarded arms (each step carries its own condition); a two-arm if/else whose branches are pure jumps reads back as a when body jump paired with an else: jump, or as two guarded jumps.

See also

  • jump - put one inside a when body to branch to another scene
  • set - assign the state variables when reads
  • choice - guarded menu options with their own per-option if tails