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.cpp → Manifest()
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.cpp → GiveAbility()
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 |