Stalker
Usage guide of enemy.stalker: a persistent hunter that roams, listens, chases, withdraws and comes back, settings and defaults, service, events, verbs and hooks.
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.
Turn it on #
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 #
<!-- test: kits/game_engine/host/tests/enemy_stalker.rs::a_stalker_hunts_withdraws_rests_and_comes_back --> 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.
{ "config": { "huntSeconds": 5, "restSeconds": 0.5 },
"npc": { "stalker": { "huntSeconds": 0.25 } } }
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 tostealth.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.