weapon-icons.ts
Single source of truth for weapon and modifier icon asset paths and emoji fallbacks. Replaces duplicate WEAPON_EMOJIS maps previously scattered across hud.ts, ShipSelectOverlay.tsx, and LeaderboardWrapper.tsx.
River — purpose
Resolves a weapon or modifier ID to its icon asset path on disk (with cache-buster) or, failing that, to an emoji glyph. Consumers: HUD weapon strip, ship-select overlay, leaderboard wrapper, anywhere a weapon ID needs visual representation.
Cocytus — symbols
WEAPON_ICON_IDS (private Set<string>)
13 weapon IDs with PNG icon assets at /weapons/{id}.png:
sweep, barrier, shotgun, disc, lightning, flame,
line, railgun, mortar, revolver, rifle,
missile, cannon
MODIFIER_ICON_IDS (private Set<string>)
5 modifier IDs with PNG icon assets at /upgrades/{id}.png. Keyed with mod_ prefix to avoid collision with weapon IDs:
mod_health, mod_shield, mod_speed, mod_damage, mod_heat
getWeaponIconPath(id: string): string | null (exported)
Returns the asset URL for a weapon or modifier icon, with ?v=${BUILD_VERSION} appended as cache-buster (prevents stale SW/CDN serving HTML). Returns null if the ID has no PNG asset.
- Weapon match →
/weapons/{id}.png?v={BUILD_VERSION} - Modifier match →
/upgrades/{id-stripped-of-mod_-prefix}.png?v={BUILD_VERSION}(strips first 4 chars viaid.slice(4)) - No match →
null
Note: the doc comment on line 24 mentions .jpg, but the actual implementation emits .png for both weapons and modifiers.
hasWeaponIcon(id: string): boolean (exported)
Returns true iff id exists in either set (weapon or modifier).
WEAPON_EMOJIS (exported Record<string, string>)
Emoji fallback map for IDs without PNG assets, or where caller chose emoji.
Standard weapons (14 entries): rifle🔫, shotgun🎯, railgun⚡, missile🚀, lightning🌩️, revolver🎖️, cannon💣, mortar💥, disc🥏, flame🔥, sweep⚔️, line➖, barrier🛡️, plus environmental projectiles fire_trail🔥, fire_ring🔆, burst🔫.
Legendary weapons (merge-only, 10 entries — distinct glyphs until PNG assets exist): lgd_autocannon💫, lgd_blackhole_cluster🕳️, lgd_railstorm🌀, lgd_inferno🔥, lgd_flak_rifle💢, lgd_railslug💠, lgd_incendiary_rifle☄️, lgd_plasma_launcher🌌, lgd_napalm_mortar🧨, lgd_arc_flame⚡.
Lethe — imports
BUILD_VERSIONfrom../engine/core/config— appended as?v={BUILD_VERSION}query string for cache-busting.
Phlegethon — invariants
- All weapons in
WEAPON_ICON_IDSoverlap withWEAPON_EMOJISkeys (PNG path takes precedence at consumer level; emoji is fallback only). - Modifier IDs are namespaced with
mod_prefix to prevent collision with weapon IDs in the same lookup. - Legendary weapons (
lgd_*prefix) have emoji-only representation — no PNG assets yet. - All returned URLs are root-relative paths (
/weapons/...,/upgrades/...) — assumes the public asset folder layout.
Acheron — EXTRACT-CANDIDATE
- The two
Setliterals (WEAPON_ICON_IDS,MODIFIER_ICON_IDS) plus theWEAPON_EMOJISmap are pure data. Candidate for migration to aweapon-icons.jsonif data-driven authoring is desired, but at 18 IDs + 24 emoji entries the inline-TS form is fine. - The
.jpgmention in the line-24 doc comment is stale (implementation uses.png) — minor doc-fix candidate. - The
id.slice(4)magic offset ingetWeaponIconPathis the length of the'mod_'prefix; replacing withid.slice('mod_'.length)or a named constantMOD_PREFIX = 'mod_'would satisfy the “every number traces to a named constant” rule.