0.1.37 天人感应·因果织锦:功德系统+飞升试炼+世界奇观+MOD扩展口

This commit is contained in:
2026-09-10 23:37:57 +08:00
parent 2984d05647
commit 87cd71ad21
24 changed files with 1062 additions and 43 deletions
+113 -4
View File
@@ -1,6 +1,6 @@
/** WorldSim —— 世界自进化引擎(game/engine/sim/WorldSim.ts */
import { World } from '../runtime/World'
import { WorldSimState, NpcDynamics, WORLDSIM, ERA_CONF, makeWorldSimState, NpcStance, REGION_TIDE, eraDuraOf, regionTideOf, calamityNames, calamityFamilyOf, calamityEffectOf, CalamityName, POOL_BASE, worldNum } from './worldsim-data'
import { WorldSimState, NpcDynamics, WORLDSIM, ERA_CONF, makeWorldSimState, NpcStance, REGION_TIDE, eraDuraOf, regionTideOf, calamityNames, calamityFamilyOf, calamityEffectOf, CalamityName, POOL_BASE, worldNum, WONDER_CHANCE, WONDER_NAMES, WONDER_DESCS, WONDER_DURATION, WorldWonderKind, WorldWonder, allWonderKinds, wonderDefOf } from './worldsim-data'
import { pack } from '../../data/registry'
import { ITEMS } from '../../data/items'
import { npcById, getNpcDefs, registerNpcDef, unregisterNpcDef } from '../../data/npcs'
@@ -85,10 +85,108 @@ export class WorldSim {
}
}
// ---- D-0.8 功德因果年首回馈(0.1.37 ----
if (this.w.state.month === 1) {
const fam = this.w.state.family
// karma 年首向中性衰减(0.1.37:衰减率可经 worldNum('karmaDecayRate') 覆写)
const decayRate = worldNum('karmaDecayRate')
if (fam.karma !== 0) {
const decay = Math.round(fam.karma * decayRate * 10) / 10
fam.karma = Math.round((fam.karma - decay) * 10) / 10
if (Math.abs(fam.karma) < 0.1) fam.karma = 0
}
// 因果回馈:高 karma 年首广播福泽
const karmaHigh = worldNum('karmaHighThreshold')
if (fam.karma > karmaHigh && !fam.flag['karmaBlessed-' + this.w.state.year]) {
fam.flag['karmaBlessed-' + this.w.state.year] = true
this.w.log('good', `积善之家必有余庆——功德深厚(${Math.round(fam.karma)}),天地福泽暗佑。`)
}
// 因果回馈:低 karma 年首天谴预警
const karmaLow = worldNum('karmaLowThreshold')
if (fam.karma < karmaLow && !fam.flag['karmaWarned-' + this.w.state.year]) {
fam.flag['karmaWarned-' + this.w.state.year] = true
this.w.log('bad', `因果缠身——功德亏缺(${Math.round(fam.karma)}),灾祸或至。`)
}
}
// ---- D-0.9 世界奇观年首判定(0.1.37 种子派生——零 rng 消耗) ----
if (this.w.state.month === 1) {
// 上一年奇观到期清理
if (s.wonder && s.wonder.duration && s.wonder.duration > 0) {
s.wonder.elapsed = (s.wonder.elapsed ?? 0) + 12
if (s.wonder.elapsed >= s.wonder.duration) {
const wdefEnd = wonderDefOf(s.wonder.kind)
const name = wdefEnd?.name ?? s.wonder.kind
s.newsFeed.push({ year: this.w.state.year, month: 1, src: '天道', text: `${name}消散——天地复常。`, kind: 'annal' })
this.w.log('info', `【天下】${name}消散,天地复常。`)
s.wonder = undefined
}
}
// 年首种子派生判定(不消耗 rng 主序列)
if (!s.wonder) {
let sh = 0
for (let i = 0; i < this.w.state.seed.length; i++) sh = (sh * 31 + this.w.state.seed.charCodeAt(i)) >>> 0
const wonderRoll = ((sh ^ (this.w.state.year * 16777619) ^ (s.npcSuccessions * 2654435761)) >>> 0) % 1000 / 1000
if (wonderRoll < worldNum('wonderChance')) {
// 0.1.37 P5:奇观类型从聚合池选取(内置 + MOD 扩展——零 rng 消耗)
const allKinds = allWonderKinds()
const kindIdx = ((sh + this.w.state.year * 40503) >>> 0) % allKinds.length
const wdef = allKinds[kindIdx]!
const kind = wdef.kind as WorldWonderKind
s.wonder = {
kind,
year: this.w.state.year,
duration: wdef.duration,
elapsed: 0
}
const name = wdef.name
const desc = wdef.desc
s.newsFeed.push({ year: this.w.state.year, month: 1, src: '天机', text: `${name}——${desc}`, kind: 'annal' })
this.w.log('good', `【天下异变】${name}${desc}`)
this.w.emitFx('pulse', `wonder:${kind}`)
// 一次性奇观效果(0.1.37 P5:通过 wonderDefOf 识别扩展奇观的 oneshot 类型)
const wdef2 = wonderDefOf(kind)
if (wdef2?.oneshot === 'bless') {
// 天降祥瑞:灾年消弭
if (s.calamity) {
s.calamity = undefined
s.calamityLeft = 0
this.w.log('good', '祥瑞降世,灾厄消弭——灾云散尽。')
}
// 声望 +5
this.w.state.family.reputation += 5
} else if (wdef2?.oneshot === 'loot') {
// 古遗迹/宝物型奇观:获得随机资源
const loot = ['lingcao', 'lingkuang', 'beastcore', 'lingyu'][((sh + this.w.state.year * 7919) >>> 0) % 4]
const qty = 10 + ((sh + this.w.state.year * 13) >>> 0) % 15
this.w.state.family.inventory[loot] = (this.w.state.family.inventory[loot] ?? 0) + qty
const lootName = { lingcao: '灵草', lingkuang: '灵矿', beastcore: '兽核', lingyu: '灵玉' }[loot] ?? loot
this.w.log('good', `${name}中得${lootName}×${qty}——前世遗珍。`)
}
}
}
}
// ---- 0.1.37 奇观持续效果(月度——通过 wonderDefOf 识别扩展奇观的 effect 类型) ----
if (s.wonder) {
const wdefCont = wonderDefOf(s.wonder.kind)
if (wdefCont?.effect === 'tide_up') {
// 灵气增益:tide 缓升(修炼加成)
s.tide = clamp(s.tide + 0.003, WORLDSIM.tideMin - 0.05, WORLDSIM.tideMax + 0.2)
} else if (wdefCont?.effect === 'tide_down') {
// 灵气衰减:tide 缓降(修行衰减)
s.tide = clamp(s.tide - 0.003, WORLDSIM.tideMin - 0.2, WORLDSIM.tideMax + 0.05)
}
}
// ---- D. 灾年(年签一掷 + 持续渐退;B12) ----
// 剩数递减
if ((s.calamityLeft ?? 0) > 0) s.calamityLeft = (s.calamityLeft ?? 0) - 1
const calamityP = worldNum('calamityChance') * ERA_CONF[s.era ?? 'pingshi'].calamityMult
// 0.1.37 因果调制:karma 高于阈值灾年概率 -15%,低于阈值 +15%(阈值可经 worldNum 覆写)
const kHigh = worldNum('karmaHighThreshold')
const kLow = worldNum('karmaLowThreshold')
const karmaCalamityMod = this.w.state.family.karma > kHigh ? 0.85 : this.w.state.family.karma < kLow ? 1.15 : 1
const calamityP = worldNum('calamityChance') * ERA_CONF[s.era ?? 'pingshi'].calamityMult * karmaCalamityMod
if (this.w.state.month === 1 && rng.chance(calamityP)) {
const cl = rng.pick(calamityNames())
s.calamity = cl
@@ -720,13 +818,24 @@ function assessStance(w: World, id: string, dyn: NpcDynamics): NpcStance {
const prosperity = dyn.prosperity ?? 50
const power = npc?.power ?? 100
const relation = npc?.relation ?? 0
// 0.1.37 因果调制:玩家家族 karma 影响 NPC 姿态倾向(阈值可经 worldNum 覆写)
const karma = w.state.family.karma ?? 0
const kHighS = worldNum('karmaHighThreshold')
const kLowS = worldNum('karmaLowThreshold')
const karmaAllyMod = karma > kHighS ? 2 : karma < kLowS ? -1 : 0
const karmaExpandMod = karma < kLowS ? 2 : karma > kHighS ? -1 : 0
// 硬判据优先
if (prosperity < 30 || power < 45) return 'endure'
if (relation >= 50) return 'ally'
if (era === 'luanshi' && power >= 120) return 'expand'
if (era === 'mofa') return 'endure'
// 软权重:乱世偏扩张、盛世偏守成、平世均衡
const W: Record<NpcStance, number> = { guardian: 3, expand: era === 'luanshi' ? 6 : 2, endure: era === 'mofa' ? 5 : 2, ally: era === 'shengshi' || era === 'pingshi' ? 4 : 1 }
// 软权重:乱世偏扩张、盛世偏守成、平世均衡 + karma 调制
const W: Record<NpcStance, number> = {
guardian: 3,
expand: Math.max(0, (era === 'luanshi' ? 6 : 2) + karmaExpandMod),
endure: era === 'mofa' ? 5 : 2,
ally: Math.max(0, (era === 'shengshi' || era === 'pingshi' ? 4 : 1) + karmaAllyMod)
}
const pick = (Object.keys(W) as NpcStance[]).sort((a, b) => W[b] - W[a])
// 用幂等 rng 抽取(先取最高权)+ 30% 软翻转
const top = pick[0]!