Hit reactions
Stun, launch and knockdown clocks, landing, getting up and temporary invulnerability for fighting games, driven by explicit commands.
Hit reactions (combat.hit_reactions) #
What it is for #
combat.hit_reactions decides what a body does after it is hit: stunned, launched into the air, knocked down, then landing, lying down, getting up and a short protection window. It is a clock and a set of rules, one instance per actor. It owns no health, gravity, collision world or animation: the game says whether the body is grounded, applies the returned velocity exactly once, and plays the clips. It is a driver you step yourself, with no hidden tick. Use it after combat.defense (guide) has decided that a hit lands, with combat.moveset (guide) for the attacker and combat.grabs (guide) for throws.
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "combat.hit_reactions" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.hit_reactions",
config: { "downFrames": 24, "getupFrames": 18, "getupInvulnerabilityFrames": 18 } }
Durations are whole fixed simulation frames (normally 60 Hz); call step once per frame with the grounded flag from your collision code.
First example #
<!-- test: kits/combat_hit_reactions/tests/combat_hit_reactions.rs::a_knockdown_stays_down_then_gets_up_with_protection --> With downFrames: 3, getupFrames: 2 and getupInvulnerabilityFrames: 4, a knockdown goes to phase downed; after three grounded steps getup_started fires and the body is protected (canBeHit is false). A hit during the protection answers accepted: false with an ignored event (reason invulnerable); two more steps give recovered and the phase is ready again.
{ "service": "combat.hit_reactions", "method": "request", "args": ["default",
{ "op": "hit", "sequence": 1, "kind": "knockdown", "grounded": true }] }
{ "service": "combat.hit_reactions", "method": "request", "args": ["default",
{ "op": "step", "grounded": true }] }
Settings and defaults #
Fixed at creation; unknown keys are refused.
| Setting | Default | Meaning |
|---|---|---|
downFrames | 24 | Frames spent on the ground before getting up (1 to 600). |
getupFrames | 18 | Frames of getting up before control returns (1 to 600). |
getupInvulnerabilityFrames | 18 | Protected frames counted from the start of getting up (0 to 600). |
maxAirFrames | 600 | Airborne steps allowed since the last accepted hit or transition (1 to 600). |
recoveries | none | Up to 16 getup choices { id, frames, invulnerabilityFrames, velocity } (a roll, a quick rise). |
Services #
Service combat.hit_reactions (up to 128 named instances): create(id, config), remove(id), ids() and request(id, command) with the commands:
hit { sequence, kind, grounded, stunFrames?, velocity? }:kindisstun,launchorknockdown;sequenceis an integer strictly above the last impact of that actor; alaunchneedsvelocity(world metres per second, Y up). Answersacceptedand the events.step { grounded, frozen? }: advances the clocks;groundedis required. A frozen step changes nothing.land { sequence }: the engine tells that the body landed during the current accepted reaction.recovery { sequence, id }: picks one of therecoverieswhile down.invulnerability { frames }: extends the protection (never shortens it).interrupt,reset,status,config,save,load { save },preview { command }.
Answers hold state, canAct (the phase is ready), canBeHit 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:
reaction { sequence, kind, phase, velocity }(apply the velocity once),ignored,airborne,landed,getup_started(withrecoveryandvelocitywhen a choice was made),recovered,air_timeout,interrupted. - 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.hit_reactions.create | Before an instance is created; may change its config or cancel. |
combat.hit_reactions.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 engine provides grounded, applies velocities and plays the animation.
When it does not do what you expect #
- A launch is refused: it needs a
velocity. - A hit answers
accepted: false: the body is protected (invulnerable) or the sequence is stale; the sequence is still consumed. - A launched body never lands: send
grounded: falsefirst, thengrounded: true, or useland; otherwiseair_timeoutends it aftermaxAirFrames.
Limits #
No health, gravity, ragdoll, root motion or clips. It does not decide whether a body is alive: gate new actions yourself.
Versions #
Kit 1.2.0 (modding contract), 1.1.0 (recoveries). Save format gripforge.motion/1.