LUA Guide


If you want to give custom behaviors to things in Burrow, this is how you do it. You should have a good understanding of LUA before proceeding.

The game has a built-in code editor and runtime environment, so no external tools are needed. (However, there is a folder you can add external scripts to, but this is completely optional. More on this later!)

You may call any of the Burrow API functions from any script at any time. The below definitions should be accurate for version 0.5x of the game.

Beware that later versions of the game may deprecate some of these functions. Don't get too attached to anything until I formally release the game, and we hit version 1.0!


All scripts can have a start(state), update(state,time), and interact(state) function. Burrow's scripting engine will run these functions at the appropriate time. start() will be called once, when the level loads. update() will be called every frame. interact() will be called when the object is interacted with by the player.

Stubs of these methods are provided for you when you create a new script. The "state" argument is a table provided to each of the these functions. Each of the above named functions may return this table as well.


The "state" table passed to each of the special functions has only three keys - "transform", "data", and "creative" (...and optionally "get_child", but don't use that right now, it's not really stable)

Let's start with the "data" key. It returns a table you can use to persist data in the object.

In other words, anything that you add or modify in the "data" table will persist and be passed to future update() and interact() functions for the object. This might be better explained with an example - say in update(), you wrote state["data"]["A"] = 1. Then, everytime update is called after that, state["data"]["A"] will equal 1.

The "transform" table can be used to move the object around.

You can read the position of the object (in meters) by accessing "px","py","pz" in the transform table. So for example, state["transform"]["px"] will return the X position of the object. You can read the rotation of the object (euler angles, in degrees) by accessing "ax","ay","az" in the transform table. Also! To change the transforms of these objects, you can change the values in the "transform" table. state["transform"]["py"] = 10 will over-write the Y position of the object to '10'.

The "creative" key simply returns true if the game is being run in creative mode, false otherwise.

Update also gets a 'time' argument passed to it, which is the time in seconds since update was last called. Most of the time, this should be around 1/60 (because script updates are capped at 60 FPS).


Limits are placed on total instructions allowed per frame, and total memory allowed to be used by the LUA scripts.

You may not execute more than 25,000 instructions per frame.

You may not allocate more than 200 MB of memory. (I will likely tighten this later.)

If Burrow sees that you're exceeding either of these limits, I will find you, and I will disable all your scripts. And then your level almost certainly wont work, so be cautious.


All scripts are run once to be loaded into the global context (via DoString). They also run in the same environment! This makes inter-script communication trivial - any variable in any script can be accessed anywhere else.

This also means you need to be careful! Use local variables inside functions religiously, and save any object-specific data in state["data"] instead of using global variables.

and now, folks, I present:



The currency of Burrow is "chips". Yes, like poker chips. If you need a way to keep track of something money-eqsue, this is your best bet right now.

Chips stack in the player's inventory, and can be dropped to be transferred between players. A player can have a maximum of 9,999 chips.

Chips spawn relative to the object that spawns the chips. For now.

spawnMoney(float x, float y, float z, int count)

Spawns COUNT chips at XYZ. They will automatically be made into a stack.

takeMoney(int count)

Takes COUNT chips from the player. Returns TRUE if the player had enough chips- this also means the chips were taken from the player. Returns FALSE if the player does not have this many chips.


You can use the below functions to spawn panels, text, and buttons. The player will not be allowed to move or take actions while any UI element is being displayed.

Use clearUI() to allow the player to move again.

In VR, these elements will manifest near the player's hand. You don't need to do anything special to make sure these work in VR - If it looks good on desktop, it'll look good in VR.

LUA don't got no enums- so we have some special arguments that I need to tell you about.

ANCHOR refers to where a UI element will be attached to on screen. For example, if you pass an ANCHOR of "left" and an xOffset and yOffset of (0,0), your element will be placed up against the left edge of the screen. Everytime you see "string anchor" passed as an argument, you must supply one of these strings:
"top" "left" "bottom" "right"
"top left" "top right" "bottom left" bottom right"

COLOR refers to what color the spawned UI element will be. You must pick from this list:
"white" "beige" "blue" "brown"

SIZE is a little abstract, just know it's an integer from 1 to 5. I will flesh out exactly how this works later.
Try not to go smaller than 2, 1 can be a little hard to read.

spawnUIPanel(float xOffset, float yOffset, string anchor, int size, string color)

Spawns a panel with size SIZE and color COLOR anchored at ANCHOR with an offset of distance (xOffset, yOffset).

spawnUIButton(float xOffset, float yOffset, string anchor, int size, string color, string text, string callbackFunction)

Spawns a button with size SIZE and color COLOR and text TEXT anchored at ANCHOR with an offset of distance (xOffset, yOffset).
The callback function is a string that designates the name of the custom function that should be called when the button is clicked.
(This is a function that you write, and it can do whatever you want)

spawnUIText(float xOffset, float yOffset, string anchor, int size, string color, string text)

Spawns text with size SIZE and color COLOR and text TEXT anchored at ANCHOR with an offset of distance (xOffset, yOffset).


Clears all UI elements from the screen and allows the player to move again. (HINT: very powerful when used in a button callback)


Like any over-ambitious indie game, Burrow has a day/night system. This does not affect any gameplay (other than, you know, making the world dark or bright) unless you want it to.

The sun can be set to any time of day from 0:00 to 23:59. I am sincerely sorry for using military time.

You can also control the rate at which the day/night cycle passes, or choose to freeze the sun where it is.

There will also be controls for rain coming soon. Rain decreases visibility and is noisy.

The sun rises at 6:00 and sets at 18:00, but there is twilight.

setSecondsPerHour(float seconds)

In terms of the day/night cycle, an hour will now last SECONDS seconds. Pass 0 to stop time from changing altogether.

setHour(float hour)

Set the day/night cycle to the target hour. For example, passing 13.5 will set the time to 13:30 (or 1:30 PM).


Returns the current hour of the day night cycle. Good if you want something to trigger at a specific time of day.


print(string message)

Prints a message, you can read it under "script log".

setAIMode(int mode)

This function is intended to be run ONLY on AI objects.
It also only takes effect in "play" mode. So be weary.
Also, Also, currently, it only works on snakes.

In short, you can use this to make your snake slayin' maps, but it may be better to wait until 0.5.

Pass 0 to make snakes idle. They will not move, or attack.
Pass 1 to use manual snake movement. You will manually have to steer the AI every frame with setAIMove(x,z) and setAIGoal(x,z).
Pass 2 to use automatic snake movement. They will automatically hunt down the player and attack them. (This is probably what you want to pass most of the time)

setAIMove(float x, float z)

Move the snake along the X and Z axis. This vector will be normalized. They will automatically steer to the player. Only compatible with setAIMode(1).

setAIGoal(float x, float z)

Move the snake to the XZ coordinate. They will automatically avoid obstactles. Only compatible with setAIMode(1).


Returns a table holding the players position, with "x","y","z" as the keys.
For example you can use getPlayerPos()["x"] to get the player's x coordinate.

launchBurrowTask(string funcname)

Oh boy, this is a complicated one.
Use this as you would a "thread" in other programming environments, to do work on a long running script that can't finish on a single frame.
It's not REALLY a thread, since it will use the extra instructions you didn't use from your 25000 limit each frame to work on this, and then yield automatically.
See the "Chess" level for an example of how this works.
Caution: Don't use functions lua can't yield arbitrarily from, such as "table.sort"