v0.1.18: 时代绘卷 + 特效入引擎(双主线完成,1002 测试破千)
【主线一:世界自演进深化《时代绘卷》】 - 世纪弧 era 状态机:盛世/平世/乱世/末法四态(ERA_CONF 全参数化)。 灾年概率×0.5~1.6、世界供需×0.7~1.25、拍卖概率×0.6~1.3、tide 偏置 ±0.09; ERA_DURA 控制转换节奏(15~45年),转移时史官快讯+log。世界有大节律了 - NPC 景气仓廪:npcDyn.prosperity(8~100)月结余——买卖+0.5~0.8、断供-2、灾年-3; >75 景气 power+1、<30 衰闷 power-1;换代焕新(55~75)。NPC 在过日子 - 蝴蝶效应:互攻胜率 power 加权(强者恒强)、打残广播(败家邻望-8/胜家+4); 玩家劫掠胜利/结盟直接写 NPC·NPC 关系网(-6/-3)——玩家行动推进世界历史 - 天下十年一鉴:每十年史官综述(灾/换代/行情/灵潮聚合,kind='annal') - 灾年↔秘境:灾年灵脉恢复减半(末法感) - WorldPanel 天下志:era 徽标(悬停描述)/史官十年鉴/群雄势衡柱状图/衰微标注 【主线二:特效系统并入引擎(架构升级)】 - WorldEventBus.onFx + Kernel 转发 + World.emitFx 语义发射(零 rng 消耗) - 12 个语义发射点:突破/化神/渡劫/劫掠胜负/遭遇战/拍卖/大比/灾年起散/换代 —— 取代 UI log 文本正则猜测(spark/blade 双源锁死) - makeBus 桥接 FxGate(kind→gate.emit),gate 挡位/密度/reduced 逻辑保留在 UI 【测试】1002 全绿(40 套件):fxqueue-semantic 3 例 + era-world 5 例; 金钟罩 0.1.18 基线固化(era/prosperity/蝴蝶效应受控变更)
This commit is contained in:
@@ -131,6 +131,7 @@ export function resolveEncounter(
|
||||
lines.push(`此战缴获:${Object.entries(loot).map(([k, v]) => `${itemName(k)} ×${v}`).join('、')}。`)
|
||||
}
|
||||
|
||||
if (win && opts.kind === 'war') w.emitFx('blade', 'battle')
|
||||
const result: EncounterResult = { win, draw, lines, loot, losses: loss }
|
||||
const log: BattleLog = {
|
||||
id: w.seq(),
|
||||
@@ -191,12 +192,20 @@ export function resolveRaid(
|
||||
npc.relation = Math.min(60, npc.relation + 25)
|
||||
w.state.family.reputation += 6
|
||||
// B5:战争伤骨——败方 power 重挫,次年不再来犯(warCooldownYear/raidCount 启用)
|
||||
w.emitFx('blade', `raid:${npcId}`)
|
||||
npc.power = Math.max(40, Math.round(npc.power * 0.82))
|
||||
npc.raidCount = (npc.raidCount ?? 0) + 1
|
||||
npc.warCooldownYear = w.state.year
|
||||
// 1-3 蝴蝶效应:玩家重创名声——邻家对败者关系趋冷
|
||||
for (const dyn of Object.values(w.state.worldSim?.npcDyn ?? {})) {
|
||||
if (dyn && dyn.relationsWithOthers && npcId in dyn.relationsWithOthers) {
|
||||
dyn.relationsWithOthers[npcId] = Math.max(-100, (dyn.relationsWithOthers[npcId] ?? 0) - 6)
|
||||
}
|
||||
}
|
||||
w.chronicle('battle', `击退${npc.name}的犯境,家族声威大振。`, undefined, true)
|
||||
} else if (!res.draw) {
|
||||
npc.relation = Math.max(-100, npc.relation - 15)
|
||||
w.emitFx('pulse', `raid-lose:${npcId}`)
|
||||
npc.raidCount = (npc.raidCount ?? 0) + 1
|
||||
npc.warCooldownYear = w.state.year
|
||||
npc.power = Math.min(900, Math.round(npc.power * 1.06))
|
||||
|
||||
@@ -190,7 +190,9 @@ export function resolveBreakthrough(w: World, c: Character, boost: number): void
|
||||
const desc = describeRealm(next)
|
||||
w.chronicle('breakthrough', `${c.name} 突破至【${desc}】。`, c.id, majorJump)
|
||||
w.log('good', `✦ ${c.name} 突破到 ${desc}!`)
|
||||
w.emitFx('spark', `break:${c.id}`)
|
||||
if (next.major === 'spirit') {
|
||||
w.emitFx('pulse', `spirit:${c.id}`)
|
||||
w.chronicle('breakthrough', `华夏震惊:${c.name} 踏入化神之列。`, c.id, true)
|
||||
if (!w.state.flags['firstSpirit']) {
|
||||
w.state.flags['firstSpirit'] = w.state.year
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { World } from '../World'
|
||||
import { worldSimOf } from '../World'
|
||||
import { Character } from '../../../types/domain'
|
||||
import { Cond, EffectDef, EventDef, EVENTS, MemberEffect } from '../../../data/events'
|
||||
import { MAJOR_ORDER } from '../../../data/realms'
|
||||
@@ -343,10 +344,11 @@ export function eventRoll(w: World): void {
|
||||
return
|
||||
}
|
||||
}
|
||||
// 仙门拍卖(每年十月掷币)
|
||||
// 仙门拍卖(每年十月掷币;时代调制:盛世频仍/末法难逢)
|
||||
if (s.month === 10 && w.sysEnabled('production')) {
|
||||
const key = `auction-${s.year}`
|
||||
if (!s.family.flag[key] && w.rng.chance(0.55)) {
|
||||
const eraChance = w.state.worldSim ? Math.min(0.85, 0.55 * worldSimOf(w).eraAuctionMult()) : 0.55
|
||||
if (!s.family.flag[key] && w.rng.chance(eraChance)) {
|
||||
s.family.flag[key] = true
|
||||
fire(w, 'ev-auction')
|
||||
return
|
||||
@@ -557,6 +559,7 @@ export function applyEffect(w: World, eff: EffectDef, squad?: string[], _extra?:
|
||||
w.log('info', '拍卖会灵器已溢价转卖,回款150灵石。')
|
||||
}
|
||||
}
|
||||
w.emitFx('spark', 'auction')
|
||||
delete fam.flag['auctionWin']
|
||||
}
|
||||
if (eff.trib) {
|
||||
|
||||
@@ -79,6 +79,7 @@ export function runTournament(w: World, squad?: string[], formation?: FormationI
|
||||
const teamNames = team.map((c) => c.name).join('、')
|
||||
w.chronicle('battle', `太虚大比:${teamNames} 最终位列第${rank}名,赏灵石${rewards.stones}、声望+${rewards.rep}。`, undefined, true)
|
||||
w.log('good', `太虚大比落下帷幕,本族第${rank}名。`)
|
||||
w.emitFx(rank <= 3 ? 'spark' : 'ripple', 'tournament')
|
||||
}
|
||||
|
||||
export function apprenticeCandidates(w: World): Character[] {
|
||||
|
||||
@@ -47,6 +47,7 @@ export function resolveTribulation(w: World, c: Character, mode: 'rash' | 'guard
|
||||
if (w.rng.chance(p)) {
|
||||
c.realm = next
|
||||
c.realmProgress = 0
|
||||
w.emitFx('spark', `trib:${c.id}`)
|
||||
c.health = 100
|
||||
c.lastBreakthroughAttempt = s.year * 12 + s.month
|
||||
w.chronicle('breakthrough', `${c.name} 渡劫功成,踏入【${describeRealm(next)}】!`, c.id, true)
|
||||
|
||||
Reference in New Issue
Block a user