From 72543be204791cd7af5b6444848faaca189dfaab Mon Sep 17 00:00:00 2001 From: Joywayer Date: Tue, 21 Jul 2026 11:29:48 +0800 Subject: [PATCH] =?UTF-8?q?docs(meta):=20=E7=A2=8E=E7=89=87=E5=A5=96?= =?UTF-8?q?=E5=8A=B1=E6=9B=B2=E7=BA=BF=E6=94=B9=E6=95=B0=E6=8D=AE=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8(balance.json=20=E9=98=88=E5=80=BC=E8=A1=A8)+=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E5=8F=AF=E8=B0=83=EF=BC=88=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E5=8F=8D=E9=A6=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-07-21-meta-progression-mvp-design.md | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/docs_dev/specs/2026-07-21-meta-progression-mvp-design.md b/docs_dev/specs/2026-07-21-meta-progression-mvp-design.md index f0a973c..87547f2 100644 --- a/docs_dev/specs/2026-07-21-meta-progression-mvp-design.md +++ b/docs_dev/specs/2026-07-21-meta-progression-mvp-design.md @@ -9,6 +9,8 @@ **目标**:给游戏加入 Roguelite 长期粘性闭环——每局结束按波次获得**以太碎片**(全局持久、死亡不失),在主菜单花碎片**解锁进阶法术**,解锁后的法术进入商店掉落池。即使失败也有收获感。 +> **设计原则(数据驱动)**:本系统所有**可调数值**(解锁费用、碎片奖励曲线)**必须落在 `data/*.json` 且能在游戏设计器里可视化调整**,不得硬编码。解锁费用走 `spells.json` 的 `meta.unlock_cost`(法术编辑器 meta 框可调,同 `shop_cost`/`mana_cost`);碎片奖励曲线走 `balance.json` 的阈值表(平衡页签可调)。 + **本次 MVP 包含**: - 全局持久的碎片货币(`user://meta.json`)。 - 每局结束(死亡)按到达波次发放碎片。 @@ -43,8 +45,8 @@ func clear() -> void # aether=0, unlocked=[], 删 meta.json ``` - 职责边界:只管"有多少碎片、解锁了哪些、怎么存读"。不知道法术费用(费用来自 spells.json,调用方传入)、不碰商店/UI。 -### 2.2 `spells.json` 门控字段 -给 6 张进阶法术的 `meta` 加 `"unlock_cost": N`(放 **meta 内**,法术编辑器把 meta 当自由 JSON 保留,不会像顶层字段那样被 rebuild 丢弃)。无 `unlock_cost` 或 =0 → 开局解锁。 +### 2.2 `spells.json` 门控字段(可在法术编辑器调) +给 6 张进阶法术的 `meta` 加 `"unlock_cost": N`(放 **meta 内**:法术编辑器把 meta 当自由 JSON 保留,不会像顶层字段那样被 rebuild 丢弃,且策划可在 meta 框直接改费用)。无 `unlock_cost` 或 =0 → 开局解锁。**锁定法术集 = `meta.unlock_cost>0` 的法术**(即"改哪张法术的 unlock_cost 就等于改解锁树",纯数据驱动)。 ### 2.3 商店池门控(`shop_manager.gd`) `_refresh_slots` 现有过滤 `shop_cost>0`,改为: @@ -53,12 +55,11 @@ shop_cost>0 且 (unlock_cost==0 或 MetaProgress.is_unlocked(id)) ``` 锁定且未解锁的法术不进商店池。 -### 2.4 碎片结算(`combat_manager.gd`) -`_on_player_died` 已在重置前捕获到达波次。新增:`MetaProgress.add_aether(_aether_for_wave(wave))`,其中 -``` -func _aether_for_wave(wave) -> int: return int(pow(float(wave), 1.4) / 3.0) -``` -(W1=0 / W5≈3 / W10≈8 / W20≈22,贴合 §7.1 的 0/3/8/20)。 +### 2.4 碎片结算(数据驱动曲线,`balance.json` + `SettingsManager` + `combat_manager.gd`) +- `data/balance.json` 增字段 `"aether_thresholds": [[1,0],[5,3],[10,8],[15,14],[20,20]]`(`[到达波次, 发放碎片]` 阶梯,升序)。 +- `SettingsManager`(已负责加载 balance.json)加 `aether_for_wave(wave) -> int`:返回**波次 ≤ 到达波次 的最高阶梯**对应的碎片(阶梯查表;缺字段则回退内置默认表并 `push_warning`)。超过最高阶梯按最高值封顶(Endless 亦然)。 +- `combat_manager._on_player_died`(已在重置前捕获到达波次)新增:`MetaProgress.add_aether(SettingsManager.aether_for_wave(wave))`。 +- **平衡页签(`balance_tab.gd`)**支持编辑 `aether_thresholds`(JSON 文本框,比照 core_tab 的 edges 编辑法),并在保存时保留该字段(不被 rebuild 丢弃)。 ### 2.5 解锁界面(`main_menu.gd`) 主菜单新增「🔓 解锁」按钮 → 程序化 CanvasLayer 面板(比照现有 settings 面板写法): @@ -73,7 +74,7 @@ func _aether_for_wave(wave) -> int: return int(pow(float(wave), 1.4) / 3.0) ``` 开始→游玩→死亡 │ combat_manager._on_player_died 捕获 wave - ▼ MetaProgress.add_aether( _aether_for_wave(wave) ) → 存 meta.json(全局持久) + ▼ MetaProgress.add_aether( SettingsManager.aether_for_wave(wave) ) → 存 meta.json(全局持久) 主菜单「🔓解锁」面板 → 花碎片 MetaProgress.unlock(id,cost) → unlocked[]+存档 ▼ 下一局商店 _refresh_slots:池 = shop_cost>0 且 (unlock_cost==0 或 已解锁) @@ -93,9 +94,9 @@ func _aether_for_wave(wave) -> int: return int(pow(float(wave), 1.4) / 3.0) | action_chain_bolt | 8 | 连锁闪电 | | action_summon_turret | 10 | 召唤炮台 | -其余 ~13 张(spark_bolt / fire_bolt / poison_dart / laser_beam / water_wave / damage_plus / spread_mod / double_cast / pierce_plus / trigger_on_hit / every_n_shots / if_hp_below / if_enemy_nearby)开局可用。解锁全部 = 39 碎片 ≈ 5 局(W10 档)。 +其余 ~13 张(spark_bolt / fire_bolt / poison_dart / laser_beam / water_wave / damage_plus / spread_mod / double_cast / pierce_plus / trigger_on_hit / every_n_shots / if_hp_below / if_enemy_nearby)开局可用。解锁全部 = 39 碎片 ≈ 5 局(W10 档)。以上费用均写在各法术 `meta.unlock_cost`,**法术编辑器可调**。 -**碎片公式**:`int(pow(wave, 1.4) / 3.0)`。 +**碎片奖励阈值表**(`balance.json.aether_thresholds`,**平衡页签可调**):`[[1,0],[5,3],[10,8],[15,14],[20,20]]`——`[波次,碎片]` 阶梯,到达波次取 ≤ 它的最高阶梯值(如 W12→8、W20→20、Endless W25→20 封顶)。贴合 §7.1 的 0/3/8/20。 > `action_plasma_storm` 是共鸣产物、`shop_cost=0`,本就不在商店池,无需门控。 @@ -114,9 +115,10 @@ func _aether_for_wave(wave) -> int: return int(pow(float(wave), 1.4) / 3.0) 1. **持久往返**:`MetaProgress.add_aether(10)` → `save_meta` → 新实例 `load_meta` → aether=10、unlocked 保留。 2. **解锁扣费**:aether=5,`unlock("action_frost_bolt", 5)`→true、aether=0、is_unlocked=true;再 `unlock("action_chain_bolt", 8)`→false(不足)、状态不变。 3. **商店池门控**:unlocked 为空时 `_refresh_slots` 抽样多次,锁定法术(如 chain_bolt)**不出现**;解锁后再抽,可出现。 -4. **碎片公式**:`_aether_for_wave` 对 1/5/10/20 返回 0/3/8/22。 +4. **碎片阈值表**:`SettingsManager.aether_for_wave` 对 1/5/10/20 返回 0/3/8/20;W12→8、W25→20(封顶);改 `balance.json.aether_thresholds` 后值随之变(数据驱动)。 5. **清除数据**:`MetaProgress.clear()` 后 aether=0/unlocked 空/文件删除。 6. **解锁面板**:主菜单点「解锁」渲染碎片数 + 6 行锁定法术;截图确认;点解锁按钮态正确变化。 +7. **编辑器可调**:`balance_tab` 编辑 `aether_thresholds` 保存后不丢字段(`execute_editor_script` 走 core-tab 同款 fresh-load 往返验证);法术编辑器改 `meta.unlock_cost` 保留。 --- @@ -125,10 +127,12 @@ func _aether_for_wave(wave) -> int: return int(pow(float(wave), 1.4) / 3.0) | :--- | :--- | | `scripts/autoloads/meta_progress.gd` | **新建** MetaProgress autoload | | `project.godot` | 注册 MetaProgress autoload | -| `data/spells.json` | 6 张法术 meta 加 `unlock_cost` | +| `data/spells.json` | 6 张法术 meta 加 `unlock_cost`(费用,法术编辑器可调) | +| `data/balance.json` | 加 `aether_thresholds` 阈值表(碎片曲线,平衡页签可调) | | `scripts/autoloads/shop_manager.gd` | `_refresh_slots` 过滤加门控条件 | -| `scripts/domain/combat/combat_manager.gd` | `_on_player_died` 按波次发碎片 + `_aether_for_wave` | -| `scripts/autoloads/settings_manager.gd` | `clear_all_local_data` 增调 `MetaProgress.clear()` | +| `scripts/domain/combat/combat_manager.gd` | `_on_player_died` 调 `MetaProgress.add_aether(SettingsManager.aether_for_wave(wave))` | +| `scripts/autoloads/settings_manager.gd` | 加载 `aether_thresholds` + `aether_for_wave()`;`clear_all_local_data` 增调 `MetaProgress.clear()` | +| `addons/game_designer/balance_tab.gd` | 平衡页签支持编辑并保留 `aether_thresholds`(**编辑器可调**) | | `scenes/ui/main_menu.gd` | 「🔓解锁」按钮 + 解锁面板 | | `translations/*.po` | `META_*` 四语键 | @@ -139,4 +143,5 @@ func _aether_for_wave(wave) -> int: return int(pow(float(wave), 1.4) / 3.0) - 死亡后碎片按波次增加并持久(重启游戏仍在)。 - 主菜单解锁面板可花碎片解锁法术;解锁后该法术出现在商店池、未解锁前不出现。 - ST-03 清除数据把碎片/解锁清空。 +- **所有可调数值(解锁费用 / 碎片曲线)均在数据文件且可在游戏设计器里改**:法术编辑器改 `unlock_cost`、平衡页签改 `aether_thresholds`,保存后运行时生效、不丢字段。 - `game_design §7` 现状 callout 更新为「碎片+解锁树 已实现(MVP);图鉴/成就/核心解锁待后续」。