-
- {actions.map(({ id, label, icon: Icon }) => (
-
- ))}
-
-
- {/* Crafting actions row - shown when there's active crafting progress */}
- {(hasDesignProgress || hasPrepProgress || hasAppProgress) && (
-
-
-
-
+
+
+
+ Current Activity
- )}
+
+ {config.label}
+
+ {getActionDetails()}
+
+ {/* Show second design slot if active */}
+ {designProgress2 && (
+
+
+
+ Second Design Slot
+
+
+
+ )}
+
);
}
diff --git a/src/components/game/tabs/SpireTab.tsx b/src/components/game/tabs/SpireTab.tsx
index ab2be33..c625760 100755
--- a/src/components/game/tabs/SpireTab.tsx
+++ b/src/components/game/tabs/SpireTab.tsx
@@ -19,9 +19,10 @@ import { getUnifiedEffects } from '@/lib/game/effects';
interface SpireTabProps {
store: GameStore;
+ simpleMode?: boolean; // When true, only show essential Spire info (for Spire Mode)
}
-export function SpireTab({ store }: SpireTabProps) {
+export function SpireTab({ store, simpleMode = false }: SpireTabProps) {
const floorElem = getFloorElement(store.currentFloor);
const floorElemDef = ELEMENTS[floorElem];
const isGuardianFloor = !!GUARDIANS[store.currentFloor];
@@ -48,7 +49,7 @@ export function SpireTab({ store }: SpireTabProps) {
return (
-
+
{/* Current Floor Card */}
@@ -92,35 +93,39 @@ export function SpireTab({ store }: SpireTabProps) {
-
-
- {/* Floor Navigation - Direction indicator only */}
-
-
-
Direction
-
-
-
- Up
-
-
-
- Down
-
+ {!simpleMode && (
+ <>
+
+
+ {/* Floor Navigation - Direction indicator only */}
+
+
+
Direction
+
+
+
+ Up
+
+
+
+ Down
+
+
+
+
+ {isFloorCleared && (
+
+
+ Floor cleared! Advancing...
+
+ )}
-
-
- {isFloorCleared && (
-
-
- Floor cleared! Advancing...
-
- )}
-
-
-
+
+
+ >
+ )}
Best: Floor
{store.maxFloorReached} •
@@ -205,8 +210,8 @@ export function SpireTab({ store }: SpireTabProps) {
- {/* Summoned Golems Card */}
- {store.golemancy.summonedGolems.length > 0 && (
+ {/* Summoned Golems Card - Always show in simple mode, conditional in normal mode */}
+ {(simpleMode || store.golemancy.summonedGolems.length > 0) && (
@@ -257,8 +262,8 @@ export function SpireTab({ store }: SpireTabProps) {
)}
- {/* Current Study (if any) */}
- {store.currentStudyTarget && (
+ {/* Current Study (if any) - Only show in normal mode */}
+ {!simpleMode && store.currentStudyTarget && (
)}
- {/* Crafting Progress (if any) */}
- {(store.designProgress || store.preparationProgress || store.applicationProgress) && (
+ {/* Crafting Progress (if any) - Only show in normal mode */}
+ {!simpleMode && (store.designProgress || store.preparationProgress || store.applicationProgress) && (
)}
- {/* Activity Log */}
-
-
- Activity Log
-
-
-
-
- {store.log.slice(0, 20).map((entry, i) => (
-
- {entry}
-
- ))}
-
-
-
-
+ {/* Activity Log - Only show in normal mode */}
+ {!simpleMode && (
+
+
+ Activity Log
+
+
+
+
+ {store.log.slice(0, 20).map((entry, i) => (
+
+ {entry}
+
+ ))}
+
+
+
+
+ )}
);
diff --git a/src/lib/game/store.ts b/src/lib/game/store.ts
index d497d2e..e57db5e 100755
--- a/src/lib/game/store.ts
+++ b/src/lib/game/store.ts
@@ -749,6 +749,9 @@ function makeInitial(overrides: Partial
= {}): 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()(
@@ -833,6 +840,9 @@ export const useGameStore = create()(
// 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()(
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()(
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()(
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()(
}
// 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()(
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()(
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()(
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()(
}
// 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()(
}
// 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()(
// 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()(
signedPacts,
currentRoom,
incursionStrength,
+ currentAction,
currentStudyTarget,
parallelStudyTarget,
skills,
@@ -1929,6 +1921,24 @@ export const useGameStore = create()(
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 }));
},
diff --git a/src/lib/game/types/game.ts b/src/lib/game/types/game.ts
index 5c2ba11..38785b3 100644
--- a/src/lib/game/types/game.ts
+++ b/src/lib/game/types/game.ts
@@ -212,6 +212,9 @@ export interface GameState {
// Loop insight (earned at end of current loop)
loopInsight: number;
+
+ // Spire Mode - simplified UI for climbing
+ spireMode: boolean;
}
// ─── Action Types for Store ─────────────────────────────────────────────