Can I use "call" for multiple menu choices?

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
Razka
Newbie
Posts: 12
Joined: Wed Jan 01, 2020 10:58 pm
Projects: Testament Legacy - Ch.1
Contact:

Can I use "call" for multiple menu choices?

#1 Post by Razka »

This question is actually two questions:

First, let's say I have the following menu:

Code: Select all

menu:
        "I have the rest of the day before leaving."

        "See what Lens is up to.":
            "wip"
            jump lensAffection_1

        "Let's meet up with Nikki." if nikkiAffection == 1:
            "wip"
            jump nikkiAffection_2

        "Go shop.":
            "Let's see what Morgue has in stock today."
            jump bunker_shop1
I would like to have more control in the flow of this menu: for example, the player should be able to go shop and jump to EITHER lensAffection_1 OR nikkiAffection_2, but not both.
I'm guessing that "call" would be the right solution but I'm not sure how to put it together.
And on a related note, would that be possible, in a shop menu like this one:

Code: Select all

    menu:
        "Should I buy something?"

        "Bioscanning Mod (5000 C)":
            $radarMod = True
            $credits -= 5000;
            "No one will surprise me."

        "Personal Shield Mod (4000 C)":
            $personalShieldMod = True
            $credits -= 4000;
            "One day, it might just make the difference between life and death."

        "Leave":
            "Better save up for now."
How should you code it to be able to buy both items? I was thinking about nesting menus but there are way more than 2 items, and that would result in a lot of repetitions.
Thank you for your insight, I hope I explained myself well.

philat
Eileen-Class Veteran
Posts: 1910
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Can I use "call" for multiple menu choices?

#2 Post by philat »

You can use conditions and jumping back to the menu. You can use the same principles as below for the other one.

Code: Select all

    menu shop: # name the menu like a label
        "Should I buy something?"

        "Bioscanning Mod (5000 C)" if not radarMod:
            $radarMod = True
            $credits -= 5000;
            "No one will surprise me."

        "Personal Shield Mod (4000 C)" if not personalShieldMod:
            $personalShieldMod = True
            $credits -= 4000;
            "One day, it might just make the difference between life and death."

        "Leave":
            "Better save up for now."
            jump after_shop

    jump shop # menu falls through to here after selecting either bioscanning or personal shield

label after_shop:
    "Jumps here after leaving."

User avatar
Razka
Newbie
Posts: 12
Joined: Wed Jan 01, 2020 10:58 pm
Projects: Testament Legacy - Ch.1
Contact:

Re: Can I use "call" for multiple menu choices?

#3 Post by Razka »

Thanks, I didn't realise you can assign an id to a menu. This really solved a lot of problems I encountered.
The first menu was harder, because affection is an integer and not a boolean and it's not good as a condition. Player must choose only one of those 2, and the shop everytime he wants.

I did it this way, but I really don't like it.
I know it's redundant to put both a check on the click and on the choicescounter, but this is oversimplified: there will be menus with 5+ choices, where you need to select max 3, and you obviously are not allowed to click multiple times the same one.

But then again, I don't like having all these variables. I didn't write in all the code, but as soon as it jumps on the main label, the game resets the variables for future use. So it's something I guess.
Is there some other way to make it better?

Code: Select all

    define lensClicked = False
    define nikkiClicked = False
    define choicesCounter = 0


    menu menu_freetime_bunker1:
        "I have the rest of the day before leaving."

        "See what Lens is up to." if not lensClicked and choicesCounter == 0:
            "xxx"
            jump lensAffection_1

        "Let's meet up with Nikki." if nikkiAffection == 1 and not lensClicked and choicesCounter == 0:
            "xxx"
            jump nikkiAffection_2

        "Go shop.":
            "Let's see what Morgue has in stock today."
            jump bunker_shop1

        "Go home and get ready to depart.":
            "xxx"
            jump roadToStormguard




label lensAffection_1:

    $choicesCounter += 1
    $lensClicked = True

jump menu_freetime_bunker1

label nikkiAffection_2:

    $choicesCounter += 1
    $nikkiClicked = True

jump menu_freetime_bunker1

strayerror
Regular
Posts: 159
Joined: Fri Jan 04, 2019 3:44 pm
Contact:

Re: Can I use "call" for multiple menu choices?

#4 Post by strayerror »

You could do something like this, which uses variables to denote which characters are unlocked (i.e. lens_unlocked) and then a set to keep track of what's been clicked this time around, this might allow use of a single menu that can be reused throughout the game as more characters are unlocked, or timeslots are available etc. Haven't had a chance to sanity test this, so ymmv, but hopefully it's of some help. :)

Code: Select all

label bunker_day:
    # start of day stuff
    call freetime_bunker(2) # limit to two interactions besides shop and continue
    jump roadToStormguard # continue

label freetime_bunker(limit):
    $ renpy.dynamic('chosen') # don't leak chosen out into the rest of the game
    $ chosen = set() # initialise it as an empty set

    menu .choice:
        'I have the rest of the day before leaving.'

        'Lens.' if lens_unlocked and len(chosen) < limit and 'lens' not in chosen:
            $ chosen.add('lens')
            'xxx'

        'Nikki.' if nikki_unlocked and len(chosen) < limit  and 'nikki' not in chosen:
            $ chosen.add('nikki')
            'xxx'

        'Sam.' if sam_unlocked and len(chosen) < limit  and 'sam' not in chosen:
            $ chosen.add('sam')
            'xxx'

        'Max.' if max_unlocked and len(chosen) < limit  and 'max' not in chosen:
            $ chosen.add('max')
            'xxx'

        'Go shop.':
            'Let's see what Morgue has in stock today.'
            jump bunker_shop1

        'Go home and get ready to depart.':
            'xxx'
            return # exit menu loop

    jump .choice # loop back to choices

philat
Eileen-Class Veteran
Posts: 1910
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Can I use "call" for multiple menu choices?

#5 Post by philat »

You can also consider using the (undocumented) set feature. viewtopic.php?f=8&t=51971&p=496464#p496453

User avatar
IrinaLazareva
Veteran
Posts: 399
Joined: Wed Jun 08, 2016 1:49 pm
Projects: Legacy
Organization: SunShI
Location: St.Petersburg, Russia
Contact:

Re: Can I use "call" for multiple menu choices?

#6 Post by IrinaLazareva »

philat wrote: Fri Jan 03, 2020 4:16 am You can also consider using the (undocumented) set feature.
By the way, this feature has now been documented
https://renpy.org/doc/html/menus.html#menu-set

philat
Eileen-Class Veteran
Posts: 1910
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Can I use "call" for multiple menu choices?

#7 Post by philat »

Ah! Good to know.

User avatar
Razka
Newbie
Posts: 12
Joined: Wed Jan 01, 2020 10:58 pm
Projects: Testament Legacy - Ch.1
Contact:

Re: Can I use "call" for multiple menu choices?

#8 Post by Razka »

strayerror wrote: Thu Jan 02, 2020 11:31 pm You could do something like this, which uses variables to denote which characters are unlocked (i.e. lens_unlocked) and then a set to keep track of what's been clicked this time around, this might allow use of a single menu that can be reused throughout the game as more characters are unlocked, or timeslots are available etc. Haven't had a chance to sanity test this, so ymmv, but hopefully it's of some help. :)

Code: Select all

label bunker_day:
    # start of day stuff
    call freetime_bunker(2) # limit to two interactions besides shop and continue
    jump roadToStormguard # continue

label freetime_bunker(limit):
    $ renpy.dynamic('chosen') # don't leak chosen out into the rest of the game
    $ chosen = set() # initialise it as an empty set

    menu .choice:
        'I have the rest of the day before leaving.'

        'Lens.' if lens_unlocked and len(chosen) < limit and 'lens' not in chosen:
            $ chosen.add('lens')
            'xxx'

        'Nikki.' if nikki_unlocked and len(chosen) < limit  and 'nikki' not in chosen:
            $ chosen.add('nikki')
            'xxx'

        'Sam.' if sam_unlocked and len(chosen) < limit  and 'sam' not in chosen:
            $ chosen.add('sam')
            'xxx'

        'Max.' if max_unlocked and len(chosen) < limit  and 'max' not in chosen:
            $ chosen.add('max')
            'xxx'

        'Go shop.':
            'Let's see what Morgue has in stock today.'
            jump bunker_shop1

        'Go home and get ready to depart.':
            'xxx'
            return # exit menu loop

    jump .choice # loop back to choices
This is super helpful!
I don't think I'll have one single shop for every occasion because they'll be different based on the player location, but the call with limiter argument and the "chosen" collection are more than enough to code it cleanly.
I'll be implementing in the next few days (I'm in the middle of several scenes to write) but I'm pretty confident about this.
Thank you and for the "set" feature tip as well.

User avatar
IrinaLazareva
Veteran
Posts: 399
Joined: Wed Jun 08, 2016 1:49 pm
Projects: Legacy
Organization: SunShI
Location: St.Petersburg, Russia
Contact:

Re: Can I use "call" for multiple menu choices?

#9 Post by IrinaLazareva »

philat wrote: Fri Jan 03, 2020 2:32 pm Ah! Good to know.
Hmm, Maybe this feature was documented in vain...
I was just thinking. It has a significant disadvantage. Set() creates many values with unique names that cannot be repeated. That is, this feature cannot be used in menus if the menu has the same answer choices.
Here is an example to demonstrate the problem. If you select a recurring ("wrong") option, they will all disappear on the next "lap".

Code: Select all

default unsw = set()
label start:
    '!'
    menu places:
        set unsw
        'Choose...'
        "Wrong":
            jump places
        "Wrong":
            jump places
        "Right":
            jump places
        "Wrong":
            jump places
        "Wrong":
            jump places          
    '??????'
    return
On the other hand, this feature can be turned to its advantage (sometimes a similar effect is also necessary).
In the end, we can just adding an extra space to the end of the option name :)

philat
Eileen-Class Veteran
Posts: 1910
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Can I use "call" for multiple menu choices?

#10 Post by philat »

Normally you don't have two options with the same text anyway so I don't see why that would be an issue (assuming that you use different sets for each menu, I guess), but the main disadvantage of set is that you can't use it if you want a 'sticky' option -- i.e., if you had something like "Leave" for all menus or if you wanted someone to be able to shop multiple times. In that case you have to roll your own solution, which is unfortunate. Would be neat if there were a way to designate options that should be once-only vs. always there (ink, for examples, uses * / + to denote that), but eh. Rolling your own is also not super complicated, tbh.

User avatar
IrinaLazareva
Veteran
Posts: 399
Joined: Wed Jun 08, 2016 1:49 pm
Projects: Legacy
Organization: SunShI
Location: St.Petersburg, Russia
Contact:

Re: Can I use "call" for multiple menu choices?

#11 Post by IrinaLazareva »

I agree.
I just wanted to mark an interesting psychological moment. When a function is not prescribed in the documentation, but you know about it, it becomes a pleasant feature (which doesn't show any flaws in it). But as soon as the function becomes documented, you start to make some demands to it at once (you notice its disadvantages, you want to improve it, etc.).

User avatar
Showsni
Miko-Class Veteran
Posts: 563
Joined: Tue Jul 24, 2007 12:58 pm
Contact:

Re: Can I use "call" for multiple menu choices?

#12 Post by Showsni »

philat wrote: Sun Jan 05, 2020 8:54 pm Normally you don't have two options with the same text anyway so I don't see why that would be an issue (assuming that you use different sets for each menu, I guess), but the main disadvantage of set is that you can't use it if you want a 'sticky' option -- i.e., if you had something like "Leave" for all menus or if you wanted someone to be able to shop multiple times. In that case you have to roll your own solution, which is unfortunate. Would be neat if there were a way to designate options that should be once-only vs. always there (ink, for examples, uses * / + to denote that), but eh. Rolling your own is also not super complicated, tbh.
If you want an option to remain, you just have to remove it from the set again.

Code: Select all

menu chapter_1_places:

    set menuset
    "Where should I go?"

    "Go to class.":
        jump go_to_class

    "Go to the bar.":
        jump go_to_bar

    "Go home.":
        $ menuset.remove("Go home.")
        jump go_home

label chapter_1_after_places:

    "Wow, that was one heck of a Tuesday."
You can also add things to the set so they don't show up.

Post Reply

Who is online

Users browsing this forum: No registered users