-
-
- {golemDef.name}
-
+
+ {golemDef.name}
- {golemDef.isAoe && (
-
AOE {golemDef.aoeTargets}
- )}
+ {golemDef.isAoe &&
AOE {golemDef.aoeTargets}}
-
- ⚔️ {damage} DMG • ⚡ {attackSpeed.toFixed(1)}/hr •
- 🗡️ {Math.floor(golemDef.armorPierce * 100)}% Pierce
-
- {/* Attack progress bar when climbing */}
+
⚔️ {damage} DMG • ⚡ {attackSpeed.toFixed(1)}/hr
{store.currentAction === 'climb' && summoned.attackProgress > 0 && (
-
-
+
+
Attack
- {Math.min(100, (summoned.attackProgress * 100)).toFixed(0)}%
+ {(summoned.attackProgress * 100).toFixed(0)}%
+
+
-
)}
);
})}
-
-
- )}
-
- {/* Current Study (if any) - Only show in normal mode */}
- {!simpleMode && store.currentStudyTarget && (
-
-
-
-
- {/* Parallel Study Progress */}
- {store.parallelStudyTarget && (
-
-
-
-
-
- Parallel: {SKILLS_DEF[store.parallelStudyTarget.id]?.name}
- {store.parallelStudyTarget.type === 'skill' && ` Lv.${(store.skills[store.parallelStudyTarget.id] || 0) + 1}`}
-
-
-
-
-
-
- {formatStudyTime(store.parallelStudyTarget.progress)} / {formatStudyTime(store.parallelStudyTarget.required)}
- 50% speed (Parallel Study)
-
+
+
+
+ )}
+
+ {/* Guardian Panel */}
+ {isGuardianFloor && simpleMode && (
+
+ )}
+
+ {/* Room Display */}
+ {simpleMode && (
+
+ )}
+
+ {/* Floor Controls */}
+ {simpleMode && (
+
+ )}
+
+ {/* Combat Stats Panel */}
+ {simpleMode && (
+
+ )}
+
+ {/* Activity Log - Spire Mode only */}
+ {simpleMode &&
}
+
+ {/* Study Progress - Normal mode only */}
+ {!simpleMode && store.currentStudyTarget && (
+
+
+ Study: {getSkillName(store.currentStudyTarget.id)}
+
+ {store.parallelStudyTarget && (
+
+
Parallel: {getSkillName(store.parallelStudyTarget.id)} (50% speed)
+
- )}
-
-
- )}
-
- {/* Activity Log - Show in Spire Mode (simpleMode) */}
- {simpleMode && (
-
-
- Activity Log
-
-
-
-
- {(store.activityLog || []).slice(0, 50).map((entry: ActivityLogEntry, i) => {
- // Style based on event type
- const getEventStyle = (eventType: string) => {
- switch (eventType) {
- case 'enemy_defeated':
- case 'floor_cleared':
- return 'text-green-400';
- case 'damage_dealt':
- return 'text-red-400';
- case 'dodge':
- return 'text-yellow-400';
- case 'armor_proc':
- return 'text-blue-400';
- case 'special_effect':
- return 'text-purple-400';
- case 'floor_transition':
- return 'text-cyan-400';
- case 'spell_cast':
- return 'text-amber-400';
- case 'golem_attack':
- return 'text-orange-400';
- case 'puzzle_solved':
- return 'text-pink-400';
- default:
- return 'text-gray-300';
- }
- };
-
- return (
-
- {entry.message}
-
- );
- })}
- {(store.activityLog || []).length === 0 && (
-
No activity yet...
- )}
+
+ )}
+
+
+ )}
+
+ {/* Crafting Progress - Normal mode only */}
+ {!simpleMode && (store.designProgress || store.preparationProgress || store.applicationProgress) && (
+
+
+ {store.designProgress && (
+
+
Design Progress
+
-
-
-
- )}
-
- {/* Crafting Progress (if any) - Only show in normal mode */}
- {!simpleMode && (store.designProgress || store.preparationProgress || store.applicationProgress) && (
-
-
-
-
-
- )}
-
-
+
+ )}
+ {store.preparationProgress && (
+
+
Preparation Progress
+
+
+ )}
+ {store.applicationProgress && (
+
+
Application Progress
+
+
+ )}
+
+
+ )}
+
);
}
SpireTab.displayName = "SpireTab";
+
+function getSkillName(skillId: string): string {
+ const { SKILLS_DEF } = require('@/lib/game/constants');
+ return SKILLS_DEF[skillId]?.name || skillId;
+}
+
+function fmt(value: number): string {
+ if (value >= 1e12) return (value / 1e12).toFixed(2) + 't';
+ if (value >= 1e9) return (value / 1e9).toFixed(2) + 'b';
+ if (value >= 1e6) return (value / 1e6).toFixed(2) + 'm';
+ if (value >= 1e3) return (value / 1e3).toFixed(2) + 'k';
+ return value.toFixed(0);
+}
+
+function getGolemDef(golemId: string) {
+ const { GOLEMS_DEF } = require('@/lib/game/data/golems');
+ return GOLEMS_DEF[golemId];
+}
+
+function getGolemDamage(golemId: string, skills: any) {
+ const { getGolemDamage } = require('@/lib/game/data/golems');
+ return getGolemDamage(golemId, skills);
+}
+
+function getGolemAttackSpeed(golemId: string, skills: any) {
+ const { getGolemAttackSpeed } = require('@/lib/game/data/golems');
+ return getGolemAttackSpeed(golemId, skills);
+}
diff --git a/src/components/game/tabs/index.ts b/src/components/game/tabs/index.ts
index 92431b4..312d95f 100755
--- a/src/components/game/tabs/index.ts
+++ b/src/components/game/tabs/index.ts
@@ -13,3 +13,11 @@ export { DebugTab } from './DebugTab';
export { LootTab } from './LootTab';
export { AchievementsTab } from './AchievementsTab';
export { GolemancyTab } from './GolemancyTab';
+
+// Spire sub-components
+export { SpireHeader } from './SpireHeader';
+export { GuardianPanel } from './GuardianPanel';
+export { RoomDisplay } from './RoomDisplay';
+export { FloorControls } from './FloorControls';
+export { CombatStatsPanel } from './CombatStatsPanel';
+export { ActivityLog } from './ActivityLog';
diff --git a/src/lib/game/types.ts b/src/lib/game/types.ts
index 5993508..49a6287 100755
--- a/src/lib/game/types.ts
+++ b/src/lib/game/types.ts
@@ -1,14 +1,64 @@
-// ─── Game Types ───────────────────────────────────────────────────────────────
-// This file now re-exports types from domain-specific files in the types/ directory.
-// All type definitions have been moved to:
-// - types/elements.ts - element-related types
-// - types/attunements.ts - attunement-related types
-// - types/spells.ts - spell-related types
-// - types/skills.ts - skill-related types
-// - types/equipment.ts - equipment-related types
-// - types/game.ts - core game state types
-//
-// Import from this file (types.ts) to maintain backward compatibility,
-// or import directly from the domain-specific files.
+import type { GameStore } from '@/lib/game/store';
+import type { SPELLS } from '@/lib/game/constants';
+import type { EquipmentSpellState } from '@/lib/game/state';
+import type { RoomType, ActivityLogEntry } from '@/lib/game/types/game';
-export * from './types/index';
+// Re-export ActivityLogEntry for convenience
+export { ActivityLogEntry };
+
+// Room Display Props
+export interface RoomDisplayProps {
+ roomType: RoomType;
+ roomConfig: { label: string; icon: string; color: string };
+ primaryEnemy: any;
+ swarmEnemies: any[];
+ puzzleId?: string;
+ puzzleProgress?: number;
+ simpleMode: boolean;
+ floorElemDef: any;
+ floorHP: number;
+ floorMaxHP: number;
+ totalDPS: number;
+ currentAction: string | null;
+ activeEquipmentSpells: Array<{ spellId: string; equipmentId: string }>;
+}
+
+// Floor Controls Props
+export interface FloorControlsProps {
+ store: GameStore;
+ climbDirection: 'up' | 'down' | null;
+ isGuardianFloor: boolean;
+ currentRoom: any;
+ currentGuardian: any;
+ isFloorCleared: boolean;
+ floorElemDef: any;
+ roomType: RoomType;
+ roomConfig: { label: string; icon: string; color: string };
+ activeEquipmentSpells: Array<{ spellId: string; equipmentId: string }>;
+ upgradeEffects: any;
+ floorElem: string;
+ totalDPS: number;
+ getEnemyName: typeof import('@/lib/game/store').getEnemyName;
+ calcDamage: typeof import('@/lib/game/store').calcDamage;
+ SPELLS_DEF: typeof import('@/lib/game/constants').SPELLS_DEF;
+ canCastSpell: (spellId: string) => boolean;
+ storeCurrentAction: string | null;
+ handleClimb: (direction: 'up' | 'down') => void;
+ formatSpellCost: typeof import('@/lib/game/formatting').formatSpellCost;
+ getSpellCostColor: typeof import('@/lib/game/formatting').getSpellCostColor;
+}
+
+// Combat Stats Panel Props
+export interface CombatStatsPanelProps {
+ activeEquipmentSpells: Array<{ spellId: string; equipmentId: string }>;
+ store: GameStore;
+ totalDPS: number;
+ calcDamage: typeof import('@/lib/game/store').calcDamage;
+ formatSpellCost: typeof import('@/lib/game/formatting').formatSpellCost;
+ getSpellCostColor: typeof import('@/lib/game/formatting').getSpellCostColor;
+ SPELLS_DEF: typeof import('@/lib/game/constants').SPELLS_DEF;
+ upgradeEffects: any;
+ canCastSpell: (spellId: string) => boolean;
+ studySpeedMult: number;
+ storeCurrentAction: string | null;
+}