Files
ChronicleOfTheImmortalClan/src/renderer/game/engine/runtime/clocks.ts
T

91 lines
3.7 KiB
TypeScript
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 { GameClock } from '../kernel/clock'
import { PluginContext } from '../kernel/plugin'
import type { World } from './World'
import { productionTick } from './Systems/production'
import { deathTick, woundHealTick } from './Systems/lifecycle'
import { cultivationTick } from './Systems/cultivation'
import { missionTick } from './Systems/missions'
import { eventRoll } from './Systems/events'
import { diplomacyTick } from './Systems/diplomacy'
import { yearStartMarriage } from './Systems/marriage'
import { WorldSim } from '../sim/WorldSim'
import { checkMandate } from './Systems/mandate'
/** 原语义保留:满门凋零后仅存生产/寿元与收尾 */
function ifAlive(fn: (w: World) => void): (w: World) => void {
return (w: World) => {
if (w.aliveMembers().length > 0) fn(w)
}
}
/** 能力开关:禁用即拔插(对应 capability id */
function viaCap(capId: string, fn: (w: World) => void): (w: World) => void {
return (w: World) => {
if (w.sysEnabled(capId)) fn(w)
}
}
export function emptyClock(): GameClock {
return new GameClock()
}
/**
* 内建系统注册(core-systems 插件入口)。
* 注册顺序 = 执行顺序(确定性红线,经由金钟罩校验)。
* 时间线:婚配养育 → 声望岁贡 → 岁末族簿 —— 再逐月:生产→寿元→修炼→任务→事件→外交→收尾
*/
export function installCoreSystems(ctx: PluginContext): Array<() => void> {
const unsubs: Array<() => void> = []
const clock = ctx.clock
unsubs.push(clock.onYearStart(viaCap('marriage', (w) => yearStartMarriage(w))))
unsubs.push(
clock.onYearStart(
viaCap('marriage', (w) => {
w.state.family.reputation += w.postBonus('familyRep')
const zhenCount = w.aliveMembers().filter((c) => c.aspiration === 'zhen').length
w.state.family.reputation += Math.round(zhenCount * 0.3 * 100) / 100
})
)
)
unsubs.push(clock.onYearStart(viaCap('annals', (w) => w.publishYearReport())))
unsubs.push(clock.register('production', viaCap('production', (w: World) => productionTick(w))))
unsubs.push(clock.register('aging', viaCap('aging', (w: World) => deathTick(w))))
unsubs.push(clock.register('aging', viaCap('aging', (w: World) => woundHealTick(w))))
unsubs.push(clock.register('cultivation', viaCap('cultivation', ifAlive((w: World) => cultivationTick(w)))))
unsubs.push(clock.register('missions', viaCap('missions', ifAlive((w: World) => missionTick(w)))))
unsubs.push(clock.register('events', viaCap('events', ifAlive((w: World) => eventRoll(w)))))
unsubs.push(clock.register('diplomacy', viaCap('diplomacy', ifAlive((w: World) => diplomacyTick(w)))))
unsubs.push(clock.register('worldsim', (w: World) => {
if (w.sysEnabled('worldsim')) {
new WorldSim(w).tick()
}
}))
unsubs.push(clock.register('epilogue', (w: World) => w.epilogueTick()))
// 0.1.40 天命系统:epilogue 末检查天命是否到期——种子派生选取,零 rng 消耗
unsubs.push(clock.register('epilogue', viaCap('events', ifAlive((w: World) => { void checkMandate(w) }))))
return unsubs
}
/** 兼容旧接口:完整安装一套核心系统(测试/工具用) */
export function buildClock(): GameClock {
const clock = emptyClock()
const ctx = {
world: undefined as never,
clock,
register: (phase: Parameters<GameClock['register']>[0], fn: (w: World) => void) => clock.register(phase, fn),
onYearStart: (fn: (w: World) => void) => clock.onYearStart(fn),
addCapability: () => undefined,
removeCapability: () => undefined,
enableCapability: () => undefined,
overridePack: () => undefined,
resetPack: () => undefined,
addEventPool: () => undefined,
removeEventPool: () => undefined
}
installCoreSystems(ctx as never)
return clock
}