# Target-locked attacks (combat.attacks) ## What it is for `combat.attacks` is the attack of a unit that picks a target and hits it: a minion, a tower, a hero auto-attack, an RTS soldier. `start` begins a windup; at the release frame a melee attack hits at once and a ranged one launches a projectile that homes on its target at `projectileSpeed`. The hit goes through `combat.damage`, so teams, shields, statuses and modifiers of `combat.core` apply (see the [combat guide](guide:combat)). A windup is cancelled when its source or its target stops being valid or leaves reach; a flying projectile survives the death of its source. The presentation draws a lit trail from the attacker to the target for each projectile (a thin arrow, an orb or a heavy shot, in the color of the attack) and never deals damage. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "combat.attacks" } gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.attacks", config: { "windup": 0.25, "cooldown": 1, "lifetime": 6 } } ``` It requires `combat.core` (health and damage) and `game.engine`. ## First example Register two fighters with `combat.health`, then start an attack. The answer is the attack id, or `null` when the attack is refused (not playing, target out of reach, source busy or on cooldown, pool full). ```json { "op": "call", "service": "combat.health", "method": "register", "args": ["e2", 40, "enemy"] } { "op": "call", "service": "combat.attacks", "method": "start", "args": [{ "source": "e1", "target": "e2", "damage": 7, "range": 2 }] } ``` Set `projectileSpeed` above 0 to make it a homing shot instead of a melee hit. ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `windup` | `0.25` | Seconds between `start` and the release (0 to 3, never longer than the cooldown). | | `cooldown` | `1` | Seconds before the same source can start again (0.1 to 20), taken at `start`. | | `rangeTolerance` | `0.35` | Metres of forgiveness at the release frame, added to the target radius. | | `lifetime` | `6` | Maximum flight time in seconds; expiry deals no damage. | | `maxActive` | `512` | Attacks in progress at once (16 to 2048). | All five are moddable. ## Services Service `combat.attacks`: - `start({ source, target, damage, range, cooldown?, windup?, projectileSpeed?, launchHeight?, kind?, tags?, color?, style? })`: returns an id such as `attack_1`, or `null`. Missing numbers take the settings. - `cancel(source)`: cancels the windup of that source and gives its cooldown back (a flight is not cancelled). - `busy(source)`: true while the source has a windup running (a flight does not keep it busy). - `cooldown(source)`: seconds left. - `snapshot()`: the attacks in progress with `phase` (`windup` or `flight`), `remaining`, `position`, `origin`, `age`, `ranged`. ## Events - `combat.attack.started`: a windup began. - `combat.attack.released`: the windup ended in reach; a melee hit lands at once, a projectile leaves its origin. - `combat.attack.impact`: the attack reached its target; adds `applied`, `amount`, `killed` from `combat.damage`. - `combat.attack.cancelled`: a windup cancelled, a flight that expired or lost its target, or a hit cancelled by a tap. Every payload carries the attack as `snapshot()` tells it. ## Hooks and modding | Hook | Mutable | Effect | |---|---|---| | `attack.start` | `damage`, `range`, `cooldown`, `windup`, `projectileSpeed` | A valid attack is about to start. Cancelled: `start` answers `null`, no cooldown is taken. | | `attack.hit` | `damage` | A released attack reached a living target. Cancelled: a miss, ended by `combat.attack.cancelled`. | ## Engines Web and native player (Rust). Godot, Unity and Unreal are not adapters of this kit. ## When it does not do what you expect - `start` answers `null`: the game is not in play, the target is out of reach, the source is busy or on cooldown, or `attack.start` was cancelled. - No damage on a ranged attack: it expired after `lifetime` or lost its target; read `combat.attack.cancelled`. ## Limits One windup at a time per source. No area damage and no aiming without a target: use `combat.projectiles` or `combat.melee` for those. ## Versions Kit 1.1.0, service contract 1.0.0. Requires `combat.health` 1, `combat.damage` 1 and `game.engine` 1.