"use client"; // 回响星核 / Echo Nexus — 星图天赋选择对话框(飞升后弹出,3 选 1) import { useEffect, useState } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { useGameStore } from "@/store/gameStore"; import { getPerk, CONSTELLATION_CATEGORY_META, constellationProgress, } from "@/lib/game/constellation"; import { sfx } from "@/hooks/useAudio"; import { Sparkles, RefreshCw } from "lucide-react"; interface Props { open: boolean; onOpenChange: (v: boolean) => void; } export function ConstellationDialog({ open, onOpenChange }: Props) { const pendingChoices = useGameStore((s) => s.pendingPerkChoices); const constellation = useGameStore((s) => s.constellation ?? []); const choosePerk = useGameStore((s) => s.chooseConstellationPerk); const reroll = useGameStore((s) => s.rerollPerkChoices); const [picked, setPicked] = useState(null); // 关闭时清理本地状态 useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect if (!open) setPicked(null); }, [open]); // 自动 open:当 pendingPerkChoices 存在且当前未 open 时 useEffect(() => { if (pendingChoices && pendingChoices.length > 0 && !open) { onOpenChange(true); } if ((!pendingChoices || pendingChoices.length === 0) && open) { onOpenChange(false); } }, [pendingChoices, open, onOpenChange]); const handlePick = (perkId: string) => { setPicked(perkId); const ok = choosePerk(perkId); if (ok) { sfx("constellation"); // 延迟关闭,让选中动画播放 setTimeout(() => onOpenChange(false), 500); } }; const handleReroll = () => { reroll(); sfx("uiClick"); }; if (!pendingChoices || pendingChoices.length === 0) return null; const progress = constellationProgress(constellation); return ( 星图觉醒 飞升带来的回响在星图上凝聚。从 3 道星辉中选择 1 道,永久获得其加成。
当前已觉醒 {progress.unlocked}/{progress.total}
{pendingChoices.map((perkId) => { const perk = getPerk(perkId); if (!perk) return null; const meta = CONSTELLATION_CATEGORY_META[perk.category]; const isPicked = picked === perkId; return ( ); })}
✦ 选择后永久保留,跨周目生效
); }