Save a highscore variable between builds?

How do i save my highscore so that it is saved when i rebuild the game? I have read alot about sys.save and load etc but i cant get a good grasp of it i feel

Try defsave from asset portal :wink:

BTW what is it that you don’t understand? :thinking:

Do you mean https://www.defold.com/community/projects/87727/?

I’ve read bout it but i still wonder how do i save my highscore variable? For example in defsave it says to save a file named config you type defsave.save(ā€œconfigā€). So if i want to save my highscore variable do i need to create a new file called ā€œconfigā€ where i keep it ? As you see i haven’t really grasped this yet

1 Like

sys.save/load is simple to use, when you get the idea. To save, you just pass a table containing your variables to the function along with a file and app name. Loading simply returns a table with your variables.

A basic implementation looks as follows. This would be put in a lua file, not a script.

local M = {}

M.variable1 = 0
M.variable2 = 0
M.variable3 = 0

M.APP_NAME = "appname"
M.SAVE_FILE_NAME = "savefile"

function M.load_file()
	local file = sys.load(sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME))
	
	M.variable1 = file.v1
	M.variable2 = file.v2
	M.variable3 = file.v3
end

function M.save_file()
	local file = {
		v1 = M.variable1,
		v2 = M.variable2,
		v3 = M.variable3,
	}

	sys.save(sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME), file)
end

return M
3 Likes

Okay so if i want my variable1 to be my self.highscore which i keep in ui.gui_script i need to message it to my lua file right? and can my app name be whatever i want or does it need to be my real game folder name or something like that? i got to go right now but i assume i want to thank for the help and i guess i will come back with more questions later perhaps

Not quite - you can’t pass messages to lua files. You could pass it as a variable instead though, or just put the load_file and save_file functions in your gui_script instead of a lua file - I’ve just demonstrated it this way for simplicity. Use whichever arrangments suits your needs.

App name can be whatever you wish - usually the name of your game.

Okay so can i use all the code u sent inside a script file or should i only use the save and load functions in the script and keep the rest in the lua file? Or if i want to pass the variable to the lua file how would i do that?

Yes you can put the code in a script file provided you remove the M. prefix from the function names.

If you stick with the lua file method, passing variables would be done in the usual way as follows:

lua module file.lua

function M.save_file(hiscore)
...
end

script file:

local file = require "file"

self.hiscore = 0

function somefunc(self)
    file.save_file(self.hiscore)
end
1 Like

Okay so from what i’ve got from your two responses i currently have:
In my lua module:
local M = {}

M.variable1 = 0

M.APP_NAME = ā€œzombiegameā€
M.SAVE_FILE_NAME = ā€œgamedataā€

function M.load_file()
local highscorefile = sys.load(sys.get_save_file(ā€œzombiegameā€, ā€œgamedataā€))

M.variable1 = highscorefile.v1

end

function M.save_file()
local highscorefile = {
v1 = M.variable1,

}

sys.save(sys.get_save_file("zombiegame", "highscorefile"), file)

end

return M

and in my ui.gui_script(of the code that is relevant to the module):

function init(self)

self.highscore = 0
local filesave = require"main.filesave"

end

function savefunction (self)
filesave.save_file(self.highscore)
end

i realize that right now they wont work together like they are right now, but i need help of what changes or additions i should do to make all of this work ?

i dont know why my comment didn’t make the code look right and sometimes it was like normal text, i can send screenshots if it’s confusing to read my code

Select the code and click the </> button to make it into a code block. Or add ``` before and after.

I’ve corrected a view errors - I wont go through them all but if there’s anything specific about the changes I’ve made you want explaining, just say.

The load_file() function would return the hiscore as a variable so you would call it as such from your script file:

self.hiscore = filesave.load_file()

Full lua file:

local M = {}

M.APP_NAME = "zombiegame"
M.SAVE_FILE_NAME = "gamedata"

function M.load_file()
	local highscorefile = sys.load(sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME))

	return highscorefile.hiscore
end

function M.save_file(hiscore)
	local highscorefile = {
	highscorefile.hiscore = hiscore,
}

sys.save(sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME), file)

end

return M

Script file:

local filesave = require "main.filesave"

function init(self)
	self.highscore = 0
end

function savefunction (self)
	filesave.save_file(self.highscore)
end
2 Likes

i am getting an error saying : ā€œ/main/filesave.lua
Line 22: Compilation failed: ā€˜}’ expected (to close ā€˜{’ at line 21) near ā€˜=ā€™ā€
my code from row 20 to row 25 looks like this:

function M.save_file(hiscore)
	local highscorefile = {
		highscorefile.hiscore = hiscore
	}
		sys.save(sys.get_save_file("M.APP_NAME", "M.SAVE_FILE_NAME"), file)
end

also

so should i set self.highscore = self.hiscore or something like that in my script file now?

Sorry, my bad - should have been:

function M.save_file(hiscore)
	local highscorefile = {
		hiscore = hiscore
	}
	sys.save(sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME), file)
end

You don’t need quotes around the app name and save file name btw. they are constants, not actual strings.

And you don’t need to do anything further in your script, the self.hiscore variable is set by the return value of filesave.loadfile()

okay thanks , how do i know if all of this works now? in my script file i added an if statement that i think will check if it works but im not sure, it looks like this:

function savefunction (self)
	filesave.save_file(self.highscore)
	if not sys.save(sys.get_save_file("zombiegame", "gamedata"), filesave)then
		pprint("Gamedata not saved")
	end
end

and if it all works now , will the file be saved somewhere on my computer?

On Windows it’s c:\users\<username>\appdata\roaming
Not sure about OSX or linux

The following should print out the file path:

local r = sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME)
print(r)

okay, im sad to say that

local r = sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME)
print(r)

didnt print anything at all :confused: and i can’t seem to find my saved file , when im at c:\users\<username> i don’t have anything called appdata , and when i search in username it doesn’t find the gamedata file

i wrote

local r = sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME)
	print(r)

in my savefunction in my scriptfile

Hmm, that’s odd. Maybe one of the Defold guys can shed some light on this.

AppData is a hidden folder in your user directory, so make sure you’ve got show hidden files on.

It must have printed something. An empty line maybe? What if you do:

print("before", M.APP_NAME, M.SAVE_FILE_NAME)
local r = sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME)
print("after", r)

Do you see ā€œbeforeā€ and ā€œafterā€ and what are the other values printed along with them?

No it didn’t print anything at all actually, i tried with the code u suggested and it’s the same thing, so i figured my savefunction, right now looking like this:

function savefunction (self)
	filesave.save_file(self.highscore)
	print("before", M.APP_NAME, M.SAVE_FILE_NAME)
	local r = sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME)
	print("after",r)
	if not sys.save(sys.get_save_file("zombiegame", "gamedata"), filesave)then
		pprint("Gamedata not saved")
	end
end

never was used, because i dont call it anywhere in my script?
so i tried pasting the code from the savefunction to my on message function:

function on_message(self, message_id, message, sender)
	if message_id == hash("add_score") then                 
		self.score = self.score + message.score             
		local scorenode = gui.get_node("score")            
		gui.set_text(scorenode, "SCORE: " .. self.score)    
	end
	if message_id == hash("game_over") then
		
		if self.score>self.highscore then
			self.highscore = self.score
		end
		filesave.save_file(self.highscore)
		print("before", M.APP_NAME, M.SAVE_FILE_NAME)
		local r = sys.get_save_file(M.APP_NAME, M.SAVE_FILE_NAME)
		print("after",r)
		if not sys.save(sys.get_save_file("zombiegame", "gamedata"), filesave)then
			pprint("Gamedata not saved")
		end

and then i got the error messages:

/main/filesave.lua:22: bad argument #2 to ā€˜save’ (table expected, got nil)

Error when dispatching message to gui scene: -2. Message ā€˜game_over’ sent from main:/instance10#tank to main:/gui#ui.

Well, you have an error in your code. You need to fix that. The code on line 22 of filesave.lua expects a table but gets nil (nothing).