Files
rebirthlife/src/engine/death.js
T
congsh 3f741b4f0a feat: add age-based event gating, event timer, and UI polish
- Add minAge/maxAge to events so infants can't go treasure hunting
- Cache event panel DOM to prevent high-speed button destruction
- Add 10s auto-select countdown for choice events
- Fix event title/text field mapping (name/description → title/text)
- Add rotating clock icon for time flow feedback
- Fix speed/pause button active states
- Fix shop affordability check (disable + show insufficient money)
- Add red styling for unmet choice requirements
- Fix log re-rendering on every tick
2026-05-13 09:09:42 +00:00

174 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ==================== 死亡与结算 ====================
import { state, addLog, resetStateForRebirth } from './state.js';
import { CAREERS } from './expSystem.js';
import { checkNewEntries as checkNewEntriesFromTalents } from '../content/talents.js';
// 检查是否死亡
export function checkDeath() {
if (!state.alive) return true;
// 年龄死亡
if (state.age >= 100) {
die('寿终正寝');
return true;
}
if (state.age >= 50) {
const deathChance = getAgeDeathChance(state.age);
if (Math.random() < deathChance) {
die('寿终正寝');
return true;
}
}
// 外敌死亡
for (const [type, progress] of Object.entries(state.enemyProgress)) {
if (progress >= 100 && Math.random() < 0.4) {
const names = { military: '死于蛮族入侵', spiritual: '被天魔吞噬', political: '王朝覆灭,死于战乱' };
die(names[type] || '死于外敌');
return true;
}
}
// 体质死亡
if (state.stats.body <= 0) {
die('体弱身亡');
return true;
}
// 危机感死亡(极端情况)
if (state.crisisLevel >= 100 && Math.random() < 0.3) {
die('在极度恐惧中精神崩溃');
return true;
}
return false;
}
function getAgeDeathChance(age) {
if (age < 50) return 0;
if (age < 60) return 0.02;
if (age < 70) return 0.08;
if (age < 80) return 0.20;
if (age < 90) return 0.45;
if (age < 100) return 0.80;
return 1.0;
}
// 死亡结算
function die(reason) {
if (!state.alive) return;
state.alive = false;
addLog(`你死了。原因:${reason}`, 'death');
// 结算元经验
const metaGains = {};
for (const [id, career] of Object.entries(state.careers)) {
const config = CAREERS[id];
if (!config) continue;
let totalExp = career.exp;
for (let i = 0; i < career.level; i++) {
totalExp += Math.floor(config.baseExp * Math.pow(config.expCurve, i));
}
const gain = Math.floor(totalExp * 0.1);
state.metaExp[id] = (state.metaExp[id] || 0) + gain;
metaGains[id] = gain;
}
// 解锁新词条
const newEntries = checkNewEntriesFromTalents(state);
for (const entry of newEntries) {
state.unlockedEntries.add(entry.id);
}
// 外敌进度跨轮继承(保留30%
for (const key of Object.keys(state.enemyProgress)) {
state.enemyProgress[key] = Math.min(100, state.enemyProgress[key] * 0.3 + 5);
}
// 触发死亡结算界面
if (typeof window !== 'undefined' && window.onDeath) {
window.onDeath({
reason,
age: state.age,
day: state.day,
careers: Object.fromEntries(
Object.entries(state.careers).map(([k, v]) => [k, { level: v.level, name: CAREERS[k]?.name }])
),
metaGains,
newEntries,
history: getHistoryComparison(),
});
}
}
// 历史对比
function getHistoryComparison() {
if (state.history.length === 0) return null;
const lastLife = state.history[state.history.length - 1];
const bestLife = state.history.reduce((best, current) =>
(current.age > best.age) ? current : best
, state.history[0]);
return {
vsLast: {
ageDiff: state.age - lastLife.age,
levelDiff: compareLevels(state.careers, lastLife.careers),
},
vsBest: {
ageDiff: state.age - bestLife.age,
levelDiff: compareLevels(state.careers, bestLife.careers),
},
};
}
function compareLevels(current, previous) {
const result = {};
const allIds = new Set([...Object.keys(current), ...Object.keys(previous)]);
for (const id of allIds) {
const curr = current[id]?.level || 0;
const prev = previous[id]?.level || 0;
result[id] = curr - prev;
}
return result;
}
// 重生
export function rebirth() {
resetStateForRebirth();
// 随机出身
state.family = Math.floor(Math.random() * 4) - 1; // -1 ~ 2
state.stats = {
body: Math.floor(Math.random() * 5) + 2, // 2~6,避免刚出生就死
wisdom: Math.floor(Math.random() * 5) + 2,
charm: Math.floor(Math.random() * 5) + 2,
luck: Math.floor(Math.random() * 5) + 2,
};
// 应用记忆效果
if (state.memories.includes('wisdom_boost')) state.stats.wisdom += 1;
if (state.memories.includes('body_boost')) state.stats.body += 1;
// 从已解锁词条池中随机抽取
const pool = Array.from(state.unlockedEntries);
state.talents = [];
const count = Math.min(3 + Math.floor(state.reincarnation / 10), 5);
for (let i = 0; i < count && pool.length > 0; i++) {
const idx = Math.floor(Math.random() * pool.length);
state.talents.push({ id: pool[idx] });
pool.splice(idx, 1);
}
addLog(`${state.reincarnation}世开始。出身: ${state.family > 0 ? '富贵' : state.family < 0 ? '贫寒' : '普通'}人家。`);
// 触发重生事件
if (typeof window !== 'undefined' && window.onRebirth) {
window.onRebirth();
}
}