In this blog post we’re integrating with the custom built Java server that can be found here and specifically implementing item equip functionality that was built in this blog post.
In the video we will cover most/all blueprints and see a demo of this in action.
I will try go step by step with what was required to be done to achieve it using Unreal Engine.
As before the API integrations have been done with a free VaRest plugin from UE marketplace.
In general, these are the functionalities I was aiming to achieve here:
- On inventory item right click, show an extended menu where user can equip/drop item
- From item menu, click drop to call API to drop the item and refresh inventory
- From item menu, click equip item to call API to equip it, then refresh inventory and equipped items
- On inventory item double click, equip the item and refresh inventory
- From equipped items icon, double click to un-equip the item, refreshing inventory and equipped items
Let’s jump straight in.
Display item menu on right click
In order to display the menu, first you want to create the widget for the menu.
The widget can be designed however you like, but this is how I’ve implemented it:
In this way, if my menu starts to grow too large I can keep it smaller because of the scrollbox, but this is optional and not required.
In general, it should just be widget containing some buttons for you to press.
Once the widget is created you can spawn it when you right click an item slot.
So from my previous posts, I created a styled item slot widget.
This will be the widget containing your item slot – don’t worry too much about the differences in style between the one above and yours, as the implementation should stay generally universal.
For reference, the slot above was created in these two blog posts, but I don’t think they are needed as pre-requisite.
Handling right click on the button
So the first thing you will notice is that buttons don’t support right clicks…
So instead, you will go into the graph view and click Add
button on top left corner and under override function
select On Mouse Button Down
.
Note that this is not for just the button component, but rather the entire widget – so place this carefully.
When you click this override, it will take you to the next view where you have a call when a mouse is pressed.
You will want to create a Is Mouse Button Down
function where you can select the right mouse button
for input.
Add a branch
to ensure that the right mouse is pressed, as this event captures both left and right mouse clicks (Note that if you have a button in widget, it will consume the left mouse click event).
And now you can safely create the menu widget here, when right mouse button is pressed.
If you leave it at that, it will create the widget at top left corner which is not what you want, so I also added a bit of code to position this menu next to the mouse.
I position the widget where the mouse is, with a small, 30×30 offset. Note that you should disable the remove DPIScale
boolean so that it will work correctly when you re-size the window.
I also added another custom event on the graph, such that when the mouse leaves the menu, it will close the menu.
This is mainly to avoid more complicated solutions of tracking click events outside this widget, which is possible and we can cover in future.
Ok now I want to handle on button pressed events, to drop and equip items.
Handling Drop item from the menu
Ok from the designer view of your item menu, locate the drop button
and add a On Clicked
event to it.
Then inside the blueprints you can handle this call.
I’ve refactored the drop event into the TopDownCharacter
blueprint, but it can live in many places, e.g. Inventory widget
or even Game mode
widget. To be honest I am not yet sure where the best place is for it yet, but I’ve set it into TopDownCharacter
incase there will be other game objects which will force the player to drop items in future for example, and it would be easier to reference it from there.
After calling the API to drop the item, remove the menu from parent.
Dropping item API has already been covered in a previous blog post so will not go into too much detail, but the blueprints for the API can be found here.
The main principal is that we create a new API request, specifying the character who has the item, the item location in the inventory and the location to drop the item in game world.
Then we also call refresh inventory
event, which will be displayed below and referenced in multiple other locations.
Refresh inventory
Refresh inventory is a simple call which fetches the inventory widget and asks itself to refresh
This is basically the call in the Inventory constructor, where it pulls the data from server and re-synchronizes itself.
This functionality was covered in this blog post.
Equipping items
There’s two ways of equipping items, one from the menu on click to equip, another by double clicking the item slot.
We don’t want to repeat code and I decided the functionality to equip it will live in the item slot (as its the one that spawns the menu).
First of all, Button widgets do not support double clicks…
So I use the button
on click event here.
And use the following implementation for checking if its double click
I am not sure why buttons don’t natively support this.
The main thing to look at here is that when we press a button we toggle a button pressed
variable to ON if it wasn’t already. Then if you click again within 0.3 seconds, it will execute your function (in my case Equip Item with API
.
Equip item with API
I tried to fit the blueprint into one image here so may look squeezed
What is it doing? It’s simply executing the following JSON request that we can see in postman, and asking inventory
to refresh itself.
i.e. we’re replicating the required headers and adding the body data, which has the Item Instance ID
, for the item you wish to drop.
The Item Instance ID
can be found from the Character Item
payload in this case, which is already part of the slot
information as it was used to draw the item.
The API requests for equipping items were covered in this blog posts in my case, but change them as per your requirements as different servers will require different inputs.
For Inventory refresh
we also want to refresh the equipped items
here so re-draw them incase we affect more than 1 item (e.g. 2h weapons can remove 2 slots etc)
Displaying equipped items
In the previous screenshot we can see that we’re asking the equipped items widget to refresh itself.
The equipped items widget is this one:
i.e. its a widget that references all equipped item slots (notice one is selected on left menu as example).
Each of the Equip Item slots is very similar to the item slots, but it has a slightly different design and the icons are drawn a little differently
The way the icon is populated is via construct by populating an image into the content box
component (border component).
This means that by default, when ItemInstance
is not set, we will draw the EmptyWidgetIcon
determined in the inventory menu
If the Item Instance
IS set, then draw the icon from the instance.
We have this on Refresh Widget
custom event.
So this is how we populate the icons inside the slots themselves, and the Equipped Items Widget
is the one that tells these slots what to draw.
Here’s the blueprints from Equipped Items Widget
for getting the contents.
This API request is mimicking this request to the server:
I also had to create a new structure to represent my equipped items model:
And as usual I created a helper method for converting the VA Rest json response into this structure:
As we can see, we’re able to re-use a lot of models and helpers here which is great.
Now for the extension of Equip Items widget blueprints
we can reference the above.
The Populate Equipped Items
custom event can be found here:
And lastly I created a custom function for returning the slot widget based on slot category here:
This Get Slot Widget By Category
is getting the widget based Item
category, which in my case is like BELT
or CHEST
etc.
And again for reference, it refers to the slot items in this EquippedItemsWidget
Note here is also where we define the default empty icon
to draw, when an item in not equipped.
Un-equip item from equip slot
The logic here is that when you double click the item from equip slot, we will un-equip it.
From the equip slot designer, find the button and add on clicked
event
In the same way that we handled equip, we check here if the button was double clicked
When the item was double clicked, we call Handle unequip item
custom event.
The event does the following
In a similar way, this is emulating the following API request:
Where the item instance ID is the item that’s referenced in the slot.
After its done, we just want to refresh all contents, for inventory, itself and the equipped widget.
The custom events can be found here:
This is essentially re-using all created blueprints to refresh themselves, i.e. as if you had to re-construct those widgets. This synchronizes the client with server.
Conclusion
We now have a basic connection of inventory with server where we’re able to pick up items, drop items and equip them.
There was some interesting limitations with buttons and I would actually advise people to potentially use border
widget instead of button
as some limitations are frustrating to work with.
E.g. next I’d like to do drag
functionality for the item slots, but the button is consuming the left mouse button input so its not registered. This should not be a problem with border
. Also for reference, they also have events similar to button for example on mouse button down
.
The main reason I haven’t done this is because I’ve got my buttons programmed with different styling for normal, hovered or pressed
.
Note this can be achieved with Border as well, but its a bit more hassle as you’d have to override the hovered
and pressed
events to update styling. Long term this is still probably easier though.