Hi guys!
So I know this is the same old problem as always, but it gets worse and worse as you update your long sandbox game over and over and you have to warn your players not to use previous versions saves.
Let's say you have a sandbox project with a short updating period, and the MC has an inventory and a quest list, but you don't know what kind of quest or items you'll need to add to the code in future updates, so you can't add them onto your code in advance. Yes, you can set a lot of flags at once in order to use it later when you need it, but you can't set "item slots" or "quest slots" because they're objects from classes and also they're displayables: you can't set a "default item1 = Item("name", "pic.png")" or this is what your players will see loading the code on their brand new version of the game, even if you change it in the new version...
So, my question is: is there a way to avoid these variables updates problems, or to make RenPy update classes and variables from old saves when players load them in new versions of the game?
I know Renpy does not have an iterative update system and does not manage well this kind of things, but I'd apreciate any help on this!
PD: Someone might think declaring objects of a class with a "define" instead of a "default" would solve the problem, since "define" loads the new code everytime, but this way the objects won't load properly if the player saves and then loads the game, and will get a crash because of the object not being in the class.
[Solved] Game saves from previous versions when adding new variables
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
-
- Regular
- Posts: 141
- Joined: Fri Mar 15, 2019 8:46 am
- Completed: Clockwork Poison
- Projects: Melodic Dates, Clockwork Poison: Salvation
- Contact:
[Solved] Game saves from previous versions when adding new variables
Last edited by Adrian_DVL on Mon Apr 08, 2019 7:03 pm, edited 1 time in total.
Re: Game saves from previous versions when adding new variables
There are a couple of aspects to this.
First, if necessary, you can use “after_load” to fix up an old save in a new game. Store a variable that will tell you what version of the game created the save, and you can write “conversion code” if necessary.
Second, and this is just personal style, I try to avoid saving class instances as part of my game. I create my classes and then create class instances using “define” so they’re not part of the save. All the save data is formatted as Python dictionaries and lists, etc. that the classes then reference as required. Essentially, the data is external to the classes themselves. That way, I can rewrite the classes as necessary as long as they’re compatible with the save format (or with a rewritten save format per the above)
Once you start saving class instances as part of your save, as you’ve found out, you’re more restricted on backwards save compatibility.
First, if necessary, you can use “after_load” to fix up an old save in a new game. Store a variable that will tell you what version of the game created the save, and you can write “conversion code” if necessary.
Second, and this is just personal style, I try to avoid saving class instances as part of my game. I create my classes and then create class instances using “define” so they’re not part of the save. All the save data is formatted as Python dictionaries and lists, etc. that the classes then reference as required. Essentially, the data is external to the classes themselves. That way, I can rewrite the classes as necessary as long as they’re compatible with the save format (or with a rewritten save format per the above)
Once you start saving class instances as part of your save, as you’ve found out, you’re more restricted on backwards save compatibility.
-
- Regular
- Posts: 141
- Joined: Fri Mar 15, 2019 8:46 am
- Completed: Clockwork Poison
- Projects: Melodic Dates, Clockwork Poison: Salvation
- Contact:
Re: Game saves from previous versions when adding new variables
As per the second point, I understand what you mean. In fact, I can "define" auxiliar instances of, for example, my "Item" class, and then update them with new items as new versions are released, and those instances do change in-game even in old saves, but this does not work on, for example, my "Quest" class, since, like I've said above, if I create quests with "define", they seem to be missed when the player saves the game and loads it again (even when my Quest class have the same format as the Item one)... I guess that's because I'm constantly appending and removing Quest instances through labels. So I can only create them using "default" in order for them to work.rames44 wrote: ↑Mon Apr 08, 2019 11:45 am There are a couple of aspects to this.
First, if necessary, you can use “after_load” to fix up an old save in a new game. Store a variable that will tell you what version of the game created the save, and you can write “conversion code” if necessary.
Second, and this is just personal style, I try to avoid saving class instances as part of my game. I create my classes and then create class instances using “define” so they’re not part of the save. All the save data is formatted as Python dictionaries and lists, etc. that the classes then reference as required. Essentially, the data is external to the classes themselves. That way, I can rewrite the classes as necessary as long as they’re compatible with the save format (or with a rewritten save format per the above)
Once you start saving class instances as part of your save, as you’ve found out, you’re more restricted on backwards save compatibility.
So, apart from creating instances using "define", which I can't, I can't see any other way to make new ones work in an old save.
On the other front, I've read a few times about the "after_load" thing but I'm afraid I don't know how it works. Is it a statement to use in a label? If that's the case, how is it supposed to fix up variables from an old save?
-
- Regular
- Posts: 141
- Joined: Fri Mar 15, 2019 8:46 am
- Completed: Clockwork Poison
- Projects: Melodic Dates, Clockwork Poison: Salvation
- Contact:
Re: Game saves from previous versions when adding new variables
Ok, I'll try to be a bit more graphic (sorry for double post).
Here's what I have. These two classes, one of them for the quest, and the other one for the container, the quest list:
And then I have the different instances created with a "default", like this:
Now, this way it works perfectly fine. Each time I need to add a quest to the list I do it by qlist.add(hope1), or replacing "add" by "ok" in order to remove it.
But this way I can't neither create new quests nor change which already exist and expect them to work in old save files, because they won't.
On the other hand, if I create them with "define" instead of "default", once the player saves the game with quests in his list and loads the game again, the player gets a crash about x instance not being in the list.
I don't have the same problem with items in the class "Inventory", and that's because, while I do append them through labels, I don't remove them through them, but from the inventory itself by clicking them with the mouse.
So neither I can create quests with default due to the "old saves" problems , nor I can create them with "define" because they're missing after loading the game.
Here's what I have. These two classes, one of them for the quest, and the other one for the container, the quest list:
Code: Select all
class Quest(renpy.store.object):
def __init__(self, subj=".png", descr=""):
self.subj = subj
self.descr = descr
class Qlist(renpy.store.object):
def __init__(self):
self.quests = []
def add(self, quest):
self.quests.append(quest)
def ok(self, quest):
self.quests.remove(quest)
Code: Select all
default hope1 = Quest("hope", "Meet Hope at the gym.")
default hope2 = Quest("hope", "Go to Hope's apartment.")
default hope3 = Quest("hope", "Go to the police station.")
But this way I can't neither create new quests nor change which already exist and expect them to work in old save files, because they won't.
On the other hand, if I create them with "define" instead of "default", once the player saves the game with quests in his list and loads the game again, the player gets a crash about x instance not being in the list.
I don't have the same problem with items in the class "Inventory", and that's because, while I do append them through labels, I don't remove them through them, but from the inventory itself by clicking them with the mouse.
So neither I can create quests with default due to the "old saves" problems , nor I can create them with "define" because they're missing after loading the game.
Re: Game saves from previous versions when adding new variables
If your game defines a label called “after_load”, Ren’py calls it after loading all the data from a save, but before executing any statements after the point where the save occurred. So you have access to all the data, and can make any changes you need to. When you “return”, then Ren’py resumes the game.
So, if I’m understanding your game logic, in the after_load block, you could add any new Quest objects that were introduced in that version of the game to your Qlist. Of course, you need some kind of logic to know which ones to add. One way might be a flag inside Quest that gets set when that Quest is added to a Qlist so that when it’s later removed, you know that it HAD been added at one point.
So, if I’m understanding your game logic, in the after_load block, you could add any new Quest objects that were introduced in that version of the game to your Qlist. Of course, you need some kind of logic to know which ones to add. One way might be a flag inside Quest that gets set when that Quest is added to a Qlist so that when it’s later removed, you know that it HAD been added at one point.
-
- Regular
- Posts: 141
- Joined: Fri Mar 15, 2019 8:46 am
- Completed: Clockwork Poison
- Projects: Melodic Dates, Clockwork Poison: Salvation
- Contact:
Re: Game saves from previous versions when adding new variables
Oh, ok, I thought it was something different. So it's a label called in order to ensure the data inside it is loaded before the player does anything else in the game.rames44 wrote: ↑Mon Apr 08, 2019 6:14 pm If your game defines a label called “after_load”, Ren’py calls it after loading all the data from a save, but before executing any statements after the point where the save occurred. So you have access to all the data, and can make any changes you need to. When you “return”, then Ren’py resumes the game.
So, if I’m understanding your game logic, in the after_load block, you could add any new Quest objects that were introduced in that version of the game to your Qlist. Of course, you need some kind of logic to know which ones to add. One way might be a flag inside Quest that gets set when that Quest is added to a Qlist so that when it’s later removed, you know that it HAD been added at one point.
Alright, I've been messing around with after_load label and different old and new saves and now it seems it works perfectly: when I create new objects for Quest they're included in an old save without problems!
So thank you so much! Pretty useful, the after_load
Who is online
Users browsing this forum: Ahrefs [Bot]