Recipes
Combat damage health and respawn scripting
Any fight loop: a projectile hits, a sword swings, contact hurts, health drops, and the loser dies and respawns. The engine has NO
HealthComponent, DamageOnContactComponent, ProjectileComponent, or RespawnTimerComponent (all stripped, see component-types.md). You express the loop as a script.engine v1.0.234since script-semantic-patch-ops.v1, action-catalog.v1.0.232, persistence.v1Copy for LLM
Use this for
dealing damage on hit or contact; tracking health as durable state; death and respawn; hitscan or melee verbs
Not for
cosmetic hit sparks only (see audio-feedback and atmosphere); anything expecting a HealthComponent or DamageComponent (they do not exist)
Pairs with: Collectibles pickups scoring and win condition, Spawn points checkpoints and respawn flow, UI HUD panels widgets and world nameplates, Physics colliders rigid bodies triggers and joints
The recipe
Author with project_apply_script_semantic_patch (AI name apply_script_semantic_patch) using only the ai_safe operation pack. Every op that lives inside a handler takes scope: { "kind":"handler", "handlerRef": <handlerKey> }.
- Seed health as durable state:
writeTypedStateValue{ "storeKey":"progress", "recordKey":"player", "field":"health", "valueType":"number", "value": 100 }(defaults storeKeyprogress, recordKeyplayer). - Make the attacker's shot a verb:
addActionHandler{ "actionKey":"fire", "handlerKey":"onFire" }(the input action from input-mapping-actions-bindings). Or make contact hurt: give the hazard a triggerColliderComponentandaddTriggerHandler{ "handlerKey":"onHurt" }. - Apply damage inside that handler:
incrementNumericState{ "scope":{...}, "field":"health", "by": -25 }. Negativebysubtracts. - Detect death:
readTypedStateValuehealth into a binding (assignTo:"hp"), then branch. For the simplest match-level check usesetBooleanState{ "field":"dead", "value": true }when health reaches 0. - Respawn:
spawnEntityFromTemplate{ "templateKey":"player-spawn" }or{ "prefabKey": <prefab key> }with aconfigof validated inline overrides, and reset health with anotherwriteTypedStateValueback to 100. - For a whole-game outcome, transition the match phase from a GessaScript body with
ctx.match.setPhase, or usedeclareWinConditionfor count-based wins.
Pitfalls
- Do not attach a component named for health or damage; there is none. Health is a warehouse field.
incrementNumericStatemutates durable state and carriesrequiresAuthority; it runs server-authoritatively. Do not expect a client-only visual to persist.addTriggerHandlertakes NO trigger key: its payload has no trigger-identity field. Distinguish hazards by inspectingfirstEntityId/secondEntityIdor entity tags inside the handler.- The rich
addShooterCollectorLoopop is NOT AI-expressible (visual_editor and template contexts only). Compose the loop from the ai_safe primitives above. - For anything the add-only op alphabet cannot express (custom branching, math), drop to
replaceScriptFromGessaScriptand callctx.warehouse.*/ctx.match.*directly.
Verify
simulation_run(qa.run.start) to prove health drops on hit and the entity respawns.project_get_graph_snapshotto confirm the trigger/action handlers and the ScriptComponent binding exist.