Skip to content

Cargo

The Cargo system is X4’s mechanism for holding wares in entities. The engine exposes three related cargo types — cargolist (base), containercargolist (container-scoped variant), modulecargolist (module-scoped) — that share the underlying ware-amount-list interface but add cargo-specific properties (free space, capacity, ware tags).

wareamountlist
└── cargolist (pseudo) — adds cargo-specific properties
├── containercargolist (pseudo) — adds container-level free/capacity
└── modulecargolist (pseudo) — adds module-level free/capacity

All cargo types are pseudo-types (engine-internal abstraction over ware-amounts; not directly instantiable from MD).

Inherited from wareamountlist:

  • .list — all wares as a script list
  • .table — all wares + amounts as a table
  • .count — number of distinct wares
  • .{$ware}.count — amount of specific ware

Plus cargo-specific:

PropertyTypeDescription
.{$ware}.freeintegerAmount of $ware that can be added (= max - current)
.{$ware}.maxintegerMaximum $ware in cargo (ignoring existing)
.tagslistCompatible ware tags
.hastag.{$tag}booleanCompatible with ware tag?
.hastag.<tagname>booleanShortcut for hastag.{tag.}
.hasanytag.{$list}booleanHas any tag from list?
.hasalltags.{$list}booleanHas all tags from list?

Used as container.cargo. Adds free space + capacity tracking per ware-transport tag:

PropertyTypeDescription
.free.alllargeintTotal free cargo volume
.free.solidlargeintFree volume for solids
.free.liquidlargeintFree volume for liquids
.free.condensatelargeintFree volume for condensate
.free.containerlargeintFree volume for containers
.free.universallargeintFree volume for universal
.free.{$tag}largeintFree volume for specified tag
.capacity.alllargeintTotal volume available
.capacity.solidlargeintTotal solid capacity
.capacity.liquidlargeintTotal liquid capacity
.capacity.condensatelargeintTotal condensate capacity
.capacity.containerlargeintTotal container capacity
.capacity.universallargeintTotal universal capacity
.capacity.{$tag}largeintTotal capacity for tag

Used as module.cargo for module-level storage. Same properties as containercargolist but module-specific.

<set_value name="$free" exact="$ship.cargo.free.all"/>
<do_if value="$free ge 100">
<add_inventory entity="$ship" ware="ware.energycells" exact="100"/>
</do_if>
<do_for_each name="$ware" in="$ship.cargo.list">
<write_to_logbook text="$ware.{1}.name + ': ' + $ware.{2}"/>
</do_for_each>

"Check container is compatible with ware tag"

Section titled “"Check container is compatible with ware tag"”
<do_if value="$ship.cargo.hastag.tag.container">
<!-- Can carry container wares -->
</do_if>
<set_value name="$max" exact="$ship.cargo.{ware.energycells}.free"/>
  • wareamountlist storage degrades when stored in a variable — access inline always. See Ware storage gotcha.
  • cargolist.{$ware}.max is the MAXIMUM possible — not current. Use cargolist.{$ware}.count for current amount.
  • Cargo is byte-level capacity tracked per WARE TRANSPORT TAG — solid/liquid/condensate are separate budgets. Adding container-tagged ware doesn’t shrink solid capacity.
  • Ship/station modulecargolist and containercargolist differ slightly — modulecargolist is per-module, containercargolist is aggregated across modules.
  • add_inventory ware="$string" silently fails — must wrap as ware.{$string}. See add_inventory gotcha.
ActionPurpose
<add_inventory>Add a ware to cargo
<remove_inventory>Remove a ware from cargo
<transfer_inventory>Transfer wares between containers
<set_cargo_target>Set target amount for a traded ware

Cargo is the central ware-storage abstraction. Modders interact with it via container.cargo (most stations) or ship.cargo (transports). The free/capacity per ware-transport-tag is the key to understanding why a “full” ship can still accept more wares — it depends on the tag.