fix: deactivate all disciplines when entering/exiting the Spire
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m20s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m20s
- Add deactivateAll() action to discipline-slice.ts - Call deactivateAll() in createEnterSpireMode() (combat-descent-actions.ts) - Add spireMode guard in gameStore.ts tick() to skip discipline processTick - Call deactivateAll() in exitSpireMode() (combatStore.ts) as safety measure - Extract buildConversionParams to utils/conversion-params.ts to keep gameStore.ts under 400 lines - Add regression tests (5 tests, all 1136 passing) Fixes #347
This commit is contained in:
@@ -10,6 +10,7 @@ import { useManaStore } from './manaStore';
|
||||
import { summonGolemsOnRoomEntry } from './golem-combat-actions';
|
||||
import { computeDisciplineEffects } from '../effects/discipline-effects';
|
||||
import { useAttunementStore } from './attunementStore';
|
||||
import { useDisciplineStore } from './discipline-slice';
|
||||
import {
|
||||
onEnterLibraryRoom,
|
||||
onEnterRecoveryRoom,
|
||||
@@ -278,6 +279,9 @@ export function createEnterSpireMode(get: GetFn, set: SetFn) {
|
||||
golemancy: { activeGolems: [], lastSummonFloor: 0, golemDesigns: get().golemancy?.golemDesigns ?? {}, golemLoadout: [] },
|
||||
});
|
||||
|
||||
// Deactivate all active disciplines when entering the Spire
|
||||
useDisciplineStore.getState().deactivateAll();
|
||||
|
||||
get().addActivityLog('floor_transition',
|
||||
`Entered the Spire at Floor ${startFloor}`);
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import {
|
||||
onEnterLibraryRoom, tickNonCombatRoom, skipNonCombatRoom, stayLongerInRoom,
|
||||
} from './non-combat-room-actions';
|
||||
import { useDisciplineStore } from './discipline-slice';
|
||||
import {
|
||||
addGolemDesign, removeGolemDesign, toggleGolemLoadoutEntry,
|
||||
} from './golemancy-actions';
|
||||
@@ -210,6 +211,8 @@ export const useCombatStore = create<CombatStore>()(
|
||||
maxFloorReached: Math.max(s.maxFloorReached, 1),
|
||||
golemancy: { ...s.golemancy, activeGolems: [] as RuntimeActiveGolem[] },
|
||||
});
|
||||
// Deactivate all disciplines on spire exit for safety
|
||||
useDisciplineStore.getState().deactivateAll();
|
||||
get().addActivityLog('floor_transition', 'Exited the Spire');
|
||||
},
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ export interface DisciplineStoreState {
|
||||
export interface DisciplineStoreActions {
|
||||
activate: (id: string, gameStateOverrides?: { elements?: Record<string, ElementState>; rawMana?: number; signedPacts?: number[] }) => void;
|
||||
deactivate: (id: string) => void;
|
||||
deactivateAll: () => void;
|
||||
processTick: (mana: { rawMana: number; elements: Record<string, ElementState> }) => {
|
||||
rawMana: number;
|
||||
elements: Record<string, ElementState>;
|
||||
@@ -161,6 +162,22 @@ export const useDisciplineStore = create<DisciplineStore>()(
|
||||
});
|
||||
},
|
||||
|
||||
deactivateAll() {
|
||||
set((s) => {
|
||||
const newDisciplines = { ...s.disciplines };
|
||||
for (const id of s.activeIds) {
|
||||
if (newDisciplines[id]) {
|
||||
newDisciplines[id] = { ...newDisciplines[id], paused: true };
|
||||
}
|
||||
}
|
||||
get().practicingCallbacks?.onStopPracticing?.();
|
||||
return {
|
||||
activeIds: [],
|
||||
disciplines: newDisciplines,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
setPracticingCallbacks(callbacks) {
|
||||
set({ practicingCallbacks: callbacks });
|
||||
},
|
||||
|
||||
@@ -19,7 +19,6 @@ import { useCombatStore } from './combatStore';
|
||||
import { useAttunementStore } from './attunementStore';
|
||||
import { useCraftingStore } from './craftingStore';
|
||||
import { useDisciplineStore } from './discipline-slice';
|
||||
import { ATTUNEMENTS_DEF } from '../data/attunements';
|
||||
import { createResetGame, createGatherMana } from './gameActions';
|
||||
import { createSafeStorage } from '../utils/safe-persist';
|
||||
import { createStartNewLoop } from './gameLoopActions';
|
||||
@@ -27,6 +26,7 @@ import { buildTickContext, applyTickWrites } from './tick-pipeline';
|
||||
import { processEnchantingTicks } from './pipelines/enchanting-tick';
|
||||
import { buildGolemCombatPipeline } from './pipelines/golem-combat';
|
||||
import { getGuardianForFloor } from '../data/guardian-encounters';
|
||||
import { buildConversionParams } from '../utils/conversion-params';
|
||||
|
||||
import type { TickContext, TickWrites } from './tick-pipeline';
|
||||
import type { GameCoordinatorState } from './gameStore.types';
|
||||
@@ -228,7 +228,10 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
usePrestigeStore.getState().completePactRitual(addLog);
|
||||
}
|
||||
|
||||
const dr = useDisciplineStore.getState().processTick({ rawMana, elements });
|
||||
// Skip discipline processing during spire runs (defense-in-depth)
|
||||
const dr = ctx.combat.spireMode
|
||||
? { rawMana, elements, unlockedEffects: [], unlockedRecipes: [], autoPausedNames: [] }
|
||||
: useDisciplineStore.getState().processTick({ rawMana, elements });
|
||||
rawMana = dr.rawMana; elements = dr.elements;
|
||||
rawMana = Math.min(rawMana, computeMaxMana({ prestigeUpgrades: ctx.prestige.prestigeUpgrades }, undefined, computeDisciplineEffects()));
|
||||
|
||||
@@ -373,27 +376,4 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
)
|
||||
);
|
||||
|
||||
/** Build pact element map and gross regen for the unified conversion system */
|
||||
function buildConversionParams(
|
||||
signedPacts: number[],
|
||||
attunements: Record<string, { active: boolean; level: number }>,
|
||||
): { pactElementMap: Record<number, string>; grossRegen: Record<string, number> } {
|
||||
const pactElementMap: Record<number, string> = {};
|
||||
for (const floor of signedPacts) {
|
||||
const guardian = getGuardianForFloor(floor);
|
||||
if (guardian?.element?.length) {
|
||||
pactElementMap[floor] = guardian.element[0];
|
||||
}
|
||||
}
|
||||
const grossRegen: Record<string, number> = {};
|
||||
for (const [id, state] of Object.entries(attunements)) {
|
||||
if (!state.active) continue;
|
||||
const def = ATTUNEMENTS_DEF[id];
|
||||
if (def?.primaryManaType && def.rawManaRegen) {
|
||||
const levelMult = Math.pow(1.5, (state.level || 1) - 1);
|
||||
grossRegen[def.primaryManaType] = (grossRegen[def.primaryManaType] || 0)
|
||||
+ def.rawManaRegen * levelMult;
|
||||
}
|
||||
}
|
||||
return { pactElementMap, grossRegen };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user