Damage Tag Taxonomy
What it is
The damage-tag union is the categorical label every damage event in the game carries — a single string that decides which artifacts, passives, and horizontals react to a hit, and which on-hit visuals the renderer plays. Tags are categorical, not numeric: they route effects, they do not change the number itself. The canonical definition lives in src/starship-survivors/engine/effects/types.ts as the DamageTag union, and is reused across the effect engine, the collision resolver, and the player damage chain.
The six tags
The union has exactly six members. Four are “weapon tags” stamped by player weapons on hit; two are engine-only tags used by internal events that don’t originate from a weapon spec.
Weapon tags (player-facing, exclusive)
Every player weapon carries exactly one of these on its spec. When a projectile or beam lands, the collision resolver writes the weapon’s tag onto the enemy’s _lastDmgTag field, then fires damage_dealt (and tagged_kill on a killing blow) with the tag in the signal payload.
- bullet — Hitscan and fast straight-line projectiles. Rifle, shotgun, revolver, railgun, burst rifle, missile-flak families. Brass/amber visual identity.
- energy — Beams, plasma arcs, chain jumps, orbiting stars, and lightning. Coilgun, barrier, line, lightning, magnetar, sweep, disc. Blue/cyan visual identity.
- bomb — Blast-radius and arcing-shell weapons. Mortar, cannon, missile. Orange/red detonation identity.
- fire — Persistent damage zones and lingering streams. Flame, fire ring, fire trail, defy. Burnt-orange ember identity.
Legendary weapons (the ten merged weapons) carry a second secondaryDamageTag; the collision resolver fires the per-hit signal twice — once per parent tag — so artifacts keyed on either tag still trigger. The full pairings live on the damage-tags page.
Engine-only tags (reserved, not player-attached)
These two members exist in the union so the effect engine can route specific internal damage events without being mistaken for weapon damage.
- true — Reserved for damage events that should bypass shield/HP routing logic in the effect engine. Distinct from the weapon-side
damage_type: 'true'field, which is the shield-bypass property of an individual weapon spec; the union slot exists so engine-fired damage that isn’t originated by any weapon can still carry a non-weapon tag downstream. No weapon spec uses this value for itsdamageTag. - boss — Reserved for boss-originated damage sources. Lets effect conditions and telemetry differentiate “damage the player took from a boss” from generic enemy damage, without having to inspect the source enemy at evaluation time. Engine-internal only — never appears on a weapon spec.
Where the tag attaches
Tags attach to weapons through two optional fields on WeaponCoreSpec in src/starship-survivors/data/weapons/_types.ts:
damageTag?: DamageTag— the weapon’s primary tag.secondaryDamageTag?: DamageTag— the second parent tag, set only on the ten legendaries.
Note that the weapon-spec DamageTag exported from _types.ts is only the four-member subset (bullet | energy | bomb | fire). The full six-member union — including true and boss — lives in engine/effects/types.ts and is what the runtime signal payloads, effect conditions, and _lastDmgTag field all type against. The four-member spec union is a strict subset; weapon authoring is locked to those four values.
How tags feed the damage horizontals
Each of the four weapon tags has its own damage horizontal modifier — a run-wide stack the player picks up from level-up cards or rewards. The four tracks are damage_bullet, damage_energy, damage_fire, and damage_bomb, plus a universal damage_all track that adds to every weapon regardless of tag. The full track definitions and per-weapon dmgPerH rates live on horizontal-modifiers.md. The engine-only true and boss tags do not have horizontal tracks — they never originate from a player weapon, so there’s no scaling rate to attach.
How tag information flows at runtime
- Player fires a weapon. The weapon’s
damageTagis on its spec. - The collision resolver hits an enemy and writes
enemy._lastDmgTag = spec.damageTag || 'bullet'. damageEnemy()inengine/combat/damage.tsdeducts HP and firesSig.fire('damage_dealt', ..., enemy._lastDmgTag).- On a killing blow,
Sig.fire('tagged_kill', ..., enemy._lastDmgTag)lets tag-conditional artifacts proc only when the matching tag landed the kill. - The effect engine’s
damage_tag_eqcondition reads the signal payload to gate tag-specific procs.
The true and boss slots in the union exist so non-weapon-originated damage events flowing through the same signal carriers stay typeable and routable without polluting the four player-facing tags.
Related pages
- damage-tags — full per-tag visual signatures and legendary dual-tag rules
- horizontal-modifiers — the four per-tag damage tracks and
damage_all