v0.1.15: 深度审计加固(7 P0 + 20+ P1 歼灭)
【引擎层 P0】 - GameEngine.restore 双重时钟注册(回档后整月双跑)→ restore 重建内核+回置 rng 状态 - engineFromSnapshot 必崩(globalThis.__state 从未设)→ 修正带 seed 重建 - DEV 性能分支二次执行整月管线 → 只读告警(绝不重跑) - 引擎 advance 遇待决事件死锁 → resolvePending(idx) 通道(自动化/测试推进) 【WorldSim 大修】 - NPC 换代文案垃圾(n-danxin行情降50%)→ 换代快讯专属文案 - secretQi 假闭环(纯写无读)→ 全秘境初始化+missions 统一 consumeSecretQi - 快讯节流自锁(lastNewsMonth 恒 1 月)→ totalTicks%24 - power 月度收敛坍塌(1400±3)→ 换代/年首化+年度成长 - relation 双重拉零(4 家全 0)→ 交还外交年度漂移 - 市场基准 5 处重复 → POOL_BASE 单一权威;灾年 stale 清理;drift 各池独立噪声 - worldsim 能力卡补全 + normalize 兜底(worldSim/stats 子字段) 【UI/动效/存储】 - ModalShell 三条 CSS 规则真正落地(close 定位/body 滚动/footer 独立底排)——0.1.12 声明未实施项 - fx-canvas:resize 监听移除/mistTimer 清零/reduced 联动/soft 档无雾 + drift 走 gate(过滤器) - 档位 density 脱钩修复;顶栏“止”钮补 onClick;版本号三处统一 0.1.15 - importAll 清 chronicle 表;自动推进季度落盘(手动逐次) - 性能:LogFeed memo / Genealogy computeGenealogy memo / Chronicle deps 修正;死码清除(lastPhaseStats/clockFromKernel/哨兵函数等 12 处) - 删除误入库的“p”游离文件 【测试】979 全绿(36 套件);金钟罩三档 0.1.15 基线固化; typecheck/build 通过
This commit is contained in:
@@ -137,7 +137,7 @@ export class GameFacade {
|
||||
about(): { title: string; version: string; modules: number; systems: number; plugins: number; packFingerprint: string } {
|
||||
return {
|
||||
title: '仙途家族志',
|
||||
version: '0.1.11',
|
||||
version: '0.1.15',
|
||||
modules: this.world.systemList().length,
|
||||
systems: this.world.systemList().filter((s) => s.enabled).length,
|
||||
plugins: this.world.pluginList().length,
|
||||
|
||||
@@ -421,8 +421,7 @@ export function applyEventChoice(
|
||||
}
|
||||
const opt = def.options[optionIdx]
|
||||
if (opt) {
|
||||
if (formation) opt.eff.formation = formation
|
||||
applyEffect(w, opt.eff, squad)
|
||||
applyEffect(w, opt.eff, squad, undefined, formation)
|
||||
if (def.once && !s.completedEvents.includes(def.id)) s.completedEvents.push(def.id)
|
||||
}
|
||||
s.pendingEvent = undefined
|
||||
@@ -468,7 +467,7 @@ export function rankPower(w: World, c: Character): number {
|
||||
return order.indexOf(c.realm.major) * 10 + c.realm.minor
|
||||
}
|
||||
|
||||
export function applyEffect(w: World, eff: EffectDef, squad?: string[]): void {
|
||||
export function applyEffect(w: World, eff: EffectDef, squad?: string[], _extra?: unknown, formation?: string): void {
|
||||
const s = w.state
|
||||
const fam = s.family
|
||||
|
||||
@@ -513,7 +512,7 @@ export function applyEffect(w: World, eff: EffectDef, squad?: string[]): void {
|
||||
if (!fam.techniques.includes(eff.addTech)) fam.techniques.push(eff.addTech)
|
||||
}
|
||||
if (eff.tournament) {
|
||||
runTournament(w, squad, eff.formation as never)
|
||||
runTournament(w, squad, formation as never)
|
||||
}
|
||||
if (eff.apprentice?.build) {
|
||||
buildApprentice(w)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { MissionState } from '../../../types/domain'
|
||||
import { FormationId } from '../../../data/formations'
|
||||
import { missionById, MissionDef, ENEMIES } from '../../../data/secrets'
|
||||
import { resolveEncounter, rollWarbooty } from './combat'
|
||||
import { WorldSim } from '../../sim/WorldSim'
|
||||
import { techniqueById } from '../../../data/techniques'
|
||||
import { describeRealm } from '../../../data/realms'
|
||||
|
||||
@@ -138,14 +139,9 @@ export function sendMission(w: World, defId: string, members: string[], formatio
|
||||
const c = w.memberById(id)
|
||||
c.state = 'expedition'
|
||||
})
|
||||
// 世界秘境灵气消耗(有 sim 时)
|
||||
if (w.state.worldSim?.secretQi) {
|
||||
const qi = w.state.worldSim.secretQi[def.id] as number | undefined
|
||||
if (qi !== undefined) {
|
||||
w.state.worldSim.secretQi[def.id] = Math.max(0, qi - 6)
|
||||
} else {
|
||||
w.state.worldSim.secretQi[def.id] = 44
|
||||
}
|
||||
// 世界秘境灵气消耗(统一走 WorldSim 入口)
|
||||
if (w.state.worldSim) {
|
||||
new WorldSim(w).consumeSecretQi(def.id)
|
||||
}
|
||||
w.state.missions.push(m)
|
||||
w.state.family.missionIds.push(m.id)
|
||||
|
||||
@@ -17,10 +17,6 @@ import { createWorldState, findInheritor } from './creation'
|
||||
import { SYSTEM_DEFS, SystemDef } from './capabilities'
|
||||
import { emptyClock } from './clocks'
|
||||
import { Rng } from '../kernel/rng'
|
||||
|
||||
function clockFromKernel(_target: GameClock, source: GameClock): void {
|
||||
void source
|
||||
}
|
||||
import { CotycPlugin, PluginContext, PluginStatus } from '../kernel/plugin'
|
||||
import { PluginManager } from './pluginManager'
|
||||
import { EventDef } from '../../data/events'
|
||||
@@ -79,6 +75,15 @@ export function normalizeGameState(state: GameState): GameState {
|
||||
if (!state.family.buildings) state.family.buildings = {}
|
||||
if (!state.family.techniques) state.family.techniques = []
|
||||
if (!state.family.missionIds) state.family.missionIds = []
|
||||
if (!state.stats.tourneyHistory) state.stats.tourneyHistory = []
|
||||
if (state.stats.tourneyBest === undefined) state.stats.tourneyBest = undefined
|
||||
if (state.worldSim) {
|
||||
state.worldSim.marketPool = state.worldSim.marketPool ?? {}
|
||||
state.worldSim.npcDyn = state.worldSim.npcDyn ?? {}
|
||||
state.worldSim.secretQi = state.worldSim.secretQi ?? {}
|
||||
state.worldSim.newsFeed = state.worldSim.newsFeed ?? []
|
||||
if (typeof state.worldSim.tide !== 'number') state.worldSim.tide = 0.5
|
||||
}
|
||||
if (state.family.headId && !state.members[state.family.headId]) {
|
||||
const firstAlive = Object.values(state.members).find((c) => c.alive)
|
||||
if (firstAlive) state.family.headId = firstAlive.id
|
||||
@@ -275,10 +280,6 @@ export class World {
|
||||
this.out.forEach((o) => o.onGameOver(reason, year))
|
||||
}
|
||||
|
||||
gameOver___placeholder(): void {
|
||||
void 0
|
||||
}
|
||||
|
||||
memberById(id: Id): Character {
|
||||
const c = this.state.members[id]
|
||||
if (!c) throw new Error(`member not found ${id}`)
|
||||
@@ -316,6 +317,13 @@ export class World {
|
||||
this.pruneYearFlags()
|
||||
}
|
||||
|
||||
applyEventChoice(eventId: string, idx: number): boolean {
|
||||
const pid = this.state.pendingEvent
|
||||
if (!pid) return false
|
||||
applyEventChoice(this, pid, idx)
|
||||
return true
|
||||
}
|
||||
|
||||
requeueEvent(eventId: string): void {
|
||||
const s = this.state
|
||||
if (!s.eventQueue.includes(eventId)) s.eventQueue.push(eventId)
|
||||
|
||||
Reference in New Issue
Block a user