[RENPY] Modding Help

21.

New Member
Oct 11, 2020
5
2
Hello, I'm quite new to ren'py and wondering what are the best tools to get started on editing the main game .rpy scripts. I currently have:

Unren.bat
Source Editor ( I'm using Visual Code with RENPY installed as a plugin; if there is maybe a better source editor I can use, please comment below which one).

I have extracted some modding sources to get an idea also, I'd love for some tips and extra comments from the community for me to start creating mods.

- Thank you.
 
  • Like
Reactions: Echoooooo

felipons

Fluffy, The Destroyer of Worlds
Modder
Game Developer
Jan 15, 2018
250
1,032
Unren.bat
Source Editor ( I'm using Visual Code with RENPY installed as a plugin; if there is maybe a better source editor I can use, please comment below which one).
About tools that's pretty much it.
Haven't found any better than Visual Code, just make sure your VC and Renpy Plugin is updated (They corrected a bug with region collapse, that was collapsing extra white lines at the end of the method on renpy)

Some good information I can give you:

1 - Info I can give you is that you can't rewrite a label, but you can create a new label and substitute the old one by this new one.

E.g: Let's say you want to add a new icon to hud and the hud of the game in question is a "label" not a "screen", and the label is called "main_hud".
If you make a new label called "main_hud" you'll get an error saying that the label is duplicated.
To substitute the label you have to create a new one with a different name let's say "main_hud_mod", and then add the override definition to the old label like this.

Python:
    define config.label_overrides = {
        'main_hud': 'main_hud_mod'
    }
This way whenever "main_hud" is called it'll actually go to "main_hub_mod".

2 - Renpy obeys an order of execution, whenever you need to change a screen or something like that keep that in mind.
Generally I just add a "init 999:" and write anything within that block.

E.g.: From one Gallery Mod I made:
Python:
init 999:
    screen main_menu() tag menu:
        window:
            style "mm_root"
        frame:
            style_group "mm"
            xalign .98
            yalign .98
            has vbox
            textbutton _("New Game") action Start()
            textbutton _("Load Game") action ShowMenu("load")
            textbutton _("Preferences") action ShowMenu("preferences")
            textbutton _("Gallery") action Start("gallery_menu")
            textbutton _("Help") action Help()
            textbutton _("Support Us!") action OpenURL("http://www.patreon.com/mity")
            textbutton _("Disclaimer") action ShowMenu("disclaimer")
            textbutton _("Quit") action Quit(confirm=False)
       
        if gallery_version in config.version:
            text "v[config.version] + Gallery" xpos 10 ypos 10
        else:
            text "v[config.version] + Gallery ([gallery_version] Check for Updates)" xpos 10 ypos 10
This way you can make sure it'll override the original screen, to the one you made.

3 - Although you are making a mod, there is virtually no limit for what is possible to do, so just make sure to not fuck the game up, and or substitute/remove something you shouldn't.

4 - Don't be afraid to use python, some people only use the basic renpy, but you can create methods classes and other nice things with python, like this:
Python:
init -5:
    python:
        class Item():
            def __init__(self, id, name):
                self.id = id
                self.name = name

        def GetItemById(id):
            for i in Items:
                if i.id == id:
                    return i

        Items = [ Item(1, "Magnanimous Dildo"), Item(2, "Car Key")]

    label start:
        $ item = GetItemById(1)

        "MC" "Hey, look I have a nice item, it's called {b}[item.name]{/b}"

5 - Compact the Mod in a ".rpa" file, or you'll end with a pain in the ass of people asking you how to install the mod...

For this you just need the engine
 

wurg

Active Member
Modder
Apr 19, 2018
705
1,632
define config.label_overrides
You need to be careful with this one, something I didn't know when I first started messing with it is that if the game doesn't "jump" or "call" the label, it will ignore config.lable_overrides. A lot of games just flow from one label to the next without any jump statements in them. If you want to use this to modify a label that is already in the game, make sure the game "jumps" or "calls" the label.

init 999: screen main_menu() tag menu:
I've never seen someone put a screen inside an init block like that, but if it works it works. I don't know the exact load order of the different structures in Ren'Py so I can't comment on it.

For the gallery mods I've made for games, if I'm going to change the main menu screen or things like that, I make the new screen in a different file and put a "z_" in front of it. Ren'py goes through and loads the files in alphabetical order, so if you want to overwrite something in the original game, like the main menu layout, put it in a file with a name lower in the alphabet and it will overwrite the original one in the game. Like most code, the last definition of something is what is stored in memory.

Labels don't work like that though, each label has to have a unique name or the game will throw errors.

If you want to look at a different code editor for Ren'Py, there's Atom ( ), I think the same people that made Ren'Py have a part in it also, not sure though. I like it for Ren'Py, just got used to it really, I use VS, and VS code for C# though. I don't like the way it displays the code colors for Ren'py code in VS.

If you don't know a lot about Python or Ren'Py ( like me ), you need to bookmark this page:

it's basically your bible to search if you need some help. The site has a good search in it to help you find things.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,235
14,996
2 - Renpy obeys an order of execution, whenever you need to change a screen or something like that keep that in mind.
Generally I just add a "init 999:" and write anything within that block.

E.g.: From one Gallery Mod I made:
Python:
init 999:
    screen main_menu() tag menu:
        window:
Ren'py also process files in alphabetical order. Therefore when it come to screen redefinition, by example, you absolutely don't need to rely on the init level. Just put the new definition in a file that will be proceeded after the one where the original screen is, and you're good.
That why some generic mods have a name starting with "z" ; it ensure that they'll be proceeded last and overwrite all what need to be overwrote.



3 - Although you are making a mod, there is virtually no limit for what is possible to do, so just make sure to not fuck the game up, and or substitute/remove something you shouldn't.
There's more to worry, among which this :
Python:
init -5:
    python:
        class Item():
            def __init__(self, id, name):
                self.id = id
                self.name = name

        def GetItemById(id):
            for i in Items:
                if i.id == id:
                    return i

        Items = [ Item(1, "Magnanimous Dildo"), Item(2, "Car Key")]

    label start:
        $ item = GetItemById(1)

        "MC" "Hey, look I have a nice item, it's called {b}[item.name]{/b}"
Congratulation, you just broke the save files. People using your mod will have the obligation to always use it, or to restart the game if they decide not to.

A mod should rely on basic types present by default in Python and Ren'py. And if you've no other choice than using custom objects, they must be kept not savable, using an external structure (a dict by example) to store the data that need to stay available from a play to another.

Also in this particular example, putting the creation of item in the start "label" imply that people wanting to try your mod will have to start a fresh game.
Using define item = GetItemById( 1 ) is the way you should have done it. Not only it would preserve the save compatibility, but it would also make the variable available for people who just want to continue playing where they left the game.
 

felipons

Fluffy, The Destroyer of Worlds
Modder
Game Developer
Jan 15, 2018
250
1,032
Congratulation, you just broke the save files. People using your mod will have the obligation to always use it, or to restart the game if they decide not to.

A mod should rely on basic types present by default in Python and Ren'py. And if you've no other choice than using custom objects, they must be kept not savable, using an external structure (a dict by example) to store the data that need to stay available from a play to another.

Also in this particular example, putting the creation of item in the start "label" imply that people wanting to try your mod will have to start a fresh game.
Using define item = GetItemById( 1 ) is the way you should have done it. Not only it would preserve the save compatibility, but it would also make the variable available for people who just want to continue playing where they left the game.

I actually just put that as an example of what is possible to do with python, as that's an example of item 4 not item 3...
I doubt someone that creates a mod would make a label called "start" as it would conflict with the already existing label "start".

But what you said is true, unless of course you use that parameter only as a local variable of the specific label you made for the mod.
E.g: Let's say you made an extended story mod, then it's ok to use local variables of complex objects, because those will be entirely new label that will only exist/be called if you have the mod.
 
Last edited:

21.

New Member
Oct 11, 2020
5
2
I want to thank you all for this load of information to help me with my modding within renpy, you guys seriously are helping me with this information and I will for sure keep this all in mind. Thank you so much!!
Gold R1 hotfixes
About tools that's pretty much it.
Haven't found any better than Visual Code, just make sure your VC and Renpy Plugin is updated (They corrected a bug with region collapse, that was collapsing extra white lines at the end of the method on renpy)

Some good information I can give you:

1 - Info I can give you is that you can't rewrite a label, but you can create a new label and substitute the old one by this new one.

E.g: Let's say you want to add a new icon to hud and the hud of the game in question is a "label" not a "screen", and the label is called "main_hud".
If you make a new label called "main_hud" you'll get an error saying that the label is duplicated.
To substitute the label you have to create a new one with a different name let's say "main_hud_mod", and then add the override definition to the old label like this.

Python:
    define config.label_overrides = {
        'main_hud': 'main_hud_mod'
    }
This way whenever "main_hud" is called it'll actually go to "main_hub_mod".

2 - Renpy obeys an order of execution, whenever you need to change a screen or something like that keep that in mind.
Generally I just add a "init 999:" and write anything within that block.

E.g.: From one Gallery Mod I made:
Python:
init 999:
    screen main_menu() tag menu:
        window:
            style "mm_root"
        frame:
            style_group "mm"
            xalign .98
            yalign .98
            has vbox
            textbutton _("New Game") action Start()
            textbutton _("Load Game") action ShowMenu("load")
            textbutton _("Preferences") action ShowMenu("preferences")
            textbutton _("Gallery") action Start("gallery_menu")
            textbutton _("Help") action Help()
            textbutton _("Support Us!") action OpenURL("http://www.patreon.com/mity")
            textbutton _("Disclaimer") action ShowMenu("disclaimer")
            textbutton _("Quit") action Quit(confirm=False)
     
        if gallery_version in config.version:
            text "v[config.version] + Gallery" xpos 10 ypos 10
        else:
            text "v[config.version] + Gallery ([gallery_version] Check for Updates)" xpos 10 ypos 10
This way you can make sure it'll override the original screen, to the one you made.

3 - Although you are making a mod, there is virtually no limit for what is possible to do, so just make sure to not fuck the game up, and or substitute/remove something you shouldn't.

4 - Don't be afraid to use python, some people only use the basic renpy, but you can create methods classes and other nice things with python, like this:
Python:
init -5:
    python:
        class Item():
            def __init__(self, id, name):
                self.id = id
                self.name = name

        def GetItemById(id):
            for i in Items:
                if i.id == id:
                    return i

        Items = [ Item(1, "Magnanimous Dildo"), Item(2, "Car Key")]

    label start:
        $ item = GetItemById(1)

        "MC" "Hey, look I have a nice item, it's called {b}[item.name]{/b}"

5 - Compact the Mod in a ".rpa" file, or you'll end with a pain in the ass of people asking you how to install the mod...

For this you just need the engine
You need to be careful with this one, something I didn't know when I first started messing with it is that if the game doesn't "jump" or "call" the label, it will ignore config.lable_overrides. A lot of games just flow from one label to the next without any jump statements in them. If you want to use this to modify a label that is already in the game, make sure the game "jumps" or "calls" the label.



I've never seen someone put a screen inside an init block like that, but if it works it works. I don't know the exact load order of the different structures in Ren'Py so I can't comment on it.

For the gallery mods I've made for games, if I'm going to change the main menu screen or things like that, I make the new screen in a different file and put a "z_" in front of it. Ren'py goes through and loads the files in alphabetical order, so if you want to overwrite something in the original game, like the main menu layout, put it in a file with a name lower in the alphabet and it will overwrite the original one in the game. Like most code, the last definition of something is what is stored in memory.

Labels don't work like that though, each label has to have a unique name or the game will throw errors.

If you want to look at a different code editor for Ren'Py, there's Atom ( ), I think the same people that made Ren'Py have a part in it also, not sure though. I like it for Ren'Py, just got used to it really, I use VS, and VS code for C# though. I don't like the way it displays the code colors for Ren'py code in VS.

If you don't know a lot about Python or Ren'Py ( like me ), you need to bookmark this page:

it's basically your bible to search if you need some help. The site has a good search in it to help you find things.
Ren'py also process files in alphabetical order. Therefore when it come to screen redefinition, by example, you absolutely don't need to rely on the init level. Just put the new definition in a file that will be proceeded after the one where the original screen is, and you're good.
That why some generic mods have a name starting with "z" ; it ensure that they'll be proceeded last and overwrite all what need to be overwrote.





There's more to worry, among which this :


Congratulation, you just broke the save files. People using your mod will have the obligation to always use it, or to restart the game if they decide not to.

A mod should rely on basic types present by default in Python and Ren'py. And if you've no other choice than using custom objects, they must be kept not savable, using an external structure (a dict by example) to store the data that need to stay available from a play to another.

Also in this particular example, putting the creation of item in the start "label" imply that people wanting to try your mod will have to start a fresh game.
Using define item = GetItemById( 1 ) is the way you should have done it. Not only it would preserve the save compatibility, but it would also make the variable available for people who just want to continue playing where they left the game.
I actually just put that as an example of what is possible to do with python, as that's an example of item 4 not item 3...
I doubt someone that creates a mod would make a label called "start" as it would conflict with the already existing label "start".

But what you said is true, unless of course you use that parameter only as a local variable of the specific label you made for the mod.
E.g: Let's say you made an extended story mod, then it's ok to use local variables of complex objects, because those will be entirely new label that will only exist/be called if you have the mod.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,235
14,996
E.g: Let's say you made an extended story mod, then it's ok to use local variables of complex objects, because those will be entirely new label that will only exist/be called if you have the mod.
The only way to have "local variables" in Ren'py is to declare them as it with renpy.dynamic, but then they will be only available in the current label. Else, the variable will be global to the whole game scope and included in any save you'll create.

You can also create the object into an init block, or with define. They will be global, but not savable, what will preserve the save compatibility.
 

DavidCF

Member
Aug 10, 2020
353
127
Hi there,
Is there a technique when modding a game that uses a .rpa file and you use a .rpy file, to
stop duplicate declaration errors.
In some games I get the error and some I do not and I have no idea what I am doing differently
in each case to avoid them.

The label s1e1_cafevisit_act2 is defined twice, at File "game/s1e1.rpy", line 66:
label s1e1_cafevisit_act2:
and File "game/z_patch.rpy", line 6:
label s1e1_cafevisit_act2:

Comments Please
Thanks.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,235
14,996
Is there a technique when modding a game that uses a .rpa file and you use a .rpy file, to
stop duplicate declaration errors.
Yes: do not copy the original labels unless you really, really can't do otherwise. And when you do, don't use the same name.

Ren'Py have a dict named that is to use when you mod and need to replace a label, hook to it, or correct something in it.