# Boss fights (enemy.boss) ## What it is for Boss fights as data: health-gated phases that cycle telegraphed patterns (slam, sweep, lunge, expanding rings and summons), with an intro, a boss health bar and a defeat event. A boss is an enemy of `enemy.ai` whose document names a boss document. 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.boss" } gripforge_gamekit_configure { project_id: "gkp_…", id: "enemy.boss", config: { "introSeconds": 1.5, "telegraphScale": 1 } } ``` Needs `enemy.ai`, `combat.melee`, `combat.core`, `game.engine`; installing the kit brings them along. ## First example An enemy names a boss document; the boss has one phase and one pattern. This is the shape the test builds (an optional `recovery` of 0 to 60 seconds follows a pattern; a nova applies it only after its last ring). ```json { "enemies": [{ "id": "keeper", "name": "Keeper", "health": 100, "boss": "keeper", "attacks": [] }], "bosses": [{ "id": "keeper", "name": "Keeper", "patterns": { "slam": { "type": "slam", "damage": 20, "radius": 4, "windup": 0.8, "at": "target" } }, "phases": [{ "id": "only", "untilHealth": 0, "patterns": ["slam"], "pause": 1.5 }] }] } ``` ## Settings and defaults | Setting | Default | Meaning | |---|---|---| | `introSeconds` | 1.5 | Seconds the boss waits after spawning (0 to 10). | | `telegraphScale` | 1 | Multiplies every pattern windup (0.25 to 3). | A document of `bosses` holds `patterns` (id to pattern) and `phases` (`id`, `untilHealth`, `patterns`, `pause`, `enrage`). A pattern has a `type`: `slam` (`damage`, `radius`, `windup`, `at`), `sweep` (`range`, `arc`), `lunge` (`distance`, `width`), `nova` (`rings`, `radiusStep`, `interval`) or `summon` (`enemy`, `count`); each has an optional `recovery`. The boss model is bound to the asset slot `boss_model`. ## Scripted end A fight the story decides (a battle that must be lost, a boss that flees, a scene that takes over before the last blow) is an optional `end` on the boss document, instead of a death: ```json { "id": "breaker", "name": "The Breaker", "patterns": { "sweep": { "type": "sweep", "damage": 25, "range": 4, "arc": 160, "windup": 0.9 } }, "phases": [{ "id": "only", "untilHealth": 0, "patterns": ["sweep"], "pause": 1.2 }], "end": { "at": 0.1, "playerDefeat": "end", "hold": 2 } } ``` | Field | Default | Meaning | |---|---|---| | `at` | none | Health ratio (0 to 1) at or below which the fight ends; a lethal blow ends it too and leaves the boss that fraction of its health. | | `playerDefeat` | `die` | `end`: a lethal blow on the player while this boss is the active one ends the fight too; the player keeps 1 health and no `player.died` is emitted, so checkpoints and end screens do not react. | | `hold` | 2 | Seconds the player takes no damage after the end (0 to 30). | Once the end is accepted the boss stands still for good, plays no more patterns and takes no more damage, and `boss.ended` is emitted once per fight. Start what follows from that event, for instance a trigger that plays a cinematic. Without `end` nothing changes: the boss dies and `boss.defeated` is emitted. ## Services, events, variables - Events: `boss.started` (`entity`, `boss`, `name`), `boss.phase` (`entity`, `boss`, `phase`), `boss.pattern` (`entity`, `boss`, `pattern`, `type`), `boss.defeated` (`entity`, `boss`), `boss.ended` (`entity`, `boss`, `reason`: `threshold` or `player_down`). It listens to `enemy.spawned`, `combat.killed`, `entity.despawned`, and `combat.damaged` when a boss document has `end`. - Variables: `boss.name`, `boss.health`, `boss.max`, `boss.phase` (they feed the boss bar). - Component `boss { "doc": "warden" }`: on an enemy instance, makes it fight as that boss even when its enemies document names none. ## Hooks and modding | Hook | Meaning | |---|---| | `boss.start` | An enemy is about to become the active boss; cancelled, it fights with its patterns but is not announced and takes no boss bar. | | `boss.phase.change` | The health ratio puts the boss in another phase; `phase` is mutable (the id of another phase of the document); cancelled, it stays in the current one. | | `boss.pattern.play` | The boss is about to play the next pattern of its phase; `pattern` and `telegraphScale` are mutable; cancelled, the pattern is skipped and the boss pauses. | | `boss.end` | The fight of a boss with `end` is about to end (`reason`, `ratio`); cancelled, the fight goes on as without `end` for that reason and it is not asked again. | Moddable: both settings and the collection `bosses`. ## Limits Runs as the same Rust logic on the web, in the native player, Godot, Unity and Unreal. The hooks, the optional `recovery` and the scripted `end` are served by the web and native Rust logic; the Godot, Unity and Unreal deliveries keep the earlier fixed recoveries and do not implement `end`. With `playerDefeat`, only the local player is watched: in co-op the other players still go down as usual. Unbound, the boss is drawn as a large capsule: bind a rigged model to `boss_model`. ## Versions Kit 1.6.0 (hooks in 1.4.0, optional `recovery` in 1.5.0, scripted `end` in 1.6.0); service `enemy.boss` 1.0.0. It relies on `enemy.behaviors` ^1 (from `enemy.ai`), `combat.melee` ^1, `combat.health` ^1 and `game.engine` ^1.