Skip to content

ItemBagAsset — Backpack Storage and the Clothing Base

Overview

ItemBagAsset extends ItemClothingAsset and represents backpack items worn in the backpack equipment slot. It adds two fields — _width and _height — that define the dimensions of the storage grid the backpack provides when equipped. The backpack's storage grid is added to the player's total inventory capacity: a player with a 5×4 backpack gains 20 additional inventory slots beyond their base capacity.

The class inherits all clothing properties (armor, explosion armor, falling damage multiplier, visibility conditions, movement speed modifiers) and adds the storage grid dimensions. The isPro flag from ItemClothingAsset gates whether the width/height fields are parsed — pro cosmetic backpacks skip the storage dimension parsing entirely.

Inheritance Chain

Asset
  └── ItemAsset
        └── ItemClothingAsset
              └── ItemBagAsset

ItemBagAsset sits on the clothing chain. This means backpacks inherit:

  • From ItemAsset: ID, rarity, size, slot, quality, name, description, tradeability.
  • From ItemClothingAsset: Armor values, explosion armor, falling damage multiplier, movement speed modifiers, visibility conditions (hair/beard visibility), slot assignment (backpack slot), and the isPro flag.

Backpacks do not inherit from ItemStorageAsset or ItemBarricadeAsset — they are clothing items that happen to provide inventory space.

Fields

Width (_width)

csharp
private byte _width;
public byte width => _width;

The horizontal dimension of the backpack's storage grid in inventory slots. A width of 5 means the backpack adds 5 columns of inventory space.

Parsed from .dat key Width:

csharp
_width = p.data.ParseUInt8("Width");

As a byte, the max width is 255. Practical values range from 1 to 10. Vanilla backpacks typically use widths of 3-7.

Height (_height)

csharp
private byte _height;
public byte height => _height;

The vertical dimension of the backpack's storage grid in inventory slots. A height of 4 means the backpack adds 4 rows of inventory space.

Parsed from .dat key Height:

csharp
_height = p.data.ParseUInt8("Height");

As a byte, the max height is 255. Practical values range from 1 to 10. The total additional slots = _width * _height.

The isPro Gate

The width/height parsing is gated by the isPro flag from ItemClothingAsset:

csharp
if (!isPro)
{
    _width = p.data.ParseUInt8("Width");
    _height = p.data.ParseUInt8("Height");
}

When isPro is true (the item is a "pro" cosmetic), the width and height fields are skipped. The backpack still loads and equips, but its _width and _height remain at their default values (0 for byte fields). A pro cosmetic backpack with width=0 and height=0 provides no additional storage — it's purely cosmetic.

This gate exists because pro cosmetic items are monetized cosmetics that should not provide gameplay advantages (extra inventory space). The isPro flag blocks the storage dimension parsing, ensuring pro backpacks are cosmetic-only.

Default Values When Skipped

When isPro is true and parsing is skipped:

  • _width = 0 (default byte value)
  • _height = 0 (default byte value)
  • The BuildDescription check width > 0 && height > 0 evaluates to false, so no storage dimensions are displayed in the tooltip.
  • The inventory system checks width > 0 && height > 0 before adding grid space. A zero-dimension backpack adds no slots.

Description UI (BuildDescription)

csharp
public override void BuildDescription(ItemDescriptionBuilder builder, Item itemInstance)
{
    base.BuildDescription(builder, itemInstance);

    if (!builder.HasFlag(EItemDescriptionFlags.Uncategorized))
        return;

    if (width > 0 && height > 0)
    {
        builder.Append(
            PlayerDashboardInventoryUI.localization.format(
                "ItemDescription_StorageDimensions", width, height
            ),
            DescSort_Important
        );
    }
}

The description adds a line showing the storage dimensions when both width and height are positive:

Storage: 5 x 4 (20 slots)

The localization key ItemDescription_StorageDimensions formats the display string. The DescSort_Important constant places this line near the top of the tooltip, after item name and rarity but before less critical properties.

The width > 0 && height > 0 guard prevents:

  • Pro cosmetic backpacks (where parsing is skipped and both are 0) from showing a nonsensical "Storage: 0 x 0" line.
  • Bugged assets with zero dimensions from showing misleading storage info.

Inventory Integration

When a backpack is equipped in the backpack slot, the player's inventory system creates additional storage pages or extends existing pages based on _width and _height:

Grid Addition

The backpack adds a rectangular grid of width × height slots to the player's inventory. The grid is typically appended as a new inventory page or as an extension of the existing backpack page:

Player base inventory: 2 pages of 5×5 (50 slots)
Equip 5×4 backpack:     +1 page of 5×4 (20 slots)
Total:                  70 slots

Slot Calculation

The total additional slots are width * height. For a 7×6 backpack: 42 slots. For a 3×3 backpack: 9 slots.

The grid is rectangular — width columns by height rows. The inventory system renders this as a grid of square slots in the UI.

Unequip Handling

When the backpack is unequipped (removed from the backpack slot), the additional storage grid is removed. Items stored in the backpack grid that exceed the player's base capacity are handled by:

  1. Item drop: Items in the backpack slots are dropped at the player's feet as world pickups.
  2. Overflow prevention: The game checks if the player has enough base capacity before allowing unequip. If unequipping would cause item loss due to insufficient base slots, the unequip may be blocked with a warning.
  3. Graceful overflow: If blocking is disabled, excess items drop to the ground.

Multiple Backpacks

A player can only equip one backpack at a time (in the backpack slot). Carrying additional backpacks in the main inventory does not provide extra storage — only the equipped backpack's grid is active. Backpacks in the inventory take up inventory slots like any other item.

Interaction with Other Storage Sources

Base Inventory

Every player has a base inventory capacity defined by the game mode config. This is typically represented as the "body" inventory — pockets, hands, and basic carrying capacity. The backpack adds to this base, not replaces it.

Clothing Pocket Storage

Some clothing items (shirts, pants, vests) provide pocket storage slots in addition to their armor values. These are separate from backpack storage. The total inventory capacity is:

Total = baseSlots + backpackSlots + shirtPocketSlots + pantsPocketSlots + vestPocketSlots

The backpack is the largest contributor to total capacity in most loadouts.

Vehicle and Storage Container Interaction

The backpack only affects the player's personal inventory. Items in vehicle storage, crates, lockers, or other containers are separate and unaffected by backpack dimensions.

Cargo Data Export

ItemBagAsset overrides BuildCargoData to export bag-specific fields to the Bag Cargo table:

csharp
internal override void BuildCargoData(CargoBuilder builder)
{
    base.BuildCargoData(builder);

    CargoDeclaration data = builder.GetOrAddDeclaration("Bag");
    data.Append("GUID", GUID); // Key

    data.Append("Width", width);
    data.Append("Height", height);
}

The Bag Cargo table exports:

  • GUID: Asset GUID (primary key).
  • Width: Grid width in slots.
  • Height: Grid height in slots.

The base class BuildCargoData is called first, which exports ItemClothingAsset fields (armor, movement modifiers) and ItemAsset fields (ID, rarity, size) to their respective Cargo tables.

Description UI — Inherited Clothing Rows

Because ItemBagAsset calls base.BuildDescription(builder, itemInstance) before adding its storage line, the backpack tooltip also displays all clothing-related stats from ItemClothingAsset:

  • Armor multiplier (if not 1.0).
  • Explosion armor (if not 1.0).
  • Falling damage multiplier (if not 1.0).
  • Movement speed modifiers (if present).

Backpacks with armor values are rare in vanilla (most backpacks have armor = 1.0, meaning no damage reduction) but entirely valid. A "bulletproof backpack" with Armor 0.7 would reduce incoming damage by 30% while providing storage.

Modding Guide

Creating a Basic Backpack

ID 58400
ItemName "Rucksack"
Rarity Common
Size_X 2
Size_Y 2
Slot Backpack
Width 5
Height 4

This creates a common backpack, 2×2 when in the inventory, that provides a 5×4 (20-slot) storage grid when equipped in the backpack slot.

Creating a Pro Cosmetic Backpack (No Storage)

ID 58401
ItemName "Designer Backpack"
Rarity Mythical
Size_X 2
Size_Y 2
Slot Backpack
Pro true

Even if Width and Height are specified, the isPro gate skips them. The backpack provides zero additional inventory slots. It is purely cosmetic.

Creating an Armored Backpack

ID 58402
ItemName "Ballistic Backpack"
Rarity Epic
Size_X 2
Size_Y 3
Slot Backpack
Width 4
Height 3
Armor 0.85
Armor_Explosion 0.8

This backpack provides 12 storage slots AND reduces incoming damage by 15% (armor 0.85) and explosive damage by 20% (armor 0.8). The tooltip shows both storage dimensions and armor values.

Creating a Large Late-Game Backpack

ID 58403
ItemName "Military ALICE Pack"
Rarity Legendary
Size_X 3
Size_Y 2
Slot Backpack
Width 7
Height 6
Movement_Speed_Multiplier 0.9

A 7×6 (42-slot) backpack that reduces movement speed by 10% (multiplier 0.9). Large backpacks often have speed penalties to balance their storage advantage.

Common Pitfalls

  1. Pro flag blocking storage: If you set Pro true on a backpack, even accidentally, the width and height are not parsed. The backpack provides zero storage. This is a common source of "my backpack doesn't give extra slots" bug reports.

  2. Zero-width or zero-height: A backpack with Width 0 or Height 0 provides no storage. The tooltip doesn't show dimensions (guarded by width > 0 && height > 0). Always set both to positive values.

  3. Extremely large backpacks: A backpack with Width 255 and Height 255 provides 65,025 slots. This is technically valid but will cause extreme UI lag, memory pressure, and disproportionate gameplay advantage. The inventory UI is not designed for grids this large. Keep dimensions reasonable (under 10×10).

  4. Slot assignment mismatch: Backpacks must use Slot Backpack. If assigned to a different slot (e.g., Slot Primary), the backpack functions as a weapon, not a backpack. The storage grid is not added because the inventory system only checks the backpack slot.

  5. Size in inventory vs. storage provided: The Size_X/Size_Y fields define how much inventory space the backpack item takes up when NOT equipped. The Width/Height fields define how much storage it provides when equipped. These are independent. A backpack that takes 3×3 slots in the inventory (Size_X 3 Size_Y 3) could provide 5×4 storage when equipped (Width 5 Height 4).

  6. Backpack stacking: Like all equipment items, backpacks are not stackable. Amount is always 1. The inventory system treats backpack items as unique equipment, not fungible stacks.

  7. Armor stacking with other clothing: The backpack's armor value stacks multiplicatively with other clothing armor values. A shirt with armor 0.8 plus a backpack with armor 0.9 gives total damage reduction of 1 - (0.8 * 0.9) = 0.28 (28% reduction). This is the clothing damage formula, not specific to backpacks.

Clothing Inheritance: What ItemBagAsset Gets for Free

Because ItemBagAsset extends ItemClothingAsset, every backpack inherits a substantial set of fields and behaviors without any additional code in the bag class itself. Understanding this inheritance is critical for modders creating backpacks with additional properties.

Inherited Clothing Fields

FieldType.dat KeyDefaultDescription
_armorfloatArmor1.0Multiplier to incoming damage. 0.5 = 50% reduction
_explosionArmorfloatArmor_Explosion_armor valueMultiplier to explosive damage
fallingDamageMultiplierfloatFalling_Damage_Multiplier1.0Multiplier to falling damage
shouldMirrorboolMirrorfalseWhether the 3D model mirrors for left/right
hairVisibleboolHair_VisibletrueWhether player hair renders when worn
beardVisibleboolBeard_VisibletrueWhether player beard renders when worn
movementSpeedMultiplierfloatMovement_Speed_Multiplier1.0Movement speed modifier when equipped
isProboolProfalsePro cosmetic flag — gates storage parsing

Clothing Slot Assignment

ItemClothingAsset defines which equipment slot the item occupies. The slot is determined by the item's _slot field (from ItemAsset) being mapped to a clothing slot type. For backpacks, this is typically Slot Backpack, which maps to the backpack equipment slot in the player's loadout.

The slot mapping is:

ItemAsset._slot → ESlotType → EquipmentSlot

Backpacks use the dedicated backpack slot. A player can equip only one backpack at a time. Attempting to equip a second backpack replaces the first (unequipping it and removing its storage grid).

Armor Calculation Stack

When multiple clothing items with armor values are equipped, the total armor is multiplicative:

totalArmor = shirt.armor * pants.armor * vest.armor * hat.armor * backpack.armor

The backpack's armor contributes to this product identically to any other clothing piece. There is no distinction between "body armor" and "backpack armor" in the damage formula — the backpack's armor reduces damage to all body parts equally.

For explosion damage:

totalExplosionArmor = shirt.explosionArmor * pants.explosionArmor * ... * backpack.explosionArmor

If Armor_Explosion is not specified in the .dat, it defaults to the Armor value. A backpack with Armor 0.8 but no Armor_Explosion key has explosionArmor = 0.8.

Movement Speed Penalty Pattern

Many large backpacks in vanilla content use the Movement_Speed_Multiplier field to add a speed penalty:

Movement_Speed_Multiplier 0.9

This reduces the player's movement speed by 10%. The multiplier stacks multiplicatively with other equipment speed modifiers. A backpack with 0.9 and pants with 0.95 gives total speed modifier of 0.9 * 0.95 = 0.855 (14.5% reduction).

The speed penalty is a balance lever: large-storage backpacks cost mobility, small-storage backpacks allow faster movement, and cosmetic (pro) backpacks have neither storage nor speed penalty. A well-designed backpack ecosystem gives players meaningful trade-offs between storage capacity, protection, and mobility.

Inventory Grid Mathematics

Grid Allocation

When a backpack is equipped, the inventory system allocates a rectangular grid of _width × _height slots. The grid is rendered in the inventory UI as rows and columns of square cells.

The grid coordinates use (column, row) indexing with origin at top-left:

(0,0) (1,0) (2,0) (3,0) (4,0)
(0,1) (1,1) (2,1) (3,1) (4,1)
(0,2) (1,2) (2,2) (3,2) (4,2)
(0,3) (1,3) (2,3) (3,3) (4,3)

This is a 5×4 grid (width=5, height=4).

Item Placement Algorithm

When an item is added to the backpack, the game uses a first-fit algorithm:

  1. Iterate rows from top to bottom (0 to height-1).
  2. Iterate columns from left to right (0 to width-1).
  3. Check if the item fits at (col, row) without overlapping existing items.
  4. If it fits, place it there.
  5. If no position fits, the item cannot be stored.

The time complexity is O(width × height × itemWidth × itemHeight) in the worst case. For typical backpacks (5×4) and items (1×1 or 2×2), this is negligible.

Slot Memory Overhead

Each backpack grid slot is a C# struct containing:

  • Item ID reference (int = 4 bytes)
  • Amount (byte = 1 byte)
  • Quality (byte = 1 byte)
  • State bytes (variable, typically 0-8 bytes)
  • Position in grid (2 bytes for x, 2 bytes for y)
  • Metadata flags (1 byte)

Total per occupied slot: ~11-19 bytes. For a 5×4 backpack with 20 occupied slots: ~220-380 bytes. Memory overhead is minimal for typical backpack dimensions.

Grid Fragmentation

Repeated add/remove operations fragment the backpack grid — small empty spaces accumulate that individual items can't fill. The first-fit algorithm exacerbates this by always placing items at the earliest valid position, leaving gaps at the end of rows.

Example of fragmentation:

[A][A][ ][B][ ]
[A][A][ ][ ][ ]
[C][ ][ ][ ][ ]
[ ][ ][ ][ ][ ]

Space exists for a 1×1 item in column 2, row 0; column 3, row 1; and all of row 3. But a 2×2 item cannot fit despite 15 available slots because the gaps are disconnected.

The vanilla inventory system does not defragment. Players must manually rearrange items to consolidate free space.

Grid Serialization

When the server saves player inventory, the backpack grid is serialized as a flat list of occupied slots with (x, y, item) tuples. Empty slots are NOT serialized — the save file only contains occupied slots. On load, the grid is reconstructed by placing each item at its recorded (x, y) position.

This sparse serialization is efficient for partially filled backpacks. A 5×4 backpack with 5 items serializes 5 entries rather than 20. The positional data ensures items restore to their exact locations — the first-fit algorithm is bypassed on load.

Pro Cosmetics and Monetization

The isPro Flag in Context

The isPro flag is a monetization gate. Pro cosmetic items are purchasable DLC or microtransaction items that change appearance without affecting gameplay. The isPro flag guarantees this separation:

  • Pro backpacks: cosmetic appearance, zero storage.
  • Non-pro backpacks: gameplay storage, may or may not have custom appearance.

The flag is checked during PopulateAsset:

csharp
if (!isPro)
{
    _width = p.data.ParseUInt8("Width");
    _height = p.data.ParseUInt8("Height");
}

Pro items CAN still specify Width and Height in their .dat — the values are simply ignored. This allows a single .dat template to be used for both pro and non-pro variants, with the pro variant overridden by the Pro flag.

Detecting Pro Status at Runtime

Plugins and mods can check isPro on an ItemClothingAsset:

csharp
ItemBagAsset bag = item.GetAsset() as ItemBagAsset;
if (bag != null && bag.isPro)
{
    // This is a cosmetic-only backpack
}

The isPro flag is inherited from ItemClothingAsset and is accessible on any clothing-derived item, not just backpacks. A plugin could, for example, prevent pro backpacks from being used in crafting recipes or restrict them to specific inventory pages.

Economy Impact

Pro backpacks don't add inventory space, so they don't affect the item economy. They're pure cosmetics with zero gameplay impact. This is by design — paid items must not provide competitive advantages. The isPro gate is the enforcement mechanism: even if a pro backpack's .dat accidentally includes Width 10 Height 10, the parsed width and height are zero.

.dat Reference Table

ItemBagAsset Complete .dat Schema

KeyTypeDefaultRequiredDescription
IDushortYesUnique item ID
ItemNamestringYesDisplay name
ItemDescriptionstring""NoTooltip description
RarityEItemRarityCommonNoItem rarity tier
Size_Xbyte1NoInventory size width (when unequipped)
Size_Ybyte1NoInventory size height (when unequipped)
SlotESlotTypeYesMust be Backpack
Widthbyte0ConditionalStorage grid width (PARSED ONLY if !isPro)
Heightbyte0ConditionalStorage grid height (PARSED ONLY if !isPro)

Clothing Base Class Fields (Inherited)

KeyTypeDefaultDescription
Armorfloat1.0Multiplier to incoming damage
Armor_ExplosionfloatArmorMultiplier to explosive damage
Falling_Damage_Multiplierfloat1.0Multiplier to falling damage
Movement_Speed_Multiplierfloat1.0Movement speed modifier when equipped
ProboolfalsePro cosmetic gate
Hair_VisiblebooltrueHair rendering when worn
Beard_VisiblebooltrueBeard rendering when worn
MirrorboolfalseMirror 3D model left/right

Inventory Grid Configuration

KeyTypeDefaultDescription
Amountbyte1Stack size (always 1 for equipment)
ExchangeablebooltrueCan be traded between players

Debugging and Troubleshooting

Symptom: "Backpack doesn't add inventory slots"

Check in order:

  1. Verify Slot is set to Backpack.
  2. Verify isPro is false (or Pro key is absent).
  3. Verify Width and Height are set to positive values.
  4. Verify the backpack is equipped (not just in inventory).
  5. Verify no other equipment is blocking the backpack slot.
  6. Verify the player's total slot count matches baseSlots + (width * height).
  7. Check server logs for equipment slot assignment errors.

Symptom: "Backpack adds slots but they're invisible"

The inventory UI may not be updating:

  1. The UI refreshes on inventory change events — try dropping/picking up an item.
  2. The backpack page may be scrolled off-screen — check for page navigation arrows.
  3. The UI grid renderer may have a null reference — check client logs.

Symptom: "Pro backpack has storage despite being pro"

  1. Verify the .dat has Pro true.
  2. Verify the asset was reimported after adding the Pro flag.
  3. Clear the asset bundle cache and reload.
  4. If the backpack was placed in inventory before the Pro flag was added, existing instances may retain old parsed values. Spawn a fresh instance.

Symptom: "Armor value on backpack doesn't reduce damage"

  1. Verify Armor is set to a value < 1.0.
  2. Verify no other plugin is overriding damage calculations.
  3. Verify damage type is affected by armor (some damage types bypass armor).
  4. Check the damage formula: finalDamage = baseDamage * shirt.armor * pants.armor * vest.armor * hat.armor * backpack.armor.

Symptom: "Movement speed penalty from backpack not applying"

  1. Verify Movement_Speed_Multiplier is set to a value < 1.0.
  2. Verify the backpack is equipped (not in inventory).
  3. Verify no other plugin is overriding movement speed.
  4. The speed multiplier stacks multiplicatively — check for other equipment offsetting the penalty.