What this is
The v2 enemy rarity system. Every base archetype (16 of them: orb, charger, shooter, mortar, gunner, field, sniper, racer, brute, wisp, lurker, bombardier, sprinter, spitter, burner, suppressor) is multiplied across 5 rarity tiers — common, uncommon, rare, epic, legendary — to produce the full ENEMY_TYPES table.
Two parallel tables drive this:
RARITY_MULTS— per-rarity stat multipliers applied to the base archetype’shp,xp,speed,radius, anddamagefields. Results areMath.round()-ed at type-build time inbuildEnemyTypes().RARITY_TINTS— per-rarity polygon stroke color baked onto every variant’stintfield.
The id of each generated type is ${archetype}_${rarity} (e.g. orb_common, mortar_legendary). Iteration order is RARITY_ORDER = ['common', 'uncommon', 'rare', 'epic', 'legendary'].
Source of truth: src/starship-survivors/data/enemies/_types.ts. Re-exported from src/starship-survivors/data/enemies/index.ts and src/starship-survivors/data/enemies.ts.
RARITY_MULTS table
Applied multiplicatively to base archetype stats. damage is used only by archetypes that scale damage per rarity (orb AOE, mortar/bombardier blast, sniper beam, field/burner field, gunner/suppressor not directly here).
| Rarity | hp | xp | speed | radius | damage |
|---|---|---|---|---|---|
| common | 2.7 | 3.0 | 1.40 | 1.00 | 3.0 |
| uncommon | 4.95 | 6.0 | 1.47 | 1.15 | 4.5 |
| rare | 6.93 | 12.0 | 1.57 | 1.30 | 6.6 |
| epic | 9.9 | 18.0 | 1.68 | 1.40 | 8.4 |
| legendary | 11.88 | 24.0 | 1.82 | 1.50 | 10.5 |
Notes:
hp,speed,radius,xpare applied to every variant viaMath.round(base.X * m.X).damageis applied selectively inbuildEnemyTypes():orb—aoeDamagemortar/bombardier— implicit viablastRadiusscaling formula1 + tierIndex * 0.15(blast radius), withfuseTimeleft at base.field/burner—fieldDamage(multiplied bym.damage), plusfieldRadius = base * (1 + tierIndex * 0.15),fieldDurationx1.5 only on legendary.sniper—sniperBeamDamage(multiplied bym.damage).gunner/suppressor— separateburstMults = [1.0, 1.0, 1.2, 1.4, 2.0]andcdMults = [1.0, 0.9, 0.8, 0.65, 0.5];m.damageis not used directly.
- Orb AOE also uses two per-rarity helper tables (not part of
RARITY_MULTS):aoeRadius=base * (1 + tierIndex * 0.20)aoeCooldown=base * [1.0, 0.85, 0.7, 0.35, 0.35][tierIndex]
- Sniper uses
chargeMults = [1.0, 0.9, 0.8, 0.7, 0.5]againstsniperChargeTime.
RARITY_TINTS table
Polygon stroke color baked into each variant’s tint. Boss-roster enemies override tint per faction-specific id and ignore this table.
| Rarity | Tint hex | Color |
|---|---|---|
| common | #cccccc | light gray |
| uncommon | #33cc55 | green |
| rare | #3388ff | blue |
| epic | #aa44ff | purple |
| legendary | #ff8800 | orange |
A second, legacy color table ENEMY_TIER_COLORS in data/enemies/index.ts uses different values for common (#cc3333), no epic entry, and matching values for uncommon / rare / legendary. RARITY_TINTS is the live source for variant tints; ENEMY_TIER_COLORS is a parallel UI palette.
Where consumed
src/starship-survivors/data/enemies/index.ts—buildEnemyTypes()consumes both tables to produce every entry inENEMY_TYPESandENEMY_TYPE_MAP.src/starship-survivors/data/enemies.ts— re-exportsRARITY_MULTSandRARITY_TINTSfor legacy import paths.src/starship-survivors/screens/RunStatsScreen.tsx— usesRARITY_TINTSfor end-of-run kill breakdown swatches and per-enemy row tint fallback.src/starship-survivors/screens/playground/EnemiesTab.tsx— referencesRARITY_MULTSin commentary on assembled stats.- Renderer reads each enemy’s baked
tintfield at draw time; it does not re-readRARITY_TINTSat runtime.