Since the first thread you mentioned was mine, let me see if I can summarize the things that might matter to you.
First things first... When we talk about save compatibility, we're mainly talking about ensuring that the variables that 0.2+ need are available when you load a save file. It's oh so easy to go back and add a variable and then forget that a group of players out there have already played 0.1 and therefore have save files that don't include that new variable you added later.
default
Personally, I would recommend that all variables initially be defined using a
default
statement. By convention (not that everyone does the same), at the top of the script you are writing.
Any variables defined using
default
ALWAYS exist, even if you added them later.
Imagine it like all those
default
statements get run before your code actually starts, no matter where they exist. You start a game normally... all those default values are used. If you load a save game that doesn't have those variables in... it still uses the default values. But if you load a save game where the value IS saved as part of the save file - that new value is used instead.
Variables defined using Python ($) only exist from the point that code is executed. So if you have added a
$ myvar = True
statement to version v0.1 code while working on v0.2 and a player loads a save game from the end of 0.1 in order to play v0.2 - if that save game is AFTER the place in the code where the
myvar
is set... it won't exist (and will probably throw an error if you reference it).
default
exists exactly to avoid shit like that.
after_load: hasattr() and $
Next.. as
anne O'nymous already mentioned is
after load:
. Any time you load a save file, that bit of code gets run immediately after the save file is loaded
(the clue is in the same). Combined with
hasattr
, it can be used to set values that previously didn't exist (though not if you're using
default
- since those variables will always exist).
So as an alternative, you could do something like:
Python:
label after_load:
# If there's no attribute named "withVariables", then it's not a new game. So create it with a substitute value.
if not hasattr( store, "withVariables" ):
$ withVariables = 0
I'd suggest NOT using a value of 0 (zero) or False or whatever here, unless it makes sense.
Generally speaking, most players won't want to continue playing as if something didn't happen. So if you're adding something like love points retroactively, set it to the theoretical maximum... not zero. If you're checking if your player peeked on his sister in the shower, assume the player did and set the value to True rather than False.
Trust me, there will always be edge cases where whatever you do will cause problems... but code for easy stuff and let the edge cases go swivel.
after_load: and default
If you want to do this same sort of thing and still use
default
, then use
null
when you add a variable retrospectively, then use
after load:
to fix it for you.
Something like:
Python:
default love_points = 0
default sex_points = 0
default myvar = null
# [blah, blah, more code....]
label after_load:
# If there's no attribute named "myvar", then it's not a new game. So create it with a substitute value.
if myvar == null:
$ myvar = 0
# [blah, blah, even more code....]
This assumes "myvar" has been added later. The default value is null (think of it as "no real value"). If you load a save game without myvar in it, the game will retain the default value of null... that check will be true and the "$" statement will replace the value with a new value (again... that makes sense for someone loading a save from the end of v0.1 or whatever).
Remember that you will still need another
$ myvar = 0
(or similar) somewhere else in your code for players who start the game from scratch.
Which leads neatly into my last point...
a final note about default and after_load:
Despite
default
always setting you up a default value and
after load:
tweaking the values if a value didn't previously exist... it's still worth setting your variables to zero or False or whatever just before you use them for the first time.
I'll be honest, this is belt and braces stuff... to catch players doing odd things. (but partly to make you think about the potential too).
Imagine you add "love_points" to v0.1 code during v0.2 (or v0.3+... whatever). You add in all the places where it should add one when the player does something and eventually decide that the maximum a player could get normally during v0.1 would be 4.
So you code something like this:
Python:
default love_points = null
# [blah, blah, more code....]
label after_load:
if love_points == null:
$ love_points = 4
# [blah, blah, even more code....]
label start:
# [blah, blah, even more code....]
Okay. No problem. Your player loads their "end of v0.1" save game in order to continue to play your new v0.2 release. They start with 4 love points as if they previously maxed out everything and the game continues.
BUT...
What if another player started v0.1... put their name in... saved and then quit almost immediately?
They fire up 0.2. The
after load:
is invoked and the value is set to 4.
Then the player continues to play through all the code of v0.1 they didn't play the first time. By the time they reach the end of v0.1 - their love_points now add up to 8.
The answer is to still include a "$" statement to set the value to zero (or False, or whatever). Ideally, somewhere just before your first
$ love_points += 1
or
$ love_points -= 1
statement.
And finally...
I hope that covers the majority of issues you're likely to run into.
Honestly though... the real secret is to never add variables into previous releases retrospectively and always have a
default
statement per variable. Do both of those and 99% of your save compatibility issues will never arise.