Variables & constants
var
Variables are declared with var. Every scalar declaration must include an initializer. The type annotation is optional when the initializer's type is enough to infer it.
var x: i32 = 10 // annotated and initialized
var y = 5 // type inferred as i32
var z: i32 // error: scalar declaration without initializerThere is no such thing as an uninitialized variable. Every read is guaranteed to see a value the script asked for — never a silent zero.
Scope
Variables are scope-bound:
- A
varat the top level (or inside aclient/serverblock) lives for the lifetime of the script. - A
varinside a block (function body, event body, loop,if) lives until that block ends.
This distinction matters constantly in event-driven code: state that must survive between frames goes outside the event; scratch values go inside.
var last_x = -1 // persists across frames
event frame(frame_num: i32) {
var x = i32(read_u8(0x0086)) // fresh each frame
if x != last_x {
last_x = x
}
}Shadowing
An inner var may reuse an outer name; it creates a new binding for the inner scope without touching the outer one.
var x = 1
if condition {
var x = 2 // shadows the outer x
print(x) // 2
}
print(x) // 1Reassignment
Plain = reassigns an existing binding (no new binding):
var x = 1
x = 2Top-level vars are not hoisted — they take effect at their textual position. (Functions are hoisted; see Functions.)
const
const is like var but the binding can't be reassigned. An initializer is required.
const PLAYER_X: u32 = 0x0086
const MAX_PLAYERS = 32
const GAME_TITLE = "Super Mario Bros."The common uses are memory-address constants and named magic numbers at the top of a script.
const freezes the binding, not the contents. A const array can't be re-pointed at a different array, but its elements are still mutable:
const arr: i32[] = [1, 2, 3]
arr[0] = 99 // allowed — element mutation
// arr = [4,5,6] // error — rebinding a const