Sign in to follow this  

Item stacking in RPGs

This topic is 2628 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm looking into item stacking for my RPG / roguelike game. For those not familiar with the term, it's when multiple identical (or near identical) items are reduced to a single 'stacked' item for the player to interact with. So if you're holding 1 arrow and pick up 9 more your inventory shows "Arrow (x10)", instead of "Arrow, Arrow, Arrow, Arrow, ..." This makes it easier to manipulate (eg. passing all your arrows to a ally) and reduces clutter when navigating your inventory.

As far as I see there are two obvious ways to implement this - either 1) at the GUI level, or 2) at the model level.

1. Stacking performed in the GUI
Here, if you've picked up 10 arrows then your inventory actually contains 10 'arrow' objects. This means that almost all of the gameplay code doesn't care about stacks, as it can just deal with items (or lists of items) as it needs to. Instead the relevant GUI sections (such as the inventory menu) will create stacks to show to the player.

The downside of this is a player's inventory could get very big very quickly. It's not unlikely to have hundreds of arrows for example.

2, Explicit item stacks in the gameplay representation
By this I mean that the inventory actually stores things internals as stacks. If you've picked up 10 arrows that would be represented by an ItemStack object containing a single Arrow object and a 'stackCount' of 10. This could be split into an ItemStack with a count of 9 and an ItemStack with a count of 1 when a single item needs to be passed elsewhere (ie. to use it).

The advantage of this is that the number of inventory items is much more manageable (a thousand arrows is really just an ItemStack object, an Arrow object and a count of 1000). The disadvantage is that most of the gameplay logic now needs to be aware of the concept of item stacks and becomes more complicated as a result.

Or, 3) some kind of hybrid of the two? Or any other ideas that people have?

Normally I'd go with 1 and just make it a gui thing, but I want to have money (in the form of gold, silver and bronze coins) individual objects. An inventory with 100 arrows is probably just about practical, but an inventory containing 1,000,000+ individual GoldCoin objects isn't.

Further complications:
'Cursed' objects are usually shown as identical to regular objects until they're worn/used/inspected. These need to be stacked along with items of their own type (otherwise that single arrow that refuses to stack will obviously be cursed and you can throw it away). However it might not be enough just to keep a 'stackCount' and a 'numCursed' count, as there may be two arrows with very different curses.

'Charged' objects (like Wands, or Potions) may have a 'uses' count (number of times the potion can be used before it is finished, or number of times a wand can be used before it breaks). Obviously these can't be stacked as a single Wand object with a count, as the individual charges would be lost.

This roguedev thread has a whole bunch of opinions on the subject as well.

Thanks.

Share this post


Link to post
Share on other sites
Virtually every game I know implements stacks at the object level, since that is what makes sense -- especially if you can possibly have thousands of them. It is practically mandatory if you have multiplayer. Even if you don't have multiplayer now, it will be a major barrier if you decide to add that feature in a year from now, which you can totally avoid from the beginning.
Imagine something like Runescape where a player typically hoard ten thousand arrows, and multiply that with as few as a thousand players. Not stacking items would be an insane load on the database, both storage wise and startup time wise. It simply isn't acceptable to load a few megabytes of data for every player that logs in, just to have an inventory of mostly identical items.

Hiding cursed items can be trivially done at GUI level, using many different approaches. I'm doing this by assigning a different item ID and adding a "looks like" field, which obviously is only needed once for every item type, not every instance.

Share this post


Link to post
Share on other sites
Quote:
Original post by samoth
Hiding cursed items can be trivially done at GUI level, using many different approaches. I'm doing this by assigning a different item ID and adding a "looks like" field, which obviously is only needed once for every item type, not every instance.


Individually it's all "trivial", it's the knock-on effects on complexity that worry me. At the moment my ItemStack design would end up looking like:


class ItemStack
{
ArrayList<InternalItemStack> internalStacks;
}

class InternalItemStack
{
Item item;
int count;
}


.. in order for an ItemStack to represent "Arrows x10" it'd internally be storing Arrow x6, Cursed Arrow x2, Blessed Arrow x2. And then everything that deals with firing arrows needs to accept an ItemStack instead of an Item, etc. etc.

Edit: The other approach could be to expand my existing Item interface so that ItemStack can actually *be* an item. However I suspect that might be more trouble than it's worth.

Share this post


Link to post
Share on other sites
Quote:
.. in order for an ItemStack to represent "Arrows x10" it'd internally be storing Arrow x6, Cursed Arrow x2, Blessed Arrow x2. And then everything that deals with firing arrows needs to accept an ItemStack instead of an Item, etc. etc.


I think you should reconsider this design. If the different types of arrows don't stack on each other all you have to do is have a counter for your stackable items.

Quote:
This makes it easier to manipulate (eg. passing all your arrows to a ally) and reduces clutter when navigating your inventory.


This would also hold true for passing all your Cursed Arrows if it'd wouldn't stack with all types of arrows.

[Edit] Didn't notice your further complications section, which makes it more complicated indeed. Could your items not contain a state indicator, which contains information on whether the item is cursed or charged and what kind of curse it is or how many charges it has?

Share this post


Link to post
Share on other sites
Quote:
Original post by Mussi
[Edit] Didn't notice your further complications section, which makes it more complicated indeed. Could your items not contain a state indicator, which contains information on whether the item is cursed or charged and what kind of curse it is or how many charges it has?

Yeah, it's those that really make it hard. Lots of games get this wrong and stacking (or lack of) reveals information about the item that the user shouldn't know yet, or stacking and unstacking resets the internal counters (like the wear, or decay state) allowing cheating.

This post has some interesting ideas on 'hard' vs. 'soft' item stacking. I'm wondering if I can use both to solve this elegantly. Eg. 100 arrows become 'hard stacked' into one Arrow object with a count of 100 in the model, and Arrowx100 and CursedArrowx2 are 'soft' stacked in the GUI so the user only sees one stack.

Share this post


Link to post
Share on other sites
Quote:

Eg. 100 arrows become 'hard stacked' into one Arrow object with a count of 100 in the model, and Arrowx100 and CursedArrowx2 are 'soft' stacked in the GUI so the user only sees one stack.

Well, hard stacking is more important at developing time whereas soft stacking can be added later to improve the UI handling.

With some simple rules you can easily handle hard stacking. First I would associate every item with a template which contains meta informations about the item, most important the stack size (bottle = 5, arrow = 100, armor=1 etc). With this approach you can easily define unique items like armor etc. which are just too large or too special to be stacked (you dont' want to stack 5 magic breastplates with different magical boni). Then I would define a restricted mode, in which you can't apply all stacking operations to a item stack , i.e. you can't merge unidentified potions with health potions.

This will leave you with one issue: hidden attributes. Either you define items with hidden attributes as unidentified (=restricted mode), or you should use soft stacking. But you will run into gameplay issues mixing hidden attribute items with standard items. There's nothing bad about an 'cursed', unstackable sword, but when you mix cursed potions with health potions, what potion will be consumed first ?

In my opinoin you should communicate an unidentified state to the player, so the player has the option to use it or to identified it first. Nothing is more annoying than to drink a "masked" health potion and to die from poision in a boss battle, because the player has never the chance nor the choice to react in a different way.

Share this post


Link to post
Share on other sites
I'd make your generic item base classes with two attributes.

First, make a query to see if something is stackable. IsStackable(), perhaps. If true, you can display it differently in the UI.

Second, a query to see how many it is. Count(), perhaps. If it isn't stackable the count should be 1. If it is stackable, the count is >= 1.




It gives you several properties that you see in Roguelike games. You dip a stack of arrows in holy water they all become blessed; you dip them in poison they all become poisoned, etc.

The "knock-on effects" also become uniform. If the object is stackable you search for a duplicate. If there is a duplicate you just add to the count. This applies to all actions. Drop an item means you check for stackable then check for prior existence. Pick up means you check for stackable then prior existence.

Other knock-on effects can operate on count without a check for stackability. If you drop x items and you don't have that many, you can drop up to the count. The player wanted to drop 57 (unstackable) wands of digging? Sorry, you only drop one because that's the count.

Another effect, using an item, can be part of the base class. Using a stackable item would decrease the count, possibly consuming it. Using a non-stackable item may modify other counts such as charge counters, possibly consuming the object.

Share this post


Link to post
Share on other sites
There are more than two options. Object + count, multiple objects, and the obvious third path of object + count + multiple objects. That is to say object + count for objects that are identical, but smart enough to use multiple objects when they are similar enough to stack but not identical. I would start with object + count then add the ability to stack item stacks.

Share this post


Link to post
Share on other sites
Quote:
Original post by frob
..snip..

Yeah, you've pretty much ignored the 'further complications' bit, which is where things get interesting. :)

stonemetal is thinking along the right lines (merging some items but keeping others unmerged). The only question is whether to hard stack existing stacks in the model, or whether to soft stack the existing hard stacks at a UI level.

I'm going to go with soft stacking at the UI for now, largely because that should keep the actual gameplay logic simpler.

Share this post


Link to post
Share on other sites
Quote:
Original post by OrangyTang
Quote:
Original post by frob
..snip..

Yeah, you've pretty much ignored the 'further complications' bit, which is where things get interesting. :)

Does it really matter if you identify each particular item as cursed? If you pull an arrow from a quiver you may decrease your cursed count randomly selected by (cursed/uncursed) percent. If you have multiple cursed types, you enumerate a count of each cursed type and randomly pull from them. The stacked and count items operate unchanged.

Share this post


Link to post
Share on other sites
Ashaman makes some good suggestions. Building on those... here are a few thoughts.

Having a stack of items called "Unidentified Potions" would immediately provide incentive for the player to get them identified. And for the courageous or chaotic players who don't mind a little risk, they could try to consume them without identification.

You could then split out identified objects into their own stack of matching items. So "Arrows", "Cursed Arrows", "Poison Arrows", etc would each be their own stack, once identified. I believe this is just what Ashaman was saying.

This way, you wouldn't have to search a list to count cursed arrows, for instance. And there would no need for group-operations on the un-identified items. If you drink one potion, you're not drinking the whole stack. You can just process the attribute flags for that one object as it gets used.

Based on what I've read here, that seems like it should work for all your item types.

In this way, you can maintain stacks that satisfy your desire to minimize the number of allocated objects, and it offers a way to address your various item attributes.

I think it's worthwhile to consider making currency a non-inventory item. If you have some specific architecture in place that requires currency to be in your inventory, that's fine. But if you're early enough in your design that you can conceptually separate currency, I would consider it a valid choice. For instance, I don't think currency will ever be unidentified, cursed, poison, etc. It's just money, and probably doesn't need to be put through the same processing as your other objects.

As for 'uses' count, you could have this is as a stat for every item, defaulted to 'one use' for anything that only gets one. Or if you have an item interface that you are deriving from, you could put uses into a class that's specifically intended for multiple-use items. Either way, this doesn't need to affect your stacking paradigm, since a uses count doesn't apply to a group.

Good luck and happy stacking!

Share this post


Link to post
Share on other sites
Quote:
Original post by smgorden
I think it's worthwhile to consider making currency a non-inventory item. If you have some specific architecture in place that requires currency to be in your inventory, that's fine. But if you're early enough in your design that you can conceptually separate currency, I would consider it a valid choice. For instance, I don't think currency will ever be unidentified, cursed, poison, etc. It's just money, and probably doesn't need to be put through the same processing as your other objects.

Nah, that's the one thing that's staying the same. :) Firstly because I always dislike RPGs that limit you to only a certain amount of inventory space but infinite amount of money. But mostly because I want an economy based around bartering. You won't have "200 currency", instead every item will have a value and you'll trade for other items. Eg. "I'll give you two gold bars, twenty copper coins and this sword for that armour". Somewhat like Fallout3 but hopefully with a bit more depth.

Also, I dislike singling out currency as 'different' from other items. Since I'm going for something simulation-y, it'd be nicer if it was just another object like everything else. Having them as proper items also lets me do interesting things later like using gold coins and other 'currency' items as ammunition or blunt weapons (either because you're desperate, or because you've found a creature with a phobia against gold, or just for the fun of it), or for smelting items down and converting them into ores or metals that might be useful in other ways.

The rest is all good points though, thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by OrangyTang
This post has some interesting ideas on 'hard' vs. 'soft' item stacking. I'm wondering if I can use both to solve this elegantly. Eg. 100 arrows become 'hard stacked' into one Arrow object with a count of 100 in the model, and Arrowx100 and CursedArrowx2 are 'soft' stacked in the GUI so the user only sees one stack.

This is how I would do it. Arrows, cursed arrows, and blessed arrows each get their own hard stack. Then you group them together into a single arrow soft stack. It wouldn't be just a GUI thing either, since the soft stack would be where you'd have your consumption logic. Additionally, a hard stack could be referenced by multiple soft stacks (i.e. a soft stack for arrows and a soft stack for cursed items). It might not even be necessary to create a proper object if you don't need the soft stacks to store any state, and what you'd end up with is a view or facade that just knows how to manipulate hard stacks (along the lines of what frob was saying).

Share this post


Link to post
Share on other sites
Quote:
Original post by frob
Quote:
Original post by OrangyTang
Quote:
Original post by frob
..snip..

Yeah, you've pretty much ignored the 'further complications' bit, which is where things get interesting. :)

Does it really matter if you identify each particular item as cursed? If you pull an arrow from a quiver you may decrease your cursed count randomly selected by (cursed/uncursed) percent. If you have multiple cursed types, you enumerate a count of each cursed type and randomly pull from them. The stacked and count items operate unchanged.


But now you've introduced a 'cursed' count, and a percentage. Where did that come from? There could be cursed items, or rotten items, or magic-but-not-identified items, and all sorts. You don't want to have to have counters for all of these on your base ItemStack object, with hard-coded ways of resolving them back to individual items.

Share this post


Link to post
Share on other sites

This topic is 2628 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this