how to add multiple entries without predesignated names to a class

closed account (2EwbqMoL)
so Basically I know how to use classes to create an item system for my game,
but im struggling with the inventory system, as I may have to have multiple types of items
stored under a single inventory, and while I can have a class like my inventory class here
1
2
3
4
5
6
struct Inventory{
	string ItemName;
	int ItemNumber;
	string ItemDesc;
	ItemType type;
}


I cant really do what I need with it, since each member to this class only has 1 item name, number etc. I need a CENTRALIZED storage unit to store what would be individual members to this class.

like, basically a whole separate class for individual items without the ItemNumber field, and a separate class to store what the player has picked up and or used, so those numbers can be added or subtracted, or listed in the console --

I dont know how to actually manage this, short of arrays... but I can see it getting messy if I have arrays like that, because I wont easily be able to correlate name[1] with itemamount[1] to add and subtract, or list out things under a class based list (ie potions: 2, weapons: dagger, sword)

any ideas?
Last edited on
How about this?:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Item
{
public:
     Item();

     //things generic to all items
}

class GreatSword: public Item
{
public:
     GreatSword();

     //things specific to this sword
     
     int ItemNumber;   //this is the unique ID given to a particular item, so that e.g. in cases
                                 //where you have more than 1 GreatSword you can differentiate them
}

struct InventoryManager
{
     std::vector<Item*> inventory;  //This is a vector that contains pointers to the base class, so that you can still access any of the derived class' members
     void dropItem(int ItemNumber_);  //Example functionality that InventoryManager would possess, drops the item labeled by ItemNumber_, pushes back variable, reassigns numbers to other items, etc.
}


Last edited on
Are you looking for polymorphism?
closed account (2EwbqMoL)
ploymorphism? maybe. I looked up the definition on wikipedia but found it a little ambiguous, and wasnt sure if it was related to math (seemed like it was related to numbers and like, the example seemed to show data handling in relation to types of numbers and number variables, would be useful in a calculator where you dont know if its gong to be int, long, etc... dont know where the decimal point rounds to...)

but it could be related to this in that im trying to get item name and number of items edited and displayed concurrently in a relative manner (i.e. potions 2)

and hyperfine, I will experiment with that code, as it might work. Im not really experienced enough to know at first glance. Im also not quite sure how ItemNumber in this case differentiates the items... because wont each greatsword have the same itemnumber? say its 001, each item would have the same itemnumber, as im not coding in each item by hand individually, more like, spreading them out. It doesnt matter, since this is a text game without shops, so you wont really be able to buy more items than I put in the game, but it would be useful in the future...
Last edited on
closed account (2EwbqMoL)
Yeah, hyperfine, IM trying to figure out some of that code, but its a bit different than anything Ive seen as Ive never worked with vectors. Once I figure out how to actually utilize it it may work. I'm mainly mystified by that dropItem function, and how I can interface it with the program in general...
A vector is similar to an array; one difference that often makes a vector more useful than an array is that the size of a vector can be dynamically changed. So, in this case you could have a vector called inventory that stores all the items that the player has. Here's an example of how one could implement pick-up and drop functions. You wouldn't want to copy-and-paste this into a program... it's hastily written and not thought out all of the way... But, this should be a start, and it should give you an idea of how you could start implementing the idea you were asking about.

1
2
3
4
5
6
7
8
9
class Item
{
public: 
     Item();
     
private:
     int ID;     //unique ID to particular item class
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Weapon: public Item
{
public:
     Weapon(int damage_, float range_)

private:
     int damage;
     float range;
}

Weapon::Weapon(int damage_, float range_)
{
     damage = damage_;
     range = range_;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

class InventoryManager
{
public:
     InventoryManager();
     pickupItem(Item* Item);
     removeItem(Item* Item);
     
private:
     double maxweight;  //example of something that might be relevant to an inventory manager
     bool inventoryfull;
     std::vector<Item*> inventory;
}

void InventoryManager::pickupItem(Item* Item)
{
     if(inventoryfull == false)
     {
          inventory.push_back(Item);  //google the push_back function; it is a function in the vector library that adds the argument to the end of the vector
     }

     return;
}

void InventoryManager::removeItem(int itemID_)
{
     for(int i = 0; i < inventory.size(); i++ )   //size of a function in vector library
     {
          if( inventory[i] == itemID_ )
          {
               delete inventory[i];    //this is if you want the item dropped to completely disappear (can't pick back up, or access at any point after this)
               inventory.erase(i);     //erase is a function in vector library
               return;
          }  
     }

     return;
}
     

1
2
3
4
5
6
7
8
//This is pseudo-code for a type of interaction that could warrant usage of the removeItem and pickupItem functions

Weapon BastardSword(5, 1.5); //BastardSword drops from some monster you killed, or something

InventoryManager.removeItem(CurrentEquippedSword->ID); //Player decides to drop current sword

InventoryManager.pickupItem(*BastardSword); //Player picks up BastardSword to replace his old sword


Let me know if you have any more questions, I'll do my best to answer.
Last edited on
closed account (2EwbqMoL)
Thanks a lot, I've been working on understanding it, and Im cooking some dinner (late here, ik), but i'll definitely look into it. I'm not really copy/pasting, the only part of code I copied into this (and I did it by hand) was a text color routine (which I changed, in a very small way)...

the whole point of this project is to learn how to manipulate and handle data and parsing in a complex environment so I would be more able to do things in the future. focusing on graphics and other things takes away from that valuable base experience which carries over into everything - If I can finish this simple project I can go on to use all those SDL/DirectX functions I know to actually do something useful in the world. to me, this is the difference between hello world and a legitimate functioning program.

if I can't understand what Im doing and implement it myself fully, there is no point in doing it. so I dont really WANT full code to copy/paste in. it would be depriving myself of essential problem solving experience, and implementing code in a real world environment...
Last edited on
No problem. And, I didn't mean "don't copy-and-paste" in a disparaging way, but more like a "this is pseudo-code and won't work verbatim, plus also probably has some basic errors" type way. Good luck with the programming. I can tell you that a few months of coding games has made me much more confident in my C++ abilities (still not great :P).
closed account (2EwbqMoL)
this is going to be a little of a battle, because I kind of more am thinking of this in a polymorphic sense, but theres probably a little bit simpler way to do it (think adventure/dunnet, just with an addition of equipping weapons only, and a number inventory system with AMOUNT of items, rather than just itemID #, like itemID 1, amount 5, name "potion", class consumable. Im not even going to include the class 'consumable because it adds complexity and is unneccessary. I can simply do it within the items subclass anyway.

its really the polymorphism thats complex. Im going to have to figure it out by finding a functional example to work off of, really.

I'll get it somehow...

like virtually I noticed the issue being if I did something like you said, I wouldnt even ultimately have a list of what was in a players inventory, or how many of it. I would need two vectors, one a string, and one an integer for both the name and amount of an Item. Could be two integers using itemID, and Item amount, and the two would have to concurrently move (i.e. ItemID stays unless ItemAmount goes under 1, if it does, then ItemID disappears and object no longer in inventory, but ItemID doesnt change if 2 get taken, just the ItemAmount).

its a lot more complex than I thought it would be. It would *almost be easier to use a text file to record objects in inventory so I could just list whats in it and delete whats in it. using fin() fout()... but that leaves a lot of core functionality missing.

this is going to take a lot more education on my part, and a serious design consideration.

I may take this another direction and I already HAVE an idea for it.

I'll come back and post the code I come up with if I get it to function properly...
Last edited on
closed account (2EwbqMoL)
what I seem to be having a problem with now is actually the drop function..

1
2
3
4
5
void InventoryManager::dropItem(int itemID_)
{ 
	inventory.erase(std::remove(inventory.begin(), inventory.end(), itemID_), inventory.end());
	return;
}

something like that seems the only way to do it. but Item* Item, does not work, nor itemID_ -- and its not because of the search function, I dont even know if my current code works at all yet! its the compiler, it says I need a const* char or something for the whole statement.

I'm guessing I have to imlement and iterator and then use a delete function?
Last edited on
closed account (2EwbqMoL)
if i use the inventory function you wrote,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void InventoryManager::removeItem(int itemID_)
{
     for(int i = 0; i < inventory.size(); i++ )   //size of a function in vector library
     {
          if( inventory[i] == itemID_ )
          {
               delete inventory[i];    //this is if you want the item dropped to completely disappear (can't pick back up, or access at any point after this)
               inventory.erase(i);     //erase is a function in vector library
               return;
          }  
     }

     return;
}

// doesnt work because of      removeItem(Item* Item); 


and even if I dont change it, and change the function instead the == does not function with the int itemID_ for some reason, says operand types not compatible or something
Last edited on
closed account (2EwbqMoL)
ultimately the problem here seems to be if I use a custom type for my vector (which sort of allows it to contain more than just string names or integers), it cannot be compared to strings or integers with operands (or ironically even other Item*) because that is a pointer and not a strict datatype.

its an interesting problem, really. it works for adding in the item and almost everything other than dropping it.

there also is no default constructor for the type Item(), and it seems any attempt I make at creating this fails miserably.

I really think im in way over my head and am just drowning in the complexity of this system at this point. it kind of disappoints me.
Last edited on
closed account (2EwbqMoL)
So, Im back to this, I guess.

I finally got all my classes in order and functional without memory errors -- but there is still the issue of the inventory class.

Using a vector is posing me all sorts of problems -- for one push_back is NEVER working, even for members (Item) its supposed to work for...

I get numerous errors upon compile that way, and with other classes, it simply wont recognize the members at all, because there is no suitable conversion from weapon to item.

my first solution was a pointer, but while the compiler accepted the pointer as valid code, it was NOT valid to compile, and also produced various errors.

I'm running into the issue that I need some method - either a built in pointer from Weapon/etc-> Item *, or universal recognition that they are the same type.


WHile I now possess the ability to create an array of items, I Have no way of handling which the player has in their possession - I can code in a weapon or potion and say what it DOES, even write a function for its use or equip it, but I cannot for the life of me create a working inventory that lists the items possessed and holds quantity.

a vector MAY work, im not sure since I Have to run everything against it - i.e. check if user has item/a potion, remove it from inventory when used/dropped/equipped, put it back later.

like I said, first Im running into the error of the classes being of different type (weapon needs to be recognized as an Item), second, I need vector functions to work -- as it is, I need members of the class I.e. PlayerInv -- and then sometimes the functions just seem to not work. third -- the functions themselves.

EDIT:::!!!!!!!!!!

It seems that perhaps if I establish the vector in the main source file and use pointers from weapon, it seems to accept them in the vector -- Im not sure how this functions from a memory standpoint because it is Untested, but will compile ( does it do the right thing? I dont know yet...)

but I certainly need a way to devise automatic pointer creation for each class should this work, or another method if it doesnt...
Last edited on
closed account (2EwbqMoL)
WHole new post,

it seems casting it as &weapon also works in terms of push_back.

I did not realize this. but again I am unsure of how the results of this will turn out.

if it works right I May in fact have fully-functional code already and no problem.

but I have no idea.
closed account (2EwbqMoL)
OK,

plus and minus -- the system sort of works -- its definitely recording SOMETHING -- its giving me hex values when I try to spill its contents out on the screen though.

I wrote a print inventory function to test it, and got a hex value or memory address or something...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Inventory {
private:
	std::vector<Item*> inventory;
public:
	Inventory(){};
	
	void pickupItem(Item* Item){
		inventory.push_back(Item);
	}
	string printInv(){
		for (int i = 0; i < inventory.size(); i++)   //size of a function in vector library
		{
			cout << "Inventory: " << inventory[i];
		}
		return 0;
	}
};


1
2
Before the debug assertion failure it outputs this
Inventory: 0017FB18Inventory: 0017FACC


It definitely IS outputting two values (I put in two values, a piece of armor and a weapon) - but the way its outputting them as an integer is odd (I even classed the function as a string.

I then tried this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Inventory {
private:
	std::vector<Item*> inventory;
public:
	Inventory(){};
	
	void pickupItem(Item* Item){
		inventory.push_back(Item);
	}
	string printInv(){
		for (int i = 0; i < inventory.size(); i++)   //size of a function in vector library
		{
			cout << "Inventory: " << inventory[i];
                        return 0;
		}
		return 0;
	}
};


and I got

Inventory: 0042FDE4 Debug Assertion Failed! Program:~include\xstring Line 1168 Expression: invalid null pointer

1
2
3
If I change the type to void() then it outputs Inventory: 003FBACInventory: 003DFB60,

but instead of crashing allows the program to run
Last edited on
closed account (2EwbqMoL)
Instead of the initial idea of one vector and a management class,

I am changing the code to represent three vectors -

a string vector for item name, and an int vector for quantity held,and a vector for possessed item id #.

the manager class has the functionality to access item information, although Ive yet to really correlate direct connection between them, but it doesnt matter really -- picking up an item is NOT an automatic process...

this way I can access information later through functions of the specific items. but I have a feeling I will run into problems if I cannot find a way to flag what Items a player does or does not have -- the way this is looking you could examine a rock you never picked up so long as the rock is in the code.

this is something I have not really thought to account for yet. but the methodology of the base of adding and dumping items is remarkably simpler, seeing as basic math and string functions accomplish the task instead of some mysterious Item type that does not really exist in C++.

I have a feeling it will ultimately die because of its shortcomings, even though right now it seems the ultimate solution...

will it be possible for me to scan through the possessed item id# vector tp assure a player has an item in the examine function before it goes through? it seems i am easily able to connect name and quantity and have them fixed to say, 2 potions, but im not sure if the third vector will stay in line well. if so, then this is the best way to go about it...

I just dont know exactly how I will scan it, but if it is possible I have to figure it out on my own I suppose...
Last edited on
I am changing the code to represent two vectors -

a string vector for item name, and an int vector for quantity held.

Do you mean:
1
2
std::vector<std::string> name;
std::vector<int> quantity;

However, getting quantity that corresponds to a name requires boring index math. Consider:

std::vector<std::pair<std::string,int>> items;

Depending on which operations are used most, a differently tuned solution could be better:

std::map<std::string,int> items;
closed account (2EwbqMoL)
forget about helping, I figured most of it out...

I still have shit to learn, but if anyone wants to see the code, send me a pm
Topic archived. No new replies allowed.