Download any of the many gallery enabling mods and read the code.How can i open and edit persistent file in RenPy games?
I want to learn it to be able to unlock the gallery in games.
Just use Ren'py's console to change the value of the right variables when you play the game. The right variables being found by looking at the source code of the game.How can i open and edit persistent file in RenPy games?
I want to learn it to be able to unlock the gallery in games.
How can i open and edit persistent file in RenPy games?
I want to learn it to be able to unlock the gallery in games.
This very much depends on how the gallery is implemented. In some games, the gallery code uses persistent variables. If you open up the game source code, you'll see references to things like:Just use Ren'py's console to change the value of the right variables when you play the game. The right variables being found by looking at the source code of the game.
if persistent.abc:
...enable the abc image in the gallery
init 999 python:
config.console = True
config.developer = True
config.console
line is required, but I sometimes use the developer features as well when exploring someone else's game, so...persistent.abc = True
persistent.abc
variable, which should unlock that one gallery entry. Repeat for the rest of the gallery entries you want to enable. image_gallery.button("slot01")
image_gallery.condition('renpy.seen_image("ch0b_12")')
image_gallery.unlock_image("ch0b_09")
image_gallery.unlock_image("ch0b_10")
image_gallery.unlock_image("ch0b_11_movie")
image_gallery.unlock_image("ch0b_12")
renpy.seen_image
is a function provided by Ren'py that will return True if the image referenced, (ch0b_12
in this case, has been seen by the player during the course of any game. In addition, the unlock_image
sets the gallery up so that the gallery will only show an image if it's been seen by the user.scene the_image_name
scene ch0b_12
, that would satisfy the renpy.seen_image
condition above.jump the_label_name
to go execute that part of the code, which will then play through the section you missed. This is the trickiest approach, because that block of code may depend on variables being set correctly, etc. Don't do this and then save - there's a very good chance that, as a result of this, you'll put the game into a bad state.There's one,There's no direct way to edit the "what images have been seen" information that Ren'py keeps. At least, if there is, I'm not aware of it.
renpy.game.persistent._seen_images[("NAME_OF_THE_IMAGE",)] = True
.renpy.game.persistent._seen_images[("ch0b_12",)] = True
would unlock the image in your example.scene
from the console is way easier and faster if you've to do it manually.Awesome! Thanks for that! In retrospect, of course, there had to be a way of doing it, I had just never gone deep enough into the Ren'py code to figure it out. You, on the other hand, seem to have explored pretty much all the nooks and crannies...There's one,renpy.game.persistent._seen_images[("NAME_OF_THE_IMAGE",)] = True
.
Therefore,renpy.game.persistent._seen_images[("ch0b_12",)] = True
would unlock the image in your example.
This said, it's not an easy to use approach, and your use ofscene
from the console is way easier and faster if you've to do it manually.
There's no direct way to edit the "what images have been seen" information that Ren'py keeps. At least, if there is, I'm not aware of it.
Thank you very much, I was going spare trying to unlock a gallery which uses seen_image() conditions until I found this thread.There's one,renpy.game.persistent._seen_images[("NAME_OF_THE_IMAGE",)] = True
.
Therefore,renpy.game.persistent._seen_images[("ch0b_12",)] = True
would unlock the image in your example.
renpy.game.persistent._seen_images[("name of image",)] = True
wouldn't work...renpy.game.persistent._seen_images[tuple("name of image".split())] = True
Oops. I don't remembered why it used a tuple, and since it worked when I tried it, to be sure that my memory was correct, didn't payed attention to the fact that the name of the image was a single word ('_' are seen as being a letter). What falsely lead me to the syntax used for screen, that isFor any other python plebs like me who stumble across this, the round brackets & comma are because when Ren'Py stores the image name, it first does a split() [replaces spaces with commas] then transforms the list that outputs into a tuple (the brackets).
( "name of the screen", ( "layer used to display it" )
.( "name of the image", "Nothing because there's no layers for images" )
.Of course, from inside the game, from the console, you could just type:Which is a painful way to unlock one image...
That makes Ren'py do all the heavy lifting...show name_of_image
And I remember that theOf course, from inside the game, from the console, you could just type:
Code:show name_of_image
show
statement also accept an expression as argument. Therefore, outside of the console it's possible to use something like :label whatever:
$ lst = [ "someImage", "and some other" ]
while lst:
# If put directly as expression, /pop()/ would have no effect.
$ img = lst.pop()
scene expression img
# Be nice with the memory.
hide expression img
label whatever:
$ i = 1
while i < 11:
scene expression "myImage_{}".format( i )
hide expression "myImage_{}".format( i )
$ i += 1
However, not all galleries are implemented this way. The gallery code I use, for example, relies on some Ren'py functionality that automatically tracks which images have been displayed to the user and which have not, so that I don't have to manage my own persistent variables for that. If you were to look inside one of my games, you'd see something like:
Code:image_gallery.button("slot01") image_gallery.condition('renpy.seen_image("ch0b_12")') image_gallery.unlock_image("ch0b_09") image_gallery.unlock_image("ch0b_10") image_gallery.unlock_image("ch0b_11_movie") image_gallery.unlock_image("ch0b_12")
renpy.seen_image
is a function provided by Ren'py that will return True if the image referenced, (ch0b_12
in this case, has been seen by the player during the course of any game. In addition, theunlock_image
sets the gallery up so that the gallery will only show an image if it's been seen by the user.
def unlock (a):
if persistent.images is None:
persistent.images = {}
if not (a in persistent.images):
persistent.images[a] = True
renpy.save_persistent()
if persistent.hide_top_menu_extra is None:
persistent.hide_top_menu_extra = False
So, that first block of code works like this.This bit you mention here, does this look like a similar method to you?
I'm trying to unlock the galleries in the "Do You Like Horny Bunnies 1 & 2 Remaster" games and am kinda a newb with ren'pyCode:def unlock (a): if persistent.images is None: persistent.images = {} if not (a in persistent.images): persistent.images[a] = True renpy.save_persistent()
I also found this in the source code as well:
However, changing that in console only shows said "extra" button on main menu (which is where the gallery is located) for a split second and then it disappears again.Code:if persistent.hide_top_menu_extra is None: persistent.hide_top_menu_extra = False
persistent
object is "special," in that, unlike traditional Python objects, any member of it will always return a value, even if the value has never been set. persistent.images
is basically saying "if I've never set an image into this before" ("is None"), then make persistent.images
be an empty dictionary. The idea is that you want a persistent dictionary, but you don't want to overwrite it if you've already set it up.if not (a in persistent.images)
is testing to see if the key passed in is already in the dictionary. If it isn't, it adds the key, then saves the persistent data.$ unlock("some_image_name")
Okay, thanks! I'll play around with it and see what I can find.So, that first block of code works like this.
So, presumably, scattered around through the code are lines like:
- The
persistent
object is "special," in that, unlike traditional Python objects, any member of it will always return a value, even if the value has never been set.- So the test
persistent.images
is basically saying "if I've never set an image into this before" ("is None"), then makepersistent.images
be an empty dictionary. The idea is that you want a persistent dictionary, but you don't want to overwrite it if you've already set it up.- Dictionaries, as you might know, map keys to values.
if not (a in persistent.images)
is testing to see if the key passed in is already in the dictionary. If it isn't, it adds the key, then saves the persistent data.
which unlocks that image.Code:$ unlock("some_image_name")
Elsewhere, in the gallery code itself, there are probably then lines that test to see if an image is unlocked.
So, basically, you have two potential approaches:
The first approach requires you to find all the values that "unlock" gets called with, of course, but you can probably figure that out from the gallery code. The second approach requires you to replace the existing gallery code with some modified gallery code.
- You could write some Python code that would call "unlock" for every image in the gallery.
- You could modify the gallery code so that the "is it unlocked" test always succeeded, whether or not the "unlock" function had actually been called.