Invincibility (iframes) Cap
The ship’s invulnerable state is hard-capped at 5 seconds of continuous wall-clock time. The cap exists as an anti-stack safety net: if every source of iframes stacked freely, the player could accrue dozens of seconds of invulnerability via overlapping triggers (hit-stop + shield-break grace + post-revive iframes + an artifact pulse) and become functionally invincible against entire boss phases. The cap forces all iframe windows to compete for the same 5-second wall-time budget.
Stuck-invuln watchdog
A watchdog runs every physics frame. It tracks _invulnWallTime, the wall-clock seconds the ship has been continuously invulnerable. The accumulator resets the instant ship.invulnerable flips false.
When _invulnWallTime > 5 and the game phase is playing, the watchdog force-clears the state: sets invulnerable=false, zeros invulnTimer, zeros _invulnWallTime, and logs [BUG] ship.invulnerable stuck for Xs — force-clearing to the console. This is treated as a bug guard rather than a balance rule — any legitimate iframe source should expire well before 5 seconds.
The accumulator uses raw dt (real wall-clock seconds), not scaled dt, so intentional game-time freezes (weapon chest pickup, hit-stop pauses) do not inflate the counter. If dt is 0 in a given frame, the counter does not advance.
Bypass: _dontStuckInvuln + setGodMode
The boss gauntlet test harness needs to hold god-mode for the full duration of a 60-second-plus boss fight. To prevent the watchdog from fighting the test, the harness flips two flags before invoking setGodMode:
ship._dontStuckInvuln = true— early-returns the watchdog and keeps_invulnWallTimepinned to 0.setGodMode(true)— setsship.invulnerable = truevia the bridge.
The bypass must be set before _configurePlayerForMode flips invulnerable on, otherwise a single stale frame can seed the accumulator and trip a spurious warning later. The gauntlet runner clears both flags on teardown.
Star Power exception
Star Power is the one in-game iframe source that legitimately holds invulnerable past 5 seconds (15 seconds base, 60-plus seconds with stacking). The watchdog explicitly checks hasExclusiveState(ship, 'starpower') and skips the force-clear branch while Star Power is active. While the state is on, ship.invulnerable is reasserted every frame and invulnTimer is held at exclusiveStateTimer.
Sources of invuln
The shorter, watchdog-bound iframe sources that stack into the 5-second budget:
- Hit-stop / shield-break grace —
CFG.INVULN(~0.3 seconds) granted when the shield breaks, to prevent the same attack from chunking HP in the same frame. - Post-revive iframes — Death Defiance and revive flows grant longer windows (the bridge sets values like 2 seconds and 3 seconds).
- Artifact pulses — e.g. the warp-puddle module refreshes
invulnTimer = 0.1each frame the player is inside the field. - Star Power — the only source exempt from the watchdog (see above).
All of these route through ship.invulnerable and ship.invulnTimer. The damage-chain trace records a blocked attempt with invuln: true and the current invulnTimer value when the invuln gate rejects a hit at the top of damagePlayer.