feat: add DebugName wrappers to 56 components + redesign attunement cards + remove ScrollArea from AttunementsTab
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m31s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m31s
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Circular Dependencies
|
# Circular Dependencies
|
||||||
Generated: 2026-05-28T11:15:20.183Z
|
Generated: 2026-05-28T11:45:27.810Z
|
||||||
|
|
||||||
No circular dependencies found. ✅
|
No circular dependencies found. ✅
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"generated": "2026-05-28T11:15:18.333Z",
|
"generated": "2026-05-28T11:45:26.075Z",
|
||||||
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
|
"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."
|
"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."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { useGameLoop } from '@/lib/game/stores/gameHooks';
|
|||||||
import { getUnifiedEffects } from '@/lib/game/effects';
|
import { getUnifiedEffects } from '@/lib/game/effects';
|
||||||
import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects';
|
import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects';
|
||||||
import { TimeDisplay } from '@/components/game';
|
import { TimeDisplay } from '@/components/game';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
import { TooltipProvider } from '@/components/ui/tooltip';
|
import { TooltipProvider } from '@/components/ui/tooltip';
|
||||||
@@ -197,6 +198,7 @@ export default function ManaLoopGame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="HomePage">
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<div className="game-root min-h-screen flex flex-col">
|
<div className="game-root min-h-screen flex flex-col">
|
||||||
@@ -235,5 +237,6 @@ export default function ManaLoopGame() {
|
|||||||
</div>
|
</div>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Sparkles, Swords, BookOpen, Target, FlaskConical, Cog, Hammer, Dumbbell } from 'lucide-react';
|
import { Sparkles, Swords, BookOpen, Target, FlaskConical, Cog, Hammer, Dumbbell } from 'lucide-react';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import type { GameAction } from '@/lib/game/types';
|
import type { GameAction } from '@/lib/game/types';
|
||||||
|
|
||||||
interface ActionButtonsProps {
|
interface ActionButtonsProps {
|
||||||
@@ -119,33 +120,35 @@ export function ActionButtons({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<DebugName name="ActionButtons">
|
||||||
<div className="bg-gray-800/50 rounded-lg p-3 border border-gray-700">
|
<div className="space-y-2">
|
||||||
<div className="flex items-center gap-2">
|
<div className="bg-gray-800/50 rounded-lg p-3 border border-gray-700">
|
||||||
<Icon className={`w-4 h-4 ${config.color}`} />
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-sm font-medium text-gray-200">Current Activity</span>
|
<Icon className={`w-4 h-4 ${config.color}`} />
|
||||||
</div>
|
<span className="text-sm font-medium text-gray-200">Current Activity</span>
|
||||||
<div className={`text-lg font-semibold mt-1 ${config.color}`}>
|
|
||||||
{config.label}
|
|
||||||
</div>
|
|
||||||
{getActionDetails()}
|
|
||||||
|
|
||||||
{/* Show second design slot if active */}
|
|
||||||
{designProgress2 && (
|
|
||||||
<div className="mt-2 pt-2 border-t border-gray-700">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Target className="w-3 h-3 text-purple-400" />
|
|
||||||
<span className="text-xs text-gray-400">Second Design Slot</span>
|
|
||||||
</div>
|
|
||||||
<ProgressBar
|
|
||||||
progress={designProgress2.progress}
|
|
||||||
required={designProgress2.required}
|
|
||||||
label="Design progress"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className={`text-lg font-semibold mt-1 ${config.color}`}>
|
||||||
|
{config.label}
|
||||||
|
</div>
|
||||||
|
{getActionDetails()}
|
||||||
|
|
||||||
|
{/* Show second design slot if active */}
|
||||||
|
{designProgress2 && (
|
||||||
|
<div className="mt-2 pt-2 border-t border-gray-700">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Target className="w-3 h-3 text-purple-400" />
|
||||||
|
<span className="text-xs text-gray-400">Second Design Slot</span>
|
||||||
|
</div>
|
||||||
|
<ProgressBar
|
||||||
|
progress={designProgress2.progress}
|
||||||
|
required={designProgress2.required}
|
||||||
|
label="Design progress"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCombatStore } from '@/lib/game/stores';
|
import { useCombatStore } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { ActivityLog } from './tabs/ActivityLog';
|
import { ActivityLog } from './tabs/ActivityLog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +13,9 @@ export function ActivityLogPanel() {
|
|||||||
const activityLog = useCombatStore((s) => s.activityLog);
|
const activityLog = useCombatStore((s) => s.activityLog);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActivityLog activityLog={activityLog} maxEntries={20} />
|
<DebugName name="ActivityLogPanel">
|
||||||
|
<ActivityLog activityLog={activityLog} maxEntries={20} />
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { useAttunementStore } from '@/lib/game/stores';
|
import { useAttunementStore } from '@/lib/game/stores';
|
||||||
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
|
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
@@ -38,70 +39,72 @@ export function AttunementStatus() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1">
|
<DebugName name="AttunementStatus">
|
||||||
<div className="flex items-center justify-between">
|
<div className="space-y-1">
|
||||||
<span className="text-[10px] uppercase tracking-wider text-[var(--text-muted)] font-bold">Attunements</span>
|
<div className="flex items-center justify-between">
|
||||||
<span className="text-[10px] text-[var(--text-muted)]">{activeAttunements.length} active</span>
|
<span className="text-[10px] uppercase tracking-wider text-[var(--text-muted)] font-bold">Attunements</span>
|
||||||
</div>
|
<span className="text-[10px] text-[var(--text-muted)]">{activeAttunements.length} active</span>
|
||||||
<Separator className="bg-[var(--border-subtle)]" />
|
</div>
|
||||||
<div className="space-y-1.5">
|
<Separator className="bg-[var(--border-subtle)]" />
|
||||||
{activeAttunements.length === 0 ? (
|
<div className="space-y-1.5">
|
||||||
<div className="text-[10px] text-[var(--text-muted)] italic">No attunements active</div>
|
{activeAttunements.length === 0 ? (
|
||||||
) : (
|
<div className="text-[10px] text-[var(--text-muted)] italic">No attunements active</div>
|
||||||
activeAttunements.map(([id, state]) => {
|
) : (
|
||||||
const def = ATTUNEMENTS_DEF[id];
|
activeAttunements.map(([id, state]) => {
|
||||||
if (!def) return null;
|
const def = ATTUNEMENTS_DEF[id];
|
||||||
const nextXp = xpForNext(state.level);
|
if (!def) return null;
|
||||||
const xpProgress = nextXp > 0 ? (state.experience / nextXp) * 100 : 0;
|
const nextXp = xpForNext(state.level);
|
||||||
|
const xpProgress = nextXp > 0 ? (state.experience / nextXp) * 100 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider key={id}>
|
<TooltipProvider key={id}>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<div className="flex items-center gap-2 p-1.5 rounded bg-[var(--bg-sunken)]/50 border border-[var(--border-subtle)]">
|
<div className="flex items-center gap-2 p-1.5 rounded bg-[var(--bg-sunken)]/50 border border-[var(--border-subtle)]">
|
||||||
<span className="text-sm">{def.icon}</span>
|
<span className="text-sm">{def.icon}</span>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="text-[11px] font-medium text-[var(--text-primary)] truncate">
|
<span className="text-[11px] font-medium text-[var(--text-primary)] truncate">
|
||||||
{def.name}
|
{def.name}
|
||||||
</span>
|
|
||||||
<span className="text-[10px] text-[var(--text-secondary)] font-mono">
|
|
||||||
Lv.{state.level}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="text-[10px] text-[var(--text-muted)]">
|
|
||||||
<span className="capitalize">{SLOT_LABELS[def.slot] || def.slot}</span>
|
|
||||||
{nextXp > 0 && (
|
|
||||||
<span className="ml-1.5 font-mono">
|
|
||||||
{Math.floor(state.experience).toLocaleString()}/{nextXp.toLocaleString()} XP
|
|
||||||
</span>
|
</span>
|
||||||
|
<span className="text-[10px] text-[var(--text-secondary)] font-mono">
|
||||||
|
Lv.{state.level}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-[10px] text-[var(--text-muted)]">
|
||||||
|
<span className="capitalize">{SLOT_LABELS[def.slot] || def.slot}</span>
|
||||||
|
{nextXp > 0 && (
|
||||||
|
<span className="ml-1.5 font-mono">
|
||||||
|
{Math.floor(state.experience).toLocaleString()}/{nextXp.toLocaleString()} XP
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{nextXp > 0 && (
|
||||||
|
<div className="w-full h-0.5 bg-[var(--border-subtle)] rounded-full mt-0.5 overflow-hidden">
|
||||||
|
<div
|
||||||
|
className="h-full transition-all duration-500"
|
||||||
|
style={{
|
||||||
|
width: `${Math.min(100, xpProgress)}%`,
|
||||||
|
backgroundColor: def.color,
|
||||||
|
opacity: 0.7,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{nextXp > 0 && (
|
|
||||||
<div className="w-full h-0.5 bg-[var(--border-subtle)] rounded-full mt-0.5 overflow-hidden">
|
|
||||||
<div
|
|
||||||
className="h-full transition-all duration-500"
|
|
||||||
style={{
|
|
||||||
width: `${Math.min(100, xpProgress)}%`,
|
|
||||||
backgroundColor: def.color,
|
|
||||||
opacity: 0.7,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</TooltipTrigger>
|
||||||
</TooltipTrigger>
|
<TooltipContent side="right">
|
||||||
<TooltipContent side="right">
|
<p className="text-xs max-w-[220px]">{def.desc}</p>
|
||||||
<p className="text-xs max-w-[220px]">{def.desc}</p>
|
</TooltipContent>
|
||||||
</TooltipContent>
|
</Tooltip>
|
||||||
</Tooltip>
|
</TooltipProvider>
|
||||||
</TooltipProvider>
|
);
|
||||||
);
|
})
|
||||||
})
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import {
|
import {
|
||||||
Toast,
|
Toast,
|
||||||
ToastClose,
|
ToastClose,
|
||||||
@@ -61,8 +62,9 @@ export function GameToaster() {
|
|||||||
const { toasts } = useToast();
|
const { toasts } = useToast();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToastProvider>
|
<DebugName name="GameToast">
|
||||||
{toasts.map((toast) => {
|
<ToastProvider>
|
||||||
|
{toasts.map((toast) => {
|
||||||
// Determine toast type from className or default to info
|
// Determine toast type from className or default to info
|
||||||
const toastType: ToastType =
|
const toastType: ToastType =
|
||||||
toast.variant === 'destructive' ? 'error' :
|
toast.variant === 'destructive' ? 'error' :
|
||||||
@@ -103,16 +105,17 @@ export function GameToaster() {
|
|||||||
- Desktop: bottom-right
|
- Desktop: bottom-right
|
||||||
- Mobile: bottom-center, full-width
|
- Mobile: bottom-center, full-width
|
||||||
*/}
|
*/}
|
||||||
<ToastViewport
|
<ToastViewport
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed z-[100] flex max-h-screen w-full flex-col-reverse p-4',
|
'fixed z-[100] flex max-h-screen w-full flex-col-reverse p-4',
|
||||||
// Desktop: bottom-right, fixed width
|
// Desktop: bottom-right, fixed width
|
||||||
'sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col sm:max-w-[420px]',
|
'sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col sm:max-w-[420px]',
|
||||||
// Mobile: bottom-center, full-width
|
// Mobile: bottom-center, full-width
|
||||||
'max-sm:bottom-0 max-sm:left-0 max-sm:flex-col max-sm:items-center'
|
'max-sm:bottom-0 max-sm:left-0 max-sm:flex-col max-sm:items-center'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Scroll } from 'lucide-react';
|
import { Scroll } from 'lucide-react';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { LOOT_DROPS } from '@/lib/game/data/loot-drops';
|
import { LOOT_DROPS } from '@/lib/game/data/loot-drops';
|
||||||
@@ -13,6 +14,7 @@ export function BlueprintsSection({ blueprints }: BlueprintsSectionProps) {
|
|||||||
if (blueprints.length === 0) return null;
|
if (blueprints.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="BlueprintsSection">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-xs text-[var(--text-muted)] mb-2 flex items-center gap-1">
|
<div className="text-xs text-[var(--text-muted)] mb-2 flex items-center gap-1">
|
||||||
<Scroll className="w-3 h-3" />
|
<Scroll className="w-3 h-3" />
|
||||||
@@ -42,5 +44,6 @@ export function BlueprintsSection({ blueprints }: BlueprintsSectionProps) {
|
|||||||
Blueprints are permanent unlocks - use them to craft equipment
|
Blueprints are permanent unlocks - use them to craft equipment
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Package, Trash2 } from 'lucide-react';
|
import { Package, Trash2 } from 'lucide-react';
|
||||||
import type { EquipmentInstance } from '@/lib/game/types';
|
import type { EquipmentInstance } from '@/lib/game/types';
|
||||||
import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
|
import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
|
||||||
@@ -20,6 +21,7 @@ export function EquipmentItem({ instanceId, instance, onDelete }: EquipmentItemP
|
|||||||
const rarityGlow = RARITY_GLOW_CSS_VAR[instance.rarity] || 'var(--rarity-common-glow)';
|
const rarityGlow = RARITY_GLOW_CSS_VAR[instance.rarity] || 'var(--rarity-common-glow)';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EquipmentItem">
|
||||||
<div
|
<div
|
||||||
className="p-2 rounded border bg-[var(--bg-sunken)] group"
|
className="p-2 rounded border bg-[var(--bg-sunken)] group"
|
||||||
style={{
|
style={{
|
||||||
@@ -55,6 +57,7 @@ export function EquipmentItem({ instanceId, instance, onDelete }: EquipmentItemP
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Droplet } from 'lucide-react';
|
import { Droplet } from 'lucide-react';
|
||||||
import { ElementBadge } from '@/components/ui/element-badge';
|
import { ElementBadge } from '@/components/ui/element-badge';
|
||||||
import type { ElementState } from '@/lib/game/types';
|
import type { ElementState } from '@/lib/game/types';
|
||||||
@@ -15,6 +16,7 @@ export function EssenceItem({ elementId, state }: EssenceItemProps) {
|
|||||||
if (!elem) return null;
|
if (!elem) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EssenceItem">
|
||||||
<div
|
<div
|
||||||
className="p-2 rounded border bg-[var(--bg-sunken)]"
|
className="p-2 rounded border bg-[var(--bg-sunken)]"
|
||||||
style={{
|
style={{
|
||||||
@@ -29,6 +31,7 @@ export function EssenceItem({ elementId, state }: EssenceItemProps) {
|
|||||||
{state.current} / {state.max}
|
{state.current} / {state.max}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import type { LootInventory } from '@/lib/game/types';
|
import type { LootInventory } from '@/lib/game/types';
|
||||||
// For backward compatibility
|
// For backward compatibility
|
||||||
type LootInventoryType = LootInventory;
|
type LootInventoryType = LootInventory;
|
||||||
@@ -22,6 +23,7 @@ export function MaterialItem({ materialId, count, onDelete }: MaterialItemProps)
|
|||||||
const rarityGlow = RARITY_GLOW_CSS_VAR[drop.rarity] || 'var(--rarity-common-glow)';
|
const rarityGlow = RARITY_GLOW_CSS_VAR[drop.rarity] || 'var(--rarity-common-glow)';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="MaterialItem">
|
||||||
<div
|
<div
|
||||||
className="p-2 rounded border bg-[var(--bg-sunken)] group relative"
|
className="p-2 rounded border bg-[var(--bg-sunken)] group relative"
|
||||||
style={{
|
style={{
|
||||||
@@ -54,6 +56,7 @@ export function MaterialItem({ materialId, count, onDelete }: MaterialItemProps)
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Zap, ChevronDown, ChevronUp } from 'lucide-react';
|
|||||||
import { fmt, fmtDec } from '@/lib/game/stores';
|
import { fmt, fmtDec } from '@/lib/game/stores';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface ManaDisplayProps {
|
interface ManaDisplayProps {
|
||||||
rawMana: number;
|
rawMana: number;
|
||||||
@@ -39,8 +40,9 @@ export function ManaDisplay({
|
|||||||
.sort((a, b) => b[1].current - a[1].current);
|
.sort((a, b) => b[1].current - a[1].current);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<DebugName name="ManaDisplay">
|
||||||
<CardContent className="pt-4 space-y-3">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
|
<CardContent className="pt-4 space-y-3">
|
||||||
{/* Raw Mana - Main Display */}
|
{/* Raw Mana - Main Display */}
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-baseline gap-1">
|
<div className="flex items-baseline gap-1">
|
||||||
@@ -133,8 +135,9 @@ export function ManaDisplay({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { formatHour } from '@/lib/game/utils/formatting';
|
import { formatHour } from '@/lib/game/utils/formatting';
|
||||||
|
|
||||||
interface TimeDisplayProps {
|
interface TimeDisplayProps {
|
||||||
@@ -15,23 +16,25 @@ export function TimeDisplay({
|
|||||||
insight,
|
insight,
|
||||||
}: TimeDisplayProps) {
|
}: TimeDisplayProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-4">
|
<DebugName name="TimeDisplay">
|
||||||
<div className="text-center">
|
<div className="flex items-center gap-4">
|
||||||
<div className="text-lg font-bold game-mono text-amber-400">
|
<div className="text-center">
|
||||||
Day {day}
|
<div className="text-lg font-bold game-mono text-amber-400">
|
||||||
|
Day {day}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-gray-400">
|
||||||
|
{formatHour(hour)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-gray-400">
|
|
||||||
{formatHour(hour)}
|
<div className="text-center">
|
||||||
|
<div className="text-lg font-bold game-mono text-purple-400">
|
||||||
|
{fmt(insight)}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-gray-400">Insight</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
<div className="text-center">
|
|
||||||
<div className="text-lg font-bold game-mono text-purple-400">
|
|
||||||
{fmt(insight)}
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-gray-400">Insight</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { SkillUpgradeChoice } from '@/lib/game/types';
|
import type { SkillUpgradeChoice } from '@/lib/game/types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
||||||
@@ -35,8 +36,9 @@ export function UpgradeDialog({
|
|||||||
const currentSelections = pendingSelections.length > 0 ? pendingSelections : alreadySelected;
|
const currentSelections = pendingSelections.length > 0 ? pendingSelections : alreadySelected;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<DebugName name="UpgradeDialog">
|
||||||
<DialogContent className="bg-gray-900 border-gray-700 max-w-lg">
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="bg-gray-900 border-gray-700 max-w-lg">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="text-amber-400">
|
<DialogTitle className="text-amber-400">
|
||||||
Choose Upgrade - {skillId}
|
Choose Upgrade - {skillId}
|
||||||
@@ -107,8 +109,9 @@ export function UpgradeDialog({
|
|||||||
{currentSelections.length < 2 ? `Select ${2 - currentSelections.length} more` : 'Confirm'}
|
{currentSelections.length < 2 ? `Select ${2 - currentSelections.length} more` : 'Confirm'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import type { EquipmentSlot } from '@/lib/game/data/equipment';
|
|||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
import { CheckCircle, Sparkles } from 'lucide-react';
|
import { CheckCircle, Sparkles } from 'lucide-react';
|
||||||
import { useCraftingStore, useManaStore } from '@/lib/game/stores';
|
import { useCraftingStore, useManaStore } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export interface EnchantmentApplierProps {
|
export interface EnchantmentApplierProps {
|
||||||
selectedEquipmentInstance: string | null;
|
selectedEquipmentInstance: string | null;
|
||||||
@@ -51,23 +52,24 @@ export function EnchantmentApplier({
|
|||||||
// Handle apply button click
|
// Handle apply button click
|
||||||
const handleApply = () => {
|
const handleApply = () => {
|
||||||
if (!selectedEquipmentInstance || !selectedDesign) return;
|
if (!selectedEquipmentInstance || !selectedDesign) return;
|
||||||
|
|
||||||
const instance = equipmentInstances[selectedEquipmentInstance];
|
const instance = equipmentInstances[selectedEquipmentInstance];
|
||||||
const design = enchantmentDesigns.find(d => d.id === selectedDesign);
|
const design = enchantmentDesigns.find(d => d.id === selectedDesign);
|
||||||
|
|
||||||
if (!instance || !design) return;
|
if (!instance || !design) return;
|
||||||
|
|
||||||
// Check capacity
|
// Check capacity
|
||||||
const availableCap = instance.totalCapacity - instance.usedCapacity;
|
const availableCap = instance.totalCapacity - instance.usedCapacity;
|
||||||
if (availableCap < design.totalCapacityUsed) {
|
if (availableCap < design.totalCapacityUsed) {
|
||||||
onCapacityExceeded?.(instance.name, instance.usedCapacity, instance.totalCapacity);
|
onCapacityExceeded?.(instance.name, instance.usedCapacity, instance.totalCapacity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
startApplying(selectedEquipmentInstance, selectedDesign);
|
startApplying(selectedEquipmentInstance, selectedDesign);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EnchantmentApplier">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
{/* Equipment & Design Selection */}
|
{/* Equipment & Design Selection */}
|
||||||
<GameCard variant="default">
|
<GameCard variant="default">
|
||||||
@@ -217,7 +219,7 @@ export function EnchantmentApplier({
|
|||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="text-lg font-semibold text-[var(--text-primary)]">{design.name}</div>
|
<div className="text-lg font-semibold text-[var(--text-primary)]">{design.name}</div>
|
||||||
<div className="text-sm text-[var(--text-secondary)]">→ {instance.name}</div>
|
<div className="text-sm text-[var(--text-secondary)]">{instance.name}</div>
|
||||||
<div className="text-xs text-[var(--color-success)]">
|
<div className="text-xs text-[var(--color-success)]">
|
||||||
<CheckCircle size={12} className="inline mr-1" />
|
<CheckCircle size={12} className="inline mr-1" />
|
||||||
Ready for Enchantment
|
Ready for Enchantment
|
||||||
@@ -271,6 +273,7 @@ export function EnchantmentApplier({
|
|||||||
)}
|
)}
|
||||||
</GameCard>
|
</GameCard>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
removeEffectFromDesign,
|
removeEffectFromDesign,
|
||||||
} from './EnchantmentDesigner/utils';
|
} from './EnchantmentDesigner/utils';
|
||||||
import { useCraftingStore } from '@/lib/game/stores';
|
import { useCraftingStore } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function EnchantmentDesigner({
|
export function EnchantmentDesigner({
|
||||||
selectedEquipmentType,
|
selectedEquipmentType,
|
||||||
@@ -88,6 +89,7 @@ export function EnchantmentDesigner({
|
|||||||
|
|
||||||
// Render stage
|
// Render stage
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EnchantmentDesigner">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
{/* Equipment Type Selection */}
|
{/* Equipment Type Selection */}
|
||||||
<EquipmentTypeSelector
|
<EquipmentTypeSelector
|
||||||
@@ -141,6 +143,7 @@ export function EnchantmentDesigner({
|
|||||||
deleteDesign={deleteDesign}
|
deleteDesign={deleteDesign}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { ActionButton } from '@/components/ui/action-button';
|
import { ActionButton } from '@/components/ui/action-button';
|
||||||
import { StatRow } from '@/components/ui/stat-row';
|
import { StatRow } from '@/components/ui/stat-row';
|
||||||
import type { DesignFormProps } from './types';
|
import type { DesignFormProps } from './types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function DesignForm({
|
export function DesignForm({
|
||||||
designName,
|
designName,
|
||||||
@@ -15,6 +16,7 @@ export function DesignForm({
|
|||||||
handleCreateDesign,
|
handleCreateDesign,
|
||||||
}: DesignFormProps) {
|
}: DesignFormProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="DesignForm">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -45,6 +47,7 @@ export function DesignForm({
|
|||||||
{isOverCapacity ? 'Over Capacity!' : `Start Design (${designTime.toFixed(1)}h)`}
|
{isOverCapacity ? 'Over Capacity!' : `Start Design (${designTime.toFixed(1)}h)`}
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
|
|||||||
import { AlertCircle, Wand2, Plus, Minus } from 'lucide-react';
|
import { AlertCircle, Wand2, Plus, Minus } from 'lucide-react';
|
||||||
import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from '@/lib/game/data/enchantment-effects';
|
import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from '@/lib/game/data/enchantment-effects';
|
||||||
import type { EffectSelectorProps } from './types';
|
import type { EffectSelectorProps } from './types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function EffectSelector({
|
export function EffectSelector({
|
||||||
selectedEquipmentType,
|
selectedEquipmentType,
|
||||||
@@ -22,6 +23,7 @@ export function EffectSelector({
|
|||||||
getIncompatibilityReason,
|
getIncompatibilityReason,
|
||||||
}: EffectSelectorProps) {
|
}: EffectSelectorProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EffectSelector">
|
||||||
<>
|
<>
|
||||||
{enchantingLevel < 1 ? (
|
{enchantingLevel < 1 ? (
|
||||||
<div className="text-center text-[var(--text-muted)] py-8">
|
<div className="text-center text-[var(--text-muted)] py-8">
|
||||||
@@ -84,7 +86,7 @@ export function EffectSelector({
|
|||||||
)}
|
)}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="h-6 w-6 p-0"
|
className="h-6 w-6 p-0"
|
||||||
onClick={() => addEffect(effect.id)}
|
onClick={() => addEffect(effect.id)}
|
||||||
disabled={!selected && selectedEffects.length >= 5}
|
disabled={!selected && selectedEffects.length >= 5}
|
||||||
@@ -143,6 +145,7 @@ export function EffectSelector({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ActionButton } from '@/components/ui/action-button';
|
|||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import type { EquipmentTypeSelectorProps } from './types';
|
import type { EquipmentTypeSelectorProps } from './types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function EquipmentTypeSelector({
|
export function EquipmentTypeSelector({
|
||||||
ownedEquipmentTypes,
|
ownedEquipmentTypes,
|
||||||
@@ -15,6 +16,7 @@ export function EquipmentTypeSelector({
|
|||||||
cancelDesign,
|
cancelDesign,
|
||||||
}: EquipmentTypeSelectorProps) {
|
}: EquipmentTypeSelectorProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EquipmentTypeSelector">
|
||||||
<GameCard variant="default">
|
<GameCard variant="default">
|
||||||
<SectionHeader title="1. Select Equipment Type" />
|
<SectionHeader title="1. Select Equipment Type" />
|
||||||
{designProgress ? (
|
{designProgress ? (
|
||||||
@@ -61,6 +63,7 @@ export function EquipmentTypeSelector({
|
|||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
)}
|
)}
|
||||||
</GameCard>
|
</GameCard>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ActionButton } from '@/components/ui/action-button';
|
|||||||
import { Trash2 } from 'lucide-react';
|
import { Trash2 } from 'lucide-react';
|
||||||
import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
|
import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
|
||||||
import type { SavedDesignsProps } from './types';
|
import type { SavedDesignsProps } from './types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function SavedDesigns({
|
export function SavedDesigns({
|
||||||
enchantmentDesigns,
|
enchantmentDesigns,
|
||||||
@@ -14,6 +15,7 @@ export function SavedDesigns({
|
|||||||
deleteDesign,
|
deleteDesign,
|
||||||
}: SavedDesignsProps) {
|
}: SavedDesignsProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="SavedDesigns">
|
||||||
<GameCard variant="default" className="lg:col-span-2">
|
<GameCard variant="default" className="lg:col-span-2">
|
||||||
<SectionHeader title={`Saved Designs (${enchantmentDesigns.length})`} />
|
<SectionHeader title={`Saved Designs (${enchantmentDesigns.length})`} />
|
||||||
{enchantmentDesigns.length === 0 ? (
|
{enchantmentDesigns.length === 0 ? (
|
||||||
@@ -63,6 +65,7 @@ export function SavedDesigns({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</GameCard>
|
</GameCard>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import type { EquipmentSlot } from '@/lib/game/types';
|
|||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
import { useCraftingStore, useManaStore } from '@/lib/game/stores';
|
import { useCraftingStore, useManaStore } from '@/lib/game/stores';
|
||||||
import { useGameToast } from '@/components/game/GameToast';
|
import { useGameToast } from '@/components/game/GameToast';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export interface EnchantmentPreparerProps {
|
export interface EnchantmentPreparerProps {
|
||||||
selectedEquipmentInstance: string | null;
|
selectedEquipmentInstance: string | null;
|
||||||
@@ -72,6 +73,7 @@ export function EnchantmentPreparer({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EnchantmentPreparer">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
{/* Equipment Selection */}
|
{/* Equipment Selection */}
|
||||||
<GameCard variant="default">
|
<GameCard variant="default">
|
||||||
@@ -296,6 +298,7 @@ export function EnchantmentPreparer({
|
|||||||
)}
|
)}
|
||||||
</GameCard>
|
</GameCard>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
|
|||||||
import type { LootInventory } from '@/lib/game/types';
|
import type { LootInventory } from '@/lib/game/types';
|
||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
import { useCraftingStore, useCombatStore, useManaStore } from '@/lib/game/stores';
|
import { useCraftingStore, useCombatStore, useManaStore } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
// ─── Crafting Progress ───────────────────────────────────────────────────────
|
// ─── Crafting Progress ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -222,6 +223,7 @@ export function EquipmentCrafter() {
|
|||||||
const currentAction = useCombatStore((s) => s.currentAction);
|
const currentAction = useCombatStore((s) => s.currentAction);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EquipmentCrafter">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
@@ -241,6 +243,7 @@ export function EquipmentCrafter() {
|
|||||||
|
|
||||||
<MaterialsInventory materials={lootInventory.materials} deleteMaterial={deleteMaterial} />
|
<MaterialsInventory materials={lootInventory.materials} deleteMaterial={deleteMaterial} />
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Sparkles, Unlock } from 'lucide-react';
|
import { Sparkles, Unlock } from 'lucide-react';
|
||||||
@@ -30,6 +31,7 @@ export function AttunementDebug() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="AttunementDebug">
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-purple-400 text-sm flex items-center gap-2">
|
<CardTitle className="text-purple-400 text-sm flex items-center gap-2">
|
||||||
@@ -75,6 +77,7 @@ export function AttunementDebug() {
|
|||||||
})}
|
})}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Star, Lock } from 'lucide-react';
|
import { Star, Lock } from 'lucide-react';
|
||||||
@@ -21,6 +22,7 @@ export function ElementDebug() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="ElementDebug">
|
||||||
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
|
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-green-400 text-sm flex items-center gap-2">
|
<CardTitle className="text-green-400 text-sm flex items-center gap-2">
|
||||||
@@ -73,6 +75,7 @@ export function ElementDebug() {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import {
|
import {
|
||||||
RotateCcw, AlertTriangle, Zap, Clock, Settings, Eye,
|
RotateCcw, AlertTriangle, Zap, Clock, Settings, Eye,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useDebug } from '@/components/game/debug/debug-context';
|
import { DebugName, useDebug } from '@/components/game/debug/debug-context';
|
||||||
import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores';
|
import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores';
|
||||||
import { computeMaxMana } from '@/lib/game/stores';
|
import { computeMaxMana } from '@/lib/game/stores';
|
||||||
|
|
||||||
@@ -282,6 +282,7 @@ export function GameStateDebug() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="GameStateDebug">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<WarningBanner />
|
<WarningBanner />
|
||||||
<DisplayOptions />
|
<DisplayOptions />
|
||||||
@@ -298,6 +299,7 @@ export function GameStateDebug() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Bug } from 'lucide-react';
|
import { Bug } from 'lucide-react';
|
||||||
|
|
||||||
export function GolemDebug() {
|
export function GolemDebug() {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="GolemDebug">
|
||||||
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
|
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
||||||
@@ -18,6 +20,7 @@ export function GolemDebug() {
|
|||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Bug } from 'lucide-react';
|
import { Bug } from 'lucide-react';
|
||||||
@@ -140,6 +141,7 @@ export function PactDebug() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="PactDebug">
|
||||||
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
|
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
||||||
@@ -174,6 +176,7 @@ export function PactDebug() {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { ActivityLogEntry } from '@/lib/game/types';
|
import type { ActivityLogEntry } from '@/lib/game/types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface ActivityLogProps {
|
interface ActivityLogProps {
|
||||||
activityLog: ActivityLogEntry[];
|
activityLog: ActivityLogEntry[];
|
||||||
@@ -10,14 +11,17 @@ export function ActivityLog({ activityLog, maxEntries = 20 }: ActivityLogProps)
|
|||||||
|
|
||||||
if (entries.length === 0) {
|
if (entries.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="text-sm text-gray-500 italic p-2">
|
<DebugName name="ActivityLog">
|
||||||
No activity yet.
|
<div className="text-sm text-gray-500 italic p-2">
|
||||||
</div>
|
No activity yet.
|
||||||
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1 max-h-64 overflow-y-auto">
|
<DebugName name="ActivityLog">
|
||||||
|
<div className="space-y-1 max-h-64 overflow-y-auto">
|
||||||
{entries.map((entry) => (
|
{entries.map((entry) => (
|
||||||
<div
|
<div
|
||||||
key={entry.id}
|
key={entry.id}
|
||||||
@@ -29,6 +33,7 @@ export function ActivityLog({ activityLog, maxEntries = 20 }: ActivityLogProps)
|
|||||||
{entry.message}
|
{entry.message}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import type { AttunementDef, AttunementState } from '@/lib/game/types';
|
|||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
||||||
import { DebugName } from '@/components/game/debug/debug-context';
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
|
|
||||||
@@ -36,36 +35,83 @@ interface AttunementCardProps {
|
|||||||
|
|
||||||
function AttunementCard({ def, state }: AttunementCardProps) {
|
function AttunementCard({ def, state }: AttunementCardProps) {
|
||||||
const unlocked = !!state;
|
const unlocked = !!state;
|
||||||
|
const isStarting = def.unlocked === true;
|
||||||
const xpProgress = state ? getXpProgress(state) : 0;
|
const xpProgress = state ? getXpProgress(state) : 0;
|
||||||
const nextXp = state ? getXpForNextLevel(state.level) : 0;
|
const nextXp = state ? getXpForNextLevel(state.level) : 0;
|
||||||
|
|
||||||
|
// Style tokens derived from def.color
|
||||||
|
const color = def.color;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={`bg-gray-900/60 ${unlocked ? 'border-gray-700' : 'border-gray-800 opacity-60'}`}>
|
<Card
|
||||||
<CardContent className="p-4 space-y-3">
|
className={`relative overflow-hidden ${
|
||||||
|
unlocked
|
||||||
|
? 'bg-gray-900/60'
|
||||||
|
: 'bg-gray-950/80'
|
||||||
|
}`}
|
||||||
|
style={{
|
||||||
|
borderLeft: `3px solid ${unlocked ? color : `${color}33`}`,
|
||||||
|
borderColor: unlocked ? `${color}88` : `${color}22`,
|
||||||
|
opacity: unlocked ? 1 : 0.55,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Starting badge (top-right ribbon) */}
|
||||||
|
{isStarting && unlocked && (
|
||||||
|
<div
|
||||||
|
className="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full"
|
||||||
|
style={{ backgroundColor: `${color}22`, color }}
|
||||||
|
>
|
||||||
|
Starting
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Locked overlay pattern */}
|
||||||
|
{!unlocked && (
|
||||||
|
<div className="absolute inset-0 pointer-events-none" style={{ background: `repeating-linear-gradient(45deg, transparent, transparent 12px, ${color}08 12px, ${color}08 24px)` }} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<CardContent className="p-4 space-y-3 relative">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2.5">
|
||||||
<span className="text-xl">{def.icon}</span>
|
<span
|
||||||
|
className="text-xl p-1 rounded"
|
||||||
|
style={{ backgroundColor: `${color}18` }}
|
||||||
|
>
|
||||||
|
{def.icon}
|
||||||
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-medium text-gray-100">{def.name}</h3>
|
<h3
|
||||||
|
className="font-semibold"
|
||||||
|
style={{ color: unlocked ? color : `${color}99` }}
|
||||||
|
>
|
||||||
|
{def.name}
|
||||||
|
</h3>
|
||||||
<p className="text-xs text-gray-500">
|
<p className="text-xs text-gray-500">
|
||||||
{ATTUNEMENT_SLOT_NAMES[def.slot] ?? def.slot}
|
{ATTUNEMENT_SLOT_NAMES[def.slot] ?? def.slot}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{unlocked ? (
|
{unlocked ? (
|
||||||
<Badge className="bg-teal-900/50 text-teal-300 text-xs">
|
<Badge
|
||||||
|
className="text-xs font-bold"
|
||||||
|
style={{ backgroundColor: `${color}25`, color, border: `1px solid ${color}44` }}
|
||||||
|
>
|
||||||
Lv.{state.level}
|
Lv.{state.level}
|
||||||
</Badge>
|
</Badge>
|
||||||
) : (
|
) : (
|
||||||
<Badge variant="outline" className="border-gray-700 text-gray-500 text-xs">
|
<Badge
|
||||||
Locked
|
variant="outline"
|
||||||
|
className="text-xs"
|
||||||
|
style={{ borderColor: `${color}44`, color: `${color}88` }}
|
||||||
|
>
|
||||||
|
🔒 Locked
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
<p className="text-xs text-gray-400 leading-relaxed">{def.desc}</p>
|
<p className={`text-xs leading-relaxed ${unlocked ? 'text-gray-400' : 'text-gray-600'}`}>{def.desc}</p>
|
||||||
|
|
||||||
{/* XP Progress (unlocked only) */}
|
{/* XP Progress (unlocked only) */}
|
||||||
{unlocked && state && (
|
{unlocked && state && (
|
||||||
@@ -76,7 +122,12 @@ function AttunementCard({ def, state }: AttunementCardProps) {
|
|||||||
{fmt(state.experience)} / {fmt(nextXp)}
|
{fmt(state.experience)} / {fmt(nextXp)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Progress value={xpProgress} className="h-2" />
|
<div className="h-2 rounded-full overflow-hidden bg-gray-800">
|
||||||
|
<div
|
||||||
|
className="h-full rounded-full transition-all"
|
||||||
|
style={{ width: `${xpProgress}%`, backgroundColor: color }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{state.level >= MAX_ATTUNEMENT_LEVEL && (
|
{state.level >= MAX_ATTUNEMENT_LEVEL && (
|
||||||
<p className="text-xs text-amber-400 italic">Maximum level reached</p>
|
<p className="text-xs text-amber-400 italic">Maximum level reached</p>
|
||||||
)}
|
)}
|
||||||
@@ -85,13 +136,19 @@ function AttunementCard({ def, state }: AttunementCardProps) {
|
|||||||
|
|
||||||
{/* Unlock condition (locked only) */}
|
{/* Unlock condition (locked only) */}
|
||||||
{!unlocked && def.unlockCondition && (
|
{!unlocked && def.unlockCondition && (
|
||||||
<div className="text-xs text-gray-500 italic border-t border-gray-800 pt-2">
|
<div
|
||||||
|
className="text-xs italic pt-2"
|
||||||
|
style={{ color: `${color}77`, borderTop: `1px solid ${color}15` }}
|
||||||
|
>
|
||||||
🔒 {def.unlockCondition}
|
🔒 {def.unlockCondition}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Details grid */}
|
{/* Details grid */}
|
||||||
<div className="grid grid-cols-2 gap-2 text-xs border-t border-gray-800 pt-3">
|
<div
|
||||||
|
className="grid grid-cols-2 gap-2 text-xs pt-3"
|
||||||
|
style={{ borderTop: `1px solid ${unlocked ? `${color}22` : `${color}10`}` }}
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-gray-500">Mana Type</span>
|
<span className="text-gray-500">Mana Type</span>
|
||||||
<p className="text-gray-300 capitalize">
|
<p className="text-gray-300 capitalize">
|
||||||
@@ -110,21 +167,35 @@ function AttunementCard({ def, state }: AttunementCardProps) {
|
|||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<span className="text-gray-500">Status</span>
|
<span className="text-gray-500">Status</span>
|
||||||
<p className={state?.active ? 'text-green-400' : 'text-gray-500'}>
|
<p style={{ color: state?.active ? '#4ade80' : unlocked ? `${color}aa` : '#6b7280' }}>
|
||||||
{state?.active ? 'Active' : unlocked ? 'Inactive' : 'Locked'}
|
{state?.active ? '● Active' : unlocked ? '○ Inactive' : 'Locked'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Invoker special: pact-based note */}
|
||||||
|
{def.primaryManaType === undefined && (
|
||||||
|
<div className="col-span-2">
|
||||||
|
<span className="text-gray-500">Special</span>
|
||||||
|
<p style={{ color: `${color}cc` }}>
|
||||||
|
Gains elemental mana from each guardian pact signed
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Capabilities */}
|
{/* Capabilities */}
|
||||||
<div className="border-t border-gray-800 pt-3">
|
<div style={{ borderTop: `1px solid ${unlocked ? `${color}22` : `${color}10`}` }} className="pt-3">
|
||||||
<span className="text-xs text-gray-500 block mb-1.5">Capabilities</span>
|
<span className="text-xs text-gray-500 block mb-1.5">Capabilities</span>
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{def.capabilities.map((cap) => (
|
{def.capabilities.map((cap) => (
|
||||||
<Badge
|
<Badge
|
||||||
key={cap}
|
key={cap}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-gray-700 text-gray-400 text-[10px]"
|
className="text-[10px]"
|
||||||
|
style={{
|
||||||
|
borderColor: `${color}44`,
|
||||||
|
color: unlocked ? `${color}cc` : `${color}66`,
|
||||||
|
backgroundColor: `${color}0a`,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{cap}
|
{cap}
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -140,7 +211,12 @@ function AttunementCard({ def, state }: AttunementCardProps) {
|
|||||||
<Badge
|
<Badge
|
||||||
key={cat}
|
key={cat}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-gray-700 text-gray-400 text-[10px]"
|
className="text-[10px]"
|
||||||
|
style={{
|
||||||
|
borderColor: `${color}33`,
|
||||||
|
color: unlocked ? `${color}aa` : `${color}55`,
|
||||||
|
backgroundColor: `${color}08`,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{cat}
|
{cat}
|
||||||
</Badge>
|
</Badge>
|
||||||
@@ -174,7 +250,7 @@ export function AttunementsTab() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<div className="text-2xl font-bold text-teal-400">
|
<div className="text-2xl font-bold" style={{ color: '#1ABC9C' }}>
|
||||||
{unlockedCount}
|
{unlockedCount}
|
||||||
<span className="text-sm text-gray-500 font-normal">
|
<span className="text-sm text-gray-500 font-normal">
|
||||||
/{allDefs.length}
|
/{allDefs.length}
|
||||||
@@ -187,17 +263,15 @@ export function AttunementsTab() {
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Attunement cards */}
|
{/* Attunement cards */}
|
||||||
<ScrollArea className="h-[600px] pr-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
{allDefs.map((def) => (
|
||||||
{allDefs.map((def) => (
|
<AttunementCard
|
||||||
<AttunementCard
|
key={def.id}
|
||||||
key={def.id}
|
def={def}
|
||||||
def={def}
|
state={attunements[def.id]}
|
||||||
state={attunements[def.id]}
|
/>
|
||||||
/>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</div>
|
</div>
|
||||||
</DebugName>
|
</DebugName>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from '@/components/game/crafting';
|
} from '@/components/game/crafting';
|
||||||
import { useCraftingStore } from '@/lib/game/stores';
|
import { useCraftingStore } from '@/lib/game/stores';
|
||||||
import type { DesignEffect } from '@/lib/game/types';
|
import type { DesignEffect } from '@/lib/game/types';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
type EnchanterPhase = 'design' | 'prepare' | 'apply';
|
type EnchanterPhase = 'design' | 'prepare' | 'apply';
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ export function EnchanterSubTab() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EnchanterSubTab">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Phase selector */}
|
{/* Phase selector */}
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
@@ -94,6 +96,7 @@ export function EnchanterSubTab() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { MANA_TYPE_LABELS } from '@/lib/game/data/fabricator-recipe-types';
|
|||||||
import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
|
import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
|
||||||
import { useCraftingStore, useManaStore } from '@/lib/game/stores';
|
import { useCraftingStore, useManaStore } from '@/lib/game/stores';
|
||||||
import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes';
|
import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
const BRANCH_RECIPE_IDS = new Set([
|
const BRANCH_RECIPE_IDS = new Set([
|
||||||
'oakStaff', 'arcanistStaff', 'battlestaff', 'arcanistCirclet', 'arcanistRobe',
|
'oakStaff', 'arcanistStaff', 'battlestaff', 'arcanistCirclet', 'arcanistRobe',
|
||||||
@@ -171,6 +172,7 @@ export function FabricatorSubTab() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="FabricatorSubTab">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Section toggle: Equipment vs Materials */}
|
{/* Section toggle: Equipment vs Materials */}
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
@@ -375,6 +377,7 @@ export function FabricatorSubTab() {
|
|||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { LOOT_DROPS, LOOT_RARITY_COLORS } from '@/lib/game/data/loot-drops';
|
|||||||
import { canCraftRecipe } from '@/lib/game/data/fabricator-recipes';
|
import { canCraftRecipe } from '@/lib/game/data/fabricator-recipes';
|
||||||
import { MANA_TYPE_LABELS } from '@/lib/game/data/fabricator-recipe-types';
|
import { MANA_TYPE_LABELS } from '@/lib/game/data/fabricator-recipe-types';
|
||||||
import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes';
|
import type { FabricatorRecipe } from '@/lib/game/data/fabricator-recipes';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface MaterialRecipeCardProps {
|
interface MaterialRecipeCardProps {
|
||||||
recipe: FabricatorRecipe;
|
recipe: FabricatorRecipe;
|
||||||
@@ -31,6 +32,7 @@ export function MaterialRecipeCard({
|
|||||||
const resultRarity = resultDrop ? LOOT_RARITY_COLORS[resultDrop.rarity] : null;
|
const resultRarity = resultDrop ? LOOT_RARITY_COLORS[resultDrop.rarity] : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="MaterialRecipeCard">
|
||||||
<div
|
<div
|
||||||
className="p-3 rounded border bg-gray-800/50"
|
className="p-3 rounded border bg-gray-800/50"
|
||||||
style={{ borderColor: resultRarity?.color ?? '#6B7280' }}
|
style={{ borderColor: resultRarity?.color ?? '#6B7280' }}
|
||||||
@@ -98,5 +100,6 @@ export function MaterialRecipeCard({
|
|||||||
{canCraft ? 'Craft' : 'Missing Resources'}
|
{canCraft ? 'Craft' : 'Missing Resources'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|||||||
import { Trophy, CheckCircle, RotateCcw } from 'lucide-react';
|
import { Trophy, CheckCircle, RotateCcw } from 'lucide-react';
|
||||||
import { useCombatStore } from '@/lib/game/stores';
|
import { useCombatStore } from '@/lib/game/stores';
|
||||||
import { ACHIEVEMENTS } from '@/lib/game/data/achievements';
|
import { ACHIEVEMENTS } from '@/lib/game/data/achievements';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function AchievementDebugSection() {
|
export function AchievementDebugSection() {
|
||||||
const achievements = useCombatStore((s) => s.achievements);
|
const achievements = useCombatStore((s) => s.achievements);
|
||||||
@@ -33,50 +34,52 @@ export function AchievementDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="AchievementDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-yellow-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<Trophy className="w-4 h-4" />
|
<CardTitle className="text-yellow-400 text-sm flex items-center gap-2">
|
||||||
Achievement Debug
|
<Trophy className="w-4 h-4" />
|
||||||
</CardTitle>
|
Achievement Debug
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent className="space-y-3">
|
</CardHeader>
|
||||||
<div className="text-xs text-gray-400">
|
<CardContent className="space-y-3">
|
||||||
Unlocked: {unlockedCount} / {totalCount}
|
<div className="text-xs text-gray-400">
|
||||||
</div>
|
Unlocked: {unlockedCount} / {totalCount}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2 flex-wrap">
|
<div className="flex gap-2 flex-wrap">
|
||||||
<Button size="sm" variant="outline" onClick={handleUnlockAll}>
|
<Button size="sm" variant="outline" onClick={handleUnlockAll}>
|
||||||
<CheckCircle className="w-3 h-3 mr-1" /> Unlock All
|
<CheckCircle className="w-3 h-3 mr-1" /> Unlock All
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm" variant="destructive" onClick={handleResetAll}>
|
<Button size="sm" variant="destructive" onClick={handleResetAll}>
|
||||||
<RotateCcw className="w-3 h-3 mr-1" /> Reset All
|
<RotateCcw className="w-3 h-3 mr-1" /> Reset All
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1 max-h-48 overflow-y-auto">
|
<div className="space-y-1 max-h-48 overflow-y-auto">
|
||||||
{Object.entries(ACHIEVEMENTS).map(([id, def]) => {
|
{Object.entries(ACHIEVEMENTS).map(([id, def]) => {
|
||||||
const isUnlocked = achievements?.unlocked?.includes(id);
|
const isUnlocked = achievements?.unlocked?.includes(id);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={id}
|
key={id}
|
||||||
className={`flex items-center justify-between p-2 rounded text-xs ${
|
className={`flex items-center justify-between p-2 rounded text-xs ${
|
||||||
isUnlocked ? 'bg-green-900/20 border border-green-600/50' : 'bg-gray-800/50'
|
isUnlocked ? 'bg-green-900/20 border border-green-600/50' : 'bg-gray-800/50'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium">{def.name}</span>
|
<span className="font-medium">{def.name}</span>
|
||||||
<span className="text-gray-500 ml-2">({def.category})</span>
|
<span className="text-gray-500 ml-2">({def.category})</span>
|
||||||
|
</div>
|
||||||
|
{isUnlocked && (
|
||||||
|
<CheckCircle className="w-3 h-3 text-green-400" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isUnlocked && (
|
);
|
||||||
<CheckCircle className="w-3 h-3 text-green-400" />
|
})}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</CardContent>
|
||||||
);
|
</Card>
|
||||||
})}
|
</DebugName>
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Sparkles, Unlock } from 'lucide-react';
|
|||||||
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
|
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
|
||||||
import { useAttunementStore } from '@/lib/game/stores';
|
import { useAttunementStore } from '@/lib/game/stores';
|
||||||
import { useManaStore } from '@/lib/game/stores';
|
import { useManaStore } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function AttunementDebugSection() {
|
export function AttunementDebugSection() {
|
||||||
const attunements = useAttunementStore((s) => s.attunements);
|
const attunements = useAttunementStore((s) => s.attunements);
|
||||||
@@ -34,54 +35,56 @@ export function AttunementDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="AttunementDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-purple-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<Sparkles className="w-4 h-4" />
|
<CardTitle className="text-purple-400 text-sm flex items-center gap-2">
|
||||||
Attunements
|
<Sparkles className="w-4 h-4" />
|
||||||
</CardTitle>
|
Attunements
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent className="space-y-3">
|
</CardHeader>
|
||||||
<Button size="sm" variant="outline" onClick={handleUnlockAll}>
|
<CardContent className="space-y-3">
|
||||||
<Unlock className="w-3 h-3 mr-1" /> Unlock All
|
<Button size="sm" variant="outline" onClick={handleUnlockAll}>
|
||||||
</Button>
|
<Unlock className="w-3 h-3 mr-1" /> Unlock All
|
||||||
{Object.entries(ATTUNEMENTS_DEF).map(([id, def]) => {
|
</Button>
|
||||||
const isActive = attunements?.[id]?.active;
|
{Object.entries(ATTUNEMENTS_DEF).map(([id, def]) => {
|
||||||
const level = attunements?.[id]?.level || 1;
|
const isActive = attunements?.[id]?.active;
|
||||||
const xp = attunements?.[id]?.experience || 0;
|
const level = attunements?.[id]?.level || 1;
|
||||||
|
const xp = attunements?.[id]?.experience || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={id} className="flex items-center justify-between p-2 bg-gray-800/50 rounded">
|
<div key={id} className="flex items-center justify-between p-2 bg-gray-800/50 rounded">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span>{def.icon}</span>
|
<span>{def.icon}</span>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-medium">{def.name}</div>
|
<div className="text-sm font-medium">{def.name}</div>
|
||||||
{isActive && (
|
{isActive && (
|
||||||
<div className="text-xs text-gray-400">Lv.{level} • {xp} XP</div>
|
<div className="text-xs text-gray-400">Lv.{level} • {xp} XP</div>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => handleUnlockAttunement(id)}
|
||||||
|
>
|
||||||
|
<Unlock className="w-3 h-3 mr-1" /> Unlock
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => handleAddAttunementXP(id, 100)}
|
||||||
|
>
|
||||||
|
+100 XP
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
);
|
||||||
<Button
|
})}
|
||||||
size="sm"
|
</CardContent>
|
||||||
variant="outline"
|
</Card>
|
||||||
onClick={() => handleUnlockAttunement(id)}
|
</DebugName>
|
||||||
>
|
|
||||||
<Unlock className="w-3 h-3 mr-1" /> Unlock
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => handleAddAttunementXP(id, 100)}
|
|
||||||
>
|
|
||||||
+100 XP
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { BookOpen, Plus, Pause, Play } from 'lucide-react';
|
|||||||
import { useDisciplineStore } from '@/lib/game/stores/discipline-slice';
|
import { useDisciplineStore } from '@/lib/game/stores/discipline-slice';
|
||||||
import { ALL_DISCIPLINES } from '@/lib/game/data/disciplines';
|
import { ALL_DISCIPLINES } from '@/lib/game/data/disciplines';
|
||||||
import { useManaStore } from '@/lib/game/stores/manaStore';
|
import { useManaStore } from '@/lib/game/stores/manaStore';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function DisciplineDebugSection() {
|
export function DisciplineDebugSection() {
|
||||||
const disciplines = useDisciplineStore((s) => s.disciplines);
|
const disciplines = useDisciplineStore((s) => s.disciplines);
|
||||||
@@ -55,81 +56,83 @@ export function DisciplineDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="DisciplineDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-indigo-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<BookOpen className="w-4 h-4" />
|
<CardTitle className="text-indigo-400 text-sm flex items-center gap-2">
|
||||||
Disciplines
|
<BookOpen className="w-4 h-4" />
|
||||||
</CardTitle>
|
Disciplines
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent className="space-y-3">
|
</CardHeader>
|
||||||
<div className="flex gap-2 flex-wrap mb-2">
|
<CardContent className="space-y-3">
|
||||||
<Button size="sm" variant="outline" onClick={handleActivateAll}>
|
<div className="flex gap-2 flex-wrap mb-2">
|
||||||
<Play className="w-3 h-3 mr-1" /> Activate All
|
<Button size="sm" variant="outline" onClick={handleActivateAll}>
|
||||||
</Button>
|
<Play className="w-3 h-3 mr-1" /> Activate All
|
||||||
<Button size="sm" variant="outline" onClick={handleDeactivateAll}>
|
</Button>
|
||||||
<Pause className="w-3 h-3 mr-1" /> Deactivate All
|
<Button size="sm" variant="outline" onClick={handleDeactivateAll}>
|
||||||
</Button>
|
<Pause className="w-3 h-3 mr-1" /> Deactivate All
|
||||||
</div>
|
</Button>
|
||||||
<div className="text-xs text-gray-400">
|
</div>
|
||||||
Active: {activeIds.length} / {concurrentLimit}
|
<div className="text-xs text-gray-400">
|
||||||
</div>
|
Active: {activeIds.length} / {concurrentLimit}
|
||||||
<div className="space-y-2 max-h-64 overflow-y-auto">
|
</div>
|
||||||
{ALL_DISCIPLINES.map((def) => {
|
<div className="space-y-2 max-h-64 overflow-y-auto">
|
||||||
const disc = disciplines[def.id];
|
{ALL_DISCIPLINES.map((def) => {
|
||||||
const isActive = activeIds.includes(def.id);
|
const disc = disciplines[def.id];
|
||||||
const xp = disc?.xp || 0;
|
const isActive = activeIds.includes(def.id);
|
||||||
|
const xp = disc?.xp || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={def.id}
|
key={def.id}
|
||||||
className="flex items-center justify-between p-2 bg-gray-800/50 rounded"
|
className="flex items-center justify-between p-2 bg-gray-800/50 rounded"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-sm font-medium">{def.name}</div>
|
<div className="text-sm font-medium">{def.name}</div>
|
||||||
<div className="text-xs text-gray-400">
|
<div className="text-xs text-gray-400">
|
||||||
{isActive ? `XP: ${xp}` : 'Inactive'}
|
{isActive ? `XP: ${xp}` : 'Inactive'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-1">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => handleAddXP(def.id, 100)}
|
||||||
|
>
|
||||||
|
<Plus className="w-3 h-3 mr-1" /> +100
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => handleAddXP(def.id, 1000)}
|
||||||
|
>
|
||||||
|
+1K
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant={isActive ? 'default' : 'outline'}
|
||||||
|
onClick={() => {
|
||||||
|
if (isActive) {
|
||||||
|
deactivate(def.id);
|
||||||
|
} else {
|
||||||
|
activate(def.id, { elements });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isActive ? (
|
||||||
|
<Pause className="w-3 h-3" />
|
||||||
|
) : (
|
||||||
|
<Play className="w-3 h-3" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1">
|
);
|
||||||
<Button
|
})}
|
||||||
size="sm"
|
</div>
|
||||||
variant="outline"
|
</CardContent>
|
||||||
onClick={() => handleAddXP(def.id, 100)}
|
</Card>
|
||||||
>
|
</DebugName>
|
||||||
<Plus className="w-3 h-3 mr-1" /> +100
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => handleAddXP(def.id, 1000)}
|
|
||||||
>
|
|
||||||
+1K
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant={isActive ? 'default' : 'outline'}
|
|
||||||
onClick={() => {
|
|
||||||
if (isActive) {
|
|
||||||
deactivate(def.id);
|
|
||||||
} else {
|
|
||||||
activate(def.id, { elements });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isActive ? (
|
|
||||||
<Pause className="w-3 h-3" />
|
|
||||||
) : (
|
|
||||||
<Play className="w-3 h-3" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|||||||
import { Star, Lock } from 'lucide-react';
|
import { Star, Lock } from 'lucide-react';
|
||||||
import { useManaStore } from '@/lib/game/stores';
|
import { useManaStore } from '@/lib/game/stores';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function ElementDebugSection() {
|
export function ElementDebugSection() {
|
||||||
const elements = useManaStore((s) => s.elements);
|
const elements = useManaStore((s) => s.elements);
|
||||||
@@ -29,63 +30,65 @@ export function ElementDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="ElementDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-green-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<Star className="w-4 h-4" />
|
<CardTitle className="text-green-400 text-sm flex items-center gap-2">
|
||||||
Elemental Mana
|
<Star className="w-4 h-4" />
|
||||||
</CardTitle>
|
Elemental Mana
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent>
|
</CardHeader>
|
||||||
<div className="mb-3">
|
<CardContent>
|
||||||
<Button size="sm" variant="outline" onClick={handleUnlockAll}>
|
<div className="mb-3">
|
||||||
<Lock className="w-3 h-3 mr-1" /> Unlock All Elements
|
<Button size="sm" variant="outline" onClick={handleUnlockAll}>
|
||||||
</Button>
|
<Lock className="w-3 h-3 mr-1" /> Unlock All Elements
|
||||||
</div>
|
</Button>
|
||||||
<div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 gap-2">
|
</div>
|
||||||
{Object.entries(elements || {}).map(([id, elem]) => {
|
<div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 gap-2">
|
||||||
const def = ELEMENTS[id];
|
{Object.entries(elements || {}).map(([id, elem]) => {
|
||||||
return (
|
const def = ELEMENTS[id];
|
||||||
<div
|
return (
|
||||||
key={id}
|
<div
|
||||||
className={`p-2 rounded border text-center ${
|
key={id}
|
||||||
elem.unlocked ? 'border-gray-600 bg-gray-800/50' : 'border-gray-800 opacity-60'
|
className={`p-2 rounded border text-center ${
|
||||||
}`}
|
elem.unlocked ? 'border-gray-600 bg-gray-800/50' : 'border-gray-800 opacity-60'
|
||||||
style={{
|
}`}
|
||||||
borderColor: elem.unlocked ? def?.color : undefined
|
style={{
|
||||||
}}
|
borderColor: elem.unlocked ? def?.color : undefined
|
||||||
>
|
}}
|
||||||
<div className="text-lg">{def?.sym}</div>
|
>
|
||||||
<div className="text-xs text-gray-400">{def?.name}</div>
|
<div className="text-lg">{def?.sym}</div>
|
||||||
<div className="text-xs text-gray-300 mt-1">
|
<div className="text-xs text-gray-400">{def?.name}</div>
|
||||||
{elem.current}/{elem.max}
|
<div className="text-xs text-gray-300 mt-1">
|
||||||
|
{elem.current}/{elem.max}
|
||||||
|
</div>
|
||||||
|
{!elem.unlocked && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
className="mt-2"
|
||||||
|
onClick={() => handleUnlockElement(id)}
|
||||||
|
>
|
||||||
|
<Lock className="w-3 h-3 mr-1" /> Unlock
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{elem.unlocked && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
className="mt-2"
|
||||||
|
onClick={() => handleAddElementalMana(id, 10)}
|
||||||
|
>
|
||||||
|
+10
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!elem.unlocked && (
|
);
|
||||||
<Button
|
})}
|
||||||
size="sm"
|
</div>
|
||||||
variant="outline"
|
</CardContent>
|
||||||
className="mt-2"
|
</Card>
|
||||||
onClick={() => handleUnlockElement(id)}
|
</DebugName>
|
||||||
>
|
|
||||||
<Lock className="w-3 h-3 mr-1" /> Unlock
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{elem.unlocked && (
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
className="mt-2"
|
|
||||||
onClick={() => handleAddElementalMana(id, 10)}
|
|
||||||
>
|
|
||||||
+10
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import {
|
import {
|
||||||
RotateCcw, AlertTriangle, Zap, Clock, Eye,
|
RotateCcw, AlertTriangle, Zap, Clock, Eye,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useDebug } from '@/components/game/debug/debug-context';
|
import { DebugName, useDebug } from '@/components/game/debug/debug-context';
|
||||||
import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores';
|
import { useGameStore, useManaStore, useUIStore, useCombatStore } from '@/lib/game/stores';
|
||||||
import { computeMaxMana } from '@/lib/game/stores';
|
import { computeMaxMana } from '@/lib/game/stores';
|
||||||
|
|
||||||
@@ -252,20 +252,22 @@ export function GameStateDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<DebugName name="GameStateDebugSection">
|
||||||
<DisplayOptions />
|
<div className="space-y-4">
|
||||||
|
<DisplayOptions />
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<GameResetSection confirmReset={confirmReset} onReset={handleReset} />
|
<GameResetSection confirmReset={confirmReset} onReset={handleReset} />
|
||||||
<ManaDebugSection rawMana={rawMana} onAddMana={handleAddMana} onFillMana={handleFillMana} />
|
<ManaDebugSection rawMana={rawMana} onAddMana={handleAddMana} onFillMana={handleFillMana} />
|
||||||
<TimeControlSection day={day} hour={hour} paused={paused} onSetDay={handleSetDay} onTogglePause={togglePause} />
|
<TimeControlSection day={day} hour={hour} paused={paused} onSetDay={handleSetDay} onTogglePause={togglePause} />
|
||||||
<QuickActionsSection
|
<QuickActionsSection
|
||||||
onUnlockBase={handleUnlockBase}
|
onUnlockBase={handleUnlockBase}
|
||||||
onSkipToFloor={() => debugSetFloor?.(100)}
|
onSkipToFloor={() => debugSetFloor?.(100)}
|
||||||
onResetFloorHP={() => resetFloorHP?.()}
|
onResetFloorHP={() => resetFloorHP?.()}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|||||||
import { Bug, Wand2 } from 'lucide-react';
|
import { Bug, Wand2 } from 'lucide-react';
|
||||||
import { useCombatStore } from '@/lib/game/stores';
|
import { useCombatStore } from '@/lib/game/stores';
|
||||||
import { GOLEMS_DEF } from '@/lib/game/data/golems';
|
import { GOLEMS_DEF } from '@/lib/game/data/golems';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function GolemDebugSection() {
|
export function GolemDebugSection() {
|
||||||
const golemancy = useCombatStore((s) => s.golemancy);
|
const golemancy = useCombatStore((s) => s.golemancy);
|
||||||
@@ -29,52 +30,54 @@ export function GolemDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="GolemDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<Bug className="w-4 h-4" />
|
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
||||||
Golem Debug
|
<Bug className="w-4 h-4" />
|
||||||
</CardTitle>
|
Golem Debug
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent className="space-y-3">
|
</CardHeader>
|
||||||
<div className="flex gap-2 flex-wrap">
|
<CardContent className="space-y-3">
|
||||||
<Button size="sm" variant="outline" onClick={handleEnableAll}>
|
<div className="flex gap-2 flex-wrap">
|
||||||
<Wand2 className="w-3 h-3 mr-1" /> Enable All Golems
|
<Button size="sm" variant="outline" onClick={handleEnableAll}>
|
||||||
</Button>
|
<Wand2 className="w-3 h-3 mr-1" /> Enable All Golems
|
||||||
<Button size="sm" variant="outline" onClick={handleDisableAll}>
|
</Button>
|
||||||
Disable All Golems
|
<Button size="sm" variant="outline" onClick={handleDisableAll}>
|
||||||
</Button>
|
Disable All Golems
|
||||||
</div>
|
</Button>
|
||||||
<div className="text-xs text-gray-400">
|
</div>
|
||||||
Enabled: {enabledGolems.length} / {Object.keys(GOLEMS_DEF).length}
|
<div className="text-xs text-gray-400">
|
||||||
</div>
|
Enabled: {enabledGolems.length} / {Object.keys(GOLEMS_DEF).length}
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 max-h-48 overflow-y-auto">
|
</div>
|
||||||
{Object.entries(GOLEMS_DEF).map(([id, def]) => {
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 max-h-48 overflow-y-auto">
|
||||||
const isEnabled = enabledGolems.includes(id);
|
{Object.entries(GOLEMS_DEF).map(([id, def]) => {
|
||||||
return (
|
const isEnabled = enabledGolems.includes(id);
|
||||||
<div
|
return (
|
||||||
key={id}
|
<div
|
||||||
className={`p-2 rounded border flex items-center justify-between ${
|
key={id}
|
||||||
isEnabled ? 'border-orange-600/50 bg-orange-900/20' : 'border-gray-700'
|
className={`p-2 rounded border flex items-center justify-between ${
|
||||||
}`}
|
isEnabled ? 'border-orange-600/50 bg-orange-900/20' : 'border-gray-700'
|
||||||
>
|
}`}
|
||||||
<div>
|
|
||||||
<div className="text-sm font-medium">{def.name}</div>
|
|
||||||
<div className="text-xs text-gray-400">{def.baseManaType}</div>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant={isEnabled ? 'default' : 'outline'}
|
|
||||||
onClick={() => handleToggleGolem(id)}
|
|
||||||
>
|
>
|
||||||
{isEnabled ? 'On' : 'Off'}
|
<div>
|
||||||
</Button>
|
<div className="text-sm font-medium">{def.name}</div>
|
||||||
</div>
|
<div className="text-xs text-gray-400">{def.baseManaType}</div>
|
||||||
);
|
</div>
|
||||||
})}
|
<Button
|
||||||
</div>
|
size="sm"
|
||||||
</CardContent>
|
variant={isEnabled ? 'default' : 'outline'}
|
||||||
</Card>
|
onClick={() => handleToggleGolem(id)}
|
||||||
|
>
|
||||||
|
{isEnabled ? 'On' : 'Off'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Bug } from 'lucide-react';
|
|||||||
import { usePrestigeStore, useUIStore, useGameStore } from '@/lib/game/stores';
|
import { usePrestigeStore, useUIStore, useGameStore } from '@/lib/game/stores';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
import { getGuardianForFloor, getAllGuardianFloors } from '@/lib/game/data/guardian-encounters';
|
import { getGuardianForFloor, getAllGuardianFloors } from '@/lib/game/data/guardian-encounters';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
// ─── Guardian Pact Row ───────────────────────────────────────────────────────
|
// ─── Guardian Pact Row ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -124,43 +125,45 @@ export function PactDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="PactDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<Bug className="w-4 h-4" />
|
<CardTitle className="text-orange-400 text-sm flex items-center gap-2">
|
||||||
Pact Debug
|
<Bug className="w-4 h-4" />
|
||||||
</CardTitle>
|
Pact Debug
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent>
|
</CardHeader>
|
||||||
<div className="space-y-3">
|
<CardContent>
|
||||||
<div className="flex gap-2 flex-wrap">
|
<div className="space-y-3">
|
||||||
<Button size="sm" variant="outline" onClick={signAllPacts}>
|
<div className="flex gap-2 flex-wrap">
|
||||||
Sign All Pacts
|
<Button size="sm" variant="outline" onClick={signAllPacts}>
|
||||||
</Button>
|
Sign All Pacts
|
||||||
<Button size="sm" variant="destructive" onClick={clearAllPacts}>
|
</Button>
|
||||||
Clear All Pacts ({signedPacts.length})
|
<Button size="sm" variant="destructive" onClick={clearAllPacts}>
|
||||||
</Button>
|
Clear All Pacts ({signedPacts.length})
|
||||||
</div>
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
||||||
{guardianFloors.map((floor) => (
|
{guardianFloors.map((floor) => (
|
||||||
<GuardianPactRow
|
<GuardianPactRow
|
||||||
key={floor}
|
key={floor}
|
||||||
floor={floor}
|
floor={floor}
|
||||||
isSigned={signedPacts.includes(floor)}
|
isSigned={signedPacts.includes(floor)}
|
||||||
onForceSign={() => forcePact(floor)}
|
onForceSign={() => forcePact(floor)}
|
||||||
onRemove={() => removePactHandler(floor)}
|
onRemove={() => removePactHandler(floor)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-xs text-gray-400 pt-2 border-t border-gray-700">
|
<div className="text-xs text-gray-400 pt-2 border-t border-gray-700">
|
||||||
Signed Pacts: {signedPacts.length} |
|
Signed Pacts: {signedPacts.length} |
|
||||||
Max Pacts: {1 + (prestigeUpgrades?.pactCapacity || 0)}
|
Max Pacts: {1 + (prestigeUpgrades?.pactCapacity || 0)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</CardContent>
|
||||||
</CardContent>
|
</Card>
|
||||||
</Card>
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Castle, ArrowUp, Eye } from 'lucide-react';
|
import { Castle, ArrowUp, Eye } from 'lucide-react';
|
||||||
import { useCombatStore } from '@/lib/game/stores';
|
import { useCombatStore } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function SpireDebugSection() {
|
export function SpireDebugSection() {
|
||||||
const [floorInput, setFloorInput] = useState('50');
|
const [floorInput, setFloorInput] = useState('50');
|
||||||
@@ -39,67 +40,69 @@ export function SpireDebugSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<DebugName name="SpireDebugSection">
|
||||||
<CardHeader className="pb-2">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardTitle className="text-teal-400 text-sm flex items-center gap-2">
|
<CardHeader className="pb-2">
|
||||||
<Castle className="w-4 h-4" />
|
<CardTitle className="text-teal-400 text-sm flex items-center gap-2">
|
||||||
Spire Debug
|
<Castle className="w-4 h-4" />
|
||||||
</CardTitle>
|
Spire Debug
|
||||||
</CardHeader>
|
</CardTitle>
|
||||||
<CardContent className="space-y-3">
|
</CardHeader>
|
||||||
<div className="text-xs text-gray-400">
|
<CardContent className="space-y-3">
|
||||||
Current Floor: {currentFloor} | Max Reached: {maxFloorReached} | Spire Mode: {spireMode ? 'ON' : 'OFF'}
|
<div className="text-xs text-gray-400">
|
||||||
</div>
|
Current Floor: {currentFloor} | Max Reached: {maxFloorReached} | Spire Mode: {spireMode ? 'ON' : 'OFF'}
|
||||||
|
|
||||||
<div className="flex gap-2 items-end">
|
|
||||||
<div className="flex-1">
|
|
||||||
<label className="text-xs text-gray-400 mb-1 block">Floor (1-100)</label>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
min={1}
|
|
||||||
max={100}
|
|
||||||
value={floorInput}
|
|
||||||
onChange={(e) => setFloorInput(e.target.value)}
|
|
||||||
className="h-8"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<Button size="sm" variant="outline" onClick={handleJumpToFloor}>
|
|
||||||
<ArrowUp className="w-3 h-3 mr-1" /> Jump
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex gap-2 flex-wrap">
|
<div className="flex gap-2 items-end">
|
||||||
<Button size="sm" variant="outline" onClick={handleClearFloor}>
|
<div className="flex-1">
|
||||||
Reset Floor HP
|
<label className="text-xs text-gray-400 mb-1 block">Floor (1-100)</label>
|
||||||
</Button>
|
<Input
|
||||||
<Button
|
type="number"
|
||||||
size="sm"
|
min={1}
|
||||||
variant={spireMode ? 'default' : 'outline'}
|
max={100}
|
||||||
onClick={handleToggleSpireMode}
|
value={floorInput}
|
||||||
>
|
onChange={(e) => setFloorInput(e.target.value)}
|
||||||
<Eye className="w-3 h-3 mr-1" />
|
className="h-8"
|
||||||
{spireMode ? 'Exit Spire Mode' : 'Enter Spire Mode'}
|
/>
|
||||||
</Button>
|
</div>
|
||||||
</div>
|
<Button size="sm" variant="outline" onClick={handleJumpToFloor}>
|
||||||
|
<ArrowUp className="w-3 h-3 mr-1" /> Jump
|
||||||
<div className="flex gap-2 flex-wrap">
|
|
||||||
{[10, 25, 50, 75, 100].map((f) => (
|
|
||||||
<Button
|
|
||||||
key={f}
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => {
|
|
||||||
setFloorInput(String(f));
|
|
||||||
debugSetFloor(f);
|
|
||||||
setMaxFloorReached(f);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Floor {f}
|
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
</div>
|
||||||
</div>
|
|
||||||
</CardContent>
|
<div className="flex gap-2 flex-wrap">
|
||||||
</Card>
|
<Button size="sm" variant="outline" onClick={handleClearFloor}>
|
||||||
|
Reset Floor HP
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant={spireMode ? 'default' : 'outline'}
|
||||||
|
onClick={handleToggleSpireMode}
|
||||||
|
>
|
||||||
|
<Eye className="w-3 h-3 mr-1" />
|
||||||
|
{spireMode ? 'Exit Spire Mode' : 'Enter Spire Mode'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-2 flex-wrap">
|
||||||
|
{[10, 25, 50, 75, 100].map((f) => (
|
||||||
|
<Button
|
||||||
|
key={f}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setFloorInput(String(f));
|
||||||
|
debugSetFloor(f);
|
||||||
|
setMaxFloorReached(f);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Floor {f}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { computeEquipmentEffects } from '@/lib/game/effects';
|
import { computeEquipmentEffects } from '@/lib/game/effects';
|
||||||
import type { EquipmentInstance } from '@/lib/game/types';
|
import type { EquipmentInstance } from '@/lib/game/types';
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ export function EquipmentEffectsSummary({ equipmentInstances, equippedInstances
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EquipmentEffectsSummary">
|
||||||
<div className="p-3 rounded border border-[var(--border-default)] bg-[var(--bg-sunken)] space-y-2">
|
<div className="p-3 rounded border border-[var(--border-default)] bg-[var(--bg-sunken)] space-y-2">
|
||||||
<h3 className="text-sm font-semibold text-[var(--text-primary)]">Equipment Effects</h3>
|
<h3 className="text-sm font-semibold text-[var(--text-primary)]">Equipment Effects</h3>
|
||||||
|
|
||||||
@@ -89,5 +91,6 @@ export function EquipmentEffectsSummary({ equipmentInstances, equippedInstances
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type { EquipmentInstance, EquipmentSlot } from '@/lib/game/types';
|
|||||||
import { EQUIPMENT_TYPES, SLOT_NAMES } from '@/lib/game/data/equipment';
|
import { EQUIPMENT_TYPES, SLOT_NAMES } from '@/lib/game/data/equipment';
|
||||||
import { RARITY_CSS_VAR } from '@/components/game/LootInventory/types';
|
import { RARITY_CSS_VAR } from '@/components/game/LootInventory/types';
|
||||||
import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
|
import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { ActionButton } from '@/components/ui/action-button';
|
import { ActionButton } from '@/components/ui/action-button';
|
||||||
|
|
||||||
interface EquipmentSlotGridProps {
|
interface EquipmentSlotGridProps {
|
||||||
@@ -17,6 +18,7 @@ const SLOTS: EquipmentSlot[] = ['mainHand', 'offHand', 'head', 'body', 'hands',
|
|||||||
|
|
||||||
export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUnequip }: EquipmentSlotGridProps) {
|
export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUnequip }: EquipmentSlotGridProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="EquipmentSlotGrid">
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
||||||
{SLOTS.map((slot) => {
|
{SLOTS.map((slot) => {
|
||||||
const instanceId = equippedInstances[slot];
|
const instanceId = equippedInstances[slot];
|
||||||
@@ -75,5 +77,6 @@ export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUne
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { EQUIPMENT_TYPES, getValidSlotsForEquipmentType } from '@/lib/game/data/
|
|||||||
import { RARITY_CSS_VAR, RARITY_GLOW_CSS_VAR } from '@/components/game/LootInventory/types';
|
import { RARITY_CSS_VAR, RARITY_GLOW_CSS_VAR } from '@/components/game/LootInventory/types';
|
||||||
import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
|
import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
|
||||||
import { ActionButton } from '@/components/ui/action-button';
|
import { ActionButton } from '@/components/ui/action-button';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
@@ -38,6 +39,7 @@ export function InventoryList({ inventoryItems, equippedInstances, onEquip, onDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="InventoryList">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{inventoryItems.map(([instanceId, instance]) => {
|
{inventoryItems.map(([instanceId, instance]) => {
|
||||||
const type = EQUIPMENT_TYPES[instance.typeId];
|
const type = EQUIPMENT_TYPES[instance.typeId];
|
||||||
@@ -131,5 +133,6 @@ export function InventoryList({ inventoryItems, equippedInstances, onEquip, onDe
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ELEMENTS, SPELLS_DEF } from '@/lib/game/constants';
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
// Format spell cost for display
|
// Format spell cost for display
|
||||||
function formatSpellCost(cost: { type: 'raw' | 'element'; element?: string; amount: number }): string {
|
function formatSpellCost(cost: { type: 'raw' | 'element'; element?: string; amount: number }): string {
|
||||||
@@ -34,7 +35,8 @@ export function SpellsTab() {
|
|||||||
const spellTiers = [0, 1, 2, 3, 4];
|
const spellTiers = [0, 1, 2, 3, 4];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<DebugName name="SpellsTab">
|
||||||
|
<div className="space-y-6">
|
||||||
{spellTiers.map(tier => {
|
{spellTiers.map(tier => {
|
||||||
const spellsInTier = Object.entries(SPELLS_DEF).filter(([, def]) => def.tier === tier);
|
const spellsInTier = Object.entries(SPELLS_DEF).filter(([, def]) => def.tier === tier);
|
||||||
if (spellsInTier.length === 0) return null;
|
if (spellsInTier.length === 0) return null;
|
||||||
@@ -121,7 +123,8 @@ export function SpellsTab() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Progress } from '@/components/ui/progress';
|
|||||||
import { getSpireRoomTypeDisplay } from '@/lib/game/utils/spire-utils';
|
import { getSpireRoomTypeDisplay } from '@/lib/game/utils/spire-utils';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface RoomDisplayProps {
|
interface RoomDisplayProps {
|
||||||
floorState: FloorState;
|
floorState: FloorState;
|
||||||
@@ -179,6 +180,7 @@ export function RoomDisplay({ floorState }: RoomDisplayProps) {
|
|||||||
const isGuardian = floorState.roomType === 'guardian';
|
const isGuardian = floorState.roomType === 'guardian';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="RoomDisplay">
|
||||||
<Card className={`bg-gray-900/80 ${isGuardian ? 'border-red-800/40' : 'border-gray-700'}`}>
|
<Card className={`bg-gray-900/80 ${isGuardian ? 'border-red-800/40' : 'border-gray-700'}`}>
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-sm flex items-center gap-2" style={{ color: roomDisplay.color }}>
|
<CardTitle className="text-sm flex items-center gap-2" style={{ color: roomDisplay.color }}>
|
||||||
@@ -196,5 +198,6 @@ export function RoomDisplay({ floorState }: RoomDisplayProps) {
|
|||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import type { ActivityLogEntry } from '@/lib/game/types';
|
import type { ActivityLogEntry } from '@/lib/game/types';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface SpireActivityLogProps {
|
interface SpireActivityLogProps {
|
||||||
activityLog: ActivityLogEntry[];
|
activityLog: ActivityLogEntry[];
|
||||||
@@ -13,6 +14,7 @@ export function SpireActivityLog({ activityLog, maxEntries = 30 }: SpireActivity
|
|||||||
const entries = activityLog.slice(0, maxEntries);
|
const entries = activityLog.slice(0, maxEntries);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="SpireActivityLog">
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-sm text-gray-400">📜 Activity Log</CardTitle>
|
<CardTitle className="text-sm text-gray-400">📜 Activity Log</CardTitle>
|
||||||
@@ -39,5 +41,6 @@ export function SpireActivityLog({ activityLog, maxEntries = 30 }: SpireActivity
|
|||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { SPELLS_DEF, ELEMENTS } from '@/lib/game/constants';
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { GOLEMS_DEF } from '@/lib/game/data/golems';
|
import { GOLEMS_DEF } from '@/lib/game/data/golems';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface SpireCombatControlsProps {
|
interface SpireCombatControlsProps {
|
||||||
castProgress: number;
|
castProgress: number;
|
||||||
@@ -31,6 +32,7 @@ export function SpireCombatControls({ castProgress }: SpireCombatControlsProps)
|
|||||||
const summonedGolems = golemancy.summonedGolems || [];
|
const summonedGolems = golemancy.summonedGolems || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="SpireCombatControls">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Active Spell Panel */}
|
{/* Active Spell Panel */}
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
@@ -127,5 +129,6 @@ export function SpireCombatControls({ castProgress }: SpireCombatControlsProps)
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { RoomDisplay } from './RoomDisplay';
|
|||||||
import { SpireCombatControls } from './SpireCombatControls';
|
import { SpireCombatControls } from './SpireCombatControls';
|
||||||
import { SpireActivityLog } from './SpireActivityLog';
|
import { SpireActivityLog } from './SpireActivityLog';
|
||||||
import { SpireManaDisplay } from './SpireManaDisplay';
|
import { SpireManaDisplay } from './SpireManaDisplay';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
// ─── Derived Stats Hook ──────────────────────────────────────────────────────
|
// ─── Derived Stats Hook ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -164,6 +165,7 @@ export function SpireCombatPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="SpireCombatPage">
|
||||||
<div className="min-h-screen bg-gray-950 flex flex-col">
|
<div className="min-h-screen bg-gray-950 flex flex-col">
|
||||||
<header className="sticky top-0 z-50 bg-gray-900/95 border-b border-gray-800 px-4 py-2">
|
<header className="sticky top-0 z-50 bg-gray-900/95 border-b border-gray-800 px-4 py-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@@ -206,5 +208,6 @@ export function SpireCombatPage() {
|
|||||||
<SpireActivityLog activityLog={activityLog} maxEntries={20} />
|
<SpireActivityLog activityLog={activityLog} maxEntries={20} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Card, CardContent } from '@/components/ui/card';
|
|||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { Mountain, ArrowUp, ArrowDown, LogOut } from 'lucide-react';
|
import { Mountain, ArrowUp, ArrowDown, LogOut } from 'lucide-react';
|
||||||
import { getGuardianForFloor, isGuardianFloor } from '@/lib/game/data/guardian-encounters';
|
import { getGuardianForFloor, isGuardianFloor } from '@/lib/game/data/guardian-encounters';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface SpireHeaderProps {
|
interface SpireHeaderProps {
|
||||||
currentFloor: number;
|
currentFloor: number;
|
||||||
@@ -39,6 +40,7 @@ export function SpireHeader({
|
|||||||
const roomProgress = totalRooms > 0 ? ((roomsCleared) / totalRooms) * 100 : 0;
|
const roomProgress = totalRooms > 0 ? ((roomsCleared) / totalRooms) * 100 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="SpireHeader">
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardContent className="py-3 space-y-3">
|
<CardContent className="py-3 space-y-3">
|
||||||
{/* Top row: Floor info + controls */}
|
{/* Top row: Floor info + controls */}
|
||||||
@@ -123,5 +125,6 @@ export function SpireHeader({
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useManaStore, fmt, fmtDec } from '@/lib/game/stores';
|
|||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
interface SpireManaDisplayProps {
|
interface SpireManaDisplayProps {
|
||||||
maxMana: number;
|
maxMana: number;
|
||||||
@@ -22,6 +23,7 @@ export function SpireManaDisplay({ maxMana, effectiveRegen }: SpireManaDisplayPr
|
|||||||
const manaPercent = maxMana > 0 ? (rawMana / maxMana) * 100 : 0;
|
const manaPercent = maxMana > 0 ? (rawMana / maxMana) * 100 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="SpireManaDisplay">
|
||||||
<Card className="bg-gray-900/80 border-gray-700">
|
<Card className="bg-gray-900/80 border-gray-700">
|
||||||
<CardContent className="py-3 space-y-2">
|
<CardContent className="py-3 space-y-2">
|
||||||
{/* Raw Mana */}
|
{/* Raw Mana */}
|
||||||
@@ -68,5 +70,6 @@ export function SpireManaDisplay({ maxMana, effectiveRegen }: SpireManaDisplayPr
|
|||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { StudyStatsSection } from './StatsTab/StudyStatsSection';
|
|||||||
import { ElementStatsSection } from './StatsTab/ElementStatsSection';
|
import { ElementStatsSection } from './StatsTab/ElementStatsSection';
|
||||||
import { LoopStatsSection } from './StatsTab/LoopStatsSection';
|
import { LoopStatsSection } from './StatsTab/LoopStatsSection';
|
||||||
import { DisciplineStatsSection } from './StatsTab/DisciplineStatsSection';
|
import { DisciplineStatsSection } from './StatsTab/DisciplineStatsSection';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
export function StatsTab() {
|
export function StatsTab() {
|
||||||
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
|
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
|
||||||
@@ -23,7 +24,8 @@ export function StatsTab() {
|
|||||||
const elemMax = 10 + (prestigeUpgrades.elementalAttune || 0) * 25;
|
const elemMax = 10 + (prestigeUpgrades.elementalAttune || 0) * 25;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<DebugName name="StatsTab">
|
||||||
|
<div className="space-y-4">
|
||||||
<ManaStatsSection
|
<ManaStatsSection
|
||||||
stats={{
|
stats={{
|
||||||
...manaStats,
|
...manaStats,
|
||||||
@@ -51,7 +53,8 @@ export function StatsTab() {
|
|||||||
elemMax={elemMax}
|
elemMax={elemMax}
|
||||||
/>
|
/>
|
||||||
<LoopStatsSection />
|
<LoopStatsSection />
|
||||||
</div>
|
</div>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Swords } from 'lucide-react';
|
import { Swords } from 'lucide-react';
|
||||||
import { fmt, fmtDec } from '@/lib/game/stores';
|
import { fmt, fmtDec } from '@/lib/game/stores';
|
||||||
import type { SpellDef } from '@/lib/game/types';
|
import type { SpellDef } from '@/lib/game/types';
|
||||||
@@ -12,6 +13,7 @@ interface CombatStatsSectionProps {
|
|||||||
|
|
||||||
export function CombatStatsSection({ activeSpellDef, pactMultiplier }: CombatStatsSectionProps) {
|
export function CombatStatsSection({ activeSpellDef, pactMultiplier }: CombatStatsSectionProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="CombatStatsSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--mana-fire)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--mana-fire)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -44,5 +46,6 @@ export function CombatStatsSection({ activeSpellDef, pactMultiplier }: CombatSta
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Brain } from 'lucide-react';
|
import { Brain } from 'lucide-react';
|
||||||
import { useDisciplineStore } from '@/lib/game/stores/discipline-slice';
|
import { useDisciplineStore } from '@/lib/game/stores/discipline-slice';
|
||||||
@@ -27,6 +28,7 @@ export function DisciplineStatsSection({ disciplineEffects }: DisciplineStatsSec
|
|||||||
if (disciplineEntries.length === 0) return null;
|
if (disciplineEntries.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="DisciplineStatsSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -68,5 +70,6 @@ export function DisciplineStatsSection({ disciplineEffects }: DisciplineStatsSec
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { FlaskConical } from 'lucide-react';
|
import { FlaskConical } from 'lucide-react';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
@@ -16,6 +17,7 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
|
|||||||
const elements = useManaStore((s) => s.elements);
|
const elements = useManaStore((s) => s.elements);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="ElementStatsSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--color-success)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--color-success)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -59,5 +61,6 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { RotateCcw } from 'lucide-react';
|
import { RotateCcw } from 'lucide-react';
|
||||||
import { fmt } from '@/lib/game/stores';
|
import { fmt } from '@/lib/game/stores';
|
||||||
@@ -18,6 +19,7 @@ export function LoopStatsSection() {
|
|||||||
const spellsLearned = Object.values(spells || {}).filter((s: SpellState) => s.learned).length;
|
const spellsLearned = Object.values(spells || {}).filter((s: SpellState) => s.learned).length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="LoopStatsSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -57,5 +59,6 @@ export function LoopStatsSection() {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { fmt, fmtDec } from '@/lib/game/stores';
|
import { fmt, fmtDec } from '@/lib/game/stores';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Droplet } from 'lucide-react';
|
import { Droplet } from 'lucide-react';
|
||||||
import type { ComputedEffects } from '@/lib/game/effects/upgrade-effects.types';
|
import type { ComputedEffects } from '@/lib/game/effects/upgrade-effects.types';
|
||||||
@@ -51,6 +52,7 @@ export function ManaStatsSection({ stats, elemMax }: ManaStatsSectionProps) {
|
|||||||
} = stats;
|
} = stats;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="ManaStatsSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--mana-water)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--mana-water)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -206,5 +208,6 @@ export function ManaStatsSection({ stats, elemMax }: ManaStatsSectionProps) {
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { Trophy } from 'lucide-react';
|
import { Trophy } from 'lucide-react';
|
||||||
import { fmtDec } from '@/lib/game/stores';
|
import { fmtDec } from '@/lib/game/stores';
|
||||||
import { ELEMENTS } from '@/lib/game/constants';
|
import { ELEMENTS } from '@/lib/game/constants';
|
||||||
@@ -19,6 +20,7 @@ export function PactStatusSection({ pactMultiplier, pactInsightMultiplier }: Pac
|
|||||||
const pactInterferenceMitigation = prestigeUpgrades?.pactInterferenceMitigation || 0;
|
const pactInterferenceMitigation = prestigeUpgrades?.pactInterferenceMitigation || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="PactStatusSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--mana-light)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -74,5 +76,6 @@ export function PactStatusSection({ pactMultiplier, pactInsightMultiplier }: Pac
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
import { BookOpen } from 'lucide-react';
|
import { BookOpen } from 'lucide-react';
|
||||||
import { fmtDec } from '@/lib/game/stores';
|
import { fmtDec } from '@/lib/game/stores';
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ interface StudyStatsSectionProps {
|
|||||||
|
|
||||||
export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsSectionProps) {
|
export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsSectionProps) {
|
||||||
return (
|
return (
|
||||||
|
<DebugName name="StudyStatsSection">
|
||||||
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
<Card className="bg-[var(--bg-panel)] border-[var(--border-subtle)]">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2">
|
<CardTitle className="text-[var(--mana-crystal)] game-panel-title text-xs flex items-center gap-2">
|
||||||
@@ -41,5 +43,6 @@ export function StudyStatsSection({ studySpeedMult, studyCostMult }: StudyStatsS
|
|||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Shield, Swords, Clock, Sparkles, Check, Lock, ChevronRight } from 'lucide-react';
|
import { Shield, Swords, Clock, Sparkles, Check, Lock, ChevronRight } from 'lucide-react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { DebugName } from '@/components/game/debug/debug-context';
|
||||||
|
|
||||||
// ─── Types ───────────────────────────────────────────────────────────────────
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -81,14 +82,15 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
|
|||||||
: elemDisplays[0]?.name ?? guardian.element;
|
: elemDisplays[0]?.name ?? guardian.element;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<DebugName name="GuardianPactsComponents">
|
||||||
className={clsx(
|
<Card
|
||||||
'border transition-colors',
|
className={clsx(
|
||||||
status === 'signed' && 'border-green-600/40',
|
'border transition-colors',
|
||||||
status === 'defeated' && 'border-amber-600/40',
|
status === 'signed' && 'border-green-600/40',
|
||||||
status === 'undefeated' && 'border-gray-700/60',
|
status === 'defeated' && 'border-amber-600/40',
|
||||||
)}
|
status === 'undefeated' && 'border-gray-700/60',
|
||||||
>
|
)}
|
||||||
|
>
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<div className="flex items-start justify-between gap-2">
|
<div className="flex items-start justify-between gap-2">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
@@ -141,7 +143,8 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
</DebugName>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user