• To improve security, we will soon start forcing password resets for any account that uses a weak password on the next login. If you have a weak password or a defunct email, please update it now to prevent future disruption.

Organizing Renpy Code/Files/Scripts

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,202
14,938
You can also consider adding code for repetitive actions, for example if you have a point based system that awards points based on an action, that also displays a message to the user - instead of repeating everything each time you can use something like:

Python:
init python:

    def change_stat(stat, amount):
            if rel_notify:
                if amount > 0:
                    renpy.notify("Your relationship has increased!")
                else:
                    renpy.notify("Your relationship has decreased!")
            stat += amount
            return stat
And in your script you would just use:

Python:
$ POINT_VARIABLE = change_stat(POINT_VARIABLE, 1)
POINT_VARIABLE is your specific variable for the points, the 1 can be any number, even a negative to reduce points.
Why so complicated in terms of use ?

There's two easier, and more flexible ways to do this:

In Python:
Python:
init python:

    def change_stat(stat, amount=1, notify=True):
            # Change the value
            setattr( store, stat, getattr( store, stat ) + amount )

            if notify:
                renpy.notify("Your relationship has {}!".format( "increased" if amount > 0 "decreased" )


label whatever:

    # Add 1 and notify ; the most frequent use.
    $ change_stat( "myVar" )

    # Remove 1 and notify
    $ change_stat( "myVar", -1 )

    # Add 1 but don't notify
    $ change_stat( "myVar", notify=False )

    # Add 5 and don't notify
    $ change_stat( "myVar", 5, False )
The same can even be done in Ren'Py language. What present not real advantage here since mostly everything is in fact Python:
Python:
label change_stat( stat, amount=1, notify=True ):

    $ setattr( store, stat, getattr( store, stat ) + amount )

    if notify:
          $ renpy.notify("Your relationship has {}!".format( "increased" if amount > 0 "decreased" )

    return

label whatever:
    call change_stat( "myVar" )

It can also works if you use an object to store the points, and then have more precise notifications:
Python:
init python:

    def change_stat( who, stat, amount=1, notify=True):
            # Change the value
            setattr( who, stat, getattr( who, stat ) + amount )

            if notify:
                # Assuming the object have a /name/ attribute.
                renpy.notify("{}'s {} has {}!".format( who.name, stat.title(), "increased" if amount > 0 "decreased" )

label whatever:
    $ change_stat( sarah, "love" )
    $ change_stat( anna, "lust", -1 )
 
  • Like
Reactions: fooslock

peterppp

Member
Mar 5, 2020
469
879
just to add, if you do use show screen (instead of Call) (there are some cases when you would), you can add:

Python:
$ _skipping = False
To prevent the player from skipping past that screen, just remember to enable it again once they have moved past the screen. (But honestly, use call and return for screens if you can).

You can also consider adding code for repetitive actions, for example if you have a point based system that awards points based on an action, that also displays a message to the user - instead of repeating everything each time you can use something like:

Python:
init python:

    def change_stat(stat, amount):
            if rel_notify:
                if amount > 0:
                    renpy.notify("Your relationship has increased!")
                else:
                    renpy.notify("Your relationship has decreased!")
            stat += amount
            return stat
And in your script you would just use:

Python:
$ POINT_VARIABLE = change_stat(POINT_VARIABLE, 1)
POINT_VARIABLE is your specific variable for the points, the 1 can be any number, even a negative to reduce points.
change_stat("relationship",0)
--> Your relationship has decreased!
:whistle:
 

peterppp

Member
Mar 5, 2020
469
879
Why would you ever use 0 ?
famous last words
point is that your code isn't covering all bases.
but to give an example... you are calculating the value to raise and so you don't know what the value will be. it could be 0.
change_stat("relationship", calculated_value)
 

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,575
2,714
famous last words
point is that your code isn't covering all bases.
but to give an example... you are calculating the value to raise and so you don't know what the value will be. it could be 0.
change_stat("relationship", calculated_value)
Since you're manually increasing or decreasing a stat, I ask again when would you EVER want to increase or decrease it by 0 ?

Since your putting 1, 2, 3 or any number in there you know full well what number it would be so you know what number to raise it by it will -never- be 0. Why would it be?

Your covering a base that just doesn't need to be covered.
 

peterppp

Member
Mar 5, 2020
469
879
Since you're manually increasing or decreasing a stat, I ask again when would you EVER want to increase or decrease it by 0 ?

Since your putting 1, 2, 3 or any number in there you know full well what number it would be so you know what number to raise it by it will -never- be 0. Why would it be?

Your covering a base that just doesn't need to be covered.
if you do it manually yes, but i gave you an example of when you don't do it manually.

my first comment was said in jest, but it doesn't mean it's not a good point. if you cover all bases, the code won't bug even when used for something you didn't intend to use it for when you first coded it.
that's good coding practice. no need to, like, get upset or anything
 

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,575
2,714
if you do it manually yes, but i gave you an example of when you don't do it manually.

my first comment was said in jest, but it doesn't mean it's not a good point. if you cover all bases, the code won't bug even when used for something you didn't intend to use it for when you first coded it.
that's good coding practice. no need to, like, get upset or anything
I'm not upset, far from it. Just curios why you thought a use case of 0 would ever exist for increasing or decrease a relationship point?

If it was in jest then it's clearly lost in translation. And covering for every use case is a rabbit hole of futility, not best coding practice. Keep It Simple Stupid, however, is.

Let's move on, shall we?
 

fooslock

Newbie
Feb 15, 2020
65
25
In Python:
Python:
init python:

def change_stat(stat, amount=1, notify=True):
# Change the value
setattr( store, stat, getattr( store, stat ) + amount )

if notify:
renpy.notify("Your relationship has {}!".format( "increased" if amount > 0 "decreased" )


label whatever:

# Add 1 and notify ; the most frequent use.
$ change_stat( "myVar" )

# Remove 1 and notify
$ change_stat( "myVar", -1 )

# Add 1 but don't notify
$ change_stat( "myVar", notify=False )

# Add 5 and don't notify
$ change_stat( "myVar", 5, False )
Is it a good idea to keep stuff like this seperate as well? Feels like a lot of this should simply have its own file to help organize it best


It can also works if you use an object to store the points, and then have more precise notifications:
Python:
init python:

def change_stat( who, stat, amount=1, notify=True):
# Change the value
setattr( who, stat, getattr( who, stat ) + amount )

if notify:
# Assuming the object have a /name/ attribute.
renpy.notify("{}'s {} has {}!".format( who.name, stat.title(), "increased" if amount > 0 "decreased" )

label whatever:
$ change_stat( sarah, "love" )
$ change_stat( anna, "lust", -1 )
Oof OOP. Not my strongest suit, but if it removes repetitiveness, It's worth looking into again.
 

fooslock

Newbie
Feb 15, 2020
65
25
just to add, if you do use show screen (instead of Call) (there are some cases when you would), you can add:

Python:
$ _skipping = False
To prevent the player from skipping past that screen, just remember to enable it again once they have moved past the screen. (But honestly, use call and return for screens if you can).
Is there certain times we would want to stop the players from skipping that you've seen? Like they stop at choices and what not, but are you maybe implying stopping at certain, important scenes, where important hints or dialogue happens?

You can also consider adding code for repetitive actions
Python:
Code:
init python:

    def change_stat(stat, amount):
            if rel_notify:
                if amount > 0:
                    renpy.notify("Your relationship has increased!")
                else:
                    renpy.notify("Your relationship has decreased!")
            stat += amount
            return stat
It is always worth it not to have to write one more extra line of code if it can be avoided. What do you see yourself usually trying to avoid retyping? Point notifications are an obvious one, but what else? And hey thanks for coming and sharing, much appreciated friend.
 

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,575
2,714
Is there certain times we would want to stop the players from skipping that you've seen? Like they stop at choices and what not, but are you maybe implying stopping at certain, important scenes, where important hints or dialogue happens?
Most uses would be edge cases to be honest, just something to put away for a possible future need :)

It is always worth it not to have to write one more extra line of code if it can be avoided. What do you see yourself usually trying to avoid retyping? Point notifications are an obvious one, but what else? And hey thanks for coming and sharing, much appreciated friend.
I also use this for a gallery, using a for loop to run through a list and if they have been unlocked to show a thumbnail in a grid that players can click on to view the image.

IT's simple shit, but instead of writing multiple lines (for each image) use a for loop once.
 

fooslock

Newbie
Feb 15, 2020
65
25
Most uses would be edge cases to be honest, just something to put away for a possible future need :)
Nothing wrong with that, I'll put it in my toolbox.

I also use this for a gallery, using a for loop to run through a list and if they have been unlocked to show a thumbnail in a grid that players can click on to view the image.

IT's simple shit, but instead of writing multiple lines (for each image) use a for loop once.
That's a pretty smart idea. Do you keep your script code and gallery code separate? What else do you separate?
 

peterppp

Member
Mar 5, 2020
469
879
If it was in jest then it's clearly lost in translation.
my bad then. i didn't know a whistle emoji would be seen as anything than a joke in that situation...you know, feigned innocence...

And covering for every use case is a rabbit hole of futility, not best coding practice.
i can't let this stand because this is really bad advice. i hope you don't code anything more important than a VN... like control mechanisms for a nuclear plant.

Keep It Simple Stupid, however, is.
that doesn't mean allowing bugs to happen just because you're too lazy to add a check for 0 too.

Let's move on, shall we?
sure thing. starting now
:whistle:
 

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,575
2,714
That's a pretty smart idea. Do you keep your script code and gallery code separate? What else do you separate?
Separate everything, events have their own script file, story goes in another. Variables have their own file. Each update has its own folder as well. It makes finding things much easier.

This is an image of an early game (not yet released) I split everything out into its own file. You don't have to do this, but as has been said before - it can make finding things much easier and quicker.

1699801734128.png

It's an example only.
 
  • Like
Reactions: fooslock

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,202
14,938
Just curios why you thought a use case of 0 would ever exist for increasing or decrease a relationship point?
Well, because it can exist, and even exist in some games:

Python:
label whatever:
   $ good = 0
   $ bad = 0
   [...]
   menu:
       "You look beautiful in that dress":
           $ good += 1
       "Hello":
           pass
       "Oh god, didn't you had something better to wear ?":
           $ bad += 1
   menu:
       "I'm sorry, the bus was stuck in the traffic, I hope you haven't had to wait too long":
           $ good += 1
       "Say nothing":
           pass
       "Glad that I'm here ?":
           $ bad += 1
   menu:
       "So, what do you want to do ?":
           $ good += 1
       "I've already planed our afternoon, you better not complain about it.":
           $ bad += 1
    [...]

    $ girlLove = change_stat( girlLove, good - bad )
Here I made the choice obvious, but it's far to be mandatory.
In stories where the girls have a clearly defined personality, offering flower can perfectly be the bad answer, because she isn't at all into "romantic shit", or because she's a gold digger who would have preferred some jewellery.

Of course, one could argue that the same can be achieved by changing the value with every interaction. But it would defeat the purpose. It's not the action that change her affection, it's the feeling she get at the end of the whole date.
You'll necessarily do some bad move, because nobody is perfect. But as long than there's less bad moves than good ones, she'll go back home loving you more.
 
  • Like
Reactions: fooslock

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,575
2,714
Well, because it can exist, and even exist in some games:

Python:
label whatever:
   $ good = 0
   $ bad = 0
   [...]
   menu:
       "You look beautiful in that dress":
           $ good += 1
       "Hello":
           pass
       "Oh god, didn't you had something better to wear ?":
           $ bad += 1
   menu:
       "I'm sorry, the bus was stuck in the traffic, I hope you haven't had to wait too long":
           $ good += 1
       "Say nothing":
           pass
       "Glad that I'm here ?":
           $ bad += 1
   menu:
       "So, what do you want to do ?":
           $ good += 1
       "I've already planed our afternoon, you better not complain about it.":
           $ bad += 1
    [...]

    $ girlLove = change_stat( girlLove, good - bad )
Here I made the choice obvious, but it's far to be mandatory.
In stories where the girls have a clearly defined personality, offering flower can perfectly be the bad answer, because she isn't at all into "romantic shit", or because she's a gold digger who would have preferred some jewellery.

Of course, one could argue that the same can be achieved by changing the value with every interaction. But it would defeat the purpose. It's not the action that change her affection, it's the feeling she get at the end of the whole date.
You'll necessarily do some bad move, because nobody is perfect. But as long than there's less bad moves than good ones, she'll go back home loving you more.
Yup good point.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Separate everything, events have their own script file, story goes in another. Variables have their own file. Each update has its own folder as well. It makes finding things much easier.

This is an image of an early game (not yet released) I split everything out into its own file. You don't have to do this, but as has been said before - it can make finding things much easier and quicker.

View attachment 3080611

It's an example only.
Pretty fancy. mind if I pop your game open and peak under the hood abit? is that considered rude? feel like it might be.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,202
14,938
Is it a good idea to keep stuff like this seperate as well? Feels like a lot of this should simply have its own file to help organize it best
Yes and no. Strictly speaking there's not reason for this, but generally people prefer when things are grouped together.
So, like it's some utility code, it being with the other ones in an "utility.rpy" file, by example, would feel more natural.


Oof OOP. Not my strongest suit, but if it removes repetitiveness, It's worth looking into again.
You'll have to deal a lot with it once you graduated. So, better to starts with something basic like an adult game.
And it's not just a question of repetitiveness, it present two other advantages:

Firstly, it permit to groups the data.
It's something regarding "sarah", it will be in the "sarah" object. Cleaner data management, less to memorize, faster access in terms of code writing.

Secondly, it permit to add a level of abstraction to your code.
If your change your mind regarding the way to do something, you just have to update the class, and your code will automatically adapt.

By example, instead of relying on a change_stat() function, it can be a method:
Python:
init python:

    class Stats( renpy.python.RevertableObject ):
        def __init__( self, name ):
            self.name = name
            self.love = 0
            self.lust = 0

        def change_stat( self, what, step = 1, notify = True ):
            setattr( self, what, getattr( self, what ) + step )
            if notify and not step == 0:
                renpy.notify( "{}'s {} has {}".format( self.name, what, "increased" if step > 0 else "decreased" )

        def update_love( self, step = 1 ):
            self.change_stat( "love", step )

        def update_lust( self, step = 1 ):
            self.change_stat( "lust", step )
If you decide to change the way you notify about a stat change, just update the change_stat() method.

If you decide to cap the lust, just change the update_lust() method, like that by example:
Python:
        def update_lust( self, step = 1 ):
            if self.lust < 20:
                self.change_stat( "lust", step )
You can also decide that the positive stats are linked to the negative ones:
Python:
        def update_love( self, step = 1 ):
            if self.anger <= 0:
                self.change_stat( "love", step )
            else:
                renpy.notify( "{} is clearly too angry to appreciate it".format( self.name ) )
All is clearly in the same place, directly and easily available, and just changing one method is enough to safely change the behavior for the whole game.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Well, because it can exist, and even exist in some games:

Python:
label whatever:
   $ good = 0
   $ bad = 0
   [...]
   menu:
       "You look beautiful in that dress":
           $ good += 1
       "Hello":
           pass
       "Oh god, didn't you had something better to wear ?":
           $ bad += 1
   menu:
       "I'm sorry, the bus was stuck in the traffic, I hope you haven't had to wait too long":
           $ good += 1
       "Say nothing":
           pass
       "Glad that I'm here ?":
           $ bad += 1
   menu:
       "So, what do you want to do ?":
           $ good += 1
       "I've already planed our afternoon, you better not complain about it.":
           $ bad += 1
    [...]

    $ girlLove = change_stat( girlLove, good - bad )
Here I made the choice obvious, but it's far to be mandatory.
In stories where the girls have a clearly defined personality, offering flower can perfectly be the bad answer, because she isn't at all into "romantic shit", or because she's a gold digger who would have preferred some jewellery.

Of course, one could argue that the same can be achieved by changing the value with every interaction. But it would defeat the purpose. It's not the action that change her affection, it's the feeling she get at the end of the whole date.
You'll necessarily do some bad move, because nobody is perfect. But as long than there's less bad moves than good ones, she'll go back home loving you more.
so looking at this I'm guessing the date can end with zero. or even negative? I was thinking of using stats in my game to where you collect them but just have to meet thresholds to get the majority of the content so like, as long as you're generally not a douche you don't have to make every perfect choice.
 

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,575
2,714
Pretty fancy. mind if I pop your game open and peak under the hood abit? is that considered rude? feel like it might be.
Fine by me. Code is code - Learning how others do it can help give people ideas, just like what anne O'nymous posted is a good idea to add flexibility to the changing stat code. It's worth adapting and using (assuming you want that flexibility) if all you want is a simple version then keep it simple. though adding a check for 0 might be an idea if you plan to aggregate relationship points at the end of a scene or choices?

Personally I prefer to give instant feedback, so I'd be notifying at each stat change - which probably defeats the whole reduce the amount of repetitions - but you get the idea.

Everyone's different - its a VN, not the inside of a nuclear reactor :p

Oh the gallery code isn't in my latest version - but if your interested I can DM it to you. if it may prove useful.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Fine by me. Code is code - Learning how others do it can help give people ideas, just like what @anne O'nymous posted is a good idea to add flexibility to the changing stat code. It's worth adapting and using (assuming you want that flexibility) if all you want is a simple version then keep it simple. though adding a check for 0 might be an idea if you plan to aggregate relationship points at the end of a scene or choices?
yea I plan to implement more than a few of the ideas floated so far. Lot of good stuff been posted here.

Oh the gallery code isn't in my latest version - but if your interested I can DM it to you. if it may prove useful.
I'm not often one to say no to a helping hand. I'd really appreciate that.