Ren'Py Suggestion: Code for Multi Game Persistent Character Names

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
Okay... So I've thinking about the number of developers who regularly visit the F95zone forums and some coding ideas.

One of them is for a common way of storing the player's preferred character names. In such a way that names would carried forward into future games.
RenPy has something called . A way of creating a shared set of variables across any game that uses the correctly named identifier.

After a bit of tweaking and some real world messing about, I've come up with this...

Python:
init python:

    mp_ndata = MultiPersistent("namedata.f95zone.to")
    # Recommended: male_fname, male_sname, female_fname, female_sname, futa_fname, futa_sname, other_fname or other_sname (or any, or all of these).
    # Other recommendations: bigsis_fname, lilsis_fname, bigbro_fname, lilbro_fname, mom_fname, dad_fname, malebff_fname or femalebff_fname. (Again, use any or use none).

default std_player_fname = "Jon"
default std_player_sname = "Dough"

default mc_name = "Unknown"
default mc_sname = "Unknown"

define mc = Character("[mc_name]", color="#66cc00", who_outlines=[(2,"#000000")], what_prefix="\"", what_suffix="\"", what_outlines=[(2,"#000000")])


label start:

    # allow default name(s) to be saved across multiple games
    if renpy.variant("pc"):
        if mp_ndata.male_fname != None:
            $ std_player_fname = mp_ndata.male_fname
        if mp_ndata.male_sname != None:
            $ std_player_sname = mp_ndata.male_sname

    $ mc_name = renpy.input("What is your name? {i}(Leave empty for '[std_player_fname]'){/i}", )
    $ mc_name = mc_name.strip() or std_player_fname

    $ mc_sname = renpy.input("What is your surname? {i}(Leave empty for '[std_player_sname]'){/i}", )
    $ mc_sname = mc_sname.strip() or std_player_sname

    if renpy.variant("pc"):
        if mc_name != std_player_fname:
            $ mp_ndata.male_fname = mc_name
        if mc_sname != std_player_sname:
            $ mp_ndata.male_sname = mc_sname
        $ mp_ndata.save()

    mc "Hello World. My name is [mc_name] [mc_sname]."

# [...] blah, blah... the rest of your game...
So in this example:
mc is the Character object for the main character.
mc_name is the character's given name.
mc_sname is the character's surname.

Most games would only use a player's first name... but I wanted to show an extended example.

One quirk is that (as far as I know), multi game persistency doesn't work on Android or iOS. There are apparently ways around it on Android... but I really couldn't be arsed that much. So instead, I have the code check to see if we're running on a PC (Windows/Linux/Mac, etc).

I check to see if a name is already available... and if there is one already stored - I use it as my standard/default name. Otherwise, I just go with whatever name(s) were coded into this game. I don't assume that just because a surname is stored, that a forename is also stored. I do each one by one.

I then let the player either pick the default name, or type in their own.

Then... if the player has picked a new name - store it in the multi-game persistent file. This allows people to accept the default names, without them being carried forward into new games. Only when a player overrides the defaults are they stored away to be used in the future.

Finally, the multi game data file is saved... just once... and again, only if we're running on a PC.

I've chosen the name of "namedata.f95zone.to" as the common store name. If people use that same name, it will both acknowledge where they found this code and mean that all other games that use similar code will share the same character names.

I've also added a comment with recommended common store names - since you're unlikely to want your default male characters to have the same name as your female characters. In this example I've only used male_fname and male_sname - but I could have used more... or less.
I've also added suggestions for store names for other common NPC types. Moms, Dads and Big Sisters and Little Sisters are all pretty common. The others should be fairly self explanatory. Though very few games actually think to let the player name anyone except the protagonist. (on that note: to anyone that does... please show the character's picture and explain who they are when asking for names.... there's nothing worse than seeing a young looking girl when naming - only to realize that it's not your younger sister... but the mom AFTER you've picked her name!).

Yes... it's more complicated and longer to type in than most of the existing code most people would cut and paste - but I think it's worth it. (well, I would... wouldn't I?)

Maybe if the idea catches on... it'll become a semi-common standard... and players will be continue to be surprised when the names from one game carry forward to the next.
 

Saki_Sliz

Well-Known Member
May 3, 2018
1,403
1,011
Having a collection of frameworks is a great idea! I don't know if I'll contribute anything since I don't use renpy nor use to any common systems used in renpy, but I think it is a good idea. I know lots of new dev often post questions for help with large complex systems, such as a day-night system or other nontypical renpy things, which tend not to have tutorials for.
 

Black Ram oss

Black Ram
Game Developer
May 10, 2018
582
1,564
hello, first of all thank you.
I wanted to ask something that I didn't know existed, that is:
mp_ndata = MultiPersistent("namedata.f95zone.to") # Recommended: male_fname, male_sname, female_fname, female_sname, futa_fname, futa_sname, other_fname or other_sname (or any, or all of these). # Other recommendations: bigsis_fname, lilsis_fname, bigbro_fname, lilbro_fname, mom_fname, dad_fname, malebff_fname or femalebff_fname. (Again, use any or use none).
I have seen the renpy documentation and your explanation but I have not quite understood what it is and how it should be used.
 

Black Ram oss

Black Ram
Game Developer
May 10, 2018
582
1,564
I would like to add a tip, during the development of my game I noticed that I was always repeating the same codes creating confusion in the code, so I wanted to recommend creating a function to rename the characters (I'm not a renpy expert):
Python:
init python:
    class Information():
        def __init__(self, name):
            self.name_default = name
            self.name = name
        def changeName(self):
            self.name = renpy.input("{i}(Default: " + self.name_default + "){/i}")
            self.name = self.name.strip() or self.name_default

default mcI = Information("Liam")
define mc = Character("{b}[mcI.name]{/b}")

label renaming_mc:
    "Player" "My name is:"
    $ mcI.changeName()
    return
I also leave a link of functions that I created to customize the character (I warn I'm not a renpy expert):
 
Last edited:

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
I have seen the renpy documentation and your explanation but I have not quite understood what it is and how it should be used.
Okay.

Any "normal" variables you create within your game only exist during that play session. You can save them (your save-games) and load them... but if you quit back to the main menu and start the game again... all your values are lost/reset.

Beyond that... there are what are known as variables. Once you change their value... those values are kept (they persist). Even if you restart the game, or load a new save... the values remain unchanged. All your game settings (like sound volumes, etc) are persistent for example. It's useful for things like achievements or other data you want to carry forward into the next play-through of the your game.

Finally... there is . This is taking persistent variables to the next level. The space they are stored in is available to OTHER RenPy games too. The only requirement is that there are a couple of extra steps to make them usable by your game (you need to name a shared space and save() the values through code).

The main use might be if you write a sequel to your game and want things that happened in the first game to be known in the second. As the first game ends, you'd copy of the values you care about to a uniquely named multi-game persistence space and then load them when your second game starts (or at least give the player the choice).

That shared space can have any name, but convention is that you use a name that looks like an internet URL for your "company" or project. So the one PyTom used in his example is demo.renpy.com. You might use something like "drincs.patreon.org" or "freeobs.darkrenpy.local" - all that matters is that the name doesn't clash with any other game (unless you need it to) and can be used as the name of file stored on your PC (so no names that use of : / \ etc.).

In my case, I picked "namedata.f95zone.to" - as a shared "name data" space for games likely to played by f95 players. The aim being so that when a player picks a name for their male protagonist... that name becomes the default for other games that use the same code.

To access the shared data, you need to create a RenPy object. In my case, I called it mp_ndata (multi persistent name data)... short enough to be easily typed, long enough to be recognized and not mistyped or mistaken for something else. Any variable you address/use within this space becomes part of the overall data. You just prefix any variables, with the name of the containing object and a fullstop. (So... mp_ndata.myvar1 would be a variable called myvar1 stored with the multi persistent area.

Because I hoped the code will be used across multiple games, I provided a list of suggested variable names for common names used by VN developers. Protagonist's first name and surname for male, female and futa characters seemed like a good start. But also suggestions for devs who want to go further and share player preferences for the names of Moms, Dads, Sisters, Brothers, etc. I stopped short of adding an incest suggestion in there - although that would mean that there could be a common mechanism for switching incest on/off for all games just once rather than every time you install a new game.

Trust me... I'm still a relative newbie too. The sort of class structures you use, terrify me.

Make more sense now?
 

Black Ram oss

Black Ram
Game Developer
May 10, 2018
582
1,564
Is an entire class really better than
it depends on the cases.
in my for each character I have a set of information, so instead of creating several separate variables I prefer to create a class that groups this information.
But I don't know if this is the best solution.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,979
16,236
it depends on the cases.
Well, I never encountered a case where a whole class, or a method, was better than a basic single line of code that will be used less than ten time in your whole project, and all more or less at the same time.
Possibly a macro (or for Python a lambda) in your toolbox unit, if you intend to use it in many projects, but not a method that you'll have to write/copy into each project.


in my for each character I have a set of information, so instead of creating several separate variables I prefer to create a class that groups this information.
But it's not what you recommended, and you can still assign the name directly to the right attribute of the class handling the variables.
Here, there's too much customization needed if you want to achieve a good looking integration, and this integration to works with all your projects, for a method, or even a function, to be better than a single line. Especially since by default this function is just a copy of the said single line.

You should keep your code as simple as possible. Else, you'll just multiply the complications and risk to be overwhelmed by it in the end.
 
  • Like
Reactions: Black Ram oss