[SOLVED] marking previously made choices - but not persistent

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
nananame
Regular
Posts: 72
Joined: Fri Oct 13, 2017 1:40 pm
Contact:

[SOLVED] marking previously made choices - but not persistent

#1 Post by nananame »

You know how the choice screen has a chosen option? This somehow keeps persistent track of whether or not a choice was selected ever before in the playthrough.

My menus are looped so that when talking to one person you see the menu several times
example:

Code: Select all

menu person_a:
    "Really?":
        "Wow, really?"
    "What happened then?":
        "And then what happened?
    "Goodbye":
        "Goodbye!"
jump person_a
This is just an example but as you can imagine the chosen variable comes in handy here.
The problem is that this is a persistent value. So if I start a new game I will have the choices marked even though I didn't pick them in this playthrough.

Using the search method I found this:
apricotorange wrote: Tue Jul 02, 2013 2:41 am Put the following somewhere in your project, and the "chosen" boolean will work the way you want:

Code: Select all

init python:
    # Track which choices have been chosen
    chosen_choice_tracker = None

    # Action for menu which tracks the chosen choice.
    class NonPersistentChoice(Action):
        def __init__(self, label, value, location):
            self.label = label
            self.value = value
            self.location = location

        def __call__(self):
            chosen_choice_tracker[(self.location, self.label)] = True
            return self.value

    def menu(items):
        global chosen_choice_tracker
        if not chosen_choice_tracker:
            chosen_choice_tracker = {}
        # Get the name of the current statement
        # (This is not a public API, but I couldn't find an equivalent.)
        location = renpy.game.context().current
        # Build the list of items in the form the screen wants
        item_actions = [ ]
        for (label, value) in items:
            action = NonPersistentChoice(label, value, location)
            item_actions.append((label, action, (location, label) in chosen_choice_tracker))
        # Display the screen
        return renpy.call_screen("choice", items=item_actions)
And it seems the exact thing I need! However, it seems to be old and doesn't work out of the box anymore. Gives an error saying:

Code: Select all

TypeError: list indices must be integers, not ChoiceReturn
I tried inserting a counter and making value an integer and then it works, but causes problems if there are conditional statements in the menu.

So, any ideas on how this code could be made to run in the current version of Renpy or another way of achieving what I need?
Last edited by nananame on Sat May 16, 2020 5:39 am, edited 1 time in total.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: marking previously made choices - but not persistent

#2 Post by trooper6 »

How exactly are you coding this?

Also is your concern the variable being saved within a game (normal behavior) or carrying over into a new game (persistent behavior)?

Variables are not persistent by default. You have to define them that way. So...could you share some of your actual code?
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: marking previously made choices - but not persistent

#3 Post by hell_oh_world »

Code: Select all

default choices_made = []
screen choice(items):
    # some codes...
    button:
        action [ If(i not in choices_made, Function(choices_made.append, i)), i.action ] # append the choice made
        sensitive i not in choices_made # makes the button interactable if the choice is not made yet
    # some codes...
the above should work by tinkering the choice screen...
also note that there's a `set` statement for a `menu`, it will eliminate already picked choice, so everytime you loop back to that menu, all of the picked choices will be eliminated leaving the unpicked ones to the user...

Code: Select all

default menu_set = []
label start:
   menu:
       set menu_set
       "choice 1":
          jump start
       "choice 2":
           jump start

nananame
Regular
Posts: 72
Joined: Fri Oct 13, 2017 1:40 pm
Contact:

Re: marking previously made choices - but not persistent

#4 Post by nananame »

trooper6 wrote: Fri May 15, 2020 11:55 am How exactly are you coding this?

Also is your concern the variable being saved within a game (normal behavior) or carrying over into a new game (persistent behavior)?

Variables are not persistent by default. You have to define them that way. So...could you share some of your actual code?
the chosen is built in. You can take a new Renpy game, just adjust the chosen button in gui to look differently and try it. You can select it then quit and start a new game and it will be different in the new game too. It's built in as persistent.
hell_oh_world wrote: Fri May 15, 2020 12:18 pm

Code: Select all

default choices_made = []
screen choice(items):
    # some codes...
    button:
        action [ If(i not in choices_made, Function(choices_made.append, i)), i.action ] # append the choice made
        sensitive i not in choices_made # makes the button interactable if the choice is not made yet
    # some codes...
the above should work by tinkering the choice screen...
also note that there's a `set` statement for a `menu`, it will eliminate already picked choice, so everytime you loop back to that menu, all of the picked choices will be eliminated leaving the unpicked ones to the user...
I know about set, but I want the choises to still be there, just marked differently.
The other stuff looks like it could work! I'll give it a try later or tomorrow and let you know.

nananame
Regular
Posts: 72
Joined: Fri Oct 13, 2017 1:40 pm
Contact:

Re: marking previously made choices - but not persistent

#5 Post by nananame »

The code provided by @hell_oh_world doesn't work. For some reason "i" isn't recognized as the same. It keeps adding it to the list and when I print it this is the contents:
[(u'Goodbye',<renpy.ui.ChoiceReturn object at 0x092776C0>, True),(u'Goodbye',<renpy.ui.ChoiceReturn object at 0x0926EF30>, True)]

I tried adding i.caption to the list but, while that does work, it also affects other menus where there is a same choice (Like Hello or Goodbye).
I tried adding i.action and I get the same problem as just with i.
I tried adding i.action() but that returns integer values, so it affects a lot of choices....

I can't figure out the ui.ChoiceReturn object. If we could somehow get one imutable part of it in the list this method should work.
I checked https://www.renpy.org/doc/html/save_loa ... oiceReturn but I don't know how to get to those values....
Any ideas?

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: marking previously made choices - but not persistent

#6 Post by hell_oh_world »

checked that doc that you referred... why not use a property of that object? not sure if this would work *again*

Code: Select all

screen choice(items):
    # some codes...
    button:
        action [ If((i[1].location, i[1].value, i[1].label) not in choices_made, Function(choices_made.append, (i[1].location, i[1].value, i[1].label))), i.action ] # append the choice made
        sensitive (i[1].location, i[1].value, i[1].label) not in choices_made # makes the button interactable if the choice is not made yet
    # some codes...
in the example, I've used the `value` and `location` and `label` properties to make a unique id, hopefully that would work though...
Last edited by hell_oh_world on Sat May 16, 2020 8:33 am, edited 2 times in total.

User avatar
MaydohMaydoh
Regular
Posts: 165
Joined: Mon Jul 09, 2018 5:49 am
Projects: Fuwa Fuwa Panic
Tumblr: maydohmaydoh
Location: The Satellite of Love
Contact:

Re: marking previously made choices - but not persistent

#7 Post by MaydohMaydoh »

Code: Select all

default choice_tracker = []

init python:
    def menu(items):
        rv = renpy.display_menu(items)
        marker = ()
        for item_text, choice_obj in items:
           ## check if choice is not say and has been chosen
            if choice_obj and rv == choice_obj.value:
                marker = (choice_obj.location, choice_obj.value)
                ## add choice stuff to list
                if not marker in choice_tracker:
                    choice_tracker.append(marker)
        return rv
Records the chosen choice

Code: Select all

screen choice(items):
   #blah blah blah
   for i in items:
       textbutton i.caption action i.action:
           if i.action and (i.action.location, i.action.value) in choice_tracker:
               ## change button however you want.
Changes it if it's already been selected

nananame
Regular
Posts: 72
Joined: Fri Oct 13, 2017 1:40 pm
Contact:

Re: marking previously made choices - but not persistent

#8 Post by nananame »

Yup, this works!
Thank you!

That's actually what I was trying to do but idiot me kept accessing the properties wrong!

In case anyone is interested, this it the screen code in the end (I didn't make the chosen buttons insensitive, just different):

Code: Select all

        for i in items:
            textbutton i.caption:
                action If((i[1].location, i[1].value, i[1].label) not in choices_made, [Function(choices_made.append, (i[1].location, i[1].value, i[1].label)), i.action],i.action) ##this will add the choice to the list and perform the action
                if (i[1].location, i[1].value, i[1].label) in choices_made:###this will change the style of the button if it has already been chosen; make sure to define the style
                    style "choice_chosen_button"
                else:
                    style "choice_button"

Post Reply

Who is online

Users browsing this forum: Google [Bot], Kocker