# Stamina in your game (combat.stamina) ## What it is for `combat.stamina` gives the player one stamina gauge. Actions pay for themselves by name (`attack`, `special`, `dash`, `guard`, `sprint`, or any custom name), the gauge refills after a short pause, and at zero the player is exhausted: every action is refused until the gauge is back at a chosen share of its maximum. It charges the strikes of `combat.melee` and the dashes of `movement.dash` by itself, drains while the character sprints, and publishes the gauge to the HUD. It draws nothing: the HUD shows the variables. ## Turn it on Install the kit in a project and set its settings with the tools below; `gripforge kit api combat.stamina` lists every setting, and `gripforge docs combat-stamina` prints this guide offline. ```text gripforge_gamekit_install { project_id: "gkp_…", id: "combat.stamina" } gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.stamina", config: { "max": 120, "regen": 20, "costs": { "attack": 15 } } } ``` ## First example A named action is paid at its cost, reported by `stamina.spent`, and a number is a custom action. ```text combat.stamina.spend("attack") // true: 100 -> 82, event stamina.spent { action: "attack", cost: 18, value: 82 } combat.stamina.value() // 82 combat.stamina.spend(30) // true: a custom action, event stamina.spent { action: "custom" } combat.stamina.value() // 52 ``` ## Settings and defaults | Setting | Default | Meaning | | --- | --- | --- | | `max` | 100 | points of the gauge when full | | `regen` | 18 | points regained per second once `regenDelay` has passed since the last spend | | `regenDelay` | 1 | {{s_regenDelay}} | | `recoverRatio` | 0.3 | {{s_recoverRatio}} | | `partialActions` | `true` | {{s_partialActions}} | | `costs` | `attack` 18, `special` 30, `dash` 22, `guard` 12, `sprint` 8 | what each action costs, in points (`sprint`: per second); any other name costs what the caller gives | | `sprintAction` | `sprint` | {{s_sprintAction}} | | `exhaustedStatus` | empty | {{s_exhaustedStatus}} | | `chargeStrikes` | `true` | {{s_chargeStrikes}} | | `chargeDashes` | `true` | {{s_chargeDashes}} | ## Services - `combat.stamina` (service, also served as `movement.stamina` for the kits that climb, swim or glide): `value()`, `max()`, `exhausted()`, `spend(action | amount, partial?)` answers `true` when paid, `costOf(action)`, `drain(action, seconds)`, `restore(amount)`, `refill()`, `setMax(max, refill?)`. - Variables for the HUD: `player.stamina`, `player.stamina.max`, `player.exhausted`. ## Events - `stamina.spent`: an action was paid: its `action`, `cost` and what is left (`value`); a sprint drain emits nothing per tick. - `stamina.refused`: an action was refused, with a `reason` of `exhausted`, `short`, `cancelled` or `dead`. - `stamina.exhausted`: the gauge hit zero and the exhaustion state began; `recover` is the value it must reach again. - `stamina.recovered`: the exhaustion state ended. - `stamina.restored`: `restore` or `refill` gave points back (a rest, a potion). ## Hooks and modding - `stamina.spend`: the player is about to pay `cost` for `action`; `cost` is mutable (0 makes the action free) and a tap can cancel, which refuses the action like an exhausted gauge (`stamina.refused`, reason `cancelled`). - `stamina.exhaust`: a continuous decision asked once when the gauge hits zero and held until it is back at `recover` x `max`; `recover` is mutable, and cancelling it means no exhaustion state at all (an "endless stamina" mod). Every setting above is moddable. A hook document of a game or a mod taps a decision: ```json { "id": "free_dash", "hook": "stamina.spend", "match": { "action": "dash" }, "set": { "cost": 0 } } { "id": "endless_stamina", "hook": "stamina.exhaust", "cancel": true } ``` ## Using it from content Script verbs: actions `stamina_spend` (a named action, or a custom name with `amount`) and `stamina_restore`; conditions `stamina_at_least` and `stamina_exhausted`. ```json { "stamina_spend": "guard" } { "stamina_restore": 50 } { "stamina_at_least": 20 } ``` ## When it does not do what you expect | Symptom | Cause and fix | | --- | --- | | A strike or a dash is not charged | `combat.melee` or `movement.dash` is not installed, or `chargeStrikes` / `chargeDashes` is `false`; only the player is charged. | | Every action is refused | The player is exhausted: wait for `stamina.recovered`, lower `recoverRatio`, or cancel the `stamina.exhaust` hook. | | A big action is refused while the gauge is not empty | `partialActions` is `false`, so an action needs its full cost (reason `short`). | ## Limits - It manages the gauge of the player only, not one gauge per NPC. - It runs on the web player and the native Rust host; there is no Godot, Unity or Unreal adapter yet. - It draws no gauge: bind the three variables to a HUD. ## Versions Kit `combat.stamina` 1.0.0 (since 2026-10-22); it needs `game.engine` ^1, and uses `combat.melee`, `movement.dash` and `combat.core` when they are installed. The shared `movement.stamina` pool is served by this kit.