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— uncommonAncients_Rune— epic
Backwater (4)
Backwater_Batwing— uncommonBackwater_Caiman— uncommonBackwater_Killer Croc— legendaryBackwater_Lizard— rare
Industria (8)
Industria_Bigbot— rareIndustria_Caravan— uncommonIndustria_Digbot— commonIndustria_Drillbot— uncommonIndustria_Eel— epicIndustria_Loader— uncommonIndustria_Milita— rareIndustria_Towncar— common
Junkrats (8)
Junkrats_Bomber— epicJunkrats_Drifter— uncommonJunkrats_Marco— uncommonJunkrats_Orca— rareJunkrats_Pierre— legendaryJunkrats_Skewer— uncommonJunkrats_Stinger— commonJunkrats_Tank— common
Prism (6)
Prism_Citrine— epicPrism_Crystal— legendaryPrism_Jade— rarePrism_Pearl— legendaryPrism_Ruby— epicPrism_Shard— legendary
Solaris (9)
Solaris_Armada— legendarySolaris_Cargo— commonSolaris_Cruiser— uncommonSolaris_Flyer— uncommonSolaris_Hauler— commonSolaris_Oracle— legendarySolaris_Princess— legendarySolaris_Torque— rareSolaris_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
| Rarity | Count |
|---|---|
| common | 6 |
| uncommon | 12 |
| rare | 6 |
| epic | 6 |
| legendary | 7 |
| total | 37 |
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_FILENAMESenum 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_Namefilename 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.