Inventory Screen

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Message
Author
User avatar
AsHLeX
Miko-Class Veteran
Posts: 556
Joined: Wed Dec 25, 2013 1:09 pm
Completed: Starlight Dreamers, Mysterious Melody, Town of Memories, Marked, To Fly, The Change, Him From The Past, A Forgotten Memory
Projects: Cafe Mysteria
Location: Malaysia
Contact:

Re: Inventory Screen

#46 Post by AsHLeX »

Okay, thanks!!! :D

User avatar
Discostar
Regular
Posts: 40
Joined: Mon Mar 10, 2014 10:29 am
Contact:

Re: Inventory Screen

#47 Post by Discostar »

Any tips for making the combine button visible only if the selected items are in the recipe?

I'm throwing all kinds of if statements at it, but I'm not getting the result I want.

darklily429
Newbie
Posts: 9
Joined: Sat Jan 21, 2012 10:06 am
Contact:

Re: Inventory Screen

#48 Post by darklily429 »

First of all I want to say thank you so much for putting this up!
I've been tearing my hair out trying to figure out how to get my inventory to work and this has made it so much easier! :D

I do have a couple of questions though that hopefully someone might be able to help me with:

1) I have a side image that is constantly on display that shows the statistics, etc. Is there a way to make the image of the selected item to show up on this sidebar as well?
(I've attached a quick picture to clarify what I mean :) )
question1.png
2) At the moment I have three buttons: hair accessories, clothes and shoes. Is there a way to organise the items so they will show up in different screens? I was hoping that, for example, when I click on the hair accessory button only the items that have to do with hair will pop up. Or would I need to create a new "inventory" for each screen?

3) Is it possible to add a statistics boost to the items the way you added a hp boost? So if, for example, I equip that hair accessory, my character will get +3 charisma and +3 cuteness. I've got my statistics defined as "$ CHA = 0 #Charisma" and so on at the moment in case that changes things...

Sorry if they're really simple questions but I haven't got much experience when it comes to Ren'Py ^^'

paviro
Newbie
Posts: 3
Joined: Tue Sep 08, 2015 6:07 pm
Contact:

Re: Inventory Screen

#49 Post by paviro »

Hi leon,
I am trying to use your inventory in my game (Thank your for sharing it!) but I am having a bit of a problem...
I want to create a point and click adventure game and therefore need the possibility to click on an item displayed on screen to add it to the inventory.

My item looks like this, when clicked it gets removed and theoretically added to the inventory:

Code: Select all

screen item_test1:
        imagebutton auto "images/test_button_%s.png" action [ Hide("item_test1"), inventory.add(stone)] align (.52,.58)
The only problem is as long as the imagebutton is visible endless stone's get picked up without ever pressing on it, any idea? Another interesting thing is when selecting one of the stones in the inventory, all of them get selected and they only get more when you open the inventory; leaving it closed and then picking up the item always results in them being there three times.

EDIT: Figured it out myself. Sometimes reading more docs helps :D

Code: Select all

Function(inventory.add, stone)

User avatar
Bartulisica
Regular
Posts: 93
Joined: Sun Aug 30, 2015 5:11 am
Organization: ArizonaIdentities
Location: Croatia
Discord: ArizonaIdentities
Contact:

Re: Inventory Screen

#50 Post by Bartulisica »

Excellent code, helped so much for understanding inventory screen.

But, could you please direct me to the part of the script that organizes displayed items.
For example if I have 3 items in my inv, and get another one, I want new item to come first, and the rest of them moved to the next inv spaces.

EDIT: Nevermind, I got it!
- ArizonaIdentities

dragonlord3989
Regular
Posts: 30
Joined: Tue Nov 17, 2015 1:34 pm
Contact:

Re: Inventory Screen

#51 Post by dragonlord3989 »

Hi when I try and click combine it get this error log

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 221, in script
    s"O hello there"
  File "renpy/common/00action_other.rpy", line 430, in __call__
    rv = self.callable(*self.args, **self.kwargs)
  File "game/script.rpy", line 168, in combine_items
    if item in recipe and item.selected:
TypeError: argument of type 'Recipe' is not iterable
And this is my script

Code: Select all

init -1 python:
    import copy
    import renpy.store as store
    import renpy.exports as renpy # we need this so Ren'Py properly handles rollback with classes
    from operator import attrgetter # we need this for sorting items

    inv_page = 0 # initial page of teh inventory screen
    item = None
    class Player(renpy.store.object):
        def __init__(self, name, max_hp=0, max_mp=0, element=None):
            self.name=name
            self.max_hp=max_hp
            self.hp=max_hp
            self.max_mp=max_mp
            self.mp=max_mp
            self.element=element
    player = Player("Derp", 100, 50)
    
    class Item(store.object):
        def __init__(self, name, player=None, hp=0, mp=0, element="", image="", cost=0, recipeItem=False):
            self.selected=False
            self.recipeItem=recipeItem
            self.name = name
            self.player=player # which character can use this item?
            self.hp = hp # does this item restore hp?
            self.mp = mp # does this item restore mp?
            self.element=element # does this item change elemental damage?
            self.image=image # image file to use for this item
            self.cost=cost # how much does it cost in shops?
        def use(self): #here we define what should happen when we use the item
            if self.recipeItem:
                self.selected=not self.selected
            if self.name=="Chocolate":
                renpy.call_in_new_context("chocolate_event")
                
    class Inventory(store.object):
        def __init__(self, money=0):
            self.money = money
            self.items = []
        def add(self, item): # a simple method that adds an item; we could also add conditions here (like check if there is space in the inventory)
            self.items.append(item)
        def drop(self, item):
            self.items.remove(item)
        def buy(self, item):
            if self.money >= item.cost:
                self.items.append(item)
                self.money -= item.cost

    def item_use():
        item.use()

    class Recipe(store.object):
        def __init__(self, items=[], item_created=None):
            self.items = items
            self.item_created = item_created
        def combine_check(self):
            too_many=False # too many items selected?
            correct_recipe_items = copy.copy(self.items) # make a copy of the list of recipe items
            for item in inventory.selected_items:
                if item.recipeItem: # and item in self.items:
                    if item in correct_recipe_items:
                        correct_recipe_items.remove(item) # remove the current item from the list of correct_recipe_items; if correct_recipe_items is empty at the end, we have created the recipe
                    if not (item in self.items): # current item is not in this recipe
                        too_many=True
            if len(correct_recipe_items) == 0 and not too_many: # correct_recipe_items is empty means we have selecte just the right items
                inventory.add(self.item_created) # add the newly created item
                for drop_item in self.items: # remove all the items in this recipe from inventory
                    inventory.drop(drop_item)

    #Tooltips:
    style.tips_top = Style(style.default)
    #style.title.font="gui/arial.ttf"
    style.tips_top.size=14
    style.tips_top.color="fff"
    style.tips_top.outlines=[(3, "6b7eef", 0,0)]
    style.tips_top.kerning = 5

    style.tips_bottom = Style(style.tips_top)
    style.tips_top.size=20
    style.tips_bottom.outlines=[(0, "6b7eef", 1, 1), (0, "6b7eef", 2, 2)]
    style.tips_bottom.kerning = 2
    
    style.button.yminimum=52
    style.button.xminimum=52
    style.button_text.color="#1aff66"


    showitems = True #turn True to debug the inventory
    # def display_items_overlay():
        # if showitems:
            # inventory_show = "Money:" + str(inventory.money) + " HP: " + str(player.hp) + " bullets: " + str(player.mp) + " element: " + str(player.element) + "\nInventory: "
            # for i in range(0, len(inventory.items)):
                # item_name = inventory.items[i].name
                # if i > 0:
                    # inventory_show += ", "
                # inventory_show += item_name
            
            # ui.frame()
            # ui.text(inventory_show, color="#000")
    # config.overlay_functions.append(display_items_overlay)
    
screen inventory_button:
    textbutton "Show Inventory" action [ Show("inventory_screen"), Hide("inventory_button")] align (.5,.00)
            
screen inventory_screen:    
    add "gui/inventory.png" # the background
    textbutton "Combine" action [Function(combine_items), Hide("inventory_screen"), Show("inventory_button")] align (.80,.80)
    modal True #prevent clicking on other stuff when inventory is shown
    #use battle_frame(char=player, position=(.97,.20)) # we show characters stats (mp, hp) on the inv. screen
    #use battle_frame(char=dog, position=(.97,.50))
    hbox align (.95,.04) spacing 20:
        textbutton "Close Inventory" action [ Hide("inventory_screen"), Show("inventory_button"),]
    $ x = 515 # coordinates of the top left item position
    $ y = 25
    $ i = 0
    $ sorted_items = sorted(inventory.items, key=attrgetter('element'), reverse=True) # we sort the items, so non-consumable items that change elemental damage (guns) are listed first
    $ next_inv_page = inv_page + 1            
    if next_inv_page > int(len(inventory.items)/16):
        $ next_inv_page = 0
    for item in sorted_items:
        if i+1 <= (inv_page+1)*16 and i+1>inv_page*16:
            $ x += 150
            if i%4==0:
                $ y += 115
                $ x = 500
            $ pic = item.image
            $ my_tooltip = "tooltip_inventory_" + pic.replace("gui/inv_", "").replace(".png", "") # we use tooltips to describe what the item does.
            if item.recipeItem:
                imagebutton idle pic hover pic xpos x ypos y action [Hide("gui_tooltip"), SetVariable("item", item), item_use] hovered [ Play ("sound", "sfx/click.wav"), Show("gui_tooltip", my_picture=my_tooltip, my_tt_ypos=693) ] unhovered [Hide("gui_tooltip")] at inv_eff
            else:
                imagebutton idle pic hover pic xpos x ypos y action [Hide("gui_tooltip"), Show("inventory_button"), SetVariable("item", item), Hide("inventory_screen"), item_use] hovered [ Play ("sound", "sfx/click.wav"), Show("gui_tooltip", my_picture=my_tooltip, my_tt_ypos=693) ] unhovered [Hide("gui_tooltip")] at inv_eff
            if item.selected:
                add "gui/selected.png" xpos x ypos y anchor(.5,.5)
        $ i += 1
        if len(inventory.items)>9:
            textbutton _("Next Page") action [SetVariable('inv_page', next_inv_page), Show("inventory_screen")] xpos .475 ypos .90

screen gui_tooltip (my_picture="", my_tt_xpos=58, my_tt_ypos=687):
    add my_picture xpos my_tt_xpos ypos my_tt_ypos

init -1:
    transform inv_eff: # too lazy to make another version of each item, we just use ATL to make hovered items super bright
        zoom 0.5 xanchor 0.5 yanchor 0.5
        on idle:
            linear 0.2 alpha 1.0
        on hover:
            linear 0.2 alpha 2.5

    image information = Text("INFORMATION", style="tips_top")
    #Tooltips-inventory:
    image tooltip_inventory_chocolate=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("A delicious bar of chocolate, it makes a great gift.", style="tips_bottom"))
    image tooltip_inventory_banana=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("A healthy banana full of potassium! You can also use it as ammo for your guns! O.O Recharges 20 bullets.", style="tips_bottom"))
    image tooltip_inventory_gun=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("An gun that looks like something a cop would\ncarry around. Most effective on humans.", style="tips_bottom"))
    image tooltip_inventory_laser=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("An energy gun that shoots photon beams.\nMost effective on aliens.", style="tips_bottom"))

init python:   
    def combine_items():
        for recipe in recipes:
            recipe.combine_check()
        inventory.selected_items = []
        return

init python:   
    def combine_items():
        for item in inventory.items:
            for recipe in recipes:
                recipe_tmp = recipe
                if item in recipe and item.selected:
                    recipe_tmp.remove(item)
                    if len(recipe_tmp)==1:
                        for tmp_item in recipe:
                            pass
                            inventory.drop(item)
                        inventory.add(recipe[0])
        return
                
# Declare images below this line, using the image statement.
# eg. image eileen happy = "eileen_happy.png
# Declare characters used by this game.  
# The phrase in the brackets is the text that the game will display to prompt 
# the player to enter the name they've chosen.
label start:
    python:
        player = Player("Derp", 100, 50)
        player.hp = 50
        player.mp = 10
        chocolate = Item("Chocolate", 5, image="gui/inv_chocolate.png")
        banana = Item("Banana", mp=20, image="gui/inv_banana.png", recipeItem=True)    
        gun = Item("Gun", element="bullets", image="gui/inv_gun.png", cost=7, recipeItem=True)
        laser = Item("Laser Gun", element="laser", image="gui/inv_laser.png")
        inventory = Inventory()
        #add items to the initial inventory:
        inventory.add(banana)
        inventory.add(puffy)
        recipes = [Recipe([banana, chocolate], laser)]
        #recipes.append([laser, chocolate,banana]) 
I am a noob any help would be great.

User avatar
Aeries Vholt
Newbie
Posts: 2
Joined: Thu Jan 14, 2016 6:21 pm
Contact:

Re: Inventory Screen

#52 Post by Aeries Vholt »

I have no clue how to open the inventory file, any help?

User avatar
Aeries Vholt
Newbie
Posts: 2
Joined: Thu Jan 14, 2016 6:21 pm
Contact:

Re: Inventory Screen

#53 Post by Aeries Vholt »

Never mind I found out how to extract it!

User avatar
Bryy
Veteran
Posts: 407
Joined: Thu Dec 20, 2012 10:12 pm
Completed: 30+ games so far
Projects: Furry Shakespeare
Organization: Stegalosaurus Game Development
Location: Portage, MI
Contact:

Re: Inventory Screen

#54 Post by Bryy »

That looks fantastic.

User avatar
Discostar
Regular
Posts: 40
Joined: Mon Mar 10, 2014 10:29 am
Contact:

Re: Inventory Screen

#55 Post by Discostar »

I'm back! (^_^)v

The biggest issue I'm having with this is that all of the items are selectable.

If two items are not in the same recipe I want the selected idle images to disappear.
(ie the glow that tells you an item is selected...?)

I want a maximum of two items to be selectable at a time.

Code: Select all


No code posted because I'm not sure if this is an inventory screen issue, or a Function thing or what!  :( 

Tips please!

era27
Newbie
Posts: 6
Joined: Thu May 12, 2016 5:52 am
Contact:

Re: Inventory Screen

#56 Post by era27 »

Hello!

How can I use the player() class with a group of players?

Thanks

UselessCoder
Regular
Posts: 96
Joined: Sun Jan 24, 2016 6:51 am
Projects: undisclosed...
Contact:

Re: Inventory Screen

#57 Post by UselessCoder »

First of all, thanks for posting this demo. It was very useful to play around with it.

Now on with a little issue I had while "playing" with it. I didn't like the "next page" behaviour, more specifically I didn't like that it kept on cycling between pages without even changing its name into "prev page" or something like that...So I've tried to change it.

given that:

Code: Select all

init -1 python:

    inv_page = 0 # initial page of teh inventory screen
I've added a prev_page button:

Code: Select all

    $ next_inv_page = inv_page + 1
    $ prev_inv_page = inv_page -1 #my code
    if next_inv_page > int(len(inventory.items)/12):
        $ next_inv_page = 0
    if prev_inv_page < int(len(inventory.items)/12): #my code 
        $ prev_inv_page = 0
and of course, added the buttons accordingly:

Code: Select all

        if len(inventory.items)>12:
            textbutton _("Next Page") action [SetVariable('inv_page', next_inv_page), Show("inventory_screen")] xpos .475 ypos .83
            textbutton _("Prev Page") action [SetVariable('inv_page', prev_inv_page), Show("inventory_screen")] xpos .575 ypos .83
Now: the prev_page button works perfectly, but that was an easy call: since every page contains 12 items only, if the items are less than 12, it necessarily means that it has to go back until it gets to the initial page and stop.
The same (obviously) doesn't apply to next_button, which keeps on cycling between pages without stopping on the last page containing items (like I would, instead).

Any hints on how can I fix this "dynamic" page logic for the next_page button?
Thanks!

EDIT:
fixed that :P
I'm sure there must be a more code-friendly/good looking way to achieve this, but I simply fixed it by adding this condition:

Code: Select all

    if next_inv_page < int(len(inventory.items)/12):
        $ next_inv_page = 1 
so the next_page button will cycle forward until it gets to the last page containing items. I've posted it for the sake of helping someone as lost as I was. ;)

DyneWulf
Newbie
Posts: 11
Joined: Sat Jul 23, 2016 9:18 pm
Contact:

Re: Inventory Screen

#58 Post by DyneWulf »

I've been playing around with the code a bit, but I can't figure it out... Whenever you use an item, I'd like for it to jump back to the inventory screen instead of calling the screen to show the inventory button. How can I go about doing this?

I don't quite understand WHY it's going there. I'm using events based off the item used, so my defined code looks like this

Code: Select all

def use(self): #here we define what should happen when we use the item
            if self.name=="Hammer":
                renpy.call_in_new_context ('hammer_event')
## Seems that it hits this point, then calls back the inventory_button screen.

label hammer_event:
    
    "You dance around with the hammer"
    "Why?"
    "Nobody knows!"
    $ inventory.drop(hammer)
    return

From my understanding, when it hits return, it's jumping back to whatever should come after the call_in_new_context, but using the sample code provided, there's nothing there except for other elif/else statements about items used, and so far, all my attempts to make it jump back to the inventory screen properly have failed. I've gotten it to loop through the inventory before, but that's not quite right x3

User avatar
CCopper
Newbie
Posts: 11
Joined: Fri Sep 02, 2016 1:44 pm
Contact:

Re: Inventory Screen

#59 Post by CCopper »

So much to learn, but threads like this one helps so much. I really love then someone has asked a question, figured it out on there own, and updated their post with the answer. That's great for people like me that are so new to this program. Thanks

User avatar
Pomeranian
Regular
Posts: 33
Joined: Wed Oct 12, 2016 6:52 pm
Contact:

Re: Inventory Screen

#60 Post by Pomeranian »

EDIT: I asked a question here but I figured it out :D Great code, btw.

Post Reply

Who is online

Users browsing this forum: No registered users