Save Games and Variables

When creating scripts, you need to be aware of some limitations when it comes to save games. It is possible to create all sorts of variables, tables and whatnot to store data with Lua but the game itself will not necessarily be able save and load the data. Naturally you don’t need to worry about saving when dealing with “normal” assets, like counters, levers, timers and so on but when it comes to scripts a little more attention from the level designer is required. Local variables won’t be stored into save games and it’s preferable to use local variables always when you have data you only need temporarily. Script variables (or variables that are “global” but only within the script entity they are defined in) will be stored in save games but with these you need to be careful that they contain data that is compatible with save games. Script variables can contain numbers (3, 412, 0.15 etc.), strings (“Hello!” and such), booleans (true or false) and tables (which, logically, can not contain any other types of data besides numbers, strings, booleans or other tables).

As a level designer, you have the responsibility of making sure variables are used correctly since the editor will not give warnings or errors about any potential issues! Always test your exported mods thoroughly in-game!

The following is a simple (and a rather silly) example of a script with a script variable and a local variable:

-- super fun number guessing game!
counter = 0                    -- this will be stored in the save
function numberGuess()
    counter = counter + 1
    local randomNumber = math.random(10)    -- this won't be saved
    if randomNumber == 10 then
        hudPrint("I guessed right and it took me only "..counter.." tries!")
    else
        hudPrint("I guessed "..randomNumber.." but I was wrong.")
    end
end

The counter-variable in the script would be saved because it is a script variable with a number in it but the randomNumber local variable won’t, which is preferable in this case since the randomNumber will always be generated again any time we need it while the counter is something we need to persist between saving and loading the game.

If you want to try out the super fun number guessing game, just add it as the target of a connector and give it a go!

As a final note, here are various (most probably impractical) examples of what works and what doesn’t regarding variables:

-- these variables and tables all work and will be stored in the save game:
startingHealth = 10
names = { "John", "Kate", "Boris" }
playerCharacter = {
    name = names[3],
    isAwesome = true,
    stats = { 4, 10, -2, startingHealth }
}

-- Use local variables in functions for data that doesn't need to be saved:
pears = 3
pineapples = 1
function countFruits()
    local fruits = pears + pineapples
    print("I have " .. fruits .. " delicious fruits.")
end

-- this doesn't work (upvalues are not supported):
local bananas = 1
function bananaSplit()
    bananas = bananas * 0.5
end

-- the following does not work when saving/loading:
-- (the variable contains the spawned object in it)
item = spawn("dagger", 1, 16, 4, 0, 0)
print(item.name, item.x, item.y)    -- prints "dagger 16 4" to console

-- the following works because the item variable contains just
-- a string (the id of the object) instead of the object itself
item = "treasure"
spawn("dagger", 1, 16, 4, 0, 0, item)
print(findEntity(item).name, findEntity(item).x, findEntity(item).y)

-- the following is okay since, even though the variable contains an object, it's a local variable:
function spawnTreasure()
    local item = spawn("dagger", 1, 16, 4, 0, 0)
    print("Spawned a "..item.name.." to level "..item.level)
end