[SOLVED] Conditional variable changes?

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
gummii_exe
Newbie
Posts: 13
Joined: Fri Jun 10, 2022 11:42 am
Contact:

[SOLVED] Conditional variable changes?

#1 Post by gummii_exe »

So in my game, I am trying to set for a character's description to change depending on the player's relationship to them. I have a seperate character screen where this change would be implemented, and I figured initially it would be as simple as putting an if, elif, and else statement for each value, but it doesn't seem to do anything. I have moments in my code where the players relationship with the character changes, but I am struggling to figure out how to set this change each time without having to copy and paste the if, elif, and else statements each time after the change. I'm sure there must be an easier way to do this, but I'm struggling to figure out how.
Here is my character class and character info, as well as the conditionals I'm trying to implement:

Code: Select all

init python:
    import renpy.store as store
    import renpy.exports as renpy

    class Chara(store.object):
        def __init__(self, name, pronouns, description, meet = False, affection = 0):
         #imageName = "",
            self.name = name
            self.pronouns = pronouns
            self.description = description
            #self.imageName = "characters/"+ imageName + ".png"
            self.meet = meet
            self.affection = affection
    class CharaList(store.object):
        def __init__(self):
            self.chara_list = []

        def metChara(self, chara):
            self.chara_list.append(chara)

        def removeChara(self, chara):
            self.chara_list.remove(chara)

        def hasChara(self, chara):
            if chara in self.chara_list:
                return True
            else:
                return False

default metCharacters = CharaList()
# characters
# add proper image names!! otherwise renpy will kick ur ass or smt idk
# example:
# default Name = Chara("name", "pronouns", "description", imageName = "")
default Player = Chara(persistent.player.upper(), "they/them", "It's you.", meet = True)
default Bug = Chara("BUG", "they/them", "Your glitchful guide to the Playgrounds.")
default Clown = Chara("JESTER", "he/him", "A temperamental fallen clown.")
default Creature = Chara("THING", "it/its", "It.. exists.")
default Theo = Chara("THEO", "he/they", "The first.")
default lostsouls = Chara("LOST SOULS", "it/they", "The wanderers of the Playgrounds.")
if lostsouls.affection <= 0:
    $lostsouls.description = "The children of the Playgrounds."
elif lostsouls.affection == 5:
    $lostsouls.description = "The playful spirits that roam the Playgrounds."
elif lostsouls.affection >= 10:
    $lostsouls.description = "They seem to like you."


default selectedCharacter = Player
And here is my character screen, in case the issue is something there:

Code: Select all

screen CharactersUI:
    tag charactersUI
    add "UI/moon.png"
    hbox:
        frame:
            style_prefix "characters"
            ysize 1080
            xsize 640
            vbox:
                xalign 0.5
                yalign 0.5
                textbutton _(Player.name):
                    action SetVariable("selectedCharacter", Player)
                    xsize 640
                if metCharacters.hasChara(lostsouls):
                    textbutton _(lostsouls.name):
                        action SetVariable("selectedCharacter", lostsouls)
                        xsize 640
                if metCharacters.hasChara(Bug):
                    textbutton _(Bug.name):
                        action SetVariable("selectedCharacter", Bug)
                        xsize 640
                if metCharacters.hasChara(Clown):
                    textbutton _(Clown.name):
                        action SetVariable("selectedCharacter", Clown)
                        xsize 640
                if metCharacters.hasChara(Creature):
                    textbutton _(Creature.name):
                        action SetVariable("selectedCharacter", Creature)
                        xsize 640
                if metCharacters.hasChara(Theo):
                    textbutton _(Theo.name):
                        action SetVariable("selectedCharacter", Theo)
                        xsize 640

            textbutton _("Return"):
                yalign 0.5
                yoffset 90
                xoffset 20
                action Return()
        ## Right frame
        ## Notice that we're using selectedCharacter to show the variables here.
        frame:
            ysize 1080
            xsize 1280
            vbox:
                xoffset 20
                yoffset 20
                text "Name: [selectedCharacter.name]"
                text "Pronouns: [selectedCharacter.pronouns]"
                text "Description: [selectedCharacter.description]"
Last edited by gummii_exe on Sun Jun 12, 2022 11:45 am, edited 1 time in total.

User avatar
zmook
Veteran
Posts: 421
Joined: Wed Aug 26, 2020 6:44 pm
Contact:

Re: Conditional variable changes?

#2 Post by zmook »

This chunk of code may never be executed:

Code: Select all

if lostsouls.affection <= 0:
    $lostsouls.description = "The children of the Playgrounds."
elif lostsouls.affection == 5:
    $lostsouls.description = "The playful spirits that roam the Playgrounds."
elif lostsouls.affection >= 10:
    $lostsouls.description = "They seem to like you."
I say "may" because it depends on what file it's in and whether runtime control flow ever happens to pass through it.

A key thing to understand in renpy scripts is what is executed at init time and what is done at runtime. This is poorly explained in the docs, but Ocelot gave a good summary the other day:

viewtopic.php?p=553018#p553018

The short version is that when it starts up your game, Renpy searches through all your scripts and runs *all* init, init python, image, define, default, transform, screen, style, and translate statements that it finds. And when you start playing, it calls label start: and then goes line by line from there.

So if you look at that first file, you have an init python and a bunch of defaults. Those are run when the game is being initialized. But the if/elif/else and $ statements are not, unless control eventually reaches them somehow after a jump or call or something.

So, you have to decide, when *do* you want the lostsouls descriptions to be updated? Maybe there's a logical place in your code to move that to, such as whenever lostsouls.affection gets updated. You could write a python function that does both, and call it when you want to increment affection.

Or you could put it in the screen CharactersUI, if that's the only place that uses lostsouls.description. You have to be a little careful about putting logic into screens because they get run repeatedly at unexpected times by renpy prediction, but with this particular logic it would be safe to run it repeatedly (nothing would change), so that would be okay.

Or you could subclass Chara for lostsouls in particular and replace .description with a @property that determines it dynamically whenever it's needed.
colin r
➔ if you're an artist and need a bit of help coding your game, feel free to send me a PM

gummii_exe
Newbie
Posts: 13
Joined: Fri Jun 10, 2022 11:42 am
Contact:

Re: Conditional variable changes?

#3 Post by gummii_exe »

zmook wrote: Sat Jun 11, 2022 10:19 pm Or you could subclass Chara for lostsouls in particular and replace .description with a @property that determines it dynamically whenever it's needed.
I temporarily solved the issue by making a label that contained the if elif and else statements which i could call anytime i changed lostsouls.affection, however this sound really fascinating to me as a semi-newbie to ren'py- I've been trying to find an explanation for properties and how I would go about this, but I'm struggling. Do you mind explaining how you would go about it?

User avatar
zmook
Veteran
Posts: 421
Joined: Wed Aug 26, 2020 6:44 pm
Contact:

Re: Conditional variable changes?

#4 Post by zmook »

gummii_exe wrote: Sun Jun 12, 2022 2:52 am this sound really fascinating to me as a semi-newbie to ren'py- I've been trying to find an explanation for properties and how I would go about this, but I'm struggling. Do you mind explaining how you would go about it?

Code: Select all

init python:
    class Chara(store.object):
        def __init__(self, name, pronouns, description, meet = False, affection = 0):
         #imageName = "",
            self.name = name
            self.pronouns = pronouns
            self.description = description
            #self.imageName = "characters/"+ imageName + ".png"
            self.meet = meet
            self.affection = affection
            
    
    # define a subclass of Chara that contains LostSouls-specific code. 
    # This might not be the usual recommended software-engineering pattern, but it works for simple
    # cases, and it's a good starting point for more complex designs if you eventually need them.
    class LostSouls(Chara):
    
        # since we're not doing anything that requires modifying init, we don't need to 
        # include this. but you could.
        # note that the "description" argument will end up getting passed to the setter
        # below
        # def __init__(self, name, pronouns, description, meet=False, affection=0):
        #    Chara.__init__(self, name, pronouns, description, meet, affection)
        
        @property
        def description(self):
            # lostsouls.description will call this, instead of just returning a field value
            rv = ""
            if self.affection <= 0:
                rv = "The children of the Playgrounds."
            elif self.affection == 5:
                rv = "The playful spirits that roam the Playgrounds."
            else:
                rv = "They seem to like you."
            return rv
            
        @description.setter
        def description(self, value):
            # I'm only including this because the base class tries to set a description
            # string, and I'm deliberately not making any changes to the base class. 
            # so we need to handle it: we will ignore whatever value gets set for LostSouls and use the 
            # values harcoded above instead
            # your design would be cleaner if you *did* make changes to both Chara and 
            # the subclass so you could avoid including this stub.
            # that's an extra-work-now for more-readable-code-later kind of tradeoff.
            pass
            
colin r
➔ if you're an artist and need a bit of help coding your game, feel free to send me a PM

gummii_exe
Newbie
Posts: 13
Joined: Fri Jun 10, 2022 11:42 am
Contact:

Re: Conditional variable changes?

#5 Post by gummii_exe »

zmook wrote: Sun Jun 12, 2022 9:38 am
gummii_exe wrote: Sun Jun 12, 2022 2:52 am this sound really fascinating to me as a semi-newbie to ren'py- I've been trying to find an explanation for properties and how I would go about this, but I'm struggling. Do you mind explaining how you would go about it?

Code: Select all

    class LostSouls(Chara):
        @property
        def description(self):
            # lostsouls.description will call this, instead of just returning a field value
            rv = ""
            if self.affection <= 0:
                rv = "The children of the Playgrounds."
            elif self.affection == 5:
                rv = "The playful spirits that roam the Playgrounds."
            else:
                rv = "They seem to like you."
            return rv
            
        @description.setter
        def description(self, value):
            pass
            
I input this code and switched the variables acoordingly, but it isn't changing the description when I change the affection- I'm using lostsouls.affection = number in my script to change the affection value so that the subclass property will be called, but that might not be right. I tested it in the console of renpy, and no matter what I changed lostsouls.affection to, it didn't change the description.

User avatar
zmook
Veteran
Posts: 421
Joined: Wed Aug 26, 2020 6:44 pm
Contact:

Re: Conditional variable changes?

#6 Post by zmook »

Just checking, did you instantiate lostsouls as a LostSouls instance?

Code: Select all

default lostsouls = LostSouls("LOST SOULS", "it/they", "")
And since it's created with 'default', it will be saved in save files, so you either have to start a new game or explicitly overwrite it when you load a game.

(If this is an already-published game with saves out in the wild, it's not worth messing around like this probably.)
colin r
➔ if you're an artist and need a bit of help coding your game, feel free to send me a PM

gummii_exe
Newbie
Posts: 13
Joined: Fri Jun 10, 2022 11:42 am
Contact:

Re: Conditional variable changes?

#7 Post by gummii_exe »

zmook wrote: Sun Jun 12, 2022 11:25 am Just checking, did you instantiate lostsouls as a LostSouls instance?

Code: Select all

default lostsouls = LostSouls("LOST SOULS", "it/they", "")
That fixed it!! Thank you so much- I'll definitely be referring back to this in the future, you explained it very well. :)

Post Reply

Who is online

Users browsing this forum: No registered users