Moveset
Move definitions with frame clocks, a bounded input buffer, directional motion commands and hit or block confirmed cancels for fighting games.
Move clocks and input buffer (combat.moveset) #
What it is for #
combat.moveset runs the timing of a fighter's attacks: which move starts, how long it is in startup, active and recovery, which buttons and directions start it (a quarter circle is [2,3,6]), how long an early press stays buffered and which cancels open on a hit or a block. One instance per actor. It owns no collision, damage, root motion or animation: the game applies the contacts, spends the resource and plays the clip when a move started event arrives. It is a driver you step yourself, with no hidden tick. It works with combat.defense (guide), whose outcomes feed the cancel confirmations, and shares its scheduler with combat.duel (guide).
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "combat.moveset" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.moveset",
config: { "bufferFrames": 8, "moves": [ … ] } }
Without moves the kit has the three default moves below. Call step once per fixed simulation frame (normally 60 Hz); times are whole frames.
First example #
<!-- test: kits/game_engine/host/tests/combat_moveset.rs::confirmation_and_save_replay_on_host --> Queue jab, step five times (the jab is then active), confirm that it hit, queue heavy: the jab cancels into the heavy on hit. The test also saves and loads the instance and gets the same result.
{ "op": "queue", "move": "jab" }
{ "op": "step" }
{ "op": "confirm", "sequence": 1, "result": "hit" }
{ "op": "queue", "move": "heavy" }
{ "op": "step", "resource": 100 }
Each line is the command of request("default", command); the single step stands for the five steps of the test. After the last step the answer has state.active.move equal to heavy.
Settings and defaults #
Fixed at creation; unknown keys are refused.
| Setting | Default | Meaning |
|---|---|---|
moves | jab, heavy, shot | 1 to 64 move definitions (see below). |
bufferFrames | 8 | How long an early press waits (1 to 60). |
historyFrames | 30 | Direction history kept for motion commands (1 to 60). |
A move needs id, button, startup (0 to 600), active (1 to 600) and recovery (0 to 600). Optional: cost (default 0), ground (any, ground or air), directions (numpad directions, [] for a plain button), maxGapFrames (12), priority (0 to 1000: highest wins, then the longest motion, then the smallest id) and up to 32 cancels { to, from, until, on } with on being always, hit or block. The defaults are jab (4/3/10, cancels into heavy on hit), heavy (9/4/18, cost 10) and shot (a quarter circle, 10/1/20, cost 20, on the ground).
Services #
Service combat.moveset (up to 128 named instances): create(id, config), remove(id), ids() and request(id, command) with the commands:
step { direction?, facing?, buttons?, grounded?, resource?, enabled?, frozen? }:directionis a numpad value 1 to 9 in world space (5 neutral),facingis 1 or -1,buttonsare press edges (up to 16),resourceis the balance the game holds.enabled: falseblocks starts and cancels;frozen: truestops the clocks (hit stop).queue { move }: buffers a known move by hand (for AI); grounds, cost and cancels still apply.confirm { sequence, result }:hitorblockfor the current attack, after it started.interrupt,reset,status,config,save,load { save },preview { command }.
Answers hold state, phase and events. Script verbs: a request verb and an exists condition named after the kit id with dots turned into underscores (<kit>_request, <kit>_exists).
Events #
- In the answer of a request:
started { move, sequence, cost }(spend the cost once),active,ended,cancelled. - Bus events, named
<kit id>.<suffix>:.created,.removed,.changed(a decided command applied) and.refused(a tap cancelled it).
Hooks and modding #
| Hook | Effect |
|---|---|
combat.moveset.create | Before an instance is created; may change its config or cancel. |
combat.moveset.request | Before a decided command; may change the command or cancel. |
create(id, { preset }) reads the presets collection of the kit (its id with dots turned into underscores, then _presets).
Engines #
The same Rust core runs on the web, the native player and as a C library and WebAssembly module for the engine wrappers. The game checks hitboxes during the whole active phase and keeps its own table of already hit targets per attack sequence.
When it does not do what you expect #
- A command does not start: check
ground,costagainst theresourceyou send,enabledand the buffer. - A cancel never opens: the window
[from, until)is in frames of the current move andonmust match the confirmation. confirmis refused: thesequenceis stale or the attack has not started yet.
Limits #
No collision, damage, animation or resources: the game owns them. The duel kit does not yet read arbitrary movesets from this kit.
Versions #
Kit 1.1.0 (modding contract). Save format gripforge.moveset/1.