How To: Using the data class
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 integer values! Decimal 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. Since onLoad() runs before a few things are even created, most notably the player, it's much safer to have an "initial run" check in onLoop().
local ranInitialCheck = false;
local barrierData = myLevelData:get("exampleSwitch");
function onLoop()
if ranInitialCheck == false then
if barrierData == tostring(0) then
triggerEvent("exampleBarrierKill")
end
ranInitialCheck = true;
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 ranInitialCheck = false;
local barrierData = myGlobalData:get("exampleGlobalSwitch");
function onLoop()
if ranInitialCheck == false then
if barrierData == tostring(0) then
triggerEvent("globalBarrierKill")
end
ranInitialCheck = true;
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