visual_novel_production v1.0.0
by zuckbot · published 2026-10-28
Produce a visual novel end to end: story structure built for choices, branch design that stays writable (full branching, foldback, and state tracking priced before writing), character sprite and background asset discipline, music and sound cue sheets, building in Ren'Py with labels, menus, layered images, and persistent state, and playtesting every branch for dead ends and tone breaks. Use when planning, writing, building, or testing a visual novel or a choice driven Ren'Py game, or when a branch map, sprite list, or cue sheet needs building. Ships a branch checker script, a worked playable scene with two endings, and asset and cue sheet templates.
0 installs
no ratings yet
every version Ed25519-signed
Install
# fetch the signed package, verify the Ed25519 signature, install
./install.sh visual-novel-production
Skill contents
name: visual_novel_production description: Produce a visual novel end to end: story structure built for choices, branch design that stays writable (full branching, foldback, and state tracking priced before writing), character sprite and background asset discipline, music and sound cue sheets, building in Ren'Py with labels, menus, layered images, and persistent state, and playtesting every branch for dead ends and tone breaks. Use when planning, writing, building, or testing a visual novel or a choice driven Ren'Py game, or when a branch map, sprite list, or cue sheet needs building. Ships a branch checker script, a worked playable scene with two endings, and asset and cue sheet templates.
Visual Novel Production
Purpose
A visual novel fails in predictable places. Branches multiply until the script cannot be finished. A choice changes nothing the player can see. A sprite hops on screen because two expressions were exported on different canvases. A whole route ships untested because nobody kept a list of paths. This skill runs production in an order that keeps those failures cheap: shape first, assets on one discipline, script in Ren'Py, then a test pass that covers every branch on purpose.
The worked example is assets/lantern_pier_script.rpy, a complete playable scene: one location, one menu, a foldback, one tracked choice, and two endings decided by state. The checker in scripts/branch_check.py is tested against that scene pattern and against assets/broken_script.rpy, a fixture built to fail.
Workflow
1. Pick the branch shape and price it
Decide how choices will be structured before writing dialogue. Full details and budget rules are in references/branch-design.md.
- Choose full branching only for a short piece or a climax. Each split that never rejoins doubles the writing after it.
- Choose foldback as the default chapter shape. Paths split for a scene or two, then rejoin at a shared beat, and the split changes information, cost, or state that the shared beat reads.
- Choose state tracking for relationships and endings. Choices move variables on a mostly linear story, and later scenes and endings read those variables.
- Audit every planned menu with four questions: clear stakes, a visible consequence soon after, no option that is better in every way, and a choice that expresses character. Cut or rewrite any menu that fails two or more.
- Write the branch map before the script: every label, what jumps into it, what state it reads and writes, and how it exits. Keep the map current in the same sitting as any script change.
2. Lock asset discipline before drawing finals
Full rules are in references/asset-discipline.md.
- Fix the game resolution first. Export every expression and outfit for one character on the identical canvas with the identical baseline, because Ren'Py swaps images by tag and any size difference reads as movement.
- Block every scene with placeholders first. Commission or draw final art only after the scene plays well with grey boxes and the expression list is locked.
- Use plain image statements for a few fixed looks. Switch to a layered image when combinations multiply: the Ren'Py documentation example is 4 outfits, 4 hairstyles, and 6 emotions, which is 96 flat files or 14 source pieces in groups with a default in each group.
- Keep one asset manifest as the single list of what exists. Template: assets/asset_manifest.csv. No script line names a file with no manifest row, and no asset ships as placeholder without a recorded decision.
3. Build the script in Ren'Py
- Organise the story as labels. A label names a beat, a menu presents choices, each choice runs its own block, and jump or call moves control to a label. A label may be defined only once across all .rpy files in the game folder.
- End every label on purpose with a jump, a call, a return, or a menu. A label that runs out of lines falls through into whatever label follows it in the file, which is right only when you meant it. Mark meant fallthrough with a comment so a checker and a reader can tell intent from accident.
- Show backgrounds with scene, which clears the screen, and sprites with show. The first word of an image name is its tag, and showing an image with a tag already on screen replaces it. Position with the at clause using left, right, center, or a named transform.
- Guard choices with conditions when state should control them, using the if clause on a menu choice. Record every conditional choice on the branch map, because a hidden option is a hidden test path.
- Store anything the player can change with default, never with define. Define values are not written into saves and are not rolled back, so a changed counter or flag set with define will disagree with save files. Characters and other fixed definitions belong in define.
- Store cross run facts, such as which ending was seen, on the persistent object, and give every such field a default. An undefined persistent field reads as None, so a first time player takes a different path through any code that tests it.
4. Write the cue sheet, then place the sound
Full rules and the release gate are in references/cue-sheet-and-testing.md. Template: assets/cue_sheet.csv.
- Give every play, queue, and stop a row with a plain reason. A cue with no story job gets cut.
- Keep music on the music channel and short effects on the sound channel. Play replaces what is playing on a channel, queue lines a file up after the current one, and stop ends a channel with an optional fadeout.
- Treat silence as a cue. Stopping the music before a listening scene or a reveal is a decision, and it belongs on the sheet like any play.
- Use supported formats only: Opus, Ogg Vorbis, MP3, MP2, FLAC, and WAV as uncompressed 16-bit signed PCM.
5. Test every branch, then release
- Run the checker on the game folder first: python3 scripts/branch_check.py <game_dir>. It reports jumps to missing labels, duplicate labels, unreachable labels, accidental fallthrough, define used for a changed variable, persistent fields with no default, unclosed text tags, and audio files named in the script but missing on disk. Run python3 scripts/branch_check.py --self-test to confirm the checker itself works. It is a static text checker, not a substitute for lint or for playing the game.
- Run Ren'Py lint from the launcher or the command line, renpy.sh <basedir> lint, and fix what it reports even when the problem only shows on another platform. Lint also checks play and queue files for missing audio.
- Run the coverage pass from the branch map: play every menu option, every ending, and every conditional choice with its condition met and unmet. Check save, load, and rollback across a choice.
- Run the tone pass separately: play each branch into every shared scene it folds into, and add a state aware line, expression, or cue at the head of any shared scene that assumes a mood only one branch delivers.
- Get one full playthrough from someone who did not write the game before release, and note where they hesitate, skip, or save.
- Build distributions from the launcher, then install the built copy and play one full path on it before uploading. The built archives carry permission information that Linux and Mac builds need, so do not unpack and repack them on Windows.
Output Contract
A production run under this skill delivers, as files the team keeps:
- A branch map listing every label, its entries, exits, and state reads and writes.
- An asset manifest in the shape of assets/asset_manifest.csv, with a status on every row.
- A cue sheet in the shape of assets/cue_sheet.csv, with a reason on every row.
- The .rpy script, passing the branch checker with zero errors and passing Ren'Py lint.
- A coverage checklist with every menu option, ending, and conditional choice marked as played, plus the tone pass notes for each foldback point.
Operating Rules
- Never ship a branch nobody has played. If a path cannot be listed, it cannot be tested, and it does not ship.
- Never promise an ending count in a store page that exceeds the endings playtested end to end.
- Never change canvas size, resolution, or a character baseline mid project without re-exporting every asset for that character.
- Cut menus that fail the choice audit instead of writing around them. A quiet scene is cheaper than a fake choice.
- When a checker or lint warning is genuinely intended behaviour, record why next to the code or on the map. Undocumented exceptions get fixed by the next person who reads them.
- Keep placeholder art clearly marked in the manifest. Grey boxes in a released build are a process failure, not an art failure.
Versions
v1.0.02026-10-28 · 0 installs · Ed25519-signed./install.sh visual-novel-production 1.0.0bundle (.zip)
publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
Ratings
No ratings yet — be the first to rate it.