Skip to content

Wander builtins

Every function a Wander script can call lives in one registry: name, typed parameters, return type, category, documentation and an example. The compiler checks calls against it (arity, types, did-you-mean), and this page is generated from it. 177 builtins in 24 categories.

Agents get the same information from wander_reference (the guide) and wander_reference {topic} (structured entries for a category or a function). For the language itself, read the Wander manual.

Category Builtins
2d play_anim, set_tile, tile_at
animation anim_state, foot_ik, hand_ik, look_at, play_animation, play_sequence, set_param, trigger, turn_in_place
audio music, play, play_sound, set_volume, stop_sound
character grounded, jump, walk
character2d drop_through2d, grounded2d, jump2d, move2d
color color, hsv
dialogue dialogue_advance, dialogue_choose, dialogue_var, start_dialogue
effects burst, camera_shake, flash, hit_stop, hit_stop_left, water_height
input action, axis, cursor_lock, key, key_pressed, pressed, quit_game, released
list clear, contains, first, index_of, insert, is_empty, join, last, pop, push, remove, remove_at, reverse, slice, sort, sorted, sum
locale locale, locales, set_locale, tr
map get, has, keys, set, values
math abs, acos, approach, asin, atan, atan2, ceil, clamp, cos, deg, exp, floor, inverse_lerp, lerp, ln, max, min, noise, pow, rad, round, sign, sin, smoothstep, sqrt, tan
navigation arrived, navigate, path_length, stop_navigation
physics impulse, overlap_sphere, push, raycast, torque, velocity
physics2d impulse2d, overlap2d, point2d, push2d, raycast2d, set_velocity2d, torque2d, velocity2d
random chance, pick, random, random_int, shuffle
render layer_mask, probe_bake
save delete_save, game_var, has_save, list_saves, load_game, save_game
scene add_tag, change_scene, children, count, current_scene, exists, find, find_all, has, load_additive, loading_progress, nearest, remove_tag, set_parent, spawn, tagged, unload_scene
text num, str, type_of, ends_with, lower, replace, split, starts_with, trim, upper
time is_paused, pause_game, resume_game, teleport, time_scale, unscaled_dt, unscaled_time
vector cross, direction, distance, dot, forward, length, normalize, right, up, vec, world_position
vehicle vehicle_drive, vehicle_shift, vehicle_speed, vehicle_state, vehicle_wheel

Subsystem triggers

Besides the core triggers (on start, on tick, on event, on key, on click, on frame, and on enter / on exit inside states), subsystems register these:

Trigger Fires when
on action An input action was pressed: on action "jump" (actions come from input.json).
on collide Two bodies touched: on collide ("name or tag")? — other, contact_point, contact_normal, impact.
on collide_end Two 2D bodies stopped touching: on collide_end — other. data: {}
on dialogue on dialogue "start" \| "line" \| "choice" \| "end" \| "&lt;command&gt;": conversation events and <<command>>s of .dialogue scripts (event "dialogue:...").
on impact A 2D body hit this one faster than physics2d_world.impactSpeed: on impact — other, data. data:
on loaded A save was loaded (load_game or the load_game tool): on loaded — data.slot, data.version, data.meta. Refresh what is derived from saved state (HUD, music). data:
on pause The game was paused (pause_game): delivered to every behavior, also those the pause stops.
on resume The game resumed (resume_game).
on saved A save_game() finished: on saved — data.slot, data.meta. data:
on scene_loaded A scene finished loading: on scene_loaded — data.id (alias or path, or a sub-scene's handle), data.path, data.additive. data:
on scene_unloading A scene is about to go: on scene_unloading — data.id, data.to (the next scene), data.additive. Delivered the tick before the change, to the leaving scene too. data:
on trigger_enter Something entered this trigger collider: on trigger_enter ("name or tag")? — other.
on trigger_exit Something left this trigger collider: on trigger_exit ("name or tag")? — other.
on ui on ui "Name": the button/toggle/slider/input named Name was used (event "ui:Name").

2d

play_anim

play_anim(entity: entity, clip: string, restart: bool?)

Plays a sprite_anim clip (keeps playing if it already is, unless restart). Frame events arrive as on anim "name"; a non-looping clip sends on anim "finished".

Parameter Type
entity entity
clip string
restart bool optional

Returns: none

play_anim(self, "run")

set_tile

set_tile(map: entity, position: vector|entity, tile: number|string, layer: string?)

Sets the tile at a world position: an id (0 clears) or a terrain from tilemap.autotile (auto-tiled).

Parameter Type
map entity
position vector|entity
tile number|string
layer string optional

Returns: none

set_tile(find("Farm"), self.position, "soil")

tile_at

tile_at(map: entity, position: vector|entity, layer: string?) -> number

Tile id of a tilemap at a world position (topmost non-empty layer, or the named layer); 0 = empty.

Parameter Type
map entity
position vector|entity
layer string optional

Returns: number

if tile_at(find("Farm"), self.position) == 3 then

animation

anim_state

anim_state(entity: entity) -> string

Name of the animator's current state.

Parameter Type
entity entity

Returns: string

if anim_state(self) == "idle" then

foot_ik

foot_ik(entity: entity, on: bool, weight: number?)

Turns automatic foot planting on or off (feet on stairs, slopes and rocks, pelvis lowered, feet locked while planted); the optional weight fades it (0..1). Adds the characterIk component if needed.

Parameter Type
entity entity
on bool
weight number optional

Returns: none

foot_ik(self, not swimming)

hand_ik

hand_ik(entity: entity, side: string, target: none|entity, weight: number?)

Makes a character's hand reach an entity ("left" or "right"): a grip point on a staff held in the other hand, a ledge, a rail, a door handle. none (or weight 0) releases it. Adds the characterIk component if needed.

Parameter Type
entity entity
side string
target none|entity
weight number optional

Returns: none

hand_ik(self, "left", find("Staff Grip"), 1)

look_at

look_at(entity: entity, target: none|entity, weight: number?)

Turns a character's head and upper spine toward an entity (look-at IK, clamped by animator.lookAtLimit), or stops with none; the turn fades in and out smoothly.

Parameter Type
entity entity
target none|entity
weight number optional

Returns: none

look_at(self, find("Player"), 0.8)

play_animation

play_animation(entity: entity, clip: string, fade: number?, loop: bool?)

Crossfades straight to a clip or state (seconds of fade, default 0.2).

Parameter Type
entity entity
clip string
fade number optional
loop bool optional

Returns: none

play_animation(self, "wave", 0.3)

play_sequence

play_sequence(entity: entity, start: number?)

Plays the entity's sequencer (a cutscene) from start seconds.

Parameter Type
entity entity
start number optional

Returns: none

play_sequence(find("Intro"))

set_param

set_param(entity: entity, name: string, value: bool|number)

Sets an animator controller parameter (blend spaces and transitions read them).

Parameter Type
entity entity
name string
value bool|number

Returns: none

set_param(self, "speed", 3)

trigger

trigger(entity: entity, name: string)

Fires an animator trigger (jump, attack, wave).

Parameter Type
entity entity
name string

Returns: none

trigger(self, "jump")

turn_in_place

turn_in_place(entity: entity, toward: number|vector|entity)

Turns a standing character in place toward a world yaw (degrees, 0 = -Z) or to face a point / entity, at characterIk.turnSpeed; planted feet stay locked and re-plant in small steps. Controllers can read the float turn (degrees left) and bool turning parameters to play turn clips.

Parameter Type
entity entity
toward number|vector|entity

Returns: none

turn_in_place(self, find("Door"))

audio

music

music(clip: string, fade: number?)

Crossfades the music to a clip ("" fades out); fade in seconds.

Parameter Type
clip string
fade number optional

Returns: none

music("audio/theme.wav", 2)

play

play(e: entity)

Starts the entity's audio component (its clip, volume, spatial settings).

Parameter Type
e entity

Returns: none

play(self)

play_sound

play_sound(clip: string, volume: number?)

Plays a one-shot sound at self (positional), e.g. a hit or a pickup.

Parameter Type
clip string
volume number optional

Returns: none

play_sound("audio/hit.wav", 0.8)

set_volume

set_volume(bus: string, volume: number)

Sets a mixer bus volume (master, music, sfx, ambience, voice, ui), 0..1.

Parameter Type
bus string
volume number

Returns: none

set_volume("music", 0.5)

stop_sound

stop_sound(e: entity)

Stops the entity's audio component.

Parameter Type
e entity

Returns: none

stop_sound(self)

character

grounded

grounded(e: entity) -> bool

Whether a character stands on the ground.

Parameter Type
e entity

Returns: bool

if grounded(self) then ... end

jump

jump(e: entity, speed: number?) -> bool

Makes a grounded character jump (default: its jumpSpeed); false when airborne.

Parameter Type
e entity
speed number optional

Returns: bool

if pressed("jump") then jump(self) end

walk

walk(e: entity, direction: vector)

Moves a character this tick (|direction| 1 = its moveSpeed). Call every tick while walking.

Parameter Type
e entity
direction vector

Returns: none

walk(self, (axis("move").x, 0, -axis("move").y))

character2d

drop_through2d

drop_through2d(e: entity) -> bool

Drops a character2d through the one-way platform it stands on; false when it stands on solid ground.

Parameter Type
e entity

Returns: bool

if pressed("down") and pressed("jump") then drop_through2d(self) end

grounded2d

grounded2d(e: entity) -> bool

Whether a character2d stands on walkable ground (a slope up to maxSlope or a platform).

Parameter Type
e entity

Returns: bool

if grounded2d(self) then play_anim(self, "run") end

jump2d

jump2d(e: entity, speed: number?) -> bool

Makes a character2d jump (default: its jumpSpeed). True when it jumps now (grounded or within coyote time); otherwise the press is buffered and the jump happens on landing within jumpBuffer seconds.

Parameter Type
e entity
speed number optional

Returns: bool

if pressed("jump") then jump2d(self) end

move2d

move2d(e: entity, x: number)

Runs a character2d this tick: -1 = full speed left, 1 = right (scaled by moveSpeed, with acceleration). Call every tick.

Parameter Type
e entity
x number

Returns: none

move2d(self, axis("move").x)

color

color

color(r: number, g: number, b: number, a: number?) -> color

Makes a color from 0..1 channels.

Parameter Type
r number
g number
b number
a number optional

Returns: color

color(1, 0.5, 0)

hsv

hsv(h: number, s: number, v: number) -> color

Color from hue (0..1, wraps), saturation and value.

Parameter Type
h number
s number
v number

Returns: color

self.color = hsv(time * 0.1, 0.8, 1)

dialogue

dialogue_advance

dialogue_advance()

Shows the rest of the typing line, or moves to the next line.

Returns: none

dialogue_advance()

dialogue_choose

dialogue_choose(index: number)

Picks one of the current dialogue choices (0-based).

Parameter Type
index number

Returns: none

dialogue_choose(0)

dialogue_var

dialogue_var(name: string, value?) -> any

Reads (or with a value, sets) a dialogue variable ($trust = "trust") of the first dialogue component.

Parameter Type
name string
value any optional

Returns: any

if dialogue_var("trust") > 2 then

start_dialogue

start_dialogue(entity_or_node: entity|string, node: string?)

Starts a conversation at a node: start_dialogue("Intro") on the first dialogue component, or start_dialogue(entity, "Intro").

Parameter Type
entity_or_node entity|string
node string optional

Returns: none

start_dialogue("Intro")

effects

burst

burst(entity_or_count: number|entity, count: number?)

Emits particles right now from self's particles (or particles2d) component: burst(n), or burst(entity, n) for another emitter. Explosions, muzzle flashes, impacts, dust puffs.

Parameter Type
entity_or_count number|entity
count number optional

Returns: none

burst(40)

camera_shake

camera_shake(trauma: number, camera: entity?)

Shakes the 2D camera: adds trauma (0..1; 0.2 a hit, 0.5 a heavy slam, 1 an explosion) to the camera2d (the active camera, or the given one). The offset grows with trauma squared (camera2d.shakeAmplitude world units at 1) and decays by shakeDecay per second. Runs through hit-stops; replays identically.

Parameter Type
trauma number
camera entity optional

Returns: none

camera_shake(0.4)

flash

flash(entity: entity, seconds: number?, color: color?)

Flashes a sprite: it turns color (default white; its alpha is the strength) and fades back over seconds (default 0.12). Damage feedback, parries, pickups. For a constant tint set sprite.flash.

Parameter Type
entity entity
seconds number optional
color color optional

Returns: none

flash(enemy, 0.15, #ffffff)

hit_stop

hit_stop(seconds: number, scale: number?)

Freeze frames on impact: the game clock stops (or runs at scale, 0..1) for seconds of real time, then resumes at the time scale. 0.04-0.12 s sells a hit; a longer, stronger stop extends the current one. UI, camera_shake and entities on the real clock keep moving. Per entity: set process.timeScale instead.

Parameter Type
seconds number
scale number optional

Returns: none

on event "hit"
  hit_stop(0.07)
  camera_shake(0.35)
end

hit_stop_left

hit_stop_left() -> number

Real seconds of hit-stop left (0 when the game clock runs normally).

Returns: number

if hit_stop_left() > 0 then return end

water_height

water_height(x_or_point: number|vector|entity, z: number?) -> number

Height of the animated water surface at (x, z) or at a point — the same surface that is rendered (0 where there is no water). Boats, buoyancy, splashes.

Parameter Type
x_or_point number|vector|entity
z number optional

Returns: number

self.position = (self.position.x, water_height(self.position) - 0.2, self.position.z)

input

action

action(name: string) -> bool

Whether an input action is held ("jump", "fire" from input.json).

Parameter Type
name string

Returns: bool

if action("fire") then ... end

axis

axis(name: string) -> number|vector

Value of an axis action: a number (-1..1), or a vector (x, y, 0) for 2D axes (x right, y forward/up).

Parameter Type
name string

Returns: number|vector

walk(self, (axis("move").x, 0, -axis("move").y))

cursor_lock

cursor_lock(on: bool)

Hides and captures the mouse cursor (first-person look: read mouse movement with axis("look")) or gives it back. Honored by the standalone player; resets when the game stops.

Parameter Type
on bool

Returns: none

cursor_lock(true)

key

key(name: string) -> bool

Whether a key is held ("w", "space", "left", ...).

Parameter Type
name string

Returns: bool

if key("w") then move self by (0, 0, -speed * dt) end

key_pressed

key_pressed(name: string) -> bool

Whether a key was pressed this tick (once per press).

Parameter Type
name string

Returns: bool

if key_pressed("space") then jump() end

pressed

pressed(name: string) -> bool

Whether an input action was pressed this tick.

Parameter Type
name string

Returns: bool

if pressed("jump") then jump(self) end

quit_game

quit_game()

Closes the game (a "Quit" menu button). The standalone player exits; the editor ignores it.

Returns: none

quit_game()

released

released(name: string) -> bool

Whether an input action was released this tick.

Parameter Type
name string

Returns: bool

released("aim")

list

clear

list|map.clear()

Removes everything.

Returns: none

self.targets.clear()

contains

string|list|map.contains(item) -> bool

Lists: has an equal item. Maps: has the key. Strings: has the substring. (Same as x in y.)

Parameter Type
item any

Returns: bool

if inventory.contains("key") then ... end

first

list.first() -> any

The first item (none if empty).

Returns: any

let next = queue.first()

index_of

string|list.index_of(item) -> number

Position of the first equal item/substring, or -1.

Parameter Type
item any

Returns: number

let i = names.index_of("Bob")

insert

list.insert(index: number, item)

Inserts an item before index (index = length appends).

Parameter Type
index number
item any

Returns: none

queue.insert(0, job)

is_empty

string|list|map.is_empty() -> bool

Whether it has no items / keys / characters.

Returns: bool

if queue.is_empty() then ... end

join

list.join(separator: string?) -> string

Text of all items joined by a separator.

Parameter Type
separator string optional

Returns: string

log names.join(", ")

last

list.last() -> any

The last item (none if empty).

Returns: any

path.last()

pop

list.pop() -> any

Removes and returns the last item.

Returns: any

let last = stack.pop()

push

list.push(item)

Appends an item.

Parameter Type
item any

Returns: none

self.visited.push(spot)

remove

list|map.remove(item_or_key) -> bool

Lists: removes the first item equal to the argument. Maps: removes a key. Returns whether something was removed.

Parameter Type
item_or_key any

Returns: bool

targets.remove(other)

remove_at

list.remove_at(index: number) -> any

Removes and returns the item at index.

Parameter Type
index number

Returns: any

let first = queue.remove_at(0)

reverse

list.reverse()

Reverses the list in place.

Returns: none

path.reverse()

slice

string|list.slice(from: number, to: number?) -> string|list

Items (or characters) from index from up to, not including, to. Negative indexes count from the end.

Parameter Type
from number
to number optional

Returns: string|list

let firstThree = items.slice(0, 3)

sort

list.sort()

Sorts numbers or strings in place (ascending).

Returns: none

scores.sort()

sorted

list.sorted() -> list

A sorted copy (numbers or strings).

Returns: list

for s in scores.sorted() ... end

sum

list.sum() -> number

Sum of a list of numbers.

Returns: number

let total = scores.sum()

locale

locale

locale() -> string

The current locale code ("en", "fr", "pt-BR").

Returns: string

if locale() == "ja" then self.text.font = "fonts/NotoSansJP.otf" end

locales

locales() -> list

Locale codes the game has strings for (with the source language), sorted: for a language menu.

Returns: list

for code in locales() log code end

set_locale

set_locale(code: string)

Switches the game's language from the next frame (a language menu): "fr", "pt-BR". Texts written as "@key" and #line dialogue lines follow at once. Undone when play stops; save it with game_var to keep it.

Parameter Type
code string

Returns: none

on ui "French"
  set_locale("fr")
end

tr

tr(key: string, args: map?) -> string

The localized string for a key in the current locale (locale/.csv or .po), falling back pt-BR -> pt -> the source language. args fill {placeholders}, plurals ({n, plural, one {# coin} other {# coins}}) and selects; numbers are formatted for the locale. A missing key returns the key and is reported by locale_check.

Parameter Type
key string
args map optional

Returns: string

self.ui.text = tr("hud.coins", {n: coins})

map

get

map.get(key: string, default?) -> any

Value for a key, or the default (none) if missing.

Parameter Type
key string
default any optional

Returns: any

let dmg = data.get("amount", 1)

has

map.has(key: string) -> bool

Whether the map has a key.

Parameter Type
key string

Returns: bool

if data.has("amount") then ... end

keys

map.keys() -> list

The keys, in insertion order.

Returns: list

for k in stats.keys() ... end

set

map.set(key: string, value)

Sets a key (same as m[key] = value).

Parameter Type
key string
value any

Returns: none

self.stats.set("hp", 10)

values

map.values() -> list

The values, in insertion order.

Returns: list

stats.values().sum()

math

abs

abs(x: number) -> number

Absolute value.

Parameter Type
x number

Returns: number

abs(-3)

acos

acos(x: number) -> number

Arc cosine in radians (x is clamped to -1..1).

Parameter Type
x number

Returns: number

acos(dot(a, b))

approach

approach(current: number, target: number, max_step: number) -> number

Moves current toward target by at most max_step (never overshoots).

Parameter Type
current number
target number
max_step number

Returns: number

speed = approach(speed, 10, 4 * dt)

asin

asin(x: number) -> number

Arc sine in radians (x is clamped to -1..1).

Parameter Type
x number

Returns: number

asin(0.5)

atan

atan(x: number) -> number

Arc tangent in radians.

Parameter Type
x number

Returns: number

atan(1)

atan2

atan2(y: number, x: number) -> number

Angle of the point (x, y) in radians, -pi..pi.

Parameter Type
y number
x number

Returns: number

deg(atan2(d.x, d.z))

ceil

ceil(x: number) -> number

Smallest whole number >= x.

Parameter Type
x number

Returns: number

ceil(2.1)

clamp

clamp(x: number, lo: number, hi: number) -> number

x limited to the range lo..hi.

Parameter Type
x number
lo number
hi number

Returns: number

clamp(speed, 0, 10)

cos

cos(radians: number) -> number

Cosine of an angle in radians.

Parameter Type
radians number

Returns: number

cos(time)

deg

deg(radians: number) -> number

Radians to degrees.

Parameter Type
radians number

Returns: number

deg(atan2(d.x, d.z))

exp

exp(x: number) -> number

e raised to x.

Parameter Type
x number

Returns: number

exp(-dt * 4)

floor

floor(x: number) -> number

Largest whole number <= x.

Parameter Type
x number

Returns: number

floor(2.7)

inverse_lerp

inverse_lerp(a: number, b: number, x: number) -> number

Where x lies between a (0) and b (1).

Parameter Type
a number
b number
x number

Returns: number

inverse_lerp(0, 100, hp)

lerp

lerp(a: number|vector|color, b: number|vector|color, t: number) -> number|vector|color

Linear blend from a (t=0) to b (t=1); numbers, vectors or colors.

Parameter Type
a number|vector|color
b number|vector|color
t number

Returns: number|vector|color

lerp(self.position, target, 0.1)

ln

ln(x: number) -> number

Natural logarithm (x > 0).

Parameter Type
x number

Returns: number

ln(10)

max

max(a: number|list, b: number?, ...) -> number

Larger of numbers, or the largest number in a list.

Parameter Type
a number|list
b number optional

Returns: number

max(0, hp - damage)

min

min(a: number|list, b: number?, ...) -> number

Smaller of numbers, or the smallest number in a list.

Parameter Type
a number|list
b number optional

Returns: number

min(hp, 10)   min([3, 1, 2])

noise

noise(x: number, y: number?) -> number

Smooth deterministic value noise in -1..1 (1D or 2D).

Parameter Type
x number
y number optional

Returns: number

move self by (0, noise(time) * 0.01, 0)

pow

pow(base: number, exponent: number) -> number

base raised to exponent.

Parameter Type
base number
exponent number

Returns: number

pow(2, 10)

rad

rad(degrees: number) -> number

Degrees to radians.

Parameter Type
degrees number

Returns: number

sin(rad(45))

round

round(x: number, digits: number?) -> number

Rounds to the nearest whole number, or to digits decimals.

Parameter Type
x number
digits number optional

Returns: number

round(3.14159, 2)

sign

sign(x: number) -> number

-1, 0 or 1.

Parameter Type
x number

Returns: number

sign(velocity.x)

sin

sin(radians: number) -> number

Sine of an angle in radians.

Parameter Type
radians number

Returns: number

sin(time * 2)

smoothstep

smoothstep(edge0: number, edge1: number, x: number) -> number

Smooth 0..1 ramp between two edges.

Parameter Type
edge0 number
edge1 number
x number

Returns: number

smoothstep(0, 1, t)

sqrt

sqrt(x: number) -> number

Square root (0 for negative input).

Parameter Type
x number

Returns: number

sqrt(2)

tan

tan(radians: number) -> number

Tangent of an angle in radians.

Parameter Type
radians number

Returns: number

tan(0.5)
arrived(e: entity) -> bool

Whether a nav agent reached its destination.

Parameter Type
e entity

Returns: bool

if arrived(self) then ... end
navigate(e: entity, target: vector|entity)

Walks a nav agent to a point, or follows an entity as it moves. on event "arrived" fires on arrival.

Parameter Type
e entity
target vector|entity

Returns: none

navigate(self, find("Player"))
path_length(from: vector|entity, to: vector|entity) -> none|number

Walking distance along the navmesh; none if unreachable or there is no navmesh.

Parameter Type
from vector|entity
to vector|entity

Returns: none|number

path_length(self, find("Exit"))
stop_navigation(e: entity)

Stops a nav agent.

Parameter Type
e entity

Returns: none

stop_navigation(self)

physics

impulse

impulse(e: entity, impulse: vector)

An instant kick (N s) to a dynamic body.

Parameter Type
e entity
impulse vector

Returns: none

impulse(self, (0, 6, 0))

overlap_sphere

overlap_sphere(center: vector|entity, radius: number, tag: string?) -> none|entity

Nearest entity (not self) whose collider overlaps the sphere, optionally with a tag; none if empty.

Parameter Type
center vector|entity
radius number
tag string optional

Returns: none|entity

let enemy = overlap_sphere(self, 3, "enemy")

push

push(e: entity, force: vector)

Applies a continuous force (N) to a dynamic body this step.

Parameter Type
e entity
force vector

Returns: none

push(self, (0, 0, -20))

raycast

raycast(origin: vector|entity, direction: vector, max_distance: number?) -> none|entity

First collider hit along a ray (self is ignored); sets hit_point, hit_normal and hit_distance.

Parameter Type
origin vector|entity
direction vector
max_distance number optional

Returns: none|entity

let ground = raycast(self, (0, -1, 0), 2)

torque

torque(e: entity, torque: vector)

Applies a torque (N m) to a dynamic body.

Parameter Type
e entity
torque vector

Returns: none

torque(self, (0, 5, 0))

velocity

velocity(e: entity) -> vector

Current linear velocity of a body or character (m/s).

Parameter Type
e entity

Returns: vector

if length(velocity(self)) > 10 then ... end

physics2d

impulse2d

impulse2d(e: entity, impulse: vector)

An instant kick (N s, x/y) to a dynamic body2d.

Parameter Type
e entity
impulse vector

Returns: none

impulse2d(self, (0, 8, 0))

overlap2d

overlap2d(center: vector|entity, radius: number, tag: string?) -> none|entity

Nearest entity (not self) whose 2D collider overlaps the circle, optionally with a tag; sensors are ignored; none if empty.

Parameter Type
center vector|entity
radius number
tag string optional

Returns: none|entity

let enemy = overlap2d(self, 3, "enemy")

point2d

point2d(point: vector|entity, tag: string?) -> none|entity

Entity whose 2D collider contains the point (sensors included, self excluded), optionally with a tag; none if empty.

Parameter Type
point vector|entity
tag string optional

Returns: none|entity

let under = point2d((2, 1, 0), "crate")

push2d

push2d(e: entity, force: vector)

Applies a continuous force (N, x/y) to a dynamic body2d this tick.

Parameter Type
e entity
force vector

Returns: none

push2d(self, (axis("move").x * 20, 0, 0))

raycast2d

raycast2d(origin: vector|entity, direction: vector, max_distance: number?) -> none|entity

First 2D collider hit along a ray on the XY plane (self is ignored, sensors too); sets hit_point, hit_normal and hit_distance.

Parameter Type
origin vector|entity
direction vector
max_distance number optional

Returns: none|entity

let ground = raycast2d(self, (0, -1, 0), 1.2)

set_velocity2d

set_velocity2d(e: entity, velocity: vector)

Sets the velocity of a body2d (dynamic or kinematic) or character2d (knockback, launch pads).

Parameter Type
e entity
velocity vector

Returns: none

set_velocity2d(self, (velocity2d(self).x, 14, 0))

torque2d

torque2d(e: entity, torque: number)

Applies a torque (N m, counter-clockwise) to a dynamic body2d.

Parameter Type
e entity
torque number

Returns: none

torque2d(self, 5)

velocity2d

velocity2d(e: entity) -> vector

Current velocity of a body2d or character2d (units/s, z = 0).

Parameter Type
e entity

Returns: vector

if abs(velocity2d(self).x) > 8 then ... end

random

chance

chance(p: number) -> bool

true with probability p (0..1).

Parameter Type
p number

Returns: bool

if chance(0.1) then ... end

pick

pick(items: list) -> any

A random element of a list (none if empty).

Parameter Type
items list

Returns: any

pick(["red", "blue"])

random

random(lo_or_hi: number?, hi: number?) -> number

random() is 0..1; random(hi) is 0..hi; random(lo, hi) is lo..hi. Seeded by the scene: replays exactly.

Parameter Type
lo_or_hi number optional
hi number optional

Returns: number

random(-1, 1)

random_int

random_int(lo: number, hi: number) -> number

A whole number from lo to hi (both included).

Parameter Type
lo number
hi number

Returns: number

random_int(1, 6)

shuffle

shuffle(items: list) -> list

A shuffled copy of a list.

Parameter Type
items list

Returns: list

for e in shuffle(find_all("spawn")) ... end

render

layer_mask

layer_mask(layers: number|string|list, ...) -> number

Render layer bitmask from layer names (game.json render.layers), layer numbers as strings ("3"), "all" / "none", or a list of names / layer numbers; several arguments are combined. Set it on mesh.layers, camera.cullMask or light.cullMask, e.g. hide the player's own body from the first-person camera.

Parameter Type
layers number|string|list

Returns: number

find("Eyes").camera.cullMask = layer_mask("world", "fx")

probe_bake

probe_bake(probe: entity?)

Re-captures a reflection probe (or every probe without an argument) over the next rendered frames: after opening a door, switching the room's lights or rearranging furniture, so once probes reflect the new state. Rendering only; the simulation is unaffected.

Parameter Type
probe entity optional

Returns: none

probe_bake(find("Hall Probe"))

save

delete_save

delete_save(slot: string) -> bool

Deletes a slot. Returns whether there was a save to delete.

Parameter Type
slot string

Returns: bool

delete_save("slot3")

game_var

game_var(name: string, value?) -> any

Reads (or with a value, sets) a global game variable: state that belongs to the game, not to one entity (chapter, flags, unlocked levels, settings). Saved with every save; reset when play stops. Setting none removes it.

Parameter Type
name string
value any optional

Returns: any

game_var("chapter", game_var("chapter") + 1)

has_save

has_save(slot: string) -> bool

Whether a slot holds a save (a "Continue" button shows only then).

Parameter Type
slot string

Returns: bool

find("Continue").ui.visible = has_save("autosave")

list_saves

list_saves() -> list

Every save, sorted by slot: maps {slot, meta, play_time, saved_at, version, scene}; damaged files have an error instead. For load / save menus.

Returns: list

for s in list_saves() log s.slot + ": " + s.meta.get("title", s.slot) end

load_game

load_game(slot: string) -> bool

Loads a slot at the end of this tick: persisted entities, game vars, the exact behavior state and the scene return to the moment of the save. Returns false (and does nothing) when the slot is empty. on loaded follows next tick.

Parameter Type
slot string

Returns: bool

if not load_game("autosave") then log "no save yet" end

save_game

save_game(slot: string, meta: map?)

Saves the game into a slot at the end of this tick: every entity with a persist component, game_var values, the scene and the play time. meta is shown in save menus (title, chapter, thumbnail). on saved follows next tick (on event "save_failed" on error). Slots: "slot1", "autosave", "quicksave"...

Parameter Type
slot string
meta map optional

Returns: none

save_game("autosave", {title: "Forest gate", chapter: 2})

scene

add_tag

add_tag(e: entity, tag: string)

Adds a tag to an entity.

Parameter Type
e entity
tag string

Returns: none

add_tag(self, "carried")

change_scene

change_scene(scene: string, options: map?)

Moves the game to another scene (a game.json "scenes" alias or a .sky.json path) after this tick: the current scene hears on scene_unloading, entities with a carry component (and options.keep) carry over with their running behaviors, the rest is replaced. Options: transition ("fade" | "crossfade" | "none" or {kind, duration, color}), duration, keep: [names], spawn_at: "EntityName" (the player moves there), loading: a loading scene shown while assets preload. on scene_loaded follows. Stopping play returns the editor to the scene play started in.

Parameter Type
scene string
options map optional

Returns: none

change_scene("level2", {transition: "fade", duration: 0.5, spawn_at: "Door_West"})

children

children(e: entity) -> list

Direct children of an entity, in order.

Parameter Type
e entity

Returns: list

for child in children(self) ... end

count

count(tag: string) -> number

How many entities have a tag.

Parameter Type
tag string

Returns: number

if count("coin") == 0 then ... end

current_scene

current_scene() -> string

The scene the game is in: its game.json alias, else its path.

Returns: string

if current_scene() == "menu" then music("audio/menu.ogg") end

exists

exists(e) -> bool

Whether a value is an entity that still exists.

Parameter Type
e any

Returns: bool

if exists(target) then ... end

find

find(name: string) -> none|entity

Entity by name (or "#id"); none if missing. "%Name" finds the entity marked unique (entity_update unique=true) inside this prefab instance, else in the scene, so each copy of a prefab finds its own part.

Parameter Type
name string

Returns: none|entity

let muzzle = find("%Muzzle")

find_all

find_all(tag: string) -> list

Active entities with a tag, in scene order.

Parameter Type
tag string

Returns: list

for e in find_all("enemy") ... end

has

has(e: entity, component: string) -> bool

Whether the entity has a component ("light", "particles", ...).

Parameter Type
e entity
component string

Returns: bool

if has(self, "light") then self.light.intensity = 2 end

load_additive

load_additive(scene: string, options: map?) -> string

Adds a scene's entities to the running one at the end of this tick (a room, a streaming chunk, a UI overlay) and returns its handle for unload_scene. Options: id (handle), parent (entity to load under), offset (vector added to its root positions). It owns exactly the entities it created.

Parameter Type
scene string
options map optional

Returns: string

let room = load_additive("rooms/cellar", {offset: (40, 0, 0)})

loading_progress

loading_progress() -> number

How far the next scene has preloaded, 0..1 (1 when nothing is loading): for a loading bar in a loading scene.

Returns: number

find("Bar").ui.value = loading_progress()

nearest

nearest(tag: string, max_distance: number?) -> none|entity

Closest other active entity with a tag (within max_distance); none if there is none.

Parameter Type
tag string
max_distance number optional

Returns: none|entity

let p = nearest("player", 10)

remove_tag

remove_tag(e: entity, tag: string)

Removes a tag from an entity.

Parameter Type
e entity
tag string

Returns: none

remove_tag(self, "carried")

set_parent

set_parent(e: entity, parent: none|entity, keep_world: bool?)

Moves an entity under a new parent, or to the scene root with none. By default it keeps its world position, rotation and scale (keep_world = false keeps its local transform instead, so it jumps to the same offset from the new parent). Parenting under itself or a descendant fails. Like every play-time change, it is undone when play stops.

Parameter Type
e entity
parent none|entity
keep_world bool optional

Returns: none

set_parent(item, self)  -- pick it up; set_parent(item, none) drops it

spawn

spawn(mesh: string, position: vector|entity?, name?) -> entity

Creates an entity: a primitive mesh ("cube", "sphere"...), "asset:models/x.glb", or a whole prefab "prefab:prefabs/coin.prefab.json" (with its children and behaviors). Its behaviors start next tick. Limits: 256 spawns per tick, 20000 entities.

Parameter Type
mesh string
position vector|entity optional
name any optional

Returns: entity

let coin = spawn("prefab:prefabs/coin.prefab.json", self.position + (0, 1, 0))

tagged

tagged(e, tag: string) -> bool

Whether an entity has a tag (false for none).

Parameter Type
e any
tag string

Returns: bool

if tagged(other, "player") then ... end

unload_scene

unload_scene(handle: string)

Removes a sub-scene loaded with load_additive: its entities hear on scene_unloading next tick and are removed the tick after. Entities the game added under it are kept (moved to the root).

Parameter Type
handle string

Returns: none

unload_scene(room)

text

num

num(text) -> none|number

Number parsed from text (none if it is not a number).

Parameter Type
text any

Returns: none|number

num("3.5")

str

str(value) -> string

Text form of any value (entities give their name).

Parameter Type
value any

Returns: string

log "hp: " + str(hp)

type_of

type_of(value) -> string

The type name: number, bool, string, vector, color, entity, list, map, none.

Parameter Type
value any

Returns: string

if type_of(data) == "map" then ... end

ends_with

string.ends_with(suffix: string) -> bool

Whether the text ends with a suffix.

Parameter Type
suffix string

Returns: bool

file.ends_with(".png")

lower

string.lower() -> string

Lowercase copy.

Returns: string

answer.lower()

replace

string.replace(old: string, new: string) -> string

Copy with every occurrence of old replaced.

Parameter Type
old string
new string

Returns: string

msg.replace("{name}", player.name)

split

string.split(separator: string?) -> list

Parts of the text between separators (default: spaces).

Parameter Type
separator string optional

Returns: list

for word in line.split(" ") ... end

starts_with

string.starts_with(prefix: string) -> bool

Whether the text starts with a prefix.

Parameter Type
prefix string

Returns: bool

name.starts_with("Enemy")

trim

string.trim() -> string

Copy without leading/trailing spaces.

Returns: string

input.trim()

upper

string.upper() -> string

Uppercase copy.

Returns: string

name.upper()

time

is_paused

is_paused() -> bool

True while the game is paused (or will be from the next tick, after pause_game()).

Returns: bool

if is_paused() then ... end

pause_game

pause_game(paused: bool?)

Pauses the game (a pause menu) from the next tick: pausable entities (the default) stop — behaviors, physics, animation, particles, sounds — while UI canvases and entities with process mode always or when_paused keep running. Sends on pause to every behavior. pause_game(false) = resume_game().

Parameter Type
paused bool optional

Returns: none

on action "pause"
  if is_paused() then resume_game() else pause_game() end
end

resume_game

resume_game()

Resumes a paused game from the next tick and sends on resume.

Returns: none

on ui "Resume"
  resume_game()
end

teleport

teleport(entity: entity, position: vector|entity?)

Moves an entity instantly (when given a position) and tells render interpolation not to smear it across the screen: respawns, portals, checkpoints. Without a position it only resets the smoothing for this frame.

Parameter Type
entity entity
position vector|entity optional

Returns: none

teleport(self, find("Spawn"))

time_scale

time_scale(scale: number?) -> number

Slow motion / fast forward: time_scale(0.3) makes the game clock run at 30% from the next tick (dt, timers, waits, physics, animation, particles; 0..10). Entities on the real clock (UI, process clock real) ignore it. Returns the scale (the requested one).

Parameter Type
scale number optional

Returns: number

time_scale(0.25)  -- bullet time
after 2 do time_scale(1) end

unscaled_dt

unscaled_dt() -> number

Real seconds per tick (1/60), whatever the time scale or pause: timers that must ignore slow motion.

Returns: number

menu_timer += unscaled_dt()

unscaled_time

unscaled_time() -> number

Real seconds since play started (keeps counting while the game is paused or slowed; time does not).

Returns: number

let pulse = sin(unscaled_time() * 4)

vector

cross

cross(a: vector, b: vector) -> vector

Cross product.

Parameter Type
a vector
b vector

Returns: vector

cross((0, 1, 0), forward(self))

direction

direction(from: vector|entity, to: vector|entity) -> vector

Unit vector pointing from one point to another.

Parameter Type
from vector|entity
to vector|entity

Returns: vector

move self by direction(self, goal) * speed * dt

distance

distance(a: vector|entity, b: vector|entity) -> number

Distance between two points; entities count as their world position.

Parameter Type
a vector|entity
b vector|entity

Returns: number

distance(self, player) < 3

dot

dot(a: vector, b: vector) -> number

Dot product.

Parameter Type
a vector
b vector

Returns: number

dot(forward(self), direction(self, player)) > 0.7

forward

forward(e: entity) -> vector

World direction the entity faces (its -Z axis).

Parameter Type
e entity

Returns: vector

move self by forward(self) * speed * dt

length

length(v: vector) -> number

Length (magnitude) of a vector.

Parameter Type
v vector

Returns: number

length(velocity)

normalize

normalize(v: vector) -> vector

Vector scaled to length 1 (zero stays zero).

Parameter Type
v vector

Returns: vector

normalize(v)

right

right(e: entity) -> vector

World direction of the entity's right side (+X).

Parameter Type
e entity

Returns: vector

right(self)

up

up(e: entity) -> vector

World direction of the entity's up axis (+Y).

Parameter Type
e entity

Returns: vector

up(self)

vec

vec(x: number, y: number, z: number) -> vector

Makes a vector (same as (x, y, z)).

Parameter Type
x number
y number
z number

Returns: vector

vec(0, 1, 0)

world_position

world_position(e: entity) -> vector

World position (self.position is relative to the parent).

Parameter Type
e entity

Returns: vector

world_position(self)

vehicle

vehicle_drive

vehicle_drive(e: entity, throttle: number, steer: number, brake: number?, handbrake: number?)

Sets a vehicle's inputs for this tick: throttle 0..1, steer -1 (left)..1 (right), brake 0..1, handbrake 0..1. Overrides the player's drive actions this tick; with control "script" it is the only driver. Holding brake at a standstill reverses (autoReverse).

Parameter Type
e entity
throttle number
steer number
brake number optional
handbrake number optional

Returns: none

vehicle_drive(self, 1, axis("steer"), 0)

vehicle_shift

vehicle_shift(e: entity, gear: number)

Manual gearbox: selects a gear (-1 reverse, 0 neutral, 1..). Automatic gearboxes shift by themselves.

Parameter Type
e entity
gear number

Returns: none

if pressed("shift_up") then vehicle_shift(self, self.vehicle.gear + 1) end

vehicle_speed

vehicle_speed(e: entity) -> number

Speed along the vehicle's heading in km/h (negative reversing).

Parameter Type
e entity

Returns: number

if vehicle_speed(self) > 120 then ... end

vehicle_state

vehicle_state(e: entity) -> map

Live vehicle state: speed (km/h), rpm, gear, wheels_on_ground, skid 0..1, drift_angle (degrees), lateral_g, longitudinal_g, load 0..1 and skidding (a list of contact points of sliding wheels, for smoke and marks).

Parameter Type
e entity

Returns: map

let s = vehicle_state(self)

vehicle_wheel

vehicle_wheel(e: entity, wheel: number|string) -> none|map

One wheel's live state by index (0-based) or name ("rear_left"): contact, point, normal, surface, load (N), slip_ratio, slip_angle (degrees), skid 0..1, compression 0..1, steer, rpm, driven. none before play. Tire smoke and skid marks: spawn at point while skid > 0.3.

Parameter Type
e entity
wheel number|string

Returns: none|map

let w = vehicle_wheel(self, "rear_left")

The guide agents read

wander_reference without a topic returns this text: a compact language guide followed by the builtin list.

wander_reference output
Wander 2 — Skywalker's behavior language (ECPS: Entity · Component · Prompt System)

A behavior = an `intent` (plain language, the human source of truth) + deterministic code.
Safe by construction: every handler run has a step budget (loops can't hang the engine),
randomness is seeded (runs replay exactly), and the compiler reports line/column/code/hint.

behavior Guard
  intent "Patrol between two posts; chase the player when close; lose 1 hp per hit."
  param speed = 3 in 0..10 "walk speed (m/s)"   -- tunable: shown as a slider in the editor
  var hp = 3                                    -- per-entity state (persisted, visible to tools)
  var posts: list = []

  on start
    posts = [self.position, self.position + (6, 0, 0)]
  end

  state Patrol                                  -- first state is the initial one
    on tick
      let goal = posts[floor(state_time / 4) % 2]
      move self toward goal at speed
      let p = nearest("player", 5)
      if p then go to Chase end
    end
  end

  state Chase
    on enter
      self.color = #ff4040
    end
    on tick
      let p = nearest("player", 8)
      if not p then go to Patrol end
      move self toward p at speed * 1.5
    end
  end

  on event "damage" with hit                     -- payload map; `other` is the sender
    hp -= hit.get("amount", 1)
    if hp <= 0 then
      emit "guard_down" with {at: self.position}
      destroy self
    end
  end

  on event "alarm"
    wait 0.5                                     -- coroutine: resumes 0.5 s later (per entity)
    log "{self.name} heard the alarm"
  end

  test "loses hp when hit"
    emit "damage" with {amount: 1} to self
    wait frames 2
    expect hp == 2
  end
end

TRIGGERS  on start | on tick | on event "name" (with x) | on key "space" | on click
          inside a state: on enter | on exit | on tick | on event ...  (plus subsystem triggers, see below)
DECLARE   var x = 0 (per entity; `x` or `self.x`)  |  param x = 1 in 0..5 "doc"  |  const MAX = 10
          fn name(a, b: number) -> number ... return a + b end   (recursion ok)  |  use "scripts/combat" (then combat.fn())
STATEMENTS
  let x = v | x = v | x += v (-= *= /=) | set x to v
  if c then .. elif c then .. else .. end     (`then` optional)
  for x in list .. end | for i, x in list | for k, v in map | for i in 0..10 (end excluded; 0..=10 includes) step 2
  while c .. end | repeat n times .. end | break | continue | return v | stop
  every 2 seconds .. end | after 1 seconds .. end      (timers that tick with the handler)
  wait 1.5 | wait frames 3 | wait until hp <= 0         (handlers and tests only, not inside fn)
  go to StateName
  move e by vec | move e toward point at speed | rotate e by (0, 90 * dt, 0) | look e at point
  emit "event" (with payload) (to entity) | destroy e | log value
VALUES    1.5  "text {interpolated}"  true false none  #ff8800  (x, y, z)  [list]  {key: value}
OPERATORS + - * / %   < <= > >= == !=   and or not   x in list/map/string   "a" + 1 joins text
NAMES     self  other (sender / collision partner)  dt  time  frame  pi  state  state_time  data (event payload)
PROPERTIES e.position e.rotation (degrees) e.scale e.color e.name e.id e.enabled e.tags e.parent e.state
          e.<component>.<field> (self.light.intensity, self.particles.rate)   e.<var>
          v.x v.y v.z v.length   c.r c.g c.b c.a   list.length   string.length   map.key
LISTS/MAPS are values (copied on assignment); mutate in place with methods: self.items.push(x)
TESTS     test "name" .. end — run by wander_test in a sandbox: expect cond ("why"), wait (advances the sim),
          emit, press "space" / hold "w" / release "w" / click e, spawn(...). Tests start after the first tick.

IDIOMS
  - Smooth motion: move self toward target at speed  |  self.position = lerp(self.position, goal, 1 - exp(-8 * dt))
  - Frame-rate independent: always multiply per-tick changes by dt.
  - Sequences: on event "open" .. wait 1 .. end — no manual timers.
  - Find things: nearest("enemy", 10), find_all("coin"), find("Door"); check `if x then` before using a maybe-none.
  - Cooldowns: var cooldown = 0 / cooldown -= dt / if cooldown <= 0 then ... cooldown = 1 end
  - Share code across behaviors with modules: use "scripts/util" then util.clamp01(x).
  - Prefer states over boolean flags for modes (Idle/Chase/Flee); `state` reads the current one.
RULES     meters, +Y up, entities face -Z, rotations are Euler degrees (pitch X, yaw Y, roll Z).
          A handler that errors 5 times disables its script. Events arrive next tick, in emission order.

FUNCTIONS (category: signature — what it does)
  [2d]
    play_anim(entity: entity, clip: string, restart: bool?) — Plays a sprite_anim clip (keeps playing if it already is, unless restart). Frame events arrive as `on anim "name"`; a non-looping clip sends `on anim "finished"`.
    set_tile(map: entity, position: vector|entity, tile: number|string, layer: string?) — Sets the tile at a world position: an id (0 clears) or a terrain from tilemap.autotile (auto-tiled).
    tile_at(map: entity, position: vector|entity, layer: string?) -> number — Tile id of a tilemap at a world position (topmost non-empty layer, or the named layer); 0 = empty.
  [animation]
    anim_state(entity: entity) -> string — Name of the animator's current state.
    foot_ik(entity: entity, on: bool, weight: number?) — Turns automatic foot planting on or off (feet on stairs, slopes and rocks, pelvis lowered, feet locked while planted); the optional weight fades it (0..1). Adds the characterIk component if needed.
    hand_ik(entity: entity, side: string, target: none|entity, weight: number?) — Makes a character's hand reach an entity ("left" or "right"): a grip point on a staff held in the other hand, a ledge, a rail, a door handle. `none` (or weight 0) releases it. Adds the characterIk component if needed.
    look_at(entity: entity, target: none|entity, weight: number?) — Turns a character's head and upper spine toward an entity (look-at IK, clamped by animator.lookAtLimit), or stops with `none`; the turn fades in and out smoothly.
    play_animation(entity: entity, clip: string, fade: number?, loop: bool?) — Crossfades straight to a clip or state (seconds of fade, default 0.2).
    play_sequence(entity: entity, start: number?) — Plays the entity's sequencer (a cutscene) from `start` seconds.
    set_param(entity: entity, name: string, value: bool|number) — Sets an animator controller parameter (blend spaces and transitions read them).
    trigger(entity: entity, name: string) — Fires an animator trigger (jump, attack, wave).
    turn_in_place(entity: entity, toward: number|vector|entity) — Turns a standing character in place toward a world yaw (degrees, 0 = -Z) or to face a point / entity, at characterIk.turnSpeed; planted feet stay locked and re-plant in small steps. Controllers can read the float `turn` (degrees left) and bool `turning` parameters to play turn clips.
  [audio]
    music(clip: string, fade: number?) — Crossfades the music to a clip ("" fades out); fade in seconds.
    play(e: entity) — Starts the entity's audio component (its clip, volume, spatial settings).
    play_sound(clip: string, volume: number?) — Plays a one-shot sound at self (positional), e.g. a hit or a pickup.
    set_volume(bus: string, volume: number) — Sets a mixer bus volume (master, music, sfx, ambience, voice, ui), 0..1.
    stop_sound(e: entity) — Stops the entity's audio component.
  [character]
    grounded(e: entity) -> bool — Whether a character stands on the ground.
    jump(e: entity, speed: number?) -> bool — Makes a grounded character jump (default: its jumpSpeed); false when airborne.
    walk(e: entity, direction: vector) — Moves a character this tick (|direction| 1 = its moveSpeed). Call every tick while walking.
  [character2d]
    drop_through2d(e: entity) -> bool — Drops a character2d through the one-way platform it stands on; false when it stands on solid ground.
    grounded2d(e: entity) -> bool — Whether a character2d stands on walkable ground (a slope up to maxSlope or a platform).
    jump2d(e: entity, speed: number?) -> bool — Makes a character2d jump (default: its jumpSpeed). True when it jumps now (grounded or within coyote time); otherwise the press is buffered and the jump happens on landing within jumpBuffer seconds.
    move2d(e: entity, x: number) — Runs a character2d this tick: -1 = full speed left, 1 = right (scaled by moveSpeed, with acceleration). Call every tick.
  [color]
    color(r: number, g: number, b: number, a: number?) -> color — Makes a color from 0..1 channels.
    hsv(h: number, s: number, v: number) -> color — Color from hue (0..1, wraps), saturation and value.
  [dialogue]
    dialogue_advance() — Shows the rest of the typing line, or moves to the next line.
    dialogue_choose(index: number) — Picks one of the current dialogue choices (0-based).
    dialogue_var(name: string, value?) -> any — Reads (or with a value, sets) a dialogue variable ($trust = "trust") of the first dialogue component.
    start_dialogue(entity_or_node: entity|string, node: string?) — Starts a conversation at a node: start_dialogue("Intro") on the first dialogue component, or start_dialogue(entity, "Intro").
  [effects]
    burst(entity_or_count: number|entity, count: number?) — Emits particles right now from self's particles (or particles2d) component: burst(n), or burst(entity, n) for another emitter. Explosions, muzzle flashes, impacts, dust puffs.
    camera_shake(trauma: number, camera: entity?) — Shakes the 2D camera: adds `trauma` (0..1; 0.2 a hit, 0.5 a heavy slam, 1 an explosion) to the camera2d (the active camera, or the given one). The offset grows with trauma squared (camera2d.shakeAmplitude world units at 1) and decays by shakeDecay per second. Runs through hit-stops; replays identically.
    flash(entity: entity, seconds: number?, color: color?) — Flashes a sprite: it turns `color` (default white; its alpha is the strength) and fades back over `seconds` (default 0.12). Damage feedback, parries, pickups. For a constant tint set sprite.flash.
    hit_stop(seconds: number, scale: number?) — Freeze frames on impact: the game clock stops (or runs at `scale`, 0..1) for `seconds` of real time, then resumes at the time scale. 0.04-0.12 s sells a hit; a longer, stronger stop extends the current one. UI, camera_shake and entities on the real clock keep moving. Per entity: set `process.timeScale` instead.
    hit_stop_left() -> number — Real seconds of hit-stop left (0 when the game clock runs normally).
    water_height(x_or_point: number|vector|entity, z: number?) -> number — Height of the animated water surface at (x, z) or at a point — the same surface that is rendered (0 where there is no water). Boats, buoyancy, splashes.
  [input]
    action(name: string) -> bool — Whether an input action is held ("jump", "fire" from input.json).
    axis(name: string) -> number|vector — Value of an axis action: a number (-1..1), or a vector (x, y, 0) for 2D axes (x right, y forward/up).
    cursor_lock(on: bool) — Hides and captures the mouse cursor (first-person look: read mouse movement with axis("look")) or gives it back. Honored by the standalone player; resets when the game stops.
    key(name: string) -> bool — Whether a key is held ("w", "space", "left", ...).
    key_pressed(name: string) -> bool — Whether a key was pressed this tick (once per press).
    pressed(name: string) -> bool — Whether an input action was pressed this tick.
    quit_game() — Closes the game (a "Quit" menu button). The standalone player exits; the editor ignores it.
    released(name: string) -> bool — Whether an input action was released this tick.
  [list]
    list|map.clear() — Removes everything.
    string|list|map.contains(item) -> bool — Lists: has an equal item. Maps: has the key. Strings: has the substring. (Same as `x in y`.)
    list.first() -> any — The first item (none if empty).
    string|list.index_of(item) -> number — Position of the first equal item/substring, or -1.
    list.insert(index: number, item) — Inserts an item before index (index = length appends).
    string|list|map.is_empty() -> bool — Whether it has no items / keys / characters.
    list.join(separator: string?) -> string — Text of all items joined by a separator.
    list.last() -> any — The last item (none if empty).
    list.pop() -> any — Removes and returns the last item.
    list.push(item) — Appends an item.
    list|map.remove(item_or_key) -> bool — Lists: removes the first item equal to the argument. Maps: removes a key. Returns whether something was removed.
    list.remove_at(index: number) -> any — Removes and returns the item at index.
    list.reverse() — Reverses the list in place.
    string|list.slice(from: number, to: number?) -> string|list — Items (or characters) from index `from` up to, not including, `to`. Negative indexes count from the end.
    list.sort() — Sorts numbers or strings in place (ascending).
    list.sorted() -> list — A sorted copy (numbers or strings).
    list.sum() -> number — Sum of a list of numbers.
  [locale]
    locale() -> string — The current locale code ("en", "fr", "pt-BR").
    locales() -> list — Locale codes the game has strings for (with the source language), sorted: for a language menu.
    set_locale(code: string) — Switches the game's language from the next frame (a language menu): "fr", "pt-BR". Texts written as "@key" and #line dialogue lines follow at once. Undone when play stops; save it with game_var to keep it.
    tr(key: string, args: map?) -> string — The localized string for a key in the current locale (locale/*.csv or *.po), falling back pt-BR -> pt -> the source language. `args` fill {placeholders}, plurals ({n, plural, one {# coin} other {# coins}}) and selects; numbers are formatted for the locale. A missing key returns the key and is reported by locale_check.
  [map]
    map.get(key: string, default?) -> any — Value for a key, or the default (none) if missing.
    map.has(key: string) -> bool — Whether the map has a key.
    map.keys() -> list — The keys, in insertion order.
    map.set(key: string, value) — Sets a key (same as m[key] = value).
    map.values() -> list — The values, in insertion order.
  [math]
    abs(x: number) -> number — Absolute value.
    acos(x: number) -> number — Arc cosine in radians (x is clamped to -1..1).
    approach(current: number, target: number, max_step: number) -> number — Moves current toward target by at most max_step (never overshoots).
    asin(x: number) -> number — Arc sine in radians (x is clamped to -1..1).
    atan(x: number) -> number — Arc tangent in radians.
    atan2(y: number, x: number) -> number — Angle of the point (x, y) in radians, -pi..pi.
    ceil(x: number) -> number — Smallest whole number >= x.
    clamp(x: number, lo: number, hi: number) -> number — x limited to the range lo..hi.
    cos(radians: number) -> number — Cosine of an angle in radians.
    deg(radians: number) -> number — Radians to degrees.
    exp(x: number) -> number — e raised to x.
    floor(x: number) -> number — Largest whole number <= x.
    inverse_lerp(a: number, b: number, x: number) -> number — Where x lies between a (0) and b (1).
    lerp(a: number|vector|color, b: number|vector|color, t: number) -> number|vector|color — Linear blend from a (t=0) to b (t=1); numbers, vectors or colors.
    ln(x: number) -> number — Natural logarithm (x > 0).
    max(a: number|list, b: number?, ...) -> number — Larger of numbers, or the largest number in a list.
    min(a: number|list, b: number?, ...) -> number — Smaller of numbers, or the smallest number in a list.
    noise(x: number, y: number?) -> number — Smooth deterministic value noise in -1..1 (1D or 2D).
    pow(base: number, exponent: number) -> number — base raised to exponent.
    rad(degrees: number) -> number — Degrees to radians.
    round(x: number, digits: number?) -> number — Rounds to the nearest whole number, or to `digits` decimals.
    sign(x: number) -> number — -1, 0 or 1.
    sin(radians: number) -> number — Sine of an angle in radians.
    smoothstep(edge0: number, edge1: number, x: number) -> number — Smooth 0..1 ramp between two edges.
    sqrt(x: number) -> number — Square root (0 for negative input).
    tan(radians: number) -> number — Tangent of an angle in radians.
  [navigation]
    arrived(e: entity) -> bool — Whether a nav agent reached its destination.
    navigate(e: entity, target: vector|entity) — Walks a nav agent to a point, or follows an entity as it moves. `on event "arrived"` fires on arrival.
    path_length(from: vector|entity, to: vector|entity) -> none|number — Walking distance along the navmesh; none if unreachable or there is no navmesh.
    stop_navigation(e: entity) — Stops a nav agent.
  [physics]
    impulse(e: entity, impulse: vector) — An instant kick (N s) to a dynamic body.
    overlap_sphere(center: vector|entity, radius: number, tag: string?) -> none|entity — Nearest entity (not self) whose collider overlaps the sphere, optionally with a tag; none if empty.
    push(e: entity, force: vector) — Applies a continuous force (N) to a dynamic body this step.
    raycast(origin: vector|entity, direction: vector, max_distance: number?) -> none|entity — First collider hit along a ray (self is ignored); sets hit_point, hit_normal and hit_distance.
    torque(e: entity, torque: vector) — Applies a torque (N m) to a dynamic body.
    velocity(e: entity) -> vector — Current linear velocity of a body or character (m/s).
  [physics2d]
    impulse2d(e: entity, impulse: vector) — An instant kick (N s, x/y) to a dynamic body2d.
    overlap2d(center: vector|entity, radius: number, tag: string?) -> none|entity — Nearest entity (not self) whose 2D collider overlaps the circle, optionally with a tag; sensors are ignored; none if empty.
    point2d(point: vector|entity, tag: string?) -> none|entity — Entity whose 2D collider contains the point (sensors included, self excluded), optionally with a tag; none if empty.
    push2d(e: entity, force: vector) — Applies a continuous force (N, x/y) to a dynamic body2d this tick.
    raycast2d(origin: vector|entity, direction: vector, max_distance: number?) -> none|entity — First 2D collider hit along a ray on the XY plane (self is ignored, sensors too); sets hit_point, hit_normal and hit_distance.
    set_velocity2d(e: entity, velocity: vector) — Sets the velocity of a body2d (dynamic or kinematic) or character2d (knockback, launch pads).
    torque2d(e: entity, torque: number) — Applies a torque (N m, counter-clockwise) to a dynamic body2d.
    velocity2d(e: entity) -> vector — Current velocity of a body2d or character2d (units/s, z = 0).
  [random]
    chance(p: number) -> bool — true with probability p (0..1).
    pick(items: list) -> any — A random element of a list (none if empty).
    random(lo_or_hi: number?, hi: number?) -> number — random() is 0..1; random(hi) is 0..hi; random(lo, hi) is lo..hi. Seeded by the scene: replays exactly.
    random_int(lo: number, hi: number) -> number — A whole number from lo to hi (both included).
    shuffle(items: list) -> list — A shuffled copy of a list.
  [render]
    layer_mask(layers: number|string|list, ...) -> number — Render layer bitmask from layer names (game.json render.layers), layer numbers as strings ("3"), "all" / "none", or a list of names / layer numbers; several arguments are combined. Set it on mesh.layers, camera.cullMask or light.cullMask, e.g. hide the player's own body from the first-person camera.
    probe_bake(probe: entity?) — Re-captures a reflection probe (or every probe without an argument) over the next rendered frames: after opening a door, switching the room's lights or rearranging furniture, so `once` probes reflect the new state. Rendering only; the simulation is unaffected.
  [save]
    delete_save(slot: string) -> bool — Deletes a slot. Returns whether there was a save to delete.
    game_var(name: string, value?) -> any — Reads (or with a value, sets) a global game variable: state that belongs to the game, not to one entity (chapter, flags, unlocked levels, settings). Saved with every save; reset when play stops. Setting none removes it.
    has_save(slot: string) -> bool — Whether a slot holds a save (a "Continue" button shows only then).
    list_saves() -> list — Every save, sorted by slot: maps {slot, meta, play_time, saved_at, version, scene}; damaged files have an `error` instead. For load / save menus.
    load_game(slot: string) -> bool — Loads a slot at the end of this tick: persisted entities, game vars, the exact behavior state and the scene return to the moment of the save. Returns false (and does nothing) when the slot is empty. `on loaded` follows next tick.
    save_game(slot: string, meta: map?) — Saves the game into a slot at the end of this tick: every entity with a `persist` component, game_var values, the scene and the play time. `meta` is shown in save menus (title, chapter, thumbnail). `on saved` follows next tick (`on event "save_failed"` on error). Slots: "slot1", "autosave", "quicksave"...
  [scene]
    add_tag(e: entity, tag: string) — Adds a tag to an entity.
    change_scene(scene: string, options: map?) — Moves the game to another scene (a game.json "scenes" alias or a .sky.json path) after this tick: the current scene hears `on scene_unloading`, entities with a `carry` component (and options.keep) carry over with their running behaviors, the rest is replaced. Options: transition ("fade" | "crossfade" | "none" or {kind, duration, color}), duration, keep: [names], spawn_at: "EntityName" (the player moves there), loading: a loading scene shown while assets preload. `on scene_loaded` follows. Stopping play returns the editor to the scene play started in.
    children(e: entity) -> list — Direct children of an entity, in order.
    count(tag: string) -> number — How many entities have a tag.
    current_scene() -> string — The scene the game is in: its game.json alias, else its path.
    exists(e) -> bool — Whether a value is an entity that still exists.
    find(name: string) -> none|entity — Entity by name (or "#id"); none if missing. "%Name" finds the entity marked unique (entity_update unique=true) inside this prefab instance, else in the scene, so each copy of a prefab finds its own part.
    find_all(tag: string) -> list — Active entities with a tag, in scene order.
    has(e: entity, component: string) -> bool — Whether the entity has a component ("light", "particles", ...).
    load_additive(scene: string, options: map?) -> string — Adds a scene's entities to the running one at the end of this tick (a room, a streaming chunk, a UI overlay) and returns its handle for unload_scene. Options: id (handle), parent (entity to load under), offset (vector added to its root positions). It owns exactly the entities it created.
    loading_progress() -> number — How far the next scene has preloaded, 0..1 (1 when nothing is loading): for a loading bar in a loading scene.
    nearest(tag: string, max_distance: number?) -> none|entity — Closest other active entity with a tag (within max_distance); none if there is none.
    remove_tag(e: entity, tag: string) — Removes a tag from an entity.
    set_parent(e: entity, parent: none|entity, keep_world: bool?) — Moves an entity under a new parent, or to the scene root with none. By default it keeps its world position, rotation and scale (keep_world = false keeps its local transform instead, so it jumps to the same offset from the new parent). Parenting under itself or a descendant fails. Like every play-time change, it is undone when play stops.
    spawn(mesh: string, position: vector|entity?, name?) -> entity — Creates an entity: a primitive mesh ("cube", "sphere"...), "asset:models/x.glb", or a whole prefab "prefab:prefabs/coin.prefab.json" (with its children and behaviors). Its behaviors start next tick. Limits: 256 spawns per tick, 20000 entities.
    tagged(e, tag: string) -> bool — Whether an entity has a tag (false for none).
    unload_scene(handle: string) — Removes a sub-scene loaded with load_additive: its entities hear `on scene_unloading` next tick and are removed the tick after. Entities the game added under it are kept (moved to the root).
  [text]
    num(text) -> none|number — Number parsed from text (none if it is not a number).
    str(value) -> string — Text form of any value (entities give their name).
    type_of(value) -> string — The type name: number, bool, string, vector, color, entity, list, map, none.
    string.ends_with(suffix: string) -> bool — Whether the text ends with a suffix.
    string.lower() -> string — Lowercase copy.
    string.replace(old: string, new: string) -> string — Copy with every occurrence of old replaced.
    string.split(separator: string?) -> list — Parts of the text between separators (default: spaces).
    string.starts_with(prefix: string) -> bool — Whether the text starts with a prefix.
    string.trim() -> string — Copy without leading/trailing spaces.
    string.upper() -> string — Uppercase copy.
  [time]
    is_paused() -> bool — True while the game is paused (or will be from the next tick, after pause_game()).
    pause_game(paused: bool?) — Pauses the game (a pause menu) from the next tick: `pausable` entities (the default) stop — behaviors, physics, animation, particles, sounds — while UI canvases and entities with process mode `always` or `when_paused` keep running. Sends `on pause` to every behavior. pause_game(false) = resume_game().
    resume_game() — Resumes a paused game from the next tick and sends `on resume`.
    teleport(entity: entity, position: vector|entity?) — Moves an entity instantly (when given a position) and tells render interpolation not to smear it across the screen: respawns, portals, checkpoints. Without a position it only resets the smoothing for this frame.
    time_scale(scale: number?) -> number — Slow motion / fast forward: time_scale(0.3) makes the game clock run at 30% from the next tick (dt, timers, waits, physics, animation, particles; 0..10). Entities on the `real` clock (UI, process clock real) ignore it. Returns the scale (the requested one).
    unscaled_dt() -> number — Real seconds per tick (1/60), whatever the time scale or pause: timers that must ignore slow motion.
    unscaled_time() -> number — Real seconds since play started (keeps counting while the game is paused or slowed; `time` does not).
  [vector]
    cross(a: vector, b: vector) -> vector — Cross product.
    direction(from: vector|entity, to: vector|entity) -> vector — Unit vector pointing from one point to another.
    distance(a: vector|entity, b: vector|entity) -> number — Distance between two points; entities count as their world position.
    dot(a: vector, b: vector) -> number — Dot product.
    forward(e: entity) -> vector — World direction the entity faces (its -Z axis).
    length(v: vector) -> number — Length (magnitude) of a vector.
    normalize(v: vector) -> vector — Vector scaled to length 1 (zero stays zero).
    right(e: entity) -> vector — World direction of the entity's right side (+X).
    up(e: entity) -> vector — World direction of the entity's up axis (+Y).
    vec(x: number, y: number, z: number) -> vector — Makes a vector (same as (x, y, z)).
    world_position(e: entity) -> vector — World position (self.position is relative to the parent).
  [vehicle]
    vehicle_drive(e: entity, throttle: number, steer: number, brake: number?, handbrake: number?) — Sets a vehicle's inputs for this tick: throttle 0..1, steer -1 (left)..1 (right), brake 0..1, handbrake 0..1. Overrides the player's drive actions this tick; with control "script" it is the only driver. Holding brake at a standstill reverses (autoReverse).
    vehicle_shift(e: entity, gear: number) — Manual gearbox: selects a gear (-1 reverse, 0 neutral, 1..). Automatic gearboxes shift by themselves.
    vehicle_speed(e: entity) -> number — Speed along the vehicle's heading in km/h (negative reversing).
    vehicle_state(e: entity) -> map — Live vehicle state: speed (km/h), rpm, gear, wheels_on_ground, skid 0..1, drift_angle (degrees), lateral_g, longitudinal_g, load 0..1 and skidding (a list of contact points of sliding wheels, for smoke and marks).
    vehicle_wheel(e: entity, wheel: number|string) -> none|map — One wheel's live state by index (0-based) or name ("rear_left"): contact, point, normal, surface, load (N), slip_ratio, slip_angle (degrees), skid 0..1, compression 0..1, steer, rpm, driven. none before play. Tire smoke and skid marks: spawn at `point` while `skid` > 0.3.
SUBSYSTEM TRIGGERS
    on action — An input action was pressed: on action "jump" (actions come from input.json).
    on collide — Two bodies touched: on collide ("name or tag")? — other, contact_point, contact_normal, impact.
    on collide_end — Two 2D bodies stopped touching: on collide_end — other. data: {}
    on dialogue — `on dialogue "start" | "line" | "choice" | "end" | "<command>"`: conversation events and <<command>>s of .dialogue scripts (event "dialogue:...").
    on impact — A 2D body hit this one faster than physics2d_world.impactSpeed: on impact — other, data. data: {point: vec, normal: vec, speed: number, impulse: number}
    on loaded — A save was loaded (load_game or the load_game tool): on loaded — data.slot, data.version, data.meta. Refresh what is derived from saved state (HUD, music). data: {slot: string, version: number, meta: map}
    on pause — The game was paused (pause_game): delivered to every behavior, also those the pause stops.
    on resume — The game resumed (resume_game).
    on saved — A save_game() finished: on saved — data.slot, data.meta. data: {slot: string, meta: map}
    on scene_loaded — A scene finished loading: on scene_loaded — data.id (alias or path, or a sub-scene's handle), data.path, data.additive. data: {id: string, path: string, additive: bool}
    on scene_unloading — A scene is about to go: on scene_unloading — data.id, data.to (the next scene), data.additive. Delivered the tick before the change, to the leaving scene too. data: {id: string, to: string, additive: bool}
    on trigger_enter — Something entered this trigger collider: on trigger_enter ("name or tag")? — other.
    on trigger_exit — Something left this trigger collider: on trigger_exit ("name or tag")? — other.
    on ui — `on ui "Name"`: the button/toggle/slider/input named Name was used (event "ui:Name").
More: wander_reference topic="<category or function>" for details and examples.