# Lifeline — health, damage & respawn kit
Drop-in health for anything that can get hurt (players, enemies, breakable props), with damage zones, heal zones, projectiles, respawning, events for your own scripts, and a large wardrobe of looks: **13 health bar styles, 7 damage-number styles (4 presets) and 5 mix-and-match hit effects**, all switched by changing one field. Multiplayer-safe: only the peer that owns an entity decides what happens to its health.

## Installing it into your world
The package is called **Lifeline** — asset `Lifeline.package`, guid `7b85ce05-3903-4374-b654-2d4ffea295a5`, MIT licensed. (Its showcase world is *Lifeline — Health, Damage & Respawn Kit*.)
One install, any of these ways:
- **From the ZeroMind library in the editor** — search for `health` or `Lifeline` and install the **Lifeline** package.
- **By guid, from the engine shell:**
```
zero zeromind installAsset 7b85ce05-3903-4374-b654-2d4ffea295a5
```
- **From Luau:**
```lua
tools.use("zeromind", "preview", "7b85ce05-3903-4374-b654-2d4ffea295a5") -- what it would write
tools.use("zeromind", "installAsset", "7b85ce05-3903-4374-b654-2d4ffea295a5") -- do it
```
- **From an agent:** `zeromind.install { guid = "7b85ce05-3903-4374-b654-2d4ffea295a5" }`.
It lands in your `/source` as `Lifeline.package/`, so after installing, every piece resolves by that name: `Lifeline.Health`, `Lifeline.LifelineHUD`, `Lifeline.DamageZone`, `Lifeline.HealZone`, `Lifeline.Projectile`, `Lifeline.ProjectileLauncher`, `Lifeline.SpawnPoint`, and `require("Lifeline.api")` / `require("Lifeline.bars")`. Nothing in it is world-specific — you bring the entities. Run `zeromind.update` later to pull new versions.
## Five-minute start
**1. Give things health.** Add `Lifeline.Health` to the player body on your scene's PlayerPrototype, and to any enemy or prop. Put enemies and props on **synced** entities (`entity.spawnSynced`) so every player sees the same health.
```lua
body.component.add("Lifeline.Health", { maxHealth = 100, regenRate = 5, maxShield = 25 })
crate.component.add("Lifeline.Health", { maxHealth = 40, onDeath = "remove" })
```
**2. Show it.** Add `Lifeline.LifelineHUD` to one plain (non-synced) entity in the scene. Every peer runs its own copy.
```lua
entity.spawn("HUD").component.add("Lifeline.LifelineHUD", { playerBar = "hearts", worldBar = "overhead" })
```
**3. Hurt and heal.** Add a zone to any entity. It's a box of `sizeX × sizeY × sizeZ` around the entity and moves with it.
```lua
lava.component.add("Lifeline.DamageZone", { sizeX = 4, sizeZ = 4, kind = "fire", amount = 5, mode = "perSecond" })
spikes.component.add("Lifeline.DamageZone", { kind = "spikes", amount = 25, mode = "onEnter" })
pad.component.add("Lifeline.HealZone", { amount = 10, interval = 0.5 })
```
**4. From code.**
```lua
local Lifeline = require("Lifeline.api")
Lifeline.damage(target, 20, { kind = "fire", source = attacker, crit = false })
Lifeline.heal(target, 15)
Lifeline.fire { origin = muzzlePos, direction = aim, damage = 15, source = shooter } -- projectile
Lifeline.on("died", function(e) print(e.target, "died to", e.kind) end)
```
**5. Respawn.** Dead players come back after `respawnDelay` seconds at a random free `Lifeline.SpawnPoint` (or at the scene's `PlayerSpawn` if you haven't placed any), with full health and a moment of spawn protection.
That's it. The `scenes.main` showcase in this world uses every piece.
## What happens on death (`onDeath`, per entity)
| value | effect |
|---|---|
| `auto` (default) | `respawn` for players, `reset` for everything else |
| `respawn` | back at a spawn point after `respawnDelay`, full health |
| `reset` | back where it started after `respawnDelay`, full health |
| `remove` | disappears after `removeDelay` |
| `stay` | stays dead until `Lifeline.revive(target)` |
## Health fields (most useful)
`maxHealth`, `health`, `maxShield`/`shield` (soaks damage first), `regenRate` + `regenDelay`, `shieldRegenRate` + `shieldRegenDelay`, `invulnerabilityTime` (i-frames after a hit; damage-over-time ticks ignore it), `invulnerable` (god mode → "IMMUNE"), `armor` (flat reduction → "BLOCKED"), `respawnDelay`, `spawnProtection`, `displayName`, `team`, `barStyle` (bar drawn over this entity, `none` hides it), `bossBar` (show the big boss bar when near), `bodyHeight`/`bodyRadius` (bar placement and hit volume), `killBelowY`. Read-only: `isDead`, `deaths`.
## Events
`Lifeline.on(name, fn)` fires on **every** peer for `damaged`, `healed`, `blocked`, `died`, `respawned`, or `"*"` for all. The payload is `{ event, target, amount, shieldAmount, kind, source, crit, health, shield, maxHealth, reason, origin, pos, isPlayer, name }`. It returns a connection with `:Disconnect()`.
Each Health component also exposes typed events: `entity.component.get("Lifeline.Health").events.died:connect(fn)`.
## Styles: change one field
On `LifelineHUD` (or at runtime per player with `Lifeline.setStyle { bar = …, worldBar = …, number = …, feedback = … }`):
- **Bars** (`playerBar`, `worldBar`, Health's `barStyle`): `classic` (lost chunk drains away), `segmented`, `ring`, `hearts` (half hearts, shield hearts, heartbeat at low HP), `boss`, `overhead`, `minimal`, `stacked` (shield on health), `scifi`, `fantasy`, `cartoon`, `pixel`, `orb`.
- **Numbers** (`numberStyle`): `classic` (pop / shaky crit / green heal / IMMUNE-BLOCKED), `combo` (hits on one target add up into a running total), `comic`, `minimal`.
- **Feedback** (`feedback`, any mix): `flash shake vignette heartbeat direction`, or `all` / `none`.
## Multiplayer & anti-cheat
Health fields are `Sync`. Only the entity's owner mutates them, and the relay refuses writes from anyone else — so one player cannot set another player's health from their own machine.
- **Hit something you own** (your avatar, or a prop your peer took) — it changes on your machine and the new value goes on the wire. Every other peer draws exactly that number: health bars, numbers and death screens all read the same synced field.
- **Hit something another player owns** — `Lifeline.damage` doesn't decide anything. It sends a request to that entity's owner over `multiplayer.send`, and the owner validates it before applying. `Lifeline.setDamageFilter(function(comp, amount, info, fromPeer) ... end)` is where that validation goes: return the amount to allow (clamped if you like), or 0 to refuse. `fromPeer` is set only when the hit arrived from another peer's request.
- **Zones** run on every peer but act only on entities that peer owns, so a player in a fire zone is burned exactly once, by their own machine. A player's damage events are broadcast by the owner, so remote players see the same flash, numbers and score hooks.
- **Events** (`Lifeline.on`) fire on every peer — same channel the kit uses for its own visuals.
**The honest limit:** the engine's model is that the owning peer is the authority for its own entities. That is what stops *other* players from touching your health, and it is what this kit is built on. It does not, by itself, stop a modified client from lying about *its own* health (a hacked client could ignore a fire zone). If your game needs damage that a cheating client can't dodge, run the damage on a peer you control and funnel it through `setDamageFilter` — the filter runs on the owner, so it's the place to require proof, rate-limit, or refuse anything that doesn't match your own simulation.
## Other hooks
`Lifeline.kill`, `Lifeline.revive`, `Lifeline.get(target)`, `Lifeline.all()`, `Lifeline.isAlive`, `Lifeline.setSpawnPicker(fn(comp, points) -> entity)`, `Lifeline.kinds` (damage kinds → colour/label, add your own).
## Contents
`Health`, `DamageZone`, `HealZone`, `Projectile`, `ProjectileLauncher` (player blaster on a key, or an auto turret), `SpawnPoint`, `LifelineHUD` components, plus the `api`, `bars`, `numbers`, `feedback` and `zone` modules.