Windows Save system -- I need a second pair of eyes

RangerX

Member
Hello all,
I am brain dead right now. I don't know what's going on. I can't seem to save my score right or again my ds lists. That feels basic but I don't see what's wrong. Let's go step by step.

At the beginning of my game, I create a file for saving the "score" variable:
Code:
if(!directory_exists("TLR_gamedata"+string(global.Version)+"\slot01\Data01"))    
then
{
directory_create("TLR_gamedata"+string(global.Version)+"\slot01\Data01");

File=file_text_open_write("TLR_gamedata"+string(global.Version)+"\slot01\Data01\0001");      
file_text_write_real(File,"000");
file_text_close(File);
}

After that, when I enter the "challenge mode", there's a object that immediately reads that file:

Code:
if(file_exists("\TLR_gamedata"+string(global.Version)+"\slot"+string(global.SlotUsed)+"\Data01\0001"))
then
{
File=file_text_open_read("\TLR_gamedata"+string(global.Version)+"\slot"+string(global.SlotUsed)+"\Data01\0001");
score=file_text_read_real(File);
file_text_close(File);                                        
}

Now the interesting result:
- If I go have a game (any save slot) and pass a checkpoint, the score is saved and when I enter "challenge mode" after that, its the right score.
- If I enter the challenge mode after a fresh boot, the score is not the right one. Like it doesn't read the file or something


Color me flabergasted.
 

jo-thijs

Member
The comments on this topic are true, but they are not the issue.
GameMaker will treat strings as the value 0 there, so it eventually does work correctly there (even though it should still be corrected).

The real problem lies here:
Code:
if(file_exists("\TLR_gamedata"+string(global.Version)+"\slot"+string(global.SlotUsed)+"\Data01\0001"))
You expect this part:
Code:
string(global.SlotUsed)
to somehow return "01".
It will instead return "1".
You'll have to manually add the 0 to it when necessary.
 

RangerX

Member
I will revise the whole thing and remove the 0s anyways.
I'll see what happens and post back. I was too tired yesterday to continue testing around.
 

RangerX

Member
Ok my score file (which is saved on the side because the score data is shared between 2 modes over 3 different save slots) is working fine. So to round up this story, here's the code that works:


- At the beginning of the game, the score file is created if it wasn't already existing. (example for slot 1)
Code:
if(!directory_exists("TLR_gamedata"+string(global.Version)+"\slot01\Data01")) 
then
{
directory_create("TLR_gamedata"+string(global.Version)+"\slot01\Data01");

File=file_text_open_write("TLR_gamedata"+string(global.Version)+"\slot01\Data01\Score.txt");
file_text_write_real(File,"0");
file_text_close(File);
}


Then in adventure mode when the player saves, score is saved.
Code:
File=file_text_open_write("TLR_gamedata"+string(global.Version)+"\slot01\Data01\Score.txt");
file_text_write_real(File,score);                                                                     
file_text_close(File);


When entering challenge mode, score is updated (therefore the score crossed from Adventure Mode to Challenge Mode)
Code:
if(file_exists(working_directory+"\TLR_gamedata"+string(global.Version)+"\slot0"+string(global.SlotUsed)+"\Data01\Score.txt"))
then
{
File=file_text_open_read(working_directory+"\TLR_gamedata"+string(global.Version)+"\slot0"+string(global.SlotUsed)+"\Data01\Score.txt");
score=file_text_read_real(File);
file_text_close(File);                        
}

Not sure why it wasn't working 2 days ago. LOL
 

Yal

🐧 *penguin noises*
GMC Elder
Yeah, for some reason GM accepts strings as values for a lot of functions, but treat them as value zero. It has caused me trouble in the past as well.
Also, I wouldn't recommend file_text_write_real() anyway when you can file_text_write_string() the string() conversion of a number... previous versions of the function would crash if it was on a locale using commas for decimal dots, and I'm still not sure whether that was fixed, while the string representation always is the same... I also think using _string() ensures you print an integer in case the value is closer to an integer than the maths comparison precision (which can be changed now) but still technically not an integer under the full, double-float precision while _real() does not take the comparison precision into account.

Also, I totally recommend making a script along these lines for cases like this. (And to display score values in shmups :p). Pasting as an image to force you to make a copy yourself, it gets a bit more insightful that just plug-and-playing it.
upload_2016-7-17_10-47-40.png
 

RangerX

Member
I love this thread, sounds like am gonna learn a thing or two 'cause I got questions...


You are still passing a string to file_text_write_real, despite 3 comments saying you shouldn't
and you solved "01" thing by always adding a leading 0?
Why do you even have that zero then?
The zero there shouldn't be there yes. However, its old code and its at multiple places in my game. I did put it back because it was there because my other night experiments and right now I don't want to "fix" it everywhere because it doesn't break anything apparently. That might sound stupid but I whatever time I can save, I save it so for now I will it like that.

However, I have a question about that "passing a string to file_text_write". Why shouldn't I?
Those functions are asking for the path of the file there. The path needs to be a string so that's exactly what I am giving. After that I write a real and not a string.
Also, the variables in my paths are real I set myself once (1,2 or3) depending the save slot the player uses and the version number. This is needed so the file is saved in the right place.
How am I using that function wrong? What am I missing?



Yeah, for some reason GM accepts strings as values for a lot of functions, but treat them as value zero. It has caused me trouble in the past as well.
Also, I wouldn't recommend file_text_write_real() anyway when you can file_text_write_string() the string() conversion of a number... previous versions of the function would crash if it was on a locale using commas for decimal dots, and I'm still not sure whether that was fixed, while the string representation always is the same... I also think using _string() ensures you print an integer in case the value is closer to an integer than the maths comparison precision (which can be changed now) but still technically not an integer under the full, double-float precision while _real() does not take the comparison precision into account.

Also, I totally recommend making a script along these lines for cases like this. (And to display score values in shmups :p). Pasting as an image to force you to make a copy yourself, it gets a bit more insightful that just plug-and-playing it.
View attachment 1219
I am not sure I understand what you are saying. I wouldn't use "file_text_write_string" since its a real I am writing.
Also, looks like I am dumb enough to not understand what your script is for overthere. :(
 

jo-thijs

Member
There is no such function as "file_text_write", and I wasn't talking about "file_text_open_write" either which you seem to think I did.
I was talking about passing a string to the function "file_text_write_real".
It expects a file identifier (a real value) and a real value to write (a real value).
No strings there, yet you do pass it a string here:
Code:
file_text_write_real(File,"0");
It is sheer coincidence that it behaves like you want it to, but if you expand on it, it will not anymore.

And Yal's suggestion is a good one.
It is sometimes better to write a real value to a file as a string.
You would first convert your real value to a string manually,
you would then use "file_text_write_string" to write that string to the file
and you can later use "file_text_read_string" to read it back and convert it into a real value again
(or use "file_text_read_real", which works fine with integers).
 

RangerX

Member
Ok good. Looked at the function's arguments again and argument 2 is indeed "val". So this is a mistake and gonna fix right now.

As for writing numbers as a string, its good for when its a float or number that could be a float when I am not totally controlling it. Otherwise when I am sure its an integer I don't have to since there's no precision story to suffer from when I will read it back, right?

Its something I would never have thought about saving simple things like I do. I also wonder why writing a real wouldn't write it "as is" and then as read it "as is" and wouldn't lose precision. If you guys can share some knowledge on that, I am really curious.
 

Yal

🐧 *penguin noises*
GMC Elder
Also, looks like I am dumb enough to not understand what your script is for overthere. :(
It even has a comment clarifying...
upload_2016-7-17_17-35-47.png

Basically, it turns a number intro a string with exactly that number of digits. string_fix(155,8) returns "00000155".


The write-real function (and read-real function) has historically had some issues. Old versions used the current locale when converting to a string, but only understand the common english format when loading the value from a string (some locales use different notation for decimal points which causes games relying on write_real() to crash when you try loading the game). I still don't trust them even after this has been fixed, and would prefer using something I know works - my own conversion to and from strings.
Secondly, write_real() writes the number at full precision no matter what precision your game actually is using, and since that is a data inconsistency (despite being a minor one), it should be treated with care.
 
Top