How-To: Bridge an Item System

Goal: let an inventory equip and unequip gear, and let it ask what is equipped, with neither system including a header from the other.

Prerequisites
How-To: Get the Building Blocks.

1. Understand the contract

UCrimsonEquipmentManagerComponent implements ICrimsonEquipmentHost (Equipment/ICrimsonEquipmentHost.h). An item system talks to that interface and the bridge statics, never to the manager's type; this plugin stores your item as an opaque UObject* and never inspects it. (CrimsonCore - requires all Crimson plugins) UCrimsonInventoryEquipmentStatics is a complete bridge for CrimsonInventory.

MethodWhat the manager does
CanEquip(Request, OutFailureReason)Rejects a class that is not a UCrimsonEquipmentDefinition ("Not an equipment definition."), a definition with no slot tag, a request whose slot tag does not match the definition's ("The item does not fit that slot."), and anything Can Equip Item refuses ("Equipping is currently blocked.").
Equip(Request)Authority only - otherwise fails with "Equip requires authority." Runs CanEquip, then Equip Item with the request's definition, source object and slot index. On success reports the resolved slot tag and index, plus Displaced Source when it pushed something out.
UnequipBySource(SourceObject, bForce)Finds the entry whose instance holds that source and unequips it. True only if it actually left.
UnequipSlot(SlotTag, SlotIndex, bForce)Unequips the occupant of that slot. False when the slot was empty.
IsSourceEquipped(SourceObject, OutSlotTag, OutSlotIndex)Whether an object is currently equipped, and optionally where.
GetEquippedSource(SlotTag, SlotIndex) / GetEquippedSources(Out)The source object in a slot, or every non-null source.
GetSlotTagForDefinition(DefinitionClass, OutSlotTag)The definition's slot tag. False for a class that is not an equipment definition - the cheap 'is this equippable' test.
GetSlotLayout(OutSlots)Copies the pawn's slot layout. Empty when the pawn has no slots component.
Verify
Call Find Equipment Host Component (UCrimsonEquipmentBridgeStatics) on the pawn: it returns the component that implements the host interface.

2. Read equipment from the item side

The query half of the bridge is Blueprint-exposed as pure statics on UCrimsonEquipmentBridgeStatics - use these in inventory UI to show an Equipped badge, or to gray out a row.

Is Object Equipped (Context Actor = the pawn, Source Object = your item) returns a bool plus Out Slot Tag and Out Slot Index. Get Equipped Object In Slot goes the other way, and Get Equipment Slot Layout gives you the cells to draw.

None of these need authority - the equipment list replicates, so the client's answer matches the server's.

Verify
Equip an item through the bridge, then ask Is Object Equipped for it on a client: true, with the slot tag and index the server chose.

3. Equip from the item side

Equipping is a mutation, so it runs on the server, behind your own routing (How-To: Get the Building Blocks, step 4). Build an FCrimsonEquipRequest and hand it to the host.

The mutating half is C++ only
ICrimsonEquipmentHost is declared CannotImplementInterfaceInBlueprint and Equip / CanEquip / UnequipBySource / UnequipSlot are plain C++ virtuals, so there are no Blueprint nodes for them. A Blueprint-only project equips by calling Equip Item on the manager directly from a server RPC - which works, at the cost of a CrimsonEquipment reference in that Blueprint. Use the C++ bridge when the calling module must stay independent.

From Blueprint, route the click to your PlayerController's Server Equip Item event and call Equip Item on the manager there, as How-To: Get the Building Blocks step 4 shows. Pass your item object into the Source Object pin - that is what makes Is Object Equipped work later.

To unequip, call Unequip Item In Slot (Slot Tag, Slot Index) from the same server event, or Unequip Item with the instance from Get Equipment Instance For Slot.

Displaced Source is how you avoid losing an item
Equipping into a full slot silently removes the occupant. Displaced Source is the object that was pushed out, and returning it to the bag is the item system's job - nothing in CrimsonEquipment does it for you. It is only meaningful for the equip that just ran.
Verify
Equip a second weapon into a one-count weapon slot: b Success is true, and Displaced Source is the first weapon's item object - which your inventory can now re-home.

4. Keep the two systems in step

The item system owns the item; the equipment system owns the slot. Keep exactly one source of truth for each and let the messages carry the rest.

QuestionWho answers it
Does the player own this item?The item system. CrimsonEquipment never checks.
Is this item equipped, and where?The equipment system, through IsSourceEquipped.
Should this item be locked from being dropped or sold?The item system, driven by IsSourceEquipped or by the source-changed message.
Which slot does this item fit?GetSlotTagForDefinition on the host - it reads the definition, so the item only has to carry the definition class.
Is the player allowed to equip it right now?Can Equip Item on your manager subclass, plus whatever your server RPC validates. See How-To: Gate Equipping and Unequipping.
Runtime-sourced entries are not saved here
Gather Save Data skips any entry whose source object is a runtime object rather than an asset, precisely so the two systems do not both restore the same equip. When the source is an inventory item instance, the item system persists that it was equipped and re-equips it on load. See How-To: Save and Restore Equipment.
Verify
Equip through the bridge, then ask both sides: the inventory reports the item as equipped, and the manager reports the same slot and index. Unequip and both agree again.

See also

  • How-To: Gate Equipping and Unequipping
  • How-To: Save and Restore Equipment
  • API Reference