NPC damage, death and interaction
Hurt, kill and revive NPCs, react to hits and deaths, and handle a player pressing the talk key at one.
The server keeps each NPC’s health. Players’ hits reach it after the server checks them, your script can change it, and events tell you when an NPC is hurt, dies, comes back or is spoken to.
Events.on("npcDeath", (npc, attacker) => { const by = attacker instanceof Player ? attacker.nickname : attacker instanceof Npc ? attacker.name : "nobody"; console.log(`${npc.name || npc.id} was killed by ${by}`);});Read and set health
Section titled “Read and set health”npc.health; // current, clamped to maxHealthnpc.maxHealth; // what it starts with and is revived to; read-onlynpc.alive; // false once health reaches zeronpc.invulnerable; // refuse damage before it reaches the ledger
npc.health = npc.maxHealth; // heal outrightPass health and maxHealth to Npc.create to change the starting values.
Hurt, kill and revive
Section titled “Hurt, kill and revive”npc.damage(25, player); // takes 25, credits playernpc.kill(player); // outright, even through invulnerablenpc.revive(); // back at full health| Call | Does | Refused when |
|---|---|---|
damage(amount, attacker?) |
Takes health, raises npcDamage, and npcDeath if it was the last. |
The NPC is invulnerable or already dead. |
kill(attacker?) |
Same path, ignoring invulnerable. |
|
revive() |
Brings a dead NPC back at full health; clients make a fresh body. |
The attacker is an optional player handle or id, used only to fill in the
events. A dead NPC stays an entity: the corpse stays, the handle resolves, and
players can search it if lootable is on. remove() or revive() it when you
are done.
Player melee, arrows and NPC attacks can damage an NPC. For melee, the
victim’s simulator resolves native contact and the server checks the accepted
swing before changing health. npcDamage reports the amount actually taken.
See NPC combat to give an NPC an attack order.
NPC events
Section titled “NPC events”| Event | Arguments | When |
|---|---|---|
npcSpawn |
npc |
Right after an NPC is created or adopted, by any script. |
npcDestroy |
npc |
While it is being removed. The handle still reads. |
npcIntentDone |
npc, status |
Its order ended; see Move NPCs. |
npcDamage |
npc, attacker, amount |
Health came off. |
npcDeath |
npc, attacker |
The last of its health went. |
npcRevive |
npc |
A dead NPC was brought back. |
npcInteract |
npc, player |
A player pressed the talk key at it. |
npcSimulatorChange |
npc, player |
The client running it changed; player is null when it went dormant. |
Damage and death events use Player | Npc | null for attacker.
The npcSimulatorChange player is still Player | null. Check the type
before reading a player-only property such as nickname. Every event fires for every NPC on the server, including other
resources’ NPCs: keep a set of your ids and return early for the rest.
React to a hit
Section titled “React to a hit”Your game mode decides whether an NPC should counterattack, flee or keep its order. Here a guard’s partner runs when the guard is hit:
const partners = new Map<number, number>(); // npc id -> partner's id
Events.on("npcDamage", (npc, attacker, amount) => { const partnerId = partners.get(npc.id); if (partnerId === undefined || !attacker) return;
console.log(`${npc.name} took ${amount.toFixed(0)}, ${npc.health.toFixed(0)} left`); Npc.getById(partnerId)?.flee(attacker.position, { speed: "run", radius: 30 });});Talk to an NPC
Section titled “Talk to an NPC”npcInteract fires when a player presses the talk key (T by default,
rebindable) within about three metres of an NPC while facing it. The server
checks the distance, so a far-off claim never reaches your handler. Only NPCs
with interactable on (the default) raise it.
Events.on("npcInteract", (npc, player) => { npc.lookAt(player); npc.say(`Well met, ${player.nickname}.`);});From here you usually open a dialogue or a shop; the NPC shop tutorial does both.
Watch the simulator change
Section titled “Watch the simulator change”Events.on("npcSimulatorChange", (npc, runner) => { console.log(`${npc.name || npc.id}: ${runner ? runner.nickname : "dormant"}`);});Most resources never need this. It helps with debugging, and with noticing that a pinned actor’s player walked away mid-scene. See Spawn NPCs.
Patrol outcomes
Section titled “Patrol outcomes”Named and point-array patrols also raise patrolWaypoint(npc, info) and
patrolFinished(npc, info). These include the route ID and waypoint state.
See Named patrol routes for statuses and
how they relate to npcIntentDone.
Inventory and harvest events
Section titled “Inventory and harvest events”npcInventoryReady(npc) fires when the starting inventory is ready.
npcInventoryChanged(npc, change) reports committed changes, including loot
transfers. npcHarvested(npc, player) fires when a player finishes harvesting an
animal. See Corpse loot for scripted stock and persistence.
Related
Section titled “Related”- Spawn NPCs: options, simulation and pinning.
- Move NPCs: orders and
npcIntentDone. - Dialogue choices: what to open on the talk key.
- Events and handlers: how
Events.onworks.