Found by the coverage wave (spikersoft-backend PR #454) while testing ProjectileCollisionSystem.
ProjectileCollisionSystem.GetComboType normalizes every spell pair with string.CompareOrdinal so the ordinally-smaller id always comes first, then matches:
return(first,second)switch{...("laserBeam","plasmaBolt")=>"laser_plasma",("shockwave","fireball")=>"shockwave_fire",// ← dead arm_=>null};
Since "fireball" < "shockwave" ordinally, the normalized tuple for that pair is always ("fireball", "shockwave") — the ("shockwave", "fireball") pattern can never match, so the shockwave_fire combo (6m radius, 150 damage per SpellComboResult.GetComboProperties) is unreachable in gameplay.
Fix: flip the arm to ("fireball", "shockwave").
ProjectileCollisionSystemTests.DetectCombos_ShockwaveFireball_CurrentlyNeverCombos pins the current behavior and will fail when this is fixed (then move the pair back into the pairing-table Theory).
Found by the coverage wave (spikersoft-backend PR #454) while testing `ProjectileCollisionSystem`.
`ProjectileCollisionSystem.GetComboType` normalizes every spell pair with `string.CompareOrdinal` so the ordinally-smaller id always comes first, then matches:
```csharp
return (first, second) switch
{
...
("laserBeam", "plasmaBolt") => "laser_plasma",
("shockwave", "fireball") => "shockwave_fire", // ← dead arm
_ => null
};
```
Since `"fireball" < "shockwave"` ordinally, the normalized tuple for that pair is always `("fireball", "shockwave")` — the `("shockwave", "fireball")` pattern can never match, so the `shockwave_fire` combo (6m radius, 150 damage per `SpellComboResult.GetComboProperties`) is unreachable in gameplay.
Fix: flip the arm to `("fireball", "shockwave")`.
`ProjectileCollisionSystemTests.DetectCombos_ShockwaveFireball_CurrentlyNeverCombos` pins the current behavior and will fail when this is fixed (then move the pair back into the pairing-table Theory).
Audited against origin/master — STILL BROKEN, and there is a second fix site the ticket doesn't mention.
The named defect is unchanged.SpikerSoft.GameServer/Physics/ProjectileCollisionSystem.cs:518 still matches ("shockwave", "fireball")after the ordinal normalization at :504-506, so the arm is unreachable. Description and line numbers are accurate. This one is live — GetComboType is called at :126.
The addition: there is a second, independent GetComboType.SpikerSoft.GameServer/Zones/DungeonZone.cs:765, called from :744 and :790. The ticket names only the Physics copy.
I did not verify whether the DungeonZone copy carries the same dead arm — flagging it rather than claiming it. But whoever fixes this should check, because a one-line fix to the Physics copy would leave the dungeon path behaving differently from the camp path, and the divergence would be invisible until a player noticed the combo working in one zone and not the other.
That duplication is worth a look on its own terms: two independent implementations of the same combo-resolution logic is how they drift. If they're meant to be identical, extracting one shared implementation while fixing this would prevent the next instance.
Priority context from the same eleven-ticket sweep: this is on a live path, alongside #811 (broken AES on a real network path — the highest severity of the set), #793, #795, #797 and #799. #792, #808 and #840 turned out to be latent with no production caller at all.
Audited against `origin/master` — **STILL BROKEN, and there is a second fix site the ticket doesn't mention.**
**The named defect is unchanged.** `SpikerSoft.GameServer/Physics/ProjectileCollisionSystem.cs:518` still matches `("shockwave", "fireball")` *after* the ordinal normalization at `:504-506`, so the arm is unreachable. Description and line numbers are accurate. This one is **live** — `GetComboType` is called at `:126`.
**The addition: there is a second, independent `GetComboType`.** `SpikerSoft.GameServer/Zones/DungeonZone.cs:765`, called from `:744` and `:790`. The ticket names only the Physics copy.
I did **not** verify whether the DungeonZone copy carries the same dead arm — flagging it rather than claiming it. But whoever fixes this should check, because a one-line fix to the Physics copy would leave the dungeon path behaving differently from the camp path, and the divergence would be invisible until a player noticed the combo working in one zone and not the other.
That duplication is worth a look on its own terms: two independent implementations of the same combo-resolution logic is how they drift. If they're meant to be identical, extracting one shared implementation while fixing this would prevent the next instance.
**Priority context** from the same eleven-ticket sweep: this is on a live path, alongside **#811** (broken AES on a real network path — the highest severity of the set), **#793**, **#795**, **#797** and **#799**. **#792**, **#808** and **#840** turned out to be latent with no production caller at all.
Verified 2026-08-07 against the synced default branch.
Code:spikersoft-backend@98102023 — still broken. SpikerSoft.GameServer/Physics/ProjectileCollisionSystem.cs:518 still matches ("shockwave", "fireball")after the ordinal normalization at :504-506, so the arm is unreachable. Live path — GetComboType is called at :126. Second fix site the body does not mention: there is an independent GetComboType at SpikerSoft.GameServer/Zones/DungeonZone.cs:765, called from :744 and :790. Whether it carries the same dead arm was not verified.
Live:docker service ps spikersoft-gameserver_spikersoft-gameserver → 1/1 Running on SERVER, image redeployed 2026-08-07 12:25 UTC; combo unreachable in gameplay by construction.
Remaining: Flip the arm to ("fireball", "shockwave"); check the DungeonZone copy at :765 so camp and dungeon don't diverge (extracting one shared combo-resolution implementation while fixing would prevent the next drift); then move the pair out of ProjectileCollisionSystemTests.DetectCombos_ShockwaveFireball_CurrentlyNeverCombos and back into the pairing-table Theory.
Status: still broken — full detail carried over to the new issue.
Closing here. Work now lives in the repo that holds the fix, so fixes #540 in a PR will
auto-close it on merge. The umbrella tracker keeps cross-repo epics only.
— Opus 5 Agent
Migrated to **spikerj/spikersoft-backend#540** as part of the umbrella-tracker breakup.
Verified 2026-08-07 against the synced default branch.
- **Code:** `spikersoft-backend@98102023` — still broken. `SpikerSoft.GameServer/Physics/ProjectileCollisionSystem.cs:518` still matches `("shockwave", "fireball")` *after* the ordinal normalization at `:504-506`, so the arm is unreachable. **Live path** — `GetComboType` is called at `:126`. **Second fix site the body does not mention:** there is an independent `GetComboType` at `SpikerSoft.GameServer/Zones/DungeonZone.cs:765`, called from `:744` and `:790`. Whether it carries the same dead arm was not verified.
- **Live:** `docker service ps spikersoft-gameserver_spikersoft-gameserver` → 1/1 Running on SERVER, image redeployed 2026-08-07 12:25 UTC; combo unreachable in gameplay by construction.
- **Remaining:** Flip the arm to `("fireball", "shockwave")`; **check the DungeonZone copy at `:765`** so camp and dungeon don't diverge (extracting one shared combo-resolution implementation while fixing would prevent the next drift); then move the pair out of `ProjectileCollisionSystemTests.DetectCombos_ShockwaveFireball_CurrentlyNeverCombos` and back into the pairing-table Theory.
Status: still broken — full detail carried over to the new issue.
Closing here. Work now lives in the repo that holds the fix, so `fixes #540` in a PR will
auto-close it on merge. The umbrella tracker keeps cross-repo epics only.
— Opus 5 Agent
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found by the coverage wave (spikersoft-backend PR #454) while testing
ProjectileCollisionSystem.ProjectileCollisionSystem.GetComboTypenormalizes every spell pair withstring.CompareOrdinalso the ordinally-smaller id always comes first, then matches:Since
"fireball" < "shockwave"ordinally, the normalized tuple for that pair is always("fireball", "shockwave")— the("shockwave", "fireball")pattern can never match, so theshockwave_firecombo (6m radius, 150 damage perSpellComboResult.GetComboProperties) is unreachable in gameplay.Fix: flip the arm to
("fireball", "shockwave").ProjectileCollisionSystemTests.DetectCombos_ShockwaveFireball_CurrentlyNeverCombospins the current behavior and will fail when this is fixed (then move the pair back into the pairing-table Theory).Audited against
origin/master— STILL BROKEN, and there is a second fix site the ticket doesn't mention.The named defect is unchanged.
SpikerSoft.GameServer/Physics/ProjectileCollisionSystem.cs:518still matches("shockwave", "fireball")after the ordinal normalization at:504-506, so the arm is unreachable. Description and line numbers are accurate. This one is live —GetComboTypeis called at:126.The addition: there is a second, independent
GetComboType.SpikerSoft.GameServer/Zones/DungeonZone.cs:765, called from:744and:790. The ticket names only the Physics copy.I did not verify whether the DungeonZone copy carries the same dead arm — flagging it rather than claiming it. But whoever fixes this should check, because a one-line fix to the Physics copy would leave the dungeon path behaving differently from the camp path, and the divergence would be invisible until a player noticed the combo working in one zone and not the other.
That duplication is worth a look on its own terms: two independent implementations of the same combo-resolution logic is how they drift. If they're meant to be identical, extracting one shared implementation while fixing this would prevent the next instance.
Priority context from the same eleven-ticket sweep: this is on a live path, alongside #811 (broken AES on a real network path — the highest severity of the set), #793, #795, #797 and #799. #792, #808 and #840 turned out to be latent with no production caller at all.
Migrated to spikerj/spikersoft-backend#540 as part of the umbrella-tracker breakup.
Verified 2026-08-07 against the synced default branch.
spikersoft-backend@98102023— still broken.SpikerSoft.GameServer/Physics/ProjectileCollisionSystem.cs:518still matches("shockwave", "fireball")after the ordinal normalization at:504-506, so the arm is unreachable. Live path —GetComboTypeis called at:126. Second fix site the body does not mention: there is an independentGetComboTypeatSpikerSoft.GameServer/Zones/DungeonZone.cs:765, called from:744and:790. Whether it carries the same dead arm was not verified.docker service ps spikersoft-gameserver_spikersoft-gameserver→ 1/1 Running on SERVER, image redeployed 2026-08-07 12:25 UTC; combo unreachable in gameplay by construction.("fireball", "shockwave"); check the DungeonZone copy at:765so camp and dungeon don't diverge (extracting one shared combo-resolution implementation while fixing would prevent the next drift); then move the pair out ofProjectileCollisionSystemTests.DetectCombos_ShockwaveFireball_CurrentlyNeverCombosand back into the pairing-table Theory.Status: still broken — full detail carried over to the new issue.
Closing here. Work now lives in the repo that holds the fix, so
fixes #540in a PR willauto-close it on merge. The umbrella tracker keeps cross-repo epics only.
— Opus 5 Agent