Growth(养成)
Growth 的当前纵切片提供等级读取、强化、素材数量和独立养成页。它只实现已登记的等级与强化范围,不把觉醒、装备、技能强化或 Battle 数值联动视为已经完成。
契约版本为 growth@1,源码位于 src/core/growth/。
接口
| 名称 | 类型 | policy | 用途 |
|---|---|---|---|
growth:stats | 服务 | trusted | 读取目标当前等级、上限与属性,执行一次强化 |
growth:items | 服务 | trusted | 查询素材余额、列出持有素材、授予素材 |
growth:resolve-cost | 机制插槽 | trusted | 求得到达下一级的实际消耗 |
growth:resolve-cap | 机制插槽 | trusted | 求目标当前等级上限 |
growth:on-enhance | 通知 | — | 强化成功后广播实际变化 |
growth:on-awaken | 通知 | — | 当前只保留契约声明,不发出觉醒通知 |
growth:formula@1 | 实现位(single) | public | 计算指定等级的属性;内置 table,卸载回落 |
公共 registry 为 growth:profiles、growth:tables、growth:items。素材 registry 与库存服务同名,只提供一个入口;装载器的分层授权与库存操作分别按既有规则执行。
数据与旗标
养成目标、属性表与素材分别写入 data/growth/profiles/、data/growth/tables/、data/growth/items/ 下的命名空间目录。条目 ID 由路径决定,不在正文重复写 ID。
interface GrowthProfile {
table: string // growth:tables 的条目 ID
level: string // 当前等级旗标
formula?: string // 可选的公式实现名
}
interface GrowthTable {
levels: Record<string, {
stats: Record<string, number>
cost?: { item: string; count: number }[]
}>
}
interface GrowthItem {
name: IrText
description?: IrText
count: string // 素材数量旗标
}等级键是不带前导零的正整数,从 1 起连续。属性名使用小写本地 ID,值为有限数;框架不预设属性集。一级不写消耗,二级起必须显式给出非空消耗。漏填消耗不会被当成免费强化。
进度字段没有隐含的资源路径或内存副本。等级旗标未写时读作 1,素材数量旗标未写时读作 0;已有值必须分别是正整数和非负安全整数。旗标仍服从 state:flags 的名称、保留命名空间与已装载所有者约束,并由既有 Save 流程按归属保存。
读取与强化
growth:stats.read(target) 返回:
{
target: string
level: number
cap: number
stats: Record<string, number>
next?: { level: number; cost: { item: string; count: number }[] }
}growth:stats.enhance(target) 在每次调用时重新求上限、公式与下一级消耗,不沿用旧页面缓存。它先检查全部素材余额、相关旗标的数值与所有权,再算出新等级的属性和后续消耗;全部通过后才逐项扣除素材并写入新等级。等级旗标和本次使用的素材数量旗标不得复用同一个字段。
失败不写旗标,也不发通知。成功后广播 { target, previous, level, stats, cost },其中 previous 是原等级,stats 是强化后的属性,cost 是实际扣除的消耗。
可换公式
growth:formula@1 条目提供:
calculate({ target, level, table }): Record<string, number>内置 table 只返回 table.levels[String(level)].stats 的独立副本,不插值、不使用随机数,也不额外修改数值。养成目标声明 formula 时,该实现名必须与当前生效实现一致,否则明确报错。插件登记其他公式后按既有选择规则使用;卸载所选实现会回落到 table。
上限与消耗机制
growth:resolve-cap接收{ target, level, table },返回{ cap }。默认取表中最大等级;上限小于当前等级或当前等级缺表时拒绝。growth:resolve-cost接收{ target, level, nextLevel, table },返回{ cost }。默认读取目标等级的消耗,缺失或空数组即报错。- 两个机制均为
trusted,输出整份校验。异常或非法输出不改变等级、库存或通知记录。
素材服务
growth:items 提供:
| 方法 | 行为 |
|---|---|
balance(item) | 返回指定素材的当前数量;未知条目报错 |
grant(item, count = 1) | 授予正整数数量的素材,返回授予后总数 |
list() | 返回数量大于零的 { item, count } 独立数组 |
没有 reset。页面关闭、插件撤销或剧本中止不会清除长期旗标;卸载数据包只撤销条目,不清除已保存的数值。
独立养成页
core:growth 经 ui:screen@1 登记,只接收 { target }。可经现有导航打开:
uiNavigator.open('core:growth', { target: 'demo:hero' })页面使用普通 DOM,不创建 Stage 场景。它显示目标 ID、当前等级/上限、属性、下一级消耗与素材余额。「强化」按钮支持焦点与键盘,每次点击只调用一次 enhance;失败显示原因,到达上限或读取失败时禁用。
页面订阅 state:flags,同一轮里的多次变化合并为一次重画;撤下时退订并移除页面,迟到的文本解析不写回旧界面。「返回」只退栈,不清除进度。本期没有剧本指令、主页快捷入口、独立美术资源协议或控件皮肤名。
边界与验证
当前不包括觉醒、装备、技能强化、经验值、任务奖励、数值兑换或活动日程。growth:on-awaken 只保留契约声明,不产生实际通知。Growth 不自动改写 Battle 的单位或属性,两个玩法的数值交界须另行登记。
验证入口:
test/unit/growth-data.test.ts:数据校验、内存旗标下的读取与强化、失败不写和通知边界。test/contract/growth.test.ts:真实装载与撤层、公式回落、机制改写审计、显式旗标授予,以及真实 Save 写入和读回。test/ui/growth-screen.test.ts:真实 DOM、键盘强化、旗标订阅、上限与错误、撤下清理和导航返回。
完整回归 1252 项通过、81 项按环境跳过;Windows WebView2 与 MuMu Android 15/WebView 110 的共用契约各 438 项通过、2 项按条件跳过,Growth 与存档往返均通过。类型检查与两端原生构建通过。
当前状态:等级与强化范围已完成;Growth 插件整体仍为实现中。本页范围不等于 Growth 的全部长期目标,平台边界见当前状态与测试。