Page 3 of 6

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Tue May 17, 2016 7:59 am
by saguaro
Updated for Ren'py 6.99.10, see first post.

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Wed May 18, 2016 9:10 am
by Donmai
Thank you so much, my favourite cactus :) .

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Thu May 19, 2016 6:32 am
by saguaro
You're welcome, my favorite Donmai. :wink:

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Sat May 21, 2016 7:08 pm
by Heiden
Thank you so so so much for this!!!!!

I was looking through it, and it seems like I keep running into an error when I try looking at my inventory at the end of the demo.

Specifically I get the error:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 101, in script
    $ renpy.pause()
  File "game/script.rpy", line 101, in <module>
    $ renpy.pause()
Exception: Required parameter first_inventory has no value.

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

Full traceback:
  File "game/script.rpy", line 101, in script
    $ renpy.pause()
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ast.py", line 806, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\python.py", line 1577, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/script.rpy", line 101, in <module>
    $ renpy.pause()
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\exports.py", line 1254, in pause
    rv = renpy.ui.interact(mouse='pause', type='pause', roll_forward=roll_forward)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ui.py", line 277, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 2425, in interact
    repeat, rv = self.interact_core(preloads=preloads, **kwargs)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 2693, in interact_core
    root_widget.visit_all(lambda i : i.per_interact())
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 396, in visit_all
    d.visit_all(callback)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 396, in visit_all
    d.visit_all(callback)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 396, in visit_all
    d.visit_all(callback)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\screen.py", line 386, in visit_all
    callback(self)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 2693, in <lambda>
    root_widget.visit_all(lambda i : i.per_interact())
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\screen.py", line 396, in per_interact
    self.update()
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\screen.py", line 565, in update
    self.screen.function(**self.scope)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ast.py", line 149, in apply_arguments
    return parameters.apply(args, kwargs, ignore_errors)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ast.py", line 118, in apply
    raise Exception("Required parameter %s has no value." % name)
Exception: Required parameter first_inventory has no value.

Windows-8-6.2.9200
Ren'Py 6.99.10.1227
Inventory System 1.5
I am running Renpy 6.99.10.1227

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Sat May 21, 2016 9:15 pm
by saguaro
Oh, good catch, thank you! I forgot to update the Inventory button.

Line 131 should be:

Code: Select all

textbutton "Inventory" action Show("inventory_screen", first_inventory=jane_inv)

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Sat May 21, 2016 10:00 pm
by Heiden
It's half working! I'm able to open the inventory, but when I click on Crafting mode, I get-

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 101, in script
    $ renpy.pause()
  File "game/script.rpy", line 101, in <module>
    $ renpy.pause()
  File "game/inventory.rpy", line 147, in execute
    screen inventory_screen(first_inventory, second_inventory=False, trade_mode=False, bank_mode=False):
  File "game/inventory.rpy", line 147, in execute
    screen inventory_screen(first_inventory, second_inventory=False, trade_mode=False, bank_mode=False):
  File "game/inventory.rpy", line 151, in execute
    frame:
  File "game/inventory.rpy", line 153, in execute
    vbox:
  File "game/inventory.rpy", line 154, in execute
    hbox:
  File "game/inventory.rpy", line 156, in execute
    vbox:
  File "game/inventory.rpy", line 163, in execute
    if not second_inventory:
  File "game/inventory.rpy", line 165, in execute
    if crafting_screen:
  File "game/inventory.rpy", line 166, in execute
    use crafting(inventory)
  File "game/inventory.rpy", line 166, in <module>
    use crafting(inventory)
NameError: name 'inventory' is not defined

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

Full traceback:
  File "game/script.rpy", line 101, in script
    $ renpy.pause()
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ast.py", line 806, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\python.py", line 1577, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/script.rpy", line 101, in <module>
    $ renpy.pause()
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\exports.py", line 1254, in pause
    rv = renpy.ui.interact(mouse='pause', type='pause', roll_forward=roll_forward)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ui.py", line 277, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 2425, in interact
    repeat, rv = self.interact_core(preloads=preloads, **kwargs)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 2693, in interact_core
    root_widget.visit_all(lambda i : i.per_interact())
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 396, in visit_all
    d.visit_all(callback)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 396, in visit_all
    d.visit_all(callback)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 396, in visit_all
    d.visit_all(callback)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\screen.py", line 386, in visit_all
    callback(self)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\core.py", line 2693, in <lambda>
    root_widget.visit_all(lambda i : i.per_interact())
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\screen.py", line 396, in per_interact
    self.update()
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\display\screen.py", line 565, in update
    self.screen.function(**self.scope)
  File "game/inventory.rpy", line 147, in execute
    screen inventory_screen(first_inventory, second_inventory=False, trade_mode=False, bank_mode=False):
  File "game/inventory.rpy", line 147, in execute
    screen inventory_screen(first_inventory, second_inventory=False, trade_mode=False, bank_mode=False):
  File "game/inventory.rpy", line 151, in execute
    frame:
  File "game/inventory.rpy", line 153, in execute
    vbox:
  File "game/inventory.rpy", line 154, in execute
    hbox:
  File "game/inventory.rpy", line 156, in execute
    vbox:
  File "game/inventory.rpy", line 163, in execute
    if not second_inventory:
  File "game/inventory.rpy", line 165, in execute
    if crafting_screen:
  File "game/inventory.rpy", line 166, in execute
    use crafting(inventory)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\ast.py", line 181, in evaluate
    args.append(renpy.python.py_eval(v, locals=scope))
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\python.py", line 1606, in py_eval
    return py_eval_bytecode(code, globals, locals)
  File "C:\Users\NO\Pictures\Games\my game\renpy-6.18.3-sdk\renpy\python.py", line 1601, in py_eval_bytecode
    return eval(bytecode, globals, locals)
  File "game/inventory.rpy", line 166, in <module>
    use crafting(inventory)
NameError: name 'inventory' is not defined

Windows-8-6.2.9200
Ren'Py 6.99.10.1227
Inventory System 1.5

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Sat May 21, 2016 10:20 pm
by saguaro
Hmmm, looks like someone needs to test their code more thoroughly! Not mentioning any names. *clears throat delicately*

Similar issue, but needed to make a slight screen adjustment as well. I have updated the files in the first post. Thank you for catching that.

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Sun Sep 18, 2016 12:26 am
by natsumachi
Thank you so much for sharing this!

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Mon Nov 21, 2016 10:29 am
by kosmosnash
Hi! This works well. But after restart items in the inventory do not save. what to do? ;(
I use ver. 6.99.11.1749

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Fri Jan 06, 2017 6:58 pm
by noeinan
Hey! I've been working more with this code again (thanks so much saguaro, it's awesome!) and I was wondering if anyone ended up making the changes suggested in this post? viewtopic.php?f=51&t=25579&start=15#p326925

Specifically, if anyone managed to divorce the crafting screen from item actions so that you can have an apple that can be eaten to restore health or crafted into a better item. Also, if anyone had success with item classes, so you can have different types of crafting! (Cooking only at a stove, blacksmithing only at a forge, etc.)

I'm trying to do these things, but I am not very familiar with Python so my learning process is very messy and I usually end up with code that is probably not optimized. (Let's try changing this and see what it does! Oh, I broke something, I'm going to undo that, google some things, and try again.) If anyone else already did this successfully and would be okay sharing the code I would greatly appreciate it!

The endgame of what I'm trying to accomplish:

-Anywhere, anytime, the player can craft a set of basic recipes. (Ex. player can tie a rock to a stick if they have a stick, string, and a rock.)

-When player is at a stove, they can create cooking recipes. When player is at the workbench, they can create recipes that require tools.

-It would be nice if the same item could be used in both types of crafting to produce different recipes, but I can make due if that is not possible. (Ex. if you need to set the variable that allows you to cook to an item instead of to a recipe.) I can see a way around this by adding a refinement process that allows a base item to change to a new item class, like you have an apple and if you want to cook with it you first have to craft it using the basic craft menu, which processes it into a "sliced apple" which is now a cooking item, then you can go to the stove and craft the sliced apple.

-Maybe instead of one cookbook, you would have multiple cookbooks that track different types of recipes? So, if you discover a cooking recipe, it shows up in the cook book. If you unlock a simple recipe it shows up in your inventory. Workbench recipes show up in the workbench "tab" of your cookbook. Alternatively, instead of having a screen to view all recipes, it would be that when you're at the stove only cooking recipes show up on the right and when you're away from a crafting station only simple recipes show up, etc.

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Thu Jan 12, 2017 1:41 am
by noeinan
I've done a lot of modification to this code and thought I'd share what I've done in case it will help anyone else. :3

First, I made a craft screen that is separate from the inventory screen. You click a button, like a forge for example, and then it will open this screen up. This screen also has it's own set of recipes, allowing you to have a different list at the forge compared to the kitchen. First, I went into the script file and made a list of all the recipes I wanted to show up. You *must* define your items before making a manual list or else it won't work.

Code: Select all

    $ cookbook = list() 
    
    call define_items
    call define_inventories
    
    $ cooklist = [sandwich,apple_pie,potato_soup,tea,chocolate_milk,grilled_cheese,cookies]
Then I copied the inventory screen, set default crafting_screen to True, and removed all the if statements regarding having a second inventory-- including the button that toggles the craft screen on and off. (I just wanted a permanent craft screen.)

Code: Select all

screen inventory_kitchen(first_inventory, second_inventory=False, trade_mode=False, bank_mode=False):
    default crafting_screen = True
    tag menu
    modal True 
    
    frame:
        style_group "invstyle"
        hbox:
            spacing 25
            vbox:
                label first_inventory.name                   
                use money(first_inventory, second_inventory, bank_mode) 
                use inventory_view(first_inventory, second_inventory, trade_mode)                          
                use view_nav(first_inventory)
                use sort_nav(first_inventory)
                textbutton "Close" action Hide("inventory_kitchen")
            use crafting_kitchen(first_inventory)
I also needed to add a custom crafting screen for the kitchen. I replace "cookbook" with my manual recipe list.

Code: Select all

screen crafting_kitchen(inventory):
    vbox:            
        label "Recipes"
        hbox:
            xmaximum 600 xminimum 600 xfill True         
            text "Name" xalign 0.5   
            text "Ingredients" xalign 0.5   
        side "c r":
            area (0,0,600,400)
            viewport id "cooklist":           
                draggable True
                mousewheel True
                vbox:
                    for item in cooklist:
                        hbox:                            
                            first_spacing 25 spacing 10
                            hbox:
                                xmaximum 250 xminimum 250 xfill True box_wrap True
                                if item.icon:
                                    add im.FactorScale(item.icon, 0.33)
                                if inventory.check_recipe(item):
                                    textbutton item.name action Function(inventory.craft,item)
                                else:                                                                   
                                    text item.name
                            for i in item.recipe: 
                                if i[0].icon:
                                    add im.FactorScale(i[0].icon, 0.33)
                                else:
                                    text i[0].name
                                if inventory.qty(i[0]) >= i[1]:
                                    text "x" + str(i[1]) bold True
                                else:
                                    text "x" + str(i[1])             
            vbar value YScrollValue("cooklist") 
Another thing I did was make it so the inventory_popup which appears when you craft an item shows a picture as well as text. I just thought this added a nice touch. You just duplicate inventory_popup, give it a new name, and make these changes:

Code: Select all

screen inventory_popup2(message,item):
    zorder 100
    imagebutton idle "gui/"+item+"_notification.png" xalign 0.5 yalign 0.35
    frame:
        style_group "msgstyle"
        vbox:
            text message
    timer 0.8 action Hide("inventory_popup2")
Should be noted that this code uses the item's name, which appears in text, instead of its variable name, so you'll have to name your files accordingly. You also need to change the crafting def under the Inventory class so that it will use this new screen instead of the old one.

Code: Select all

        def craft(self, item):
            for line in item.recipe:
                self.drop(line[0], line[1])
            self.take(item)  
            message = "Crafted %s!" % (item.name)
            renpy.show_screen("inventory_popup2", message=message,item=item.name)   
Still working on a few more features-- like the ability to have items be both craftable and useable, and also I'm going to try to make recipes that produce more than one item. (We'll see how that goes because it seems hard. But I want to make it so I can, for example, have a recipe that takes a bottle of oil and a bottle of wine, then produces a the end product + an empty bottle.)

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Sat Jan 14, 2017 11:26 am
by Yadi
This my first post, and iam kind of noob with coding, and i have couple of question.

instead of crafting iam using it as cooking
so, add a variable in class Item

the code is like this

Code: Select all

class Item(store.object):
        def __init__(self, name, desc, icon=False, value=0, dishOrg=0,  act=Show("inventory_popup", message="Nothing happened!"), type="item", recipe=False):
            global cookbook
            self.name = name
            self.desc = desc
            self.icon = icon
            self.value = value      
            self.dishOrg = dishOrg
           
 
            self.act = act # screen action
            self.type = type # type of item
            self.recipe = recipe # nested list of [ingredient, qty]   
            
            if recipe:
                cookbook.append(self)
                cookbook.sort(key=lambda i: i.name) #alpha order
iam tried to make a cafe gameplay example
so, iam change the items acts to jump to label test if we clicked the icon and then iam put this code in label test

Code: Select all

label test:
  if item[0].dishOrg > 50: 
     $costumerhappy = + 6
      call Satisfied_costumer from          Satisfied_costumer
but i got an error, said: name 'item' isn't defined, then what the right code of it ?

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Mon Jan 30, 2017 6:27 pm
by noeinan
Yadi wrote: iam tried to make a cafe gameplay example
so, iam change the items acts to jump to label test if we clicked the icon and then iam put this code in label test

Code: Select all

label test:
  if item[0].dishOrg > 50: 
     $costumerhappy = + 6
      call Satisfied_costumer from          Satisfied_costumer
but i got an error, said: name 'item' isn't defined, then what the right code of it ?
I am not an expert by any means, but here is my best guess:

Everywhere else in the code that uses item directly is a function, inside a python block. Variables inside of functions aren't defined outside of that function. It seems to me that you will need to make a function that takes in information about the item and then calls "Satisfied_customer" if the conditions are met.

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Wed Feb 01, 2017 12:01 am
by sataneku
Is there a way that I can change the background of the inventory, but not the bar in top left corner? I know it uses frame.png, I just want the inventory to use a different background and the top left bar to use frame.png

Re: Infinite, Stackable Inventory/Crafting/Vendor - UPDATED

Posted: Thu Feb 09, 2017 12:50 am
by noeinan
Hey, so I did another thing with this awesome code and wanted to share in case it would be useful to anyone else. :3 I wanted to make it so that when you craft items, any extra containers are added to your inventory. For example, if I have water (in a bottle), oil (in a bottle), and beeswax (in a tin), and you combine all those things into *one* bottle, you get the final product (in a bottle) PLUS the unused bottle and unused tin.

First, I added a new variable, "containers" to the Item class, right after recipes:

Code: Select all

init python: 
    import renpy.store as store    
    
    class Item(store.object):
        def __init__(self, name, desc, icon=False, value=0, act=Show("inventory_popup", message="Nothing happened!"), type="item", recipe=False, containers=False):
            global cookbook
            self.name = name
            self.desc = desc
            self.icon = icon
            self.value = value
            self.act = act # screen action
            self.type = type # type of item
            self.recipe = recipe # nested list of [ingredient, qty]  
            self.containers = containers
            
            if recipe:
                cookbook.append(self)
                cookbook.sort(key=lambda i: i.name) #alpha order

        def change(self, name, desc=False, icon=False, value=False, act=False, recipe=False, containers=False): 
            self.name = name
            if desc:
                self.desc = desc
            if icon:
                self.icon = icon
            if value:
                self.value = value   
            if act:
                self.act = act
            if recipe:
                self.recipe = recipe  
            if containers:
                self.containers = containers
Then I added the containers, similar to how the recipe lists work. The containers list only has the *extra* containers in it, so you don't add the container that the final product uses.

Code: Select all

$ cream001 = Item("Thistle Cream", "Medicine applied to the skin.", "inv/jar.medicine04.png", 2400, recipe=[[empty_jar,1],[water,2],[wax,1],[herb_oil001,1]], containers=[[empty_bottle,3], [empty_tin,1]])
And for any recipes that don't have extra containers, you need to add an empty container list or else you get errors:

Code: Select all

$ herb_oil001 = Item("Thistle Oil", "Made by soaking herbs in oil.", "inv/bottle.extract.png", 800, recipe=[[oil,1],[herb001,1]], containers=[])
Lastly, I modified the craft function so that after it removes the ingredients from your inventory, it adds the extra bottles:

Code: Select all

        def craft(self, item):
            for line in item.recipe:
                self.drop(line[0], line[1])
            for line in item.containers:
                self.take(line[0], line[1])

            self.take(item)
            message = "Crafted %s!" % (item.name)
            renpy.show_screen("inventory_popup2", message=message,item=item.name)  
Hope this helps other folks who wanted a similar feature!