feat(0.1.16-P1): 资源闭环引擎(修为耗草/炼丹概率化/铸器/灵脉收益/NPC战力/灾变落效)+ C13C14
【A 经济闭环】 - 修为经济化:练气以上修行者月耗灵草(闭关2普通1),无草速修0.6~1.0衰减+缺草年告警 - 炼丹等级化:bonusOf 表达式引擎(白名单安全求值),craftChance 转正;丹方单源 PILL_RECIPES(聚气L1/凝元L2/破境L3)+ 失败折半退料 - 炼器筑宝:FORGE_RECIPES(法器/灵器/法宝,灵矿+兽核+灵石) - 秘境灵脉:secretQiOf→rollWarbooty 收益门槛(0.5~1.3折算);掉落按秘境 techGrades 过滤 - NPC 实力参战:raid 强度/风险随 npc.power 浮动(0.5~1.8) - 灾年落效:疫病/兽潮一次性袭击 + CALAMITY_FAMILY 月度减产乘子 【C 治理】 - C13 破境丹渡劫修正:大境界时药力→tribBoost 加成(+12%)入渡劫事件,不再跳过三选 - C14 存储防线:loadState 补 migrate;MigrationError(TOO_NEW/未知版本)提示升级 【UI 半批】 - 坊市新增 定制tab(丹方/铸器);ChroniclePanel 手写史书输入条;MemberModal 册立家主钮 - 年报摘要(要闻5条+辞世讣告);EventModal 选项收益预览 - 结盟引擎:setAlliance(relation≥40)/盟友岁差不降/年利15灵石
This commit is contained in:
@@ -95,3 +95,15 @@ export const BUILDING_IDS = Object.keys(BUILDINGS)
|
||||
export function buildingById(id: string): BuildingDef {
|
||||
return BUILDINGS[id]
|
||||
}
|
||||
|
||||
/** 解析 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
|
||||
}
|
||||
|
||||
@@ -41,3 +41,41 @@ export interface SimpleTradeItem {
|
||||
desc: string
|
||||
count: number
|
||||
}
|
||||
|
||||
/** 丹方:丹房等级门槛 + 材料 + 灵石;唯一权威(craftPill 引用)。 */
|
||||
export interface PillRecipe {
|
||||
output: string
|
||||
name: string
|
||||
danfangLevel: number
|
||||
stones: number
|
||||
lingcao: number
|
||||
beastcore: number
|
||||
desc: string
|
||||
}
|
||||
export const PILL_RECIPES: PillRecipe[] = [
|
||||
{ output: 'pill-qiyuan', name: '聚气丹', danfangLevel: 1, stones: 20, lingcao: 15, beastcore: 0, desc: '炼气期修士服之,一月修为大增。' },
|
||||
{ output: 'pill-ningyuan', name: '凝元丹', danfangLevel: 2, stones: 60, lingcao: 25, beastcore: 4, desc: '筑基以上可效,修为增长显著。' },
|
||||
{ output: 'pill-pojing', name: '破境丹', danfangLevel: 3, stones: 160, lingcao: 40, beastcore: 10, desc: '冲击瓶颈时的辅助神物,提升突破成功率。' }
|
||||
]
|
||||
|
||||
/** 铸器配方:灵矿+兽核+灵石 → 兵刃;无建筑限制(自建工坊念头,数值即门槛)。 */
|
||||
export interface ForgeRecipe {
|
||||
output: string
|
||||
name: string
|
||||
stones: number
|
||||
lingkuang: number
|
||||
beastcore: number
|
||||
desc: string
|
||||
}
|
||||
export const FORGE_RECIPES: ForgeRecipe[] = [
|
||||
{ output: 'weapon-qi', name: '法器', stones: 300, lingkuang: 8, beastcore: 2, desc: '蕴灵之器,可引动灵力。' },
|
||||
{ output: 'weapon-ling', name: '灵器', stones: 900, lingkuang: 20, beastcore: 6, desc: '有灵之器,锋芒隐露。' },
|
||||
{ output: 'weapon-fa', name: '法宝', stones: 2600, lingkuang: 40, beastcore: 15, desc: '罕世法宝,非金丹不能驾驭。' }
|
||||
]
|
||||
|
||||
export function pillRecipeByOutput(id: string): PillRecipe | undefined {
|
||||
return PILL_RECIPES.find((r) => r.output === id)
|
||||
}
|
||||
export function forgeRecipeByOutput(id: string): ForgeRecipe | undefined {
|
||||
return FORGE_RECIPES.find((r) => r.output === id)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ export interface LootDef {
|
||||
artifactChance: number
|
||||
techniqueChance: number
|
||||
beastcoreChance?: number
|
||||
/** 掉功法品阶上限(按秘境难度设定,防低阶秘境出四阶仙典) */
|
||||
techGrades?: number[]
|
||||
}
|
||||
|
||||
export interface MissionDef {
|
||||
@@ -60,7 +62,7 @@ export const MISSIONS: MissionDef[] = [
|
||||
{ kind: 'combat', months: 2, title: '遭遇袭击', enemyId: 'e-tiebei' },
|
||||
{ kind: 'resource', months: 2, title: '寻获残洞', loot: { resources: { lingcao: [30, 80], beastcore: [1, 3] }, artifactChance: 0.05, techniqueChance: 0.03 } }
|
||||
],
|
||||
completionLoot: { resources: { lingcao: [20, 60], lingkuang: [5, 15] }, artifactChance: 0.08, techniqueChance: 0.03 }
|
||||
completionLoot: { resources: { lingcao: [20, 60], lingkuang: [5, 15] }, artifactChance: 0.08, techniqueChance: 0.03, techGrades: [1, 2] }
|
||||
},
|
||||
{
|
||||
id: 'm-xuangu', name: '玄冰谷', region: '北境寒渊', icon: '冰',
|
||||
@@ -71,7 +73,7 @@ export const MISSIONS: MissionDef[] = [
|
||||
{ kind: 'combat', months: 2, title: '泉主现身', enemyId: 'e-huiyuan' },
|
||||
{ kind: 'boss', months: 2, title: '冰潭之下', enemyId: 'e-baiqi' }
|
||||
],
|
||||
completionLoot: { resources: { lingkuang: [30, 70], beastcore: [2, 5] }, artifactChance: 0.15, techniqueChance: 0.06 }
|
||||
completionLoot: { resources: { lingkuang: [30, 70], beastcore: [2, 5] }, artifactChance: 0.15, techniqueChance: 0.06, techGrades: [2, 3] }
|
||||
},
|
||||
{
|
||||
id: 'm-guzhan', name: '古战阵', region: '南陵荒原', icon: '战',
|
||||
@@ -83,7 +85,7 @@ export const MISSIONS: MissionDef[] = [
|
||||
{ kind: 'combat', months: 2, title: '守阵铁骑', enemyId: 'e-huanhan' },
|
||||
{ kind: 'resource', months: 3, title: '挖开枯井', loot: { resources: { lingkuang: [40, 90], beastcore: [2, 6] }, artifactChance: 0.2, techniqueChance: 0.08 } }
|
||||
],
|
||||
completionLoot: { resources: { lingkuang: [40, 90], beastcore: [2, 8] }, artifactChance: 0.22, techniqueChance: 0.1 }
|
||||
completionLoot: { resources: { lingkuang: [40, 90], beastcore: [2, 8] }, artifactChance: 0.22, techniqueChance: 0.1, techGrades: [2, 3] }
|
||||
},
|
||||
{
|
||||
id: 'm-lingshan', name: '灵鹫山', region: '东海之滨', icon: '鹫',
|
||||
|
||||
Reference in New Issue
Block a user