Inventory System

Started by
10 comments, last by Phil123 11 years, 9 months ago
Alright, so I've been working on a Text-Based RPG during my spare time for a few weeks now and I'm kind of stuck on how I want to implement an inventory system.

Before you say, "you're wasting your time, you should do X, Y, or Z instead," I decided to start this project for a few reasons:

1. For fun (gasp!)
2. To solidify the concepts I've learned over the past few months
3. To develop my ability to work with larger projects (3400ish lines of code)
4. To continue developing my ability to debug code
5. And lastly, because I can smile.png

Now that that's out of the way, here's my question:

So it's your standard text-based RPG. Monsters, abilities, levels, spells, unique battle system, different areas, merchants/other NPCs (eventually), towns (eventually), quests (eventually). All of this was quite easy to implement, given I have the time (which I did, and I still do). But one thing I've learned is that I should know exactly how I want to do something before investing hours into it to make it perfect and 100% bug free.

Here in lies my problem - I don't really have a solid idea of how I should go about implementing an inventory system (hence why I'm looking any ideas/advice/tips that people can provide).
Advertisement
Perhaps start with telling us what is it exactly that you need the inventory system to do? Do you need to track the location and status of every item in a dungeon or would something like Hero.HealingPotionCount++ be sufficient?
What kind of language are you using?

Perhaps start with telling us what is it exactly that you need the inventory system to do? Do you need to track the location and status of every item in a dungeon or would something like Hero.HealingPotionCount++ be sufficient?


Ack, had this in the original post, but I deleted it (was in a rush sad.png ).

Some things I will want included in said inventory system:

1. There will be weapons, armour, accessories that the player can equip.
2. Consumables that the player will use (non-stackable, for example healing/mana potions - they will help, but won't make or break a player's ability to progress in the game)
3. The item data must be stored in a way such that it's easy to display to the player (shouldn't be a problem regardless of how it's implemented, but it's still something I have to take into account)
4. It must be designed/coded such that its functionality is simple and user friendly.
5. Each item must have a designation (for example, a sword could be labelled as a 1h Weapon - meaning, if the user tries to use a "sword" in battle, which is an equippable item and not say, a healing potion, it's extremely easy to distinguish between the two and tell the player "hey, what the hell, you don't want to do that.")
6. Inventory size will be limited.
7. Item pickup will be automated (may eventually make it manual, but for simplicity sake at the moment, it's planned to be automated), but the player can choose to drop items.
8. Items will always take up 1 slot, so I don't have to worry about different items taking up different amounts of space.

I've been thinking of a few things. I could use an array of strings to represent the player's inventory, with some file input to get the item stats and item type if need be. I could read in the item name, then read in the item type, and depending on the item type I'll read in different values to an cItem class.

But now when the player uses an item or equips an item I have to be careful as well because various items do different things, and I'd think it'd be inefficient to add 0 to every stat except for damage when the player equips a sword, or add 0 to every stat except for defense when they equip armour (maybe I'd just have to suck it up and have a separate function for EACH item type, but this seems time+space inefficient - there are many ways to do something in C++, but I'd prefer to do it the correct way the first time, or at least, a more "correct" way the first time). This is my main wall in my project currently.


What kind of language are you using?


Doh, was in the title (or at least it should have been...still new to the forums). C++, with Microsoft Visual C++ 2010 Express as the compiler/debugger.
How about something like this(just a rough and simple outline):

[source lang="cpp"]enum ItemSlot
{
HEAD,
CHEST,
WEAPON,
MAX_SLOTS
};

class Item
{
ItemSlot slot;
String name;
// other base class stuff
doStuff(); // maybe?
};

class ItemWeapon
{
doStuff(){ /* special stuff */ }
};

class Player
{
Item inventory[];
Item equipment[MAX_SLOTS];

equip(int i)
{
Item item = inventory;
// check if something else is equiped and revert stats if so
equipment[item.slot] = item; // equip item
// apply stats
}
};[/source]

Forgot about consumables when writing that, left some blanks as well, but I think this can get you going.
I'm going to avoid answering the question to a specific programming language and just sort of explain my thinking based solely on OOP.

First, you could start with the "Item" class that you can extend in each other class for their respective item types. The fields and functions in "Item" would just be what is common between every item. (ie. name, size, etc.)

Once you start making new classes like "One Handers" or "Consumables" you can get more specific. You could create the functions that only those item types can use. (ie. equip, getDamage, etc.)

This is the very beginning of what could end up being your entire game's item system. I don't like providing code or getting into super specific details because it's more fun to figure it out on your own.

One more thing that I will say, is that you can break up your "Inventory" into multiple collections. For example, you could keep an array of consumables, an array of weapons, and an array of armor. Then when you display them to the player you could separate them logically. The problem that might come up is keeping track of how much stuff is in your inventory. This could easily be solved by using a counter for each item you pick up, or adding weight to your items.

Anyway, I hope I helped at least get the creative juices flowing. Also, I'd love to hear what your ideas are at this point. You may not have an answer yet, but you must have the beginnings of what your inventory will look like.

Happy coding
Thanks for the posts guys.

How about something like this(just a rough and simple outline):

Forgot about consumables when writing that, left some blanks as well, but I think this can get you going.


Hmm yeah, that helps a lot, thanks!


Anyway, I hope I helped at least get the creative juices flowing. Also, I'd love to hear what your ideas are at this point. You may not have an answer yet, but you must have the beginnings of what your inventory will look like.

Happy coding


Definitely, I didn't expect such quick responses - my plan was to establish some ideas in my head as to how I wanted to approach it and then really crack down on it this upcoming Weekend (Friday to Sunday) as I won't have much time to devote to it before then.

Really appreciate it guys, be sure to check this thread Sunday when I'm done smile.png
just as JDGamedev mentioned, using OOP is your best bet at making it simple, shorter, and efficient (in some sense, since inheritance = virtual call table)

As he said, start with a base Item class that has everything that will be in common to everything in the inventory (i recommend not only name/proportionns etc but also a "type", so you can request anything that is an item what kind of item it is so you can do proper management)

from there make classes that inherit Item to be more specialized (armour, weapons, potions etc). Just keep a nice hierarchy but dont go too deep, as everyone know too many levels means a huge virtual lookup table (this is know when to use a subclasses function instead of a base classes function)

Then all you have to do is keep a vector/list/whathaveyou of Item pointers, then whenever something is added (like a Spear for example), just add its pointer to the list. Whenever you want to use an item, just find it (using its name or type) and use it; if its a weapon or potion that has specific functions that Item does not have, as long as you know it is the correct type you can use type-casting and call the function (Anyone here is free to correct me if I am wrong)
Always improve, never quit.
Okay, mostly done.

Item.h
[source lang="cpp"]#ifndef _ITEMS_H_
#define _ITEMS_H_

#include "Spells.h"

// // // // // // // // // // // // //
/* Inventory Class */
// // // // // // // // // // // // //
class Inventory
{
public:
string Inv_List[InventorySize];
int Inv_Slots_Filled;

string Weapon; string Chest;
string Head; string Legs;
string Feet; string Arms;
string Hands; string Fingers;
string Neck; string Ears;
};
// // // // // // // // // // // // //
/* Inventory Class */
// // // // // // // // // // // // //
// // // // // // // // // // // // //
/* Item Class */
// // // // // // // // // // // // //
class Item
{
public:
string cName;
string cType;
};
// // // // // // // //
/* Weapon */
// // // // // // // //
class Weapon : public Item
{
public:
int Offense_Increase;
int Magic_Increase;
};
// // // // // // // //
/* Chest */
// // // // // // // //
class Chest : public Item
{
public:
int Defense_Increase;
int Heal_Eff_Increase;
};
// // // // // // // //
/* Head */
// // // // // // // //
class Head : public Item
{
public:
int Defense_Increase;
int Magic_Eff_Increase;
};
// // // // // // // //
/* Legs */
// // // // // // // //
class Legs : public Item
{
public:
int Defense_Increase;
int Regen_Increase;
};
// // // // // // // //
/* Feet */
// // // // // // // //
class Feet : public Item
{
public:
int Defense_Increase;
int Dodge_Increase;
};
// // // // // // // //
/* Arms */
// // // // // // // //
class Arms : public Item
{
public:
int Defense_Increase;
int Magic_Eff_Increase;
};
// // // // // // // //
/* Hands */
// // // // // // // //
class Hands : public Item
{
public:
int Defense_Increase;
int Accuracy_Increase;
};
// // // // // // // //
/* Fingers */
// // // // // // // //
class Fingers : public Item
{
public:
int Earth_Resist_Increase;
int Air_Resist_Increase;
};
// // // // // // // //
/* Neck */
// // // // // // // //
class Neck : public Item
{
public:
int Death_Resist_Increase;
int Holy_Resist_Increase;
};
// // // // // // // //
/* Ears */
// // // // // // // //
class Ears : public Item
{
public:
int Fire_Resist_Increase;
int Ice_Resist_Increase;
};
// // // // // // // // // // // // //
/* Item Class */
// // // // // // // // // // // // //
/* // // // // // // // // Item Objects // // // // // // // // */
Weapon cWeapon; /* Player Weapon */ Weapon tempWeapon; /* Temp Weapon */
Chest cChest; /* Player Chest */ Chest tempChest; /* Temp Chest */
Head cHead; /* Player Head */ Head tempHead; /* Temp Head */
Legs cLegs; /* Player Legs */ Legs tempLegs; /* Temp Legs */

Feet cFeet; /* Player Feet */ Feet tempFeet; /* Temp Feet */
Arms cArms; /* Player Arms */ Arms tempArms; /* Temp Arms */
Hands cHands; /* Player Hands */ Hands tempHands; /* Temp Hands */

Fingers cFingers; /* Player Fingers */ Fingers tempFingers; /* Temp Fingers */
Neck cNeck; /* Player Neck */ Neck tempNeck; /* Temp Neck */
Ears cEars; /* Player Ears */ Ears tempEars; /* Temp Ears */
/* // // // // // // // // Item Objects // // // // // // // // */
#endif _ITEMS_H_[/source]

Normally I don't like using global objects, but in this case, it made life easier. Basically, I have one object for equipped items, and one object for temporary data. (cItemType and tempItemType respectively).

The object for the Inventory class is in my int main().

Function prototypes in my Main.cpp
[source lang="cpp"]string Get_Item_Stats (const string & szItemName);
/* Inventory */
void Equip_Item (Inventory & cInventory);
/* Inventory */
void Unequip_Item (Inventory & cInventory);
/* Inventory */
void Display_Gear (const Inventory & cInventory);
/* Inventory */
void Display_Inventory (const Inventory & cInventory);
/* Inventory */
void Display_Item ();
/* Inventory */
bool Slot_Open (const Inventory & cInventory);
/* Inventory */
void Drop_Item (Inventory & cInventory);[/source]

Get_Item_Stats uses file input to read in item stats. Depending on the item type, it'll read in to the corresponding tempItemType object. It also returns a string that contains the type of the item (this is important below).

Equip_Item allows the player to equip an item of his choice, granted that they have the item and the item slot is currently empty. Depending on the type of the item (which is where Get_Item_Stats comes in handy), the function will equip the item and store all of the data in the correct cItemType object, which I utilize in a different function to set the player's battle stats.

Unequip_Item unequips the specified item. Not much to say here.

Display_Gear displays the player's gear if they have something equipped in that slot. Again, nothing fancy here.

Display_Inventory lists what's currently in the player's inventory. It uses cInventory.Inv_Slots_Filled to determine how many items to display for cInventory.Inv_List[].

Display_Item displays the stats of a specific item. Again, uses Get_Item_Stats to temporarily store the item stat data, and it'll return the item type so my Display_Item function knows what item object to display.

Slot_Open returns true if a slot is open (who woulda thought). I'll be using this when monsters start dropping loot.

Drop_Item drops the item specified by the player (if they actually have that item).


Mission accomplished ^^ and after very minor amounts of testing, is 99.9% bug free. Thanks guys.

Edit: Didn't post the actual functions, but if anyone's curious, I can, just let me know.
why do you have c and temp objects?

and more importantly, do you only have 1 type of items for each type of class? What I'm asking is wont you have like 3 different swords with various stats? or different clothing/gear?

The way you have set this up it seems like you can't expand it, the user can't have 5 differente unique weapons or clothing, only 1 of each. What i can see is that you edit the temp ones to accomodate changes to the particular item, where it can be a different weapon entirely, but this still prevents the user from having many different items of the same type. If this system serves your purposes that is fine, but this seems like a bad design approach. It is very limited and if you want to make changes to it later you most likely have to change the entire thing.


The point of recommending inheritance to aid you was to make this whole thing simlper, shorter and cleaner.

Your item hierarchy is fine, its just your c and temp globals that make this very unusual. I will come back to this thread and post an expanded example of how you may approach this (i am currently at work and cannot risk typing on here for an extended amount of time).
Like i said if your layout is working fine and your game is behaving how you want, you can just ignore me. I just want to help
Always improve, never quit.

This topic is closed to new replies.

Advertisement