How-To: Make an Item Usable
Goal: give an item a Use action that applies gameplay effects, spends the item and starts a cooldown - from the context menu, a double-click, or an action bar slot, all through one ability you grant once.
ICrimsonUsableObject (Usable/ICrimsonUsableObject.h): this plugin ships the interface and the fragment that answers it, and you grant one ability that reads it. See API Reference for the full contract.GA_UseItem once and grant it once. Every consumable in the game routes to it and supplies its own effects and cooldown, so a hundred potions still cost the ability system component a single spec. There is no per-item ability to make.1. Register the tags
Two project tags: one gameplay event that reaches the ability, and one cooldown identity per item (or per family of items that should share a cooldown). Add them in Project Settings -> GameplayTags, or in an ini:
[/Script/GameplayTags.GameplayTagsList]GameplayTagList=(Tag="Ability.Event.UseItem",DevComment="Activates the shared use-item ability.")GameplayTagList=(Tag="Ability.Cooldown.Item.HealthPotion",DevComment="Cooldown identity for the health potion.")
2. Author the effect the item applies
A plain UGameplayEffect Blueprint. Leave the NUMBER off it: set the modifier's Magnitude Calculation Type to Set by Caller and give it a Data Tag, and the item supplies the value at use time. One authored heal then serves the minor, greater and supreme potions instead of three near-identical assets that drift apart the first time the heal formula changes.
| For | Duration Policy | Modifier | Magnitude |
|---|---|---|---|
| An instant heal | Instant | your health set's incoming-healing attribute, Add (Base) | Set by Caller, Data Tag SetByCaller.Value |
| A heal over time | Has Duration | your health set's incoming-healing attribute, Add (Base) | Set by Caller, Data Tag SetByCaller.Value |
Period to how often it ticks (1.0 for once a second), and set Duration Magnitude to Set by Caller with its own Data Tag so the item can name the window. The per-tick amount is what the modifier's magnitude carries - a 50-over-5-seconds draught ticks 10 five times.3. Create the use-ability
One ability, granted to the player like any other, answers the event for every consumable in the game. Set its Ability Triggers to a Gameplay Event on Ability.Event.UseItem, its Instancing Policy to Instanced Per Execution (the ability carries which object this activation is for, so a shared instance would let two uses in the same frame overwrite each other), and its Net Execution Policy to Local Predicted. Leave the ability's own Cooldown Gameplay Effect Class unset unless you want a shared lockout across every consumable - the per-item cooldown comes from the item, not from here.
| In the ability | Call on the object (all ICrimsonUsableObject) |
|---|---|
| Resolve what is being used | The triggering FGameplayEventData carries it in OptionalObject - it is a replicated subobject, so the client and the server resolve the very same one. |
| Check before anything is spent | CanBeUsedBy(User, OutReason). Asked on both sides; end the ability and show OutReason when it says no. |
| Pay for it | Commit the ability, then GetUseCooldown(OutCooldown) and apply CooldownEffect for BaseSeconds, granting CooldownTag for the duration. |
| Do the thing | GetUseGameplayEffects(OutEffects) and apply each Effect, feeding its SetByCallerMagnitudes in as SetByCaller values. |
| Spend it | ConsumeUse(User) under authority only. false means nothing was spent and the use must be abandoned. |
Create a Gameplay Ability Blueprint, name it GA_UseItem, and set the three properties above in Class Defaults. Then build the graph from the table: Event ActivateAbilityFromEvent -> break the payload -> Can Be Used By (Branch) -> Commit Ability -> Get Use Cooldown -> Get Use Gameplay Effects -> Consume Use (Has Authority branch). Add it to the ability set you already grant your player.
Want a drink animation? Commit first, then play your montage and run the effects-and-consume half from an anim notify. Because the cooldown is paid at commit, the window is not spammable while the montage plays.
4. Add the Consumable fragment to the item
Open the item definition and add UCrimsonInventoryItemFragment_Consumable to Fragments. This is the whole integration - the item now answers ICrimsonUsableObject, and every path that offers a Use finds it.
| Property | For a health potion | What it does |
|---|---|---|
UseEventTag | Ability.Event.UseItem | Which ability answers. Per item, so a potion, a bomb and a scroll can reach three different abilities from the same bar. Unset makes the item inert everywhere. |
EffectsToApply | one entry: GE_Item_HealthPotion | The effects, each with the SetByCaller magnitudes this item feeds it. For the potion: key SetByCaller.Value, value 50.0. The number lives here, not on the effect. |
Application | Instant | Whether the effects land at once or run for a window. Over Time reveals the two duration fields below. |
DurationSeconds | (hidden) | Over Time only. How long the effects run. Fed to every effect under the tag below. |
DurationSetByCallerTag | (hidden) | Over Time only. Data Tag of the effect's duration SetByCaller. Leave unset to let the effect keep its authored duration. |
ConsumeCount | 1 | How much of the stack one use spends. 0 makes the item reusable without being consumed - a refillable flask, a rune that only pays a cooldown. |
CooldownTag | Ability.Cooldown.Item.HealthPotion | Granted on the user while the item is on cooldown. Two items sharing a tag share a cooldown; different tags run on independent clocks even though one ability serves both. Unset means no cooldown. |
CooldownSeconds | 10.0 | The authored length, before modifiers and the user's cooldown recovery rate. |
CooldownEffect | your shared cooldown effect | Carries the cooldown. Its duration is overwritten per use; CooldownTag is what keeps this item's cooldown separate from everything else using the same effect. |
EffectsToApply entry with 75.0 instead of 50.0, and a regeneration draught is Application = Over Time plus a duration - all three pointing at authored effects that never mention a number. That is the whole reason the magnitudes live on the item.Unable to find SetByCaller magnitude and that modifier evaluates to ZERO. The effect still applies and quietly does nothing, which reads like the use never fired at all. The fragment validates this on save, so a mismatch is reported against the item rather than discovered in play - see Validation below.Set the definition's ItemType too (for example Item.Type.Consumable) - the type action set in the next step is keyed on it.
5. Offer Use in the context menu
From your UI, call UCrimsonUsableStatics::SendUseEvent for the item (or your own menu's Use action). (CrimsonCore - requires all Crimson plugins) ships UCrimsonInventoryContextAction_Use as the default action of its item context menu.
The entry hides itself on items with no Consumable fragment, and on vendor stock, loot and container contents. It grays out with a reason when the player has none left or the item is still on cooldown.
Use is an OwningClient action (ExecutionPolicy on UCrimsonContextAction): picking it runs on the player's own machine and sends the item's use event there, the same path as an action bar press. That is not optional - the use ability is locally predicted, and GAS only triggers a locally predicted ability from a gameplay event where the ability system is locally controlled, so an event sent by the server for a remote client is dropped silently. The ability still re-checks CanBeUsedBy and spends through ConsumeUse under authority, so nothing is trusted client-side.
ExecuteAction runs on the server and sends the item's use event - exactly what an action bar press sends. Both paths land in the same ability, pay the same cooldown and hit one authority check, so a menu and a hotbar cannot drift apart about what using a potion means.6. Put it on an action bar (optional)
An action bar resolves the bound item by identity and presses it through the same use event. (CrimsonCore - requires all Crimson plugins) supplies the action-bar resolver and presentable for inventory items. The slot draws its cooldown sweep from the effect the ability applied - the same place an ability's sweep comes from.
7. Make the cooldown respond to stats
The authored CooldownSeconds is a starting point, not the final number. What the item hands over is an FCrimsonUseCooldown (Usable/ICrimsonUsableObject.h), and its BaseSeconds is explicitly pre-modifier: the ability that answers folds in the owner's cooldown modifiers and cooldown recovery rate before it applies anything. Ask the ability for the effective number when you put one in a tooltip - never show CooldownSeconds raw.
The item also reports the tags a cooldown modifier may be keyed to, in ModifierTags, widest to narrowest:
| Reported key | Comes from | What a modifier keyed to it targets |
|---|---|---|
Ability.Cooldown.Item.HealthPotion | the fragment's CooldownTag | this item, and anything else sharing the tag. |
Item.Type.Consumable | the definition's ItemType | every item of that type at once. |
So one modifier can shorten health potions specifically and another every consumable, with identical authoring, and the ability never has to know which item it is holding. An ability system that does not read ModifierTags simply ignores them; nothing else changes.
CooldownTag is what everything else grabs: the applied effect grants it for the duration, a slot view watches it to draw the sweep, and a modifier keys to it. Two items sharing a tag share a cooldown - which is how a family of potions is stopped from being chain-drunk. Two items with different tags run on independent clocks even though one ability serves both.Where each piece runs
| Step | Runs on |
|---|---|
CanBeUsedBy for the menu entry and the slot's enabled state | Owning client |
| Ability activation and cooldown commit | Owning client (predicted) and server |
ConsumeUse and effect application | Server only |
| Stack count and cooldown sweep updating in the UI | Owning client, from replicated state |
The item is spent before its effects are applied. If the stack emptied between activation and that moment - a second press in the same frame, another player's transfer - nothing has been handed out and the use simply does not happen.
Validation
Every way this can be misconfigured fails silently at runtime - the item applies cleanly and changes nothing - so the fragment checks itself when the item definition is saved or validated. UCrimsonInventoryItemDefinition walks its fragments to make that happen; UObject::IsDataValid does not descend into instanced subobjects on its own.
| Reported | When |
|---|---|
| Error | An effect entry with nothing set. |
| Error | Application is Over Time but the effect is not Has Duration - the window has nowhere to go. |
| Error | The effect asks for a SetByCaller nothing supplies. Names the tag and the effect. |
| Error | CooldownTag set with no CooldownEffect, or the reverse. Either way no cooldown is applied. |
| Warning | A supplied SetByCaller the effect never asks for - usually a mistyped tag. |
| Warning | UseEventTag unset (the item is inert), or EffectsToApply empty (using it does nothing). |
| Warning | Over Time with no DurationSetByCallerTag, or a cooldown of 0 seconds. |
See also
- How-To: Author an Item Definition
- How-To: Add Context Actions
- API Reference
- API Reference