VN Ren'Py help with complicated script

Sep 10, 2017
50
49
hey guys! there is something I have been trying to implement in my game but I just cant figure it out.

basically what is going on: the game starts of static as hell, but after the player has gone through that he gets to the free roam section. this is filled to the brim with sidequests. the status of those is saved by $ quest_weeknumber_location_active = "True"/"false" and $ quest_weeknumber_location_completed = "True"/"False". I know using strings isnt necesary but had some issues bla bla bla.

to end the free roam section and continue the game the player goes to sleep, but the way the game is built means that after going to the next week (sleeping) the quests in the previous week are unaccusable. aka a quest in progress breaks the game when u go to bed.

I have a way to combat this, by adding a script to the sleeping that checks all the quest statuses and if any of them are active or not completed, the player gets a warning that he either didnt complete a quest or hasnt done all of them. but the problem with that is that that would mean writing down all possible quest variables in that script. is there another way to go about this? maybe have the script check every variable that starts with $quest_weeknumber or something like that?
 

MoonPillow

Newbie
Apr 5, 2020
31
9
Small adaptation to previous post. I guess you have some story section then free roam and then again story section. Each free roam section will have some required number/list of side quests which needs to be completed.
I would define this list of side quests per free roam section and create listener that whenever a quest is completed then it is removed from that list. After that you can only check if that list is empty or not whenever the player goes to bed.
 

xj47

Member
Nov 4, 2017
235
383
I agree with hiya that you should use some sort of organized data structure to store the quest info. A dictionary object for example.

However if you want to literally check variable names (which I wouldn't recommend), you can do something like:

Python:
allComplete = True
for varName in dir(store):
    if varName.startswith("quest_5_") and varName.endswith("completed"):
        if not getattr(store,varName):
            allComplete = False
            break
In renpy the "store" object holds all variables. When you write if someVar == 1: in code, usually that's equivalent to if store.someVar == 1:

The python function dir(x) returns the list of attributes an object has as strings. So dir(store) gives you a list of game variables.

Finally you can use getattr(containerObj,varName) and setattr(containerObj,varName,value) to get & set attributes using string keys. ie. getattr(containerObj,"someVar") == containerObj.someVar
 
  • Like
Reactions: SecretSal

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,131
14,810
the status of those is saved by $ quest_weeknumber_location_active = "True"/"false" and $ quest_weeknumber_location_completed = "True"/"False". I know using strings isnt necesary but had some issues bla bla bla.
I really wonder what issues you could have had that make the use of strings instead of True/False less risked.
Half of the time you'll forget to put the first letter in uppercase and will end with a totally broken game. And like you'll have to explicitly test the value, the error will happen both when you assign the value, and when you test it.


but the problem with that is that that would mean writing down all possible quest variables in that script. is there another way to go about this? maybe have the script check every variable that starts with $quest_weeknumber or something like that?
I pass on the "omfg what over complicated game mechanism", to just answer the question:
Code:
define questsList = [ "quest_1", "quest_2", [...], "quest_3" ]

label dayEnd:
    python:
        for i in questList:
            if not hasattr( store, i ): continue
            if getattr( store, i ) is "False":
                say( narrator, "quest unfinished" )
                setattr( store, i ) = "True"

The python function dir(x) returns the list of attributes an object has as strings. So dir(store) gives you a list of game variables.
As well as the list of the exported core variables, functions, classes and a lot of totally useless information. For an empty unstarted game, dir already return a list of more than 600 attributes, all totally useless. And the list will grow over the time. If really you want to follow this logic, it's the renpy.python.store_dicts["store"].ever_been_changed set that should be iterated.
 
Sep 10, 2017
50
49
I agree with hiya that you should use some sort of organized data structure to store the quest info. A dictionary object for example.

However if you want to literally check variable names (which I wouldn't recommend), you can do something like:

Python:
allComplete = True
for varName in dir(store):
    if varName.startswith("quest_5_") and varName.endswith("completed"):
        if not getattr(store,varName):
            allComplete = False
            break
In renpy the "store" object holds all variables. When you write if someVar == 1: in code, usually that's equivalent to if store.someVar == 1:

The python function dir(x) returns the list of attributes an object has as strings. So dir(store) gives you a list of game variables.

Finally you can use getattr(containerObj,varName) and setattr(containerObj,varName,value) to get & set attributes using string keys. ie. getattr(containerObj,"someVar") == containerObj.someVar
thanks, this really helps out alot. I had no idea that storing was a thing. I had like 3 to 4 online classes in python. so I am definitely going to look into that
 
Sep 10, 2017
50
49
Small adaptation to previous post. I guess you have some story section then free roam and then again story section. Each free roam section will have some required number/list of side quests which needs to be completed.
I would define this list of side quests per free roam section and create listener that whenever a quest is completed then it is removed from that list. After that you can only check if that list is empty or not whenever the player goes to bed.
yeah just about right. the way everything is split up for this part of the game is that it is split up in main plot (scripted content) and free roam. every free roam section would have ppl you can talk to and do quests for, which give points to that character and change things like background renders, that girls corruption etc. after the first scripted part you get 5 free roam weeks, then the next scripted part of the game is triggered. yeh its complicated. but with some help I can definitely get it done. thanks for your help!
 
Sep 10, 2017
50
49
I really wonder what issues you could have had that make the use of strings instead of True/False less risked.
Half of the time you'll forget to put the first letter in uppercase and will end with a totally broken game. And like you'll have to explicitly test the value, the error will happen both when you assign the value, and when you test it.




I pass on the "omfg what over complicated game mechanism", to just answer the question:
Code:
define questsList = [ "quest_1", "quest_2", [...], "quest_3" ]

label dayEnd:
    python:
        for i in questList:
            if not hasattr( store, i ): continue
            if getattr( store, i ) is "False":
                say( narrator, "quest unfinished" )
                setattr( store, i ) = "True"



As well as the list of the exported core variables, functions, classes and a lot of totally useless information. For an empty unstarted game, dir already return a list of more than 600 attributes, all totally useless. And the list will grow over the time. If really you want to follow this logic, it's the renpy.python.store_dicts["store"].ever_been_changed set that should be iterated.
thank you so much for the code. this really helps me along