# Target lock-on (combat.lockon) ## What it is for `combat.lockon` is the lock of action games: the player presses `lock_on` and the most relevant enemy becomes the target. A candidate is a living entity that carries one of `targetTags`, none of `ignoreTags`, stands within `maxDistance` and inside the cone `acquireAngle` in front of the camera; the nearest comes first. `lock_next` moves the lock around the player. While it holds, the free-look camera turns toward the target and the body keeps facing it, so the character strafes around it. The lock breaks on death, disappearance, distance, loss of sight (a ray through the physics port) or by hand. Even without a camera kit the lock still names a target for other kits (an aim, a HUD). The kit has no presentation. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "combat.lockon" } gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.lockon", config: { "maxDistance": 18, "breakDistance": 24, "relock": false } } ``` It requires `game.engine` and `input.actions`. Optional companions: `character.third_person` (free look and body facing), `combat.core` (a candidate must be alive for `combat.health`) and `enemy.ai` (its enemies carry the `enemy` tag). ## First example A player at the origin looks along +z. Two enemies stand about 3 m and 9 m ahead. `lock` takes the nearest, `locked` is true, the variables follow and one `lockon.acquired` event is emitted. Locking again on the same target is true and silent. ```json { "service": "combat.lockon", "method": "lock", "args": [] } { "service": "combat.lockon", "method": "target", "args": [] } ``` `lock` answers true; `target` answers the id of the nearest enemy. `lockon.active` is true, `lockon.target` is that id and `lockon.distance` is its distance rounded to a tenth of a metre. ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `maxDistance` | `18` | Metres: a candidate must be this close to be locked. | | `breakDistance` | `24` | Metres: the lock breaks (reason `distance`) beyond this; never below `maxDistance`. | | `acquireAngle` | `150` | Degrees of the cone in front of the camera for the first lock (360: any direction). | | `lineOfSight` | `true` | A target hidden behind a collider for `sightGrace` seconds breaks the lock (reason `sight`). | | `sightGrace` | `1.5` | Seconds a target may stay out of sight. | | `targetTags` | `["enemy"]` | An entity with any of these tags is a candidate. | | `ignoreTags` | `["dead", "player"]` | An entity with any of these tags is never a candidate. | | `cameraFollow` | `true` | Turn the free-look camera toward the target while locked. | | `cameraSpeed` | `6` | How fast the camera turns, per second (0 snaps). | | `strafe` | `true` | The body keeps facing the target. | | `relock` | `false` | When the target dies or leaves, lock the next candidate at once. | All are moddable. ## Services, events, variables - Service `combat.lockon`: `target()`, `locked()`, `lock(entity?)` (a named entity must be a living enemy in reach; none: the best candidate), `unlock(reason?)`, `next(direction?)` (1 or -1 moves around the player; without a lock it locks), `candidates()` (nearest first) and `yawTo()`. - Events `lockon.acquired` (`entity`, `target`, `distance`), `lockon.switched` (`entity`, `from`, `to`), `lockon.lost` (`entity`, `target`, `reason`: `manual`, `distance`, `sight`, `dead` or `gone`). The kit listens to `entity.despawned` and `combat.killed`. - Variables `lockon.active`, `lockon.target`, `lockon.distance`. - Actions `lock_on` (default keys `Mouse1` and `Tab`, gamepad button 11: locks, or releases when pressed again) and `lock_next` (`KeyC`, gamepad button 15: switches). - Script verbs `lockon_lock { target? }`, `lockon_release` and the condition `lockon_locked { target? }`. ## Hooks and modding | Hook | Mutable | Effect | |---|---|---| | `lockon.acquire` | `target` | The player is about to lock a target among `candidates`; name another entity (a boss the story wants first) or cancel: no lock, `lock` answers false. | | `lockon.lose` | none | The lock is about to break for `reason`; cancelled for `distance` or `sight` the lock holds; ignored for `manual`, `dead` and `gone`. | ## Engines Web and the native player (Rust); the kit has no Godot, Unity or Unreal adapter. ## When it does not do what you expect - Nothing locks: the candidate has no `targetTags`, has an `ignoreTags` tag (a dead enemy), is farther than `maxDistance`, or is outside the cone; try `acquireAngle: 360`. - The lock breaks at once: `breakDistance` is reached, or the target is behind a collider for longer than `sightGrace`. - The camera does not turn: `character.third_person` free look is not installed or `cameraFollow` is false. ## Limits One lock, for the player. No target indicator is drawn here: read `lockon.target` from your HUD. ## Versions Kit 1.0.0. Requires `game.engine` 1 and `input.actions` 1.