Compare commits
40
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ad72f44a0 | ||
|
|
c585a6bd73 | ||
|
|
c009cf7b1e | ||
|
|
b991f52ac2 | ||
|
|
cd121b18c2 | ||
|
|
83a4fbf5c5 | ||
|
|
70d071f850 | ||
|
|
8be5d425ca | ||
|
|
4554e0e702 | ||
|
|
b75688c6ca | ||
|
|
ab5a45af00 | ||
|
|
afee92476d | ||
|
|
b5433285b4 | ||
|
|
546ed1d611 | ||
|
|
37ed6ab426 | ||
|
|
5269ed4080 | ||
|
|
5ecfabc251 | ||
|
|
57084e0bd3 | ||
|
|
12af4fe00c | ||
|
|
22809f9b79 | ||
|
|
94dfa7e79b | ||
|
|
7fd50fc485 | ||
|
|
e7090bc9c1 | ||
|
|
3a8634ab92 | ||
|
|
92e9c70a8d | ||
|
|
4a2ed96182 | ||
|
|
33525d19de | ||
|
|
3499638dee | ||
|
|
e075f92e0f | ||
|
|
34bb62a55b | ||
|
|
ceb816cd39 | ||
|
|
94628fca83 | ||
|
|
870b2f2bf6 | ||
|
|
3a1878ff80 | ||
|
|
d216ae0498 | ||
|
|
e090ea8af2 | ||
|
|
263050adf1 | ||
|
|
eb5dc1e7cb | ||
|
|
aba54ab228 | ||
|
|
3fa99583fb |
No files matched your search
@@ -16,7 +16,7 @@
|
||||
|
||||
## 运行与验证(工作目录 = 含 project.godot 的切片目录)
|
||||
|
||||
- **合回验证 = 本地 CI(2026-10-30 用户裁)**:git merge 合回 master 落地后,post-merge 钩子(`tools/hooks/post-merge`)后台触发 `tools/ci_runner.sh` 跑一次全量域闸(调 `tools/run_all_gates.sh` 不带参数档,02 全套件),结果落 `game/tests/.gates/ci-status.json`(commit/绿红/红闸名单+关键日志行/耗时)+`ci-history.jsonl` 流水账;CI 红态下每个修复提交经 post-commit 钩子(`tools/hooks/post-commit`)自动追绿复验,绿态与无状态零触发——主区小批直提不重复跑全量,同一份字节禁止第二次人手跑。CI 红不回滚合并,红项在案、修复提交追绿;开工先读 CI 状态,红未修不开新批。跑批起手自动 `--editor --quit` 刷类名缓存(.godot 缓存不入 git,防合并后失配假红)。`tools/run_all_gates.sh` 仍是全部验证闸的**唯一入口与唯一清单,域划分与选闸算法只写在它这一个地方**,闸件增减与分域调整都只改它,文档禁另列清单;`--code`/`--docs`/`--quick` 手动档只服务开发期按域跑批(开发期窄测纪律见 process-conventions §6),不构成验收;全量回归由用户自发发起
|
||||
- **合回验证 = 本地 CI(2026-10-30 用户裁)**:git merge 合回 master 落地后,post-merge 钩子(`tools/hooks/post-merge`)后台触发 `tools/ci_runner.sh` 跑一次全量域闸(调 `tools/run_all_gates.sh` 不带参数档,02 全套件),结果落 `game/tests/.gates/ci-status.json`(commit/绿红/红闸名单+关键日志行/耗时)+`ci-history.jsonl` 流水账;CI 红态下修复合回落地即由 post-merge 钩子复验追绿(红态修复走新开修复 worktree,`fix-<任务名>` 分支,免重塑免数卡;post-commit 钩子保留为红态主区直提兜底触发,绿态与无状态零触发)——批内提交零钩子检查、合回只验一次,同一份字节禁止第二次人手跑。CI 红不回滚合并,红项在案、修复合回追绿;开工先读 CI 状态,红未修不开新批。跑批起手自动 `--editor --quit` 刷类名缓存(.godot 缓存不入 git,防合并后失配假红)。`tools/run_all_gates.sh` 仍是全部验证闸的**唯一入口与唯一清单,域划分与选闸算法只写在它这一个地方**,闸件增减与分域调整都只改它,文档禁另列清单;`--code`/`--docs`/`--quick` 手动档只服务开发期按域跑批(开发期窄测纪律见 process-conventions §6),不构成验收;全量回归由用户自发发起
|
||||
- 单件直跑(调试期最窄确认用,**不构成验收**):冒烟测试 `python tools/run_smoke.py`(`game/tests/smoke_boot.tscn` 极小启动场景)· 系统测试 `python tools/run_system_test.py`(宿主 `game/tests/system_test.gd`)· 场景探针 `…console.exe --headless --path . res://probe/ui_probe.tscn` · 单元与集成 `… --script res://tests/run_all.gd`
|
||||
- 调参批量:`--script res://sim/adventure_monte_carlo.gd`(全冒险期望)· `res://sim/reward_expectation.gd`(奖励期望);关卡完成率/难度类测量一律走全冒险
|
||||
- 数值验证:`python tools/balance_verifier.py`(采集端 `res://sim/verifier_batch.gd`,报告与原始数据落 `sim-data/`)
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
| 时机 | 权威文档 |
|
||||
|---|---|
|
||||
| 批次开工 / 流程纪律 | `design/engineering/process-conventions.md`——车道铁律(主区直改+直提;大批约定走 worktree)、合回后本地 CI、五段流水线、批次清单、测试两入口与 MC/闸机细则、像素纪律 |
|
||||
| 批次开工 / 流程纪律 | `design/engineering/process-conventions.md`——车道铁律(一切改动走独立 worktree,主区只作合并落点)、合回后本地 CI、五段流水线、批次清单、测试两入口与 MC/闸机细则、像素纪律 |
|
||||
| 流水线段入口 | 技能对照——doc-design=文档设计(兼任反哺点落文)/asset-ingest=美术录入/req-card=写卡/iter-plan=迭代编排/iter=实现(五者均装于项目 `.zcode/skills/`);登记不立技能;批后收尾与中间文档退役=batch-closure(同一目录);格式与状态机权威=`design/engineering/doc-conventions.md` §12 |
|
||||
| 定代码方案 / 写代码 / 改代码前 | `design/engineering/code-conventions.md`——结构/契约/语言/数值/流程五类硬纪律(反例库 = 同目录 code-conventions-cases.md) |
|
||||
| 定测试方案 / 写测试 / 改测试前 | `design/engineering/test-conventions.md`——探针标配 / 回归断言 / 提交前验证 / 验收清单落码 |
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
**判据**:描述含多个实体、实体间有明确关系(先后顺序、包含、依赖、状态转移、布局对比)的内容时,直接画图说明,不写长段文字;单点事实(一句装得下)不画,纯数据对照用表格。
|
||||
|
||||
**载体**:默认用 visualize 技能出 HTML/SVG(会话内联渲染,表现力优先),流程/状态/结构/实体关系与空间对比、像素级示意、界面草图同一通道;查看端不支持内联渲染时退回 Mermaid 代码块,仍不行用字符画。
|
||||
**载体**:用 diagram-design 技能出 HTML/SVG 内联交付(流程/状态/结构/实体关系与空间对比、像素级示意、界面草图同一通道),大图精修与导出用 archify 技能;查看端不支持内联渲染时用字符画。
|
||||
|
||||
**边界**:硬数值与前提条件留在文字里,图不承载唯一数值依据;图与文禁重复说同一件事,文字只留图说不清的部分。
|
||||
|
||||
@@ -93,12 +93,12 @@
|
||||
|
||||
## 硬性红线(勿违反;操作细则在 process-conventions.md 与各规约)
|
||||
|
||||
- 车道铁律(判据与改动域划分同一,按文件性质切;2026-10-30 用户裁本地 CI 化)——一切面(含代码面 `game/` 下非 `.md` 的行为载体与 `.zcode/`、`.qoder/` 等不入 git 面)主工作区直改+直提;commit 点由 git pre-commit 钩子(`tools/hooks/pre-commit`,`core.hooksPath` 挂载)现场跑文档域闸,绿落地红拦,合并收尾提交跳过(归合回后 CI);代码面全量验证归合回后本地 CI(`tools/hooks/post-merge` 触发,见「运行与验证」首条);大批次(迭代实现批等)按约定仍走独立 worktree(冻结→件核→并 master→重塑→主区合回→CI 验证),约定非强制;`--no-verify` 仅属用户,agent 禁用(细则见 process-conventions §1)
|
||||
- 车道铁律(2026-10-31 用户裁恢复)——主工作区只作合并落点,一切开发/设计改动走独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`(建区即跑 `tools/setup_worktree_userdir.sh`),收口=冻结→件核→并 master→重塑→主区 `git merge --no-ff`→删区(合回即删,2026-09-19 原裁),CI 红不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,免重塑免数卡)修复合回追绿;主区唯一合法写动作=合并,agent 侧由 worktree-guard 拦主区 Edit/Write 与非 merge 提交;豁免面仅 `.zcode/`、`.qoder/`(不入 git,主区直改);commit 点零钩子检查(pre-commit 直改闸已退役),全量验证归合回后本地 CI(`tools/hooks/post-merge` 触发,见「运行与验证」首条);`--no-verify` 仅属用户,agent 禁用(细则见 process-conventions §1)
|
||||
- **仓库根禁止设会话状态文件**(`active.md` 已废除)——现状看 roadmap「当前位」,待办看待办清单,过程看 git 提交信息,产出物看 `reports/`;任何文档禁止另设「当前状态快照」节,两处记同一件事必然漂移(细则见 doc-conventions 第 10 节)
|
||||
- 测试执行两入口铁规——只有迭代 loop 开发与用户点名两个触发入口;其余会话零测试,需测试支撑先请示并注明未跑测
|
||||
- 合回后验证 = 本地 CI 全量域闸全绿(唯一强制验证点;唯一入口、唯一闸清单、唯一域划分与选闸算法仍只在 `tools/run_all_gates.sh`,禁在文档另列;触发与追绿语义见「运行与验证」首条与 process-conventions §1)。开发期手动跑批按需选档(`--code` 关联档选测——02 跑「卡片申报 ∪ diff 推导」并集套件、三件保险恒跑、横切面回落全量——算法只在闸脚本内定义),手动跑不构成验收;全量回归由用户自发发起。文档面直改批验收=commit 点 git 钩子自动跑 `--docs`(process-conventions §1)
|
||||
- **改动四类**——**需求改动**(游戏代码,含随逻辑写/改的测试代码):唯一走「写需求卡片+编入迭代批次」通道;迭代实现批禁写 `design/` 整个目录、两份根流程清单(`待办清单.md`/`体验验证清单.md`)与 `game/tests/README.md`(能力清单,归写卡段维护)(含新增/修改/删除),设计文档对它只读、是写测试与实现代码的输入依据;两份流程清单的条目状态只由流水线各段推进,实现批禁止顺手改;产出物只准写 `reports/`;合回后由本地 CI 全量验证(红项修复提交追绿,process-conventions §1)。**工程改动**(tools/、闸件、模拟测量工具、纯测试维护——不改变游戏行为的配套代码)、**文档设计改动**、**美术素材改动**:不写需求卡片、不编迭代批次,由用户发令在主工作区直改+直提(commit 点 git 钩子自动跑文档域闸);大体量改动(含触及代码面的工程改动如纯测试维护)按约定走 worktree 批(非强制);文档设计类写入走 doc-design 技能(登记条目格式由流水线闸强制)
|
||||
- 五段流水线铁律——**需求改动**(游戏代码)按「登记 → 文档设计/美术设计 → 写需求卡片 → 迭代编排 → 实现」五段推进,段间不自动流转、每段转进由用户发令;编入迭代的卡片必须设计闭合+零待裁点——需求卡片任何工作量皆可写、皆可编入迭代,工作量限制只属迭代层(迭代估时总量 <5 个工作日=「冻结待凑批」、不可开工);流水线闸 `tools/pipeline_gate.py` 强制(已注册进 run_all_gates.sh 文档域);实现段零裁断——卡片没写清=上游缺陷,停该卡退回上游,禁内联求裁(process-conventions §2,格式与状态机=doc-conventions §12)。工程/文档设计/美术素材三类改动不走写卡与编排段:(如需设计讨论)→ 用户发令直改 → 主区直改+commit 点闸(车道细则=process-conventions §1)
|
||||
- 合回后验证 = 本地 CI 全量域闸全绿(唯一强制验证点;唯一入口、唯一闸清单、唯一域划分与选闸算法仍只在 `tools/run_all_gates.sh`,禁在文档另列;触发与追绿语义见「运行与验证」首条与 process-conventions §1)。开发期手动跑批按需选档(`--code` 关联档选测——02 跑「卡片申报 ∪ diff 推导」并集套件、三件保险恒跑、横切面回落全量——算法只在闸脚本内定义),手动跑不构成验收;全量回归由用户自发发起。文档面批与代码面批验收同走合回 CI 全量(`--docs` 仅属开发期手动档,process-conventions §1)
|
||||
- **改动四类**——**需求改动**(游戏代码,含随逻辑写/改的测试代码):唯一走「写需求卡片+编入迭代批次」通道;迭代实现批禁写 `design/` 整个目录、两份根流程清单(`待办清单.md`/`体验验证清单.md`)与 `game/tests/README.md`(能力清单,归写卡段维护)(含新增/修改/删除),设计文档对它只读、是写测试与实现代码的输入依据;两份流程清单的条目状态只由流水线各段推进,实现批禁止顺手改;产出物只准写 `reports/`;合回后由本地 CI 全量验证(红项修复合回追绿,process-conventions §1)。**工程改动**(tools/、闸件、模拟测量工具、纯测试维护——不改变游戏行为的配套代码)、**文档设计改动**、**美术素材改动**:不写需求卡片、不编迭代批次,由用户发令走独立 worktree 直改+合回(车道铁律,commit 点零钩子检查);大体量改动(含触及代码面的工程改动如纯测试维护)同车道无特殊通道;文档设计类写入走 doc-design 技能(登记条目格式由流水线闸强制)
|
||||
- 五段流水线铁律——**需求改动**(游戏代码)按「登记 → 文档设计/美术设计 → 写需求卡片 → 迭代编排 → 实现」五段推进,段间不自动流转、每段转进由用户发令;编入迭代的卡片必须设计闭合+零待裁点——需求卡片任何工作量皆可写、皆可编入迭代,工作量限制只属迭代层(迭代估时总量 <5 个工作日=「冻结待凑批」、不可开工);流水线闸 `tools/pipeline_gate.py` 强制(已注册进 run_all_gates.sh 文档域);实现段零裁断——卡片没写清=上游缺陷,停该卡退回上游,禁内联求裁(process-conventions §2,格式与状态机=doc-conventions §12)。工程/文档设计/美术素材三类改动不走写卡与编排段:(如需设计讨论)→ 用户发令 → 独立 worktree 直改 → 合回 CI(车道细则=process-conventions §1)
|
||||
- MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起
|
||||
- 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6)
|
||||
- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,可 grep 定位、在当轮真实跑批中执行并通过,判据绑被测改动特有的可观测提交面;**禁变异类测试与撤销类取证**(2026-10-24/2026-10-28 用户裁——人为制造红属伪造证据),证明做不出=停卡呈报;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §8+iter 技能第 5 步)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 美术圣经(Art Bible)— Dungeon Sweeper
|
||||
|
||||
> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.30,历次修订明细见 git 提交史
|
||||
> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.31,历次修订明细见 git 提交史
|
||||
>
|
||||
> **Art Director Sign-Off(AD-ART-BIBLE)**:历次批均未签核——此为 Lean/Solo 模式(非 PHASE-GATE)下的现行治理状态;full 门禁签核时机待用户表态。
|
||||
> 风格基调:地牢题材但**非暗黑风**——轻快明亮的幻想冒险风,全年龄;像素风;角色 2~3 头身。
|
||||
@@ -395,7 +395,7 @@
|
||||
- **交互四态(零新素材,全部程序化)**:悬停=**轮廓亮边 + 浮动**(浮动须整像素吸附);按下=位移 1px;**禁用/未解锁=降明度 + 去饱和**(§2 已缩窄至情绪域,状态表达不受限),**仅锻炉(锻造工坊)与宝箱(秘宝匣)两件会有此态**;已解锁=常态。
|
||||
- **钥石余额**:常驻画面顶部的一行小 HUD 栏(高 48px,**浮层覆盖,不挤压画面**)。
|
||||
- **事实源边界**:解锁条件/价格/存档写入归元进度 GDD 与 `MetaProgression`;素材命名与路径归 `asset-path-map`;清单登记归 `art-assets-checklist` §3.5。
|
||||
- **待裁(本节不填数,由作者定)**:① **营地环境子板色值**——色彩脚本只给定色方向,落地色值属 §4.1 单点,须过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门;② **门扇与门洞的高宽比例**——中景带自底部往上约 2/3 处起之后高度有限,门扇高度远超围墙带,两者关系待作者重定;③ **帐篷的落地尺寸**——帐篷体量大于被替换的旧承载件,尺寸待作者重定;坐标草案的现行出口见 `camp.md` 的指路句。
|
||||
- **已裁(2026-11-01 用户裁,随迭代 47 卡④ 开工门销号)**:① **营地环境子板色值**——不前置拍板:T1 量化场景实际用色后按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——门扇 240×220 追认现值,坐标按门洞 x520–760 对齐(`camp-scene-prompts.md` §2.3);③ **帐篷的落地尺寸**——300×170 追认现值(各素材第一张样本稿已过审为终稿,重定即触发重出,不裁)。
|
||||
|
||||
### 6.3 三关图类型色板候选(board_type 换挡方向)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 营地场景 · 分层生图提示词卡 v1.2
|
||||
# 营地场景 · 分层生图提示词卡 v1.3
|
||||
|
||||
> **性质**:营地场景图(1280×800,一张可点击场景图 + 十张分层:背景层 1 + 围墙层 1 + 八个物件层)的出图执行侧文件。**场景级资产,与角色级 [art-prompts](art-prompts.md) 并列,两文件互不覆盖**。
|
||||
> **依据**:色彩与氛围 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`(本卡不复述色值);坐标与层序 = `artwork/2026-10-23-营地场景/布局草案-1280x800.html`;物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。冲突时色彩以色彩脚本为准,画法以 art-bible 为准。
|
||||
@@ -171,10 +171,10 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm
|
||||
|
||||
---
|
||||
|
||||
## 5. 待裁(不阻塞出图,阻塞坐标表与定稿)
|
||||
## 5. 已裁(2026-11-01 用户裁,随迭代 47 卡④ 开工门销号;不再阻塞坐标表与定稿)
|
||||
|
||||
1. **帐篷尺寸**:现 300×170 待重定,重定后按比例重出
|
||||
2. **门扇高宽**:现 240×220,围墙带只有 43px 高;围墙独立成层后门扇叠在门洞上,两者高宽关系待裁
|
||||
3. **布告板位置**:现 y330 悬空在围墙下方,建议 `(845, 268, 130, 140)` 挂回围墙带
|
||||
4. **描边颜色追认**:本卡按奶油色(去底技术前提);若改参照物的深灰褐,需换去底方案
|
||||
5. **营地环境子板色值**:art-bible §4.1 为数值单点,色值待作者拍板,本卡不复述
|
||||
1. **帐篷尺寸**:300×170 追认现值(各素材第一张样本稿已过审为终稿;重定即按比例重出、不裁)
|
||||
2. **门扇高宽**:240×220 追认现值,坐标按门洞 x520–760 对齐(§2.3);围墙带桩身高 43px、门扇叠在门洞上的叠放关系随此锁定
|
||||
3. **布告板位置**:采纳建议值 `(845, 268, 130, 140)` 挂回围墙带(y330 悬空案弃);终值随坐标表(卡④ `camp_scene_layout.tres`)落盘
|
||||
4. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全批重出,不裁
|
||||
5. **营地环境子板色值**:不前置拍板——T1 量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值
|
||||
@@ -249,18 +249,17 @@
|
||||
| **文档域** | gdd_lint、doc_link_audit、doc_term_audit、流水线闸 | `game/` 内的 `.md` 与 `game/` 外的一切路径:`design/`、根规则文件(`AGENTS.md`/`roadmap.md`/`待办清单.md`/`体验验证清单.md`)、`tools/` 工具脚本、`.zcode/` 配置、`sim-data/`、`reports/` |
|
||||
| **两域都含** | repo_structure_audit(熵增闸:顶层目录/根文件/图像白名单/退役路径/design 子目录五查——文档批新增或挪动 `.md` 同样会绊它;纯文本扫描秒级) | — |
|
||||
|
||||
口径三条:**域划分的唯一出处是 `tools/run_all_gates.sh`**(`--code`/`--docs`/不带参数=全量),本表是它的现状登记、不是第二份清单;改闸件本身或一次改动跨两域 → 跑全量档(§6.2 共享件例外);合回闸按 merge diff 的文件性质推出应验的域(`game/` 内 `.md` 归文档域),再校验回执的 `domain` 字段与新增红。代码域跑前先过**素材齐盘预检**——`game/assets/art/**` 与一切 `*.import` 边车都不入 git(2026-09-29 裁定),worktree 冷检出必空盘,空盘态冒烟 V1 成片假红、渲染闸更是一段 golden 都不比。
|
||||
口径三条:**域划分的唯一出处是 `tools/run_all_gates.sh`**(`--code`/`--docs`/不带参数=全量),本表是它的现状登记、不是第二份清单;改闸件本身或一次改动跨两域 → 跑全量档(§6.2 共享件例外);开发期手动档按本批改动域选 `--code`/`--docs`,合回后 CI 恒跑全量档。代码域跑前先过**素材齐盘预检**——`game/assets/art/**` 与一切 `*.import` 边车都不入 git(2026-09-29 裁定),worktree 冷检出必空盘,空盘态冒烟 V1 成片假红、渲染闸更是一段 golden 都不比。
|
||||
|
||||
### 车道分层执法(2026-10-26 用户裁「按路径切车道,取代一切改动走 worktree」)
|
||||
### 车道分层执法(2026-10-31 用户裁恢复「一切改动走 worktree」)
|
||||
|
||||
改动车道与改动域同一判据(文件性质):代码面=worktree 批车道,文档面=主工作区直改车道。执法全机械——判据只有文件路径性质与 git 图,不含「改动大小」等语义判断;「预期大改」由用户开工点名自愿开 worktree,不进规则。
|
||||
一切改动走独立 worktree,主工作区只作合并落点。执法全机械——判据只有 git 图与路径(豁免面 `.zcode/`、`.qoder/` 不入 git,主区直改),不含「改动大小」等语义判断。
|
||||
|
||||
| 执法层 | 载体 | 职责 | 判据 |
|
||||
|---|---|---|---|
|
||||
| **git pre-commit 钩子** | `tools/hooks/pre-commit`(版本化本体,`core.hooksPath` 挂载;在位性由 run_all_gates.sh 跑批自检——失位即红) | 直改车道闸机检:staged 不含代码面的提交,提交点现场跑 `run_all_gates.sh --docs`(秒级文本扫描),绿落地红拦;staged 含代码面时主工作区=拦(代码面唯一合法路径=worktree 批合回)、任务 worktree=跳过(归批末闸+合回闸,不打扰迭代批中间提交) | staged 文件性质+主区/worktree 判定(git-dir 与 common-dir 同一=主区) |
|
||||
| **worktree-guard**(ZCode PreToolUse) | `.zcode/hooks/worktree-guard.sh`(本机件,不入 git) | agent 侧车道纪律:主工作区代码面的 Edit/Write 与 staged 含代码面的 commit 拦截;`git commit --no-verify` 拦截(该旗标仅属用户);合回闸回执六况校验 | 路径性质+分支名+回执 JSON+git 图 |
|
||||
| **worktree-guard**(ZCode PreToolUse) | `.zcode/hooks/worktree-guard.sh`(本机件,不入 git) | agent 侧车道纪律:主工作区 Edit/Write 与主区非 merge `git commit` 拦截(豁免 `.zcode/`、`.qoder/`;worktree 内目标快速放行;合并收尾提交凭 MERGE_HEAD 豁免);`git commit --no-verify` 拦截(该旗标仅属用户);iter 分支合回一卡一提交数卡校验;规则闸 | 路径性质+分支名+MERGE_HEAD+git 图 |
|
||||
|
||||
取舍依据:失败代价不对称——docs 红是死链/术语/格式,下次任何跑批对基线比对必暴露、秒级修复,故文档面轻执法(commit 点闸、无回执流程);代码面红是运行时行为坏,保留「worktree+批末域闸+回执硬绑定」全套。git 层钩子对一切提交者生效(含用户手工提交,紧急出口 `--no-verify`);ZCode 层只约束 agent。子代理覆盖面(2026-10-26 冷启动评估实测):子代理的工具调用不经过 ZCode 层守卫(代码面 Edit 未被拦、`--no-verify` 探针未被拦)——ZCode 层实际只覆盖主会话工具调用,git 层因此是唯一覆盖一切提交者的执法层;残余暴露面=蓄意 `--no-verify`(pre-commit 族钩子被该旗标整族跳过,git 层无法自防),属故意越权而非遗忘型失误,与防遗忘的设计目标正交。
|
||||
验证收拢为合回后本地 CI 全量(post-merge 触发),commit 点零执法;主工作区防污染由 ZCode 层守卫承担——只约束 agent,用户手工改动不受限。子代理覆盖面(2026-10-26 冷启动评估实测):子代理的工具调用不经过 ZCode 层守卫——ZCode 层实际只覆盖主会话工具调用;残余暴露面=子代理写主工作区与蓄意 `--no-verify`(该旗标整族跳过 git 层钩子),属故意越权而非遗忘型失误,与防遗忘的设计目标正交。
|
||||
|
||||
### 三条判定硬闸现行状态
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# 流程规范(Dungeon Sweeper)
|
||||
|
||||
> 约束范围:一切批次的流程纪律——车道(代码面 worktree 批/其余主区直改)、五段流水线、批次工作流、测试执行细则、像素件工作纪律。
|
||||
> 约束范围:一切批次的流程纪律——车道(一切改动走独立 worktree,主区只作合并落点)、五段流水线、批次工作流、测试执行细则、像素件工作纪律。
|
||||
> 分工:硬性红线的一句话索引在 AGENTS.md「硬性红线」;本文承载其操作细则;批次开工前通读本文。
|
||||
|
||||
**开工任何批次前必须通读本文。**
|
||||
|
||||
## 1. 分支纪律(车道铁律)
|
||||
## 1. 分支纪律(worktree 铁律)
|
||||
|
||||
一切面主工作区直改+直提(2026-10-30 用户裁本地 CI 化:验证挪到合回后,主区直提不再拦任何面;判据与 §3 第 8 条改动域划分同一):
|
||||
主工作区(master 检出)只作合并落点,一切开发/设计改动禁止直接发生在主工作区(2026-10-31 用户裁恢复;2026-10-30 的「主区直改+直提」车道与 commit 点 pre-commit 直改闸随之退役;验证模型不动——合回后本地 CI 仍是唯一强制验证点):
|
||||
|
||||
1. **主区直改车道(一切面)**:`game/`(含代码面=`game/` 下非 `.md` 的行为载体)、`design/`、`reports/`、`tools/`、根规则与清单文件、`.zcode/`、`.qoder/`——直接改、直接提交。验收分两层:commit 点 git pre-commit 钩子(`tools/hooks/pre-commit`,经 `core.hooksPath` 挂载,在位性由 run_all_gates.sh 跑批自检)现场跑 `tools/run_all_gates.sh --docs`(秒级文本扫描)绿即落地红即拦,合并收尾提交跳过(MERGE_HEAD 在,内容归合回后 CI);代码面的全量验证归合回后本地 CI(下条)。开发期纪律不变:卡内只测自己改的东西、出红只跑红件最小单元(§6)
|
||||
2. **合回后验证(本地 CI,2026-10-30 用户裁)**:git merge 合回 master 落地后 post-merge 钩子(`tools/hooks/post-merge`)后台触发 `tools/ci_runner.sh merge` 对 master 尖跑一次全量域闸——唯一强制全量验证点;CI 红态下每个修复提交经 post-commit 钩子(`tools/hooks/post-commit`)自动追绿复验,绿态与无状态零触发。重跑判据:同一份字节禁止第二次人手跑;有意义的重跑只剩「验证修复」一类。CI 红不回滚合并——红项记 `game/tests/.gates/ci-status.json`,修复提交追绿;开工先读 CI 状态,红未修不开新批。跑批起手 `--editor --quit` 刷类名缓存(在册坑:.godot 缓存不入 git,合并后失配假红假绿)——原「合并后零复跑」的秒级动作由跑批件接管。并跑语义=跑完补跑(coalesce):跑批期间新触发不中断当前轮,轮尾对最新尖端补跑,绝不逐笔各跑一轮
|
||||
3. **worktree 批车道(大批约定,非强制)**:迭代实现批与大体量改动按约定仍走独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`;建区后立刻跑 `tools/setup_worktree_userdir.sh`——给该区独立 Godot user 目录(测试夹具、试玩日志、截图产物不与其他区共用;主区不生成,真实档保持原位)。收口顺序固定为**冻结 → 件核 → 并 master → 重塑 → 主区合回 → CI 验证**——代码与断言改完即冻结,全仓件核 grep 查残留;master 已被别的批次推进时先 `git merge master` 解冲突;**重塑**=迭代分支(iter<N> 形)合回前执行 `python tools/reshape_cards.py`,把分支线性史按卡末态快照压成一卡一笔(可选追加一笔纯文档收尾),master 台账由此每卡一行——工具自带「重塑前后树逐字节一致」断言与 backup 分支,不改任何文件内容;非迭代工程小批免重塑;然后主工作区 `git merge --no-ff <任务分支>`(合回守卫对迭代分支数卡校验,未归卡提交拦下),合并落地 post-merge 钩子触发 CI,红则修复提交(主区直提)追绿,全绿后 `git worktree remove`+删分支。游戏类测试(冒烟/单测/MC/探针)批内默认零执行(两入口铁规,见 §4),用户点名或当场问才跑
|
||||
4. **执法分层(全机械,零自觉依赖)**:①git pre-commit 钩子——一切提交的文档域闸机检(合并收尾提交豁免)。②post-merge/post-commit 钩子——本地 CI 触发(仅主工作区;任务 worktree 内的合并不触发)。③`.zcode/hooks/worktree-guard.sh`(PreToolUse,本机件不入 git)——agent 侧:`git commit --no-verify` 拦截(该旗标仅属用户)、iter<N> 分支合回的一卡一提交数卡校验、规则闸(写 design//game/ 前核对会话规约读取记录)。git 层钩子对一切提交者生效(含用户手工提交,紧急出口 `--no-verify`);ZCode 层只约束 agent
|
||||
1. **worktree 车道(一切面)**:每批先建独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`;建区后立刻跑 `tools/setup_worktree_userdir.sh`——给该区独立 Godot user 目录(测试夹具、试玩日志、截图产物不与其他区共用;主区不生成,真实档保持原位)。所有改动与提交都在 worktree 内自由进行——commit 点零钩子检查(`tools/hooks/pre-commit` 已删除)。豁免面仅 `.zcode/`(钩子与配置)与 `.qoder/`(本机 harness 配置)允许主工作区直改——两份实测均不入 git(走 worktree 反而带不进去,改动只对本机生效)
|
||||
2. **收口顺序(固定)**:**冻结 → 件核 → 并 master → 重塑 → 主区合回 → 删区**——代码与断言改完即冻结,全仓件核 grep 查残留;master 已被别的批次推进时先在 worktree 内 `git merge master` 解冲突(必须在合回之前,合回后才并=CI 验的是中间态);**重塑**=迭代分支(iter<N> 形)合回前执行 `python tools/reshape_cards.py`,把分支线性史按卡末态快照压成一卡一笔(可选追加一笔纯文档收尾),master 台账由此每卡一行——工具自带「重塑前后树逐字节一致」断言与 backup 分支,不改任何文件内容;非迭代批免重塑;然后主工作区 `git merge --no-ff <任务分支>`——这是主区唯一合法写动作(合回守卫对迭代分支数卡校验,未归卡提交拦下)。**合回落地即 `git worktree remove`+删分支(合回即删,2026-09-19 原裁);post-merge 钩子已在合回落地时自动触发 CI,红态不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,非 iter<N> 形免重塑免数卡)修复提交再合,落地复验追绿后删修复区**。游戏类测试(冒烟/单测/MC/探针)批内默认零执行(两入口铁规,见 §4),用户点名或当场问才跑
|
||||
3. **合回后验证(本地 CI,2026-10-30 用户裁)**:git merge 合回 master 落地后 post-merge 钩子(`tools/hooks/post-merge`)后台触发 `tools/ci_runner.sh merge` 对 master 尖跑一次全量域闸——唯一强制全量验证点;CI 红态下修复合回落地即由 post-merge 钩子复验追绿(红态修复走新开修复 worktree,`fix-<任务名>` 分支,非 iter<N> 形免重塑免数卡;post-commit 钩子保留为红态主区直提兜底触发,绿态与无状态零触发)。重跑判据:同一份字节禁止第二次人手跑;有意义的重跑只剩「验证修复」一类。CI 红不回滚合并——红项记 `game/tests/.gates/ci-status.json`,开工先读 CI 状态,红未修不开新批。跑批起手 `--editor --quit` 刷类名缓存(在册坑:.godot 缓存不入 git,合并后失配假红假绿)。并跑语义=跑完补跑(coalesce):跑批期间新触发不中断当前轮,轮尾对最新尖端补跑,绝不逐笔各跑一轮
|
||||
4. **执法分层(全机械,零自觉依赖)**:①`.zcode/hooks/worktree-guard.sh`(PreToolUse,本机件不入 git)——agent 侧:主工作区 Edit/Write 与主区非 merge `git commit` 拦截(豁免 `.zcode/`、`.qoder/`;worktree 内目标快速放行;合并收尾提交凭 MERGE_HEAD 豁免)、`git commit --no-verify` 拦截(该旗标仅属用户)、iter<N> 分支合回的一卡一提交数卡校验、规则闸(写 design//game/ 前核对会话规约读取记录)。②post-merge/post-commit 钩子——本地 CI 触发(仅主工作区;任务 worktree 内的合并不触发)。③git 层不设车道钩子(pre-commit 直改闸已退役)——用户手工改动不受限;ZCode 层只约束 agent(子代理不经守卫层)
|
||||
|
||||
## 2. 五段流水线
|
||||
|
||||
**需求改动**(游戏代码,含随逻辑写/改的测试)按五段流水线走:**登记 → 文档设计/美术设计(两条设计线)→ 写需求卡片 → 迭代编排 → 实现**;工程/文档设计/美术素材三类改动不走写卡与编排段,走「(如需设计讨论)→ 用户发令直改 → 主区直改+commit 点闸」(车道细则见 §1)。两层口径(2026-10-25 用户立):需求卡片=需求单位的实施文档,任何工作量皆可写、皆可编入迭代;工作量限制只属迭代层——迭代估时总量 <5 个工作日=「冻结待凑批」,不可开工。段间不自动流转,每段转进由用户发令;每段一个技能入口(五者均装于项目 `.zcode/skills/`:doc-design/asset-ingest/req-card/iter-plan/iter),登记不立技能(条目格式由流水线闸强制)。设计工作在会话内进行、用户主导、禁无监管自跑。
|
||||
**需求改动**(游戏代码,含随逻辑写/改的测试)按五段流水线走:**登记 → 文档设计/美术设计(两条设计线)→ 写需求卡片 → 迭代编排 → 实现**;工程/文档设计/美术素材三类改动不走写卡与编排段,走「(如需设计讨论)→ 用户发令 → 独立 worktree 直改 → 合回 CI」(车道细则见 §1)。两层口径(2026-10-25 用户立):需求卡片=需求单位的实施文档,任何工作量皆可写、皆可编入迭代;工作量限制只属迭代层——迭代估时总量 <5 个工作日=「冻结待凑批」,不可开工。段间不自动流转,每段转进由用户发令;每段一个技能入口(五者均装于项目 `.zcode/skills/`:doc-design/asset-ingest/req-card/iter-plan/iter),登记不立技能(条目格式由流水线闸强制)。设计工作在会话内进行、用户主导、禁无监管自跑。
|
||||
|
||||
| 段 | 入口技能 | 产出 | 出入口铁律 |
|
||||
|---|---|---|---|
|
||||
@@ -40,7 +40,7 @@
|
||||
3. **用户发开工令才动手**——需求卡片经用户批准(U0)后方开工
|
||||
|
||||
**环境与基线**
|
||||
4. **代码面批独立 worktree+拷导入缓存**——触及代码面的批次按 §1 建 worktree;先拷主区 `.godot/` 目录与字体 `.import` 边车再跑测试,否则全量重导入资源近似卡死。检出工作区零测试,直接开工(2026-10-22 频率规则);闸壳每次跑批先自检/自愈本区 user 目录隔离(§1 第 1 条),建不起来即拒跑;直改车道(非代码面)无此项
|
||||
4. **一切批独立 worktree+拷导入缓存**——按 §1 建 worktree;涉代码域跑闸或测试的批先拷主区 `.godot/` 目录与字体 `.import` 边车(纯文档批免拷),否则全量重导入资源近似卡死。检出工作区零测试,直接开工(2026-10-22 频率规则);闸壳每次跑批先自检/自愈本区 user 目录隔离(§1 第 1 条),建不起来即拒跑
|
||||
5. **涉数值改动先采改前读数**——与改后同随机种子配对比较并写明逐项比对口径;无数值改动禁跑模拟
|
||||
|
||||
**实施**
|
||||
@@ -48,8 +48,8 @@
|
||||
7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补
|
||||
|
||||
**完成**
|
||||
8. **合回后 CI 验证(worktree 批;主区直改小批的验收在 commit 点由 git 钩子执行,见 §1 第 1 条)**——主工作区 `git merge --no-ff <任务分支>` 落地后 post-merge 钩子自动跑全量域闸(不带参数档,02 全套件),判定与红项落 `game/tests/.gates/ci-status.json`。全量是唯一强制档:跨卡触面、探针与未申报套件的消费漏网只有全量闸能抓(迭代 44 实证),关联档选测的盲区由它兜底。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。该脚本是全部验证闸的**唯一入口、唯一清单与唯一域划分(含选闸算法与套件族映射表)**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。开发期手动跑批按需选档(按文件性质判域:代码面→`--code`,文档件→`--docs`,两类都有→全量;`--code` 关联档选测——02 只跑「需求卡片申报 ∪ diff 推导」并集套件、00 冒烟/01 系统测试/09 静态扫描三件保险恒跑、横切面回落全量——算法见闸脚本),手动跑不构成验收。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占 CI 全量——其质量义务=落批时人工确认闸可跑通且判据口径未变;闸真崩溃时 CI 判红在案(跑不出回执=verdict 红,fail-closed 语义保留)
|
||||
9. **重跑语义(2026-10-30 用户裁,取代原「每批一次/合并后零复跑」口径)**——同一份字节禁止第二次人手跑;允许的重跑只剩两类:① CI 红后的修复提交(post-commit 钩子自动追绿复验,每笔修复至多触发一轮);② 用户自发发起的全量回归。「跑都跑了再跑一遍保险」「顺手改点再补一跑」都不构成重跑理由。类名缓存刷新与开机确认由 CI 跑批起手接管(§1 第 2 条),合并后无手工动作
|
||||
8. **合回后 CI 验证(唯一强制验证点)**——主工作区 `git merge --no-ff <任务分支>` 落地后 post-merge 钩子自动跑全量域闸(不带参数档,02 全套件),判定与红项落 `game/tests/.gates/ci-status.json`。全量是唯一强制档:跨卡触面、探针与未申报套件的消费漏网只有全量闸能抓(迭代 44 实证),关联档选测的盲区由它兜底。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。该脚本是全部验证闸的**唯一入口、唯一清单与唯一域划分(含选闸算法与套件族映射表)**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。开发期手动跑批按需选档(按文件性质判域:代码面→`--code`,文档件→`--docs`,两类都有→全量;`--code` 关联档选测——02 只跑「需求卡片申报 ∪ diff 推导」并集套件、00 冒烟/01 系统测试/09 静态扫描三件保险恒跑、横切面回落全量——算法见闸脚本),手动跑不构成验收。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占 CI 全量——其质量义务=落批时人工确认闸可跑通且判据口径未变;闸真崩溃时 CI 判红在案(跑不出回执=verdict 红,fail-closed 语义保留)
|
||||
9. **重跑语义(2026-10-30 用户裁,取代原「每批一次/合并后零复跑」口径)**——同一份字节禁止第二次人手跑;允许的重跑只剩两类:① CI 红后的修复合回(post-merge 钩子复验,每轮修复至多触发一轮);② 用户自发发起的全量回归。「跑都跑了再跑一遍保险」「顺手改点再补一跑」都不构成重跑理由。类名缓存刷新与开机确认由 CI 跑批起手接管(§1 第 2 条),合并后无手工动作
|
||||
10. **批次完成后的登记义务**——合回 master 后按 doc-conventions §12.1 推进待办清单条目状态(做完整条删除),涉及迭代编排的在 roadmap 迭代总表与顶部「当前位」节换代——执行入口=项目技能 batch-closure(批后收尾与中间文档退役),跨会话教训写记忆库。批次过程与结论由 git 提交信息承载,禁止再写会话状态文件(见 doc-conventions 第 10 节)。`design/` 与根规则文件(`AGENTS.md`/`roadmap.md`/`待办清单.md`/`体验验证清单.md`)实现批禁写,见 §12
|
||||
11. **文档同步闸(实现批禁写文档)**——实现批**禁写 `design/` 整个目录与根规则文件**,**另禁写 `game/tests/README.md`(能力清单,归写卡段维护,test-conventions §8.9)**,要往外交代的东西一律落 `reports/`:实现报告 `reports/iter<N>-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务+实现决定记录——超白名单/超卡片明列范围事项逐条记「决了什么/为什么/代价/撤销方式」,全部按卡执行时只写一行「零拍板」)、GDD 反哺点清单 `reports/iter<N>-反哺点-<日期>.md`(每条写清哪个文件哪一节、改成什么、依据是什么)。设计权威文档(GDD/art-bible)**任何批都不直改**:用户在会话中逐点裁决后,由工程/文档设计改动批(直改类)写入 `design/`(执行入口=doc-design 技能),并把反哺条目从 `reports/` 清掉(吸收即死;退役执行=batch-closure 技能)。机械面文档(roadmap 行/术语表/README 工具注)同样归工程/文档设计改动批在合并前更新。反哺点未落地期间相关 GDD 节视为待反哺,读前先查 `reports/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注
|
||||
12. **实机目检归用户,只登记不阻塞**——真人检测项登记进实现报告目检总清单与体验验证清单即完成批内义务;禁把等目检当停工理由或完成前置
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
## 4. 验证时机(合回后本地 CI 制,2026-10-30 换代)
|
||||
|
||||
开发期窄测义务不变:每批开发中,本批新增/改动的验收测试自己跑绿即收口(卡内只测自己改的东西,process-conventions §6);主区小改孤跑验证后直提。全量验证归合回后的本地 CI:git merge 合回 master 触发 post-merge 钩子跑 `tools/run_all_gates.sh` 不带参数档(两域全量,02 全套件——跨卡触面与关联档选测的盲区由全量兜底),结果落 `game/tests/.gates/ci-status.json`;CI 红态下修复提交经 post-commit 钩子自动追绿。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
|
||||
开发期窄测义务不变:每批开发中,本批新增/改动的验收测试自己跑绿即收口(卡内只测自己改的东西,process-conventions §6)。全量验证归合回后的本地 CI:git merge 合回 master 触发 post-merge 钩子跑 `tools/run_all_gates.sh` 不带参数档(两域全量,02 全套件——跨卡触面与关联档选测的盲区由全量兜底),结果落 `game/tests/.gates/ci-status.json`;CI 红态下修复合回落地即由 post-merge 钩子复验追绿(修复走新开 `fix-<任务名>` 修复 worktree,process-conventions §1)。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
|
||||
行为探针使用随机化玩家行为(封印/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
|
||||
|
||||
## 5. 测试函数怎么写——验收清单条目的落码规范
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
| `术语表.md` | 全库专用术语的唯一对照表——危险格/安全格/同调位/RAP/GP/真视等定义+退役词对照(2026-10-11 建立,v1.23) |
|
||||
| `待办清单.md`(仓库根,不属本树) | 全项目待办事项的唯一登记处;各系统文档的「待办」节只留指路存根 |
|
||||
| `体验验证清单.md`(仓库根,不属本树) | 需要真人试玩观测的验证项登记处(与待办清单分工:待办清单是"要拍板的事",本篇是"要玩过才知道的事");每条注明结论回流路径 |
|
||||
| `08-Alpha版本标准.md` | Alpha 版本包含哪些东西的清单——里程碑 M3 的完成标准;只列条目不写内容,定义一律指路各权威文档(**已定稿 v1.20**,2026-10-13) |
|
||||
| `08-Alpha版本标准.md` | Alpha 版本包含哪些东西的清单——里程碑 M3 的完成标准;只列条目不写内容,定义一律指路各权威文档(**已定稿 v1.21**,2026-10-13) |
|
||||
|
||||
## systems/ 五个循环
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **一句话定位**:本文定义这个项目的 **Alpha 版本包含哪些东西**——它是里程碑 M3 的完成标准,也是判断"还差什么"的对照表。
|
||||
> **本文只列条目,不写内容**:每样东西是什么、规则怎么走,一律归各自的权威文档,本文只给指路链接。想知道某样东西的定义,请点链接,不要在本文里找解释。
|
||||
> **状态**:**已定稿(v1.20)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。
|
||||
> **状态**:**已定稿(v1.21)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。
|
||||
> **成文**:2026-10-13。
|
||||
|
||||
## 本文怎么用
|
||||
@@ -104,7 +104,7 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战
|
||||
| 开始覆盖层 | —— | 在役 |
|
||||
| 选档界面(3 存档位) | —— | 在役(迭代 33 卡③——空槽新档/有档进档/删档二次确认+摘要三项;2026-10-22 用户裁增行〔反哺 #8〕) |
|
||||
| 营地(天赋树 / 锻造工坊 / 秘宝匣 / 图鉴) | [camp](ux/camp.md) | 在役(场景图与七物件点选随营地交互重做列入 Alpha,见下行) |
|
||||
| 营地交互重做(五卡:存档制数据层/主菜单三入口/选档界面/营地场景图/Esc 浮窗与营地顶栏) | [camp](ux/camp.md)+[需求澄清](../../reports/需求澄清-营地交互重做-2026-10-18.md) | 部分在役(卡①②③ 已随迭代 33 实装合回,2026-10-22;卡④营地场景图 2026-10-21 用户令退回美术设计段,美术生成方案提案 2026-10-22 成文,余三个用户侧前置未销号:像素规格执行(Q6 甲过渡口径已裁)、点选反馈设计稿、参照物;卡⑤ Esc 浮窗随卡④ 代码波同行、未编排。2026-10-21 用户裁:五卡整体列入 Alpha。出口=五卡各自验收标准通过+营地屏用户目检通过) |
|
||||
| 营地交互重做(五卡:存档制数据层/主菜单三入口/选档界面/营地场景图/Esc 浮窗与营地顶栏) | [camp](ux/camp.md)+[需求澄清](../../reports/需求澄清-营地交互重做-2026-10-18.md) | 部分在役(卡①②③ 已随迭代 33 实装合回,2026-10-22;卡④营地场景图美术设计已闭合(样张过审 2026-10-31)、v3.0 现行有效卡重立,与卡⑤ Esc 浮窗同编迭代 47(待开工)。2026-10-21 用户裁:五卡整体列入 Alpha。出口=五卡各自验收标准通过+营地屏用户目检通过) |
|
||||
| 生涯页 | [生涯](systems/跨局循环/生涯.md) | 在役(期一) |
|
||||
| 关卡地图屏 | [level-map](ux/level-map.md) | 在役 |
|
||||
| 战斗屏 | [battle](ux/battle.md) | 在役 |
|
||||
@@ -135,7 +135,7 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战
|
||||
| 机器可读的呈现断言(对比度 / 结构) | ——(清单唯一出处=process-conventions 运行与验证节) | 在役 |
|
||||
| 分辨率两档(1280×800 / 1920×1080) | [HUD框架](systems/表现与支撑/HUD框架.md) | 在役 |
|
||||
| 绘制调用数达标 | —— | 在役 |
|
||||
| 真人试玩轮次 | [体验验证清单](../../体验验证清单.md) | 在役(义务维持;当前轮次未清:㉚/㉛ 未核销,迭代 34 三条目检项待登记) |
|
||||
| 真人试玩轮次 | [体验验证清单](../../体验验证清单.md) | 在役(义务维持;当前轮次未清=㉚–㊸ 各条待用户核销——迭代 32 起各批实机目检项登记不阻塞,迭代 42 无玩家可见改动未登记) |
|
||||
|
||||
---
|
||||
|
||||
@@ -157,7 +157,7 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战
|
||||
| 站桩帧动画 | [待办清单](../../待办清单.md) | 待做(列入 Alpha 定版前置清单:定版前完成最小版,路线预选拆件驱动;未完成则顺延 Beta;不占功能迭代) |
|
||||
| 全局纹理过滤设为邻近采样 | [待办清单](../../待办清单.md) | 在役(迭代 26 · 2026-10-14 入库:default_texture_filter=0+平滑渐变件三处显式 LINEAR 白名单,翻转面全枚举闭合) |
|
||||
| UI 字体(全局像素字,Fusion Pixel 单套单字重) | [美术圣经](../art/art-bible.md) §7.4 | 在役(2026-10-24 用户裁现状即终稿——拉丁沿用自带字形不另接专件、不上第二字重;信息层级手段=字号档差+墨色深浅) |
|
||||
| 战斗一屏样张(界面美术的终稿闸) | [美术圣经](../art/art-bible.md) §1.4 | 待做(Alpha 硬前置:站桩帧动画的定版前置与主角+三 Boss 重产都依赖它;出口=用户目检通过的战斗屏样张,并产出尺寸档/色板/明度档清单) |
|
||||
| 战斗一屏样张(界面美术的终稿闸) | [美术圣经](../art/art-bible.md) §1.4 | 部分在役(规格半已闭合=目标规格清单已落 art-bible 五张规格表〔2026-10-30 合回〕,五项实装定值与样张机检随迭代 43 入库;未结半=出口未达——方向稿用户目检(体验验证清单㊶)先行,样张整体过闸随其后。站桩帧动画的定版前置与主角+三 Boss 重产依赖照旧) |
|
||||
| UI 氛围层与九宫格切片观感修 | [待办清单](../../待办清单.md) | 部分在役(光柱硬边已修=连续 alpha 渐变;未结半=九宫格切片错位——Alpha 内做最小修复:核对素材尺寸,必要时重出九宫格素材,全套素材重出排 Beta;出口=结算屏与图例屏错位消失,渲染闸+用户目检通过) |
|
||||
| UI 元素细节修(滑轨填充 / 图标垫块 / 留白 / 开发件外泄) | [待办清单](../../待办清单.md) | 在役(迭代 26 · 2026-10-14 入库:①滑轨填充随迭代 25 注销;余②图标垫块明度差降档/③商店+营地布局修/④诊断钮迁调试浮窗 全落地) |
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
>
|
||||
> **兑付频率(先看这条,它是三条渠道的共同前提)**:奇物**不是打一场战斗给一份**。关内的普通战斗节点打完了什么也不给;一关之内奇物**只兑付一次**,触发点是**关底 Boss 被击败**——而按 [冒险结构](冒险结构.md) 的定义,打掉关底 Boss 恰好就等于"通过这一关",这两件事是同一个时刻,不是一条链上的两步。
|
||||
>
|
||||
> 状态:**已实现**(2026-10-04 双层 BD 实施批落地);现行为 v1.2。本文件是奇物的唯一定义文档。
|
||||
> 状态:**已实现**(2026-10-04 双层 BD 实施批落地);现行为 v1.3。本文件是奇物的唯一定义文档。
|
||||
>
|
||||
> 数值纪律:本文件只写概念、取值域与指路;每件给多少、效果是什么一律不进正文,事实源是 `data/tables/feats.tres` 与 `data/tables/adventure.tres`。
|
||||
|
||||
@@ -99,25 +99,25 @@
|
||||
|
||||
### 换图系(7 件,设计定稿,待实现)
|
||||
|
||||
换图系把「弃图刷新」从坏图逃生改成主动构筑行为。两件基座分别解决 RAP 的来源与价格;后续专长让成功刷新产生输出、生存或资源收益。七件不要求一次拿齐,不设强制先拿基座、集件标签或集件奖励。
|
||||
换图系把「弃图刷新」从坏图逃生改成主动构筑行为。两件基座分别解决 RAP 的来源与价格;后续专长让成功刷新产生输出、生存或 GP 资源收益。七件不要求一次拿齐,不设强制先拿基座、集件标签或集件奖励。
|
||||
|
||||
| 层 | 代号 | 规则 | 行为职责 |
|
||||
|---|---|---|---|
|
||||
| 基座 | 掘进储能 | 每次付费挖格后额外获得 RAP;安全格与危险格同口径 | 持续挖图也能准备刷新,不再必须少挖停手 |
|
||||
| 基座 | 折价换图 | 弃图刷新的 RAP 成本减半 | 同一份储备支持更多刷新 |
|
||||
| 输出 | 弃图轰击 | 成功刷新后,在本轮战斗段对全体存活敌人造成一次伤害 | 刷新成为直接进攻行为 |
|
||||
| 输出 | 换图蓄势 | 成功刷新攒层,层数有上限;下一次攻击附加全部层数对应的伤害后清零,战斗结束清空 | 连续换图蓄成一次单点爆发 |
|
||||
| 生存 | 换图庇护 | 成功刷新后,在本轮授予段获得护盾 | 用刷新预防后续伤害 |
|
||||
| 生存 | 弃图休整 | 成功刷新后,在本轮授予段回复生命,封顶生命上限 | 放弃当前图换取恢复 |
|
||||
| 资源 | 弃图回收 | 成功刷新后,按旧图探索进度在本轮授予段回收清图奖励 | 先探索再主动弃图变现 |
|
||||
| 基座 | 矿脉储能 | 每次付费挖格被受理后,额外获得 RAP;安全格与危险格同口径 | 持续挖图也能准备刷新,不再必须少挖停手 |
|
||||
| 基座 | 省力周转 | 弃图刷新的 RAP 成本减半 | 同一份储备支持更多刷新 |
|
||||
| 输出 | 崩壁冲击 | 成功刷新后,在本轮战斗段末对全体存活敌人造成一次固定伤害 | 刷新成为直接进攻行为 |
|
||||
| 输出 | 蓄力周转 | 成功刷新攒层,最多 3 层;本轮下一次主角攻击消费全部层数后清零,战斗结束不跨战保留 | 连续换图蓄成一次单点爆发 |
|
||||
| 生存 | 石层缓冲 | 本轮至少成功刷新一次后,主角每次受到伤害固定减少 2 点;不叠加 | 刷新形成当轮全局防御姿态 |
|
||||
| 生存 | 坑道小憩 | 每次成功刷新累计 1 点恢复,最多 3 点;本轮授予段合计回复生命,封顶生命上限 | 放弃当前图换取恢复 |
|
||||
| 资源 | 矿道红利 | 每次成功刷新固定获得 1 GP | 刷新动作自身带少量GP收益 |
|
||||
|
||||
共同规则:
|
||||
|
||||
- **双基座叠加**:掘进储能与折价换图可以同时持有,产 RAP 与成本减半分别生效;每轮刷新次数上限继续限频,不设互斥规则。
|
||||
- **成功才触发**:后续五件只认成功换图;刷新被拒绝时不产生效果。同一轮多次成功刷新按发生顺序逐次登记。
|
||||
- **轮末兑付**:刷新不新增结算段。群伤、护盾、回血与回收按[战斗结算](../战斗循环/战斗结算.md)的既有段序兑付,刷新瞬间不直接改这些战斗结果。
|
||||
- **回收看旧图**:弃图回收读取被放弃旧图的探索进度,不把旧图或新图判为清图;具体口径归[地图战斗资源](../战斗循环/地图战斗资源.md)。
|
||||
- **基线不变**:没有这些专长时,RAP 来源、刷新成本、清图奖励与刷新结果保持原规则。数值与稀有度归 `feats.tres`,落表前本节只作设计声明。
|
||||
- **双基座叠加**:矿脉储能与省力周转可以同时持有,产 RAP 与成本减半分别生效;每轮刷新次数上限继续限频,不设互斥规则。
|
||||
- **成功才触发**:后续五件只认成功换图;刷新被拒绝时不产生事实,也不给输出、生存或资源收益。同一轮多次成功刷新按发生顺序逐次登记。
|
||||
- **轮末兑付**:刷新不新增结算段。崩壁冲击走本轮战斗段末结账,石层缓冲在每次主角受伤时消费,坑道小憩与矿道红利走本轮授予段兑付。
|
||||
- **全局受伤面**:石层缓冲覆盖敌方攻击、危险格、错误封印资源格与地形造成的主角伤害;临时生命值不在本流派设计范围内。
|
||||
- **基线不变**:没有这些专长时,RAP 来源、刷新成本、清图奖励与伤害结果保持原规则。数值与稀有度归 `feats.tres`,落表前本节只作设计声明。
|
||||
|
||||
### 迁入登记(秘宝域迁出件;实装批落地后并入件表)
|
||||
|
||||
@@ -479,7 +479,7 @@
|
||||
11. 凭证拿到即开,不进持有集,玩家无法囤积——选中或买下的同一时刻就开专长三选一。
|
||||
12. 凭证带有计步保底:连续 5 次三选一展示未出现则第 6 次必出;计数跨奖励节点与商店共享,刷新后的重新展示计入次数,限购用满后保底不再触发。
|
||||
13. 被称为流派基座的专长必须能说明拿到前后的操作差异与新行为的持续资源来源;只有同一操作后的泛用数值增长,不得登记为基座。
|
||||
14. 换图系两件基座同时持有时都生效;后续五件只在成功刷新后触发,无专长基线不变;弃图回收按旧图探索进度结算,同一旧图至多回收一次。
|
||||
14. 换图系两件基座同时持有时都生效;后续五件只在成功刷新后触发,无专长基线不变;石层缓冲覆盖所有主角受伤路径且同轮不叠加,矿道红利按成功刷新次数固定获得 GP。
|
||||
|
||||
> 实装批落地前,现役代码按旧 27 件专长目录与旧资源成员在同框架下运行;新成员口径(27 件基础件表 / 凭证件表)自实装批起验。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 地图战斗资源
|
||||
|
||||
> 一句话:格面资源的产出、极性字典与清图奖励封装
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.2
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.3
|
||||
|
||||
## 设计目的
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
| defense 护甲 | ac_up 盾牌加护(AC 掷点阈值轴——2026-09-16 换装,不入池)——幅度/上限/权重见 `reward.tres` | off_guard 失衡(AC 掷点阈值轴负向——2026-09-18 换装,不入池、退出主角防御池)——幅度/上限见 `status_effects.tres` off_guard 行 |
|
||||
| heal 回血 | heal_minor(满血零兑付照旧)——威力/权重见 `reward.tres` | heal_backlash 直伤:战斗结算直接扣血,不经增益状态——威力见 `reward.tres` |
|
||||
| blast 群伤 | spark_aoe 全体存活敌各吃一笔——威力/权重见 `reward.tres` | enemy_alert 警觉:敌方全体护甲等级 +1/层(`status_effects.tres` alert 行)——见 `reward.tres` |
|
||||
| weaken 削弱 | weaken(敌方输出池;同名重复授予只刷新剩余次数——2026-09-18 续时定案)——幅度见 `status_effects.tres` weaken 行 | sapped(主角输出池)——幅度见 `status_effects.tres` sapped 行 |
|
||||
| weaken 削弱 | weaken(敌方输出池;同名重复授予只加时长)——幅度见 `status_effects.tres` weaken 行 | sapped(主角输出池)——幅度见 `status_effects.tres` sapped 行 |
|
||||
| action 行动点 | ap_up:下轮行动点 +1——见 `reward.tres` | ap_drain 迟滞:下轮行动点 −1——见 `reward.tres` |
|
||||
| gp 财货 | gp_gain GP 袋:战斗内 GP 缓冲 +power,战斗完成随 GP 掉落统一入钱包账本(兑付编排归[战斗结算](战斗结算.md)、账本归[冒险结构](../冒险循环/冒险结构.md))——威力/权重见 `reward.tres` | gp_loss 破财:战斗内 GP 缓冲 −power,weight=0 纯字典不参与摇号——见 `reward.tres` |
|
||||
| pierce 穿刺 | pierce_strike 穿刺弹:单目标克制直伤(attack_type=pierce 查克制矩阵,必中全额不掷点;目标 = 固定顺位最前存活敌)——威力/权重见 `reward.tres` | pierce_snare 穿刺陷阱:主角直伤,不经增益状态——威力见 `reward.tres` |
|
||||
@@ -158,29 +158,8 @@
|
||||
| 可配置可替换 | 内容 = 池行值;允许即时类(当场兑付,不入库) |
|
||||
| 图类型差异化是预留插槽 | 现行只有默认槽;结构位已留,启用走棋盘生成词表落定 |
|
||||
|
||||
持有弃图回收专长时,同一清图奖励对象也可按旧图探索进度部分回收;这不改变正常清图与清图奖励的定义,例外口径见下节。
|
||||
|
||||
举证:本节为封装与流程规则,无计算。
|
||||
|
||||
### 弃图回收:按旧图探索进度兑付(设计定稿,待实现)
|
||||
|
||||
弃图回收让玩家不必挖完最后几个安全格,也能把已经推进的探索换成一部分清图奖励。它只读取被放弃的旧图,不把旧图判为清图,也不把新图判为已清图。
|
||||
|
||||
旧图退役前记录三项读数:装板初始已开安全格数、装板初始未开安全格数、退役时已开安全格数。探索进度定义为:
|
||||
|
||||
```
|
||||
探索进度 =(退役时已开安全格数 − 装板初始已开安全格数)÷ 装板初始未开安全格数
|
||||
```
|
||||
|
||||
进度限制在 0~1。玩家付费挖开与连锁展开的安全格都真实推进探索,计入分子;装板时白送的初始格、封锁格与危险格不计入。没有新探索就刷新,进度为 0,不能获得回收奖励。
|
||||
|
||||
回收兑付的是旧图在装板期已经摇定的清图奖励对象,按探索进度取对应份额;具体比例、档位、取整与数值归调参。它只发基础奖励的进度份额:
|
||||
|
||||
- 不触发完美封印加倍,不产生清图事件,不执行正常清图的整板兑付。
|
||||
- 同一旧图只在成功退役时回收一次;新图不继承旧图探索进度。
|
||||
- 刷新被拒绝时旧图不退役,也不回收;成功后的兑付时机归[战斗结算](战斗结算.md)本轮授予段。
|
||||
- 正常清图仍发完整清图奖励对象;弃图回收不得让同等探索投入的收益无条件高于正常清图。
|
||||
|
||||
## 依赖与输出
|
||||
|
||||
本系统被两侧夹住:事实与数值从上游来,调用与呈现往下游去。下表就是删除任何一方时的影响面清单。
|
||||
@@ -260,9 +239,6 @@
|
||||
- 类型封闭与字典完整:表里出现九型之外的类型、或任一型缺正向/负向行,加载拒绝。
|
||||
- 未生效可见:满层增益、满血正向治疗、无存活敌的群伤,各自在结算明细记"奖励未生效"行,零折算、零补偿。
|
||||
- 加载护栏:池空、清图池无正当量、增益引用悬空——任一命中即加载时返回错误并中止;默认内容加载通过。
|
||||
- 弃图回收进度:付费挖开与连锁展开的安全格计入探索,初始格、封锁格与危险格不计;无新探索时进度为 0,不能获得回收奖励。
|
||||
- 弃图回收恰一次:成功退役的旧图按当次探索进度回收其预摇清图奖励对象,新图不继承进度,同一旧图不能重复回收;被拒绝的刷新零兑付。
|
||||
- 回收不是清图:弃图回收不触发完美封印加倍、清图事件或正常清图整板兑付;正常清图仍发完整清图奖励对象。
|
||||
- 表实一致:数据表字段与奖励表字段定义逐字段一致。
|
||||
|
||||
## 待办
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# 增益状态
|
||||
|
||||
> 一句话:增益/减益的状态池、叠层与衰减
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.2
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.3
|
||||
|
||||
## 设计目的
|
||||
|
||||
战斗里有一类效果不在当场一次性用掉,而要管上几次结算:挖开安全格拿到的主角增益、封印标中带来的怪物削弱、踩雷喂给怪物的增强(警觉——blast 型负向)、标错封印招来的负向兑付,都是这类。本文把它们统称"状态":发给主角的有益效果叫增益(失衡与乏力是例外——它们是发给主角的减益),发给敌人的负面效果叫减益;敌方侧的增强同样是状态——几个方向共用同一个状态池。
|
||||
|
||||
增益状态就是这一个状态池:它收下全部状态,用同一套规矩管理——发入、合并(同一种效果重复拿到时按表行策略处理:叠层加一,或只刷新剩余次数——读 `status_effects.tres` 逐行 stack_policy)、衰减(每次结算后剩余次数减一,减到零效果消失)、清空(战斗结束全部清除)。没有它,几类效果得各写一套计时逻辑,结算明细也无法逐行指回"这效果是我哪步棋带来的"。状态池管机制、不管数值从哪来:某个效果该多大,由各收益系统的表去定,状态池只照章入列、按次衰减。
|
||||
增益状态就是这一个状态池:它收下全部状态,用同一套规矩管理——发入、合并(同一种效果重复拿到时按表行策略处理:叠层加一,或把剩余次数累加上本次授予的时长——读 `status_effects.tres` 逐行 stack_policy)、衰减(每次结算后剩余次数减一,减到零效果消失)、清空(战斗结束全部清除)。没有它,几类效果得各写一套计时逻辑,结算明细也无法逐行指回"这效果是我哪步棋带来的"。状态池管机制、不管数值从哪来:某个效果该多大,由各收益系统的表去定,状态池只照章入列、按次衰减。
|
||||
|
||||
## 系统范围
|
||||
|
||||
@@ -76,14 +76,14 @@
|
||||
|
||||
举证:本节为授予路径与登记规则,无计算。
|
||||
|
||||
### 同名状态再拿到:叠层、刷新、并存
|
||||
### 同名状态再拿到:叠层、累加、并存
|
||||
|
||||
同一种状态还没消失又拿到一份,怎么合并由状态表每行的合并策略字段说了算,共三种。合并在授予那一刻由状态池完成;多个状态在结算里按什么先后起作用,是战斗结算的编排——两件事互不干扰。
|
||||
|
||||
| 合并策略 | 重复授予时发生什么 | 说明 |
|
||||
|---|---|---|
|
||||
| 叠加 | 层数加一;剩余结算次数不动——只有首次授予定钟 | 现行内容行多数用叠加(逐行合并策略读 `status_effects.tres`) |
|
||||
| 刷新 | 剩余结算次数重置为该实例首次授予时的初始值,层数不变 | 刷新类内容行已就位——削弱行 weaken(2026-09-18 续时定案)、增益技行 empower / fortify、**主角增益行 attack_up / ac_up(2026-09-20 用户拍板「只续时不叠层」,全状态表增益/减益两侧合并语义就此统一为:主角可重复获取的增益与减益一律续时、不叠层)**;逐行读 `status_effects.tres` |
|
||||
| 累加 | 剩余结算次数加上本次授予的时长——技能施放行带覆盖时长时按覆盖值加;层数不变 | 现行内容行六行用累加(削弱行 weaken、增益技行 empower / fortify、主角增益行 attack_up / ac_up);重复拿一次就多攒一段时长,同一轮拿几份攒几段,停手后按剩余次数逐轮耗完;逐行读 `status_effects.tres` |
|
||||
| 并存 | 新建一份独立实例,两份各算各的 | 同上 |
|
||||
|
||||
并存分支没有满层上限,但状态池规模天然有界:实例数的上界就是受理过的授予数——多受理一份就多一份实例,多少份在授予那一刻就完全确定,不会无限膨胀。
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
### 剩余次数怎么倒数:按结算次数衰减
|
||||
|
||||
每个状态实例自带一个倒数计数——剩余结算次数(本文说的"衰减"就是它逐次递减、归零消失)。它不承诺"活几轮",而是数"经历过几次轮末结算":每轮结算先让状态起作用,随后计数减一,减到零状态即被移除。持续 1 的状态就是"一次性":在授予它的那轮结算里生效一次,轮末消失。MVP 时期六行内容均为一次性(削弱后改续时——见 git 提交史;2026-09-20 起主角增益两行也走续时、duration 表值仍为 1——重复拿等于重新获得一次当轮增益);跨轮持续的状态,寿命由表行初始值表达,给几就活几次结算。
|
||||
每个状态实例自带一个倒数计数——剩余结算次数(本文说的"衰减"就是它逐次递减、归零消失)。它不承诺"活几轮",而是数"经历过几次轮末结算":每轮结算先让状态起作用,随后计数减一,减到零状态即被移除。持续 1 的状态就是"一次性":在授予它的那轮结算里生效一次,轮末消失。现行累加行里主角增益两行持续 1、削弱与敌方增益技行持续 2——累加语义下重复拿一次就按本次授予时长多攒一段,同一轮拿几份攒几段;跨轮持续的状态,寿命由表行初始值表达,给几就活几次结算。
|
||||
|
||||
```
|
||||
一轮结算:查询生效清单 → 逐行兑付(层数 × 行值)→ 轮末衰减(全部实例剩余次数 −1)→ 归零实例移除
|
||||
@@ -140,8 +140,8 @@
|
||||
|
||||
| 例子 | 状态池输出 | 消费侧读法 |
|
||||
|---|---|---|
|
||||
| 暴走叠两层 | +(2 × enrage 行幅度)(读表;越出单行取值域,原样输出) | 压在天花板 +100% 上:敌方输出乘区封顶 ×2(削弱已改续时——"叠两层压地板 −100% 归零"的读法随 2026-09-18 结构修复批退役) |
|
||||
| 主角盾牌加护再拿一份 | 层数恒 1、剩余结算次数重置(refresh——2026-09-20 主角增益续时批) | 不经任何池:掷点判定阈值 = 主角基准(读 hero 表)+ 层数(现行 +1——上限 2 层叠读取法退役,局内可达 AC 上限 11) |
|
||||
| 暴走叠两层 | +(2 × enrage 行幅度)(读表;越出单行取值域,原样输出) | 压在天花板 +100% 上:敌方输出乘区封顶 ×2(削弱非叠层行——"叠两层压地板 −100% 归零"的读法不成立) |
|
||||
| 主角盾牌加护再拿一份 | 层数恒 1、剩余结算次数累加本次授予的时长 | 不经任何池:掷点判定阈值 = 主角基准(读 hero 表)+ 层数(现行 +1——上限 2 层叠读取法退役,局内可达 AC 上限 11) |
|
||||
|
||||
状态池还有一条快照纪律:实例的幅度、初始次数、量纲在授予那一刻从表行拷贝。战斗中配置表即使被重载,已授予实例不受任何影响,只影响后续授予。
|
||||
|
||||
@@ -162,15 +162,15 @@
|
||||
|
||||
| 状态 | 效果一句话 | 发给谁 | 幅度(现行值) | 时限 / 合并 | 来源类别 |
|
||||
|---|---|---|---|---|---|
|
||||
| attack_up 增伤 | 主角攻击提升 | 主角 | 见 `data/tables/status_effects.tres` attack_up 行 | 时限/上限读表 / 刷新(2026-09-20 续时批 stack→refresh,层数恒 1) | 安全格 |
|
||||
| ac_up 盾牌加护 | 主角护甲等级提升(掷点折扣判定阈值——AC 轴,不入池) | 主角 | 见 `status_effects.tres` ac_up 行(2026-09-16 换装,原 defense_up 行已退役) | 时限/上限读表 / 刷新(2026-09-20 续时批 stack→refresh,层数恒 1) | 安全格 |
|
||||
| attack_up 增伤 | 主角攻击提升 | 主角 | 见 `data/tables/status_effects.tres` attack_up 行 | 时限/上限读表 / 累加(层数恒 1) | 安全格 |
|
||||
| ac_up 盾牌加护 | 主角护甲等级提升(掷点折扣判定阈值——AC 轴,不入池) | 主角 | 见 `status_effects.tres` ac_up 行(2026-09-16 换装,原 defense_up 行已退役) | 时限/上限读表 / 累加(层数恒 1) | 安全格 |
|
||||
| alert 警觉 | 敌方护甲等级 +1/层 | 敌方 | 见 `status_effects.tres` alert 行 | 1 结算 / 叠加读表 | 踩雷 / 标空封印(blast 型负向) |
|
||||
| weaken 削弱 | 敌方攻击被削弱(同名重复标中只刷新剩余次数、层数恒 1) | 敌方 | 见 `status_effects.tres` weaken 行(取值域 [60,85],取负生效) | 时限读表 / 刷新(2026-09-18 续时定案) | 封印标中 |
|
||||
| weaken 削弱 | 敌方攻击被削弱(同名重复标中只加时长、层数恒 1) | 敌方 | 见 `status_effects.tres` weaken 行(取值域 [60,85],取负生效) | 时限读表 / 累加 | 封印标中 |
|
||||
| enrage 暴走 | 敌方攻击提升 | 敌方 | 见 `status_effects.tres` enrage 行 | 时限/上限读表 / 叠加 | 标空封印反噬 / 踩雷(attack 型负向) |
|
||||
| off_guard 失衡 | 主角护甲等级降低(AC 轴——掷点判定阈值下调、更易被命中;2026-09-18 换装,原百分比承伤池已退) | 主角 | 见 `status_effects.tres` off_guard 行 | 时限/上限读表 / 叠加 | 标空封印反噬 / 踩雷(defense 型负向)/ 敌方妨害技(2026-09-19 新效应词汇批——蛛网束缚载体,duration 由技能行覆盖) |
|
||||
| sapped 乏力 | 主角输出降低(weaken 型负向,主角输出池) | 主角 | 见 `status_effects.tres` sapped 行 | 时限/上限读表 / 叠加 | 危险格负向 / 标空封印(2026-09-15 格面资源批)/ 敌方妨害技(大地脉动——L3 Boss 石君王独占,2026-09-20 第三关内容批) |
|
||||
| empower 蓄力 | 敌方输出倍率增益(敌方输出池——蓄力技载体;幅度读表) | 敌方 | 见 `status_effects.tres` empower 行 | duration 读表 = 1 个有效增益拍 / 刷新 | 敌方技能施放(2026-09-16 敌人技能池批) |
|
||||
| fortify 硬化 | 敌方防御提升(**敌方防御池**——硬化技载体;负值入池 = 主角攻击折半,2026-09-18 符号纠正——旧正值实际翻倍) | 敌方 | 见 `status_effects.tres` fortify 行 | duration 读表 = 1 个有效增益拍 / 刷新 | 敌方技能施放(2026-09-16 敌人技能池批) |
|
||||
| empower 蓄力 | 敌方输出倍率增益(敌方输出池——蓄力技载体;幅度读表) | 敌方 | 见 `status_effects.tres` empower 行 | duration 读表 = 1 个有效增益拍 / 累加 | 敌方技能施放(2026-09-16 敌人技能池批) |
|
||||
| fortify 硬化 | 敌方防御提升(**敌方防御池**——硬化技载体;负值入池 = 主角攻击折半,2026-09-18 符号纠正——旧正值实际翻倍) | 敌方 | 见 `status_effects.tres` fortify 行 | duration 读表 = 1 个有效增益拍 / 累加 | 敌方技能施放(2026-09-16 敌人技能池批) |
|
||||
|
||||
empower 与 fortify 是敌方技能池增益技在状态池侧的数据落点(技能行 buff_ref 引用,施放时长由技能行覆盖——技能冷却与增益持续是两个计时器):两行 duration 表值(读表)的口径是"先兑付后衰减含施放当轮"——施放发生在第 N 结算战斗段,存活到第 N+1 结算战斗段才兑付"下一拍",即"持续 1 个有效结算"(proposal 语义的状态池落地)。敌方防御池是第四个乘区池:敌方作为防守方的百分比修正池,消费面 = [战斗结算](战斗结算.md)主角攻击的池乘区——四池对称(敌打主角 = 主角防御池 × 敌方输出池,主角打敌 = 主角输出池 × 敌方防御池),状态池语义零延伸:仍是同构实例、side-wide 加算、不封顶不保底。
|
||||
|
||||
@@ -195,7 +195,7 @@ empower 与 fortify 是敌方技能池增益技在状态池侧的数据落点(
|
||||
|
||||
1. 战斗结算通知战斗开始:状态池初始化,空池进入可用状态。
|
||||
2. 轮末结算时,战斗结算把这一轮的扫雷事实兑换成授予:挖开安全格给主角上增益、封印标中削弱敌人、踩雷给敌方上增强、标空封印触发反噬——授予入口是唯一进货口。
|
||||
3. 状态池按表行合并策略受理(新建 / 叠一层 / 刷新),实例立即生效并携带归因记录。
|
||||
3. 状态池按表行合并策略受理(新建 / 叠一层 / 累加时长),实例立即生效并携带归因记录。
|
||||
4. 战斗结算查询生效清单,逐行兑付进结算公式(有效值 = 层数 × 行值)。
|
||||
5. 兑付完做轮末衰减:全部实例剩余次数减一,归零移除——先兑付、后衰减。
|
||||
6. 战斗外授予、未知状态、满层授予一律被拒且状态池不变;满层的"奖励未生效"行归战斗结算的结算明细。
|
||||
@@ -207,7 +207,7 @@ empower 与 fortify 是敌方技能池增益技在状态池侧的数据落点(
|
||||
|
||||
| 优先级 | 内容 | 后置原因 |
|
||||
|---|---|---|
|
||||
| P1 | 刷新、并存两类合并策略的后续内容行 | 语义已定义、状态池已承载;刷新类已有内容(empower/fortify 2026-09-16 敌人技能池批、weaken 2026-09-18 续时定案),并存仍空,首个并存内容行上线时顺带补验收 |
|
||||
| P1 | 累加、并存两类合并策略的后续内容行 | 语义已定义、状态池已承载;累加类已有内容(weaken/empower/fortify/attack_up/ac_up),并存仍空,首个并存内容行上线时顺带补验收 |
|
||||
| P1 | 清图奖励含增益的授予路径 | 来源类别已预留;内容与档位归[地图战斗资源](地图战斗资源.md)定稿 |
|
||||
| P1 | 单体寻址扩展位(接口已定稿——五条语义见核心规则〈单体寻址扩展位〉节) | 实现随首个单体效果的内容批进游戏,真实入口验收随该批闭合 |
|
||||
| P2 | 驱散 / 延时 / 转移接口 | 状态一旦生效,玩家没有任何手段摘掉、延后或挪给别人——省掉一整类界面复杂度是明确的设计决定;要加属于新增接口的修订,不是调参 |
|
||||
@@ -230,12 +230,12 @@ empower 与 fortify 是敌方技能池增益技在状态池侧的数据落点(
|
||||
| sapped 幅度 | 百分比 [−100,100] 且非 0 | percent 行 magnitude | 乏力;危险格负向 weaken 型,进主角输出修正池(2026-09-15 格面资源批补登记) |
|
||||
| empower 幅度 | 百分比 [−100,100] 且非 0 | percent 行 magnitude | 蓄力;敌方技能池增益技载体,进敌方输出修正池 |
|
||||
| fortify 幅度 | 百分比 [−100,100] 且非 0 | percent 行 magnitude | 硬化;敌方技能池增益技载体,进**敌方防御池**(负值 = 减伤方向——2026-09-18 符号纠正) |
|
||||
| 初始剩余次数 | 整数 [1,99] | duration_settlements | 一次性语义行逐行读表;续时行 = weaken(2026-09-18 定案,duration 2)+ empower/fortify(1 个有效增益拍——先兑付后衰减含施放当轮)+ **attack_up / ac_up(2026-09-20 主角增益续时批,duration 表值 1 维持——续时语义在 duration=1 下表现为重复拿重置当轮倒数;跨轮延续随将来 duration 拉长自然显形,数值归状态层重设计批)**;拉长 = 恢复跨轮延续、规划变简单 |
|
||||
| 叠层上限 | 整数 [1,16] | max_stack | 仅叠加策略消费;刷新行层数恒 1——weaken / attack_up / ac_up 表值上限在续时语义下不消费(2026-09-18 / 2026-09-20),empower/fortify ×1(冷却闸下不可能自叠加) |
|
||||
| 初始剩余次数 | 整数 [1,99] | duration_settlements | 累加行 = weaken(duration 2)+ empower/fortify(表值 2 = 先兑付后衰减含施放当轮的 1 个有效增益拍)+ attack_up / ac_up(duration 1);累加语义下重复拿一次就按本次授予时长加一段;拉长表值 = 每次授予攒更多段、规划变简单 |
|
||||
| 叠层上限 | 整数 [1,16] | max_stack | 仅叠加策略消费;累加行层数恒 1、表值上限不消费,empower/fortify ×1(冷却闸下不可能自叠加) |
|
||||
|
||||
非调参的冻结项:三类合并策略语义、两种量纲语义、来源类别枚举、"先兑付后衰减"时序、拒绝原子性、零随机——改动走本文修订流程,不走调参。
|
||||
|
||||
联动纪律:增伤与削弱是当量锚的两端;盾牌加护与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)的承伤预期联动(掷点折扣轴——AC 行值变更须复算生存链区间;2026-09-20 主角增益续时批后 ac_up 层数恒 1、局内可达 AC 上限 11,复算随调参批);削弱改续时后"单轮层数上限受[行动经济](../排雷循环/行动经济.md)行动点约束"的联动随之失效(2026-09-18 续时定案——同名重复标中只刷新剩余次数、层数恒 1;2026-09-20 起主角侧 attack_up / ac_up 同口径)。这些联动值禁止独立调参,修订须重跑锚对照并同步登记册。
|
||||
联动纪律:增伤与削弱是当量锚的两端;盾牌加护与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)的承伤预期联动(掷点折扣轴——AC 行值变更须复算生存链区间;ac_up 层数恒 1、局内可达 AC 上限 11,复算随调参批);削弱与主角增益行同名重复授予只加时长、层数恒 1,"单轮层数上限受[行动经济](../排雷循环/行动经济.md)行动点约束"的联动不成立。这些联动值禁止独立调参,修订须重跑锚对照并同步登记册。
|
||||
|
||||
## 验收标准
|
||||
|
||||
@@ -243,7 +243,7 @@ empower 与 fortify 是敌方技能池增益技在状态池侧的数据落点(
|
||||
- 多向同构:主角侧增益与减益、敌方侧增强与削弱共用同一套受理、合并、倒数、清除语义,不存在第二套计时逻辑。
|
||||
- 授予即生效:状态发入当轮结算即兑付第一次,无"待生效"中间态。
|
||||
- 只登记不去重:同一事实被转化两次授予,登记两层——去重责任在战斗结算。
|
||||
- 叠层不减钟:叠加策略行叠加只加层数,剩余次数保持首次授予定下的轨迹不变(刷新策略行则相反——层数不变、只重置剩余次数;两策略逐行读表)。
|
||||
- 叠层不减钟:叠加策略行叠加只加层数,剩余次数保持首次授予定下的轨迹不变(累加策略行则相反——层数不变、剩余次数加上本次授予的时长;两策略逐行读表)。
|
||||
- 满层拒绝原子且留痕:叠满后再授予返回失败、状态池逐字不变;结算明细多一行"奖励未生效"(含来源)。
|
||||
- 先兑付后衰减:每轮结算恰做一次衰减,归零实例当轮移除;停手轮、弃图刷新轮照常衰减。
|
||||
- 合成不设上下限:状态池输出的有效值恒等于层数 × 行值,越出百分比域不封顶不保底;地板在战斗结算侧。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 战斗结算
|
||||
|
||||
> 一句话:轮末结算的编排与逐行兑现
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.3
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.4
|
||||
|
||||
## 设计目的
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
| 判定行 | 胜 / 负 / 继续各一行;终局判定行同时是胜负画面的数据锚 |
|
||||
| 高光行 | 完美封印成立时一行,只记实际有效兑付 |
|
||||
|
||||
每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。
|
||||
每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。奖励直伤行的数值字段沿用 `effectiveness` 键名、值为整数点数——键名与量纲是数据导出与分析工具的兼容契约,改动须连动分析工具面。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。
|
||||
|
||||
任何一行找不到来源即断言失败——宁可返回错误,也不让"合并到看不出来源"的呈现混过数据层。但有些行天然没有棋盘来源,断言为此留了两层豁免,豁免集合是封闭清单,改动同样走本文修订。
|
||||
|
||||
@@ -268,21 +268,21 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
|
||||
|
||||
### 换图系专长:刷新事实与本轮兑付(设计定稿,待实现)
|
||||
|
||||
持有换图系后续专长时,成功刷新除执行上述换图编排外,还产生一次 `board_refreshed` 事实。旧图退役前保存它的探索进度与清图奖励对象身份;新板就位后登记事实。刷新被拒绝时不产生事实,任何后续效果都不触发。同一轮多次成功刷新按发生顺序逐次登记,不合并成一次。
|
||||
持有换图系后续专长时,成功刷新除执行上述换图编排外,还产生一次 `board_refreshed` 事实。事实只在新板装板成功后登记;刷新被拒绝时不产生事实,任何后续效果都不触发。同一轮多次成功刷新按发生顺序逐次登记,不合并成一次。
|
||||
|
||||
刷新只登记事实,不当场插入结算。各效果在既有五段内兑付:
|
||||
刷新只登记事实,不当场插入结算。各效果在既有五段与对应消费点兑付:
|
||||
|
||||
| 专长 | 兑付规则 |
|
||||
|---|---|
|
||||
| 弃图轰击 | 每次刷新事实开一张全体敌人伤害单据,在本轮战斗段末经伤害控制器统一结账;目标按结账时的存活状态解析 |
|
||||
| 换图蓄势 | 每次刷新事实当场累计一层,受表值上限约束;下一次主角攻击附加全部层数对应的伤害,随后清零;战斗结束清空 |
|
||||
| 换图庇护 | 每次刷新事实在本轮授予段经既有护盾通道授予一次,不新开挖掘期状态入口 |
|
||||
| 弃图休整 | 每次刷新事实在本轮授予段回复生命,按既有治疗规则封顶生命上限;满血时记未生效行 |
|
||||
| 弃图回收 | 每次刷新事实在本轮授予段按旧图探索进度回收其清图奖励对象;进度与奖励口径归[地图战斗资源](地图战斗资源.md) |
|
||||
| 崩壁冲击 | 每次刷新事实开一张全体敌人伤害单据,在本轮战斗段末经伤害控制器统一结账;目标按结账时的存活状态解析 |
|
||||
| 蓄力周转 | 每次刷新事实累计一层,最多 3 层;本轮下一次主角攻击消费全部层数对应的攻击加成,随后清零;战斗结束不跨战保留 |
|
||||
| 石层缓冲 | 每次刷新事实把当轮全局减伤状态置为生效;本轮主角每次受到伤害都固定减少 2 点,同一轮多次刷新不继续叠加 |
|
||||
| 坑道小憩 | 每次刷新事实累计 1 点恢复量,最多 3 点;本轮授予段合计回复生命,封顶生命上限,随后清零;满血时记未生效行 |
|
||||
| 矿道红利 | 每次刷新事实固定获得 1 GP,走战斗内 GP 缓冲并在授予段留痕;不按旧图探索进度折算,也不与清图奖励绑定 |
|
||||
|
||||
弃图轰击若击杀最后敌人,仍由本轮判定段按既有顺序判胜,不新增挖掘期即时胜利出口。换图系效果使用扩展行留痕:来源写明专长与被弃旧图,弃图轰击走伤害单据,护盾、回血与回收各保留自己的兑付记录;它们不指向单一棋盘格,使用明细流水的专长刷新效果来源豁免,不伪造来源格。
|
||||
全局受伤事件统一:`damage_taken` 是主角受到伤害的唯一效果事件,覆盖敌方攻击、危险格、错误封印资源格与地形造成的主角伤害。石层缓冲订阅该事件并在现行伤害下限之前消费;旧有订阅同一事件的专长也按这一完整语义生效。临时生命值不在此机制内。
|
||||
|
||||
弃图回收不是清图:不触发完美封印加倍,不发清图事件,不改变「刷新图不发清图奖励」。它兑的是被放弃旧图按探索进度回收的一部分奖励。
|
||||
崩壁冲击若击杀最后敌人,仍由本轮判定段按既有顺序判胜,不新增挖掘期即时胜利出口。换图系效果使用扩展行留痕:崩壁冲击走伤害单据,石层缓冲在受伤消费行体现减免,坑道小憩与矿道红利分别走治疗与 GP 入账记录。刷新事实来源不指向单一棋盘格,使用明细流水的专长刷新效果来源豁免,不伪造来源格。
|
||||
|
||||
战斗开始按固定序列开张:关上配置热重载的闸门、初始化状态池、掷骰定敌方实际数量、生成敌人、装板并预分配资源恰一次、变异布置([地形变异](../排雷循环/地形变异.md)——棋盘设置顺序第 4 步:生成棋盘 → 打开状态初始化 → 战斗资源格设置 → 变异格设置,消费 `variant_place` 封闭流)、发开轮通知并执行开轮摇号(摇定首轮各敌本拍动作)。上一关的大奖励(如血上限提升)经战斗开始入参的覆盖值通道生效,内容归[冒险结构](../冒险循环/冒险结构.md)。
|
||||
|
||||
@@ -379,8 +379,9 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
|
||||
- 行型封闭:流水行型只出现本文登记的基础 9 类与扩展行;行型词表改动必须走本文修订并同步呈现层行格式化,未登记行型禁止落行。
|
||||
- 伤害单据管线(2026-09-24):全部伤害(主角先手、敌方伤害技、棋盘克制直伤、群伤、反噬、地形变异)经伤害控制器单据管线兑现,兑付配方封闭五种;目标在结账时刻照规则解析;死亡事件由单位自行宣布——怪死其未结单据作废(零行、不进冷却不进保底计数)、主角死兑付终止;段界结账为现行口径、开单即结为回切结构位,两模式各自同种子同输入逐位复现。
|
||||
- 换图系刷新事实:成功刷新保存旧图探索进度并登记一次事实,被拒绝时不登记;同一轮多次刷新按发生顺序逐次兑付,刷新本身不新增结算段或轮次结束。
|
||||
- 换图系输出:弃图轰击在本轮战斗段末经伤害控制器结算;换图蓄势受层数上限约束,下一次主角攻击消费全部层数,战斗结束清空;群伤致敌清空时仍由本轮判定段判胜。
|
||||
- 换图系生存与回收:护盾、回血与弃图回收在本轮授予段兑付并留下可归因扩展行;回复封顶生命上限;回收不触发清图事件或完美封印加倍。
|
||||
- 换图系输出:崩壁冲击在本轮战斗段末经伤害控制器结算;蓄力周转受 3 层上限约束,本轮下一次主角攻击消费全部层数,战斗结束清空;群伤致敌清空时仍由本轮判定段判胜。
|
||||
- 换图系生存与资源:石层缓冲经全局 `damage_taken` 对敌方攻击、危险格、错误封印与地形伤害各减 2,同轮不叠加;坑道小憩在授予段按累计值回血并封顶;矿道红利每次成功刷新固定入账 1 GP。
|
||||
- 全局受伤事件:`damage_taken` 只在主角实际承伤消费点发射一次,所有伤害路径均经同一效果引擎减免面,禁止同一张单重复发射或只让部分伤害来源订阅生效。
|
||||
- 条款3 对账(2026-10-05 判式换代批 T3——与行动经济 F1 条款3 重立同步):①聚合健康式 (1−ρ̂)·E_dig(u) − ρ̂·V_mine(u) ≥ 0 与 β 比值带 [1.2, 2.5] 判读逐 u 检算(清图支配性审计为常设重跑项,读数快照登记归 clause3 重立条);②封印溢价兑付正确:封印标中正向兑付 = 同型正向 ×(1+δ)(δ 读 `settlement.tres` flag_hit_premium,100=无溢价直通零扰动),三类形态全覆盖(flat power / percent 幅度 / gp 缓冲)、标空与挖格兑付不乘溢价、危险格与安全格同池结构零触碰。
|
||||
|
||||
## 待办
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
| trigger(触发条件) | 全部,可省 | {fact, op, value, latch} 四键——fact 与 op 取「触发条件」节封闭词表,value 类型与域随 fact,出域加载期拒绝;缺省无字段=无条件技,旧行为零变化(2026-10-26 情境条件触发器批立列、2026-10-27 迭代 39 实装落地;原池条目的血量百分比字段收编为本字段闩型首用例) |
|
||||
| P1 字段位 | — | 命中段数、目标数——随对应后置批加列(触发条件位已由 trigger 立列收编——2026-10-26 立列、2026-10-27 实装;原"固定值分量"位已由 rider_mult 实装收编——2026-09-19;多段命中「命中段数」保留以防复活) |
|
||||
|
||||
普通攻击也是一行技能行,两条域校验锁死它的特殊性:倍率恒 1、冷却恒 0——想配倍率或冷却的就不是普攻,是伤害技。技能伤害存倍率、不存固定值:伤害 = 施放者攻击基线 × 技能倍率——同一行"重击",不同敌种按各自攻击基线缩放 = 基线 A × 技能倍率 M(行值读 enemy.tres / skills.tres),深层强化行自动缩放,这是共享技能表成立的前提;**固定的绝对值伤害不满足该前提**(不随基线缩放、跨关稀释——Brotato 教训),"固定值伤害"的合法形态是**必中附加分量 rider_mult**(×攻击基线的必中小倍率,2026-09-19 实装)。增益技带效果引用与持续回合,百分比天然按施放者同池生效,无缩放问题;妨害技同构,落点由状态行 target_side 路由到主角。
|
||||
普通攻击也是一行技能行,两条域校验锁死它的特殊性:倍率恒 1、冷却恒 0——想配倍率或冷却的就不是普攻,是伤害技。技能伤害存倍率、不存固定值:伤害 = 施放者攻击基线 × 技能倍率——同一行"重击",不同敌种按各自攻击基线缩放 = 基线 A × 技能倍率 M(行值读 enemy.tres / skills.tres),深层强化行自动缩放,这是共享技能表成立的前提;**固定的绝对值伤害不满足该前提**(不随基线缩放、跨关稀释——Brotato 教训),"固定值伤害"的合法形态是**必中附加分量 rider_mult**(×攻击基线的必中小倍率,2026-09-19 实装)。增益技带效果引用与持续回合,百分比天然按施放者同池生效,无缩放问题;妨害技同构,落点由状态行 target_side 路由到主角。技能伤害基线的取整:攻击基线 × 倍率按四舍五入、正好半格时一律向上取——全伤害管线唯一不用向下取整的点(半点上取保住低攻击档特殊技的辨识度:攻击 1 配 ×1.5 的突刺落到 2 而不是 1)。
|
||||
|
||||
池构成纪律(加载校验,违规拒绝入表):**每池恰一行普通攻击**(普攻冷却恒 0 → 可摇集合恒非空,"空池不可能"由结构保证,最坏情况怪物平砍等待——那是玩家的反打窗口而非死拍);**每池增益类技能 ≤1**(非 RPG,怪物连出不同增益显得呆);**每池妨害类技能 ≤1**(2026-09-19 新效应词汇批同构纪律);**每池至少一行不带触发条件的特殊技**(普攻不算——保底特殊技集合恒非空的结构保证,2026-10-26 触发条件批);池条目 skill_id 悬空致命;权重 > 0、冷却 ≥ 0。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 行动经济
|
||||
|
||||
> 一句话:每轮行动点怎么花、停手与刷新的代价
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.2
|
||||
> 状态:已定稿(自旧体系迁移);现行为 v1.3
|
||||
|
||||
## 设计目的
|
||||
|
||||
@@ -97,12 +97,12 @@
|
||||
|
||||
| 专长 | 规则 | 不变边界 |
|
||||
|---|---|---|
|
||||
| 掘进储能 | 每次付费挖格被受理后,额外获得表值 RAP;安全格与危险格同口径 | 连锁展开只随首格的一次付费动作结算,不逐格追加;封印、移动、刷新不产 RAP |
|
||||
| 折价换图 | 弃图刷新的 RAP 成本为基线的 50% | 只改价格;AP、轮次、每轮刷新上限与换图流程不变 |
|
||||
| 矿脉储能 | 每次付费挖格被受理后,额外获得表值 RAP;安全格与危险格同口径 | 连锁展开只随首格的一次付费动作结算,不逐格追加;封印、移动、刷新不产 RAP |
|
||||
| 省力周转 | 弃图刷新的 RAP 成本为基线的 50% | 只改价格;AP、轮次、每轮刷新上限与换图流程不变 |
|
||||
|
||||
两件基座可以同时持有并叠加:付费挖格照常产 RAP,刷新同时按半价扣费。两条规则作用在不同账户入口,不互相覆盖,也不设互斥。刷新仍须储备达到折后门槛才受理;储备不足或超过每轮次数上限时拒绝,状态不变。RAP 仍在战斗结束清零,刷新本身不返 RAP。
|
||||
|
||||
无掘进储能时,挖格不新增 RAP;无折价换图时,刷新成本仍读全局基值。后续输出、生存与资源专长如何使用成功刷新这个事实,归[战斗结算](../战斗循环/战斗结算.md)。
|
||||
无矿脉储能时,挖格不新增 RAP;无省力周转时,刷新成本仍读全局基值。后续输出、生存与资源专长如何使用成功刷新这个事实,归[战斗结算](../战斗循环/战斗结算.md)。
|
||||
|
||||
### 下轮行动点修正(格面资源八型批 2026-09-20)
|
||||
|
||||
@@ -249,8 +249,8 @@
|
||||
| move_ap_cost | int | 表值(冻结 0) | 移动免费——冻结,非调参项 |
|
||||
| chain_ap_cost | int | 表值(冻结 0) | 连锁免费——冻结,非调参项 |
|
||||
| refresh_cap_per_round | int | 表值(provisional,结构位预留) | 每轮刷新上限,开轮重置计数 |
|
||||
| (跨表)掘进储能产 RAP | int [1, 64] | 设计定稿,待入 `feats.tres` | 每次受理的付费挖格兑付一次;连锁不逐格追加 |
|
||||
| (跨表)折价换图成本率 | percent | 50%(结构已裁,待入 `feats.tres`) | 只改持有者的刷新价格;双基座叠加时不覆盖掘进储能 |
|
||||
| (跨表)矿脉储能产 RAP | int [1, 64] | 设计定稿,待入 `feats.tres` | 每次受理的付费挖格兑付一次;连锁不逐格追加 |
|
||||
| (跨表)省力周转成本率 | percent | 50%(结构已裁,待入 `feats.tres`) | 只改持有者的刷新价格;双基座叠加时不覆盖矿脉储能 |
|
||||
| (跨表)跨冒险行动点加成 | int [0,10] / int [0,99],冒险表 | adventure_table bonus_ap_flat / bonus_cap_ap(provisional) | 三选一 AP 件兑现值与全冒险次数上限;加成轴语义见「跨冒险行动点加成轴」节 |
|
||||
|
||||
字段名注记:2026-09-18 措辞完成批已全链对齐正式名——表字段与本文行名统一为 `refresh_cap_per_round`,刷新入口命名与表字段口径对齐(命名统一登记兑现,切片临时名零残留)。
|
||||
@@ -265,8 +265,8 @@
|
||||
- 仲裁唯一:最后 1 点行动点挖开最后一个安全格时,判清图(剩余清零 + 换图 + 清图奖励),不判耗尽;输出恰一条。
|
||||
- 停手 1:1:剩余 3 点停手,储备池加 3,下轮同图继续。
|
||||
- 刷新规则:储备不足时刷新被拒绝且状态不变;同一轮第 3 次刷新被拒绝;刷新不重置行动点、不发清图奖励、旧图上的封印印记失效。
|
||||
- 掘进储能:持有专长时,每次受理的付费挖格额外产一次 RAP,安全格与危险格同口径,连锁展开不逐格追加;无专长时挖格不新增 RAP。
|
||||
- 折价换图与双基座:持有折价换图时按基线的 50% 扣费;与掘进储能同时持有则两条规则都生效,刷新仍受储备门槛与每轮次数上限约束。
|
||||
- 矿脉储能:持有专长时,每次受理的付费挖格额外产一次 RAP,安全格与危险格同口径,连锁展开不逐格追加;无专长时挖格不新增 RAP。
|
||||
- 省力周转与双基座:持有省力周转时按基线的 50% 扣费;与矿脉储能同时持有则两条规则都生效,刷新仍受储备门槛与每轮次数上限约束。
|
||||
- 储备清零:战斗结束信号到达后储备池归 0,行动点进入休眠。
|
||||
- 跨字段校验:任一动作成本配置超过每轮预算时,加载期致命中止。
|
||||
- 零随机:同一动作序列驱动两个独立行动点实例,轮次结束记录与储备轨迹逐项相同。
|
||||
|
||||
+29
-12
@@ -93,11 +93,29 @@ func request_dig(chain_size: int, clears_map: bool) -> bool:
|
||||
_reject("phase")
|
||||
return false
|
||||
var cost := _cost("dig")
|
||||
# dig_paid 发射+施加(付费开掘发起、动作经济闸收对价前:
|
||||
# dig_paid 发射+施加(付费开掘发起、动作经济闸收对价前——施加单点 _apply_dig_paid_hits):
|
||||
# counter_spend 命中=尝试加收对价并积计数;资源不足走 fallback/耗尽即止=只付常规基础对价。
|
||||
# counter_add〔双管镐 付费挖格计数〕/ grant_ap〔每第 2 次返 1 AP——对价减免,
|
||||
# mod_eq 闸在行 when〕同面施加)
|
||||
var apply_res := _apply_dig_paid_hits(cost)
|
||||
cost = int(apply_res["cost"])
|
||||
if _ap < cost:
|
||||
_reject("resource_face")
|
||||
return false # 拒绝轮零入池(矿脉储能只在扣费受理后兑付——C2 成功才登记同款纪律)
|
||||
if int(apply_res["refund"]) > 0:
|
||||
cost = maxi(0, cost - int(apply_res["refund"])) # 返还=对价减免(净费不低于 0——免费开格不产生负对价)
|
||||
var accepted := _spend_cost_and_arbitrate(cost, clears_map)
|
||||
if accepted and int(apply_res["rap_gain"]) > 0:
|
||||
grant_reserve_ap(int(apply_res["rap_gain"])) # 每次受理的付费挖格产 RAP(一次性入池——每动作恰一挖,连锁不二次)
|
||||
return accepted
|
||||
|
||||
|
||||
# dig_paid 命中施加单点(迭代 46 卡A T3 自 request_dig 迁出——分支本体逐字保留:
|
||||
# counter_spend 加收对价并积计数/counter_add 施加〔双管镐 付费挖格计数〕/
|
||||
# grant_ap 对价减免〔每第 2 次返 1 AP——mod_eq 闸在行 when〕/grant_reserve_ap 矿脉储能累计;
|
||||
# 命中序=声明序不变。返回 {cost, refund, rap_gain} 交受理面消费)
|
||||
func _apply_dig_paid_hits(base_cost: int) -> Dictionary:
|
||||
var cost := base_cost
|
||||
var dig_refund := 0
|
||||
var rap_gain := 0
|
||||
if _fx != null:
|
||||
for h in _fx.dispatch(_ctx, "dig_paid", {"ap_cost": cost, "ap_surplus": _ap - cost}):
|
||||
if String(h.get("kind", "")) == "counter_spend":
|
||||
@@ -110,12 +128,9 @@ func request_dig(chain_size: int, clears_map: bool) -> bool:
|
||||
EffectEngine.counter_add(_ctx, String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
|
||||
elif String(h.get("kind", "")) == "grant_ap":
|
||||
dig_refund += int(h.get("value", 0))
|
||||
if _ap < cost:
|
||||
_reject("resource_face")
|
||||
return false
|
||||
if dig_refund > 0:
|
||||
cost = maxi(0, cost - dig_refund) # 返还=对价减免(净费不低于 0——免费开格不产生负对价)
|
||||
return _spend_cost_and_arbitrate(cost, clears_map)
|
||||
elif String(h.get("kind", "")) == "grant_reserve_ap":
|
||||
rap_gain += int(h.get("value", 0))
|
||||
return {"cost": cost, "refund": dig_refund, "rap_gain": rap_gain}
|
||||
|
||||
|
||||
func _spend_cost_and_arbitrate(cost: int, clears_map: bool) -> bool:
|
||||
@@ -196,13 +211,15 @@ func finish_round_stop(transfer: bool, transfer_pct: int = 100) -> void:
|
||||
# 轮内刷新:唯一入口 =
|
||||
# Active 相位——仅扣 RAP,相位与 AP 均不动。刷新不打断轮次、不触发结算;换图编排归 战斗结算
|
||||
# (retire + install 立即执行,玩家同轮继续挖新图)。决策主体 = 玩家(经 HUD框架发起)纪律不变。
|
||||
func request_refresh() -> bool:
|
||||
# cost_override=折后价入参(迭代 46 卡A T3——BattleRefreshFlow 折价读数传入;缺省 -1=表基线逐位不变)
|
||||
func request_refresh(cost_override: int = -1) -> bool:
|
||||
if _phase != Phase.ACTIVE:
|
||||
_reject("phase")
|
||||
return false
|
||||
if _rap < db.run.action_economy.rap_refresh_cost:
|
||||
var cost := int(db.run.action_economy.rap_refresh_cost) if cost_override < 0 else cost_override
|
||||
if _rap < cost:
|
||||
return false # EC13 资源不足拒绝——合法相位内资源拒绝,非编排错误
|
||||
_rap -= db.run.action_economy.rap_refresh_cost
|
||||
_rap -= cost
|
||||
return true
|
||||
|
||||
|
||||
|
||||
@@ -31,8 +31,9 @@ signal settlement_snapshot(snap: Dictionary) ## 每结算末尾的全量状态
|
||||
const SOURCE_EXEMPT_TYPES := ["decay", "verdict"]
|
||||
# 行来源断言豁免集合(来源类别层)——事实来源是单位 / 清图而非棋盘格;
|
||||
# fx_reveal=专长揭示掷格(落空行无真实格);
|
||||
# fx_grant_gp=专长·GP 入账(钱包面而非棋盘面,行无格子可指)
|
||||
const SOURCE_EXEMPT_CLASSES := ["hero_attack", "enemy_action", "clear_reward", "fx_reveal", "fx_grant_gp"]
|
||||
# fx_grant_gp=专长·GP 入账(钱包面而非棋盘面,行无格子可指);
|
||||
# fx_board_refresh=成功刷新事实族(迭代 46 卡A——崩壁冲击群伤行源=换图动作而非棋盘格)
|
||||
const SOURCE_EXEMPT_CLASSES := ["hero_attack", "enemy_action", "clear_reward", "fx_reveal", "fx_grant_gp", "fx_board_refresh"]
|
||||
|
||||
var _facts: BattleFacts # 战斗事实件(battle_facts.gd——事实族 15 成员单点)
|
||||
var _rounds: RoundCycle # 轮循环驱动件(settlement/round_cycle.gd——五段持有/段序/重入闸/摇号)
|
||||
@@ -596,26 +597,17 @@ func _exit_distribution() -> void:
|
||||
round_started.emit(round_index)
|
||||
|
||||
|
||||
# 呈现层查询面(HUD 刷新按钮可用性)——挖掘期唯一通道
|
||||
# 呈现层查询面(HUD 刷新按钮可用性)——挖掘期唯一通道(折价成本同源:判据归 BattleRefreshFlow)
|
||||
func can_refresh() -> bool:
|
||||
return battle_result == "" \
|
||||
and _facts.refresh_used < int(db.run.action_economy.refresh_cap_per_round) \
|
||||
and action_economy.phase == action_economy.PHASE_ACTIVE \
|
||||
and action_economy.rap >= int(db.run.action_economy.rap_refresh_cost)
|
||||
return BattleRefreshFlow.can_refresh(self)
|
||||
|
||||
|
||||
# 玩家经 HUD框架发起、战斗结算 代理调用(禁止 RAP 满自动刷)。
|
||||
# 挖掘期唯一通道:Active 相位立即换图
|
||||
# 继续挖(RAP -8;AP 保留、相位不动、不触发结算);非挖掘期请求一律拒绝——非清图轮恒同图。
|
||||
# 挖掘期唯一通道:Active 相位立即换图继续挖(RAP 按折后价扣;AP 保留、相位不动、不触发结算);
|
||||
# 非挖掘期请求一律拒绝——非清图轮恒同图。刷新门/折价扣费/换图/成功事实归 BattleRefreshFlow
|
||||
# (迭代 46 卡A T3 拆出——编排器入口与唯一通道不变,C10 结构预算只降不升)。
|
||||
func player_request_refresh() -> bool:
|
||||
if not can_refresh():
|
||||
return false
|
||||
if not action_economy.request_refresh():
|
||||
return false
|
||||
_facts.refresh_used += 1
|
||||
_reward_economy.retire_mapping() # 旧图批次退役(地图战斗资源 Ready→retired;E6 新批重置前提)
|
||||
minesweeper.retire_board(true) # 旧板退役(轮内通道)
|
||||
return _install_and_reset(true) # 当场换图——失败即编排违例 fail-fast
|
||||
return BattleRefreshFlow.execute(self)
|
||||
|
||||
|
||||
func _battle_over(result: String) -> void:
|
||||
|
||||
@@ -460,8 +460,8 @@ func _hero_attack_deliver(t: Dictionary, ctx: Dictionary, redemption: Dictionary
|
||||
# 敌方伤害技:掷点 → 折扣/暴击 → 克制点数(attack_type vs 主角护甲类型——
|
||||
# 无类型恒中性 delta 0,写法同 hero_attack 的 _counter_delta 消费位)→ hero_defense×enemy_output
|
||||
# 池乘区 → 下限 → +rider(后置必中附加)→ 交付 → commit_action(作废单不 commit——死亡即不动手)。
|
||||
# 掷点算术归 _enemy_roll;damage_taken 施加面归 _enemy_shield_apply(发射在本函数——
|
||||
# 与减伤落快照的先后序固定)。
|
||||
# 掷点算术归 _enemy_roll;damage_taken 统一发射+消费归 _emit_hero_damage_taken(发射在本函数——
|
||||
# 与减伤落快照的先后序固定;「掷点后、交付前」消费时点不变)。
|
||||
func _resolve_enemy_skill(t: Dictionary) -> void:
|
||||
var hero: Dictionary[Variant, Variant] = units.hero_unit()
|
||||
var roll := _enemy_roll(t)
|
||||
@@ -469,9 +469,8 @@ func _resolve_enemy_skill(t: Dictionary) -> void:
|
||||
# damage_taken 发射(kind=enemy_skill;铁壁整备减伤订阅面:shield 加法族合计 value×per(charge_layers),
|
||||
# 稳健拓荒树规则同面(rebuild 合成订阅);减后过下限保底。damage_reduce〔背水 hp_ratio when〕/
|
||||
# counter_add〔保险丝/石肤〕/ac_bonus〔石肤〕同面施加;hp_ratio fact 由 _fx_fact 补充事实面回落提供)
|
||||
var dt_hits := _fx_hits("damage_taken", {"kind": "enemy_skill", "amount": total,
|
||||
"source": String(t.context.get("skill_id", "")), "round": int(t.round_index)})
|
||||
total = int(_enemy_shield_apply(dt_hits, total)["total"])
|
||||
var dt_res := _emit_hero_damage_taken(total, "enemy_skill", String(t.context.get("skill_id", "")), t.origin_cell, int(t.round_index))
|
||||
total = int(dt_res["total"])
|
||||
units.apply_damage(hero, total)
|
||||
var payload: Dictionary[Variant, Variant] = {"target": "hero", "skill_id": String(t.context.get("skill_id", "")), "baseline": int(t.context.get("baseline", 0)),
|
||||
"roll": int(roll["roll"]), "ac": int(roll["threshold"]), "tier": int(roll["discount"]), "attack_type": String(t.attack_type)}
|
||||
@@ -502,9 +501,22 @@ func _enemy_roll(t: Dictionary) -> Dictionary:
|
||||
return {"roll": int(roll_read.roll), "threshold": threshold, "crit": crit, "discount": discount, "total": total}
|
||||
|
||||
|
||||
# damage_taken 施加面(shield 加法族合计;damage_reduce 逐条减量〔背水〕;ac_bonus 转编排器单点
|
||||
# 〔石肤 AC 累积归 set_hero_ac_override 消费面〕;counter_add 施加)。返回 {total, shield}。
|
||||
func _enemy_shield_apply(hits: Array, total: int) -> Dictionary:
|
||||
# 全局受伤发射单点(迭代 46 卡A T2——所有主角承伤路径唯一发射口:敌方攻击/地形/危险格/错误封印
|
||||
# 资源直伤(后三者经 board_flat_hero 单据进入)都经此 dispatch 一次 damage_taken 并消费一次;
|
||||
# 同一伤害单据重复发射由 context.hero_damage_consumed 标记闸拦(地形路径在开单点标记)。
|
||||
# payload 必含 kind/amount/source/cell/round/hp_ratio;返回 {total, hits} 交调用侧按减后值开单/交付)。
|
||||
func _emit_hero_damage_taken(amount: int, damage_kind: String, source: String, cell: Vector2i, ri: int) -> Dictionary:
|
||||
var hu: Dictionary[Variant, Variant] = units.hero_unit()
|
||||
var payload: Dictionary[Variant, Variant] = {"kind": damage_kind, "amount": amount, "source": source,
|
||||
"cell": cell, "round": ri, "hp_ratio": int(round(100.0 * float(int(hu.get("hp", 0))) / float(maxi(1, int(hu.get("max_hp", 1))))))}
|
||||
var hits := _fx_hits("damage_taken", payload)
|
||||
return {"total": int(_apply_hero_damage_effects(hits, amount)["total"]), "hits": hits}
|
||||
|
||||
|
||||
# damage_taken 唯一消费族(组合次序冻结:shield 加法族合计→damage_reduce 逐条减量〔背水/石层缓冲〕→
|
||||
# ac_bonus 转编排器单点〔石肤 AC 累积归 set_hero_ac_override 消费面〕→counter_add 施加〔保险丝/石肤/
|
||||
# 换图系临时计数夹具〕。返回 {total, shield})。
|
||||
func _apply_hero_damage_effects(hits: Array, total: int) -> Dictionary:
|
||||
var shield := 0
|
||||
for h in hits:
|
||||
match String(h.get("kind", "")):
|
||||
@@ -565,9 +577,15 @@ func _resolve_board_blast(t: Dictionary) -> void:
|
||||
_outcomes[int(t.ticket_id)] = "redeemed"
|
||||
|
||||
|
||||
# 棋盘主角直伤(反噬/治疗包负向/地形变异):无类型必中,下限保底;context 键并入行载荷
|
||||
# 棋盘主角直伤(反噬/治疗包负向/危险格/错误封印资源直伤):无类型必中,下限保底;context 键并入行载荷。
|
||||
# damage_taken 全局发射点(迭代 46 卡A T2——单据未标 hero_damage_consumed 时在下限前发射并消费一次;
|
||||
# 地形路径已在授予段开单点发射并标记,此处跳过防重复)
|
||||
func _resolve_board_flat_hero(t: Dictionary) -> void:
|
||||
var dealt: int = maxi(int(db.combat.settlement.damage_roll.damage_floor), int(t.base_value)) # 伤害下限全来源
|
||||
var dealt: int = int(t.base_value)
|
||||
if not bool((t.get("context", {}) as Dictionary).get("hero_damage_consumed", false)):
|
||||
var res_flat := _emit_hero_damage_taken(dealt, "board_flat_hero", String(t.get("source_class", "")), t.origin_cell, int(t.round_index))
|
||||
dealt = int(res_flat["total"])
|
||||
dealt = maxi(int(db.combat.settlement.damage_roll.damage_floor), dealt) # 伤害下限全来源(减后过下限)
|
||||
units.apply_damage(units.hero_unit(), dealt)
|
||||
var extra: Dictionary[Variant, Variant] = {"target": "hero"}
|
||||
for k in t.context.keys():
|
||||
|
||||
@@ -12,11 +12,15 @@ extends RefCounted
|
||||
const EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "attack_commit", "clamp_check",
|
||||
"armor_roll", "kill", "damage_taken", "enemy_hp_threshold", "round_start", "seal_settle",
|
||||
"round_end", "reward_roll", "treasure_used", "charge_full", "dig_stop", "battle_won", "seal_missed",
|
||||
"board_installed"]
|
||||
"board_installed",
|
||||
# 换图系双事件(refresh_request=玩家请求刷新〔省力周转 apply_discount 订阅面——折扣只改门槛
|
||||
# 与扣费不改拒绝判据〕;board_refreshed=成功刷新事实〔换图系七件订阅主挂点——装新板后才发射〕)
|
||||
"refresh_request", "board_refreshed"]
|
||||
|
||||
## 扫雷侧事件集(🔴 流派扫雷触发铁律新形态:每流派 ≥1 行订阅本集事件——schema 加载校验。
|
||||
## 原 MINE_HOOKS 的同义迁移:挖掘/封印/轮末结算面事件)
|
||||
const MINE_EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "seal_settle", "round_end", "reward_roll"]
|
||||
## 原 MINE_HOOKS 的同义迁移:挖掘/封印/轮末结算面事件+轮内刷新面〔换图系〕)
|
||||
const MINE_EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "seal_settle", "round_end", "reward_roll",
|
||||
"refresh_request", "board_refreshed"]
|
||||
|
||||
## 效果类型词汇(解释器 switch 闭集——词表实数以 EFFECT_KINDS 常量为准,含共享行拆型:
|
||||
## grant_gp/bias_wallet、counter_add/counter_spend、reveal_tiles/remove_mines/refresh_pick、
|
||||
@@ -40,7 +44,11 @@ const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open
|
||||
"mine_count_preview",
|
||||
# forgive_seal_miss=完美保险(本场首次封印落空不计入完美
|
||||
# 封印判定——订阅 seal_missed 的豁免效果,消费点在授予段;feats.tres 首例 domain=battle 行)
|
||||
"forgive_seal_miss"]
|
||||
"forgive_seal_miss",
|
||||
# 换图系两效果(grant_reserve_ap=矿脉储能·付费挖格产 RAP〔消费点在行动经济 dig_paid
|
||||
# 受理后一次性入池〕;apply_discount=省力周转·刷新成本折扣〔mode=refresh cost_mult 百分比,
|
||||
# floor 取整——只改门槛与扣费、不改拒绝判据〕)
|
||||
"grant_reserve_ap", "apply_discount"]
|
||||
|
||||
## fact 条件词汇(封闭枚举——payload 同名键直读面〔fact 取值序 payload
|
||||
## 优先——effect_engine._fact_value 既有机制〕。new_resource_type=首开资源类型〔地质学家〕;
|
||||
|
||||
@@ -365,6 +365,12 @@ func outcome_of(ticket_id: int) -> String:
|
||||
return "redeemed" if ticket_id < 0 else damage.outcome(ticket_id)
|
||||
|
||||
|
||||
# 延迟单据入队(迭代 46 卡A T4——成功刷新的崩壁冲击群伤单走案C 同队列:授予段闸外唯一入口,
|
||||
# 战斗段末 _board_deferred_settle 按开单序补提交统一结账;类变量零增员——复用 defer.queue)
|
||||
func defer_ticket(t: Dictionary) -> void:
|
||||
(defer.queue as Array).append(t)
|
||||
|
||||
|
||||
# 主角直伤单据(反噬/治疗包负向——无类型必中,下限保底在控制器管线内)
|
||||
func _submit_flat_hero(display: String, power: int, att: Dictionary, sync: bool) -> String:
|
||||
var t := damage.open_ticket(DamageController.KIND_BOARD_FLAT_HERO, String(att.get("source_class", "")), display,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
class_name BattleRefreshFlow
|
||||
extends RefCounted
|
||||
## 换图刷新流程件(迭代 46 卡A T3/T4 自编排器拆出):刷新可用性门、折价扣费、换图执行与成功事实登记。
|
||||
## 拆分边界(需求卡片 C13):本件只负责可用性、扣费、换图与成功事实登记——七件效果的算法留在
|
||||
## 效果引擎、授予段与伤害控制器。调用路径=呈现层→编排器单行转发→本件→行动经济/装板壳/授予段。
|
||||
## 反自动刷新(C11):只经玩家入口发起,禁 RAP 满自动刷——编排器公开面单行转发,无自动调用点。
|
||||
## 成功序钉死(T4):折价扣 RAP→refresh_used+1→旧资源退役→旧板退役→装新板→授予段成功事实发射;
|
||||
## 装板失败返回 false 且零效果——成功事实只在新板就位后发射。
|
||||
|
||||
|
||||
## 折价成本读数(refresh_request 命中省力周转 apply_discount——只认 kind==apply_discount 且
|
||||
## mode==refresh,取声明序第一命中,floor(base×cost_mult/100);无命中=表基线逐位不变。
|
||||
## can_refresh 与 execute 同源取数〔V3——can 与执行同源判断〕;折扣只改变门槛与扣费,
|
||||
## 不改变拒绝判据〔C2——每轮上限与相位判据照旧〕)
|
||||
static func _effective_refresh_cost(oc: BattleOrchestrator) -> int:
|
||||
var base := int(oc.db.run.action_economy.rap_refresh_cost)
|
||||
for h in oc.fx_host().fx_emit("refresh_request", {"mode": "refresh", "base": base}):
|
||||
if String(h.get("kind", "")) == "apply_discount" and String(h.get("mode", "")) == "refresh":
|
||||
return int(floor(float(base) * float(int(h.get("cost_mult", 100))) / 100.0))
|
||||
return base
|
||||
|
||||
|
||||
## 可用性门(HUD 刷新按钮同源判据):战斗未终局、每轮上限未满、Active 相位、RAP 抵折后价。
|
||||
static func can_refresh(oc: BattleOrchestrator) -> bool:
|
||||
return oc.battle_result == "" \
|
||||
and oc._facts.refresh_used < int(oc.db.run.action_economy.refresh_cap_per_round) \
|
||||
and oc.action_economy.phase == oc.action_economy.PHASE_ACTIVE \
|
||||
and oc.action_economy.rap >= _effective_refresh_cost(oc)
|
||||
|
||||
|
||||
## 执行(玩家请求刷新唯一通道体):扣费受理后继续;扣费拒绝/门拒零效果零事实。
|
||||
static func execute(oc: BattleOrchestrator) -> bool:
|
||||
if not can_refresh(oc):
|
||||
return false
|
||||
if not oc.action_economy.request_refresh(_effective_refresh_cost(oc)):
|
||||
return false
|
||||
oc._facts.refresh_used += 1
|
||||
oc._reward_economy.retire_mapping() # 旧图批次退役(地图战斗资源 Ready→retired;E6 新批重置前提)
|
||||
oc.minesweeper.retire_board(true) # 旧板退役(轮内通道)
|
||||
if not oc._install_and_reset(true): # 当场换图——失败即编排违例 fail-fast(零成功事实)
|
||||
return false
|
||||
oc._rounds._grant_seg.apply_board_refreshed(oc.round_index) # 成功事实:新板就位后一次发射
|
||||
return true
|
||||
@@ -0,0 +1 @@
|
||||
uid://d2kjxlt5b2eqv
|
||||
@@ -6,7 +6,8 @@ extends RefCounted
|
||||
# 效果施加归 BattleFxHost(段持三引用直调,零转发壳)——
|
||||
# 本段只搬运时序,零算法改动(🔴 零行为变更契约:同种子完整局输出逐位一致)。
|
||||
# run 编排骨架+批私有族(_reveal_batch/_terrain_batch/_seal_batch/_round_end_apply,段内施加面
|
||||
# 再拆 _reveal_safe_apply/_reveal_mine_apply/_terrain_damage_reduce/_seal_hit_effects 等单面函数);
|
||||
# 再拆 _reveal_safe_apply/_reveal_mine_apply/_seal_hit_effects 等单面函数);地形 damage_taken
|
||||
# 消费随迭代 46 卡A T2 并入伤害控制器全局消费族(本段零本地减伤函数);
|
||||
# kind 分派单点化(P1-1 同批):counter_add 五位三行组 / grant_material 三位兑付块
|
||||
# 收 _apply_counter_hit / _apply_material_hit 两助手(分支本体逐字保留在助手内)。
|
||||
|
||||
@@ -32,6 +33,27 @@ func run(ri: int) -> void:
|
||||
_round_end_apply(ri)
|
||||
|
||||
|
||||
# 成功刷新事实发射+施加(迭代 46 卡A T4——BattleRefreshFlow 装新板后单点调用,每成功刷新恰一次;
|
||||
# 拒绝刷新零事实〔C2〕。命中消费三面:counter_add→既有单点落账〔蓄力周转/石层缓冲/坑道小憩 计数〕;
|
||||
# grant_gp→战斗内缓冲 escrow 入账+fx_grant_gp 行〔矿道红利——不绑清图奖励,C7〕;
|
||||
# open_ticket channel=blast→崩壁冲击群伤单延迟入队〔案C 同队列,战斗段末按存活目标结账〕)
|
||||
func apply_board_refreshed(ri: int) -> void:
|
||||
var br_hits := fx_host.fx_emit("board_refreshed", {"round": ri})
|
||||
for h in br_hits:
|
||||
if String(h.get("kind", "")) == "counter_add":
|
||||
_apply_counter_hit(h)
|
||||
for h in br_hits:
|
||||
if String(h.get("kind", "")) == "grant_gp":
|
||||
reward_grant.escrow += int(h.get("value", 0))
|
||||
oc._emit_row({"type": "effect", "source_class": "fx_grant_gp", "origin_cell": Vector2i(-1, -1)}, ri, "专长·GP 入账 +%d" % int(h.get("value", 0)), int(h.get("value", 0)), {"effect_id": "fx_grant_gp", "escrow": reward_grant.escrow})
|
||||
for h in br_hits:
|
||||
if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "blast":
|
||||
var bb_t := oc._damage.open_ticket(DamageController.KIND_BOARD_BLAST, "fx_board_refresh", "崩壁冲击",
|
||||
{"channel": "board", "base_value": int(h.get("value", 0)), "target_rule": DamageController.TARGET_ALL_ALIVE,
|
||||
"ri": ri, "origin_cell": Vector2i(-1, -1)})
|
||||
reward_grant.defer_ticket(bb_t)
|
||||
|
||||
|
||||
# 开格/踩雷兑付批(轮 facts_reveals 资源事件序:safe 正向乘区兑付 / mine_hit 减半负向兑付)
|
||||
func _reveal_batch(ri: int) -> void:
|
||||
for evt in oc._facts.reveals:
|
||||
@@ -167,37 +189,22 @@ func _terrain_batch(ri: int) -> void:
|
||||
if String(vrow.get("effect", "")) != "flat_damage":
|
||||
continue # 触发词表按 effect 路由:flat_damage=on_open 兑现;hide_number/on_open 外组合 = 数据行新词表未接线(显式忽略面)
|
||||
# 地形变异伤害单据——无类型必中,下限保底在控制器管线内
|
||||
# damage_taken 发射在单据开立前:damage_reduce〔背水——hp_ratio when
|
||||
# 面〕先收集再按减后值开单;counter_add〔保险丝/石肤〕+ ac_bonus〔石肤〕照常施加;
|
||||
# grant_material〔荆棘/地脉〕移到单据提交后(兑付值序一致——收益不因减伤变化)
|
||||
# damage_taken 统一发射(迭代 46 卡A T2——地形路径并入全局消费族 _emit_hero_damage_taken:
|
||||
# 发射在单据开立前、减后值开单,组合消费含 shield〔全局受伤语义〕;
|
||||
# hero_damage_consumed 标记入单据 context——战斗段末 _resolve_board_flat_hero 跳过重复发射;
|
||||
# grant_material〔荆棘/地脉〕移到单据提交后(兑付值序一致——收益不因减伤变化))
|
||||
var dt_amount := int(vrow.get("effect_value", 0))
|
||||
var dt_hits := fx_host.fx_emit("damage_taken", {"kind": "terrain", "amount": dt_amount,
|
||||
"source": String(vid), "cell": evt.cell, "round": ri, "terrain_kind": String(vid),
|
||||
"hp_ratio": int(round(100.0 * float(int(oc._enemy_system.hero_unit().get("hp", 0))) / float(maxi(1, int(oc._enemy_system.hero_unit().get("max_hp", 1))))))})
|
||||
dt_amount = _terrain_damage_reduce(dt_hits, dt_amount)
|
||||
var dt_res := oc._damage._emit_hero_damage_taken(dt_amount, "terrain", String(vid), evt.cell, ri)
|
||||
dt_amount = int(dt_res["total"])
|
||||
var vt := oc._damage.open_ticket(DamageController.KIND_BOARD_FLAT_HERO, "地形变异", String(vrow.get("display_name", vid)),
|
||||
{"channel": "board", "base_value": dt_amount, "target_rule": DamageController.TARGET_HERO,
|
||||
"ri": ri, "origin_cell": evt.cell, "context": {"variant_id": String(vid)}})
|
||||
"ri": ri, "origin_cell": evt.cell, "context": {"variant_id": String(vid), "hero_damage_consumed": true}})
|
||||
reward_grant.submit(vt, false)
|
||||
for h in dt_hits:
|
||||
for h in (dt_res["hits"] as Array):
|
||||
if String(h.get("kind", "")) == "grant_material":
|
||||
_apply_material_hit(h, evt.cell, ri)
|
||||
|
||||
|
||||
# damage_taken 施加面(damage_reduce 减量收集〔背水——定值〕/ac_bonus〔石肤〕/counter_add〔保险丝/石肤〕;
|
||||
# 返回减后 amount 交开单消费)
|
||||
func _terrain_damage_reduce(dt_hits: Array, dt_amount: int) -> int:
|
||||
for h in dt_hits:
|
||||
match String(h.get("kind", "")):
|
||||
"damage_reduce":
|
||||
dt_amount = maxi(0, dt_amount - int(h.get("value", 0)))
|
||||
"ac_bonus":
|
||||
fx_host.apply_ac_bonus(h)
|
||||
"counter_add":
|
||||
_apply_counter_hit(h)
|
||||
return dt_amount
|
||||
|
||||
|
||||
# 封印判定批+战封印军规开单段(封印流:seal_judged 批后统一开单:轮末每面封印命中对最前存活敌
|
||||
# 结算 board_typed 必中伤害〔复用零新配方;「封印所在巢穴敌」简化为 default_target 最前存活敌——
|
||||
# 台账披露待追认〕;完美布防=本轮封印批全中(hit>0 且 miss==0)时封印伤 ×mult——全对推理奖励)。
|
||||
@@ -259,6 +266,7 @@ func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionar
|
||||
func _round_end_apply(ri: int) -> void:
|
||||
var re_fx := fx_host.fx_emit("round_end", {"round": ri})
|
||||
_round_end_blast_tickets(re_fx, ri)
|
||||
_round_end_heal_value_counter(re_fx, ri) # 迭代 46 卡A T5——坑道小憩恢复兑付(先于清零行消费层值,声明序=heal 行在 counter set 行前)
|
||||
for h in re_fx:
|
||||
if String(h.get("kind", "")) == "counter_add":
|
||||
_apply_counter_hit(h)
|
||||
@@ -278,6 +286,24 @@ func _round_end_apply(ri: int) -> void:
|
||||
oc._damage.flush() # 授予段界结账(案C 后本段伤害单据全数暂存,此处对空队 no-op——保留作防御性段界)
|
||||
|
||||
|
||||
# round_end heal value_counter 兑付(迭代 46 卡A T5——坑道小憩:层值=本轮成功刷新累计恢复点,
|
||||
# units.heal 封顶、满血发未生效行;层清零由同事件 counter_add set 行承载〔声明序在后〕——本面
|
||||
# 先于 counter_add 遍历消费层值即保序。行源=成功刷新事实族(无棋盘格——fx_board_refresh 豁免类))
|
||||
func _round_end_heal_value_counter(re_fx: Array, ri: int) -> void:
|
||||
for h in re_fx:
|
||||
if String(h.get("kind", "")) != "heal" or String(h.get("value_counter", "")) == "":
|
||||
continue
|
||||
var layers := EffectEngine.counter(fx_host.counters_ctx, String(h.get("value_counter", "")))
|
||||
if layers <= 0:
|
||||
continue
|
||||
var hu: Dictionary[Variant, Variant] = oc._enemy_system.hero_unit()
|
||||
if int(hu.get("hp", 0)) >= int(hu.get("max_hp", 1)):
|
||||
oc._emit_row({"type": "reward_ineffective", "source_class": "fx_board_refresh", "origin_cell": Vector2i(-1, -1)}, ri, "坑道小憩 未生效(满血)", 0, {"batch_key": String(h.get("value_counter", ""))})
|
||||
continue
|
||||
var healed: int = oc._enemy_system.heal(hu, layers)
|
||||
oc._emit_row({"type": "heal", "source_class": "fx_board_refresh", "origin_cell": Vector2i(-1, -1)}, ri, "坑道小憩 回复", healed, {"target": "hero"})
|
||||
|
||||
|
||||
# round_end blast 通道反打单(per-counter 积层读数×value=反打总量;source_class 用中性名,
|
||||
# per-counter 反打通道保留泛用面;案C 暂存战斗段末兑付)
|
||||
func _round_end_blast_tickets(re_fx: Array, ri: int) -> void:
|
||||
|
||||
@@ -869,5 +869,215 @@ rows = [
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "vein_reserve",
|
||||
"display_name": "矿脉储能",
|
||||
"rarity": "excellent",
|
||||
"cap": 1,
|
||||
"desc": "挖格储能:每次受理的付费挖格 +1 储备点(RAP)",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "dig_paid",
|
||||
"do": {
|
||||
"kind": "grant_reserve_ap",
|
||||
"value": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "easy_swap",
|
||||
"display_name": "省力周转",
|
||||
"rarity": "excellent",
|
||||
"cap": 1,
|
||||
"desc": "刷新半价:弃图刷新成本为基线 50%",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "refresh_request",
|
||||
"do": {
|
||||
"kind": "apply_discount",
|
||||
"mode": "refresh",
|
||||
"cost_mult": 50
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "wall_blast",
|
||||
"display_name": "崩壁冲击",
|
||||
"rarity": "excellent",
|
||||
"cap": 1,
|
||||
"desc": "刷后群伤:成功刷新后全体存活敌各受 2 点",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "board_refreshed",
|
||||
"do": {
|
||||
"kind": "open_ticket",
|
||||
"channel": "blast",
|
||||
"value": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "mine_profit",
|
||||
"display_name": "矿道红利",
|
||||
"rarity": "rare",
|
||||
"cap": 1,
|
||||
"desc": "刷后GP:每次成功刷新固定 +1 GP",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "board_refreshed",
|
||||
"do": {
|
||||
"kind": "grant_gp",
|
||||
"value": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "stone_mitigation",
|
||||
"display_name": "石层缓冲",
|
||||
"rarity": "common",
|
||||
"cap": 1,
|
||||
"desc": "当轮减伤:本轮成功刷新后,每次受伤固定 −2(多刷不叠加)",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "board_refreshed",
|
||||
"do": {
|
||||
"kind": "counter_add",
|
||||
"counter_id": "round_swap_guard",
|
||||
"value": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"on": "damage_taken",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "round_swap_guard",
|
||||
"op": "gte",
|
||||
"value": 1
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "damage_reduce",
|
||||
"value": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "charge_rotation",
|
||||
"display_name": "蓄力周转",
|
||||
"rarity": "excellent",
|
||||
"cap": 1,
|
||||
"desc": "刷后蓄力:每次刷新 +1 层(上限 3),下一次攻击消费全部层数",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "board_refreshed",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "swap_charge_layers",
|
||||
"op": "lt",
|
||||
"value": 3
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "counter_add",
|
||||
"counter_id": "swap_charge_layers",
|
||||
"value": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"on": "attack_commit",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "swap_charge_layers",
|
||||
"op": "gte",
|
||||
"value": 1
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "attack_bonus",
|
||||
"value_counter": "swap_charge_layers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"on": "attack_commit",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "swap_charge_layers",
|
||||
"op": "gte",
|
||||
"value": 1
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "counter_add",
|
||||
"counter_id": "swap_charge_layers",
|
||||
"set": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"feat_id": "tunnel_rest",
|
||||
"display_name": "坑道小憩",
|
||||
"rarity": "common",
|
||||
"cap": 1,
|
||||
"desc": "当轮恢复:每次刷新累计 1 点(上限 3),本轮轮末合计回复",
|
||||
"triggers": [
|
||||
{
|
||||
"on": "board_refreshed",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "round_swap_rest",
|
||||
"op": "lt",
|
||||
"value": 3
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "counter_add",
|
||||
"counter_id": "round_swap_rest",
|
||||
"value": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"on": "round_end",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "round_swap_rest",
|
||||
"op": "gte",
|
||||
"value": 1
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "heal",
|
||||
"value_counter": "round_swap_rest"
|
||||
}
|
||||
},
|
||||
{
|
||||
"on": "round_end",
|
||||
"when": [
|
||||
{
|
||||
"fact": "counter",
|
||||
"id": "round_swap_rest",
|
||||
"op": "gte",
|
||||
"value": 1
|
||||
}
|
||||
],
|
||||
"do": {
|
||||
"kind": "counter_add",
|
||||
"counter_id": "round_swap_rest",
|
||||
"set": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -203,15 +203,11 @@ func set_world_font(f: Font) -> void:
|
||||
|
||||
# D 区可用面积(AP 条之外)→ 格边长 = floor((min(宽, 高) − 预留 − (N−1)×格间距) / N)(battle.md 格尺寸公式)
|
||||
# 公式须补算 (N−1)×2px 网格间距与垂直预留 24px,否则 12×12 板实高溢出可用区 ~6px,下缘被 clip_contents 裁掉。
|
||||
# 算式唯一落点 = _cell_for(迭代 46 卡C——探针与单元测试共用该静态函数求值,禁复写算式造第二口径)。
|
||||
func set_cell_area(avail: Vector2) -> void:
|
||||
if _board == null or _board.width == 0:
|
||||
return
|
||||
var n: int = maxi(_board.width, _board.height)
|
||||
var sep := SEP # 格间距(_init 同值)
|
||||
var d := DEPTH_PX
|
||||
var reserve := 24.0 + d # 垂直总预留(上 12 + 下 12 + 悬崖外延——悬崖占预算防溢出)
|
||||
var cell := int(floor((minf(avail.x - 12.0 - d, avail.y - reserve) - float((n - 1) * sep)) / float(n)))
|
||||
_cell = float(clampi(cell, 26, 46))
|
||||
_cell = float(_cell_for(maxi(_board.width, _board.height), avail))
|
||||
_hero_sprite.set_cell_size(_cell, float(SEP))
|
||||
var stride := _cell + float(SEP)
|
||||
for c in _cells:
|
||||
@@ -224,6 +220,17 @@ func set_cell_area(avail: Vector2) -> void:
|
||||
_update_world_size()
|
||||
|
||||
|
||||
# 格边长算式唯一落点(迭代 46 卡C T1 自 set_cell_area 抽出——逐位同式:SEP/DEPTH_PX 读本文件
|
||||
# 既有常量、clampi [26,46] 留本函数内;名字带下划线是 S13 max-public-methods 27 顶格的约束,禁改公开名。
|
||||
# 探针(非当前板型 13/14×实板可用面积)与单元测试(四档板型)经本函数求值,复写算式即造第二口径)
|
||||
static func _cell_for(n: int, avail: Vector2) -> int:
|
||||
var sep := SEP # 格间距(_init 同值)
|
||||
var d := DEPTH_PX
|
||||
var reserve := 24.0 + d # 垂直总预留(上 12 + 下 12 + 悬崖外延——悬崖占预算防溢出)
|
||||
var cell := int(floor((minf(avail.x - 12.0 - d, avail.y - reserve) - float((n - 1) * sep)) / float(n)))
|
||||
return clampi(cell, 26, 46)
|
||||
|
||||
|
||||
# 悬崖参数下发(网格像素尺寸/步距/列数/材质锚色——BoardWorld._draw 消费)
|
||||
func _refresh_slab() -> void:
|
||||
if _board == null or _board.width == 0:
|
||||
|
||||
@@ -173,7 +173,7 @@ func _draw_south_facade(canvas: CanvasItem, rect: Rect2) -> void:
|
||||
var y_far := rect.size.x - far_h
|
||||
var y_near := y_far - near_h
|
||||
var y_hl := y_near - FACADE_HIGHLIGHT_PX
|
||||
canvas.draw_rect(Rect2(0.0, y_hl, rect.size.x, FACADE_HIGHLIGHT_PX), UiKit.STAND_STONE_RIM, true) # 口沿高光(UiKit.STAND_STONE_RIM 并档——同值单点)
|
||||
canvas.draw_rect(Rect2(0.0, y_hl, rect.size.x, FACADE_HIGHLIGHT_PX), UiKit.BRICK, true) # 口沿高光(合并归掩尘枚 BRICK——art-bible §4.1 换色合并①同值单点)
|
||||
canvas.draw_rect(Rect2(0.0, y_near, rect.size.x, near_h), FACADE_NEAR_COL, true)
|
||||
canvas.draw_rect(Rect2(0.0, y_far, rect.size.x, far_h), FACADE_FAR_COL, true)
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@ func intent_probe() -> Dictionary:
|
||||
|
||||
|
||||
# 名字行探针出口(ui_probe 呈现口径 + 本批 V6/V8 断言面:armor_icon = 绑定纹理路径〔缺位回退字形〕、
|
||||
# 几何 = 素底牌矩形与文字基线、素底色——V6 判据 = baseline_y < plinth_top_y)
|
||||
# 几何 = 素底牌矩形与文字基线、素底色——V6 判据 = baseline_y < plinth_top_y;
|
||||
# name_font_size = 名字行字号档实读(迭代 46 卡B——提档 FS_HINT 14 的几何单点出口))
|
||||
func name_line_probe() -> Dictionary:
|
||||
var f := _efont()
|
||||
var tex := UiKit.load_tex(_armor_tex_path(st._armor))
|
||||
@@ -69,7 +70,8 @@ func name_line_probe() -> Dictionary:
|
||||
"armor_tex_bound": tex != null,
|
||||
"plate": plate, "baseline_y": _name_baseline(plate).y,
|
||||
"plinth_top_y": _pedestal_rect().position.y,
|
||||
"plate_color": UiKit.HP_BAR_BACK}
|
||||
"plate_color": UiKit.HP_BAR_BACK,
|
||||
"name_font_size": UiKit.FS_HINT}
|
||||
|
||||
|
||||
# ---- setter 面(presenter/组合根零改排) ----
|
||||
@@ -332,15 +334,16 @@ func _name_plate_rect(f: Font, tex: Texture2D) -> Rect2:
|
||||
var icon_w := 24.0
|
||||
if tex == null:
|
||||
icon_w = f.get_string_size(String(ARMOR_ICONS.get(st._armor, "◇")),
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_CAPTION).x
|
||||
var name_w := f.get_string_size(st._display_name, HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_CAPTION).x
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT).x
|
||||
var name_w := f.get_string_size(st._display_name, HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT).x
|
||||
var total_w := icon_w + 3.0 + name_w
|
||||
return Rect2((box.x - total_w - 8.0) * 0.5, box.y - 18.0 - 26.0, total_w + 8.0, 26.0)
|
||||
|
||||
|
||||
# 名字行文字基线(牌内几何单点——图标 24px 垂直居中牌内〔中心=牌顶+13〕,12px 字形基线=中心+4)
|
||||
# 名字行文字基线(牌内几何单点——图标 24px 垂直居中牌内〔中心=牌顶+13〕,14px 字形基线=中心+5
|
||||
# (0.35h 规则按字号档推导 14×0.35≈4.9→5,T0 实测校验——迭代 46 卡B §7.4 提档))
|
||||
func _name_baseline(plate: Rect2) -> Vector2:
|
||||
return plate.position + Vector2(4.0, 17.0)
|
||||
return plate.position + Vector2(4.0, 18.0)
|
||||
|
||||
|
||||
# 绘制内容矩形(世界局部;ui_struct_probe ⑥standee「不出框+下余量≥8px」断言读数面——
|
||||
@@ -362,8 +365,8 @@ func _draw() -> void:
|
||||
## 地面域:椭圆落影(圣经 §6.1 地台落影压脚:方向稿椭圆 (0,0,0,70),压在地台
|
||||
## 上缘周围;24 段多边形近似椭圆,中心=台面上方 6px、横半径=台宽一半)
|
||||
## + 石板地台(§6.1 近景地台独立件:TEX_STAGE_PLAZA 源 48×12 九宫格横向拉伸、顶缘受光线 2px
|
||||
## 不随拉伸变形、跨三关恒定;素材缺位回退程序化三段绘制〔STAND_STONE 族方向稿取色,几何同源
|
||||
## _pedestal_rect——与 panel_skinned 缺位回退同构〕)
|
||||
## 不随拉伸变形、跨三关恒定;素材缺位回退程序化三段绘制〔板身 STAND_STONE/描边 PLAZA_EDGE/
|
||||
## 顶缘线 BRICK——art-bible §4.1 换色合并①②改指目标色,几何同源 _pedestal_rect〕)
|
||||
func _draw_ground(f: Font) -> void:
|
||||
var sh_center := Vector2(box.x * 0.5, box.y - 24.0)
|
||||
var sh_rx := (box.x - 36.0) * 0.5
|
||||
@@ -379,8 +382,8 @@ func _draw_ground(f: Font) -> void:
|
||||
_draw_plinth_stretched(plaza, ped)
|
||||
else:
|
||||
draw_rect(ped, UiKit.STAND_STONE, true)
|
||||
draw_rect(ped, UiKit.STAND_STONE_EDGE, false, 1.0)
|
||||
draw_rect(Rect2(ped.position.x, ped.position.y, ped.size.x, 2.0), UiKit.STAND_STONE_RIM, true)
|
||||
draw_rect(ped, UiKit.PLAZA_EDGE, false, 1.0)
|
||||
draw_rect(Rect2(ped.position.x, ped.position.y, ped.size.x, 2.0), UiKit.BRICK, true)
|
||||
|
||||
|
||||
## 地台九宫格横向拉伸域(循环体提函数——左右 4px 端头切片 + 中段拉伸;纵向恒 12px 源档,
|
||||
@@ -464,13 +467,13 @@ func _draw_armor_name_line(f: Font) -> void:
|
||||
draw_texture_rect(tex, Rect2(baseline.x, plate.position.y + 1.0, 24.0, 24.0), false)
|
||||
else:
|
||||
var armor_txt := String(ARMOR_ICONS.get(st._armor, "◇"))
|
||||
icon_w = f.get_string_size(armor_txt, HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_CAPTION).x
|
||||
icon_w = f.get_string_size(armor_txt, HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT).x
|
||||
var col: Color = UiKit.WARM_FAINT # 轻甲 = 暖白弱化(v3.5 暗底双色墨制)
|
||||
match st._armor:
|
||||
"ward":
|
||||
col = UiKit.HERO_BLUE_BRIGHT # 魔法护甲 = 小人蓝亮档
|
||||
"heavy":
|
||||
col = UiKit.GOLD_BRIGHT # 重甲 = 金族亮档
|
||||
f.draw_string(get_canvas_item(), baseline, armor_txt, HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_CAPTION, col)
|
||||
f.draw_string(get_canvas_item(), baseline, armor_txt, HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT, col)
|
||||
f.draw_string(get_canvas_item(), baseline + Vector2(icon_w + 3.0, 0.0), st._display_name,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_CAPTION, UiKit.WARM) # v3.5 暗底双色墨制
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT, UiKit.WARM) # v3.5 暗底双色墨制
|
||||
@@ -185,8 +185,7 @@ const TIP_BG := Color(0.16, 0.12, 0.09, 0.96) # tooltip 深底
|
||||
const STAGE_BG := Color8(62, 52, 42) # B 区舞台暗底(方向稿 render_battle_screen——battle_stage_view 面板底)
|
||||
const BEAM_LIGHT := Color8(255, 236, 200) # B 区顶光柱暖光(用时乘 alpha 渐隐——battle_stage_view 光柱层)
|
||||
const STAND_STONE := Color8(150, 130, 100) # 站桩石板地台·板身(standee_body 方向稿取色)
|
||||
const STAND_STONE_EDGE := Color8(90, 76, 58) # 站桩石板地台·描边
|
||||
const STAND_STONE_RIM := Color8(196, 172, 132) # 站桩石板地台·顶缘受光线
|
||||
const PLAZA_EDGE := Color8(76, 64, 56) # 小石台描边(art-bible §4.1 换色合并②合并目标——贴图已落此值,缺位回退同值)
|
||||
const CAMP_HEADER_BAND := Color8(110, 69, 38) # 营地柜台头带深棕 #6E4526(4-camp.png 方向稿取色;对齐 demo --wood-deep)
|
||||
const CAMP_ROW_PLATE := Color8(240, 230, 206) # 营地行板暖米(同上)
|
||||
const CAMP_BADGE_PANEL := Color8(40, 32, 24) # 营地钥石徽暗底(同上)
|
||||
|
||||
@@ -6,15 +6,16 @@
|
||||
extends Node
|
||||
|
||||
const ProbeUiUtil := preload("res://probe/probe_ui_util.gd") # 隔离样板单点
|
||||
const BoardViewScript := preload("res://presentation/views/board_view.gd") # 算式单点静态调用载体(迭代 46 卡C)
|
||||
|
||||
# 分辨率档位表(逻辑视口尺寸;数据侧——增删档位只改这里,断言代码零改动)
|
||||
const VIEWPORTS := [
|
||||
{"label": "基座 1280x800", "size": Vector2i(1280, 800)},
|
||||
{"label": "16:9 全屏 1920x1080", "size": Vector2i(1920, 1080)},
|
||||
]
|
||||
const MIN_CELL := 36.0 # 格子可读门槛(battle.md §棋盘格尺寸公式 1280 档 12×12 → 36px)
|
||||
|
||||
var _problems: PackedStringArray = []
|
||||
var _cell_reads: Dictionary = {} # 逐档格边长实读留痕(label→cell_size;PASS 行引基座值)
|
||||
var _est_reads: Dictionary = {} # 逐档 13/14 板推定读数留痕(label→{13,14,avail};PASS 后打印对拍)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -41,8 +42,12 @@ func _ready() -> void:
|
||||
# 复原本项目基座(探针不该把进程留在末档尺寸)
|
||||
get_tree().root.content_scale_size = Vector2i(1280, 800)
|
||||
if _problems.is_empty():
|
||||
print("[layout_probe] PASS — %d 档几何不变量全过(三区非零/不越视口/互不重叠/view 含于 D 区/格子 ≥%.0fpx)"
|
||||
% [VIEWPORTS.size(), MIN_CELL])
|
||||
print("[layout_probe] PASS — %d 档几何不变量全过+格边长等价成立(基座实读 %.0fpx)〔格边长 V1〕"
|
||||
% [VIEWPORTS.size(), float(_cell_reads.get("基座 1280x800", -1.0))])
|
||||
for label in _est_reads:
|
||||
var e: Dictionary = _est_reads[label]
|
||||
print("[layout_probe] [%s] 13 板推定 %dpx/14 板推定 %dpx(实板可用面积 %s)〔格边长 V4〕"
|
||||
% [label, int(e["13"]), int(e["14"]), str(e["avail"])])
|
||||
get_tree().quit(0)
|
||||
else:
|
||||
for p in _problems:
|
||||
@@ -91,5 +96,25 @@ func _check_one(label: String, main: Node) -> void:
|
||||
_problems.append("[%s] 顶层区重叠 %s×%s(%s ∩ %s)"
|
||||
% [label, keys[i], keys[j], rects[keys[i]], rects[keys[j]]])
|
||||
var cell: float = main.ui.battle.board_zone.board_view.get("cell_size")
|
||||
if cell < MIN_CELL:
|
||||
_problems.append("[%s] 格子边长 %.1fpx < 可读门槛 %.0fpx" % [label, cell, MIN_CELL])
|
||||
_cell_reads[label] = cell
|
||||
# 格边长接线守卫——判据=等价(生产写入值与单点算式严格相等,生产接线断开即红;
|
||||
# 全仓禁任何人造格边长可读阈值)。
|
||||
# 板型 N 无公开出口→`bv.get("_board")` 内部字段直查=受控例外(改动—验收对照表行 1 注明理由)。
|
||||
var b = bv.get("_board")
|
||||
if b == null:
|
||||
_problems.append("[%s] _board 为 null(板型 N 无从取值,等价断言无依据)〔格边长 V1〕" % label)
|
||||
elif cell != float(BoardViewScript._cell_for(maxi(int(b.width), int(b.height)), bv.size)):
|
||||
_problems.append("[%s] 格边长等价破——生产写入 %.1fpx ≠ _cell_for(n=%d, avail=%s) 返回 %.1fpx(实板可用面积 %s)〔格边长 V1〕"
|
||||
% [label, cell, maxi(int(b.width), int(b.height)), str(bv.size),
|
||||
float(BoardViewScript._cell_for(maxi(int(b.width), int(b.height)), bv.size)), str(bv.size)])
|
||||
# 最大板推定留痕(迭代 46 卡C T2——实板可用面积代入 13/14 板型求算式单点,读数打印不作判红:
|
||||
# 锚点=用户验收的现行渲染值;对拍归实现报告,对拍不一致=卡 §9 L3 #2 呈报,禁实现侧改锚;
|
||||
# 零尺寸前置=可用面积不可信时推定无依据)
|
||||
if bv.size.x <= 0.0 or bv.size.y <= 0.0:
|
||||
_problems.append("[%s] board_view 零尺寸(可用面积不可信,格边长推定无依据)〔格边长 V4〕" % label)
|
||||
else:
|
||||
_est_reads[label] = {
|
||||
"13": BoardViewScript._cell_for(13, bv.size),
|
||||
"14": BoardViewScript._cell_for(14, bv.size),
|
||||
"avail": str(bv.size),
|
||||
}
|
||||
@@ -139,6 +139,15 @@ tests/
|
||||
| 调参测速批量模拟(逐帧步进与统计读数) | 调参测量 | `TuneSimController.run()`(调试浮窗批量模拟入口) | `tune_sim_batch_parity_test.gd:_init`(配对对拍套件,随测速循环批建) |
|
||||
| 战斗叙述与终局文案(数值带入/胜负互异) | HUD框架 | `BattleNarrator.battle_end_text()`/`BattleNarrator.boss_name()` | `battle_narrator_test.gd:_test_numeric_lines_carry_values`;`battle_narrator_test.gd:_test_end_text_differs_by_result`;`battle_narrator_test.gd:_test_boss_name_uses_boss_rowset` |
|
||||
| 玩家面文案与危险格格面字形 | HUD框架 | `BoardView.rebuild()`/`StatusSlotRow.set_effects()` | `player_copy_sweep_test.gd:_sweep_board_glyph`;`player_copy_sweep_test.gd:_sweep_legend`;`player_copy_sweep_test.gd:_sweep_hero_panel` |
|
||||
| 营地场景图十层铺底与门洞留空呈现 | 营地场景视图 | 进入存档→选档→进档→营地场景屏(`CampSceneView.setup_layers()` 驱动);单元测试载入 `camp_scene_layout.tres` | `shot_probe.gd:_ready`(camp 截图段)〔营地图批 V1〕;`camp_scene_layout_test.gd:_test_layout_hotspot_geometry`〔营地图批 V14〕 |
|
||||
| 营地七物件命中区点选与分界面可达 | 营地场景视图 | 七物件命中区 `_gui_input()` → `CampSceneView.object_pressed()` → 组合根开界面 | `ui_click_probe.gd:_ready`(七物件合成点击段)〔营地图批 V2〕 |
|
||||
| 营地大门两分支确认与断点续玩接线 | 营地交互流 | 大门命中区 → ConfirmDialog(三出口)→ `main._on_confirm_new_adventure()`/`_resume_from_menu()` | `ui_click_probe.gd:_ready`(大门两分支段/断点确认段 :500-528)〔营地图批 V3〕 |
|
||||
| 四柜台拆解后五界面入口改挂与写口零回归 | 营地五界面 | 五界面意图信号 → `CampShopPresenter` → `MetaProgression.tree_buy()` 写口 | `forge_workbench_test.gd:_test_forge_rows`〔营地图批 V4〕;`ui_click_probe.gd:_ready`(写口链段) |
|
||||
| 营地篝火回主菜单与笔记本改挂动线 | 营地交互流 | 笔记本命中区 → `CareerOverlay.open()`;篝火命中区 → ConfirmDialog 二次确认 → 主菜单 | `ui_struct_probe.gd:_ready`(career 段)〔营地图批 V5〕;`screen_flow_probe.gd:_ready`(篝火/开合段)〔营地图批 V7〕 |
|
||||
| 营地图鉴占位挂起态与反参照结构纪律 | 营地场景视图 | 布告板命中区 → `CampSceneView.object_pressed()` → 图鉴占位视图;营地根态场景树审计 | `ui_struct_probe.gd:_ready`(占位禁词/禁行段)〔营地图批 V6〕;`ui_struct_probe.gd:_ready`(结构禁词段)〔营地图批 V9〕 |
|
||||
| 营地刷新单口与场景根 HUD 同步 | 营地刷新总线 | 写口尾 → `CampRefreshBus.refresh()` → 现开界面刷新+场景根 HUD 刷新 | `ui_struct_probe.gd:_ready`(顶栏位段)〔营地图批 V8〕;`ui_click_probe.gd:_ready`(写口尾刷新段) |
|
||||
| Esc 浮窗唤起与三出口动线 | 营地 Esc 流 | 营地场景根态合成 Esc 键事件→ `main_esc_flow.on_esc_input()` → `ui.modals.flow.open/close`;浮窗三钮 `pressed` → 三出口 | `screen_flow_probe.gd:_ready`(Esc 唤起/子界面开态不唤起/再按关窗/非营地不唤起段)〔ESC批 V1〕;`screen_flow_probe.gd:_ready`(返回动线/设置双路径段)〔ESC批 V3/V4〕 |
|
||||
| 营地顶栏 HUD 钥石读数与刷新单口同步 | 营地 HUD 栏 | 隔离存档实例 `meta_state._add_keystone()`→ 显式触发 `CampRefreshBus.refresh(camp_data)` → `camp_hud_band.refresh()` → `keystone_badge` 读数 | `screen_flow_probe.gd:_ready`(HUD 余额读数/刷新段)〔ESC批 V6〕;`ui_struct_probe.gd:_ready`(顶栏位结构段) |
|
||||
|
||||
**旅程段七:数据配置与跨系统契约**
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ func _suites() -> Array:
|
||||
{"path": "res://tests/unit/presentation/pacing_queue_test.gd", "expect": 0}, # AC⑤/T9——排空零分叉/零丢行/延迟双态
|
||||
{"path": "res://tests/unit/presentation/standee_fx_sweep_test.gd", "expect": 0}, # 呈现域缺陷扫掠(d2 蓄力档/d4 庆祝句柄/d5+d8 互斥/d12 站桩按 id 解析)
|
||||
{"path": "res://tests/unit/presentation/tune_sim_batch_parity_test.gd", "expect": 0}, # 测速循环批双实现对拍(帧索引/运行态/进度串/stats/报告五面——信号步进 vs await 基线)
|
||||
{"path": "res://tests/unit/presentation/standee_present_values_test.gd", "expect": 0}, # 战斗一屏样张批 V5–V9(血条危险红/名字行素底不压地台/徽标 FS_HINT/护甲 PNG 绑定/素材入包)
|
||||
{"path": "res://tests/unit/presentation/standee_present_values_test.gd", "expect": 0}, # 战斗一屏样张批 V5–V12(血条危险红/名字行素底不压地台与提档 FS_HINT/徽标/护甲 PNG 绑定/素材入包/地台色合并退役)
|
||||
{"path": "res://tests/unit/presentation/reward_overlay_test.gd", "expect": 0}, # 奖励节点 UI 直验(盲区补漏)
|
||||
{"path": "res://tests/unit/presentation/level_map_info_fog_test.gd", "expect": 0}, # 信息迷雾——呈现显隐/Boss 豁免/详情零显示/大图拟合
|
||||
{"path": "res://tests/unit/presentation/forge_workbench_test.gd", "expect": 0}, # 工作间两区六路线 UI 直验(V13 自动化前置面)
|
||||
|
||||
@@ -314,7 +314,7 @@ fi
|
||||
# get_tree());排除注释行(行首 #/##)与字符串字面量(双引号包裹段内的 await 非代码),
|
||||
# 口径仿 S1/S2 的 grep 排除手法。
|
||||
# 自检:清单内文件缺位(路径写错/被改名)即判红——防扫面为空静默绿。
|
||||
S8_FILES="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd"
|
||||
S8_FILES="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd game/core/settlement/battle_refresh_flow.gd"
|
||||
S8_MISS=0
|
||||
for f in $S8_FILES; do
|
||||
if [ ! -f "$f" ]; then
|
||||
@@ -356,7 +356,9 @@ fi
|
||||
# 自检:扫描面为空即判红(require_scan_face);B1 文件集与三族自家文件缺位即判红
|
||||
# (文件被改名=豁免名单失效,宁可红不可静默放行)。
|
||||
if require_scan_face "S7" "$DIR_CORE"; then
|
||||
S7_B1_SET="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd"
|
||||
# B1 域文件集(迭代 46 卡A 增补 battle_refresh_flow——换图刷新流程件=C13 拆分边界的 B1 域拆件,
|
||||
# 承载旧资源退役/装板编排调用;architecture.md「模块归属」BattleRefreshFlow 行随反哺点落文)
|
||||
S7_B1_SET="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd game/core/settlement/battle_refresh_flow.gd"
|
||||
S7_MISS=0
|
||||
for f in $S7_B1_SET game/core/unit_container.gd game/core/status_container.gd game/core/reward_economy.gd; do
|
||||
if [ ! -f "$f" ]; then
|
||||
|
||||
@@ -0,0 +1,650 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 换图系双基座七件专项宿主(迭代 46 卡A——对照表 V1–V12 按轮落地:V5=T2 全局受伤链路、
|
||||
# V2/V3=T3 两基座、V4/V10=T4 成功事实与 GP、V6–V9=T5 五件后续、V11=T6 数据与池;
|
||||
# V12 无专长基线回归归 round_flow/seal_polarity 既有断言承载)。
|
||||
# 临时承伤计数专长经现行 ConfigDB 注入(表行追加+持有集传 id——正常数据配置路径,卡片 §12);
|
||||
# 真实入口驱动:AutoPlayer 盲挖循环+停手/封印动作;判据绑可观测提交面(damage_taken 命中计数器
|
||||
# 与 target=hero 明细行)。
|
||||
# 运行:godot --headless --path game --script res://tests/unit/battle_settlement/refresh_feats_test.gd(expect 0)
|
||||
extends SceneTree
|
||||
|
||||
const Kit := preload("res://tests/unit/test_kit.gd")
|
||||
const ConfigDBScript = preload("res://core/config_db.gd")
|
||||
const EffectEngineScript = preload("res://core/effect_engine.gd")
|
||||
const AutoPlayer := preload("res://sim/auto_player.gd")
|
||||
|
||||
# 直接伤型资源类型(负向极性兑付=主角直伤单据的三型——reward 表 pierce/magic/heal 负向行)
|
||||
const DIRECT_TYPES := ["pierce", "magic", "heal"]
|
||||
|
||||
var _db
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_db = ConfigDBScript.new()
|
||||
if not _db.load_tables("res://data/tables", true):
|
||||
print("[refresh_feats_test] FAIL — 数值表加载失败")
|
||||
quit(1)
|
||||
return
|
||||
_install_dt_probe()
|
||||
test_all_hero_damage_paths_emit_once()
|
||||
test_no_duplicate_damage_taken_event()
|
||||
test_reserve_on_accepted_dig()
|
||||
test_refresh_discount_gate_and_charge()
|
||||
test_double_base_stack()
|
||||
test_no_feats_baseline()
|
||||
test_board_refresh_fact_only_on_success()
|
||||
test_mine_profit_gp()
|
||||
test_stone_mitigation_all_damage()
|
||||
test_rest_rotation_cap_and_clear()
|
||||
test_charge_layers_consumed_same_round()
|
||||
test_blast_defers_to_combat_segment()
|
||||
test_seven_feats_validate_and_pool()
|
||||
quit(Kit.finish("refresh_feats_test"))
|
||||
|
||||
|
||||
# ---- 夹具族(真实入口驱动——settle_batch/stop/封印动作;直构只用于编排器受理)----
|
||||
|
||||
# 临时承伤计数专长(damage_taken → counter_add battle 桶——每张主角承伤单据恰 +1)
|
||||
func _install_dt_probe() -> void:
|
||||
if _db.crossrun.feats.row_by_id("probe_dt_counter").is_empty():
|
||||
(_db.crossrun.feats.rows as Array).append({
|
||||
"feat_id": "probe_dt_counter", "display_name": "承伤计数探针", "rarity": "common",
|
||||
"desc": "测试夹具:每次主角承伤计数 +1",
|
||||
"triggers": [{"on": "damage_taken", "do": {"kind": "counter_add", "counter_id": "dt_probe_hits", "value": 1}}],
|
||||
})
|
||||
|
||||
|
||||
func _orch(seed_v: int):
|
||||
var rng = load("res://core/rng_service.gd").new()
|
||||
rng.set_master_seed(seed_v)
|
||||
return load("res://core/battle_orchestrator.gd").new(_db, rng)
|
||||
|
||||
|
||||
func _enc(feats: Array, voucher_rap: int = 0, armor: int = 10, hero_hp: int = 200) -> Dictionary:
|
||||
return {"level_index": 1, "node_depth": 4, "hero_hp": hero_hp, "hero_atk": 8, "hero_max_hp": 200,
|
||||
"hero_armor_class": armor, "hero_ap_bonus": 0, "attunement": [], "feats": feats, "tree_rules": [],
|
||||
"battle_index": 1, "voucher_rap": voucher_rap, "voucher_time_sand": 0, "node_type": "boss", "adv_bucket": {}}
|
||||
|
||||
|
||||
func _probe_count(orch) -> int:
|
||||
return EffectEngineScript.counter(orch.fx_host().counters_ctx, "dt_probe_hits")
|
||||
|
||||
|
||||
# 主角承伤明细行收集(type=damage 且 target=hero——敌方技与棋盘主角直伤两类单据的行面)
|
||||
func _collect_hero_rows(orch) -> Array:
|
||||
var rows: Array = []
|
||||
orch.step_row.connect(func(row):
|
||||
if String(row.get("type", "")) == "damage" and String(row.get("target", "")) == "hero":
|
||||
rows.append(row))
|
||||
return rows
|
||||
|
||||
|
||||
# 按来源类分桶计数(rows 收集器的只读后处理)
|
||||
func _count_by_source(rows: Array, source: String) -> int:
|
||||
var n := 0
|
||||
for r_v in rows:
|
||||
if String((r_v as Dictionary).get("source_class", "")) == source:
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
# AutoPlayer 盲挖循环直到 cell_revealed 谓词命中(真实挖掘入口;返回 {"cell","evt"} 或空)
|
||||
func _dig_until(orch, pred: Callable) -> Dictionary:
|
||||
var ms = orch.minesweeper
|
||||
var hit := {}
|
||||
ms.cell_revealed.connect(func(evt):
|
||||
if hit.is_empty() and bool(pred.call(evt)):
|
||||
hit["cell"] = evt.cell
|
||||
hit["evt"] = evt)
|
||||
var guard := 40
|
||||
while hit.is_empty() and guard > 0:
|
||||
guard -= 1
|
||||
var plan = AutoPlayer.choose_dig(ms)
|
||||
if plan.is_empty():
|
||||
break
|
||||
if plan.hero_cell != ms.hero_pos():
|
||||
ms.settle_batch([{"action": "move", "cell": plan.hero_cell}])
|
||||
ms.settle_batch([{"action": "dig", "cell": plan.dig_cell}])
|
||||
return hit
|
||||
|
||||
|
||||
# 直接伤型快照判定(未揭示格可查——reward_economy 装板期摇定身份,示警烟火同源读面)
|
||||
func _is_direct_type(orch, c: Vector2i) -> bool:
|
||||
var snap_v = orch.reward_grant().reward_economy.query_full_snapshot(c)
|
||||
return snap_v is Dictionary and DIRECT_TYPES.has(String((snap_v as Dictionary).get("cell_type", "")))
|
||||
|
||||
|
||||
# 可封印的直接伤型安全格扫描(未揭示+非雷+直接伤型+邻接可达 revealed 格——封印动作真实落点位)
|
||||
func _find_sealable_direct(orch) -> Vector2i:
|
||||
var ms = orch.minesweeper
|
||||
var b = ms.current_board()
|
||||
var revealed := {}
|
||||
for c_v in ms.revealed_cells():
|
||||
revealed[c_v] = true
|
||||
for y in b.height:
|
||||
for x in b.width:
|
||||
var c := Vector2i(x, y)
|
||||
if ms.is_revealed(c) or b.is_mine(c) or ms.has_seal(c) or not _is_direct_type(orch, c):
|
||||
continue
|
||||
for n_v in b.neighbors8(c):
|
||||
var n := Vector2i(n_v)
|
||||
if revealed.has(n) and (ms.compute_move_path(n).size() > 0 or n == ms.hero_pos()):
|
||||
return c
|
||||
return Vector2i(-1, -1)
|
||||
|
||||
|
||||
# 盲挖扩板直至出现可封印直接伤型安全格(有界;返回格位或 (-1,-1))
|
||||
func _seal_direct_with_expansion(orch) -> Vector2i:
|
||||
var c := _find_sealable_direct(orch)
|
||||
var guard := 12
|
||||
while c.x < 0 and guard > 0:
|
||||
guard -= 1
|
||||
var plan = AutoPlayer.choose_dig(orch.minesweeper)
|
||||
if plan.is_empty():
|
||||
break
|
||||
if plan.hero_cell != orch.minesweeper.hero_pos():
|
||||
orch.minesweeper.settle_batch([{"action": "move", "cell": plan.hero_cell}])
|
||||
orch.minesweeper.settle_batch([{"action": "dig", "cell": plan.dig_cell}])
|
||||
c = _find_sealable_direct(orch)
|
||||
return c
|
||||
|
||||
|
||||
# ---- V5 全局受伤链路(迭代 46 卡A T2)----
|
||||
|
||||
# 四条真实路径(敌方攻击/危险格/错误封印/地形)逐路驱动:每条至少一张主角承伤单据在案,
|
||||
# 且承伤计数器 == 主角承伤单据行数(每单据恰发射一次的全量判据——重复发射即计数器>行数)。
|
||||
func test_all_hero_damage_paths_emit_once() -> void:
|
||||
print("--- V5 全局 damage_taken:四路径逐路恰一次 ---")
|
||||
# ① 敌方攻击路径(Boss 战零挖掘连停三轮——干净样本:零地形零资源单据;多轮保证伤害技在案)
|
||||
var orch1 = _orch(46001)
|
||||
var rows1 := _collect_hero_rows(orch1)
|
||||
Kit.check("V5① 前置:战斗受理", orch1.begin_battle(_enc(["probe_dt_counter"])))
|
||||
for _i in 3:
|
||||
orch1.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var enemy_rows := _count_by_source(rows1, "enemy_action")
|
||||
Kit.check("V5① 敌方攻击路径:承伤单据在案且逐单恰一次(行 %d=计数 %d)〔换图系批 V5〕" % [enemy_rows, _probe_count(orch1)],
|
||||
enemy_rows >= 1 and _probe_count(orch1) == enemy_rows)
|
||||
# ② 地形路径(AutoPlayer 真挖至伤害型变异格开出——发射在授予段开单点、单据标 hero_damage_consumed)
|
||||
var orch2 = _orch(46002)
|
||||
var rows2 := _collect_hero_rows(orch2)
|
||||
Kit.check("V5② 前置:战斗受理", orch2.begin_battle(_enc(["probe_dt_counter"])))
|
||||
var terr := _dig_until(orch2, func(evt):
|
||||
for vid_v in (evt.get("variant_ids", []) as Array):
|
||||
if String(_db.combat.variation.row_by_id(String(vid_v)).get("effect", "")) == "flat_damage":
|
||||
return true
|
||||
return false)
|
||||
Kit.check("V5② 前置:伤害型变异格已挖开(%s)" % str(terr.get("cell", Vector2i(-1, -1))), not terr.is_empty())
|
||||
orch2.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var terrain_rows := _count_by_source(rows2, "地形变异")
|
||||
Kit.check("V5② 地形路径:地形单据在案且全单据逐张恰一次(行 %d=计数 %d——盲挖途经单据一并计入)〔换图系批 V5〕" % [rows2.size(), _probe_count(orch2)],
|
||||
terrain_rows >= 1 and _probe_count(orch2) == rows2.size())
|
||||
# ③ 危险格路径(AutoPlayer 真挖直接伤型危险格——负向直伤单据)
|
||||
var orch3 = _orch(46003)
|
||||
var rows3 := _collect_hero_rows(orch3)
|
||||
Kit.check("V5③ 前置:战斗受理", orch3.begin_battle(_enc(["probe_dt_counter"])))
|
||||
var mine_hit := _dig_until(orch3, func(evt):
|
||||
return String(evt.get("kind", "")) == "mine" and _is_direct_type(orch3, evt.cell))
|
||||
Kit.check("V5③ 前置:直接伤型危险格已挖开(%s)" % str(mine_hit.get("cell", Vector2i(-1, -1))), not mine_hit.is_empty())
|
||||
orch3.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var danger_rows := _count_by_source(rows3, "mine_hit")
|
||||
Kit.check("V5③ 危险格路径:直伤单据在案且全单据逐张恰一次(行 %d=计数 %d)〔换图系批 V5〕" % [rows3.size(), _probe_count(orch3)],
|
||||
danger_rows >= 1 and _probe_count(orch3) == rows3.size())
|
||||
# ④ 错误封印路径(扩板→封直接伤型安全格不挖→停手轮末判标错——负向直伤单据)
|
||||
var orch4 = _orch(46004)
|
||||
var rows4 := _collect_hero_rows(orch4)
|
||||
Kit.check("V5④ 前置:战斗受理", orch4.begin_battle(_enc(["probe_dt_counter"])))
|
||||
var scell := _seal_direct_with_expansion(orch4)
|
||||
Kit.check("V5④ 前置:可封直接伤型安全格在位(%s)" % str(scell), scell.x >= 0)
|
||||
if scell.x >= 0:
|
||||
var plan4 = AutoPlayer.choose_dig(orch4.minesweeper)
|
||||
# 封印动作真实落点:先就位到目标邻接可达格(封印距离同挖掘距离)
|
||||
var seal_plan := _plan_seal(orch4, scell)
|
||||
if not seal_plan.is_empty():
|
||||
if seal_plan["hero_cell"] != orch4.minesweeper.hero_pos():
|
||||
orch4.minesweeper.settle_batch([{"action": "move", "cell": seal_plan["hero_cell"]}])
|
||||
var seal_out: Array = orch4.minesweeper.settle_batch([{"action": "seal_place", "cell": scell}])
|
||||
Kit.check("V5④ 前置:封印受理", not seal_out.is_empty() and bool((seal_out[0] as Dictionary).get("accepted", false)))
|
||||
orch4.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var sealwrong_rows := _count_by_source(rows4, "seal_miss")
|
||||
Kit.check("V5④ 错误封印路径:直伤单据在案且全单据逐张恰一次(行 %d=计数 %d)〔换图系批 V5〕" % [rows4.size(), _probe_count(orch4)],
|
||||
sealwrong_rows >= 1 and _probe_count(orch4) == rows4.size())
|
||||
|
||||
|
||||
# 封印落点计划(目标格邻接可达 revealed 位——AutoPlayer._plan_on 同构最小私有形)
|
||||
func _plan_seal(orch, target: Vector2i) -> Dictionary:
|
||||
var ms = orch.minesweeper
|
||||
for n_v in ms.current_board().neighbors8(target):
|
||||
var n := Vector2i(n_v)
|
||||
if ms.is_revealed(n) and (ms.compute_move_path(n).size() > 0 or n == ms.hero_pos()):
|
||||
return {"hero_cell": n}
|
||||
return {}
|
||||
|
||||
|
||||
# 同一伤害不得出现两次消费(重复发射=计数器>行数):敌方路径与地形路径两样本逐位核对——
|
||||
# 地形单据带 hero_damage_consumed 标记,战斗段末 _resolve_board_flat_hero 跳过二次发射由此钉住。
|
||||
func test_no_duplicate_damage_taken_event() -> void:
|
||||
print("--- V5 全局 damage_taken:无重复消费 ---")
|
||||
var orch1 = _orch(46011)
|
||||
var rows1 := _collect_hero_rows(orch1)
|
||||
Kit.check("ND 前置:战斗受理", orch1.begin_battle(_enc(["probe_dt_counter"])))
|
||||
for _i in 2:
|
||||
orch1.minesweeper.settle_batch([{"action": "stop"}])
|
||||
Kit.check("ND 敌方路径零重复(行 %d=计数 %d——重复消费即计数>行)〔换图系批 V5〕" % [rows1.size(), _probe_count(orch1)],
|
||||
rows1.size() >= 1 and _probe_count(orch1) == rows1.size())
|
||||
var orch2 = _orch(46012)
|
||||
var rows2 := _collect_hero_rows(orch2)
|
||||
Kit.check("ND 前置:战斗受理", orch2.begin_battle(_enc(["probe_dt_counter"])))
|
||||
var terr2 := _dig_until(orch2, func(evt):
|
||||
for vid_v in (evt.get("variant_ids", []) as Array):
|
||||
if String(_db.combat.variation.row_by_id(String(vid_v)).get("effect", "")) == "flat_damage":
|
||||
return true
|
||||
return false)
|
||||
Kit.check("ND 前置:伤害型变异格已挖开(%s)" % str(terr2.get("cell", Vector2i(-1, -1))), not terr2.is_empty())
|
||||
orch2.minesweeper.settle_batch([{"action": "stop"}])
|
||||
Kit.check("ND 地形路径零重复(行 %d=计数 %d——context 标记闸失效即计数翻倍)〔换图系批 V5〕" % [rows2.size(), _probe_count(orch2)],
|
||||
rows2.size() >= 1 and _probe_count(orch2) == rows2.size())
|
||||
|
||||
|
||||
# ---- V2/V3 两件基座(迭代 46 卡A T3)----
|
||||
|
||||
# 表驱动停手攒 RAP(每轮 1:1 转存——无转存率订阅缺省)
|
||||
func _bank_rap(orch, rounds_n: int) -> void:
|
||||
for _i in rounds_n:
|
||||
orch.minesweeper.settle_batch([{"action": "stop"}])
|
||||
|
||||
|
||||
# AutoPlayer 单次付费挖格(真实挖掘入口——移位+dig 一动作)
|
||||
func _auto_dig(orch) -> void:
|
||||
var plan = AutoPlayer.choose_dig(orch.minesweeper)
|
||||
if not plan.is_empty():
|
||||
if plan.hero_cell != orch.minesweeper.hero_pos():
|
||||
orch.minesweeper.settle_batch([{"action": "move", "cell": plan.hero_cell}])
|
||||
orch.minesweeper.settle_batch([{"action": "dig", "cell": plan.dig_cell}])
|
||||
|
||||
|
||||
# V2 矿脉储能:受理的付费挖格 RAP 恰 +1、AP 按表扣、板资源不变
|
||||
func test_reserve_on_accepted_dig() -> void:
|
||||
print("--- V2 矿脉储能:付费挖格产 RAP ---")
|
||||
var orch = _orch(46021)
|
||||
Kit.check("V2 前置:战斗受理", orch.begin_battle(_enc(["vein_reserve"])))
|
||||
_bank_rap(orch, 1)
|
||||
var rap_before: int = orch.action_economy.rap
|
||||
var ap_before: int = orch.action_economy.ap
|
||||
_auto_dig(orch)
|
||||
var dig_cost: int = int(_db.run.action_economy.dig_ap_cost)
|
||||
Kit.check("V2 受理付费挖格 RAP 恰 +1(%d→%d)〔换图系批 V2〕" % [rap_before, orch.action_economy.rap],
|
||||
orch.action_economy.rap == rap_before + 1)
|
||||
Kit.check("V2 AP 按表扣(%d→%d,dig 价 %d)〔换图系批 V2〕" % [ap_before, orch.action_economy.ap, dig_cost],
|
||||
orch.action_economy.ap == ap_before - dig_cost)
|
||||
Kit.check("V2 受理记账闭合:AP 耗尽轮 RAP 增量恰等于受理挖数(AP 消耗数——每受理恰 +1,未受理零入池)〔换图系批 V2〕",
|
||||
_drain_round_rap_accounting(orch))
|
||||
|
||||
|
||||
# V2 辅证:挖到 AP 耗尽——RAP 增量 == 受理挖数(每受理恰 +1;移位耗 AP 不入账故按挖计数)
|
||||
func _drain_round_rap_accounting(orch) -> bool:
|
||||
var rap0: int = orch.action_economy.rap
|
||||
var digs := 0
|
||||
var guard := 24
|
||||
while orch.action_economy.phase == "Active" and guard > 0:
|
||||
guard -= 1
|
||||
var plan = AutoPlayer.choose_dig(orch.minesweeper)
|
||||
if plan.is_empty():
|
||||
break
|
||||
if plan.hero_cell != orch.minesweeper.hero_pos():
|
||||
orch.minesweeper.settle_batch([{"action": "move", "cell": plan.hero_cell}])
|
||||
if orch.action_economy.phase != "Active":
|
||||
break # 移位耗尽 AP 收轮——本轮不再有受理挖
|
||||
orch.minesweeper.settle_batch([{"action": "dig", "cell": plan.dig_cell}])
|
||||
digs += 1
|
||||
return digs > 0 and orch.action_economy.rap - rap0 == digs
|
||||
|
||||
|
||||
# V3 省力周转:折价门槛与扣费(can 与执行同源;base 8→扣 4)
|
||||
func test_refresh_discount_gate_and_charge() -> void:
|
||||
print("--- V3 省力周转:折价门槛与扣费 ---")
|
||||
var orch = _orch(46022)
|
||||
Kit.check("V3 前置:战斗受理", orch.begin_battle(_enc(["easy_swap"])))
|
||||
_bank_rap(orch, 1)
|
||||
var base_cost: int = int(_db.run.action_economy.rap_refresh_cost)
|
||||
var discounted: int = int(floor(float(base_cost) * 50.0 / 100.0))
|
||||
var rap0: int = orch.action_economy.rap
|
||||
Kit.check("V3 门同源:can_refresh 与折后价同源(RAP %d ≥ 折后 %d)〔换图系批 V3〕" % [rap0, discounted],
|
||||
orch.can_refresh())
|
||||
Kit.check("V3 第 1 次刷新受理", orch.player_request_refresh())
|
||||
Kit.check("V3 折后单次扣费(%d→%d,−%d)〔换图系批 V3〕" % [rap0, orch.action_economy.rap, discounted],
|
||||
orch.action_economy.rap == rap0 - discounted)
|
||||
Kit.check("V3 第 2 次刷新受理(RAP=%d)" % orch.action_economy.rap, orch.player_request_refresh())
|
||||
Kit.check("V3 两次折后扣费累计(RAP=%d=%d−2×%d)〔换图系批 V3〕" % [orch.action_economy.rap, rap0, discounted],
|
||||
orch.action_economy.rap == rap0 - 2 * discounted)
|
||||
Kit.check("V3 门槛拒:RAP 不足折后价零受理(can=false 且执行拒)〔换图系批 V3〕",
|
||||
orch.action_economy.rap < discounted and not orch.can_refresh() and not orch.player_request_refresh())
|
||||
|
||||
|
||||
# V3 双基座叠加:挖格产 RAP 与刷新折价同场生效
|
||||
func test_double_base_stack() -> void:
|
||||
print("--- V3 双基座叠加 ---")
|
||||
var orch = _orch(46023)
|
||||
Kit.check("V3 前置:战斗受理", orch.begin_battle(_enc(["vein_reserve", "easy_swap"])))
|
||||
_bank_rap(orch, 1)
|
||||
var rap_before: int = orch.action_economy.rap
|
||||
var base_cost: int = int(_db.run.action_economy.rap_refresh_cost)
|
||||
_auto_dig(orch)
|
||||
Kit.check("V3 双基座:挖格产 RAP +1(%d→%d)〔换图系批 V3〕" % [rap_before, orch.action_economy.rap],
|
||||
orch.action_economy.rap == rap_before + 1)
|
||||
var rap_after_dig: int = orch.action_economy.rap
|
||||
Kit.check("V3 双基座:刷新按折后价扣(−%d)〔换图系批 V3〕" % int(base_cost / 2),
|
||||
orch.player_request_refresh() and orch.action_economy.rap == rap_after_dig - int(base_cost / 2))
|
||||
|
||||
|
||||
# V12(refresh_feats 侧):无专长基线——挖格零产 RAP、刷新按表基线扣、AP 保留、上限照旧
|
||||
func test_no_feats_baseline() -> void:
|
||||
print("--- V12 无专长基线(refresh_feats 侧) ---")
|
||||
var orch = _orch(46024)
|
||||
Kit.check("V12 前置:战斗受理", orch.begin_battle(_enc([])))
|
||||
_bank_rap(orch, 3)
|
||||
var rap_before: int = orch.action_economy.rap
|
||||
var ap_before: int = orch.action_economy.ap
|
||||
var base_cost: int = int(_db.run.action_economy.rap_refresh_cost)
|
||||
_auto_dig(orch)
|
||||
Kit.check("V12 无基座:挖格零产 RAP(%d 不变)〔换图系批 V12〕" % rap_before, orch.action_economy.rap == rap_before)
|
||||
Kit.check("V12 刷新受理并按表基线扣(−%d)〔换图系批 V12〕" % base_cost,
|
||||
orch.player_request_refresh() and orch.action_economy.rap == rap_before - base_cost)
|
||||
Kit.check("V12 AP 保留、相位 Active(基线刷新不重置)〔换图系批 V12〕",
|
||||
orch.action_economy.ap == ap_before - int(_db.run.action_economy.dig_ap_cost) and orch.action_economy.phase == "Active")
|
||||
Kit.check("V12 每轮上限照旧:第 3 次拒(RAP 足额仍拒)〔换图系批 V12〕",
|
||||
orch.player_request_refresh() and not orch.player_request_refresh())
|
||||
|
||||
|
||||
# ---- V4/V10 成功刷新事实与命中施加(迭代 46 卡A T4)----
|
||||
|
||||
# 成功刷新事实探针专长安装(board_refreshed → counter_add——成功事实的可观测计数面)
|
||||
func _install_br_probe() -> void:
|
||||
if _db.crossrun.feats.row_by_id("probe_br_counter").is_empty():
|
||||
(_db.crossrun.feats.rows as Array).append({
|
||||
"feat_id": "probe_br_counter", "display_name": "刷新事实探针", "rarity": "common",
|
||||
"desc": "测试夹具:每次成功刷新计数 +1",
|
||||
"triggers": [{"on": "board_refreshed", "do": {"kind": "counter_add", "counter_id": "br_probe_hits", "value": 1}}],
|
||||
})
|
||||
|
||||
|
||||
func _br_count(orch) -> int:
|
||||
return EffectEngineScript.counter(orch.fx_host().counters_ctx, "br_probe_hits")
|
||||
|
||||
|
||||
# V4 成功事实只在新板就位后发射:成功恰一次;非 Active/每轮上限/RAP 不足三拒面全零事实零换图
|
||||
func test_board_refresh_fact_only_on_success() -> void:
|
||||
print("--- V4 成功刷新事实:拒绝零事实 ---")
|
||||
_install_br_probe()
|
||||
var orch = _orch(46031)
|
||||
var swaps := {"n": 0}
|
||||
var waiting_rejected := {"v": false}
|
||||
orch.board_changed.connect(func(): swaps["n"] += 1)
|
||||
# 非 Active 探针(round_flow 同款:借衰减行在结算段内同步探测一次——Waiting 相位刷新必拒)
|
||||
orch.step_row.connect(func(row):
|
||||
if String(row.get("type", "")) == "decay" and not bool(waiting_rejected["v"]):
|
||||
waiting_rejected["v"] = not orch.player_request_refresh())
|
||||
Kit.check("V4 前置:战斗受理", orch.begin_battle(_enc(["probe_br_counter"])))
|
||||
_bank_rap(orch, 3) # RAP=3×AP;首轮结算衰减行触发 Waiting 探针
|
||||
var swaps0: int = swaps["n"]
|
||||
Kit.check("V4 非 Active 拒零事实(结算段内探测拒绝)〔换图系批 V4〕",
|
||||
bool(waiting_rejected["v"]) and _br_count(orch) == 0 and int(swaps["n"]) == swaps0)
|
||||
# 成功 ×2:事实计数与换图信号逐次 +1
|
||||
Kit.check("V4 第 1 次成功(事实 +1 换图 +1)〔换图系批 V4〕",
|
||||
orch.player_request_refresh() and _br_count(orch) == 1 and int(swaps["n"]) == swaps0 + 1)
|
||||
Kit.check("V4 第 2 次成功(事实 +1 换图 +1)〔换图系批 V4〕",
|
||||
orch.player_request_refresh() and _br_count(orch) == 2 and int(swaps["n"]) == swaps0 + 2)
|
||||
# 每轮上限拒:used=2 满门、RAP 足额——零事实零换图
|
||||
Kit.check("V4 上限拒零事实(RAP %d 足额仍拒)〔换图系批 V4〕" % orch.action_economy.rap,
|
||||
not orch.can_refresh() and not orch.player_request_refresh() and _br_count(orch) == 2 and int(swaps["n"]) == swaps0 + 2)
|
||||
# RAP 不足拒:停手进新轮(used 重置、停手再入 RAP)→ 消费至 RAP 0 → 拒(零事实零换图;
|
||||
# 纯 RAP 不足拒绝面已由 V3 门槛拒单测钉住,此处并拦形态)
|
||||
orch.minesweeper.settle_batch([{"action": "stop"}])
|
||||
Kit.check("V4 新轮受理两次(used 重置、RAP 复入)〔换图系批 V4〕",
|
||||
orch.action_economy.phase == "Active" and orch.player_request_refresh() and orch.player_request_refresh() and _br_count(orch) == 4)
|
||||
Kit.check("V4 RAP 不足拒零事实(RAP %d < 价 %d)〔换图系批 V4〕" % [orch.action_economy.rap, int(_db.run.action_economy.rap_refresh_cost)],
|
||||
orch.action_economy.rap < int(_db.run.action_economy.rap_refresh_cost) and not orch.can_refresh() and not orch.player_request_refresh() and _br_count(orch) == 4 and int(swaps["n"]) == swaps0 + 4)
|
||||
|
||||
|
||||
# V10 矿道红利:每次成功刷新 escrow 恰 +1 且 fx_grant_gp 行在案;拒绝零变化
|
||||
func test_mine_profit_gp() -> void:
|
||||
print("--- V10 矿道红利:刷新固定 GP ---")
|
||||
var orch = _orch(46032)
|
||||
var gp_rows := {"n": 0}
|
||||
orch.step_row.connect(func(row):
|
||||
if String(row.get("type", "")) == "effect" and String(row.get("effect_id", "")) == "fx_grant_gp":
|
||||
gp_rows["n"] += 1)
|
||||
Kit.check("V10 前置:战斗受理", orch.begin_battle(_enc(["mine_profit"])))
|
||||
_bank_rap(orch, 2)
|
||||
var escrow0: int = orch.reward_grant().escrow
|
||||
Kit.check("V10 第 1 次成功 escrow +1(%d→%d)〔换图系批 V10〕" % [escrow0, orch.reward_grant().escrow],
|
||||
orch.player_request_refresh() and orch.reward_grant().escrow == escrow0 + 1)
|
||||
Kit.check("V10 fx_grant_gp 行在案(%d 行)〔换图系批 V10〕" % int(gp_rows["n"]), int(gp_rows["n"]) == 1)
|
||||
Kit.check("V10 第 2 次成功 escrow +1(%d→%d)〔换图系批 V10〕" % [orch.reward_grant().escrow, orch.reward_grant().escrow + 1],
|
||||
orch.player_request_refresh() and orch.reward_grant().escrow == escrow0 + 2)
|
||||
# 拒绝零变化:RAP 不足
|
||||
Kit.check("V10 拒绝零变化(escrow=%d)〔换图系批 V10〕" % orch.reward_grant().escrow,
|
||||
not orch.player_request_refresh() and orch.reward_grant().escrow == escrow0 + 2 and int(gp_rows["n"]) == 2)
|
||||
|
||||
|
||||
# ---- V6/V8/V9/V7 五件后续效果(迭代 46 卡A T5)----
|
||||
|
||||
func _counter(orch, counter_id: String) -> int:
|
||||
return EffectEngineScript.counter(orch.fx_host().counters_ctx, counter_id)
|
||||
|
||||
|
||||
# 伤害明细行泛收集(type=damage 全量——按来源类与值断言)
|
||||
func _collect_damage_rows(orch) -> Array:
|
||||
var rows: Array = []
|
||||
orch.step_row.connect(func(row):
|
||||
if String(row.get("type", "")) == "damage":
|
||||
rows.append(row))
|
||||
return rows
|
||||
|
||||
|
||||
func _damage_rows_by_source(rows: Array, source: String) -> Array:
|
||||
var out: Array = []
|
||||
for r_v in rows:
|
||||
var r := r_v as Dictionary
|
||||
if String(r.get("source_class", "")) == source:
|
||||
out.append(r)
|
||||
return out
|
||||
|
||||
|
||||
# V6 石层缓冲:全局固定减伤(危险格 pierce 8→6 两档钉死:单刷减 2·同轮多刷不叠加·未刷新轮不减;
|
||||
# 地形路径减后值=max(下限, effect_value−2)——含下限保持;敌方路径照常单次发射)
|
||||
func test_stone_mitigation_all_damage() -> void:
|
||||
print("--- V6 石层缓冲:全局固定减伤 ---")
|
||||
# S1 同轮双刷 → 危险格 pierce 8 减 2=6(叠加即 4——多刷不增钉死)
|
||||
var orch1 = _orch(46041)
|
||||
var rows1 := _collect_damage_rows(orch1)
|
||||
Kit.check("V6 S1 前置:战斗受理", orch1.begin_battle(_enc(["stone_mitigation"])))
|
||||
_bank_rap(orch1, 3)
|
||||
Kit.check("V6 S1 同轮双刷受理", orch1.player_request_refresh() and orch1.player_request_refresh())
|
||||
Kit.check("V6 S1 guard 累计 2(同轮双刷)", _counter(orch1, "round_swap_guard") == 2)
|
||||
var mine1 := _dig_until(orch1, func(evt):
|
||||
return String(evt.get("kind", "")) == "mine" and _is_direct_type(orch1, evt.cell))
|
||||
Kit.check("V6 S1 前置:直接伤型危险格已挖开(%s)" % str(mine1.get("cell", Vector2i(-1, -1))), not mine1.is_empty())
|
||||
orch1.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var pierce_rows1 := _damage_rows_by_source(rows1, "mine_hit")
|
||||
Kit.check("V6 S1 危险格减伤恰 2 且多刷不叠加(行值 %s∈[6]——叠加态应为 4)〔换图系批 V6〕" % str(pierce_rows1.map(func(r): return int(r.value))),
|
||||
pierce_rows1.size() >= 1 and int((pierce_rows1[0] as Dictionary).get("value", -1)) == 6)
|
||||
# S2 未刷新轮:guard 随 round_start 清空 → 同型危险格不减(pierce/magic 表幂 8——heal 型幂 6 不同锚勿混)
|
||||
var mine2 := _dig_until(orch1, func(evt):
|
||||
var snap_v2 = orch1.reward_grant().reward_economy.query_full_snapshot(evt.cell)
|
||||
return String(evt.get("kind", "")) == "mine" and snap_v2 is Dictionary \
|
||||
and ["pierce", "magic"].has(String((snap_v2 as Dictionary).get("cell_type", ""))))
|
||||
Kit.check("V6 S2 前置:第二直接伤型危险格已挖开(%s)" % str(mine2.get("cell", Vector2i(-1, -1))), not mine2.is_empty())
|
||||
orch1.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var pierce_rows2 := _damage_rows_by_source(rows1, "mine_hit")
|
||||
Kit.check("V6 S2 未刷新轮不减伤(新轮行值 %s 含 8——round 桶轮始清空)〔换图系批 V6〕" % str(pierce_rows2.map(func(r): return int(r.value))),
|
||||
pierce_rows2.size() >= 2 and int((pierce_rows2[pierce_rows2.size() - 1] as Dictionary).get("value", -1)) == 8)
|
||||
# S3 地形路径:减后值 = max(下限, effect_value−2)——下限保持与定值减一并钉死
|
||||
# (种子 46002=V5② 已证含 flat_damage 变异板;刷新换板后变异重布—— digging guard 内可达)
|
||||
var orch3 = _orch(46002)
|
||||
var rows3 := _collect_damage_rows(orch3)
|
||||
Kit.check("V6 S3 前置:战斗受理", orch3.begin_battle(_enc(["stone_mitigation"])))
|
||||
_bank_rap(orch3, 2)
|
||||
Kit.check("V6 S3 单刷受理", orch3.player_request_refresh())
|
||||
var terr3 := _dig_until(orch3, func(evt):
|
||||
for vid_v in (evt.get("variant_ids", []) as Array):
|
||||
if String(_db.combat.variation.row_by_id(String(vid_v)).get("effect", "")) == "flat_damage":
|
||||
return true
|
||||
return false)
|
||||
Kit.check("V6 S3 前置:伤害型变异格已挖开(%s)" % str(terr3.get("cell", Vector2i(-1, -1))), not terr3.is_empty())
|
||||
orch3.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var terrain_rows := _damage_rows_by_source(rows3, "地形变异")
|
||||
var floor_v: int = int(_db.combat.settlement.damage_roll.damage_floor)
|
||||
var ev_ok := true
|
||||
for tr_v in terrain_rows:
|
||||
var tr := tr_v as Dictionary
|
||||
var vid := String(tr.get("variant_id", ""))
|
||||
var ev: int = int(_db.combat.variation.row_by_id(vid).get("effect_value", 0))
|
||||
if int(tr.get("value", -1)) != maxi(floor_v, ev - 2):
|
||||
ev_ok = false
|
||||
Kit.check("V6 S3 地形减伤=max(下限,effect_value−2) 逐单闭合(%d 单)〔换图系批 V6〕" % terrain_rows.size(),
|
||||
terrain_rows.size() >= 1 and ev_ok)
|
||||
|
||||
|
||||
# V9 坑道小憩:轮末合计回复(白盒预置承载上限 3——计数器直改属数据面注入;
|
||||
# 自然累计 2 与满血未生效两形态分战场钉死)
|
||||
func test_rest_rotation_cap_and_clear() -> void:
|
||||
print("--- V9 坑道小憩:轮末恢复 ---")
|
||||
# R1 白盒预置 3 层 + 刷新闸(when<3 拒第 4 层)→ 停手回复 min(3, 缺血)——护甲降档保缺血 ≥3
|
||||
var orch1 = _orch(46051)
|
||||
var rows1: Array = []
|
||||
orch1.step_row.connect(func(row): rows1.append(row))
|
||||
Kit.check("V9 R1 前置:战斗受理", orch1.begin_battle(_enc(["tunnel_rest"], 0, 10, 100)))
|
||||
_bank_rap(orch1, 1) # 开局血差 100(hero_hp 100/max 200)——缺血 ≥3 恒成立,回复面确定
|
||||
var missing: int = 200 - int(orch1._enemy_system.hero_unit().get("hp", 0))
|
||||
EffectEngineScript.counter_add(orch1.fx_host().counters_ctx, "round_swap_rest", 3)
|
||||
Kit.check("V9 R1 预置 3 层后刷新被闸(when<3——上限 3)", orch1.player_request_refresh() and _counter(orch1, "round_swap_rest") == 3)
|
||||
orch1.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var heal_rows1: Array = []
|
||||
var idle_rows1 := 0
|
||||
for r_v in rows1:
|
||||
var r := r_v as Dictionary
|
||||
if String(r.get("type", "")) == "heal" and String(r.get("source_class", "")) == "fx_board_refresh":
|
||||
heal_rows1.append(r)
|
||||
if String(r.get("type", "")) == "reward_ineffective" and String(r.get("batch_key", "")) == "round_swap_rest":
|
||||
idle_rows1 += 1
|
||||
Kit.check("V9 R1 轮末回复=min(3,缺血%d) 且层清 0(heal 行值 %s)〔换图系批 V9〕" % [missing, str(heal_rows1.map(func(r): return int(r.value)))],
|
||||
missing >= 3 and heal_rows1.size() == 1 and int((heal_rows1[0] as Dictionary).get("value", -1)) == 3 and _counter(orch1, "round_swap_rest") == 0)
|
||||
# R2 满血未生效:首轮刷新后停手——授予段 heal 时点主角仍满血(combat 段还手在其后)
|
||||
var orch2 = _orch(46052)
|
||||
var rows2: Array = []
|
||||
orch2.step_row.connect(func(row): rows2.append(row))
|
||||
Kit.check("V9 R2 前置:战斗受理", orch2.begin_battle(_enc(["tunnel_rest"], 8)))
|
||||
Kit.check("V9 R2 首轮刷新受理(voucher_rap 入池)", orch2.player_request_refresh())
|
||||
orch2.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var heal_rows2 := 0
|
||||
var idle2 := 0
|
||||
for r2_v in rows2:
|
||||
var r2 := r2_v as Dictionary
|
||||
if String(r2.get("type", "")) == "heal" and String(r2.get("source_class", "")) == "fx_board_refresh":
|
||||
heal_rows2 += 1
|
||||
if String(r2.get("type", "")) == "reward_ineffective" and String(r2.get("batch_key", "")) == "round_swap_rest":
|
||||
idle2 += 1
|
||||
Kit.check("V9 R2 满血未生效行在案且零 heal 行(未生效 %d·heal %d)〔换图系批 V9〕" % [idle2, heal_rows2],
|
||||
idle2 == 1 and heal_rows2 == 0 and _counter(orch2, "round_swap_rest") == 0)
|
||||
# R3 自然累计:同轮双刷 → 回复 2(上限 3 的闸面由 R1 白盒钉住,此处证自然路径)
|
||||
var orch3 = _orch(46053)
|
||||
var rows3: Array = []
|
||||
orch3.step_row.connect(func(row): rows3.append(row))
|
||||
Kit.check("V9 R3 前置:战斗受理", orch3.begin_battle(_enc(["tunnel_rest"])))
|
||||
_bank_rap(orch3, 2)
|
||||
Kit.check("V9 R3 同轮双刷受理", orch3.player_request_refresh() and orch3.player_request_refresh())
|
||||
Kit.check("V9 R3 自然累计 2 层", _counter(orch3, "round_swap_rest") == 2)
|
||||
orch3.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var heal3 := 0
|
||||
for r3_v in rows3:
|
||||
if String((r3_v as Dictionary).get("type", "")) == "heal" and String((r3_v as Dictionary).get("source_class", "")) == "fx_board_refresh":
|
||||
heal3 += 1
|
||||
Kit.check("V9 R3 轮末 heal 行值 2(自然累计路径)〔换图系批 V9〕",
|
||||
heal3 == 1 and _counter(orch3, "round_swap_rest") == 0)
|
||||
|
||||
|
||||
# V8 蓄力周转:当轮攻击消费全部层数(上限 3 闸=白盒预置;战斗新建自然清空)
|
||||
func test_charge_layers_consumed_same_round() -> void:
|
||||
print("--- V8 蓄力周转:攻击消费层 ---")
|
||||
var orch1 = _orch(46061)
|
||||
var rows1 := _collect_damage_rows(orch1)
|
||||
Kit.check("V8 前置:战斗受理", orch1.begin_battle(_enc(["charge_rotation"], 16)))
|
||||
# 上限 3 闸:白盒预置 3 层后刷新被拒层(when<3)
|
||||
EffectEngineScript.counter_add(orch1.fx_host().counters_ctx, "swap_charge_layers", 3)
|
||||
Kit.check("V8 上限 3 闸(预置 3 刷新不加层)", orch1.player_request_refresh() and _counter(orch1, "swap_charge_layers") == 3)
|
||||
# 当轮攻击消费:停手 → 主角先手攻击 → 层数全消费清零
|
||||
orch1.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var attack_rows := 0
|
||||
for r_v in rows1:
|
||||
if String((r_v as Dictionary).get("source_class", "")) == "hero_attack":
|
||||
attack_rows += 1
|
||||
Kit.check("V8 当轮攻击消费全部层(攻击行在案 %d·层清 0)〔换图系批 V8〕" % attack_rows,
|
||||
attack_rows >= 1 and _counter(orch1, "swap_charge_layers") == 0)
|
||||
# 自然累计:双刷 2 层(voucher_rap 16 入池)→ 停手消费归零
|
||||
var orch2 = _orch(46062)
|
||||
Kit.check("V8 前置:战斗受理", orch2.begin_battle(_enc(["charge_rotation"], 16)))
|
||||
Kit.check("V8 战斗新建层 0(引擎重建自然清空)", _counter(orch2, "swap_charge_layers") == 0)
|
||||
Kit.check("V8 双刷累计 2 层", orch2.player_request_refresh() and orch2.player_request_refresh() and _counter(orch2, "swap_charge_layers") == 2)
|
||||
orch2.minesweeper.settle_batch([{"action": "stop"}])
|
||||
Kit.check("V8 攻击后层清 0(消费面闭合)〔换图系批 V8〕", _counter(orch2, "swap_charge_layers") == 0)
|
||||
|
||||
|
||||
# V7 崩壁冲击:延迟群伤单(刷新时点零伤害行——战斗段末按存活目标结账)
|
||||
func test_blast_defers_to_combat_segment() -> void:
|
||||
print("--- V7 崩壁冲击:延迟群伤 ---")
|
||||
var orch = _orch(46071)
|
||||
var rows := _collect_damage_rows(orch)
|
||||
Kit.check("V7 前置:战斗受理", orch.begin_battle(_enc(["wall_blast"], 8)))
|
||||
Kit.check("V7 刷新受理(voucher_rap 入池)", orch.player_request_refresh())
|
||||
Kit.check("V7 刷新时点零伤害行(授予段不结账——案C 延迟)〔换图系批 V7〕",
|
||||
_damage_rows_by_source(rows, "fx_board_refresh").is_empty())
|
||||
orch.minesweeper.settle_batch([{"action": "stop"}])
|
||||
var blast_rows := _damage_rows_by_source(rows, "fx_board_refresh")
|
||||
Kit.check("V7 战斗段末群伤单恰一单(全体存活敌 ×2——行值 2 count≥1)〔换图系批 V7〕",
|
||||
blast_rows.size() == 1 and int((blast_rows[0] as Dictionary).get("value", -1)) == 2
|
||||
and int((blast_rows[0] as Dictionary).get("count", 0)) >= 1)
|
||||
|
||||
|
||||
# ---- V11 数据与池(迭代 46 卡A T6)----
|
||||
|
||||
# 七件 validate/在册/稀有度 cap 对表/跨表计数器引用闭合/desc 禁词
|
||||
func test_seven_feats_validate_and_pool() -> void:
|
||||
print("--- V11 七件数据与池 ---")
|
||||
var seven := {"vein_reserve": "excellent", "easy_swap": "excellent", "wall_blast": "excellent",
|
||||
"charge_rotation": "excellent", "stone_mitigation": "common", "tunnel_rest": "common", "mine_profit": "rare"}
|
||||
Kit.check("V11 feats.validate 零违例(七行全过词表/行键白名单/前缀校验)〔换图系批 V11〕",
|
||||
_db.crossrun.feats.validate().is_empty())
|
||||
var all_in := true
|
||||
var desc_bad := 0
|
||||
for fid in seven.keys():
|
||||
var row: Dictionary = _db.crossrun.feats.row_by_id(String(fid))
|
||||
if row.is_empty() or String(row.get("rarity", "")) != String(seven[fid]) or int(row.get("cap", 0)) != 1:
|
||||
all_in = false
|
||||
if String(row.get("desc", "")).contains("雷") or String(row.get("desc", "")).contains("旗"):
|
||||
desc_bad += 1
|
||||
Kit.check("V11 七行在册且稀有度/cap 逐件对表〔换图系批 V11〕", all_in)
|
||||
Kit.check("V11 七件 desc 禁词零命中(雷/旗字面)〔换图系批 V11〕", desc_bad == 0)
|
||||
# 跨表计数器引用闭合(判据域=换图系七件自身:value_counter/when-id 读取全部有 counter_add 写入方;
|
||||
# 预存行的消费点记账形态〔如完美保险 insurance_used 由授予段落账〕不在此判据域)
|
||||
var written := {}
|
||||
for row_v in (_db.crossrun.feats.rows as Array):
|
||||
for tv in ((row_v as Dictionary).get("triggers", []) as Array):
|
||||
var do_d: Dictionary = (tv as Dictionary).get("do", {})
|
||||
if String(do_d.get("kind", "")) == "counter_add":
|
||||
written[String(do_d.get("counter_id", ""))] = true
|
||||
var refs_ok := true
|
||||
for fid2 in seven.keys():
|
||||
var row2: Dictionary = _db.crossrun.feats.row_by_id(String(fid2))
|
||||
for tv2 in ((row2.get("triggers", []) as Array)):
|
||||
var tr2 := tv2 as Dictionary
|
||||
var do2: Dictionary = tr2.get("do", {})
|
||||
for reader in [String(do2.get("value_counter", "")), String(do2.get("value_from", ""))]:
|
||||
if reader != "" and not written.has(reader):
|
||||
refs_ok = false
|
||||
for c_v in (tr2.get("when", []) as Array):
|
||||
var cid := String((c_v as Dictionary).get("id", ""))
|
||||
if (c_v as Dictionary).get("fact", "") == "counter" and cid != "" and not written.has(cid):
|
||||
refs_ok = false
|
||||
Kit.check("V11 七件跨表计数器引用闭合(value_counter/when-id 全部有 counter_add 写入方)〔换图系批 V11〕", refs_ok)
|
||||
Kit.check("V11 换图系三计数器在写入集(swap_charge_layers/round_swap_guard/round_swap_rest)〔换图系批 V11〕",
|
||||
written.has("swap_charge_layers") and written.has("round_swap_guard") and written.has("round_swap_rest"))
|
||||
@@ -0,0 +1 @@
|
||||
uid://bmsh0idfmpw3j
|
||||
@@ -461,8 +461,8 @@ func _smoke_adventure() -> void:
|
||||
|
||||
func _smoke_feats() -> void:
|
||||
print("--- 专长重设计实装(feat_table 四级 · 专长带池接线 · 订阅面逐件)---")
|
||||
# ① 现行表牌库构成:30 件全量入池——102 数值令牌+30 relic 令牌(四级 rarity 直映射)
|
||||
Kit.check("feat_table 已加载(30 件=基础 27+迁入 2+卡② 完美保险 1——迭代 31 卡② 换代)", _db.crossrun.feats != null and (_db.crossrun.feats.rows as Array).size() == 30)
|
||||
# ① 现行表牌库构成:37 件全量入池——102 数值令牌+37 relic 令牌(四级 rarity 直映射)
|
||||
Kit.check("feat_table 已加载(37 件=基础 27+迁入 2+完美保险 1+迭代 46 换图系七件——换代)", _db.crossrun.feats != null and (_db.crossrun.feats.rows as Array).size() == 37)
|
||||
Kit.check("feat_table.validate 零违例(四级 rarity/cap 域/trigger 词表/行键白名单全过)", _db.crossrun.feats.validate().is_empty())
|
||||
var a_r0 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(71))
|
||||
Kit.check("专长带场景:冒险启动(seed 71)", a_r0.start_adventure(71))
|
||||
@@ -473,7 +473,7 @@ func _smoke_feats() -> void:
|
||||
feat_tokens += 1
|
||||
var tk := String((t as Dictionary).get("tier", ""))
|
||||
tier_counts[tk] = int(tier_counts.get(tk, 0)) + 1
|
||||
Kit.check("专长带入池:30 件四级直映射(普通 12/优秀 9/稀有 9/传说 0)——牌库 102+30=132〔专长批 V2+卡② 完美保险迁入〕", feat_tokens == 30 and int(tier_counts.get("common", 0)) == 12 and int(tier_counts.get("excellent", 0)) == 9 and int(tier_counts.get("rare", 0)) == 9 and a_r0.deck().deck.size() == 132)
|
||||
Kit.check("专长带入池:37 件四级直映射(普通 14/优秀 13/稀有 10/传说 0)——牌库 102+37=139〔专长批 V2+迭代 46 换图系七件换代〕", feat_tokens == 37 and int(tier_counts.get("common", 0)) == 14 and int(tier_counts.get("excellent", 0)) == 13 and int(tier_counts.get("rare", 0)) == 10 and a_r0.deck().deck.size() == 139)
|
||||
# ② 旧 27 件零残留钉面(V2——arcane_ember 系旧件表首行;全仓 grep 零残留归静态核查)
|
||||
Kit.check("旧 27 件已退役:arcane_ember/magma_body 表内零残留〔专长批 V2〕", _db.crossrun.feats.row_by_id("arcane_ember").is_empty() and _db.crossrun.feats.row_by_id("magma_body").is_empty())
|
||||
Kit.check("迁出收尾:treasure_items 无 venom_edge/seal_burst 行(同调目录自然收窄)〔专长批 V13〕", _db.crossrun.treasure_items.row_by_id("venom_edge").is_empty() and _db.crossrun.treasure_items.row_by_id("seal_burst").is_empty())
|
||||
|
||||
@@ -51,21 +51,29 @@ func _mk_stream(stream_name: String, scope: int) -> RandomNumberGenerator:
|
||||
# 公式 N×cell ≤ 可用高−12 必须计入 (N−1)×2px 网格间距,否则网格实高溢出被 clip_contents 裁掉;
|
||||
# 现公式 = 计入间距 + 垂直预留 24px〔上 12/下 12——底部不贴 D 区边框〕)----
|
||||
func _smoke_layout_cell_formula() -> void:
|
||||
print("--- 棋盘布局格边长公式(底部预留回归)---")
|
||||
print("--- 棋盘布局格边长公式(底部预留回归·四档板型)---")
|
||||
var board_generator = load("res://core/board_generator.gd").new()
|
||||
var board_view = load("res://presentation/views/board_view.gd").new()
|
||||
for L in [1, 2]:
|
||||
var b = board_generator.generate(L, 0, _mk_stream("board_gen", 555), _db)
|
||||
var board_view_script := load("res://presentation/views/board_view.gd")
|
||||
# 四档取样表(board_gen.tres 实表取档——(L,D)→尺寸:10/12/13/14;13×13 与 14×14 首次入断言)
|
||||
var tiers := [{"L": 1, "D": 0, "n": 10}, {"L": 2, "D": 0, "n": 12}, {"L": 3, "D": 0, "n": 13}, {"L": 3, "D": 9, "n": 14}]
|
||||
for t_v in tiers:
|
||||
var t: Dictionary = t_v
|
||||
var b = board_generator.generate(int(t["L"]), int(t["D"]), _mk_stream("board_gen", 555), _db)
|
||||
board_view.rebuild(b, null)
|
||||
var avail := Vector2(1036, 460) # 受约束 D 区可用面积样本(1280×800 档量级——用户实测裁切场景)
|
||||
board_view.set_cell_area(avail)
|
||||
var n: int = maxi(b.width, b.height)
|
||||
var cell: float = board_view.get("_cell")
|
||||
var grid_h := n * int(cell) + (n - 1) * 2
|
||||
Kit.check("L%d %dx%d 板网格高 %d ≤ 可用高 %d − 预留 24(格边 %dpx——下缘不贴边不裁切)" % [L, b.width, b.height, grid_h, int(avail.y), int(cell)],
|
||||
Kit.check("L%d D%d 板型一致(%dx%d = 取样 %d——表改动致取样落错档即红)〔格边长 V3〕" % [int(t["L"]), int(t["D"]), b.width, b.height, int(t["n"])],
|
||||
n == int(t["n"]))
|
||||
Kit.check("L%d D%d %dx%d 板网格高 %d ≤ 可用高 %d − 预留 24(格边 %dpx——下缘不贴边不裁切)〔格边长 V3〕" % [int(t["L"]), int(t["D"]), b.width, b.height, grid_h, int(avail.y), int(cell)],
|
||||
grid_h <= int(avail.y) - 24)
|
||||
Kit.check("L%d 格边在 26–46 档内(%dpx)" % [L, int(cell)],
|
||||
Kit.check("L%d D%d 格边在 26–46 档内(%dpx)〔格边长 V3〕" % [int(t["L"]), int(t["D"]), int(cell)],
|
||||
cell >= 26.0 and cell <= 46.0)
|
||||
Kit.check("L%d D%d 算式单点等价(set_cell_area 写入 %d == _cell_for 返回 %d——同一事实两路读取)〔格边长 V2〕" % [int(t["L"]), int(t["D"]), int(cell), board_view_script._cell_for(n, avail)],
|
||||
int(cell) == board_view_script._cell_for(n, avail))
|
||||
board_view.free()
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ func _init() -> void:
|
||||
# ① 词表在册断言(扩签面:2 事件+8 事实+7 效果类型+1 算子)
|
||||
Kit.check_quiet(EffectEngineScript.EVENTS.has("dig_stop") and EffectEngineScript.EVENTS.has("battle_won"),
|
||||
"新事件在册:dig_stop/battle_won〔专长批 V1〕")
|
||||
# ①-a 换图系两事件两效果在册(迭代 46 扩签——旧出域负例全部保留)
|
||||
Kit.check_quiet(EffectEngineScript.EVENTS.has("refresh_request") and EffectEngineScript.EVENTS.has("board_refreshed"),
|
||||
"换图系新事件在册:refresh_request/board_refreshed〔换图系批 V1〕")
|
||||
Kit.check_quiet(EffectEngineScript.EFFECT_KINDS.has("grant_reserve_ap") and EffectEngineScript.EFFECT_KINDS.has("apply_discount"),
|
||||
"换图系新效果在册:grant_reserve_ap/apply_discount〔换图系批 V1〕")
|
||||
Kit.check_quiet(EffectEngineScript.FACTS.has("hp_ratio") and EffectEngineScript.FACTS.has("is_edge_cell")
|
||||
and EffectEngineScript.FACTS.has("new_resource_type") and EffectEngineScript.FACTS.has("dug_under_seal")
|
||||
and EffectEngineScript.FACTS.has("ap_exhausted_last") and EffectEngineScript.FACTS.has("ap_left")
|
||||
|
||||
@@ -199,7 +199,7 @@ func _test_negative_cases() -> void:
|
||||
# 现行 31;本套件零扩签,钉现行数(将来任何加词即转红提示复核)。
|
||||
|
||||
func _test_effect_kinds_closed() -> void:
|
||||
Kit.check("效果引擎效果类型闭集 32 种(锻造工坊批零新增口径随迭代 31 卡② 扩签 forgive_seal_miss 换代)〔锻造工坊批 V11〕",
|
||||
EffectEngineScript.EFFECT_KINDS.size() == 32)
|
||||
Kit.check("效果引擎事件词表在册 20 种(本批零扩签参照面)〔锻造工坊批 V11〕",
|
||||
EffectEngineScript.EVENTS.size() == 20)
|
||||
Kit.check("效果引擎效果类型闭集 34 种(迭代 46 换图系扩签 grant_reserve_ap/apply_discount 换代)〔锻造工坊批 V11〕",
|
||||
EffectEngineScript.EFFECT_KINDS.size() == 34)
|
||||
Kit.check("效果引擎事件词表在册 22 种(迭代 46 换图系扩签 refresh_request/board_refreshed 换代)〔锻造工坊批 V11〕",
|
||||
EffectEngineScript.EVENTS.size() == 22)
|
||||
@@ -228,16 +228,14 @@ func _smoke_enemy_bands() -> void:
|
||||
int(row.get("depth_band", -1)), String(row.get("enemy_id", ""))])
|
||||
Kit.check("敌人表 28 行且键序 = 覆盖表序((L,row_kind,depth_band,enemy_id) 逐行比对——文件行序不变)〔fv11〕",
|
||||
_db.combat.enemy.rows.size() == 28 and got_keys == expect_keys)
|
||||
# ② hobgoblin 缺口行留任随迁(契约 9:不删行不补立绘——缺口登记随行)
|
||||
# ② hobgoblin 缺口行留任随迁(不删行不补立绘——补齐归敌种内容批)
|
||||
var hob := {}
|
||||
for row in _db.combat.enemy.rows:
|
||||
if String(row.get("enemy_id", "")) == "hobgoblin":
|
||||
hob = row
|
||||
Kit.check("hobgoblin 行在 (1,battle,3) 留任随迁(缺口行不删不补——补齐归敌种内容批)〔fv12〕〔fv25〕",
|
||||
Kit.check("hobgoblin 行在 (1,battle,3) 留任随迁(缺口行不删不补——补齐归敌种内容批)〔fv12〕",
|
||||
int(hob.get("level_index", -1)) == 1 and String(hob.get("row_kind", "")) == "battle" \
|
||||
and int(hob.get("depth_band", -1)) == 3)
|
||||
Kit.check("hobgoblin 缺口登记随行(表文件注释在位——缺口不静默)〔fv25〕",
|
||||
FileAccess.get_file_as_string("res://data/tables/enemy.tres").contains("hobgoblin 行为缺口行"))
|
||||
# ③ Boss 行集带键 = 覆盖表(旧判据「各恰一行=图 Boss 节点深度」属单终点模板时代;
|
||||
# 生成图多终点要求每终点深度解析到互异带键 ⇒ 每关 Boss 行必然多于一行——
|
||||
# 迭代 35 覆盖批随动改写为带键清单,「带键互异」的运行时把关在 level_shop_economy_test〔v11〕)
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 战斗一屏样张批 V5–V9 断言面(2026-10-29 迭代 43)——五项实装定值的真实入口断言:
|
||||
# 战斗一屏样张批 V5–V12 断言面(2026-10-29 迭代 43 立五项;2026-10-31 迭代 46 卡B 增 V10–V12)——
|
||||
# 实装定值的真实入口断言:
|
||||
# V5 血条填充 = 危险红(UiKit.HP_BAR_FILL 值单点 + 绘制点源码锚:全仓零 #689CE8 与零裸
|
||||
# Color(0.41,0.61,0.91);条底收 HP_BAR_TRACK 常量);
|
||||
# V6 站桩名字行垫 HP_BAR_BACK 素底且不压地台(名字行基线 y < 地台顶 y——name_line_probe 几何出口);
|
||||
# V7 顺位徽标提档 UiKit.FS_HINT(值断言 + 绘制点源码锚,§7.4 清单外 11–13px 提档);
|
||||
# V8 护甲图标三键(light/ward/heavy)绑对应 24×24 PNG(ResourceLoader 装载结果 + name_line_probe
|
||||
# 绑定面);
|
||||
# V9 地台件 scene_stage_plaza.png + 护甲三枚入包可加载且尺寸 48×12 / 24×24(§5.2/§5.3 工单)。
|
||||
# V9 地台件 scene_stage_plaza.png + 护甲三枚入包可加载且尺寸 48×12 / 24×24(§5.2/§5.3 工单);
|
||||
# V10 名字行提档 FS_HINT 14(探针 name_font_size 实读 + 两绘制点源码锚 + FS_CAPTION 计数锚==1);
|
||||
# V11 退役常量不在册 + 掩尘 BRICK 逐位 + 顶缘线/口沿高光两绘制点改指源码锚;
|
||||
# V12 PLAZA_EDGE 逐位 #4C4038 + 回退描边改指源码锚。
|
||||
# headless 无渲染面:像素采样以常量单点 + 源码锚 + 探针几何承载(观测面注记,验收对照表 V5 行)。
|
||||
# 运行:godot --headless --path game --script res://tests/unit/presentation/standee_present_values_test.gd(expect 0)
|
||||
extends SceneTree
|
||||
@@ -48,14 +52,39 @@ func _init() -> void:
|
||||
Rect2(nl.plate).end.y <= float(nl.plinth_top_y) + 0.01)
|
||||
Kit.check("名字行素底 = HP_BAR_BACK 深档 #282220(挂载底色口径)〔样张批 V6〕",
|
||||
Color(nl.plate_color).to_html(false) == "282220")
|
||||
Kit.check("基线读数与实装几何同源(基线 = 地台顶上方 9px 档:149 < 158)〔样张批 V6〕",
|
||||
absf(float(nl.baseline_y) - 149.0) < 0.51 and absf(float(nl.plinth_top_y) - 158.0) < 0.51)
|
||||
Kit.check("基线读数与实装几何同源(基线 = 地台顶上方 8px 档:150 < 158——14px 档牌顶+18)〔样张批 V6〕",
|
||||
absf(float(nl.baseline_y) - 150.0) < 0.51 and absf(float(nl.plinth_top_y) - 158.0) < 0.51)
|
||||
|
||||
# ---- V7 顺位徽标提档 FS_HINT ----
|
||||
Kit.check("FS_HINT = 14(§7.4 六档)〔样张批 V7〕", UiKit.FS_HINT == 14)
|
||||
Kit.check("顺位徽标绘制点取 UiKit.FS_HINT(源码锚)〔样张批 V7〕",
|
||||
body_src.contains("HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT"))
|
||||
|
||||
# ---- V10 名字行提档 FS_HINT 14(迭代 46 卡B——五取值点+基线随档联动) ----
|
||||
Kit.check("名字行探针字号实读 = FS_HINT(几何单点出口 name_font_size)〔名字行 V10〕",
|
||||
int(nl.name_font_size) == UiKit.FS_HINT)
|
||||
Kit.check("名字与护甲两绘制点取 FS_HINT(源码锚——沿 V7 先例)〔名字行 V10〕",
|
||||
body_src.contains("HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT, UiKit.WARM")
|
||||
and body_src.contains("HORIZONTAL_ALIGNMENT_LEFT, -1, UiKit.FS_HINT, col"))
|
||||
Kit.check("全文件 FS_CAPTION 仅剩消散提示一处(计数锚==1——三处宽度测量点强制换代)〔名字行 V10〕",
|
||||
body_src.count("UiKit.FS_CAPTION") == 1)
|
||||
|
||||
# ---- V11/V12 地台色合并(迭代 46 卡B——常量面载体=Script 常量表,源码锚正证改指目标色) ----
|
||||
var uikit_script: Script = load("res://presentation/views/ui_kit.gd")
|
||||
var cmap: Dictionary = uikit_script.get_script_constant_map()
|
||||
var cell_src := _read_source("res://presentation/views/cell_base_layer.gd")
|
||||
Kit.check("退役常量不在册(STAND_STONE_RIM/STAND_STONE_EDGE 零键)〔名字行 V11〕",
|
||||
not cmap.has("STAND_STONE_RIM") and not cmap.has("STAND_STONE_EDGE"))
|
||||
Kit.check("掩尘 BRICK 值逐位 #C9AF83(合并目标①)〔名字行 V11〕",
|
||||
UiKit.BRICK.to_html(false) == "c9af83")
|
||||
Kit.check("顶缘受光线与口沿高光两绘制点改指 BRICK(源码锚)〔名字行 V11〕",
|
||||
body_src.contains("ped.size.x, 2.0), UiKit.BRICK, true")
|
||||
and cell_src.contains("FACADE_HIGHLIGHT_PX), UiKit.BRICK, true"))
|
||||
Kit.check("PLAZA_EDGE 值逐位 #4C4038(合并目标②)〔名字行 V12〕",
|
||||
UiKit.PLAZA_EDGE.to_html(false) == "4c4038")
|
||||
Kit.check("回退描边绘制点改指 PLAZA_EDGE(源码锚)〔名字行 V12〕",
|
||||
body_src.contains("UiKit.PLAZA_EDGE"))
|
||||
|
||||
# ---- V8 护甲图标三键绑 24×24 PNG ----
|
||||
var armor_paths := {"light": UiKit.TEX_ARMOR_LIGHT, "ward": UiKit.TEX_ARMOR_WARD,
|
||||
"heavy": UiKit.TEX_ARMOR_HEAVY}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 迭代 46 GDD 反哺点清单(2026-10-31)
|
||||
|
||||
> 接收方:待办清单「反哺点专条」通道——用户会话逐条裁决后由文档批写入 `design/`,写入后本清单条目清掉(吸收即死)。
|
||||
> 依据:迭代 46 实现报告(同目录)与实测评读数。实现批禁写 `design/`,以下为待裁决落文面。
|
||||
|
||||
## 卡A 换图系双基座七件批
|
||||
|
||||
1. **[奇物.md]** 基础件表(或专长实装状态句):七件(矿脉储能/省力周转/崩壁冲击/蓄力周转/石层缓冲/坑道小憩/矿道红利)由设计声明改为**已实装**(feats.tres 37 行、稀有度 14/13/10/0、cap 均 1);「双基座叠加、后续效果本轮五段结算内兑付」已在案零改述。依据=实现报告 §二 V2–V11。
|
||||
2. **[行动经济.md]** 两件基座由「待实现」改为在册:付费挖格 +1 RAP(受理后一次性入池、拒绝轮零入池)、刷新成本折价 50%(floor 取整、can 与执行同源、只改门槛与扣费不改拒绝判据)。依据=V2/V3。
|
||||
3. **[战斗结算.md]** 全局 `damage_taken` 落码状态补记:敌方攻击/地形/危险格/错误封印资源直伤四路径统一经唯一发射口与唯一消费族;**地形路径消费面自三件扩为五件(+shield)——铁壁自此对地形伤害生效;危险格/错误封印直伤路径自此纳入 damage_taken 订阅面**(用户已裁全局语义,实现报告 §六);成功刷新事实 `board_refreshed` 为七件订阅主挂点(装新板后恰一次发射)。依据=V5/V4。
|
||||
4. **[地图战斗资源.md]** 清图奖励语义确认句:矿道红利不绑清图奖励(每次成功刷新固定 +1 GP 走战斗内缓冲,不读旧图探索进度、不触发清图事件;刷新图零清图奖励守卫不变)——若现行正文已含此意则零改(本行核对性反哺)。依据=V10/V12。
|
||||
5. **[architecture.md]** 「模块归属」增补/现状化三行:①**BattleRefreshFlow**(新 B1 域拆件——刷新可用性门/折价扣费/换图执行/成功事实登记,调用路径呈现层→编排器单行转发→流程件→行动经济/装板壳/授予段;static_scan S7_B1_SET 已随批增补该文件,判据口径不变);②**damage_controller** 行现状化(damage_taken 唯一发射口 `_emit_hero_damage_taken`+唯一消费族 `_apply_hero_damage_effects`(原名 _enemy_shield_apply 改名)+board_flat_hero 结账前统一发射);③**action_economy** 行现状化(dig_paid 命中施加抽私有 `_apply_dig_paid_hits` 单点;request_refresh 收折后价入参)+**grant_segment** 行现状化(apply_board_refreshed 成功事实消费+round_end heal value_counter 兑付面)。依据=实现报告 §五/§八.6。
|
||||
|
||||
## 卡B 站桩名字行提档与地台色合并批
|
||||
|
||||
6. **[art-bible.md §4.1]** 换色合并登记①②句的代码指称换代:①「代码 `STAND_STONE_RIM`」②「代码 `STAND_STONE_EDGE`」两源常量已删除(全仓零引用——唯一残留=退役断言测试串,预期例外);②合并目标 `#4C4038` 补代码名 **`PLAZA_EDGE`**(ui_kit 唯一落点)。依据=卡B 对照表 3/4 行+grep 取证(实现报告 §三)。
|
||||
7. **[art-bible.md §8.2]** 高墙瓦片体系条口沿高光行:「Color8(196,172,132)」值随换值换代为 **`#C9AF83`(201,175,131)**(并档掩尘枚 BRICK 单点);程序化回退顶缘线与口沿高光两绘制点已改指。依据=对照表 3 行。
|
||||
|
||||
## 卡C 棋盘格边长口径收口批(停摆——随裁决落文)
|
||||
|
||||
8. **[battle.md §棋盘格尺寸公式]** 算例表(:148-152)与实机偏差实测落点:1280 档实板可用面积 **(1022, 454)**(算例假设 486 可用高)→ 实测 L1 格边 40px、13×13 推定 30px(恰达标)、**14×14 推定 28px(低于可读下限 30)**;1080 档 (1662, 734) → L1=46、13/14 推定=46(钳制顶格)。落文方向随「30px 下限适用域」裁决(读法甲/乙见停机呈报 §三):读法乙需补「下限按视口档分级」条+算例表填实测值或标注「按旧布局口径」。依据=停机呈报 §一/§四。
|
||||
|
||||
## 术语表
|
||||
|
||||
9. 零新增术语——本批新名(BattleRefreshFlow/_cell_for/PLAZA_EDGE/counter_id 三枚)均属代码标识符与数据行键,不入术语表(登记口径=概念规范名)。
|
||||
@@ -0,0 +1,12 @@
|
||||
# 迭代 46 GDD 反哺点清单——卡C(2026-11-01)
|
||||
|
||||
> 接收方:待办清单「反哺点专条」通道——用户会话逐条裁决后由文档批写入 `design/`,写入后本清单条目清掉(吸收即死)。
|
||||
> 卡A/卡B 反哺条见同目录 `iter46-反哺点-2026-10-31.md`;本文件只收卡C v2.0。
|
||||
|
||||
1. **[battle.md §棋盘格尺寸公式 :144]** 「可读下限 30px——与结构钳制分开:钳制管算式不越界,下限管玩家能否看清」整句**退役**:整句删除,或改写为「格边长可读性以用户验收的现行画面为基准;结构钳制 [26,46] 管算式不越界」(措辞由文档批裁)。依据=2026-11-01 用户三项裁定(锚点=用户验收的现行渲染值,基座档 14×14=28px 达标;30 无实测背书)+停机呈报读数链(`reports/停机呈报-棋盘格边长口径收口批-2026-10-31.md`)+实现报告 §四锚点留档(`iter46-实现报告-卡C-2026-11-01.md`)。随句建议同节载明判据现行形态:全域禁人造格边长可读阈值,接线守卫=生产写入值与单点算式严格相等,最大板推定读数留痕不作判红。
|
||||
|
||||
2. **作废声明**:`iter46-反哺点-2026-10-31.md` 第 8 条(battle.md 算例表改数——随「30px 下限适用域」读法甲/乙裁决落文)**作废**——`:148-152` 算例表已随布局几何单点化批(1cdef6ba)退役,无落点;读法甲/乙之争已被 2026-11-01 用户三项裁定取代(下限句退役,不再有适用域问题)。文档批落文时以本条为准,10-31 清单第 8 条不再执行。
|
||||
|
||||
## 术语表
|
||||
|
||||
零新增术语——本批新名 `_cell_for` 属代码标识符,不入术语表(登记口径=概念规范名)。
|
||||
@@ -0,0 +1,109 @@
|
||||
# 迭代 46 实现报告(2026-10-31)
|
||||
|
||||
> 批次:迭代 46 三卡——卡A 换图系双基座七件批 · 卡B 站桩名字行提档与地台色合并批 · 卡C 棋盘格边长口径收口批。
|
||||
> 工作区:`D:\code\g-plan2-iter46`(分支 iter46,自 b5b2c555 检出)。
|
||||
> **批内状态总览:卡A 收口 · 卡B 收口 · 卡C 停摆(L3 #2 预设停机点,呈报见主区 `reports/停机呈报-棋盘格边长口径收口批-2026-10-31.md`)**。合并阻塞等裁决。
|
||||
|
||||
## 一、各卡状态
|
||||
|
||||
| 卡 | 状态 | 出口证据 |
|
||||
|---|---|---|
|
||||
| 卡A 换图系双基座七件批 | **收口**(T0–T8 全落) | `tools/run_all_gates.sh --code` 7 闸全绿(回执 commit 45b53d68 时点);此后 S9/S7 修正与卡B 提交待迭代级复跑 |
|
||||
| 卡B 站桩名字行提档与地台色合并批 | **收口**(T0–T3 全落) | standee_present_values_test 26 checks 绿;golden 板面三张 0.00% 留痕;gdstyle 零新增键 |
|
||||
| 卡C 棋盘格边长口径收口批 | **停摆**(T0 完成;T1–T3 改动已验未提交;T4 未走) | 卡C §9 L3 #2:实板可用面积代入 14×14 得 28px < 30px(1280 档)——停卡呈报等裁决 |
|
||||
|
||||
## 二、卡A 实际对照表(改动—验收)
|
||||
|
||||
| 需求点 | 改动(文件:行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 结果 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| V1 词表扩签 | effect_engine.gd EVENTS 20→22/MINE_EVENTS 同步换图刷新面/EFFECT_KINDS 32→34;forge_table/effect_words 计数换代 | `effect_words_t1_test.gd:_init`(新增①-a 两断言);`forge_table_test.gd:_test_effect_kinds_closed` | 单元 | validate 与整表加载 | EVENTS=22、EFFECT_KINDS=34、出域仍拒(旧负例全保留) | 绿(20/41 checks) |
|
||||
| V2 矿脉储能 | action_economy.gd dig_paid 命中环累计 grant_reserve_ap(扣费受理后一次性入池·拒绝轮零入池);feats.tres vein_reserve 行 | `refresh_feats_test.gd:test_reserve_on_accepted_dig` | 接口 | `settle_batch(dig)`(AutoPlayer 真实挖掘) | RAP 恰+1(8→9)、AP 按表扣(8→7)、耗尽轮增量==受理挖数 | 绿 |
|
||||
| V3 省力周转 | BattleRefreshFlow `_effective_refresh_cost`(声明序第一命中 floor(base×mult/100),can 与执行同源);request_refresh 收折后价入参;easy_swap 行 | `test_refresh_discount_gate_and_charge`;`test_double_base_stack` | 接口 | `player_request_refresh()` | base 8→扣 4;两次折后扣尽 8→0;门槛拒零受理;双基座同场生效 | 绿 |
|
||||
| V4 成功事实 | battle_refresh_flow execute 成功序(折价扣RAP→used+1→旧资源退役→旧板退役→装新板→apply_board_refreshed);编排器两公开方法单行转发 | `test_board_refresh_fact_only_on_success` | 集成 | `player_request_refresh()` | 非 Active/每轮上限/RAP 不足三拒面零事实零换图(probe_br_counter 计数+board_changed 双观测);成功恰一次 | 绿 |
|
||||
| V5 全局受伤 | damage_controller `_emit_hero_damage_taken` 唯一发射口+`_apply_hero_damage_effects` 唯一消费族(改名自 _enemy_shield_apply,组合次序冻结);敌方攻击/棋盘直伤/地形三路径接入;grant_segment 删本地 _terrain_damage_reduce | `test_all_hero_damage_paths_emit_once`;`test_no_duplicate_damage_taken_event` | 集成 | 敌方攻击、dig danger、seal wrong、terrain 四真实入口 | 每路径承伤单据在案且计数器==行数(逐单恰一次);context 标记闸防地形二次发射 | 绿 |
|
||||
| V6 石层缓冲 | round_swap_guard 计数+damage_taken when≥1 damage_reduce 2(round 桶轮始自清) | `test_stone_mitigation_all_damage` | 集成 | 刷新→危险格(pierce 8)/地形两真实受伤路径 | pierce 8→6(双刷不叠加)、未刷新轮不减(8)、地形 max(下限, effect_value−2) 逐单闭合 | 绿 |
|
||||
| V7 崩壁冲击 | apply_board_refreshed open_ticket blast→reward_grant.defer_ticket(案C 同队列);SOURCE_EXEMPT_CLASSES+fx_board_refresh;wall_blast 行 | `test_blast_defers_to_combat_segment` | 集成 | 刷新→停手 | 刷新时点零伤害行;战斗段末恰一单 ×2 全体存活敌 | 绿 |
|
||||
| V8 蓄力周转 | swap_charge_layers 战斗桶+attack_bonus value_counter+set0(既有消费面零新码) | `test_charge_layers_consumed_same_round` | 接口 | 两次刷新→停手(主角先手攻击) | 双刷 2 层→攻击后 0;白盒预置 3 层时刷新被闸(上限 3);战斗新建 0 | 绿 |
|
||||
| V9 坑道小憩 | round_swap_rest+round_end heal value_counter(grant_segment 新增 `_round_end_heal_value_counter`——先于 set0 行消费层值) | `test_rest_rotation_cap_and_clear` | 集成 | 刷新→停手(轮末授予段) | 回复 min(3,缺血)==3、层清 0、满血发未生效行、自然累计 2 路径 | 绿 |
|
||||
| V10 矿道红利 | board_refreshed grant_gp→escrow+fx_grant_gp 行(apply_board_refreshed 消费);mine_profit 行 | `test_mine_profit_gp` | 集成 | `player_request_refresh()` | escrow 每成功+1(0→1→2)、fx_grant_gp 行在案、拒绝零变化 | 绿 |
|
||||
| V11 数据与池 | feats.tres 七行(rarity 14/13/10/0·cap 1);adventure_feats 30→37/牌库 132→139 | `test_seven_feats_validate_and_pool`;adventure_feats `_smoke_feats` | 单元 | ConfigDB 整表与冒险牌库 | rows 37、relic 37、14/13/10、deck 139、validate 空、禁词 0、七件计数器引用闭合 | 绿(85/138 checks) |
|
||||
| V12 无专长回归 | round_flow/seal 旧基线零改动(刷新体迁移编排器单行转发) | `_smoke_active_refresh`;`_smoke_refresh_provenance_guard`;`test_no_feats_baseline` | 单元+集成 | 现行刷新/清图入口 | RAP8、AP 保留、上限 2、刷新图零清图、挖格零产 RAP、表基线扣费 | 绿(134/70 checks) |
|
||||
|
||||
**窄测实跑记录**:refresh_feats 85 · adventure_feats 138 · round_flow 134 · seal_polarity 70 · damage_controller 44 · effect_words 20 · forge_table 41 · config_db 29——全绿。批末 `--code` 闸 00/01/02/03/05/09/10 全绿(回执 45b53d68)。
|
||||
|
||||
## 三、卡B 实际对照表(改动—验收)
|
||||
|
||||
| # | 需求点 | 改动 | 验收测试 | 结果 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 名字行字号提档 FS_HINT 14 | standee_body.gd 五取值点+name_line_probe 增 name_font_size | 〔名字行 V10〕探针实读==FS_HINT+两绘制点源码锚+FS_CAPTION 计数锚==1 | 绿 |
|
||||
| 2 | 名字行几何随档联动 | _name_baseline 偏移 17→18+注释换代 | V6 换代读数 150±0.51(8px 档)且 < plinth_top_y | 绿 |
|
||||
| 3 | 受光线常量退役改指 BRICK | ui_kit 删 STAND_STONE_RIM;standee_body:386+cell_base_layer:176 改指 | 〔名字行 V11〕常量表零键+BRICK==#C9AF83+两绘制点源码锚;grep 反证(仅剩测试断言串——预期例外) | 绿 |
|
||||
| 4 | 描边常量退役改指新 token | ui_kit 删 STAND_STONE_EDGE+增 PLAZA_EDGE=Color8(76,64,56);standee_body:385 改指 | 〔名字行 V12〕PLAZA_EDGE 逐位+常量表零旧键+描边源码锚 | 绿 |
|
||||
| 5 | 板面 golden 与换值一致 | (预期重锚——实际无需) | render_gate 板面三张 0.00%(改后跑,基线未动) | 绿(见实现决定 #4) |
|
||||
| 6 | 批末收口 | 全批 | 迭代级 --code 闸(待卡C 裁决后统一走) | 待迭代出口 |
|
||||
|
||||
卡B 改前读数(T0):standee_present_values_test 18 checks 绿 · gdstyle 5 键全基线内 · 渲染闸绿(--code 回执 45b53d68 内 05 闸)· 字体度量 ts(14px)=(14,20)。
|
||||
|
||||
## 四、卡C 停摆实况(改动已验未提交)
|
||||
|
||||
- T0 完成:行号重锚(board_view set_cell_area 现 :206-224、layout_probe MIN_CELL :15、冒烟 :53-69);取档对账 resolve_row(1,0)/(2,0)/(3,0)/(3,9)=10/12/13/14 全符;改前读数 board_gen_reward_test 62 绿+layout_probe 两档绿+gdstyle board_view max-public-methods 27 持平。
|
||||
- T1 算式单点:`BoardView._cell_for(n, avail)` 提取(逐位同式)+set_cell_area 改调——等价性由 board_gen_reward_test 既有断言承载(62 checks 绿)+gdstyle 持平。
|
||||
- T2 探针:MIN_CELL 36→30+注释改指 battle.md+BoardViewScript preload+零尺寸前置+13/14 推定断言——**推定断言触发 L3 #2(14×14=28<30)**。
|
||||
- T3 冒烟四档:取样表 [{1,0,10},{2,0,10→12},{3,0,13},{3,9,14}]+板型一致断言+算式单点等价断言——74 checks 绿(单元面全过:钳制 [26,46] 面无越界)。
|
||||
- 三件改动**未提交**(停摆卡不提交),随裁决处置(可复用——行为零变化)。
|
||||
- 停机呈报:主区 `reports/停机呈报-棋盘格边长口径收口批-2026-10-31.md`(分歧读法/建议案/待办回退拟稿)。
|
||||
|
||||
## 五、结构预算(S13 前后)
|
||||
|
||||
| 触面 | 前测 | 后测 | 判定 |
|
||||
|---|---|---|---|
|
||||
| battle_orchestrator.gd | 811 行/类变量 15(卡A 写 38 系笔误) | 803 行(−8 达标)/类变量 15 | 只降不升 ✓ |
|
||||
| reward_grant.gd | 类变量 15 | 15(defer_ticket 为方法零增员) | ✓ |
|
||||
| grant_segment.gd | 类变量 3/公开方法 1 | 3/2(apply_board_refreshed);私有新增 1(_round_end_heal_value_counter)≤4 | ✓ |
|
||||
| damage_controller.gd | 公开方法 9 | 9(私有净增 1:_emit_hero_damage_taken)≤2 | ✓ |
|
||||
| action_economy.gd | 公开方法 15 | 15(命中环抽私有 _apply_dig_paid_hits——S13 分支超限重构,分支本体逐字迁入) | ✓ |
|
||||
| battle_refresh_flow.gd(新件) | — | 公开函数 2(can_refresh/execute)/类变量 0 | ≤20/≤15 ✓ |
|
||||
| gdstyle_gate | 5 键全基线内 | 5 键全基线内零新增零恶化 | ✓ |
|
||||
|
||||
## 六、旧 damage_taken 专长覆盖面变化
|
||||
|
||||
全局统一后,订阅 `damage_taken` 的既有专长(背水 hp_ratio when/石肤 ac_bonus+counter_add/保险丝 counter_add)与换图系石层缓冲的覆盖面变化:
|
||||
|
||||
- **敌方攻击路径**:不变(原即经 _enemy_shield_apply 全组合消费)。
|
||||
- **地形路径**:消费族从本地三件(damage_reduce/ac_bonus/counter_add)扩为全局五件(+shield)——**铁壁(shield)自此对地形伤害生效**(用户已裁全局语义;卡A §十二削弱申报第 2 条在案)。
|
||||
- **危险格/错误封印资源直伤路径(board_flat_hero)**:原零事件,现统一发射——上述专长自此对这些路径生效(同上申报面)。
|
||||
- 无专长基线逐位零漂移(V12 全绿;同一伤害恰一次由 V5 钉死)。
|
||||
|
||||
## 七、实机目检总清单(登记不阻塞)
|
||||
|
||||
1. 〔卡A〕玩家持基座与收益件后,是否主动规划刷新而非只在坏图刷新(行为观感)。
|
||||
2. 〔卡B〕站桩名字行 14px 清晰可读且长名不截字(验收底线句)。
|
||||
3. 〔卡B〕墙格口沿亮线换值后观感无异(#C4AC84→#C9AF83)。
|
||||
4. 〔卡B〕贴图缺位回退描边与顶缘线观感无异(PLAZA_EDGE/BRICK 程序化回退)。
|
||||
5. 〔卡C·停摆批登记〕第三关 14×14 板格面数字在基座档的可辨读性(28px 实况——随裁决)。
|
||||
|
||||
## 八、实现决定记录(超白名单/偏差备案)
|
||||
|
||||
1. **卡A 自洽扫描笔误三处(不改合同)**:「类变量 38」实为 15;gdstyle_baseline.txt:9 引用实无 battle_orchestrator 键(该文件现无 S13 键);稀有度断言实挂 :476 非 :465。T0 按实数重锚记录,合同(只降不升/换代判据)不受影响。
|
||||
2. **卡A T0 工具名**:卡写 `bash tools/gdstyle.sh game`——该文件不存在,实际工具 `python tools/gdstyle_gate.py`(与卡B/C 一致),按实跑。
|
||||
3. **MINE_EVENTS 同步口径**:卡A T1「同步 :19 的 MINE_EVENTS」取「两新事件入集」读法——弃图刷新属扫雷侧动作面,流派铁律订阅集随之认列(零机械消费面差异,mine_covered 生产无强制点)。
|
||||
4. **卡B golden 预期红未现**:卡预期「板面三张红→重锚」,实测三张 0.00%——口沿高光换值 #C4AC84→#C9AF83 每通道差 ≤5,低于逐像素容差(≤16 差/≤2%),golden 判定零变化;重锚步骤无需执行(基线未动、零差留痕达成 V5 判据;禁借重锚夹带红线零触碰)。
|
||||
5. **S9 修正**:四处显式非参数化容器注解改 `:=` 推断(R1)——零行为改动。
|
||||
6. **S7 域集增补**:`static_scan.sh` S7_B1_SET 增补 battle_refresh_flow.gd——换图刷新流程件=卡A C13 拆分边界的 B1 域拆件(承载 retire_mapping/装板编排调用,卡A §八明列新结算族件);判据口径不变(B2/B3/B4 对外 API 仍限 B1 域调用)。**architecture.md「模块归属」需补 BattleRefreshFlow 行——已入反哺点清单**。
|
||||
7. **V11 引用闭合判据域**:全表扫描发现预存行完美保险 when 读 insurance_used 无 counter_add 写入方(消费点落账合法形态——feats.tres 注记在案)——判据域收窄为「换图系七件自身引用闭合」,预存形态不入判据。
|
||||
8. **apply_board_refreshed 访问形态**:BattleRefreshFlow 经 `oc._rounds._grant_seg` 直调(round_cycle 不在卡A §八改动文件清单内,不加转发壳——沿结算族直调惯例)。
|
||||
9. **卡A T8「代拍板追认单」不另立**:iter 技能与 process-conventions §2 定「超白名单记实现报告实现决定记录,不另立追认单」——本批全部决定在上列备案,白名单内决定零追认面。
|
||||
10. **测试断言口径修正(开发期自纠)**:V5②③④ 聚合判据从「两来源行合计」修正为「全 hero 行数」(盲挖途经的其他直伤单据一并入账);V2 辅证改「RAP 增量==受理挖数」(移位耗 AP 不入账);V4 时序修正(停手再入 RAP)——均为测试侧修正,生产码零回退。
|
||||
11. **V9 上限 3 承载形态**:每轮刷新上限 2(表值)使自然路径层值至多 2——「上限 3」判据由白盒计数器预置+真实刷新入口承载(test-conventions §5.4 计数器直改属数据面注入),自然累计 2 另设战场钉死。
|
||||
|
||||
## 九、独立验收审计结论
|
||||
|
||||
- **审计方**:未参与实现的子代理(独立会话上下文),2026-10-31 执行。
|
||||
- **报告**:`reports/iter46-验收审计-2026-10-31.md`(本目录)。
|
||||
- **结论**:**审计通过(零缺漏)**——卡A V1–V12 与卡B 6 行对照表逐行通过;尾缀全可 grep;真实入口零绕过(V2 真挖/V3·V4·V10 经 player_request_refresh/V5 四路径真实战斗驱动);自跑复核 refresh_feats 85/standee 26/adventure_feats 138/round_flow 134/seal_polarity 70/effect_words 20/forge_table 41 全绿+gdstyle 5 键零新增+render_gate 三张 0.00% 实跑;削弱核对全部落在两卡申报面内(round_flow/seal 零进 diff,禁删面原样在案);无变异/撤销类取证。
|
||||
- **审计附加发现处置**:①两枚新件 .uid 边车未随批提交——已补提交(.gitignore 要求);②static_scan S8_FILES 与 S7_B1_SET 未同步增补新件——已同步(新件零 await,扫描面实跑绿);③V10 断言消息在求值前格式化的显示瑕疵(判据本体正确,零处置);④V9 私有读前置守卫附注(审计方判例外不阻塞——判据主面走公共 step_row 信号)。
|
||||
|
||||
## 十、遗留读数义务
|
||||
|
||||
- 卡C 裁决后:探针两档 bv.size/L1 格边/13·14 推定读数已录本报告第四节与停机呈报——重写卡可直接引用,无需重采。
|
||||
- 无 MC/数值验证义务(本批无数值改动,feats.tres 七行为卡内 provisional 值——归调参批)。
|
||||
@@ -0,0 +1,70 @@
|
||||
# 迭代 46 实现报告——卡C 棋盘格边长口径收口批 v2.0(2026-11-01)
|
||||
|
||||
> 批次:迭代 46 卡C(v2.0 重立回编——2026-11-01 用户三项裁定后写卡批重立,合并提交 e7090bc9)。卡A/卡B 已于 2026-10-31 收口合回,见同目录 `iter46-实现报告-2026-10-31.md`。
|
||||
> 工作区:`D:\code\g-plan2-iter46`(分支 iter46,卡C 段基点=master 5269ed40,WIP 三件按 v2 卡 §12 判定复用两件返工一件)。
|
||||
> 需求卡片:`reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md`(v2.0 定稿,零待裁点)。
|
||||
|
||||
## 一、卡C 状态
|
||||
|
||||
**收口**(T0–T4 全落)。游戏行为零变化:算式逐位同式、`set_cell_area` 副作用尾链零动、两条生产调用路径不改、画面像素零变化。本批改动全部落在守卫面=**人造阈值退役+算式单点+13/14 两档入卫**。
|
||||
|
||||
## 二、T0 改前基线读数(2026-11-01,master 5269ed40 态实测)
|
||||
|
||||
| 读数 | 结果 |
|
||||
|---|---|
|
||||
| `python tools/gdstyle_gate.py` | 扫描面 142 件、命中 5 条全在基线、基线外新违规 0、较登记值恶化 0(board_view.gd `max-public-methods=27`/`max-class-variables=31` 持平) |
|
||||
| 单件跑 `board_gen_reward_test` | all green(**62 checks**——改前基线值) |
|
||||
| 单件跑 `layout_probe` | 2 档 PASS(旧阈值形态「≥36px」消息,即本批退役对象) |
|
||||
| 四档取档对账(`resolve_row(1,0)/(2,0)/(3,0)/(3,9)`,临时对账件跑后即删) | 10×10/12×12/13×13/14×14,与卡 §2 第 6 条全符 |
|
||||
| `battle_layout.tres` 五字段 | stage_h=252/ap_bar_h=44/info_panel_w=240/log_band_h_dig=24/log_band_h_settle=84,与卡 §2 第 8 条全符 |
|
||||
|
||||
行号重锚:卡 §2 行号在 5269ed40 上逐一核实(`layout_probe.gd:15` MIN_CELL/`board_view.gd:206-215` 内联算式/`board_zone_view.gd:91-92` 生产调用路径+`board_view.rebuild` 末尾调用/`board_gen_reward_test.gd:53-69` 冒烟)——卡成文时点(3499638d)至 T0 时点间零漂移。`tools/gdstyle_baseline.txt` 两键登记值与卡 §2 第 5 条一致(:11=31、:22=27)。
|
||||
|
||||
## 三、实际对照表(改动—验收)
|
||||
|
||||
| # | 需求点 | 改动 | 验收测试(名称+实际落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 结果 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 1 | 探针阈值退役+格边长接线守卫 | `layout_probe.gd` MIN_CELL 常量整行删除;阈值断言换等价断言(:106-109) | 「两档几何不变量+格边长等价」`layout_probe.gd:_ready`(PASS 行 :45 尾缀〔格边长 V1〕;失败路径 :107) | 探针 | `godot --headless --path game res://probe/layout_probe.tscn` | 实读 `cell_size`(生产经 `set_cell_area` 真实写入)与 `_cell_for(n, bv.size)` 同输入严格相等——生产停止调单点算式即红;`_board` 内部字段直查=受控例外(板型 N 无公开出口,卡 §14.2);`grep -rn "MIN_CELL\|可读门槛\|可读下限" game/` 零命中(已跑,exit=1 零命中) | 绿(两档全过,基座实读 40px) |
|
||||
| 2 | 算式单点(`_cell_for`) | `board_view.gd:210` 改调 `static _cell_for`(:226,逐位同式);:206 注释补唯一落点句 | 「算式单点等价」`board_gen_reward_test.gd:75-76`(尾缀〔格边长 V2〕) | 单元 | `godot --headless --path game --script res://tests/unit/core/board_gen_reward_test.gd` | `set_cell_area` 写入的 `_cell` 与 `BoardView._cell_for(n, avail)` 返回值逐档严格相等(同一事实两路读取,分叉即红) | 绿(四档 4 断言全过;既有四套断言全绿=等价性证明,62→74 checks) |
|
||||
| 3 | 13×13/14×14 进入冒烟 | `board_gen_reward_test.gd:58` 循环集改四档取样表 [(1,0,10),(2,0,12),(3,0,13),(3,9,14)];:69-74 板型一致+既有两断言(前缀 L%d D%d) | 「格边长冒烟四档板型」同函数(尾缀〔格边长 V3〕) | 单元 | 同上 | 13/14 两档首次被断言:取档尺寸与实表一致、网格高 ≤ 可用高−24、格边 ∈ [26,46](既有断言逐字保留) | 绿(四档 12 断言全过,10/12/13/14 实测 41/33/31/28px) |
|
||||
| 4 | 最大板推定守卫(留痕型) | `layout_probe.gd:_check_one` 零尺寸前置(:112-114 记红)+13/14 推定留痕(:116-119 采集,:47-50 PASS 后打印) | 「最大板推定留痕」同探针(尾缀〔格边长 V4〕) | 探针 | 同行 1 | ①零尺寸前置(size ≤ 0 记红);②推定读数打印并与本报告 §四留档锚点读数逐值对拍,不一致=卡 §9 L3 #2 呈报(禁实现侧改锚) | 绿(基座 30/28、全屏 46/46——与锚点逐值一致,零对拍偏差) |
|
||||
| 5 | 批末收口 | 全批 | 代码域闸 `tools/run_all_gates.sh --code` | 全量闸 | `tools/run_all_gates.sh --code` | 所选域全绿回执(`game/tests/.gates/receipt.json`) | 绿(`all_green=true`,七闸 00/01/02/03/05/09/10,commit e3e206d0,域=code·scope=related[presentation],`changed_vs_baseline=[]`) |
|
||||
|
||||
**测试削弱申报核对**(卡 §8 申报全集四条,实际执行逐条对上):①探针阈值断言删除=申报 1 的执行面,补偿三件全落(等价断言/四档结构钳制/推定留痕对拍);②PASS 消息改写=申报 2;③循环集 2→4 档纯增量、样本值 (1036,460) 未改、既有两断言逐字保留=申报 3;④未发生恢复阈值、删旧断言、放宽区间、换读取入口任一项=申报 4 成立。另:既有几何不变量(三区非零/不越视口/互不重叠/view 含于 D 区)与视口档位表零改动(卡 §14.1 核对通过)。
|
||||
|
||||
## 四、锚点读数留档(两档视口 × 四板型——未来批次对照基准)
|
||||
|
||||
锚点=用户验收的现行渲染值(2026-11-01 用户裁,卡 §2 第 7 条)。本批探针实跑复核:
|
||||
|
||||
| 视口 | board_view.size(实读) | 10 板 | 12 板 | 13 板 | 14 板 |
|
||||
|---|---|---|---|---|---|
|
||||
| 基座 1280×800 | (1022.0, 454.0) | **40px(实读)** | 33px(单点算式读) | **30px(推定打印)** | **28px(推定打印)** |
|
||||
| 16:9 全屏 1920×1080 | (1662.0, 734.0) | 46px(实读·钳制顶格) | 46px(单点算式读) | **46px(推定打印)** | **46px(推定打印)** |
|
||||
|
||||
基座档 10 板实读经等价断言与 `_cell_for(10, (1022,454))` 严格相等(V1 守卫当轮执行);13/14 推定由探针 V4 打印(当轮留痕);12 板与全屏 10/12 三格由单点算式读数件在两档真实可用面积上读出(一次性临时件,当轮跑批留痕后即删):基座 12 板=33px、全屏 10/12=46px。全表与卡 §2 第 7 条锚点逐值一致,零对拍偏差。
|
||||
|
||||
## 五、实机目检总清单(登记不阻塞)
|
||||
|
||||
1. **第三关 14×14 板格面数字清楚可辨**——2026-11-01 用户已实际背书现行画面(锚点裁定),登记照留(卡 T4)。
|
||||
|
||||
## 六、实现决定记录
|
||||
|
||||
代拍板白名单 6 项全部按卡执行(`_cell_for` 局部变量名与注释措辞/四档取样表用字典数组/探针消息文案与 PASS 措辞/尾缀〔格边长 V1–V4〕编排/`BoardViewScript` 常量名/`bv.get("_board")` 取值形态),零超范围裁决。超白名单备案三件(均属测量面承载,判据零扩张):
|
||||
|
||||
1. **探针 `_board == null` 前置**(`layout_probe.gd:104-105`)——卡片明列判据只有零尺寸前置与等价断言;null 前置防「内部直查遇 null 即脚本错误静默跳过剩余断言」(test-conventions §7 失败模式),属测量面防御。撤销方式=删该分支(等价断言改回无条件求值)。
|
||||
2. **探针新增两成员 `_cell_reads`/`_est_reads`**(`layout_probe.gd:17-18`)——PASS 行基座实读与推定留痕打印的承载面;探针不在 S13 扫描面,无预算约束。撤销方式=删成员与两处打印(PASS 行退回无读数形态)。
|
||||
3. **单点算式锚点全表读数件**(本报告 §四 12 板与全屏 10/12 三格补读)——卡 §2 第 7 条锚点表含四板型,探针打印只覆盖 13/14(卡定死),全表留档用一次性临时脚本对两档实读可用面积逐板型读 `_cell_for`(当轮跑批留痕后即删)。撤销方式=无(纯读数,不落码)。
|
||||
|
||||
## 七、遗留读数义务
|
||||
|
||||
零。本批无数值改动,MC/verifier 零跑(卡 §4 范围边界 6)。§四全表读数已当轮留痕,无待补。
|
||||
|
||||
## 八、S13 结构预算与批末闸对账
|
||||
|
||||
- `board_view.gd`:`max-public-methods` **27→27**(`_cell_for` 私有名不计数)、`max-class-variables` **31→31**(零新增成员——钳制界未外提)、无 NEW 键;gdstyle 全批「基线外新违规 0、较登记值恶化 0」。
|
||||
- 探针与测试件不在 S13 扫描面(扫描面=产品码,测量面直构为既有惯例)。
|
||||
- 批末代码域闸:`tools/run_all_gates.sh --code` 全绿(回执落 `game/tests/.gates/receipt.json`,T4 当轮执行)。
|
||||
|
||||
## 九、独立验收审计结论
|
||||
|
||||
独立验收审计由未参与实现的子代理执行,报告=`reports/iter46-验收审计-卡C-2026-11-01.md`。结论:**通过,可合并**——五项全过(对照表五行逐行核对/自跑最窄测试实读:探针基座实读 40px·推定 30/28·46/46·单元 74 checks 全绿/判据绑定面钉生产写入值/测试削弱逐处对上卡 §8 申报全集/全仓无人造阈值回归且无变异·撤销取证)。一处非阻断备注已处置:实现报告 §三 行 1 判据绑定面格补「受控例外」句(审计报告原文备注定格于补句前)。审计方自跑读数与本实现会话当轮实跑逐值一致。未过不得合并红线未触发。
|
||||
@@ -0,0 +1,130 @@
|
||||
# 迭代 46 独立验收审计报告
|
||||
|
||||
> 审计方:独立验收审计子代理(未参与本批实现——迭代 loop 内启动,符合 test-conventions §8.7 两入口铁规)。
|
||||
> 日期:2026-10-31。
|
||||
> 工作区:`D:\code\g-plan2-iter46`(分支 iter46,基点 b5b2c555)。Godot:`Godot_v4.7.2-stable_win64_console.exe`。
|
||||
> 审计范围:合并候选=卡A(换图系双基座七件批)+卡B(站桩名字行提档与地台色合并批)已提交 diff=`git diff b5b2c555..c10bbc11`(10 笔提交=9 实现+1 收尾文档;20 文件,+1231/−96)。卡C(棋盘格边长)停摆不计。
|
||||
> 审计方式:不采信实现报告「已全绿」自述——逐行核对对照表两端、自跑最窄套件与闸件、对照 diff 逐处核对削弱申报。本审计只写本报告,零源码/测试/数据文件改动。
|
||||
|
||||
## 一、审计自跑记录(当轮真实执行)
|
||||
|
||||
| 套件/闸 | 结果 | 与报告申报对照 |
|
||||
|---|---|---|
|
||||
| refresh_feats_test | **all green (85 checks)**,exit 0 | 与报告§二 申报 85 一致 |
|
||||
| standee_present_values_test | **all green (26 checks)**,exit 0 | 与报告§三 申报 26 一致 |
|
||||
| adventure_feats_test | **all green (138 checks)**,exit 0 | 与报告§二 申报 138 一致 |
|
||||
| round_flow_skill_pool_test | **all green (134 checks)**,exit 0 | 与报告§二 申报 134 一致 |
|
||||
| seal_polarity_test(附加) | all green (70 checks),exit 0 | 与报告§二 申报 70 一致 |
|
||||
| effect_words_t1_test(附加,V1) | all green (20 checks),exit 0 | 与报告§二 申报 20 一致 |
|
||||
| forge_table_test(附加,V1) | all green (41 checks),exit 0 | 与报告§二 申报 41 一致 |
|
||||
| gdstyle_gate | 5 键全基线内、基线外新违规 0、恶化 0 | 与报告§五「零新增零恶化」一致 |
|
||||
| static_scan.sh | exit 0——S7 ok(B2/B3/B4 符号收敛 B1 文件集)/S8 ok/S13 ok | S7 新域集生效见§六① |
|
||||
| render_gate.sh(窗口化实跑) | 板面三张+menu_boot 全 **changed=0.00%**,全绿 | 与报告§八.4 一致,见§三行 5 |
|
||||
|
||||
## 二、卡A 对照表逐行核对(V1–V12)
|
||||
|
||||
| 需求点 | 测试存在 | 尾缀可 grep | 真实入口无绕过 | 判定 |
|
||||
|---|---|---|---|---|
|
||||
| V1 词表扩签 | `effect_words_t1_test.gd:_init` 新增①-a 两断言+`forge_table_test.gd:_test_effect_kinds_closed` 22/34 换代 | 〔换图系批 V1〕×2+〔锻造工坊批 V11〕×2 | ConfigDB 整表加载+词表常量直读 | **通过**(实跑 20/41 checks 绿;diff 核对 effect_words 纯增量 5 行,旧出域负例零删) |
|
||||
| V2 矿脉储能 | `test_reserve_on_accepted_dig` | 〔换图系批 V2〕×3 | 经 `_auto_dig`→`settle_batch([move]+[dig])` 真实付费挖格;辅证 `_drain_round_rap_accounting` 仍走 settle_batch 逐挖计数 | **通过**(RAP 8→9、AP 按表扣、耗尽轮增量==受理挖数三面全钉) |
|
||||
| V3 省力周转 | `test_refresh_discount_gate_and_charge`+`test_double_base_stack` | 〔换图系批 V3〕×6 | 经 `orch.player_request_refresh()` 唯一入口;can 与执行同源(`_effective_refresh_cost` 单点,diff 核实编排器两公开方法单行转发) | **通过**(折后 −4×2、门槛拒 can=false 且执行拒、双基座同场生效) |
|
||||
| V4 成功事实 | `test_board_refresh_fact_only_on_success` | 〔换图系批 V4〕×6 | 经 `player_request_refresh()`;非 Active 拒=decay 行内同步探测(round_flow_skill_pool_test:161 先例同款),上限拒/RAP 不足拒均在 Active 相位真入口 | **通过**(三拒面 probe_br_counter==0+board_changed 计数冻结双观测;成功恰一次×2+新轮×2) |
|
||||
| V5 全局受伤 | `test_all_hero_damage_paths_emit_once`+`test_no_duplicate_damage_taken_event` | 〔换图系批 V5〕×8 | **四路径全真实战斗驱动、零直调 `_emit`**:①敌方攻击=boss 战零挖掘连停三轮(enemy_action 行在案);②地形=AutoPlayer 盲挖 flat_damage 变异格+stop;③危险格=真挖直接伤型雷格;④错误封印=真 `seal_place`+stop | **通过**(每路径「承伤行数==计数器」恰一次+无重复消费两样本;实跑读数 行2=计2/行9=计9/行2=计2/行2=计2) |
|
||||
| V6 石层缓冲 | `test_stone_mitigation_all_damage` | 〔换图系批 V6〕×3 | 刷新经 `player_request_refresh`;危险格/地形经真挖+stop 结算 | **通过**(pierce 8→6 双刷不叠=叠加态 4 反证钉死;未刷轮不减=round 桶轮始清空;地形 max(下限, effect_value−2) 逐单闭合) |
|
||||
| V7 崩壁冲击 | `test_blast_defers_to_combat_segment` | 〔换图系批 V7〕×2 | 刷新+停手(轮末授予段→战斗段末) | **通过**(刷新时点零伤害行=授予段不结账;停手后恰一单 value 2 全体存活敌) |
|
||||
| V8 蓄力周转 | `test_charge_layers_consumed_same_round` | 〔换图系批 V8〕×2 | 双刷+停手(主角先手攻击)真实消费 | **通过**(白盒预置 3 层上限闸=实现决定 #11 申报面;双刷 2 层攻击后清 0;战斗新建 0) |
|
||||
| V9 坑道小憩 | `test_rest_rotation_cap_and_clear` | 〔换图系批 V9〕×3 | 刷新经真入口;轮末恢复在授予段(stop 触发) | **通过(附未注例外,见§五)**(回复 min(3,缺血)==3 且层清 0;满血未生效行+零 heal 行;自然累计 2 路径) |
|
||||
| V10 矿道红利 | `test_mine_profit_gp` | 〔换图系批 V10〕×4 | 经 `player_request_refresh()`;拒绝=RAP 不足真拒 | **通过**(escrow 每次+1、fx_grant_gp 行恰 1、拒绝零变化;消息文案时点瑕疵见§七.3,不涉判据) |
|
||||
| V11 数据与池 | `test_seven_feats_validate_and_pool`+adventure_feats `_smoke_feats` | 〔换图系批 V11〕×5+〔专长批 V2〕换代句 | ConfigDB 整表+冒险牌库真实启动(seed 71) | **通过**(validate 空/七行稀有度 cap 对表/desc 禁词/七件计数器引用闭合/三计数器在册;rows 37、14/13/10/0、deck 139;feats.tres 七行 trigger 结构逐行对照卡§十.T6 零出入) |
|
||||
| V12 无专长回归 | `test_no_feats_baseline`+round_flow `_smoke_active_refresh`+seal `_smoke_refresh_provenance_guard` | 〔换图系批 V12〕×4 | 挖格/刷新/停手全真入口 | **通过**(挖格零 RAP、表基线扣 8、AP 保留、第 3 次拒;round_flow/seal 两文件**零进 diff**——RAP8/上限2/AP保留/刷新图零清图/五段序/回放断言原样在案,134/70 checks 实跑绿) |
|
||||
|
||||
## 三、卡B 对照表逐行核对(6 行)
|
||||
|
||||
| # | 需求点 | 判定 |
|
||||
|---|---|---|
|
||||
| 1 | 名字行字号提档 FS_HINT 14 | **通过**——diff 核对五取值点(`:334-336` 两测量+`:467` 测量+`:474` 护甲绘制+`:476` 名字绘制)全改 `UiKit.FS_HINT`;`:114` 消散提示零触碰(FS_CAPTION 计数锚==1 断言在案且实跑绿);`name_line_probe` 增 `name_font_size` 键(探针实读==FS_HINT 绿) |
|
||||
| 2 | 名字行几何随档联动 | **通过**——`_name_baseline` 偏移 17→18+注释换代(diff 核实);V6 读数 150±0.51 与「8px 档」句换代=卡B§8 申报第 1 条面内;`baseline_y < plinth_top_y` 文字不压地台判据零改动且绿 |
|
||||
| 3 | 受光线常量退役改指 BRICK | **通过**——ui_kit 真删 `STAND_STONE_RIM` 无别名占位;`standee_body` 顶缘线与 `cell_base_layer:176` 口沿高光两绘制点改指 `BRICK`;V11=常量表零键+BRICK 逐位 c9af83+两处源码锚全绿;grep 全仓退役常量仅剩测试断言串(与报告§三「预期例外」申报一致) |
|
||||
| 4 | 描边常量退役改指新 token | **通过**——ui_kit 删 `STAND_STONE_EDGE`+原位增 `PLAZA_EDGE := Color8(76, 64, 56)`;`standee_body` 回退描边改指;V12=PLAZA_EDGE 逐位 4c4038+源码锚全绿 |
|
||||
| 5 | 板面 golden 与换值一致 | **通过**——审计方自跑 `bash tools/render_gate.sh`(窗口化):board_L1/L2/L3 与 menu_boot 全 0.00%;golden 五文件 git 零改动=基线未动、重锚未执行(与实现决定 #4 备案一致——#C4AC84→#C9AF83 灰度差约 2,低于容差 ≤16,0.00% 为必然);level_map.png 不在 render_gate 对比域、git 零改动 |
|
||||
| 6 | 批末收口 | **通过(遗留义务明示)**——迭代级 `--code` 闸未跑(卡B 行 6 申报「待迭代出口」);批内证据=commit 点 docs 域回执(fde1795d)全绿含 08c 流水线闸+审计方补跑 gdstyle/static_scan/render_gate/五套件全绿。合回后本地 CI 全量域闸为唯一强制验证点(process-conventions §1),本行遗留义务随合回 CI 承接 |
|
||||
|
||||
## 四、抽查断言原样输出行(当轮实跑摘录)
|
||||
|
||||
```
|
||||
[refresh_feats_test] all green (85 checks)
|
||||
[PASS] V5① 敌方攻击路径:承伤单据在案且逐单恰一次(行 2=计数 2)〔换图系批 V5〕
|
||||
[PASS] V5② 地形路径:地形单据在案且全单据逐张恰一次(行 9=计数 9——盲挖途经单据一并计入)〔换图系批 V5〕
|
||||
[PASS] V5③ 危险格路径:直伤单据在案且全单据逐张恰一次(行 2=计数 2)〔换图系批 V5〕
|
||||
[PASS] V5④ 错误封印路径:直伤单据在案且全单据逐张恰一次(行 2=计数 2)〔换图系批 V5〕
|
||||
[PASS] V2 受理付费挖格 RAP 恰 +1(8→9)〔换图系批 V2〕
|
||||
[PASS] V3 折后单次扣费(8→4,−4)〔换图系批 V3〕
|
||||
[PASS] V4 第 1 次成功(事实 +1 换图 +1)〔换图系批 V4〕
|
||||
[PASS] V6 S1 危险格减伤恰 2 且多刷不叠加(行值 [6]∈[6]——叠加态应为 4)〔换图系批 V6〕
|
||||
[PASS] V9 R1 轮末回复=min(3,缺血102) 且层清 0(heal 行值 [3])〔换图系批 V9〕
|
||||
[PASS] V10 第 1 次成功 escrow +1(0→0)〔换图系批 V10〕
|
||||
[PASS] V12 刷新受理并按表基线扣(−8)〔换图系批 V12〕
|
||||
[standee_present_values] all green (26 checks)
|
||||
[PASS] 基线读数与实装几何同源(基线 = 地台顶上方 8px 档:150 < 158——14px 档牌顶+18)〔样张批 V6〕
|
||||
[PASS] 名字行探针字号实读 = FS_HINT(几何单点出口 name_font_size)〔名字行 V10〕
|
||||
[PASS] 全文件 FS_CAPTION 仅剩消散提示一处(计数锚==1——三处宽度测量点强制换代)〔名字行 V10〕
|
||||
[PASS] 退役常量不在册(STAND_STONE_RIM/STAND_STONE_EDGE 零键)〔名字行 V11〕
|
||||
[PASS] PLAZA_EDGE 值逐位 #4C4038(合并目标②)〔名字行 V12〕
|
||||
[adventure_feats_test] all green (138 checks)
|
||||
[PASS] 专长带入池:37 件四级直映射(普通 14/优秀 13/稀有 10/传说 0)——牌库 102+37=139〔专长批 V2+迭代 46 换图系七件换代〕
|
||||
[round_flow_skill_pool_test] all green (134 checks)
|
||||
[seal_polarity_test] all green (70 checks)
|
||||
[effect_words_t1] all green (20 checks)
|
||||
[forge_table_test] all green (41 checks)
|
||||
```
|
||||
|
||||
```
|
||||
[render_gate] [golden] board_L1_dungeon.png — changed=0.00%(容差 ≤16 差/≤2%)OK
|
||||
[render_gate] [golden] board_L2_underdark.png — changed=0.00%(容差 ≤16 差/≤2%)OK
|
||||
[render_gate] [golden] board_L3_deep_underdark.png — changed=0.00%(容差 ≤16 差/≤2%)OK
|
||||
[render_gate] [golden] menu_boot.png — changed=0.00%(容差 ≤16 差/≤2%)OK
|
||||
[render_gate] 全绿
|
||||
```
|
||||
|
||||
注:V10 消息「escrow +1(0→0)」的两个读数均在 `player_request_refresh()` 求值前格式化——显示瑕疵;断言本体绑刷新后 `escrow == escrow0 + 1`,判据面正确(绿即真值)。
|
||||
|
||||
## 五、内部字段直查受控例外核对(test-conventions §80/§8.7 第 4 条)
|
||||
|
||||
| 直查行 | 性质 | 判定 |
|
||||
|---|---|---|
|
||||
| `orch.fx_host().counters_ctx`(refresh_feats_test 5 处:读计数器×3+白盒预置×2) | `counters_ctx` 是 BattleFxHost **公开成员**(无下划线),读经公共 API `EffectEngine.counter` | 非私有直查;存量套件 adventure_feats_test 同款先例 |
|
||||
| `EffectEngineScript.counter_add(...)` 白盒预置(V9/V8 上限 3 闸) | 计数器直改=数据面注入 | **已申报**——实现决定 #11(test-conventions §5.4 引用)+对照表 V8/V9 行「白盒预置」在案 |
|
||||
| `orch1._enemy_system.hero_unit()`(refresh_feats_test:518,V9 缺血读数) | **私有面直查 1 处** | **例外(手续缺注,不阻塞)**——对照表 V9 行与实现决定 #11 均未注该行理由。依据:①判据主面(heal 行/未生效行)经公共 `step_row` 信号在案,私有读只作前置量(`missing >= 3` 守卫),行为并非钉在私有面上;②存量套件 roll_multiplier_test.gd:51 同款先例;③公开替代面存在(`presentation_snapshot()` 含 hero.hp)。建议实现报告 V9 行补注一句(随合回流程,本审计不代改) |
|
||||
| 生产码 `oc._damage._emit_hero_damage_taken`/`oc._rounds._grant_seg` 直调 | 结算族内部协作 | 实现决定 #8 备案(结算族直调惯例)——非测试面,不在本节判域 |
|
||||
|
||||
## 六、附加核对(实现决定复核三项+卡C 脏面)
|
||||
|
||||
1. **S7_B1_SET 增补(实现决定 #6)——判据口径未变,通过**:static_scan.sh diff 仅 1 行清单+2 行注释;B2/B3/B4 三族符号交替式(14/5/9 符号)逐字未动;豁免语义(自家文件、注释/字符串排除、s7-b1-exempt)未动;`battle_refresh_flow.gd` 调 `oc._reward_economy.retire_mapping()` 命中 B4 符号,入 B1 域集与 C13 拆分边界自洽。审计实跑 static_scan:S7 ok(50 文件扫描面)。
|
||||
2. **S9 修正(f498d2ec)——零行为变化,通过**:4 处显式非参数化容器注解(`damage_controller.gd` 3 处 `: Dictionary`/`: Array`、`grant_segment.gd` 1 处)改 `:=` 推断,静态注解改写,无逻辑分支变化。
|
||||
3. **卡C 停摆脏面核对——申报一致,另见§七.1**:`git status` 修改面恰为申报的三件(`board_view.gd`/`layout_probe.gd`/`board_gen_reward_test.gd`),均未提交、不在审计 diff 内;另有 2 个未跟踪 `.uid` 文件(§七.1)。
|
||||
4. **golden 申报制核对**:golden 五文件(三张板面+level_map+menu_boot)git 零改动=重锚申报制零触发(实现决定 #4「无需重锚」与实跑 0.00% 互证);不存在借重锚夹带。
|
||||
|
||||
## 七、测试削弱核对清单(diff 被改/被删旧断言逐处 → 申报面)
|
||||
|
||||
| 位置 | 改动 | 申报依据 | 判定 |
|
||||
|---|---|---|---|
|
||||
| adventure_feats_test :464/:476 | 行数 30→37、稀有度 12/9/9→14/13/10、牌库 132→139 | 卡A§十二第 1 条(计数换代申报) | **通过**——零放宽:validate/禁词/退役钉面零删(diff 核对) |
|
||||
| forge_table_test :202 附近 | EFFECT_KINDS 32→34、EVENTS 20→22 | 卡A§十二第 1 条 | **通过** |
|
||||
| effect_words_t1_test :17-21 | 纯增量 5 行(两事件两效果在册) | 增量非削弱 | **通过**(旧负例全保留,diff 核对) |
|
||||
| standee_present_values_test V6 | 读数 149→150+「9px 档→8px 档」句 | 卡B§8 申报第 1 条 | **通过**(文字不压地台判据零改动) |
|
||||
| standee_present_values_test V10–V12 | 纯增量 8 断言+文件头注释换代 | 卡B§8 申报第 2 条 | **通过**(V5/V7/V8/V9 判据零改动,diff 核对) |
|
||||
| run_all.gd :191 | 套件注释 V5–V9→V5–V12 | 非行为改动(卡B§6 预告) | **通过** |
|
||||
| 禁删面(卡A§十二):RAP8 基线/每轮上限 2/AP 保留/刷新图零清图/伤害下限/五段序/同种子回放 | round_flow/seal 两文件零进 diff;伤害下限在 `_resolve_board_flat_hero` 保位(`maxi(下限, dealt)` 减后过下限=卡C4 同款) | 卡A§十二禁删令 | **通过**(134/70 checks 实跑绿承载) |
|
||||
| 生产面删除项 | `_terrain_damage_reduce` 删/编排器旧刷新体删/`_enemy_shield_apply` 改名/ui_kit 两常量删 | 卡A T2/T3 步骤明列+卡B§1/§3 | **通过**(全部卡面内,无未申报删改) |
|
||||
| 变异/撤销类取证 | 全 diff 无回退 hunk/注入破坏证明 | 卡A§十二+卡B§3 | **通过**(临时专长经 ConfigDB 表行追加=卡§十二「正常数据配置路径」申报一致) |
|
||||
|
||||
## 八、附加发现(不属验收对照面、不阻塞合并——处置建议随合回流程)
|
||||
|
||||
1. **批内新件两枚 `.uid` 未随批提交**:`game/core/settlement/battle_refresh_flow.gd.uid` 与 `game/tests/unit/battle_settlement/refresh_feats_test.gd.uid` 未跟踪(mtime 07:49,早于 T3 提交 07:52——非审计跑测所生成)。`.gitignore` 第 6 行明文「Godot 4 的 .uid 文件必须提交,不要忽略」,全仓其余 `.gd` 均有 `.uid` 入库伴件。已核零 UID 引用(grep 两 uid 串零命中),风险低;建议合回前补提交(本审计受只读约束不代提交)。
|
||||
2. **S8_FILES 未与 S7_B1_SET 同步增补**:await 零命中扫描集仍为 10 文件,新 B1 拆件不在其内。实查新件零 await(grep 证),当日无漏扫;但两清单同源 B1 域集出现分叉,建议 architecture「模块归属」BattleRefreshFlow 行落文(反哺点 #5)时同批补 S8_FILES。
|
||||
3. **V10 消息文案时点**(§四注):纯文案瑕疵,判据不受影响。
|
||||
4. **V9 私有读未注理由**(§五):建议补注。
|
||||
|
||||
## 九、结论
|
||||
|
||||
**审计通过(零缺漏)**——卡A 对照表 V1–V12 与卡B 对照表 6 行逐行通过(例外 1 处=V9 私有读手续缺注,附依据不阻塞);四套件+三附加套件+gdstyle+static_scan+render_gate 当轮自跑全绿;测试削弱全部在两卡申报面内,无未申报删改,无变异/撤销类取证;结构预算申报(803 行/类变量 15/各件增员)经实数核对全部相符。§八附加发现四条均不属验收对照面,随合回流程处置。
|
||||
@@ -0,0 +1,91 @@
|
||||
# 迭代 46 验收审计——卡C 棋盘格边长口径收口批 v2.0(2026-11-01)
|
||||
|
||||
> 审计方:独立子代理(未参与实现,只读证据+自跑最窄测试,不采信实现报告转述)。
|
||||
> 审计对象:commit `e3e206d0`(代码三件)+`8eaf7d87`(收尾文档两件);卡C 段基点 master `5269ed40`。
|
||||
> 依据:需求卡片 v2.0(§8 改动—验收对照表+测试削弱申报全集)、实现报告 §三 实际对照表、批末闸回执。
|
||||
> 审计工作区:`D:\code\g-plan2-iter46`(分支 iter46)。审计全程只读,唯一写入=本报告。
|
||||
|
||||
## 一、对照表逐行核对——通过
|
||||
|
||||
实现报告 §三 五行逐行核对,每行的验收测试真实存在、尾缀可 grep、真实入口未绕过改动点。
|
||||
|
||||
行 1(探针阈值退役+接线守卫):
|
||||
- 测试真实存在:`game/probe/layout_probe.gd:98-109`(读 `cell_size` → 等价断言),失败路径 `:107`,PASS 行 `:45`。
|
||||
- 尾缀 grep:`grep -n "格边长 V1" game/probe/layout_probe.gd` → `:45`/`:105`/`:107` 三处。
|
||||
- 真实入口:`layout_probe.tscn:6` 挂载 `res://probe/layout_probe.gd`(场景进,非脚本直调);探针断言对象=`main.tscn` 实例化的生产 UI 链(`main.ui.battle.board_zone.board_view`),非测试替身。
|
||||
- 报告附带的 grep 读数(MIN_CELL 零命中)由审计方独立复跑证实(见第五节)。
|
||||
|
||||
行 2(算式单点 V2):
|
||||
- 测试真实存在:`game/tests/unit/core/board_gen_reward_test.gd:75-76`,断言条件 `int(cell) == board_view_script._cell_for(n, avail)`。
|
||||
- 改动点行号核实:`board_view.gd:210`=`_cell = float(_cell_for(maxi(_board.width, _board.height), avail))`、`:226`=`static func _cell_for`——与报告所记 `:210`/`:226` 逐一相符。
|
||||
- 真实入口:`--script res://tests/unit/core/board_gen_reward_test.gd` 直跑(文件头 `:10` 自述同入口)。
|
||||
|
||||
行 3(四档冒烟 V3):
|
||||
- 测试真实存在:`board_gen_reward_test.gd:59` 四档取样表 `[(1,0,10),(2,0,12),(3,0,13),(3,9,14)]`,`:69`/`:71`/`:73` 三条 V3 断言。
|
||||
- 真实入口同行 2(同一宿主 `_init:33` 调 `_smoke_layout_cell_formula`)。
|
||||
|
||||
行 4(推定留痕 V4):
|
||||
- 测试真实存在:零尺寸前置 `layout_probe.gd:113-114`,推定采集 `:116-119`,PASS 后打印 `:47-50`,尾缀 `:49`/`:114`。
|
||||
- 真实入口同行 1。
|
||||
|
||||
行 5(批末收口):
|
||||
- `game/tests/.gates/receipt.json` 实读:`all_green=true`、`commit=e3e206d0f5646ecb8ece22ac08018c26e5591e1d`、七闸(00/01/02/03/05/09/10)exit 全 `0`、`domain=code`、`scope=related[presentation]`、`changed_vs_baseline=[]`——与报告行 5 所记一致。审计方未重跑全量闸(按审计约束,回执承载)。
|
||||
|
||||
## 二、自跑最窄测试抽查——通过
|
||||
|
||||
a. 探针两档(工作目录 `D:\code\g-plan2-iter46\game`):
|
||||
- 命令:`/d/code/godot/Godot_v4.7.2-stable_win64_console.exe --headless --path . res://probe/layout_probe.tscn`
|
||||
- 实测 exit 0。关键输出原文:
|
||||
- `[layout_probe] PASS — 2 档几何不变量全过+格边长等价成立(基座实读 40px)〔格边长 V1〕`
|
||||
- `[layout_probe] [基座 1280x800] 13 板推定 30px/14 板推定 28px(实板可用面积 (1022.0, 454.0))〔格边长 V4〕`
|
||||
- `[layout_probe] [16:9 全屏 1920x1080] 13 板推定 46px/14 板推定 46px(实板可用面积 (1662.0, 734.0))〔格边长 V4〕`
|
||||
- 读数与卡 §2 第 7 条锚点(基座 30/28、全屏 46/46,可用面积 1022×454/1662×734)逐值一致,零对拍偏差。审计方另按公式手工复核:基座 13 板 `(422−24)/13=30.6→30`、14 板 `(422−26)/14=28.28→28`、全屏 14 板 `(702−26)/14=48.3→钳制 46`——打印值与单点算式自洽。
|
||||
|
||||
b. 单元四档(同工作目录):
|
||||
- 命令:`…console.exe --headless --path . --script res://tests/unit/core/board_gen_reward_test.gd`
|
||||
- 实测 exit 0,收尾行 `[board_gen_reward_test] all green (74 checks)`。
|
||||
- 四档各四断言全 PASS:L1D0(41px)/L2D0(33px)/L3D0(31px)/L3D9(28px)——每档「板型一致〔格边长 V3〕」「网格高 ≤ 可用高−24〔格边长 V3〕」「格边 ∈ 26–46〔格边长 V3〕」「算式单点等价〔格边长 V2〕」各一条,16 条尾缀齐全。62→74 增量=每档净增 3 条 × 4 档,账目相符。
|
||||
|
||||
c. gdstyle(工作目录 `D:\code\g-plan2-iter46`):
|
||||
- 命令:`python tools/gdstyle_gate.py`
|
||||
- 实测 exit 0:`扫描面 142 个 .gd;命中 5 条,基线内 5 条,基线外新违规 0 条,较登记值恶化 0 条`。
|
||||
- 基线两键实读:`tools/gdstyle_baseline.txt:11`=`board_view.gd|quality/max-class-variables = 31`、`:12`=`board_view.gd|quality/max-public-methods = 27`——持平,无 NEW 键。
|
||||
|
||||
## 三、判据绑定面核查——通过(一处非阻断措辞备注)
|
||||
|
||||
1. 绑定的是生产写入值,不是多层防御后的终态:
|
||||
- 探针取值面=`cell_size` 公开只读属性(`board_view.gd:89-91` getter 直返 `_cell`),`_cell` 由 `set_cell_area` 在 `:210` 直接写入;生产写入路径两条未动(`board_zone_view.gd:92` resized 信号→`set_cell_area(_board_area.size)`、`board_view.gd:273` rebuild 末尾)。等价断言 `layout_probe.gd:106` 对 `bv.size`(实板可用面积)严格相等(`!=` 记红)——生产停调单点算式即红(基座档默认值 46 与算式值 40 分叉可捕)。
|
||||
- 单元取值面=真实调用 `set_cell_area(avail)` 后直读 `_cell`(`board_gen_reward_test.gd:65,67`),与同输入 `_cell_for(n, avail)` 逐档 int 严格相等(`:76`)——同一事实两路读取。
|
||||
2. 内部字段直查两处的例外依据:
|
||||
- 探针读 `_board`(`layout_probe.gd:103`):理由「板型 N 无公开出口」已载于代码注释 `:102`、卡 §7.3 T2 与卡 §14.2、报告 §六 白名单第 6 项。
|
||||
- 测试读 `_cell`(`board_gen_reward_test.gd:67`):批前既有取值面(卡 §2 第 4 条记载改前即如此),卡 §8 申报 4 明列 `cell_size`/`_cell` 为两合法入口、禁换别的入口——属守住的旧面,非新开直查。
|
||||
3. 非阻断措辞备注:卡 §14.2 与代码注释 `layout_probe.gd:102` 均称例外理由「对照表行 1 注明」,但实现报告 §三 行 1 判据绑定面格(以及卡 §8 行 1)未逐字带「N 无公开出口/受控例外」句——交叉引用指针落空。例外事实与理由已在他处完整承载(本节第 2 点所列四处),断言零削弱、无申报外改动,不判红;建议实现会话顺手把该句补进报告 §三 行 1(可选,不阻塞合并)。
|
||||
|
||||
## 四、测试削弱核查——通过
|
||||
|
||||
e3e206d0 负向行(删除行)全集逐处对账,全部落进卡 §8 申报四条,无申报外删改:
|
||||
|
||||
| 删除内容 | 对应申报 |
|
||||
|---|---|
|
||||
| `const MIN_CELL := 36.0` 整行 | 申报 1(阈值常量退役) |
|
||||
| `if cell < MIN_CELL:` +「< 可读门槛」记红两行 | 申报 1(阈值断言删除) |
|
||||
| 旧 PASS 消息(「格子 ≥36px」形态)两行 | 申报 2(文案随判据换代) |
|
||||
| `for L in [1, 2]` 与 `generate(L, 0, …)` 两行 | 申报 3(循环集 2→4 档)+白名单第 2 项(字典数组形态) |
|
||||
| 两条旧 Kit.check 的消息行 | 申报 3(前缀 L%d→L%d D%d——卡 §7.4 明许)+白名单第 4 项(尾缀编排) |
|
||||
| 冒烟 print 头行(「底部预留回归」→「·四档板型」) | 申报 3 同批日志头随档数换代(非断言,无条件面) |
|
||||
| `board_view.gd` 内联算式六行 | 非断言——逐字搬入 `_cell_for`(`board_view.gd:226-231` 对拍:SEP/DEPTH_PX 同源、reserve 24.0+d 同式、clampi(26,46) 留函数内),行为零变化由单元 74 checks 全绿承载 |
|
||||
|
||||
补偿三件全在位:等价断言(V1)、结构钳制四档(V3)、推定留痕(V4)。既有两断言条件逐字保留(`grid_h <= int(avail.y) - 24`、`cell >= 26.0 and cell <= 46.0`),样本 `Vector2(1036, 460)` 未改。既有几何不变量与视口档位表零改动(diff 负向行中无其一)。申报 4(禁恢复阈值/删旧断言/放宽区间/换读取入口)成立——四处均未发生。
|
||||
|
||||
## 五、全仓无人造阈值回归——通过
|
||||
|
||||
- `grep -rn "MIN_CELL\|可读门槛\|可读下限" game/` → 零命中(exit 1);扩到 `tools/`、`design/` 查 `MIN_CELL` 亦零命中。
|
||||
- 30/36 阈值形态穷举:三件改动文件中 30 仅两处且均非格边长判据(`board_gen_reward_test.gd:203`「板面 30% 锚」=雷数比例锚、`board_view.gd:659`「南部 30%」=墙面口径注释);36 零出现。全 `game/` 断言形态 grep(`(>|>=|<|<=)\s*(30|36)`)命中皆为无关域(RNG 位移 `>> 30`、商店 `1 << 30` 哨兵价、护甲 `<= 30` 属性域检);`clampi` 无 30/36 形态。格边长唯一区间判据仍是公式自带 `clampi(26, 46)`。
|
||||
- 变异类测试与撤销类取证:diff 负向行无「人为改错值验抓取」形态;无回退 hunk;测试代码无注入破坏分支(探针 `_board == null` 前置属测量面防御,报告 §六 第 1 项已备案,非变异)。
|
||||
- design/ 现状:`battle.md:144`「可读下限 30px」句仍在位=预期(实现批禁写 `design/`,退役走反哺点通道——`reports/iter46-反哺点-卡C-2026-11-01.md` 第 1 条已登记,卡 §5 明示不阻塞本批)。
|
||||
- 禁写面核查:卡C 段全区间 `5269ed40..8eaf7d87` 触碰文件恰为三件代码+两件 reports,`待办清单.md`/`体验验证清单.md`/`game/tests/README.md`/`design/` 零触碰。
|
||||
- 工作区漂移核查:三件代码文件 `git status` 干净——审计实跑的即 e3e206d0 提交的字节。
|
||||
|
||||
## 六、总结论
|
||||
|
||||
**通过。** 五项审计全过:对照表五行真实入口与尾缀齐全;自跑探针两档绿(基座实读 40px、推定 30/28 与 46/46 合锚点)、单元 all green 74 checks(四档 41/33/31/28px,V2/V3 全 PASS)、gdstyle 基线外新违规 0 恶化 0;判据绑生产写入值与 `_cell_for` 严格相等;删改逐处对上申报四条;全仓无人造阈值回归、无变异/撤销形态。唯一遗留=第三节第 3 点的交叉引用措辞备注(不判红、不阻塞合并,补句归实现会话可选动作)。
|
||||
@@ -0,0 +1,55 @@
|
||||
# 停机呈报:棋盘格边长口径收口批(迭代 46 卡C)——L3 #2 实板可读面不达标
|
||||
|
||||
> 日期:2026-10-31 · 呈报人:迭代 46 实现会话(iter 技能执行中)
|
||||
> 接收方:待办清单条目「棋盘格边长三方取值不一致——待扩板定档处置(2026-10-06 登记)」
|
||||
> 性质:实现段零裁断——需求卡片预设停机点触发(需求卡片-棋盘格边长口径收口批-2026-10-30.md §9 异常分级 L3 第 2 条),停该卡呈报退回上游,等用户裁决。
|
||||
|
||||
## 一、触发了什么
|
||||
|
||||
需求卡片 §7.3 T2 规定探针新增「实板可用面积下 13/14 板格边长推定」断言:以探针实读 `board_view.size` 代入算式单点 `BoardView._cell_for(n, size)`,`< 30px`(battle.md 可读下限)即记问题。§9 L3 第 2 条预设:实板可用面积代入 13/14 后 < 30 = 产品面问题,**停卡呈报,禁调低下限、禁换样本凑绿**。
|
||||
|
||||
当轮真实跑批实测(worktree iter46,种子 42,两档视口):
|
||||
|
||||
| 视口档 | board_view.size(实板可用面积) | L1 实测格边 | 13×13 推定 | 14×14 推定 |
|
||||
|---|---|---|---|---|
|
||||
| 基座 1280×800 | (1022.0, 454.0) | 40px ✓ | 30px(恰达标) | **28px < 30 ✗** |
|
||||
| 16:9 1920×1080 | (1662.0, 734.0) | 46px(钳制顶格) | 46px ✓ | 46px ✓ |
|
||||
|
||||
代入算式复核(1280 档):`min(1022−12−8, 454−32) = 422`;`(422 − 13×2) / 14 = 28.28 → floor 28` → 钳制 [26,46] 内 → 28px。**14×14 板在基座档的实板格边长低于 battle.md「可读下限 30px」**。
|
||||
|
||||
## 二、事实定性(这不是本批制造的回归)
|
||||
|
||||
1. 算式逐位未动(卡C 行为零变化,单元四档冒烟 74 checks 全绿——结构钳制 [26,46] 面全过)。
|
||||
2. 28px 是**存量事实**:现行生产公式对 14×14 板(board_gen.tres:L3 depth 9–13)在基座档一向算出 28px;本批新增的推定断言只是首次把它量出来。
|
||||
3. battle.md 算例表的「14×14 → 30px」按「可用高 486px」推算,而实机 D 列结构给出 454px——卡片 §2.8 已登记该偏差(「实机可用面积与算例不同源」),本读数即该偏差的实测落点。
|
||||
4. 同样数据下 13×13=30 恰好达标,仅 14×14 一档越线下。
|
||||
|
||||
## 三、分歧点与两种以上读法
|
||||
|
||||
**分歧点**:battle.md「可读下限 30px」(:144)的适用域——是否按视口档/板型分级适用。
|
||||
|
||||
- **读法甲(全域硬下限)**:30px 对一切视口档×板型组合生效 → 14×14 板在基座档不达标=产品缺陷,需要设计动作(改布局可用面积/改板型表/缩 14×14 适用域)。
|
||||
- **读法乙(按档分级)**:30px 下限以 1920 档为守卫面(推定断言只判 1080 档),基座档按实测算例记录(battle.md 算例本标注「随布局与板型变化,不是契约值」)→ 推定断言判据域改判 1080 档,基座档记录实测 28px 不下断言。
|
||||
- 两读法都属设计裁决(owner 文档 battle.md 的判据域修订),**实现段无权自裁**——读法乙虽不是「调低下限」(30 数值不动),但改变断言的适用域,同样超出卡片明列范围。
|
||||
|
||||
## 四、建议案(供裁决,禁代裁)
|
||||
|
||||
1. **建议主案=拆批**:迭代 46 以卡A(换图系七件批)+卡B(名字行提档与地台色合并批)先行合回——两卡已收口、代码域闸全绿(回执 45b53d68,commit 45b53d68 后另有 S9/S7 修正与卡B 提交);卡C 停摆退回写卡段,待 30px 下限适用域裁决后重立卡编入后续迭代。拆批合回前置=roadmap 迭代 46 行与待办清单条目状态换代(归文档批,本批禁写)。
|
||||
2. **裁决后的卡C 重写方向**(按所选读法):
|
||||
- 读法甲:重写卡范围收窄为「算式单点+门槛 36→30+四档冒烟+13 板推定」,14×14 不达标另立缺陷条目走设计段(布局或板型表动作)。
|
||||
- 读法乙:卡C 原范围保留,推定断言判据域改「1080 档 ≥30」+基座档实测记录句;battle.md 反哺点补「下限适用域分级」条。
|
||||
3. **卡C 已完成的可保留面**(worktree iter46 未提交改动,停摆卡不提交——随裁决处置):`board_view.gd` 算式单点提取 `_cell_for`(等价性已证:board_gen_reward_test 62→74 checks 全绿)、`layout_probe.gd` 门槛 36→30 与推定断言、`board_gen_reward_test.gd` 四档扩样。三件改动行为零变化,裁决后可直接复用。
|
||||
|
||||
## 五、待办清单条目状态回退+缺口补记(拟稿——落笔归上游段/用户)
|
||||
|
||||
条目「棋盘格边长三方取值不一致——待扩板定档处置(2026-10-06 登记,来源=批次移交)」:
|
||||
|
||||
- **状态**(现「已写卡+已编迭代 46」)→ 回退拟稿:`已写卡(卡C 停摆退回——L3 #2 实板可读面不达标)`。
|
||||
- **缺口补记拟稿**:`缺口:14×14 板基座档(1280×800)实板格边 28px 低于 battle.md 可读下限 30px 的适用域待设计裁决——1280 档实板可用面积 (1022,454)→28px、1080 档 (1662,734)→46px;13×13 两档均达标(30/46)。裁决点=读法甲(全域硬下限→产品缺陷走设计动作)vs 读法乙(下限按视口档分级→断言判据域改 1080 档)。裁决后重写卡C(算式单点/门槛对齐/四档冒烟三件已验可复用)。`
|
||||
|
||||
## 六、本批实况速览
|
||||
|
||||
- 卡A 换图系双基座七件批:**收口**(T0–T8 全落,--code 闸 7 闸全绿)。
|
||||
- 卡B 站桩名字行提档与地台色合并批:**收口**(26 checks 绿,golden 三张 0.00% 留痕)。
|
||||
- 卡C 棋盘格边长口径收口批:**停摆**(T0 完成、T1–T3 改动已验未提交、T4 未走)——本呈报。
|
||||
- 迭代合并:**阻塞**,等本呈报裁决(拆批合回 A+B,或卡C 闭合后整体合回)。
|
||||
@@ -0,0 +1,60 @@
|
||||
# 复核报告:迭代 47 双卡 grilling+godot-master 双审(2026-11-01)
|
||||
|
||||
- **接收方**:`reports/需求卡片-营地场景图新建批-2026-10-18.md`(卡④,v3.0→v3.1)+ `reports/需求卡片-ESC浮窗与营地顶栏批-2026-10-18.md`(卡⑤,v1.3→v1.4)。本报告是双审过程稿,裁断与订正已全部吸收进两卡,批末收尾按吸收即死退役。
|
||||
- **审查构成**:四个独立子代理——卡④ grilling/卡⑤ grilling/卡④ godot-master/卡⑤ godot-master(全程只读、未落盘、未跑测试)。
|
||||
- **发起**:用户令(开工前审查:零待裁点、零阻塞点、零灰色地带、符合 Godot 设计规范)。
|
||||
- **裁决**:用户 2026-11-01 裁「都可以按照推荐来」——五裁点照推荐采纳、P3/P5 销号口径采纳、卡⑤ v1.4 补句、卡④ 漂移就地订正+Godot 风险项落卡。
|
||||
|
||||
## 一、双审结论
|
||||
|
||||
| 卡 | grilling | godot-master |
|
||||
|---|---|---|
|
||||
| 卡④ | 有条件可开工——卡内设计待裁点确为零、重立凭据属实、与卡⑤ 接口名实闭合;但 §0.3 四道开工门实证全部未销号(会卡 T1/T2/T5),另有成片现状事实漂移 | 基本符合有风险项——分层/信号/单点纪律全对齐、零硬违反;风险=1024×1024 源档降采样算式断裂+核心视觉不变量机器验收零覆盖 |
|
||||
| 卡⑤ | 有条件可开工——零真待裁点(Q1/Q2/Q3 留痕完整);但三处现行文本会指导出错实现(浮窗残留缺陷级/V4 判据与契约 3 矛盾/Esc 第四态未定义) | 基本符合有风险项——浮窗选型/层序/拆件与现役先例同构、零硬违反;风险=文件表漏列 ui_modals/main_ui_build 两必改件+Esc 第四态连带语境分支谓词二义 |
|
||||
|
||||
## 二、裁断与销号落点(2026-11-01 用户裁)
|
||||
|
||||
| 项 | 裁断 | 卡内落点 |
|
||||
|---|---|---|
|
||||
| camp-scene-prompts §5 五裁点 | ①帐篷 300×170 追认现值②门扇 240×220 追认③布告板 (845,268,130,140) 挂围墙带④描边奶油色追认⑤环境子板色值不前置(T1 量化后按 art-bible §4.1 两道门登记;T5 色计数改条件步) | 卡④ §0.3-3/§9-4/§10;反哺点(§5 落文归文档批) |
|
||||
| P3 点选反馈设计稿 | 销号口径=camp.md v2.2:35-37 四态规格即设计稿;名牌文案与可点区域视觉归 T2 域内 | 卡④ §0.2/§0.3-1 |
|
||||
| P5 GDD/art-bible 落文 | 销号口径=形态落文完成;实装回填归 T6 反哺点义务,非停机条件 | 卡④ §0.2/§0.3-2 |
|
||||
| T1 素材后处理发令 | /iter 开工令即含授权,不再两次发令 | 卡④ §0.3-4/T1 |
|
||||
| 1024×1024 档降采样 | 逐张登记换算式;1024 档非整数缩放显式特批登记(L2+实现报告申报局限),不回炉(追认已过审终稿优先) | 卡④ T1 |
|
||||
| Esc 第四态与接线 | 契约 9 四态优先序(判据单点=ModalStack 现开集合)+接线定稿=事件驱动 `_unhandled_input`+KEY_ESCAPE、禁 Input 单例轮询、不挂 ui_cancel、pressed 且非 echo | 卡⑤ 契约 9/T0/T1/§9-1 |
|
||||
| 设置语境分支谓词 | =`camp_esc_overlay.visible`(谁开的设置谁收),与 Esc 守卫谓词分立 | 卡⑤ 契约 3 |
|
||||
| 返回主菜单浮窗残留 | 动线首步 close 浮窗;V3 断言补浮窗 closed | 卡⑤ 契约 4/T3/V3 |
|
||||
| camp 截图排序约束死信 | 废止原句;按迭代 47 执行序=卡④ 整卡先、卡⑤ 后,卡⑤ T2 限 HUD 区显式更新兜底 | 卡⑤ §0/卡④ T0 |
|
||||
|
||||
## 三、双审独立发现、交叉确证的灰色地带(全部落卡)
|
||||
|
||||
1. Esc 第四态(设置开在浮窗之上再按 Esc)——两审独立发现 → 契约 9①。
|
||||
2. 返回主菜单后浮窗残留(缺陷级)——grilling 发现、godot-master 同域印证 → 契约 4。
|
||||
3. V4 判据与契约 3 自相矛盾(浮窗恒 visible 由栈语义保证,非属性隐藏)→ V4 改述。
|
||||
4. V6 badge 文本格式字面不等(带「钥石 」前缀)→ V6 改格式串比较。
|
||||
5. CampRefreshBus「Bus」命名 vs 全局事件总线否决史(architecture.md:353)→ 卡④ T3 头注自陈+卡⑤ 措辞「挂接/接收推送」。
|
||||
6. 文件表漏列 `ui_modals.gd`/`main_ui_build.gd`(S13 触面失察;ui_modals 类变量 14→15 恰贴上限)→ 两卡文件表与存量触面一查补列。
|
||||
7. 「卡④ T5 晚于卡⑤ T2」排序约束单侧声明且按执行序天然不可满足 → 死信改述(见 §二)。
|
||||
8. V7 零动效扫描面漏开合编排件 → 扫描面扩两新件;V5 补「禁对退出钮 pressed.emit」;V1 补冒险语境段与 echo 断言;「进档重读」触发主体钉组合根动线尾。
|
||||
|
||||
## 四、卡④ 成片事实漂移订正(T0 级,v3.1 就地订正)
|
||||
|
||||
`game/smoke/` 已退役(git 16c6f136)→ 探针全在 `game/probe/`;smoke_all.gd 已退役(git 957391e1)→ system_test.gd(V2 :67-68/V3g :520-541)+theme_projection_test.gd:710-717;`main.camp_overlay` 句柄已退役 → `main.ui.modals.camp_overlay`(ui_modals.gd:14);F3/F7 行号簇换 2026-11-01 实测;F6「断点弹窗现居主菜单」失实(main.gd:118-120 注释)——T4 承接;`_on_confirm_new_adventure` 已随卡②摘除;`UiKit.TEX_CAMP_*` 尚不存在(本批 ui_kit.gd 新增十键);`tools/gdstyle.sh` 不存在(→ static_scan.sh/gdstyle_gate.py);presenters/core 子目录路径订正;`design/gdd/06-待办清单.md` 已迁仓库根;契约 4 行号换实数(八处 :82/90/102/114/126/139/151/165=七口+on_camp_buy 双尾);终局落点 main.gd:703 → main_adventure_flow.gd:123-143。
|
||||
|
||||
## 五、卡⑤ F1–F10 抽验
|
||||
|
||||
10 条全抽:F1/F2/F3/F5/F6/F7/F8/F9/F10 属实;F4 消费点全对、行号三处系统性 ±1(keystone_badge :633→:632、modal_shell :487→:486、danger_button :700→:699)——已订正。卡外小漂:screen_flow_probe 营地旗标在 :54(:53 是菜单行)、待办清单五卡总条 :447 起——已订正。
|
||||
|
||||
## 六、Godot 规范审查补立(卡④)
|
||||
|
||||
- 节点选型钉死:Control 根+TextureRect 层+子节点序即 z 序;禁 CanvasLayer/z_index/Sprite2D 根(LAYER_CONTRACT 树序落位兼容)。
|
||||
- V1 扩判据:camp_scene_view 子节点序=layout 表 z 序逐层相等、纹理矩形与表逐值一致;新增 V14 layout 数据件校验(fail-fast 命中区几何)——核心视觉不变量机器验收面补齐。
|
||||
- T2 实现约束:浮动经 Tween 禁 `_process`;名牌 Label mouse_filter=IGNORE;禁用态去饱和经 ShaderMaterial;名牌画面内钳制;HUD 载体循 page_shell `PRESET_TOP_WIDE` 先例。
|
||||
- layout.tres 接 ConfigDB schema 类(先例 battle_layout.tres)+加载期 fail-fast 校验。
|
||||
|
||||
## 七、遗留与开工判定
|
||||
|
||||
- **零待裁点、零阻塞点**:卡④ §0.3 四道开工门全部裁断销号;卡⑤ 零真待裁点、开工按序随卡④ 代码波(迭代内排序,非跨迭代阻塞)。
|
||||
- 反哺点落文已完成(2026-11-01 本会话文档批,同批合回):camp-scene-prompts.md v1.3 §5 改已裁+art-bible.md v3.31 §6.2 待裁行改已裁;camp.md/art-bible 实装状态回填归迭代实现批 T6 义务。
|
||||
- 机检预算互斥裁决(2026-11-01 用户裁,停机呈报=iter47 worktree):实现段实测两卡平铺合计 ui_modals.gd 类变量 19>S13 上限 15——裁**最小改动**=营地六句柄落 `ui_camp_modals.gd` 子容器(新立卡⑥ 前置基建,迭代 47 执行序第一位;卡④ v3.2/卡⑤ v1.5 随批改口径,卡⑤ v1.4「14→15 恰贴」算术缺陷一并订正);全量分域句柄分家登记待办清单另立批。双审预算审为单卡口径、未做跨卡同文件累加核对,已在裁决中注记。
|
||||
- **判定:迭代 47 可开工**(卡⑥ → 卡④ → 卡⑤ 按序,`/iter` 发令即起 T0)。
|
||||
@@ -1,331 +1,145 @@
|
||||
# 提案:弃图刷新系专长流派(双基座七件)——预案 v0.4(2026-10-30)
|
||||
# 提案:弃图刷新系专长流派(双基座七件)——预案 v0.5(2026-10-31)
|
||||
|
||||
> **性质**:待办清单条目「封锁-蓄力」combo 设计素材的设计提案与 GDD 修改清单。双基座七件结构已经用户确认,修改清单已经用户审核并落入四份 GDD;本文按用户要求保留,供后续写需求卡片参考。代码与数值表尚未实现。
|
||||
> **性质**:换图系设计提案与 GDD 修改清单。双基座七件结构已经用户终审;本文保留为后续实现与验收的参考件,不随 GDD 落文退役。
|
||||
>
|
||||
> **需求来源**:用户 2026-10-30 明确设计方向——流派先有基座专长,从资源来源、动作成本或结算规则上改变基础行为;后续专长围绕新行为提供输出、生存与资源收益。只有刷新后的数值增长,不足以形成流派。
|
||||
> **核心裁定**:流派先由基座专长改变资源来源与刷新价格,再由后续专长让成功刷新直接形成输出、生存与 GP 资源收益。所有效果都改变玩家的刷新决策,不把旧图探索进度折算成清图奖励。
|
||||
>
|
||||
> **结构裁定**:用户指定设计 **2 件基座+2 件输出+2 件生存+1 件资源**,共 7 件;两件基座允许同时持有并叠加;弃图回收按旧图探索进度发清图奖励,不采用固定发一份。本提案结构待裁点已清零。
|
||||
>
|
||||
> **结论行**:「掘进储能」让挖格产 RAP,解决刷新资源从哪里来;「折价换图」让刷新 RAP 成本减半,解决同样资源能刷几次。两件基座叠加后形成完整换图引擎。后续五件让刷新分别产生群体直伤、下次攻击爆发、护盾、回血与按探索进度回收的清图奖励。拿到任一基座后,刷新不再只是坏图逃生;配上后续专长,玩家会为了输出、生存或资源主动规划换图。
|
||||
> **结论行**:矿脉储能让付费挖格产 RAP,省力周转把刷新成本减半;两件基座允许叠加。崩壁冲击与蓄力周转把刷新变成输出,石层缓冲把刷新变成当轮全局受伤减免,坑道小憩把多次刷新累计成当轮恢复,矿道红利每次成功刷新固定给 1 GP。
|
||||
|
||||
---
|
||||
|
||||
## 0. 七件总表
|
||||
|
||||
> 名称均为代号;数值与稀有度均为 provisional,不在本预案定稿。
|
||||
|
||||
| 层 | 代号 | 效果候选 | 它改变的决策 |
|
||||
| 层 | 显示名 | 效果 | 行为职责 |
|
||||
|---|---|---|---|
|
||||
| **基座** | **掘进储能** | 每次付费挖格后额外获得 RAP | 想刷新不再必须少挖停手;持续挖图也能蓄能 |
|
||||
| **基座** | **折价换图** | 弃图刷新的 RAP 成本减半 | 同样的储备支持更多刷新;部分挖格+部分停手也能维持换图 |
|
||||
| **输出** | **弃图轰击** | 成功刷新后,对全体存活敌人造成伤害 | 刷新本身成为进攻动作 |
|
||||
| **输出** | **换图蓄势** | 每次刷新攒层;下一次攻击附加全部层数后清零 | 连续换图可以蓄成一次单点爆发 |
|
||||
| **生存** | **换图庇护** | 成功刷新后获得护盾 | 刷新可以主动用来抵挡后续伤害 |
|
||||
| **生存** | **弃图休整** | 成功刷新后回复生命 | 玩家可以放弃当前图,换取一次恢复机会 |
|
||||
| **资源** | **弃图回收** | 成功刷新后,按旧图探索进度回收清图奖励 | 不必挖完最后几格;可以先投入,再主动弃图变现 |
|
||||
|
||||
**结构关系**:基座负责让主动刷新可持续;输出、生存、资源五件负责让主动刷新有明确目的。后续专长不需要设置「必须先拿基座」的硬前置,它们的联动由实际刷新频率自然形成。
|
||||
| 基座 | 矿脉储能 | 每次受理的付费挖格额外获得 RAP | 持续挖图也能为刷新蓄能 |
|
||||
| 基座 | 省力周转 | 弃图刷新的 RAP 成本减半 | 同一份 RAP 支撑更多刷新 |
|
||||
| 输出 | 崩壁冲击 | 成功刷新后,本轮战斗段末对全体存活敌造成固定伤害 | 刷新成为进攻动作 |
|
||||
| 输出 | 蓄力周转 | 每次成功刷新叠层,上限 3;本轮下一次主角攻击消费全部层数 | 连续刷新汇成单点爆发 |
|
||||
| 生存 | 石层缓冲 | 本轮只要成功刷新过,主角每次受到伤害固定减少 2 点;不叠加 | 刷新成为当轮防御姿态 |
|
||||
| 生存 | 坑道小憩 | 每次成功刷新累计 1 点恢复,上限 3;本轮授予段合计回血 | 用刷新换取恢复空间 |
|
||||
| 资源 | 矿道红利 | 每次成功刷新固定获得 1 GP | 刷新动作自身带少量金币收益 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 通用设计思想:先改变行为,再给新行为收益
|
||||
## 1. 设计原则
|
||||
|
||||
这一节同时作为后续修订 `奇物.md`「专长·设计原则」的建议文本。现在只记录在提案中,尚未写入 GDD。
|
||||
|
||||
### 1.1 基座专长的定义
|
||||
|
||||
**基座专长=让某个原本偶尔使用、主要用于止损的动作,变成可以持续使用的主要打法的专长。**
|
||||
|
||||
它至少改变下列一项:
|
||||
|
||||
1. **资源来源**:原来主要靠停手获得 RAP,现在挖格也能获得 RAP。
|
||||
2. **动作成本或频率**:原来一整轮停手才能刷新一次,现在同样储备可以支持更多刷新。
|
||||
3. **动作结算**:原来危险格只伤害玩家,现在也能重伤敌人,使主动踩雷成为进攻手段。
|
||||
4. **动作关系**:原来挖图与弃图争夺资源,现在挖图为弃图蓄能,两个动作组成循环。
|
||||
|
||||
成本减半虽然形式上仍是数值变化,但如果它让刷新从偶尔可用变成持续可用,也满足基座要求。**判断标准不是改了多少规则文本,而是玩家的实际操作是否改变。**
|
||||
|
||||
### 1.2 基座与后续专长的分工
|
||||
|
||||
| 层 | 职责 | 不合格形态 |
|
||||
|---|---|---|
|
||||
| **基座专长** | 建立新的资源循环或动作规则,让核心动作能持续使用 | 只在原动作后加少量攻击、护甲或资源,动作使用时机不变 |
|
||||
| **后续专长** | 让核心动作产生输出、生存或资源收益,扩展新打法 | 不依赖新行为、放进任何构筑都同样有效的泛用数值增长 |
|
||||
|
||||
后续专长仍可采用「当 X 时 Y」的触发器句式,也可以各自独立生效;不另设集件标签。它们与基座的联系来自实际玩法:没有基座时,刷新少、收益兑现慢;有基座后,同一效果成为主循环的一部分。
|
||||
|
||||
### 1.3 行为改变检验
|
||||
|
||||
新流派或新基座专长过准入时,必须回答三个问题:
|
||||
|
||||
1. **拿之前怎么玩,拿之后怎么玩?** 如果最优操作与决策时机基本不变,只是结算数字变大,就不是基座。
|
||||
2. **新行为为什么能持续?** 必须写清资源从哪里来、多久能做一次、什么限制防止无限循环。
|
||||
3. **后续专长为什么属于这里?** 它应当兑现或强化基座建立的行为,而不是替代基座。
|
||||
|
||||
以自爆流为例:没有相关专长时,玩家应躲开危险格;拿到能减少自身雷伤、同时让危险格重伤敌人的基座后,玩家会主动寻找危险格。后续专长再提供踩雷后的回复、护甲或追加伤害。**「本来不该点」变成「现在值得主动点」,才是行为改变。**
|
||||
1. **基座先改行为**:必须改变资源来源、动作成本、动作结算或动作关系,使偶尔止损的刷新成为可持续打法。
|
||||
2. **后续收益围绕新行为**:输出、生存、资源件只在成功刷新后兑现,不做放进任何构筑都成立的泛用增益。
|
||||
3. **双基座可叠加**:一件改 RAP 收入,一件改 RAP 支出;每轮刷新上限继续负责限频。
|
||||
4. **无专长基线不变**:七件只给持有者增加规则;全局经济、清图奖励与刷新基础语义不改。
|
||||
5. **临时生命值不做**:现有体系没有独立血量护盾,本流派不使用该概念;石层缓冲直接减少最终承伤。
|
||||
|
||||
---
|
||||
|
||||
## 2. 两件基座:分别改资源来源与动作价格
|
||||
## 2. 行为循环
|
||||
|
||||
### 2.1 掘进储能
|
||||
无专长时:
|
||||
|
||||
**效果候选**:每次付费挖格后,额外获得一定 RAP。安全格与危险格都按付费挖格计,不另判玩家意图。
|
||||
|
||||
**基础循环**:
|
||||
|
||||
```
|
||||
持续挖格并获得格面收益 ──同时积攒 RAP──▶ 主动弃图刷新
|
||||
▲ │
|
||||
└──────── 新图继续挖格 ◀───────────────┘
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[正常挖图] --> B[遇到坏图]
|
||||
B --> C[停手攒 RAP]
|
||||
C --> D[必要时刷新]
|
||||
D --> A
|
||||
```
|
||||
|
||||
**行为改变**:
|
||||
拿到两件基座后:
|
||||
|
||||
- 玩家可以一边挖图拿收益,一边准备下一次刷新,不再必须停手。
|
||||
- 每轮 AP 有限,因此新增 RAP 也有限;它扩大刷新机会,不提供无限刷新。
|
||||
- 单拿时,坏图更容易被换掉;配上任意后续专长得益后,主动刷新才有完整目的。
|
||||
|
||||
### 2.2 折价换图
|
||||
|
||||
**效果候选**:弃图刷新的 RAP 成本减半。
|
||||
|
||||
**基础循环**:
|
||||
|
||||
```
|
||||
部分挖格/部分停手留 AP → 同一份 RAP 支持更多次刷新 → 更频繁兑现后续专长
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[付费挖格] -->|矿脉储能| B[RAP 增长]
|
||||
B -->|省力周转半价| C[成功刷新]
|
||||
C --> D[崩壁冲击]
|
||||
C --> E[蓄力周转]
|
||||
C --> F[石层缓冲]
|
||||
C --> G[坑道小憩]
|
||||
C --> H[矿道红利]
|
||||
C --> I[新图继续挖格]
|
||||
```
|
||||
|
||||
**行为改变**:
|
||||
玩家会同时比较:
|
||||
|
||||
- 玩家不再需要为一次刷新攒下完整一轮的 AP;挖图与留 AP 的比例出现更多选择。
|
||||
- 与掘进储能不同,它保留停手攒 RAP 的旧来源,但降低主动换图所需的投资。
|
||||
- 单拿时,刷新从昂贵逃生变成常用工具;配上后续专长后,刷新次数直接转化为输出、生存或资源。
|
||||
|
||||
### 2.3 两件基座的组合
|
||||
|
||||
两件基座作用在不同位置:一个改 RAP 来源,一个改 RAP 价格。**用户已裁定允许同时持有并叠加**,组合后形成完整基座:
|
||||
|
||||
```
|
||||
挖格产 RAP + 刷新半价 → 每轮更容易达到刷新次数上限 → 后续五件兑现收益
|
||||
```
|
||||
|
||||
叠加后的硬边界仍是每轮刷新次数上限、有限 AP、旧图进度损失与战斗结束 RAP 清零。若实测过强,优先调产能量与半价数值,不增加「两件基座互斥」的特殊规则。
|
||||
- 还要不要继续挖旧图,还是现在刷新兑现崩壁冲击或矿道红利;
|
||||
- 本轮承伤压力大时,是否用石层缓冲换一次全局减伤;
|
||||
- 生命偏低时,是否通过多次刷新累计坑道小憩的恢复;
|
||||
- 是否蓄满 3 层蓄力周转,把多次刷新集中成一次攻击;
|
||||
- 刷新次数与 RAP 价格如何影响后续图推进。
|
||||
|
||||
---
|
||||
|
||||
## 3. 两件输出:即时群伤与延迟爆发
|
||||
## 3. 七件效果结构
|
||||
|
||||
### 3.1 弃图轰击
|
||||
### 3.1 矿脉储能
|
||||
|
||||
**效果候选**:每次弃图刷新成功后,对全体存活敌人造成伤害。
|
||||
每次付费挖格被受理后,额外获得 1 RAP。连锁展开不逐格追加;封印、移动、刷新不产 RAP。
|
||||
|
||||
**玩法职责**:提供即时、稳定的群体输出。玩家会在「继续挖旧图」与「现在刷新打一轮伤害」之间做选择。
|
||||
### 3.2 省力周转
|
||||
|
||||
**与其他件的关系**:
|
||||
刷新 RAP 成本固定为基线的 50%。它只改持有者的价格,不改全局基值,也不返 RAP。
|
||||
|
||||
- 掘进储能支持持续挖、持续刷、持续轰击。
|
||||
- 折价换图让同一份 RAP 兑现更多次轰击。
|
||||
- 与换图蓄势组合时,一次刷新同时提供当场群伤与下次攻击的蓄力层。
|
||||
### 3.3 崩壁冲击
|
||||
|
||||
**边界**:只有成功刷新才触发;刷新被拒绝不触发;每轮刷新上限同时限制伤害次数。
|
||||
每次成功刷新记录一次当轮事实。本轮战斗段末,所有存活敌人各受 2 点固定伤害;刷新瞬间不当场插入战斗结算。
|
||||
|
||||
### 3.2 换图蓄势
|
||||
### 3.4 蓄力周转
|
||||
|
||||
**效果候选**:每次成功刷新获得 1 层蓄势,层数有上限;下一次攻击附加全部层数对应的伤害,然后清零。
|
||||
每次成功刷新叠 1 层,最多 3 层。本轮下一次主角攻击附加全部层数对应的攻击加成,消费后清零;战斗结束不跨战保留。
|
||||
|
||||
**玩法职责**:提供延迟、集中的单点爆发。与弃图轰击的即时群伤不同,它鼓励连续换图后寻找合适的攻击窗口。
|
||||
### 3.5 石层缓冲
|
||||
|
||||
**与其他件的关系**:
|
||||
每次成功刷新把当轮减伤状态置为生效。本轮主角每次受到伤害,在现行伤害下限之前固定减少 2 点;同一轮多次刷新不继续叠加。覆盖敌方攻击、危险格、错误封印资源格与地形造成的主角伤害。
|
||||
|
||||
- 双基座组合更容易连续刷新,为一次重攻蓄满层数。
|
||||
- 与现有攻击强化专长可以组合,但不另设专属加成。
|
||||
- 层数只在当前战斗内保留,战斗结束清零,避免跨战囤积。
|
||||
### 3.6 坑道小憩
|
||||
|
||||
**边界**:层数必须有上限;一次攻击消费全部层数,不能同一批层数重复附加到多次攻击。
|
||||
每次成功刷新累计 1 点恢复量,最多累计 3 点。本轮授予段一次性合计回复生命,不超过生命上限,随后清零。
|
||||
|
||||
### 3.7 矿道红利
|
||||
|
||||
每次成功刷新固定获得 1 GP。不按旧图探索进度折算,也不与清图奖励绑定。每轮刷新上限限制触发次数。
|
||||
|
||||
---
|
||||
|
||||
## 4. 两件生存:当场护盾与直接回血
|
||||
## 4. 与现行结算时序的衔接
|
||||
|
||||
### 4.1 换图庇护
|
||||
|
||||
**效果候选**:每次成功刷新后获得护盾,按现有护盾规则抵挡伤害与消耗。
|
||||
|
||||
**玩法职责**:提供面向未来伤害的保护。玩家可以预判敌方压力,主动弃图换护盾,而不是只在棋盘不好时刷新。
|
||||
|
||||
**与弃图休整的区别**:护盾适合抵挡即将发生的伤害;休整用于修复已经失去的生命。一件偏预防,一件偏补救。
|
||||
|
||||
### 4.2 弃图休整
|
||||
|
||||
**效果候选**:每次成功刷新后回复一定生命。
|
||||
|
||||
**玩法职责**:把旧图与 RAP 转成恢复机会。生命偏低时,玩家可以放弃当前图的后续收益,换取继续冒险的空间。
|
||||
|
||||
**边界**:
|
||||
|
||||
- 回复不能超过生命上限,不转化为额外生命。
|
||||
- 刷新成本与每轮次数上限不变,不能无代价连续回血。
|
||||
- 强度对账时须同时计算放弃旧图进度的损失,不能只看单次回血量。
|
||||
|
||||
两件生存专长可以同时持有,让刷新兼具保护与恢复;但它们不替代输出件,玩家仍需通过其他攻击手段结束战斗。
|
||||
- 刷新只结束挖掘动作的资源支出,不结束当前轮次,也不新增第六个结算段。
|
||||
- 成功刷新后产生 `board_refreshed` 事实;刷新被拒绝时不产生事实。
|
||||
- 崩壁冲击只先开伤害单,沿用现行案 C,在战斗段末结账。
|
||||
- 石层缓冲订阅全局 `damage_taken`;该事件统一覆盖所有主角受伤路径。
|
||||
- 坑道小憩和矿道红利用现有 GP/治疗兑付通道留痕。
|
||||
- 刷新图仍不发清图奖励;正常清图支配性不变。
|
||||
|
||||
---
|
||||
|
||||
## 5. 一件资源:把旧图投入换成清图奖励
|
||||
## 5. 防退化边界
|
||||
|
||||
### 5.1 弃图回收
|
||||
|
||||
**已定效果**:成功刷新后,按旧图本次探索进度回收清图奖励;探索越多,回收越完整。具体档位、比例与奖励内容归后续调参。
|
||||
|
||||
**玩法职责**:建立与正常清图不同的资源兑现路线:
|
||||
|
||||
```
|
||||
先挖图投入 AP、积累探索进度 → 不再挖最后几格 → 主动刷新 → 按进度回收清图奖励
|
||||
```
|
||||
|
||||
**行为改变**:旧图不再只有「清完」与「全部放弃」两个结果。玩家可以比较继续清图的时间与风险,选择提前弃图变现。
|
||||
|
||||
**为什么不固定发一份**:空图刷新也拿完整收益,会让挖图投入失去意义,并把资源流退化成机械地点刷新。按进度回收要求玩家先探索、再决定何时兑现,保留先投入再弃图的循环,也保留接近清图时的取舍。用户已据此裁定采用按进度回收。
|
||||
|
||||
**边界**:同一旧图只能在成功放弃时结算一次;新图没有继承旧图的可回收进度;刷新被拒绝时不发奖励。
|
||||
- RAP 仍来自有限 AP,不能无限刷新。
|
||||
- 刷新本身不返 RAP。
|
||||
- 每轮刷新上限继续生效。
|
||||
- 石层缓冲是固定减伤,不堆层、不产生零伤害。
|
||||
- 坑道小憩恢复上限 3,不能靠无限刷新稳定续命。
|
||||
- 矿道红利每次仅 1 GP,量级明显低于正常战斗掉落,不足以替代清图与探索收益。
|
||||
- 不引入临时生命值,不改变棋盘信息规则。
|
||||
|
||||
---
|
||||
|
||||
## 6. 七件如何组成不同打法
|
||||
## 6. 最终裁定记录
|
||||
|
||||
| 构筑方向 | 组合 | 主要操作 |
|
||||
|---|---|---|
|
||||
| **持续轰击** | 掘进储能+弃图轰击 | 边挖边蓄 RAP,够价就刷新,刷新持续削全体敌人 |
|
||||
| **蓄力爆发** | 折价换图+换图蓄势 | 用较低成本连续换图,把多次刷新汇成一次重攻 |
|
||||
| **双基座输出** | 两基座+两件输出 | 高频刷新同时提供群伤与攻击层数,形成完整输出流 |
|
||||
| **换图续命** | 任一基座+换图庇护+弃图休整 | 在生命与敌方压力下主动换图,用护盾与回血延长战斗 |
|
||||
| **弃图采收** | 掘进储能+弃图回收 | 挖到一定进度后主动放弃,连续从新图获取探索收益与回收奖励 |
|
||||
| **七件完整形态** | 全部七件 | 挖格蓄能、低价刷新,每次换图同时兑现输出、生存与资源;仍受每轮次数上限约束 |
|
||||
|
||||
**最小成立单位**是任一基座+任一符合当前需要的后续专长。七件不要求一次拿齐,也不设集件奖励。
|
||||
- D1:双基座允许叠加。
|
||||
- D2:资源件改为每次成功刷新固定 1 GP,不采用探索进度回收清图奖励。
|
||||
- D3:生存件改为全局固定减伤,不使用护盾或临时生命。
|
||||
- D4:恢复量按当轮成功刷新次数累计,上限 3。
|
||||
- D5:所有主角伤害统一经过 `damage_taken`,允许现有订阅该事件的专长覆盖面按字面扩展。
|
||||
- D6:七件显示名采用矿脉储能/省力周转/崩壁冲击/蓄力周转/石层缓冲/坑道小憩/矿道红利。
|
||||
- D7:其余数值与稀有度先按需求卡片 provisional 投值,出口人闸追认。
|
||||
|
||||
---
|
||||
|
||||
## 7. 防退化与共同边界
|
||||
## 7. 后续参考
|
||||
|
||||
| 检查 | 约束 |
|
||||
|---|---|
|
||||
| **是否无限自供能** | 新 RAP 来自有限 AP 的付费挖格;刷新本身不产 RAP;每轮刷新上限与战斗结束清零不变。 |
|
||||
| **无专长基线是否改变** | 不改变。两件基座是专长提供的新规则,不直接修改无专长时的全局经济。 |
|
||||
| **双基座是否失控** | 叠加后仍受每轮次数上限;数值对账以每轮实际可达到的刷新次数为准。 |
|
||||
| **输出是否重复消费** | 轰击每次成功刷新结算一次;蓄势层数在一次攻击后全部清零。 |
|
||||
| **生存是否无代价** | 护盾与回血都要求成功刷新;玩家同时付出 RAP、旧图进度与刷新名额。 |
|
||||
| **正常清图是否被删除** | 不删除。弃图回收不应让同等投入的收益无条件高于正常清图。 |
|
||||
| **空图是否拿满资源** | 推荐案不允许;回收按旧图探索进度计算。 |
|
||||
| **信息红线** | 七件均不增加揭示效果,不碰危险格信息规则。 |
|
||||
本文保留供需求卡片、实现验收与后续调参比对。换图系现行权威规则仍以四份 GDD为准:
|
||||
|
||||
若实装后玩家仍然只在坏图时刷新,说明基座或后续收益没有真正成立;不能只继续增加数值来掩饰行为没有改变。
|
||||
|
||||
---
|
||||
|
||||
## 8. 旧案处置
|
||||
|
||||
| 旧内容 | 本案处置 |
|
||||
|---|---|
|
||||
| 抬高刷新成本 | 删除;与主动刷新方向相反 |
|
||||
| 刷新全板开 | 不进入本案;不是形成刷新流的必要条件 |
|
||||
| 静气:不刷新给减伤 | 从本流派删除;奖励相反行为 |
|
||||
| 换图回气 | 删除;只返还部分成本,不建立新循环 |
|
||||
| 换图开眼/明察 | 删除;属于信息附属收益 |
|
||||
| 换图退守 | 由换图庇护承接生存方向 |
|
||||
| 换图成势 | 保留其延迟爆发思路,重写为换图蓄势;另增即时群伤弃图轰击 |
|
||||
| 单基座二选一 | 改为双基座并存;用户已裁定允许同时持有并叠加 |
|
||||
|
||||
---
|
||||
|
||||
## 9. GDD 修改清单(用户已审核,已落文)
|
||||
|
||||
以下清单已经用户审核并落入对应 GDD;现行规则以各 GDD 为准,本节保留供后续写卡核对改动面。采用**刷新记录事实、本轮结算兑付效果**的衔接方案:不新增第六个结算段,不让刷新当场结束一轮,也不改状态只能在轮末授予的现行规则。
|
||||
|
||||
### 9.1 `design/gdd/systems/冒险循环/奇物.md`
|
||||
|
||||
- 在「专长·设计原则」加入基座专长定义:改变资源来源、动作成本/频率、动作结算或动作关系,使原本止损用的动作成为持续主打法。
|
||||
- 加入三项行为改变检验:拿前后操作是否不同;新行为如何持续;后续专长为何依附该行为。泛用数值增长不能冒充基座。
|
||||
- 事件族由五族扩为六族,新增设计侧分组「换图系」;族名仍不上玩家卡面,不设集件奖励或强制先拿基座。
|
||||
- 登记双基座七件:掘进储能、折价换图、弃图轰击、换图蓄势、换图庇护、弃图休整、弃图回收;写清两件基座允许叠加。
|
||||
- 写清七件职责:两件输出分别为群体直伤与下次攻击爆发;两件生存分别为护盾与回血;资源件按旧图探索进度回收清图奖励。
|
||||
- 同步专长总数、族数与相关验收标准;落文已按当轮 `feats.tres` 实数复核为 30 行,换图系七件标为待实现,不计入现役行数。
|
||||
- 落文版本=v1.2。
|
||||
|
||||
**不自动改自爆流**:现行「净血账期望必须为负、防见雷就踩」与用户描述的理想自爆流方向不同,需另一次明确裁决,不随换图系一并改掉。
|
||||
|
||||
### 9.2 `design/gdd/systems/排雷循环/行动经济.md`
|
||||
|
||||
- 在停手转存之外登记专长提供的第二 RAP 来源:持有掘进储能时,每次付费挖格额外获得 RAP;安全格与危险格同口径,无专长时不变。
|
||||
- 登记折价换图:持有专长时刷新 RAP 成本减半;只改专长持有者的价格,不改全局表基值。
|
||||
- 写清双基座叠加:挖格产 RAP 与刷新半价同时生效;结算顺序、拒绝刷新不产效果要有验收口径。
|
||||
- 保留现有限制:刷新不终结本轮、不重置 AP;每轮次数上限不变;RAP 战斗结束清零;刷新本身不产 RAP。
|
||||
- 增补对应验收标准。
|
||||
|
||||
### 9.3 `design/gdd/systems/战斗循环/战斗结算.md`
|
||||
|
||||
- 新增「刷新成功」事实:只有成功换图才产生;旧图退役前保存本次探索进度,供弃图回收使用;刷新被拒绝不产生事实。
|
||||
- **推荐时序**:刷新只记录事实,不当场插入一轮结算。弃图轰击在本轮战斗段经伤害控制器兑付;换图庇护与弃图休整在本轮授予段兑付;弃图回收随本轮授予段结算。五段顺序不变。
|
||||
- 换图蓄势在刷新成功时累计层数,下一次主角攻击附加并清零;层数上限与战斗结束清零写入规则。
|
||||
- 群伤若击杀最后敌人,由本轮既有判定段判胜,避免新增挖掘期即时胜利分支。
|
||||
- 专长效果写扩展现行:群伤走伤害单据,护盾/回血/回收各留可归因的结算行;来源指向刷新专长与被弃旧图,不伪造格子来源。
|
||||
- 「刷新图不发清图奖励」保持不动;弃图回收兑的是**旧图**按进度回收的奖励,不是把新图判成已清图。
|
||||
- 增补对应验收标准。
|
||||
|
||||
### 9.4 `design/gdd/systems/战斗循环/地图战斗资源.md`
|
||||
|
||||
- 扩展清图奖励对象的使用口径:正常清图仍发完整对象;持有弃图回收时,旧图可按探索进度回收同一奖励对象的一部分。
|
||||
- 建议把「探索进度」定义为:`(旧图已开安全格数 − 装板初始已开安全格数)÷ 装板初始未开安全格数`,限制在 0~1。连锁展开真实推进探索,计入;初始封锁格与危险格不计入。
|
||||
- 写清弃图回收只发基础奖励的进度份额:不触发完美封印加倍,不产生清图事件,不把旧图判为清图。
|
||||
- 同一旧图只在成功退役时回收一次;新图不继承旧图进度;空投入刷新不能拿完整奖励。
|
||||
- 具体比例、档位、取整与奖励数值归调参;已增补对应验收标准,落文版本=v1.2。
|
||||
|
||||
### 9.5 按推荐时序不需要修改的文档
|
||||
|
||||
- `增益状态.md`:护盾仍在轮末授予段进入状态池,继续遵守「授予只在结算时发生」与「跨轮跨图延续」,不需要为刷新开即时授予例外。
|
||||
- `02-系统清单.md`:不新增文档,只改现有系统文档,无需改根索引。
|
||||
- `术语表.md`:七件名称目前均为代号,正式命名前不登记新术语。
|
||||
|
||||
### 9.6 本 GDD 批明确不改
|
||||
|
||||
- 不改 `feats.tres`、其他数值表、代码、测试或架构实现现状;这些归后续写卡与实现批。
|
||||
- 不改自爆流现行条款,不顺带重做其他专长族。
|
||||
- 不采用「刷新瞬间结算全部效果」方案。若用户要求即时生效,需另增 `增益状态.md` 与战斗胜利时序的修改项,再重新审核。
|
||||
|
||||
**两处衔接已经用户审核**:①后续效果统一在本轮结算兑付,而非刷新瞬间兑付;②弃图回收的探索进度按安全格实际推进计算,连锁计入、初始格与危险格不计。
|
||||
|
||||
---
|
||||
|
||||
## 10. 后续验收必须证明的行为
|
||||
|
||||
1. **掘进储能**:从真实挖格入口进入,持有专长时 RAP 按声明增加;无专长时挖格不新增 RAP。
|
||||
2. **折价换图**:真实刷新入口按修改后的成本扣 RAP;AP、轮次与其他刷新规则不变。
|
||||
3. **基座组合**:两件同时持有时,挖格产 RAP 与刷新半价都生效;验证成本与产 RAP 顺序,任何组合都不能超过每轮刷新上限。
|
||||
4. **弃图轰击**:成功换图后全体存活敌人受伤;刷新被拒绝时不触发。
|
||||
5. **换图蓄势**:多次刷新正确叠层并受上限约束;下一次攻击附加全部层数后清零;战斗结束清空。
|
||||
6. **换图庇护/弃图休整**:只在成功刷新后给护盾或回血;回复不超过生命上限。
|
||||
7. **弃图回收**:读取被放弃旧图的探索进度;不同进度按规则得到不同奖励;同一旧图不能重复领取。
|
||||
8. **基线零扰动**:没有这些专长时,RAP 来源、刷新成本、清图奖励与刷新结果保持现行规则。
|
||||
9. **真人体验判断**:拿到基座与后续专长后,玩家会主动考虑刷新,而不是仍只在坏图时使用。此项登记真人验证,不阻塞实现验收。
|
||||
|
||||
---
|
||||
|
||||
## 11. 已定结构:零待裁点
|
||||
|
||||
| 决策 | 用户裁定 | 落地口径 |
|
||||
|---|---|---|
|
||||
| **D1 双基座关系** | 允许同时持有并叠加 | 掘进储能改 RAP 来源,折价换图改 RAP 价格;每轮刷新上限继续限频,不设互斥规则。 |
|
||||
| **D2 弃图回收** | 按旧图探索进度回收 | 必须先探索再兑现;不采用每次刷新固定发一份,避免空图刷新拿完整收益、退化成机械点刷新。 |
|
||||
|
||||
双基座七件结构由此闭合。具体数值与稀有度不属于结构待裁点,统一归后续调参。
|
||||
|
||||
---
|
||||
|
||||
## 12. 下一步
|
||||
|
||||
1. 用户发令后进入写需求卡片段,以本提案与四份 GDD 为输入,按第 10 节建立真实入口断言与行为验收。
|
||||
2. 迭代编排后实现;具体数值与稀有度归后续调参。
|
||||
3. 自爆流现行条款不在本批改动面内;若以后要按同一基座思想重构,另行登记与裁决。
|
||||
|
||||
本提案保留为写卡参考;换图系七件尚未实装,未跑任何游戏测试。
|
||||
- `design/gdd/systems/冒险循环/奇物.md`
|
||||
- `design/gdd/systems/排雷循环/行动经济.md`
|
||||
- `design/gdd/systems/战斗循环/战斗结算.md`
|
||||
- `design/gdd/systems/战斗循环/地图战斗资源.md`
|
||||
@@ -1,18 +1,19 @@
|
||||
# 需求卡片:Esc 浮窗与营地顶栏批(营地顶部小 HUD 栏 · Esc 三钮浮窗)· 营地交互重做卡⑤
|
||||
|
||||
- 版本:**v1.2**(2026-10-18 grilling 轮次裁定回写——Q1 裁定甲(只营地根态响应,代拍板留痕)、Q2 裁定甲(再按 Esc 关浮窗,推荐案)、Q3 裁定甲(确认 Esc 只在营地语境,推荐案,用户的从严收窄升格为已确认);契约 2 随 Q3 升格;卡④回设计段→本卡排期随④重新立卡后,卡片保留有效)
|
||||
- 版本:**v1.5(现行有效卡)**。留痕:Q1/Q2/Q3 均于 2026-10-18 裁定(甲/甲/甲,见 §10,已裁非待裁);卡④ 2026-10-31 重立、2026-11-01 修订为 v3.1,本卡随卡④ 代码波同行;2026-11-01 grilling+godot-master 双审后用户令修订(v1.4)——契约 9 新立、契约 3 谓词钉死、契约 4 浮窗自收、V4/V6 订正、死信约束改述、文件表补两件;2026-11-01 用户裁机检预算互斥停机呈报(v1.5)——浮窗句柄改落 `ui_camp_modals.gd` 子容器(卡⑥ 前置建件,本卡 T1 落第六枚),`ui_modals.gd` 类变量 14 不升(原「14→15 恰贴」句作废),契约 7 补寻址形态。
|
||||
- 来源:[需求澄清-营地交互重做-2026-10-18.md](需求澄清-营地交互重做-2026-10-18.md)(唯一事实源:⑤裁决 9/10、④结构树语境、⑦切批原则⑤)
|
||||
- 归属:呈现层/组合根(`game/presentation/`)——营地交互重做五卡之五
|
||||
- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁)
|
||||
- 开工门:U0(用户 `/iter` 发令)+ 待裁点已裁(Q1/Q2/Q3 均裁定,见 §10)+ grilling 复核门过+ **卡④重新立卡并落地后**(本卡浮窗与 HUD 落在卡④新建的场景屏上——卡④ 2026-10-18 回设计段,本卡排期随④之后,卡片本身有效)
|
||||
- 开工门:U0(用户 `/iter` 发令)+ 零待裁点(Q1/Q2/Q3 已裁,见 §10;2026-11-01 双审零新增真待裁点)+ grilling 复核门过+ **卡④ 代码波落地后**(卡④ v3.1 现行有效卡、设计线闭合、开工门已裁断销号;本卡浮窗与 HUD 落在卡④ 新建的场景屏上,排期随卡④ 代码波之后,卡片本身有效)
|
||||
|
||||
## 0. 前置依赖与并行性
|
||||
|
||||
- 前置卡④(营地场景图):Esc 浮窗的「返回主菜单」与顶栏 HUD 都落在营地场景屏上;**卡④ 2026-10-18 已回设计段**(美术设计定稿未过设计前置闸)——本卡不可先于卡④重新立卡落地,排期随④之后;本卡自身零美术依赖(零新素材、裁决 9/10 已给全),设计前置检查通过,卡片有效。
|
||||
- **跨卡接口(v1.1 补全)**:①场景屏顶栏位(卡④ T2 预留);②**营地刷新单口**(卡④ T3 定义:各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成)——本卡 HUD 刷新挂该单口,**非已退役的 `refresh_camp`**;③子界面返回钮承诺(卡④ T3——Q1 甲案前提);④卡④终局落点不变量(T0 互证)。
|
||||
- 前置卡④(营地场景图,v3.1 现行有效卡——2026-11-01 双审修订、开工门已裁断销号):Esc 浮窗的「返回主菜单」与顶栏 HUD 都落在卡④ 新建的营地场景屏上;卡④ 设计线已闭合(样张过审 2026-10-31+art-bible v3.31 §6.2)——本卡不可先于卡④ 代码波落地,排期随④ 之后;本卡自身零美术依赖(零新素材、裁决 9/10 已给全),设计前置检查通过,卡片有效。
|
||||
- **跨卡接口(保持既有名,不改名)**:①场景屏顶栏位(卡④ T2 预留;卡④ v3.1 挂接签名=`camp_scene_view.gd set_hud_band()`,「卡⑤ 填值」);②**营地刷新单口**(卡④ T3 定义;卡④ v3.1 定名 `camp_refresh_bus.gd` 的 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`)——本卡 HUD 刷新挂该单口,**非已退役的 `refresh_camp`**;③子界面返回钮承诺(卡④ T3——Q1 甲案前提:五界面各带返回/关闭钮);④卡④终局落点不变量(T0 互证:现役=终局 continue 回主菜单,`main_adventure_flow.gd:123-143` 终局出口 `_begin_session(false)`,行号 T0 复核;若后续改落点为营地则本卡「返回主菜单」动线须补会话收束)。卡④ v3.1 已原样承接上述四项,接口名无改动;场景根句柄名与 `LAYER_CONTRACT` 槽名由卡④ T0 定稿(显式验收点),本卡只消费不改名。
|
||||
- 卡②的退出游戏钮、现役设置面——本批只复用不重做(契约 3)。
|
||||
- 与卡④同批或随后(两卡触碰同一新屏)。**探针入口路径还依赖卡②③链**(v1.1 补明): restructuring 后营地只能经「菜单三钮→进入存档→选档→进档」到达——本卡 V1/V3 探针段隐含依赖该全链在位;若本卡先于卡②③合入,探针段挂起或走中间态断言(仿卡② §9 第 4 条先例)。
|
||||
- **camp 截图/golden 联动(v1.1 补)**:HUD 栏落营地场景屏会改 camp 截图内容——若本批晚于卡④单跑,卡④ 刚重制的 camp 断言基线必再漂移;若同批,卡④ T5 迁移时点须晚于本卡 T2 HUD 落位(排序约束)。本卡 T2 含「HUD 落位后核漂移热区→限 HUD 区显式更新+呈报」条。
|
||||
- 与卡④同批或随后(两卡触碰同一新屏)。**探针入口路径依赖卡②③链**:营地交互重做后营地只能经「菜单三钮→进入存档→选档→进档」到达——本卡 V1/V3 探针段隐含依赖该全链在位;卡②③ 工程波已随迭代 33 合回(待办清单 2026-10-18 条实况),探针段全链在位,无挂起前提。
|
||||
- **多卡共改文件分界(`screen_flow_probe.gd`)**:卡④ T5 改该文件营地旗标语义(:54→新场景根句柄;:53 是菜单行——v1.4 订正)与回退段(:119-125);本卡 T3 扩展该文件 Esc 合成段(现 :153-165 已有「选档语境 Esc 零响应」断言)为营地语境 Esc 浮窗断言段。两段按行域分界,各自改各自段,禁互相覆盖;**分界锚=断言段语义/段名,不锚行号**(一侧插删行会平移另一侧行号,2026-11-01 双审补立);T0 与卡④ 对齐。
|
||||
- **camp 截图/golden 联动(v1.4 改述,原排序约束句废止)**:HUD 栏落营地场景屏会改 camp 截图内容。按迭代 47 执行序(roadmap 迭代总表格内排列顺序=执行顺序——卡④ 整卡先行、卡⑤ 后),卡④ T5 的 camp 断言基线建立在**无 HUD 场景屏**上;本卡 T2 HUD 落位后核漂移热区→限 HUD 区显式更新+呈报(T2 已列该条)。原 v1.3「卡④ T5 迁移时点须晚于本卡 T2 HUD 落位」句在上述执行序下天然不可满足(死信),2026-11-01 用户裁改述如上;现无 camp 逐像素 golden(卡④ 契约 10)。
|
||||
|
||||
## 1. 目标与完成定义
|
||||
|
||||
@@ -21,48 +22,57 @@
|
||||
- 裁决 10「钥石余额:场景**顶部小 HUD 栏**」(用户原话「先按顶部小HUD栏设计」——provisional 措辞留痕)。
|
||||
|
||||
**相对现状,新增了什么**:
|
||||
1. Esc 浮窗(全仓现无任何键盘快捷键处理——从零新建);
|
||||
2. 营地场景顶部小 HUD 栏(钥石余额常驻——现营地钥石徽在 CampOverlay 顶栏,随卡④拆解后由新 HUD 栏承接)。
|
||||
1. Esc 浮窗(产品码现无任何键盘快捷键处理——从零新建);
|
||||
2. 营地场景顶部小 HUD 栏(钥石余额常驻——现营地钥石徽在 CampOverlay 顶栏 `camp_overlay_view.gd:125`,随卡④拆解后由新 HUD 栏承接,落卡④ T2 顶栏预留位)。
|
||||
|
||||
**完成定义**:
|
||||
1. 营地语境按 Esc 唤起浮窗,浮窗有且仅有返回主菜单/设置/退出游戏三项;浮窗的关闭/取消路径按 Q2 裁定落地;
|
||||
2. 「返回主菜单」回主菜单(营地场景屏隐藏+选档层同收+主菜单可见);「设置」开现役设置面(语境分支见契约 3);「退出游戏」接现役退出路径;
|
||||
3. 营地场景顶部小 HUD 栏在位,钥石余额读数=存档单口现值,刷新时机=购买后(挂卡④营地刷新单口)/进档或回营地进入时重读/夹具直写后探针显式触发(v1.1 清单化);
|
||||
3. 营地场景顶部小 HUD 栏在位,钥石余额读数=存档单口现值,刷新时机=购买后(挂卡④ `CampRefreshBus.refresh()` 单口)/进档或回营地进入时重读/夹具直写后探针显式触发;
|
||||
4. 浮窗零动效直开直关(生涯页同款契约);新层入 `LAYER_CONTRACT`;
|
||||
5. 批末重闸按改动域选档全绿;三份 `reports/` 产出物写齐(T4)。
|
||||
|
||||
## 2. 现状事实(2026-10-18 实查;开工日 T0 复核行号)
|
||||
## 2. 现状事实(2026-10-18 实查;2026-10-31 复核行号;2026-11-01 双审全量复核——F4 行号 ±1 漂移订正、F9 补全路径,开工日 T0 再核)
|
||||
|
||||
| # | 事实 | 出处 |
|
||||
|---|---|---|
|
||||
| F1 | **全仓零键盘快捷键处理**:`KEY_ESCAPE`/`ui_cancel`/`ui_accept` 在 `game/` 全目录 grep 零命中(2026-10-18 实查)——Esc 浮窗是从零新建,无旧路径可迁;现成输入合成先例只有鼠标 `Viewport.push_input`(ui_input_probe.gd:51-63/:657-680,headless 实证),键盘合成须 T0 spike | 全仓 grep 实证;`game/smoke/ui_input_probe.gd:51-63` |
|
||||
| F2 | 设置面在役:`settings_overlay` 构建+`closed` 接线;开=`_open_settings`(:1055-1057),关=`_on_settings_closed`(:1060-1063,关后**带 `_start_overlay.visible = true` 硬副作用**——营地语境照抄会在关设置后弹主菜单,须语境分支,见契约 3);`_open_settings`/`_quit_game` 现唯二调用点都是菜单钮 | `main.gd:277-279`/:1055-1057/:1060-1063/:333-334(v1.1 行号订正) |
|
||||
| F3 | 退出游戏在役:`_quit_game`(设置即时落盘后 `get_tree().quit()`;无语义副作用,可原样复用) | `main.gd:500-503` |
|
||||
| F4 | 钥石徽工厂件在役:`UiKit.keystone_badge`(三处消费先例——营地顶栏/生涯页/状态面板;迭代 17 卡③ Q10 甲工厂化)——HUD 栏复用该件,零新素材 | `camp_overlay_view.gd:82`;`career_overlay.gd:54` |
|
||||
| F5 | art-bible §6.2 现载「钥石余额常驻顶栏」——与裁决 10 同向,本批是把该呈现位从 CampOverlay 顶栏迁场景屏 HUD | `design/art/art-bible.md:369` |
|
||||
| F6 | 层序唯一事实源=`main.gd` `LAYER_CONTRACT`;`_apply_layer_contract` 全仓唯一落位口;冒烟 V1d 源码断言判红散落 `move_child` | `main.gd:34-53`/:430-455 |
|
||||
| F7 | 零动效契约先例:生涯页/状态面板「直开直关」——ui_struct_probe 载 `_career_zero_motion_contract`(子树 AnimationPlayer 零命中+视图源码禁动效令牌扫描) | `game/smoke/ui_struct_probe.gd:313-328` |
|
||||
| F8 | 08「六 · Alpha 不含」载「键盘 / 手柄输入(排 Beta)」行(**:192**——:191 是反雪球机制行)——Esc 属用户明示裁决(澄清⑤裁决 9),与该行的关系须同步注记(反哺点),本批不自扩其余键盘面 | `design/gdd/08-Alpha版本标准.md:192`(v1.1 行号订正) |
|
||||
| F9 | **刷新链路实况(v1.1 订正,原结论失实)**:营地侧刷新腿=`camp_overlay.refresh_camp(camp_data())`(CampShopPresenter 各购买口尾与 `_refresh_presentations` 成对调用)——`refresh_camp` 是 CampOverlay 方法,**随卡④拆解退役**;`_refresh_presentations`(main.gd:1293-1298)刷的是战斗侧 HudPresenter+秘宝槽+结算视觉,**营地语境零营地视图触碰**;钥石入账发生在冒险收束、不在营地(存档序列化.md:116)——营地语境无现行入账触发源 | `camp_shop_presenter.gd:85-86`/:93-94 等;`main.gd:1293-1298`;`存档序列化.md:116` |
|
||||
| F10 | 调试入口全局浮层角标在役(LAYER_CONTRACT 末位 float 类,不注册 ModalStack,任何 UI 不遮挡);ModalStack.open 只隐藏登记层 | `main.gd:51-53`/:312-314;`modal_stack.gd:21-30` |
|
||||
| F1 | **产品码零键盘快捷键处理**:`KEY_ESCAPE`/`ui_cancel`/`ui_accept` 在 `game/core/`+`game/presentation/` grep 零命中——Esc 浮窗产品码从零新建,无旧路径可迁。**但探针侧已有键盘合成先例**:`screen_flow_probe.gd:156-160` 用 `InputEventKey`(keycode=`KEY_ESCAPE`)经 `Viewport.push_input(ev, true)` 合成,断言「选档语境 Esc 零响应」(:153-165,卡⑤ 范围外的零实现断言)——键盘事件合成机制已实证,T0 由「从零 spike」改为「复核该先例并迁移到营地语境」。鼠标 `push_input` 先例=`ui_input_probe.gd:84-116`(`InputEventMouseMotion`/`InputEventMouseButton`;原 `game/smoke/` 目录已不存在,全部探针在 `game/probe/`) | `game/probe/screen_flow_probe.gd:153-165`;`game/probe/ui_input_probe.gd:84-116` |
|
||||
| F2 | 设置面在役:开=`_open_settings()`(`main.gd:444` 薄委托→`main_overlay_flow.gd:7-9`:`start_overlay.visible=false`+`ui.modals.flow.open(settings_overlay)`);关=`_on_settings_closed()`(`main.gd:448`→`main_overlay_flow.gd:11-13`:`ui.modals.flow.close`+**`start_overlay.visible = true` 硬副作用**——营地语境照抄会在关设置后弹主菜单,须语境分支,契约 3)。开合走组合根模态编排口 `ui.modals.flow.open/close`;静态承接件是 main 同名函数逐字搬运、main 侧留薄委托,探针 `main.X` 路径零改动。`_open_settings`/`_quit_game` 菜单钮调用点见装配段(T0 复核行号) | `main.gd:444`/:448;`game/presentation/main_overlay_flow.gd:7-13` |
|
||||
| F3 | 退出游戏在役:`_quit_game()`(`settings_store.save_settings()` 后 `get_tree().quit()`;无语义副作用,可原样复用) | `main.gd:143-146` |
|
||||
| F4 | 钥石徽工厂件在役:`UiKit.keystone_badge` 定义 `ui_kit.gd:632`;消费点四处产品码——营地顶栏 `camp_overlay_view.gd:125`/生涯页 `career_overlay.gd:54`/状态面板 `status_panel.gd:32`/选档界面 `save_select_overlay.gd:86`(卡③ 新增),+ `theme_projection_test.gd:853-854` 单测投影断言。HUD 栏复用该件,零新素材 | `game/presentation/views/ui_kit.gd:632`;`camp_overlay_view.gd:125`;`career_overlay.gd:54`;`status_panel.gd:32`;`save_select_overlay.gd:86` |
|
||||
| F5 | art-bible **v3.31** §6.2 现载「钥石余额:常驻画面顶部的一行小 HUD 栏(高 48px,浮层覆盖,不挤压画面)」(:396);camp.md v2.2 §顶栏(:39-41)同述+「刷新入口=营地刷新单口(卡⑤同口挂接)」——与裁决 10 同向,本批把呈现位从 CampOverlay 顶栏迁场景屏 HUD | `design/art/art-bible.md:396`;`design/gdd/ux/camp.md:39-41` |
|
||||
| F6 | 层序唯一事实源=`ui_registry.gd:15-35 LAYER_CONTRACT`(`UiRegistry`;`main.gd:5` 头注自陈界面句柄与层清单归 ui 注册面);全仓唯一落位口=`ui_registry.gd:76 apply_layer_contract(root)`(唯一 `move_child` 点);模态登记册序/树序断言=`system_test.gd:94-106`(V1c 合同树序链)。浮窗新槽入该合同表,禁散落 `move_child` | `game/presentation/ui_registry.gd:15-35`/:76;`game/tests/system_test.gd:94-106` |
|
||||
| F7 | 零动效契约先例:生涯页/状态面板「直开直关」——`ui_struct_probe.gd:379-391 _career_zero_motion_contract`(子树 AnimationPlayer 零命中+视图源码 `create_tween`/`UiKit.motion` 令牌扫描)、:334-341 `_status_zero_motion_contract` 同形 | `game/probe/ui_struct_probe.gd:334-341`/:379-391 |
|
||||
| F8 | 08「六 · Alpha 不含」载「键盘 / 手柄输入(排 Beta)」行(**:193**——:192 是反雪球机制行)——Esc 属用户明示裁决(澄清⑤裁决 9),与该行的关系须同步注记(反哺点),本批不自扩其余键盘面 | `design/gdd/08-Alpha版本标准.md:193` |
|
||||
| F9 | **刷新链路实况**:营地侧刷新腿=`camp_overlay.refresh_camp(camp_data())`(`camp_shop_presenter.gd:82/90/102/114/126/139/151/165` 各写口尾,与 `_refresh_presentations.call()` 成对,实数 T0 复核)——`refresh_camp` 是 CampOverlay 方法,**随卡④拆解退役**;`_refresh_presentations`(`main.gd:628-633`)刷 `HudPresenter.refresh(ui.battle.*)`+`_treasure_ui.refresh_slots()`+`_sync_settlement_visuals()`,仍战斗侧、不刷营地视图(营地购买口尾成对调用它属既有行为,卡④ 契约 4 明令「禁顺手统一」);`camp_shop_presenter.gd:50-53 on_camp_closed()` 关营地亦 `_refresh_presentations.call()`;钥石读数单点=`camp_shop_presenter.gd:62 camp_data()` 的 `meta.meta_state.keystone_balance()`;钥石入账在冒险收束、不在营地(`存档序列化.md`)——营地语境无现行入账触发源 | `game/presentation/camp_shop_presenter.gd:50-53`/:62/:82-83;`main.gd:628-633`;`存档序列化.md` |
|
||||
| F10 | 调试角标:`ui_registry.gd:33-34` 载 `debug_badge` 为 `LAYER_CONTRACT` 末位 `float` 类、不注册 ModalStack;`modal_stack.gd:21-41 open()` 只遍历登记层 `_list` 隐藏上方可见层、不触及 float 类 ⇒ 浮窗开不波及角标节点(结构语义)。**但角标发布态恒隐**:`main.gd:98` `ui.screens.debug_badge.visible = _debug_entry`(缺省 false,迭代 38 卡⑦ 发布态换代),`ui_click_probe.gd:330-333` 断言「设置面开中调试角标不可见(发布态恒隐)」——v1.2「角标恒压浮窗且保持可点/可见」是换代前旧结论,已失实;本批删该运行期断言面(契约 7/T3/V8 同步订正),改以「浮窗登记序+open 只动登记层」结构断言承载;开发期临时启用角标(本地改 `_debug_entry`、不提交)后的浮窗不遮角标观感归用户目检 | `game/presentation/ui_registry.gd:33-34`;`game/presentation/modal_stack.gd:21-41`;`main.gd:98`;`game/probe/ui_click_probe.gd:330-333` |
|
||||
|
||||
## 3. 设计契约(红线,违反 = L3 停机呈报)
|
||||
|
||||
🔴 **契约 1 · 浮窗三项且仅三项**:返回主菜单/设置/退出游戏(裁决 9)。禁加项(禁「继续冒险」类——营地无冒险可继续)、禁减项。浮窗的关闭路径=Q2 裁定项(再按 Esc 关/关闭钮/无关闭三选一),不属「加项」争议。
|
||||
🔴 **契约 1 · 浮窗三项且仅三项**:返回主菜单/设置/退出游戏(裁决 9)。禁加项(禁「继续冒险」类——营地无冒险可继续)、禁减项。浮窗的关闭路径=Q2 裁定项(再按 Esc 关),不属「加项」争议。
|
||||
|
||||
🔴 **契约 2 · Esc 范围=营地语境(Q3 已确认,2026-10-18)**:浮窗只在营地场景图语境唤起(含其子界面开态——行为按 Q1 裁定的甲案:只根态响应)。**禁扩展到战斗/地图/其他屏**(用户 2026-10-18 确认「只在营地语境」;08:192 键盘面仍排 Beta,本批只落 Esc 一项)。
|
||||
🔴 **契约 2 · Esc 范围=营地语境(Q3 已确认,2026-10-18)**:浮窗只在营地场景图语境唤起(含其子界面开态——行为按 Q1 裁定的甲案:只根态响应)。**禁扩展到战斗/地图/其他屏**(用户 2026-10-18 确认「只在营地语境」;08:193 键盘面仍排 Beta,本批只落 Esc 一项)。
|
||||
|
||||
🔴 **契约 3 · 设置与退出本体零重做、接线允许语境分支(v1.1 放宽)**:设置面本体与退出行为零改(F2/F3);**开合接线允许按语境分支**——现役 `_on_settings_closed` 带「回开始层」硬副作用,营地语境须分支为「关设置回浮窗不回主菜单」;正解=浮窗登记于设置层之下,`_open_modal(settings_overlay)` 自动隐藏浮窗、关闭自动恢复(既有栈语义);`_quit_game` 无语义副作用,原样复用。
|
||||
🔴 **契约 3 · 设置与退出本体零重做、接线允许语境分支**:设置面本体与退出行为零改(F2/F3);**开合接线允许按语境分支**——现役 `main_overlay_flow.gd:11-13 _on_settings_closed` 带「回开始层」硬副作用(`start_overlay.visible = true`),营地语境须分支为「关设置回浮窗不回主菜单」。栈语义正解(F6/modal_stack.gd:21-41):浮窗登记于设置层**之下**(合同表槽位在营地层与 `settings_overlay` 之间,T0 与卡④ 对齐最终槽名),`ui.modals.flow.open(settings_overlay)` 时设置层绘制在浮窗之上遮挡之(open 只隐藏登记序在设置层**之上**的层,浮窗在下不被隐藏),`close` 后遮挡解除、浮窗自然重现——「关设置回浮窗」由栈语义保证;**语境分支点=`_on_settings_closed` 的 `start_overlay.visible = true` 硬副作用**(菜单路径保留、营地浮窗路径跳过),落 `main_overlay_flow.gd._on_settings_closed`(改)。**语境分支谓词(2026-11-01 双审钉死)=`camp_esc_overlay.visible`**(谁开的设置谁收:浮窗开态下关设置必回浮窗;菜单路径浮窗必未开);与 Esc 守卫谓词(契约 9①②,按 ModalStack 现开集合判)**分立**——禁复用同一谓词。`_quit_game`(`main.gd:143`)无语义副作用,原样复用。
|
||||
|
||||
🔴 **契约 4 · 返回主菜单动线**:营地场景屏隐藏+**选档层同收**(卡④ T3 口径)+开始层恢复;营地语境⇔闲时会话(无冒险会话——卡④ 契约 6「冒险进行中不开营地」+现役终局回菜单并 `_begin_session(false)` 收束推得,v1.1 前提成文),故动线本身不含会话收束;**回主菜单后菜单=卡②三钮、断点在档不在菜单露面**(禁实现者自作主张加「继续冒险」钮——那正是契约 1 在浮窗侧禁的);营地每笔消费即时写盘(存档序列化.md:121),回主菜单不写档也无损。
|
||||
🔴 **契约 4 · 返回主菜单动线**:**动线首步=close 浮窗**(`ui.modals.flow.close(camp_esc_overlay)`——浮窗是模态层,与屏壳可见性无关,缺此步浮窗残留主菜单上方;v1.4 补,V3 断言含浮窗 closed);营地场景屏隐藏+**选档层同收**(卡④ T3 口径)+开始层恢复;营地语境⇔闲时会话(无冒险会话——卡④ 契约 6「冒险进行中不开营地」+现役终局回菜单并 `_begin_session(false)` 收束推得),故动线本身不含会话收束;**回主菜单后菜单=卡②三钮、断点在档不在菜单露面**(禁实现者自作主张加「继续冒险」钮——那正是契约 1 在浮窗侧禁的);营地每笔消费即时写盘(`design/gdd/systems/表现与支撑/存档序列化.md`,行号 T0 复核),回主菜单不写档也无损。
|
||||
|
||||
🔴 **契约 5 · 顶栏 HUD 单口读数+刷新挂卡④单口(v1.1 订正)**:钥石余额只经 MetaProgression/SaveManager 访问器单口读(禁第二账本、禁视图自算);**刷新挂卡④定义的营地刷新单口**(非已退役 `refresh_camp`——F9);刷新时机清单=购买后/进档或回营地进入时重读/夹具直写后探针显式触发(T2 落定)。
|
||||
🔴 **契约 5 · 顶栏 HUD 单口读数+刷新挂卡④单口**:钥石余额只经 MetaProgression/SaveManager 访问器单口读(`camp_shop_presenter.gd:62 camp_data()` 的 `keystone_balance()`;禁第二账本、禁视图自算);**刷新挂卡④定义的营地刷新单口**(卡④ v3.1 定名 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`,非已退役 `refresh_camp`——F9);刷新时机清单=购买后(挂单口)/进档或回营地进入时重读/夹具直写后探针显式触发(T2 落定)。**「进档/回营地进入时重读」的触发主体(v1.4 钉死)=组合根进档动线尾(营地开层同口)显式调 `CampRefreshBus.refresh(camp_data())` 一闸**——禁 band `_ready` 自刷或自持第二入口(保 V6「显式触发才变」单口调用记录锚)。
|
||||
|
||||
🔴 **契约 6 · 零动效**:浮窗直开直关,子树零 AnimationPlayer、源码禁动效令牌(生涯页同款契约,F7);减动效设置项不新增(在役项沿用)。
|
||||
🔴 **契约 6 · 零动效**:浮窗直开直关,子树零 AnimationPlayer、源码禁 `create_tween`/`UiKit.motion` 令牌(生涯页同款契约,F7);减动效设置项不新增(在役项沿用)。
|
||||
|
||||
🔴 **契约 7 · 层序纪律+遮挡结论(v1.1 落结论)**:浮窗入 `LAYER_CONTRACT`(改层序只改合同表);禁散落 `move_child`。**与调试角标遮挡的结论(v1.1 补,既有纪律已定论、无需用户裁)**:debug_badge 是末位 float 类不注册 ModalStack,ModalStack.open 只隐藏登记层⇒角标**恒压浮窗且保持可点**(树序末位=最顶绘制序,全仓无 `debug_badge.disabled` 赋值)——合同内照此表达。另写明一条栈语义防误触 L3:浮窗开会隐藏登记序在其上的已开层(如调试浮窗体 debug_overlay),关闭恢复——属既有栈语义非新决策。
|
||||
🔴 **契约 7 · 层序纪律+遮挡结论(订正)**:浮窗入 `ui_registry.gd LAYER_CONTRACT`(改层序只改合同表;唯一落位口 `apply_layer_contract()`——F6);禁散落 `move_child`。**与调试角标遮挡的结论**:`debug_badge` 是末位 `float` 类、不注册 ModalStack,`ModalStack.open` 只隐藏登记层 ⇒ 浮窗开不波及角标节点(结构语义);但角标**发布态恒隐**(F10,`main.gd:98` `_debug_entry` 缺省 false),故「角标恒压浮窗且保持可点/可见」不是本批可跑断言面——删该运行期断言,以「浮窗登记序+open 只动登记层」结构断言承载,开发期临时启用角标后的浮窗不遮角标观感归用户目检。另写明一条栈语义防误触 L3:浮窗开会隐藏登记序在其上的已开层(如 debug_overlay),关闭恢复——属既有栈语义非新决策。**浮窗句柄寻址(v1.5 钉死)=`ui.modals.camp.esc_overlay` 二层**(营地子容器,卡⑥ 建件;`ui.modals.flow.open/close` 调用形态不变——flow 是全局调度器、非句柄册成员)。
|
||||
|
||||
🔴 **契约 8 · provisional 口径留痕**:裁决 10「先按顶部小HUD栏设计」的「先」字留痕——HUD 栏形态按最小集落地(只承载钥石余额),扩项=新裁点。
|
||||
🔴 **契约 8 · provisional 口径留痕**:裁决 10「先按顶部小HUD栏设计」的「先」字留痕——HUD 栏形态按最小集落地(只承载钥石余额),扩项=新裁点。
|
||||
|
||||
🔴 **契约 9 · Esc 输入语义四态与接线定稿(v1.4 新立,2026-11-01 用户裁采纳双审推荐)**:Esc 路由按**四级优先序**,判据单点=ModalStack 登记册现开集合(禁手枚名单——设置面/ConfirmDialog/五子界面自然全被覆盖):
|
||||
①**除浮窗外任一登记模态开态 → 无反馈**(「设置开在浮窗之上」态被本条覆盖=无反馈,关设置后浮窗自然重现——契约 3 栈语义;旧三态表「隔设置层误关不可见浮窗」歧义就此消解);
|
||||
②**浮窗开态 → `close(camp_esc_overlay)`**(同键唤起/关闭单义切换,Q2 甲);
|
||||
③**营地语境(`is_camp_context()`:营地场景屏 visible)→ `open(camp_esc_overlay)`**;
|
||||
④**非营地语境 → 无反馈**(现役「选档语境 Esc 零响应」语义保持,契约 2)。
|
||||
**接线定稿(同日裁,出 §9 白名单)**:事件驱动 `_unhandled_input`,键值判定 `KEY_ESCAPE`(配 physical_keycode 桌面惯例);**禁 Input 单例轮询**(`Viewport.push_input` 合成链不更新 `Input.is_action_pressed` 动作态——合成探针必然测不到轮询路径);**不挂 ui_cancel**(Beta 手柄面往 ui_cancel 挂键会致语义漂移;用户裁决原话「ESC键」;08:193 键盘面只加 KEY_ESCAPE 键值判定、不新增 InputMap action)。**触发沿=pressed 且非 echo**、忽略释放沿(真实键盘长按 echo 连发禁翻转浮窗;V1 补合成 echo 断言零响应)。
|
||||
|
||||
**拆分边界纪律适用性判定(req-card 第 15 节/code-conventions §1.1)**:本卡=**新增功能批**——新增 Esc 浮窗视图、营地顶栏 HUD 栏、Esc 键盘输入接线三类件,其余为存量文件接线改造;无「拆分存量单元/收敛/重构」动作,`camp_overlay_view.gd` 四柜台拆解退役属卡④ 职责(本卡不改该文件)。按 code-conventions §1.1 拆分判据五条,本卡不触发拆分/收敛/重构类,故不在设计契约区写拆分红线条款,仅在此写明判定理由。同理 req-card 第 13 节「禁为机检文本保留无效成员」(重构类卡必填)不适用;新增件类的「机检预算互斥=上游缺陷停卡退回写卡段」(第 9/14 节)已写入 §8 L3 与「实现规范预算」节。
|
||||
|
||||
## 4. 范围边界
|
||||
|
||||
@@ -70,116 +80,225 @@
|
||||
|
||||
**不做**(明示去向):
|
||||
- 营地场景图本体 → 卡④(本批只在其顶栏位落 HUD+挂刷新单口);
|
||||
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①;
|
||||
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①(工程波已随迭代 33 合回);
|
||||
- 其余键盘快捷键(任意键关闭浮窗/手柄/战斗内 Esc) → 用户未裁,禁自扩(契约 2);
|
||||
- 设置面/退出路径本体改动 → 无(契约 3);
|
||||
- HUD 栏扩项(冒险天数/种子等) → 契约 8,扩项另裁。
|
||||
- HUD 栏扩项(冒险天数/种子等) → 契约 8,扩项另裁;
|
||||
- 不新建 camp golden(卡④ 契约 10:现无 camp 逐像素 golden,camp 验收=shot_probe 出图+shot_checker 语义断言)。
|
||||
|
||||
## 5. 关联文档同步面
|
||||
|
||||
> **v1.3 口径**:本批禁写 `design/` 整目录与根规则文件,唯一可写目录 = `reports/`;下表一律执行为列进反哺点清单。
|
||||
> **现行口径**:实现批禁写 `design/` 整目录与根规则文件、两份根流程清单与 `game/tests/README.md`,唯一可写目录=`reports/`(+`game/` 实施本体);下表一律执行为列进 `reports/iter<N>-反哺点-<日期>.md` 反哺点清单(义务格全为「反哺点 · 列清单」类,禁旧「随批」措辞)。待办清单与体验验证清单已迁仓库根(原 `design/gdd/06-*`、`07-*` 路径已不存在)。
|
||||
|
||||
| 文档 | 关联点 | 同步义务 |
|
||||
|---|---|---|
|
||||
| `design/gdd/08-Alpha版本标准.md` | :192「键盘 / 手柄输入(排 Beta)」行——Esc 营地浮窗已落地(用户明示裁决,澄清⑤裁决 9),须加注防「Beta 行=本批违例」误读 | 反哺点 · 行内加注(v1.1 行号订正 :192) |
|
||||
| `design/art/art-bible.md` | §6.2「钥石余额常驻顶栏」呈现位从 CampOverlay 顶栏迁场景屏 HUD(:369 述) | 反哺点 · 随卡④ §6.2 改版一并落 |
|
||||
| `design/gdd/ux/camp.md` | 顶栏铭牌/钥石徽记述(:14-20)随 HUD 栏改挂 | 反哺点 · 随 camp.md 改版落 |
|
||||
| `design/gdd/06-待办清单.md` | 本卡登记条 | 反哺点 · 列清单 |
|
||||
| `design/gdd/07-体验验证清单.md` | 新增目检条(Esc 浮窗三动线/HUD 余额观感)——登记不阻塞 | 反哺点 · 列清单 |
|
||||
| `roadmap.md` | 迭代行编入/状态刷新 | 反哺点 · 列清单 |
|
||||
| `game/presentation/*`(浮窗视图+接线)、`game/smoke/*` | 实现与断言本体 | 实施本体(可写) |
|
||||
| `design/gdd/08-Alpha版本标准.md`(v1.13) | :193「键盘 / 手柄输入(排 Beta)」行——Esc 营地浮窗已落地(用户明示裁决,澄清⑤裁决 9),须加注防「Beta 行=本批违例」误读 | 反哺点 · 列清单(行内加注) |
|
||||
| `design/art/art-bible.md`(v3.31) | §6.2「钥石余额:常驻画面顶部的一行小 HUD 栏」(:396)呈现位从 CampOverlay 顶栏迁场景屏 HUD | 反哺点 · 列清单(权威面零直改,过用户裁决后归文档批) |
|
||||
| `design/gdd/ux/camp.md`(v2.2) | §顶栏(:39-41)「钥石余额常驻顶部小 HUD 栏、刷新入口=营地刷新单口(卡⑤同口挂接)」实装状态回填 | 反哺点 · 列清单 |
|
||||
| `待办清单.md`(仓库根) | 本卡登记条(五卡总条,:447 起——原引 438-449 行号漂移,v1.4 订正)状态推进 | 反哺点 · 列清单(实现批禁写待办清单) |
|
||||
| `体验验证清单.md`(仓库根) | 新增目检条(Esc 浮窗三动线/HUD 余额观感/浮窗视觉面)——登记不阻塞 | 反哺点 · 列清单(实现批禁写体验验证清单,入册条目由文档批落) |
|
||||
| `roadmap.md`(仓库根) | 迭代行编入/状态刷新 | 反哺点 · 列清单(实现批禁写 roadmap) |
|
||||
| `game/tests/README.md` | 能力行入表(§7 对照表「能力行」列定名) | **已入表**(旅程段六,本卡两条新增能力行在役)——实现批只核对名实一致,禁写 |
|
||||
| `game/presentation/*`(浮窗视图/HUD 栏/接线/注册面)、`game/probe/*` | 实现与断言本体 | 实施本体(可写) |
|
||||
|
||||
## 卡前·文件结构与职责(T0 前)
|
||||
|
||||
定义 T 卡前先列全本批新建/修改文件,一文件一职责。**每个文件行标「行为改动/非行为改动」并指向 §7 对照表行号;「落位」列与「落位与可复用性预检」节互指**(标「新建」的必须能在预检节指到不能复用的理由与唯一落点核查)。行号为开工日 T0 复核对象。
|
||||
|
||||
| 文件 | 职责 | 改动类型 | 落位 | 对照表行 |
|
||||
|---|---|---|---|---|
|
||||
| `game/presentation/views/camp_esc_overlay.gd` | Esc 浮窗视图:`UiKit.modal_shell` 模态壳+三钮(返回主菜单/设置/退出游戏,退出用 `UiKit.danger_button`)+Q2 再按 Esc 关窗;零新素材 | 行为改动 | 新建 | V1/V2/V5/B1 |
|
||||
| `game/presentation/views/camp_hud_band.gd` | 营地顶栏小 HUD 栏:承载 `UiKit.keystone_badge`(钥石余额单口读数);挂接卡④ `CampRefreshBus.refresh()` 刷新 | 行为改动 | 新建 | V6/B2 |
|
||||
| `game/presentation/main_esc_flow.gd` | 组合根 Esc 流程承接件:键盘输入路由+营地语境判据+Q2 再按关窗+三出口动线(返回主菜单/设置/退出);静态承接件,main 侧留同名薄委托 | 行为改动 | 新建 | V1/V3/B1/B3 |
|
||||
| `game/presentation/main.gd` | 组合根:Esc 输入入口+`main_esc_flow.gd` 同名薄委托+返回主菜单动线接线 | 行为改动 | 复用既有(改) | V1/V3/B3 |
|
||||
| `game/presentation/ui_registry.gd` | `LAYER_CONTRACT` 加 `camp_esc_overlay` 槽(登记于营地层与 `settings_overlay` 之间,契约 3 正解)+`node()` 寻址(`camp.*` 二层解析由卡⑥ 建件承担,本卡只消费) | 行为改动 | 复用既有(改) | V8/B1 |
|
||||
| `game/presentation/main_overlay_flow.gd` | `_on_settings_closed` 语境分支:营地浮窗路径关设置回浮窗、不回主菜单(契约 3;谓词=camp_esc_overlay.visible) | 行为改动 | 复用既有(改) | V4/B3 |
|
||||
| `game/presentation/ui_modals.gd` | 本卡零句柄新增(浮窗句柄落 `ui_camp_modals.gd` 子容器——卡⑥ 前置建件,2026-11-01 用户裁);类变量 14 预期不升(S13 触面消除,见「实现规范预算·存量触面一查」) | 非行为改动(卡⑤ 段零改) | 复用既有 | V8/B1 |
|
||||
| `game/presentation/ui_camp_modals.gd`(卡⑥ 新建) | 营地域句柄子容器:本卡 T1 落第六枚句柄 `esc_overlay`(寻址 `ui.modals.camp.esc_overlay` 二层;卡④ T3 已落五枚) | 行为改动 | 卡⑥ 新建(跨卡共改) | V8/B1 |
|
||||
| `game/presentation/main_ui_build.gd` | 浮窗实例化装配点:`.new()`+装配尾 `apply_layer_contract(root)`(先例 :105/:121/:242;S13 触面) | 行为改动 | 复用既有(改) | V8/B1 |
|
||||
| `game/presentation/views/camp_scene_view.gd`(卡④ 新建) | 顶栏预留位 `set_hud_band()` 填 `CampHudBand` 实例(卡④ T2 跨卡接口①「卡⑤ 填值」);本卡只填值、不改场景图铺底/命中区逻辑 | 行为改动 | 卡④ 新建(跨卡共改,仅顶栏填值) | V6/B2 |
|
||||
| `game/probe/screen_flow_probe.gd` | 探针宿主:扩展现 :153-165 Esc 合成段为营地语境浮窗断言+三动线+Q2 关窗+HUD 余额读数;与卡④ T5 营地键段按行域分界(§0) | 非行为改动(测试面) | 复用既有(改) | V1/V3/V4/V6 |
|
||||
| `game/probe/ui_struct_probe.gd` | 浮窗三钮结构断言+零动效契约段(仿 career :379-391)+顶栏位/登记序结构断言 | 非行为改动(测试面) | 复用既有(改) | V2/V7/V8 |
|
||||
| `game/tests/README.md` | 能力行入表(四列:能力|系统|真实入口|代表用例) | 非行为改动(文档,写卡段) | 主 Agent 统一收口 | 全表能力行 |
|
||||
| `reports/iter<N>-实现报告-<日期>.md`/`reports/iter<N>-反哺点-<日期>.md`/`reports/iter<N>-验收审计-<日期>.md` | T4 三份产出物 | 非行为改动(过程件) | 新建 | T4 |
|
||||
|
||||
## 落位与可复用性预检
|
||||
|
||||
定义 T 卡前,对本批每个**新增文件/新增函数/新增数据件**过三问(复用面/唯一面/分层与交互面),与「卡前·文件结构与职责」互指。生效=2026-10-21 用户立规;本卡虽文件名日期 2026-10-18,经 2026-10-31 用户明令补充为现行有效卡,按现行规则补齐。
|
||||
|
||||
### 新增件三问
|
||||
|
||||
| 新件 | 复用面(grep 同职责实现) | 唯一面(grep 同名同义标识符) | 分层与交互面(调用路径+跨层出口) |
|
||||
|---|---|---|---|
|
||||
| `camp_esc_overlay.gd` | 盘上视图件=`camp_overlay_view.gd`(CampOverlay 四柜台,随卡④ 形态退役、反参照禁复用)、`settings_overlay.gd`/`career_overlay.gd`(各有专职、无三钮 Esc 浮窗同职责实现)、`ui_kit.gd modal_shell`(工厂只产 dim+center+panel+VBox、不产完整浮窗)。grep `camp_esc`/`esc_overlay` 盘上无同职责实现 → 不能复用,须新建视图件;模态壳/按钮复用 `UiKit.modal_shell`(`ui_kit.gd:486`)/`UiKit.danger_button`(:699),零新素材零新色值 | grep `camp_esc_overlay`/`EscOverlay` 盘上无第二处;三钮文案「返回主菜单/设置/退出游戏」只此一处定义,禁在探针/T 卡各写一份 | 呈现层视图,零 Core 写调用;三钮 `pressed` → 组合根 `main_esc_flow.gd` → 现役动线(`_quit_game`/`ui.modals.flow.open(settings_overlay)`/返回主菜单);Q2 再按 Esc 关窗由组合根路由,视图只发 `closed` 信号 |
|
||||
| `camp_hud_band.gd` | 盘上钥石徽消费面四处(F4),但**无「顶栏 HUD 栏」独立视图件**——现钥石徽直接挂 CampOverlay 顶栏(`camp_overlay_view.gd:125`),随卡④ 拆解退役;新 HUD 栏须独立承载读数+挂接刷新单口(接收推送,非信号订阅),职责不同 → 不能复用,须新建 | grep `camp_hud_band`/`CampHudBand`/`hud_band` 盘上无第二处;余额读数只经 `camp_data()` 单口(F9),禁视图自算 | 呈现层视图;`UiKit.keystone_badge`(`ui_kit.gd:632`)承载显示;挂接卡④ `CampRefreshBus.refresh(camp_data)` 单口刷新(跨卡接口②);经卡④ `camp_scene_view.gd set_hud_band()` 顶栏预留位挂入(跨卡接口①);零 Core 写调用 |
|
||||
| `main_esc_flow.gd` | 盘上组合根承接件=`main_overlay_flow.gd`(设置/状态/生涯/选档/图例/钱包六类覆盖层开合与数据投喂)、`main_adventure_flow.gd`、`main_debug_flow.gd`。**无「键盘输入路由+Esc 三出口动线」同职责实现**;并入 `main_overlay_flow.gd` 会使其承载第二变化原因(开合数据投喂 vs 键盘输入交互),且该文件已 6 类开合 → 不能复用,须新建单一职责承接件;`main.gd` 留同名薄委托(与现行拆件模式一致,探针 `main.X` 路径零改动) | grep `main_esc_flow`/`_on_esc`/`EscFlow` 盘上无第二处;营地语境判据只此一处定义(营地场景屏 visible 且无营地子模态开态),禁散落 | 组合根拆件(静态、零成员态,仿 `main_overlay_flow.gd`);键盘输入 → 营地语境判据 → 浮窗 `ui.modals.flow.open/close`(模态栈单口);三出口 → 现役动线;返回主菜单 → 营地隐+选档层同收+开始层恢复(卡④ T3 同口径);Core 零 UI 不破 |
|
||||
|
||||
### 非新增件说明
|
||||
|
||||
- `main.gd`/`ui_registry.gd`/`main_overlay_flow.gd`/`camp_scene_view.gd`(卡④ 新建):存量或邻卡文件改造,不新增本卡文件;公开方法/成员预算见「实现规范预算」存量触面一查。
|
||||
- `game/probe/screen_flow_probe.gd`/`ui_struct_probe.gd`:复用既有探针宿主(`screen_flow_probe` 已在 `tools/probe_gate.sh:142-146` 登记、零登记成本;本卡 T3 不另起新文件),只加断言段。
|
||||
- **数据件/RNG/Core**:本卡纯呈现层+输入接线,零玩法数值、无新增 `data/tables/` 表(钥石余额读数经既有 `camp_data()` 单口);数值单一事实源 `data/tables/` 不被触碰;RNG 零新增(RNG 单点 RngService 不被触碰);Core 零 UI 依赖不因新增浮窗/输入接线绕过。
|
||||
- **浮窗新槽落点唯一**:`camp_esc_overlay` 只在 `ui_registry.gd LAYER_CONTRACT` 登记一次、`node()` 寻址一次;禁在探针/T 卡另写层序字面量。
|
||||
|
||||
## 实现规范预算
|
||||
|
||||
定义接口块/文件结构图前,对本批每个**新增文件**对照 gdstyle 默认阈值做预算,与接口块及「卡前·文件结构与职责」互指。**生效说明**:规范写「生效=文件名日期 ≥2026-10-27,此前卡片属历史留档不回头改」——本卡经 2026-10-31 用户明令补充为现行有效卡,按现行规则补齐,不援引「不回头改」跳过。gdstyle v0.4.0 默认阈值:**公开方法 ≤20、类变量 ≤15、单函数分支 ≤8、返回 ≤6**(阈值取工具默认,改阈值=基线口径变须在本批重生成)。
|
||||
|
||||
### 新件三查
|
||||
|
||||
| 触面 | ①公开方法数 | ②成员变量数 | ③迁移函数对账 | 结论 |
|
||||
|---|---|---|---|---|
|
||||
| `camp_esc_overlay.gd` | 预期 ≤6:`setup_buttons()`/`set_close_path()`/`bind_signals()`/`_on_pressed(key: String)` 等,远低 ≤20 | 预期 ≤8:三钮句柄+modal_shell 句柄+`closed` 信号,低 ≤15 | 无自存量文件迁入函数 | 三查通过;T0 实测实数回填,超阈值即拆件或砍面(砍面=退设计段裁职责) |
|
||||
| `camp_hud_band.gd` | 预期 ≤4:`bind_refresh_bus()`/`set_balance()`/`refresh()`,远低 ≤20 | 预期 ≤4:`keystone_badge` 句柄+刷新单口句柄,低 ≤15 | 无迁入函数 | 三查通过;T0 实测实数回填 |
|
||||
| `main_esc_flow.gd` | 预期 ≤7:`on_esc_input()`/`is_camp_context()`/`open_overlay()`/`close_overlay()`/`_on_return_to_menu()`/`_on_settings()`/`_on_quit()`,远低 ≤20 | 预期 0(静态承接件、零成员态,仿 `main_overlay_flow.gd`) | 无迁入函数(新写,不搬存量函数) | 三查通过;T0 实测实数回填 |
|
||||
|
||||
### 存量触面一查
|
||||
|
||||
本卡触碰存量文件:`main.gd`/`ui_registry.gd`/`ui_modals.gd`/`main_ui_build.gd`/`main_overlay_flow.gd`/`camp_scene_view.gd`(卡④ 新建)/`screen_flow_probe.gd`/`ui_struct_probe.gd`。**T0 读数步骤写明「S13 键较 `tools/gdstyle_baseline.txt` 登记值只降不升」的预期与达成手段**:`main.gd` 组合根新增 Esc 输入入口与薄委托(不引入重复 load/循环内 await/循环内分配等 S13 违规类型,键只降不升);`ui_registry.gd` 合同表加一槽、`node()` 加一寻址分支(不新增公开方法面);`ui_modals.gd` 零句柄新增(浮窗句柄落 `ui_camp_modals.gd` 子容器,类变量 14 预期——v1.4「14→15 恰贴」句作废:该算术只算本卡 +1、未算卡④ 同批净+4,两卡合计 19>15,2026-11-01 停机呈报裁决改子容器);`ui_camp_modals.gd`(卡⑥ 建件)本卡落第六枚句柄(类变量 5→6);`main_ui_build.gd` 加浮窗实例化与装配(方法面微增,T0 实测对账);`main_overlay_flow.gd` `_on_settings_closed` 加语境分支(单函数分支数仍 ≤8、返回 ≤6);`camp_scene_view.gd` 只填 `set_hud_band()` 顶栏位;探针改接=加断言段、不新增扫描面键。任何 S13 键被迫上升=§8 L3 停卡。**`main.gd` 为组合根架构先例,其公开方法基数不在本卡新件三查面内**(第 14 节三查只对新增文件)。
|
||||
|
||||
### 指标例外通道
|
||||
|
||||
现预算内,无需例外。若三新件实测超默认阈值,或组合根薄委托致 S13 键上升,设「指标例外申报」节——键名+理由+用户特批落基线;未申报的超预算面进实现段=停卡退回写卡段(写进 §8 L3)。
|
||||
|
||||
## 6. 任务卡
|
||||
|
||||
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。
|
||||
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。步骤用 `- [ ]` 复选框记步,一步=一个动作+一个可核查结果;每卡声明「取用/产出」接口块,后卡引用的名字与早卡定义逐字一致;禁占位待定句式(不决定任何事的行不留)。
|
||||
|
||||
### T0 事实坐实与跨卡对齐(≈0.5–1d)
|
||||
|
||||
- 复核 §2 行号;确认卡④场景屏顶栏预留位接口+营地刷新单口签名(跨卡);
|
||||
- **Esc 输入合成 spike**(v1.1 补):headless 下键盘事件合成机制验证(现成先例只有鼠标 `Viewport.push_input`——F1);与 §9 第 1 条接线方式选型联动(InputMap action+轮询路线与合成探针不兼容,选型时一并定);
|
||||
- Q1 子界面行为、Q2 关闭路径、Q3 范围确认裁定执行;
|
||||
- 与卡④ T0 互证终局落点不变量(契约 4 前提);探针入口路径依赖卡②③链的时点确认(§0)。
|
||||
- 取用:待办清单五卡总条实况(卡④ v3.1 现行、卡②③ 迭代 33 合回)、§0 跨卡接口、卡④ v3.1 §0.5/T2/T3、`game/tests/README.md` 能力表。
|
||||
- [ ] 复核 §2 F1–F10 全部 `file:line` 行号;漂移就地订正、订正不了的写明「开工日 T0 复核」,不硬编旧行号。
|
||||
- [ ] 与卡④ 对齐三项接口:①顶栏预留位 `camp_scene_view.gd set_hud_band()` 填值签名;②营地刷新单口 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`;③终局落点不变量(现役=终局 continue 回主菜单,若改落点为营地则本卡返回动线补 `_begin_session(false)`)——接口名保持既有,不改名;与卡④ 确认 `screen_flow_probe.gd` 行域分界(§0)。
|
||||
- [ ] **Esc 输入合成先例复核**:读 `game/probe/screen_flow_probe.gd:153-165`(`InputEventKey`+`Viewport.push_input` 合成 Esc、断言选档语境零响应),确认该机制可迁移到营地语境;接线方式已定稿(契约 9——事件驱动 `_unhandled_input`+`KEY_ESCAPE`,2026-11-01 裁),T0 复核合成链可达 unhandled 段(push_input 不更新 Input 单例动作态——禁轮询路线的实据)并回写文件结构图接线落点。
|
||||
- [ ] Q1/Q2/Q3 裁定执行确认(甲/甲/甲,见 §10);开工门核:U0 发令、grilling 复核门过、卡④ 代码波状态。
|
||||
- [ ] 跑 `bash tools/static_scan.sh` 开发期局部读数(gdstyle 键=S13,闸件 `tools/gdstyle_gate.py`——原 `tools/gdstyle.sh` 不存在,v1.4 订正),记录三新件预算实数与存量触面 S13 基线键(预期只降不升);本步最窄确认,不构成验收。
|
||||
- 产出:基线 commit、三新件接口块定稿(签名/取值)、S13 读数、跨卡接口核对表、Esc 合成先例复核结论;后续卡只按本卡契约施工。
|
||||
|
||||
### T1 Esc 浮窗(≈1–1.5d)
|
||||
### T1 Esc 浮窗视图与键盘接线(≈1–1.5d)
|
||||
|
||||
- 浮窗视图:模态壳(`UiKit.modal_shell` 先例——该工厂只产 dim+center+panel+VBox、无内置关闭件,关闭件按 Q2 裁定)+三钮(返回主菜单/设置/退出游戏);危险钮形制用于退出(`UiKit.danger_button` 先例);零新素材零新色值;
|
||||
- 接线:返回主菜单→营地场景屏隐藏+选档层同收+开始层恢复(卡④动线同口);设置→`_open_settings`(**语境分支**:浮窗登记于设置层之下,关设置回浮窗——契约 3);退出→`_quit_game`;
|
||||
- **营地语境判据(v1.1 补)**:判据=营地场景屏 visible(根态与子界面开态下皆真——子界面是模态叠加非熄屏;screen_flow_probe 营地旗标先例 :53 可迁移复用);Q1 裁甲则判据加「无营地子模态开态」;调试浮窗开态不影响判据(全局浮层、营地屏仍可见);Q1 裁后回写契约 2 消歧;
|
||||
- 层序入 `LAYER_CONTRACT`(与调试角标遮挡按契约 7 结论表达);零动效(契约 6);
|
||||
- Q2 关闭路径接线(再按 Esc 关/关闭钮/无关闭,按裁定)。
|
||||
- 取用:T0 三新件接口块、Esc 合成先例复核结论、`ui_kit.gd:486 modal_shell`/:699 `danger_button`/:632 `keystone_badge`、`ui_registry.gd:15-35 LAYER_CONTRACT`。
|
||||
- [ ] 在 `camp_esc_overlay.gd` 实现 `setup_buttons()`:`UiKit.modal_shell`(`ui_kit.gd:486`,只产 dim+center+panel+VBox、无内置关闭件)+三钮(返回主菜单/设置/退出游戏,退出用 `UiKit.danger_button` :699);零新素材零新色值。
|
||||
- [ ] 在 `camp_esc_overlay.gd` 实现 `set_close_path()`/`bind_signals()`:Q2 裁甲=再按 Esc 关窗(同键唤起/关闭单义切换),关闭由组合根路由、视图只发 `closed` 信号;三钮 `pressed` 外发不内含动线。
|
||||
- [ ] 在 `main_esc_flow.gd` 实现 `is_camp_context() -> bool`:判据=营地场景屏 visible(子界面是模态叠加非熄屏;复用 `screen_flow_probe.gd:54` 营地旗标先例——:53 是菜单行、:54 才是营地旗标,v1.4 订正);「子界面开态不唤浮窗」(Q1 甲)由契约 9① 现开集合判据承载,不并入本谓词;调试浮窗开态不影响判据(全局浮层、营地屏仍可见)。
|
||||
- [ ] 在 `main_esc_flow.gd` 实现 `on_esc_input(ev: InputEvent) -> void`/`open_overlay() -> void`/`close_overlay() -> void`:按**契约 9 四态优先序**路由(①除浮窗外任一登记模态开→无反馈②浮窗开→close③营地语境→open④非营地语境→无反馈),判据单点=ModalStack 登记册现开集合、禁手枚名单;接线定稿=事件驱动 `_unhandled_input`+`KEY_ESCAPE`(physical_keycode)、禁 Input 单例轮询、不挂 ui_cancel、pressed 且非 echo(契约 9 接线定稿 2026-11-01 已裁,不再 T0 选型)。
|
||||
- [ ] 在 `ui_registry.gd` `LAYER_CONTRACT` 加 `camp_esc_overlay` 槽(位于营地层与 `settings_overlay` 之间,契约 3 登记序正解)+`node()` 寻址;句柄落 `ui_camp_modals.gd` 子容器第六枚 `esc_overlay`(卡⑥ 前置建件,寻址 `ui.modals.camp.esc_overlay` 二层)——禁平铺回 `ui_modals.gd`(S13 上限,2026-11-01 用户裁);禁散落 `move_child`(F6)。
|
||||
- [ ] 在 `main.gd` 加 Esc 输入入口(`_unhandled_input`)与 `main_esc_flow.gd` 同名薄委托(探针 `main.X` 路径零改动);`main.gd` 的 `_unhandled_input` 将是产品码首个键盘入口——`main_esc_flow.gd` 头注自陈此身份(2026-11-01 双审注)。
|
||||
- [ ] 零动效(契约 6):浮窗子树零 AnimationPlayer、源码禁 `create_tween`/`UiKit.motion` 令牌(仿 `ui_struct_probe.gd:379-391`)。
|
||||
- 产出:`CampEscOverlay.setup_buttons()`/`set_close_path()`/`bind_signals()`、`closed` 信号;`MainEscFlow.on_esc_input()`/`is_camp_context()`/`open_overlay()`/`close_overlay()`;`LAYER_CONTRACT` 新槽键 `camp_esc_overlay`;T2 按接口块接线。
|
||||
|
||||
### T2 营地顶栏小 HUD 栏(≈0.5–1d)
|
||||
|
||||
- 顶栏位落 `UiKit.keystone_badge` 工厂件(余额单口读数,契约 5);
|
||||
- **刷新挂卡④营地刷新单口**(契约 5);**刷新时机清单落定(v1.1 补)**:①购买后(挂单口)②进档/回营地进入时重读③夹具直写后由探针显式触发——断言前须显式触发,禁依赖「自动重读」假设;
|
||||
- HUD 栏形态按最小集(契约 8):只承载钥石余额;
|
||||
- **camp 截图/golden 联动条(v1.1 补)**:HUD 落位后核 camp 截图漂移热区→限 HUD 区显式更新+呈报(仿卡④ T5/卡② 契约 6 口径;现无 camp 逐像素 golden——卡④ 契约 10)。
|
||||
- 取用:T1 `MainEscFlow`、`camp_hud_band.gd` 接口块、卡④ `CampRefreshBus.refresh(camp_data)` 单口、`camp_scene_view.gd set_hud_band()` 顶栏预留位、`camp_shop_presenter.gd:62 camp_data()` 读数单点。
|
||||
- [ ] 在 `camp_hud_band.gd` 实现 `set_balance(v: int) -> void`/`bind_refresh_bus(bus: Object) -> void`/`refresh(camp_data: Dictionary) -> void`:`UiKit.keystone_badge`(`ui_kit.gd:632`)承载,读数只经 `camp_data()` 单口(F9/契约 5,禁第二账本、禁视图自算);挂接卡④ `CampRefreshBus.refresh(camp_data)`;载体循 UiKit `page_shell` 的 `PRESET_TOP_WIDE`+`custom_minimum_size` 先例(ui_kit.gd:523-525),禁手动 rect。
|
||||
- [ ] 在卡④ `camp_scene_view.gd` 的 `set_hud_band()` 顶栏预留位填 `CampHudBand` 实例(高 48px 浮层覆盖、不挤压画面;卡④ T2 跨卡接口①);`camp_scene_view.gd` 场景图铺底/命中区逻辑零改(卡④ 职责)。
|
||||
- [ ] 刷新时机清单落定(契约 5):①购买后(挂单口)②进档/回营地进入时重读③夹具直写后探针显式触发——断言前须显式触发,禁依赖「自动重读」假设;②的触发主体=组合根进档动线尾(营地开层同口)显式调 `CampRefreshBus.refresh(camp_data())` 一闸(契约 5 v1.4 补钉),禁 band `_ready` 自刷或自持第二入口。
|
||||
- [ ] HUD 栏形态按最小集(契约 8):只承载钥石余额;扩项=新裁点。
|
||||
- [ ] camp 截图/golden 联动:HUD 落位后核 camp 截图漂移热区→限 HUD 区显式更新+呈报;现无 camp 逐像素 golden(卡④ 契约 10),camp 验收=shot_probe 出图+shot_checker 语义断言。
|
||||
- 产出:`CampHudBand.set_balance()`/`bind_refresh_bus()`/`refresh()`、顶栏填值、刷新时机清单;T3 按接口块验收。
|
||||
|
||||
### T3 断言批(≈0.5–1d)
|
||||
### T3 三出口动线、设置语境分支与断言批(≈1–1.5d)
|
||||
|
||||
- 探针(**宿主选 screen_flow_probe——v1.1 定:轻闸默认段且「菜单⇄营地屏壳切换」正是其职域,零闸登记成本;若另起新文件须改 tools/probe_gate.sh 登记=§5 可写面外,禁**):合成 Esc 键事件→浮窗可见+三项在位;非营地语境(boot 菜单)不唤起;返回主菜单动线(营地隐+选档层收+菜单显);设置项开合(**含营地浮窗→设置→关闭回浮窗高危路径+「关闭设置后禁弹主菜单」反向断言——v1.1 补**);退出项接线断言(headless 不可真退);
|
||||
- HUD:余额读数=存档单口(夹具经**隔离存档实例直写** `add_keystone` 或等效写口——smoke 既有先例 smoke_all.gd:5440;**不经 DebugOverlay 界面——其钥石项是只读投影,debug_overlay.gd:173-189,v1.1 订正**);直写后显式触发刷新断言;
|
||||
- 契约断言:浮窗零动效(career 同款段复用/仿写);层序登记(冒烟 V1d);**浮窗开态 `debug_badge.visible==true`**(仿 ui_click_probe.gd:174-177 设置面开中角标可见先例——v1.1 补);
|
||||
- **变异验证伴生**:Esc 接线漏营地隐(预期动线断言红)、HUD 读缓存旧值(预期刷新断言红)、浮窗加第四钮(预期三项断言红)、**设置关闭后误回主菜单**(预期语境断言红——v1.1 补)、**Esc 再按不关窗**(预期关窗断言红,若 Q2 裁甲——v1.1 补);注入→最窄闸见红→精确还原→记录。
|
||||
- 取用:T1/T2 产物、`main_overlay_flow.gd:11-13 _on_settings_closed`、`main.gd:143 _quit_game`、`camp_shop_presenter.gd:50-53 on_camp_closed`、`screen_flow_probe.gd:153-165` Esc 合成段、`ui_struct_probe.gd:379-391` 零动效段。
|
||||
- [ ] 在 `main_esc_flow.gd` 实现 `_on_return_to_menu() -> void`:**首步 close 浮窗**(`ui.modals.flow.close(camp_esc_overlay)`——浮窗是模态层,屏壳可见性收不了它,缺此步浮窗残留主菜单上方;契约 4 v1.4 补)→ 营地场景屏隐藏+选档层同收+开始层恢复(卡④ T3 动线同口);营地语境⇔闲时会话(契约 4 前提),动线不含会话收束;回主菜单后菜单=卡②三钮、禁加「继续冒险」钮。
|
||||
- [ ] 在 `main_esc_flow.gd` 实现 `_on_settings() -> void`/`_on_quit() -> void`:设置→`ui.modals.flow.open(settings_overlay)`(浮窗登记于其下、关后遮挡解除重现);退出→`_quit_game`(`main.gd:143`,原样复用)。
|
||||
- [ ] 在 `main_overlay_flow.gd` `_on_settings_closed` 加语境分支:营地浮窗路径关设置回浮窗、不回主菜单(契约 3;现役 :13 `start_overlay.visible = true` 硬副作用仅菜单路径保留)。
|
||||
- [ ] 探针(宿主 `screen_flow_probe.gd`,已在 `tools/probe_gate.sh:142-146` 登记、零登记成本;不另起新文件):扩展 :153-165 Esc 合成段——营地根态合成 Esc→浮窗可见+三项在位;营地子界面开态合成 Esc→无反馈(Q1 甲,契约 9①);**设置开在浮窗之上合成 Esc→无反馈且浮窗不误关**(契约 9①——浮窗不隔层关闭,关设置后浮窗重现);再按 Esc 关窗(契约 9②);非营地语境(boot 菜单)不唤起(契约 9④);**冒险语境合成 Esc→浮窗不现**(契约 2 全局接线回归面,screen_flow_probe 冒险步内);**echo 事件合成→零响应**(触发沿 pressed 且非 echo,契约 9);返回主菜单动线(**浮窗自收**+营地隐+选档层收+菜单显);设置项开合(含营地浮窗→设置→关闭回浮窗高危路径+「关闭设置后禁弹主菜单」反向断言);退出项接线断言(headless 不可真退)。
|
||||
- [ ] HUD 余额断言:读数=存档单口(夹具经**隔离存档实例直写** `meta_state._add_keystone(9999)` 先例 `game/probe/ui_click_probe.gd:74`;**不经 DebugOverlay 界面——其钥石项是只读投影** `debug_overlay.gd:194-205`);直写后显式触发刷新断言。
|
||||
- [ ] 结构断言(`ui_struct_probe.gd`):浮窗三钮在位且仅三;零动效(仿 career :379-391);`LAYER_CONTRACT` 登记序(浮窗入合同表、`system_test.gd:94-106` V1c 树序链复跑);**浮窗开不波及 `debug_badge` 节点**(F10:发布态恒隐,改结构断言替代 v1.2 `visible==true` 断言)。
|
||||
- [ ] 正向验收断言(v1.2 计划的人工制造红取证条目整条已删,替换为 §7 上表正向断言):每条从真实入口进入、判据绑被测改动特有的可观测提交面(信号/入参/状态源取值/可见性/树序),在当轮真实跑批执行并通过;**禁把生产码改成错值看断言抓不抓得到、禁回退 hunk 看断言红不红**(人为制造红属伪造证据);判据绑不上=静态判据+评审注记申报观测面局限,证明做不出=停卡呈报。
|
||||
- 产出:三出口动线接线、设置语境分支、探针断言段(V1–V8 落点)、能力行名实核对表;T4 收口。
|
||||
|
||||
### T4 产出物落位卡(≈0.5d,末卡)
|
||||
|
||||
三份 `reports/` 写齐。
|
||||
- 取用:T0–T3 全部产物。
|
||||
- [ ] 里程碑步(T 段)出口跑一次代码域全套闸:`bash tools/run_all_gates.sh --code`;回执 `all_green=true`;任何新增红停卡,不得带红合回。波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。
|
||||
- [ ] 独立验收审计由未参与实现的会话/子代理执行,产出 `reports/iter<N>-验收审计-<日期>.md`;未过禁合并(审计入口见 §7)。
|
||||
- [ ] 轻闸全绿、合并前写齐三份 `reports/`:
|
||||
- [ ] `reports/iter<N>-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务+实现决定记录/代拍板追认单);
|
||||
- [ ] `reports/iter<N>-反哺点-<日期>.md`(§5 每条有落点:文件/节/原句/拟改句/依据,明确「实现批未写 design/」);
|
||||
- [ ] `reports/iter<N>-验收审计-<日期>.md`(独立审计逐行「通过/缺漏/例外及依据」)。
|
||||
- [ ] 用户目检项登记 `体验验证清单.md`(仓库根,反哺点列清单:Esc 三动线+HUD 余额观感+浮窗视觉面),登记完成即卡内义务了结,不阻塞批末收尾/合并/下一迭代开工。
|
||||
- 产出:三份 `reports/` 齐全+代码域闸全绿+验收审计通过,方算收口;合回后由本地 CI 跑不带参数的 `tools/run_all_gates.sh`(两域全量)复验。
|
||||
|
||||
**估时合计 ≈3–4.5d**(v1.1 订正:分项和=3.0–4.5d,原「2.5–3.5d」算术少算)。切分预案:T1/T2 后可切(浮窗先落、HUD 后落)——切分价值低,建议与卡④同批单跑。
|
||||
**估时合计 ≈3–4.5d**。切分预案:T1/T2 后可切(浮窗先落、HUD 后落)——切分价值低,建议与卡④同批单跑。
|
||||
|
||||
## 7. 验证闸(逐需求点验收清单)
|
||||
## 7. 验证闸:改动—验收对照表
|
||||
|
||||
| # | 需求点 | 测什么 | 落点/判定手段 |
|
||||
|---|---|---|---|
|
||||
| V1 | Esc 唤起(按 Q1 分拆) | **根态**合成 Esc→浮窗可见;**子界面开态按 Q1 案**(甲=不现/乙=先关子界面再现);boot 菜单语境不唤起(其余非营地语境由契约 2 红线+源码断言兜底——可达性单一,登记原因) | screen_flow_probe 合成键盘事件段(T0 spike 机制) |
|
||||
| V2 | 浮窗三项 | 返回主菜单/设置/退出游戏三钮在位且仅三 | ui_struct_probe 结构断言 |
|
||||
| V3 | 返回主菜单 | 营地场景屏隐藏+选档层同收+主菜单可见 | screen_flow_probe 型断言 |
|
||||
| V4 | 设置项(双路径) | 菜单路径(冒烟 V3g settings 段复跑)+**营地浮窗→设置→关闭回浮窗**(含禁弹主菜单反向断言) | 冒烟复跑+探针新路径段 |
|
||||
| V5 | 退出项 | 接线到 `_quit_game`(headless 不可真退——接线断言代偿) | 源码/结构断言 |
|
||||
| V6 | HUD 余额 | 读数=存档单口(隔离实例直写);直写后显式触发刷新;购买后刷新(挂卡④单口——跨卡联验) | 探针数据断言(smoke_all.gd:5440 同型先例) |
|
||||
| V7 | 零动效 | 浮窗子树零 AnimationPlayer+源码禁动效令牌 | ui_struct_probe 零动效契约段(career 同款) |
|
||||
| V8 | 层序与遮挡 | 浮窗入 LAYER_CONTRACT(冒烟 V1d);浮窗开态 debug_badge 可见 | 冒烟 V1d+探针 badge 断言 |
|
||||
| V9 | 目检项登记 | Esc 三动线+HUD 观感+浮窗视觉面(文字 WCAG 若入 shot_checker 取样,否则显式登记归目检并写明理由)入 07 | 件核(登记不阻塞) |
|
||||
| V10 | 反哺点清单 | §5 每条有落点 | 件核对表 |
|
||||
七格表:需求点|改动(文件:行/行为)|验收测试(名称+落点+尾缀)|层级(单元/接口/集成/探针)|真实入口|判据绑定面|能力行。**每个需求点至少一行;每个行为改动至少一行(V1–V10 需求点行+B1–B3 行为改动专行);每行必须有真实入口和判据绑定面——缺任一项=该需求点未验收,卡片不成立。** 断言尾缀〔ESC批 Vn〕/〔ESC批 Bn〕,与卡片清单互相 grep。能力行格式 `既有:<能力名>;新增:<能力名>`(中文分号分隔,对齐机检与卡④ v3.1 先例),两形态名称都须在 `game/tests/README.md` 能力表在场(既有=现役在场名,新增=本卡定名、由主 Agent 统一收口入表;本卡只写卡内能力行文字,README 由主 Agent 收口)。
|
||||
|
||||
**测试方式两分法**:V1–V8 机检自动化(能力验证经隔离存档实例直写钥石/开态——v1.1 订正:不经 DebugOverlay 界面);V9 归用户目检(生命周期末步统一进行,不阻塞迭代,澄清⑥口径)。
|
||||
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| V1 Esc 唤起(根态/子界面/关窗/非营地) | `camp_esc_overlay.gd` 浮窗视图;`main_esc_flow.gd on_esc_input()`/`is_camp_context()`/`open_overlay()`/`close_overlay()`;`main.gd` 输入入口 | `screen_flow_probe.gd:_ready`(Esc 唤起/子界面开态不唤起/再按关窗/非营地不唤起段)〔ESC批 V1〕 | 探针 | 营地场景根态合成 Esc 键事件(`InputEventKey`+`Viewport.push_input`,先例 :156-160)→ `main_esc_flow.on_esc_input()` → `ui.modals.flow.open/close` | 根态 Esc→浮窗 `visible=true`;再按→`visible=false`(绑 open/close 调用记录+浮窗可见性);子界面开态/设置开在浮窗之上合成 Esc→无反馈且浮窗不误关(契约 9①,浮窗不隔层关闭);boot 菜单与冒险语境合成 Esc→浮窗不现(契约 9④/契约 2,绑语境判据返回值);echo 合成→零响应(触发沿 pressed 且非 echo,契约 9) | 新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V2 浮窗三项 | `camp_esc_overlay.gd setup_buttons()` 三钮(modal_shell+danger_button) | `ui_struct_probe.gd:_ready`(浮窗三钮结构段)〔ESC批 V2〕 | 探针 | 浮窗视图实例化 → 三钮节点树 | 三钮节点存在且仅三(绑按钮名与数量;禁第四钮) | 既有:UI 全局主题与按钮五态(含对比度锚);新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V3 返回主菜单 | `main_esc_flow.gd _on_return_to_menu()`(营地隐+选档层同收+开始层恢复) | `screen_flow_probe.gd:_ready`(返回动线段)〔ESC批 V3〕 | 探针 | 浮窗「返回主菜单」钮 `pressed` → `main_esc_flow._on_return_to_menu()` → 屏显编排 | **浮窗 closed(动线首步自收,契约 4 v1.4)**+营地场景屏 `visible=false`+选档层 `visible=false`+`start_overlay.visible=true`(绑四处可见性/open-close 调用记录;`_screen_seals()` :51-57 互斥复跑) | 新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V4 设置项(双路径) | `main_esc_flow.gd _on_settings()`;`main_overlay_flow.gd _on_settings_closed` 语境分支 | `screen_flow_probe.gd:_ready`(营地浮窗→设置→关闭回浮窗段)〔ESC批 V4〕+菜单路径冒烟 V3g settings 段复跑 | 探针(+冒烟复跑) | 浮窗「设置」钮 → `ui.modals.flow.open(settings_overlay)` → 关闭 → `_on_settings_closed` 语境分支 | 设置开→浮窗 `visible` 恒 true(open 只隐登记序上方层——modal_stack.gd:27-31,浮窗登记在下、由树序遮挡非属性隐藏);关闭→浮窗重现+`start_overlay.visible=false`(绑语境分支谓词=camp_esc_overlay.visible;反向断言「关闭设置后禁弹主菜单」) | 既有:模态覆盖层编排与输入锁;新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V5 退出项 | `main_esc_flow.gd _on_quit()` → `main.gd:143 _quit_game()`(原样复用) | `ui_struct_probe.gd:_ready`(退出钮接线结构断言)〔ESC批 V5〕 | 探针(源码/结构,headless 不可真退) | 浮窗「退出游戏」钮 `pressed` → `_on_quit()` → `_quit_game()`(`settings_store.save_settings()`+`get_tree().quit()`) | 钮 `pressed` 连接目标=`_on_quit`→`_quit_game`(绑信号连接与调用链;headless 不真退=静态判据+评审注记申报观测面局限);**禁对退出钮 `pressed.emit()`**(防 `get_tree().quit()` 中止探针进程——quit(0) 仅靠 probe_gate 签名兜底不假绿,2026-11-01 双审补立) | 新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V6 HUD 余额 | `camp_hud_band.gd set_balance()`/`bind_refresh_bus()`/`refresh()`;`camp_scene_view.gd set_hud_band()` 填值;挂接卡④ `CampRefreshBus.refresh()` | `screen_flow_probe.gd:_ready`(HUD 余额读数/刷新段)〔ESC批 V6〕+`ui_struct_probe.gd:_ready`(顶栏位结构段) | 探针(跨卡联验:购买后刷新挂卡④单口) | 隔离存档实例 `meta_state._add_keystone(9999)`(`ui_click_probe.gd:74` 先例)→ 显式触发 `CampRefreshBus.refresh(camp_data)` → `camp_hud_band.refresh()` → `keystone_badge` 读数 | `value_label.text`=`"钥石 %d" % camp_data()["balance"]` 格式串比较(badge 文本带「钥石 」前缀——`ui_kit.gd:632` 工厂约定单点,禁实现期自造第二格式串;`keystone_balance()` 单口取值,2026-11-01 双审订正);直写后显式触发刷新才变(绑单口调用记录+badge 文本状态源) | 既有:元进度入账与锻造两轴;新增:营地顶栏 HUD 钥石读数与刷新单口同步 |
|
||||
| V7 零动效 | `camp_esc_overlay.gd` 直开直关(零 AnimationPlayer、源码禁 `create_tween`/`UiKit.motion`) | `ui_struct_probe.gd:_ready`(浮窗零动效契约段,仿 career :379-391)〔ESC批 V7〕 | 探针(结构/源码扫描) | 浮窗视图子树+`camp_esc_overlay.gd` 源码 | 两新件源码(camp_esc_overlay.gd+main_esc_flow.gd)+浮窗子树零 AnimationPlayer+源码零 `create_tween`/`UiKit.motion` 令牌(扫描面 >0 非空前置;扫描面扩两新件——2026-11-01 双审补立,开合编排件不脱扫) | 既有:模态覆盖层编排与输入锁;新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V8 层序与遮挡 | `ui_registry.gd` `LAYER_CONTRACT` 加 `camp_esc_overlay` 槽(营地层与 `settings_overlay` 之间)+`node()` 寻址 | `ui_struct_probe.gd:_ready`(浮窗登记序/遮挡段)〔ESC批 V8〕+`system_test.gd:_ready`(V1c 合同树序链 :94-106 复跑) | 探针(+系统测试复跑) | `main.ui.LAYER_CONTRACT` 单一事实源;`ui.modals.flow.open()` 遮挡记账 | 登记册序=合同模态序、直接子层树序=合同序逐对相等;`debug_badge` 末位 float 类不注册(open 只动登记层,绑登记册成员性;F10 发布态恒隐,不绑 `visible==true`) | 既有:模态覆盖层编排与输入锁;新增:Esc 浮窗唤起与三出口动线 |
|
||||
| V9 目检项登记 | `reports/iter<N>-实现报告-<日期>.md` 实机目检总清单 | 件核对(`体验验证清单.md` 登记,登记不阻塞)〔ESC批 V9〕 | 用户目检(非自动化) | 用户实机(生命周期末步统一进行,不阻塞迭代) | Esc 三动线+HUD 余额观感+浮窗视觉面(文字 WCAG 若入 shot_checker 取样,否则显式登记归目检并写明理由)入 `体验验证清单.md`=登记即义务了结 | 既有:模态覆盖层编排与输入锁 |
|
||||
| V10 反哺点清单 | §5 每条有落点 | 件核对表〔ESC批 V10〕 | 件核对(非自动化) | §5 同步面逐条对账 | §5 每条有 `reports/iter<N>-反哺点-<日期>.md` 落点 | 既有:模态覆盖层编排与输入锁 |
|
||||
| B1 Esc 输入接线与浮窗视图(行为改动专行) | `main.gd` 输入入口/薄委托;`main_esc_flow.gd on_esc_input()`/`is_camp_context()`/`open_overlay()`/`close_overlay()`;`camp_esc_overlay.gd` 新建;`ui_registry.gd` 新槽 | `screen_flow_probe.gd:_ready`(Esc 唤起/关窗/非营地段)+`ui_struct_probe.gd:_ready`(三钮/零动效/登记序段)〔ESC批 B1〕 | 集成 | 营地场景根态合成 Esc 键 → `main_esc_flow` → `ui.modals.flow.open/close(camp_esc_overlay)` | Esc 输入→浮窗 visible 两态(绑 open/close 调用记录);契约 9 四态路由(绑现开集合判据与 open/close 调用记录,含「设置开在浮窗之上」无反馈态);浮窗三钮数量+登记序(绑节点树与合同表) | 既有:模态覆盖层编排与输入锁;新增:Esc 浮窗唤起与三出口动线 |
|
||||
| B2 HUD 栏落位与刷新挂单口(行为改动专行) | `camp_hud_band.gd` 新建;`camp_scene_view.gd set_hud_band()` 填值;挂接卡④ `CampRefreshBus.refresh()` | `screen_flow_probe.gd:_ready`(HUD 读数/刷新段)+`ui_struct_probe.gd:_ready`(顶栏位结构段)〔ESC批 B2〕 | 集成 | `CampRefreshBus.refresh(camp_data)` → `camp_hud_band.refresh()` → `keystone_badge` | badge 文本=`camp_data()["balance"]` 单口取值;顶栏位存在(结构断言,高 48px 浮层);刷新单口调用记录(跨卡联验) | 既有:元进度入账与锻造两轴;新增:营地顶栏 HUD 钥石读数与刷新单口同步 |
|
||||
| B3 设置语境分支与返回主动线接线(行为改动专行) | `main_esc_flow.gd _on_return_to_menu()`/`_on_settings()`/`_on_quit()`;`main_overlay_flow.gd _on_settings_closed` 语境分支 | `screen_flow_probe.gd:_ready`(返回动线/设置双路径段)+`ui_struct_probe.gd:_ready`(退出钮接线断言)〔ESC批 B3〕 | 集成 | 浮窗三钮 `pressed` → `main_esc_flow` 三出口 → 现役动线/`_quit_game`;设置关闭 → `_on_settings_closed` 语境分支 | 返回动线三处可见性(绑屏显编排);设置关闭后浮窗 `visible=true`+`start_overlay.visible=false`(绑语境分支);退出钮连接链(绑信号连接) | 既有:模态覆盖层编排与输入锁;新增:Esc 浮窗唤起与三出口动线 |
|
||||
|
||||
**闸口径**:轻闸每卡出口自跑;批末重闸按改动域选档(本批碰 `game/` 代码与断言面 → `--code`)全绿才合并;MC 零跑(零数值零行为)。
|
||||
**落点集中**:V1/B1 → T1/T3;V2/V7/V8 → T1/T3;V3/V4/V5/B3 → T3;V6/B2 → T2/T3;V9/V10 → T4。全表名实核对归 T4。
|
||||
|
||||
**测试方式两分法**:V1–V8、B1–B3 机检自动化(能力验证经隔离存档实例直写钥石 `meta_state._add_keystone()`,`ui_click_probe.gd:74` 先例;不经 DebugOverlay 界面——其钥石项只读投影 `debug_overlay.gd:194-205`);V9 归用户目检(生命周期末步统一进行,不阻塞迭代,澄清⑥口径);V10 为件核对表。**用户目检一律「登记不阻塞」**:登记完成即卡内义务了结,不得作为批末收尾、合并或下一迭代开工的前置条件。
|
||||
|
||||
**判据绑定面口径**:每个需求点与每个行为改动的验收=一条从真实入口进入的断言,可 grep 定位、在当轮真实跑批中执行并通过,判据绑被测改动特有的可观测提交面(信号/事件/入参/状态源取值/绘制记录/可见性/树序)(2026-10-24/10-28 用户两裁)。**禁把生产码改成错值看断言抓不抓得到、禁回退 hunk 看断言红不红——人为制造红属伪造证据,一律禁止**;v1.2 计划的人工制造红取证条目整条已删,替换为上表正向验收断言。判据绑不上(纯防御分支、headless 不可真退)=静态判据+评审注记申报观测面局限,证明做不出=停卡呈报。配判据按强弱分层配齐:运行期断言(可见性/树序/状态源取值)抓状态类缺陷,golden 逐像素抓内容观感类缺陷(本卡无 camp golden,用 shot_checker 语义断言段+目检),占比/统计类判据只兜「整框空白/整框糊」、是补充不是主力(细则=test-conventions §8.4)。
|
||||
|
||||
**测试削弱申报(零削弱)**:**本卡零削弱申报**——本批只新增断言,不删除/放宽任何在役旧断言、不缩小扫描面、不把真实入口换成下层直调。v1.2 计划断言「浮窗开态 `debug_badge.visible==true`」因调试角标发布态恒隐换代(迭代 38 卡⑦,`main.gd:98`)与现行事实冲突,属**计划期订正**(该断言从未落地、非在役旧断言),改写为「浮窗登记序+open 不波及 float 类 `debug_badge` 节点」结构断言(V8),不计削弱。除此外实现期不得删除断言、放宽阈值、缩小扫描面、换下层直调;未申报的削弱由独立验收审计判红。
|
||||
|
||||
**独立验收审计**:合并前由未参与实现的会话/子代理执行,入口=审计只读本卡、实际对照表、diff、测试文件与实现报告,自跑最窄测试抽查、不采信报告「已全绿」;至少四件事——①逐行核对照表(测试存在、真的执行、尾缀能 grep 到、真实入口没有绕过改动点)②抽查判据绑定面(绑被测改动特有可观测提交面、当轮真实跑批执行过)③检查测试削弱(删除断言/放宽阈值/缩小扫描面/换下层直调逐处要本卡申报或用户批准)④核内部字段直查的受控例外(该行为无公开可观测面可钉时已在对照表注明理由)。报告落 **`reports/iter<N>-验收审计-<日期>.md`**,逐行「通过/缺漏/例外及依据」,未通过不得合并。测试执行两入口铁规不变:审计在迭代 loop 内启动的子代理算 loop,另开会话须用户点名。
|
||||
|
||||
**闸口径**:轻闸每卡出口自跑;批末重闸按改动域选档(本批碰 `game/` 代码/断言面 → `--code`)全绿才合并;MC 零跑(零数值零行为)。**卡内不写死闸件名单与域划分**,唯一出处在 `tools/run_all_gates.sh`。合回验证=主区直改+直提后由本地 CI 跑不带参数的 `tools/run_all_gates.sh`(两域全量)复验,代码面全量验证归合回后本地 CI,主区小批直提不重复跑全量。回归措辞按模板:里程碑步(波/T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试/工具先行孤立验证再并入全套。
|
||||
|
||||
## 8. 异常分级
|
||||
|
||||
- **L1(自救)**:断言写法、探针合成键事件写法、命名。
|
||||
- **L2(记录继续)**:Esc 接线方式选型(§9 域内)、浮窗壳尺寸/位次(UiKit 现行件域内)、HUD 栏位微调。
|
||||
- **L3(停机呈报)**:卡④ 场景屏未到位又需合并;Q1/Q2/Q3 未裁即开工;发现需扩展到非营地语境才能成立(触契约 2=用户裁面);Esc 键盘合成 spike 失败且无替代验收手段(真实路径纪律不让直呼处理函数代偿);浮窗开会隐藏其上登记层的栈语义被误判为缺陷(契约 7 已写明,勿误停机)。
|
||||
- **L1(自救一次)**:断言写法、探针合成键事件写法、命名、编译错误、签名拼写、测试套件 manifest 登记遗漏。
|
||||
- **L2(记录继续;同一红连续三次升 L3)**:浮窗壳尺寸/位次(UiKit 现行件域内)、HUD 栏位微调(顶栏域内)、行数较 T0 预期漂移但 S13 键不升。
|
||||
- **L3(立即停卡写报告等用户)**:
|
||||
- 卡④ 代码波未到位又需合并;
|
||||
- Q1/Q2/Q3 裁定被执行期擅自改值(已裁=甲/甲/甲,见 §10);
|
||||
- 发现需扩展到非营地语境才能成立(触契约 2=用户裁面);
|
||||
- Esc 键盘合成先例(`screen_flow_probe.gd:153-165`)复核失败且无替代真实入口验收手段(真实路径纪律不让直呼处理函数代偿);
|
||||
- 浮窗开会隐藏其上登记层的栈语义被误判为缺陷(契约 7 已写明,勿误停机);
|
||||
- 任何验收行无法从真实入口绑定特有可观测提交面(证明做不出=停卡呈报);
|
||||
- **机检预算互斥=上游缺陷停卡退回写卡段**:实现规范预算三新件超默认未走指标例外申报、或存量触面 S13 键较登记值上升、或机检键/计数与卡片契约互斥——一律停该卡呈报退回写卡段,禁为凑绿保留无效成员、造第三条路或内联求裁(req-card 第 9/14 节合流)。
|
||||
|
||||
## 9. 代拍板白名单(超清单必呈报)
|
||||
|
||||
1. Esc 输入接线方式(`_unhandled_input` vs InputMap 新 action vs 专用控制器)——约束:不吞他处输入、探针可合成(与 T0 spike 结论兼容;InputMap action+轮Polling 路线禁——与合成探针不兼容)。
|
||||
2. 浮窗模态壳尺寸与位次(UiKit `modal_shell` 现行件域内)。
|
||||
1. **(v1.4 已定稿,移出白名单)Esc 接线=事件驱动 `_unhandled_input`+`KEY_ESCAPE`(physical_keycode)、禁 Input 单例轮询、不挂 ui_cancel、pressed 且非 echo**——契约 9 接线定稿(2026-11-01 用户裁);白名单保留此条作裁定留痕,实现期无选型自由。
|
||||
2. 浮窗模态壳尺寸与位次(UiKit `modal_shell` 现行件域内,`ui_kit.gd:486`)。
|
||||
3. HUD 栏在顶栏的左右位次与间距(卡④场景屏顶栏域内)。
|
||||
4. 「返回主菜单」复用卡④篝火同一处理函数(建议复用——动线同口;实现期定)。
|
||||
5. 浮窗视觉面是否入 shot_checker 取样(T3 定:入=补截图段;不入=显式登记归目检并写明理由)。
|
||||
6. 提交切分与 worktree 分支命名。
|
||||
5. 浮窗视觉面是否入 shot_checker 取样(T3 定:入=补截图段;不入=显式登记归目检并写明理由)。
|
||||
6. 提交切分与 worktree 分支命名(车道铁律:主区直改+直提;大批按约定 worktree 非强制)。
|
||||
|
||||
## 10. 待裁点
|
||||
超出必须呈报:任何数值、事件名、接口名、文件职责、T 卡验收落点、三钮文案、Q1/Q2/Q3 裁定值。
|
||||
|
||||
### Q1 · Esc 在子界面开态下的行为(必裁,未裁不开 T1)
|
||||
## 10. 待裁点:零待裁点,开工门=U0
|
||||
|
||||
**本卡设计待裁点清零,开工门=U0。** Q1/Q2/Q3 均于 2026-10-18 裁定(下列为现行裁定留痕,非待裁点,实现期禁自行改值):
|
||||
|
||||
### Q1 · Esc 在子界面开态下的行为(已裁定 甲)
|
||||
|
||||
**背景**:营地语境含「场景根态」与「子界面开态」(锻造/秘宝/生涯/天赋树/图鉴开着时)。澄清⑤裁决 9 未覆盖此分支。两案并列,**无推荐(用户令:不代裁)**:
|
||||
|
||||
| 案 | 内容 | 代价 |
|
||||
|---|---|---|
|
||||
| 甲 | 只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗(**前提=各子界面自带返回钮闭环——待卡④ T3 承诺,v1.1 括注**) | 语义最简;子界面里按 Esc 无反馈 |
|
||||
| 甲 | 只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗(前提=各子界面自带返回钮闭环——待卡④ T3 承诺) | 语义最简;子界面里按 Esc 无反馈 |
|
||||
| 乙 | 营地语境任意态响应 Esc:子界面开着时先关子界面回根态,再按才唤浮窗(单义化) | 多一层输入编排;与既有「子界面返回钮」形成双关闭路径 |
|
||||
|
||||
连带:判据形态随案(T1 已列);V1 按案分拆断言;契约 2 措辞裁后回写。裁决方式:随卡片评审定案;裁定落 T0 执行+实现报告留痕。
|
||||
连带:判据形态随案(T1 已列);V1 按案分拆断言;契约 2 措辞裁后回写。
|
||||
|
||||
**裁定(2026-10-18)**:**甲**——只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗。代拍板留痕(用户令「事项按推荐的来」,本项无推荐案,取默认甲=语义最简;前提=卡④ T3 承诺各子界面自带返回钮闭环,卡④重新立卡时该承诺已在内;追认单可 veto)。T1 判据=营地场景屏 visible 且无营地子模态开态。
|
||||
**裁定(2026-10-18)**:**甲**——只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗。代拍板留痕(用户令「事项按推荐的来」,本项无推荐案,取默认甲=语义最简;前提=卡④ T3 承诺各子界面自带返回钮闭环,卡④ v3.1 已在内;追认单可 veto)。T1 判据=营地场景屏 visible;「无营地子模态开态」由契约 9① 现开集合判据承载(v1.4,判据单点化)。裁定落 T0 执行+实现报告留痕。
|
||||
|
||||
### Q2 · 浮窗的关闭/取消路径(必裁,未裁 T1 视图定不了稿——v1.1 新增)
|
||||
### Q2 · 浮窗的关闭/取消路径(已裁定 甲)
|
||||
|
||||
**背景**:`UiKit.modal_shell`(ui_kit.gd:456-475)只产 dim+center+panel+VBox、**无内置关闭件**;契约 1 禁加项⇒浮窗只有三钮,无一「关闭」。而 §4 不做清单把「任意键关闭浮窗」划为用户未裁禁自扩——**Esc 自身再按的行为恰好落在被 punt 的缝隙里**:Q1 两案都不覆盖「浮窗已开时按 Esc」。若不裁且无关闭钮,玩家误开浮窗后离开营地只有「回主菜单/开设置/退游戏」三条路——体感陷阱,且与卡④子界面(生涯有返回钮)的可用性水准倒挂。
|
||||
**背景**:`UiKit.modal_shell`(`ui_kit.gd:486`)只产 dim+center+panel+VBox、**无内置关闭件**;契约 1 禁加项⇒浮窗只有三钮,无一「关闭」。而 §4 不做清单把「任意键关闭浮窗」划为用户未裁禁自扩——Esc 自身再按的行为恰好落在被 punt 的缝隙里:Q1 两案都不覆盖「浮窗已开时按 Esc」。若不裁且无关闭钮,玩家误开浮窗后离开营地只有「回主菜单/开设置/退游戏」三条路——体感陷阱,且与卡④子界面(生涯有返回钮)的可用性水准倒挂。
|
||||
|
||||
| 案 | 内容 | 代价 |
|
||||
|---|---|---|
|
||||
@@ -187,23 +306,15 @@
|
||||
| 乙 | 浮窗加关闭钮 | 触契约 1「禁加项」——须重新解释「三项」仅指功能项 |
|
||||
| 丙 | 维持无关闭(三钮即全部出口,「返回主菜单」充当默认离开) | 误开浮窗后成本高;与子界面可用性水准倒挂 |
|
||||
|
||||
裁决方式:随卡片评审定案;裁定落 T1 视图与接线+V 表。
|
||||
**裁定(2026-10-18)**:**甲**——再按 Esc 关浮窗(同键唤起/关闭单义切换)。推荐案,用户令按推荐执行。T1 接线含「浮窗已开时再按 Esc=关浮窗」;V1 断言按「根态唤起/再按关闭」两态分拆。裁定落 T1 视图与接线+V 表。
|
||||
|
||||
**裁定(2026-10-18)**:**甲**——再按 Esc 关浮窗(同键唤起/关闭单义切换)。推荐案,用户令按推荐执行。T1 接线含「浮窗已开时再按 Esc=关浮窗」;V1 断言按「根态唤起/再按关闭」两态分拆。
|
||||
|
||||
### Q3 · Esc 范围确认(顺带确认项,低成本高保险——v1.1 新增)
|
||||
### Q3 · Esc 范围确认(已裁定 甲)
|
||||
|
||||
**背景**:契约 2「Esc 只在营地语境」是卡的从严收窄(澄清文档只裁「Esc 唤浮窗三项」、未裁范围——S1)。收窄方向保守且已自标「用户未裁」,但若用户本意是全局 Esc 菜单,范围锁死即返工。
|
||||
|
||||
| 案 | 内容 | 代价 |
|
||||
|---|---|---|
|
||||
| 甲(推荐) | 确认「Esc 浮窗只在营地语境」——契约 2 现文成立 | 无(一句话确认) |
|
||||
| 乙 | 用户本意为全局(或更宽范围) | 本卡范围重开=契约 2/T1/V1 大改,且触 08:192 Beta 行口径 |
|
||||
|
||||
裁决方式:随卡片评审顺带确认。
|
||||
| 乙 | 用户本意为全局(或更宽范围) | 本卡范围重开=契约 2/T1/V1 大改,且触 08:193 Beta 行口径 |
|
||||
|
||||
**裁定(2026-10-18)**:**甲**——确认「Esc 浮窗只在营地语境」(推荐案,用户令按推荐执行)。契约 2 从「卡的从严收窄」升格为已确认口径;S1 保留意见关闭。
|
||||
|
||||
---
|
||||
|
||||
**审查回写要点**:v1.0→v1.1(2026-10-18 grilling 子 Agent 对抗审查回写)——事实订正 5 处:F9 刷新链路失实(营地刷新腿随 CampOverlay 退役、`_refresh_presentations` 是战斗侧腿)→契约 5 改挂卡④营地刷新单口+T2 刷新时机清单;E2「调试接口直改钥石」能力不存在(DebugOverlay 钥石只读)→改隔离存档实例直写(smoke 先例);F2 行号拆分(_open_settings :1055-1057);F8 :191→:192;估时算术 2.5–3.5d→3–4.5d。自扩订正:契约 2 标卡的从严收窄+Q3 请用户确认。卡内可收 8 项:契约 3 放宽语境分支、契约 7 遮挡结论+栈语义、契约 4 前提成文、T1 语境判据、T2 刷新时机+golden 联动、T3 探针宿主定 screen_flow_probe+badge 断言+变异补二条、V1 按 Q1 分拆、V4/V6/V8/V9 订补。跨卡对齐:HUD 刷新单口(§0 接口+卡④ T3 定义)、子界面返回钮承诺(Q1 甲案前提=卡④ T3)、终局落点不变量(T0 互证)、探针路径依赖卡②③链(§0)。新增待裁点 Q2 浮窗关闭路径、Q3 Esc 范围确认。用户面裁决(裁决 9/10)零改动。
|
||||
@@ -1,57 +1,61 @@
|
||||
# 需求卡片——棋盘格边长口径收口批(探针门槛纠偏+格边长算式单点+冒烟扩四档板型)
|
||||
# 需求卡片——棋盘格边长口径收口批 v2(阈值退役+格边长算式单点+冒烟扩四档板型)
|
||||
|
||||
状态行:v1.0 定稿——零待裁点(2026-10-30 用户裁:①探针不扩到 L3 推关;②最紧档 14×14 的可读断言落单元四档+探针实板推定两处;③算式单点提取用私有静态名,依据见 §2 第 5 条)
|
||||
状态行:v2.0 定稿——零待裁点(2026-11-01 用户裁:①可读性锚点=用户验收的现行渲染值——基座档 14×14 板实测 28px 即达标,battle.md「可读下限 30px」判据句退役(落文归文档批,走反哺点通道),探针旧值 36 一并废弃;②探针格边长判据换锚=实读值与单点算式严格相等+结构钳制保护+全档读数留痕,全仓禁任何人造格边长阈值;③阈值手抄常量 `MIN_CELL` 删除,禁第二份阈值抄本再入代码或测试)
|
||||
|
||||
接收方:待办清单条目「棋盘格边长三方取值不一致——待扩板定档处置(2026-10-06 登记,来源=批次移交)」(`待办清单.md` 在册,状态「待写卡」)
|
||||
接收方:待办清单条目「棋盘格边长三方取值不一致——待扩板定档处置(2026-10-06 登记,来源=批次移交)」(`待办清单.md` 在册)
|
||||
|
||||
来源:**设计事实源**=`design/gdd/ux/battle.md`「棋盘格尺寸公式」节(Last Updated 2026-10-29;格边长口径的**唯一事实源**——公式、可读下限 30px、结构钳制 [26,46] 三项都在此节)。指路文档(2026-10-26 已归一、不再存算例)=`design/art/art-bible.md` §8.1/§8.2、`design/gdd/systems/表现与支撑/HUD框架.md`。四档板型事实源=`game/data/tables/board_gen.tres`。
|
||||
来源:**设计事实源**=`design/gdd/ux/battle.md`「棋盘格尺寸公式」节(2026-11-01 实查——公式与结构钳制 [26,46] 在 `:137-146`;原 `:148-152` 算例表已于 2026-10-31 布局几何单点化批退役(commit 1cdef6ba),现行 `:148`=「算例不入文档」句;`:144`「可读下限 30px」句经 2026-11-01 用户裁退役,落文走 §5 反哺点通道,本卡判据零引用)。布局事实源=`game/data/tables/battle_layout.tres` 五字段(2026-10-31 布局几何单点化批起为分区几何唯一事实源)。四档板型事实源=`game/data/tables/board_gen.tres`。锚点裁决过程与实测读数链=[停机呈报-棋盘格边长口径收口批-2026-10-31](停机呈报-棋盘格边长口径收口批-2026-10-31.md)。
|
||||
|
||||
## 1. 目标与完成定义
|
||||
|
||||
这批做什么:把「棋盘格边长」在代码侧残留的两处旧口径收干净。文档侧已于 2026-10-26 归一(口径只剩 battle.md 一节),代码侧还差两件——探针的可读门槛仍是 12×12 时代的 36px(比 battle.md 的可读下限 30px 严 6px,属用旧值当新标准),格边长冒烟只跑 L1/L2(13×13 与 14×14 两档板型无断言)。本批顺带把格边长算式收成单点(现在它内联在 `set_cell_area` 里,任何「在别的板型/别的面积上求值」的需求都只能复写算式=造第二口径)。
|
||||
这批做什么:把「棋盘格边长」在代码侧的残留旧口径收干净——**方向经 2026-11-01 用户裁换代**:不是把探针阈值 36 改成 30(v1 方向,已废),而是**把人造阈值整个退役**——可读性的锚点=用户验收过的现行渲染画面(基座档四档板型 40/33/30/28px),检查工具不再拿任何编造的下限给画面打分,只做两件事:①验证生产写入值与单点算式严格相等(接线守卫);②把四档板型在实板可用面积上的推定值留痕(回归对照基准)。同时完成 v1 已裁的两件:格边长算式收成单点(现在内联在 `set_cell_area` 里,任何「在别的板型/别的面积上求值」的需求都只能复写算式=造第二口径)、13/14 两档板型进入测试守卫。
|
||||
|
||||
**行为零变化**:算式逐位不变,`set_cell_area` 的副作用顺序(英雄脚锚重置 → `_refresh_slab` → `_update_world_size`)零改动,玩家可见画面零变化。
|
||||
|
||||
完成定义(全部满足才算完):
|
||||
1. 代码侧可读门槛=30px,与 battle.md「可读下限 30px」一致;旧值 36 在 `game/` 下零残留。
|
||||
1. 代码侧人造阈值归零:`layout_probe.gd` 的 `MIN_CELL` 常量删除,`grep -rn "MIN_CELL\|可读门槛\|可读下限" game/` 零残留;30 与 36 均不得以任何形态回到代码或测试判据。
|
||||
2. 格边长算式只剩一处落点(`BoardView._cell_for`),`set_cell_area` 只调它;探针与单元测试不再各自复写算式。
|
||||
3. 13×13 与 14×14 两档进入断言并在当轮真实跑批中执行通过(单元四档+探针实板面积推定两条)。
|
||||
4. 代码域闸全绿;`tools/gdstyle_baseline.txt` 中 board_view.gd 各键只许持平或下降(MATCH——`max-public-methods` 保持 27)。
|
||||
3. 13×13 与 14×14 两档进入守卫并在当轮真实跑批中执行通过(单元四档冒烟+探针等价断言与推定留痕)。
|
||||
4. 代码域闸全绿;`tools/gdstyle_baseline.txt` 中 board_view.gd 各键只许持平或下降(MATCH——`max-public-methods` 保持 27、`max-class-variables` 保持 31)。
|
||||
5. 产出物三份落 `reports/`(实现报告/反哺点清单/验收审计报告),独立验收审计未过不合并。
|
||||
|
||||
**编队注记与估时**:估时 **0.5 个工作日**(T0 0.1/T1 0.15/T2 0.1/T3 0.1/T4 0.05),远低于迭代冻结线(5 个工作日),可编批;编入哪个迭代由迭代编排段定。本批触面=`game/presentation/views/board_view.gd`+`game/probe/layout_probe.gd`+`game/tests/unit/core/board_gen_reward_test.gd`+`game/tests/README.md`(写卡段已同批入表),与在飞批次无文件交叠需编排段复核。
|
||||
**编队注记与估时**:估时 **0.5 个工作日**(T0 0.1/T1 0.15/T2 0.1/T3 0.1/T4 0.05),远低于迭代冻结线(5 个工作日),可编批;编入哪个迭代由迭代编排段定(worktree iter46 的未提交 WIP 三件中,T1 与 T3 两件按 v2 原样复用,T2 探针件按本卡新判据返工——见 §12)。本批触面=`game/presentation/views/board_view.gd`+`game/probe/layout_probe.gd`+`game/tests/unit/core/board_gen_reward_test.gd`,与在飞批次无文件交叠需编排段复核。
|
||||
|
||||
## 2. 现状事实
|
||||
|
||||
全部行号为 **2026-10-30 实查**——本批编入后须由 T0 按 T0 时点 master 重测重锚。
|
||||
全部行号为 **2026-11-01 实查**(master 3499638d)——本批编入后须由 T0 按 T0 时点 master 重测重锚。
|
||||
|
||||
1. 算式内联在 `game/presentation/views/board_view.gd:191-209`(`set_cell_area`):`:194` N=`maxi(width,height)`、`:195` `sep := SEP`(`SEP := 2`,`:34`)、`:196-197` `d := DEPTH_PX`(`8.0`,`:37`)与 `reserve := 24.0 + d`、`:198` 一条 `int(floor((minf(avail.x - 12.0 - d, avail.y - reserve) - float((n - 1) * sep)) / float(n)))`、`:199` `clampi(cell, 26, 46)`。副作用尾链 `:200-209`(英雄脚锚重置/`_refresh_slab`/`_update_world_size`)。
|
||||
2. 生产调用路径两条:`game/presentation/views/board_zone_view.gd:91-92`(`board_area.resized` → `set_cell_area(_board_area.size)`)与 `game/presentation/views/board_view.gd:250`(`rebuild` 末尾 `set_cell_area(size)`)——传入的都是棋盘视图实际可用区尺寸,`board_view` 为 `PRESET_FULL_RECT` 子级,故 `board_view.size` 即生产传入值。
|
||||
3. 探针门槛:`game/probe/layout_probe.gd:15` `const MIN_CELL := 36.0`,注释自陈「battle.md §棋盘格尺寸公式 1280 档 12×12 → 36px」;`:92-94` 断言 `cell < MIN_CELL` 记红。探针只进 L1(`:27` 起始冒险)、`:31` `press_candidate(0)`,故实跑只会遇到 10×10(格边约 45px),门槛 36 从未在 30–35px 区间生效过。
|
||||
4. 格边长冒烟:`game/tests/unit/core/board_gen_reward_test.gd:53-69`(`_smoke_layout_cell_formula`):`:57` `for L in [1, 2]`、`:58` `generate(L, 0, ...)`、`:60` 样本 `avail := Vector2(1036, 460)`、`:63` 读 `board_view.get("_cell")`、`:64-66` 网格高 ≤ 可用高−24、`:67-68` 格边长 ∈ [26,46]。13×13 与 14×14 两档从未进入断言。
|
||||
5. **S13 顶格事实(本机 gdstyle v0.4.0 实测)**:`tools/gdstyle_baseline.txt:22` 登记 `game/presentation/views/board_view.gd|quality/max-public-methods = 27`,与实测公开方法数 27 相等。对同一文件副本加一个公开静态函数后实测升到 **28**(WORSENED 红);改名为下划线前缀(`_cell_for`)后实测仍为 **27**(零新发现)。故算式提取必须用私有名。
|
||||
6. 四档板型取档(`game/data/tables/board_gen.tres` 实查 (level_index, node_depth) → 尺寸):L1 depth 0–3=10×10、L1 depth 4–6=12×12、L2 depth 0–9=12×12、L3 depth 0–8=13×13、L3 depth 9–13=14×14。即 `generate(1,0)`=10、`generate(2,0)`=12、`generate(3,0)`=13、`generate(3,9)`=14。
|
||||
7. 规格侧:`battle.md:137-146` 公式与两项判据——结构钳制区间 [26,46]px(`:143`,管算式不越界)、**可读下限 30px**(`:144`,管玩家能否看清,与钳制分开);`:148-152` 算例表按「1280 档可用高 486px」推算 43/36/33/30,文内明标「随布局与板型变化,不是契约值」。
|
||||
8. 实机可用面积与算例不同源:`game/presentation/ui_assembler.gd:20-28` 结构为 B 区 252px + C/D 两列占余高(该文件 `:24` 注释写明 548px),D 列内 `board_zone_view.gd:24-36` 再减 AP 条 44px 与 4px 间距——与 battle.md 算例假设的 486 可用高存在偏差(与待办清单在册的「B 区高度 270 vs 252」同源)。本卡不把算例当契约,实板可用面积一律以探针实读 `board_view.size` 为准。
|
||||
1. 算式内联在 `game/presentation/views/board_view.gd:206-215`(`set_cell_area`):`:209` N=`maxi(width,height)`、`:210` `sep := SEP`(`SEP := 2`)、`:211-212` `d := DEPTH_PX` 与 `reserve := 24.0 + d`、`:213` 一条 `int(floor((minf(avail.x - 12.0 - d, avail.y - reserve) - float((n - 1) * sep)) / float(n)))`、`:214` `clampi(cell, 26, 46)`。副作用尾链自 `:215` 起(英雄脚锚重置/`_refresh_slab`/`_update_world_size`)。
|
||||
2. 生产调用路径两条:`game/presentation/views/board_zone_view.gd:91-92`(`board_area.resized` → `set_cell_area(_board_area.size)`)与 `board_view.gd` `rebuild` 末尾 `set_cell_area(size)`——传入的都是棋盘视图实际可用区尺寸,`board_view` 为 `PRESET_FULL_RECT` 子级,故 `board_view.size` 即生产传入值。
|
||||
3. 探针阈值手抄件:`game/probe/layout_probe.gd:15` `const MIN_CELL := 36.0`,注释自陈出处为旧算例表「1280 档 12×12 → 36px」;`:93-95` 断言 `cell < MIN_CELL` 记红;`:44-45` PASS 消息引用 MIN_CELL。探针只进 L1(`:27` 起始冒险)、`:31` `press_candidate(0)`,实跑只遇 10×10(实读 40px),36 阈值从未在 28–35px 区间生效过——**该常量与旧算例表同源,旧算例表已退役(1cdef6ba),此抄本成为无源之值**。
|
||||
4. 格边长冒烟:`game/tests/unit/core/board_gen_reward_test.gd:53-69`(`_smoke_layout_cell_formula`):`:57` `for L in [1, 2]`、`:60` 样本 `avail := Vector2(1036, 460)`、`:63` 读 `board_view.get("_cell")`、`:64-66` 网格高 ≤ 可用高−24、`:67-68` 格边长 ∈ [26,46]。13×13 与 14×14 两档从未进入断言。
|
||||
5. **S13 顶格事实(2026-11-01 实查,gdstyle v0.4.0)**:`tools/gdstyle_baseline.txt` 登记 `board_view.gd|quality/max-public-methods = 27`(`:22`)与 `max-class-variables = 31`(`:11`),与静态清点逐一相符。对同一文件副本加一个公开静态函数后实测升 28(WORSENED 红);改名为下划线前缀(`_cell_for`)后持平 27。**故算式提取必须用私有名,且本批禁给 board_view.gd 新增任何成员(31 同样不容新增——钳制界不得提取为公开常量)**。
|
||||
6. 四档板型取档(`board_gen.tres` 实查 (level_index, node_depth) → 尺寸):L1 depth 0–3=10×10、L1 depth 4–6=12×12、L2 depth 0–9=12×12、L3 depth 0–8=13×13、L3 depth 9–13=14×14。即 `generate(1,0)`=10、`generate(2,0)`=12、`generate(3,0)`=13、`generate(3,9)`=14。
|
||||
7. **锚点读数(2026-10-31 探针实读,停机呈报在案;2026-11-01 用户裁定为现行锚点)**:基座 1280×800 档 `board_view.size`=(1022.0, 454.0),10/12/13/14 板 → 40/33/30/28px;16:9 1920×1080 档 (1662.0, 734.0) → 四档全部 46px(钳制顶格)。代入复核(1280 档 14 板):`min(1022−12−8, 454−32) = 422`;`(422 − 13×2) / 14 = 28.28 → floor 28` → 钳制 [26,46] 内 → 28px。
|
||||
8. 布局事实源换代(2026-10-31 布局几何单点化批,1cdef6ba):分区几何唯一事实源=`battle_layout.tres` 五字段(实查 `stage_h=252`/`ap_bar_h=44`/`info_panel_w=240`/`log_band_h_dig=24`/`log_band_h_settle=84`);容器内部结构(VBox 间距 4px、常驻操作提示条、面板边距)在代码中,实板可用面积以探针实读 `board_view.size` 为准,不静态推算。
|
||||
9. 旧判据毒性记录(v1 停机的根因,防复发):「可读下限 30px」与「36px 门槛」均无实测背书——30 系旧算例表(按假设可用高 486px 推算)的产物被写成规则,36 是探针从该表错抄的第二份手抄件;两者互相打架且与实机脱节,是 2026-10-31 停机的直接原因。本批后此类「文档句子↔代码常量」双写形态在本域不得再现(§3 契约②③)。
|
||||
|
||||
## 3. 设计契约(违反即返工,标 🔴 触碰=L3 停机呈报)
|
||||
|
||||
- 🔴 **算式单点**:格边长算式只在 `BoardView._cell_for` 一处;`set_cell_area` 只调它。探针、测试、任何新调用方都不得复写这条算式(复写=造第二口径,本批立项原因就是三处口径打架)。
|
||||
- 🔴 **两个数不得合并**:可读下限 30px(battle.md 判据)与结构钳制 [26,46]px(算式不越界)是两个概念。前者只出现在探针门槛与断言里,后者只出现在 `_cell_for` 内;禁止用钳制区间替代下限判据,也禁止把下限塞进 `cell_for` 的 clamp。
|
||||
- 🔴 **私有名固定**:提取函数名必须是 `_cell_for`(下划线前缀)。依据=§2 第 5 条的实测:公开名即令 `max-public-methods` 27→28 恶化。实现期「顺手改成公开方法更好看」=L3。
|
||||
- 🔴 **锚点唯一**:格边长的判据锚=①用户验收的现行渲染值(§2 第 7 条读数表,只作记录与对照,不作判红阈值)+②公式自身结构钳制 [26,46](battle.md `:143`,单元冒烟既有断言承载)。**本批起全仓禁任何人造格边长可读阈值**——30、36 及其变体不得出现在任何代码、测试、探针判据中;发现即 L3。
|
||||
- 🔴 **阈值手抄禁令**:探针与测试不得新增阈值常量。与算式相关的判据一律经 `BoardViewScript._cell_for(...)` 等价比较或既有公开出口(`cell_size`)承载;唯一例外=单元冒烟既有的 [26,46] 区间断言(v1 前已存在,逐字保留)。
|
||||
- 🔴 **算式单点**:格边长算式只在 `BoardView._cell_for` 一处;`set_cell_area` 只调它。探针、测试、任何新调用方都不得复写这条算式(复写=造第二口径)。
|
||||
- 🔴 **私有名固定**:提取函数名必须是 `_cell_for`(下划线前缀)。依据=§2 第 5 条实测:公开名即令 `max-public-methods` 27→28 恶化;同理禁新增任何成员(`max-class-variables` 31 顶格)。实现期「顺手改成公开方法更好看」=L3。
|
||||
- 🔴 **行为零变化**:`set_cell_area` 的副作用顺序与数值逐位不变;`rebuild`/`resized` 两条调用路径不改;画面像素零变化。
|
||||
- 🔴 **禁为机检文本保留无效成员**(重构类卡条款,2026-10-25 立):禁止为迎合机检消息文本(含计数)而保留或新增无效成员/别名;机检键与本卡契约互斥时,实现段一律停卡呈报,不得自造第三条路。
|
||||
- 🔴 **拆分边界纪律**(结构类卡条款,2026-10-28 立,判据权威=code-conventions §1.1):①拆出单元 `_cell_for` 职责语句=「按 battle.md 格尺寸公式,由板型 N 与可用面积算格边长的无状态纯函数」,单一变化原因=公式本身,实现报告逐件一行承载;②集体身份=「算式唯一落点」(命得出名字,非凑计数袋);③「过阈值」只许作为发现信号,作为拆分或收拢的动机即违规;④按纪律拆不出内聚单元 → 停卡呈报走豁免/还债通道,禁硬拆凑绿(进 §9 L3)。
|
||||
- 🔴 **测试削弱申报制**:允许改动的旧断言全集见 §8「测试削弱申报」,未申报的删改由独立验收审计判红。
|
||||
- 🔴 **禁变异类测试与撤销类取证**:不得靠回退 hunk 或注入破坏证明断言有效。
|
||||
|
||||
## 4. 范围边界
|
||||
|
||||
做:算式提取为 `_cell_for` 并改调;探针门槛 36→30 与注释改指 battle.md;探针新增「实板可用面积下 13/14 板格边长推定」断言与 board_view 零尺寸前置;格边长冒烟扩到四档板型并加算式单点等价断言;`game/tests/README.md` 能力行入表(写卡段同批,见 §5)。
|
||||
做:算式提取为 `_cell_for` 并改调;探针删除 `MIN_CELL` 常量与阈值断言、改等价断言+推定留痕+零尺寸前置;格边长冒烟扩到四档板型并加算式单点等价断言。
|
||||
|
||||
不做(明示去向):
|
||||
1. **探针扩到 L3 推关**——2026-10-30 用户裁不做:成本是探针要真打穿两关(main 无跳关入口),且一旦红因是推关而非布局会污染该闸;最大板可读面改由 §7.3 的推定断言承担。
|
||||
2. **battle.md 算例表改数**——实现批禁写 `design/`;实测与算例的偏差走 §5 反哺点通道。
|
||||
3. **四档板型数值调整**——`board_gen.tres` 板尺寸由设计侧定,本批只读不写。
|
||||
4. **B 区高度 252 vs 270**——另一条在册待办(迭代 43 批后待裁三点),本批不碰。
|
||||
1. **探针扩到 L3 推关**——v1 已裁不做(推关成本与红因混淆);维持。
|
||||
2. **battle.md「可读下限 30px」句的落文**——实现批禁写 `design/`;退役措辞走 §5 反哺点通道,文档批落文。本批判据不依赖该句(退役与否不阻塞实现)。
|
||||
3. **四档板型数值调整**——`board_gen.tres` 由设计侧定,本批只读不写。
|
||||
4. **布局表字段调整**——`battle_layout.tres`(含 `stage_h`)刚经布局几何单点化批落地,本批只读;任何为格边长而动的布局调整(如加高棋盘区)=另一张设计批的卡。
|
||||
5. **`set_cell_area` 副产物顺序调整**——零触碰。
|
||||
6. **MC/数值验证**——无数值改动零跑。
|
||||
|
||||
@@ -59,112 +63,114 @@
|
||||
|
||||
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|
||||
|---|---|---|
|
||||
| design/gdd/ux/battle.md(设计权威——实现批禁直改) | ①`:148-152` 算例表按「可用高 486px」推算 43/36/33/30,而实机 D 列结构为 548px(§2 第 8 条)——探针实测格边长若与算例不符,是算例随布局漂移而非代码错;②「可读下限 30px」(`:144`)条本身不变,本批正是向它对齐 | 反哺点通道:把探针 L1 实测格边长与 13/14 推定读数逐条列进 `reports/iter<N>-反哺点-<日期>.md`(改哪一节=`:148-152` 算例表、改成什么=填实测值或标注「按旧布局口径」、依据=实测读数),用户会话裁决后归文档批落文 |
|
||||
| game/tests/README.md(机械面——归写卡段维护) | 新增能力行「战斗屏三区几何与棋盘格边长(分辨率两档×四档板型)」,覆盖域表 HUD框架.md 行同步补名 | 写卡段已于本卡成文同批入表,实现批零增删零改行 |
|
||||
| design/gdd/systems/表现与支撑/HUD框架.md、design/art/art-bible.md §8.1/§8.2(已归一为指路) | 本批不改二者的任何陈述(2026-10-26 归一后它们只写规则与指针,不存算例与定值档) | 无(本行占位——按规约查不出也要写明) |
|
||||
| design/gdd/ux/battle.md(设计权威——实现批禁直改) | ①`:144`「可读下限 30px——与结构钳制分开:钳制管算式不越界,下限管玩家能否看清」句——2026-11-01 用户裁退役;依据=锚点裁决+停机呈报读数链(30 无实测背书、36 错抄自已退役的算例表)。推荐落文方向(措辞由文档批裁):整句删除,或改写为「格边长可读性以用户验收的现行画面为基准;结构钳制 [26,46] 管算式不越界」 | 反哺点通道:列进 `reports/iter<N>-反哺点-<日期>.md`(改哪节=`:144`、改成什么=删除或上述改写、依据=停机呈报+用户裁),用户裁决后归文档批落文。②v1 的「算例表改数」反哺条**作废**——`:148-152` 表已随 1cdef6ba 退役,无落点 |
|
||||
| game/tests/README.md(机械面——归写卡段维护) | 能力行「战斗屏三区几何与棋盘格边长(分辨率两档×四档板型)」v1 写卡段已入表;v2 判据换代不改能力名与真实入口 | 无增删(本行占位核对:批末核对表上名字与实况一致) |
|
||||
| design/gdd/systems/表现与支撑/HUD框架.md、design/art/art-bible.md §8.1/§8.2(已归一为指路) | 本批不改二者的任何陈述 | 无(本行占位——按规约查不出也要写明) |
|
||||
|
||||
## 6. 卡前文件结构图
|
||||
|
||||
| 文件 | 职责 | 新增/复用 | 行为改动? |
|
||||
|---|---|---|---|
|
||||
| game/presentation/views/board_view.gd | 修改:`set_cell_area` 内联算式抽成 `static func _cell_for(n, avail) -> int`,`set_cell_area` 改调;注释补「算式唯一落点」句 | 复用既有(抽自本文件既有代码,不新增文件/类) | 否(算式逐位相同——对照表行 2 的等价断言承载) |
|
||||
| game/probe/layout_probe.gd | 修改:门槛 36→30+注释改指 battle.md;新增 board_view 零尺寸前置与 13/14 板格边长推定断言 | 修改 | 是(守卫面变化——对照表行 1/4) |
|
||||
| game/tests/unit/core/board_gen_reward_test.gd | 修改:格边长冒烟循环扩四档板型+板型一致断言+算式单点等价断言 | 修改 | 是(测试面——对照表行 2/3) |
|
||||
| game/tests/README.md | 修改:能力清单加一行+覆盖域表 HUD框架行补名 | 修改 | 否(机械面文档,写卡段同批完成) |
|
||||
| game/presentation/views/board_view.gd | 修改:`set_cell_area` 内联算式抽成 `static func _cell_for(n, avail) -> int`,`set_cell_area` 改调;注释补「算式唯一落点」句 | 复用既有(抽自本文件既有代码,不新增文件/类/成员) | 否(算式逐位相同——对照表行 2 的等价断言承载) |
|
||||
| game/probe/layout_probe.gd | 修改:删 `:15` MIN_CELL 常量;`:93-95` 阈值断言换等价断言;`:44-45` PASS 消息改写并附 13/14 推定读数;新增 board_view 零尺寸前置与推定有效性判据 | 修改(v1 WIP 的探针件按本卡返工——v1 的「30 阈值+推定 ≥30」形态作废) | 是(守卫面换代——对照表行 1/4) |
|
||||
| game/tests/unit/core/board_gen_reward_test.gd | 修改:格边长冒烟循环扩四档板型+板型一致断言+算式单点等价断言 | 修改(v1 WIP 原样复用) | 是(测试面——对照表行 2/3) |
|
||||
|
||||
不触碰:`board_zone_view.gd`、`ui_assembler.gd`、`data/tables/board_gen.tres`、全部 `core/` 与 `data/` 代码、其余探针与测试套件。
|
||||
不触碰:`board_zone_view.gd`、`ui_assembler.gd`、`data/tables/board_gen.tres`、`data/tables/battle_layout.tres`、全部 `core/` 与 `data/` 代码、`game/tests/README.md`(v1 已入表)、其余探针与测试套件。
|
||||
|
||||
## 7. 任务卡 T0..T4
|
||||
|
||||
### 7.1 T0——读数重锚与取档对账(估时 0.1 个工作日)
|
||||
|
||||
- [ ] 按 T0 时点 master 重测重锚 §2 全部行号:`layout_probe.gd:15`/`:92-94`/`:27`/`:31`、`board_view.gd:34`/`:37`/`:191-209`/`:250`、`board_zone_view.gd:91-92`、`board_gen_reward_test.gd:53-69`。
|
||||
- [ ] 按 T0 时点 master 重测重锚 §2 全部行号:`layout_probe.gd:15`/`:31`/`:44-45`/`:93-95`、`board_view.gd:206-215`、`board_zone_view.gd:91-92`、`board_gen_reward_test.gd:53-69`。
|
||||
- [ ] 四档取档复核:对 `db.combat.board_gen.resolve_row(L, D)` 逐组取 (1,0)(2,0)(3,0)(3,9),实测返回 `board_width` 依次为 10/12/13/14——不符=L3 停卡退回写卡段。
|
||||
- [ ] `battle_layout.tres` 五字段读数与 `battle.md:137-146` 现状句确认(`:144` 30px 句仍在位=预期,本批不碰,§5 反哺承载;若已被文档批提前退役亦不阻塞——本卡判据零依赖该句)。
|
||||
- [ ] 改前基线读数(孤立验证):`python tools/gdstyle_gate.py`(board_view.gd `max-public-methods` 实测 27 持平)+单件跑 `board_gen_reward_test`(绿)+单件跑 `layout_probe`(两档绿)。三条读数进实现报告 T0 节。
|
||||
- 取用:本卡 §2。产出:重锚后的行号与三份改前读数(T1–T4 对拍基准)。
|
||||
|
||||
### 7.2 T1——算式单点提取(估时 0.15 个工作日)
|
||||
|
||||
- [ ] `board_view.gd` 新增 `static func _cell_for(n: int, avail: Vector2) -> int`,函数体=`:195-199` 五行算式逐字搬入(`SEP`/`DEPTH_PX` 仍读本文件既有常量,`clampi(..., 26, 46)` 留在该函数内),返回 `int`。
|
||||
- [ ] `set_cell_area` 的 `:194-199` 六行替换为 `_cell = float(_cell_for(maxi(_board.width, _board.height), avail))`;`:200-209` 副作用尾链一字不动。
|
||||
- [ ] `:189-190` 注释块补一句:算式唯一落点=`_cell_for`(探针与单元测试共用);名字带下划线是 S13 `max-public-methods` 27 顶格的约束,禁改公开名。
|
||||
- [ ] `board_view.gd` 新增 `static func _cell_for(n: int, avail: Vector2) -> int`,函数体=`:210-214` 五行算式逐字搬入(`SEP`/`DEPTH_PX` 仍读本文件既有常量,`clampi(..., 26, 46)` 留在该函数内),返回 `int`。
|
||||
- [ ] `set_cell_area` 的 `:209-214` 六行替换为 `_cell = float(_cell_for(maxi(_board.width, _board.height), avail))`;`:215` 起副作用尾链一字不动。
|
||||
- [ ] `:204-205` 注释块补一句:算式唯一落点=`_cell_for`(探针与单元测试共用);名字带下划线是 S13 `max-public-methods` 27 顶格的约束,禁改公开名。
|
||||
- [ ] 孤立验证:单件跑 `board_gen_reward_test`(既有四套断言全绿=算式等价性证明)+`python tools/gdstyle_gate.py`(board_view.gd 各键持平,`max-public-methods` 仍 27)。
|
||||
- 取用:T0 读数。产出:`BoardView._cell_for(n: int, avail: Vector2) -> int`(公开静态调用面,T2/T3 逐字消费)。
|
||||
- 取用:T0 读数。产出:`BoardView._cell_for(n: int, avail: Vector2) -> int`(调用面,T2/T3 逐字消费)。
|
||||
|
||||
### 7.3 T2——探针门槛与最大板推定(估时 0.1 个工作日)
|
||||
### 7.3 T2——探针阈值退役与判据换锚(估时 0.1 个工作日)
|
||||
|
||||
- [ ] `layout_probe.gd:15` 改 `const MIN_CELL := 30.0`,注释改为「可读下限 30px(battle.md §棋盘格尺寸公式;结构钳制 [26,46] 管算式不越界,是另一回事)」。
|
||||
- [ ] 顶部加 `const BoardViewScript := preload("res://presentation/views/board_view.gd")`(静态调用载体)。
|
||||
- [ ] `_check_one` 在既有格子断言之后追加两段:①board_view 零尺寸前置——`bv.size.x <= 0.0 or bv.size.y <= 0.0` 时记问题「board_view 零尺寸(可用面积不可信,格边长推定无依据)」;②推定断言——对 `n in [13, 14]` 取 `BoardViewScript._cell_for(n, bv.size)`,`< int(MIN_CELL)` 即记问题,消息含实板可用面积、板型、算出的格边长与下限。
|
||||
- [ ] 收口 PASS 消息补一句「13/14 板推定 ≥30px」。
|
||||
- [ ] 孤立验证:单件跑 `layout_probe`(两档全绿)+`tools/probe_gate.sh` 默认段(含本探针在内的默认段退出码 0)。
|
||||
- 取用:T1 `_cell_for`。产出:绿的两档探针日志(T4 对拍基准)。
|
||||
- [ ] 删除 `layout_probe.gd:15` `const MIN_CELL := 36.0` 整行。
|
||||
- [ ] `:93-95` 阈值断言替换为**等价断言**:读 `var b = bv.get("_board")`(内部字段直查——受控例外,对照表行 1 注明理由:实跑板型 N 无公开出口),`var n := maxi(b.width, b.height)`;断言 `cell == float(BoardViewScript._cell_for(n, bv.size))`,失败消息含实板可用面积、n、两值(生产写入 vs 单点返回)。文件顶部加 `const BoardViewScript := preload("res://presentation/views/board_view.gd")`(静态调用载体)。
|
||||
- [ ] `:44-45` PASS 消息改写:去 MIN_CELL 引用,改为「三区几何不变量全过+格边长等价成立(基座实读 %.0fpx)」。
|
||||
- [ ] `_check_one` 追加两段:①board_view 零尺寸前置——`bv.size.x <= 0.0 or bv.size.y <= 0.0` 时记问题「board_view 零尺寸(可用面积不可信,推定无依据)」;②**推定留痕**:对 `n2 in [13, 14]` 取 `var est := BoardViewScript._cell_for(n2, bv.size)`,随 PASS 打印「13 板推定 %dpx/14 板推定 %dpx」留痕(实现报告对拍 §2 第 7 条锚点读数 30/28;对拍不一致=§9 L3 #2 呈报,禁实现侧改锚)。
|
||||
- [ ] 孤立验证:单件跑 `layout_probe`(两档全绿,PASS 行含推定读数)+`tools/probe_gate.sh` 默认段退出码 0+`grep -rn "MIN_CELL" game/` 零命中。
|
||||
- 取用:T1 `_cell_for`。产出:绿的两档探针日志含四档推定读数(T4 对拍基准)。
|
||||
|
||||
### 7.4 T3——格边长冒烟扩四档(估时 0.1 个工作日)
|
||||
|
||||
- [ ] `_smoke_layout_cell_formula` 的 `:57` 循环集改为四档取样表:`[{L:1,D:0,n:10}, {L:2,D:0,n:12}, {L:3,D:0,n:13}, {L:3,D:9,n:14}]`(按 §2 第 6 条的实表取档)。
|
||||
- [ ] 每档追加两条断言:①板型一致——`maxi(b.width, b.height) == 取样 n`(表改动导致取样落错档时红);②算式单点——`int(cell) == BoardViewScript._cell_for(n, avail)`(`set_cell_area` 写入值与纯函数返回同值)。
|
||||
- [ ] 既有两条断言(网格高 ≤ 可用高−24、格边长 ∈ [26,46])逐字保留,仅把消息前缀从 `L%d` 扩成 `L%d D%d`;`:60` 样本 `Vector2(1036, 460)` 不改(本卡把「真实可用面积」的可读面交给探针,样本只承担算式不溢出面)。
|
||||
- [ ] 既有两条断言(网格高 ≤ 可用高−24、格边长 ∈ [26,46])逐字保留,仅把消息前缀从 `L%d` 扩成 `L%d D%d`;`:60` 样本 `Vector2(1036, 460)` 不改(样本只承担算式不溢出面,真实可用面积守卫归探针 V1/V4)。
|
||||
- [ ] 孤立验证:单件跑 `board_gen_reward_test`(四档全绿)。
|
||||
- 取用:T1 `_cell_for`、T0 取档对账。产出:四档冒烟日志(T4 对拍基准)。
|
||||
|
||||
### 7.5 T4——批末收口与产出物落位(估时 0.05 个工作日)
|
||||
|
||||
- [ ] 批末代码域闸:`tools/run_all_gates.sh --code` 全绿(本批改动含 `game/` 下非 `.md` 行为载体 → 代码域;02 单元与集成按关联档选跑 `board_gen_reward` 套件,冒烟/系统测试/静态扫描三件恒跑)。里程碑步出口跑一次全套;波内修复只做出红最小单元的最窄确认。
|
||||
- [ ] S13 键账对账:board_view.gd 各键持平(`max-public-methods` 27 不变、`max-class-variables` 32 不变、无 NEW 键);探针与测试不在 S13 扫描面。
|
||||
- [ ] 批末代码域闸:`tools/run_all_gates.sh --code` 全绿(本批改动含 `game/` 下非 `.md` 行为载体 → 代码域)。里程碑步出口跑一次全套;波内修复只做出红最小单元的最窄确认。
|
||||
- [ ] S13 键账对账:board_view.gd 各键持平(`max-public-methods` 27 不变、`max-class-variables` 31 不变、无 NEW 键);探针与测试不在 S13 扫描面。
|
||||
- [ ] **产出物落位卡**(轻闸全绿后、合并前写齐,方算收口):
|
||||
- `reports/iter<N>-实现报告-<日期>.md`——各卡状态+T0 三份改前读数与各卡改后读数对拍+探针实读的 `board_view.size`(两档视口)与 L1 格边长实测值+13/14 推定值+实机目检总清单(登记不阻塞:「第三关 14×14 板格面数字清楚可辨」一项,时间由用户自定)。
|
||||
- `reports/iter<N>-反哺点-<日期>.md`——§5 同步面第 1 行(battle.md 算例表 vs 实测)逐条有落点。
|
||||
- `reports/iter<N>-实现报告-<日期>.md`——各卡状态+T0 三份改前读数与各卡改后读数对拍+**锚点读数留档**(两档视口 × 四板型实读/推定全表=§2 第 7 条,未来批次对照基准)+实机目检总清单(登记不阻塞:「第三关 14×14 板格面数字清楚可辨」一项——2026-11-01 用户已实际背书现行画面,登记照留)。
|
||||
- `reports/iter<N>-反哺点-<日期>.md`——§5 同步面第 1 行(battle.md `:144` 退役)有落点。
|
||||
- `reports/iter<N>-验收审计-<日期>.md`——独立验收审计(未参与实现的会话或子代理执行,未过不得合并)。
|
||||
- 取用:T1–T3 全部产出。产出:代码域闸回执+三份 reports/ 产出物。
|
||||
|
||||
## 8. 验证闸(改动—验收对照表)
|
||||
|
||||
本批三处改动全部落在守卫面(探针门槛/测试覆盖/算式落点),游戏行为零变化,故无新玩法验收;用户目检一项登记不阻塞(T4)。对照表 5 行对应 §1 完成定义第 1–5 条。
|
||||
本批三处改动全部落在守卫面(阈值退役/算式落点/测试覆盖),游戏行为零变化,故无新玩法验收;用户目检一项登记不阻塞(T4)。对照表 5 行对应 §1 完成定义第 1–5 条。
|
||||
|
||||
| # | 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 1 | 探针可读门槛与 battle.md 对齐(36→30) | `layout_probe.gd:15` 常量与注释;`:92-94` 断言文本沿用 | 「layout_probe 两档几何不变量」`layout_probe.gd:_ready`(尾缀〔格边长 V1〕) | 探针 | `godot --headless --path game res://probe/layout_probe.tscn` | 探针经真实战斗屏装配读到 `board_view.cell_size` 且 ≥30px(下限判据直接作用于实机取值) | 新增:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 2 | 算式单点(`_cell_for`) | `board_view.gd:191-209` 抽函数并改调;`:189-190` 注释补唯一落点句 | 「格边长算式单点等价」`board_gen_reward_test.gd:_smoke_layout_cell_formula`(尾缀〔格边长 V2〕) | 单元 | `godot --headless --path game --script res://tests/unit/core/board_gen_reward_test.gd` | `set_cell_area` 写入的 `_cell` 与 `BoardView._cell_for(n, avail)` 返回值逐档严格相等(同一事实两路读取,分叉即红) | 新增:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 3 | 13×13/14×14 进入冒烟 | `board_gen_reward_test.gd:53-69` 循环集改四档取样+板型一致断言 | 「格边长冒烟四档板型」同函数(尾缀〔格边长 V3〕) | 单元 | 同上 | 13/14 两档首次被断言:取档尺寸与实表一致、网格高 ≤ 可用高−24、格边长 ∈ [26,46](此前从未执行) | 新增:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 4 | 最大板可读推定(实板可用面积) | `layout_probe.gd:_check_one` 新增 board_view 零尺寸前置+`n∈{13,14}` 推定断言 | 「最大板格边长推定」同探针(尾缀〔格边长 V4〕) | 探针 | `godot --headless --path game res://probe/layout_probe.tscn` | 以探针实读 `board_view.size` 代入 `_cell_for(13/14, size)` 得 ≥30px(真实容器尺寸下的最大板可读面——不推关即可覆盖) | 新增:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 5 | 批末收口 | 全批 | 代码域闸:`tools/run_all_gates.sh --code` | 全量闸 | `tools/run_all_gates.sh --code` | 所选域全绿回执(`game/tests/.gates/receipt.json`) | 新增:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 1 | 探针阈值退役+格边长接线守卫(等价判据) | `layout_probe.gd:15` 删常量;`:93-95` 阈值断言换 `cell == _cell_for(n, bv.size)` | 「layout_probe 两档几何不变量」`layout_probe.gd:_ready`(尾缀〔格边长 V1〕) | 探针 | `godot --headless --path game res://probe/layout_probe.tscn` | 实读 `cell_size`(生产经 `set_cell_area` 真实写入)与 `_cell_for` 同输入返回严格相等——生产停止调单点算式即红;`grep -rn "MIN_CELL" game/` 零命中 | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 2 | 算式单点(`_cell_for`) | `board_view.gd:206-215` 抽函数并改调;`:204-205` 注释补唯一落点句 | 「格边长算式单点等价」`board_gen_reward_test.gd:_smoke_layout_cell_formula`(尾缀〔格边长 V2〕) | 单元 | `godot --headless --path game --script res://tests/unit/core/board_gen_reward_test.gd` | `set_cell_area` 写入的 `_cell` 与 `BoardView._cell_for(n, avail)` 返回值逐档严格相等(同一事实两路读取,分叉即红) | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 3 | 13×13/14×14 进入冒烟 | `board_gen_reward_test.gd:53-69` 循环集改四档取样+板型一致断言 | 「格边长冒烟四档板型」同函数(尾缀〔格边长 V3〕) | 单元 | 同上 | 13/14 两档首次被断言:取档尺寸与实表一致、网格高 ≤ 可用高−24、格边长 ∈ [26,46](公式自身结构钳制——既有断言逐字保留) | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 4 | 最大板推定守卫(实板可用面积,留痕型) | `layout_probe.gd:_check_one` 新增零尺寸前置+`n∈{13,14}` 推定(读数打印) | 「最大板推定留痕」同探针(尾缀〔格边长 V4〕) | 探针 | `godot --headless --path game res://probe/layout_probe.tscn` | ①零尺寸前置(size ≤ 0 记红);②推定读数打印并与实现报告留档的锚点读数(基座档 30/28px)逐值对拍,不一致=§9 L3 #2 呈报(禁实现侧改锚) | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
| 5 | 批末收口 | 全批 | 代码域闸:`tools/run_all_gates.sh --code` | 全量闸 | `tools/run_all_gates.sh --code` | 所选域全绿回执(`game/tests/.gates/receipt.json`) | 既有:战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) |
|
||||
|
||||
**测试削弱申报**(实现期允许的旧断言改动全集,超出即审计判红):
|
||||
1. **探针门槛 36→30=阈值放宽**,依据 battle.md `:144`「可读下限 30px」(旧值 36 是 12×12 旧锚点的误用,探针实跑从未触及 30–35px 区间,等于该门槛对大板无效)。补偿=第 4 行新增推定断言与第 3 行四档冒烟——原门槛守不住的面由两者接管。
|
||||
2. 第 3 行循环集从 2 档扩到 4 档=纯增量;`avail` 样本值不改;既有两条断言(网格高、区间)逐字保留。
|
||||
3. 探针新增断言=纯增量,既有格子断言与两档视口表不改。
|
||||
4. 显式禁止:删任何旧断言、放宽区间 [26,46]、把格子读取从 `cell_size`/`_cell` 换成别的入口。
|
||||
1. **删除探针阈值断言**(`:93-95` `cell < MIN_CELL` 记红)=人造阈值退役的执行面(v1 申报的「36→30 放宽」作废,v2 直接删除)。补偿=行 1 等价断言(同测量对象上严格相等,强于区间阈值——生产接线断开即红)+行 3 结构钳制四档+行 4 读数留痕对拍;目检项「第三关 14×14 板格面数字清楚可辨」继续登记(2026-11-01 用户已实际背书现行画面)。
|
||||
2. `:44-45` PASS 消息改写=文案随判据换代,非削弱。
|
||||
3. 行 3 循环集从 2 档扩到 4 档=纯增量;`avail` 样本值不改;既有两条断言逐字保留。
|
||||
4. 显式禁止:恢复任何人造阈值(30/36 及变体)、删任何旧断言、放宽区间 [26,46]、把格子读取从 `cell_size`/`_cell` 换成别的入口。
|
||||
|
||||
**独立验收审计**:入口与报告=`reports/iter<N>-验收审计-<日期>.md`;审计方=未参与实现的会话或子代理,逐行核对对照表两端、抽查判据绑定面是否绑在被测改动特有的可观测面(`cell_size`/`_cell` 取值与 `_cell_for` 返回)、核对削弱申报、确认全文无变异/撤销类取证;未过不得合并。
|
||||
**独立验收审计**:入口与报告=`reports/iter<N>-验收审计-<日期>.md`;审计方=未参与实现的会话或子代理,逐行核对对照表两端、抽查判据绑定面是否绑被测改动特有的可观测提交面(`cell_size`/`_cell` 取值与 `_cell_for` 返回)、核对削弱申报、确认全文无变异/撤销类取证、**并核查全仓无人造阈值回归**(grep 30/36 阈值形态);未过不得合并。
|
||||
|
||||
## 9. 异常分级
|
||||
|
||||
- **L1 自救**:单件跑红→定位该件最小单元修后重跑;探针单件超时→孤立复跑该件;`--only` 选跑零命中(用法错 exit 2)→修正选词重跑。
|
||||
- **L2 记录继续**:同一红连续 3 次同因→在实现报告「实现决定记录」记因后继续最窄确认。
|
||||
- **L3 停机写报告等用户**:
|
||||
1. **机检预算互斥=上游缺陷停卡退回写卡段**——`gdstyle_gate` 出 NEW 键或 `board_view.gd|quality/max-public-methods` 升到 28(即 `_cell_for` 的下划线被去掉);本批零新增文件、零新增成员,任何键恶化都不许改基线换绿,禁开豁免。
|
||||
2. **实板可读面本身不达标**——探针实测 L1 `cell_size` < 30,或实板可用面积代入 13/14 后 < 30。这是产品面问题(不是断言错),停卡呈报,禁调低下限、禁换样本凑绿。
|
||||
1. **机检预算互斥=上游缺陷停卡退回写卡段**——`gdstyle_gate` 出 NEW 键或 board_view.gd `max-public-methods` 升 28/`max-class-variables` 升 32(即 `_cell_for` 的下划线被去掉或钳制界被提取为成员);禁改基线换绿,禁开豁免。
|
||||
2. **锚点冲突复现**——实现期任何一方(用户目检/新读数)推翻 §2 第 7 条现行渲染锚点,或有人再提人造阈值方案,或探针推定读数与 §2 第 7 条留档读数对拍不一致且复测排除环境因素;停卡呈报,禁实现侧自裁。
|
||||
3. **四档取档对不上**——`resolve_row(1,0)/(2,0)/(3,0)/(3,9)` 实测尺寸与 §2 第 6 条不符(表已改而本卡未跟上)。
|
||||
4. **算式等价性破**——T1 后既有四套断言出现改前不存在的红,说明提取改变了算式语义。
|
||||
5. **battle_layout.tres 被并发批改动**——T0 实读五字段与本卡 §2 第 8 条不符(布局几何单点化批之后又有布局批落地),读数锚点须重测重锚,停卡呈报。
|
||||
|
||||
## 10. 代拍板白名单(逐条列,超清单记实现报告「实现决定记录」)
|
||||
|
||||
1. `_cell_for` 内部局部变量名与注释措辞(算式、常量、clamp 数值不变)。
|
||||
2. 四档取样表用字典数组还是三元组数组(取值与断言不变)。
|
||||
3. 探针推定断言与零尺寸前置的失败消息文案、PASS 消息措辞(判据不变)。
|
||||
3. 探针推定留痕与零尺寸前置的失败消息文案、PASS 消息措辞(判据不变)。
|
||||
4. 尾缀〔格边长 V1〕–〔格边长 V4〕的字样编排(含义不变)。
|
||||
5. `BoardViewScript` 常量名(preload 载体命名)。
|
||||
6. 探针内读取板型 N 的取值写法(`bv.get("_board")` 后取 `maxi(width, height)` 的具体表达式形态——直查事实与判据不变)。
|
||||
|
||||
## 11. 待裁点
|
||||
|
||||
**零待裁点,开工门=U0。** 2026-10-30 用户三项裁定已定案:①探针不扩到 L3(推关成本与红因混淆,最大板改走推定断言);②最紧档 14×14 的断言落两处(单元四档+探针实板推定);③算式提取用 `_cell_for` 私有名(§2 第 5 条 S13 实测依据)。编批由迭代编排段定。
|
||||
**零待裁点,开工门=U0。** 2026-11-01 用户三项裁定已定案:①锚点=用户验收的现行渲染值——基座档 14×14=28px 达标,battle.md「可读下限 30px」与探针 36px 退役;②探针判据换锚=等价+结构钳制+读数留痕,禁人造阈值;③手抄常量 `MIN_CELL` 删除、禁第二份阈值抄本。v1 的「探针不扩到 L3」「算式提取用 `_cell_for` 私有名」两项裁定沿用。battle.md `:144` 句退役的落文走反哺点通道(文档批,用户发令),不阻塞本批。编批由迭代编排段定。
|
||||
|
||||
## 12. 落位与可复用性预检
|
||||
|
||||
**复用面**:本批零新增文件、零新增类。`_cell_for` 抽自 `board_view.set_cell_area` 既有内联算式——不能只留在原处内联,是因为探针要在「非当前板型(13/14)× 真实可用面积」上求值、单元测试要在四档板型上求值,内联形态无法复用,复写算式就是造第二口径(正是本卡要消灭的缺陷形态)。探针与测试的既有工具件(`probe_ui_util.gd`、`test_kit.gd`)与本批职责无关,不复用也不扩展。
|
||||
**复用面**:本批零新增文件、零新增类、零新增成员。`_cell_for` 抽自 `board_view.set_cell_area` 既有内联算式——不能只留在原处内联,是因为探针要在「非当前板型(13/14)× 真实可用面积」上求值、单元测试要在四档板型上求值,内联形态无法复用,复写算式就是造第二口径。**worktree iter46 未提交 WIP 三件的复用判定**:`board_view.gd` 算式提取与 `board_gen_reward_test.gd` 四档冒烟两件=按本卡原样复用(等价性已证:单元 62→74 checks 全绿);`layout_probe.gd` 件=**返工**(其 v1 形态「MIN_CELL→30+推定 ≥30 断言」带有人造阈值,与本卡契约①③冲突——按 §7.3 重做)。探针与测试的既有工具件(`probe_ui_util.gd`、`test_kit.gd`)与本批职责无关,不复用也不扩展。
|
||||
|
||||
**唯一面**:算式唯一落点=`BoardView._cell_for`;可读下限 30px 的唯一代码判据面=`layout_probe.MIN_CELL`(文本出处=battle.md `:144`);四档板型唯一事实源=`board_gen.tres`(测试按 (L,D) 取行,不复制取值)。2026-10-30 实查 `game/` 下无 `cell_for`/`_cell_for` 同名或同义函数,无第二落点。
|
||||
**唯一面**:算式唯一落点=`BoardView._cell_for`;四档板型唯一事实源=`board_gen.tres`(测试按 (L,D) 取行,不复制取值);分区几何唯一事实源=`battle_layout.tres` 五字段(本批只读);**格边长无阈值判据面**——2026-11-01 起本域不存在可读下限常数,唯一结构性界限=公式内 `clampi(..., 26, 46)`(不外提)。2026-11-01 实查 `game/` 下无 `cell_for`/`_cell_for` 同名或同义函数,无第二落点;`MIN_CELL` 仅 `layout_probe.gd:15` 一处(本批删除后 grep 零残留为证)。
|
||||
|
||||
**分层与交互面**:`_cell_for` 是无状态纯函数——零成员读写、零信号、零 RNG、零 UI 依赖、零 `load()`;调用路径=`set_cell_area`(生产)/探针 `_check_one`(经脚本常量静态调用)/单元测试(同前)。preservation:不新增跨层依赖,Core 零 UI 红线零触碰(本批不触 `core/`)。
|
||||
|
||||
@@ -172,12 +178,13 @@
|
||||
|
||||
**新件三查**:本批零新增文件——三查不适用(写「无新增件」)。
|
||||
|
||||
**存量触面一查**:触碰的存量件为 `board_view.gd`(S13 扫描面内)与探针/测试两件(不在 S13 扫描面)。`board_view.gd` 预期:`quality/max-public-methods` 保持 **27**(私有静态不计数,§2 第 5 条实测)、`quality/max-class-variables` 保持 32、`quality/max-branches|_paint_cell` 等函数级键持平(本批不增分支、不增成员、不增局部变量——`set_cell_area` 局部变量反而减少)。达成手段:算式整体搬出,函数体只留一行调用。
|
||||
**存量触面一查**:触碰的存量件为 `board_view.gd`(S13 扫描面内)与探针/测试两件(不在 S13 扫描面)。`board_view.gd` 预期:`quality/max-public-methods` 保持 **27**(私有静态不计数,§2 第 5 条实测)、`quality/max-class-variables` 保持 **31**(零新增成员——钳制界禁提取为常量,§3 契约④)、`quality/max-branches|_paint_cell` 等函数级键持平(本批不增分支、不增成员、不增局部变量——`set_cell_area` 局部变量反而减少)。达成手段:算式整体搬出,函数体只留一行调用。
|
||||
|
||||
**指标例外申报**:无。
|
||||
|
||||
## 14. 源码级断言与探针契约面的随批义务(防漏项清单)
|
||||
|
||||
1. `layout_probe` 的既有两档视口表(`VIEWPORTS`)与三条几何不变量(三区非零/不越视口/互不重叠/view 含于 D 区)本批零改动——T2 只追加断言,不改判据。
|
||||
2. `board_view` 的对外只读出口(`cell_size`,`board_view.gd:93-95`)是探针取值面,本批不动;测试内部读 `_cell`(测试惯例已如此,`board_gen_reward_test.gd:63`),不改为公开出口。
|
||||
3. `game/tests/README.md` 能力行由写卡段同批入表(本卡成文时已落),实现批不写该文件;批末核对表上名字与实况一致。
|
||||
1. `layout_probe` 的既有两档视口表(`VIEWPORTS`)与三条几何不变量(三区非零/不越视口/互不重叠/view 含于 D 区)本批零改动——T2 只换代格边长判据,几何判据与档位表一字不动。
|
||||
2. `board_view` 的对外只读出口(`cell_size`)是探针取值面,本批不动;测试内部读 `_cell`、探针内部读 `_board`(板型 N 取值——受控例外,对照表行 1 已注明理由:N 无公开出口),不为此新开公开出口。
|
||||
3. `battle_layout.tres` 五字段为分区几何唯一事实源(1cdef6ba 起),本批只读;任何布局字段改动归设计批。
|
||||
4. `game/tests/README.md` 能力行由 v1 写卡段同批入表,v2 名字与入口不变,实现批不写该文件;批末核对表上名字与实况一致。
|
||||
+359
-208
@@ -1,308 +1,459 @@
|
||||
# 需求卡片:营地场景图新建批(交互式营地 · 七物件绑定 · 四柜台拆解)· 营地交互重做卡④
|
||||
|
||||
- 版本:**v2.3**(2026-10-21 用户令:**退回美术设计段**——美术轨凭据缺(P1–P5 未销号),按 req-card 第〇步不具写卡资格;**本卡非有效卡**,内容保留作美术设计段输入(Q4/Q5/Q6/Q8 已裁记录+七物件绑定表+七物件绑定现状定性),美术设计闭合(样张过审+art-bible 条款版本)后**重立卡**,再谈编迭代。🔴 归属纪律:卡只登记缺口与已有裁断,前置由谁解决/何时解决/设计稿与素材由谁产出**由用户定**(美术/设计线=用户自立批,铁律 2),Agent 不代跑不代产)
|
||||
- 来源:[需求澄清-营地交互重做-2026-10-18.md](需求澄清-营地交互重做-2026-10-18.md)(唯一事实源:①目标体验原话、②参照与反参照、③非目标、④目标结构树+纵深稿、⑤裁决 5/6/7/8/10、⑥验收方式、⑦切批原则④、⑧遗留)+ [camp.md](../design/gdd/ux/camp.md) v1.5 + [art-bible](../design/art/art-bible.md) §6.2/§7.5
|
||||
- 版本:**v3.2(现行有效卡)**。留痕:2026-10-21 用户令退回美术设计段待闭合;2026-10-31 用户令重立——美术设计已闭合(样张过审+art-bible 条款版本),据 req-card 第〇步重立为现行有效卡,零设计待裁点;2026-11-01 grilling+godot-master 双审后用户令修订(v3.1)——§0.3 四道代码段开工门裁断销号、§2 换新盘面、Godot 风险项落卡;2026-11-01 用户裁机检预算互斥停机呈报(v3.2)——营地六句柄改落 `ui_camp_modals.gd` 子容器(卡⑥ 前置建件),`ui_modals.gd` 类变量 14→14 零基线,存量触面一查补列 ui_modals/ui_registry/main_ui_build 三件,全量分域分家登记待办清单另立批。
|
||||
- 来源:[需求澄清-营地交互重做-2026-10-18.md](需求澄清-营地交互重做-2026-10-18.md)(目标体验原话/目标结构树+纵深稿/裁决 5·6·7·8·10/验收方式/切批原则④)+ 样张过审(2026-10-31 用户裁定,清单 [artwork/candidates/_终稿裁定-2026-10-31.txt](../artwork/candidates/_终稿裁定-2026-10-31.txt):各素材第一张样本稿为终稿、保留全部待选稿)+ [art-bible.md](../design/art/art-bible.md) v3.31 §6.2(营地场景 10 层口径)(**唯一事实源**:样张过审 2026-10-31 + art-bible.md v3.31 §6.2;配套 [camp.md](../design/gdd/ux/camp.md) v2.2/[camp-scene-prompts.md](../design/art/camp-scene-prompts.md) v1.2/[asset-path-map.md](../design/art/asset-path-map.md)/[art-assets-checklist.md](../design/art/art-assets-checklist.md) §3.5 同步;需求澄清为目标体验事实源)
|
||||
- 归属:呈现层+美术线(`game/presentation/` + 场景素材)——营地交互重做五卡之四,**最大件**
|
||||
- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁)
|
||||
- 开工门:**前置条件销号后进代码实现**(设计前置闸纪律不变:设计定稿前禁 `/iter` 开本卡代码段——美术素材线按铁律 2 走自立批并行推进,不占迭代位);前置解决清单见下方
|
||||
- 开工门:**零设计待裁点,开工门=U0**;编入迭代由 iter-plan 段发令,代码段按 `/iter` 开工,代码段开工门见 §0(不阻塞本卡作为有效卡与编迭代)
|
||||
|
||||
## 🔧 状态:已退回美术设计段 · 非有效卡(2026-10-21 用户令;美术设计闭合后重立卡,再谈编迭代)
|
||||
## 🔧 状态:现行有效卡(v3.1,2026-11-01 双审修订)
|
||||
|
||||
**背景**:本卡是新内容+新美术件需求,按 2026-10-10 用户立规(req-card 设计前置检查),设计定稿前不进代码实现。v1.x 曾用「待裁点」覆盖设计缺项(渠道/规格/设计稿/参照物),违立规;v2.0 一度按「回设计段」移出序列;v2.1 一度把「批内解决」执行成「Agent 代跑设计稿」——**v2.2 用户令终订:本卡是批内成员,前置条件在批内登记、逐项销号;但由谁解决、何时解决由用户定,美术/设计线是用户自立批(铁律 2),Agent 不代跑不代产**。设计前置闸纪律不变(设计定稿前禁 `/iter` 开本卡代码段),执行方式是「批内销号」而非剔除,也非 Agent 代劳。
|
||||
本卡设计线已闭合,凭据见 §0「重立凭据」:样张过审(2026-10-31)+ art-bible v3.31 §6.2 条款版本齐备。2026-11-01 grilling+godot-master 双审通过、§0.3 四道代码段开工门全部裁断销号(用户照双审推荐采纳),设计待裁点与开工门清零;已编入迭代 47(roadmap.md 迭代总表,与卡⑤ 同波,卡⑤ 随本卡代码波之后)。属呈现层+美术线,五卡之四。
|
||||
|
||||
**前置条件销号清单**(五项重启条件转为批内登记项):
|
||||
**归属纪律**:本卡只登记代码段开工门与已裁断。前置由谁解决、何时解决、设计稿与素材由谁产出由用户定——美术/设计线=用户自立批(铁律 2),Agent 不代跑、不代产、不自行开工设计稿。素材终稿落 `game/assets/art/` 属实现段 T1/`asset-ingest` 第 3 步,不属写卡门(用户 2026-10-31 令:只生成素材、不做后处理;2026-11-01 用户裁:后处理授权随 /iter 开工令一并生效,见 §0.3-4)。
|
||||
|
||||
| # | 前置条件 | 归属 | 状态(2026-10-18) | 解决路径 |
|
||||
| -- | ------------------------- | -------------------------- | -------------- | ----------------------------------------------------------------------------------- |
|
||||
| P1 | Q1 美术渠道裁定(A/B) | **用户**(一句话裁) | ⬜ 待裁 | 阻塞场景方向稿与规格路径分支;裁后由用户定推进方式 |
|
||||
| P2 | 像素规格有着落 | 用户线(裁断已在卡:Q6 甲) | 🟨 半消 | Q6 甲已裁:Q1 裁 A 时用过渡规格(1280 工程档+烛光黄 #F6C667/木色 #8A5A34);终档归样张批冻结清单后置换(反哺点登记)——执行由用户线定 |
|
||||
| P3 | 点选反馈设计稿(悬停高亮/提示文案/可点区域判定) | **用户线**(美术/设计归用户自立批——铁律 2) | ⬜ 未启动 | 澄清⑧3 已登记缺口;产出方式有备(Q8 甲=出稿呈裁)但**未受命开工**——2026-10-18 曾越权起草 v0.1,已按用户令撤回;待用户方向 |
|
||||
| P4 | 参照物 | **用户**后续找 | ⬜ 待补 | 找到后与纵深稿对表;结构性冲突=呈报订正构图,禁批内私改 |
|
||||
| P5 | GDD/art-bible 营地条款落文 | 文档批(P1–P4 定稿后,用户发令) | ⬜ 未启动 | camp.md 整体改版+art-bible §6.2/§7.5/§2.8 改版 |
|
||||
**批内批次次序(铁律 2:美术素材走自立批、不占迭代位;先产图后改代码)**:美术设计已闭合(样张过审)→ 场景素材后处理与入库(自立批,产物 `artwork/`→`game/assets/art/scene/`)→ 本卡代码段 `/iter`(与卡⑤ 同波)。工程面 ①②③ 代码已随迭代 33 合回(卡①②③ 已按吸收即死退役);④⑤ 未编排,编入哪一迭代由用户经迭代编排段发令。
|
||||
|
||||
**批内批次次序(铁律 2:美术素材走自立批、不占迭代位;先产图后改代码)**:P1–P4 销号(设计定稿)→ 场景图美术产出(自立批,素材线并行推进,产物归档 artwork/→game/assets/art/)→ P5 文档落文 → 本卡代码段 `/iter`(与 ⑤ 同波)。工程面 ①②③ 代码在美术线推进期间并行开发、先行交付(③ 进档落点按 Q3 裁定乙暂行接现役 CampOverlay,本卡落地时改挂)——**四卡同在批内,分波收口,不是剔除**。
|
||||
## 0. 前置依赖与代码段开工门
|
||||
|
||||
**归属纪律(2026-10-18 用户令订正,v2.2)**:本卡只负责**登记前置缺口与已有裁断**;前置条件由谁来解决、何时解决、设计稿/素材由谁产出,**由用户定**——美术/设计线是用户自立批(铁律 2),Agent 不代跑、不代产、不自行开工设计稿。本卡曾越权起草点选反馈设计稿 v0.1(2026-10-18),已按用户令撤回删除;Q8(出稿呈裁)仅是「若用户发令出稿时的产出方式」预裁,非开工授权。
|
||||
### 0.1 重立凭据(已齐,非待裁点)
|
||||
|
||||
**已裁事项(2026-10-18 grilling 轮次)**:
|
||||
req-card 第〇步+卡头 2026-10-21 退回令口径=美术设计闭合(样张过审+art-bible 条款版本)。两样已齐:
|
||||
|
||||
- Q4=甲:最近冒险条带随四柜台拆解撤下,生涯.md P6 同批注销(代拍板留痕);
|
||||
- Q5=甲:ConfirmDialog 扩第三钮(继续上一段冒险/开始新冒险/取消,cancelled 恒=无变更退回营地);
|
||||
- Q6=甲:Q1 裁 A 时过渡尺寸档=现役 1280 工程档+烛光黄 #F6C667/木色 #8A5A34 既有规格,终档归样张批冻结后置换(反哺点登记);
|
||||
- Q8=甲:设计稿产出方式=批内出稿呈裁(方向稿先行纪律照旧——2~3 张低成本方向稿供选划,判完方向才精制);
|
||||
- Q3 设计稿只覆盖根态点选反馈;进界面后的叠层规则随承载形态裁定派生(独立全屏页=场景根隐藏/单一内页切换=场景根留底)。
|
||||
- **样张过审**=用户 2026-10-31 裁定「保留全部待选稿、各素材第一张样本稿为终稿、每个都还可以接受」(清单 `artwork/candidates/_终稿裁定-2026-10-31.txt`),用户准备在游戏内做最终审核。
|
||||
- **art-bible 条款版本**=`art-bible.md v3.31 §6.2`(营地场景 10 层口径;camp.md v2.2/camp-scene-prompts.md v1.2/asset-path-map.md/art-assets-checklist.md §3.5/评估报告同步)。
|
||||
|
||||
**仍待用户裁**:Q1 美术渠道 A/B(我的推荐:**A · CC0 改色**——06:23 已有配色规格、成本低、方向稿不受「从零构图」拖累;B 依赖规格清单输入且周期长。你说过不替你选,但我把推荐摊开了,等你一句 A 或 B,方向稿当天就能出);Q2 参照物(你后续找)。
|
||||
两样齐 ⇒ 重立卡判据齐,本卡为现行有效卡。P3/P5 等未销号项属**代码段开工门**,不阻塞重立卡。
|
||||
|
||||
## 0. 前置依赖与并行性(批内视角,v2.1)
|
||||
### 0.2 P1–P5 前置现状(已裁/已补项写进卡,不再当待裁点)
|
||||
|
||||
> 本卡在批内,前置条件解决中(见卡头销号清单)——本节描述批内并行关系,非排期承诺。
|
||||
| # | 前置条件 | 归属 | 现状 | 落点 |
|
||||
| -- | ------- | ---- | ---- | ---- |
|
||||
| P1 | Q1 美术渠道裁定(A/B) | 用户 | **已裁=B·插画级新产**(2026-10-22);✦ 渠道作者自跑远程生图管线,规格沿用 art-bible §6.2/§8.1/§8.2 既有裁决 | art-assets-checklist.md §3.5 |
|
||||
| P2 | 像素规格 | 用户线 | **Q6 甲过渡口径已裁**:现役 1280 工程档(1280×800)+烛光黄 #F6C667/木色 #8A5A34;2× 源档出图、最近邻降采样;终档归样张批冻结清单后置换(反哺点登记),执行归用户线 | 契约 8 |
|
||||
| P3 | 点选反馈设计稿(悬停高亮/提示文案/可点区域判定) | 用户线 | **已销号(2026-11-01 用户裁)**:销号口径=camp.md v2.2:35-37 四态规格即点选反馈设计稿(四态参数已钉死);剩余实质=七物件名牌文案与可点区域视觉,归 T2 域内(名牌文案按 §1 绑定表界面名逐字落、可点区域判定归 §9 白名单 3) | §0.3 |
|
||||
| P4 | 参照物 | 用户 | **已补**(2026-10-23)=`artwork/2026-10-23-营地场景/Gemini_Generated_Image_ykrc0nykrc0nykrc.jpg`,已进 camp-scene-prompts.md §1 登记为「作者提供的参照物」,与纵深稿对过表、围墙结构冲突已呈报;参照物只是参考图,保留 `artwork/`、不入 git、不入游戏目录 | camp-scene-prompts.md §1 |
|
||||
| P5 | GDD/art-bible 营地条款落文 | 文档批(用户发令) | **已销号(2026-11-01 用户裁)**:销号口径=形态落文完成(camp.md v2.2/art-bible v3.31 §6.2 已在盘);实装状态回填与 §7.5/§2.8 同步归 T6 反哺点义务(§5),非停机条件,实现批禁写 `design/` | §5 反哺点 |
|
||||
|
||||
- 卡③(选档界面)Q3 已裁乙:随①②③工程波先行时进档/新档暂行接现役 CampOverlay——**本卡代码波落地后,营地入口从现役 CampOverlay 改挂场景图,现役 CampOverlay 随之拆解退役**(卡③暂行接线与本次改挂的二次验证面在卡③ T2/实现报告登记)。
|
||||
- 卡⑤(ESC 浮窗与营地顶栏)落在本批新建的场景屏顶栏位——两卡触碰同一新屏,建议同批或卡⑤随后。**跨卡接口(v1.1 补全)**:①场景屏顶栏位(T2 预留);②**营地刷新单口**(T3 定义:各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成)——卡⑤ HUD 刷新挂该单口,非已退役的 `refresh_camp`;③ConfirmDialog 三钮化与消费方编排(T4,卡③ 契约 3 同款互指);④子界面返回钮承诺(T3)。
|
||||
- 美术线与代码线的批次关系:T1(素材产出)与 T2–T4(代码)可分批——素材先归档齐、代码后挂(用户批次归属裁,本卡不预占)。
|
||||
- 样张线关系:**营地屏的整屏样张是 art-bible §1.4 四屏之一,现列 06「待设计」排队行**(样张批 Q2 甲案:本批只判战斗屏,余三屏排队)——本卡**不跑整屏样张闸、不替代样张批**,只按既有约束(§3 契约 7/9)生产与自检;营地屏样张义务留原排队行(反哺点注记)。文档既定序列(排队行措辞「终稿后再出样」)本就终稿先于营地样张,故 T1 终稿落盘不构成违背 art-bible §7.5「前置」条(§5 反哺点已注)。
|
||||
### 0.3 代码段 `/iter` 开工门(不是设计待裁点,不阻塞重立卡与编迭代)
|
||||
|
||||
下列项属代码段开工门;未销号即需开工对应任务段=§8 L3 停机呈报,禁批内自补、禁 T0 现场发挥:
|
||||
|
||||
1. **P3 点选反馈设计稿——已销号(2026-11-01 用户裁)**:销号口径=camp.md v2.2:35-37 四态规格即点选反馈设计稿(悬停/按下/禁用/常态参数已钉死);剩余实质=七物件名牌文案与可点区域视觉,归 T2 域内(名牌文案按 §1 绑定表界面名逐字落,可点区域判定归 §9 白名单 3)。
|
||||
2. **P5 GDD/art-bible 条款落文——已销号(2026-11-01 用户裁)**:销号口径=形态落文完成(camp.md v2.2/art-bible v3.31 §6.2 已在盘);实装状态回填与 §7.5/§2.8 同步归 T6 反哺点义务(§5),非停机条件。
|
||||
3. **camp-scene-prompts.md §5 五裁点——已裁断(2026-11-01 用户裁,照双审推荐采纳)**:①帐篷 300×170 追认现值 ②门扇 240×220 追认现值、坐标按门洞 x520–760 对齐锚点 ③布告板 (845,268,130,140) 挂围墙带(y330 悬空案弃)④描边颜色=奶油色追认(去底技术前提随现值锁定,改深灰褐须换去底方案全批重出、禁)⑤营地环境子板色值**不前置**——T1 量化实际用色后按 art-bible §4.1 两道门(语义检查+RGB 三通道差)登记;未登记前 T5「截屏级 48 色计数是否新建」(§9-4)为条件步:色值已登记→拍板,未登记→该子步显式跳过+T6 登记遗留(不阻塞批末闸,素材级二器 palette_check/standee_asset_check 已覆盖素材级执法)。camp-scene-prompts.md §5 节改已裁+art-bible :398 对应三处值落文归文档批(§5 反哺点表已列)。
|
||||
4. **十张终稿后处理与入库——发令形态已裁(2026-11-01 用户裁)**:**/iter 开工令即含 T1 后处理授权**(去底转透明〔bg 不去底、全幅不透明〕/擦通道水印/降采样/裁围墙细条/色板量化),不再两次发令;逐张画布档→目标矩形换算式登记见 §6 T1(1024×1024 档无整数倍降采样,禁现场默认)。
|
||||
|
||||
### 0.4 10 层拆分(现行口径,覆盖旧 8/9 张)
|
||||
|
||||
| z | 层 | 内容 | 可点 |
|
||||
| -- | -- | ---- | ---- |
|
||||
| z0 | `scene_camp_bg` | 不透明全幅=天空+远山+整片地面+门洞内一条通向远处的小路 | 否 |
|
||||
| z1 | `scene_camp_wall` | 透明底,横贯全宽密排竖木桩墙(左右两段)+两根略高门柱;门洞 x520–760 留透明缺口透出 bg 小路;落盘按细条 (0,240,1280,70) 裁、不做全幅 | 否 |
|
||||
| z2 | `scene_camp_board` 布告板 | 挂围墙带,点进图鉴占位 | 是 |
|
||||
| z3 | `scene_camp_gate` 门扇 | 半开双扇,叠在门洞上(240×220 追认现值、2026-11-01 裁;坐标按门洞 x520–760 对齐) | 是 |
|
||||
| z4 | `scene_camp_dummy` 木桩/`scene_camp_forge` 锻炉/`scene_camp_tent` 帐篷 | 木桩、锻炉可点;帐篷承载件不可点 | 部分 |
|
||||
| z5 | `scene_camp_chest` 宝箱/`scene_camp_notebook` 笔记本 | 宝箱、帐篷旁笔记本 | 是 |
|
||||
| z6 | `scene_camp_campfire` 篝火 | 最前;命中矩形只取下半(火堆),上半火焰只展示 | 是 |
|
||||
|
||||
围墙从背景层独立成层(z1),门洞小路画在 bg 层(z0)。**中景带自画面底部往上约 2/3 处起**;近景物件可压住围墙,**唯一例外=中间门洞必须留空、不被任何物件遮挡**。坐标草案与分层验收判据见 [camp-scene-prompts.md](../design/art/camp-scene-prompts.md) §2.3/§4(10 张口径现行事实源)与 [布局草案-1280x800.html](../artwork/2026-10-23-营地场景/布局草案-1280x800.html)。
|
||||
|
||||
### 0.5 跨卡接口与并行性(批内视角,非排期承诺)
|
||||
|
||||
- 卡③(选档界面)Q3 已裁乙:随 ①②③ 工程波先行时进档/新档暂行接现役 CampOverlay——**本卡代码波落地后,营地入口从现役 CampOverlay 改挂场景图,现役 CampOverlay 随之拆解退役**(卡③ 暂行接线与本次改挂的二次验证面在卡③ T2/实现报告登记)。
|
||||
- 卡⑤(ESC 浮窗与营地顶栏)落在本批新建的场景屏顶栏位——两卡触碰同一新屏,建议同批或卡⑤ 随后。**跨卡接口**:①场景屏顶栏位(T2 预留);②**营地刷新单口**(T3 定义:各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成)——卡⑤ HUD 刷新挂该单口,非已退役的 `refresh_camp`;③ConfirmDialog 三钮化与消费方编排(T4,卡③ 契约 3 同款互指);④子界面返回钮承诺(T3);⑤篝火二次确认走 ConfirmDialog 先例(camp.md v2.2 已裁必须)。
|
||||
- 样张线关系:营地屏整屏样张是 art-bible §1.4 四屏之一,现列 06「待设计」排队行——本卡不跑整屏样张闸、不替代样张批,只按既有约束(契约 7/9)生产与自检;营地屏样张义务留原排队行(反哺点注记)。文档既定序列(排队行措辞「终稿后再出样」)本就终稿先于营地样张,故 T1 终稿落盘不构成违背 art-bible §7.5「前置」条(§5 反哺点已注)。
|
||||
|
||||
## 1. 目标与完成定义
|
||||
|
||||
**目标(澄清①一句提炼照录)**:营地首页从「文字按钮菜单 + 列表式覆盖层」改为「**一张可点击的营地场景图**」——点场景中的具体物件进入对应功能界面。用户原话照录:「我是希望有一个营地地图的游戏画面;或者是一张营地的图片,跟 UI 的交互是点击图片中的某一处地方,然后再进入界面。不是完全普通的那种 UI 设计,不是各种框框的……我点击某些具体的东西之后,就可以进入对应的操作界面。」(称呼订正:「它就是一个营地的画面;并不是一张地图。」)
|
||||
**目标(澄清①一句提炼照录)**:营地首页从「文字按钮菜单 + 列表式覆盖层」改为「**一张可点击的营地场景图**」——点场景中的具体物件进入对应功能界面。用户原话照录:「我是希望有一个营地地图的游戏画面;或者是一张营地的图片,跟 UI 的交互是点击图片中的某一处地方,然后再进入界面。不是完全普通的那种 UI 设计,不是各种框框的……我点击某些具体的东西之后,就可以进入对应的操作界面。」(称呼订正:「它就是一个营地的画面;并不是一张地图。」)
|
||||
|
||||
**七物件绑定(澄清④结构树照录,逐一落地)**:
|
||||
**七物件绑定(camp.md v2.2 §场景构成与七物件绑定,逐一落地)**:
|
||||
|
||||
| 物件 | 绑定目标 | 现状定性 |
|
||||
| ------- | -------------------------- | ------------ |
|
||||
| 营地大门 | 冒险(选路屏/战斗屏已实现,不动;断点弹窗保留移位) | 入口新建+动线迁徒 |
|
||||
| 锻炉·铁砧 | 锻造工坊 | 界面已实现 · 入口改挂 |
|
||||
| 宝箱 | 秘宝匣 | 界面已实现 · 入口改挂 |
|
||||
| 床铺旁笔记本 | 生涯记录 | 界面已实现 · 入口改挂 |
|
||||
| 木桩 | 树淬炼天赋树 | 界面已实现 · 入口改挂 |
|
||||
| 布告板/悬赏板 | 奖励格图鉴 | 界面已实现 · 入口改挂 |
|
||||
| 篝火 | 离开营地/回主菜单 | 新建小动线 |
|
||||
| 物件 | 进入 | 备注(现状定性+现行约束) |
|
||||
| ---- | ---- | ------------------------ |
|
||||
| 大门(半开门扇,门洞内一条通向远处的小路) | 冒险(选路屏/战斗屏已实现不动;断点弹窗移位) | 入口新建+动线迁移;点大门永远先出确认(有断点=三出口,无=是否开始新冒险) |
|
||||
| 锻炉·铁砧 | 锻造工坊 | 界面已实现·入口改挂;未解锁=禁用态(降明度+去饱和) |
|
||||
| 宝箱 | 秘宝匣 | 界面已实现·入口改挂;未解锁=禁用态 |
|
||||
| 帐篷旁笔记本 | 生涯记录 | 界面已实现·入口改挂;生涯页返回钮文案禁含「营地」字样 |
|
||||
| 木桩 | 树淬炼天赋树 | 界面已实现·入口改挂 |
|
||||
| 布告板/悬赏板 | 奖励格图鉴 | 界面已实现·入口改挂;内容冻结未激活,点进看占位(**不是禁用态**) |
|
||||
| 篝火 | 离开营地/回主菜单 | 新建小动线;**必须二次确认**;命中区只含火堆、不含火焰 |
|
||||
| 帐篷 | — | 承载件不可点;落地尺寸与占位范围待作者重定(代码段开工门,camp-scene-prompts §5) |
|
||||
|
||||
**纵深稿(用户原话照录)**:「远景是天空;中景是一个围栏,还有营地大门;近景中间是一个篝火;左边是锻炉铁砧;右边是我们的床铺,宝箱等。」
|
||||
**纵深稿(用户原话照录)**:「远景是天空;中景是一个围栏,还有营地大门;近景中间是一个篝火;左边是锻炉铁砧;右边是我们的床铺,宝箱等。」(承载件落地为帐篷,见 §0.4 z4。)
|
||||
|
||||
**大门两分支(裁决 5 照录)**:有未完冒险 → 弹「继续上一段冒险 / 开始新冒险」;无未完冒险 → 弹「是否开始新冒险:是/否」。**点大门永远先出确认,不直接进冒险**(「断点续玩也是开始冒险的两个分支之一……它算是开始冒险的一个子节点」)。**「有断点」分支的三出口弹窗形态待裁(Q5)**——现役 ConfirmDialog 双钮表达不了两个肯定性动作。
|
||||
**大门两分支(裁决 5 照录,Q5 已裁=甲)**:有未完冒险 → ConfirmDialog 三出口「继续上一段冒险/开始新冒险/取消」;无未完冒险 → 「是否开始新冒险:是/否」。**点大门永远先出确认,不直接进冒险**;cancelled 恒=无变更退回营地。
|
||||
|
||||
**钥石余额(裁决 10 照录)**:场景**顶部小 HUD 栏**(用户原话「先按顶部小HUD栏设计」——provisional 措辞留痕;承载落卡⑤)。
|
||||
**钥石余额(裁决 10 照录)**:场景**顶部小 HUD 栏**(高 48px 全宽窄条、浮层覆盖不挤压画面;承载落卡⑤)。
|
||||
|
||||
**相对现状,新增了什么**:
|
||||
|
||||
1. 交互式营地场景图(场景素材+场景屏+七物件命中区与点选交互)——从零新建;
|
||||
2. 现四柜台覆盖层(CampOverlay)拆解:锻造工坊/秘宝匣/天赋树/奖励格图鉴四界面抽为独立可开界面,入口改挂场景物件;生涯页入口自主菜单改挂笔记本;
|
||||
3. 大门动线(开始冒险/继续上局两分支+断点确认弹窗从主菜单移位);
|
||||
4. 篝火回主菜单小动线;场景屏顶栏预留位(卡⑤ HUD);
|
||||
5. camp 截图断言段与六探针营地段的迁移(**现无 camp 逐像素 golden 基线**——v1.1 订正,见契约 10)。
|
||||
1. 交互式营地场景图(10 层场景素材+场景屏+七物件命中区与点选交互)——从零新建;
|
||||
2. 现四柜台覆盖层(CampOverlay)拆解:锻造工坊/秘宝匣/天赋树/奖励格图鉴四界面抽为独立可开界面,入口改挂场景物件;生涯页入口自主菜单改挂帐篷旁笔记本;
|
||||
3. 大门动线(开始冒险/继续上局两分支+断点确认弹窗从主菜单移位);
|
||||
4. 篝火回主菜单小动线(带二次确认);场景屏顶栏预留位(卡⑤ HUD);
|
||||
5. camp 截图断言段与六探针营地段的迁移(**现无 camp 逐像素 golden 基线**——见契约 10)。
|
||||
|
||||
**完成定义**:
|
||||
|
||||
1. 营地首页=可点击场景图;七物件绑定逐一在役,点各物件进对应界面;
|
||||
2. 四柜台拆解完毕:CampOverlay 覆盖层形态退役,五界面(锻造/秘宝/生涯/天赋树/图鉴)经新入口可达且**功能与写口链路零回归**(presenter 改造=承载面迁移的一部分——见契约 4);
|
||||
3. 大门两分支确认弹窗在役;点大门不直接进冒险;
|
||||
4. 篝火可回主菜单;场景屏顶栏预留位就绪(卡⑤联验);
|
||||
5. camp 截图=场景图形态(迭代内验收=截图对比,澄清⑥);探针断言迁移完毕;
|
||||
6. 美术约束(48 色板/禁入带/语义色/WCAG)入闸或登记缺口;**用户目检项登记 07**(生命周期末步,不阻塞);
|
||||
1. 营地首页=可点击场景图(10 层按 §0.4 铺底、门洞留空);七物件绑定逐一在役,点各物件进对应界面;
|
||||
2. 四柜台拆解完毕:CampOverlay 覆盖层形态退役,五界面(锻造/秘宝/生涯/天赋树/图鉴)经新入口可达且**功能与写口链路零回归**(presenter 改造=承载面迁移的一部分——见契约 4);
|
||||
3. 大门两分支确认弹窗在役;点大门不直接进冒险;cancelled 无变更退回;
|
||||
4. 篝火经二次确认可回主菜单;场景屏顶栏预留位就绪(卡⑤ 联验);
|
||||
5. camp 截图=场景图形态(迭代内验收=截图对比,澄清⑥);探针断言迁移完毕;
|
||||
6. 美术约束(48 色板/禁入带/语义色/WCAG)入闸或登记缺口;**用户目检项登记 07**(生命周期末步,不阻塞);
|
||||
7. 批末重闸按改动域选档全绿;三份 `reports/` 产出物写齐(T6)。
|
||||
|
||||
## 2. 现状事实(2026-10-18 实查;开工日 T0 复核行号)
|
||||
## 2. 现状事实(2026-11-01 双审全量复核换新盘面;开工日 T0 仍按「漂移即停卡核对」抽核)
|
||||
|
||||
| # | 事实 | 出处 |
|
||||
| --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| F1 | 营地场景图完全不存在(澄清④判定「完全没有 · 新建」);现营地=CampOverlay 四柜台覆盖层(树淬炼/锻造工坊/秘宝匣/奖励格图鉴并排,迭代 21 T6 程序占位重排——代码注释原文「视觉终稿归 HUD 营地视觉批」) | `需求澄清-营地交互重做-2026-10-18.md` §④;`game/presentation/views/camp_overlay_view.gd:86-87` |
|
||||
| F2 | 营地屏壳(CampScreen)持 CampOverlay 成员;组合根 `main.camp_overlay` 句柄指向屏壳成员(探针挂载假设) | `game/presentation/scenes/camp_screen.gd:8-14`;`main.gd:112` |
|
||||
| F3 | CampOverlay 结构:顶栏铭牌+钥石徽(:64-84);四柜台并排横滚(树淬炼 :99-109/锻造工坊 :111-137/秘宝匣 :139-159/奖励格图鉴 :161-172);底栏关闭钮+最近冒险条带(:174-189);钥匙门判据读树投影(:287-296);图鉴柜台=结构位预留(:168「内容排 Alpha」) | `camp_overlay_view.gd` 各处 |
|
||||
| F4 | 五目标界面现状:锻造工坊=CampOverlay 内工作间(`_forge_workbench` 两区六路线);秘宝匣=`_ws_scroll`/`_workshop_holder`(12 件+同调装配段+Y 升级行);天赋树=`_tree_holder`(脉分组行板+Fork 双态钮);图鉴=占位;生涯=**已独立全屏页**(CareerOverlay,入口现居主菜单生涯钮,自带返回钮) | `camp_overlay_view.gd:116-137`/:144-159/:99-109/:161-172;`views/career_overlay.gd`;`main.gd:332` |
|
||||
| F5 | 营地购买写口链路:视图只发意图信号(`buy_requested`/`tree_buy_requested`/`forge_*` 等),组合根经 CampShopPresenter 转 MetaProgression 写口;投影数据=`camp_shop_presenter.gd:62-72` `camp_data()` 单点 | `camp_overlay_view.gd:8-15`;`camp_shop_presenter.gd:62-72` |
|
||||
| F6 | 断点确认弹窗现居主菜单开始冒险路径(有断点先出 ConfirmDialog 再开局)——随卡②撤钮整体移交本卡大门 | `main.gd:475-497` |
|
||||
| F7 | 冒险屏已实现不动:选路屏(LevelMapScreen,`route_chosen` 前进唯一通道)与战斗屏宿住 AdventureScreen;组合根侧:`_start_adventure_from_menu`(:475-484)/`_on_confirm_new_adventure`(:487-492)/`_resume_from_menu`(:518-536)/`_start_adventure`(:579-597)/`build_adventure_params`(:564-574) | `views/level_map_screen.gd:7`;`scenes/adventure_screen.gd:36-37`;`main.gd` 各处(v1.1 行号订正) |
|
||||
| F8 | 探针面营地段(全部随本批迁移,v1.1 补列):ui_probe(营地入口+余额+秘宝匣 12 行断言 :28-55,深员 `_balance_label`/`_tree_buy_btns`/`_workshop_rows` :39-52)、ui_click_probe(营地购买全链 :53-127;**断点确认段 :500-528**〔经 lvbtn 驱动 ConfirmDialog 取消/开新冒险——被卡②撤钮+本批弹窗移位双杀,v1.1 补列〕)、screen_flow_probe(营地可见态键 :53 直读 `main.camp_overlay.visible`;营地开合 :109-125 回退段直呼 `main.camp_overlay.closed.emit()`;菜单→冒险 lvbtn 步 :130-136)、shot_probe(camp 截图+「关闭营地」钮收闭 :126-133)、ui_struct_probe(camp 结构审计 :41-49;同槽特例断言 :331/:373)、smoke_all(V2 营地屏壳实例化 :170-171;V3g 营地模态开合 :405-435;**camp_overlay_view.gd 源码断言段 :6469-6475**〔三条锁四柜台等高形态本身——`Vector2(0,336)`×3/`SIZE_FILL`×4/`SIZE_SHRINK_CENTER`≥3,随形态退役〕)、ui_contrast_probe(营地令牌段 :48-55〔UiKit 令牌恒等式,不随拆解红;新界面若不再消费 `CAMP_HEADER_BAND`/`CAMP_ROW_PLATE` 则段标签虚挂,须核签〕)、**forge_workbench_test.gd 单测**(:33 直载 camp_overlay_view.gd 并消费 `_forge_rows`/`_forge_workbench`/`open_camp`/`refresh_camp`/三 forge 信号——CampOverlay 一删即红) | `game/smoke/` 各处+`game/tests/unit/presentation/forge_workbench_test.gd:33` |
|
||||
| F9 | camp UX spec 形态记述将整体退役:三柜台列/顶栏铭牌钥石徽/底栏关闭钮+最近冒险条带(v1.5,事实源声明= camp_overlay_view.gd 实态;条带实述于 :19-20) | `design/gdd/ux/camp.md:14-20` |
|
||||
| F10 | art-bible 营地条款将失义:§6.2 营地场景「三柜台在烛光下一字排开,钥石余额常驻顶栏」;§7.5 营地界面「三柜台界面画法……视觉终稿以表现层样张过审为前置」;§2.8 承载元素同述 | `design/art/art-bible.md:366-369`/:436-438`/:136-140` |
|
||||
| F11 | 图鉴内容在册挂起:奖励格图鉴柜台已随配比预设批整体挂起冻结(2026-10-05 用户令,06 在册),重启须用户另行发令——本批只改入口不激活内容 | `design/gdd/systems/跨局循环/生涯.md:63` |
|
||||
| F12 | 贴图重构批搁置未废:营地与元进度件终稿置换(06:21-27)等交互重做定形后再议(澄清③1/§⑧5)——本批不清偿该债;四柜台拆解后原「柜台场景贴图」债对象变化,随该批重新评估 | `design/gdd/06-待办清单.md:21-27`;`需求澄清-营地交互重做-2026-10-18.md` §③1/§⑧5 |
|
||||
| F13 | 营地底栏「最近冒险」条带与生涯历史回看同源(同一份 `recent_summaries`),其去留=生涯.md P6 待裁点(期二必答)——CampOverlay 拆解后该条带无处挂,P6 被迫提前面对(本卡 Q4) | `camp_overlay_view.gd:186-189`/:536-549;`生涯.md:69`/:91-101\` |
|
||||
| F14 | 素材线纪律:`artwork/` 不入 git(`.gitignore:51` 忽略行)——批次 worktree 内无该目录、主工作区 D:/code/g-plan2 实体存在(在途工作区);涉素材脚本须传主区绝对路径否则静默 0 张;素材替换前先归档旧档;终稿归 `game/assets/art/` | `AGENTS.md:32`;`.gitignore:51`;art-bible §8.3 归档纪律(v1.1 行号与表述订正) |
|
||||
| F15 | 美术硬约束继续有效(澄清③4):明亮轻快像素风、**48 色板、HSV 300°–345° 禁入带、语义色纪律、WCAG ≥4.5:1**——全局约束,不在本讨论范围翻案 | `需求澄清-营地交互重做-2026-10-18.md` §③4 |
|
||||
| F16 | 像素级规格不在本卡硬定(澄清③5):尺寸档/色板/明度档归「战斗一屏样张批」冻结的规格清单——该批现列 06「待设计」未排期(2026-10-17 用户令自迭代 30 剔除),本卡只写指针并登记依赖(缺口连带裁=Q6) | `需求澄清-营地交互重做-2026-10-18.md` §③5;`design/gdd/06-待办清单.md`(迭代 30 剔除卡②③ 条) |
|
||||
| F17 | 机检工具面(v1.1 订正):**截屏级 48 色计数不在役**;在役=`tools/palette_check.py`(art-bible §8.3①挂点——48 设计色板令牌+新增色双门)+`tools/standee_asset_check.py`(像素画单张 32 色冻结执法);`tools/render_gate.sh`(shot_probe 七屏→shot_checker 语义断言;golden 段=棋盘三张+menu_boot 四张,**无 camp golden**——shot_checker.py:143 明载「camp/level 走骨架+目检清单」);shot_checker 段=屏级骨架/文字 WCAG/明度三档带/文字禁压纹理/文字在判据 | `tools/palette_check.py`;`tools/standee_asset_check.py`;`tools/render_gate.sh`;`tools/shot_checker.py:143` |
|
||||
| # | 事实 | 出处 |
|
||||
| --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| F1 | 营地场景图完全不存在(澄清④判定「完全没有 · 新建」);现营地=CampOverlay 四柜台覆盖层(树淬炼/锻造工坊/秘宝匣/奖励格图鉴并排,迭代 21 T6 程序占位重排)——原引注释「视觉终稿归 HUD 营地视觉批」已随后续重构删除(2026-11-01 复核,引文退役、事实不变) | `需求澄清-营地交互重做-2026-10-18.md` §④;`game/presentation/views/camp_overlay_view.gd` |
|
||||
| F2 | 营地屏壳(CampScreen)持 CampOverlay 成员;组合根句柄=`main.ui.modals.camp_overlay`(ui_modals.gd:14;ui_registry.gd:25 LAYER_CONTRACT 模态槽)——`main.camp_overlay` 旧寻址已退役,探针挂载随句柄迁移(F8) | `game/presentation/scenes/camp_screen.gd:8-14`;`game/presentation/ui_modals.gd:14`;`game/presentation/ui_registry.gd:25` |
|
||||
| F3 | CampOverlay 结构(结构在、行号以 2026-11-01 复核为基准):顶栏铭牌+钥石徽(:125);四柜台并排横滚(树淬炼/锻造工坊/秘宝匣/图鉴——图鉴锁文现 :207);底栏关闭钮+最近冒险条带(:214 起,`_rebuild_recent` :634);钥匙门判据读树投影 | `camp_overlay_view.gd` 各处 |
|
||||
| F4 | 五目标界面现状:锻造工坊=CampOverlay 内工作间(`_forge_workbench` 两区六路线);秘宝匣=`_ws_scroll`/`_workshop_holder`(12 件+同调装配段+Y 升级行);天赋树=`_tree_holder`(脉分组行板+Fork 双态钮);图鉴=占位;生涯=**已独立全屏页**(CareerOverlay,入口现经组合根函数直调——卡②已撤主菜单生涯钮、改函数直调中间态,shot_probe.gd:103/ui_struct_probe.gd:59「careerbtn 已撤」注;终态=本批改挂帐篷旁笔记本,自带返回钮) | `camp_overlay_view.gd` 四柜台各处;`views/career_overlay.gd` |
|
||||
| F5 | 营地购买写口链路:视图只发意图信号(`buy_requested`/`tree_buy_requested`/`forge_*` 等),组合根经 CampShopPresenter 转 MetaProgression 写口;投影数据=`camp_shop_presenter.gd:62-72` `camp_data()` 单点 | `camp_overlay_view.gd:8-15`;`camp_shop_presenter.gd:62-72` |
|
||||
| F6 | 断点确认链已随卡②摘除(main.gd:118-120 注释「弹窗本体与两分支逻辑归卡④大门承接」);main.gd:475-497 现为选档委托(旧「断点弹窗现居主菜单」引文失实,2026-11-01 复核)——断点确认弹窗本卡 T4 承接(卡②移交) | `main.gd:118-120` |
|
||||
| F7 | 冒险屏已实现不动:选路屏(LevelMapScreen,`route_chosen` 前进唯一通道)与战斗屏宿住 AdventureScreen;组合根侧(2026-11-01 复核行号):`_start_adventure_from_menu` :116/`_resume_from_menu` :150/`build_adventure_params` :183/`_start_adventure` :198——`_on_confirm_new_adventure` 已随卡②摘除(T4 重立消费方编排) | `views/level_map_screen.gd:7`;`scenes/adventure_screen.gd:36-37`;`main.gd` 各处 |
|
||||
| F8 | 探针面营地段(全部随本批迁移;宿主=`game/probe/`+`game/tests/`——`game/smoke/` 目录已于 2026-10-24 退役(git 16c6f136)、smoke_all.gd 已整体退役(git 957391e1),v3.0 的 `game/smoke/*`+smoke_all 旧盘面写法作废):ui_probe(营地入口+余额+秘宝匣 12 行断言,深员 `_balance_label`/`_tree_buy_btns`/`_workshop_rows`)、ui_click_probe(营地购买全链;**断点确认段**〔经 lvbtn 驱动 ConfirmDialog——被卡②撤钮+本批弹窗移位双杀〕)、screen_flow_probe(营地旗标 :54 直读主菜单句柄——:53 是菜单行,v3.1 订正;营地开合 :119-125 回退段;菜单→冒险 lvbtn 步)、shot_probe(camp 截图+「关闭营地」钮收闭;生涯段函数直调驱动 :103)、ui_struct_probe(camp 结构审计;同槽特例断言)、system_test.gd(V2 营地屏壳实例化 :67-68;V3g 营地模态开合 :520-541)、theme_projection_test.gd:710-717(四柜台等高源码断言段 `_smoke_element_details`——`Vector2(0,336)`×3/`SIZE_FILL`×4/`SIZE_SHRINK_CENTER`≥3,随形态退役)、ui_contrast_probe(营地令牌段〔UiKit 令牌恒等式,不随拆解红;新界面若不再消费 `CAMP_HEADER_BAND`/`CAMP_ROW_PLATE` 则段标签虚挂,须核签〕)、**forge_workbench_test.gd 单测**(:33 直载 camp_overlay_view.gd 并消费 `_forge_rows`/`_forge_workbench`/`open_camp`/`refresh_camp`/三 forge 信号——CampOverlay 一删即红) | `game/probe/` 各处+`game/tests/system_test.gd:67-68`/:520-541+`game/tests/unit/presentation/theme_projection_test.gd:710-717`+`game/tests/unit/presentation/forge_workbench_test.gd:33` |
|
||||
| F9 | camp UX spec 现行 **camp.md v2.2** 已落文可点击场景图形态(定位/场景构成与七物件绑定/10 层拆分/点选反馈四态/顶栏 48px/叠层与开合);本批实现=**对齐** v2.2,旧三柜台形态已由 v2.2 取代,本批只需回填实装状态与目检结论 | `design/gdd/ux/camp.md:10-51` |
|
||||
| F10 | art-bible 现行 **v3.31 §6.2** 已落文营地场景 10 层口径(z0 bg 不透明全幅/z1 wall 透明细条门洞缺口/八物件层/篝火命中只下半/围墙落盘 (0,240,1280,70));§7.5 营地界面已改为「可点击场景图+七物件点选」画法;§2.8 承载元素同述;本批实现=对齐现行条款 | `design/art/art-bible.md` §6.2/§7.5/§2.8 |
|
||||
| F11 | 图鉴内容在册挂起:奖励格图鉴柜台已随配比预设批整体挂起冻结(2026-10-05 用户令,06 在册),重启须用户另行发令——本批只改入口不激活内容 | `design/gdd/systems/跨局循环/生涯.md:63` |
|
||||
| F12 | 贴图重构批搁置未废:营地与元进度件终稿置换(待办清单.md 在册条)等交互重做定形后再议(澄清③1/§⑧5)——本批不清偿该债;四柜台拆解后原「柜台场景贴图」债对象变化,随该批重新评估(原 `design/gdd/06-待办清单.md` 路径已迁仓库根) | `待办清单.md`(仓库根);`需求澄清-营地交互重做-2026-10-18.md` §③1/§⑧5 |
|
||||
| F13 | 营地底栏「最近冒险」条带与生涯历史回看同源(同一份 `recent_summaries`),其去留=生涯.md P6 待裁点(期二必答)——CampOverlay 拆解后该条带无处挂,**Q4 已裁=甲**(随四柜台拆解撤下,逐局历史回看归生涯,生涯.md P6 同批注销) | `camp_overlay_view.gd`(底栏 :214 起/`_rebuild_recent` :634);`生涯.md:69` |
|
||||
| F14 | 素材线纪律:`artwork/` 不入 git(`.gitignore:54` 忽略行)——批次 worktree 内无该目录、主工作区 D:/code/g-plan2 实体存在(在途工作区);涉素材脚本须传主区绝对路径否则静默 0 张;素材替换前先归档旧档;终稿归 `game/assets/art/scene/`;**消费常量 `UiKit.TEX_CAMP_*` 尚不存在**(全仓 grep 零命中,仅 art-assets-checklist.md:135 文字提及)——本批在 `ui_kit.gd` 新增十键(T1 先定常量、素材名跟常量走,防断链;2026-11-01 裁) | `AGENTS.md:32`;`.gitignore:54`;art-bible §8.3 归档纪律;art-assets-checklist.md §3.5 |
|
||||
| F15 | 美术硬约束继续有效(澄清③4):明亮轻快像素风、**48 色板、HSV 300°–345° 禁入带、语义色纪律、WCAG ≥4.5:1**——全局约束,不在本讨论范围翻案 | `需求澄清-营地交互重做-2026-10-18.md` §③4 |
|
||||
| F16 | 像素级规格已定(Q6 甲过渡口径+渠道 B):1280×800 工程档、烛光黄 #F6C667/木色 #8A5A34、2× 源档出图最近邻降采样(art-assets-checklist.md §3.5);终档归样张批冻结清单后置换(反哺点);卡内禁自定像素规格数值 | `design/art/art-assets-checklist.md` §3.5;`design/art/art-bible.md` §6.2 |
|
||||
| F17 | 机检工具面:**截屏级 48 色计数不在役**;在役=`tools/palette_check.py`(art-bible §8.3①挂点——48 设计色板令牌+新增色双门)+`tools/standee_asset_check.py`(像素画单张 32 色冻结执法);`tools/render_gate.sh`(shot_probe 七屏→shot_checker 语义断言;golden 段=棋盘三张+menu_boot 四张,**无 camp golden**——shot_checker.py:143 明载「camp/level 走骨架+目检清单」);shot_checker 段=屏级骨架/文字 WCAG/明度三档带/文字禁压纹理/文字在判据 | `tools/palette_check.py`;`tools/standee_asset_check.py`;`tools/render_gate.sh`;`tools/shot_checker.py:143` |
|
||||
| F18 | 参照物已补(2026-10-23)=`artwork/2026-10-23-营地场景/Gemini_Generated_Image_ykrc0nykrc0nykrc.jpg`,已进 camp-scene-prompts.md §1 风格参考图表登记为「作者提供的参照物」,与纵深稿对过表、围墙结构冲突已呈报;参照物只是参考图,保留 `artwork/`、不入 git、不入游戏目录 | `design/art/camp-scene-prompts.md` §1;`artwork/2026-10-23-营地场景/` |
|
||||
| F19 | 10 层拆分现行口径(覆盖旧 8/9 张):art-bible v3.31 §6.2/camp.md v2.2/camp-scene-prompts.md v1.2/asset-path-map.md §3/art-assets-checklist.md §3.5 同步;围墙从背景层独立成 z1、门洞小路画在 z0 bg 层;围墙落盘细条 (0,240,1280,70) 不做全幅 | `design/art/art-bible.md` §6.2;`design/gdd/ux/camp.md:27-31` |
|
||||
| F20 | 样张过审与终稿裁定(2026-10-31 用户裁定):保留全部待选稿、各素材第一张样本稿为终稿、「目前我看每个都还可以接受」,用户准备在游戏内做最终审核;终稿此刻=原始候选图本身,未做去底/擦水印/降采样/裁细条等任何后处理(用户 2026-10-31 令只生成素材不做后续工序);清单=`artwork/candidates/_终稿裁定-2026-10-31.txt` | `artwork/candidates/_终稿裁定-2026-10-31.txt` |
|
||||
|
||||
## 3. 设计契约(红线,违反 = L3 停机呈报)
|
||||
## 3. 设计契约(红线,违反 = L3 停机呈报)
|
||||
|
||||
🔴 **契约 1 · 交互式场景图形态**:营地首页=一张可点击的营地场景图,点物件进界面(澄清①)。**禁退回文字按钮列表+面板覆盖层形态**(澄清②反参照:「完全普通的那种 UI 设计」「各种框框」——用户判现状「交互流程完全错误」)。
|
||||
🔴 **契约 1 · 交互式场景图形态**:营地首页=一张可点击的营地场景图,点物件进界面(澄清①)。**禁退回文字按钮列表+面板覆盖层形态**(澄清②反参照:「完全普通的那种 UI 设计」「各种框框」——用户判现状「交互流程完全错误」)。
|
||||
|
||||
🔴 **契约 2 · 七物件绑定逐一落地**:大门/锻炉铁砧/宝箱/笔记本/木桩/布告板/篝火七个绑定(§1 表)缺一不可;禁合并、禁以「其他入口」替代(如顶栏文字钮)。
|
||||
🔴 **契约 2 · 七物件绑定逐一落地**:大门/锻炉铁砧/宝箱/帐篷旁笔记本/木桩/布告板/篝火七个绑定(§1 表)缺一不可;禁合并、禁以「其他入口」替代(如顶栏文字钮)。帐篷为承载件、不可点。
|
||||
|
||||
🔴 **契约 3 · 大门两分支**(裁决 5):有未完冒险→「继续上一段冒险/开始新冒险」二选一弹窗(**三出口形态=Q5 待裁**);无→「是否开始新冒险:是/否」弹窗。**点大门永远先出确认,不直接进冒险**;弹窗类=ConfirmDialog(三钮化+消费方编排=T4,卡③ 契约 3 同款互指)。
|
||||
🔴 **契约 3 · 大门两分支**(裁决 5,Q5 已裁=甲):有未完冒险→ConfirmDialog 三出口「继续上一段冒险/开始新冒险/取消」;无→「是否开始新冒险:是/否」弹窗。**点大门永远先出确认,不直接进冒险**;cancelled 恒=无变更退回营地;弹窗类=ConfirmDialog(三钮化+消费方编排=T4,卡③ 契约 3 同款互指)。
|
||||
|
||||
🔴 **契约 4 · 已实现界面只改挂不重做+presenter 承接面(v1.1 精确化)**:锻造工坊/秘宝匣/天赋树/图鉴/生涯五界面「界面已实现 · 入口改挂」——功能、行板、写口链路零重设计(拆解=承载面迁移)。**presenter 改造=承载面迁移的一部分**:`camp_shop_presenter.gd` 持 `camp_overlay` 句柄(:10)、七条写口尾全部 `camp_overlay.refresh_camp(camp_data())`(:85/93/105/117/129/142/154/168)、`CampFlowContext` 持类型化字段(camp_flow_context.gd:10/22/29)、open/close 编排(:41-56)——**写口语义零改≠presenter 文件零改**:投影目标改线(五界面/场景根)、写口尾刷新改路由、open/close 编排随入口从 campbtn 迁位到卡③进档动作、ctx 字段语义订正、探针缝保缝(main.gd:1163-1171)。改造纪律:`on_camp_attune_toggle`(:98-106)尾只 refresh_camp、不调 `_refresh_presentations`(与其余六口不一致)——**保持原样,禁「顺手统一」防行为漂移**。
|
||||
🔴 **契约 4 · 已实现界面只改挂不重做+presenter 承接面**:锻造工坊/秘宝匣/天赋树/图鉴/生涯五界面「界面已实现 · 入口改挂」——功能、行板、写口链路零重设计(拆解=承载面迁移)。**presenter 改造=承载面迁移的一部分**:`camp_shop_presenter.gd` 持 `camp_overlay` 句柄(:10)、写口尾刷新调用八处(七口+`on_camp_buy` 双尾)全部 `camp_overlay.refresh_camp(camp_data())`(:82/90/102/114/126/139/151/165,2026-11-01 复核实数)、`CampFlowContext` 持类型化字段(camp_flow_context.gd:10/22/29)、open/close 编排(:41-56)——**写口语义零改≠presenter 文件零改**:投影目标改线(五界面/场景根)、写口尾刷新改路由、open/close 编排随入口从 campbtn 迁位到卡③ 进档动作、ctx 字段语义订正、探针缝保位(组合根薄委托缝,T0 复核现役行号——原引 main.gd:1163-1171 超出文件实长、系旧盘面残留)。改造纪律:`on_camp_attune_toggle` 口尾(:102)只 refresh_camp、不调 `_refresh_presentations`(与其余口不一致)——**保持原样,禁「顺手统一」防行为漂移**。
|
||||
|
||||
🔴 **契约 5 · 图鉴内容保持挂起**:只改入口(布告板),不激活图鉴内容(F11:2026-10-05 用户令冻结,重启须用户发令);布告板点开的图鉴=现行占位态(T3 定义占位壳)。
|
||||
🔴 **契约 5 · 图鉴内容保持挂起**:只改入口(布告板),不激活图鉴内容(F11:2026-10-05 用户令冻结,重启须用户发令);布告板点开的图鉴=现行占位态(T3 定义占位壳),不是禁用态(camp.md v2.2)。
|
||||
|
||||
🔴 **契约 6 · 冒险进行中不开营地**(澄清③6):营地是存档语境(局外)枢纽,现状口径延续;局内只读面=状态面板(在役,本批零改动——其「营地三柜台进度」文案若因拆解失义,列反哺点归文档批订正)。
|
||||
|
||||
🔴 **契约 6 · 冒险进行中不开营地**(澄清③6):营地是存档语境(局外)枢纽,现状口径延续;局内只读面=状态面板(在役,本批零改动——其「营地三柜台进度」文案若因拆解失义,列反哺点归文档批订正)。
|
||||
🔴 **契约 7 · 美术硬约束+10 层红线**:48 色板、HSV 300°–345° 禁入带、语义色纪律、WCAG ≥4.5:1(F15);场景素材全局纹理过滤=Nearest(project.godot 现行默认,像素纪律)。**10 层拆分按 §0.4**:z0 bg 不透明全幅(含门洞小路)、z1 wall 透明细条 (0,240,1280,70) 门洞 x520–760 留透明缺口、z2–z6 八物件层;围墙禁并回背景层、门洞禁填死、门洞禁被任何物件遮挡。点选反馈四态(悬停=轮廓亮边+浮动〔整像素吸附〕+名牌〔物件下方 8px 居中、字号 14、对比 ≥4.5:1〕/按下=位移 1px/禁用=降明度+去饱和〔仅锻炉、宝箱〕/已解锁=常态)零新素材、全程序化;命中区两两不相交、不越画面、不侵入顶栏禁区 y≤48。篝火命中矩形只取下半(火堆),火焰只展示。
|
||||
|
||||
🔴 **契约 7 · 美术硬约束**:48 色板、HSV 300°–345° 禁入带、语义色纪律、WCAG ≥4.5:1(F15);场景素材全局纹理过滤=Nearest(project.godot 现行默认,像素纪律)。
|
||||
🔴 **契约 8 · 像素规格不硬定**:尺寸档/色板/明度档只写指针(Q6 甲过渡口径=1280 工程档+烛光黄/木色,落 art-bible §6.2/art-assets-checklist §3.5,F16);卡内禁自定像素规格数值;终档置换归反哺点,执行归用户线;禁批内自补、禁 T0 现场发挥。
|
||||
|
||||
🔴 **契约 8 · 像素规格不硬定**:尺寸档/色板/明度档只写指针(战斗一屏样张批冻结的规格清单,F16);卡内禁自定像素规格数值;规格清单未产出时的输入缺口=Q6 裁定(禁批内自补、禁 T0 现场发挥)。
|
||||
🔴 **契约 9 · 迭代内验收=截图对比+终稿落盘口径**(澄清⑥):camp 截图须为场景图形态;用户实机目检=生命周期最后一步、统一进行、**不阻塞迭代**——目检项登记 07 清单即完成义务。**T1 终稿落 `game/assets/art/scene/` 的「验收」口径=迭代内验收**(截图对比+shot_checker 机检+样张过审留痕)——营地屏整屏样张按既定排队行延后(§0.5),不构成对 art-bible §7.5「前置」条的违背(§5 反哺点注)。
|
||||
|
||||
🔴 **契约 9 · 迭代内验收=截图对比+终稿落盘口径(v1.1 补)**(澄清⑥):camp 截图须为场景图形态;用户实机目检=生命周期最后一步、统一进行、**不阻塞迭代**——目检项登记 07 清单即完成义务。**T1 终稿落 `game/assets/art/` 的「验收」口径=迭代内验收**(截图对比+shot_checker 机检+方向稿用户选划)——营地屏整屏样张按既定排队行延后(§0),不构成对 art-bible §7.5「前置」条的违背(§5 反哺点注)。
|
||||
🔴 **契约 10 · 探针断言迁移契约**(属仓库既有测试纪律的卡内成文,非用户裁决):F8 全量位点逐点显式迁移并留痕;**现无 camp 逐像素 golden 基线**(F17:golden 现役仅棋盘三张+menu_boot)——本批不建 camp golden(「把不存在的东西列进迁移清单」禁),camp 截图验收=shot_probe 出图+shot_checker 语义断言段;若要新建 camp golden 须另裁登记(L3)。
|
||||
|
||||
🔴 **契约 10 · 探针断言迁移契约(v1.1 订正,属仓库既有测试纪律的卡内成文,非用户裁决)**:F8 全量位点逐点显式迁移并留痕;**现无 camp 逐像素 golden 基线**(F17:golden 现役仅棋盘三张+menu_boot)——本批不建 camp golden(「把不存在的东西列进迁移清单」禁),camp 截图验收=shot_probe 出图+shot_checker 语义断言段;若要新建 camp golden 须另裁登记(L3)。
|
||||
🔴 **契约 11 · 拆分边界纪律**(结构类卡必填,判据权威=`design/engineering/code-conventions.md` §1.1,本卡写条款、不复制定文):本卡含「四柜台拆解」,拆分沿**职责轴**不沿阈值轴——每个拆出单元(锻造/秘宝/天赋树/图鉴四界面 view)须有可陈述的职责语句与单一变化原因、须有集体身份(命不出名字、只能说「剩下的成员」的打包=凑计数袋,禁);「过阈值」只许作为发现信号,作为拆分或收拢的动机即违规;按纪律拆不出内聚单元 → 停卡呈报走豁免/还债通道,禁硬拆凑绿(写进 §8 L3)。实现报告逐件一行承载职责语句。
|
||||
|
||||
🔴 **契约 12 · 禁为机检文本保留无效成员**(重构类卡必填条款,与 code-conventions §1.1 同款):禁止为迎合机检消息文本(含计数)而保留或新增无效成员/别名;机检键与卡片契约互斥时,实现段一律停卡呈报,不得自造第三条路。
|
||||
|
||||
## 4. 范围边界
|
||||
|
||||
**做**:场景素材产出(渠道按 Q1 裁定);场景屏+七物件命中区与点选交互(反馈细节按 Q3 设计稿);四柜台拆解与五界面入口改挂(含 presenter 承接面改造);大门动线两分支+断点弹窗移位;篝火回主菜单;场景屏顶栏预留位;断言/探针迁移;反哺点清单。
|
||||
**做**:场景屏+10 层场景素材铺底+七物件命中区与点选交互(四态规格按 camp.md v2.2——§0.3 P3 已销号=camp.md v2.2 四态规格即设计稿);四柜台拆解与五界面入口改挂(含 presenter 承接面改造);大门动线两分支+断点弹窗移位;篝火回主菜单小动线(带二次确认);场景屏顶栏预留位;断言/探针迁移;反哺点清单。
|
||||
|
||||
**不做**(明示去向):
|
||||
- **不做贴图重构批**(澄清③1):柜台场景贴图/钥石顶栏图标/永久强化条目图标的达标化置换——搁置未废,待交互重做完形后重新评估立项(F12);
|
||||
- **不做贴图重构批**(澄清③1):柜台场景贴图/钥石顶栏图标/永久强化条目图标的达标化置换——搁置未废,待交互重做完形后重新评估立项(F12);
|
||||
- 不激活图鉴内容(契约 5);
|
||||
- 不改五界面功能与写口链路(契约 4);
|
||||
- 不改冒险屏/选路屏/战斗屏本体(F7 已实现不动);
|
||||
- 不做整屏样张闸、不替代样张批、不新建 camp golden(§0/契约 10);
|
||||
- 不改冒险屏/选路屏/战斗屏本体(F7 已实现不动);
|
||||
- 不做整屏样张闸、不替代样张批、不新建 camp golden(§0.5/契约 10);
|
||||
- 局内状态面板零改动(契约 6);
|
||||
- 素材后处理与入库属实现段 T1/`asset-ingest` 第 3 步(§0.3-4 授权形态:/iter 开工令即含授权),不属写卡门;
|
||||
- ESC 浮窗与顶栏 HUD 实现 → 卡⑤(本卡只留顶栏位+定义刷新单口);
|
||||
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①。
|
||||
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①。
|
||||
|
||||
## 5. 关联文档同步面
|
||||
|
||||
> **v1.3 口径**:本批禁写 `design/` 整目录与根规则文件,唯一可写目录 = `reports/`;下表一律执行为列进反哺点清单。美术素材产物按素材线纪律落 `artwork/`(在途)→ `game/assets/art/`(终稿),不随 git 合并(F14)。
|
||||
> **现行口径**:实现批禁写 `design/` 整目录与根规则文件,唯一可写目录=`reports/`(+`game/` 实施本体);设计权威文档(GDD/art-bible)与机械面文档(roadmap/体验验证清单/README)对代码实现批一律不直改,逐条列进 `reports/iter<N>-反哺点-<日期>.md`,用户裁决后归文档批落文;本卡全表义务格一律为「反哺点 · 列清单」。camp.md v2.2/art-bible v3.31 §6.2 已先行落文 10 层新形态,本批实现=对齐现行条款,反哺义务为**实装状态回填+目检结论**,非形态改版。美术素材产物按素材线纪律落 `artwork/`(在途)→ `game/assets/art/scene/`(终稿),不随 git 合并(F14)。
|
||||
|
||||
| 文档 | 关联点 | 同步义务 |
|
||||
|---|---|---|
|
||||
| `design/gdd/ux/camp.md` | :14-20 布局与交互节(三柜台列/顶栏/底栏)+:10 定位句(主菜单入口)+头注事实源声明(=camp_overlay_view.gd 实态)——四柜台形态整体退役、入口改挂场景物件 | 反哺点 · spec 整体改版重写(形态节退役+新形态成文) |
|
||||
| `design/art/art-bible.md` | §6.2 营地场景(三柜台一字排开→交互式场景纵深稿);§7.5 营地界面(三柜台画法→五界面画法+场景图画法);§2.8 承载元素;营地屏整屏样张排队行注记(本批不跑闸);**§7.5「视觉终稿以表现层样张过审为前置」条与本批的关系=样张排队行既定延后(终稿后再出样),防文档批误判违例**(v1.1 补注) | 反哺点 · 列清单(权威面零直改,过用户裁决后归文档批) |
|
||||
| `design/gdd/systems/跨局循环/生涯.md` | :69 与营地边界表(条带 `_rebuild_recent` 随 CampOverlay 拆解去向=Q4);:63 图鉴挂起条(入口改挂注记) | 反哺点 · 列清单(P6 去留随 Q4 裁定) |
|
||||
| `design/gdd/ux/camp.md` v2.2 | §定位/§场景构成与七物件绑定/§点选反馈/§顶栏/§叠层与开合:新形态已落文,本批实现后回填实装状态、样张过审留痕、实机目检结论 | 反哺点 · 列清单(实现批禁写 `design/`) |
|
||||
| `design/art/art-bible.md` v3.31 | §6.2 营地场景 10 层口径已落文;§7.5 营地界面画法、§2.8 承载元素、§1.4 营地屏整屏样张排队行注记(本批不跑样张闸) | 反哺点 · 列清单(权威面零直改,过用户裁决后归文档批) |
|
||||
| `design/art/camp-scene-prompts.md` v1.3 | §5「待裁」节五点已裁断(2026-11-01 用户裁:①帐篷追认现值②门扇追认现值③布告板 (845,268,130,140)④描边奶油色追认⑤环境子板色值不前置、T1 量化后按 §4.1 登记)——**已落文(2026-11-01 本会话文档批):camp-scene-prompts.md v1.3 §5 改已裁+art-bible.md v3.31 §6.2 待裁行改已裁,义务了结** | 已落文 · 义务了结 |
|
||||
| `design/gdd/systems/跨局循环/生涯.md` | :69 与营地边界表(条带 `_rebuild_recent` 随 CampOverlay 拆解去向=Q4 已裁甲);:63 图鉴挂起条(入口改挂注记) | 反哺点 · 列清单 |
|
||||
| `design/gdd/08-Alpha版本标准.md` | 「三 · 界面」营地行(:104)形态注记改写——状态列可改;注记改写列反哺点;增删行须用户裁(三卡统一口径) | 反哺点 · 列清单 |
|
||||
| `design/gdd/06-待办清单.md` | 本卡登记条;UI 贴图重构批条(:21-27)注记「四柜台对象变化、重评待交互重做完形」;图鉴挂起条注记 | 反哺点 · 列清单 |
|
||||
| `design/gdd/07-体验验证清单.md` | 新增实机目检条(场景观感/七物件辨识与点选反馈/大门两分支/篝火动线)——登记不阻塞 | 反哺点 · 列清单 |
|
||||
| `roadmap.md` | 迭代行编入/状态刷新 | 反哺点 · 列清单 |
|
||||
| `game/presentation/*`、`game/smoke/*`、`game/tests/**`(v1.1 补——forge_workbench_test 迁移面)、`game/tests/golden/*`(仅棋盘/menu 既有基线复跑)、`game/assets/art/*` | 实现/断言/终稿素材本体 | 实施本体(可写) |
|
||||
| `design/gdd/06-待办清单.md` | 本卡登记条;UI 贴图重构批条(:21-27)注记「四柜台对象变化、重评待交互重做完形」;图鉴挂起条注记 | 反哺点 · 列清单(实现批禁写待办清单) |
|
||||
| `design/gdd/07-体验验证清单.md` | 新增实机目检条(场景观感/七物件辨识与点选反馈/大门两分支/篝火动线)——登记不阻塞 | 反哺点 · 列清单(实现批禁写体验验证清单,入册条目由文档批落) |
|
||||
| `roadmap.md` | 迭代行编入/状态刷新 | 反哺点 · 列清单(实现批禁写 roadmap) |
|
||||
| `game/tests/README.md` | 能力行入表(§7 对照表「能力行」列定名) | **已入表**(旅程段六,本卡七条新增能力行在役;v3.1 V14 用例锚随批补)——实现批只核对名实一致,禁写 |
|
||||
| `game/presentation/*`、`game/probe/*`、`game/tests/**`(含 forge_workbench_test 迁移面)、`game/tests/golden/*`(仅棋盘/menu 既有基线复跑)、`game/assets/art/scene/*`(10 层终稿) | 实现/断言/终稿素材本体 | 实施本体(可写) |
|
||||
| `tools/shot_checker.py` | camp 取样面语义断言段(文字 WCAG/明度三档带/文字禁压纹理/文字在判据扩 camp) | 实施本体(可写,属工具/测试面) |
|
||||
|
||||
## 卡前·文件结构与职责(T0 前)
|
||||
|
||||
定义 T 卡前先列全本批新建/修改文件,一文件一职责。**每个文件行标「行为改动/非行为改动」并指向 §7 对照表行号;「落位」列与「落位与可复用性预检」节互指**(标「新建」的必须能在预检节指到不能复用的理由与唯一落点核查)。行号为开工日 T0 复核对象。
|
||||
|
||||
| 文件 | 职责 | 改动类型 | 落位 | 对照表行 |
|
||||
|---|---|---|---|---|
|
||||
| `game/presentation/views/camp_scene_view.gd` | 交互式营地场景图视图:10 层纹理铺底(z0–z6)+七物件命中区+点选反馈四态+名牌(节点选型=Control 根+TextureRect 层+子节点序即 z 序,T2) | 行为改动 | 新建 | V1/V2/V9/V10 |
|
||||
| `game/data/tables/camp_scene_layout.tres` | 10 层贴图矩形/命中矩形/z 序/门洞缺口坐标(数值单一事实源 `data/tables/`;schema 类+表现域容器类型化成员,先例 battle_layout.tres=`core/config_db.gd`/`core/config_domain_presentation.gd`;加载期 fail-fast 校验命中区几何,T2) | 行为改动 | 新建 | V1/V2/V9/V14 |
|
||||
| `game/presentation/views/camp_refresh_bus.gd` | 营地刷新单口:各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成(卡⑤ 同口挂接;头注自陈「非 autoload、非信号广播——组合根单点推送」) | 行为改动 | 新建 | V8/B1 |
|
||||
| `game/presentation/views/forge_view.gd` | 锻造工坊独立可开界面(自 CampOverlay `_forge_workbench` 抽出,界面逻辑复用) | 行为改动 | 新建(抽出) | V4/B2 |
|
||||
| `game/presentation/views/treasure_view.gd` | 秘宝匣独立可开界面(自 `_ws_scroll`/`_workshop_holder` 抽出) | 行为改动 | 新建(抽出) | V4/B2 |
|
||||
| `game/presentation/views/tree_view.gd` | 天赋树独立可开界面(自 `_tree_holder` 抽出) | 行为改动 | 新建(抽出) | V4/B2 |
|
||||
| `game/presentation/views/codex_view.gd` | 奖励格图鉴独立可开界面占位壳(内容保持挂起,契约 5) | 行为改动 | 新建(抽出) | V4/V6/B2 |
|
||||
| `game/presentation/scenes/camp_screen.gd` | 屏壳改造:持 camp_scene_view 取代 CampOverlay 成员+顶栏 HUD 预留位+模态栈单口 | 行为改动 | 复用既有(改造) | V1/V8 |
|
||||
| `game/presentation/views/camp_overlay_view.gd` | 四柜台覆盖层拆解后退役(无消费面即删,吸收即死) | 行为改动 | 退役 | V4/V9/B2 |
|
||||
| `game/presentation/views/career_overlay.gd` | 生涯页入口自主菜单改挂帐篷旁笔记本(本体零改,返回钮文案禁含「营地」) | 行为改动 | 复用既有(改入口) | V5 |
|
||||
| `game/presentation/views/confirm_dialog.gd` | 三钮化(继续上一段冒险/开始新冒险/取消) | 行为改动 | 复用既有(改) | V3/B1 |
|
||||
| `game/presentation/camp_shop_presenter.gd` | 投影目标改线+写口尾刷新改路由+open/close 编排迁位(契约 4;路径订正——v3.0 写 `presenters/` 子目录不存在) | 行为改动 | 复用既有(改) | V4/V8/B1 |
|
||||
| `game/presentation/camp_flow_context.gd` | 类型化字段语义订正(路径订正——v3.0 写 `core/` 子目录不存在) | 行为改动 | 复用既有(改) | V4/B1 |
|
||||
| `game/presentation/ui_camp_modals.gd` | 营地域模态句柄子容器(卡⑥ 前置建件;本卡 T3 落场景根+四子界面五枚句柄,卡⑤ T1 落浮窗句柄;寻址 `ui.modals.camp.X` 二层) | 行为改动 | 新建(卡⑥) | V1/V8 |
|
||||
| `game/presentation/ui_modals.gd` | 本卡零句柄新增(营地域句柄落 ui_camp_modals.gd 子容器,2026-11-01 用户裁);类变量 14 不升(S13 预期,见「实现规范预算·存量触面一查」) | 非行为改动(卡④ 段零改) | 复用既有 | V1/V8 |
|
||||
| `game/presentation/main_ui_build.gd` | 新层实例化装配点:各 `.new()`+装配尾 `apply_layer_contract(root)`(先例 :105/:121/:242);五句柄赋值经 `modals.camp.X` 子容器 | 行为改动 | 复用既有(改) | V1/V8 |
|
||||
| `main.gd`(组合根) | 断点弹窗移位+ConfirmDialog 三钮消费方编排+营地入口改挂+篝火动线+开层互斥/关层收闭 | 行为改动 | 复用既有(改) | V3/V4/V7/B1 |
|
||||
| `game/assets/art/scene/scene_camp_*.png`(10 张) | 10 层场景素材终稿(asset-ingest 第 3 步拷入,命名对齐 `UiKit.TEX_CAMP_*`——常量十键本批在 `ui_kit.gd` 新增) | 非行为改动(美术资源) | asset-ingest | V1/V10 |
|
||||
| `game/probe/shot_probe.gd` | camp 截图路径改场景图+收闭改接篝火动线 | 非行为改动(测试面) | 复用既有(改) | V1 |
|
||||
| `game/probe/ui_click_probe.gd` | 七物件可达+大门两分支+断点确认段改走大门+写口链迁移+深员改指 | 非行为改动(测试面) | 复用既有(改) | V2/V3/V4 |
|
||||
| `game/probe/ui_probe.gd` | 营地入口/余额/秘宝匣深员改指新界面 | 非行为改动(测试面) | 复用既有(改) | V4 |
|
||||
| `game/probe/screen_flow_probe.gd` | 营地旗标新语义+回退段改新场景根 closed/篝火动线 | 非行为改动(测试面) | 复用既有(改) | V7 |
|
||||
| `game/probe/ui_struct_probe.gd` | 反参照结构禁词+生涯段驱动改接+图鉴占位锚定+camp 场景层序段(V1 补立) | 非行为改动(测试面) | 复用既有(改) | V1/V5/V6/V9 |
|
||||
| `game/probe/ui_contrast_probe.gd` | 营地令牌段核签(CAMP_HEADER_BAND/CAMP_ROW_PLATE 消费判定) | 非行为改动(测试面) | 复用既有(改) | V10 |
|
||||
| `game/tests/system_test.gd`+`game/tests/unit/presentation/theme_projection_test.gd` | V2 实例化/V3g 模态开合改指(system_test :67-68/:520-541)+四柜台等高源码断言段重写或注销(theme_projection_test :710-717)——`game/smoke/smoke_all.gd` 已退役,v3.0 旧位点作废 | 非行为改动(测试面) | 复用既有(改) | V4/B2 |
|
||||
| `game/tests/unit/presentation/forge_workbench_test.gd` | 随锻造视图抽出同迁(断言零改、只换承载类) | 非行为改动(测试面) | 复用既有(改) | V4/B2 |
|
||||
| `tools/shot_checker.py` | camp 取样面语义断言段 | 非行为改动(工具/测试) | 复用既有(改) | V10 |
|
||||
| `game/tests/README.md` | 能力行入表(四列:能力|系统|真实入口|代表用例) | 非行为改动(文档,写卡段) | 主 Agent 统一收口 | 全表能力行 |
|
||||
| `reports/iter<N>-实现报告-<日期>.md`/`reports/iter<N>-反哺点-<日期>.md`/`reports/iter<N>-验收审计-<日期>.md` | T6 三份产出物 | 非行为改动(过程件) | 新建 | T6 |
|
||||
|
||||
## 落位与可复用性预检
|
||||
|
||||
定义 T 卡前,对本批每个**新增文件/新增函数/新增数据件**过三问(复用面/唯一面/分层与交互面),与「卡前·文件结构与职责」互指。生效=2026-10-21 用户立规;本卡虽文件名日期 2026-10-18,经 2026-10-31 用户明令重立为现行有效卡,按现行规则补齐。
|
||||
|
||||
### 新增件三问
|
||||
|
||||
| 新件 | 复用面(grep 同职责实现) | 唯一面(grep 同名同义标识符) | 分层与交互面(调用路径+跨层出口) |
|
||||
|---|---|---|---|
|
||||
| `camp_scene_view.gd` | 盘上视图件=CampOverlay(四柜台覆盖层,形态本批退役、与场景图形态正交,反参照禁复用)、CareerOverlay(生涯全屏页,职责不同)、camp_screen.gd(屏壳)。**无**「场景图铺底+七物件命中区+点选反馈」同职责实现 → 不能复用,须新建视图件;屏壳复用既有 `camp_screen.gd` 改造,不新建屏壳 | grep `camp_scene`/`scene_camp` 视图标识符盘上无第二处;素材消费常量 `UiKit.TEX_CAMP_*` 单点(asset-path-map.md §3),不另立路径常量 | 呈现层视图,零 Core 写调用;命中区 `_gui_input()` → `object_pressed(key: String)` 信号 → 组合根 → 开界面/写口;10 层装载经 `UiKit.load_tex()`(exists 守卫、禁 preload);不直连 MetaProgression |
|
||||
| `camp_scene_layout.tres` | grep `game/data/tables/` 无营地坐标表;坐标草案在 artwork HTML(不入 git)与 camp-scene-prompts §2.3(设计文档,非运行时数据源)。数值单一事实源要求落 `data/tables/` → 新建 | 坐标事实只此一处;禁在 `camp_scene_view.gd`/探针/T 卡各写一份坐标字面量(契约 8 禁自定规格、数值单点) | 视图启动时经 ConfigDB 单点读取(schema 类+表现域容器类型化成员,先例 battle_layout.tres);坐标值按 §0.3-3 五裁点裁断(2026-11-01)由 T2 定值落入 |
|
||||
| `camp_refresh_bus.gd` | grep 现役 `refresh_camp` 绑定 CampOverlay 句柄(F5),随四柜台形态**退役**(卡⑤/§0.5 明确「非已退役的 refresh_camp」);新单口须同时刷新现开界面与场景根 HUD、职责不同 → 不能复用,须新建 | grep `camp_refresh`/刷新单口类标识符盘上无第二处;卡⑤ HUD 刷新挂此单口,不另立第二口 | 组合根拆件:七写口尾 → `CampRefreshBus.refresh(camp_data: Dictionary) -> void` → 现开界面刷新+场景根 HUD 刷新;一次性刷新,不新增写口语义(契约 4) |
|
||||
| `ui_camp_modals.gd`(卡⑥ 建件,本卡落五枚) | grep 句柄分域容器无先例;`UiModals` 本体=按技术角色平铺的注册面容器(职责不同)、`ModalFlow`=调度器非句柄册 → 不能复用,须新建(卡⑥ 已立卡) | grep `UiCampModals`/`ui_camp_modals` 无第二处;营地句柄寻址唯一落点 | RefCounted 不挂树;`main_ui_build` 构造注入 `ui_modals.camp`;`register_layer`/LAYER_CONTRACT/树序零触碰(句柄册结构≠树结构) |
|
||||
| `forge_view.gd`/`treasure_view.gd`/`tree_view.gd`/`codex_view.gd` | 界面逻辑**已实现**于 CampOverlay 内(F4:`_forge_workbench`/`_ws_scroll`/`_tree_holder`/图鉴占位);本批是抽出承载壳、**复用既有界面逻辑**(行板/写口链路零重设计,契约 4),非从零新写 → 新建壳、迁移逻辑 | grep `forge_view`/`treasure_view`/`tree_view`/`codex_view`/`_forge_rows`/`_forge_workbench` 盘上无第二处定义;`forge_workbench_test.gd:33` 消费 `_forge_rows`/`_forge_workbench`,抽出后同迁,断言零改只换承载类 | 各视图发意图信号(`buy_requested`/`tree_buy_requested`/`forge_*`)→ 组合根 → CampShopPresenter → MetaProgression 写口(Core 零 UI 不破);五界面各带返回/关闭钮;开合走模态栈单口、层序入 `LAYER_CONTRACT` |
|
||||
|
||||
### 非新增件说明
|
||||
|
||||
- `camp_screen.gd`/`camp_shop_presenter.gd`/`camp_flow_context.gd`/`confirm_dialog.gd`/`career_overlay.gd`/`main.gd`:存量文件改造,不新增文件;公开方法/成员预算见「实现规范预算」存量触面一查。
|
||||
- `camp_overlay_view.gd`:四柜台拆解后无消费面即删(吸收即死),禁留死代码;`main.camp_overlay` 探针句柄迁移留痕(F2/F8)。
|
||||
- `game/tests/golden/*`:棋盘三张+menu_boot 既有基线复跑,不新建 camp golden(契约 10)。
|
||||
- **数据件**:本卡纯呈现层,零玩法数值、无新增 `data/tables/` 玩法表(`camp_scene_layout.tres` 为呈现坐标件,非玩法数值);数值单一事实源 `data/tables/` 不被玩法值触碰;RNG 零新增(RNG 单点 RngService 不被触碰);Core 零 UI 依赖不因新增场景屏绕过。
|
||||
|
||||
## 实现规范预算
|
||||
|
||||
定义接口块/文件结构图前,对本批每个**新增文件**对照 gdstyle 默认阈值做预算,与接口块及「卡前·文件结构与职责」互指。**生效说明**:规范写「生效=文件名日期 ≥2026-10-27,此前卡片属历史留档不回头改」——本卡经 2026-10-31 用户明令重立为现行有效卡,按现行规则补齐,不援引「不回头改」跳过。gdstyle v0.4.0 默认阈值:**公开方法 ≤20、类变量 ≤15、单函数分支 ≤8、返回 ≤6**(阈值取工具默认,改阈值=基线口径变须在本批重生成)。
|
||||
|
||||
### 新件三查
|
||||
|
||||
| 触面 | ①公开方法数 | ②成员变量数 | ③迁移函数对账 | 结论 |
|
||||
|---|---|---|---|---|
|
||||
| `camp_scene_view.gd` | 预期 ≤8:`setup_layers()`/`bind_hotspots()`/`set_feedback_state()`/`get_hotspot_rect()`/`set_hud_band()`/`_on_hotspot_input()` 等,远低 ≤20 | 预期 ≤12:10 层纹理句柄+命中区表+反馈态+名牌节点;收编进内聚结构,低 ≤15 | 无自存量文件迁入函数 | 三查通过;T0 实测实数回填,超阈值即拆件或砍面(砍面=退设计段裁职责) |
|
||||
| `camp_refresh_bus.gd` | 预期 ≤3:`refresh()`/`bind_targets()`/`_dispatch()`,远低 ≤20 | 预期 ≤4:现开界面句柄+场景根 HUD 句柄+投影数据,低 ≤15 | 自 `camp_shop_presenter.gd` 迁入刷新路由;先查 `tools/gdstyle_baseline.txt` 源函数键,branches/returns/函数长超默认登记值的迁移即拆函数(拆分不改语义,不算迎合机检) | 三查通过;迁入后补跑 S13,不凭旧读数放行 |
|
||||
| `ui_camp_modals.gd`(卡⑥ 建件) | 预期 ≤1(`_init`) | 预期 5(本卡 T3 落五枚;卡⑤ 落满 6),低 ≤15 | 无迁入函数 | 三查通过(卡⑥ 卡面已立预算) |
|
||||
| 四界面 view(各) | 各预期 ≤6:`open()`/`close()`/`bind_rows()`/`_on_action()` 等,远低 ≤20 | 各预期 ≤10:复用既有行板成员(`_forge_workbench`/`_ws_scroll`/`_tree_holder`),低 ≤15 | 自 `camp_overlay_view.gd` 迁入对应界面函数;逐个对 `tools/gdstyle_baseline.txt` 源键,超登记值即拆函数 | 三查通过;抽出后实测实数回填 |
|
||||
| `camp_scene_layout.tres` | 不适用(数据件,无方法) | 不适用(结构键,非类变量) | 不适用(无迁入函数) | 结构键唯一,坐标值按 §0.3-3 五裁点裁断(2026-11-01)由 T2 定值落入 |
|
||||
|
||||
### 存量触面一查
|
||||
|
||||
本卡触碰存量文件:`camp_screen.gd`/`camp_shop_presenter.gd`/`camp_flow_context.gd`/`confirm_dialog.gd`/`career_overlay.gd`/`camp_overlay_view.gd`(退役)/`main.gd`/`ui_modals.gd`/`ui_registry.gd`/`main_ui_build.gd`/探针七件/`forge_workbench_test.gd`。**T0 读数步骤写明「S13 键较 `tools/gdstyle_baseline.txt` 登记值只降不升」的预期与达成手段**:`ui_modals.gd` 类变量 14→14(−平铺 `camp_overlay`+camp 容器成员由卡⑥ 建件承担——营地域句柄一律落 `ui_camp_modals.gd` 子容器,2026-11-01 用户裁,禁平铺);`ui_registry.gd` +camp 二层解析分支(分支数 ≤8);`main_ui_build.gd` 装配行改指(方法面微增,T0 实测对账);CampOverlay 拆解=删四柜台代码(键只降);`camp_shop_presenter.gd` 改造=投影目标改线、不新增公开方法/成员;`main.gd` 组合根=断点弹窗移位+消费方编排(新增私有状态量一枚,S13 类级键只降不升);探针改接=替换断言段、不新增扫描面键。任何 S13 键被迫上升=§8 L3 停卡。
|
||||
|
||||
### 指标例外通道
|
||||
|
||||
现预算内,无需例外。若场景视图十层句柄+七命中区+反馈态实测超 15 类变量,或组合根成员超基线,设「指标例外申报」节——键名+理由+用户特批落基线;未申报的超预算面进实现段=停卡退回写卡段(写进 §8 L3)。
|
||||
|
||||
## 6. 任务卡
|
||||
|
||||
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。**估时主变量=美术渠道(Q1 待裁)、点选反馈设计稿往返(Q3)与规格输入(Q6)**。
|
||||
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。步骤用 `- [ ]` 复选框记步,一步=一个动作+一个可核查结果;每卡声明「取用/产出」接口块,后卡引用的名字与早卡定义逐字一致;禁占位待定句式(不决定任何事的行不留)。**天然切分点=T1 出口**(场景素材归档齐)——美术线与代码线可分批交付(用户批次归属裁);若单批跑超迭代盒,T3 末(四柜台拆解完)为次切分点。
|
||||
|
||||
### T0 事实坐实与设计输入齐备检查(≈0.5d)
|
||||
|
||||
- 复核 §2 全部行号;四柜台界面清单与探针面清单(F8)逐点过;
|
||||
- 设计输入齐备检查:Q1(美术渠道)/Q2(参照物)/Q3(点选反馈细节)/Q4(条带去留)/Q5(三出口弹窗)/Q6(规格缺口)状态逐项核——**未裁项对应的任务段禁开工**(缺输入=呈报,禁批内自补);
|
||||
- 规格清单依赖核检:战斗一屏样张批(06 待设计)产出时点 vs 本批排期——按 Q6 裁定执行(禁 T0 现场发挥);
|
||||
- 与卡③对齐 ConfirmDialog 消费方编排机制(T4 互指)、与卡⑤对齐顶栏位与刷新单口(§0 跨卡接口)。
|
||||
- 取用:待办清单条目状态(文档设计已闭合+美术设计已闭合+已写卡)、§0 重立凭据、art-bible v3.31 §6.2、camp.md v2.2、camp-scene-prompts.md v1.2、`_终稿裁定-2026-10-31.txt`、布局草案-1280x800.html。
|
||||
- [ ] 复核 §2 F1–F20 全部 `file:line` 行号;四柜台界面清单与探针面清单(F8)逐点过——漂移即停卡核对,不猜行号。
|
||||
- [ ] 设计输入齐备检查:Q1(美术渠道=B 已裁)/Q2(参照物已补)/Q4(条带=甲)/Q5(三钮=甲)/Q6(过渡口径=甲)/Q8(出稿方式=甲)状态逐项核为已裁;**代码段开工门**(§0.3 四项)状态逐项核为已裁断销号(2026-11-01)——若发现裁断实况反转=L3 停机呈报,禁批内自补。
|
||||
- [ ] **新场景根句柄名+四子界面(forge/treasure/tree/codex view)+场景层 `LAYER_CONTRACT` 槽名定稿**(显式验收点,2026-11-01 双审补立——卡⑤ 只消费不改名);句柄落 `ui_camp_modals.gd` 子容器(卡⑥ 前置建件,寻址 `ui.modals.camp.X` 二层)+`main_ui_build.gd` 装配点(卡⑤ v1.5 文件表同步列)。
|
||||
- [ ] **跨卡排序登记**:camp 断言基线建立在无 HUD 场景屏(本卡 T5);卡⑤ T2 落 HUD 后由卡⑤ 限 HUD 区显式更新+呈报(卡⑤ v1.4 §0 已对齐)。
|
||||
- [ ] 规格清单依赖核检:样张批规格清单产出时点 vs 本批排期——按 Q6 甲过渡口径执行(1280 工程档+烛光黄/木色,终档置换归反哺点),禁 T0 现场发挥。
|
||||
- [ ] 跑 `bash tools/static_scan.sh` 开发期局部读数(gdstyle 键=S13,闸件 `tools/gdstyle_gate.py`——原 `tools/gdstyle.sh` 不存在,v3.1 订正),记录 `camp_screen.gd`/`camp_shop_presenter.gd`/`main.gd` 当前行数、类变量、公开方法数;登记 S13 基线键(预期只降不升)。本步为最窄确认,不构成验收。
|
||||
- [ ] 与卡③ 对齐 ConfirmDialog 消费方编排机制(T4 互指)、与卡⑤ 对齐顶栏位与营地刷新单口(§0.5 跨卡接口)。
|
||||
- 产出:基线 commit、S13 实数、设计凭据核对表、代码段开工门未销号清单;后续卡只按本卡契约施工。
|
||||
|
||||
### T1 场景美术产出(≈2–4d,渠道 A/B 待裁 Q1)
|
||||
### T1 场景素材终稿录入(asset-ingest 第 3 步,≈1–1.5d;后处理授权随 /iter 开工令,§0.3-4)
|
||||
|
||||
- 按纵深稿构图(远景天空/中景围栏+大门/近景篝火居中/左锻炉铁砧/右床铺+宝箱)出场景图;七物件可辨性=第一合格线(玩家一眼找到点哪);
|
||||
- 美术硬约束入产线(契约 7):48 色板/禁入带/语义色/WCAG/Nearest;**色板机检二器复用**(palette_check.py 48 令牌+新增色双门/standee_asset_check.py 像素 32 色冻结——v1.1 订正:非「全仓无工具」);
|
||||
- 尺寸档=样张批规格清单指针(契约 8);按 Q6 裁定执行过渡口径或挂起;
|
||||
- 产物按素材线纪律落盘(F14):在途 `artwork/`(主区绝对路径)→ 验收后终稿 `game/assets/art/`;替换先归档旧档;**命名纪律**:art-bible §8.3:503(`<域>_<对象键>_<状态|变体>.png`)+doc-conventions §12 三段式「终稿文件名=代码消费名——先定资源路径常量,素材名跟它走,防断链」(v1.1 补指针);
|
||||
- 终稿落盘「验收」口径=契约 9(迭代内验收三件套);
|
||||
- **防不满意工序**:场景图先出 2–3 张低成本方向稿供用户选划,判完方向才精制(样张卡「方向稿先行」同型纪律;选划记录三段表进开工单)。⚠ 本条为**本卡自我从严的执行纪律**,非用户新裁决——用户若要以单路线直接精制,从其裁。
|
||||
- 取用:P1=B 渠道已裁(2026-10-22)、P4 参照物已补(2026-10-23)、Q6 甲过渡口径已裁(1280×800+烛光黄/木色、2× 源档最近邻降采样)、`_终稿裁定-2026-10-31.txt`(各素材第一张样本稿为终稿、保留全部待选稿)、camp-scene-prompts.md §2–§4。
|
||||
- [ ] 按终稿裁定清单核对十层指定文件(z0 bg/z1 wall/z2–z6 八物件层),确认各取第一张样本稿为终稿、其余候选保留不删。
|
||||
- [ ] 后处理(**授权形态已裁 2026-11-01:/iter 开工令即含本步授权**,不再两次发令):去底转透明(bg 不去底、全幅不透明)/擦通道水印/降采样/围墙层裁细条 (0,240,1280,70) 不做全幅/色板量化/四联底测试条——工具清单见 `design/art/art-pipeline-tools.md`。**降采样逐张登记换算式**(2026-11-01 双审补立):2560×1600 档=÷2 最近邻;**1024×1024 档无整数倍降采样(1024<1280)**——按非整数缩放显式特批登记(L2 记录+实现报告申报像素纪律局限),不回炉重出(追认 2026-10-31 已过审终稿优先、免美术线重开),禁现场默认。
|
||||
- [ ] 产物落盘:`artwork/`(在途,主区绝对路径)→ 验收后终稿 `game/assets/art/scene/`;替换先归档旧档;命名 `scene_camp_<键>.png` 对齐消费常量 `UiKit.TEX_CAMP_*`(常量十键本批在 `ui_kit.gd` 新增——先定资源路径常量、素材名跟它走,防断链;asset-path-map.md §3/art-assets-checklist.md §3.5);texture 导入口径=mipmaps 关、filter 跟项目默认(Nearest,project.godot 现行)。
|
||||
- [ ] 美术硬约束入产线(契约 7):48 色板/HSV 300°–345° 禁入带/语义色/WCAG/Nearest;**色板机检二器复用**(`palette_check.py` 48 令牌+新增色双门/`standee_asset_check.py` 像素 32 色冻结)。
|
||||
- [ ] 方向稿选划留痕:用户 2026-10-31 已裁「第一张样本稿为终稿、保留全部待选稿、每个都还可以接受」,选划三段表进开工单;本批不再重跑方向稿工序。
|
||||
- [ ] 终稿落盘「验收」口径=契约 9(迭代内验收:截图对比+shot_checker 机检+样张过审留痕)。
|
||||
- 产出:十层终稿入 `game/assets/art/scene/`(`UiKit.TEX_CAMP_*` 常量对齐)+素材线在途/归档清单;T2 可挂接。
|
||||
|
||||
### T2 场景视图与点选交互(≈1.5–2d)
|
||||
|
||||
- 场景屏承载(camp_screen 屏壳改造 vs 新屏壳——§9 拍板):场景图铺底+七物件命中区;
|
||||
- 点选交互:命中区判定+反馈形态按 Q3 设计稿(悬停高亮/提示文案/可点区域判定三项);
|
||||
- **场景屏顶栏预留位(v1.1 注明)**:卡⑤ HUD 落位;**刷新入口=本卡 T3 定义的营地刷新单口**(卡⑤同口挂接);
|
||||
- **叠层规则显式派生(v1.1 补)**:随 §9 第 2 条承载形态裁定派生并写入 V2 断言——独立全屏页=场景根隐藏(生涯先例);单一内页切换=场景根留底;「缩放虚化」是两选项之外的第三形态(涉新演出面+素材),禁批内自选(若设计稿/用户想要,升格裁点);
|
||||
- 键盘焦点/手柄不涉(08:191-192 排 Beta;ESC 属卡⑤用户明示裁决面)。
|
||||
- 取用:T1 十层终稿 `UiKit.TEX_CAMP_*`、`camp_scene_layout.tres` 坐标结构键、camp.md v2.2 点选反馈四态规格、§0.3 P3 已销号(camp.md v2.2 四态规格即设计稿)。
|
||||
- [ ] 节点选型(2026-11-01 godot-master 审查定案):**Control 根+TextureRect 层+子节点序即 z 序**;禁 CanvasLayer(绕开 LAYER_CONTRACT 树序落位)、禁 z_index、禁 Sprite2D 根(项目视图全 extends Control;全屏 UI canvas_items 拉伸需 Control 锚点;ui_registry.gd:76 落位口按子节点序 move_child)。命中区=TextureRect 分区+`_gui_input()`(§9-3 域内确认 TextureRect 分区)。
|
||||
- [ ] 在 `game/presentation/views/camp_scene_view.gd` 实现 `setup_layers()`:按 §0.4 z0–z6 铺 10 层(bg 不透明全幅/wall 透明细条 (0,240,1280,70)/门洞 x520-760 留透明缺口透出 bg 小路/八物件层);围墙不并回背景层、门洞不填死、门洞不被任何物件遮挡。
|
||||
- [ ] 实现七物件命中区 `bind_hotspots()` 与 `get_hotspot_rect()`:读 `camp_scene_layout.tres` 坐标键;七件两两不相交、不越画面、不侵入顶栏禁区 y≤48;篝火命中矩形只取下半(火堆),火焰只展示。
|
||||
- [ ] `camp_scene_layout.tres` 加载期 fail-fast 校验(2026-11-01 双审补立):七命中区两两不相交/不越画面/不侵 y≤48,违则致命中止(fail-fast 红线;契约 7 几何红线机检化)。
|
||||
- [ ] 实现点选反馈四态 `set_feedback_state()`(零新素材、全程序化):悬停=轮廓亮边+浮动(整像素吸附)+名牌(下方 8px 居中、字号 14、对比 ≥4.5:1)/按下=位移 1px/禁用=降明度+去饱和(仅锻炉、宝箱)/已解锁=常态。实现约束(2026-11-01 双审补立):悬停浮动位移经 Tween(禁 `_process` 逐帧移 UI);名牌 Label `mouse_filter = IGNORE`(防挡命中区,UiKit 惯例 ui_kit.gd:312/333);名牌位置加画面内钳制(贴底物件防出画);禁用态去饱和经 ShaderMaterial(modulate 只能调明度,去饱和需 shader——零新素材、代码件)。
|
||||
- [ ] 场景屏顶栏预留位 `set_hud_band()`(高 48px 浮层覆盖、不挤压画面,卡⑤ 填值;载体循 UiKit `page_shell` 的 `PRESET_TOP_WIDE`+`custom_minimum_size` 先例 ui_kit.gd:523-525,禁手动 rect);刷新入口=本卡 T3 定义的营地刷新单口(卡⑤ 同口挂接)。
|
||||
- [ ] 叠层规则显式派生并写入 V2 断言:随 §9 第 2 条承载形态裁定派生——独立全屏页=场景根隐藏(生涯先例)/单一内页切换=场景根留底;「缩放虚化」是两选项之外的第三形态(涉新演出面+素材),禁批内自选(若设计稿/用户想要,升格裁点)。
|
||||
- [ ] 键盘焦点/手柄不涉(08:191-192 排 Beta;ESC 属卡⑤ 用户明示裁决面)。
|
||||
- 产出:`CampSceneView.setup_layers()`/`bind_hotspots()`/`set_feedback_state()`/`get_hotspot_rect()`/`set_hud_band()`,`object_pressed(key: String)` 信号;T3 按接口块接线。
|
||||
|
||||
### T3 四柜台拆解与入口改挂(≈2–2.5d)
|
||||
|
||||
- 锻造工坊/秘宝匣/天赋树/图鉴四界面自 CampOverlay 抽出为独立可开界面(承载形态=§9 拍板:各自独立全屏页〔生涯先例〕vs 单一营地内页切换——约束=写口链路零改、零新素材);**五界面各带返回/关闭钮**(v1.1 补承诺——现四者共用 CampOverlay 底栏关闭钮随拆解消失,卡⑤ Q1 甲案前提即此);
|
||||
- 生涯页入口自主菜单生涯钮改挂床铺旁笔记本(CareerOverlay 本体零改);**生涯页返回钮文案禁含「营地」字样**(ui_struct_probe.gd:382 nojump 禁词表含「营地」——career_overlay.gd:27 现「返回」安全,改文案时避坑,v1.1 补坑注);
|
||||
- 入口改挂后各界面开合走模态栈单口;层序入 `LAYER_CONTRACT`;
|
||||
- **CampShopPresenter 承接面改造(v1.1 补条,契约 4)**:投影目标改线(五界面/场景根)、七写口尾刷新改路由(经营地刷新单口——**各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成**)、open/close 编排从 campbtn 迁位到卡③进档动作、CampFlowContext 字段语义订正、探针缝保缝(main.gd:1163-1171);改造纪律见契约 4(attune 尾不一致口保持原样);
|
||||
- **图鉴占位态(v1.1 补条)**:独立界面壳=§9 第 2 条承载形态;文案照录 camp_overlay_view.gd:168 现行锁文,「柜台结构位预留」中『柜台』称谓随形态订正(L2 记录,零新文案);V6 断言锚定新视图占位标签;
|
||||
- **开层互斥与关层收闭(v1.1 补条)**:营地开层时选档层被模态栈遮挡隐藏(卡③ T2 同口径);篝火/ESC 回主菜单=营地层与选档层同收+开始层恢复(现役 on_camp_closed 模式只视野开始层,选档层不在其视野——须显式);
|
||||
- CampOverlay 类退役处理(拆解后无消费面即删——吸收即死纪律);`main.camp_overlay` 探针句柄迁移留痕;
|
||||
- 最近冒险条带去向按 Q4 裁定执行。
|
||||
- 取用:T2 的 `CampSceneView`(`object_pressed(key: String)`)、F4 五界面实态、F5 写口链、§0.5 跨卡接口。
|
||||
- [ ] 锻造工坊/秘宝匣/天赋树/图鉴四界面自 CampOverlay 抽出为独立可开界面(`forge_view.gd`/`treasure_view.gd`/`tree_view.gd`/`codex_view.gd`,承载形态=§9 拍板;约束=写口链路零改、零新素材、界面逻辑复用);**五界面各带返回/关闭钮**(现四者共用 CampOverlay 底栏关闭钮随拆解消失,卡⑤ Q1 甲案前提即此)。
|
||||
- [ ] 按契约 11 拆分边界纪律落四界面:每界面写职责语句与单一变化原因(实现报告逐件一行)、有集体身份;禁凑计数袋、禁沿阈值轴硬拆;拆不出内聚单元=停卡呈报走豁免。
|
||||
- [ ] 生涯页入口自主菜单生涯钮改挂帐篷旁笔记本(CareerOverlay 本体零改);**生涯页返回钮文案禁含「营地」字样**(ui_struct_probe.gd:382 nojump 禁词表含「营地」——career_overlay.gd:27 现「返回」安全,改文案时避坑)。
|
||||
- [ ] 入口改挂后各界面开合走模态栈单口;层序入 `LAYER_CONTRACT`;五枚句柄(场景根+四子界面)落 `ui_camp_modals.gd` 子容器(卡⑥ 前置建件,寻址 `ui.modals.camp.X` 二层)——禁平铺回 `ui_modals.gd`(S13 上限,2026-11-01 用户裁)。
|
||||
- [ ] **CampShopPresenter 承接面改造(契约 4)**:投影目标改线(五界面/场景根)、七写口尾刷新改路由(经营地刷新单口——**各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成**)、open/close 编排从 campbtn 迁位到卡③ 进档动作、CampFlowContext 字段语义订正、探针缝保位(组合根薄委托缝,T0 复核现役行号——原引 main.gd:1163-1171 超出文件实长);`on_camp_attune_toggle` 口尾(:102)只 refresh_camp、不调 `_refresh_presentations` 保持原样。
|
||||
- [ ] 新建 `camp_refresh_bus.gd` 实现 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`(T0 接口块);卡⑤ HUD 刷新挂此单口,非已退役的 `refresh_camp`;头注自陈「非 autoload、非信号广播——组合根单点推送」(防被读成已否决的全局事件总线形态,2026-11-01 双审注)。
|
||||
- [ ] **图鉴占位态(契约 5)**:独立界面壳=§9 第 2 条承载形态;文案照录 camp_overlay_view.gd:168 现行锁文,「柜台结构位预留」中『柜台』称谓随形态订正(L2 记录,零新文案);V6 断言锚定新视图占位标签。
|
||||
- [ ] **开层互斥与关层收闭**:营地开层时选档层被模态栈遮挡隐藏(卡③ T2 同口径);篝火/ESC 回主菜单=营地层与选档层同收+开始层恢复(现役 on_camp_closed 模式只视野开始层,选档层不在其视野——须显式)。
|
||||
- [ ] CampOverlay 类退役处理(拆解后无消费面即删——吸收即死);`main.camp_overlay` 探针句柄迁移留痕。
|
||||
- [ ] 最近冒险条带去向按 Q4=甲执行(随四柜台拆解一并撤下,逐局历史回看归生涯,生涯.md P6 同批注销——反哺点)。
|
||||
- 产出:五界面独立可开(各带返回/关闭钮)+`CampRefreshBus.refresh()` 单口+CampOverlay 退役;T4 按接口块消费。
|
||||
|
||||
### T4 大门动线(≈1–1.5d)
|
||||
|
||||
- 大门点击→两分支确认弹窗(裁决 5):有断点=「继续上一段冒险/开始新冒险」二选一;无断点=「是否开始新冒险:是/否」;
|
||||
- **三出口弹窗形态(Q5 已裁=甲)**:ConfirmDialog 三钮化+**消费方编排**(组合根单实例+待确认消费方状态量:open 前设、confirmed/cancelled 后分派;禁每次 connect/disconnect 漂移、禁双常驻静态接线——卡③ 契约 3 同款互指);
|
||||
- 断点弹窗自主菜单移位(main.gd:475-497 逻辑整体迁来,卡②已摘除原调用);
|
||||
- 「继续上一段冒险」接现役续玩编排(`_resume_from_menu` 同源);「开始新冒险」接现役开局编排(`_start_adventure` 同源)——冒险屏/选路屏/战斗屏零改(F7);
|
||||
- 冒险发起后营地场景屏隐藏;**终局落点不变量(v1.1 补)**:现役口径=终局 continue 回主菜单(main.gd:703)——若后续改落点为营地,营地语境可能出现未收束会话,卡⑤「返回主菜单」动线须补 `_begin_session(false)`,两卡 T0 互证;
|
||||
- `_refresh_resume_button` **不复用**(大门两分支直读 `has_breakpoint`,无钮可刷——v1.1 明示,函数随卡②删,防两卡互以为对方在处理)。
|
||||
- 取用:T2 的 `object_pressed(key: String)`、T3 的 `CampRefreshBus`、F6/F7 断点弹窗与冒险编排、Q5 已裁=甲三钮化、卡③ ConfirmDialog 契约 3。
|
||||
- [ ] 大门点击→两分支确认弹窗(裁决 5):有断点=ConfirmDialog 三出口「继续上一段冒险/开始新冒险/取消」;无断点=「是否开始新冒险:是/否」;点大门永远先出确认、不直接进冒险。
|
||||
- [ ] **三出口弹窗形态(Q5 已裁=甲)**:ConfirmDialog 三钮化+**消费方编排**(组合根单实例+待确认消费方状态量:open 前设、confirmed/cancelled 后分派;cancelled 恒=无变更退回营地;禁每次 connect/disconnect 漂移、禁双常驻静态接线——卡③ 契约 3 同款互指)。
|
||||
- [ ] 断点弹窗移位:弹窗本体与两分支逻辑自组合根摘除位迁来(卡②已摘除原调用,main.gd:118-120 注释明载归本卡大门承接;main.gd:475-497 现为选档委托、非断点弹窗——旧引文失实,v3.1 订正)。
|
||||
- [ ] 「继续上一段冒险」接现役续玩编排(`_resume_from_menu` 同源);「开始新冒险」接现役开局编排(`_start_adventure` 同源)——冒险屏/选路屏/战斗屏零改(F7)。
|
||||
- [ ] 冒险发起后营地场景屏隐藏;**终局落点不变量**:现役口径=终局 continue 回主菜单(`main_adventure_flow.gd:123-143` 终局出口 `_begin_session(false)`——原引 main.gd:703 失实,v3.1 订正)——若后续改落点为营地,营地语境可能出现未收束会话,卡⑤「返回主菜单」动线须补 `_begin_session(false)`,两卡 T0 互证。
|
||||
- [ ] 篝火回主菜单动线:命中区只含火堆(不含火焰),**必须二次确认**(camp.md v2.2 已裁,走 ConfirmDialog 先例);确认后营地层与选档层同收+开始层恢复(T3 开层互斥/关层收闭同口径)。
|
||||
- [ ] `_refresh_resume_button` **不复用**(大门两分支直读 `has_breakpoint`,无钮可刷——函数随卡②删,防两卡互以为对方在处理)。
|
||||
- 产出:大门两分支+三钮消费方编排+篝火二次确认动线;T5 按接口块验收。
|
||||
|
||||
### T5 断言、探针与 golden 迁移批(≈2–2.5d)
|
||||
### T5 断言、探针与截图迁移批(≈2–2.5d)
|
||||
|
||||
- shot_probe:camp 截图路径改(进入存档→选档→进档→营地场景图);截图自检存在且非空;**camp 段收闭改缆(v1.1 补)**:现经「关闭营地」钮收闭(:133)——营地根态无关闭钮(出口=篝火/ESC),改篝火动线或调试直改 visible;
|
||||
- **无 camp golden**(契约 10):camp 验收=shot_probe 出图+shot_checker 语义断言段(文字 WCAG/明度三档带/文字禁压纹理/文字在判据扩 camp 取样面);棋盘/menu 既有 golden 复跑;
|
||||
- F8 全量位点逐点迁移(v1.1 补列项):
|
||||
- **探针深员改指表**:ui_probe `_balance_label`/`_tree_buy_btns`/`_workshop_rows`(:39-52)、ui_click_probe `_tree_buy_btns`/`_tree_fork_btns`+三处 `main.camp_overlay.refresh_camp(main._camp_data())` 直呼(:72/99/110)、ui_struct_probe audit 根(:45)——「改挂新入口」不够,这些是成员级耦合;七命中区与笔记本命中区的探针寻址名随 T2 命名稳定化一并定;
|
||||
- **smoke_all:6469-6475 源码断言段**:三条锁四柜台等高形态本身——按新形态重写或注销(四栏等高纪律是否迁入新界面=§9 第 2 条裁后定);
|
||||
- **ui_click_probe:500-528 断点确认段**:改走大门路径断言(与 V3 合并或互指;卡② T2 明列移交、本卡 T5 接收);
|
||||
- **ui_contrast_probe:48-55 营地令牌段**:核签(新界面仍消费 `CAMP_HEADER_BAND`/`CAMP_ROW_PLATE`=段留;不再消费=段随注销);
|
||||
- **forge_workbench_test.gd 单测**:随锻造视图抽出同迁(断言零改、只换承载类);V4 复跑清单补该单测;
|
||||
- **生涯段驱动改缆**:ui_struct_probe:54-69 与 shot_probe:103-124 现经 `_start_overlay`「生涯」钮驱动——改挂后须合成点击场景笔记本命中区;命中区若为 TextureRect/Area2D 而非 Button,`ProbeUiUtil.find_button` 失效,寻址面随 T2 扩展;
|
||||
- **screen_flow_probe 营地键新语义**::53 改指新场景根句柄;子界面开态时键真值按 T2 叠层规则派生;:119-125 回退段改新场景根 closed 信号或篝火动线;
|
||||
- **多卡共改文件分界**:screen_flow_probe(入口路径段归卡②、键语义/开合/篝火段归本卡)、ui_click_probe(入口路径归卡②、槽操作路径归卡③、营地段+断点确认段归本卡)——每条探针注分界;
|
||||
- 新增断言段:七物件逐一可达对应界面;大门两分支;点大门不直接进冒险;**点大门→开局后营地场景屏隐藏(v1.1 补)**;图鉴=占位挂起态;场景根态无文字按钮列表/无四柜台面板(反参照纪律断言);
|
||||
- 美术约束机检:shot_checker 现役段扩 camp 取样;截屏级 48 色计数是否新建=§9 第 5 条拍板(依赖样张批规格清单,随 Q6 一并裁);
|
||||
- **变异验证伴生**:某物件命中区漏绑(预期可达性断言红)、大门直连开局绕过确认(预期分支断言红)、图鉴内容激活(预期挂起态断言红)、**presenter 某写口尾漏挂新界面刷新**(预期余额/HUD 不同步红——v1.1 补)、**三钮弹窗取消被接成写档动作**(预期无变更退回红——v1.1 补);注入→最窄闸见红→精确还原→记录。
|
||||
- 取用:T2/T3/T4 全部产物、F8 全量探针位点、F17 机检工具面、契约 10。
|
||||
- [ ] shot_probe:camp 截图路径改(进入存档→选档→进档→营地场景图);截图自检存在且非空;**camp 段收闭改接**:现经「关闭营地」钮收闭(:133)——营地根态无关闭钮(出口=篝火/ESC),改篝火动线或调试直改 visible。
|
||||
- [ ] **无 camp golden**(契约 10):camp 验收=shot_probe 出图+shot_checker 语义断言段(文字 WCAG/明度三档带/文字禁压纹理/文字在判据扩 camp 取样面);棋盘/menu 既有 golden 复跑。
|
||||
- [ ] F8 全量位点逐点迁移:
|
||||
- [ ] 探针深员改指表:ui_probe `_balance_label`/`_tree_buy_btns`/`_workshop_rows`(:39-52)、ui_click_probe `_tree_buy_btns`/`_tree_fork_btns`+三处 `main.camp_overlay.refresh_camp(main._camp_data())` 直呼(:72/99/110)、ui_struct_probe audit 根(:45)——「改挂新入口」不够,这些是成员级耦合;七命中区与笔记本命中区的探针寻址名随 T2 命名稳定化一并定。
|
||||
- [ ] theme_projection_test.gd:710-717 四柜台等高源码断言段(`_smoke_element_details`)+system_test.gd V2 实例化(:67-68)/V3g 模态开合(:520-541):四柜台等高三条锁按新形态重写或注销(四栏等高纪律是否迁入新界面=§9 第 2 条裁后定)——`game/smoke/smoke_all.gd` 已退役,v3.0 旧位点作废。
|
||||
- [ ] ui_click_probe:500-528 断点确认段:改走大门路径断言(与 V3 合并或互指;卡② T2 明列移交、本卡 T5 接收)。
|
||||
- [ ] ui_contrast_probe:48-55 营地令牌段:核签(新界面仍消费 `CAMP_HEADER_BAND`/`CAMP_ROW_PLATE`=段留;不再消费=段随注销)。
|
||||
- [ ] forge_workbench_test.gd 单测:随锻造视图抽出同迁(断言零改、只换承载类);V4 复跑清单补该单测。
|
||||
- [ ] 生涯段驱动改接:ui_struct_probe:54-69 与 shot_probe:103-124 现经 `_start_overlay`「生涯」钮驱动——改挂后须合成点击场景笔记本命中区;命中区若为 TextureRect/Area2D 而非 Button,`ProbeUiUtil.find_button` 失效,寻址面随 T2 扩展。
|
||||
- [ ] screen_flow_probe 营地旗标新语义::54 改指新场景根句柄(:53 是菜单行,v3.1 订正);子界面开态时键真值按 T2 叠层规则派生;:119-125 回退段改新场景根 closed 信号或篝火动线。
|
||||
- [ ] 多卡共改文件分界:screen_flow_probe(入口路径段归卡②、键语义/开合/篝火段归本卡)、ui_click_probe(入口路径归卡②、槽操作路径归卡③、营地段+断点确认段归本卡)——每条探针注分界;分界锚=断言段语义/段名,不锚行号(一侧插删行会平移另一侧行号,2026-11-01 双审补立)。
|
||||
- [ ] 新增断言段(**正向验收断言,从真实入口进入、判据绑被测改动特有的可观测提交面**):七物件逐一可达对应界面;大门两分支;点大门不直接进冒险(绑 `confirmed` 信号与 `route_chosen` 未发);点大门→开局后营地场景屏隐藏;图鉴=占位挂起态;场景根态无文字按钮列表/无四柜台面板(反参照纪律断言);presenter 七写口尾→现开界面刷新+场景根 HUD 刷新一闸(绑刷新单口调用记录与 HUD 状态源取值);三钮弹窗 cancelled 恒=无变更退回营地(绑写口零调用+营地根 visible)。**判据绑不上=静态判据+评审注记申报观测面局限,证明做不出=停卡呈报;断言只在当轮真实跑批执行并通过,不做注入破坏。**
|
||||
- [ ] 美术约束机检:shot_checker 现役段扩 camp 取样;截屏级 48 色计数是否新建=§9 第 4 条拍板(**条件步**:§0.3-3⑤环境子板色值已按 T1 量化登记→拍板;未登记→本子步显式跳过+T6 登记遗留,不阻塞批末闸)。
|
||||
- [ ] **新增两条 headless 断言(2026-11-01 godot-master 审查补立)**:①`ui_struct_probe` camp 场景层序段——camp_scene_view 子节点序=layout 表 z 序逐层相等、各层纹理矩形与表逐值一致(本批核心视觉不变量的机器验收面);②`camp_scene_layout.tres` 加载期校验断言——载入数据件断言校验通过+七命中区几何(两两不相交/不越画面/不侵 y≤48),落 `game/tests/unit/presentation/camp_scene_layout_test.gd:_test_layout_hotspot_geometry`(新建单测件,随套件 manifest 登记)。
|
||||
- 产出:探针/断言迁移留痕表(F8 全量位点逐点「改前→改后」)+新增断言段;T6 收口。
|
||||
|
||||
### T6 产出物落位卡(≈0.5d,末卡)
|
||||
|
||||
三份 `reports/` 写齐(实现报告含方向稿选划记录三段表、探针迁移留痕表、变异记录表、目检总清单/代拍板追认单/反哺点清单)。
|
||||
- 取用:T0–T5 全部产物。
|
||||
- [ ] 里程碑步(波/T 段)出口跑一次代码域全套闸:`bash tools/run_all_gates.sh --code`;回执 `all_green=true`;任何新增红停卡,不得带红合回。波内修复只做出红最小单元的最窄确认;新增测试/工具先行孤立验证再并入全套。
|
||||
- [ ] 独立验收审计由未参与实现的会话/子代理执行,产出 `reports/iter<N>-验收审计-<日期>.md`;未过禁合并(审计入口见 §7)。
|
||||
- [ ] 轻闸全绿、合并前写齐三份 `reports/`:
|
||||
- [ ] `reports/iter<N>-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务+实现决定记录/代拍板追认单+探针迁移留痕表+方向稿选划留痕〔已由 2026-10-31 裁定〕);
|
||||
- [ ] `reports/iter<N>-反哺点-<日期>.md`(§5 每条有落点:文件/节/原句/拟改句/依据,明确「实现批未写 design/」);
|
||||
- [ ] `reports/iter<N>-验收审计-<日期>.md`(独立审计逐行「通过/缺漏/例外及依据」)。
|
||||
- [ ] 用户目检项登记 07 清单(场景观感/七物件辨识与点选反馈/大门两分支/篝火动线),登记完成即卡内义务了结,不阻塞批末收尾/合并/下一迭代开工。
|
||||
- 产出:三份 `reports/` 齐全+代码域闸全绿+验收审计通过,方算收口;合回后由本地 CI 全量域闸复验。
|
||||
|
||||
**估时合计 ≈9–12d**(v1.1 上调:presenter 承接面+三钮弹窗+坏槽态联动+探针深员面增量)。**天然切分点=T1 出口**(场景素材归档齐)——美术线与代码线可分批交付(用户批次归属裁);若单批跑超迭代盒,T3 末(四柜台拆解完)为次切分点。
|
||||
**估时合计 ≈9–12d**(presenter 承接面+三钮弹窗+探针深员面增量;T1 为素材录入、美术创作主体归美术自立批已完成)。
|
||||
|
||||
## 7. 验证闸(逐需求点验收清单)
|
||||
## 7. 验证闸:改动—验收对照表
|
||||
|
||||
| # | 需求点 | 测什么 | 落点/判定手段 |
|
||||
|---|---|---|---|
|
||||
| V1 | 场景图形态(机检半) | camp 截图=场景图形态(非四柜台覆盖层) | shot_probe camp 截图+shot_checker 结构禁词(与 V9 同)——**「七要素可辨(构图)」归 V11 目检**(v1.1 拆半:shot_checker 不判构图) |
|
||||
| V2 | 七物件可达性 | 点每物件→对应界面可见+营地场景按 T2 叠层规则退避 | ui_click_probe 七段合成点击(新断言;命中区寻址面随 T2) |
|
||||
| V3 | 大门两分支+开局收闭 | 有断点=弹二选一;无断点=弹是否开始;点大门不直接进冒险;点确认开局后营地场景屏隐藏 | 探针合成点击+状态断言(夹具经调试接口直写/清断点) |
|
||||
| V4 | 五界面功能+写口链零回归 | 树购买/Fork 切换/锻造三意图/秘宝购买/同调装配/图鉴占位——既有断言全链复跑绿;presenter 各写口尾的 MetaProgression 原语调用序列不变(v1.1 扩) | ui_click_probe 迁移段+smoke `_face_snapshot` 段+forge_workbench_test 迁移复跑 |
|
||||
| V5 | 生涯只读契约保持 | 生涯页经笔记本可达;页内零跳转零动效契约不破(三契约只约束页子树、不依赖入口位置——v1.1 证实原样成立) | ui_struct_probe career 段迁移复跑 |
|
||||
| V6 | 图鉴挂起态 | 布告板→图鉴=占位态;内容零激活 | 探针禁词/禁行断言(锚定新视图占位标签) |
|
||||
| V7 | 篝火动线 | 点篝火→营地隐藏+选档层同收+主菜单可见 | screen_flow_probe 型断言 |
|
||||
| V8 | 顶栏预留位 | 场景屏顶栏 HUD 位存在(卡⑤联验填值+刷新单口挂接) | 结构断言+跨卡联验 |
|
||||
| V9 | 反参照纪律 | 营地根态无文字按钮列表、无四柜台面板 | ui_struct_probe 结构禁词断言 |
|
||||
| V10 | 美术约束 | 文字 WCAG/明度三档带/文字禁压纹理底;素材色板(palette_check/standee 二器或截屏计数若建) | shot_checker 段扩 camp 取样+§9 第 5 条拍板面 |
|
||||
| V11 | 目检项登记 | 场景观感/七物件辨识(纵深稿构图可辨)/点选反馈/大门两分支/篝火动线入 07 | 件核(登记不阻塞,澄清⑥) |
|
||||
| V12 | 探针迁移留痕核验 | F8 全量位点逐点有「改前→改后」记录(契约 10 留痕义务) | 件核对表(T6 追认单) |
|
||||
| V13 | 反哺点清单 | §5 每条有落点 | 件核对表 |
|
||||
七格表:需求点|改动(文件:行/行为)|验收测试(名称+落点+尾缀)|层级(单元/接口/集成/探针)|真实入口|判据绑定面|能力行。**每个需求点至少一行;每个行为改动至少一行(V1–V13 需求点行+B1–B2 行为改动专行);每行必须有真实入口和判据绑定面——缺任一项=该需求点未验收,卡片不成立。** 断言尾缀〔营地图批 Vn〕/〔营地图批 Bn〕,与卡片清单互相 grep。能力行格式 `既有:<能力名>`/`新增:<能力名>`,两形态名称都须在 `game/tests/README.md` 能力表在场(既有=现役在场名,新增=本卡定名、由主 Agent 统一收口入表;本卡只写卡内能力行文字,README 由主 Agent 收口)。
|
||||
|
||||
**测试方式两分法**:V1–V10、V12 机检自动化(能力验证经调试接口直改断点/钥石/解锁状态,沿用 DebugOverlay/DS_DEBUG 门控);V11 归用户目检(生命周期末步统一进行,不阻塞迭代)。
|
||||
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| V1 场景图形态(机检半) | `camp_scene_view.gd` 10 层铺底(z0 不透明全幅含门洞小路/z1 透明细条 (0,240,1280,70) 门洞缺口/z2–z6);`camp_screen.gd` 改挂;`shot_probe.gd` camp 段 | `shot_probe.gd:_ready`(camp 截图段)〔营地图批 V1〕+`ui_struct_probe.gd:_ready`(camp 场景层序段)〔营地图批 V1〕+`shot_checker.py` 结构禁词段 | 探针 | 进入存档→选档→进档→营地场景屏(shot_probe 驱动) | camp 截图出图非空+shot_checker 结构禁词命中(无四柜台覆盖层/无文字按钮列表);camp_scene_view 子节点序=layout 表 z 序逐层相等、各层纹理矩形与表逐值一致(2026-11-01 双审补立——核心视觉不变量机器验收面);「七要素可辨(构图)」归 V11 目检 | 新增:营地场景图十层铺底与门洞留空呈现 |
|
||||
| V2 七物件可达性+叠层退避 | `camp_scene_view.gd` 七命中区+`object_pressed` 信号;`camp_scene_layout.tres` 坐标键;组合根开界面 | `ui_click_probe.gd:_ready`(七物件合成点击段)〔营地图批 V2〕 | 探针 | 命中区 `_gui_input()` → `object_pressed(key)` → 组合根开界面 | 七物件各自对应界面 visible 断言+场景根按 T2 叠层规则退避(树序/可见性);绑 `object_pressed` 信号发射面 | 既有:模态覆盖层编排与输入锁;新增:营地七物件命中区点选与分界面可达 |
|
||||
| V3 大门两分支+开局收闭 | `main.gd:475-497` 断点弹窗移位;`confirm_dialog.gd` 三钮化;消费方编排 | `ui_click_probe.gd:_ready`(大门两分支段/断点确认段 :500-528)〔营地图批 V3〕 | 探针 | 大门命中区 → ConfirmDialog(三出口)→ `main._on_confirm_new_adventure()`/`_resume_from_menu()` | 有断点三出口/无断点两出口;点大门不直接进冒险(绑 `confirmed` 信号与 `route_chosen` 未发);cancelled 绑写口零调用+营地根 visible;开局后营地场景屏隐藏 | 既有:断点片段往返与续玩幂等;新增:营地大门两分支确认与断点续玩接线 |
|
||||
| V4 五界面功能+写口链零回归 | 四界面 view 抽出;`camp_shop_presenter.gd` 承接面;`camp_flow_context.gd` 字段;`forge_workbench_test.gd` 迁移 | `forge_workbench_test.gd:_test_forge_rows`〔营地图批 V4〕+`ui_click_probe.gd:_ready`(写口链段)+`smoke_all.gd:_face_snapshot` 段 | 单元+探针 | 五界面意图信号(`buy_requested`/`tree_buy_requested`/`forge_*`)→ CampShopPresenter → MetaProgression 写口 | 树购买/Fork 切换/锻造三意图/秘宝购买/同调装配既有断言全链复跑绿;presenter 各写口尾 MetaProgression 原语调用序列不变(绑调用序列,不绑终态兜底) | 既有:元进度入账与锻造两轴;新增:四柜台拆解后五界面入口改挂与写口零回归 |
|
||||
| V5 生涯只读契约保持 | `career_overlay.gd` 入口改挂笔记本;`ui_struct_probe.gd`/`shot_probe.gd` 生涯段驱动改接 | `ui_struct_probe.gd:_ready`(career 段)〔营地图批 V5〕 | 探针 | 笔记本命中区 → `CareerOverlay.open()` | 生涯页经笔记本可达+页内零跳转零动效契约三断言不破(三契约只约束页子树、不依赖入口位置);返回钮文案禁含「营地」 | 新增:营地篝火回主菜单与笔记本改挂动线 |
|
||||
| V6 图鉴挂起态 | `codex_view.gd` 占位壳;布告板命中区 | `ui_struct_probe.gd:_ready`(占位禁词/禁行段)〔营地图批 V6〕 | 探针 | 布告板命中区 → 图鉴占位视图 | 锚定新视图占位标签(现行锁文「柜台结构位预留」称谓随形态订正)+内容零激活禁行断言;不是禁用态 | 新增:营地图鉴占位挂起态与反参照结构纪律 |
|
||||
| V7 篝火动线(二次确认) | `main.gd` 篝火回主菜单+开层互斥/关层收闭;`screen_flow_probe.gd` 段 | `screen_flow_probe.gd:_ready`(篝火/开合段)〔营地图批 V7〕 | 探针 | 篝火命中区(只下半火堆)→ ConfirmDialog 二次确认 → 主菜单 | 二次确认弹窗 `confirmed` 信号先于关层;确认后营地隐藏+选档层同收+主菜单可见(绑可见性/层序);命中区只含火堆不含火焰 | 新增:营地篝火回主菜单与笔记本改挂动线 |
|
||||
| V8 顶栏预留位+刷新单口 | `camp_scene_view.gd` 顶栏 HUD 位;`camp_refresh_bus.gd` 新建;presenter 七写口尾改路由 | `ui_struct_probe.gd:_ready`(顶栏位段)〔营地图批 V8〕+`ui_click_probe.gd:_ready`(写口尾刷新段) | 探针 | 写口尾 → `CampRefreshBus.refresh(camp_data)` → 现开界面刷新+场景根 HUD 刷新 | 场景屏顶栏 HUD 位存在(结构断言,高 48px 浮层);各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成(绑刷新单口调用记录与 HUD 状态源取值);卡⑤ 联验填值 | 新增:营地刷新单口与场景根 HUD 同步 |
|
||||
| V9 反参照纪律 | `camp_scene_view.gd` 根态;`camp_overlay_view.gd` 退役;`smoke_all.gd:6469-6475` 源码断言段 | `ui_struct_probe.gd:_ready`(结构禁词段)〔营地图批 V9〕 | 探针 | 营地根态场景树审计 | 营地根态无文字按钮列表、无四柜台面板(结构禁词断言);四柜台等高源码断言按新形态重写或注销(迁移留痕) | 新增:营地图鉴占位挂起态与反参照结构纪律 |
|
||||
| V10 美术约束 | `tools/shot_checker.py` camp 取样面;`ui_contrast_probe.gd` 令牌核签;素材色板二器 | `ui_contrast_probe.gd:_ready`(营地令牌段)〔营地图批 V10〕+`shot_checker.py` WCAG/明度三档带段 | 探针(机检) | camp 截图+素材文件(`palette_check.py`/`standee_asset_check.py`) | 文字 WCAG ≥4.5:1/明度三档带/文字禁压纹理底/文字在判据;素材色板(48 令牌+新增色双门/像素 32 色冻结);§9 第 4 条拍板截屏计数面(条件步,§0.3-3⑤) | 既有:UI 全局主题与按钮五态(含对比度锚);新增:营地场景图十层铺底与门洞留空呈现 |
|
||||
| V11 目检项登记 | `reports/iter<N>-实现报告-<日期>.md` 实机目检总清单 | 件核对(07 清单登记,登记不阻塞)〔营地图批 V11〕 | 用户目检(非自动化) | 用户实机(生命周期末步统一进行,不阻塞迭代) | 场景观感/七物件辨识(纵深稿构图可辨)/点选反馈/大门两分支/篝火动线入 07 清单=登记即义务了结 | 新增:营地场景图十层铺底与门洞留空呈现 |
|
||||
| V12 探针迁移留痕核验 | F8 全量位点逐点迁移 | 件核对表(T6 追认单)〔营地图批 V12〕 | 件核对(非自动化) | 探针脚本 diff 对账 | F8 全量位点逐点有「改前→改后」记录(契约 10 留痕义务) | 既有:模态覆盖层编排与输入锁;新增:营地七物件命中区点选与分界面可达 |
|
||||
| V13 反哺点清单 | §5 每条有落点 | 件核对表〔营地图批 V13〕 | 件核对(非自动化) | §5 同步面逐条对账 | §5 每条有 `reports/iter<N>-反哺点-<日期>.md` 落点 | 既有:模态覆盖层编排与输入锁 |
|
||||
| V14 layout 数据件校验(2026-11-01 新增) | `camp_scene_layout.tres` 加载期 fail-fast 校验(schema 类+表现域容器类型化成员,先例 battle_layout.tres) | `camp_scene_layout_test.gd:_test_layout_hotspot_geometry`(新建单测件 `game/tests/unit/presentation/`,随套件 manifest 登记)〔营地图批 V14〕 | 单元 | 单元测试载入 `camp_scene_layout.tres` | 校验函数通过+七命中区两两不相交/不越画面/不侵 y≤48(契约 7 几何红线机检化) | 既有:模态覆盖层编排与输入锁;新增:营地场景图十层铺底与门洞留空呈现 |
|
||||
| B1 组合根接线总改造(行为改动专行) | `main.gd`(断点弹窗移位+三钮消费方编排+营地入口改挂+篝火动线+开层互斥);`confirm_dialog.gd` 三钮;`camp_shop_presenter.gd` 写口尾路由;`camp_flow_context.gd` 字段;`camp_refresh_bus.gd` 单口 | `ui_click_probe.gd:_ready`(断点确认段)+`screen_flow_probe.gd:_ready`(篝火段)〔营地图批 B1〕 | 集成 | `_on_confirm_new_adventure()`/`_resume_from_menu()`/`_start_adventure()`/`CampRefreshBus.refresh()` | 三钮消费方编排:open 前设消费方、confirmed/cancelled 后分派;cancelled 绑写口零调用;写口尾绑 `CampRefreshBus.refresh()` 调用记录+现开界面+场景根 HUD 同刷;`on_camp_attune_toggle` 尾只 refresh_camp 保持原样 | 既有:断点片段往返与续玩幂等;新增:营地刷新单口与场景根 HUD 同步 |
|
||||
| B2 CampOverlay 退役+五界面抽出(行为改动专行) | `camp_overlay_view.gd` 退役;四界面 view 抽出;`career_overlay.gd` 入口改挂;`smoke_all.gd:6469-6475` 源码断言段 | `smoke_all.gd:_ready`(源码断言段重写)+`forge_workbench_test.gd:_test_forge_rows`(承载类换)〔营地图批 B2〕 | 集成 | 五界面 `open()`/`close()` → 模态栈单口 | CampOverlay 无消费面即删(吸收即死,绑 `main.camp_overlay` 句柄迁移留痕);四界面各带返回/关闭钮;拆分沿职责轴(契约 11:职责语句/单一变化原因/集体身份,禁凑计数袋) | 既有:元进度入账与锻造两轴;新增:四柜台拆解后五界面入口改挂与写口零回归 |
|
||||
|
||||
**闸口径**:轻闸每卡出口自跑;批末重闸按改动域选档(本批碰 `game/` 代码/断言/终稿素材 → `--code`)全绿才合并;MC 零跑(零数值零行为——纯呈现+承载迁移)。
|
||||
**落点集中**:V1/V9/V11/V12 → T5/T6;V2/V8 → T2/T3;V3/V7 → T4;V4/V5/V6 → T3;V10 → T5;V13 → T6;V14 → T2/T5;B1 → T3/T4;B2 → T3/T5。全表名实核对归 T6。
|
||||
|
||||
**测试方式两分法**:V1–V10、B1–B2 机检自动化(能力验证经调试接口直改断点/钥石/解锁状态,沿用 DebugOverlay/DS_DEBUG 门控,不走正常资源积累流程);V11 归用户目检(生命周期末步统一进行,不阻塞迭代);V12/V13 为件核对表(非自动化,T6 追认单)。**用户目检一律「登记不阻塞」**:登记完成即卡内义务了结,验收时间由用户自行安排,不得作为批末收尾、合并或下一迭代开工的前置条件。
|
||||
|
||||
**判据绑定面口径**:每个行为改动的验收断言从真实入口进入、判据绑被测改动特有的可观测提交面(信号/事件/入参/状态源取值/绘制记录/可见性/树序),在当轮真实跑批中执行并通过(2026-10-24/2026-10-28 用户两裁:断言从真实入口进、判据钉可观测提交面,人为制造红属伪造证据)。判据绑不上(纯防御分支、release 独有位)=静态判据+评审注记申报观测面局限,**证明做不出=停卡呈报**。配判据按强弱分层配齐:运行期断言(可见性/树序/状态源取值)抓状态类缺陷,golden 逐像素抓内容观感类缺陷(本卡无 camp golden,用 shot_checker 语义断言段+目检),占比/统计类判据只兜「整框空白/整框糊」、是补充不是主力(细则=test-conventions §8.4)。
|
||||
|
||||
**测试削弱申报**(实现期未申报的削弱由独立验收审计判红):允许改/删的旧断言逐条列——
|
||||
|
||||
| 旧断言 | 允许处置 | 理由 |
|
||||
|---|---|---|
|
||||
| `smoke_all.gd:6469-6475` 三条锁四柜台等高形态源码断言(`Vector2(0,336)`×3/`SIZE_FILL`×4/`SIZE_SHRINK_CENTER`≥3) | 按新形态重写或注销 | CampOverlay 四柜台形态退役,旧形态断言失去对象(吸收即死,不保留无效断言) |
|
||||
| `ui_contrast_probe.gd:48-55` 营地令牌段 | 核签后段留或随注销 | 新界面若不再消费 `CAMP_HEADER_BAND`/`CAMP_ROW_PLATE` 则段标签虚挂;仍消费则保留 |
|
||||
| `ui_click_probe.gd:500-528` 断点确认段(经 lvbtn 驱动) | 改走大门路径断言 | 卡②撤钮+本批弹窗移位双杀,改挂大门命中区(与 V3 合并或互指) |
|
||||
| `ui_probe.gd:39-52` 深员(`_balance_label`/`_tree_buy_btns`/`_workshop_rows`) | 改指新界面/场景根成员 | 成员级耦合随四柜台拆解迁移,寻址名随 T2 稳定化 |
|
||||
| `screen_flow_probe.gd:53`/:109-125 营地键/回退段直呼 `main.camp_overlay` | 改指新场景根句柄/closed 信号 | 句柄迁移到新场景根(F2/F8) |
|
||||
| `shot_probe.gd:126-133` camp 收闭段经「关闭营地」钮 | 改篝火动线或调试直改 visible | 营地根态无关闭钮(出口=篝火/ESC) |
|
||||
| `ui_struct_probe.gd:54-69`/`shot_probe.gd:103-124` 生涯段经 `_start_overlay`「生涯」钮 | 合成点击笔记本命中区 | 入口改挂帐篷旁笔记本,驱动改接 |
|
||||
| `forge_workbench_test.gd:33` 直载 `camp_overlay_view.gd` | 随锻造视图抽出同迁,断言零改只换承载类 | 承载类迁移,行板/写口逻辑复用(契约 4) |
|
||||
|
||||
**禁止削弱声明**:除上列外,实现期不得删除断言、放宽阈值、缩小扫描面、把真实入口换成下层直调。五界面写口链(V4)、生涯只读契约(V5)、图鉴挂起态(V6)、美术约束(V10)的既有断言全链复跑绿,禁削弱;棋盘三张+menu_boot 既有 golden 逐像素复跑、不放宽容差;不新建 camp golden(契约 10,若新建须另裁 L3)。
|
||||
|
||||
**独立验收审计**:合并前由未参与实现的会话/子代理执行,入口为审计只读本卡、实际对照表、diff、测试文件与实现报告,自跑最窄测试抽查、不采信报告「已全绿」;至少四件事——①逐行核对照表(测试存在、真的执行、尾缀能 grep 到、真实入口没有绕过改动点)②抽查判据绑定面(绑被测改动特有可观测提交面、当轮真实跑批执行过)③检查测试削弱(删除断言/放宽阈值/缩小扫描面/换下层直调逐处要本卡申报或用户批准)④核内部字段直查的受控例外(该行为无公开可观测面可钉时已在对照表注明理由)。报告落 **`reports/iter<N>-验收审计-<日期>.md`**,逐行「通过/缺漏/例外及依据」,未通过不得合并。测试执行两入口铁规不变:审计在迭代 loop 内启动的子代理算 loop,另开会话须用户点名。
|
||||
|
||||
**闸口径**:轻闸每卡出口自跑;批末重闸按改动域选档(本批碰 `game/` 代码/断言/终稿素材 → `--code`)全绿才合并;MC 零跑(零数值零行为——纯呈现+承载迁移)。卡内不写死闸件名单,域划分唯一出处在 `tools/run_all_gates.sh`。回归措辞按模板:里程碑步(波/T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试/工具先行孤立验证再并入全套。
|
||||
|
||||
## 8. 异常分级
|
||||
|
||||
- **L1(自救)**:断言写法、探针路径、命中区微调、命名。
|
||||
- **L2(记录继续)**:场景屏承载形态选择(§9 域内)、点选反馈参数(Q3 设计稿域内)、四界面承载形态(§9 域内)、方向稿张数在 2–3 内自选、图鉴占位文案称谓订正。
|
||||
- **L3(停机呈报)**:Q1–Q6 未裁即需开工对应任务段;规格清单(样张批)晚于本批且 Q6 未裁;golden 漂移越出预期面(若涉及既有棋盘/menu 基线);发现五界面任一功能/写口链路被意外触碰(契约 4 破);参照物到手后与纵深稿结构性冲突(呈报,禁批内自行改构图);美术渠道 A/B 执行中撞墙(如 CC0 改色达不到七物件可辨性);提议新建 camp golden(契约 10——须另裁)。
|
||||
- **L1(自救一次)**:断言写法、探针路径、命中区微调、命名、编译错误、签名拼写、测试套件 manifest 登记遗漏。
|
||||
- **L2(记录继续;同一红连续三次升 L3)**:场景屏承载形态选择(§9 域内)、点选反馈参数(§0.3 P3 设计稿域内)、四界面承载形态(§9 域内)、图鉴占位文案称谓订正、行数较 T0 预期漂移但 S13 键不升。
|
||||
- **L3(立即停卡写报告等用户)**:
|
||||
- §0.3 代码段开工门裁断实况反转(四项 2026-11-01 已裁断销号;开工时发现未销号实况=停机呈报);
|
||||
- 规格清单(样张批)终档置换未按反哺点登记;
|
||||
- golden 漂移越出预期面(若涉及既有棋盘/menu 基线);
|
||||
- 发现五界面任一功能/写口链路被意外触碰(契约 4 破);
|
||||
- 参照物与纵深稿结构性冲突再现(P4 已补、冲突已呈报,禁批内自行改构图);
|
||||
- 美术渠道 B 执行中撞墙(插画级新产达不到七物件可辨性);
|
||||
- 提议新建 camp golden(契约 10——须另裁);
|
||||
- 任何验收行无法从真实入口绑定特有可观测提交面(证明做不出=停卡呈报);
|
||||
- **机检预算互斥=上游缺陷停卡退回写卡段**:实现规范预算超默认未走指标例外申报、或 S13 键较登记值上升、或机检键/计数与卡片契约互斥——一律停该卡呈报退回写卡段,禁为凑绿保留无效成员、造第三条路或内联求裁(契约 12/第 13 节合流);
|
||||
- **拆分边界**:按契约 11 拆不出内聚单元(只能凑计数袋/沿阈值轴硬拆)=停卡呈报走豁免/还债通道,禁硬拆凑绿。
|
||||
|
||||
## 9. 代拍板白名单(超清单必呈报)
|
||||
|
||||
> 篝火二次确认已由 camp.md v2.2 裁定为**必须**(走 ConfirmDialog 先例),不属代拍板域。
|
||||
|
||||
1. 场景屏承载形态(camp_screen 屏壳改造 vs 新屏壳)——约束:`LAYER_CONTRACT` 更新+探针挂载面迁移留痕。
|
||||
2. 五界面拆出后的承载形态(独立全屏页 vs 单一内页切换)+**叠层规则派生**(v1.1:独立全屏页=场景根隐藏/单一内页切换=场景根留底;写入 V2 断言;「缩放虚化」禁自选)。
|
||||
3. 七物件命中区实现(TextureRect 分区 vs 其他)与点选反馈参数(Q3 裁定域内)。
|
||||
4. 篝火是否需二次确认——默认直回(营地每笔消费即时写盘,无未保存风险——存档序列化.md:121);如判需确认,走 ConfirmDialog 先例。
|
||||
5. 截屏级 48 色计数工具是否新建及落点(现役=素材级二器,F17;截屏级依赖样张批规格清单,随 Q6 一并裁)。
|
||||
6. CampOverlay 类退役范围(整类删 vs 留片段)——约束:吸收即死,禁留死代码。
|
||||
7. 提交切分与 worktree 分支命名。
|
||||
2. 五界面拆出后的承载形态(独立全屏页 vs 单一内页切换)+**叠层规则派生**(独立全屏页=场景根隐藏/单一内页切换=场景根留底;写入 V2 断言;「缩放虚化」禁自选)。
|
||||
3. 七物件命中区实现(TextureRect 分区 vs 其他)与点选反馈参数(§0.3 P3 设计稿域内)。
|
||||
4. 截屏级 48 色计数工具是否新建及落点(现役=素材级二器 F17;**条件步**——§0.3-3⑤环境子板色值已按 T1 量化登记则拍板,未登记则本子步显式跳过+T6 登记遗留)。
|
||||
5. CampOverlay 类退役范围(整类删 vs 留片段)——约束:吸收即死,禁留死代码。
|
||||
6. 提交切分与 worktree 分支命名。
|
||||
|
||||
## 10. 裁点与设计议程(v2.1:本卡在批内,以下为前置解决议程)
|
||||
超出必须呈报:任何数值、像素规格、事件名、命中区绑定目标、文件职责、T 卡验收落点、五界面写口链路、拆分单元职责。
|
||||
|
||||
> Q4/Q5/Q6/Q8 已裁(裁定见卡头);Q1/Q2 仍待用户。本节约等于批内设计段的工作清单。
|
||||
## 10. 待裁点:零待裁点,开工门=U0
|
||||
|
||||
### Q1 · 营地场景图的美术渠道(**仍待用户裁——批内第一议程,阻塞 P2 规格分支与方向稿**)
|
||||
**本卡设计待裁点清零,开工门=U0。** Q1/Q2/Q4/Q5/Q6/Q8 均已裁(下列为现行裁定留痕,非待裁点,实现期禁自行改值):
|
||||
|
||||
**背景**:澄清⑧2——「美术渠道 A/B 未裁:CC0 改色 vs 插画级新产——原贴图批的渠道问题对营地场景图同样成立,本讨论未裁决」。
|
||||
- **Q1 美术渠道=B·插画级新产**(2026-10-22 用户裁):✦ 渠道作者自跑远程生图管线;规格沿用 art-bible §6.2/§8.1/§8.2 既有裁决(art-assets-checklist.md §3.5)。
|
||||
- **Q2 参照物=已补**(2026-10-23):`artwork/2026-10-23-营地场景/Gemini_Generated_Image_ykrc0nykrc0nykrc.jpg`,已进 camp-scene-prompts.md §1 登记为「作者提供的参照物」,与纵深稿对过表、围墙结构冲突已呈报;参照物只是参考图,保留 `artwork/`、不入 git、不入游戏目录。
|
||||
- **Q4 营地底栏「最近冒险」条带去留=甲**(2026-10-18):随四柜台拆解一并撤下,逐局历史回看整体归生涯(期二承接);生涯.md P6 同批注销(反哺点)。
|
||||
- **Q5 大门「有断点」分支三出口弹窗=甲**(2026-10-18):ConfirmDialog 扩第三钮(继续上一段冒险/开始新冒险/取消,cancelled 恒=无变更退回营地);卡③ 契约 3 已按三钮化落定(删档确认只用取消/确认)。
|
||||
- **Q6 Q1 与规格清单缺口连带裁=甲**(2026-10-18):过渡尺寸档=现役 1280 工程档(1280×800)+烛光黄 #F6C667/木色 #8A5A34;渠道 B 已裁(2026-10-22),规格落 art-bible v3.31 §6.2/art-assets-checklist.md §3.5(2× 源档出图、最近邻降采样到 1280×800);终档归样张批冻结清单后置换(反哺点登记),执行归用户线。
|
||||
- **Q8 设计稿产出方式=甲**(2026-10-18):批内出稿呈裁(方向稿先行纪律照旧——方向稿选划已由 2026-10-31 样张过审裁定完成,各素材第一张样本稿为终稿、保留全部待选稿)。
|
||||
|
||||
**我的推荐:A · CC0 改色**(理由:06:23 已有配色规格〔烛光黄 #F6C667 配木色 #8A5A34〕与渠道合法性记载、零新绘成本、方向稿不受「从零构图」拖累;B 依赖尚未冻结的规格清单且周期长)。用户此前令不代裁——推荐已摊开,等你一句 A 或 B,方向稿(T1 防不满意工序)当天可出。
|
||||
|
||||
| 案 | 内容 | 代价 |
|
||||
|---|---|---|
|
||||
| A · CC0 改色 | 通用场景素材改色复用(06:23 载明该渠道对营地件合法:烛光黄 #F6C667 配木色 #8A5A34 已有规格) | 快、零新绘成本;上限=改色件构图不完全贴合七物件+纵深稿,可能要容忍「近似构图」 |
|
||||
| B · 插画级新产 | 按纵深稿全新绘制(像素级) | 七物件与构图完全受控;成本高、周期长,且依赖规格清单输入(F16)——须走「等样张批规格清单」或用户另裁过渡规格 |
|
||||
|
||||
连带:渠道裁定影响 T1 估时(A 趋下限、B 趋上限)与切分点位置;「归建卡时或样张批规格语境下裁」(澄清⑧2 原文)。
|
||||
|
||||
### Q2 · 参照物(**待补输入**)
|
||||
|
||||
澄清②/§⑧1:用户原话「目前还没有一个参照,我可以后续找一下」——参照物找到后补充进本卡(与纵深稿对表,结构性冲突=呈报,禁批内自行改构图)。
|
||||
|
||||
### Q3 · 物件点选反馈细节(设计稿产出方式已裁=批内出稿呈裁)
|
||||
|
||||
澄清⑧3:「悬停高亮/提示文案/可点区域判定」未谈。三项形态归设计稿阶段——**产出方式已裁(Q8=批内出稿呈裁,方向稿先行纪律照旧)**;设计稿只覆盖根态点选反馈,不覆盖进界面后的叠层规则(叠层=随承载形态裁定派生:独立全屏页=场景根隐藏/单一内页切换=场景根留底;「缩放虚化」是第三形态,涉新演出面+素材,禁批内自选)。
|
||||
|
||||
### Q4 · 营地底栏「最近冒险」条带去留(**已裁=甲**)
|
||||
|
||||
**裁定(2026-10-18)**:甲——随四柜台拆解一并撤下,逐局历史回看整体归生涯(期二承接);生涯.md P6 同批注销(反哺点)。代拍板留痕(用户令「事项按推荐的来」,本项无推荐案,取默认甲=分工矩阵干净、逐局历史只剩一个权威呈现面;追认单可 veto)。
|
||||
|
||||
### Q5 · 大门「有断点」分支的三出口弹窗形态(**已裁=甲**)
|
||||
|
||||
**裁定(2026-10-18)**:甲——ConfirmDialog 扩第三钮(继续上一段冒险/开始新冒险/取消,cancelled 恒=无变更退回营地)。推荐案,用户令按推荐执行。连带:卡③ 契约 3 已按三钮化落定(删档确认只用取消/确认);类签名变更随本卡重新立卡时的实现落地,卡③ T0 对齐。
|
||||
|
||||
### Q6 · Q1 与规格清单缺口的连带裁(**已裁=甲**)
|
||||
|
||||
**裁定(2026-10-18)**:甲——Q1 裁 A 同时订过渡口径:「过渡尺寸档=现役 1280 工程档+烛光黄 #F6C667/木色 #8A5A34 既有规格;终档归样张批冻结后置换(反哺点登记)」。推荐案,用户令按推荐执行。若 Q1 裁 B(插画级新产),过渡口径不成立——B 依赖规格清单,须走乙案「T1 等样张批规格清单产出才开」或用户另行裁定过渡规格。
|
||||
|
||||
---
|
||||
|
||||
**审查回写要点**:v1.0→v1.1(2026-10-18 grilling 子 Agent 对抗审查回写)——事实订正 6 处:E1「48 色工具全仓不在役」→截屏级不在役/素材级二器在役(F17/§9-5/V10/T5 连带);E2「camp golden」五处不存在→删并立契约 10 不建;E3 F7 行号(_start_adventure :579-597 等);E4 F14 .gitignore:51+「恒无」表述订正;E5 存档序列化 :122→:121(卡⑤同订);E6 行号微漂(ui_struct_probe :41-49、smoke_all :170-171、camp.md :19-20)。自扩订正:契约 10 标仓库纪律成文。卡内可收 15 项:presenter 承接面(T3/契约 4)、叠层规则派生(T2/§9-2)、ConfirmDialog 消费方编排(T4)、生涯探针驱动改缆+返回钮文案坑(T3/T5)、图鉴占位态(T3)、screen_flow 键新语义(T5)、HUD 刷新单口(T2/T3)、深员改指表(T5)、源码断言段重写(T5)、shot_probe 收闭改缆(T5)、forge_workbench_test 迁移+§5 补 tests 可写面(T5/§5)、断点确认段补列(F8/T5)、contrast 段核签(T5)、素材命名指针(T1)、终稿落盘口径(T1/契约 9/§5)。跨卡对齐:HUD 刷新挂点(§0 接口+卡⑤订正)、ConfirmDialog 类事实双向失效(Q5)、开层互斥/关层收闭(T3+卡③ T2)、探针文件分界(T5)、`_refresh_resume_button` 不复用(T4)。验收补:V1 拆半、V3 扩、V4 扩、V12 留痕行、变异补二条。新增待裁点 Q5 三出口弹窗、Q6 规格缺口连带;估时 8.5–11.5d→9–12d。用户面裁决(①④⑤裁决 5/10)零改动。
|
||||
**代码段 `/iter` 开工门已全部裁断销号(2026-11-01 用户裁,照 grilling+godot-master 双审推荐采纳)**:P3 销号口径=camp.md v2.2 四态规格即设计稿;P5 销号口径=形态落文完成、实装回填归反哺点;camp-scene-prompts §5 五裁点=①帐篷 300×170 追认②门扇 240×220 追认③布告板 (845,268,130,140)④描边奶油色追认⑤环境子板色值不前置(T1 量化后按 art-bible §4.1 登记);十张终稿后处理=/iter 开工令即含授权。**本卡零待裁点、开工门清零——迭代 47 可开工。**
|
||||
@@ -0,0 +1,144 @@
|
||||
# 需求卡片:营地模态句柄子容器批(UiCampModals 分域句柄容器 · camp_overlay 句柄迁移)· 营地交互重做卡⑥(前置基建)
|
||||
|
||||
- 版本:**v1.1(现行有效卡)**。留痕:2026-11-01 用户裁(迭代 47 机检预算互斥停机呈报裁决=最小改动先走:营地域六句柄落子容器,全量分域分家登记待办清单另立批);2026-11-01 grilling+godot-master 双审后写卡段修订(v1.1,执行级四缺口+措辞订正,设计面零改动)——T0 命令路径订正 game/tests/static_scan.sh、T1 补类名缓存刷新步+ui_modals 头注同步+断言尾缀落点+复跑面扩改指面 8 文件、V3 判据改计数留痕+观测面局限申报、迁移面实测 8 文件入 F4、契约 2/4 计数与退役删除句、node() 改写分支措辞。
|
||||
- 来源:2026-11-01 用户裁决(**唯一事实源**:本卡 §2 现状实测+`design/engineering/code-conventions.md` §1.1 拆分判据;需求性工程条目证据指认=迭代 47 机检预算互斥停机呈报〔ui_modals.gd 类变量 14,卡④⑤ 平铺合计 19>S13 上限 15〕+用户裁决留痕,属重构基建、无设计线前置)
|
||||
- 归属:呈现层/组合根(`game/presentation/`)——营地交互重做卡⑥,**迭代 47 执行序第一位**(卡④ T3 落五句柄、卡⑤ T1 落浮窗句柄的本批前提)
|
||||
- 开工门:U0(随迭代 47 `/iter` 发令,无独立开工令)+零待裁点
|
||||
|
||||
## 1. 目标与完成定义
|
||||
|
||||
**目标**:给营地域模态句柄立独立子容器,使迭代 47 营地域六句柄(场景根+四子界面+Esc 浮窗)不再平铺进 `ui_modals.gd`——该文件类变量终值 14(不超 S13 上限 15),零基线登记;调度器/层序合同/登记口三件全局职责零改动。
|
||||
|
||||
**完成定义**:
|
||||
1. `ui_camp_modals.gd`(类名 UiCampModals,RefCounted)新件在役;`ui_modals.gd` 持 `camp` 成员一枚,`camp_overlay` 平铺成员删除——类变量 14→14;
|
||||
2. `camp_overlay` 句柄寻址迁移 `ui.modals.camp.overlay`,全仓引用(组合根+探针)改指完毕,现役营地探针段复跑绿(行为零变化的证明);
|
||||
3. `ui_registry.gd node()` 的 `camp_overlay` 分支返回属性链改经子容器(`modals.camp.overlay`;**LAYER_CONTRACT key 平铺不改名**,camp.* 新增解析分支随卡④⑤);
|
||||
4. `main_ui_build.gd` 装配赋值改经子容器;S13 读数 `ui_modals.gd`=14 不升;
|
||||
5. 批末按改动域选档全绿;三份 `reports/` 产出物写齐(T2)。
|
||||
|
||||
## 2. 现状事实(2026-11-01 实测;开工日 T0 复核)
|
||||
|
||||
| # | 事实 | 出处 |
|
||||
|---|---|---|
|
||||
| F1 | `ui_modals.gd` 类变量 14 枚=flow+13 模态句柄;gdstyle 直跑零命中(14≤15) | `game/presentation/ui_modals.gd:7-20` |
|
||||
| F2 | S13 类变量上限=15(gdstyle v0.4.0 默认 `quality/max-class-variables`,超即 NEW 键红);15 枚文件直跑零命中、20 枚合成文件实测 warn | `tools/gdstyle_gate.py`;停机呈报实测凭据 |
|
||||
| F3 | 卡④⑤ 原平铺写法合计 19>15(卡④ 净+4=场景根+四子界面−`camp_overlay` 退役;卡⑤ +1 浮窗)——迭代 47 机检预算互斥成因;2026-11-01 用户裁=子容器方案,禁基线特批 | 停机呈报-迭代47机检预算互斥-2026-11-01.md(iter47 worktree 在档,裁决已吸收本卡与卡④⑤) |
|
||||
| F4 | `camp_overlay` 句柄现役消费面实测 **8 文件 40 余处**(2026-11-01 双审实查;T0 逐处列清单):`main_ui_build.gd`(约 10 处)/`ui_registry.gd:61`/`screen_flow_probe.gd`(3)/`ui_click_probe.gd`(16–20)/`ui_probe.gd`(8–9)/`shot_probe.gd`(2)/`ui_struct_probe.gd`(1)/`system_test.gd`(2——:108 句柄同一性链、:121 候选层清单,含 `game/tests/` 域) | `main.ui.modals.camp_overlay` 全仓引用位 |
|
||||
| F5 | `ui_registry.gd node()` 现经 `modals.X` 一层寻址;LAYER_CONTRACT 与 `apply_layer_contract` 与本批正交(句柄册结构≠场景树结构——子容器不挂树、零树序影响) | `game/presentation/ui_registry.gd`(node() 寻址段,T0 复核) |
|
||||
|
||||
## 3. 设计契约(红线,违反=L3 停机呈报)
|
||||
|
||||
🔴 **契约 1 · 行为零变化**:纯句柄搬家+容器新立;LAYER_CONTRACT/登记序/树序/`register_layer`/ModalFlow 零改动;现有探针断言**零改判据**(只改寻址)。
|
||||
|
||||
🔴 **契约 2 · 寻址唯一形态**:营地域全部句柄(过渡期含本卡迁入的 `camp.overlay`;**终态六枚=场景根+四子界面+Esc 浮窗**)寻址一律 `ui.modals.camp.X` 二层;禁平铺回 `ui_modals.gd`(卡④ T3 落五句柄、卡⑤ T1 落 esc 时同规——卡⑤ 契约 7 已载、卡④ T3 步与文件表已载)。
|
||||
|
||||
🔴 **契约 3 · UiModals 只减不增**:本卡后类变量 14(flow+12 平铺句柄+camp 容器成员),卡④⑤ 阶段终值保持 14;任何新句柄平铺回顶层=S13 NEW 红=L3。S13 红线实际兜 **+2 起**(14→15 闸零命中)——+1 漂移由 V3 计数留痕与独立验收审计兜,契约分工在此写明。
|
||||
|
||||
🔴 **契约 4 · 禁无效成员**:子容器内不预占句柄——本卡只迁 `camp_overlay` 一枚实件;五枚新句柄随卡④ T3 创建视图时落、esc 随卡⑤ T1 落;禁空占位凑结构(code-conventions §1.1 第⑤条同款)。**`camp.overlay` 枚随卡④ T3 CampOverlay 类退役一并删除**(禁悬挂——类删后类型悬挂即 parse error,删除义务显式归卡④ T3)。
|
||||
|
||||
🔴 **契约 5 · 拆分边界纪律**(判据权威=code-conventions §1.1,本卡写条款不复制定文):本卡新建分域容器沿**职责轴**——UiCampModals=可命名领域概念「营地交互域模态组」(营地场景图+其子界面+其浮窗)、单一变化原因=营地交互重做;非凑计数袋;实现报告逐件一行承载职责语句。
|
||||
|
||||
## 4. 范围边界
|
||||
|
||||
**做**:UiCampModals 新件+`ui_modals.gd` 持 camp 成员+`camp_overlay` 句柄迁移+`node()` camp 二层寻址+装配与全仓引用改指。
|
||||
|
||||
**不做**(明示去向):
|
||||
- 其余 12 枚存量句柄分域分家、flow 自 UiModals 升格独立持有 → 待办清单「模态句柄册分域重构」条(2026-11-01 登记,另立批);
|
||||
- 卡④ 的五枚新句柄实装 → 卡④ T3;esc 句柄 → 卡⑤ T1;
|
||||
- LAYER_CONTRACT/模态栈语义任何改动 → 无(契约 1)。
|
||||
|
||||
## 5. 关联文档同步面
|
||||
|
||||
| 文档 | 关联点 | 同步义务 |
|
||||
|---|---|---|
|
||||
| `design/engineering/architecture/architecture.md` | 呈现层模块清单(UiCampModals 新件归属) | 反哺点 · 列清单(实现批禁写 `design/`) |
|
||||
| `待办清单.md`(仓库根) | 营地交互重做条实况补卡⑥路径;本卡来源裁决 | 已同步(2026-11-01 写卡段登记维护)——实现批禁写 |
|
||||
| `roadmap.md`(仓库根) | 迭代 47 行需求卡片列(卡⑥ 排第一)+预计周期 | 已换代(2026-11-01 编排入表,写卡/编排段动作)——实现批禁写 |
|
||||
| `game/tests/README.md` | 能力行:**零新增能力**(V1–V3 全落既有「模态覆盖层编排与输入锁」) | 已核:零增行;实现批禁写 |
|
||||
| `game/presentation/*`、`game/probe/*`、`game/tests/**` | 实施/断言本体 | 实施本体(可写) |
|
||||
|
||||
## 卡前·文件结构与职责(T0 前)
|
||||
|
||||
| 文件 | 职责 | 改动类型 | 落位 | 对照表行 |
|
||||
|---|---|---|---|---|
|
||||
| `game/presentation/ui_camp_modals.gd` | 营地域模态句柄子容器(RefCounted;本卡 1 枚 `overlay`,卡④⑤ 落满 6 枚;头注自陈禁平铺回 ui_modals) | 行为改动 | 新建 | V1 |
|
||||
| `game/presentation/ui_modals.gd` | 持 `camp` 成员(_init 构造);删除平铺 `camp_overlay` 成员 | 行为改动 | 复用既有(改) | V1 |
|
||||
| `game/presentation/main_ui_build.gd` | 装配赋值改经子容器(`modals.camp.overlay = …`) | 行为改动 | 复用既有(改) | V1 |
|
||||
| `game/presentation/ui_registry.gd` | `node()` 的 `camp_overlay` 分支返回属性链改经子容器(key 平铺不改名);camp.* 新增解析分支随卡④⑤ | 行为改动 | 复用既有(改) | V2 |
|
||||
| 全仓 `camp_overlay` 句柄引用位(组合根+探针,T0 grep 列清单) | 寻址改指 `ui.modals.camp.overlay`(断言零改) | 非行为改动(寻址改指) | 复用既有(改) | V1 |
|
||||
|
||||
## 落位与可复用性预检
|
||||
|
||||
| 新件 | 复用面(grep 同职责实现) | 唯一面(grep 同名同义标识符) | 分层与交互面 |
|
||||
|---|---|---|---|
|
||||
| `ui_camp_modals.gd` | grep 句柄分域容器/分组容器无先例;`UiModals` 本体=按技术角色平铺的注册面容器(职责不同);`ModalFlow`=调度器非句柄册 → 不能复用,须新建 | grep `UiCampModals`/`ui_camp_modals`/`camp_modals` 无第二处;营地句柄寻址唯一落点 | RefCounted 不挂树;`ui_modals._init` 构造 camp(与 flow 同拍,先例 ui_modals.gd:24)、`main_ui_build` 只向 camp 赋句柄;`register_layer`/LAYER_CONTRACT/树序零触碰 |
|
||||
|
||||
**非新增件说明**:`ui_modals.gd`/`main_ui_build.gd`/`ui_registry.gd`/探针=存量改造;**数据件/RNG/Core 零触碰**(纯呈现层簿记);Core 零 UI 依赖不因新件绕过。
|
||||
|
||||
## 实现规范预算
|
||||
|
||||
gdstyle v0.4.0 默认阈值:公开方法 ≤20、类变量 ≤15、单函数分支 ≤8、返回 ≤6。
|
||||
|
||||
| 触面 | ①公开方法数 | ②成员变量数 | ③迁移函数对账 | 结论 |
|
||||
|---|---|---|---|---|
|
||||
| `ui_camp_modals.gd` | 预期 ≤1(`_init`) | 预期 1(本卡)→6(卡④⑤ 落满) | 无迁入函数 | 三查通过 |
|
||||
| `ui_modals.gd`(存量) | 不适用 | 14→14(−平铺 `camp_overlay`+`camp` 容器成员) | 无 | S13 只降不升 |
|
||||
| `ui_registry.gd`(存量) | 不适用 | 不适用 | 无 | node() +1 解析分支,分支数 ≤8 |
|
||||
| `main_ui_build.gd`(存量) | 不适用 | 不适用 | 无 | 装配行改指 |
|
||||
|
||||
## 6. 任务卡
|
||||
|
||||
### T0 事实坐实(≈0.25d)
|
||||
|
||||
- 取用:§2 F1–F5、营地交互重做条(已编迭代 47)、卡⑤ v1.5 契约 7+卡④ v3.2 T3 步与文件表(寻址规则落点)。
|
||||
- [ ] 复核 §2 全部 `file:line`;grep 全仓 `modals.camp_overlay` 引用位列清单(改指面:组合根+探针逐处)。
|
||||
- [ ] 实读 `ui_registry.gd node()` 寻址形态,定 `camp.*` 二层解析的顺延写法(循 `modals.X` 先例,禁另造第三种寻址)。
|
||||
- [ ] 跑 `bash game/tests/static_scan.sh`(tools/ 下无此件——v1.0 路径失实订正)记录 S13 读数(**禁手改 `tools/gdstyle_baseline.txt`**——基线是欠账簿,重生成人工专用;`ui_modals.gd` 类变量 14)。
|
||||
- 产出:引用位清单、寻址形态结论、S13 读数留痕。
|
||||
|
||||
### T1 实装与验证(≈0.25d)
|
||||
|
||||
- [ ] 新建 `ui_camp_modals.gd`(RefCounted;`var overlay: CampOverlay`;头注自陈「营地交互域句柄子容器,终态六枚,新营地句柄禁平铺回 ui_modals」)。
|
||||
- [ ] **类名缓存刷新**(code-conventions 语言纪律 5——新 class_name 必步):新件落盘后、任何 headless 验证前先跑一次编辑器扫描(`--editor --quit`;新 worktree 无 `.godot` 缓存,缺此步 `--script` 模式 parse 假红)。
|
||||
- [ ] `ui_modals.gd`:持 `camp: UiCampModals`(`_init` 构造,与 flow 同拍——ui_modals.gd:24 先例);删除平铺 `camp_overlay` 成员;**头注同步**(「十三个模态覆盖层句柄」→「十二个平铺句柄+营地域子容器」——§1.4.1 头注如实义务)。
|
||||
- [ ] `main_ui_build.gd` 装配改指;全仓引用位按 T0 清单(8 文件)改指 `ui.modals.camp.overlay`(逐处留痕)。
|
||||
- [ ] `ui_registry.gd` `node()` 的 `camp_overlay` 分支返回属性链改经子容器(**key 平铺不改名**);camp.* 新增解析分支随卡④⑤。
|
||||
- [ ] 现役营地断言消息文本追加〔句柄子容器批 V1/V2〕尾缀(**判据零改、仅消息文本**——独立验收审计「尾缀能 grep 到」义务的落点步)。
|
||||
- [ ] 验证:改指面 8 文件逐件复跑绿(探针五件营地段+`system_test.gd`——screen_flow_probe/ui_click_probe/ui_probe/shot_probe/ui_struct_probe;断言零改只换寻址);`system_test.gd` V1c 合同树序链(:94-106)+句柄同一性链(:108)复跑绿;S13 读数=gate 绿(≤15 零 NEW)+`grep -c '^var '` 计数=14 留痕。
|
||||
- 产出:子容器在位+迁移绿证+引用位改指留痕表;卡④ T3/卡⑤ T1 按契约 2 落新句柄。
|
||||
|
||||
### T2 产出物落位卡(≈0.25d,末卡)
|
||||
|
||||
- [ ] 里程碑步出口跑一次改动域全套闸:`bash tools/run_all_gates.sh --code`;回执 `all_green=true`;波内修复只做出红最小单元最窄确认。
|
||||
- [ ] 独立验收审计(未参与实现的会话/子代理),产出 `reports/iter<N>-验收审计-<日期>.md`;未过禁合并。
|
||||
- [ ] 合并前写齐三份 `reports/`:实现报告/反哺点清单(§5 每条有落点)/验收审计。
|
||||
- 产出:三份 `reports/` 齐全+闸全绿+审计通过;合回后本地 CI 全量复验。
|
||||
|
||||
**估时合计 ≈0.75d**(T0 0.25+T1 0.25+T2 0.25)。**切分预案**:T2 偏紧(闸+审计+三报告挤 0.25d)——三份 `reports/` 先行成稿、独立验收审计走并行子代理,不串行等。
|
||||
|
||||
## 7. 验证闸:改动—验收对照表
|
||||
|
||||
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| V1 句柄迁移零行为漂移 | `ui_camp_modals.gd` 新件;`ui_modals.gd` 持 camp/删平铺成员;`main_ui_build.gd` 装配改指;全仓引用改指 | 改指面探针五件营地段+`system_test.gd`(V1c :94-106+句柄同一性链 :108)〔句柄子容器批 V1〕 | 探针(+系统测试复跑) | 现役营地断言逐件复跑(断言零改、寻址新——改指面 8 文件全覆盖) | 全段绿=行为零变化证明;改指后全仓 grep 零 `modals.camp_overlay` 平铺寻址残留(静态判据);句柄同一性链绿=同一实例零漂移 | 既有:模态覆盖层编排与输入锁 |
|
||||
| V2 层序合同零漂移 | `ui_registry.gd` node() 分支返回属性链改写 | `system_test.gd:_ready`(V1c 合同树序链 :94-106 复跑)〔句柄子容器批 V2〕 | 系统测试 | LAYER_CONTRACT 单一事实源 | 树序链绿=合同与落位零漂移(子容器不挂树、零树序影响;key 平铺不改名) | 既有:模态覆盖层编排与输入锁 |
|
||||
| V3 S13 读数 | `ui_modals.gd` 类变量 14 | gdstyle S13 gate+`grep -c '^var '` 计数(T1 验证步留痕)〔句柄子容器批 V3〕 | 静态读数 | `bash game/tests/static_scan.sh` | gate 绿(≤15 零 NEW)+计数=14 留痕——**观测面局限申报**:S13 闸对 14/15 同样零命中,「=14」由人工计数承载(test-conventions §8.4 静态判据出口) | 既有:模态覆盖层编排与输入锁 |
|
||||
|
||||
**测试方式两分法**:V1/V2 机检自动化;V3 静态读数留痕(gdstyle 基线机制域内)。**测试削弱申报:零削弱**(断言零改判据,只换寻址)。**独立验收审计**:合并前由未参与实现的会话/子代理执行(四件事口径同 test-conventions §8.7),报告落 `reports/iter<N>-验收审计-<日期>.md`,未过禁合并。**闸口径**:轻闸每卡出口自跑;批末 `--code` 关联档全绿才合并;MC 零跑(零数值零行为)。回归措辞按模板:里程碑步出口一次全套闸,波内修复只跑红件。
|
||||
|
||||
## 8. 异常分级
|
||||
|
||||
- **L1(自救一次)**:改指拼写、探针寻址写法、node() 分支写法、类名缓存失配 parse 失败(重跑 `--editor --quit` 即清)、manifest 登记遗漏。
|
||||
- **L2(记录继续;同一红连续三次升 L3)**:行数较 T0 预期漂移但 S13 键不升。
|
||||
- **L3(立即停卡写报告等用户)**:迁移后任一现役营地断言红且非寻址成因(=行为被意外触碰);机检预算互斥(`ui_modals.gd` 类变量被迫>14、或子容器被塞入非营地句柄=拆分边界破)——停卡退回写卡段,禁造第三条路。
|
||||
|
||||
## 9. 代拍板白名单(超清单必呈报)
|
||||
|
||||
1. `node()` 解析形态=match 平铺(现役唯一形态,ui_registry.gd:50-69;字典形态弃用、禁另造第三种寻址)。
|
||||
2. 子容器头注措辞(契约 4 自陈内容域内)。
|
||||
|
||||
超出必须呈报:寻址形态、文件落位、契约数字、句柄归属。
|
||||
|
||||
## 10. 待裁点:零待裁点,开工门=U0(随迭代 47 发令)
|
||||
|
||||
**零待裁点。** 2026-11-01 用户裁留痕:最小改动=本卡+卡④ v3.2/卡⑤ v1.5 落子容器;全量分域句柄分家=待办清单「模态句柄册分域重构」条(另立批,不属迭代 47)。
|
||||
+3
-2
@@ -6,7 +6,7 @@
|
||||
|
||||
- **阶段**:M3——Alpha 版本的完整实现(2026-10-09 立规:未明令宣布完成前停留 M3,迭代只排 M3 需求,M4 不排期;根目录 stage.txt 为旧阶段开关仅存档)。
|
||||
- **迭代位**:迭代 1–45 全部已完成——迭代 45(呈现层状态件+gdstyle 尾波补件两卡)2026-10-31 合回(合并提交 f817ab2d,独立验收审计通过零缺漏,行为零变化),批后收尾闭合(2026-10-31):反哺点七条处置闭合(architecture 六条落文=breakpoint_store/board_hover/单格两件/站桩两件四行现状化+构造句改述与 7 项引用束/15 贴顶实况+gdstyle 截断缺陷节清偿结果;第 7 条工具观察迁待办新条)、目检三项登记体验验证清单 ㊸、产出物退役九件(两报告/反哺点/审计/两停机呈报+两卡+两设计文档)、worktree 两件清理(iter45+assert-slim-b2)。迭代 44 收尾记录见 git 提交 9eedf896。
|
||||
- **下一步**:迭代 46 待开工(编排提交 da24047c:换图系双基座七件批+站桩名字行提档与地台色合并批+棋盘格边长口径收口批三卡,≈9.125 个工作日)——开工由用户经 iter 发令。待编池:营地交互重做卡⑤(排卡④之后)、卡④(美术设计已闭合=样张过审 2026-10-31+art-bible v3.24 §6.2,待用户发令重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)。
|
||||
- **下一步**:迭代 46 进行中〔用户裁拆批 2026-10-31〕——卡A 换图系双基座七件批+卡B 站桩名字行提档与地台色合并批已收口合回(合并提交 34bb62a5,独立验收审计通过,CI 全量绿);卡C 棋盘格边长口径收口批 **v2.0 重立回编**(用户裁锚点换代:可读性锚点=用户验收的现行渲染值,基座档 14×14=28px 达标,battle.md 可读下限 30px 句与探针 36px 人造阈值全退役,探针判据换锚=实读与单点算式严格相等+结构钳制+13/14 推定留痕;v2.0 卡经 grilling 独立复核,写卡批合并提交 e7090bc9,CI 全量绿),待 `/iter` 发令回 worktree iter46 续工(WIP 算式单点与四档冒烟两件复用、探针件返工)。battle.md `:144` 可读下限句退役归文档批待发令。迭代 47(营地交互卡⑥句柄子容器前置+卡④⑤)已编排待开工。待编池:冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)。
|
||||
|
||||
## 里程碑时间线
|
||||
|
||||
@@ -79,7 +79,8 @@
|
||||
| 迭代 43 | 已完成(2026-10-30) | 已退役(git 历史可考) | 2026-10-29 | ≈6.5 个工作日 | 已退役(git 历史可考) |
|
||||
| 迭代 44 | 已完成(2026-10-30) | 已退役(git 历史可考) | 2026-10-29 | ≈7.875 个工作日 | 已退役(git 历史可考) |
|
||||
| 迭代 45 | 已完成(2026-10-31) | 已退役(git 历史可考) | 2026-10-29 | ≈7 个工作日 | 已退役(git 历史可考) |
|
||||
| 迭代 46 | 待开工 | reports/需求卡片-换图系双基座七件批-2026-10-31.md<br>reports/需求卡片-站桩名字行提档与地台色合并批-2026-10-31.md<br>reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md | 2026-10-31 | ≈9.125 个工作日 | — |
|
||||
| 迭代 46 | 进行中 | reports/需求卡片-换图系双基座七件批-2026-10-31.md<br>reports/需求卡片-站桩名字行提档与地台色合并批-2026-10-31.md<br>reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md | 2026-11-01 | ≈8.625 个工作日 | — |
|
||||
| 迭代 47 | 待开工 | reports/需求卡片-营地模态句柄子容器批-2026-11-01.md<br>reports/需求卡片-营地场景图新建批-2026-10-18.md<br>reports/需求卡片-ESC浮窗与营地顶栏批-2026-10-18.md | 2026-11-01 | ≈15 个工作日〔用户特批 2026-11-01 超 10 个工作日〕 | — |
|
||||
|
||||
- 迭代 38 收口为带红合并〔用户特批 2026-10-26〕:09 静态扫描 S13 gdstyle 恶化 2 条经批准记入基线存量红(git 提交 c4c69701),卡② 停卡退上游,处方已于 2026-10-26 修订定稿 v1.3(git 提交 b3ea7532),随「gdstyle 存量债全量清偿」条目波 7 待编排。
|
||||
- 迭代 39 收口为带红合并〔用户特批 2026-10-27〕:02 EV 锚 goblin 0.9148∉[1.00,1.20](触发器批有意行为改动,fp f74b9a48ef4a)已随 EV 锚重锚批换带归绿(git 提交 ba5105aa);08d 生涯.md:55 行号漂移已随 2026-10-28 批后收尾反哺落文修复归绿。三卡拆分后终局 gdstyle 恶化 2 条(battle_orchestrator max-file-length、level_map_screen max-class-variables)归迭代 40 卡①还债与迭代 41 存量债序列。
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# 直改车道闸(git pre-commit,2026-10-30 本地 CI 化换代)——提交点现场跑文档域闸
|
||||
# (tools/run_all_gates.sh --docs,秒级文本扫描):绿=落地,红=中止。
|
||||
# 代码面提交不再拦(2026-10-30 用户裁:主区直改全面放开)——代码验证归合回后的本地 CI
|
||||
# (tools/hooks/post-merge 全量跑批;CI 红态下 tools/hooks/post-commit 追绿复验)。
|
||||
# 合并收尾提交跳过(MERGE_HEAD 在=冲突合并的收尾 commit)——内容归合回后的 CI 全量验。
|
||||
# --no-verify 绕过仅属用户(agent 侧由 worktree-guard 拦截)。
|
||||
set -u
|
||||
REPO="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# 合并收尾提交:跳过文档闸,交合回后 CI
|
||||
[ -f "$(git rev-parse --git-dir)/MERGE_HEAD" ] && exit 0
|
||||
|
||||
RC=0
|
||||
# 收暂存清单(增量档输入):quotepath 关闭保中文名原样,NUL 转行落临时文件传闸机
|
||||
_LIST="$(mktemp "${TMPDIR:-/tmp}/gates-staged.XXXXXX")" || _LIST=""
|
||||
if [ -n "$_LIST" ]; then
|
||||
git -C "$REPO" -c core.quotepath=false diff --cached --name-only -z | tr '\0' '\n' >"$_LIST"
|
||||
bash "$REPO/tools/run_all_gates.sh" --docs --staged "$_LIST" || RC=$?
|
||||
rm -f "$_LIST"
|
||||
else
|
||||
bash "$REPO/tools/run_all_gates.sh" --docs || RC=$?
|
||||
fi
|
||||
if [ "$RC" -eq 0 ]; then
|
||||
exit 0
|
||||
elif [ "$RC" -eq 1 ]; then
|
||||
echo "[直改闸] 文档域闸有新增红,提交已拦。修上方红项后重新 commit,钩子会自动重跑闸;禁跑代码域/游戏类测试,与本次红项无关。" >&2
|
||||
else
|
||||
echo "[直改闸] 闸脚本自身故障(退出码 $RC),不是文档红——把本输出原样呈报用户,勿改文档、勿跑替代测试。" >&2
|
||||
fi
|
||||
exit 1
|
||||
+10
-118
@@ -22,13 +22,6 @@
|
||||
# ——本批改动只有文档件时用:game/ 内的 .md(README、生成清单)、design/、根规则文件、
|
||||
# tools/ 工具脚本、.zcode/ 配置等一切非代码面改动。
|
||||
# --quick 全量档的中段自检形态:跳过渲染闸(窗口化,需开显示器)与静态扫描;完成出库禁用。
|
||||
# --staged <清单文件> 文档域增量档(仅配 --docs):清单=本次提交暂存文件(pre-commit 钩子生成,NUL 转行)。
|
||||
# 触发矩阵(唯一落点):任一 .md → 06/06b/07/08/08d 先按清单内 .md 扫描(快路径);
|
||||
# 待办清单.md/roadmap.md/reports/**.md 任一 → 08c 全量(关系型,不可切片);
|
||||
# design/gdd/systems/**、game/tests/README.md、reports/**.md 任一 → 08e 全量(关系型);
|
||||
# 10 熵增闸恒跑(结构哨兵)。快路径扫出红时全量复跑定谳——清单面外文件的失败不在全量档
|
||||
# 判定面内,全量复跑绿=按绿放行并注记,红=真红;增量判定面与 CI 全量档严格对齐,
|
||||
# 跨文件漏检面(改 A 断 B 的链)由合回后 CI 全量兜底。缺省不带 --staged = 现行全量档,CI 零影响。
|
||||
# 不带参数 = 全量档(两域全跑),触发条件=同批既有代码面改动又有文档件改动。闸件(tools/ 下机检脚本
|
||||
# 与闸壳)自身的改动不占合回全量——其质量义务=落批时人工确认闸可跑通且判据口径未变;
|
||||
# 闸真崩溃时合回闸 fail-closed(跑不出回执即拦),不以全量为兜底。
|
||||
@@ -54,24 +47,16 @@ BASELINE="$STAMP_DIR/baseline.json"
|
||||
|
||||
QUICK=0
|
||||
DOMAIN="full"
|
||||
STAGED_FILE=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--quick) QUICK=1 ;;
|
||||
--code|--docs)
|
||||
[ "$DOMAIN" = "full" ] || { echo "用法: --code 与 --docs 互斥"; exit 2; }
|
||||
DOMAIN="${1#--}" ;;
|
||||
--staged)
|
||||
[ -n "${2:-}" ] || { echo "用法: --staged <暂存清单文件>"; exit 2; }
|
||||
STAGED_FILE="$2"; shift ;;
|
||||
*) echo "用法: tools/run_all_gates.sh [--code|--docs|--quick] [--staged <清单文件>]"; exit 2 ;;
|
||||
*) echo "用法: tools/run_all_gates.sh [--code|--docs|--quick]"; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [ -n "$STAGED_FILE" ]; then
|
||||
[ "$DOMAIN" = "docs" ] || { echo "用法: --staged 仅配 --docs(增量档只定义在文档域)"; exit 2; }
|
||||
[ -f "$STAGED_FILE" ] || { echo "用法: --staged 清单文件缺位:$STAGED_FILE"; exit 2; }
|
||||
fi
|
||||
|
||||
# 每个代码面 worktree 用独立 Godot user 目录(game/override.cfg 由 setup 脚本自愈生成;主区 no-op)。
|
||||
# 并行批共用一套夹具、日志与截图目录会互相踩盘造成假红——隔离建不起来就拒跑(fail-closed)。
|
||||
@@ -88,23 +73,8 @@ fi
|
||||
# 与基线比必判「红项清单变化」假红)、末尾汇总自身崩掉打不出结论。
|
||||
export PYTHONIOENCODING=utf-8
|
||||
|
||||
# ── 直改闸在位自检(车道铁律):pre-commit 钩子失位=主区直改提交静默免验,任何跑批点红暴露 ──
|
||||
_HP="$(git -C "$REPO" config core.hooksPath)"
|
||||
if [ -n "$_HP" ]; then
|
||||
case "$_HP" in /*) _HPT="$_HP/pre-commit" ;; *) _HPT="$REPO/$_HP/pre-commit" ;; esac
|
||||
if [ ! -f "$_HPT" ]; then
|
||||
echo "[gates] FAIL — core.hooksPath=$_HP 但 pre-commit 文件缺位:直改闸失位,主区直改提交免验。"
|
||||
echo " 处置:确认 tools/hooks/pre-commit 在位后 git config core.hooksPath tools/hooks"
|
||||
exit 1
|
||||
fi
|
||||
elif [ ! -f "$(git -C "$REPO" rev-parse --git-path hooks)/pre-commit" ]; then
|
||||
echo "[gates] FAIL — core.hooksPath 未设置且默认钩子位无 pre-commit:主区直改提交免验。"
|
||||
echo " 自愈:git config core.hooksPath tools/hooks"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 代码面(game/ 下非 .md 的行为载体)是否带着未提交改动(只算已跟踪文件——闸件自身产物都落在
|
||||
# gitignore 面)。脏树跑出来的回执记的是 HEAD,验的却是别的字节,合回闸据此拒收。
|
||||
# gitignore 面)。脏树跑出来的回执记的是 HEAD,验的却是别的字节,回执标 dirty_game 由 CI 落账留痕。
|
||||
DIRTY_GAME=0
|
||||
if [ -n "$(git -C "$REPO" -c core.quotepath=false diff HEAD --name-only -- game/ 2>/dev/null | grep -viE '\.md$')" ]; then
|
||||
DIRTY_GAME=1
|
||||
@@ -357,38 +327,6 @@ gate() { # gate <名称> <日志名> <命令...>
|
||||
return 0
|
||||
}
|
||||
|
||||
# 增量文档检查壳(--staged 档专用):先按暂存清单扫(快路径),扫出红时全量复跑定谳——
|
||||
# 清单面外文件的失败不在全量档判定面内,全量复跑绿=按绿放行并注记,红=真红。
|
||||
# 增量判定面与 CI 全量档严格对齐(增量档不产生全量档不会有的红)。
|
||||
gate_docs_inc() { # gate_docs_inc <名称> <日志名> <全量命令...> -- <增量命令...>
|
||||
local name="$1" log="$2"; shift 2
|
||||
local -a full_cmd=() inc_cmd=()
|
||||
local _in_inc=0 _a
|
||||
for _a in "$@"; do
|
||||
if [ "$_a" = "--" ]; then _in_inc=1; continue; fi
|
||||
if [ $_in_inc -eq 0 ]; then full_cmd+=("$_a"); else inc_cmd+=("$_a"); fi
|
||||
done
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════"
|
||||
echo " $name(增量档:暂存 .md $(( ${#inc_cmd[@]} - ${#full_cmd[@]} )) 件)"
|
||||
echo "════════════════════════════════════════════"
|
||||
local rc=0
|
||||
"${inc_cmd[@]}" >"$STAMP_DIR/$log" 2>&1
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
"${full_cmd[@]}" >>"$STAMP_DIR/$log" 2>&1
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ]; then
|
||||
echo " [增量注记] 清单扫描出红、全量复跑绿——红项在暂存清单面外(不在全量档判定面内),按绿放行。"
|
||||
fi
|
||||
fi
|
||||
if [ $rc -ne 0 ]; then
|
||||
grep -E "FAIL|红|Error|error" "$STAMP_DIR/$log" | tail -12 | sed 's/^/ | /'
|
||||
fi
|
||||
NAMES+=("$name"); EXITS+=("$rc"); LOGS+=("$log")
|
||||
return 0
|
||||
}
|
||||
|
||||
gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分片态=多 Godot 进程各跑一片
|
||||
local name="02 单元与集成测试"
|
||||
# 关联档选跑:把套件词列表经 --only= 传给 run_all(闸机来源标记 --only-source=gates,
|
||||
@@ -478,60 +416,14 @@ fi
|
||||
fi
|
||||
# ══ 文档域(6–8e)══
|
||||
if in_domain docs; then
|
||||
# ── 增量触发矩阵(唯一落点,判据依据与漏检面见头注 --staged 段)──
|
||||
_md_list=()
|
||||
_trigger_08c=0
|
||||
_trigger_08e=0
|
||||
if [ -n "$STAGED_FILE" ]; then
|
||||
while IFS= read -r _f; do
|
||||
[ -z "$_f" ] && continue
|
||||
case "$_f" in
|
||||
待办清单.md|roadmap.md|reports/*) _trigger_08c=1 ;;
|
||||
esac
|
||||
case "$_f" in
|
||||
design/gdd/systems/*|game/tests/README.md|reports/*) _trigger_08e=1 ;;
|
||||
esac
|
||||
case "$_f" in
|
||||
*.md) [ -f "$REPO/$_f" ] && _md_list+=("$_f") ;;
|
||||
esac
|
||||
done < "$STAGED_FILE"
|
||||
fi
|
||||
if [ -z "$STAGED_FILE" ]; then
|
||||
# 全量档(CI 与手动档原路径,判定面不变)
|
||||
gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
|
||||
gate "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only
|
||||
gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
|
||||
gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
gate "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
else
|
||||
# 增量档:清单内 .md 走快路径(扫出红全量复跑定谳,见 gate_docs_inc)
|
||||
if [ "${#_md_list[@]}" -gt 0 ]; then
|
||||
gate_docs_inc "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py" -- "$PY" "$REPO/tools/gdd_lint.py" "${_md_list[@]}"
|
||||
gate_docs_inc "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only -- "$PY" "$REPO/tools/gdd_lint.py" --changelog-only "${_md_list[@]}"
|
||||
gate_docs_inc "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict -- "$PY" "$REPO/tools/doc_link_audit.py" --strict "${_md_list[@]}"
|
||||
gate_docs_inc "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict -- "$PY" "$REPO/tools/doc_term_audit.py" --strict "${_md_list[@]}"
|
||||
gate_docs_inc "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict -- "$PY" "$REPO/tools/doc_ref_audit.py" --strict "${_md_list[@]}"
|
||||
else
|
||||
for _n in "06 gdd_lint" "06b 变更记录节" "07 doc_link" "08 doc_term" "08d 引用可核"; do
|
||||
NAMES+=("$_n"); EXITS+=("SKIP"); LOGS+=("")
|
||||
done
|
||||
echo ""; echo "[gates] 06/06b/07/08/08d → SKIP(增量档:暂存清单无 .md)"
|
||||
fi
|
||||
if [ "$_trigger_08c" -eq 1 ]; then
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
else
|
||||
NAMES+=("08c 流水线闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 08c 流水线闸 → SKIP(增量档:登记面文件未触)"
|
||||
fi
|
||||
if [ "$_trigger_08e" -eq 1 ]; then
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
else
|
||||
NAMES+=("08e 能力审计"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 08e 能力审计 → SKIP(增量档:系统文档/能力清单/卡片未触)"
|
||||
fi
|
||||
fi
|
||||
# 全量档(CI 与手动档同判定面)
|
||||
gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
|
||||
gate "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only
|
||||
gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
|
||||
gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
gate "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
fi
|
||||
|
||||
# ── 7. 静态扫描(代码域)+ 熵增闸(两域都跑:它查顶层目录/根文件/图像白名单/退役路径,
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
本清单是流水线的唯一登记处:以后才做的事在此登记一条,随流水线段推进改状态,做完整条删除(条目记进度,不是各段的开工前置);各系统文档的「待办」节只留一行指路存根,不再自建条目。条目格式(标题=登记元数据含可选优先级,正文=实况/缺口/改动面/状态四属性)与状态机以 [doc-conventions §12.1](design/engineering/doc-conventions.md) 为权威。
|
||||
|
||||
#### hobgoblin 内容三件套补齐(2026-11-01 登记,来源=审计发现)
|
||||
|
||||
**实况**:敌人表 hobgoblin 行(寻址键 (1, battle, 3))数值完整在役、战斗正常运行,但内容三件套未交付——立绘、敌种语义模板、敌人系统.md 敌种表行均缺,呈现面因语义模板未成文无定义可依。登记凭据=[敌人系统](design/gdd/systems/战斗循环/敌人系统.md) v1.1「hobgoblin 缺口登记」节(2026-10-13 迭代 24 反哺④)。
|
||||
|
||||
**缺口**:还差敌种语义模板的文档设计讨论闭合(呈现面定义、池构成口径),闭合后立绘走美术线。
|
||||
|
||||
**改动面**:文档+美术素材+游戏代码
|
||||
|
||||
**状态**:待文档设计
|
||||
|
||||
#### 状态合并改累加制——同名状态重复授予改加时长(2026-10-31 登记,来源=会话提及)
|
||||
|
||||
**实况**:2026-10-31 用户立案并四点裁决闭合:六行 refresh 全改累加/时长不封顶/只加时长、层数与强度不变/累加量=本次授予的生效时长(技能施放行带覆盖时长时按覆盖值)。设计定稿=[增益状态](design/gdd/systems/战斗循环/增益状态.md) v1.3(2026-10-31,合并策略「刷新」改「累加」)+[地图战斗资源](design/gdd/systems/战斗循环/地图战斗资源.md) 削弱行引用句随改。查证记录:全仓设计文档、reports 与 git 全历史均无既往累加制决策,本次为新裁决、非补同步。本裁决消解「空刷新的可见性」条目(累加制下重复授予恒有变化,无空操作授予面)。
|
||||
|
||||
**改动面**:文档+游戏代码
|
||||
|
||||
**状态**:文档设计已闭合
|
||||
|
||||
#### 迭代 43 批后待裁两点——名字行字号档位/换色常量退役(2026-10-30 登记,来源=批次移交)
|
||||
|
||||
**实况**:证据=迭代 43 反哺点清单 1/8/10(已按吸收即死退役,git 历史可考)。①**B 区高度 270 vs 252——已裁并落地(2026-10-30 用户裁)**:取代码标准 `stage_h`;布局几何(`stage_h` / `info_panel_w` / `ap_bar_h` / `log_band_h_dig` / `log_band_h_settle`)入驻 `game/data/tables/battle_layout.tres`,经 `ConfigDb.presentation.battle_layout` 单点读取;游戏代码、文档、样张工具三面改指该表,文档去数值化。②**站桩名字行 12px 档位归属**——standee_body.gd 名字行取 `UiKit.FS_CAPTION`(12px),art-bible §7.4 字号档位表下属「清单外 11–13px」。③**art-bible §4.1 换色合并残余三处**——`STAGE_BG` 换值(#3E342A→#3E362C)未执行;`STAND_STONE_RIM`(#C4AC84)仍被 board_cell_unit 口沿高光在役引用;`STAND_STONE_EDGE`(#5A4C3A)由地台缺位回退路径在役引用。**2026-10-31 用户裁两点闭合**:①名字行提档 `FS_HINT` 14 归六档、不增列②装饰 caption 在册面(design/art/art-bible.md v3.29 §7.4 小字号豁免条款;验收底线=名字清晰可读、长名不截字);②换色合并拆解——`STAND_STONE_RIM`/`STAND_STONE_EDGE` 两对照合并执行(绘制点改指目标色+源常量删除,归小批写卡),`STAGE_BG` 对随「战斗区背景图替换」批一并消化(art-bible v3.29 §4.1 登记句已改注)。需求卡片:reports/需求卡片-站桩名字行提档与地台色合并批-2026-10-31.md(v1.1 定稿零待裁点,grilling 复核过)。
|
||||
@@ -220,16 +238,6 @@
|
||||
|
||||
**状态**:文档设计已闭合
|
||||
|
||||
#### 空刷新的可见性(2026-10-18 登记,来源=会话提及)
|
||||
|
||||
**实况**:刷新类策略在剩余次数已满时再授予是合法空操作(返回成功、无任何变化),与"溢出不静默吞"的诚实原则存在张力;MVP 无刷新类内容行,首批刷新行上线时顺带裁决。(原条目无登记日期,按本批格式整改补登 2026-10-18。)
|
||||
|
||||
**缺口**:还差首批刷新行上线时的空刷新语义裁决(提示形态与诚实原则的平衡)。
|
||||
|
||||
**改动面**:文档
|
||||
|
||||
**状态**:待文档设计(备选)
|
||||
|
||||
#### 冒险前资源配比预设(构筑提案)(2026-09-18 登记,来源=会话提及)
|
||||
|
||||
**实况**:构筑提案 2026-09-18 立项、八项裁决全裁(2026-10-04),设计闭合机制=[元进度](design/gdd/systems/跨局循环/元进度.md)「冒险开始参数面与覆盖值通道」(零新机制);2026-10-05 挂起——移出 roadmap 迭代 14,八项裁决与需求卡片冻结保留,重启须用户另行发令;全案与淘汰依据原载已退役提案(git 历史可考),裁决细节冻结在卡片。关联文档:[元进度](design/gdd/systems/跨局循环/元进度.md) v1.0(闭合凭据;现行 v1.25 已复核在役,2026-10-26 文档体检第 10 项);需求卡片 reports/需求卡片-冒险前资源配比预设批-2026-10-04.md(文件头挂冻结横幅)。
|
||||
@@ -283,7 +291,8 @@
|
||||
|
||||
**实况**:扩板已落地(四档板型 10/12/13/14 在跑),2026-10-26 文档面已按单点维护归一:①格边长口径的唯一出处收敛到 [战斗屏规格](design/gdd/ux/battle.md)「棋盘格尺寸公式」——公式含格间距与垂直预留,可读下限 30px,1280 档算例 43/36/33/30 标注为随布局变化的非契约值;②[美术圣经](design/art/art-bible.md) §8.1 改为指路 battle.md、只锁资产侧两条比例,§8.2 甲类整数倍纪律已剔除砖面 tile(瓦片随格边长整格铺满,允许非整数倍);③[HUD框架](design/gdd/systems/表现与支撑/HUD框架.md) 只留装板可行性不等式,删去 36/45 定值档与旧算例;④demo 原型 44px 那一路随 `src/` 退役消失。剩余为代码面两处与口径不同步:`game/probe/layout_probe.gd:15` 的格子可读门槛 `MIN_CELL := 36.0` 仍取 12×12 的旧锚点值,比 battle.md 的可读下限 30px 严——现探针只进 10×10 的 L1 故仍全绿,一旦覆盖 13×13(33px)与 14×14(30px)即会误报红;`game/tests/unit/core/board_gen_reward_test.gd:53` 的格边长冒烟只跑 L1/L2,13×13 与 14×14 无覆盖。断言改动后按 `game/tests/README.md`「能力清单」核对受影响行(验证集清单已退役——test-conventions §8.3)。
|
||||
|
||||
- 需求卡片:[需求卡片-棋盘格边长口径收口批-2026-10-30](reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md)(2026-10-30 已写卡,零待裁点——算式单点提取经 `BoardView._cell_for`/探针门槛 36→30 对齐 battle.md 可读下限/冒烟扩 13×13 与 14×14;探针不扩到 L3,最大板可读面改由实板面积推定断言承担)
|
||||
- 需求卡片:[需求卡片-棋盘格边长口径收口批-2026-10-30](reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md)(2026-10-30 写 v1.0;迭代 46 触发 L3#2 停机退回写卡段后,2026-11-01 用户裁重立 **v2.0**——可读性锚点=用户验收的现行渲染值(基座档 14×14=28px 达标)、人造阈值退役(battle.md 可读下限 30px 句与探针 36px 全废、`MIN_CELL` 手抄常量删除)、探针判据换锚=实读与单点算式严格相等+结构钳制+13/14 推定留痕;v1 的「探针门槛 36→30 对齐」方向作废)。
|
||||
- 停机呈报:[停机呈报-棋盘格边长口径收口批-2026-10-31](reports/停机呈报-棋盘格边长口径收口批-2026-10-31.md)(迭代 46 实现会话触发卡片 §9 L3 #2 预设停机点,2026-10-31 用户裁拆批退回写卡段。**2026-11-01 裁决已落**:14×14 基座档 28px 不再是「低于下限的不达标值」——用户裁可读性锚点=现行渲染画面本身,30/36 属无实测背书的历史编造数全部退役;battle.md `:144` 句退役归文档批落文(反哺点通道)。卡C v2.0 按此重立:算式单点与四档冒烟两件 WIP 复用,探针件返工)。
|
||||
|
||||
**改动面**:游戏代码
|
||||
|
||||
@@ -437,13 +446,22 @@
|
||||
|
||||
#### 营地交互重做·五张需求卡片(2026-10-18 登记,来源=会话提及)
|
||||
|
||||
**实况**:2026-10-17~18 需求讨论澄清会话产出结论文档,用户令按工作内容维度拆卡、卡片不预占迭代号。五卡已写(顺序=执行顺序):①存档制数据层改造批 ②主菜单三入口化批 ③选档界面新建批 ④营地场景图新建批 ⑤Esc 浮窗与营地顶栏批(各卡估时与内容见卡片自身)。三道复核:grilling 子 Agent 对抗审查(五卡各一)→v1.1;用户裁定「事项按推荐的来」→v1.2;用户两次订正(**卡④留在批内不踢出**;前置归用户自立批,Agent 不代跑不代产——曾越权起草的点选反馈设计稿 v0.1 已撤回删除)→卡④ v2.2;**卡④ 2026-10-21 用户令退回美术设计段(v2.3,非有效卡,美术设计闭合后重立卡)**。①②③⑤ 零待裁点可编工程波次:②③ 硬耦合同波(「进入存档」钮落点=选档界面),① 是 ③ 前置;⑤ 随 ④ 代码波同行。Alpha 出口裁决(2026-10-21 用户裁):五卡整体列入 Alpha——08「三 · 界面」已开条目,Alpha 出口依赖五卡完工与卡④三个用户侧前置销号。**工程波次一已落地(2026-10-22)**:卡①②③ 随迭代 33 实现批合回 master(合并提交 ebf40947/5c2a7bcf/508f190b,总收口 6e8f72b2),三卡需求卡片与批次产出物已按「吸收即死」退役(设计口径已吸收进 存档序列化.md/生涯.md/camp.md/08-Alpha版本标准.md v1.13/art-bible.md v3.18,反哺落文凭据=文档批 git 提交 1864f157+9f7b3e8a);卡④(营地场景图)退回美术设计段待重立卡、卡⑤(Esc 浮窗)随卡④ 代码波同行,两卡未编排——编入哪一迭代由用户经迭代编排段发令。关联文档:
|
||||
**实况**:2026-10-17~18 需求讨论澄清会话产出结论文档,用户令按工作内容维度拆卡、卡片不预占迭代号。五卡已写(顺序=执行顺序):①存档制数据层改造批 ②主菜单三入口化批 ③选档界面新建批 ④营地场景图新建批 ⑤Esc 浮窗与营地顶栏批(各卡估时与内容见卡片自身)。三道复核:grilling 子 Agent 对抗审查(五卡各一)→v1.1;用户裁定「事项按推荐的来」→v1.2;用户两次订正(**卡④留在批内不踢出**;前置归用户自立批,Agent 不代跑不代产——曾越权起草的点选反馈设计稿 v0.1 已撤回删除)→卡④ v2.2;**卡④ 2026-10-21 用户令退回美术设计段、2026-10-31 用户令据 req-card 第〇步重立为 v3.0 现行有效卡(美术设计已闭合=样张过审+art-bible 条款版本 v3.24 §6.2)**。①②③⑤ 零待裁点可编工程波次:②③ 硬耦合同波(「进入存档」钮落点=选档界面),① 是 ③ 前置;⑤ 随 ④ 代码波同行。Alpha 出口裁决(2026-10-21 用户裁):五卡整体列入 Alpha——08「三 · 界面」已开条目,Alpha 出口依赖五卡完工与卡④三个用户侧前置销号。**工程波次一已落地(2026-10-22)**:卡①②③ 随迭代 33 实现批合回 master(合并提交 ebf40947/5c2a7bcf/508f190b,总收口 6e8f72b2),三卡需求卡片与批次产出物已按「吸收即死」退役(设计口径已吸收进 存档序列化.md/生涯.md/camp.md/08-Alpha版本标准.md v1.13/art-bible.md v3.18,反哺落文凭据=文档批 git 提交 1864f157+9f7b3e8a);卡④(营地场景图)退回美术设计段待重立卡、卡⑤(Esc 浮窗)随卡④ 代码波同行,两卡未编排——编入哪一迭代由用户经迭代编排段发令。关联文档:
|
||||
- 设计澄清定稿:reports/需求澄清-营地交互重做-2026-10-18.md(v1.0:目标体验原话/目标结构树+纵深稿/10 条交互裁决/验收口径/切批原则/遗留待裁)
|
||||
- 卡④:reports/需求卡片-营地场景图新建批-2026-10-18.md(v2.3,**2026-10-21 用户令退回美术设计段,非有效卡**,美术设计闭合后重立卡,见缺口)
|
||||
- 卡⑤:reports/需求卡片-ESC浮窗与营地顶栏批-2026-10-18.md
|
||||
- 卡④:reports/需求卡片-营地场景图新建批-2026-10-18.md(**v3.2 现行有效卡**,2026-10-31 重立 v3.0、2026-11-01 双审修订 v3.1、同日机检预算裁决修订 v3.2=营地六句柄落 ui_camp_modals.gd 子容器;样张过审+art-bible v3.31 §6.2,开工门已全部销号)
|
||||
- 卡⑤:reports/需求卡片-ESC浮窗与营地顶栏批-2026-10-18.md(**v1.5 现行有效卡**,2026-11-01 双审修订 v1.4、同日机检预算裁决修订 v1.5)
|
||||
- 卡⑥(前置基建):reports/需求卡片-营地模态句柄子容器批-2026-11-01.md(**v1.0**,2026-11-01 用户令立——营地模态句柄子容器 UiCampModals+camp_overlay 句柄迁移,迭代 47 执行序第一位)
|
||||
|
||||
**缺口**:卡④(营地场景图)**已退回美术设计段**(2026-10-21 用户令)——现卡 v2.3 为非有效卡;**重立卡判据=卡头 v2.3 用户令「美术设计闭合(样张过审+art-bible 条款版本)后重立卡,再谈编迭代」**。前置登记(P1–P5 属代码段开工门,非重立卡前置):P1 美术渠道(**2026-10-22 已裁=B 插画级新产**,✦ 渠道作者自跑远程生图管线;规格沿用 art-bible §8.1/§8.2 既有裁决);P2 像素规格(Q6 甲过渡口径已裁,执行归用户线);P3 点选反馈设计稿(用户线,未受命开工;Agent 曾越权起草 v0.1,已按用户令撤回删除;**代码段开工门**);P4 参照物(**2026-10-23 已补**=artwork/2026-10-23-营地场景/Gemini_Generated_Image_ykrc0nykrc0nykrc.jpg,已进 camp-scene-prompts.md §1 风格参考图表、与纵深稿对表、围墙结构冲突已呈报;参照物是参考图,保留 artwork/ 不入游戏目录);P5 GDD/art-bible 落文(文档批,用户发令;**代码段开工门**)。**2026-10-31 用户裁定:保留全部待选稿、各素材第一张样本稿为终稿、「目前我看每个都还可以接受」=样张过审完成;art-bible 条款版本已落 v3.24 §6.2(camp.md v2.2/camp-scene-prompts v1.2/asset-path-map/art-assets-checklist/评估报告同步)——卡④ 重立判据两样已齐。** 终稿指定清单= artwork/candidates/_终稿裁定-2026-10-31.txt(用户准备在游戏内做最终审核)。**重立卡待用户发令**;以下均为**代码段 `/iter` 开工门,不阻塞重立卡**:P3/P5 两项用户侧前置未销号(P2 Q6 甲口径已裁不阻塞写卡、终档置换归反哺点)、camp-scene-prompts §5 五个待裁点(帐篷尺寸/门扇高宽/布告板位置/描边颜色追认/环境子板色值)未清零;十张终稿仍为原始候选未做后处理未落 `game/assets/art/`,此属实现段 T1/素材录入(asset-ingest 第 3 步终稿拷入),用户 2026-10-31 令只生成素材不做后续,开工时另发令。
|
||||
**代码段开工门(/iter 闸门)**:卡④ 已重立为 v3.0 现行有效卡(美术设计已闭合=样张过审 2026-10-31+art-bible 条款版本 v3.24 §6.2,据 req-card 第〇步);原「美术设计闭合后重立卡,再谈编迭代」判据已满足,可编迭代;**重立卡判据=卡头 v2.3 用户令「美术设计闭合(样张过审+art-bible 条款版本)后重立卡,再谈编迭代」**。前置登记(P1–P5 属代码段开工门,非重立卡前置):P1 美术渠道(**2026-10-22 已裁=B 插画级新产**,✦ 渠道作者自跑远程生图管线;规格沿用 art-bible §8.1/§8.2 既有裁决);P2 像素规格(Q6 甲过渡口径已裁,执行归用户线);P3 点选反馈设计稿(用户线,未受命开工;Agent 曾越权起草 v0.1,已按用户令撤回删除;**代码段开工门**);P4 参照物(**2026-10-23 已补**=artwork/2026-10-23-营地场景/Gemini_Generated_Image_ykrc0nykrc0nykrc.jpg,已进 camp-scene-prompts.md §1 风格参考图表、与纵深稿对表、围墙结构冲突已呈报;参照物是参考图,保留 artwork/ 不入游戏目录);P5 GDD/art-bible 落文(文档批,用户发令;**代码段开工门**)。**2026-10-31 用户裁定:保留全部待选稿、各素材第一张样本稿为终稿、「目前我看每个都还可以接受」=样张过审完成;art-bible 条款版本已落 v3.24 §6.2(camp.md v2.2/camp-scene-prompts v1.2/asset-path-map/art-assets-checklist/评估报告同步)——卡④ 重立判据两样已齐。** 终稿指定清单= artwork/candidates/_终稿裁定-2026-10-31.txt(用户准备在游戏内做最终审核)。重立卡已完成(v3.0 现行有效卡)。**2026-11-01 用户令修订换代**:卡④ v3.1→v3.2、卡⑤ v1.4→v1.5(双审修订+机检预算裁决——营地六句柄落 ui_camp_modals.gd 子容器,卡⑥ 前置建件);**代码段 `/iter` 开工门已全部裁断销号**——P3 销号口径=camp.md v2.2 四态规格即设计稿;P5 销号口径=形态落文完成、实装回填归反哺点(camp-scene-prompts v1.3 §5 已改已裁+art-bible v3.31 §6.2 同步,本会话文档批落文);十张终稿后处理授权随 `/iter` 开工令一并生效(不再两次发令)。**开工门清零,迭代 47 可开工,执行序=卡⑥ 句柄子容器 → 卡④ → 卡⑤。**
|
||||
|
||||
**改动面**:文档+游戏代码+美术素材
|
||||
|
||||
**状态**:文档设计已闭合+待美术设计+已写卡
|
||||
**状态**:文档设计已闭合+美术设计已闭合+已写卡+已编迭代 47
|
||||
|
||||
#### 模态句柄册分域重构(2026-11-01 登记,来源=会话提及)
|
||||
|
||||
**实况**:重构证据=`game/presentation/ui_modals.gd:7-20`(类变量 14 实测)+停机呈报-迭代47机检预算互斥-2026-11-01.md(卡④⑤ 平铺合计 19>S13 上限 15)——按技术角色平铺 13 模态句柄+flow,迭代 47 营地域新增六句柄顶格 S13 类变量上限 15(2026-11-01 用户裁:最小改动先走——营地六句柄落 `ui_camp_modals.gd` 子容器,随迭代 47 卡⑥/卡④/卡⑤ 落地,本条只登记**全量分家**)。目标形态=存量句柄按域分组抽容器(局内 run 六件/菜单与跨语境归组)+ModalFlow 自 UiModals 升格独立持有;行为零变化、纯句柄搬家;返工面=全仓探针深员寻址+`ui_registry.gd node()` 寻址+`main_ui_build.gd` 装配。拆分判据权威=code-conventions §1.1(沿职责轴;营地子容器先例=`ui_camp_modals.gd`,随迭代 47 落地后为准)。
|
||||
|
||||
**改动面**:游戏代码
|
||||
|
||||
**状态**:待写卡
|
||||
Reference in new issue
Block a user