ships-v4-rarity.ts

Rarity table for v5 player ship assets in public/ships-v4/. Source of truth: outline color baked into each sprite by the sprite workbench. 44-ship roster organized by 7 factions. All exports are 1024×1024 square with premultiplied alpha.

River — what flows through

Static lookup map. Consumers import SHIPS_V4_RARITY and index by the sprite filename (no extension, case-sensitive, spaces preserved) to retrieve its ShipRarity band. The rarity is authoritative for downstream UI tinting, drop-table weights, and shop pricing — the file mirrors the outline color the sprite workbench baked into each PNG.

Banks — types and exports

  • ShipRarity'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'.
  • SHIPS_V4_RARITY: Record<string, ShipRarity> — frozen filename → rarity map.

Falls — drops by faction

44 ships across 7 factions. Counts per band shown below.

Ancients (2)

  • Ancients_Glyph — uncommon
  • Ancients_Rune — epic

Backwater (4)

  • Backwater_Batwing — uncommon
  • Backwater_Caiman — uncommon
  • Backwater_Killer Croc — legendary
  • Backwater_Lizard — rare

Industria (8)

  • Industria_Bigbot — rare
  • Industria_Caravan — uncommon
  • Industria_Digbot — common
  • Industria_Drillbot — uncommon
  • Industria_Eel — epic
  • Industria_Loader — uncommon
  • Industria_Milita — rare
  • Industria_Towncar — common

Junkrats (8)

  • Junkrats_Bomber — epic
  • Junkrats_Drifter — uncommon
  • Junkrats_Marco — uncommon
  • Junkrats_Orca — rare
  • Junkrats_Pierre — legendary
  • Junkrats_Skewer — uncommon
  • Junkrats_Stinger — common
  • Junkrats_Tank — common

Prism (6)

  • Prism_Citrine — epic
  • Prism_Crystal — legendary
  • Prism_Jade — rare
  • Prism_Pearl — legendary
  • Prism_Ruby — epic
  • Prism_Shard — legendary

Solaris (9)

  • Solaris_Armada — legendary
  • Solaris_Cargo — common
  • Solaris_Cruiser — uncommon
  • Solaris_Flyer — uncommon
  • Solaris_Hauler — common
  • Solaris_Oracle — legendary
  • Solaris_Princess — legendary
  • Solaris_Torque — rare
  • Solaris_Valet — epic

Roster note

Source comment says “7 factions” but only 6 faction prefixes appear in the map. One faction (or its 7th-faction roster) is unlisted in this file — verify against the v4 sprite roster before treating the count as canonical.

Banks — rarity distribution

RarityCount
common6
uncommon12
rare6
epic6
legendary7
total37

Distribution sums to 37 — the header comment claims 44 ships. Seven entries are missing from the table (likely the implied 7th faction). Treat 37 as the authoritative count for code that iterates this map; treat 44 as aspirational until reconciled.

Confluences — coupling

  • Filename keys must match files in public/ships-v4/ byte-for-byte (case + spaces). One drift breaks the lookup.
  • Outline color in the sprite PNG must agree with the rarity band here. The sprite workbench bakes the outline; this map is the read side. Mismatch is a sprite-export bug, not a data bug.
  • Any consumer reading rarity should default-handle missing keys, since the table is incomplete vs. the header claim.

EXTRACT-CANDIDATE

  • Factual gap: header says 44 ships / 7 factions; map contains 37 ships / 6 factions. Confirm whether the missing 7 ships and the 7th faction prefix are pending sprite exports or were deleted, and update either the header comment or the map.
  • Magic strings: filename keys are stringly-typed. A SHIP_FILENAMES enum or const-tuple would let TypeScript catch typos at the call site and would also enforce roster completeness.
  • No reverse index: consumers that need “all legendary ships” must filter the map at runtime. A precomputed SHIPS_BY_RARITY: Record<ShipRarity, string[]> would be cheap and would surface band imbalance at build time.
  • Faction prefix is implicit: the Faction_Name filename convention is load-bearing for grouping but not enforced. A { faction, name, rarity } shape (or a parser) would make faction-level queries first-class instead of string-split guesswork.
  • Outline-color SoT lives in PNGs: the comment names sprite outlines as source of truth, but this TS map is what code actually reads. If a sprite’s outline disagrees with the table, code silently uses the table. Either generate this file from the sprites or add a CI check that the two agree.