Adding 'tags' to objects in my Inventory ...

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
danasavage
Newbie
Posts: 9
Joined: Thu Jun 11, 2020 9:28 am
Projects: Girl Games
Contact:

Adding 'tags' to objects in my Inventory ...

#1 Post by danasavage »

Hi everyone! It's my first post - sorry it's a question! But I'm hoping somebody might be able to help me while I still have a few strands of hair left on my head.

So, I've been porting a Twine game over to Ren'py and for the most part it's been pretty seamless. But I've hit a bit of a snag. I had a system back in the old version of the game where I could open up the player wardrobe, click on an item and - under the hood - Twine would cycle through each 'tag' attached to that item and then place it on the player, removing any clothing items with the same tag. So like, a t-shirt would have the tag "torso" attached to it. And if i clicked the button and put the new tee on the player, the one they were wearing would automatically switch over to the wardrobe. Make sense? (I should also mention here that somebody else was very kind and wrote me the code for the Twine/javascript version)

So here's where I'm at with Ren'py: I've implemented some kind of frankenstein's monster cross between Saguaro's inventory and the Dynamic Dressup Framework by Pippin123 and with a few days crash course in Python I feel like I can just about get my head around what's happening. Only thing is, I'm stuck at the point where I would add my extra 'tags' onto my object.

Here's my code so far:

Code: Select all

init python:
    import renpy.store as store


    class Clothing(store.object):
        def __init__(self,name,desc):
            self.name = name
            self.desc = desc
            self.place = []


    class Inventory(store.object):
        def __init__(self, name):
            self.name=name
            self.wearing=[]

        def remove(self,clothes):
            if clothes in self.wearing:
                self.wearing.remove(clothes)
            return

        def wear(self,clothes):
            self.wearing.append(clothes)
            return

        def remove_all(self):
            list = [item for item in self.wearing]
            if list!=[]:
                for item in list:
                    self.wearing.remove(item)
            return

    def trade(seller, buyer, item):
        seller.remove(item)
        buyer.wear(item)


screen inventory_screen():
    zorder 60
    modal False
    frame:
        style_group "invstyle"
        area (0, 0, 440, 520)
        xalign 0.5 yalign 0.5 xpos 430 ypos 116
        hbox:
            spacing 25
            vbox:
                text "{font=GreatVibes-Regular.ttf}{color=#ff00da}{size=50}Wardrobe{/size}{/color}{/font}{vspace=5}"
                text "{u}Your wardrobe contains{/u}:\n"
                if len(wardrobe_inv.wearing) == 0:
                    text "Nothing"
                else:
                    for item in wardrobe_inv.wearing:
                        $ name = item.desc
                        textbutton ("[name]") action(Function(trade,wardrobe_inv, player_inv, item))

                text "\n\n{u}You are wearing{/u}:\n"
                if len(player_inv.wearing) == 0:
                    text "Nothing"
                else:
                    for item in player_inv.wearing:
                        $ name = item.desc
                        textbutton ("[name]") action(Function(trade,player_inv, wardrobe_inv, item))
                        
                        
                        
label start:

    $ cookbook = list()

    $ player_inv = Inventory("Player")
    $ wardrobe_inv = Inventory("Wardrobe")

    $ jeans = Clothing(name="Jeans", desc="blue jeans", place=["legs"])
    $ tshirt = Clothing(name="T-shirt", desc="white tee", place=["torso"])
    $ boxers = Clothing(name="Boxer shorts", desc="white boxer shorts", place=["crotch"])

    $ socks = Clothing(name="Socks", desc="sports socks", place=["shins"])
    $ sneakers = Clothing(name="Sneakers", desc="beat up old sneakers", place=["feet"])

    $ towel = Clothing(name="Towel", desc="a basic towel", place=["torso", "chest", "legs", "crotch", "shins", "feet"]) ##this is intended to have a bunch of tags! it's so that it will force all other clothing the player might be wearing to the wardrobe when they put it on!
  



Everything was going swimmingly until I introduced those "Place" tags. I did some reading up on Python, objects, classes, lists, etc, and I thought I could add self.place = [] to my Clothing object, but when I run the game now that's added, I get back:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 30, in script
    $ jeans = Clothing(name="Jeans", desc="blue jeans", place=["legs"])
  File "game/script.rpy", line 30, in <module>
    $ jeans = Clothing(name="Jeans", desc="blue jeans", place=["legs"])
TypeError: __init__() got an unexpected keyword argument 'place'

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

Full traceback:
  File "game/script.rpy", line 30, in script
    $ jeans = Clothing(name="Jeans", desc="blue jeans", place=["legs"])
  File "/Renpy/renpy-7.3.5-sdk/renpy/ast.py", line 914, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "/Renpy/renpy-7.3.5-sdk/renpy/python.py", line 2028, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/script.rpy", line 30, in <module>
    $ jeans = Clothing(name="Jeans", desc="blue jeans", place=["legs"])
TypeError: __init__() got an unexpected keyword argument 'place'

Ren'Py 7.3.5.606
(Fyi, I tried each tag both in and out of quotes, too - so place=[legs,shins,chest,etc] but that also came back with the same error ...)

EDIT: I think I have solved the above part of the problem on my own!!!! I realized I hadn't added place to my Clothing object - so:

Code: Select all

class Clothing(store.object):
        def __init__(self,name,desc, PLACE!!!):
            self.name = name
            self.desc = desc
            self.place = [] 

So hooray - now this actually seems to "work" in the sense that I'm no longer getting that initial error back. BUT Im still unsure how to add more than one tag to place ...

($ towel = Clothing(name="Towel", desc="a basic towel", place="torso","feet","shins") <-- this last part with the multiple 'tags' returns a new error (non keword arg after keyword arg) but hey ho, one step closer i guess ...

And obviously even if i could figure this latest piece of the puzzle out, i'm still unsure how to actually use the tags to do exactly what I want!

Just to be totally clear on what I am after, here's the working "widget" from my old Twine version, which gives a pretty clear idea of what I'd like to make happen:

Code: Select all

<<widget "PlayerCheck">>
<<set _tags = UInv.GetItemPropertyValue("player", _item, "place")>> /* This first line gets the item's place tags */
				<<for _tag range _tags>>
	<<run UInv.MoveItemsByItemTag("player", "wardrobe", "place", _tag)>>
<</for>> /* Then the loop then goes through each tag, and moves any items the player is wearing with a matching tag to the wardrobe.*/
<<run UInv.MoveItem("wardrobe", "player", _item, 1)>>
/*Then finally it moves the item from the wardrobe to the player */
<</widget>>

and my old inventory items were pretty similarly structured too ...

Items.socks = { place : ["shins"], description: "white sports socks" };
			
Items.sneakers = { place : ["feet"], description: "beat up old sneakers" };
			
Items.towel = { place : ["torso", "legs", "chest", "crotch", "shins", "feet"], description: "a towel" };


Looking at the old Twine code and items and the new Python inventory stuff, it gives me hope that this MUST be possible somehow, right?! Unfortunately I'm just not advanced enough in Python yet to figure this out on my own ... So this is where you come in!
Fingers crossed there's a way to implement something my old system in my Ren'py version! And thanks in advance. Hopefully at some point I'll be able to help out on solving someone else's dilemma too! :)

User avatar
Milkymalk
Miko-Class Veteran
Posts: 754
Joined: Wed Nov 23, 2011 5:30 pm
Completed: Don't Look (AGS game)
Projects: KANPEKI! ★Perfect Play★
Organization: Crappy White Wings
Location: Germany
Contact:

Re: Adding 'tags' to objects in my Inventory ...

#2 Post by Milkymalk »

variable = ["hat"] means it is a list. With variable.append("socks"), you can add more elements to the list, or you make it variable = ["hat", "socks", "shirt"] from the beginning. Basically the same as in Twine, just minor changes to syntax.
Crappy White Wings (currently quite inactive)
Working on: KANPEKI!
(On Hold: New Eden, Imperial Sea, Pure Light)

danasavage
Newbie
Posts: 9
Joined: Thu Jun 11, 2020 9:28 am
Projects: Girl Games
Contact:

#3 Post by danasavage »

THank you so much for your speedy reply but Im afraid I'm still a little confused - If you hadnt guessed from my huge wall of text, I've kinda gotten myself into rather a muddle with all this!

Maybe I should just try and clarify with a couple of small bonus questions:

Are you suggesting that I need to "append" my tags to my main Clothing object (below) somehow? (And if so, I'm not quite sure how!)

Code: Select all

class Clothing(store.object):
        def __init__(self,name,desc, place):
            self.name = name
            self.desc = desc
            self.place = [] <-- is this incorrect? 
or i'm guessing to the actual items? but currently an item like:

Code: Select all

 $ towel = Clothing(name="Towel", desc="a basic towel", place=["torso", "chest", "legs", "crotch", "shins", "feet"]) 
returns an error of "non keword arg after keyword arg" ... even though this seems to be what you are suggesting?

Or ... WAIT. Are you suggesting I do something like this:


Code: Select all

class Clothing(store.object):
        def __init__(self,name,desc, place):
            self.name = name
            self.desc = desc
            self.place = place
            place = [] <-- thus turning place into a variable that I could then put my 'tags' into?
            

EDIT: Ha ha, awesome. Yes this seems to work! Thank you so much!! So now I (hopefully) have a working way of adding the "tags" to my place variable.

Which brings us to the second part of what I want to do - create a function somehow which does the following:

1) whenever an item in the wardrobe is selected, its "place" tags are first noted
2) then any item of clothing the player is currently wearing with those same matching tags is moved to the wardrobe
3) finally the new item is moved onto the player

I'm guessing some digging around in the documentation of Python lists and their various functions is where I'm headed next! But if anyone knows how to save me a few hours of headaches (and most likely another post or two on here) then please do feel free to chip in!

And thank you again to Milkymalk for bringing me one step closer to the finish line! :)

Post Reply

Who is online

Users browsing this forum: Google [Bot], Lucyper, MisterPinetree