Inventory RPG-style

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.
Post Reply
Message
Author
User avatar
jeffster
Miko-Class Veteran
Posts: 888
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Inventory RPG-style

#1 Post by jeffster »

UPDATE:
v1.6. Added import from typing to work with 8.2+.
(Ren'Py 8.2 could give errors with v1.5, because of some Python type hints. Use v1.6 please).
Now it's more like a usable framework than just a sketch.
Discussion

Here is yet another inventory, RPG-style:
  • Equip/unequip with dragging or clicking.
  • Backpack grid and custom equipment slots.
  • When an item is hovered or dragged, highlight suitable equipment slots.
  • "Filtering": highlight backpack slots with different colors according to their item type.
  • Calculating stats bonuses depending on the equipped items' properties.
  • Tooltips.
  • v1.1: Stackables & consumables. Stats bars (mana, energy, health).
  • v1.3: Crafting. The code was reworked for that.
  • v1.4-1.5: More documentation with some improvements.
v1.0:
inventoryrpg.jpg
v1.1:
screenshot-v1.1.jpg
v1.3:
drag-v1.3.jpg
drag-v1.3a.jpg
It's not a framework, rather a simple code that you can modify and use as a starting point for your own system.

v1.0 is a simple (291 lines not counting comments) how-to drag-n-drop or click to rearrange and move draggables between drop areas.

The last version is a more complex program, with crafting etc.

Code: Select all

The program has "items" and "slots".

TL;DR: Use functions like

  addItem("egg", 5)             Add 5 eggs to the inventory.
  addItems("sword", "shield")   Add sword & shield to backpack.
  equip("sword", "hand_r")      Equip sword in right hand.
  Sack.push("sword")            Move sword from hand to backpack.
  consume("egg")                Eat 1 egg and feel the effects.
  minusOne("egg")               Remove 1 egg from inventory.
                                Works for non-stackables as well.
  mixPotion()                   Create 1 potion. Works only when there
                                are at least 2 suitable ingredients
                                in any of the slots "p1"-"p4".


Items
=====

Every item in the universe has an entry in the dictionary `items`.

When a new kind of item is crafted, it should be added to `items` dict.

When an item is placed in the inventory, its reference in `items`
receives `place` (the name of the slot where that item goes).

Example:

  items["shield"]["place"] = "hand_l"

means item "shield" goes to the left hand (= slot named "hand_l").

Likewise, when a stackable item appears in the inventory,
its reference in `items` receives "amount" value.

Example:

  items["egg"]["amount"] = 3

Each item (single or stack) in the inventory has a corresponding
`drag` element in the `inventory` screen.


Slots
=====

There are several inventory screens:

  * `manslots` shows equipment slots on the character figure.
  * `potions` is a crafting screen with slots for alchemy ingredients.
  * `smithy` is another crafting screen (under development).

Unique slots of every screen have entries in corresponding dictionaries:
"manslots", "potions", "smithy".

These entries contain positions (x, y) in pixels of the slot on screen;
slot size (px) and field "item". If there's an item in that slot,
the name of an item is recorded there. E.g.:

  potions["p1"]["item"] = "egg"

Every name of an item is a unique identifier, there's only 1 item
(single or stack) with that name.

If another item of that kind would be necessary, it would get another
name and entry in `items` (like "egg000123").

Slot names should be unique too. Even in different screens there must
be no slots with the same name. Slot names should not start with "bk_",
because such names are recognized as backpack cells.


backpack
--------

`backpack` is a common element of all inventory screens.

Its slots (cells) have always the same positions, calculated as a grid;
so there is no need to store their (x, y). Therefore data collection
`backpack` is just a list with 8*8=64 elements.

It contains names of items in those cells. E.g.:

  backpack[0] = "sword"

means that the left-top cell of the backpack contains sword.

Backpack cells as drag areas have drag_name's like "bk_0", "bk_1" etc.


Summary
=======

Draggables:
  `items`     {} all the items in the game

Drop areas:
  `backpack` [] names of items in the backpack
  `manslots` {} character equipment slots (params + names of items there)
  `potions`  {} crafting potions slots (params + names of items there)
  `smithy`   {} crafting smithy slots (params + names of items there)


Screen `inventory`
==================

It is switchable between variants: "manslots", "potions", "smithy".

Dict `drops` references current drop areas for the screen variant. So:

  default drops = manslots

means that the initial screen variant is character slots.

Then switching to screen "potions" looks like:

    SetVariable("screenType", "potions"),
    SetVariable("drops", potions)


In action
=========

Moving between backpack and other screen slots can be done by clicking
or drag-n-dropping.

Dragging or hovering an item makes its suitable slots highlighted.

`manslots` has slot "eat", to be used with consumables.

`backpack` cells can be highlighted with colored background, according
to the type of item there.

`potions` slots are used to put there ingredients and create a potion.

Moving an item from one slot to another involves updating data
both for those slots and for the item. For example, to move
item "egg" in "potions" drop areas from slot "p1" to "p2":

  potions["p1"]["item"] = None       # or use `unequip("egg")`
  potions["p2"]["item"] = "egg"
  items["egg"]["place"] = "p2"

Moving the egg to a backpack cell #5 for example would be similar,

  backpack[5] = "egg"
  items["egg"]["place"] = "bk_5"

Also to clean the data for the previous slot of the egg, do first

  oldSlot = items["egg"]["place"]
  drops[oldSlot] = None

provided that `drops` dict is the reference to currently active
screen slots. For example,

  drops = potions

In practice, to put items in the backpack, just use `Sack.push()`:

  Sack.push("egg", cell="bk_5")

or to put the item in whatever empty backpack cell:

  Sack.push("egg")

In these examples, if there is a stack of several eggs, then
the item "egg" is treated as the whole stack.

E.g. if player drops eggs onto slot "eat", it consumes 1 egg,
and internally it's:

  items["egg"]["amount"] -= 1

The remaining stack falls back in its backpack cell, or
disappears if there was only 1 egg in the stack.

Removing the item from inventory is done by cleaning its slot
and setting

  items[name]["place"] = None

where name is "egg" for example. And if the item was a stackable,

  items[name]["amount"] = 0

(removing "amount" key from items[name] works too).

In practice it's more convenient to use functions

  equip(itemName, slotName)  to equip in a slot

  minusOne(itemName)         to remove an item from inventory,
                             or remove 1 piece if it's a stack
  addItem(name [, amount])   to add item (or stack) to inventory
  addItems(*items)           to add different items in one go

  Sack.push(name [, amount, cell])  to move item to the backpack

  consume(item)              remove 1 item and run its effects

  mixPotion()                create 1 potion, spending 1 ingredient
                             from each slot "p1", "p2", "p3", "p4"

No copyright, public domain.

The demo is made and should be run with Ren'Py SDK at least 8.1. Earlier Ren'Py 8 versions would give errors (complaining about unknown variable config.check_conflicting_properties). If you want to use this with Ren'Py 7, you would need to rework the code a bit, as it uses some Python 3 magic.

Version 1.6:
Drag-v1.6.zip
(1.28 MiB) Downloaded 47 times
First version:
Drag-1.0.zip
(537.52 KiB) Downloaded 90 times
Last edited by jeffster on Mon Apr 01, 2024 4:35 am, edited 13 times in total.
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

User avatar
Andredron
Miko-Class Veteran
Posts: 776
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Inventory RPG-style

#2 Post by Andredron »

๐Ÿ‘๐Ÿ‘๐Ÿ‘
Renpy textbook (in Russian). https://disk.yandex.ru/i/httNEajU7iFWHA (all information is out of date) Update 22.06.18

Sawa - a game of the Drow Nation

Honest Critique

Poses in visual novels, or how to hold a character properly in the frame

Help save articles to the webarchive. [/color]

Please save your projects on github, you would know how hard it is to find projects after 7 years...

User avatar
jeffster
Miko-Class Veteran
Posts: 888
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Inventory RPG-style

#3 Post by jeffster »

Andredron wrote: โ†‘Sat Jun 03, 2023 11:58 pm ๐Ÿ‘๐Ÿ‘๐Ÿ‘
Updated to v1.1
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

User avatar
jeffster
Miko-Class Veteran
Posts: 888
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Inventory RPG-style

#4 Post by jeffster »

Andredron wrote: โ†‘Sat Jun 03, 2023 11:58 pm ๐Ÿ‘๐Ÿ‘๐Ÿ‘
Updated to 1.3. Crafting etc.
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

User avatar
jeffster
Miko-Class Veteran
Posts: 888
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Inventory RPG-style

#5 Post by jeffster »

v1.4. Some improvements. More explanations/documentation.
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

User avatar
jeffster
Miko-Class Veteran
Posts: 888
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Inventory RPG-style

#6 Post by jeffster »

v1.5. More documentation. Some algorithms were reworked to be user-friendlier.
Now it's more like a usable framework than just a sketch.
If the problem is solved, please edit the original post and add [SOLVED] to the title. 8)

Post Reply

Who is online

Users browsing this forum: No registered users