fix: multiple bug fixes - infinite loop crash, enchant tick handlers, discipline crash, Plasma symbol, desync
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m24s

- #236: Fix Climb the Spire React #185 infinite loop - removed redundant set() in processCombatTick that caused double Zustand writes per tick
- #235: Add enchanting design/prepare/apply tick handlers - extracted to pipelines/enchanting-tick.ts
- #235: Fix startApplying not setting currentAction to 'enchant'
- #243: Guard discipline store against undefined activeIds/processedPerks from corrupted persisted state
- #245: Change Plasma symbol from  (conflicts with Lightning) to 🔴
- #241: Fix combat store maxFloorReached desync - initialize to 0, reset on exitSpireMode
- #239: Fix EffectSelector not rendering when unlockedEffects is empty (fresh game)
- Created pipelines/enchanting-tick.ts to keep gameStore.ts under 400 lines
This commit is contained in:
2026-06-01 12:57:52 +02:00
parent 2539559edc
commit 7dd9ad5b92
11 changed files with 213 additions and 21 deletions
+9 -6
View File
@@ -77,9 +77,12 @@ export const useDisciplineStore = create<DisciplineStore>()(
const def = DISCIPLINE_MAP[id];
if (!def) return s;
// Guard against corrupted persisted state
const activeIds = s.activeIds ?? [];
// Allow re-activation if discipline exists but is paused
const existing = s.disciplines[id];
if (s.activeIds.includes(id)) {
if (activeIds.includes(id)) {
// If already active and paused, un-pause it
if (existing?.paused) {
return {
@@ -89,7 +92,7 @@ export const useDisciplineStore = create<DisciplineStore>()(
return s;
}
const nonPaused = s.activeIds.filter((aid) => {
const nonPaused = activeIds.filter((aid) => {
const d = s.disciplines[aid];
return d && !d.paused;
}).length;
@@ -117,7 +120,7 @@ export const useDisciplineStore = create<DisciplineStore>()(
get().practicingCallbacks?.onStartPracticing?.();
return {
disciplines: { ...s.disciplines, [id]: { ...discState, paused: false } },
activeIds: [...s.activeIds, id],
activeIds: [...activeIds, id],
};
});
},
@@ -160,10 +163,10 @@ export const useDisciplineStore = create<DisciplineStore>()(
const newDisciplines = { ...s.disciplines };
const newUnlockedEffects: string[] = [];
const newUnlockedRecipes: string[] = [];
const newProcessedPerks = [...s.processedPerks];
const newProcessedPerks = [...(s.processedPerks ?? [])];
const drainedIds: string[] = [];
for (const id of s.activeIds) {
for (const id of s.activeIds ?? []) {
const disc = newDisciplines[id];
if (!disc) continue;
if (disc.paused) continue;
@@ -245,7 +248,7 @@ export const useDisciplineStore = create<DisciplineStore>()(
);
// Remove mana-drained disciplines from activeIds so onStopPracticing fires
const newActiveIds = s.activeIds.filter((aid) => !drainedIds.includes(aid));
const newActiveIds = (s.activeIds ?? []).filter((aid) => !drainedIds.includes(aid));
if (newActiveIds.length === 0 && s.activeIds.length > 0) {
get().practicingCallbacks?.onStopPracticing?.();
}