Compare commits

..
Author SHA1 Message Date
DKChan ff5fcd644d 迭代46收尾文档(审计结论+审计修正): 独立验收审计通过(零缺漏——对照表逐行/自跑八套件/削弱全申报面/无变异撤销取证,报告落reports)·处置审计附加发现①两新件.uid边车补提交②S8_FILES与S7_B1_SET同步增补battle_refresh_flow(新件零await,S8/S7实跑绿)·实现报告补审计结论节 2026-10-31 09:20:13 +08:00
DKChan c10bbc1114 迭代46收尾文档(实现报告+反哺点): 卡A/B收口·卡C停摆(L3#2实板可读面不达标——14×14基座档28px<30px,停机呈报落主区reports)·实际对照表V1-V12与卡B六行·结构预算S13前后·目检五项登记·实现决定十一条备案·反哺点九条(奇物/行动经济/战斗结算/地图战斗资源/architecture三行/art-bible两行/battle.md随裁决/术语表零增) 2026-10-31 08:56:57 +08:00
DKChan fde1795dd0 迭代46卡B(名字行提档与地台色合并): 名字行五取值点FS_CAPTION→FS_HINT(12→14·消散提示:114合法位零触碰)·_name_baseline偏移17→18(0.35h字号档推导14×0.35≈5,T0实测ts=(14,20)记录)·name_line_probe增name_font_size键·ui_kit删STAND_STONE_EDGE/STAND_STONE_RIM两常量+原位增PLAZA_EDGE=Color8(76,64,56)·三绘制点改指(描边→PLAZA_EDGE·顶缘线/口沿高光→BRICK)·standee测试V6换代149→150(9px档→8px档)+V10/V11/V12增量(探针实读/两绘制点源码锚/FS_CAPTION计数锚==1/常量表退役零键/BRICK·PLAZA_EDGE逐位/改指源码锚)·golden三张0.00%留痕(换值色差≤5低于容差≤16——重锚无需执行)·grep退役常量仅剩测试断言串(预期例外)·26 checks全绿·gdstyle零新增键 2026-10-31 08:47:56 +08:00
DKChan 45b53d6897 迭代46卡A-T8修正(S7): S7_B1_SET增补battle_refresh_flow.gd——换图刷新流程件=C13拆分边界的B1域拆件(承载旧资源retire_mapping/装板编排调用,卡A§八明列新结算族件);判据口径不变(B2/B3/B4对外API仍限B1域调用);architecture模块归属BattleRefreshFlow行走反哺点 2026-10-31 08:34:07 +08:00
DKChan f498d2ec85 迭代46卡A-T8修正(S9): 四处显式非参数化容器注解改:=推断(R1无类型容器——emit返回值承接形态;零行为改动) 2026-10-31 08:24:26 +08:00
DKChan bf7aa514b6 迭代46卡A-T6(数据行与牌库计数): adventure_feats换代37行(普通14/优秀13/稀有10/传说0·牌库102+37=139——旧30行断言按实数换代零放宽)·V11专项(validate零违例·七行稀有度cap对表·desc禁词·七件计数器引用闭合[value_counter/when-id全有写入方——预存行消费点记账形态不入判据域]·三计数器在册)·refresh_feats 85 checks绿·adventure_feats 138 checks绿 2026-10-31 08:08:37 +08:00
DKChan 208e5652db 迭代46卡A-T5(五件后续效果): 授予段round_end heal value_counter兑付(坑道小憩——units.heal封顶·满血未生效行·先于set清零行消费层值)·石层缓冲/蓄力周转全走既有消费面(统一damage_taken与attack_bonus value_counter零新码)·feats.tres+3行(石层缓冲common/蓄力周转excellent/坑道小憩common·trigger结构按卡§十.T6)·V6全局固定减伤(pierce8→6双刷不叠加·未刷新轮不减·地形max(下限,ev−2))·V9轮末恢复(白盒预置上限3闸·回复3层清0·满血未生效·自然累计2)·V8蓄力消费(攻击后清0·战斗新建0)·V7延迟群伤(刷新零伤害行·战斗段末×2)·窄测三件全绿(44/70/134) 2026-10-31 08:06:06 +08:00
DKChan be7ef54e30 迭代46卡A-T4(成功事实与命中施加): feats.tres+2行(崩壁冲击/矿道红利——群伤open_ticket与grant_gp订阅面)·V4成功事实专项(非Active/每轮上限/RAP不足三拒面零事实零换图——成功恰一次经probe_br_counter计数与board_changed双观测)·V10矿道红利专项(escrow每次成功+1·fx_grant_gp行在案·拒绝零变化)·refresh_feats 48 checks全绿 2026-10-31 07:56:07 +08:00
DKChan c062b62d12 迭代46卡A-T3(两件基座): action_economy dig_paid命中环累计grant_reserve_ap(扣费受理后一次性入池·连锁不二次·拒绝轮零入池)+request_refresh收折后价入参(缺省-1=表基线逐位不变)·新建BattleRefreshFlow(可用性门/折价扣费/换图/成功事实——C13拆分边界,_effective_refresh_cost声明序第一命中floor(base×mult/100),can与执行同源)·编排器两公开方法单行转发(删旧刷新体,C10行数只降)·授予段apply_board_refreshed成功事实单点+奖励授予件defer_ticket案C同队列(类变量零增员)+来源豁免fx_board_refresh·feats.tres+2基座行(矿脉储能/省力周转·excellent·cap1)·T3四专项+V12侧全绿·round_flow 134 checks回归绿 2026-10-31 07:52:14 +08:00
DKChan b44d3234b8 迭代46卡A-T2(全局damage_taken统一): 新增_emit_hero_damage_taken唯一发射口(payload必含kind/amount/source/cell/round/hp_ratio)·_enemy_shield_apply改名_apply_hero_damage_effects=唯一消费族(组合次序shield→damage_reduce→ac_bonus→counter_add冻结)·敌方攻击改走统一口(掷点后交付前时点不变)·_resolve_board_flat_hero下限前接入(hero_damage_consumed标记闸防重复)·地形路径并入全局消费族并删本地_terrain_damage_reduce(全局受伤语义=shield同面消费)·私有可能净增1≤2·refresh_feats_test新建V5两专项(四路径逐路恰一次+无重复消费,临时承伤计数专长经ConfigDB注入)·窄测refresh_feats/damage_controller/seal_polarity/round_flow全绿(44/70/134 checks) 2026-10-31 07:44:24 +08:00
DKChan 94a05afd49 迭代46卡A-T1(词表扩签): EVENTS+refresh_request/board_refreshed(20→22)·MINE_EVENTS同步换图刷新面·EFFECT_KINDS+grant_reserve_ap/apply_discount(32→34)·零fact/op/DO_KEYS新增·forge_table计数断言20/32→22/34换代·effect_words新增两事件两效果在册断言(旧出域负例全保留)·孤立验证两件全绿(20 checks/exit0) 2026-10-31 07:35:16 +08:00
59 changed files with 2843 additions and 906 deletions

No files matched your search

+7 -7
View File
@@ -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-commit 钩子(`tools/hooks/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 @@
**判据**:描述含多个实体、实体间有明确关系(先后顺序、包含、依赖、状态转移、布局对比)的内容时,直接画图说明,不写长段文字;单点事实(一句装得下)不画,纯数据对照用表格。
**载体**:用 diagram-design 技能出 HTML/SVG 内联交付(流程/状态/结构/实体关系与空间对比、像素级示意、界面草图同一通道),大图精修与导出用 archify 技能;查看端不支持内联渲染时用字符画。
**载体**:默认用 visualize 技能出 HTML/SVG(会话内联渲染,表现力优先),流程/状态/结构/实体关系与空间对比、像素级示意、界面草图同一通道;查看端不支持内联渲染时退回 Mermaid 代码块,仍不行用字符画。
**边界**:硬数值与前提条件留在文字里,图不承载唯一数值依据;图与文禁重复说同一件事,文字只留图说不清的部分。
@@ -93,12 +93,12 @@
## 硬性红线(勿违反;操作细则在 process-conventions.md 与各规约)
- 车道铁律(2026-10-31 用户裁恢复)——主工作区只作合并落点,一切开发/设计改动走独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`(建区即跑 `tools/setup_worktree_userdir.sh`),收口=冻结→件核→并 master→重塑→主区 `git merge --no-ff`→CI 全量绿→删区,CI 红回任务 worktree 修复合回;主区唯一合法写动作=合并,agent 侧由 worktree-guard 拦主区 Edit/Write 与非 merge 提交;豁免面仅 `.zcode/`、`.qoder/`(不入 git,主区直改);commit 点零钩子检查(pre-commit 直改闸已退役),全量验证归合回后本地 CI(`tools/hooks/post-merge` 触发,见「运行与验证」首条);`--no-verify` 仅属用户,agent 禁用(细则见 process-conventions §1)
- 车道铁律(判据与改动域划分同一,按文件性质切;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)
- **仓库根禁止设会话状态文件**(`active.md` 已废除)——现状看 roadmap「当前位」,待办看待办清单,过程看 git 提交信息,产出物看 `reports/`;任何文档禁止另设「当前状态快照」节,两处记同一件事必然漂移(细则见 doc-conventions 第 10 节)
- 测试执行两入口铁规——只有迭代 loop 开发与用户点名两个触发入口;其余会话零测试,需测试支撑先请示并注明未跑测
- 合回后验证 = 本地 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)
- 合回后验证 = 本地 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)
- MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起
- 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6)
- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,可 grep 定位、在当轮真实跑批中执行并通过,判据绑被测改动特有的可观测提交面;**禁变异类测试与撤销类取证**(2026-10-24/2026-10-28 用户裁——人为制造红属伪造证据),证明做不出=停卡呈报;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §8+iter 技能第 5 步)
@@ -249,17 +249,18 @@
| **文档域** | 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 共享件例外);开发期手动档按本批改动域选 `--code`/`--docs`,合回后 CI 恒跑全量档。代码域跑前先过**素材齐盘预检**——`game/assets/art/**` 与一切 `*.import` 边车都不入 git(2026-09-29 裁定),worktree 冷检出必空盘,空盘态冒烟 V1 成片假红、渲染闸更是一段 golden 都不比。
口径三条:**域划分的唯一出处是 `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 都不比。
### 车道分层执法(2026-10-31 用户裁恢复「一切改动走 worktree」)
### 车道分层执法(2026-10-26 用户裁「按路径切车道,取代一切改动走 worktree」)
一切改动走独立 worktree,主工作区只作合并落点。执法全机械——判据只有 git 图与路径(豁免面 `.zcode/`、`.qoder/` 不入 git,主区直改),不含「改动大小」等语义判断。
改动车道与改动域同一判据(文件性质):代码面=worktree 批车道,文档面=主工作区直改车道。执法全机械——判据只有文件路径性质与 git 图,不含「改动大小」等语义判断;「预期大改」由用户开工点名自愿开 worktree,不进规则。
| 执法层 | 载体 | 职责 | 判据 |
|---|---|---|---|
| **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 图 |
| **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 图 |
验证收拢为合回后本地 CI 全量(post-merge 触发),commit 点零执法;主工作区防污染由 ZCode 层守卫承担——只约束 agent,用户手工改动不受限。子代理覆盖面(2026-10-26 冷启动评估实测):子代理的工具调用不经过 ZCode 层守卫——ZCode 层实际只覆盖主会话工具调用;残余暴露面=子代理写主工作区与蓄意 `--no-verify`(该旗标整族跳过 git 层钩子),属故意越权而非遗忘型失误,与防遗忘的设计目标正交。
取舍依据:失败代价不对称——docs 红是死链/术语/格式,下次任何跑批对基线比对必暴露、秒级修复,故文档面轻执法(commit 点闸、无回执流程);代码面红是运行时行为坏,保留「worktree+批末域闸+回执硬绑定」全套。git 层钩子对一切提交者生效(含用户手工提交,紧急出口 `--no-verify`);ZCode 层只约束 agent。子代理覆盖面(2026-10-26 冷启动评估实测):子代理的工具调用不经过 ZCode 层守卫(代码面 Edit 未被拦、`--no-verify` 探针未被拦)——ZCode 层实际只覆盖主会话工具调用,git 层因此是唯一覆盖一切提交者的执法层;残余暴露面=蓄意 `--no-verify`(pre-commit 族钩子被该旗标整族跳过,git 层无法自防),属故意越权而非遗忘型失误,与防遗忘的设计目标正交。
### 三条判定硬闸现行状态
+10 -10
View File
@@ -1,22 +1,22 @@
# 流程规范(Dungeon Sweeper)
> 约束范围:一切批次的流程纪律——车道(一切改动走独立 worktree,主区只作合并落点)、五段流水线、批次工作流、测试执行细则、像素件工作纪律。
> 约束范围:一切批次的流程纪律——车道(代码面 worktree 批/其余主区直改)、五段流水线、批次工作流、测试执行细则、像素件工作纪律。
> 分工:硬性红线的一句话索引在 AGENTS.md「硬性红线」;本文承载其操作细则;批次开工前通读本文。
**开工任何批次前必须通读本文。**
## 1. 分支纪律(worktree 铁律)
## 1. 分支纪律(车道铁律)
主工作区(master 检出)只作合并落点,一切开发/设计改动禁止直接发生在主工作区(2026-10-31 用户裁恢复;2026-10-30 的「主区直改+直提」车道与 commit 点 pre-commit 直改闸随之退役;验证模型不动——合回后本地 CI 仍是唯一强制验证点):
一切面主工作区直改+直提(2026-10-30 用户裁本地 CI 化:验证挪到合回后,主区直提不再拦任何面;判据与 §3 第 8 条改动域划分同一):
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 → 重塑 → 主区合回 → CI 验证 → 删区**——代码与断言改完即冻结,全仓件核 grep 查残留;master 已被别的批次推进时先在 worktree 内 `git merge master` 解冲突(必须在合回之前,合回后才并=CI 验的是中间态);**重塑**=迭代分支(iter<N> 形)合回前执行 `python tools/reshape_cards.py`,把分支线性史按卡末态快照压成一卡一笔(可选追加一笔纯文档收尾),master 台账由此每卡一行——工具自带「重塑前后树逐字节一致」断言与 backup 分支,不改任何文件内容;非迭代批免重塑;然后主工作区 `git merge --no-ff <任务分支>`——这是主区唯一合法写动作(合回守卫对迭代分支数卡校验,未归卡提交拦下)。**CI 全绿后才 `git worktree remove`+删分支;CI 红不删区——回任务 worktree 修复提交再合,追绿后删区**。游戏类测试(冒烟/单测/MC/探针)批内默认零执行(两入口铁规,见 §4),用户点名或当场问才跑
3. **合回后验证(本地 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):跑批期间新触发不中断当前轮,轮尾对最新尖端补跑,绝不逐笔各跑一轮
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(子代理不经守卫层)
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
## 2. 五段流水线
**需求改动**(游戏代码,含随逻辑写/改的测试)按五段流水线走:**登记 → 文档设计/美术设计(两条设计线)→ 写需求卡片 → 迭代编排 → 实现**;工程/文档设计/美术素材三类改动不走写卡与编排段,走「(如需设计讨论)→ 用户发令 → 独立 worktree 直改 → 合回 CI」(车道细则见 §1)。两层口径(2026-10-25 用户立):需求卡片=需求单位的实施文档,任何工作量皆可写、皆可编入迭代;工作量限制只属迭代层——迭代估时总量 <5 个工作日=「冻结待凑批」,不可开工。段间不自动流转,每段转进由用户发令;每段一个技能入口(五者均装于项目 `.zcode/skills/`:doc-design/asset-ingest/req-card/iter-plan/iter),登记不立技能(条目格式由流水线闸强制)。设计工作在会话内进行、用户主导、禁无监管自跑。
**需求改动**(游戏代码,含随逻辑写/改的测试)按五段流水线走:**登记 → 文档设计/美术设计(两条设计线)→ 写需求卡片 → 迭代编排 → 实现**;工程/文档设计/美术素材三类改动不走写卡与编排段,走「(如需设计讨论)→ 用户发令直改 → 主区直改+commit 点闸」(车道细则见 §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,7 +48,7 @@
7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补
**完成**
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 语义保留)
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 条),合并后无手工动作
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/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注
+1 -1
View File
@@ -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-commit 钩子自动追绿。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
行为探针使用随机化玩家行为(封印/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
## 5. 测试函数怎么写——验收清单条目的落码规范
+15 -15
View File
@@ -11,7 +11,7 @@
>
> **兑付频率(先看这条,它是三条渠道的共同前提)**:奇物**不是打一场战斗给一份**。关内的普通战斗节点打完了什么也不给;一关之内奇物**只兑付一次**,触发点是**关底 Boss 被击败**——而按 [冒险结构](冒险结构.md) 的定义,打掉关底 Boss 恰好就等于"通过这一关",这两件事是同一个时刻,不是一条链上的两步。
>
> 状态:**已实现**(2026-10-04 双层 BD 实施批落地);现行为 v1.3。本文件是奇物的唯一定义文档。
> 状态:**已实现**(2026-10-04 双层 BD 实施批落地);现行为 v1.2。本文件是奇物的唯一定义文档。
>
> 数值纪律:本文件只写概念、取值域与指路;每件给多少、效果是什么一律不进正文,事实源是 `data/tables/feats.tres` 与 `data/tables/adventure.tres`。
@@ -99,25 +99,25 @@
### 换图系(7 件,设计定稿,待实现)
换图系把「弃图刷新」从坏图逃生改成主动构筑行为。两件基座分别解决 RAP 的来源与价格;后续专长让成功刷新产生输出、生存或 GP 资源收益。七件不要求一次拿齐,不设强制先拿基座、集件标签或集件奖励。
换图系把「弃图刷新」从坏图逃生改成主动构筑行为。两件基座分别解决 RAP 的来源与价格;后续专长让成功刷新产生输出、生存或资源收益。七件不要求一次拿齐,不设强制先拿基座、集件标签或集件奖励。
| 层 | 代号 | 规则 | 行为职责 |
|---|---|---|---|
| 基座 | 矿脉储能 | 每次付费挖格被受理后,额外获得 RAP;安全格与危险格同口径 | 持续挖图也能准备刷新,不再必须少挖停手 |
| 基座 | 省力周转 | 弃图刷新的 RAP 成本减半 | 同一份储备支持更多刷新 |
| 输出 | 崩壁冲击 | 成功刷新后,在本轮战斗段末对全体存活敌人造成一次固定伤害 | 刷新成为直接进攻行为 |
| 输出 | 蓄力周转 | 成功刷新攒层,最多 3 层;本轮下一次主角攻击消费全部层数后清零,战斗结束不跨战保留 | 连续换图蓄成一次单点爆发 |
| 生存 | 石层缓冲 | 本轮至少成功刷新一次后,主角每次受到伤害固定减少 2 点;不叠加 | 刷新形成当轮全局防御姿态 |
| 生存 | 坑道小憩 | 每次成功刷新累计 1 点恢复,最多 3 点;本轮授予段合计回复生命,封顶生命上限 | 放弃当前图换取恢复 |
| 资源 | 矿道红利 | 每次成功刷新固定获得 1 GP | 刷新动作自身带少量GP收益 |
| 基座 | 掘进储能 | 每次付费挖格后额外获得 RAP;安全格与危险格同口径 | 持续挖图也能准备刷新,不再必须少挖停手 |
| 基座 | 折价换图 | 弃图刷新的 RAP 成本减半 | 同一份储备支持更多刷新 |
| 输出 | 弃图轰击 | 成功刷新后,在本轮战斗段对全体存活敌人造成一次伤害 | 刷新成为直接进攻行为 |
| 输出 | 换图蓄势 | 成功刷新攒层,层数有上限;下一次攻击附加全部层数对应的伤害后清零,战斗结束清空 | 连续换图蓄成一次单点爆发 |
| 生存 | 换图庇护 | 成功刷新后,在本轮授予段获得护盾 | 用刷新预防后续伤害 |
| 生存 | 弃图休整 | 成功刷新后,在本轮授予段回复生命,封顶生命上限 | 放弃当前图换取恢复 |
| 资源 | 弃图回收 | 成功刷新后,按旧图探索进度在本轮授予段回收清图奖励 | 先探索再主动弃图变现 |
共同规则:
- **双基座叠加**:矿脉储能与省力周转可以同时持有,产 RAP 与成本减半分别生效;每轮刷新次数上限继续限频,不设互斥规则。
- **成功才触发**:后续五件只认成功换图;刷新被拒绝时不产生事实,也不给输出、生存或资源收益。同一轮多次成功刷新按发生顺序逐次登记。
- **轮末兑付**:刷新不新增结算段。崩壁冲击走本轮战斗段末结账,石层缓冲在每次主角受伤时消费,坑道小憩与矿道红利走本轮授予段兑付。
- **全局受伤面**:石层缓冲覆盖敌方攻击、危险格、错误封印资源格与地形造成的主角伤害;临时生命值不在本流派设计范围内。
- **基线不变**:没有这些专长时,RAP 来源、刷新成本、清图奖励与伤害结果保持原规则。数值与稀有度归 `feats.tres`,落表前本节只作设计声明。
- **双基座叠加**:掘进储能与折价换图可以同时持有,产 RAP 与成本减半分别生效;每轮刷新次数上限继续限频,不设互斥规则。
- **成功才触发**:后续五件只认成功换图;刷新被拒绝时不产生效果。同一轮多次成功刷新按发生顺序逐次登记。
- **轮末兑付**:刷新不新增结算段。群伤、护盾、回血与回收按[战斗结算](../战斗循环/战斗结算.md)的既有段序兑付,刷新瞬间不直接改这些战斗结果。
- **回收看旧图**:弃图回收读取被放弃旧图的探索进度,不把旧图或新图判为清图;具体口径归[地图战斗资源](../战斗循环/地图战斗资源.md)。
- **基线不变**:没有这些专长时,RAP 来源、刷新成本、清图奖励与刷新结果保持原规则。数值与稀有度归 `feats.tres`,落表前本节只作设计声明。
### 迁入登记(秘宝域迁出件;实装批落地后并入件表)
@@ -479,7 +479,7 @@
11. 凭证拿到即开,不进持有集,玩家无法囤积——选中或买下的同一时刻就开专长三选一。
12. 凭证带有计步保底:连续 5 次三选一展示未出现则第 6 次必出;计数跨奖励节点与商店共享,刷新后的重新展示计入次数,限购用满后保底不再触发。
13. 被称为流派基座的专长必须能说明拿到前后的操作差异与新行为的持续资源来源;只有同一操作后的泛用数值增长,不得登记为基座。
14. 换图系两件基座同时持有时都生效;后续五件只在成功刷新后触发,无专长基线不变;石层缓冲覆盖所有主角受伤路径且同轮不叠加,矿道红利按成功刷新次数固定获得 GP。
14. 换图系两件基座同时持有时都生效;后续五件只在成功刷新后触发,无专长基线不变;弃图回收按旧图探索进度结算,同一旧图至多回收一次。
> 实装批落地前,现役代码按旧 27 件专长目录与旧资源成员在同框架下运行;新成员口径(27 件基础件表 / 凭证件表)自实装批起验。
@@ -1,7 +1,7 @@
# 地图战斗资源
> 一句话:格面资源的产出、极性字典与清图奖励封装
> 状态:已定稿(自旧体系迁移);现行为 v1.3
> 状态:已定稿(自旧体系迁移);现行为 v1.2
## 设计目的
@@ -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(敌方输出池;同名重复授予只加时长)——幅度见 `status_effects.tres` weaken 行 | sapped(主角输出池)——幅度见 `status_effects.tres` sapped 行 |
| weaken 削弱 | weaken(敌方输出池;同名重复授予只刷新剩余次数——2026-09-18 续时定案)——幅度见 `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,8 +158,29 @@
| 可配置可替换 | 内容 = 池行值;允许即时类(当场兑付,不入库) |
| 图类型差异化是预留插槽 | 现行只有默认槽;结构位已留,启用走棋盘生成词表落定 |
持有弃图回收专长时,同一清图奖励对象也可按旧图探索进度部分回收;这不改变正常清图与清图奖励的定义,例外口径见下节。
举证:本节为封装与流程规则,无计算。
### 弃图回收:按旧图探索进度兑付(设计定稿,待实现)
弃图回收让玩家不必挖完最后几个安全格,也能把已经推进的探索换成一部分清图奖励。它只读取被放弃的旧图,不把旧图判为清图,也不把新图判为已清图。
旧图退役前记录三项读数:装板初始已开安全格数、装板初始未开安全格数、退役时已开安全格数。探索进度定义为:
```
探索进度 =(退役时已开安全格数 − 装板初始已开安全格数)÷ 装板初始未开安全格数
```
进度限制在 0~1。玩家付费挖开与连锁展开的安全格都真实推进探索,计入分子;装板时白送的初始格、封锁格与危险格不计入。没有新探索就刷新,进度为 0,不能获得回收奖励。
回收兑付的是旧图在装板期已经摇定的清图奖励对象,按探索进度取对应份额;具体比例、档位、取整与数值归调参。它只发基础奖励的进度份额:
- 不触发完美封印加倍,不产生清图事件,不执行正常清图的整板兑付。
- 同一旧图只在成功退役时回收一次;新图不继承旧图探索进度。
- 刷新被拒绝时旧图不退役,也不回收;成功后的兑付时机归[战斗结算](战斗结算.md)本轮授予段。
- 正常清图仍发完整清图奖励对象;弃图回收不得让同等探索投入的收益无条件高于正常清图。
## 依赖与输出
本系统被两侧夹住:事实与数值从上游来,调用与呈现往下游去。下表就是删除任何一方时的影响面清单。
@@ -239,6 +260,9 @@
- 类型封闭与字典完整:表里出现九型之外的类型、或任一型缺正向/负向行,加载拒绝。
- 未生效可见:满层增益、满血正向治疗、无存活敌的群伤,各自在结算明细记"奖励未生效"行,零折算、零补偿。
- 加载护栏:池空、清图池无正当量、增益引用悬空——任一命中即加载时返回错误并中止;默认内容加载通过。
- 弃图回收进度:付费挖开与连锁展开的安全格计入探索,初始格、封锁格与危险格不计;无新探索时进度为 0,不能获得回收奖励。
- 弃图回收恰一次:成功退役的旧图按当次探索进度回收其预摇清图奖励对象,新图不继承进度,同一旧图不能重复回收;被拒绝的刷新零兑付。
- 回收不是清图:弃图回收不触发完美封印加倍、清图事件或正常清图整板兑付;正常清图仍发完整清图奖励对象。
- 表实一致:数据表字段与奖励表字段定义逐字段一致。
## 待办
+18 -18
View File
@@ -1,13 +1,13 @@
# 增益状态
> 一句话:增益/减益的状态池、叠层与衰减
> 状态:已定稿(自旧体系迁移);现行为 v1.3
> 状态:已定稿(自旧体系迁移);现行为 v1.2
## 设计目的
战斗里有一类效果不在当场一次性用掉,而要管上几次结算:挖开安全格拿到的主角增益、封印标中带来的怪物削弱、踩雷喂给怪物的增强(警觉——blast 型负向)、标错封印招来的负向兑付,都是这类。本文把它们统称"状态":发给主角的有益效果叫增益(失衡与乏力是例外——它们是发给主角的减益),发给敌人的负面效果叫减益;敌方侧的增强同样是状态——几个方向共用同一个状态池。
增益状态就是这一个状态池:它收下全部状态,用同一套规矩管理——发入、合并(同一种效果重复拿到时按表行策略处理:叠层加一,或把剩余次数累加上本次授予的时长——读 `status_effects.tres` 逐行 stack_policy)、衰减(每次结算后剩余次数减一,减到零效果消失)、清空(战斗结束全部清除)。没有它,几类效果得各写一套计时逻辑,结算明细也无法逐行指回"这效果是我哪步棋带来的"。状态池管机制、不管数值从哪来:某个效果该多大,由各收益系统的表去定,状态池只照章入列、按次衰减。
增益状态就是这一个状态池:它收下全部状态,用同一套规矩管理——发入、合并(同一种效果重复拿到时按表行策略处理:叠层加一,或只刷新剩余次数——读 `status_effects.tres` 逐行 stack_policy)、衰减(每次结算后剩余次数减一,减到零效果消失)、清空(战斗结束全部清除)。没有它,几类效果得各写一套计时逻辑,结算明细也无法逐行指回"这效果是我哪步棋带来的"。状态池管机制、不管数值从哪来:某个效果该多大,由各收益系统的表去定,状态池只照章入列、按次衰减。
## 系统范围
@@ -76,14 +76,14 @@
举证:本节为授予路径与登记规则,无计算。
### 同名状态再拿到:叠层、累加、并存
### 同名状态再拿到:叠层、刷新、并存
同一种状态还没消失又拿到一份,怎么合并由状态表每行的合并策略字段说了算,共三种。合并在授予那一刻由状态池完成;多个状态在结算里按什么先后起作用,是战斗结算的编排——两件事互不干扰。
| 合并策略 | 重复授予时发生什么 | 说明 |
|---|---|---|
| 叠加 | 层数加一;剩余结算次数不动——只有首次授予定钟 | 现行内容行多数用叠加(逐行合并策略读 `status_effects.tres`) |
| 累加 | 剩余结算次数加上本次授予的时长——技能施放行带覆盖时长时按覆盖值加;层数不变 | 现行内容行六行用累加(削弱行 weaken、增益技行 empower / fortify、主角增益行 attack_up / ac_up);重复拿一次就多攒一段时长,同一轮拿几份攒几段,停手后按剩余次数逐轮耗完;逐行读 `status_effects.tres` |
| 刷新 | 剩余结算次数重置为该实例首次授予时的初始值,层数不变 | 刷新类内容行已就位——削弱行 weaken(2026-09-18 续时定案)、增益技行 empower / fortify、**主角增益行 attack_up / ac_up(2026-09-20 用户拍板「只续时不叠层」,全状态表增益/减益两侧合并语义就此统一为:主角可重复获取的增益与减益一律续时、不叠层)**;逐行读 `status_effects.tres` |
| 并存 | 新建一份独立实例,两份各算各的 | 同上 |
并存分支没有满层上限,但状态池规模天然有界:实例数的上界就是受理过的授予数——多受理一份就多一份实例,多少份在授予那一刻就完全确定,不会无限膨胀。
@@ -110,7 +110,7 @@
### 剩余次数怎么倒数:按结算次数衰减
每个状态实例自带一个倒数计数——剩余结算次数(本文说的"衰减"就是它逐次递减、归零消失)。它不承诺"活几轮",而是数"经历过几次轮末结算":每轮结算先让状态起作用,随后计数减一,减到零状态即被移除。持续 1 的状态就是"一次性":在授予它的那轮结算里生效一次,轮末消失。现行累加行里主角增益两行持续 1、削弱与敌方增益技行持续 2——累加语义下重复拿一次就按本次授予时长多攒一段,同一轮拿几份攒几段;跨轮持续的状态,寿命由表行初始值表达,给几就活几次结算。
每个状态实例自带一个倒数计数——剩余结算次数(本文说的"衰减"就是它逐次递减、归零消失)。它不承诺"活几轮",而是数"经历过几次轮末结算":每轮结算先让状态起作用,随后计数减一,减到零状态即被移除。持续 1 的状态就是"一次性":在授予它的那轮结算里生效一次,轮末消失。MVP 时期六行内容均为一次性(削弱后改续时——见 git 提交史;2026-09-20 起主角增益两行也走续时、duration 表值仍为 1——重复拿等于重新获得一次当轮增益);跨轮持续的状态,寿命由表行初始值表达,给几就活几次结算。
```
一轮结算:查询生效清单 → 逐行兑付(层数 × 行值)→ 轮末衰减(全部实例剩余次数 −1)→ 归零实例移除
@@ -140,8 +140,8 @@
| 例子 | 状态池输出 | 消费侧读法 |
|---|---|---|
| 暴走叠两层 | +(2 × enrage 行幅度)(读表;越出单行取值域,原样输出) | 压在天花板 +100% 上:敌方输出乘区封顶 ×2(削弱非叠层行——"叠两层压地板 −100% 归零"的读法不成立) |
| 主角盾牌加护再拿一份 | 层数恒 1、剩余结算次数累加本次授予的时长 | 不经任何池:掷点判定阈值 = 主角基准(读 hero 表)+ 层数(现行 +1——上限 2 层叠读取法退役,局内可达 AC 上限 11) |
| 暴走叠两层 | +(2 × enrage 行幅度)(读表;越出单行取值域,原样输出) | 压在天花板 +100% 上:敌方输出乘区封顶 ×2(削弱已改续时——"叠两层压地板 −100% 归零"的读法随 2026-09-18 结构修复批退役) |
| 主角盾牌加护再拿一份 | 层数恒 1、剩余结算次数重置(refresh——2026-09-20 主角增益续时批) | 不经任何池:掷点判定阈值 = 主角基准(读 hero 表)+ 层数(现行 +1——上限 2 层叠读取法退役,局内可达 AC 上限 11) |
状态池还有一条快照纪律:实例的幅度、初始次数、量纲在授予那一刻从表行拷贝。战斗中配置表即使被重载,已授予实例不受任何影响,只影响后续授予。
@@ -162,15 +162,15 @@
| 状态 | 效果一句话 | 发给谁 | 幅度(现行值) | 时限 / 合并 | 来源类别 |
|---|---|---|---|---|---|
| attack_up 增伤 | 主角攻击提升 | 主角 | 见 `data/tables/status_effects.tres` attack_up 行 | 时限/上限读表 / 累加(层数恒 1) | 安全格 |
| ac_up 盾牌加护 | 主角护甲等级提升(掷点折扣判定阈值——AC 轴,不入池) | 主角 | 见 `status_effects.tres` ac_up 行(2026-09-16 换装,原 defense_up 行已退役) | 时限/上限读表 / 累加(层数恒 1) | 安全格 |
| 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) | 安全格 |
| alert 警觉 | 敌方护甲等级 +1/层 | 敌方 | 见 `status_effects.tres` alert 行 | 1 结算 / 叠加读表 | 踩雷 / 标空封印(blast 型负向) |
| weaken 削弱 | 敌方攻击被削弱(同名重复标中只加时长、层数恒 1) | 敌方 | 见 `status_effects.tres` weaken 行(取值域 [60,85],取负生效) | 时限读表 / 累加 | 封印标中 |
| weaken 削弱 | 敌方攻击被削弱(同名重复标中只刷新剩余次数、层数恒 1) | 敌方 | 见 `status_effects.tres` weaken 行(取值域 [60,85],取负生效) | 时限读表 / 刷新(2026-09-18 续时定案) | 封印标中 |
| 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 | 累加、并存两类合并策略的后续内容行 | 语义已定义、状态池已承载;累加类已有内容(weaken/empower/fortify/attack_up/ac_up),并存仍空,首个并存内容行上线时顺带补验收 |
| P1 | 刷新、并存两类合并策略的后续内容行 | 语义已定义、状态池已承载;刷新类已有内容(empower/fortify 2026-09-16 敌人技能池批、weaken 2026-09-18 续时定案),并存仍空,首个并存内容行上线时顺带补验收 |
| 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(duration 2)+ empower/fortify(表值 2 = 先兑付后衰减含施放当轮的 1 个有效增益拍)+ attack_up / ac_up(duration 1);累加语义下重复拿一次就按本次授予时长加一段;拉长表值 = 每次授予攒更多段、规划变简单 |
| 叠层上限 | 整数 [1,16] | max_stack | 仅叠加策略消费;累加行层数恒 1、表值上限不消费,empower/fortify ×1(冷却闸下不可能自叠加) |
| 初始剩余次数 | 整数 [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(冷却闸下不可能自叠加) |
非调参的冻结项:三类合并策略语义、两种量纲语义、来源类别枚举、"先兑付后衰减"时序、拒绝原子性、零随机——改动走本文修订流程,不走调参。
联动纪律:增伤与削弱是当量锚的两端;盾牌加护与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)的承伤预期联动(掷点折扣轴——AC 行值变更须复算生存链区间;ac_up 层数恒 1、局内可达 AC 上限 11,复算随调参批);削弱与主角增益行同名重复授予只加时长、层数恒 1,"单轮层数上限受[行动经济](../排雷循环/行动经济.md)行动点约束"的联动不成立。这些联动值禁止独立调参,修订须重跑锚对照并同步登记册。
联动纪律:增伤与削弱是当量锚的两端;盾牌加护与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)的承伤预期联动(掷点折扣轴——AC 行值变更须复算生存链区间;2026-09-20 主角增益续时批后 ac_up 层数恒 1、局内可达 AC 上限 11,复算随调参批);削弱改续时后"单轮层数上限受[行动经济](../排雷循环/行动经济.md)行动点约束"的联动随之失效(2026-09-18 续时定案——同名重复标中只刷新剩余次数、层数恒 1;2026-09-20 起主角侧 attack_up / ac_up 同口径)。这些联动值禁止独立调参,修订须重跑锚对照并同步登记册。
## 验收标准
@@ -243,7 +243,7 @@ empower 与 fortify 是敌方技能池增益技在状态池侧的数据落点(
- 多向同构:主角侧增益与减益、敌方侧增强与削弱共用同一套受理、合并、倒数、清除语义,不存在第二套计时逻辑。
- 授予即生效:状态发入当轮结算即兑付第一次,无"待生效"中间态。
- 只登记不去重:同一事实被转化两次授予,登记两层——去重责任在战斗结算。
- 叠层不减钟:叠加策略行叠加只加层数,剩余次数保持首次授予定下的轨迹不变(累加策略行则相反——层数不变、剩余次数加上本次授予的时长;两策略逐行读表)。
- 叠层不减钟:叠加策略行叠加只加层数,剩余次数保持首次授予定下的轨迹不变(刷新策略行则相反——层数不变、只重置剩余次数;两策略逐行读表)。
- 满层拒绝原子且留痕:叠满后再授予返回失败、状态池逐字不变;结算明细多一行"奖励未生效"(含来源)。
- 先兑付后衰减:每轮结算恰做一次衰减,归零实例当轮移除;停手轮、弃图刷新轮照常衰减。
- 合成不设上下限:状态池输出的有效值恒等于层数 × 行值,越出百分比域不封顶不保底;地板在战斗结算侧。
+13 -14
View File
@@ -1,7 +1,7 @@
# 战斗结算
> 一句话:轮末结算的编排与逐行兑现
> 状态:已定稿(自旧体系迁移);现行为 v1.4
> 状态:已定稿(自旧体系迁移);现行为 v1.3
## 设计目的
@@ -84,7 +84,7 @@
| 判定行 | 胜 / 负 / 继续各一行;终局判定行同时是胜负画面的数据锚 |
| 高光行 | 完美封印成立时一行,只记实际有效兑付 |
每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。奖励直伤行的数值字段沿用 `effectiveness` 键名、值为整数点数——键名与量纲是数据导出与分析工具的兼容契约,改动须连动分析工具面。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。
每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。
任何一行找不到来源即断言失败——宁可返回错误,也不让"合并到看不出来源"的呈现混过数据层。但有些行天然没有棋盘来源,断言为此留了两层豁免,豁免集合是封闭清单,改动同样走本文修订。
@@ -268,21 +268,21 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
### 换图系专长:刷新事实与本轮兑付(设计定稿,待实现)
持有换图系后续专长时,成功刷新除执行上述换图编排外,还产生一次 `board_refreshed` 事实。事实只在新板装板成功后登记;刷新被拒绝时不产生事实,任何后续效果都不触发。同一轮多次成功刷新按发生顺序逐次登记,不合并成一次。
持有换图系后续专长时,成功刷新除执行上述换图编排外,还产生一次 `board_refreshed` 事实。旧图退役前保存它的探索进度与清图奖励对象身份;新板就位后登记事实。刷新被拒绝时不产生事实,任何后续效果都不触发。同一轮多次成功刷新按发生顺序逐次登记,不合并成一次。
刷新只登记事实,不当场插入结算。各效果在既有五段与对应消费点兑付:
刷新只登记事实,不当场插入结算。各效果在既有五段内兑付:
| 专长 | 兑付规则 |
|---|---|
| 崩壁冲击 | 每次刷新事实开一张全体敌人伤害单据,在本轮战斗段末经伤害控制器统一结账;目标按结账时的存活状态解析 |
| 蓄力周转 | 每次刷新事实累计一层,最多 3 层;本轮下一次主角攻击消费全部层数对应的攻击加成,随后清零;战斗结束不跨战保留 |
| 石层缓冲 | 每次刷新事实把当轮全局减伤状态置为生效;本轮主角每次受到伤害都固定减少 2 点,同一轮多次刷新不继续叠加 |
| 坑道小憩 | 每次刷新事实累计 1 点恢复量,最多 3 点;本轮授予段合计回复生命,封顶生命上限,随后清零;满血时记未生效行 |
| 矿道红利 | 每次刷新事实固定获得 1 GP,走战斗内 GP 缓冲并在授予段留痕;不按旧图探索进度折算,也不与清图奖励绑定 |
| 弃图轰击 | 每次刷新事实开一张全体敌人伤害单据,在本轮战斗段末经伤害控制器统一结账;目标按结账时的存活状态解析 |
| 换图蓄势 | 每次刷新事实当场累计一层,受表值上限约束;下一次主角攻击附加全部层数对应的伤害,随后清零;战斗结束清空 |
| 换图庇护 | 每次刷新事实在本轮授予段经既有护盾通道授予一次,不新开挖掘期状态入口 |
| 弃图休整 | 每次刷新事实在本轮授予段回复生命,按既有治疗规则封顶生命上限;满血时记未生效行 |
| 弃图回收 | 每次刷新事实在本轮授予段按旧图探索进度回收其清图奖励对象;进度与奖励口径归[地图战斗资源](地图战斗资源.md) |
全局受伤事件统一:`damage_taken` 是主角受到伤害的唯一效果事件,覆盖敌方攻击、危险格、错误封印资源格与地形造成的主角伤害。石层缓冲订阅该事件并在现行伤害下限之前消费;旧有订阅同一事件的专长也按这一完整语义生效。临时生命值不在此机制内。
弃图轰击若击杀最后敌人,仍由本轮判定段按既有顺序判胜,不新增挖掘期即时胜利出口。换图系效果使用扩展行留痕:来源写明专长与被弃旧图,弃图轰击走伤害单据,护盾、回血与回收各保留自己的兑付记录;它们不指向单一棋盘格,使用明细流水的专长刷新效果来源豁免,不伪造来源格。
崩壁冲击若击杀最后敌人,仍由本轮判定段按既有顺序判胜,不新增挖掘期即时胜利出口。换图系效果使用扩展行留痕:崩壁冲击走伤害单据,石层缓冲在受伤消费行体现减免,坑道小憩与矿道红利分别走治疗与 GP 入账记录。刷新事实来源不指向单一棋盘格,使用明细流水的专长刷新效果来源豁免,不伪造来源格。
弃图回收不是清图:不触发完美封印加倍,不发清图事件,不改变「刷新图不发清图奖励」。它兑的是被放弃旧图按探索进度回收的一部分奖励。
战斗开始按固定序列开张:关上配置热重载的闸门、初始化状态池、掷骰定敌方实际数量、生成敌人、装板并预分配资源恰一次、变异布置([地形变异](../排雷循环/地形变异.md)——棋盘设置顺序第 4 步:生成棋盘 → 打开状态初始化 → 战斗资源格设置 → 变异格设置,消费 `variant_place` 封闭流)、发开轮通知并执行开轮摇号(摇定首轮各敌本拍动作)。上一关的大奖励(如血上限提升)经战斗开始入参的覆盖值通道生效,内容归[冒险结构](../冒险循环/冒险结构.md)。
@@ -379,9 +379,8 @@ 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 配 ×1.5 的突刺落到 2 而不是 1)。
普通攻击也是一行技能行,两条域校验锁死它的特殊性:倍率恒 1、冷却恒 0——想配倍率或冷却的就不是普攻,是伤害技。技能伤害存倍率、不存固定值:伤害 = 施放者攻击基线 × 技能倍率——同一行"重击",不同敌种按各自攻击基线缩放 = 基线 A × 技能倍率 M(行值读 enemy.tres / skills.tres),深层强化行自动缩放,这是共享技能表成立的前提;**固定的绝对值伤害不满足该前提**(不随基线缩放、跨关稀释——Brotato 教训),"固定值伤害"的合法形态是**必中附加分量 rider_mult**(×攻击基线的必中小倍率,2026-09-19 实装)。增益技带效果引用与持续回合,百分比天然按施放者同池生效,无缩放问题;妨害技同构,落点由状态行 target_side 路由到主角。
池构成纪律(加载校验,违规拒绝入表):**每池恰一行普通攻击**(普攻冷却恒 0 → 可摇集合恒非空,"空池不可能"由结构保证,最坏情况怪物平砍等待——那是玩家的反打窗口而非死拍);**每池增益类技能 ≤1**(非 RPG,怪物连出不同增益显得呆);**每池妨害类技能 ≤1**(2026-09-19 新效应词汇批同构纪律);**每池至少一行不带触发条件的特殊技**(普攻不算——保底特殊技集合恒非空的结构保证,2026-10-26 触发条件批);池条目 skill_id 悬空致命;权重 > 0、冷却 ≥ 0。
@@ -1,7 +1,7 @@
# 行动经济
> 一句话:每轮行动点怎么花、停手与刷新的代价
> 状态:已定稿(自旧体系迁移);现行为 v1.3
> 状态:已定稿(自旧体系迁移);现行为 v1.2
## 设计目的
@@ -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
View File
@@ -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
+9 -17
View File
@@ -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:
+28 -10
View File
@@ -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 -4
View File
@@ -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=首开资源类型〔地质学家〕;
+6
View File
@@ -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
+50 -24
View File
@@ -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:
+15
View File
@@ -11,3 +11,18 @@ rap_refresh_cost = 8
refresh_cap_per_round = 2
move_ap_cost = 0
chain_ap_cost = 0
; AP 压速批(2026-09-16 用户拍板):ap_per_round 8→6——无伤通关根因诊断(playtest_5678/1234 实录:
; 第 1 轮 8 AP 全封印 = 8 份正向兑付 + 16 魔法充能,减伤/削弱单轮堆满 → "被减伤归零"零承伤通关)
; 的主阀门:削每轮兑付吞吐(封印 rush 墙/归零轮覆盖率 ~50%→~35%)。单格兑付语义零改动(保留封印命中
; 正向兑付——危险格/安全格概率差异化设计的前提)。rap_refresh_cost 8→6 随动 = 保持 registry 登记
; "默认 = ap_per_round,满停一轮 = 恰好一刷基线节拍"耦合不变式;若有意解耦(刷新相对变贵推清图)
; 须单独立批。减伤幅度下调(-30 → 下调)为同根因配套项,待用户拍板数值后另行落表;
; 终局方案 = 减伤换装护甲等级 AC+1(随 AC 掷点定稿批 EV 中性换装)。
; 观察口径:AP 6 不够再降 4(墙覆盖率 ~19%,代价 = 12×12 板挖掘节奏拖长)。
;
; Package B 数值优化批·首版(2026-09-22——qa-data/实现计划书_PackageB.md §4.2):ap_per_round 6→8、
; rap_refresh_cost 6→8 随动(维持 registry 登记"刷新成本 = 每轮 AP,满停一轮恰一刷"不变式;schema
; 非硬约束,系设计不变式)。上批 8→6 所杀"首轮全封印→减伤削弱堆满→零承伤通关"退化,在 B1 敌人 HP
; 大幅抬升后单轮堆满已无法零承伤通关多轮整场,风险缓解;复测须盯 analyze.py 零承伤轮指标,明显回升
; 则按计划书 §6.5 AP 8→7 回调。dig/seal/move/chain cost 与 refresh_cap 未动(move/chain 结构冻结 0)。
+45
View File
@@ -408,3 +408,48 @@ rows = [{
"shave_ring_radius": 1,
"r0_max_cap": 59
}]
; 切片调参登记(SLICE-TUNED provisional,调参所有权仍归 C3):
; A1 GDD 参考行(d0.10/0.12)经"先布后删"环内移除后仅幸存 2-3 雷、R0/|S|约0.97、残余挖掘 2-4 格——
; 掘近退化板(A2 反例 B 机制的低密度放大)。实验数据(8 种子均值,smoke/experiment_density.gd):
; d0.25 → L1 幸存雷 11/残余 13/inf 0.925/att 2.9 · L2 雷 19/残余 21/inf 0.908/att 7.9(seed42 实测 inf 0.889→target 定 0.88 首过),零降级告警。
; target 收窄至 0.88/0.88(不低于 0.85 绝对锚)为密度上移的对价——B1 条款③⑤对账重跑义务随调参触发。
; 2026-09-11 关卡扩展批:L1 增 D1–D4 行(Boss=Dmax=4)。
; Boss 板以 12×12 区分(d0.28/t0.87 实测达不到推理率门槛——best≈0.81 降级告警,回退 0.25/0.88;
; 密度轴上调留给 C3 与求解器能力一起解)。
;
; 分支节点图批(2026-09-17——L2 幽暗地域板行铺满,全值 provisional 归 难度曲线与Boss):
; L2 战斗/Boss 节点 (2, 0/1/4/5/6/7/8) 七行精确铺满(跨表校验强制——ConfigDB ④ level_node_dangling);
; 奖励点 (2,2)/恢复点 (2,3) 不开战斗、无板行(跨表校验只查 battle/boss 节点)。
; 板面参数与 L1 高档同值(12×12 d0.25 t0.88)——密度/推理率轴差异化留给 难度曲线与Boss 调参批;
; board_type 词表 v1.0(2026-09-19 用户拍板):L1=dungeon 地牢基线 / L2=underdark 幽暗地域(玩家侧显示名「地图类型」);域校验在 board_gen_table.gd 词表常量。
;
; 第三关内容批(2026-09-20):板面 13×13 / Boss 14×14 兑现「Boss 板 = 本关最大板形」纪律;
; 密度维持 0.25(0.28 破推理率门槛有失败先例——切片调参登记 best≈0.81 降级告警,加难主杠杆 = 板面 + 地形);
; 词表第三值 deep_underdark(灰矮人矿道方向——v1.1 2026-09-20 L3 内容批,显示名归呈现侧);
; min_safe_count 按既有 ~0.42 格占比外推(13×13 → 70 / 14×14 → 82)。
; 降档登记:Boss max_gen_attempts 批内拟值 36 越 schema 域 [1,32](config_fatal 修行值纪律——不许放宽 schema),
; 按域上限取 32(批内降档梯子「Boss 回 13×13 时 attempts 32」同款值)。行值全 provisional 归 难度曲线与Boss。
;
; 商店房批连带(2026-09-21——level.tres 商店房批 Boss 重编号 8→9):新增 (2,9)/(3,9) 精确行
; (跨表校验强制——ConfigDB ④ level_node_dangling),行值照抄原 Boss (L,8) 行;
; 商店房 (L,8) 不开战斗、无板行(跨表校验只查 battle/boss 节点)。行值 provisional 归 难度曲线与Boss。
; 陈旧行清理(GP+商店房实施批收尾 2026-09-21):并行表代理曾把 Boss 板行照抄到 (2,8)/(3,8)——节点 8 现为
; 商店房、无板行需求,原 (2,8)/(3,8) 行成陈旧冗余已删(删前核 (·,9) 行在位且内容与被删行逐字段一致);
; 本行集迁移 = Boss 重编号 8→9 的商店房批连带。
;
; Package B 迭代·第 6 轮·d3 改板试点(2026-09-22——用户提出并授权,破 §4.4 板面冻结的单行试点):
; (1,3) 第一关·节点3·熊地精双雄 板 12×12→10×10(min_safe_count 60→50、max_gen_attempts 24→16,
; 对齐 (1,0)/(1,1) 的 10×10 行)。依据:第 5 轮读数 d3 完成度 84% 中 83.2pp 系 R₀ 免费展开、实挖仅
; ~18 格/3.7 轮——总血 28-42 撑不起 121 格精英板;缩板后同战斗量读数 (68.6+18)/87≈100% 回带,
; 清图率升(打完近全翻开,清图尖峰 24-40 伤可兑现),轮数/承伤/胜率预计不动(难度刀≠设计意图修复)。
; 连带义务:board_calibration.csv 全量重跑 calibrate_boards(§4.4 预告)。provisional 未提交。
;
; 板尺寸策略改判批(2026-09-24——用户拍板「小怪板统一 10×10」原则,取代第 6 轮「板随战斗时长」原则):
; 第 6 轮单行缩板在 L1 内造出 10→10→12→10→12 锯齿——弱怪长战配大板、强怪速战配小板,节奏倒挂
; (用户实测定罪:第三场单只熊地精 50 血占 12×12、第四场三只强怪占 10×10)。本批 L1 小怪场统一 10×10:
; d2 12×12→10×10(min_safe_count 60→50、max_gen_attempts 24→16,对齐本关其余小怪行);
; **boss d4 维持 12×12 不动**(首次实施时误将 boss 板一并缩小,用户纠正后回滚——boss 场更大=
; 战斗逐渐变难的视觉收束,板序列 10/10/10/10/12 单调递增)。
; 战斗轮数由怪血量与玩家输出决定、与板大小无关=难度中性;完成度分母/清图率变化连带 board_calibration
; 全量重跑。L2 全 12×12 / L3 全 13×13(boss 14×14 单调收尾)本原则下无需动。provisional 未提交。
+2
View File
@@ -5,3 +5,5 @@
[resource]
script = ExtResource("1")
rows = []
; C3 GDD Core Rule 1:全局修饰结构位——MVP 空表(零行为)。首个修饰行 = 精英节点上线(C1 联动)。
+172
View File
@@ -754,4 +754,176 @@ rows = [{
"armor_class": 12
}]
; 切片调参登记 v3(2026-09-12 试玩批次 1 触发——F7 流程;C3 GDD F5 对照):
; 试玩反馈 = 基线满血全冒险成功(模拟 80%/真人 100%)——难度严重不足,主杠杆 = atk 曲线上调(承伤侧):
; 4/4/6/4/7 → 7/5/9/6/9(约 +50%);HP 结构调整(D0 24→20 缩短战斗、Boss 130→150 用户拍板可上调)。
; D0 注:20 HP 会被首轮盲挖粉尘秒杀(12+9)——回 24(4 轮战斗/承伤 42%,有过程有痛感)。
; DND 命名(用户指令):goblin 地精(单拍杂鱼)→ bugbear 熊地精(三拍伏击环——DND 原型即伏击手)→
; ogre_chief 食人魔酋长(经典低阶 Boss)。enemy_id 同步更名(内部键,无外部引用)。
; L2 锚行同步 v3 语义(bugbear 30/7)。
; 遭遇随机化批(2026-09-12 用户拍板):D0 [1,2]/D1 [2,3] hp13/D3 [2,3] hp18——数量区间骰(encounter 流,B1 掷骰);
; D2/Boss 固定(新敌种首遇教学位不加骰——C3 GDD Core Rule 8)。期望总量 ≈304(+8%),F6 带内。
;
; 护甲类型批(2026-09-12 用户拍板:攻击类型 × 护甲类型克制;2026-09-15 命名统一批——原位置键/位置名作废):
; armor_type ∈ {light, ward, heavy} = 轻甲 / 魔法护甲 / 重甲(缺省 = light 向后兼容;原 {none, a, b});
; 克制矩阵本体在 settlement.tres.armor_effectiveness。
; 映射(教学梯度:轻甲→魔法护甲→重甲):goblin=light · bugbear=ward · ogre_chief=heavy(L2 bugbear 同 ward)——候选方案,
; 数值与映射均 provisional 待用户调参。
; 敌方攻击区间批(2026-09-14 用户拍板②第二步——"上限掺运气"敌方侧:atk 上阶/下阶,中点恒等行值;
; roll 时机 = 遭遇骰同流〔encounter〕spawn 期整战持久,每拍抖动否决〔数字可读性锚〕;B2 零随机纪律保持
; ——收 override 即确定值。宽度 ±3 provisional 归 C3 测量迭代;验收 = 完美策略档 0 加成关卡完成 ≤40%。
; 护甲等级掷点批(2026-09-16 用户拍板):armor_class 字段入列(缺省 0 向后兼容)——防守方掷点判定阈值基数,
; 与 armor_type(克制属性轴)两概念严格分离、不做映射。首关六行暂定 0(正式行值归怪物/敌人系统设定批——
; 登记待办:第一关怪物 AC 相对较低,值待怪物设定投值;投值所有权归 难度曲线与Boss)。
; 敌人技能池批(2026-09-16 用户拍板——设计权威 docs/proposal-skill-pool.md v1.0):
; pattern 行为环数组 + heavy_multiplier 整体退役,改池模板 pool = [{skill_id, weight}](技能行本体在 skills.tres;
; 实例池快照与冷却状态在 单位容器 spawn)。建议池(全部 provisional,投值归 难度曲线与Boss;EV 锚 = proposal §2.5):
; 地精 普攻 9/突刺 1(名义 EV 1.05;**整数基线 EV 1.10**——atk1 突刺落地 2:〔9×1+1×2〕÷10;2026-10-05 技能池执行批 D4 整数口径重登记);
; 熊地精 普攻 6/蓄力 2/重击 2(EV 1.00 中性);食人魔酋长 普攻 6/重击 2/硬化 2(EV 1.00 中性;
; 硬化 = Boss 池独占增益技——增益 ≤1 纪律下旧蓄力拍退役不进 Boss 池)。;
; 酋长 EV 重锚(2026-10-05 技能池执行批 T5——震地怒击半血解锁入池:前半场池 6/2/2/3,
; 后半场 6/2/2/2+震地怒击 2=每拍 4.33;含闸长期速率抽样实测 1.1948,smoke EV 抽样带重锚 [1.10, 1.30];
; 卓尔遏毒/石君王岩崩同批入池——读数判读归 T7 节奏重测〔后置挂 07,跑批待用户批准〕)
; 含闸长期速率(冷却/保底)EV 锚按实施批 EV 抽样复核登记(proposal §2.5)。
; 地精 EV 重锚(2026-10-28——触发条件批孤注守势入池(w1,血量 ≤35% 情境入池):池 9/1/1;
; EV 抽样模拟器取无情境口径(trigger 行不过滤、每拍可摇)实测 0.9148,smoke EV 抽样带重锚 [0.82, 1.02];
; 旧带 [1.00, 1.20] 系触发器前唯一特殊技=突刺的池结构下登记,随池构成换代作废)。
;
; 分支节点图批(2026-09-17——L2 幽暗地域内容批,行值全部 provisional,投值归 难度曲线与Boss):
; 每战斗/Boss 节点 (2, node_depth) 精确行(跨表校验强制,违例加载致命——ConfigDB ④);锚行 (2,0) 保留。
; L2 熊地精 = 熊地精 bugbear 复用(幽暗地域部族设定——第二关三行):
; 池差异化改造 = 蓄力拍退役换突刺(复用共享技能行 lunge——共享技能表验证面),display_name 沿用
; 熊地精系译名(熊地精/熊地精猎群/熊地精重击手——行值与池与 L1 错开)。节点 5 重击手轮廓:普攻 5/突刺 2/重击 2(名义 EV 1.333;atk1 整数口径 1.333、atk3 每拍 ≈4.11——2026-10-05 整数口径重登记;权重期望
——冷却闸实际拉低,抽样复核归实施批口径)。
; 巨蜘蛛 giant_spider(新敌种——关间台阶纪律的"新敌种"半边):群行倾向(数量区间 [2,3],首遇位节点 4
; 固定 2 不加骰——新敌种首遇教学位纪律同 L1 D2);池 = 普攻 6/撕咬 2/蓄力 1(增益 ≤1 纪律——charge 复用
; empower;EV 名义 1.00——批注旧值 1.11 = **atk1 整数口径**〔6+2×2〕÷9=1.111,非混用(2026-10-05 T2 消歧登记);护甲 light(与 L2 熊地精 ward 错开克制面;L1 三甲 goblin=light/
; bugbear=ward/ogre_chief=heavy 全覆盖,蜘蛛取 light 与同关敌种错开)。
; 蛛化卓尔精灵 drider(Boss——用户 2026-09-17 拍板定名,蜘蛛主题呼应):
; 专属池 = 普攻 6/重击 2/毒爆 2(独占技 venom_burst 权重轮廓;EV ≈1.67 权重期望,冷却闸拉低后待抽样),
; armor heavy,血量 175 = r_boss 口径 provisional 锚(定位本关最大单场消耗)。
; L2 敌种首遇位绿档(节点 0 熊地精/节点 4 巨蜘蛛):任何掷骰结果稳过——完美策略档扫描验证,读数另批登记。
;
; 数值压缩批(2026-09-17 用户拍板暂定——整体绝对值轴 ÷3,四舍五入):
; 全部 12 行 hp/atk/atk_min/atk_max ÷3(24/7→8/2 · 13/5→4/2 · 40/9→13/3 · 18/6→6/2 · Boss 150/9→50/3 ·
; 30/7→10/2 · 15/5→5/2 · 14/5→5/2 · 38/8→13/3 · 12/4→4/1 · 13/5→4/2 · drider 175/8→58/3)。
; armor_type / armor_class / unit_count 区间 / 技能池权重不动(相对轴与概率轴不压缩)。
; 粒度告警登记:atk 1~3 域下掷点折扣 25% 档大量触 damage_floor=1,地板伤害相对权重上升——
; 属压缩的已知效应,难度复测(monte carlo 压缩前后对比)随批产出。行值 provisional 归 难度曲线与Boss。
;
; 护甲类型重配批(2026-09-18 用户拍板):关卡 1 全部轻甲(食人魔酋长 heavy→light、熊地精两行 ward→light);
; 关卡 2 除 Boss(蛛化卓尔精灵 heavy→ward 魔法甲)外全部轻甲(熊地精四行 ward→light,巨蜘蛛既有 light 不动)。
; hero 侧两轴(armor_type/attack_type)同批入列(hero.tres 批注),敌方技能攻击类型轴仍未开(全部 normal 档)。
;
; 甲效矩阵加法核换装批(2026-09-18 用户拍板——settlement.tres armor_effectiveness 量纲 percent→整数点数,
; 三档 克制 +1 / 中性 0 / 被克 −1,五档百分比词表随批退役)。
;
; 新效应词汇批(2026-09-19 用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0):卓尔池
; 6/2/2 → 6/2/2/2(+蛛网束缚 web_snare 2——妨害技,对主角施 off_guard;每池妨害 ≤1 纪律入跨表校验)。
; 主分量权重期望 1.67 → 1.25(零伤害拍占 2/12),加毒爆必中附加分量(max(1,floor(atk×0.75)),atk 区间
; 2–4 → 1–3 点)后净期望待抽样复核归 难度曲线与Boss;实装面 = 仅卓尔,其余敌种不动。
; 现行读数效果:L1/L2 小怪全 light → 穿刺类(开格充能/穿刺弹)被克 −1(穿刺弹 2→1、充能 3 点→2)、普通/魔法中性;
; L2 仅 Boss 战非中性(魔法甲)——基础攻击与穿刺弹克制 +1、魔法矢被克 −1(原威力 + delta 自行核算后落笔)。
; 原重配批注「魔法矢克 Boss ×150、穿刺弹被克 ×50」与当批矩阵正反互倒(系笔误),随本批订正为上行读数。
;
; 第三关内容批(2026-09-20):新敌种 duergar 灰矮人(单体重甲中坚——关间台阶 ≈L2 单体 ×1.5,落 [1.3,1.6] 域)
; 与 hook_horror 钩爪恐魔(群行捕食者,复用 bite 共享技能行——lunge 已有 L2 熊地精复用先例);两敌种首遇位
; (节点 0 / 节点 1)固定数量不加骰——新敌种首遇教学位纪律同 L1 D2 / L2 节点 4;克制面重轻错开
; (重甲灰矮人 = 重甲首次登台,轻甲钩爪恐魔保穿刺/普通分量有用武之地),Boss duergar_king 灰矮人石君王
; 重甲收束「轻甲→魔法甲→重甲」教学梯度;Boss 血量 75 = Σ普通战生命期望 91 × r_boss≈0.82
; (provisional 锚,域 [0.5,1.1]);Boss 专属池独占技 earth_pulse(第二妨害词汇 sapped 首发);
; armor_class 恒 0(正式投值仍归「敌方护甲等级正式行值」在案条目全表同批)。行值全 provisional
; 归 难度曲线与Boss。
;
; 商店房批连带(2026-09-21——level.tres 商店房批 Boss 重编号 8→9):新增 (2,9)/(3,9) 精确行
; (跨表校验强制——ConfigDB ④ level_node_dangling),行值照抄原 Boss (L,8) 行(drider / duergar_king);
; 商店房 (L,8) 不开战斗、无行集。行值 provisional 归 难度曲线与Boss。
; 陈旧行清理(GP+商店房实施批收尾 2026-09-21):并行表代理曾把 Boss 行照抄到 (2,8)/(3,8)——节点 8 现为
; 商店房、无战斗行需求,原 (2,8)/(3,8) 行成陈旧冗余已删(删前核 (·,9) 行在位且内容与被删行逐字段一致);
; 本行集迁移 = Boss 重编号 8→9 的商店房批连带。
;
; Package B 数值优化批·首版(2026-09-22——qa-data/实现计划书_PackageB.md §4.1,worktree
; adventure-mc-playtest,provisional 未提交):B1 敌人 HP 阶梯整体重锚(完成度主旋钮——零加成基线
; naive 完成度普遍过低,见 qa-data/分析报告_零加成全流程.md)。只改 hp 字段;atk/atk_min/atk_max/
; 池/armor_type/armor_class/unit_count 全部不动(atk 系 §6 承伤迭代旋钮,改时须三值同步保中点恒等)。
; 改动清单:L1 d2 熊地精 13→50 · d3 双雄 6→20 · d4 酋长 50→72(d0/d1 弱档不动);
; L2 d0 10→45 · d1 5→18 · d4 巨蜘蛛 5→20 · d5 13→68 · d6 巢群 4→18 · d7 巢群 4→18 · d9 卓尔 58→85;
; L3 d0 灰矮人 15→50 · d1 钩爪 5→25 · d4 钩爪 5→20 · d5 16→76 · d6 巢群 6→20 · d7 小队 8→20 ·
; d9 石君王 75→105。以 MC 复测读数为准(runbook 计划书 §5;迭代记录 qa-data/iteration_log.md)。
;
; Package B 迭代·第 3 轮(2026-09-22——计划书 §6.2 承伤带守卫,用户拍板):8 行 atk-3 精英/boss
; 三值同步 3(2/4)→2(1/3)。第 2 轮 max_hp/heal 组合拳后单场承伤% 仍 49-62%(战斗变长吃掉血池收益,
; heal 加强主导经济修复)——§6.2「AP 已到顶 → 长战斗档 atk −1」条件成立。行清单:L1 d2 熊地精 /
; d4 酋长 · L2 d5 重击手 / d9 卓尔 · L3 d0 灰矮人 / d5 重装手 / d7 小队 / d9 石君王。
; atk-1/2 行(弱怪/群怪/L1 d3 双雄)不动。预期单场承伤 ~35%(20% 带在 Package B 框架内结构性
; 不可达,带位全达标归 Package A)。provisional 未提交。
;
; Package B 迭代·第 4 轮(2026-09-22——用户拍板 A):L1 d3 熊地精双雄 hp 20→16/单位
; (总量 [32,48])。第 3 轮后唯一未回调的 L1 高压行——双单位每轮双判定,单场承伤 51%、
; 胜率 70%,拖住 L1 通过率(40.7% vs 靶 70-78%)。其余行不动。provisional 未提交。
;
; Package B 迭代·第 5 轮(2026-09-22——用户拍板「继续」,修理刀三处,胜率带优先、完成度让路):
; ① 第一关·节点3·熊地精双雄 hp 16→14/单位(冲 ≥90 胜率靶;该行胜率/完成度两靶互斥已登记);
; ② 第二关·节点9·蛛化卓尔精灵 85→80(L2 boss 胜率 59% 回 60-75 带);
; ③ 第三关·节点9·灰矮人石君王 105→92(L3 boss 胜率 38% 向 50-70 带靠;该行完成度靶未设带,让路合法)。
; 否决项登记:食人魔酋长 +10% 方案经测算否决——boss 完成度 >130 需 HP +~50-75%(98→104 买不回靶),
; 会把刚入带的 66% 胜率打回带外,纯亏。provisional 未提交。
;
; 数值设计批·关卡成长×永久成长对齿(2026-09-22——设计权威 qa-data/数值设计_关卡成长×永久成长_v1.md,
; 用户三拍板 1A/2A/3A,第 7 轮):第二/三关阶段拔高 14 行(L1 一行不动)。血轴=每关上一档;
; 伤害轴=atk 2→3 三值同步 3(2/4)【L2 d5 重击手/d9 卓尔;L3 d0 灰矮人/d1 钩爪/d4 钩爪/d5 重装手/
; d6 巢群/d7 小队/d9 石君王】。清单:L2 d0 45→50 · d1 18→22 · d4 20→24 · d5 68→88+atk3 · d6 18→22 ·
; d7 18→22 · d9 80→112+atk3;L3 d0 50→62+atk3 · d1 25→30+atk3 · d4 20→26+atk3 · d5 76→98+atk3 ·
; d6 20→26+atk3 · d7 20→26+atk3 · d9 92→140+atk3。
; 目标对齿(熟练玩家):S0 零成长 L2 达 boss ~20%/通 ~0%、L3 ~0;S1(≈5 次 L1 关卡完成锻造后,hero 快照
; 攻4/血26/甲11)L2 达 ~70%/通 ~50%;S2(攻6/血32/甲12)L3 通 ~55%。验证 = hero.tres 阶段快照 MC
; (设计文档 §6,快照后恢复基线)。验证出带微调旋钮序:L2 d1/d6/d7 血 22→20 → d4 24→22 → d9 112→108。
; provisional 未提交。
;
; 实体名修正批(2026-09-24——用户裁决,DND 阶梯对齐):(1,3) 熊地精双雄 → 大地精
; (enemy_id bugbear→hobgoblin,仅本行;L2 bugbear 三行熊地精系不动)。依据:①DND 阶梯
; 地精(goblin)→大地精(hobgoblin)→熊地精(bugbear) 与实测每只血量 4-8→14→50 严格同构——
; 单只熊地精 50 血在前、三只 14 血在后,同族每只血量倒挂的观感由阶名归位化解;
; ②「双雄」名硬编码数量、数量却是 [2,3] 变量骰——摇出 3 只即成「三个双雄」自相矛盾
; (用户截图实证),集体名(猎群/巢群/小队/大地精)为正解。hp/atk/池/数量区间零改动。
; M-3 迭代 5 判读锁值批(2026-09-28):(2,9) 卓尔 hp 130→100(杠杆扫描 C3 组合——Boss 杠杆对普通档 +4pp;
; r_boss 锚漂移加重 100/389≈0.26 低于域 [0.5,1.1] 下限,收锚裁决挂迭代 5 出口人闸;读数见
; design/qa/m3-iter5-lever-scan-2026-09-28.md)。
; M-3 迭代 5 T4 AC 投值批·终版 Boss-only(2026-09-28:v1 硬梯度普通 L2 14.3% 越带/v2 软梯度 15.7% 仍越带——杂鱼税对普通画像〔普通分量为主力输出〕系统性超压;终版=杂鱼全 0〔带 0~5 下缘,掷点戏剧性集中 Boss 战〕+Boss 台阶 8/9/12 严格递增;三版演化链读数见 design/qa/m3-iter5-t4-ac-2026-09-28.md,随出口人闸追认)。
; M-3 迭代 5 返工批·U2 裁 v1 硬梯度重投(2026-09-29 用户推翻 Boss-only:重击手 8/重装手 9〔逐行手设值,非精英编码位——解读 A 追认,精英 P2 承载〕+Boss 台阶 8/10/12;杂鱼行按 T4 报告 §一 软梯度恢复〔v1 中间态未入 git,v1↔v2 唯一差异=重击手/重装手,代拟面记台账 247〕;卓尔 hp 100→130 随 C3 回退复原;组合读数 C1+v1 无先测,全量确认归返工批——裁断全录 design/qa/m3-iter5-u2-gate-2026-09-29.md)。
;
; 数值修复批·调参二(2026-10-01 新尺 MC 驱动):L1 系八行 atk 2→1(行 15/35/54/77/99/121/144/166;
; 行 234 巨蜘蛛巢群主体=L2 域维持)——新尺读数:普通档 v3.4 死因=L1 四连战无治疗夹缝(雷伤 6/8/8
; + 杂兵垫刀双压,L1 条件关卡完成率 1-2%,0/100 出第一关);完美档战役 50%(L1 93%)。刀位语义=
; 「危险来自雷,不来自杂兵」:杂兵垫刀减半,雷直伤 6/8/8 维持痛感;L2/L3(atk 3 系)本刀不动。
; 全旧带读数随新尺作废重测归本批。
; 调参二补充:上述八行 atk 区间 1-3→0-2(中点恒等期望当量锚不变式——atk=1 需区间中点同步 1;0=掷点空刀,保随机手感)。
;
; 混编遭遇首批投放批(2026-10-07 迭代 18 卡⑤——需求卡片 v1.2 裁点全裁 P1-P4 甲;机制前置=敌人表行集多行批
; 已提交 9cc4b8b):首个混编遭遇行落表 = (2,5) 双行行集〔R6 行序契约:同坐标两行文件内相邻、
; 行序=声明序=生成序——resolver 返回序/生成序/断言面全依赖文件行序〕:
; 行 1 = 既有 熊地精重击手 (2,5,bugbear)(行值零变更);
; 行 2 = 新增 (2,5,giant_spider) 巨蜘蛛巢群——行值整行复制 (2,6) 巢群行(P4 甲零数值新增:unit_count 2/
; unit_count_max 3/hp 26/atk 1/atk [1,2]/池 普攻6·撕咬2·蓄力1/light/armor_class 2),
; 行序=重击手在前(默认目标=前排坦克 ac 8,蜘蛛后排输出——强弱搭配形态)。
; 设计意图(P1 甲单点试水):「巨蜘蛛+熊地精」同场混编——生产内容实打卡①「每行一骰数量骰」交付面
; (重击手定值不骰、蜘蛛掷 [2,3],同场两种数量语义并存);静态最坏骰和 = 1+3 = 4 ≤ ENEMY_ROWSET_INSTANCE_MAX
; (spawn 期守卫内)。
; 读数预期:(2,5) 场敌人 3-4 只(3=重击手 1+蜘蛛 2,4=蜘蛛掷 3);L2 难度带位移读数随 Alpha 收官 M4 数值批
; 统一执行(07 在册义务——MC 取证跑批届时另报批,本批零跑)。禁区排查:巨蜘蛛首遇位 (2,4)「固定 2 不加骰」
; 零触碰、Boss d9 零触碰、跨关混编禁令过(两敌种首遇关均 ≤L2)、既有 19 行现值零变更。
; 敌人表内容修批 N1(2026-10-13 用户令「按推荐方式」,迭代 24 卡①):(1,2) 熊地精降档 hp 50>>22、armor_class 3>>2——
; 2026-09-24 阶名化解方案((1,3) 改名大地精以阶名归位化解同族血量倒挂观感)实机验证未达预期,按体验反馈重裁:
; 第一关总量曲线 12/10/50/35/72 的 5 倍墙消除(22 后曲线 12/10/22/35/72 相邻比最大 2.2);敌种 bugbear/池/数量/atk 区间零改动。
; 曲线标定其余行归 M4 数值批。
; N3 敌方攻击类型轴开列(2026-10-13 迭代 24 卡①,承接锻造工坊实装批迁移面⑥):20 行全填 normal 挂敌种行——
; 不做差异化(pierce/magic 属新设计另立项)。全局平移效应=主角穿重甲受伤 −1 / 魔法护甲 +1 / 轻甲 0,
; 锻造甲路线首次具备战斗意义;克制矩阵数值零触碰(settlement.tres armor_effectiveness 不改)。
;
; 行键 = (level_index, row_kind, depth_band, enemy_id);row_kind ∈ {battle, boss}——battle=战斗节点配池,boss=终点行集;
; depth_band=节点深度所在的带键,请求落带取首个 ≥ 深度的键(偏难一侧);越顶带由 resolver clamp、跨表校验判为调参事故。
; hobgoblin 行为缺口行:无立绘、不在敌种表——留任在役,补齐三件套(立绘+语义模板+敌种表行)归敌种内容批。
+221
View File
@@ -4,6 +4,17 @@
[resource]
script = ExtResource("1")
; 迭代 20 专长实装批 T3——专长重设计 27+2 件换代(奇物.md 基础件表 27 件+迁入登记 2 件=29 行;
; 件数口径=卡文 §10.4 推荐案:29 行=基础 27+迁入 2,V2/V3 断言按落表实数)。旧 27 件随本批整体
; 退役(素材库表二);订阅行 on/when/do 词表=效果引擎封闭集;rarity 四级直映射令牌档;cap=已拿
; 上限(案②解耦——拿了才计刷出不计);数值全 provisional 归调参批;desc 禁「雷/旗」字面
; (契约 6 命名纪律:旗〔旧称〕=封印、危险格=陷阱/巢穴风味层)。dispatch 预评估口径注记:「每第 N 次/积
; 满触发」系 when 于命中前读计数器现值——行 when 按 N-1 落值(双管镐 mod_eq ref 1/地质学家 eq 3/
; 跳格 eq 2/封印匠 mod_eq ref 2/保险丝 eq 1——effect_words_t1_test mod_eq 断言钉住该口径)。
; 迭代 31 卡② 凭证件裁削批 T5——完美保险自资源类迁入专长表(第 30 行):rarity rare/cap 省略
; (承 twin_pick/seal_burst 惯例)/domain=battle 显式写出(现役 29 行全为 adventure 或不写,本行
; 系战斗域首例——豁免计数每战清零)。限次落法=单订阅行:when counter(insurance_used) lt 1 承载
; 「本场首次」,do 自带 counter_id 记账由授予段消费点落账(dispatch 不代执行计数器)。
rows = [
{
"feat_id": "twin_pick",
@@ -858,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
}
}
]
}
]
+11
View File
@@ -85,3 +85,14 @@ routes = [{
"prereq_route": "light",
"unlock_price": 200
}]
; 锻造工坊实装批 T1(2026-10-12——迭代 23;设计权威 design/gdd/systems/跨局循环/锻造工坊.md v0.6,
; 需求卡片=锻造工坊实装批(迭代 23,卡片已按「吸收即死」退役,git 历史可考)T1 锚表):
; 六路线 provisional 投值——cap 5/每级增量统一 +1(v1.2 用户裁:provisional 线性起步,4a 前缓后陡为
; 终值形状方向归 M4)/甲型基础 AC 10-12-9(现役结构值 settlement.tres 矩阵同行)/基础价 20/公比 150%
; (历史考古参数 meta.tres:82-84 退役批注)/各级价格 20/30/45/67/101/一次性解锁价 200(中段三级 213 九折)。
; 初始持有=长剑+轻甲(语义继承自已退役属性锻造行——迭代 21 T5 行族删除后的新建行族,非改造)。
; 并联双通道(4b-1 裁):长枪/法杖←长剑练满、重甲/魔法护甲←轻甲练满,或一次性解锁价直购,互不影响。
; 默认两轴(契约 2 所有权移交):hero.tres 静态表两轴随本批删除,默认值归本表常驻持有——normal/light
; = 裸体态类型(Q1:未解锁/未锻造=0 加值)。全部数值 provisional 终值归 M4 数值批。
; 表运行期只读(铁律):永久强化只写存档 forge_routes 域,本表零写面。
+28
View File
@@ -8,3 +8,31 @@ max_hp = 26
atk = 2
armor_class = 10
display_name = "探险者"
; 〔2026-10-12 迭代 23 锻造工坊实装批 T2——两根类型轴删除(契约 2 所有权移交):armor_type/
; attack_type 两字段随本批从静态表删除,默认值归锻造工坊配置常驻持有(forge.tres
; default_attack_type=normal/default_armor_type=light),选中态写存档域 forge_routes、冒险开始
; 经参数面注入;单位快照读取面改读注入值(缺省回退锻造配置默认值——行为连续)。原 2026-09-18
; 营地扩展前置批「两根可配置轴」登记随字段删除退役,历史记载归 git 考古。〕
; 数值压缩批(2026-09-17 用户拍板暂定——整体绝对值轴 ÷3):
; max_hp 50→17(16.67 四舍五入)、atk 6→2。armor_class 10 不动(掷点阈值轴,相对量纲不压缩——
; 用户同日裁决:本体自带 AC 不算减伤统计)。恢复奖励削弱随批在 reward.tres(概率 1/4 + 量再减半)。
; 全部行值 provisional 归 难度曲线与Boss;压缩前基线读数(N=30 normal):基线档通关率 3%。
; 护甲等级掷点批(2026-09-16 用户拍板):armor_class = 10(暂定基准,归 难度曲线与Boss;
; EV 参考数按判定式复算 = 期望减免 21.25%);ac_up 增益 +1 AC/层(×2 层 = AC+2)在其上加算。
;
; 〔营地扩展前置批(2026-09-18 用户指令)两根可配置轴 armor_type/attack_type 已于 2026-10-12
; 迭代 23 锻造工坊实装批 T2 删除——所有权移交锻造工坊配置(见顶部注记);甲型基础 AC 随甲路线
; 行承载(轻 10/重 12/魔法护甲 9),本表 armor_class=10 保留为甲路线缺失时的兜底基准。〕
;
; Package B 迭代·第 2 轮(2026-09-22——计划书 §6.2,用户拍板一B):max_hp 17→20。第 1 轮读数
; 触发 §6.2(L1 精英承伤 43-55% vs 靶 ≤20%、L1 净消耗 17.7/17=104% 破产、normal L1 通过率
; 8.3% vs 靶 70-78%)的生存侧修复。单变量归因原则:同轮第二变量(heal_minor 加强)在 reward.tres。
; 血线 17/27/37→20/30/40(关间大奖励 +10 不变)。provisional 未提交。
; 数值修复批(2026-10-01——模拟档位重构后新尺首调):max_hp 20→26(调参二再 +2:普通档 L1 7% 差 2-4 血量级,+8% 池把 b3/b4 压线死改写险胜;完美档 62% 上界余量健康)。依据=新尺 MC 读数:普通档 v3.4
; (完美+失误注入,踩雷 ~2.5/战)L1 四连战无治疗夹缝全灭(L1 条件通关 2%,0/100 出第一关);
; 完美档战役 36-41%(L2 53% 弱环)。+20% 血池抬夹缝生存;配套直伤雷当量同步上调(reward.tres
; 4/5/5→6/8/8,雷痛回归用户口径)双向对冲。全旧带读数随新尺作废重测归本批。
+4
View File
@@ -10,3 +10,7 @@ rows = [
{"level_index": 2, "display_name": "第二层 · 幽暗地域", "rest_heal_pct": 30},
{"level_index": 3, "display_name": "第三层 · 灰矮人矿城", "rest_heal_pct": 30}
]
; 节点图源已换代为参数化生成器(关卡节点图生成 v1.1)——本表逐关行只承载关卡序号/显示名/恢复比例,
; 不再携带节点数据;图 = f(参数档, 种子),参数档见 level_gen_params.tres 三行(消费侧按 level_index 解析后交 generate)。
; 旧 15 张模板池(3 关 × 5)已清出,历史查 git 提交史与 tools/t5_build_templates.py、t17_fanout2_rebuild.py 留档。
+3
View File
@@ -44,3 +44,6 @@ rows = [{
"fork_ways_min": 2,
"fork_ways_max": 3
}]
; 节点图生成器核心批 卡① §8.1 参数档 provisional 取值表逐行填列(定值批落终值,数值全 provisional)。
; 层深/出口/岔口去路数为已锁域;商店实数由摆放约束钉死=出口数(shop_ratio 为名义值,配比填余次序见卡① §8.1 注)。
+40
View File
@@ -36,3 +36,43 @@ attune_refresh_upgrade = [{
"refresh_charges": 2,
"keystone_cost": 60
}]
; 元进度实现批(2026-09-21,设计权威 design/gdd/systems/冒险循环/元进度.md 定稿 v1.2):
; 数值全 provisional 归元进度设计批配读数(骨架先行——元进度实现批 2026-09-21,先例 = GP+商店房批)。
; 〔forge_products 属性锻造行族已退役——迭代 21 T5 攻防所有权切分:生命唯一入口=树脊柱淬炼、
; 攻/AC 唯一入口=锻造工坊路线(契约 9 红线),meta_forge_row 访问器与 buy_forge 购买面随批删除;
; 历史投值记载(2026-09-22 对齿批 base 20/ratio 150、2026-09-23 标定批 6/9/1)系 conversion 行
; 与 ForgeGDD 考古用,行族本体不再在表。〕
; 〔workshop_items 道具工坊行族已退役——迭代 22 T2 秘宝实装批:解锁换代混合制(钥石购买价
; unlock_keystone_cost + 条件谓词 unlock_requires 全挂 treasure_items.tres 行内单一事实源),
; 旧「总通关次数达阈值」六行(阈值 1/1/2/2/3/3)与渠道面随批删除;历史记载归 git 考古。〕
; boss 两档 L1 5/1 · L2 8/2 · L3 12/3
; (首杀全量、重复杀固定小额恒定不递减);conversion 全 0 = 未标定占位(标定归设计批,护甲行强条目:验收读数必须按
; 解锁后参数重测)。
;
; 数值设计批·关卡成长×永久成长对齿(2026-09-22——设计权威 qa-data/数值设计_关卡成长×永久成长_v1.md,
; game-balancer 工作流,用户三拍板 1A/2A/3A):forge base_price 10→20(三行同,ratio 150% 不变,
; 效果档 血+3/攻+1/甲+1 不变)——S1 一档(攻+2/血+6/甲+1 ≈ 120 GP)对齐「≈5 次 L1 关卡完成开门」节奏
; (实测 L1 通关局收入 ≈29-35 GP)。换算率表维持全 0(墙/钥匙闭环不依赖该轴,留扩展)。
; 配套怪表改动见 enemy.tres 同日批注。provisional 未提交。
;
; 换算率标定批(2026-09-23——用户指令「现在标定」;读数报告 production/qa/conversion-calibration/
; calibration.raw.md,判定端 tools/balance_verifier.py ④ 段可复判):conversion 三行全 0 → 6/9/1 投值。
; 方法 = OFAT 冒险注入档(每属性 +1/+2 级 × 双画像 × na=100,与白板同种子流配对)逐关条件
; 通关率差实测每级带平移 生命 +6.0±0.7 / 攻击 +8.8±0.8 / 护甲 +1.2±0.4 点(配对 bootstrap SE,
; 逆方差加权合并)→ 取整投 6/9/1。测量面 = 冒险条件口径(同日单关直入口口径退役后重测——
; 首轮直入口面读数作废)+ 当日 L2 收紧/关间大奖励 10→5 后的现行数值包。
; 护甲行强条目重测义务随批履行:重测暴露并修复护甲断链(begin_battle hero_armor_class 参数此前
; 零消费——_defender_ac 主角分支本次接线,缺参/-1 = 表值兜底);修复后甲轴读数 +1.2±0.4 为
; 解锁后参数实测,非基线外推。战役轨迹三花费序(生命/攻击/护甲优先)随批采集验证。
;
; 迭代 10 奖励重构批(2026-10-01——boss_keystone 重锚,P-B 乙拍板):首杀 3 三关统一;
; 复杀按关 2/2/3 递进(**用户 2026-10-01 裁「a 用备选」**——原代拍板「复杀统一 2」被推翻;
; L3 首杀=复杀=3 系 first_kill ≥ repeat_kill 结构约束下的合法端点)。
; 钥石渠道自本批起 =
; Boss/精英击杀逐杀掉落(大奖励 keystone_per_level 渠道退役;精英掉 1 预留行随怪物批实装落)。
; 产出结构变化 → 元进度标定义务重开(06-待办清单 2026-10-01 登记条)。provisional 归曲线调参批。
;
; 迭代 11 第①批 同调实施批 T4(2026-10-03):attune_refresh_upgrade 行族 = Y 刷新升级行(需求卡片 P1 甲——
; 每冒险开局给 Y 次、冒险周期池、用完即无;等级 L → Y=L 次刷新,钥石直购)。数值全 provisional 归
; 难度曲线与Boss(需求卡片 §三 7)。
+13
View File
@@ -155,3 +155,16 @@ rows = [{
"economy_spend": 1
}
}]
; 迭代 21 天赋树实装批 T1 换代(2026-10-12,设计权威 design/gdd/systems/跨局循环/天赋树.md v0.8):
; 12 节点 = 脊柱 2(生命淬炼/命中淬炼——一线一节点 cap4,2026-10-11 用户裁,原 4 层×4 线 16 行收编;
; 攻/护淬炼线随攻防所有权切分砍除——攻唯一入口=锻造工坊武器路线、AC 唯一入口=甲路线〔契约 9 红线〕)
; + 锻造脉 2(forge_workshop 钥匙 free 无前置 + easter_ley 彩蛋——effects 只持生命/命中两键,
; :402/:405 旧攻/护分量已摘除)+ 钥石脉 2(秘宝匣 ks_workshop〔display 旧名「道具工坊」退役〕/
; 刷新升级 ks_refresh)+ 同调脉 6(同调位 1/2/3——socket1 改根节点无前置 + Fork 3 单行双态节点,
; 原 8 行 A/B 双行结构与 fg_mastery 克制专精组退役)。
; 行门槛=一线一节点主语:脊柱节点第 N 级需全树总等级 ≥4×(N−1)(SPINE_ROW_GATE=4 公式平移,
; row 字段退役);requires=点亮前置(R1 裁撤案执行,schema 无等级阈值形态)。
; 🔴 层级纪律:局外树只放全局规则件——零 archetype 键(schema 校验强制);规则改写型特性只走局内随机渠道。
; 数值全 provisional 归 M4 数值批(契约 7——价格沿旧量纲锚:脊柱 10=旧 r1 价、socket 20/40/60、
; Fork 25、刷新 30 沿旧;生命 +5/级、命中 +1/级沿旧量纲);A/B 两侧差 <~3pp 验收=V19 MC。
+59
View File
@@ -201,3 +201,62 @@ rows = [{
"pool_tag": "cell",
"tier": 1
}]
; 格面资源批(2026-09-15 用户拍板——registry reward_table 条目为现行 schema 事实源):
; 十行格面池(五型 × 正负各一行)+ 清图槽一行。安全格与危险格同池同分布(雷安同池),
; 装板期一次摇定;摇号只消费正向行权重(类型频次 = attack 20 / defense 16 / blast 16 / heal 3 / weaken 12,合计 67;
; 头段"heal 15 / weaken 12,合计 79"为历史注记——数值压缩批后 heal 3、合计 67,见本文件尾部 2026-09-17 批注);
; 负向行 weight=0 不参与摇号,纯(类型, 极性)兑付字典——heal 负向 = 主角直伤 4(不经增益状态),
; blast 负向 = 警觉(敌方 AC +1,2026-09-20 伏击退役换装)。
; 可选类三行(knife_t1/knife_adv/heal_pack)与注入池 active_inject 随可选类道具整体删除(供给控制器/保底/窗口同步下线)。
; 格面资源八型批(2026-09-20 用户拍板):① blast 负向 ambush_double 退役 → enemy_alert(警觉,effect_id=alert
; 敌方 AC +1 percent 行);② 新增第 8 型 action 两行——ap_up(正向,下轮行动点 +1)/ ap_drain(负向,下轮
; 行动点 −1),排队兑现于下一轮开始(action_economy.queue_ap_delta);③ off_guard 数值 −2→−1 归 status_effects.tres。
; 区间行(伤害量值区间批 2026-09-14):heal_minor [2,6] · clear_blast [25,55]——中点锚 power 恒等期望当量,
; roll 时机 = 身份预分配批内追加取号(既有取号序零扰动);spark_aoe 定值行无区间字段。
; 减伤墙调参批(2026-09-13):defense_up 权重 24→16——攻击成为池内最高行(历史注记)。
; 护甲等级掷点批(2026-09-16 用户拍板):defense 型正向行换装——reward_id/effect_id defense_up → ac_up
; (显示名"盾牌加护"——2026-10-12 由"护甲强化"改名;AC +1/层 ×2 层);cell_type defense / 权重 16 / tier 2 零改动(类型频次合计 79 不变——历史注记,数值压缩批后现合计 67);
; 百分比减伤行无双轨退役——status_effects.tres defense_up 行同批删除。
;
; 数值压缩批(2026-09-17 用户拍板暂定):
; ① 整体绝对值轴 ÷3:spark_aoe 4→1 · heal_backlash 4→1 · clear_blast [25,55]→[8,18](中点 power 40→13,
; 区间中点恒等期望当量的锚口径不漂移)。
; ② 恢复奖励削弱(用户拍板两条):出现概率下调到当前的 1/4——权重 15→3(当前频率 15/79≈19.0%,目标
; 4.75%,整数权重最接近 = 3/67≈4.5%);恢复量在 ÷3 后再 ÷2(现值 ×1/6)——[2,6]→定值 1
; (0.33~1 取整,区间字段保留 min=max=1 占位,量级再调时恢复区间结构)。
; ③ 雷安同池连带(结构冻结,自动同侧):heal 权重下调同比例降低踩中 heal 型雷(反噬)的频率——
; 负向侧反噬量同步 ÷3(4→1)。
; 类型频次合计 79→67(attack 20 / defense 16 / blast 16 / heal 3 / weaken 12)。行值 provisional 归 难度曲线与Boss。
;
; 伤害道具批(2026-09-18 用户指令):① 七型字典——五型增补 pierce(穿刺)/ magic(魔法)两型,各正负一行:
; 正向 = 单目标克制直伤道具(穿刺弹/魔法矢 power 2,attack_type 字段载攻击类型轴,走克制矩阵、
; 必中全额不掷点——棋盘来源伤害既有口径);负向 = 主角直伤(穿刺陷阱/魔法反噬 power 2,复用反噬通道不经增益状态)。
; ② 权重再平衡(保 spark_aoe 16 不动、总 67 不变):attack_up 20→14 · ac_up 16→11 · heal_minor 3→2 · weaken 12→8;
; 新行各 8。等比基准 = 其余四行 51→35(×0.686),整取后 14/11/2/8,微差登记已知偏差。
; 类型频次合计仍 67:attack 14 / defense 11 / blast 16 / heal 2 / weaken 8 / pierce 8 / magic 8。
;
; 九型批(2026-09-20 用户拍板——GP 进第九型,获取来源=战斗结束掉落+雷图低概率惊喜获取〔量与战斗掉落相当〕;
; GP 袋=挖开安全格入战斗内缓冲、战斗完成统一入账;破财=危险格摇到 gp 面的字典负向行〔weight 0 不入池,
; 挖危险格兑付=缓冲 -2 钱包侧 clamp ≥0〕;正向权重合计 74→76);行值 provisional 归 难度曲线与Boss。
; gp 两行 tier=1(provisional 占位);effect_id gp_gain/gp_loss = 战斗内缓冲(escrow)通道路由键
;(战斗结算 _apply_percent_row 分流,不入增益容器——ConfigDB ① status_effects 悬空豁免归 core 面)。
;
; Package B 数值优化批·首版(2026-09-22——qa-data/实现计划书_PackageB.md §4.3):clear_blast
; 区间 [8,18]→[18,35](中点 power 13→26)——清第一图回归真正伤害尖峰,撑起 boss"必清图才打得动"
; 节奏(L1 boss 清图≥1 靶 ≥80%);其余行全部不动。provisional,以 MC 复测读数为准
;(runbook 计划书 §5;迭代记录 qa-data/iteration_log.md)。
; ⚠️ 计划书笔误代拍板:原文"power 25"违反 schema 中点锚硬校验(config_fatal)——power ≡ floor((min+max)/2),
; (18+35)/2=26 故落 26(期望当量 +1 vs 计划书 25,掷点区间 18–35 与计划一致,玩法值零偏离)。
;
; Package B 迭代·第 2 轮(2026-09-22——计划书 §6.2,用户拍板一B):heal_minor 恢复量 1→2
;(区间三值同步 power/min/max = 2/2/2 过中点锚校验)+ 出现权重 2→4(正向池合计 76→78)。
; 与 hero.tres max_hp 17→20 同轮双变量(用户拍板组合拳,归因混在一起由下轮分摊)。provisional 未提交。
;
; Package B 迭代·第 4 轮(2026-09-22——计划书 §6.4,用户拍板 A):clear_blast 26→32
;(区间 [18,35]→[24,40],(24+40)/2=32 恰为整中点锚)。boss 面三缺同解(normal 胜率 62% 贴下沿 /
; 清图率 49% vs ≥80 / 完成度 99 vs >130)——清图尖峰加大让"先清一图"成为 boss 战最优路径。
; 副作用已知:perfect L1 boss 胜率 97% 越 75% 上界加剧。provisional 未提交。
; 数值修复批(2026-10-01):直伤雷三行 4/5/5→6/8/8(迭代 8 雷当量 provisional 的再抬档)——用户口径
; 「踩雷必须痛」;配套 hero max_hp 20→24 双向对冲(见 hero.tres 批注)。新尺 MC 复测归本批。
+54
View File
@@ -63,3 +63,57 @@ script = ExtResource("1")
segment_order = PackedStringArray("grant", "buff_debuff", "combat", "decay", "verdict")
core = SubResource("SettlementCoreTable_core")
damage_roll = SubResource("DamageRollTable_roll")
; 攻击类型 × 护甲克制批(2026-09-12 用户拍板结构;2026-09-15 命名统一批 + 抽象分离批,数值 provisional 待用户/C3 调参):
; 主角攻击 = 单一基础分量(2026-09-19 充能退役批·用户拍板——原三分量模型退役,克制策略归冒险前配置:
; 类型 = hero 表 attack_type,营地换型 = 改字段;局内无挖掘攒弹药的第二供给)。
; 【抽象分离纪律保留】攻击类型 {normal, pierce, magic} = 普通 / 穿刺 / 魔法 = 伤害的属性轴,
; 只决定查矩阵哪一行,定义里不含任何棋盘来源;护甲类型 {light, ward, heavy} = 轻甲 / 魔法护甲 / 重甲是敌单位属性。
; 格面资源批(2026-09-15 用户拍板):段序七段 → 五段(item_window/item 两段随可选类道具删除下线);
; source_label_map 删 item 键;effect_pool_map 增 sapped→hero_offense(weaken 型负向——乏力)。
; enrage(敌方暴走 +25%,enemy_output 池)/ off_guard(我方失衡 +25%,hero_defense 池)/
; sapped(我方乏力 -25%,hero_offense 池)= attack/defense/weaken 三型负向字典行
; (极性路由兑付:挖危险格 / 标错安全格按该格 cell_type 取负向行;heal 负向 = 主角直伤不经状态、blast 负向 = 警觉(敌方 AC +1,2026-09-20 八型批换装))。
; 减伤墙调参批(2026-09-13):pool_clamp 域 [-100,+100] 结构冻结不动;减伤杠杆走 status_effects.tres(批注在该表)。
; 护甲等级掷点批(2026-09-16 用户拍板,数字即规范——战斗结算 GDD 护甲等级掷点节定稿同批):
; roll_faces=20 / roll_tier_bounds=[3,7] / roll_tier_discounts=[75,50,25] / crit_roll=20 / crit_multiplier=200 /
; damage_floor=1 / armor_roll_stream=armor_roll;attack_bonus=0 结构位(元进度/武器附魔未来投值)。
; 判定式:掷点 ≥ 防守方 AC + attack_bonus → 全额;缺口 1-3 → ×0.75、4-7 → ×0.5、8+ → ×0.25;无 miss 无零收益档;
; nat20 = 暴击 ×2 恒全额(双方同规);任何攻击落地伤害 ≥ damage_floor(全局 max(1,·))。
; 掷点只吃基础攻击分量(主角普通分量 / 敌方攻击拍与重击拍基线);穿刺/魔法充能与棋盘来源伤害必中全额。
; EV 参考数(按判定式复算):AC10 期望减免 21.25% / AC11 25% / AC12 28.75%;微调旋钮 = bounds/discounts,不动 AC 值。
; effect_pool_map 同批删 defense_up 键(减伤百分比行整体退役、无双轨)——ac_up 是 AC 阈值轴效果,不入任何池;
; off_guard(hero_defense 池)保留不动,池结构与乘区公式零改动。
; 敌人技能池批(2026-09-16 用户拍板):effect_pool_map 增 empower→enemy_output(蓄力技载体——敌方输出 ×2
; 经既有 enemy_output 乘区兑付)与 fortify→enemy_defense(硬化技载体——敌方防御池新词汇)。
; enemy_defense 池乘区消费面 = 主角攻击落地段(Σ三分量后 ×(100+clamp(enemy_defense))/100)——
; 四池对称乘区:敌打主角 = hero_defense×enemy_output,主角打敌 = hero_offense×enemy_defense
; (hero_offense 现行走主角普通分量 attack_up 直乘、切片未改——登记遗留)。
;
; 数值压缩批(2026-09-17 用户拍板暂定):
; equivalence_ref_damage 12→4(当量参考敞口,绝对值轴 ÷3 取整);
; roll_faces/折扣档/暴击/damage_floor/克制矩阵/pool_clamp 全部不动(相对轴)。clamp 域 [-100,+100] 共用。
;
; 战斗数值结构修复批(2026-09-18 盘问会话用户拍板):
; effect_pool_map 删 off_guard 键——off_guard(失衡)换装 AC 轴(unit percent→ac、+25→−2,provisional
; 归 状态层重设计批;消费走 _defender_ac 既有 ac 型读法零代码),退离 hero_defense 池(池清空、结构保留;
; 上方 2026-09-15 attack/defense/weaken 三型负向字典行的极性路由注记不变——defense 型兑付行仍是 off_guard,
; 变的只是池归属)。hero_offense 乘区接线同步落地(battle_orchestrator 主角攻击段):Σ三分量后
; ×(100+clamp(hero_offense))/100×(100+clamp(enemy_defense))/100——attack_up 普通分量直乘旁路退役,
; 增伤/乏力覆盖面 = 普通+穿刺+魔法 合计;上方"hero_offense 现行走直乘——登记遗留"注记随之销项。
;
; 甲效矩阵用户调参批(2026-09-18 用户逐格给值,五格改值、四格不动):
; normal ward 100→120 · normal heavy 100→50 · pierce light 100→80 · pierce ward 150→120 · pierce heavy 50→80;
; magic 全行与 normal light 不动。上方「克制语义 = 克制 ×150 / 中性 ×100 / 被克 ×50(对策三角)」三档措辞退役——
; 现行五档:克制 ×150 / 弱克制 ×120 / 中性 ×100 / 弱被克 ×80 / 被克 ×50,普通行不再恒中性。
; 键集 3×3 满格结构冻结不动;矩阵消费面 = 主角侧(道具直伤 / 主角攻击三分量 / 充能分量),
; 敌打主角现行不查矩阵——主角 armor_type 轴仍休眠,轴生效待敌方技能攻击类型批。
; 实战读数(现行敌种甲配置):L1/L2 小怪全轻甲 → 穿刺类(开格充能/穿刺弹)×80 小幅折损、普通/魔法中性;
; L2 Boss 魔法甲 → 基础攻击与穿刺弹 ×120、魔法矢 ×50(不变)。重甲现行无消费敌种(零消费格)。
;
; 甲效矩阵加法核换装批(2026-09-18 用户拍板数值语言——小整数加法核,与 01-核心循环 数值语言条款同批):
; 量纲 percent→整数点数,三档 克制 +1 / 中性 0 / 被克 −1,九格 normal [0,+1,−1] / pierce [−1,+1,0] / magic [0,−1,+1];
; pierce×heavy = 0 中性为用户特别拍板(重甲挡刀刃不排斥穿刺;现行无重甲敌种,纯结构位)。
; 上方 2026-09-18 甲效矩阵用户调参批(五档 ×150/×120/×100/×80/×50)与更早三档三角批注的百分比量纲全部随批退役(历史留痕不删)。
; 键集 3×3 满格结构冻结不动;缺项回退 = 0 中性(battle_orchestrator._counter_delta);域 [−3,+3](schema 校验)。
; 奖励直伤行 payload 键 effectiveness 保留键名、值语义改点数(JSONL 契约稳定——analyze_playtest 等分析工具不破坏)。
+15
View File
@@ -94,3 +94,18 @@ price_a = 1.8
price_b = 1.1
relic_base_price = 15.0
spend_discount = 0.8
; GP+商店房实施批(2026-09-20 用户拍板,设计权威 design/research/proposal-gp-shop-room-2026-09-20.md 裁决记录):
; 掉落=均值±方差掷定(gp_drop 封闭流)+关级加值;精英行为预留行(当前无消费方,随精英节点内容批启用);
; 价格公式 = base_price + price_level_bonus(关卡) + price_increment × 该商品已购档数(已购档数在 冒险结构——
; 冒险内累计、跨冒险清零);商品三件全陈列无刷新无摇号(2026-09-20 拍板,提案 §2.4 的三选一+刷新方案退役)。
; 期望账:L2 商店前可得 GP 期望 ≈ 35–40(L1 全程 22 ± 惊喜 + L2 商店前五战 21 ± ),三件首购总价 L2 =
; (4+2)+(2+2)+(4+2)=16、全购欲望 ≈ 26–34——取舍空间成立;量级与方差全部 provisional-pending-曲线调参批
;(用户拍板骨架先行、数值整体后置,行值归 难度曲线与Boss)。
; GP 商店房重构批(M-4 迭代 11 第②批 T1,2026-10-03——需求卡片 v1.3 全裁 P1 共享池/P4 ceil/P5 甲):
; pool_shelf 行族 = 共享池货架(kind_id 词表 attack/max_hp/armor/ap/feat_ticket/heal 六行——heal 系 T6 商店补回复〔默认原则:分类内成员都要在它该出现的渠道池里,现行缺〕、GP 袋负交易切边计价物不自售、feat_ticket 系 T5 专长凭证行〔非 Boss 渠道专长入口,价与其他商品相当=契约④口径②〕、
; 规则改写型特性三轴 doctrine 切边;库存=上限即库存,账本在 冒险结构 _bonus_taken 单点共享,行族不记库存);
; 价格公式换代(pool 模式)= ceil(base_price × b^(关序−1) × A^(本次进店已购次数)),price_a=1.8/price_b=1.1
; provisional 投值(零人工令改 provisional+后置追认,原 P5 甲研究拍板后置);products 行族 + 加法定价
; 随 legacy 模式(shop=off 对照承载)保留不退役,退役归 off 锚换代批。货架行值全部 provisional 归
; 难度曲线与Boss。
+59
View File
@@ -112,3 +112,62 @@ rows = [{
"damage_mult": 1.7,
"cooldown_beats": 3
}]
; 敌人技能池批(2026-09-16 用户拍板——设计权威 docs/proposal-skill-pool.md v1.0,全值 provisional 投值归 难度曲线与Boss):
; 五行 = 普通攻击 / 突刺(新行:伤害 ×1.5 冷却 2)/ 蓄力(增益技)/ 重击 / 硬化(新行:独占增益技——Boss 专属池载体)。
; 普通攻击两条域校验锁死:倍率恒 1、冷却恒 0(schema 拒绝配置)——池恒非空的结构前提。
; 蓄力 = 纯"攻击力增加"增益技(0 伤害、施加 empower 状态),与重击无任何组合语义(纠偏二——旧"蓄力→猛击"
; 固定配对随行为环退役);增益与倍率同拍只是两层乘法共存(×2 遇 ×2 = ×4)。
; buff_duration = 2 的口径:容器时限纲 = remaining_settlements(先兑付后衰减、授予当轮衰减段即 −1)——
; 施放发生在第 N 结算战斗段,需存活到第 N+1 结算战斗段才兑付("下一拍"),故持续 1 个有效结算 ⇔ 表值 2
; (提案"攻击×2 持续 1 结算"的容器语义落地;有效增益拍恰 1 拍,归 增益状态/难度曲线 复核)。
; 硬化 = 自防增益(fortify 状态 → 敌方防御池),Boss 池独占——增益 ≤1 纪律下旧蓄力拍不进 Boss 池(proposal §2.5)。
; 保底 M = pity_threshold = 4:连续 4 拍执行普攻 → 下拍必出特殊技(特殊技内按权重、不受冷却限制)。
;
; 分支节点图批(2026-09-17——L2 幽暗地域新技能行,全值 provisional 投值归 难度曲线与Boss):
; 撕咬 bite = 伤害 ×1.5 冷却 1(高频小爆发轮廓,与突刺 ×1.5 冷却 2 同倍率错开冷却轴——巨蜘蛛池载体;
; 复用技能行纪律下 lunge 仍归 L2 熊地精,两行不共用是有意的权重/冷却独立投值位)。
; 毒爆 venom_burst = 伤害 ×2.5 冷却 4(蛛化卓尔精灵 drider 专属池独占技——"Boss=专属池独占技+权重轮廓"
; 纪律的本批兑现;池引用唯一性 = 唯一 enemy_id: drider)。
; 两行均为 damage 型(存倍率不存固定值——伤害 = 施放者攻击基线 × 技能倍率,三乘法链第一乘)。
;
; 新效应词汇批(2026-09-19 用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0,全值 provisional
; 投值归 难度曲线与Boss):三词收敛两词——多段命中退役(无防御磨损体系,无对照机制);固定值伤害改形
; 必中附加分量(rider_mult,域 (0,1]):后置加法、必中全额、不进乘区不出暴击,分量值 =
; max(damage_floor, floor(攻击基线 × rider_mult))——随基线缩放保持共享技能表前提;
; ×0.75 价位锚 = AC 折扣档最轻档"不掉档的稳定伤害"(可掷分量期望 AC10≈0.80 / AC12≈0.76 对表)。
; ① 毒爆 + rider_mult 0.75(必中毒分量:atk3 → 毒 2 点,atk 区间 2–4 → 1–3 点随开战掷定值缩放)。
; ② 蛛网束缚 web_snare(新行,妨害型 debuff——对主角施加 off_guard 失衡):0 伤害施放行(不掷不折不兑付
; 伏击),字段复用 buff_ref/buff_duration;duration 2 = 1 个有效结算(empower/fortify 先兑付后衰减含
; 施放当轮口径);冷却 4;首发载荷 = 失衡(用户拍板),乏力 sapped 为第二词汇暂不实装;
; 池纪律 +:每池妨害 ≤1(ConfigDB 跨表校验);实装面 = 仅卓尔池,其余敌种不动。
;
; 第三关内容批(2026-09-20):大地脉动 earth_pulse = 灰矮人石君王 duergar_king 专属池独占妨害技
; (0 伤害施放行,对主角施加 sapped 乏力——第二妨害词汇首发,状态行 status_effects.tres 既有);
; 字段口径同 web_snare(duration 2 = 1 个有效结算);每池妨害 ≤1 纪律由跨表校验覆盖。
; provisional 归 难度曲线与Boss。
;
; Boss 半血解锁技三行(2026-10-05 技能池执行批 T5,迭代14④——D7 用户裁案甲:每 Boss 一行新独占伤害技,
; 工作值 provisional 归调参;pool 侧 半血解锁(trigger 收编)=50 门槛随 enemy.tres 三 Boss 行):
; quake_smash 震地怒击 ×2.5/CD4(食人魔酋长)· venom_curb 遏毒 ×2.0/CD3(蛛化卓尔精灵)·
; rockslide 岩崩 ×2.5/CD4(灰矮人石君王)。解锁语义/双面过滤/一次性弹出规格 = 敌人系统.md 意图呈现节。
;
; 有效倍率表(2026-10-05 技能池执行批 T2——D4 整数基线登记:敌技基线=int(round(atk×mult)) 四舍五入半值上取,
; 全伤害管线唯一非 floor 取整点〔豁免登记见 registry skill_table〕;半点恒上取保住 atk=1 特殊技辨识度):
; atk=0(区间下界):全技塌缩下限 1(突刺==普攻==重击==1)
; atk=1(L1 全系+L2 四行):attack 1 / lunge·bite 2(实际 ×2.0 +33%)/ heavy 2(==突刺)/
; venom_burst 3(×3.0 +20%)/ venom_curb 2(×2.0 =名义)/ quake_smash 3 / rockslide 3(×3.0 +20%)
; atk=2:attack 2 / lunge·bite 3 / heavy 4 / venom_burst 5 / venom_curb 4 / quake_smash 5 / rockslide 5(全精确)
; atk=3(L2 精英/L3 全系):attack 3 / lunge·bite 5(×1.667 +11pp)/ heavy 6 / venom_burst 8(×2.667 +6.7pp)/
; venom_curb 6(=名义)/ quake_smash 8 / rockslide 8
; atk=4(区间上界):全精确(4/6/6/8/10/8/10)
;
; 敌人表内容修批 N2(2026-10-13 用户令「按推荐方式」,迭代 24 卡①)——普通敌错峰两行(12→14 行):
; venom_spit 毒吐 = 伤害 ×1.6 冷却 2(巨蜘蛛族普通敌池载体,挂 (2,5)/(2,6)/(2,7),首遇教学位 (2,4) 不投——
; 「独占技随关错峰」首轨只做在 Boss 侧的补齐;venom_spit 自 (2,5) 起投)。
; shield_bash 盾击 = 伤害 ×1.7 冷却 3(灰矮人族普通敌池载体,挂 (3,0)/(3,5)/(3,7))。
; 两行均不带 rider_mult:L2/L3 普通敌 atk 1–3,floor(atk×r) 恒被 damage_floor 兜成 1,与 0.75 档效果
; 完全相同——白占字段(毒绕开护甲由 damage 直伤表达已足够)。
; 有效倍率(int(round) 半值上取):毒吐 atk1→2/atk2→3/atk3→5;盾击 atk1→2/atk2→3/atk3→5。
; 倍率 provisional 归 M4 数值批。池权重均 2;逐池「恰一普攻/增益≤1/妨害≤1」纪律复查过
; (巨蜘蛛族增益仍仅 charge、灰矮人族 (3,0)/(3,7) 仅 charge·(3,5) 无增益、两族妨害 0)。
+44
View File
@@ -95,3 +95,47 @@ rows = [{
"stack_policy": "stack",
"max_stack": 16
}]
; 减伤墙调参批(2026-09-13,playtest-2026-09-12 报告 Q1 触发——defense_scan 实测墙轮 39%、
; 真人局 12/12 轮零承伤满血冒险成功):defense_up magnitude -50 → -30——叠满两层 = -60 减伤帽
; (原拟 pool_clamp_lo=-60 被 schema 冻结域拦截,杠杆移至本表);石肤权重 24→16 随批(reward.tres)。
; 承伤带对 C3 F4(≤20%/普通场、≤50%/Boss 场)复验责任随批;B3 GDD "-50" 文字同步随下次 B3 修订批。
; 格面资源批(2026-09-15):新增 sapped(乏力——weaken 型负向,hero_offense 池,attack_up 镜像;
; 进 effect_pool_map 同批登记)——状态表六行→七行;enrage/off_guard 语义 = attack/defense 型负向
; (标错安全格 / 踩到危险格经极性路由兑付,不再绑"标错反噬"单一来源)。
; 护甲等级掷点批(2026-09-16 用户拍板——百分比减伤增益整体换装为 AC,无双轨):
; defense_up(减伤 −30 percent ×2 层)整行退役(上方 2026-09-13 减伤墙批注随之留档)——
; "叠满池触底 ×0"免伤墙的结构面随 AC 掷点从根杜绝;新增 ac_up(盾牌加护 +1 ac ×2 层——2026-10-12 由"护甲强化"改名)——
; unit=ac 新量纲(AC 阈值轴效果,不入 effect_pool_map 任何池),消费面 = 战斗结算掷点判定
; (防守方 AC = 主角表值 armor_class + Σac 型效果层数×幅度);off_guard(失衡 +25 percent,hero_defense 池)
; 保留不动,其余六行零改动——状态表仍七行(一行换装)。
; 敌人技能池批(2026-09-16 用户拍板——增益技新状态行,七行→九行;敌方增益走既有增益状态容器):
; empower(蓄力:敌方攻击 +100 percent,enemy_output 池——蓄力技 buff_ref 载体)与
; fortify(硬化:敌方防御 +100 percent,enemy_defense 池——敌方防御池新词汇载体,Boss 池独占硬化技)。
; 两行 duration = 2 的口径:先兑付后衰减含施放当轮 → 表值 2 ⇔ 有效增益拍 1 拍(施放后下一结算兑付,
; 提案"持续 1 结算"的容器语义落地——详见 skills.tres 批注);refresh ×1 层(冷却闸下不可能自叠加)。
; enemy 侧池语义 = side-wide(registry 既有口径):蓄力 +100 入 enemy_output 与 weaken/enrage 共池 clamp;
; 硬化 +100 入 enemy_defense 新池(乘区消费面 = 战斗结算 主角攻击落地段)。值全部 provisional 归 难度曲线与Boss。
;
; 数值压缩批(2026-09-17 用户拍板暂定):ambush magnitude 3→1(伏击附加 = 层数×幅度,3 整除 ÷3)。
; percent 全族(attack_up 50 / weaken −65 / enrage 25 / off_guard 25 / sapped −25 / empower·fortify 100)
; 与 duration/max_stack 全部不动(相对轴与结构轴不压缩)。
;
; 战斗数值结构修复批(2026-09-18 盘问会话用户拍板——本批三行全部临时值,provisional 归 状态层重设计批):
; off_guard(失衡)换装 AC 轴:unit percent→ac、magnitude +25→−2(失衡 = 主角 AC −2,更易被命中;
; 消费走 _defender_ac 既有 ac 型读法零代码;settlement effect_pool_map 同批删 off_guard 键——
; hero_defense 池清空、池结构保留);fortify(硬化)符号纠正:+100→−50(乘区 = enemy_defense 池 −50
; → 主角攻击 ×0.5 折半——旧 +100 实际 ×2 翻倍,与"硬化=减伤"语义相反,用户确认系符号 bug);
; weaken(削弱)叠层改续时:stack_policy stack→refresh、duration_settlements 1→2(同名重复授予
; 只刷新剩余结算数、层数恒 1——结构性消饱和,×2 叠满池触底 ×0 免伤轮从根杜绝;refresh 实现与
; empower/fortify 同款零代码)。duration 终值、off_guard N 值、当量锚复算全部归 状态层重设计批。
;
; 格面资源八型批(2026-09-20 用户拍板):① off_guard magnitude −2→−1(护甲型奖励/惩罚数值对齐 = ±1);
; ② ambush(伏击)行整体退役——群伤负向不再放大敌方伤害;③ 新增 alert(警觉:敌方护甲等级 +1,
; target_side enemy、unit ac、1 结算、stack 上限 16)——blast 型负向新载体,消费 = _defender_ac 敌方侧
; ac 型读法(本批新接线)。状态表九行→九行(伏击出、警觉进)。数值全部 provisional 归 难度曲线与Boss。
;
; 主角增益只续时不叠层批(2026-09-20 用户拍板「主角的其实也一样,都是按照叙事的方式,不要有叠层;只续时不叠层」——
; 对齐削弱 2026-09-18 续时定案):attack_up / ac_up 两行 stack_policy stack→refresh;
; duration_settlements=1 与 max_stack=2 表值不动(refresh 下层数恒 1、max_stack 不消费——weaken 先例;
; dur=1 下续时表现为重复拿重置当轮倒数,跨轮延续随将来 duration 拉长自然显形——数值归状态层重设计批)。
+11
View File
@@ -4,6 +4,17 @@
[resource]
script = ExtResource("1")
; 迭代 22 秘宝体系实现重构落地批 T1(2026-10-12):新目录 12 行全量换代(设计权威=秘宝.md「目录(重设计 v1)」;
; 旧 12 行删除——venom_edge/seal_burst 已随迭代 20 专长批迁出删除,本批实删 12 行)。三档=普通 7/优秀 3/稀有 2
; (传说留空=空集合法,迭代 20 追认③先例)。解锁混合制(契约 8 逐件分配锁定表,2026-10-11 用户裁 C1):
; 钥石购买件 unlock_keystone_cost(provisional 占位);条件件 unlock_requires 谓词行——计数键
; adventure_cleared=生涯冒险成功局数(C6 裁:打通整局冒险)/boss_kill_count=生涯 Boss 击杀/vision_used=
; 真视类工具累计使用(本批新增计数域)。全部数值 provisional 归调参批(契约 7)。
; 常时参数面件(无订阅行——效果=开局/装板参数注入,非事件订阅):阔视野带/储备罐/远程镐/信标网络/刷新练习/
; 刷新执照六件 effect_kinds 挂参数 kind,由注入面按装配集 kind 分发读取(_attune_refresh_x_total 先例)。
; 主动件:线香(battle 级充能)/天眼(level 级充能)charge_reset 扩签;试炼镐=自动兑付(charges=0 无上限,
; ap_charge_safe 满 charge_n=8 自动当轮 grant_ap——2026-10-12 反哺批⑤用户裁:无玩家发起入口、
; 旧行 counter_spend 受理闸随裁删除;挖格扣 AP 后、轮末判定前兑付;战斗级重置=账即时清空自然无感)。
rows = [{
"item_id": "morning_order",
"display_name": "晨操令",
+31
View File
@@ -74,3 +74,34 @@ rows = [{
"board_types": ["deep_underdark"],
"counter_items": []
}]
; 地形变异 首批类型定稿批(2026-09-19 用户拍板)——四行两轴×两关:
; 第一关 dungeon(平原/密林基线):荆棘丛(伤害型:挖开扣 1 点生命,轮末结算兑现)+ 藤蔓缠绕
; (信息型:挖开且显示数字时数字被遮蔽,呈现层读取);第二关 underdark(幽暗地域):岩浆
; (伤害型 2 点,登记名沿用)+ 烬覆(信息型)。unlock_level 门控 + board_types 交集门控双闸,
; 首关候选池恒 {荆棘丛, 藤蔓缠绕},第二关候选池恒 {岩浆, 烬覆}。
; counter_items 恒空:反制道具配套义务随框架契约保留,兑现归 Alpha 反制批(2026-09-19 用户拍板
; 反制道具改排 Alpha——切片期变异暂无反制手段,纯税状态已知悉接受)。
; 全部行值 provisional 归 难度曲线与Boss 调参批(effect_value/布置参数均为加法核小整数轴)。
;
; 第三关内容批(2026-09-20):伤害型关间递进 1(荆棘)→ 2(岩浆)→ 3(落石)+ 信息型矿尘;
; counter_items 恒空(反制归 Alpha 反制批);布量走既有公式
; (5% + per_level_bonus × 2——percent_of_cells 表头字段驱动,不加新配置)。
; 行值全 provisional 归 难度曲线与Boss。
;
; 基数修正批(2026-09-21 用户拍板):数量公式百分比基数由总格数改为候选池格数
; (安全格 − 初始展开区 = 实际可挖格)——总格数基数下初始展开占全板 56–67%,
; 有效密度膨胀 4–6 倍(L1 10×10 板实测 5%→30%,极端板全池覆盖);percent 语义 =
; 占可挖格比例,关卡递增由 per_level_bonus 绝对格数承载。表值不变归 调参批 重标。
; M-3 迭代 5 判读锁值批(2026-09-28):岩浆 effect_value 2→1 · per_level_bonus 2→0 · percent_of_cells 5→4
; (杠杆扫描 C3 组合收带 L2——配对种子读数见 design/qa/m3-iter5-lever-scan-2026-09-28.md;L3 侧效应=
; 变异密度 9%→4%、完美 L3 0→34%,L3 无带记观察态;行值 provisional→正式随迭代 5 出口人闸追认)。
; M-3 迭代 5 返工批(2026-09-29 U2 推翻 C3 裁 C1 两刀):percent_of_cells 4→5 回退;岩浆 1 与 per_level_bonus 0 维持——C1 终态;
; C1+v1 AC 组合读数归返工批全量确认(裁断全录 design/qa/m3-iter5-u2-gate-2026-09-29.md)。
;
; 屏蔽记录(2026-10-16 用户令):skewed_veins 贫矿脉行已删除——用户裁「地形变异特异关卡后续重新做
; 设计,先屏蔽」。删除后 Boss/精英图全局池空 → _resolve_global_variant 空行回落 → region 布置原路
; 兜底(battle_orchestrator.gd 既有回落路径),玩家面零横幅零角标零资源偏斜。删除行内容与首发批
; 裁决依据(2026-10-04 迭代 14 ③号卡:案A 资源面微贫向偏斜、effect_value=30 provisional、域 [0,50]、
; 0=中性 off 锚)见 git 历史;resource_face 机制代码(RewardEconomy 偏斜投影/schema 互锁/负样本
; 断言)全部保留,重建设计直接加行即可。
+1 -1
View File
@@ -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)
+16 -13
View File
@@ -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 暗底双色墨制
+1 -2
View File
@@ -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) # 营地钥石徽暗底(同上)
-9
View File
@@ -139,15 +139,6 @@ 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()` 驱动) | `shot_probe.gd:_ready`(camp 截图段)〔营地图批 V1〕 |
| 营地七物件命中区点选与分界面可达 | 营地场景视图 | 七物件命中区 `_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`(顶栏位结构段) |
**旅程段七:数据配置与跨系统契约**
+1 -1
View File
@@ -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 自动化前置面)
+4 -2
View File
@@ -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
+3 -3
View File
@@ -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())
@@ -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)
@@ -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}
+25
View File
@@ -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 三枚)均属代码标识符与数据行键,不入术语表(登记口径=概念规范名)。
+109
View File
@@ -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 值——归调参批)。
+130
View File
@@ -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/各件增员)经实数核对全部相符。§八附加发现四条均不属验收对照面,随合回流程处置。
@@ -1,55 +0,0 @@
# 停机呈报:棋盘格边长口径收口批(迭代 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 闭合后整体合回)。
@@ -1,145 +1,331 @@
# 提案:弃图刷新系专长流派(双基座七件)——预案 v0.5(2026-10-31)
# 提案:弃图刷新系专长流派(双基座七件)——预案 v0.4(2026-10-30)
> **性质**:换图系设计提案与 GDD 修改清单。双基座七件结构已经用户终审;本文保留为后续实现与验收的参考件,不随 GDD 落文退役。
> **性质**:待办清单条目「封锁-蓄力」combo 设计素材的设计提案与 GDD 修改清单。双基座七件结构已经用户确认,修改清单已经用户审核并落入四份 GDD;本文按用户要求保留,供后续写需求卡片参考。代码与数值表尚未实现。
>
> **核心裁定**:流派先由基座专长改变资源来源与刷新价格,再由后续专长让成功刷新直接形成输出、生存与 GP 资源收益。所有效果都改变玩家的刷新决策,不把旧图探索进度折算成清图奖励。
> **需求来源**:用户 2026-10-30 明确设计方向——流派先有基座专长,从资源来源、动作成本或结算规则上改变基础行为;后续专长围绕新行为提供输出、生存与资源收益。只有刷新后的数值增长,不足以形成流派。
>
> **结论行**:矿脉储能让付费挖格产 RAP,省力周转把刷新成本减半;两件基座允许叠加。崩壁冲击与蓄力周转把刷新变成输出,石层缓冲把刷新变成当轮全局受伤减免,坑道小憩把多次刷新累计成当轮恢复,矿道红利每次成功刷新固定给 1 GP。
> **结构裁定**:用户指定设计 **2 件基座+2 件输出+2 件生存+1 件资源**,共 7 件;两件基座允许同时持有并叠加;弃图回收按旧图探索进度发清图奖励,不采用固定发一份。本提案结构待裁点已清零。
>
> **结论行**:「掘进储能」让挖格产 RAP,解决刷新资源从哪里来;「折价换图」让刷新 RAP 成本减半,解决同样资源能刷几次。两件基座叠加后形成完整换图引擎。后续五件让刷新分别产生群体直伤、下次攻击爆发、护盾、回血与按探索进度回收的清图奖励。拿到任一基座后,刷新不再只是坏图逃生;配上后续专长,玩家会为了输出、生存或资源主动规划换图。
---
## 0. 七件总表
| 层 | 显示名 | 效果 | 行为职责 |
> 名称均为代号;数值与稀有度均为 provisional,不在本预案定稿。
| 层 | 代号 | 效果候选 | 它改变的决策 |
|---|---|---|---|
| 基座 | 矿脉储能 | 每次受理的付费挖格额外获得 RAP | 持续挖图也能为刷新蓄能 |
| 基座 | 省力周转 | 弃图刷新的 RAP 成本减半 | 同一份 RAP 支撑更多刷新 |
| 输出 | 崩壁冲击 | 成功刷新后,本轮战斗段末对全体存活敌造成固定伤害 | 刷新成为进攻动作 |
| 输出 | 蓄力周转 | 每次成功刷新叠层,上限 3;本轮下一次主角攻击消费全部层数 | 连续刷新汇成单点爆发 |
| 生存 | 石层缓冲 | 本轮只要成功刷新过,主角每次受到伤害固定减少 2 点;不叠加 | 刷新成为当轮防御姿态 |
| 生存 | 坑道小憩 | 每次成功刷新累计 1 点恢复,上限 3;本轮授予段合计回血 | 用刷新换取恢复空间 |
| 资源 | 矿道红利 | 每次成功刷新固定获得 1 GP | 刷新动作自身带少量金币收益 |
| **基座** | **掘进储能** | 每次付费挖格后额外获得 RAP | 想刷新不再必须少挖停手;持续挖图也能蓄能 |
| **基座** | **折价换图** | 弃图刷新的 RAP 成本减半 | 同样的储备支持更多刷新;部分挖格+部分停手也能维持换图 |
| **输出** | **弃图轰击** | 成功刷新后,对全体存活敌人造成伤害 | 刷新本身成为进攻动作 |
| **输出** | **换图蓄势** | 每次刷新攒层;下一次攻击附加全部层数后清零 | 连续换图可以蓄成一次单点爆发 |
| **生存** | **换图庇护** | 成功刷新后获得护盾 | 刷新可以主动用来抵挡后续伤害 |
| **生存** | **弃图休整** | 成功刷新后回复生命 | 玩家可以放弃当前图,换取一次恢复机会 |
| **资源** | **弃图回收** | 成功刷新后,按旧图探索进度回收清图奖励 | 不必挖完最后几格;可以先投入,再主动弃图变现 |
**结构关系**:基座负责让主动刷新可持续;输出、生存、资源五件负责让主动刷新有明确目的。后续专长不需要设置「必须先拿基座」的硬前置,它们的联动由实际刷新频率自然形成。
---
## 1. 设计原则
## 1. 通用设计思想:先改变行为,再给新行为收益
1. **基座先改行为**:必须改变资源来源、动作成本、动作结算或动作关系,使偶尔止损的刷新成为可持续打法。
2. **后续收益围绕新行为**:输出、生存、资源件只在成功刷新后兑现,不做放进任何构筑都成立的泛用增益。
3. **双基座可叠加**:一件改 RAP 收入,一件改 RAP 支出;每轮刷新上限继续负责限频。
4. **无专长基线不变**:七件只给持有者增加规则;全局经济、清图奖励与刷新基础语义不改。
5. **临时生命值不做**:现有体系没有独立血量护盾,本流派不使用该概念;石层缓冲直接减少最终承伤。
这一节同时作为后续修订 `奇物.md`「专长·设计原则」的建议文本。现在只记录在提案中,尚未写入 GDD。
### 1.1 基座专长的定义
**基座专长=让某个原本偶尔使用、主要用于止损的动作,变成可以持续使用的主要打法的专长。**
它至少改变下列一项:
1. **资源来源**:原来主要靠停手获得 RAP,现在挖格也能获得 RAP。
2. **动作成本或频率**:原来一整轮停手才能刷新一次,现在同样储备可以支持更多刷新。
3. **动作结算**:原来危险格只伤害玩家,现在也能重伤敌人,使主动踩雷成为进攻手段。
4. **动作关系**:原来挖图与弃图争夺资源,现在挖图为弃图蓄能,两个动作组成循环。
成本减半虽然形式上仍是数值变化,但如果它让刷新从偶尔可用变成持续可用,也满足基座要求。**判断标准不是改了多少规则文本,而是玩家的实际操作是否改变。**
### 1.2 基座与后续专长的分工
| 层 | 职责 | 不合格形态 |
|---|---|---|
| **基座专长** | 建立新的资源循环或动作规则,让核心动作能持续使用 | 只在原动作后加少量攻击、护甲或资源,动作使用时机不变 |
| **后续专长** | 让核心动作产生输出、生存或资源收益,扩展新打法 | 不依赖新行为、放进任何构筑都同样有效的泛用数值增长 |
后续专长仍可采用「当 X 时 Y」的触发器句式,也可以各自独立生效;不另设集件标签。它们与基座的联系来自实际玩法:没有基座时,刷新少、收益兑现慢;有基座后,同一效果成为主循环的一部分。
### 1.3 行为改变检验
新流派或新基座专长过准入时,必须回答三个问题:
1. **拿之前怎么玩,拿之后怎么玩?** 如果最优操作与决策时机基本不变,只是结算数字变大,就不是基座。
2. **新行为为什么能持续?** 必须写清资源从哪里来、多久能做一次、什么限制防止无限循环。
3. **后续专长为什么属于这里?** 它应当兑现或强化基座建立的行为,而不是替代基座。
以自爆流为例:没有相关专长时,玩家应躲开危险格;拿到能减少自身雷伤、同时让危险格重伤敌人的基座后,玩家会主动寻找危险格。后续专长再提供踩雷后的回复、护甲或追加伤害。**「本来不该点」变成「现在值得主动点」,才是行为改变。**
---
## 2. 行为循环
## 2. 两件基座:分别改资源来源与动作价格
无专长时:
### 2.1 掘进储能
```mermaid
flowchart LR
A[正常挖图] --> B[遇到坏图]
B --> C[停手攒 RAP]
C --> D[必要时刷新]
D --> A
**效果候选**:每次付费挖格后,额外获得一定 RAP。安全格与危险格都按付费挖格计,不另判玩家意图。
**基础循环**:
```
持续挖格并获得格面收益 ──同时积攒 RAP──▶ 主动弃图刷新
▲ │
└──────── 新图继续挖格 ◀───────────────┘
```
拿到两件基座后:
**行为改变**:
```mermaid
flowchart LR
A[付费挖格] -->|矿脉储能| B[RAP 增长]
B -->|省力周转半价| C[成功刷新]
C --> D[崩壁冲击]
C --> E[蓄力周转]
C --> F[石层缓冲]
C --> G[坑道小憩]
C --> H[矿道红利]
C --> I[新图继续挖格]
- 玩家可以一边挖图拿收益,一边准备下一次刷新,不再必须停手。
- 每轮 AP 有限,因此新增 RAP 也有限;它扩大刷新机会,不提供无限刷新。
- 单拿时,坏图更容易被换掉;配上任意后续专长得益后,主动刷新才有完整目的。
### 2.2 折价换图
**效果候选**:弃图刷新的 RAP 成本减半。
**基础循环**:
```
部分挖格/部分停手留 AP → 同一份 RAP 支持更多次刷新 → 更频繁兑现后续专长
```
玩家会同时比较:
**行为改变**:
- 还要不要继续挖旧图,还是现在刷新兑现崩壁冲击或矿道红利;
- 本轮承伤压力大时,是否用石层缓冲换一次全局减伤;
- 生命偏低时,是否通过多次刷新累计坑道小憩的恢复;
- 是否蓄满 3 层蓄力周转,把多次刷新集中成一次攻击;
- 刷新次数与 RAP 价格如何影响后续图推进。
- 玩家不再需要为一次刷新攒下完整一轮的 AP;挖图与留 AP 的比例出现更多选择。
- 与掘进储能不同,它保留停手攒 RAP 的旧来源,但降低主动换图所需的投资。
- 单拿时,刷新从昂贵逃生变成常用工具;配上后续专长后,刷新次数直接转化为输出、生存或资源。
### 2.3 两件基座的组合
两件基座作用在不同位置:一个改 RAP 来源,一个改 RAP 价格。**用户已裁定允许同时持有并叠加**,组合后形成完整基座:
```
挖格产 RAP + 刷新半价 → 每轮更容易达到刷新次数上限 → 后续五件兑现收益
```
叠加后的硬边界仍是每轮刷新次数上限、有限 AP、旧图进度损失与战斗结束 RAP 清零。若实测过强,优先调产能量与半价数值,不增加「两件基座互斥」的特殊规则。
---
## 3. 七件效果结构
## 3. 两件输出:即时群伤与延迟爆发
### 3.1 矿脉储能
### 3.1 弃图轰击
每次付费挖格被受理后,额外获得 1 RAP。连锁展开不逐格追加;封印、移动、刷新不产 RAP。
**效果候选**:每次弃图刷新成功后,对全体存活敌人造成伤害。
### 3.2 省力周转
**玩法职责**:提供即时、稳定的群体输出。玩家会在「继续挖旧图」与「现在刷新打一轮伤害」之间做选择。
刷新 RAP 成本固定为基线的 50%。它只改持有者的价格,不改全局基值,也不返 RAP。
**与其他件的关系**:
### 3.3 崩壁冲击
- 掘进储能支持持续挖、持续刷、持续轰击。
- 折价换图让同一份 RAP 兑现更多次轰击。
- 与换图蓄势组合时,一次刷新同时提供当场群伤与下次攻击的蓄力层。
每次成功刷新记录一次当轮事实。本轮战斗段末,所有存活敌人各受 2 点固定伤害;刷新瞬间不当场插入战斗结算。
**边界**:只有成功刷新才触发;刷新被拒绝不触发;每轮刷新上限同时限制伤害次数。
### 3.4 蓄力周转
### 3.2 换图蓄势
每次成功刷新叠 1 层,最多 3 层。本轮下一次主角攻击附加全部层数对应的攻击加成,消费后清零;战斗结束不跨战保留。
**效果候选**:每次成功刷新获得 1 层蓄势,层数有上限;下一次攻击附加全部层数对应的伤害,然后清零。
### 3.5 石层缓冲
**玩法职责**:提供延迟、集中的单点爆发。与弃图轰击的即时群伤不同,它鼓励连续换图后寻找合适的攻击窗口。
每次成功刷新把当轮减伤状态置为生效。本轮主角每次受到伤害,在现行伤害下限之前固定减少 2 点;同一轮多次刷新不继续叠加。覆盖敌方攻击、危险格、错误封印资源格与地形造成的主角伤害。
**与其他件的关系**:
### 3.6 坑道小憩
- 双基座组合更容易连续刷新,为一次重攻蓄满层数。
- 与现有攻击强化专长可以组合,但不另设专属加成。
- 层数只在当前战斗内保留,战斗结束清零,避免跨战囤积。
每次成功刷新累计 1 点恢复量,最多累计 3 点。本轮授予段一次性合计回复生命,不超过生命上限,随后清零。
### 3.7 矿道红利
每次成功刷新固定获得 1 GP。不按旧图探索进度折算,也不与清图奖励绑定。每轮刷新上限限制触发次数。
**边界**:层数必须有上限;一次攻击消费全部层数,不能同一批层数重复附加到多次攻击。
---
## 4. 与现行结算时序的衔接
## 4. 两件生存:当场护盾与直接回血
- 刷新只结束挖掘动作的资源支出,不结束当前轮次,也不新增第六个结算段。
- 成功刷新后产生 `board_refreshed` 事实;刷新被拒绝时不产生事实。
- 崩壁冲击只先开伤害单,沿用现行案 C,在战斗段末结账。
- 石层缓冲订阅全局 `damage_taken`;该事件统一覆盖所有主角受伤路径。
- 坑道小憩和矿道红利用现有 GP/治疗兑付通道留痕。
- 刷新图仍不发清图奖励;正常清图支配性不变。
### 4.1 换图庇护
**效果候选**:每次成功刷新后获得护盾,按现有护盾规则抵挡伤害与消耗。
**玩法职责**:提供面向未来伤害的保护。玩家可以预判敌方压力,主动弃图换护盾,而不是只在棋盘不好时刷新。
**与弃图休整的区别**:护盾适合抵挡即将发生的伤害;休整用于修复已经失去的生命。一件偏预防,一件偏补救。
### 4.2 弃图休整
**效果候选**:每次成功刷新后回复一定生命。
**玩法职责**:把旧图与 RAP 转成恢复机会。生命偏低时,玩家可以放弃当前图的后续收益,换取继续冒险的空间。
**边界**:
- 回复不能超过生命上限,不转化为额外生命。
- 刷新成本与每轮次数上限不变,不能无代价连续回血。
- 强度对账时须同时计算放弃旧图进度的损失,不能只看单次回血量。
两件生存专长可以同时持有,让刷新兼具保护与恢复;但它们不替代输出件,玩家仍需通过其他攻击手段结束战斗。
---
## 5. 防退化边界
## 5. 一件资源:把旧图投入换成清图奖励
- RAP 仍来自有限 AP,不能无限刷新。
- 刷新本身不返 RAP。
- 每轮刷新上限继续生效。
- 石层缓冲是固定减伤,不堆层、不产生零伤害。
- 坑道小憩恢复上限 3,不能靠无限刷新稳定续命。
- 矿道红利每次仅 1 GP,量级明显低于正常战斗掉落,不足以替代清图与探索收益。
- 不引入临时生命值,不改变棋盘信息规则。
### 5.1 弃图回收
**已定效果**:成功刷新后,按旧图本次探索进度回收清图奖励;探索越多,回收越完整。具体档位、比例与奖励内容归后续调参。
**玩法职责**:建立与正常清图不同的资源兑现路线:
```
先挖图投入 AP、积累探索进度 → 不再挖最后几格 → 主动刷新 → 按进度回收清图奖励
```
**行为改变**:旧图不再只有「清完」与「全部放弃」两个结果。玩家可以比较继续清图的时间与风险,选择提前弃图变现。
**为什么不固定发一份**:空图刷新也拿完整收益,会让挖图投入失去意义,并把资源流退化成机械地点刷新。按进度回收要求玩家先探索、再决定何时兑现,保留先投入再弃图的循环,也保留接近清图时的取舍。用户已据此裁定采用按进度回收。
**边界**:同一旧图只能在成功放弃时结算一次;新图没有继承旧图的可回收进度;刷新被拒绝时不发奖励。
---
## 6. 最终裁定记录
## 6. 七件如何组成不同打法
- D1:双基座允许叠加。
- D2:资源件改为每次成功刷新固定 1 GP,不采用探索进度回收清图奖励。
- D3:生存件改为全局固定减伤,不使用护盾或临时生命。
- D4:恢复量按当轮成功刷新次数累计,上限 3。
- D5:所有主角伤害统一经过 `damage_taken`,允许现有订阅该事件的专长覆盖面按字面扩展。
- D6:七件显示名采用矿脉储能/省力周转/崩壁冲击/蓄力周转/石层缓冲/坑道小憩/矿道红利。
- D7:其余数值与稀有度先按需求卡片 provisional 投值,出口人闸追认。
| 构筑方向 | 组合 | 主要操作 |
|---|---|---|
| **持续轰击** | 掘进储能+弃图轰击 | 边挖边蓄 RAP,够价就刷新,刷新持续削全体敌人 |
| **蓄力爆发** | 折价换图+换图蓄势 | 用较低成本连续换图,把多次刷新汇成一次重攻 |
| **双基座输出** | 两基座+两件输出 | 高频刷新同时提供群伤与攻击层数,形成完整输出流 |
| **换图续命** | 任一基座+换图庇护+弃图休整 | 在生命与敌方压力下主动换图,用护盾与回血延长战斗 |
| **弃图采收** | 掘进储能+弃图回收 | 挖到一定进度后主动放弃,连续从新图获取探索收益与回收奖励 |
| **七件完整形态** | 全部七件 | 挖格蓄能、低价刷新,每次换图同时兑现输出、生存与资源;仍受每轮次数上限约束 |
**最小成立单位**是任一基座+任一符合当前需要的后续专长。七件不要求一次拿齐,也不设集件奖励。
---
## 7. 后续参考
## 7. 防退化与共同边界
本文保留供需求卡片、实现验收与后续调参比对。换图系现行权威规则仍以四份 GDD为准:
| 检查 | 约束 |
|---|---|
| **是否无限自供能** | 新 RAP 来自有限 AP 的付费挖格;刷新本身不产 RAP;每轮刷新上限与战斗结束清零不变。 |
| **无专长基线是否改变** | 不改变。两件基座是专长提供的新规则,不直接修改无专长时的全局经济。 |
| **双基座是否失控** | 叠加后仍受每轮次数上限;数值对账以每轮实际可达到的刷新次数为准。 |
| **输出是否重复消费** | 轰击每次成功刷新结算一次;蓄势层数在一次攻击后全部清零。 |
| **生存是否无代价** | 护盾与回血都要求成功刷新;玩家同时付出 RAP、旧图进度与刷新名额。 |
| **正常清图是否被删除** | 不删除。弃图回收不应让同等投入的收益无条件高于正常清图。 |
| **空图是否拿满资源** | 推荐案不允许;回收按旧图探索进度计算。 |
| **信息红线** | 七件均不增加揭示效果,不碰危险格信息规则。 |
- `design/gdd/systems/冒险循环/奇物.md`
- `design/gdd/systems/排雷循环/行动经济.md`
- `design/gdd/systems/战斗循环/战斗结算.md`
- `design/gdd/systems/战斗循环/地图战斗资源.md`
若实装后玩家仍然只在坏图时刷新,说明基座或后续收益没有真正成立;不能只继续增加数值来掩饰行为没有改变。
---
## 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. 自爆流现行条款不在本批改动面内;若以后要按同一基座思想重构,另行登记与裁决。
本提案保留为写卡参考;换图系七件尚未实装,未跑任何游戏测试。
@@ -1,19 +1,18 @@
# 需求卡片:Esc 浮窗与营地顶栏批(营地顶部小 HUD 栏 · Esc 三钮浮窗)· 营地交互重做卡⑤
- 版本:**v1.3(现行有效卡)**。留痕:Q1/Q2/Q3 均于 2026-10-18 裁定(甲/甲/甲,见 §10,已裁非待裁);契约 2 随 Q3 升格;卡④ 2026-10-31 已重立为 v3.0 现行有效卡,本卡随卡④ 代码波同行(改动沿革只进 git commit log)。
- 版本:**v1.2**(2026-10-18 grilling 轮次裁定回写——Q1 裁定甲(只营地根态响应,代拍板留痕)、Q2 裁定甲(再按 Esc 关浮窗,推荐案)、Q3 裁定甲(确认 Esc 只在营地语境,推荐案,用户的从严收窄升格为已确认);契约 2 随 Q3 升格;卡④回设计段→本卡排期随④重新立卡后,卡片保留有效)
- 来源:[需求澄清-营地交互重做-2026-10-18.md](需求澄清-营地交互重做-2026-10-18.md)(唯一事实源:⑤裁决 9/10、④结构树语境、⑦切批原则⑤)
- 归属:呈现层/组合根(`game/presentation/`)——营地交互重做五卡之五
- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁)
- 开工门:U0(用户 `/iter` 发令)+ 零待裁点(Q1/Q2/Q3 已裁,见 §10)+ grilling 复核门过+ **卡④ 代码波落地后**(卡④ 2026-10-31 已重立为 v3.0 现行有效卡、设计线闭合;本卡浮窗与 HUD 落在卡④ 新建的场景屏上,排期随卡④ 代码波之后,卡片本身有效)
- 开工门:U0(用户 `/iter` 发令)+ 待裁点已裁(Q1/Q2/Q3 均裁定,见 §10)+ grilling 复核门过+ **卡④重新立卡并落地后**(本卡浮窗与 HUD 落在卡④新建的场景屏上——卡④ 2026-10-18 回设计段,本卡排期随④之后,卡片本身有效)
## 0. 前置依赖与并行性
- 前置卡④(营地场景图,2026-10-31 已重立为 v3.0 现行有效卡):Esc 浮窗的「返回主菜单」与顶栏 HUD 都落在卡④ 新建的营地场景屏上;卡④ 设计线已闭合(样张过审 2026-10-31+art-bible v3.24 §6.2)——本卡不可先于卡④ 代码波落地,排期随④ 之后;本卡自身零美术依赖(零新素材、裁决 9/10 已给全),设计前置检查通过,卡片有效。
- **跨卡接口(保持既有名,不改名)**:①场景屏顶栏位(卡④ T2 预留;卡④ v3.0 挂接签名=`camp_scene_view.gd set_hud_band()`,「卡⑤ 填值」);②**营地刷新单口**(卡④ T3 定义;卡④ v3.0 定名 `camp_refresh_bus.gd` 的 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`)——本卡 HUD 刷新挂该单口,**非已退役的 `refresh_camp`**;③子界面返回钮承诺(卡④ T3——Q1 甲案前提:五界面各带返回/关闭钮);④卡④终局落点不变量(T0 互证:现役=终局 continue 回主菜单,`main_adventure_flow.gd:124-143` 终局出口 `_begin_session(false)`,行号 T0 复核;若后续改落点为营地则本卡「返回主菜单」动线须补会话收束)。卡④ v3.0 已原样承接上述四项,接口名无改动。
- 前置卡④(营地场景图):Esc 浮窗的「返回主菜单」与顶栏 HUD 都落在营地场景屏上;**卡④ 2026-10-18 已回设计段**(美术设计定稿未过设计前置闸)——本卡不可先于卡④重新立卡落地,排期随④之后;本卡自身零美术依赖(零新素材、裁决 9/10 已给全),设计前置检查通过,卡片有效。
- **跨卡接口(v1.1 补全)**:①场景屏顶栏位(卡④ T2 预留);②**营地刷新单口**(卡④ T3 定义:各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成)——本卡 HUD 刷新挂该单口,**非已退役的 `refresh_camp`**;③子界面返回钮承诺(卡④ T3——Q1 甲案前提);④卡④终局落点不变量(T0 互证)。
- 卡②的退出游戏钮、现役设置面——本批只复用不重做(契约 3)。
- 与卡④同批或随后(两卡触碰同一新屏)。**探针入口路径依赖卡②③链**:营地交互重做后营地只能经「菜单三钮→进入存档→选档→进档」到达——本卡 V1/V3 探针段隐含依赖该全链在位;卡②③ 工程波已随迭代 33 合回(待办清单 2026-10-18 条实况),探针段全链在位,无挂起前提。
- **多卡共改文件分界(`screen_flow_probe.gd`)**:卡④ T5 改该文件营地键语义(:53→新场景根句柄)与回退段(:119-125);本卡 T3 扩展该文件 Esc 合成段(现 :153-165 已有「选档语境 Esc 零响应」断言)为营地语境 Esc 浮窗断言段。两段按行域分界,各自改各自段,禁互相覆盖;T0 与卡④ 对齐行域。
- **camp 截图/golden 联动**:HUD 栏落营地场景屏会改 camp 截图内容——若本批晚于卡④单跑,卡④ 刚重制的 camp 断言基线必再漂移;若同批,卡④ T5 迁移时点须晚于本卡 T2 HUD 落位(排序约束)。本卡 T2 含「HUD 落位后核漂移热区→限 HUD 区显式更新+呈报」条;现无 camp 逐像素 golden(卡④ 契约 10)。
- 与卡④同批或随后(两卡触碰同一新屏)。**探针入口路径还依赖卡②③链**(v1.1 补明): restructuring 后营地只能经「菜单三钮→进入存档→选档→进档」到达——本卡 V1/V3 探针段隐含依赖该全链在位;若本卡先于卡②③合入,探针段挂起或走中间态断言(仿卡② §9 第 4 条先例)。
- **camp 截图/golden 联动(v1.1 补)**:HUD 栏落营地场景屏会改 camp 截图内容——若本批晚于卡④单跑,卡④ 刚重制的 camp 断言基线必再漂移;若同批,卡④ T5 迁移时点须晚于本卡 T2 HUD 落位(排序约束)。本卡 T2 含「HUD 落位后核漂移热区→限 HUD 区显式更新+呈报」条。
## 1. 目标与完成定义
@@ -22,50 +21,48 @@
- 裁决 10「钥石余额:场景**顶部小 HUD 栏**」(用户原话「先按顶部小HUD栏设计」——provisional 措辞留痕)。
**相对现状,新增了什么**:
1. Esc 浮窗(产品码现无任何键盘快捷键处理——从零新建);
2. 营地场景顶部小 HUD 栏(钥石余额常驻——现营地钥石徽在 CampOverlay 顶栏 `camp_overlay_view.gd:125`,随卡④拆解后由新 HUD 栏承接,落卡④ T2 顶栏预留位)。
1. Esc 浮窗(全仓现无任何键盘快捷键处理——从零新建);
2. 营地场景顶部小 HUD 栏(钥石余额常驻——现营地钥石徽在 CampOverlay 顶栏,随卡④拆解后由新 HUD 栏承接)。
**完成定义**:
1. 营地语境按 Esc 唤起浮窗,浮窗有且仅有返回主菜单/设置/退出游戏三项;浮窗的关闭/取消路径按 Q2 裁定落地;
2. 「返回主菜单」回主菜单(营地场景屏隐藏+选档层同收+主菜单可见);「设置」开现役设置面(语境分支见契约 3);「退出游戏」接现役退出路径;
3. 营地场景顶部小 HUD 栏在位,钥石余额读数=存档单口现值,刷新时机=购买后(挂卡④ `CampRefreshBus.refresh()` 单口)/进档或回营地进入时重读/夹具直写后探针显式触发;
3. 营地场景顶部小 HUD 栏在位,钥石余额读数=存档单口现值,刷新时机=购买后(挂卡④营地刷新单口)/进档或回营地进入时重读/夹具直写后探针显式触发(v1.1 清单化);
4. 浮窗零动效直开直关(生涯页同款契约);新层入 `LAYER_CONTRACT`;
5. 批末重闸按改动域选档全绿;三份 `reports/` 产出物写齐(T4)。
## 2. 现状事实(2026-10-18 实查;2026-10-31 复核行号,开工日 T0 再核)
## 2. 现状事实(2026-10-18 实查;开工日 T0 复核行号)
| # | 事实 | 出处 |
|---|---|---|
| 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:633`;消费点四处产品码——营地顶栏 `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:633`;`camp_overlay_view.gd:125`;`career_overlay.gd:54`;`status_panel.gd:32`;`save_select_overlay.gd:86` |
| F5 | art-bible **v3.24** §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` |
| 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` |
## 3. 设计契约(红线,违反 = L3 停机呈报)
🔴 **契约 1 · 浮窗三项且仅三项**:返回主菜单/设置/退出游戏(裁决 9)。禁加项(禁「继续冒险」类——营地无冒险可继续)、禁减项。浮窗的关闭路径=Q2 裁定项(再按 Esc 关),不属「加项」争议。
🔴 **契约 1 · 浮窗三项且仅三项**:返回主菜单/设置/退出游戏(裁决 9)。禁加项(禁「继续冒险」类——营地无冒险可继续)、禁减项。浮窗的关闭路径=Q2 裁定项(再按 Esc 关/关闭钮/无关闭三选一),不属「加项」争议。
🔴 **契约 2 · Esc 范围=营地语境(Q3 已确认,2026-10-18)**:浮窗只在营地场景图语境唤起(含其子界面开态——行为按 Q1 裁定的甲案:只根态响应)。**禁扩展到战斗/地图/其他屏**(用户 2026-10-18 确认「只在营地语境」;08:193 键盘面仍排 Beta,本批只落 Esc 一项)。
🔴 **契约 2 · Esc 范围=营地语境(Q3 已确认,2026-10-18)**:浮窗只在营地场景图语境唤起(含其子界面开态——行为按 Q1 裁定的甲案:只根态响应)。**禁扩展到战斗/地图/其他屏**(用户 2026-10-18 确认「只在营地语境」;08:192 键盘面仍排 Beta,本批只落 Esc 一项)。
🔴 **契约 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`(改)。`_quit_game`(`main.gd:143`)无语义副作用,原样复用。
🔴 **契约 3 · 设置与退出本体零重做、接线允许语境分支(v1.1 放宽)**:设置面本体与退出行为零改(F2/F3);**开合接线允许按语境分支**——现役 `_on_settings_closed` 带「回开始层」硬副作用,营地语境须分支为「关设置回浮窗不回主菜单」;正解=浮窗登记于设置层之下,`_open_modal(settings_overlay)` 自动隐藏浮窗、关闭自动恢复(既有栈语义);`_quit_game` 无语义副作用,原样复用。
🔴 **契约 4 · 返回主菜单动线**:营地场景屏隐藏+**选档层同收**(卡④ T3 口径)+开始层恢复;营地语境⇔闲时会话(无冒险会话——卡④ 契约 6「冒险进行中不开营地」+现役终局回菜单并 `_begin_session(false)` 收束推得),故动线本身不含会话收束;**回主菜单后菜单=卡②三钮、断点在档不在菜单露面**(禁实现者自作主张加「继续冒险」钮——那正是契约 1 在浮窗侧禁的);营地每笔消费即时写盘(`存档序列化.md`,行号 T0 复核),回主菜单不写档也无损。
🔴 **契约 4 · 返回主菜单动线**:营地场景屏隐藏+**选档层同收**(卡④ T3 口径)+开始层恢复;营地语境⇔闲时会话(无冒险会话——卡④ 契约 6「冒险进行中不开营地」+现役终局回菜单并 `_begin_session(false)` 收束推得,v1.1 前提成文),故动线本身不含会话收束;**回主菜单后菜单=卡②三钮、断点在档不在菜单露面**(禁实现者自作主张加「继续冒险」钮——那正是契约 1 在浮窗侧禁的);营地每笔消费即时写盘(存档序列化.md:121),回主菜单不写档也无损。
🔴 **契约 5 · 顶栏 HUD 单口读数+刷新挂卡④单口**:钥石余额只经 MetaProgression/SaveManager 访问器单口读(`camp_shop_presenter.gd:62 camp_data()` 的 `keystone_balance()`;禁第二账本、禁视图自算);**刷新挂卡④定义的营地刷新单口**(卡④ v3.0 定名 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`,非已退役 `refresh_camp`——F9);刷新时机清单=购买后(挂单口)/进档或回营地进入时重读/夹具直写后探针显式触发(T2 落定)。
🔴 **契约 5 · 顶栏 HUD 单口读数+刷新挂卡④单口(v1.1 订正)**:钥石余额只经 MetaProgression/SaveManager 访问器单口读(禁第二账本、禁视图自算);**刷新挂卡④定义的营地刷新单口**(非已退役 `refresh_camp`——F9);刷新时机清单=购买后/进档或回营地进入时重读/夹具直写后探针显式触发(T2 落定)。
🔴 **契约 6 · 零动效**:浮窗直开直关,子树零 AnimationPlayer、源码禁 `create_tween`/`UiKit.motion` 令牌(生涯页同款契约,F7);减动效设置项不新增(在役项沿用)。
🔴 **契约 6 · 零动效**:浮窗直开直关,子树零 AnimationPlayer、源码禁动效令牌(生涯页同款契约,F7);减动效设置项不新增(在役项沿用)。
🔴 **契约 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),关闭恢复——属既有栈语义非新决策。
🔴 **契约 7 · 层序纪律+遮挡结论(v1.1 落结论)**:浮窗入 `LAYER_CONTRACT`(改层序只改合同表);禁散落 `move_child`。**与调试角标遮挡的结论(v1.1 补,既有纪律已定论、无需用户裁)**:debug_badge 是末位 float 类不注册 ModalStack,ModalStack.open 只隐藏登记层⇒角标**恒压浮窗且保持可点**(树序末位=最顶绘制序,全仓无 `debug_badge.disabled` 赋值)——合同内照此表达。另写明一条栈语义防误触 L3:浮窗开会隐藏登记序在其上的已开层(如调试浮窗体 debug_overlay),关闭恢复——属既有栈语义非新决策。
🔴 **契约 8 · provisional 口径留痕**:裁决 10「先按顶部小HUD栏设计」的「先」字留痕——HUD 栏形态按最小集落地(只承载钥石余额),扩项=新裁点。
**拆分边界纪律适用性判定(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 与「实现规范预算」节。
🔴 **契约 8 · provisional 口径留痕**:裁决 10「先按顶部小HUD栏设计」的「先」字留痕——HUD 栏形态按最小集落地(只承载钥石余额),扩项=新裁点。
## 4. 范围边界
@@ -73,222 +70,116 @@
**不做**(明示去向):
- 营地场景图本体 → 卡④(本批只在其顶栏位落 HUD+挂刷新单口);
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①(工程波已随迭代 33 合回);
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①;
- 其余键盘快捷键(任意键关闭浮窗/手柄/战斗内 Esc) → 用户未裁,禁自扩(契约 2);
- 设置面/退出路径本体改动 → 无(契约 3);
- HUD 栏扩项(冒险天数/种子等) → 契约 8,扩项另裁;
- 不新建 camp golden(卡④ 契约 10:现无 camp 逐像素 golden,camp 验收=shot_probe 出图+shot_checker 语义断言)。
- HUD 栏扩项(冒险天数/种子等) → 契约 8,扩项另裁。
## 5. 关联文档同步面
> **现行口径**:实现批禁写 `design/` 整目录与根规则文件、两份根流程清单与 `game/tests/README.md`,唯一可写目录=`reports/`(+`game/` 实施本体);下表一律执行为列进 `reports/iter<N>-反哺点-<日期>.md` 反哺点清单(义务格全为「反哺点 · 列清单」类,禁旧「随批」措辞)。待办清单与体验验证清单已迁仓库根(原 `design/gdd/06-*`、`07-*` 路径已不存在)。
> **v1.3 口径**:本批禁写 `design/` 整目录与根规则文件,唯一可写目录 = `reports/`;下表一律执行为列进反哺点清单。
| 文档 | 关联点 | 同步义务 |
|---|---|---|
| `design/gdd/08-Alpha版本标准.md`(v1.13) | :193「键盘 / 手柄输入(排 Beta)」行——Esc 营地浮窗已落地(用户明示裁决,澄清⑤裁决 9),须加注防「Beta 行=本批违例」误读 | 反哺点 · 列清单(行内加注) |
| `design/art/art-bible.md`(v3.24) | §6.2「钥石余额:常驻画面顶部的一行小 HUD 栏」(:396)呈现位从 CampOverlay 顶栏迁场景屏 HUD | 反哺点 · 列清单(权威面零直改,过用户裁决后归文档批) |
| `design/gdd/ux/camp.md`(v2.2) | §顶栏(:39-41)「钥石余额常驻顶部小 HUD 栏、刷新入口=营地刷新单口(卡⑤同口挂接)」实装状态回填 | 反哺点 · 列清单 |
| `待办清单.md`(仓库根) | 本卡登记条(五卡总条第 438-449 行)状态推进 | 反哺点 · 列清单(实现批禁写待办清单) |
| `体验验证清单.md`(仓库根) | 新增目检条(Esc 浮窗三动线/HUD 余额观感/浮窗视觉面)——登记不阻塞 | 反哺点 · 列清单(实现批禁写体验验证清单,入册条目由文档批落) |
| `roadmap.md`(仓库根) | 迭代行编入/状态刷新 | 反哺点 · 列清单(实现批禁写 roadmap) |
| `game/tests/README.md` | 能力行入表(§7 对照表「能力行」列定名) | 写卡段定名(本卡只写卡内能力行文字,README 由主 Agent 统一收口);实现批只核对名实一致,禁写 |
| `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()` 寻址 | 行为改动 | 复用既有(改) | V8/B1 |
| `game/presentation/main_overlay_flow.gd` | `_on_settings_closed` 语境分支:营地浮窗路径关设置回浮窗、不回主菜单(契约 3) | 行为改动 | 复用既有(改) | V4/B3 |
| `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:487`)/`UiKit.danger_button`(:700),零新素材零新色值 | 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:633`)承载显示;订阅卡④ `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`/`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()` 加一寻址分支(不新增公开方法面);`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)。
| `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/*` | 实现与断言本体 | 实施本体(可写) |
## 6. 任务卡
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。步骤用 `- [ ]` 复选框记步,一步=一个动作+一个可核查结果;每卡声明「取用/产出」接口块,后卡引用的名字与早卡定义逐字一致;禁占位待定句式(不决定任何事的行不留)。
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。
### T0 事实坐实与跨卡对齐(≈0.5–1d)
- 取用:待办清单五卡总条实况(卡④ 已重立 v3.0、卡②③ 迭代 33 合回)、§0 跨卡接口、卡④ v3.0 §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 第 1 条接线方式选型联动,T0 定选型并回写文件结构图接线落点。
- [ ] Q1/Q2/Q3 裁定执行确认(甲/甲/甲,见 §10);开工门核:U0 发令、grilling 复核门过、卡④ 代码波状态。
- [ ] 跑 `bash tools/gdstyle.sh game` 开发期局部读数,记录三新件预算实数与存量触面 S13 基线键(预期只降不升);本步最窄确认,不构成验收。
- 产出:基线 commit、三新件接口块定稿(签名/取值)、S13 读数、跨卡接口核对表、Esc 合成先例复核结论;后续卡只按本卡契约施工。
- 复核 §2 行号;确认卡④场景屏顶栏预留位接口+营地刷新单口签名(跨卡);
- **Esc 输入合成 spike**(v1.1 补):headless 下键盘事件合成机制验证(现成先例只有鼠标 `Viewport.push_input`——F1);与 §9 第 1 条接线方式选型联动(InputMap action+轮询路线与合成探针不兼容,选型时一并定);
- Q1 子界面行为、Q2 关闭路径、Q3 范围确认裁定执行;
- 与卡④ T0 互证终局落点不变量(契约 4 前提);探针入口路径依赖卡②③链的时点确认(§0)。
### T1 Esc 浮窗视图与键盘接线(≈1–1.5d)
### T1 Esc 浮窗(≈1–1.5d)
- 取用:T0 三新件接口块、Esc 合成先例复核结论、`ui_kit.gd:487 modal_shell`/:700 `danger_button`/:633 `keystone_badge`、`ui_registry.gd:15-35 LAYER_CONTRACT`。
- [ ] 在 `camp_esc_overlay.gd` 实现 `setup_buttons()`:`UiKit.modal_shell`(`ui_kit.gd:487`,只产 dim+center+panel+VBox、无内置关闭件)+三钮(返回主菜单/设置/退出游戏,退出用 `UiKit.danger_button` :700);零新素材零新色值。
- [ ] 在 `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` 营地旗标先例,卡④ T5 改指新场景根句柄后对齐)且无营地子模态开态(Q1 裁甲);调试浮窗开态不影响判据(全局浮层、营地屏仍可见)。
- [ ] 在 `main_esc_flow.gd` 实现 `on_esc_input(ev: InputEvent) -> void`/`open_overlay() -> void`/`close_overlay() -> void`:营地语境 Esc → `ui.modals.flow.open(camp_esc_overlay)`;再按 Esc → `close`;非营地语境(boot 菜单)不唤起(契约 2)。接线方式按 T0 选型,禁吞他处输入。
- [ ] 在 `ui_registry.gd` `LAYER_CONTRACT` 加 `camp_esc_overlay` 槽(位于营地层与 `settings_overlay` 之间,契约 3 登记序正解)+`node()` 寻址;禁散落 `move_child`(F6)。
- [ ] 在 `main.gd` 加 Esc 输入入口与 `main_esc_flow.gd` 同名薄委托(探针 `main.X` 路径零改动)。
- [ ] 零动效(契约 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 按接口块接线。
- 浮窗视图:模态壳(`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 关/关闭钮/无关闭,按裁定)。
### T2 营地顶栏小 HUD 栏(≈0.5–1d)
- 取用: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:633`)承载,读数只经 `camp_data()` 单口(F9/契约 5,禁第二账本、禁视图自算);订阅卡④ `CampRefreshBus.refresh(camp_data)`。
- [ ] 在卡④ `camp_scene_view.gd` 的 `set_hud_band()` 顶栏预留位填 `CampHudBand` 实例(高 48px 浮层覆盖、不挤压画面;卡④ T2 跨卡接口①);`camp_scene_view.gd` 场景图铺底/命中区逻辑零改(卡④ 职责)。
- [ ] 刷新时机清单落定(契约 5):①购买后(挂单口)②进档/回营地进入时重读③夹具直写后探针显式触发——断言前须显式触发,禁依赖「自动重读」假设。
- [ ] HUD 栏形态按最小集(契约 8):只承载钥石余额;扩项=新裁点。
- [ ] camp 截图/golden 联动:HUD 落位后核 camp 截图漂移热区→限 HUD 区显式更新+呈报;现无 camp 逐像素 golden(卡④ 契约 10),camp 验收=shot_probe 出图+shot_checker 语义断言。
- 产出:`CampHudBand.set_balance()`/`bind_refresh_bus()`/`refresh()`、顶栏填值、刷新时机清单;T3 按接口块验收。
- 顶栏位落 `UiKit.keystone_badge` 工厂件(余额单口读数,契约 5);
- **刷新挂卡④营地刷新单口**(契约 5);**刷新时机清单落定(v1.1 补)**:①购买后(挂单口)②进档/回营地进入时重读③夹具直写后由探针显式触发——断言前须显式触发,禁依赖「自动重读」假设;
- HUD 栏形态按最小集(契约 8):只承载钥石余额;
- **camp 截图/golden 联动条(v1.1 补)**:HUD 落位后核 camp 截图漂移热区→限 HUD 区显式更新+呈报(仿卡④ T5/卡② 契约 6 口径;现无 camp 逐像素 golden——卡④ 契约 10)。
### T3 三出口动线、设置语境分支与断言批(≈1–1.5d)
### T3 断言批(≈0.5–1d)
- 取用: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`:营地场景屏隐藏+选档层同收+开始层恢复(卡④ 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 甲案判据);再按 Esc 关窗;非营地语境(boot 菜单)不唤起(契约 2);返回主菜单动线(营地隐+选档层收+菜单显);设置项开合(含营地浮窗→设置→关闭回浮窗高危路径+「关闭设置后禁弹主菜单」反向断言);退出项接线断言(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 收口。
- 探针(**宿主选 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 补);注入→最窄闸见红→精确还原→记录。
### T4 产出物落位卡(≈0.5d,末卡)
- 取用: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`(两域全量)复验。
三份 `reports/` 写齐。
**估时合计 ≈3–4.5d**。切分预案:T1/T2 后可切(浮窗先落、HUD 后落)——切分价值低,建议与卡④同批单跑。
**估时合计 ≈3–4.5d**(v1.1 订正:分项和=3.0–4.5d,原「2.5–3.5d」算术少算)。切分预案:T1/T2 后可切(浮窗先落、HUD 后落)——切分价值低,建议与卡④同批单跑。
## 7. 验证闸:改动—验收对照表
## 7. 验证闸(逐需求点验收清单)
七格表:需求点|改动(文件:行/行为)|验收测试(名称+落点+尾缀)|层级(单元/接口/集成/探针)|真实入口|判据绑定面|能力行。**每个需求点至少一行;每个行为改动至少一行(V1–V10 需求点行+B1–B3 行为改动专行);每行必须有真实入口和判据绑定面——缺任一项=该需求点未验收,卡片不成立。** 断言尾缀〔ESC批 Vn〕/〔ESC批 Bn〕,与卡片清单互相 grep。能力行格式 `既有:<能力名>;新增:<能力名>`(中文分号分隔,对齐机检与卡④ v3.0 先例),两形态名称都须在 `game/tests/README.md` 能力表在场(既有=现役在场名,新增=本卡定名、由主 Agent 统一收口入表;本卡只写卡内能力行文字,README 由主 Agent 收口)。
| # | 需求点 | 测什么 | 落点/判定手段 |
|---|---|---|---|
| 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 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→浮窗 `visible=false`(Q1 甲案,绑 `is_camp_context()` 无子模态开态判据);boot 菜单合成 Esc→浮窗 `visible=false`(契约 2,绑语境判据返回值) | 新增: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()` → 屏显编排 | 营地场景屏 `visible=false`+选档层 `visible=false`+`start_overlay.visible=true`(绑三处可见性;`_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` 语境分支 | 设置开→浮窗被遮挡不可见(绑 ModalStack 遮挡记账);关闭→浮窗 `visible=true`+`start_overlay.visible=false`(绑语境分支;反向断言「关闭设置后禁弹主菜单」) | 既有:模态覆盖层编排与输入锁;新增: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 不真退=静态判据+评审注记申报观测面局限) | 新增: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` 读数 | `keystone_badge.value_label.text`=`camp_data()["balance"]`(`keystone_balance()` 单口取值);直写后显式触发刷新才变(绑单口调用记录+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` 源码 | 子树零 AnimationPlayer+源码零 `create_tween`/`UiKit.motion` 令牌(扫描面 >0 非空前置) | 既有:模态覆盖层编排与输入锁;新增: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 调用记录);语境判据返回值(绑 `is_camp_context()`);浮窗三钮数量+登记序(绑节点树与合同表) | 既有:模态覆盖层编排与输入锁;新增: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 浮窗唤起与三出口动线 |
**测试方式两分法**:V1–V8 机检自动化(能力验证经隔离存档实例直写钥石/开态——v1.1 订正:不经 DebugOverlay 界面);V9 归用户目检(生命周期末步统一进行,不阻塞迭代,澄清⑥口径)。
**落点集中**: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 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试/工具先行孤立验证再并入全套。
**闸口径**:轻闸每卡出口自跑;批末重闸按改动域选档(本批碰 `game/` 代码与断言面 → `--code`)全绿才合并;MC 零跑(零数值零行为)。
## 8. 异常分级
- **L1(自救一次)**:断言写法、探针合成键事件写法、命名、编译错误、签名拼写、测试套件 manifest 登记遗漏。
- **L2(记录继续;同一红连续三次升 L3)**:Esc 接线方式选型(§9 第 1 条域内)、浮窗壳尺寸/位次(UiKit 现行件域内)、HUD 栏位微调(顶栏域内)、行数较 T0 预期漂移但 S13 键不升。
- **L3(立即停卡写报告等用户)**:
- 卡④ 代码波未到位又需合并;
- Q1/Q2/Q3 裁定被执行期擅自改值(已裁=甲/甲/甲,见 §10);
- 发现需扩展到非营地语境才能成立(触契约 2=用户裁面);
- Esc 键盘合成先例(`screen_flow_probe.gd:153-165`)复核失败且无替代真实入口验收手段(真实路径纪律不让直呼处理函数代偿);
- 浮窗开会隐藏其上登记层的栈语义被误判为缺陷(契约 7 已写明,勿误停机);
- 任何验收行无法从真实入口绑定特有可观测提交面(证明做不出=停卡呈报);
- **机检预算互斥=上游缺陷停卡退回写卡段**:实现规范预算三新件超默认未走指标例外申报、或存量触面 S13 键较登记值上升、或机检键/计数与卡片契约互斥——一律停该卡呈报退回写卡段,禁为凑绿保留无效成员、造第三条路或内联求裁(req-card 第 9/14 节合流)。
- **L1(自救)**:断言写法、探针合成键事件写法、命名。
- **L2(记录继续)**:Esc 接线方式选型(§9 域内)、浮窗壳尺寸/位次(UiKit 现行件域内)、HUD 栏位微调。
- **L3(停机呈报)**:卡④ 场景屏未到位又需合并;Q1/Q2/Q3 未裁即开工;发现需扩展到非营地语境才能成立(触契约 2=用户裁面);Esc 键盘合成 spike 失败且无替代验收手段(真实路径纪律不让直呼处理函数代偿);浮窗开会隐藏其上登记层的栈语义被误判为缺陷(契约 7 已写明,勿误停机)。
## 9. 代拍板白名单(超清单必呈报)
1. Esc 输入接线方式(`_unhandled_input` vs InputMap 新 action vs 专用控制器)——约束:不吞他处输入、探针可合成;现 `screen_flow_probe.gd:156-160` 已有 `Viewport.push_input(InputEventKey)` 合成先例,T0 复核该先例与所选路线的兼容性(InputMap action+轮询路线与合成探针的兼容性不预断,T0 定稿)。
2. 浮窗模态壳尺寸与位次(UiKit `modal_shell` 现行件域内,`ui_kit.gd:487`)。
1. Esc 输入接线方式(`_unhandled_input` vs InputMap 新 action vs 专用控制器)——约束:不吞他处输入、探针可合成(与 T0 spike 结论兼容;InputMap action+轮Polling 路线禁——与合成探针不兼容)。
2. 浮窗模态壳尺寸与位次(UiKit `modal_shell` 现行件域内)。
3. HUD 栏在顶栏的左右位次与间距(卡④场景屏顶栏域内)。
4. 「返回主菜单」复用卡④篝火同一处理函数(建议复用——动线同口;实现期定)。
5. 浮窗视觉面是否入 shot_checker 取样(T3 定:入=补截图段;不入=显式登记归目检并写明理由)。
6. 提交切分与 worktree 分支命名(车道铁律:主区直改+直提;大批按约定 worktree 非强制)。
5. 浮窗视觉面是否入 shot_checker 取样(T3 定:入=补截图段;不入=显式登记归目检并写明理由)。
6. 提交切分与 worktree 分支命名。
超出必须呈报:任何数值、事件名、接口名、文件职责、T 卡验收落点、三钮文案、Q1/Q2/Q3 裁定值。
## 10. 待裁点
## 10. 待裁点:零待裁点,开工门=U0
**本卡设计待裁点清零,开工门=U0。** Q1/Q2/Q3 均于 2026-10-18 裁定(下列为现行裁定留痕,非待裁点,实现期禁自行改值):
### Q1 · Esc 在子界面开态下的行为(已裁定 甲)
### Q1 · Esc 在子界面开态下的行为(必裁,未裁不开 T1)
**背景**:营地语境含「场景根态」与「子界面开态」(锻造/秘宝/生涯/天赋树/图鉴开着时)。澄清⑤裁决 9 未覆盖此分支。两案并列,**无推荐(用户令:不代裁)**:
| 案 | 内容 | 代价 |
|---|---|---|
| 甲 | 只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗(前提=各子界面自带返回钮闭环——待卡④ T3 承诺) | 语义最简;子界面里按 Esc 无反馈 |
| 甲 | 只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗(**前提=各子界面自带返回钮闭环——待卡④ T3 承诺,v1.1 括注**) | 语义最简;子界面里按 Esc 无反馈 |
| 乙 | 营地语境任意态响应 Esc:子界面开着时先关子界面回根态,再按才唤浮窗(单义化) | 多一层输入编排;与既有「子界面返回钮」形成双关闭路径 |
连带:判据形态随案(T1 已列);V1 按案分拆断言;契约 2 措辞裁后回写。
连带:判据形态随案(T1 已列);V1 按案分拆断言;契约 2 措辞裁后回写。裁决方式:随卡片评审定案;裁定落 T0 执行+实现报告留痕。
**裁定(2026-10-18)**:**甲**——只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗。代拍板留痕(用户令「事项按推荐的来」,本项无推荐案,取默认甲=语义最简;前提=卡④ T3 承诺各子界面自带返回钮闭环,卡④ v3.0 已在内;追认单可 veto)。T1 判据=营地场景屏 visible 且无营地子模态开态。裁定落 T0 执行+实现报告留痕。
**裁定(2026-10-18)**:**甲**——只营地根态响应 Esc;子界面开着时 Esc 不唤浮窗。代拍板留痕(用户令「事项按推荐的来」,本项无推荐案,取默认甲=语义最简;前提=卡④ T3 承诺各子界面自带返回钮闭环,卡④重新立卡时该承诺已在内;追认单可 veto)。T1 判据=营地场景屏 visible 且无营地子模态开态。
### Q2 · 浮窗的关闭/取消路径(已裁定 甲)
### Q2 · 浮窗的关闭/取消路径(必裁,未裁 T1 视图定不了稿——v1.1 新增)
**背景**:`UiKit.modal_shell`(`ui_kit.gd:487`)只产 dim+center+panel+VBox、**无内置关闭件**;契约 1 禁加项⇒浮窗只有三钮,无一「关闭」。而 §4 不做清单把「任意键关闭浮窗」划为用户未裁禁自扩——Esc 自身再按的行为恰好落在被 punt 的缝隙里:Q1 两案都不覆盖「浮窗已开时按 Esc」。若不裁且无关闭钮,玩家误开浮窗后离开营地只有「回主菜单/开设置/退游戏」三条路——体感陷阱,且与卡④子界面(生涯有返回钮)的可用性水准倒挂。
**背景**:`UiKit.modal_shell`(ui_kit.gd:456-475)只产 dim+center+panel+VBox、**无内置关闭件**;契约 1 禁加项⇒浮窗只有三钮,无一「关闭」。而 §4 不做清单把「任意键关闭浮窗」划为用户未裁禁自扩——**Esc 自身再按的行为恰好落在被 punt 的缝隙里**:Q1 两案都不覆盖「浮窗已开时按 Esc」。若不裁且无关闭钮,玩家误开浮窗后离开营地只有「回主菜单/开设置/退游戏」三条路——体感陷阱,且与卡④子界面(生涯有返回钮)的可用性水准倒挂。
| 案 | 内容 | 代价 |
|---|---|---|
@@ -296,15 +187,23 @@
| 乙 | 浮窗加关闭钮 | 触契约 1「禁加项」——须重新解释「三项」仅指功能项 |
| 丙 | 维持无关闭(三钮即全部出口,「返回主菜单」充当默认离开) | 误开浮窗后成本高;与子界面可用性水准倒挂 |
**裁定(2026-10-18)**:**甲**——再按 Esc 关浮窗(同键唤起/关闭单义切换)。推荐案,用户令按推荐执行。T1 接线含「浮窗已开时再按 Esc=关浮窗」;V1 断言按「根态唤起/再按关闭」两态分拆。裁定落 T1 视图与接线+V 表。
裁决方式:随卡片评审定案;裁定落 T1 视图与接线+V 表。
### Q3 · Esc 范围确认(已裁定 甲)
**裁定(2026-10-18)**:**甲**——再按 Esc 关浮窗(同键唤起/关闭单义切换)。推荐案,用户令按推荐执行。T1 接线含「浮窗已开时再按 Esc=关浮窗」;V1 断言按「根态唤起/再按关闭」两态分拆。
### Q3 · Esc 范围确认(顺带确认项,低成本高保险——v1.1 新增)
**背景**:契约 2「Esc 只在营地语境」是卡的从严收窄(澄清文档只裁「Esc 唤浮窗三项」、未裁范围——S1)。收窄方向保守且已自标「用户未裁」,但若用户本意是全局 Esc 菜单,范围锁死即返工。
| 案 | 内容 | 代价 |
|---|---|---|
| 甲(推荐) | 确认「Esc 浮窗只在营地语境」——契约 2 现文成立 | 无(一句话确认) |
| 乙 | 用户本意为全局(或更宽范围) | 本卡范围重开=契约 2/T1/V1 大改,且触 08:193 Beta 行口径 |
| 乙 | 用户本意为全局(或更宽范围) | 本卡范围重开=契约 2/T1/V1 大改,且触 08:192 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,447 +1,308 @@
# 需求卡片:营地场景图新建批(交互式营地 · 七物件绑定 · 四柜台拆解)· 营地交互重做卡④
- 版本:**v3.0(现行有效卡)**。留痕:2026-10-21 用户令退回美术设计段待闭合;2026-10-31 用户令重立——美术设计已闭合(样张过审+art-bible 条款版本),据 req-card 第〇步重立为现行有效卡,零设计待裁点。
- 来源:[需求澄清-营地交互重做-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.24 §6.2(营地场景 10 层口径)(**唯一事实源**:样张过审 2026-10-31 + art-bible.md v3.24 §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 同步;需求澄清为目标体验事实源)
- 版本:**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
- 归属:呈现层+美术线(`game/presentation/` + 场景素材)——营地交互重做五卡之四,**最大件**
- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁)
- 开工门:**零设计待裁点,开工门=U0**;编入迭代由 iter-plan 段发令,代码段按 `/iter` 开工,代码段开工门见 §0(不阻塞本卡作为有效卡与编迭代)
- 开工门:**前置条件销号后进代码实现**(设计前置闸纪律不变:设计定稿前禁 `/iter` 开本卡代码段——美术素材线按铁律 2 走自立批并行推进,不占迭代位);前置解决清单见下方
## 🔧 状态:现行有效卡(v3.0,2026-10-31 重立)
## 🔧 状态:已退回美术设计段 · 非有效卡(2026-10-21 用户令;美术设计闭合后重立卡,再谈编迭代)
本卡设计线已闭合,凭据见 §0「重立凭据」:样张过审(2026-10-31)+ art-bible v3.24 §6.2 条款版本齐备。设计待裁点清零、开工门=U0;未编入迭代,编入由 iter-plan 段发令。属呈现层+美术线,五卡之四。
**背景**:本卡是新内容+新美术件需求,按 2026-10-10 用户立规(req-card 设计前置检查),设计定稿前不进代码实现。v1.x 曾用「待裁点」覆盖设计缺项(渠道/规格/设计稿/参照物),违立规;v2.0 一度按「回设计段」移出序列;v2.1 一度把「批内解决」执行成「Agent 代跑设计稿」——**v2.2 用户令终订:本卡是批内成员,前置条件在批内登记、逐项销号;但由谁解决、何时解决由用户定,美术/设计线是用户自立批(铁律 2),Agent 不代跑不代产**。设计前置闸纪律不变(设计定稿前禁 `/iter` 开本卡代码段),执行方式是「批内销号」而非剔除,也非 Agent 代劳。
**归属纪律**:本卡只登记代码段开工门与已裁断。前置由谁解决、何时解决、设计稿与素材由谁产出由用户定——美术/设计线=用户自立批(铁律 2),Agent 不代跑、不代产、不自行开工设计稿。素材终稿落 `game/assets/art/` 属实现段 T1/`asset-ingest` 第 3 步,不属写卡门(用户 2026-10-31 令:只生成素材、不做后处理,开工时另发令)。
**前置条件销号清单**(五项重启条件转为批内登记项):
**批内批次次序(铁律 2:美术素材走自立批、不占迭代位;先产图后改代码)**:美术设计已闭合(样张过审)→ 场景素材后处理与入库(自立批,产物 `artwork/`→`game/assets/art/scene/`)→ 本卡代码段 `/iter`(与卡⑤ 同波)。工程面 ①②③ 代码已随迭代 33 合回(卡①②③ 已按吸收即死退役);④⑤ 未编排,编入哪一迭代由用户经迭代编排段发令。
| # | 前置条件 | 归属 | 状态(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 改版 |
## 0. 前置依赖与代码段开工门
**批内批次次序(铁律 2:美术素材走自立批、不占迭代位;先产图后改代码)**:P1–P4 销号(设计定稿)→ 场景图美术产出(自立批,素材线并行推进,产物归档 artwork/→game/assets/art/)→ P5 文档落文 → 本卡代码段 `/iter`(与 ⑤ 同波)。工程面 ①②③ 代码在美术线推进期间并行开发、先行交付(③ 进档落点按 Q3 裁定乙暂行接现役 CampOverlay,本卡落地时改挂)——**四卡同在批内,分波收口,不是剔除**。
### 0.1 重立凭据(已齐,非待裁点)
**归属纪律(2026-10-18 用户令订正,v2.2)**:本卡只负责**登记前置缺口与已有裁断**;前置条件由谁来解决、何时解决、设计稿/素材由谁产出,**由用户定**——美术/设计线是用户自立批(铁律 2),Agent 不代跑、不代产、不自行开工设计稿。本卡曾越权起草点选反馈设计稿 v0.1(2026-10-18),已按用户令撤回删除;Q8(出稿呈裁)仅是「若用户发令出稿时的产出方式」预裁,非开工授权。
req-card 第〇步+卡头 2026-10-21 退回令口径=美术设计闭合(样张过审+art-bible 条款版本)。两样已齐:
**已裁事项(2026-10-18 grilling 轮次)**:
- **样张过审**=用户 2026-10-31 裁定「保留全部待选稿、各素材第一张样本稿为终稿、每个都还可以接受」(清单 `artwork/candidates/_终稿裁定-2026-10-31.txt`),用户准备在游戏内做最终审核。
- **art-bible 条款版本**=`art-bible.md v3.24 §6.2`(营地场景 10 层口径;camp.md v2.2/camp-scene-prompts.md v1.2/asset-path-map.md/art-assets-checklist.md §3.5/评估报告同步)。
- Q4=甲:最近冒险条带随四柜台拆解撤下,生涯.md P6 同批注销(代拍板留痕);
- Q5=甲:ConfirmDialog 扩第三钮(继续上一段冒险/开始新冒险/取消,cancelled 恒=无变更退回营地);
- Q6=甲:Q1 裁 A 时过渡尺寸档=现役 1280 工程档+烛光黄 #F6C667/木色 #8A5A34 既有规格,终档归样张批冻结后置换(反哺点登记);
- Q8=甲:设计稿产出方式=批内出稿呈裁(方向稿先行纪律照旧——2~3 张低成本方向稿供选划,判完方向才精制);
- Q3 设计稿只覆盖根态点选反馈;进界面后的叠层规则随承载形态裁定派生(独立全屏页=场景根隐藏/单一内页切换=场景根留底)。
两样齐 ⇒ 重立卡判据齐,本卡为现行有效卡。P3/P5 等未销号项属**代码段开工门**,不阻塞重立卡。
**仍待用户裁**:Q1 美术渠道 A/B(我的推荐:**A · CC0 改色**——06:23 已有配色规格、成本低、方向稿不受「从零构图」拖累;B 依赖规格清单输入且周期长。你说过不替你选,但我把推荐摊开了,等你一句 A 或 B,方向稿当天就能出);Q2 参照物(你后续找)。
### 0.2 P1–P5 前置现状(已裁/已补项写进卡,不再当待裁点)
## 0. 前置依赖与并行性(批内视角,v2.1)
| # | 前置条件 | 归属 | 现状 | 落点 |
| -- | ------- | ---- | ---- | ---- |
| 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 | 点选反馈设计稿(悬停高亮/提示文案/可点区域判定) | 用户线 | **代码段开工门**:camp.md v2.2 已定四态规格;设计稿细化未受命开工,Agent 不代跑不代产 | §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 营地条款落文 | 文档批(用户发令) | **代码段开工门**:camp.md v2.2/art-bible v3.24 §6.2 已先行落文新形态;实装状态回填与 §7.5/§2.8 同步归文档批,实现批禁写 `design/` | §5 反哺点 |
> 本卡在批内,前置条件解决中(见卡头销号清单)——本节描述批内并行关系,非排期承诺。
### 0.3 代码段 `/iter` 开工门(不是设计待裁点,不阻塞重立卡与编迭代)
下列项属代码段开工门;未销号即需开工对应任务段=§8 L3 停机呈报,禁批内自补、禁 T0 现场发挥:
1. **P3 点选反馈设计稿**:悬停高亮/提示文案/可点区域判定三项细化稿(camp.md v2.2 已定四态规格与名牌参数,设计稿只细化呈现,不阻塞本卡成立)。
2. **P5 GDD/art-bible 条款落文**:文档批对实装状态、§7.5/§2.8 的回填(实现批禁写 `design/`,逐条列 `reports/iter<N>-反哺点-<日期>.md`)。
3. **camp-scene-prompts.md §5 五个待裁点**:帐篷尺寸(现 300×170 待重定)/门扇高宽(现 240×220,围墙带仅 43px 高、叠放关系待裁)/布告板位置(现 y330 悬空、建议 (845,268,130,140) 挂回围墙带)/描边颜色追认(现按奶油色、去底技术前提,改深灰褐须换去底方案)/营地环境子板色值(art-bible §4.1 数值单点,待作者拍板)。五点阻塞坐标表定稿与接线,不阻塞出图(样张已过审)。
4. **十张终稿后处理与入库**:终稿此刻=原始候选图本身(带通道水印、浅灰不透明底、画布 2560×1600 或 1024×1024),未做去底/擦水印/降采样/裁围墙细条;落 `game/assets/art/scene/` 属实现段 T1/`asset-ingest` 第 3 步,用户 2026-10-31 令只生成素材不做后续工序,开工时另发令。
### 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` 门扇 | 半开双扇,叠在门洞上(高宽待 §0.3 裁) | 是 |
| 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 反哺点已注)。
- 卡③(选档界面)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 反哺点已注)。
## 1. 目标与完成定义
**目标(澄清①一句提炼照录)**:营地首页从「文字按钮菜单 + 列表式覆盖层」改为「**一张可点击的营地场景图**」——点场景中的具体物件进入对应功能界面。用户原话照录:「我是希望有一个营地地图的游戏画面;或者是一张营地的图片,跟 UI 的交互是点击图片中的某一处地方,然后再进入界面。不是完全普通的那种 UI 设计,不是各种框框的……我点击某些具体的东西之后,就可以进入对应的操作界面。」(称呼订正:「它就是一个营地的画面;并不是一张地图。」)
**目标(澄清①一句提炼照录)**:营地首页从「文字按钮菜单 + 列表式覆盖层」改为「**一张可点击的营地场景图**」——点场景中的具体物件进入对应功能界面。用户原话照录:「我是希望有一个营地地图的游戏画面;或者是一张营地的图片,跟 UI 的交互是点击图片中的某一处地方,然后再进入界面。不是完全普通的那种 UI 设计,不是各种框框的……我点击某些具体的东西之后,就可以进入对应的操作界面。」(称呼订正:「它就是一个营地的画面;并不是一张地图。」)
**七物件绑定(camp.md v2.2 §场景构成与七物件绑定,逐一落地)**:
**七物件绑定(澄清④结构树照录,逐一落地)**:
| 物件 | 进入 | 备注(现状定性+现行约束) |
| ---- | ---- | ------------------------ |
| 大门(半开门扇,门洞内一条通向远处的小路) | 冒险(选路屏/战斗屏已实现不动;断点弹窗移位) | 入口新建+动线迁移;点大门永远先出确认(有断点=三出口,无=是否开始新冒险) |
| 锻炉·铁砧 | 锻造工坊 | 界面已实现·入口改挂;未解锁=禁用态(降明度+去饱和) |
| 宝箱 | 秘宝匣 | 界面已实现·入口改挂;未解锁=禁用态 |
| 帐篷旁笔记本 | 生涯记录 | 界面已实现·入口改挂;生涯页返回钮文案禁含「营地」字样 |
| 木桩 | 树淬炼天赋树 | 界面已实现·入口改挂 |
| 布告板/悬赏板 | 奖励格图鉴 | 界面已实现·入口改挂;内容冻结未激活,点进看占位(**不是禁用态**) |
| 篝火 | 离开营地/回主菜单 | 新建小动线;**必须二次确认**;命中区只含火堆、不含火焰 |
| 帐篷 | — | 承载件不可点;落地尺寸与占位范围待作者重定(代码段开工门,camp-scene-prompts §5) |
| 物件 | 绑定目标 | 现状定性 |
| ------- | -------------------------- | ------------ |
| 营地大门 | 冒险(选路屏/战斗屏已实现,不动;断点弹窗保留移位) | 入口新建+动线迁徒 |
| 锻炉·铁砧 | 锻造工坊 | 界面已实现 · 入口改挂 |
| 宝箱 | 秘宝匣 | 界面已实现 · 入口改挂 |
| 床铺旁笔记本 | 生涯记录 | 界面已实现 · 入口改挂 |
| 木桩 | 树淬炼天赋树 | 界面已实现 · 入口改挂 |
| 布告板/悬赏板 | 奖励格图鉴 | 界面已实现 · 入口改挂 |
| 篝火 | 离开营地/回主菜单 | 新建小动线 |
**纵深稿(用户原话照录)**:「远景是天空;中景是一个围栏,还有营地大门;近景中间是一个篝火;左边是锻炉铁砧;右边是我们的床铺,宝箱等。」(承载件落地为帐篷,见 §0.4 z4。)
**纵深稿(用户原话照录)**:「远景是天空;中景是一个围栏,还有营地大门;近景中间是一个篝火;左边是锻炉铁砧;右边是我们的床铺,宝箱等。」
**大门两分支(裁决 5 照录,Q5 已裁=甲)**:有未完冒险 → ConfirmDialog 三出口「继续上一段冒险/开始新冒险/取消」;无未完冒险 → 「是否开始新冒险:是/否」。**点大门永远先出确认,不直接进冒险**;cancelled 恒=无变更退回营地。
**大门两分支(裁决 5 照录)**:有未完冒险 → 弹「继续上一段冒险 / 开始新冒险」;无未完冒险 → 弹「是否开始新冒险:是/否」。**点大门永远先出确认,不直接进冒险**(「断点续玩也是开始冒险的两个分支之一……它算是开始冒险的一个子节点」)。**「有断点」分支的三出口弹窗形态待裁(Q5)**——现役 ConfirmDialog 双钮表达不了两个肯定性动作。
**钥石余额(裁决 10 照录)**:场景**顶部小 HUD 栏**(高 48px 全宽窄条、浮层覆盖不挤压画面;承载落卡⑤)。
**钥石余额(裁决 10 照录)**:场景**顶部小 HUD 栏**(用户原话「先按顶部小HUD栏设计」——provisional 措辞留痕;承载落卡⑤)。
**相对现状,新增了什么**:
1. 交互式营地场景图(10 层场景素材+场景屏+七物件命中区与点选交互)——从零新建;
2. 现四柜台覆盖层(CampOverlay)拆解:锻造工坊/秘宝匣/天赋树/奖励格图鉴四界面抽为独立可开界面,入口改挂场景物件;生涯页入口自主菜单改挂帐篷旁笔记本;
3. 大门动线(开始冒险/继续上局两分支+断点确认弹窗从主菜单移位);
4. 篝火回主菜单小动线(带二次确认);场景屏顶栏预留位(卡⑤ HUD);
5. camp 截图断言段与六探针营地段的迁移(**现无 camp 逐像素 golden 基线**——见契约 10)。
1. 交互式营地场景图(场景素材+场景屏+七物件命中区与点选交互)——从零新建;
2. 现四柜台覆盖层(CampOverlay)拆解:锻造工坊/秘宝匣/天赋树/奖励格图鉴四界面抽为独立可开界面,入口改挂场景物件;生涯页入口自主菜单改挂笔记本;
3. 大门动线(开始冒险/继续上局两分支+断点确认弹窗从主菜单移位);
4. 篝火回主菜单小动线;场景屏顶栏预留位(卡⑤ HUD);
5. camp 截图断言段与六探针营地段的迁移(**现无 camp 逐像素 golden 基线**——v1.1 订正,见契约 10)。
**完成定义**:
1. 营地首页=可点击场景图(10 层按 §0.4 铺底、门洞留空);七物件绑定逐一在役,点各物件进对应界面;
2. 四柜台拆解完毕:CampOverlay 覆盖层形态退役,五界面(锻造/秘宝/生涯/天赋树/图鉴)经新入口可达且**功能与写口链路零回归**(presenter 改造=承载面迁移的一部分——见契约 4);
3. 大门两分支确认弹窗在役;点大门不直接进冒险;cancelled 无变更退回;
4. 篝火经二次确认可回主菜单;场景屏顶栏预留位就绪(卡⑤ 联验);
5. camp 截图=场景图形态(迭代内验收=截图对比,澄清⑥);探针断言迁移完毕;
6. 美术约束(48 色板/禁入带/语义色/WCAG)入闸或登记缺口;**用户目检项登记 07**(生命周期末步,不阻塞);
1. 营地首页=可点击场景图;七物件绑定逐一在役,点各物件进对应界面;
2. 四柜台拆解完毕:CampOverlay 覆盖层形态退役,五界面(锻造/秘宝/生涯/天赋树/图鉴)经新入口可达且**功能与写口链路零回归**(presenter 改造=承载面迁移的一部分——见契约 4);
3. 大门两分支确认弹窗在役;点大门不直接进冒险;
4. 篝火可回主菜单;场景屏顶栏预留位就绪(卡⑤联验);
5. camp 截图=场景图形态(迭代内验收=截图对比,澄清⑥);探针断言迁移完毕;
6. 美术约束(48 色板/禁入带/语义色/WCAG)入闸或登记缺口;**用户目检项登记 07**(生命周期末步,不阻塞);
7. 批末重闸按改动域选档全绿;三份 `reports/` 产出物写齐(T6)。
## 2. 现状事实(开工日 T0 复核行号)
## 2. 现状事实(2026-10-18 实查;开工日 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` 各处 |
| F8 | 探针面营地段(全部随本批迁移):ui_probe(营地入口+余额+秘宝匣 12 行断言 :28-55,深员 `_balance_label`/`_tree_buy_btns`/`_workshop_rows` :39-52)、ui_click_probe(营地购买全链 :53-127;**断点确认段 :500-528**〔经 lvbtn 驱动 ConfirmDialog 取消/开新冒险——被卡②撤钮+本批弹窗移位双杀〕)、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 现行 **camp.md v2.2** 已落文可点击场景图形态(定位/场景构成与七物件绑定/10 层拆分/点选反馈四态/顶栏 48px/叠层与开合);本批实现=**对齐** v2.2,旧三柜台形态已由 v2.2 取代,本批只需回填实装状态与目检结论 | `design/gdd/ux/camp.md:10-51` |
| F10 | art-bible 现行 **v3.24 §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 | 贴图重构批搁置未废:营地与元进度件终稿置换(06:21-27)等交互重做定形后再议(澄清③1/§⑧5)——本批不清偿该债;四柜台拆解后原「柜台场景贴图」债对象变化,随该批重新评估 | `design/gdd/06-待办清单.md:21-27`;`需求澄清-营地交互重做-2026-10-18.md` §③1/§⑧5 |
| F13 | 营地底栏「最近冒险」条带与生涯历史回看同源(同一份 `recent_summaries`),其去留=生涯.md P6 待裁点(期二必答)——CampOverlay 拆解后该条带无处挂,**Q4 已裁=甲**(随四柜台拆解撤下,逐局历史回看归生涯,生涯.md P6 同批注销) | `camp_overlay_view.gd:186-189`/:536-549;`生涯.md:69` |
| F14 | 素材线纪律:`artwork/` 不入 git(`.gitignore:51` 忽略行)——批次 worktree 内无该目录、主工作区 D:/code/g-plan2 实体存在(在途工作区);涉素材脚本须传主区绝对路径否则静默 0 张;素材替换前先归档旧档;终稿归 `game/assets/art/scene/`,消费常量 `UiKit.TEX_CAMP_*`(asset-path-map.md §3/art-assets-checklist.md §3.5) | `AGENTS.md:32`;`.gitignore:51`;art-bible §8.3 归档纪律 |
| 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.24 §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` |
| # | 事实 | 出处 |
| --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| 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` |
## 3. 设计契约(红线,违反 = L3 停机呈报)
## 3. 设计契约(红线,违反 = L3 停机呈报)
🔴 **契约 1 · 交互式场景图形态**:营地首页=一张可点击的营地场景图,点物件进界面(澄清①)。**禁退回文字按钮列表+面板覆盖层形态**(澄清②反参照:「完全普通的那种 UI 设计」「各种框框」——用户判现状「交互流程完全错误」)。
🔴 **契约 1 · 交互式场景图形态**:营地首页=一张可点击的营地场景图,点物件进界面(澄清①)。**禁退回文字按钮列表+面板覆盖层形态**(澄清②反参照:「完全普通的那种 UI 设计」「各种框框」——用户判现状「交互流程完全错误」)。
🔴 **契约 2 · 七物件绑定逐一落地**:大门/锻炉铁砧/宝箱/帐篷旁笔记本/木桩/布告板/篝火七个绑定(§1 表)缺一不可;禁合并、禁以「其他入口」替代(如顶栏文字钮)。帐篷为承载件、不可点。
🔴 **契约 2 · 七物件绑定逐一落地**:大门/锻炉铁砧/宝箱/笔记本/木桩/布告板/篝火七个绑定(§1 表)缺一不可;禁合并、禁以「其他入口」替代(如顶栏文字钮)。
🔴 **契约 3 · 大门两分支**(裁决 5,Q5 已裁=甲):有未完冒险→ConfirmDialog 三出口「继续上一段冒险/开始新冒险/取消」;无→「是否开始新冒险:是/否」弹窗。**点大门永远先出确认,不直接进冒险**;cancelled 恒=无变更退回营地;弹窗类=ConfirmDialog(三钮化+消费方编排=T4,卡③ 契约 3 同款互指)。
🔴 **契约 3 · 大门两分支**(裁决 5):有未完冒险→「继续上一段冒险/开始新冒险」二选一弹窗(**三出口形态=Q5 待裁**);无→「是否开始新冒险:是/否」弹窗。**点大门永远先出确认,不直接进冒险**;弹窗类=ConfirmDialog(三钮化+消费方编排=T4,卡③ 契约 3 同款互指)。
🔴 **契约 4 · 已实现界面只改挂不重做+presenter 承接面**:锻造工坊/秘宝匣/天赋树/图鉴/生涯五界面「界面已实现 · 入口改挂」——功能、行板、写口链路零重设计(拆解=承载面迁移)。**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 承接面(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`(与其余六口不一致)——**保持原样,禁「顺手统一」防行为漂移**。
🔴 **契约 5 · 图鉴内容保持挂起**:只改入口(布告板),不激活图鉴内容(F11:2026-10-05 用户令冻结,重启须用户发令);布告板点开的图鉴=现行占位态(T3 定义占位壳),不是禁用态(camp.md v2.2)。
🔴 **契约 5 · 图鉴内容保持挂起**:只改入口(布告板),不激活图鉴内容(F11:2026-10-05 用户令冻结,重启须用户发令);布告板点开的图鉴=现行占位态(T3 定义占位壳)。
🔴 **契约 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。篝火命中矩形只取下半(火堆),火焰只展示。
🔴 **契约 6 · 冒险进行中不开营地**(澄清③6):营地是存档语境(局外)枢纽,现状口径延续;局内只读面=状态面板(在役,本批零改动——其「营地三柜台进度」文案若因拆解失义,列反哺点归文档批订正)。
🔴 **契约 8 · 像素规格不硬定**:尺寸档/色板/明度档只写指针(Q6 甲过渡口径=1280 工程档+烛光黄/木色,落 art-bible §6.2/art-assets-checklist §3.5,F16);卡内禁自定像素规格数值;终档置换归反哺点,执行归用户线;禁批内自补、禁 T0 现场发挥。
🔴 **契约 7 · 美术硬约束**:48 色板、HSV 300°–345° 禁入带、语义色纪律、WCAG ≥4.5:1(F15);场景素材全局纹理过滤=Nearest(project.godot 现行默认,像素纪律)。
🔴 **契约 9 · 迭代内验收=截图对比+终稿落盘口径**(澄清⑥):camp 截图须为场景图形态;用户实机目检=生命周期最后一步、统一进行、**不阻塞迭代**——目检项登记 07 清单即完成义务。**T1 终稿落 `game/assets/art/scene/` 的「验收」口径=迭代内验收**(截图对比+shot_checker 机检+样张过审留痕)——营地屏整屏样张按既定排队行延后(§0.5),不构成对 art-bible §7.5「前置」条的违背(§5 反哺点注)。
🔴 **契约 8 · 像素规格不硬定**:尺寸档/色板/明度档只写指针(战斗一屏样张批冻结的规格清单,F16);卡内禁自定像素规格数值;规格清单未产出时的输入缺口=Q6 裁定(禁批内自补、禁 T0 现场发挥)。
🔴 **契约 10 · 探针断言迁移契约**(属仓库既有测试纪律的卡内成文,非用户裁决):F8 全量位点逐点显式迁移并留痕;**现无 camp 逐像素 golden 基线**(F17:golden 现役仅棋盘三张+menu_boot)——本批不建 camp golden(「把不存在的东西列进迁移清单」禁),camp 截图验收=shot_probe 出图+shot_checker 语义断言段;若要新建 camp golden 须另裁登记(L3)。
🔴 **契约 9 · 迭代内验收=截图对比+终稿落盘口径(v1.1 补)**(澄清⑥):camp 截图须为场景图形态;用户实机目检=生命周期最后一步、统一进行、**不阻塞迭代**——目检项登记 07 清单即完成义务。**T1 终稿落 `game/assets/art/` 的「验收」口径=迭代内验收**(截图对比+shot_checker 机检+方向稿用户选划)——营地屏整屏样张按既定排队行延后(§0),不构成对 art-bible §7.5「前置」条的违背(§5 反哺点注)。
🔴 **契约 11 · 拆分边界纪律**(结构类卡必填,判据权威=`design/engineering/code-conventions.md` §1.1,本卡写条款、不复制定文):本卡含「四柜台拆解」,拆分沿**职责轴**不沿阈值轴——每个拆出单元(锻造/秘宝/天赋树/图鉴四界面 view)须有可陈述的职责语句与单一变化原因、须有集体身份(命不出名字、只能说「剩下的成员」的打包=凑计数袋,禁);「过阈值」只许作为发现信号,作为拆分或收拢的动机即违规;按纪律拆不出内聚单元 → 停卡呈报走豁免/还债通道,禁硬拆凑绿(写进 §8 L3)。实现报告逐件一行承载职责语句。
🔴 **契约 12 · 禁为机检文本保留无效成员**(重构类卡必填条款,与 code-conventions §1.1 同款):禁止为迎合机检消息文本(含计数)而保留或新增无效成员/别名;机检键与卡片契约互斥时,实现段一律停卡呈报,不得自造第三条路。
🔴 **契约 10 · 探针断言迁移契约(v1.1 订正,属仓库既有测试纪律的卡内成文,非用户裁决)**:F8 全量位点逐点显式迁移并留痕;**现无 camp 逐像素 golden 基线**(F17:golden 现役仅棋盘三张+menu_boot)——本批不建 camp golden(「把不存在的东西列进迁移清单」禁),camp 截图验收=shot_probe 出图+shot_checker 语义断言段;若要新建 camp golden 须另裁登记(L3)。
## 4. 范围边界
**做**:场景屏+10 层场景素材铺底+七物件命中区与点选交互(反馈细节按 §0.3 P3 设计稿、四态规格按 camp.md v2.2);四柜台拆解与五界面入口改挂(含 presenter 承接面改造);大门动线两分支+断点弹窗移位;篝火回主菜单小动线(带二次确认);场景屏顶栏预留位;断言/探针迁移;反哺点清单。
**做**:场景素材产出(渠道按 Q1 裁定);场景屏+七物件命中区与点选交互(反馈细节按 Q3 设计稿);四柜台拆解与五界面入口改挂(含 presenter 承接面改造);大门动线两分支+断点弹窗移位;篝火回主菜单;场景屏顶栏预留位;断言/探针迁移;反哺点清单。
**不做**(明示去向):
- **不做贴图重构批**(澄清③1):柜台场景贴图/钥石顶栏图标/永久强化条目图标的达标化置换——搁置未废,待交互重做完形后重新评估立项(F12);
- **不做贴图重构批**(澄清③1):柜台场景贴图/钥石顶栏图标/永久强化条目图标的达标化置换——搁置未废,待交互重做完形后重新评估立项(F12);
- 不激活图鉴内容(契约 5);
- 不改五界面功能与写口链路(契约 4);
- 不改冒险屏/选路屏/战斗屏本体(F7 已实现不动);
- 不做整屏样张闸、不替代样张批、不新建 camp golden(§0.5/契约 10);
- 不改冒险屏/选路屏/战斗屏本体(F7 已实现不动);
- 不做整屏样张闸、不替代样张批、不新建 camp golden(§0/契约 10);
- 局内状态面板零改动(契约 6);
- 素材后处理与入库属实现段 T1/`asset-ingest` 第 3 步、开工另发令(§0.3-4),不属写卡门;
- ESC 浮窗与顶栏 HUD 实现 → 卡⑤(本卡只留顶栏位+定义刷新单口);
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①。
- 选档界面/主菜单/数据层 → 卡③/卡②/卡①。
## 5. 关联文档同步面
> **现行口径**:实现批禁写 `design/` 整目录与根规则文件,唯一可写目录=`reports/`(+`game/` 实施本体);设计权威文档(GDD/art-bible)与机械面文档(roadmap/体验验证清单/README)对代码实现批一律不直改,逐条列进 `reports/iter<N>-反哺点-<日期>.md`,用户裁决后归文档批落文;本卡全表义务格一律为「反哺点 · 列清单」。camp.md v2.2/art-bible v3.24 §6.2 已先行落文 10 层新形态,本批实现=对齐现行条款,反哺义务为**实装状态回填+目检结论**,非形态改版。美术素材产物按素材线纪律落 `artwork/`(在途)→ `game/assets/art/scene/`(终稿),不随 git 合并(F14)。
> **v1.3 口径**:本批禁写 `design/` 整目录与根规则文件,唯一可写目录 = `reports/`;下表一律执行为列进反哺点清单。美术素材产物按素材线纪律落 `artwork/`(在途)→ `game/assets/art/`(终稿),不随 git 合并(F14)。
| 文档 | 关联点 | 同步义务 |
|---|---|---|
| `design/gdd/ux/camp.md` v2.2 | §定位/§场景构成与七物件绑定/§点选反馈/§顶栏/§叠层与开合:新形态已落文,本批实现后回填实装状态、样张过审留痕、实机目检结论 | 反哺点 · 列清单(实现批禁写 `design/`) |
| `design/art/art-bible.md` v3.24 | §6.2 营地场景 10 层口径已落文;§7.5 营地界面画法、§2.8 承载元素、§1.4 营地屏整屏样张排队行注记(本批不跑样张闸) | 反哺点 · 列清单(权威面零直改,过用户裁决后归文档批) |
| `design/gdd/systems/跨局循环/生涯.md` | :69 与营地边界表(条带 `_rebuild_recent` 随 CampOverlay 拆解去向=Q4 已裁甲);:63 图鉴挂起条(入口改挂注记) | 反哺点 · 列清单 |
| `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/08-Alpha版本标准.md` | 「三 · 界面」营地行(:104)形态注记改写——状态列可改;注记改写列反哺点;增删行须用户裁(三卡统一口径) | 反哺点 · 列清单 |
| `design/gdd/06-待办清单.md` | 本卡登记条;UI 贴图重构批条(:21-27)注记「四柜台对象变化、重评待交互重做完形」;图鉴挂起条注记 | 反哺点 · 列清单(实现批禁写待办清单) |
| `design/gdd/07-体验验证清单.md` | 新增实机目检条(场景观感/七物件辨识与点选反馈/大门两分支/篝火动线)——登记不阻塞 | 反哺点 · 列清单(实现批禁写体验验证清单,入册条目由文档批落) |
| `roadmap.md` | 迭代行编入/状态刷新 | 反哺点 · 列清单(实现批禁写 roadmap) |
| `game/tests/README.md` | 能力行入表(§7 对照表「能力行」列定名) | 写卡段定名(本卡只写卡内能力行文字,README 由主 Agent 统一收口);实现批只核对名实一致,禁写 |
| `game/presentation/*`、`game/smoke/*`、`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)+七物件命中区+点选反馈四态+名牌 | 行为改动 | 新建 | V1/V2/V9/V10 |
| `game/data/tables/camp_scene_layout.tres` | 10 层贴图矩形/命中矩形/z 序/门洞缺口坐标(数值单一事实源 `data/tables/`,坐标最终值随 §0.3 代码段开工门裁定落入,本卡不硬定) | 行为改动 | 新建 | V1/V2/V9 |
| `game/presentation/views/camp_refresh_bus.gd` | 营地刷新单口:各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成(卡⑤ 同口挂接) | 行为改动 | 新建 | 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/presenters/camp_shop_presenter.gd` | 投影目标改线+七写口尾刷新改路由+open/close 编排迁位(契约 4) | 行为改动 | 复用既有(改) | V4/V8/B1 |
| `game/presentation/core/camp_flow_context.gd` | 类型化字段语义订正 | 行为改动 | 复用既有(改) | V4/B1 |
| `main.gd`(组合根) | 断点弹窗移位+ConfirmDialog 三钮消费方编排+营地入口改挂+篝火动线+开层互斥/关层收闭 | 行为改动 | 复用既有(改) | V3/V4/V7/B1 |
| `game/assets/art/scene/scene_camp_*.png`(10 张) | 10 层场景素材终稿(asset-ingest 第 3 步拷入,命名对齐 `UiKit.TEX_CAMP_*`) | 非行为改动(美术资源) | asset-ingest | V1/V10 |
| `game/smoke/shot_probe.gd` | camp 截图路径改场景图+收闭改接篝火动线 | 非行为改动(测试面) | 复用既有(改) | V1 |
| `game/smoke/ui_click_probe.gd` | 七物件可达+大门两分支+断点确认段改走大门+写口链迁移+深员改指 | 非行为改动(测试面) | 复用既有(改) | V2/V3/V4 |
| `game/smoke/ui_probe.gd` | 营地入口/余额/秘宝匣深员改指新界面 | 非行为改动(测试面) | 复用既有(改) | V4 |
| `game/smoke/screen_flow_probe.gd` | 营地键新语义+回退段改新场景根 closed/篝火动线 | 非行为改动(测试面) | 复用既有(改) | V7 |
| `game/smoke/ui_struct_probe.gd` | 反参照结构禁词+生涯段驱动改接+图鉴占位锚定 | 非行为改动(测试面) | 复用既有(改) | V5/V6/V9 |
| `game/smoke/ui_contrast_probe.gd` | 营地令牌段核签(CAMP_HEADER_BAND/CAMP_ROW_PLATE 消费判定) | 非行为改动(测试面) | 复用既有(改) | V10 |
| `game/smoke/smoke_all.gd` | V2 实例化/V3g 模态开合改指+`camp_overlay_view.gd` 源码断言段 :6469-6475 重写或注销 | 非行为改动(测试面) | 复用既有(改) | 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 单点读取;坐标最终值随 §0.3 代码段开工门(camp-scene-prompts §5 五裁点)裁定落入,本卡只定结构键不定值 |
| `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) |
| `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,不凭旧读数放行 |
| 四界面 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 开工门落入 |
### 存量触面一查
本卡触碰存量文件:`camp_screen.gd`/`camp_shop_presenter.gd`/`camp_flow_context.gd`/`confirm_dialog.gd`/`career_overlay.gd`/`camp_overlay_view.gd`(退役)/`main.gd`/探针七件/`forge_workbench_test.gd`。**T0 读数步骤写明「S13 键较 `tools/gdstyle_baseline.txt` 登记值只降不升」的预期与达成手段**:CampOverlay 拆解=删四柜台代码(键只降);`camp_shop_presenter.gd` 改造=投影目标改线、不新增公开方法/成员;`main.gd` 组合根=断点弹窗移位+消费方编排(新增私有状态量一枚,S13 类级键只降不升);探针改接=替换断言段、不新增扫描面键。任何 S13 键被迫上升=§8 L3 停卡。
### 指标例外通道
现预算内,无需例外。若场景视图十层句柄+七命中区+反馈态实测超 15 类变量,或组合根成员超基线,设「指标例外申报」节——键名+理由+用户特批落基线;未申报的超预算面进实现段=停卡退回写卡段(写进 §8 L3)。
| `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/*` | 实现/断言/终稿素材本体 | 实施本体(可写) |
## 6. 任务卡
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。步骤用 `- [ ]` 复选框记步,一步=一个动作+一个可核查结果;每卡声明「取用/产出」接口块,后卡引用的名字与早卡定义逐字一致;禁占位待定句式(不决定任何事的行不留)。**天然切分点=T1 出口**(场景素材归档齐)——美术线与代码线可分批交付(用户批次归属裁);若单批跑超迭代盒,T3 末(四柜台拆解完)为次切分点。
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核全部行号。**估时主变量=美术渠道(Q1 待裁)、点选反馈设计稿往返(Q3)与规格输入(Q6)**。
### T0 事实坐实与设计输入齐备检查(≈0.5d)
- 取用:待办清单条目状态(文档设计已闭合+美术设计已闭合+已写卡)、§0 重立凭据、art-bible v3.24 §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:P3/P5/camp-scene-prompts §5 五裁点/素材后处理入库)状态逐项核——未销号项对应的任务段禁开工(缺输入=呈报,禁批内自补)。
- [ ] 规格清单依赖核检:样张批规格清单产出时点 vs 本批排期——按 Q6 甲过渡口径执行(1280 工程档+烛光黄/木色,终档置换归反哺点),禁 T0 现场发挥。
- [ ] 跑 `bash tools/gdstyle.sh game` 开发期局部读数,记录 `camp_screen.gd`/`camp_shop_presenter.gd`/`main.gd` 当前行数、类变量、公开方法数;登记 S13 基线键(预期只降不升)。本步为最窄确认,不构成验收。
- [ ] 与卡③ 对齐 ConfirmDialog 消费方编排机制(T4 互指)、与卡⑤ 对齐顶栏位与营地刷新单口(§0.5 跨卡接口)。
- 产出:基线 commit、S13 实数、设计凭据核对表、代码段开工门未销号清单;后续卡只按本卡契约施工。
- 复核 §2 全部行号;四柜台界面清单与探针面清单(F8)逐点过;
- 设计输入齐备检查:Q1(美术渠道)/Q2(参照物)/Q3(点选反馈细节)/Q4(条带去留)/Q5(三出口弹窗)/Q6(规格缺口)状态逐项核——**未裁项对应的任务段禁开工**(缺输入=呈报,禁批内自补);
- 规格清单依赖核检:战斗一屏样张批(06 待设计)产出时点 vs 本批排期——按 Q6 裁定执行(禁 T0 现场发挥);
- 与卡③对齐 ConfirmDialog 消费方编排机制(T4 互指)、与卡⑤对齐顶栏位与刷新单口(§0 跨卡接口)。
### T1 场景素材终稿录入(asset-ingest 第 3 步,≈1–1.5d,用户另发令)
### T1 场景美术产出(≈2–4d,渠道 A/B 待裁 Q1)
- 取用: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 八物件层),确认各取第一张样本稿为终稿、其余候选保留不删。
- [ ] 用户发令后做后处理:去底转透明(bg 不去底、全幅不透明)/擦通道水印/降采样到 1280×800(整数倍)/围墙层裁细条 (0,240,1280,70) 不做全幅/色板量化/四联底测试条——工具清单见 `design/art/art-pipeline-tools.md`;**用户 2026-10-31 令只生成素材不做后续工序,本步须开工另发令**。
- [ ] 产物落盘:`artwork/`(在途,主区绝对路径)→ 验收后终稿 `game/assets/art/scene/`;替换先归档旧档;命名 `scene_camp_<键>.png` 对齐消费常量 `UiKit.TEX_CAMP_*`(asset-path-map.md §3/art-assets-checklist.md §3.5,先定资源路径常量、素材名跟它走,防断链)。
- [ ] 美术硬约束入产线(契约 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 可挂接。
- 按纵深稿构图(远景天空/中景围栏+大门/近景篝火居中/左锻炉铁砧/右床铺+宝箱)出场景图;七物件可辨性=第一合格线(玩家一眼找到点哪);
- 美术硬约束入产线(契约 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 张低成本方向稿供用户选划,判完方向才精制(样张卡「方向稿先行」同型纪律;选划记录三段表进开工单)。⚠ 本条为**本卡自我从严的执行纪律**,非用户新裁决——用户若要以单路线直接精制,从其裁。
### T2 场景视图与点选交互(≈1.5–2d)
- 取用:T1 十层终稿 `UiKit.TEX_CAMP_*`、`camp_scene_layout.tres` 坐标结构键、camp.md v2.2 点选反馈四态规格、§0.3 P3 设计稿(代码段开工门)。
- [ ] 在 `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;篝火命中矩形只取下半(火堆),火焰只展示。
- [ ] 实现点选反馈四态 `set_feedback_state()`(零新素材、全程序化):悬停=轮廓亮边+浮动(整像素吸附)+名牌(下方 8px 居中、字号 14、对比 ≥4.5:1)/按下=位移 1px/禁用=降明度+去饱和(仅锻炉、宝箱)/已解锁=常态;提示文案与可点区域视觉按 §0.3 P3 设计稿销号后落(未销号=本段禁开工)。
- [ ] 场景屏顶栏预留位 `set_hud_band()`(高 48px 浮层覆盖、不挤压画面,卡⑤ 填值);刷新入口=本卡 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 按接口块接线。
- 场景屏承载(camp_screen 屏壳改造 vs 新屏壳——§9 拍板):场景图铺底+七物件命中区;
- 点选交互:命中区判定+反馈形态按 Q3 设计稿(悬停高亮/提示文案/可点区域判定三项);
- **场景屏顶栏预留位(v1.1 注明)**:卡⑤ HUD 落位;**刷新入口=本卡 T3 定义的营地刷新单口**(卡⑤同口挂接);
- **叠层规则显式派生(v1.1 补)**:随 §9 第 2 条承载形态裁定派生并写入 V2 断言——独立全屏页=场景根隐藏(生涯先例);单一内页切换=场景根留底;「缩放虚化」是两选项之外的第三形态(涉新演出面+素材),禁批内自选(若设计稿/用户想要,升格裁点);
- 键盘焦点/手柄不涉(08:191-192 排 Beta;ESC 属卡⑤用户明示裁决面)。
### T3 四柜台拆解与入口改挂(≈2–2.5d)
- 取用: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`。
- [ ] **CampShopPresenter 承接面改造(契约 4)**:投影目标改线(五界面/场景根)、七写口尾刷新改路由(经营地刷新单口——**各写口尾→现开界面刷新+场景根 HUD 刷新一闸完成**)、open/close 编排从 campbtn 迁位到卡③ 进档动作、CampFlowContext 字段语义订正、探针缝保位(main.gd:1163-1171);`on_camp_attune_toggle`(:98-106)尾只 refresh_camp、不调 `_refresh_presentations` 保持原样。
- [ ] 新建 `camp_refresh_bus.gd` 实现 `CampRefreshBus.refresh(camp_data: Dictionary) -> void`(T0 接口块);卡⑤ HUD 刷新挂此单口,非已退役的 `refresh_camp`。
- [ ] **图鉴占位态(契约 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 按接口块消费。
- 锻造工坊/秘宝匣/天赋树/图鉴四界面自 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 裁定执行。
### T4 大门动线(≈1–1.5d)
- 取用: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:475-497 逻辑整体迁来,卡②已摘除原调用)。
- [ ] 「继续上一段冒险」接现役续玩编排(`_resume_from_menu` 同源);「开始新冒险」接现役开局编排(`_start_adventure` 同源)——冒险屏/选路屏/战斗屏零改(F7)。
- [ ] 冒险发起后营地场景屏隐藏;**终局落点不变量**:现役口径=终局 continue 回主菜单(main.gd:703)——若后续改落点为营地,营地语境可能出现未收束会话,卡⑤「返回主菜单」动线须补 `_begin_session(false)`,两卡 T0 互证。
- [ ] 篝火回主菜单动线:命中区只含火堆(不含火焰),**必须二次确认**(camp.md v2.2 已裁,走 ConfirmDialog 先例);确认后营地层与选档层同收+开始层恢复(T3 开层互斥/关层收闭同口径)。
- [ ] `_refresh_resume_button` **不复用**(大门两分支直读 `has_breakpoint`,无钮可刷——函数随卡②删,防两卡互以为对方在处理)。
- 产出:大门两分支+三钮消费方编排+篝火二次确认动线;T5 按接口块验收。
- 大门点击→两分支确认弹窗(裁决 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 明示,函数随卡②删,防两卡互以为对方在处理)。
### T5 断言、探针与截图迁移批(≈2–2.5d)
### T5 断言、探针与 golden 迁移批(≈2–2.5d)
- 取用: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 命名稳定化一并定。
- [ ] 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(入口路径归卡②、槽操作路径归卡③、营地段+断点确认段归本卡)——每条探针注分界。
- [ ] 新增断言段(**正向验收断言,从真实入口进入、判据绑被测改动特有的可观测提交面**):七物件逐一可达对应界面;大门两分支;点大门不直接进冒险(绑 `confirmed` 信号与 `route_chosen` 未发);点大门→开局后营地场景屏隐藏;图鉴=占位挂起态;场景根态无文字按钮列表/无四柜台面板(反参照纪律断言);presenter 七写口尾→现开界面刷新+场景根 HUD 刷新一闸(绑刷新单口调用记录与 HUD 状态源取值);三钮弹窗 cancelled 恒=无变更退回营地(绑写口零调用+营地根 visible)。**判据绑不上=静态判据+评审注记申报观测面局限,证明做不出=停卡呈报;断言只在当轮真实跑批执行并通过,不做注入破坏。**
- [ ] 美术约束机检:shot_checker 现役段扩 camp 取样;截屏级 48 色计数是否新建=§9 第 5 条拍板(依赖 §0.3 环境子板色值代码段开工门销号)。
- 产出:探针/断言迁移留痕表(F8 全量位点逐点「改前→改后」)+新增断言段;T6 收口。
- 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 补);注入→最窄闸见红→精确还原→记录。
### T6 产出物落位卡(≈0.5d,末卡)
- 取用: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 全量域闸复验。
三份 `reports/` 写齐(实现报告含方向稿选划记录三段表、探针迁移留痕表、变异记录表、目检总清单/代拍板追认单/反哺点清单)。
**估时合计 ≈9–12d**(presenter 承接面+三钮弹窗+探针深员面增量;T1 为素材录入、美术创作主体归美术自立批已完成)。
**估时合计 ≈9–12d**(v1.1 上调:presenter 承接面+三钮弹窗+坏槽态联动+探针深员面增量)。**天然切分点=T1 出口**(场景素材归档齐)——美术线与代码线可分批交付(用户批次归属裁);若单批跑超迭代盒,T3 末(四柜台拆解完)为次切分点。
## 7. 验证闸:改动—验收对照表
## 7. 验证闸(逐需求点验收清单)
七格表:需求点|改动(文件:行/行为)|验收测试(名称+落点+尾缀)|层级(单元/接口/集成/探针)|真实入口|判据绑定面|能力行。**每个需求点至少一行;每个行为改动至少一行(V1–V13 需求点行+B1–B2 行为改动专行);每行必须有真实入口和判据绑定面——缺任一项=该需求点未验收,卡片不成立。** 断言尾缀〔营地图批 Vn〕/〔营地图批 Bn〕,与卡片清单互相 grep。能力行格式 `既有:<能力名>`/`新增:<能力名>`,两形态名称都须在 `game/tests/README.md` 能力表在场(既有=现役在场名,新增=本卡定名、由主 Agent 统一收口入表;本卡只写卡内能力行文字,README 由主 Agent 收口)。
| # | 需求点 | 测什么 | 落点/判定手段 |
|---|---|---|---|
| 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 场景图形态(机检半) | `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〕+`shot_checker.py` 结构禁词段 | 探针 | 进入存档→选档→进档→营地场景屏(shot_probe 驱动) | camp 截图出图非空+shot_checker 结构禁词命中(无四柜台覆盖层/无文字按钮列表);「七要素可辨(构图)」归 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 第 5 条拍板截屏计数面 | 既有: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` 落点 | 既有:模态覆盖层编排与输入锁 |
| 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:职责语句/单一变化原因/集体身份,禁凑计数袋) | 既有:元进度入账与锻造两轴;新增:四柜台拆解后五界面入口改挂与写口零回归 |
**测试方式两分法**:V1–V10、V12 机检自动化(能力验证经调试接口直改断点/钥石/解锁状态,沿用 DebugOverlay/DS_DEBUG 门控);V11 归用户目检(生命周期末步统一进行,不阻塞迭代)。
**落点集中**:V1/V9/V11/V12 → T5/T6;V2/V8 → T2/T3;V3/V7 → T4;V4/V5/V6 → T3;V10 → T5;V13 → T6;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 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试/工具先行孤立验证再并入全套。
**闸口径**:轻闸每卡出口自跑;批末重闸按改动域选档(本批碰 `game/` 代码/断言/终稿素材 → `--code`)全绿才合并;MC 零跑(零数值零行为——纯呈现+承载迁移)。
## 8. 异常分级
- **L1(自救一次)**:断言写法、探针路径、命中区微调、命名、编译错误、签名拼写、测试套件 manifest 登记遗漏。
- **L2(记录继续;同一红连续三次升 L3)**:场景屏承载形态选择(§9 域内)、点选反馈参数(§0.3 P3 设计稿域内)、四界面承载形态(§9 域内)、图鉴占位文案称谓订正、行数较 T0 预期漂移但 S13 键不升。
- **L3(立即停卡写报告等用户)**:
- 代码段开工门未销号即需开工对应任务段(§0.3:P3 点选反馈设计稿/P5 GDD·art-bible 落文/camp-scene-prompts §5 五裁点/素材后处理入库);
- 规格清单(样张批)终档置换未按反哺点登记;
- golden 漂移越出预期面(若涉及既有棋盘/menu 基线);
- 发现五界面任一功能/写口链路被意外触碰(契约 4 破);
- 参照物与纵深稿结构性冲突再现(P4 已补、冲突已呈报,禁批内自行改构图);
- 美术渠道 B 执行中撞墙(插画级新产达不到七物件可辨性);
- 提议新建 camp golden(契约 10——须另裁);
- 任何验收行无法从真实入口绑定特有可观测提交面(证明做不出=停卡呈报);
- **机检预算互斥=上游缺陷停卡退回写卡段**:实现规范预算超默认未走指标例外申报、或 S13 键较登记值上升、或机检键/计数与卡片契约互斥——一律停该卡呈报退回写卡段,禁为凑绿保留无效成员、造第三条路或内联求裁(契约 12/第 13 节合流);
- **拆分边界**:按契约 11 拆不出内聚单元(只能凑计数袋/沿阈值轴硬拆)=停卡呈报走豁免/还债通道,禁硬拆凑绿。
- **L1(自救)**:断言写法、探针路径、命中区微调、命名。
- **L2(记录继续)**:场景屏承载形态选择(§9 域内)、点选反馈参数(Q3 设计稿域内)、四界面承载形态(§9 域内)、方向稿张数在 2–3 内自选、图鉴占位文案称谓订正。
- **L3(停机呈报)**:Q1–Q6 未裁即需开工对应任务段;规格清单(样张批)晚于本批且 Q6 未裁;golden 漂移越出预期面(若涉及既有棋盘/menu 基线);发现五界面任一功能/写口链路被意外触碰(契约 4 破);参照物到手后与纵深稿结构性冲突(呈报,禁批内自行改构图);美术渠道 A/B 执行中撞墙(如 CC0 改色达不到七物件可辨性);提议新建 camp golden(契约 10——须另裁)。
## 9. 代拍板白名单(超清单必呈报)
> 篝火二次确认已由 camp.md v2.2 裁定为**必须**(走 ConfirmDialog 先例),不属代拍板域。
1. 场景屏承载形态(camp_screen 屏壳改造 vs 新屏壳)——约束:`LAYER_CONTRACT` 更新+探针挂载面迁移留痕。
2. 五界面拆出后的承载形态(独立全屏页 vs 单一内页切换)+**叠层规则派生**(独立全屏页=场景根隐藏/单一内页切换=场景根留底;写入 V2 断言;「缩放虚化」禁自选)。
3. 七物件命中区实现(TextureRect 分区 vs 其他)与点选反馈参数(§0.3 P3 设计稿域内)。
4. 截屏级 48 色计数工具是否新建及落点(现役=素材级二器 F17;截屏级依赖 §0.3 环境子板色值代码段开工门销号后定)。
5. CampOverlay 类退役范围(整类删 vs 留片段)——约束:吸收即死,禁留死代码。
6. 提交切分与 worktree 分支命名。
2. 五界面拆出后的承载形态(独立全屏页 vs 单一内页切换)+**叠层规则派生**(v1.1:独立全屏页=场景根隐藏/单一内页切换=场景根留底;写入 V2 断言;「缩放虚化」禁自选)。
3. 七物件命中区实现(TextureRect 分区 vs 其他)与点选反馈参数(Q3 裁定域内)。
4. 篝火是否需二次确认——默认直回(营地每笔消费即时写盘,无未保存风险——存档序列化.md:121);如判需确认,走 ConfirmDialog 先例。
5. 截屏级 48 色计数工具是否新建及落点(现役=素材级二器,F17;截屏级依赖样张批规格清单,随 Q6 一并裁)。
6. CampOverlay 类退役范围(整类删 vs 留片段)——约束:吸收即死,禁留死代码。
7. 提交切分与 worktree 分支命名。
超出必须呈报:任何数值、像素规格、事件名、命中区绑定目标、文件职责、T 卡验收落点、五界面写口链路、拆分单元职责。
## 10. 裁点与设计议程(v2.1:本卡在批内,以下为前置解决议程)
## 10. 待裁点:零待裁点,开工门=U0
> Q4/Q5/Q6/Q8 已裁(裁定见卡头);Q1/Q2 仍待用户。本节约等于批内设计段的工作清单。
**本卡设计待裁点清零,开工门=U0。** Q1/Q2/Q4/Q5/Q6/Q8 均已裁(下列为现行裁定留痕,非待裁点,实现期禁自行改值):
### Q1 · 营地场景图的美术渠道(**仍待用户裁——批内第一议程,阻塞 P2 规格分支与方向稿**)
- **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.24 §6.2/art-assets-checklist.md §3.5(2× 源档出图、最近邻降采样到 1280×800);终档归样张批冻结清单后置换(反哺点登记),执行归用户线。
- **Q8 设计稿产出方式=甲**(2026-10-18):批内出稿呈裁(方向稿先行纪律照旧——方向稿选划已由 2026-10-31 样张过审裁定完成,各素材第一张样本稿为终稿、保留全部待选稿)。
**背景**:澄清⑧2——「美术渠道 A/B 未裁:CC0 改色 vs 插画级新产——原贴图批的渠道问题对营地场景图同样成立,本讨论未裁决」。
**代码段 `/iter` 开工门(不是设计待裁点,不阻塞重立卡与编迭代)**,见 §0.3:P3 点选反馈设计稿、P5 GDD/art-bible 条款落文、camp-scene-prompts.md §5 五个待裁点(帐篷尺寸/门扇高宽/布告板位置/描边颜色追认/环境子板色值)、十张终稿后处理与落 `game/assets/art/scene/`(实现段 T1/`asset-ingest` 第 3 步,用户 2026-10-31 令只生成素材不做后续,开工时另发令)。编入哪一迭代归 iter-plan 段发令,本卡不代裁。
**我的推荐: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)零改动。
+2 -2
View File
@@ -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 进行中〔用户裁拆批 2026-10-31〕——卡A 换图系双基座七件批+卡B 站桩名字行提档与地台色合并批已收口,代码域闸全绿且独立验收审计通过,合回与 CI 待发令;卡C 棋盘格边长口径收口批停摆退回写卡段:触发卡片 L3 #2 停机点,14×14 板基座档实测 28px 低于 battle.md 可读下限 30px、系存量事实首测非本批回归,读数与读法甲/乙裁决点见 reports/停机呈报-棋盘格边长口径收口批-2026-10-31.md,裁决后重立卡。待编池:营地交互重做卡⑤(排卡④之后)、卡④(美术设计已闭合=样张过审 2026-10-31+art-bible v3.24 §6.2,待用户发令重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)。
- **下一步**:迭代 46 待开工(编排提交 da24047c:换图系双基座七件批+站桩名字行提档与地台色合并批+棋盘格边长口径收口批三卡,≈9.125 个工作日)——开工由用户经 iter 发令。待编池:营地交互重做卡⑤(排卡④之后)、卡④(美术设计已闭合=样张过审 2026-10-31+art-bible v3.24 §6.2,待用户发令重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)。
## 里程碑时间线
@@ -79,7 +79,7 @@
| 迭代 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 | 2026-10-31 | ≈8.625 个工作日 | — |
| 迭代 46 | 待开工 | reports/需求卡片-换图系双基座七件批-2026-10-31.md<br>reports/需求卡片-站桩名字行提档与地台色合并批-2026-10-31.md<br>reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md | 2026-10-31 | ≈9.125 个工作日 | — |
- 迭代 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 存量债序列。
+31
View File
@@ -0,0 +1,31 @@
#!/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
+118 -10
View File
@@ -22,6 +22,13 @@
# ——本批改动只有文档件时用: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(跑不出回执即拦),不以全量为兜底。
@@ -47,16 +54,24 @@ 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#--}" ;;
*) echo "用法: tools/run_all_gates.sh [--code|--docs|--quick]"; exit 2 ;;
--staged)
[ -n "${2:-}" ] || { echo "用法: --staged <暂存清单文件>"; exit 2; }
STAGED_FILE="$2"; shift ;;
*) echo "用法: tools/run_all_gates.sh [--code|--docs|--quick] [--staged <清单文件>]"; 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)。
@@ -73,8 +88,23 @@ 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,验的却是别的字节,回执标 dirty_game 由 CI 落账留痕。
# gitignore 面)。脏树跑出来的回执记的是 HEAD,验的却是别的字节,合回闸据此拒收。
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
@@ -327,6 +357,38 @@ 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,
@@ -416,14 +478,60 @@ fi
fi
# ══ 文档域(6–8e)══
if in_domain docs; 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
# ── 增量触发矩阵(唯一落点,判据依据与漏检面见头注 --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
fi
# ── 7. 静态扫描(代码域)+ 熵增闸(两域都跑:它查顶层目录/根文件/图像白名单/退役路径,
+16 -15
View File
@@ -2,14 +2,6 @@
本清单是流水线的唯一登记处:以后才做的事在此登记一条,随流水线段推进改状态,做完整条删除(条目记进度,不是各段的开工前置);各系统文档的「待办」节只留一行指路存根,不再自建条目。条目格式(标题=登记元数据含可选优先级,正文=实况/缺口/改动面/状态四属性)与状态机以 [doc-conventions §12.1](design/engineering/doc-conventions.md) 为权威。
#### 状态合并改累加制——同名状态重复授予改加时长(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 复核过)。
@@ -228,6 +220,16 @@
**状态**:文档设计已闭合
#### 空刷新的可见性(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(文件头挂冻结横幅)。
@@ -281,12 +283,11 @@
**实况**:扩板已落地(四档板型 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-31](reports/停机呈报-棋盘格边长口径收口批-2026-10-31.md)(迭代 46 实现会话触发卡片 §9 L3 #2 预设停机点,2026-10-31 用户裁拆批退回写卡段;14×14 板基座档实测 28px 低于可读下限 30px 的适用域裁决待定——读法甲/乙见呈报 §三,裁决后重写卡C;算式单点提取/探针门槛对齐/四档冒烟三件已验改动可复用,worktree iter46 未提交 WIP 在案)。
- 需求卡片:[需求卡片-棋盘格边长口径收口批-2026-10-30](reports/需求卡片-棋盘格边长口径收口批-2026-10-30.md)(2026-10-30 已写卡,零待裁点——算式单点提取经 `BoardView._cell_for`/探针门槛 36→30 对齐 battle.md 可读下限/冒烟扩 13×13 与 14×14;探针不扩到 L3,最大板可读面改由实板面积推定断言承担)
**改动面**:游戏代码
**状态**:已写卡
**状态**:已写卡+已编迭代 46
#### 立绘清晰度回退评估——是否改用高清图(2026-10-13 登记,来源=playnote)
@@ -436,13 +437,13 @@
#### 营地交互重做·五张需求卡片(2026-10-18 登记,来源=会话提及)
**实况**: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 浮窗)随卡④ 代码波同行,两卡未编排——编入哪一迭代由用户经迭代编排段发令。关联文档:
**实况**: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 浮窗)随卡④ 代码波同行,两卡未编排——编入哪一迭代由用户经迭代编排段发令。关联文档:
- 设计澄清定稿:reports/需求澄清-营地交互重做-2026-10-18.md(v1.0:目标体验原话/目标结构树+纵深稿/10 条交互裁决/验收口径/切批原则/遗留待裁)
- 卡④:reports/需求卡片-营地场景图新建批-2026-10-18.md(**v3.0 现行有效卡**,2026-10-31 用户令据 req-card 第〇步重立=美术设计已闭合;样张过审+art-bible 条款版本 v3.24 §6.2,见代码段开工门)
- 卡④:reports/需求卡片-营地场景图新建批-2026-10-18.md(v2.3,**2026-10-21 用户令退回美术设计段,非有效卡**,美术设计闭合后重立卡,见缺口)
- 卡⑤:reports/需求卡片-ESC浮窗与营地顶栏批-2026-10-18.md
**代码段开工门(/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 现行有效卡);以下为**代码段 `/iter` 开工门**(不阻塞编迭代):P3/P5 两项用户侧前置未销号(P2 Q6 甲口径已裁不阻塞写卡、终档置换归反哺点)、camp-scene-prompts §5 五个待裁点(帐篷尺寸/门扇高宽/布告板位置/描边颜色追认/环境子板色值)未清零;十张终稿仍为原始候选未做后处理未落 `game/assets/art/`,此属实现段 T1/素材录入(asset-ingest 第 3 步终稿拷入),用户 2026-10-31 令只生成素材不做后续,开工时另发令。
**缺口**:卡④(营地场景图)**已退回美术设计段**(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 令只生成素材不做后续,开工时另发令。
**改动面**:文档+游戏代码+美术素材
**状态**:文档设计已闭合+美术设计已闭合+已写卡
**状态**:文档设计已闭合+待美术设计+已写卡