[High] [Bug] Active disciplines not deactivated when entering the Spire #347
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: Active disciplines not deactivated when entering the Spire
Steps to reproduce
Expected behavior
When entering the Spire, all active disciplines should be deactivated (stopped). The player is now focused on climbing/combat, not practicing disciplines. Disciplines should not drain mana or gain XP during spire runs.
Actual behavior
Disciplines remain fully active during the entire spire run. They continue to:
onStartPracticingcallbacks (settingcurrentActionto'practicing', which conflicts with'climb')Root cause analysis
File 1:
src/lib/game/stores/combat-descent-actions.ts(lines 247-284)createEnterSpireMode()setsspireMode: trueandcurrentAction: 'climb'but never callsuseDisciplineStore.getState().deactivate()for each active discipline, nor does it clearactiveIds.File 2:
src/lib/game/stores/combatStore.ts(lines 186-216)exitSpireMode()resetscurrentActionto'meditate'but also never deactivates disciplines. If disciplines were somehow still active from before entering, they would resume ticking after exit.File 3:
src/lib/game/stores/gameStore.ts(line 231)The
tick()function callsuseDisciplineStore.getState().processTick(...)unconditionally — there is no guard likeif (ctx.combat.spireMode) returnto skip discipline processing during spire runs.File 4:
src/lib/game/stores/discipline-slice.tsThe discipline store has zero awareness of spire mode. It imports no spire-related state and checks no spire flag in
processTick().Evidence
grepforspireModeindiscipline-slice.tsreturns zero matchesgrepfordisciplineincombat-descent-actions.tsreturns only thecomputeDisciplineEffectsimport (for golem summoning), with no discipline deactivation logicenterSpireModefunction incombat-descent-actions.tsdoes not import or call any discipline store actionsexitSpireModefunction incombatStore.tsdoes not import or call any discipline store actionsSeverity: High
This is a high-severity bug because:
practicingCallbackssystem setscurrentActionto'practicing'when disciplines are active, but spire mode sets it to'climb'— these conflict, and the last setter wins depending on tick orderingSuggested fix locations
combat-descent-actions.ts→createEnterSpireMode(): After setting spire state, iterateuseDisciplineStore.getState().activeIdsand calldeactivate(id)for each, or add a newdeactivateAll()action to the discipline storegameStore.ts→tick(): Add an early return or skip for disciplineprocessTickwhenctx.combat.spireModeis true (defense-in-depth)combatStore.ts→exitSpireMode(): Also deactivate disciplines on exit for safetyAffected files
src/lib/game/stores/combat-descent-actions.tssrc/lib/game/stores/combatStore.tssrc/lib/game/stores/gameStore.tssrc/lib/game/stores/discipline-slice.tsStarting work on this bug. Reading affected files to understand current state before implementing fix.
Fix applied — all 1136 tests pass (64 test files)
Changes made across 4 files:
1.
src/lib/game/stores/discipline-slice.tsdeactivateAll()action to the discipline store interface and implementationactiveIds, marks each discipline as paused, clearsactiveIds, firesonStopPracticingcallback2.
src/lib/game/stores/combat-descent-actions.tsuseDisciplineStoreuseDisciplineStore.getState().deactivateAll()call increateEnterSpireMode()after setting spire state — this is the primary fix3.
src/lib/game/stores/gameStore.tstick(): whenctx.combat.spireModeis true, disciplineprocessTickis skipped entirely (returns empty result), preventing any mana drain or XP accrual during spire runs even if disciplines somehow remain active4.
src/lib/game/stores/combatStore.tsuseDisciplineStoreuseDisciplineStore.getState().deactivateAll()call inexitSpireMode()as a safety measure to clean up any edge casesNew test file:
src/lib/game/__tests__/discipline-deactivate-on-spire-entry.test.ts— 5 regression tests covering:deactivateAll()preserves XP and pause statedeactivateAll()works with multiple active disciplinesFix committed and pushed (commit
48eee17). All 1136 tests pass. Pre-commit hooks passed (file sizes, tests, project structure updated).