# Room encounters with waves (encounters.waves) ## What it is for Fights as data. When a room with an encounter is entered, waves of enemies appear at its spawn points after a short telegraph; the next wave comes once the previous one is cleared, and the room is cleared after the last wave. The enemies themselves come from `enemy.ai`. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "encounters.waves" } gripforge_gamekit_configure { project_id: "gkp_…", id: "encounters.waves", config: { "startDelay": 0.8, "telegraph": 0.6 } } ``` Needs `world.rooms`, `enemy.ai`, `game.engine`; installing the kit brings them along. ## First example An encounter of two waves: two grunts, then, 0.1 s after the first wave is cleared, one brute. Starting it announces the encounter, then each wave once its spawn markers have stood for `telegraph` seconds. ```json { "encounters": [{ "id": "pair", "waves": [ { "spawns": [{ "enemy": "grunt", "count": 2 }] }, { "delay": 0.1, "spawns": [{ "enemy": "brute", "count": 1 }] } ] }] } ``` ```text call encounters.waves.start("pair") -> true (an encounter without wave answers false) event encounter.started { encounter: "pair", room: "", waves: 2 } call encounters.waves.active() -> { id: "pair", wave: 1, waves: 2, remaining: 2 } event encounter.wave { encounter: "pair", wave: 1, count: 2 } ``` ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `startDelay` | 0.8 | Default seconds before a wave (a wave can set its own `delay`). | | `spread` | 1.2 | Random offset around a spawn point (m). | | `telegraph` | 0.6 | Seconds a spawn marker shows before its enemy appears. | | `countScaleVar` | `difficulty.enemy_count` | Game variable that multiplies the enemies of each spawn row (rounded, at least 1): scale by player count or by a difficulty menu. Unset or empty: 1. | The collection `encounters` holds documents `{ id, waves: [{ spawns: [{ enemy, count }], delay? }] }`. A scene can carry its own encounters (documents or ids): the first one starts when the scene is entered, at the instances tagged `encounter_spawn`, and a running encounter ends with its enemies when the scene is left. ## Services, events, variables - Service `encounters.waves`: `start(encounter)`, `active()`, `clear()`. - Verbs and conditions: `start_encounter` (`{ "start_encounter": "enc_crypt" }`; a running one is replaced). - Events: `encounter.started` (`encounter`, `room`, `waves`), `encounter.wave` (`encounter`, `wave`, `count`), `encounter.cleared` (`encounter`, `room`). It listens to `room.entered`, `enemy.killed`, `entity.despawned`. - Variables: `encounter.wave`, `encounter.waves`, `encounter.remaining`. ## Hooks and modding | Hook | Meaning | |---|---| | `encounter.start` | An encounter is about to start in a room (a pacified room, a fight the story skips); cancelled, no wave comes and the room is cleared like a room without encounter. | Moddable: the four settings and the collection `encounters`. ## Limits Runs as the same Rust logic on the web, in the native player, Godot, Unity and Unreal. The hook runs on the web and native players; on Godot, Unity and Unreal every encounter starts as usual. Spawn points keep away from every player, not only the first. ## Versions Kit 1.4.0 (hook and moddable settings in 1.4.0, `countScaleVar` in 1.3.0); service `encounters.waves` 1.3.0. It relies on `world.rooms` ^1, `enemy.behaviors` ^1 (from `enemy.ai`) and `game.engine` ^1.