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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user