v0.5: 深空信标系统 + 编年史历史 BUG 修复

新功能:深空信标(Deep Space Beacon)
- 每日挑战:UTC 日期种子确定性生成,5 种类型 × 3 档难度
- 本地排行榜 Top 20,奖牌图标 + 难度色点 + 今日高亮
- 进度追踪独立 localStorage,不污染 GameState
- 倒计时 + 领取奖励发放到游戏状态

BUG 修复:编年史历史条目显示原始 tide 键名
- 新增 regenerateLoreFromEntry(),显示时重新生成 lore
- 修复 v0.4 之前条目 lore 中 tide_ruins 等原始键名

UI:第 7 标签页「信标」+ 统计面板「信标最高分」行
版本号 v0.4 → v0.5

详见 docs/10-深空信标系统-v0.5.md
This commit is contained in:
2026-06-23 15:24:51 +00:00
parent 04f6a398f4
commit 60445abd42
7 changed files with 844 additions and 20 deletions
+58
View File
@@ -59,6 +59,13 @@ import {
migrateChronicleFields,
withPerks,
} from "@/lib/game/chronicle";
import {
generateDailyChallenge,
loadDailyProgress,
addBeaconProgress,
type BeaconDailyChallenge,
type BeaconDailyProgress,
} from "@/lib/game/beacon";
interface GameActions {
// 生命周期
@@ -107,6 +114,9 @@ interface GameActions {
toggleTheme: () => void;
toggleSound: () => void;
// 深空信标奖励发放(v0.5
grantBeaconReward: (insights: number, contact: number) => void;
// 派生
canPrestige: () => boolean;
}
@@ -135,6 +145,29 @@ function syncStats(state: Partial<GameState>) {
};
}
/**
* 深空信标进度追踪(v0.5)。
* 在游戏关键动作(脉冲/解码/探险/BOSS/洞见)后调用,按今日挑战类型增量更新进度。
* 进度独立存储于 localStorageecho-nexus-beacon-prog-v1),不污染 GameState。
* @returns 若刚完成则返回 true(供 UI 触发通知)
*/
function trackBeacon(
type: "pulse" | "decode" | "expedition" | "boss" | "insight",
delta: number
): boolean {
if (typeof window === "undefined") return false;
try {
const challenge: BeaconDailyChallenge = generateDailyChallenge();
if (challenge.type !== type) return false;
const current: BeaconDailyProgress = loadDailyProgress();
if (current.completedAt !== null) return false; // 已完成不再累加
const { justCompleted } = addBeaconProgress(current, challenge, delta);
return justCompleted;
} catch {
return false;
}
}
/** 检查并解锁叙事碎片 */
function checkFragments(state: GameState): string[] {
const unlocked: string[] = [];
@@ -367,6 +400,8 @@ export const useGameStore = create<Store>()(
_combo: combo,
_lastPulse: now,
});
// 深空信标:脉冲任务进度 +1
trackBeacon("pulse", 1);
return { gain, combo };
},
@@ -414,6 +449,9 @@ export const useGameStore = create<Store>()(
totalDecoded: newTotal,
fragments: tentative.fragments,
});
// 深空信标:解码 +1,洞见累计
trackBeacon("decode", 1);
trackBeacon("insight", rewards.insights);
return { ok: true, finished: true, failReason: unlocked.join(",") || undefined };
}
// 点击成功但未完成:检测当前局面是否仍可解
@@ -490,6 +528,9 @@ export const useGameStore = create<Store>()(
fragments: tentative.fragments,
_lastAutoDecode: now,
});
// 深空信标:自动解码也算进度
trackBeacon("decode", 1);
trackBeacon("insight", rewards.insights);
},
buyTech: (techId) => {
@@ -590,6 +631,14 @@ export const useGameStore = create<Store>()(
expeditionLog: newLog,
bossKills,
});
// 深空信标:探险完成(胜负都计)+ 洞见累计 + BOSS 击破
if (result.ended) {
trackBeacon("expedition", 1);
if (result.endReason === "victory" && exp.nodes[exp.currentNode]?.type === "boss") {
trackBeacon("boss", 1);
}
}
if (result.insights) trackBeacon("insight", result.insights);
return result;
},
@@ -723,6 +772,15 @@ export const useGameStore = create<Store>()(
toggleTheme: () => set({ theme: get().theme === "dark" ? "light" : "dark" }),
toggleSound: () => set({ soundOn: !get().soundOn }),
// 深空信标:发放每日挑战奖励(v0.5)
grantBeaconReward: (insights, contact) => {
const s = get();
set({
insights: s.insights + Math.round(insights),
contact: Math.min(100, s.contact + contact),
});
},
}),
{
name: "echo-nexus-save-v1",