Class instance variable not changing

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
Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Class instance variable not changing

#1 Post by Thundy »

Hey all. So i have a class for my dialogue system which is defined as follows.

Code: Select all

class DIALOGUE(object):
        def __init__(self, place, who, sTime, eTime, isActive, mood, menuText, func, repeatable, num):
            self.place = place
            self.who = who
            self.sTime = sTime
            self.eTime = eTime
            self.isActive = isActive
            self.mood = mood
            self.menuText = menuText
            self.func = func
            self.repeatable = repeatable
            self.num = num
The variables are fairly self explanatory but for clarity they are,
place = where the dialogue takes place
who = the character with whom the dialogue is
sTime = The time at which the dialogue becomes available
eTime = The time at which the dialogue becomes unavailable
isActive = master on / off switch
mood = not currently used
MenuText = The text which will appear on the choices screen to begin the dialogue
func = The label to call to start the dialogue
repeatable = Is the dialogue repeatable or a one off
num = How many times has the dialogue occured

Essentially each time the came loops it carries out a check to see if the dialogue is available, and if so, the dialogue is added to a menu so the player can start it.
the checks are as follows

Is it the right time of day for the Dialogue?

Code: Select all

@property
        def ACheck(self):
            global Date
            if self.sTime == "none":
                return True
            else:
                tHour,tMin = self.sTime.split(":")
                if tHour >= Date.Hour and tMin <= Date.Minute:
                    tHour,tMin = self.eTime.split(":")
                    if tHour < Date.Hour and tMin < Date.Minute:
                        return True
            return False
Is the participant for the dialogue the person that the player currently has selected?

Code: Select all

@property
        def BCheck(self):
            global Act
            if self.who == Act:
                return True
            else:
                return False
Is the player in the correct location for the dialogue?

Code: Select all

@property
        def CCheck(self):
            global Location
            if self.place == Location:
                return True
            if self.place == "none":
                return True
            return False
Is the dialogue repeatable, if so has it been read before?

Code: Select all

@property
        def DCheck(self):
            if self.repeatable:
                return True
            else:
                if self.num > 0:
                    return False
                else:
                    return True
Are all these checks true?

Code: Select all

@property
        def CanChat(self):
            if self.isActive and self.ACheck and self.BCheck and self.CCheck and self.DCheck:
                return True
            else:
                return False
Then start the dialogue

Code: Select all

def Do(self):
            self.num += 1
            renpy.call(self.func)
All of the above code is contained within an init python: block

Now for my problem

For some reason the CanChat property doesn't seem to be updating. On a dialogue where repeatable = False DCheck still returns True even though self.num is greater than 0. Anyone spot any reason why this might be happening?

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#2 Post by Thundy »

Forgive the bump. Would it be fair to assume that either my mistake is so monumentally simple that it doesn't warrant an answer, or that nobody else has a clue either?
PyTom wrote:The latter problem feels like it might be an issue with what object are saved. An object is only saved in Ren'Py if it's reachable from a variable that's changed after Ren'Py starts. So if you have:

Code: Select all

define foo = MyObject()

label start:
      $ foo.field += 1
That won't save, because foo has never changed.

Tom sent me this a while back about a different issue which may be the problem here too but I didn't really understand the explanation. This is one of the few parts of Python / RenPy that really trips me up

rames44
Veteran
Posts: 233
Joined: Sun May 29, 2016 4:38 pm
Contact:

Re: Class instance variable not changing

#3 Post by rames44 »

Well, you’ve provided the code for your class, but you haven’t shown how the instance that you’re using is created, nor how you’re updating it.

You said “On a dialogue where repeatable = False DCheck still returns True even though self.num is greater than 0.”

What are you doing? Calling “myDialog.Do()”? And then? How are confirming that self.num is, in fact, greater than zero zero and that repeatable is False?

What you might do is try creating some kind of debug screen or extra “say” statements that show the values of the attributes before and after. That might clue you in as to what’s going on. Also, is the @property indented as shown in your examples, or is that an artifact of the post? Have you tried indenting it to match the “def”?

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#4 Post by Thundy »

I use the console to check the values at varying stages of the process the list of inscances is created by parsing an xml file as follows. I know that the DCheck value is always returning True which shouldn't be happening

Code: Select all

Dialogues = []
    for j in Dialo:
        JPlace = j.find('Place').text
        JWho = j.find('Who').text
        JsTime = j.find('Start').text
        JeTime = j.find('End').text
        JMood = int(j.find('Mood').text)
        JText = j.find('Text').text
        JFunc = j.find('Func').text
        JRep = j.find('Rep').text
        if JRep == "True":
            Jrep = True
        else:
            Jrep = False
        Dialogues.append(DIALOGUE(JPlace, JWho, JsTime, JeTime, False, JMood, JText, JFunc, JRep, 0))
The method for creating the menu is as follows

Code: Select all

def TalkCheck():
    talks = []
    talks.append(("Nevermind.", "none"))
    for i, q in enumerate(Dialogues):
        if q.CanChat:
            talks.append((q.menuText,i))
    renpy.say(None, "", interact=False)
    talkchoice = renpy.display_menu(talks)
    if talkchoice <> "none":
        talkchoice = int(talkchoice)
        Dialogues[talkchoice].Do()
The decorators are indented correctly in my code, its just pasting them on the forum that made it look like that

philat
Eileen-Class Veteran
Posts: 1909
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Class instance variable not changing

#5 Post by philat »

It doesn't appear to be the class itself, so it's probably something in how you're initializing. AFAIK, Ren'py in general doesn't take kindly to instances being created outside of default. Hard to debug without being able to run it. *shrug*

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#6 Post by Thundy »

All the code I've posted so far is contained within the Init Python block. When the player clicks on an imagebutton DialogueOpen is set to True and Act is set to the name of a character The Ren'Py code then says:

Code: Select all

if DialogueOpen:
        python:
            DialogueOpen = False
            TalkCheck()
That's all the code for the system. After staring at it for 2 days I still cant figure out why the instance methods are returning weird values. The strangest thing about it is that the values seem correct until TalkCheck() is called at which point they seem to revert to values that don't make any sense.

There doesnt necessarily need to be a python block there but It does the same thing either way

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Class instance variable not changing

#7 Post by Remix »

Are you overloading __getattribute__ in your class?
If so, you'd want to determine if the attribute object supports __get__ and return that.

Does Do() differentiate between callable methods and properties? Does it or anything else address the properties as callables?

Realistically, without a slimmed down, working mini-script.rpy that showcases the problem, we're pretty much guessing wildly as we cannot see how the code fully operates from just a bunch of disjointed methods.

Could you get the parts you've highlighted semi functional in a script.rpy to help debug?
Frameworks & Scriptlets:

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#8 Post by Thundy »

Hi @Remix. I totally understand. It is asking a lot to get people to help with only half the picture. I'll upload the code to mega and PM a link. It's not a huge amount of code at the moment but it's the easiest way to get a complete picture of what I am seeing.

rames44
Veteran
Posts: 233
Joined: Sun May 29, 2016 4:38 pm
Contact:

Re: Class instance variable not changing

#9 Post by rames44 »

You said you were initializing everything in an init block. Is the problem with persisting across saves? Or is it a purely runtime issue? Unless you take steps to explicitly put stuff into “store”, I don’t think objects you create during the init phase are going to get pickled into your save. So things like your “num” may need special treatment if that is to be saved.

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#10 Post by Thundy »

rames44 wrote: Tue Sep 11, 2018 12:19 pm You said you were initializing everything in an init block. Is the problem with persisting across saves? Or is it a purely runtime issue? Unless you take steps to explicitly put stuff into “store”, I don’t think objects you create during the init phase are going to get pickled into your save. So things like your “num” may need special treatment if that is to be saved.
Hi Rames. I havent gotten as far as save games yet. This issue cropped up whilst i was still building the framework for the dialogue system which is one of the first things I started working on. It does feel like a data store issue but during runtime. The instance attributes seem to exist in two states, the correct one which they exist in most of the time, and then the wrong values which they seem to revert to when I try to access them with my TalkCheck() method.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Class instance variable not changing

#11 Post by trooper6 »

All variables should be declared outside of any block using default (if the variable will change) or define (if it won't).

So the definition of your class would be in the init python block, but the declaration of an instance of your dialogue class should be using default outside of a block. That may not be the cause of your problem, but it will cause a problem down the line.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#12 Post by Thundy »

trooper6 wrote: Tue Sep 11, 2018 6:03 pm All variables should be declared outside of any block using default (if the variable will change) or define (if it won't).

So the definition of your class would be in the init python block, but the declaration of an instance of your dialogue class should be using default outside of a block. That may not be the cause of your problem, but it will cause a problem down the line.
Thanks. It's things like this which are still a bit new to me. I have moved the declarations into a label which is called inside start(). I know it is unrelated to my actual issue but what is the difference between my current method: i.e parsing the xml file into a list of instances without using the default statement and doing it with default? I always thought that default was only used if an instance was created with attributes missing, which would never be the case in my current method. I am happy to be corrected on this though as it is important to learn

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Class instance variable not changing

#13 Post by trooper6 »

As I said, declarations should be outside of all blocks and labels.

Code: Select all

default money = 0

label start:
    "Game starts."
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#14 Post by Thundy »

Thanks. Have implemented it for the non xml parsed variables. Circling back to my issue the thing that is causing me so much headache is that the variables being fed into the RepCheck method are correct, but the method returns True anyway which is just plain odd.

Thundy
Regular
Posts: 88
Joined: Tue Dec 05, 2017 9:08 am
Contact:

Re: Class instance variable not changing

#15 Post by Thundy »

Ok so my less than elegant solution was to create two lists called is_repeatable and is_repeated.

so the class now looks like this

Code: Select all

    class DIALOGUE(object):
        def __init__(self, place, who, sTime, eTime, isActive, mood, menuText, func, repeatable, times_viewed, ID):
            global is_repeatable
            global is_repeated
            self.place = place
            self.who = who
            self.sTime = sTime
            self.eTime = eTime
            self.isActive = isActive
            self.mood = mood
            self.menuText = menuText
            self.func = func
            self.repeatable = repeatable
            self.times_viewed = times_viewed
            self.ID = ID
            is_repeatable.append(repeatable)
            is_repeated.append(False)
        def Do(self):
            global is_repeated
            XR = self.ID
            is_repeated[XR] = True
            self.times_viewed += 1
            renpy.call(self.func)

        def SetActive(self):
            self.isActive = True

        @property
        def TimeCheck(self):
            global Date
            if self.sTime == "none":
                return True
            tHour,tMin = self.sTime.split(':')
            eHour,eMin = self.eTime.split(':')
            tHour = int(tHour)
            tMin = int(tMin)
            eHour = int(eHour)
            eMin = int(eMin)
            if (Date.Hour > tHour) or (Date.Hour == tHour and Date.Minute >= tMin):
                if (Date.Hour < eHour) or (eHour == Date.Hour and Date.Minute < eMin):
                    return True
            return False

        @property
        def WhoCheck(self):
            global Act
            if self.who == Act:
                return True
            return False

        @property
        def LocCheck(self):
            global Location
            if self.place == Location or self.place == "none":
                return True
            return False

        @property
        def RepCheck(self):
            if self.max_repeats == 0:
                if self.times_viewed > 0:
                    return False
            return True

        @property
        def CanChat(self):
            global is_repeatable
            global is_repeated
            XR = self.ID
            if not is_repeatable[XR]:
                if is_repeated[XR]:
                    return False
            if not self.RepCheck:
                print("Not RepCheck")
                return False
            if not self.isActive:
                print("Not isActive")
                return False
            if not self.TimeCheck:
                print("Not TimeCheck")
                return False
            if not self.WhoCheck:
                print("Not WhoCheck")
                return False
            if not self.LocCheck:
                print("Not LocCheck")
                return False
            return True
This produces the results I need although I would still like to keep investigating why the RepCheck method wasn't returning the correct value since there is no visible reason why it shouldn't have worked, at least not from a python perespective.

thanks to Remix for looking at the source code

Post Reply

Who is online

Users browsing this forum: Google [Bot]