Skip to content

Lua API reference

Generated from the engine's bindings each time the site is built (tools/docs_site/lua_api.py), so it lists exactly what exists on main. How to use them, with examples, is in Scripting; the tutorials use them step by step.

Each table exists only when its module is in the game: no RigidBodyModule, no physics. Arguments in {} are one table of named fields, for example physics.box{pos = Vec(0, 1, 0), size = Vec(1, 1, 1)}.

Vec

Function Defined in
Vec(x, y, z) ScriptVM.cpp:167

hook

Function Defined in
hook.Add(event, name, fn) ScriptVM.cpp:44
hook.GetTable() ScriptVM.cpp:59
hook.Remove(event, name) ScriptVM.cpp:54
hook.Run(event, ...) ScriptVM.cpp:69

timer

Function Defined in
timer.Create(name, delay, reps, fn) ScriptVM.cpp:83
timer.Exists(name) ScriptVM.cpp:89
timer.Remove(name) ScriptVM.cpp:88
timer.Simple(delay, fn) ScriptVM.cpp:80

__kke_nettable

Function Defined in
__kke_nettable.clear ScriptTables.cpp:152
__kke_nettable.count ScriptTables.cpp:147
__kke_nettable.get ScriptTables.cpp:119
__kke_nettable.remove ScriptTables.cpp:128
__kke_nettable.rows ScriptTables.cpp:135
__kke_nettable.set ScriptTables.cpp:110

__kke_netview

Function Defined in
__kke_netview.count ScriptTables.cpp:182
__kke_netview.get ScriptTables.cpp:168
__kke_netview.ready ScriptTables.cpp:178
__kke_netview.rows ScriptTables.cpp:157
__kke_netview.stop ScriptTables.cpp:187

ai

Creatures with a mind ("Creatures" below, docs/AI.md "Lua"): add(inst, species), orders goTo/follow/attack/hold/flee/fetch/free, anims(inst, {idle, walk, run, ...}), actor(id, pos [, species, velocity]), doing, need, knows, noise, ...

Function Defined in
ai.actor ScriptBindings.cpp:1361
ai.anims ScriptBindings.cpp:1377

audio

impact(pos, material, intensity) (material id or name), materials() → {Stone = 1, Wood = 2, ...}; the game's own files (AUDIO.md "Sounds and music from scripts"): sound(file) → id, play(sound, {pos, volume, pitch, loop, near, range, fade, category}) → voice, stop(voice [, fade]), move, volume(voice, v [, seconds]), playing; music(file or nil [, {fade, volume}]) crossfades; bus(category [, v [, seconds]]), snapshot({music = 0.4, ...} [, seconds]), duck(by, target [, {volume, attack, release}]), clearDucks()

Function Defined in
audio.bus ScriptBindings.cpp:1092
audio.clearDucks ScriptBindings.cpp:1141
audio.duck ScriptBindings.cpp:1127
audio.impact ScriptModule.cpp:454
audio.materials ScriptModule.cpp:467
audio.move ScriptBindings.cpp:1052
audio.music ScriptBindings.cpp:1067
audio.play ScriptBindings.cpp:990
audio.playing ScriptBindings.cpp:1062
audio.snapshot ScriptBindings.cpp:1100
audio.sound ScriptBindings.cpp:968
audio.stop ScriptBindings.cpp:1044
audio.volume ScriptBindings.cpp:1057

breakable

FEMFX objects that really break. box{pos, size, material, pattern, cells, chunk, velocity, arm} → id (material glass, stone, wood, ice, iron; pattern shards, voronoi, splinters, radial, solid, default by material), ball{pos, radius, velocity, material} → id (iron by default: a projectile), remove(id), broken(id), pieces(id), count(). The Break hook says when one breaks.

Function Defined in
breakable.ball ScriptBindings.cpp:396
breakable.box ScriptBindings.cpp:354
breakable.broken ScriptBindings.cpp:435
breakable.count ScriptBindings.cpp:443
breakable.pieces ScriptBindings.cpp:439
breakable.remove ScriptBindings.cpp:427

camera

position(), target(), forward(), fov(): what the player sees (during a cutscene, its shot). Cutscenes in any game: path(shots, opts) (shots {pos=, look=, fov=, t=}; opts loop, hold, blend, blendOut, seconds when the shots have no t; returns its length), hold(pos, look [, {fov=, blend=}]), release([blend]), directing(), shake(strength 0..1 [, seconds]). Hook CameraDone when a path ends (cameras, kke/CameraDirector.h)

Function Defined in
camera.directing ScriptCamera.cpp:109
camera.forward ScriptCamera.cpp:46
camera.fov ScriptCamera.cpp:51
camera.hold ScriptCamera.cpp:91
camera.path ScriptCamera.cpp:54
camera.position ScriptCamera.cpp:44
camera.release ScriptCamera.cpp:105
camera.shake ScriptCamera.cpp:110
camera.target ScriptCamera.cpp:45

clock

Time of day (MOODS.md "Time of day"): start{hour, dayLength, noon, sunrise, sunset}, set(hour), pause, resume, stop, hour(), time() → "07:30", isDay(), running(), sun() → direction, elevation, dayLength([seconds]); hooks Dawn, Dusk, Hour (e.hour)

Function Defined in
clock.dayLength ScriptClock.cpp:140
clock.hour ScriptClock.cpp:112
clock.isDay ScriptClock.cpp:124
clock.pause ScriptClock.cpp:94
clock.resume ScriptClock.cpp:98
clock.running ScriptClock.cpp:128
clock.set ScriptClock.cpp:87
clock.start ScriptClock.cpp:71
clock.stop ScriptClock.cpp:107
clock.sun ScriptClock.cpp:133
clock.time ScriptClock.cpp:117

decal

Marks laid onto surfaces (DECALS.md): place(texture, pos, opts) → id, or nil and the reason (a built-in, textures() lists them, or assets/decals/<name>.png); opts: normal (out of the surface, default up), size (m, default 1), depth, angle (radians), color, opacity, roughness (0.05 wet, -1 keeps the surface's), life and fade (s; 0 stays); remove(id) → true if it was there, clear(), count(). 1024 at once; the oldest go first

Function Defined in
decal.clear ScriptModule.cpp:282
decal.count ScriptModule.cpp:286
decal.place ScriptModule.cpp:256
decal.remove ScriptModule.cpp:278
decal.textures ScriptModule.cpp:290

fx

Particle effects by name (effects.lua, the list): play(name, pos, opts) → true, or nil and the reason (an unknown name); start(name, pos, opts) → id (keeps going), move(id, pos, opts), stop(id) (what's in the air finishes), count() → this script's running effects, names(), define(name, effect) → true, or nil and what's wrong (an effect as a Lua table, the fields of the YAML), wind(vec) (m/s; smoke and flakes drift); opts: normal, velocity, scale, floor. 8000 particles for all scripts together; the oldest go first

Function Defined in
fx.count ScriptModule.cpp:346
fx.define ScriptModule.cpp:359
fx.move ScriptModule.cpp:335
fx.names ScriptModule.cpp:350
fx.play ScriptModule.cpp:316
fx.start ScriptModule.cpp:322
fx.stop ScriptModule.cpp:340
fx.wind ScriptModule.cpp:373

input

define(id, label, defaultKey [, padButton]) (pad button names: "a", "b", "x", "y", "lb", "rb", "lt", "rt", "start", "back", "dpad_up"...), pressed(id), held(id), value(id); actions show up in the rebinding screen like any other. Button prompts (INPUT.md "Button prompts"): style([player]) → "keyboard", "xbox", "playstation", "switch", "steamdeck", "steamcontroller" or "touch", the device the player uses now; prompt(action or button [, label, player]) → RML with the button's picture (for ui.rml); promptText("{jump} jump, {sprint} run" [, player]) → RML; glyph(action or button [, player or style]) → the picture's path (for your own <img>), or nil + why. In documents, <prompt action="jump" label="Jump"/> redraws by itself.

Function Defined in
input.define ScriptModule.cpp:380
input.glyph ScriptModule.cpp:419
input.held ScriptModule.cpp:406
input.pressed ScriptModule.cpp:405
input.prompt ScriptModule.cpp:440
input.promptText ScriptModule.cpp:446
input.style ScriptModule.cpp:415
input.value ScriptModule.cpp:407

kke

log(...), time(), dt() (and plain print)

Function Defined in
kke.dt ServerScripts.cpp:402
kke.log ServerScripts.cpp:389
kke.time ServerScripts.cpp:401

light

Lamps (lamps.lua): point{pos, color, intensity, range, shadows} → id, or nil and the reason when every light is in use (16 in all: light 0 is the sun, and a game's own lights take slots too); range in metres (default 10; 0 = reaches everywhere); shadows = true casts shadows (the first 4 lights that ask); move(id, pos), set(id, {color, intensity, range, shadows, on}) (missing fields stay as they are), remove(id), count() → this script's lights

Function Defined in
light.count ScriptModule.cpp:250
light.move ScriptModule.cpp:232
light.point ScriptModule.cpp:209
light.remove ScriptModule.cpp:246
light.set ScriptModule.cpp:236

models

load(name) → model (an asset name: a model in the game's own models/ folder by file name, e.g. "Fox" for models/Fox.glb, or from an installed pack, e.g. "SM_Prop_Crate_01", or a path inside the game's folder; nil + reason if missing), spawn(model, {pos, yaw, scale, tint}) → instance, move(inst, pos [, yaw, scale]), remove(inst), tint(inst, Vec), visible(inst, bool), play(inst, clip [, loop, speed]) (clip name or number; nil stops), event(model, clip, seconds, name) (an animation event: the AnimEvent hook runs each time a script model playing that clip passes seconds, a looping clip every cycle; event(model, clip, nil) clears the clip's; MOVEMENT.md "Animation events"), clips(model) → names, bounds(model) → min, max, position(inst) → pos, yaw

Function Defined in
models.bounds ScriptBindings.cpp:301
models.clips ScriptBindings.cpp:290
models.event ScriptBindings.cpp:272
models.load ScriptBindings.cpp:166
models.move ScriptBindings.cpp:213
models.play ScriptBindings.cpp:263
models.position ScriptBindings.cpp:220
models.remove ScriptBindings.cpp:226
models.spawn ScriptBindings.cpp:187
models.tint ScriptBindings.cpp:233
models.visible ScriptBindings.cpp:237

mood

The sky, sun, fog, colour look and ambience in one go (MOODS.md): set(name) → true, or false and the reason ("clear_day", "golden_hour", "sunset", "night", "misty_morning", ... or a mood file of the game's own in moods/), current() → name, list() → names

Function Defined in
mood.current ScriptModule.cpp:197
mood.list ScriptModule.cpp:198
mood.set ScriptModule.cpp:187

Pathfinding ("Finding the way" below): build({radius, height, climb, slope, cell, tile, dynamic}) → true, info, path(from, to) → points, partial, walkable(from, to), nearest(pos [, reach]), move(from, to), random(centre, radius), obstacle{pos, size, yaw} or {pos, radius, height} → id, remove(id), ready()

Function Defined in
nav.build ScriptBindings.cpp:1157
nav.move ScriptBindings.cpp:1259
nav.nearest ScriptBindings.cpp:1247
nav.obstacle ScriptBindings.cpp:1283
nav.path ScriptBindings.cpp:1222
nav.random ScriptBindings.cpp:1264
nav.ready ScriptBindings.cpp:1217
nav.remove ScriptBindings.cpp:1312
nav.walkable ScriptBindings.cpp:1239

net

role() ("offline", "host", "client"), isServer(), connected(), playerId(), players() → { {id, name}, ... }, send(name, data): from a client to the host, from the host to every client; data is nil, a boolean, number, string or a table of those (about 500 bytes encoded, one network event); call(name, data [, function(ok, answer) end]) → sent? and handle(name, function(data, from) end): a question to the host and its answer ("Calls" below); table(name) → a synced table (host/server only: :set(key, row), :get(key), :remove(key), :rows(), :count(), :clear()) and watch(name [, filter] [, function(event, key, row, old) end]) → a view (:rows(), :get(key), :ready(), :count(), :stop()) ("Synced tables" below)

Function Defined in
net.call ScriptCalls.cpp:91
net.connected ServerScripts.cpp:407
net.group ServerScripts.cpp:464
net.handle ScriptCalls.cpp:120
net.isServer ServerScripts.cpp:406
net.playerId ServerScripts.cpp:408
net.players ServerScripts.cpp:410
net.role ServerScripts.cpp:405
net.send ServerScripts.cpp:428
net.setGroup ServerScripts.cpp:460
net.showGroups ServerScripts.cpp:468
net.solid ServerScripts.cpp:482
net.table ScriptTables.cpp:199
net.watch ScriptTables.cpp:215

physics

box{pos, size, density, material, color, velocity, bounce, friction, static, visible, glass, cloudy, group} / sphere{pos, radius, ...} → id (visible = false: collides but isn't drawn, an invisible wall; glass = true: see-through, tinted by color, cloudy 0 clear to 1 milky; the look reaches every player); showHidden([on]) → on: draw the invisible ones faintly, on this machine (building a level; also a checkbox in the F1 Scripts panel); remove(id), position(id), velocity(id), setVelocity(id, v), impulse(id, v [, point]), raycast(from, dir [, maxDist]) → {pos, normal, distance, body, material} or nil, count(); joints ("Joints" below): joint{type, a, b, pos, posB, axis, min, max, frequency, damping, friction} → joint or nil + reason, motor(joint, mode [, target, maxForce]), jointValue(joint), removeJoint(joint)

Function Defined in
physics.box ServerScripts.cpp:631
physics.count ServerScripts.cpp:670
physics.impulse ServerScripts.cpp:646
physics.joint ScriptModule.cpp:569
physics.jointValue ScriptModule.cpp:649
physics.motor ScriptModule.cpp:638
physics.position ServerScripts.cpp:643
physics.raycast ServerScripts.cpp:651
physics.remove ServerScripts.cpp:633
physics.removeJoint ScriptModule.cpp:653
physics.setVelocity ServerScripts.cpp:645
physics.showHidden ScriptModule.cpp:527
physics.sphere ServerScripts.cpp:632
physics.velocity ServerScripts.cpp:644

saves

Save slots for a "Load game" menu (SAVING.md): write(slot, data [, {title, playtime}]), read(slot) → data, info, list() newest first, exists, remove, version([n]), migrate(from, fn)

Function Defined in
saves.exists ScriptStore.cpp:297
saves.list ScriptStore.cpp:287
saves.migrate ScriptStore.cpp:212
saves.read ScriptStore.cpp:254
saves.remove ScriptStore.cpp:303
saves.version ScriptStore.cpp:200
saves.write ScriptStore.cpp:228

scene

list() → names in the game's own scenes/ folder and the shared scenes/, load(name, origin) → scene, missing count (or nil + reason), unload(scene), spawnPoint(scene) → pos, yaw

Function Defined in
scene.list ScriptBindings.cpp:615
scene.load ScriptBindings.cpp:634
scene.spawnPoint ScriptBindings.cpp:689
scene.unload ScriptBindings.cpp:680

server

Function Defined in
server.kick ServerScripts.cpp:496
server.name ServerScripts.cpp:488
server.say ServerScripts.cpp:489
server.score ServerScripts.cpp:509
server.top ServerScripts.cpp:528

store

What outlives the session ("Saving" below): save(name, value) → true or false, reason; load(name [, default]); add(name [, n]) → new count; remove(name); keys([prefix]) → names in order

Function Defined in
store.add ScriptStore.cpp:107
store.keys ScriptStore.cpp:93
store.load ScriptStore.cpp:79
store.remove ScriptStore.cpp:88
store.save ScriptStore.cpp:71

terrain

Hills and valleys (TERRAIN.md): create{size, resolution, pos, height, seed, ridged, image, flat, layers} → true, height(x, z) → y, on, ground(pos), normal, slope, raise/lower(pos, radius, metres), smooth(pos, radius [, strength]), flatten(pos, radius [, height, strength]), paint(pos, radius, layer [, strength]), scatter{model, density, layer, maxSlope, scale, align, solid, clear} → group, count, unscatter(group), scattered(), layer, info, remove

Function Defined in
terrain.create ScriptTerrain.cpp:230
terrain.exists ScriptTerrain.cpp:293
terrain.flatten ScriptTerrain.cpp:363
terrain.ground ScriptTerrain.cpp:334
terrain.height ScriptTerrain.cpp:316
terrain.info ScriptTerrain.cpp:298
terrain.layer ScriptTerrain.cpp:378
terrain.lower ScriptTerrain.cpp:351
terrain.normal ScriptTerrain.cpp:323
terrain.paint ScriptTerrain.cpp:370
terrain.raise ScriptTerrain.cpp:346
terrain.remove ScriptTerrain.cpp:481
terrain.scatter ScriptTerrain.cpp:389
terrain.scattered ScriptTerrain.cpp:477
terrain.slope ScriptTerrain.cpp:328
terrain.smooth ScriptTerrain.cpp:357
terrain.unscatter ScriptTerrain.cpp:466

ui

RmlUi documents. open(rml) / load("file.rml") (next to the scripts) → doc, text(doc, id, text) (plain text, shown as typed), rml(doc, id, markup), class(doc, id, name, on), property(doc, id, name, value), show(doc, bool), close(doc), onClick(doc, id, fn), profile() → "phone", "desktop" or "console" (the kind of screen, INPUT.md "Phone, PC and console"; every document's body also has the class kke-phone/kke-desktop/kke-console and kke-portrait/kke-landscape for RCSS)

Function Defined in
ui.class ScriptBindings.cpp:538
ui.close ScriptBindings.cpp:561
ui.load ScriptBindings.cpp:495
ui.onClick ScriptBindings.cpp:578
ui.open ScriptBindings.cpp:491
ui.profile ScriptBindings.cpp:522
ui.property ScriptBindings.cpp:543
ui.rml ScriptBindings.cpp:533
ui.show ScriptBindings.cpp:555
ui.text ScriptBindings.cpp:527

Note

Not described in SCRIPTING.md yet: __kke_nettable, __kke_netview, server.

Your own tables

A game adds its own with ScriptVM::registerFunction from a C++ module. The starter template's player table is the example (tutorial 3):

player

Function Defined in
player.facing PlayerModule.cpp:105
player.position PlayerModule.cpp:97
player.teleport PlayerModule.cpp:101