[Solved]Re-launching re-initializes persistent data?

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.
Message
Author
rimir
Regular
Posts: 52
Joined: Mon Jul 06, 2009 12:30 pm
Projects: Only test projects
Contact:

[Solved]Re-launching re-initializes persistent data?

#1 Post by rimir »

My novel is still in the WIP stage...

Whenever I launch the game to check if the code's working properly I find that all the persistent variables have been reset...is this what is supposed to happen? should I use MultiPersistent objects for retaining values from previous play-throughs?

Also, is there any way to change the main menu after a certain point in the game without re-launching it?

TIA :)
Last edited by rimir on Thu Oct 01, 2009 7:22 am, edited 1 time in total.

User avatar
Aleema
Lemma-Class Veteran
Posts: 2677
Joined: Fri May 23, 2008 2:11 pm
Organization: happyB
Tumblr: happybackwards
Contact:

Re: Re-launching re-initializes persistent data?

#2 Post by Aleema »

Persistent data does not reset when you re-launch, because that's the whole point of it. You're either deleting it yourself (by deleting saved games), or not assigning the variables properly. You can post your code here so that we can check.

As for the main menu, I haven't tried it myself, but if you make a custom menu screen with a label (not just the imagemap code), you could theoretically split it into two different menus using an if statement. Since it's not in the init code, could work. :)

Code: Select all

label main_menu:
     if not turnedevil:
           #Your menu code#
     else:
           #Your alternate menu code#

Counter Arts
Miko-Class Veteran
Posts: 649
Joined: Fri Dec 16, 2005 5:21 pm
Completed: Fading Hearts, Infinite Game Works
Projects: Don't Save the World
Organization: Sakura River
Location: Canada
Contact:

Re: Re-launching re-initializes persistent data?

#3 Post by Counter Arts »

You shouldn't be changing persistent data in an init block if that's what you are doing.

For the second question, remember that for the tuples in the config.main_menu stuff is made of three parts. The last one determines if it is actually shown or not. Look it up in the documentation.
Fading Hearts is RELEASED
http://www.sakurariver.ca

rimir
Regular
Posts: 52
Joined: Mon Jul 06, 2009 12:30 pm
Projects: Only test projects
Contact:

Re: Re-launching re-initializes persistent data?

#4 Post by rimir »

Counter Arts wrote:You shouldn't be changing persistent data in an init block if that's what you are doing.
I only declared them in an init block...or am I supposed to declare persistent variables outside any blocks?

My code...
options.rpy

Code: Select all

##

init -2 python hide :
    config.developer="True"
      
    config.screen_width = 800
    config.screen_height = 600
    
    # Layouts
    layout.imagemap_main_menu("main_menu2.jpg" ,
                                            "main_menu3.jpg" ,[ 
                                            (315,360,460,400,"_continue"),
                                            (315,401, 460, 433, "Start Game"),
                                            (315,434,460,470,"load"),
                                            (315,471,460,505,"preferences"),
                                            (315,506,460,540,"gallery"),
                                            (315,541,460,580,"quit")])  
                                            if (persistent.cleared >  0) else layout.imagemap_main_menu(
                                                                                "main_menu4.jpg",

                                                                                "main_menu5.jpg",[ 

                                                                                (315,401, 460, 433, "Start Game"),
                                                                                                                                                                                                              (315,434,460,470,"load"),
                                                                                                                                                                                                              (315,471,460,505,"preferences"),
                                                                                                                                                                                                              (315,506,460,540,"gallery"),
                                                                                                                                                                                                              (315,541,460,580,"quit")])
    

    layout.classic_yesno_prompt()
    layout.classic_navigation()
    layout.classic_load_save()
    
label quit :
   $ renpy.quit()
   
label _continue :
      if persistent.cleared == 0 :
         $ persistent.cleared = 1
      if persistent.cleared == 1 :
         $ ui.imagemap("start1_menu.bmp","start1_hovered_menu.bmp",[(170,370,630,415,"A"),(170,200,630,255,"B")]) 
      elif persistent.cleared == 2 :
           $ ui.imagemap("start2_menu.bmp","start2_hovered_menu.bmp",[(170,435,630,480,"A"),(170,280,630,325,"B"),(170,100,630,150,"C")])
      else :
           $ ui.imagemap("start3_menu.bmp","start3_hovered_menu.bmp",[(250,96,550,126,"A"),(250,222,550,252,"B"),(250,348,550,378,"C"),(250,440,550,500,"Credits")])
      $ result =ui.interact()
      if result == "A" :
          jump A
      elif result == "B" :
             jump B
      elif result == "C" :
             jump C         
       
label load :
    pass
   

script.rpy

Code: Select all

# You can place the script of your game in this file.

init :
    # Declare images below this line, using the image statement.
    # eg. image eileen happy = "eileen_happy.png"

    # Declare characters used by this game.
    $ persistent.cleared = 0 
    $ e = Character('Eileen', color="#c8ffc8")
    


# The game starts here.
label start :

    e "You've created a new Ren'Py game."

    e "Once you add a story, pictures, and music, you can release it to the world!"
    jump A
    
label A :
     e"This is the placeholder for the First Arc."
     if persistent.cleared == 0 :
        $ persistent.cleared += 1
     e"reached here "
     jump return_to_mm
        
label B :
    e"This is the placeholder for the Second Arc."
    if persistent.cleared == 1 :
       $ persistent.cleared +=1
    jump return_to_mm
       
label C :
    e"This is the placeholder for the Third Arc."
    if persistent.cleared == 2 :
       $ persistent.cleared += 1
    jump return_to_mm
    
label Credits :
    e"This is the placeholder for the credits."
    jump return_to_mm
       
label help :
    e"This is the placeholder for the help system ."
    jump return_to_mm
    
label return_to_mm :
    pass
    
The indentation got messed up a little while pasting but lint shows no errors.

Counter Arts
Miko-Class Veteran
Posts: 649
Joined: Fri Dec 16, 2005 5:21 pm
Completed: Fading Hearts, Infinite Game Works
Projects: Don't Save the World
Organization: Sakura River
Location: Canada
Contact:

Re: Re-launching re-initializes persistent data?

#5 Post by Counter Arts »

Everytime you start up or reload the game, all init blocks are re-run. That's why it should not be declared or changed in an init block.

There's only a very specific case when you should and for most people in this form you won't need it.
Fading Hearts is RELEASED
http://www.sakurariver.ca

rimir
Regular
Posts: 52
Joined: Mon Jul 06, 2009 12:30 pm
Projects: Only test projects
Contact:

Re: Re-launching re-initializes persistent data?

#6 Post by rimir »

Thanks. It's solved now. Declared them outside any blocks.

EDIT : Oh no! wait! It doesn't show the second imagemap for the main menu on re-launching now.Why?
Last edited by rimir on Thu Sep 24, 2009 12:29 pm, edited 1 time in total.

delta
Epitome of Generic
Posts: 525
Joined: Sat Dec 22, 2007 12:59 pm
Projects: yes
Contact:

Re: Re-launching re-initializes persistent data?

#7 Post by delta »

Wrong, you can do whatever you want with persistent data in init. Of course, it's probably pointless if you don't do it conditionally, but that doesn't mean you can't do it. In fact, it's sometimes a good idea to initialize persistent variables in init if they don't yet exist because some things won't work with variables that don't exist. Try incrementing an unset persistent integer:

Code: Select all

label start:
    $ persistent.doesnotexist += 1
will crash.

Code: Select all

init python:
    if not persistent.doesnotexist:
        persistent.doesnotexist = 0

label start:
    $ persistent.doesnotexist += 1
will work. This is especially insidious because the first example will always work if the persistent variable was ever set on your project, even if the code that sets it is normally not executed before anymore or no longer even exists. On a fresh installation elsewhere, this might not be he case, and it will crash. That is why I always conditionally initialize all persistent variables I use during init.

In fact, I think this is the source of rimir's problem. You're testing whether your persistent variable is 0, but an unset persistent variable is not 0, it's None.
The rest is left as an exercise for the reader.

Counter Arts
Miko-Class Veteran
Posts: 649
Joined: Fri Dec 16, 2005 5:21 pm
Completed: Fading Hearts, Infinite Game Works
Projects: Don't Save the World
Organization: Sakura River
Location: Canada
Contact:

Re: Re-launching re-initializes persistent data?

#8 Post by Counter Arts »

EDIT: The imagemap layout might not be able change after launching. If you really need it then consider making one with the ui functions.
delta wrote:

Code: Select all

init python:
    if not persistent.doesnotexist:
        persistent.doesnotexist = 0

label start:
    $ persistent.doesnotexist += 1
will work.
This "works" but may cause people lot of trouble if they don't know how truth value testing works in python. If you wanted to do something like a countdown this breaks.

Code: Select all

init python:
    if not persistent.doesnotexist:
        persistent.doesnotexist = 10

label start:
    $ persistent.doesnotexist -= 1
If you restart when the counter reaches zero then it's going to be reset to 10 again. Zero counts as a "False" along with a few other things like empty lists.

You should use this...

Code: Select all

init python:
    if persistent.doesnotexist == None:
        persistent.doesnotexist = 10

label start:
    if persistent.doesnotexist > 0:
        $ persistent.doesnotexist -= 1
    else:
        "Welcome to the secret intro sequence."
Fading Hearts is RELEASED
http://www.sakurariver.ca

delta
Epitome of Generic
Posts: 525
Joined: Sat Dec 22, 2007 12:59 pm
Projects: yes
Contact:

Re: Re-launching re-initializes persistent data?

#9 Post by delta »

And your example breaks if you want to allow values below zero. In shocking news, different ideas need different approaches. If you want to be really anal about it (and you apparently do), you should init depending on the data type:

Code: Select all

init python:
    if type(persistent.doesnotexist) is not int:
        persistent.doesnotexist = 10
In before someone points out that you should use isinstance() instead, but that will count False as an integer, and we ARE being anal here. We're talking about a language in which 3/2 = 1.
The rest is left as an exercise for the reader.

Counter Arts
Miko-Class Veteran
Posts: 649
Joined: Fri Dec 16, 2005 5:21 pm
Completed: Fading Hearts, Infinite Game Works
Projects: Don't Save the World
Organization: Sakura River
Location: Canada
Contact:

Re: Re-launching re-initializes persistent data?

#10 Post by Counter Arts »

If that persistent variable gets overwritten with something that is another type like a float then good luck finding out why it keeps being reset.
Fading Hearts is RELEASED
http://www.sakurariver.ca

delta
Epitome of Generic
Posts: 525
Joined: Sat Dec 22, 2007 12:59 pm
Projects: yes
Contact:

Re: Re-launching re-initializes persistent data?

#11 Post by delta »

Jesus why are we even having this discussion. Just admit that you're wrong about that you "can't" change persistent data in init blocks, and I'll admit that I have not yet found the perfect, catch-all solution to set them in a way that will never break under any circumstances.
The rest is left as an exercise for the reader.

rimir
Regular
Posts: 52
Joined: Mon Jul 06, 2009 12:30 pm
Projects: Only test projects
Contact:

Re: Re-launching re-initializes persistent data?

#12 Post by rimir »

*mildly points out his newbie-esque inability to put Delta and Counter Arts' (anal?) discussion about the details of persistent variables to good use in his project and pleads for clearer advice ~ Peace*

OK. Here's the relevant portion of my present code (in scripts.rpy) :

Code: Select all

$ persistent.cleared = 0
init :
    # Declare images below this line, using the image statement.
    # eg. image eileen happy = "eileen_happy.png"

    # Declare characters used by this game.
    #$ persistent.cleared 
    $ e = Character('Eileen', color="#c8ffc8")

But this is causing the first main-menu imagemap (the one containing call to "_continue" to not appear (This was working correctly before when I'd initialized persistent.cleared in "init")).
Earlier when I'd initialized persistent.cleared in "init" on the virgin-run it would show the main-menu imagemap without "_continue" and then if I entered "Start" and exited then on re-launching it'd show me the main-menu imagemap with the call to "_continue" and all else would proceed smoothly for that run.
The problem was that on exiting and launching a third time it'd show me the imagemap calling "_continue" alright but then I'd find that persistent.cleared had been reset and I'd have to proceed once again through all the imagemaps under "_continue" whereas it was supposed to show only the last imagemap under that label.
Counter Arts wrote:Everytime you start up or reload the game, all init blocks are re-run. That's why it should not be declared or changed in an init block.
Delta wrote:Wrong, you can do whatever you want with persistent data in init. Of course, it's probably pointless if you don't do it conditionally, but that doesn't mean you can't do it. In fact, it's sometimes a good idea to initialize persistent variables in init if they don't yet exist because some things won't work with variables that don't exist. Try incrementing an unset persistent integer:
I hope I have explained what I need clearly enough in the paragraphs preceding these quotes.So guys... please help.

BTW,does Ren'Py support all logical operators in ...like...C?

User avatar
mugenjohncel
Hentai Poofter
Posts: 2121
Joined: Sat Feb 04, 2006 11:13 pm
Organization: Studio Mugenjohncel
Location: Philippines
Contact:

Re: Re-launching re-initializes persistent data?

#13 Post by mugenjohncel »

rimir wrote:But this is causing the first main-menu imagemap (the one containing call to "_continue" to not appear (This was working correctly before when I'd initialized persistent.cleared in "init")).Earlier when I'd initialized persistent.cleared in "init" on the virgin-run it would show the main-menu imagemap without "_continue" and then if I entered "Start" and exited then on re-launching it'd show me the main-menu imagemap with the call to "_continue" and all else would proceed smoothly for that run.The problem was that on exiting and launching a third time it'd show me the imagemap calling "_continue" alright but then I'd find that persistent.cleared had been reset and I'd have to proceed once again through all the imagemaps under "_continue" whereas it was supposed to show only the last imagemap under that label.
Hmm... I have experienced this before... I just can't recall how'd I solved it...

Give me until tommorrow to recall...

"POOF" (Disappears...)

Counter Arts
Miko-Class Veteran
Posts: 649
Joined: Fri Dec 16, 2005 5:21 pm
Completed: Fading Hearts, Infinite Game Works
Projects: Don't Save the World
Organization: Sakura River
Location: Canada
Contact:

Re: Re-launching re-initializes persistent data?

#14 Post by Counter Arts »

When I mean launching I mean close the program completely and restart. Is that what you mean by launching?

Also, try Delta's suggestion on doing a conditional in the init block because he is right.

Code: Select all

init python:
    if persistent.cleared == None:
       persistent.cleared = 0
Fading Hearts is RELEASED
http://www.sakurariver.ca

delta
Epitome of Generic
Posts: 525
Joined: Sat Dec 22, 2007 12:59 pm
Projects: yes
Contact:

Re: Re-launching re-initializes persistent data?

#15 Post by delta »

I think we should take this one from the beginning. Ren'Py knows to types of code: Init code, which is always run when the game starts (and under certain other conditions, which you mostly will need to force), and label code, which is run when the script parser reaches that point in that label. Obviously, setting a persistent variable unconditionally in an init block will defeat the point of a persistent variable (which is persistence over sessions, which normal (aka "store") variables don't have), since then it will always be reset to the default value when the game is started. Hence the recommendation to set persistent variable "outside of init".

However, that doesn't mean setting it wherever you like; in your example, you're setting it... nowhere, because the line is neither in an init block nor any label, so it is NEVER executed. In fact, I always thought that Ren'Py would choke on something like that, but it seems like it drops it silently. If you are not initializing the persistent variable in init (as I recommended), you have to just plain create it at the point where it would change (because you can't just increment it - you'd get a TypeError). You can also initialize it at the start of a game (i.e. in the label called "start"), but that is also run more often than you'd like it so you would have to put the same conditions on it as you would have to use in an init block, defeating the point.

So, either use the above code snippet or do something which is better from a design standpoint: Set a distinct boolean flag for every ending. You don't have to initialize those (though you obviously can), because you can just set it to True when you reach the ending, and None (which an uninitialized persistent variable will be) and False (which you would initialize it to) are completely equivalent for most practical purposes. Also, this will actually tell you what you want to know, which paths have been finished. It's pretty much the same, but if you ever decide to change your logic it is a far more flexible approach.

So:

Code: Select all

init :
    # Declare images below this line, using the image statement.
    # eg. image eileen happy = "eileen_happy.png"

    # Declare characters used by this game.
    $ e = Character('Eileen', color="#c8ffc8")

    # The below is entirely optional, and mostly useful for reference purposes
    # the script will behave exactly the same whether it is present or not

    if not persistent.cleared_A:
        persistent.cleared_A = False

    if not persistent.cleared_B:
        persistent.cleared_B = False

    if not persistent.cleared_C:
        persistent.cleared_C = False

label _continue :
    if persistent.cleared_C:
        $ ui.imagemap("start3_menu.bmp","start3_hovered_menu.bmp",[(250,96,550,126,"A"),(250,222,550,252,"B"),(250,348,550,378,"C"),(250,440,550,500,"Credits")])
    elif persistent.cleared_B:
        $ ui.imagemap("start2_menu.bmp","start2_hovered_menu.bmp",[(170,435,630,480,"A"),(170,280,630,325,"B"),(170,100,630,150,"C")])
    else: #default menu, shown if nothing is cleared or just A is cleared
        $ ui.imagemap("start1_menu.bmp","start1_hovered_menu.bmp",[(170,370,630,415,"A"),(170,200,630,255,"B")])

    $ result =ui.interact()
    if result == "A" :
        jump A
    elif result == "B" :
        jump B
    else: # don't do elif result == "C" :, always offer a default unless you like mysterious bugs
        jump C

# The game starts here.
label start :

    e "You've created a new Ren'Py game."

    e "Once you add a story, pictures, and music, you can release it to the world!"
    jump A
   
label A :
    e"This is the placeholder for the First Arc."
    # the following operation will work whether or not the variable was set in init
    $ persistent.cleared_A = True 
    e"reached here "
    jump return_to_mm
       
label B :
    e"This is the placeholder for the Second Arc."
    $ persistent.cleared_B = True
    jump return_to_mm
       
label C :
    e"This is the placeholder for the Third Arc."
    $ persistent.cleared_C = True
    jump return_to_mm
   
label Credits :
    e"This is the placeholder for the credits."
    jump return_to_mm
       
label help :
    e"This is the placeholder for the help system ."
    jump return_to_mm
   
label return_to_mm :
    pass
The rest is left as an exercise for the reader.

Post Reply

Who is online

Users browsing this forum: No registered users