Skip to content

Story and Project Format

Nick Hamze edited this page Jul 19, 2026 · 4 revisions

Story and Project Format

Story Forge uses the WSC VN Studio .wscvn.json format. Keep the editable JSON as source evidence: a release is incomplete if the project cannot be traced to the compiled ROM.

For new stories and major rewrites, develop the narrative first in the prose-first novel.json format described in Light Novel Framework. Preserve its stable scene IDs while adapting them into VN nodes. Pass concept and outline before production art, and pass revision before presenting the adaptation as a finished story.

Schema v3 also carries scene-delivery evidence, typed continuity state, reader synthesis, rights scope, optional soundtrack motifs, and full-set ImageGen art approval into the adaptation. Keep the novel lockfile current before declaring the narrative source frozen.

Useful node types

  • title: title copy, menu labels, and the first transition.
  • scene: dialogue, staging, animation, music, sound, and the next node.
  • choice: up to four choices with targets, flag operations, and conditions.
  • branch: an instantaneous conditional jump; it may not be visible for a whole runtime frame.
  • chapter: an instantaneous organizational transition; treat it like graph structure rather than a screenshot target.
  • investigation: cursor-driven hotspots, conditions, flag operations, and a default leave target.
  • end: explicit graph terminus.

Keep node IDs stable and descriptive. Reports and proof routes depend on them.

The exhaustive route planner evaluates state, not merely node adjacency. Two routes can reach the same ending while taking different choices or hotspot orders; both remain coverage obligations. Conversely, routes that converge on the same final scene are allowed to share the same capture.

A compact choice

{
  "id": "first_choice",
  "type": "choice",
  "prompt": "Where should Mira search first?",
  "choices": [
    {
      "text": "Tune the receiver",
      "target": "radio_tune",
      "flagOps": [{"name": "signal", "op": "add", "value": 1}],
      "condition": ""
    },
    {
      "text": "Open the locker",
      "target": "locker",
      "flagOps": [{"name": "found_key", "op": "set", "value": 1}],
      "condition": ""
    }
  ],
  "defaultTarget": "quiet_deck"
}

Writing limits

  • Each text block separated by {pause} must be 100 visible characters or fewer.
  • Every dialogue page must fit the real 26-column by 4-line runtime textbox. The surrounding tile map is 32 columns wide, but dialogue is not.
  • Choices are limited to four.
  • Keep choice labels short enough for one 26-character handheld row.
  • Use printable ASCII until the font and renderer have been deliberately extended and proven together.
  • Treat typed control tags as syntax, not decorative braces.

The text contract measures the actual runtime font and layout. Character count alone is not a substitute for a 224×144 preview. Builders must call normalize_project_text() from scripts/wscvn_text_layout.py after assembling the project. It inserts {pause} controls only at word boundaries and preserves all dialogue; scripts/selftest_wscvn_text_layout.py guards against dropped or joined words.

Finished-story pacing floor

A ten-node premise demo is not a finished short VN. For a normal Story Forge release, every complete ending route should contain at least 25 scene beats and roughly 1,800-3,000 dialogue words, which is about 15-25 minutes at the readiness gate's 140-word-per-minute planning rate. Shorter work needs an explicit pacing justification rather than silently passing as complete.

Length should come from escalation, reversals, character decisions, callbacks, quiet reaction beats, and ending payoff. Do not inflate the count with repeated sentences or cosmetically duplicated nodes. check_wscvn_game_readiness.py enumerates every route and records scene, word, and estimated-minute totals. audit_wscvn_story_prose.py provides an additional duplicate and stock-filler audit for legacy projects; the full novel.json gate is stricter because it can also verify causality, genre and series promises, chemistry and delight maps, hash-bound editorial reports, reader testing, ImageGen provenance, publication proofs, and approval.

Branches should change the picture

A meaningful choice should usually produce a visible consequence: a new location, object insert, pose, reaction, or ending frame. Repeated left/right portraits with different text are technically branching but visually flat.

Useful rhythm:

  1. establish the place;
  2. let a character act;
  3. show the object or evidence;
  4. offer a choice;
  5. give each branch its own visible beat;
  6. converge only after the consequence has landed.

Character animation wiring

For blink:

  • charId: neutral
  • char2Id: blink
  • char3Id: empty

For talk-blink:

  • charId: neutral
  • char2Id: talk
  • char3Id: blink

Keep alternate sprite slots hidden unless the runtime is actively using them. During {pause}, the mouth should return to neutral while blinking continues. The closed-eye dwell is four presented frames in the current 75 Hz runtime. Blink art must be derived from the neutral master; see Graphics Pipeline.

Validation

The generic builder runs project, graphics, text, readiness, conversion, compile, emulator, and audit checks in the expected order:

python3 scripts/build_wscvn_game.py <slug>

Use the resulting review sheets and reports as editorial feedback, not merely as pass/fail paperwork.

Clone this wiki locally