Skip to content

Item Fragments

Summary: Composable item behavior through FItemFragment structs. Fragments define properties (grid, icon), equipment stats, weapon behavior, granted abilities, and special mechanics. All equipment-related fragments now receive FFragmentEquipContext for unified reference access.

Table of Contents


Architecture Overview

FItemFragment (Base)
├── UI Fragments (display data)
│   ├── FGridFragment         → Inventory dimensions
│   ├── FImageFragment        → Icon texture
│   ├── FItemNameFragment     → Display name
│   └── FItemDescriptionFragment → Tooltip text
├── Behavior Fragments (runtime state)
│   ├── FStackableFragment    → Stack count/limits
│   └── FConsumableFragment   → Usage tracking
├── Equipment Fragments (equip behavior)
│   ├── FEquipmentFragment    → GAS effects, visual actor
│   └── FWeaponFragment       → Combat stats, animation overlay
├── Ability Fragments (GAS integration)
│   └── FAbilityFragment      → Grant/remove abilities
└── Special Fragments (game-specific)
    ├── FQuestFragment        → Quest item behavior
    ├── FCraftingMaterialFragment → Crafting influence
    ├── FStonePlateFragment   → Glyph system
    └── FGlyphPieceFragment   → Glyph pieces

Key Design Principles

Principle Implementation
Composition Items compose fragments instead of inheriting behavior
Tag Identification Each fragment type has unique FGameplayTag
Context-Based Equipment fragments receive FFragmentEquipContext
Virtual Manifest Fragments can override Manifest() for initialization
Polymorphic Storage TInstancedStruct enables UPROPERTY storage

Core Concepts

Why Fragments?

Traditional inheritance creates rigid hierarchies:

UWeaponItem : UEquippableItem : UItem  ← Hard to add "quest weapon"

Fragments allow flexible composition:

Weapon Item = FGridFragment + FImageFragment + FEquipmentFragment + FWeaponFragment + FQuestFragment

Fragment vs Component

Aspect Fragment Component
Lifecycle Lives in item data Lives on actor
Replication Part of item manifest Separate replication
Storage TInstancedStruct UPROPERTY()
Purpose Define item behavior Runtime functionality

Fragment vs State Module

Fragments describe what an item is at template time. Some gameplay needs per-instance runtime state that mutates during play (Remnant Sealed→Awakened, Echo Mod reveal flags, desire progress). That's what state modules handle — they're the runtime counterpart to fragments.

Aspect Fragment (FItemFragment) State Module (FItemInstanceStateModule)
Mutability Static — copied from data asset Mutable — changes during play
Storage FItemManifest::Fragments UItemObject::StateModules
Authoring Designer on a UItemManifestDataAsset Server code (factory, tracker, crafting)
Example FEquipmentFragment (stats, modifiers) FRemnantItemState (Sealed/Awakened)

Heuristic: if two items with the same ItemID would have different values for this data, it's a state module. If they'd always share it, it's a fragment. See Item State Modules.

Marker Fragments

Some fragments carry no fields — they exist purely to identify an item. FRemnantFragment is the canonical example: HasFragmentOfType<FRemnantFragment>() answers "is this a Remnant?" while all the runtime data lives on the sibling state module. This keeps the manifest a complete "what is this item" snapshot without forcing instance data into the template layer.


Fragment Lifecycle

Creation (Item Manifest)

Item Data Asset
    ├─ Define fragments in editor
UItemObject::Manifest()
    ├─ Copy fragments from data asset
    ├─ Call Fragment::Manifest() on each
Item ready for use

Equipment Lifecycle

Equip Flow:
    Fragment::ApplyEquipmentEffects(Context)
    Fragment::OnEquip(Context)  [FAbilityFragment]

Unequip Flow:
    Fragment::RemoveEquipmentEffects(Context)
    Fragment::OnUnEquip(Context)  [FAbilityFragment]

Source Reference

  • Base fragment: ItemFragment.h:70-110
  • Manifest call: ItemObject.cppManifest()

Fragment Context Pattern

FFragmentEquipContext

All equipment-related fragment methods receive this context:

FFragmentEquipContext
├── PlayerController*     ← The owning player controller
├── OwningPawn*          ← Current possessed pawn
├── AbilitySystem*       ← Cached UAbilitySystemComponent
├── EquipmentSlot        ← FGameplayTag for target slot
└── EquippedItem*        ← The UItemObject being equipped

Methods Using Context

Fragment Method Purpose
FEquipmentFragment ApplyEquipmentEffects(Context) Apply GAS effects
FEquipmentFragment RemoveEquipmentEffects(Context) Remove GAS effects
FWeaponFragment ActivateWeaponOverlay(Context) Set animation overlay
FWeaponFragment DeactivateWeaponOverlay(Context) Reset animation overlay
FAbilityFragment OnEquip(Context) Grant ability
FAbilityFragment OnUnEquip(Context) Remove ability

Benefits

  • No repeated GetAbilitySystemComponent() lookups in each fragment
  • Fragments don't need to know reference acquisition logic
  • Easy to extend - add fields to context, not change signatures
  • Testable - can create mock contexts

Source Reference

  • Context struct: ItemFragment.h:22-68

Fragment Categories

Category Overview

Category Purpose Lifecycle
UI Display data for inventory/tooltips Read-only after manifest
Behavior Runtime state (stacks, usages) Modified during gameplay
Equipment Equip/unequip effects Active while equipped
Ability GAS ability granting Active while equipped
Special Game-specific mechanics Varies

UI Fragments

FGridFragment

Defines item size in spatial inventory:

Property Type Purpose
GridSize FIntPoint Width x Height in cells
GridPadding float Visual padding

FImageFragment

Item icon for UI:

Property Type Purpose
Icon TSoftObjectPtr<UTexture2D> Lazy-loaded icon
IconDimensions FVector2D Display size

FItemNameFragment

Display name:

Property Type Purpose
FragmentText FText Localized item name

FStackableFragment

Stacking behavior:

Property Type Purpose
MaxStackSize int32 Maximum stack count
StackCount int32 Current stack count

Source Reference

  • All UI fragments: ItemFragment.h:112-274

Equipment Fragments

FEquipmentFragment

Core equipment behavior - visual spawning and GAS effects. There is no base-attribute stat block: everything a base contributes inherently arrives as its pinned implicit modifier, so equipping only applies the item's modifiers:

Equip Flow:
    ApplyEquipmentEffects(Context)
        └─ ApplyGlobalModifiersToCharacter(Context)

Unequip Flow:
    RemoveEquipmentEffects(Context)
        ├─ RemoveGlobalModifiersFromCharacter(Context)
        └─ Clear DynamicEquipEffects

Key Properties

Property Purpose
ItemLevel Tier for modifier generation
BaseTypeID Links to base type data asset
Modifiers Prefixes, suffixes, implicits
EquipmentType Slot category tag
SkeletalMesh Visual mesh for AEquipActor
CompatibleSlots Valid equipment slots

Modifier Access

Method Returns
GetPrefixes() Prefix modifiers
GetSuffixes() Suffix modifiers
GetImplicits() Implicit modifiers
GetLocalModifiers() Non-GAS modifiers
GetGlobalModifiers() GAS-applied modifiers

FWeaponFragment

Weapon-specific properties and combat stats:

Property Purpose
BaseDamage Base damage value
BaseStaminaCost Stamina per attack
BasePoiseDamageMultiplier Poise damage scaling
BaseAttackSpeed Animation speed multiplier
MontageTables TMap<WeaponHand, UDataTable*> — montage tables per hand context
ComboConfigs TMap<WeaponHand, FComboConfiguration> — combo counts/multipliers per hand context
ChargeConfigs TMap<WeaponHand, FChargeConfiguration> — charge levels/timing per hand context
WeaponTypeTag Weapon category for animations

Hand-Aware Data Resolution

Montages, combo configs, and charge configs are all keyed by WeaponHand tag (Right, Left, Both, RightWithShield, ShieldOnly). Each lookup method falls back to the first TMap entry when the current hand context has no explicit mapping.

GetMontagesForHand(WeaponHand)      → DataTable for that hand context
GetComboConfigForHand(WeaponHand)   → Combo counts + multipliers for that hand context
GetChargeConfigForHand(WeaponHand)  → Charge levels + timing for that hand context

This means a single weapon defines different combat feel per hand context — a sword solo has 5-hit light chains while sword+shield might have 3-hit chains with different multipliers.

Animation Overlay

ActivateWeaponOverlay(Context)
    └─ Sets character overlay mode via MovementSystemComponent

DeactivateWeaponOverlay(Context)
    └─ Resets to default overlay mode

Source Reference

  • Equipment fragment: ItemFragment.h:290-432
  • Weapon fragment: ItemFragment.h:434-541

Ability Fragments

FAbilityFragment

Grants gameplay abilities when item is equipped:

OnEquip(Context)
    ├─ Get ASC from context
    ├─ Check if ability already exists on ASC
    │   └─ Yes: reuse existing, add input tag
    │   └─ No: create new FGameplayAbilitySpec
    ├─ Set SourceObject to equipped item
    └─ Store GrantedHandle for removal

OnUnEquip(Context)
    ├─ Get ASC from context
    └─ ClearAbility(GrantedHandle)

Key Properties

Property Purpose
AbilityClass The ability to grant
GrantedHandle Handle for removal

Source Reference

  • Ability fragment: ItemFragment.h:543-559
  • Grant logic: ItemFragment.cppGiveAbility()

Special Fragments

FQuestFragment

Quest item restrictions and behavior:

Property Purpose
RelatedQuestTag Associated quest
QuestObjectiveTag Specific objective
bConsumeOnQuestComplete Auto-remove when done
bCanBeDropped Allow dropping
bCanBeSold Allow vendor sales

FConsumableFragment

Usage tracking for consumables:

Property Purpose
MaxUsages Total charges
CurrentUsagesLeft Remaining charges

Lifecycle: Manifest() sets CurrentUsagesLeft = MaxUsages

FCraftingMaterialFragment

Crafting modifier influence:

Property Purpose
GuaranteedSpecificModifierID Force exact modifier
GuaranteedModifierFamilies Force modifier family
BiasedModifierFamilies Increase family weight
BiasMultiplier Weight increase factor

Priority: Specific > Guaranteed > Biased

Source Reference

  • Quest fragment: ItemFragment.h:561-612
  • Consumable fragment: ItemFragment.h:675-698
  • Crafting material: ItemFragment.h:713-812

Fragment Queries

From FItemManifest

Method Purpose
GetFragmentOfType<T>() Get single fragment by type
GetFragmentOfTypeMutable<T>() Get mutable fragment
GetAllFragmentsOfType<T>() Get all fragments of type
HasFragmentOfType<T>() Check if fragment exists

UItemFragmentLibrary (Blueprint)

Function Purpose
GetAllFragmentTagsFromItem() List all fragment tags
HasFragmentOfType() Check fragment presence
GetImageIcon() Get icon texture
GetGridSize() Get inventory dimensions
GetStackSize() Get current stack count
GetWeaponAttackSpeed() Get attack speed

Source Reference

  • Manifest queries: ItemManifest.h
  • Blueprint library: ItemFragmentLibrary.h

Public Contracts

Fragment Base

Method Purpose
GetFragmentTag() Returns fragment type tag
SetFragmentTag(Tag) Sets fragment type tag
Manifest() Virtual - called on item creation

FEquipmentFragment

Method Parameters Purpose
ApplyEquipmentEffects (FFragmentEquipContext&) Apply GAS effects
RemoveEquipmentEffects (FFragmentEquipContext&) Remove GAS effects
SpawnAttachedActor (Mesh, Item, SlotTag) Create visual actor
GetCompatibleSlots none Valid slot tags
GetSocketNameForTag (SlotTag) Skeleton socket name

FWeaponFragment

Method Parameters Purpose
ActivateWeaponOverlay (FFragmentEquipContext&) Set animation overlay
DeactivateWeaponOverlay (FFragmentEquipContext&) Reset animation overlay
GetBaseDamage none Base damage value
GetBaseStaminaCost none Stamina per attack
GetWeaponMontages none Default (first) montage table
GetMontagesForHand (FGameplayTag WeaponHand) Hand-aware montage table lookup
GetComboConfigForHand (FGameplayTag WeaponHand) Hand-aware combo config lookup
GetChargeConfigForHand (FGameplayTag WeaponHand) Hand-aware charge config lookup

FAbilityFragment

Method Parameters Purpose
OnEquip (FFragmentEquipContext&) Grant ability
OnUnEquip (FFragmentEquipContext&) Remove ability
GiveAbility (ASC, Item) Internal grant logic
RemoveAbility (ASC) Internal remove logic


Recent Changes

Date Change Impact
2026-04 Cross-reference to state modules; FRemnantFragment added as a marker-fragment example Clarifies the static-template vs runtime-state boundary. Fragments that carry no fields serve as identity markers for systems querying HasFragmentOfType<T>().
2026-03 Hand-aware combo and charge configs on FWeaponFragment ComboConfigs and ChargeConfigs TMaps keyed by WeaponHand, replacing standalone data assets. Combo/charge now vary per hand context.
2026-03 Hand-aware montages on FWeaponFragment MontageTables TMap keyed by WeaponHand replaces separate WeaponMontages/OffHandMontages/DualWieldMontages
2025-12-27 FFragmentEquipContext All equipment methods receive context instead of PlayerController
2025-12-27 Removed DestroyAttachedActor() Actor cleanup handled by EquipmentComponent
2025-12-27 Context-based overlay ActivateWeaponOverlay/DeactivateWeaponOverlay use context
2025-12-27 Simplified ability lifecycle OnEquip/OnUnEquip receive context with ASC
2025-12-27 Added FWeaponFragment setters SetWeaponTypeTag(), SetWeaponType() for unarmed config