v0.2
VNEngine v0.2
For coders
The big fix: saves no longer break when you edit the script
- Every save now stores a hash of the script plus its position as
(nearest label, offset)instead of a raw op index. Insert a line in chapter 1 and existing saves in chapter 3 still resume in the right place. - If the hash doesn't match on load, the player gets a "Save may be out of date" dialog (Resume / Restart chapter / Back to title) instead of silently landing mid-sentence in the wrong scene.
Read-tracking cleaned up
seen("have I read this line") moved to its own localStorage key,vnengine_seen, keyed bylabel+offset. It's no longer cloned into all 30 checkpoints, so it can't blow the storage quota.lsSetnow reports failures (quota full) with a toast + console error instead of swallowing them.
Boot-time validator
- On load,
engine.jschecks the script and logs a grouped console report:- Errors: duplicate labels, unknown jump/choice targets
- Warnings: unknown characters, unknown sfx names, unreachable code
- Each entry includes the op index. It never stops the game.
jump/ifto a missing label is now guarded (was a hard crash).
Rendering / effects
renderSprites()diffs bydata-idand swapssrcin place instead of rebuilding. Fixes sprite pop-in and the sprite "jump" on every expression change (the bob animation no longer restarts).- The flash effect is removed on
animationend, so it fades fully instead of being cut at 260ms. - Character color now actually tints the name box (with an auto light/dark text-contrast pick).
New engine subsystems
- Rollback (50-entry ring buffer; wheel-up / PageUp / button)
- A backlog overlay
- Skip / auto-advance modes
Tooling
playtest.py: dev mode sendsCache-Control: no-store(so the?v=cache-busting trick is gone), packaged-archive assets get a long immutable cache, and it scans for a free port instead of assuming port 8000 is the same game.- Fonts are bundled as
woff2insrc/fonts/and@font-face'd — no Google Fonts request, works offline. setup.pynow rewrites the title-screen logo and credit line fromproject.json, so a fresh project doesn't show the engine's branding.audio.js: the deadMARKSmap is wired intomusic()offsets;SFX_NAMESis exported for the validator.
Touched: engine.js (most of it), story.js, audio.js, style.css, index.html, playtest.py, setup.py, VNengine.md, README.md, new src/fonts/. Nothing committed.
For writers
Your saves won't break when you edit your script. Add, move, or rewrite lines freely. Old saves resume in the right spot because they're anchored to the nearest label, not a line count. If a save is from an older draft, the player sees a small "this save may be out of date" prompt instead of getting dumped into the wrong scene.
The console now tells you when you make a mistake. Open the browser console (F12) and the engine lists: typo'd jump/choice targets, duplicate label names, characters or sound names you referenced but didn't define, and unreachable lines — each with its position. It won't stop your game, it just points at the problem.
New things you can write
- Variables in text.
set({ gold: 5 })thensay('ari', 'You have {gold} coins'). Any variable name in{curly braces}gets substituted. - Text styling.
[b]bold[/b],[i]italic[/i],[c=#ff8ec4]coloured[/c]inside any line. - Conditional choices. Give a choice option a
showfunction and it only appears when that's true:{ text: 'Hug them', to: 'hug', show: function (s) { return s.vars.warmth > 2; } }
- Set a number exactly. Normally
set({ gold: 5 })adds 5. Useabs()to assign:set({ gold: abs(0) })sets it to 0. - Voice lines.
say('ari', 'Hello.', 'talk', 'ari_hello')— the 4th argument plays a sound file (registered inSFX_FILES) for that line.
New things your players get, for free
- Rollback — scroll the mouse wheel up, press PageUp, or click the ↶ button to go back a line.
- Backlog — press
Lor the ▤ button to see everything said so far. - Skip — hold Ctrl (or press Tab) to fast-forward; it stops at every choice.
- Auto-advance — press
A.
Other
- Character color now tints the name box, not just the placeholder card.
- Sprites fade in smoothly and no longer jump when they change expression.
- The flash effect fades instead of cutting off.
- Fonts are built in, so your game works with no internet.
- Editing while playtesting: just reload — no more bumping
?v=numbers.