feat(v0.4): 回响编年史 — 跨周目叙事时间轴系统
- 新增 ChronicleEntry / RunStartSnapshot 类型与 GameState 字段 - 新建 chronicle.ts: 5 纪元名生成、模板化叙事、里程碑检测、run delta 计算 - engine.ts performPrestige 构建编年史条目并重置 runStart - gameStore: init 兼容旧存档 + tickTide 记录星潮 + resolveCurrentNode 计 BOSS 击杀 - chooseConstellationPerk 回填最近一条 entry 的 perksThisAscension - 新建 ChronicleDialog.tsx: 时间轴 UI + 5 纪元循环色 + 入场动画 - 新增 6 项成就: 首部编年/三纪元回响/五纪元闭环/首杀维度/维度猎手/星潮亲历者 - 新增 chronicle / chronicleOpen 程序化音效 - 修复关键 BUG: PrestigeDialog disabled 逻辑错误导致玩家永远无法飞升 - 修复 UX: newBp=0 时不再永久禁用飞升按钮(v0.3.1 星图+v0.4 编年史已提供动机) - 统计面板新增 BOSS 击破/星潮亲历/编年史条目 3 行 - 版本号升至 v0.4
This commit is contained in:
+36
-1
@@ -55,6 +55,10 @@ import {
|
||||
constellationBonuses,
|
||||
rollPerkChoices,
|
||||
} from "@/lib/game/constellation";
|
||||
import {
|
||||
migrateChronicleFields,
|
||||
withPerks,
|
||||
} from "@/lib/game/chronicle";
|
||||
|
||||
interface GameActions {
|
||||
// 生命周期
|
||||
@@ -177,6 +181,8 @@ export const useGameStore = create<Store>()(
|
||||
const activeTide = s.activeTide ?? null;
|
||||
const constellation = s.constellation ?? [];
|
||||
const pendingPerkChoices = s.pendingPerkChoices ?? null;
|
||||
// v0.4 编年史兼容:补全 chronicle / runStart / bossKills / starTidesEncountered
|
||||
const migrated = migrateChronicleFields(s);
|
||||
// 星图「能量共振」天赋 +1 能量上限
|
||||
const cm = constellationBonuses(constellation);
|
||||
const energyMax = (INITIAL_STATE.energyMax) + cm.energyMaxBonus;
|
||||
@@ -200,10 +206,14 @@ export const useGameStore = create<Store>()(
|
||||
constellation,
|
||||
pendingPerkChoices,
|
||||
energyMax,
|
||||
chronicle: migrated.chronicle,
|
||||
runStart: migrated.runStart,
|
||||
bossKills: migrated.bossKills,
|
||||
starTidesEncountered: migrated.starTidesEncountered,
|
||||
...syncStats({ tech: s.tech, blueprints: s.blueprints, achievements, activeTide: tide, constellation }),
|
||||
});
|
||||
} else {
|
||||
set({ lastTick: now, activePuzzle, achievements, activeTide: tide, lastTideEnd: tide ? lastTideEndRaw : lastTideEndRaw, constellation, pendingPerkChoices, energyMax, ...syncStats({ tech: s.tech, blueprints: s.blueprints, achievements, activeTide: tide, constellation }) });
|
||||
set({ lastTick: now, activePuzzle, achievements, activeTide: tide, lastTideEnd: tide ? lastTideEndRaw : lastTideEndRaw, constellation, pendingPerkChoices, energyMax, chronicle: migrated.chronicle, runStart: migrated.runStart, bossKills: migrated.bossKills, starTidesEncountered: migrated.starTidesEncountered, ...syncStats({ tech: s.tech, blueprints: s.blueprints, achievements, activeTide: tide, constellation }) });
|
||||
}
|
||||
},
|
||||
|
||||
@@ -258,8 +268,13 @@ export const useGameStore = create<Store>()(
|
||||
endsAt: now + TIDE_CONFIG.duration,
|
||||
};
|
||||
const event: { started?: TideType; ended?: TideType; silenceCompensation?: number } = { started: type };
|
||||
// v0.4 编年史:累计遇到的星潮 ID(去重)
|
||||
const tidesAll = s.starTidesEncountered ?? [];
|
||||
const tideId = `tide_${type}`;
|
||||
const newTidesAll = tidesAll.includes(tideId) ? tidesAll : [...tidesAll, tideId];
|
||||
set({
|
||||
activeTide: newTide,
|
||||
starTidesEncountered: newTidesAll,
|
||||
// 星潮开始后重算 stats(应用 contactRate/insight 修饰)
|
||||
...syncStats({ tech: s.tech, blueprints: s.blueprints, achievements: s.achievements, activeTide: newTide, constellation: s.constellation }),
|
||||
_tideEvents: [...s._tideEvents, event],
|
||||
@@ -556,6 +571,16 @@ export const useGameStore = create<Store>()(
|
||||
exp.finished = true;
|
||||
}
|
||||
|
||||
// v0.4 编年史:击破 BOSS 时累计计数
|
||||
let bossKills = s.bossKills ?? 0;
|
||||
if (
|
||||
result.ended &&
|
||||
result.endReason === "victory" &&
|
||||
exp.nodes[exp.currentNode]?.type === "boss"
|
||||
) {
|
||||
bossKills = bossKills + 1;
|
||||
}
|
||||
|
||||
set({
|
||||
activeExpedition: exp,
|
||||
crystals: newCrystals,
|
||||
@@ -563,6 +588,7 @@ export const useGameStore = create<Store>()(
|
||||
contact: newContact,
|
||||
fragments: newFragments,
|
||||
expeditionLog: newLog,
|
||||
bossKills,
|
||||
});
|
||||
return result;
|
||||
},
|
||||
@@ -626,10 +652,19 @@ export const useGameStore = create<Store>()(
|
||||
const newConstellation = [...(s.constellation ?? []), perkId];
|
||||
const cm = constellationBonuses(newConstellation);
|
||||
const energyMax = INITIAL_STATE.energyMax + cm.energyMaxBonus;
|
||||
// v0.4 编年史:回填最近一条 entry 的 perksThisAscension
|
||||
const chronicle = s.chronicle ?? [];
|
||||
let newChronicle = chronicle;
|
||||
if (chronicle.length > 0) {
|
||||
const lastEntry = chronicle[chronicle.length - 1];
|
||||
const updatedLast = withPerks(lastEntry, [perkId]);
|
||||
newChronicle = [...chronicle.slice(0, -1), updatedLast];
|
||||
}
|
||||
set({
|
||||
constellation: newConstellation,
|
||||
pendingPerkChoices: null,
|
||||
energyMax,
|
||||
chronicle: newChronicle,
|
||||
...syncStats({ tech: s.tech, blueprints: s.blueprints, achievements: s.achievements, activeTide: s.activeTide, constellation: newConstellation }),
|
||||
});
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user