[Solved] Conditional textbuttons in Quickmenu don't work

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
Ayutac
Regular
Posts: 150
Joined: Thu Oct 18, 2012 2:23 pm
Projects: Pokémon Dating Sim
Organization: A Breeze Of Science
Deviantart: Ubro
Location: Mayence, Germany
Contact:

[Solved] Conditional textbuttons in Quickmenu don't work

#1 Post by Ayutac »

In my original script I get cryptical error messages.

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/intro.rpy", line 69, in script
    scene bg apartment with fade
  File "game/screens.rpy", line 310, in <module>
    use quick_menu #xalign 0.0 yalign 0.5
  File "game/screens.rpy", line 388, in <module>
    textbutton _("To Apartment") action [shortcutToApartment(), renpy.jump('endMeeting')]
  File "game/events.rpy", line 92, in shortcutToApartment
    narrator("You take a shortcut back home.")
  File "game/screens.rpy", line 310, in <module>
    use quick_menu #xalign 0.0 yalign 0.5
  File "game/screens.rpy", line 388, in <module>
    textbutton _("To Apartment") action [shortcutToApartment(), renpy.jump('endMeeting')]
[Recursion occurs]
  File "game/events.rpy", line 92, in shortcutToApartment
    narrator("You take a shortcut back home.")
  File "game/screens.rpy", line 310, in <module>
    use quick_menu #xalign 0.0 yalign 0.5
  File "game/screens.rpy", line 380, in <module>
    yalign 1.0
RuntimeError: maximum recursion depth exceeded in cmp

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

Full traceback:
  File "game/intro.rpy", line 69, in script
    scene bg apartment with fade
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/ast.py", line 1187, in execute
    renpy.exports.with_statement(trans, paired)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/exports.py", line 1155, in with_statement
    return renpy.game.interface.do_with(trans, paired, clear=clear)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 1726, in do_with
    clear=clear)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 2076, in interact
    scene_lists.replace_transient()
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 592, in replace_transient
    self.remove(layer, tag)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 866, in remove
    self.hide_or_replace(layer, remove_index, "hide")
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 790, in hide_or_replace
    d = oldsle.displayable._hide(now - st, now - at, prefix)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 204, in _hide
    hid.update()
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 288, in update
    self.screen.function(**self.scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/screenlang.py", line 1239, in __call__
    renpy.python.py_exec_bytecode(self.code.bytecode, locals=scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/python.py", line 1382, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/screens.rpy", line 310, in <module>
    use quick_menu #xalign 0.0 yalign 0.5
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 621, in use_screen
    screen.function(**scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/screenlang.py", line 1239, in __call__
    renpy.python.py_exec_bytecode(self.code.bytecode, locals=scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/python.py", line 1382, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/screens.rpy", line 388, in <module>
    textbutton _("To Apartment") action [shortcutToApartment(), renpy.jump('endMeeting')]
  File "game/events.rpy", line 92, in shortcutToApartment
    narrator("You take a shortcut back home.")
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/character.py", line 817, in __call__
    self.do_display(who, what, cb_args=self.cb_args, **display_args)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/character.py", line 683, in do_display
    **display_args)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/character.py", line 462, in display_say
    what_text = show_function(who, what_string)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/character.py", line 667, in do_show
    **self.show_args)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/character.py", line 268, in show_display_say
    **kwargs)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 513, in show_screen
    renpy.exports.show(name, tag=_tag, what=d, layer=_layer, zorder=d.zorder, transient=_transient, munge_name=False)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/exports.py", line 443, in show
    sls.add(layer, img, key, zorder, behind, at_list=at_list, name=name, atl=atl, default_transform=renpy.config.default_transform, transient=transient)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 768, in add
    self.hide_or_replace(layer, remove_index, "replaced")
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/core.py", line 790, in hide_or_replace
    d = oldsle.displayable._hide(now - st, now - at, prefix)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 204, in _hide
    hid.update()
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 288, in update
    self.screen.function(**self.scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/screenlang.py", line 1239, in __call__
    renpy.python.py_exec_bytecode(self.code.bytecode, locals=scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/python.py", line 1382, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/screens.rpy", line 310, in <module>
    use quick_menu #xalign 0.0 yalign 0.5
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/display/screen.py", line 621, in use_screen
    screen.function(**scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/screenlang.py", line 1239, in __call__
    renpy.python.py_exec_bytecode(self.code.bytecode, locals=scope)
  File "/run/media/nait/nanika/mobile_programs/renpy-6.15.7-sdk/renpy/python.py", line 1382, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/screens.rpy", line 388, in <module>
    textbutton _("To Apartment") action [shortcutToApartment(), renpy.jump('endMeeting')]
[Recursion occurs]
RuntimeError: maximum recursion depth exceeded in cmp

Linux-3.13.8-1-ARCH-x86_64-with-glibc2.2.5
Ren'Py 6.17.6.512
I tried to abstract my code so the error is easier to find.
In a new game just with these modifications:

Code: Select all

screen quick_menu:

    # Add an in-game quick menu.
    hbox:
        style_group "quick"

        xalign 1.0
        yalign 1.0

        if location != 0:
            if location/10 == 1:
                textbutton _("To Map") action [shortcutToMap(), renpy.jump('endMeeting')]
            else:
                textbutton _("To Apartment") action [shortcutToApartment(), renpy.jump('endMeeting')]
        textbutton _("Back") action Rollback()
        textbutton _("Save") action ShowMenu('save')
        textbutton _("Q.Save") action QuickSave()
        textbutton _("Q.Load") action QuickLoad()
        textbutton _("Skip") action Skip()
        textbutton _("F.Skip") action Skip(fast=True, confirm=True)
        textbutton _("Auto") action Preference("auto-forward", "toggle")
        textbutton _("Prefs") action ShowMenu('preferences')

Code: Select all

init python:
    location = 1
    def shortcutToApartment():
        location = 10
    def shortcutToMap():
        location = 2

label start:

    "ets"
    
label endMeeting:
    
    "lol"
It won't even start really. I hit "Start Game" and the program freezes.

I have absolutely no idea where the recursion could occur. The buttons shouldn't even be activated before clicked. The original methods look like

Code: Select all

def shortcutToApartment():
        if random.randint(0,200) in [0,1]:
            location = iLocForest
            eForestVisited = True
            mLocationY = random.randint(len(mazeGrid[0]))
            mLocationX = random.randint(len(mazeGrid))
            renpy.scene()
            renpy.show("bg forest"+str(mBGIndex))
            narrator("You try to take a shortcut back to your apartment, but somehow end up in the woods.")
            Prota("What?!")
            narrator("Good luck, pal!")
        else:
            location = iLocOwnApartment
            floor = 3
            narrator("You take a shortcut back home.")
        return
        
    def shortcutToMap():
        if random.randint(0,200) in [0,1]:
            location = iLocForest
            eForestVisited = True
            mLocationY = random.randint(len(mazeGrid[0]))
            mLocationX = random.randint(len(mazeGrid))
            renpy.scene()
            renpy.show("bg forest"+str(mBGIndex))
            narrator("You try to take a shortcut, but somehow end up in the woods.")
            Prota("What?!")
            narrator("Good luck, pal!")
        else:
            location = -1
        return
Last edited by Ayutac on Mon Aug 18, 2014 4:47 am, edited 1 time in total.
Up next: An original, open source, text-based Dating Sim. Stay tuned ;)

Rietr
Newbie
Posts: 8
Joined: Sat Jun 28, 2014 1:15 pm
Contact:

Re: Conditional textbuttons in Quickmenu don't work

#2 Post by Rietr »

Hi!

I've been struggling with a (kind of ) similar problem, but the main point is you can't actually directly supply a function (or at least with arguments) to a text button.
Well, that sound a bit strange, but let me show you what I mean in simpler terms.

Code: Select all

 textbutton _("To Map") action [shortcutToMap(), renpy.jump('endMeeting')]
Let's take a look at this line, there are two problems here. The first one is shortcutToMap(), which should be shortcutToMap. Yes without the brackets. Otherwise the button thinks you pass an argument and it will keep refreshing. Something goes for renpy.jump('endMeeting'), you supply an argument here and that's why it's executed immediately.

So, how can we fix this? well for shotcutToMap it's easy, just remove the brackets. For the renpy.jump we can use curry.I've rewritten some of the code and got it working:

Code: Select all

screen quick_menu:

    # Add an in-game quick menu.
    hbox:
        style_group "quick"

        xalign 1.0
        yalign 1.0
        python:
            jumpy = renpy.curry(renpy.jump)
            if location != 0:
                if location/10 == 1:
                    ui.textbutton("To Map",clicked=[shortcutToApartment,jumpy("endMeeting")])
                else:
                    ui.textbutton("To Apartment",clicked=[shortcutToMap,jumpy("endMeeting")])
        textbutton _("Back") action Rollback()
        textbutton _("Save") action ShowMenu('save')
        textbutton _("Q.Save") action QuickSave()
        textbutton _("Q.Load") action QuickLoad()
        textbutton _("Skip") action Skip()
        textbutton _("F.Skip") action Skip(fast=True, confirm=True)
        textbutton _("Auto") action Preference("auto-forward", "toggle")
        textbutton _("Prefs") action ShowMenu('preferences')
I hope this helps!

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Conditional textbuttons in Quickmenu don't work

#3 Post by xela »

Ayutac wrote:I have absolutely no idea where the recursion could occur. The buttons shouldn't even be activated before clicked. The original methods look like
Because your functions are being evaluated every time the screen is refreshed. In fact, they are very likely to cause a redraw themselves so forcing Ren'Py into a recursive loop.

According to documentation:

You use Screen Actions or custom classes inheriting from Action.

Curry as suggested above will work too. You don't need to do that hack referencing a curried func btw:

Code: Select all

renpy.curry(renpy.jump)("label")
will work just fine, however:

Code: Select all

Jump("label")
will do the same thing, it's prettier + documented + suggested by Ren'Py developer(s).
Like what we're doing? Support us at:
Image

User avatar
Ayutac
Regular
Posts: 150
Joined: Thu Oct 18, 2012 2:23 pm
Projects: Pokémon Dating Sim
Organization: A Breeze Of Science
Deviantart: Ubro
Location: Mayence, Germany
Contact:

Re: Conditional textbuttons in Quickmenu don't work

#4 Post by Ayutac »

Ah, I understand.

My idea was that I just remembered that SetVariable or as above Jump work with arguments, so I thought it would do so with any method. I think I did my hardest to forget about curry, never used it so far and with Jump I won't do so any soon.

Thanks, you two!
Up next: An original, open source, text-based Dating Sim. Stay tuned ;)

User avatar
Ayutac
Regular
Posts: 150
Joined: Thu Oct 18, 2012 2:23 pm
Projects: Pokémon Dating Sim
Organization: A Breeze Of Science
Deviantart: Ubro
Location: Mayence, Germany
Contact:

Re: [Solved] Conditional textbuttons in Quickmenu don't work

#5 Post by Ayutac »

Protocol-Post:

I wrote a function like

Code: Select all

python:
    shortcutToApartment():
        narrator("You take a shortcut.")
        location = iLocOwnApartment
and added

Code: Select all

textbutton _("To Apartment") action [shortcutToApartment, Jump('worldReturn')]
in the appropriate menu, where in worldReturn the jump to the apartment will be done depending on variable location. This would at least not work because I'm "creating content within content" (it was an exception), I guess that means having dialog within a screen language command execution. I made a pleasent work-around by introducing a new variable shortcutUsed and changing the menu to

Code: Select all

textbutton _("To Apartment") action [SetVariable('shortcutUsed', True), Jump('apartment')]
with the first three lines of code in apartment being

Code: Select all

label apartment:
    if shortcutUsed:
        $ shortcutToApartmentUsed()
That works just as intended (the method name changed of course), although it's a bit messier in terms of code. But that won't bother many I guess.
Up next: An original, open source, text-based Dating Sim. Stay tuned ;)

Post Reply

Who is online

Users browsing this forum: No registered users