Errors and Questions with Python Classes -- Trying to read character stats

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
User avatar
zirkkun
Newbie
Posts: 6
Joined: Fri Jan 25, 2019 11:02 pm
Projects: Undertale: Act to Flirt
Deviantart: zirkkun
Contact:

Errors and Questions with Python Classes -- Trying to read character stats

#1 Post by zirkkun »

Hello! I'm new to the forums, but I have been lurking them for a while for help. I recently have sprung a very specific issue that I'm just not quite sure how to fix. Additionally, I'm still not all that advanced in Python coding, since a couple of very basic, mostly unfinished visual novels are the bulk of my experience up until very recently.

Recently, I've been trying to add RPG aspects to my game. Currently, I'm making a test code with filler assets and am having difficulty in creating a "party" option that's frequently available in RPG's. I'm not quite sure if the rest of my coding is working outside of the party option, since its error is barricading the rest of it from working to be tested, but based on the fact that the guide I based it off of worked fine, I assume it's fine?

The main problem is I want Ren'Py to be able to read the stats of a character based off of their location in the party as opposed to the character directly, so that way the same character can be moved from slot 1 to slot 2 by the player while retaining the same information. Currently, to the shortest possible extent I could make it, this is the failing code I have.

Code: Select all

init python:

    class EnemyChar:
        def __init__(self, hp, sp, atk, dfn, int, res, spd, level=1, char=""):
            self.char = char
            self.hp = hp
            self.max_hp = hp
            self.sp = sp
            self.max_sp = sp
            self.atk = atk
            self.dfn = dfn
            self.int = int
            self.res = res
            self.spd = spd
            self.level = level
            self.hand = {"right": None, "left": None}
            self.acc = {"neck": None, "arm": None}
            self.armor = {"head": None, "chest": None}

    class PlayChar:
        def __init__(self, hp, sp, atk, dfn, int, res, spd, level=1, char="", job=""):
            self.char = char
            self.job = job
            self.hp = hp
            self.max_hp = hp
            self.sp = sp
            self.max_sp = sp
            self.atk = atk
            self.dfn = dfn
            self.int = int
            self.res = res
            self.spd = spd
            self.level = level
            self.hand = {"right": None, "left": None}
            self.acc = {"neck": None, "arm": None}
            self.armor = {"head": None, "chest": None}
            
    class Party:
        def __init__(self):
            self.place = {"one": None, "two": None, "three": None, "four": None}

define corrin = Character("Corrin")
default corr = EnemyChar(19,12,3,8,5,6,6,1,char="Corrin")

define azura = Character("Azura")
default azu = EnemyChar(18,16,4,4,1,6,7,1,char="Azura")

define robin = Character("Robin", image="robin")
default robi = PlayChar(18,15,1,7,7,7,6,1,char="Robin",job="Mage")

define lucina = Character("Lucina (Not Marth)", image="lucina")
default luci = PlayChar(19,13,8,6,0,4,10,1,char="Lucina",job="Mercenary")

define party = Party()
default party.place = {"one": robi, "two": luci}

define enemy = Party()
default enemy.place = {"one": corr, "two": azu}
       
label start:
        if party.place["two"].spd >= ['[enemy.place["one"].spd]','[enemy.place["two"].spd]','[enemy.place["three"].spd]','[enemy.place["four"].spd]','[party.place["one"].spd]','[party.place["three"].spd]','[party.place["four"].spd]']:
            menu battlelist2:
                "What will [party.place['two'].char] do?"
                "Attack":
                    $ d20roll = renpy.random.randint(1, 20)
                    if ([enemy.place["one"]],[enemy.place["two"]]) != None:
                        menu:
                            "Who will [party.place['two'].char] attack?"
                            "[enemy.place['one'].char]":
                                if d20roll >= 20:
                                    $ damage = math.ceil((party.place["two"].atk - enemy.place["one"].dfn)*2)
                                else:
                                    $ damage = math.ceil(party.place["two"].atk - enemy.place["one"].dfn)
                                $ enemy.place["one"].hp -= damage                            
                            "[enemy.place['two'].char]":
                                if d20roll >= 20:
                                    $ damage = math.ceil((party.place["two"].atk - enemy.place["two"].dfn)*2)
                                else:
                                    $ damage = math.ceil(party.place["two"].atk - enemy.place["two"].dfn)
                                $ enemy.place["two"].hp -= damage
                    if [enemy.place["one"]] != None:
                        menu:
                            "Who will [party.place['two'].char] attack?"
                            "[enemy.place['one'].char]":
                                if d20roll >= 20:
                                    $ damage = math.ceil((party.place["two"].atk - enemy.place["one"].dfn)*2)
                                else:
                                    $ damage = math.ceil(party.place["two"].atk - enemy.place["one"].dfn)
                                $ enemy.place["one"].hp -= damage
                    "Dealt [damage] damage."
                    if enemy.place["one"].hp < 0:
                        $ enemy.place["one"].hp = 0
                    if enemy.place["two"].hp < 0:
                        $ enemy.place["two"].hp = 0
                    if [[enemy.place["one"].hp],[enemy.place["two"].hp]] == 0:
                        jump battle_1_ending
                        
label battle_1_ending:
    "The end."
    return    
It's a bit long still, unfortunately, and I apologize if my inexperienced coding makes that an absolute pain to read. Nevertheless, the biggest issue I'm sure the code has is the ones in this format:

Code: Select all

enemy.place["one"].dfn 
Clearly, this doesn't work, as something to this extent (the failing code is slightly different in this traceback, since I hoped it was a formatting error, but it's essentially the same problem):

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 265, in script
    if [party.place["one"]].spd > ['[[enemy.place["one"]].spd]','[[enemy.place["two"]].spd]','[[enemy.place["three"]].spd]','[[enemy.place["four"]].spd]','[[party.place["two"]].spd]','[[party.place["three"].spd]]','[[party.place["four"]].spd]']:
  File "game/script.rpy", line 265, in <module>
    if [party.place["one"]].spd > ['[[enemy.place["one"]].spd]','[[enemy.place["two"]].spd]','[[enemy.place["three"]].spd]','[[enemy.place["four"]].spd]','[[party.place["two"]].spd]','[[party.place["three"].spd]]','[[party.place["four"]].spd]']:
AttributeError: 'RevertableList' object has no attribute 'spd'

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 265, in script
    if [party.place["one"]].spd > ['[[enemy.place["one"]].spd]','[[enemy.place["two"]].spd]','[[enemy.place["three"]].spd]','[[enemy.place["four"]].spd]','[[party.place["two"]].spd]','[[party.place["three"].spd]]','[[party.place["four"]].spd]']:
  File "C:\Users\name\Desktop\Renpy\renpy-7.1.3-sdk\renpy\ast.py", line 1762, in execute
    if renpy.python.py_eval(condition):
  File "C:\Users\name\Desktop\Renpy\renpy-7.1.3-sdk\renpy\python.py", line 1944, in py_eval
    return py_eval_bytecode(code, globals, locals)
  File "C:\Users\name\Desktop\Renpy\renpy-7.1.3-sdk\renpy\python.py", line 1937, in py_eval_bytecode
    return eval(bytecode, globals, locals)
  File "game/script.rpy", line 265, in <module>
    if [party.place["one"]].spd > ['[[enemy.place["one"]].spd]','[[enemy.place["two"]].spd]','[[enemy.place["three"]].spd]','[[enemy.place["four"]].spd]','[[party.place["two"]].spd]','[[party.place["three"].spd]]','[[party.place["four"]].spd]']:
AttributeError: 'RevertableList' object has no attribute 'spd'

Windows-8-6.2.9200
Ren'Py 7.1.3.1092
test rpg 1.0
Fri Jan 25 20:52:35 2019]
Is there a better way to have the code written so Ren'Py can read it properly? I'm assuming that because the "Party" class itself doesn't have any of the stats associated with the "PlayChar" class, it is unable to connect the two even though what is associated with the "place" part is a character with associated stats.

Is there a way I can have the associated stats be pulled up from the character in the associated party slot without having to specifically write what character is in that slot a thousand times based on where the player places them?

Thank you in advance to anyone willing to read through this and help me. I hope my question isn't too difficult to understand. I'm willing to clarify anything if it is.

User avatar
Kia
Eileen-Class Veteran
Posts: 1040
Joined: Fri Aug 01, 2014 7:49 am
Deviantart: KiaAzad
Discord: Kia#6810
Contact:

Re: Errors and Questions with Python Classes -- Trying to read character stats

#2 Post by Kia »

the easier way is to add you'r players / enemies to lists and give the list to a loop to place your characters on the screen

Code: Select all

default enemy = [corr, robi, azu]
for i in enemy:
	if i.spd:
		the code for enemies...
And I would suggest using screens instead. should be easier to create a combat scenario that you can call at any time

Post Reply

Who is online

Users browsing this forum: Google [Bot], Ocelot