diff --git a/design/research/研究-内容数据驱动扩展架构-2026-10-06.md b/design/research/研究-内容数据驱动扩展架构-2026-10-06.md new file mode 100644 index 00000000..bea5c6ea --- /dev/null +++ b/design/research/研究-内容数据驱动扩展架构-2026-10-06.md @@ -0,0 +1,119 @@ +# 研究-内容数据驱动扩展架构-2026-10-06 + +状态:调研+提案,**零代码修改**,待用户拍板。 +问题原文(用户):「如果我们要对其物进行修改设计的话,是不是只要更改我们的配置文件就好了?如果是一些机制类的专长,也能够只改配置文件,不改动代码吗?我希望我们这里可以做得比较拓展一些……你可以学习一下各种支持mod扩展的游戏,他们是如何实现的。」 + +--- + +## 〇 结论(先答两问) + +1. **改已有物品的数值/名字/稀有度/投放渠道 → 是,只改配置表就能生效**(所有内容族都已是 `.tres` 数据表,加载期校验,运行时通用读取)。 +2. **给已有物品换一个全新效果行为 / 加一件带新效果的新物品 / 加机制类新专长 → 现状必须改代码**。因为「效果类型」是封闭枚举,每新增一个枚举值都要:改 schema 枚举 → 加一处 `match` 翻译分支 → 在结算代码里加消费点 → 在文案代码里加说明文字,共 3-4 处代码。 +3. 项目里**已经有一个完全做到「只改配置」的范本:技能池**。`skills.tres` 加一行技能、`enemy.tres` 的 `pool` 里引用它(Boss 半血解锁只需 `unlock_hp_pct: 50` 字段),全链路零代码。差距是把专长/秘宝/令牌提到同等水平。 + +--- + +## 一 现状盘点:各内容族「改配置能走多远」 + +内容全部在 `game/data/tables/*.tres`,schema 在 `game/data/schemas/`,统一清单装载于 `game/core/config_db.gd:12-31`;表里没有任何回调/脚本路径,行为全部用封闭枚举字符串键+参数字典表达。表内数据与「配置」的分离没有问题,问题出在代码侧对数据的解释方式。 + +| 内容族 | 定义处 | 只改配置能做什么 | 必须改代码才能做什么 | +|---|---|---|---| +| 技能(技能池) | `skills.tres` + `enemy.tres` pool | **加新技能整件**(伤害/增益/妨害、权重、冷却、Boss半血解锁)——全链路数据驱动 | 新的技能大类(现仅 basic/damage/buff/debuff 四类) | +| 状态效果 | `status_effects.tres` | 加新状态行(技能/奖励格引用它) | 新的状态机制形态 | +| 专长(奇物·规则改写类) | `feats.tres`(27行) | 加「挂点已存在」的新专长:数值、稀有度、流派标签随写随生效;同挂点多件自动累加 | 新挂点(hook)=4处代码;现 23 挂点封闭(`feat_table.gd:36-67`) | +| 秘宝/同调件 | `treasure_items.tres`(13行) | 加「效果类型已存在」的新件(如又一个 3×3 显影件);改充能/占槽/解锁谓词 | 新效果类型=改枚举+执行分支;**被动件按物品 id 硬编码**(见二B) | +| 奇物令牌(属性/资源) | `adventure.tres` | 改配额/数值 | 新令牌种类(分发键=代码 match,`adventure_table.gd:84-114`) | +| 格面资源 | `reward.tres` | 加新资源行(percent 类经 `effect_id` 路由进状态系统) | 新格面行为 | +| 局外天赋树 | `meta_tree.tres`(33节点) | 数值/价格/前置/上限 | 新规则键(现仅 2 个规则键 wired,`battle_orchestrator.gd:261-264`) | + +--- + +## 二 差距精确清单:效果行为硬编码在哪些代码位置 + +调查核证(file:line 均经抽查复核): + +**A. 专长:两段式,翻译段硬编码。** +- 求值段(半通用):`_feat_flags_for` 对 23 个 hook 逐个 `match` 展开(`battle_orchestrator.gd:101-179`)。 +- 消费段(硬编码):每个展开出的旗在结算代码里各有一处读取点——`damage_controller.gd` 13 处(rider_flat:253、nest_aura:257、round_dig:264、crack:276、shield:312、clamp:429-434、discount_shift:219-221、hit_trade:203/228、armor_roll_rewrite:209、spike:215/236 等);`battle_orchestrator.gd` 11 处(first_dig_spell:487、terrain_dig_double:519、flag_strike:537、dig_yield:604-615、chain_arrows:974-980 等)。 +- 流派档位(≥2件/≥4件质变)硬编码在 `battle_orchestrator.gd:171-175`。 + +**B. 秘宝:主动件半通用,被动件按 id 硬编码。** +- 主动件:`use_treasure` 按 `effect_kinds` 通用分发(`battle_orchestrator.gd:648-666`)——这部分是好的;但混有按 id 的特判(`dig_charge` 积点闸,:643-647)。 +- 被动件按件 id 硬编码:`venom_edge`(:248 → damage_controller.gd:225)、`luck_coin`(:249 → reward_economy.gd:195-207)、`dawn_order`(:272-273、:1098-1099)、`nest_counter`(:703-713)、`flag_burst`(:828-831)、`pick_refresh`(adventure_runner.gd:650)。 + +**C. 奇物令牌:** `_apply_curio_pick` 按 kind match(`adventure_runner.gd:412-449`)。 + +**D. 呈现文本硬编码(新内容会「无名无声」的直接原因):** +- 物品卡说明:`battle_narrator.gd:104-121`(令牌)、`:142-166`(专长逐 hook 文案)、`curio_interact_controller.gd:185-204`(秘宝只认 3 种 kind)。 +- 无本地化/文本表:`display_name` 内联在 .tres 里(这本身没问题),但**效果说明文字**没有一处在数据行里,全在代码里。 + +**E. 基础设施(新词=代码,但这是合理边界):** +- 谓词表计数键 `COUNTER_KEYS`(`attunement_growth_table.gd:22`)、存档域(版本迁移 `save_manager.gd:50-57`)、渠道白名单(`adventure_runner.gd:757-763`,设计规格 `design/gdd/systems/冒险循环/奇物.md:200-217`)。 + +**F. 已经在做对的事(不需要改,是改造的地基):** +- 加载期校验+交叉校验悬空引用即致命(`config_db.gd:106-148`、`config_db_cross_validator.gd`); +- 行键白名单/零裸flat护栏(`treasure_item_table.gd:51-53`、`feat_table.gd:76-79`)——这些封闭校验是设计护栏,改造要保留它们,改的只是「枚举值↔代码分支」的绑定方式; +- MC 模拟器直接实例化真实的 battle_orchestrator(`monte_carlo.gd:20-22`)——**效果执行一旦数据化,模拟器自动看到新内容,调平衡不用双写**。 + +--- + +## 三 支持 mod 的成熟游戏是怎么实现的(官方文档查证) + +| 游戏 | 内容加法 | 机制加法 | 机制要点 | +|---|---|---|---| +| Minecraft(数据包,官方) | 纯 JSON:配方/战利品表/进度/谓词/标签/附魔等几十类注册表 | 要写 Java mod | 战利品表=「条件对象+奖池条目」纯 JSON;进度=「触发器类型+条件+奖励」纯 JSON;谓词是跨系统复用的通用条件词汇 | +| Factorio(官方 mod API) | 数据阶段 prototype(Lua 表:物品/配方/实体)——官方内容本身就是 prototype | 要写运行阶段 Lua 脚本 | 数据/逻辑分两个阶段;运行期行为靠事件系统钩子 | +| RimWorld(官方 mod 体系) | XML Defs(defName 主键,加载期注册)+ XML 补丁操作改原版数据 | 要写 C# 程序集(Harmony 运行时补丁) | 纯数据 mod 能加特性/研究/动物等几乎所有「内容」;数据不够时才落代码,且补丁机制把改动隔离在数据层 | + +(来源:minecraft.wiki/w/Data_pack、wiki.factorio.com/Modding、rimworldwiki.com/wiki/Modding——前两者已逐条核对原文,RimWorld 维基反爬只取到入口页,机制按通行记载表述。) + +**四条共性,就是「改配置不改代码」的全部秘密:** + +1. **内容=数据,机制=解释器。** 代码里只有一套通用的「效果类型+参数」解释器;每件内容是一行数据,声明自己是什么类型、带什么参数。 +2. **游戏在稳定的时机对外喊一声(事件),内容声明「我在什么时机、什么条件下、发生什么效果」。** 时机词汇(开格/标旗/受击/击杀/轮末……)是封闭且稳定的,内容条目只是订阅者。 +3. **条件是通用词汇,跨内容复用**(Minecraft 谓词、RimWorld 的条件类、我们已有的谓词表雏形)。 +4. **加载期注册+校验闸兜底**:id 唯一、引用悬空、键出域,全部启动即报错——这一条我们已经在做。 +5. **边界同样存在**:Minecraft 数据包加不了新机制,Factorio 的新行为也要写 Lua。mod 游戏不是「零代码」,而是**把「新机制」压缩成「往词汇表里加一个类型」(一次性、低频),让「新内容」完全数据化**(高频、零代码)。 + +--- + +## 四 改造方案(备选案全列) + +### 案甲:最小修(清理性,约 1 天) +只消灭「按件 id 硬编码」(二B 被动件改造成 effect_kinds 通用分发)+ 把物品效果说明文字搬进数据行。 +- 收益:秘宝族达到「同类件纯配置」;新件不再无名无声。 +- 不解决:专长新挂点仍要改代码;令牌/树不变。 +- 风险:低。纯重构+文案搬家,冒烟+MC 对拍可验。 + +### 案乙:效果类型统一+时机埋点(推荐,约 3-4 天,可分期) +把专长/秘宝/令牌统一到「**触发时机 + 条件 + 效果类型+参数**」的数据形态: +1. 定一份跨内容通用的**效果类型词汇表**(伤害修正/开单/资源授予/状态授予/改写/计数器……)——现 23 hook+12 kind 是这份词汇表的初稿素材,也是主要工作量所在(熔火之躯的积层反打、矿工重锤的命中交换这类需要词汇表有计数器/轮末/改写能力)。 +2. 在结算段关键节点布**语义事件点**(开格/标旗/受击/击杀/轮末/Boss半血/使用道具……),一条内容行声明 `{on=时机, when=条件谓词, do=效果}`,由通用执行器解释。 +3. 保留全部现有护栏:封闭词表、键白名单、悬空引用致命、零裸flat禁令照旧,只是校验对象从「枚举在 schema 里」变为「词汇表条目存在且已实现」。 +4. MC 模拟器零改动自动受益(共用执行器)。 +- 分期建议:①专长(23 hook 收敛)→②秘宝被动件并入 →③令牌/树规则键。每期独立冒烟可落籍。 +- 风险:中。23 个消费点的等价性改写,需 MC 对拍锚+冒烟全绿兜底;触到 battle_orchestrator 历史脏件(惯例走 worktree 批)。 + +### 案丙:完整 mod 式(外挂脚本层,约 5 天以上) +案乙基础上允许数据行指向外挂 GDScript 效果脚本(Godot 支持运行时加载脚本),即真正意义上的第三方可扩展。 +- 收益:任何行为都可外挂,词汇表不再是边界。 +- 不建议现在做:导出安全、脚本沙箱、兼容矩阵、探针全覆盖都是额外工程;Alpha 前没有第三方 mod 需求,词汇表不够用时再加类型(案乙路径)成本远低于维护插件层。挂账待「mod 需求」立项再启。 + +**推荐:案乙,按 ①②③ 分期立项**(可并进现有 roadmap 排期,或作为迭代 17 候选卡)。 + +--- + +## 五 拍板点 + +1. **立项选择**:案甲(1天,只清秘宝)/ 案乙(3-4天,专长+秘宝+令牌全数据化,推荐)/ 案丙(挂账)。 +2. **排期位置**:并入迭代 17 候选序列,还是单独立卡插队。 +3. **案乙词汇表范围**:首批是否 23 hook+12 kind 全收敛,还是先收敛专长族试点后扩。 +4. **文本表值化是否随批**(牵 UI 呈现,battle_narrator/curio_interact_controller 两处)。 + +--- + +## 六 附:顺带发现(非本议题,仅登记) + +- 菜单开局路径 `main.gd:475` 未传 `attunement`/`tree_rules` 参数(营地装配后从主菜单开局可能丢同调装配/局外树规则;冒烟是直呼 runner 面故未拦住)——是否立项修复待用户令。 +- relic 词族与 feat 词族命名统一已在 `design/gdd/06-待办清单.md:101` 在册,案乙动 feats.tres 时可顺路处理或明确避让。