Ren'Py Anyone know how to call a screen from within a defined function?

Studio Errilhl

Member
Game Developer
Oct 16, 2017
315
235
So, I have a function (which I'm pondering just turning into a label at this point):
Code:
def w_mc():
        c = 0
        mcI = False
        mc_b = getattr(store,"mc_b")
        if mc_b >= 40 and mc_b < 100:
            c = .35
        elif mc_b >= 100 and mc_b <= 150:
            c = .25
        else:
            c = .5
        if renpy.random.random() > c:
            if mc_b <= 40:
                mcI = 1
            elif mc_b <= 75:                       
                mcI = .5
            else:
                mcI = .25
        if mcI:
            statschangeNotify("mc_b",mcI)
        hour = getattr(store,"current_hour")
        current_hour = str(int(hour[:2])+1)+hour[2:]
        renpy.show_screen("ingame_menu_display")
It works fine - but, the renpy.show_screen("ingame_menu_display") does not. I've of course tried the regular Ren'Py method of show screen ingame_menu_display, but that doesn't seem to work either. This code is in a init -10 python: block, which might have something to do with it - so, anyone know what I need to do? :D
 

Papa Ernie

Squirrel!?
Uploader
Donor
Dec 4, 2016
12,327
47,120
So, I have a function (which I'm pondering just turning into a label at this point):
Code:
def w_mc():
        c = 0
        mcI = False
        mc_b = getattr(store,"mc_b")
        if mc_b >= 40 and mc_b < 100:
            c = .35
        elif mc_b >= 100 and mc_b <= 150:
            c = .25
        else:
            c = .5
        if renpy.random.random() > c:
            if mc_b <= 40:
                mcI = 1
            elif mc_b <= 75:                      
                mcI = .5
            else:
                mcI = .25
        if mcI:
            statschangeNotify("mc_b",mcI)
        hour = getattr(store,"current_hour")
        current_hour = str(int(hour[:2])+1)+hour[2:]
        renpy.show_screen("ingame_menu_display")
It works fine - but, the renpy.show_screen("ingame_menu_display") does not. I've of course tried the regular Ren'Py method of show screen ingame_menu_display, but that doesn't seem to work either. This code is in a init -10 python: block, which might have something to do with it - so, anyone know what I need to do? :D
I know very little about programming, but doesn't your last "if" statement need a value? ie "if mcI >= 0:"
 

Studio Errilhl

Member
Game Developer
Oct 16, 2017
315
235
No - in Python, you check if the value exist at all - if it's empty / False, it will not return True - which that one will, given that it has a value after the previous statement. The problem is that the show screen blah blah doesn't work, it returns an unknown syntax error.
 

Studio Errilhl

Member
Game Developer
Oct 16, 2017
315
235
try

renpy.show_screen(ingame_menu_display)
Nope, it returns a "global name 'ingame_menu_display' is not defined"... which gives me an idea...

And my idea didn't work (not that surprising) - I tried setting it as global, but that didn't work, of course.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,101
14,748
Alright, first the code :
Code:
        mc_b = getattr(store,"mc_b")
It do what you want, but here it's useless since "store.mc_b", and even "mc_b", let you directly access to the value. The prefixed syntax is better, because it clearly show that you talk about a variable/attribute in the Ren'py default store, and not a local variable/attribute.
getattr is to use when the name of the variable/attribute isn't fixed, like in your statschangeNotify where the name is stored into a variable. But here you know the name and it will always be the same.

Code:
       if mc_b >= 40 and mc_b < 100:
Python can works with intervals. I don't know if it's faster or not, but it's definitively easier to read. Like you begin with Python, using the most readable way is always the best option, because it let you focus on things more complex.

You don't have permission to view the spoiler content. Log in or register now.

This code is in a init -10 python: block, which might have something to do with it
No, the place where the code is declared change nothing. It's just the place where the code is called which have a influence. By example, running it at "init" level will obviously lead to a problem since there nowhere to display a screen at this time.


All this said, I just tried your code, exactly like you wrote it. And it works, the screen (well, the things I put behind "screen ingame_menu_display" for my test) is displayed and all.
Anyway, you said that you tried to display it directly from Ren'py and that it doesn't worked. So, my guess is an error somewhere in the screen. But a subtle error. Something that don't crash because it's a valid syntax, but still display an empty screen or directly return. More or less like the indentation problem you had last time. All works, but because of this little subtle error, it doesn't work at all like expected.
Still I'll go for a full debug process, it can help you in the future. But before this, because indentations are a real problem let's be clear : Your file look like this, right ?
Code:
init -10 python:
    [can be something or nothing, but at least at this level of indentation]
    def w_mc():
         [your code]
Like you can multiply the "init" blocks in a single file, in case of doubt just put an "init -10 python:" (without any indentation obviously) right before the "def w_mc():" (with a 4 indentation, and the code of the function with a 8 indentation).
Now that we are clear and sure that the problem is not the indentation, let's go...

1) Rename the screen "ingame_menu_display1", and write a basic "ingame_menu_display" screen for the test. Something really simple which will never fail like :
Code:
screen ingame_menu_display:
    frame:
        text "working"
Is it working now ? If yes, it's the screen the problem.

2) Return to the initial "ingame_menu_display" content and change the "start" label of your game like this :
Code:
label start:
   show screen ingame_menu_display
   "blablabla is this working ?"
   return
   [the actual content of your "start" label]
Is the screen displayed ? If yes, it's not the screen. Yeah I know, obvious :D but like you know that you function is correct, since it works for me, it's still a progress.

3) Try with the most basic function possible :
Code:
    def w_mc():
        renpy.show_screen("ingame_menu_display")
Once again, rename your actual function "w_mc1" like for the screen ; no need to loss your works.
If it works, it's somewhere in the function. The only difference between your version and the one I tried is "statschangeNotify". I used a "renpy.notify" instead since I don't have the code anymore. So, the problem come from somewhere in "statschangeNotify".

4) If it still don't work, it's weird. It probably mean that the moment you call the function is not appropriated for a "show screen". So, back to the "start" label, this time with :
Code:
   $ w_mc()
   "blablabla is this working ?"
   return
If it works, it's because you call it at a moment where Ren'py don't agree to display a screen. But it's still weird.


Nope, it returns a "global name 'ingame_menu_display' is not defined"...
Yeah, the syntax suggested assume that "ingame_menu_display" is a variable, so it can't works. The syntax you use for "renpy.show_screen" is correct.
Oh, by the way, try: "renpy.call_screen" ? It works differently and probably isn't what you wanted, but who know.
 

Studio Errilhl

Member
Game Developer
Oct 16, 2017
315
235
Oh, well, I ended up doing it as a simple label, and calling it when needed, instead. Can't waste that much time on this.

Hi again @anne O'nymous :) You seem to be a regular drop in on these questions. Well, I know the screen works, because 1. Before I moved everything into a function, it worked fine. Second, this is a ingame-menu screen, it's always displayed. What this show-call does, is simply updating it with new content (ie, the time-variable gets updated)
2. As stated, I modified it to a label, and tried running it from with in the label start: - and that works fine. So I think it's a renpy-issue, not anything else.

Here's the code I'm currently using:
Code:
label w_mc:
        $ c = 0
        $ mcI = False
        if mc_b >= 40 and mc_b < 100:
            $ c = .35
        elif mc_b >= 100 and mc_b <= 150:
            $ c = .25
        else:
            $ c = .5
        if renpy.random.random() > c:
            if mc_b <= 40:
               $ mcI = 1
            elif mc_b <= 75:                       
               $ mcI = .5
            else:
               $ mcI = .25
        if mcI:
            $ statschangeNotify("mc_b",mcI)
        $ hour = getattr(store,"current_hour")
        $ current_hour = str(int(hour[:2])+1)+hour[2:]
        $ current_hour = current_hour.rjust(5,'0')
        show screen ingame_menu_display
I modified the getattr call, and I had to do some minor adjustments to the time-code, to get it to work properly. But that there works fine, the screen gets updated, and everyone (well, me) is happy :) Thanks for trying to help, though - I will remember what you said for future endeavors, finding errors and such :)
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,101
14,748
What this show-call does, is simply updating it with new content (ie, the time-variable gets updated)
I stop you here. You do NOT need to do this, Ren'py do it for you.

Try this :
Code:
init python:
    myValue = 1
screen test:
    frame:
        text "value [myValue]"
label start:
    show screen test
    python:
        for i in range( 1, 50 ):
            myValue += 1
            renpy.pause( 0.1 )
    "end"
    return
Launch it, start the "game", and watch the magic happen :D

Ren'py predict each screen more or less every two seconds, and it also update every displayed screen in (feel like) real time when something have changed.
 

Studio Errilhl

Member
Game Developer
Oct 16, 2017
315
235
Disregard that... I had trouble with it not updating, hence why I added that in. Tested again now... and it works just fine... Have no idea what broke it before (back then it was just manual assignments in the script.rpy file). Oh well, I've taken out the show-calls now :)