P1-a 探险 BOSS 胜率平衡 + 能量恢复(expedition.ts + config.ts + gameStore.ts + ExpeditionPanel.tsx): - combatWinRate: scale 8→4, floor 0.25→0.35(基础力10对BOSS胜率 25%→35-45%) - BOSS 难度 5-7→3-5(配合新公式基础胜率达 45-55%) - computeEnergyRegenInterval(state): 动态恢复间隔 - exp_2 解锁 -30%, exp_3 解锁 -20%, 探索力属性 -最高30% - 下限 12s(原固定 45s) - computeEnergyRegen 接受 intervalSec 参数 - gameStore tick 传入动态间隔 - config.ts: exp_2/exp_3 描述加'能量恢复 +30%/+20%' - ExpeditionPanel: 显示实际恢复速度 + '已加速'标记 P1-b 信标系统扩展(beacon.ts + BeaconPanel.tsx + gameStore.ts)[subagent 9-b]: - 周挑战: getWeekKey ISO 8601 + FNV-1a 种子确定性生成 - 难度强制 anomaly 60%/singular 40%, goal 日挑战×3-5倍 - 完整进度/领奖/排行榜推送(isWeekly标记) - 信标链: 4里程碑(3/7/14/30天) + grace续命机制(每链1次) - recordChainCompletion 核心断链/续命逻辑 - 奖励 50→680洞见递增 - BeaconPanel: 周挑战fuchsia主题 + 信标链amber→rose渐变里程碑节点 - gameStore: trackBeacon升级 + claimWeeklyBeacon/claimChainReward actions - VLM 8/10, lint零错误, 5场景bun测试全PASS
343 lines
9.3 KiB
TypeScript
343 lines
9.3 KiB
TypeScript
// 回响星核 / Echo Nexus — 数值配置(数据驱动,便于平衡与工单迭代)
|
||
import type {
|
||
CrystalTier,
|
||
ResonanceColor,
|
||
TechNode,
|
||
Fragment,
|
||
} from "./types";
|
||
|
||
/** 初始状态 */
|
||
export const INITIAL_STATE = {
|
||
crystals: 0,
|
||
insights: 0,
|
||
energy: 3,
|
||
contact: 0,
|
||
crystalsPerSec: 0.4,
|
||
crystalCap: 50,
|
||
pulsePower: 2,
|
||
offlineEff: 0.5,
|
||
insightMult: 1,
|
||
contactRateMult: 1,
|
||
autoDecode: false,
|
||
totalDecoded: 0,
|
||
ascensions: 0,
|
||
blueprints: [] as string[],
|
||
pendingCrystals: [],
|
||
activePuzzle: null,
|
||
activeExpedition: null,
|
||
expeditionLog: [],
|
||
energyMax: 5,
|
||
lastEnergyTick: Date.now(),
|
||
totalExpeditions: 0,
|
||
bossKills: 0,
|
||
achievements: {},
|
||
activeTide: null,
|
||
lastTideEnd: 0,
|
||
starTidesEncountered: [] as string[],
|
||
constellation: [] as string[],
|
||
pendingPerkChoices: null as string[] | null,
|
||
chronicle: [] as import("./types").ChronicleEntry[],
|
||
runStart: {
|
||
timestamp: Date.now(),
|
||
techsUnlocked: 0,
|
||
expeditionsCompleted: 0,
|
||
bossKills: 0,
|
||
starTidesEncountered: [] as string[],
|
||
crystalsDecoded: 0,
|
||
},
|
||
// v0.7 角色属性系统
|
||
attributes: {
|
||
exploration: 0,
|
||
wisdom: 0,
|
||
courage: 0,
|
||
inspiration: 0,
|
||
} as import("./attributes").CharacterAttributes,
|
||
attributeProgress: {
|
||
exploration: { exp: 0, level: 0 },
|
||
wisdom: { exp: 0, level: 0 },
|
||
courage: { exp: 0, level: 0 },
|
||
inspiration: { exp: 0, level: 0 },
|
||
} as import("./attributes").AttributeProgress,
|
||
pendingAttrPoints: 0,
|
||
theme: "dark" as const,
|
||
soundOn: true,
|
||
};
|
||
|
||
/** 主动脉冲:连击窗口(毫秒)与加成 */
|
||
export const PULSE = {
|
||
comboWindowMs: 1500,
|
||
comboMultStep: 0.15, // 每连击 +15%
|
||
comboMax: 10,
|
||
};
|
||
|
||
/** 离线收益上限(小时) */
|
||
export const OFFLINE_CAP_HOURS = 8;
|
||
|
||
/** 接触进度:每次解码贡献 = base * tier * contactRateMult */
|
||
export const CONTACT = {
|
||
basePerDecode: 0.6,
|
||
// 飞升所需最低接触进度
|
||
prestigeMin: 100,
|
||
};
|
||
|
||
/** 晶体生成:每 N 秒自动产出一颗待解码晶体(受技术影响) */
|
||
export const CRYSTAL_SPAWN = {
|
||
baseIntervalSec: 8, // 每 8 秒产一颗
|
||
maxPending: 6,
|
||
/** tier 概率分布 */
|
||
tierWeights: { 1: 0.7, 2: 0.25, 3: 0.05 } as Record<CrystalTier, number>,
|
||
};
|
||
|
||
/** 晶体价值(解码奖励基础,× tier) */
|
||
export const CRYSTAL_VALUE = {
|
||
1: { crystals: 6, insights: 1 },
|
||
2: { crystals: 22, insights: 4 },
|
||
3: { crystals: 90, insights: 16 },
|
||
} as const;
|
||
|
||
/** 解码阵列配置(按 tier) */
|
||
export const DECODE_CONFIG: Record<
|
||
CrystalTier,
|
||
{ rows: number; cols: number; targetLen: number; stepLimitBase: number }
|
||
> = {
|
||
1: { rows: 3, cols: 3, targetLen: 3, stepLimitBase: 5 },
|
||
2: { rows: 4, cols: 4, targetLen: 4, stepLimitBase: 7 },
|
||
3: { rows: 5, cols: 4, targetLen: 5, stepLimitBase: 9 },
|
||
};
|
||
|
||
/** 共振颜色(4 色全息色谱,避开蓝/靛) */
|
||
export const RESONANCE_COLORS: ResonanceColor[] = [
|
||
"emerald",
|
||
"rose",
|
||
"amber",
|
||
"fuchsia",
|
||
];
|
||
|
||
/** 颜色可视化(用于 Canvas / CSS) */
|
||
export const COLOR_VISUAL: Record<
|
||
ResonanceColor,
|
||
{ hex: string; glow: string; label: string }
|
||
> = {
|
||
emerald: { hex: "#34d399", glow: "rgba(52,211,153,0.55)", label: "翠" },
|
||
rose: { hex: "#fb7185", glow: "rgba(251,113,133,0.55)", label: "玫" },
|
||
amber: { hex: "#fbbf24", glow: "rgba(251,191,36,0.55)", label: "琥" },
|
||
fuchsia: { hex: "#e879f9", glow: "rgba(232,121,249,0.55)", label: "紫" },
|
||
};
|
||
|
||
/** 技术树:4 分支 × 3 级 = 12 节点 */
|
||
export const TECH_TREE: TechNode[] = [
|
||
// 采矿分支
|
||
{
|
||
id: "min_1",
|
||
branch: "mining",
|
||
level: 1,
|
||
name: "谐振钻头",
|
||
desc: "晶体/秒 +0.6",
|
||
cost: 5,
|
||
effect: { kind: "crystalsPerSec", value: 0.6 },
|
||
},
|
||
{
|
||
id: "min_2",
|
||
branch: "mining",
|
||
level: 2,
|
||
name: "深层矿脉",
|
||
desc: "晶体/秒 +1.6,仓库上限 +100",
|
||
cost: 24,
|
||
effect: { kind: "crystalsPerSec", value: 1.6 },
|
||
},
|
||
{
|
||
id: "min_3",
|
||
branch: "mining",
|
||
level: 3,
|
||
name: "自治机群",
|
||
desc: "晶体/秒 +5,仓库上限 +300",
|
||
cost: 120,
|
||
effect: { kind: "crystalsPerSec", value: 5 },
|
||
},
|
||
// 解码分支
|
||
{
|
||
id: "dec_1",
|
||
branch: "decoding",
|
||
level: 1,
|
||
name: "谐振校准",
|
||
desc: "解码步数上限 +2",
|
||
cost: 6,
|
||
effect: { kind: "decodeSteps", value: 2 },
|
||
},
|
||
{
|
||
id: "dec_2",
|
||
branch: "decoding",
|
||
level: 2,
|
||
name: "脉冲增幅",
|
||
desc: "主动脉冲产出 +3",
|
||
cost: 30,
|
||
effect: { kind: "pulsePower", value: 3 },
|
||
},
|
||
{
|
||
id: "dec_3",
|
||
branch: "decoding",
|
||
level: 3,
|
||
name: "自动解码阵列",
|
||
desc: "自动解码 T1 晶体(每 12 秒一颗)",
|
||
cost: 200,
|
||
effect: { kind: "autoDecode", value: 1 },
|
||
},
|
||
// 探险分支(v0.2:探险力/生命/能量上限/产能)
|
||
{
|
||
id: "exp_1",
|
||
branch: "expedition",
|
||
level: 1,
|
||
name: "远征推进器",
|
||
desc: "探险力 +3,晶体/秒 +1.2",
|
||
cost: 12,
|
||
effect: { kind: "crystalsPerSec", value: 1.2 },
|
||
},
|
||
{
|
||
id: "exp_2",
|
||
branch: "expedition",
|
||
level: 2,
|
||
name: "遗迹图谱",
|
||
desc: "探险力 +5,探险生命 +20,能量恢复 +30%",
|
||
cost: 60,
|
||
effect: { kind: "crystalCap", value: 200 },
|
||
},
|
||
{
|
||
id: "exp_3",
|
||
branch: "expedition",
|
||
level: 3,
|
||
name: "维度信标",
|
||
desc: "探险力 +8,接触进度转化率 +50%,能量恢复 +20%",
|
||
cost: 180,
|
||
effect: { kind: "contactRate", value: 0.5 },
|
||
},
|
||
// 叙事分支
|
||
{
|
||
id: "nar_1",
|
||
branch: "narrative",
|
||
level: 1,
|
||
name: "记忆校音",
|
||
desc: "洞见获取 +25%",
|
||
cost: 8,
|
||
effect: { kind: "insightMult", value: 0.25 },
|
||
},
|
||
{
|
||
id: "nar_2",
|
||
branch: "narrative",
|
||
level: 2,
|
||
name: "深空回响",
|
||
desc: "接触进度转化率 +35%",
|
||
cost: 45,
|
||
effect: { kind: "contactRate", value: 0.35 },
|
||
},
|
||
{
|
||
id: "nar_3",
|
||
branch: "narrative",
|
||
level: 3,
|
||
name: "以太共鸣",
|
||
desc: "洞见获取 +60%",
|
||
cost: 160,
|
||
effect: { kind: "insightMult", value: 0.6 },
|
||
},
|
||
];
|
||
|
||
/** 技术分支元信息 */
|
||
export const TECH_BRANCH_META: Record<
|
||
string,
|
||
{ name: string; icon: string; color: string; desc: string }
|
||
> = {
|
||
mining: { name: "采矿", icon: "Pickaxe", color: "emerald", desc: "提升晶体产能与仓储" },
|
||
decoding: { name: "解码", icon: "ScanLine", color: "rose", desc: "强化解码与脉冲" },
|
||
expedition: { name: "探险", icon: "Rocket", color: "amber", desc: "远征与维度信标" },
|
||
narrative: { name: "叙事", icon: "BookOpen", color: "fuchsia", desc: "洞见与接触进度" },
|
||
};
|
||
|
||
/** 记忆碎片(首纪元 8 个,v0.1) */
|
||
export const FRAGMENTS: Fragment[] = [
|
||
{
|
||
id: "f1_1",
|
||
era: 1,
|
||
title: "第一缕谐振",
|
||
echo:
|
||
"在被称作「寂灭前夜」的年代,以太族第一次捕捉到来自虚空深处的谐振——那不是声音,而是存在的回声。他们将之记录在第一颗记忆晶体里。",
|
||
threshold: 1,
|
||
},
|
||
{
|
||
id: "f1_2",
|
||
era: 1,
|
||
title: "晶体之始",
|
||
echo:
|
||
"「我们为何要留下?」一位长者问。「因为后来的生命会需要方向。」于是他们熔铸星核,封存记忆,让晶体成为跨越时间的信笺。",
|
||
threshold: 3,
|
||
},
|
||
{
|
||
id: "f1_3",
|
||
era: 1,
|
||
title: "谐振法则",
|
||
echo:
|
||
"他们发现:思维可以被编码为共振序列。同色的节点相邻,便构成一句低语;一句句连成回响,回响连成文明。",
|
||
threshold: 6,
|
||
},
|
||
{
|
||
id: "f1_4",
|
||
era: 1,
|
||
title: "飞升之议",
|
||
echo:
|
||
"议会表决:是留下,还是离去?「留下意味着停滞;离去意味着信任。」最终,他们选择了信任——信任素未谋面的后来者。",
|
||
threshold: 10,
|
||
},
|
||
{
|
||
id: "f1_5",
|
||
era: 1,
|
||
title: "面包屑",
|
||
echo:
|
||
"他们没有带走一切。他们将知识拆成碎片,藏入晶体,散布星海。「让解码本身,成为资格的证明。」",
|
||
threshold: 15,
|
||
},
|
||
{
|
||
id: "f1_6",
|
||
era: 1,
|
||
title: "回响之名",
|
||
echo:
|
||
"舰载 AI 被命名为「回响」——意为:你是他们留下的回声,也是他们等待的回应。当你读懂这句话时,接触便已开始。",
|
||
threshold: 22,
|
||
},
|
||
{
|
||
id: "f1_7",
|
||
era: 1,
|
||
title: "第一个纪元的终焉",
|
||
echo:
|
||
"以太族集体褪去形体,如潮水退去。星海寂静了数万年。直到——你的脉冲扫描,唤醒了第一颗沉睡的晶体。",
|
||
threshold: 32,
|
||
},
|
||
{
|
||
id: "f1_8",
|
||
era: 1,
|
||
title: "致后来者",
|
||
echo:
|
||
"「如果你读到这里,说明你已具备跨越维度的资格。继续解码,继续拼凑。当进度满溢,我们将在更高处相会。」——以太族·第一纪元·绝笔",
|
||
threshold: 45,
|
||
},
|
||
];
|
||
|
||
/** 飞升:保留蓝图数 = floor(totalDecoded / 20),最多 6 */
|
||
export const PRESTIGE = {
|
||
blueprintsPerDecode: 20,
|
||
maxBlueprints: 6,
|
||
/** 每个蓝图提供 +5% 产能、+3% 洞见、+4% 接触率 */
|
||
perBlueprint: {
|
||
crystalsPerSecMult: 0.05,
|
||
insightMult: 0.03,
|
||
contactRateMult: 0.04,
|
||
},
|
||
};
|
||
|
||
/** 数值格式化:大数字友好显示 */
|
||
export function formatNum(n: number): string {
|
||
if (!isFinite(n)) return "∞";
|
||
if (n < 1000) return n.toFixed(n < 10 && n % 1 !== 0 ? 1 : 0);
|
||
if (n < 1e6) return (n / 1e3).toFixed(2) + "K";
|
||
if (n < 1e9) return (n / 1e6).toFixed(2) + "M";
|
||
if (n < 1e12) return (n / 1e9).toFixed(2) + "B";
|
||
return (n / 1e12).toFixed(2) + "T";
|
||
}
|