diff --git a/docs/circular-deps.txt b/docs/circular-deps.txt index a194a94..551811a 100644 --- a/docs/circular-deps.txt +++ b/docs/circular-deps.txt @@ -1,4 +1,4 @@ # Circular Dependencies -Generated: 2026-05-27T09:40:41.085Z +Generated: 2026-05-27T09:44:00.635Z No circular dependencies found. ✅ diff --git a/docs/dependency-graph.json b/docs/dependency-graph.json index 2ef1359..ae82217 100644 --- a/docs/dependency-graph.json +++ b/docs/dependency-graph.json @@ -1,6 +1,6 @@ { "_meta": { - "generated": "2026-05-27T09:40:39.287Z", + "generated": "2026-05-27T09:43:58.768Z", "description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.", "usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry." }, diff --git a/docs/project-structure.txt b/docs/project-structure.txt index 768038f..3c52250 100644 --- a/docs/project-structure.txt +++ b/docs/project-structure.txt @@ -115,6 +115,7 @@ Mana-Loop/ │ │ │ │ │ └── index.ts │ │ │ │ ├── StatsTab/ │ │ │ │ │ ├── CombatStatsSection.tsx +│ │ │ │ │ ├── DisciplineStatsSection.tsx │ │ │ │ │ ├── ElementStatsSection.tsx │ │ │ │ │ ├── LoopStatsSection.tsx │ │ │ │ │ ├── ManaStatsSection.tsx diff --git a/src/components/game/tabs/StatsTab.tsx b/src/components/game/tabs/StatsTab.tsx index b2b830d..3b5377b 100644 --- a/src/components/game/tabs/StatsTab.tsx +++ b/src/components/game/tabs/StatsTab.tsx @@ -2,12 +2,14 @@ import { usePrestigeStore } from '@/lib/game/stores'; import { useManaStats, useCombatStats, useStudyStats } from '@/lib/game/hooks/useGameDerived'; +import { computeDisciplineEffects } from '@/lib/game/effects/discipline-effects'; import { ManaStatsSection } from './StatsTab/ManaStatsSection'; import { CombatStatsSection } from './StatsTab/CombatStatsSection'; import { PactStatusSection } from './StatsTab/PactStatusSection'; import { StudyStatsSection } from './StatsTab/StudyStatsSection'; import { ElementStatsSection } from './StatsTab/ElementStatsSection'; import { LoopStatsSection } from './StatsTab/LoopStatsSection'; +import { DisciplineStatsSection } from './StatsTab/DisciplineStatsSection'; export function StatsTab() { const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); @@ -15,6 +17,7 @@ export function StatsTab() { const manaStats = useManaStats(); const combatStats = useCombatStats(); const studyStats = useStudyStats(); + const disciplineEffects = computeDisciplineEffects(); // Compute element max (base + prestige only) const elemMax = 10 + (prestigeUpgrades.elementalAttune || 0) * 25; @@ -37,6 +40,9 @@ export function StatsTab() { studySpeedMult={studyStats.studySpeedMult} studyCostMult={studyStats.studyCostMult} /> + diff --git a/src/components/game/tabs/StatsTab/DisciplineStatsSection.tsx b/src/components/game/tabs/StatsTab/DisciplineStatsSection.tsx new file mode 100644 index 0000000..82d8776 --- /dev/null +++ b/src/components/game/tabs/StatsTab/DisciplineStatsSection.tsx @@ -0,0 +1,72 @@ +'use client'; + +import { useMemo } from 'react'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Brain } from 'lucide-react'; +import { useDisciplineStore } from '@/lib/game/stores/discipline-slice'; +import type { DisciplineEffectsResult } from '@/lib/game/effects/discipline-effects'; +import { ALL_DISCIPLINES } from '@/lib/game/data/disciplines'; +import { getUnlockedPerks } from '@/lib/game/utils/discipline-math'; + +interface DisciplineStatsSectionProps { + disciplineEffects: DisciplineEffectsResult; +} + +export function DisciplineStatsSection({ disciplineEffects }: DisciplineStatsSectionProps) { + const disciplines = useDisciplineStore((s) => s.disciplines); + const activeIds = useDisciplineStore((s) => s.activeIds); + + const disciplineEntries = useMemo(() => { + return ALL_DISCIPLINES.map((def) => { + const state = disciplines[def.id] ?? { xp: 0, paused: true }; + const unlockedPerks = getUnlockedPerks(def, state.xp); + return { def, state, unlockedPerks }; + }).filter(({ def, state }) => state.xp > 0 || activeIds.includes(def.id)); + }, [disciplines, activeIds]); + + if (disciplineEntries.length === 0) return null; + + return ( + + + + + Disciplines + + + +
+ {disciplineEntries.map(({ def, state, unlockedPerks }) => { + const totalEffect = disciplineEffects.bonuses[def.statBonus.stat] ?? 0; + + return ( +
+
+ {def.name} + + {activeIds.includes(def.id) ? 'Active' : 'Paused'} • {state.xp} XP + +
+ {totalEffect > 0 && ( +
+ Effect: +{totalEffect.toFixed(2)} {def.statBonus.label} +
+ )} + {unlockedPerks.length > 0 && ( +
+ Perks: +
    + {unlockedPerks.map((perk) => ( +
  • • {perk.description}
  • + ))} +
+
+ )} +
+ ); + })} +
+
+
+ ); +}