Gessa Docs
Recipes

Recipe

Projectiles bullets and ranged weapons

The player fires and something flies out or an instant beam hits. There is no ProjectileComponent, HitscanWeaponComponent, or WeaponSlotComponent (all stripped); a weapon is a fire action plus a spawn-and-launch or a shapecast.
engine v1.0.234since script-semantic-patch-ops.v1, action-catalog.v1.0.232, physics.v1, spawn.v1, prefabs.v1Copy for LLM

Use this for

guns that fire bullets; thrown grenades, arrows, and fireballs; hitscan and instant-hit weapons; spawning a moving projectile that damages what it hits

Not for

melee or contact damage without a projectile (see combat-damage-and-respawn); the score bookkeeping after a kill (see match-flow-and-scoreboards); firing rate limited by a cooldown clock only (see timers-countdowns-and-waves)

Pairs with: Combat damage health and respawn scripting, Timers countdowns cooldowns and enemy waves, Input mapping actions bindings keyboard mouse gamepad touch, Particles explosions and visual effects

The recipe

Author with project_apply_script_semantic_patch using the ai_safe op pack.

  1. Bind the trigger: declare a fire action (see input-mapping-actions-bindings) and addActionHandler { "actionKey":"fire" }.
  2. Spawned projectile (grenade, arrow, fireball): build a projectile prefab once with project_create_prefab carrying a RigidBodyComponent and a trigger ColliderComponent (collision:"trigger"). In the fire handler, spawnEntityFromTemplate { "prefabKey": <projectile>, "config": {...} } at the muzzle, then push it with ctx.physics.command using a launch body command (VelocityComponent's contract note: launch bodies via Physics.command { type: "launch" }; never patch VelocityComponent directly, it is engine-internal). Damage on contact via addTriggerHandler on the projectile that applies damage (see combat-damage-and-respawn) and despawnEntity the bullet.
  3. Hitscan (instant hit): in the fire handler body (GessaScript via replaceScriptFromGessaScript), call ctx.physics.shapecast from the muzzle along the aim direction; if it returns a hit, apply damage to the hit entity and spawn an impact effect. No projectile entity is spawned.
  4. Rate limit: guard the fire handler with a cooldown (a TimerComponent or a last-fired timestamp in state; see timers-countdowns-and-waves) so holding fire does not spawn one bullet per tick.
  5. Muzzle flash and impact: pair with particles-and-visual-effects for the burst and a DecalComponent scorch at the hit point.

Pitfalls

  • Never write VelocityComponent to move a bullet; it is hidden from AI/SDK and runtime-owned. Launch through ctx.physics.command.
  • spawnEntityFromTemplate and ctx.world.spawn are authority-gated (spawn.bounds); spawn on the server, at a bounded position near the muzzle.
  • Bullets that never despawn accumulate and hit the collider budget (1000 per tick). Despawn on impact and add a lifetime timeout.
  • A projectile collider must be trigger, not solid, or it will be blocked by the target instead of passing through and reporting the hit.
  • Aim direction must come from the shooter's facing (camera or transform), resolved in the handler; there is no built-in "forward vector" field to read blindly.

Verify

  • simulation_run (qa.run.start) to prove a shot spawns and travels, a hit applies damage, and the projectile despawns on impact or timeout.
  • project_get_graph_snapshot to confirm the fire action handler and the projectile prefab exist.
Was this helpful?Report an issueContact support

On this page