- Jun 10, 2017
- 12,927
- 21,423
- 1,026
Many games nowadays become too big to fit in a single volume. Beyond the simple question of size, the fact that games are mostly released by update is the main issue here. Let's say that a game grow by 1GB with each update, and need 10 updates to be completed. Having to download the whole game each time mean that the player will have downloaded a total of 55 GB.
A solution used by some developers is to offer an "update only" option, where only the updated content will be present. While this would limit the total download size to 10 GB, this solution isn't without drawbacks. Players have to keep the whole game uncompressed and not everyone have a top computer with a conveniently big enough storage space. Plus, not all of them would know how to correctly archive back the new 'whole game', and even less how to add the updated content to their current archive. In fact, way less people that one can imagine understand how to deal with those "update only" release.
An alternative option is to split the game in different volume. They are separated games that continue the story where it was leaved at the end of the previous volume. This permit to limit the whole download size; split in two volumes, our 10GB game would only need 30 GB of full download, in place of 55 GB. But, more important, this put the charge of the handling on the developer, not on the players.
For them, it's a game like any others, they have no special manipulation to do outside of the game itself. This mean that, when correctly handled, 99,99% of your players will be able to deal with the change of volume. And it's what I'll talk about here.
There's two methods to pass from a volume to another. Well, to be fully exact there's three, the third one being "forget everything that happened in the previous volume", I'll not talk about it for obvious reasons.
The first method consist to trick Ren'Py in believing that it's still the same game, and therefore the same volume. The other one is to let the player export the significant data at the end of one volume, then import them at the start of the next volume.
Method 1 - Tricking Ren'Py:
Ren'Py rely on a basic but strong save system. Basic, because it just save the current variables values, including the one telling it at where line of the script it currently is. Strong, because if the current line do not exist anymore, Ren'Py have mechanism that permit it to still catch up, even if this need restarting the whole current label.
The trick rely on this particularity. You'll start the next volume with a label that have the same name than the last label of the previous volume.
How does it works:
If your volume ends like this:
Then, when the player will load its save file from the next volume, it will starts like this:
/!\Warning/!\, not all players can be trusted. You tell them to "save here", and they'll save later in the credits or, more frequent, a bit previously in the story. Therefore a good practice is to include a bit more than the actual last label.
Your game will looks like:
And your new volume should looks like:
Note that the same logic apply if the current volume end with a multi-path approach. Your new volume should have a label for all the possible labels where you ask the player to make its finale save, and all the possible labels right before this one. It's not really much more works for you, and a tons of headache saved by not having to answer to futures, "hey, I saved before you said I must, and now I got an error when I load the game".
How implement it:
For this magic to happen, you need one and only one manipulation.
Open the file "options.rpy" from the current volume. In there, search for the line starting with
Once you've got that name, open the "options.rpy" file from the new volume, and again search for the line starting with
Going further:
While doing this is enough, you've to keep in mind that all the variables from the previous volume will be imported into the new one. But some are perhaps now irrelevant, just present because they weren't a bother enough to worth being deleted. So, you can also jump on the occasion and benefit from this change of volume to clean a bit your variables.
While Ren'Py itself do not have a way to delete a variable, Python do, the
Let's say that your game offer more than one opportunity to open a path with a character. In the first volume you used something like this:
This become useless in your second volume, because either the player already is in a relationship with Amanda, or he'll never be able to pursue her anymore. Therefore, why still bother with those three variables, while a
To clean your variables, you just need to tweak a bit the end of the current volume:
Side note: Due to Ren'Py rollback system, the deletion will not be immediate, but it will happen.
Note that the same logic permit you to rename a variable:
And in fact everything that is possible to do with variables.
There's a bit more to do for this to be perfect, because you still need to deal with players that don't have played the first volume. But, like this apply in the same way for both method, I'll talk about it later in this How-To.
Method 2 - Exportation/Importation:
While the previous method is a trick, this one rely on a Ren'Py feature designed to this purpose, the
This feature and class permit you to store data in a file of your choice, file that will be stored in a special folder named "persistent"; for Windows users it will be "%AppData%/Roaming/RenPy/persistent". This folder not being unique to a game, it permit to share the stored data through different games or, what interest us here, just different volumes of a game. As long as you know the name of the file, you'll be able to load the data it store.
The MultiPersistent object:
Using a
Firstly you need to create the object. Here I'll name it "mp", but you can use whatever name you want, especially if you already have a variable, or a
Note the presence of two arguments for the creation of the object.
The first one is the name of the file where the data will be stored. Remember that Ren'Py store all the multi persistent data in the same directory, therefore make this name as unique as possible; "myMPobject" being everything but a good name for such file.
The second argument is telling Ren'Py if it must (
Then, once the object is created, you just use it like any other object, either to store the data that you want to export:
or to import the data from the previous volume:
For the importation, you'll also need to add an "import" button to the main menu. This is done through the edition of the "navigation" screen, located by default in the "screen.rpy" file:
Strictly speaking, this is all you need to do for this approach to works. But, obviously, this is also the most basic approach. Since you picked this method over the first one, you can do, and should do, more. I'll come to this a bit later in this how-to.
The pitfall to avoid:
Do not use directly the data from
I know, it's really tempting... Why bother to import the data when they are already available? And the reason why you shouldn't is simple: because it could break your players experience.
/!\Bad practice example/!\
In the example above I use boolean variables, even more, variables that have been defined long ago and will never change. But imagine that instead of the moment where the player opened the relationship with Amanda, it was the number of time the MC did something that amanda disliked?
/!\Bad practice example/!\
You updated the value for "amandaDislike", the content of the
Except that the values aren't anymore accurate in regard of what it was at the end of the previous volume. MC haven't been too much selfish, but it passed "amandaDislike" from the
And, yes, even the first example is bad practice. Strictly speaking it have no consequence, but it starts a bad habit, and soon or later you'll forget to be cautious and write the second example.
Advantage over the previous method:
While more complex to implement that the previous method, this approach offer you a better control over what variables will be shared. With the first method, all variables will be imported to your new volume unless you explicitly deleted them. With a
More constraining, this approach is also way more flexible than the raw important from the previous method.
The explicit export is an incentive to think about your variables and weight their actual significance. It also force you to consider a possible new approach, like switching from a set of boolean into a string to store some information. This while the explicit import offer you the possibility to change your mind between the end of a volume and the start of the next one. It also permit you to export data that you're not sure as being significant in the future, and just keep them available in the
Advanced exporting:
Like with the previous method, the moment you'll pass form a volume to another is the best moment to think about your variables, weight the ones that are really significant and, possibly, decide to restructure some of them.
Let's say that the multi entries for the opening of Amanda's relationship also correspond to the first kiss you shared. While it's not really significant to know when the relationship started, it's not the same for the first kiss; girls tend to remember this, and so should your MC if he want to earn extra sweet points. But do you really need three booleans for this?
The answer fuly depend on you and your own logic, but if you're really have a lot of those variables, it's more than possible that you want to limits their number for the import/export process. One way to do this is to replace the said booleans by a string:
Advanced importing:
As I said above, the need to implicitly import the data offer you a second chance to change your mind regarding the way you'll handle some data, as well as what variables will host them.
By example, you used the previous code to change the variables regarding Amanda relationship. But, while you were working on the next chapter of your game, you finally decided that having just one variable for Amanda relationship would be better, using a two level variable for this. If "amandaRelationship" is None, the relationship is closed, and else the value for "amandaRelationship" will be the moment where MC and her shared their first kiss:
Whatever during the exportation phase or the importantion one, there's absolutely no obligation for the variables stored in the
Case of players with more than one playthrough:
Unless your game is pretty linear, there's chance that some of your players have more than one playthrough, playing them on parallel to see all the marvels you add in each update.
This isn't an issue for the first method, since it rely on the save files created by the player. But this need a different approach if you use the
The best way to handle this is to store your data not directly in the
Then you import the data by doing this:
But, obviously, this is an extremely basic approach of the problem. The two pieces of code above are more to show the principle than to tell you how to do it. Below are two codes, way more advanced, that you can use, either as it or as base for your own import/export system.
How to have a clean volume start:
As hinted above, not all your players will have played the previous volume(s) of your game. While it's a pity since they clearly miss something amazing, it's also their right, and you've to be ready for this.
This mean that, in top of your game continuation or data importation label, you also need to have a regular "start" label. And, whatever the method you chose, you've a lot to do for this to be correct.
First thing first, you need to decide of a canon path for your game. Like players haven't interacted with your story, you've to decide what are the canon choices, and make them for those newcomers. For this, you need to give a default value to all the variables from the previous volume that you intent to use in this one, or that you'll import.
Another approach, more complex, is to ask the player for his input:
As you surely noticed, this approach can easily become really heavy. While it's tempting to ask everything to the player, you must limits to what is strictly mandatory and strongly relevant to the experience offered by your game.
Forcing a player to be in a relationship he don't want could harm his experience, as well as forcing him to be top when he's more submissive, or the opposite. But if the player really want to decide what swimsuit the MC offered to Amanda, he just have to play the first volume; beggar can't be choosers.
Second thing that you've to do in order to offer a clean start to newcomers is to present a small overview of what happened in the previous volume(s).
Remember how you started your game. The player knew nothing, and you had to introduce each character, including the MC. You also had to explain each major point of the universe the MC evolve in, and so on. Newcomers need this, else they'll understand nothing and be too lost to actually continue to play your game. But faithful players who play your game since the starts do not have to suffer from this second slow burn. Therefore you need to add a good old "previously on", to help those newcomers to catch up.
I'll not tell you how to do this, it fully depend on your game and style. Just keep in mind that, since you made it, why not offer to your faithful player the possibility to also see it? Not all will be interested, so it should stay an option, but those who are will without doubt be please to have this reminder. After all, how many years since you started your game?
For this last option, you can have something like this:
And now?:
Well, now you're ready...
You know how to pass from a volume to another while keeping the choices made by the player. You know how to clean up your variables in order to only keep the ones that will be significant for this new volume. And you know how to have a clean starts for both long time players and newcomers.
The rest, therefore how to actually implement it, what is a significant variable, and how to actually starts the game to the newcomers is totaly up to you. I gave you the canvas, now it's time for you to do your creator magic and transform it into art.
A solution used by some developers is to offer an "update only" option, where only the updated content will be present. While this would limit the total download size to 10 GB, this solution isn't without drawbacks. Players have to keep the whole game uncompressed and not everyone have a top computer with a conveniently big enough storage space. Plus, not all of them would know how to correctly archive back the new 'whole game', and even less how to add the updated content to their current archive. In fact, way less people that one can imagine understand how to deal with those "update only" release.
An alternative option is to split the game in different volume. They are separated games that continue the story where it was leaved at the end of the previous volume. This permit to limit the whole download size; split in two volumes, our 10GB game would only need 30 GB of full download, in place of 55 GB. But, more important, this put the charge of the handling on the developer, not on the players.
For them, it's a game like any others, they have no special manipulation to do outside of the game itself. This mean that, when correctly handled, 99,99% of your players will be able to deal with the change of volume. And it's what I'll talk about here.
There's two methods to pass from a volume to another. Well, to be fully exact there's three, the third one being "forget everything that happened in the previous volume", I'll not talk about it for obvious reasons.
The first method consist to trick Ren'Py in believing that it's still the same game, and therefore the same volume. The other one is to let the player export the significant data at the end of one volume, then import them at the start of the next volume.
Method 1 - Tricking Ren'Py:
Ren'Py rely on a basic but strong save system. Basic, because it just save the current variables values, including the one telling it at where line of the script it currently is. Strong, because if the current line do not exist anymore, Ren'Py have mechanism that permit it to still catch up, even if this need restarting the whole current label.
The trick rely on this particularity. You'll start the next volume with a label that have the same name than the last label of the previous volume.
How does it works:
If your volume ends like this:
Python:
label day10_atThePark:
[content of the scene]
dev "Hello, here's [dev.name], your favorite host, speaking."
dev "I want to thanks you for playing my game, and have to warn you that this mark the end of this {i}volume{/i} of [config.name]."
dev "But don't be worried, the transition will be invisible. Just save your game here, as you usually do, and you'll be able to load it in the next {i}volume{/i}."
pause
return
Python:
label day10_atThePark:
dev "Hello, here's [dev.name], your favorite host, speaking."
dev "Welcome to the second {i}volume{/i} of [config.name]. As you can see, your save loaded correctly, so be ready to enjoy the rest of your adventure."
Your game will looks like:
Python:
label day10_lunch:
[...]
jump day10_atThePark
label day10_atThePark:
[...]
dev "But don't be worried, the transition will be invisible. Just save your game here, as you usually do, and you'll be able to load it in the next {i}volume{/i}."
jump creditsEpisode5
label creditsEpisode5:
[credits]
pause
return
Python:
label day10_lunch:
jump creditsEpisode5
label day10_atThePark:
jump creditsEpisode5
label creditsEpisode5:
dev "Hello, here's [dev.name], your favorite host, speaking."
dev "Welcome to the second {i}volume{/i} of [config.name]. As you can see, your saved loaded correctly, so be ready to enjoy the rest of your adventure."
[...]
How implement it:
For this magic to happen, you need one and only one manipulation.
Open the file "options.rpy" from the current volume. In there, search for the line starting with
define config.save_directory =. The line will be followed by something like "Example-1523023424". This is the name of the folder where Ren'Py store the save files on the system. For Windows, this mean that the save files are in "%AppData%/Roaming/RenPy/Example-1523023424".Once you've got that name, open the "options.rpy" file from the new volume, and again search for the line starting with
define config.save_directory =. This time the value will be different, perhaps "ExampleVolume2-5132024342". You just have to replace it with the "Example-1523023424" you got from the other file, and Ren'Py will use the same folder to store the save files for the two volume. What mean that players will be able to load the final save file they created at the end of the previous volume.Going further:
While doing this is enough, you've to keep in mind that all the variables from the previous volume will be imported into the new one. But some are perhaps now irrelevant, just present because they weren't a bother enough to worth being deleted. So, you can also jump on the occasion and benefit from this change of volume to clean a bit your variables.
While Ren'Py itself do not have a way to delete a variable, Python do, the
delattr() function. To use it, you just need to put $ delattr( store, "nameOfTheVariable" ) into a label. You can also use this occasion to redefine a bit your variables.Let's say that your game offer more than one opportunity to open a path with a character. In the first volume you used something like this:
Python:
default amandaFirst = False
default amandaSecond = False
default amandaThird = False
label whatever:
[...]
menu:
"Do you want to invite Amanda?"
"Yes":
$ amandaFirst = True
jump amandaInvited
"No":
jump amandaNotInvited
[...]
label anotherLabel:
[...]
menu:
"What do you want to do?"
"Invite Amanda to see a movie with you" if amandaFirst is False:
$ amandaSecond = True
jump amandaMovie
"Play videogames":
[...]
"Go to the park":
[...]
[...]
amandaRelationship boolean would be better and easier to deal with?To clean your variables, you just need to tweak a bit the end of the current volume:
Python:
label dayAtThePark:
[content of the scene]
call variablesCleaning # Add this line
dev "Hello, here's [dev.name], your favorite host, speaking."
dev "I want to thanks you for playing my game, and have to warn you that this mark the end of this {i}volume{/i} of [config.name]."
dev "But don't be worried, the transition will be invisible. Just save your game here, as you usually do, and you'll be able to load it in the next {i}volume{/i}."
pause
return
label variablesCleaning:
# If the player opened Amanda relationship, whatever at which moment...
if amandaFirst is True or amandaSecond is True or amandaThird is True:
# ... mark the relationship as being opened.
$ amandaRelationship = True
# If the player never opened the relationship with Amanda...
else:
# ... mark the relationship as being closed.
$ amandaRelationship = False
# Then delete the variables.
$ delattr( store, "amandaFirst" )
$ delattr( store, "amandaSecond" )
$ delattr( store, "amandaThird" )
[do all the other modification you need to do]
# Then return to the end of the game.
return
Note that the same logic permit you to rename a variable:
Python:
label variableCleaning:
[...]
$ newName = oldName
$ delattr( store, "oldName" )
[...]
There's a bit more to do for this to be perfect, because you still need to deal with players that don't have played the first volume. But, like this apply in the same way for both method, I'll talk about it later in this How-To.
Method 2 - Exportation/Importation:
While the previous method is a trick, this one rely on a Ren'Py feature designed to this purpose, the
You must be registered to see the links
and more precisely the MultiPersistent class.This feature and class permit you to store data in a file of your choice, file that will be stored in a special folder named "persistent"; for Windows users it will be "%AppData%/Roaming/RenPy/persistent". This folder not being unique to a game, it permit to share the stored data through different games or, what interest us here, just different volumes of a game. As long as you know the name of the file, you'll be able to load the data it store.
The MultiPersistent object:
Using a
MultiPersistent object need more works than the previous method, but this doesn't mean that it's something difficult to do. It's not because it's designed for a specific task that it's not a object like any other one, and therefore that it isn't used like any object.Firstly you need to create the object. Here I'll name it "mp", but you can use whatever name you want, especially if you already have a variable, or a
Character, named like this:define mp = MultiPersistent( "myMPobject", save_on_quit=True )Note the presence of two arguments for the creation of the object.
The first one is the name of the file where the data will be stored. Remember that Ren'Py store all the multi persistent data in the same directory, therefore make this name as unique as possible; "myMPobject" being everything but a good name for such file.
The second argument is telling Ren'Py if it must (
True) or not (False) save the data before the player quit the game. For better nights, you must put the value at True for the volume exporting the data. This in order to be sure that everything will be saved at least once. For the same reason you must put the value at (False for the game volume importing the data, since you're only reading them.Then, once the object is created, you just use it like any other object, either to store the data that you want to export:
Python:
default amandaFirst = False
default amandaSecond = False
default amandaThird = False
define mp = MultiPersistent( STRING_WITH_AN_UNIQUE_NAME_RELATED_TO_YOUR_PROJECT, save_on_quit=True )
label mpExport:
$ mp.amandaFirst = amandaFirst
$ mp.amandaSecond = amandaSecond
$ mp.amandaThird = amandaThird
[...]
return
Python:
default amandaFirst = False
default amandaSecond = False
default amandaThird = False
define mp = MultiPersistent( STRING_WITH_AN_UNIQUE_NAME_RELATED_TO_YOUR_PROJECT, save_on_quit=False )
label mpImport:
$ amandaFirst = mp.amandaFirst
$ amandaSecond = mp.amandaSecond
$ amandaThird = mp.amandaThird
[...]
jump someLabelThatStartsTheGame
Python:
screen navigation():
vbox:
[...]
if main_menu:
textbutton _("Start") action Start()
# Add this button.
textbutton _("Import a playthrough") action Jump( "mpImport" )
[...]
The pitfall to avoid:
Do not use directly the data from
MultiPersistent object.I know, it's really tempting... Why bother to import the data when they are already available? And the reason why you shouldn't is simple: because it could break your players experience.
/!\Bad practice example/!\
Python:
label whatever:
amanda "Remember our first kiss?"
if mp.amandaFirst is True:
mc "Of course, it was in the park."
elif mp.amandaSecond is True:
mc "Of course, we missed most of the movie because we were too busy kissing."
else:
mc "I still feel the taste of coffee over your lips while doing it."
/!\Bad practice example/!\
Python:
label whatever:
menu:
"I promised Amanda to go see a movie with her, but there's football on the TV tonight, what should I do?"
"Keep your promise.":
jump amandaMovie
"Well, it's the final and your favorite team, she'll understand.":
$ mp.amandaDislike += 1
jump finaleNight
MultiPersistent value have changed. This value, as well as other ones, changed more than once over the time when, suddenly, the player discover that he missed an important turn in the game. He really want to take that turn and therefore decide to restart the volume...Except that the values aren't anymore accurate in regard of what it was at the end of the previous volume. MC haven't been too much selfish, but it passed "amandaDislike" from the
1 it should be, to a 3 that represent a MC that have always made the selfish choice in the previous volume. The story will change radically, while it shouldn't.And, yes, even the first example is bad practice. Strictly speaking it have no consequence, but it starts a bad habit, and soon or later you'll forget to be cautious and write the second example.
Advantage over the previous method:
While more complex to implement that the previous method, this approach offer you a better control over what variables will be shared. With the first method, all variables will be imported to your new volume unless you explicitly deleted them. With a
MultiPersistent object, only the variables that you'll explicitly export will be available for importation. Plus, while being available, the importation will not be automatic; you need to explicitly do it.More constraining, this approach is also way more flexible than the raw important from the previous method.
The explicit export is an incentive to think about your variables and weight their actual significance. It also force you to consider a possible new approach, like switching from a set of boolean into a string to store some information. This while the explicit import offer you the possibility to change your mind between the end of a volume and the start of the next one. It also permit you to export data that you're not sure as being significant in the future, and just keep them available in the
MultiPersistent save file, having them at your disposal but not yet imported into the game.Advanced exporting:
Like with the previous method, the moment you'll pass form a volume to another is the best moment to think about your variables, weight the ones that are really significant and, possibly, decide to restructure some of them.
Let's say that the multi entries for the opening of Amanda's relationship also correspond to the first kiss you shared. While it's not really significant to know when the relationship started, it's not the same for the first kiss; girls tend to remember this, and so should your MC if he want to earn extra sweet points. But do you really need three booleans for this?
The answer fuly depend on you and your own logic, but if you're really have a lot of those variables, it's more than possible that you want to limits their number for the import/export process. One way to do this is to replace the said booleans by a string:
Python:
default amandaFirst = False
default amandaSecond = False
default amandaThird = False
define mp = MultiPersistent( STRING_WITH_AN_UNIQUE_NAME_RELATED_TO_YOUR_PROJECT, save_on_quit=True )
label mpExport:
# If the player opened Amanda relationship, whatever at which moment...
if amandaFirst is True or amandaSecond is True or amandaThird is True:
# ... mark the relationship as being opened.
$ mp.amandaRelationship = True
# Now it's time to remmeber the first kiss...
if amandaFirst is True:
# The first opportunity happened in the park.
$ mp.amandaFirstKiss = "park"
elif amandaSecond is True:
# The second opportunity happened in the movie theater.
$ mp.amandaFirstKiss = "movie"
# Since the first /if/ told us that one of the three is True, if it's not one of the
# two above, then it's the third one.
else:
# The third and last opportunity happened in a coffee shop.
$ mp.amandaFirstKiss = "coffee"
# If the player never opened the relationship with Amanda...
else:
# ... mark the relationship as being closed.
$ mp.amandaRelationship = False
[...]
return
Advanced importing:
As I said above, the need to implicitly import the data offer you a second chance to change your mind regarding the way you'll handle some data, as well as what variables will host them.
By example, you used the previous code to change the variables regarding Amanda relationship. But, while you were working on the next chapter of your game, you finally decided that having just one variable for Amanda relationship would be better, using a two level variable for this. If "amandaRelationship" is None, the relationship is closed, and else the value for "amandaRelationship" will be the moment where MC and her shared their first kiss:
Python:
default amandaRelationship = None
define mp = MultiPersistent( STRING_WITH_AN_UNIQUE_NAME_RELATED_TO_YOUR_PROJECT, save_on_quit=False )
label mpImport:
# If the player have opened Amanda relationship...
if mp.amandaRelationship is True:
# ... copy directly the first kiss value in amandaRelationsip.
$ amandaRelationship = mp.amandaFirstKiss
# If the player haven't opened the relationship with Amanda, then there's no first kiss.
else
$ amandaRelationship = None
[...]
jump someLabelThatStartsTheGame
MultiPersistent object to match the name of the variables in your game.Case of players with more than one playthrough:
Unless your game is pretty linear, there's chance that some of your players have more than one playthrough, playing them on parallel to see all the marvels you add in each update.
This isn't an issue for the first method, since it rely on the save files created by the player. But this need a different approach if you use the
MultiPersistent obbject.The best way to handle this is to store your data not directly in the
MultiPersistent object, like shown in all the previous examples, but in a dictionary stored into this object:
Python:
default amandaFirst = False
default amandaSecond = False
default amandaThird = False
define mp = MultiPersistent( STRING_WITH_AN_UNIQUE_NAME_RELATED_TO_YOUR_PROJECT, save_on_quit=True )
label mpExport:
# If the dictionary don't exist yet...
if not hasattr( mp, "exportData" ):
# ... create it.
$ mp.exportData = {}
# Ask the player for a name for the current route.
$ exportName = Input( "Name this route")
# The data for the route will be store in a dictionary, under the name of their variable.
# Dictionary that itself will be saved in the "exportData" dictionary, under the name gave by the player.
$ mp.exportData[exportName] = {}
$ mp.exportData[exportName]["amandaFirst"] = amandaFirst
$ mp.exportData[exportName]["amandaSecond"] = amandaSecond
$ mp.exportData[exportName]["amandaThird"] = amandaThird
[...]
return
Python:
default amandaFirst = False
default amandaSecond = False
default amandaThird = False
define mp = MultiPersistent( STRING_WITH_AN_UNIQUE_NAME_RELATED_TO_YOUR_PROJECT, save_on_quit=False )
# Make this variable savable, this will permit you to know what entry in the MultiPersistent object
# is used for this playthrough. This way, you'll be able to still access it in the future
default importName = ""
label mpImport:
# Ask the player for the name of the route he want to load.
$ importName = Input( "What route to load")
$ amandaFirst = mp.exportData[importName]["amandaFirst"]
$ amandaSecond = mp.exportData[importName]["amandaSecond"]
$ amandaThird = mp.exportData[importName]["amandaThird"]
[...]
jump someLabelThatStartsTheGame
But, obviously, this is an extremely basic approach of the problem. The two pieces of code above are more to show the principle than to tell you how to do it. Below are two codes, way more advanced, that you can use, either as it or as base for your own import/export system.
You don't have permission to view the spoiler content.
Log in or register now.
You don't have permission to view the spoiler content.
Log in or register now.
How to have a clean volume start:
As hinted above, not all your players will have played the previous volume(s) of your game. While it's a pity since they clearly miss something amazing, it's also their right, and you've to be ready for this.
This mean that, in top of your game continuation or data importation label, you also need to have a regular "start" label. And, whatever the method you chose, you've a lot to do for this to be correct.
First thing first, you need to decide of a canon path for your game. Like players haven't interacted with your story, you've to decide what are the canon choices, and make them for those newcomers. For this, you need to give a default value to all the variables from the previous volume that you intent to use in this one, or that you'll import.
Python:
# The canon route is to have a relationship with Amanda...
default amandaRelationship = True
# ... but to not let her top you...
default amandaIsTop = False
# ... and to buy her a swimsuit neither too slutty nor too strict.
default amandaSwimsuit = "casual"
Python:
label start:
call screen amandaDefaultChoices
[...]
jump startForOldPlayers
screen amandaDefaultChoices():
vbox:
hbox:
# A flatering image of Amanda.
add "images/amandaProfil.png"
# A description of Amanda's personality as the player know it so far.
vbox:
text "This is Amanda."
null height 10
text "This 25 years old girl is single. Lovely and energic, she [...]"
# Ask the player about his choice.
hbox:
text "Do you want to be in a relationship with her?"
null width 20
textbutton "Yes":
action SetVariables( "amandaRelationsip", True )
null width 5
textbutton "No":
# If the player don't want to pursue her, there's no need to know who will top who.
action [ SetVariables( "amandaRelationsip", False ), Return() ]
# If the player want to be in a relationship with Amanda, ask for the complementary question.
if amandaRelationship is True:
hbox:
text "Do you want her to top you?"
null width 20
textbutton "Yes":
# Whatever the choice, we have finished here.
action [ SetVariables( "amandaIsTop", True ), Return() ]
null width 5
textbutton "No":
# Whatever the choice, we have finished here.
action [ SetVariables( "amandaIsTop", False ), Return() ]
Forcing a player to be in a relationship he don't want could harm his experience, as well as forcing him to be top when he's more submissive, or the opposite. But if the player really want to decide what swimsuit the MC offered to Amanda, he just have to play the first volume; beggar can't be choosers.
Second thing that you've to do in order to offer a clean start to newcomers is to present a small overview of what happened in the previous volume(s).
Remember how you started your game. The player knew nothing, and you had to introduce each character, including the MC. You also had to explain each major point of the universe the MC evolve in, and so on. Newcomers need this, else they'll understand nothing and be too lost to actually continue to play your game. But faithful players who play your game since the starts do not have to suffer from this second slow burn. Therefore you need to add a good old "previously on", to help those newcomers to catch up.
I'll not tell you how to do this, it fully depend on your game and style. Just keep in mind that, since you made it, why not offer to your faithful player the possibility to also see it? Not all will be interested, so it should stay an option, but those who are will without doubt be please to have this reminder. After all, how many years since you started your game?
For this last option, you can have something like this:
Python:
label start:
[Whatever you need to starts the game for newcomers]
jump previouslyOn
label previouslyOn:
"You are [MC.name] a young student addicted to adult games, living [...]"
"One day, you encountered a young girl named Amanda."
if amandaRelationship is True:
"And started a relationship with her."
if amandaIsTop is True:
"She happened to be a bit dominante, what isn't to displease you."
"Together you [...]"
[...]
"And now, let's continue our journey through this story..."
jump theStoryContinue
label mpImport:
[Whatever your import label looks like]
jump startForOldPlayers
label startForOldPlayers:
menu:
"Do you want to be reminded what happened so far?"
"Yes, it would be nice.":
jump previouslyOn
"No, I remember it.":
jump theStoryContinue
label theStoryContinue:
[Where the volume actually continue the story]
And now?:
Well, now you're ready...
You know how to pass from a volume to another while keeping the choices made by the player. You know how to clean up your variables in order to only keep the ones that will be significant for this new volume. And you know how to have a clean starts for both long time players and newcomers.
The rest, therefore how to actually implement it, what is a significant variable, and how to actually starts the game to the newcomers is totaly up to you. I gave you the canvas, now it's time for you to do your creator magic and transform it into art.
Last edited: