🐛 Entering the spire crashes the game irreversibly #125
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bug
Entering the spire causes an irreversible game crash. The player gets stuck in a crashed state and even refreshing the page doesn't fix it (because the corrupted state is persisted in localStorage via Zustand persist).
Root Cause Analysis
Critical Issue 1:
enterSpireMode()doesn't reset stateenterSpireMode()incombatStore.tsonly sets{ spireMode: true }. It does NOT reset:currentFloor(stays at whatever it was — could be 100)floorHP/floorMaxHP(stale values)currentRoom(stale room from previous climb)castProgress,climbDirection,isDescendingCritical Issue 2: Stale persisted state
On first render of
SpireCombatPage(beforeuseEffectfires),currentRoomis the stale persisted value from localStorage. If this value has an unhandledroomType(like'recovery','library','treasure'fromspire-utils.ts), or isnull/undefined,RoomDisplaycrashes onfloorState.roomTypeaccess.Critical Issue 3: Type system bypassed
spire-utils.tsusesas unknown as FloorStatecasts for recovery/library/treasure rooms, bypassing TypeScript's type checking. These room types have different field names than whatRoomDisplayexpects.Critical Issue 4: No null check on
currentRoomSpireCombatPagepassesfloorState={currentRoom}toRoomDisplaywithout checking ifcurrentRoomis valid.The Irreversible Crash Loop
spireMode: truespireMode: true→ SpireCombatPage mounts → crashes againFiles Involved
src/lib/game/stores/combatStore.ts(enterSpireMode, exitSpireMode)src/lib/game/stores/combat-actions.ts(spire actions)src/components/game/tabs/SpireCombatPage/SpireCombatPage.tsxsrc/components/game/tabs/SpireCombatPage/RoomDisplay.tsxsrc/lib/game/utils/spire-utils.tssrc/app/page.tsx(ErrorBoundary wrapping)Suggested Fix
enterSpireMode()must fully reset spire state: floor=1, fresh room, HP reset, action='climb'currentRoombefore renderingRoomDisplayexitSpireMode()to reset all spire-related statespire-utils.ts— properly extendFloorStatetype or handle different room types explicitly✅ Fixed. Changes made:
enterSpireMode()now fully resets spire state (floor=1, fresh room, HP reset, castProgress=0, clearedFloors={}, etc.)exitSpireMode()now resets all spire-related state back to defaultsfloorStatebefore renderingas unknown as FloorStatecasts; recovery/library/treasure rooms now return proper typesRoomTypeto include'recovery' | 'library' | 'treasure'; addedrecoveryProgress/RequiredandlibraryProgress/Requiredfields toFloorStateonResetcallback with a "Reset & Recover" buttononResetthat callsexitSpireMode()to break crash looprecoveryProgress/recoveryRequiredinstead ofpuzzleProgress/puzzleRequired✅ Fixed spire crash (enterSpireMode now resets state and exitSpireMode resets spire state). Added null guard in RoomDisplay and proper type handling for recovery/library/treasure rooms.