Ren'Py Boolean not keeping his value when scrolling back

dogcatbfg9000

DogCat
Game Developer
Jul 30, 2022
49
349
Hi,

I have an issue when I want to assign a boolean with the value True after a certain line of code in a script. When I roll back to the previous scene/s (with the back button of the mouse wheel), the boolean loses its True value and returns to False.
I initialize the boolean at the beginning of the game or the scene with the value False and change it along the way.

Is there a way to keep this value even if the player wants to return to the previous scene/s to change his decisions?
I only want this logic on a single playthrough, so I can't use the persistent here.

Is there a way to do that?

init.rpy
Python:
label init_game_values:
    default some_boolean = False
scene.rpy
Python:
label some_label:
    scene some_scene1 with dissolve
    mc "some blah blah 1"
    scene some_scene2 with dissolve
    mc "some blah blah 2"
    $ some_booelan = True
    scene some_scene2 with dissolve
    mc "some blah blah 3"


Thank you,
DogCat
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,960
16,195
use define, not default.
No, here it wouldn't make a difference. It's only with structures (list, dict and obvious object) that it would make a difference. But here he's using a scalar-like variable, therefore it will be full part of the rollback feature, and also switched to savable the instant its value will be changed for the first time.


As for OP's question:
I have an issue when I want to assign a boolean with the value True after a certain line of code in a script. When I roll back to the previous scene/s (with the back button of the mouse wheel), the boolean loses its True value and returns to False.
You effectively have an issue, Ren'Py is behaving exactly like it is expected, both by the developers and by the players, to behave, while you want to make it behave like it didn't had a rollback feature.
But the issue isn't due to Ren'Py, it's due to your intent.


All this being said, Winterfire was half right, the solution is in the use of define, but indirectly.
Instead of using standalone Booleans, you need to have them hosted by a generic object that you create with define, for them to fall outside of the rollback scope.

But this will annoy the players, lead to some code issue, and of course the value you defined will be lost because it will never be part of the save/load process.
 

dogcatbfg9000

DogCat
Game Developer
Jul 30, 2022
49
349
Thank you both for the answers.

You effectively have an issue, Ren'Py is behaving exactly like it is expected, both by the developers and by the players, to behave, while you want to make it behave like it didn't had a rollback feature.
But the issue isn't due to Ren'Py, it's due to your intent.
I imagined that this was the behavior of Renpy but I wasn't sure. Thank you for clarifying that. This is valuable information for me.

But this will annoy the players, lead to some code issue, and of course the value you defined will be lost because it will never be part of the save/load process.
I have no intention of annoying the players. What I want will not affect the gameplay, decisions, or history. I only need to show something on the screen when it is already shown. That's it. I am happy to hear a better solution of course. That's why I'm here in the first place :)

Having said that, I removed this boolean because now I found a better way to implement what I need.

Thank you,
DogCat.
 

lobotomist

Active Member
Sep 4, 2017
907
879
Thank you both for the answers.


I imagined that this was the behavior of Renpy but I wasn't sure. Thank you for clarifying that. This is valuable information for me.


I have no intention of annoying the players. What I want will not affect the gameplay, decisions, or history. I only need to show something on the screen when it is already shown. That's it. I am happy to hear a better solution of course. That's why I'm here in the first place :)

Having said that, I removed this boolean because now I found a better way to implement what I need.

Thank you,
DogCat.
sounds to me like you are confused on what you want think you need to do, it might be better to clarify what exactly you need to happen (as in the desired effect), and maybe you may get a suggestion for something completely different to what you imagined that has the same result.
 

lobotomist

Active Member
Sep 4, 2017
907
879
sounds to me like you are confused on what you want think you need to do, it might be better to clarify what exactly you need to happen (as in the desired effect), and maybe you may get a suggestion for something completely different to what you imagined but ends up producing the same result.
 

dogcatbfg9000

DogCat
Game Developer
Jul 30, 2022
49
349
sounds to me like you are confused on what you want think you need to do, it might be better to clarify what exactly you need to happen (as in the desired effect), and maybe you may get a suggestion for something completely different to what you imagined that has the same result.
That's a good suggestion. Let me give it a try.
I want to make a screen appear only once in a play-through after a certain point in the game. It's like a notification.
If this screen/notification already appeared. Then I don't want it to appear again if the player is rolling back.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,960
16,195
I want to make a screen appear only once in a play-through after a certain point in the game. It's like a notification.
If this screen/notification already appeared. Then I don't want it to appear again if the player is rolling back.
Then the define approach with a generic object is the answer. Something like:

Python:
init python:
    class BoolFlags( object ):
        def __init__( self ):
            self.whatever = False

define myFlags = BoolFlags()

label whatever:
    if not myFlags.whatever:
        [whatever]
        $ myFlags.whatever = True
    [...]
[/quote]

The [icode]True[/icode] value will be kept as long as the player do not close Ren'Py, and will return at [icode]False[/icode] when he'll launch it (Ren'Py) again.
 
  • Like
Reactions: dogcatbfg9000

Deleted member 2282952

Developing I SCREAM
Game Developer
May 1, 2020
416
870
Wow, the solutions here are kinda over-engineered (no offense), just use save states.

Code:
$ current_value_x = value_x
if current_value_x != value_x:
   $ value_x = current_value_x
Works perfectly fine for my game
 
  • Like
Reactions: dogcatbfg9000

dogcatbfg9000

DogCat
Game Developer
Jul 30, 2022
49
349
Wow, the solutions here are kinda over-engineered (no offense), just use save states.

Code:
$ current_value_x = value_x
if current_value_x != value_x:
   $ value_x = current_value_x
Works perfectly fine for my game
Thank you
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,607
2,256
My gut feel here is that you're trying to fix something that isn't broken.

The mechanism you are describing... rollback... is working as intended (and therefore behaves how players will expect).

Python:
default my_flag = False

label start:

   scene black with fade
   "*** START ***"

   "Dialogue #1"
   "Dialogue #2"

   $ my_flag = True

   "Dialogue #3"
   "Dialogue #4"

   "*** THE END ***"
   return

Your complaint seems to be that if the player reaches #3 or #4, then rollbacks to to #2 or #1 - then the value of my_flag reverts to being False. That's exactly what rollback is intended to do. When the player encountered #1 and #2, the value was False, if the player chooses to return to that moment, then the state of the game (in 99% of cases) will return to the same state as when originally shown.

Imagine a bit of code like:

Python:
     "Dialogue#4"

     menu:
           "Kiss her":
                 $ love_points += 1
                 "You kiss her."

           "Don't kiss her":
                 pass

     "Dialogue #5"

Now imagine that RenPy was rolling back without affecting the values of variables.
A player would need only keep picking "Kiss her", rollback to #4, "Kiss her" again... rinse and repeat a dozen times and your game is broken, with the player accumulating dozens if not hundreds of love points simply by using rollback.

Instead, RenPy reverts values to match their original value and things work as intended.

Or put another way. You want to show a special action once. If a player rollsback, then they are rolling back to a point before that special action happened and therefore it SHOULD be shown again... because as far as the game is concerned, it hasn't happened yet. That's the normal behavior of all RenPy games, and therefore what players will expect. Realistically, the vast majority of players aren't going to rollback through your special action... and if they do... you should let them.

As an aside, you have code that reads:

Python:
label init_game_values:
    default some_boolean = False

default statements do not require a label line.
If you ever did jump init_game_values, the values would NOT change to their default values.
default statements are effectively processed during the games startup process. The script files are scanned, looking for statements like default and they are processed before the game even starts. They are ignored while the game is running.

For example:

Python:
label start:

    "*** START ***"

    $ myvar1 += 1
    "value is [myvar1]."

    default myvar1 = 5

    "new value is [myvar1]."

    "*** THE END ***"

Will display 6 and 6, not 6 and 5.

default is the correct way to set up variables - but the label statement made me think there was the possibility that you expected it to work in the same way as $ some_boolean = False. The label statement doesn't affect anything, it just doesn't do anything either.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,960
16,195
Wow, the solutions here are kinda over-engineered (no offense), just use save states.

Code:
$ current_value_x = value_x
if current_value_x != value_x:
   $ value_x = current_value_x
Works perfectly fine for my game
Hmmm, I must be missing something, because this code really don't looks like answering the question.

When the first assignation to current_value_x happen, the variable will be saved, same for value_x.
Therefore, at really short terms the two variables will synchronize. And starting this instant the intent (showing something just once by play session) will be defeated.

Even a three way step:
Python:
if current_value_x == value_x:
    pass
else:
    show something
    current_value_x = value_x
    value_x = not value_x
wouldn't answer the issue. It would just show the content every other time.


More globally, the instant the value is saved, it don't address the question. For the next play session, it's the saved value that will be used, while the used value should be a fresh one.