# Projectiles (combat.projectiles) ## What it is for `combat.projectiles` flies point projectiles, straight or ballistic, in a bounded pool. `launch` returns an id; each tick the kit sweeps every segment of the path through the physics port, the owner excluded. A contact ends the flight once and deals the damage through `combat.damage` when `combat.health` knows the target, through `vehicle.damage` for a vehicle, otherwise through its `health` component. `projectile.impact` announces every contact, scenery included. A finished shot stays in the snapshot for its trail and impact. Each shot can carry its own look and behaviours: homing, bounces, splash damage, chain jumps, an on-hit status, a mine, a returning throw. `combat.ranged` delegates to it when its `projectile` option is on. The presentation draws the shots in flight, world-space trails, impacts and the light they carry. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "combat.projectiles" } gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.projectiles", config: { "speed": 12, "gravity": 0, "damage": 25, "style": "fire" } } ``` It requires `physics.port` and `game.engine`; the damage path uses `combat.core` when installed. ## First example A returning throw in manual mode (Rust kit host, with a physics port). The owner launches a shot toward a foe 4 m ahead; it passes through the foe once (15 damage), rests at its range of 8 m, and a `recall` by the owner sends it back, where it is caught. Another entity cannot recall it, and the foe is damaged only once for the whole throw. ```json { "service": "combat.projectiles", "method": "launch", "args": [{ "owner": "e1", "origin": [0, 1, 0.4], "direction": [0, 0, 1], "speed": 12, "damage": 15, "lifetime": 20, "return": { "mode": "manual", "range": 8, "catch": 0.8 } }] } { "service": "combat.projectiles", "method": "recall", "args": ["e1"] } ``` `launch` answers the shot id (or `null` when refused or the pool is full); `recall` answers the number of shots recalled. ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `speed` | `12` | Metres per second (0.1 to 300). | | `gravity` | `0` | Downward acceleration in m/s² (-40 to 40); 0 is straight flight. | | `lifetime` | `4` | Seconds before the shot expires (0.05 to 20). | | `damage` | `25` | Damage on contact (0 to 1000). | | `maxActive` | `32` | Shots alive at once (1 to 128). | | `style` | `fire` | Look: `fire`, `ice`, `arcane` or `poison`. | | `radius` | `0.18` | Visual radius only; contacts sweep the centre path. | | `trailLifetime` | `0.35` | Seconds a trail lasts (0.06 to 1). | | `impactDuration` | `0.85` | Seconds an impact effect lasts (0.15 to 2). | | `quality` | `high` | `low` or `high` effects. | | `presentationProfile` | none | Id of a `presentation_profiles` document for the shot model and spin; presentation only. | All except `presentationProfile` are moddable. ## Services, events, variables - Service `combat.projectiles`: `launch({ owner, origin, direction, speed?, gravity?, lifetime?, damage?, source?, look?, homing?, bounces?, bounceOn?, restitution?, splash?, chain?, status?, return?, mine? })`, `snapshot()` and `recall(owner, id?)` (Rust, manual returns). - Behaviours of a launch: `look { style, variant, color, radius }`; `homing { turnRate, range?, target? }`; `bounces` (0 to 8), `bounceOn` (`scenery` or `all`) and `restitution`; `splash { radius, share?, onExpire? }`; `chain { targets, radius, share?, speed? }`; `status { id, stacks? }`; `mine { arm?, trigger? }`; `return { range?, catch?, mode? }` (`auto` or `manual`; manual cannot combine with homing, bounces or mine). - Events `projectile.launched`, `projectile.impact` (`target`, `damage`, `applied`, `bounced`), `projectile.chained`, `projectile.splashed`, `projectile.planted`, `projectile.detonated`, `projectile.returning`, `projectile.returned`, `projectile.rested`, `projectile.expired`, `projectile.ended` (reason `returned`, `expired`, `hit`, `owner-dead` or `owner-lost`), and the compatible `combat.hit`. - Variable `combat.projectiles.active`. - Script verbs `projectile.launch { instance | owner, origin?, direction?, ... }` and `projectile.recall { instance | owner, id? }`. ## Hooks and modding | Hook | Mutable | Effect | |---|---|---| | `projectile.launch` | `speed`, `gravity`, `lifetime`, `damage` | A shot is about to enter the pool. Cancelled: `launch` answers `null`. | | `projectile.impact` | `damage` | A shot reached an entity (not scenery, not splash). Cancelled: the flight ends but nothing is damaged (impact tells damage 0, applied false). | ## Engines Web and the native player (Rust). The manual return, `recall` and `aimFromView` of the launch verb are Rust only. ## When it does not do what you expect - `launch` answers `null`: the owner is unknown, the pool is full (`maxActive`) or `projectile.launch` was cancelled. - No damage: the shot hit scenery, expired (`lifetime`), or the target is unknown to `combat.health`; read `projectile.impact`. - The shot passes through its owner: by design, the owner is never hit. ## Limits No area query beyond `splash` and `chain`. A manual returning shot keeps at most 16 victims in its ledger and cannot also home, bounce or be a mine. ## Versions Kit 1.8.0 (Rust direct contacts go through the shared defense of `combat.defense`), 1.7.0 (`aimFromView`), 1.6.0 (manual returns and `recall`), 1.5.0 (mines), 1.4.0 (returning throws), 1.3.0 (per-shot behaviours), 1.2.0 (hooks). Requires `physics.port` 1 and `game.engine` 1.