How To: Using the data class

From PGE Wiki
Jump to: navigation, search

Quest levels can become very frustrating very quickly, since if you die, you have to obtain everything all over again. The use of LunaLua's data class can solve this problem easily. This tutorial will show you how to save variables for a level and an episode, though saving variables for the entirety of the SMBX executable is possible.

Example 1 - Saving Your Level Progress

Say your level revolves around the player hitting switches on different paths to progress. With the data class, you can make these paths as long as you want without having to worry about the player getting too frustrated, as they only have to hit the switch once.

First, you're going to need to create the data.

local myLevelData = Data(Data.DATA_LEVEL, "myData")

Of course, you can change the variable name and "myData" to whatever you want - you'll just have to account for those changes in the following code.

Alternatively, if you want to go the safe route, you can use Encrypt.dll to make your data files an unreadable mess, protecting it from players. However, you can only use this library with natural number values! Decimal numbers, negative numbers and strings are not work.

local encrypt = API.load("encrypt")
local myLevelData = encrypt.Data(Data.DATA_LEVEL, "myData")

Now, as an example, I'll be using a simple one-screen level with a single switch and barrier leading to the exit star. The barrier is on the layer "exampleBarrier", and the switch in question triggers an event "exampleBarrierKill". After loading the data, you have to check if the variable is already set or not.

if myLevelData:get("exampleSwitch") == "" then
    myLevelData:set("exampleSwitch", tostring(1))
    myLevelData:save()
end

Next, we have to make it so the switch in question actually saves the data.

function onEvent(eventname)
    if eventname == "exampleBarrierKill" then
        myLevelData:set("exampleSwitch", tostring(0))
        myLevelData:save()
    end
end

Simple enough. To complete the code, we have to check if the variable is equal to 0 and if it equals 0, hide the barrier as soon as the level starts.

local ranInitialCheck = false;
local barrierData = myLevelData:get("exampleSwitch");

function onStart()
    if barrierData == tostring(0) then
        triggerEvent("exampleBarrierKill")
    end
end

Example 2 - Switch Palace

Now we'll get a bit broader. The code for an episode-wide data saving is similar to the last example's code, but with a few changes. First off, a lunaworld.lua file is required, not a lunadll.lua file.

local myGlobalData = Data(Data.DATA_WORLD, "switchPalace")

Then, check if the data is equal to nil, set the variables accordingly, and create the events and layers needed. Make sure that your event and layer names are very specific, and make sure that you add the layers and events to all of the levels you want to be affected by the code. For this example, we'll be using two layers, "globalBarrierOff" (the layer shown before the switch is hit) and "globalBarrierOn" (the layer that appears after the switch is hit), and one event, "globalBarrierKill". Replace all of the strings needed to be changed from the last example's code with the relevant strings, and your final code should turn out to be this:

local myGlobalData = Data(Data.DATA_WORLD, "switchPalace")

if myGlobalData == nil then
    myGlobalData:set("exampleGlobalSwitch", tostring(1))
    myGlobalData:save()
end

function onEvent(eventname)
    if eventname == "globalBarrierKill" then
        myGlobalData:set("exampleGlobalSwitch", tostring(0))
        myGlobalData:save()
    end
end

local barrierData = myGlobalData:get("exampleGlobalSwitch");

function onStart()
    if barrierData == tostring(0) then
        triggerEvent("globalBarrierKill")
    end
end

This code should allow you to create your own switch palaces within your episodes!

Further Reading

The Data class documentation, containing all possible fields/functions

The global memory map for SMBX