Files
game-code-4/CLAUDE.md
T
程基岩(engineering-lead) 4f650aeb39 W3:相机 rig + band 组装器 + 事件系统 + 殿王战(灰盒);ADR-5 落定
P0 文档
- 架构文档:殿王战 HP 系数 50× → 15×(Balance Bible [B§5] 口径),全文档无残留
- 新增 ADR-5:2D 骨骼动画(Spine)取代 ADR-1 的单位/殿王 billboard 条目
  * 背景/决策/后果/三项被否决方案(多帧 billboard、Skeleton2D、DragonBones)
  * Godot 4.7 接入方式标注"需立项时复核",不臆造 API;挂探针 P12
  * 资产规格约束:部件分离 PNG / 图集 / 锚点命名 / 动画命名 / AI 绑骨质检门槛
  * 数据行纪律影响:sprite_row → 动画资源路径行,坚持"新资产 = 加行"
  * 美术工时对照(pipeline 报告 115-185h)
  * 3D 特效落地约定:走 flipbook 序列帧,理由是 3D 粒子直塞 2D 会绕过单趟
    后处理(ADR-2 红线)导致风格撕裂;挂探针 P13
- ADR-1 标注"单位/殿王条目被 ADR-5 取代",降级为回退规格(§5.1 保留)
- 架构 §8 清单 / §11 探针表 / 【确定】【探针】标注段同步;CLAUDE.md ADR 节同步

P1 横版核心
- camera.csv(10 行,一行一殿)+ camera.schema.json + core/data/camera_def.gd
  * 独立成表的四条理由写入 schema description,不污染 halls.csv
  * 全局标量(弹簧刚度/阻尼/平滑 tau/偷看上限/战前预告分钟)进 balance_tuning.csv
- presentation/stage:camera_rig.gd(进度锚定 + 偷看回弹 + 殿王战推近)
  + hall_band_world.gd + band_world_root.gd(四层视差)+ stage_world.gd
- stage_root 接入横版舞台,取代 W2 十殿色带(hall_band.gd 保留作回退)

P2 玩法系统
- game/event_director.gd:events.csv 四事件 → 触发/持续/效果/二选一/失败哗变
  * 效果全走 EconomyState 既有 API(瞬时区 set_event_mult / set_event_click_mult /
    set_mutiny),不直接改字段;四个出口统一 _clear_runtime 防"漏清永久 ×N"
- game/boss_battle.gd:30s 状态机(INTRO/ACTIVE/RESOLVED)
  * HP = 15 × 进入时产出/s × 殿系数(1.0→2.2),连击 +2%/层封顶 +60%
  * 胜 = 阴德爆发 HP×0.2(进本轮累计口径);败 = 60s 冷却(购路引可消)
  * 不用随机数 → sim 门 #11 可直接复用
- EconomyState 接事件瞬时区与哗变惩罚;GameState 接线 + 快照扩展
- presentation:event_panel.gd(事件卡/二选一)+ boss_arena.gd
  (预告/HP/连击/倒计时/结算/再战);stage_root 布局接入
- debug 构建 dev 热键 F1-F6/F9,走 GameState 既有命令口,不改数值

P3 质量
- 新增 3 个用例:test_camera_data / test_event_director / test_boss_battle
  (进 test_runner.CASE_FILES,共 7 个用例文件)
- 用户验证手册:docs/engineering/2026-10-19-w3-verification-manual.md(文档区)

修掉的两个潜伏缺陷(从根因修,非打补丁)
- gen_balance_sheets.py:halls.is_prestige_gate 落成字符串 "false",
  Godot 的 bool("false") == true → 十殿会被全部判为 prestige gate。
  改为真布尔,并把自检查从 == "true" 收紧为 is True(再犯即断言失败)
- boss_battles.schema.json:hp_factor 漏 type,GDScript SheetImporter 会产出
  字符串 "15"(Python 生成器产出的是数字),两条路径不一致。补 type: number

上报(未擅自改动,等裁定)
- H9/H10 殿王战数学上不可胜:纯军列耗时 = 15 × 殿系数(与产出/s 无关),
  殿系数 >2.0 → 31.5s/33.0s > 30s 限时;而缺口 ∝ 产出/s,点击伤害是常数
  (上限 25.6,不随产出/s 增长)→ 玩家越强越打不过,难度曲线是反的。
  已在 test_boss_battle._test_winnability_doc 把当前事实钉成断言哨兵,
  一旦有人改 hall_factor/active_sec/hp_factor 立刻变红强制重评。修数权属文策渊。

本机验证(无 Godot,靠移植仿真,非代替引擎实跑)
- 把 CameraDef/BossBattle/EventDirector 逐行移植成 JS 喂真实 build JSON,
  134 条断言全绿;9 张表 schema 校验通过且 build 逐字节一致(含新增 camera)
- 静态检查:跨文件方法/字段引用审计、静态调用合法性、src/core 禁 extends Node、
  缩进/括号配平/空函数体 —— 全部 0 问题
- 待本机验证:全部 GDScript 从未被引擎执行过;SubViewport 舞台与 Camera2D
  在 gl_compatibility 下的行为未实测(探针 P12 范畴)
2026-10-20 01:39:14 +08:00

104 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md —— F《WRATH OF THE DEAD / 怨返》工程偏好
> 由 `docs/architecture/2026-10-19-F-architecture.md`(v1.0)派生 · 2026-10-19 · W1
> 本文件为工程宪法摘要;**冲突时以架构文档为准**;架构更新须两边同步。目标 ≤100 行。
## 引擎版本纪律
- **钉 Godot 4.7.x 补丁线,当前 4.7.2**(`project.godot` config/features);小版本补丁可升,**跨 minor(4.8)上线后不追**;
- GDScript + GodotSteam **v4.23.1**(GDExtension 构建必须与 4.7.x 匹配;升级引擎 = 重新获取匹配构建);
- renderer:`gl_compatibility`(2D 合成 + 核显底线;改 renderer = ADR 级动作);
- ⚠ **知识缺口**:4.7.x 超出训练数据。API 不确定 → 先查官方文档/探针实测,**不臆造 API**;缺口持续标注,`docs/engine-reference/` 待补(架构 §11 P0)。
## 路径作用域编码标准(架构 §2.2)
| 作用域 | 纪律 |
|---|---|
| `src/core/` | 纯逻辑;禁 `extends Node`/访问场景树;`tick()` 零分配;100% 被 sim 与 GUT 无头复用 |
| `src/game/` | 唯一权威状态持有者;系统在此 tick;不直连 Steam(走 platform/);不碰渲染 |
| `src/presentation/` | **只读快照 + 发命令**;UI 不持有游戏状态(仅视图本地态);禁反向写 core |
| `src/platform/` | Steam API 唯一出口;`game/` 禁直调 `Steam.*` |
| `src/tools/` | `@tool` 标注;CI 可 headless;运行时场景禁引用 |
| `data/` | 零代码;稳定字符串 ID;**不重编号**;schema 违规 = CI 红 |
| `pipeline/` | 契约 = 命名 + 导出参数;唯一逐资产代码 = sprite 路径 |
| network | **不适用**:单人买断无网络代码 |
依赖方向:`presentation → game → core`;`game → platform`;`tools → data`。禁反向、禁跨层。
## 数据驱动红线(架构 §9.2 + ADR-3)
1. 零硬编码:一切数值进 `data/sheets/` → JSON → Resource;
2. **新资产 = 加行**;唯一逐资产代码 = `GeneratorDef.sprite_row`;
3. 新增资产若需改代码 = **设计失败,回退重做**;
4. 稳定 ID 永不重编号/复用;schema 违规 = CI 红(行号+列名+原因,禁跳过坏行);
5. 数值列禁千分位;`_cn/_en` 本地化后缀;引用列填目标 ID;
6. "AI 让加一个班底变便宜了"禁用作加范围理由。
## ADR 一句话(架构 §8,均已接受)
- **ADR-1**:预渲染 2 朝向 billboard,不用实时 3D(用户比较优势在批渲染)——**⚠ 单位/殿王条目 W3 起被 ADR-5 取代**;背景/套件/后处理部分仍有效,并作为 ADR-5 的**回退规格**(探针 P12 不过则军列带退回本条);
- **ADR-2**:单趟 fused 全屏后处理 shader(posterize→LUT→纸纹→暗角),UI 层在其上;
- **ADR-3**:美术数据行纪律(新资产=加行;逐资产代码 = 资产路径;ADR-5 扩展为 `animations.csv` 动画行);
- **ADR-4**:AI 仅内部使用(mood board/概念),不进包体、不出厂、商店页披露填 No——ADR-5 的"AI 自动绑骨"属**工具层**(对自己渲染的部件做蒙皮,不产出图像),不触本条;若未来变成 AI 生成部件图像,立即回到本条管辖;
- **ADR-5**(W3 新增):**单位/殿王/军列单位动画改用 2D 骨骼动画 Spine**(简单动作 = AI 自动绑骨 + 人工精修;复杂动作 = 纯手工 Spine);背景/后处理/UI 皮肤不动。**3D 特效只走 flipbook 序列帧**(3D 渲染成帧序列当 2D 素材),运行时不放任何 3D node——否则绕过单趟后处理=风格撕裂(ADR-2 红线)。
- ⚠ **知识缺口**:spine-godot GDExtension × Godot 4.7.2 × gl_compatibility 未实测;**版本矩阵/节点类名/许可条款均为空白**,由**探针 P12** 回填,**禁止臆造 API**;美术工时口径 billboard 115-185h → Spine **142-232h【估计】**(Δ +28-48h)。
## 参考模板(只读参照,非项目基底)
- **本仓库架构即基底**,不导入任何模板代码。套模板 = 重做 W1/W2:横版军列带布局、sim 与经济核心同源、CSV→JSON→Resource 管线——通用模板三者皆无;
- 三份只读参照(克隆到本仓库之外,仅供阅读与 P0 练手):
| 用途 | 仓库 | 许可 / 引擎 | 取什么 |
|---|---|---|---|
| P0 练手 | `DontBeBlink/2d-incremental-template` | MIT / Godot 4.5 | "Your first 2D game" 作业直接改它:点击赚币→升级→prestige→存档→数字格式化,1h 跑通整循环 |
| 架构与公式参照 | `Jegethy/idle-godot` | Godot 4.x(**许可待复核:克隆后先看 LICENSE**) | autoload 分层、批量购买几何级数 `cost_bulk(L,n)=C0·r^L·(r^n−1)/(r−1)`、版本化存档迁移、rate/multiplier 双型升级公式 |
| 成品参照 | `TinyTakinTeller/GodotProjectZero`(A Dark Forest,Steam app/3314970) | 代码 MIT、**资产各自版权** | 看"做完的挂机"长什么样:本地化结构(含简中)、导出预设、上架配置、终局内容补法 |
- **取用纪律**:抄结构/公式,不抄资产;抄入代码须在文件头注明来源与许可;
- A Dark Forest 引用的第三方 shader 中**仅 CC0 条目**可直接取用,CC-BY 需署名,**CC-BY-SA 禁入商业闭源包**。
## 探针状态(W1)
| 探针 | 状态 | 手册 / 结论 |
|---|---|---|
| P1 SCREEN_TEXTURE/CanvasLayer | ⏳ 待用户实测 | `docs/engineering/2026-10-19-f-w1-probe-p1-manual.md` → `docs/engineering/probes/P1-result.md` |
| P3 noise seamless 平铺 | ⏳ 待用户实测 | `docs/engineering/2026-10-19-f-w1-probe-p3-manual.md` → `docs/engineering/probes/P3-result.md` |
| P6 字体许可 / P7 用户 GPU | ⏳ 用户侧任务(W1) | 不在本仓库;结论回填 probes/ |
| P2/P4/P5/P8-P11 | 未启动 | 架构 §11 排期(W2-W5) |
**不过的回退**:P1 → SubViewport+BackBufferCopy(+2-4h);P3 → 脚本预烘焙无缝纹理(+0.5-1h)。
## 常用命令
```bash
# 数据门(导入 + 校验)
godot --headless --path . --import
godot --headless --path . -s res://src/tools/import_main.gd # import_all
godot --headless --path . -s res://src/tools/import_main.gd -- --validate-only
# 运行:编辑器 F5(main scene W2 起);探针:打开 tests/probe_* 场景 F6
```
## 数据管线速查
`data/sheets/*.csv` →(SheetImporter,本仓库 `src/tools/`)→ `data/build/*.json`(提交)→(W3 `.tres`)→ DataRegistry。
单向流动:游戏永不写 `data/`;sim 与游戏读同一份 build。契约见 `README.md` + 架构 §3。
**表清单(W3 = 9 张)**:`generators` / `upgrades` / `meta_upgrades` / `halls` / `hall_palettes` /
`boss_battles` / `events` / `balance_tuning` / **`camera`(W3 新增,一行一殿)**。
新增表 = 加 schema + 加 `.csv` + 进 `SheetImporter` 白名单,**不重编号既有 ID**。
**W3 相机参数为什么独立成表**(`camera.csv`,不是给 `halls.csv` 加列):
① `halls.csv` 是"世界身份行",被经济核心 / sim / UI / 引用校验广泛消费,加相机列会让每次手感
微调都重写整张十殿表;② 相机参数在灰盒期会高频手调,生命周期与数值表不同;③ 仍是"一行一殿",
年更新冤案包 = 加一行;④ 全局标量(弹簧刚度/阻尼/平滑时间常数)不随殿变,按既有纪律进
`balance_tuning.csv`(`tune_cam_*` 五行)。逐条理由见架构 §4.3 与 `data/schema/camera.schema.json`。
**验证手册**:`docs/engineering/2026-10-19-w3-verification-manual.md`(文档区,不入库)。
W3 的 GDScript 从未被引擎执行过(本机无 Godot)——**跑通第 1 节 headless 单测才算 W3 验过**。
## 纪律提醒
- 写代码前**先写测试**(GUT W3 起);每个 Story 留测试证据路径;
- 高影响动作(提交/删除/上线)须用户审批;本仓库 `git` 提交信息写架构基线;
- 目录微调 = 架构 §2.1 变更 = ADR 流程,不擅自挪目录。