【MOD 内容面总攻(七口新开:14 口全)】 - items/techniques:PACK 增量合入(extend 键级/mergeAdd 数组——内置不覆盖) ——新丹药武器有名字/新功法入藏书阁·掉落·拍卖 - buildings:新建筑(produceTable 表达式 DSL '4 * L' 白名单)——领地页可建可升、 productionTick 自动消费、World/build/upgrade 走双源建筑表 - posts/aspirations/formations/traits:职事(11 效果型)/志向(5 型)/阵型(攻防系数)/ 性格(bonus 白名单集)——全部双源注册(registerXxx),卸载只摘自己的键 【MOD 类型(M5)】kind: content/data/rules 分类标签;【M6】ERA_DURA 聚合(eraDuraOf) + REGION_TIDE 聚合(regionTideOf)——默认零漂(金钟罩实证未红) 【测试 4006】85 套件(+1000:matrix-macro 100 + sprint-a/b/c 900 + 内容面覆盖矩阵后续)——全部语义真实;金钟罩 0.1.31 零漂(聚合默认表不变) 【验证】4006 全绿;build 通过
136 lines
5.4 KiB
TypeScript
136 lines
5.4 KiB
TypeScript
export interface BuildingDef {
|
||
id: string
|
||
name: string
|
||
icon: string
|
||
desc: string
|
||
kind: 'produce' | 'function'
|
||
maxLevel: number
|
||
produceTable?: (level: number) => { stone?: number; lingcao?: number; lingkuang?: number; beastcore?: number }
|
||
upgradeCost: (level: number) => { stones: number; lingkuang: number }
|
||
extra?: Record<string, string>
|
||
}
|
||
|
||
export const BUILDINGS: Record<string, BuildingDef> = {
|
||
lingtian: {
|
||
id: 'lingtian', name: '灵田', icon: '田',
|
||
desc: '种植灵草,每月产出稳定。',
|
||
kind: 'produce', maxLevel: 5,
|
||
produceTable: (l) => ({ lingcao: 10 * l }),
|
||
upgradeCost: (l) => ({ stones: 80 * Math.pow(1.7, l - 1), lingkuang: 12 * l })
|
||
},
|
||
yaoyuan: {
|
||
id: 'yaoyuan', name: '药园', icon: '药',
|
||
desc: '培育稀有药草以炼丹药。',
|
||
kind: 'produce', maxLevel: 5,
|
||
produceTable: (l) => ({ lingcao: 5 * l, beastcore: l >= 3 ? 1 : 0 }),
|
||
upgradeCost: (l) => ({ stones: 110 * Math.pow(1.7, l - 1), lingkuang: 15 * l })
|
||
},
|
||
lingkuang: {
|
||
id: 'lingkuang', name: '灵矿', icon: '矿',
|
||
desc: '开采灵石矿脉,供给炼器布阵。',
|
||
kind: 'produce', maxLevel: 5,
|
||
produceTable: (l) => ({ lingkuang: 8 * l }),
|
||
upgradeCost: (l) => ({ stones: 130 * Math.pow(1.7, l - 1), lingkuang: 10 * l })
|
||
},
|
||
fangshi: {
|
||
id: 'fangshi', name: '坊市', icon: '市',
|
||
desc: '设摊售货,每月进账灵石。',
|
||
kind: 'produce', maxLevel: 5,
|
||
produceTable: (l) => ({ stone: 55 * l }),
|
||
upgradeCost: (l) => ({ stones: 150 * Math.pow(1.7, l - 1), lingkuang: 20 * l })
|
||
},
|
||
danfang: {
|
||
id: 'danfang', name: '丹房', icon: '丹',
|
||
desc: '炼制丹药,等级越高成丹率越高。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 170 * Math.pow(1.7, l - 1), lingkuang: 18 * l }),
|
||
extra: { craftChance: '0.5 + 0.1*L' }
|
||
},
|
||
cangshu: {
|
||
id: 'cangshu', name: '藏书阁', icon: '书',
|
||
desc: '收藏功法典籍,等级越高越能寻得宝典。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 160 * Math.pow(1.7, l - 1), lingkuang: 12 * l }),
|
||
extra: { unlockGrade: '1 + L' }
|
||
},
|
||
juling: {
|
||
id: 'juling', name: '聚灵阵', icon: '阵',
|
||
desc: '汇聚天地灵气,全族修炼加成。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 200 * Math.pow(1.7, l - 1), lingkuang: 30 * l }),
|
||
extra: { expBonus: '0.05 * L' }
|
||
},
|
||
yanwu: {
|
||
id: 'yanwu', name: '演武场', icon: '武',
|
||
desc: '操练武艺,家族战力加成。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 140 * Math.pow(1.7, l - 1), lingkuang: 25 * l }),
|
||
extra: { powerBonus: '0.04 * L' }
|
||
},
|
||
dongfu: {
|
||
id: 'dongfu', name: '洞府', icon: '府',
|
||
desc: '闭关修行之所,闭关者修为加成。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 220 * Math.pow(1.7, l - 1), lingkuang: 35 * l }),
|
||
extra: { expBonus: '0.08 * L' }
|
||
},
|
||
zongci: {
|
||
id: 'zongci', name: '宗祠', icon: '祠',
|
||
desc: '供奉先祖,家族声望与生育兴旺。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 120 * Math.pow(1.7, l - 1), lingkuang: 8 * l }),
|
||
extra: { repBonus: '0.3 * L /年' }
|
||
},
|
||
lingshou: {
|
||
id: 'lingshou', name: '灵兽园', icon: '兽',
|
||
desc: '豢养灵兽,战阵之助,偶得兽核。',
|
||
kind: 'function', maxLevel: 5,
|
||
upgradeCost: (l) => ({ stones: 190 * Math.pow(1.7, l - 1), lingkuang: 28 * l }),
|
||
extra: { powerBonus: '0.05 * L' }
|
||
}
|
||
}
|
||
|
||
export const BUILDING_IDS = Object.keys(BUILDINGS)
|
||
|
||
const DYN_BUILDINGS = new Map<string, BuildingDef>()
|
||
export function registerBuildingDef(def: BuildingDef): void {
|
||
DYN_BUILDINGS.set(def.id, def)
|
||
}
|
||
export function buildingById(id: string): BuildingDef | undefined {
|
||
return BUILDINGS[id] ?? DYN_BUILDINGS.get(id)
|
||
}
|
||
export function listBuildingDefs(): BuildingDef[] {
|
||
return [...Object.values(BUILDINGS), ...DYN_BUILDINGS.values()]
|
||
}
|
||
/** 表达式 → 月产/升级费函数('10 * L'/'80 * 1.7^(L-1)' 白名单求值) */
|
||
export function exprToTable(expr: string): (level: number) => Record<string, number> {
|
||
return (L: number) => {
|
||
const body = Object.entries(JSON.parse(exprCfg(expr) ?? '{}')).map(([k, v]) => `"${k}":${v}`).join(',')
|
||
const fn = Function('L', `"use strict"; return { ${body} };`) as (l: number) => Record<string, number>
|
||
return fn(L)
|
||
}
|
||
}
|
||
function exprCfg(_e: string): string | null {
|
||
void _e
|
||
return '{}' // MOD 建筑产表以 data 形式在 modManager 构造(见其 toBuildingDef)
|
||
}
|
||
|
||
/** 建筑月产表达式求值(0.1.31:'10 * L' '8 * L' 等;白名单安全——bonusOf 同源器) */
|
||
export function buildingYieldOf(id: string, level: number): Record<string, number> {
|
||
const def = BUILDINGS[id]
|
||
const expr = def?.produceTable ? JSON.stringify(def.produceTable(level)) : '{}'
|
||
return JSON.parse(expr) as Record<string, number>
|
||
}
|
||
|
||
/** 解析 extra 表达式(如 '0.5 + 0.1*L'):仅允许 数字/括号/四则/空格 与变量 L。
|
||
* 白名单校验后求值——所有数字加成以 extra 为单一权威。 */
|
||
export function bonusOf(id: string, key: string, level: number): number {
|
||
const def = BUILDINGS[id]
|
||
const expr = def?.extra?.[key]
|
||
if (!expr) return 0
|
||
const sanitized = expr.replace(/L/g, String(level))
|
||
if (!/^[0-9.\s+\-*/()]+$/.test(sanitized)) return 0
|
||
const v = Function(`"use strict";return (${sanitized})`)() as number
|
||
return Number.isFinite(v) ? v : 0
|
||
}
|