[Solved] Variable reference handling on save/load

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
moogsparfait
Regular
Posts: 53
Joined: Mon Apr 28, 2014 9:26 pm
Completed: Danmaku!! (Card Game)
Projects: The Parasol Festival
Organization: Mystery Parfait
Contact:

[Solved] Variable reference handling on save/load

#1 Post by moogsparfait »

I'm trying to debug the minigame in my visual novel. I have a global variable instance called AniseStats that contains the player character data, and my intent is to share it between the story sections written in Ren'Py and the minigame logic classes written in the underlying Python. I'm using Ren'Py 6.18 currently.

To achieve this, when a new instance of my minigame starts (ShopkeepGame) I pass the AniseStats object to it. This makes AniseStats and shopkeepgame.player the same instance like I expect. However upon save/load AniseStats appears to be a new object and I have to reassign it during the main game loop to get it to update.

  1. Is there a better way to do this?
  • If how I'm doing it is fine, how would I make things resync upon load?



Also, I apologise for the inconsistent code style, I'm used to camel & pascal case and the habit is hard to break.

script.rpy

Code: Select all


init:
    $ global AniseStats
    $ AniseStats = Anise()
anise.rpy

Code: Select all

python early:
    class Anise:        
        charm_level = 0
        charm_experience = 0
        
        upsell_level = 0
        upsell_experience = 0
       
        pressure_level = 0
        pressure_experience = 0
        
        bargain_level = 0
        bargain_experience = 0
        
        merchant_reputation = 0
        maturity_reputation = 0
        honesty_reputation = 0
        
shopkeepcontroller.rpy

Code: Select all

label shopkeep_init:   
    
    show shop
    with dissolve
    
    
    $ shopkeep = ShopkeepGame(AniseStats)
    $ shopkeep.session_time = 40

...(snip)...

label shopkeep_loop:

    $ shopkeep.level_up()
    
    if (shopkeep.current_customer.patience <= 0):
        call lost_customer
    
    $ cu_mouth = "smile"
    
    $ customer_is(shopkeep.current_customer.face)
    cu "[shopkeep.current_customer.response]"
    call customer_enter
    
    
    $ AniseStats = shopkeep.player
    if shopkeep.session_time > 0:
        jump shopkeep_loop
    else:
        return

    return
screens.rpy

Code: Select all

        vbox xalign 0.0 yalign 0.5 spacing 10:
            text "{color=#000}time [shopkeep.session_time]{/color}"
            text "{color=#000}rush! [shopkeep.rush]{/color}"
            text "rush customers [shopkeep.rush_customers]"
            text ""
            text "charm [AniseStats.charm_level]"
            text "{color=#000}charm [shopkeep.player.charm_level]([shopkeep.player.charm_experience]){/color}"
            text "{color=#000}upsell [shopkeep.player.upsell_level]([shopkeep.player.upsell_experience]){/color}"
            text "{color=#000}bargain [shopkeep.player.bargain_level]([shopkeep.player.bargain_experience]){/color}"
            text "{color=#000}pressure [shopkeep.player.pressure_level]([shopkeep.player.pressure_experience]){/color}"
        
Last edited by moogsparfait on Thu May 07, 2015 10:45 pm, edited 1 time in total.

User avatar
Zetsubou
Miko-Class Veteran
Posts: 522
Joined: Wed Mar 05, 2014 1:00 am
Completed: See my signature
Github: koroshiya
itch: zetsuboushita
Contact:

Re: Question about variable reference handling on save/load

#2 Post by Zetsubou »

I believe the problem is

Code: Select all

init:
    #...
    $ AniseStats = Anise()
As a per-game variable you want to save, you should instantiate it elsewhere.
eg. Remove it from init and put it in your start label.
Also, I don't think you need to make it global.
Finished games
-My games: Sickness, Wander No More, Max Massacre, Humanity Must Perish, Tomboys Need Love Too, Sable's Grimoire, My Heart Grows Fonder, Man And Elf, A Dragon's Treasure, An Adventurer's Gallantry
-Commissions: No One But You, Written In The Sky, Diamond Rose, To Libertad, Catch Canvas, Love Ribbon, Happy Campers, Wolf Tails

Working on:
Sable's Grimoire 2

https://zetsubou.games

User avatar
PyTom
Ren'Py Creator
Posts: 16096
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: Question about variable reference handling on save/load

#3 Post by PyTom »

So basically, when you do:

Code: Select all

init:
    $ global AniseStats
    $ AniseStats = Anise()
AniseStats will not be saved.

In 6.99.3 and earlier, you have to do:

Code: Select all

label start:
    $ AniseStats = Anise()
To ensure that AniseStats is saved. In 6.99.4 and later:

Code: Select all

default AniseStats = Anise()
will also work.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

User avatar
moogsparfait
Regular
Posts: 53
Joined: Mon Apr 28, 2014 9:26 pm
Completed: Danmaku!! (Card Game)
Projects: The Parasol Festival
Organization: Mystery Parfait
Contact:

Re: Question about variable reference handling on save/load

#4 Post by moogsparfait »

That was it, thank you!

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: Question about variable reference handling on save/load

#5 Post by trooper6 »

PyTom wrote:So basically, when you do:

Code: Select all

init:
    $ global AniseStats
    $ AniseStats = Anise()
AniseStats will not be saved.

In 6.99.3 and earlier, you have to do:

Code: Select all

label start:
    $ AniseStats = Anise()
To ensure that AniseStats is saved. In 6.99.4 and later:

Code: Select all

default AniseStats = Anise()
will also work.
PyTom, could you explain the new syntax that uses "default"?
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
PyTom
Ren'Py Creator
Posts: 16096
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: [Solved] Variable reference handling on save/load

#6 Post by PyTom »

Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

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: [Solved] Variable reference handling on save/load

#7 Post by trooper6 »

Hm.

if

Code: Select all

default points = 0
is the same as

Code: Select all

label start:
    $points = 0
in what circumstances would you want to use the former rather than the latter?
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

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

Re: [Solved] Variable reference handling on save/load

#8 Post by philat »

Well, trooper, probably for a game that will ship "finished", no difference, but if you ever want to update a game and add new features and such it seems it would be handy.

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: [Solved] Variable reference handling on save/load

#9 Post by trooper6 »

philat wrote:Well, trooper, probably for a game that will ship "finished", no difference, but if you ever want to update a game and add new features and such it seems it would be handy.
Could you give an example so I can wrap my head around the difference between the two options?
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

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

Re: [Solved] Variable reference handling on save/load

#10 Post by philat »

Per the documentation, default is the same as doing $ var = value BOTH directly after label start and directly after label after_load.

Let's say v1.0 of a game is the following.

Code: Select all

label start:
    $ var1 = 1

    "blah blah"

    if var1 == 1:
        "Var1 is 1."
v1.1 of the game expands upon v1.0 to the following.

Code: Select all

label start:
    $ var1 = 1
    $ var2 = 2

    "blah blah"

    if var1 == 1:
        "Var1 is 1."

    if var2 == 2:
         "Furthermore, var2 is 2."
Imagine if one user had saved with v1.0 "blah blah" -- in other words, after var2 is supposed to be initialized. The dev pushes an update to v1.1 and the user tries to load that save. It would crash at if var2 == 2. To get around this, the dev could do something like:

Code: Select all

label after_load:
    python:
        try:
            var2
        except NameError:
            var2 = 2
(Or conceptually something like the above, I've never actually tried it tbh.) However, with default, you can just default the variable at init time and not worry about any of this. Another avenue I could see it being pretty useful is when the game is still in development and as the dev, you're trying to develop later parts of the game while using save files to be able to jump to a particular place in the game. I mean, we've all had save files become useless because of features we added later, right?

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: [Solved] Variable reference handling on save/load

#11 Post by trooper6 »

huh! That is really interesting!

But wait...what happens here? (I wanted to test it, but 6.99.4 isn't out yet...so I keep getting errors when trying to use it.)

Code: Select all

default var1 = 0

label start:
    "Var1 = [var1]" #This should say 0
    $ var1 = 1
    "Var1 = [var1]"#This should say 1
    "Save and Load Now."
    "Var1 = [var1]" #Will this say 0 or 1?
does using default overright assignments made to a variable during the course of a game? Because that could be irritating.
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

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot]