Ren'Py python functions

Evildad

Member
Jan 7, 2019
113
218
Google translator
Good day.
I needed your help with the implementation of several functions.
I have now made the introduction to my game so far. But only with renpy basics.
In the further course I need on the one hand a day system, quest system, menus and queries.
I can do this with my basic knowledge, but then it's very static and excessively long.
I've already found something on the subject of the Tag System and Quest. However, I have problems with creating my own functions.

I would like to pack my renpy menus into functions with variables so that I don't always have to create hundreds of menus.
Especially when there are innovations during an update, I have to constantly adjust everything individually.

My train of thought now looked like this.
Python:
init:
    $ aa = "text"
    $ bb = "text"
    $ cc = "text"
    $ dd = "text"

init python:
    def menue():
        if xy = True
            menu:
                "[aa]":
                    "yy"
                    jump 1 # Mit Variable?
                "[bb]":
                    "zz"
                    jump 2 # Mit Variable?
        else:
            menu:
                "[cc]":
                    "xx"
                    jump 3
                "[dd]":
                    "yy"
                    jump 4
label start:
    $ Menu = menue()
Of course, python doesn't make it that easy for me.
How would something like that look like when implemented correctly?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,363
15,277
Python:
init python:
    def menue():
        if xy = True    # <-- This should be "==" and not "="
            menu:          # <-- This is Ren'py, not Python
                "[aa]":          # <-- This is Ren'py, not Python
                    "yy"          # <-- This is Ren'py, not Python
                    jump 1          # <-- This is Ren'py, not Python
                "[bb]":          # <-- This is Ren'py, not Python
                    "zz"          # <-- This is Ren'py, not Python
                    jump 2          # <-- This is Ren'py, not Python
        else:
            menu:          # <-- This is Ren'py, not Python
                "[cc]":          # <-- This is Ren'py, not Python
                    "xx"          # <-- This is Ren'py, not Python
                    jump 3          # <-- This is Ren'py, not Python
                "[dd]":          # <-- This is Ren'py, not Python
                    "yy"          # <-- This is Ren'py, not Python
                    jump 4          # <-- This is Ren'py, not Python
label start:
    $ Menu = menue()          # <-- This could be just "$ menue()"

How would something like that look like when implemented correctly?
Your main problem is that you don't understand the difference between "Python language" and "Ren'py language".

Ren'py is easy to use because it have its own language, that is an easy way to write the code of your game.
But if, or when, you want to do the same directly with Python language, it will become more difficult and complicated. And, more important, it will only exceptionally be easier than doing the same directly with "Ren'py language".

In your case, having menus in Python is (relatively) simple, you have to use . A working equivalent of what you tried to do is :
Code:
init python:
    def menue():

        if xy == True
            return = renpy.display_menu( [ ( aa, aa ), ( bb, bb ) ] )
            if return == aa:
                renpy.say( narrator, yy )
                renpy.jump( label1 )
            else:
                renpy.say( narrator, zz )
                renpy.jump( label2 )
        else:
            return = renpy.display_menu( [ ( cc, cc ), ( dd, dd ) ] )
            if return == cc:
                renpy.say( narrator, xx )
                renpy.jump( label3 )
            else:
                renpy.say( narrator, yy )
                renpy.jump( label4 )

label start:
    $ aa = "first choice if xy is True"
    $ bb = "second choice if xy is True"
    $ cc = "first choice if xy is not True"
    $ dd = "first choice if xy is not True"
    $ xx = "answer if first choice for xy is not True"
    $ yy = "answer if first  choice for xy is True and second choice for xy is not True"
    $ zz = "answer if second choice for xy is True"
    $ label1 = "label if first choice for xy is True
    $ label2 = "label if second choice for xy is True"
    $ label3 = "label if first choice for xy is not True"
    $ label4 = "label if second choice for xy is not True"
    $ menue()

But how can it be better than the same directly in "Ren'py language" ? And I mean something that would do exactly the same :
Code:
menu menue:
    "[aa]" if xy == True:
        "yy"
        jump expression label1
    "[bb]" if xy == True :
        "zz"
        jump expression label2
    "[cc]" if xy != True :
        "xx"
        jump expression label3
    "[dd]" if xy != True :
        "yy"
        jump expression label4

label start:
    $ aa = "first choice if xy is True"
    $ bb = "second choice if xy is True"
    $ cc = "first choice if xy is not True"
    $ dd = "first choice if xy is not True"
    $ xx = "answer if first choice for xy is not True"
    $ yy = "answer if first  choice for xy is True and second choice for xy is not True"
    $ zz = "answer if second choice for xy is True"
    $ label1 = "label if first choice for xy is True
    $ label2 = "label if second choice for xy is True"
    $ label3 = "label if first choice for xy is not True"
    $ label4 = "label if second choice for xy is not True"
    jump menue

But anyway, how this can be easier than effectively creating a menu each time you need one ?
Code:
label start:
    menu:
        "first choice if xy is True" if xy == True:
        "answer if first  choice for xy is True and second choice for xy is not True"
        jump theRightLabel
    "second choice if xy is True" if xy == True :
        "answer if second choice for xy is True"
        jump theRightLabel
    "first choice if xy is not True" if xy != True :
        "answer if first choice for xy is not True"
        jump theRightLabel
    "first choice if xy is not True" if xy != True :
        "answer if first  choice for xy is True and second choice for xy is not True"
        jump theRightLabel
You will need exactly the same number of lines to write both.
Except that, when you use directly a menu, you have an intuitive view of what you are doing.
Plus you are not dependent of the number of choice defined in your menue idea, and can have more than one dialog line for a choice, no dialog line for another choice, and whatever else you can need to have at a given moment.


TL;DR: There is absolutely no advantage to rewrite the menu statement, unless you are in a position where this statement can not be used.
 

Evildad

Member
Jan 7, 2019
113
218
First of all, thank you very much for the help.
Unfortunately, my translation didn't come across as easy to understand.
It was clear to me that Renpy and Python are two independent languages. Had I asked (how do I open renpy in python) it would probably have made it easier.
I am currently learning python and have just arrived at functions and classes. It also says that my code should make it as flexible as possible. Of course I try to implement that.
Why not directly with renpy? It's just for practice purposes and I thought that I would learn more that way and that it would be easier for me to build a system of tasks and time.
My problem until now was that my attempt to only use renpy has become extremely confusing. I had felt 200 lines of if queries in each scene. Therefore, it seemed to me that the whole thing should be packed into functions as a sympathetic.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,363
15,277
Since you used Google translate for your first message, I'll be direct in order to facilitate the translation. Sorry if it make me looks rude.


It also says that my code should make it as flexible as possible.
And, as I said, you'll never ever achieve to do something better than Ren'py menu.
How do you intend to implement:
  • the parameters, both for the menu itself and for the choices ?
  • text interpolation inside the choices text ?
  • the possibility to have a dialog line displayed in the same time than the menu ?
  • the optional display of disabled choices ?
  • the possibility to only display the choices that have not been picked yet ?
  • empty choice ?
  • inline python into the choice block ?
  • the optional choice conditioning ?
  • nested menu and complex Ren'py code in a choice block ?

Of course, for some of those points you can always make it happen in an independent label. But, while it will be as flexible as the actual menu, it will not be as easier. This because you'll have to write a label for that, and make it return to the correct point, what imply that you'll need to have a label to define this return point ; all this being purely optional when you directly use Ren'py menu.

It's purely theoretical, but with Ren'py, menus can looks like that:
Code:
label whatever:
    e "I'll take you with me this time."
    menu menuLabel (screen="altMenu", x=100, y=200 ):
        set menuLabelChoices
        e "Do you need some preparations ?"
        "To do this"(hint="Need to have 'that'") if haveThat is True:
            $ haveThat = False
            e "blabla"
            "blibli"
            jump menuLablel
        "To do that"(hint="She'll not necessarily like that"):
            if counter < 5:
                e "The fuck !!!"
            else:
                menu:
                    "really ?"
                    "yes":
                        $ counter += 1
                        e "blabla..."
                        extend "blibli"
                        "bloblo"
                    "no":
                        pass
            jump menuLablel
        "I'm done.":
            pass
    e "Alright, you seem ready to continue."
And there's just no way that you achieve to make something that will be as powerful, easy and flexible. The best you'll be able to do is to rewrite what already exist. But even then, it will not be easier to use, and it will not have the years of existence, and thousand of people who used it, then validated that there's no bugs.


Why not directly with renpy? It's just for practice purposes and I thought that I would learn more that way and that it would be easier for me to build a system of tasks and time.
Practice that, globally speaking, will lead you nowhere.
You'll not learn more about Python by doing this. Most of the time you will use functions and objects that are purely dedicated to Ren'py, and therefore that don't exist elsewhere.
As for Ren'py, you will learn near to nothing about it. All the "Python equivalent" are a limited version of the corresponding statement. Learning Ren'py through them will let you with a limited view of what is effectively possible to achieve. Just look above what the menu statement permit, compared to the renpy.display_menu() "Python equivalent", that only let you define the screen to use and choices that will return a string. Some features can be copied (the possibility to display a dialog line or the conditioning, by example), other absolutely cannot (the parameters associated to the menu and choices).


My problem until now was that my attempt to only use renpy has become extremely confusing. I had felt 200 lines of if queries in each scene. Therefore, it seemed to me that the whole thing should be packed into functions as a sympathetic.
While I agree that if is a plague that you've to use too often in Ren'py, if you need to have this many of them, to the point you think that using Python would be easier, the problem do not come from Ren'py but from you. It's not due to the language, but to the way you use it ; and probably a lack of knowledge regarding Ren'py.
And trying to replicate Ren'py by using Python will never be the solution to this problem.


A scene need different images depending of the way a character is dressed ? Instead of :
Code:
label whatever:
    if dress == "something":
        scene scene01dress
    else:
        scene scene01dress1
    [...]
    if dress == "something":
        scene scene02dress
    else:
        scene scene02dress1
    [...]
    if dress == "something":
        scene scene03dress
    else:
        scene scene03dress1
    [...]
Just do :
Code:
image scene01 = "/images/characterName/sceneX/[dress]_01.jpg"
image scene02 = "/images/characterName/sceneX/[dress]_02.jpg"
image scene03 = "/images/characterName/sceneX/[dress]_03.jpg"

label whatever:
    scene scene01
    [...]
    scene scene02
    [...]
    scene scene03
    [...]
Or even :
Code:
label whatever:
    scene expression "/images/characterName/sceneX/{}_01.jpg".format( dress )
    [...]
    scene expression "/images/characterName/sceneX/{}_02.jpg".format( dress )
    [...]
    scene expression "/images/characterName/sceneX/{}_03.jpg".format( dress )
    [...]
A menu will have more or less choice depending of the context ? Instead of :
Code:
label whatever:
    if this == "something":
        menu:
            "do this":
                [...]
            "do that":
                [...]
    else:
        menu:
            "do this":
                [...]
            "do that":
                [...]
Just do :
Code:
label whatever:
    if this == "something":
        menu:
            "do this" if this == "something":
                [...]
            "do that" if this == "something":
                [...]
            "do this" if this != "something":
                [...]
            "do that" if this != "something":
                [...]
You want to branch to a different label depending of the context ? Instead of :
Code:
label whatever:
    [...]
    if this == "one":
        jump oneLabel
    elif this == "another":
        jump anotherLabel
Just do:
Code:
label whatever:
    [...]
    jump expression "{}Label".format( this )
And so on. Ren'py offer an amazing flexibility that render a lot of if purely useless.
 

Evildad

Member
Jan 7, 2019
113
218
Since you used Google translate for your first message, I'll be direct in order to facilitate the translation. Sorry if it make me looks rude.
Doesn't seem rude. I prefer it directly anyway. ;)

You've convinced me. I have now experimented a little and have already been able to make my code much clearer.
I really have a lot to learn.
And thanks again for the help and food for thought!