v0.1.20: 万世无谬(第二轮全量审计歼灭,1011 测试+双金钟罩)
【事件闸(机制重锤)】 - fire(w,id,priority):单闸+优先级——高优(raid/渡劫/大比)顶替被占者、被顶替入 eventQueue 下月兑现不丢失;普通被占返回 false 调用方冷却(raid 被吞也写 CD) - pending 唯一写入入口:渡劫/破境丹改走 fire(防覆盖丢弃);名宿传薪年锚 flag(防同年重复 12 次) - applyEventChoice 前置校验 pendingEvent===id(陈旧 Modal 二次结算防线) 【世界模型四修(真·活世界)】 - era 延续档:flow 权重和<1(留白=续任)——盛世能撑 30 年而非固定 25 - 潮汐供给符号修正:灵涨万物丰(原实现反了)+tide 双界 clamp - driftMarket 弱锚定:rebalance 0.1→0.025——供需/era/灾年真实撬动价格(原五池被锚死±5%) - 断供/池底单常量 poolFloorPct=0.35(消灭禁买暗雷带) 【知识防线(审计虫洞修复)】 - 指纹扩展:era/stance/prosperity/relationsWithOthers/calamityLeft/pendingEvent 全入 hash - 第二金钟罩 GOLDEN_RESOLVED:自动 resolve 长跑锁“现实”世界(原指纹锁的只是“事件流冻结”世界) 【性能与存储】 - 存档节流(疾12/常6/缓4,手动即时)+ saveChronicle O(N)→O(1) 单查增量写(2160 月档告别每 tick 数千 OPFS) - battles≤220/chronicle≤520 截断(stringify 线性膨胀止血);startNewGame/openState 停 timer 摘旧 bus 【杂项】actDirect 对齐 ACT_CATALOG 全 24 项;about 三版本统一 0.1.20;kernel.bus 死总线删;seed 改 RngHub.rollSeed;normalize 补 eraStartYear/overflux/distress;WorldPanel 买卖条件反转修复;音效与视效同闸 【测试】1011 全绿(42 套件):audit-0.1.20 9 例(事件闸/传薪/二次结算/era延续/潮汐符号/断供一致/弱锚定/指纹敏感)
This commit is contained in:
@@ -13,6 +13,7 @@ import { ASPIRATION_IDS } from '../../../data/aspirations'
|
||||
import { seasonMod } from '../../../data/season'
|
||||
import { bonusOf } from '../../../data/buildings'
|
||||
import { needsTribulation, tribulationEventId } from './tribulation'
|
||||
import { fire } from './events'
|
||||
|
||||
export function monthlyRate(w: World, c: Character, herbFactor = 1): number {
|
||||
const st = w.state
|
||||
@@ -125,8 +126,7 @@ export function cultivationTick(w: World): void {
|
||||
continue
|
||||
}
|
||||
c.tribDelayYear = undefined
|
||||
w.pendingEvent(tribulationEventId(c))
|
||||
w.state.pendingEvent = tribulationEventId(c)
|
||||
fire(w, tribulationEventId(c), 1)
|
||||
} else {
|
||||
resolveBreakthrough(w, c, 0)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { World } from '../World'
|
||||
import { npcById } from '../../../data/npcs'
|
||||
import { findEvent, fire } from './events'
|
||||
import { WORLDSIM } from '../../sim/worldsim-data'
|
||||
|
||||
export function diplomacyTick(w: World): void {
|
||||
const s = w.state
|
||||
@@ -14,16 +15,18 @@ export function diplomacyTick(w: World): void {
|
||||
const last = (w.state.family.flag[`raidCD-${npc.id}`] as number | undefined) ?? 0
|
||||
// 姿态调制:扩张好勇、隐忍避战、结盟之势休兵
|
||||
const stance = (w.state.worldSim?.npcDyn?.[npc.id] as { stance?: string } | undefined)?.stance
|
||||
let raidMult = stance === 'expand' ? 2 : stance === 'endure' ? 0.4 : stance === 'ally' ? 0 : 1
|
||||
// 0.1.19 盟约连坐:与我结盟各家的世仇,更易扣边
|
||||
let raidP = 0.03 * (stance === 'expand' ? 2 : stance === 'endure' ? 0.4 : stance === 'ally' ? 0 : 1)
|
||||
// 0.1.20 盟约连坐(加性):与我结盟各家的世仇,更易扣边——不再×2×盟数叠爆
|
||||
const dyns = (w.state.worldSim?.npcDyn ?? {}) as Record<string, { relationsWithOthers?: Record<string, number> }>
|
||||
for (const ally of Object.values(s.npcFamilies)) {
|
||||
if (!ally.allied) continue
|
||||
const rel = dyns[ally.id]?.relationsWithOthers?.[npc.id] ?? 0
|
||||
if (rel < -60) raidMult *= 2
|
||||
if (rel < -60) raidP += WORLDSIM.allianceGriefRaid
|
||||
}
|
||||
if (s.year - last >= 2 && w.rng.chance(0.03 * raidMult)) {
|
||||
fire(w, `ev-raid-${npc.id}`)
|
||||
if (s.year - last >= 2 && w.rng.chance(Math.min(0.3, raidP))) {
|
||||
// 高优投放;被顶替不丢失
|
||||
const ok = fire(w, `ev-raid-${npc.id}`, 1)
|
||||
if (!ok) w.state.family.flag[`raidCD-${npc.id}`] = s.year
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,10 +401,22 @@ export function eventRoll(w: World): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function fire(w: World, id: string): void {
|
||||
if (w.state.pendingEvent) return
|
||||
w.state.pendingEvent = id
|
||||
/**
|
||||
* 事件投放(唯一 pending 入口)。
|
||||
* priority=0 普通(被占则放弃,下次再来);priority=1 高优(raid/渡劫/大比——可顶替被占的普通事件,
|
||||
* 被顶替者转存 eventQueue 下月兑现,不丢失)。
|
||||
* 返回 true=已在档(pending=id);false=被占未投放(调用方应自行冷却/重试)。
|
||||
*/
|
||||
export function fire(w: World, id: string, priority: 0 | 1 = 0): boolean {
|
||||
const s = w.state
|
||||
if (s.pendingEvent) {
|
||||
if (priority === 0) return false
|
||||
const prev = s.pendingEvent
|
||||
if (prev !== id && !s.eventQueue.includes(prev)) s.eventQueue.push(prev)
|
||||
}
|
||||
s.pendingEvent = id
|
||||
w.pendingEvent(id)
|
||||
return true
|
||||
}
|
||||
|
||||
export function applyEventChoice(
|
||||
@@ -416,6 +428,8 @@ export function applyEventChoice(
|
||||
formation?: string
|
||||
): void {
|
||||
const s = w.state
|
||||
// 2 次结算防线:事件已被自动压制/取代/清空时,UI 陈旧选择不得落盘
|
||||
if (s.pendingEvent && s.pendingEvent !== eventId) return
|
||||
const def = findEvent(eventId, w)
|
||||
if (!def) {
|
||||
s.pendingEvent = undefined
|
||||
|
||||
Reference in New Issue
Block a user