Task 2: SpireTab Overhaul - add Climb the Spire button, implement Spire Mode with exit condition
This commit is contained in:
+43
-33
@@ -749,6 +749,9 @@ function makeInitial(overrides: Partial<GameState> = {}): GameState {
|
||||
|
||||
// Mana Well Effects (Phase 4)
|
||||
manaHeartBonus: manaHeartBonus, // Cumulative +10% max mana per loop from MANA_HEART
|
||||
|
||||
// Spire Mode - simplified UI for climbing
|
||||
spireMode: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -801,6 +804,10 @@ interface GameStore extends GameState, CraftingActions {
|
||||
getMeditationMultiplier: () => number;
|
||||
canCastSpell: (spellId: string) => boolean;
|
||||
getSkillUpgradeChoices: (skillId: string, milestone: 5 | 10) => { available: SkillUpgradeChoice[]; selected: string[] };
|
||||
|
||||
// Spire Mode actions
|
||||
enterSpireMode: () => void;
|
||||
exitSpireMode: () => void;
|
||||
}
|
||||
|
||||
export const useGameStore = create<GameStore>()(
|
||||
@@ -833,6 +840,9 @@ export const useGameStore = create<GameStore>()(
|
||||
|
||||
// Compute unified effects (includes skill upgrades AND equipment enchantments)
|
||||
const effects = getUnifiedEffects(state);
|
||||
|
||||
// Track current action for potential auto-transitions
|
||||
let currentAction = state.currentAction;
|
||||
|
||||
const maxMana = computeMaxMana(state, effects);
|
||||
const baseRegen = computeRegen(state, effects);
|
||||
@@ -878,7 +888,7 @@ export const useGameStore = create<GameStore>()(
|
||||
let meditateTicks = state.meditateTicks;
|
||||
let meditationMultiplier = 1;
|
||||
|
||||
if (state.currentAction === 'meditate') {
|
||||
if (currentAction === 'meditate') {
|
||||
meditateTicks++;
|
||||
meditationMultiplier = getMeditationBonus(meditateTicks, state.skills);
|
||||
|
||||
@@ -973,7 +983,7 @@ export const useGameStore = create<GameStore>()(
|
||||
let unlockedEffects = state.unlockedEffects;
|
||||
let consecutiveStudyHours = state.consecutiveStudyHours;
|
||||
|
||||
if (state.currentAction === 'study' && currentStudyTarget) {
|
||||
if (currentAction === 'study' && currentStudyTarget) {
|
||||
// Calculate base study speed
|
||||
let studySpeedMult = getStudySpeedMultiplier(skills);
|
||||
|
||||
@@ -1076,11 +1086,13 @@ export const useGameStore = create<GameStore>()(
|
||||
log = [`📖 ${SPELLS_DEF[spellId]?.name} learned!`, ...log.slice(0, 49)];
|
||||
}
|
||||
currentStudyTarget = null;
|
||||
// Auto-transition to meditate when study completes
|
||||
currentAction = 'meditate';
|
||||
}
|
||||
}
|
||||
// Parallel Study processing (PARALLEL_STUDY special effect)
|
||||
let parallelStudyTarget = state.parallelStudyTarget;
|
||||
if (parallelStudyTarget && state.currentAction === 'study') {
|
||||
if (parallelStudyTarget && currentAction === 'study') {
|
||||
// Parallel study progresses at 50% speed
|
||||
const parallelProgressGain = HOURS_PER_TICK * 0.5;
|
||||
parallelStudyTarget = {
|
||||
@@ -1101,7 +1113,7 @@ export const useGameStore = create<GameStore>()(
|
||||
}
|
||||
|
||||
// Convert action - auto convert mana
|
||||
if (state.currentAction === 'convert') {
|
||||
if (currentAction === 'convert') {
|
||||
const unlockedElements = Object.entries(elements)
|
||||
.filter(([, e]) => e.unlocked && e.current < e.max);
|
||||
|
||||
@@ -1130,7 +1142,7 @@ export const useGameStore = create<GameStore>()(
|
||||
const floorElement = getFloorElement(currentFloor);
|
||||
|
||||
// Handle puzzle rooms separately
|
||||
if (state.currentAction === 'climb' && currentRoom.roomType === 'puzzle') {
|
||||
if (currentAction === 'climb' && currentRoom.roomType === 'puzzle') {
|
||||
const progressSpeed = getPuzzleProgressSpeed(
|
||||
currentRoom.puzzleId || '',
|
||||
state.attunements
|
||||
@@ -1154,7 +1166,7 @@ export const useGameStore = create<GameStore>()(
|
||||
maxFloorReached = Math.max(maxFloorReached, currentFloor);
|
||||
castProgress = 0;
|
||||
}
|
||||
} else if (state.currentAction === 'climb') {
|
||||
} else if (currentAction === 'climb') {
|
||||
const spellId = state.activeSpell;
|
||||
const spellDef = SPELLS_DEF[spellId];
|
||||
|
||||
@@ -1358,7 +1370,7 @@ export const useGameStore = create<GameStore>()(
|
||||
const floorChanged = currentFloor !== golemancy.lastSummonFloor;
|
||||
const inCombatRoom = currentRoom.roomType !== 'puzzle';
|
||||
|
||||
if (state.currentAction === 'climb' && inCombatRoom && floorChanged && maxGolemSlots > 0) {
|
||||
if (currentAction === 'climb' && inCombatRoom && floorChanged && maxGolemSlots > 0) {
|
||||
// Determine which golems should be summoned
|
||||
const unlockedElementIds = Object.entries(elements)
|
||||
.filter(([, e]) => e.unlocked)
|
||||
@@ -1406,7 +1418,7 @@ export const useGameStore = create<GameStore>()(
|
||||
}
|
||||
|
||||
// Process golem maintenance and attacks each tick
|
||||
if (golemancy.summonedGolems.length > 0 && state.currentAction === 'climb' && inCombatRoom) {
|
||||
if (golemancy.summonedGolems.length > 0 && currentAction === 'climb' && inCombatRoom) {
|
||||
const floorDuration = getGolemFloorDuration(skills);
|
||||
const survivingGolems: typeof golemancy.summonedGolems = [];
|
||||
let anyGolemDismissed = false;
|
||||
@@ -1525,7 +1537,7 @@ export const useGameStore = create<GameStore>()(
|
||||
}
|
||||
|
||||
// Unsummon golems when not climbing or in puzzle room
|
||||
if ((state.currentAction !== 'climb' || !inCombatRoom) && golemancy.summonedGolems.length > 0) {
|
||||
if ((currentAction !== 'climb' || !inCombatRoom) && golemancy.summonedGolems.length > 0) {
|
||||
log = [`🗿 Golems returned to the earth.`, ...log.slice(0, 49)];
|
||||
golemancy = {
|
||||
...golemancy,
|
||||
@@ -1559,31 +1571,10 @@ export const useGameStore = create<GameStore>()(
|
||||
// Apply crafting updates
|
||||
if (craftingUpdates.rawMana !== undefined) rawMana = craftingUpdates.rawMana;
|
||||
if (craftingUpdates.log !== undefined) log = craftingUpdates.log;
|
||||
|
||||
// If crafting slice set currentAction (e.g., auto-transition to meditate), use it
|
||||
if (craftingUpdates.currentAction !== undefined) {
|
||||
set({
|
||||
...craftingUpdates,
|
||||
day,
|
||||
hour,
|
||||
rawMana,
|
||||
meditateTicks,
|
||||
totalManaGathered,
|
||||
currentFloor,
|
||||
floorHP,
|
||||
floorMaxHP,
|
||||
maxFloorReached,
|
||||
signedPacts,
|
||||
currentRoom,
|
||||
incursionStrength,
|
||||
currentStudyTarget,
|
||||
skills,
|
||||
skillProgress,
|
||||
spells,
|
||||
elements,
|
||||
log,
|
||||
castProgress,
|
||||
golemancy,
|
||||
});
|
||||
return;
|
||||
currentAction = craftingUpdates.currentAction;
|
||||
}
|
||||
|
||||
set({
|
||||
@@ -1599,6 +1590,7 @@ export const useGameStore = create<GameStore>()(
|
||||
signedPacts,
|
||||
currentRoom,
|
||||
incursionStrength,
|
||||
currentAction,
|
||||
currentStudyTarget,
|
||||
parallelStudyTarget,
|
||||
skills,
|
||||
@@ -1929,6 +1921,24 @@ export const useGameStore = create<GameStore>()(
|
||||
set(newState);
|
||||
},
|
||||
|
||||
// Spire Mode - enter simplified UI for climbing
|
||||
enterSpireMode: () => {
|
||||
set((state) => ({
|
||||
spireMode: true,
|
||||
currentAction: 'climb',
|
||||
log: ['🏔️ Entered Spire Mode! The climb begins...', ...state.log.slice(0, 49)],
|
||||
}));
|
||||
},
|
||||
|
||||
// Exit Spire Mode - return to normal game UI
|
||||
exitSpireMode: () => {
|
||||
set((state) => ({
|
||||
spireMode: false,
|
||||
currentAction: 'meditate',
|
||||
log: ['⬇️ Climbed down from the Spire. Returning to normal view.', ...state.log.slice(0, 49)],
|
||||
}));
|
||||
},
|
||||
|
||||
togglePause: () => {
|
||||
set((state) => ({ paused: !state.paused }));
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user