Skip to content

Faction economy

How do NPC factions grow their economies during gameplay? Argon doesn’t just stand still β€” they expand when shortages appear, build new factories, and request more freighters. This is driven by factionlogic_economy.xml β€” ~4100 lines of MD running per-faction tick logic.

This overview explains the shortage β†’ evaluation β†’ corrective action loop that makes NPC economies dynamic.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Per-faction tick (every N minutes) β”‚
β”‚ β†’ EvaluateShortages β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ EvaluateShortages β”‚
β”‚ - Iterate faction sectors β”‚
β”‚ - Read demand vs supply per ware β”‚
β”‚ - Compute shortage scores β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Per-sector evaluation β”‚
β”‚ β†’ EvaluateSectorShortage β”‚
β”‚ - Which wares are short? β”‚
β”‚ - Which station type can fix? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Pick corrective action β”‚
β”‚ (one of N Request_X cues) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Request_X runs β”‚
β”‚ - Find suitable site β”‚
β”‚ - Issue build / spawn / etc. β”‚
β”‚ - Wait for outcome β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Outcome handler β”‚
β”‚ - Built / disregarded / destroyed β”‚
β”‚ - Update faction state β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The top-level cue EvaluateShortages runs per-faction on a heartbeat. It walks the faction’s sectors, reading ware demand and supply data, and identifies sectors where supply lags demand.

For each affected sector, it dispatches to EvaluateSectorShortage which determines:

  • Which wares are short
  • Which station-type (production factory, shipyard, defence station) can address the shortage
  • Whether the faction has resources / budget to act

When a shortage is identified, vanilla picks one of several Request_X actions:

Action cueWhat it does
Request_Production_ModuleAdd a production module to an existing factory
Request_FreighterSpawn a new transport ship to cover supply
Request_Commandeerable_FreighterSpawn a freighter that the player can capture (balance lever)
(and others)New station construction, defence reinforcement, etc.

Each Request_X is a substantial sub-cue with _Disregarded, _Destroyed, _Started, _Built, _Spawned, _Not_Requested sub-handlers. The state machine tracks:

  • Disregard (faction decided not to act after all)
  • Destruction (the requested asset was destroyed before completion)
  • Successful build / spawn

The verbose _Disregarded handling reflects that NPC economy decisions are tentative β€” many factors can cancel a planned build (faction goes hostile, budget changes, sector ownership flips).

EvaluateSectorShortage reads several signals:

SignalSourceIndicates
Container.cargo.{ware}.target - .amountPer-station target deficitHow much is missing
iswaitingforresources on production modulesBuild module stateSupply chain stalled
iswaitingforstorage on production modulesBuild module stateOutput backed up
Sector.yieldrating.{ware}Sector dataMining capacity

The heuristic isn’t pure shortage β€” it combines stalled state, deficit, and capability (does the sector have resources for the missing ware).

Custom mods that touch production modules (paused state, custom cargo) can confuse the shortage evaluator. Vanilla’s EvaluateSectorShortage reads iswaitingforresources and iswaitingforstorage directly β€” pause your custom modules with <set_production_paused> rather than alternative mechanisms.

When Request_Production_Module decides to build, it ultimately calls into the Construction sequence pipeline. Custom plans in constructionplans.xml are eligible β€” your mod’s plans are real options for NPC factions.

If your mod adds new wares, NPC factions don’t know to demand them. To integrate:

  1. Add wares to faction-relevant production chains
  2. Update factionlogic data so faction recognises ware demand
  3. Or accept that only player stations produce/consume new wares

EvaluateShortages runs per-faction per-tick across all sectors. Mods that add many factions or many sectors can multiply this cost. The vanilla tick interval is tuned for ~10 factions; adding more without adjusting the interval impacts CPU.

factionlogic_economy.xml (4103 lines) organises like:

factionlogic_economy.xml
β”œβ”€β”€ Manage_Stations (top-level state machine)
β”‚ β”œβ”€β”€ EvaluateShortages (heartbeat)
β”‚ β”‚ └── EvaluateSectorShortage (per-sector)
β”‚ β”œβ”€β”€ Request_Production_Module
β”‚ β”‚ β”œβ”€β”€ Request_Production_Module_Generate_Sequence
β”‚ β”‚ β”œβ”€β”€ Request_Production_Module_Sequence_Generated
β”‚ β”‚ β”œβ”€β”€ Request_Production_Module_Disregarded
β”‚ β”‚ β”œβ”€β”€ Request_Production_Module_Started
β”‚ β”‚ └── Request_Production_Module_Evaluate_Build
β”‚ β”œβ”€β”€ Request_Freighter
β”‚ β”‚ β”œβ”€β”€ Request_Freighter_Spawned
β”‚ β”‚ β”œβ”€β”€ Request_Freighter_Disregarded
β”‚ β”‚ β”œβ”€β”€ Request_Freighter_Destroyed
β”‚ β”‚ β”œβ”€β”€ Request_Freighter_Built
β”‚ β”‚ └── Request_Freighter_Not_Requested
β”‚ └── Request_Commandeerable_Freighter (similar)
└── (additional cues for support / cleanup)

The Disregard / Destroyed / Built handler pattern is consistent across all Request_X actions. Custom mods extending this should follow the same shape.

  • Galaxy seeding β€” initial state before this loop runs
  • Construction sequence β€” what Request_Production_Module calls into
  • Faction goals β€” the layer ABOVE economy (which decides hold / invade / patrol)
  • Trade routing β€” separate but related ware-distribution system