Page 1 of 1

[Solved] Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Tue Mar 03, 2020 10:14 pm
by NewMaxD
So I'm not used to ask on forums, cause I normally end up finding answers to whatever I want to know, but days ago I started experiencing some problems related to saving data. Didn't really care about it until today. Today I wanted to fix it, and after spend some time without result I started googling more.

Didn't get anything from the docs, nor the forum itself, even asking google to only show results from here (lol) which makes me think, am I really that bad at just googling? (Probably true)

Let's talk about the issue. First of all, I want to clarify that my game is a management simulation one, about building and upgrading some city. I have a custom class inside a RPY file. The class Building. And one of its parameters is a list of Buildings named container.

It works like this: you create buildings of type Building, and a "building container" with only that last parameter set. The list contains al the buildings related to the main one. This is used by me to represent an actual building along with its multiple other upgraded versions. A more easy to get example would be:

house = Building(....)
house_big = Building(....)
h_container = Building(container=[house, house_big])


To access the actual building you use the actualproperty of the h_container (it "selects the current building, like selecting a state).

I know it is a kind of wtf approach, but I'm still prototyping it at a very basic level, I'll surely change it later..

I create every build inside a python block, inside the start label. And then I use $b = [container1, container2..] to create the list of buildings to use.

The saving-load problem comes when actually saving and loading. I use screens to navigate within options on what to build or upgrade, and this is done by using a "build" and "levelUp" methods corresponding to each building. So to upgrade, you would just do container.levelUp() and done.

But if you go buy and build whatever you want, quick save and load, you'll notice it didn't save anything. It doesn't save the Player class with the money changes, nor the list of containers, nor the buildings alone, nothing.

But, if you do the same, and before quick saving and loading you click to advance (I tested it with two "example" narrator dialogues), then it will get saved correctly, from the player stuff, to the buildings and all. Still, this forces me to like, "advance one line each time the player builds or do something" in order to actually make saving available for the user..

Does anyone know how to fix this? Some workaround? I could use the choice selection system (the menu of choices one tipically see on VNs), since it would "advance" statements and would allow the data to be saved after each click on the buttons.. But I do want to use Screens here.

Any help will be greatly appreciated! I've also already tried: going default on everything (doesn't work) and going $ .... on everything (same again).

There are no errors, just no saving. The values also do save well if you do as I said before (but it needs the user to advance forward in order to save, it's like if Renpy wasn't updating anything), if someone wants, I could minimize it and give a small example (would need to modify the classes to make them smaller, but should not be a problem).

Thanks in advance! (and hope this was not another dumb question, I've spent days actually trying to fix this .-.)

Quick Note: I've actually fixed it, you can read down in the comments section in case you want to check it out, feel free to leave suggestions or whatever alike (since fixed is not the same as optimized or clean).

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Tue Mar 03, 2020 10:54 pm
by Imperf3kt
Adding a renpy.restart_interaction() to your function might solve the issue.
https://www.renpy.org/doc/html/other.ht ... nteraction

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Tue Mar 03, 2020 11:19 pm
by NewMaxD
Imperf3kt wrote:
Tue Mar 03, 2020 10:54 pm
Adding a renpy.restart_interaction() to your function might solve the issue.
https://www.renpy.org/doc/html/other.ht ... nteraction
I've just tried it. But still the same, no change. I added it before ending both functions in charge of Upgrading and Building (the ones modifying the object), and also tried adding them as separated functions with Function(...) (as an action).

So still no results :| But thanks for trying to help dude, appreciate it!

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Wed Mar 04, 2020 5:06 am
by philat
https://www.renpy.org/doc/html/save_loa ... n-py-saves
https://www.renpy.org/doc/html/save_loa ... after-load

Basically, the system is working as intended. There are ways of working around it, but hard to say in the abstract, so it's probably up to you to figure out what works best for your game.

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Wed Mar 04, 2020 2:33 pm
by NewMaxD
philat wrote:
Wed Mar 04, 2020 5:06 am
https://www.renpy.org/doc/html/save_loa ... n-py-saves
https://www.renpy.org/doc/html/save_loa ... after-load

Basically, the system is working as intended. There are ways of working around it, but hard to say in the abstract, so it's probably up to you to figure out what works best for your game.
So basically there's no easy fix after all :|
I'd need a function to tell renpy to manually "rescan" everything within the same statement (to force it to notice the changes manually).

But as far as I've read, there's no such function apparently, all I see are functions to save, load or reset, but nothing to emulate the exact same "scan" renpy performs each time yo advance to a new statement..

I'm certainly sure it won't be a good practice, but maybe save the current position, then jumping to some other blank label to force renpy to notice all, and then go back to where I was could work. I think there are worse ways to do it, but I just know about that one, I'm pretty sure that's not a good practice lol (don't even know how to do it without losing info on where I exactly was)

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Thu Mar 05, 2020 1:30 am
by NewMaxD
I've made some progress trying to identify the problem and apparently found it.
No solution for now sadly (I cannot even tell why, I mean, lots of games, all made in renpy, do similar stuff, even way way more advance things..).

So the actual problem is simply that any action that comes from my screens *doesn't actually represents a new statement*, and since I suck at english sometimes, I'll try to explain myself in the easiest way possible: if you do "$ building.whatever()" on your start label, it will be taken by renpy as an action or statement. And you'll see the back button down there allowing to rollback.
Now, if you use the textbutton from a screen, let's say, "textbutton "test" action Function(building.whatever)", you'll notice the change, but it won't conform a new statement, and you won't get that back button. So basically renpy acts like if nothing happened for real. So if you do a bunch of these, and quick/load, you'll lose everything you did before.

I'm sure this is not a bug (too stupid to actually be one), and I assume it is not some kind of logic fail (not possible, renpy is an actual complete VN engine, featuring a bunch of stuff, with too many updates already). So I'm a bit confused.. Are screens actually supposed to act like this? Is there a specific way to declare them in order to make whatever action they perform, relevant enough to renpy so it can save it? Is there some alternative?

I tried google, but each time I search for something I get the same 8 webs from the docs. And I'm starting to get pissed after reading a lot of times the same thing.. I must be blind or something..

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Thu Mar 05, 2020 7:01 pm
by shin.e.d
I'm not familiar with python classes, but I used something similar in my own game (with droppable RPG items) & used Ren'py's new screen action Call() but within a loop. So maybe you can use action Call() in screens to call a label?

Not sure how helpful it would be (it seems to save/load ok) but the script is something like this, tho it doesn't allow muliples of the same type of item unfortunately. Hopefully you can figure out how to get your game to work. I love sim games where you can build stuff.

Code: Select all

default buildables =["box","tent","house"]
default your_lot ={}# python dictionary that saves (x,y,z) coordinates.
image box =Solid("#776622",xysize=(50,50))
image tent =Solid("#336611",xysize=(100,100))
image house =Solid("#ffffff90",xysize=(300,300))

label start:
    scene
    label loop:
        show screen build_stuff(buildables)
        call screen ok
        if not _return=="ok!":
            jump loop
    hide screen build_stuff with dissolve
    "Now that you've built your home, come with me."
    scene some_other_place with fade
    "I'll let you return to your place now."
    scene
    python: # show your home again.
        for i,v in your_lot.items():
            renpy.show(i, zorder=v[2], at_list=[Position(xpos=v[0],ypos=v[1])])
    with dissolve
    menu:
        "Build something else":
            jump loop
        "Sleep":
            show you zorder 720 with dissolve
            # walk to your home's position.
            show you at Position(xpos=your_lot[i][0],ypos=your_lot[i][1]) with MoveTransition(2.0)
            return # ends the game

screen build_stuff(local_var_buildables):
    vbox:
        label "Choose what to build..."
        for i in local_var_buildables:
            textbutton "[i!c]" action Call("build_it",i)
        textbutton "Demolish" action ShowTransient("demolish")
        textbutton "Undo" action Rollback()
screen ok():
    textbutton "OK!" align(0.0,1.0) action Return("ok!")
label build_it(i):
    if not renpy.in_rollback():
        $ x,y = renpy.get_mouse_pos() # build it where the mouse is.
        $ persistent.undo_data[i]=(x,y)
    else:
        $ x,y = persistent.undo_data[i]
    $ z = y # it's z will be based on the y-coordinate.
    $renpy.show(i, zorder=z, at_list=[Position(xpos=x,ypos=y)])
    $ your_lot[i]=(x,y,z)# puts the item in the dictionary, saving it.
    with dissolve
    return
default persistent.undo_data ={}#keeps (x,y) coords in a safe place from rollback.

screen demolish():
    vbox xpos 333:
        label "What do you want to demolish?"
        for i in your_lot:
            textbutton "[i!c]" action Call("demolish_it",i)
        textbutton "Cancel" action Return()
label demolish_it(i):
    $renpy.hide(i,layer="master")# the image's name must be lowercase.
    $ del your_lot[i]
    with vpunch
    return

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Fri Mar 06, 2020 1:30 am
by NewMaxD
shin.e.d wrote:
Thu Mar 05, 2020 7:01 pm
I'm not familiar with python classes, but I used something similar in my own game (with droppable RPG items) & used Ren'py's new screen action Call() but within a loop. So maybe you can use action Call() in screens to call a label?

Not sure how helpful it would be (it seems to save/load ok) but the script is something like this, tho it doesn't allow muliples of the same type of item unfortunately. Hopefully you can figure out how to get your game to work. I love sim games where you can build stuff.

Code: Select all

default buildables =["box","tent","house"]
default your_lot ={}# python dictionary that saves (x,y,z) coordinates.
image box =Solid("#776622",xysize=(50,50))
image tent =Solid("#336611",xysize=(100,100))
image house =Solid("#ffffff90",xysize=(300,300))

label start:
    scene
    label loop:
        show screen build_stuff(buildables)
        call screen ok
        if not _return=="ok!":
            jump loop
    hide screen build_stuff with dissolve
    "Now that you've built your home, come with me."
    scene some_other_place with fade
    "I'll let you return to your place now."
    scene
    python: # show your home again.
        for i,v in your_lot.items():
            renpy.show(i, zorder=v[2], at_list=[Position(xpos=v[0],ypos=v[1])])
    with dissolve
    menu:
        "Build something else":
            jump loop
        "Sleep":
            show you zorder 720 with dissolve
            # walk to your home's position.
            show you at Position(xpos=your_lot[i][0],ypos=your_lot[i][1]) with MoveTransition(2.0)
            return # ends the game

screen build_stuff(local_var_buildables):
    vbox:
        label "Choose what to build..."
        for i in local_var_buildables:
            textbutton "[i!c]" action Call("build_it",i)
        textbutton "Demolish" action ShowTransient("demolish")
        textbutton "Undo" action Rollback()
screen ok():
    textbutton "OK!" align(0.0,1.0) action Return("ok!")
label build_it(i):
    if not renpy.in_rollback():
        $ x,y = renpy.get_mouse_pos() # build it where the mouse is.
        $ persistent.undo_data[i]=(x,y)
    else:
        $ x,y = persistent.undo_data[i]
    $ z = y # it's z will be based on the y-coordinate.
    $renpy.show(i, zorder=z, at_list=[Position(xpos=x,ypos=y)])
    $ your_lot[i]=(x,y,z)# puts the item in the dictionary, saving it.
    with dissolve
    return
default persistent.undo_data ={}#keeps (x,y) coords in a safe place from rollback.

screen demolish():
    vbox xpos 333:
        label "What do you want to demolish?"
        for i in your_lot:
            textbutton "[i!c]" action Call("demolish_it",i)
        textbutton "Cancel" action Return()
label demolish_it(i):
    $renpy.hide(i,layer="master")# the image's name must be lowercase.
    $ del your_lot[i]
    with vpunch
    return
Appreciate the help, I managed to handle it and forced it to save just every time I change menu or perform an action. The trick was to just use the loop, in my case it would last depending on a condition, that is set to False from the "Done." button in a screen. So everytime I do something like change menu or whatever, I just hide my screen, perform any function, and return the next screen to show (if I do Build->Start New Building->Building1, I hide the first screen and return the name of the next one, and from the loop it will load that new screen up..). This way you can save everything you do. Cool if you want to autosave while blocking the Back button (to avoid having players losing progress due to just quiting without saving something or just doing rollback every two seconds hah)

I don't know about your game, but maybe I can help you with that (?). Mine has a simple concept actually: you're suddenly in charge of a Japanese themed village, and have 3 years to prepare for a big invasion. You need to build, upgrade and research stuff. Train soldiers, and get help from allies. This way I can introduce management along with VN aspects (such as talking to other leaders/rulers around).

I've so far created a system to handle buildings, alone or in group (such as having "Small walls, medium walls, long walls, etc.." each one better than the one before, but all part of the same group or container as I call it), it also features requirements (list of references to improvements/buildings and their levels in order to be build/upgrade), and finally introduced the Improvements (the ones you strictly need to research). The time would advance weekly, and I plan to make every change actually visible so you can see the every building and every upgrade.

As I said, if you need help I could try to give you a hand (I'm not an expert as you can surely tell, specially with python, I'm a C# coder after all), I could also translate your game to spanish for free if you want, just saying.

Thanks again dude, my problem got a temp fix at least for the moment hah

Re: Struggling a lot saving objects and variables.. (Yes, another one..)

Posted: Sat Mar 07, 2020 1:08 am
by shin.e.d
Your game sounds cool. I like Japanese stuff. I know abit about traditional Japanese architecture so maybe I could help out with art/references for the buildings? (both indoors & outdoors, city layouts & furnishings) I do best in pixel art styles. I also do characters, like in my forum avatar. :3

My games are all RPG prototypes & use the same mechanics. But I'll send a link to one if you wanna look through it. (though I need some time to clean up the code first) The systems are for saving & loading items/NPCs.
But really thank you for offering the help, that's really nice of you. It actually caught me by surprise. lol My code might be beyond help tho, it uses Ren'py's drag 'n drop system in unintended ways...

You can send me some requests for art designs via PM. Eventually I'll send the link to my game's code too but it might take awhile.