Docs Quick code
The language
Values, variables and their scopes, maths, text, conditions and loops.
#Lines and comments
- Write one statement per line (several on a line work too). A
;at the end of a line is allowed and ignored. - Comments:
--to the end of the line,--[[ … ]]across lines, and a line starting with#is a comment too. - Capitals matter in names:
coinsandCoinsare different variables.
#Values
| Kind | Looks like | type(x) |
|---|---|---|
| Number | 3, 2.5, -1, 1e3, 0x1F |
"number" |
| Text | "hello" or 'hello' (escapes: \n, \t, \") |
"text" |
| True / false | true, false |
"bool" |
| Nothing | nil (null works too) |
"nil" |
| List | [1, 2, 3] or {1, 2, 3} |
"list" |
| Table | {hp = 10, name = "Rat"} |
"table" |
| Vector | vec(1, 0, 2) |
"vector" |
| Function | function(x) return x * 2 end |
"function" |
| Object | self, player, object("door") |
"object" |
Truth: false, nil and 0 count as false; everything else — text, lists, tables,
objects that exist — counts as true. Whole numbers stay whole (3, not 3.0).
#Variables
coins = coins + 1 -- a game variable: every script sees it, saved with the game
score += 10 -- also -= *= /= %= ..=
local tries = 3 -- local: only this code, only this run
self.opened = true -- this object's own value (see Objects)
| Scope | Where it lives | Lasts |
|---|---|---|
| Game | Explorer ▸ Player ▸ Variables | The whole playthrough, one value everywhere (saved). |
| World | Explorer ▸ a world ▸ World variables | While the player is in that world's levels; another world can have its own with the same name. |
| Local | local x = … |
The block it's in (a function, a loop, an if), for this run. |
| Object | obj.name = …, or Properties ▸ Values for code |
That object, while the game runs (saved). See Objects. |
A variable code sets without it being listed in the Explorer is a game variable that starts at 0 (it shows there as (made by code)). Game variables are saved when they hold numbers, text, true / false, or lists and tables of those; functions, objects and vectors in game variables aren't saved.
Locals are block-scoped: a local made inside a loop or an if disappears at its end,
and doesn't touch a variable of the same name outside. Use locals for anything temporary, so
two scripts never fight over the same name.
local x = 1
for i = 1, 3 do
local x = i * 10 -- a different x, only inside the loop
end
popup(x) -- 1
Several at once: a, b = 1, 2 — and a, b = b, a swaps. Several names from one list take its
items: local ok, msg = pcall(f), x, y = [3, 4].
Names: letters, numbers and _, starting with a letter (door_open, wave2). They can't
be language words (if, end, function…) or the older game functions (popup, give…).
A variable may share its name with a newer built-in (time, keys, data…): calling
time() still works.
#Maths
| Operator | Means | Example |
|---|---|---|
+ - * |
add, subtract, multiply | 2 + 3 * 4 → 14 |
/ |
divide (can make a fraction) | 7 / 2 → 3.5 |
// |
divide, rounded down | 7 // 2 → 3 |
% |
remainder (always 0 or positive) | 7 % 3 → 1, -1 % 3 → 2 |
^ |
power | 2 ^ 10 → 1024 |
-x |
negative | -2 ^ 2 → -4 (power first) |
Brackets ( ) group. Maths functions (abs, min, round, clamp, sin in degrees…) are in
the reference. Vectors add, subtract and multiply too:
vec(1, 0, 0) * 3 + vec(0, 1, 0).
#Comparing and logic
== equal, ~= not equal (!= works too), < > <= >=. Numbers compare as numbers, texts
alphabetically. Values of different kinds are simply not equal ("3" == 3 is false).
and, or, not (also &&, ||, !). Like Lua, and / or give one of their values,
which makes handy defaults:
local name = self.nickname or "stranger" -- "stranger" when nickname is nil
local hp = (self.hp or 0) + 1
#Text
name = "Mira"
popup("Hello, " .. name .. "!") -- .. joins text — and numbers, true / false, nil
popup("Coins: " .. coins)
local line = format("{0} has {1} hp", name, 12) -- "Mira has 12 hp"
local shout = name:upper() -- "MIRA"
+ joins two texts, but not text and a number — .. handles everything. Text functions
(upper, lower, sub, find, split, replace, trim, format…) work both ways:
upper(s) or s:upper(). #s is its length, s[0] its first letter.
#Conditions
if has("Key") > 0 then popup("Unlocked") end -- on one line (end is optional here)
if coins >= 10 then
popup("Rich!")
elseif coins > 0 then
popup("Some coins")
else
popup("Broke")
end
Every block if needs a closing end; Check says which one is missing it. To compare use
== — a single = puts a value in (Check points that out).
#Loops
while n < 5 do n += 1 end -- while a condition holds
for i = 1, 10 do … end -- 1, 2, … 10 (both ends included)
for i = 10, 1, -1 do … end -- count down with a step of -1
for i = 0, 100, 25 do … end -- 0, 25, 50, 75, 100
for o in objects("enemy") do o.hide() end -- each item of a list
for i, v in ["a", "b"] do … end -- index (0, 1, …) and item
for key, value in {hp = 3, mp = 1} do … end
for k in {hp = 3} do … end -- a table with one name: its keys
for i in 3 do … end -- a number counts 1, 2, 3
repeat -- runs at least once
tries -= 1
until tries <= 0 or has("Key") > 0
breakleaves the loop;continueskips to its next round.- A loop with one statement can sit on one line:
for i = 1, 3 do give("Coin") end.
#Loops can't freeze the game
A loop in a running game that goes round 500 times without waiting pauses for one frame
by itself, as if it had wait(0), and carries on next frame. So while true do … end is fine:
while true do
if key_pressed("E") then popup("E!") end
end
(Adding your own wait(0) or wait(0.1) is still a little cheaper.) Code in a dialogue
runs all at once and can't pause, so an endless loop there is stopped after 10,000 rounds, with
a message in the Output panel. Check also warns about loops that can never stop or never run.