3d8566bc-063f-41e8-8934-68c9ac5b8211

This commit is contained in:
2026-06-23 13:38:23 +00:00
parent 674775be0e
commit da18f32df2
36 changed files with 849 additions and 34 deletions
+185
View File
@@ -0,0 +1,185 @@
// 回响星核 / Echo Nexus — 成就系统(数据驱动)
import type { GameState } from "./types";
/** 成就奖励类型 */
export interface AchievementReward {
crystals?: number;
insights?: number;
contact?: number;
/** 永久产能加成(百分比,叠加到所有周目) */
crystalsPerSecPct?: number;
insightPct?: number;
}
export interface Achievement {
id: string;
name: string;
desc: string;
/** 图标 emoji(轻量,无需图标库) */
icon: string;
/** 颜色(用于徽章) */
color: string;
/** 判定函数:返回 true 表示达成 */
check: (s: GameState) => boolean;
reward: AchievementReward;
/** 奖励文本(展示用) */
rewardText: string;
}
export const ACHIEVEMENTS: Achievement[] = [
{
id: "ach_first_pulse",
name: "初次触碰",
desc: "发起第一次脉冲扫描",
icon: "✦",
color: "#34d399",
check: (s) => s.totalDecoded >= 0 || s.crystals > 0,
reward: { crystals: 5 },
rewardText: "+5 晶体",
},
{
id: "ach_first_decode",
name: "谐振初鸣",
desc: "成功解码第一颗记忆晶体",
icon: "◈",
color: "#fb7185",
check: (s) => s.totalDecoded >= 1,
reward: { insights: 3 },
rewardText: "+3 洞见",
},
{
id: "ach_decoded_10",
name: "回响解码者",
desc: "累计解码 10 颗晶体",
icon: "❖",
color: "#fbbf24",
check: (s) => s.totalDecoded >= 10,
reward: { insights: 15, crystalsPerSecPct: 5 },
rewardText: "+15 洞见 · 产能 +5%",
},
{
id: "ach_decoded_25",
name: "记忆织匠",
desc: "累计解码 25 颗晶体",
icon: "✺",
color: "#e879f9",
check: (s) => s.totalDecoded >= 25,
reward: { insights: 40, crystalsPerSecPct: 8 },
rewardText: "+40 洞见 · 产能 +8%",
},
{
id: "ach_decoded_50",
name: "星核解密师",
desc: "累计解码 50 颗晶体",
icon: "✷",
color: "#34d399",
check: (s) => s.totalDecoded >= 50,
reward: { insights: 100, crystalsPerSecPct: 12, insightPct: 10 },
rewardText: "+100 洞见 · 产能 +12% · 洞见 +10%",
},
{
id: "ach_tech_3",
name: "初窥门径",
desc: "解锁 3 项技术",
icon: "⚙",
color: "#fbbf24",
check: (s) => Object.values(s.tech).filter((v) => v > 0).length >= 3,
reward: { insights: 20 },
rewardText: "+20 洞见",
},
{
id: "ach_tech_all",
name: "全谱精通",
desc: "解锁全部 12 项技术",
icon: "⬡",
color: "#e879f9",
check: (s) => Object.values(s.tech).filter((v) => v > 0).length >= 12,
reward: { crystalsPerSecPct: 15, insightPct: 15 },
rewardText: "产能 +15% · 洞见 +15%",
},
{
id: "ach_frag_4",
name: "残篇拾遗",
desc: "拼凑 4 段记忆碎片",
icon: "▤",
color: "#fb7185",
check: (s) => Object.values(s.fragments).filter(Boolean).length >= 4,
reward: { contact: 10, insights: 25 },
rewardText: "+10 接触 · +25 洞见",
},
{
id: "ach_frag_all",
name: "回响全谱",
desc: "拼凑全部首纪元记忆碎片",
icon: "▦",
color: "#34d399",
check: (s) => Object.values(s.fragments).filter(Boolean).length >= 8,
reward: { contact: 25, crystalsPerSecPct: 10 },
rewardText: "+25 接触 · 产能 +10%",
},
{
id: "ach_exp_1",
name: "初探遗迹",
desc: "完成第一次遗迹探险",
icon: "▲",
color: "#fbbf24",
check: (s) => s.totalExpeditions >= 1,
reward: { insights: 10 },
rewardText: "+10 洞见",
},
{
id: "ach_exp_5",
name: "遗迹猎手",
desc: "累计出发 5 次探险",
icon: "⬢",
color: "#fb7185",
check: (s) => s.totalExpeditions >= 5,
reward: { insights: 30, crystalsPerSecPct: 5 },
rewardText: "+30 洞见 · 产能 +5%",
},
{
id: "ach_prestige_1",
name: "初次接触",
desc: "完成第一次飞升",
icon: "✧",
color: "#e879f9",
check: (s) => s.ascensions >= 1,
reward: { crystalsPerSecPct: 10, insightPct: 10 },
rewardText: "产能 +10% · 洞见 +10%",
},
{
id: "ach_prestige_3",
name: "维度行者",
desc: "累计飞升 3 次",
icon: "✶",
color: "#34d399",
check: (s) => s.ascensions >= 3,
reward: { crystalsPerSecPct: 20, insightPct: 20 },
rewardText: "产能 +20% · 洞见 +20%",
},
{
id: "ach_warehouse",
name: "满仓时刻",
desc: "晶体储量达到仓库上限",
icon: "▣",
color: "#fbbf24",
check: (s) => s.crystals >= s.crystalCap,
reward: { insights: 8 },
rewardText: "+8 洞见",
},
];
/** 计算成就提供的永久加成(跨周目保留) */
export function achievementBonuses(unlocked: Record<string, boolean>): {
crystalsPerSecPct: number;
insightPct: number;
} {
let crystalsPerSecPct = 0;
let insightPct = 0;
for (const a of ACHIEVEMENTS) {
if (!unlocked[a.id]) continue;
crystalsPerSecPct += a.reward.crystalsPerSecPct ?? 0;
insightPct += a.reward.insightPct ?? 0;
}
return { crystalsPerSecPct, insightPct };
}