Legendary Weapon Dual-Tag Damage
Legendary weapons are produced by merging two level-20 non-legendary
weapons. Each merge yields a weapon that inherits BOTH parent damage tags
via damageTag (primary) and secondaryDamageTag (secondary) on its
WeaponCoreSpec. The four base tags — bullet, energy, bomb, fire
— pair with each other (including with themselves) for 10 unordered
pairings; one legendary per pair.
Parent-pair table
Each legendary’s mergeParents is a canonical (alphabetical) pair of
tags. Primary/secondary tag on the weapon spec matches that pair:
| Weapon | mergeParents | damageTag | secondaryDamageTag |
|---|---|---|---|
| Mega Bullet | [bullet, bullet] | bullet | bullet |
| Hellrain | [bomb, bomb] | bomb | bomb |
| Star Halo | [energy, energy] | energy | energy |
| Phoenix | [fire, fire] | fire | fire |
| 4-Way Burst | [bomb, bullet] | bullet | bomb |
| Wave Gun | [bullet, energy] | bullet | energy |
| Trailblazer | [bullet, fire] | bullet | fire |
| Railstorm | [bomb, energy] | bomb | energy |
| Carpet Bomber | [bomb, fire] | bomb | fire |
| Plasma Mortar | [energy, fire] | energy | fire |
What “dual-tag” means at fire time
When a legendary lands a hit, the collision resolver fires a
bullet_hit signal carrying the weapon’s damageTag, then fires a
SECOND bullet_hit signal carrying secondaryDamageTag — but only when
the two tags differ:
// engine/combat/collision-resolver.ts (around line 137-142)
Sig.fire('bullet_hit', e.eid || 0, 0, b.dmg, 0, e._lastDmgTag);
// Legendary weapons carry a secondary damage tag; fire a matching signal so
// artifacts/effects keyed on EITHER parent tag react to the same hit.
if (_wSpec?.secondaryDamageTag && _wSpec.secondaryDamageTag !== _wSpec.damageTag) {
Sig.fire('bullet_hit', e.eid || 0, 0, b.dmg, 0, _wSpec.secondaryDamageTag);
}The guard _wSpec.secondaryDamageTag !== _wSpec.damageTag is the load-bearing
detail. It splits the 10 legendaries into two cohorts:
Cross-tag pairs — fire TWO signals per hit
The six cross-tag legendaries (4-Way Burst, Wave Gun, Trailblazer,
Railstorm, Carpet Bomber, Plasma Mortar) emit bullet_hit once with
their primary tag and once with their secondary. Artifacts or effects
that listen for bullet_hit filtered by tag will trigger off whichever
tag they care about — and an artifact keyed on either parent tag will
react to every legendary hit.
Same-tag pairs — fire ONE signal per hit
The four same-tag legendaries (Mega Bullet bullet+bullet, Hellrain
bomb+bomb, Star Halo energy+energy, Phoenix fire+fire) skip the second
emit. The secondaryDamageTag !== damageTag check rejects them so the
bullet_hit signal fires exactly once per hit, carrying that tag. This
prevents artifact triggers keyed on (for example) bullet hits from
double-counting Mega Bullet rounds.
Downstream signals on kill
The dual-tag emit lives only in the collision resolver. Other signals
along the kill chain read a single stamped tag (_lastDmgTag on the
enemy) and fire once per kill:
damage_dealt— fired indamageEnemycarrying_lastDmgTag(the primary tag, stamped when the hit landed).tagged_kill— fired indamageEnemyonce the enemy’s HP reaches zero, carrying the same_lastDmgTag.
Neither of these doubles for cross-tag legendaries — only bullet_hit
does. Artifacts that key on tagged_kill see the primary tag only.
Designing for the cohort split
Two implications fall out of this for designers tuning artifacts and
mods that listen on bullet_hit:
-
Cross-tag legendaries are double-counters. An artifact whose trigger condition is “on bullet_hit with tag = energy” fires twice per Plasma Mortar hit (once for energy primary, once for fire secondary). When designing trigger budgets, account for this 2× multiplier on cross-tag legendaries.
-
Same-tag legendaries are single-counters. Mega Bullet does NOT double-stack the bullet artifact triggers despite being a bullet+bullet merge. To get extra triggers off Mega Bullet, use hit count, fire rate, or pierce count — not the dual-tag signal.
Related
Source
src/starship-survivors/data/weapons/_types.ts—WeaponCoreSpec.damageTag+secondaryDamageTagfields.src/starship-survivors/data/weapons/legendaries.ts— all 10 legendary specs withmergeParents+ dual-tag assignments.src/starship-survivors/engine/combat/collision-resolver.ts(~L131-142) — the secondary-tag signal emit and the!==guard.src/starship-survivors/engine/combat/damage.ts(~L341, L442) —damage_dealtandtagged_killuse_lastDmgTag(primary only).