Skip to content

Tutorial Battle Animation Modes

johnjohto edited this page Jul 30, 2026 · 1 revision

Tutorial: Battle Animations by Mode and by Outcome

Two things presentation/move_anims.json couldn't do: change an animation for one save mode and not another, and animate an outcome rather than a move.

Half 1 — one project, two looks

If your project runs more than one mode — a faithful one and an enriched one, say — a change to an animation used to apply to both. Now an anims entry can be an ordered candidate list:

"anims": {
  "TACKLE": [
    {"when": "mode_overhaul", "script": [{"sfx": "TACKLE", "sub": 1, "tileset": 0, "delay": 8},
                                         {"se": "move_mon_horizontally"}]},
    {"script": [{"sfx": "TACKLE", "sub": 1, "tileset": 0, "delay": 8}]}
  ]
}

The enriched save gets a contact lunge. The faithful save gets the animation it always had. Same file, same project.

If you've used Conditioned Bindings for zone slots or palettes, this is exactly that grammar again:

  • A bare command list is sugar for one unconditioned candidate — every animation you never touched behaves as before.
  • First match wins, in the order you wrote them.
  • A candidate with no when is the fallback. Anything after it can never fire, and refuses at --validate.
  • when is a condition over the same identifiers your events use — story flags, event variables, badges, clock buckets.
  • Conditions are compiled once at boot. An unparseable one refuses there, loudly.
  • Resolution draws no randomness, so a conditioned project's battles stay replay-identical.

Condition every candidate and let none match, and nothing animates — that's a real answer ("no animation in this mode"), not a fall-through to the faithful one.

Half 2 — animating an outcome

Animations are keyed by move, so you could say what TACKLE looks like but never that a critical hit looks like something. Two reserved keys fix that:

key plays when typical use
_CRIT the hit was a critical a flash, a harder shake
_MISS the attack missed the defender visibly moves aside

They're ordinary anims entries, so they get the conditioning above for free:

"anims": {
  "_CRIT": [
    {"when": "mode_overhaul", "silent": true, "script": [{"sfx": null, "se": "flash_screen_long"}]},
    {"script": []}
  ]
}

Leave both keys out and nothing changes anywhere — the faithful message stream is byte-identical.

silent, and why it's per-candidate

"silent": true drops the message that outcome would normally print. A visible dodge already says "missed"; a flash already says "critical". No need for the words too.

The flag rides the candidate, not the entry. That's what makes the two halves one feature: the suppression is conditioned along with the animation that earns it. Your faithful save keeps "A critical hit!" while your enriched save shows the flash instead — from the same entry.

The suppression is deliberately partial

You cannot suppress "It's super effective!". There is no _SUPER slot, and silent on any other key is a validation error.

This is on purpose. A flash can say critical. Nothing visual can say why something was super effective — and that line is how a player learns the type chart in the first place. Replacing it makes the game less readable to exactly the player who most needs it.

A single "animations replace text" switch would have forced you to take that suppression in order to get the miss suppression. Per-outcome control means you don't.

Nothing is suppressed when nothing plays

With BATTLE ANIMATION turned off in the options, outcome animations aren't queued and the lines stand. Otherwise the option would silently delete the only report of the outcome.

No new animation primitives

This is about selecting between animations, not inventing them. Your _CRIT and _MISS scripts use the same command vocabulary as any move animation — subanimations, tilesets, delays, and the special effects that already exist. (move_mon_horizontally, the contact lunge, was already there.)

Verifying

python tools/run.py --battleanimtest checks the whole surface headlessly. The full format reference is battle-anims.md.

Pairs with Conditioned Bindings and Overlay Projects.

Clone this wiki locally