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.
So I've made a codex, and I've hit a roadblock. I've set codex variables to add another sentence of information to the codex topic whenever I increase the variable, but it's not really working. Basically with this codex, the player will gather information as the story progresses, but the information isn't 'gathering', only staying with one line and it's infuriating me that I can't figure it out. Here's my code:
screen codexmain:
tag menu
frame:
xmaximum 1600
ymaximum 900
xalign .5
yalign .5
textbutton _("Back") action Return() xalign 1.0
fixed:
hbox:
xsize 300
ysize 838
ypos 50
frame:
xsize 300
ysize 838
vbox:
text "{size=60}{b}{color=9A0AF5}TOPICS{/color}{/b}{/size}"
viewport:
scrollbars "vertical"
mousewheel True
vbox:
if you_codex != 0:
textbutton _("You"):
action [ShowMenu('codexmain'), SetVariable('you_codex', 1), ShowMenu('you_desc')]
frame:
xsize 1288
ysize 838
vbox:
xsize 1276
ysize 826
text "{size=40}{b}{color=9A0AF5}DESCRIPTION:{/color}{/b}{/size}"
viewport:
scrollbars "vertical"
mousewheel True
vbox:
transclude
screen you_desc:
tag menu
use codexmain:
if you_codex == 0:
text ""
elif you_codex == 1:
text "blablabla"
[b] elif you_codex == 2:
text "blablabla" [/b]
# This line isn't appearing on the codex screen, only when the variable is set to 1 does it show the line above
I don't really know what to do, I'm really desperate.
Last edited by rusicaria on Sat May 21, 2022 5:45 pm, edited 1 time in total.
Depends of what you trying to achieve.
Looks like your 'you_desc' screen shows the content depended of 'you_codex' variable value. So, if you change this value somewhere in game you should remove SetVariable('you_codex', 1) from the list of actions to not to set it to 1 when button is clicked.
Alex wrote: ↑Tue May 17, 2022 4:27 pm
Depends of what you trying to achieve.
Looks like your 'you_desc' screen shows the content depended of 'you_codex' variable value. So, if you change this value somewhere in-game you should remove SetVariable('you_codex', 1) from the list of actions to not to set it to 1 when button is clicked.
It kind of worked. So if I repeat the earlier code into the if statement text, if works how I want it to, but if I don't then it only shows the variable of that number, and not as well as the earlier information. But I don't want to do that, because it's messy and unnecessary to do that, if that makes sense.
screen you_desc:
tag menu
use codexmain:
if you_codex == 0:
text ""
elif you_codex == 1:
text "you did this" #first codex text
elif you_codex ==2:
text "you did this" # first text repeated WORKS, but if I did this over the length of the game, each paragraph of code will get longer and longer the more the player learns.
text "you also did this"
Is there an easier way to do this without repeating each line of code?
default codex_entries = ["first entry", "second entry", "third entry"]
default you_codex = 0
screen codex:
for i, entry in enumerate(codex_entries):
if i <= you_codex:
text codex_entries[i]
default codex_entries = ["first entry", "second entry", "third entry"]
default you_codex = 0
screen codex:
for i, entry in enumerate(codex_entries):
if i <= you_codex:
text codex_entries[i]
Hello! So I understand how the first way that you sent me works, but I only understand the first half of the second way. I understand for the first way, the player accumulates increased variables which gradually adds to the codex, but if they missed out some information by taking a different route, they would still accumulate the information in the codex. In a way that could still work, but I'd have to be careful and control when the player can learn certain information in the game, but it isn't specified.
How does the second way work? I'm not sure how to test it out, what does 'enumerate' mean in Python language? Thank you for your help!
rusicaria wrote: ↑Fri May 20, 2022 12:31 pm
How does the second way work? I'm not sure how to test it out, what does 'enumerate' mean in Python language? Thank you for your help!
The enumerate() function is just a more elegant way of going through a list and additionally increasing an integer variable (in this case "i") by 1 every loop. It's useful if you need to have a counter while looping.
$ i = 0
for entry in codex_entries:
if i <= you_codex:
text codex_entries[i]
$ i += 1
You talked about the player only getting information inside the codex he already learned, so it's not just linearly increasing. Okay. That's still possible without problems. You just need to collect information about stuff the player already knows.
default player_wisdom = []
define codex_entries = {
"entry1": "This is information about the map.",
"entry2": "This is other useful information."
}
init python:
def playerLearns(info):
global player_wisdom
# make sure the player doesn't already know and it's a valid codex entry
if info not in player_wisdom and info in codex_entries.keys():
player_wisdom.append(info)
screen codex:
if len(player_wisdom) == 0:
text "The player doesn't know anything"
else:
vbox:
for entry in player_wisdom:
text "The player knows: " + codex_entries[entry]
label start:
show screen codex
"The player will learn something:"
$ playerLearns("entry1")
"And another thing."
$ playerLearns("entry2")
"Now we let him forget."
$ player_wisdom.remove("entry1")
"End of game."
This will of course only list what he knows, it's just for you to get an idea, you can do whatever you want. If the codex should have a very specific structure, then you could do something like:
screen codex:
if "entry1" in player_wisdom:
text "This is the knowledge about wands." xpos 50 ypos 50
if "entry2" in player_wisdom:
text "This is secret information" size 8 xpos 100 ypos 200
add "secret map"
rusicaria wrote: ↑Fri May 20, 2022 12:31 pm
How does the second way work? I'm not sure how to test it out, what does 'enumerate' mean in Python language? Thank you for your help!
The enumerate() function is just a more elegant way of going through a list and additionally increasing an integer variable (in this case "i") by 1 every loop. It's useful if you need to have a counter while looping.
$ i = 0
for entry in codex_entries:
if i <= you_codex:
text codex_entries[i]
$ i += 1
You talked about the player only getting information inside the codex he already learned, so it's not just linearly increasing. Okay. That's still possible without problems. You just need to collect information about stuff the player already knows.
default player_wisdom = []
define codex_entries = {
"entry1": "This is information about the map.",
"entry2": "This is other useful information."
}
init python:
def playerLearns(info):
global player_wisdom
# make sure the player doesn't already know and it's a valid codex entry
if info not in player_wisdom and info in codex_entries.keys():
player_wisdom.append(info)
screen codex:
if len(player_wisdom) == 0:
text "The player doesn't know anything"
else:
vbox:
for entry in player_wisdom:
text "The player knows: " + codex_entries[entry]
label start:
show screen codex
"The player will learn something:"
$ playerLearns("entry1")
"And another thing."
$ playerLearns("entry2")
"Now we let him forget."
$ player_wisdom.remove("entry1")
"End of game."
This will of course only list what he knows, it's just for you to get an idea, you can do whatever you want. If the codex should have a very specific structure, then you could do something like:
screen codex:
if "entry1" in player_wisdom:
text "This is the knowledge about wands." xpos 50 ypos 50
if "entry2" in player_wisdom:
text "This is secret information" size 8 xpos 100 ypos 200
add "secret map"
Thank you for the really detailed response! I'll have a go and mess around with this and let you know if it works! Just one more question, since the code for the codex is in a separate screen, do I add the default/define in that screen or the original script.rpy?
If you define/default variables inside screens, you are creating a screen variable, that is only known inside the screen (like a local variable inside a python function). If the variable is only used inside the screen do it like that. But if that variable is used all over the game, then define/default it outside of screens. It doesn't have to be inside the script.rpy, you can just create your own empty *.rpy files for every part of the game. Renpy will automatically load all those files.
So I managed to do what I needed to do with your help! I didn't end up using enumerate, probably because I'm half-asleep. I'll still look into using the function in the future.
screen codexmain:
vbox:
if you_entry1 == True:
textbutton _("You"):
action [ShowMenu('codexmain'), ShowMenu('you_desc')]
screen you_desc:
tag menu
use codexmain:
if you_entry1 == True:
text "Here's some information!"
if you_entry1_1 == True:
text ""
text "Here's some MORE information!"
default you_entry1 = False
default you_entry1_1 = False
label start:
"Here's some information!"
$ you_entry1 = True
"Here's some MORE information!"
$ you_entry1_1 = True
It's worked with the other topic entries as well, and while it means that I have to define each piece of information because I have multiple .rpy files, it won't be all clumped up on the same file. Thank you for the great advice!