Appearance
Clientside NPCs clientside
The NPC this for clientside NPC scripts and triggerAction (npc.client.d.ts), on top of the client globals.
Source
Generated from templates/server/data/scripts/npc.client.d.ts. To change this page, edit the JSDoc in that file.
Overview
Ambient declarations for CLIENTSIDE NPC scripts (the clientScript baked into a level's NPCs). NPC scripts also see the weapon client globals (weapons/globals.client.d.ts) — player is still the LOCAL player, and echo/findimg/keydown/timers all work.
Inside every handler, this is the NPC as seen by THIS client (use function declarations, not arrow functions). Property writes are client-local: they change what this client sees and never go on the wire. Unknown properties are a per-NPC state bag that persists between calls.
export function onCreated(): void
The NPC appeared on this client (level entered, or hot reload).export function onPlayerEnters(player: ChatPlayer): void
A player entered the level (the local player included, right after onCreated).export function onPlayerChats(player: ChatPlayer, chat: string): void
A player chatted. /-prefixed commands arrive here too (they are not shown as bubbles).export function onUpdate(dt: number): void
Every frame; dt is the frame time in seconds.export function onKeyPressed(key: string): void
A key went down (once per press — held keys don't repeat). Same key names and rules as for weapons (see weapons/globals.client.d.ts).export function onAction<Name>(...params: any[]): void
A serverside level.triggerAction hit this NPC. <Name> is the action name with its first letter uppercased.export function onPMReceived(sender: PMSender): void
A PM arrived for the local player (notification only — no text), same as for weapons (see weapons/globals.client.d.ts).export function onShotAt(x: number, y: number, data: any): void
A projectile stopped in this level (blocking tile or lifetime expiry) at (x, y) — level tiles, gmap-global on a gmap. Fires on every clientside NPC script and every weapon;datais the shoot payload.export function onShot(data: any): void
A projectile hit THIS NPC's shape. Fires on this NPC's clientside script on every client (and its serverside script on the server).export function onMovementFinished(): void
A clientside this.move() with option 8 ended (reached or blocked). Moves started by the serverside script fire it serverside only.
setTimeout/setInterval/sleep work per-NPC: timer callbacks keep this bound to the NPC, and timers die when the NPC unloads (level change or hot reload).
Declarations
triggerAction function
ts
declare function triggerAction(x: number, y: number, action: string, ...params: any[]): voidAsks the server to fire onAction<Name> on the serverside script of every NPC whose shape contains (x, y) — tile units. The serverside handler receives (player, ...params) with the triggering player first. Strict Graal routing: nothing runs clientside from this call.
NpcThis interface
ts
interface NpcThisthis inside a clientside NPC handler: this client's copy of the NPC. Writes are local to this client (the server's copy is the authority for everyone else).
NpcThis.id
ts
readonly id: numberRuntime id of this NPC (unique per server run).
NpcThis.name
ts
readonly name: string"npc-<id>": a client-side identifier for this NPC.
NpcThis.x
ts
x: numberPosition in tiles (fractional allowed). Assigning moves the NPC on this client only and cancels any move(). While a move() runs (serverside or clientside) these read the interpolated position.
NpcThis.y
ts
y: numberPosition in tiles (fractional allowed). Assigning moves the NPC on this client only and cancels any move(). While a move() runs (serverside or clientside) these read the interpolated position.
NpcThis.dir
ts
dir: numberFacing: 0 up, 1 left, 2 down, 3 right (Graal convention). Assigning is client-local.
NpcThis.move
ts
move(dx: number, dy: number, time: number, options?: number): voidGraal's move(dx, dy, time, options) on THIS client only: glides the NPC by (dx, dy) tiles over time seconds. A later serverside move or position change overrides it.
Options is a bitmask (Graal's move flags; combine with |):
ts
1 cache — queue behind the moves already pending instead of
replacing them (without it, pending moves are dropped
and this one starts from the current position)
2 append — dx/dy are measured from the end of the queued path
instead of the current position
4 blockcheck — stop at the last clear spot when the NPC would walk
into a wall (a character NPC's walking footprint, else
its shape/image); drops the rest of the queue
8 onMovementFinished fires when this move ends (reached or blocked)
16 apply direction — face the move's dominant axis when it startstime <= 0 moves instantly (on the next update). Assigning x or y cancels every pending move.
NpcThis.image
ts
image: stringAsset-relative image, e.g. "images/sign.png". '' = invisible (unless showCharacter).
NpcThis.chat
ts
chat: stringChat bubble text on this client ('' clears it).
NpcThis.head
ts
head: stringAppearance when rendered as a character ('' = the gani defaults).
NpcThis.body
ts
body: stringAppearance when rendered as a character ('' = the gani defaults).
NpcThis.colors
ts
colors: string[]Body colors as 'r,g,b' strings, like player.colors: [0] skin, [1] coat, [2] sleeves, [3] shoes, [4] belt. Assigning an index or an array changes them on this client only (batched like the other props); invalid indices or values are ignored.
NpcThis.ani
ts
ani: stringCurrent animation name; only visible after showCharacter().
NpcThis.showCharacter
ts
showCharacter(): voidRenders the NPC as a gani character (idle) on this client only.
NpcThis.setAni
ts
setAni(name: string): voidPlays an animation on this NPC on this client only.
NpcThis.dontblock
ts
dontblock(): voidGraal dontblock() on THIS client only: the local player and this client's NPC moves pass through it. The serverside this.dontblock() applies for everyone (and overrides this on its next change).
NpcThis.blockagain
ts
blockagain(): voidGraal blockagain() on this client only: undoes dontblock().
NpcThis.blocking
ts
readonly blocking: booleanFalse after dontblock() (this client's view).
NpcThis.setShape
ts
setShape(x: number, y: number, w: number, h: number): voidSets this client's copy of the trigger hitbox: offset and size in PIXELS relative to the NPC's top-left. Note the server hit-tests its OWN shapes for triggerAction, so a client-local setShape does not change what triggers hit.
NpcThis.drawaslight
ts
drawaslight(): voidMarks this NPC as a light source on this client. Only visible while the ambient light is below full (see setambient) unless lightmode is 1. The light follows this.x/y, and blocking (type-22) tiles eat it far faster than air, so walls cast shadows. One-way like showCharacter(); turn the light off with this.lightintensity = 0.
NpcThis.lightcolor
ts
lightcolor: stringLight color as 'r,g,b' (0-255 each). Default '255,255,255'.
NpcThis.lightintensity
ts
lightintensity: numberBrightness at the source: 1 = full. Values above 1 overdrive the core so full brightness extends further out (the lightmap clamps at 1). Default 1, max 10.
NpcThis.lightradius
ts
lightradius: numberDistance in tiles at which the light fades out in open air. Default 8, max 48.
NpcThis.lightshape
ts
lightshape: stringFalloff shape of the light. Default 'circle'.
ts
'circle' — round glow
'diamond' — pointed on the axes
'square' — even brightness out to a square edge
'cone' — directional wedge, aimed with lightdir/lightarc
'ring' — glowing band at ~2/3 radius, dark centerEvery shape is still blocked by walls.
NpcThis.lightdir
ts
lightdir: numberCone aim in degrees: 0 = up, 90 = right (clockwise). Default 0.
NpcThis.lightarc
ts
lightarc: numberCone width in degrees (the full wedge). Default 90, max 360.
NpcThis.lightmode
ts
lightmode: number0 (default): the light only shows where setambient has darkened the world. 1: the light is also drawn as an additive glow on top of the scene, the
ts
same by day or night, so it stays visible at full ambient. At night it
still lights the tiles under it like mode 0. Additive saturates fast:
use a lower lightintensity (0.3-0.6) for a subtle daytime glow.NpcThis.join
ts
join(name: string): booleanJoins this script to a class's clientside half (scripts/classes/<name>.client.ts): the class's exported handlers fire after this script's own, its exported helpers become callable on this, and its onCreated runs now with this script as this. Serverside joins replicate here automatically. Returns false when the class has no clientside half.
NpcThis.leave
ts
leave(name: string): booleanRemoves a joined class's handlers from this script.
NpcThis.joinedclasses
ts
readonly joinedclasses: readonly string[]Currently joined class names, in join order.
NpcThis.[key]
ts
[key: string]: anyAnything else is per-NPC script state, kept between handler calls.