Items / Usable Items

What is a usable item?

Usable items are items that provide an effect when the players activates them.

Players can activate a usable item by double clicking on them in their inventory or by selecting them through the hotbar.

When activated the usable handler runs, performing our custom logic specific to the item and the player. Then the item is typically removed from the player's inventory. We can however control if and when it is removed.

We "handle" this by creating a blueprint based on the Usable Item Handler abstract class AC_UsableItemHandler located in the Blueprints/UsableItems folder then assigning it to our item in our item data table. What happens when it is used is entirely up to you and is what you program into this handler.

When a usable item handler is spawned (through the AC_Inventory_Storage instance holding the usable item) the handler is attached to the owner. If the owner is a player controller, the controlled pawn (if valid), will be what the handler is attached to.

Create a Usable Item

  1. Navigate to the Blueprints/UsableItems folder.
  2. Right click on the AC_UsableItemHandler and select Create Child Blueprint. Name your handler something easy to remember and related to the action it will perform.
  3. Open the Items data table, select your item and then set the UsableItemhandler to the blueprint you just created.

This handles all the foundation and linking the handler to the item. Next we will go over creating the functionality that occurs when we use the item.

Creating the functionality for a Usable Item

  1. Open up the usable item handler you created. If you haven't created one follow the steps above.
  2. Override the CheckConditions function and the OnItemUsed event.
  3. CheckConditions is called right before the item is actually used to provide you with an opportunity to do a validation pass to see if the item can and should be used by the player. For example, if your player has full health and accidentally tries to use a heal potion you may not want to actually consume it, and in turn save them from a moment of frusteration. This is where our checkConditions function comes into play. To use just return the proper boolean value. If the item can be used you would return True. If it can't be used you would return false. The storage component holding the item, the slot id, the item row name, and the dynamic data will be provided at this point to help with your validation. Keep in mind the variables in the blueprint with similar names as the inputs are not actually available at this point, and are only set when the onUseItem event activates. For checking conditions you will want to stick to the inputs. There is an event called NotifyClientCantUse which you can call from within CheckConditions to send a text alert with a custom message to the client trying to use the item if you would like to relay that it is not available and why.
    OnItemUsed is where you will start to build your logic to perform the actual action you want to occur when the item is used. For multiplayer games this is happening on the server. Unlike checkConditions, no data is passed into this event, the same data however is provided to you set to variables already inside the blueprint if you need them. When spawned this handler is attached to the owner of the item before this event is called. If the owner is a player controller, the controlled pawn (if valid), will be what the handler is attached to. You can use the getOwner native function if you need to get a reference to this actor to handle your usable item functionality.
  4. Tweak the usable item handler variables (if needed).
  5. AutoDestroy? when true the handler will automatically be destroyed after running the OnItemUsed event. If set to false you can manually manage when it is destroyed by calling destroy component when you are ready. If you are using timers or delays and don't want to delegate the action out this may come in handy. Just remember to actually destroy the component when you are done or you will create a memory leak by disabling this and not doing that step.
    AutoRemove? when true the handler will automatically manage removing the item after it is used. If you want to not remove it, or conditionally remove it you would set this to false. When you are ready to remove it you would call RemoveItemFromStorage within the handler.
    RemoveQuantity The quantity of the item to remove, by default is 1. Perhaps you would like to remove more, or dynamically decide this value at runtime by comboing it up with an AutoRemove? of false and calling RemoveItemFromStorage after setting the value of RemoveQuantity.

Reusable Items with Charges

How about reusable items but with a limited number of charges? If you define the charges DynamicData on your item the integer value will be used to track available usable charges of the item. For example if you set charges to 3 you would be able to use the item 3 times before it is removed.

Reusable Items with Unlimited Charges

You can create reusable items with unlimited charges by setting the value of charges in DynamicData to -1. You can also alternatively set AutoRemove? to false inside the handler to avoid showing the charges label on the tooltip while maintaining the same non-removing functionality.

Playing Animations and Sounds when using items

In the demo world when you use food, drink or a potion item, the pawn would make a sound and play an animation. You also probably saw the consumable item in the pawns hand while the animation to consume it played. These usable items share a usable item handler which initiates a callback on our pawn when used.

Our demo world pawn is setup to handle receiving this callback using the BPI_ConsumableItem blueprint interface and implementing its ConsumedItem event. Using this event our demo pawn can determine what animation and sound to play based on the item consumed, and toggling of what temp mesh to show.

The AC_UsableItemHandler_Consumable is where the process starts for each of these demo items. During its onItemUse event it gets a reference to the owner and calls the ConsumedItem blueprint interfaced event, which our demo world pawn is setup to handle.

Now open the demo world pawn at the root of the Demo/ folder and locate the ConsumedItem event to see how it handles the callback. The pawn performs the different animation, sound fx, and also toggling of our temp mesh from this callback.

This ConsumedItem event has an input of ConsumableType which is just a string that we use to identify the type of consumable (food, drink, potion). In the example handler we get this value from our dynamic data which we set when creating our items. It also has an input of ItemRowName which can be used to get any specific item info. In this example we use it to toggle our temp mesh, which is actually handled through the equipment system, as this is the system responsible for attaching items to the pawn.

You are welcome to reuse these parts and the flow in your project, however keep in mind this is just intended to be an example of the implementation. It is not the only way to handle something like this. It should however be enough to show you how the pieces connect together.

As another example, if all of your pawns share the same skeleton and animation you could get away with containing all of it inside the same usable item handler. You would only need to delegate it to the pawn like I did in this example if you want to leave what actually happens to the pawn, on the pawn. Maybe we have different pawns who will use this item and will consume it with unique animations, or different skeletons, in which case containing it all in the handler is not the best fit.

With my example what the pawn actually does is handled entirely on the pawn. We (as the item) could care less, we just tell our pawn that it consumed us, how it responds to this information is up to it.