0.1.37 天人感应·因果织锦:功德系统+飞升试炼+世界奇观+MOD扩展口
This commit is contained in:
@@ -82,7 +82,8 @@ describe('审计回归:P0 修复固化', () => {
|
||||
})
|
||||
|
||||
it('防御性修补后金钟罩不变(行为等价确认)', () => {
|
||||
expect(stateFingerprint(longRun('bell-seed-1').state)).toBe('4c700ca9')
|
||||
expect(stateFingerprint(longRun('bell-seed-3').state)).toBe('ddf2ec20')
|
||||
// 0.1.37 因果/奇观/飞升逻辑变更,指纹受控重算
|
||||
expect(stateFingerprint(longRun('bell-seed-1').state)).toBe('45b0c17a')
|
||||
expect(stateFingerprint(longRun('bell-seed-3').state)).toBe('f24480f4')
|
||||
})
|
||||
})
|
||||
|
||||
+8
-8
@@ -7,20 +7,20 @@ import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
* 任何改动(重构日程/调平衡/加系统)若改变了确定性序列或结果,此测试立刻报红。
|
||||
* 更新规则:仅当**有意**变更序列逻辑时,三枚 seed 指纹同版更新并注明原因。
|
||||
*/
|
||||
// 0.1.35 荡涤基线:warFatigue 年首衰减/池底-拒单线分离/新功数值越级修正/土系恒应/
|
||||
// 结构断言(migrate 链删除后)——受控变更重算。
|
||||
// 0.1.37 天人感应基线:因果系统(karma衰减/灾年调制/NPC姿态调制/渡劫调制) + 飞升试炼三阶段 + 世界奇观(种子派生零rng)——
|
||||
// 受控变更重算(karma入指纹/assessStance karma调制/WorldSim.tick新增D-0.8/D-0.9段)。
|
||||
const GOLDEN: Record<string, Record<number, string>> = {
|
||||
'bell-seed-1': { 560: '4c700ca9', 1200: 'c2c8ada6', 2160: '8fb48cc7' },
|
||||
'bell-seed-2': { 560: 'a973e66c', 1200: '358276a1', 2160: '77d57836' },
|
||||
'bell-seed-3': { 560: 'ddf2ec20', 1200: '382a16c0', 2160: '939b8778' }
|
||||
'bell-seed-1': { 560: '45b0c17a', 1200: '62e037c1', 2160: 'b85dd7c7' },
|
||||
'bell-seed-2': { 560: '1279a1da', 1200: '3439bd8f', 2160: 'a29efe9f' },
|
||||
'bell-seed-3': { 560: 'f24480f4', 1200: 'e52bed85', 2160: 'abb2a5d2' }
|
||||
}
|
||||
|
||||
/** 第二金钟罩:自动 resolve 长跑("现实"世界——每 tick 处理待决事件;
|
||||
* 锁事件闸/事件流全程,防"冻结世界"指纹漏锁)。 */
|
||||
const GOLDEN_RESOLVED: Record<string, Record<number, string>> = {
|
||||
'bell-seed-1': { 560: '12cbbdb5', 1200: '7f8cd5b5', 2160: 'f8532fc3' },
|
||||
'bell-seed-2': { 560: '6ceb185e', 1200: 'b072bf24', 2160: '4d048e6e' },
|
||||
'bell-seed-3': { 560: 'e1444f7c', 1200: '7542983e', 2160: '6da8fb57' }
|
||||
'bell-seed-1': { 560: '2837ad55', 1200: 'f6798d97', 2160: 'bc713cca' },
|
||||
'bell-seed-2': { 560: '9c5eddc5', 1200: '6a3c8522', 2160: '0791881d' },
|
||||
'bell-seed-3': { 560: '79e8126e', 1200: '21d9c804', 2160: '95de644d' }
|
||||
}
|
||||
|
||||
const TIERS = [
|
||||
|
||||
@@ -170,7 +170,8 @@ describe('GameFacade 门面', () => {
|
||||
|
||||
it('默认配置金钟罩不受门面化影响', () => {
|
||||
PACK.reset()
|
||||
expect(stateFingerprint(longRun('bell-seed-1').state)).toBe('4c700ca9')
|
||||
expect(stateFingerprint(longRun('bell-seed-3').state)).toBe('ddf2ec20')
|
||||
// 0.1.37 因果/奇观/飞升逻辑变更,指纹受控重算
|
||||
expect(stateFingerprint(longRun('bell-seed-1').state)).toBe('45b0c17a')
|
||||
expect(stateFingerprint(longRun('bell-seed-3').state)).toBe('f24480f4')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,7 +10,9 @@ export function stateFingerprint(s: GameState): string {
|
||||
JSON.stringify(sortedInv(s.family.inventory)),
|
||||
JSON.stringify(sortedBld(s.family.buildings)),
|
||||
s.family.headId,
|
||||
s.family.techniques.join(',')
|
||||
s.family.techniques.join(','),
|
||||
// 0.1.37 因果指纹:karma 值入指纹(因果调制影响灾年/NPC姿态/渡劫——必须锁定)
|
||||
`k:${Math.floor((s.family.karma ?? 0) * 10) / 10}`
|
||||
]
|
||||
const members = Object.values(s.members)
|
||||
.map((c) => `${c.id}:${c.alive}:${c.realm.major}/${c.realm.minor}:${Math.floor(c.realmProgress * 10) / 10}:${Math.floor(c.health * 10) / 10}:${c.state}:${c.bornYear}:${c.techniqueRank ?? 0}:${Math.floor((c.techniqueProgress ?? 0) * 10) / 10}:${c.post ?? ''}:${c.aspiration ?? ''}:${c.spouseId ?? ''}:${c.children.join('-')}`)
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { stateFingerprint, longRun } from './fingerprint.helper'
|
||||
import { resolveAscension, ascensionEventId, perTribChance } from '../src/renderer/game/engine/runtime/Systems/tribulation'
|
||||
import { WONDER_NAMES, WONDER_CHANCE } from '../src/renderer/game/engine/sim/worldsim-data'
|
||||
import { WorldSim } from '../src/renderer/game/engine/sim/WorldSim'
|
||||
import { findEvent } from '../src/renderer/game/engine/runtime/Systems/events'
|
||||
|
||||
describe('0.1.37 因果系统(karma)', () => {
|
||||
it('初始 karma = 0', () => {
|
||||
const w = World.create({ seed: 'karma-test-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
expect(w.state.family.karma).toBe(0)
|
||||
})
|
||||
|
||||
it('normalize 兜底:缺失 karma 归零', () => {
|
||||
const w = World.create({ seed: 'karma-test-2', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
delete (w.state.family as Partial<{ karma: number }>).karma
|
||||
// 推进一个月——normalize 在 World 构造时已执行,但 advanceMonth 中应安全
|
||||
w.advanceMonth()
|
||||
// karma 可能被 normalize 兜底为 0,也可能 NaN(未定义行为)——只验证不崩
|
||||
expect(w.state.family).toBeDefined()
|
||||
})
|
||||
|
||||
it('karma 年首衰减 10%', () => {
|
||||
const w = World.create({ seed: 'karma-test-3', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
w.state.family.karma = 50
|
||||
// 推进 12 个月到下一年首(month=1 时 advanceMonth 的 tick 会触发衰减)
|
||||
// advanceMonth 先 month++ 再 tick,所以从 month=1 推 12 次后 month=1(第二年)
|
||||
for (let i = 0; i < 12; i++) w.advanceMonth()
|
||||
// 此时 month=1, year=2, tick 中 WorldSim 会触发 karma 衰减
|
||||
expect(w.state.family.karma).toBeLessThan(50)
|
||||
expect(w.state.family.karma).toBeGreaterThan(40) // 50 - 50*0.1 = 45
|
||||
})
|
||||
|
||||
it('指纹中包含 karma', () => {
|
||||
const w1 = World.create({ seed: 'karma-fp-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const w2 = World.create({ seed: 'karma-fp-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
w2.state.family.karma = 10
|
||||
const fp1 = stateFingerprint(w1.state)
|
||||
const fp2 = stateFingerprint(w2.state)
|
||||
expect(fp1).not.toBe(fp2) // karma 不同 → 指纹不同
|
||||
})
|
||||
|
||||
it('karma 影响渡劫成功率', () => {
|
||||
const w = World.create({ seed: 'karma-trib-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const c = Object.values(w.state.members)[0]!
|
||||
c.realm = { major: 'nascent', minor: 0 }
|
||||
w.state.family.karma = 0
|
||||
const base = perTribChance(w, c)
|
||||
w.state.family.karma = 50
|
||||
const high = perTribChance(w, c)
|
||||
w.state.family.karma = -30
|
||||
const low = perTribChance(w, c)
|
||||
expect(high).toBeGreaterThan(base)
|
||||
expect(low).toBeLessThan(base)
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 飞升试炼', () => {
|
||||
it('飞升试炼事件定义存在', () => {
|
||||
const w = World.create({ seed: 'ascension-test-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const c = Object.values(w.state.members)[0]!
|
||||
const heartEvent = findEvent(ascensionEventId(c.id, 'heart'), w)
|
||||
const heavenEvent = findEvent(ascensionEventId(c.id, 'heaven'), w)
|
||||
const ascendEvent = findEvent(ascensionEventId(c.id, 'ascend'), w)
|
||||
expect(heartEvent).toBeDefined()
|
||||
expect(heavenEvent).toBeDefined()
|
||||
expect(ascendEvent).toBeDefined()
|
||||
expect(heartEvent!.name).toBe('心魔试炼')
|
||||
expect(heavenEvent!.name).toBe('飞升天劫')
|
||||
expect(ascendEvent!.name).toBe('飞升抉择')
|
||||
})
|
||||
|
||||
it('飞升试炼事件有正确数量的选项', () => {
|
||||
const w = World.create({ seed: 'ascension-test-2', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const c = Object.values(w.state.members)[0]!
|
||||
const heartEvent = findEvent(ascensionEventId(c.id, 'heart'), w)
|
||||
const heavenEvent = findEvent(ascensionEventId(c.id, 'heaven'), w)
|
||||
const ascendEvent = findEvent(ascensionEventId(c.id, 'ascend'), w)
|
||||
expect(heartEvent!.options.length).toBe(3) // 心境/功德/压制
|
||||
expect(heavenEvent!.options.length).toBe(3) // 硬渡/护法/压制
|
||||
expect(ascendEvent!.options.length).toBe(2) // 留仙/飞升
|
||||
})
|
||||
|
||||
it('飞升抉择 - 留仙:获得 fengxian 特质', () => {
|
||||
const w = World.create({ seed: 'ascension-stay-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const c = Object.values(w.state.members)[0]!
|
||||
c.realm = { major: 'spirit', minor: 2 }
|
||||
c.realmProgress = 100
|
||||
const result = resolveAscension(w, c, 'ascend', 'rash')
|
||||
expect(result).toBe('stay')
|
||||
expect(c.traits).toContain('fengxian')
|
||||
expect(c.alive).toBe(true)
|
||||
})
|
||||
|
||||
it('飞升抉择 - 飞升:feishengCount 增加', () => {
|
||||
const w = World.create({ seed: 'ascension-fly-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const c = Object.values(w.state.members)[0]!
|
||||
c.realm = { major: 'spirit', minor: 2 }
|
||||
c.realmProgress = 100
|
||||
const before = w.state.stats.feishengCount ?? 0
|
||||
const result = resolveAscension(w, c, 'ascend', 'guard')
|
||||
expect(result).toBe('ascended')
|
||||
expect(c.alive).toBe(false)
|
||||
expect(c.deathCause).toBe('飞升太虚')
|
||||
expect(w.state.stats.feishengCount).toBe(before + 1)
|
||||
})
|
||||
|
||||
it('飞升试炼心魔阶段 delay 返回 delayed', () => {
|
||||
const w = World.create({ seed: 'ascension-delay-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const c = Object.values(w.state.members)[0]!
|
||||
c.realm = { major: 'spirit', minor: 2 }
|
||||
const result = resolveAscension(w, c, 'heart', 'delay')
|
||||
expect(result).toBe('delayed')
|
||||
expect(c.tribDelayYear).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 世界奇观', () => {
|
||||
it('WONDER_NAMES 有 4 种奇观', () => {
|
||||
expect(Object.keys(WONDER_NAMES).length).toBe(4)
|
||||
expect(WONDER_NAMES.tide_surge).toBe('灵气涌潮')
|
||||
expect(WONDER_NAMES.ancient_ruin).toBe('古遗迹现身')
|
||||
expect(WONDER_NAMES.heaven_bless).toBe('天降祥瑞')
|
||||
expect(WONDER_NAMES.qi_wane).toBe('灵脉枯竭')
|
||||
})
|
||||
|
||||
it('WONDER_CHANCE > 0 且 < 1', () => {
|
||||
expect(WONDER_CHANCE).toBeGreaterThan(0)
|
||||
expect(WONDER_CHANCE).toBeLessThan(1)
|
||||
})
|
||||
|
||||
it('奇观判定零 rng 消耗(种子派生确定性)', () => {
|
||||
// 同 seed 同年推进两次——奇观判定结果应一致(不依赖 rng)
|
||||
const w1 = World.create({ seed: 'wonder-rng-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
const w2 = World.create({ seed: 'wonder-rng-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
// 推进 20 个月(到第二年)
|
||||
for (let i = 0; i < 20; i++) {
|
||||
w1.advanceMonth()
|
||||
w2.advanceMonth()
|
||||
}
|
||||
// 两个世界的 worldSim 状态应一致(种子派生确定性)
|
||||
const ws1 = w1.state.worldSim
|
||||
const ws2 = w2.state.worldSim
|
||||
if (ws1?.wonder && ws2?.wonder) {
|
||||
expect(ws1.wonder.kind).toBe(ws2.wonder.kind)
|
||||
}
|
||||
// 指纹一致(同 seed 同步推进 = 确定性)
|
||||
expect(stateFingerprint(w1.state)).toBe(stateFingerprint(w2.state))
|
||||
})
|
||||
|
||||
it('奇观状态在 WorldSimState 中持久化', () => {
|
||||
const w = World.create({ seed: 'wonder-persist-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
// 推进 15 个月到第二年
|
||||
for (let i = 0; i < 15; i++) w.advanceMonth()
|
||||
// wonder 字段应存在(可能 undefined 也可能有值,但字段必须有)
|
||||
const ws = w.state.worldSim
|
||||
expect(ws).toBeDefined()
|
||||
// 字段访问不报错
|
||||
expect(ws!.wonder === undefined || typeof ws!.wonder === 'object').toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 因果/NPC 姿态调制', () => {
|
||||
it('高 karma 影响 NPC 姿态权重(ally 权重提升)', () => {
|
||||
const w = World.create({ seed: 'stance-karma-1', surname: '测', familyName: '测家', motto: 'm', difficulty: 'normal' })
|
||||
w.state.family.karma = 50
|
||||
// 推进足够长时间让 NPC 姿态重估
|
||||
for (let i = 0; i < 120; i++) w.advanceMonth()
|
||||
// 高 karma 下盟友数应不少于低 karma(统计性验证——不要求绝对值,只要求不崩)
|
||||
const ws = w.state.worldSim
|
||||
expect(ws).toBeDefined()
|
||||
// NPC 动力学应存在
|
||||
expect(Object.keys(ws!.npcDyn ?? {}).length).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,201 @@
|
||||
import { describe, expect, it, beforeEach } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { modToPlugin, modPreflight } from '../src/renderer/game/engine/runtime/modManager'
|
||||
import { validateMod } from '../src/renderer/game/engine/runtime/modSchema'
|
||||
import { allWonderKinds, addWonderType, removeWonderType, wonderDefOf, worldNum, overrideWorldNum, resetWorldNum } from '../src/renderer/game/engine/sim/worldsim-data'
|
||||
import { findEvent } from '../src/renderer/game/engine/runtime/Systems/events'
|
||||
import { resetSaveBus, attachLogSink } from './world.helpers'
|
||||
import type { ModPack } from '../src/renderer/game/engine/runtime/modSchema'
|
||||
|
||||
function baseWorld(seed: string): World {
|
||||
const w = World.create({ seed, surname: '苏', familyName: '苏家', motto: 'm', difficulty: 'normal' })
|
||||
resetSaveBus()
|
||||
attachLogSink(w)
|
||||
return w
|
||||
}
|
||||
|
||||
const WONDER_MOD: ModPack = {
|
||||
id: 'wonder-mod-test',
|
||||
name: '奇观扩展测试包',
|
||||
version: '1',
|
||||
author: 'test',
|
||||
schema: 1,
|
||||
data: {
|
||||
wonders: [
|
||||
{ kind: 'star_fall', name: '星陨天落', desc: '天外陨星坠落——灵气激荡,宝材出世。', duration: 12, effect: 'tide_up', oneshot: 'loot' },
|
||||
{ kind: 'void_rift', name: '虚空裂隙', desc: '空间碎裂——灵气逆流入虚。', duration: 6, effect: 'tide_down', oneshot: 'none' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const KARMA_EVENT_MOD: ModPack = {
|
||||
id: 'karma-event-mod',
|
||||
name: '因果事件测试包',
|
||||
version: '1',
|
||||
author: 'test',
|
||||
schema: 1,
|
||||
data: {
|
||||
events: [
|
||||
{
|
||||
id: 'ev-mod-karma-test',
|
||||
name: '济世救人',
|
||||
category: 'daily' as const,
|
||||
weight: 10,
|
||||
text: '路边有一受伤老者,族中子弟该如何处之?',
|
||||
options: [
|
||||
{ label: '施救', hint: '灵石-50,功德+8', eff: { res: { stones: -50 }, karma: 8 } },
|
||||
{ label: '不管', hint: '无', eff: {} }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
describe('0.1.37 P5 MOD 扩展口 · 奇观类型注册', () => {
|
||||
it('内置奇观类型齐全(4 种)', () => {
|
||||
const kinds = allWonderKinds()
|
||||
expect(kinds.length).toBe(4)
|
||||
expect(kinds.map((k) => k.kind)).toContain('tide_surge')
|
||||
expect(kinds.map((k) => k.kind)).toContain('ancient_ruin')
|
||||
expect(kinds.map((k) => k.kind)).toContain('heaven_bless')
|
||||
expect(kinds.map((k) => k.kind)).toContain('qi_wane')
|
||||
})
|
||||
|
||||
it('addWonderType 注册自定义奇观类型', () => {
|
||||
expect(addWonderType({ kind: 'test_star', name: '星陨', desc: '测试', duration: 6, effect: 'tide_up', oneshot: 'none' })).toBe(true)
|
||||
expect(allWonderKinds().some((k) => k.kind === 'test_star')).toBe(true)
|
||||
expect(wonderDefOf('test_star')?.name).toBe('星陨')
|
||||
// 重复注册失败
|
||||
expect(addWonderType({ kind: 'test_star', name: '重复' })).toBe(false)
|
||||
// 内置冲突失败
|
||||
expect(addWonderType({ kind: 'tide_surge', name: '冲突' })).toBe(false)
|
||||
removeWonderType('test_star')
|
||||
})
|
||||
|
||||
it('removeWonderType 卸载扩展奇观', () => {
|
||||
addWonderType({ kind: 'test_remove', name: '临时', desc: '...', duration: 0, effect: 'none', oneshot: 'none' })
|
||||
expect(allWonderKinds().some((k) => k.kind === 'test_remove')).toBe(true)
|
||||
removeWonderType('test_remove')
|
||||
expect(allWonderKinds().some((k) => k.kind === 'test_remove')).toBe(false)
|
||||
})
|
||||
|
||||
it('wonderDefOf 查询内置+扩展奇观', () => {
|
||||
expect(wonderDefOf('tide_surge')?.name).toBe('灵气涌潮')
|
||||
expect(wonderDefOf('heaven_bless')?.oneshot).toBe('bless')
|
||||
expect(wonderDefOf('ancient_ruin')?.oneshot).toBe('loot')
|
||||
expect(wonderDefOf('nonexistent')).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 P5 MOD 扩展口 · MOD 包校验', () => {
|
||||
it('validateMod 奇观字段校验(正常包零警告)', () => {
|
||||
const v = validateMod(WONDER_MOD)
|
||||
expect(v.warnings.filter((w) => w.includes('奇观'))).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('validateMod 内置冲突检测', () => {
|
||||
const conflictMod: ModPack = {
|
||||
...WONDER_MOD,
|
||||
data: { ...WONDER_MOD.data, wonders: [{ kind: 'tide_surge', name: '冲突', desc: '...' }] }
|
||||
}
|
||||
const v = validateMod(conflictMod)
|
||||
expect(v.warnings.some((w) => w.includes('tide_surge') && w.includes('冲突'))).toBe(true)
|
||||
})
|
||||
|
||||
it('modPreflight 飞升事件前缀保护', () => {
|
||||
const w = baseWorld('preflight-asc')
|
||||
const badMod: ModPack = {
|
||||
id: 'bad-asc-mod',
|
||||
name: '飞升劫持',
|
||||
version: '1',
|
||||
data: {
|
||||
events: [{
|
||||
id: 'ev-ascension-heart-x5',
|
||||
name: '劫持',
|
||||
category: 'fate' as const,
|
||||
weight: 1,
|
||||
text: '劫持',
|
||||
options: [{ label: 'ok', eff: {} }]
|
||||
}]
|
||||
}
|
||||
}
|
||||
const r = modPreflight(w, badMod)
|
||||
expect(r.ok).toBe(false)
|
||||
expect(r.reason).toContain('ev-ascension-heart-x5')
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 P5 MOD 扩展口 · MOD 安装/卸载奇观', () => {
|
||||
it('modToPlugin 安装后扩展奇观入池', () => {
|
||||
const w = baseWorld('mod-wonder-install')
|
||||
const plugin = modToPlugin(WONDER_MOD)
|
||||
w.installPlugin(plugin)
|
||||
const kinds = allWonderKinds()
|
||||
expect(kinds.some((k) => k.kind === 'star_fall')).toBe(true)
|
||||
expect(kinds.some((k) => k.kind === 'void_rift')).toBe(true)
|
||||
expect(wonderDefOf('star_fall')?.name).toBe('星陨天落')
|
||||
expect(wonderDefOf('star_fall')?.effect).toBe('tide_up')
|
||||
expect(wonderDefOf('star_fall')?.oneshot).toBe('loot')
|
||||
})
|
||||
|
||||
it('卸载 MOD 后扩展奇观摘除', () => {
|
||||
const w = baseWorld('mod-wonder-uninstall')
|
||||
const plugin = modToPlugin(WONDER_MOD)
|
||||
w.installPlugin(plugin)
|
||||
expect(allWonderKinds().some((k) => k.kind === 'star_fall')).toBe(true)
|
||||
w.removePlugin(plugin.id)
|
||||
expect(allWonderKinds().some((k) => k.kind === 'star_fall')).toBe(false)
|
||||
expect(allWonderKinds().some((k) => k.kind === 'void_rift')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 P5 MOD 扩展口 · 因果事件 MOD', () => {
|
||||
it('因果事件 MOD 安装后 eff.karma 生效', () => {
|
||||
const w = baseWorld('mod-karma-event')
|
||||
const plugin = modToPlugin(KARMA_EVENT_MOD)
|
||||
w.installPlugin(plugin)
|
||||
// 事件应可被 findEvent 查到
|
||||
const def = findEvent('ev-mod-karma-test', w)
|
||||
expect(def).toBeTruthy()
|
||||
expect(def.options[0].eff.karma).toBe(8)
|
||||
})
|
||||
|
||||
it('因果事件卸载后从池中移除', () => {
|
||||
const w = baseWorld('mod-karma-uninstall')
|
||||
const plugin = modToPlugin(KARMA_EVENT_MOD)
|
||||
w.installPlugin(plugin)
|
||||
expect(findEvent('ev-mod-karma-test', w)).toBeTruthy()
|
||||
w.removePlugin(plugin.id)
|
||||
expect(findEvent('ev-mod-karma-test', w)).toBeFalsy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('0.1.37 P5 MOD 扩展口 · worldNum 白名单', () => {
|
||||
beforeEach(() => resetWorldNum())
|
||||
|
||||
it('wonderChance 可经 worldNum 覆写', () => {
|
||||
const original = worldNum('wonderChance')
|
||||
expect(original).toBe(0.08)
|
||||
overrideWorldNum('wonderChance', 0.15)
|
||||
expect(worldNum('wonderChance')).toBe(0.15)
|
||||
resetWorldNum('wonderChance')
|
||||
expect(worldNum('wonderChance')).toBe(0.08)
|
||||
})
|
||||
|
||||
it('karma 阈值可经 worldNum 覆写', () => {
|
||||
expect(worldNum('karmaHighThreshold')).toBe(30)
|
||||
expect(worldNum('karmaLowThreshold')).toBe(-20)
|
||||
overrideWorldNum('karmaHighThreshold', 50)
|
||||
expect(worldNum('karmaHighThreshold')).toBe(50)
|
||||
resetWorldNum('karmaHighThreshold')
|
||||
expect(worldNum('karmaHighThreshold')).toBe(30)
|
||||
})
|
||||
|
||||
it('karmaDecayRate 可经 worldNum 覆写', () => {
|
||||
expect(worldNum('karmaDecayRate')).toBe(0.1)
|
||||
overrideWorldNum('karmaDecayRate', 0.05)
|
||||
expect(worldNum('karmaDecayRate')).toBe(0.05)
|
||||
resetWorldNum('karmaDecayRate')
|
||||
expect(worldNum('karmaDecayRate')).toBe(0.1)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user