Targeted attacks
Attacks that lock a target for MOBA, RTS and tower defense: a cancellable windup, then a melee hit or a homing projectile, with damage exactly at impact.
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). 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 #
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 #
<!-- test: kits/game_engine/host/tests/parity.rs::rust_host_matches_the_typescript_traces (fixture combat.attacks.duel) --> 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).
{ "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 asattack_1, ornull. 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 withphase(winduporflight),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; addsapplied,amount,killedfromcombat.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 #
startanswersnull: the game is not in play, the target is out of reach, the source is busy or on cooldown, orattack.startwas cancelled.- No damage on a ranged attack: it expired after
lifetimeor lost its target; readcombat.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.