# 缺失功能路线图(Missing-Features Roadmap) > **日期**:2026-07-23 > **用途**:盘点 Spellforge 当前所有未实现/占位的功能,分组为史诗(Epic),给出目标·现状·依赖·工作量·优先级·验收标准·切分建议,作为后续逐个 `spec → plan → 实现` 的统筹入口。 > **来源**:`docs_dev/doc_code_audit_2026-07-20.md`(对抗性复核过)+ 2026-07-23 代码复核(见各 Epic「现状」引用行号)。已完成并从本表剔除:Mana(`93dffd7`)、元进展(`MetaProgress`)、Boss 阶段+攻击系统(`95e5587`)。 > **⚠️ 复核约定**:审计为 7-20 快照,本文 7-23 复核了关键声明;每个 Epic 真正立项写详细计划前,仍须对其「现状」再复核一次当前代码(行号可能漂移)。 --- ## 0. 优先级与推荐顺序 优先级分层(用户 2026-07-23 选定 P0/P1 四项为最先详细规划): | 层级 | Epic | 一句话理由 | | :-- | :-- | :-- | | **P0** | E1 战斗深度 | 元素/轨迹词条现为死代码,落地即让大量已有内容"活过来",build 多样性提升最直接 | | **P0** | E3 经济与 build | 货架 B/C + 出售 + 属性词条,撑起 roguelite 的核心成长/取舍循环 | | **P1** | E4 游戏循环/里程碑 | 通关演出 + `GAME_CLEARED` + NG+ + Boss Rush,让游戏有"结局"与重玩驱动 | | **P1** | E6 Boss 深化 | 承接已完成的 Boss 核心:场地机制、通关演出、玩家无敌帧 | | P2 | E2 状态/元素反应 | 依赖 E1 元素成熟;催化/反应矩阵是深度上限 | | P2 | E5 教程/引导 | 独立打磨项,商业化必需但非玩法核心 | | P3 | E7 渲染/性能/债务 | LOD/C# 热路径/UI .tscn 化/i18n 债务,长尾优化 | **推荐实现顺序(含依赖)**: ``` E6-a 玩家无敌帧(i-frames) ← 先行小项:Boss 弹幕公平性前置,E1 也受益 → E1 战斗深度(抗性 → 连锁/弹跳 → 归航 → 轨迹修正) → E3 经济与 build(属性词条系统 → 货架 C → 货架 B → 出售退款) → E4 游戏循环(GAME_CLEARED/通关演出 → 里程碑 → Boss Rush/Endless 词条 → NG+) → E6-b Boss 深化其余(场地机制:冰墙/收缩 → 通关/死亡演出) → E2 状态反应 → E5 教程 → E7 债务 ``` 工作量记号:**S**≈3–5 任务、**M**≈6–10 任务、**L**≈11–16 任务(Boss 系统为 12 任务=M~L 参照系)。 --- ## E1. 战斗深度(元素抗性 / 连锁 / 弹跳 / 归航 / 轨迹修正) · P0 · 工作量 M **目标**:让子弹的 pierce 以外的深度维度真正生效,使元素、抗性、轨迹类词条与核心特性产生行为差异。 **现状(代码复核 2026-07-23)**: - ~~元素抗性~~ ✅ **完成**(2026-07-24,`feat/element-resistance`):`apply_damage_from_context` 按 `ctx.damage_type` 查 `_RESIST` 表传入 `calc_damage(0, res)`;`enemies.json` 每型可选 `resistances{元素名:-0.9~0.9}`(支持负=弱点加伤);设计器敌人页加 6×5 抗性网格。MCP 实测:抗火0.5→半伤、弱冰-0.5→1.5×、抗性+护甲叠加45。⚠️ **已知限制**:DOT 伤害(`status_manager.gd:116` 直调 `apply_damage`)暂不享元素抗性(架构上 DOT 不走 context,见 E2)。(~~`player_stats.gd:23 resistance` 玩家侧抗性仍占位~~ —— **2026-07-31 订正**:该字段零消费方且不在权威属性表内,属实现先于设计的残留,已随 E3-① 删除;玩家侧减伤真要做时按货架 C 属性词条立项,见 `docs_dev/specs/2026-07-31-player-attributes-design.md` §2.6。) - ~~连锁/弹跳~~ ✅ **完成**(2026-07-24,`feat/bullet-bounce`):镜像 pierce 管线——`CastStats.bounce_add` → `_apply_modifier` 折叠 → `_push_projectile` 写冷数据 → `_check_collision` 命中转向最近未访问敌(`_find_nearest_unvisited`)、`damage_mult×decay` 递减、`visited_targets` 防回跳、命中循环跳过已访问防密集群重复命中。bounce 优先于 pierce(耗尽后落 pierce)。`modifier_bounce` 词条上架。MCP 实测:bounce=2→3 敌 100/90/81、速度重定向证明优先级、折叠 bounce_add=2。 - ~~归航~~ ✅ **完成**(2026-07-30,`feat/bullet-homing`):镜像 bounce 管线——`CastStats.homing_add`(float) → `_apply_modifier` 折叠 → `_push_projectile` 写冷数据 `homing_strength/homing_range/homing_target_id` → `_gd_integrate` 在位置积分**之前**调 `_apply_homing`,用 `wrapf` 取最短转向、`clampf` 到 `strength*delta` 限角速度、`rotated()` 保速率。目标为**发射后锁定**:仅首帧与目标死亡时经 `_find_nearest_unvisited` 重选;bounce 命中重定向时改写 `homing_target_id`(bounce 选目标、homing 追上去)。`modifier_homing` 词条上架。MCP 实测见下方「⚠️ 有意偏离」与 spec §5。 - ⚠️ **有意偏离本文档原方案**:本行原写「`_gd_integrate` 消费 `_enemy_pos_snapshot`」,实现**没有**消费它,而是**删除**了 `_enemy_pos_snapshot` 及其唯一生产者 `EnemyManager.fill_pos_snapshot`。理由:最终设计采用**按 entity_id 锁定目标**(轨迹可读、目标死亡有明确判据 `get_pos_by_id` 哨兵),而该快照**按槽位存位置、不含 entity_id**,结构上支撑不了锁定语义;接上它反而要每帧 O(敌人数) 重扫最近点。净效果是**减少**一份每帧 O(敌人数) 开销。 - ⚠️ **性能**:重选**失败**路径会每帧重跑 `query_circle(r=400)`,实测 300 弹即越过 2.0 ms 线,故同期落地**退避 + 抖动**(`homing_retry_at`,`HOMING_RETRY_MS=200`)。抖动必需——朴素固定退避会把同帧失败的子弹锁进同相,尖峰每 12 帧永久复发。详见 spec §5。 - 轨迹修正(加速/曲线):`_data +11 acceleration` 已积分,但无"转向/曲线"类修饰器写入。 **设计来源**:`docs/mechanics/combat_mechanics_depth.md §4`(抗性公式)、子弹冷数据字段。 **依赖**:无硬依赖;元素 tag 体系已在(`SpellNode.element_tags`)。敌人需有 per-type/per-status 抗性数据源(新增 `enemies.json` 抗性字段或状态减抗)。 **切分(建议 4 个子计划)**: 1. ~~**元素抗性 (1-Res)**~~ ✅ **完成**(2026-07-24,`feat/element-resistance`;spec/plan `docs_dev/{specs,plans}/2026-07-24-element-resistance*`):enemies.json `resistances{元素名:-0.9~0.9}`;EnemyManager `_RESIST` 查表传入 `calc_damage(0,res)`;设计器 6×5 抗性网格。 2. ~~**连锁/弹跳 chain/bounce**~~ ✅ **完成**(2026-07-24,`feat/bullet-bounce`;spec/plan `docs_dev/{specs,plans}/2026-07-24-bullet-bounce*`):冷数据 `bounce_remaining/visited_targets/decay/range`,命中转向最近未访问敌+×0.9 递减,bounce 优先于 pierce,`modifier_bounce` 词条。 3. ~~**归航 homing**~~ ✅ **完成**(2026-07-30,`feat/bullet-homing`;spec/plan `docs_dev/{specs,plans}/2026-07-30-bullet-homing*`):冷数据 `homing_strength/homing_range/homing_target_id`,每帧以 `strength*delta` 为上限朝**锁定目标**转向(`wrapf` 最短转向 + `rotated()` 保速率),目标死亡才重选;失败退避 + 抖动(`homing_retry_at`);bounce 协同改写目标;`modifier_homing` 词条。**偏离**:未消费 `_enemy_pos_snapshot` 而是删除之(快照按槽位存位置、不含 entity_id,支撑不了锁定语义),见上方「现状」。 4. **轨迹修正**:曲线/环绕类(angular velocity 字段)+ 对应修饰器。S(可选,最低价值,YAGNI 可延后)。 **验收标准**:抗性 50% 的敌人受火伤减半(数值实测);bounce=2 子弹依次命中 3 个不同敌人且伤害递减;homing 子弹命中偏移目标;各修饰器可在商店买到并影响弹道;纯数据驱动、MCP 运行时实测。 --- ## E2. 状态 / 元素反应(催化 / 环境反应 / 状态交互矩阵 / VULNERABILITY) · P2 · 工作量 M **目标**:状态之间、元素之间产生化学反应(催化引爆、易伤叠加、地表反应),把 StatusManager 从"独立计时器"升级为"交互矩阵"。 **现状**:`status_registry.gd` 不解析 `can_catalyze`(死字段);无 overwrite/immunity 规则、无反应地表;VULNERABILITY 状态(+5% 受伤,`consecutive_hits_stacking.md:80`)**未实现**(现只有 COMBO_MARK +2%)。 **设计来源**:`docs/mechanics/consecutive_hits_stacking.md`、`combat_mechanics_depth.md` 状态矩阵。 **依赖**:E1(元素/抗性成熟后反应才有意义)。 **切分**:① VULNERABILITY 状态 + 命中叠层(S);② 状态交互矩阵(overwrite/immunity/refresh 规则表,JSON 驱动,S~M);③ 催化引爆(catalyze:某状态达阈值被特定元素引爆成 AoE,M);④ 反应地表(借 ZoneManager,M,可延后)。 **验收标准**:VULNERABILITY 叠层增伤生效;毒+火催化引爆造成范围伤;矩阵规则(如冰覆盖火)按 JSON 生效;MCP 实测。 --- ## E3. 经济与 build(货架 B/C + 出售退款 + 属性词条系统) · P0 · 工作量 M~L **目标**:把商店从"只卖法术"扩成完整 roguelite 经济:核心抽取、属性升级、出售退款,配合玩家属性成长系统。 **现状(代码复核 2026-07-23;属性部分 2026-07-31 订正)**:`shop_manager.gd` 无 shelf/sell/core/attr 任何字段(grep 零匹配)→ **仅货架 A(法术抽取)**。无出售退款(G5)。 - ⚠️ **2026-07-31 订正**:本行原写「`player_stats.gd` 有 `resistance` 等占位属性(4/5 stats 未接线)」,**与事实不符**。权威属性表(`docs/design/numerical_design.md` §1.1)是 **11 个属性**(`hp_max`/`mana_max`/`move_speed`/`cast_delay_mod`/`recharge_speed_mod`/`luck`/`cpu_limit`/`attunement_×4`),`armor`/`resistance` **根本不在表内** —— 它们是实现先于设计的孤儿字段(零消费方),已随子计划 ① 删除。真实缺口是:三条**死数据**(`cpu_limit`/`move_speed`/`cast_delay_mod`,消费方已存在只是没接上,子计划 ① 已修)+ 三类**未立项新机制**(`attunement_×4`/`luck`/`recharge_speed_mod`)。详见 `docs_dev/specs/2026-07-31-player-attributes-design.md` §0/§1。 **设计来源**:`docs/design/game_design.md §5`(三货架)、`numerical_design.md`(属性曲线、退款比例)。 **依赖**:货架 C 依赖「属性词条系统」先落地;核心抽取复用已有 `cores.json`/`make_core_by_id`。 **切分(建议 4 个子计划,属性词条优先)**: 1. ~~**属性词条系统**~~ ✅ **完成**(2026-07-31,`feat/player-attributes`;spec/plan `docs_dev/{specs,plans}/2026-07-31-player-attributes*`):`AttributeFormula` 纯静态公式模块(`hybrid` 连乘 / `inverse` 反向下限 / `add_int` 拒 `pct` + `pct` 越界钳 0);`PlayerStats` 持 `_attr_def` + `_modifiers` 并把公式结果写回静态类型裸字段(读取端零开销);`add_modifier` / `remove_modifiers_from(source)` 按来源增撤;`data/attributes.json` + 设计器「属性」页。**接线三条死数据**:`spell_evaluator` MAX_OPS 改读生效 `cpu_limit`(法杖份额以 `source="core"` 加成接入,运行时实测 3→120 / 5→200 / 8→320 步)、`player_manager` 删 `const MOVE_SPEED` 改读 `PlayerStats.move_speed`(**发版基准仍是 200**;实测手段是临时挂一条 `+50%` 加成使生效值变 300,测得玩家实际位移速度同步由 200 变 300 px/s,证明读取端是活的)、`_handle_auto_cast` 开火时乘 `cast_delay_mod`。删孤儿字段 `armor`/`resistance`;`hp_max`/`cpu_limit` 移出存档(改为派生值)。 - ⚠️ **实际范围小于原描述**:原写「定义 4/5 缺失 player stats(如暴击/急速/范围/吸血/减伤)」—— 那些属性名是拟稿推测,不存在于任何权威文档(见上方「现状」订正)。本期只做**框架 + 三条死数据**,明确延后三项,各有理由: - `attunement_fire/ice/lightning/poison`(4 个元素精通)—— 属**新增玩法维度**而非断线,需接入元素伤害管线,独立立项。 - `luck` —— 权威表定义它「影响暴击率」,而**暴击链目前是死的**(`bullet_manager.gd:81` 把 `is_crit` 硬编码为 `false`,`CastStats.crit_chance` 从未被掷判);打通暴击链是其前置。 - `recharge_speed_mod` —— 代码中**不存在充能系统**(全项目 grep `recharge` 零命中),属新增机制而非断线。 - 另:`mana_max` 的「与法杖取 Min」语义(权威 §1.1)未迁入框架,现状是核心值直接覆盖玩家值;那是独立设计判断,记为已知遗留。 - ✅ **`cast_delay_mod` 的饱和区问题已处理(`hard: 0.01 → 0.05`,提交 `ba7c885`,决定已关闭)**:`_handle_auto_cast` 用 `if` 而非 `while`,每物理帧至多一次施法 → 60 次/秒硬顶,实际速率按**整帧量化**,故饱和点 = `(1/60) / 法杖基准间隔`(`circuit_fork` 0.0278 / `wand_basic` 0.0333 / `wand_fast` 0.0667)。原 `hard: 0.01` 远在所有杖的饱和点之下,从饱和点买到 0.01 射速纹丝不动。因饱和点随杖而异、不存在对所有杖都最优的单一 `hard`,取 0.05 为折中:`wand_basic` / `circuit_fork` 无无效区间,`wand_fast` 仍剩 `[0.05, 0.0667)`(较原来的 6.7 倍缩至 1.33 倍)。完整实测数据集见 `docs_dev/specs/2026-07-31-player-attributes-design.md` §2.2b。若日后要把 `wand_fast` 那段也消掉,正确做法是让 `hard` **逐杖化**(挪进 `cores.json`)而非继续挪这个全局数 —— 属独立立项,**不是本期遗留待办**。 2. ~~**货架 C(属性购买)**~~ ✅ **完成**(2026-07-31,`feat/shelf-c-attribute-shop`;spec/plan `docs_dev/{specs,plans}/2026-07-31-shelf-c-attribute-shop*`):`PriceFormula` 纯静态定价模块(`geometric`/`linear`/`flat` 三曲线,`class_name` 零依赖,可脱离游戏进程单测,风格对齐 `AttributeFormula`);`ShopManager` 新增货架 C 状态(`_attr_purchases` 唯一写入点 `_apply_attr_purchases()` 重建加成,来源常量 `MOD_SOURCE_SHOP_C="shop_c"`);`attributes.json` 逐属性加 `shop` 段(`mode`/`step`/`price_base`/`price_growth`/`curve`)驱动可售集合与定价,**无 `shop` 段即不可售**(数据驱动,加属性零代码,运行时实测:注入无 `shop` 段的合成属性会被正确排除);`ProfileManager` schema 2→3 新增 `attr_purchases` 持久化,`apply_run()` 顺序为**先 `ShopManager.apply_attr_purchases_save` 后 `PlayerStats.load_save_data`**(颠倒会在"已有历史购买"场景下吞血,运行时实测复现:错误顺序丢 30 HP、正确顺序不丢);商店 UI 新增「📊 属性」按钮打开独立子面板(原计划设想内联在商店面板,实测面板仅余 18px 放不下,改独立子面板);设计器「属性」页扩展 `shop` 五字段编辑。 - ⚠️ **实际范围**:仅落地 `attributes.json` 现有的 4 个框架内属性(`hp_max`/`move_speed`/`cast_delay_mod`/`cpu_limit`)。E3-① 延后的 B 类 7 个属性(`attunement_*` ×4、`luck`、`recharge_speed_mod`、`mana_max` 的 Min 语义)仍待各自前置(暴击链、充能系统、元素伤害管线等)解除后才有意义可买;**「加 `shop` 段即可上架、零代码」只在该属性已接入 PlayerStats 框架之后才成立**——上述 7 个都还没有,届时仍需先在 `scripts/autoloads/player_stats.gd`(裸字段 + `_recompute_attrs()` 一行 + `_attr_effective` 字面量各加一条)与 `addons/game_designer/attribute_tab.gd` 的 `ATTR_ORDER` 常量把它接进框架,之后加 `shop` 段才是零代码(2026-08 最终评审修复:`get_sellable_attrs()` 现同时校验 `shop` 段与 `PlayerStats.has_attr()`,未接线的属性会被排除而非被静默售卖——此前的「已运行时验证」结论范围有误,验证的只是"有 shop 段即出现在列表",没验证"未接线属性会怎样")。另外,商店「属性」子面板当前坐标常量(`scenes/main/combat_s2.gd` 的 `_setup_attr_shop_ui`)在关闭按钮之前最多容纳 6 行,7 个属性一次性全部上架会超出,需要先做布局/滚动改造。 - ✅ **`cast_delay_mod` 的 soft 上限验证**:三个饱和点(`wand_basic` 0.0333 等)全部低于货架购买软上限 `soft`(0.1),常规购买够不到饱和区。运行时实测买到 `soft` 需 22 次购买,此时帧距仍为 3 帧(未饱和),证明 `soft` 才是玩家实际能碰到的约束。 3. **货架 B(核心抽取)**:商店提供 Core 抽取/更换(复用 `_CORE_ROSTER`),与现有换杖打通。S~M。 4. **出售退款 G5**:背包内法术/核心可出售,按 `numerical` 退款比例返还货币。S。 **验收标准**:三货架并存刷新正确;买属性词条后伤害/射速等实测变化;核心抽取可换 build;出售返还货币且从背包移除;纯数据驱动 + 设计器可调 + MCP 实测。 --- ## E4. 游戏循环 / 里程碑(通关演出 / GAME_CLEARED / 里程碑 / Boss Rush / Endless 词条 / NG+) · P1 · 工作量 L **目标**:给游戏一个"结局"与重玩驱动:W20 通关演出 + `GAME_CLEARED` 事件、里程碑奖励、Boss Rush/Endless 全局词条、NG+(Phase4)。 **现状(代码复核 2026-07-23)**:`scripts/` 无 `GAME_CLEARED`/`NG_PLUS`/`boss_rush`/`milestone` 任何引用(grep 零匹配)。游戏**只能靠死亡结束**;Boss 死亡已发 `BOSS_KILLED=30`(E4 可挂钩),但无通关流程。 **设计来源**:`docs/design/game_design.md §8`。 **依赖**:Boss 系统(已完成,`BOSS_KILLED` 可作通关触发);存档系统(已在,NG+ 需扩 schema)。 **切分(建议 5 个子计划)**: 1. **通关演出 + `GAME_CLEARED` 事件**:W20 Boss 死 → `GAME_CLEARED{elapsed, wave}` → 通关结算屏(复用 settlement)。事件常量续 31。S。 2. **里程碑 W5/W10/W15**:达波次触发奖励/事件(宝箱/免费法术/属性)。S~M。 3. **Boss Rush 模式**:连续 Boss 波模式入口(复用 BossManager + waves 子集)。M。 4. **Endless 全局词条**:>W20 每 N 波抽全局增益/减益词条(正负权衡)。M。 5. **NG+(Phase4)**:通关后开启的更高难度循环,敌人/Boss 强化曲线 + 存档标记。M。 **验收标准**:W20 击杀 → 通关屏 + `GAME_CLEARED` 发出;里程碑奖励发放;Boss Rush 可进入并结算;Endless 词条按波刷新生效;NG+ 循环难度提升且可存读;MCP 实测。 --- ## E5. 教程 / 引导(TutorialManager / 渐进解锁 / 靶场) · P2 · 工作量 M **目标**:新手引导从"仅难度选择"升级为真正教学:分步教程、内容渐进解锁、练习靶场。 **现状**:FTUE 仅难度选择(`main_menu.gd`);无 `TutorialManager` autoload、无渐进解锁、无靶场场景。 **设计来源**:`docs/design/tutorial_design.md`。 **依赖**:解锁树可复用 `MetaProgress`。 **切分**:① TutorialManager(分步提示状态机 + 事件钩子,M);② 渐进解锁(法术/核心按进度解锁,接 MetaProgress,S~M);③ 靶场/练习模式(无伤害假人场景,S)。 **验收标准**:首次进入分步教学可完成;未解锁内容不出现在商店/背包;靶场可自由测试 build;MCP 实测。 --- ## E6. Boss 深化(玩家无敌帧 / 场地机制 / 通关·死亡演出) · P1 · 工作量 M **目标**:承接已完成的 Boss 核心(阶段+7 招式+敌弹),补齐当初范围外的深度项。 **现状**:Boss 核心已完成(`95e5587`)。✅ **玩家无敌帧已完成**(分支 `feat/player-iframes`,2026-07-24:`take_damage` 时间戳门控 0.5s 窗口 + `is_invulnerable()` + 8Hz 闪烁 + 复活 `PLAYER_DAMAGED`/hurt 音效 + 顺带修复 balance_tab `_save` 丢键;时长入 `balance.json` `player_iframe_sec`)。**未实现**:场地机制(冰墙障碍 / 场地收缩,`boss_design §5.2`);Boss 通关/死亡演出序列(`PHASE_DYING` 阶段)。 **设计来源**:`docs/technical/boss_design.md §5`。 **依赖**:ZoneManager(场地机制复用);BossManager(已在)。 **切分(建议 3 个子计划)**: 1. ~~**玩家无敌帧 (i-frames)**~~ ✅ **完成**(2026-07-24,`feat/player-iframes`):PlayerStats 时间戳无敌窗口 + HUD 闪烁反馈;所有外部伤害(敌弹/Boss 接触/近战)经 `take_damage` 单点尊重 i-frame。spec/plan:`docs_dev/{specs,plans}/2026-07-24-player-iframes*`。 2. **场地机制**:BossManager 招式可生成冰墙障碍(ZoneManager 阻挡区)+ 场地边界周期收缩(bosses.json 阶段字段 `arena_shrink`/`hazards`)。M。 3. **通关/死亡演出**:`PHASE_DYING` 阶段 + 死亡序列 VFX + 恢复部分 HP 的终章弹幕(final boss)。S~M,与 E4 通关演出衔接。 **验收标准**:连续受击有无敌窗口、HUD 反馈;冰墙阻挡玩家移动/子弹、场地按时收缩;Boss 死亡播放序列后才移除并触发通关(衔接 E4);MCP 实测。 --- ## E7. 渲染 / 性能 / 债务(LOD 剔除 / DamageNumber / C# 热路径 / UI .tscn 化 / i18n 债务) · P3 · 工作量 M~L(可拆分独立小项) **目标**:长尾优化与技术债清理,不阻塞玩法但影响手感/规模/可维护性。 **现状**:`enemy_manager.gd:25 _visible_flags` 声明却从不置 1 → 屏内剔除/低频分离力未实现;无伤害飘字(DamageNumber);C# 热路径(BulletManagerCs/EnemyManagerCs/SpatialGridCs)为死代码(R-08 已承认);UI 全程序化(无 `.tscn`);i18n 债务:法术/核心/状态 `display_name`/`description` 仍硬编码未 tr 化,缺裸中文静态检查。 **设计来源**:`architecture_design.md §4.4`、R-08、ADR-A1。 **依赖**:无。各项可独立作为"缝隙任务"穿插。 **切分(独立小项)**:① DamageNumber 飘字(S,高手感回报);② 敌人 LOD 屏内剔除 + 屏外低频分离(S~M);③ 内容名 tr 化 + 裸中文静态检查(S,i18n 收尾);④ UI 关键面板 `.tscn` 化(M,可选);⑤ C# 热路径落地(L,仅当 GDScript 达性能瓶颈时;当前 500 敌 3.6% 预算,非必需);⑥ **计算模块化重构(M~L,2026-07-31 立项确认,用户指定)** —— 见下。 ### E7-⑥ 计算模块化重构(用户 2026-07-31 指定的架构方向) **原则**:凡涉及计算的都由**专门功能模块**负责,便于测试、配置,符合「专门模块负责专门功能」的设计理念。`AttributeFormula`(E3-① 建)是已验证的模板:`class_name` 纯静态、零依赖(不碰 autoload/场景树),因此**不启动游戏就能单元断言**,改公式立刻回归。 **现状盘点(代码复核 2026-07-31)**:计算散落 8 处,仅 1 处已模块化。 | 计算 | 现在住在哪 | 状态 | | :-- | :-- | :-- | | 属性合成 | `AttributeFormula` | ✅ 已模块化(模板) | | 伤害合成(一半) | `DamageContext.calc_damage`(`damage_context.gd:26`) | ⚠️ 与上下文数据混在同一个类 | | 伤害合成(另一半) | `EnemyManager.apply_damage:285-289` | ❌ 内联在管理器 | | 经验曲线 | `PlayerStats.xp_for_level` | 纯静态但与状态混住 | | 分数 | `EndlessRecords.compute_score` | 同上 | | 刷新费用 | `ShopManager.get_reroll_cost` | ❌ 内联 | | 蓝耗 + heat 乘子 | `SpellEvaluator._charge_mana` | ❌ 内联在法术 VM | | 波次缩放 | `WaveManager:61,62,76` | ❌ 内联三处 | **最严重的一处 —— 伤害被劈成两半,分别在两个文件里,且两处都在扣护甲**: ```gdscript # damage_context.gd:26 base_damage × mult × (1 − resistance) − armor × (1 − pierce_rate) # enemy_manager.gd:285-289 ← 又算了一遍 damage × (1 + combo_stacks × 0.02) − armor # 保底 1 ``` 目前**没有**重复扣,因为 `apply_damage_from_context` 特意传 `calc_damage(0.0, res)` 把 armor 置 0 留给下游 —— 但该约定只存在于调用点,两个函数各自看都是完整公式。想知道「这一击到底怎么算」必须同时读两个文件并知道那条不成文约定。连击的 `+2%/层` 也硬编码在管理器里,不在任何数据文件中。 **立项时必须先决定的设计问题**(都不该在实现期顺手定):伤害那两半如何合并、`calc_damage` 的 `armor` 参数语义要不要改、连击 `+2%` 进哪个数据文件、DOT 伤害(`status_manager.gd:116` 直调 `apply_damage`,绕过 context 故不享元素抗性,E1-① 记录的已知限制)是否借此一并归位。 **风险**:触碰全游戏最热路径(500 敌 + 1500 弹),必须有迁移前后的基准对比。 **依赖**:无硬依赖。`PriceFormula`(E3-② 货架 C 建)会成为第二个已模块化的例子,可与 `AttributeFormula` 一起确立命名/签名/测试惯例,再据此重构其余 7 处。 **验收标准**:飘字随命中显示;屏外敌人低频更新且 FPS 提升;4 语言无裸中文;MCP/截图实测。 --- ## 附:立项流程 每个子计划遵循已验证的流水线(同 Boss): 1. `superpowers:brainstorming` → 澄清范围/设计决策 → `docs_dev/specs/--design.md`(提交)。 2. `superpowers:writing-plans` → 逐任务实现计划 → `docs_dev/plans/-.md`(提交)。 3. `superpowers:subagent-driven-development` → 子代理逐任务实现 + 两阶段评审 → 验收 → 合并。 4. 全程 Godot MCP 运行时实测;纯数据驱动;改动记 memory。 > 本路线图为"活文档":完成一个 Epic/子项后在此勾除并更新现状引用。