Ren'Py Say screen must return a text object

watcher24

Newbie
Jun 17, 2017
69
21
Hopefully I'm posting this properly. I'm trying to create a game in renpy and I had tested it without errors. When I opened the game later, after not making any changes, I got the following error message:

While running game code:
File "game/script.rpy", line 48, in script
"Thanks for playing."
Exception: The say screen (or show_function) must return a Text object.

-- Full Traceback ------------------------------------------------------------

Full traceback:
File "game/script.rpy", line 48, in script
"Thanks for playing."
File "D:\programs\renpy\renpy 7.1.3\renpy-7.1.3-sdk\renpy\ast.py", line 690, in execute
renpy.exports.say(who, what, *args, **kwargs)
File "D:\programs\renpy\renpy 7.1.3\renpy-7.1.3-sdk\renpy\exports.py", line 1322, in say
who(what, *args, **kwargs)
File "D:\programs\renpy\renpy 7.1.3\renpy-7.1.3-sdk\renpy\character.py", line 1127, in __call__
self.do_display(who, what, cb_args=self.cb_args, **display_args)
File "D:\programs\renpy\renpy 7.1.3\renpy-7.1.3-sdk\renpy\character.py", line 842, in do_display
**display_args)
File "D:\programs\renpy\renpy 7.1.3\renpy-7.1.3-sdk\renpy\character.py", line 555, in display_say
raise Exception("The say screen (or show_function) must return a Text object.")
Exception: The say screen (or show_function) must return a Text object.

Windows-8-6.2.9200
Ren'Py 7.2.1.457
Earth girls are...? 0.10
Sat Mar 23 15:19:34 2019

If I remove all the text, the game plays fine. Would have thought the text part would be the easiest part of making the game. Would appreciate some guidance as I don't follow what the traceback is wanting me to correct. Thanks.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
File "game/script.rpy", line 48, in script
"Thanks for playing."
Exception: The say screen (or show_function) must return a Text object.
It's a really strange error you got here, and like it happen too often, the error message don't really help.
Ren'py recognize the line as a dialog line (partly because the error talk about the "say screen", partly because otherwise the error would have happen when parsing the code). My guess goes for blank character(s) at the end of the text, probably tabulation(s) since else Ren'py shouldn't complain.

If it's not this, simply remove the line and write it again to see what happen.
If the error persist, comment the line and see what happen.
If the error persist, also comment the line above and the line after, and again see what happen.
 

watcher24

Newbie
Jun 17, 2017
69
21
Thanks for the reply. I've made multiple games in rags, but this is my first renpy effort. I deleted the "Thanks for playing" line that renpy took exception to. Renpy then took exception with the very next text line. I've copied the bit of script that renpy is having a fit over. I put the line about "Thanks for playing." back in. Not sure if I did the comment lines that you suggested correctly.

# The game starts here.



label start:
scene bedroom
"Thanks for playing Earth girls are...?"
"This game contains adult material. All characters depicted are over 18."

I have a main screen with: the day number, day, time of day, etc. I'm trying to use an image button to click on that calls up a new screen to show stats for the various characters. Any suggestions how to best do something like this? I followed the format from the game take over and I had a clickable journal like in the game until the text errors killed the game. Take over does edit the screen folder so I don't know if I messed something up when I tried to follow the screen folder edit.
 
U

User_920791

Guest
Guest
I already got a similar error message after making a wrong modification on the "say" screen. Try undoing the last modifications you made in the script until you find the source of the problem.
(...) this is my first renpy effort (...) I'm trying to use an image button to click on that calls up a new screen to show stats for the various characters. (...)
Isn't a good idea start a "complex project" without having a certain experience with the engine.
 

Epadder

Programmer
Game Developer
Oct 25, 2016
568
1,064
As a general piece of advice, it's probably best not to just rip the code directly out of another game... unless it is commented to death and you know exactly how it works. It will help avoid problems like this ;).

Here's the Code for the say screen from Take Over for reference:
Python:
screen say(who, what):


#screen resistancebutton:
    text "{vspace=0}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 20} Day [day], [week_day], [time_name] {/size}{/color}{/font}"
    text "{vspace=20}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 20} Day Research points: [res_points], suspicion [suspicion]/[max_suspicion] {/size}{/color}{/font}"
    text "{vspace=40}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 20} Money: [money], supplies: [supplies]   {/size}{/color}{/font}"
    vbox xalign 0.005 yalign 0.1:
        imagebutton:
            idle "gui/s_diary_idle.png"
            hover "gui/s_diary_hover.png"
            action ui.callsinnewcontext("aff_screen_label")


            
    
    text "{vspace=690}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 18} Control serum: [serum] {/size}{/color}{/font}"

    #vbox xalign 0.075 yalign 0.82:
        #imagebutton:
            #idle "gui/icon_diary_idle.png"
            #hover "gui/icon_diary_hover.png"
            #action ui.callsinnewcontext("aff_screen_label")
            
#screen resistancebutton:
#    vbox xalign 0.075 yalign 0.98:
#        imagebutton:
#            idle "gui/icon_reich_idle.png"
#            hover "gui/icon_reich_hover.png"
#            action ui.callsinnewcontext("aff_screen_label2")
#    style_prefix "say"

    window:
        id "window"

        if who is not None:

            window:
                style "namebox"
                text who id "who"

        text what id "what"


    ## If there's a side image, display it above the text. Do not display on the
    ## phone variant - there's no room.
    if not renpy.variant("small"):
        add SideImage() xalign 0.0 yalign 1.0


style window is default
style say_label is default
style say_dialogue is default
style say_thought is say_dialogue

style namebox is default
style namebox_label is say_label


style window:
    xalign 0.5
    xfill True
    yalign gui.textbox_yalign
    ysize gui.textbox_height

    background Image("gui/textbox.png", xalign=0.5, yalign=1.0)

style namebox:
    xpos gui.name_xpos
    xanchor gui.name_xalign
    xsize gui.namebox_width
    ypos gui.name_ypos
    ysize gui.namebox_height

    background Frame("gui/namebox.png", gui.namebox_borders, tile=gui.namebox_tile, xalign=gui.name_xalign)
    padding gui.namebox_borders.padding

style say_label:
    properties gui.text_properties("name", accent=True)
    xalign gui.name_xalign
    yalign 0.5

style say_dialogue:
    properties gui.text_properties("dialogue")

    xpos gui.dialogue_xpos
    xsize gui.dialogue_width
    ypos gui.dialogue_ypos
The Code for the default say screen is for reference:
Python:
screen say(who, what):
    style_prefix "say"

    window:
        id "window"

        if who is not None:

            window:
                id "namebox"
                style "namebox"
                text who id "who"

        text what id "what"


    ## If there's a side image, display it above the text. Do not display on the
    ## phone variant - there's no room.
    if not renpy.variant("small"):
        add SideImage() xalign 0.0 yalign 1.0


## Make the namebox available for styling through the Character object.
init python:
    config.character_id_prefixes.append('namebox')

style window is default
style say_label is default
style say_dialogue is default
style say_thought is say_dialogue

style namebox is default
style namebox_label is say_label


style window:
    xalign 0.5
    xfill True
    yalign gui.textbox_yalign
    ysize gui.textbox_height

    background Image("gui/textbox.png", xalign=0.5, yalign=1.0)

style namebox:
    xpos gui.name_xpos
    xanchor gui.name_xalign
    xsize gui.namebox_width
    ypos gui.name_ypos
    ysize gui.namebox_height

    background Frame("gui/namebox.png", gui.namebox_borders, tile=gui.namebox_tile, xalign=gui.name_xalign)
    padding gui.namebox_borders.padding

style say_label:
    properties gui.text_properties("name", accent=True)
    xalign gui.name_xalign
    yalign 0.5

style say_dialogue:
    properties gui.text_properties("dialogue")

    xpos gui.dialogue_xpos
    xsize gui.dialogue_width
    ypos gui.dialogue_ypos
The thing I notice is that the "namebox" id is missing for the nested window from their code which might cause issues? I will also note that if you based your imagebutton off theirs that "ui.callsinnewcontext" is a deprecated function (all ui prefixed functions are) now and shouldn't be used.

Otherwise things I can think of are, that you have an error in the lines that are displaying the day/time/etc info and Ren'py is just happening to run into them at the text lines in question. The other possibility that springs to mind is if all the day/time/etc info was jammed into the say screen that there is a subtle syntax error that is only triggering occasionally. :unsure:
 

watcher24

Newbie
Jun 17, 2017
69
21
I already got a similar error message after making a wrong modification on the "say" screen. Try undoing the last modifications you made in the script until you find the source of the problem.


Isn't a good idea start a "complex project" without having a certain experience with the engine.
Thanks for the reply. I created a separate file for the screen so I wouldn't need to touch the original screen coding and tried to call the screen from the new file but I kept getting an error message that it could find the script. I'll restore the original screen file and, if I'm correctly following your post, this should correct the say screen error. I'd already discovered that placing the screen info in the script works.

I enjoy stat builders and a main menu of info & stats plus an image button for character info looked liked a challenging, but less complex method than say the cell phones that I've seen some games use for character stats. Having these elements in my game will help me enjoy the learning process more and be more likely to stick with it than if I instead went with a more visual novel approach. Just need to be careful not to get too over my head. Thanks for the advice.
 

watcher24

Newbie
Jun 17, 2017
69
21
As a general piece of advice, it's probably best not to just rip the code directly out of another game... unless it is commented to death and you know exactly how it works. It will help avoid problems like this ;).
Thanks so much for the reply and info. I watched various renpy videos on how to create buttons but I couldn't find one that would create a new screen for stats.


Here's the Code for the say screen from Take Over for reference:
Python:
screen say(who, what):


#screen resistancebutton:
    text "{vspace=0}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 20} Day [day], [week_day], [time_name] {/size}{/color}{/font}"
    text "{vspace=20}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 20} Day Research points: [res_points], suspicion [suspicion]/[max_suspicion] {/size}{/color}{/font}"
    text "{vspace=40}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 20} Money: [money], supplies: [supplies]   {/size}{/color}{/font}"
    vbox xalign 0.005 yalign 0.1:
        imagebutton:
            idle "gui/s_diary_idle.png"
            hover "gui/s_diary_hover.png"
            action ui.callsinnewcontext("aff_screen_label")


           
   
    text "{vspace=690}{font=fonts/Sansation_Bold.ttf}{color=#fff}{size= 18} Control serum: [serum] {/size}{/color}{/font}"

    #vbox xalign 0.075 yalign 0.82:
        #imagebutton:
            #idle "gui/icon_diary_idle.png"
            #hover "gui/icon_diary_hover.png"
            #action ui.callsinnewcontext("aff_screen_label")
           
#screen resistancebutton:
#    vbox xalign 0.075 yalign 0.98:
#        imagebutton:
#            idle "gui/icon_reich_idle.png"
#            hover "gui/icon_reich_hover.png"
#            action ui.callsinnewcontext("aff_screen_label2")
#    style_prefix "say"

    window:
        id "window"

        if who is not None:

            window:
                style "namebox"
                text who id "who"

        text what id "what"


    ## If there's a side image, display it above the text. Do not display on the
    ## phone variant - there's no room.
    if not renpy.variant("small"):
        add SideImage() xalign 0.0 yalign 1.0


style window is default
style say_label is default
style say_dialogue is default
style say_thought is say_dialogue

style namebox is default
style namebox_label is say_label


style window:
    xalign 0.5
    xfill True
    yalign gui.textbox_yalign
    ysize gui.textbox_height

    background Image("gui/textbox.png", xalign=0.5, yalign=1.0)

style namebox:
    xpos gui.name_xpos
    xanchor gui.name_xalign
    xsize gui.namebox_width
    ypos gui.name_ypos
    ysize gui.namebox_height

    background Frame("gui/namebox.png", gui.namebox_borders, tile=gui.namebox_tile, xalign=gui.name_xalign)
    padding gui.namebox_borders.padding

style say_label:
    properties gui.text_properties("name", accent=True)
    xalign gui.name_xalign
    yalign 0.5

style say_dialogue:
    properties gui.text_properties("dialogue")

    xpos gui.dialogue_xpos
    xsize gui.dialogue_width
    ypos gui.dialogue_ypos
The Code for the default say screen is for reference:
Python:
screen say(who, what):
    style_prefix "say"

    window:
        id "window"

        if who is not None:

            window:
                id "namebox"
                style "namebox"
                text who id "who"

        text what id "what"


    ## If there's a side image, display it above the text. Do not display on the
    ## phone variant - there's no room.
    if not renpy.variant("small"):
        add SideImage() xalign 0.0 yalign 1.0


## Make the namebox available for styling through the Character object.
init python:
    config.character_id_prefixes.append('namebox')

style window is default
style say_label is default
style say_dialogue is default
style say_thought is say_dialogue

style namebox is default
style namebox_label is say_label


style window:
    xalign 0.5
    xfill True
    yalign gui.textbox_yalign
    ysize gui.textbox_height

    background Image("gui/textbox.png", xalign=0.5, yalign=1.0)

style namebox:
    xpos gui.name_xpos
    xanchor gui.name_xalign
    xsize gui.namebox_width
    ypos gui.name_ypos
    ysize gui.namebox_height

    background Frame("gui/namebox.png", gui.namebox_borders, tile=gui.namebox_tile, xalign=gui.name_xalign)
    padding gui.namebox_borders.padding

style say_label:
    properties gui.text_properties("name", accent=True)
    xalign gui.name_xalign
    yalign 0.5

style say_dialogue:
    properties gui.text_properties("dialogue")

    xpos gui.dialogue_xpos
    xsize gui.dialogue_width
    ypos gui.dialogue_ypos
The thing I notice is that the "namebox" id is missing for the nested window from their code which might cause issues? I will also note that if you based your imagebutton off theirs that "ui.callsinnewcontext" is a deprecated function (all ui prefixed functions are) now and shouldn't be used.

Otherwise things I can think of are, that you have an error in the lines that are displaying the day/time/etc info and Ren'py is just happening to run into them at the text lines in question. The other possibility that springs to mind is if all the day/time/etc info was jammed into the say screen that there is a subtle syntax error that is only triggering occasionally. :unsure:
 

watcher24

Newbie
Jun 17, 2017
69
21
I've removed all the text from the game and the menu & buttons work correctly now. My understanding is that if I restore the original screen file that I will be able to restore the text and have the game not kick out an exception. I'll still continue to watch tutorials to improve my renpy coding. Just haven't found examples for such things as using an image button to call a screen.

Below is the script code with the text removed due to the exceptions in which the main screen and the image button does work to pull up the stat screen. Various items aren't currently part of the game but are for future use. Would appreciate any suggestions on other methods to use for a main menu of game/player info and various character info. Thanks for all the kind help and suggestions.

$ player_money = 50
$ game_length = 30 #default length of the game
$ day = 0 #goes for 1 months, so 30 days in the game.
$ dayTime = 0 #where 0 is morning, 1 is afternoon, 2 is night.
$ day_name = "Sunday"
$ dayTime = "Early Morning"
$day += 1 #Monday is day = 1,8,15, ect.
$ intell = 0
$ athlete = 0
$ charm = 0
$ art = 0
$hot = 9

style hudStyle is text:
bold True
color Color("#dadada")
outlines [(3, "#000", 0,0)]

style statStyle is text:
color Color("#66a3ff")
outlines [(3, "#000", 0,0)]


define day = 0
define dayTime = 0
define player_money = 50
define weekend = ((day+1)%7==0 or (day%7)==0)
define game_length = 30
define intell = 5
define athlete = 5
define charm = 5
define art = 5
define hot = 9


# The game starts here.



label start:
scene bedroom

menu:
"I am over 18.":
jump overCont

"I am under 18.":
jump underQuit

label underQuit:
"You're not allowed to view this content."
return

label overCont:
python:
inputName = renpy.input("What is your first name?")
inputName = inputName.strip()
if not inputName:
inputName = "Michael"



$ dayTime = 1
$ day = 1






screen hud: ##displays stuff for the player during normal gameplay
$day_name = "Sunday"
if (day%7) == 0:
$day_name = "Sunday"
elif (day%7 == 1):
$day_name = "Monday"
elif (day%7 == 2):
$day_name = "Tuesday"
elif (day%7 == 3):
$day_name = "Wednesday"
elif (day%7 == 4):
$day_name = "Thursday"
elif (day%7 == 5):
$day_name = "Friday"
elif (day%7 == 6):
$day_name = "Saturday"

$time_name = "Early Morning"
if dayTime == 0:
$time_name = "Early Morning"
elif dayTime == 1:
$time_name = "Morning"
elif dayTime == 2:
$time_name = "Mid Morning"
elif dayTime == 3:
$time_name = "Afternoon"
elif dayTime == 4:
$time_name = "Mid Afternoon"
elif dayTime == 5:
$time_name = "Night"

text ("Day %i/[game_length] - %s %s \n{color=#67c149}Money: $%i" %(day, day_name, time_name, player_money)) style "hudStyle" at topleft #TODO make this a style and unify the UI in v0.4
text "Intell: [intell] {p} Art: [art] {p} Charm: [charm]{p} Athlete: [athlete]" style "statStyle" at topright


show screen hud
call screen mapview

screen aff_screen:
tag menu
default ch_bio = "none"
$ corr_name = "None"
frame:

xmaximum 0
ymaximum 0
#xanchor 0.5
#yanchor 0.5
#xalign 0.5
#yalign 0.5
#xpos 0.5
#ypos 0.5
image "gui/char_bio.jpg" at Position(xaling = 0.5, yaling=0.5)
xoffset -2
yoffset -4
hbox:
vbox:
xoffset 60
yoffset 35
xsize 580

text "{font=DejaVuSans.ttf}{color=#000000}{size= 36}Journal{/size}{/color}{/font}" at center

hbox:
yoffset 15
imagebutton:
idle "gui/port_celia.png"
hover "gui/port_celia_hl.png"
action SetScreenVariable("ch_bio", "celia")

vbox:
xoffset 150
yoffset -125
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Name: Celia {/size}{/color}{/font}"
null height 10
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Occupation: Housewife{/size}{/color}{/font}"
null height 10
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Hotness: [hot] {/size}{/color}{/font}"


hbox:
yoffset 100
textbutton "Return" action Return()
null width 400

label aff_screen_label:
call screen aff_screen



label newDay:
$ renpy.block_rollback()
$ day += 1
$ dayTime = 0
$ weekend = ((day+1)%7==0 or (day%7)==0)

if day >= 60:
jump endScreen
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
The thing I notice is that the "namebox" id is missing for the nested window from their code which might cause issues?
Oh... Reading you talk about the "missing id" trigger something in my (way to be this good) memory. It was a long time ago and I don't remember it clearly, just that the id gave me a hard time when I was messing with the say screen.
If I remember correctly, at this time I found that, somewhere in Ren'py's "say" related code, the value of the id ended being a return value. View the default code for the "say" screen, I assume that it's the id "what" that should stay, since the id "who" appear before and is optional.


Otherwise things I can think of are, that you have an error in the lines that are displaying the day/time/etc info and Ren'py is just happening to run into them at the text lines in question. The other possibility that springs to mind is if all the day/time/etc info was jammed into the say screen that there is a subtle syntax error that is only triggering occasionally. :unsure:
The problem with Ren'py is that PyTom follow the Python's (Easier to Ask for Forgiveness than Permission) paradigm (by opposition to the (Look Before You Leap) paradigm). This mean that he don't validate the data when they are provided, but when they are used, which imply that the exceptions aren't triggered when the error is commit, but when the error effectively happen.

A live example of the "late triggered error" effect can be this :
Python:
default encounters = "a"

label start:
    "Welcome to my game..."
    [...]
    menu:
        "Stay at home":
            [...]
        "Go out with them":
            $ encounter += 1
            [...]
While the error is in the first line, you assigned a string value to what you'll use as counter (so a number), it's only when you'll try to increment the counter that the error will happen. The error will be a TypeError exception, "coercing to Unicode: need string or buffer, int found". Despite being not this obvious, if you track the use of the variable, you'll found the declaration line and understand that the default value shouldn't be "a".

Another example is encountered time to time with Ren'py games, and demonstrate how hard it can be to solve the problem in these cases :
Python:
define m = Character( "[m]" )

label start:
    "What's your name ?"
    $ m = renpy.input()
You overwrite the value of m, and will have a hard time because of this. But the error will talk about an endless loop, and will happen only when you'll use things like this girl "Hey [m.name] how are you ?".
Here, finding the error is a real pain in the ass if you don't already heard about the problem. Ren'py will point out the Character object as source of the error, and you'll look everything regarding it, without thinking that it can be in fact the m variable the real cause of the error.

In those two examples, there's no real way to LBYL, but providing an example directly related to Ren'py's code isn't this easy. They are numerous, but not necessarily easy to understand and/or demonstrate. So I'll create one :
Python:
init python:

    class MyCharEAFP( renpy.python.RevertableObject ):

        def __init__( self, name, charObj, baseLove ):
            self.name = name
            self.renpyChar = charObj
            self.love = baseLove

        def incLove( self, step ):
            self.love += step

    class MyCharLBYL( renpy.python.RevertableObject ):

        def __init__( self, name, charObj, baseLove ):
            # Technically you should also validate these two.
            self.name = name
            self.renpyChar = charObj
            # Validate that it's effectively an integer.
            if not isinstance( baseLove, int ):
                raise exceptions.TypeError( "The default value for 'Love' MUST be a number: {} found".format( type( baseLove ) ) )
            self.love = baseLove

        def incLove( self, step ):
            self.love += step

default s = Character( "Sarah" )
default girl1 = MyCharEAFP( "Sarah", 1, s )
default a = Character( "Amanda" )
default girl2 = MyCharLBYLP( "Amanda", 1, a )

label start:
    [...]
    $ girl1.incLove( 1 )
The error is simple and the same for both the EAFP and LBYL version of the object, the value for charObj and baseLove parameters are inverted ; it's something that happen more often that I'm ready to admit.
With the EAFP version, the error will be triggered when you'll use the incLove and be the "coercing to Unicode: need string or buffer, int found" TypeError exception I talked above.
With the LBYL version, the error will be triggered when you'll create the girl2 object, and be the explicit error message I decided to use.


All this doesn't mean that the LBYL paradigm is better, ideally you should use both, depending of the context. Nor it mean that Ren'py is badly wrote. No, it just show that Ren'py's errors message can be really tricky, aren't necessarily user friendly, and should never be took "as it".
 
  • Like
Reactions: Epadder

watcher24

Newbie
Jun 17, 2017
69
21
Thanks to everyone for all the help and suggestions. I restored the original screen file and this fixed the text exceptions. I'm continuing to work through tutorials and creating mini test projects to try out the info I learn from the tutorials. Wonderful to be unstuck again.
 

watcher24

Newbie
Jun 17, 2017
69
21
I've run into an additional issue with the mapview & aff screens. At mid day I give the journal access to the player with:
call screen mapview
screen mapview:
vbox xalign 0.5 yalign 0.02:
imagebutton:
idle "gui/diary_idle.png"
hover "gui/diary_hover.png"
action ui.callsinnewcontext("aff_screen_label")-I tried to replace this with a jump command but it didn't work. Maybe I had the wrong syntax for it?

This puts the journal imagebutton on the screen. In order for the player to click on the journal imagebutton, I need to call for the aff screen:
label aff_screen_label:
call screen aff_screen

screen aff_screen:
tag menu
default ch_bio = "none"
$ corr_name = "None"
frame:

xmaximum 0
ymaximum 0
#xanchor 0.5
#yanchor 0.5
#xalign 0.5
#yalign 0.5
#xpos 0.5
#ypos 0.5
image "gui/char_bio.jpg" at Position(xaling = 0.5, yaling=0.5)
xoffset -2
yoffset -4
hbox:
vbox:
xoffset 60
yoffset 35
xsize 580

text "{font=DejaVuSans.ttf}{color=#000000}{size= 36}Journal{/size}{/color}{/font}" at center

hbox:
yoffset 15
imagebutton:
idle "gui/port_celia.png"
hover "gui/port_celia_hl.png"
action SetScreenVariable("ch_bio", "celia")

vbox:
xoffset 150
yoffset -125
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Name: Celia {/size}{/color}{/font}"
null height 10
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Occupation: Housewife{/size}{/color}{/font}"
null height 10
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Hotness: [hot] {/size}{/color}{/font}"


hbox:
yoffset 100
textbutton "Return" action Return()
null width 400

Now the player can click on the imagebutton to see the character stats. They hit the return button on the journal page to return to the main screen. At this point, renpy is waiting for the next action. So I enter a jump to the next label. However, when the player uses the aff button again it reuses the jump action and puts the game into a loop. How do I instruct renpy to return to where the game left off when the player consulted the stat screen? I may be getting this issue due to putting the aff screen info in the script file. I tried to place the aff screen info on it's own file but this gave me a renpy exception telling me that it couldn't find the aff.

I'm trying to have an image button that players click on to take them to a screen of character stats to view and then return to the main screen. There may be a better way to do this, but I haven't had any luck finding a similar example.
 

Epadder

Programmer
Game Developer
Oct 25, 2016
568
1,064
It would really help if you used the "Insert Code" function the forum has ;).

Regardless, instead of using ui.callsinnewcontext, use The command both shows and hides the screen named, just make sure to add "modal True" to aff_screen so that only things on that screen can be clicked on.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Regardless, instead of using ui.callsinnewcontext, use [...] just make sure to add "modal True" to aff_screen so that only things on that screen can be clicked on.
Since the screen will be modal, ToggleScreen isn't necessary ; it will never have to hide the screen. is a better option, coupled to in the shown screen
Code:
textbutton "Return" action Hide( "screen_aff")
 

watcher24

Newbie
Jun 17, 2017
69
21
It would really help if you used the "Insert Code" function the forum has ;).

Regardless, instead of using ui.callsinnewcontext, use The command both shows and hides the screen named, just make sure to add "modal True" to aff_screen so that only things on that screen can be clicked on.
Sorry for the code . Wasn't aware of the insert code function. I'm wanting the journal that is called by mapview & then the aff screen to be hidden for roughly the first half of the day as it contains character info and the player hasn't met the characters associated with it. At mid day, the player has met the characters so I'm calling the mapview for the image button and the associated aff screen to show character stats once the imagebutton is pressed. At this point, I would like the journal image button to remain shown on the main screen to be able to be used by the player for the rest of the game. Are you saying that I should have the screens active prior to the game and call them with show at the mid day point? Sorry for my confusion.

To clarify - I need to change the original mapview code:
Code:
action ui.callsinnewcontext("aff_screen_label")
To:
Code:
textbutton "Return" action Hide( "screen_aff")
As well as add:
Code:
modal True
To the aff screen.

I've made the above changes but still have the same loop when the player uses the journal image button. Namely that it jumps the player home and runs through some holding place text that I put into the game. Do I need to move the aff screen coding prior to the start of the game? Coding is as follows:

Code:
label aff_screen_label:
    call screen aff_screen

jump home

return

label home:
    scene bedroom
    show screen hud
    "Finally, the school day is over."
Thanks for the help.
 

watcher24

Newbie
Jun 17, 2017
69
21
Since the screen will be modal, ToggleScreen isn't necessary ; it will never have to hide the screen. is a better option, coupled to in the shown screen
Code:
textbutton "Return" action Hide( "screen_aff")
Thanks for the reply. As noted in my post above, I've replaced the action ui.call with your textbutton return code. However, it appears that I need coding to address what renpy needs to do after the journal stat screen has been closed. Currently renpy reuses the jump home command(see above) after every use of the journal. I moved the aff screen code to prior to the game start and call the journal code at mid day but still get the same loop. I call the journal with:
Code:
show screen mapview
label aff_screen_label:
    show screen aff_screen
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Do I need to move the aff screen coding prior to the start of the game? Coding is as follows:

Code:
label aff_screen_label:
    call screen aff_screen

jump home

return

label home:
    scene bedroom
    show screen hud
    "Finally, the school day is over."
Thanks for the help.

Stop, you're doing it wrong here. But to be honest without an effective piece of code it's not necessarily easy to understand if you start with all this.

Code:
init python:
    #  This will display the /mapview/ screen as overlay on the screen.
    # So the button will always be visible.
    config.overlay_screens.append( "mapview" )


screen mapview:
    vbox xalign 0.5 yalign 0.02:
    imagebutton:
        idle "gui/diary_idle.png"
        hover "gui/diary_hover.png"
        # This will display the /aff_screen/ screen.
        action Show( "aff_screen" )

screen aff_screen:

    #  This will prevent the player to click somewhere else
    # than THIS screen. So he can only click on the /Return/
    # button defined bellow.
    modal True
    [Your actual code for this screen]

    hbox:
        yoffset 100
        #  This will close the screen and let the game continue
        # exactly where he were before the screen show up.
        textbutton "Return" action Hide( "aff_screen" )
 

watcher24

Newbie
Jun 17, 2017
69
21
Thank you again for your help. Sorry for misunderstanding. I've made the corrections that you posted above. When I call the mapview to show the journal imagebutton, the game doesn't show any additional text until the player clicks on the journal imagebutton and then closes the stat screen that the diary opens. I believe this is due to the return action for the journal being in the aff screen coding. I've tried to add a return action to the mapview coding using "return" but it didn't work. It's not a huge deal of course since the game will continue once the journal is opened. Just trying to figure out how to code it in case a player doesn't want to click the journal button to check the character stats. Thanks for everyone's assistance for a renpy newbie.
 

Scrot

Definitely not Scrot
Apr 30, 2018
525
5,477
I've removed all the text from the game and the menu & buttons work correctly now. My understanding is that if I restore the original screen file that I will be able to restore the text and have the game not kick out an exception. I'll still continue to watch tutorials to improve my renpy coding. Just haven't found examples for such things as using an image button to call a screen.

Below is the script code with the text removed due to the exceptions in which the main screen and the image button does work to pull up the stat screen. Various items aren't currently part of the game but are for future use. Would appreciate any suggestions on other methods to use for a main menu of game/player info and various character info. Thanks for all the kind help and suggestions.

$ player_money = 50
$ game_length = 30 #default length of the game
$ day = 0 #goes for 1 months, so 30 days in the game.
$ dayTime = 0 #where 0 is morning, 1 is afternoon, 2 is night.
$ day_name = "Sunday"
$ dayTime = "Early Morning"
$day += 1 #Monday is day = 1,8,15, ect.
$ intell = 0
$ athlete = 0
$ charm = 0
$ art = 0
$hot = 9

style hudStyle is text:
bold True
color Color("#dadada")
outlines [(3, "#000", 0,0)]

style statStyle is text:
color Color("#66a3ff")
outlines [(3, "#000", 0,0)]


define day = 0
define dayTime = 0
define player_money = 50
define weekend = ((day+1)%7==0 or (day%7)==0)
define game_length = 30
define intell = 5
define athlete = 5
define charm = 5
define art = 5
define hot = 9


# The game starts here.



label start:
scene bedroom

menu:
"I am over 18.":
jump overCont

"I am under 18.":
jump underQuit

label underQuit:
"You're not allowed to view this content."
return

label overCont:
python:
inputName = renpy.input("What is your first name?")
inputName = inputName.strip()
if not inputName:
inputName = "Michael"



$ dayTime = 1
$ day = 1






screen hud: ##displays stuff for the player during normal gameplay
$day_name = "Sunday"
if (day%7) == 0:
$day_name = "Sunday"
elif (day%7 == 1):
$day_name = "Monday"
elif (day%7 == 2):
$day_name = "Tuesday"
elif (day%7 == 3):
$day_name = "Wednesday"
elif (day%7 == 4):
$day_name = "Thursday"
elif (day%7 == 5):
$day_name = "Friday"
elif (day%7 == 6):
$day_name = "Saturday"

$time_name = "Early Morning"
if dayTime == 0:
$time_name = "Early Morning"
elif dayTime == 1:
$time_name = "Morning"
elif dayTime == 2:
$time_name = "Mid Morning"
elif dayTime == 3:
$time_name = "Afternoon"
elif dayTime == 4:
$time_name = "Mid Afternoon"
elif dayTime == 5:
$time_name = "Night"

text ("Day %i/[game_length] - %s %s \n{color=#67c149}Money: $%i" %(day, day_name, time_name, player_money)) style "hudStyle" at topleft #TODO make this a style and unify the UI in v0.4
text "Intell: [intell] {p} Art: [art] {p} Charm: [charm]{p} Athlete: [athlete]" style "statStyle" at topright


show screen hud
call screen mapview

screen aff_screen:
tag menu
default ch_bio = "none"
$ corr_name = "None"
frame:

xmaximum 0
ymaximum 0
#xanchor 0.5
#yanchor 0.5
#xalign 0.5
#yalign 0.5
#xpos 0.5
#ypos 0.5
image "gui/char_bio.jpg" at Position(xaling = 0.5, yaling=0.5)
xoffset -2
yoffset -4
hbox:
vbox:
xoffset 60
yoffset 35
xsize 580

text "{font=DejaVuSans.ttf}{color=#000000}{size= 36}Journal{/size}{/color}{/font}" at center

hbox:
yoffset 15
imagebutton:
idle "gui/port_celia.png"
hover "gui/port_celia_hl.png"
action SetScreenVariable("ch_bio", "celia")

vbox:
xoffset 150
yoffset -125
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Name: Celia {/size}{/color}{/font}"
null height 10
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Occupation: Housewife{/size}{/color}{/font}"
null height 10
text "{font=DejaVuSans.ttf}{color=#000000}{size= 30}Hotness: [hot] {/size}{/color}{/font}"


hbox:
yoffset 100
textbutton "Return" action Return()
null width 400

label aff_screen_label:
call screen aff_screen



label newDay:
$ renpy.block_rollback()
$ day += 1
$ dayTime = 0
$ weekend = ((day+1)%7==0 or (day%7)==0)

if day >= 60:
jump endScreen
I have a question for you when i tested your code the code didn't show the day on screen i added there the missing image but what i wanted from your code didn't show up so i wanted to know if your code really shows up that information so i need to delete half of your code to it show?
-EDIT-
Found my error i deleted everything and kept what i really wanted from your code and for now everything working fine thank you :)
 
Last edited: