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.

Source: module-kits:kits/combat_attacks/usage/en.mdView Markdown source

Also read offline — CLI: grip-forge docs combat-attacksMCP tool: gripforge_docs { "topic": "combat-attacks" }

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 #

SettingDefaultMeaning
windup0.25Seconds between start and the release (0 to 3, never longer than the cooldown).
cooldown1Seconds before the same source can start again (0.1 to 20), taken at start.
rangeTolerance0.35Metres of forgiveness at the release frame, added to the target radius.
lifetime6Maximum flight time in seconds; expiry deals no damage.
maxActive512Attacks 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 #

HookMutableEffect
attack.startdamage, range, cooldown, windup, projectileSpeedA valid attack is about to start. Cancelled: start answers null, no cooldown is taken.
attack.hitdamageA 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.