// 回响星核 / Echo Nexus — 星潮事件系统(周期性全局玩法修饰) // // 深空中偶发的「星潮」会短暂改变物理法则,给放置循环注入动态变化。 // 每 ~40s 间隙后触发一次持续 ~75s 的星潮,6 种类型各有正负效果。 export type TideType = | "crystal" // 晶体潮:产能 ×2 | "resonance" // 谐振风暴:解码奖励 +60% | "ruins" // 遗迹共振:探险力 +5、生命 +30 | "void" // 虚空低语:洞见 ×2 | "core" // 星核悸动:接触率 ×3、脉冲 ×2 | "silence"; // 寂静期:产能 ×0.5,但结束时补偿洞见 export interface StarTide { type: TideType; startedAt: number; endsAt: number; /** 唯一 id,用于 React key */ id: string; } export interface TideModifiers { crystalsPerSecMult: number; decodeRewardMult: number; insightMultAdd: number; // 加到 insightMult(百分比,0.5 = +50%) contactRateMult: number; pulsePowerMult: number; expeditionPowerBonus: number; expeditionHpBonus: number; /** 寂静期结束时补偿的洞见(按持续秒数) */ silenceInsightPerSec?: number; } export const TIDE_CONFIG = { /** 星潮持续时间(毫秒) */ duration: 75000, /** 星潮之间的间隙(毫秒) */ gap: 40000, /** 首次星潮触发延迟(毫秒,从 init 起) */ firstDelay: 30000, }; export const TIDE_EVENTS: Record< TideType, { name: string; desc: string; color: string; glow: string; icon: string; /** 是否负面事件(影响 UI 提示语气) */ negative: boolean; } > = { crystal: { name: "晶体潮", desc: "深空晶体涌动,采矿产能翻倍", color: "#34d399", glow: "rgba(52,211,153,0.5)", icon: "✺", negative: false, }, resonance: { name: "谐振风暴", desc: "共振序列被放大,解码奖励 +60%", color: "#fb7185", glow: "rgba(251,113,133,0.5)", icon: "❖", negative: false, }, ruins: { name: "遗迹共振", desc: "远古遗迹苏醒,探险力 +5、生命 +30", color: "#fbbf24", glow: "rgba(251,191,36,0.5)", icon: "⬢", negative: false, }, void: { name: "虚空低语", desc: "虚空传来回响,洞见获取翻倍", color: "#e879f9", glow: "rgba(232,121,249,0.5)", icon: "✷", negative: false, }, core: { name: "星核悸动", desc: "星核震荡,接触率 ×3、脉冲威力 ×2", color: "#a5f3fc", glow: "rgba(165,243,252,0.5)", icon: "✦", negative: false, }, silence: { name: "寂静期", desc: "虚空沉寂,产能减半;结束时按时长补偿洞见", color: "#94a3b8", glow: "rgba(148,163,184,0.5)", icon: "◌", negative: true, }, }; /** 权重表(寂静期概率略低) */ const TIDE_WEIGHTS: Record = { crystal: 22, resonance: 20, ruins: 16, void: 18, core: 14, silence: 10, }; export function rollTide(rng: () => number = Math.random): TideType { const total = Object.values(TIDE_WEIGHTS).reduce((a, b) => a + b, 0); let r = rng() * total; for (const k of Object.keys(TIDE_WEIGHTS) as TideType[]) { r -= TIDE_WEIGHTS[k]; if (r <= 0) return k; } return "crystal"; } /** 计算当前星潮的修饰器 */ export function getTideModifiers(tide: StarTide | null): TideModifiers { if (!tide) { return { crystalsPerSecMult: 1, decodeRewardMult: 1, insightMultAdd: 0, contactRateMult: 1, pulsePowerMult: 1, expeditionPowerBonus: 0, expeditionHpBonus: 0, }; } switch (tide.type) { case "crystal": return { crystalsPerSecMult: 2, decodeRewardMult: 1, insightMultAdd: 0, contactRateMult: 1, pulsePowerMult: 1, expeditionPowerBonus: 0, expeditionHpBonus: 0, }; case "resonance": return { crystalsPerSecMult: 1, decodeRewardMult: 1.6, insightMultAdd: 0, contactRateMult: 1, pulsePowerMult: 1, expeditionPowerBonus: 0, expeditionHpBonus: 0, }; case "ruins": return { crystalsPerSecMult: 1, decodeRewardMult: 1, insightMultAdd: 0, contactRateMult: 1, pulsePowerMult: 1, expeditionPowerBonus: 5, expeditionHpBonus: 30, }; case "void": return { crystalsPerSecMult: 1, decodeRewardMult: 1, insightMultAdd: 1, // insightMult 翻倍(+100%) contactRateMult: 1, pulsePowerMult: 1, expeditionPowerBonus: 0, expeditionHpBonus: 0, }; case "core": return { crystalsPerSecMult: 1, decodeRewardMult: 1, insightMultAdd: 0, contactRateMult: 3, pulsePowerMult: 2, expeditionPowerBonus: 0, expeditionHpBonus: 0, }; case "silence": return { crystalsPerSecMult: 0.5, decodeRewardMult: 1, insightMultAdd: 0, contactRateMult: 1, pulsePowerMult: 1, expeditionPowerBonus: 0, expeditionHpBonus: 0, silenceInsightPerSec: 0.4, }; } } /** 寂静期结束时的洞见补偿 */ export function computeSilenceCompensation(tide: StarTide): number { const mod = getTideModifiers(tide); if (!mod.silenceInsightPerSec) return 0; const secs = (tide.endsAt - tide.startedAt) / 1000; return Math.round(mod.silenceInsightPerSec * secs); }