Making a Hack’n’slash #20: Equipping our items

Let’s work on the equipment system of our Hack’n’slash!

This article is also available on Medium.

We’ve had quite a lot of episodes about our inventory so far – but we’ve hardly implemented anything for actually equipping our items and benefiting from their stats!

So, today, let’s start working on that and begin with some basics: we’re going to move our items from the inventory to the equipment grid slots (according to the type of item we’re equipping, and ignoring the ones that are neither weapons nor armours) 🙂

Preparing the inventory and the input actions

First of all, let’s re-check our scene UI elements are properly named and nested.

You might remember from screenshots in previous episodes that I decided to do something similar to World of Warcraft’s equipment window:

In other words, I’m going to have two columns on each side of my hero’s preview for the armours or the jewellery, and a couple of slots in the bottom center for the weapons (one slot for each hand) – I’ve slightly less slots than World of Warcraft, because I focused on the main types of equipments:

On this picture, you also see the name I gave each slot: this is the name of the associated game object in the hierarchy, and it will be its reference later on in our code.

Those game objects are simply new instances of the “InventoryItemSlot” prefab.

I could have nested them in some containers to give them horizontal or vertical layouts and place them in the right place, but that would make things more difficult down the line, with quite unintuitive indices; rather, we can place them with top-left, top-right and bottom-centre anchors:

Parallel to this scene setup, we also need to create a new input to use or equip our items easily – I’ll use a button I’d left free for that before: the right-mouse button on computers, or the “west” button on gamepads.

So let’s add our new “UseItem” action in the “InGameMenu”:

And of course, we should also update our inventory input displays (the ones we configured last time) – I think we can safely make the navigation input “implicit” for now, and use this second display to show the “Use/Equip” action instead.

Also, since I’ll need to have some items to equip (and because I don’t want to go through the whole chase-kill-loot loop to get them), I’ll re-define a few serialised fields for some test items:

Defining equipment slot types for our items

Alright – now that our scene and input actions are ready, let’s update our scripts a bit to introduce all the necessary concepts.

To begin with, we’ll have to modify our InventoryItemData to set up a new EquipmentSlot enum matching our various UI game objects, and set some default value (the None option is for all the items that cannot be equipped):

Of course, we can also change this default in the sub-classes WeaponItemData and ArmorItemData:

Now, you can change and/or create new Scriptable Objects from our *ItemData scripts to set their equipmentSlot field value:

Implementing a basic “equip” feature

Ok: we’re finally ready to use all of this in our inventory panel and transfer some items from the grid on the left to the correct slot on the right.

The first step is, as usual, to link our input action to its callback:

Then, we’ll simply add a new _equipment dictionary in our script and update its contents at the right time. Basically, we want our “UseItem” action to check if the item can be equipped and, if so, move it from its position in the inventory grid to the slot matching its equipmentSlot value and refresh the UI.

The code in itself is pretty self-explanatory, but it relies on two important additional methods not yet shown in this snippet:

  • the AddItem() function we already defined in previous tutorials, but that we have to modify now to allow for a direct slot index
  • and the _SetEquipmentItem() function: this is very similar to the SetGridItem() UI refreshing method we had before, except it takes care of the equipment-related elements on the right

Here is the AddItem() method with its new parameter – in short, we add a new if-else branching to check for this variable and, if it’s not -1, we do all of our item movement based on this starting slot; else, we just do exactly the same as before:

You see that I’ve also extracted the grab logic to a _GrabItem() function so I can easily share it between this method and the _OnToggleItemGrabAction() from before… and I’ve taken this opportunity to fix an edge case: in case we click to grab an item, we have to make sure we try to grab one in the inventory grid (and not in an equipment slot, for example) 😉

Then, here is the _SetEquipmentItem() function:

If you re-run the game now, you’ll see that if you open your inventory (containing these few test items), you can use the “UseItem” action to send them to the matching slot in the equipment grid:

And what’s even better is that you can switch with an already equipped item, if one was in the same slot!

Important note: I’ve decided to implement the “equip” like the “drop”, meaning that moving an item from the items grid to an equipment slot liberates both one cell and the matching weight from the total weight… but you can totally say that equipment weighs on the player, too, and code this differently in your own game 🙂

Doing the reverse: “unequip”!

The next step is obviously to have some way of removing an item from an equipment slot (I mean, without necessarily replacing it with another).

To do this, we just have to change the checks at the top of _OnUseItemAction() to handle this other case and add an if-check (I’ve also moved the UI update chunk to the end of the function, after the if-check, to avoid code redundancy):

Here, I use a little click for the checkEquipment boolean: any C# enum automatically indexes its values (starting from 0 by default), so you can turn an enum value to an integer and vice-versa, just by casting it. So I can take my current _selectedSlotIndex (remember it’s the index of the cell in the list of children, we recorded it previously) and “turn it” into its equivalent EquipmentSlot value to check whether the slot already contains an item or not.

And here we are! We can now right-click on the inventory side to equip an armour or a weapon, and right-click on the equipment side to unequip it 🙂

Showing the details of equipped item

However, for now, you see that when we hover the items in the equipment slots, we don’t see their details anymore. That’s because, a while ago, when we worked on this feature for our inventory items, we wrote this function:

As you can see, once again, our initial check is a bit too strict. What we have to do is to check if the slot index matches either an inventory item or an equipment item:

With that fix, we get back our nice item details no matter which part of the panel we hover 🙂

Bonus: preparing some player stats

Just to finish today’s episode, let’s sidetrack a little bit and start to implement some stats for our player. This will eventually be linked to our equipment, since we’ll want our armours and weapons to combine with those stats to make our final defence and attack score, or even directly boost those values.

This feature isn’t too hard to code: we’ll simply have to define some variables in our PlayerData script for the various stats (note that I’ve chosen some arbitrary default value for now):

You can obviously add more stats, and change some of those, if they don’t match your own game! 😉

Then, in the inventory panel, I’ll display those values in the block on the far right (feel free to setup a TextMeshPro UI element in your layout, and drag it to the _inventoryPlayerStats field:

Finally, I’ll re-update my attack logic – instead of having a direct attackDamage variable, I’ll compute it based on my player’s stats:

And don’t forget to also change the Graphics.cs and PlayerAttackManager.cs scripts to use this new property:

For good measure, let’s also show this computed value in our inventory panel, below the stats:

Conclusion

Here we are! In this tutorial, we implemented the fundamentals of our equipment system, and we’re now able to transfer items from the inventory grid on the left to the equipment slots on the right.

We’ve also set up and displayed some stats for our players so that we can easily update, boost or diminish them in the future…

Next time, we’ll continue working on this system and see how to actually show the equipment as 3D objects anchored to our avatar, and update the animations accordingly!

Leave a Reply

Your email address will not be published.