Crate Drop System

β€œCrate” is overloaded in Starship Survivors β€” three different on-field reward sources share the πŸ“¦ sticker but originate from distinct subsystems, spawn on different schedules, and award different things on pickup or break. This page disambiguates them.

SourceWorld list / poolSpawn driverPickup / break reward
Artifact crateworld.artifactBoxesKPM-based timer _artifactNextDropTime (currently gated off β€” fed by artifact-type events)artifact_box reward β€” upgrade picks from owned artifacts
Weapon chestworld.weaponBoxesFirst-check / recurring-interval timer _wcNextSpawnTime (currently gated off β€” fed by weapon-type events)weapon_box reward β€” unowned weapon choice, or +1 to every equipped weapon if slots are full
Destructible πŸ“¦ / Supply PodCratePool / PropPoolWorld-gen off-screen spawn driven by planets[].destructibles.crates sliderXP orb burst on ship-contact break

1. Artifact crates (world.artifactBoxes)

State. engine/bridge.ts holds _artifactNextDropTime: number (line 409). -1 means β€œschedule on first tick”; once positive, it stores the game.missionElapsed at which the next drop fires.

Scheduler (KPM-based, currently dormant). The intended cadence lives at bridge.ts:3413-3462 but the block is wrapped if (false && !runDef.sandbox) β€” it’s preserved for resurrection but never runs in shipped builds. Constants in engine/core/config/_artifact-drops.ts:

  • ARTIFACT_DROP_GRACE_SEC = 30 β€” no drops before 30s.
  • KPM window: ARTIFACT_KPM_WINDOW_SEC = 60 rolls a kills-per-minute snapshot.
  • KPM β†’ interval lerp: KPM_LOW = 50 maps to DROP_MIN_SEC = 60 (struggling player gets help fast); KPM_HIGH = 200 maps to DROP_MAX_SEC = 360 (dominant player waits longer).
  • Tier ramp: TIER_RAMP_BASE = 0.3 plus +0.2 per current-level β€” early tiers slow drops down.

Live spawn source. Today artifact crates only spawn when an artifact-type world event completes. bridge.ts:2611-2631 pushes a queued artifact_box reward when the player owns 2+ artifacts and at least one is below legendary. If neither gate is met the event silently drops a weapon chest at cev.x, cev.y instead.

Pickup. Collection (bridge.ts:3007-3033) clears the box and queues { type: 'artifact_box' }. The reward dispatcher (line 3085) calls rollArtifactChoices(2, 'upgrade_only') β€” up to 2 cards from 2 different owned, non-legendary artifacts. If only one is upgradeable the player must pick it (no skip).

2. Weapon chests (world.weaponBoxes)

State. _wcNextSpawnTime, _wcChecksDone, _wcSpawnedThisLevel, _wcPendingChest in bridge.ts:364+. Same -1-means-unscheduled convention as artifacts.

Scheduler (currently dormant). The block at bridge.ts:3364-3407 is wrapped if (false && !runDef.sandbox). When live it schedules three phases:

  • First check (WC_FIRST_CHECK_SEC): guaranteed within 5-60s of mission start.
  • Second check (WC_SECOND_CHECK_SEC): guaranteed in a 0-90s window after 2:00.
  • Recurring: every WC_RECURRING_INTERVAL_SEC starting at WC_RECURRING_START_SEC (3:30).

Spawn gates: weapon slots not full, no chest already on the field, and _wcSpawnedThisLevel < 2. Failing the gates pushes the timer by WC_RESCHEDULE_DELAY_SEC.

Live spawn source. Currently fed by weapon-type completed events β€” bridge.ts:2602-2610 pushes a weaponBox at the event center.

Pickup. Collection at bridge.ts:2885-2922 snapshots whether weapon slots were full at collect-time, then queues { type: 'weapon_box', _slotsFullAtCollect }. The dispatcher (line 3103) splits:

  • Slots free: roll up to 3 unowned weapon choices.
  • Slots full: bypass the picker β€” every equipped weapon gets +1 level via the fly-to-slot animation under family weapon_chest_auto. Still feels like a reward.
  • Slots free but no unowned weapons left: falls back to the auto-upgrade animation.

3. Destructibles β€” πŸ“¦ crates and the Supply Pod prop

These look like crates but are spawned by the world’s destructible-density system, not the reward scheduler. They have no β€œpickup” β€” the ship rams them and they break.

Plain πŸ“¦ crates β€” engine/world/crates.ts

  • Pool size POOL_SIZE = 80, max active MAX_DENSITY = 20 (halved from 40 in v5.165).
  • Density is planets[id].destructibles.crates / 100 Γ— MAX_DENSITY. Every planet in data/planet-config.ts currently ships crates: 40 (lines 96, 112, 129, 146, 164, 181, 198, 215, 232, 248, 264, 280) β†’ ~8 active crates.
  • Spawn cadence: 200ms tick, off-screen only (SPAWN_MIN = 400 to SPAWN_MAX = 1400 from ship), 70% velocity-cone bias toward player heading, MIN_GAP = 120 between actives.
  • Cull radius CULL_RADIUS = 2000 (never culls on-screen).
  • Break on ship contact (COLLISION_RADIUS = 36) β†’ fires crate_break signal, plays Juice.fire('crate_break'), spawns 3-5 XP orbs whose total value is CRATE_XP_PCT_MIN..MAX = 3-9% of the current level’s XP bar (xpForLevel(L+1) - xpForLevel(L)), then a three-layer VFX burst (spark cloud, brown debris chunks, amber rim flash ring).

Supply Pod β€” data/props.ts:172

The Supply Pod is the rarest tier in the typed PropPool (engine/world/props.ts). It’s a destructible, not a pickup.

  • hp: 80 β€” survives ship contact, but breakable with bullets. (Ship contact one-shots regardless of hp; the hp matters for bullet damage.)
  • densityMult: 0.15 (weighted roll) β†’ ~10% of total prop spawns. Shared MAX_DENSITY = 10 caps active Pods at ~1-2.
  • edgeArrow: true β€” HUD draws a screen-edge indicator so the player can hunt one.
  • Break drop: orbCount: 12 Γ— orbXpFracPerOrb: 0.035 β†’ ~42% of the current level bar. The largest XP bundle in the prop catalog.

Supply Pod cascade. SUPPLY_POD_CASCADE_CHANCE = 1.0 β€” every break fires triggerSupplyPodCascade(x, y) (engine/world/props.ts:655). It fan-spawns 5 props in a ring at SUPPLY_POD_CASCADE_RING_PX = 110:

['scrap_pile', 'scrap_pile', 'mineral_vein', 'comet_fragment', 'magnetar_pulse']

Each cascaded prop respects its own break-synergy roll, so a single Pod can chain up to 6 synergies in one beat (Scrap Γ— magnet pulse, Mineral Γ— shatter cascade, Comet Γ— ship speed-boost, Magnetar Γ— gravity-pull). The same routine is also fired on boss defeat for a Hades-style reward chamber.

Summary

  • Artifact crates and weapon chests are reward-schedule entities tracked on world with dedicated bridge timers (_artifactNextDropTime, _wcNextSpawnTime). Both schedulers are presently gated behind if (false); the only live spawn path is via artifact/weapon-type completed events. Pickup queues artifact_box / weapon_box rewards routed through levelup flow.
  • Destructible πŸ“¦ crates and Supply Pods are spatial clutter from the destructible-density system. They live in pooled allocations (CratePool, PropPool), spawn off-screen, respect planets[].destructibles.crates (currently 40 everywhere), and pay out XP-orb bursts on ship-contact break β€” no reward queue, no choice screen.

Source files

  • engine/bridge.ts β€” artifact + weapon-chest schedulers and pickup dispatch (lines 364, 409, 2602-2631, 2885-2922, 3007-3033, 3085-3140, 3364-3462).
  • engine/world/crates.ts β€” πŸ“¦ destructible pool, density curve, break VFX, XP-orb payout.
  • engine/world/props.ts β€” typed prop pool, Supply Pod break behaviour, triggerSupplyPodCascade.
  • engine/world/artifacts.ts β€” artifact runtime, grantArtifact, signal handlers.
  • engine/core/config/_artifact-drops.ts β€” KPM tuning constants for the dormant artifact scheduler.
  • data/economy.ts β€” currency / pull / death-defiance / mission rewards (no crate-drop rates; rewards are gated by event completion, not drop tables).
  • data/planet-config.ts β€” per-planet destructibles.crates slider (40 across all 12 planets).
  • data/props.ts β€” typed prop catalog including supply_pod (hp 80, 12 orbs Γ— 3.5%, density 0.15).