Ren'Py More Help with Menuset

_13_

Active Member
Game Developer
Oct 8, 2020
799
2,679
Several of you were very helpful when I was previously having trouble using menuset. I thought everything was good. It seemed like everything was good. But players are having an issue when rolling back through the menu.
Some of them complain that if they rollback, the option they were in is no longer available. That's true, I can recreate this. Of course, it also makes sense, since they're still within the menuset, it hasn't been cleared. I'm not sure how to get it to clear, though. Rolling further than the start of the menu and then progressing back to it doesn't seem to clear the menuset. My initial thought is to just disable rollback for these menus, but I know that players (including myself) don't like that.

Others are getting an error.
You don't have permission to view the spoiler content. Log in or register now.
Script line 379 is the menu line "menu morning_menu2:" and 380 is "set menuset21" which sets the menuset. This only gives an error to some people and I haven't been able to recreate it. I really don't know what any of that means.

Is there, maybe, some easy fix for all of this? Is there a better way to do multiple choice menus than using menuset?

Help me F95 gurus, you're my only hope.
 

Zargon_games

Creating Games
Game Developer
Jan 22, 2020
703
3,474
You haven't posted your script code, so it's hard to know what the error is, but as a reference you should use something like this:

Code:
default chosen_menu_choices = []

label menustart:

    menu:

        set chosen_menu_choices

        "Lots of choices"

        "Choice 1":
            # do something
            jump menustart

        "Choice 2"          
            # do something
            jump menustart

        "Choice 3":
            # do something
            jump menustart

        "Choice 4":
            # do something
            jump menustart

        "Choice 5":
            # do something
            jump menustart
 
  • Like
Reactions: _13_

_13_

Active Member
Game Developer
Oct 8, 2020
799
2,679
Well, that's not much different than using menuset. So what's the difference? If the chosen_menu_choices lets players scroll back and forth, it must be superior... at least for this usage.

Code:
default menuset1 = set()

menu menu1:
    set menuset1
    "It's a menu"
    "Choice 1":
        #do something
        jump menu1
    "Choice 2":
        #do something
        jump menu1
    "Choice 3":
        #do something
        jump menu1
 

_13_

Active Member
Game Developer
Oct 8, 2020
799
2,679
Now I see a Ren'Py example where they use:
# This variable is used to save the choices that have been made in
# the main menu.
$ seen_set = [ ]

# The set menu clause ensures that each menu choice can only
# be chosen once.
set seen_set


So, is it just the set function and then you can call it whatever you want?
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
So, is it just the set function and then you can call it whatever you want?

Not quite.

The menu: statement does slightly different things when you include a set option. It adds the text of the menu option to the specified . If the value is already within the list when the menu is shown, that menu option is hidden.

So.

Python:
label start:

    scene black with fade


label do_the_menu:

    $ my_menu_var = set()


label repeat_the_menu:

    menu:
        set my_menu_var

        "Option 1":
            "Option 1 was picked."
            jump repeat_the_menu

        "Option 2":
            "Option 2 was picked."
            jump repeat_the_menu

        "Option 3":
            "Option 3 was picked."
            jump repeat_the_menu
       
    "Menu has been completed."

    return

Is exactly the same as:

Python:
label start:

    scene black with fade


label do_the_menu:

    $ my_menu_var = set()


label repeat_the_menu:

    menu:

        "Option 1"  if "Option 1" not in my_menu_var:
            "Option 1 was picked."
            $ my_menu_var.add("Option 1")
            jump repeat_the_menu

        "Option 2"  if "Option 2" not in my_menu_var:
            "Option 2 was picked."
            $ my_menu_var.add("Option 2")
            jump repeat_the_menu

        "Option 3"  if "Option 3" not in my_menu_var:
            "Option 3 was picked."
            $ my_menu_var.add("Option 3")
            jump repeat_the_menu

    "Menu has been completed."

    return

Obviously using set is just a shortcut to stop you needing to type in all that extra crap.

This is one of the few occasions where I would NOT recommend using default to initialize the list variable used. It's very important that it be emptied IMMEDIATELY before the menu is first invoked, but not emptied each time the player returns to the menu having picked an option. It's why I initialize the variable immediately before the label used by the menu: in my example.

But regardless of that, players should not have issues with rollback. Rollback resets variables to their previous values if they have been changed. So even though the menu:/set has added values to the list variable - those values will be removed again when RenPy does a rollback through that section of code. It's kinda the whole point of rollback.
 
Last edited:
  • Like
Reactions: _13_ and LightmanP

LightmanP

Well-Known Member
Modder
Game Developer
Oct 5, 2020
1,671
15,504
Well, that's not much different than using menuset. So what's the difference? If the chosen_menu_choices lets players scroll back and forth, it must be superior... at least for this usage.

Code:
default menuset1 = set()

menu menu1:
    set menuset1
    "It's a menu"
    "Choice 1":
        #do something
        jump menu1
    "Choice 2":
        #do something
        jump menu1
    "Choice 3":
        #do something
        jump menu1
I think this example and what Zargon_games shown is all menuset, just one uses set() and the other uses a list.
As for your issue, I've tested it on a clean Ren'Py build and rollback seems to work fine with menuset, options chosen previously were available after rolling back. I've used default menuset1 = set() in the testing, btw.

However, I did notice the issue in your game and it seems that menuset entries are not clearing during rollback. 79flavors' suggestion of initializing menuset right before the menu does work, though, I've tried that for one of your menus and all the options were showing up after the rollback.
 
  • Like
Reactions: _13_ and 79flavors

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
And yeah. You can swap out $ my_menu_var = [] for $ my_menu_var = set().
It's technically more correct than me using a rather than a .

Updated my original example to reflect that.

I've re-tested rollback with both initializing using default and just before the menu itself. Both work fine with 7.3.5 and 7.4.8 using this very simple example. 7.4.8 is currently the latest release of RenPy.
This is one of those "there are subtleties that matter" discussions that I avoid by just going with the "reset the variable right before the menu that uses it" solution. Because doing it this way will always work, rather than almost always (assuming it's coded correctly).
 
Last edited:
  • Like
Reactions: _13_ and LightmanP

_13_

Active Member
Game Developer
Oct 8, 2020
799
2,679
Not quite.

The menu: statement does slightly different things when you include a set option. It adds the text of the menu option to the specified . If the value is already within the list when the menu is shown, that menu option is hidden.

So.

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


Obviously using set is just a shortcut to stop you needing to type in all that extra crap.

This is one of the few occasions where I would NOT recommend using default to initialize the list variable used. It's very important that it be emptied IMMEDIATELY before the menu is first invoked, but not emptied each time the player returns to the menu having picked an option. It's why I initialize the variable immediately before the label used by the menu: in my example.

But regardless of that, players should not have issues with rollback. Rollback resets variables to their previous values if they have been changed. So even though the menu:/set has added values to the list variable - those values will be removed again when RenPy does a rollback through that section of code. It's kinda the whole point of rollback.
In both of your examples, you have two labels before menu:, is that a style choice or is that good coding? I don't normally use many labels and instead name my menus. Does that make a difference?
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
In both of your examples, you have two labels before menu:, is that a style choice or is that good coding? I don't normally use many labels and instead name my menus. Does that make a difference?

It's merely to add emphasis that the $ my_menu_var = set() is separate but also immediately before. It can be considered entirely cosmetic most of the time.
I also tend to use labels rather than naming menu: statement to make it easier to search the code when updating later. But that is a personal choice and both methods of using labels and naming the menu will work equally way.

It was also to highlight that having the $ my_menu_var = set() within the label repeat_the_menu: would break the way it works.

But this would be equally valid:

Python:
label start:

    scene black with fade

    $ my_menu_var = set()

    menu repeat_the_menu:
        set my_menu_var

        "Option 1":
            "Option 1 was picked."
            jump repeat_the_menu

        "Option 2":
            "Option 2 was picked."
            jump repeat_the_menu

        "Option 3":
            "Option 3 was picked."
            jump repeat_the_menu
    
    "Menu has been completed."

    return
 
  • Like
Reactions: _13_

_13_

Active Member
Game Developer
Oct 8, 2020
799
2,679
Thanks to all three of you! I seem to have it working correctly now.
 
  • Like
Reactions: LightmanP