# An unkillable hunter (enemy.stalker) ## What it is for A persistent hunter that cannot be killed: an NPC that roams ever closer to where the player is, listens for every noise, searches, and chases on sight with the perception of `stealth.detection`. After a while it withdraws to its lair, rests out of sight, then comes back. It cannot perceive the player in a safe room (`horror.sanity`). Catching the player is an event the game turns into damage or a loss. For survival horror, chase sequences and hunted stealth levels. Shared concepts of the family are in the [Enemies in your game](guide:enemies) guide. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "enemy.stalker" } gripforge_gamekit_configure { project_id: "gkp_…", id: "enemy.stalker", config: { "huntSeconds": 90, "restSeconds": 30 } } ``` Needs `stealth.detection`, `npc.core`, `game.engine`; installing the kit brings them along. Give the stalker NPC the initial behaviour `stalker_roam` and the component below. ## First example A stalker hunts for a short time, goes back to its lair (where it stood), rests hidden, then returns. The stalker tells each change of phase. ```json { "config": { "huntSeconds": 5, "restSeconds": 0.5 }, "npc": { "stalker": { "huntSeconds": 0.25 } } } ``` ```text phase("e2") -> "hunt" stalker.phase = hunt, stalker.near = true 20 ticks -> stalker.retreated (hidden, stalker.phase = rest) 32 ticks -> stalker.returned ``` ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `huntSeconds` | 90 | Time it hunts before withdrawing (not while chasing). | | `restSeconds` | 30 | Time it rests in its lair, out of sight, before coming back. | | `roamRadius` | 10 | It roams to points this close to the player (m). | | `retreatSeconds` | 25 | Time given to reach its lair; after that it rests where it stands. | | `retreatOnCatch` | `true` | After catching the player it withdraws (a breather); otherwise it goes on. | | `catchDamage` | 0 | Damage dealt when it catches the player, through `combat.damage`; 0: none, the game decides on `stealth.caught`. | | `invulnerable` | `true` | Damage to it is cancelled. Turn it off and the stalker can die. | | `perceiver` | fov 120, range 18, hearing 1.5, catch 1.3 | Senses of a stalker that has no perceiver component of its own. | Component on the NPC: `stalker { "lair": [0, 0, -30], "huntSeconds": 120 }` (also `restSeconds` and `roamRadius`; the lair defaults to where it appeared). ## Services, events, variables - Service `enemy.stalker`: `stalkers()` (a list of `{ entity, phase, until, state, distance }`), `phase(entity)`, `retreat(entity)`, `summon(entity, at?)` (back to the hunt, searching a point; false when a hook cancels). - Verbs and conditions: `summon_stalker` (`at`), `stalker_retreat`, `stalker_phase` (hunt, retreat, rest). - Events: `stalker.spotted`, `stalker.caught` (`entity`, `target`), `stalker.retreated`, `stalker.returned`. It listens to `stealth.state`, `stealth.caught`, `entity.spawned`. - Variables: `stalker.phase` (hunt, retreat, rest), `stalker.distance`, `stalker.near` (a hunting stalker within 10 m). ## Hooks and modding | Hook | Meaning | |---|---| | `stalker.catch` | A stalker is about to catch the target it sees; `damage` is mutable; cancelled, nothing happens and it goes on hunting. | | `stalker.retreat` | A hunting stalker is about to withdraw to its lair; cancelled, it goes on hunting. | | `stalker.hunt` | A stalker is about to start a hunt (its rest is over, or `summon()` called it); `huntSeconds` is mutable; cancelled, it stays as it is. | Moddable: every setting above (no collection). ## Limits Runs on the web player and the native player; Godot, Unity and Unreal have no native delivery of this kit. Its random draws come from a seeded stream saved with the game. The stalker never dies by default; it sees nothing in a safe room. ## Versions Kit 1.1.0 (hooks and `retreatSeconds` in 1.1.0); service `enemy.stalker` 1.0.0. It relies on `stealth.detection` ^1, `npc.behavior` ^1, `npc.locomotion` ^1 (from `npc.core`) and `game.engine` ^1.