"use client"; // 回响星核 / Echo Nexus — 星潮事件 UI(横幅 + 通知 + 背景叠层) import { useEffect, useState } from "react"; import { useGameStore } from "@/store/gameStore"; import { useToast } from "@/hooks/use-toast"; import { sfx } from "@/hooks/useAudio"; import { TIDE_EVENTS, TIDE_CONFIG } from "@/lib/game/starTide"; /** 星潮事件通知消费者:监听 _tideEvents 队列,弹 Toast + 播音效 */ export function StarTideNotifier() { const events = useGameStore((s) => s._tideEvents); const consume = useGameStore((s) => s.consumeTideEvents); const { toast } = useToast(); useEffect(() => { if (events.length === 0) return; const items = consume(); for (const ev of items) { const globalTag = ev.isGlobal ? "🌐 " : ""; if (ev.started) { const meta = TIDE_EVENTS[ev.started]; sfx("tideStart"); toast({ title: `${globalTag}${meta.icon} ${ev.isGlobal ? "全球星潮" : "星潮降临"}:${meta.name}`, description: ev.isGlobal ? `全球玩家同步经历 · ${meta.desc}` : meta.desc, }); } if (ev.ended) { const meta = TIDE_EVENTS[ev.ended]; if (ev.silenceCompensation && ev.silenceCompensation > 0) { sfx("techBuy"); toast({ title: `${globalTag}${meta.icon} 寂静期消散`, description: `虚空回赠 ${ev.silenceCompensation} 洞见。`, }); } else { sfx("tideEnd"); toast({ title: `${globalTag}${meta.icon} ${meta.name}结束`, description: ev.isGlobal ? "全球星潮退去,物理法则恢复。" : "星潮退去,物理法则恢复。", }); } } } }, [events, consume, toast]); return null; } /** 顶部星潮指示器(活跃时显示倒计时芯片) */ export function StarTideIndicator() { const activeTide = useGameStore((s) => s.activeTide); const globalTide = useGameStore((s) => s.globalTide); const [, force] = useState(0); // 每秒刷新倒计时 useEffect(() => { if (!activeTide) return; const id = setInterval(() => force((n) => n + 1), 500); return () => clearInterval(id); }, [activeTide]); if (!activeTide) return null; const meta = TIDE_EVENTS[activeTide.type]; const remaining = Math.max(0, activeTide.endsAt - Date.now()); const secs = Math.ceil(remaining / 1000); // 全球星潮持续 60s,本地 75s —— 用实际 endsAt-startedAt 计算 progress,避免越界 const duration = globalTide ? globalTide.endsAt - globalTide.startedAt : TIDE_CONFIG.duration; const progress = Math.min(1, Math.max(0, 1 - remaining / duration)); const isGlobal = !!globalTide; return (
{/* 进度环背景 */}
{isGlobal && ( 🌐 )} {meta.icon} {meta.name} {secs}s
); } /** 全屏背景叠层:活跃星潮时给页面罩一层对应色的微光 */ export function StarTideOverlay() { const activeTide = useGameStore((s) => s.activeTide); const globalTide = useGameStore((s) => s.globalTide); if (!activeTide) return null; const meta = TIDE_EVENTS[activeTide.type]; const isGlobal = !!globalTide; return (
{/* 顶部色带 */}
{/* 底部色带 */}
{/* 边缘呼吸光 */}
{/* 全球星潮:顶部多一道琥珀色光带,强化"全球同步"视觉信号 */} {isGlobal && (
)}
); }