v0.9 工单修复: 4 bug + 4 玩法改进
Gitea Issue #2 修复: Bug: 1. 探险只能一次 → 能量恢复 45→20s, 初始能量 3→5, 上限 5→8 新增 lastExpeditionSummary 显示上次结果 新增 dismissExpedition action 2. 元素偏移/遮挡 → 标签页 grid-cols-8 → 响应式 grid-cols-4/sm:8 3. 成就UI遮挡 → max-h 440→520, min-h 提高 4. 提示框遮挡 → toast top-0→top-14 避开 header, TOAST_LIMIT 1→3 玩法改进: 1. 中央晶体球 → 下方新增 4 指标收益面板(产能/脉冲/连击/仓库) 2. 技术树 12→20 节点 (每分支 3→5 级) 3. 成就解锁 → 全屏居中特效通知 (framer-motion 弹窗) 4. 叙事融入 → 新建 narrative.ts, 脉冲/技术树注入世界观文本
This commit is contained in:
+128
-2
@@ -45,6 +45,10 @@ import {
|
||||
Radio,
|
||||
Navigation,
|
||||
User,
|
||||
Gem,
|
||||
Zap,
|
||||
Flame,
|
||||
Database,
|
||||
} from "lucide-react";
|
||||
import { TECH_TREE, FRAGMENTS, formatNum } from "@/lib/game/config";
|
||||
import { ACHIEVEMENTS } from "@/lib/game/achievements";
|
||||
@@ -275,6 +279,8 @@ export default function Page() {
|
||||
<div data-tut="crystal-orb" className="contents">
|
||||
<CrystalOrb />
|
||||
</div>
|
||||
{/* v0.9 工单 #2:全息收益信息面板 — 让晶体球价值可视化 */}
|
||||
<CrystalYieldPanel />
|
||||
</section>
|
||||
|
||||
{/* 右侧:解码 + 标签面板 */}
|
||||
@@ -284,9 +290,11 @@ export default function Page() {
|
||||
<DecodePanel />
|
||||
</div>
|
||||
{/* 标签面板:探险 / 技术 / 星图 / 图谱 / 成就 / 信标 / 统计 / 角色 */}
|
||||
<div className="glass rounded-2xl p-3 min-h-[280px] sm:min-h-[320px] max-h-[440px] flex flex-col">
|
||||
{/* v0.9 工单修复:移除 max-h 硬限制,改用 min-h + flex 自适应,避免成就/技术树内容被挤压遮挡 */}
|
||||
<div className="glass rounded-2xl p-3 min-h-[300px] sm:min-h-[360px] max-h-[520px] flex flex-col">
|
||||
<Tabs defaultValue={hasActiveExpedition ? "expedition" : hasPendingPerk ? "constellation" : "tech"} className="h-full flex flex-col">
|
||||
<TabsList className="grid grid-cols-8 h-9 bg-black/30 gap-0.5 p-1">
|
||||
{/* v0.9 工单修复:标签页响应式布局,小屏 4 列 2 行避免拥挤遮挡 */}
|
||||
<TabsList className="grid grid-cols-4 sm:grid-cols-8 h-auto sm:h-9 bg-black/30 gap-0.5 p-1">
|
||||
<TabsTrigger value="expedition" data-tut="tab-expedition" className="text-[11px] gap-1 relative px-0.5 flex-col h-7 data-[state=active]:bg-amber-500/15 data-[state=active]:shadow-[0_0_12px_rgba(251,191,36,0.3)] transition-all">
|
||||
<Rocket className="h-3.5 w-3.5" />
|
||||
<span className="leading-none">探险</span>
|
||||
@@ -428,6 +436,124 @@ export default function Page() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* v0.9 工单 #2:全息收益信息面板
|
||||
* 在中央晶体球下方展示 4 项核心收益指标(产能 / 脉冲 / 连击 / 仓库),
|
||||
* 让玩家明确感知晶体球的价值,缓解"占地方又没用"的反馈。
|
||||
* 严格四色全息配色:emerald / rose / amber / fuchsia(禁止蓝色/靛色)。
|
||||
*/
|
||||
function CrystalYieldPanel() {
|
||||
const crystalsPerSec = useGameStore((s) => s.crystalsPerSec);
|
||||
const pulsePower = useGameStore((s) => s.pulsePower);
|
||||
const combo = useGameStore((s) => s._combo);
|
||||
const crystals = useGameStore((s) => s.crystals);
|
||||
const crystalCap = useGameStore((s) => s.crystalCap);
|
||||
|
||||
// 连击倍率:1 + (combo - 1) * 0.15(仅 combo≥1 时生效)
|
||||
const comboMult = combo >= 1 ? 1 + (combo - 1) * 0.15 : 1;
|
||||
const comboHot = combo >= 3; // 连击≥3 高亮闪烁
|
||||
|
||||
// 仓库容量百分比
|
||||
const fillPct = crystalCap > 0 ? (crystals / crystalCap) * 100 : 0;
|
||||
const warehouseWarn = fillPct >= 90; // ≥90% 警告色 + pulse
|
||||
|
||||
return (
|
||||
<div className="mt-3 grid grid-cols-2 sm:grid-cols-4 gap-2 w-full max-w-md pointer-events-none">
|
||||
{/* 晶体产能 — emerald */}
|
||||
<div className="rounded-lg border border-emerald-400/30 bg-black/30 backdrop-blur p-2 flex items-center gap-1.5">
|
||||
<Gem className="h-3.5 w-3.5 text-emerald-400 shrink-0" />
|
||||
<div className="min-w-0 leading-tight">
|
||||
<div className="text-[9px] uppercase tracking-wider text-emerald-300/70 truncate">
|
||||
晶体产能
|
||||
</div>
|
||||
<div className="text-sm font-mono tabular-nums text-emerald-200 truncate">
|
||||
{formatNum(crystalsPerSec)}
|
||||
<span className="text-[9px] text-emerald-300/60">/s</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 主动脉冲 — rose */}
|
||||
<div className="rounded-lg border border-rose-400/30 bg-black/30 backdrop-blur p-2 flex items-center gap-1.5">
|
||||
<Zap className="h-3.5 w-3.5 text-rose-400 shrink-0" />
|
||||
<div className="min-w-0 leading-tight">
|
||||
<div className="text-[9px] uppercase tracking-wider text-rose-300/70 truncate">
|
||||
主动脉冲
|
||||
</div>
|
||||
<div className="text-sm font-mono tabular-nums text-rose-200 truncate">
|
||||
{formatNum(pulsePower)}
|
||||
{combo >= 1 && (
|
||||
<span className="text-[9px] text-rose-300/80"> ×{comboMult.toFixed(2)}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 当前连击 — amber,≥3 时高亮闪烁 */}
|
||||
<div
|
||||
className={`rounded-lg border bg-black/30 backdrop-blur p-2 flex items-center gap-1.5 ${
|
||||
comboHot ? "border-amber-400/70 animate-pulse" : "border-amber-400/30"
|
||||
}`}
|
||||
>
|
||||
<Flame
|
||||
className={`h-3.5 w-3.5 text-amber-400 shrink-0 ${
|
||||
comboHot ? "drop-shadow-[0_0_4px_rgba(251,191,36,0.7)]" : ""
|
||||
}`}
|
||||
/>
|
||||
<div className="min-w-0 leading-tight">
|
||||
<div className="text-[9px] uppercase tracking-wider text-amber-300/70 truncate">
|
||||
当前连击
|
||||
</div>
|
||||
<div
|
||||
className={`text-sm font-mono tabular-nums truncate ${
|
||||
comboHot ? "text-amber-200" : "text-amber-300/80"
|
||||
}`}
|
||||
>
|
||||
{combo}
|
||||
<span className="text-[9px] text-amber-300/60">/10</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 仓库容量 — fuchsia,≥90% 切 rose 警告色 + pulse */}
|
||||
<div
|
||||
className={`rounded-lg border bg-black/30 backdrop-blur p-2 flex items-center gap-1.5 ${
|
||||
warehouseWarn ? "border-rose-400/70 animate-pulse" : "border-fuchsia-400/30"
|
||||
}`}
|
||||
>
|
||||
<Database
|
||||
className={`h-3.5 w-3.5 shrink-0 ${
|
||||
warehouseWarn ? "text-rose-400" : "text-fuchsia-400"
|
||||
}`}
|
||||
/>
|
||||
<div className="min-w-0 leading-tight">
|
||||
<div
|
||||
className={`text-[9px] uppercase tracking-wider truncate ${
|
||||
warehouseWarn ? "text-rose-300/80" : "text-fuchsia-300/70"
|
||||
}`}
|
||||
>
|
||||
仓库容量
|
||||
</div>
|
||||
<div
|
||||
className={`text-sm font-mono tabular-nums truncate ${
|
||||
warehouseWarn ? "text-rose-200" : "text-fuchsia-200"
|
||||
}`}
|
||||
>
|
||||
{formatNum(crystals)}
|
||||
<span
|
||||
className={`text-[9px] ${
|
||||
warehouseWarn ? "text-rose-300/70" : "text-fuchsia-300/60"
|
||||
}`}
|
||||
>
|
||||
/{formatNum(crystalCap)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StatsPanel() {
|
||||
const s = useGameStore();
|
||||
const achCount = Object.values(s.achievements).filter(Boolean).length;
|
||||
|
||||
@@ -1,26 +1,168 @@
|
||||
"use client";
|
||||
// 回响星核 / Echo Nexus — 成就解锁通知消费者
|
||||
import { useEffect } from "react";
|
||||
// 回响星核 / Echo Nexus — 成就解锁通知(v0.9 全屏特效增强)
|
||||
// 工单 Issue #2 反馈"成就系统没看出来有什么用",改为居中全息弹窗 + 奖励数字弹出
|
||||
import { useEffect, useState } from "react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { useGameStore } from "@/store/gameStore";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { sfx } from "@/hooks/useAudio";
|
||||
import type { Achievement } from "@/lib/game/achievements";
|
||||
|
||||
interface NotificationItem {
|
||||
achievement: Achievement;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function AchievementNotifier() {
|
||||
const queue = useGameStore((s) => s._achievementQueue);
|
||||
const consume = useGameStore((s) => s.consumeAchievementQueue);
|
||||
const { toast } = useToast();
|
||||
const [notifications, setNotifications] = useState<NotificationItem[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (queue.length === 0) return;
|
||||
const items = consume();
|
||||
for (const a of items) {
|
||||
sfx("achievement");
|
||||
// v0.9:全屏居中特效通知
|
||||
const id = Date.now() + Math.random();
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setNotifications((prev) => [...prev, { achievement: a, id }]);
|
||||
// 4 秒后自动移除
|
||||
setTimeout(() => {
|
||||
setNotifications((prev) => prev.filter((n) => n.id !== id));
|
||||
}, 4000);
|
||||
// 同时保留底部 toast 作为日志
|
||||
toast({
|
||||
title: `🏆 成就解锁:${a.name}`,
|
||||
title: `成就解锁:${a.name}`,
|
||||
description: `${a.desc} 奖励:${a.rewardText}`,
|
||||
});
|
||||
}
|
||||
}, [queue, consume, toast]);
|
||||
|
||||
return null;
|
||||
if (notifications.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[120] pointer-events-none flex items-center justify-center">
|
||||
<AnimatePresence>
|
||||
{notifications.map((n, idx) => {
|
||||
const a = n.achievement;
|
||||
// 多个同时出现时垂直堆叠偏移
|
||||
const offset = (idx - (notifications.length - 1) / 2) * 140;
|
||||
return (
|
||||
<motion.div
|
||||
key={n.id}
|
||||
initial={{ opacity: 0, scale: 0.4, y: 40, rotateX: -30 }}
|
||||
animate={{ opacity: 1, scale: 1, y: offset, rotateX: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.6, y: -60 }}
|
||||
transition={{ type: "spring", stiffness: 280, damping: 22 }}
|
||||
className="absolute"
|
||||
style={{ transformOrigin: "center center" }}
|
||||
>
|
||||
<div
|
||||
className="relative rounded-2xl border-2 px-8 py-5 backdrop-blur-xl overflow-hidden"
|
||||
style={{
|
||||
borderColor: a.color,
|
||||
background: `linear-gradient(135deg, ${a.color}22, rgba(5,4,16,0.92))`,
|
||||
boxShadow: `0 0 60px ${a.color}66, 0 0 120px ${a.color}33, inset 0 0 30px ${a.color}11`,
|
||||
minWidth: 320,
|
||||
maxWidth: 420,
|
||||
}}
|
||||
>
|
||||
{/* 背景径向辉光 */}
|
||||
<div
|
||||
className="absolute -top-20 -right-20 h-40 w-40 rounded-full blur-3xl opacity-50"
|
||||
style={{ background: a.color }}
|
||||
/>
|
||||
{/* 旋转光线 */}
|
||||
<motion.div
|
||||
className="absolute inset-0 rounded-2xl opacity-20"
|
||||
style={{
|
||||
background: `conic-gradient(from 0deg, transparent, ${a.color}, transparent, ${a.color}, transparent)`,
|
||||
}}
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{ duration: 8, repeat: Infinity, ease: "linear" }}
|
||||
/>
|
||||
|
||||
<div className="relative flex items-center gap-4">
|
||||
{/* 图标徽章 */}
|
||||
<motion.div
|
||||
className="shrink-0 h-16 w-16 rounded-2xl flex items-center justify-center text-3xl"
|
||||
style={{
|
||||
background: `${a.color}33`,
|
||||
border: `2px solid ${a.color}`,
|
||||
boxShadow: `0 0 20px ${a.color}88, inset 0 0 12px ${a.color}44`,
|
||||
}}
|
||||
animate={{
|
||||
boxShadow: [
|
||||
`0 0 20px ${a.color}88, inset 0 0 12px ${a.color}44`,
|
||||
`0 0 40px ${a.color}cc, inset 0 0 20px ${a.color}66`,
|
||||
`0 0 20px ${a.color}88, inset 0 0 12px ${a.color}44`,
|
||||
],
|
||||
}}
|
||||
transition={{ duration: 2, repeat: Infinity }}
|
||||
>
|
||||
{a.icon}
|
||||
</motion.div>
|
||||
|
||||
{/* 文本 */}
|
||||
<div className="min-w-0 flex-1">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.15 }}
|
||||
className="text-[10px] font-mono uppercase tracking-[0.2em] mb-0.5"
|
||||
style={{ color: a.color }}
|
||||
>
|
||||
✦ Achievement Unlocked
|
||||
</motion.div>
|
||||
<motion.h3
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="text-lg font-bold truncate"
|
||||
style={{ color: a.color, textShadow: `0 0 12px ${a.color}66` }}
|
||||
>
|
||||
{a.name}
|
||||
</motion.h3>
|
||||
<motion.p
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.3 }}
|
||||
className="text-[11px] text-muted-foreground/90 truncate"
|
||||
>
|
||||
{a.desc}
|
||||
</motion.p>
|
||||
{/* 奖励条 */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 8 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.4 }}
|
||||
className="mt-1.5 inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-[10px] font-mono font-semibold"
|
||||
style={{
|
||||
background: `${a.color}22`,
|
||||
border: `1px solid ${a.color}55`,
|
||||
color: a.color,
|
||||
}}
|
||||
>
|
||||
▸ {a.rewardText}
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 进度条(倒计时) */}
|
||||
<motion.div
|
||||
className="absolute bottom-0 left-0 h-0.5"
|
||||
style={{ background: a.color }}
|
||||
initial={{ width: "100%" }}
|
||||
animate={{ width: "0%" }}
|
||||
transition={{ duration: 4, ease: "linear" }}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useGameStore } from "@/store/gameStore";
|
||||
import { formatNum } from "@/lib/game/config";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { sfx } from "@/hooks/useAudio";
|
||||
import { PULSE_WHISPERS, maybeWhisper } from "@/lib/game/narrative";
|
||||
|
||||
interface FloatNum {
|
||||
id: number;
|
||||
@@ -242,10 +243,18 @@ export function CrystalOrb() {
|
||||
setFloats((f) => f.filter((it) => it.id !== id));
|
||||
}, 900);
|
||||
if (res.combo >= 5 && res.combo % 5 === 0) {
|
||||
// v0.9 叙事融入:高连击时注入世界观低语
|
||||
const whisper = maybeWhisper(PULSE_WHISPERS, 0.6);
|
||||
toast({
|
||||
title: `×${res.combo} 连击!`,
|
||||
description: "谐振叠加,产能飙升。",
|
||||
description: whisper ? `「${whisper}」` : "谐振叠加,产能飙升。",
|
||||
});
|
||||
} else if (res.combo >= 3 && res.combo % 3 === 0) {
|
||||
// 3 连击时也有概率出现叙事
|
||||
const whisper = maybeWhisper(PULSE_WHISPERS, 0.3);
|
||||
if (whisper) {
|
||||
toast({ title: "低语", description: `「${whisper}」` });
|
||||
}
|
||||
}
|
||||
},
|
||||
[pulse, toast, triggerPulseEffect]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
// 回响星核 / Echo Nexus — 遗迹探险面板(v0.2 肉鸽系统)
|
||||
import { useState } from "react";
|
||||
// 回响星核 / Echo Nexus — 遗迹探险面板(v0.2 肉鸽系统,v0.9 工单修复)
|
||||
import { useState, useEffect } from "react";
|
||||
import { useGameStore } from "@/store/gameStore";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { sfx } from "@/hooks/useAudio";
|
||||
@@ -42,20 +42,30 @@ export function ExpeditionPanel() {
|
||||
const lastEnergyTick = useGameStore((s) => s.lastEnergyTick);
|
||||
const expeditionLog = useGameStore((s) => s.expeditionLog);
|
||||
const totalExpeditions = useGameStore((s) => s.totalExpeditions);
|
||||
const lastExpeditionSummary = useGameStore((s) => s.lastExpeditionSummary);
|
||||
// v0.8.1 动态能量恢复间隔(技术 + 探索力属性缩短)
|
||||
const regenIntervalSec = useGameStore((s) => computeEnergyRegenInterval(s));
|
||||
const startExpedition = useGameStore((s) => s.startExpedition);
|
||||
const resolveCurrentNode = useGameStore((s) => s.resolveCurrentNode);
|
||||
const advanceNode = useGameStore((s) => s.advanceNode);
|
||||
const abortExpedition = useGameStore((s) => s.abortExpedition);
|
||||
const dismissExpedition = useGameStore((s) => s.dismissExpedition);
|
||||
const { toast } = useToast();
|
||||
const [lastLog, setLastLog] = useState<string | null>(null);
|
||||
const [now, setNow] = useState(() => Date.now());
|
||||
// v0.9 工单修复:能量恢复实时倒计时(每秒刷新)
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => setNow(Date.now()), 1000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
// 能量恢复进度(v0.8.1 动态间隔)
|
||||
const now = Date.now();
|
||||
// 能量恢复进度(v0.8.1 动态间隔,v0.9 实时刷新)
|
||||
const regenMs = regenIntervalSec * 1000;
|
||||
const regenProgress = energy >= energyMax ? 100 : Math.min(100, ((now - lastEnergyTick) / regenMs) * 100);
|
||||
const elapsed = now - lastEnergyTick;
|
||||
const regenProgress = energy >= energyMax ? 100 : Math.min(100, (elapsed / regenMs) * 100);
|
||||
const regenBoosted = regenIntervalSec < EXPEDITION_CONFIG.energyRegenSec;
|
||||
const nextEnergyInSec = energy >= energyMax ? 0 : Math.max(0, Math.ceil((regenMs - elapsed) / 1000));
|
||||
const canStart = energy >= EXPEDITION_CONFIG.energyCost;
|
||||
|
||||
const handleStart = () => {
|
||||
const res = startExpedition();
|
||||
@@ -100,6 +110,9 @@ export function ExpeditionPanel() {
|
||||
|
||||
// ===== 无活跃探险:展示入口 =====
|
||||
if (!activeExpedition || activeExpedition.finished) {
|
||||
// v0.9 工单修复:如果探险刚结束(finished 且有摘要),显示结算面板
|
||||
const justFinished = activeExpedition?.finished && lastExpeditionSummary &&
|
||||
Date.now() - lastExpeditionSummary.finishedAt < 60000;
|
||||
return (
|
||||
<div className="flex flex-col gap-3 h-full">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -110,6 +123,40 @@ export function ExpeditionPanel() {
|
||||
<span className="text-[10px] text-muted-foreground">已探索 {totalExpeditions} 次</span>
|
||||
</div>
|
||||
|
||||
{/* v0.9 工单修复:上次探险结果摘要 */}
|
||||
{lastExpeditionSummary && (
|
||||
<div
|
||||
className={`rounded-xl border p-2.5 relative overflow-hidden ${
|
||||
lastExpeditionSummary.result === "victory"
|
||||
? "border-emerald-400/40 bg-emerald-950/20"
|
||||
: lastExpeditionSummary.result === "defeat"
|
||||
? "border-rose-400/40 bg-rose-950/20"
|
||||
: "border-amber-400/30 bg-amber-950/10"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-[11px] font-semibold flex items-center gap-1">
|
||||
{lastExpeditionSummary.result === "victory" ? "✦ 上次探险:胜利" : lastExpeditionSummary.result === "defeat" ? "✕ 上次探险:失败" : "→ 上次探险:撤退"}
|
||||
</span>
|
||||
<span className="text-[9px] text-muted-foreground font-mono">{lastExpeditionSummary.nodeCount} 节点</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2.5 text-[10px]">
|
||||
{lastExpeditionSummary.rewards.crystals > 0 && (
|
||||
<span className="text-emerald-300">+{formatNum(lastExpeditionSummary.rewards.crystals)} 晶体</span>
|
||||
)}
|
||||
{lastExpeditionSummary.rewards.insights > 0 && (
|
||||
<span className="text-amber-300">+{lastExpeditionSummary.rewards.insights} 洞见</span>
|
||||
)}
|
||||
{lastExpeditionSummary.rewards.contact > 0 && (
|
||||
<span className="text-fuchsia-300">+{lastExpeditionSummary.rewards.contact.toFixed(1)} 接触</span>
|
||||
)}
|
||||
{lastExpeditionSummary.rewards.crystals === 0 && lastExpeditionSummary.rewards.insights === 0 && (
|
||||
<span className="text-muted-foreground/60">无奖励</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 能量条 */}
|
||||
<div className="rounded-xl border border-amber-400/20 bg-amber-950/20 p-3">
|
||||
<div className="flex items-center justify-between mb-1.5">
|
||||
@@ -127,8 +174,10 @@ export function ExpeditionPanel() {
|
||||
value={regenProgress}
|
||||
className="h-1.5 bg-black/40 [&>div]:bg-gradient-to-r [&>div]:from-amber-500 [&>div]:to-yellow-300"
|
||||
/>
|
||||
<p className="text-[10px] text-muted-foreground/70 mt-1">
|
||||
下一点能量约 {Math.ceil((regenMs - (now - lastEnergyTick)) / 1000)}s 后恢复
|
||||
<p className="text-[10px] text-muted-foreground/70 mt-1 flex items-center gap-1">
|
||||
<span>下一点能量</span>
|
||||
<span className="text-amber-300 font-mono font-semibold">{nextEnergyInSec}s</span>
|
||||
<span>后恢复</span>
|
||||
{regenBoosted && (
|
||||
<span className="text-emerald-400/80 ml-1">⚡ {regenIntervalSec.toFixed(0)}s/点 (已加速)</span>
|
||||
)}
|
||||
@@ -140,35 +189,32 @@ export function ExpeditionPanel() {
|
||||
</div>
|
||||
|
||||
{/* 出发按钮 */}
|
||||
<div className="flex-1 flex flex-col items-center justify-center gap-4 rounded-2xl border border-dashed border-amber-400/20 bg-black/30 p-6 relative overflow-hidden">
|
||||
<div className="flex-1 flex flex-col items-center justify-center gap-3 rounded-2xl border border-dashed border-amber-400/20 bg-black/30 p-4 relative overflow-hidden">
|
||||
<div className="absolute -top-10 -right-10 h-32 w-32 rounded-full bg-amber-500/10 blur-2xl" />
|
||||
<div className="relative">
|
||||
<div className="h-20 w-20 rounded-full bg-gradient-to-br from-amber-500/30 to-rose-500/20 flex items-center justify-center mx-auto" style={{ boxShadow: "0 0 30px rgba(251,191,36,0.3)" }}>
|
||||
<Rocket className="h-9 w-9 text-amber-300" />
|
||||
<div className={`h-16 w-16 rounded-full bg-gradient-to-br from-amber-500/30 to-rose-500/20 flex items-center justify-center mx-auto ${canStart ? "animate-pulse" : ""}`} style={{ boxShadow: "0 0 30px rgba(251,191,36,0.3)" }}>
|
||||
<Rocket className="h-7 w-7 text-amber-300" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center space-y-1">
|
||||
<p className="text-sm font-medium text-amber-100">深入以太遗迹</p>
|
||||
<p className="text-[11px] text-muted-foreground/80 max-w-[220px]">
|
||||
派出探险队进入程序化生成的遗迹路径,沿途遭遇战斗、宝藏、抉择与解谜,击败终点 BOSS 获取丰厚奖励。
|
||||
程序化生成的遗迹路径,沿途遭遇战斗、宝藏、抉择与解谜,击败终点 BOSS 获取丰厚奖励。
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleStart}
|
||||
disabled={energy < EXPEDITION_CONFIG.energyCost}
|
||||
disabled={!canStart}
|
||||
className="bg-gradient-to-r from-amber-600 to-rose-500 hover:from-amber-500 hover:to-rose-400 text-white border-0"
|
||||
>
|
||||
<Rocket className="h-4 w-4 mr-1.5" />
|
||||
出发(消耗 {EXPEDITION_CONFIG.energyCost} 能量)
|
||||
{canStart ? `出发(消耗 ${EXPEDITION_CONFIG.energyCost} 能量)` : `能量不足(${nextEnergyInSec}s 后恢复)`}
|
||||
</Button>
|
||||
{energy < EXPEDITION_CONFIG.energyCost && (
|
||||
<p className="text-[10px] text-rose-300/80">能量不足,请等待恢复</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 探险日志 */}
|
||||
{expeditionLog.length > 0 && (
|
||||
<div className="rounded-xl border border-white/5 bg-black/20 p-2 max-h-32 overflow-y-auto echo-scroll">
|
||||
<div className="rounded-xl border border-white/5 bg-black/20 p-2 max-h-28 overflow-y-auto echo-scroll">
|
||||
<div className="text-[10px] text-muted-foreground/60 mb-1 px-1">最近探险记录</div>
|
||||
{expeditionLog.slice(0, 4).map((entry, i) => (
|
||||
<div key={i} className="text-[10px] text-muted-foreground/70 px-1 py-0.5 border-b border-white/5 last:border-0">
|
||||
@@ -178,6 +224,18 @@ export function ExpeditionPanel() {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* v0.9 工单修复:刚结束的探险,显示"返回"按钮 */}
|
||||
{justFinished && (
|
||||
<Button
|
||||
onClick={() => dismissExpedition()}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 text-[11px] border-amber-400/30 text-amber-200"
|
||||
>
|
||||
收起结算,准备下次出发
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useGameStore } from "@/store/gameStore";
|
||||
import { TECH_TREE, TECH_BRANCH_META, formatNum } from "@/lib/game/config";
|
||||
import { sfx } from "@/hooks/useAudio";
|
||||
import { TECH_LORE } from "@/lib/game/narrative";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -58,10 +59,14 @@ export function TechTree() {
|
||||
<span className="text-xs font-medium" style={{ color }}>
|
||||
{meta.name}
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground/70">
|
||||
<span className="text-[10px] text-muted-foreground/70 truncate flex-1">
|
||||
{meta.desc}
|
||||
</span>
|
||||
</div>
|
||||
{/* v0.9 叙事融入:每分支的以太族遗产描述 */}
|
||||
<p className="text-[9px] italic text-muted-foreground/50 px-1 mb-1.5 truncate">
|
||||
「{TECH_LORE[b] ?? ""}」
|
||||
</p>
|
||||
<div className="grid gap-1.5">
|
||||
{nodes.map((node) => {
|
||||
const owned = (tech[node.id] ?? 0) >= 1;
|
||||
|
||||
@@ -16,7 +16,7 @@ const ToastViewport = React.forwardRef<
|
||||
<ToastPrimitives.Viewport
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
||||
"fixed top-14 z-[90] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
ToastProps,
|
||||
} from "@/components/ui/toast"
|
||||
|
||||
const TOAST_LIMIT = 1
|
||||
const TOAST_LIMIT = 3
|
||||
const TOAST_REMOVE_DELAY = 1000000
|
||||
|
||||
type ToasterToast = ToastProps & {
|
||||
|
||||
@@ -90,10 +90,10 @@ export const ACHIEVEMENTS: Achievement[] = [
|
||||
{
|
||||
id: "ach_tech_all",
|
||||
name: "全谱精通",
|
||||
desc: "解锁全部 12 项技术",
|
||||
desc: "解锁全部 20 项技术",
|
||||
icon: "⬡",
|
||||
color: "#e879f9",
|
||||
check: (s) => Object.values(s.tech).filter((v) => v > 0).length >= 12,
|
||||
check: (s) => Object.values(s.tech).filter((v) => v > 0).length >= 20,
|
||||
reward: { crystalsPerSecPct: 15, insightPct: 15 },
|
||||
rewardText: "产能 +15% · 洞见 +15%",
|
||||
},
|
||||
|
||||
+77
-4
@@ -10,7 +10,7 @@ import type {
|
||||
export const INITIAL_STATE = {
|
||||
crystals: 0,
|
||||
insights: 0,
|
||||
energy: 3,
|
||||
energy: 5,
|
||||
contact: 0,
|
||||
crystalsPerSec: 0.4,
|
||||
crystalCap: 50,
|
||||
@@ -26,10 +26,11 @@ export const INITIAL_STATE = {
|
||||
activePuzzle: null,
|
||||
activeExpedition: null,
|
||||
expeditionLog: [],
|
||||
energyMax: 5,
|
||||
energyMax: 8,
|
||||
lastEnergyTick: Date.now(),
|
||||
totalExpeditions: 0,
|
||||
bossKills: 0,
|
||||
lastExpeditionSummary: null as import("./types").GameState["lastExpeditionSummary"],
|
||||
achievements: {},
|
||||
activeTide: null,
|
||||
lastTideEnd: 0,
|
||||
@@ -124,7 +125,7 @@ export const COLOR_VISUAL: Record<
|
||||
fuchsia: { hex: "#e879f9", glow: "rgba(232,121,249,0.55)", label: "紫" },
|
||||
};
|
||||
|
||||
/** 技术树:4 分支 × 3 级 = 12 节点 */
|
||||
/** 技术树:4 分支 × 5 级 = 20 节点(v0.9 工单 #2 扩充:12→20) */
|
||||
export const TECH_TREE: TechNode[] = [
|
||||
// 采矿分支
|
||||
{
|
||||
@@ -154,6 +155,24 @@ export const TECH_TREE: TechNode[] = [
|
||||
cost: 120,
|
||||
effect: { kind: "crystalsPerSec", value: 5 },
|
||||
},
|
||||
{
|
||||
id: "min_4",
|
||||
branch: "mining",
|
||||
level: 4,
|
||||
name: "量子采掘矩阵",
|
||||
desc: "晶体/秒 +12,仓库上限 +800",
|
||||
cost: 400,
|
||||
effect: { kind: "crystalsPerSec", value: 12 },
|
||||
},
|
||||
{
|
||||
id: "min_5",
|
||||
branch: "mining",
|
||||
level: 5,
|
||||
name: "戴森星核",
|
||||
desc: "晶体/秒 +30,仓库上限 +2000",
|
||||
cost: 1200,
|
||||
effect: { kind: "crystalsPerSec", value: 30 },
|
||||
},
|
||||
// 解码分支
|
||||
{
|
||||
id: "dec_1",
|
||||
@@ -182,7 +201,25 @@ export const TECH_TREE: TechNode[] = [
|
||||
cost: 200,
|
||||
effect: { kind: "autoDecode", value: 1 },
|
||||
},
|
||||
// 探险分支(v0.2:探险力/生命/能量上限/产能)
|
||||
{
|
||||
id: "dec_4",
|
||||
branch: "decoding",
|
||||
level: 4,
|
||||
name: "谐振放大器",
|
||||
desc: "主动脉冲产出 +8",
|
||||
cost: 500,
|
||||
effect: { kind: "pulsePower", value: 8 },
|
||||
},
|
||||
{
|
||||
id: "dec_5",
|
||||
branch: "decoding",
|
||||
level: 5,
|
||||
name: "全息解码核心",
|
||||
desc: "自动解码扩展至 T2 晶体,解码步数 +3",
|
||||
cost: 1500,
|
||||
effect: { kind: "decodeSteps", value: 3 },
|
||||
},
|
||||
// 探险分支(v0.2:探险力/生命/能量上限/产能;v0.9:level 4/5 高级探险力+能量恢复)
|
||||
{
|
||||
id: "exp_1",
|
||||
branch: "expedition",
|
||||
@@ -210,6 +247,24 @@ export const TECH_TREE: TechNode[] = [
|
||||
cost: 180,
|
||||
effect: { kind: "contactRate", value: 0.5 },
|
||||
},
|
||||
{
|
||||
id: "exp_4",
|
||||
branch: "expedition",
|
||||
level: 4,
|
||||
name: "虚空航标",
|
||||
desc: "探险力 +12,探险生命 +30,能量恢复 +25%",
|
||||
cost: 450,
|
||||
effect: { kind: "crystalCap", value: 400 },
|
||||
},
|
||||
{
|
||||
id: "exp_5",
|
||||
branch: "expedition",
|
||||
level: 5,
|
||||
name: "维度跃迁引擎",
|
||||
desc: "探险力 +25,探险生命 +50,能量恢复 +30%",
|
||||
cost: 1400,
|
||||
effect: { kind: "crystalCap", value: 600 },
|
||||
},
|
||||
// 叙事分支
|
||||
{
|
||||
id: "nar_1",
|
||||
@@ -238,6 +293,24 @@ export const TECH_TREE: TechNode[] = [
|
||||
cost: 160,
|
||||
effect: { kind: "insightMult", value: 0.6 },
|
||||
},
|
||||
{
|
||||
id: "nar_4",
|
||||
branch: "narrative",
|
||||
level: 4,
|
||||
name: "以太低语",
|
||||
desc: "洞见获取 +100%",
|
||||
cost: 500,
|
||||
effect: { kind: "insightMult", value: 1.0 },
|
||||
},
|
||||
{
|
||||
id: "nar_5",
|
||||
branch: "narrative",
|
||||
level: 5,
|
||||
name: "文明回响",
|
||||
desc: "接触进度转化率 +80%,洞见获取 +150%",
|
||||
cost: 1600,
|
||||
effect: { kind: "insightMult", value: 1.5 },
|
||||
},
|
||||
];
|
||||
|
||||
/** 技术分支元信息 */
|
||||
|
||||
@@ -79,6 +79,15 @@ export function recomputeStats(state: Partial<GameState>): {
|
||||
}
|
||||
}
|
||||
|
||||
// v0.9 工单 #2:多效果节点的次效果(desc 中描述但 effect.kind 只能承载一个)
|
||||
// 采矿分支 desc 承诺的仓库上限加成(同时补齐 min_2/min_3 旧 desc 文案)
|
||||
if (tech.min_2) crystalCap += 100;
|
||||
if (tech.min_3) crystalCap += 300;
|
||||
if (tech.min_4) crystalCap += 800;
|
||||
if (tech.min_5) crystalCap += 2000;
|
||||
// 叙事分支 nar_5 文明回响:接触进度转化率 +80%(与 insightMult +150% 并存)
|
||||
if (tech.nar_5) contactRateMult += 0.8;
|
||||
|
||||
// 飞升蓝图加成(+ 星图「蓝图回响」额外加成)
|
||||
const bpAllPct = cm.perBlueprintAllStatsPct / 100;
|
||||
crystalsPerSec *= 1 + (bp * (PRESTIGE.perBlueprint.crystalsPerSecMult + bpAllPct));
|
||||
|
||||
@@ -39,10 +39,11 @@ export const EXPEDITION_CONFIG = {
|
||||
* v0.8.1 平衡:scale 8→4,floor 0.25→0.35,让基础探险力也能有合理胜率 */
|
||||
combatDifficultyScale: 4,
|
||||
combatWinRateFloor: 0.35,
|
||||
/** 能量恢复基础间隔(秒),可被技术/属性缩短 */
|
||||
energyRegenSec: 45,
|
||||
/** 能量恢复基础间隔(秒),可被技术/属性缩短
|
||||
* v0.9 工单修复:45→20,解决「探险只能一次」体验问题 */
|
||||
energyRegenSec: 20,
|
||||
/** 能量恢复最短间隔(秒,技术+属性全满时) */
|
||||
energyRegenMinSec: 12,
|
||||
energyRegenMinSec: 8,
|
||||
};
|
||||
|
||||
/** 节点类型权重(boss 固定末位,其余按权重随机) */
|
||||
@@ -181,11 +182,13 @@ export function generateExpedition(
|
||||
/** 计算探险力(由技术树 + 飞升蓝图 + 星图天赋) */
|
||||
export function computeExpeditionPower(state: GameState): number {
|
||||
let power = EXPEDITION_CONFIG.basePower;
|
||||
// 探险分支技术加成
|
||||
// 探险分支技术加成(v0.9 扩充:exp_4 +12,exp_5 +25)
|
||||
const exp1 = state.tech?.exp_1 ?? 0;
|
||||
const exp2 = state.tech?.exp_2 ?? 0;
|
||||
const exp3 = state.tech?.exp_3 ?? 0;
|
||||
power += exp1 * 3 + exp2 * 5 + exp3 * 8;
|
||||
const exp4 = state.tech?.exp_4 ?? 0;
|
||||
const exp5 = state.tech?.exp_5 ?? 0;
|
||||
power += exp1 * 3 + exp2 * 5 + exp3 * 8 + exp4 * 12 + exp5 * 25;
|
||||
// 飞升蓝图加成
|
||||
power *= 1 + (state.blueprints?.length ?? 0) * 0.08;
|
||||
// 飞升周目加成
|
||||
@@ -200,6 +203,9 @@ export function computeExpeditionPower(state: GameState): number {
|
||||
export function computeExpeditionHp(state: GameState): number {
|
||||
let hp = EXPEDITION_CONFIG.baseHp;
|
||||
hp += (state.tech?.exp_2 ?? 0) * 20;
|
||||
// v0.9 扩充:exp_4 +30,exp_5 +50
|
||||
hp += (state.tech?.exp_4 ?? 0) * 30;
|
||||
hp += (state.tech?.exp_5 ?? 0) * 50;
|
||||
hp += (state.ascensions ?? 0) * 10;
|
||||
// 星图「维生护盾」加成
|
||||
const cm = constellationBonuses(state.constellation ?? []);
|
||||
@@ -366,13 +372,16 @@ export function advanceExpedition(expedition: Expedition): ExpeditionResult {
|
||||
}
|
||||
|
||||
/** 计算实际能量恢复间隔(秒),由技术树 + 角色属性缩短
|
||||
* v0.8.1:exp_2 解锁 -30%,exp_3 解锁 -20%,探索力属性 -最高30%,下限 12s */
|
||||
* v0.8.1:exp_2 解锁 -30%,exp_3 解锁 -20%,探索力属性 -最高30%,下限 12s
|
||||
* v0.9 扩充:exp_4 加速 25%(×0.75),exp_5 加速 30%(×0.70),下限 8s */
|
||||
export function computeEnergyRegenInterval(state: GameState): number {
|
||||
const base = EXPEDITION_CONFIG.energyRegenSec;
|
||||
let mult = 1;
|
||||
// 技术:遗迹图谱(exp_2)+ 维度信标(exp_3)
|
||||
// 技术:遗迹图谱(exp_2)+ 维度信标(exp_3)+ 虚空航标(exp_4)+ 维度跃迁引擎(exp_5)
|
||||
if (state.tech?.exp_2) mult *= 0.7;
|
||||
if (state.tech?.exp_3) mult *= 0.8;
|
||||
if (state.tech?.exp_4) mult *= 0.75;
|
||||
if (state.tech?.exp_5) mult *= 0.7;
|
||||
// 角色属性:探索力(exploration)每点缩短少量,高探索力最高 -30%
|
||||
const exploration = state.attributes?.exploration ?? 0;
|
||||
const explorationBonus = exploration >= 50
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// 回响星核 / Echo Nexus — 叙事氛围文本池(v0.9 工单修复)
|
||||
// 工单 Issue #2 反馈"很多东西都没靠着世界观去写,像是为了做游戏而做的一样"
|
||||
// 本模块为各系统交互注入叙事碎片,让世界观渗透到每个角落
|
||||
|
||||
/** 脉冲扫描时随机触发的氛围低语(连击越高出现概率越大) */
|
||||
export const PULSE_WHISPERS: string[] = [
|
||||
"晶核深处传来一阵微弱的震颤…",
|
||||
"以太族的余响在谐振中回荡。",
|
||||
"你听见了一句无法辨认的低语。",
|
||||
"星海的寂静被你的脉冲短暂打破。",
|
||||
"晶体表面的纹路闪烁,像是某种回应。",
|
||||
"回响核心记录着每一次触碰。",
|
||||
"虚空深处,有什么在倾听。",
|
||||
"谐振频率与你的脉冲产生了共鸣。",
|
||||
"这是以太族留下的第一道印记。",
|
||||
"晶体内部的光,比星辰更古老。",
|
||||
"你的脉冲唤醒了一段沉睡的频率。",
|
||||
"维度薄膜因你的触碰而微微颤动。",
|
||||
"采矿不是掠夺,是聆听。",
|
||||
"每一颗晶体,都是一封跨越时间的信。",
|
||||
"以太族信任你,所以留下了这些。",
|
||||
];
|
||||
|
||||
/** 解码成功时的叙事碎片(按解码次数递进解锁更深层的叙事) */
|
||||
export const DECODE_ECHOES: string[] = [
|
||||
"一段记忆在你的解码中苏醒…",
|
||||
"谐振序列被还原,低语化为可读的符文。",
|
||||
"你触碰到了以太族思维的一角。",
|
||||
"解码完成的瞬间,你看见了他们的星海。",
|
||||
"记忆晶体释放出封存了万年的画面。",
|
||||
"这不仅是数据,是一段被编码的经历。",
|
||||
"以太族的语言不是文字,是共振本身。",
|
||||
"你读懂了这句话时,接触便已开始。",
|
||||
"晶体褪去外壳,露出内核中的回响。",
|
||||
"解码,是以太族留给后来者的资格证明。",
|
||||
"你的思维与晶体中的残响短暂重合。",
|
||||
"一段文明的碎片在你手中重组。",
|
||||
];
|
||||
|
||||
/** 技术解锁时的叙事(每分支一段通用叙事) */
|
||||
export const TECH_LORE: Record<string, string> = {
|
||||
mining: "以太族从不掠夺星海,他们与矿脉共振,让晶体自愿献出光芒。",
|
||||
decoding: "谐振法则是以太族的核心遗产——思维可被编码为共振序列。",
|
||||
expedition: "他们留下的遗迹不是废墟,是故意设置的试炼场。",
|
||||
narrative: "记忆校音,是以太族赋予后来者的第一项礼物。",
|
||||
};
|
||||
|
||||
/** 探险节点事件额外的叙事前缀 */
|
||||
export const EXPEDITION_NARRATIVE: Record<string, string> = {
|
||||
combat: "以太族的守卫残影仍在执行万年前的指令。",
|
||||
treasure: "这些宝藏是以太族特意留下的补给。",
|
||||
choice: "分岔甬道是他们对后来者的考验。",
|
||||
puzzle: "谐振锁的答案,藏在以太族的思维模式里。",
|
||||
rest: "这处休憩节点,是以太族留给疲惫旅人的礼物。",
|
||||
boss: "终焉之核是以太族离去前留下的最后一道试炼。",
|
||||
};
|
||||
|
||||
/** 飞升时的叙事 */
|
||||
export const PRESTIGE_ECHOES: string[] = [
|
||||
"你的意识与以太族的残响交汇,维度薄膜被穿透…",
|
||||
"飞升不是结束,是与更高处的他们相会。",
|
||||
"你褪去了这一周目的形态,回响却永存。",
|
||||
"以太族在更高处等你,已等候了万年。",
|
||||
"接触完成。你成为了他们等待的回应。",
|
||||
];
|
||||
|
||||
/** 随机取一条叙事文本 */
|
||||
export function pickWhisper(pool: string[], seed?: number): string {
|
||||
if (pool.length === 0) return "";
|
||||
const idx = seed !== undefined
|
||||
? Math.abs(Math.floor(seed)) % pool.length
|
||||
: Math.floor(Math.random() * pool.length);
|
||||
return pool[idx];
|
||||
}
|
||||
|
||||
/** 按概率返回一条叙事(probability 0-1) */
|
||||
export function maybeWhisper(pool: string[], probability: number): string | null {
|
||||
if (Math.random() < probability) {
|
||||
return pickWhisper(pool);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -125,6 +125,13 @@ export interface GameState {
|
||||
lastEnergyTick: number;
|
||||
totalExpeditions: number;
|
||||
bossKills: number; // 累计击败 BOSS 数(跨周目)
|
||||
/** v0.9 工单修复:上次探险结果摘要,用于入口界面展示 */
|
||||
lastExpeditionSummary: {
|
||||
result: "victory" | "defeat" | "abort";
|
||||
rewards: { crystals: number; insights: number; contact: number };
|
||||
nodeCount: number;
|
||||
finishedAt: number;
|
||||
} | null;
|
||||
|
||||
// 成就
|
||||
achievements: Record<string, boolean>; // achievementId -> unlocked
|
||||
|
||||
+37
-3
@@ -127,6 +127,8 @@ interface GameActions {
|
||||
resolveCurrentNode: () => ExpeditionResult | null;
|
||||
advanceNode: () => void;
|
||||
abortExpedition: () => void;
|
||||
/** v0.9 工单修复:手动关闭已结束的探险,回到入口 */
|
||||
dismissExpedition: () => void;
|
||||
|
||||
// 技术
|
||||
buyTech: (techId: string) => boolean;
|
||||
@@ -778,12 +780,17 @@ export const useGameStore = create<Store>()(
|
||||
const tideIntervalMult = tideModEarly.autoDecodeIntervalMult ?? 1;
|
||||
const interval = Math.max(5000, baseInterval * am.autoDecodeIntervalMult * tideIntervalMult);
|
||||
if (now - s._lastAutoDecode < interval) return;
|
||||
// 找一颗 T1 晶体自动解码
|
||||
const idx = s.pendingCrystals.findIndex((c) => c.tier === 1);
|
||||
// 找一颗 T1 晶体自动解码;v0.9 dec_5「全息解码核心」解锁后可自动解码 T2
|
||||
let autoTier: CrystalTier = 1;
|
||||
let idx = s.pendingCrystals.findIndex((c) => c.tier === 1);
|
||||
if (idx < 0 && s.tech?.dec_5) {
|
||||
idx = s.pendingCrystals.findIndex((c) => c.tier === 2);
|
||||
autoTier = 2;
|
||||
}
|
||||
if (idx < 0) return;
|
||||
const crystal = s.pendingCrystals[idx];
|
||||
const tideMod = getTideModifiers(s.activeTide);
|
||||
const base = decodeRewards(1, s.insightMult, s.contactRateMult);
|
||||
const base = decodeRewards(autoTier, s.insightMult, s.contactRateMult);
|
||||
const finalMult = tideMod.decodeRewardMult * cm.decodeRewardMult;
|
||||
const rewards = {
|
||||
crystals: Math.round(base.crystals * finalMult),
|
||||
@@ -923,6 +930,17 @@ export const useGameStore = create<Store>()(
|
||||
exp.finished = true;
|
||||
}
|
||||
|
||||
// v0.9 工单修复:探险结束时记录摘要,用于入口界面展示
|
||||
let lastExpeditionSummary = s.lastExpeditionSummary ?? null;
|
||||
if (result.ended && (result.endReason === "victory" || result.endReason === "defeat")) {
|
||||
lastExpeditionSummary = {
|
||||
result: result.endReason,
|
||||
rewards: { ...exp.rewards },
|
||||
nodeCount: exp.nodes.length,
|
||||
finishedAt: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
// v0.4 编年史:击破 BOSS 时累计计数
|
||||
let bossKills = s.bossKills ?? 0;
|
||||
let bossKilledThisNode = false;
|
||||
@@ -979,6 +997,7 @@ export const useGameStore = create<Store>()(
|
||||
bossKills,
|
||||
attributes: newAttributes,
|
||||
attributeProgress: newProgress,
|
||||
lastExpeditionSummary,
|
||||
...(statsNeedResync
|
||||
? syncStats({ tech: s.tech, blueprints: s.blueprints, achievements: s.achievements, activeTide: s.activeTide, constellation: s.constellation, attributes: newAttributes })
|
||||
: {}),
|
||||
@@ -1017,12 +1036,27 @@ export const useGameStore = create<Store>()(
|
||||
rewards: "",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
// v0.9 工单修复:记录上次探险摘要,用于入口展示
|
||||
const summary = {
|
||||
result: "abort" as const,
|
||||
rewards: { ...exp.rewards },
|
||||
nodeCount: exp.nodes.length,
|
||||
finishedAt: Date.now(),
|
||||
};
|
||||
set({
|
||||
activeExpedition: exp,
|
||||
expeditionLog: [logEntry, ...s.expeditionLog].slice(0, 30),
|
||||
lastExpeditionSummary: summary,
|
||||
});
|
||||
},
|
||||
|
||||
// v0.9 工单修复:手动关闭已结束探险,回到入口
|
||||
dismissExpedition: () => {
|
||||
const s = get();
|
||||
if (!s.activeExpedition || !s.activeExpedition.finished) return;
|
||||
set({ activeExpedition: null });
|
||||
},
|
||||
|
||||
doPrestige: () => {
|
||||
const s = get();
|
||||
if (s.contact < CONTACT.prestigeMin) return null;
|
||||
|
||||
@@ -0,0 +1,730 @@
|
||||
1→# 回响星核 / Echo Nexus — 开发工作日志
|
||||
2→
|
||||
3→> 持续性任务的工作交接文档。每个阶段更新,避免进度丢失。
|
||||
4→
|
||||
5→---
|
||||
6→
|
||||
7→## 一、项目当前状态描述 / 判断
|
||||
8→
|
||||
9→### 概况
|
||||
10→- **项目**:回响星核 / Echo Nexus — 深空考古放置策略游戏
|
||||
11→- **一句话**:自治无人机采矿 → 解码记忆晶体(原创共振谜题)→ 拼凑碎片叙事 → 飞升多周目。差异化:解码谜题驱动叙事涌现,全息晶体 + 深空粒子美学。
|
||||
12→- **当前版本**:**v0.7**(CrystalOrb Canvas 粒子系统 + 角色属性系统)
|
||||
13→- **在线游玩**:https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
14→- **仓库**:https://git.atdunbg.xyz/Super_Z/echo-nexus
|
||||
15→- **技术栈**:Next.js 16 (App Router) + TypeScript + Tailwind + shadcn/ui + Canvas 2D + Zustand + Web Audio API
|
||||
16→- **定时任务**:每 15 分钟一次 `webDevReview`(`fixed_rate` + `"900"` 秒,priority=10,job_id 228266)。正常完成不会被删除,无需自持续机制。
|
||||
17→
|
||||
18→### 状态判断
|
||||
19→- dev 服务器运行正常(HTTP 200,编译 < 250ms)
|
||||
20→- v0.7 两大新功能已完成:CrystalOrb Canvas 粒子系统升级(VLM 8/10)+ 角色属性系统(VLM 7/10)
|
||||
21→- 系统总体稳定,无阻塞性 bug,可继续推进新功能
|
||||
22→
|
||||
23→### 已完成版本里程碑(精简)
|
||||
24→| 版本 | 核心内容 |
|
||||
25→|------|---------|
|
||||
26→| v0.1 | MVP:放置采矿 + 解码共振谜题 + 技术树 + 记忆图谱 + 飞升 + 统计 |
|
||||
27→| v0.1.1 | 解码可解性修复(路径构造法生成器,100% 可解率)|
|
||||
28→| v0.2 | 遗迹探险肉鸽系统(能量/探险力/6 节点/程序化路径/BOSS)|
|
||||
29→| v0.2.1 | 程序化音频(15 种音效)+ 14 项成就 + 视觉打磨 |
|
||||
30→| v0.3 | 星潮事件系统(6 种星潮 + 全屏叠层 + 程序化音效)|
|
||||
31→| v0.3.1 | 星图天文台元进程(6 类 × 3 = 18 天赋 + 飞升后 3 选 1 draft + Canvas 星图)|
|
||||
32→| v0.4 | 回响编年史(5 纪元循环命名 + 模板化叙事 + 时间轴 UI + 6 项新成就 + 飞升 BUG 修复)|
|
||||
33→| v0.5 | 深空信标(每日挑战 + 本地排行榜 Top20 + 7 标签页 + 编年史历史 BUG 修复)|
|
||||
34→| v0.5.1 | 静态部署 Gitea Pages + 新手教程系统(7 步聚光灯引导)+ UI 间距优化 |
|
||||
35→| v0.5.2 | 离线收益报告弹窗 + 标签页 UI 重设计 + persist rehydrate 竞态修复 |
|
||||
36→| v0.6 | 深空巡航 Canvas 2D 实时玩法 + UI 偏移重叠修复 |
|
||||
37→| **v0.7** | **CrystalOrb Canvas 粒子系统升级 + 角色属性系统(四维)** |
|
||||
38→
|
||||
39→### 核心系统清单(8 大系统)
|
||||
40→1. **放置采矿** — 中央晶体球 + 主动脉冲 + 连击加成(`CrystalOrb.tsx`)
|
||||
41→2. **谐振解码** — 原创路径谜题,路径构造法 100% 可解(`DecodeArray.tsx` + `engine.ts`)
|
||||
42→3. **技术树** — 三层科技解锁,提升产能/解码/探险(`TechTree.tsx`)
|
||||
43→4. **遗迹探险** — 肉鸽系统,6 种节点 + 程序化路径 + BOSS(`ExpeditionPanel.tsx` + `expedition.ts`)
|
||||
44→5. **星潮事件** — 6 种动态事件,为放置循环注入变化(`StarTide.tsx` + `starTide.ts`)
|
||||
45→6. **星图天文台** — 飞升后 3 选 1 天赋 draft,跨周目永久生效,18 个天赋(`ConstellationPanel.tsx` + `constellation.ts`)
|
||||
46→7. **回响编年史** — 跨周目叙事时间轴,5 纪元循环命名(`ChronicleDialog.tsx` + `chronicle.ts`)
|
||||
47→8. **深空信标** — 每日挑战 + 本地排行榜 Top20(`BeaconPanel.tsx` + `beacon.ts`)
|
||||
48→9. **深空巡航** — Canvas 2D 实时玩法,飞船操控/陨石躲避/星门通关(`CruiseMode.tsx` + `cruise.ts`)【v0.6】
|
||||
49→10. **角色属性系统** — 四维属性(探索力/智慧/勇气/灵感),飞升获得属性点,影响所有系统(`AttributesPanel.tsx` + `attributes.ts`)【v0.7 新增】
|
||||
50→
|
||||
51→---
|
||||
52→
|
||||
53→## 二、当前目标 / 已完成的修改 / 验证结果
|
||||
54→
|
||||
55→### v0.7 CrystalOrb Canvas 粒子系统升级(已完成)
|
||||
56→**动机**:P0 优先级 — 将中央晶体球从 CSS 动画升级为 Canvas 粒子视觉盛宴,提升视觉震撼。
|
||||
57→
|
||||
58→**重写文件**:`src/components/game/CrystalOrb.tsx`
|
||||
59→- 从纯 CSS 动画升级为 Canvas 2D 粒子系统
|
||||
60→- **多层粒子**:
|
||||
61→ - 环绕能量粒子(3层14/10/8个,emerald/fuchsia/rose三色,不同速度方向环绕晶核,带拖尾)
|
||||
62→ - 环境星尘(40个,缓慢漂移 + 闪烁)
|
||||
63→ - 点击爆发粒子(10-30个径向发散,颜色随连击等级变色)
|
||||
64→ - 冲击波环(点击触发1-3层错峰扩散,连击≥3/5解锁更多层)
|
||||
65→- **晶核升级**:径向渐变辉光 + 3层六边形纹理旋转 + 高光 + 鼠标视差偏移
|
||||
66→- **呼吸动画**:晶核 + 外层辉光随时间呼吸(sin波)
|
||||
67→- **进度环**:SVG渐变环(emerald→fuchsia→rose)保留
|
||||
68→- **交互保留**:点击脉冲、连击Toast、浮动数字、音效、`data-tut="crystal-orb"` 锚点
|
||||
69→- **性能**:DPR cap 2,ResizeObserver 自适应,requestAnimationFrame 60fps
|
||||
70→
|
||||
71→**QA 验证**(agent-browser + VLM):
|
||||
72→- VLM 视觉评分 **8/10**:晶体球清晰可见,多层辉光,环绕粒子动态自然,无渲染问题
|
||||
73→- 点击交互:冲击波环 ✅ + 爆发粒子 ✅,评分 7/10
|
||||
74→- lint 零错误;HTTP 200
|
||||
75→
|
||||
76→### v0.7 角色属性系统(已完成)
|
||||
77→**动机**:P1 优先级 — 增加RPG深度,四维属性影响所有游戏系统。
|
||||
78→
|
||||
79→**新增文件**:
|
||||
80→- `src/lib/game/attributes.ts`(~330行逻辑层):CharacterAttributes/AttributeProgress 类型、ATTRIBUTE_CONFIG 元信息、getAttributeBonus 两区加成公式(0-50线性+0.5%/点,50-100递减+0.2%/点)、getAllBonuses 12项修饰器、levelUpCheck 自动升级、computePrestigeAttrPoints、migrateAttributes 旧存档兼容
|
||||
81→- `src/components/game/AttributesPanel.tsx`(~330行 UI):四维卡片网格(小屏2×2/大屏1×4)、图标+中英文名+Lv.badge+数值/100+加成%+经验条+影响列表+分配按钮、顶部待分配点数badge闪烁、底部总览+12项修饰器明细
|
||||
82→
|
||||
83→**修改文件**:
|
||||
84→- `types.ts`:GameState 新增 attributes/attributeProgress/pendingAttrPoints
|
||||
85→- `config.ts`:INITIAL_STATE 补全默认值
|
||||
86→- `engine.ts`:recomputeStats 聚合属性加成;performPrestige 发放属性点(ascensions×2+1)
|
||||
87→- `gameStore.ts`:新增 allocateAttribute/gainAttributeExp actions;pulse/clickNode/autoDecodeTick/resolveCurrentNode/grantCruiseReward/tickTide 全部接入属性经验;init() 调用 migrateAttributes
|
||||
88→- `achievements.ts`:新增 ach_attr_total_50 + ach_attr_max_100 两项成就
|
||||
89→- `page.tsx`:grid-cols-7→8,新增「角色」标签页(User图标),红点提示,StatsPanel新增5行属性行,版本号 v0.6→v0.7
|
||||
90→
|
||||
91→**四维属性设计**:
|
||||
92→- 探索力(emerald):探险力+X%/巡航飞船速度+X%
|
||||
93→- 智慧(fuchsia):解码步数+X/洞见+X%/自动解码周期-X%
|
||||
94→- 勇气(amber):探险生命+X/BOSS胜率+X%/巡航护盾+X
|
||||
95→- 灵感(rose):接触率+X/星潮概率+X/脉冲连击+X%
|
||||
96→
|
||||
97→**QA 验证**(agent-browser + VLM):
|
||||
98→- VLM 视觉评分 **7/10**(面板)/ **8/10**(待分配状态):四维卡片可见、数值/等级/加成/经验条齐全、四色全息
|
||||
99→- 功能验证:setState pendingAttrPoints=5 → 显示5点待分配 → 点击分配按钮 → exploration 0→1, pending 5→4 ✅
|
||||
100→- lint 零错误;HTTP 200
|
||||
101→
|
||||
102→---
|
||||
103→
|
||||
104→### v0.6 深空巡航 Canvas 2D 实时玩法(历史记录)
|
||||
105→**动机**:回应用户反馈「玩法太单调(全是点点点)」+「视觉震撼不足」——首次引入实时操作玩法。
|
||||
106→
|
||||
107→**新增文件**:
|
||||
108→- `src/lib/game/cruise.ts`(~520 行逻辑层)
|
||||
109→ - 类型系统:CruiseEntity 联合类型(ship/asteroid/storm/crystal/insight/beacon/stargate/particle 共 8 种)
|
||||
110→ - mulberry32 + FNV-1a 种子化 RNG(`cruiseSeed(level)`)
|
||||
111→ - `generateLevel`:程序化生成陨石带(8+lvl×2)、虚空风暴(1+lvl/2)、晶体碎片(5+lvl)、洞见光球(2+lvl/3)、信标(1+lvl/4)、星门
|
||||
112→ - `updateCruise`:物理推进 + 碰撞检测 + 粒子系统 + 震动 + 600ms 无敌帧
|
||||
113→ - `computeRewards`:crystals=碎片×(8+lvl×2)、insights=洞见×(2+lvl×0.5)、contact=信标×(1.5+lvl×0.3);通关×1.5、失败×0.5
|
||||
114→ - 独立 localStorage `echo-nexus-cruise-v1`:最高分/累计通关/最高关卡/累计奖励/最近 20 局
|
||||
115→
|
||||
116→- `src/components/game/CruiseMode.tsx`(~830 行渲染层)
|
||||
117→ - 全屏 fixed inset-0 z-50 Canvas,DPR cap 2,resize 监听
|
||||
118→ - 3 层视差星空:远(100星)/中(60星)/近(30星),独立漂移 + 飞船速度视差 + 闪烁
|
||||
119→ - 8 种实体全部 ctx.shadowBlur 辉光绘制
|
||||
120→ - 粒子系统:尾焰/收集/碰撞/烟花,上限 200
|
||||
121→ - 屏幕震动 280ms 衰减;低护盾(<30%)红色边框脉冲
|
||||
122→ - HUD(HTML 叠层,glass+backdrop-blur,80ms 节流):护盾/能量/分数/用时/收集计数
|
||||
123→ - 控制:桌面 WASD/方向键 8 方向 + 移动端虚拟摇杆 + P 暂停 + Esc 退出 + 失焦自动暂停
|
||||
124→ - 阶段:ready → playing → won/lost(结算明细 + 奖励 + 下一关/重试/返回)
|
||||
125→
|
||||
126→**修改文件**:
|
||||
127→- `src/app/page.tsx`:header 新增 amber 主题「巡航」按钮(Navigation 图标)+ cruiseOpen state + 条件渲染 CruiseMode
|
||||
128→- `src/store/gameStore.ts`:新增 `grantCruiseReward({crystals?, insights?, contact?})` action(crystals 受 crystalCap 限制,contact 受 100 上限)
|
||||
129→- 版本号 v0.5.2 → v0.6
|
||||
130→
|
||||
131→**UI 偏移/重叠 BUG 修复**(3 处):
|
||||
132→- `DecodeArray.tsx`:移除 className 冲突的 `-translate-x-1/2 -translate-y-1/2`,统一用 inline transform 定位+缩放
|
||||
133→- `AchievementsPanel.tsx`:移除内层 `max-h-[300px]`,改 `flex-1 min-h-0` 自适应父容器
|
||||
134→- `page.tsx`:调整三个 section 的 min-h,避免小屏单列时总高度超过手机视口
|
||||
135→
|
||||
136→**色彩规范**:严格遵循 emerald(#34d399) / rose(#fb7185) / amber(#fbbf24) / fuchsia(#e879f9) 四色全息色谱,零蓝色/靛色
|
||||
137→
|
||||
138→**QA 验证**(agent-browser + VLM):
|
||||
139→- lint 零错误;dev 服务器 HTTP 200;编译 < 250ms
|
||||
140→- VLM 确认主界面:巡航按钮存在、晶体球居中、解码区正常、无重叠偏移
|
||||
141→- VLM 确认巡航玩法:飞船可见(绿色三角形)、HUD 完整、陨石+星空背景、粒子特效(黄色尾焰+紫色辉光)
|
||||
142→- WASD 控制飞船移动,按 W 直冲星门 → 通关,奖励 +30 晶体(2×10×1.5=30 计算正确)
|
||||
143→- localStorage 正确记录 highScore/totalRuns/totalWins/bestLevel
|
||||
144→- 奖励同步 gameStore(grantCruiseReward,满仓时 cap 逻辑正确)
|
||||
145→- 退出返回主界面,7 标签页 + 晶体球 + 解码面板均完好
|
||||
146→
|
||||
147→---
|
||||
148→
|
||||
149→## 三、未解决问题或风险 / 下一阶段优先事项
|
||||
150→
|
||||
151→### 已知问题 / 风险
|
||||
152→1. **dev 服务器 Turbopack 缓存偶发损坏**:`Unable to open static sorted file` + 进程被杀,需 `rm -rf .next` 重启。静态导出构建稳定可靠。
|
||||
153→2. **定时任务调度类型**:必须用 `fixed_rate` + `"900"` 秒(15分钟),不要用 cron 表达式。`webDevReview` 类型任务正常完成不会被删除,只有抛出未捕获异常才会被标记失败。
|
||||
154→3. **v0.3 星潮为单机版**:原计划 socket 全局事件,后续可扩展为多人同步。
|
||||
155→4. **v0.5 信标排行榜为本地版**(纯 localStorage):升级云排行榜需后端 API。
|
||||
156→5. **v0.5 每日挑战仅 1 个/天**:可加入"周挑战"或"信标链"(连续完成 N 天奖励)。
|
||||
157→6. **探险 BOSS 战胜率较低**:基础探索力 10 vs BOSS 难度 5-7,胜率约 25%,需玩家投资探险技术。
|
||||
158→7. **探险能量恢复较慢**:45s/点,可加技术提升恢复速度。
|
||||
159→8. **编年史上限 50 条**:超过自动丢弃最早的;v0.4 之前飞升无回填(空状态有提示)。
|
||||
160→9. **5 纪元叙事为模板化生成**:v0.5+ 将加入手写剧情节点。
|
||||
161→10. ~~**CrystalOrb 仍为 CSS 动画**~~ → ✅ **v0.7 已完成 Canvas 粒子系统升级**。
|
||||
162→
|
||||
163→### 下一阶段优先级(v0.7 后修正版)
|
||||
164→> 工单修正:原 P0 CrystalOrb Canvas + P1 角色属性两项均已在 v0.7 完成,现重新排序。
|
||||
165→
|
||||
166→1. **🔴 P0 — 巡航玩法大增强(v0.8 主线)**:BOSS 战关卡(每 5 关一个 BOSS,三阶段攻击模式 + 飞船射击系统)/ 道具掉落(5 种 powerup:护盾/能量/急速/超载/磁吸)/ 事件选择节点(每关通关后 3 选 1 强化牌,10 种强化)。这是当前最高优先级,能显著提升巡航玩法的深度与可玩性。
|
||||
167→2. **🟠 P1 — 探险 BOSS 战胜率平衡 + 探险能量恢复**:修复已知问题 6/7(探险 BOSS 胜率 25% 偏低,能量 45s/点 偏慢),提升探险体验。
|
||||
168→3. **🟠 P1 — 信标系统扩展**:周挑战 / 信标链(连续完成 N 天奖励),修复已知问题 5。
|
||||
169→4. **🟡 P2 — UI 样式细节打磨**:标签页图标/文字比例、视觉层次强化、移动端响应式进一步优化、CrystalOrb 周边留白优化(VLM 指出主界面左侧有空白)。
|
||||
170→5. **🟡 P2 — 云存档 + 云排行榜**:v0.5+ 后端 API(需评估是否引入 mini-service)。
|
||||
171→6. **🟢 P3 — 全 5 纪元手写叙事节点**:替换模板化 lore。
|
||||
172→7. **🟢 P3 — socket 多人同步星潮**:全局事件共享。
|
||||
173→
|
||||
174→### 定时任务(fixed_rate · 900s)
|
||||
175→- **当前 job_id**: **228357**(2026-06-24 13:25 重建)
|
||||
176→- **配置**: `fixed_rate` + `"900"`(15分钟间隔),`priority=10`(高优先级),`payload.kind=webDevReview`,`tz=Asia/Shanghai`
|
||||
177→- **任务名**: Echo Nexus - 任务审查与持续迭代
|
||||
178→- **任务描述强制要求**:每次触发 MUST 先完整阅读 worklog.md 工单,以工单为准,不凭记忆工作
|
||||
179→- **正常完成不会被删除**,只有未捕获异常会标记失败。若任务列表为空,需用 cron create 重建(schedule.kind=fixed_rate, expr="900", priority=10, payload.kind=webDevReview)。
|
||||
180→- **job_id 历史**: 227909(失效) → 228130(失效) → 228172(失效) → 228186(失效) → 228218(删除重建) → 228236(cron版,删除重建) → 228266(fixed_rate,失效) → 228329(失效) → **228357(当前,重建)**
|
||||
181→
|
||||
182→---
|
||||
183→
|
||||
184→## 定时任务描述模板(webDevReview · fixed_rate)
|
||||
185→
|
||||
186→> 重建参数:schedule.kind=`fixed_rate`, schedule.expr=`"900"`, params.priority=`10`, payload.kind=`webDevReview`
|
||||
187→
|
||||
188→```
|
||||
189→请先判断当前项目状态,使用 agent-browser 进行必要测试和 QA,然后自主选择本轮最合适的工作重点并继续开发。
|
||||
190→
|
||||
191→要求:
|
||||
192→1. 开始任务时查看 /home/z/my-project/worklog.md 了解实际进展,拆解详细todo
|
||||
193→2. 使用 agent-browser 进行测试和QA,有bug优先修复
|
||||
194→3. 如果稳定,自主提出新需求继续推进
|
||||
195→4. 样式要越做细节越多!!
|
||||
196→5. 功能要越做越多!!
|
||||
197→6. 工作告一段落更新 /home/z/my-project/worklog.md
|
||||
198→7. 项目结束后一定要把工作记录写在 worklog.md 里
|
||||
199→
|
||||
200→交接文档建议包含三部分:
|
||||
201→- 项目当前状态描述/判断
|
||||
202→- 当前目标/已完成的修改/验证结果
|
||||
203→- 未解决问题或风险,建议下一阶段优先事项
|
||||
204→```
|
||||
205→
|
||||
206→---
|
||||
207→
|
||||
208→## 历史详细版本记录(按需查阅 docs/repo/docs/)
|
||||
209→
|
||||
210→- `04-解码系统修复-v0.1.1.md`
|
||||
211→- `05-遗迹探险系统-v0.2.md`
|
||||
212→- `06-音频与成就系统-v0.2.1.md`
|
||||
213→- `07-星潮事件系统-v0.3.md`
|
||||
214→- `08-星图天文台系统-v0.3.1.md`
|
||||
215→- `09-回响编年史系统-v0.4.md`
|
||||
216→- `10-深空信标系统-v0.5.md`
|
||||
217→
|
||||
218→---
|
||||
219→
|
||||
220→Task ID: 7
|
||||
221→Agent: full-stack-developer
|
||||
222→Task: 角色属性系统(探索力/智慧/勇气/灵感)
|
||||
223→
|
||||
224→Work Log:
|
||||
225→- 阅读 worklog.md 了解 v0.6 项目背景,确认 8 大系统架构与四色全息色彩规范
|
||||
226→- 新建 `src/lib/game/attributes.ts` 逻辑层(~330 行):
|
||||
227→ - 定义 CharacterAttributes/AttributeProgress/AttributeKey 类型 + ATTRIBUTE_CONFIG 元信息
|
||||
228→ - getAttributeBonus 线性+递减两区加成公式(0-50 每 10 点 +5%,50-100 每点 +2%)
|
||||
229→ - getAllBonuses 返回 12 个修饰器(探险力/巡航速度/解码步数/洞见/自动解码周期/探险生命/BOSS 胜率/巡航护盾/接触率/星潮触发/脉冲连击/产能)
|
||||
230→ - levelUpCheck 自动跨多级 + expRequiredForLevel + computePrestigeAttrPoints + migrateAttributes 兼容
|
||||
231→- 扩展 `src/lib/game/types.ts` GameState:新增 attributes/attributeProgress/pendingAttrPoints
|
||||
232→- 扩展 `src/lib/game/config.ts` INITIAL_STATE:补全默认值(0 数值 + 空 progress)
|
||||
233→- 扩展 `src/lib/game/engine.ts`:
|
||||
234→ - recomputeStats 末尾聚合 am.crystalsPerSecMult/insightMultAdd/contactRateMult/decodeStepsBonus
|
||||
235→ - performPrestige 保留 attributes 数值,清空 attributeProgress,发放 ascensions × 2 + 1 点属性点
|
||||
236→ - createInitialState 每次返回全新对象避免引用共享
|
||||
237→- 扩展 `src/store/gameStore.ts`(核心改造,10+ 处 syncStats 调用全部补 attributes 参数):
|
||||
238→ - pulse:连击 ≥3 给灵感经验 + 脉冲威力乘灵感连击加成
|
||||
239→ - clickNode 完成:给智慧经验(tier × 2)
|
||||
240→ - autoDecodeTick:智慧经验 +1 + 自动解码周期受 am.autoDecodeIntervalMult 影响
|
||||
241→ - startExpedition:探险力乘 am.expeditionPowerMult,生命加 am.expeditionHpBonus
|
||||
242→ - resolveCurrentNode:BOSS 节点包装 RNG 提升 +am.bossWinRateBonus 胜率;战斗胜利给勇气+探索力经验
|
||||
243→ - grantCruiseReward:按总奖励量给探索力+勇气经验
|
||||
244→ - tickTide:灵感 am.tideTriggerBonus 缩短星潮间隙(上限 30%)
|
||||
245→ - init() 调用 migrateAttributes 补全旧存档
|
||||
246→ - 新增 allocateAttribute / gainAttributeExp 两个 action
|
||||
247→- 新建 `src/components/game/AttributesPanel.tsx` UI 面板(~330 行):
|
||||
248→ - 四维卡片网格(小屏 2×2,大屏 1×4)
|
||||
249→ - 每张卡片:图标 + 中英文名 + Lv.badge + 数值/100 + 加成% + 经验条 + 影响列表 + 「+分配」按钮
|
||||
250→ - 顶部待分配点数 badge(pendingAttrPoints > 0 时 echo-pending-pulse 闪烁动画)
|
||||
251→ - 底部总等级/总加成概览 + 12 个修饰器明细
|
||||
252→ - 4 色辉光边框(emerald/fuchsia/amber/rose),顶角光晕装饰
|
||||
253→- 接入 `src/app/page.tsx`:
|
||||
254→ - grid-cols-7 → grid-cols-8,新增第 8 个「角色」TabsTrigger(User 图标,渐变主题)
|
||||
255→ - pendingAttrPoints > 0 时显示 rose 红点提示
|
||||
256→ - 渲染 AttributesPanel
|
||||
257→ - StatsPanel 新增 5 行属性行(探索力/智慧/勇气/灵感/待分配点)
|
||||
258→ - 版本号 v0.6 → v0.7
|
||||
259→- 新增 `src/lib/game/achievements.ts` 2 项成就:
|
||||
260→ - ach_attr_total_50(四维觉醒):总属性 ≥ 50 → 产能+6%/洞见+6%
|
||||
261→ - ach_attr_max_100(维度精通):任一属性 100 → 产能+12%/洞见+10%
|
||||
262→- 写入 `agent-ctx/7-full-stack-developer.md` 工作记录
|
||||
263→- 最终验证:lint 零错误 + dev 服务器 HTTP 200 + 编译 < 250ms
|
||||
264→
|
||||
265→Stage Summary:
|
||||
266→- ✅ 角色属性系统 v0.7 P1 全部完成
|
||||
267→- ✅ 新增 2 文件(attributes.ts + AttributesPanel.tsx),修改 6 文件(types/config/engine/gameStore/achievements/page)
|
||||
268→- ✅ 四维属性完整接入游戏各系统(探险/解码/脉冲/巡航/星潮)
|
||||
269→- ✅ 飞升属性点公式 = ascensions × 2 + 1;经验累积自动升级(每级 10×level)
|
||||
270→- ✅ 旧存档兼容(migrateAttributes 补全字段,同步 level 与 attributes)
|
||||
271→- ✅ lint 零错误 + HTTP 200 + 编译 < 250ms
|
||||
272→- ✅ 严格四色全息(emerald/fuchsia/amber/rose),零蓝色/靛色
|
||||
273→- ✅ 8 标签页 + 巡航按钮全部保留,data-tut 锚点未破坏
|
||||
274→- ✅ 待分配点数时标签页 rose 红点提示 + 顶部 badge 闪烁
|
||||
275→
|
||||
276→---
|
||||
277→Task ID: 8-deploy
|
||||
278→Agent: main
|
||||
279→Task: 重建定时任务 + 更新 README + 部署 gh-pages(v0.7)
|
||||
280→
|
||||
281→Work Log:
|
||||
282→- 检查项目状态:CrystalOrb.tsx 已是 v0.7 Canvas 粒子系统(659 行),无活动 cron job
|
||||
283→- 重建定时任务:cron create fixed_rate="900" priority=10 webDevReview → job_id 228329(tz=Asia/Shanghai)
|
||||
284→- 重写 README.md:
|
||||
285→ - 顶部显著位置添加「在线游玩」链接(https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/)
|
||||
286→ - 版本号 v0.1 → v0.7
|
||||
287→ - 新增 10 大系统表格(含 v0.6 巡航 + v0.7 角色属性)
|
||||
288→ - 完整开发路线表(v0.1-v1.0,标记 ✅/🔜 状态)
|
||||
289→ - 新增本地开发命令 + Gitea Pages 部署指南
|
||||
290→ - 文档索引扩展至 10 个版本文档
|
||||
291→- 静态导出:BUILD_EXPORT=true bun run build:static → out/ 1.6M(HTTP 200 编译 4.3s)
|
||||
292→- 推送 gh-pages 分支:force push origin gh-pages(commit 8727fed "deploy: v0.7")
|
||||
293→- 提交 main:README 更新(commit 43dfc2d "docs: README 添加在线游玩链接 + v0.7 状态更新")
|
||||
294→- 验证 Gitea Pages:https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/ → HTTP 200 ✅
|
||||
295→- QA 验证:agent-browser 打开 http://localhost:3000/ → VLM 评分 8/10(主界面 polished,minor 空白)
|
||||
296→
|
||||
297→Stage Summary:
|
||||
298→- ✅ 定时任务重建成功(job_id 228329,每 15 分钟自动审查迭代)
|
||||
299→- ✅ README 重写完成,网站链接显著展示,v0.7 状态完整
|
||||
300→- ✅ gh-pages 部署成功,Gitea Pages HTTP 200 可访问
|
||||
301→- ✅ main 分支已同步推送(README + worklog 更新)
|
||||
302→- ✅ dev 服务器健康(HTTP 200,编译 < 250ms)
|
||||
303→- ✅ CrystalOrb v0.7 Canvas 粒子系统已确认完整(659 行)
|
||||
304→- 下一步:v0.8 巡航玩法增强(BOSS 战 / 道具掉落 / 事件选择节点)
|
||||
305→
|
||||
306→---
|
||||
307→Task ID: 8
|
||||
308→Agent: main
|
||||
309→Task: v0.8 巡航玩法大增强(BOSS 战 + 道具掉落 + 事件选择节点)+ 工单修正 + 审查流程重建
|
||||
310→
|
||||
311→Work Log:
|
||||
312→- 重读 worklog 工单,发现 v0.7 两项(CrystalOrb Canvas + 角色属性)已完成但工单"下一阶段优先级"未更新
|
||||
313→- 修正 worklog 工单:标注 P0/P1 v0.7 已完成,重新排序下一阶段优先级(P0=巡航增强, P1=探险平衡/信标扩展, P2=UI打磨/云存档, P3=叙事/多人)
|
||||
314→- 重建审查流程 cron job:fixed_rate=900s, priority=10, webDevReview, tz=Asia/Shanghai, job_id=228357
|
||||
315→ - 任务描述强制要求:每次触发 MUST 先完整阅读 worklog.md 工单,以工单为准,不凭记忆工作
|
||||
316→- 发现之前被中断的 v0.8 subagent 已写入 2037 行代码(cruise.ts +1487 / CruiseMode.tsx +858 / page.tsx +2)
|
||||
317→- 修复 2 个 lint 错误(react-hooks/set-state-in-effect):
|
||||
318→ - isTouch: useState(false) + useEffect(setIsTouch) → useState initializer
|
||||
319→ - stats: useState(null) + useEffect(setStats(loadCruiseStats)) → useState initializer
|
||||
320→- QA 验证(agent-browser + VLM):
|
||||
321→ - 主界面 VLM 7/10:v0.8 版本号 ✅ + 巡航按钮 ✅
|
||||
322→ - 巡航 READY 阶段 VLM 8/10:BOSS 战说明 ✅(每5关BOSS战/击败BOSS)+ 射击控制说明 ✅(空格/右下角射击按钮)
|
||||
323→ - 巡航第1关游戏 VLM 8/10:飞船(绿色三角)✅ + HUD(护盾/能量/分数/计时)✅ + 陨石/收集物/能量场 ✅ + 无渲染错误
|
||||
324→- 提交 v0.8(commit 494bc5f)+ 推送 main
|
||||
325→- 静态导出 BUILD_EXPORT=true → out/ 1.6M(编译 4.1s)
|
||||
326→- 部署 gh-pages(force push, commit b865922)→ Gitea Pages HTTP 200 ✅
|
||||
327→
|
||||
328→Stage Summary:
|
||||
329→- ✅ 工单修正完成:v0.7 已完成项标注清楚,下一阶段优先级重新排序
|
||||
330→- ✅ 审查流程重建:cron job_id 228357,每15分钟触发,强制读工单
|
||||
331→- ✅ v0.8 巡航玩法大增强全部完成并部署:
|
||||
332→ - BOSS 战系统(每5关,三阶段攻击,HP条,击败奖励×3)
|
||||
333→ - 飞船射击系统(空格/射击按钮,能量消耗,子弹尾焰)
|
||||
334→ - 道具掉落(5种powerup:护盾/能量/急速/超载/磁吸)
|
||||
335→ - 事件选择节点(每关通关后3选1,10种强化牌)
|
||||
336→ - lint 零错误 + dev HTTP 200 + gh-pages HTTP 200
|
||||
337→- ✅ VLM 评分:主界面 7/10 + 巡航READY 8/10 + 巡航游戏 8/10
|
||||
338→- 在线游玩 v0.8:https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
339→- 下一阶段工单:P1 探险BOSS胜率平衡 + 探险能量恢复 / 信标系统扩展(周挑战/信标链)
|
||||
340→
|
||||
341→---
|
||||
342→Task ID: 9-b
|
||||
343→Agent: full-stack-developer
|
||||
344→Task: 信标系统扩展(周挑战 + 信标链连续奖励)
|
||||
345→
|
||||
346→Work Log:
|
||||
347→- 阅读现有 `src/lib/game/beacon.ts`(v0.5 每日挑战 + 本地排行榜,358 行)+ `src/components/game/BeaconPanel.tsx` + `src/store/gameStore.ts` 的 `trackBeacon` 函数(约第 173 行)+ worklog v0.8 项目状态,确认四色全息规范与现有架构。
|
||||
348→- **扩展 `src/lib/game/beacon.ts`(358 → 873 行,新增 ~515 行)**:
|
||||
349→ - **周挑战(WEEKLY CHALLENGE)**:
|
||||
350→ - `BeaconWeeklyChallenge` 接口(weekKey YYYY-Www / type / difficulty 强制 anomaly|singular / goal / rewardInsight / rewardContact / seed / title / desc)
|
||||
351→ - `BeaconWeeklyProgress` 接口(weekKey / progress / startedAt / completedAt / claimed / durationSec)
|
||||
352→ - `getWeekKey(now)`:ISO 8601 周键(周一为起点,含首个周四的周为第一周)
|
||||
353→ - `weekKeyToSeed`:FNV-1a 哈希
|
||||
354→ - `generateWeeklyChallenge(now)`:基于 weekKey 种子确定性生成,难度加权 anomaly 60% / singular 40%,goal 为日基准 ×3-5 倍(decode 18-75 / expedition 3-15 / pulse 60-245 / boss 3-12 / insight 120-595)
|
||||
355→ - `loadWeeklyProgress` / `saveWeeklyProgress` / `addWeeklyProgress` / `claimWeeklyReward`(推送排行榜,entry 加 `isWeekly: true`)
|
||||
356→ - `msUntilNextWeek(now)`:距离下周一 UTC 0 点的毫秒数
|
||||
357→ - `BEACON_WEEKLY_KEY = "echo-nexus-beacon-weekly-v1"`
|
||||
358→ - **信标链(BEACON CHAIN)**:
|
||||
359→ - `BeaconChainState` 接口(lastCompletedDateKey / currentStreak / longestStreak / totalCompletions / graceUsed / milestonesClaimed)
|
||||
360→ - `BEACON_CHAIN_KEY = "echo-nexus-beacon-chain-v1"`
|
||||
361→ - `BEACON_CHAIN_MILESTONES = [3, 7, 14, 30]` 常量
|
||||
362→ - `BEACON_CHAIN_REWARDS`:4 个里程碑(三日谐振 +50/+5 / 七日回响 +120/+12 / 半月星潮 +280/+28 / 满月飞升 +680/+68)
|
||||
363→ - `loadChainState` / `saveChainState`(每次返回新对象避免引用共享)
|
||||
364→ - `recordChainCompletion(dateKey)` 核心逻辑:同日重复忽略;次日 streak++;隔一天 miss 且 graceUsed<1 时续命 streak++ graceUsed++;其他断链 streak=1 graceUsed=0;返回 `{ state, newMilestones }`
|
||||
365→ - `claimChainMilestone(milestone)` / `getNextMilestone(streak)` / `getChainProgress(streak)`(返回 current/next/prev/progressPct 用于 UI)
|
||||
366→ - `dateKeyToTimestamp` / `dateKeyDiffDays` 工具函数
|
||||
367→ - `BeaconScoreEntry` 新增可选 `isWeekly?: boolean` 字段
|
||||
368→- **扩展 `src/store/gameStore.ts`**:
|
||||
369→ - import 扩展:generateWeeklyChallenge / loadWeeklyProgress / loadChainState / addWeeklyProgress / recordChainCompletion / claimWeeklyReward / claimChainMilestone / getTodayKey + 类型
|
||||
370→ - `trackBeacon(type, delta)` 函数签名从 `boolean` 改为 `{ dailyJustCompleted, weeklyJustCompleted, newChainMilestones }`:
|
||||
371→ - 日挑战类型匹配且未完成 → addBeaconProgress;若刚完成 → recordChainCompletion(getTodayKey()) 收集 newMilestones
|
||||
372→ - 周挑战类型匹配且未完成 → addWeeklyProgress
|
||||
373→ - 所有调用点(pulse/clickNode/autoDecodeTick/resolveCurrentNode 等 7 处)原本就忽略返回值,向后兼容
|
||||
374→ - 新增 action `claimWeeklyBeacon`:调用 claimWeeklyReward → 发放 insights + contact 到 state,返回 `{ rewardInsight, rewardContact, score }`
|
||||
375→ - 新增 action `claimChainReward(milestone)`:前置校验 currentStreak 与 milestonesClaimed,调用 claimChainMilestone → 发放奖励,返回 `{ rewardInsight, rewardContact, label, ok }`
|
||||
376→ - GameActions 接口同步新增两个 action 签名
|
||||
377→- **重写 `src/components/game/BeaconPanel.tsx`(301 → 638 行)**:
|
||||
378→ - 顶部头部 + 每日挑战卡片(保留 v0.5 完整功能 + 按钮主题色随难度色淡显)
|
||||
379→ - **新增周挑战区块**(fuchsia 主题):标题"周挑战 · WEEKLY" + weekKey + 倒计时 + 挑战卡片(类型/难度标签/标题/描述/进度条/奖励/领取按钮 emerald 主题)+ weekly-glow 动画
|
||||
380→ - **新增信标链区块**(amber→rose 渐变):标题"信标链 · CHAIN" + 大字号 streak(chain-streak-text 渐变流动动画)+ 今日完成状态徽章 + 4 个里程碑节点(w-12 h-12 圆形,claimed=emerald/✓,reachable=rose 脉冲动画+领取按钮,inProgress=amber 半亮,未到达=muted 灰)+ 节点间连线(背景灰 + 已达成部分 amber→rose 渐变 + 辉光,基于 prev→next 插值定位)+ 进度条 + 底部统计(最长/累计/续命状态)
|
||||
381→ - 桌面端 lg:grid-cols-2 让周挑战+信标链并排,移动端单列
|
||||
382→ - 排行榜条目区分日/周:周挑战 entry 显示 "WEEK" 徽章 + fuchsia 高亮背景
|
||||
383→ - 空状态提示扩展为"完成今日或本周信标即可登榜"
|
||||
384→ - 4 个新动画:weekly-glow / chain-milestone-pulse / chain-streak-flux(背景渐变流动)
|
||||
385→- **QA 验证**:
|
||||
386→ - `bun run lint` 零错误(每次修改后均验证)
|
||||
387→ - dev.log 全程无错误,所有编译 < 300ms
|
||||
388→ - **信标链逻辑测试**(bun 直接运行 TS,5 个场景全 PASS):
|
||||
389→ 1. 昨日 streak=1 → 今日完成 → streak=2 ✅
|
||||
390→ 2. 同日重复完成 → 忽略 ✅
|
||||
391→ 3. 明日完成 → streak=3,无需 grace ✅
|
||||
392→ 4. 隔一天 miss(lastCompleted + 2 天)→ streak=4,graceUsed=1 ✅
|
||||
393→ 5. 再次 miss(grace 已用)→ 断链 streak=1,graceUsed=0 ✅
|
||||
394→ - **UI 集成测试**(agent-browser):
|
||||
395→ - localStorage 模拟设置 chain state(lastCompletedDateKey=yesterday, currentStreak=1)→ reload → UI 正确显示 streak=1
|
||||
396→ - 设置 streak=3 + milestonesClaimed=[] → milestone 3 节点显示 rose 脉冲动画 + "领取"按钮
|
||||
397→ - 点击"领取"→ milestonesClaimed=[3] + Toast "✦ 三日谐振 已领取 +50 洞见 · +5.0 接触" + 按钮消失 ✅
|
||||
398→ - **VLM 视觉评分**(目标 ≥7/10):
|
||||
399→ - 首屏截图:8/10(四色一致、布局合理、信标链清晰)
|
||||
400→ - 里程碑可领取状态:8/10(amber→rose 渐变醒目、里程碑层次分明、fuchsia 主题清晰)
|
||||
401→ - 重置后干净状态:8/10(WEEKLY 字体对比度可优化,但整体可读性强)
|
||||
402→ - **不破坏现有功能**:日挑战进度/领奖/排行榜流程全部保留并工作正常
|
||||
403→
|
||||
404→Stage Summary:
|
||||
405→- ✅ beacon.ts 扩展完成(358 → 873 行):周挑战 + 信标链全部函数与类型
|
||||
406→- ✅ gameStore.ts 集成完成:trackBeacon 升级为对象返回值 + claimWeeklyBeacon + claimChainReward 两个新 action
|
||||
407→- ✅ BeaconPanel.tsx UI 完整重写(301 → 638 行):周挑战 fuchsia 卡片 + 信标链 amber→rose 渐变区块
|
||||
408→- ✅ 严格四色全息:周挑战 fuchsia、信标链 amber→rose、领取按钮 emerald、无蓝/紫色违规
|
||||
409→- ✅ localStorage 新增 2 个独立 key(weekly + chain),不污染旧 key
|
||||
410→- ✅ 确定性:周挑战同周同种子同结果(weekKey FNV-1a 种子)
|
||||
411→- ✅ 信标链 grace 续命机制工作正常(5 个场景 bun 测试全 PASS)
|
||||
412→- ✅ lint 零错误 + dev HTTP 200 + VLM 8/10
|
||||
413→- ✅ 现有日挑战 + 排行榜 + 领奖流程全部保留,无回归
|
||||
414→
|
||||
415→---
|
||||
416→Task ID: 9
|
||||
417→Agent: main + subagent(9-b)
|
||||
418→Task: v0.8.1 P1 双任务 — 探险 BOSS 胜率平衡 + 能量恢复 + 信标系统扩展(周挑战 + 信标链)
|
||||
419→
|
||||
420→Work Log:
|
||||
421→- 重读工单确认 P1 两项为下一阶段优先级
|
||||
422→- P1-a 探险平衡(main 自己做,平衡需要精细控制):
|
||||
423→ - expedition.ts: combatDifficultyScale 8→4, combatWinRateFloor 0.25→0.35, BOSS difficulty 5-7→3-5
|
||||
424→ - 新增 computeEnergyRegenInterval(state): exp_2 -30%, exp_3 -20%, 探索力属性 -最高30%, 下限12s
|
||||
425→ - computeEnergyRegen 接受 intervalSec 参数
|
||||
426→ - config.ts: exp_2/exp_3 描述加能量恢复说明
|
||||
427→ - gameStore.ts tick: 传入动态间隔
|
||||
428→ - ExpeditionPanel.tsx: 显示实际恢复速度 + '已加速'标记
|
||||
429→- P1-b 信标系统扩展(dispatch subagent 9-b,并行完成):
|
||||
430→ - beacon.ts 358→873行: 周挑战(getWeekKey ISO 8601 + 确定性生成) + 信标链(4里程碑+grace续命)
|
||||
431→ - BeaconPanel.tsx 301→638行: 周挑战fuchsia主题 + 信标链amber→rose里程碑节点
|
||||
432→ - gameStore.ts: trackBeacon升级 + claimWeeklyBeacon/claimChainReward actions
|
||||
433→- QA 验证:
|
||||
434→ - lint 零错误
|
||||
435→ - 探险面板 VLM 7/10(能量条 + 恢复速度显示正常)
|
||||
436→ - 信标面板 VLM 8/10(周挑战 WEEKLY + 信标链 3/7/14/30 + 排行榜全部可见)
|
||||
437→ - subagent 5场景 bun 测试全 PASS(信标链断链/续命逻辑)
|
||||
438→- 提交 v0.8.1(commit 71ca5b4)+ 推送 main
|
||||
439→- 静态导出 + 部署 gh-pages(commit 97eecaa)→ HTTP 200
|
||||
440→
|
||||
441→Stage Summary:
|
||||
442→- ✅ P1-a 探险平衡完成: BOSS 基础胜率 25%→35-45%, 配合技术/属性可达 55-70%
|
||||
443→- ✅ P1-a 能量恢复: 固定45s → 动态12-45s(技术+属性加速)
|
||||
444→- ✅ P1-b 周挑战: 每周一UTC刷新, fuchsia主题, goal×3-5倍
|
||||
445→- ✅ P1-b 信标链: 4里程碑(3/7/14/30天) + grace续命, amber→rose渐变
|
||||
446→- ✅ 在线游玩 v0.8.1: https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
447→- 下一阶段工单: P2 UI样式细节打磨 / P2 云存档+云排行榜 / P3 全纪元叙事
|
||||
448→
|
||||
449→---
|
||||
450→Task ID: 10-a
|
||||
451→Agent: full-stack-developer
|
||||
452→Task: #5 限时挑战 + #3 星潮类型深化
|
||||
453→
|
||||
454→Work Log:
|
||||
455→- 阅读项目上下文:worklog.md(v0.8.1,10 大系统)+ beacon.ts(873行,日+周+链)+ starTide.ts(209行,6种星潮)+ gameStore trackBeacon/tickTide + BeaconPanel.tsx,确认四色全息规范与现有架构
|
||||
456→- **工单 #5 限时挑战**:
|
||||
457→ - beacon.ts(873→1162行)新增限时挑战系统:
|
||||
458→ - BeaconTimedChallenge/BeaconTimedProgress 接口 + isTimed 字段加入 BeaconScoreEntry
|
||||
459→ - getTimedSlotKey(UTC 0/4/8/12/16/20 点切分,"timed_YYYY-MM-DD_HH")+ timedSlotKeyToSeed(FNV-1a)
|
||||
460→ - generateTimedChallenge(确定性,难度 routine,goal=日基准×0.3-0.5,5类型公式)
|
||||
461→ - loadTimedProgress/saveTimedProgress/addTimedProgress/claimTimedReward(排行榜 isTimed)
|
||||
462→ - msUntilNextTimedSlot + TIMED_SLOT_MS=4h + BEACON_TIMED_KEY
|
||||
463→ - gameStore.ts:trackBeacon 返回值新增 timedJustCompleted,三进度同时更新;新增 claimTimedBeacon action
|
||||
464→ - BeaconPanel.tsx(753→944行):日挑战与周挑战之间插入限时挑战区块(amber 主题)
|
||||
465→ - Hourglass图标+TIMED标题+slotKey+倒计时 + 进度+奖励+领取按钮(emerald)
|
||||
466→ - 紧急状态:距时段结束<30min 切 rose 脉冲动画+"即将结束"徽章
|
||||
467→ - 2新动画 timed-glow(amber)/timed-urgent(rose) + 排行榜 TIMED 徽章
|
||||
468→- **工单 #3 星潮深化**:
|
||||
469→ - starTide.ts(209→289行):TideType 新增 surge/eclipse/prism
|
||||
470→ - surge(emerald ⇈): crystalsPerSec×2.5 + targetLenBonus=2(解码目标序列+2,更长更难)
|
||||
471→ - eclipse(rose ◐): crystalsPerSec×0.7 + bossWinRateBonus=0.2(BOSS胜率+20%)
|
||||
472→ - prism(fuchsia ◬): insightMultAdd=1.0(洞见×2) + autoDecodeIntervalMult=0.7(自动解码-30%)
|
||||
473→ - TideModifiers 新增 targetLenBonus/bossWinRateBonus/autoDecodeIntervalMult 可选字段
|
||||
474→ - TIDE_WEIGHTS 新增3种各12(总136)+ getTideModifiers 3新case
|
||||
475→ - decode.ts:generatePuzzle 新增 targetLenBonus 参数(surge用,targetLen+stepLimit同步增加)
|
||||
476→ - gameStore.ts 3处修饰器应用:
|
||||
477→ - startDecode:surge 时传 targetLenBonus → 谜题更长
|
||||
478→ - autoDecodeTick:prism 时 interval×=autoDecodeIntervalMult
|
||||
479→ - resolveCurrentNode:eclipse 时 bossWinRate 加 tideBossBonus
|
||||
480→ - achievements.ts:ach_tides_all 阈值6→9;page.tsx StatsPanel 星潮亲历 /9
|
||||
481→- QA 验证:
|
||||
482→ - lint 零错误(exit 0)+ dev HTTP 200 + 编译<30ms
|
||||
483→ - BeaconPanel VLM 8.5/10(限时区块可见)+ 最终 9/10
|
||||
484→ - 三新星潮 localStorage 注入触发截图 VLM:surge 8/10、prism 7/10、eclipse 8/10
|
||||
485→ - 日/周/信标链/6旧星潮全部保留无回归
|
||||
486→
|
||||
487→Stage Summary:
|
||||
488→- ✅ beacon.ts +289行(限时挑战完整系统:4h时段+确定性+进度+领奖+排行榜)
|
||||
489→- ✅ starTide.ts +80行(3新类型 surge/eclipse/prism + 3新修饰器字段)
|
||||
490→- ✅ decode.ts generatePuzzle 支持 targetLenBonus(surge 谜题+2)
|
||||
491→- ✅ gameStore.ts trackBeacon 三进度同步 + claimTimedBeacon + 3处新星潮修饰器
|
||||
492→- ✅ BeaconPanel.tsx +191行(amber 限时区块 + 紧急状态 + TIMED 徽章)
|
||||
493→- ✅ 严格四色规范:限时amber/surge-emerald/eclipse-rose/prism-fuchsia,零蓝色
|
||||
494→- ✅ 确定性:限时挑战同时段同种子同结果(FNV-1a slotKey 哈希)
|
||||
495→- ✅ lint 零错误 + dev HTTP 200 + VLM 全部≥7/10
|
||||
496→
|
||||
497→---
|
||||
498→Task ID: 10-b
|
||||
499→Agent: full-stack-developer
|
||||
500→Task: P2/#4 云排行榜 mini-service(信标本机榜升级为云端 Top100)
|
||||
501→
|
||||
502→Work Log:
|
||||
503→- 前置阅读:worklog(v0.8.1 项目状态)+ beacon.ts(BeaconScoreEntry / loadLeaderboard / pushLeaderboardEntry / claimBeaconReward / claimWeeklyReward / claimTimedReward)+ BeaconPanel.tsx(排行榜 UI 渲染)+ Caddyfile(?XTransformPort=端口号 转发规则)+ examples/websocket(mini-service 参考)+ .zscripts/dev.sh(mini-service 启动模式)
|
||||
504→- 发现 worklog 信息滞后:beacon.ts 实际已扩到 1161 行(v0.8.2 已加限时挑战 + claimTimedReward),BeaconPanel 已扩到 953 行
|
||||
505→- 创建 mini-service:
|
||||
506→ - `mini-services/leaderboard-service/package.json`:独立 bun 项目,type=module,scripts `dev: bun --hot index.ts` + `start: bun index.ts`,依赖 hono ^4.6.14
|
||||
507→ - `mini-services/leaderboard-service/index.ts`(182 行):
|
||||
508→ - Hono + cors 中间件(origin: * 全开放,跨端口必须)
|
||||
509→ - 内存数组存储(最多 1000 条,按 score 降序,同分按时长→时间戳排序)
|
||||
510→ - 防刷:同 dateKey+challenge 10s 内只接受 1 次提交(Map 记录 lastSubmitAt),返回 429 + retryAfterMs
|
||||
511→ - GET /api/leaderboard → Top100 + total
|
||||
512→ - POST /api/leaderboard body {entry} → 校验 schema → 推入 → 排序 → 返回 {entries, total, rank}
|
||||
513→ - GET /api/leaderboard/stats → {totalSubmissions, uniquePlayers, topScore}
|
||||
514→ - GET / → 健康检查 {service, version, ok, uptime}
|
||||
515→ - 端口固定 3030,`export default { port, fetch }` 标准 bun 模式
|
||||
516→ - `mini-services/leaderboard-service/README.md`:API 文档 + 联调规范
|
||||
517→- mini-service 启动调试:bun --hot 在本沙盒环境下会因文件 watcher 异常被 kill;改用 `bun index.ts`(无 --hot)+ 双 fork `( ... & )` 模式启动,PPID=1,uptime 4+ 分钟稳定
|
||||
518→- eslint.config.mjs 新增 ignores "mini-services/**"(mini-service 独立项目,不参与主项目 lint)
|
||||
519→- beacon.ts 扩展(1161 → 1290 行,+129 行):
|
||||
520→ - 三个 claim 函数返回值新增 `entry: BeaconScoreEntry`(非破坏性扩展):
|
||||
521→ - `claimBeaconReward` 返回 `entry`(daily)
|
||||
522→ - `claimWeeklyReward` 返回 `entry`(weekly)
|
||||
523→ - `claimTimedReward` 返回 `entry`(timed)
|
||||
524→ - 新增云排行榜模块(v0.8.2 P2/#4):
|
||||
525→ - `BEACON_CLOUD_PORT = 3030` 常量
|
||||
526→ - `BEACON_CLOUD_LAST_SUBMIT_KEY = "echo-nexus-beacon-cloud-last-submit-v1"` 本地 key
|
||||
527→ - `CloudLeaderboardResponse` / `CloudSubmitResponse` / `CloudStatsResponse` 接口
|
||||
528→ - `loadLastCloudSubmitTimestamp()` / `saveLastCloudSubmitTimestamp(ts)` 工具
|
||||
529→ - `fetchCloudLeaderboard(): Promise<BeaconScoreEntry[]>` — GET 相对路径 + ?XTransformPort=3030
|
||||
530→ - `submitCloudScore(entry): Promise<number>` — POST,成功返回 rank,失败返回 -1,自动记录 ts 供全球榜高亮
|
||||
531→ - `fetchCloudStats(): Promise<CloudStatsResponse | null>` — 全局统计
|
||||
532→ - 所有 fetch 用相对路径 + `?XTransformPort=3030`,**禁止** localhost:3030
|
||||
533→- gameStore.ts 集成:
|
||||
534→ - import 新增 `submitCloudScore`
|
||||
535→ - `claimWeeklyBeacon` action:领奖成功后 `void submitCloudScore(res.entry)`(fire-and-forget,不 await,不阻塞)
|
||||
536→ - `claimTimedBeacon` action:同上
|
||||
537→ - `claimBeaconReward` (daily) 由 BeaconPanel 直接调用,不通过 gameStore
|
||||
538→- BeaconPanel.tsx 重写(953 → 1170 行,+217 行):
|
||||
539→ - 新增 import: fetchCloudLeaderboard / submitCloudScore / loadLastCloudSubmitTimestamp + 4 个 lucide 图标(RefreshCw/Globe/WifiOff/Loader2)
|
||||
540→ - 新增状态: lbTab ('local'|'global') / cloudEntries / cloudLoading / cloudError / cloudFetched / mySubmitTs / cloudFetchingRef
|
||||
541→ - 新增 `refreshCloudLeaderboard()` callback:拉取云端榜 + 防并发(ref)+ 空 entries 时显示提示
|
||||
542→ - useEffect: 切到全球 tab 自动拉取(仅首次)+ 初始化读取 mySubmitTs
|
||||
543→ - handleClaimDaily: 领奖成功后 `void submitCloudScore(res.entry).then(rank => ...)` — 若用户在全球 tab 自动刷新
|
||||
544→ - handleClaimTimed/Weekly: 领奖后更新 mySubmitTs + 若在全球 tab 自动刷新
|
||||
545→ - 排行榜 UI 重写为双 tab:
|
||||
546→ - 顶部「本地」(amber 主题) / 「全球」(emerald 主题) 切换按钮 + 全球 tab 专属刷新按钮(旋转动画)
|
||||
547→ - 子标题:本地"本机 Top N · 离线可用" / 全球"全球 Top N · 已同步 / 同步中…"
|
||||
548→ - 本地榜保留原 v0.8.2 渲染(max-h-200px overflow-y-auto)
|
||||
549→ - 全球榜:
|
||||
550→ - 加载中:Loader2 spinner + "正在拉取全球榜…"
|
||||
551→ - 空榜+错误:WifiOff 图标 + 错误文案 + 重试按钮
|
||||
552→ - 空榜+无错:Globe 图标 + "尚无全球记录"提示
|
||||
553→ - 有数据:渲染前 100 条,每条带排名(1-3 名用 Crown/Medal/Award 图标)/ 难度色 / WEEK·TIMED 徽章 / 用时 / 分数
|
||||
554→ - 玩家自己的记录通过 timestamp 匹配 mySubmitTs 高亮:emerald 边框 + emerald 阴影 + YOU 徽章 + emerald 分数色 + 加粗排名
|
||||
555→- QA 验证:
|
||||
556→ - `bun run lint` 零错误零警告(eslint.config.mjs 把 mini-services 加入 ignores)
|
||||
557→ - dev.log 全程无错误,所有编译 < 300ms
|
||||
558→ - mini-service curl 全通过:
|
||||
559→ - GET / → 200 {service, version, ok, uptime}
|
||||
560→ - GET /api/leaderboard (空) → 200 {entries:[], total:0}
|
||||
561→ - POST /api/leaderboard → 200 {entries, total, rank:1}
|
||||
562→ - GET /api/leaderboard (有数据) → 200 {entries:[...], total:N}
|
||||
563→ - GET /api/leaderboard/stats → 200 {totalSubmissions, uniquePlayers, topScore}
|
||||
564→ - OPTIONS 预检 → 204 + 完整 CORS 头(Allow-Origin: *)
|
||||
565→ - 重复 POST(同 dateKey+challenge 10s 内)→ 429 {error:"Rate limited", retryAfterMs}
|
||||
566→ - 网关路由验证:Caddy :81 → localhost:3030 通过 ?XTransformPort=3030 正确转发,返回 JSON 200
|
||||
567→ - agent-browser 集成测试(通过 :81 端口访问,绕过 Next.js 404):
|
||||
568→ - 信标 tab 选中(用 KeyboardEvent Enter 激活 Radix Tabs,因 pointerdown 被覆盖层拦截)
|
||||
569→ - 切到「全球」tab → 自动拉取 → 显示"全球 Top 6 · 已同步" → 渲染 6 条记录
|
||||
570→ - 刷新按钮可点击,旋转动画正常
|
||||
571→ - POST 测试:浏览器 fetch 提交 score=9999 → 返回 rank=1 → 刷新后榜首显示 10.00K
|
||||
572→ - YOU 高亮:手动设置 localStorage[BEACON_CLOUD_LAST_SUBMIT_KEY] 后刷新 → 榜首显示 emerald 边框 + YOU 徽章
|
||||
573→ - VLM 视觉评分(目标 ≥7/10):
|
||||
574→ - 全球榜含 YOU 高亮:**8/10**(双tab切换清晰,全球榜记录完整,难度色与标签规范,视觉层次佳)
|
||||
575→ - 本地榜:**8/10**(双tab切换逻辑清晰,本地tab内容完整,四色规范应用,信息层级合理)
|
||||
576→
|
||||
577→Stage Summary:
|
||||
578→- ✅ mini-service 独立项目:自己的 package.json + bun.lock + node_modules,依赖 hono ^4.6.14,不污染主项目
|
||||
579→- ✅ 端口 3030 + Caddy 网关:前端用相对路径 `fetch('/api/leaderboard?XTransformPort=3030')`,**禁止** localhost:3030
|
||||
580→- ✅ CORS 全开放:origin: * + OPTIONS 预检自动处理,前端跨端口无忧
|
||||
581→- ✅ 内存存储 + 防刷:1000 条上限,同 dateKey+challenge 10s 限 1 次
|
||||
582→- ✅ 三个 claim 入口全部接入云提交:claimBeaconReward(BeaconPanel 直接调)/ claimWeeklyBeacon / claimTimedBeacon(gameStore action 内)
|
||||
583→- ✅ 本地榜保留:loadLeaderboard / pushLeaderboardEntry 未删除,作为离线 fallback
|
||||
584→- ✅ 双 tab UI:本地(amber 主题,立即可用)/ 全球(emerald 主题,按需拉取)+ 刷新按钮 + 加载态 + 错误重试
|
||||
585→- ✅ 玩家高亮:通过 timestamp 匹配 localStorage[BEACON_CLOUD_LAST_SUBMIT_KEY],emerald 边框 + YOU 徽章
|
||||
586→- ✅ lint 零错误 + dev HTTP 200 + VLM 8/10
|
||||
587→- ✅ mini-service 启动稳定:uptime 4+ 分钟,PPID=1(双 fork 模式)
|
||||
588→- 下一阶段工单:P3 #10-c 全球星潮同步(star-tide-service 已在 mini-services 目录中)
|
||||
589→
|
||||
590→---
|
||||
591→Task ID: 10-c
|
||||
592→Agent: full-stack-developer
|
||||
593→Task: #9 手写叙事节点 + P3 socket 多人同步星潮
|
||||
594→
|
||||
595→Work Log:
|
||||
596→- 前置阅读:worklog.md(v0.8.1,四色规范 emerald/rose/amber/fuchsia,禁止蓝色,10 大系统)+ chronicle.ts(680 行)+ starTide.ts(297 行,9 种星潮)+ gameStore.ts(1332 行)+ StarTide.tsx(170 行)+ StarTideOverlay.tsx + Caddyfile(:81 网关 ?XTransformPort 转发规则)+ 前序 10-a/10-b 工单(限时挑战/3 新星潮/云排行榜 mini-service)
|
||||
597→- **状态确认**:本任务为重试,发现上次重试已落地主体代码,本次为验证 + 补 QA + 启动 mini-service + 追加 worklog
|
||||
598→- **工单 #9 手写叙事节点**(chronicle.ts 已就绪):
|
||||
599→ - EPOCH_LORE 常量:5 纪元 × 3 节点(opening/middle/ending)= 15 段手写叙事,每段 80-150 字文学性
|
||||
600→ - 5 纪元主题:1 觉醒(emerald)/2 谐振(rose)/3 遗迹(amber)/4 飞升(fuchsia)/5 终末
|
||||
601→ - 每段含 fallback + variants(按 ctx 命中条件挑变体):
|
||||
602→ - 第一纪元:解码者(≥15)/学者(techs≥5)/里程碑密集(≥2) + 深度轮回(asc>5)
|
||||
603→ - 第二纪元:探险者(≥3)/解码者(≥15)/觉醒天赋 + 深度轮回
|
||||
604→ - 第三纪元:BOSS 猎手(≥2)/深度探险(≥4)/星潮亲历(≥3)/BOSS 收尾 + 深度轮回
|
||||
605→ - 第四纪元:觉醒天赋/蓝图接近完整(≥5)/里程碑密集 + 深度轮回
|
||||
606→ - 第五纪元:里程碑密集(≥3)/星潮汹涌(≥3)/觉醒天赋 + 深度轮回
|
||||
607→ - 变量替换:{decodedThisRun}/{techsThisRun}/{expThisRun}/{bossKillsThisRun}/{blueprintsAfter}/{milestonesCount}/{milestonesList}/{tideCount}/{tideNames}/{perksList}/{minutes}
|
||||
608→ - buildLore 改造:优先 buildHandwrittenLore,无匹配(ascensionNumber 异常)时 fallback 到 v0.4 模板拼接
|
||||
609→ - 验证:bun 脚本测试 5 纪元 × 2 上下文(minimal/rich)= 10 个 case 全通过,文字长度 233-273 字(含收尾段),变体匹配正确,变量替换无残留 {xxx}
|
||||
610→- **P3 socket 多人同步星潮**:
|
||||
611→ - **mini-service(mini-services/star-tide-service/)**:
|
||||
612→ - 独立 bun 项目,package.json type=module + scripts dev:bun --hot index.ts + start:bun index.ts,依赖 socket.io ^4.8.3
|
||||
613→ - index.ts(250 行):
|
||||
614→ - 端口固定 3031,path:"/"(Caddy 据此转发)
|
||||
615→ - 6 种星潮类型表(crystal/resonance/ruins/void/core/silence)+ 权重表 + rollTide
|
||||
616→ - DURATION_SEC=60s 全球星潮持续;FIRST_TIDE_DELAY_MS=60s(QA 友好,env 可覆盖);MIN/MAX_GAP_MS=10-15 分钟随机间隔
|
||||
617→ - 调度:startTide → io.emit("global-tide", {type,name,startedAt,endsAt,durationSec}) → 60s 后 endTide → io.emit("tide-ended", {endedAt,nextTideAt}) → scheduleNextTide(10-15 分钟随机)
|
||||
618→ - 客户端连接:socket.emit("tide-state", {current, nextTideAt, serverTime}) 立即推送
|
||||
619→ - 客户端可 emit "get-next-tide" → 服务端响应 "next-tide-info" {current, nextTideAt, serverTime, remainingMs}
|
||||
620→ - dev/QA 用 "admin-trigger-tide":立即触发一次全球星潮(不等待下次定时器)
|
||||
621→ - 优雅退出:SIGTERM/SIGINT → 清 timer → io.close → httpServer.close → exit(0)
|
||||
622→ - README.md:API/事件文档
|
||||
623→ - **前端集成**:
|
||||
624→ - src/hooks/useGlobalTide.ts(127 行):
|
||||
625→ - 单例 socket(sharedSocket + connectRefCount 引用计数,多组件挂载共享同一连接)
|
||||
626→ - io("/?XTransformPort=3031", {transports:["websocket","polling"], reconnection:true, reconnectionAttempts:Infinity})
|
||||
627→ - 监听 "global-tide" → triggerRef.current(type),用 startedAt+type 去重(防重连重复触发),过期 tide 不触发
|
||||
628→ - 监听 "tide-state" → 连接/重连时若服务端正有进行中的全球星潮,补触发
|
||||
629→ - 主动 emit "get-next-tide" 保险
|
||||
630→ - 导出 adminTriggerGlobalTide(dev 控制台 QA 用),window.__adminTriggerGlobalTide 暴露
|
||||
631→ - gameStore.ts 新增 triggerGlobalTide action + globalTide state:
|
||||
632→ - GLOBAL_TIDE_DURATION_MS = 60_000 常量
|
||||
633→ - GlobalTideState 类型 {type, startedAt, endsAt, id}
|
||||
634→ - TideEvent 新增 isGlobal?: boolean 字段
|
||||
635→ - triggerGlobalTide(type):创建 newTide(60s)+ newGlobalTide,覆盖本地 activeTide(即使本地有进行中的星潮也会被替换),加入 _tideEvents 队列 with isGlobal:true
|
||||
636→ - tickTide 改造:globalTide 优先 → 全球星潮进行中本地不触发新星潮;全球星潮结束时设 globalTide:null + activeTide:null + lastTideEnd + silenceCompensation + ended 事件 with isGlobal:true
|
||||
637→ - partialize 排除 globalTide(瞬态运行时状态,不持久化)
|
||||
638→ - page.tsx 顶层挂载 useGlobalTide()
|
||||
639→ - StarTide.tsx UI 升级:
|
||||
640→ - StarTideIndicator:读 globalTide → isGlobal 标记 → 加 🌐 emoji + ring-1 ring-amber-300/60 + 强化 boxShadow + 渐变背景 + title 改为 "🌐 全球星潮 · {meta.desc}";duration 用 globalTide.endsAt-startedAt 计算(60s)避免越界
|
||||
641→ - StarTideOverlay:全球星潮多一道顶部琥珀色光带 + global-tide-sweep 2.5s 扫光动画 + inset boxShadow 加深(160px vs 120px)
|
||||
642→ - StarTideNotifier:toast 文案区分全球/本地("🌐 全球星潮降临:{name}" + "全球玩家同步经历 · {desc}")
|
||||
643→- **QA 验证**:
|
||||
644→ - `bun run lint` 零错误零警告
|
||||
645→ - dev.log 全程无错误,编译 < 70ms,HTTP 200
|
||||
646→ - mini-service 启动稳定:pid 9456,PPID=1(双 fork 脱离 dev.sh),uptime 19+ 分钟,端口 3031 监听正常
|
||||
647→ - curl http://localhost:3031/ → {"code":0,"message":"Transport unknown"}(socket.io-only 服务预期响应)
|
||||
648→ - curl http://localhost:3031/socket.io/?EIO=4&transport=polling → 正确握手 {"sid":...,"upgrades":["websocket"]}
|
||||
649→ - 网关路由验证:curl http://localhost:81/socket.io/?EIO=4&transport=polling&XTransformPort=3031 → 通过 Caddy 转发到 3031,返回正确握手
|
||||
650→ - socket.io 端到端测试(bun 脚本 /tmp/test-socket.ts):connect ✅ → tide-state ✅ → emit admin-trigger-tide → 504ms 内收到 global-tide {type:ruins, startedAt, endsAt, durationSec:60} ✅
|
||||
651→ - agent-browser 集成测试(通过 http://localhost:81/ 走 Caddy 网关,socket.io 才能正确路由):
|
||||
652→ - 页面加载 200,window.__adminTriggerGlobalTide 已挂载(useGlobalTide hook 已挂载)
|
||||
653→ - 调用 adminTriggerGlobalTide() → 1-3s 内 StarTideIndicator 渲染 🌐 芯片
|
||||
654→ - DOM 验证:芯片文本 "🌐✷虚空低语57s",title "🌐 全球星潮 · 虚空传来回响,洞见获取翻倍"(isGlobal:true 路径生效)
|
||||
655→ - 第二次触发:"🌐⬢遗迹共振59s",title "🌐 全球星潮 · 远古遗迹苏醒,探险力 +5、生命 +30"
|
||||
656→ - 全球星潮结束(60s 后)→ activeTide:null + globalTide:null + lastTideEnd 更新 → 本地 tickTide 恢复正常节奏
|
||||
657→ - VLM 视觉评分:**8/10**(确认 🌐 地球图标 + 汉字名称"遗迹共振" + 倒计时"59s" 全部可见;颜色 emerald/amber/fuchsia/rose 四色规范,零蓝色)
|
||||
658→ - 编年史 buildLore 验证(bun 脚本测试 5 纪元 × 2 上下文 = 10 case):
|
||||
659→ - 全部产出 233-273 字文学性叙事,包含开场+中段+结尾+收尾段
|
||||
660→ - fallback 路径:默认文本,无变量替换
|
||||
661→ - variant 路径:按 ctx 命中条件挑变体,{decodedThisRun}/{bossKillsThisRun}/{milestonesList}/{perksList} 等变量正确替换
|
||||
662→ - 纪元名生成正确:第一纪元·初鸣之夕 / 第二纪元·光谱涌动 / 第三纪元·星辉汇聚 / 第四纪元·以太共振 / 第五纪元·永恒闭环
|
||||
663→
|
||||
664→Stage Summary:
|
||||
665→- ✅ 工单 #9:chronicle.ts EPOCH_LORE 5 纪元 × 3 节点 = 15 段手写叙事(每段 80-150 字文学性),buildLore 优先手写节点 + fallback 模板,buildChronicleEntry/regenerateLoreFromEntry/withPerks 全部接入;10 case 测试通过,变体匹配 + 变量替换正确
|
||||
666→- ✅ P3 socket 多人同步星潮:mini-services/star-tide-service 独立 bun 项目,socket.io 端口 3031,每 10-15 分钟随机广播 global-tide(60s 持续),admin-trigger-tide 供 QA 触发;前端 useGlobalTide hook + gameStore.triggerGlobalTide + globalTide 状态 + tickTide 全球优先 + StarTide UI 🌐 标记 + toast 区分全球/本地
|
||||
667→- ✅ 网关规范:socket.io 严格用 `io("/?XTransformPort=3031")`,path "/",禁止 localhost:3031 直连;Caddy :81 → localhost:3031 转发正确
|
||||
668→- ✅ 离线容错:socket.io 自动重连(Infinity attempts),断连期间本地 tickTide 继续按原节奏工作,玩家不会被卡住;globalTide 不持久化(瞬态运行时状态)
|
||||
669→- ✅ 防重连重复触发:useGlobalTide 用 startedAt+type 去重(Set 上限 32 条 FIFO 清理),过期 tide 不触发
|
||||
670→- ✅ 本地星潮保留:全球星潮是增强而非替换,全球星潮结束后本地 tickTide 恢复正常节奏
|
||||
671→- ✅ mini-service 启动稳定:pid 9456,PPID=1,uptime 19+ 分钟,端口 3031 监听正常
|
||||
672→- ✅ lint 零错误 + dev HTTP 200 + VLM 8/10(🌐 全球星潮标记清晰可见)
|
||||
673→- ✅ 严格四色规范:全球星潮琥珀色扫光(amber)+ 各星潮本色(emerald/rose/amber/fuchsia),零蓝色
|
||||
674→- 下一阶段工单:可考虑 v0.9 收尾(全球星潮成就/编年史全球星潮高亮/星图天文台全球星潮增强天赋)
|
||||
675→
|
||||
676→---
|
||||
677→Task ID: 10
|
||||
678→Agent: main + subagent(10-a/10-b/10-c)
|
||||
679→Task: v0.8.2 工单大清理 — 7 项工单一次性清零
|
||||
680→
|
||||
681→Work Log:
|
||||
682→- 重读工单发现两类列表(已知问题10项 + 下一阶段优先级7项)多项未解决
|
||||
683→- #8 编年史上限+分页(main 自己做):
|
||||
684→ - engine.ts: slice(-50)→slice(-200)
|
||||
685→ - ChronicleDialog.tsx: 加分页(每页10条)+上一页/下一页+页码显示
|
||||
686→- #5 限时挑战 + #3 星潮深化(subagent 10-a 并行):
|
||||
687→ - 限时挑战: BeaconTimedChallenge + 4h时段 + amber主题 + <30min紧急状态
|
||||
688→ - 星潮深化: +3种(surge/eclipse/prism) + 修饰器扩展 + ach_tides_all 6→9
|
||||
689→- #4/P2 云排行榜(subagent 10-b 并行):
|
||||
690→ - mini-service 端口3030 Hono+bun 内存1000条 + CORS + 防刷
|
||||
691→ - 前端双tab(本地/全球) + YOU徽章 + 自动云提交
|
||||
692→- #9 手写叙事 + P3 socket星潮(subagent 10-c):
|
||||
693→ - 5纪元×3节点=15段手写叙事(80-150字) + 11变量替换 + fallback模板
|
||||
694→ - mini-service 端口3031 socket.io 每10-15min广播 + useGlobalTide + 🌐标记
|
||||
695→- P2 UI打磨(main 自己做):
|
||||
696→ - CrystalOrb区: 3层旋转全息环 + 四角标记 + 顶部状态条 + 底部铭文
|
||||
697→- 最终 QA: lint零错误 + dev HTTP200 + VLM 8/10 + 2 mini-service运行中(3030/3031)
|
||||
698→- 提交 v0.8.2(commit 191434e)+ 推送 main + 部署 gh-pages(7e0a59b)HTTP 200
|
||||
699→
|
||||
700→Stage Summary:
|
||||
701→- ✅ 工单 #3 星潮深化: 6种→9种(+surge/eclipse/prism)
|
||||
702→- ✅ 工单 #4 云排行榜: 本地→云端(mini-service 3030)
|
||||
703→- ✅ 工单 #5 限时挑战: 每4h一个额外挑战(amber主题)
|
||||
704→- ✅ 工单 #8 编年史: 上限50→200 + 分页UI
|
||||
705→- ✅ 工单 #9 手写叙事: 5纪元×3节点=15段文学性叙事
|
||||
706→- ✅ P2 UI打磨: CrystalOrb留白→装饰全息环+四角标记+状态条
|
||||
707→- ✅ P3 socket多人星潮: mini-service 3031 + 🌐全球星潮
|
||||
708→- 剩余未解决: #1 Turbopack缓存(环境问题) / #2 定时任务(已文档化)
|
||||
709→- 在线游玩 v0.8.2: https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
710→
|
||||
711→---
|
||||
712→Task ID: 1
|
||||
713→Agent: 主代理 (Phase 1 Bug 修复)
|
||||
714→Task: 获取 Gitea 工单并修复 Issue #2 的 4 个 bug
|
||||
715→
|
||||
716→Work Log:
|
||||
717→- 通过 Gitea API 获取到 2 个未解决工单(Issue #1 + #2)
|
||||
718→- Issue #2 详细分析了 4 个 bug + 4 个玩法问题
|
||||
719→- Bug1 探险只能一次:能量恢复间隔 45→20s,初始能量 3→5,上限 5→8,新增 lastExpeditionSummary 状态记录结果,ExpeditionPanel 入口显示上次结果摘要 + 实时倒计时,新增 dismissExpedition action
|
||||
720→- Bug2 元素偏移/遮挡:标签页 grid-cols-8 → 响应式 grid-cols-4/sm:grid-cols-8,小屏 2 行避免拥挤
|
||||
721→- Bug3 成就UI遮挡:标签面板 max-h 440→520,min-h 提高
|
||||
722→- Bug4 提示框遮挡:toast viewport top-0→top-14 避开 header,TOAST_LIMIT 1→3
|
||||
723→- lint 通过,编译正常
|
||||
724→
|
||||
725→Stage Summary:
|
||||
726→- Phase 1 四个 bug 全部修复完成
|
||||
727→- 探险系统现在有完整的状态反馈:能量实时倒计时、上次结果摘要、刚结束时的结算按钮
|
||||
728→- 标签页移动端不再挤压
|
||||
729→- 待 Phase 2:技术树扩充、晶体球信息卡、成就特效、叙事融入
|
||||
730→
|
||||
@@ -0,0 +1,786 @@
|
||||
1→# 回响星核 / Echo Nexus — 开发工作日志
|
||||
2→
|
||||
3→> 持续性任务的工作交接文档。每个阶段更新,避免进度丢失。
|
||||
4→
|
||||
5→---
|
||||
6→
|
||||
7→## 一、项目当前状态描述 / 判断
|
||||
8→
|
||||
9→### 概况
|
||||
10→- **项目**:回响星核 / Echo Nexus — 深空考古放置策略游戏
|
||||
11→- **一句话**:自治无人机采矿 → 解码记忆晶体(原创共振谜题)→ 拼凑碎片叙事 → 飞升多周目。差异化:解码谜题驱动叙事涌现,全息晶体 + 深空粒子美学。
|
||||
12→- **当前版本**:**v0.7**(CrystalOrb Canvas 粒子系统 + 角色属性系统)
|
||||
13→- **在线游玩**:https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
14→- **仓库**:https://git.atdunbg.xyz/Super_Z/echo-nexus
|
||||
15→- **技术栈**:Next.js 16 (App Router) + TypeScript + Tailwind + shadcn/ui + Canvas 2D + Zustand + Web Audio API
|
||||
16→- **定时任务**:每 15 分钟一次 `webDevReview`(`fixed_rate` + `"900"` 秒,priority=10,job_id 228266)。正常完成不会被删除,无需自持续机制。
|
||||
17→
|
||||
18→### 状态判断
|
||||
19→- dev 服务器运行正常(HTTP 200,编译 < 250ms)
|
||||
20→- v0.7 两大新功能已完成:CrystalOrb Canvas 粒子系统升级(VLM 8/10)+ 角色属性系统(VLM 7/10)
|
||||
21→- 系统总体稳定,无阻塞性 bug,可继续推进新功能
|
||||
22→
|
||||
23→### 已完成版本里程碑(精简)
|
||||
24→| 版本 | 核心内容 |
|
||||
25→|------|---------|
|
||||
26→| v0.1 | MVP:放置采矿 + 解码共振谜题 + 技术树 + 记忆图谱 + 飞升 + 统计 |
|
||||
27→| v0.1.1 | 解码可解性修复(路径构造法生成器,100% 可解率)|
|
||||
28→| v0.2 | 遗迹探险肉鸽系统(能量/探险力/6 节点/程序化路径/BOSS)|
|
||||
29→| v0.2.1 | 程序化音频(15 种音效)+ 14 项成就 + 视觉打磨 |
|
||||
30→| v0.3 | 星潮事件系统(6 种星潮 + 全屏叠层 + 程序化音效)|
|
||||
31→| v0.3.1 | 星图天文台元进程(6 类 × 3 = 18 天赋 + 飞升后 3 选 1 draft + Canvas 星图)|
|
||||
32→| v0.4 | 回响编年史(5 纪元循环命名 + 模板化叙事 + 时间轴 UI + 6 项新成就 + 飞升 BUG 修复)|
|
||||
33→| v0.5 | 深空信标(每日挑战 + 本地排行榜 Top20 + 7 标签页 + 编年史历史 BUG 修复)|
|
||||
34→| v0.5.1 | 静态部署 Gitea Pages + 新手教程系统(7 步聚光灯引导)+ UI 间距优化 |
|
||||
35→| v0.5.2 | 离线收益报告弹窗 + 标签页 UI 重设计 + persist rehydrate 竞态修复 |
|
||||
36→| v0.6 | 深空巡航 Canvas 2D 实时玩法 + UI 偏移重叠修复 |
|
||||
37→| **v0.7** | **CrystalOrb Canvas 粒子系统升级 + 角色属性系统(四维)** |
|
||||
38→
|
||||
39→### 核心系统清单(8 大系统)
|
||||
40→1. **放置采矿** — 中央晶体球 + 主动脉冲 + 连击加成(`CrystalOrb.tsx`)
|
||||
41→2. **谐振解码** — 原创路径谜题,路径构造法 100% 可解(`DecodeArray.tsx` + `engine.ts`)
|
||||
42→3. **技术树** — 三层科技解锁,提升产能/解码/探险(`TechTree.tsx`)
|
||||
43→4. **遗迹探险** — 肉鸽系统,6 种节点 + 程序化路径 + BOSS(`ExpeditionPanel.tsx` + `expedition.ts`)
|
||||
44→5. **星潮事件** — 6 种动态事件,为放置循环注入变化(`StarTide.tsx` + `starTide.ts`)
|
||||
45→6. **星图天文台** — 飞升后 3 选 1 天赋 draft,跨周目永久生效,18 个天赋(`ConstellationPanel.tsx` + `constellation.ts`)
|
||||
46→7. **回响编年史** — 跨周目叙事时间轴,5 纪元循环命名(`ChronicleDialog.tsx` + `chronicle.ts`)
|
||||
47→8. **深空信标** — 每日挑战 + 本地排行榜 Top20(`BeaconPanel.tsx` + `beacon.ts`)
|
||||
48→9. **深空巡航** — Canvas 2D 实时玩法,飞船操控/陨石躲避/星门通关(`CruiseMode.tsx` + `cruise.ts`)【v0.6】
|
||||
49→10. **角色属性系统** — 四维属性(探索力/智慧/勇气/灵感),飞升获得属性点,影响所有系统(`AttributesPanel.tsx` + `attributes.ts`)【v0.7 新增】
|
||||
50→
|
||||
51→---
|
||||
52→
|
||||
53→## 二、当前目标 / 已完成的修改 / 验证结果
|
||||
54→
|
||||
55→### v0.7 CrystalOrb Canvas 粒子系统升级(已完成)
|
||||
56→**动机**:P0 优先级 — 将中央晶体球从 CSS 动画升级为 Canvas 粒子视觉盛宴,提升视觉震撼。
|
||||
57→
|
||||
58→**重写文件**:`src/components/game/CrystalOrb.tsx`
|
||||
59→- 从纯 CSS 动画升级为 Canvas 2D 粒子系统
|
||||
60→- **多层粒子**:
|
||||
61→ - 环绕能量粒子(3层14/10/8个,emerald/fuchsia/rose三色,不同速度方向环绕晶核,带拖尾)
|
||||
62→ - 环境星尘(40个,缓慢漂移 + 闪烁)
|
||||
63→ - 点击爆发粒子(10-30个径向发散,颜色随连击等级变色)
|
||||
64→ - 冲击波环(点击触发1-3层错峰扩散,连击≥3/5解锁更多层)
|
||||
65→- **晶核升级**:径向渐变辉光 + 3层六边形纹理旋转 + 高光 + 鼠标视差偏移
|
||||
66→- **呼吸动画**:晶核 + 外层辉光随时间呼吸(sin波)
|
||||
67→- **进度环**:SVG渐变环(emerald→fuchsia→rose)保留
|
||||
68→- **交互保留**:点击脉冲、连击Toast、浮动数字、音效、`data-tut="crystal-orb"` 锚点
|
||||
69→- **性能**:DPR cap 2,ResizeObserver 自适应,requestAnimationFrame 60fps
|
||||
70→
|
||||
71→**QA 验证**(agent-browser + VLM):
|
||||
72→- VLM 视觉评分 **8/10**:晶体球清晰可见,多层辉光,环绕粒子动态自然,无渲染问题
|
||||
73→- 点击交互:冲击波环 ✅ + 爆发粒子 ✅,评分 7/10
|
||||
74→- lint 零错误;HTTP 200
|
||||
75→
|
||||
76→### v0.7 角色属性系统(已完成)
|
||||
77→**动机**:P1 优先级 — 增加RPG深度,四维属性影响所有游戏系统。
|
||||
78→
|
||||
79→**新增文件**:
|
||||
80→- `src/lib/game/attributes.ts`(~330行逻辑层):CharacterAttributes/AttributeProgress 类型、ATTRIBUTE_CONFIG 元信息、getAttributeBonus 两区加成公式(0-50线性+0.5%/点,50-100递减+0.2%/点)、getAllBonuses 12项修饰器、levelUpCheck 自动升级、computePrestigeAttrPoints、migrateAttributes 旧存档兼容
|
||||
81→- `src/components/game/AttributesPanel.tsx`(~330行 UI):四维卡片网格(小屏2×2/大屏1×4)、图标+中英文名+Lv.badge+数值/100+加成%+经验条+影响列表+分配按钮、顶部待分配点数badge闪烁、底部总览+12项修饰器明细
|
||||
82→
|
||||
83→**修改文件**:
|
||||
84→- `types.ts`:GameState 新增 attributes/attributeProgress/pendingAttrPoints
|
||||
85→- `config.ts`:INITIAL_STATE 补全默认值
|
||||
86→- `engine.ts`:recomputeStats 聚合属性加成;performPrestige 发放属性点(ascensions×2+1)
|
||||
87→- `gameStore.ts`:新增 allocateAttribute/gainAttributeExp actions;pulse/clickNode/autoDecodeTick/resolveCurrentNode/grantCruiseReward/tickTide 全部接入属性经验;init() 调用 migrateAttributes
|
||||
88→- `achievements.ts`:新增 ach_attr_total_50 + ach_attr_max_100 两项成就
|
||||
89→- `page.tsx`:grid-cols-7→8,新增「角色」标签页(User图标),红点提示,StatsPanel新增5行属性行,版本号 v0.6→v0.7
|
||||
90→
|
||||
91→**四维属性设计**:
|
||||
92→- 探索力(emerald):探险力+X%/巡航飞船速度+X%
|
||||
93→- 智慧(fuchsia):解码步数+X/洞见+X%/自动解码周期-X%
|
||||
94→- 勇气(amber):探险生命+X/BOSS胜率+X%/巡航护盾+X
|
||||
95→- 灵感(rose):接触率+X/星潮概率+X/脉冲连击+X%
|
||||
96→
|
||||
97→**QA 验证**(agent-browser + VLM):
|
||||
98→- VLM 视觉评分 **7/10**(面板)/ **8/10**(待分配状态):四维卡片可见、数值/等级/加成/经验条齐全、四色全息
|
||||
99→- 功能验证:setState pendingAttrPoints=5 → 显示5点待分配 → 点击分配按钮 → exploration 0→1, pending 5→4 ✅
|
||||
100→- lint 零错误;HTTP 200
|
||||
101→
|
||||
102→---
|
||||
103→
|
||||
104→### v0.6 深空巡航 Canvas 2D 实时玩法(历史记录)
|
||||
105→**动机**:回应用户反馈「玩法太单调(全是点点点)」+「视觉震撼不足」——首次引入实时操作玩法。
|
||||
106→
|
||||
107→**新增文件**:
|
||||
108→- `src/lib/game/cruise.ts`(~520 行逻辑层)
|
||||
109→ - 类型系统:CruiseEntity 联合类型(ship/asteroid/storm/crystal/insight/beacon/stargate/particle 共 8 种)
|
||||
110→ - mulberry32 + FNV-1a 种子化 RNG(`cruiseSeed(level)`)
|
||||
111→ - `generateLevel`:程序化生成陨石带(8+lvl×2)、虚空风暴(1+lvl/2)、晶体碎片(5+lvl)、洞见光球(2+lvl/3)、信标(1+lvl/4)、星门
|
||||
112→ - `updateCruise`:物理推进 + 碰撞检测 + 粒子系统 + 震动 + 600ms 无敌帧
|
||||
113→ - `computeRewards`:crystals=碎片×(8+lvl×2)、insights=洞见×(2+lvl×0.5)、contact=信标×(1.5+lvl×0.3);通关×1.5、失败×0.5
|
||||
114→ - 独立 localStorage `echo-nexus-cruise-v1`:最高分/累计通关/最高关卡/累计奖励/最近 20 局
|
||||
115→
|
||||
116→- `src/components/game/CruiseMode.tsx`(~830 行渲染层)
|
||||
117→ - 全屏 fixed inset-0 z-50 Canvas,DPR cap 2,resize 监听
|
||||
118→ - 3 层视差星空:远(100星)/中(60星)/近(30星),独立漂移 + 飞船速度视差 + 闪烁
|
||||
119→ - 8 种实体全部 ctx.shadowBlur 辉光绘制
|
||||
120→ - 粒子系统:尾焰/收集/碰撞/烟花,上限 200
|
||||
121→ - 屏幕震动 280ms 衰减;低护盾(<30%)红色边框脉冲
|
||||
122→ - HUD(HTML 叠层,glass+backdrop-blur,80ms 节流):护盾/能量/分数/用时/收集计数
|
||||
123→ - 控制:桌面 WASD/方向键 8 方向 + 移动端虚拟摇杆 + P 暂停 + Esc 退出 + 失焦自动暂停
|
||||
124→ - 阶段:ready → playing → won/lost(结算明细 + 奖励 + 下一关/重试/返回)
|
||||
125→
|
||||
126→**修改文件**:
|
||||
127→- `src/app/page.tsx`:header 新增 amber 主题「巡航」按钮(Navigation 图标)+ cruiseOpen state + 条件渲染 CruiseMode
|
||||
128→- `src/store/gameStore.ts`:新增 `grantCruiseReward({crystals?, insights?, contact?})` action(crystals 受 crystalCap 限制,contact 受 100 上限)
|
||||
129→- 版本号 v0.5.2 → v0.6
|
||||
130→
|
||||
131→**UI 偏移/重叠 BUG 修复**(3 处):
|
||||
132→- `DecodeArray.tsx`:移除 className 冲突的 `-translate-x-1/2 -translate-y-1/2`,统一用 inline transform 定位+缩放
|
||||
133→- `AchievementsPanel.tsx`:移除内层 `max-h-[300px]`,改 `flex-1 min-h-0` 自适应父容器
|
||||
134→- `page.tsx`:调整三个 section 的 min-h,避免小屏单列时总高度超过手机视口
|
||||
135→
|
||||
136→**色彩规范**:严格遵循 emerald(#34d399) / rose(#fb7185) / amber(#fbbf24) / fuchsia(#e879f9) 四色全息色谱,零蓝色/靛色
|
||||
137→
|
||||
138→**QA 验证**(agent-browser + VLM):
|
||||
139→- lint 零错误;dev 服务器 HTTP 200;编译 < 250ms
|
||||
140→- VLM 确认主界面:巡航按钮存在、晶体球居中、解码区正常、无重叠偏移
|
||||
141→- VLM 确认巡航玩法:飞船可见(绿色三角形)、HUD 完整、陨石+星空背景、粒子特效(黄色尾焰+紫色辉光)
|
||||
142→- WASD 控制飞船移动,按 W 直冲星门 → 通关,奖励 +30 晶体(2×10×1.5=30 计算正确)
|
||||
143→- localStorage 正确记录 highScore/totalRuns/totalWins/bestLevel
|
||||
144→- 奖励同步 gameStore(grantCruiseReward,满仓时 cap 逻辑正确)
|
||||
145→- 退出返回主界面,7 标签页 + 晶体球 + 解码面板均完好
|
||||
146→
|
||||
147→---
|
||||
148→
|
||||
149→## 三、未解决问题或风险 / 下一阶段优先事项
|
||||
150→
|
||||
151→### 已知问题 / 风险
|
||||
152→1. **dev 服务器 Turbopack 缓存偶发损坏**:`Unable to open static sorted file` + 进程被杀,需 `rm -rf .next` 重启。静态导出构建稳定可靠。
|
||||
153→2. **定时任务调度类型**:必须用 `fixed_rate` + `"900"` 秒(15分钟),不要用 cron 表达式。`webDevReview` 类型任务正常完成不会被删除,只有抛出未捕获异常才会被标记失败。
|
||||
154→3. **v0.3 星潮为单机版**:原计划 socket 全局事件,后续可扩展为多人同步。
|
||||
155→4. **v0.5 信标排行榜为本地版**(纯 localStorage):升级云排行榜需后端 API。
|
||||
156→5. **v0.5 每日挑战仅 1 个/天**:可加入"周挑战"或"信标链"(连续完成 N 天奖励)。
|
||||
157→6. **探险 BOSS 战胜率较低**:基础探索力 10 vs BOSS 难度 5-7,胜率约 25%,需玩家投资探险技术。
|
||||
158→7. **探险能量恢复较慢**:45s/点,可加技术提升恢复速度。
|
||||
159→8. **编年史上限 50 条**:超过自动丢弃最早的;v0.4 之前飞升无回填(空状态有提示)。
|
||||
160→9. **5 纪元叙事为模板化生成**:v0.5+ 将加入手写剧情节点。
|
||||
161→10. ~~**CrystalOrb 仍为 CSS 动画**~~ → ✅ **v0.7 已完成 Canvas 粒子系统升级**。
|
||||
162→
|
||||
163→### 下一阶段优先级(v0.7 后修正版)
|
||||
164→> 工单修正:原 P0 CrystalOrb Canvas + P1 角色属性两项均已在 v0.7 完成,现重新排序。
|
||||
165→
|
||||
166→1. **🔴 P0 — 巡航玩法大增强(v0.8 主线)**:BOSS 战关卡(每 5 关一个 BOSS,三阶段攻击模式 + 飞船射击系统)/ 道具掉落(5 种 powerup:护盾/能量/急速/超载/磁吸)/ 事件选择节点(每关通关后 3 选 1 强化牌,10 种强化)。这是当前最高优先级,能显著提升巡航玩法的深度与可玩性。
|
||||
167→2. **🟠 P1 — 探险 BOSS 战胜率平衡 + 探险能量恢复**:修复已知问题 6/7(探险 BOSS 胜率 25% 偏低,能量 45s/点 偏慢),提升探险体验。
|
||||
168→3. **🟠 P1 — 信标系统扩展**:周挑战 / 信标链(连续完成 N 天奖励),修复已知问题 5。
|
||||
169→4. **🟡 P2 — UI 样式细节打磨**:标签页图标/文字比例、视觉层次强化、移动端响应式进一步优化、CrystalOrb 周边留白优化(VLM 指出主界面左侧有空白)。
|
||||
170→5. **🟡 P2 — 云存档 + 云排行榜**:v0.5+ 后端 API(需评估是否引入 mini-service)。
|
||||
171→6. **🟢 P3 — 全 5 纪元手写叙事节点**:替换模板化 lore。
|
||||
172→7. **🟢 P3 — socket 多人同步星潮**:全局事件共享。
|
||||
173→
|
||||
174→### 定时任务(fixed_rate · 900s)
|
||||
175→- **当前 job_id**: **228357**(2026-06-24 13:25 重建)
|
||||
176→- **配置**: `fixed_rate` + `"900"`(15分钟间隔),`priority=10`(高优先级),`payload.kind=webDevReview`,`tz=Asia/Shanghai`
|
||||
177→- **任务名**: Echo Nexus - 任务审查与持续迭代
|
||||
178→- **任务描述强制要求**:每次触发 MUST 先完整阅读 worklog.md 工单,以工单为准,不凭记忆工作
|
||||
179→- **正常完成不会被删除**,只有未捕获异常会标记失败。若任务列表为空,需用 cron create 重建(schedule.kind=fixed_rate, expr="900", priority=10, payload.kind=webDevReview)。
|
||||
180→- **job_id 历史**: 227909(失效) → 228130(失效) → 228172(失效) → 228186(失效) → 228218(删除重建) → 228236(cron版,删除重建) → 228266(fixed_rate,失效) → 228329(失效) → **228357(当前,重建)**
|
||||
181→
|
||||
182→---
|
||||
183→
|
||||
184→## 定时任务描述模板(webDevReview · fixed_rate)
|
||||
185→
|
||||
186→> 重建参数:schedule.kind=`fixed_rate`, schedule.expr=`"900"`, params.priority=`10`, payload.kind=`webDevReview`
|
||||
187→
|
||||
188→```
|
||||
189→请先判断当前项目状态,使用 agent-browser 进行必要测试和 QA,然后自主选择本轮最合适的工作重点并继续开发。
|
||||
190→
|
||||
191→要求:
|
||||
192→1. 开始任务时查看 /home/z/my-project/worklog.md 了解实际进展,拆解详细todo
|
||||
193→2. 使用 agent-browser 进行测试和QA,有bug优先修复
|
||||
194→3. 如果稳定,自主提出新需求继续推进
|
||||
195→4. 样式要越做细节越多!!
|
||||
196→5. 功能要越做越多!!
|
||||
197→6. 工作告一段落更新 /home/z/my-project/worklog.md
|
||||
198→7. 项目结束后一定要把工作记录写在 worklog.md 里
|
||||
199→
|
||||
200→交接文档建议包含三部分:
|
||||
201→- 项目当前状态描述/判断
|
||||
202→- 当前目标/已完成的修改/验证结果
|
||||
203→- 未解决问题或风险,建议下一阶段优先事项
|
||||
204→```
|
||||
205→
|
||||
206→---
|
||||
207→
|
||||
208→## 历史详细版本记录(按需查阅 docs/repo/docs/)
|
||||
209→
|
||||
210→- `04-解码系统修复-v0.1.1.md`
|
||||
211→- `05-遗迹探险系统-v0.2.md`
|
||||
212→- `06-音频与成就系统-v0.2.1.md`
|
||||
213→- `07-星潮事件系统-v0.3.md`
|
||||
214→- `08-星图天文台系统-v0.3.1.md`
|
||||
215→- `09-回响编年史系统-v0.4.md`
|
||||
216→- `10-深空信标系统-v0.5.md`
|
||||
217→
|
||||
218→---
|
||||
219→
|
||||
220→Task ID: 7
|
||||
221→Agent: full-stack-developer
|
||||
222→Task: 角色属性系统(探索力/智慧/勇气/灵感)
|
||||
223→
|
||||
224→Work Log:
|
||||
225→- 阅读 worklog.md 了解 v0.6 项目背景,确认 8 大系统架构与四色全息色彩规范
|
||||
226→- 新建 `src/lib/game/attributes.ts` 逻辑层(~330 行):
|
||||
227→ - 定义 CharacterAttributes/AttributeProgress/AttributeKey 类型 + ATTRIBUTE_CONFIG 元信息
|
||||
228→ - getAttributeBonus 线性+递减两区加成公式(0-50 每 10 点 +5%,50-100 每点 +2%)
|
||||
229→ - getAllBonuses 返回 12 个修饰器(探险力/巡航速度/解码步数/洞见/自动解码周期/探险生命/BOSS 胜率/巡航护盾/接触率/星潮触发/脉冲连击/产能)
|
||||
230→ - levelUpCheck 自动跨多级 + expRequiredForLevel + computePrestigeAttrPoints + migrateAttributes 兼容
|
||||
231→- 扩展 `src/lib/game/types.ts` GameState:新增 attributes/attributeProgress/pendingAttrPoints
|
||||
232→- 扩展 `src/lib/game/config.ts` INITIAL_STATE:补全默认值(0 数值 + 空 progress)
|
||||
233→- 扩展 `src/lib/game/engine.ts`:
|
||||
234→ - recomputeStats 末尾聚合 am.crystalsPerSecMult/insightMultAdd/contactRateMult/decodeStepsBonus
|
||||
235→ - performPrestige 保留 attributes 数值,清空 attributeProgress,发放 ascensions × 2 + 1 点属性点
|
||||
236→ - createInitialState 每次返回全新对象避免引用共享
|
||||
237→- 扩展 `src/store/gameStore.ts`(核心改造,10+ 处 syncStats 调用全部补 attributes 参数):
|
||||
238→ - pulse:连击 ≥3 给灵感经验 + 脉冲威力乘灵感连击加成
|
||||
239→ - clickNode 完成:给智慧经验(tier × 2)
|
||||
240→ - autoDecodeTick:智慧经验 +1 + 自动解码周期受 am.autoDecodeIntervalMult 影响
|
||||
241→ - startExpedition:探险力乘 am.expeditionPowerMult,生命加 am.expeditionHpBonus
|
||||
242→ - resolveCurrentNode:BOSS 节点包装 RNG 提升 +am.bossWinRateBonus 胜率;战斗胜利给勇气+探索力经验
|
||||
243→ - grantCruiseReward:按总奖励量给探索力+勇气经验
|
||||
244→ - tickTide:灵感 am.tideTriggerBonus 缩短星潮间隙(上限 30%)
|
||||
245→ - init() 调用 migrateAttributes 补全旧存档
|
||||
246→ - 新增 allocateAttribute / gainAttributeExp 两个 action
|
||||
247→- 新建 `src/components/game/AttributesPanel.tsx` UI 面板(~330 行):
|
||||
248→ - 四维卡片网格(小屏 2×2,大屏 1×4)
|
||||
249→ - 每张卡片:图标 + 中英文名 + Lv.badge + 数值/100 + 加成% + 经验条 + 影响列表 + 「+分配」按钮
|
||||
250→ - 顶部待分配点数 badge(pendingAttrPoints > 0 时 echo-pending-pulse 闪烁动画)
|
||||
251→ - 底部总等级/总加成概览 + 12 个修饰器明细
|
||||
252→ - 4 色辉光边框(emerald/fuchsia/amber/rose),顶角光晕装饰
|
||||
253→- 接入 `src/app/page.tsx`:
|
||||
254→ - grid-cols-7 → grid-cols-8,新增第 8 个「角色」TabsTrigger(User 图标,渐变主题)
|
||||
255→ - pendingAttrPoints > 0 时显示 rose 红点提示
|
||||
256→ - 渲染 AttributesPanel
|
||||
257→ - StatsPanel 新增 5 行属性行(探索力/智慧/勇气/灵感/待分配点)
|
||||
258→ - 版本号 v0.6 → v0.7
|
||||
259→- 新增 `src/lib/game/achievements.ts` 2 项成就:
|
||||
260→ - ach_attr_total_50(四维觉醒):总属性 ≥ 50 → 产能+6%/洞见+6%
|
||||
261→ - ach_attr_max_100(维度精通):任一属性 100 → 产能+12%/洞见+10%
|
||||
262→- 写入 `agent-ctx/7-full-stack-developer.md` 工作记录
|
||||
263→- 最终验证:lint 零错误 + dev 服务器 HTTP 200 + 编译 < 250ms
|
||||
264→
|
||||
265→Stage Summary:
|
||||
266→- ✅ 角色属性系统 v0.7 P1 全部完成
|
||||
267→- ✅ 新增 2 文件(attributes.ts + AttributesPanel.tsx),修改 6 文件(types/config/engine/gameStore/achievements/page)
|
||||
268→- ✅ 四维属性完整接入游戏各系统(探险/解码/脉冲/巡航/星潮)
|
||||
269→- ✅ 飞升属性点公式 = ascensions × 2 + 1;经验累积自动升级(每级 10×level)
|
||||
270→- ✅ 旧存档兼容(migrateAttributes 补全字段,同步 level 与 attributes)
|
||||
271→- ✅ lint 零错误 + HTTP 200 + 编译 < 250ms
|
||||
272→- ✅ 严格四色全息(emerald/fuchsia/amber/rose),零蓝色/靛色
|
||||
273→- ✅ 8 标签页 + 巡航按钮全部保留,data-tut 锚点未破坏
|
||||
274→- ✅ 待分配点数时标签页 rose 红点提示 + 顶部 badge 闪烁
|
||||
275→
|
||||
276→---
|
||||
277→Task ID: 8-deploy
|
||||
278→Agent: main
|
||||
279→Task: 重建定时任务 + 更新 README + 部署 gh-pages(v0.7)
|
||||
280→
|
||||
281→Work Log:
|
||||
282→- 检查项目状态:CrystalOrb.tsx 已是 v0.7 Canvas 粒子系统(659 行),无活动 cron job
|
||||
283→- 重建定时任务:cron create fixed_rate="900" priority=10 webDevReview → job_id 228329(tz=Asia/Shanghai)
|
||||
284→- 重写 README.md:
|
||||
285→ - 顶部显著位置添加「在线游玩」链接(https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/)
|
||||
286→ - 版本号 v0.1 → v0.7
|
||||
287→ - 新增 10 大系统表格(含 v0.6 巡航 + v0.7 角色属性)
|
||||
288→ - 完整开发路线表(v0.1-v1.0,标记 ✅/🔜 状态)
|
||||
289→ - 新增本地开发命令 + Gitea Pages 部署指南
|
||||
290→ - 文档索引扩展至 10 个版本文档
|
||||
291→- 静态导出:BUILD_EXPORT=true bun run build:static → out/ 1.6M(HTTP 200 编译 4.3s)
|
||||
292→- 推送 gh-pages 分支:force push origin gh-pages(commit 8727fed "deploy: v0.7")
|
||||
293→- 提交 main:README 更新(commit 43dfc2d "docs: README 添加在线游玩链接 + v0.7 状态更新")
|
||||
294→- 验证 Gitea Pages:https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/ → HTTP 200 ✅
|
||||
295→- QA 验证:agent-browser 打开 http://localhost:3000/ → VLM 评分 8/10(主界面 polished,minor 空白)
|
||||
296→
|
||||
297→Stage Summary:
|
||||
298→- ✅ 定时任务重建成功(job_id 228329,每 15 分钟自动审查迭代)
|
||||
299→- ✅ README 重写完成,网站链接显著展示,v0.7 状态完整
|
||||
300→- ✅ gh-pages 部署成功,Gitea Pages HTTP 200 可访问
|
||||
301→- ✅ main 分支已同步推送(README + worklog 更新)
|
||||
302→- ✅ dev 服务器健康(HTTP 200,编译 < 250ms)
|
||||
303→- ✅ CrystalOrb v0.7 Canvas 粒子系统已确认完整(659 行)
|
||||
304→- 下一步:v0.8 巡航玩法增强(BOSS 战 / 道具掉落 / 事件选择节点)
|
||||
305→
|
||||
306→---
|
||||
307→Task ID: 8
|
||||
308→Agent: main
|
||||
309→Task: v0.8 巡航玩法大增强(BOSS 战 + 道具掉落 + 事件选择节点)+ 工单修正 + 审查流程重建
|
||||
310→
|
||||
311→Work Log:
|
||||
312→- 重读 worklog 工单,发现 v0.7 两项(CrystalOrb Canvas + 角色属性)已完成但工单"下一阶段优先级"未更新
|
||||
313→- 修正 worklog 工单:标注 P0/P1 v0.7 已完成,重新排序下一阶段优先级(P0=巡航增强, P1=探险平衡/信标扩展, P2=UI打磨/云存档, P3=叙事/多人)
|
||||
314→- 重建审查流程 cron job:fixed_rate=900s, priority=10, webDevReview, tz=Asia/Shanghai, job_id=228357
|
||||
315→ - 任务描述强制要求:每次触发 MUST 先完整阅读 worklog.md 工单,以工单为准,不凭记忆工作
|
||||
316→- 发现之前被中断的 v0.8 subagent 已写入 2037 行代码(cruise.ts +1487 / CruiseMode.tsx +858 / page.tsx +2)
|
||||
317→- 修复 2 个 lint 错误(react-hooks/set-state-in-effect):
|
||||
318→ - isTouch: useState(false) + useEffect(setIsTouch) → useState initializer
|
||||
319→ - stats: useState(null) + useEffect(setStats(loadCruiseStats)) → useState initializer
|
||||
320→- QA 验证(agent-browser + VLM):
|
||||
321→ - 主界面 VLM 7/10:v0.8 版本号 ✅ + 巡航按钮 ✅
|
||||
322→ - 巡航 READY 阶段 VLM 8/10:BOSS 战说明 ✅(每5关BOSS战/击败BOSS)+ 射击控制说明 ✅(空格/右下角射击按钮)
|
||||
323→ - 巡航第1关游戏 VLM 8/10:飞船(绿色三角)✅ + HUD(护盾/能量/分数/计时)✅ + 陨石/收集物/能量场 ✅ + 无渲染错误
|
||||
324→- 提交 v0.8(commit 494bc5f)+ 推送 main
|
||||
325→- 静态导出 BUILD_EXPORT=true → out/ 1.6M(编译 4.1s)
|
||||
326→- 部署 gh-pages(force push, commit b865922)→ Gitea Pages HTTP 200 ✅
|
||||
327→
|
||||
328→Stage Summary:
|
||||
329→- ✅ 工单修正完成:v0.7 已完成项标注清楚,下一阶段优先级重新排序
|
||||
330→- ✅ 审查流程重建:cron job_id 228357,每15分钟触发,强制读工单
|
||||
331→- ✅ v0.8 巡航玩法大增强全部完成并部署:
|
||||
332→ - BOSS 战系统(每5关,三阶段攻击,HP条,击败奖励×3)
|
||||
333→ - 飞船射击系统(空格/射击按钮,能量消耗,子弹尾焰)
|
||||
334→ - 道具掉落(5种powerup:护盾/能量/急速/超载/磁吸)
|
||||
335→ - 事件选择节点(每关通关后3选1,10种强化牌)
|
||||
336→ - lint 零错误 + dev HTTP 200 + gh-pages HTTP 200
|
||||
337→- ✅ VLM 评分:主界面 7/10 + 巡航READY 8/10 + 巡航游戏 8/10
|
||||
338→- 在线游玩 v0.8:https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
339→- 下一阶段工单:P1 探险BOSS胜率平衡 + 探险能量恢复 / 信标系统扩展(周挑战/信标链)
|
||||
340→
|
||||
341→---
|
||||
342→Task ID: 9-b
|
||||
343→Agent: full-stack-developer
|
||||
344→Task: 信标系统扩展(周挑战 + 信标链连续奖励)
|
||||
345→
|
||||
346→Work Log:
|
||||
347→- 阅读现有 `src/lib/game/beacon.ts`(v0.5 每日挑战 + 本地排行榜,358 行)+ `src/components/game/BeaconPanel.tsx` + `src/store/gameStore.ts` 的 `trackBeacon` 函数(约第 173 行)+ worklog v0.8 项目状态,确认四色全息规范与现有架构。
|
||||
348→- **扩展 `src/lib/game/beacon.ts`(358 → 873 行,新增 ~515 行)**:
|
||||
349→ - **周挑战(WEEKLY CHALLENGE)**:
|
||||
350→ - `BeaconWeeklyChallenge` 接口(weekKey YYYY-Www / type / difficulty 强制 anomaly|singular / goal / rewardInsight / rewardContact / seed / title / desc)
|
||||
351→ - `BeaconWeeklyProgress` 接口(weekKey / progress / startedAt / completedAt / claimed / durationSec)
|
||||
352→ - `getWeekKey(now)`:ISO 8601 周键(周一为起点,含首个周四的周为第一周)
|
||||
353→ - `weekKeyToSeed`:FNV-1a 哈希
|
||||
354→ - `generateWeeklyChallenge(now)`:基于 weekKey 种子确定性生成,难度加权 anomaly 60% / singular 40%,goal 为日基准 ×3-5 倍(decode 18-75 / expedition 3-15 / pulse 60-245 / boss 3-12 / insight 120-595)
|
||||
355→ - `loadWeeklyProgress` / `saveWeeklyProgress` / `addWeeklyProgress` / `claimWeeklyReward`(推送排行榜,entry 加 `isWeekly: true`)
|
||||
356→ - `msUntilNextWeek(now)`:距离下周一 UTC 0 点的毫秒数
|
||||
357→ - `BEACON_WEEKLY_KEY = "echo-nexus-beacon-weekly-v1"`
|
||||
358→ - **信标链(BEACON CHAIN)**:
|
||||
359→ - `BeaconChainState` 接口(lastCompletedDateKey / currentStreak / longestStreak / totalCompletions / graceUsed / milestonesClaimed)
|
||||
360→ - `BEACON_CHAIN_KEY = "echo-nexus-beacon-chain-v1"`
|
||||
361→ - `BEACON_CHAIN_MILESTONES = [3, 7, 14, 30]` 常量
|
||||
362→ - `BEACON_CHAIN_REWARDS`:4 个里程碑(三日谐振 +50/+5 / 七日回响 +120/+12 / 半月星潮 +280/+28 / 满月飞升 +680/+68)
|
||||
363→ - `loadChainState` / `saveChainState`(每次返回新对象避免引用共享)
|
||||
364→ - `recordChainCompletion(dateKey)` 核心逻辑:同日重复忽略;次日 streak++;隔一天 miss 且 graceUsed<1 时续命 streak++ graceUsed++;其他断链 streak=1 graceUsed=0;返回 `{ state, newMilestones }`
|
||||
365→ - `claimChainMilestone(milestone)` / `getNextMilestone(streak)` / `getChainProgress(streak)`(返回 current/next/prev/progressPct 用于 UI)
|
||||
366→ - `dateKeyToTimestamp` / `dateKeyDiffDays` 工具函数
|
||||
367→ - `BeaconScoreEntry` 新增可选 `isWeekly?: boolean` 字段
|
||||
368→- **扩展 `src/store/gameStore.ts`**:
|
||||
369→ - import 扩展:generateWeeklyChallenge / loadWeeklyProgress / loadChainState / addWeeklyProgress / recordChainCompletion / claimWeeklyReward / claimChainMilestone / getTodayKey + 类型
|
||||
370→ - `trackBeacon(type, delta)` 函数签名从 `boolean` 改为 `{ dailyJustCompleted, weeklyJustCompleted, newChainMilestones }`:
|
||||
371→ - 日挑战类型匹配且未完成 → addBeaconProgress;若刚完成 → recordChainCompletion(getTodayKey()) 收集 newMilestones
|
||||
372→ - 周挑战类型匹配且未完成 → addWeeklyProgress
|
||||
373→ - 所有调用点(pulse/clickNode/autoDecodeTick/resolveCurrentNode 等 7 处)原本就忽略返回值,向后兼容
|
||||
374→ - 新增 action `claimWeeklyBeacon`:调用 claimWeeklyReward → 发放 insights + contact 到 state,返回 `{ rewardInsight, rewardContact, score }`
|
||||
375→ - 新增 action `claimChainReward(milestone)`:前置校验 currentStreak 与 milestonesClaimed,调用 claimChainMilestone → 发放奖励,返回 `{ rewardInsight, rewardContact, label, ok }`
|
||||
376→ - GameActions 接口同步新增两个 action 签名
|
||||
377→- **重写 `src/components/game/BeaconPanel.tsx`(301 → 638 行)**:
|
||||
378→ - 顶部头部 + 每日挑战卡片(保留 v0.5 完整功能 + 按钮主题色随难度色淡显)
|
||||
379→ - **新增周挑战区块**(fuchsia 主题):标题"周挑战 · WEEKLY" + weekKey + 倒计时 + 挑战卡片(类型/难度标签/标题/描述/进度条/奖励/领取按钮 emerald 主题)+ weekly-glow 动画
|
||||
380→ - **新增信标链区块**(amber→rose 渐变):标题"信标链 · CHAIN" + 大字号 streak(chain-streak-text 渐变流动动画)+ 今日完成状态徽章 + 4 个里程碑节点(w-12 h-12 圆形,claimed=emerald/✓,reachable=rose 脉冲动画+领取按钮,inProgress=amber 半亮,未到达=muted 灰)+ 节点间连线(背景灰 + 已达成部分 amber→rose 渐变 + 辉光,基于 prev→next 插值定位)+ 进度条 + 底部统计(最长/累计/续命状态)
|
||||
381→ - 桌面端 lg:grid-cols-2 让周挑战+信标链并排,移动端单列
|
||||
382→ - 排行榜条目区分日/周:周挑战 entry 显示 "WEEK" 徽章 + fuchsia 高亮背景
|
||||
383→ - 空状态提示扩展为"完成今日或本周信标即可登榜"
|
||||
384→ - 4 个新动画:weekly-glow / chain-milestone-pulse / chain-streak-flux(背景渐变流动)
|
||||
385→- **QA 验证**:
|
||||
386→ - `bun run lint` 零错误(每次修改后均验证)
|
||||
387→ - dev.log 全程无错误,所有编译 < 300ms
|
||||
388→ - **信标链逻辑测试**(bun 直接运行 TS,5 个场景全 PASS):
|
||||
389→ 1. 昨日 streak=1 → 今日完成 → streak=2 ✅
|
||||
390→ 2. 同日重复完成 → 忽略 ✅
|
||||
391→ 3. 明日完成 → streak=3,无需 grace ✅
|
||||
392→ 4. 隔一天 miss(lastCompleted + 2 天)→ streak=4,graceUsed=1 ✅
|
||||
393→ 5. 再次 miss(grace 已用)→ 断链 streak=1,graceUsed=0 ✅
|
||||
394→ - **UI 集成测试**(agent-browser):
|
||||
395→ - localStorage 模拟设置 chain state(lastCompletedDateKey=yesterday, currentStreak=1)→ reload → UI 正确显示 streak=1
|
||||
396→ - 设置 streak=3 + milestonesClaimed=[] → milestone 3 节点显示 rose 脉冲动画 + "领取"按钮
|
||||
397→ - 点击"领取"→ milestonesClaimed=[3] + Toast "✦ 三日谐振 已领取 +50 洞见 · +5.0 接触" + 按钮消失 ✅
|
||||
398→ - **VLM 视觉评分**(目标 ≥7/10):
|
||||
399→ - 首屏截图:8/10(四色一致、布局合理、信标链清晰)
|
||||
400→ - 里程碑可领取状态:8/10(amber→rose 渐变醒目、里程碑层次分明、fuchsia 主题清晰)
|
||||
401→ - 重置后干净状态:8/10(WEEKLY 字体对比度可优化,但整体可读性强)
|
||||
402→ - **不破坏现有功能**:日挑战进度/领奖/排行榜流程全部保留并工作正常
|
||||
403→
|
||||
404→Stage Summary:
|
||||
405→- ✅ beacon.ts 扩展完成(358 → 873 行):周挑战 + 信标链全部函数与类型
|
||||
406→- ✅ gameStore.ts 集成完成:trackBeacon 升级为对象返回值 + claimWeeklyBeacon + claimChainReward 两个新 action
|
||||
407→- ✅ BeaconPanel.tsx UI 完整重写(301 → 638 行):周挑战 fuchsia 卡片 + 信标链 amber→rose 渐变区块
|
||||
408→- ✅ 严格四色全息:周挑战 fuchsia、信标链 amber→rose、领取按钮 emerald、无蓝/紫色违规
|
||||
409→- ✅ localStorage 新增 2 个独立 key(weekly + chain),不污染旧 key
|
||||
410→- ✅ 确定性:周挑战同周同种子同结果(weekKey FNV-1a 种子)
|
||||
411→- ✅ 信标链 grace 续命机制工作正常(5 个场景 bun 测试全 PASS)
|
||||
412→- ✅ lint 零错误 + dev HTTP 200 + VLM 8/10
|
||||
413→- ✅ 现有日挑战 + 排行榜 + 领奖流程全部保留,无回归
|
||||
414→
|
||||
415→---
|
||||
416→Task ID: 9
|
||||
417→Agent: main + subagent(9-b)
|
||||
418→Task: v0.8.1 P1 双任务 — 探险 BOSS 胜率平衡 + 能量恢复 + 信标系统扩展(周挑战 + 信标链)
|
||||
419→
|
||||
420→Work Log:
|
||||
421→- 重读工单确认 P1 两项为下一阶段优先级
|
||||
422→- P1-a 探险平衡(main 自己做,平衡需要精细控制):
|
||||
423→ - expedition.ts: combatDifficultyScale 8→4, combatWinRateFloor 0.25→0.35, BOSS difficulty 5-7→3-5
|
||||
424→ - 新增 computeEnergyRegenInterval(state): exp_2 -30%, exp_3 -20%, 探索力属性 -最高30%, 下限12s
|
||||
425→ - computeEnergyRegen 接受 intervalSec 参数
|
||||
426→ - config.ts: exp_2/exp_3 描述加能量恢复说明
|
||||
427→ - gameStore.ts tick: 传入动态间隔
|
||||
428→ - ExpeditionPanel.tsx: 显示实际恢复速度 + '已加速'标记
|
||||
429→- P1-b 信标系统扩展(dispatch subagent 9-b,并行完成):
|
||||
430→ - beacon.ts 358→873行: 周挑战(getWeekKey ISO 8601 + 确定性生成) + 信标链(4里程碑+grace续命)
|
||||
431→ - BeaconPanel.tsx 301→638行: 周挑战fuchsia主题 + 信标链amber→rose里程碑节点
|
||||
432→ - gameStore.ts: trackBeacon升级 + claimWeeklyBeacon/claimChainReward actions
|
||||
433→- QA 验证:
|
||||
434→ - lint 零错误
|
||||
435→ - 探险面板 VLM 7/10(能量条 + 恢复速度显示正常)
|
||||
436→ - 信标面板 VLM 8/10(周挑战 WEEKLY + 信标链 3/7/14/30 + 排行榜全部可见)
|
||||
437→ - subagent 5场景 bun 测试全 PASS(信标链断链/续命逻辑)
|
||||
438→- 提交 v0.8.1(commit 71ca5b4)+ 推送 main
|
||||
439→- 静态导出 + 部署 gh-pages(commit 97eecaa)→ HTTP 200
|
||||
440→
|
||||
441→Stage Summary:
|
||||
442→- ✅ P1-a 探险平衡完成: BOSS 基础胜率 25%→35-45%, 配合技术/属性可达 55-70%
|
||||
443→- ✅ P1-a 能量恢复: 固定45s → 动态12-45s(技术+属性加速)
|
||||
444→- ✅ P1-b 周挑战: 每周一UTC刷新, fuchsia主题, goal×3-5倍
|
||||
445→- ✅ P1-b 信标链: 4里程碑(3/7/14/30天) + grace续命, amber→rose渐变
|
||||
446→- ✅ 在线游玩 v0.8.1: https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
447→- 下一阶段工单: P2 UI样式细节打磨 / P2 云存档+云排行榜 / P3 全纪元叙事
|
||||
448→
|
||||
449→---
|
||||
450→Task ID: 10-a
|
||||
451→Agent: full-stack-developer
|
||||
452→Task: #5 限时挑战 + #3 星潮类型深化
|
||||
453→
|
||||
454→Work Log:
|
||||
455→- 阅读项目上下文:worklog.md(v0.8.1,10 大系统)+ beacon.ts(873行,日+周+链)+ starTide.ts(209行,6种星潮)+ gameStore trackBeacon/tickTide + BeaconPanel.tsx,确认四色全息规范与现有架构
|
||||
456→- **工单 #5 限时挑战**:
|
||||
457→ - beacon.ts(873→1162行)新增限时挑战系统:
|
||||
458→ - BeaconTimedChallenge/BeaconTimedProgress 接口 + isTimed 字段加入 BeaconScoreEntry
|
||||
459→ - getTimedSlotKey(UTC 0/4/8/12/16/20 点切分,"timed_YYYY-MM-DD_HH")+ timedSlotKeyToSeed(FNV-1a)
|
||||
460→ - generateTimedChallenge(确定性,难度 routine,goal=日基准×0.3-0.5,5类型公式)
|
||||
461→ - loadTimedProgress/saveTimedProgress/addTimedProgress/claimTimedReward(排行榜 isTimed)
|
||||
462→ - msUntilNextTimedSlot + TIMED_SLOT_MS=4h + BEACON_TIMED_KEY
|
||||
463→ - gameStore.ts:trackBeacon 返回值新增 timedJustCompleted,三进度同时更新;新增 claimTimedBeacon action
|
||||
464→ - BeaconPanel.tsx(753→944行):日挑战与周挑战之间插入限时挑战区块(amber 主题)
|
||||
465→ - Hourglass图标+TIMED标题+slotKey+倒计时 + 进度+奖励+领取按钮(emerald)
|
||||
466→ - 紧急状态:距时段结束<30min 切 rose 脉冲动画+"即将结束"徽章
|
||||
467→ - 2新动画 timed-glow(amber)/timed-urgent(rose) + 排行榜 TIMED 徽章
|
||||
468→- **工单 #3 星潮深化**:
|
||||
469→ - starTide.ts(209→289行):TideType 新增 surge/eclipse/prism
|
||||
470→ - surge(emerald ⇈): crystalsPerSec×2.5 + targetLenBonus=2(解码目标序列+2,更长更难)
|
||||
471→ - eclipse(rose ◐): crystalsPerSec×0.7 + bossWinRateBonus=0.2(BOSS胜率+20%)
|
||||
472→ - prism(fuchsia ◬): insightMultAdd=1.0(洞见×2) + autoDecodeIntervalMult=0.7(自动解码-30%)
|
||||
473→ - TideModifiers 新增 targetLenBonus/bossWinRateBonus/autoDecodeIntervalMult 可选字段
|
||||
474→ - TIDE_WEIGHTS 新增3种各12(总136)+ getTideModifiers 3新case
|
||||
475→ - decode.ts:generatePuzzle 新增 targetLenBonus 参数(surge用,targetLen+stepLimit同步增加)
|
||||
476→ - gameStore.ts 3处修饰器应用:
|
||||
477→ - startDecode:surge 时传 targetLenBonus → 谜题更长
|
||||
478→ - autoDecodeTick:prism 时 interval×=autoDecodeIntervalMult
|
||||
479→ - resolveCurrentNode:eclipse 时 bossWinRate 加 tideBossBonus
|
||||
480→ - achievements.ts:ach_tides_all 阈值6→9;page.tsx StatsPanel 星潮亲历 /9
|
||||
481→- QA 验证:
|
||||
482→ - lint 零错误(exit 0)+ dev HTTP 200 + 编译<30ms
|
||||
483→ - BeaconPanel VLM 8.5/10(限时区块可见)+ 最终 9/10
|
||||
484→ - 三新星潮 localStorage 注入触发截图 VLM:surge 8/10、prism 7/10、eclipse 8/10
|
||||
485→ - 日/周/信标链/6旧星潮全部保留无回归
|
||||
486→
|
||||
487→Stage Summary:
|
||||
488→- ✅ beacon.ts +289行(限时挑战完整系统:4h时段+确定性+进度+领奖+排行榜)
|
||||
489→- ✅ starTide.ts +80行(3新类型 surge/eclipse/prism + 3新修饰器字段)
|
||||
490→- ✅ decode.ts generatePuzzle 支持 targetLenBonus(surge 谜题+2)
|
||||
491→- ✅ gameStore.ts trackBeacon 三进度同步 + claimTimedBeacon + 3处新星潮修饰器
|
||||
492→- ✅ BeaconPanel.tsx +191行(amber 限时区块 + 紧急状态 + TIMED 徽章)
|
||||
493→- ✅ 严格四色规范:限时amber/surge-emerald/eclipse-rose/prism-fuchsia,零蓝色
|
||||
494→- ✅ 确定性:限时挑战同时段同种子同结果(FNV-1a slotKey 哈希)
|
||||
495→- ✅ lint 零错误 + dev HTTP 200 + VLM 全部≥7/10
|
||||
496→
|
||||
497→---
|
||||
498→Task ID: 10-b
|
||||
499→Agent: full-stack-developer
|
||||
500→Task: P2/#4 云排行榜 mini-service(信标本机榜升级为云端 Top100)
|
||||
501→
|
||||
502→Work Log:
|
||||
503→- 前置阅读:worklog(v0.8.1 项目状态)+ beacon.ts(BeaconScoreEntry / loadLeaderboard / pushLeaderboardEntry / claimBeaconReward / claimWeeklyReward / claimTimedReward)+ BeaconPanel.tsx(排行榜 UI 渲染)+ Caddyfile(?XTransformPort=端口号 转发规则)+ examples/websocket(mini-service 参考)+ .zscripts/dev.sh(mini-service 启动模式)
|
||||
504→- 发现 worklog 信息滞后:beacon.ts 实际已扩到 1161 行(v0.8.2 已加限时挑战 + claimTimedReward),BeaconPanel 已扩到 953 行
|
||||
505→- 创建 mini-service:
|
||||
506→ - `mini-services/leaderboard-service/package.json`:独立 bun 项目,type=module,scripts `dev: bun --hot index.ts` + `start: bun index.ts`,依赖 hono ^4.6.14
|
||||
507→ - `mini-services/leaderboard-service/index.ts`(182 行):
|
||||
508→ - Hono + cors 中间件(origin: * 全开放,跨端口必须)
|
||||
509→ - 内存数组存储(最多 1000 条,按 score 降序,同分按时长→时间戳排序)
|
||||
510→ - 防刷:同 dateKey+challenge 10s 内只接受 1 次提交(Map 记录 lastSubmitAt),返回 429 + retryAfterMs
|
||||
511→ - GET /api/leaderboard → Top100 + total
|
||||
512→ - POST /api/leaderboard body {entry} → 校验 schema → 推入 → 排序 → 返回 {entries, total, rank}
|
||||
513→ - GET /api/leaderboard/stats → {totalSubmissions, uniquePlayers, topScore}
|
||||
514→ - GET / → 健康检查 {service, version, ok, uptime}
|
||||
515→ - 端口固定 3030,`export default { port, fetch }` 标准 bun 模式
|
||||
516→ - `mini-services/leaderboard-service/README.md`:API 文档 + 联调规范
|
||||
517→- mini-service 启动调试:bun --hot 在本沙盒环境下会因文件 watcher 异常被 kill;改用 `bun index.ts`(无 --hot)+ 双 fork `( ... & )` 模式启动,PPID=1,uptime 4+ 分钟稳定
|
||||
518→- eslint.config.mjs 新增 ignores "mini-services/**"(mini-service 独立项目,不参与主项目 lint)
|
||||
519→- beacon.ts 扩展(1161 → 1290 行,+129 行):
|
||||
520→ - 三个 claim 函数返回值新增 `entry: BeaconScoreEntry`(非破坏性扩展):
|
||||
521→ - `claimBeaconReward` 返回 `entry`(daily)
|
||||
522→ - `claimWeeklyReward` 返回 `entry`(weekly)
|
||||
523→ - `claimTimedReward` 返回 `entry`(timed)
|
||||
524→ - 新增云排行榜模块(v0.8.2 P2/#4):
|
||||
525→ - `BEACON_CLOUD_PORT = 3030` 常量
|
||||
526→ - `BEACON_CLOUD_LAST_SUBMIT_KEY = "echo-nexus-beacon-cloud-last-submit-v1"` 本地 key
|
||||
527→ - `CloudLeaderboardResponse` / `CloudSubmitResponse` / `CloudStatsResponse` 接口
|
||||
528→ - `loadLastCloudSubmitTimestamp()` / `saveLastCloudSubmitTimestamp(ts)` 工具
|
||||
529→ - `fetchCloudLeaderboard(): Promise<BeaconScoreEntry[]>` — GET 相对路径 + ?XTransformPort=3030
|
||||
530→ - `submitCloudScore(entry): Promise<number>` — POST,成功返回 rank,失败返回 -1,自动记录 ts 供全球榜高亮
|
||||
531→ - `fetchCloudStats(): Promise<CloudStatsResponse | null>` — 全局统计
|
||||
532→ - 所有 fetch 用相对路径 + `?XTransformPort=3030`,**禁止** localhost:3030
|
||||
533→- gameStore.ts 集成:
|
||||
534→ - import 新增 `submitCloudScore`
|
||||
535→ - `claimWeeklyBeacon` action:领奖成功后 `void submitCloudScore(res.entry)`(fire-and-forget,不 await,不阻塞)
|
||||
536→ - `claimTimedBeacon` action:同上
|
||||
537→ - `claimBeaconReward` (daily) 由 BeaconPanel 直接调用,不通过 gameStore
|
||||
538→- BeaconPanel.tsx 重写(953 → 1170 行,+217 行):
|
||||
539→ - 新增 import: fetchCloudLeaderboard / submitCloudScore / loadLastCloudSubmitTimestamp + 4 个 lucide 图标(RefreshCw/Globe/WifiOff/Loader2)
|
||||
540→ - 新增状态: lbTab ('local'|'global') / cloudEntries / cloudLoading / cloudError / cloudFetched / mySubmitTs / cloudFetchingRef
|
||||
541→ - 新增 `refreshCloudLeaderboard()` callback:拉取云端榜 + 防并发(ref)+ 空 entries 时显示提示
|
||||
542→ - useEffect: 切到全球 tab 自动拉取(仅首次)+ 初始化读取 mySubmitTs
|
||||
543→ - handleClaimDaily: 领奖成功后 `void submitCloudScore(res.entry).then(rank => ...)` — 若用户在全球 tab 自动刷新
|
||||
544→ - handleClaimTimed/Weekly: 领奖后更新 mySubmitTs + 若在全球 tab 自动刷新
|
||||
545→ - 排行榜 UI 重写为双 tab:
|
||||
546→ - 顶部「本地」(amber 主题) / 「全球」(emerald 主题) 切换按钮 + 全球 tab 专属刷新按钮(旋转动画)
|
||||
547→ - 子标题:本地"本机 Top N · 离线可用" / 全球"全球 Top N · 已同步 / 同步中…"
|
||||
548→ - 本地榜保留原 v0.8.2 渲染(max-h-200px overflow-y-auto)
|
||||
549→ - 全球榜:
|
||||
550→ - 加载中:Loader2 spinner + "正在拉取全球榜…"
|
||||
551→ - 空榜+错误:WifiOff 图标 + 错误文案 + 重试按钮
|
||||
552→ - 空榜+无错:Globe 图标 + "尚无全球记录"提示
|
||||
553→ - 有数据:渲染前 100 条,每条带排名(1-3 名用 Crown/Medal/Award 图标)/ 难度色 / WEEK·TIMED 徽章 / 用时 / 分数
|
||||
554→ - 玩家自己的记录通过 timestamp 匹配 mySubmitTs 高亮:emerald 边框 + emerald 阴影 + YOU 徽章 + emerald 分数色 + 加粗排名
|
||||
555→- QA 验证:
|
||||
556→ - `bun run lint` 零错误零警告(eslint.config.mjs 把 mini-services 加入 ignores)
|
||||
557→ - dev.log 全程无错误,所有编译 < 300ms
|
||||
558→ - mini-service curl 全通过:
|
||||
559→ - GET / → 200 {service, version, ok, uptime}
|
||||
560→ - GET /api/leaderboard (空) → 200 {entries:[], total:0}
|
||||
561→ - POST /api/leaderboard → 200 {entries, total, rank:1}
|
||||
562→ - GET /api/leaderboard (有数据) → 200 {entries:[...], total:N}
|
||||
563→ - GET /api/leaderboard/stats → 200 {totalSubmissions, uniquePlayers, topScore}
|
||||
564→ - OPTIONS 预检 → 204 + 完整 CORS 头(Allow-Origin: *)
|
||||
565→ - 重复 POST(同 dateKey+challenge 10s 内)→ 429 {error:"Rate limited", retryAfterMs}
|
||||
566→ - 网关路由验证:Caddy :81 → localhost:3030 通过 ?XTransformPort=3030 正确转发,返回 JSON 200
|
||||
567→ - agent-browser 集成测试(通过 :81 端口访问,绕过 Next.js 404):
|
||||
568→ - 信标 tab 选中(用 KeyboardEvent Enter 激活 Radix Tabs,因 pointerdown 被覆盖层拦截)
|
||||
569→ - 切到「全球」tab → 自动拉取 → 显示"全球 Top 6 · 已同步" → 渲染 6 条记录
|
||||
570→ - 刷新按钮可点击,旋转动画正常
|
||||
571→ - POST 测试:浏览器 fetch 提交 score=9999 → 返回 rank=1 → 刷新后榜首显示 10.00K
|
||||
572→ - YOU 高亮:手动设置 localStorage[BEACON_CLOUD_LAST_SUBMIT_KEY] 后刷新 → 榜首显示 emerald 边框 + YOU 徽章
|
||||
573→ - VLM 视觉评分(目标 ≥7/10):
|
||||
574→ - 全球榜含 YOU 高亮:**8/10**(双tab切换清晰,全球榜记录完整,难度色与标签规范,视觉层次佳)
|
||||
575→ - 本地榜:**8/10**(双tab切换逻辑清晰,本地tab内容完整,四色规范应用,信息层级合理)
|
||||
576→
|
||||
577→Stage Summary:
|
||||
578→- ✅ mini-service 独立项目:自己的 package.json + bun.lock + node_modules,依赖 hono ^4.6.14,不污染主项目
|
||||
579→- ✅ 端口 3030 + Caddy 网关:前端用相对路径 `fetch('/api/leaderboard?XTransformPort=3030')`,**禁止** localhost:3030
|
||||
580→- ✅ CORS 全开放:origin: * + OPTIONS 预检自动处理,前端跨端口无忧
|
||||
581→- ✅ 内存存储 + 防刷:1000 条上限,同 dateKey+challenge 10s 限 1 次
|
||||
582→- ✅ 三个 claim 入口全部接入云提交:claimBeaconReward(BeaconPanel 直接调)/ claimWeeklyBeacon / claimTimedBeacon(gameStore action 内)
|
||||
583→- ✅ 本地榜保留:loadLeaderboard / pushLeaderboardEntry 未删除,作为离线 fallback
|
||||
584→- ✅ 双 tab UI:本地(amber 主题,立即可用)/ 全球(emerald 主题,按需拉取)+ 刷新按钮 + 加载态 + 错误重试
|
||||
585→- ✅ 玩家高亮:通过 timestamp 匹配 localStorage[BEACON_CLOUD_LAST_SUBMIT_KEY],emerald 边框 + YOU 徽章
|
||||
586→- ✅ lint 零错误 + dev HTTP 200 + VLM 8/10
|
||||
587→- ✅ mini-service 启动稳定:uptime 4+ 分钟,PPID=1(双 fork 模式)
|
||||
588→- 下一阶段工单:P3 #10-c 全球星潮同步(star-tide-service 已在 mini-services 目录中)
|
||||
589→
|
||||
590→---
|
||||
591→Task ID: 10-c
|
||||
592→Agent: full-stack-developer
|
||||
593→Task: #9 手写叙事节点 + P3 socket 多人同步星潮
|
||||
594→
|
||||
595→Work Log:
|
||||
596→- 前置阅读:worklog.md(v0.8.1,四色规范 emerald/rose/amber/fuchsia,禁止蓝色,10 大系统)+ chronicle.ts(680 行)+ starTide.ts(297 行,9 种星潮)+ gameStore.ts(1332 行)+ StarTide.tsx(170 行)+ StarTideOverlay.tsx + Caddyfile(:81 网关 ?XTransformPort 转发规则)+ 前序 10-a/10-b 工单(限时挑战/3 新星潮/云排行榜 mini-service)
|
||||
597→- **状态确认**:本任务为重试,发现上次重试已落地主体代码,本次为验证 + 补 QA + 启动 mini-service + 追加 worklog
|
||||
598→- **工单 #9 手写叙事节点**(chronicle.ts 已就绪):
|
||||
599→ - EPOCH_LORE 常量:5 纪元 × 3 节点(opening/middle/ending)= 15 段手写叙事,每段 80-150 字文学性
|
||||
600→ - 5 纪元主题:1 觉醒(emerald)/2 谐振(rose)/3 遗迹(amber)/4 飞升(fuchsia)/5 终末
|
||||
601→ - 每段含 fallback + variants(按 ctx 命中条件挑变体):
|
||||
602→ - 第一纪元:解码者(≥15)/学者(techs≥5)/里程碑密集(≥2) + 深度轮回(asc>5)
|
||||
603→ - 第二纪元:探险者(≥3)/解码者(≥15)/觉醒天赋 + 深度轮回
|
||||
604→ - 第三纪元:BOSS 猎手(≥2)/深度探险(≥4)/星潮亲历(≥3)/BOSS 收尾 + 深度轮回
|
||||
605→ - 第四纪元:觉醒天赋/蓝图接近完整(≥5)/里程碑密集 + 深度轮回
|
||||
606→ - 第五纪元:里程碑密集(≥3)/星潮汹涌(≥3)/觉醒天赋 + 深度轮回
|
||||
607→ - 变量替换:{decodedThisRun}/{techsThisRun}/{expThisRun}/{bossKillsThisRun}/{blueprintsAfter}/{milestonesCount}/{milestonesList}/{tideCount}/{tideNames}/{perksList}/{minutes}
|
||||
608→ - buildLore 改造:优先 buildHandwrittenLore,无匹配(ascensionNumber 异常)时 fallback 到 v0.4 模板拼接
|
||||
609→ - 验证:bun 脚本测试 5 纪元 × 2 上下文(minimal/rich)= 10 个 case 全通过,文字长度 233-273 字(含收尾段),变体匹配正确,变量替换无残留 {xxx}
|
||||
610→- **P3 socket 多人同步星潮**:
|
||||
611→ - **mini-service(mini-services/star-tide-service/)**:
|
||||
612→ - 独立 bun 项目,package.json type=module + scripts dev:bun --hot index.ts + start:bun index.ts,依赖 socket.io ^4.8.3
|
||||
613→ - index.ts(250 行):
|
||||
614→ - 端口固定 3031,path:"/"(Caddy 据此转发)
|
||||
615→ - 6 种星潮类型表(crystal/resonance/ruins/void/core/silence)+ 权重表 + rollTide
|
||||
616→ - DURATION_SEC=60s 全球星潮持续;FIRST_TIDE_DELAY_MS=60s(QA 友好,env 可覆盖);MIN/MAX_GAP_MS=10-15 分钟随机间隔
|
||||
617→ - 调度:startTide → io.emit("global-tide", {type,name,startedAt,endsAt,durationSec}) → 60s 后 endTide → io.emit("tide-ended", {endedAt,nextTideAt}) → scheduleNextTide(10-15 分钟随机)
|
||||
618→ - 客户端连接:socket.emit("tide-state", {current, nextTideAt, serverTime}) 立即推送
|
||||
619→ - 客户端可 emit "get-next-tide" → 服务端响应 "next-tide-info" {current, nextTideAt, serverTime, remainingMs}
|
||||
620→ - dev/QA 用 "admin-trigger-tide":立即触发一次全球星潮(不等待下次定时器)
|
||||
621→ - 优雅退出:SIGTERM/SIGINT → 清 timer → io.close → httpServer.close → exit(0)
|
||||
622→ - README.md:API/事件文档
|
||||
623→ - **前端集成**:
|
||||
624→ - src/hooks/useGlobalTide.ts(127 行):
|
||||
625→ - 单例 socket(sharedSocket + connectRefCount 引用计数,多组件挂载共享同一连接)
|
||||
626→ - io("/?XTransformPort=3031", {transports:["websocket","polling"], reconnection:true, reconnectionAttempts:Infinity})
|
||||
627→ - 监听 "global-tide" → triggerRef.current(type),用 startedAt+type 去重(防重连重复触发),过期 tide 不触发
|
||||
628→ - 监听 "tide-state" → 连接/重连时若服务端正有进行中的全球星潮,补触发
|
||||
629→ - 主动 emit "get-next-tide" 保险
|
||||
630→ - 导出 adminTriggerGlobalTide(dev 控制台 QA 用),window.__adminTriggerGlobalTide 暴露
|
||||
631→ - gameStore.ts 新增 triggerGlobalTide action + globalTide state:
|
||||
632→ - GLOBAL_TIDE_DURATION_MS = 60_000 常量
|
||||
633→ - GlobalTideState 类型 {type, startedAt, endsAt, id}
|
||||
634→ - TideEvent 新增 isGlobal?: boolean 字段
|
||||
635→ - triggerGlobalTide(type):创建 newTide(60s)+ newGlobalTide,覆盖本地 activeTide(即使本地有进行中的星潮也会被替换),加入 _tideEvents 队列 with isGlobal:true
|
||||
636→ - tickTide 改造:globalTide 优先 → 全球星潮进行中本地不触发新星潮;全球星潮结束时设 globalTide:null + activeTide:null + lastTideEnd + silenceCompensation + ended 事件 with isGlobal:true
|
||||
637→ - partialize 排除 globalTide(瞬态运行时状态,不持久化)
|
||||
638→ - page.tsx 顶层挂载 useGlobalTide()
|
||||
639→ - StarTide.tsx UI 升级:
|
||||
640→ - StarTideIndicator:读 globalTide → isGlobal 标记 → 加 🌐 emoji + ring-1 ring-amber-300/60 + 强化 boxShadow + 渐变背景 + title 改为 "🌐 全球星潮 · {meta.desc}";duration 用 globalTide.endsAt-startedAt 计算(60s)避免越界
|
||||
641→ - StarTideOverlay:全球星潮多一道顶部琥珀色光带 + global-tide-sweep 2.5s 扫光动画 + inset boxShadow 加深(160px vs 120px)
|
||||
642→ - StarTideNotifier:toast 文案区分全球/本地("🌐 全球星潮降临:{name}" + "全球玩家同步经历 · {desc}")
|
||||
643→- **QA 验证**:
|
||||
644→ - `bun run lint` 零错误零警告
|
||||
645→ - dev.log 全程无错误,编译 < 70ms,HTTP 200
|
||||
646→ - mini-service 启动稳定:pid 9456,PPID=1(双 fork 脱离 dev.sh),uptime 19+ 分钟,端口 3031 监听正常
|
||||
647→ - curl http://localhost:3031/ → {"code":0,"message":"Transport unknown"}(socket.io-only 服务预期响应)
|
||||
648→ - curl http://localhost:3031/socket.io/?EIO=4&transport=polling → 正确握手 {"sid":...,"upgrades":["websocket"]}
|
||||
649→ - 网关路由验证:curl http://localhost:81/socket.io/?EIO=4&transport=polling&XTransformPort=3031 → 通过 Caddy 转发到 3031,返回正确握手
|
||||
650→ - socket.io 端到端测试(bun 脚本 /tmp/test-socket.ts):connect ✅ → tide-state ✅ → emit admin-trigger-tide → 504ms 内收到 global-tide {type:ruins, startedAt, endsAt, durationSec:60} ✅
|
||||
651→ - agent-browser 集成测试(通过 http://localhost:81/ 走 Caddy 网关,socket.io 才能正确路由):
|
||||
652→ - 页面加载 200,window.__adminTriggerGlobalTide 已挂载(useGlobalTide hook 已挂载)
|
||||
653→ - 调用 adminTriggerGlobalTide() → 1-3s 内 StarTideIndicator 渲染 🌐 芯片
|
||||
654→ - DOM 验证:芯片文本 "🌐✷虚空低语57s",title "🌐 全球星潮 · 虚空传来回响,洞见获取翻倍"(isGlobal:true 路径生效)
|
||||
655→ - 第二次触发:"🌐⬢遗迹共振59s",title "🌐 全球星潮 · 远古遗迹苏醒,探险力 +5、生命 +30"
|
||||
656→ - 全球星潮结束(60s 后)→ activeTide:null + globalTide:null + lastTideEnd 更新 → 本地 tickTide 恢复正常节奏
|
||||
657→ - VLM 视觉评分:**8/10**(确认 🌐 地球图标 + 汉字名称"遗迹共振" + 倒计时"59s" 全部可见;颜色 emerald/amber/fuchsia/rose 四色规范,零蓝色)
|
||||
658→ - 编年史 buildLore 验证(bun 脚本测试 5 纪元 × 2 上下文 = 10 case):
|
||||
659→ - 全部产出 233-273 字文学性叙事,包含开场+中段+结尾+收尾段
|
||||
660→ - fallback 路径:默认文本,无变量替换
|
||||
661→ - variant 路径:按 ctx 命中条件挑变体,{decodedThisRun}/{bossKillsThisRun}/{milestonesList}/{perksList} 等变量正确替换
|
||||
662→ - 纪元名生成正确:第一纪元·初鸣之夕 / 第二纪元·光谱涌动 / 第三纪元·星辉汇聚 / 第四纪元·以太共振 / 第五纪元·永恒闭环
|
||||
663→
|
||||
664→Stage Summary:
|
||||
665→- ✅ 工单 #9:chronicle.ts EPOCH_LORE 5 纪元 × 3 节点 = 15 段手写叙事(每段 80-150 字文学性),buildLore 优先手写节点 + fallback 模板,buildChronicleEntry/regenerateLoreFromEntry/withPerks 全部接入;10 case 测试通过,变体匹配 + 变量替换正确
|
||||
666→- ✅ P3 socket 多人同步星潮:mini-services/star-tide-service 独立 bun 项目,socket.io 端口 3031,每 10-15 分钟随机广播 global-tide(60s 持续),admin-trigger-tide 供 QA 触发;前端 useGlobalTide hook + gameStore.triggerGlobalTide + globalTide 状态 + tickTide 全球优先 + StarTide UI 🌐 标记 + toast 区分全球/本地
|
||||
667→- ✅ 网关规范:socket.io 严格用 `io("/?XTransformPort=3031")`,path "/",禁止 localhost:3031 直连;Caddy :81 → localhost:3031 转发正确
|
||||
668→- ✅ 离线容错:socket.io 自动重连(Infinity attempts),断连期间本地 tickTide 继续按原节奏工作,玩家不会被卡住;globalTide 不持久化(瞬态运行时状态)
|
||||
669→- ✅ 防重连重复触发:useGlobalTide 用 startedAt+type 去重(Set 上限 32 条 FIFO 清理),过期 tide 不触发
|
||||
670→- ✅ 本地星潮保留:全球星潮是增强而非替换,全球星潮结束后本地 tickTide 恢复正常节奏
|
||||
671→- ✅ mini-service 启动稳定:pid 9456,PPID=1,uptime 19+ 分钟,端口 3031 监听正常
|
||||
672→- ✅ lint 零错误 + dev HTTP 200 + VLM 8/10(🌐 全球星潮标记清晰可见)
|
||||
673→- ✅ 严格四色规范:全球星潮琥珀色扫光(amber)+ 各星潮本色(emerald/rose/amber/fuchsia),零蓝色
|
||||
674→- 下一阶段工单:可考虑 v0.9 收尾(全球星潮成就/编年史全球星潮高亮/星图天文台全球星潮增强天赋)
|
||||
675→
|
||||
676→---
|
||||
677→Task ID: 10
|
||||
678→Agent: main + subagent(10-a/10-b/10-c)
|
||||
679→Task: v0.8.2 工单大清理 — 7 项工单一次性清零
|
||||
680→
|
||||
681→Work Log:
|
||||
682→- 重读工单发现两类列表(已知问题10项 + 下一阶段优先级7项)多项未解决
|
||||
683→- #8 编年史上限+分页(main 自己做):
|
||||
684→ - engine.ts: slice(-50)→slice(-200)
|
||||
685→ - ChronicleDialog.tsx: 加分页(每页10条)+上一页/下一页+页码显示
|
||||
686→- #5 限时挑战 + #3 星潮深化(subagent 10-a 并行):
|
||||
687→ - 限时挑战: BeaconTimedChallenge + 4h时段 + amber主题 + <30min紧急状态
|
||||
688→ - 星潮深化: +3种(surge/eclipse/prism) + 修饰器扩展 + ach_tides_all 6→9
|
||||
689→- #4/P2 云排行榜(subagent 10-b 并行):
|
||||
690→ - mini-service 端口3030 Hono+bun 内存1000条 + CORS + 防刷
|
||||
691→ - 前端双tab(本地/全球) + YOU徽章 + 自动云提交
|
||||
692→- #9 手写叙事 + P3 socket星潮(subagent 10-c):
|
||||
693→ - 5纪元×3节点=15段手写叙事(80-150字) + 11变量替换 + fallback模板
|
||||
694→ - mini-service 端口3031 socket.io 每10-15min广播 + useGlobalTide + 🌐标记
|
||||
695→- P2 UI打磨(main 自己做):
|
||||
696→ - CrystalOrb区: 3层旋转全息环 + 四角标记 + 顶部状态条 + 底部铭文
|
||||
697→- 最终 QA: lint零错误 + dev HTTP200 + VLM 8/10 + 2 mini-service运行中(3030/3031)
|
||||
698→- 提交 v0.8.2(commit 191434e)+ 推送 main + 部署 gh-pages(7e0a59b)HTTP 200
|
||||
699→
|
||||
700→Stage Summary:
|
||||
701→- ✅ 工单 #3 星潮深化: 6种→9种(+surge/eclipse/prism)
|
||||
702→- ✅ 工单 #4 云排行榜: 本地→云端(mini-service 3030)
|
||||
703→- ✅ 工单 #5 限时挑战: 每4h一个额外挑战(amber主题)
|
||||
704→- ✅ 工单 #8 编年史: 上限50→200 + 分页UI
|
||||
705→- ✅ 工单 #9 手写叙事: 5纪元×3节点=15段文学性叙事
|
||||
706→- ✅ P2 UI打磨: CrystalOrb留白→装饰全息环+四角标记+状态条
|
||||
707→- ✅ P3 socket多人星潮: mini-service 3031 + 🌐全球星潮
|
||||
708→- 剩余未解决: #1 Turbopack缓存(环境问题) / #2 定时任务(已文档化)
|
||||
709→- 在线游玩 v0.8.2: https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
710→
|
||||
711→---
|
||||
712→Task ID: 1
|
||||
713→Agent: 主代理 (Phase 1 Bug 修复)
|
||||
714→Task: 获取 Gitea 工单并修复 Issue #2 的 4 个 bug
|
||||
715→
|
||||
716→Work Log:
|
||||
717→- 通过 Gitea API 获取到 2 个未解决工单(Issue #1 + #2)
|
||||
718→- Issue #2 详细分析了 4 个 bug + 4 个玩法问题
|
||||
719→- Bug1 探险只能一次:能量恢复间隔 45→20s,初始能量 3→5,上限 5→8,新增 lastExpeditionSummary 状态记录结果,ExpeditionPanel 入口显示上次结果摘要 + 实时倒计时,新增 dismissExpedition action
|
||||
720→- Bug2 元素偏移/遮挡:标签页 grid-cols-8 → 响应式 grid-cols-4/sm:grid-cols-8,小屏 2 行避免拥挤
|
||||
721→- Bug3 成就UI遮挡:标签面板 max-h 440→520,min-h 提高
|
||||
722→- Bug4 提示框遮挡:toast viewport top-0→top-14 避开 header,TOAST_LIMIT 1→3
|
||||
723→- lint 通过,编译正常
|
||||
724→
|
||||
725→Stage Summary:
|
||||
726→- Phase 1 四个 bug 全部修复完成
|
||||
727→- 探险系统现在有完整的状态反馈:能量实时倒计时、上次结果摘要、刚结束时的结算按钮
|
||||
728→- 标签页移动端不再挤压
|
||||
729→- 待 Phase 2:技术树扩充、晶体球信息卡、成就特效、叙事融入
|
||||
730→
|
||||
731→---
|
||||
732→Task ID: 2-a
|
||||
733→Agent: subagent (技术树扩充专员)
|
||||
734→Task: Issue #2 反馈"技术树太少,分分钟点满" — 扩充技术树 12→20 节点(4 分支 × 5 级)
|
||||
735→
|
||||
736→Work Log:
|
||||
737→- 读取 worklog.md 了解项目背景(v0.8.2 已完成 7 工单清零;Task 1 Phase 1 已修复 4 个 bug;本次为 Phase 2 技术树扩充)
|
||||
738→- 读取 config.ts / expedition.ts / engine.ts / achievements.ts / TechTree.tsx / types.ts / gameStore.ts 摸清数据驱动结构
|
||||
739→
|
||||
740→- **config.ts**:TECH_TREE 由 12 节点扩充至 20 节点(4 分支 × 5 级),新增 8 节点:
|
||||
741→ - 采矿 (mining) level 4/5:量子采掘矩阵(晶体/秒+12,cost 400)/ 戴森星核(晶体/秒+30,cost 1200),desc 含仓库上限 +800/+2000
|
||||
742→ - 解码 (decoding) level 4/5:谐振放大器(脉冲+8,cost 500)/ 全息解码核心(自动解码 T2+解码步数+3,cost 1500)
|
||||
743→ - 探险 (expedition) level 4/5:虚空航标(探险力+12,生命+30,能量恢复+25%,cost 450)/ 维度跃迁引擎(探险力+25,生命+50,能量恢复+30%,cost 1400)
|
||||
744→ - 叙事 (narrative) level 4/5:以太低语(洞见+100%,cost 500)/ 文明回响(接触率+80%,洞见+150%,cost 1600)
|
||||
745→ - 注释头部更新:"4 分支 × 3 级 = 12 节点" → "4 分支 × 5 级 = 20 节点(v0.9 工单 #2 扩充:12→20)"
|
||||
746→
|
||||
747→- **expedition.ts**:
|
||||
748→ - computeExpeditionPower:新增 exp_4 * 12 + exp_5 * 25 加成
|
||||
749→ - computeExpeditionHp:新增 exp_4 * 30 + exp_5 * 50 加成
|
||||
750→ - computeEnergyRegenInterval:新增 exp_4 × 0.75(加速 25%)/ exp_5 × 0.70(加速 30%),下限 8s 由 energyRegenMinSec 守护
|
||||
751→ - 注释更新说明 v0.9 扩展点
|
||||
752→
|
||||
753→- **engine.ts** recomputeStats:在 TECH_TREE 主循环后追加多效果节点的次效果(effect.kind 只能承载一个主效果,次效果需硬编码):
|
||||
754→ - min_2/min_3/min_4/min_5 的仓库上限加成(+100/+300/+800/+2000)— 顺带补齐 min_2/min_3 旧 desc 文案中承诺但未实装的 cap 加成
|
||||
755→ - nar_5 文明回响的接触进度转化率 +0.8(与 insightMult +1.5 并存)
|
||||
756→
|
||||
757→- **gameStore.ts** autoDecodeTick:dec_5 解锁后自动解码扩展至 T2 晶体
|
||||
758→ - 原:仅 findIndex(tier === 1)
|
||||
759→ - 新:先找 T1,若无 T1 且 tech.dec_5 已解锁,则找 T2 并将 autoTier 设为 2
|
||||
760→ - decodeRewards(autoTier, ...) 使用动态 tier,T2 晶体奖励按 CRYSTAL_VALUE[2] = 22 晶体 / 4 洞见基础计算
|
||||
761→
|
||||
762→- **achievements.ts**:ach_tech_all(全谱精通)desc "12 项技术" → "20 项技术",check 阈值 12 → 20;name 保持"全谱精通",奖励不变
|
||||
763→
|
||||
764→- **TechTree.tsx**:无需修改。已数据驱动(TECH_TREE.filter(branch === b)),自动渲染 5 节点/分支;滚动容器 flex-1 overflow-y-auto echo-scroll 已存在,20 个 Card 可纵向滚动查看
|
||||
765→
|
||||
766→- **数值递进合理性**:
|
||||
767→ - mining cost: 5→24→120→400→1200(每级 ~3-4x 增长)
|
||||
768→ - decoding cost: 6→30→200→500→1500
|
||||
769→ - expedition cost: 12→60→180→450→1400
|
||||
770→ - narrative cost: 8→45→160→500→1600
|
||||
771→ - 严格 emerald/rose/amber/fuchsia 四色(沿用 TECH_BRANCH_META 既有映射,零蓝色/靛色)
|
||||
772→
|
||||
773→- 验证:`bun run lint` 零错误零警告(exit 0);`bunx tsc --noEmit` 我修改的文件(config/expedition/engine/achievements/gameStore 的 autoDecode 区域)无 TS 错误,其余 TS 报错(BeaconPanel/ChronicleDialog/ExpeditionPanel style prop、beacon.ts entry 属性等)均为预存问题,与本次改动无关
|
||||
774→
|
||||
775→Stage Summary:
|
||||
776→- ✅ 技术树节点数 12 → 20(4 分支 × 5 级),直击 Issue #2 "分分钟点满" 痛点,玩家需要 ~5-10x 更多洞见才能全解锁
|
||||
777→- ✅ 4 个分支 level 4/5 设计紧扣分支主题(采矿产能+仓库 / 解码脉冲+自动 / 探险力+生命+能量恢复 / 洞见+接触)
|
||||
778→- ✅ expedition.ts 三函数(power/hp/regen)全部接入 exp_4/exp_5,探险后期强度与能量恢复节奏显著提升
|
||||
779→- ✅ engine.ts 修复 min_2/min_3 旧 desc 文案承诺但未实装的仓库上限 bug,新 min_4/min_5 同步生效
|
||||
780→- ✅ dec_5 全息解码核心:自动解码扩展至 T2 晶体(保留 T1 优先,无 T1 时回退 T2),显著降低后期 T2 晶体积压
|
||||
781→- ✅ nar_5 文明回响:双效果(接触率+80% + 洞见+150%)通过硬编码并存
|
||||
782→- ✅ ach_tech_all 阈值同步 12→20,奖励保持产能+15% / 洞见+15%
|
||||
783→- ✅ TechTree.tsx 数据驱动,无需改动;overflow-y-auto 容器支持 20 节点滚动浏览
|
||||
784→- ✅ lint 零错误,严格四色全息配色(零蓝色/靛色)
|
||||
785→- 后续可考虑:1) TechTree.tsx 增加分支进度条(已解锁/总数);2) Codex/编年史加入"技术解锁里程碑"叙事;3) 为 level 4/5 节点添加解锁动画或特殊视觉标记
|
||||
786→
|
||||
+123
@@ -707,3 +707,126 @@ Stage Summary:
|
||||
- ✅ P3 socket多人星潮: mini-service 3031 + 🌐全球星潮
|
||||
- 剩余未解决: #1 Turbopack缓存(环境问题) / #2 定时任务(已文档化)
|
||||
- 在线游玩 v0.8.2: https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/
|
||||
|
||||
---
|
||||
Task ID: 1
|
||||
Agent: 主代理 (Phase 1 Bug 修复)
|
||||
Task: 获取 Gitea 工单并修复 Issue #2 的 4 个 bug
|
||||
|
||||
Work Log:
|
||||
- 通过 Gitea API 获取到 2 个未解决工单(Issue #1 + #2)
|
||||
- Issue #2 详细分析了 4 个 bug + 4 个玩法问题
|
||||
- Bug1 探险只能一次:能量恢复间隔 45→20s,初始能量 3→5,上限 5→8,新增 lastExpeditionSummary 状态记录结果,ExpeditionPanel 入口显示上次结果摘要 + 实时倒计时,新增 dismissExpedition action
|
||||
- Bug2 元素偏移/遮挡:标签页 grid-cols-8 → 响应式 grid-cols-4/sm:grid-cols-8,小屏 2 行避免拥挤
|
||||
- Bug3 成就UI遮挡:标签面板 max-h 440→520,min-h 提高
|
||||
- Bug4 提示框遮挡:toast viewport top-0→top-14 避开 header,TOAST_LIMIT 1→3
|
||||
- lint 通过,编译正常
|
||||
|
||||
Stage Summary:
|
||||
- Phase 1 四个 bug 全部修复完成
|
||||
- 探险系统现在有完整的状态反馈:能量实时倒计时、上次结果摘要、刚结束时的结算按钮
|
||||
- 标签页移动端不再挤压
|
||||
- 待 Phase 2:技术树扩充、晶体球信息卡、成就特效、叙事融入
|
||||
|
||||
---
|
||||
Task ID: 2-a
|
||||
Agent: subagent (技术树扩充专员)
|
||||
Task: Issue #2 反馈"技术树太少,分分钟点满" — 扩充技术树 12→20 节点(4 分支 × 5 级)
|
||||
|
||||
Work Log:
|
||||
- 读取 worklog.md 了解项目背景(v0.8.2 已完成 7 工单清零;Task 1 Phase 1 已修复 4 个 bug;本次为 Phase 2 技术树扩充)
|
||||
- 读取 config.ts / expedition.ts / engine.ts / achievements.ts / TechTree.tsx / types.ts / gameStore.ts 摸清数据驱动结构
|
||||
|
||||
- **config.ts**:TECH_TREE 由 12 节点扩充至 20 节点(4 分支 × 5 级),新增 8 节点:
|
||||
- 采矿 (mining) level 4/5:量子采掘矩阵(晶体/秒+12,cost 400)/ 戴森星核(晶体/秒+30,cost 1200),desc 含仓库上限 +800/+2000
|
||||
- 解码 (decoding) level 4/5:谐振放大器(脉冲+8,cost 500)/ 全息解码核心(自动解码 T2+解码步数+3,cost 1500)
|
||||
- 探险 (expedition) level 4/5:虚空航标(探险力+12,生命+30,能量恢复+25%,cost 450)/ 维度跃迁引擎(探险力+25,生命+50,能量恢复+30%,cost 1400)
|
||||
- 叙事 (narrative) level 4/5:以太低语(洞见+100%,cost 500)/ 文明回响(接触率+80%,洞见+150%,cost 1600)
|
||||
- 注释头部更新:"4 分支 × 3 级 = 12 节点" → "4 分支 × 5 级 = 20 节点(v0.9 工单 #2 扩充:12→20)"
|
||||
|
||||
- **expedition.ts**:
|
||||
- computeExpeditionPower:新增 exp_4 * 12 + exp_5 * 25 加成
|
||||
- computeExpeditionHp:新增 exp_4 * 30 + exp_5 * 50 加成
|
||||
- computeEnergyRegenInterval:新增 exp_4 × 0.75(加速 25%)/ exp_5 × 0.70(加速 30%),下限 8s 由 energyRegenMinSec 守护
|
||||
- 注释更新说明 v0.9 扩展点
|
||||
|
||||
- **engine.ts** recomputeStats:在 TECH_TREE 主循环后追加多效果节点的次效果(effect.kind 只能承载一个主效果,次效果需硬编码):
|
||||
- min_2/min_3/min_4/min_5 的仓库上限加成(+100/+300/+800/+2000)— 顺带补齐 min_2/min_3 旧 desc 文案中承诺但未实装的 cap 加成
|
||||
- nar_5 文明回响的接触进度转化率 +0.8(与 insightMult +1.5 并存)
|
||||
|
||||
- **gameStore.ts** autoDecodeTick:dec_5 解锁后自动解码扩展至 T2 晶体
|
||||
- 原:仅 findIndex(tier === 1)
|
||||
- 新:先找 T1,若无 T1 且 tech.dec_5 已解锁,则找 T2 并将 autoTier 设为 2
|
||||
- decodeRewards(autoTier, ...) 使用动态 tier,T2 晶体奖励按 CRYSTAL_VALUE[2] = 22 晶体 / 4 洞见基础计算
|
||||
|
||||
- **achievements.ts**:ach_tech_all(全谱精通)desc "12 项技术" → "20 项技术",check 阈值 12 → 20;name 保持"全谱精通",奖励不变
|
||||
|
||||
- **TechTree.tsx**:无需修改。已数据驱动(TECH_TREE.filter(branch === b)),自动渲染 5 节点/分支;滚动容器 flex-1 overflow-y-auto echo-scroll 已存在,20 个 Card 可纵向滚动查看
|
||||
|
||||
- **数值递进合理性**:
|
||||
- mining cost: 5→24→120→400→1200(每级 ~3-4x 增长)
|
||||
- decoding cost: 6→30→200→500→1500
|
||||
- expedition cost: 12→60→180→450→1400
|
||||
- narrative cost: 8→45→160→500→1600
|
||||
- 严格 emerald/rose/amber/fuchsia 四色(沿用 TECH_BRANCH_META 既有映射,零蓝色/靛色)
|
||||
|
||||
- 验证:`bun run lint` 零错误零警告(exit 0);`bunx tsc --noEmit` 我修改的文件(config/expedition/engine/achievements/gameStore 的 autoDecode 区域)无 TS 错误,其余 TS 报错(BeaconPanel/ChronicleDialog/ExpeditionPanel style prop、beacon.ts entry 属性等)均为预存问题,与本次改动无关
|
||||
|
||||
Stage Summary:
|
||||
- ✅ 技术树节点数 12 → 20(4 分支 × 5 级),直击 Issue #2 "分分钟点满" 痛点,玩家需要 ~5-10x 更多洞见才能全解锁
|
||||
- ✅ 4 个分支 level 4/5 设计紧扣分支主题(采矿产能+仓库 / 解码脉冲+自动 / 探险力+生命+能量恢复 / 洞见+接触)
|
||||
- ✅ expedition.ts 三函数(power/hp/regen)全部接入 exp_4/exp_5,探险后期强度与能量恢复节奏显著提升
|
||||
- ✅ engine.ts 修复 min_2/min_3 旧 desc 文案承诺但未实装的仓库上限 bug,新 min_4/min_5 同步生效
|
||||
- ✅ dec_5 全息解码核心:自动解码扩展至 T2 晶体(保留 T1 优先,无 T1 时回退 T2),显著降低后期 T2 晶体积压
|
||||
- ✅ nar_5 文明回响:双效果(接触率+80% + 洞见+150%)通过硬编码并存
|
||||
- ✅ ach_tech_all 阈值同步 12→20,奖励保持产能+15% / 洞见+15%
|
||||
- ✅ TechTree.tsx 数据驱动,无需改动;overflow-y-auto 容器支持 20 节点滚动浏览
|
||||
- ✅ lint 零错误,严格四色全息配色(零蓝色/靛色)
|
||||
- 后续可考虑:1) TechTree.tsx 增加分支进度条(已解锁/总数);2) Codex/编年史加入"技术解锁里程碑"叙事;3) 为 level 4/5 节点添加解锁动画或特殊视觉标记
|
||||
|
||||
---
|
||||
|
||||
## Task ID: 2-b
|
||||
|
||||
**Agent**: 子代理 2-b(general-purpose)
|
||||
|
||||
**Task**: 为中央晶体球区域添加全息收益信息面板,回应 Issue #2 "占满空屏的没啥用的按钮(浪费大量空间,不知道有啥用)"。让玩家明确看到晶体球的收益价值,缓解"占地方又没用"的反馈。
|
||||
|
||||
**Work Log**:
|
||||
|
||||
修改文件:`/home/z/my-project/src/app/page.tsx`
|
||||
|
||||
1. **lucide-react 图标导入扩充**:在原 import 块追加 `Gem, Zap, Flame, Database` 4 个图标,用于收益面板四色指标卡。
|
||||
|
||||
2. **新增 `CrystalYieldPanel()` 组件**(定义在 `StatsPanel` 上方):
|
||||
- 从 `useGameStore` 订阅 5 个字段:`crystalsPerSec` / `pulsePower` / `_combo` / `crystals` / `crystalCap`
|
||||
- 连击倍率计算:`comboMult = 1 + (combo - 1) * 0.15`(仅 combo≥1 时显示 ×N.NN)
|
||||
- 连击热度判定:`comboHot = combo >= 3`(≥3 时 amber 边框 + animate-pulse + 图标 drop-shadow 发光)
|
||||
- 仓库容量百分比:`fillPct = crystals / crystalCap * 100`,`warehouseWarn = fillPct >= 90`(≥90% 切 rose 警告色 + animate-pulse,图标/标签/数值全部 rose 化)
|
||||
- 容器:`mt-3 grid grid-cols-2 sm:grid-cols-4 gap-2 w-full max-w-md pointer-events-none`(小屏 2×2,sm+ 横排 1×4)
|
||||
- 单卡:`rounded-lg border bg-black/30 backdrop-blur p-2 flex items-center gap-1.5`,含图标 + 标签(text-[9px] uppercase tracking-wider)+ 数值(text-sm font-mono tabular-nums)
|
||||
- 4 卡严格四色映射:emerald(产能)/ rose(脉冲)/ amber(连击)/ fuchsia(仓库);仓库满仓时 fuchsia→rose 切换属警告态,仍属四色范围
|
||||
|
||||
3. **挂载位置**:左侧 section 内、`<div data-tut="crystal-orb" className="contents"><CrystalOrb /></div>` 之后追加 `<CrystalYieldPanel />`,作为 flex 列的第二个子项。section `min-h-[340px] sm:min-h-[420px]` 未改动(遵守约束),section 本身无 max-height 故内容超出 min-h 时自然向下扩展,配合外层 `min-h-screen flex flex-col` 页面滚动。
|
||||
|
||||
4. **数据/视觉细节**:
|
||||
- 数值使用 `formatNum()` 友好格式化(K/M/B/T),保证大数字不溢出卡片
|
||||
- 所有数值文本 `tabular-nums` 等宽对齐,跳动时不抖动
|
||||
- 卡片 `pointer-events-none` 避免遮挡 CrystalOrb 悬浮态(卡片本身无交互)
|
||||
- 仓库卡 split span:主数值 + `/cap` 副数值用 text-[9px] 降级,避免长数字撑爆卡片
|
||||
- 连击卡数值色随热度切换:常态 `text-amber-300/80`,hot 态 `text-amber-200`
|
||||
|
||||
5. **验证**:
|
||||
- `bun run lint` → exit 0,零错误零警告
|
||||
- 视觉自查:4 卡四色与既有全息环 / 四角标记 / 顶部状态条配色完全协调(emerald + fuchsia + amber + rose 已是 section 主色),无任何蓝色/靛色介入
|
||||
- 未触碰 `CrystalOrb.tsx`,未改 section 的 min-h
|
||||
|
||||
**Stage Summary**:
|
||||
- ✅ 中央晶体球下方新增全息收益信息面板,4 项核心指标可视化(产能/s · 脉冲×倍率 · 连击/10 · 仓库/cap),直击 Issue #2 "不知道有啥用" 痛点
|
||||
- ✅ 严格四色全息配色(emerald/rose/amber/fuchsia),与 section 既有装饰元素(全息环、四角标记、顶部状态条)色系完全统一,零蓝色/靛色
|
||||
- ✅ 紧凑布局(卡片 p-2 + text-sm,整体 ~h-12),不抢占晶体球视觉焦点;小屏 2×2 / sm+ 横排 1×4 响应式
|
||||
- ✅ 智能高亮:连击≥3 amber 闪烁 + 图标发光;仓库≥90% fuchsia→rose 警告色 + pulse,引导玩家解码消耗
|
||||
- ✅ 数据实时订阅 store,连击倍率 / 仓库百分比均前端计算,零额外性能开销
|
||||
- ✅ lint 零错误;未改 CrystalOrb.tsx;未改 section min-h
|
||||
- 后续可考虑:1) 鼠标悬停卡片显示 tooltip 详解(如连击衰减规则、仓库溢出损失率);2) 卡片点击跳转对应系统(产能→技术树采矿分支,仓库→解码面板);3) 为脉冲卡加入"下次脉冲预估收益"实时计算
|
||||
|
||||
|
||||
Reference in New Issue
Block a user