window.GDD = window.GDD || {}; function EconomyPage() { const [activeSection, setActiveSection] = React.useState('overview'); const refiningTable = [ { ore: 'Veldspar', mineral: 'Tritanium', yield: 415, batch: 333, time: '45s' }, { ore: 'Scordite', mineral: 'Pyerite', yield: 171, batch: 333, time: '45s' }, { ore: 'Pyroxeres', mineral: 'Nocxium', yield: 8, batch: 333, time: '60s' }, { ore: 'Kernite', mineral: 'Isogen', yield: 107, batch: 200, time: '60s' }, { ore: 'Omber', mineral: 'Isogen', yield: 86, batch: 500, time: '75s' }, { ore: 'Jaspet', mineral: 'Zydrine', yield: 8, batch: 500, time: '75s' }, { ore: 'Hemorphite', mineral: 'Nocxium', yield: 21, batch: 500, time: '90s' }, { ore: 'Arkonor', mineral: 'Megacyte', yield: 18, batch: 200, time: '120s' }, ]; const manufacturingRecipes = [ { product: 'Mining Laser I', minerals: 'Tritanium ×200, Pyerite ×80', time: '5m', station: 'Any', skill: 'Industry I' }, { product: '150mm Railgun', minerals: 'Tritanium ×400, Pyerite ×150, Nocxium ×20', time: '15m', station: 'Any', skill: 'Industry II' }, { product: 'Shield Booster I', minerals: 'Tritanium ×300, Isogen ×50', time: '10m', station: 'Any', skill: 'Industry II' }, { product: 'Frigate Hull', minerals: 'Tritanium ×2000, Pyerite ×800, Nocxium ×100', time: '30m', station: 'Factory', skill: 'Industry III' }, { product: 'Cruiser Hull', minerals: 'Tritanium ×8000, Pyerite ×3000, Isogen ×500, Nocxium ×200', time: '2h', station: 'Factory', skill: 'Industry IV' }, { product: '1MN Afterburner', minerals: 'Tritanium ×150, Pyerite ×50, Isogen ×20', time: '8m', station: 'Any', skill: 'Industry II' }, ]; const faucetsAndSinks = [ { type: 'faucet', name: 'NPC Buy Orders', description: 'Station NPCs buy basic ores at floor prices. Guarantees new players can always earn ISK.', rate: '~2,000 ISK/min for rookie miner' }, { type: 'faucet', name: 'Insurance Payout', description: 'Ship destruction triggers insurance payout (30–120s delay). Tier-dependent: 40–95% of hull value. See Gameplay → Insurance tab.', rate: 'Varies by ship value and tier' }, { type: 'faucet', name: 'Mission Rewards', description: 'NPC agents pay ISK for completed missions. Scaling rewards based on mission tier and standing. See Gameplay → Missions tab.', rate: '~5,000–300,000 ₢ per mission (level 1–4)' }, { type: 'faucet', name: 'Bounty Prizes', description: 'NPC pirates drop bounty ISK when destroyed. Higher in low-sec space.', rate: '~1,000–20,000 ISK per kill' }, { type: 'faucet', name: 'Loyalty Point Store', description: 'Mission LP can be exchanged for faction items at below-market prices, creating indirect ISK value. See Gameplay → Missions tab.', rate: '~500 LP per mission, redeemable for items worth 1–50₢/LP' }, { type: 'sink', name: 'Market Tax', description: '2% tax on all market transactions. Higher in NPC stations, lower in player stations (post-MVP).', rate: '2% of transaction value' }, { type: 'sink', name: 'Manufacturing Fees', description: 'Station takes a cut of mineral value as a manufacturing fee.', rate: '1–5% of output value' }, { type: 'sink', name: 'Ship Purchase', description: 'Buying ships and modules from market or manufacturing. Largest single sink.', rate: 'Variable' }, { type: 'sink', name: 'Insurance Premiums', description: 'Players pay 10–50% of hull value for insurance coverage. See Gameplay → Insurance tab.', rate: '10–50% of hull value per 30-day policy' }, { type: 'sink', name: 'Blueprint Research', description: 'ME/TE research costs ISK and time. See Economy → Manufacturing tab.', rate: '50,000–5,000,000 ₢ per research level' }, { type: 'sink', name: 'Crew Wages', description: 'AI crew members require wage payments. Higher rank = higher cost. (Post-MVP)', rate: '~500–5,000 ISK/cycle' }, ]; return (
Player-led economy with NPC support as an underlying demand/supply buffer. Players mine, refine, manufacture, and trade. NPCs provide a price floor and basic market liquidity so new players always have a way to earn and spend.
{step.desc}
| Channel | Propagation | Latency | Reliability | Example |
|---|---|---|---|---|
| Local Market | Instant, system-only | 0s | 100% — live order book | You see every buy/sell order in your current station |
| Local Chat | Instant, system-only | 0s | Unverified — players lie | "Scordite prices are crashing in Amarr" — could be true, could be market manipulation |
| Ship AI Reports | Aggregated, player-specific | Real-time | High — computed from data your ship has seen | Zora says: "Veldspar is 18% below its 7-day average here. I've logged 3 similar price dips that corrected within 2 hours." |
| Region Market Data | Delayed by jump distance | 2–10 min | Stale — snapshot, not live | The price you see for a system 5 jumps away is from 5 minutes ago. It may have moved. |
| News Feed | Galaxy-wide events | 15–30 min | Factual but delayed | "Major fleet engagement in PF-346. Megacyte supply disruptions expected." Includes world events: faction wars, anomalies, migrations. |
| Scout Reports | Manual, player-to-player | Variable | Trust-based | A corpmate tells you they saw a Tritanium shortage in Rens. First-hand intel. |
The player who knows a price discrepancy exists first can fill a hauler and profit. The player who arrives late finds the gap already closed. This is why speed of information matters, and why players will pay for better intel, scout networks, and fast ships for information running.
Because market data from other systems is delayed, traders must predict where prices are heading. They see a snapshot from 5 minutes ago and must decide: is the trend still moving, or has it reversed? This creates genuine risk and reward from pure information work — no combat required.
Systems farther from trade hubs have more stale data and wider spreads. Deep null-sec markets are almost blind — the player who establishes a reliable supply chain out there controls the local economy. Distance is not just travel time; it's an information barrier.
The ship AI (Zora) is a force multiplier for information. She remembers every price the player has seen, spots patterns, flags anomalies, and can continue monitoring markets while the player is offline. A high-phase Zora is worth more than any single module — she's a living spreadsheet that thinks about your portfolio.
// Each system has its own view of market reality
table system_market_view {'{'}
system_id: u64,
commodity_id: u64,
best_bid: f64,
best_ask: f64,
last_trade_price: f64,
volume_24h: u64,
snapshot_time: timestamp,
// ^ How stale is this data? Key field.
{'}'}
// Diffusion scheduler — propagates data between connected systems
reducer propagate_market_data(ctx) {'{'}
// Each tick, for each system pair connected by a gate:
// 1. Compare local prices vs neighbor's snapshot
// 2. If snapshot_age > propagation_delay, push updated prices
// 3. Add random noise proportional to distance from source
// 4. Diffusion speed ~1 system per 2 minutes per jump
{'}'}
Players set prices, build supply chains, and create market dynamics. NPC orders are a safety net, not the primary economy. The goal is emergent trade routes, regional price differences, and player-driven scarcity.
NPC buy orders create a price floor so mining is always worth something. NPC sell orders provide basic items at a premium so new players aren't stuck. As the player economy matures, NPCs step back.
Different systems produce different ores. Null-sec has rarer minerals but higher risk. This creates natural trade corridors and hauler opportunities. Region matters.
Every ISK entering the economy must eventually leave. Ship destruction is the primary sink — it's fun, dramatic, and removes value. Taxes and fees are the steady drain. Inflation is the enemy.
js/demos/market.js) validates a feature set that goes beyond the original
Economy spec. This section brings the spec up to what the demo actually implements.
Every commodity has a live order book with bid/ask spread visualization. Buy orders (bids) stack on the left, sell orders (asks) on the right. Depth chart shows cumulative volume at each price level. Players can see exactly where their order sits in the queue.
Candlestick charts with configurable timeframes (1h, 6h, 24h, 7d, 30d). Volume bars overlaid. Moving averages (7-period, 20-period). Players can annotate charts and share screenshots. Historical data is per-station, per-commodity — no galaxy-wide aggregation (information is local).
Each commodity is traded as a contract with standardized lot sizes. Contracts specify: commodity type, lot size, tick size (minimum price increment), and settlement rules. This enables the order book to aggregate orders efficiently and provides a clean abstraction for the market engine.
Era 2 feature. Players can open long and short positions on commodity contracts using a margin account. Margin requires collateral (ISK + assets). Maintenance margin enforced — if position moves against the player beyond the margin, the position is force-liquidated. This adds speculative depth for advanced traders.
Scrolling price ticker across all active contracts. Real-time price updates filtered by player's current station or region. Category filters (Ore, Minerals, Modules, Ships). Sparkline mini-charts next to each ticker entry. The ticker runs in both Flight Mode (bottom bar) and Station Mode (market panel sidebar).
Market data is station-local by default. Players see the full order book for their current station. To see prices at other stations, they must use the Region Market Data channel (delayed, see Info Diffusion tab) or travel there physically. No global market view exists — information geography is real.
Raw ore can be sold directly or refined into minerals at a station with reprocessing facilities. Refined minerals are worth more per m³ but require batch sizes and processing time. Refining efficiency improves with the player's Industry skill level.
| Ore | Yields Mineral | Units per Batch | Base Yield | Process Time |
|---|---|---|---|---|
| {row.ore} | {row.mineral} | {row.batch} | {row.yield} | {row.time} |
At 50% efficiency, selling raw ore is usually better ISK/m³. At 80%+ efficiency, refining is almost always more profitable. This creates a natural skill gate: new players sell raw, veterans refine and manufacture.
Players can manufacture ships, modules, and ammunition from refined minerals. Manufacturing requires a station with factory facilities, the correct minerals, and the appropriate Industry skill level. Manufacturing time creates natural production queues and opportunity cost.
| Product | Mineral Cost | Time | Station | Skill Req. |
|---|---|---|---|---|
| {row.product} | {row.minerals} | {row.time} | {row.station} | {row.skill} |
| Stage | Input | Output | Example | Industry Skill |
|---|---|---|---|---|
| {row.stage} | {row.input} | {row.output} | {row.example} | {row.skill} |
Every manufacturable item has a Blueprint Original (BPO). BPOs define the base recipe, but they can be researched to improve two attributes: Material Efficiency (ME) reduces mineral waste, and Time Efficiency (TE) reduces manufacturing time. Research costs time and ISK but permanently improves the BPO.
Each ME level reduces material waste by 1%. At ME 0, the recipe uses the base material list (includes 10% waste). At ME 10, waste is reduced to 0%. Research time increases exponentially.
Each TE level reduces manufacturing time by 2%. At TE 0, the recipe takes the base time. At TE 20, manufacturing time is reduced by 40%. TE research is cheaper and faster than ME research.
Each station has a limited number of manufacturing slots. Players queue jobs and they execute in order. A player can have multiple jobs running simultaneously, limited by their Industry skill level.
Not all stations can manufacture everything. Station facility level determines what can be built:
BPOs can be copied to create Blueprint Copies (BPCs) with a limited number of runs. BPCs are tradable — a manufacturer can sell BPCs on the market without giving up the original BPO. Copies inherit ME/TE levels from the original.
Tech 2 items are created through invention — a research process that consumes a BPC, datacores, and a decryptor to produce a T2 BPC with a probability of success. T2 items are significantly more powerful than T1, making invention a high-value, high-risk specialization.
Each manufacturable item has a Blueprint Original (BPO) that defines the recipe. BPOs can be researched to reduce mineral waste (Material Efficiency) and production time (Time Efficiency).
Advanced items require intermediate components (not just raw minerals). This creates multi-step production chains where different players can specialize in different stages.
Every commodity has a base price (the global reference), a regional modifier (set at galaxy generation, reflects local abundance/scarcity), and a dynamic modifier that shifts based on player activity. NPC prices are never random — they are a deterministic function of these three inputs.
| Commodity | Base Price (₢/unit) | Type | NPC Buy Spread | NPC Sell Spread |
|---|---|---|---|---|
| Veldspar | 2.50 | Ore | 0.70 | 1.25 |
| Scordite | 4.00 | Ore | 0.70 | 1.25 |
| Pyroxeres | 12.00 | Ore | 0.68 | 1.28 |
| Kernite | 25.00 | Ore | 0.65 | 1.30 |
| Tritanium | 3.20 | Mineral | 0.75 | 1.20 |
| Pyerite | 8.00 | Mineral | 0.75 | 1.20 |
| Nocxium | 120.00 | Mineral | 0.72 | 1.22 |
| Megacyte | 450.00 | Mineral | 0.68 | 1.30 |
| Mining Laser I | 800 | Module | — | 1.30 |
| 150mm Railgun | 2,500 | Module | — | 1.30 |
| Frigate Hull | 15,000 | Ship | — | 1.35 |
| Cruiser Hull | 80,000 | Ship | — | 1.35 |
The demand_pressure multiplier is the only dynamic component of NPC prices. It tracks recent buy/sell volume at each station and adjusts prices to simulate supply and demand. This is what prevents infinite arbitrage and makes regional trade meaningful.
Regional modifiers are set at galaxy generation and never change. They reflect the natural abundance or scarcity of resources in a region. A region rich in Veldspar belts has a low modifier for Veldspar (cheap locally, not worth importing) but might have a high modifier for Megacyte (rare locally, profitable to import). This creates natural trade corridors.
| Region | Character | Veldspar Mod | Nocxium Mod | Megacyte Mod | Module Mod |
|---|---|---|---|---|---|
| The Forge (Jita) | Trade Hub | 0.90 | 0.85 | 1.30 | 0.95 |
| Domain (Amarr) | Manufacturing | 0.95 | 0.90 | 0.80 | 0.90 |
| Sinq Laison | High-sec Mixed | 1.00 | 1.00 | 1.20 | 1.05 |
| Metropolis | Border Zone | 1.15 | 1.10 | 1.35 | 1.15 |
| Pure Blind (Null) | Null-sec Frontier | 1.40 | 0.70 | 0.60 | 1.35 |
| Fade (Low-sec) | Pirate Corridor | 1.30 | 0.75 | 0.75 | 1.25 |
NPC buy price is always ≤ NPC sell price for the same commodity at the same station. The minimum spread (buy_spread × sell_spread⁻¹) is 0.65/1.10 = 0.59 — meaning NPCs pay at most 59% of what they charge. You cannot buy from an NPC and sell back to the same NPC at a profit.
demand_pressure clamps to [0.8, 1.4]. Even at maximum demand, NPC prices only reach 1.4× baseline. Even at maximum oversupply, they only drop to 0.8×. This prevents price spirals in either direction and ensures new players can always estimate their income within a known range.
NPCs have finite order depth. If players flood a station with Veldspar, the NPC buy order eventually fills and the price drops sharply (demand_pressure floor). This limits infinite farming of any single station and encourages players to diversify or find remote stations with unfilled orders.
Each station tracks its own demand_pressure independently. Selling Tritanium at Jita doesn't affect Tritanium prices at Amarr — until the diffusion pipeline propagates the information (see Info Diffusion tab). Players who travel between stations can exploit this lag; players who don't, can't.
// Per-station per-commodity demand state
table station_commodity_demand {'{'}
station_id: u64,
commodity_id: u64,
flow_ema: f64, // rolling net flow EMA
demand_pressure: f64, // current multiplier, clamped [0.8, 1.4]
volume_sold_to_npc: u64, // cumulative this tick
volume_bought_from_npc: u64, // cumulative this tick
npc_stock_remaining: u64, // stock limit for buy orders
last_tick: timestamp,
{'}'}
// Per-commodity base prices and parameters
table commodity_price_params {'{'}
commodity_id: u64,
base_price: f64,
buy_spread: f64, // [0.65, 0.85]
sell_spread: f64, // [1.10, 1.35]
ema_alpha: f64, // smoothing factor (default 0.3)
pressure_beta: f64, // sensitivity per unit (default 0.002)
decay_gamma: f64, // idle decay rate (default 0.05)
{'}'}
// Per-region per-commodity static modifier
table regional_price_seeds {'{'}
region_id: u64,
commodity_id: u64,
modifier: f64, // fixed at galaxy gen, range [0.6, 1.5]
{'}'}
// Scheduled agent that ticks demand pressure
reducer tick_npc_pricing(ctx) {'{'}
// Every 5 minutes, for each station_commodity_demand row:
// 1. Compute net_flow = volume_sold_to_npc - volume_bought_from_npc
// 2. Update flow_ema with EMA formula
// 3. Recompute demand_pressure = clamp(1.0 - β × flow_ema, 0.8, 1.4)
// 4. Apply idle decay: lerp(demand_pressure, 1.0, γ)
// 5. Reset volume counters for next tick
{'}'}
{item.description}