Compare commits
199
Commits
6559604ef8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47355d2da7 | ||
|
|
52e5711128 | ||
|
|
bcc78ce980 | ||
|
|
fa668eab3e | ||
|
|
9af7b8ea0c | ||
|
|
e34310de35 | ||
|
|
ddd342c0c2 | ||
|
|
1bf813dc74 | ||
|
|
e0103d82ef | ||
|
|
db7719ca47 | ||
|
|
3ae1372171 | ||
|
|
d034970c64 | ||
|
|
a9bf6ae957 | ||
|
|
2fac0c8dce | ||
|
|
d234a5474b | ||
|
|
cedc2e0b5d | ||
|
|
5ec4a311bb | ||
|
|
908e518306 | ||
|
|
9251d35650 | ||
|
|
bccc2d825d | ||
|
|
1e9b21e406 | ||
|
|
b8125cde0c | ||
|
|
7158366a0e | ||
|
|
7fc7a8925a | ||
|
|
9f683800fa | ||
|
|
295e67ca1c | ||
|
|
11eed6ac80 | ||
|
|
7d720f58a1 | ||
|
|
661c2fcc79 | ||
|
|
7b6bbea9cf | ||
|
|
b83dc5fd55 | ||
|
|
9903fa906d | ||
|
|
89f4fc7847 | ||
|
|
461effaad1 | ||
|
|
5b42c13aca | ||
|
|
a0ea828f78 | ||
|
|
01b8778504 | ||
|
|
9241a6aca0 | ||
|
|
09042f92fa | ||
|
|
665304cf14 | ||
|
|
7d4d97eebb | ||
|
|
a992691069 | ||
|
|
a5a7dc4d7c | ||
|
|
c41ce9cfc5 | ||
|
|
095bb4c91b | ||
|
|
bdd69cf177 | ||
|
|
3447bd7f07 | ||
|
|
53e65eaeaf | ||
|
|
5f233bac9a | ||
|
|
912a44541f | ||
|
|
54f9f23342 | ||
|
|
ef5d46793d | ||
|
|
e89151fb55 | ||
|
|
2bf347a1df | ||
|
|
055a4067f4 | ||
|
|
ea09b71386 | ||
|
|
a6d5607882 | ||
|
|
843edf9d70 | ||
|
|
bb6b17266b | ||
|
|
3714e20b65 | ||
|
|
52b9490e82 | ||
|
|
28c4645ae2 | ||
|
|
4993845839 | ||
|
|
87aa113973 | ||
|
|
79c077eb9d | ||
|
|
74e981a5a3 | ||
|
|
bde6b65e9b | ||
|
|
7c3de01017 | ||
|
|
c802b6b70d | ||
|
|
7618ee44c6 | ||
|
|
59406bd800 | ||
|
|
1aab4dbaf1 | ||
|
|
7604e5ef1c | ||
|
|
b03e4eeee8 | ||
|
|
f7d7761e7c | ||
|
|
76b86dc44d | ||
|
|
9f21236f80 | ||
|
|
5fb6c17fe6 | ||
|
|
aa0b23c951 | ||
|
|
166114e094 | ||
|
|
4b7276f5d7 | ||
|
|
5c4d6000ef | ||
|
|
5d178130d6 | ||
|
|
453c5ce640 | ||
|
|
18d1565dfb | ||
|
|
4f21255cd7 | ||
|
|
933d67eca7 | ||
|
|
51e87d6d95 | ||
|
|
1858ce3be2 | ||
|
|
9d4c91543f | ||
|
|
6669dca72d | ||
|
|
ee0b1d4081 | ||
|
|
bce20eeb2f | ||
|
|
0a6b115be7 | ||
|
|
d1599a1362 | ||
|
|
b35a639d9e | ||
|
|
d07361fd64 | ||
|
|
61c99ce8a8 | ||
|
|
c9a5a6b904 | ||
|
|
2a17260c8e | ||
|
|
85abe37cf5 | ||
|
|
77c1d360f6 | ||
|
|
cde68adfa7 | ||
|
|
fdef56c749 | ||
|
|
799df7d2ba | ||
|
|
5b5e629706 | ||
|
|
5358880072 | ||
|
|
f9c9caf56b | ||
|
|
4c424af358 | ||
|
|
96123978c1 | ||
|
|
a2e500a4af | ||
|
|
9f80609518 | ||
|
|
40a3ac1281 | ||
|
|
fe00f90c1b | ||
|
|
ca4b9baf2f | ||
|
|
8bee626138 | ||
|
|
b0b0cd0c81 | ||
|
|
b6d3162d43 | ||
|
|
8b09b2c952 | ||
|
|
9e81408efc | ||
|
|
7ef099b061 | ||
|
|
c76b712d70 | ||
|
|
83cae72789 | ||
|
|
df1c10e30e | ||
|
|
86172f5429 | ||
|
|
7ed648da54 | ||
|
|
e76a31c494 | ||
|
|
03ebb4741d | ||
|
|
fcb3ecd8ae | ||
|
|
193902ad8f | ||
|
|
f3138df5df | ||
|
|
cba3d64709 | ||
|
|
085717166d | ||
|
|
9e26df16be | ||
|
|
ddc352a985 | ||
|
|
157fb62a17 | ||
|
|
3537f8e2a5 | ||
|
|
b3f435434f | ||
|
|
086966be86 | ||
|
|
4dc5e9a3a8 | ||
|
|
5e6cec8353 | ||
|
|
8883e6101b | ||
|
|
7aa0126b22 | ||
|
|
8d170007be | ||
|
|
4f48c40fd5 | ||
|
|
e0b22f40fb | ||
|
|
d68c32470e | ||
|
|
00a0b82a0a | ||
|
|
7679208279 | ||
|
|
f73f3c1d47 | ||
|
|
a1f1c258ea | ||
|
|
d3c8539062 | ||
|
|
be0cab8356 | ||
|
|
49b4a63f93 | ||
|
|
41f32e1845 | ||
|
|
d7d4bc87d3 | ||
|
|
c1acb47c92 | ||
|
|
adfe15db08 | ||
|
|
8d8e4255c3 | ||
|
|
336e66163a | ||
|
|
c17a5430f6 | ||
|
|
bb9ce8a117 | ||
|
|
07d4977f41 | ||
|
|
afce55b09f | ||
|
|
886368684c | ||
|
|
2cbd2ca9a7 | ||
|
|
0977a548bf | ||
|
|
1730a8fbda | ||
|
|
03f0f1aa0d | ||
|
|
ec1c0da1ff | ||
|
|
909a9709b4 | ||
|
|
7bbde05243 | ||
|
|
111bf1bd10 | ||
|
|
515a50f896 | ||
|
|
b4e6db2f89 | ||
|
|
1345179032 | ||
|
|
c89e59febb | ||
|
|
76a7067440 | ||
|
|
55f4de3ca4 | ||
|
|
4a52d769ec | ||
|
|
4a650d0ed3 | ||
|
|
fd9c8ad90e | ||
|
|
33ab7deebd | ||
|
|
2b06ad163c | ||
|
|
c9ae0dea07 | ||
|
|
8be1634d04 | ||
|
|
e8bd1f58de | ||
|
|
441111f49d | ||
|
|
c3d78eed85 | ||
|
|
36be33f81d | ||
|
|
859926b5e5 | ||
|
|
898f77e552 | ||
|
|
00d7bbfba1 | ||
|
|
709d9a85d2 | ||
|
|
b480a2f3c2 | ||
|
|
121aca4073 | ||
|
|
b86e0b803a | ||
|
|
79c3abdf2a | ||
|
|
cc2be27b9d |
No files matched your search
@@ -1,2 +1,19 @@
|
|||||||
# git 钩子文件必须保持 LF——autocrlf=true 检出会转 CRLF,bash 执行带 \r 的脚本即崩。
|
# git 钩子文件必须保持 LF——autocrlf=true 检出会转 CRLF,bash 执行带 \r 的脚本即崩。
|
||||||
tools/hooks/* text eol=lf
|
tools/hooks/* text eol=lf
|
||||||
|
# 全仓文本一律 LF 入库与检出——Windows core.autocrlf=true 会把工作区检出成 CRLF,
|
||||||
|
# 行尾一旦进入逐字符比对的字符串基线数据面(如测试内嵌的多行 golden 常量),
|
||||||
|
# 运行时基线(\n)与源码基线(\r\n)逐位比对必红。本规则让一切平台检出落 LF。
|
||||||
|
* text=auto eol=lf
|
||||||
|
# 二进制面显式豁免(防 auto 误判转码损坏素材与基线图)
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.jpeg binary
|
||||||
|
*.webp binary
|
||||||
|
*.gif binary
|
||||||
|
*.ico binary
|
||||||
|
*.ogg binary
|
||||||
|
*.wav binary
|
||||||
|
*.mp3 binary
|
||||||
|
*.ttf binary
|
||||||
|
*.otf binary
|
||||||
|
*.zip binary
|
||||||
@@ -42,8 +42,20 @@ jobs:
|
|||||||
if: steps.route.outputs.mode != 'skip' && steps.route.outputs.mode != 'gates'
|
if: steps.route.outputs.mode != 'skip' && steps.route.outputs.mode != 'gates'
|
||||||
run: |
|
run: |
|
||||||
cd "$GITHUB_WORKSPACE/repo"
|
cd "$GITHUB_WORKSPACE/repo"
|
||||||
|
# run134 实证:runner 缓存目录部分失效(.import 哈希记录在而 ctex 缺)时增量导入会跳过
|
||||||
|
# 重导、运行期成片资源 ERROR(字体/UI 素材)并污染 system_test 退出码与 golden 比对——
|
||||||
|
# 每批强制全量重导(幂等,代价≈1-2 分钟导入时长)
|
||||||
|
rm -rf game/.godot/imported
|
||||||
/usr/local/bin/godot --headless --path game --editor --quit
|
/usr/local/bin/godot --headless --path game --editor --quit
|
||||||
|
|
||||||
|
- name: 棋盘黄金图自愈补采(full 批——缺基准时 runner 会话渲染→提交回 master→下一轮拉取生效)
|
||||||
|
if: steps.route.outputs.mode == 'full'
|
||||||
|
env:
|
||||||
|
GODOT_BIN: /usr/local/bin/godot
|
||||||
|
run: |
|
||||||
|
cd "$GITHUB_WORKSPACE/repo"
|
||||||
|
bash tools/ci/golden_selfheal.sh
|
||||||
|
|
||||||
- name: 跑闸
|
- name: 跑闸
|
||||||
if: steps.route.outputs.mode != 'skip'
|
if: steps.route.outputs.mode != 'skip'
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -16,21 +16,22 @@
|
|||||||
|
|
||||||
## 运行与验证(工作目录 = 含 project.godot 的切片目录)
|
## 运行与验证(工作目录 = 含 project.godot 的切片目录)
|
||||||
|
|
||||||
- **合回验证 = 远端 CI(2026-11-03 用户裁)**:git merge 合回 master 落地后,post-merge 钩子(`tools/hooks/post-merge`)自动 `git push origin master` 触发远端 CI(Gitea Actions,runner=Mac 本机 host 模式,环境自举件=`tools/ci/mac_setup.sh`),工作流(`.gitea/workflows/ci.yml`)按改动域分流(分流算法单点=`tools/ci/domain_route.sh`):游戏码批=两域全量含渲染闸,文档批=文档域秒级闸,纯闸件/管线批=零触发。远端结果**按需现查**:`tools/ci_check.sh <合并提交>` 读该提交任务的 run `status`/`conclusion`,只呈报、不落盘(2026-11-04 用户裁:合回不等待、不唤醒;判据=run 落定后的终局态,且绿须坐实跑闸步真跑过——零触发批呈报「未验」不作绿证,细则=process-conventions §1 第 3 条)。**合回落地即向用户呈报本批总结并止回合**,禁前台 sleep/轮询等 CI。CI 红态不回滚合并——红项在案、修复批合回即再推再验追绿;开工先跑现查件读 CI 状态,红未修不开新批。同一份字节禁止第二次人手跑。`tools/run_all_gates.sh` 仍是全部验证闸的**唯一入口与唯一清单,域划分与选闸算法只写在它这一个地方**,文档禁另列清单;`--code`/`--docs`/`--quick` 是开发期改完即测的选档入口(细则见 process-conventions §4),全量档不替代它。**runner 依赖**:Mac 需开机在线(关机=远端任务排队延后);换机/重装按 `tools/ci/mac_setup.sh` 自举
|
- **合回验证 = 前置检查 + 远端 CI(前置检查 2026-11-06 用户裁)**:主区 `git merge --no-ff` 落合并提交前,pre-merge-commit 钩子(`tools/hooks/pre-merge-commit`)自动跑 `tools/run_all_gates.sh --premerge`——冒烟测试+单元测试全套件(4 分片),热导入缓存约 2 分钟;红=合并提交不落(一律 git merge --abort 放弃 → 回 worktree 处理 → 重新 git merge --no-ff;禁 git commit 续合,该路径两合回钩子零触发),快进合并不触发钩子,`--no-verify` 可跳过且仅属用户。git merge 合回 master 落地后,post-merge 钩子(`tools/hooks/post-merge`)自动 `git push origin master` 触发远端 CI(Gitea Actions,runner=Mac 本机 host 模式,环境自举件=`tools/ci/mac_setup.sh`),工作流(`.gitea/workflows/ci.yml`)按改动域分流(分流算法单点=`tools/ci/domain_route.sh`):游戏码批=两域全量含渲染闸,文档批=文档域秒级闸,纯闸件/管线批=零触发。远端结果**按需现查**:`tools/ci_check.sh <合并提交>` 读该提交任务的 run `status`/`conclusion`,只呈报、不落盘(2026-11-04 用户裁:合回不等待、不唤醒;判据=run 落定后的终局态,且绿须坐实跑闸步真跑过——零触发批呈报「未验」不作绿证,细则=process-conventions §1 第 3 条)。**合回落地即向用户呈报本批总结并止回合**,禁前台 sleep/轮询等 CI。CI 红态不回滚合并——红项在案、修复批合回即再推再验追绿;开工先跑现查件读 CI 状态,红未修不开新批。同一份字节禁止第二次人手跑。`tools/run_all_gates.sh` 仍是全部验证闸的**唯一入口与唯一清单,域划分与选闸算法只写在它这一个地方**,文档禁另列清单;`--code`/`--docs`/`--quick` 是开发期改完即测的选档入口(细则见 process-conventions §4),全量档不替代它。**runner 依赖**:Mac 需开机在线(关机=远端任务排队延后);换机/重装按 `tools/ci/mac_setup.sh` 自举
|
||||||
- 单件直跑(=改完即测的最窄确认,其读数就是那一步的凭据;跨改动面的漏网由合回后远端全量档兜):冒烟测试 `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`
|
- 单件直跑(=改完即测的最窄确认,其读数就是那一步的凭据;跨改动面的漏网由合回后远端全量档兜):冒烟测试 `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`(奖励期望);关卡完成率/难度类测量一律走全冒险
|
- 调参批量:`--script res://sim/adventure_monte_carlo.gd`(全冒险期望)· `res://sim/reward_expectation.gd`(奖励期望);关卡完成率/难度类测量一律走全冒险
|
||||||
- 数值验证:`python tools/balance_verifier.py`(采集端 `res://sim/verifier_batch.gd`,报告与原始数据落 `sim-data/`)
|
- 数值验证:`python tools/balance_verifier.py`(采集端 `res://sim/verifier_batch.gd`,报告与原始数据落 `sim-data/`)
|
||||||
- 熵增闸(新类别 = 同批修订 Project Layout + 白名单):`python tools/repo_structure_audit.py`
|
- 熵增闸(新类别 = 同批修订 Project Layout + 白名单):`python tools/repo_structure_audit.py`
|
||||||
|
|
||||||
## Project Layout
|
## Project Layout
|
||||||
|
|
||||||
- `design/gdd/` — 现行设计文档树(根索引 `02-系统清单.md`,文档增删必须同步;`gdd/ux/` 战斗画面与交互规格)
|
- `design/gdd/` — 系统与概念文档树(根索引 `02-系统清单.md`,文档增删必须同步)
|
||||||
|
- `design/ux/` — 呈现实现设计规格层(屏级布局、交互规格与预览图;与 gdd/ 同级)
|
||||||
- `design/art/` — 美术文档(圣经/角色设计/两份清单/路径图/提示词库与生图操作单);只放 .md 与 `references/` 参考图,审计报告与调研归 `reports/`
|
- `design/art/` — 美术文档(圣经/角色设计/两份清单/路径图/提示词库与生图操作单);只放 .md 与 `references/` 参考图,审计报告与调研归 `reports/`
|
||||||
- `design/engineering/` — 工程规范(五份规约 + architecture + engine-reference)
|
- `design/engineering/` — 工程规范(五份规约 + architecture + engine-reference)
|
||||||
- `design/content-archive/` — 退役内容留底(活文档,2026-10-20 用户裁新立:内容已退役、留底供日后重新过准入;落内文件头部写明所属线)
|
- `design/content-archive/` — 退役内容留底(活文档,2026-10-20 用户裁新立:内容已退役、留底供日后重新过准入;落内文件头部写明所属线)
|
||||||
- `design/research/` **已退役(2026-10-21 用户裁)**——`design/` 全目录只放持久化设计文档与规范,调研/提案/评估/历史验收一律落 `reports/`(熵增闸退役路径清单已收该目录,再现即判红);`design/qa/` 已退役,验证截图不进 `design/`(判据见 doc-conventions §11)
|
- `design/research/` **已退役(2026-10-21 用户裁)**——`design/` 全目录只放持久化设计文档与规范,调研/提案/评估/历史验收一律落 `reports/`(熵增闸退役路径清单已收该目录,再现即判红);`design/qa/` 已退役,验证截图不进 `design/`(判据见 doc-conventions §11)
|
||||||
- `artwork/` — 在途图像素材唯一工作区(文档归文档/在途图归一处/终稿归游戏);整目录不入 git(.gitignore 强制),收口归档 `archive/`
|
- `artwork/` — 在途图像素材唯一工作区(文档归文档/在途图归一处/终稿归游戏);整目录不入 git(.gitignore 强制),收口归档 `archive/`
|
||||||
- `game/assets/art/` — 已验收终稿(入包被游戏加载);`game/probe/` — 场景探针的场景与宿主+探针共用面(probe_gate/render_gate 在闸+人工取证探针);`game/sim/` — 测量/诊断/模拟驱动件(autoplay 策略、MC 批量、数值验证采集端);`game/` — 游戏工程本体(代码 + tests/ 冒烟/单元/集成/系统测试面)
|
- `game/assets/art/` — 已验收终稿(入包被游戏加载);`game/probe/` — 场景探针的场景与宿主+探针共用面(probe_gate/render_gate 在闸+人工取证探针);`game/sim/` — 测量/诊断/模拟驱动件(autoplay 策略、MC 批量、数值验证采集端);`game/` — 游戏工程本体(代码 + tests/ 冒烟/单元/系统测试面)
|
||||||
- `sim-data/` — 机器读数据产物;数据件不入 git(入库例外 = README+analyze.py+growth_model.py);MC 锚与读数常驻留盘,无数值调整禁重跑
|
- `sim-data/` — 机器读数据产物;数据件不入 git(入库例外 = README+analyze.py+growth_model.py);MC 锚与读数常驻留盘,无数值调整禁重跑
|
||||||
- `tools/` — python 工具脚本(含 `hooks/`=版本化 git 钩子,经 `core.hooksPath` 挂载);`archive/` — 批次完结归档 zip(gitignored)
|
- `tools/` — python 工具脚本(含 `hooks/`=版本化 git 钩子,经 `core.hooksPath` 挂载);`archive/` — 批次完结归档 zip(gitignored)
|
||||||
- `reports/` — 过程件容器:**需求卡片**(写卡段产出,实现批的输入合同)+迭代批产出物(实现报告/GDD 反哺点清单)+设计讨论段过程稿(提案/审计/需求澄清/评估);**实现批唯一可写目录**,中间文档唯一容器(`design/research/` 已退役),不是事实源(细则见 `reports/README.md`)
|
- `reports/` — 过程件容器:**需求卡片**(写卡段产出,实现批的输入合同)+迭代批产出物(实现报告/GDD 反哺点清单)+设计讨论段过程稿(提案/审计/需求澄清/评估);**实现批唯一可写目录**,中间文档唯一容器(`design/research/` 已退役),不是事实源(细则见 `reports/README.md`)
|
||||||
@@ -43,11 +44,11 @@
|
|||||||
| 批次开工 / 流程纪律 | `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 |
|
| 流水线段入口 | 技能对照——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/code-conventions.md`——结构/契约/语言/数值/流程五类硬纪律(反例库 = 同目录 code-conventions-cases.md) |
|
||||||
| 定测试方案 / 写测试 / 改测试前 | `design/engineering/test-conventions.md`——探针标配 / 回归断言 / 提交前验证 / 验收清单落码 |
|
| 定测试方案 / 写测试 / 改测试前 | `design/engineering/test-conventions.md`——探针标配 / 回归断言 / 提交前验证 / 验收清单落码;测试工具手册与闸机操作=`game/tests/README.md` |
|
||||||
| 定文档方案 / 写文档 / 改文档前 | `design/engineering/doc-conventions.md`——白话写作 / 载体分工 / 用语 / 结构骨架 / 会话记录与生命周期 |
|
| 定文档方案 / 写文档 / 改文档前 | `design/engineering/doc-conventions.md`——白话写作 / 载体分工 / 用语 / 结构骨架 / 会话记录与生命周期 |
|
||||||
| 概念切分与互链 | `design/engineering/concept-conventions.md`——概念封装 / 跨文档引用 / 归档与事实源 |
|
| 概念切分与互链 | `design/engineering/concept-conventions.md`——概念封装 / 跨文档引用 / 归档与事实源 |
|
||||||
| 系统设计 / 增删文档 | `design/gdd/02-系统清单.md`——根索引 + 中文规范名↔英文代号对照 |
|
| 系统设计 / 增删文档 | `design/gdd/02-系统清单.md`——根索引 + 中文规范名↔英文代号对照 |
|
||||||
| 架构(唯一事实源) | `design/engineering/architecture/architecture.md`——历史决策沿革查 git commit log,不另设决策文档 |
|
| 架构(唯一事实源) | `design/engineering/architecture/architecture.md`(只写约束面:分层/模块归属/数据流/API 边界;实现现状归代码与头注,闸清单归 `game/tests/README.md`)——历史决策沿革查 git commit log,不另设决策文档;修订须用户发令 |
|
||||||
| 术语与已锁数值 | 规范名与定义 = `design/gdd/术语表.md`(全库唯一对照表,仅 owner 文档可修订);现行数值 = `game/data/tables/*.tres`;规则(概念面)= 各系统 owner 文档;取值域与字段契约 = `game/data/schemas/*.gd`。冲突须显式提出,禁默默改值 |
|
| 术语与已锁数值 | 规范名与定义 = `design/gdd/术语表.md`(全库唯一对照表,仅 owner 文档可修订);现行数值 = `game/data/tables/*.tres`;规则(概念面)= 各系统 owner 文档;取值域与字段契约 = `game/data/schemas/*.gd`。冲突须显式提出,禁默默改值 |
|
||||||
| 现在做什么 / 待办与待裁 | 根 `roadmap.md` 顶部「当前位」节+迭代总表六列 · 待办唯一登记处 `待办清单.md` · 批次过程与结论查 git 提交信息与 `reports/` |
|
| 现在做什么 / 待办与待裁 | 根 `roadmap.md` 顶部「当前位」节+迭代总表六列 · 待办唯一登记处 `待办清单.md` · 批次过程与结论查 git 提交信息与 `reports/` |
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
2. **判断挂依据**:判断=「X 是/不是/造成了/应该」类陈述;每个判断后面必须跟依据。依据只认三种:仓库文件+行号或逐字引用(给行号就必须真读过那几行);本对话的消息号或原话;外部链接。三种都拿不出的判断必须当场标「这是推测」;说不出依据就答「不知道/没查过」,禁止编造。答复形状=结论行→依据清单→细节。
|
2. **判断挂依据**:判断=「X 是/不是/造成了/应该」类陈述;每个判断后面必须跟依据。依据只认三种:仓库文件+行号或逐字引用(给行号就必须真读过那几行);本对话的消息号或原话;外部链接。三种都拿不出的判断必须当场标「这是推测」;说不出依据就答「不知道/没查过」,禁止编造。答复形状=结论行→依据清单→细节。
|
||||||
3. **简洁**:同一意思只说一遍;能用一句不说两句。硬约束、数字、前提条件不参与压缩;信息完整与简洁冲突时保信息。
|
3. **简洁**:同一意思只说一遍;能用一句不说两句。硬约束、数字、前提条件不参与压缩;信息完整与简洁冲突时保信息。
|
||||||
4. **多角度**:介绍一个物体、一个概念、一个问题,多角度讲清楚;每角度信息点 ≤3 个,禁止违背第 3 条。
|
4. **多角度**:介绍一个物体、一个概念、一个问题,多角度讲清楚;每角度信息点 ≤3 个,禁止违背第 3 条。
|
||||||
5. **闸况呈报用闸名**:对话里报验证闸的跑批结果一律用闸名(冒烟测试/系统测试/单元与集成测试/场景探针/渲染闸等),不裸报编号。
|
5. **闸况呈报用闸名**:对话里报验证闸的跑批结果一律用闸名(冒烟测试/系统测试/单元测试/场景探针/渲染闸等),不裸报编号。
|
||||||
|
|
||||||
### 简洁细则
|
### 简洁细则
|
||||||
|
|
||||||
@@ -104,13 +105,13 @@
|
|||||||
|
|
||||||
## 硬性红线(勿违反;操作细则在 process-conventions.md 与各规约)
|
## 硬性红线(勿违反;操作细则在 process-conventions.md 与各规约)
|
||||||
|
|
||||||
- 车道铁律(2026-10-31 用户裁恢复)——主工作区只作合并落点,一切开发/设计改动走独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`(建区即跑 `tools/setup_worktree_userdir.sh`),收口=冻结→件核→并 master→重塑→主区 `git merge --no-ff`→删区(合回即删,2026-09-19 原裁),CI 红不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,免重塑免数卡)修复合回追绿;会话单区(2026-11-04 用户裁)——同一时刻每会话至多一个 worktree 在役,同会话追加事项并入在役区、只做一次合入(一次 CI),合回后用户再发令=新回合另开区,迭代实现批独占回合(细则见 process-conventions §1 第 5 条);主区唯一合法写动作=合并,agent 侧由 worktree-guard 拦主区 Edit/Write 与非 merge 提交;豁免面仅 `.zcode/`、`.qoder/`(不入 git,主区直改);commit 点零钩子检查(pre-commit 直改闸已退役),全量验证归合回后远端 CI(post-merge 钩子推送触发,见「运行与验证」首条);`--no-verify` 仅属用户,agent 禁用(细则见 process-conventions §1)
|
- 车道铁律(2026-10-31 用户裁恢复)——主工作区只作合并落点,一切开发/设计改动走独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`(建区即跑 `tools/setup_worktree_userdir.sh`),收口=冻结→件核→并 master→重塑→主区 `git merge --no-ff`→删区(合回即删,2026-09-19 原裁),CI 红不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,免重塑免数卡)修复合回追绿;会话单区(2026-11-04 用户裁)——同一时刻每会话至多一个 worktree 在役,同会话追加事项并入在役区、只做一次合入(一次 CI),合回后用户再发令=新回合另开区,迭代实现批独占回合(细则见 process-conventions §1 第 5 条);主区唯一合法写动作=合并,agent 侧由 worktree-guard 拦主区 Edit/Write 与一切 git commit;豁免面仅 `.zcode/`、`.qoder/`(不入 git,主区直改);commit 点零钩子检查(pre-commit 直改闸已退役);合回 merge 点另有前置检查钩子(pre-merge-commit,2026-11-06 用户裁,见「运行与验证」首条);全量验证归合回后远端 CI(post-merge 钩子推送触发,见「运行与验证」首条);`--no-verify` 仅属用户,agent 禁用(细则见 process-conventions §1)
|
||||||
- **仓库根禁止设会话状态文件**(`active.md` 已废除)——现状看 roadmap「当前位」,待办看待办清单,过程看 git 提交信息,产出物看 `reports/`;任何文档禁止另设「当前状态快照」节,两处记同一件事必然漂移(细则见 doc-conventions 第 10 节)
|
- **仓库根禁止设会话状态文件**(`active.md` 已废除)——现状看 roadmap「当前位」,待办看待办清单,过程看 git 提交信息,产出物看 `reports/`;任何文档禁止另设「当前状态快照」节,两处记同一件事必然漂移(细则见 doc-conventions 第 10 节)
|
||||||
- **改完即测铁规(2026-11-05 用户裁,取代原「测试执行两入口铁规」)**——任何会话里的任何改动,落笔之后立刻跑一遍覆盖该改动面的验证并跑绿、读数写进这一步的提交信息,这一步才算完成;验证载体一律按 `tools/run_all_gates.sh` 的域划分与该件自身的直跑方式,不扩出改动面、不请示、不等点名,未改动的面不测,合回后远端 CI 的全量跑批不替代本条。读数类采集(MC/verifier)不在该域划分内,不属本条义务
|
- **改完即测铁规(2026-11-05 用户裁,取代原「测试执行两入口铁规」)**——任何会话里的任何改动,落笔之后立刻跑一遍覆盖该改动面的验证并跑绿、读数写进这一步的提交信息,这一步才算完成;验证载体一律按 `tools/run_all_gates.sh` 的域划分与该件自身的直跑方式,不扩出改动面、不请示、不等点名,未改动的面不测,合回后远端 CI 的全量跑批不替代本条。读数类采集(MC/verifier)不在该域划分内,不属本条义务
|
||||||
- **红账不清不开新批**——上一批远端跑批有真红未闭合不开新批;假红(导入缓存、user 目录未隔离那类在册环境坑)走异常分级处置,不算未闭合
|
- **红账不清不开新批**——上一批远端跑批有真红未闭合不开新批;假红(导入缓存、user 目录未隔离那类在册环境坑)走异常分级处置,不算未闭合
|
||||||
- 合回后验证 = 远端 CI 闸全绿(唯一强制**全量**验证点;唯一入口、唯一闸清单、唯一域划分与选闸算法仍只在 `tools/run_all_gates.sh`,禁在文档另列;触发与追绿语义见「运行与验证」首条与 process-conventions §1)。它兜的是跨改动面的漏网,不替代改完即测铁规;主动发起的跨域全量回归归用户。分流算法单点=`tools/ci/domain_route.sh`
|
- 合回后验证 = 远端 CI 闸全绿(唯一强制**全量**验证点;唯一入口、唯一闸清单、唯一域划分与选闸算法仍只在 `tools/run_all_gates.sh`,禁在文档另列;触发与追绿语义见「运行与验证」首条与 process-conventions §1)。它兜的是跨改动面的漏网,不替代改完即测铁规;主动发起的跨域全量回归归用户。分流算法单点=`tools/ci/domain_route.sh`
|
||||||
- **改动四类**——**需求改动**(游戏代码,含随逻辑写/改的测试代码):唯一走「写需求卡片+编入迭代批次」通道;迭代实现批禁写 `design/` 整个目录、两份根流程清单(`待办清单.md`/`体验验证清单.md`)与 `game/tests/README.md`(能力清单,归写卡段维护)(含新增/修改/删除),设计文档对它只读、是写测试与实现代码的输入依据;两份流程清单的条目状态只由流水线各段推进,实现批禁止顺手改;产出物只准写 `reports/`;合回后由远端 CI 验证(红项修复合回追绿,process-conventions §1)。**工程改动**(tools/、闸件、模拟测量工具、纯测试维护——不改变游戏行为的配套代码)、**文档设计改动**、**美术素材改动**:不写需求卡片、不编迭代批次,由用户发令走独立 worktree 直改+合回(车道铁律,commit 点零钩子检查);大体量改动(含触及代码面的工程改动如纯测试维护)同车道无特殊通道;文档设计类写入走 doc-design 技能(登记条目格式由流水线闸强制)
|
- **改动四类**——**需求改动**(游戏代码,含随逻辑写/改的测试代码):唯一走「写需求卡片+编入迭代批次」通道;迭代实现批禁写 `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)
|
- 五段流水线铁律——**需求改动**(游戏代码)按「登记 → 文档设计/美术设计 → 写需求卡片 → 迭代编排 → 实现」五段推进,段间不自动流转、每段转进由用户发令;编入迭代的卡片必须设计闭合+零待裁点+卡内复核记录在位(2026-11-05 用户立规:复核发现按四类去向处置——自判/补写/待裁/退回上游,只有后两类归用户;复核没跑完禁对用户称完成,细则=req-card 技能「复核发现四类分流」与「写卡段的完成判据与呈报口径」)——需求卡片任何工作量皆可写、皆可编入迭代,工作量限制只属迭代层(迭代估时总量 <5 个工作日=「冻结待凑批」、不可开工);流水线闸 `tools/pipeline_gate.py` 强制(已注册进 run_all_gates.sh 文档域);实现段零裁断——卡片没写清=上游缺陷,停该卡退回上游,禁内联求裁(process-conventions §2,格式与状态机=doc-conventions §12)。工程/文档设计/美术素材三类改动不走写卡与编排段:(如需设计讨论)→ 用户发令 → 独立 worktree 直改 → 合回 CI(车道细则=process-conventions §1)
|
||||||
- MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起
|
- MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起
|
||||||
- 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6)
|
- 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6)
|
||||||
- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,可 grep 定位、在当轮真实跑批中执行并通过,判据绑被测改动特有的可观测提交面;**禁变异类测试与撤销类取证**(2026-10-24/2026-10-28 用户裁——人为制造红属伪造证据),证明做不出=停卡呈报;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §8+iter 技能第 5 步)
|
- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,可 grep 定位、在当轮真实跑批中执行并通过,判据绑被测改动特有的可观测提交面;**禁变异类测试与撤销类取证**(2026-10-24/2026-10-28 用户裁——人为制造红属伪造证据),证明做不出=停卡呈报;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §8+iter 技能第 5 步)
|
||||||
@@ -121,7 +122,7 @@
|
|||||||
- 文件头 = `##` 文档注释,介绍本模块是什么;禁写变更叙事(改动史查 git log);禁文档反向链接(code-conventions §1.4.1)
|
- 文件头 = `##` 文档注释,介绍本模块是什么;禁写变更叙事(改动史查 git log);禁文档反向链接(code-conventions §1.4.1)
|
||||||
- 数值单一事实源——玩法数值只存 `data/tables/`(.tres)经 ConfigDB 单点读取;禁数值字面量与自建 `load()` 表路径
|
- 数值单一事实源——玩法数值只存 `data/tables/`(.tres)经 ConfigDB 单点读取;禁数值字面量与自建 `load()` 表路径
|
||||||
- RNG 单点——禁 `randomize()`/自建 RandomNumberGenerator,随机只经 `RngService` 统一流
|
- RNG 单点——禁 `randomize()`/自建 RandomNumberGenerator,随机只经 `RngService` 统一流
|
||||||
- 架构事实唯一源——架构事实只认 `design/engineering/architecture/architecture.md`;禁立第二架构文档或决策文档体系,历史决策记录只进 git commit log
|
- 架构事实唯一源——架构事实只认 `design/engineering/architecture/architecture.md`(只写约束面:分层/模块归属/数据流/API 边界;实现现状归代码与头注);禁立第二架构文档或决策文档体系,历史决策记录只进 git commit log;架构文档写权限=用户专属,agent 与技能只读(2026-11-07 用户裁)
|
||||||
- Core 层零 UI 依赖——完整战斗必须可 `--headless --script` 跑通;fail-fast——数据校验错误一律致命中止,无软回退
|
- Core 层零 UI 依赖——完整战斗必须可 `--headless --script` 跑通;fail-fast——数据校验错误一律致命中止,无软回退
|
||||||
- spec-AC 一致性——规约与验收标准禁止在同一输入上给出不同答案;评审隔离——`/design-review` 必须独立会话跑(与 `/design-system` 隔离)
|
- spec-AC 一致性——规约与验收标准禁止在同一输入上给出不同答案;评审隔离——`/design-review` 必须独立会话跑(与 `/design-system` 隔离)
|
||||||
- 像素结构件——先抄后造、验收写成像素级判据、±1px 坐标推导(process-conventions 第 7 节)
|
- 像素结构件——先抄后造、验收写成像素级判据、±1px 坐标推导(process-conventions 第 7 节)
|
||||||
@@ -26,12 +26,12 @@
|
|||||||
| 条款 | 对出图的具体要求 |
|
| 条款 | 对出图的具体要求 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 一句话视觉规则 | 明快的地牢,轻快的扫荡,仔细的推理——**明亮像素幻想,全年龄,非暗黑**,角色 2~3 头身 |
|
| 一句话视觉规则 | 明快的地牢,轻快的扫荡,仔细的推理——**明亮像素幻想,全年龄,非暗黑**,角色 2~3 头身 |
|
||||||
| 原则一「预告上格」 | 格内绘制优先级 **数字(含色牌)> 小人 > 封印印记 > 变异纹带 > 装饰变体 > 底色**;任何元素禁止遮挡数字字形区;类型微光为底效泛光层,不入遮挡栈 |
|
| 原则一「预告上格」 | 格内绘制优先级 **浮空数字与引导线(最顶)> 小人 > 封印印记 > 交互反馈 > 变异纹带 > 装饰变体 > 底色**;北侧贴花低于小人、南侧随岩体在前;任何元素禁止遮挡浮空数字与引导线;类型微光为底效泛光层,不入遮挡栈 |
|
||||||
| 原则二「明亮为皮,明度分档为骨」 | 暖倾向;数字亮墨直画已开格底(亮墨 L≥0.75 / 已开格底 L 0.08–0.14,art-bible §4.1),对比 ≥4.5:1;色牌 `#F5EAD3` 为复杂格底后备(牌上深墨 L≤0.027);未开格底 L≥0.30、HSV 饱和 ≤0.55 |
|
| 原则二「明亮为皮,明度分档为骨」 | 暖倾向;浮空数字暖白芯+2px 深墨描边(art-bible §3.2/§4.1);普通数字色牌退役(封印格身份字形色牌保留);未开格底亮度地板与饱和上限同 §4.1(门值定值面=互辨抽测件) |
|
||||||
| 原则三「一砖一世界」 | 变体优先换色板不加新资产;危险状态必须**形状+颜色双通道**(色弱灰度可辨) |
|
| 原则三「一砖一世界」 | 变体优先换色板不加新资产;危险状态必须**形状+颜色双通道**(色弱灰度可辨) |
|
||||||
| 类型预读单通道(§4.6.3) | 未开格 = **类型常显微光**(五组色带 §4.2:芥末黄/黄绿/青/紫罗兰/绯红,色相+明度双码,避 300°–345° 禁入带,样张冻结);不呈现极性、不泄危险格与安全格(角嵌形状通道已不存在——微光格只留微光) |
|
| 类型预读单通道(§4.6.3) | 未开格 = **类型常显微光**(五组色带 §4.2:芥末黄/黄绿/青/紫罗兰/绯红,色相+明度双码,避 300°–345° 禁入带,样张冻结);不呈现极性、不泄危险格与安全格(角嵌形状通道已不存在——微光格只留微光) |
|
||||||
| 剪影哲学(§5.1) | **所有角色自带轮廓通道:亮色描边+落影底盘**,识别不依赖背景;四类原型见各条目 |
|
| 剪影哲学(§5.1) | **所有角色自带轮廓通道:亮色描边+落影底盘**,识别不依赖背景;四类原型见各条目 |
|
||||||
| 语义色规则(§4.2) | 红只说危险(危险红 `#A8321F` 单档)、金只说收益(`#F0A828`)、蓝只说己方(`#2E86DE`);封印印记现行色 = 封印黑 `#000000`(色史归 art-bible §4.1);**紫赤 `#8F2F6A` 为 Boss 独占,HSV 色相 300°–345° 全场禁入带**(微光群伤组绯红为类型先验色带域,例外见 §4.2) |
|
| 语义色规则(§4.2) | 红只说危险、金只说收益、蓝只说己方(各语义色定值面=ui_kit,art-bible §4.1);封印印记现行色 = 封印黑(色史归 art-bible §4.1);**紫赤为 Boss 独占,高饱和紫赤域全场禁入带**(带域定值面=互辨抽测件;微光群伤组绯红为类型先验色带域,例外见 §4.2) |
|
||||||
| UI 形状语法(§7.1,§3.3 存方向指导) | 半拟物:面板=石板圆角矩形(与地砖同圆角率),按钮=可按的砖,仪式确认=圆形蜡封;数据区直角细线无纹理 |
|
| UI 形状语法(§7.1,§3.3 存方向指导) | 半拟物:面板=石板圆角矩形(与地砖同圆角率),按钮=可按的砖,仪式确认=圆形蜡封;数据区直角细线无纹理 |
|
||||||
|
|
||||||
**参考图**:`design/art/references/` 三款×2 张(Into the Breach / Moonlighter / Peglin,与圣经点名池一一对应;gungeon 已退场,反面条款见 art-bible §9.2;正面取/弃与反面条款已成文 art-bible §9,反面图证待素材生成后增补)。
|
**参考图**:`design/art/references/` 三款×2 张(Into the Breach / Moonlighter / Peglin,与圣经点名池一一对应;gungeon 已退场,反面条款见 art-bible §9.2;正面取/弃与反面条款已成文 art-bible §9,反面图证待素材生成后增补)。
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
### 1.1 格子样张(砖面形态定稿闸)⚙
|
### 1.1 格子样张(砖面形态定稿闸)⚙
|
||||||
|
|
||||||
- **要什么**:一张按 art-bible §1.4 参数画成的格子风格试验图。**内容清单与验收四项以 art-bible §1.4 为唯一定义处**(含类型微光呈现组),本条只登记生产视角差异:图类型色板变体组至少两套、样张含至少一处砖缘/岛缘厚度与一格装饰立牌示例(§3.2 呈现基准)。
|
- **要什么**:一张按 art-bible §1.4 参数画成的格子风格试验图。**内容清单与验收四项以 art-bible §1.4 为唯一定义处**(含类型微光呈现组),本条只登记生产视角差异:图类型色板变体组至少两套、样张含至少一处砖缘/岛缘厚度与一格装饰立牌示例(§3.2 呈现基准)。
|
||||||
- **风格/规格**:色板 token 直接取 §4.1(掩尘 `#C9AF83`、裸土 `#B39A78`、数字墨三档、封印黑、危险红、奖励金、小人蓝、数字色牌)。
|
- **风格/规格**:棋盘三关八色取 art-bible §4.1「三关棋盘环境八色」;语义岗 token 取 ui_kit 常量组(封印黑、危险红、奖励金、小人蓝;普通数字色牌退役,封印格身份字形色牌保留)。
|
||||||
- **验收**:art-bible §1.4 四项按序判定(数字可读性 WCAG ≥4.5:1 硬指标 → 格态三形与微光互辨灰度可辨 → 焦点预算 → 图类型换皮抽测)。**通过 = 砖面形态与色板冻结**。
|
- **验收**:art-bible §1.4 四项按序判定(数字可读性 WCAG ≥4.5:1 硬指标 → 格态三形与微光互辨灰度可辨 → 焦点预算 → 图类型换皮抽测)。**通过 = 砖面形态与色板冻结**。
|
||||||
- **来源**:⚙ 脚本管线自产——样张是验收闸本身,必须按圣经参数画,无复用意义。
|
- **来源**:⚙ 脚本管线自产——样张是验收闸本身,必须按圣经参数画,无复用意义。
|
||||||
- **现状**:验收标准已成文,**测试未跑**。
|
- **现状**:验收标准已成文,**测试未跑**。
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
- **要什么**:按双舞台布局(战斗画面与扫雷图同屏常驻)出的整屏试验图。要锁的四件事:**角色剪影方向 / 动画方案 / 战斗空间 / 敌人层绘制优先级插入位置**;**敌种呈现形态已裁决:全站桩式(主角同站桩、状态小图标挂血条下),卡片式已弃,正式样张按站桩形态单版出样**。
|
- **要什么**:按双舞台布局(战斗画面与扫雷图同屏常驻)出的整屏试验图。要锁的四件事:**角色剪影方向 / 动画方案 / 战斗空间 / 敌人层绘制优先级插入位置**;**敌种呈现形态已裁决:全站桩式(主角同站桩、状态小图标挂血条下),卡片式已弃,正式样张按站桩形态单版出样**。
|
||||||
- **风格/规格**:敌人剪影按 art-bible §5.1 四类原型出(见 2.2);战斗舞台背景=明亮地窟,紫赤仅 Boss;像素尺寸按已定案两档换算(见 §0 通用规格纪律)。
|
- **风格/规格**:敌人剪影按 art-bible §5.1 四类原型出(见 2.2);战斗舞台背景=明亮地窟,紫赤仅 Boss;像素尺寸按已定案两档换算(见 §0 通用规格纪律)。
|
||||||
- **验收**:战斗表现「一屏样张的验收标准」(已成文)。
|
- **验收**:战斗表现「一屏样张的验收标准」(已成文)。
|
||||||
- **联动**:样张未过,**不启动任何终稿资产与动画设计**(文档明文的排期硬前置);格边长的计算口径不在本清单——现行唯一出处是 [battle.md](../gdd/ux/battle.md)「棋盘格尺寸公式」,HUD框架只判装板可行性(固定两档分辨率、窗口不可调、格子量增加则格边长相应变小;**档位值已定案 1280×800 + 1920×1080**)。
|
- **联动**:样张未过,**不启动任何终稿资产与动画设计**(文档明文的排期硬前置);格边长的计算口径不在本清单——现行唯一出处是 [battle.md](../ux/battle.md)「棋盘格尺寸公式」,HUD框架只判装板可行性(固定两档分辨率、窗口不可调、格子量增加则格边长相应变小;**档位值已定案 1280×800 + 1920×1080**)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
- **要什么**:营地场景图 10 张——`scene_camp_bg`(背景层,不透明全幅=天空+远山+整片地面+门洞内一条通向远处的小路)+ `scene_camp_wall`(围墙层,透明底=横贯全宽密排木桩墙+两根门柱,门洞留透明缺口)+ `scene_camp_gate / forge / chest / notebook / dummy / board / campfire`(七个可点物件)+ `scene_camp_tent`(承载件)。钥石顶栏图标沿用现役 `icon_keystone`。
|
- **要什么**:营地场景图 10 张——`scene_camp_bg`(背景层,不透明全幅=天空+远山+整片地面+门洞内一条通向远处的小路)+ `scene_camp_wall`(围墙层,透明底=横贯全宽密排木桩墙+两根门柱,门洞留透明缺口)+ `scene_camp_gate / forge / chest / notebook / dummy / board / campfire`(七个可点物件)+ `scene_camp_tent`(承载件)。钥石顶栏图标沿用现役 `icon_keystone`。
|
||||||
- **来源/规格**:**✦ 插画级**(作者自跑远程生图管线);烛光黄 `#F6C667` + 木色 `#8A5A34`(art-bible §6.2);2× 源档出图、最近邻降采样到 1280×800;后处理=抠底/降采样/色板量化/描边统一。**出图登记照 [remote-gen-prompts](remote-gen-prompts.md) 头注轻量口径执行:用途+生成时间必注,其余参数有则记。**
|
- **来源/规格**:**✦ 插画级**(作者自跑远程生图管线);烛光黄 `#F6C667` + 木色 `#8A5A34`(art-bible §6.2);2× 源档出图、最近邻降采样到 1280×800;后处理=抠底/降采样/色板量化/描边统一。**出图登记照 [remote-gen-prompts](remote-gen-prompts.md) 头注轻量口径执行:用途+生成时间必注,其余参数有则记。**
|
||||||
- **排期**:已执行。终稿落 `game/assets/art/scene/`,消费常量 `UiKit.TEX_CAMP_*`。
|
- **排期**:已执行。终稿落 `game/assets/art/scene/`,消费常量 `UiKit.TEX_CAMP_*`。
|
||||||
- **现状**:已入包(十件按锁定矩形 contain 落位、营地主色板 32 色重量化;用户游戏内终审如有置换意见,按同径替换)。
|
- **现状**:已入包(十件按锁定矩形 contain 落位;围墙与八件九件按营地主色板 32 色重量化,背景层 2026-11-07 换代走自板 ≤32 色、双板制见 art-bible §4.1 营地行;用户游戏内终审如有置换意见,按同径替换)。
|
||||||
|
|
||||||
### 3.6 字体(全局 UI 像素字,已定稿单套)
|
### 3.6 字体(全局 UI 像素字,已定稿单套)
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
| Kenney 全系(ui-pack/fantasy-ui-borders/game-icons/board-game-icons/kenney-fonts/roguelike 系/tiny-dungeon/tiny-town) | CC0 | 无 | ui-reuse 待审;tiny-dungeon 终局否决(架构不适配);余顺带否决;kenney-fonts 拉丁字候选退役(全局字体定稿 Fusion Pixel 单套,不再接入) |
|
| Kenney 全系(ui-pack/fantasy-ui-borders/game-icons/board-game-icons/kenney-fonts/roguelike 系/tiny-dungeon/tiny-town) | CC0 | 无 | ui-reuse 待审;tiny-dungeon 终局否决(架构不适配);余顺带否决;kenney-fonts 拉丁字候选退役(全局字体定稿 Fusion Pixel 单套,不再接入) |
|
||||||
| OGA Pixel UI 750(Kenney 作) / PixUI(CamTatz) / Handpainted stone | CC0 | 无 | ui-reuse 待审 |
|
| OGA Pixel UI 750(Kenney 作) / PixUI(CamTatz) / Handpainted stone | CC0 | 无 | ui-reuse 待审 |
|
||||||
| DENZI public domain art | CC0 | 无 | 否决 |
|
| DENZI public domain art | CC0 | 无 | 否决 |
|
||||||
| beast-cave(OGA) | CC0 | 无 | **已退役**(源包归档;地砖现行 = terrain_ 自产全套) |
|
| beast-cave(OGA) | CC0 | 无 | **已退役**(源包归档;地砖随 2026-11-07 棋盘地形重做退役——棋盘改程序化材质) |
|
||||||
| JaggedStone / Screaming Brain / ExileGL / Corey Archer(OGA) | CC0 | 无 | 否决 |
|
| JaggedStone / Screaming Brain / ExileGL / Corey Archer(OGA) | CC0 | 无 | 否决 |
|
||||||
| Calciumtrice / Buch / bart cobblestone(OGA) | CC-BY 3.0 | **需署名** | 否决 |
|
| Calciumtrice / Buch / bart cobblestone(OGA) | CC-BY 3.0 | **需署名** | 否决 |
|
||||||
| LD rogue / Evert cave / poikilos underworld(OGA) | OGA-BY 3.0 | **需署名** | 否决 |
|
| LD rogue / Evert cave / poikilos underworld(OGA) | OGA-BY 3.0 | **需署名** | 否决 |
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
| Fusion Pixel 缝合像素字体 | SIL OFL 1.1 | 保留许可证 | **已接入终稿**(全局 UI 字体;用户裁现状即终稿——单套单字重,拉丁沿用自带字形) |
|
| Fusion Pixel 缝合像素字体 | SIL OFL 1.1 | 保留许可证 | **已接入终稿**(全局 UI 字体;用户裁现状即终稿——单套单字重,拉丁沿用自带字形) |
|
||||||
| DCSS dngn / Lost Garden / Cavernlock / Aftertile / Voirol / oga-zelda-like(armm1998) | CC0 | 无 | 评估否决(架构/风格不适配;zelda-like 留作干净度基准) |
|
| DCSS dngn / Lost Garden / Cavernlock / Aftertile / Voirol / oga-zelda-like(armm1998) | CC0 | 无 | 评估否决(架构/风格不适配;zelda-like 留作干净度基准) |
|
||||||
| Golden UI 系列 | CC-BY-SA | — | **闸④不过,未下载** |
|
| Golden UI 系列 | CC-BY-SA | — | **闸④不过,未下载** |
|
||||||
| Gemini 生图(用户自跑) | 自产 | 无 | **terrain_ 高墙瓦片材质源(现行定稿)** |
|
| Gemini 生图(用户自跑) | 自产 | 无 | **已退役**(2026-11-07 棋盘地形重做;旧 terrain_ 瓦片全删) |
|
||||||
|
|
||||||
### 复用四闸(现行)
|
### 复用四闸(现行)
|
||||||
色板量化 / 禁入带吸色 / 灰度可辨 / 授权干净(SA 不可、来路不明不可)。
|
色板量化 / 禁入带吸色 / 灰度可辨 / 授权干净(SA 不可、来路不明不可)。
|
||||||
+84
-69
@@ -1,10 +1,10 @@
|
|||||||
# 美术圣经(Art Bible)— Dungeon Sweeper
|
# 美术圣经(Art Bible)— Dungeon Sweeper
|
||||||
|
|
||||||
> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.42,历次修订明细见 git 提交史
|
> 项目:Dungeon Sweeper(扫雷 × 自动战斗 闯关 Roguelike)· 状态:**第 1–9 节定稿**;现行为 v3.51,历次修订明细见 git 提交史
|
||||||
>
|
>
|
||||||
> **Art Director Sign-Off(AD-ART-BIBLE)**:历次批均未签核——此为 Lean/Solo 模式(非 PHASE-GATE)下的现行治理状态;full 门禁签核时机待用户表态。
|
> **Art Director Sign-Off(AD-ART-BIBLE)**:历次批均未签核——此为 Lean/Solo 模式(非 PHASE-GATE)下的现行治理状态;full 门禁签核时机待用户表态。
|
||||||
> 风格基调:地牢题材但**非暗黑风**——轻快明亮的幻想冒险风,全年龄;像素风;角色 2~3 头身。
|
> 风格基调:地牢题材但**非暗黑风**——轻快明亮的幻想冒险风,全年龄;像素风;角色 2~3 头身。
|
||||||
> 参考池(用户审阅选定,三者相融):**Into the Breach**(网格信息分层;雷图棋盘呈现基准 = 其战棋地块质感 × 正俯视角,见 §3.2)× **Moonlighter**(明亮像素地牢质感)× **Peglin**(明快全年龄地牢色彩);参考截图存于 `design/art/references/`(三款 × 2 张,与点名池一一对应);Enter the Gungeon 不作参考,反面条款见 §9.2。
|
> 参考池(用户审阅选定,2026-11-07 扩充):**Into the Breach**(网格信息分层;雷图棋盘呈现基准 = 战棋地块质感 × 正俯视角,见 §3.2)× **Moonlighter**(明亮像素地牢质感)× **Peglin**(明快全年龄地牢色彩)× **Stardew Valley**(连续地面与大地块地形的平铺控制、暖色可读性)× **Minish Cap**(圆润岩体轮廓与紧凑像素可读性);补充参考:**Necesse**(大块地形按连续面画、不按逐格物件画)、**Link's Awakening 原版/DX 2D**(抬升台面与南向崖面;2019 重制 3D 立体模型版不作参考)。参考截图存于 `design/art/references/`(原三款 × 2 张在库;新增参考图证待补,不阻塞画法条款);Enter the Gungeon 不作参考,反面条款见 §9.2。
|
||||||
> 约束:本圣经是**纯表现层文档**——明亮轻快是美术风格,不是玩法成分。圣经禁止引入、暗示或预设任何玩法语义,不改变任何 GDD 已锁机制;凡表现层需要玩法钩子才能表达之处(如完美封印检测、Boss 预警),一律标注「待 GDD 定夺」,圣经只规定"若有,则如何呈现"。GDD 机制与圣经冲突时,机制语义以 GDD 为准,呈现方案以本圣经为准。
|
> 约束:本圣经是**纯表现层文档**——明亮轻快是美术风格,不是玩法成分。圣经禁止引入、暗示或预设任何玩法语义,不改变任何 GDD 已锁机制;凡表现层需要玩法钩子才能表达之处(如完美封印检测、Boss 预警),一律标注「待 GDD 定夺」,圣经只规定"若有,则如何呈现"。GDD 机制与圣经冲突时,机制语义以 GDD 为准,呈现方案以本圣经为准。
|
||||||
> **条款验收标注纪律(全文书写规范)**:条款尾部按三档标注验收方式——**`验收:机检〈判据>`**(可量化,脚本能断言)/**`验收:目检〈判据>`**(机器测不了,但看什么、怎么算有明确判据)/**`验收:方向性`**(气质与方向原则,不承担验收);推导源尾注「←」继续表达推导来源,与验收标注同句并存时,验收标注放句末;数值类条款推荐「**待定现用**」态(现行即执法、修订走登记,释义见 §4.1)
|
> **条款验收标注纪律(全文书写规范)**:条款尾部按三档标注验收方式——**`验收:机检〈判据>`**(可量化,脚本能断言)/**`验收:目检〈判据>`**(机器测不了,但看什么、怎么算有明确判据)/**`验收:方向性`**(气质与方向原则,不承担验收);推导源尾注「←」继续表达推导来源,与验收标注同句并存时,验收标注放句末;数值类条款推荐「**待定现用**」态(现行即执法、修订走登记,释义见 §4.1)
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
**原则一|预告上格**(取自 Into the Breach;锚定 P1 推理的掌控感、P2 规划的延迟兑现)
|
**原则一|预告上格**(取自 Into the Breach;锚定 P1 推理的掌控感、P2 规划的延迟兑现)
|
||||||
|
|
||||||
继承其格内信息分层与"攻击预告画在目标格上"的范式:一切威胁、伤害与结算预告必须直接绘制在雷图格本体上,禁止只进侧栏或悬浮提示;格内绘制优先级固定:**数字(含色牌) > 小人标记 > 封印印记 > 变异纹带 > 装饰变体 > 底色**,任何元素禁止遮挡数字。格面类型预读 = 类型微光单通道,色相+明度双码(色带见 §4.2、键契约见 §4.6;徽章小图标族保留给库存与结算明细;类型微光为底效泛光层,不入遮挡栈、不遮任何元素)。与 ITB 之别:只取其信息骨架,弃其冷暗军事色调。验收:目检〈预告画在雷图格本体上,任何元素不遮挡数字〉
|
继承其格内信息分层与"攻击预告画在目标格上"的范式:一切威胁、伤害与结算预告必须直接绘制在雷图格本体上,禁止只进侧栏或悬浮提示;格上绘制优先级固定:**浮空数字与引导线(最顶层,永不被遮挡) > 小人标记 > 封印印记/类型微光 > 交互反馈(悬停/路径/可挖域微光) > 变异纹带 > 装饰变体 > 岩体顶面/地面底色**,任何元素禁止遮挡浮空数字与引导线。屏幕层序按脚底行分档:顶面贴花与交互反馈随所属格件 z——北侧(脚底≤小人)低于小人,南侧(脚底>小人)随岩体在前;封印印记与封印格身份色牌固定低于小人(不参与南侧前推);信息优先级不变(北侧重叠时小人压过贴花)。格面类型预读 = 类型微光单通道,色相+明度双码(色带见 §4.2、键契约见 §4.6;徽章小图标族保留给库存与结算明细;类型微光为底效泛光层,不入遮挡栈、不遮任何元素)。与 ITB 之别:只取其信息骨架,弃其冷暗军事色调。验收:目检〈预告画在雷图格本体上,任何元素不遮挡浮空数字与引导线〉
|
||||||
|
|
||||||
*范围注:本原则约束"已存在的信息往哪里画",不新增信息种类;预告类信息以战斗侧 GDD 实际定义的为准(如 P2 已锁的结算来源标注),GDD 未定义的预告不因本条而存在。*
|
*范围注:本原则约束"已存在的信息往哪里画",不新增信息种类;预告类信息以战斗侧 GDD 实际定义的为准(如 P2 已锁的结算来源标注),GDD 未定义的预告不因本条而存在。*
|
||||||
|
|
||||||
@@ -30,38 +30,38 @@
|
|||||||
|
|
||||||
**原则二|明亮为皮,明度分档为骨**(取自 Moonlighter、Peglin;锚定 P1 可读性前提、P4 探险氛围)
|
**原则二|明亮为皮,明度分档为骨**(取自 Moonlighter、Peglin;锚定 P1 可读性前提、P4 探险氛围)
|
||||||
|
|
||||||
取 Moonlighter 的暖质地砖与亲和冒险者气质、Peglin 的明快全年龄洞穴色彩:全局暖倾向、无压抑。可读性由**格底明度分档**承载——已开格(数字所在格)明度走世界底层档(§2 明度分层;格态语义见《排雷玩法》;美术侧据此未开格走受光墙顶档、已开格走挖出空间沉暗档,与 §8.5 图底分离同轴),亮族数字墨直接画在格底上,直画对比 ≥4.5:1 恒成立。**数字色牌为后备手段**——仅复杂格底(物件纹样/变异纹带/微光叠加致格底对比不足)时垫牌后备(画法 §3.3、色值 §4.1)。格子本体美术放开:纹理、材质、装饰变体、类型纹样皆可入画;格底参数域见 §4.1 硬指标(分档明度域、饱和上限),仍避 Boss 禁入色相带。与参考之别:ITB 以半透明压暗板承载信息;本作格底功能分档(信息可读性服务)。验收:机检〈1–8 全档数字对所在已开格底对比 ≥4.5:1〉
|
取 Moonlighter 的暖质地砖与亲和冒险者气质、Peglin 的明快全年龄洞穴色彩:全局暖倾向、无压抑。可读性由**岩顶/地面明度分档 + 浮空描边字**承载——已开格地面走世界底层档、未开格岩顶走世界中层(§2 明度分层;格态语义见《排雷玩法》;美术侧据此未开格走受光岩顶档、已开格走挖出空间沉暗档,与 §8.5 图底分离同轴);数字以浮空描边字画在格上方(字芯暖白 + 2px 深墨描边,§3.2/§4.1),不使用数字底牌。格子本体美术放开:纹理、材质、装饰变体、类型纹样皆可入画;岩顶/地面参数域见 §4.1 硬指标(分档明度域、饱和上限),仍避 Boss 禁入色相带。与参考之别:ITB 以半透明压暗板承载信息;本作岩顶/地面功能分档 + 浮空数字(信息可读性服务)。验收:机检〈四类底复合对比 ≥4.5(判据 §4.1)〉
|
||||||
|
|
||||||
*设计测试:当格子美术与数字可读性冲突时,先调格底明度档,复杂格底垫色牌后备,不动格子画。*
|
*设计测试:当格子美术与数字可读性冲突时,先调岩顶/地面明度档,禁止使用数字底牌,不动浮空数字画法。*
|
||||||
|
|
||||||
**原则三|一砖一世界**(融合 Moonlighter 地砖观;锚定 P3 风险与收益同源、P4 地牢下探隐喻)
|
**原则三|一砖一世界**(融合 Moonlighter 地砖观;锚定 P3 风险与收益同源、P4 地牢下探隐喻)
|
||||||
|
|
||||||
格子即地牢地砖:未开 = 覆尘完整砖,已开 = 碎裂裸露,雷 = 被惊动的巢穴(格态定义与玩家说法见《排雷玩法》),图类型(board_type)= 同款地砖换色板。图类型与变异格的视觉差异一律先做色板变体,不做新资产;一切危险状态必须"形状 + 颜色"双通道冗余,色弱可辨。像 Moonlighter 之处在砖缝质感与暖色道具,但装饰禁止伪装成逻辑差异——玩家须一眼分清"好看"与"有雷"。验收:目检〈危险状态均为形状+颜色双通道,色弱模拟下可辨〉
|
格子即地牢地形:未开 = 抬升合并岩体,已开 = 连续地面,雷 = 地面上的巢穴(格态定义与玩家说法见《排雷玩法》),图类型(board_type)= 同款材质换色板。图类型与变异格的视觉差异一律先做色板变体,不做新资产;一切危险状态必须"形状 + 颜色"双通道冗余,色弱可辨。像 Moonlighter 之处在岩板缝质感与暖色道具,但装饰禁止伪装成逻辑差异——玩家须一眼分清"好看"与"有雷"。验收:目检〈危险状态均为形状+颜色双通道,色弱模拟下可辨〉
|
||||||
|
|
||||||
格子同时是**内容舞台**,格与格的美术表达按格内实态分层多样化(画法细则 §3.2)。已开格按当格结果整格表达——产资源格嵌对应家族物件纹样(地图战斗资源九类型,§4.6.3)、纯安全格呈现干净裸土、危险格巢穴更凶。未开格在覆尘完整砖之上叠加**装饰变体**(裂纹/碎石斑/物件级点缀等氛围层),用途是破除大面积同砖平铺的重复感。物件级装饰(小石块/陶片/骨殖等)须走**专属装饰形状家族**:形与信息元素(数字/小人/封印印记/纹样)形状语言隔离,灰度下不与任何逻辑元素同形。零信息纪律:随机分布、与雷/安/类型零相关、禁止构成可读线索、分布每板一次跨轮不复掷。焦点预算约束:装饰不构成完整凸形、不抢读(§3.4);数量配额按图类型定(候选 3–5 种,样张已冻结,§1.4)。未开格的类型预读画为**类型微光单通道**(色相+明度双码;仍只表达类型,不泄危险格与安全格——呈现契约见 §4.6.3;概念定义、可见范围与生命周期见《HUD框架》「未开格类型微光」节)。验收:目检〈物件级装饰与逻辑元素形状隔离;装饰不构成完整凸形〉
|
格子同时是**内容舞台**,格与格的美术表达按格内实态分层多样化(画法细则 §3.2)。已开格按当格结果整格表达——产资源格嵌对应家族物件纹样(地图战斗资源九类型,§4.6.3)、纯安全格呈现干净裸土、危险格巢穴更凶。未开格在抬升岩体顶面之上叠加**装饰变体**(裂纹/碎石斑/物件级点缀等氛围层),用途是破除大面积同材质平铺的重复感。物件级装饰(小石块/陶片/骨殖等)须走**专属装饰形状家族**:形与信息元素(浮空数字/小人/封印印记/纹样)形状语言隔离,灰度下不与任何逻辑元素同形。零信息纪律:随机分布、与雷/安/类型零相关、禁止构成可读线索、分布每板一次跨轮不复掷。焦点预算约束:装饰不构成完整凸形、不抢读(§3.4);数量配额按图类型定(候选 3–5 种,样张已冻结,§1.4)。未开格的类型预读画为**类型微光单通道**(色相+明度双码;仍只表达类型,不泄危险格与安全格——呈现契约见 §4.6.3;概念定义、可见范围与生命周期见《HUD框架》「未开格类型微光」节)。验收:目检〈物件级装饰与逻辑元素形状隔离;装饰不构成完整凸形〉
|
||||||
|
|
||||||
*设计测试:当新图类型或新变异格需要新视觉时,先换色板加形状,再谈新资产;当格子多样化与"好看/有雷"之辨冲突时,砍装饰,不动逻辑通道。*
|
*设计测试:当新图类型或新变异格需要新视觉时,先换色板加形状,再谈新资产;当格子多样化与"好看/有雷"之辨冲突时,砍装饰,不动逻辑通道。*
|
||||||
|
|
||||||
### 1.4 格子样张测试(验收标准)
|
### 1.4 格子样张测试(验收标准)
|
||||||
|
|
||||||
> 立意:扫雷数字可读性与暗色氛围相冲突,由一次格子样张测试定风格,具体形态由样张测试定稿。**样张** = 一张按本圣经参数画成的格子风格试验图,是砖面形态的定稿闸——样张通过前,§3.2/§4.1 的一切参数只是候选,通过后冻结为制作标准。
|
> 立意:扫雷数字可读性与暗色氛围相冲突,由一次格子样张测试定风格,具体形态由样张测试定稿。**样张** = 一张按本圣经参数画成的格子风格试验图,是棋盘地形形态(岩体+地面+浮空数字)的定稿闸——样张通过前,§3.2/§4.1 的一切参数只是候选,通过后冻结为制作标准。
|
||||||
|
|
||||||
**样张内容清单**(一图齐备,缺项即无效):未开格(覆尘完整砖,含至少两种装饰变体)、已开格(碎裂裸露,含 0 格与 1–8 全档数字)、危险格(被惊动的巢穴)、封印印记、小人两态(独立占格 + 与数字同格——后者须验"边框高亮不覆盖文本")、图类型色板变体组(§4.3 四槽换色,至少两套)、数字呈现组(已开格底亮墨直画组 + 复杂格底色牌后备组——素底/装饰变体底/变异纹带底至少三种格底上各一组数字)、已开格结果表达组(纯安全格 + 至少两类型物件纹样)、**类型微光呈现组**(至少三个类型的微光在纯砖格上呈现——样张为静态定格测试图,非运行时行为承诺,实际可见时机见《HUD框架》「未开格类型微光」节;含两两相邻格微光并列;微光格内零角嵌/箭头/加号类附加图形)。验收:目检〈样张图含清单全部组项〉
|
**样张内容清单**(一图齐备,缺项即无效):未开格(合并岩体:岩顶大板+南/东崖面,含至少两种装饰变体)、已开格(连续地面,含 0 格与 1–8 全档浮空数字)、危险格(地面上的巢穴纹)、封印印记(画在已揭示地面+受光棱封印石上)、小人两态(独立占格 + 与数字同格——后者须验"数字与引导线完整可见")、图类型色板变体组(§4.3 四槽换色,至少两套)、数字呈现组(浮空数字+引导线:地面格/岩顶格/顶行越出棋盘三种背景各一组,含 1–8 全档)、已开格结果表达组(纯安全格 + 至少两类型物件纹样)、**遮挡组**(小人站在南邻岩体的北侧,脚底被岩体自然遮住;小人与数字同格时数字仍完整可见)、**类型微光呈现组**(至少三个类型的微光在纯岩顶格上呈现——样张为静态定格测试图,非运行时行为承诺,实际可见时机见《HUD框架》「未开格类型微光」节;含两两相邻格微光并列;微光格内零角嵌/箭头/加号类附加图形)。验收:目检〈样张图含清单全部组项〉
|
||||||
|
|
||||||
**验收项按序判定,第一项不过 = 整张否决(数字可读性定风格,风格服从可读)**:
|
**验收项按序判定,第一项不过 = 整张否决(数字可读性定风格,风格服从可读)**:
|
||||||
|
|
||||||
1. **第一验收项|数字可读性(硬指标,可测)**:1–8 全档数字对其所在**已开格底**直画 WCAG 对比 ≥4.5:1(参数域见 §4.1:已开格底走世界底层档、棋盘数字墨亮族);复杂格底(物件纹样/变异纹带/微光叠加致直画对比不足)启用**色牌后备**,牌墨组合 ≥4.5:1(色牌与牌上深墨族数字的定值见 §4.1),牌缘灰度可分;0.5× 缩放抽检数字仍可辨;纹带/裂纹/巢穴纹/物件纹样禁止侵入数字字形占位区(砖心留白,§3.2)。验收:机检〈1–8 数字对已开格底直画与牌墨组合对比均 ≥4.5:1〉
|
1. **第一验收项|数字可读性(硬指标,可测)**:棋盘数字一律为浮空描边字(§3.2「浮空数字」条):字芯暖白 `#F0E2C8`、2px 深墨描边 `#1A140E`、1px 浮空投影、2px 双色引导线;不使用数字底牌。对比判据 = `max(字芯对底, 描边对底) ≥4.5:1` 且 `字芯对描边 ≥4.5:1`;抽测底 = 地面 `#695038`、岩顶 `#9C8462`、崖面 `#403325`、板外暗底四类;最亮底岩顶实测描边对底 5.1:1 过门。0.5× 缩放抽检数字仍可辨;纹带/裂纹/巢穴纹/物件纹样禁止侵入浮空数字与引导线占位区(浮空层独立于格面,格面纹样禁止升到浮空层)。验收:机检〈四类底上 max(字芯对底,描边对底) ≥4.5 且字芯对描边 ≥4.5〉
|
||||||
2. **格态三形可辨(灰度通道)**:未开/已开/雷三态转灰度截图后仍可逐格分类;明度差(墙亮/空间暗)与碎裂形同为合法分类通道,双通道冗余(§3.2 完整度叙事)。装饰变体禁止制造新的分类特征——同一格态下带与不带变体的灰度差异禁止成为三态分类线索。色弱模拟(去色相)下封印印记、巢穴纹不与裂纹混淆。**五组类型微光互辨**:色弱玩家的类型主通道 = 微光,色相+明度双码,微光以明度梯度承载分组(组内不细分,属 §2 信息面层内梯度);微光禁止侵入数字字形占位区,明度梯度禁止压破格底明度档(三态分类不受扰)。验收:目检〈三态灰度逐格可分类;五组微光互辨;色弱模拟下封印印记、巢穴纹不与裂纹混淆〉
|
2. **格态三形可辨(灰度通道)**:未开/已开/雷三态转灰度截图后仍可逐格分类;合并岩体不改变三态分类——未开 = 抬升岩体,已开 = 连续地面,雷 = 地面上的巢穴纹;明度差(岩顶亮/地面暗)与巢穴形同为合法分类通道,双通道冗余(§3.2 完整度叙事)。装饰变体禁止制造新的分类特征——同一格态下带与不带变体的灰度差异禁止成为三态分类线索。色弱模拟(去色相)下封印印记、巢穴纹不与裂纹混淆。**五组类型微光互辨**:色弱玩家的类型主通道 = 微光,色相+明度双码,微光以明度梯度承载分组(组内不细分,属 §2 信息面层内梯度);微光禁止侵入浮空数字占位区,明度梯度禁止压破岩顶/地面明度档(三态分类不受扰)。验收:目检〈三态灰度逐格可分类;五组微光互辨;色弱模拟下封印印记、巢穴纹不与裂纹混淆〉
|
||||||
3. **焦点预算成立(§3.4)**:任意一格至多一个完整凸形;数字所在格无第二焦点。验收:目检〈任一格至多一个完整凸形,数字所在格无第二焦点〉
|
3. **焦点预算成立(§3.4)**:任意一格至多一个信息完整凸形(浮空数字/小人/封印印记);岩体为连续地形,不作单格凸形计;数字所在格无第二信息焦点。验收:目检〈任一格至多一个信息完整凸形,数字所在格无第二焦点〉
|
||||||
4. **图类型换皮抽测(§4.3)**:变体组中数字墨亮族三档、封印黑、危险红、奖励金、小人蓝、数字色牌(后备件)、类型微光五组恒定不动;变体格底仍过第 1、2 项指标。验收:机检〈换皮后不变槽色值恒定,变体格底仍过第 1、2 项〉
|
4. **图类型换皮抽测(§4.3)**:变体组中浮空数字字芯/描边、封印黑、危险红、奖励金、小人蓝、类型微光五组恒定不动;变体岩顶/地面底仍过第 1、2 项指标。验收:机检〈换皮后不变槽色值恒定,变体岩顶/地面底仍过第 1、2 项〉
|
||||||
|
|
||||||
**判定与回退**:第 1 项不过时按原则二设计测试回退——先调格底明度档,复杂格底垫色牌后备,禁止缩字号换字形逃避;第 2–4 项不过时修形不修数。样张通过 = 砖面形态与色板冻结;新增图类型/变异色板须重跑本测试(§4.3)。执行时机:正式砖面资产开工前;《HUD框架》以本节为引用依据。验收:机检〈样张机检断言集全绿后方可冻结砖面形态与色板〉
|
**判定与回退**:第 1 项不过时按原则二设计测试回退——先调岩顶/地面明度档,禁止使用数字底牌;浮空字描边是唯一可读性装置,禁止缩字号换字形逃避;第 2–4 项不过时修形不修数。样张通过 = 棋盘地形形态与色板冻结;新增图类型/变异色板须重跑本测试(§4.3)。执行时机:正式地形资产或程序化材质开工前;《HUD框架》以本节为引用依据。验收:机检〈样张机检断言集全绿后方可冻结地形形态与色板〉
|
||||||
|
|
||||||
**整屏样张闸**:格子样张验"格",整屏样张验"屏"——战斗屏/关卡屏/菜单屏/营地屏各出一张整屏样张,验收四项:①全部文字(含菜单/说明/tooltip/按钮)对其直接背景 ≥4.5:1(WCAG AA),大字(≥18px 或加粗档)底线 3:1、目标 4.5:1;②明度分层三档带成立(信息面层 > 世界中层 > 世界底层,层间灰度可分);③整屏焦点预算(§3.4:首焦唯一——数字区/立绘/主按钮,无第二焦点竞争;负空间服务焦点,不属空窗);④文字禁直接压纹理底(垫容器或罩层)。验收顺序 = **方向稿目检先行**(防"机检过闸但气质否决"式返工),目检过后机检冻结。执行时机 = 屏级视觉落码开工前;过闸前一切屏级视觉为占位临时态(§7.1 完成条款)。**样张判定物的产出手段与素材输入级别不进圣经定值**——圣经只定样张要验什么,不定样张以何种手段产出、也不定它取哪一级别素材输入。验收:机检〈整屏样张四项断言全绿,且目检先行过审〉
|
**整屏样张闸**:格子样张验"格",整屏样张验"屏"——战斗屏/关卡屏/菜单屏/营地屏各出一张整屏样张,验收四项:①全部文字(含菜单/说明/tooltip/按钮)对其直接背景 ≥4.5:1(WCAG AA),大字(≥18px 或加粗档)底线 3:1、目标 4.5:1;②明度分层三档带成立(信息面层 > 世界中层 > 世界底层,层间灰度可分);③整屏焦点预算(§3.4:首焦唯一——数字区/立绘/主按钮,无第二焦点竞争;负空间服务焦点,不属空窗);④文字禁直接压纹理底(垫容器或罩层)。**浮空数字为描边字,按 §1.4 第一验收项的复合对比判据,不套本条文字直画 4.5:1 口径。** 验收顺序 = **方向稿目检先行**(防"机检过闸但气质否决"式返工),目检过后机检冻结。执行时机 = 屏级视觉落码开工前;过闸前一切屏级视觉为占位临时态(§7.1 完成条款)。**样张判定物的产出手段与素材输入级别不进圣经定值**——圣经只定样张要验什么,不定样张以何种手段产出、也不定它取哪一级别素材输入。验收:机检〈整屏样张四项断言全绿,且目检先行过审〉
|
||||||
|
|
||||||
**战斗一屏样张**:整屏样张闸已过——整屏四项机检全绿,方向稿目检已通过(用户实机目检核销,沿革查 git 提交史)
|
**战斗一屏样张**:整屏样张闸已过——整屏四项机检全绿,方向稿目检已通过(用户实机目检核销,沿革查 git 提交史)
|
||||||
|
|
||||||
**样张现状**:格子样张已冻结,冻结凭据 = §4.1/§8.2 定值表;样张 v3 产物原件已丢失、未入 git。现行冻结态:色板与帧数档维持冻结;数字形制 = 亮墨三档直画 + 色牌后备(值见 §4.1);新增图类型/变异色板须重跑本节测试。验收:机检〈冻结项定值均以 §4.1/§8.2 对应 owner 表为准〉
|
**样张现状**:格子样张已冻结,冻结凭据 = §4.1/§8.2 定值表;样张 v3 产物原件已丢失、未入 git。现行冻结态:色板与帧数档维持冻结;数字形制 = 浮空描边字(暖白字芯 + 2px 深墨描边 + 双色引导线,值见 §4.1/§3.2);普通数字色牌退役(封印格身份字形色牌保留,见 §3.2 封印印记条);新增图类型/变异色板须重跑本节测试。验收:机检〈冻结项定值均以 §4.1/§8.2 对应 owner 表为准〉
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -159,29 +159,31 @@
|
|||||||
|
|
||||||
### 3.2 环境几何
|
### 3.2 环境几何
|
||||||
|
|
||||||
- **雷图棋盘呈现基准**:战棋地块质感 × 正俯视角——取 ITB 参考图(`references/itb_1.jpg`)的地表质感骨架:地块纹理多样、起伏体块感、岛缘/砖缘厚度、格上装饰小立牌;但相机一律正上方垂直向下,格线屏轴对齐,**禁等距/斜视角与菱形格**;形状语言仍守总纲圆角方形。砖缘厚度与岛缘立体面属形体塑造(顶面格底仍守 §4.1 参数域)。装饰小立牌属 ITB 参考的观感元素,本作不采用;装饰变体走氛围层纪律(纹理级/物件级形状家族,见下方装饰变体条),零信息纪律以原则三为准。验收:目检〈棋盘正俯视、格线屏轴对齐、无菱形格〉 ←原二;原三;§2
|
- **雷图棋盘呈现基准**:战棋地块质感 × 正俯视角——取 ITB 参考图(`references/itb_1.jpg`)的地表质感骨架:地块纹理多样、起伏体块感、岛缘/砖缘厚度;但相机一律正上方垂直向下,格线屏轴对齐,**禁等距/斜视角与菱形格**;形状语言仍守总纲圆角方形。**立体表现取抬升合并岩体+南/东崖面**(2026-11-07 用户裁,采 Link's Awakening 原版/DX 2D 的台面抬升与崖面观感,2019 重制 3D 立体模型版不作参考);砖缘厚度与岛缘立体面属形体塑造(岩顶/地面仍守 §4.1 参数域)。装饰小立牌属 ITB 参考的观感元素,本作不采用;装饰变体走氛围层纪律(纹理级/物件级形状家族,见下方装饰变体条),零信息纪律以原则三为准。验收:目检〈棋盘正俯视、格线屏轴对齐、无菱形格;未开格呈抬升合并岩体+南/东崖面〉 ←原二;原三;§2
|
||||||
- **地砖**:一切环境体由同一圆角方形衍生:未开 = 完整凸砖,已开 = 同形缺角碎裂,雷 = 碎裂加巢穴纹(危险格玩家说法见《排雷玩法》);只以"完整度"叙事,不为状态新造形。验收:目检〈三格态仅以完整度区分,无新造状态形〉 ←原三;P4
|
- **地形**:一切环境体由同一圆角方形衍生:未开 = 抬升岩体(完整),已开 = 连续地面(挖出空间),雷 = 地面上的巢穴纹(危险格玩家说法见《排雷玩法》);只以“完整/挖开”叙事,不为状态新造形。验收:目检〈三格态仅以完整/挖开与巢穴纹区分,无新造状态形〉 ←原三;P4
|
||||||
- **装饰变体(未开格氛围层)**:覆尘完整砖之上叠加裂纹/碎石斑/物件级点缀等装饰。物件级装饰(小石块/陶片/骨殖等)须走**专属装饰形状家族**(与信息元素形状语言隔离、灰度下不与任何逻辑元素同形),数量配额按图类型定(候选 3–5 种,样张已冻结,§1.4),一律残缺、内凹、低对比而自然后退(§3.4);零信息纪律(分布随机、与雷/安/类型零相关、灰度下禁止制造新分类特征、分布每板一次跨轮不复掷)以原则三为准,此处不赘。验收:目检〈物件级装饰不与任何逻辑元素同形;装饰残缺低对比后退〉 ←原三
|
- **装饰变体(未开格氛围层)**:抬升岩体的顶面之上叠加裂纹/碎石斑/物件级点缀等装饰。物件级装饰(小石块/陶片/骨殖等)须走**专属装饰形状家族**(与信息元素形状语言隔离、灰度下不与任何逻辑元素同形),数量配额按图类型定(候选 3–5 种,样张已冻结,§1.4),一律残缺、内凹、低对比而自然后退(§3.4);零信息纪律(分布随机、与雷/安/类型零相关、灰度下禁止制造新分类特征、分布每板一次跨轮不复掷)以原则三为准,此处不赘。验收:目检〈物件级装饰不与任何逻辑元素同形;装饰残缺低对比后退〉 ←原三
|
||||||
- **结果整格表达(已开格)**:已开格按当格结果整格表达(结果清单见原则三);画法——产资源格的家族物件纹样用 §3.1 道具点剪影语言(直线几何体)角嵌于砖缘,砖心与数字字形占位区留白(已开格仍承载数字);危险格巢穴纹较已开格更凶一档,形状+颜色双通道。验收:目检〈产资源格嵌家族纹样且砖心留白;巢穴纹更凶一档〉 ←原三;P3
|
- **结果整格表达(已开格)**:已开格按当格结果整格表达(结果清单见原则三);画法——产资源格的家族物件纹样用 §3.1 道具点剪影语言(直线几何体)角嵌于格面边缘,格心留白(数字已迁浮空层,格面纹样不再需要给字形让位;封印格身份字形走色牌例外,见封印印记条,仍禁止升到浮空层);危险格巢穴纹较已开格更凶一档,形状+颜色双通道。验收:目检〈产资源格嵌家族纹样且格心留白;巢穴纹更凶一档〉 ←原三;P3
|
||||||
- **未开格预读通道(微光单通道)**:类型预读 = 类型微光单通道(色相+明度双码,色带 §4.2);色弱类型主通道 = 微光明度梯度(组粒度——组间互辨;§2 微光明度例外);格内零角嵌/箭头/加号类附加形(微光格只留微光)。验收:目检〈微光格内零角嵌/箭头/加号类附加形〉 ←原一;原三
|
- **未开格预读通道(微光单通道)**:类型预读 = 类型微光单通道(色相+明度双码,色带 §4.2);色弱类型主通道 = 微光明度梯度(组粒度——组间互辨;§2 微光明度例外);格内零角嵌/箭头/加号类附加形(微光格只留微光)。微光画在抬升后的岩顶面内,锚点随岩顶偏移(−ESHIFT/−LIFT),禁止越出本格岩顶。验收:目检〈微光格内零角嵌/箭头/加号类附加形;微光不越本格岩顶〉 ←原一;原三
|
||||||
- **封印印记**:封印动作的叙事呈现 = **封印**(玩家可见专名,术语定义见 [术语表](../gdd/术语表.md)「封印」条;动作面见《排雷玩法》)——封印动作落在格上的印记称封印印记。**形 = 法阵**:一圈外环+环内一个十字,十字四端顶到环内沿、与环连成一体——两层构成取法阵通用骨架(外环=圈定范围,环内图形=力量图形,非指特定作品):环=封印圈定,十字=钉住此格。**画法 = 参数化绘制**(着色器按格边实时画环与十字,不出贴图):格边 26–46px 连续可变,任何贴图源都得非整数缩放(32px 源在 28 格缩到 0.875、在 46 格放到 1.44),像素必宽窄不均;参数化按比例画,任意格边清晰。**环外光圈**:印记外面一圈**压暗光**(纯黑只加透明度)——自环外缘起、向外衰减到格边为止、**不外溢邻格**,作用 =「此格被罩住」;禁中心亮、禁色相、禁呼吸。**尺寸定值**见 §8.2「封印印记参数表」(本处不复述数值)。**色** = 封印黑 `#000000`(§4.1),光圈只改 alpha、不新增色。**占位**:印记居格心,环外留 9% 格宽给光圈(见 §8.2);封印印记只出现在未开格,不与数字同格。格内栈位见 §1.2;层序纪律——印记层低于小人,且迷雾态(区外全黑/记忆态)隐藏(§6.5「封印随格隐没」)。封印特效两件:常显形态即本件,施印瞬间未实装。战末金蜡封徽记仍取贴图 `seal_mark.png`(与棋盘侧参数化绘制并存,两处互不依赖)。验收:目检〈环径占格宽 82%±1px;光圈只在环外且不出格;纯黑无色相〉 ←原一;P2
|
- **封印印记**:封印动作的叙事呈现 = **封印**(玩家可见专名,术语定义见 [术语表](../gdd/术语表.md)「封印」条;动作面见《排雷玩法》)——封印动作落在格上的印记称封印印记。**形 = 法阵**:一圈外环+环内一个十字,十字四端顶到环内沿、与环连成一体——两层构成取法阵通用骨架(外环=圈定范围,环内图形=力量图形,非指特定作品):环=封印圈定,十字=钉住此格。**画法 = 参数化绘制**(着色器按格边实时画环与十字,不出贴图):格边 26–46px 连续可变,任何贴图源都得非整数缩放(32px 源在 28 格缩到 0.875、在 46 格放到 1.44),像素必宽窄不均;参数化按比例画,任意格边清晰。**环外光圈**:印记外面一圈**压暗光**(纯黑只加透明度)——自环外缘起、向外衰减到格边为止、**不外溢邻格**,作用 =「此格被罩住」;禁中心亮、禁色相、禁呼吸。**尺寸定值**见 §8.2「封印印记参数表」(本处不复述数值)。**色** = 封印黑 `#000000`(§4.1),光圈只改 alpha、不新增色。**占位**:印记居**格心**(已揭示连续地面;环外留 9% 格宽给光圈,见 §8.2);封印印记出现在**已揭示格**上(封印受理即揭示——机制口径见《排雷玩法》动作合法性节,呈现规格与预览见《ux/battle》「封印格呈现预览」节)——格下身份字形(危/数字)按格内栈位(§1.2 数字 > 印记)垫色牌叠于法阵之上,印记与数字同格合法;该格字形不参与浮空数字层。**承载面**:封印格地面铺本关受光棱色封印石(dungeon `#C9AF83`/underdark `#A1B1BF`/deep_underdark `#918E8B`,§4.1)——新连续地面 `#695038` 系对封印黑仅 2.35–2.98:1,不达 §4.1 ≥4.5:1;受光棱系 6.45–9.94:1,零新增色。格内栈位见 §1.2;层序纪律——印记与身份色牌固定低于小人(不参与南侧格件前推),且迷雾态(区外全黑/记忆态)隐藏(§6.5「封印随格隐没」)。封印特效两件:常显形态即本件,施印瞬间未实装。战末金蜡封徽记仍取贴图 `seal_mark.png`(与棋盘侧参数化绘制并存,两处互不依赖)。验收:目检〈环径占格宽 82%±1px;光环居格心、只在环外且不出格;纯黑无色相〉 ←原一;P2
|
||||||
- **可挖域接触带微光(交互反馈层)**:挖掘期,英雄格周界与可挖域(概念见《排雷玩法》动作合法性节;呈现义务见《HUD框架》可挖域指示)的接触面画呼吸微光——正交邻墙 = 该侧整条边,斜向邻墙 = 共享角点 + 向两侧各延伸半条边;光只画英雄格(空间)一侧、不进墙格(与装饰变体零冲突,数字砖心不涉);微光 = 空间的灯光边界(画法规则)。色相 = 蓝族浅一档(§4.2 蓝条;与主角蓝框的分层由样张测试定,§1.4);呼吸 = §2.1 挖掘期唯一在动元素,减动效停格。角点为斜墙与正交墙共享、不逐格归因,逐格指认 = 悬停金框(呈现交互归《HUD框架》悬停指示域)。验收:目检〈微光只画英雄格一侧接触面:正交邻墙整条边、斜向邻墙角点 + 半边〉 ←§2.1;§4.2;P1
|
- **可挖域接触带微光(交互反馈层)**:挖掘期,英雄格周界与可挖域(概念见《排雷玩法》动作合法性节;呈现义务见《HUD框架》可挖域指示)的接触面画呼吸微光——正交邻墙 = 该侧整条边,斜向邻墙 = 共享角点 + 向两侧各延伸半条边;光只画英雄格(空间/地面)一侧、不进岩体(岩体抬升不改变接触带的逻辑格边;光画在地面侧,不贴岩顶;与装饰变体零冲突);微光 = 空间的灯光边界(画法规则)。色相 = 蓝族浅一档(§4.2 蓝条;与主角蓝框的分层由样张测试定,§1.4);呼吸 = §2.1 挖掘期唯一在动元素,减动效停格。角点为斜墙与正交墙共享、不逐格归因,逐格指认 = 悬停金框(呈现交互归《HUD框架》悬停指示域)。验收:目检〈微光只画英雄格一侧接触面:正交邻墙整条边、斜向邻墙角点 + 半边;光不进岩体〉 ←§2.1;§4.2;P1
|
||||||
- **墙体**:圆角砌块堆叠,禁尖刺装饰——尖刺专属危险语义,装饰禁止伪装逻辑差异。验收:目检〈墙体无尖刺装饰〉 ←原三
|
- **岩体**:圆角岩体堆叠/合并,禁尖刺装饰——尖刺专属危险语义,装饰禁止伪装逻辑差异。验收:目检〈岩体无尖刺装饰〉 ←原三
|
||||||
- **高墙瓦片体系|术语与定义**:未挖格 = **一整块 32×32 自含凸起岩体**;素材语义名——未开格素材 = **墙瓦片**,已开格素材 = **地面瓦片**。瓦片以自含岩体为单位,Tiny Dungeon 拼块套不进自含岩体定义,不作瓦片参考。验收:目检〈未开格为整块凸起岩体,无拼块接缝感〉 ←原三
|
- **棋盘地形体系|术语与定义**:未开格 = **抬升岩体**——连通的未开格(四邻:上下左右;斜角不连)合并为一块岩体,共享一块岩顶与连续崖面;已开格 = **连续地面**。素材语义名——岩顶材质 = **大岩板**,南/东崖面材质 = **崖面**,已开地面 = **地面**;**不做逐格自含瓦片**,Tiny Dungeon 拼块套与逐格 16+5 墙/地瓦片套均退役(2026-11-07 用户裁)。验收:目检〈连通未开格共享一块岩顶与连续崖面,无逐格拼缝〉 ←原三
|
||||||
- **高墙瓦片体系|边界墨线纪律**:墙瓦片与相邻格分界一律 1px 深墨线、直线贴格边、零锯齿;墨线职责 = 分隔,不追求与地面融合。验收:目检〈分界为 1px 深墨直线贴格边、零锯齿〉
|
- **棋盘地形体系|投影与搭接**:整块岩顶向北偏西抬升——LIFT = round(格边 × 0.435)(46 格 20px、26 格 11px,下限 1),ESHIFT = round(格边 × 0.109)(46 格 5px、26 格 3px,下限 1);南/东崖面沉在岩体格内(南面高 = LIFT,东面宽 = ESHIFT,东面高 = 格边 + LIFT),不侵下一行地面;相邻岩体的岩顶按 2px 互相搭接盖住格缝;板边岩顶向外延伸 ESHIFT 铺到板缘。单个墙格的**顶面 rect** = 格矩形左上偏移 (−ESHIFT, −LIFT)、边长 = 格边;**整格视觉 rect** = 顶面 rect 向右补 ESHIFT、向下补 LIFT。验收:机检〈LIFT/ESHIFT 比例与下限;相邻岩顶搭接 2px;崖面不越格〉
|
||||||
- **高墙瓦片体系|光照纪律(单一北受光)**:北缘 = 墨线内侧 1px 微亮棱(就地取色提亮,禁宽亮带);西/东缘 = 墨线后直进纹理、不加修饰;南缘 = 墨线 + 立面窄暗条(约 1/3 格高,横层理叠石、禁竖条纹栅栏感)。验收:目检〈北缘亮棱、南缘窄暗条;无宽亮带、无竖条纹栅栏感〉
|
- **棋盘地形体系|受光与崖面**:光照 = **北/西受光**(2026-11-07 用户裁)——北/西临空缘 = 2px 主亮棱 + 2px 次亮棱(暖白族就地提亮),再外 2px 深墨临空边线;南/东临空缘 = 2px 深墨内缘 + 3 段 ×2px 顶面内阴影(自缘内 0.217×格边起,黑 α≈0.27/0.16/0.08)。南崖面 = 高 LIFT、宽 = 格边 + ESHIFT,顶缘 2px 口沿高光取本关受光棱(§4.1,dungeon `#C9AF83`)+1px 深墨线,面身横向层理叠石(大岩板同族、背光暗面),禁竖条纹栅栏;东崖面 = 宽 ESHIFT、高随岩顶南缘,横向层理、外缘 1px 深墨。验收:目检〈北/西亮棱、南/东内阴影与崖面层理;南崖不越下一行、东崖不越下一列;无竖条纹〉
|
||||||
- **高墙瓦片体系|凹角收头**:角点单像素落线;南立面侧凹角加 1px 立面收头——带身与转角竖线同列收尾,禁悬空、禁突出。验收:目检〈凹角收头与转角竖线同列,无悬空突出〉
|
- **棋盘地形体系|材质与装饰**:岩顶 = **大岩板**(低频率斑驳 + 稀疏大板块缝 + 板缘浮雕倒角,单块材质覆盖整块岩体;禁逐格小砖纹与逐格边框);地面 = 连续暖褐土(低对比石屑、碎石斑;无缝,禁逐格砖缝);装饰变体 = 岩顶材质内的低对比裂纹/麻点/碎石贴花,走原则三零信息纪律,不新增逐格资产。验收:目检〈岩顶为单块大岩板、无逐格拼缝;地面连续无缝;装饰不构成逻辑线索〉
|
||||||
- **高墙瓦片体系|现行定稿**:`game/assets/art/board/terrain_*`(16 唯一墙瓦片 + 5 地面瓦片变体;词表与查表逻辑落码于 `board_world.gd`)。验收:机检〈terrain_* 素材 16 墙瓦片 + 5 地面变体在库,查表逻辑与词表一致〉
|
- **棋盘地形体系|投影与整板悬崖**:南/东临空岩体在地面投 4 段 ×4px 渐隐影(黑 α 0.44/0.30/0.16/0.07,自崖面外缘起);整板悬崖 = 板底/右侧 `DEPTH_PX 8px` 暗面 + 岩层横纹 + 口沿高光 + 接触 AO + 底线收边 + 悬浮影,色取棋盘环境子板(§4.1)。验收:目检〈南/东投影四段渐隐;整板悬崖结构件齐备〉
|
||||||
- **高墙瓦片体系|高墙感 D 投影档与整板悬崖**:南临空墙格 = 立面口沿高光 2px `#C9AF83`(201,175,131——代码色 `BRICK`,与掩尘枚同源单点) + 双段暗带(0.16/0.25 格边,黑罩 α0.60/0.82);北邻墙地面格 = 三段渐隐投影(顶带 0.22 格边,α0.28 起);整板悬崖 = 板底/右侧 `DEPTH_PX 8px` 暗面 + 列分隔竖缝 + 岩层横纹 + 口沿高光 + 接触 AO + 底线收边 + 悬浮影(游戏 `board_world.gd` 同款结构件,样张脚本与游戏渲染常量同源)。验收:目检〈南临空墙格呈口沿高光+双段暗带;北邻墙地面格呈三段渐隐投影;整板悬崖结构件齐备〉
|
- **棋盘地形体系|绘制序与遮挡**:层序 = 地面(封印格地面铺本关受光棱色封印石)→ 投影 → 数字所属格的**地面阴影圆**(开启格地面,位于小人之下,小人站该格时遮住圆)→ **按脚底 y 排序的深度对象**(岩体 = 其最南格格底;小人 = 所在格格底;升序绘制,南侧岩体自然遮住小人脚底)→ 顶面贴花(类型微光/变异纹带,随岩顶锚点偏移 −ESHIFT/−LIFT;只在未开格岩顶)与交互反馈(悬停/路径/可挖域微光)随所属格件同序——北侧(脚底≤小人)低于小人,南侧(脚底>小人)随岩体在前;封印印记与封印格身份色牌在已揭示地面、固定低于小人(不参与南侧前推)→ **浮空数字+引导线(最顶)**。验收:机检〈深度对象按脚底升序绘制;格件贴花/交互随脚底行分档;浮空层 z 最高〉+目检〈南侧岩体遮住小人脚底;顶行数字越出棋盘仍完整〉
|
||||||
- **变异格形状通道**(双通道之"形",与色无关):底砖圆角外轮廓不变,砖面内缘绘一圈定宽专属几何纹带(纹带形全作不与他类共用),砖心留白予数字与封印印记;验收标准 = **灰度截图下仍可分类**。种类清单 = 地形变异六类型已定稿(地形变异 GDD;荆棘丛/藤蔓缠绕/岩浆/烬覆/落石/矿尘):**纹带形按轴只分两种**——伤害轴(荆棘丛/岩浆/落石)= 刺/缺排斥形,信息轴(藤蔓缠绕/烬覆/矿尘)= 遮蔽/缠绕形;同轴跨图类型只做色板变体(§4.3 `variant_tint` 槽),不做新纹形。岩浆纹带橙红须与危险红互辨(变异格不是雷,色相邻近有混淆风险);信息轴遮蔽呈现禁止侵入数字字形占位区(§1.4 验收 1 延伸)。验收:目检〈六类型纹带灰度下仍可分类,同轴不新增纹形;岩浆纹带与危险红互辨〉 ←原一(纹理位次第 4,让位于数字/小人/封印印记);原三
|
- **棋盘地形体系|浮空数字(信息层)**:数字与格面字形(危/?)脱离格面,浮在格上方——**封印格除外**,其身份字形按封印印记条垫色牌叠于法阵之上、不进浮空层;字高 21px(7px 像素字 ×3,固定不随格边缩放)、2px 深墨描边、字芯暖白 `#F0E2C8`、1px 浮空投影;字底距格顶 15px;引导线 = 2px 双色实线(左深 `#1A140E`/右浅 `#E8D3AB`),自字底 +3 落到格顶 +4;格顶 +7 处画 10×6 四层柔边小阴影圆(标明数字所属格),圆画在开启格地面、位于小人之下,不盖小人。浮空层 z 最高,任何地形/小人/特效不遮数字与引导线。顶行数字出棋盘上缘,D 区上方预留 44px(字高 21+间距 15+描边 2+余量 6)。验收:机检〈字高 21、间距 15、顶预留 44;浮空层 z 最高;封印格无浮空 entries〉+目检〈顶行数字与引导线完整;阴影圆指向正确格〉
|
||||||
|
- **棋盘地形体系|旧资产处理**:旧 `terrain_*` 63 件(16 墙瓦片 + 5 地面变体,三关各一套)全部退役——无参考价值者直接删除,不归档;`seal_mark.png` 保留(战末金蜡封专用)。验收:机检〈旧 terrain_* 零引用、零在库;seal_mark 在库〉
|
||||||
|
- **变异格形状通道**(双通道之"形",与色无关):岩体外形由合并岩体决定、不因变异改变;变异纹带画在本格抬升岩顶面内缘(锚点随岩顶偏移 −ESHIFT/−LIFT),一圈定宽专属几何纹带(纹带形全作不与他类共用),格心留白(数字已迁浮空层;封印印记在已揭示地面承载,不与变异纹带同格);验收标准 = **灰度截图下仍可分类**。种类清单 = 地形变异六类型已定稿(地形变异 GDD;荆棘丛/藤蔓缠绕/岩浆/烬覆/落石/矿尘):**纹带形按轴只分两种**——伤害轴(荆棘丛/岩浆/落石)= 刺/缺排斥形,信息轴(藤蔓缠绕/烬覆/矿尘)= 遮蔽/缠绕形;同轴跨图类型只做色板变体(§4.3 `variant_tint` 槽),不做新纹形。岩浆纹带橙红须与危险红互辨(变异格不是雷,色相邻近有混淆风险);信息轴遮蔽呈现禁止侵入浮空数字与引导线占位区(§1.4 验收 1 延伸)。验收:目检〈六类型纹带灰度下仍可分类,同轴不新增纹形;岩浆纹带与危险红互辨〉 ←原一(纹理位次第 4,让位于浮空数字/小人/封印印记);原三
|
||||||
|
|
||||||
### 3.3 UI 形状语法(方向指导,细则见 §7.1)
|
### 3.3 UI 形状语法(方向指导,细则见 §7.1)
|
||||||
|
|
||||||
**方向指导**:半拟物——容器穿戏服、数据素面;圆角 = 可触摸的物件,直角 = 须精确的信息(总纲「圆角为世,直线为信」的 UI 侧落法)。画法细则(面板/按钮/蜡封/数字色牌/参考分界)成文于 **§7.1**。验收:方向性 ←原二;§2.4
|
**方向指导**:半拟物——容器穿戏服、数据素面;圆角 = 可触摸的物件,直角 = 须精确的信息(总纲「圆角为世,直线为信」的 UI 侧落法)。画法细则(面板/按钮/蜡封/参考分界)成文于 **§7.1**。验收:方向性 ←原二;§2.4
|
||||||
|
|
||||||
### 3.4 主角形状与对比预算
|
### 3.4 主角形状与对比预算
|
||||||
|
|
||||||
显著度 = 完整度:**每格至多一个"完整凸形"**(数字/小人/封印印记,依 1.2 优先级让位;装饰变体贴砖缘分布、不构成第二完整凸形——§4.6;数字色牌随数字一体,不作独立焦点;类型微光为底效泛光,不作焦点、不抢完整凸形预算),底砖与装饰一律残缺、内凹、低对比而自然后退;危险用刺与缺(排斥形),收益用满与圆(吸引形),同表预算、此消彼长。焦点分配双机制:**完整度**(形状,本条上文)+ **明度带**(§2 明度分层——信息面层恒亮于世界层,焦点天然落信息面);明暗只做层间分离,层内禁明暗竞争(不靠明暗抢焦)。验收:目检〈任一格至多一个完整凸形;信息面层恒亮于世界层〉 ←原二;P1;P3
|
显著度 = 完整度:**每格至多一个信息完整凸形**(浮空数字/小人/封印印记,依 1.2 优先级让位)。岩体为连续地形,不作单格凸形计;装饰变体贴岩顶分布、不构成第二完整凸形(§4.6);浮空数字的引导线与阴影圆随数字一体,不作独立焦点;类型微光为底效泛光,不作焦点、不抢完整凸形预算。岩体与装饰一律残缺、内凹、低对比而自然后退;危险用刺与缺(排斥形),收益用满与圆(吸引形),同表预算、此消彼长。焦点分配双机制:**完整度**(形状,本条上文)+ **明度带**(§2 明度分层——信息面层恒亮于世界层,焦点天然落信息面);明暗只做层间分离,层内禁明暗竞争(不靠明暗抢焦)。验收:目检〈任一格至多一个信息完整凸形;信息面层恒亮于世界层〉 ←原二;P1;P3
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -193,35 +195,42 @@
|
|||||||
|
|
||||||
### 4.1 主色板
|
### 4.1 主色板
|
||||||
|
|
||||||
- **掩尘 `#C9AF83`**|未开格底色,覆尘完整砖:全作的"未知",画面最大沉默面。验收:机检〈未开格底色 = #C9AF83〉 ←原二;§2.1
|
- **掩尘 `#9C8462`**|未开格**岩体顶面基色**(覆尘完整岩体):全作的"未知",画面最大沉默面;原 `#C9AF83` 收缩为受光棱/口沿高光专用(代码 `BRICK` 保留为高光锚色,不再作未开格基色)。验收:机检〈未开格岩顶基色 = #9C8462;#C9AF83 只作受光棱/口沿高光〉 ←原二;§2.1
|
||||||
- **裸土 `#B39A78`**|已开格底色,碎裂裸露:更收更退;明度分层——已开格(挖出的空间)走**世界底层档**,明度低于未开格墙体一档(与 §8.5 图底分离同轴),L 0.08–0.14 带(更高明度底实测达不到 4.5:1,故取本带;样张已冻结,§1.4)。验收:机检〈已开格底 L 落在 0.08–0.14,对亮墨数字 ≥4.5:1〉 ←原三
|
- **裸土 `#695038`**|已开格**连续地面基色**:更收更退;明度分层——已开格(挖出的空间)走**世界底层档**,明度低于未开格岩体一档(与 §8.5 图底分离同轴),L 0.08–0.14 带(样张实测 L≈0.09)。验收:机检〈已开格地面基色 = #695038,L 落 0.08–0.14〉 ←原三
|
||||||
- **数字墨双色制**:1–8 **不做八色分色**,按密度分三档色温(冷 = 稀疏,暖 = 密集);**字形为唯一数值载体**,色温只作密度氛围。验收:目检〈1–8 数字按密度呈三档色温而非八色〉 ←原一/原二;P3
|
- **棋盘环境子板(分层②,不占 48 token 额度)**|现行基座档八色:岩顶 `#9C8462`、地面 `#695038`、崖面 `#403325`、板块缝 `#64523A`、倒角亮 `#CCB288`、倒角暗 `#766248`、临空墨线 `#261E15`、受光棱 `#C9AF83`;单张像素域 ≤32,三关按 §4.3 换色不新增 token。验收:机检〈八色在册、单张像素域 ≤32〉
|
||||||
- **棋盘数字呈现 = 按板自适应三态**:暗纹理板(dungeon 系)= **亮族**三档 1–3 冷亮青白 #D8ECF0/4–5 暖白 #F0E2C8/6–8 金亮 #F8E3A8 直画(判据 = 族最弱成员对 p90 ≥4.5:1 且对均值 ≥2.5:1);双峰纹理板(underdark/deep_underdark 系)= **色牌垫底**(素牌 DIGIT_PLATE + 深墨 #33261B 12:1,纹理免疫——双峰纹理板上任何墨族直画都不可读,渲染帧取证;判据 = 亮深两族皆不过门,深族均值门 3.0);缺盘平色回退态(#B39A78 中明度底)默认深墨直画。选模式管线落码单点 `board_view._digit_ink_mode`(三态:亮直/深直/落牌),机检面 = `terrain_tile_sets_test` 三关呈现模式断言;目视验证面 = board_shot_probe 渲染帧取证(机检≠看得清)。验收:机检〈terrain_tile_sets_test 三关呈现模式断言全绿,board_shot_probe 渲染帧目视复核〉
|
|
||||||
- **垫牌与 UI 数据墨 = 深墨族 `#33261B` 系**(L≤0.027,§7.2)。验收:机检〈垫牌与 UI 数据墨取深墨族,L≤0.027〉
|
**三关棋盘环境八色(2026-11-07 用户看样张通过,冻结)**:槽位顺序 = 岩顶/地面/崖面/板块缝/倒角亮/倒角暗/临空墨线/受光棱。
|
||||||
|
- dungeon:`#9C8462`/`#695038`/`#403325`/`#64523A`/`#CCB288`/`#766248`/`#261E15`/`#C9AF83`。
|
||||||
|
- underdark:`#7B8894`/`#4F5A64`/`#31373D`/`#4D565F`/`#A5B4C2`/`#5C6770`/`#1D2124`/`#A1B1BF`。
|
||||||
|
- deep_underdark:`#706E6B`/`#4C4947`/`#2E2D2C`/`#484644`/`#93908D`/`#555351`/`#1B1B1A`/`#918E8B`。
|
||||||
|
换皮只换这八色与 §4.3 tint 槽;数字字芯/描边、封印黑、危险红、小人蓝、类型微光五组三关恒定。旧瓦片均值不作终值(旧 16+5 套已退役);三关互辨抽测按新材质重跑。验收:机检〈三关八色在册且与 §4.3 不变槽恒定〉
|
||||||
|
- **数字墨单色制(浮空字)**:1–8 **不做八色分色**,统一暖白字芯 `#F0E2C8` + 2px 深墨描边 `#1A140E`;**字形为唯一数值载体**,密度氛围不靠换字色。验收:目检〈1–8 数字芯色一致、非八色分色〉 ←原一/原二;P3
|
||||||
|
- **棋盘数字呈现 = 浮空描边字(全板统一,2026-11-07 定)**:字芯暖白 `#F0E2C8` + 2px 深墨描边 `#1A140E` + 1px 浮空投影;引导线 2px 双色(左深 `#1A140E`/右浅 `#E8D3AB`);不使用数字底牌、不随图类型换色、不再有亮直/深直/落牌三态。对比判据 = `max(字芯对底, 描边对底) ≥4.5:1` 且 `字芯对描边 ≥4.5:1`(最亮底岩顶 `#9C8462` 实测描边对底 5.1:1);机检面 = 浮空字几何/对比测试,目视验证面 = board_shot_probe 渲染帧。验收:机检〈四类底复合对比 ≥4.5;字高 21/间距 15/顶部预留 44 定值〉
|
||||||
|
- **UI 数据墨 = 深墨族 `#33261B` 系**(L≤0.027,§7.2);棋盘数字底牌已退役、不再使用。验收:机检〈UI 数据墨取深墨族,L≤0.027〉
|
||||||
- **八色弃用**:八色必与红/金/蓝/紫赤语义冲突,故弃。验收:方向性
|
- **八色弃用**:八色必与红/金/蓝/紫赤语义冲突,故弃。验收:方向性
|
||||||
- **封印黑 `#000000`**|封印宣告色,无色相:玩家的宣告"此格封印"。封印现行 = 无色相黑——紫色与微光蓝族(魔法微光 256° 等)色相冲突,黑色无色相天然避开 300°–345° 禁入带与全部微光色带;未开格墙顶明度 ≈113 对纯黑对比 ≥4.4:1,纯黑实心剪影单靠明度差即成立,不依赖任何浅色细件。封印紫不再用于棋盘(色史归 git 提交史);红族棋盘侧只剩危险红;主角随身背包件为朱红矩形件(人设侧见 character-design),与棋盘封印色脱钩。验收:机检〈封印宣告色 = #000000,未开格墙顶对其对比 ≥4.4:1〉 ←原一;P2
|
- **封印黑 `#000000`**|封印宣告色,无色相:玩家的宣告"此格封印"。封印现行 = 无色相黑——紫色与微光蓝族(魔法微光 256° 等)色相冲突,黑色无色相天然避开 300°–345° 禁入带与全部微光色带;承载面 = 本关受光棱色封印石(dungeon `#C9AF83`/underdark `#A1B1BF`/deep_underdark `#918E8B`,见 §3.2 封印印记条)对纯黑对比 9.94/9.56/6.45:1,纯黑实心剪影单靠明度差即成立,不依赖任何浅色细件;新连续地面 `#695038` 系对纯黑仅 2.35–2.98:1,故不作封印承载面。旧裸土 `#B39A78` 随旧地板瓦片退役。封印紫不再用于棋盘(色史归 git 提交史);红族棋盘侧只剩危险红;主角随身背包件为朱红矩形件(人设侧见 character-design),与棋盘封印色脱钩。验收:机检〈封印宣告色 = #000000,受光棱封印石对其对比 ≥4.5:1〉 ←原一;P2
|
||||||
- **危险红 `#A8321F`**|危险色:雷 = 被惊动的巢穴,兑现档红,更深更沉。验收:机检〈危险语义色 = #A8321F〉 ←原三;P2
|
- **危险红 `#A8321F`**|危险色:雷 = 被惊动的巢穴,兑现档红,更深更沉。验收:机检〈危险语义色 = #A8321F〉 ←原三;P2
|
||||||
- **奖励金 `#F0A828`**|已兑现的收益:GP/宝箱/蜡封,全作唯一亮金。验收:机检〈收益语义色 = #F0A828〉 ←P2;§2.3/2.4
|
- **奖励金 `#F0A828`**|已兑现的收益:GP/宝箱/蜡封,全作唯一亮金。验收:机检〈收益语义色 = #F0A828〉 ←P2;§2.3/2.4
|
||||||
- **小人蓝 `#2E86DE`**|小人主色:棋盘唯一"己方",与光标准线同族。验收:机检〈己方语义色 = #2E86DE〉 ←P1;§2.1
|
- **小人蓝 `#2E86DE`**|小人主色:棋盘唯一"己方",与光标准线同族。验收:机检〈己方语义色 = #2E86DE〉 ←P1;§2.1
|
||||||
- **数字色牌 `#F5EAD3`**|数字底具,**后备手段**:素色暖纸白直角小牌,仅复杂格底(物件纹样/变异纹带/微光叠加致直画对比不足)垫于数字正下方;素面无纹理、不随图类型/装饰变体变。验收:机检〈色牌 L≥0.70,仅复杂格底垫用〉 ←原二
|
- **数字色牌 `#F5EAD3`**|**普通数字棋盘侧退役**(2026-11-07 浮空数字定案;普通数字不再使用底牌);**封印格身份字形色牌保留**(`UiKit.DIGIT_PLATE`+`DIGIT_PLATE_EDGE`,叠于法阵之上,见 §3.2 封印印记条,2026-11-07 封印改版定案)。token 若被 UI 其他面复用按 UI 侧登记,不属棋盘数字呈现;棋盘普通数字绘制路径零色牌调用,封印格色牌为唯一例外。验收:机检〈普通数字绘制路径零色牌调用;封印格色牌在位〉 ←原二
|
||||||
- **收益金亮档 `#E0B860`(GOLD_BRIGHT)**|UI 徽标可读性亮档 token:敌顺位徽标①②③与重甲徽标对舞台底 6.47:1(GOLD_DEEP 3.26:1 不达 §7.2 带,故另立亮档);金族亮档,与奖励金 #F0A828 同族不同岗——奖励金 = 已兑现收益语义(§4.2 金条),本 token 只承载徽标可读性、不占收益语义。GOLD_DEEP/HERO_BLUE 常量本尊不动(standee 意图判据等语义岗现行使用)。验收:机检〈GOLD_BRIGHT 对舞台底 ≥4.5:1〉
|
- **收益金亮档 `#E0B860`(GOLD_BRIGHT)**|UI 徽标可读性亮档 token:敌顺位徽标①②③与重甲徽标对舞台底 6.47:1(GOLD_DEEP 3.26:1 不达 §7.2 带,故另立亮档);金族亮档,与奖励金 #F0A828 同族不同岗——奖励金 = 已兑现收益语义(§4.2 金条),本 token 只承载徽标可读性、不占收益语义。GOLD_DEEP/HERO_BLUE 常量本尊不动(standee 意图判据等语义岗现行使用)。验收:机检〈GOLD_BRIGHT 对舞台底 ≥4.5:1〉
|
||||||
- **小人蓝亮档 `#7EBAF0`(HERO_BLUE_BRIGHT)**|魔法护甲徽标对舞台底 5.88:1(HERO_BLUE 3.23:1 不达带,故另立亮档);蓝族亮档,与小人蓝 #2E86DE 同族不同岗——本 token 只承载徽标可读性,不占用「蓝只说己方」的语义。验收:机检〈HERO_BLUE_BRIGHT 对舞台底 ≥4.5:1〉
|
- **小人蓝亮档 `#7EBAF0`(HERO_BLUE_BRIGHT)**|魔法护甲徽标对舞台底 5.88:1(HERO_BLUE 3.23:1 不达带,故另立亮档);蓝族亮档,与小人蓝 #2E86DE 同族不同岗——本 token 只承载徽标可读性,不占用「蓝只说己方」的语义。验收:机检〈HERO_BLUE_BRIGHT 对舞台底 ≥4.5:1〉
|
||||||
- **图标槽柔和档 `#806A4E`(SLOT_BACKDROP_SOFT)**|BCard 图标槽底:对米色卡面 PANEL_DATA 3.69:1(深档 SLOT_BACKDROP #3E362C 8.53:1 过强、像硬贴补丁,故槽底另立柔和档),槽内白图标 5.14:1,满足 ≥3:1 图形参考线硬约束;仅 BCard 图标槽换档,B 区状态槽仍用深档 SLOT_BACKDROP。验收:机检〈槽内白图标对槽底 ≥3:1〉
|
- **图标槽柔和档 `#806A4E`(SLOT_BACKDROP_SOFT)**|BCard 图标槽底:对米色卡面 PANEL_DATA 3.69:1(深档 SLOT_BACKDROP #3E362C 8.53:1 过强、像硬贴补丁,故槽底另立柔和档),槽内白图标 5.14:1,满足 ≥3:1 图形参考线硬约束;仅 BCard 图标槽换档,B 区状态槽仍用深档 SLOT_BACKDROP。验收:机检〈槽内白图标对槽底 ≥3:1〉
|
||||||
- **群伤微光暗档 `#A61D37`(TG_GLOW_AOE)**|类型微光群伤组的**明度档**(UI token 板,占 1 枚额度,**余量 3→2**):色相 349° 与亮档 `#FF2D55` 零移动,明度落 V=0.65 档——即 §4.2「微光 = 色相+明度双码」里明度侧的落法;与 §4.2「红只说危险」不相撞(微光组色相刻意错开语义红,见 §4.2「类型微光色带」条)。已在役(`ui_kit.gd` 常量与 `type_glow_test.gd` 守门断言),本节为登记转正。验收:机检〈ui_kit.gd TG_GLOW_AOE 与 type_glow_test 断言的 H/S 逐位一致、V 落 0.65 档〉
|
- **群伤微光暗档 `#A61D37`(TG_GLOW_AOE)**|类型微光群伤组的**明度档**(UI token 板,占 1 枚额度,**余量 3→2**):色相 349° 与亮档 `#FF2D55` 零移动,明度落 V=0.65 档——即 §4.2「微光 = 色相+明度双码」里明度侧的落法;与 §4.2「红只说危险」不相撞(微光组色相刻意错开语义红,见 §4.2「类型微光色带」条)。已在役(`ui_kit.gd` 常量与 `type_glow_test.gd` 守门断言),本节为登记转正。验收:机检〈ui_kit.gd TG_GLOW_AOE 与 type_glow_test 断言的 H/S 逐位一致、V 落 0.65 档〉
|
||||||
- **站桩石板地台板身 `#968264`(STAND_STONE)**|战斗屏场景环境子板(分层②,不占 48 token 额度):B 区站桩地台板身与顶缘的材质色,跨三关恒定、不吃 §4.3 `wall_ambient` tint(地台是 §6.1 定死的世界中层承载面,随关卡变会破 §2 明度分层的层间关系)。转正前即在役。验收:机检〈战斗屏场景环境子板色数 ≤32 且本值在册〉
|
- **站桩石板地台板身 `#968264`(STAND_STONE)**|战斗屏场景环境子板(分层②,不占 48 token 额度):B 区站桩地台板身与顶缘的材质色,跨三关恒定、不吃 §4.3 `wall_ambient` tint(地台是 §6.1 定死的世界中层承载面,随关卡变会破 §2 明度分层的层间关系)。转正前即在役。验收:机检〈战斗屏场景环境子板色数 ≤32 且本值在册〉
|
||||||
- **营地场景环境子板(分层②,不占 48 token 额度)**:营地场景十层环境色按子板制落地——各层独立量化并集 272 色经最近对合并收敛至 **32 色、违例对 0**,十层按终版色板重量化回写。色值不另立逐值清单,事实源=入包素材 `scene_camp_*` 十件的量化产物;换算与合并过程登记于 artwork 工作区换算式登记。验收:机检〈营地屏唯一色数判据(shot_checker 闸件承载,2026-11-01 用户裁口径)〉
|
- **营地场景环境子板(分层②,不占 48 token 额度)**:营地屏走**双板制**(2026-11-07 用户裁放宽屏上限)——围墙与八件九件共用主色板 **32 色**(2026-11-01 并集 272 色经最近对合并收敛在册、违例对 0);背景层自板 **≤32 色**(2026-11-07 背景换代登记:量化 32 色、近色合并 4 对〔九件板 1 对+全局色板基线 3 对〕后对九件板新增 31 色);**屏并集上限 64、实测 63**。色值不另立逐值清单,事实源=入包素材 `scene_camp_*` 十件的量化产物;换算与合并过程登记于 artwork 工作区执行件。验收:机检〈单张像素域 ≤32;营地屏并集 ≤64〉
|
||||||
- **重甲冷灰金属材质色 `#868C9A`(ARMOR_PLATE_COLD,token 名暂拟)**|语义/UI token 板(**分层①**,占 1 枚额度;用户裁):重甲档甲材质色;character-design §5.3 通道 = 甲面覆盖率 × 甲材质色,甲材质色按甲档统一,故石君王岩石板甲**同引本枚、不另计额度**;材质色跨屏恒定,落分层①不落分层②(环境色才随场景走)。过门情况:第二道门按宽松口径(禁止三通道全 <8)与在册色逐一比对,**无三通道全 <8 的对 → 过门**;§4.2 语义检查过门(色相 222°,不占红/金/蓝/紫赤/绿语义段、不在 300°–345° 禁入带;材质色不进信息层与语义物件岗)。对比实测:对深素底 `#282220` 4.65:1、对舞台底 `#3E362C` 3.52:1(图形 ≥3:1 门槛);相对亮度 L≈0.261 落 §2 世界中层 0.22–0.45 带。验收:机检〈本值入板后全板色对中三通道差全部 <8/255 的对数 = 0〉
|
- **重甲冷灰金属材质色 `#868C9A`(ARMOR_PLATE_COLD,token 名暂拟)**|语义/UI token 板(**分层①**,占 1 枚额度;用户裁):重甲档甲材质色;character-design §5.3 通道 = 甲面覆盖率 × 甲材质色,甲材质色按甲档统一,故石君王岩石板甲**同引本枚、不另计额度**;材质色跨屏恒定,落分层①不落分层②(环境色才随场景走)。过门情况:第二道门按宽松口径(禁止三通道全 <8)与在册色逐一比对,**无三通道全 <8 的对 → 过门**;§4.2 语义检查过门(色相 222°,不占红/金/蓝/紫赤/绿语义段、不在 300°–345° 禁入带;材质色不进信息层与语义物件岗)。对比实测:对深素底 `#282220` 4.65:1、对舞台底 `#3E362C` 3.52:1(图形 ≥3:1 门槛);相对亮度 L≈0.261 落 §2 世界中层 0.22–0.45 带。验收:机检〈本值入板后全板色对中三通道差全部 <8/255 的对数 = 0〉
|
||||||
- **卓尔浅紫灰皮 `#A79CB8`(DRIDER_SKIN,token 名暂拟)**|语义/UI token 板(**分层①**,占 1 枚额度,**额度用尽**;用户裁):蛛化卓尔精灵上体皮色(体块主色,L≈0.355 落 §2 世界中层带)。过门情况:第二道门同上行口径,**无三通道全 <8 的对 → 过门**;§4.2 语义检查过门(色相 264°,避开 300°–345° 禁入带,紫赤独占仍归 `#8F2F6A`;不占本节五语义段)。对比实测:对深素底 `#282220` **6.04:1**、对舞台底 `#3E362C` **4.57:1**——**两处均过图形 ≥3:1 门槛**。验收:机检〈本值入板后全板色对中三通道差全部 <8/255 的对数 = 0〉
|
- **卓尔浅紫灰皮 `#A79CB8`(DRIDER_SKIN,token 名暂拟)**|语义/UI token 板(**分层①**,占 1 枚额度,**额度用尽**;用户裁):蛛化卓尔精灵上体皮色(体块主色,L≈0.355 落 §2 世界中层带)。过门情况:第二道门同上行口径,**无三通道全 <8 的对 → 过门**;§4.2 语义检查过门(色相 264°,避开 300°–345° 禁入带,紫赤独占仍归 `#8F2F6A`;不占本节五语义段)。对比实测:对深素底 `#282220` **6.04:1**、对舞台底 `#3E362C` **4.57:1**——**两处均过图形 ≥3:1 门槛**。验收:机检〈本值入板后全板色对中三通道差全部 <8/255 的对数 = 0〉
|
||||||
- **换色合并登记五处(用户裁,部件色落值)**|按本表「不过门即触发换色合并、禁加色绕行」执行,五处**零新增额度**(各件原拟新增候选一律不取):① 主角铲刃浅铁灰(原拟 `#A8AEB8`)→ 并入 `FOG_MEMORY_INK #C4C4C4`,**部件取值 = `#C4C4C4`**;② 主角提灯铜色(原拟 `#C08A3A`)→ 并入 `GOLD_DEEP #B07A14`,**部件取值 = `#B07A14`**;③ 食人魔酋长暖褐皮(原拟 `#B08050` / `#A97C4E`)→ 并入 `暖石 #B8A582`,**部件取值 = `#B8A582`**;④ 石君王灰皮(原拟 `#9A968C` / `#949089`,按**次级皮**口径——板甲视同体块主色、灰皮属次级皮故不受 L 0.22–0.45 约束)→ 并入 `STONE #786E62`,**部件取值 = `#786E62`**;⑤ 轻甲护甲图标木色 `#8A5A34`(深素底下 2.72:1 不过门;原拟新增木色亮档 `#C49A5E`)→ 并入 `WARM_FAINT #CDB88C`,**部件取值 = `#CDB88C`**(8.08:1)。**一色两岗代价已随裁定接受**:① 的 `#C4C4C4` 语义岗 = 迷雾记忆墨(§6.5)、② 的 `#B07A14` 属金族(§4.2 金只说收益与兑现)——两者均作角色随身件材质色用,不进信息层与语义物件岗;③④⑤ 无语义岗冲突。验收:机检〈五处部件取值点全部改指合并目标色,四枚原拟新增候选值零入板〉
|
- **换色合并登记五处(用户裁,部件色落值)**|按本表「不过门即触发换色合并、禁加色绕行」执行,五处**零新增额度**(各件原拟新增候选一律不取):① 主角铲刃浅铁灰(原拟 `#A8AEB8`)→ 并入 `FOG_MEMORY_INK #C4C4C4`,**部件取值 = `#C4C4C4`**;② 主角提灯铜色(原拟 `#C08A3A`)→ 并入 `GOLD_DEEP #B07A14`,**部件取值 = `#B07A14`**;③ 食人魔酋长暖褐皮(原拟 `#B08050` / `#A97C4E`)→ 并入 `暖石 #B8A582`,**部件取值 = `#B8A582`**;④ 石君王灰皮(原拟 `#9A968C` / `#949089`,按**次级皮**口径——板甲视同体块主色、灰皮属次级皮故不受 L 0.22–0.45 约束)→ 并入 `STONE #786E62`,**部件取值 = `#786E62`**;⑤ 轻甲护甲图标木色 `#8A5A34`(深素底下 2.72:1 不过门;原拟新增木色亮档 `#C49A5E`)→ 并入 `WARM_FAINT #CDB88C`,**部件取值 = `#CDB88C`**(8.08:1)。**一色两岗代价已随裁定接受**:① 的 `#C4C4C4` 语义岗 = 迷雾记忆墨(§6.5)、② 的 `#B07A14` 属金族(§4.2 金只说收益与兑现)——两者均作角色随身件材质色用,不进信息层与语义物件岗;③④⑤ 无语义岗冲突。验收:机检〈五处部件取值点全部改指合并目标色,四枚原拟新增候选值零入板〉
|
||||||
- **换色合并登记三处**|按本表「不过门即触发换色合并、禁加色绕行」执行,三处零新增额度:①地台顶缘受光线 `#C4AC84` 已并入 `#C9AF83`(掩尘枚 `BRICK`,与 §8.2 高墙口沿高光同枚)——源常量已删除(全仓零引用,退役断言测试串为预期例外),绘制点全部改指 `#C9AF83`;②地台描边 `#5A4C3A` 已并入 `#4C4038`(代码 `PLAZA_EDGE`,ui_kit 唯一落点)——源常量已删除,绘制点全部改指;③舞台底 `#3E342A`(代码 `STAGE_BG`)→ 并入 `#3E362C`(状态槽底)——源常量已删除(常量表零键),背景资产接管该绘制面,程序化平色缺图回退改指 `SLOT_BACKDROP`(`#3E362C`)。程序化回退绘制与已落合并值的贴图保持一致。验收:机检〈①②两枚源常量全仓零引用,绘制点全部改指合并目标色〉
|
- **换色合并登记三处**|按本表「不过门即触发换色合并、禁加色绕行」执行,三处零新增额度:①地台顶缘受光线 `#C4AC84` 已并入 `#C9AF83`(掩尘枚 `BRICK`,与 §8.2 高墙口沿高光同枚)——源常量已删除(全仓零引用,退役断言测试串为预期例外),绘制点全部改指 `#C9AF83`;②地台描边 `#5A4C3A` 已并入 `#4C4038`(代码 `PLAZA_EDGE`,ui_kit 唯一落点)——源常量已删除,绘制点全部改指;③舞台底 `#3E342A`(代码 `STAGE_BG`)→ 并入 `#3E362C`(状态槽底)——源常量已删除(常量表零键),背景资产接管该绘制面,程序化平色缺图回退改指 `SLOT_BACKDROP`(`#3E362C`)。程序化回退绘制与已落合并值的贴图保持一致。验收:机检〈①②两枚源常量全仓零引用,绘制点全部改指合并目标色〉
|
||||||
|
|
||||||
**对比硬指标(可测)**:数字可读性由**格底明度分档**承载——棋盘数字亮墨 **L≥0.75** 对**已开格底 L 0.08–0.14** ⇒ 直画对比 **≥4.5:1 恒成立**(WCAG AA,样张逐组合抽测冻结);**色牌后备**:色牌素色恒定 **L≥0.70**、牌上数字深墨 **L≤0.027** ⇒ 任意牌墨组合 ≥4.5:1(实测样例:#33261B/#F5EAD3 = 12.3:1)。未开格底槽(含全部图类型)相对亮度 **L≥0.30**(墙顶面受光档)、HSV 饱和 **≤0.55**、避 Boss 禁入色相带;已开格底走世界底层档(见上)。物件识别不依赖格底(§5.1 轮廓通道),封印印记、金色不作识别依赖。验收:机检〈亮墨对已开格底 ≥4.5:1;未开格底 L≥0.30、饱和 ≤0.55;任意牌墨组合 ≥4.5:1〉 ←原二;地形变异 AC-9
|
**对比硬指标(可测)**:数字可读性由**浮空描边字**承载——棋盘数字字芯暖白 `#F0E2C8` + 2px 深墨描边 `#1A140E`,判据 = `max(字芯对底, 描边对底) ≥4.5:1` 且 `字芯对描边 ≥4.5:1`;抽测底 = 地面/岩顶/崖面/板外暗底四类(最亮底岩顶实测描边对底 5.1:1);普通数字不使用数字底牌、无色牌后备(封印格身份字形色牌为唯一例外,见 §3.2 封印印记条)。岩顶/地面/崖面底槽(含全部图类型)与类型微光之间存在**相对亮度与相对饱和关系**——禁止底槽吞没微光环、禁止岩顶与地面同档;本节只定这层关系,阈值与准入判定由图类型色板互辨抽测的执行件承载(用法登记见 [art-pipeline-tools](art-pipeline-tools.md))。已开格地面走世界底层档(见上)。物件识别不依赖底色(§5.1 轮廓通道),封印印记、金色不作识别依赖。验收:机检〈四类底复合对比 ≥4.5;岩顶/地面底对微光环与对彼此的相对亮度关系经互辨抽测准入〉 ←原二;地形变异 AC-9
|
||||||
|
|
||||||
**色板增量纪律(数值状态 = 待定现用)**:全作色板硬上限 **48 色**(防色板无限膨胀的封口条款;**额度已用尽、余量 0**,后续余量以色板检查器实报为准);新色入板须同时过两道门:①§4.2 语义检查(不占语义色段/禁入带);②**与既有任一色的 RGB 三通道差禁止全部 <8/255**——即三通道里至少一通道 ≥8/255 即过门,「三通道差全部 <8」才算不过门(条文原写的「三通道差 ≥8/255」有「逐通道全过」与「禁止全灭」两种互斥读法,前者下现行色板 247 对不达标、与本节自认的「现行即执法」合规状态不能同真,故取后者;用户裁)。**额度已用尽:后续任何新增须先压缩或合并既有色**——按本节「额度不足时呈报作者」口径呈报,**压缩或合并哪几枚由作者裁,本节不代裁、不预指对象**。反例实证:#3A2E22 ↔ #362B20 三通道差均 <5,肉眼不可辨,同板共存只增噪。不过门即触发「换色合并」(把意图色并进最近既有色),**禁加色绕行**;加色义务同时登记于本表修订。**「待定现用」态释义**:数值**现行即执法**(色板检查器按此拦,§8.3)——非候选(不存在"等冻结"空窗)、非死规(后续需求引入时可变);调整走本节修订并登记,改值 = 修订不是违约。验收:机检〈色板总数 ≤48;新色入板过两道门〉
|
**色板增量纪律(数值状态 = 待定现用)**:全作色板硬上限 **48 色**(防色板无限膨胀的封口条款;**额度已用尽、余量 0**,后续余量以色板检查器实报为准);新色入板须同时过两道门:①§4.2 语义检查(不占语义色段/禁入带);②**与既有任一色的 RGB 三通道差禁止全部 <8/255**——即三通道里至少一通道 ≥8/255 即过门,「三通道差全部 <8」才算不过门(条文原写的「三通道差 ≥8/255」有「逐通道全过」与「禁止全灭」两种互斥读法,前者下现行色板 247 对不达标、与本节自认的「现行即执法」合规状态不能同真,故取后者;用户裁)。**额度已用尽:后续任何新增须先压缩或合并既有色**——按本节「额度不足时呈报作者」口径呈报,**压缩或合并哪几枚由作者裁,本节不代裁、不预指对象**。反例实证:#3A2E22 ↔ #362B20 三通道差均 <5,肉眼不可辨,同板共存只增噪。不过门即触发「换色合并」(把意图色并进最近既有色),**禁加色绕行**;加色义务同时登记于本表修订。**「待定现用」态释义**:数值**现行即执法**(色板检查器按此拦,§8.3)——非候选(不存在"等冻结"空窗)、非死规(后续需求引入时可变);调整走本节修订并登记,改值 = 修订不是违约。验收:机检〈色板总数 ≤48;新色入板过两道门〉
|
||||||
|
|
||||||
- **换色合并欠账清单(全板重扫 6 对不达标,逐对清偿)**:`#18120C` ↔ `#181410`、`#33261B` ↔ `#362B20`、`#362B20` ↔ `#3A2E22`、`#3E362C` ↔ `#3E3731`、`#3E4048` ↔ `#3F4147`、`#453723` ↔ `#4A3B2A`——六对按「不过门即换色合并」纪律逐对清偿(并进最近既有色);清偿前该对不视作合规,清偿动作落本节修订。**本节所举反例 `#3A2E22` ↔ `#362B20` 正在这 6 对之内**,与本口径自洽。验收:机检〈全板色对中三通道差全部 <8/255 的对数 = 0〉
|
- **换色合并欠账清单(全板重扫 6 对不达标,逐对清偿)**:`#18120C` ↔ `#181410`、`#33261B` ↔ `#362B20`、`#362B20` ↔ `#3A2E22`、`#3E362C` ↔ `#3E3731`、`#3E4048` ↔ `#3F4147`、`#453723` ↔ `#4A3B2A`——六对按「不过门即换色合并」纪律逐对清偿(并进最近既有色);清偿前该对不视作合规,清偿动作落本节修订。**本节所举反例 `#3A2E22` ↔ `#362B20` 正在这 6 对之内**,与本口径自洽。验收:机检〈全板色对中三通道差全部 <8/255 的对数 = 0〉
|
||||||
|
|
||||||
- **色板分层**:色板分两层管理——① **语义/UI token 板**:全作共享,硬上限 **48 色**,管 UI 语义色、墨色、材质色,跨屏恒定;② **场景环境子板**:**每屏一套,≤32 色,允许跨屏不共享**(环境色 = 天空、地面、植被、石材、火焰等随场景走的颜色)。新增环境色仍须过两道门(§4.2 语义检查 + 与既有任一色 RGB 三通道差禁止全部 <8/255),但**不占用 48 token 额度**;不过门照旧走「换色合并」,**禁加色绕行**。单张 PNG 的像素域色数上限 **≤32 色**另由 `standee_asset_check` 执法(按单图像素域取值方式计数,与本表 token 计数互不干扰)。额度不足时向作者报告,由作者决定压缩或合并既有色。验收:机检〈token 板 ≤48;每屏环境子板 ≤32〉
|
- **色板分层**:色板分两层管理——① **语义/UI token 板**:全作共享,硬上限 **48 色**,管 UI 语义色、墨色、材质色,跨屏恒定;② **场景环境子板**:**每屏一套,≤32 色,允许跨屏不共享**(营地屏例外=双板制、屏并集 ≤64,见本节营地行,2026-11-07 用户裁)(环境色 = 天空、地面、植被、石材、火焰等随场景走的颜色)。新增环境色仍须过两道门(§4.2 语义检查 + 与既有任一色 RGB 三通道差禁止全部 <8/255),但**不占用 48 token 额度**;不过门照旧走「换色合并」,**禁加色绕行**。单张 PNG 的像素域色数上限 **≤32 色**另由 `standee_asset_check` 执法(按单图像素域取值方式计数,与本表 token 计数互不干扰)。额度不足时向作者报告,由作者决定压缩或合并既有色。验收:机检〈token 板 ≤48;每屏环境子板 ≤32(营地屏并集 ≤64)〉
|
||||||
- **整屏有效色数总闸(色板第三层,2026-11-02 用户裁)**|整屏的色板纪律裁判面=**画面上成片出现的颜色数(有效色数)**,不是逐像素去重总数:多源并集与程序混合(压暗遮罩/软阴影/渐变/tween 中间帧)使逐像素色数随素材与渲染状态大幅漂移(实测同屏不同时点差一至九倍),不可治理也不承载观感。整屏唯一色数只保留「渲染真实发生」的存在性地板(地板值归闸件承载);**色板纪律的上限闸=每屏有效色数 ≤128**(**待定现用**——现行即执法、修订走登记,释义同色板增量纪律条)。构成推导源:双环境层 32×2+token 板 48+混合容差 16(←本条色板分层;推导源非额度分配,各层额度照旧独立执法)。超限处置沿色板增量纪律:先合并压缩既有色再进,禁加色绕行。有效色的测量口径(面积阈值等实现参数)归色数检查器承载,本圣经不载。验收:机检〈各屏有效色数 ≤128,口径=色数检查器现行定义〉
|
- **整屏有效色数总闸(色板第三层,2026-11-02 用户裁)**|整屏的色板纪律裁判面=**画面上成片出现的颜色数(有效色数)**,不是逐像素去重总数:多源并集与程序混合(压暗遮罩/软阴影/渐变/tween 中间帧)使逐像素色数随素材与渲染状态大幅漂移(实测同屏不同时点差一至九倍),不可治理也不承载观感。整屏唯一色数只保留「渲染真实发生」的存在性地板(地板值归闸件承载);**色板纪律的上限闸=每屏有效色数 ≤128**(**待定现用**——现行即执法、修订走登记,释义同色板增量纪律条)。构成推导源:双环境层 32×2+token 板 48+混合容差 16(←本条色板分层;推导源非额度分配,各层额度照旧独立执法)。超限处置沿色板增量纪律:先合并压缩既有色再进,禁加色绕行。有效色的测量口径(面积阈值等实现参数)归色数检查器承载,本圣经不载。验收:机检〈各屏有效色数 ≤128,口径=色数检查器现行定义〉
|
||||||
|
|
||||||
### 4.2 语义色彩规则
|
### 4.2 语义色彩规则
|
||||||
@@ -235,8 +244,8 @@
|
|||||||
- **紫赤只说 Boss 与精英** `#8F2F6A`(色相 323°):郑重来自色相独占,不来自压暗。禁:**HSV 色相 300°–345° 为信息层与语义物件禁入带**——UI、粒子、类型微光、语义物件及图类型色板信息面禁止落入;环境层(背景/装饰)可入但限低饱和,高饱和紫赤仍 Boss 独占。验收:机检〈信息层与语义物件色值色相不落 300°–345°;高饱和紫赤仅 Boss 战〉 ←§2.6;原三
|
- **紫赤只说 Boss 与精英** `#8F2F6A`(色相 323°):郑重来自色相独占,不来自压暗。禁:**HSV 色相 300°–345° 为信息层与语义物件禁入带**——UI、粒子、类型微光、语义物件及图类型色板信息面禁止落入;环境层(背景/装饰)可入但限低饱和,高饱和紫赤仍 Boss 独占。验收:机检〈信息层与语义物件色值色相不落 300°–345°;高饱和紫赤仅 Boss 战〉 ←§2.6;原三
|
||||||
- **绿只说自然生机**(环境植被;恢复类状态若有则用绿——待增益状态定夺)。**例外:类型微光治疗组**(见下条「类型微光色带」)。禁(信息层域):绿禁止承载逻辑状态(微光色带除外),禁止与红构成唯一区分对。验收:目检〈信息层域绿色仅微光治疗组;绿红不构成唯一区分对〉 ←原三
|
- **绿只说自然生机**(环境植被;恢复类状态若有则用绿——待增益状态定夺)。**例外:类型微光治疗组**(见下条「类型微光色带」)。禁(信息层域):绿禁止承载逻辑状态(微光色带除外),禁止与红构成唯一区分对。验收:目检〈信息层域绿色仅微光治疗组;绿红不构成唯一区分对〉 ←原三
|
||||||
- **类型微光色带 = 格面类型先验专用逻辑色带**(未开格类型预读的色彩通道;概念定义、可见范围与生命周期见《HUD框架》「未开格类型微光」节):未开格类型微光的信息色彩按以下五组执行——**通用增益组**(attack/defense/weaken/action/gp 五族)芥末黄 `#D6C13A`(≈52°)、**治疗组**(heal)黄绿 `#5CB83A`(≈104°)、**穿刺组**(pierce)青 `#2E9E9E`(≈180°)、**魔法组**(magic)紫罗兰 `#7B5BD6`(≈256°)、**群伤组**(blast)绯红 `#FF2D55`(≈349°,刻意避开危险红色相段与 300°–345° 禁入带)。验收:机检〈类型微光五组色值与本表一致〉
|
- **类型微光色带 = 格面类型先验专用逻辑色带**(未开格类型预读的色彩通道;概念定义、可见范围与生命周期见《HUD框架》「未开格类型微光」节):未开格类型微光的信息色彩按以下五组执行——**通用增益组**(attack/defense/weaken/action/gp 五族)芥末黄 `#D6C13A`(≈52°)、**治疗组**(heal)黄绿 `#5CB83A`(≈104°)、**穿刺组**(pierce)青 `#2E9E9E`(≈180°)、**魔法组**(magic)紫罗兰 `#7B5BD6`(≈256°)、**群伤组**(blast)绯红 `#FF2D55`(≈349°,刻意避开危险红色相段与 300°–345° 禁入带)。验收:机检〈类型微光五组色值与本表一致〉
|
||||||
- **微光呈现参数**:内缘带状泛光 α170、带宽 cell÷8(亮度不压格底明度档,§2 微光例外);组间互辨以抽检核对。验收:机检〈微光泛光 α=170、带宽=cell÷8〉
|
- **微光呈现参数**:内缘带状泛光 α170、带宽 cell÷8(亮度不压岩顶/地面明度档,§2 微光例外);组间互辨以抽检核对。验收:机检〈微光泛光 α=170、带宽=cell÷8〉
|
||||||
- **微光分域纪律与双码**:微光色相只承载类型先验,不迁移复用为物件/阵营/UI 语义色;微光 = **色相+明度双码**——明度梯度承载分组(组间五色相、组内不细分:通用增益组五族同色相、不承诺组内分型;§2 微光明度例外:梯度禁止压破格底明度档与三态分类);色弱玩家的类型主通道 = 微光双码(组粒度:组间五色相 + 各组一档明度互辨)。验收:目检〈五组微光两两互辨,明度梯度不压破格底明度档与三态分类〉 ←§4.6.3
|
- **微光分域纪律与双码**:微光色相只承载类型先验,不迁移复用为物件/阵营/UI 语义色;微光 = **色相+明度双码**——明度梯度承载分组(组间五色相、组内不细分:通用增益组五族同色相、不承诺组内分型;§2 微光明度例外:梯度禁止压破岩顶/地面明度档与三态分类);色弱玩家的类型主通道 = 微光双码(组粒度:组间五色相 + 各组一档明度互辨)。验收:目检〈五组微光两两互辨,明度梯度不压破岩顶/地面明度档与三态分类〉 ←§4.6.3
|
||||||
- **金/红兼作极性色相槽(§4.6)**:极性(概念定义与符号矩阵见《地图战斗资源》极性提案)的视觉取色只在这两族间——有利兑付 = 金族,有害兑付 = 红族,不新增语义色。验收:目检〈极性视觉取色仅金/红两族〉 ←§4.6;原二
|
- **金/红兼作极性色相槽(§4.6)**:极性(概念定义与符号矩阵见《地图战斗资源》极性提案)的视觉取色只在这两族间——有利兑付 = 金族,有害兑付 = 红族,不新增语义色。验收:目检〈极性视觉取色仅金/红两族〉 ←§4.6;原二
|
||||||
|
|
||||||
### 4.3 图类型色板换皮规则(board_type)
|
### 4.3 图类型色板换皮规则(board_type)
|
||||||
@@ -248,7 +257,7 @@
|
|||||||
- `wall_ambient` 墙雾氛围 tint:可带主题色相,L≥0.30。验收:机检〈wall_ambient tint L≥0.30〉
|
- `wall_ambient` 墙雾氛围 tint:可带主题色相,L≥0.30。验收:机检〈wall_ambient tint L≥0.30〉
|
||||||
- `variant_tint` 变异纹带染槽:只改色相不改纹形(纹带形按轴两分,见 §3.2 变异格形状通道;种类 = 地形变异六类型已定稿)。验收:目检〈同纹带形跨图类型仅色相不同〉
|
- `variant_tint` 变异纹带染槽:只改色相不改纹形(纹带形按轴两分,见 §3.2 变异格形状通道;种类 = 地形变异六类型已定稿)。验收:目检〈同纹带形跨图类型仅色相不同〉
|
||||||
|
|
||||||
**不变槽**:棋盘数字墨亮族三档、数字色牌(后备件)、封印黑、危险红、奖励金、小人蓝、紫赤、绿、类型微光五组——**信息与语义层全图类型恒定**;换挡动色相饱和,格底两档明度关系(墙亮/空间暗)全图类型恒定(§2 明度分层)。新增色板须重跑 §1.4 格子样张(灰度可辨+对比抽测)。验收:机检〈换皮前后不变槽色值逐项一致〉 ←原三/原二;地形变异 AC-9
|
**不变槽**:棋盘浮空数字字芯/描边、封印黑、危险红、奖励金、小人蓝、紫赤、绿、类型微光五组——**信息与语义层全图类型恒定**;换挡动色相饱和,岩顶/地面两档明度关系(岩顶亮/地面暗)全图类型恒定(§2 明度分层)。新增色板须重跑 §1.4 格子样张(灰度可辨+对比抽测)。验收:机检〈换皮前后不变槽色值逐项一致〉 ←原三/原二;地形变异 AC-9
|
||||||
|
|
||||||
### 4.4 UI 色板(方向指导,细则迁 §7.2)
|
### 4.4 UI 色板(方向指导,细则迁 §7.2)
|
||||||
|
|
||||||
@@ -260,7 +269,7 @@
|
|||||||
|
|
||||||
1. 已开 vs 未开:§3.2 完整/碎裂形承载,无需另加。验收:目检〈色弱模拟下两态以完整度可辨〉
|
1. 已开 vs 未开:§3.2 完整/碎裂形承载,无需另加。验收:目检〈色弱模拟下两态以完整度可辨〉
|
||||||
2. 已开 vs 变异格:纹带形状通道,灰度截图可辨,无需另加。验收:目检〈灰度截图下变异格可辨〉
|
2. 已开 vs 变异格:纹带形状通道,灰度截图可辨,无需另加。验收:目检〈灰度截图下变异格可辨〉
|
||||||
3. 封印印记 vs 巢穴(危险格):印记形物件对砖面巢穴纹,无需另加。验收:目检〈色弱模拟下印记与巢穴纹可辨〉
|
3. 封印印记 vs 巢穴(危险格):印记形物件对格面巢穴纹,无需另加。验收:目检〈色弱模拟下印记与巢穴纹可辨〉
|
||||||
4. 奖励金 vs 危险红(色弱下皆偏褐):§3.1 道具点两类剪影 + §3.4 满圆对刺缺 + 金粒运动,无需另加。验收:目检〈色弱模拟下奖励金与危险红可辨〉
|
4. 奖励金 vs 危险红(色弱下皆偏褐):§3.1 道具点两类剪影 + §3.4 满圆对刺缺 + 金粒运动,无需另加。验收:目检〈色弱模拟下奖励金与危险红可辨〉
|
||||||
5. Boss 紫赤 vs 其他敌:§5.1 形状独占,无需另加。验收:目检〈色弱模拟下 Boss 可辨〉
|
5. Boss 紫赤 vs 其他敌:§5.1 形状独占,无需另加。验收:目检〈色弱模拟下 Boss 可辨〉
|
||||||
6. 小人蓝 vs 青墨数字:明度悬殊 + 小人轮廓与底盘,无需另加。验收:目检〈色弱模拟下小人与数字可辨〉
|
6. 小人蓝 vs 青墨数字:明度悬殊 + 小人轮廓与底盘,无需另加。验收:目检〈色弱模拟下小人与数字可辨〉
|
||||||
@@ -392,19 +401,21 @@
|
|||||||
- **情绪与色域**:承载 §2.8——全作最暖:烛光黄 `#F6C667` × 木色 `#8A5A34`(§7.2),中等饱和,无棋盘式高对比。
|
- **情绪与色域**:承载 §2.8——全作最暖:烛光黄 `#F6C667` × 木色 `#8A5A34`(§7.2),中等饱和,无棋盘式高对比。
|
||||||
- **场景构成**:一张可点击的营地场景图(1280×800,与工程档同幅面)。远景=天空与远山;中景=**独立成层的木围墙**(密排竖木桩、桩顶削尖、不透缝无横木)与**半开的营地大门**;近景=中央篝火、左侧锻炉铁砧、右侧帐篷与宝箱、帐篷旁的笔记本,另有木桩与挂在围墙上的布告板。**中景带自底部往上约 2/3 处起**;**近景物件可覆盖围墙,唯一例外=中间门洞必须留空、不被任何物件遮挡**。七个可点物件的功能绑定归 `camp.md`,本节只定画法。
|
- **场景构成**:一张可点击的营地场景图(1280×800,与工程档同幅面)。远景=天空与远山;中景=**独立成层的木围墙**(密排竖木桩、桩顶削尖、不透缝无横木)与**半开的营地大门**;近景=中央篝火、左侧锻炉铁砧、右侧帐篷与宝箱、帐篷旁的笔记本,另有木桩与挂在围墙上的布告板。**中景带自底部往上约 2/3 处起**;**近景物件可覆盖围墙,唯一例外=中间门洞必须留空、不被任何物件遮挡**。七个可点物件的功能绑定归 `camp.md`,本节只定画法。
|
||||||
- **图层拆分(10 张)**:场景按「远景/中景/近景要素各自成层」拆——`scene_camp_bg` 背景层(z0,不透明全幅)=天空+远山+整片地面+门洞内一条通向远处的小路;`scene_camp_wall` 围墙层(z1,透明底)=横贯全宽密排木桩墙(左右两段)+两根略高的门柱,**门洞处留透明缺口**透出背景层的小路;`scene_camp_board` 布告板(z2)、`scene_camp_gate` 门扇(z3)、`scene_camp_dummy` 木桩/`scene_camp_forge` 锻炉/`scene_camp_tent` 帐篷(z4)、`scene_camp_chest` 宝箱/`scene_camp_notebook` 笔记本(z5)、`scene_camp_campfire` 篝火(z6,最前)=八个物件层,各透明底单件一张。**帐篷**为承载件、不可点。围墙独立成层的好处:桩高可单独锁死、门洞做透明缺口、背景层不混入暖木色。提示词与坐标 = `camp-scene-prompts.md`,消费常量 = `asset-path-map`。
|
- **图层拆分(10 张)**:场景按「远景/中景/近景要素各自成层」拆——`scene_camp_bg` 背景层(z0,不透明全幅)=天空+远山+整片地面+门洞内一条通向远处的小路;`scene_camp_wall` 围墙层(z1,透明底)=横贯全宽密排木桩墙(左右两段)+两根略高的门柱,**门洞处留透明缺口**透出背景层的小路;`scene_camp_board` 布告板(z2)、`scene_camp_gate` 门扇(z3)、`scene_camp_dummy` 木桩/`scene_camp_forge` 锻炉/`scene_camp_tent` 帐篷(z4)、`scene_camp_chest` 宝箱/`scene_camp_notebook` 笔记本(z5)、`scene_camp_campfire` 篝火(z6,最前)=八个物件层,各透明底单件一张。**帐篷**为承载件、不可点。围墙独立成层的好处:桩高可单独锁死、门洞做透明缺口、背景层不混入暖木色。提示词与坐标 = `camp-scene-prompts.md`,消费常量 = `asset-path-map`。
|
||||||
- **交付形态**:**背景层 1 张(不透明全幅)+ 围墙层 1 张 + 八个物件层 = 10 张**,其中 9 张透明底、1 张不透明全幅 + 一份坐标表(贴图矩形/命中矩形/z 序)。**篝火例外**:命中矩形只取下半(火堆),上半(火焰)只作特效展示。围墙层落盘按细条裁,不做全幅(全幅约 3.9 MB 显存,细条约 0.35 MB);**实装落盘矩形 `(0, 261, 1280, 49)`、底锚 y310**(Y 压缩按桩身 43px 终稿锁定值精确,落带内〔规划带 (0,240,1280,70)〕;备选 A′〔带高 70/桩身 62〕存档 artwork 同目录)。
|
- **交付形态**:**背景层 1 张(不透明全幅)+ 围墙层 1 张 + 八个物件层 = 10 张**,其中 9 张透明底、1 张不透明全幅 + 一份坐标表(贴图矩形/命中矩形/z 序)。背景层由**远景片 `bg_far`(2560×734)与地面片 `bg_floor`(2560×866)两片出图、按 y734 拼成一张**——整张一次出图时模型把远山挤到画面下半部,被围墙挡住后完全消失(实测三张里两张山体上缘落在墙顶以下)。接缝整条落在围墙背后,画面无接缝。**篝火例外**:命中矩形只取下半(火堆),上半(火焰)只作特效展示。围墙层落盘按细条裁,不做全幅(全幅约 3.9 MB 显存,细条约 0.35 MB);**实装落盘矩形 `(0, 220, 1280, 200)`、底锚 y420**(2026-11-07 用户裁:墙高 200、顶 y220;素材 1280×164 按 200 高显示拉伸,桩身/门柱比例随缩放;围墙带 (0,220,1280,200))。
|
||||||
- **色彩与氛围依据**:营地场景的冷暖分工(冷的大面积后退、暖的小面积前进)、空气透视三档与大面积用色规则 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`。本节不复述色值;新增环境色按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门)。
|
- **墙脚入土线(2026-11-07 用户裁)**:围墙不与地面以直线相接——墙底按 1–7px 低频起伏裁成透明缺口,透出背景层地面纹理,读作桩子插入土中。像素级判据:墙底不存在贯通全宽的直线边界,缺口透出的像素与背景层同列地面纹理同源。参考图指针=[camp-scene-prompts](camp-scene-prompts.md) §5 第 12 条。验收:目检〈墙底无贯通直线、桩脚有入土感〉
|
||||||
|
- **色彩与氛围依据**:营地的暖由晒白的地面、木色物件与烛光黄承载,安全温馨,与冒险中的地下城形成对比;远景=正午强日照——天空淡晴蓝(高明度低饱和的清蓝)、远山一整片连续的淡蓝灰山体(禁层叠轮廓带与阴影台阶)、草地与土路晒白,整体淡而退后,近景暖调为主。现行口径 = 本文件 §2.8「全作最暖」(管菜单容器与元进度,不约束背景天空)与本节「情绪与色域」条。本节不复述色值;新增环境色按 §4.1 场景环境子板条款登记(背景层自板 ≤32 色、营地屏双板制并集 ≤64,过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门)。
|
||||||
|
- **背景层环境色与自板(2026-11-07 录入登记)**:背景层单张走自板 ≤32 色,环境色五族=淡晴蓝天空、淡蓝灰一整片远山、晒白浅黄绿草地、暖米白土路、泛白米黄营地地面;新增色过 §4.1 两道门,近色走换色合并(本次 4 对:九件板 `#D7B281`→`#D1B27F`;全局色板基线 `#B3C8D3`→`#BAC1D2`、`#DCEDF5`→`#D8ECF0`、`#E7E5D2`→`#EBE8CE`)。像素级判据:机检〈单张像素域唯一色 ≤32;palette_check 对九件主色板基线与全局色板基线(`game/tests/golden/palette_baseline/`)均零近色红〉;目检判读句=[camp-scene-prompts](camp-scene-prompts.md) §4 远景片两条(淡晴蓝/一整片山体)。参考图指针=[asset-path-map](asset-path-map.md) §3 scene/ 行(`scene_camp_bg`)。验收:机检〈单张 ≤32 且 palette_check 零红〉+目检〈天空淡蓝不深饱和、山体一整片无层叠带〉
|
||||||
- **交互四态(零新素材,全部程序化)**:悬停=**轮廓亮边 + 浮动**(浮动须整像素吸附);按下=位移 1px;**禁用/未解锁=降明度 + 去饱和**(§2 已缩窄至情绪域,状态表达不受限),**仅锻炉(锻造工坊)与宝箱(秘宝匣)两件会有此态**;已解锁=常态。
|
- **交互四态(零新素材,全部程序化)**:悬停=**轮廓亮边 + 浮动**(浮动须整像素吸附);按下=位移 1px;**禁用/未解锁=降明度 + 去饱和**(§2 已缩窄至情绪域,状态表达不受限),**仅锻炉(锻造工坊)与宝箱(秘宝匣)两件会有此态**;已解锁=常态。
|
||||||
- **钥石余额**:常驻画面顶部的一行小 HUD 栏(高 48px,**浮层覆盖,不挤压画面**)。
|
- **钥石余额**:常驻画面顶部的一行小 HUD 栏(高 48px,**浮层覆盖,不挤压画面**)。栏体底=`CAMP_HEADER_BAND` `#6E4526`(§7.2 五 token 对齐表在册色)× 不透明度 0.80;栏内只钥石徽章一件、右位顶格,左位不放件。呈现定值的唯一事实源=[camp](../ux/camp.md) §顶栏,本节不复述判据。验收:目检〈顶栏成一条可辨窄带,徽章落在带内〉
|
||||||
- **事实源边界**:解锁条件/价格/存档写入归元进度 GDD 与 `MetaProgression`;素材命名与路径归 `asset-path-map`;清单登记归 `art-assets-checklist` §3.5。
|
- **事实源边界**:解锁条件/价格/存档写入归元进度 GDD 与 `MetaProgression`;素材命名与路径归 `asset-path-map`;清单登记归 `art-assets-checklist` §3.5。
|
||||||
- **已裁(2026-11-01 用户裁)**:① **营地环境子板色值**——不前置拍板:量化场景实际用色后按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——门扇 240×220 追认现值,坐标按门洞 x520–760 对齐(`camp-scene-prompts.md` §2.3);③ **帐篷的落地尺寸**——300×170 追认现值(各素材第一张样本稿已过审为终稿,重定即触发重出,不裁)。
|
- **已裁(2026-11-01 用户裁)**:① **营地环境子板色值**——不前置拍板:量化场景实际用色后按 §4.1 场景环境子板条款登记(背景层自板 ≤32 色、营地屏双板制并集 ≤64,过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——显示矩形 240×147(贴图可见高 138),门扇件沿用 240×211 由运行时压扁(2026-11-07 用户裁「不动美术素材」),坐标按门洞 x520–760 对齐、底压墙底 y420;③ **帐篷的落地尺寸**——251×170 落位 (982, 335),上端遮住围墙下部。
|
||||||
|
|
||||||
### 6.3 三关图类型色板候选(board_type 换挡方向)
|
### 6.3 三关图类型色板候选(board_type 换挡方向)
|
||||||
|
|
||||||
- **模板与不变槽**:换皮只换 §4.3 四槽(`tile_closed`/`tile_open`/`wall_ambient`/`variant_tint`),信息与语义层全图类型恒定——本节只给三关**方向性候选**,终值按 §4.3 现行规则重跑 §1.4 格子样张冻结。**终值的取值程序**:先跑「三关色相 × 五组类型微光」互辨抽测(抽测任务登记在待办清单),再按 §4.3 现行规则重跑 §1.4 格子样张冻结——本节不填终值色值,待该抽测与格子样张重跑后落本节修订。验收:机检〈本节三关行无 `tile_closed`/`wall_ambient` 终值色值字面量(终值未冻结前禁填)〉
|
- **模板与不变槽**:换皮只换 §4.3 四槽(`tile_closed`/`tile_open`/`wall_ambient`/`variant_tint`),信息与语义层全图类型恒定——本节的三关两槽终值**已冻结**。**冻结口径(本节不抄色值字面量)**:各关 `tile_closed` 终值=该关**岩体顶面基色**(dungeon 基准档 `#9C8462`;underdark/deep 取 §4.1「三关棋盘环境八色」的岩顶/地面值),`wall_ambient` 取同关同槽值(两槽同值;同属 §4.1 分层②场景环境子板,零新增色值、不占 48 额度);实测值与准入判定只在执行件里算,执行件用法登记见 [art-pipeline-tools](art-pipeline-tools.md)。**2026-11-07 棋盘地形换代**:旧「在役墙瓦片三块底型件实测最亮值」口径随 16+5 瓦片套退役失效;三关 `tile_closed`/`tile_open` 终值 = §4.1「三关棋盘环境八色」的岩顶/地面色(2026-11-07 用户看样张通过,冻结),旧瓦片均值不作终值;三关互辨抽测按新材质同批重跑(旧冻结凭据沿革查 git 提交史)。验收:机检〈三关行两槽终值与互辨抽测执行件的实测读数同值(该件三行铺底代表值判定全过),且本节三关行不含色值字面量〉
|
||||||
- **三关背景变体**:§6.1 的三张背景取本节三关方向作为岩体形态、剪影语言与色族差异(dungeon 暖石棕+地精巢穴支洞/木栈道/木桩围栏;underdark 冷蓝灰+卓尔巨柱/石笋/蛛网/螺旋塔剪影/巨菇/石桥;deep_underdark 灰黑+灰矮人石笋城郭/棱角石厅/矿道口/烟囱塔);背景不复用 `wall_ambient` tint(该槽作用于棋盘/世界),背景色值归战斗屏场景环境子板。验收:目检〈三关背景可辨为不同洞窟,非同一图换色〉
|
- **三关背景变体**:§6.1 的三张背景取本节三关方向作为岩体形态、剪影语言与色族差异(dungeon 暖石棕+地精巢穴支洞/木栈道/木桩围栏;underdark 冷蓝灰+卓尔巨柱/石笋/蛛网/螺旋塔剪影/巨菇/石桥;deep_underdark 灰黑+灰矮人石笋城郭/棱角石厅/矿道口/烟囱塔);背景不复用 `wall_ambient` tint(该槽作用于棋盘/世界),背景色值归战斗屏场景环境子板。验收:目检〈三关背景可辨为不同洞窟,非同一图换色〉
|
||||||
- **深度轴叙事**(§2.7 下探过渡):色相层进预告「更深更险」,明度档不动——
|
- **深度轴叙事**(§2.7 下探过渡):色相层进预告「更深更险」,明度档不动——
|
||||||
- **dungeon 地精洞窟**(第一关):现行掩尘系暖石棕(`#C9AF83` 基)即基准档,`wall_ambient` 暖棕;
|
- **dungeon 地精洞窟**(第一关):现行岩体系暖石棕(岩顶 `#9C8462` 基)即基准档,`wall_ambient` 暖棕;
|
||||||
- **underdark 幽暗地域**(第二关;方向:**冷调幽暗**):主调**灰白蓝**候选(低饱和蓝灰域,`tile_closed`),少量紫黑倾向点缀——紫系取紫罗兰域(≈256°)候选,禁入带 300°–345° 不变;`wall_ambient` 冷蓝灰;
|
- **underdark 幽暗地域**(第二关;方向:**冷调幽暗**):主调**灰白蓝**候选(低饱和蓝灰域,`tile_closed`),少量紫黑倾向点缀——紫系取紫罗兰域(≈256°)候选,禁入带 300°–345° 不变;`wall_ambient` 冷蓝灰;
|
||||||
- **deep_underdark 灰矮人矿城**(第三关;方向:**灰黑主调 + 矿脉金属色点缀**候选,守 §4.1 明度地板 L≥0.30):矿脉点缀走金属质感族(冷银/铜灰候选)——「金属色」以材质感承载,奖励金亮金仍禁上格底(§4.2),不占用收益语义金;`wall_ambient` 铁灰。
|
- **deep_underdark 灰矮人矿城**(第三关;方向:**灰黑主调 + 矿脉金属色点缀**候选,守 §4.1 明度地板 L≥0.30):矿脉点缀走金属质感族(冷银/铜灰候选)——「金属色」以材质感承载,奖励金亮金仍禁上格底(§4.2),不占用收益语义金;`wall_ambient` 铁灰。
|
||||||
- **共同纪律**:三套候选色相均须与五组类型微光色带(§4.2)抽测互辨(格底与微光同在未开格面,邻近色相有吞没风险);避 300°–345° 禁入带;L≥0.30、饱和 ≤0.55(§4.1 硬指标)。
|
- **共同纪律**:三套候选色相均须与五组类型微光色带(§4.2)抽测互辨(格底与微光同在未开格面,邻近色相有吞没风险);避 300°–345° 禁入带;L≥0.30、饱和 ≤0.55(§4.1 硬指标)。
|
||||||
@@ -420,9 +431,9 @@
|
|||||||
|
|
||||||
- **菱形灯光区(遮罩几何)**:灯光区 = 以角色所在格为中心、**曼哈顿距离 ≤ LIGHT_RADIUS** 的格集,区内照常渲染。LIGHT_RADIUS 走表值/常量参数化,**基准 8**——现行事实源「灯光区起步半径=微光环 8 格」的落码取值(半径数值沿微光「周围 8 格」的 8 起步,实测后可调)。**两圈分立注**:类型微光作用圈 = 英雄贴身 8 邻格(与可挖域同圈,现行事实源《HUD框架》「未开格类型微光」节),**不随灯光区扩**(权威文档配套裁决)——灯光区只裁可见性,微光锚仍是可挖域,两圈几何分立、半径参数互不读写。提灯插值位:FOG_LANTERN_BONUS = **+2**(flat 整数档,权威文档配套裁决;落码常量名 `board_view.gd FOG_LANTERN_BONUS`),**已接效果入库**(载体=秘宝·同调位 fog_lantern「魔法提灯」行,组合根每战装配链显式重算接线;呈现画法零改动——本节只管"怎么画",机制现行事实源仍归《HUD框架》)。边界随角色格位逐格重算,无半径插值动画。←现行事实源;§2 光照氛围允许域
|
- **菱形灯光区(遮罩几何)**:灯光区 = 以角色所在格为中心、**曼哈顿距离 ≤ LIGHT_RADIUS** 的格集,区内照常渲染。LIGHT_RADIUS 走表值/常量参数化,**基准 8**——现行事实源「灯光区起步半径=微光环 8 格」的落码取值(半径数值沿微光「周围 8 格」的 8 起步,实测后可调)。**两圈分立注**:类型微光作用圈 = 英雄贴身 8 邻格(与可挖域同圈,现行事实源《HUD框架》「未开格类型微光」节),**不随灯光区扩**(权威文档配套裁决)——灯光区只裁可见性,微光锚仍是可挖域,两圈几何分立、半径参数互不读写。提灯插值位:FOG_LANTERN_BONUS = **+2**(flat 整数档,权威文档配套裁决;落码常量名 `board_view.gd FOG_LANTERN_BONUS`),**已接效果入库**(载体=秘宝·同调位 fog_lantern「魔法提灯」行,组合根每战装配链显式重算接线;呈现画法零改动——本节只管"怎么画",机制现行事实源仍归《HUD框架》)。边界随角色格位逐格重算,无半径插值动画。←现行事实源;§2 光照氛围允许域
|
||||||
- **区外未开格:全黑不渲染(不透明档,照抄现行事实源)**:现行事实源原文「区外**未开格=全黑不渲染**」——不透明纯黑(L=0),**非高遮蔽半透档**。理由注记(为何不用高遮蔽档):①三档信息阶梯干净——未开格不可见=零信息、记忆格=弱信息、活格=全信息,叠读不打架;②高遮蔽档下砖面纹理隐约残留,与「类型微光=未开格唯一信息通道」(§4.2/§4.6.3)冲突——纹理残影泄格面观感;③现行事实源验收线「区外未开格不可见」须二值态才能逐格断言。←现行事实源;§4.2
|
- **区外未开格:全黑不渲染(不透明档,照抄现行事实源)**:现行事实源原文「区外**未开格=全黑不渲染**」——不透明纯黑(L=0),**非高遮蔽半透档**。理由注记(为何不用高遮蔽档):①三档信息阶梯干净——未开格不可见=零信息、记忆格=弱信息、活格=全信息,叠读不打架;②高遮蔽档下砖面纹理隐约残留,与「类型微光=未开格唯一信息通道」(§4.2/§4.6.3)冲突——纹理残影泄格面观感;③现行事实源验收线「区外未开格不可见」须二值态才能逐格断言。←现行事实源;§4.2
|
||||||
- **区外已开格:暗淡记忆态(灰显可读档)**:画法 = **地板纹理原样 + 灰罩压顶**——纹理直画后 `FOG_MEMORY_PLATE #3A3A3A` α0.66 灰罩盖顶,素材零改动(原「程序化素色记忆板平涂」已弃用);格内元素灰阶随罩隐现:**记忆墨 #C4C4C4(中性灰 L≈0.55)**。双峰板色牌格在记忆态**退牌归板**——牌面并入记忆态、数字以记忆墨直画。**封印印记不在记忆态面**:印记只落在未开格,区外未开格全黑——印记随格隐没、灯光区移回复显(纯呈现,封印数据零影响,现行事实源的显式推论)。←HUD框架 可访问性基线;§4.1;§3.2
|
- **区外已开格:暗淡记忆态(灰显可读档)**:画法 = **地面材质原样 + 灰罩压顶**——地面直画后 `FOG_MEMORY_PLATE #3A3A3A` α0.66 灰罩盖顶,素材零改动(原「程序化素色记忆板平涂」已弃用);格内元素灰阶随罩隐现:**记忆墨 #C4C4C4(中性灰 L≈0.55)**。记忆态数字以记忆墨直画、不使用数字底牌(浮空层随格隐没)。**封印印记与封印格身份色牌不在记忆态面**:封印格已揭示,区外记忆态灰罩下印记与色牌随格隐没、灯光区移回复显(纯呈现,封印数据零影响,现行事实源的显式推论)。←HUD框架 可访问性基线;§4.1;§3.2
|
||||||
- **记忆态可读性判据**:数字对合成底**归一后(真实渲染面)三关 ≥4.5:1**(WCAG 硬指标;合成底 L1 #4C4038/L2 #3F4147/L3 #3E4048;行值与素材随动,测点=ui_contrast_probe 迷雾段)。**归一注**:装载亮度归一是现行生产路径(`board_view._normalize_floor_luma`),原图均值≠渲染面,复算须落归一后底。可辨性自查(三通道,随样张/实机自检):①对全黑未开格——合成底 #3E3731(L≈0.036)对 L0,实机目检常光档可分(暗房档一并抽检);②对灯光区内活态已开格——主判据=数字墨灰度差(记忆墨 L0.55 对亮墨三档 L≥0.75 / 色牌 #F5EAD3 L≈0.83,灰度 ΔL≥0.20)+ 色相通道(记忆态近中性灰,对活态暖底暖墨);③格态三形在记忆态保持灰度可辨——形通道经纹理+灰罩形态不变,沿 §1.4 验收 2 同源判据。验收:机检〈ui_contrast_probe 迷雾段记忆墨对比 ≥4.5:1〉←§1.4
|
- **记忆态可读性判据**:数字对合成底**归一后(真实渲染面)三关 ≥4.5:1**(WCAG 硬指标;合成底取 §4.1 三关地面色叠加 `FOG_MEMORY_PLATE` α0.66;行值以实现批 `ui_contrast_probe` 实测登记,测点=该探针迷雾段)。旧瓦片均值派生随 `terrain_*` 退役,不再作为测点基准。可辨性自查(三通道,随样张/实机自检):①对全黑未开格——合成底 #3E3731(L≈0.036)对 L0,实机目检常光档可分(暗房档一并抽检);②对灯光区内活态已开格——主判据=数字墨灰度差(记忆墨 L0.55 对活态字芯 #F0E2C8 L≈0.77,灰度 ΔL≥0.20)+ 色相通道(记忆态近中性灰,对活态暖底暖字芯);③格态三形在记忆态保持灰度可辨——形通道经材质+灰罩形态不变,沿 §1.4 验收 2 同源判据。验收:机检〈ui_contrast_probe 迷雾段记忆墨对比 ≥4.5:1〉←§1.4
|
||||||
- **迷雾过渡边:硬边(逐格二值)**:灯光区边界 = **整格二值切换**(区内全渲染 / 区外全黑或记忆态),**不做渐变过渡带、不做半透明晕边**。理由:①边界是信息边界不是氛围晕——渐变中间态 =「看得见但看不清」,破数字可读硬指标与记忆态明度档;②现行事实源验收断言(边界格呈态、两态逐位一致)须格级二值可判;③与砖面整格表达(§3.2 高墙瓦片体系)、ITB 格内信息分层气质同轴。无动画,减动效无涉。←现行事实源;§1.2 原则一;§3.2
|
- **迷雾过渡边:硬边(逐格二值)**:灯光区边界 = **整格二值切换**(区内全渲染 / 区外全黑或记忆态),**不做渐变过渡带、不做半透明晕边**。理由:①边界是信息边界不是氛围晕——渐变中间态 =「看得见但看不清」,破数字可读硬指标与记忆态明度档;②现行事实源验收断言(边界格呈态、两态逐位一致)须格级二值可判;③与棋盘地形体系(§3.2)的整格表达、ITB 格内信息分层气质同轴。无动画,减动效无涉。←现行事实源;§1.2 原则一;§3.2
|
||||||
- **与结算期去饱和的叠加共存**:结算期去饱和偏移(settlement_fx_view,同族先例)与迷雾调制叠加规则 = **记忆态为终态档**——区外已开格在结算期保持记忆态档、**不再叠加**结算去饱和(灰显已含去饱和语义,二次调制无信息增量且明度不可控);灯光区内格照常吃结算去饱和;全黑格两态无差。叠加态随实施批共存校验 + 探针断言(provisional,实机目检可代拍)。验收:机检〈叠加态下记忆态灰显不被二次调制〉
|
- **与结算期去饱和的叠加共存**:结算期去饱和偏移(settlement_fx_view,同族先例)与迷雾调制叠加规则 = **记忆态为终态档**——区外已开格在结算期保持记忆态档、**不再叠加**结算去饱和(灰显已含去饱和语义,二次调制无信息增量且明度不可控);灯光区内格照常吃结算去饱和;全黑格两态无差。叠加态随实施批共存校验 + 探针断言(provisional,实机目检可代拍)。验收:机检〈叠加态下记忆态灰显不被二次调制〉
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -433,7 +444,7 @@
|
|||||||
|
|
||||||
### 7.1 形状语法细则(自 §3.3 迁入)
|
### 7.1 形状语法细则(自 §3.3 迁入)
|
||||||
|
|
||||||
**半拟物:容器穿戏服,数据素面。**面板=石板圆角矩形(与地砖同圆角率,全 UI 恒定),按钮=凸圆角的"可按的砖"(按压态=下沉一档,运动手段 §2),仪式性确认(胜利等)=圆形蜡封(呼应 §2.4);数字框、准线、进度条一律直角细线、无纹理;**数字色牌 = 直角小素牌**(后备件)——宽随数字位、无纹理无装饰,仅复杂格底兜底时垫于数字正下方一层(色值 §4.1),属"须精确的信息"侧、走直角律。判据:圆角=可触摸的物件,直角=须精确的信息。与参考分界:取 ITB 的信息分层,弃其冷硬斜切 HUD;取 Moonlighter 的木石亲和,不做全拟物。验收:目检〈面板圆角/按钮凸圆角/数据直角三态可辨〉
|
**半拟物:容器穿戏服,数据素面。**面板=石板圆角矩形(与地砖同圆角率,全 UI 恒定),按钮=凸圆角的"可按的砖"(按压态=下沉一档,运动手段 §2),仪式性确认(胜利等)=圆形蜡封(呼应 §2.4);数字框、准线、进度条一律直角细线、无纹理;**棋盘数字已改浮空描边字(§3.2),UI 不再有数字色牌形态**;其余数据件属"须精确的信息"侧、走直角律。判据:圆角=可触摸的物件,直角=须精确的信息。与参考分界:取 ITB 的信息分层,弃其冷硬斜切 HUD;取 Moonlighter 的木石亲和,不做全拟物。验收:目检〈面板圆角/按钮凸圆角/数据直角三态可辨〉
|
||||||
|
|
||||||
- **极性强调冗余**(§4.5⑦):UI 红/金强调对必须补图标+文案冗余;破坏性确认与常规确认禁止同位(位置通道)。验收:目检〈红/金强调位有图标+文案,破坏性确认独立位〉
|
- **极性强调冗余**(§4.5⑦):UI 红/金强调对必须补图标+文案冗余;破坏性确认与常规确认禁止同位(位置通道)。验收:目检〈红/金强调位有图标+文案,破坏性确认独立位〉
|
||||||
- **圆角率单点注记**:容器/按钮圆角值收敛为全站唯一 `RADIUS_OBJECT = 5`(ui_kit 单点;面板与按钮同圆角率即满足本节「全 UI 恒定圆角率」);数据框/数字牌/AP 点阵/准线/血条维持 0 直角;**例外三件保留**=标题屏底座椭圆 17/结算金印 200(圆形蜡封)/状态脉冲环 100(圆形)。验收:机检〈ui_kit 圆角取值仅 RADIUS_OBJECT 与例外三件〉
|
- **圆角率单点注记**:容器/按钮圆角值收敛为全站唯一 `RADIUS_OBJECT = 5`(ui_kit 单点;面板与按钮同圆角率即满足本节「全 UI 恒定圆角率」);数据框/数字牌/AP 点阵/准线/血条维持 0 直角;**例外三件保留**=标题屏底座椭圆 17/结算金印 200(圆形蜡封)/状态脉冲环 100(圆形)。验收:机检〈ui_kit 圆角取值仅 RADIUS_OBJECT 与例外三件〉
|
||||||
@@ -459,9 +470,9 @@
|
|||||||
### 7.4 字体与字号
|
### 7.4 字体与字号
|
||||||
|
|
||||||
- **字体**:全局一套像素字,单套即终稿——缝合像素字体 Fusion Pixel(OFL,已接入 `game/assets/fonts/ui_font_fusion_pixel_zh_hans.ttf`),拉丁字符与数字沿用其自带拉丁字形,不另设拉丁专件(现状即终稿;旧拉丁候选 Kenney Fonts 已弃;生产工单=清单 §3.6);墨色走主墨系(§7.2);换字体 = 全局决策。验收:机检〈主题字体指向 Fusion Pixel 件〉
|
- **字体**:全局一套像素字,单套即终稿——缝合像素字体 Fusion Pixel(OFL,已接入 `game/assets/fonts/ui_font_fusion_pixel_zh_hans.ttf`),拉丁字符与数字沿用其自带拉丁字形,不另设拉丁专件(现状即终稿;旧拉丁候选 Kenney Fonts 已弃;生产工单=清单 §3.6);墨色走主墨系(§7.2);换字体 = 全局决策。验收:机检〈主题字体指向 Fusion Pixel 件〉
|
||||||
- **字号**:像素字体**整数倍缩放,禁非整数缩放**(像素模糊);下限(1280×800 基座):棋盘数字 ≥18px(公式 = `max(18, ceil(格边长 × 0.5))`不变)、**正文/明细 ≥16px、tooltip ≥14px**(1280×800 低于 1080p 基准,同字号实际更小)。验收:机检〈静态文字位点字号 ≥ 档位表值〉
|
- **字号**:像素字体**整数倍缩放,禁非整数缩放**(像素模糊);下限(1280×800 基座):棋盘浮空数字字高 **21px 固定**(7px 像素字 ×3,不随格边缩放;见 §3.2 浮空数字)、**正文/明细 ≥16px、tooltip ≥14px**(1280×800 低于 1080p 基准,同字号实际更小)。验收:机检〈静态文字位点字号 ≥ 档位表值〉
|
||||||
- **字号档位表(六档)**:全站 UI 文字字号只经 `UiKit.FS_*` 单点取值,裸数字字号弃用——`FS_CAPTION 12`/`FS_HINT 14`/`FS_BODY 16`/`FS_SUB 18`/`FS_TITLE 24`/`FS_H1 34`。旧实测档按就近归档收编(10/11/12→CAPTION、13/14→HINT、15/16→BODY、17/18/20→SUB、21/22/24/26→TITLE、32/40→H1;静态位点全归档,数据驱动动态字号位点除外);棋盘数字公式 `maxi(18, ceil(格边长×0.5))` 与站桩血数 11px(条带内读数豁免)不入表。注:六档相邻比 12→14→16→18 三段 <1.25×,系裁决值优先于字重纪律的档差参考线,该参考线对新层级设计仍有效。验收:机检〈全站无裸数字字号,位点走 FS_*〉
|
- **字号档位表(六档)**:全站 UI 文字字号只经 `UiKit.FS_*` 单点取值,裸数字字号弃用——`FS_CAPTION 12`/`FS_HINT 14`/`FS_BODY 16`/`FS_SUB 18`/`FS_TITLE 24`/`FS_H1 34`。旧实测档按就近归档收编(10/11/12→CAPTION、13/14→HINT、15/16→BODY、17/18/20→SUB、21/22/24/26→TITLE、32/40→H1;静态位点全归档,数据驱动动态字号位点除外);棋盘浮空数字 21px 定值(非 UI 文字档)与站桩血数 11px(条带内读数豁免)不入表。注:六档相邻比 12→14→16→18 三段 <1.25×,系裁决值优先于字重纪律的档差参考线,该参考线对新层级设计仍有效。验收:机检〈全站无裸数字字号,位点走 FS_*〉
|
||||||
- **小字号豁免条款(合并单条不开两口子)**:下款两类**豁免于本节下限**——①**条带内读数**:压在窄条带(血条/进度条等 ≤12px 高带)内居中的数字,受条带高度物理约束,维持 11px 下限,且必须按 §7.2 垫素色牌后计对比(实装=B 区站桩血数 11px 压 HP_BAR_BACK 牌 14.3:1);②**装饰性 overline/caption**:不承载须精确读取的信息、仅作分区标题或氛围小字者,可至 **12px**。**豁免逐处清单(撤除史归 git 提交史,余清单如下)**:条带内读数=B 区站桩血数一处;装饰 caption 档(FS_CAPTION)在册面=棋盘底操作提示条/营地柜台说明文与结构位预留注记/图例 RAP 词条说明/设置警示文两处/关卡地图底栏组标(生命/属性/特性)与分隔系/站桩消散提示/B 区状态槽微计数(×N●○)/bcard 脚注/RAP 反馈行/刷新余量徽标——清单外 11-13px 文字一律按正文/tooltip 下限提档,新增 caption 位须同批增补本清单。**站桩顺位徽标 ①②③ 不增列本清单**:既不在①条带内读数在册面、也不在②装饰 caption 在册面,按本条纪律取 `FS_HINT` 14 归六档;为它单独入册等于开第二口子,与「合并单条不开两口子」的立条理由正面相撞。**站桩名字行同理**:名字行(敌人名与护甲文字)承载须精确读取的信息,不在①②两在册面,按本条纪律取 `FS_HINT` 14 归六档、不增列②在册面,名字行几何(素底牌矩形、文字基线、宽度测量)随档位联动。②装饰 caption 在册面逐处维持不变。验收:机检〈豁免文字位均可对上本清单,清单外无 <14px;站桩顺位徽标与站桩名字行绘制点取 UiKit.FS_HINT,且②在册面不含该两位〉
|
- **小字号豁免条款(合并单条不开两口子)**:下款两类**豁免于本节下限**——①**条带内读数**:压在窄条带(血条/进度条等 ≤12px 高带)内居中的数字,受条带高度物理约束,维持 11px 下限,且必须按 §7.2 垫素色牌后计对比(实装=B 区站桩血数 11px 压 HP_BAR_BACK 牌 14.3:1);②**装饰性 overline/caption**:不承载须精确读取的信息、仅作分区标题或氛围小字者,可至 **12px**。**豁免逐处清单(撤除史归 git 提交史,余清单如下)**:条带内读数=B 区站桩血数一处;装饰 caption 档(FS_CAPTION)在册面=营地柜台说明文与结构位预留注记/图例 RAP 词条说明/设置警示文两处/关卡地图底栏组标(生命/属性/特性)与分隔系/站桩消散提示/B 区状态槽微计数(×N●○)/bcard 脚注/RAP 反馈行/刷新余量徽标——清单外 11-13px 文字一律按正文/tooltip 下限提档,新增 caption 位须同批增补本清单。**站桩顺位徽标 ①②③ 不增列本清单**:既不在①条带内读数在册面、也不在②装饰 caption 在册面,按本条纪律取 `FS_HINT` 14 归六档;为它单独入册等于开第二口子,与「合并单条不开两口子」的立条理由正面相撞。**站桩名字行同理**:名字行(敌人名与护甲文字)承载须精确读取的信息,不在①②两在册面,按本条纪律取 `FS_HINT` 14 归六档、不增列②在册面,名字行几何(素底牌矩形、文字基线、宽度测量)随档位联动。②装饰 caption 在册面逐处维持不变。验收:机检〈豁免文字位均可对上本清单,清单外无 <14px;站桩顺位徽标与站桩名字行绘制点取 UiKit.FS_HINT,且②在册面不含该两位〉
|
||||||
- **字重纪律(字重两档不启用)**:层级手段为两件——**字号档差(相邻层级 ≥1.25×)+ 墨色深浅**;全局单字重,不上第二个字重(**重开钩子已注销**——整屏样张复核确认:屏内各级文字全部能归进本节六档字号,顺位徽标与站桩名字行两处按本节纪律提档即可,屏内实测对比全部达标(暖白对舞台底 9.49:1、GOLD_BRIGHT 6.47:1、血数 14.3:1),**未实证标题层级不足**,维持单字重,不另立条目);数字禁描边/阴影伪加粗不变(字形为唯一数值载体,§4.1 同源纪律)。验收:机检〈主题仅注册单字重〉/目检〈屏内标题与正文层级仅靠字号档差与墨色深浅两件即可分辨,无一处需要第二字重才读得清〉
|
- **字重纪律(字重两档不启用)**:层级手段为两件——**字号档差(相邻层级 ≥1.25×)+ 墨色深浅**;全局单字重,不上第二个字重(**重开钩子已注销**——整屏样张复核确认:屏内各级文字全部能归进本节六档字号,顺位徽标与站桩名字行两处按本节纪律提档即可,屏内实测对比全部达标(暖白对舞台底 9.49:1、GOLD_BRIGHT 6.47:1、血数 14.3:1),**未实证标题层级不足**,维持单字重,不另立条目);数字禁描边/阴影伪加粗不变(字形为唯一数值载体,§4.1 同源纪律)。验收:机检〈主题仅注册单字重〉/目检〈屏内标题与正文层级仅靠字号档差与墨色深浅两件即可分辨,无一处需要第二字重才读得清〉
|
||||||
|
|
||||||
### 7.5 营地界面
|
### 7.5 营地界面
|
||||||
@@ -508,12 +519,12 @@
|
|||||||
### 8.1 分辨率档位与格边长
|
### 8.1 分辨率档位与格边长
|
||||||
|
|
||||||
- **两档定案**:1280×800(基座)+ 1920×1080,窗口不可调;后续调整走修订。验收:机检〈工程分辨率配置与两档一致〉
|
- **两档定案**:1280×800(基座)+ 1920×1080,窗口不可调;后续调整走修订。验收:机检〈工程分辨率配置与两档一致〉
|
||||||
- **格边长取值**:按档位与板形计算——固定档位下格子量增加则格边长相应变小;公式、单位与现行算例的唯一出处 = [battle.md](../gdd/ux/battle.md)「棋盘格尺寸公式」,本节不复述数值。资产侧锁两条比例:**瓦片整格铺满**(32×32 源随格边长缩放,允许非整数倍——瓦片不适用 §8.2 甲类整数倍纪律)、**棋盘小人显示占位 ≤ 0.75× 格边长**。(1920 档已裁决全局等比缩放)验收:机检〈瓦片显示尺寸随格边长、小人占位 ≤0.75×〉
|
- **格边长取值**:按档位与板形计算——固定档位下格子量增加则格边长相应变小;公式、单位与现行算例的唯一出处 = [battle.md](../ux/battle.md)「棋盘格尺寸公式」,本节不复述数值。资产侧锁两条比例:**棋盘地形不铺逐格瓦片**(岩顶/地面/崖面材质按整板矩形与格边程序化绘制,允许连续缩放——地形材质不适用 §8.2 甲类整数倍纪律)、**棋盘小人显示占位 ≤ 0.75× 格边长**。(1920 档已裁决全局等比缩放)验收:机检〈地形材质随格边/整板绘制、小人占位 ≤0.75×〉
|
||||||
|
|
||||||
### 8.2 像素基准与画布
|
### 8.2 像素基准与画布
|
||||||
|
|
||||||
- **缩放纪律(硬规则,按资产两类分级;不做个案豁免)**:
|
- **缩放纪律(硬规则,按资产两类分级;不做个案豁免)**:
|
||||||
- **甲类·文本与语义件**(数字、图标、格面纹样):维持严格整数倍缩放硬规则——可读性与语义精确性优先,**禁非整数缩放不变**。封印印记不属本类(参数化绘制件,见本条末「封印印记参数表」)。砖面 tile 亦不属本类,随格边长整格铺满(见 §8.1)。验收:机检〈甲类件显示尺寸为源整数倍〉
|
- **甲类·文本与语义件**(数字、图标、格面纹样):维持严格整数倍缩放硬规则——可读性与语义精确性优先,**禁非整数缩放不变**。封印印记不属本类(参数化绘制件,见本条末「封印印记参数表」)。棋盘地形材质亦不属本类,按整板连续绘制(见 §8.1)。验收:机检〈甲类件显示尺寸为源整数倍〉
|
||||||
- **全局纹理过滤与平滑渐变件例外**:`project.godot` `default_texture_filter=0`(Nearest)全局——像素风 UI 皮(九宫格/主题石纹样式盒/滑轨抓子/勾选/箭头图标)翻 Nearest=意图面;**显式 LINEAR 豁免清单(有意例外)= vignette / gradient_base / beams 三件程序化平滑渐变件**——保平滑连续 alpha 的程序化氛围件(§7.6 三已裁);新增平滑件须同批入册本清单,禁静默挂 LINEAR。翻转面枚举与冒烟断言(6 条)在闸。验收:机检〈过滤面枚举与 LINEAR 清单逐项一致〉
|
- **全局纹理过滤与平滑渐变件例外**:`project.godot` `default_texture_filter=0`(Nearest)全局——像素风 UI 皮(九宫格/主题石纹样式盒/滑轨抓子/勾选/箭头图标)翻 Nearest=意图面;**显式 LINEAR 豁免清单(有意例外)= vignette / gradient_base / beams 三件程序化平滑渐变件**——保平滑连续 alpha 的程序化氛围件(§7.6 三已裁);新增平滑件须同批入册本清单,禁静默挂 LINEAR。翻转面枚举与冒烟断言(6 条)在闸。验收:机检〈过滤面枚举与 LINEAR 清单逐项一致〉
|
||||||
- **显示档登记例外(64 源 0.5×,待素材批消除)**:柜台四枚 `icon_forge/workshop/atlas/keystone`(64×64 源)显示档统一 **32px = 0.5×**;状态九枚(32×32 源)mini(站桩)档 **16px = 0.5×**。两处均系「显示尺寸侧唯一可调、素材一字节禁改」红线下的人工检整数半倍档,登记为**待消除例外**——素材设计出 32px 源后回归 1×。常规档显示一律 1×(状态九枚 32px、手绘十枚 20px/40px 双档、BCard 图标槽 40px=2×、**护甲类型图标三枚 24px=1×**——源 24×24,归甲类整数倍纪律)。验收:机检〈显示档与登记表一致〉
|
- **显示档登记例外(64 源 0.5×,待素材批消除)**:柜台四枚 `icon_forge/workshop/atlas/keystone`(64×64 源)显示档统一 **32px = 0.5×**;状态九枚(32×32 源)mini(站桩)档 **16px = 0.5×**。两处均系「显示尺寸侧唯一可调、素材一字节禁改」红线下的人工检整数半倍档,登记为**待消除例外**——素材设计出 32px 源后回归 1×。常规档显示一律 1×(状态九枚 32px、手绘十枚 20px/40px 双档、BCard 图标槽 40px=2×、**护甲类型图标三枚 24px=1×**——源 24×24,归甲类整数倍纪律)。验收:机检〈显示档与登记表一致〉
|
||||||
- **乙类·角色与单位精灵**(有机形体、非文字):允许运行时非整数倍缩放(NEAREST 过滤不变),容忍轻度像素宽窄不均;判据 = 实机目检,可感不适即回整数档。乙类免逐案豁免。验收:目检〈立绘无可感拉花〉
|
- **乙类·角色与单位精灵**(有机形体、非文字):允许运行时非整数倍缩放(NEAREST 过滤不变),容忍轻度像素宽窄不均;判据 = 实机目检,可感不适即回整数档。乙类免逐案豁免。验收:目检〈立绘无可感拉花〉
|
||||||
@@ -521,10 +532,10 @@
|
|||||||
- **1920×1080 档策略**:全局等比(stretch=canvas_items+aspect **keep**)——16:10 设计在 16:9 窗口=等比 1.35×+左右黑边各 ~96px,构图与 1280×800 基准档完全一致;甲类 1.35 非整数缩放例外注记:轻度宽窄不均系本档位接受代价(像素游戏 shipped 常态),实机目检可感不适→回乙案(1920 独立 2× 基准)重议;乙类同前款。验收:目检〈1920 档构图与 1280 档一致〉
|
- **1920×1080 档策略**:全局等比(stretch=canvas_items+aspect **keep**)——16:10 设计在 16:9 窗口=等比 1.35×+左右黑边各 ~96px,构图与 1280×800 基准档完全一致;甲类 1.35 非整数缩放例外注记:轻度宽窄不均系本档位接受代价(像素游戏 shipped 常态),实机目检可感不适→回乙案(1920 独立 2× 基准)重议;乙类同前款。验收:目检〈1920 档构图与 1280 档一致〉
|
||||||
- **画布基准(暂定值)**:
|
- **画布基准(暂定值)**:
|
||||||
- **主角人设原图 = 48×72**(1× 基准,暂定;与站姿降采样可读性验证一致);
|
- **主角人设原图 = 48×72**(1× 基准,暂定;与站姿降采样可读性验证一致);
|
||||||
- **棋盘小人 = 32×32 二头身派生版(暂定,允许更小)**——独立资产,自人设定稿压缩派生(character-design §5.4),不吞数字位、占位 ≤ 0.75× 格边长;板越小占比摩擦越大(13×13 / 14×14 更小,算例见 [battle.md](../gdd/ux/battle.md)「棋盘格尺寸公式」),32px 源档的去留已定终值 = **保留 32×32 源档**(沿「独立小源档」路线;N=12 板下显示占位上限 27px = 0.84 倍,正落本节乙类非整数缩放许可范围,**连豁免都不用再办**),待决标注注销;
|
- **棋盘小人 = 32×32 二头身派生版(暂定,允许更小)**——独立资产,自人设定稿压缩派生(character-design §5.4),不吞数字位、占位 ≤ 0.75× 格边长;板越小占比摩擦越大(13×13 / 14×14 更小,算例见 [battle.md](../ux/battle.md)「棋盘格尺寸公式」),32px 源档的去留已定终值 = **保留 32×32 源档**(沿「独立小源档」路线;N=12 板 38px 档下显示占位上限 = 0.75×38 ≈ 28px,正落本节乙类非整数缩放许可范围,**连豁免都不用再办**),待决标注注销;
|
||||||
- **封印印记参数表(绘制件,非贴图件)**:形与画法见 §3.2。定值——**环外径 = 0.82 × 格边**(26 格 21.3px/46 格 37.7px);**环壁厚 = 0.11 × 环径**(≈2.3/4.1px);**十字臂宽 = 0.156 × 环径**(≈3.3/5.9px);**环外光圈宽 = 0.09 × 格边**(≈2.3/4.1px),向外衰减指数 1.6、峰值 alpha 0.50;圆心 = 格心。色 = 封印黑单色(光圈只改 alpha)。本件随格边连续缩放,**不适用甲类整数倍纪律**(非贴图件,见上条清单)。参数单点 = `ui_kit.gd` 六枚常量 `SEAL_RING_FRAC`/`SEAL_WALL_FRAC`/`SEAL_ARM_FRAC`/`SEAL_HALO_ALPHA`/`SEAL_HALO_GAMMA`/`SEAL_HALO_FRAC`,本节为条款侧对照值。改值须本节与 §3.2 同批修订。验收:机检〈ui_kit 六常量与本表逐值一致〉+目检〈渲染帧量环径落 82%±1px、光圈不越格边〉
|
- **封印印记参数表(绘制件,非贴图件)**:形与画法见 §3.2。定值——**环外径 = 0.82 × 格边**(26 格 21.3px/46 格 37.7px);**环壁厚 = 0.11 × 环径**(≈2.3/4.1px);**十字臂宽 = 0.156 × 环径**(≈3.3/5.9px);**环外光圈宽 = 0.09 × 格边**(≈2.3/4.1px),向外衰减指数 1.6、峰值 alpha 0.50;**圆心 = 格心**(已揭示地面;承载面 = 本关受光棱色封印石,见 §3.2;不再随岩顶偏移)。色 = 封印黑单色(光圈只改 alpha)。本件随格边连续缩放,**不适用甲类整数倍纪律**(非贴图件,见上条清单)。参数单点 = `ui_kit.gd` 六枚常量 `SEAL_RING_FRAC`/`SEAL_WALL_FRAC`/`SEAL_ARM_FRAC`/`SEAL_HALO_ALPHA`/`SEAL_HALO_GAMMA`/`SEAL_HALO_FRAC`,本节为条款侧对照值。改值须本节与 §3.2 同批修订。验收:机检〈ui_kit 六常量与本表逐值一致〉+目检〈渲染帧量环径落 82%±1px、圆心落格心、光圈不越格边〉
|
||||||
- **站桩立绘显示档 = 三档绝对高**:小型 96 / 中型 144 / 大型 188。逐件归档——小:地精、巨蜘蛛、灰矮人;中:主角、钩爪恐魔、熊地精;大:食人魔酋长、蛛化卓尔、灰矮人石君王。**源 = 原稿像素网格**(八敌 `pixel-1`、主角手修 2× 三态稿),紧裁后原样入包,**禁再降采样**;显示倍率 = 档高 ÷ 源高,NEAREST,宽度随源图比例(高定宽随不变,见上条)。定档依据 = 生物体型(体量=物种体型,非强度线性映射,见 character-design §5.2),**顺序由显示档承载、不由源高承载**。已接受项:中型三件与地精/巨蜘蛛的源高(92/94/123/90/81)低于档高,属放大显示;食人魔酋长显示宽 157 超桩盒 150。验收:机检〈standee_asset_check 逐件显示档高与归档一致、纵横倍率恒等〉+目检〈同屏体量顺序成立〉
|
- **站桩立绘显示档 = 三档绝对高**:小型 96 / 中型 144 / 大型 188。逐件归档——小:地精、巨蜘蛛、灰矮人;中:主角、钩爪恐魔、熊地精;大:食人魔酋长、蛛化卓尔、灰矮人石君王。**源 = 原稿像素网格**(八敌 `pixel-1`、主角手修 2× 三态稿),紧裁后原样入包,**禁再降采样**;显示倍率 = 档高 ÷ 源高,NEAREST,宽度随源图比例(高定宽随不变,见上条)。定档依据 = 生物体型(体量=物种体型,非强度线性映射,见 character-design §5.2),**顺序由显示档承载、不由源高承载**。已接受项:中型三件与地精/巨蜘蛛的源高(92/94/123/90/81)低于档高,属放大显示;食人魔酋长显示宽 157 超桩盒 150。验收:机检〈standee_asset_check 逐件显示档高与归档一致、纵横倍率恒等〉+目检〈同屏体量顺序成立〉
|
||||||
- **站桩立绘排版**:① 区高 B 区 ≈1/3 屏 / C 区 ≈2/3 屏,**扫雷盘原尺寸不缩、格子不变**(区高事实源 = 布局表 `battle_layout.tres`;压缩由 C 区面板空档吸收);② 站桩内部重排——立绘双脚落石台上缘(弃盒内居中)、**血条+状态/名字行落底排**(立绘→血条→状态 顺序,全场血条对齐一线;血条嵌石板位、台缘线留作地面线、落影保留接地感),状态空时该行退化为名字行;③ 大体档(显示 >150px 级:食人魔酋长/蛛化卓尔/灰矮人石君王)**允许向上溢出盒顶 N px**(N 按实测尺寸算定,**与背景/光柱无关**——现行溢出区恰为临时光柱氛围层〔§6.1 方向稿四柱,x 基准 110/900/1055/1210@1280,`battle_stage_view.gd:47-56`〕,正式舞台背景插画(三关变体)到位后该层直接退役(背景不画光柱),**溢出判定不随之变更**;横向禁止压到顶部中央轮次·阶段指示,溢出上限用真图复算 x 区间定),血条仍落底(落底排的第二个收益=头部探顶不带出血条);意图徽标悬浮头顶上方(探顶档压胸);④ 「血条悬浮头顶+立绘盒内居中」排式已弃——盒顶固定 y 与盒内居中在高盒下拉开血条-立绘空洞。验收:目检〈血条一线对齐、大体档溢出不压轮次指示〉
|
- **站桩立绘排版**:① 区高 B 区 ≈1/3 屏 / C 区 ≈2/3 屏,**扫雷盘不从 D 区裁尺寸**(区高事实源 = 布局表 `battle_layout.tres`;2026-11-07 顶栏搬两侧后 D 区全高归棋盘,格边按 battle.md 公式现算——基座档 12×12=38px、14×14=32px,不再受 AP 条高度挤压);② 站桩内部重排——立绘双脚落石台上缘(弃盒内居中)、**血条+状态/名字行落底排**(立绘→血条→状态 顺序,全场血条对齐一线;血条嵌石板位、台缘线留作地面线、落影保留接地感),状态空时该行退化为名字行;③ 大体档(显示 >150px 级:食人魔酋长/蛛化卓尔/灰矮人石君王)**允许向上溢出盒顶 N px**(N 按实测尺寸算定,**与背景/光柱无关**——现行溢出区恰为临时光柱氛围层〔§6.1 方向稿四柱,x 基准 110/900/1055/1210@1280,`battle_stage_view.gd:47-56`〕,正式舞台背景插画(三关变体)到位后该层直接退役(背景不画光柱),**溢出判定不随之变更**;横向禁止压到顶部中央轮次·阶段指示,溢出上限用真图复算 x 区间定),血条仍落底(落底排的第二个收益=头部探顶不带出血条);意图徽标悬浮头顶上方(探顶档压胸);④ 「血条悬浮头顶+立绘盒内居中」排式已弃——盒顶固定 y 与盒内居中在高盒下拉开血条-立绘空洞。验收:目检〈血条一线对齐、大体档溢出不压轮次指示〉
|
||||||
- **站桩石板地台件**:`scene_stage_plaza.png`,源 48×12、九宫格横向拉伸、顶缘受光线 2px 不随拉伸变形;跨三关恒定、不吃 §4.3 `wall_ambient` tint(独立理由见 §6.1 近景地台独立件条)。验收:机检〈地台件按九宫格拉伸后顶缘受光线宽度恒为 2px〉
|
- **站桩石板地台件**:`scene_stage_plaza.png`,源 48×12、九宫格横向拉伸、顶缘受光线 2px 不随拉伸变形;跨三关恒定、不吃 §4.3 `wall_ambient` tint(独立理由见 §6.1 近景地台独立件条)。验收:机检〈地台件按九宫格拉伸后顶缘受光线宽度恒为 2px〉
|
||||||
|
|
||||||
### 8.3 导出格式与命名规范
|
### 8.3 导出格式与命名规范
|
||||||
@@ -545,14 +556,14 @@
|
|||||||
|
|
||||||
- **结构件完整性**:格面立体感(高墙顶面/坡缘/角件/周界轮廓)只能来自**素材本体绘制的结构件拼装**(样例=Necesse 式缘件:专属底色+手绘细节+暗轮廓线的独立贴图);禁止以调色、渐变、明暗滤镜、跨格投影等生成手段伪造素材中不存在的结构。样稿暴露缺件时,正确动作=停下报告缺口与「换素材/自产缺件」选项,由用户裁决后执行。验收:目检〈立体感逐件来自素材本体,无滤镜伪造〉
|
- **结构件完整性**:格面立体感(高墙顶面/坡缘/角件/周界轮廓)只能来自**素材本体绘制的结构件拼装**(样例=Necesse 式缘件:专属底色+手绘细节+暗轮廓线的独立贴图);禁止以调色、渐变、明暗滤镜、跨格投影等生成手段伪造素材中不存在的结构。样稿暴露缺件时,正确动作=停下报告缺口与「换素材/自产缺件」选项,由用户裁决后执行。验收:目检〈立体感逐件来自素材本体,无滤镜伪造〉
|
||||||
- **参考核验**:宣称「参考 X 游戏」前,必须取得并实际查看 X 的截图证据(像素级放大核验其实现方式),证据存 `artwork/mockups/` 或 `design/art/references/`;仅凭文字资料、记忆或宏观印象作出「X 是这样做」的断言无效。验收:目检〈参考结论有截图证据在库〉
|
- **参考核验**:宣称「参考 X 游戏」前,必须取得并实际查看 X 的截图证据(像素级放大核验其实现方式),证据存 `artwork/mockups/` 或 `design/art/references/`;仅凭文字资料、记忆或宏观印象作出「X 是这样做」的断言无效。验收:目检〈参考结论有截图证据在库〉
|
||||||
- **图底分离**:已开地面的明度须低于未开格墙体,由素材选型承载(选更暗的地板砖),不靠渲染压暗实现。验收:机检〈已开格底明度低于墙顶面〉
|
- **图底分离**:已开地面的明度须低于未开格岩体,由材质选型承载(地面基色 `#695038` 低于岩顶 `#9C8462`),不靠渲染压暗实现。验收:机检〈已开地面明度低于岩顶面〉
|
||||||
- **生产分工**:格面地形类素材=**材质归模型、结构归程序**——AI 生图模型只出无缝填充纹理(无边框/无亮边/均匀光照/方形);一切结构件(缘件/轮廓/立面/角件/收头)一律程序化绘制或手修,因为 autotile 任意拼接的边界像素约束超出 2D 生图模型能力(实证:生图 5×5 瓦片表每枚砖自带啃咬边框与宽亮带,提示词无法根除)。**镜像规则**:东西对称结构件只许水平翻转(flip_h)复用、**禁旋转**——北受光下东西侧缘光照对称,镜像无损真;旋转会把北受光转到东边。验收:目检〈瓦片表无自带边框/亮带;对称件仅 flip_h〉
|
- **生产分工**:格面地形类素材=**材质归模型、结构归程序**——AI 生图模型只出无缝填充纹理(无边框/无亮边/均匀光照/方形);一切结构件(缘件/轮廓/立面/角件/收头)一律程序化绘制或手修,因为 autotile 任意拼接的边界像素约束超出 2D 生图模型能力(实证:生图 5×5 瓦片表每枚砖自带啃咬边框与宽亮带,提示词无法根除)。**镜像规则**:东西对称结构件只许水平翻转(flip_h)复用、**禁旋转**——北受光下东西侧缘光照对称,镜像无损真;旋转会把北受光转到东边。验收:目检〈瓦片表无自带边框/亮带;对称件仅 flip_h〉
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. 参考与反参考(References & Anti-References)
|
## 9. 参考与反参考(References & Anti-References)
|
||||||
|
|
||||||
> **白话**:正面参考 = 向谁抄什么;反面参考 = 避什么。两者同等效力——方案违反反面条款时,禁止以「参考了某游戏」辩护。参考图库存于 `design/art/references/`(点名池三款×2 张,与头注点名池一一对应)。
|
> **白话**:正面参考 = 向谁抄什么;反面参考 = 避什么。两者同等效力——方案违反反面条款时,禁止以「参考了某游戏」辩护。参考图库存于 `design/art/references/`(原三款×2 张在库;2026-11-07 新增参考图证待补,不阻塞画法条款)。
|
||||||
|
|
||||||
### 9.1 正面参考(点名池,用户审阅选定)
|
### 9.1 正面参考(点名池,用户审阅选定)
|
||||||
|
|
||||||
@@ -561,6 +572,10 @@
|
|||||||
| **Into the Breach** | 格内信息分层、攻击预告上格范式、战棋地块质感骨架(§1.2 原则一;§3.2) | 冷暗军事色调、压暗信息板、斜切 HUD(原则二;§3.3) |
|
| **Into the Breach** | 格内信息分层、攻击预告上格范式、战棋地块质感骨架(§1.2 原则一;§3.2) | 冷暗军事色调、压暗信息板、斜切 HUD(原则二;§3.3) |
|
||||||
| **Moonlighter** | 暖质地砖与砖缝质感、亲和冒险者气质、木石暖色道具(原则二/原则三);**光照层次与明度纵深**(亮地板/暗深渊/发光体三档,§2 明度分层) | 全拟物倾向(§3.3 半拟物边界);Darkest 式压暗(§9.2 反面基准) |
|
| **Moonlighter** | 暖质地砖与砖缝质感、亲和冒险者气质、木石暖色道具(原则二/原则三);**光照层次与明度纵深**(亮地板/暗深渊/发光体三档,§2 明度分层) | 全拟物倾向(§3.3 半拟物边界);Darkest 式压暗(§9.2 反面基准) |
|
||||||
| **Peglin** | 明快全年龄洞穴色彩、胖体量亲和怪(§5.1 普通怪原型) | 色块依赖——先读轮廓后读颜色(§5.1) |
|
| **Peglin** | 明快全年龄洞穴色彩、胖体量亲和怪(§5.1 普通怪原型) | 色块依赖——先读轮廓后读颜色(§5.1) |
|
||||||
|
| **Stardew Valley** | 连续地面与大地块地形的平铺控制、暖色可读性(§3.2 地形材质与装饰) | 农务 UI、角色比例、柔光/渐变 |
|
||||||
|
| **Minish Cap** | 圆润岩体轮廓、紧凑像素可读性(§3.2 岩体受光与崖面) | GBA 分辨率限制、过小角色比例 |
|
||||||
|
| **Necesse**(补充) | 大块地形按连续面画、不按逐格物件画(§3.2 术语与定义) | 生存制作 UI |
|
||||||
|
| **Link's Awakening 原版/DX 2D**(补充) | 抬升台面与南向崖面的 2D 观感(§3.2 投影与搭接) | 2019 重制 3D 立体模型版(风格不合,排除) |
|
||||||
|
|
||||||
- **反面条款已成文**(§9.2);反面参考**图证**待本作素材生成后增补。验收:方向性
|
- **反面条款已成文**(§9.2);反面参考**图证**待本作素材生成后增补。验收:方向性
|
||||||
|
|
||||||
@@ -569,9 +584,9 @@
|
|||||||
| 反面参考 | 违反条款 | 立法理由 |
|
| 反面参考 | 违反条款 | 立法理由 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Darkest Dungeon** 式压暗 | §9.2 反面基准(风格取向记录,非禁令——压暗属普通设计决策,逐案走样张与目检) | 失败重开,世界无光暗记忆——明亮基调下不以整屏变暗作常态表达 |
|
| **Darkest Dungeon** 式压暗 | §9.2 反面基准(风格取向记录,非禁令——压暗属普通设计决策,逐案走样张与目检) | 失败重开,世界无光暗记忆——明亮基调下不以整屏变暗作常态表达 |
|
||||||
| **传统扫雷白牌/贴纸式数字承载** | §1.2 原则二(明度分档为骨) | 数字由格底明度分档承载、直画入世界;色牌仅复杂格底后备——满屏白牌=电子表格观感,非游戏画面 |
|
| **传统扫雷白牌/贴纸式数字承载** | §1.2 原则二(明度分档为骨);§3.2 浮空数字 | 数字由浮空描边字承载、画在世界之上;不使用数字底牌——满屏白牌=电子表格观感,非游戏画面 |
|
||||||
| **Enter the Gungeon** 式粒子与色相爆炸 | §3.4 焦点预算;§4.2 色相纪律 | 信息层禁止被特效与杂色吞没,特效入画先过焦点预算 |
|
| **Enter the Gungeon** 式粒子与色相爆炸 | §3.4 焦点预算;§4.2 色相纪律 | 信息层禁止被特效与杂色吞没,特效入画先过焦点预算 |
|
||||||
| **Hades** 式特效密度 | §2.2 兑现爽感的上限 | 爽感靠逐行因果归因,不靠满屏特效;承载元素以 §2.2 清单为界 |
|
| **Hades** 式特效密度 | §2.2 兑现爽感的上限 | 爽感靠逐行因果归因,不靠满屏特效;承载元素以 §2.2 清单为界 |
|
||||||
| **传统扫雷 1–8 八色分色** | §4.1 数字墨三档 | 八色必撞红/金/蓝/紫赤语义色段;数字只走墨族三档色温,字形为唯一数值载体 |
|
| **传统扫雷 1–8 八色分色** | §4.1 数字墨单色制 | 八色必撞红/金/蓝/紫赤语义色段;数字只走单色浮空字芯,字形为唯一数值载体 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1,7 +1,28 @@
|
|||||||
# 美术后处理与校验工具清单
|
# 美术后处理与校验工具清单
|
||||||
|
|
||||||
> **性质**:本文件是 `tools/` 下美术资产处理与校验脚本的用法清单。回答三件事:这类资产该跑哪件工具、命令怎么敲、判据与坑在哪。
|
> **性质**:本文件是 `tools/` 下美术资产处理与校验脚本的用法清单,兼**执行件门值登记面**——美术数值定值(色值、阈值、档位、帧数、区间)的落点速查索引。回答三件事:这类资产该跑哪件工具、命令怎么敲、判据与坑在哪。
|
||||||
> **边界**:只管工具用法,不立美术规格。色值、画布、体量、命名与验收条款归 [art-bible](art-bible.md)(§4.1 主色板、§8 资产与技术规范)和 [art-assets-checklist](art-assets-checklist.md);命令与源码冲突时以源码现行为准,美术规格冲突时以 art-bible 为准。素材入库与代码接线归 [asset-path-map](asset-path-map.md),不在本文件。
|
> **边界**:只管工具用法与定值落点登记,不立美术规格。概念、规则与方向归 [art-bible](art-bible.md);命令与源码冲突时以源码现行为准,美术规格冲突时以 art-bible 为准。素材入库与代码接线归 [asset-path-map](asset-path-map.md),不在本文件。
|
||||||
|
|
||||||
|
## 执行件门值登记(定值落点速查索引,2026-11-07 立)
|
||||||
|
|
||||||
|
美术数值定值的落点速查——每行=一个定值面与其承载件;改值=改对应执行件并跑其守门断言,文档侧对照值同批核对:
|
||||||
|
|
||||||
|
| 定值面 | 承载件 |
|
||||||
|
|---|---|
|
||||||
|
| 色值 token 全板(语义色/墨族/材质色/呈现态) | `game/presentation/views/ui_kit.gd` 常量组(色板唯一来源)+ theme README 溯源表 |
|
||||||
|
| token 存量近色互查与新增色第二道门 | `tools/palette_check.py`(素材侧)+ `palette_token_pairwise_test.gd`(常量面守门,含在册豁免账) |
|
||||||
|
| 微光五组色值与呈现参数 | `ui_kit.gd` 微光常量组+`type_glow_test.gd` 守门断言 |
|
||||||
|
| 未开格底/图类型色板准入门(亮度地板/饱和上限/禁入带/近色容差)与**世界底层两子带** | `tools/glow_discrimination_sheet.py` 门值常量(本件「判据或口径」节) |
|
||||||
|
| 已开格底渲染面亮度 | `game/presentation/views/tile_palette.gd` 归一化目标常量;对比判据=`game/probe/ui_contrast_probe.gd` |
|
||||||
|
| 文字对比门槛(WCAG AA)与整屏有效色数上限 | `tools/shot_checker.py` 常量(`ui_contrast_probe` 同源) |
|
||||||
|
| 封印印记六参数 | `ui_kit.gd` `SEAL_*` 六常量+`seal_mark_params_test.gd` |
|
||||||
|
| 站桩显示档三档与源档逐件 | `standee_present_values_test.gd` 钉值+`tools/standee_asset_check.py` |
|
||||||
|
| 动画帧数档(待机/攻击/受击) | `animation_frame_spec_test.gd` 规格表(序列帧资产入包后逐件判) |
|
||||||
|
| 字号六档与下限 | `ui_kit.gd` `FS_*` 常量组 |
|
||||||
|
| 屏级分区几何/带高 | `game/data/tables/battle_layout.tres`(数据索引,art-bible 直指) |
|
||||||
|
| 营地场景坐标群(落盘矩形/命中矩形/z 序/桩柱高) | `camp-scene-prompts.md` 坐标表+落盘件 |
|
||||||
|
| 棋盘结构件 px(墨线/暗带/投影/悬崖) | `board_world.gd`/`board_view.gd` 常量+渲染闸 golden 基线 |
|
||||||
|
| 视野迷雾半径/提灯加成/记忆态常量 | `board_view.gd` `FOG_*` 常量+`ui_kit.gd` 迷雾常量组 |
|
||||||
> **分工**:[art-prompts](art-prompts.md) 管角色级提示词与五步出图流程,[camp-scene-prompts](camp-scene-prompts.md) 管营地场景分层提示词与四步流程;两卡只把「后处理」一步指到本文件。提示词怎么写出图、出完图怎么处理,是两件事。
|
> **分工**:[art-prompts](art-prompts.md) 管角色级提示词与五步出图流程,[camp-scene-prompts](camp-scene-prompts.md) 管营地场景分层提示词与四步流程;两卡只把「后处理」一步指到本文件。提示词怎么写出图、出完图怎么处理,是两件事。
|
||||||
> **命令前提**:以下命令均在仓库根执行。素材不入 git,worktree 缺件时部分脚本回退主检出 `D:/code/g-plan2`,部分直接返回错误,见各节「已知坑与适用边界」。
|
> **命令前提**:以下命令均在仓库根执行。素材不入 git,worktree 缺件时部分脚本回退主检出 `D:/code/g-plan2`,部分直接返回错误,见各节「已知坑与适用边界」。
|
||||||
|
|
||||||
@@ -15,6 +36,7 @@
|
|||||||
| UI 框材(面板、按钮、石框、底噪、图标) | `tools/quantize_ui_skin.py` | `tools/palette_check.py`、`tools/path_check.py` | 主题小件另跑 `tools/gen_theme_icons.py` |
|
| UI 框材(面板、按钮、石框、底噪、图标) | `tools/quantize_ui_skin.py` | `tools/palette_check.py`、`tools/path_check.py` | 主题小件另跑 `tools/gen_theme_icons.py` |
|
||||||
| 地形瓦片 | `tools/recolor_terrain_tiles.py` | `tools/palette_check.py` | 只换色,不重绘 |
|
| 地形瓦片 | `tools/recolor_terrain_tiles.py` | `tools/palette_check.py` | 只换色,不重绘 |
|
||||||
| 整屏样张 | `tools/render_sample_sheet_v3.py`、`tools/render_level_map_sheet.py` | `tools/shot_checker.py`;棋盘回归用 `tools/golden_board_crop.py` 加 `tools/golden_compare.py` | 样张脚本生成后自带机检 |
|
| 整屏样张 | `tools/render_sample_sheet_v3.py`、`tools/render_level_map_sheet.py` | `tools/shot_checker.py`;棋盘回归用 `tools/golden_board_crop.py` 加 `tools/golden_compare.py` | 样张脚本生成后自带机检 |
|
||||||
|
| 图类型色板互辨抽测(三关格底 × 五组微光) | `tools/glow_discrimination_sheet.py` | `tools/palette_check.py`(近色比对池同源)、`tools/shot_checker.py`(WCAG 公式同源) | 出并列样图+逐对读数表;格底准入的门值单点在本件 |
|
||||||
|
|
||||||
## 三条已知边界
|
## 三条已知边界
|
||||||
|
|
||||||
@@ -291,3 +313,22 @@ python tools/path_check.py --repo . --code game
|
|||||||
**判据或口径**:L1 查 `asset-path-map` §1 的声明目录,`design/art/candidates` 按需创建豁免。L2 查 `game/assets/art` 的四个语义子目录与现役文件清单,含主角 idle/walk/portrait、八敌、铲三帧、封印印记。L3 grep 代码里的 `res://assets/art` 引用,核对盘上存在性,并检出 `board_floor`、`board_wall`、`pillar_dungeon`、`production/mockups` 等退役命名;路径模板含 `%s` 或 `%d` 的跳过。worktree 素材未同步时,缺失项标 SKIP 不判红;主区完整素材环境才全量判。全过 0,有红灯 1。
|
**判据或口径**:L1 查 `asset-path-map` §1 的声明目录,`design/art/candidates` 按需创建豁免。L2 查 `game/assets/art` 的四个语义子目录与现役文件清单,含主角 idle/walk/portrait、八敌、铲三帧、封印印记。L3 grep 代码里的 `res://assets/art` 引用,核对盘上存在性,并检出 `board_floor`、`board_wall`、`pillar_dungeon`、`production/mockups` 等退役命名;路径模板含 `%s` 或 `%d` 的跳过。worktree 素材未同步时,缺失项标 SKIP 不判红;主区完整素材环境才全量判。全过 0,有红灯 1。
|
||||||
|
|
||||||
**已知坑与适用边界**:依赖 `asset-path-map.md` 的声明清单与代码常量;新增素材目录不更新文档就不会被查。素材不入 git,worktree 空或半同步会大量 SKIP,不能据此判断主区健康。只核对路径存在与退役命名,不核对图像内容、尺寸或色板。
|
**已知坑与适用边界**:依赖 `asset-path-map.md` 的声明清单与代码常量;新增素材目录不更新文档就不会被查。素材不入 git,worktree 空或半同步会大量 SKIP,不能据此判断主区健康。只核对路径存在与退役命名,不核对图像内容、尺寸或色板。
|
||||||
|
|
||||||
|
## tools/glow_discrimination_sheet.py
|
||||||
|
|
||||||
|
**一句话定位**:三关图类型色板 × 五组类型微光的互辨抽测执行件——出一张并列样图(54 格=三关 × 三底型 × 五组 + 基准格,含灰度副本段与图例),自带机检判定并落逐对读数表。
|
||||||
|
|
||||||
|
**归属**:仓库内 `tools/glow_discrimination_sheet.py`。
|
||||||
|
|
||||||
|
**输入与输出**:读 `game/assets/art/board/terrain_wall_center*_ <board_type>.png` 三块底型件、`game/presentation/views/ui_kit.gd` 的微光冻结常量、`game/tests/golden/palette_baseline/` 两张条带作近色比对池;合成侧逐像素复刻 `game/presentation/views/cell_type_glow.gdshader`。产物=`artwork/mockups/glow-discrimination-sheet-<日期>.png`(不入 git)+ `reports/` 下当日读数表。
|
||||||
|
|
||||||
|
**用法命令**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python tools/glow_discrimination_sheet.py # 取准入读数 + 出样图 + 机检全道 + 落读数表
|
||||||
|
python tools/glow_discrimination_sheet.py --no-sheet # 只跑铺底准入五门,不出图不落表
|
||||||
|
```
|
||||||
|
|
||||||
|
**判据或口径**:门值单点在本件常量,文档侧不抄——`FLOOR_L`(未开格底线性亮度地板)、`CEIL_SAT`(饱和上限)、`BANNED_HUE`(禁入色相带)、`NEAR_EPS`(近色容差)、`B_MIN_CH_DIFF`(格底对微光可辨底线)、`C_MODEL_TOL`(样图与合成模型容差)。铺底代表值不查色表:取该关三块底型件像素里**线性相对亮度最大**的实测色(顶面受光档),素材换色后读数自动跟随。判定四道=A 五组明度阶梯单调且组间对比过线、B 格底对微光的三通道差禁止全部小于容差、C 样图与合成模型差落在容差内、D 准入五门;目检四条归用户,与机器判定并列取严(任一侧不过即该对不过)。退出码 0=全绿、1=有 FAIL、2=底型件缺位硬阻塞。
|
||||||
|
|
||||||
|
**已知坑与适用边界**:素材不入 git,worktree 缺三块底型件时直接 `exit(2)`——抽测的先决条件不成立,不是假红。色相吞没刻意不设机检阈值:本仓无一条文给出色相差门槛,自造一个等于把观感问题伪装成可机检问题,故色相差只进读数表列、不参与判定。带域与格心取样口径与 `game/probe/type_glow_shot_probe.gd` 同源(带域 de<格边×0.125、格心内缩 20%),改探针口径须同步本件。
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
| 素材 | 状态 | 需求文档 |
|
| 素材 | 状态 | 需求文档 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 主角战斗小人(待机/攻击/受击三态) | ✅ 已交付:B 区站桩三态按原稿分辨率入包、显示按档缩放落位(显示档=中档 144,源=手修 2× 三态稿,art-bible §8.2),机检全绿;挂事件切换、结算回 idle 短驻自回;棋盘 1.5×/脚锚25%/椭圆影在役 | [character-design](character-design.md) + [art-prompts](art-prompts.md) §2 |
|
| 主角战斗小人(待机/攻击/受击三态) | ✅ 已交付:B 区站桩三态按原稿分辨率入包、显示按档缩放落位(显示档=中档,源=手修 2× 三态稿,art-bible §8.2),机检全绿;挂事件切换、结算回 idle 短驻自回;棋盘 1.5×/脚锚25%/椭圆影在役 | [character-design](character-design.md) + [art-prompts](art-prompts.md) §2 |
|
||||||
| 八敌种形象(L2 熊地精=bugbear 复用,不单列) | ✅ 已交付:B 区站桩八敌真图服役——八件源=原稿不降采样入包、显示按档缩放落位(三档绝对高 96/144/188,art-bible §8.2),闸件全绿;character_enemy_<键>.png 按常量入位,字形回退退役为缺位兜底;素材不入 git 本地在盘 | [art-bible](art-bible.md) §5 + [art-prompts](art-prompts.md) §3 |
|
| 八敌种形象(L2 熊地精=bugbear 复用,不单列) | ✅ 已交付:B 区站桩八敌真图服役——八件源=原稿不降采样入包、显示按档缩放落位(三档绝对高,art-bible §8.2),闸件全绿;character_enemy_<键>.png 按常量入位,字形回退退役为缺位兜底;素材不入 git 本地在盘 | [art-bible](art-bible.md) §5 + [art-prompts](art-prompts.md) §3 |
|
||||||
| 意图准备动画三档 | ◐ | [art-bible](art-bible.md) §4.6.4 |
|
| 意图准备动画三档 | ◐ | [art-bible](art-bible.md) §4.6.4 |
|
||||||
|
|
||||||
## P2 图标与格面(可与样张并行)
|
## P2 图标与格面(可与样张并行)
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
| 关卡节点图图标组 | ◐ | [art-assets-checklist](art-assets-checklist.md) §3.2(正式 UI 设计未成文) |
|
| 关卡节点图图标组 | ◐ | [art-assets-checklist](art-assets-checklist.md) §3.2(正式 UI 设计未成文) |
|
||||||
| 雷/封印印记/数字砖面全套 | ◐ 封印印记已换代(环+十字法阵,参数化绘制);雷与数字砖面仍待格子样张前置 | [art-bible](art-bible.md) §1.4/§3.2 |
|
| 雷/封印印记/数字砖面全套 | ◐ 封印印记已换代(环+十字法阵,参数化绘制);雷与数字砖面仍待格子样张前置 | [art-bible](art-bible.md) §1.4/§3.2 |
|
||||||
| 增益状态效果图标 9 枚 | ✅ 已接入 | [art-bible](art-bible.md) §4.6.1(候选原稿归 candidates 档——路径描述性引用,归档纪律见 art-bible §8.3) |
|
| 增益状态效果图标 9 枚 | ✅ 已接入 | [art-bible](art-bible.md) §4.6.1(候选原稿归 candidates 档——路径描述性引用,归档纪律见 art-bible §8.3) |
|
||||||
| 营地场景图 | ◐ | [art-bible](art-bible.md) §6.2 |
|
| 营地场景图 | ✅ 已交付:十层在包;背景层 2026-11-07 换代录入(远景 v5+地面 v3 过审、拼接量化 32 色落 `scene_camp_bg.png`);坐标接线归下游实现批(`camp_scene_layout.tres` 仍旧值) | [art-bible](art-bible.md) §6.2 |
|
||||||
| 字体(全局 UI 像素字,Fusion Pixel 单套单字重) | ✅ 已定稿在役(用户裁现状即终稿——不另接拉丁专件、不上第二字重) | [art-bible](art-bible.md) §7.4 |
|
| 字体(全局 UI 像素字,Fusion Pixel 单套单字重) | ✅ 已定稿在役(用户裁现状即终稿——不另接拉丁专件、不上第二字重) | [art-bible](art-bible.md) §7.4 |
|
||||||
|
|
||||||
## P3 演出类(样张后排期)
|
## P3 演出类(样张后排期)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
| `character/` | 角色棋盘帧 + B 区立绘 | character_hero_idle/walk(棋盘 32×32 朝左基准)、character_hero_portrait(B 区立绘 46×48)+ character_enemy_<键> 八敌 |
|
| `character/` | 角色棋盘帧 + B 区立绘 | character_hero_idle/walk(棋盘 32×32 朝左基准)、character_hero_portrait(B 区立绘 46×48)+ character_enemy_<键> 八敌 |
|
||||||
| `fx/` | 特效帧 | shovel_swing_f0/f1/f2(挥铲三帧,握把锚 (18,12)) |
|
| `fx/` | 特效帧 | shovel_swing_f0/f1/f2(挥铲三帧,握把锚 (18,12)) |
|
||||||
| `scene/` | **场景图**(背景层 + 地面层 + 围墙层 + 可点物件层;营地场景图首批) | 营地 10 张:`scene_camp_bg`(背景层,不透明全幅=天空+远山+地面+门洞小路)+ `scene_camp_wall`(围墙层,透明底、门洞留透明缺口)+ `scene_camp_gate / forge / chest / notebook / dummy / board / campfire`(七个可点物件)+ `scene_camp_tent`(承载件,不可点)+ `scene_stage_bg_dungeon` / `scene_stage_bg_underdark` / `scene_stage_bg_deep_underdark`(B 区战斗舞台背景层三关变体,✦ 插画级,顶部空区+远景天然洞壁,不画近景地面,按 board_type 选图)+ `scene_stage_ground`(B 区连续近景地面层,✦ 插画级,泥土/砂砾/碎石+顶缘分隔带,跨关恒定)+ `scene_stage_plaza`(B 区角色脚下小石台,48×12 九宫格件)——B 区战斗舞台背景与连续地面已入包;营地 10 张已入包(`scene_camp_*` 十件在役、`TEX_CAMP_*` 十键消费;用户游戏内终审如有置换,按本行键名同径替换) |
|
| `scene/` | **场景图**(背景层 + 地面层 + 围墙层 + 可点物件层;营地场景图首批) | 营地 10 张:`scene_camp_bg`(背景层,不透明全幅=天空+远山+地面+门洞小路)+ `scene_camp_wall`(围墙层,透明底、门洞留透明缺口)+ `scene_camp_gate / forge / chest / notebook / dummy / board / campfire`(七个可点物件)+ `scene_camp_tent`(承载件,不可点)+ `scene_stage_bg_dungeon` / `scene_stage_bg_underdark` / `scene_stage_bg_deep_underdark`(B 区战斗舞台背景层三关变体,✦ 插画级,顶部空区+远景天然洞壁,不画近景地面,按 board_type 选图)+ `scene_stage_ground`(B 区连续近景地面层,✦ 插画级,泥土/砂砾/碎石+顶缘分隔带,跨关恒定)+ `scene_stage_plaza`(B 区角色脚下小石台,48×12 九宫格件)——B 区战斗舞台背景与连续地面已入包;营地 10 张已入包(`scene_camp_*` 十件在役、`TEX_CAMP_*` 十键消费;用户游戏内终审如有置换,按本行键名同径替换) |
|
||||||
| `board/` | 砖面(三关换皮);seal_mark.png 现役用途=战末金蜡封徽记专用(战末弹层消费——棋盘侧贴图绘制路径已退役) | terrain_floor_<board_type>_<n>.png(三关地面系)、seal_mark.png(战末蜡封专用) |
|
| `board/` | 棋盘地形材质(2026-11-07 重做后改程序化绘制,无入包地形 PNG);seal_mark.png 现役用途=战末金蜡封徽记专用(战末弹层消费——棋盘侧贴图绘制路径已退役) | seal_mark.png(战末蜡封专用);旧 `terrain_*` 63 件(16 墙瓦片+5 地面变体×三关)随重做退役删除 |
|
||||||
|
|
||||||
## 4. 坐标/朝向等工程侧约定备查
|
## 4. 坐标/朝向等工程侧约定备查
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
# 营地场景 · 分层生图提示词卡 v1.5
|
# 营地场景 · 分层生图提示词卡 v1.10
|
||||||
|
|
||||||
> **性质**:营地场景图(1280×800,一张可点击场景图 + 十张分层:背景层 1 + 围墙层 1 + 八个物件层)的出图执行侧文件。**场景级资产,与角色级 [art-prompts](art-prompts.md) 并列,两文件互不覆盖**。
|
> **性质**:营地场景图(1280×800,一张可点击场景图 + 十张分层:背景层 1 + 围墙层 1 + 八个物件层)的出图执行侧文件。**场景级资产,与角色级 [art-prompts](art-prompts.md) 并列,两文件互不覆盖**。
|
||||||
> **依据**:色彩与氛围 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`(本卡不复述色值);坐标与层序 = `artwork/2026-10-23-营地场景/布局草案-1280x800.html`;物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。冲突时色彩以色彩脚本为准,画法以 art-bible 为准。
|
> **依据**:色彩与氛围 = [art-bible](art-bible.md) §2.8 与 §6.2(营地的暖由晒白的地面、木色与烛光件承载;远景走正午强日照、天空淡晴蓝,与冒险中的地下城形成对比;本卡不复述色值);坐标与层序 = 本卡 §2.3(运行期单一事实源 = `game/data/tables/camp_scene_layout.tres`);物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。画法与用色冲突时以 art-bible 为准。
|
||||||
> **边界**:只管营地场景图的分层出图。角色、图标、格面走 art-prompts.md 与脚本管线,不需要提示词。
|
> **边界**:只管营地场景图的分层出图。角色、图标、格面走 art-prompts.md 与脚本管线,不需要提示词。
|
||||||
> **建立**:2026-10-25 · 状态:十条提示词成文(背景层 1 + 围墙层 1 + 八个物件层),出图通道由作者自定
|
> **建立**:2026-10-25 · 状态:十条提示词成文(背景层 1 + 围墙层 1 + 八个物件层);背景层两片与围墙层待按 §4 新判据重出,门扇随门洞压扁重画
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
3. **后处理**:脚本管线代跑——去底转透明、降采样到终稿尺寸(整数倍)、色板量化、四联底测试条。**背景层不去底(全幅不透明)**;围墙层与八个物件层去底转透明。后处理工具清单与用法见 [art-pipeline-tools](art-pipeline-tools.md)。
|
3. **后处理**:脚本管线代跑——去底转透明、降采样到终稿尺寸(整数倍)、色板量化、四联底测试条。**背景层不去底(全幅不透明)**;围墙层与八个物件层去底转透明。后处理工具清单与用法见 [art-pipeline-tools](art-pipeline-tools.md)。
|
||||||
4. **转正**:终稿转入切片资产目录,按坐标表接线。
|
4. **转正**:终稿转入切片资产目录,按坐标表接线。
|
||||||
|
|
||||||
**出图顺序(先锁后产,不能跳)**:概念脚本 → **本卡提示词** → 贴风格参考图**先出背景层 `scene_camp_bg` 1 张** → 作者确认风格前缀 → 才扩产围墙层 `scene_camp_wall` 与八个物件层(共 9 张)。
|
**出图顺序(先锁后产,不能跳)**:概念脚本 → **本卡提示词** → 贴风格参考图**先出远景片 `bg_far` 1 张** → 作者确认风格前缀 → 才出地面片 `bg_floor`、围墙层与八个物件层。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
贴参考图时,在提示词末尾接这一句:
|
贴参考图时,在提示词末尾接这一句:
|
||||||
|
|
||||||
```
|
```
|
||||||
Style reference: the attached images are this game's own finished pixel art and its camp scene reference — match only their rendering style, the same pixel density, flat shading, thin warm cream outline and warm limited palette. They are style references only: do not copy their character, gear or props, and do not put any character into the scene.
|
Style reference: the attached images are this game's own finished pixel art and its camp scene reference — match only their rendering style, the same pixel density, flat shading, thin warm cream outline and the same limited palette discipline. They are style references only: do not copy their character, gear or props, and do not put any character into the scene.
|
||||||
```
|
```
|
||||||
|
|
||||||
> **描边取奶油色**,不取参照物的深灰褐:去底脚本走"奶油描边膨胀 3px 当屏障"吞底色,深褐描边会让该步失效。这条是技术前提,不是美术取向;若改深褐,需另换去底方案。
|
> **描边取奶油色**,不取参照物的深灰褐:去底脚本走"奶油描边膨胀 3px 当屏障"吞底色,深褐描边会让该步失效。这条是技术前提,不是美术取向;若改深褐,需另换去底方案。
|
||||||
@@ -39,26 +39,62 @@ Style reference: the attached images are this game's own finished pixel art and
|
|||||||
|
|
||||||
## 2. 背景层与围墙层(两张,不可点)
|
## 2. 背景层与围墙层(两张,不可点)
|
||||||
|
|
||||||
围墙从背景层拆出、独立成层:围墙层可单独锁死桩高、门洞做成透明缺口透出背景层的小路;背景层不混入暖木色、更易守住冷色占比判据(判据见 §4)。两层都不可点;按乙工序门**先只出背景层 1 张**供作者确认风格前缀,确认后才扩产围墙层与八个物件层。
|
围墙从背景层拆出、独立成层:围墙层可单独锁死桩高、门洞做成透明缺口透出背景层的小路;背景层只画天、山、草地与地面,不画任何物件——远景走正午强日照(淡晴蓝天空、一整片连续的淡蓝灰远山、晒白的草地与土路),整体淡而退后,让近景的暖调木色与烛光件成为画面主角。两层都不可点;按乙工序门**先只出背景层 1 张**供作者确认风格前缀,确认后才扩产围墙层与八个物件层。
|
||||||
|
|
||||||
### 2.1 背景层(`scene_camp_bg`,不可点,不透明全幅)
|
### 2.1 背景层(`scene_camp_bg`,不可点,不透明全幅)
|
||||||
|
|
||||||
**出图画布**:2560×1600(终稿 1280×800 的 2 倍,保证整数倍降采样)
|
**产出方式**:分两片出图,后处理按 y734 拼成一张 2560×1600。接缝整条落在围墙层(406–734)背后,画面里看不见。
|
||||||
**画什么**:天空、远山、整片地面、门洞位置一条通向远处的小路
|
|
||||||
**不画什么**:木围墙、门柱、门扇、七个物件、角色、接地阴影——围墙与门柱是 §2.2 的独立层,门洞是它的透明缺口;小路在本层画好、透出来即可
|
| 片 | 出图画布 | 终稿落位 | 内容 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 远景片 `bg_far` | 2560×734(3.5:1 超宽) | (0, 0, 1280, 367) | 天空+远山+草地+小路 |
|
||||||
|
| 地面片 `bg_floor` | 2560×866(3:1 超宽) | (0, 367, 1280, 433) | 营地内踩实裸土 |
|
||||||
|
|
||||||
|
**为什么分两片**:整张一次出图时,模型按「构图好看」分配天地比例,山被挤到画面下半部——三张实测里两张的山体整段落在围墙后面(山体上缘 y280/y227,墙顶 217),远山等于消失。拆开后远景片的全部高度都归天空+山+草地,山才可能长到围墙之上。
|
||||||
|
|
||||||
|
#### 2.1.1 远景片(`bg_far`)
|
||||||
|
|
||||||
|
**画布比例**:3.5:1 超宽。通道支持直接出 2560×734;不支持则按 3:2 出图后纵向压到 3.5:1,构图比例不变
|
||||||
|
**光照口径**:正午强日照晴天。太阳不入画,猛烈感从三处读出——天空清透的淡蓝、云烧得白、地面晒到泛白。
|
||||||
|
**分带(按画面高度)**:
|
||||||
|
- 天空 0–14%=淡晴蓝(高明度、低饱和的清蓝,不是深饱和的正午蓝),至多两朵烧白扁平简笔云
|
||||||
|
- 远山 14–55%(**山体占 41%,硬指标**)=一整片连续的淡蓝灰山体,轮廓自然起伏;**禁一层叠一层的轮廓带与阴影台阶**
|
||||||
|
- 草地 55–100%=晒白的浅黄绿
|
||||||
|
- 小路在草地内:从底边向上收窄,到山脚为止,**不越过山脚、不上探到天空**;路面晒白成暖米白
|
||||||
|
**画什么**:淡晴蓝天空、一整片连续的淡蓝灰远山、晒白草地、草地中央一条暖米白土路
|
||||||
|
**不画什么**:围墙、门柱、门扇、物件、角色、营地内地面(那是 §2.1.2);太阳本体、太阳光晕、奶白或暖黄底色的天空、深饱和的蓝天;一层叠一层的山体轮廓带、平行山脊条带、台阶式横条阴影;山与草地之间禁出现平直硬边
|
||||||
|
|
||||||
```
|
```
|
||||||
Pixel art style. True pixel art game background layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the FAR BACKGROUND LAYER ONLY of a small adventurer camp: sky, distant hills and the whole ground. It must contain no palisade wall, no gate posts, no camp objects, no gate leaves, no characters and no drop shadows, because all of those are drawn as separate transparent layers on top of this one. COLOR SCRIPT — cool recedes, warm advances: the sky, the hills and the ground are all COOL, pale, desaturated and low in contrast; there is no warm accent anywhere in this layer, warm color belongs only to the separate object layers drawn on top. ATMOSPHERIC DEPTH: every plane that is farther away is lighter, closer to the value of the sky, cooler, lower in contrast and simpler in detail, while the nearest plane is the darkest and highest in contrast. SKY (top of frame): the lightest thing in the picture, flat pale cool off-white with a faint blue-grey tint, no yellow or cream tone, no sun anywhere; the very top strip of the frame, about one sixteenth of the frame height, stays completely calm and empty, reserved as clear space with nothing in it; at most one or two extremely simple flat low-contrast clouds. FAR DISTANCE: two or three layers of low rolling hill silhouettes in pale cool blue-grey, each farther layer lighter, cooler and lower in contrast than the one in front, fading towards the value of the sky, no trees, no individual foliage. HILLS TO GROUND: the hills fade gradually and smoothly down into the ground, with NO visible horizon line and NO distant ground band — the transition must not read as a separate horizontal stripe of a different color. GATE PATH: in the middle of the frame, between x=1040 and x=1520, one clearly visible dirt path runs from the ground at two thirds of the frame height measured from the bottom edge away into the distance between the hills, narrowing as it recedes, painted in a muted desaturated grey-brown earth tone, never golden or warm yellow; this path shows through the empty gate opening of the wall layer above. FOREGROUND GROUND: the darkest area of the picture, dry packed bare earth in a neutral desaturated grey-brown, never golden, amber or warm yellow, hard flat color blocks, hard edges, no gradient, no grass, no grass tufts, no weeds and no plants of any kind. The foreground ground is completely empty apart from the dirt path: no objects, no icons, no badges, no markers, no decorations of any kind. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows, contact shadows or any shadow band; blur or compression artifacts; a vignette, dark corners, or any mood darkening; night, dusk, moon, stars, sunset or sunrise light; a sun or any light source drawn in the sky; a visible horizon line, a separate horizontal distant ground band or any distant grass strip below the hills; trees, forests or foliage in the distance; grass, grass tufts, weeds or plants in the foreground; a palisade wall, wooden fence, fence posts, gate posts or any wall structure; any warm, golden, amber or yellow cast on the sky, on the hills or on the ground; any camp object, furniture, crate, barrel, fire, tent or tool; any gate leaf, door panel or hinge; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element; any icon, badge, item tile, emblem, sign, marker or symbol anywhere in the frame; any characters, people, creatures or animals.
|
Pixel art style. True pixel art game background, chunky square pixels, strict pixel grid, hard edges, no anti-aliasing, flat colors, limited palette about 20 colors, retro 16-bit look, Aseprite style, flat side view, orthographic, ULTRA WIDE horizontal composition, aspect ratio 3.5 to 1. This is the far view seen from inside a small adventurer camp, looking out, at high noon on a clear hot day. It contains ONLY three bands stacked top to bottom, plus one path. The sun itself never enters the frame; its strength must be read from the surfaces instead — bleached ground, burned white clouds, a pale clear blue sky. BAND 1 — SKY, from the top edge down to 14 percent of the frame height: a pale light clear blue, high value and low saturation, like a washed-out summer sky, never a deep or vivid blue; flat and empty, no gradient; at most two extremely simple flat clouds in clean bright white with a pale grey underside, so they read as burned white by the sun; no sun, no sun glow, no warm or cream tint anywhere in the sky. BAND 2 — DISTANT HILLS, from 14 percent down to 55 percent of the frame height: ONE single continuous mass of rolling hills in pale blue-grey, not a stack of separate ridges. The skyline rises and falls naturally with a few broad soft summits; the whole mass reads as one flat pale blue-grey tone, with at most one or two very gentle lighter planes to suggest volume. DO NOT draw layered silhouette bands, stacked parallel ridges, terrace-like steps, or repeated shadow stripes running across the hills. THE HILLS MUST FILL THIS ENTIRE BAND — the highest ridgeline reaches up to 14 to 20 percent of the frame height and the hill mass continues down to 55 percent; a low ridge hugging the bottom of the frame is WRONG. Silhouette edges are stepped in pixel blocks, no outline, no rim light. BAND 3 — MEADOW, from 55 percent down to the bottom edge: sun-bleached pale yellow-green grass, flat and low contrast, marked only by a few simple flat grass tufts, no trees, no bushes. PATH — one dirt path in the meadow only, sun-bleached warm off-white tan: it starts at the bottom edge of the frame in the middle, about one fifth of the frame width there, runs straight up and narrows until it meets the hill foot at 55 percent, where it disappears; it must not go above the hill foot and must not reach the sky. COLOR: a high-noon clear-daylight palette — pale clear blue sky, burned white clouds, one continuous pale blue-grey hill mass, sun-bleached pale yellow-green meadow, warm off-white dirt path. THE WHOLE FAR VIEW STAYS PALE AND LOW IN CONTRAST; the sky is the bluest area but it is a light washed-out blue, never deep or vivid, and everything below the skyline stays pale and dry. LIGHT: harsh dry daylight straight from above, no visible sun, no long shadows, no warm or sunset cast; the far view reads as a safe open place under a strong sun. DO NOT ADD: any palisade wall, fence, gate, gate posts, tent, campfire, crate, barrel, prop, character, animal; any hard straight horizontal seam between sky, hills and meadow — the hill foot dissolves into the meadow through stepped intermediate tones; any outline or rim; trees, forests or dense vegetation; a visible sun disc, sun glow, lens flare, god rays, a warm cream or yellow tinted sky, a deep saturated blue sky, sunset, golden hour, overcast grey sky; stacked layered hill silhouettes, parallel ridge bands, terrace steps or repeated shadow stripes across the hills; antialiasing, gradients, dithering, painterly strokes, 3D, realistic shading, glossy light, bloom, vignette, night; any text, letters, number, watermark, signature, logo, frame, border, UI element, icon, badge.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 2.1.2 地面片(`bg_floor`)
|
||||||
|
|
||||||
|
**画布比例**:3:1 超宽
|
||||||
|
**内容**:营地内被正午太阳晒到泛白的踩实米黄土地,铺满整幅
|
||||||
|
**硬指标**:**中线与左右两侧同色——没有任何路、小径、车辙**;明度与饱和读到正午下晒到发白的干土——高明度、低饱和,不暗、不闷,也不许发黄发焦糖;色相与远景片草地明显区分;细节由大像素块构成,块尺寸与远景片同一档,禁 1–2px 碎点噪声
|
||||||
|
**不画什么**:草、植被、大石块、物件、天空、地平线、围墙、接缝线;迷彩式闭合斑块与满屏碎点
|
||||||
|
|
||||||
|
```
|
||||||
|
Pixel art style. True pixel art game ground texture, chunky square pixels, strict pixel grid, hard edges, no anti-aliasing, flat colors, limited palette about 12 colors, retro 16-bit look, Aseprite style, ULTRA WIDE horizontal composition, aspect ratio 3 to 1. This is the trodden floor INSIDE a small adventurer camp at high noon — bare packed dry earth filling the whole frame edge to edge, seen at a shallow angle from slightly above. The sun is strong and directly overhead, so the ground reads bleached rather than richly coloured. PIXEL SCALE: the whole frame is built from large square pixel blocks, each block about one two-hundredth of the frame width; every mark is one such block or a small group of them, never 1 or 2 pixel speckle. MATERIAL: sun-bleached dry pale beige-tan earth (trodden loess washed out by the midday sun), a light warm bone-to-straw colour, high value, low saturation, dry and never muddy, never grey, never saturated ochre, caramel or mustard. LIGHT: harsh dry daylight straight from above; broad flat sunlit areas dominate, with only gentle tonal steps between them; no long shadows, no vignette. TEXTURE: deliberate large pixel clusters only — short paired scuff marks that read as dragged footprints, small scattered pebbles, beaten patches where feet have worn the ground smooth, occasional faint drag marks; density rises slightly toward the bottom edge and the middle stays calm and open. PATCH SHAPE: the tonal patches are broad, few and flat, their edges stepped in whole pixel blocks; do not create irregular closed blotches, camouflage patches, speckle noise or dithered dot clusters, and keep the ground reading as one continuous packed soil surface. CRITICAL, NO PATH: there is no road, no trail, no track, no wheel rut and no worn strip anywhere in this image — the middle of the frame must look the same as the left and right edges, nothing leads anywhere. DO NOT ADD: grass, vegetation, plants, flowers, moss, lichen; rocks larger than a pebble; crates, sticks, bones, debris piles, tools; water, puddles; shadows of objects; sky, horizon, hills, wall, fence, gate, building; any line, seam, border or edge inside the frame; saturated mustard, caramel or golden colouring; antialiasing, gradients, dithering, painterly strokes, 3D, realistic shading, glossy light, bloom, vignette; any text, letters, number, watermark, signature, logo, frame, border, UI element, icon, badge.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1.3 拼接与后处理
|
||||||
|
|
||||||
|
1. 两片各缩放到终稿尺寸:远景片 1280×367、地面片 1280×433
|
||||||
|
2. 按 y367 上下拼接成 1280×800
|
||||||
|
3. 量化到背景层自板(≤32 色;营地屏双板制、屏并集 ≤64,见 art-bible §4.1 营地行)
|
||||||
|
4. 需要 2× 档时整数倍放大到 2560×1600
|
||||||
|
5. 接缝不做过渡处理——它整条落在围墙(220–420)背后
|
||||||
|
|
||||||
### 2.2 围墙层(`scene_camp_wall`,不可点,透明底)
|
### 2.2 围墙层(`scene_camp_wall`,不可点,透明底)
|
||||||
|
|
||||||
**出图画布**:2560×1600(与背景层同画布,门洞 x 坐标直接对齐);墙横贯画在出图 y480–620 这条**窄带**内,其余为纯色底 `#F2F2F2`。落盘由 S4 后处理裁成终稿外接矩形 `(0, 240, 1280, 70)` / 出图 `(0, 480, 2560, 140)` 的细条,**不做全幅 1280×800 落盘**(全幅约 3.9 MB 显存,细条约 0.35 MB)。
|
**出图画布**:2560×1600(与背景层同画布,门洞 x 坐标直接对齐);墙横贯画在出图 y406–734 这条带内(桩身 y434–734,门柱 y406–734),其余为纯色底 `#F2F2F2`。落盘由 S4 后处理裁成素材细条 `1280×164`(出图 `(0, 406, 2560, 328)`),**不做全幅 1280×800 落盘**(全幅约 3.9 MB 显存,细条约 0.35 MB);**显示矩形 `(0, 220, 1280, 200)`(2026-11-07 裁,运行时按 200 高拉伸)**。
|
||||||
**画什么**:横贯全宽的密排竖木桩墙(左右两段)+ 两根略高的门柱,门洞处完全透明
|
**画什么**:横贯全宽的密排竖木桩墙(左右两段,桩身终稿 150 高)+ 两根略高的门柱(终稿 164 高),门洞处完全透明
|
||||||
**不画什么**:天空、远山、地面、小路、门扇、七个物件、角色;门洞内不画任何东西,透出背景层的小路
|
**不画什么**:天空、远山、地面、小路、门扇、七个物件、角色;门洞内不画任何东西,透出背景层的小路
|
||||||
|
|
||||||
```
|
```
|
||||||
Pixel art style. True pixel art game layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the PALISADE WALL LAYER ONLY of a small adventurer camp, drawn on a plain flat uniform light grey #F2F2F2 background for easy keying. A wooden palisade wall runs straight across the full width of the frame, seen from the front, built from closely spaced vertical logs standing side by side with no gaps between them, every log cut to a sharp point at the top, a solid barrier with no horizontal rails, no see-through gaps, no ranch-style post-and-rail fence. The wall is SHORT and LOW: including the pointed tips the whole band occupies only about one eighteenth of the total frame height, a thin horizontal strip, NOT a tall barrier; the logs stand only about one eighteenth of the total frame height above their base line. In the middle of the wall one wide gap holds two thick gate posts slightly taller than the wall, and the entire opening between them is completely EMPTY — plain flat uniform light grey #F2F2F2 showing through, no logs, no path, no ground, no scenery inside the opening, because the dirt path and the hills belong to the background layer below and the gate leaves are a separate object layer. The wall is painted in a muted greyed wood brown, with a thin warm cream outline around the whole silhouette, flat shading. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows or contact shadows; blur or compression artifacts; a vignette or dark corners; any sky, hills, ground, grass, dirt path or scenery of any kind; any gate leaf, door panel or hinge; any camp object, furniture, crate, barrel, fire, tent or tool; any characters, people, creatures or animals; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element.
|
Pixel art style. True pixel art game layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the PALISADE WALL LAYER ONLY of a small adventurer camp, drawn on a plain flat uniform light grey #F2F2F2 background for easy keying. A wooden palisade wall runs straight across the full width of the frame, seen from the front, built from closely spaced vertical logs standing side by side with no gaps between them, every log cut to a sharp point at the top, a solid barrier with no horizontal rails, no see-through gaps, no ranch-style post-and-rail fence. The wall stands on the ground line at y=734 of 1600. The LOG BODIES, pointed tips included, rise 300 pixels above that base line — about nineteen percent of the total frame height — so it reads as a real barrier with presence, clearly taller than the gate opening cut into it, not a thin decorative strip. In the middle of the wall one wide gap holds two thick gate posts standing 28 pixels taller than the logs, and the entire opening between them is completely EMPTY — plain flat uniform light grey #F2F2F2 showing through, spanning x=1040 to x=1520 and rising from the base line y=734 up to y=566, no logs, no path, no ground, no scenery inside the opening, because the dirt path and the hills belong to the background layer below and the gate leaves are a separate object layer. The wall is painted in a muted greyed wood brown, with a thin warm cream outline around the whole silhouette, flat shading. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows or contact shadows; blur or compression artifacts; a vignette or dark corners; any sky, hills, ground, grass, dirt path or scenery of any kind; any gate leaf, door panel or hinge; any camp object, furniture, crate, barrel, fire, tent or tool; any characters, people, creatures or animals; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element.
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.3 出图画布上的坐标(终稿 ×2)
|
### 2.3 出图画布上的坐标(终稿 ×2)
|
||||||
@@ -66,11 +102,17 @@ Pixel art style. True pixel art game layer drawn with chunky square pixels, stri
|
|||||||
| 元素 | 终稿 1280×800 | 出图画布 2560×1600 |
|
| 元素 | 终稿 1280×800 | 出图画布 2560×1600 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 顶栏 HUD 保留带 | y ≤ 48 | **y ≤ 96**(保持空旷) |
|
| 顶栏 HUD 保留带 | y ≤ 48 | **y ≤ 96**(保持空旷) |
|
||||||
| 背景层 `scene_camp_bg` | 全幅 1280×800 | 全幅 2560×1600 |
|
| 远景片 `bg_far` | y 0–367(高 367) | y 0–734(高 734,3.5:1) |
|
||||||
| 围墙带(wall 层桩身) | y 267–310(**高 43px**) | y 534–620(**高 86px**) |
|
| 地面片 `bg_floor` | y 367–800(高 433) | y 734–1600(高 866,3:1) |
|
||||||
| 门柱(wall 层,略高) | y 240–310;x 500–520 / 760–780 | y 480–620;x 1000–1040 / 1520–1560 |
|
| 两片接缝 | **y 367**(落在围墙 220–420 背后) | **y 734**(落在围墙 406–734 背后) |
|
||||||
| 门洞(wall 层透明缺口) | x 520–760 | x 1040–1520 |
|
| 地平线(山脚/草地起点) | y 与两片接缝重合,墙背后不可见 | 同左 |
|
||||||
| 门洞内小路(画在 bg 层) | x 520–760,自 y310 向上收窄至远山 | x 1040–1520,自 y620 向上收窄至远山 |
|
| 远山带 | y 51–202(画面 14%–55%,山体 41%) | y 103–403 |
|
||||||
|
| 草地带 | y 202–367 | y 403–734 |
|
||||||
|
| 围墙层外接矩形 | y 220–420(高 200,2026-11-07 裁) | y 406–734(高 328,素材画布不变) |
|
||||||
|
| 围墙带(wall 层桩身) | 素材桩身 150 按 200/164 显示拉伸(显示约高 183) | y 434–734(**高 300px**) |
|
||||||
|
| 门柱(wall 层,略高) | 显示 y 220–420(高 200);x 500–520 / 760–780 | y 406–734;x 1000–1040 / 1520–1560 |
|
||||||
|
| 门洞(wall 层透明缺口) | 墙件缺口全高 y 220–420;门扇可见 y 282–420(高 138);x 520–760 | y 566–734(高 168);x 1040–1520 |
|
||||||
|
| 门洞内小路(画在远景片草地内) | x 520–760 穿门洞,自接缝 y367 向上收窄,到山脚 y202 消失 | x 1040–1520,自 y734 向上收窄,到 y403 消失 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -97,7 +139,7 @@ Do not add any of the following: realistic, photorealistic or 3D rendering; pain
|
|||||||
| 件 | z 序 | 终稿矩形 | 出图画布 | 正文 |
|
| 件 | z 序 | 终稿矩形 | 出图画布 | 正文 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| 布告板 | 2 | 130×140 | 260×280 | §3.1 |
|
| 布告板 | 2 | 130×140 | 260×280 | §3.1 |
|
||||||
| 门扇 | 3 | 240×220 | 480×440 | §3.2 |
|
| 门扇 | 3 | 240×147 | 480×294 | §3.2 |
|
||||||
| 木桩 | 4 | 120×180 | 240×360 | §3.3 |
|
| 木桩 | 4 | 120×180 | 240×360 | §3.3 |
|
||||||
| 锻炉·铁砧 | 4 | 240×240 | 480×480 | §3.4 |
|
| 锻炉·铁砧 | 4 | 240×240 | 480×480 | §3.4 |
|
||||||
| 帐篷 | 4(不可点) | 300×170 | 600×340 | §3.5 |
|
| 帐篷 | 4(不可点) | 300×170 | 600×340 | §3.5 |
|
||||||
@@ -105,7 +147,7 @@ Do not add any of the following: realistic, photorealistic or 3D rendering; pain
|
|||||||
| 笔记本 | 5 | 100×80 | 200×160 | §3.7 |
|
| 笔记本 | 5 | 100×80 | 200×160 | §3.7 |
|
||||||
| 篝火 | 6 | 160×160 | 320×320 | §3.8 |
|
| 篝火 | 6 | 160×160 | 320×320 | §3.8 |
|
||||||
|
|
||||||
**落位实测(锁定矩形 contain)**:布告板 130×121/门扇 240×211/木桩 120×180/锻炉 240×193/帐篷 251×170/宝箱 106×90/笔记本 100×66/篝火 160×149——贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙);命中矩形按锁定值。换算式登记(源 2× 档→落位尺寸)存 artwork 工作区。
|
**落位尺寸(2026-11-05 用户裁地平线 y367 重排后)**:布告板 130×121/门扇 240×138/木桩 120×180/锻炉 240×193/帐篷 251×170/宝箱 106×90/笔记本 100×66/篝火 160×149——贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙);命中矩形按锁定值。八件只改落位,门扇另随门洞压扁重画(原 240×211 → 240×138),其余七件沿用现有终稿。**2026-11-07 追加**:布告板 `(845, 241)`、门扇 `(520, 282)`、围墙显示矩形与墙脚入土见 §5 第 12 条。
|
||||||
|
|
||||||
**3.1 布告板(→ 图鉴)**
|
**3.1 布告板(→ 图鉴)**
|
||||||
```
|
```
|
||||||
@@ -114,7 +156,7 @@ A wooden notice board hung on a wall, with two or three blank pinned papers, no
|
|||||||
|
|
||||||
**3.2 门扇(→ 冒险)**
|
**3.2 门扇(→ 冒险)**
|
||||||
```
|
```
|
||||||
Two wooden gate leaves hanging from their hinges, half open and tilted outward, each made of thick planks with a cross brace and dark iron fittings, seen from the front, the pair shown together as one single object; wood brown #8A5A34 planks, dark iron fittings.
|
Two wooden gate leaves hanging from their hinges, half open and tilted outward, each made of thick planks with a cross brace and dark iron fittings, seen from the front, the pair shown together as one single object; the pair together fills a WIDE LOW rectangle about 240 wide by 138 tall, so the leaves read as broad rather than tall, each leaf roughly twice as wide as it is high; wood brown #8A5A34 planks, dark iron fittings.
|
||||||
```
|
```
|
||||||
|
|
||||||
**3.3 木桩(→ 天赋树)**
|
**3.3 木桩(→ 天赋树)**
|
||||||
@@ -151,17 +193,34 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm
|
|||||||
|
|
||||||
## 4. 验收(机检 + 目检)
|
## 4. 验收(机检 + 目检)
|
||||||
|
|
||||||
**背景层 `scene_camp_bg`**
|
**远景片 `bg_far`**
|
||||||
- 黄度 =(R+G)/2−B 分区取样:天空 ≤20、远山 ≤20、地面 ≤35
|
- 整体读作正午强日照晴天、安全开阔,与冒险中的地下城形成对比;色温与色值判据按 §5 第 11 条随环境子板登记回填
|
||||||
- 冷色像素占比 ≥55%;本层不应出现任何暖色高饱和像素
|
- 远景片整幅保持中低饱和、低对比,高饱和只留给近景的火焰与烛光件;远景淡而退后、近景暖调木色与烛光件为主,禁出现整屏高饱和偏色
|
||||||
- 目检:顶部约 1/16 完全空旷;**无地平线、无远景地面带**(远山自然渐隐过渡到地面);不含围墙、门柱、门扇、物件、角色
|
- 机检:**山体上缘 ≤ 画面高度 15%**(这是硬指标——山体上缘落得越低,被围墙挡住后越是什么都看不见)
|
||||||
- 目检/机检:门洞 x1040–1520 处**有一条清晰可辨、向远处收窄的土路**(非纯色块),透出「出去即冒险」
|
- 机检:**山体占画面高度 ≥40%**(山体上缘到山脚)
|
||||||
- 机检/目检:全幅**无任何独立物件/图标/徽章/标记**(前景地面除小路外全空);参考做法=中下方块区独立色数应≈邻区
|
- 机检:草地上限 ≤ 画面高度 55%
|
||||||
|
- 机检:山脚与草地交界处,上下各 8px 窄带的行均色差 ≤6/255(禁平直硬边;旧稿 y321 处约 37/255)
|
||||||
|
- 目检:顶部天空=淡晴蓝(清透、高明度、低饱和),无太阳本体、无太阳光晕、无奶白或暖黄底色、无深饱和正午蓝;云为烧白扁平简笔且不超过两朵
|
||||||
|
- 目检:远山读作一整片连续的淡蓝灰山体,轮廓自然起伏,禁一层叠一层的轮廓带与阴影台阶;草地与土路读作晒白(浅黄绿/暖米白),不落深橄榄绿
|
||||||
|
- 目检:小路只在草地内,从底边向上收窄到山脚为止,**不越过山脚、不上探到天空**
|
||||||
|
- 目检:无围墙、门柱、门扇、物件、角色
|
||||||
|
|
||||||
|
**地面片 `bg_floor`**
|
||||||
|
- 明度与饱和读到正午太阳下晒到泛白的干土——高明度、低饱和,不暗、不闷、不发焦糖黄;硬阈值随环境子板登记回填(§5 第 11 条)
|
||||||
|
- 机检:画面中线 200px 带与左右各 250px 带的平均色差 ≤6/255(**营地内无路带**)
|
||||||
|
- 机检:与远景片草地的平均色 (R−B) 差 ≥10/255(两种材质色相可辨)
|
||||||
|
- 目检:能读出正午太阳下晒到泛白的干土与大块柔和日照面;禁出现草、植被、大石块、物件、水面
|
||||||
|
- 目检:细节由大像素块构成、块尺寸与远景片同一档,读作拖拽脚印/碎石/踩踏斑块;禁 1–2px 碎点噪声、禁迷彩式闭合斑块
|
||||||
|
|
||||||
|
**整图(两片拼接后)**
|
||||||
|
- 接缝 y367 落在围墙 220–420 背后,**画面里看不见接缝**
|
||||||
|
- 单张 ≤32 色(量化后)
|
||||||
|
- 全幅无任何独立物件/图标/徽章/标记
|
||||||
|
|
||||||
**围墙层 `scene_camp_wall`**
|
**围墙层 `scene_camp_wall`**
|
||||||
- 透明底 `#F2F2F2` 可去底、奶油描边闭合
|
- 透明底 `#F2F2F2` 可去底、奶油描边闭合
|
||||||
- **桩身高度 = 出图 y534–620(终稿 43px);门柱略高 y480–620。桩身超出围墙带下沿 y620 达 5px 以上即判红**
|
- **桩身 = 出图 y434–734(终稿 150px);门柱 y406–734(终稿 164px);外接矩形 (0,406,2560,328)。桩身超出下沿 y734 达 5px 以上即判红**
|
||||||
- 目检:密排竖木桩、桩顶削尖、不透缝、无横木;门洞 x1040–1520 **完全透明**(透出 bg 小路)、无门扇
|
- 目检:密排竖木桩、桩顶削尖、不透缝、无横木;门洞 y566–734 / x1040–1520 **完全透明**(透出 bg 小路)、无门扇;桩身高度须明显大于门洞高度
|
||||||
- 单张色数 ≤32(量化后)、缩放为整数倍无拉伸痕迹
|
- 单张色数 ≤32(量化后)、缩放为整数倍无拉伸痕迹
|
||||||
|
|
||||||
> **量化与缩放实况注记**:围墙层与八件已按营地主色板 **32 色重量化回写**(art-bible §4.1 子板行——违例对 0);落位缩放实况=源 2× 档经后处理换算为锁定矩形 contain(×0.1934–0.4404 非整数倍),「整数倍无拉伸痕迹」判据的机检面以落位实测尺寸与目检兜底执行。
|
> **量化与缩放实况注记**:围墙层与八件已按营地主色板 **32 色重量化回写**(art-bible §4.1 子板行——违例对 0);落位缩放实况=源 2× 档经后处理换算为锁定矩形 contain(×0.1934–0.4404 非整数倍),「整数倍无拉伸痕迹」判据的机检面以落位实测尺寸与目检兜底执行。
|
||||||
@@ -175,10 +234,18 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. 已裁(2026-11-01 用户裁;不再阻塞坐标表与定稿)
|
## 5. 已裁(2026-11-05 用户裁;不再阻塞坐标表与定稿)
|
||||||
|
|
||||||
1. **帐篷尺寸**:300×170 追认现值(各素材第一张样本稿已过审为终稿;重定即按比例重出、不裁)
|
1. **地平线与整体分带**:地平线定在终稿 y367(出图 y734);地面 433px、可见远景 217px(27%);围墙、门、布告板随之上调
|
||||||
2. **门扇高宽**:240×220 追认现值,坐标按门洞 x520–760 对齐(§2.3);围墙带桩身高 43px、门扇叠在门洞上的叠放关系随此锁定
|
2. **围墙高度**:桩身 150(出图 300)、门柱 164(出图 328)、门洞 84(出图 168);墙高须大于门洞高
|
||||||
3. **布告板位置**:采纳建议值 `(845, 268, 130, 140)` 挂回围墙带;终值随坐标表(`camp_scene_layout.tres`)落盘
|
3. **门扇尺寸**:显示矩形 240×147(贴图可见高 138),门扇件沿用现 240×211 由运行时压扁(2026-11-07 用户裁「不动美术素材」),x 对齐门洞 520–760、底压墙底 → (520, 282)
|
||||||
4. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全量重出,不裁
|
4. **帐篷**:251×170 沿用现终稿,落位 (982, 335),遮住墙下部 32px(覆盖围墙可接受)
|
||||||
5. **营地环境子板色值**:不前置拍板——量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值
|
5. **笔记本**:随帐篷跟随,落在帐篷左下方外侧、两者不重叠——`x = 帐篷 x − 112`、`y = 帐篷底 + 10`
|
||||||
|
6. **宝箱离底**:贴图底 y744,距画面底 56px;其余物件同步上移 46px
|
||||||
|
7. **地面分两区**:营地外(y734 以上)=晒白的浅黄绿草地+一条向远山收窄的暖米白土路;营地内(y734 至画面底)=正午太阳下晒到泛白的踩实米黄土地、与草地异色相、无草无路无车辙;两区分界被围墙层完全遮住
|
||||||
|
8. **背景层分两片出图**:远景片 `bg_far`(2560×734,天空 14%/远山 41%/草地 45%+小路)+ 地面片 `bg_floor`(2560×866 踩实裸土),后处理按 y734 拼成一张 2560×1600;接缝落在围墙 406–734 背后。分片理由=整张出图时模型把山挤到画面下半部,实测三张里两张山体整段被围墙遮没
|
||||||
|
9. **布告板位置**:(845, 241, 130, 121)(2026-11-07 随墙顶),底 362 落在墙内(墙 220–420);命中 130×140
|
||||||
|
10. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全量重出,不裁
|
||||||
|
11. **营地环境子板色值**:不前置拍板——量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值
|
||||||
|
12. **围墙显示几何与墙脚入土(2026-11-07 用户裁)**:围墙显示矩形 `(0, 220, 1280, 200)`(顶 y220、高 200、底锚 y420);大门 240×138 尺寸不变、底压墙底 → `(520, 282)`;告示板 130×121 尺寸不变、随墙顶下移 17px → `(845, 241)`;墙脚按 1–7px 低频起伏裁透明缺口透出地面纹理(入土线,判据归 art-bible §6.2)
|
||||||
|
13. **其余六件落位(2026-11-05 用户裁;2026-11-08 复核补录)**:dummy `(340, 474, 120, 180)`/命中同矩形;forge `(40, 421, 240, 193)`/命中 `(40, 374, 240, 240)`;tent `(982, 335, 251, 170)`;chest `(1097, 654, 106, 90)`/命中 `(1085, 654, 130, 90)`;notebook `(870, 515, 100, 66)`/命中 `(870, 501, 100, 80)`;campfire `(560, 525, 160, 149)`/命中 `(560, 594, 160, 80)`。行内四元组=texture_rect `(x, y, w, h)`,「命中」=hotspot;运行期唯一事实源仍是 `game/data/tables/camp_scene_layout.tres`。
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
- **主色域 = 物种本色**,不受圣经 §4.2 语义色禁则约束(该禁则管格面与 UI 的逻辑色,角色身体主色豁免);**两例外**:禁入带 300°–345° 全角色禁入(仅 drider/duergar_king 两 Boss 独占)、蓝族禁入敌方主色(§5.4 同款)。
|
- **主色域 = 物种本色**,不受圣经 §4.2 语义色禁则约束(该禁则管格面与 UI 的逻辑色,角色身体主色豁免);**两例外**:禁入带 300°–345° 全角色禁入(仅 drider/duergar_king 两 Boss 独占)、蓝族禁入敌方主色(§5.4 同款)。
|
||||||
- **L2 熊地精 = bugbear 复用**(第二关三行,显示名熊地精系,非独立键):同剪影**换色板不换形**(色板替换走脚本管线——原则三"先换色板"的角色侧应用);变体主色避小人蓝族与禁入带。
|
- **L2 熊地精 = bugbear 复用**(第二关三行,显示名熊地精系,非独立键):同剪影**换色板不换形**(色板替换走脚本管线——原则三"先换色板"的角色侧应用);变体主色避小人蓝族与禁入带。
|
||||||
- 每敌种出 2–3 版候选(清单 §2.2);受击反馈/死亡表现/顺位标记三类呈现下限见圣经 §4.6.4 资产需求行。
|
- 每敌种出 2–3 版候选(清单 §2.2);受击反馈/死亡表现/顺位标记三类呈现下限见圣经 §4.6.4 资产需求行。
|
||||||
- **立绘显示档(定值单点 = 圣经 §8.2 站桩立绘显示档条,本档指路不复述)**:三档绝对高 96/144/188,逐件归档、源档与缩放规则一律见圣经 §8.2——**数值权威 = 圣经 §8.2**(定值单点纪律,圣经 §8 头注);归档经三体型约束校验(§5.2)确认;派生管线与排版规范同归圣经 §8.2。
|
- **立绘显示档(定值单点 = 圣经 §8.2 站桩立绘显示档条,本档指路不复述)**:三档绝对高,逐件归档、源档与缩放规则一律见圣经 §8.2——**数值权威 = 圣经 §8.2 指向的执行件**(定值单点纪律,圣经头注);归档经三体型约束校验(§5.2)确认;派生管线与排版规范同归圣经 §8.2。
|
||||||
- **钩爪恐魔「宽≥高」豁免登记(待样张终审)**:定档源 58 高窄条束状剪影(长臂圆钩),宽高比 <1,与 §5.1 普通怪「近圆墩形宽≥高」冲突——按体量=生物天性(§5.2)登记豁免:以长臂束状轮廓为识别锚,不强行压成墩形;样张(圣经 §1.4)终审复验灰度剪影可辨性。
|
- **钩爪恐魔「宽≥高」豁免登记(待样张终审)**:定档源 58 高窄条束状剪影(长臂圆钩),宽高比 <1,与 §5.1 普通怪「近圆墩形宽≥高」冲突——按体量=生物天性(§5.2)登记豁免:以长臂束状轮廓为识别锚,不强行压成墩形;样张(圣经 §1.4)终审复验灰度剪影可辨性。
|
||||||
|
|
||||||
## 5.6 意图准备动画三档(规格承载节)
|
## 5.6 意图准备动画三档(规格承载节)
|
||||||
|
|||||||
@@ -24,6 +24,24 @@
|
|||||||
| probe_dust | 显影尘 | 未投值(effect_kinds 空)——设计方向=信息显影(把玩家暂时看不到的棋盘信息还给玩家) | 退役(2026-10-10 用户裁第一版全弃用) | 2026-10-10 用户裁 |
|
| probe_dust | 显影尘 | 未投值(effect_kinds 空)——设计方向=信息显影(把玩家暂时看不到的棋盘信息还给玩家) | 退役(2026-10-10 用户裁第一版全弃用) | 2026-10-10 用户裁 |
|
||||||
| catacomb_scroll | 地穴全图卷 | 未投值(effect_kinds 空)——名义指向地穴全图揭示 | 退役(2026-10-10 用户裁第一版全弃用) | 2026-10-10 用户裁 |
|
| catacomb_scroll | 地穴全图卷 | 未投值(effect_kinds 空)——名义指向地穴全图揭示 | 退役(2026-10-10 用户裁第一版全弃用) | 2026-10-10 用户裁 |
|
||||||
|
|
||||||
|
## 表一附:退役效果词面留底
|
||||||
|
|
||||||
|
> 所属线=道具/秘宝。下列词面是旧目录时代秘宝数据行的效果类型标识,旧目录退役后不再由任何现行数据行使用;留底供日后重新准入时查证,不构成现行词表。
|
||||||
|
|
||||||
|
| 词面 | 关联旧件 | 旧效果 |
|
||||||
|
|---|---|---|
|
||||||
|
| mine_reveal | 探巢摆钟、爆破工兵包 | 真视 3×3 |
|
||||||
|
| reward_preview | 探宝罗盘 | 预读 3×3 |
|
||||||
|
| ap_grant | 工兵令、爆破工兵包 | 一次给 2 或 4 点行动点 |
|
||||||
|
| mine_hit_halve | 惊巢反制 | 踩雷惩罚减半 |
|
||||||
|
| reflect_damage | 惊巢反制 | 受击反弹伤害 |
|
||||||
|
| ap_rounds_front | 工兵晨令 | 开局前几轮每轮 +1 行动点 |
|
||||||
|
| cell_removal | 爆破工兵包 | 中立移除危险格(棋盘事实不可变契约下已废止) |
|
||||||
|
| reward_weight_bias | 偏运硬币 | 摇号稀有资源权重偏置 |
|
||||||
|
| bonus_refresh | 三选一刷新件 | 三选一刷新次数加算 |
|
||||||
|
|
||||||
|
效果引擎侧另有 bias_wallet:原预期为偏运硬币在摇号上影响金币面;现行由 bias_rewards 承载摇号权重偏置、grant_gp 承载 GP 入账,该词面无独立效果。
|
||||||
|
|
||||||
## 表二 专长退役 27 件
|
## 表二 专长退役 27 件
|
||||||
|
|
||||||
只读引用 `game/data/tables/feats.tres` 现行 27 行(feat_id 与 display_name;效果不抄——效果以表为事实源,此处仅留名单)。
|
只读引用 `game/data/tables/feats.tres` 现行 27 行(feat_id 与 display_name;效果不抄——效果以表为事实源,此处仅留名单)。
|
||||||
@@ -72,6 +90,14 @@
|
|||||||
| 换装券 | 冒险中可在节点处换装一次 | 终裁装配只在冒险开始前配置、冒险中零更换途径——无此件存在空间 | 2026-10-11 |
|
| 换装券 | 冒险中可在节点处换装一次 | 终裁装配只在冒险开始前配置、冒险中零更换途径——无此件存在空间 | 2026-10-11 |
|
||||||
| 第四只手 | 同调位 +1(额外格=优秀格) | 净收益为零的自指件——占一槽换一槽(真实携带量 3=3)且自锁唯一稀有格 | 2026-10-11 |
|
| 第四只手 | 同调位 +1(额外格=优秀格) | 净收益为零的自指件——占一槽换一槽(真实携带量 3=3)且自锁唯一稀有格 | 2026-10-11 |
|
||||||
|
|
||||||
|
## 表五 重设计件退役(2026-11-07 起)
|
||||||
|
|
||||||
|
已实装 `feats.tres` 后退役的重设计专长,留底供日后重新过准入(回收须过准入校验/分界尺/定义卡三关,与其他素材库件同规)。
|
||||||
|
|
||||||
|
| 代号 | 效果 | 退役原因 | 退役日期 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 破封一击 | on 挖开有封印印记的危险格:额外 +1 层(疼痛记忆同账) | 触发路径删除——「封印受理即揭示、封印格拒绝挖掘」口径换代后「挖开封印格」不复存在,专长永远无法触发(2026-11-07 用户裁) | 2026-11-07 |
|
||||||
|
|
||||||
## 备选素材(未立项提名,2026-10-10 用户令增设)
|
## 备选素材(未立项提名,2026-10-10 用户令增设)
|
||||||
|
|
||||||
> 本节收纳**曾被提名但从未立项、零设计细则**的备选概念——只记提名出处与当前结构前提,不做详细设计;是否立项、立项后怎么设计,待用户另议。与退役表不同:这些件从未落过数据表或正文设计,回收时无「原效果」可考,须从头过定义卡。
|
> 本节收纳**曾被提名但从未立项、零设计细则**的备选概念——只记提名出处与当前结构前提,不做详细设计;是否立项、立项后怎么设计,待用户另议。与退役表不同:这些件从未落过数据表或正文设计,回收时无「原效果」可考,须从头过定义卡。
|
||||||
|
|||||||
@@ -2,21 +2,20 @@
|
|||||||
|
|
||||||
## 文档状态
|
## 文档状态
|
||||||
|
|
||||||
- 版本:1.36
|
- 版本:2.0(收窄为约束面形态——分层/模块归属/数据流/API 边界;实现现状归代码与代码头注,实现历史归 git commit log,闸清单与判定口径归 `game/tests/README.md`,见 doc-conventions「架构事实唯一源」行)
|
||||||
- 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定)
|
- 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定)
|
||||||
- 评审模式:solo(`review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调)
|
- 评审模式:solo(`review-mode.txt`——门禁按 solo 跳过)
|
||||||
- 覆盖 GDD:现行全集(根索引=`design/gdd/02-系统清单.md`,文档树构成以根索引为准)
|
- 覆盖 GDD:现行全集(根索引=`design/gdd/02-系统清单.md`,文档树构成以根索引为准)
|
||||||
- 事实源地位:本文是架构事实的唯一来源——分层/所有权/数据流/API 边界/测试与质量域均以本文为准;历史决策沿革查 git commit log,不另设决策文档体系
|
- 事实源地位:本文是架构约束的唯一权威(分层/模块归属/数据流/API 边界);写权限=用户专属(agent 与技能只读)
|
||||||
- 实现实证:`game/`(2026-09-10 起开发,**现为完整游戏开发版本,已非垂直切片**;测试层级=冒烟/单元/集成/系统四级+UI 探针与渲染 golden(2026-10-22 用户裁),闸机按改动域分跑在役)——本文档的分层/所有权/数据流均经实现验证,非纯纸面设计
|
- 实现实证:`game/`(完整游戏开发版本;本文分层与所有权经实现验证)。测试层级=冒烟/单元/系统三级+UI 探针与渲染 golden,识别三元组权威=`design/engineering/test-conventions.md`「测试层三元组」节
|
||||||
- 主程序可行性:跳过 — solo 模式
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 引擎知识缺口摘要
|
## 引擎知识缺口摘要
|
||||||
|
|
||||||
- 引擎事实现行事实源=`design/engineering/engine-reference/godot/`(VERSION / breaking-changes / deprecated-apis / current-best-practices 四件)——迁移核实结论、语义变化与编码注意一律查那里,本文不重复。
|
- 引擎事实现行事实源=`design/engineering/engine-reference/godot/`(VERSION / breaking-changes / deprecated-apis / current-best-practices 四件)——迁移核实结论、语义变化与编码注意一律查那里,本文不重复。
|
||||||
- 渲染器与窗口基座=gl_compatibility + 1280×800(2026-09-12 裁);UI/渲染域为引擎风险集中地,采纳引擎增量前对照 engine-reference 核实。
|
- 渲染器与窗口基座=gl_compatibility + 1280×800;UI/渲染域为引擎风险集中地,采纳引擎增量前对照 engine-reference 核实。
|
||||||
- 写码纪律不变:不确定的 API 一律查 `docs.godotengine.org/en/4.7/` 核实后再用;4.8(dev 阶段)稳定版发布后跑 `/setup-engine refresh`。
|
- 写码纪律不变:不确定的 API 一律查 `docs.godotengine.org/en/4.7/` 核实后再用。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@
|
|||||||
│ D4 音频 (Beta) · D5 教学引导 (Beta) │
|
│ D4 音频 (Beta) · D5 教学引导 (Beta) │
|
||||||
├────────────────────────────────────────────────────────────┤
|
├────────────────────────────────────────────────────────────┤
|
||||||
│ 功能层 │
|
│ 功能层 │
|
||||||
│ B1 战斗结算编排 (MVP) · C1 关卡节点地图 (lite 已实装) │
|
│ B1 战斗结算编排 (MVP) · C1 关卡节点地图 │
|
||||||
│ C2 冒险结构 · C3 难度曲线 · C4 元进度 (Alpha) │
|
│ C2 冒险结构 · C3 难度曲线 · C4 元进度 (Alpha) │
|
||||||
├────────────────────────────────────────────────────────────┤
|
├────────────────────────────────────────────────────────────┤
|
||||||
│ 核心层 │
|
│ 核心层 │
|
||||||
@@ -61,13 +60,13 @@
|
|||||||
| B2 敌人系统 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
|
| B2 敌人系统 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
|
||||||
| B4 地图战斗资源 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
|
| B4 地图战斗资源 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
|
||||||
| B1 战斗结算编排 | 功能层 | MVP | ✅ 完整可跑(禁 await) | LOW(纯逻辑) |
|
| B1 战斗结算编排 | 功能层 | MVP | ✅ 完整可跑(禁 await) | LOW(纯逻辑) |
|
||||||
| C1 关卡节点地图 | 功能层 | MVP(切片期实装) | ✅(切片 level_runner 先例) | LOW |
|
| C1 关卡节点地图 | 功能层 | MVP | ✅ | LOW |
|
||||||
| C2 冒险结构 | 功能层 | MVP(切片期实装) | ✅ | LOW |
|
| C2 冒险结构 | 功能层 | MVP | ✅ | LOW |
|
||||||
| C3 难度曲线 | 功能层 | MVP(切片期实装) | ✅ | LOW |
|
| C3 难度曲线 | 功能层 | MVP | ✅ | LOW |
|
||||||
| C4 元进度 | 功能层 | Alpha | ✅ | LOW |
|
| C4 元进度 | 功能层 | Alpha | ✅ | LOW |
|
||||||
| D1 HUD | 呈现层 | MVP | ❌(UI 层——场景级探针测试承载) | **MEDIUM**(Control/Input/文本域) |
|
| D1 HUD | 呈现层 | MVP | ❌(UI 层——场景级探针测试承载) | **MEDIUM**(Control/Input/文本域) |
|
||||||
| B5 战斗表现 | 呈现层 | 切片后立项(未实装,前置战斗表现美术测试) | ❌ | **MEDIUM**(Animation/Tween/渲染) |
|
| B5 战斗表现 | 呈现层 | 切片后立项(未实装,前置战斗表现美术测试) | ❌ | **MEDIUM**(Animation/Tween/渲染) |
|
||||||
| D4 音频 / D5 教学 | 呈现层 | Beta(2026-10-13 Alpha 版本标准裁:与游戏内容无关者一律排 Beta) | 部分 | LOW-MEDIUM |
|
| D4 音频 / D5 教学 | 呈现层 | Beta(与游戏内容无关者一律排 Beta) | 部分 | LOW-MEDIUM |
|
||||||
| D3 存档序列化 | 基础层 | Alpha | ✅ | LOW |
|
| D3 存档序列化 | 基础层 | Alpha | ✅ | LOW |
|
||||||
| D6 设置/本地化 | 基础层 | 完整愿景 | ✅ | LOW |
|
| D6 设置/本地化 | 基础层 | 完整愿景 | ✅ | LOW |
|
||||||
|
|
||||||
@@ -77,142 +76,88 @@
|
|||||||
|
|
||||||
## 模块归属
|
## 模块归属
|
||||||
|
|
||||||
> 命名遵循 `design/engineering/code-conventions.md`:领域命名、禁 ID 前缀(文件头注不写文档链接——「实现 GDD:xxx」一类已废止,代码↔设计追溯由 GDD 文档承担)。
|
> 命名遵循 `design/engineering/code-conventions.md`:领域命名、禁 ID 前缀。本表只写约束:模块的职责语句、对外封闭面概述与消费依赖——各件的完整公开方法面、成员与接线明细归代码文件头注(`##` 文档注释)与代码自身承载;文件路径是导航索引。
|
||||||
|
|
||||||
### 基础层
|
### 基础层
|
||||||
|
|
||||||
| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API |
|
| 模块 | 文件 | 独占职责 | 对外封闭面 | 消费依赖 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **ConfigDB**(autoload,D2) | 全部玩法数值表与表现层布局配置表(`data/tables/*.tres` + `data/schemas/*.gd`);加载/校验/override/诊断状态机。**行族访问器归位各 schema 表类(表管自己的行查询),本类只留加载/校验/override/诊断门面;表持有成员按域收进四张域容器 Resource(`config_domain_combat/run/crossrun/presentation.gd`——四张域容器均已建件,类型化成员 7/7/5/1);三张 resolver 表(board_gen.resolve_row/enemy.resolve_rowset/difficulty.resolve_modifiers)经 `load_tables` 装配段注入各容器,resolver 文件与键零搬移**——红线不变:本类仍是唯一加载与持有单点,"经 ConfigDB 单点读取"=经其持有的表对象 | 类型化域容器属性(每域一张容器);公开面 8(push_diag/is_fatal/reset_diagnostics/diagnostics/diagnostics_count/load_tables/set_reload_gate/reload)、类变量 10 | 无(基础层顶点) | Resource/.tres 加载、autoload 生命周期——LOW |
|
| **ConfigDB**(autoload,D2) | `game/core/config_db.gd` | 全部玩法数值表唯一加载与持有单点(`.tres` 经校验后入容器);行族访问器归各 schema 表类(表管自己的行查询),本类只留加载/校验/override/诊断门面,表持有按域收进域容器 Resource | 类型化域容器属性+load_tables / reload / set_reload_gate / diagnostics 族 | 无(基础层顶点) |
|
||||||
| **SlotStore**(`core/slot_store.gd`,D3 存档槽位域件,已建件) | 存档三槽位文件域唯一所有者:槽位挂载与模板、激活与建删、槽位摘要窥视(peek 族);改名覆盖原语(_rename_overwrite)留 save_manager(IO 原语单点) | 槽位读写原语族+摘要投影(公开 11:active_path 读投影、migrate_legacy_save 公开化;对 SaveManagerCore 反向私取 21 处清零=双向公开面;类变量 4;SaveManager 与菜单消费方经 `save.slots.` 直连) | save_manager(注入路径与模板配置);FileAccess——LOW |
|
| **RngService**(autoload,D2) | `game/core/rng_service.gd` | master_seed 与各封闭流 scope 计数器单点(封闭流词表现值以 `RngServiceCore.PURPOSE_TAGS` 为准,增流走 P1 评审) | set_master_seed(唯一调用方 C2)/ open_stream 有状态门面 / derive_at 纯函数 / 只读计数器 | 无 |
|
||||||
| **MetaStateStore**(`core/meta_state_store.gd`,D3 存档内元进度数据件,已建件) | 存档内元进度数据的读写唯一层(钥石/道具解锁/树节点与叉侧/锻造路线/同调/真视/计数器/摘要——数据读写原语,不含业务规则);save_manager 与 meta_progression 双 God Class 的共同病根=该数据域摊在两文件,本件即其归一 | 写口原语 13+只读投影 6(tree_state/forge_state/attune_state/career_state 四投影+keystone_balance/item_unlocked)=公开 19(add_keystone 私有 `_add_keystone`),零 _data 副本零缓存;MetaProgression 业务层与营地/锻造 UI 消费方经 `save.meta_state.` 直连(meta 的纯转发读方法已退役) | save_manager(序列化接线);FileAccess——LOW |
|
| **save_system**(SaveManager,autoload,D3) | `game/core/save_manager.gd` | 存档格式与版本比较、序列化接线单点;槽位文件域归 SlotStore、元进度数据归 MetaStateStore | 写盘/读回/槽位管理/断点快照公开面(契约规范源:`../../gdd/systems/表现与支撑/存档序列化.md`——契约锚:SAVE_FORMAT_VERSION + master_seed + 各流 scope 计数器快照) | ConfigDB、RngService 只读计数器 |
|
||||||
| **MetaProgression**(autoload,`core/meta_progression.gd`,D3 元进度业务层) | 元进度账本服务:钥石收束入账、营地消费定价与秘宝解锁判定的纯被动服务,零信号零外发;数据读写全经注入的 MetaStateStore(`save.meta_state.` 直连);hero_override() 现算不写表(全零=白板合法态——生效注入只走冒险开始参数面显式传参) | 写口族(天赋树购买/叉侧切换/锻造解锁与升级与选中/同调装配切换等)+解锁判定与读投影;**构造双形态**=autoload 装配走 `.new()` 零参+`_ready` 从 autoload 链取依赖(工程序 ConfigDB→RngService→SaveManager→MetaProgression,注册顺序即依赖序),单测/工具走 `.new(db, save)` 直构形态(不入树零 _ready)——**四个 Autoload 中唯一有跨 Autoload 依赖的件(ConfigDB/SaveManager)** | ConfigDB(定价与档位表值);SaveManager(存档访问器,经节点路径延迟取用) | autoload 生命周期——LOW |
|
| **SlotStore**(D3) | `game/core/slot_store.gd` | 存档三槽位文件域唯一所有者:槽位挂载与模板、激活与建删、摘要窥视 | 槽位读写原语族+摘要投影 | save_manager(注入路径与模板配置) |
|
||||||
| **RngService**(autoload,D2) | master_seed、各流 scope 计数器(封闭流词表现值以 `RngServiceCore.PURPOSE_TAGS` 为准;增流走 P1 评审) | `set_master_seed()`(唯一调用方 C2);`open_stream(stream)` 有状态门面;`derive_at(stream, scope)` 纯函数;只读计数器 | ConfigDB(无) | 无——纯逻辑 |
|
| **MetaStateStore**(D3) | `game/core/meta_state_store.gd` | 存档内元进度数据的读写唯一层(数据读写原语,不含业务规则) | 写口原语族+只读投影(消费方经 `save.meta_state.` 直连) | save_manager(序列化接线) |
|
||||||
| **action_economy**(A3) | AP/RAP 账本、last_round_end、轮次相位机 {Idle, Active, Waiting}、结束仲裁;dig_paid 命中施加抽私有单点(_apply_dig_paid_hits——矿脉储能入池面) | 意图与通知布尔面:notify_round_start / request_dig / request_stop / request_refresh(收折后价入参——折价计算归 BattleRefreshFlow 单点)/ notify_settlement_done / notify_combat_end;预授权通道:grant_reserve_ap / finish_round_stop;ap/rap/phase 只读;实测类变量 10 | ConfigDB(ActionEconomyTable);EffectPort(效果端口件——发射经端口单点,effect_engine 直连退役);B1 回发 next_round_mode/battle_over | 无 |
|
| **MetaProgression**(autoload,C4) | `game/core/meta_progression.gd` | 元进度账本服务:钥石收束入账、营地消费定价与解锁判定的纯被动服务,零信号零外发;业务层(数据读写全经 MetaStateStore) | 写口族(天赋树/锻造/同调)+解锁判定与读投影;四个 Autoload 中唯一有跨 Autoload 依赖(ConfigDB/SaveManager) | ConfigDB、SaveManager |
|
||||||
| **variation 定义**(A4) | VariationTable schema(现行 6 行:六 region——贫矿脉 global 行已屏蔽删行,global 型机制代码保留)与 F1 候选池门控谓词 | `variant_pool(level_index, board_type, node_type="")`(门控三维:unlock+board_types+节点身份——global 行仅 boss/elite 入池,缺省跳过零扰动);`global_variant_row(level_index, board_type, node_type)`(全局型单行决议访问器) | ConfigDB(VariationTable) | 无 |
|
| **action_economy**(A3) | `game/core/action_economy.gd` | AP/RAP 账本、轮次相位机 {Idle, Active, Waiting}、结束仲裁 | 意图与通知布尔面(request_dig / request_stop / request_refresh / notify_* 族)+预授权通道;ap/rap/phase 只读 | ConfigDB、EffectPort、B1 回发 |
|
||||||
| **status_container**(B3) | 状态实例容器(战斗域生命周期、跨轮跨图延续) | 5 API:notify_battle_start / apply_effect / query_active / decay_round / notify_battle_end | ConfigDB(StatusEffectTable) | 无(RefCounted) |
|
| **variation**(A4) | `game/core/variation*.gd` | VariationTable schema 与 F1 候选池门控谓词 | variant_pool(门控三维)/ global_variant_row 访问器 | ConfigDB |
|
||||||
| **effect_engine** | 零运行时可变状态的系统(见「架构原则」条 8):全同步解释器——事件由宿主在明确代码点位显式调 dispatch 进件,命中序=装载声明序(feats→treasure→树规则)写死保种子复放,不是事件总线/事件循环;事件/事实/效果类型/算子四词表封闭 + 树规则合成订阅六键(posture 每关首轮窗/sense 两组限次 counter 闸·adv_ 前缀走冒险桶跨战斗持久) | rebuild(每战重建订阅表)/`dispatch(ctx, event, payload, facts)`/`validate_trigger_row` + 静态计数口 `counter`·`counter_add`·`counter_spend`·`bucket_of`·`counter_id_legal`(计数器读写只经 EffectContext 引用束,无导出/灌入接口) | ConfigDB(feats/treasure 行集)、EffectContext(四桶引用由宿主持有:round/battle 桶归编排器、level 桶归关卡域、adventure 桶归应用层——RunLedger 已退役,桶字典由 adventure_runner 持有) | 无(零随机全确定) |
|
| **status_container**(B3) | `game/core/status_container.gd` | 状态实例容器(战斗域生命周期、跨轮跨图延续) | 五 API:notify_battle_start / apply_effect / query_active / decay_round / notify_battle_end | ConfigDB |
|
||||||
| **save_system**(D3,Alpha;已升格 autoload「SaveManager」) | 存档格式与版本比较 | save_manager 公开面 14(set_read_only/read_only/reset_to_default/data_snapshot/restore_data 五承接方法+peek_summary_at/rename_overwrite 两更名公开化);(契约规范源:`../../gdd/systems/表现与支撑/存档序列化.md`——契约锚:SAVE_FORMAT_VERSION + master_seed + 各流 scope 计数器快照,须在无正在执行中的 open_stream 实例时切出) | ConfigDB、RngService 只读计数器 | FileAccess——LOW |
|
| **effect_engine** | `game/core/effect_engine.gd` | 零运行时可变状态的全同步解释器(架构原则 8):事件由宿主在明确代码点位显式 dispatch 进件,命中序=装载声明序,不是事件总线/事件循环 | rebuild / dispatch / validate_trigger_row +静态计数口;事件/事实/效果类型/算子四词表封闭+树规则合成订阅六键 | ConfigDB 行集、EffectContext 引用束(四桶由宿主持有) |
|
||||||
| **settings/localization**(D6,愿景) | 设置项、翻译数据 | (契约规范源:`../../gdd/systems/表现与支撑/设置与本地化.md`) | ConfigDB | 无 |
|
| **settings/localization**(D6,愿景) | — | 设置项、翻译数据 | (契约规范源:`../../gdd/systems/表现与支撑/设置与本地化.md`) | ConfigDB |
|
||||||
|
|
||||||
### 核心层
|
### 核心层
|
||||||
|
|
||||||
| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API |
|
| 模块 | 文件 | 独占职责 | 对外封闭面 | 消费依赖 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **board_generator**(A1) | 生成算法(五阶段管线)、BoardGenTable 回填、生成期指标集、合法性谓词(clearable / R₀≠S / min_safe)、可推理率度量(metric_version);生成姿态 = MVP 同步生成 + 加载幕(切片实证 10×10/12×12 同步可接受,WorkerThread 留扩展) | `generate(L, D, rng) -> Board`;度量独立入口×3(推理器 / F3 度量 / 合法性谓词——独立纯函数、同一实现) | ConfigDB(BoardGenTable/VariationTable);board_gen 流(一次 open_stream = 一张图);dig_ap_cost 只读 | 无 |
|
| **board_generator**(A1) | `game/core/board_generator.gd` | 生成算法(五阶段管线)、合法性谓词(clearable / R₀≠S / min_safe)、可推理率度量;生成姿态=MVP 同步生成+加载幕(WorkerThread 留扩展) | `generate(L, D, rng) -> Board`;度量独立入口 | ConfigDB;board_gen 封闭流(一次 open_stream=一张图) |
|
||||||
| **minesweeper_rules**(A2) | 棋盘状态(已开集 O / 封印集 G / 小人位)、三事件面、批次仲裁、install 四不变式 | `install_board(board)`;`settle_batch(intents)`(唯一提交入口);查询只读面(current_board / hero_pos / is_revealed / has_seal 等);`compute_move_path(cell)` 只读;`preview_reveal(cell)` 只读预览口(零写入零事件——0 格连锁传播闭包);`retire_board()`;+harmful_variants/harmful_adjacent 两有害判定面(编排器归位);三源拒绝(board_face / resource_face / phase)+ sub_reason 封闭枚举;公开方法面 20(`safe_remaining` 已私有化为 `_safe_remaining`,唯一生产消费点=同类 `clear_map_cleared`),gdstyle S13 归绿零基线键 | A1 产物(Board class_name 数据契约);A3 try_spend / last_round_end/ 相位 | 无(零表读取、零 UI——切片实证) |
|
| **minesweeper_rules**(A2) | `game/core/minesweeper_rules.gd` | 棋盘状态(已开集/封印集/小人位)、批次仲裁、install 四不变式 | `install_board` / `settle_batch`(唯一提交入口)/ 查询只读面 / preview_reveal 只读预览口 / retire_board;三事件封闭(cell_revealed / flag_judged / round_end,payload 字段封闭) | A1 Board 契约(class_name 数据契约);A3 try_spend |
|
||||||
| **unit_container**(B2) | hero/enemy 单位实例(hp/atk/实例池:池快照+冷却+摇定动作+保底计数)、行值快照 | spawn / query_alive / rollable_skills / special_skills / check_trigger_unlocks / set_pending_action / pending_action / basic_streak / commit_action / tick_cooldowns / apply_damage / heal / default_target / check_skill_unlocks / despawn_all(query_beat/query_attack/advance 已随行为环退役;rollable_skills/special_skills/check_trigger_unlocks 带 facts 参——情境条件触发器在役,事实缺键=条件假拦下,百分比事实走阈值式折算) | ConfigDB(EnemyTable/SkillTable/HeroTable) | 无 |
|
| **unit_container**(B2) | `game/core/unit_container.gd` | hero/enemy 单位实例(hp/atk/实例池) | spawn / query_alive / 动作与伤害面 | ConfigDB |
|
||||||
| **reward_economy**(B4) | 格面资源身份映射(install 期预分配、Ready 只读、换图映射消亡)、极性路由字典面((类型, 极性)→ 字典行查询;路由执行归 B1 授予段)、F6 当量供给投影;装配期摇号面已拆出掷格件 RewardRoller(roll_board 装配序=守卫→复位→委托→收纳→ready;受理账面留守) | 封闭 API:roll_board / query_identity / query_full_snapshot / grant / grant_clear / retire_mapping / polarity_row / phase(weighted_pick 退役——返行选行算子迁掷格件);另有 is_mapped 静默布尔投影(批量工具用);实测类变量 11 | ConfigDB(RewardTable);BattleFxHost 经注入 Callable `luck_bias_query` 取偏运合计(reward_roll 发射与 bias_rewards 求和移至效果层完成);reward_roll 流(scope = 每次 install 批,取号经掷格件) | 无 |
|
| **reward_economy**(B4) | `game/core/reward_economy.gd` | 格面资源身份映射(install 期预分配、换图映射消亡)、极性路由字典面、受理账面(装配期摇号归掷格件 RewardRoller) | 封闭 API:roll_board / query_identity / grant / grant_clear / retire_mapping / polarity_row / phase | ConfigDB;BattleFxHost 偏运合计查询(注入 Callable) |
|
||||||
| **helper_items**(A5,切片已实装秘宝域) | HelperItemTable、探测显影语义 | (契约规范源:`../../gdd/systems/跨局循环/秘宝.md`——桥接位:A2 查询接口 + A4 counter_item_ids) | A2 / A4 / B4 | 无 |
|
| **helper_items**(A5) | `game/core/helper_items*.gd` | HelperItemTable、探测显影语义 | (契约规范源:`../../gdd/systems/跨局循环/秘宝.md`——桥接位:A2 查询接口+A4 counter_item_ids) | A2 / A4 / B4 |
|
||||||
| **CurioDeck**(`core/curio_deck.gd`,A5 秘宝域令牌池件) | 三选一/商店共享池的持久多重集、抽签(候选抽取)、cap 库存与专长凭证三计数与判定唯一所有者——件只管池与判定,停点编排与兑付推进留冒险编排器 | `draw_candidates(channel)` 抽签;`consume_deck_token` / `consume_pool_purchase` 池消耗;`cap_ok` 上限判定;`feat_ticket_consider` 凭证判定;`stock_snapshot` / `pool_stock` 只读投影;商店购买消费经注入 Callable 链至 CurioStop 兑付单点(已转纯池——bind_handlers 反向回调已退役) | ConfigDB(秘宝令牌行集);注入 RngServiceCore(reward_pick 封闭流,禁自建随机) | 无(RefCounted 纯逻辑) |
|
| **CurioDeck**(A5) | `game/core/curio_deck.gd` | 三选一/商店共享令牌池、抽签、cap 库存与专长凭证判定唯一所有者(停点编排与兑付推进留 CurioStop) | draw_candidates 抽签 / consume 族池消耗 / cap_ok / 凭证判定 / stock 只读投影 | ConfigDB;注入 RngServiceCore(reward_pick 封闭流) |
|
||||||
| **ShopSession**(`core/shop_session.gd`,商店会话件) | 关卡商店双模式(legacy 固定三件加定价/pool 共享令牌池)的货架、定价、购买与刷新唯一宿主——账本/钱包/装配集归宿主 LevelRunner(共享引用经 `bind` 注入,出账直接落同一引用改写宿主账本);legacy 模式零 RNG 零池消费(off 对照承载) | 货架与定价只读面(`shop_products` / `shop_shelf` / `current_price` / `shop_refresh_cost`)+写入口(`buy_product` / `buy_pool_item` / `shop_refresh` / `player_request_refresh` / `open_pool`);外部调用面=调用方经宿主 LevelRunner 公开成员 `shop` 直连(调用直连不留委托壳,2026-10-26 Middle Man 裁定),直连消费的方法=`shop_products`/`current_price`/`purchased_tier`/`buy_product`/`player_request_refresh`/`set_shop_pool`/`pool_price`/`shop_shelf`/`shop_refresh_free_left`/`shop_refresh_cost`/`shop_refresh`/`spend_gp`/`buy_pool_item`/`is_shop_pool`/`shop_bp_shelf`/`shop_bp_visit_buys`(另白盒两入口仅测试侧:`_draw_shelf`/`_spend_discounted`);set_shop_pool 调用面=pool 注入经 LevelRunner 构造 ctx 供给(构造期内部直调),测试面直连 `shop.set_shop_pool` | ConfigDB(商店行集);注入 RngServiceCore;宿主钱包/账本引用;pool 模式令牌消耗与判定经注入 Callable 转 CurioDeck | 无 |
|
| **ShopSession** | `game/core/shop_session.gd` | 关卡商店双模式(legacy 固定三件/pool 共享令牌池)的货架、定价、购买与刷新唯一宿主;账本/钱包经宿主 LevelRunner 注入共享引用 | 货架与定价只读面+写入口;调用方经宿主公开成员 `shop` 直连 | ConfigDB;注入 RngServiceCore;pool 模式经注入 Callable 转 CurioDeck |
|
||||||
| **HeroStats**(`core/hero_stats.gd`,主角数值账件,已实装) | 冒险生命周期主角数值域唯一所有者:生命账与特性持有集(活引用注入——关内兑付当关生效)、锻造强化快照、调试百分比通道、攻击/甲类型轴快照、生效上限/攻击/护甲公式与回血封顶公式单点、续玩生命钳制收口;生效公式经注入 GainJournal 只读引用取加算区汇总(无反向引用不成环) | 构造注入;单写原语族+只读投影;断点自交片段(账本键) | ConfigDB(表值读取);注入 GainJournal(只读);由 AdventureRunner 冒险开始创建、注入战斗 encounter | 无(RefCounted 纯逻辑) |
|
| **HeroStats** | `game/core/hero_stats.gd` | 冒险生命周期主角数值域唯一所有者:生命账与特性持有集、生效公式单点 | 构造注入;单写原语族+只读投影 | ConfigDB;注入 GainJournal(只读);AdventureRunner 创建 |
|
||||||
| **GainJournal**(`core/gain_journal.gd`,加算日记件,已实装) | 统一冒险加算区与获得记录唯一所有者:获得记录三层结构=记录列表(三选一件/商店购买/战末奖励各一条)→属性增益明细(带来源指回)→四轴汇总(由明细同步维护);三写通道统一走 gain_bonus 单写原语(source_class=curio_pick/shop_product/battle_export);本局钥石增量与逐杀明细、真视使用记录、商店已购档数记账同域 | gain_bonus 单写原语;记录与汇总只读投影;断点自交片段(获得日记键) | 由 AdventureRunner 冒险开始创建、注入 CurioStop/level_runner/ShopSession/战斗 encounter(战末 bonus 四轴经 gain_bonus 汇入) | 无(RefCounted 纯逻辑) |
|
| **GainJournal** | `game/core/gain_journal.gd` | 统一冒险加算区与获得记录唯一所有者(三层结构:记录→明细→四轴汇总) | gain_bonus 单写原语;记录与汇总只读投影 | AdventureRunner 创建,注入各消费方 |
|
||||||
| **GpWallet**(`core/gp_wallet.gd`,GP 钱包件,已实装) | 冒险局内货币唯一所有者(LevelRunner 与 ShopSession 读写全指此单点;冒险开始=0、收束清零,不入存档不入摘要) | gain/spend/clear 单写原语 | 由 AdventureRunner 冒险开始创建;宿主与商店经注入引用读写 | 无(RefCounted 纯逻辑) |
|
| **GpWallet** | `game/core/gp_wallet.gd` | 冒险局内货币唯一所有者(不入存档不入摘要) | gain / spend / clear 单写原语 | AdventureRunner 创建,宿主与商店注入读写 |
|
||||||
| **RefreshBank**(`core/refresh_bank.gd`,刷新账件,已实装) | 三选一刷新三源账唯一所有者:X 刷新件每碰三选一重给(优先消耗不结转)/Y 营地升级行冒险周期池(用完即无)/刷新券存量账(冒险级跨停点持久)+GP 付费刷计数与报价公式;零停点态依赖(免费/付费支出的编排归 CurioStop,本件只记账) | 支出与余量原语+报价公式;断点自交片段(refresh_stock/attune_refresh_y 两键,Y 缺键回退参数面) | ConfigDB(刷新件与营地升级行表值);注入 CurioStop 支出路径 | 无(RefCounted 纯逻辑) |
|
| **RefreshBank** | `game/core/refresh_bank.gd` | 三选一刷新三源账唯一所有者+GP 付费刷报价公式(零停点态依赖,编排归 CurioStop) | 支出与余量原语+报价公式;断点自交片段(refresh_stock / attune_refresh_y) | ConfigDB;注入 CurioStop 支出路径 |
|
||||||
| **AttuneLoadout**(`core/attune_loadout.gd`,同调配装件,已实装) | 装备中的秘宝件对象集唯一所有者(每件内含充能单位与重置周期);同调充能的物化行为唯一事实源——种行/补行改写时同步(RunLedger 充能字典轨与差额对账函数退役);旧档 aux_items 同调行迁移归件 | 构造注入;充能查询/消耗/按周期重置原语;断点自交片段(attunement_charges 键,键名与策略不变) | ConfigDB(秘宝行集);TreasureItems(同调行投放面);注入战斗使用路径 | 无 |
|
| **AttuneLoadout** | `game/core/attune_loadout.gd` | 装备中的秘宝件对象集与同调充能唯一所有者(种行/补行改写时同步) | 构造注入;充能查询/消耗/按周期重置原语 | ConfigDB;TreasureItems 投放面;注入使用路径 |
|
||||||
| **CurioStop**(`core/curio_stop.gd`,三选一停点件,已实装) | 三选一停点编排唯一所有者(架构原则 9 本域承载):停点三态(关卡完成三选一在途/已兑付待推进/奖励节点三选一在途)、刷新编排(三源账面归 RefreshBank 件、查停点态→支出→重抽重发编排留本件)、兑付方法族(pick/refresh/redeem/skip)、凭证出箱(RAP/时沙待注入);三选一信号面自带;零自动推进停点语义承载 | 对外=开停点/刷新/兑付/放行谓词/交断点片段五组入口+信号面(curio_choice_presented/curio_resolved);由 AdventureRunner 关卡完成受理时调用 | ConfigDB;注入 CurioDeck(抽签/摘牌)、HeroStats 与 GainJournal(兑付落账单写原语)、RefreshBank(刷新支出);随机只经 CurioDeck 的 reward_pick 封闭流 | 无 |
|
| **CurioStop** | `game/core/curio_stop.gd` | 三选一停点编排唯一所有者(架构原则 9 本域承载):停点三态、刷新编排、兑付方法族、零自动推进语义 | 开停点/刷新/兑付/放行谓词/交断点片段五组入口+信号面(curio_choice_presented / curio_resolved) | ConfigDB;注入 CurioDeck、HeroStats、GainJournal、RefreshBank |
|
||||||
| **breakpoint_store**(`core/breakpoint_store.gd`,冒险域·断点组装与回放件,已建件) | 存档断点组装与回放唯一承载:断点快照拼盘、回放回填、读侧策略分发;`BREAKPOINT_FIELDS` 27 键登记单源随件(键名/策略标签/键序冻结) | 构造=引用束注入(九引用束成员解包为原名成员——保迁移函数体逐字);`resume_adventure` 留宿主(壳+宿主侧回填语句——R2 所有权缝分家);断点键面零变化;公开方法面 18(13 新面承接 adventure_runner 私取清零+bp_read 公开化);实测类变量 15(贴顶禁再增) | adventure_runner(宿主);注入主角账三件与 curio/stop/bank/loadout 引用 | 无(RefCounted 纯逻辑) |
|
| **breakpoint_store** | `game/core/breakpoint_store.gd` | 存档断点组装与回放唯一承载:断点快照拼盘、回放回填、读侧策略分发 | `BREAKPOINT_FIELDS` 键登记单源(键名/策略标签/键序冻结) | 注入引用束 |
|
||||||
|
|
||||||
### 功能层
|
### 功能层
|
||||||
|
|
||||||
| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API |
|
| 模块 | 文件 | 独占职责 | 对外封闭面 | 消费依赖 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **battle_orchestrator**(B1) | 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、[明细行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(基础行型+扩展行两层 + 字段分层,词表以 owner「明细流水」节为准)、条款③⑤闭合对账、**战斗域全部跨系统调用权**、效果引擎宿主面与树规则挂点施加面(**已拆出 BattleFxHost 并实装(2026-10-28 迭代 40——battle_fx_host.gd/reward_grant.gd 两件在库,效果引擎宿主面归 BattleFxHost 行承载,拆件细则见「战斗编排域拆件定稿」节);2026-10-29 零豁免裁设计闭合:RoundCycle/BattleFacts 两新件随批(宿主 38→15、S13 豁免第三条注销——见下两行与定稿节轴丁)**) | `begin_battle(encounter)`;窗口/刷新意图提交面(扮演 D1);`level_clear()`;步骤流(输出契约) | B2/B3/B4 全调用面(**唯一调用方=B1 域文件集:battle_orchestrator.gd + settlement/ 五段段类 + damage_controller + 拆件后三新件**);A3 request_refresh 代理 + 回发;A2 install/retire + 三事件订阅;A1 generate(attempt 非 scope 事件);D2 SettlementTable + set_reload_gate | 无(零随机、禁 await——切片 88 冒烟实证可回放) |
|
| **battle_orchestrator**(B1,域文件集=编排器+`settlement/` 五段段类+其拆件:BattleFxHost / RewardGrant / DamageController / BattleRefreshFlow / BoardInstaller / RoundCycle / BattleFacts / EffectPort / RewardRoller) | `game/core/battle_orchestrator.gd` 等 | 战斗域编排唯一宿主:战斗状态机与生命周期、A2 三事件订阅、结算五段驱动(授予/增益减益/战斗/衰减/判定,段序冻结于 SettlementTable.segment_order)、行发射基建、呈现投影;**战斗域全部跨系统调用权集中本域**(静态扫描域 S7 执法,文件集清单单点=`game/tests/static_scan.sh`) | `begin_battle(encounter)`;窗口/刷新意图提交面;`level_clear()`;步骤流(输出契约);[明细行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋) | B2/B3/B4 全调用面;A2 订阅;A1 generate;A3 代理+回发;D2 SettlementTable |
|
||||||
| **BattleFxHost**(`core/battle_fx_host.gd`,B1 域·效果引擎宿主件,已建件) | 效果引擎挂点施加面唯一承载:事件发射与事实判定(_fx_emit/_fx_fact)、主角 AC 基线与本轮/本战 AC 累积、bonus_delta 四轴累积(战末宿主 drain 汇入账本)、揭示待兑队列与兑付(含 _fx_revealing 再入闸——同步信号回环防二次缓冲二次兑付)、树规则合成订阅的 round/battle 桶计数器持有(桶随编排器生灭语义不变);效果端口件为业务类朝向机房的窄门面——端口在本件组建、bind_port 组装期转注两业务类,计数器账面收归本件;实测类变量 15 | 构造=引用束注入(防 _init max-parameters 新键);bind 时注入 emit Callable(行发射经宿主协议面单点)与兑付 Callable(RewardGrant 授予面——揭示队列 flush 回调);+mark_new_resource_type/+add_bonus_delta 两公开累积方法(grant 消费面——类变量 15 不变,方法-only);只读投影分两类消费方:AC 累积/bonus_delta 供宿主呈现快照与战末 drain,揭示态供宿主 A2 订阅旁路判定;`luck_bias_for(cell_count) -> int` 偏运合计查询口(体内三参形 dispatch——reward_roll 发射与 bias_rewards 求和自 RewardEconomy 收回本件,RewardEconomy 经注入 Callable 消费) | EffectEngine(EffectContext 引用束);RngServiceCore(fx_reveal 封闭流——除该流外零随机);A2 minesweeper(板读与 fx_reveal 调用);A3 action_economy(queue_ap_delta 读);B3 status_container 读;B2 unit_container 读(hp_ratio);DamageController(set_hero_ac_override);ConfigDB;encounter 引用 | 无(零 await——效果引擎全同步解释器) |
|
| **level_runner**(C1) | `game/core/level_runner.gd` | 关卡域生命周期:节点链推进、共享 B4、HP 携带、关卡末 level_clear;依赖构造注入一次给齐 | 节点推进接口;LevelTable(ConfigDB 跨表校验) | B1(直构接线战斗)、ConfigDB |
|
||||||
| **RewardGrant**(`core/reward_grant.gd`,B1 域·奖励授予件,2026-10-26 编排域拆件设计定稿——实现批建件) | 奖励授予唯一兑付管线(自 battle_orchestrator 收编 grant 族):极性字典路由与封印溢价兑付(_grant_routed)、三种行应用(flat/percent/gp)、伤害单据提交面(_submit 族)、清图奖励与身份授予、秘宝使用编排(use_treasure 四步)、战斗域 GP 缓冲 escrow 与授予段暂存伤害闸(_defer_board_damage/_deferred_board) | use_treasure 编排入口(treasure_interact_controller 经组合根现值回调直连);授予入口(结算段类直调);+feat_yield_adjust(专长收益调整——自编排器归位);只读投影(escrow 读与 GP 掉落合计——宿主呈现快照与 _roll_gp_drop 消费) | B4 RewardEconomy(polarity_row/grant);B1 域 DamageController(开单);BattleFxHost 引用(treasure_used 事件发射与计数器消耗);A2 minesweeper(校验回调/fx_reveal/remove_mines_in);A3 action_economy(相位闸/grant_ap/queue_ap_delta);B3 status_container(apply_effect/池读);B2 unit_container(hero_unit/heal);ConfigDB;注入 emit Callable、宿主 fatal Callable(battle_result 状态机唯一写点留宿主)、宿主 attune 读投影(_attune_safe_seen)、encounter 账本引用;TreasureItems 经宿主 setter 转发注入(库存注入时序在宿主构造之后) | 无(零随机零 await——授予期零随机口径,roll 值授予前已定) |
|
| **run_structure**(C2) | — | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (契约规范源:`../../gdd/systems/冒险循环/冒险结构.md`) | RngService.set_master_seed、C3/D2 |
|
||||||
| **damage_controller**(B1 域·伤害单据管线) | 伤害单据唯一兑现管线(单据九栏目声明→分量掷点/克制修正/伤害下限归一→明细行发射;双方同规);`damage_taken` 唯一发射口(_emit_hero_damage_taken)+唯一消费族(_apply_hero_damage_effects)——敌方攻击/地形/危险格/错误封印直伤四路径统一发射,board_flat_hero 结账前统一发射 | 兑付入口(编排侧开单)+ fx 揭示回调注入位;+hero_atk()/static hits_of()/emit_hero_damage_taken 公开化(_emit 去下划线非并存——编排器与段类消费);实测类变量 13(facts 构造注入) | B2 单位实例(单据目标传入);B1 注入(EffectPort 端口引用——发射经端口;EffectContext 引用束与编排回调收归宿主侧 BattleFxHost 域,业务类零引擎直连) | 无 |
|
| **difficulty**(C3) | — | DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表 | 调参输出(经 D2 解析传递,禁反向调用生成) | ConfigDB、B1 对账输出、A1 报告 |
|
||||||
| **BattleRefreshFlow**(`core/battle_refresh_flow.gd`,B1 域·换图刷新流程件,已建件) | 弃图刷新流程唯一承载:刷新可用性门(相位/每轮上限/储备门槛)、折后价单点(_effective_refresh_cost——专长行声明序第一命中、floor 取整、can 与执行同源)、换图执行序(扣储备→used+1→旧资源退役→旧板退役→装新板→board_refreshed 成功事实登记) | can_refresh/execute 两公开入口(构造=实例束注入 8 键——facts/db/action_economy/fx_host/reward_economy/minesweeper/install_cb/grant_seg;类变量 8);调用路径呈现层→编排器两公开方法单行转发→RoundCycle.refresh_flow() 取件→本件;grant_seg 段间引用直接交接(编排器 _rounds._grant_seg 跨两层链式取段消灭);A3 request_refresh 收折后价入参 | 编排器(宿主,B1 域内唯一调用方约束同族适用);A3 action_economy(折价扣费与拒绝判据);A2 装板壳(装板与退役);RewardGrant(apply_board_refreshed 成功事实消费);feats 折价行经 ConfigDB;static_scan S7_B1_SET 已增补本件(判据口径不变) | 无(零随机零 await) |
|
| **meta_progression**(C4,业务层) | `game/core/meta_progression.gd` | MetaTable、钥石账本、天赋树域、同调位槽位判定(业务规则与写口编排;数据原语归 MetaStateStore) | tree_* / forge_* / attune_* / settle_adventure / hero_override 族 | MetaStateStore、ConfigDB |
|
||||||
| **BoardInstaller**(`core/board_installer.gd`,B1 域·装板域件,2026-10-29 尾波清偿批设计闭合——实现批建件,细则见「战斗编排域拆件定稿」节轴丙) | 棋盘安装与变异布置域唯一承载(自 battle_orchestrator 收编装板族六函数):生成受理、全局作用域变异决议、资源摇号资格域组装(roll_board 恰一次)、region 变异决议与连通片布置;BoardGenerator 实例随件自建自接线(宿主成员退役)——宿主侧装板后状态复位(封印/完美计数清零、板序推进、board_changed 发射、秘宝叠加层退役)留宿主薄壳,时序逐字保持 | `install(during_round) -> bool` 单入口;构造=引用束注入(rng/db/minesweeper/reward_economy/encounter 只读引用+宿主 fatal Callable——防 _init max-parameters 新键) | A1 board_generator(件内持有);A2 install_board;B4 roll_board/board_skew 写;A4 变异决议行集经 ConfigDB;board_gen/variant_place 两封闭流随件、流名与开流时点零漂移 | 无(零 await——装板全同步) |
|
|
||||||
| **RoundCycle**(`core/round_cycle.gd`,B1 域·轮循环驱动件,已建件) | 轮循环驱动域唯一承载:结算五段段件持有与驱动、重入门闸、开轮摇号、踩雷账 | 引用束注入(编排器 20 键封闭束,解包自用七键后原束分发五段;持有 BattleRefreshFlow);段驱动入口由宿主接线调用;公开方法 4(refresh_flow() 读出口);实测类变量 15(贴顶禁再增) | B1 宿主;settlement/ 五段段类;A3 相位读 | 无 |
|
|
||||||
| **BattleFacts**(`core/battle_facts.gd`,B1 域·战斗事实件,已建件) | 战斗事实域唯一承载:受理事实(encounter)、轮 facts 缓冲(reveals/seals/path)、封印判定账、事实溯源、同调快照读面;attune 状态两成员随件(行为函数留宿主) | 零参直构;宿主与段类经注入引用读写;实测类变量 15(贴顶)/公开方法 4(reset_round+三 mark 写口) | B1 宿主;A2/A3 只读 | 无 |
|
|
||||||
| **settlement/ 五段段类**(B1 域·结算段件) | B1 每轮结算序列的五段逻辑件(授予/增益减益/战斗/衰减/判定——细则见下「战斗域装配现状」节) | 段处理入口(B1 接线调用);构造=引用束注入(各段断言各自必需键);段类对编排器零引用(注入 Callable 亦属接线面);可直接 `new()` 单测 | B2/B3/B4 兑付面与 B1 轮 facts 缓冲(各段按职责) | 无 |
|
|
||||||
| **level_runner**(C1-lite,切片已建) | 关卡域生命周期(节点链推进、共享 B4 + HP 携带、关卡末 level_clear) | 节点推进接口;LevelTable(`level.tres`——节点 enum {battle,reward,rest,boss}、末节点必须 Boss、ConfigDB 跨表校验⑧) | B1(直构 BattleOrchestrator 接线战斗)、ConfigDB LevelTable | 无 |
|
|
||||||
| **run_structure**(C2) | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (契约规范源:`../../gdd/systems/冒险循环/冒险结构.md`) | RngService.set_master_seed、C3/D2 | 无 |
|
|
||||||
| **difficulty**(C3) | DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表(切片 monte_carlo 为工具原型) | 调参输出(经 D2 R1 解析/编排器传递,禁反向调用生成) | ConfigDB、B1 对账输出(调参约束清单)、A1 报告 C | 无 |
|
|
||||||
| **meta_progression**(C4,Alpha) | MetaTable、钥石账本、天赋树域(MetaTreeTable 12 节点 v0.8——Fork 一节点双态/row 字段退役/RULE_KEY_PARAMS 六键参数字典/彩蛋特化觉醒)+ 同调位槽位判定(树点亮数单源)。**存档内元进度数据读写原语归 MetaStateStore——已落地:本类纯转发读已退役(消费方直连 meta_state),业务规则与写口编排留本类;hero_override 内联锻造加值与树淬炼 flat;并组三组(forge_select(kind,route_id)/hero_type_axes()→{attack,armor}/tree_camp_status()→{rows,fork_groups});补 meta_state 成员装配** | 公开面 20 定稿:buy_treasure_unlock / refresh_treasure_unlocks / treasure_shop_status / forge_buy_level / forge_buy_unlock / forge_select / hero_type_axes / forge_shop_status / settle_adventure / hero_override / tree_can_buy / tree_buy / tree_toggle_fork / tree_buy_fork / tree_rules(返参数字典)/ tree_camp_status / toggle_attunement / attune_camp_status / attune_refresh_charges / buy_attune_refresh | D3、C2、ConfigDB | 无 |
|
|
||||||
|
|
||||||
### 战斗域装配现状(RunLedger 段已退役,四账去向见下「冒险域拆分(现状登记)」节)
|
|
||||||
|
|
||||||
- **结算五段**:B1 编排器的每轮结算序列拆为 `game/core/settlement/` 五个段类——GrantSegment(①授予段,含封印判定与 counter/grant 助手单点、成功刷新事实消费面 apply_board_refreshed 与轮末治疗计数兑付面)→ AuraSegment(②增益/减益段)→ CombatSegment(③战斗段)→ DecaySegment(④衰减段)→ VerdictSegment(⑤判定段,返回裁定,终局早退语义留 B1)。段序骨架冻结于 `SettlementTable.segment_order` 语义,B1 退为段序编排+接线;段类可直接 `new()` 单测(`settle_segments_test` 在役)。
|
|
||||||
|
|
||||||
### 战斗编排域拆件定稿(本节为现状登记)
|
|
||||||
|
|
||||||
- **轴甲两件**:battle_orchestrator按变化原因拆出 BattleFxHost(效果引擎宿主域)与 RewardGrant(奖励授予域)两协作件;宿主保留架构在册职责全部——战斗状态机与生命周期、轮 facts 缓冲(_facts_reveals/seals/path)、A2 三事件订阅、结算五段驱动、attune 族原位、行发射基建(_emit_row/_assert_row_source/_fatal)、呈现投影(presentation/diagnostic_snapshot 唯一出口不变)、刷新面、nest_preview_count(巢穴预告读数口——外部直读面 main.gd 与 treasure_effects_test 随批点名冻结)。拆件动机与残留债口径见待办清单「gdstyle 存量债全量清偿」条目。
|
|
||||||
- **轴丙一件(2026-10-29 尾波清偿批设计闭合——实现批建件)**:battle_orchestrator 装板域六函数(`_install_new_board`/`_resolve_global_variant`/`_place_variants`/`_place_variants_apply`/`_variants_fringe`/`_adjacent_to_packs`,约 140 行;全仓仅宿主三调用点——begin_battle/中途刷新受理/player_request_refresh,实查零外部调用)按变化原因拆出 BoardInstaller,职责语句「棋盘安装与变异布置域」(生成→全局变异决议→装板受理→资源摇号→变异布置;单一变化原因=棋盘设置顺序与变异布置算法)。形态两修正(实测裁,与初案「逐字搬运」之差):①宿主复位块不随件——`_install_new_board` 体内五处计数清零、板序推进、board_changed 发射与秘宝叠加层退役留宿主薄壳 `_install_and_reset`,三调用点改调薄壳、时序逐字;②`_board_generator` 全文件仅装板族使用——实例随件自建自接线(fatal 经注入 Callable),宿主成员退役(类变量 38→37,禁无效成员义务)。encounter(23 处跨宿主)与 _reward_economy(18 处)确认留宿主、经引用束注入。文件长键(1035/1000)随本件迁出归绿;attune 族与 begin_battle 受理段序禁动不变。
|
|
||||||
- **轴丁两件(2026-10-29 零豁免裁设计闭合——实现批建件)**:RoundCycle(轮循环驱动件)与 BattleFacts(战斗事实件)见功能层表两行——宿主 38(轴丙落地后 37)→15,S13 豁免第三条注销;宿主保留面改登记为「战斗状态机与生命周期、行发射基建(_emit_row/_assert_row_source/_fatal)、呈现投影(两快照出口签名不变)、刷新面、nest_preview_count」;attune 族处置由下一条改判;treasure_inventory 注入改址追认——原「外部赋值路径零改址」句失效,level_runner 经 RewardGrant 出口直注;成员级对账以需求卡片为卡内契约(开工 T0 复核)。
|
|
||||||
- **轴戊两件(已建件)**:①**效果端口件 EffectPort**(`core/effect_port.gd`)——职责语句「战斗业务类唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批」;实测形态=六 Callable 路由、bind_port 组装期转注、闭面四键 biz_fact(dig_streak/hp_ratio/rider_tier_bonus/rider_tier_crit——charge_layers 键退役后宿主应答 null)、未绑零扰动缺省;`DamageController`/`ActionEconomy` 各持端口引用(同一实例、构造注入),`EffectEngine`/`EffectContext` 引用与计数器账面(value_counter 层值读后清零)收归宿主侧(BattleFxHost 域),业务类零引擎直连、零账面触碰;facts 取值束(dig_streak/rider_tier_*)与入站回调束(reveal/ac)随发射契约归宿主侧注入面;端口**单实现零接口抽象**(无基类无多态——GDScript 无 interface,本案不需要);端口与宿主经注入 Callable 束协作、零宿主对象引用(跨件单向接线条款适用,禁双向强引用)。②**掷格件 RewardRoller**(`core/reward_roller.gd`)——职责语句「装配期格面资源摇号:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影)」;实测形态=roll 批束四键(mapping/power_roll/clear_identity/clear_power)、选行算子 `_weighted_pick_row` 返表行、fatal 经构造 Callable 链;受理账面(grant/身份查询/快照/retire/polarity_row)留 `RewardEconomy`,衔接面=格→奖励身份映射(掷格件产出、受理件接收);掷格件经注入 RngServiceCore 取号(roll_board 流 scope=每次 install 批不变、取号序零漂移)。行为零变化红线沿本节「验收红线」全款:命中序=声明序、明细行协议词表零触碰、`_ineffective_row` 载荷 deferred 自描述键观测面不回退(甲案在案)、EV/MC 锚同种子逐位零漂移——round_flow 逐位回放 134 检查为主证(红线成立);`RewardEconomy` 实测类变量 11;S7 B1 域文件集与 S8 await 文件集已含两新件。
|
|
||||||
- **跨件单向接线**:RewardGrant 持 BattleFxHost 引用(treasure_used 事件发射与计数器消耗);BattleFxHost 对授予面走 bind 时注入的兑付 Callable(揭示队列 flush 回调)——禁双向强引用(两件均 RefCounted,环引用随每战新建泄漏)。行发射经 bind 时注入的 emit Callable(协议面单点留宿主——CurioDeck bind_handlers 同款先例,禁件回调宿主私有族);轮 facts 缓冲留宿主、fx 件经注入取值;_seal_consumed 留宿主(与 A2 seal_judged 订阅同域);fatal 经注入 Callable 转宿主 _fatal(battle_result 状态机唯一写点不变)。注入 Callable 亦属接线面、同单向纪律——禁为省参数改持对象引用。授予件对账本零强引用:战斗期消费经 `battle_hooks` 三键回调束(attune_consume/vision_add/negative_blast,bind_battle 缺键 assert),宿主侧三单点记账(RunLedger 类已退役,直持对象引用无处可指)。
|
|
||||||
- **战斗域读面(RunLedger 退役后)**:账本读经编排器 `_journal()`/`_attune_loadout()` 现值派生(GainJournal/AttuneLoadout,enc 派生、无成员接收);冒险桶经 `enc["adv_bucket"]` 下传 `battle_fx_host.mount_buckets`;战末 bonus 四轴经 `GainJournal.gain_bonus` 汇入。
|
|
||||||
- **settlement/ 段类随动(2026-11-04 迭代51卡② 换代)**:段类构造=引用束注入(编排器 20 键封闭束分发——各段断言各自必需键),段类对编排器零引用(跨件单向接线,注入 Callable 亦属接线面)。四个授予段 helper 归位:_feat_yield_adjust→RewardGrant(feat_yield_adjust)、_harmful_variants/_harmful_adjacent→minesweeper_rules(harmful_variants/harmful_adjacent)、_hits_of→damage_controller(static hits_of);_pool_effective/perfect_sweep_earned 留宿主(段类经编排器公开读投影消费)。
|
|
||||||
- **attune 族处置**:attune 状态两成员归 BattleFacts、行为函数留宿主——AttuneLoadout 充能单源化语义领地不破,外部三面消费点零改址;RewardGrant 经宿主 attune 读投影取 _attune_safe_seen 形态不变。
|
|
||||||
- **呈现零变化**:两快照出口签名与载荷逐字不变,内部改读两件只读投影(快照本体不读揭示态——揭示态投影消费方=宿主 A2 订阅旁路判定);treasure_interact_controller 三触点分家——use_treasure 经组合根现值回调改注 RewardGrant(每战新建编排器,禁一次性直引防悬挂),minesweeper 读与 attune_convert_state 仍走宿主取值回调(双取值面);nest_preview_count 直读面零变化。
|
|
||||||
- **验收红线**:游戏行为零变化(RNG 消费序零漂移——fx_reveal 封闭流随件迁移取号序不变、信号顺序契约冻结、明细行协议词表零触碰、同种子逐位一致);battle_orchestrator 头注发射点指址随拆件改写(词表不动,指址须真)。
|
|
||||||
- **S7/S8 登记**:RewardGrant 调 B4 API,两新件一并登记进 S7 B1 域文件集与 S8 结算路径 await 文件集(static_scan.sh 两清单独立、同步更新——防 await 面漏闸);轴丙 BoardInstaller 同规(调 B4 roll_board,已登记进两清单)。
|
|
||||||
|
|
||||||
### 冒险域拆分(现状登记——本节各条即现行形态)
|
|
||||||
|
|
||||||
- **应用层形态**:adventure_runner 退出上帝对象、转薄应用层(DDD 应用层形态)——只留冒险状态机、关序推进、结算受理、建件接线、效果引擎冒险桶字典持有(桶=效果引擎域数据,应用层只锚定生命周期);零领域决策。核心层表新件行(主角账三件与刷新账件/AttuneLoadout/CurioStop——见基础层与功能层登记)即本拆分目标。
|
|
||||||
- **CurioDeck 转纯池**:bind_handlers 反向回调退役;商店购买消费经注入 Callable 链至 CurioStop 兑付单点——牌库只管抽签/消耗/cap 判定/凭证计数。
|
|
||||||
- **RunLedger 退役**:四账各归其主——加算区/购买记录/钥石增量/真视记录归 GainJournal、特性集归 HeroStats(GP 钱包归 GpWallet),充能归 AttuneLoadout,冒险桶字典归应用层持有;战斗侧 encounter 注入面由单一账类引用改为多路(桶字典+实体账+配装件);ShopSession 账本引用面同步换代,商店属性商品加算改经 GainJournal 单写原语。
|
|
||||||
- **level_runner**:依赖改构造注入一次给齐(后置 setter 群与商店重绑机制退役;注入活引用禁快照——特性集共享引用语义保留);商店白盒转发属性撤除;战斗→关卡信号转发族保留(战斗实例每节点新建,关卡层做战斗域稳定面)。
|
|
||||||
- **断点片段化**:各件自写自读自己的键(关卡层交关卡域五键片段:node_id/visited_ids/aux_items/shop_shelf/shop_visit_buys),缺键回退策略随领域知识归各件;应用层唯一落盘口(收齐各件片段拼成顶层快照后写盘),写触发点不变(五处);既有 27 键逐键冻结;新增获得日记键沿扩列不升版先例——旧档缺日记回退汇总键直载并跳过比对,日记在档时由日记推导汇总、与留存值不符即报错中止(迁移正确性自检)。拼盘与读侧策略机组拆出 breakpoint_store(核心层表新行),应用层落盘口与写触发点不变——宿主经件组装快照后写盘,27 键冻结不变。
|
|
||||||
- **信号直连**:adventure_runner 六转发信号族(node_entered/choices_presented/step_row/round_started/board_changed/wallet_changed)退役;呈现层在 level_started 重取点重订阅关卡对象信号(旧实例连接随引用释放消亡);「关卡开始信号前零发射」契约写进关卡件头注;「恰好连接一次」断言用 is_connected 守卫(release 模板剥 assert);三选一信号面归 CurioStop。
|
|
||||||
- **调用直连**:不留中间人委托壳(纯转传=Middle Man 反模式,2026-10-26 用户裁定);呈现控制器经取值回调持件——回调只许捕获长活根对象,禁件方法 Callable(防悬挂);测试/探针直连件读写。
|
|
||||||
- **验收红线**:游戏行为零变化(RNG 流名 reward_pick 与消费序零漂移、信号顺序契约冻结、同种子逐位一致);gdstyle 基线禁改(类变量计数下降属改善);怪物寻址 resolve_enemy_rowset 调用面与关卡参数档装配零变化(未来关卡主题的数据缝不堵)。
|
|
||||||
|
|
||||||
### 呈现层
|
### 呈现层
|
||||||
|
|
||||||
| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API |
|
| 模块 | 文件 | 独占职责 | 对外封闭面 | 消费依赖 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| **D1 HUD**(呈现面拆分持续换代:组合根 main.gd + 三屏壳(MenuScreen/CampScreen/AdventureScreen)+ views/ 视图单元(现行承载面见「呈现层装配与会话生命周期」节;早期 9 单元清单与 LevelStripView 已随场景换代退役)+三画面件内部数据类=宿主画面登记表(关卡地图屏 `_MapState`/战末弹层 `_EndOverlayState`/调试浮窗 `_DebugState` 各 14 字段公开数据成员,文件外零消费者,sweep 断言承载);营地面=场景根+四子界面功能窗口+Esc 浮窗+顶栏 HUD 栏〔四柜台覆盖层已退役〕) | 全部 Control/CanvasLayer(例外:BoardView 棋盘本体与 BattleStageView 站桩本体 = Control 壳 + SubViewportContainer + SubViewport + Node2D 世界〔BoardWorld/CellUnit;StageWorld/StandeeBody——B 区 slot_row 伴随件留壳层〕,探针契约面不变)、输入→意图翻译(**唯一提交路径 = settle_batch,不直调 A3**)、呈现义务状态记录(A2×6 / B2×4 / B3×4 / B4×5 / B1×3) | 视图单元接口(信号外发、setter 只读注入);组合根交接面=公开服务面 18(refresh_presentations/sync_status_entry/fatal_screen/quit_game/begin_session/start_debug_levels/check_board_hints/show_board_fx_for_node/replay_locked_click/sync_settlement_visuals/wire_battle/sync_debug_overlay/open_settings/open_save_select/status_data/gp_summary_text/seed_value/current_master_seed)+句柄读投影/设置口 12(set_treasure_ui/treasure_ui/set_bonus/bonus/set_camp_pres/camp_pres/set_debug/debug/set_tune_sim/tune_sim/set_confirm_consumer/set_confirm_consumer_slot)+on_* 处理器保私有经 Callable 束交付(束参=main_ui_build.build 31 键、main_adventure_flow.wire_adventure 2+6 键);指标例外=main.gd 公开方法 32 落 gdstyle 基线(先例=level_runner 33 在册);UiKit 三工厂(gradient_base/beams_rect/switch_toggle)公开化 | A2 compute_move_path / ActionOutcome;A3 ap/rap;B1 步骤流行协议(数据源);ConfigDB display_name | **MEDIUM**:Control / CanvasLayer / draw_* / InputEvent / RichTextLabel——对照 breaking-changes.md 4.5–4.7 条目(CanvasItem 线条无抗锯齿羽化、设备 ID 常量、RichTextLabel 图片参数两轮变化) |
|
| **D1 HUD** | `game/presentation/main.gd`(组合根)+三屏壳+`views/` 视图单元族+`ui_registry.gd` | 全部 Control/CanvasLayer;输入→意图翻译(**唯一提交路径=settle_batch,不直调 A3**);组合根=信号接线与核心写调用唯一出口;views/ 各域呈现拆件的职责与接口归各件头注 | 组合根公开服务面与注册面句柄寻址合同(`main.ui.<域容器>.<句柄>`)归 main.gd / ui_registry.gd 头注承载 | A2 compute_move_path;A3 只读;B1 步骤流;ConfigDB display_name;**MEDIUM**:Control/CanvasLayer/draw_*/InputEvent/RichTextLabel |
|
||||||
| **组合根拆件**(呈现侧写口子件:curio_interact_controller / camp_shop_presenter / treasure_interact_controller) | 代组合根执行核心写调用(冒险节点后续推进/营地购买与刷新/道具使用——依赖与回调由 main 构造注入) | 各拆件的写入口(仅组合根装配面可达;视图零直连) | 构造注入的核心写引用(推进/商店/道具各域——详见各拆件头注) | 无 |
|
| **组合根拆件** | `game/presentation/*_controller.gd` / `camp_shop_presenter.gd` | 代组合根执行核心写调用(冒险节点推进/营地购买与刷新/道具使用) | 各拆件写入口(仅组合根装配面可达;视图零直连) | 构造注入的核心写引用 |
|
||||||
| **ui_registry**(`presentation/ui_registry.gd`,界面注册面,已建件) | 呈现层接口面唯一承载:层序合同(LAYER_CONTRACT)迁驻与合同寻址、三域句柄容器 ui_screens(9 屏壳与覆盖层句柄)/ui_battle(5 战区句柄)/ui_modals(模态句柄按域分三子容器——局内冒险域 run/菜单与跨语境域 menu〔两子容器〕/营地域 camp=既有 UiCampModals〔六句柄、两段式寻址 `modals.camp.*`〕,三子容器纯字段、两段式寻址 `modals.run.*`/`modals.menu.*`/`modals.camp.*`)+模态编排件 ModalFlow 直驻本面(自 UiModals 升格 UiRegistry 直持);层序合同营地槽=camp_scene+四子界面+camp_esc_overlay(camp_overlay 已退役);组合根经其一级寻址接线,探针挂载假设迁移为 `main.ui.<域容器>.<句柄>` | 三容器属性+flow+合同寻址口(RefCounted 门面,不挂树、零会话期引用);register_layer 迁驻注册面;四件类变量 UiRegistry 4/UiScreens 9/UiBattle 5/UiModals 3(run/menu/camp 三子容器纯字段——ui_modals 平铺面清零,分域纪律册级化);ModalFlow 随 UiRegistry 构造建立(注册面构造点先于装配) | 构造注入:三屏壳、覆盖层、战区句柄、ModalFlow(main_ui_build 交付随之改型) | 无(RefCounted) |
|
| **HudPresenter** | `game/presentation/hud_presenter.gd` | 战斗屏数据投影+文案拼装静态族(核心状态→呈现文案的全部翻译集中于此) | refresh 全量重查装配+只读静态投影族 | 只走 `settlement.presentation_snapshot()` 成文快照面(禁链式穿透) |
|
||||||
| **UiCampModals**(`presentation/ui_camp_modals.gd`,营地域句柄子容器,已建件) | ui_modals 营地域六句柄唯一容器(场景根/四子界面/Esc 浮窗/HUD 栏),句柄寻址两段式 `modals.camp.*`;ui_modals 平铺面已清零(分域纪律册级化) | 子容器属性+六句柄只读投影;main_ui_build 装配交付 | 构造注入(六视图句柄);ui_modals(父容器挂载) | 无(RefCounted) |
|
| **board_resolvers** | `game/presentation/board_resolvers.gd` | 棋盘每格渲染数据只读解析回调四函数(与无态静态投影族职责互斥) | 构造注入产出绑定 Callable 供组合根接线 | ConfigDB / 结算活态取值 Callable |
|
||||||
| **CampSceneView**(`views/camp_scene_view.gd`,营地场景根视图,已建件) | 营地场景图唯一呈现件:十层贴图铺底(层序按 layout 表 z 序;`camp_scene_layout.tres` fail-fast 校验+七命中区几何红线——camp_scene_layout_test 承载)、七物件命中区命中即发 object_pressed(组合根路由大门/篝火/笔记本/四界面)、反参照纪律(场景根零文字按钮)、登记模态初始隐(boot 态不盖菜单) | 构造注入(贴图经 `UiKit.TEX_CAMP_*`、layout 表经 ConfigDB 表现域容器);object_pressed 信号外发;open/close 经营地域子容器寻址 | camp_screen(宿主挂载);ConfigDB;组合根(路由消费) | Control+TextureRect 树 |
|
| **battle_presentation**(B5,垂直切片后) | — | 结算动画 / 伤害数字 / 战斗舞台 | (契约规范源:`../../gdd/systems/战斗循环/战斗表现.md`——前置「战斗表现美术测试」锁双舞台陷阱) | B1 步骤流、D1;**MEDIUM**:AnimationPlayer/Tween |
|
||||||
| **营地四子界面视图**(`views/camp_sub_view_base.gd`+forge_view/tree_view/treasure_view/codex_view,功能窗口公共壳+四件,已建件) | 营地五功能窗口的四个承载视图(锻造工坊/天赋树/秘宝匣/图鉴)+公共壳(窗口壳/行板/关闭钮;生涯页挂笔记本路由不经此族);模态栈单口 open/close、五窗互斥单开;presenter 承接面零回表(树购买/锻造三意图经既有写口族) | 各 view open/close+意图信号外发;关闭钮 pressed | camp_shop_presenter/MetaProgression 写口(经组合根);CampRefreshBus(刷新广播消费) | Control |
|
| **audio**(D4,Alpha) | — | 音频挂点 | 挂点=B1 明细行类型流(负反馈聚合——单结算至多一次) | B1 流水 |
|
||||||
| **camp_esc_overlay+MainEscFlow**(`views/camp_esc_overlay.gd`+`presentation/main_esc_flow.gd`,Esc 浮窗视图+四态路由件,已建件) | Esc 浮窗三钮视图(返回主菜单/设置/退出)+Esc 四态路由静态件(根态唤起/再按关窗/功能窗开着先关最上层窗〔camp.md v2.3 定稿〕/设置开态不误关;菜单语境不唤起);**main._unhandled_input=产品码首个键盘输入入口**(契约 9——事件驱动、禁 Input 轮询、不挂 ui_cancel、pressed 非 echo) | flow.open/close 路由口;三钮 pressed 意图信号(经组合根接线);入口方法公开化(main 转发调用的入口去下划线——on_esc_input/is_camp_context 先前已公开) | 组合根(_unhandled_input 前置与意图消费);模态栈(关窗单口);screen_flow(设置/返回动线) | Control+静态件 |
|
| **tutorial**(D5,Alpha) | — | 教学条目 | 口径来源=A2/A3/B3/B1 各教学条目 | 各上游 |
|
||||||
| **CampHudBand**(`views/camp_hud_band.gd`,营地顶栏 HUD 件,已建件) | 顶栏 48px 全宽窄条:钥石余额 badge 唯一呈现(单口取现值、显式刷新才变);set_hud_band 预留位落座 | badge 文本投影;refresh 时取现值 | CampRefreshBus(挂册广播);MetaProgression 钥石读 | Control |
|
|
||||||
| **CampRefreshBus**(`views/camp_refresh_bus.gd`,营地刷新单口件,已建件) | 营地刷新单口唯一承载:进档尾与营地写口尾触发 refresh 广播(八写口尾改路由),现开界面与 HUD 同步取现值 | 挂册/refresh 广播 | 组合根(触发点接线);四子界面与 CampHudBand(消费) | 无(RefCounted 信号件) |
|
|
||||||
| **board_hover**(`views/board_hover.gd`,悬停预承诺呈现域件,已建件) | 悬停反馈域唯一承载:三语义光标、目标格边框、BFS 路径预览、chord 双击首遇锚;_r0 出生展开区成员留宿主 | 构造=引用束注入 7 项(cells/minesweeper/diggable 引用+格命中换算/光标写入/hover_forbidden/chord_attempted 四 Callable);三入站口留宿主委托;hover_probe 读面留宿主;公开方法面 7(七口公开化——rebind/reset/refresh_after_paint/hover_at/detect_chord/on_shell_mouse_exited/hover_pos) | board_view(宿主);输入事件经宿主入站口 | 无(RefCounted) |
|
|
||||||
| **cell_base_layer/cell_mark_overlay**(`views/`,单格两绘制域件,已建件) | 单格绘制域拆分(入参与该层绘制命令同件):基座层(底面/描边/立面/投影/接触带/倒角,12 成员)与标识叠加层(标记/字形/徽章/点迹/高亮/退色,14 成员);徽章遮罩走构造交付 Callable(`_mask_set`);宿主 _draw 退为六步时序器,宿主实测类变量 10 | 构造注入;绘制命令由宿主 _draw 按层序调用 | board_cell_unit(宿主);gdstyle 键各文件独立计数(12/13 均 ≤15) | 无(RefCounted) |
|
|
||||||
| **standee_vitals/standee_motion**(`views/`,站桩两状态件,已建件) | 站桩状态域拆分:身份命值(hp/atk/状态值族,12 成员)与资产演出(动作/姿态/位移演出族,11 成员);三个演出探针计数器留宿主,宿主实测类变量 10 | 构造注入;st(沿用)/mo 两实例由宿主持有;公开方法面 vitals 14/motion 14(站桩两状态件公开面换代,成员计数零增) | standee_body(宿主);battle_stage_view 写入面逐字保持 | 无(RefCounted) |
|
|
||||||
| **HudPresenter**(`presentation/hud_presenter.gd`) | 战斗屏**数据投影+文案拼装静态族**——核心状态→呈现文案的全部翻译集中于此(B/C/D 区文案与投影),静态无状态 | `refresh(…)` 全量重查装配(组合根每次动作/结算返回后调用,漏调即陈旧呈现)+只读静态投影族 | 核心读取只走 `settlement.presentation_snapshot()` 成文快照面(禁链式穿透结算内部);ConfigDB display_name | 无(RefCounted 静态) |
|
|
||||||
| **board_resolvers**(`presentation/board_resolvers.gd`) | 棋盘每格渲染数据的只读解析回调四函数(奖励徽章身份——挖掘期 Active 相位内、地形变异数字遮蔽与角标、调试加成生效值)——有态绑定件,与无态静态投影族 HudPresenter 职责互斥 | 构造注入 db、调试浮窗与结算活态取值,产出绑定 Callable 供组合根接线 | ConfigDB / DebugOverlay / 结算活态取值 Callable | 无(纯投影) |
|
|
||||||
| **main_ui_build**(`presentation/main_ui_build.gd`) | `_build_ui` 八步拆分件——组合根 UI 装配分步承接(三屏壳实例化、视图句柄接线、覆盖层装配与模态编排注入按步拆开);main 侧留同名薄委托,装配序与 z 序零改动 | 分步静态函数(成员访问经 root 显式传入);入口方法公开化(main 转发调用的入口去下划线) | 层序逻辑不在此件——唯一事实源=`ui_registry.LAYER_CONTRACT`+`ui.apply_layer_contract(root)`(已迁驻注册面) | 同 D1(Control 装配面) |
|
|
||||||
| **main_adventure_flow**(`presentation/main_adventure_flow.gd`) | main 冒险流程族——菜单开局/续玩后的冒险编排接线、节点事件分发、终局面与选路屏开合;逐字搬运,main 侧留同名薄委托(探针 `main.X` 路径零迁移) | 流程静态函数(root 显式);入口方法公开化(main 转发调用的入口去下划线) | 局态全局住 run_scope 节点——本件零成员态、零新增信号连接(连接语句随原段搬运) | 无 |
|
|
||||||
| **main_overlay_flow**(`presentation/main_overlay_flow.gd`) | main 浮层流程族——设置/状态面板/生涯页/选档界面/图例/钱包事件的开合与数据投喂;逐字搬运,main 侧留同名薄委托 | 流程静态函数(root 显式);入口方法公开化(main 转发调用的入口去下划线) | 全部开合走组合根模态编排口(`root.ui.flow.open/close`——ModalFlow 自 UiModals 升格 UiRegistry 直驻)——本件零成员态 | 同 D1 |
|
|
||||||
| **main_debug_flow**(`presentation/main_debug_flow.gd`) | main 调试流程族——调试浮窗开合与上下文同步、批量模拟入口、两层调试对局起手、诊断转储;逐字搬运,main 侧留同名薄委托 | 流程静态函数(root 显式);入口方法公开化(main 转发调用的入口去下划线) | 调试会话状态机归 debug_session.gd——本件只接线与出 UI,零成员态 | 同 D1 |
|
|
||||||
| **TilePalette**(`presentation/views/tile_palette.gd`) | 瓦片排版/装载:高墙/地面瓦片整批装载与运行时镜像合成、地板明度归一、数字墨族按板自适应判据、格坐标确定性散列与十六正交情形墙瓦片查表 | 查表族(读件持棋盘引用——棋盘视图 rebuild 经 `bind_board` 同步);装载缓存七成员持于件内(同板型零重载、换板重载时序同源) | 零绘制面、零玩法数据写入(绘制调用面留棋盘视图);纹理路径单点在件内 | Resource 纹理加载——LOW |
|
|
||||||
| **HeroSprite**(`presentation/views/hero_sprite.gd`) | 英雄精灵四态与落位装配(落位与位移演出、撞墙帧闪、挖掘弹跳、脚底锚与持握手位出口) | 由棋盘视图 `_init` 建为子件(注入世界根与壳层容器引用)——精灵本体经世界根 ensure_hero 建于 SubViewport 世界内,本件只驱动其状态 | BoardWorld 世界根;素材缺位=零精灵(棋盘视图字形「人」回退路径在役) | Node2D / create_tween(Tween 系 Node 方法——MEDIUM 域对照 breaking-changes.md) |
|
|
||||||
| **BoardWorld**(`presentation/views/board_world.gd`) | 棋盘 Node2D 世界根(SubViewport 内 CellUnit 容器):世界级去饱和材质与字体注入挂点、英雄精灵持有位;封印印记=参数化绘制子件 seal_mark_layer(CellUnit 新公开属性 `seal_on`:on 才建/off 撤/edge 重注入/fog_state 联动;棋盘侧 tex_seal 贴图槽退役——`seal_mark.png` 只余战末蜡封贴图专用) | 无 class_name——使用方经 preload 引用挂树 | BoardView 壳层(SubViewportContainer + SubViewport 结构不变) | Node2D/SubViewport——同 D1 |
|
|
||||||
| **battle_presentation**(B5,垂直切片后) | 结算动画 / 伤害数字 / 战斗舞台 | (契约规范源:`../../gdd/systems/战斗循环/战斗表现.md`——前置「战斗表现美术测试」锁双舞台陷阱) | B1 步骤流(回放脚本源)、D1 | **MEDIUM**:AnimationPlayer(String→StringName 变更)/ Tween |
|
|
||||||
| **audio**(D4,Alpha) | 音频挂点 | (挂点 = B1 明细行类型流;负反馈聚合——单结算至多一次) | B1 流水 | AudioStreamPlayer(4.7 area_mask 默认 1→0 注意) |
|
|
||||||
| **tutorial**(D5,Alpha) | 教学条目 | (口径来源:A2/A3/B3/B1 各教学条目) | 各上游 | 无 |
|
|
||||||
|
|
||||||
**依赖单向性**:上层可消费下层,禁止反向(C3 禁调用 A1 生成、D1 不直调 A3、A2/B3/B4 零相互直调)。全项目唯一回边 = A2 事件订阅面。
|
**依赖单向性**:上层可消费下层,禁止反向(C3 禁调用 A1 生成、D1 不直调 A3、A2/B3/B4 零相互直调)。全项目唯一回边=A2 事件订阅面。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 呈现层装配与会话生命周期
|
## 呈现层装配与会话生命周期
|
||||||
|
|
||||||
### 三屏壳与组合根句柄面
|
### 三屏壳与组合根
|
||||||
|
|
||||||
- 呈现场景拆为三屏壳:MenuScreen(开始菜单屏)/CampScreen(营地屏)/AdventureScreen(冒险屏——内含关卡地图与战斗两容器)。
|
- 呈现场景拆为三屏壳:MenuScreen(开始菜单屏)/CampScreen(营地屏)/AdventureScreen(冒险屏——内含关卡地图与战斗两容器)。
|
||||||
- 屏成员寻址迁经界面注册面(**已建件**):探针挂载假设 `main.X` 迁移为 `main.ui.<域容器>.<句柄>`(ui_screens/ui_battle/ui_modals 三域容器);main.gd 实测类变量 15,注册面形态见「模块归属·呈现层」表 ui_registry 行;ModalFlow 实例随 UiRegistry 构造建立(注册面构造点先于装配);取证探针 shot_probe/fx_shot_probe 已改址;局态一律住 RunScope 节点,禁在屏/视图侧持有局态引用。
|
- 屏成员寻址经界面注册面(ui_registry):探针与消费方走 `main.ui.<域容器>.<句柄>` 合同寻址;句柄清单与合同细节归 ui_registry 头注承载。
|
||||||
- **组合根拆件**=组合根构造注入、代组合根执行核心写调用的呈现侧子件(现行三件:curio_interact_controller/camp_shop_presenter/treasure_interact_controller——冒险节点后续推进、营地购买与刷新、道具使用)。视图禁直连拆件;核心写调用的可达路径仍是「视图→信号→组合根(含拆件)→核心」,依赖规则与组合根单点装配不变。成员见「模块归属·呈现层」表。
|
- 局态一律住 RunScope 节点,禁在屏/视图侧持有局态引用。
|
||||||
|
|
||||||
### 视觉层装配合同
|
### 视觉层装配合同
|
||||||
|
|
||||||
- **树序 = 登记序 = z 序**,同源派生;层序唯一事实源 = `main.gd` 的 `LAYER_CONTRACT` 常量表(kind 五类:shell=屏壳〔成员随壳不占独立树位〕/modal=模态层〔入登记册,tags 随登记〕/state=全屏态/node=非视觉节点/float=不注册 ModalStack 的最顶浮层〔任何 UI 打开都不遮挡它〕)。
|
- **树序=登记序=z 序**,同源派生;层序唯一事实源=`main.gd` 的 `LAYER_CONTRACT` 常量表(kind 五类:shell/modal/state/node/float)。
|
||||||
- 全仓唯一落位口 = `_apply_layer_contract()`(装配尾统一排序+登记);散落 `move_child` 由冒烟 V1d 源码断言判红;**改层序只改合同表**。
|
- 全仓唯一落位口=`_apply_layer_contract()`(装配尾统一排序+登记);散落 `move_child` 由冒烟源码断言判红;**改层序只改合同表**。
|
||||||
- 具体层清单不复制进本文(双写失同步禁令)——查现行层项直接读 `main.gd`。
|
- 具体层清单不复制进本文(双写失同步禁令)——查现行层项直接读 `main.gd`。
|
||||||
|
|
||||||
### 会话生命周期(RunScope)
|
### 会话生命周期(RunScope)
|
||||||
|
|
||||||
- `run_scope.gd` = 纯状态承载 Node:零信号连接、零视图构建、零核心写调用(连接只在组合根,组合根经 `run_scope.X` 读写)。
|
- `run_scope.gd`=纯状态承载 Node:零信号连接、零视图构建、零核心写调用(连接只在组合根,组合根经 `run_scope.X` 读写)。
|
||||||
- 会话更替机制:`_begin_session()` 新建会话节点挂树、旧会话节点**整节点 `queue_free()`**——无独立收束函数,跨局字段清理靠节点释放机制(新增跨局字段零新增泄漏点);`_ready` 即建闲时会话,`run_scope` 永非 null。
|
- 会话更替机制:`_begin_session()` 新建会话节点挂树、旧会话节点**整节点 `queue_free()`**——无独立收束函数,跨局字段清理靠节点释放机制。
|
||||||
- **存活性矩阵**(九阶段 × 五引用面,2026-10-17 用户裁认账阶段划分;执行判据=冒烟 V3a–V3i):
|
- **存活性矩阵**(九阶段 × 五引用面;执行判据=系统测试 V3a–V3i):
|
||||||
|
|
||||||
| 阶段 | run_scope | adventure | runner | settlement |
|
| 阶段 | run_scope | adventure | runner | settlement |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
@@ -222,118 +167,31 @@
|
|||||||
| ④ 结算后(胜利停点)/⑤ 选路页 | 在树 | alive | alive | both |
|
| ④ 结算后(胜利停点)/⑤ 选路页 | 在树 | alive | alive | both |
|
||||||
| ⑥ 终局面 | 在树 | alive | alive | null |
|
| ⑥ 终局面 | 在树 | alive | alive | null |
|
||||||
| ⑦ 回菜单收束 | 新闲时会话即刻在树(旧会话已释放——无真空窗) | null | null | null |
|
| ⑦ 回菜单收束 | 新闲时会话即刻在树(旧会话已释放——无真空窗) | null | null | null |
|
||||||
| ⑧ 各模态开合后(设置/生涯/营地/调试) | 闲时会话零扰动 | null | null | null |
|
| ⑧ 各模态开合后 | 闲时会话零扰动 | null | null | null |
|
||||||
| ⑨ 两连局+续玩断点 | 换全新会话在树 | alive | both | both |
|
| ⑨ 两连局+续玩断点 | 换全新会话在树 | alive | both | both |
|
||||||
|
|
||||||
- 三态记号沿用冒烟参数:**alive**=应有实例、**null**=必须缺位(实测非空判红)、**both**=按分支可空可活(如胜停点后走向选路或直接终局)。对象有值但已失效一律判「悬挂」红。
|
- 三态记号:**alive**=应有实例、**null**=必须缺位(实测非空判红)、**both**=按分支可空可活。对象有值但已失效一律判「悬挂」红。
|
||||||
- 第五引用面=四持句柄件(`_treasure_ui`/`_bonus`/`_camp_pres`/`_modal_flow`,另有 `_row_pacer`):其会话取值 Callable 与 `run_scope` 成员**逐面同源比对**(回调悬挂=两值不等即红),会话更替零残留由矩阵每阶段顺带铁证。
|
|
||||||
|
|
||||||
### 模态编排(ModalFlow/ModalStack)
|
### 模态编排(ModalFlow/ModalStack)
|
||||||
|
|
||||||
- `modal_flow.gd` = 模态编排纯逻辑类(依赖仅 ModalStack + 查询 Callable,可直接 `new()` 单测):开合编排(遮挡记账单口 + 演播后排窗挂起)/棋盘输入锁谓词/角标置灰谓词三职责。
|
- `modal_flow.gd`=模态编排纯逻辑类:开合编排(遮挡记账单口+演播后排窗挂起)/棋盘输入锁谓词/角标置灰谓词三职责;可直接 `new()` 单测。
|
||||||
- 互斥排除语义随层登记(`register(node, tags)`):`debug_overlay=["non_locking"]`、`level_screen=["screen_state"]`,其余层零标签。
|
- 互斥排除语义随层登记(`register(node, tags)`);其余层零标签。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 测试与质量域
|
## 测试与质量域
|
||||||
|
|
||||||
> 定位:本节为测试域(本地闸、探针、静态扫描等横切关注点)的**事实源**。全量验证=合回后远端 CI(唯一强制全量验证点,post-merge 钩子推送触发、按改动域分流);开发期义务=`process-conventions.md` §4 改完即测(改完即测自己改过的面、读数在案),判定严密性即全仓质量下限。第三方测试框架(gdUnit4)经 2026-09-12 评估不引入,现行测试载体=本节自制闸体系。
|
> 定位:本节只写测试域的架构事实。测试工具手册与各闸判定口径的事实源=`game/tests/README.md`;闸清单与改动域划分的唯一出处=`tools/run_all_gates.sh`(脚本即清单);测试怎么写、怎么算合格=`design/engineering/test-conventions.md`;静态扫描域 S 系规则的规则全集与动机=`game/tests/README.md`「Static Scan」节。全量验证=合回后远端 CI;开发期义务=改完即测(process-conventions §4)。
|
||||||
|
|
||||||
### 模块归属
|
### 测试域依赖约束
|
||||||
|
|
||||||
| 模块 | 载体 | 独占职责 | 对外暴露 | 判定口径 |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| **run_smoke**(冒烟测试运行器) | `tools/run_smoke.py` | 冒烟测试总入口与判定权:headless 以项目运行目标拉起 `res://tests/smoke_boot.tscn`(极小启动场景——autoload 在位、配置表全载、主屏实例化,零逻辑判定)+ 三闸判定 | 进程退出码(0=PASS / 1=FAIL) | 三闸齐备、判定无洞:①退出码 = 0;②摘要行「[smoke] 摘要:N 项检查,0 项失败」在案且失败数为 0;③输出扫 `SCRIPT ERROR` / `Parse Error` 标记行。外部 wall-clock 超时在位(超时 = FAIL) |
|
|
||||||
| **run_system_test**(系统测试运行器) | `tools/run_system_test.py` | 系统测试总入口:headless 跑真实玩法路径断言面(宿主=`res://tests/system_test.gd`)+ 三闸判定(口径同 run_smoke,摘要行兼容两种宿主格式) | 进程退出码(0=PASS / 1=FAIL) | 三闸齐备(同 run_smoke:退出码/摘要失败数/脚本错误扫描;wall-clock 超时在位) |
|
|
||||||
| **run_all**(单元与集成测试) | `game/tests/run_all.gd` | 64 套统一入口(61 单元+3 集成,2026-10-28 实数):套件 manifest 逐条「套件 → 期望退出码」,致命类 expect=1 独立子进程实跑;`negative` 字段标负面套件(仅豁免错误扫描一闸);选跑态 `--only=<词[,词…]>`(直跑形态对套件路径子串匹配只跑命中套件,零命中=用法错 quit(2),仅供开发期最窄确认——不产闸回执、不作验收凭据,批末全量闸不经选跑分支) | 逐套件结果 + 汇总退出码(任一套件失败 quit(1)) | 套件级退出码协议在位;三硬闸齐备(入口内扫子套件输出 + 编排层扫 `unit.log`;`Kit.finish` 零断言返回专用码 2)。子进程输出须经系统命令解释器重定向落盘再读——`OS.execute` 的输出管道在本机恒空 |
|
|
||||||
| **probe_gate**(场景探针) | `tools/probe_gate.sh` | headless 场景探针段编排(单一形态十件恒跑):ui_input_probe / ui_struct_probe / layout_probe / ui_contrast_probe / **screen_flow_probe**(屏壳切换)/ ui_click_probe(行为走查)/ ui_probe / ui_tune_probe / t17_defer_probe / fx_probe;孤儿 Godot 预清 + 批末残留清点(必须 0) | 段级 FAIL 输出 + 汇总退出码 | 每段 timeout 守卫在位(挂死 124/137 = FAIL,不静默);判定统一走 `verdict` 函数——退出码为唯一权威判据,PASS 串降级为附加判据,逐段跑 `tools/error_scan.py` |
|
|
||||||
| **render_gate**(视觉 golden) | `tools/render_gate.sh` | 窗口化渲染闸:①shot_probe 七屏截图 → shot_checker A-D 语义断言;②fx_shot_probe / board_shot_probe 取证(超时/零字节/文件缺失任一 = FAIL);③棋盘 golden 逐像素容差比对(差 ≤16 / changed ≤2%,provisional)+ 菜单 golden;④批末孤儿残留清零;⑤三段探针日志逐段脚本错误扫描 | 段级 FAIL 输出 + 汇总退出码 | 查退出码在位(每段 timeout 守卫 + 退出码/取证文件双检);SCRIPT ERROR 扫描在位(逐段 `tools/error_scan.py`,标记与 run_smoke 同源);断言数下限不适用(判定主体 = golden 容差与取证文件存在性,非断言计数) |
|
|
||||||
| **static_scan**(静态扫描域) | `game/tests/static_scan.sh` | 静态扫描域 S1–S10 可执行载体(grep 规则 + `tools/audit_type_hints.py`〔S9〕+ `tools/audit_file_headers.py`〔S10〕) | fail 聚合退出码(任一硬失败规则命中即 exit 1) | 查退出码在位;SCRIPT ERROR 扫描与断言数下限不适用(逐规则命中即红,无运行时错误面与断言计数);S3 现为 warning 级、不参与 fail 判定(见下表) |
|
|
||||||
|
|
||||||
### 改动域划分(2026-10-17 用户裁「代码批只跑代码闸、文档批只跑文档闸」)
|
|
||||||
|
|
||||||
| 域 | 闸 | 本批改动落在这些路径即属该域 |
|
|
||||||
|---|---|---|
|
|
||||||
| **代码域** | run_smoke、run_system_test、run_all、probe_gate、render_gate、static_scan | **唯一触发=`game/` 下非 `.md` 的行为载体**(代码、测试脚本、探针、场景、数据表、素材)。`game/` 内的 `.md`(README、生成清单)归文档域——2026-10-26 用户裁:判据按文件性质,不按路径前缀。2026-10-18 用户裁「跨领域执法禁绝」后,`tools/`、`artwork/` 两前缀不把改动拉进代码域 |
|
|
||||||
| **文档域** | 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 都不比。
|
|
||||||
|
|
||||||
### 车道分层执法(2026-10-31 用户裁「一切改动走 worktree」)
|
|
||||||
|
|
||||||
一切改动走独立 worktree,主工作区只作合并落点。执法全机械——判据只有 git 图与路径(豁免面 `.zcode/`、`.qoder/` 不入 git,主区直改),不含「改动大小」等语义判断。
|
|
||||||
|
|
||||||
| 执法层 | 载体 | 职责 | 判据 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| **worktree-guard**(ZCode PreToolUse) | `.zcode/hooks/worktree-guard.sh`(本机件,不入 git) | agent 侧车道纪律:主工作区 Edit/Write 与主区非 merge `git commit` 拦截(豁免 `.zcode/`、`.qoder/`;worktree 内目标快速放行;合并收尾提交凭 MERGE_HEAD 豁免);`git commit --no-verify` 拦截(该旗标仅属用户);iter 分支合回一卡一提交数卡校验;规则闸 | 路径性质+分支名+MERGE_HEAD+git 图 |
|
|
||||||
|
|
||||||
验证收拢为合回后远端 CI(post-merge 钩子推送 origin master 触发 Gitea Actions,runner=Mac 本机 host 模式;按改动域分流,分流单点=tools/ci/domain_route.sh),commit 点零执法;主工作区防污染由 ZCode 层守卫承担——只约束 agent,用户手工改动不受限。子代理覆盖面(2026-10-26 冷启动评估实测):子代理的工具调用不经过 ZCode 层守卫——ZCode 层实际只覆盖主会话工具调用;残余暴露面=子代理写主工作区与蓄意 `--no-verify`(该旗标整族跳过 git 层钩子),属故意越权而非遗忘型失误,与防遗忘的设计目标正交。
|
|
||||||
|
|
||||||
### 三条判定硬闸现行状态
|
|
||||||
|
|
||||||
| 硬闸 | run_smoke | run_system_test | run_all | probe_gate | render_gate | static_scan |
|
|
||||||
|---|---|---|---|---|---|---|
|
|
||||||
| **退出码优先** | 已落实(闸①) | 已落实(闸①,口径同 run_smoke) | 已落实(套件 manifest expect 协议) | 已落实(`verdict` 函数逐段判退出码,PASS 串不作判据) | 已落实(段级退出码 + 取证双检) | 已落实(fail 聚合退出) |
|
|
||||||
| **SCRIPT ERROR 扫描** | 已落实(闸③,外部扫描——GDScript 无脚本错误陷阱 API,闸设在外部包装) | 已落实(闸③,标记清单与 run_smoke 同源) | 已落实(入口内扫子套件输出;子进程的 stdout/stderr 须先落盘——`OS.execute` 管道在本机恒空) | 已落实(逐探针段 `tools/error_scan.py`,标记与 run_smoke 同源) | 已落实(三段探针日志逐段 `tools/error_scan.py`,标记与 run_smoke 同源) | 不适用(静态域无运行时错误面) |
|
|
||||||
| **断言数下限** | 无独立下限(闸②摘要行必须在案,防「跑一半仍 PASS」;脚本错误吞断言路径由闸③兜住) | 同 run_smoke(过渡期宿主摘要行必须在案) | 已落实(`Kit.finish` 零断言返回专用退出码 2——与「断言失败=1」区分,防致命类套件的 expect 协议放过) | 已落实(退出码 0 但无该探针签名标记亦判红——防静默退出) | 不适用(golden 容差 + 取证存在性判定) | 不适用(逐规则命中判定;另有扫描面为空即判红的零命中自检) |
|
|
||||||
|
|
||||||
背景事实(run_smoke 头注在案):GDScript 运行时脚本错误不改进程退出码、不计入冒烟失败数、且静默中断所在函数剩余断言——实证:「309 项 0 失败」实为断言未跑全。这是 SCRIPT ERROR 扫描必须存在于判定层的原因。
|
|
||||||
|
|
||||||
### 静态扫描域 S1–S13 承接清单
|
|
||||||
|
|
||||||
静态扫描域规则(2026-09-12 立,沿革见 git commit log;下表为现行事实登记):
|
|
||||||
|
|
||||||
| # | 规则 | 状态 |
|
|
||||||
|---|---|---|
|
|
||||||
| S1 | 玩法代码禁 `randomize()`、自建 `RandomNumberGenerator`(D2 Rule 5) | **在位**(硬失败;扫描面 game/core + game/presentation)。非产品码三目录(`game/tests`/`game/probe`/`game/sim`)不进本闸与 S2——它们自建且**显式定种**的随机源是合法测量口径(同种子对拍改前改后读数),禁的是不定种形态;适用域分档与无机器闸的理由见 code-conventions §4 第 13 条(2026-11-03 架构审查 P1 余项裁:不扩扫描面,人工评审承载) |
|
|
||||||
| S2 | 禁全局随机函数 `randi()` / `randf()` / `randf_range()`——全局 RNG 绕开 RngService(specialist 补登) | **在位**(与 S1 同段硬失败;实例方法 `.randi()` 排除、`rng-seed-exempt` 豁免注记在案) |
|
|
||||||
| S3 | core/ 禁 ConfigDB 外 data 表加载(`load(` / `preload(` / `ResourceLoader.load`;schema class_name 直引豁免)(D2 Rule 2) | **在位**(warning 级——class_name 直引误报需人工复核;路径=`game/core`;豁免 config_db.gd 自身=数值单一事实源的正主)。2026-11-03 架构审查 P1 余项裁**维持 warning 级不升硬**:升硬的前提是先有可靠的直引误报排除判据,该判据未立;本行状态即事实源,禁在别处另列 |
|
|
||||||
| S4 | core/ 禁 `extends Control/Node2D`、禁 `.tscn` preload(D2 Rule 7) | **在位**(硬失败) |
|
|
||||||
| S5 | core/ 禁裸引用 autoload 全局标识符(`ConfigDB` / `RngService` 直接写 = --script 模式 parse error)——构造注入 only(specialist 升格) | **在位**(硬失败;形态=标识符后紧跟 `.` 的成员访问,排除注释行与字符串字面量) |
|
|
||||||
| S6 | core↔core 信号连接只许方法 Callable(禁 lambda 捕获 self);发射者禁持有订阅者反向引用 | **在位**(2026-10-25 落闸:内联 lambda 禁令机器闸——同行与跨行两形态、豁免注记 `s6-signal-exempt`、盘面零存量;「发射者禁反向引用」句静态判据不成熟,归人工评审面承接、不造弱判据) |
|
|
||||||
| S7 | B1 编排唯一性:B2/B3/B4 API 符号命中文件 ⊆ B1 文件集;A2/B3/B4 零相互直调(B1 AC-43) | **在位**(2026-10-25 落闸:符号清单×B1 域文件集,族内自调用豁免、豁免注记 `s7-b1-exempt`、缺位自检;全符号形态盘面零存量) |
|
|
||||||
| S8 | 结算路径 `await` 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) | **在位**(2026-10-25 落闸:B1 域文件集 await 零命中,排除注释与字符串;盘面零存量。清单单点=`static_scan.sh` 的 `B1_SET`,S7 的豁免名单由它派生。自检两件:①清单内文件缺位即红;②**目录域反向对账**——`game/core/settlement/` 实有 `.gd` 未登记进 `B1_SET` 即红(新段类忘登记=await 面静默失效)。反向对账只覆盖 settlement/:装板/授予/效果端口/掷格四件结算码住 `game/core` 根下,纯目录域覆盖不住,根下新增仍由本行「模块归属」B1 登记面+写卡段申报承接。本行后半句「字面量扫描=warning 级+人工三要素复核」为独立子项、仍归人工面 |
|
|
||||||
|
|
||||||
域外扩充五件:**S9** 类型闸(`tools/audit_type_hints.py`——产品码无类型容器/有值返回缺类型/参数缺类型;扫描面=产品码三目录);**S10** 文件头闸(`tools/audit_file_headers.py`——头注 `##` 载体+日期/变更叙事黑名单;扫描面=产品码三目录);**S11** 代码注释禁用词闸(扫描面=`game/` 全域 `.gd`/`.tres`/`.md`/`.json`/`.sh`,词表单点取 `design/gdd/术语表.md`);**S12** 效果引擎无状态化旧件零残留闸(扫描面=`game/` 全域 `.gd`/`.tres`,旧符号与旧 id 字面清单为脚本字面值);**S13** 第三方质量规则闸(`tools/gdstyle_gate.py`,钉 gdstyle v0.4.0;扫描面=产品码三目录,存量以 `tools/gdstyle_baseline.txt` 欠账簿登记,判定=基线外新键红、同键数值恶化红)。
|
|
||||||
|
|
||||||
S11/S12 扫描面覆盖全域,故 sim/probe/tests 的术语与旧件面**在册**;其余十一闸(S1–S10、S13)扫描面止于产品码,非产品码三目录不受约束——分档理由与各目录的运行期承接通道见 code-conventions §4 第 13 条。**防空转自检现行状态**(本文「三层承载与判定原则」要求扫描面为空即判红):S1–S8 与 S11/S12/S13 各自带空面或缺位自检;**S9/S10 两件已补齐同款自检**(`tools/audit_type_hints.py` 与 `tools/audit_file_headers.py` 缺目录或扫描面零个 `.gd` 一律判红,并绿时打印扫描面件数供核)。
|
|
||||||
|
|
||||||
### 三层承载与判定原则
|
|
||||||
|
|
||||||
测试分标准四级+UI 探针(2026-10-22 用户裁),各有在册承载与入闸方式(细目见 `game/tests/README.md`):
|
|
||||||
|
|
||||||
| 层 | 判什么 | 承载 | 入闸 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| 冒烟测试 | 这版活着吗(零逻辑判定) | `game/tests/smoke_boot.tscn/.gd` | `run_smoke.py`(冒烟测试闸) |
|
|
||||||
| 单元测试 | 领域类的原子行为对不对(从对外方法进、钉对外可观测面——写法判据归 test-conventions §8.2) | `game/tests/unit/` | `run_all.gd`(单元与集成测试闸) |
|
|
||||||
| 集成测试 | 跨系统闭环对不对 | `game/tests/integration/` | 同上(同一入口同一协议) |
|
|
||||||
| 系统测试 | 真实玩法路径断言面 | `game/tests/system_test.gd` | `run_system_test.py`(系统测试闸) |
|
|
||||||
| UI 探针+渲染 golden | 场景切换与观感 | `game/probe/*.tscn` 探针 | `probe_gate.sh`(场景探针闸)、`render_gate.sh`(渲染闸) |
|
|
||||||
|
|
||||||
**判定原则**:验收不能只是「跑一遍没崩」。三硬闸(退出码/脚本错误扫描/断言数下限)是判定的底线,
|
|
||||||
缺一即判定有洞;「日志里写着 PASS」不作判据。另有两类静默失效必须机制性防范——规则扫描面为空
|
|
||||||
(路径写错即恒零命中恒绿)与子进程输出丢失(本机 `OS.execute` 管道恒空),两者都以显式自检拦住。
|
|
||||||
|
|
||||||
### 依赖约束
|
|
||||||
|
|
||||||
测试域禁止反向依赖呈现层具体实现。五闸及其调用的探针场景、审计脚本只允许依赖两类边界:
|
测试域禁止反向依赖呈现层具体实现。五闸及其调用的探针场景、审计脚本只允许依赖两类边界:
|
||||||
|
|
||||||
1. **autoload 边界**——ConfigDB / RngService 的公开面(--script 模式不加载 autoload 且不注册全局标识符,测试文件自带显式实例化夹具);
|
1. **autoload 边界**——ConfigDB / RngService 的公开面(--script 模式不加载 autoload 且不注册全局标识符,测试文件自带显式实例化夹具);
|
||||||
2. **场景契约**——探针场景的信号外发面与视图单元接口(信号外发、setter 只读注入),禁直引呈现层实现内部(如 UiKit 工厂内部状态、BoardView 绘制细节)。
|
2. **场景契约**——探针场景的信号外发面与视图单元接口(信号外发、setter 只读注入),禁直引呈现层实现内部。
|
||||||
|
|
||||||
测试域是所有层的消费方,进入方式限于上述两类边界;除此之外的依赖方向一律与「模块归属」节依赖单向性同规。
|
测试域是所有层的消费方,进入方式限于上述两类边界;除此之外的依赖方向一律与「模块归属」节依赖单向性同规。
|
||||||
|
|
||||||
### 事实源声明
|
|
||||||
|
|
||||||
本节为测试域(测试载体、判定口径、静态扫描域)的事实源。新增违规案例仍须先补 static_scan 规则再修码(code-conventions 缺陷-规范对照表纪律)。
|
|
||||||
|
|
||||||
**S13 测量面豁免注销(2026-10-29 零豁免裁)**:tune_sim_controller 改 process_frame 信号常驻连接+步进状态机(每帧一局、帧相位逐点对齐,已建件);运行态收尾现行形态=run() 尾每批一次执行。
|
|
||||||
|
|
||||||
**S13 豁免第三条注销(2026-10-29 零豁免裁)**:RoundCycle/BattleFacts 两新件设计闭合(宿主实测 15,已建件,见「战斗编排域拆件定稿」节轴丁)。
|
|
||||||
|
|
||||||
**gdstyle 计数截断缺陷登记**:gdstyle v0.4.0 对文件内 inner class 的成员计数存在截断——内嵌类中带行尾注释的属性声明截断其后续成员计数(standee_body 实测 31 声明仅记 19、board_cell_unit 33 仅记 30)。基线登记值属欠估;闸机扫描与基线同源、判定口径自洽不误报,债的真值以实查为准——按真实口径设计(实数低于阈值,不依赖解析缺陷)。登记待办:向 gdstyle 上游报 issue(仍在册)。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 数据流
|
## 数据流
|
||||||
@@ -348,7 +206,7 @@ Input(鼠标)→ D1 输入翻译 → 意图对象 → A2.settle_batch(唯
|
|||||||
```
|
```
|
||||||
|
|
||||||
- 回合制下每帧只做:输入采样、呈现刷新、动效推进——**玩法状态只在意图事务内变更**(单意图帧输入收集:stop 点击终结当帧)。
|
- 回合制下每帧只做:输入采样、呈现刷新、动效推进——**玩法状态只在意图事务内变更**(单意图帧输入收集:stop 点击终结当帧)。
|
||||||
- 无跨线程玩法数据流(Godot 主线程假设,D2 EC13);A1 生成若引入 WorkerThread,join 必须先于任何快照切出(既定约束)。
|
- 无跨线程玩法数据流(Godot 主线程假设);A1 生成若引入 WorkerThread,join 必须先于任何快照切出(既定约束)。
|
||||||
|
|
||||||
### 2. 事件/信号路径(系统间通信,无紧耦合)
|
### 2. 事件/信号路径(系统间通信,无紧耦合)
|
||||||
|
|
||||||
@@ -356,29 +214,29 @@ Input(鼠标)→ D1 输入翻译 → 意图对象 → A2.settle_batch(唯
|
|||||||
A2 ──cell_revealed / flag_judged / round_end(棋盘路径)──▶ B1(轮 facts 缓冲)
|
A2 ──cell_revealed / flag_judged / round_end(棋盘路径)──▶ B1(轮 facts 缓冲)
|
||||||
A3 ──round_end(stopped 直发,payload 同构)──────────────▶ B1
|
A3 ──round_end(stopped 直发,payload 同构)──────────────▶ B1
|
||||||
B1 ──notify_settlement_done(next_round_mode) / notify_combat_end──▶ A3
|
B1 ──notify_settlement_done(next_round_mode) / notify_combat_end──▶ A3
|
||||||
B1 ──apply_effect / apply_damage / grant / 伤害单据 submit…──▶ B3/B2/B4(唯一调用方;段内伤害序=主角先手→逐敌还手→地图账殿后〔案C 2026-10-06〕)
|
B1 ──apply_effect / apply_damage / grant / 伤害单据 submit…──▶ B3/B2/B4(唯一调用方)
|
||||||
B1 ──install_board / retire_board──▶ A2 B1 ──generate(L,D)──▶ A1
|
B1 ──install_board / retire_board──▶ A2 B1 ──generate(L,D)──▶ A1
|
||||||
D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB display_name
|
D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB display_name
|
||||||
```
|
```
|
||||||
|
|
||||||
- **事件载体(已定)**:组合根直连信号接线 + B1 Waiting 相位触发(不依赖事件到达序);autoload 全局事件总线已否决(2026-09-12,沿革见 git 历史)——单线程回合制沿用组合根直连(KISS)。选型理由=可回放(架构原则 3):同步直连让调用顺序显式可见,「同种子逐位相同」才可断言;Godot 信号本身就是同步函数派发,全库不存在事件循环。事件驱动形态服务的是并发/IO 场景对外部不确定时序的反应性,与本作「顺序确定」的需求相反。
|
- **事件载体(已定)**:组合根直连信号接线 + B1 Waiting 相位触发(不依赖事件到达序);autoload 全局事件总线已否决(2026-09-12,沿革见 git 历史)——单线程回合制沿用组合根直连(KISS)。选型理由=可回放(架构原则 3):同步直连让调用顺序显式可见,「同种子逐位相同」才可断言;事件驱动形态服务的是并发/IO 场景对外部不确定时序的反应性,与本作「顺序确定」的需求相反。
|
||||||
- 事件规范序:A2 发射序 = 触发格 BFS、8 邻行主序;事件序契约 `flag_judged` < `round_end` 全路径统一。
|
- 事件规范序:A2 发射序=触发格 BFS、8 邻行主序;事件序契约 `flag_judged` < `round_end` 全路径统一。
|
||||||
- **呈现层订阅禁令(切片缺陷②教训固化)**:呈现层永不直接订阅 排雷玩法/行动经济 的事件流,只订 战斗结算 步骤流与 `level_runner`——核心事件形态变化不得直接冲击界面。
|
- **呈现层订阅禁令(切片缺陷教训固化)**:呈现层永不直接订阅排雷玩法/行动经济的事件流,只订战斗结算步骤流与 `level_runner`——核心事件形态变化不得直接冲击界面。
|
||||||
|
|
||||||
### 3. 存档/读档路径
|
### 3. 存档/读档路径
|
||||||
|
|
||||||
- 存档系统已实装:格式、三槽位、断点域与迁移链的现行契约以 `design/gdd/systems/表现与支撑/存档序列化.md`(owner)为准。
|
- 存档系统已实装:格式、三槽位、断点域与迁移链的现行契约以 `design/gdd/systems/表现与支撑/存档序列化.md`(owner)为准。
|
||||||
- RNG 快照契约(现行仍成立):断点续玩回填 = master_seed + 各流 scope 计数器;快照切出须发生在无正在执行中的 open_stream 实例时(scope 事件边界外——B1 编排保证:切点 = board install 边界);SAVE_FORMAT_VERSION 高版本拒读。
|
- RNG 快照契约(约束,现行成立):断点续玩回填=master_seed + 各流 scope 计数器;快照切出须发生在无正在执行中的 open_stream 实例时(scope 事件边界外——切点=board install 边界);SAVE_FORMAT_VERSION 高版本拒读。
|
||||||
|
|
||||||
### 4. 打包与字体(CJK 随包发行)
|
### 4. 打包与字体(CJK 随包发行)
|
||||||
|
|
||||||
CJK 字体随包发行并设为 theme 默认字体——运行时默认字体无中文字形。此项是 HUD框架 正式化的硬性前置,同时进导出 checklist 核对项。
|
CJK 字体随包发行并设为 theme 默认字体——运行时默认字体无中文字形。此项是 HUD 框架正式化的硬性前置,同时进导出 checklist 核对项。
|
||||||
|
|
||||||
### 5. 初始化顺序
|
### 5. 初始化顺序
|
||||||
|
|
||||||
```
|
```
|
||||||
进程启动
|
进程启动
|
||||||
→ autoload 实例化:ConfigDB → RngService → SaveManager → MetaProgression(顺序固定;战斗编排器等核心类为普通类、由组合根按局实例化)
|
→ autoload 实例化:ConfigDB → RngService → SaveManager → MetaProgression(顺序固定;核心类为普通类、由组合根按局实例化)
|
||||||
→ ConfigDB._ready():load_tables 加载 + 校验(致命通道;失败 = 构建中止 + 错误清单)
|
→ ConfigDB._ready():load_tables 加载 + 校验(致命通道;失败 = 构建中止 + 错误清单)
|
||||||
→ 主场景(D1 组合根)装配视图单元 + 信号接线
|
→ 主场景(D1 组合根)装配视图单元 + 信号接线
|
||||||
→ C2 begin_run:RngService.set_master_seed()(唯一接线方;两流计数器全零前提)
|
→ C2 begin_run:RngService.set_master_seed()(唯一接线方;两流计数器全零前提)
|
||||||
@@ -387,14 +245,14 @@ CJK 字体随包发行并设为 theme 默认字体——运行时默认字体无
|
|||||||
→ 关卡末:通关结算(钥石/GP/专长 level_clear 渠道——现行语义归 冒险结构 GDD)
|
→ 关卡末:通关结算(钥石/GP/专长 level_clear 渠道——现行语义归 冒险结构 GDD)
|
||||||
```
|
```
|
||||||
|
|
||||||
**启动后置条件**(2026-10-17 用户裁入册;执行判据事实源在 `game/tests/system_test.gd`):
|
**启动后置条件**(执行判据事实源在 `game/tests/system_test.gd`):
|
||||||
|
|
||||||
1. ConfigDB 就绪且表已载(`is_ready` + hero 表在座)。
|
1. ConfigDB 就绪且表已载(`is_ready` + hero 表在座)。
|
||||||
2. 系统设置已落引擎态——Master 音量 mute/volume_db = settings_store 现值;减动效开关 = `UiKit.motion_scale`。
|
2. 系统设置已落引擎态——Master 音量 mute/volume_db=settings_store 现值;减动效开关=`UiKit.motion_scale`。
|
||||||
3. 启动态菜单可见(boot 后自树顶向下第一个可见内容层 = 开始层——菜单被冒险屏盖住即红)。
|
3. 启动态菜单可见(boot 后自树顶向下第一个可见内容层=开始层)。
|
||||||
4. 续玩钮可见态恒等于断点在档态(双向:无断点隐藏/有断点可见/清断点回隐;boot 路径与刷新单口同源)。
|
4. 续玩钮可见态恒等于断点在档态(双向)。
|
||||||
5. 闲时会话已在树(`run_scope` 非空、非冒险会话、在树——永非 null 契约的启动侧证明)。
|
5. 闲时会话已在树(`run_scope` 永非 null 契约的启动侧证明)。
|
||||||
6. 调试浮窗 boot 不自动开(菜单优先,2026-10-16 用户令)+ 调试入口全局浮层角标 boot 可见。
|
6. 调试浮窗 boot 不自动开(菜单优先)+调试入口全局浮层角标 boot 可见。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -405,46 +263,28 @@ CJK 字体随包发行并设为 theme 默认字体——运行时默认字体无
|
|||||||
| 边界 | 契约要点 | 调用方必须遵守的不变式 | 模块保证 |
|
| 边界 | 契约要点 | 调用方必须遵守的不变式 | 模块保证 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| D1 → A2 | 意图经 `settle_batch(intents)` 提交;不直调 A3 | 单意图帧收集;stop 经批次委托 | 语义序仲裁 + voided 零副作用 |
|
| D1 → A2 | 意图经 `settle_batch(intents)` 提交;不直调 A3 | 单意图帧收集;stop 经批次委托 | 语义序仲裁 + voided 零副作用 |
|
||||||
| A2 → A3 | 挖/插/拔 = 先棋盘面判定后 `try_spend`;A2 不可自行扣减 | 相位判定两侧一致(同一矩阵) | 原子事务(余量+扣减+仲裁一体) |
|
| A2 → A3 | 挖/插/拔=先棋盘面判定后 `try_spend`;A2 不可自行扣减 | 相位判定两侧一致(同一矩阵) | 原子事务(余量+扣减+仲裁一体) |
|
||||||
| A2 → 下游 | 只外发三事件,payload 字段封闭(digit 恒真透传 / reward_eligible / variant_ids) | 增删事件 = 接口漂移 | 发射面封闭 + 规范序 |
|
| A2 → 下游 | 只外发三事件,payload 字段封闭(digit 恒真透传 / reward_eligible / variant_ids) | 增删事件=接口漂移 | 发射面封闭 + 规范序 |
|
||||||
| B1 → B2/B3/B4 | 全调用面集中 B1;调用序钉死(按摇定技能行兑现→apply_damage→commit_action;先兑付后衰减;段内伤害序=主角先手→逐敌还手→地图账殿后〔案C 2026-10-06〕) | 禁第二调用方(静态扫描域:API 符号命中文件 ⊆ B1 文件集) | 恰一次编排纪律(roll_board/decay/清理全序) |
|
| B1 → B2/B3/B4 | 全调用面集中 B1;调用序钉死(按摇定技能行兑现→apply_damage→commit_action;先兑付后衰减;段内伤害序=主角先手→逐敌还手→地图账殿后) | 禁第二调用方(静态扫描域 S7:API 符号命中文件 ⊆ B1 文件集) | 恰一次编排纪律(roll_board/decay/清理全序) |
|
||||||
| B1 ↔ A3 | 编排期代理 `request_refresh`(玩家意图,禁 RAP 满自动刷);回发 next_round_mode/battle_over | stopped/ap_exhausted 未刷新回发 new_board = 违约 fail-fast | 刷新受理契约(同 Waiting 多次合法) |
|
| B1 ↔ A3 | 编排期代理 `request_refresh`(玩家意图,禁 RAP 满自动刷);回发 next_round_mode/battle_over | stopped/ap_exhausted 未刷新回发 new_board=违约 fail-fast | 刷新受理契约(同 Waiting 多次合法) |
|
||||||
| 各系统 → D2 | ConfigDB 类型化属性单点读取 | 禁绕过 ConfigDB load 表、禁缓存副本、禁玩法数值字面量、禁 randomize()/自建 RNG | 校验双通道 + fail-fast 致命 |
|
| 各系统 → D2 | ConfigDB 类型化属性单点读取 | 禁绕过 ConfigDB load 表、禁缓存副本、禁玩法数值字面量、禁 randomize()/自建 RNG | 校验双通道 + fail-fast 致命 |
|
||||||
| A1 → A2 | Board 产物 class_name 数据契约 | install 四不变式校验(violation = 拒绝 + 五类诊断枚举) | 生成期合法性闸(R₀≠S / clearable / min_safe) |
|
| A1 → A2 | Board 产物 class_name 数据契约 | install 四不变式校验(violation=拒绝 + 五类诊断枚举) | 生成期合法性闸(R₀≠S / clearable / min_safe) |
|
||||||
| A1 ↔ B1 | attempt 边界非 scope 事件;actuals p10 为对账输入(非 target 参数) | 编排不把重试当取号 | 生成期指标集输出(实测可推理率 / 实际雷数与安全格数 / 重试次数 / 降级与非法产物标记) |
|
| A1 ↔ B1 | attempt 边界非 scope 事件;actuals p10 为对账输入(非 target 参数) | 编排不把重试当取号 | 生成期指标集输出(实测可推理率 / 实际雷数与安全格数 / 重试次数 / 降级与非法产物标记) |
|
||||||
| B4 → B3 | buff 类经 B1 调 apply_effect(B4 零跨系统读、零直接接口) | 满层拒绝 = 零兑付 + 明细行(无折算) | 授予时数值快照(抗热重载) |
|
| B4 → B3 | buff 类经 B1 调 apply_effect(B4 零跨系统读、零直接接口) | 满层拒绝=零兑付 + 明细行(无折算) | 授予时数值快照(抗热重载) |
|
||||||
| B1 → D1 | [步骤流行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(基础行型+扩展行两层封闭 + 公共字段 type/source_class/origin_cell/round_index/display_name/value/highlight? + 特有字段 target/effect_id/pool_value) | 无来源行 = 断言失败;呈现侧禁按行序重演 B2 状态机 | 可回放步骤流(同种子逐行相同) |
|
| B1 → D1 | [步骤流行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(基础行型+扩展行两层封闭 + 公共字段 type/source_class/origin_cell/round_index/display_name/value/highlight? + 特有字段 target/effect_id/pool_value) | 无来源行=断言失败;呈现侧禁按行序重演 B2 状态机 | 可回放步骤流(同种子逐行相同) |
|
||||||
|
|
||||||
**引擎类型核验注记**:接口使用的引擎类型 = Resource / .tres(D2 全表)、RefCounted(容器类)、Signal/Callable(事件载体)、Control/CanvasLayer/Drawing(D1)、SceneTree headless 协议(测试)——均属 4.x 基线稳定面;4.7 Control 域增量(offset_transform_* 等)已在 breaking-changes.md 登记,D1 采纳前对照核实。
|
**引擎类型核验注记**:接口使用的引擎类型=Resource / .tres(D2 全表)、RefCounted(容器类)、Signal/Callable(事件载体)、Control/CanvasLayer/Drawing(D1)、SceneTree headless 协议(测试)——均属 4.x 基线稳定面;4.7 Control 域增量已在 breaking-changes.md 登记,D1 采纳前对照核实。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 架构原则
|
## 架构原则
|
||||||
|
|
||||||
1. **核心层纯逻辑、headless 完整可跑**——核心层/功能层玩法逻辑零 Control/场景引用、零 UI 依赖;`--headless --script` 可跑完整战斗(D2 Rule 7 工程债;切片 88 冒烟实证)。输入是意图对象、输出是事件流/步骤流,D1 与输入设备皆可替换。
|
1. **核心层纯逻辑、headless 完整可跑**——核心层/功能层玩法逻辑零 Control/场景引用、零 UI 依赖;`--headless --script` 可跑完整战斗。输入是意图对象、输出是事件流/步骤流,D1 与输入设备皆可替换。
|
||||||
2. **单一事实源与零字面量**——玩法数值只存在于 `data/tables/*.tres`,经 ConfigDB 类型化单点读取;代码零玩法数值字面量;参数禁止跨系统复制(D2 Rule 1/2)。
|
2. **单一事实源与零字面量**——玩法数值只存在于 `data/tables/*.tres`,经 ConfigDB 类型化单点读取;代码零玩法数值字面量;参数禁止跨系统复制(D2 Rule 1/2)。
|
||||||
3. **封闭 RNG 与可回放**——玩法代码零随机;一切随机经 RngService 具名封闭流(增流走 P1 评审);同种子 + 同输入序列 ⇒ 事件流/步骤流逐位相同(结算禁 await,B1 承重约束)。
|
3. **封闭 RNG 与可回放**——玩法代码零随机;一切随机经 RngService 具名封闭流(增流走 P1 评审);同种子 + 同输入序列 ⇒ 事件流/步骤流逐位相同(结算禁 await,B1 承重约束)。
|
||||||
4. **编排唯一性与事件面封闭**——战斗域跨系统调用权集中 B1(静态扫描承载);A2 三事件面封闭即负空间;每格受理、每雷转化、每次推进、每次衰减各恰一次。
|
4. **编排唯一性与事件面封闭**——战斗域跨系统调用权集中 B1(静态扫描承载);A2 三事件面封闭即负空间;每格受理、每雷转化、每次推进、每次衰减各恰一次。
|
||||||
5. **fail-fast + 零特判**——数据错误一律致命中止(错误数值上线比崩溃更伤);API 非法 = 拒绝 + 诊断不静默;变异零运行时分支(行为差异全部由生成端约束保证)。
|
5. **fail-fast + 零特判**——数据错误一律致命中止(错误数值上线比崩溃更伤);API 非法=拒绝 + 诊断不静默;变异零运行时分支(行为差异全部由生成端约束保证)。
|
||||||
6. **依赖单向 + 组合根模式**——层间单向依赖、唯一回边 = A2 事件订阅面;核心写调用唯一发生在组合根;禁上帝对象(切片 1100 行 main.gd 反面案例 → 9 单元拆分)。
|
6. **依赖单向 + 组合根模式**——层间单向依赖、唯一回边=A2 事件订阅面;核心写调用唯一发生在组合根;禁上帝对象。
|
||||||
7. **呈现层契约成文**——面向呈现的信号载荷必须有成文 schema;模态覆盖层必须有"打开时遮挡物隐藏"场景级断言;场景级 UI 探针测试为标配(切片缺陷 ①②④⑤ 教训沉淀)。
|
7. **呈现层契约成文**——面向呈现的信号载荷必须有成文 schema;模态覆盖层必须有"打开时遮挡物隐藏"场景级断言;场景级 UI 探针测试为标配(切片缺陷教训沉淀)。
|
||||||
8. **系统无状态**——效果引擎这类系统零运行时可变状态:数据由宿主对象持有并随宿主生灭,状态按参数传入系统,系统只做判定(立项判据=2026-10-19 用户会话裁定)。系统实例不持计数器——计数器住桶(round/battle/level/adventure 四桶,EffectContext 引用束),桶住宿主。
|
8. **系统无状态**——效果引擎这类系统零运行时可变状态:数据由宿主对象持有并随宿主生灭,状态按参数传入系统,系统只做判定。系统实例不持计数器——计数器住桶(round/battle/level/adventure 四桶,EffectContext 引用束),桶住宿主。
|
||||||
9. **停点权威在核心层**——玩家决策停点(选路、三选一、商店、恢复这类)的推进守卫住核心层状态机:停点未兑付,推进口一律拒绝(零自动推进契约);呈现层模态只做开合与输入锁——阻塞是两层结构,核心守卫为权威、模态为体验;停点态是核心状态、随断点序列化,headless 跑批与真实局同一套规则,中断续玩恢复到同一停点。
|
9. **停点权威在核心层**——玩家决策停点(选路、三选一、商店、恢复这类)的推进守卫住核心层状态机:停点未兑付,推进口一律拒绝(零自动推进契约);呈现层模态只做开合与输入锁——阻塞是两层结构,核心守卫为权威、模态为体验;停点态是核心状态、随断点序列化,headless 跑批与真实局同一套规则,中断续玩恢复到同一停点。
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 未决问题
|
|
||||||
|
|
||||||
| ID | Summary | Priority | Resolution Path |
|
|
||||||
|----|---------|----------|-----------------|
|
|
||||||
| QQ-04 | 轮内刷新数值连锁(清图支配性条款⑤ / 真人刷图行为获取期望)重算 | Medium | playtest 实测 |
|
|
||||||
| QQ-05 | 战斗末可选类"j==0 补发 1 件"兜底是否采纳(切片遗留待办) | Medium | playtest + B4 GDD 修订批 |
|
|
||||||
| QQ-06 | 可选类退出格子池后 buff 频率被动上升(44%→59%)的难度对冲杠杆(敌 HP / 权重 / 幅度) | High | C3 调参 + 切片数据复测 |
|
|
||||||
| QQ-07 | 标错惩罚(A2 OQ1:候选敌方伏击+1;hit=false 无去重的不对称裁决) | Medium | 原型小补丁实测会话(可与 v3 终验合并) |
|
|
||||||
| QQ-08 | B5 双舞台陷阱(战斗发生在棋盘上还是独立场景) | Low(B5 前) | 战斗表现美术测试后裁决 |
|
|
||||||
| QQ-09 | C3 消费 B1 对账输出的事实依赖回写 `design/gdd/02-系统清单.md` | Low | C3 GDD 定稿时 |
|
|
||||||
| QQ-10 | `.claude/docs/director-gates.md` 缺失(TD-ARCHITECTURE/LP-FEASIBILITY 判据无载体) | Low | 补建 gate 定义文件或维持 solo/lean 模式约定 |
|
|
||||||
| QQ-11 | A1 生成性能姿态(F2c 常数 C 定稿;切片实证 10×10/12×12 同步生成可接受,WorkerThread 留扩展) | Medium | A1 GDD 修订批 |
|
|
||||||
| QQ-12 | 零伤害死局跨字段/跨表护栏落点(B2 OQ9;推荐 D2 跨表校验——切片 LevelTable 校验⑧先例) | Medium | D2 校验设计批 |
|
|
||||||
| QQ-13 | A1 EC5 运行期熔断(连续降级确定性回退已知好种子) | Low | A1 GDD 修订批 |
|
|
||||||
| QQ-14 | A5 探测显影接口 / D3 存档格式(RNG 快照契约已在案,格式归 Alpha) | Low | 秘宝域正式化 / D3 Alpha 设计批 |
|
|
||||||
@@ -5160,7 +5160,7 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
|
|
||||||
<rect data-graph-role="structural-frame" data-composition-frame-kind="region" data-composition-frame-id="1" data-composition-frame-label="浮层与对话框(组合根挂载)" x="90" y="390" width="1060" height="106" rx="12" class="c-region" stroke-width="1"/>
|
<rect data-graph-role="structural-frame" data-composition-frame-kind="region" data-composition-frame-id="1" data-composition-frame-label="浮层与对话框(组合根挂载)" x="90" y="390" width="1060" height="106" rx="12" class="c-region" stroke-width="1"/>
|
||||||
|
|
||||||
<rect data-graph-role="structural-frame" data-composition-frame-kind="region" data-composition-frame-id="2" data-composition-frame-label="逻辑层 core/(21 件·名称清单)" x="66" y="524" width="1226" height="222" rx="12" class="c-region" stroke-width="1"/>
|
<rect data-graph-role="structural-frame" data-composition-frame-kind="region" data-composition-frame-id="2" data-composition-frame-label="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" x="66" y="524" width="1226" height="222" rx="12" class="c-region" stroke-width="1"/>
|
||||||
|
|
||||||
<!-- Connection paths (before components for correct z-order) -->
|
<!-- Connection paths (before components for correct z-order) -->
|
||||||
<path data-edge-from="main" data-edge-to="stage" data-edge-key="0" data-edge-id="main-stage" data-composition-points="566,132;566,196;125,196;125,260" d="M 566 132 L 566 188 Q 566 196 558 196 L 133 196 Q 125 196 125 204 L 125 260" class="a-default" stroke-width="1.5" marker-end="url(#arrowhead)"/>
|
<path data-edge-from="main" data-edge-to="stage" data-edge-key="0" data-edge-id="main-stage" data-composition-points="566,132;566,196;125,196;125,260" d="M 566 132 L 566 188 Q 566 196 558 196 L 133 196 Q 125 196 125 204 L 125 260" class="a-default" stroke-width="1.5" marker-end="url(#arrowhead)"/>
|
||||||
@@ -5375,8 +5375,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="fine" x="876" y="468" class="t-frontend" font-size="7" text-anchor="middle">confirm_dialog.gd</text>
|
<text data-detail="fine" x="876" y="468" class="t-frontend" font-size="7" text-anchor="middle">confirm_dialog.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-debug" data-node-id="debug" data-node-label="调试浮窗" tabindex="0" role="button" aria-label="聚焦调试浮窗,DS_DEBUG 门控, 浮层与对话框(组合根挂载)" aria-pressed="false" data-node-kind="frontend" data-node-sublabel="DS_DEBUG 门控" data-node-tag="debug_overlay.gd" data-node-context="浮层与对话框(组合根挂载)">
|
<g id="node-debug" data-node-id="debug" data-node-label="调试浮窗" tabindex="0" role="button" aria-label="聚焦调试浮窗,发布态恒隐, 浮层与对话框(组合根挂载)" aria-pressed="false" data-node-kind="frontend" data-node-sublabel="发布态恒隐" data-node-tag="debug_overlay.gd" data-node-context="浮层与对话框(组合根挂载)">
|
||||||
<title>调试浮窗 · DS_DEBUG 门控 · 浮层与对话框(组合根挂载) · debug_overlay.gd</title>
|
<title>调试浮窗 · 发布态恒隐 · 浮层与对话框(组合根挂载) · debug_overlay.gd</title>
|
||||||
<rect x="968" y="420" width="152" height="56" rx="6" class="c-mask"/>
|
<rect x="968" y="420" width="152" height="56" rx="6" class="c-mask"/>
|
||||||
<rect x="968" y="420" width="152" height="56" rx="6" class="c-frontend" stroke-width="1.5"/>
|
<rect x="968" y="420" width="152" height="56" rx="6" class="c-frontend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="frontend" class="semantic-sigil s-frontend" transform="translate(974 426) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="frontend" class="semantic-sigil s-frontend" transform="translate(974 426) scale(0.6875)">
|
||||||
@@ -5386,12 +5386,12 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<circle cx="6.3" cy="4.8" r=".7" class="sigil-fill"/>
|
<circle cx="6.3" cy="4.8" r=".7" class="sigil-fill"/>
|
||||||
</g>
|
</g>
|
||||||
<text data-node-label="" data-detail-anchor="" x="1044" y="446" class="t-primary" font-size="11" font-weight="600" text-anchor="middle">调试浮窗</text>
|
<text data-node-label="" data-detail-anchor="" x="1044" y="446" class="t-primary" font-size="11" font-weight="600" text-anchor="middle">调试浮窗</text>
|
||||||
<text data-detail="context" x="1044" y="462" class="t-muted" font-size="9" text-anchor="middle">DS_DEBUG 门控</text>
|
<text data-detail="context" x="1044" y="462" class="t-muted" font-size="9" text-anchor="middle">发布态恒隐</text>
|
||||||
<text data-detail="fine" x="1044" y="468" class="t-frontend" font-size="7" text-anchor="middle">debug_overlay.gd</text>
|
<text data-detail="fine" x="1044" y="468" class="t-frontend" font-size="7" text-anchor="middle">debug_overlay.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-save" data-node-id="save" data-node-label="存档管理" tabindex="0" role="button" aria-label="聚焦存档管理,save_manager.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="database" data-node-sublabel="save_manager.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-save" data-node-id="save" data-node-label="存档管理" tabindex="0" role="button" aria-label="聚焦存档管理,save_manager.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="database" data-node-sublabel="save_manager.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>存档管理 · save_manager.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>存档管理 · save_manager.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="96" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="96" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="96" y="554" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
<rect x="96" y="554" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(102 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(102 560) scale(0.6875)">
|
||||||
@@ -5402,8 +5402,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="161" y="592" class="t-muted" font-size="9" text-anchor="middle">save_manager.gd</text>
|
<text data-detail="context" x="161" y="592" class="t-muted" font-size="9" text-anchor="middle">save_manager.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-meta" data-node-id="meta" data-node-label="元进度" tabindex="0" role="button" aria-label="聚焦元进度,meta_progression.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="database" data-node-sublabel="meta_progression.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-meta" data-node-id="meta" data-node-label="元进度" tabindex="0" role="button" aria-label="聚焦元进度,meta_progression.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="database" data-node-sublabel="meta_progression.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>元进度 · meta_progression.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>元进度 · meta_progression.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="244" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="244" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="244" y="554" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
<rect x="244" y="554" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(250 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(250 560) scale(0.6875)">
|
||||||
@@ -5414,8 +5414,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="309" y="592" class="t-muted" font-size="9" text-anchor="middle">meta_progression.gd</text>
|
<text data-detail="context" x="309" y="592" class="t-muted" font-size="9" text-anchor="middle">meta_progression.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-orch" data-node-id="orch" data-node-label="战斗编排器" tabindex="0" role="button" aria-label="聚焦战斗编排器,battle_orchestrator.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="battle_orchestrator.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-orch" data-node-id="orch" data-node-label="战斗编排器" tabindex="0" role="button" aria-label="聚焦战斗编排器,battle_orchestrator.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="battle_orchestrator.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>战斗编排器 · battle_orchestrator.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>战斗编排器 · battle_orchestrator.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="383" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="383" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="383" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="383" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(389 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(389 560) scale(0.6875)">
|
||||||
@@ -5425,8 +5425,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="448" y="592" class="t-muted" font-size="9" text-anchor="middle">battle_orchestrator.gd</text>
|
<text data-detail="context" x="448" y="592" class="t-muted" font-size="9" text-anchor="middle">battle_orchestrator.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-rules" data-node-id="rules" data-node-label="扫雷规则" tabindex="0" role="button" aria-label="聚焦扫雷规则,minesweeper_rules.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="minesweeper_rules.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-rules" data-node-id="rules" data-node-label="扫雷规则" tabindex="0" role="button" aria-label="聚焦扫雷规则,minesweeper_rules.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="minesweeper_rules.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>扫雷规则 · minesweeper_rules.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>扫雷规则 · minesweeper_rules.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="540" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="540" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="540" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="540" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(546 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(546 560) scale(0.6875)">
|
||||||
@@ -5436,8 +5436,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="605" y="592" class="t-muted" font-size="9" text-anchor="middle">minesweeper_rules.gd</text>
|
<text data-detail="context" x="605" y="592" class="t-muted" font-size="9" text-anchor="middle">minesweeper_rules.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-boardgen" data-node-id="boardgen" data-node-label="棋盘生成" tabindex="0" role="button" aria-label="聚焦棋盘生成,board_generator.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="board_generator.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-boardgen" data-node-id="boardgen" data-node-label="棋盘生成" tabindex="0" role="button" aria-label="聚焦棋盘生成,board_generator.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="board_generator.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>棋盘生成 · board_generator.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>棋盘生成 · board_generator.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="688" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="688" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="688" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="688" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(694 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(694 560) scale(0.6875)">
|
||||||
@@ -5447,8 +5447,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="753" y="592" class="t-muted" font-size="9" text-anchor="middle">board_generator.gd</text>
|
<text data-detail="context" x="753" y="592" class="t-muted" font-size="9" text-anchor="middle">board_generator.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-boarddata" data-node-id="boarddata" data-node-label="棋盘数据" tabindex="0" role="button" aria-label="聚焦棋盘数据,board_data.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="database" data-node-sublabel="board_data.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-boarddata" data-node-id="boarddata" data-node-label="棋盘数据" tabindex="0" role="button" aria-label="聚焦棋盘数据,board_data.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="database" data-node-sublabel="board_data.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>棋盘数据 · board_data.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>棋盘数据 · board_data.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="836" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="836" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="836" y="554" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
<rect x="836" y="554" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(842 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(842 560) scale(0.6875)">
|
||||||
@@ -5459,8 +5459,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="901" y="592" class="t-muted" font-size="9" text-anchor="middle">board_data.gd</text>
|
<text data-detail="context" x="901" y="592" class="t-muted" font-size="9" text-anchor="middle">board_data.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-effects" data-node-id="effects" data-node-label="效果引擎" tabindex="0" role="button" aria-label="聚焦效果引擎,effect_engine.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="effect_engine.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-effects" data-node-id="effects" data-node-label="效果引擎" tabindex="0" role="button" aria-label="聚焦效果引擎,effect_engine.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="effect_engine.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>效果引擎 · effect_engine.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>效果引擎 · effect_engine.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="984" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="984" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="984" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="984" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(990 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(990 560) scale(0.6875)">
|
||||||
@@ -5470,8 +5470,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="1049" y="592" class="t-muted" font-size="9" text-anchor="middle">effect_engine.gd</text>
|
<text data-detail="context" x="1049" y="592" class="t-muted" font-size="9" text-anchor="middle">effect_engine.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-adventure" data-node-id="adventure" data-node-label="冒险运行器" tabindex="0" role="button" aria-label="聚焦冒险运行器,adventure_runner.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="adventure_runner.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-adventure" data-node-id="adventure" data-node-label="冒险运行器" tabindex="0" role="button" aria-label="聚焦冒险运行器,adventure_runner.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="adventure_runner.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>冒险运行器 · adventure_runner.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>冒险运行器 · adventure_runner.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="1132" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="1132" y="554" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="1132" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="1132" y="554" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(1138 560) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(1138 560) scale(0.6875)">
|
||||||
@@ -5481,8 +5481,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="1197" y="592" class="t-muted" font-size="9" text-anchor="middle">adventure_runner.gd</text>
|
<text data-detail="context" x="1197" y="592" class="t-muted" font-size="9" text-anchor="middle">adventure_runner.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-levelrun" data-node-id="levelrun" data-node-label="关卡运行器" tabindex="0" role="button" aria-label="聚焦关卡运行器,level_runner.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="level_runner.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-levelrun" data-node-id="levelrun" data-node-label="关卡运行器" tabindex="0" role="button" aria-label="聚焦关卡运行器,level_runner.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="level_runner.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>关卡运行器 · level_runner.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>关卡运行器 · level_runner.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="96" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="96" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="96" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="96" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(102 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(102 622) scale(0.6875)">
|
||||||
@@ -5492,8 +5492,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="161" y="654" class="t-muted" font-size="9" text-anchor="middle">level_runner.gd</text>
|
<text data-detail="context" x="161" y="654" class="t-muted" font-size="9" text-anchor="middle">level_runner.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-dmgctl" data-node-id="dmgctl" data-node-label="伤害控制" tabindex="0" role="button" aria-label="聚焦伤害控制,damage_controller.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="damage_controller.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-dmgctl" data-node-id="dmgctl" data-node-label="伤害控制" tabindex="0" role="button" aria-label="聚焦伤害控制,damage_controller.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="damage_controller.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>伤害控制 · damage_controller.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>伤害控制 · damage_controller.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="244" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="244" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="244" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="244" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(250 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(250 622) scale(0.6875)">
|
||||||
@@ -5503,8 +5503,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="309" y="654" class="t-muted" font-size="9" text-anchor="middle">damage_controller.gd</text>
|
<text data-detail="context" x="309" y="654" class="t-muted" font-size="9" text-anchor="middle">damage_controller.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-dgmath" data-node-id="dgmath" data-node-label="伤害公式" tabindex="0" role="button" aria-label="聚焦伤害公式,damage_math.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="damage_math.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-dgmath" data-node-id="dgmath" data-node-label="伤害公式" tabindex="0" role="button" aria-label="聚焦伤害公式,damage_math.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="damage_math.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>伤害公式 · damage_math.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>伤害公式 · damage_math.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="392" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="392" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="392" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="392" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(398 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(398 622) scale(0.6875)">
|
||||||
@@ -5514,8 +5514,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="457" y="654" class="t-muted" font-size="9" text-anchor="middle">damage_math.gd</text>
|
<text data-detail="context" x="457" y="654" class="t-muted" font-size="9" text-anchor="middle">damage_math.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-reward" data-node-id="reward" data-node-label="奖励经济" tabindex="0" role="button" aria-label="聚焦奖励经济,reward_economy.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="reward_economy.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-reward" data-node-id="reward" data-node-label="奖励经济" tabindex="0" role="button" aria-label="聚焦奖励经济,reward_economy.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="reward_economy.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>奖励经济 · reward_economy.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>奖励经济 · reward_economy.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="540" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="540" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="540" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="540" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(546 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(546 622) scale(0.6875)">
|
||||||
@@ -5525,8 +5525,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="605" y="654" class="t-muted" font-size="9" text-anchor="middle">reward_economy.gd</text>
|
<text data-detail="context" x="605" y="654" class="t-muted" font-size="9" text-anchor="middle">reward_economy.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-lottery" data-node-id="lottery" data-node-label="技能抽奖" tabindex="0" role="button" aria-label="聚焦技能抽奖,skill_lottery.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="skill_lottery.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-lottery" data-node-id="lottery" data-node-label="技能抽奖" tabindex="0" role="button" aria-label="聚焦技能抽奖,skill_lottery.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="skill_lottery.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>技能抽奖 · skill_lottery.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>技能抽奖 · skill_lottery.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="688" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="688" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="688" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="688" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(694 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(694 622) scale(0.6875)">
|
||||||
@@ -5536,8 +5536,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="753" y="654" class="t-muted" font-size="9" text-anchor="middle">skill_lottery.gd</text>
|
<text data-detail="context" x="753" y="654" class="t-muted" font-size="9" text-anchor="middle">skill_lottery.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-attune" data-node-id="attune" data-node-label="同调" tabindex="0" role="button" aria-label="聚焦同调,attunement.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="attunement.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-attune" data-node-id="attune" data-node-label="同调" tabindex="0" role="button" aria-label="聚焦同调,attunement.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="attunement.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>同调 · attunement.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>同调 · attunement.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="836" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="836" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="836" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="836" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(842 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(842 622) scale(0.6875)">
|
||||||
@@ -5547,8 +5547,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="901" y="654" class="t-muted" font-size="9" text-anchor="middle">attunement.gd</text>
|
<text data-detail="context" x="901" y="654" class="t-muted" font-size="9" text-anchor="middle">attunement.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-action" data-node-id="action" data-node-label="行动经济" tabindex="0" role="button" aria-label="聚焦行动经济,action_economy.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="action_economy.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-action" data-node-id="action" data-node-label="行动经济" tabindex="0" role="button" aria-label="聚焦行动经济,action_economy.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="action_economy.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>行动经济 · action_economy.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>行动经济 · action_economy.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="984" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="984" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="984" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="984" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(990 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(990 622) scale(0.6875)">
|
||||||
@@ -5558,8 +5558,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="1049" y="654" class="t-muted" font-size="9" text-anchor="middle">action_economy.gd</text>
|
<text data-detail="context" x="1049" y="654" class="t-muted" font-size="9" text-anchor="middle">action_economy.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-feats" data-node-id="feats" data-node-label="特长引擎" tabindex="0" role="button" aria-label="聚焦特长引擎,feats_engine.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="feats_engine.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-feats" data-node-id="feats" data-node-label="特长引擎" tabindex="0" role="button" aria-label="聚焦特长引擎,feats_engine.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="feats_engine.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>特长引擎 · feats_engine.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>特长引擎 · feats_engine.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="1132" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="1132" y="616" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="1132" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="1132" y="616" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(1138 622) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(1138 622) scale(0.6875)">
|
||||||
@@ -5569,8 +5569,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="1197" y="654" class="t-muted" font-size="9" text-anchor="middle">feats_engine.gd</text>
|
<text data-detail="context" x="1197" y="654" class="t-muted" font-size="9" text-anchor="middle">feats_engine.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-status" data-node-id="status" data-node-label="状态容器" tabindex="0" role="button" aria-label="聚焦状态容器,status_container.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="status_container.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-status" data-node-id="status" data-node-label="状态容器" tabindex="0" role="button" aria-label="聚焦状态容器,status_container.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="status_container.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>状态容器 · status_container.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>状态容器 · status_container.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="96" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="96" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="96" y="678" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="96" y="678" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(102 684) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(102 684) scale(0.6875)">
|
||||||
@@ -5580,8 +5580,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="161" y="716" class="t-muted" font-size="9" text-anchor="middle">status_container.gd</text>
|
<text data-detail="context" x="161" y="716" class="t-muted" font-size="9" text-anchor="middle">status_container.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-units" data-node-id="units" data-node-label="单位容器" tabindex="0" role="button" aria-label="聚焦单位容器,unit_container.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="unit_container.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-units" data-node-id="units" data-node-label="单位容器" tabindex="0" role="button" aria-label="聚焦单位容器,unit_container.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="unit_container.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>单位容器 · unit_container.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>单位容器 · unit_container.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="244" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="244" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="244" y="678" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="244" y="678" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(250 684) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(250 684) scale(0.6875)">
|
||||||
@@ -5591,8 +5591,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="309" y="716" class="t-muted" font-size="9" text-anchor="middle">unit_container.gd</text>
|
<text data-detail="context" x="309" y="716" class="t-muted" font-size="9" text-anchor="middle">unit_container.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-treasure" data-node-id="treasure" data-node-label="秘宝数据" tabindex="0" role="button" aria-label="聚焦秘宝数据,treasure_items.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="database" data-node-sublabel="treasure_items.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-treasure" data-node-id="treasure" data-node-label="秘宝数据" tabindex="0" role="button" aria-label="聚焦秘宝数据,treasure_items.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="database" data-node-sublabel="treasure_items.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>秘宝数据 · treasure_items.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>秘宝数据 · treasure_items.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="392" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="392" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="392" y="678" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
<rect x="392" y="678" width="130" height="48" rx="6" class="c-database" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(398 684) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="database" class="semantic-sigil s-database" transform="translate(398 684) scale(0.6875)">
|
||||||
@@ -5603,8 +5603,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="457" y="716" class="t-muted" font-size="9" text-anchor="middle">treasure_items.gd</text>
|
<text data-detail="context" x="457" y="716" class="t-muted" font-size="9" text-anchor="middle">treasure_items.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-resolver" data-node-id="resolver" data-node-label="配置解析" tabindex="0" role="button" aria-label="聚焦配置解析,config_db_resolver.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="config_db_resolver.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-resolver" data-node-id="resolver" data-node-label="配置解析" tabindex="0" role="button" aria-label="聚焦配置解析,config_db_resolver.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="config_db_resolver.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>配置解析 · config_db_resolver.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>配置解析 · config_db_resolver.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="540" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
<rect x="540" y="678" width="130" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="540" y="678" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="540" y="678" width="130" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(546 684) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(546 684) scale(0.6875)">
|
||||||
@@ -5614,8 +5614,8 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-detail="context" x="605" y="716" class="t-muted" font-size="9" text-anchor="middle">config_db_resolver.gd</text>
|
<text data-detail="context" x="605" y="716" class="t-muted" font-size="9" text-anchor="middle">config_db_resolver.gd</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g id="node-xvalid" data-node-id="xvalid" data-node-label="配置交叉校验" tabindex="0" role="button" aria-label="聚焦配置交叉校验,config_db_cross_validator.gd, 逻辑层 core/(21 件·名称清单)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="config_db_cross_validator.gd" data-node-context="逻辑层 core/(21 件·名称清单)">
|
<g id="node-xvalid" data-node-id="xvalid" data-node-label="配置交叉校验" tabindex="0" role="button" aria-label="聚焦配置交叉校验,config_db_cross_validator.gd, 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)" aria-pressed="false" data-node-kind="backend" data-node-sublabel="config_db_cross_validator.gd" data-node-context="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<title>配置交叉校验 · config_db_cross_validator.gd · 逻辑层 core/(21 件·名称清单)</title>
|
<title>配置交叉校验 · config_db_cross_validator.gd · 逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</title>
|
||||||
<rect x="688" y="678" width="170" height="48" rx="6" class="c-mask"/>
|
<rect x="688" y="678" width="170" height="48" rx="6" class="c-mask"/>
|
||||||
<rect x="688" y="678" width="170" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
<rect x="688" y="678" width="170" height="48" rx="6" class="c-backend" stroke-width="1.5"/>
|
||||||
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(694 684) scale(0.6875)">
|
<g aria-hidden="true" data-semantic-sigil="backend" class="semantic-sigil s-backend" transform="translate(694 684) scale(0.6875)">
|
||||||
@@ -5660,9 +5660,9 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<text data-boundary-label="" x="98" y="413" class="t-cloud" font-size="9" font-weight="600">浮层与对话框(组合根挂载)</text>
|
<text data-boundary-label="" x="98" y="413" class="t-cloud" font-size="9" font-weight="600">浮层与对话框(组合根挂载)</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g data-graph-role="structural-frame-label" data-composition-frame-id="2" data-composition-frame-kind="region" data-composition-frame-label="逻辑层 core/(21 件·名称清单)">
|
<g data-graph-role="structural-frame-label" data-composition-frame-id="2" data-composition-frame-kind="region" data-composition-frame-label="逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)">
|
||||||
<rect data-graph-role="structural-frame-label-mask" x="70" y="534" width="172" height="16" rx="3" class="c-mask"/>
|
<rect data-graph-role="structural-frame-label-mask" x="70" y="534" width="339.4" height="16" rx="3" class="c-mask"/>
|
||||||
<text data-boundary-label="" x="74" y="547" class="t-cloud" font-size="9" font-weight="600">逻辑层 core/(21 件·名称清单)</text>
|
<text data-boundary-label="" x="74" y="547" class="t-cloud" font-size="9" font-weight="600">逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Legend -->
|
<!-- Legend -->
|
||||||
@@ -5859,7 +5859,7 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<h3>组合根与建树</h3>
|
<h3>组合根与建树</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>• main.tscn 全场景仅 1 个节点,整棵界面树由 main.gd 运行时搭建(1392 行)</li>
|
<li>• main.tscn 全场景仅 1 个节点,整棵界面树由 main.gd 运行时搭建</li>
|
||||||
<li>• 战斗界面由 UiAssembler 拼装;商店/营地浮层即拼装于战斗根内</li>
|
<li>• 战斗界面由 UiAssembler 拼装;商店/营地浮层即拼装于战斗根内</li>
|
||||||
<li>• 元进度账本与存档同由组合根持有(main.gd preload)</li>
|
<li>• 元进度账本与存档同由组合根持有(main.gd preload)</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -5883,7 +5883,7 @@ OTHER DEALINGS IN THE FONT SOFTWARE.
|
|||||||
<h3>逻辑层与边界</h3>
|
<h3>逻辑层与边界</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>• core/ 21 件仅列名称,源码出处见各节点 sources 指针</li>
|
<li>• core/ 模块与拆件全量清单以 architecture.md「模块归属」表为准,本图只画顶层导航件</li>
|
||||||
<li>• ConfigDB/RngService 两单例经 project.godot autoload 全局供给</li>
|
<li>• ConfigDB/RngService 两单例经 project.godot autoload 全局供给</li>
|
||||||
<li>• smoke/ 下 13 个测试探针场景属测试基建,不入架构主干</li>
|
<li>• smoke/ 下 13 个测试探针场景属测试基建,不入架构主干</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -556,7 +556,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "region",
|
"kind": "region",
|
||||||
"label": "逻辑层 core/(21 件·名称清单)",
|
"label": "逻辑层 core/(模块与拆件清单=architecture.md「模块归属」表)",
|
||||||
"wraps": [
|
"wraps": [
|
||||||
"save",
|
"save",
|
||||||
"meta",
|
"meta",
|
||||||
@@ -671,7 +671,7 @@
|
|||||||
"dot": "cyan",
|
"dot": "cyan",
|
||||||
"title": "组合根与建树",
|
"title": "组合根与建树",
|
||||||
"items": [
|
"items": [
|
||||||
"main.tscn 全场景仅 1 个节点,整棵界面树由 main.gd 运行时搭建(1392 行)",
|
"main.tscn 全场景仅 1 个节点,整棵界面树由 main.gd 运行时搭建",
|
||||||
"战斗界面由 UiAssembler 拼装;商店/营地浮层即拼装于战斗根内",
|
"战斗界面由 UiAssembler 拼装;商店/营地浮层即拼装于战斗根内",
|
||||||
"元进度账本与存档同由组合根持有(main.gd preload)"
|
"元进度账本与存档同由组合根持有(main.gd preload)"
|
||||||
]
|
]
|
||||||
@@ -689,7 +689,7 @@
|
|||||||
"dot": "rose",
|
"dot": "rose",
|
||||||
"title": "逻辑层与边界",
|
"title": "逻辑层与边界",
|
||||||
"items": [
|
"items": [
|
||||||
"core/ 21 件仅列名称,源码出处见各节点 sources 指针",
|
"core/ 模块与拆件全量清单以 architecture.md「模块归属」表为准,本图只画顶层导航件",
|
||||||
"ConfigDB/RngService 两单例经 project.godot autoload 全局供给",
|
"ConfigDB/RngService 两单例经 project.godot autoload 全局供给",
|
||||||
"smoke/ 下 13 个测试探针场景属测试基建,不入架构主干"
|
"smoke/ 下 13 个测试探针场景属测试基建,不入架构主干"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
### 1.6 拆分交接与封装边界
|
### 1.6 拆分交接与封装边界
|
||||||
本节管拆分类改动的交接面与封装面,与 §1.1 拆分判据(职责轴)配合使用:§1.1 管怎么切,本节管切完之后件与件之间怎么往来。
|
本节管拆分类改动的交接面与封装面,与 §1.1 拆分判据(职责轴)配合使用:§1.1 管怎么切,本节管切完之后件与件之间怎么往来。
|
||||||
|
|
||||||
1. **拆分交接定义**:拆出一个新类时,交付物必须同时写明职责边界与交接定义——新类构造时需要哪些依赖,由拆出它的类在构造它时一次交给它;新类需要回调拆出它的类的哪些方法,以 Callable 形式交付。两者齐备才算拆分合格。为什么:只切职责不定义交接,新件会伸手回原类内部拿东西,封装从拆件那天起就破了。正面先例=装板件的引用束注入(表数据、随机流、装板所需对象与出错回调一次性交付——架构文档「战斗编排域拆件定稿」节 BoardInstaller 行在册)。
|
1. **拆分交接定义**:拆出一个新类时,交付物必须同时写明职责边界与交接定义——新类构造时需要哪些依赖,由拆出它的类在构造它时一次交给它;新类需要回调拆出它的类的哪些方法,以 Callable 形式交付。两者齐备才算拆分合格。为什么:只切职责不定义交接,新件会伸手回原类内部拿东西,封装从拆件那天起就破了。正面先例=装板件的引用束注入(表数据、随机流、装板所需对象与出错回调一次性交付——先例本体=`game/core/board_installer.gd` 构造面,沿革 git 历史可考)。
|
||||||
2. **封装边界**:任何代码不得访问其他对象的下划线成员;跨对象往来只走公开方法与属性。为什么:下划线只是命名约定,语言不设防、无编译期检查——此条是封装硬纪律,违者即红。
|
2. **封装边界**:任何代码不得访问其他对象的下划线成员;跨对象往来只走公开方法与属性。为什么:下划线只是命名约定,语言不设防、无编译期检查——此条是封装硬纪律,违者即红。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
10. **`# rng-seed-exempt` 标记豁免通道**——S1/S2 随机函数扫描对该行豁免;限定用途=非玩法 RNG 消费面的引擎熵(现行例:组合根种子编辑框空态取 `randi()`——建种子不进玩法封闭流);非产品码三目录自建随机源的定种要求见第 13 条。
|
10. **`# rng-seed-exempt` 标记豁免通道**——S1/S2 随机函数扫描对该行豁免;限定用途=非玩法 RNG 消费面的引擎熵(现行例:组合根种子编辑框空态取 `randi()`——建种子不进玩法封闭流);非产品码三目录自建随机源的定种要求见第 13 条。
|
||||||
11. **`--script` 模式禁裸 autoload 标识符**——`ConfigDB`/`RngService` 等 autoload 名在 `--headless --script` 模式编译器不解析(parse error);产品码与测试夹具一律经节点路径取用(`get_node("/root/…")`/`AUTOLOAD_PATH_*` 常量);静态扫描域 S5 硬失败承载在位。
|
11. **`--script` 模式禁裸 autoload 标识符**——`ConfigDB`/`RngService` 等 autoload 名在 `--headless --script` 模式编译器不解析(parse error);产品码与测试夹具一律经节点路径取用(`get_node("/root/…")`/`AUTOLOAD_PATH_*` 常量);静态扫描域 S5 硬失败承载在位。
|
||||||
12. **Variant 参数化现行口径**——账本类字典/数组标注 `Dictionary[Variant, Variant]`/`Array[Variant]` 即合格(满足 R1);元素类型精化列后续事项、不入硬纪律,口径变更须用户裁决后续批次另行写入。
|
12. **Variant 参数化现行口径**——账本类字典/数组标注 `Dictionary[Variant, Variant]`/`Array[Variant]` 即合格(满足 R1);元素类型精化列后续事项、不入硬纪律,口径变更须用户裁决后续批次另行写入。
|
||||||
13. **静态扫描适用域按来源分档(2026-11-03 架构审查 P1 余项裁)**——S 系静态扫描(S1–S13)的扫描面一律止于产品码三目录,`game/tests`/`game/probe`/`game/sim` 不进任何 S 系扫描面;这三目录的可靠性由运行期通道承接,各通道是:`game/tests`=冒烟·单元与集成·系统测试三闸、`game/probe`=场景探针与渲染 golden 两闸(同目录内 `type_glow_shot_probe` 是人工取证件、`probe_ui_util` 是探针共用面,两者不入闸)、`game/sim`=不入 CI,属用户手动发起的调参与数值测量批量。三目录**允许**自建 `RandomNumberGenerator`,条件=**必须显式定种**(改前改后读数要用同种子对拍,这是全项目测量口径);三目录真正禁止的形态是不定种随机——`randomize()` 与全局 `randi()`/`randf()`/`randf_range()`,一旦命中那次运行结果不可复现,读数与取证一并失效。这条对三目录的部分目前**无机器闸**(S1/S2 扫描面不含它们):扩面需给每处合法定种挂 `rng-seed-exempt` 注记、只拦得住新增,2026-11-03 用户裁不扩,改由本条文字+批末独立验收审计的人工评审承载。术语口径:`tools/run_all_gates.sh` 里的「测量面」指 `game/tests`+`game/sim`(影响面选闸用语,`game/probe` 不在其中——改探针必须跑场景探针与渲染闸),与本条分档无关;本文不再用「测量面」统称这三个目录。
|
13. **静态扫描适用域按来源分档(2026-11-03 架构审查 P1 余项裁)**——S 系静态扫描(S1–S13)的扫描面一律止于产品码三目录,`game/tests`/`game/probe`/`game/sim` 不进任何 S 系扫描面;这三目录的可靠性由运行期通道承接,各通道是:`game/tests`=冒烟·单元·系统测试三闸、`game/probe`=场景探针与渲染 golden 两闸(同目录内 `type_glow_shot_probe` 是人工取证件、`probe_ui_util` 是探针共用面,两者不入闸)、`game/sim`=不入 CI,属用户手动发起的调参与数值测量批量。三目录**允许**自建 `RandomNumberGenerator`,条件=**必须显式定种**(改前改后读数要用同种子对拍,这是全项目测量口径);三目录真正禁止的形态是不定种随机——`randomize()` 与全局 `randi()`/`randf()`/`randf_range()`,一旦命中那次运行结果不可复现,读数与取证一并失效。这条对三目录的部分目前**无机器闸**(S1/S2 扫描面不含它们):扩面需给每处合法定种挂 `rng-seed-exempt` 注记、只拦得住新增,2026-11-03 用户裁不扩,改由本条文字+批末独立验收审计的人工评审承载。术语口径:`tools/run_all_gates.sh` 里的「测量面」指 `game/tests`+`game/sim`(影响面选闸用语,`game/probe` 不在其中——改探针必须跑场景探针与渲染闸),与本条分档无关;本文不再用「测量面」统称这三个目录。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -63,17 +63,17 @@
|
|||||||
| 规则 | 内容 |
|
| 规则 | 内容 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 树形文档体系 | 全部设计文档构成一棵树;文档增删必须同步根索引 `design/gdd/02-系统清单.md` |
|
| 树形文档体系 | 全部设计文档构成一棵树;文档增删必须同步根索引 `design/gdd/02-系统清单.md` |
|
||||||
| 架构事实唯一源 | `design/engineering/architecture/architecture.md` 是架构事实的唯一权威(分层/模块归属/数据流/API 边界/测试与质量域);禁建第二份架构文档;历史决策记录只进 git commit log |
|
| 架构事实唯一源 | `design/engineering/architecture/architecture.md` 是架构事实的唯一权威(分层/模块归属/数据流/API 边界——只写约束面:难以改变的分层、依赖规则、边界契约与关键决策;实现现状归代码与代码头注,实现历史归 git commit log);禁建第二份架构文档;**架构文档写权限=用户专属**(2026-11-07 用户裁:agent 与技能只读,修订须用户发起) |
|
||||||
| 一页纸节点 | 一节、一条规则 ≤一页纸(约 ≤80 行);装不下就拆节 |
|
| 一页纸节点 | 一节、一条规则 ≤一页纸(约 ≤80 行);装不下就拆节 |
|
||||||
| 一系统一文档 | 不建 analysis 推演件;两三句能说清的"为什么"直接写进设计目的或规则正文 |
|
| 一系统一文档 | 不建 analysis 推演件;两三句能说清的"为什么"直接写进设计目的或规则正文 |
|
||||||
| 正文只写现行规则 | 禁删除线、"(作废)"、"(日期+拍板)"式注记;审计信息入对应文档附录 |
|
| 正文只写现行规则 | 禁删除线、"(作废)"、"(日期+拍板)"式注记;审计信息入对应文档附录 |
|
||||||
| 禁实现内容 | 系统文档与概念文档全文禁写实现细节——代码路径(`.gd`/`.py`/`.sh` 与运行时文件路径)、测试文件名、断言名、类名/方法名/信号名/常量名/调试与遥测入口名、提交号一律不出现;唯一例外=数据索引(`game/data/tables/*.tres` 与 `game/data/schemas/` 的表路径与表名、表字段名与表内枚值、存档键、封闭词表标签)。实现事实归 `architecture.md`;验收标准只写玩家或系统可观测面。本行由文档域闸的能力审计机检两个可判死的面(带后缀路径、反引号调用形态),其余靠写卡段人工核对;闸件清单与域划分的唯一出处=`tools/run_all_gates.sh` 头部 |
|
| 禁实现内容 | 系统文档与概念文档全文禁写实现细节——代码路径(`.gd`/`.py`/`.sh` 与运行时文件路径)、测试文件名、断言名、类名/方法名/信号名/常量名/调试与遥测入口名、提交号一律不出现;唯一例外=数据索引(`game/data/tables/*.tres` 与 `game/data/schemas/` 的表路径与表名、表字段名与表内枚值、存档键、封闭词表标签)。实现事实归代码与代码头注(2026-11-07 用户裁,架构文档只写约束面);验收标准只写玩家或系统可观测面。本行由文档域闸的能力审计机检两个可判死的面(带后缀路径、反引号调用形态),其余靠写卡段人工核对;闸件清单与域划分的唯一出处=`tools/run_all_gates.sh` 头部 |
|
||||||
| 正文单点维护 | 一条规则句只写在定义它的那份文档(owner 文档);其他文档要引用时写指针或语义概括,禁复制色值、尺寸、路径等可核对的具体值——上一句管不住数值之外的双写,本句补上。豁免面 = 执行侧文件必须带字面值才能工作时(生图提示词里的十六进制色、脚本参数),转写不算双写,但该文件头部必须写明"冲突时以 owner 文档为准" |
|
| 正文单点维护 | 一条规则句只写在定义它的那份文档(owner 文档)——此前半句全域适用;后半句(其他文档要引用时写指针或语义概括,禁复制色值、尺寸、路径等可核对的具体值)适用域=`design/gdd/**`(GDD 设计文档;2026-11-07 用户裁收窄——美术圣经与 UX 呈现规格层为可带值参考层,不在后半句约束内)。豁免面 = 执行侧文件必须带字面值才能工作时(生图提示词里的十六进制色、脚本参数),转写不算双写,但该文件头部必须写明"冲突时以 owner 文档为准" |
|
||||||
| 禁写变更记录 | 文档与代码文件内一律禁设「版本历史/修订记录/变更记录/修改记录/更新记录/更新日志」节或表格,禁逐版本叙述「改了哪些条款」;沿革与改动明细只进 git commit log。版本号可作为文档现行身份标记出现在文首状态行与正文引用中,但不得再挂变更表 |
|
| 禁写变更记录 | 文档与代码文件内一律禁设「版本历史/修订记录/变更记录/修改记录/更新记录/更新日志」节或表格,禁逐版本叙述「改了哪些条款」;沿革与改动明细只进 git commit log。版本号可作为文档现行身份标记出现在文首状态行与正文引用中,但不得再挂变更表 |
|
||||||
| 后置 ≠ 删除 | P1/P2 后置内容逐条列出;复活后置项 = 修订文档,禁静默加回 |
|
| 后置 ≠ 删除 | P1/P2 后置内容逐条列出;复活后置项 = 修订文档,禁静默加回 |
|
||||||
| 活体清单不冻结计数 | 对会生长的清单(文档树构成、UI 层项、RNG 流词表等)不写死计数与枚举——写指针到 owner(根索引/常量表/实现文件),现状值由 owner 承载;历史计数只进 git 提交信息 |
|
| 活体清单不冻结计数 | 对会生长的清单(文档树构成、UI 层项、RNG 流词表等)不写死计数与枚举——写指针到 owner(根索引/常量表/实现文件),现状值由 owner 承载;历史计数只进 git 提交信息 |
|
||||||
|
|
||||||
**数值纪律(概念/实现分界,2026-11-05 用户立)**:GDD 概念文档只定概念、机制与规则——是什么、有什么、为什么;数量面(多大、多少、多大概率)与呈现实现细节不进概念文档正文。分工三处:取值域与字段契约归 `game/data/schemas/*.gd`(表结构定义+域校验执法,provisional 随值标注);现行值归 `game/data/tables/*.tres`;呈现实现规格(冻结公式、像素值、动效参数)居 `design/gdd/ux/`=呈现实现设计规格层,豁免概念纯度约束。存量系统文档的旧调参表节由独立清扫批消化,消化期不作机检对象(现行闸无此项判据)。
|
**数值纪律(概念/实现分界,2026-11-05 用户立)**:GDD 概念文档只定概念、机制与规则——是什么、有什么、为什么;数量面(多大、多少、多大概率)与呈现实现细节不进概念文档正文。分工三处:取值域与字段契约归 `game/data/schemas/*.gd`(表结构定义+域校验执法,provisional 随值标注);现行值归 `game/data/tables/*.tres`;呈现实现规格(冻结公式、像素值、动效参数)居 `design/ux/`=呈现实现设计规格层,豁免概念纯度约束。存量系统文档的旧调参表节由独立清扫批消化,消化期不作机检对象(现行闸无此项判据)。
|
||||||
|
|
||||||
**登记处唯一性**:`design/registry/`(`entities.yaml`/`architecture.yaml`)已注销删除,禁再建第二处事实登记——术语进 术语表、数值进 `.tres`、架构进 架构文档、影响面靠全仓搜索概念规范名得出。强制收口条款:
|
**登记处唯一性**:`design/registry/`(`entities.yaml`/`architecture.yaml`)已注销删除,禁再建第二处事实登记——术语进 术语表、数值进 `.tres`、架构进 架构文档、影响面靠全仓搜索概念规范名得出。强制收口条款:
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
#### <条目名>(<YYYY-MM-DD>登记,来源=<playnote/会话提及/审计发现/批次移交>[,优先级=<P0/P1/P2>])
|
#### <条目名>(<YYYY-MM-DD>登记,来源=<playnote/会话提及/审计发现/批次移交>[,优先级=<P0/P1/P2>])
|
||||||
```
|
```
|
||||||
|
|
||||||
`优先级` 是紧急度标记,可选,规则三条:不写=默认档 P2;只有用户明示才写,会话不得自行给任何条目定档;P0 最高、P2 最低。它只服务阅读时的排序,不参与开工门、编排四查与状态机。`P0/P1/P2` 这组记号在本仓库只指待办紧急度,新文档禁另立别义。
|
`优先级` 是紧急度标记,可选,规则三条:不写=默认档 P2;只有用户明示才写,会话不得自行给任何条目定档;P0 最高、P2 最低。它只服务阅读时的排序,不参与开工门、编排五查与状态机。`P0/P1/P2` 这组记号在本仓库只指待办紧急度,新文档禁另立别义。
|
||||||
|
|
||||||
正文四属性模板:
|
正文四属性模板:
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
|
|
||||||
只写本条目自己交付的产出面,不预写下游实现批要动的面。`reports/` 下的需求卡片与批次产出物属过程件(第 11 节管辖),不计入 `文档` 档。四档与 AGENTS.md 硬红线的「改动四类」对应关系:`游戏代码`=需求改动(走写卡与编排段)、`工具代码`/`文档`/`美术素材` 三档各自对应工程改动/文档设计改动/美术素材改动三类直改通道;一条条目可以同时含多档。
|
只写本条目自己交付的产出面,不预写下游实现批要动的面。`reports/` 下的需求卡片与批次产出物属过程件(第 11 节管辖),不计入 `文档` 档。四档与 AGENTS.md 硬红线的「改动四类」对应关系:`游戏代码`=需求改动(走写卡与编排段)、`工具代码`/`文档`/`美术素材` 三档各自对应工程改动/文档设计改动/美术素材改动三类直改通道;一条条目可以同时含多档。
|
||||||
|
|
||||||
状态段用词自带所属设计线——`待文档设计`/`文档设计中`/`文档设计已闭合` 是文档线,`待美术设计`/`美术设计中`/`美术设计已闭合` 是美术线,不需要在标题另行声明走哪条线。状态一律取下例用词。状态行按**状态段累积制**书写:条目每推进一段,就把新状态段接在状态行末尾,段与段用+号连接,书写顺序=推进顺序;跨线的段一律保留、禁删(同一设计线内只留最新一段),下游段一旦写下不回收——状态履历供编排四查与开工核验比对。每段各自按状态词白名单校验,+号只作状态段连接符。
|
状态段用词自带所属设计线——`待文档设计`/`文档设计中`/`文档设计已闭合` 是文档线,`待美术设计`/`美术设计中`/`美术设计已闭合` 是美术线,不需要在标题另行声明走哪条线。状态一律取下例用词。状态行按**状态段累积制**书写:条目每推进一段,就把新状态段接在状态行末尾,段与段用+号连接,书写顺序=推进顺序;跨线的段一律保留、禁删(同一设计线内只留最新一段),下游段一旦写下不回收——状态履历供编排五查与开工核验比对。每段各自按状态词白名单校验,+号只作状态段连接符。
|
||||||
|
|
||||||
```
|
```
|
||||||
各设计线推进序列(同条目两条线并列推进时,两段各写各的):
|
各设计线推进序列(同条目两条线并列推进时,两段各写各的):
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
|
|
||||||
设计线段与下游段同条并存是合法形态:状态行里出现过的**每条设计线各自留最新一段**,跨线依赖不阻塞本条推进(文档线闭合后写卡、美术线仍未出图,就把 `文档设计已闭合` 与 `待美术设计` 并写)。「写卡前本条要落的那条设计线必须已闭合」是实现侧的执行义务,由编排段查卡片凭据核对,不靠标题声明——闸只查同线并现多段。
|
设计线段与下游段同条并存是合法形态:状态行里出现过的**每条设计线各自留最新一段**,跨线依赖不阻塞本条推进(文档线闭合后写卡、美术线仍未出图,就把 `文档设计已闭合` 与 `待美术设计` 并写)。「写卡前本条要落的那条设计线必须已闭合」是实现侧的执行义务,由编排段查卡片凭据核对,不靠标题声明——闸只查同线并现多段。
|
||||||
|
|
||||||
状态行只写状态词:去掉特批标记与「(备选)」后缀后,残留任何括号即违规。闭合类状态词(文档设计已闭合/美术设计已闭合/已写卡/已写入)的证据——设计定稿路径+版本、art-bible 条款版本、需求卡片路径、落点文档+版本——一律写在实况的关联文档清单里,由流水线闸到正文核对;已编迭代 N 段的交叉核依据=实况清单里的需求卡片路径。
|
状态行只写状态词:去掉特批标记与「(备选)」后缀后,残留任何括号即违规。闭合类状态词(文档设计已闭合/美术设计已闭合/已写卡/已写入)的证据——设计定稿路径+版本、art-bible 条款版本、需求卡片路径(「已写卡」段的复核凭据=卡内「复核记录」节,2026-11-06 用户裁:不另设复核报告文件;对文件名日期 ≥2026-11-06 的卡生效,旧卡不回头改,核对由 `tools/pipeline_gate.py` 的卡片复核判据到卡正文做)、落点文档+版本——一律写在实况的关联文档清单里,由流水线闸到正文核对;已编迭代 N 段的交叉核依据=实况清单里的需求卡片路径。
|
||||||
|
|
||||||
三种条目形态与一种后缀:
|
三种条目形态与一种后缀:
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
主工作区(master 检出)只作合并落点,一切开发/设计改动禁止直接发生在主工作区(2026-10-31 用户裁恢复;验证模型=批内按 §4 改完即测、合回后远端 CI 是唯一强制全量验证点,细则见本节第 3 条):
|
主工作区(master 检出)只作合并落点,一切开发/设计改动禁止直接发生在主工作区(2026-10-31 用户裁恢复;验证模型=批内按 §4 改完即测、合回后远端 CI 是唯一强制全量验证点,细则见本节第 3 条):
|
||||||
|
|
||||||
1. **worktree 车道(一切面)**:每回合先建独立 worktree(建区粒度=回合,会话单区细则见第 5 条):`git worktree add ../g-plan2-<任务名> -b <任务分支>`;建区后立刻跑 `tools/setup_worktree_userdir.sh`——给该区独立 Godot user 目录(测试夹具、试玩日志、截图产物不与其他区共用;主区不生成,真实档保持原位)。所有改动与提交都在 worktree 内自由进行——commit 点零钩子检查(`tools/hooks/pre-commit` 已删除)。豁免面仅 `.zcode/`(钩子与配置)与 `.qoder/`(本机 harness 配置)允许主工作区直改——两份实测均不入 git(走 worktree 反而带不进去,改动只对本机生效)
|
1. **worktree 车道(一切面)**:每回合先建独立 worktree(建区粒度=回合,会话单区细则见第 5 条):`git worktree add ../g-plan2-<任务名> -b <任务分支>`;建区后立刻跑 `tools/setup_worktree_userdir.sh`——给该区独立 Godot user 目录(测试夹具、试玩日志、截图产物不与其他区共用;主区不生成,真实档保持原位)。所有改动与提交都在 worktree 内自由进行——commit 点零钩子检查(`tools/hooks/pre-commit` 已删除)。豁免面仅 `.zcode/`(钩子与配置)与 `.qoder/`(本机 harness 配置)允许主工作区直改——两份实测均不入 git(走 worktree 反而带不进去,改动只对本机生效)
|
||||||
2. **收口顺序(固定)**:**冻结 → 件核 → 并 master → 重塑 → 主区合回 → 删区**——代码与断言改完即冻结,全仓件核 grep 查残留;master 已被别的批次推进时先在 worktree 内 `git merge master` 解冲突(必须在合回之前,合回后才并=CI 验的是中间态);**重塑**=迭代分支(iter<N> 形)合回前执行 `python tools/reshape_cards.py`,把分支线性史按卡末态快照压成一卡一笔(可选追加一笔纯文档收尾),master 台账由此每卡一行——工具自带「重塑前后树逐字节一致」断言与 backup 分支,不改任何文件内容;非迭代批免重塑;然后主工作区 `git merge --no-ff <任务分支>`——这是主区唯一合法写动作(合回守卫对迭代分支数卡校验,未归卡提交拦下)。**合回落地即 `git worktree remove`+删分支(合回即删,2026-09-19 原裁);post-merge 钩子已在合回落地时自动触发 CI,红态不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,非 iter<N> 形免重塑免数卡)修复提交再合,落地复验追绿后删修复区**。批内的验证义务按 §4 改完即测铁规履行——改完即测自己改过的那部分,不请示、不等点名;收口顺序本身不设跑批关口。**卡片复核前置判据(2026-11-05 用户裁)**:需求卡片的 grilling 复核先于卡片提交、卡片提交先于合回——复核未跑完、缺陷清单未裁完,禁把卡片落 commit(落了也不算成立),`master` 永不落未成立卡;本条与 §2 段三出口铁律、doc-conventions §12.1「已写卡」凭据同判。
|
2. **收口顺序(固定)**:**冻结 → 件核 → 并 master → 重塑 → 主区合回 → 删区**——代码与断言改完即冻结,全仓件核 grep 查残留;master 已被别的批次推进时先在 worktree 内 `git merge master` 解冲突(必须在合回之前,合回后才并=CI 验的是中间态);**重塑**=迭代分支(iter<N> 形)合回前执行 `python tools/reshape_cards.py`,把分支线性史按卡末态快照压成一卡一笔(可选追加一笔纯文档收尾),master 台账由此每卡一行——工具自带「重塑前后树逐字节一致」断言与 backup 分支,不改任何文件内容;非迭代批免重塑;然后主工作区 `git merge --no-ff <任务分支>`(pre-merge-commit 钩子先跑前置检查——冒烟+单元全套件约 2 分钟,红则停合并提交,细则见第 4 条 ③)——这是主区唯一合法写动作(合回守卫对迭代分支数卡校验,未归卡提交拦下)。**合回落地即 `git worktree remove`+删分支(合回即删,2026-09-19 原裁);post-merge 钩子已在合回落地时自动触发 CI,红态不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,非 iter<N> 形免重塑免数卡)修复提交再合,落地复验追绿后删修复区**。批内的验证义务按 §4 改完即测铁规履行——改完即测自己改过的那部分,不请示、不等点名;收口顺序本身不设跑批关口。**卡片复核前置判据(2026-11-05 用户裁)**:需求卡片的 grilling 复核先于卡片提交、卡片提交先于合回——复核未跑完、缺陷清单未裁完,禁把卡片落 commit(落了也不算成立),`master` 永不落未成立卡;本条与 §2 段三出口铁律、doc-conventions §12.1「已写卡」凭据同判。
|
||||||
3. **合回后验证(远端 CI,2026-11-03 用户裁)**:git merge 合回 master 落地后 post-merge 钩子(`tools/hooks/post-merge`)自动 `git push origin master` 触发远端 CI(Gitea Actions,runner=Mac 本机 host 模式),工作流按改动域分流(分流算法单点=`tools/ci/domain_route.sh`:游戏码批=两域全量含渲染闸,文档批=文档域秒级闸,纯闸件/管线批=零触发)——唯一强制全量验证点。远端结果用 `tools/ci_check.sh <合并提交>` 按需现查(读该提交任务的 run 自身 `status`/`conclusion`,只呈报、不落盘),agent 开工先读 CI 状态的纪律不变,红未修不开新批。**绿须坐实**:零触发批的 run 照样建、照样 conclusion=success,但跑闸步是 `skipped`(run 55 实证)——一条闸都没跑不构成验证,现查件对此呈报「未验」(退出码 4),禁当绿证用;job 列表为空、取不到步级读数或工作流里没有跑闸步时呈报「不可判」,同样禁当绿证。CI 红态不回滚合并——修复走新开修复 worktree(`fix-<任务名>` 分支,非 iter<N> 形免重塑免数卡),修复合回落地即再推再验追绿(追绿同链)。导入缓存刷新(.godot 不入 git 的在册坑)由工作流「导入缓存刷新」步接管。**合回零等待纪律(2026-11-04 用户裁,取代 2026-11-02 回执等待纪律)**:合回落地即向用户呈报本批总结并止回合——不挂后台轮询、不等回执、不被唤醒;CI 结论什么时候要看就现查一次(`tools/ci_check.sh`,run 那时早已落定,秒级)。退役缘由=原轮询件把「commit status 离开 pending」当终局判据,会把 run 未落定期的尝试级失败写成终局红(run 37 实证:开跑 36 秒写红,该 run 三分半后 `conclusion=success`),且零触发批与 runner 排队必熬满超时再写红;同 commit 的多路轮询还重复覆写同一份判定。跑闸等一切分钟级跑批的等待纪律不变——后台运行,禁前台 sleep/轮询循环。
|
3. **合回后验证(远端 CI,2026-11-03 用户裁)**:git merge 合回 master 落地后 post-merge 钩子(`tools/hooks/post-merge`)自动 `git push origin master` 触发远端 CI(Gitea Actions,runner=Mac 本机 host 模式),工作流按改动域分流(分流算法单点=`tools/ci/domain_route.sh`:游戏码批=两域全量含渲染闸,文档批=文档域秒级闸,纯闸件/管线批=零触发)——唯一强制全量验证点。远端结果用 `tools/ci_check.sh <合并提交>` 按需现查(读该提交任务的 run 自身 `status`/`conclusion`,只呈报、不落盘),agent 开工先读 CI 状态的纪律不变,红未修不开新批。**绿须坐实**:零触发批的 run 照样建、照样 conclusion=success,但跑闸步是 `skipped`(run 55 实证)——一条闸都没跑不构成验证,现查件对此呈报「未验」(退出码 4),禁当绿证用;job 列表为空、取不到步级读数或工作流里没有跑闸步时呈报「不可判」,同样禁当绿证。CI 红态不回滚合并——修复走新开修复 worktree(`fix-<任务名>` 分支,非 iter<N> 形免重塑免数卡),修复合回落地即再推再验追绿(追绿同链)。导入缓存刷新(.godot 不入 git 的在册坑)由工作流「导入缓存刷新」步接管。**合回零等待纪律(2026-11-04 用户裁,取代 2026-11-02 回执等待纪律)**:合回落地即向用户呈报本批总结并止回合——不挂后台轮询、不等回执、不被唤醒;CI 结论什么时候要看就现查一次(`tools/ci_check.sh`,run 那时早已落定,秒级)。退役缘由=原轮询件把「commit status 离开 pending」当终局判据,会把 run 未落定期的尝试级失败写成终局红(run 37 实证:开跑 36 秒写红,该 run 三分半后 `conclusion=success`),且零触发批与 runner 排队必熬满超时再写红;同 commit 的多路轮询还重复覆写同一份判定。跑闸等一切分钟级跑批的等待纪律不变——后台运行,禁前台 sleep/轮询循环。
|
||||||
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 钩子——远端 CI 触发(只推送,不挂等待;仅主工作区,任务 worktree 内的合并不触发)。③git 层不设车道钩子——用户手工改动不受限;ZCode 层只约束 agent(子代理不经守卫层)
|
4. **执法分层(全机械,零自觉依赖)**:①`.zcode/hooks/worktree-guard.sh`(PreToolUse,本机件不入 git)——agent 侧:主工作区 Edit/Write 拦截(豁免 `.zcode/`、`.qoder/`;worktree 内目标快速放行)、主区一切 `git commit` 一律拦(含 MERGE_HEAD 态续合与链式命令;冲突/红态一律 git merge --abort → 回 worktree → 重新 git merge --no-ff)、`git commit --no-verify` 拦截(该旗标仅属用户)、iter<N> 分支合回的一卡一提交数卡校验、规则闸(写 design//game/ 前核对会话规约读取记录)。②post-merge 钩子——远端 CI 触发(只推送,不挂等待;仅主工作区,任务 worktree 内的合并不触发)。③git 层钩子=合回链两件:pre-merge-commit(合回前置检查,2026-11-06 用户裁:主区 merge 落合并提交前自动跑 `tools/run_all_gates.sh --premerge`=冒烟+单元全套件 4 分片,热导入缓存约 2 分钟;exit≠0 拦合并提交不拦合并动作——红态仓库停 MERGE_HEAD 态,处置唯一=git merge --abort → 回 worktree 处理 → 重新 git merge --no-ff(禁 git commit 续合);快进合并不触发;--no-verify 可跳过且仅属用户)+post-merge(远端 CI 触发,只推送,不挂等待);合回链之外 git 层不设车道钩子——用户手工改动不受限;ZCode 层只约束 agent(子代理不经守卫层)
|
||||||
5. **会话单区(2026-11-04 用户裁)**:建区粒度=回合——同一时刻每会话至多一个 worktree 在役;合入删区之前,会话内用户追加的事项一律并入在役区推进,禁为追加事项另开新区。区内全部事项完成后只做一次合入(一次 `git merge --no-ff`、post-merge 一次推送、远端 CI 只跑一次),追加事项在合入提交信息里分列;无改动需求的事项不建区。合回删区后用户再发令的事项=新回合,另开新区(区名取该回合主任务名)。CI 红的 `fix-<任务名>` 修复区属同一回合的追绿延续,不另算新区。迭代实现批(iter<N> 形分支)独占回合——其他类事项不得并入迭代区(合回守卫数卡校验本就拦未归卡提交),待其合回后按新回合另开。
|
5. **会话单区(2026-11-04 用户裁)**:建区粒度=回合——同一时刻每会话至多一个 worktree 在役;合入删区之前,会话内用户追加的事项一律并入在役区推进,禁为追加事项另开新区。区内全部事项完成后只做一次合入(一次 `git merge --no-ff`、post-merge 一次推送、远端 CI 只跑一次),追加事项在合入提交信息里分列;无改动需求的事项不建区。合回删区后用户再发令的事项=新回合,另开新区(区名取该回合主任务名)。CI 红的 `fix-<任务名>` 修复区属同一回合的追绿延续,不另算新区。迭代实现批(iter<N> 形分支)独占回合——其他类事项不得并入迭代区(合回守卫数卡校验本就拦未归卡提交),待其合回后按新回合另开。
|
||||||
|
|
||||||
## 2. 五段流水线
|
## 2. 五段流水线
|
||||||
@@ -23,11 +23,11 @@
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 一·登记 | 无(闸管格式) | 待办清单条目 | 条目=标题登记元数据(日期/来源/可选优先级)+正文四属性(实况/缺口/改动面/状态);标题登记后不再变,正文随进程演进。格式与状态机权威=doc-conventions 第 12 节 |
|
| 一·登记 | 无(闸管格式) | 待办清单条目 | 条目=标题登记元数据(日期/来源/可选优先级)+正文四属性(实况/缺口/改动面/状态);标题登记后不再变,正文随进程演进。格式与状态机权威=doc-conventions 第 12 节 |
|
||||||
| 二·文档设计/美术设计 | doc-design(文档线,兼任反哺点写入)/asset-ingest(美术录入;样张素材由用户主导产出) | GDD 文档或 art-bible/过审样张素材;画面类需求另出预览图(文档线,2026-11-05 用户裁) | 用户提起或从待办清单取出;会话内进行、用户主导、禁无监管自跑;经用户点头确认心智一致才许写入文档;完成判据=待裁点清零,带未裁点的是讨论稿;设计线闭合凭据记入待办清单实况清单(文档线=文档路径+版本号,美术线=art-bible 条款版本);缺哪条线写在缺口属性,闭合与否写在状态段。画面类需求(新增画面要素/布局/配色/动效等触碰画面呈现规格的改动)设计段先出预览图=目标画面的 HTML/SVG 效果图(diagram-design 通道,AGENTS.md 图优先的同款载体),经用户人审通过才许进写卡段;预览图内嵌对应 ux/ 规格文档并随附像素级视觉判据句(§7 第 2 条同款写法);缺陷修复以现行规格与在库基线为准,不触发新预览 |
|
| 二·文档设计/美术设计 | doc-design(文档线,兼任反哺点写入)/asset-ingest(美术录入;样张素材由用户主导产出) | GDD 文档或 art-bible/过审样张素材;画面类需求另出预览图(文档线,2026-11-05 用户裁) | 用户提起或从待办清单取出;会话内进行、用户主导、禁无监管自跑;经用户点头确认心智一致才许写入文档;完成判据=待裁点清零,带未裁点的是讨论稿;设计线闭合凭据记入待办清单实况清单(文档线=文档路径+版本号,美术线=art-bible 条款版本);缺哪条线写在缺口属性,闭合与否写在状态段。画面类需求(新增画面要素/布局/配色/动效等触碰画面呈现规格的改动)设计段先出预览图=目标画面的 HTML/SVG 效果图(diagram-design 通道,AGENTS.md 图优先的同款载体),经用户人审通过才许进写卡段;预览图内嵌对应 ux/ 规格文档并随附像素级视觉判据句(§7 第 2 条同款写法);缺陷修复以现行规格与在库基线为准,不触发新预览 |
|
||||||
| 三·写需求卡片 | req-card | 需求卡片 | 设计线闭合后用户发令;新玩法/新系统/新内容必须有设计定稿前置,例外=需求性工程条目(缺陷修复/重构等改游戏行为)凭实况里的证据指认跳过设计线;配套维护类(工程债/测试基建/工具维护,不动游戏行为)=工程改动直改类,不走本段,由用户发令直改;卡片必经 grilling 多轮复核、零待裁点才成立;写完在待办清单状态记「已写卡」,卡片路径记入实况清单(防遗忘);画面类需求卡片必引设计段已人审的预览图(验收判据的判据出处行锚指向 ux/ 内嵌预览节,test-conventions §8.3 锚口径不变) |
|
| 三·写需求卡片 | req-card | 需求卡片 | 设计线闭合后用户发令;新玩法/新系统/新内容必须有设计定稿前置,例外=需求性工程条目(缺陷修复/重构等改游戏行为)凭实况里的证据指认跳过设计线;配套维护类(工程债/测试基建/工具维护,不动游戏行为)=工程改动直改类,不走本段,由用户发令直改;卡片必经 grilling 多轮复核、零待裁点才成立;复核发现按四类去向处置(2026-11-05 用户立规,定义在 req-card 技能「复核发现四类分流」:自判=查权威文档或查代码现状有唯一答案,复核者自己下结论改卡;补写=卡里漏写,回炉补全;待裁=几种做法都不违规且代价不同、影响玩法取向,才交用户;退回上游=文档设计线未闭合、美术设计线未闭合、或架构与代码规范本身冲突,停笔退对应段);成立凭据=卡内「复核记录」节(2026-11-06 用户裁:不另设复核报告文件),顺序未走完禁对用户称完成、禁落 commit(同 §1 第 2 条卡片复核前置判据);写完在待办清单状态记「已写卡」,卡片路径记入实况清单(防遗忘);画面类需求卡片必引设计段已人审的预览图(验收判据的判据出处行锚指向 ux/ 内嵌预览节,test-conventions §8.3 锚口径不变) |
|
||||||
| 四·迭代编排 | iter-plan | roadmap 迭代行 | 编排四查:①每卡卡片文件存在 ②每卡设计闭合凭据齐(或需求性工程条目的证据指认)③估时与冻结线——所选卡估时按区间**中值**求和(单位工作日、写精确值不取整):**卡片任何工作量均可编入**(2026-10-25 用户立:工作量限制属迭代层、非卡片层);编入后迭代总量 <5 个工作日=迭代行状态「冻结待凑批」、不可开工,凑批 ≥5 后由编排段改「待开工」(迭代体量偏好,2026-10-21 用户立、2026-10-25 改冻结制);5–10 个工作日为常规区间;超过 10 个工作日须经用户确认(确认前呈报整批/拆批两案等裁,禁自行拆分或塞入),确认后迭代行随带日期特批标记;超过 20 个工作日禁止编(硬上限,用户确认也不放行,必须拆批)④写完 roadmap 行后跑流水线闸确认绿;编入未完成迭代,新开迭代行经用户确认 |
|
| 四·迭代编排 | iter-plan | roadmap 迭代行 | **开工前预检(2026-11-07 用户立)**:收令点名拟编卡集后、五查与落表前,对卡集做一轮只读事实面预检——八类检查、P1/P2/P3 分级去向与只读子代理执行方式=iter-plan 技能「第 3 步·开工前预检」;P1 红项停编排、退回写卡段,禁编入。预检目标=尽量减少实现期停工、非杜绝——环境漂移与卡片并行修改仍可在实现期停工,由实现段异常分级与 iter T0 开工日窄复核兜底。编排五查:①每卡卡片文件存在 ②每卡设计闭合凭据齐(或需求性工程条目的证据指认)③估时与冻结线——所选卡估时按区间**中值**求和(单位工作日、写精确值不取整):**卡片任何工作量均可编入**(2026-10-25 用户立:工作量限制属迭代层、非卡片层);编入后迭代总量 <5 个工作日=迭代行状态「冻结待凑批」、不可开工,凑批 ≥5 后由编排段改「待开工」(迭代体量偏好,2026-10-21 用户立、2026-10-25 改冻结制);5–10 个工作日为常规区间;超过 10 个工作日须经用户确认(确认前呈报整批/拆批两案等裁,禁自行拆分或塞入),确认后迭代行随带日期特批标记;超过 20 个工作日禁止编(硬上限,用户确认也不放行,必须拆批)④每卡复核记录在位(2026-11-05 用户立规;2026-11-06 用户裁凭据换代——复核凭据=「复核记录」节自身,不另查报告文件)——卡内有「复核记录」节;缺节或节内任一条发现没有去向标记则呈报退回写卡段,禁编入,本段不代跑复核也不代补记录(生效=卡片文件名日期 ≥2026-11-06,旧卡不回头改)⑤写完 roadmap 行后跑流水线闸确认绿;编入未完成迭代,新开迭代行经用户确认 |
|
||||||
| 五·实现 | iter | 代码与配置,可运行的游戏 | 需求卡片永不单独施工,统一由用户指定迭代号触发(=U0 开工令),按 iter 技能与本文 §3 执行;**本段是代码实现批:禁写 `design/` 与根规则文件,产出物只落 `reports/`(见 §3 第 12 条)**;设计权威文档(GDD/art-bible)批内一律不更新;完成人闸=实机目检清单+实现决定记录写齐即完成批内义务;画面类需求实现批另按 test-conventions §8.2 黄金图基线冻结口径执行(实跑截图入基线前用户对照预览图确认一眼,此后渲染闸自动盯) |
|
| 五·实现 | iter | 代码与配置,可运行的游戏 | 需求卡片永不单独施工,统一由用户指定迭代号触发(=U0 开工令),按 iter 技能与本文 §3 执行;**本段是代码实现批:禁写 `design/` 与根规则文件,产出物只落 `reports/`(见 §3 第 12 条)**;设计权威文档(GDD/art-bible)批内一律不更新;完成人闸=实机目检清单+实现决定记录写齐即完成批内义务;画面类需求实现批另按 test-conventions §8.2 黄金图基线冻结口径执行(实跑截图入基线前用户对照预览图确认一眼,此后渲染闸自动盯) |
|
||||||
|
|
||||||
**实现段零裁断**:实现段的输入在编排段出口已锁死(卡片零待裁点+设计闭合凭据齐+编排四查过)。实现中冒出卡片没写清的分歧=上游缺陷——停该卡、待办清单状态回退+缺口补记,退回上游;禁自答、禁内联提问求裁断;该卡停摆不阻塞同迭代其他卡。环境故障与测试红走异常分级(自救重试/记录继续/停机呈报)。代拍板白名单保留:授权发生在卡片审问阶段,实现只执行预授权;超白名单/超卡片明列范围事项记入实现报告「实现决定记录」节备案,不另立追认单。
|
**实现段零裁断**:实现段的输入在编排段出口已锁死(卡片零待裁点+设计闭合凭据齐+编排五查过)。实现中冒出卡片没写清的分歧=上游缺陷——停该卡、待办清单状态回退+缺口补记,退回上游;禁自答、禁内联提问求裁断;该卡停摆不阻塞同迭代其他卡。环境故障与测试红走异常分级(自救重试/记录继续/停机呈报)。代拍板白名单保留:授权发生在卡片审问阶段,实现只执行预授权;超白名单/超卡片明列范围事项记入实现报告「实现决定记录」节备案,不另立追认单。
|
||||||
|
|
||||||
**流水线闸**:`tools/pipeline_gate.py` 机检待办清单与 roadmap 两文件的格式与互相引用;已注册进 `run_all_gates.sh` 文档域。流程文档的条目格式、迭代行格式与状态机细则见 doc-conventions 第 12 节。
|
**流水线闸**:`tools/pipeline_gate.py` 机检待办清单与 roadmap 两文件的格式与互相引用;已注册进 `run_all_gates.sh` 文档域。流程文档的条目格式、迭代行格式与状态机细则见 doc-conventions 第 12 节。
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
每个批次按以下链路执行(本清单是总索引,细则散见各规约;冲突以细则为准,发现清单过时须同批修订):
|
每个批次按以下链路执行(本清单是总索引,细则散见各规约;冲突以细则为准,发现清单过时须同批修订):
|
||||||
|
|
||||||
**开工前**
|
**开工前**
|
||||||
1. **先检索后提问**——先查在册记忆与权威文档,禁把已裁决事项当新问题重问或重踩在册坑
|
1. **先检索后提问**——先查在册记忆与权威文档,禁把已裁决事项当新问题重问或重踩在册坑。本条对五段流水线的每一段都生效,不限批次开工前(2026-11-05 用户扩面):权威文档(所属系统 owner 文档、本文与 `design/engineering/` 其余规约、architecture、术语表)或代码现状能给出唯一答案的,禁当问题呈报用户——写了卡片的复核环节也一样,详见 req-card 技能「复核发现四类分流」
|
||||||
2. **需求卡片全列备选案**——每个待拍板点列全部备选方案与代价交用户裁决,禁卡片内自行定夺
|
2. **需求卡片全列备选案**——每个待拍板点列全部备选方案与代价交用户裁决,禁卡片内自行定夺。**待拍板点的边界(2026-11-05 用户立规)**=只有「几种做法都不违反权威文档、代价不同、影响玩法或体验取向」的分叉才算待拍板点;查权威文档或查代码现状就有答案的、以及卡里漏写要补的(名字与参数、测试落点、钉住的取值),一律由写卡段与复核环节自己定下来写进卡,禁转成问句
|
||||||
3. **用户发开工令才动手**——需求卡片经用户批准(U0)后方开工
|
3. **用户发开工令才动手**——需求卡片经用户批准(U0)后方开工
|
||||||
|
|
||||||
**环境与基线**
|
**环境与基线**
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补
|
7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补
|
||||||
|
|
||||||
**完成**
|
**完成**
|
||||||
8. **合回后 CI 验证(唯一强制全量验证点)**——主工作区 `git merge --no-ff <任务分支>` 落地后 post-merge 钩子自动推送 origin master 触发远端 CI;远端按改动域分流(§1 第 3 条),全量档兜的是跨卡触面、探针与未申报套件的消费漏网(迭代 44 实证),判定与红项用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 终局态,只呈报不落盘)。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。`tools/run_all_gates.sh` 是全部验证闸的**唯一入口、唯一清单与唯一域划分(含选闸算法与套件族映射表)**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。开发期的验证义务与选档一律见 §4,CI 全量档不替代它。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占 CI 全量——其质量义务=按 §4 把该件实跑一遍(最小参数全路径含产出落盘)并核对判据口径未变;闸真崩溃时远端 CI 判红在案(job 失败=verdict 红,fail-closed 语义保留)
|
8. **合回后 CI 验证(唯一强制全量验证点)**——主工作区 `git merge --no-ff <任务分支>` 落地后 post-merge 钩子自动推送 origin master 触发远端 CI;远端按改动域分流(§1 第 3 条),全量档兜的是跨卡触面、探针与未申报套件的消费漏网(迭代 44 实证),判定与红项用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 终局态,只呈报不落盘)。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。`tools/run_all_gates.sh` 是全部验证闸的**唯一入口、唯一清单与唯一域划分(含选闸算法与套件族映射表)**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。开发期的验证义务与选档一律见 §4,CI 全量档不替代它。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占 CI 全量——其质量义务=按 §4 把该件实跑一遍(最小参数全路径含产出落盘)并核对判据口径未变;闸真崩溃时远端 CI 判红在案(job 失败=verdict 红,fail-closed 语义保留)。合回前的 pre-merge-commit 前置检查(§1 第 4 条 ③)是当场拦截面不是验证台账——不落回执不入基线,不改变本条「唯一强制全量验证点」口径
|
||||||
9. **重跑语义(2026-10-30 用户裁)**——同一份字节禁止第二次人手跑;允许的重跑只剩两类:① CI 红后的修复合回(post-merge 钩子再推再验,每轮修复至多触发一轮);② 用户自发发起的全量回归。「跑都跑了再跑一遍保险」「顺手改点再补一跑」都不构成重跑理由。导入缓存刷新由远端工作流「导入缓存刷新」步接管,合并后无手工动作
|
9. **重跑语义(2026-10-30 用户裁)**——同一份字节禁止第二次人手跑;允许的重跑只剩三类:① CI 红后的修复合回(post-merge 钩子再推再验,每轮修复至多触发一轮);② 用户自发发起的全量回归;③ 合回 pre-merge-commit 前置检查(§1 第 4 条 ③——与合回后远端跑批判面不同档〔拦截面 vs 台账〕,不算同一判面的二次人手跑)。「跑都跑了再跑一遍保险」「顺手改点再补一跑」都不构成重跑理由。导入缓存刷新由远端工作流「导入缓存刷新」步接管,合并后无手工动作
|
||||||
10. **批次完成后的登记义务**——合回 master 后按 doc-conventions §12.1 推进待办清单条目状态(做完整条删除),涉及迭代编排的在 roadmap 迭代总表与顶部「当前位」节换代——执行入口=项目技能 batch-closure(批后收尾与中间文档退役),跨会话教训写记忆库。批次过程与结论由 git 提交信息承载,禁止再写会话状态文件(见 doc-conventions 第 10 节)。`design/` 与根规则文件(`AGENTS.md`/`roadmap.md`/`待办清单.md`/`体验验证清单.md`)实现批禁写,见 §12
|
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/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注
|
11. **文档同步闸(实现批禁写文档)**——实现批**禁写 `design/` 整个目录与根规则文件**,**另禁写 `game/tests/README.md`(能力清单,归写卡段维护,test-conventions §8.9)**,要往外交代的东西一律落 `reports/`:实现报告 `reports/iter<N>-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务+实现决定记录——超白名单/超卡片明列范围事项逐条记「决了什么/为什么/代价/撤销方式」,全部按卡执行时只写一行「零拍板」)、GDD 反哺点清单 `reports/iter<N>-反哺点-<日期>.md`(每条写清哪个文件哪一节、改成什么、依据是什么)。设计权威文档(GDD/art-bible)**任何批都不直改**:用户在会话中逐点裁决后,由工程/文档设计改动批(直改类)写入 `design/`(执行入口=doc-design 技能),并把反哺条目从 `reports/` 清掉(吸收即死;退役执行=batch-closure 技能)。机械面文档(roadmap 行/术语表/README 工具注)同样归工程/文档设计改动批在合并前更新。反哺点未落地期间相关 GDD 节视为待反哺,读前先查 `reports/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注
|
||||||
12. **实机目检归用户,只登记不阻塞**——真人检测项登记进实现报告目检总清单与体验验证清单即完成批内义务;禁把等目检当停工理由或完成前置
|
12. **实机目检归用户,只登记不阻塞**——真人检测项登记进实现报告目检总清单与体验验证清单即完成批内义务;禁把等目检当停工理由或完成前置
|
||||||
|
|||||||
@@ -13,6 +13,20 @@
|
|||||||
核心层验收标准通过不算有测试:GDScript 编译不查字典字段与时序,呈现层错误只在运行时暴露。
|
核心层验收标准通过不算有测试:GDScript 编译不查字典字段与时序,呈现层错误只在运行时暴露。
|
||||||
测试必须证明功能可达(用户真的能用到)且行为正确(结果符合验收标准)。
|
测试必须证明功能可达(用户真的能用到)且行为正确(结果符合验收标准)。
|
||||||
|
|
||||||
|
### 1.1 测试层三元组(2026-11-07 用户裁——测试层识别权威表)
|
||||||
|
|
||||||
|
识别一个测试层靠三元组,不靠名字——**层级名只是代称**;名称与定义的登记面=`design/gdd/术语表.md`,本表是识别判据的单点:
|
||||||
|
|
||||||
|
| 层(代称) | 职责 | 触发时间点 | 覆盖面积 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 冒烟测试 | 真实开机路径存活检查——启动/加载表/进主屏,零逻辑判定 | 每次代码域跑批+合回前置检查+远端 CI(三件保险恒跑不降) | 最小:一条真实开机路径 |
|
||||||
|
| 单元测试 | 受控裸环境断言面:单机制契约+跨系统真实路径闭环——不加载开机装配、手工构造注入实跑;闭环套件=两以上真实系统手工装配×落盘往返,性质归属由各套件头注「跨系统面」句承载 | 同冒烟(恒跑;关联档选套件=需求卡片申报∪diff 推导并集,横切回落全量) | 领域类原子行为+跨系统接缝——不含开机装配与画面 |
|
||||||
|
| 系统测试 | 真实开机+真实玩法路径行为断言(推理→战斗→结算→推进) | 同冒烟(恒跑) | 完整装配下的玩法旅程 |
|
||||||
|
| 场景探针 | 真实实例化场景+真输入管线(合成输入事件走输入管线)的 UI 可达性/可见性/状态 | 代码域跑批(测量面批记 SKIP)+远端 CI | 逐 UI 区域交互动线 |
|
||||||
|
| 渲染闸 | 窗口化真实渲染截图 vs 冻结基线图逐像素容差比对 | 代码域跑批(测量面批与 --quick 记 SKIP)+远端 CI | 像素呈现(主题/素材/排版) |
|
||||||
|
|
||||||
|
层级合并说明(2026-11-07 用户裁):跨系统真实路径闭环套件归单元层承载,三套件实体在 `game/tests/unit/`;「集成测试/集成用例/集成层/集成侧/集成宿主/集成族」为退役词(术语表「退役词对照」;S11 注释面+用语审计文档面双承接)。
|
||||||
|
|
||||||
## 2. 场景级探针标配
|
## 2. 场景级探针标配
|
||||||
|
|
||||||
每新增一个可交互 UI 区域(视图/覆盖层/面板),必须配套场景级 headless 探针:
|
每新增一个可交互 UI 区域(视图/覆盖层/面板),必须配套场景级 headless 探针:
|
||||||
@@ -20,6 +34,8 @@
|
|||||||
|
|
||||||
凡模态覆盖层,探针必须断言:打开后自身 visible 且遮挡物已隐藏(模态被遮挡 = 功能存在但不可达)。
|
凡模态覆盖层,探针必须断言:打开后自身 visible 且遮挡物已隐藏(模态被遮挡 = 功能存在但不可达)。
|
||||||
|
|
||||||
|
**UI 驱动断言须走真输入管线(2026-11-06 立)**:探针里「点按钮/点场景物件」类驱动断言,一律经引擎输入管线承载(合成 InputEvent 走 `push_input`,press+release 成对;合成滚轮同样必须 press+release 成对——只发 press 会把鼠标焦点钉死在按下点控件上,后续点击全部失效);信号直发(`pressed.emit()` 等)绕过命中测试,保不了「玩家点击可达」,只许用于真输入到不了的面并当场标〔接线断言〕(现役例:置灰态穿透钉处理器兜底)。折叠区控件先以真输入滚轮滚入可视区再点。每个动线断言钉「落点」判定(点了之后到哪个屏/哪层可见),防驱动中断后的空转假绿。真输入命中控件时自动登记控件覆盖(探针共用面登记件落 `.gates/` 观测产物),覆盖面生长不靠人记。
|
||||||
|
|
||||||
## 3. 缺陷修复必须沉淀回归断言
|
## 3. 缺陷修复必须沉淀回归断言
|
||||||
|
|
||||||
每个缺陷修复必须在探针或冒烟中留下能抓住该缺陷的断言(例:封印动作耗尽 AP → 必须进入第 2 轮;
|
每个缺陷修复必须在探针或冒烟中留下能抓住该缺陷的断言(例:封印动作耗尽 AP → 必须进入第 2 轮;
|
||||||
@@ -27,7 +43,7 @@
|
|||||||
|
|
||||||
## 4. 验证时机(合回后远端 CI 制,2026-11-03 换代)
|
## 4. 验证时机(合回后远端 CI 制,2026-11-03 换代)
|
||||||
|
|
||||||
开发期义务=`process-conventions.md` §4 改完即测铁规:本批新增/改动的验收测试自己跑绿、读数写进该步提交信息才算完成(卡内只测自己改的东西)。全量验证归合回后的远端 CI:git merge 合回 master 落地后 post-merge 钩子推送 origin master,远端按改动域分流跑 `tools/run_all_gates.sh`(游戏码批=不带参数档两域全量、单元与集成测试全套件——跨卡触面与关联档选测的盲区由全量兜底;文档批=文档域秒级闸;分流算法单点=`tools/ci/domain_route.sh`),远端结果用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 自身 `status`/`conclusion`,只呈报、不落盘——合回不等待、不唤醒,process-conventions §1 第 3 条);CI 红态下修复合回落地即再推再验追绿(修复走新开 `fix-<任务名>` 修复 worktree,process-conventions §1)。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
|
开发期义务=`process-conventions.md` §4 改完即测铁规:本批新增/改动的验收测试自己跑绿、读数写进该步提交信息才算完成(卡内只测自己改的东西)。合回 merge 提交落笔前另有 pre-merge-commit 前置检查(2026-11-06 用户裁:冒烟+单元全套件 4 分片,约 2 分钟——当场拦截面,不落回执;细则见 process-conventions §1 第 4 条 ③)。全量验证归合回后的远端 CI:git merge 合回 master 落地后 post-merge 钩子推送 origin master,远端按改动域分流跑 `tools/run_all_gates.sh`(游戏码批=不带参数档两域全量、单元测试全套件——跨卡触面与关联档选测的盲区由全量兜底;文档批=文档域秒级闸;分流算法单点=`tools/ci/domain_route.sh`),远端结果用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 自身 `status`/`conclusion`,只呈报、不落盘——合回不等待、不唤醒,process-conventions §1 第 3 条);CI 红态下修复合回落地即再推再验追绿(修复走新开 `fix-<任务名>` 修复 worktree,process-conventions §1)。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
|
||||||
行为探针使用随机化玩家行为(封印/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
|
行为探针使用随机化玩家行为(封印/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
|
||||||
|
|
||||||
## 5. 测试函数怎么写——验收清单条目的落码规范
|
## 5. 测试函数怎么写——验收清单条目的落码规范
|
||||||
@@ -52,7 +68,7 @@
|
|||||||
|
|
||||||
## 6. 判定三硬闸——闸承载的构造义务
|
## 6. 判定三硬闸——闸承载的构造义务
|
||||||
|
|
||||||
任何**新增或改写的闸承载**(闸脚本/批跑编排/探针入口)必须三闸齐备;现行各闸状态登记归架构文档「测试与质量域」节(本文不另列闸件清单):
|
任何**新增或改写的闸承载**(闸脚本/批跑编排/探针入口)必须三闸齐备;现行各闸状态登记归 `game/tests/README.md`(测试工具手册,本文不另列闸件清单):
|
||||||
|
|
||||||
1. **退出码为唯一权威判据**——输出里的 PASS 串只作附加判据不作判据主体;打印 PASS 后 `quit(1)` 必须判红。
|
1. **退出码为唯一权威判据**——输出里的 PASS 串只作附加判据不作判据主体;打印 PASS 后 `quit(1)` 必须判红。
|
||||||
2. **SCRIPT ERROR / Parse Error 扫描面在位**——GDScript 脚本错误不改进程退出码、不计失败数(机制事实见 §7),错误标记必须扫输出,且判据必须覆盖「跑了但半途脚本错误」态——退出码 0 但输出缺预期签名同样判红(防静默退出)。
|
2. **SCRIPT ERROR / Parse Error 扫描面在位**——GDScript 脚本错误不改进程退出码、不计失败数(机制事实见 §7),错误标记必须扫输出,且判据必须覆盖「跑了但半途脚本错误」态——退出码 0 但输出缺预期签名同样判红(防静默退出)。
|
||||||
@@ -77,9 +93,9 @@
|
|||||||
|
|
||||||
### 8.2 四层与真实入口
|
### 8.2 四层与真实入口
|
||||||
|
|
||||||
- **单元**:不依赖场景树和真实宿主的纯逻辑;测试从领域类的对外方法进出,断言钉对外可观测面(返回值/信号/查询接口/落盘内容)。内部字段直查=受控例外:仅当该行为没有公开可观测面可钉时允许,对照表该行注明理由;存量不回头清扫,被批次触碰时顺带换代。
|
- **单元**:不依赖场景树和真实宿主的纯逻辑;测试从领域类的对外方法进出,断言钉对外可观测面(返回值/信号/查询接口/落盘内容)。内部字段直查=受控例外:仅当该行为没有公开可观测面可钉时允许,对照表该行注明理由;存量不回头清扫,被批次触碰时顺带换代。探针直读视口承载子件结构(画布取视口首子件、渐隐带两片与平移提示子件按名取)属此类——断言对象即承载结构本身,无公开可观测面可钉,理由随对照表行申报。
|
||||||
- **接口**:模块边界的公开契约——数据表加载、存档与断点、事件载荷、命令接口;测试从公开入口进出。接口级断言随单元套件落(`unit/contracts/`),不另设承载目录。
|
- **接口**:模块边界的公开契约——数据表加载、存档与断点、事件载荷、命令接口;测试从公开入口进出。接口级断言随单元套件落(`unit/contracts/`),不另设承载目录。
|
||||||
- **集成**:跨宿主的接线、持久、生命周期——例如 LevelRunner 把 level_counters 传给 BattleOrchestrator、两场战斗共享同一个桶、断点续玩;测试必须实例化真实宿主链,禁止用裸 EffectEngine 代替。
|
- **跨宿主**:跨宿主的接线、持久、生命周期——例如 LevelRunner 把 level_counters 传给 BattleOrchestrator、两场战斗共享同一个桶、断点续玩;测试必须实例化真实宿主链,禁止用裸 EffectEngine 代替。断言载体归单元层跨系统闭环套件(§1.1 三元组表),验收入口不变。
|
||||||
- **探针/golden**:玩家可达性与观感;真实实例化场景、驱动真实输入。
|
- **探针/golden**:玩家可达性与观感;真实实例化场景、驱动真实输入。
|
||||||
- **golden 测试项扩项(2026-11-05 立)**:触碰画面呈现规格的需求批(新增画面要素/布局/配色/动效;判据=设计段出了预览图),实现段把该画面纳入渲染闸机器面:截图采集清单扩项+实跑截图冻结进 `game/tests/golden/`(基线属入库测试资产,render_gate.sh 在册例外)。黄金图=游戏真实渲染截屏冻结的逐像素基准,比对器与容差口径见 render_gate.sh 头注释(脚本即清单,本文不另列)。基线冻结(新建与换代同口径)=用户对照设计段预览图确认后执行,触发原因写进当批提交说明(`tools/golden_baseline_refresh.sh` 现役义务);此后渲染闸逐像素自动盯、零人工。预览图(HTML/SVG 效果图)与引擎渲染是两套管线,禁直接充当比对基线——预览图只作人审参照与验收判据句的出处(判据出处行锚指向 ux/ 内嵌预览节);缺陷修复以现行规格与在库基线为准,不触发新预览。
|
- **golden 测试项扩项(2026-11-05 立)**:触碰画面呈现规格的需求批(新增画面要素/布局/配色/动效;判据=设计段出了预览图),实现段把该画面纳入渲染闸机器面:截图采集清单扩项+实跑截图冻结进 `game/tests/golden/`(基线属入库测试资产,render_gate.sh 在册例外)。黄金图=游戏真实渲染截屏冻结的逐像素基准,比对器与容差口径见 render_gate.sh 头注释(脚本即清单,本文不另列)。基线冻结(新建与换代同口径)=用户对照设计段预览图确认后执行,触发原因写进当批提交说明(`tools/golden_baseline_refresh.sh` 现役义务);此后渲染闸逐像素自动盯、零人工。预览图(HTML/SVG 效果图)与引擎渲染是两套管线,禁直接充当比对基线——预览图只作人审参照与验收判据句的出处(判据出处行锚指向 ux/ 内嵌预览节);缺陷修复以现行规格与在库基线为准,不触发新预览。
|
||||||
|
|
||||||
@@ -100,6 +116,8 @@
|
|||||||
|
|
||||||
**判据出处行锚(2026-11-05 立,自 2026-11-05 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改,被编入迭代开工前由写卡段按本粒度补挂)**:对照表「需求点」列每行必须带**判据出处行锚**——该行验收判据所依据的现行文档句子,格式「`<文档相对路径>:<行号>`」。现行文档=`design/` 全域现行文档(含 `ux/` 交互规格与 art-bible 的判据行);已退役的需求卡片不是现行文档,不得充当判据出处。作用=断言预期值从规格句抄出,不从实现反推:实现行为与规格句冲突时断言红;规格缺席的行写不出锚,即停卡退回写卡段(那是需求澄清缺口,不是测试缺口)。机检=`tools/pipeline_gate.py` 判据 C5(锚格式与指向存在性,按卡文件名日期分流)+`tools/capability_audit.py` 链式锚检查(断言→套件→能力行→系统文档,见 §8.9)。
|
**判据出处行锚(2026-11-05 立,自 2026-11-05 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改,被编入迭代开工前由写卡段按本粒度补挂)**:对照表「需求点」列每行必须带**判据出处行锚**——该行验收判据所依据的现行文档句子,格式「`<文档相对路径>:<行号>`」。现行文档=`design/` 全域现行文档(含 `ux/` 交互规格与 art-bible 的判据行);已退役的需求卡片不是现行文档,不得充当判据出处。作用=断言预期值从规格句抄出,不从实现反推:实现行为与规格句冲突时断言红;规格缺席的行写不出锚,即停卡退回写卡段(那是需求澄清缺口,不是测试缺口)。机检=`tools/pipeline_gate.py` 判据 C5(锚格式与指向存在性,按卡文件名日期分流)+`tools/capability_audit.py` 链式锚检查(断言→套件→能力行→系统文档,见 §8.9)。
|
||||||
|
|
||||||
|
**测试函数的判据出处注记(2026-11-06 立)**:`game/tests/**` 与 `game/probe/**` 内每个**验证函数**(函数体含 `check(`/`check_quiet(`/`_problems.append(`/`push_error(` 判定调用的函数——定义行与 `_check(` 前缀不作判定计)必须带至少一条**判据出处注记**,格式「`# 判据出处: <design/相对路径>:<行号> <判据一句>`」——指针在前、判据摘要句在后;锚形态两档:行号锚(默认)与节锚(`<design/相对路径>「节名」<行关键词>`)——所指文档整节重排时同批把行号锚重锚为节锚,免行号漂移(2026-11-07 架构收窄批立),断言预期值的出处随断言走:断言红时读注记即达出处文档句,零查表。指针空间=`design/` 全域现行文档(行为测试锚 owner 系统文档「验收标准」句或 `ux/` 规格句;惯例类测试〔封装扫描、判定通道纪律、驱动契约〕锚规约条款行);`game/sim/` 不进扫描面(测量面直构惯例)。与链式锚的分工:链式锚(断言→套件→能力行→系统文档)不变、属义务清单层;本注记属执行证据层、写在断言文件内,非独立账本(§8.9 法则 4 不变)。写新测试函数时当场挂注记;被指规格句改行号时随批维护指针——死指针即红。局限如实声明:注记是被动文本,句内容改而行数不变时机检抓不到(与卡片判据 C5 同限)。机检=`tools/capability_audit.py` 判据出处注记道(覆盖检查+指针存在性;扫描面零文件自检红)。规格缺席写不出锚=发现规格缺口:记发现不造锚、收尾呈报,禁锚到非现行文档凑数。
|
||||||
|
|
||||||
**验收档申报(2026-11-04 立,自 2026-11-05 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改)**:每张需求卡片在头部信息区(与设计事实源声明同区)申报一个验收档,三档:高/中/低。判据=失败代价单维——这条改动做错了,后果随存档或结算传播的(存档写读与迁移、RNG 流、战斗结算公式与乘区、经济入账、数值表结构校验)=高;后果玩家可见但不损持久状态的(常规玩法逻辑、门控、交互逻辑、呈现数据面)=中;后果即看即知且无状态残留的(文案、纯呈现样式、布局微调)=低。一张卡触多档按最高档申报;申报由写卡段落笔,用户批卡(U0)时确认或改判。档位只调节 §8.7 审计深度——闸机与 CI 的域划分、选闸算法、全量强制档一概不因档位变化,真实入口、判据绑定面、禁削弱等验收闭合判据全部照旧。未申报档位的卡一律按高档全量审计。机检=`tools/pipeline_gate.py` 判据 C4:卡内须含「验收档:高/中/低」申报行。
|
**验收档申报(2026-11-04 立,自 2026-11-05 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改)**:每张需求卡片在头部信息区(与设计事实源声明同区)申报一个验收档,三档:高/中/低。判据=失败代价单维——这条改动做错了,后果随存档或结算传播的(存档写读与迁移、RNG 流、战斗结算公式与乘区、经济入账、数值表结构校验)=高;后果玩家可见但不损持久状态的(常规玩法逻辑、门控、交互逻辑、呈现数据面)=中;后果即看即知且无状态残留的(文案、纯呈现样式、布局微调)=低。一张卡触多档按最高档申报;申报由写卡段落笔,用户批卡(U0)时确认或改判。档位只调节 §8.7 审计深度——闸机与 CI 的域划分、选闸算法、全量强制档一概不因档位变化,真实入口、判据绑定面、禁削弱等验收闭合判据全部照旧。未申报档位的卡一律按高档全量审计。机检=`tools/pipeline_gate.py` 判据 C4:卡内须含「验收档:高/中/低」申报行。
|
||||||
|
|
||||||
**能力清单维护锚(2026-10-29 用户裁改版定稿)**:`game/tests/README.md`「能力清单」是**实现指导+阅读导航+义务声明**——只宣布「要验证什么」,不记「是否已验证/是否跑过」;落地账归现行验收闭合链(改动—验收对照表逐条挂断言+合回前独立验收审计),本清单不承载验证状态。表为四列:能力|系统|真实入口|代表用例(`文件:函数`)。**维护归写卡段,当场入表**:写需求卡片时,本批新增能力当场写入能力行——真实入口取自设计文档已定的入口,代表用例=卡里定死的计划测试(`文件:函数`);受影响存量行(入口/用例名变更)同批更新;能力退役删行。**实现照单落名**:测试函数名以清单为唯一依据,名实不符=卡片没写清=停卡退回。**收尾核对**:批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段;实现批禁写该文件的现行红线不变(process-conventions §3 第 11 条),核对义务归收尾提交。三层模型见 §8.9。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
|
**能力清单维护锚(2026-10-29 用户裁改版定稿)**:`game/tests/README.md`「能力清单」是**实现指导+阅读导航+义务声明**——只宣布「要验证什么」,不记「是否已验证/是否跑过」;落地账归现行验收闭合链(改动—验收对照表逐条挂断言+合回前独立验收审计),本清单不承载验证状态。表为四列:能力|系统|真实入口|代表用例(`文件:函数`)。**维护归写卡段,当场入表**:写需求卡片时,本批新增能力当场写入能力行——真实入口取自设计文档已定的入口,代表用例=卡里定死的计划测试(`文件:函数`);受影响存量行(入口/用例名变更)同批更新;能力退役删行。**实现照单落名**:测试函数名以清单为唯一依据,名实不符=卡片没写清=停卡退回。**收尾核对**:批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段;实现批禁写该文件的现行红线不变(process-conventions §3 第 11 条),核对义务归收尾提交。三层模型见 §8.9。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
|
||||||
@@ -108,7 +126,7 @@
|
|||||||
|
|
||||||
**新增 core 件的覆盖登记义务(2026-11-03 架构审查 P1 余项裁)**:拆件或重构产出的新 core 文件不触发 process-conventions §3 第 6 条「新功能必配新测试」(那条只管新增玩法/机制),因此单由本条承接——新 core 件要么被 `game/tests/` 某套件按文件名或 `class_name` 点名,要么在承接它的能力行「代表用例」里申报「经宿主链覆盖(宿主=<件>)」;两者都无=批末收尾核对时补登。本条**不是覆盖率要求**,与 §7「覆盖率不是目标」同轨:登记的是能力义务的归属,不做文件计数——「每个 core 件必须被点名一次」的机器闸已裁否(它逼出为点名而点名的空套件,且与 §7 正面冲突)。落笔面沿用现行分工:申报行由写卡段入能力清单(实现批禁写该文件),核对归批末收尾提交。
|
**新增 core 件的覆盖登记义务(2026-11-03 架构审查 P1 余项裁)**:拆件或重构产出的新 core 文件不触发 process-conventions §3 第 6 条「新功能必配新测试」(那条只管新增玩法/机制),因此单由本条承接——新 core 件要么被 `game/tests/` 某套件按文件名或 `class_name` 点名,要么在承接它的能力行「代表用例」里申报「经宿主链覆盖(宿主=<件>)」;两者都无=批末收尾核对时补登。本条**不是覆盖率要求**,与 §7「覆盖率不是目标」同轨:登记的是能力义务的归属,不做文件计数——「每个 core 件必须被点名一次」的机器闸已裁否(它逼出为点名而点名的空套件,且与 §7 正面冲突)。落笔面沿用现行分工:申报行由写卡段入能力清单(实现批禁写该文件),核对归批末收尾提交。
|
||||||
|
|
||||||
**退役对账义务(2026-11-05 立)**:需求卡片退役(吸收即死)时,其对照表每行的验收意图必须已被承接——承接形态=能力清单行(能力+真实入口+代表用例)或已落地的断言;退役后无承接=该能力的规格判据断链,收尾核对判红。机检=`tools/capability_audit.py`(套件→能力行反向覆盖+断言链核验)。先例教训:营地图批卡片退役后,大门判据(`design/gdd/ux/camp.md:16`)无任何活面承接,探针 emit 断言悬空假绿——规格在、链接断。
|
**退役对账义务(2026-11-05 立)**:需求卡片退役(吸收即死)时,其对照表每行的验收意图必须已被承接——承接形态=能力清单行(能力+真实入口+代表用例)或已落地的断言;退役后无承接=该能力的规格判据断链,收尾核对判红。机检=`tools/capability_audit.py`(套件→能力行反向覆盖+断言链核验)。先例教训:营地图批卡片退役后,大门判据(`design/ux/camp.md:16`)无任何活面承接,探针 emit 断言悬空假绿——规格在、链接断。
|
||||||
|
|
||||||
### 8.4 真实入口断言(验收闭合的主判据)
|
### 8.4 真实入口断言(验收闭合的主判据)
|
||||||
|
|
||||||
@@ -134,7 +152,7 @@
|
|||||||
2. 抽查判据绑定面:断言从真实入口进入、钉在被测改动的特有可观测提交面上,且当轮真实跑批执行过;
|
2. 抽查判据绑定面:断言从真实入口进入、钉在被测改动的特有可观测提交面上,且当轮真实跑批执行过;
|
||||||
3. 检查测试削弱:删除断言、放宽阈值、缩小扫描面、换下层直调,逐处要卡片申报或用户批准。
|
3. 检查测试削弱:删除断言、放宽阈值、缩小扫描面、换下层直调,逐处要卡片申报或用户批准。
|
||||||
4. 核对内部字段直查的受控例外:直查行是否已在对照表注明理由(该行为无公开可观测面可钉)。
|
4. 核对内部字段直查的受控例外:直查行是否已在对照表注明理由(该行为无公开可观测面可钉)。
|
||||||
5. 核对判据出处:抽查断言的预期值能否从其判据出处行锚(§8.3)的规格句独立写出——预期值只在实现里有的(同义反复,oracle 镜像实现),判红。
|
5. 核对判据出处:抽查断言的预期值能否从其判据出处行锚(§8.3)的规格句独立写出——预期值只在实现里有的(同义反复,判据镜像实现),判红。
|
||||||
|
|
||||||
**审计深度分级(2026-11-04 立)**:审计按卡内申报的验收档(§8.3)逐卡定深度;梯度只落在昂贵的判断件上,机械且堵造假向量的两件(削弱检查、例外核对)三档全保留不抽。中/低档省略的测试复跑以远端 CI 读数为执行证据——`tools/ci_check.sh <合并提交>` 的现查输出(commit+run 号+conclusion)是机器产物,run 号在远端永久可复核,审计报告照抄该行即可;照抄前先核对读数必须是「绿」——「未验」(零触发批跑闸步全跳过)与「不可判」不作证据,那种批的回补办法是等一次含代码面的合回或用户自发全量回归(2026-11-04 用户裁:回执等待件退役,证据由落盘文件改为现查读数;「不采信实现者自述已全绿」的口径不变):
|
**审计深度分级(2026-11-04 立)**:审计按卡内申报的验收档(§8.3)逐卡定深度;梯度只落在昂贵的判断件上,机械且堵造假向量的两件(削弱检查、例外核对)三档全保留不抽。中/低档省略的测试复跑以远端 CI 读数为执行证据——`tools/ci_check.sh <合并提交>` 的现查输出(commit+run 号+conclusion)是机器产物,run 号在远端永久可复核,审计报告照抄该行即可;照抄前先核对读数必须是「绿」——「未验」(零触发批跑闸步全跳过)与「不可判」不作证据,那种批的回补办法是等一次含代码面的合回或用户自发全量回归(2026-11-04 用户裁:回执等待件退役,证据由落盘文件改为现查读数;「不采信实现者自述已全绿」的口径不变):
|
||||||
|
|
||||||
@@ -175,4 +193,4 @@
|
|||||||
|
|
||||||
**文档纯度**:验收意图与能力描述只写玩家或系统可观测面,禁写代码路径(`.gd`/`.py`/`.sh`)、测试文件名、断言名;唯一例外=配置文件索引(`game/data/tables/*.tres` 这类表路径与表名)。规则正文见 doc-conventions §5「禁实现内容」。
|
**文档纯度**:验收意图与能力描述只写玩家或系统可观测面,禁写代码路径(`.gd`/`.py`/`.sh`)、测试文件名、断言名;唯一例外=配置文件索引(`game/data/tables/*.tres` 这类表路径与表名)。规则正文见 doc-conventions §5「禁实现内容」。
|
||||||
|
|
||||||
**机器闸**:本节的结构由文档域闸「能力审计」机检——GDD 纯度(同款禁实现内容口径)、系统文档验收标准节非空、能力行四列与非空、代表用例(`文件:函数`)与真实入口可核(双通道:代码在或卡在——计划中的用例与入口由需求卡片锚定)、覆盖域表与能力行对得上;红项按新增红处理。闸件清单与域划分的唯一出处=`tools/run_all_gates.sh` 头部。
|
**机器闸**:本节的结构由文档域闸「能力审计」机检——GDD 纯度(同款禁实现内容口径)、系统文档验收标准节非空、能力行四列与非空、代表用例(`文件:函数`)与真实入口可核(双通道:代码在或卡在——计划中的用例与入口由需求卡片锚定)、覆盖域表与能力行对得上、判据出处注记覆盖与指针可核(§8.3 测试函数的判据出处注记);红项按新增红处理。闸件清单与域划分的唯一出处=`tools/run_all_gates.sh` 头部。
|
||||||
@@ -47,12 +47,6 @@
|
|||||||
|
|
||||||
| 专名 | 是什么 | 出处条目 |
|
| 专名 | 是什么 | 出处条目 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 显影尘 | 信息类秘宝 | aux_items |
|
|
||||||
| 工兵令 | 加行动点的秘宝 | aux_items |
|
|
||||||
| 探宝罗盘 | 预读奖励身份的秘宝 | aux_items |
|
|
||||||
| 探巢摆钟 | 探知巢穴位置的秘宝 | aux_items |
|
|
||||||
| 地穴全图卷 | 全图级稀有秘宝 | aux_items |
|
|
||||||
| 爆破工兵包 | 行动点 + 探巢的稀有秘宝 | aux_items |
|
|
||||||
| 地精 / 熊地精 / 食人魔酋长 | 首发三敌种(末者为 Boss) | enemy |
|
| 地精 / 熊地精 / 食人魔酋长 | 首发三敌种(末者为 Boss) | enemy |
|
||||||
| 第一层 · 地精洞窟 | 首关层名 | level_table |
|
| 第一层 · 地精洞窟 | 首关层名 | level_table |
|
||||||
| 封印 | 正式动作名(全库统一,非比喻、非呈现层别名)——对未开格实施封印,印记=封印印记 | terminology |
|
| 封印 | 正式动作名(全库统一,非比喻、非呈现层别名)——对未开格实施封印,印记=封印印记 | terminology |
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
| `教学引导.md` | 新手教学与提示 | 范围草案·待设计 |
|
| `教学引导.md` | 新手教学与提示 | 范围草案·待设计 |
|
||||||
| `设置与本地化.md` | 设置项与多语言 | 范围草案·待设计 |
|
| `设置与本地化.md` | 设置项与多语言 | 范围草案·待设计 |
|
||||||
|
|
||||||
## ux/(战斗画面与交互规格,`ux/`)
|
## ux/(战斗画面与交互规格,`design/ux/`——与 gdd/ 同级的呈现实现设计规格层)
|
||||||
|
|
||||||
| 文件 | 一句话概要 | 状态 |
|
| 文件 | 一句话概要 | 状态 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ MVP 不加新敌种,也不做同深度多敌种混搭;敌种扩容走 `enemy
|
|||||||
|
|
||||||
目录(重设计 v1)已定稿 **12 件**(普通 7 / 优秀 3 / 稀有 2——代号制,正式命名归用户;数值全 provisional 归调参批),现行事实源=[秘宝](systems/跨局循环/秘宝.md)「目录(重设计 v1)」节。数据行随实装批落表(同调件数据表 = `data/tables/treasure_items.tres`),MVP 不新增。
|
目录(重设计 v1)已定稿 **12 件**(普通 7 / 优秀 3 / 稀有 2——代号制,正式命名归用户;数值全 provisional 归调参批),现行事实源=[秘宝](systems/跨局循环/秘宝.md)「目录(重设计 v1)」节。数据行随实装批落表(同调件数据表 = `data/tables/treasure_items.tres`),MVP 不新增。
|
||||||
|
|
||||||
旧目录(旧 aux_items 六行:显影尘/工兵令/探宝罗盘/探巢摆钟/地穴全图卷/爆破工兵包,及过渡形态诸件)已全数退役、只作素材库(design/content-archive/道具退役素材库.md);旧行删除归实装批。
|
旧目录(旧 aux_items 六行:显影尘/工兵令/探宝罗盘/探巢摆钟/地穴全图卷/爆破工兵包,及过渡形态诸件)已全数退役、留底 design/content-archive/道具退役素材库.md(数据表旧行已删净——treasure_items.tres 旧六名扫描零命中)。
|
||||||
|
|
||||||
## 增益与状态
|
## 增益与状态
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ MVP 不加新状态;扩容走 `status_effects.tres` 加行 + [增益状态](sy
|
|||||||
垂直切片阶段明确砍掉或推迟的内容,写在这里防止回潮:
|
垂直切片阶段明确砍掉或推迟的内容,写在这里防止回潮:
|
||||||
|
|
||||||
- 更多关卡(N>3)——第三关已按扩展批流程落地(行集);三关正式序列已生效,唯一试玩入口 = 完整冒险
|
- 更多关卡(N>3)——第三关已按扩展批流程落地(行集);三关正式序列已生效,唯一试玩入口 = 完整冒险
|
||||||
- 精英节点与词缀系统——只预留了字段位,不定义语义(精英怪**设定**已登记预留——同立绘+附加特征标记+数值更强、钥石掉 1 个预留;实装随怪物批)
|
- 精英节点与词缀系统——精英怪本体已落敌人表(行类 elite+池继承基础池加附加技,首只=地精精英),精英节点与投放仍未接线;词缀系统未设计
|
||||||
- 地形变异扩展内容——首批四类型已落地,反制道具与全局作用域排 Alpha
|
- 地形变异扩展内容——首批四类型已落地,反制道具与全局作用域排 Alpha
|
||||||
- 道具/增益之间的组合协同(遗物式联动)
|
- 道具/增益之间的组合协同(遗物式联动)
|
||||||
- 战后自动回复——回复只有道具与恢复点两个来源
|
- 战后自动回复——回复只有道具与恢复点两个来源
|
||||||
|
|||||||
+11
-13
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> **一句话定位**:本文定义这个项目的 **Alpha 版本包含哪些东西**——它是里程碑 M3 的完成标准,也是判断"还差什么"的对照表。
|
> **一句话定位**:本文定义这个项目的 **Alpha 版本包含哪些东西**——它是里程碑 M3 的完成标准,也是判断"还差什么"的对照表。
|
||||||
> **本文只列条目,不写内容**:每样东西是什么、规则怎么走,一律归各自的权威文档,本文只给指路链接。想知道某样东西的定义,请点链接,不要在本文里找解释。
|
> **本文只列条目,不写内容**:每样东西是什么、规则怎么走,一律归各自的权威文档,本文只给指路链接。想知道某样东西的定义,请点链接,不要在本文里找解释。
|
||||||
> **状态**:**已定稿(v1.28)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。
|
> **状态**:**已定稿(v1.30)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。
|
||||||
> **成文**:2026-10-13。
|
> **成文**:2026-10-13。
|
||||||
|
|
||||||
## 本文怎么用
|
## 本文怎么用
|
||||||
@@ -103,15 +103,15 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战
|
|||||||
| 主菜单 | —— | 在役(三入口:进入存档/设置/退出游戏——入口拓扑=进入存档→选档界面→进档/新档→营地覆盖层→营地场景图与生涯笔记本) |
|
| 主菜单 | —— | 在役(三入口:进入存档/设置/退出游戏——入口拓扑=进入存档→选档界面→进档/新档→营地覆盖层→营地场景图与生涯笔记本) |
|
||||||
| 开始覆盖层 | —— | 在役 |
|
| 开始覆盖层 | —— | 在役 |
|
||||||
| 选档界面(3 存档位) | —— | 在役(空槽新档/有档进档/删档二次确认+摘要三项) |
|
| 选档界面(3 存档位) | —— | 在役(空槽新档/有档进档/删档二次确认+摘要三项) |
|
||||||
| 营地(天赋树 / 锻造工坊 / 秘宝匣 / 图鉴) | [camp](ux/camp.md) | 在役(场景图+七物件点选+Esc 浮窗与顶栏;五功能页呈现=居中定尺寸功能窗口、场景根留底、窗内滚动) |
|
| 营地(天赋树 / 锻造工坊 / 秘宝匣 / 图鉴) | [camp](../ux/camp.md) | 在役(场景图+七物件点选+Esc 浮窗与顶栏;五功能页呈现=居中定尺寸功能窗口、场景根留底、窗内滚动) |
|
||||||
| 营地交互重做(五卡:存档制数据层/主菜单三入口/选档界面/营地场景图/Esc 浮窗与营地顶栏) | [camp](ux/camp.md) | 在役(五卡全部落地,2026-10-21 用户裁整体列入 Alpha;沿革查 git 提交史。出口=五卡各自验收标准通过+营地屏用户目检〔登记体验验证清单 ㊺〕) |
|
| 营地交互重做(五卡:存档制数据层/主菜单三入口/选档界面/营地场景图/Esc 浮窗与营地顶栏) | [camp](../ux/camp.md) | 在役(五卡全部落地,2026-10-21 用户裁整体列入 Alpha;沿革查 git 提交史。出口=五卡各自验收标准通过+营地屏用户目检〔登记体验验证清单 ㊺〕) |
|
||||||
| 生涯页 | [生涯](systems/跨局循环/生涯.md) | 在役(期一) |
|
| 生涯页 | [生涯](systems/跨局循环/生涯.md) | 在役(期一) |
|
||||||
| 关卡地图屏 | [level-map](ux/level-map.md) | 在役 |
|
| 关卡地图屏 | [level-map](../ux/level-map.md) | 在役 |
|
||||||
| 战斗屏 | [battle](ux/battle.md) | 在役 |
|
| 战斗屏 | [battle](../ux/battle.md) | 在役 |
|
||||||
| 战斗结算总结框 | [settlement-summary](ux/settlement-summary.md) | 在役 |
|
| 战斗结算总结框 | [settlement-summary](../ux/settlement-summary.md) | 在役 |
|
||||||
| 关卡结算屏 | [level-clear](ux/level-clear.md) | 在役 |
|
| 关卡结算屏 | [level-clear](../ux/level-clear.md) | 在役 |
|
||||||
| 三选一(奖励节点 / 关卡完成) | [node-reward](ux/node-reward.md) | 在役(两渠道均三选一停点:关卡完成与奖励节点各停一次,奖励节点经兑付拉起开三选一) |
|
| 三选一(奖励节点 / 关卡完成) | [node-reward](../ux/node-reward.md) | 在役(两渠道均三选一停点:关卡完成与奖励节点各停一次,奖励节点经兑付拉起开三选一) |
|
||||||
| 商店 | [shop](ux/shop.md) | 在役 |
|
| 商店 | [shop](../ux/shop.md) | 在役 |
|
||||||
| 状态面板(局内) | [元进度](systems/跨局循环/元进度.md)(「解锁界面:双入口框架」节) | 在役 |
|
| 状态面板(局内) | [元进度](systems/跨局循环/元进度.md)(「解锁界面:双入口框架」节) | 在役 |
|
||||||
| 冒险终局面板 | —— | 在役 |
|
| 冒险终局面板 | —— | 在役 |
|
||||||
| 图例面板 | —— | 在役 |
|
| 图例面板 | —— | 在役 |
|
||||||
@@ -146,18 +146,16 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战
|
|||||||
| 像素美术风格与色板 | [美术圣经](../art/art-bible.md) | 在役 |
|
| 像素美术风格与色板 | [美术圣经](../art/art-bible.md) | 在役 |
|
||||||
| 棋盘瓦片与格面资源图标 | [美术圣经](../art/art-bible.md) | 在役 |
|
| 棋盘瓦片与格面资源图标 | [美术圣经](../art/art-bible.md) | 在役 |
|
||||||
| 未开格类型微光(五组色相+明度档) | [HUD框架](systems/表现与支撑/HUD框架.md) | 在役(明度档 provisional 值登记见 art-bible 的 git 提交史;观感复核已随战斗一屏样张过闸完成——用户实机目检核销,沿革查 git 提交史) |
|
| 未开格类型微光(五组色相+明度档) | [HUD框架](systems/表现与支撑/HUD框架.md) | 在役(明度档 provisional 值登记见 art-bible 的 git 提交史;观感复核已随战斗一屏样张过闸完成——用户实机目检核销,沿革查 git 提交史) |
|
||||||
| 棋盘观感(第二 / 三关亮度与对比度) | [待办清单](../../待办清单.md) | 待做(开工前置=先做素材轴/UI 轴对照截图定性,再按定轴修复;旧卡 v1.4 存 reports/ 作素材、非已写卡状态,重启须重新立卡;出口=用户实机目检第二、三关不再判「看着费劲」) |
|
| 棋盘瓦片与立体表现重做 | [待办清单](../../待办清单.md) | 已写卡(待编排)——设计闭合=C 方向+D 布局+三关八色冻结(art-bible v3.51/battle.md 2026-11-07/HUD框架 2026-11-07);卡片=[需求卡片](../../reports/需求卡片-棋盘瓦片与立体表现重做批-2026-11-07.md)(卡内 §16 复核通过);出口=用户实机目检棋盘立体感与素材观感达标 |
|
||||||
| 立绘显示清晰度(原稿分辨率+三档显示) | [角色设计](../art/character-design.md) | 在役(原稿分辨率入包禁降采样、显示按三档绝对高 96/144/188 缩放、现有形象即终稿;定值单点=art-bible §8.2;实机目检清晰度与同屏体量顺序登记体验验证清单 ㊻) |
|
| 立绘显示清晰度(原稿分辨率+三档显示) | [角色设计](../art/character-design.md) | 在役(原稿分辨率入包禁降采样、显示按三档绝对高缩放、现有形象即终稿;定值单点=art-bible §8.2(档值定值面=站桩守门测试);实机目检清晰度与同屏体量顺序登记体验验证清单 ㊻) |
|
||||||
| 敌人立绘(全敌种) | [角色设计](../art/character-design.md) | 在役 |
|
| 敌人立绘(全敌种) | [角色设计](../art/character-design.md) | 在役 |
|
||||||
| 主角立绘三态 | [角色设计](../art/character-design.md) | 在役 |
|
| 主角立绘三态 | [角色设计](../art/character-design.md) | 在役 |
|
||||||
| 状态图标 | [美术圣经](../art/art-bible.md) | 在役 |
|
| 状态图标 | [美术圣经](../art/art-bible.md) | 在役 |
|
||||||
| 战斗演出链(弹道 / 受击 / 血条 / 灰化) | [战斗表现](systems/战斗循环/战斗表现.md) | 在役 |
|
| 战斗演出链(弹道 / 受击 / 血条 / 灰化) | [战斗表现](systems/战斗循环/战斗表现.md) | 在役 |
|
||||||
| 逐行结算排播 | [settlement-summary](ux/settlement-summary.md) | 在役 |
|
|
||||||
| 减动效开关 | [设置与本地化](systems/表现与支撑/设置与本地化.md) | 在役 |
|
| 减动效开关 | [设置与本地化](systems/表现与支撑/设置与本地化.md) | 在役 |
|
||||||
| 全局纹理过滤设为邻近采样 | [待办清单](../../待办清单.md) | 在役(default_texture_filter=0+平滑渐变件三处显式 LINEAR 白名单,翻转面全枚举闭合) |
|
| 全局纹理过滤设为邻近采样 | [待办清单](../../待办清单.md) | 在役(default_texture_filter=0+平滑渐变件三处显式 LINEAR 白名单,翻转面全枚举闭合) |
|
||||||
| UI 字体(全局像素字,Fusion Pixel 单套单字重) | [美术圣经](../art/art-bible.md) §7.4 | 在役(现状即终稿——拉丁沿用自带字形不另接专件、不上第二字重;信息层级手段=字号档差+墨色深浅) |
|
| UI 字体(全局像素字,Fusion Pixel 单套单字重) | [美术圣经](../art/art-bible.md) §7.4 | 在役(现状即终稿——拉丁沿用自带字形不另接专件、不上第二字重;信息层级手段=字号档差+墨色深浅) |
|
||||||
| 战斗一屏样张(界面美术的终稿闸) | [美术圣经](../art/art-bible.md) §1.4 | 在役(样张整体过闸——用户实机目检核销,沿革查 git 提交史;目标规格与五项实装定值单点=art-bible 五张规格表。主角+三 Boss 重产依赖照旧;站桩帧动画已改排 Beta,见「六 · Alpha 不含」) |
|
| 战斗一屏样张(界面美术的终稿闸) | [美术圣经](../art/art-bible.md) §1.4 | 在役(样张整体过闸——用户实机目检核销,沿革查 git 提交史;目标规格与五项实装定值单点=art-bible 五张规格表。主角+三 Boss 重产依赖照旧;站桩帧动画已改排 Beta,见「六 · Alpha 不含」) |
|
||||||
| UI 氛围层与九宫格切片观感修 | [待办清单](../../待办清单.md) | 部分在役(光柱硬边已修=连续 alpha 渐变;未结半=九宫格切片错位——Alpha 内做最小修复:核对素材尺寸,必要时重出九宫格素材,全套素材重出排 Beta;出口=结算屏与图例屏错位消失,渲染闸+用户目检通过) |
|
|
||||||
| UI 元素细节修(滑轨填充 / 图标垫块 / 留白 / 开发件外泄) | [待办清单](../../待办清单.md) | 在役(四子项中滑轨填充注销,余三件——图标垫块明度差降档/商店+营地布局修/诊断钮迁调试浮窗——全落地) |
|
| UI 元素细节修(滑轨填充 / 图标垫块 / 留白 / 开发件外泄) | [待办清单](../../待办清单.md) | 在役(四子项中滑轨填充注销,余三件——图标垫块明度差降档/商店+营地布局修/诊断钮迁调试浮窗——全落地) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
每关一套参数档(L1/L2/L3),生成器只吃参数档、不认关卡号。生长曲线:层高、宽度、节点总数、路径长度逐关递增且增幅变大;决策点密度逐关递增;第一关即含岔口——第一关也要有选择。单链是分支密度取下限的合法退化形态,不作为三关参数档的取值。
|
每关一套参数档(L1/L2/L3),生成器只吃参数档、不认关卡号。生长曲线:层高、宽度、节点总数、路径长度逐关递增且增幅变大;决策点密度逐关递增;第一关即含岔口——第一关也要有选择。单链是分支密度取下限的合法退化形态,不作为三关参数档的取值。
|
||||||
|
|
||||||
图规模无呈现侧上限:关卡画面为卷轴视口呈现,画布随图生长、屏为窗口(呈现规格归 [level-map](../../ux/level-map.md));规模由参数档与生长曲线约束,参数档给不出合法图即致命中止。
|
图规模无呈现侧上限:关卡画面为卷轴视口呈现,画布随图生长、屏为窗口(呈现规格归 [level-map](../../../ux/level-map.md));规模由参数档与生长曲线约束,参数档给不出合法图即致命中止。
|
||||||
|
|
||||||
### 节点类型配比:类型分布怎么掷、内容归谁
|
### 节点类型配比:类型分布怎么掷、内容归谁
|
||||||
|
|
||||||
|
|||||||
@@ -64,9 +64,9 @@
|
|||||||
|
|
||||||
每个节点在图上有**节点深度**(本文含义:自入口沿路走到该节点的最长路径步数;多入口时取距任一入口的最长路径),用来当战斗的定位地址——遭遇坐标=关卡序号+节点深度,敌人表按**深度带**(深度区间)配池,寻址语义见[敌人系统](../战斗循环/敌人系统.md)。不用最短路径:合流节点或多入口图上取最短,会让某些出边指向深度不增甚至更浅的节点,破坏「连线只朝前进方向」的无环判据。"最深处是关底"的直感由深度承载:终点恒在各路径最深处。单链(每步只有一条连线)是合法退化形态,节点深度等于它前面走过的战斗场数;三关参数档都含岔口,第一关不再是单链。图的来源见[关卡节点图生成](关卡节点图生成.md)。
|
每个节点在图上有**节点深度**(本文含义:自入口沿路走到该节点的最长路径步数;多入口时取距任一入口的最长路径),用来当战斗的定位地址——遭遇坐标=关卡序号+节点深度,敌人表按**深度带**(深度区间)配池,寻址语义见[敌人系统](../战斗循环/敌人系统.md)。不用最短路径:合流节点或多入口图上取最短,会让某些出边指向深度不增甚至更浅的节点,破坏「连线只朝前进方向」的无环判据。"最深处是关底"的直感由深度承载:终点恒在各路径最深处。单链(每步只有一条连线)是合法退化形态,节点深度等于它前面走过的战斗场数;三关参数档都含岔口,第一关不再是单链。图的来源见[关卡节点图生成](关卡节点图生成.md)。
|
||||||
|
|
||||||
呈现侧口径(2026-09-17 用户拍板):节点图的画面表达走**方块地牢观感**——节点画成地牢房间的方块、连线画成通道——但逻辑拓扑就是本文的节点图,不产生任何额外选路或探索语义。关卡画面本体即节点链进度的呈现载体(选路覆盖层的常驻形态,节点态直接读图:已过暗金 / 当前金 / 候选下一跳通道亮金 / Boss 紫赤描边(紫赤+深墨环,视觉定稿见 [level-map](../../ux/level-map.md))),不另设进度条组件;视觉规格归 [HUD 框架](../表现与支撑/HUD框架.md)。
|
呈现侧口径(2026-09-17 用户拍板):节点图的画面表达走**方块地牢观感**——节点画成地牢房间的方块、连线画成通道——但逻辑拓扑就是本文的节点图,不产生任何额外选路或探索语义。关卡画面本体即节点链进度的呈现载体(选路覆盖层的常驻形态,节点态直接读图:已过暗金 / 当前金 / 候选下一跳通道亮金 / Boss 紫赤描边(紫赤+深墨环,视觉定稿见 [level-map](../../../ux/level-map.md))),不另设进度条组件;视觉规格归 [HUD 框架](../表现与支撑/HUD框架.md)。
|
||||||
|
|
||||||
**商店覆盖层呈现**(呈现 spec:[design/gdd/ux/shop.md](../../ux/shop.md) v1.0;pool 模式货架面=共享池三选一同构卡〔进店抽 3/买 1 全重抽/空架售罄态〕,与三选一奖励同一交互语言;legacy 固定三件面随对照模式保留。**库存余量不呈现**(2026-10-04 用户裁)——货架卡不带「库存余 N/∞」字样,库存语义仍在共享池令牌库、只是不呈现):兑付 = 打开商店覆盖层(模态)——货架卡陈列、GP 余额读数、购买/离开;离开后兑付确认回选路。本节锁编排面(何时开/何时关/回选路),呈现细节归 spec;定价数值归[难度曲线与Boss](难度曲线与Boss.md)(shop.tres)。
|
**商店覆盖层呈现**(呈现 spec:[design/ux/shop.md](../../../ux/shop.md) v1.0;pool 模式货架面=共享池三选一同构卡〔进店抽 3/买 1 全重抽/空架售罄态〕,与三选一奖励同一交互语言;legacy 固定三件面随对照模式保留。**库存余量不呈现**(2026-10-04 用户裁)——货架卡不带「库存余 N/∞」字样,库存语义仍在共享池令牌库、只是不呈现):兑付 = 打开商店覆盖层(模态)——货架卡陈列、GP 余额读数、购买/离开;离开后兑付确认回选路。本节锁编排面(何时开/何时关/回选路),呈现细节归 spec;定价数值归[难度曲线与Boss](难度曲线与Boss.md)(shop.tres)。
|
||||||
|
|
||||||
### 行进与选路:兑付后确认,选路就是行进
|
### 行进与选路:兑付后确认,选路就是行进
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
|
|
||||||
| 纪律 | 内容 |
|
| 纪律 | 内容 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 兑付后确认 | 到达节点立即兑付,不设"进入前确认"步;兑付反馈呈现完,玩家确认才回图。战斗节点的确认挂在战斗总结结算上(呈现 spec:design/gdd/ux/settlement-summary.md),奖励/恢复节点挂在兑付反馈覆盖层上,商店节点挂在商店覆盖层的离开动作上——复用既有呈现位,零新增交互范式 |
|
| 兑付后确认 | 到达节点立即兑付,不设"进入前确认"步;兑付反馈呈现完,玩家确认才回图。战斗节点的确认挂在战斗总结结算上(呈现 spec:design/ux/settlement-summary.md),奖励/恢复节点挂在兑付反馈覆盖层上,商店节点挂在商店覆盖层的离开动作上——复用既有呈现位,零新增交互范式 |
|
||||||
| 零自动推进 | 确认之后回到关卡画面的选路口:岔路口玩家选一条连线,单链路口确认"继续"。选了才走;不选就停在图上 |
|
| 零自动推进 | 确认之后回到关卡画面的选路口:岔路口玩家选一条连线,单链路口确认"继续"。选了才走;不选就停在图上 |
|
||||||
|
|
||||||
Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选路——关卡已定局,后续流程归冒险结构。
|
Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选路——关卡已定局,后续流程归冒险结构。
|
||||||
@@ -123,7 +123,7 @@ Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选
|
|||||||
|
|
||||||
第二关的"新内容 = 既有池新技能"(技能池构成已定稿入[敌人系统](../战斗循环/敌人系统.md)技能池节)投放时,改的是战斗侧行里引用的技能池内容——节点图结构原样不动,本文无需为投放留任何新结构位。
|
第二关的"新内容 = 既有池新技能"(技能池构成已定稿入[敌人系统](../战斗循环/敌人系统.md)技能池节)投放时,改的是战斗侧行里引用的技能池内容——节点图结构原样不动,本文无需为投放留任何新结构位。
|
||||||
|
|
||||||
**节点奖励 = 提升三选一(用户 2026-10-01 拍板:与通关三选一共享同池)**:奖励节点到达即开三选一(呈现 = 提升三选一覆盖层共用面,spec:[node-reward.md](../../ux/node-reward.md) v2.0)——从提升池七种(攻击/生命上限/护甲/GP 袋/行动点件/恢复件/刷新件)按同一令牌库洗牌不放回抽 3(同 kind 去重、同一封闭随机流),玩家点选一件兑付(选中踢池、未选回池;秘宝件已出池,满位替换子交互随之不再触发)。件获取次数计数与令牌库为冒险级单例——两渠道同一令牌库合计消耗。「池空直通」为合法态——池耗即枯竭,空库 = 零候选合法态直通(见[冒险结构](冒险结构.md)令牌池节)。
|
**节点奖励 = 提升三选一(用户 2026-10-01 拍板:与通关三选一共享同池)**:奖励节点到达即开三选一(呈现 = 提升三选一覆盖层共用面,spec:[node-reward.md](../../../ux/node-reward.md) v2.0)——从提升池七种(攻击/生命上限/护甲/GP 袋/行动点件/恢复件/刷新件)按同一令牌库洗牌不放回抽 3(同 kind 去重、同一封闭随机流),玩家点选一件兑付(选中踢池、未选回池;秘宝件已出池,满位替换子交互随之不再触发)。件获取次数计数与令牌库为冒险级单例——两渠道同一令牌库合计消耗。「池空直通」为合法态——池耗即枯竭,空库 = 零候选合法态直通(见[冒险结构](冒险结构.md)令牌池节)。
|
||||||
|
|
||||||
### 关卡收束点:先清库、后宣布
|
### 关卡收束点:先清库、后宣布
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
| 节点奖励件的分类与凭证定义、池结构与抽取机制(案D——共享池库存仍归本文) | [奇物](奇物.md) |
|
| 节点奖励件的分类与凭证定义、池结构与抽取机制(案D——共享池库存仍归本文) | [奇物](奇物.md) |
|
||||||
| 关卡完成率带、敌我数值与 Boss 设计 | [难度曲线与Boss](难度曲线与Boss.md) |
|
| 关卡完成率带、敌我数值与 Boss 设计 | [难度曲线与Boss](难度曲线与Boss.md) |
|
||||||
| 钥石与跨局成长 | [元进度](../跨局循环/元进度.md) |
|
| 钥石与跨局成长 | [元进度](../跨局循环/元进度.md) |
|
||||||
| 冒险总结结算(呈现摘要五件事;呈现 spec:design/gdd/ux/settlement-summary.md)与关卡推进指示 | [HUD框架](../表现与支撑/HUD框架.md) |
|
| 冒险总结结算(呈现摘要五件事;呈现 spec:design/ux/settlement-summary.md)与关卡推进指示 | [HUD框架](../表现与支撑/HUD框架.md) |
|
||||||
|
|
||||||
## 在核心循环中的位置
|
## 在核心循环中的位置
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ GP(显示名「GP」)是冒险内的一次性属性提升货币:战斗胜
|
|||||||
- **停点粒度**:快照只挂选路停点(入口呈现/战斗胜利后/兑付确认后的选路态)——这是唯一可恢复停点形态。战斗进行中不写快照:中断恢复后**当场战斗从头打**,棋盘中局不入档。
|
- **停点粒度**:快照只挂选路停点(入口呈现/战斗胜利后/兑付确认后的选路态)——这是唯一可恢复停点形态。战斗进行中不写快照:中断恢复后**当场战斗从头打**,棋盘中局不入档。
|
||||||
- **七字段拍板面**:关卡序号 / 节点位 / 生命 / 本关加成区 / GP 钱包 / 商店已购档 / 已抽模板。附随件(续玩正确性必需):主种子 + 取数计数器(rng 快照契约回填——续玩从断点号位精确续接原随机时间线,已抽模板零重抽)、钥石累计(Boss 掉落逐杀入账的中途值,终局摘要不失真)、已到节点序(关卡画面图条重建)、秘宝库存(奖励节点已选件防静默丢失)、**奖励选择态**(三选一停点中断:已选件 / 同调位替换在途——续玩已选不丢失;候选一致性=快照现状非强求 feature,2026-10-01 用户裁决)、**件获取次数计数**(kind 维度派生账本——断点附随件与读数承载)、**令牌池余库**(bonus_deck 逐枚还原——TP0 扩列,池消耗即上限的续玩正确性承载;旧版断点缺键=满库重建防御口径,单版本周期)、**商店货架态**(当前货架三件 + 本次进店已购次数;离开店=空架合法态,货架续玩由确定性重放承载:重进店同种子同货架逐位)、**Y 刷新池余量**(attune_refresh_y——冒险周期池消耗余量随断点:续玩优先读断点、不自参数面整额重注入,堵「用完 Y 退菜单再续玩满血复活」可利用漏洞;旧断点缺键回退参数面=旧档行为零变化)。
|
- **七字段拍板面**:关卡序号 / 节点位 / 生命 / 本关加成区 / GP 钱包 / 商店已购档 / 已抽模板。附随件(续玩正确性必需):主种子 + 取数计数器(rng 快照契约回填——续玩从断点号位精确续接原随机时间线,已抽模板零重抽)、钥石累计(Boss 掉落逐杀入账的中途值,终局摘要不失真)、已到节点序(关卡画面图条重建)、秘宝库存(奖励节点已选件防静默丢失)、**奖励选择态**(三选一停点中断:已选件 / 同调位替换在途——续玩已选不丢失;候选一致性=快照现状非强求 feature,2026-10-01 用户裁决)、**件获取次数计数**(kind 维度派生账本——断点附随件与读数承载)、**令牌池余库**(bonus_deck 逐枚还原——TP0 扩列,池消耗即上限的续玩正确性承载;旧版断点缺键=满库重建防御口径,单版本周期)、**商店货架态**(当前货架三件 + 本次进店已购次数;离开店=空架合法态,货架续玩由确定性重放承载:重进店同种子同货架逐位)、**Y 刷新池余量**(attune_refresh_y——冒险周期池消耗余量随断点:续玩优先读断点、不自参数面整额重注入,堵「用完 Y 退菜单再续玩满血复活」可利用漏洞;旧断点缺键回退参数面=旧档行为零变化)。
|
||||||
- **中断与退出两口径分离**(2026-09-29 用户裁决):中断(关游戏)= 留断点可续;**退出冒险**(放弃流程)= 失败同型结算 + **清除断点**——退出后「继续上局」不再出现。
|
- **中断与退出两口径分离**(2026-09-29 用户裁决):中断(关游戏)= 留断点可续;**退出冒险**(放弃流程)= 失败同型结算 + **清除断点**——退出后「继续上局」不再出现。
|
||||||
- **获得日记键**(gain_journal,断点 28 键):获得记录明细(三层结构归架构文档「冒险域拆分」节主角账条目——本域只登记断点面口径)随断点保存,回退策略 plain;旧档回退两态——旧断点缺日记键=汇总键直载并跳过比对(零迁移损失),日记在档=由日记推导汇总值与留存值比对,不符即报错中止(迁移正确性自检)。
|
- **获得日记键**(gain_journal,断点 28 键):获得记录明细(三层结构归架构文档「模块归属·核心层」GainJournal 行——本域只登记断点面口径)随断点保存,回退策略 plain;旧档回退两态——旧断点缺日记键=汇总键直载并跳过比对(零迁移损失),日记在档=由日记推导汇总值与留存值比对,不符即报错中止(迁移正确性自检)。
|
||||||
- **续玩**:自断点重建到最近停点(逐字段回填 + 随机流回填),停点处玩家重新选路。三结局(冒险成功/失败/放弃)一律清断点——断点只活在一个进行中的冒险上。
|
- **续玩**:自断点重建到最近停点(逐字段回填 + 随机流回填),停点处玩家重新选路。三结局(冒险成功/失败/放弃)一律清断点——断点只活在一个进行中的冒险上。
|
||||||
- 与测量面的关系:断点面只在注入存档承载的正式冒险路径生效;模拟/冒烟不注入 = 整面静默,MC 逐项比对零扰动。
|
- 与测量面的关系:断点面只在注入存档承载的正式冒险路径生效;模拟/冒烟不注入 = 整面静默,MC 逐项比对零扰动。
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
>
|
>
|
||||||
> **兑付频率(先看这条,它是三条渠道的共同前提)**:奇物**不是打一场战斗给一份**。关内的普通战斗节点打完了什么也不给;一关之内奇物**只兑付一次**,触发点是**关底 Boss 被击败**——而按 [冒险结构](冒险结构.md) 的定义,打掉关底 Boss 恰好就等于"通过这一关",这两件事是同一个时刻,不是一条链上的两步。
|
> **兑付频率(先看这条,它是三条渠道的共同前提)**:奇物**不是打一场战斗给一份**。关内的普通战斗节点打完了什么也不给;一关之内奇物**只兑付一次**,触发点是**关底 Boss 被击败**——而按 [冒险结构](冒险结构.md) 的定义,打掉关底 Boss 恰好就等于"通过这一关",这两件事是同一个时刻,不是一条链上的两步。
|
||||||
>
|
>
|
||||||
> 状态:**已实现**;现行为 v1.6。本文件是奇物的唯一定义文档。
|
> 状态:**已实现**;现行为 v1.7。本文件是奇物的唯一定义文档。
|
||||||
>
|
>
|
||||||
> 数值纪律:本文件只写概念、取值域与指路;每件给多少、效果是什么一律不进正文,事实源是 `data/tables/feats.tres` 与 `data/tables/adventure.tres`。
|
> 数值纪律:本文件只写概念、取值域与指路;每件给多少、效果是什么一律不进正文,事实源是 `data/tables/feats.tres` 与 `data/tables/adventure.tres`。
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
> **落行注记**:「每第 N 次 / 积满触发」的数据行条件写 **N−1**——效果引擎分发时 when 先于 do 读计数器现值(预评估),故「满 N 触发」落行写 N−1(例:地质学家「满 4 种」写 eq 3、封印匠「每第 3 次」写 mod_eq ref 2、双管镐「每第 2 次」写 mod_eq ref 1)。行为仍为每第 N 次准点触发,单元测试钉住;新件落行照此口径。
|
> **落行注记**:「每第 N 次 / 积满触发」的数据行条件写 **N−1**——效果引擎分发时 when 先于 do 读计数器现值(预评估),故「满 N 触发」落行写 N−1(例:地质学家「满 4 种」写 eq 3、封印匠「每第 3 次」写 mod_eq ref 2、双管镐「每第 2 次」写 mod_eq ref 1)。行为仍为每第 N 次准点触发,单元测试钉住;新件落行照此口径。
|
||||||
|
|
||||||
### 基础件表(27 件,五族 + 跨族桥 + 契约尖点)
|
### 基础件表(26 件,五族 + 契约尖点)
|
||||||
|
|
||||||
**开格系(6)**
|
**开格系(6)**
|
||||||
|
|
||||||
@@ -69,11 +69,7 @@
|
|||||||
|
|
||||||
**踩雷转化对账锚(自爆流 kill-switch,2026-10-11 用户裁)**:踩雷的净血账期望必须为负——雷伤 > 血蜜回复 + 其余转化件的血当量;对账归调参批,两轮数值迭代压不住则砍血蜜。防「见雷就踩」退化(喂雷流教训同源);主动/误踩不判定(用户裁:不预判玩家意图,拿件自选收益最高的操作)。
|
**踩雷转化对账锚(自爆流 kill-switch,2026-10-11 用户裁)**:踩雷的净血账期望必须为负——雷伤 > 血蜜回复 + 其余转化件的血当量;对账归调参批,两轮数值迭代压不住则砍血蜜。防「见雷就踩」退化(喂雷流教训同源);主动/误踩不判定(用户裁:不预判玩家意图,拿件自选收益最高的操作)。
|
||||||
|
|
||||||
**跨族桥(封印系 × 踩雷系)(1)**
|
**跨族桥退役(2026-11-07 用户裁)**:破封一击(on 挖开有封印印记的危险格:额外 +1 层)退役进[道具退役素材库](../../../content-archive/道具退役素材库.md)表五——「封印受理即揭示、封印格拒绝挖掘」口径换代后「挖开封印格」路径不存在,专长永远无法触发;其触发事实词「被挖格当时有封印印记」随件自引擎除名。跨族桥位现空缺。
|
||||||
|
|
||||||
| 代号 | on / when / do(声明要点) | 账 |
|
|
||||||
|---|---|---|
|
|
||||||
| 破封一击 | on 挖开有封印印记的危险格:额外 +1 层(疼痛记忆同账) | 印记=标定引信、挖=引爆——推理定位的显式回报;挂棋盘事实(挖开格当时有封印印记)非玩家意图判定(扩签:被挖格当时有封印印记) |
|
|
||||||
|
|
||||||
**节奏系(3)**
|
**节奏系(3)**
|
||||||
|
|
||||||
@@ -281,7 +277,7 @@
|
|||||||
**两层是两件事,别混**:
|
**两层是两件事,别混**:
|
||||||
|
|
||||||
- **命名是本节的规矩**——三个分类各有一个专名,文档、代码词族、帮百科一律用它。指代某个分类时直接说「专长」,不说「机制类」「专长那一类」。
|
- **命名是本节的规矩**——三个分类各有一个专名,文档、代码词族、帮百科一律用它。指代某个分类时直接说「专长」,不说「机制类」「专长那一类」。
|
||||||
- **呈现是另一件事**(归 [battle](../../ux/battle.md) 与 [node-reward](../../ux/node-reward.md),本节不裁决):玩家看到某件奇物时,卡面只写**这件东西的名字与效果**,不附带它的分类。玩家可以从效果反推它属于哪一类,但界面不替他说破。
|
- **呈现是另一件事**(归 [battle](../../../ux/battle.md) 与 [node-reward](../../../ux/node-reward.md),本节不裁决):玩家看到某件奇物时,卡面只写**这件东西的名字与效果**,不附带它的分类。玩家可以从效果反推它属于哪一类,但界面不替他说破。
|
||||||
|
|
||||||
**为什么两层都要有**:分类名在卡面上不出现,不等于玩家对它没有概念——帮助手册、百科条目、成就名称三处一定会用到它(「首次集齐 4 件专长」「三件属性值提升」),效果描述里出现指代时也需要名字(如「本项属专长」类归类指代)。所以它必须是一个**玩家读得懂、读一遍就懂**的正式名词,不能是内部描述或自造词。
|
**为什么两层都要有**:分类名在卡面上不出现,不等于玩家对它没有概念——帮助手册、百科条目、成就名称三处一定会用到它(「首次集齐 4 件专长」「三件属性值提升」),效果描述里出现指代时也需要名字(如「本项属专长」类归类指代)。所以它必须是一个**玩家读得懂、读一遍就懂**的正式名词,不能是内部描述或自造词。
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 难度曲线与Boss
|
# 难度曲线与Boss
|
||||||
|
|
||||||
> 一句话:难度曲线、期望值带与 Boss 设计
|
> 一句话:难度曲线、期望值带与 Boss 设计
|
||||||
> 状态:已定稿;现行为 v1.5
|
> 状态:已定稿;现行为 v1.6
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 关间台阶(关卡序号) | 每关至少投放一项新内容(新敌种或既有池新技能),加基准数值跳升 | 台阶必须能归因到看得见的变化,不是纯数字膨胀;投放断档是内容生产缺口,调参修补不了 |
|
| 关间台阶(关卡序号) | 每关至少投放一项新内容(新敌种或既有池新技能),加基准数值跳升 | 台阶必须能归因到看得见的变化,不是纯数字膨胀;投放断档是内容生产缺口,调参修补不了 |
|
||||||
| 关内坡度(节点深度) | 同敌种数值平缓上移,深度也可表达为敌人成群 | 数量是比单体质变更优先的深度表达:保持技能池 EV 读数不变(权重即旋钮、EV 重锚顺带登记)、总量受控 |
|
| 关内坡度(节点深度) | 同敌种数值平缓上移,深度也可表达为敌人成群 | 数量是比单体质变更优先的深度表达:保持技能池 EV 读数不变(权重即旋钮、EV 重锚顺带登记)、总量受控 |
|
||||||
| Boss 与精英修饰(预留第三轴) | Boss 走最深深度直填行;精英只有字段命名空间预留 | Boss 不走修饰表;修饰乘数表 MVP 为空表、零行为,首个使用场景 = 精英节点(随[关卡节点地图](关卡节点地图.md)定稿联动);数值所有权在本系统,[棋盘生成](../排雷循环/棋盘生成.md)只按表生成。精英怪设定已登记预留(与其他普通小怪同一立绘 + 附加特征标记 + 数值更强;视觉特征三件 = 名称前后缀「精英·」+ 底座光环 + 描边变色,色板合规与样张闸义务随怪物设定批实装) |
|
| Boss 与精英修饰(预留第三轴) | Boss 走最深深度直填行;精英怪本体走敌人表精英行(独立行+池继承附加,语义见[敌人系统](../战斗循环/敌人系统.md)「精英行」节),精英节点修饰只有字段命名空间预留 | Boss 不走修饰表;修饰乘数表 MVP 为空表、零行为,首个使用场景 = 精英节点(随[关卡节点地图](关卡节点地图.md)定稿联动);数值所有权在本系统(含精英行数值与附加技权重),[棋盘生成](../排雷循环/棋盘生成.md)只按表生成。精英怪设定:与其他普通小怪同一立绘 + 附加特征标记 + 数值更强;视觉特征三件 = 名称前缀「精英·」(由精英行名字行值承载)+ 底座光环 + 描边变色,后两件的色板合规与样张闸义务随怪物设定批实装 |
|
||||||
|
|
||||||
**结论**:关内坡度 = 每深一档同敌种基准上移,或按"深度也可表达为敌人成群"改由数量承载——单体生命随深度的具体走向以 `enemy.tres` 行值为准(数量优先于单体;s_hp 线性式为建模工具,现行行值不承诺随深度单调上移);关间台阶 = 相邻关同敌种基准乘 1.3–1.6(域语义如上;s_hp / k_L 现行行值读 `enemy.tres`,取值域归敌人表字段定义)。
|
**结论**:关内坡度 = 每深一档同敌种基准上移,或按"深度也可表达为敌人成群"改由数量承载——单体生命随深度的具体走向以 `enemy.tres` 行值为准(数量优先于单体;s_hp 线性式为建模工具,现行行值不承诺随深度单调上移);关间台阶 = 相邻关同敌种基准乘 1.3–1.6(域语义如上;s_hp / k_L 现行行值读 `enemy.tres`,取值域归敌人表字段定义)。
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 地图战斗资源
|
# 地图战斗资源
|
||||||
|
|
||||||
> 一句话:格面资源的产出、极性字典与清图奖励封装
|
> 一句话:格面资源的产出、极性字典与清图奖励封装
|
||||||
> 状态:已定稿;现行为 v1.5
|
> 状态:已定稿;现行为 v1.7
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
|
|
||||||
- **档由两个参数定义:概率位 + 保底上限**。「永不保底」不单立规则——T4 的保底上限 = 0 即其统一表达;T1/T2 上限同为 0。
|
- **档由两个参数定义:概率位 + 保底上限**。「永不保底」不单立规则——T4 的保底上限 = 0 即其统一表达;T1/T2 上限同为 0。
|
||||||
- **保底数量挂在型上、不挂在档上**:每个型各自登记「每板至少出几个」。档内登记保底的型数 ≤ 档上限 → 全部兑现;> 上限 → 每板从登记型中随机选定「上限」个兑现,其余型该板按普通概率出现、不保底。
|
- **保底数量挂在型上、不挂在档上**:每个型各自登记「每板至少出几个」。档内登记保底的型数 ≤ 档上限 → 全部兑现;> 上限 → 每板从登记型中随机选定「上限」个兑现,其余型该板按普通概率出现、不保底。
|
||||||
- **补签纪律**:执行序 = 装板摇号(含偏运硬币投影)→ 按上限定本期保底型集合 → 校验补签 → 板上全程只读。补签只改类型身份:危险格与安全格不动(补签格可为雷可为安全格,危险格与安全格同池不破)、不消费权重(补签不是一次取号)、清图判定不动、不泄露元信息(补签格与摇号格不可区分)。粒度 = 板,换板重新校验。
|
- **补签纪律**:执行序 = 装板摇号(含订阅加权投影)→ 按上限定本期保底型集合 → 校验补签 → 板上全程只读。补签只改类型身份:危险格与安全格不动(补签格可为雷可为安全格,危险格与安全格同池不破)、不消费权重(补签不是一次取号)、清图判定不动、不泄露元信息(补签格与摇号格不可区分)。粒度 = 板,换板重新校验。
|
||||||
- **GP 数值锚**:以战斗结束 GP 奖励为锚——小 GP 袋 ≈ 其 1/10、大宝箱 ≈ 其 1 倍(具体数值归调参批)。
|
- **GP 数值锚**:以战斗结束 GP 奖励为锚——小 GP 袋 ≈ 其 1/10、大宝箱 ≈ 其 1 倍(具体数值归调参批)。
|
||||||
- 大宝箱为枚举新增(九型→十型走本文修订流程,不随手加行);微光归通用增益组(五色相不变,组内不细分正好容下)。
|
- 大宝箱为枚举新增(九型→十型走本文修订流程,不随手加行);微光归通用增益组(五色相不变,组内不细分正好容下)。
|
||||||
- **对外稀有度映射**(现行事实源=[核心循环](../../01-核心循环.md)「档位与获取规则」节):T1=普通 / T2=优秀 / T3=稀有 / T4=传说;任何概率提升禁止改变本档保底承诺(保底=承诺非概率)。
|
- **对外稀有度映射**(现行事实源=[核心循环](../../01-核心循环.md)「档位与获取规则」节):T1=普通 / T2=优秀 / T3=稀有 / T4=传说;任何概率提升禁止改变本档保底承诺(保底=承诺非概率)。
|
||||||
@@ -108,8 +108,7 @@
|
|||||||
| 玩家动作 | 安全格 | 危险格 |
|
| 玩家动作 | 安全格 | 危险格 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 开格 | **+类型**:该格资源的正向兑付(奖励) | **−类型**:该格资源的负向兑付(惩罚) |
|
| 开格 | **+类型**:该格资源的正向兑付(奖励) | **−类型**:该格资源的负向兑付(惩罚) |
|
||||||
| 封印且留到轮末判定 | **−类型**:标错,该格资源的负向兑付(惩罚) | **+类型**:标中,该格资源的正向兑付(奖励) |
|
| 封印(受理即揭示、留到轮末判定——封印格拒绝挖掘,挖开封印格路径不存在) | **−类型**:标错,该格资源的负向兑付(惩罚);该格资源正向不兑付 | **+类型**:标中,该格资源的正向兑付(奖励) |
|
||||||
| 封印格直接挖开 | 零兑付(四情况④:零惩罚零奖励——标空不判、正向作废) | **−类型**照常(四情况②:只受挖雷一层惩罚——标中不发) |
|
|
||||||
|
|
||||||
矩阵的定义归本文;把矩阵跑起来的路由(结算队列、判定基线、逐行兑付)归[战斗结算](战斗结算.md)的授予段。blast 型负向 = 警觉。矩阵只描述现行规则;被本矩阵取代的旧体系与历次结构变更(撤旗退役、伏击换装等)只进 git 提交史,不在正文复述。
|
矩阵的定义归本文;把矩阵跑起来的路由(结算队列、判定基线、逐行兑付)归[战斗结算](战斗结算.md)的授予段。blast 型负向 = 警觉。矩阵只描述现行规则;被本矩阵取代的旧体系与历次结构变更(撤旗退役、伏击换装等)只进 git 提交史,不在正文复述。
|
||||||
|
|
||||||
@@ -147,7 +146,7 @@
|
|||||||
|
|
||||||
### 清图奖励对象:整图封装,可配置可替换
|
### 清图奖励对象:整图封装,可配置可替换
|
||||||
|
|
||||||
清图奖励不属于任何一格的格面资源——它是作用域为整张板的独立奖励对象:把一张图的雷全部清完(全部安全格开完)时结算发的那一份。装板摇号时与格子资源同批判尾摇定身份;清图批兑付恰好一次;完美封印(零误标且至少一次封印标中)追加第二份同身份兑付。清图奖励只在清图批兑付:弃图刷新不触发清图事件,换来的新图不发清图奖励;刷新专长的固定 GP 收益走战斗内缓冲入账,不属清图奖励封装。
|
清图奖励不属于任何一格的格面资源——它是作用域为整张板的独立奖励对象:把一张图的雷全部清完(全部安全格完成——挖开或封印,口径见[排雷玩法](../排雷循环/排雷玩法.md))时结算发的那一份。装板摇号时与格子资源同批判尾摇定身份;清图批兑付恰好一次;完美封印(零误标且至少一次封印标中)追加第二份同身份兑付。清图奖励只在清图批兑付:弃图刷新不触发清图事件,换来的新图不发清图奖励;刷新专长的固定 GP 收益走战斗内缓冲入账,不属清图奖励封装。
|
||||||
|
|
||||||
它是可配置可替换的封装:数据面上是清图池里的一行(现行默认槽 clear_default),换行即换内容,机制零改动。按图类型差异化已留结构位——`clear_<图类型>` 命名空间预留,不同地图类型可以配不同的清图奖励;词表现行 = {dungeon, underdark, deep_underdark}(玩家侧「地图类型」),差异化内容启用随内容批。
|
它是可配置可替换的封装:数据面上是清图池里的一行(现行默认槽 clear_default),换行即换内容,机制零改动。按图类型差异化已留结构位——`clear_<图类型>` 命名空间预留,不同地图类型可以配不同的清图奖励;词表现行 = {dungeon, underdark, deep_underdark}(玩家侧「地图类型」),差异化内容启用随内容批。
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 战斗结算
|
# 战斗结算
|
||||||
|
|
||||||
> 一句话:轮末结算的编排与逐行兑现
|
> 一句话:轮末结算的编排与逐行兑现
|
||||||
> 状态:已定稿;现行为 v1.7
|
> 状态:已定稿;现行为 v1.9
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|---|---|
|
|---|---|
|
||||||
| 轮次编排 | 战斗开始序列、每轮五段结算、五种出口分发(继续 / 换图 / 挖掘期刷新 / 战斗结束 / 关卡结束) |
|
| 轮次编排 | 战斗开始序列、每轮五段结算、五种出口分发(继续 / 换图 / 挖掘期刷新 / 战斗结束 / 关卡结束) |
|
||||||
| 结算触发与段序 | 轮末自动触发一次整轮结算;五段顺序为冻结结构,改动走文档修订而非调参 |
|
| 结算触发与段序 | 轮末自动触发一次整轮结算;五段顺序为冻结结构,改动走文档修订而非调参 |
|
||||||
| 结算队列与判定基线 | 挖掘期动作(开格、封印)入结算队列;封印判定以轮末在场封印为基线,逐行兑付(撤旗动作退役) |
|
| 结算队列与判定基线 | 挖掘期动作(开格、封印)入结算队列;封印判定以轮末在场封印为基线,逐行兑付(封印格拒绝挖掘,受理过的封印必然在基线) |
|
||||||
| 明细流水协议 | 结算中的每件事逐行留档并标注来源,是呈现、回放对账、数据导出共读的唯一数据源 |
|
| 明细流水协议 | 结算中的每件事逐行留档并标注来源,是呈现、回放对账、数据导出共读的唯一数据源 |
|
||||||
| 收益对照表 | 一张效果档位对照表归一全部收益的折算口径(详见核心规则) |
|
| 收益对照表 | 一张效果档位对照表归一全部收益的折算口径(详见核心规则) |
|
||||||
| 伤害与治疗边界 | 修正池合成与封顶、溢杀丢弃、治疗封顶、死亡判定时机 |
|
| 伤害与治疗边界 | 修正池合成与封顶、溢杀丢弃、治疗封顶、死亡判定时机 |
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
| 判定行 | 胜 / 负 / 继续各一行;终局判定行同时是胜负画面的数据锚 |
|
| 判定行 | 胜 / 负 / 继续各一行;终局判定行同时是胜负画面的数据锚 |
|
||||||
| 高光行 | 完美封印成立时一行,只记实际有效兑付 |
|
| 高光行 | 完美封印成立时一行,只记实际有效兑付 |
|
||||||
|
|
||||||
每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。奖励直伤行的数值字段沿用 `effectiveness` 键名、值为整数点数——键名与量纲是数据导出与分析工具的兼容契约,改动须连动分析工具面。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。
|
每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。**显示名等玩家可见文案是数据面字段:文案值登记在数据表行,代码按来源类别与效果身份读表拼行,不在代码里写死文案字串**(2026-11-06 用户裁——文案归属数据表承载;承载表与字段形态归表结构设计段定,设计闭合后由实装批落表)。奖励直伤行的数值字段沿用 `effectiveness` 键名、值为整数点数——键名与量纲是数据导出与分析工具的兼容契约,改动须连动分析工具面。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。
|
||||||
|
|
||||||
任何一行找不到来源即断言失败——宁可返回错误,也不让"合并到看不出来源"的呈现混过数据层。但有些行天然没有棋盘来源,断言为此留了两层豁免,豁免集合是封闭清单,改动同样走本文修订。
|
任何一行找不到来源即断言失败——宁可返回错误,也不让"合并到看不出来源"的呈现混过数据层。但有些行天然没有棋盘来源,断言为此留了两层豁免,豁免集合是封闭清单,改动同样走本文修订。
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
基础 9 类写的是裸机制的账:玩家没有任何专长时,结算流水的每一行都出得了这九类。有了专长之后,效果引擎会在段内挂点插入额外的结算效果,这类效果写**扩展行**。扩展行是**一个**行型,不是每种专长效果各占一个行型——具体插的是哪种效果,由行携带的效果身份(effect_id 载荷)说明,呈现层按身份取各自的行文案。专长会不断增加、效果种类不可穷举,行型词表因此对扩展类封口:新增专长效果只新增载荷身份,不再新增行型。
|
基础 9 类写的是裸机制的账:玩家没有任何专长时,结算流水的每一行都出得了这九类。有了专长之后,效果引擎会在段内挂点插入额外的结算效果,这类效果写**扩展行**。扩展行是**一个**行型,不是每种专长效果各占一个行型——具体插的是哪种效果,由行携带的效果身份(effect_id 载荷)说明,呈现层按身份取各自的行文案。专长会不断增加、效果种类不可穷举,行型词表因此对扩展类封口:新增专长效果只新增载荷身份,不再新增行型。
|
||||||
|
|
||||||
扩展行与基础行共用同一套行协议:公共字段、来源归因、两层豁免、无来源即炸,全部照常生效。发射时点由段序骨架的挂点决定(时序与挂点施加面归架构文档「战斗域装配现状」节),本节只管这行是什么、带什么字段。扩展行携带效果身份(effect_id 载荷);效果身份清单与各发射点归架构文档「战斗域装配现状」与「战斗编排域拆件定稿」节登记。
|
扩展行与基础行共用同一套行协议:公共字段、来源归因、两层豁免、无来源即炸,全部照常生效。发射时点由段序骨架的挂点决定(时序与挂点施加面、效果身份清单与各发射点归代码文件头注承载——模块归属见架构文档「模块归属·功能层」battle_orchestrator 行),本节只管这行是什么、带什么字段。扩展行携带效果身份(effect_id 载荷)。
|
||||||
|
|
||||||
举证:本节为行协议约定,无计算。
|
举证:本节为行协议约定,无计算。
|
||||||
|
|
||||||
@@ -127,22 +127,15 @@ percent 类(每结算、每层): E = |层数 × 行值| ÷ 100 ×
|
|||||||
|
|
||||||
### 授予段兑付:极性路由,四类动作各归各系统资源
|
### 授予段兑付:极性路由,四类动作各归各系统资源
|
||||||
|
|
||||||
授予段消费结算队列。**队列与判定基线**:挖掘期玩家对格子的动作——开格、封印——都进入结算队列;结算逐批兑付,不走逐动作出栈直算。封印判定以轮末在场封印位为基线:被直接挖开的封印已随挖掘消失、不在基线(零兑付——标中 / 标空让位于挖掘本体结局,见下文封印不可逆四情况);开格事实不可撤(已开格无法回退)。过滤后按触发源分三批兑换,每格受理、每封印判定恰好一次。
|
授予段消费结算队列。**队列与判定基线**:挖掘期玩家对格子的动作——开格、封印——都进入结算队列;结算逐批兑付,不走逐动作出栈直算。封印判定以轮末在场封印位为基线:封印格拒绝挖掘,受理过的封印必然保留到轮末、全部在基线;开格事实不可撤(已开格无法回退)。过滤后按触发源分三批兑换,每格受理、每封印判定恰好一次。
|
||||||
|
|
||||||
兑付走**极性矩阵**(定义归[地图战斗资源](地图战斗资源.md)):开安全格 → 该格格面资源的正向;开危险格 → 负向;封印标中 → 该危险格资源的正向;标错封印 → 该安全格资源的负向。九型字典里每型各有一行正向、一行负向(gp 正负两向兑付 = 战斗内 GP 缓冲,见下方兑付形态表);伏击已退役,blast 型负向现况 = 警觉(敌方护甲等级 +1)。
|
兑付走**极性矩阵**(定义归[地图战斗资源](地图战斗资源.md)):开安全格 → 该格格面资源的正向;开危险格 → 负向;封印标中 → 该危险格资源的正向;标错封印 → 该安全格资源的负向。九型字典里每型各有一行正向、一行负向(gp 正负两向兑付 = 战斗内 GP 缓冲,见下方兑付形态表);伏击已退役,blast 型负向现况 = 警觉(敌方护甲等级 +1)。
|
||||||
|
|
||||||
**封印不可逆四情况(2026-09-19 用户拍板)**:封印印记是一次性承诺、移除动作退役、挖封印格放行——兑付按四情况改判:
|
**封印受理即揭示(2026-11-07 用户裁)**:封印受理只完成揭示与立印——墙瓦片换地板、格下身份当场可见(裁决见[排雷玩法](../排雷循环/排雷玩法.md)),兑付仍全部发生在轮末判定批,受理当场零兑付;封印格拒绝挖掘,「挖开封印格」的兑付改判路径随之不存在。
|
||||||
|
|
||||||
| 情况 | 兑付 |
|
|
||||||
|---|---|
|
|
||||||
| ① 插危险格、留到轮末判定 | 标中照常(该危险格资源正向) |
|
|
||||||
| ② 插危险格、再直接挖开 | 只受挖雷一层惩罚(该危险格资源负向照常兑付;挖雷惩罚因惊动触发);标中不发(封印已随挖掘消失、不入判定基线) |
|
|
||||||
| ③ 插安全格、留到轮末判定 | 标空惩罚照常(该安全格资源负向) |
|
|
||||||
| ④ 插安全格、再直接挖开 | 零惩罚零奖励——正向兑付作废,记「奖励作废(封印格直接挖开)」归因行;标空判定同②自然缺席 |
|
|
||||||
|
|
||||||
| 批 | 兑付 |
|
| 批 | 兑付 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 挖格批 | 开到的安全格逐格兑该格资源的正向(封印格直挖除外——四情况④零奖励);开到的危险格逐格兑该格资源的负向(封印危险格照常——四情况②) |
|
| 挖格批 | 开到的安全格逐格兑该格资源的正向;开到的危险格逐格兑该格资源的负向 |
|
||||||
| 封印判定批 | 标中则兑该危险格资源的正向,每颗雷的资格只兑一次;标空则记"封印未中"归因行,并兑该安全格资源的负向 |
|
| 封印判定批 | 标中则兑该危险格资源的正向,每颗雷的资格只兑一次;标空则记"封印未中"归因行,并兑该安全格资源的负向 |
|
||||||
| 清图批 | 清图奖励对象恰好发一次;完美封印追加第二份同身份兑付 |
|
| 清图批 | 清图奖励对象恰好发一次;完美封印追加第二份同身份兑付 |
|
||||||
|
|
||||||
@@ -162,7 +155,7 @@ percent 类(每结算、每层): E = |层数 × 行值| ÷ 100 ×
|
|||||||
|
|
||||||
警觉(blast 负向)按个体归属:每个存活敌各发一条自己的实例(全体存活敌规则,见[增益状态](增益状态.md)〈目标规则与个体归属〉节),只活一轮、轮末随体清零;战斗段由防守方护甲等级读数消费(我打敌 = 该敌 armor_class + 它名下的 ac 型状态合计)。其余各型负向受池 clamp 与叠层上限承载。
|
警觉(blast 负向)按个体归属:每个存活敌各发一条自己的实例(全体存活敌规则,见[增益状态](增益状态.md)〈目标规则与个体归属〉节),只活一轮、轮末随体清零;战斗段由防守方护甲等级读数消费(我打敌 = 该敌 armor_class + 它名下的 ac 型状态合计)。其余各型负向受池 clamp 与叠层上限承载。
|
||||||
|
|
||||||
标中资格认雷不认封印:兑付资格以危险格实例为键——封印印记无任何移除手段(移除动作已退役,重复封印被"已有封印"拒绝)、同一颗雷跨轮不重复兑付;换图后新雷是新实例,资格自然重置。同一处封印一直落在雷上,每轮都会重新上报标中,去重是本系统的职责。
|
标中资格认雷不认封印:兑付资格以危险格实例为键——封印印记无任何移除手段(封印格拒绝挖掘,重复封印被"已有封印"拒绝)、同一颗雷跨轮不重复兑付;换图后新雷是新实例,资格自然重置。同一处封印一直落在雷上,每轮都会重新上报标中,去重是本系统的职责。
|
||||||
|
|
||||||
标错的惩罚:标空封印(标了但格不是雷)= 该安全格格面资源的负向兑付(极性矩阵的"标错"分支),类型化、确定性、零额外派生。负向兑付与"封印未中"归因行同键去重,每危险格实例只触发一次;叠层已满授予被拒时记"奖励未生效"行,不静默吞掉。
|
标错的惩罚:标空封印(标了但格不是雷)= 该安全格格面资源的负向兑付(极性矩阵的"标错"分支),类型化、确定性、零额外派生。负向兑付与"封印未中"归因行同键去重,每危险格实例只触发一次;叠层已满授予被拒时记"奖励未生效"行,不静默吞掉。
|
||||||
|
|
||||||
@@ -325,7 +318,7 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
|
|||||||
1. 战斗开始序列跑完(关闸门、初始化状态池、掷骰定敌数、生成敌人、装板并预分配资源、发开轮通知 + 开轮摇号),进入第一轮挖掘期。
|
1. 战斗开始序列跑完(关闸门、初始化状态池、掷骰定敌数、生成敌人、装板并预分配资源、发开轮通知 + 开轮摇号),进入第一轮挖掘期。
|
||||||
2. 挖掘期本系统只缓冲事实流(开格、封印入结算队列),不做任何兑付。
|
2. 挖掘期本系统只缓冲事实流(开格、封印入结算队列),不做任何兑付。
|
||||||
3. 轮末自动触发五段结算,触发与事件到达序无关。
|
3. 轮末自动触发五段结算,触发与事件到达序无关。
|
||||||
4. 授予段按判定基线过滤(被挖开的封印不入判定),再按极性矩阵三批兑现:开安全格兑正向(封印安全格直挖 = 四情况④零奖励作废行)、开危险格 / 标错封印兑负向(封印危险格直挖照常——四情况②)、清图发清图奖励对象(完美乘数读 settlement.tres p_perfect)。
|
4. 授予段按轮末在场封印基线兑付(封印格拒绝挖掘,在场封印必然全部在基线),再按极性矩阵三批兑现:开安全格兑正向、开危险格 / 标错封印兑负向、清图发清图奖励对象(完美乘数读 settlement.tres p_perfect)。
|
||||||
5. 增益合成、主角先手加逐敌按摇定技能兑付(伤害技三乘法链 / 增益技施放行)加地图伤害账殿后(暂存单随战斗段末统一结账)、衰减恰好一次。
|
5. 增益合成、主角先手加逐敌按摇定技能兑付(伤害技三乘法链 / 增益技施放行)加地图伤害账殿后(暂存单随战斗段末统一结账)、衰减恰好一次。
|
||||||
6. 判定段先主角后敌人:继续通知同图、清图换图续轮、胜负走战斗结束清理(秘宝背包不清)。
|
6. 判定段先主角后敌人:继续通知同图、清图换图续轮、胜负走战斗结束清理(秘宝背包不清)。
|
||||||
7. 明细流水全程落行,供呈现、回放与导出。
|
7. 明细流水全程落行,供呈现、回放与导出。
|
||||||
@@ -361,7 +354,7 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
|
|||||||
|
|
||||||
- 五段全序:任一轮结算的明细行按五段顺序排列。
|
- 五段全序:任一轮结算的明细行按五段顺序排列。
|
||||||
- 触发与到达序无关:同一轮末的两条结束消息按任意先后驱动,结算步骤流逐行相同。
|
- 触发与到达序无关:同一轮末的两条结束消息按任意先后驱动,结算步骤流逐行相同。
|
||||||
- 挖封印格兑付改判:有封印格直接挖开被受理——封印安全格直挖零奖励(作废归因行恰一次)、封印危险格直挖只吃挖雷惩罚;被挖开的封印不入轮末判定(零标中 / 标空兑付);开格事实不可撤。
|
- 封印受理即揭示零兑付:封印受理只完成揭示与立印,当场零资源兑付(无正向无负向);兑付只发生在轮末封印判定批——标中正向 / 标空负向,在场封印全部入判定基线;开格事实不可撤。
|
||||||
- 每事实恰一次:每格受理、每封印判定恰好一次;重复投递不改变结果。
|
- 每事实恰一次:每格受理、每封印判定恰好一次;重复投递不改变结果。
|
||||||
- 极性路由正确:开安全格 / 封印标中只兑正向、开危险格 / 标错封印只兑负向;兑付效果与该格资源类型的字典行一一对应。
|
- 极性路由正确:开安全格 / 封印标中只兑正向、开危险格 / 标错封印只兑负向;兑付效果与该格资源类型的字典行一一对应。
|
||||||
- 警觉按个体:每只敌各持自己的警觉实例、互不共享;blast 负向逐层直授无上限(个体化——2026-11-02 用户裁)。
|
- 警觉按个体:每只敌各持自己的警觉实例、互不共享;blast 负向逐层直授无上限(个体化——2026-11-02 用户裁)。
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
## 系统范围
|
## 系统范围
|
||||||
|
|
||||||
边界这样划:战斗屏上"发生什么、摆在哪里、是什么意思"已经由两份现行文档定稿——屏级呈现形态归 [战斗屏 UX 规格 battle.md](../../ux/battle.md),视觉基调与剪影色彩归 [美术圣经 art-bible](../../../art/art-bible.md)。本文只负责"这些东西怎么动",而且是排期靠后的打磨项(见 [不做清单](../../05-不做清单.md):战斗动画演出是 MVP 内的打磨项,一律排后)。
|
边界这样划:战斗屏上"发生什么、摆在哪里、是什么意思"已经由两份现行文档定稿——屏级呈现形态归 [战斗屏 UX 规格 battle.md](../../../ux/battle.md),视觉基调与剪影色彩归 [美术圣经 art-bible](../../../art/art-bible.md)。本文只负责"这些东西怎么动",而且是排期靠后的打磨项(见 [不做清单](../../05-不做清单.md):战斗动画演出是 MVP 内的打磨项,一律排后)。
|
||||||
|
|
||||||
负责:
|
负责:
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
| 不负责 | 归谁 |
|
| 不负责 | 归谁 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 屏级呈现形态与呈现语义(四区布局、敌人呈现〔站桩形态〕、明细带、高光行) | [battle.md](../../ux/battle.md) 与 [HUD 框架](../表现与支撑/HUD框架.md),本文只引用 |
|
| 屏级呈现形态与呈现语义(四区布局、敌人呈现〔站桩形态〕、明细带、高光行) | [battle.md](../../../ux/battle.md) 与 [HUD 框架](../表现与支撑/HUD框架.md),本文只引用 |
|
||||||
| 视觉基调、剪影哲学、色彩与图标键契约 | [art-bible](../../../art/art-bible.md),本文只引用 |
|
| 视觉基调、剪影哲学、色彩与图标键契约 | [art-bible](../../../art/art-bible.md),本文只引用 |
|
||||||
| 结算逻辑与逐行流水本身 | [战斗结算](战斗结算.md) |
|
| 结算逻辑与逐行流水本身 | [战斗结算](战斗结算.md) |
|
||||||
| 敌种视觉状态的数据面(哪个敌种有几态、什么姿态) | [敌人系统](敌人系统.md) |
|
| 敌种视觉状态的数据面(哪个敌种有几态、什么姿态) | [敌人系统](敌人系统.md) |
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
### 不另起场景:在既有呈现上叠加动画密度
|
### 不另起场景:在既有呈现上叠加动画密度
|
||||||
|
|
||||||
战斗屏是挖掘与结算两种形态共用的同一张屏:常驻双舞台(白话:战斗画面与扫雷图同屏常驻,像同一块屏上的两个舞台),结算期不切换场景,裁决与理由见 [battle.md 布局决策 1](../../ux/battle.md)。所以战斗表现的工作不是另做一个战斗场景,而是在既有呈现上叠加动画密度与演出——这是本系统范围边界的第一条。
|
战斗屏是挖掘与结算两种形态共用的同一张屏:常驻双舞台(白话:战斗画面与扫雷图同屏常驻,像同一块屏上的两个舞台),结算期不切换场景,裁决与理由见 [battle.md 布局决策 1](../../../ux/battle.md)。所以战斗表现的工作不是另做一个战斗场景,而是在既有呈现上叠加动画密度与演出——这是本系统范围边界的第一条。
|
||||||
|
|
||||||
"发生什么"与"怎么动"因此分了工:敌人死亡是血条归零后灰化加碎裂退场、禁止瞬间消失,结算明细带逐行滚动,完美封印与封印标中有高光行强调——这些呈现语义已由 battle.md 与 HUD 框架定稿,本文不复述。本文将来承接的只是其上的动画密度:受击反馈、弹道、退场动画等类别。
|
"发生什么"与"怎么动"因此分了工:敌人死亡是血条归零后灰化加碎裂退场、禁止瞬间消失,结算明细带逐行滚动,完美封印与封印标中有高光行强调——这些呈现语义已由 battle.md 与 HUD 框架定稿,本文不复述。本文将来承接的只是其上的动画密度:受击反馈、弹道、退场动画等类别。
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
样张是前置美术测试的判定物;本节把"怎么算过"在测试组织前写成文,避免临场现定标准。成文做法参照 [art-bible](../../../art/art-bible.md) §1.4 格子样张测试(内容清单、按序验收项、判定与回退),判据全部落到已冻结的现行口径上——本节不定任何新的视觉参数。
|
样张是前置美术测试的判定物;本节把"怎么算过"在测试组织前写成文,避免临场现定标准。成文做法参照 [art-bible](../../../art/art-bible.md) §1.4 格子样张测试(内容清单、按序验收项、判定与回退),判据全部落到已冻结的现行口径上——本节不定任何新的视觉参数。
|
||||||
|
|
||||||
样张内容清单(一组齐备,缺项即无效):按 [battle.md 布局决策 1](../../ux/battle.md) 的常驻双舞台四区布局整屏出样;角色剪影按棋盘格、结算明细带、战斗舞台三个语境同图摆放;~~敌人卡两候选形态对照(卡片式与站桩式各一版,其余内容不变)~~——**本项已完成(全站桩定稿、卡片式退役),正式样张按站桩形态单版出样即可**;受击、退场、高光兑现三组动画关键帧条(每组至少起、中、末三帧);敌人姿态精灵与数字、封印印记、小人同格叠放的遮挡对照组至少一组。
|
样张内容清单(一组齐备,缺项即无效):按 [battle.md 布局决策 1](../../../ux/battle.md) 的常驻双舞台四区布局整屏出样;角色剪影按棋盘格、结算明细带、战斗舞台三个语境同图摆放;~~敌人卡两候选形态对照(卡片式与站桩式各一版,其余内容不变)~~——**本项已完成(全站桩定稿、卡片式退役),正式样张按站桩形态单版出样即可**;受击、退场、高光兑现三组动画关键帧条(每组至少起、中、末三帧);敌人姿态精灵与数字、封印印记、小人同格叠放的遮挡对照组至少一组。
|
||||||
|
|
||||||
验收项按序判定,第一项不过 = 整张否决(继承格子样张"数字可读性定风格"的次序):
|
验收项按序判定,第一项不过 = 整张否决(继承格子样张"数字可读性定风格"的次序):
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
| 上游 | [HUD 框架](../表现与支撑/HUD框架.md) | 四区布局、战斗画面区(四区中的 B 区)演出区结构、敌人呈现(站桩形态)与明细带呈现语义——本文在其上叠加密度 |
|
| 上游 | [HUD 框架](../表现与支撑/HUD框架.md) | 四区布局、战斗画面区(四区中的 B 区)演出区结构、敌人呈现(站桩形态)与明细带呈现语义——本文在其上叠加密度 |
|
||||||
| 上游 | [敌人系统](敌人系统.md) | 资产需求下限三类与敌种姿态数据面——数据已锁,本文出终稿;另登记一项随样张一并裁决的事项:敌人层绘制优先级的插入位置 |
|
| 上游 | [敌人系统](敌人系统.md) | 资产需求下限三类与敌种姿态数据面——数据已锁,本文出终稿;另登记一项随样张一并裁决的事项:敌人层绘制优先级的插入位置 |
|
||||||
| 上游 | [art-bible](../../../art/art-bible.md)(现行权威) | 剪影、色彩、图标键契约、各阶段氛围——表现侧约束 |
|
| 上游 | [art-bible](../../../art/art-bible.md)(现行权威) | 剪影、色彩、图标键契约、各阶段氛围——表现侧约束 |
|
||||||
| 上游 | [battle.md](../../ux/battle.md)(现行权威) | 屏级呈现形态与呈现语义 |
|
| 上游 | [battle.md](../../../ux/battle.md)(现行权威) | 屏级呈现形态与呈现语义 |
|
||||||
| 协作 | [音频](../表现与支撑/音频.md) | 坍塌显形动画与音效方向配对登记,将来对位设计(挂点未定) |
|
| 协作 | [音频](../表现与支撑/音频.md) | 坍塌显形动画与音效方向配对登记,将来对位设计(挂点未定) |
|
||||||
|
|
||||||
## P0 最小闭环
|
## P0 最小闭环
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 敌人系统
|
# 敌人系统
|
||||||
|
|
||||||
> 一句话:敌人数据、技能池出招、意图呈现
|
> 一句话:敌人数据、技能池出招、意图呈现
|
||||||
> 状态:已定稿;现行为 v1.8
|
> 状态:已定稿;现行为 v1.9
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -138,6 +138,20 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
|
|||||||
|
|
||||||
举证:**摇定结果 = 可摇集合按权重份额归一的一次抽签;当前可摇集合 = 实例池排除冷却中与触发条件不满足的技能(保底命中时 = 条件满足的全部特殊技)。**连带可判别:把权重当固定百分比、把冷却当只锁高伤技、把蓄力当重击前奏,都是与本规约相悖的旧口径。
|
举证:**摇定结果 = 可摇集合按权重份额归一的一次抽签;当前可摇集合 = 实例池排除冷却中与触发条件不满足的技能(保底命中时 = 条件满足的全部特殊技)。**连带可判别:把权重当固定百分比、把冷却当只锁高伤技、把蓄力当重击前奏,都是与本规约相悖的旧口径。
|
||||||
|
|
||||||
|
### 精英行:现役敌种的强化版,池=继承基础池+附加技
|
||||||
|
|
||||||
|
精英怪是某个现役敌种的强化版本:玩家看到的是同一种怪(同立绘、名字带「精英·」前缀),数值更强、出招多几样。它在敌人表里是独立的一行——自己的 enemy_id、自己的数值、自己的专属池,和基础敌种的行互不覆盖;外显与内部定义因此可以是一对多(一个外观对应基础行与精英行两份定义)。精英身份由行类承载:敌人表行类新增 elite 值。
|
||||||
|
|
||||||
|
| 规则 | 含义 |
|
||||||
|
|---|---|
|
||||||
|
| 独立行 | 精英=敌人表行类为 elite 的一行,enemy_id 独立、不与基础敌种同名;名字前缀「精英·」由该行名字行值承载。数值字段(生命、攻击、护甲两轴、数量)与战斗行同一套定义与取值域 |
|
||||||
|
| 基础敌种引用 | 精英行用基础敌种引用字段指向一个基础敌种的 enemy_id;被指敌种必须在同关战斗行类里存在,指向不存在的敌种或另一条精英行,加载期拒绝 |
|
||||||
|
| 专属池=继承+附加 | 精英行不写自己的池模板,只写附加技清单({skill_id, weight} 数组);它的池模板=基础池+附加技合并。基础池取自同关、战斗行类、该基础敌种深度带最小的那一行的池模板——继承不复制:基础池调参自动传到精英。附加技的 skill_id 与基础池重复,加载期拒绝 |
|
||||||
|
| 合并池过同一纪律 | 池构成纪律(恰一普攻、增益 ≤1、妨害 ≤1、至少一行无条件特殊技、悬空引用致命、权重域)校验的对象是合并后的池;开战快照、实例池、冷却、保底、触发条件语义全部不变——精英实例拿到的就是合并后池的快照 |
|
||||||
|
| 暂不接线 | 精英行落表即合法;开战寻址只按节点类型取战斗或 Boss 行集,精英行在接线前不会被任何节点读到,静置合法、不返回错误。精英遭遇怎么投放到节点,归待办清单「战斗节点遭遇编排方式」条目 |
|
||||||
|
|
||||||
|
举证:**精英池模板 = 基础池条目 ∪ 附加技条目(两者 skill_id 不相交)**;中签率公式不变,可摇权重合计含附加技权重——加附加技会摊薄基础池各技能的中签率,EV 重锚归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)。各精英行的数值与附加技行值读敌人表(`enemy.tres`),本文不登记。
|
||||||
|
|
||||||
### 触发条件:情境技与闩型解锁共用一套门槛
|
### 触发条件:情境技与闩型解锁共用一套门槛
|
||||||
|
|
||||||
技能行可以带一个触发条件:条件不满足的拍,这行技能不进可摇集合——与冷却中的排除同一待遇;条件满足时,按正常权重照摇。它服务两类出招:情境技(自身低血才用的防御、上轮玩家停手才会出的偷袭等)让怪物像在"看情况出招",停手与压血因此有了代价;闩型解锁(半血解锁)让大招只在血量跌破阈值后才可被摇出。两类用例、一套机制——条件只管"现在能不能被摇到",不改权重、不强制出手。
|
技能行可以带一个触发条件:条件不满足的拍,这行技能不进可摇集合——与冷却中的排除同一待遇;条件满足时,按正常权重照摇。它服务两类出招:情境技(自身低血才用的防御、上轮玩家停手才会出的偷袭等)让怪物像在"看情况出招",停手与压血因此有了代价;闩型解锁(半血解锁)让大招只在血量跌破阈值后才可被摇出。两类用例、一套机制——条件只管"现在能不能被摇到",不改权重、不强制出手。
|
||||||
@@ -236,7 +250,8 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
|
|||||||
| 优先级 | 内容 | 后置原因 |
|
| 优先级 | 内容 | 后置原因 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| P1 | 情境条件触发器(低血触发防御、玩家停手时偷袭技等) | 已实装(三 Boss 闩型+两示范投放,见「触发条件」节与「首批落地」段) |
|
| P1 | 情境条件触发器(低血触发防御、玩家停手时偷袭技等) | 已实装(三 Boss 闩型+两示范投放,见「触发条件」节与「首批落地」段) |
|
||||||
| P1 | 个体化变体池(A 型好斗 / B 型守势、精英专属池) | 共识点 A 的 A2 案;登记[待办清单](../../../../待办清单.md) |
|
| P1 | 个体化变体池(同种个体分型:A 型好斗 / B 型守势) | 共识点 A 的 A2 案;排期 Beta,登记[待办清单](../../../../待办清单.md) |
|
||||||
|
| P1 | 精英遭遇接线、精英底座光环与描边变色、精英钥石掉落 | 精英行已落表静置(见「精英行」节);接线归[待办清单](../../../../待办清单.md)「战斗节点遭遇编排方式」条目,视觉二件随怪物设定批,钥石随接线批 |
|
||||||
| P1 | 全局特殊间隔旋钮 | 特殊技背靠背实测仍嫌时的备用闸;登记[待办清单](../../../../待办清单.md) |
|
| P1 | 全局特殊间隔旋钮 | 特殊技背靠背实测仍嫌时的备用闸;登记[待办清单](../../../../待办清单.md) |
|
||||||
| P1 | 新效应词汇(妨害技 + 必中附加分量已实装——实装面 = L2 Boss 卓尔;多段命中经用户拍板退役) | 妨害类型 + rider_mult 字段已落地;登记[待办清单](../../../../待办清单.md)(已解决移除,去向见状态记录) |
|
| P1 | 新效应词汇(妨害技 + 必中附加分量已实装——实装面 = L2 Boss 卓尔;多段命中经用户拍板退役) | 妨害类型 + rider_mult 字段已落地;登记[待办清单](../../../../待办清单.md)(已解决移除,去向见状态记录) |
|
||||||
| P1 | 敌种扩容与投放节奏(含第二关池与投放) | 投放节奏是关卡命脉,归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
| P1 | 敌种扩容与投放节奏(含第二关池与投放) | 投放节奏是关卡命脉,归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
||||||
@@ -253,7 +268,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
|
|||||||
| 参数 | 取值域 | 说明 |
|
| 参数 | 取值域 | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| level_index(关卡序号) | int ≥ 1 | 行集坐标第一维:第几关;每关必有战斗类、深度带 0 的一行(锚行)与至少一行 Boss 类行——加载校验强制;关间台阶的坐标轴,行值投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
| level_index(关卡序号) | int ≥ 1 | 行集坐标第一维:第几关;每关必有战斗类、深度带 0 的一行(锚行)与至少一行 Boss 类行——加载校验强制;关间台阶的坐标轴,行值投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
||||||
| row_kind | {battle, boss} | 行类:battle = 战斗节点配池(非 Boss 的战斗节点一律取此类),boss = 终点行集——Boss 战按终点配置,多终点各配一行(走哪条路决定打谁);开战按节点类型取对应类的行集 |
|
| row_kind | {battle, boss, elite} | 行类:battle = 战斗节点配池(非 Boss 的战斗节点一律取此类),boss = 终点行集——Boss 战按终点配置,多终点各配一行(走哪条路决定打谁);elite = 精英行(见核心规则「精英行」节,接线前不被任何节点读到);开战按节点类型取对应类的行集 |
|
||||||
| depth_band | int ≥ 0 | 深度带 = 节点深度所在的区间(定义见核心规则「行集构成纪律」):配池按带不按点,难度坡随带递增;节点深度落在带与带之间时取首个 ≥ 深度的带键(偏难一侧);越顶带加载校验判为调参事故;带键投放归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
| depth_band | int ≥ 0 | 深度带 = 节点深度所在的区间(定义见核心规则「行集构成纪律」):配池按带不按点,难度坡随带递增;节点深度落在带与带之间时取首个 ≥ 深度的带键(偏难一侧);越顶带加载校验判为调参事故;带键投放归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
||||||
| unit_count | [1, 3] | 遭遇数量区间下界;有上界的行开战时在区间内掷定,教学位节点同样掷骰 |
|
| unit_count | [1, 3] | 遭遇数量区间下界;有上界的行开战时在区间内掷定,教学位节点同样掷骰 |
|
||||||
| unit_count_max | [unit_count, 3],可省略 | 数量区间上界;开战时在区间内掷定本战实际数量;缺省 = 定值 |
|
| unit_count_max | [unit_count, 3],可省略 | 数量区间上界;开战时在区间内掷定本战实际数量;缺省 = 定值 |
|
||||||
@@ -263,7 +278,9 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
|
|||||||
| armor_class(护甲等级) | int [0, 999],缺省 0 | 防守方护甲等级——基础攻击掷点的折扣判定读数,掷点结算归[战斗结算](战斗结算.md);与 armor_type(克制属性轴)两概念禁止混用;行值投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
| armor_class(护甲等级) | int [0, 999],缺省 0 | 防守方护甲等级——基础攻击掷点的折扣判定读数,掷点结算归[战斗结算](战斗结算.md);与 armor_type(克制属性轴)两概念禁止混用;行值投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
|
||||||
| hp | [1, 999] | 单位生命基线(难度修饰前) |
|
| hp | [1, 999] | 单位生命基线(难度修饰前) |
|
||||||
| atk | [0, 999] | 攻击基线 |
|
| atk | [0, 999] | 攻击基线 |
|
||||||
| pool(池模板) | {skill_id, weight} 数组,weight ∈ (0, 9999] | 技能行引用在技能表;池构成纪律与悬空引用加载期拒绝(校验在数据配置跨表通道) |
|
| pool(池模板) | {skill_id, weight} 数组,weight ∈ (0, 9999] | battle / boss 行必填、elite 行禁填;技能行引用在技能表;池构成纪律与悬空引用加载期拒绝(校验在数据配置跨表通道) |
|
||||||
|
| base_ref(基础敌种引用) | enemy_id 字符串 | 仅 elite 行、必填(其余行类禁填);须指向同关 battle 行类存在的敌种,悬空或指向 elite 行加载期拒绝 |
|
||||||
|
| pool_extra(附加技清单) | {skill_id, weight} 数组,weight ∈ (0, 9999],非空 | 仅 elite 行、必填(其余行类禁填);skill_id 与基础池不相交;合并后池过池构成纪律 |
|
||||||
|
|
||||||
技能表(全局单表,技能行主键 skill_id):
|
技能表(全局单表,技能行主键 skill_id):
|
||||||
|
|
||||||
@@ -305,6 +322,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
|
|||||||
- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、行集构成违例(行集内同敌种第二行 / 同带键多行不相邻)均在加载期返回错误并止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。
|
- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、行集构成违例(行集内同敌种第二行 / 同带键多行不相邻)均在加载期返回错误并止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。
|
||||||
- 零随机回放:同一动作与受击序列驱动两个独立实例,存活投影、逐实例摇定轨迹、顺位返回序列逐项相同。
|
- 零随机回放:同一动作与受击序列驱动两个独立实例,存活投影、逐实例摇定轨迹、顺位返回序列逐项相同。
|
||||||
- 表实一致:敌人表、主角表、技能表三张配置表的字段与各自字段定义逐字段一致。
|
- 表实一致:敌人表、主角表、技能表三张配置表的字段与各自字段定义逐字段一致。
|
||||||
|
- 精英行:elite 行的池模板 = 基础池(同关、战斗行类、基础敌种深度带最小行)+附加技清单,开战快照拿到合并后池;基础池改表后精英合并池随之改变;elite 行落表时任何战斗节点与 Boss 节点开战都不读到它;elite 行缺基础敌种引用或附加技清单、基础敌种引用悬空或指向 elite 行、精英 enemy_id 与基础敌种引用同名、附加技与基础池 skill_id 重复、合并池违反池构成纪律、elite 行写自己的池模板、非 elite 行写基础敌种引用或附加技清单——均在加载期返回错误并止动。
|
||||||
|
|
||||||
## 待办
|
## 待办
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 地形变异
|
# 地形变异
|
||||||
|
|
||||||
> 一句话:格子的非雾变异(荆棘丛/藤蔓缠绕/岩浆/烬覆/落石/矿尘)与 Boss 图整图变异(贫矿脉),挖掘中可遭遇的地貌偏离
|
> 一句话:格子的非雾变异(荆棘丛/藤蔓缠绕/岩浆/烬覆/落石/矿尘)与 Boss 图整图变异(贫矿脉),挖掘中可遭遇的地貌偏离
|
||||||
> 状态:已定稿;现行为 v1.3
|
> 状态:已定稿;现行为 v1.4
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
机制口径:
|
机制口径:
|
||||||
|
|
||||||
- 伤害型:挖开变异格(含连锁揭示,chain 通道同口径)在轮末结算逐行兑现扣生命——地形后果同挖雷口径,非奖励、封印格直挖不作废;危险格恒不吃变异(双层叠罚污染逐行归因,首版排除)。
|
- 伤害型:挖开变异格(含连锁揭示,chain 通道同口径)在轮末结算逐行兑现扣生命——地形后果同挖雷口径,非奖励(封印受理只揭示不挖开,不触发变异伤害——挖开封印格路径已删,口径见[排雷玩法](排雷玩法.md));危险格恒不吃变异(双层叠罚污染逐行归因,首版排除)。
|
||||||
- 信息型:已开且显示数字时该格真实数字不呈现(呈现层读取遮蔽;挖掘规划被迫降级为盲区推理)。呈现层读取不回灌规则本体——模拟试玩走查询面、不经遮蔽,读数口径不受影响。
|
- 信息型:已开且显示数字时该格真实数字不呈现(呈现层读取遮蔽;挖掘规划被迫降级为盲区推理)。呈现层读取不回灌规则本体——模拟试玩走查询面、不经遮蔽,读数口径不受影响。
|
||||||
- 直伤量为加法核小整数(effect_value ∈ [1,9],行值 provisional 归难度曲线与Boss);每格携带单类型单 id。
|
- 直伤量为加法核小整数(effect_value ∈ [1,9],行值 provisional 归难度曲线与Boss);每格携带单类型单 id。
|
||||||
- 变异格未开时无预告呈现(遭遇式;视觉标识归表现层升级批)。
|
- 变异格未开时无预告呈现(遭遇式;视觉标识归表现层升级批)。
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 排雷玩法
|
# 排雷玩法
|
||||||
|
|
||||||
> 一句话:挖格、封印、连锁展开等扫雷规则本体
|
> 一句话:挖格、封印、连锁展开等扫雷规则本体
|
||||||
> 状态:已定稿
|
> 状态:已定稿(v2.0)
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -11,13 +11,13 @@
|
|||||||
|
|
||||||
## 系统范围
|
## 系统范围
|
||||||
|
|
||||||
边界这样划:一个动作"碰棋盘"的部分全归这里——合不合法、执行后格子变成什么样、翻开了哪些格、封印印记立在哪;"花多少钱"归行动经济,"兑现成什么战斗效果"归战斗结算,"画成什么样"归 HUD 框架,"格子怎么生出来"归棋盘生成。本系统自己不含任何玩法数值、零随机、也不认界面:同一张板、同一份动作序列,必然得到逐位相同的结果。
|
边界这样划:一个动作"碰棋盘"的部分全归这里——合不合法、执行后格子变成什么样、哪些格被揭示、封印印记立在哪;"花多少钱"归行动经济,"兑现成什么战斗效果"归战斗结算,"画成什么样"归 HUD 框架,"格子怎么生出来"归棋盘生成。本系统自己不含任何玩法数值、零随机、也不认界面:同一张板、同一份动作序列,必然得到逐位相同的结果。
|
||||||
|
|
||||||
负责:
|
负责:
|
||||||
|
|
||||||
| 负责 | 说明 |
|
| 负责 | 说明 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 全部棋盘面规则 | 动作合法性(相邻、开未开、封印位)、连锁展开、数字提示、封印印记的棋盘状态、清图判定(安全格是否全部开完) |
|
| 全部棋盘面规则 | 动作合法性(相邻、开未开、封印位)、连锁展开、数字提示、封印印记的棋盘状态、清图判定(安全格是否全部完成——挖开或封印) |
|
||||||
| 开局初始展开 | 装板事务:结构前提校验、免费展开出生开阔地、小人落位 |
|
| 开局初始展开 | 装板事务:结构前提校验、免费展开出生开阔地、小人落位 |
|
||||||
| 单一结算入口 | 玩家意图只从批次结算入口进,按固定语义序仲裁 |
|
| 单一结算入口 | 玩家意图只从批次结算入口进,按固定语义序仲裁 |
|
||||||
| 三种对外事件 | 挖开格、封印判定、轮次结束——全项目的事实流源头 |
|
| 三种对外事件 | 挖开格、封印判定、轮次结束——全项目的事实流源头 |
|
||||||
@@ -49,15 +49,15 @@
|
|||||||
|
|
||||||
移动不花行动点:点任何已开格,小人沿已探明区一次走到位,"已探明区"包括踩过的危险格残址。点击已开格的唯一含义就是移动——本作没有经典扫雷里"双击数字格一键翻开周围"的 chord(双击快开),每一格的兑现都必须花行动点。
|
移动不花行动点:点任何已开格,小人沿已探明区一次走到位,"已探明区"包括踩过的危险格残址。点击已开格的唯一含义就是移动——本作没有经典扫雷里"双击数字格一键翻开周围"的 chord(双击快开),每一格的兑现都必须花行动点。
|
||||||
|
|
||||||
挖已封印的格是合法动作(2026-09-19 用户拍板):封印印记是一次性承诺、没有撤旗动作,直接挖开就是对承诺的兑现——封印印记随挖掘消失、该封印轮末不再判定;挖开封印格的兑付改判(标中不发 / 安全格零奖励等四情况)归[战斗结算](../战斗循环/战斗结算.md)。
|
封印与挖开同样揭示格子(2026-11-07 用户裁):封印被受理的那一刻,墙瓦片换成地板瓦片、格下身份(危险格还是安全格、安全格的数字)当场可见,封印印记叠在其上——玩家不用等轮末判定就知道封中还是封空。兑付仍然全部发生在轮末判定批,受理当场零兑付、零事件。封印格从此拒绝挖掘:挖已封印的格被拒(拒绝原因独立可辨),"封印后再挖开"这条路径不存在。封印印记没有任何撤下手段——不能被挖开、不能被撤下,随图存续到换图或战斗结束。
|
||||||
|
|
||||||
| 动作 | 合法对象 | 棋盘面拒绝情形 |
|
| 动作 | 合法对象 | 棋盘面拒绝情形 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 挖 | 8 向相邻、未开(有封印照挖) | 不相邻 / 已开过 |
|
| 挖 | 8 向相邻、未开、无封印 | 不相邻 / 已开过 / 已封印 |
|
||||||
| 封印 | 8 向相邻、未开、无封印 | 不相邻 / 已开过 / 已有封印 |
|
| 封印 | 8 向相邻、未开、无封印 | 不相邻 / 已开过 / 已有封印 |
|
||||||
| 移动 | 任意已开格,且能只经已开格连通到达 | 目标未开 / 无连通路径 |
|
| 移动 | 任意已开格,且能只经已开格连通到达 | 目标未开 / 无连通路径 |
|
||||||
|
|
||||||
每个被拒动作都带一个可辨的拒绝原因;原因只能取自一份固定清单,清单外没有别的来源。三个来源互不混淆:棋盘面非法(上表各情形,细因彼此数据可分——"已有封印"和"不相邻"必须是两个可区分的原因)、资源不足(判定权在行动经济)、相位不对(本轮已收尾,不收动作)。玩家看到的文案归[HUD 框架](../表现与支撑/HUD框架.md)。
|
每个被拒动作都带一个可辨的拒绝原因;原因只能取自一份固定清单,清单外没有别的来源。三个来源互不混淆:棋盘面非法(上表各情形,细因彼此数据可分——"已有封印"(封印动作)与"已封印"(挖动作)和"不相邻"必须互可区分)、资源不足(判定权在行动经济)、相位不对(本轮已收尾,不收动作)。玩家看到的文案归[HUD 框架](../表现与支撑/HUD框架.md)。
|
||||||
|
|
||||||
```
|
```
|
||||||
一个意图进来
|
一个意图进来
|
||||||
@@ -73,16 +73,16 @@
|
|||||||
|
|
||||||
每个已开安全格都亮着一个数字,恒等于它周围 8 格里的雷数。这条"数字恒真"是全部推理的地基:数据层从不说谎,呈现层怎么遮掩都不改真值——任何让数字失真的实现都在禁止之列。
|
每个已开安全格都亮着一个数字,恒等于它周围 8 格里的雷数。这条"数字恒真"是全部推理的地基:数据层从不说谎,呈现层怎么遮掩都不改真值——任何让数字失真的实现都在禁止之列。
|
||||||
|
|
||||||
挖开一个数字为 0 的格(周围一圈没有雷)时,它周围未封印的安全格免费连锁全开,一路递推到没有新的 0 格为止——这就是连锁展开,玩家看到的是"坍塌显形":挖穿一层薄壳,整片松动的地面塌陷露出。连锁格只扣首格挖掘按价计的一笔,照常计入清图进度(清图 = 开完全部安全格),格面资源资格也照常——连锁开出的格与单挖的格同权,资源身份归[地图战斗资源](../战斗循环/地图战斗资源.md)、极性兑付归[战斗结算](../战斗循环/战斗结算.md),本系统不区分。
|
挖开一个数字为 0 的格(周围一圈没有雷)时,它周围未封印的安全格免费连锁全开,一路递推到没有新的 0 格为止——这就是连锁展开,玩家看到的是"坍塌显形":挖穿一层薄壳,整片松动的地面塌陷露出。连锁格只扣首格挖掘按价计的一笔,照常计入清图进度(清图 = 全部安全格完成,完成 = 挖开或封印),格面资源资格也照常——连锁开出的格与单挖的格同权,资源身份归[地图战斗资源](../战斗循环/地图战斗资源.md)、极性兑付归[战斗结算](../战斗循环/战斗结算.md),本系统不区分。
|
||||||
|
|
||||||
连锁遇到封印就停:封印格不被链开,也不给更远的格当传播跳板。封印按价计费,正是玩家亲手买下的"链阻断器"——对一片不敢确定的地,提前落一枚封印印记,塌方到它为止。
|
连锁遇到封印就停:封印格不被链开,也不给更远的格当传播跳板。封印按价计费,正是玩家亲手买下的"链阻断器"——对一片不敢确定的地,提前落一枚封印印记,塌方到它为止。
|
||||||
|
|
||||||
清图在每次挖完成后判定;封印、移动都不改已开格,永远不会触发清图。
|
清图在每次挖或封印完成后判定;移动不改格子,永远不会触发清图。
|
||||||
|
|
||||||
| 连锁展开的性质 | 含义 |
|
| 连锁展开的性质 | 含义 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 免费 | 只扣首格按价计的一笔,连锁翻开的格不另收费 |
|
| 免费 | 只扣首格按价计的一笔,连锁翻开的格不另收费 |
|
||||||
| 计入清图进度 | 连锁开的格照常算进"全部安全格开完"的判定 |
|
| 计入清图进度 | 连锁开的格照常算进"全部安全格完成"的判定 |
|
||||||
| 资源资格照常 | 连锁开出的安全格与单挖的安全格同权 |
|
| 资源资格照常 | 连锁开出的安全格与单挖的安全格同权 |
|
||||||
| 遇封印即止 | 封印格不入链、不作传播跳板;封印印记留在原地,轮末照常判定 |
|
| 遇封印即止 | 封印格不入链、不作传播跳板;封印印记留在原地,轮末照常判定 |
|
||||||
|
|
||||||
@@ -134,9 +134,9 @@
|
|||||||
|
|
||||||
### 封印立得住、也带不走:封印印记的生命周期与换图重置
|
### 封印立得住、也带不走:封印印记的生命周期与换图重置
|
||||||
|
|
||||||
封印印记是棋盘状态的一部分,不是背包里的实物:落下的封印印记跨轮保留、随图存续,没有数量上限,也没有任何移除手段(移除动作已退役——封印印记只能被挖开,不能被撤下)。每次轮次结束(行动点耗尽、玩家停手或清图时),本系统对当时在场的每一处封印如实上报一条判定——封印底下是雷记标中(玩家看到危险格被控制、化险为利),不是雷记标空;封印一直落在雷上,就每轮如实重复上报标中,去重是[战斗结算](../战斗循环/战斗结算.md)的事,本系统只报事实。被直接挖开的封印随挖掘消失、不在轮末在场基线里,自然不报判定;封印本身不发事件,界面反馈走调用返回值。
|
封印印记是棋盘状态的一部分,不是背包里的实物:落下的封印印记跨轮保留、随图存续,没有数量上限,也没有任何撤下手段——封印格拒绝挖掘(见「挖、封印、移动」节),印记只能随图更替消失。每次轮次结束(行动点耗尽、玩家停手或清图时),本系统对当时在场的每一处封印如实上报一条判定——底下是雷记标中(玩家看到危险格被控制、化险为利),不是雷记标空;封印一直落在雷上,就每轮如实重复上报标中,去重是[战斗结算](../战斗循环/战斗结算.md)的事,本系统只报事实。封印本身不发事件,界面反馈走调用返回值。
|
||||||
|
|
||||||
标空(封错格)的纠错路径只有一条:把它挖开(兑付改判四情况见[战斗结算](../战斗循环/战斗结算.md));不挖也可以留着它当链阻断器、当"别走这边"的地图注记。封印印记不参与清图判定,但带封印的格没挖开就照常挡着——全图封印一格不挖,永远清不了图。
|
标空(封错格)没有纠错路径:印记不撤不消、随图存续——封错的格从此是一块标了价的地图注记:它算完成探索(计入清图进度),但格面资源不兑付,轮末标空的负向兑付(归[战斗结算](../战斗循环/战斗结算.md))就是封错的代价;它同时仍是链阻断器和不可通行的地形。清图判定口径(2026-11-07 用户裁):清图 = 全部安全格完成,完成 = 挖开或封印——封印可以完成清图,全图不可能被"封错一格"卡死。
|
||||||
|
|
||||||
标空就是标错,玩家读到的是控制失败——惩罚兑付为该安全格格面资源的负向(极性矩阵,归[地图战斗资源](../战斗循环/地图战斗资源.md)与[战斗结算](../战斗循环/战斗结算.md)),本系统只报"标空"事实。
|
标空就是标错,玩家读到的是控制失败——惩罚兑付为该安全格格面资源的负向(极性矩阵,归[地图战斗资源](../战斗循环/地图战斗资源.md)与[战斗结算](../战斗循环/战斗结算.md)),本系统只报"标空"事实。
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
| 随战斗结束消失 | 整板退役 | 与板一同清空 |
|
| 随战斗结束消失 | 整板退役 | 与板一同清空 |
|
||||||
|
|
||||||
```
|
```
|
||||||
封印(按价计费,界面即时反馈)→ 封印印记立在未开格上,跨轮保留
|
封印(按价计费,界面即时反馈)→ 封印印记立在已揭示格(地板)上,跨轮保留
|
||||||
每次轮次结束 → 逐封印判定,如实上报(标中 / 标空)
|
每次轮次结束 → 逐封印判定,如实上报(标中 / 标空)
|
||||||
换图(清图或刷新)或战斗结束 → 封印印记随旧图全量消失
|
换图(清图或刷新)或战斗结束 → 封印印记随旧图全量消失
|
||||||
```
|
```
|
||||||
@@ -159,11 +159,11 @@
|
|||||||
|
|
||||||
### 一帧一个意图、对外只有三种事件:批次仲裁与事件面
|
### 一帧一个意图、对外只有三种事件:批次仲裁与事件面
|
||||||
|
|
||||||
玩家每帧只提交一个意图,全部意图经同一个批次结算入口进入本系统——这是唯一的结算入口,保证任何情况下只有一种结算顺序。批次是整体事务:先按固定语义序重排(能清图的挖最优先、停手次之、其余殿后,同类内按提交顺序),再逐个执行;轮次结束条件第一次成立处定出赢家,其后的意图全部丢弃。丢弃不等于被拒:拒绝是本来就不合法,丢弃是来不及了——零棋盘效果、零扣费、零事件。单意图帧下正常玩不出批次竞争,这套仲裁是防御性兜底。
|
玩家每帧只提交一个意图,全部意图经同一个批次结算入口进入本系统——这是唯一的结算入口,保证任何情况下只有一种结算顺序。批次是整体事务:先按固定语义序重排(能清图的挖或封最优先、停手次之、其余殿后,同类内按提交顺序),再逐个执行;轮次结束条件第一次成立处定出赢家,其后的意图全部丢弃。丢弃不等于被拒:拒绝是本来就不合法,丢弃是来不及了——零棋盘效果、零扣费、零事件。单意图帧下正常玩不出批次竞争,这套仲裁是防御性兜底。
|
||||||
|
|
||||||
| 批次语义序 | 类别 | 说明 |
|
| 批次语义序 | 类别 | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 最先 | 能清图的挖 | 执行后图即全开的挖——防止"耗尽优先"把清图高光结算成最差结局 |
|
| 最先 | 能清图的挖或封 | 执行后图即全开的挖或封——防止"耗尽优先"把清图高光结算成最差结局 |
|
||||||
| 次之 | 停手 | 玩家主动收轮 |
|
| 次之 | 停手 | 玩家主动收轮 |
|
||||||
| 其余 | 普通挖、封印、移动 | 同类内按提交顺序 |
|
| 其余 | 普通挖、封印、移动 | 同类内按提交顺序 |
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
一批意图到达
|
一批意图到达
|
||||||
→ 按语义序重排(能清图的挖 > 停手 > 其余,同类按提交序)
|
→ 按语义序重排(能清图的挖或封 > 停手 > 其余,同类按提交序)
|
||||||
→ 逐个执行,轮次结束第一次成立处定赢家,其后意图丢弃
|
→ 逐个执行,轮次结束第一次成立处定赢家,其后意图丢弃
|
||||||
→ 收轮:先把封印判定逐条报完,再报轮次结束
|
→ 收轮:先把封印判定逐条报完,再报轮次结束
|
||||||
```
|
```
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
| 方向 | 系统 | 接口要点 |
|
| 方向 | 系统 | 接口要点 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 上游 | [棋盘生成](棋盘生成.md) | 棋盘产物的消费方;装板时校验结构前提(出生区无雷、数字恒真等),违例拒绝装板 |
|
| 上游 | [棋盘生成](棋盘生成.md) | 棋盘产物的消费方;装板时校验结构前提(出生区无雷、数字恒真等),违例拒绝装板 |
|
||||||
| 上游 | [行动经济](行动经济.md) | 唯一扣费入口:本系统判棋盘面后请行动经济扣费,绝不自行扣减;挖成后上报连锁规模与清图事实;停手意图经批次入口转交 |
|
| 上游 | [行动经济](行动经济.md) | 唯一扣费入口:本系统判棋盘面后请行动经济扣费,绝不自行扣减;挖成或封成后上报连锁规模与清图事实;停手意图经批次入口转交 |
|
||||||
| 下游 | [战斗结算](../战斗循环/战斗结算.md) | 三事件的订阅方、轮末兑现方;换新图指令由它回发 |
|
| 下游 | [战斗结算](../战斗循环/战斗结算.md) | 三事件的订阅方、轮末兑现方;换新图指令由它回发 |
|
||||||
| 下游 | [地图战斗资源](../战斗循环/地图战斗资源.md) | 本系统只上报"这格有无格面资源资格"的事实;资源内容与极性兑付不经本系统 |
|
| 下游 | [地图战斗资源](../战斗循环/地图战斗资源.md) | 本系统只上报"这格有无格面资源资格"的事实;资源内容与极性兑付不经本系统 |
|
||||||
| 下游 | [HUD 框架](../表现与支撑/HUD框架.md) | 呈现义务归 HUD 框架 |
|
| 下游 | [HUD 框架](../表现与支撑/HUD框架.md) | 呈现义务归 HUD 框架 |
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
最小闭环只保留跑通"装板—挖—收轮—兑现—换图"必需的规则:
|
最小闭环只保留跑通"装板—挖—收轮—兑现—换图"必需的规则:
|
||||||
|
|
||||||
1. 战斗开始装上新图:校验结构前提,违例拒绝;初始展开免费翻开出生开阔地,小人落位。
|
1. 战斗开始装上新图:校验结构前提,违例拒绝;初始展开免费翻开出生开阔地,小人落位。
|
||||||
2. 玩家每帧提交一个意图:挖(判棋盘面,请行动经济按价扣费,开格加连锁并逐格上报;有封印格照挖、封印印记随挖掘消失)、封印(按价计费,封印印记入棋盘,零事件)、移动(免费,已开区一次走到位)。
|
2. 玩家每帧提交一个意图:挖(判棋盘面,请行动经济按价扣费,开格加连锁并逐格上报;封印格拒绝挖掘)、封印(按价计费,受理即揭示——墙变地板、身份可见,印记立其上;零事件)、移动(免费,已开区一次走到位)。
|
||||||
3. 被拒动作带可辨原因、状态不变;批次内轮次结束首次成立处定赢家,其后意图丢弃。
|
3. 被拒动作带可辨原因、状态不变;批次内轮次结束首次成立处定赢家,其后意图丢弃。
|
||||||
4. 收轮:先报完在场封印的逐条判定,再报轮次结束(停手路径由行动经济直发)。
|
4. 收轮:先报完在场封印的逐条判定,再报轮次结束(停手路径由行动经济直发)。
|
||||||
5. 战斗结算订阅事件流逐行兑现;清图或刷新换图时按它回发的指令装新图,旧板封印印记全量失效,回到第 1 步。
|
5. 战斗结算订阅事件流逐行兑现;清图或刷新换图时按它回发的指令装新图,旧板封印印记全量失效,回到第 1 步。
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
|
|
||||||
## 调参表
|
## 调参表
|
||||||
|
|
||||||
本系统无自有参数:价目与每轮点数见[行动经济](行动经济.md)的调参表,棋盘形态见[棋盘生成](棋盘生成.md)。连锁免费、移动免费、无 chord、批次语义序、三种事件封闭都是冻结设计而非参数——改动走本文修订流程,不走调参。
|
本系统无自有参数:价目与每轮点数见[行动经济](行动经济.md)的调参表,棋盘形态见[棋盘生成](棋盘生成.md)。连锁免费、移动免费、无 chord、封印受理即揭示、清图口径(挖开或封印算完成)、批次语义序、三种事件封闭都是冻结设计而非参数——改动走本文修订流程,不走调参。
|
||||||
|
|
||||||
## 验收标准
|
## 验收标准
|
||||||
|
|
||||||
@@ -228,7 +228,8 @@
|
|||||||
- 数字恒真:任意已开安全格的数字恒等于其 8 向相邻雷数;出生区无雷、数字恒真、初始展开不吞全图三条结构前提任一不满足时,装板被拒绝。
|
- 数字恒真:任意已开安全格的数字恒等于其 8 向相邻雷数;出生区无雷、数字恒真、初始展开不吞全图三条结构前提任一不满足时,装板被拒绝。
|
||||||
- 初始展开恰等:装板后翻开的格集合恰为"出生 3×3 加连通开阔地"——不止 3×3,也不外扩一圈;全程免费、恒无格面资源(封锁格)、计入清图进度;跨轮不重放。
|
- 初始展开恰等:装板后翻开的格集合恰为"出生 3×3 加连通开阔地"——不止 3×3,也不外扩一圈;全程免费、恒无格面资源(封锁格)、计入清图进度;跨轮不重放。
|
||||||
- 连锁免费且遇封印即止:一次触发连锁翻开任意多格,扣费恒为首格按价计的一笔;封印格不被链开、不作传播跳板;连锁格计入清图进度、资源资格照常。
|
- 连锁免费且遇封印即止:一次触发连锁翻开任意多格,扣费恒为首格按价计的一笔;封印格不被链开、不作传播跳板;连锁格计入清图进度、资源资格照常。
|
||||||
- 挖封印格放行:有封印格直接挖开被受理——封印印记随挖掘消失、该封印轮末不判;重复封印仍被"已有封印"拒绝;兑付改判四情况(标中不发 / 安全格零奖励)归战斗结算。
|
- 封印受理即揭示、挖封印格被拒:封印被受理后该格进入已揭示态——身份(危险/安全与数字)当场可查、封印印记叠在其上、受理当场零兑付零事件;挖已封印的格被拒(拒绝原因独立可辨、零副作用);重复封印仍被"已有封印"拒绝。
|
||||||
|
- 清图口径:清图 = 全部安全格完成——挖开或封印都算完成;封到安全格计入清图进度,封印可以完成清图。
|
||||||
- 已引爆危险格可通行:挖雷后轮次不结束,小人可站、可经已开区穿行续挖;危险格不计清图、不可再挖再封印。
|
- 已引爆危险格可通行:挖雷后轮次不结束,小人可站、可经已开区穿行续挖;危险格不计清图、不可再挖再封印。
|
||||||
- 移动合法且预览同源:目标未开或无已开区连通路径时拒绝;路径预览与实际执行逐格相同;移动免费、零事件。
|
- 移动合法且预览同源:目标未开或无已开区连通路径时拒绝;路径预览与实际执行逐格相同;移动免费、零事件。
|
||||||
- 批次仲裁与到达序无关:同一批意图按任意顺序提交,结束路径与结算结果一致;赢家定出后其余意图丢弃——零棋盘效果、零扣费、零事件,且丢弃区别于拒绝。
|
- 批次仲裁与到达序无关:同一批意图按任意顺序提交,结束路径与结算结果一致;赢家定出后其余意图丢弃——零棋盘效果、零扣费、零事件,且丢弃区别于拒绝。
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 行动经济
|
# 行动经济
|
||||||
|
|
||||||
> 一句话:每轮行动点怎么花、停手与刷新的代价
|
> 一句话:每轮行动点怎么花、停手与刷新的代价
|
||||||
> 状态:已定稿;现行为 v1.5
|
> 状态:已定稿;现行为 v1.6
|
||||||
|
|
||||||
## 设计目的
|
## 设计目的
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
| 动作 | 花费 | 说明 |
|
| 动作 | 花费 | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 挖开格 | 标准价(见 action_economy.tres) | 只能挖小人 8 向相邻的格子;若触发连锁展开(flood fill 式整片翻开),连锁翻开的部分免费,且计入清图进度 |
|
| 挖开格 | 标准价(见 action_economy.tres) | 只能挖小人 8 向相邻的格子;若触发连锁展开(flood fill 式整片翻开),连锁翻开的部分免费,且计入清图进度 |
|
||||||
| 封印 | 标准价(见 action_economy.tres) | 同样限相邻格。封印印记只是棋盘上的标记,不是背包里的实物,想用多少有多少——它的稀缺性完全由"要花一次标准价行动点"承载。封印印记是一次性承诺:落子就没有移除动作,纠错 = 直接挖开该格 |
|
| 封印 | 标准价(见 action_economy.tres) | 同样限相邻格。封印印记只是棋盘上的标记,不是背包里的实物,想用多少有多少——它的稀缺性完全由"要花一次标准价行动点"承载。封印印记是一次性承诺:落子就没有移除动作;封印受理即揭示、封印格拒绝挖掘(口径见[排雷玩法](排雷玩法.md))——封错的代价 = 轮末标空负向兑付,纠错路径不存在 |
|
||||||
|
|
||||||
不花钱的有两件事:移动小人(点已翻开的格子走过去,仅限已探明区域)和连锁展开。这两项免费是冻结设计,服务"边缘探索不心疼"的氛围,不是经济杠杆。
|
不花钱的有两件事:移动小人(点已翻开的格子走过去,仅限已探明区域)和连锁展开。这两项免费是冻结设计,服务"边缘探索不心疼"的氛围,不是经济杠杆。
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ HUD框架把各玩法系统产生的事实变成玩家看得见、点得动、
|
|||||||
|
|
||||||
## 系统范围
|
## 系统范围
|
||||||
|
|
||||||
边界这样划:本系统管"怎么呈现、怎么翻译输入、弹层怎么排队"。一个动作合不合法、结果算什么意思,归排雷玩法、行动经济、战斗结算等上游裁定;画面具体长什么样、组件落在哪一像素,屏级权威按屏分治——战斗屏是 [battle.md](../../ux/battle.md)、关卡画面是 [level-map.md](../../ux/level-map.md)——本文只锁系统级契约。
|
边界这样划:本系统管"怎么呈现、怎么翻译输入、弹层怎么排队"。一个动作合不合法、结果算什么意思,归排雷玩法、行动经济、战斗结算等上游裁定;画面具体长什么样、组件落在哪一像素,屏级权威按屏分治——战斗屏是 [battle.md](../../../ux/battle.md)、关卡画面是 [level-map.md](../../../ux/level-map.md)——本文只锁系统级契约。
|
||||||
|
|
||||||
负责:
|
负责:
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ HUD框架把各玩法系统产生的事实变成玩家看得见、点得动、
|
|||||||
|---|---|
|
|---|---|
|
||||||
| 任何玩法状态与玩法数值 | 各玩法系统;数值表本体归[数据配置](数据配置.md) |
|
| 任何玩法状态与玩法数值 | 各玩法系统;数值表本体归[数据配置](数据配置.md) |
|
||||||
| 合法性判定与机制语义裁定 | [排雷玩法](../排雷循环/排雷玩法.md)、[行动经济](../排雷循环/行动经济.md)、[战斗结算](../战斗循环/战斗结算.md) |
|
| 合法性判定与机制语义裁定 | [排雷玩法](../排雷循环/排雷玩法.md)、[行动经济](../排雷循环/行动经济.md)、[战斗结算](../战斗循环/战斗结算.md) |
|
||||||
| 屏级布局与动画时长的像素级裁决 | [battle.md](../../ux/battle.md)(战斗屏)与 [level-map.md](../../ux/level-map.md)(关卡画面) |
|
| 屏级布局与动画时长的像素级裁决 | [battle.md](../../../ux/battle.md)(战斗屏)与 [level-map.md](../../../ux/level-map.md)(关卡画面) |
|
||||||
| 美术终稿与动画密度 | [art-bible](../../../art/art-bible.md)与[战斗表现](../战斗循环/战斗表现.md) |
|
| 美术终稿与动画密度 | [art-bible](../../../art/art-bible.md)与[战斗表现](../战斗循环/战斗表现.md) |
|
||||||
| 音频、教学内容、本地化文本生产 | [音频](音频.md)、[教学引导](教学引导.md)、[设置与本地化](设置与本地化.md) |
|
| 音频、教学内容、本地化文本生产 | [音频](音频.md)、[教学引导](教学引导.md)、[设置与本地化](设置与本地化.md) |
|
||||||
| 任何随机消费 | 无——呈现层零随机 |
|
| 任何随机消费 | 无——呈现层零随机 |
|
||||||
@@ -59,11 +59,11 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| B 战斗画面 | 全宽,高读布局表 `stage_h`(背景三关变体+连续地面层高另读 `ground_h`) | 三关舞台背景+连续地面层、主角站桩立绘、敌人站桩立绘 ×1–3(**全站桩形态,2026-09-20 用户拍板:无框立绘+底座、状态小图标挂血条下,英雄卡/敌人卡退役**)、轮次阶段指示、结算明细带 |
|
| B 战斗画面 | 全宽,高读布局表 `stage_h`(背景三关变体+连续地面层高另读 `ground_h`) | 三关舞台背景+连续地面层、主角站桩立绘、敌人站桩立绘 ×1–3(**全站桩形态,2026-09-20 用户拍板:无框立绘+底座、状态小图标挂血条下,英雄卡/敌人卡退役**)、轮次阶段指示、结算明细带 |
|
||||||
| C 角色信息 | 左下,宽读 `info_panel_w`,高 = 基准屏高 − B 区高 | 生命 / 攻击 / 储备数据框、状态效果槽、小人立绘 |
|
| C 角色信息 | 左下,宽读 `info_panel_w`,高 = 基准屏高 − B 区高 | 生命 / 攻击 / 储备数据框、状态效果槽、小人立绘 |
|
||||||
| D 扫雷图 | 中下,宽 = 基准屏宽 − C 区宽 − 列间距,高同 C 区 | 行动点条与按钮组、棋盘本体、toast 槽 |
|
| D 扫雷图 | 中下,宽 = 基准屏宽 − C 区宽 − 列间距,高同 C 区(2026-11-07 顶栏搬两侧:D 区全高归棋盘) | 左/右行动资源侧栏、棋盘本体、toast 槽(棋盘底常驻操作提示条退役) |
|
||||||
|
|
||||||
分区几何的唯一事实源 = `game/data/tables/battle_layout.tres`(经 `ConfigDb.presentation.battle_layout` 读取);分区尺寸与组件落位的像素级裁决归 [battle.md](../../ux/battle.md),两份文档只写结构关系、不复写数值。三区结构与双舞台常驻是结构冻结项,修订走文档修订而非调参。节点链进度不在战斗屏呈现——它由关卡画面(选路覆盖层常驻形态)的节点态承载,见[关卡节点地图](../冒险循环/关卡节点地图.md)。
|
分区几何的唯一事实源 = `game/data/tables/battle_layout.tres`(经 `ConfigDb.presentation.battle_layout` 读取);分区尺寸与组件落位的像素级裁决归 [battle.md](../../../ux/battle.md),两份文档只写结构关系、不复写数值。三区结构与双舞台常驻是结构冻结项,修订走文档修订而非调参。节点链进度不在战斗屏呈现——它由关卡画面(选路覆盖层常驻形态)的节点态承载,见[关卡节点地图](../冒险循环/关卡节点地图.md)。
|
||||||
|
|
||||||
**结论**:棋盘格边长由 [battle.md](../../ux/battle.md)「棋盘格尺寸公式」按棋盘区实测面积与板型算出;本文只判"塞不塞得进",不复制算式与算例。**分辨率档位**:两档=1280×800 基准档(本表全部定值的口径)+1920×1080 档=**全局等比**(stretch canvas_items+aspect keep——16:10 设计在 16:9 窗口为等比 1.35×+左右黑边各 ~96px);本节与各屏定值一律按 1280 基准档书写,1920 档由引擎等比承载、零重排。
|
**结论**:棋盘格边长由 [battle.md](../../../ux/battle.md)「棋盘格尺寸公式」按棋盘区实测面积与板型算出;本文只判"塞不塞得进",不复制算式与算例。**分辨率档位**:两档=1280×800 基准档(本表全部定值的口径)+1920×1080 档=**全局等比**(stretch canvas_items+aspect keep——16:10 设计在 16:9 窗口为等比 1.35×+左右黑边各 ~96px);本节与各屏定值一律按 1280 基准档书写,1920 档由引擎等比承载、零重排。
|
||||||
|
|
||||||
```
|
```
|
||||||
装板可行性(网格实高 ≤ 棋盘区可用高):
|
装板可行性(网格实高 ≤ 棋盘区可用高):
|
||||||
@@ -74,9 +74,9 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
| 变量 | 含义 | 现行值 |
|
| 变量 | 含义 | 现行值 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| N | 棋盘边长格数 | 读[棋盘生成](../排雷循环/棋盘生成.md)(现行四档;事实源 board_gen.tres) |
|
| N | 棋盘边长格数 | 读[棋盘生成](../排雷循环/棋盘生成.md)(现行四档;事实源 board_gen.tres) |
|
||||||
| 棋盘区宽 / 高 | 扫雷图区基准尺寸 | 由 D 区尺寸扣行动点条高(读 `ap_bar_h`)得出,本表不复制现算值 |
|
| 棋盘区宽 / 高 | 扫雷图区基准尺寸 | 高 = D 区全高(不再扣 AP 条);宽按 battle.md 格尺寸公式扣 `side_rail_w` 侧栏,本表不复制现算值 |
|
||||||
|
|
||||||
装板可行性由上面的不等式保证;格边长的可读下限见 [battle.md](../../ux/battle.md),算例由样张渲染脚本按布局表现算、不入文档。棋盘数字直接显示排雷玩法给的真值——呈现层禁止自己算数字,这是"数据层从不说谎"在呈现侧的镜像。
|
装板可行性由上面的不等式保证;格边长的可读下限见 [battle.md](../../../ux/battle.md),算例由样张渲染脚本按布局表现算、不入文档。棋盘数字直接显示排雷玩法给的真值——呈现层禁止自己算数字,这是"数据层从不说谎"在呈现侧的镜像。
|
||||||
|
|
||||||
### 提示与弹层:轻提示随起随消、重弹层排队进出
|
### 提示与弹层:轻提示随起随消、重弹层排队进出
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
| toast | 非模态 | 自动消退 2.5 秒,不打断挖掘 |
|
| toast | 非模态 | 自动消退 2.5 秒,不打断挖掘 |
|
||||||
| 图例面板 / 明细回看 / 胜负终局 | 模态 | 同一张登记序栈:统一入栈出栈、后开置顶、关闭逐层恢复 |
|
| 图例面板 / 明细回看 / 胜负终局 | 模态 | 同一张登记序栈:统一入栈出栈、后开置顶、关闭逐层恢复 |
|
||||||
|
|
||||||
两条纪律横跨两族。其一,"第一次遇到"类提示(本作没有双击快开、挖不相邻格要先走近)走 toast,每场冒险至多弹一次。其二,拒绝反馈不属于一次性族——每次被拒都要可感知,且图标与文案双通道冗余(不靠颜色单独承载);棋盘面拒绝(动作不合棋盘规则,目标格边框闪)与资源面拒绝(行动点或储备不足,数字脉冲)必须可区分。图例面板恒可随时打开回看,不设解锁门。
|
三条纪律横跨两族。其一,"第一次遇到"类提示(本作没有双击快开、挖不相邻格要先走近)走 toast,每场冒险至多弹一次。其二,拒绝反馈不属于一次性族——每次被拒都要可感知,且图标与文案双通道冗余(不靠颜色单独承载);棋盘面拒绝(动作不合棋盘规则,目标格边框闪)与资源面拒绝(行动点或储备不足,数字脉冲)必须可区分。图例面板恒可随时打开回看,不设解锁门。其三,**确认弹窗的按钮位次定值**:推进操作的钮在左、维持现状的钮(取消/留下/否)在右,三钮形态的次推进钮居中;全项目确认弹窗共用同一件、同一序,四处消费方(删档确认/营地大门有断点的三出口/营地大门无断点是否开局/篝火离场)皆然。**位次不随文案变**,语义由文案承担。
|
||||||
|
|
||||||
### 呈现层订阅纪律:界面不自持状态、订阅面只留两条线
|
### 呈现层订阅纪律:界面不自持状态、订阅面只留两条线
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
|
|
||||||
### 营地:可点击场景图
|
### 营地:可点击场景图
|
||||||
|
|
||||||
营地形态**已换代为一张可点击的场景图 + 七物件点选**(现行权威=[camp](../../ux/camp.md));全部程序占位视觉(占位纪律延续,2026-10-11 用户令),**视觉与布局终稿归 HUD 营地视觉批**(未立项)。结构现行事实源 = [天赋树](../跨局循环/天赋树.md)「营地=树:统一模型」节。
|
营地形态**已换代为一张可点击的场景图 + 七物件点选**(现行权威=[camp](../../../ux/camp.md));全部程序占位视觉(占位纪律延续,2026-10-11 用户令),**视觉与布局终稿归 HUD 营地视觉批**(未立项)。结构现行事实源 = [天赋树](../跨局循环/天赋树.md)「营地=树:统一模型」节。
|
||||||
|
|
||||||
### 可访问性基线:看得清、不闪、纯鼠标玩得通
|
### 可访问性基线:看得清、不闪、纯鼠标玩得通
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
|---|---|
|
|---|---|
|
||||||
| 对比度 | 全部数字对格底 ≥4.5:1 |
|
| 对比度 | 全部数字对格底 ≥4.5:1 |
|
||||||
| 色弱安全 | 无信息仅靠色相承载;格态在灰度截图下可逐格分类 |
|
| 色弱安全 | 无信息仅靠色相承载;格态在灰度截图下可逐格分类 |
|
||||||
| 字号下限 | 棋盘数字 ≥18px、明细正文 ≥14px、tooltip ≥13px(1280×800 基座) |
|
| 字号下限 | 棋盘浮空数字字高 21px 固定、明细正文 ≥14px、tooltip ≥13px(1280×800 基座) |
|
||||||
| 闪烁 | 无每秒超过三次的闪烁 |
|
| 闪烁 | 无每秒超过三次的闪烁 |
|
||||||
| 减动效 | 提供全部动画时长减半或跳终态的开关;结算逐行兑现是信息载体——可加速、不可整体跳过 |
|
| 减动效 | 提供全部动画时长减半或跳终态的开关;结算逐行兑现是信息载体——可加速、不可整体跳过 |
|
||||||
| 输入 | 全部操作纯鼠标可完成 |
|
| 输入 | 全部操作纯鼠标可完成 |
|
||||||
@@ -212,7 +212,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
| [排雷玩法](../排雷循环/排雷玩法.md) | 已开 / 未开格态一眼可辨;悬停预承诺与可挖域常驻指示;移动路径预览即合法性指示;每次拒绝可感知且棋盘面细因可区分;停手被改判可感知 |
|
| [排雷玩法](../排雷循环/排雷玩法.md) | 已开 / 未开格态一眼可辨;悬停预承诺与可挖域常驻指示;移动路径预览即合法性指示;每次拒绝可感知且棋盘面细因可区分;停手被改判可感知 |
|
||||||
| [行动经济](../排雷循环/行动经济.md) | 行动点与储备常显;储备清零反馈;棋盘面与资源面拒绝可区分;刷新入口与代价可读 |
|
| [行动经济](../排雷循环/行动经济.md) | 行动点与储备常显;储备清零反馈;棋盘面与资源面拒绝可区分;刷新入口与代价可读 |
|
||||||
| [战斗结算](../战斗循环/战斗结算.md) | 未生效类明细行(奖励未生效)的呈现;高光行强调 |
|
| [战斗结算](../战斗循环/战斗结算.md) | 未生效类明细行(奖励未生效)的呈现;高光行强调 |
|
||||||
| [关卡节点地图](../冒险循环/关卡节点地图.md) | 节点链进度呈现(关卡画面选路覆盖层节点态承载:暗金已过、金当前、候选下一跳通道亮金、Boss 紫赤描边);选路覆盖层只读呈现(零自动推进停点语义)——屏级 spec:[level-map](../../ux/level-map.md) |
|
| [关卡节点地图](../冒险循环/关卡节点地图.md) | 节点链进度呈现(关卡画面选路覆盖层节点态承载:暗金已过、金当前、候选下一跳通道亮金、Boss 紫赤描边);选路覆盖层只读呈现(零自动推进停点语义)——屏级 spec:[level-map](../../../ux/level-map.md) |
|
||||||
| [敌人系统](../战斗循环/敌人系统.md) | 意图线索映射成文且全局恒定;单位顺位与血条可读;敌方共享层数各卡同值 |
|
| [敌人系统](../战斗循环/敌人系统.md) | 意图线索映射成文且全局恒定;单位顺位与血条可读;敌方共享层数各卡同值 |
|
||||||
| [增益状态](../战斗循环/增益状态.md) | 状态栏常显;无状态时整排槽隐藏;有利 / 有害极性呈现不看数值符号 |
|
| [增益状态](../战斗循环/增益状态.md) | 状态栏常显;无状态时整排槽隐藏;有利 / 有害极性呈现不看数值符号 |
|
||||||
| [地图战斗资源](../战斗循环/地图战斗资源.md) | 已开格的奖励身份常读;未开格类型微光(英雄周围 8 格内的未开格显示资源类型——概念定义见本篇「未开格类型微光」节) |
|
| [地图战斗资源](../战斗循环/地图战斗资源.md) | 已开格的奖励身份常读;未开格类型微光(英雄周围 8 格内的未开格显示资源类型——概念定义见本篇「未开格类型微光」节) |
|
||||||
@@ -236,7 +236,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
| P1 | 远格点击自动"先移动再挖"复合意图 | 移动免费高频,两击摩擦先经实测验证再裁 |
|
| P1 | 远格点击自动"先移动再挖"复合意图 | 移动免费高频,两击摩擦先经实测验证再裁 |
|
||||||
| P1 | Gamepad 焦点序 | 纯鼠标已覆盖 MVP 全部操作 |
|
| P1 | Gamepad 焦点序 | 纯鼠标已覆盖 MVP 全部操作 |
|
||||||
| P1 | 可访问性正式分层(文本缩放 / 色盲模式 / 按键重映射) | 归[设置与本地化](设置与本地化.md)设置项全集裁决(2026-09-27 拍板不另立专项文档) |
|
| P1 | 可访问性正式分层(文本缩放 / 色盲模式 / 按键重映射) | 归[设置与本地化](设置与本地化.md)设置项全集裁决(2026-09-27 拍板不另立专项文档) |
|
||||||
| P1 | 相邻域屏(节点奖励 / 关卡结算)完整屏形态 | 归后续 UX 文档(关卡结算屏 spec 已建 [level-clear](../../ux/level-clear.md);节点奖励屏 spec 已在役:[node-reward](../../ux/node-reward.md) v2.5 令牌池口径);MVP 以覆盖层反馈承载 |
|
| P1 | 相邻域屏(节点奖励 / 关卡结算)完整屏形态 | 归后续 UX 文档(关卡结算屏 spec 已建 [level-clear](../../../ux/level-clear.md);节点奖励屏 spec 已在役:[node-reward](../../../ux/node-reward.md) v2.5 令牌池口径);MVP 以覆盖层反馈承载 |
|
||||||
| P2 | 提示一次性作用域升级为存档级"一生一次" | 归[存档序列化](存档序列化.md)与[元进度](../跨局循环/元进度.md)后重议 |
|
| P2 | 提示一次性作用域升级为存档级"一生一次" | 归[存档序列化](存档序列化.md)与[元进度](../跨局循环/元进度.md)后重议 |
|
||||||
| P2 | 调试面板退役 | 正式侧归元进度;诊断按钮保留为调试设施 |
|
| P2 | 调试面板退役 | 正式侧归元进度;诊断按钮保留为调试设施 |
|
||||||
| P2 | 探测类秘宝的显影呈现面 | 接口归[秘宝](../跨局循环/秘宝.md)定稿批 |
|
| P2 | 探测类秘宝的显影呈现面 | 接口归[秘宝](../跨局循环/秘宝.md)定稿批 |
|
||||||
@@ -244,7 +244,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
|||||||
|
|
||||||
## 调参表
|
## 调参表
|
||||||
|
|
||||||
本系统的参数全部是呈现节奏与可读性常量,不是玩法数值——玩法数值一律归[数据配置](数据配置.md)的表,与本表无关。修订本文常量走文档修订流程。**本表常量无数据表承载,为文档面唯一事实源;入驻 .tres 时本列改指路。** 布局几何(B 区高 / B 区连续地面层高 / C 区宽 / AP 条高 / 明细带两态高)已入驻 `game/data/tables/battle_layout.tres`,不在本表重复。
|
本系统的参数全部是呈现节奏与可读性常量,不是玩法数值——玩法数值一律归[数据配置](数据配置.md)的表,与本表无关。修订本文常量走文档修订流程。**本表常量无数据表承载,为文档面唯一事实源;入驻 .tres 时本列改指路。** 布局几何(B 区高 / B 区连续地面层高 / C 区宽 / D 区侧栏宽 / 明细带两态高)已入驻 `game/data/tables/battle_layout.tres`,不在本表重复。
|
||||||
|
|
||||||
| 参数 | 域 | 现行值(文档自持,无表承载) | 说明 |
|
| 参数 | 域 | 现行值(文档自持,无表承载) | 说明 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
第二条边界是反面清单:局内资源不入存档。行动点、储备行动点、道具库存、生命、GP 全部单局清零——各归各的系统管,没有局内数值需要持久化。若未来某局内资源要开放跨局携带(如储备行动点跨战斗携带),须修订其池规则并向本系统登记持久化归属,禁止静默超域。
|
第二条边界是反面清单:局内资源不入存档。行动点、储备行动点、道具库存、生命、GP 全部单局清零——各归各的系统管,没有局内数值需要持久化。若未来某局内资源要开放跨局携带(如储备行动点跨战斗携带),须修订其池规则并向本系统登记持久化归属,禁止静默超域。
|
||||||
|
|
||||||
**唯一豁免 = `breakpoint` 断点域**:断点是冒险进行中的瞬态快照,不是跨局携带——里面的生命/GP/道具库存只在「续玩上局」时还原进局内,冒险收束(冒险成功/失败/放弃)即整域清除,永远不会渗进永久进度。反面清单的管辖对象因此收窄为 `meta` 永久进度域(冒烟域界扫描收窄到 meta 域);断点域自身的字段口径归[冒险结构](../冒险循环/冒险结构.md)登记。断点顶层键(28 键)的登记单源=冒险应用层的断点键表(键→回退策略;现行契约见架构文档「冒险域拆分」节);写读已换代为各件自交片段——主角账/停点件/关卡件各自写读自己的键(缺键回退策略随领域知识归各件),冒险应用层是唯一拼盘落盘口(收齐各件片段拼成顶层快照后写盘,写触发点不变)。**关卡完成停点的同调未用行留存**:`aux_items` 键在此停点形态含同调未用行(「同调行始终留在 treasure_inventory」与「键值形态逐位不变」在关卡完成停点互斥,采行留存;玩家可见 C 区投影零变化,24 停点充能读数逐位一致)。
|
**唯一豁免 = `breakpoint` 断点域**:断点是冒险进行中的瞬态快照,不是跨局携带——里面的生命/GP/道具库存只在「续玩上局」时还原进局内,冒险收束(冒险成功/失败/放弃)即整域清除,永远不会渗进永久进度。反面清单的管辖对象因此收窄为 `meta` 永久进度域(冒烟域界扫描收窄到 meta 域);断点域自身的字段口径归[冒险结构](../冒险循环/冒险结构.md)登记。断点顶层键(28 键)的登记单源=冒险应用层的断点键表(键→回退策略;现行契约见架构文档「模块归属·核心层」breakpoint_store 行);写读已换代为各件自交片段——主角账/停点件/关卡件各自写读自己的键(缺键回退策略随领域知识归各件),冒险应用层是唯一拼盘落盘口(收齐各件片段拼成顶层快照后写盘,写触发点不变)。**关卡完成停点的同调未用行留存**:`aux_items` 键在此停点形态含同调未用行(「同调行始终留在 treasure_inventory」与「键值形态逐位不变」在关卡完成停点互斥,采行留存;玩家可见 C 区投影零变化,24 停点充能读数逐位一致)。
|
||||||
|
|
||||||
**三存档位**:存档是 3 个独立的 JSON 文件(三个独立存档文件,槽文件名只经存档系统单点派生,槽 1 禁复用旧单档名),字典键一律字符串。写盘目标=当前激活槽的文件;启动(boot)不读任何槽文件——启动态=无激活态,不读写;激活态由选档界面的「新档」或「进档」建立。数据模型(现行 = v7;示例值全为零值默认态):
|
**三存档位**:存档是 3 个独立的 JSON 文件(三个独立存档文件,槽文件名只经存档系统单点派生,槽 1 禁复用旧单档名),字典键一律字符串。写盘目标=当前激活槽的文件;启动(boot)不读任何槽文件——启动态=无激活态,不读写;激活态由选档界面的「新档」或「进档」建立。数据模型(现行 = v7;示例值全为零值默认态):
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ HUD 框架定稿时已为教学留好两个承载位,本系统的内容将来
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 行动点价目 | [行动经济](../排雷循环/行动经济.md) | 挖 / 封印各花多少、移动与连锁免费 |
|
| 行动点价目 | [行动经济](../排雷循环/行动经济.md) | 挖 / 封印各花多少、移动与连锁免费 |
|
||||||
| 储备池清零提示 | [行动经济](../排雷循环/行动经济.md) | 必须说清"储备行动点在战斗结束时清零",防止"攒的钱凭空没了"的误读 |
|
| 储备池清零提示 | [行动经济](../排雷循环/行动经济.md) | 必须说清"储备行动点在战斗结束时清零",防止"攒的钱凭空没了"的误读 |
|
||||||
| 封印是一次性承诺的首遇提示 | [排雷玩法](../排雷循环/排雷玩法.md)(封印不可逆批 2026-09-19) | 经典扫雷玩家会习惯性右键拔除标记——本作封印印记不能拔,落子就是承诺;想改主意就左键直接挖开(安全格零奖励、危险格受挖掘惩罚)。每场冒险提示一次,非模态 |
|
| 封印是一次性承诺的首遇提示 | [排雷玩法](../排雷循环/排雷玩法.md)(封印受理即揭示口径 2026-11-07) | 经典扫雷玩家会习惯性右键拔除标记——本作封印印记不能拔,落子就是承诺:受理即揭示,封中还是封空当场可见,没有反悔路径(封错的代价=轮末标空负向兑付,印记随图存续)。每场冒险提示一次,非模态 |
|
||||||
| chord 不存在的首遇提示 | [HUD 框架](HUD框架.md)(承接排雷玩法的呈现义务) | 经典扫雷玩家会习惯性双击数字格——本作没有 chord,点数字格 = 移动小人。每场冒险提示一次,非模态 |
|
| chord 不存在的首遇提示 | [HUD 框架](HUD框架.md)(承接排雷玩法的呈现义务) | 经典扫雷玩家会习惯性双击数字格——本作没有 chord,点数字格 = 移动小人。每场冒险提示一次,非模态 |
|
||||||
| 挖非相邻格的首次提示 | [HUD 框架](HUD框架.md) | 挖与封印都限小人 8 向相邻的格子,第一次越界操作时提示 |
|
| 挖非相邻格的首次提示 | [HUD 框架](HUD框架.md) | 挖与封印都限小人 8 向相邻的格子,第一次越界操作时提示 |
|
||||||
| 增益叠层节奏 | [增益状态](../战斗循环/增益状态.md) | "同一轮拿满优于跨轮慢慢叠"——增益有结算次数衰减,教学要传达这个节奏 |
|
| 增益叠层节奏 | [增益状态](../战斗循环/增益状态.md) | "同一轮拿满优于跨轮慢慢叠"——增益有结算次数衰减,教学要传达这个节奏 |
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
| 关卡表 | 逐关节点图与层名 | [冒险结构](../冒险循环/冒险结构.md) |
|
| 关卡表 | 逐关节点图与层名 | [冒险结构](../冒险循环/冒险结构.md) |
|
||||||
| 冒险表 | 关卡大奖励与钥石入账(单行全局) | [冒险结构](../冒险循环/冒险结构.md) |
|
| 冒险表 | 关卡大奖励与钥石入账(单行全局) | [冒险结构](../冒险循环/冒险结构.md) |
|
||||||
| 元进度表 | 元进度字段(现行五行族:属性锻造 / Boss 钥石 / 工坊阈值 / 换算率 / 同调刷新升级行族) | [元进度](../跨局循环/元进度.md) |
|
| 元进度表 | 元进度字段(现行五行族:属性锻造 / Boss 钥石 / 工坊阈值 / 换算率 / 同调刷新升级行族) | [元进度](../跨局循环/元进度.md) |
|
||||||
| 战斗屏布局表(`battle_layout.tres`) | 分区几何、B 区连续地面层高与明细带两态高(单行;呈现层布局配置,非玩法数值——供呈现层与样张工具同源读取) | [战斗屏规格](../../ux/battle.md)(结构)/[HUD框架](HUD框架.md)(呈现常量) |
|
| 战斗屏布局表(`battle_layout.tres`) | 分区几何、B 区连续地面层高与明细带两态高(单行;呈现层布局配置,非玩法数值——供呈现层与样张工具同源读取) | [战斗屏规格](../../../ux/battle.md)(结构)/[HUD框架](HUD框架.md)(呈现常量) |
|
||||||
|
|
||||||
举证:本节为数据纪律约定,无计算。违规检测 = 静态扫描加人工复核,随各表回填定稿与里程碑检查执行。
|
举证:本节为数据纪律约定,无计算。违规检测 = 静态扫描加人工复核,随各表回填定稿与里程碑检查执行。
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
|
|
||||||
| 优先级 | 内容 | 后置原因 |
|
| 优先级 | 内容 | 后置原因 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| P1 | 战斗级可回放集成测试(同主种子同动作序列,步骤流逐行相同) | 需战斗域载体,随[战斗结算](../战斗循环/战斗结算.md)回放验收兑现 |
|
| P1 | 战斗级可回放闭环测试(同主种子同动作序列,步骤流逐行相同) | 需战斗域载体,随[战斗结算](../战斗循环/战斗结算.md)回放验收兑现 |
|
||||||
| P1 | 难度曲线导出工具(无窗口导出行解析矩阵供比对) | 难度审计的离线载体,[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)期交付物 |
|
| P1 | 难度曲线导出工具(无窗口导出行解析矩阵供比对) | 难度审计的离线载体,[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)期交付物 |
|
||||||
| P2 | 正式包构建的致命表现验证与调试覆盖结构性不存在验证 | 挂首次正式导出检查清单 |
|
| P2 | 正式包构建的致命表现验证与调试覆盖结构性不存在验证 | 挂首次正式导出检查清单 |
|
||||||
| P2 | 进度键表的调试覆盖行寻址语法 | 调试覆盖现只支持单行全局表字段,行寻址登记为后续扩展 |
|
| P2 | 进度键表的调试覆盖行寻址语法 | 调试覆盖现只支持单行全局表字段,行寻址登记为后续扩展 |
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
| 不负责 | 归谁 |
|
| 不负责 | 归谁 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 呈现语义与可访问性基线本体(字号下限、闪烁上限、纯鼠标可玩等) | [HUD 框架](HUD框架.md) |
|
| 呈现语义与可访问性基线本体(字号下限、闪烁上限、纯鼠标可玩等) | [HUD 框架](HUD框架.md) |
|
||||||
| 逐行结算的呈现规则 | [battle.md](../../ux/battle.md) 与 [HUD 框架](HUD框架.md),本文只引用 |
|
| 逐行结算的呈现规则 | [battle.md](../../../ux/battle.md) 与 [HUD 框架](HUD框架.md),本文只引用 |
|
||||||
| 减动效开启后动画怎么演 | [战斗表现](../战斗循环/战斗表现.md)——本文提供开关,动画侧兑现归对方 |
|
| 减动效开启后动画怎么演 | [战斗表现](../战斗循环/战斗表现.md)——本文提供开关,动画侧兑现归对方 |
|
||||||
| 音量调节对声音怎么生效 | [音频](音频.md)——生效侧归对方,口径已对齐 |
|
| 音量调节对声音怎么生效 | [音频](音频.md)——生效侧归对方,口径已对齐 |
|
||||||
| 文案内容本体(教学条目、界面用语等写了什么) | 各系统文档——本文只做翻译生产,不改含义 |
|
| 文案内容本体(教学条目、界面用语等写了什么) | 各系统文档——本文只做翻译生产,不改含义 |
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
| 输入 | 登记处 | 将来要做的 |
|
| 输入 | 登记处 | 将来要做的 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 减动效开关 | [HUD 框架](HUD框架.md)的可访问性基线与 [battle.md](../../ux/battle.md)的呈现承诺;[战斗表现](../战斗循环/战斗表现.md)已登记承接其动画侧 | 提供开关:开启后全部动画有时长减半或直达终态的通路。呈现侧的约束以 battle.md 与 HUD 框架为权威,本文不复述 |
|
| 减动效开关 | [HUD 框架](HUD框架.md)的可访问性基线与 [battle.md](../../../ux/battle.md)的呈现承诺;[战斗表现](../战斗循环/战斗表现.md)已登记承接其动画侧 | 提供开关:开启后全部动画有时长减半或直达终态的通路。呈现侧的约束以 battle.md 与 HUD 框架为权威,本文不复述 |
|
||||||
| 音量控制入口 | 归档对本系统的常规分工登记;[音频](音频.md)已登记同款分工 | 在设置里提供音量入口;生效侧归音频(口径已对齐) |
|
| 音量控制入口 | 归档对本系统的常规分工登记;[音频](音频.md)已登记同款分工 | 在设置里提供音量入口;生效侧归音频(口径已对齐) |
|
||||||
| 键位映射表 | [HUD 框架](HUD框架.md)定稿登记的交付物输入(全键族) | 如何转化成设置项(比如是否允许改键)待设计 |
|
| 键位映射表 | [HUD 框架](HUD框架.md)定稿登记的交付物输入(全键族) | 如何转化成设置项(比如是否允许改键)待设计 |
|
||||||
| 结算风味词 | 归档概念层增补批随巢穴隐喻换轴登记("封印 / 镇 / 反制"一类类型风味词),只登记了存在、各归各的时机 | 内容与形态未定,本文只登记这条输入在 |
|
| 结算风味词 | 归档概念层增补批随巢穴隐喻换轴登记("封印 / 镇 / 反制"一类类型风味词),只登记了存在、各归各的时机 | 内容与形态未定,本文只登记这条输入在 |
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
|
|
||||||
### 解锁界面:双入口框架
|
### 解锁界面:双入口框架
|
||||||
|
|
||||||
(2026-09-18 拍板;入口拓扑=三入口化)营地消费面(消费钥石、查看与管理永久强化)经主菜单「进入存档」→选档界面→进档/新档进入,主菜单不再设营地独立钮;局内状态面板(游戏非实时无暂停语义)也可查看钥石余额与本局冒险信息(只读)。钥石余额在 HUD 常驻展示。呈现 spec:[ux/camp.md](../../ux/camp.md) v1.0(退役/封存件「已退役/已解锁·能力封存中」呈现语义随 spec 落位);视觉终稿已落码。本节锁框架与需求,呈现细节归 spec;局内状态面板入口已实装(实机目检待用户,待办清单登记条在册)。
|
(2026-09-18 拍板;入口拓扑=三入口化)营地消费面(消费钥石、查看与管理永久强化)经主菜单「进入存档」→选档界面→进档/新档进入,主菜单不再设营地独立钮;局内状态面板(游戏非实时无暂停语义)也可查看钥石余额与本局冒险信息(只读)。钥石余额在 HUD 常驻展示。呈现 spec:[ux/camp.md](../../../ux/camp.md) v1.0(退役/封存件「已退役/已解锁·能力封存中」呈现语义随 spec 落位);视觉终稿已落码。本节锁框架与需求,呈现细节归 spec;局内状态面板入口已实装(实机目检待用户,待办清单登记条在册)。
|
||||||
|
|
||||||
### 单局循环零依赖:排期边界的推论
|
### 单局循环零依赖:排期边界的推论
|
||||||
|
|
||||||
|
|||||||
@@ -69,9 +69,9 @@
|
|||||||
|
|
||||||
| 界面 | 管什么(现状指证) | 与生涯的边界 |
|
| 界面 | 管什么(现状指证) | 与生涯的边界 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 营地([camp UX spec](../../ux/camp.md)) | 跨局成长**操作**面(花钥石买强化 / 装配 / 点树——营地场景图+五功能窗口形态);原底栏「最近冒险」条带已撤下(P6 甲),逐局历史回看唯一归生涯 | 营地不改生涯只读定位;生涯不做任何购买入口,也不放「去买」按钮。营地条带已撤(P6 甲) |
|
| 营地([camp UX spec](../../../ux/camp.md)) | 跨局成长**操作**面(花钥石买强化 / 装配 / 点树——营地场景图+五功能窗口形态);原底栏「最近冒险」条带已撤下(P6 甲),逐局历史回看唯一归生涯 | 营地不改生涯只读定位;生涯不做任何购买入口,也不放「去买」按钮。营地条带已撤(P6 甲) |
|
||||||
| 状态面板 | **局内**只读查看这一局进行中的钥石与本局冒险进度 | 状态面板看当局当前值,生涯看跨局累计与历史;局内无生涯入口(P4 甲) |
|
| 状态面板 | **局内**只读查看这一局进行中的钥石与本局冒险进度 | 状态面板看当局当前值,生涯看跨局累计与历史;局内无生涯入口(P4 甲) |
|
||||||
| 结算屏([settlement-summary UX spec](../../ux/settlement-summary.md)) | 冒险收束当下的入账明细——冒险收束时由结算屏呈现入账明细与钥石明细(复用终局面账行的呈现形态) | 收束当下的呈现保留不动;生涯承接的是收束之后的任意时刻回看 |
|
| 结算屏([settlement-summary UX spec](../../../ux/settlement-summary.md)) | 冒险收束当下的入账明细——冒险收束时由结算屏呈现入账明细与钥石明细(复用终局面账行的呈现形态) | 收束当下的呈现保留不动;生涯承接的是收束之后的任意时刻回看 |
|
||||||
| 帮助手册(Beta 批,未实装——教学内容归 Beta 帮助手册) | 讲「怎么玩」 | 生涯讲「我玩过什么」。图鉴条目文案与手册是否共用内容源,接口登记归 Beta 批一并裁 |
|
| 帮助手册(Beta 批,未实装——教学内容归 Beta 帮助手册) | 讲「怎么玩」 | 生涯讲「我玩过什么」。图鉴条目文案与手册是否共用内容源,接口登记归 Beta 批一并裁 |
|
||||||
| 图例面板 | 局内符号/徽标即时解码 | 不合并——图例是局内解码面,图鉴是跨局收集面 |
|
| 图例面板 | 局内符号/徽标即时解码 | 不合并——图例是局内解码面,图鉴是跨局收集面 |
|
||||||
|
|
||||||
|
|||||||
+12
-10
@@ -1,7 +1,7 @@
|
|||||||
# 术语表
|
# 术语表
|
||||||
|
|
||||||
> 全库专用术语的唯一对照表(2026-10-11 用户令建立)。规矩:新术语先登记本表、再在文档使用;退役词见文末对照表,文档正文一律使用现行词。文档中遇到看不懂的词,查本表。用词纪律(禁用词、替换值、豁免范围)见「用语规范」节。
|
> 全库专用术语的唯一对照表(2026-10-11 用户令建立)。规矩:新术语先登记本表、再在文档使用;退役词见文末对照表,文档正文一律使用现行词。文档中遇到看不懂的词,查本表。用词纪律(禁用词、替换值、豁免范围)见「用语规范」节。
|
||||||
> 状态:**现行 v1.26**——2026-10-11 建立;历次升版明细见 git 提交史。
|
> 状态:**现行 v1.28**——2026-10-11 建立;历次升版明细见 git 提交史。
|
||||||
|
|
||||||
## 格与棋盘
|
## 格与棋盘
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
| 安全格 | 没有惩罚的格子——挖开安全并获得其上信息与收益 |
|
| 安全格 | 没有惩罚的格子——挖开安全并获得其上信息与收益 |
|
||||||
| 整图 | 单张棋盘(的整个范围)——原「整图」退役(2026-10-11 用户裁)。例:整图叠加层、整图作用域 |
|
| 整图 | 单张棋盘(的整个范围)——原「整图」退役(2026-10-11 用户裁)。例:整图叠加层、整图作用域 |
|
||||||
| 叠加层(整图叠加层) | 秘宝产生的信息的自持容器:按效果分类的格集,随图消亡、不回写棋盘(见[秘宝](systems/跨局循环/秘宝.md)) |
|
| 叠加层(整图叠加层) | 秘宝产生的信息的自持容器:按效果分类的格集,随图消亡、不回写棋盘(见[秘宝](systems/跨局循环/秘宝.md)) |
|
||||||
| 封印 / 控制 | 封印动作的机制名/玩家名:封印印记落在危险格上为「标中」(危险格被控制、化险为利),封错为「标空」(原「旗 / 控制」,2026-10-18 用户裁:「旗」概念不存在——动作=封印、印记=封印印记),板面单字字形=「封」 |
|
| 封印 / 控制 | 封印动作的机制名/玩家名:受理即揭示——墙瓦片换地板、格下身份当场可见(2026-11-07 用户裁),封印格拒绝挖掘、印记随图存续;封印印记落在危险格上为「标中」(危险格被控制、化险为利),封错为「标空」(原「旗 / 控制」,2026-10-18 用户裁:「旗」概念不存在——动作=封印、印记=封印印记),板面单字字形=「封」 |
|
||||||
| 真视 | 直接告诉玩家某范围内哪些格是危险格的效果(秘宝承重契约:一次最多 3×3,见[秘宝](systems/跨局循环/秘宝.md)核心规则) |
|
| 真视 | 直接告诉玩家某范围内哪些格是危险格的效果(秘宝承重契约:一次最多 3×3,见[秘宝](systems/跨局循环/秘宝.md)核心规则) |
|
||||||
| 类型微光 | 棋盘上按格子类型显示的提示光效(视野参数控制其显示范围) |
|
| 类型微光 | 棋盘上按格子类型显示的提示光效(视野参数控制其显示范围) |
|
||||||
| 换图 / 弃图刷新 | 清完一图进入下一图 / 花储备放弃当前图重开一张(代价见[行动经济](systems/排雷循环/行动经济.md)) |
|
| 换图 / 弃图刷新 | 清完一图进入下一图 / 花储备放弃当前图重开一张(代价见[行动经济](systems/排雷循环/行动经济.md)) |
|
||||||
@@ -94,8 +94,8 @@
|
|||||||
|
|
||||||
| 术语 | 定义 |
|
| 术语 | 定义 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 效果端口件 | 战斗业务类(伤害管线/行动经济)唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批——业务类零引擎直连(机制归属见架构文档「战斗编排域拆件定稿」节轴戊;实现类 EffectPort) |
|
| 效果端口件 | 战斗业务类(伤害管线/行动经济)唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批——业务类零引擎直连(机制归属见架构文档「模块归属·功能层」battle_orchestrator 行;实现类 EffectPort) |
|
||||||
| 掷格件 | 装配期格面资源摇号的承载件:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影);受理账面留守地图战斗资源件(机制归属同上;实现类 RewardRoller) |
|
| 掷格件 | 装配期格面资源摇号的承载件:池行装配、区间行 roll、权重合成(订阅加权/board_skew 两路投影);受理账面留守地图战斗资源件(机制归属同上;实现类 RewardRoller) |
|
||||||
| `seal_missed` | 封印落空事件(旧名已换代):封印动作落在安全格上时发出,订阅面据此做限次与豁免判定 |
|
| `seal_missed` | 封印落空事件(旧名已换代):封印动作落在安全格上时发出,订阅面据此做限次与豁免判定 |
|
||||||
| `forgive_seal_miss` | 本场首次封印落空豁免——专长「完美保险」的效果类型,`domain=battle` 首例;有效误标=误标总数 − 豁免数,豁免不改写误标账 |
|
| `forgive_seal_miss` | 本场首次封印落空豁免——专长「完美保险」的效果类型,`domain=battle` 首例;有效误标=误标总数 − 豁免数,豁免不改写误标账 |
|
||||||
|
|
||||||
@@ -103,15 +103,16 @@
|
|||||||
|
|
||||||
| 术语 | 定义 |
|
| 术语 | 定义 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 样张 | 按美术圣经参数画成的风格试验图,是砖面形态等视觉定稿的验收闸(规格见[美术圣经](../art/art-bible.md) §1.4) |
|
| 样张 | 按美术圣经参数画成的风格试验图,是棋盘地形形态(岩体+地面+浮空数字)等视觉定稿的验收闸(规格见[美术圣经](../art/art-bible.md) §1.4) |
|
||||||
| 整屏样张 | 整屏级样张——战斗/关卡/菜单/营地屏各出一张,验屏级文字对比度、明度分层与焦点预算 |
|
| 整屏样张 | 整屏级样张——战斗/关卡/菜单/营地屏各出一张,验屏级文字对比度、明度分层与焦点预算 |
|
||||||
| 掩尘 | 未开格底色的专色名——覆尘完整砖的「未知」面色 |
|
| 掩尘 | 未开格岩体顶面基色的专色名——覆尘完整岩体的「未知」面色(现行值 `#9C8462`,见美术圣经 §4.1) |
|
||||||
| 裸土 | 已开格底色的专色名——碎裂裸露空间的沉暗面色 |
|
| 裸土 | 已开格连续地面基色的专色名——挖出空间的沉暗面色(现行值 `#695038`,见美术圣经 §4.1) |
|
||||||
| 色牌 | 垫在数字正下方的素色直角小牌,复杂格底时保数字可读的后备手段 |
|
| 色牌 | 棋盘数字底具——普通数字已退役(2026-11-07 浮空数字定案,棋盘普通数字不再使用底牌);封印格身份字形色牌保留(2026-11-07 封印改版,叠于法阵之上);沿革查美术圣经 §4.1 |
|
||||||
| 图类型 | 棋盘生成产物 `board_type` 的中文名——三关换皮的单位(同款地砖换色板) |
|
| 浮空数字 | 棋盘数字的现行呈现——数字与格面字形浮在格上方,暖白字芯+2px 深墨描边+双色引导线;字高 21px、字底距格顶 15px(规格见[美术圣经](../art/art-bible.md) §3.2) |
|
||||||
|
| 图类型 | 棋盘生成产物 `board_type` 的中文名——三关换皮的单位(同款地形材质换色板) |
|
||||||
| 方向稿 | 冻结前的方向性候选稿,供气质目检;过目检后才进机检冻结 |
|
| 方向稿 | 冻结前的方向性候选稿,供气质目检;过目检后才进机检冻结 |
|
||||||
| 站桩 | 战斗画面区(B 区)里角色直立立绘的显示形态(配血条与状态行) |
|
| 站桩 | 战斗画面区(B 区)里角色直立立绘的显示形态(配血条与状态行) |
|
||||||
| 显示档 | 站桩立绘的显示尺寸规则——源用原稿分辨率入包(禁降采样),显示按三档绝对高(小型 96/中型 144/大型 188)缩放、宽随源比例;定值单点见[美术圣经](../art/art-bible.md) §8.2 站桩立绘显示档条 |
|
| 显示档 | 站桩立绘的显示尺寸规则——源用原稿分辨率入包(禁降采样),显示按三档绝对高缩放、宽随源比例;定值单点见[美术圣经](../art/art-bible.md) §8.2 站桩立绘显示档条(档值定值面=站桩呈现守门测试) |
|
||||||
| 徽章 | 库存条与结算明细用的小图标(与格面类型微光预读相区分) |
|
| 徽章 | 库存条与结算明细用的小图标(与格面类型微光预读相区分) |
|
||||||
|
|
||||||
## 开发流程
|
## 开发流程
|
||||||
@@ -179,6 +180,7 @@
|
|||||||
| 罕见(档位名) | 稀有(2026-10-26 用户裁入表:旧三档档位名,现行四级第三档=稀有;散文形容词义不受限) |
|
| 罕见(档位名) | 稀有(2026-10-26 用户裁入表:旧三档档位名,现行四级第三档=稀有;散文形容词义不受限) |
|
||||||
| 通关 | 关卡完成(单关)/冒险成功(整局)——2026-10-26 用户裁:主体明确短语族替代歧义单义词 |
|
| 通关 | 关卡完成(单关)/冒险成功(整局)——2026-10-26 用户裁:主体明确短语族替代歧义单义词 |
|
||||||
| 冒险终结 | 冒险落幕——2026-10-26 通关口径统一批 |
|
| 冒险终结 | 冒险落幕——2026-10-26 通关口径统一批 |
|
||||||
|
| 集成测试 / 集成用例 / 集成层 / 集成侧 / 集成宿主 / 集成族 | 单元测试(2026-11-07 用户裁层级合并——跨系统真实路径闭环套件归单元层,三套件实体迁移 tests/unit/;测试层识别靠三元组〔职责×触发时间点×覆盖面积,权威表=test-conventions「测试层三元组」节〕,层级名只是代称;闭环套件的性质归属由各套件头注承载) |
|
||||||
|
|
||||||
## 对外命名纪律(玩家可见命名,2026-10-11 用户令)
|
## 对外命名纪律(玩家可见命名,2026-10-11 用户令)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> **Status**: Complete(现行)
|
> **Status**: Complete(现行)
|
||||||
> **Author**: user + ux-designer
|
> **Author**: user + ux-designer
|
||||||
> **Last Updated**: 2026-11-02
|
> **Last Updated**: 2026-11-07
|
||||||
> **Platform Target**: PC (Steam)——Keyboard/Mouse 主(全部操作纯鼠标可完成)、Gamepad Partial 非 MVP、Touch None(同 technical-preferences)
|
> **Platform Target**: PC (Steam)——Keyboard/Mouse 主(全部操作纯鼠标可完成)、Gamepad Partial 非 MVP、Touch None(同 technical-preferences)
|
||||||
> **上游修订依赖**: 弃图刷新挖掘期受理依赖上游现行规则(行动经济 Active 受理 + 每轮上限 2 次、排雷玩法 Active·仅刷新路径装板、战斗结算的挖掘期刷新编排 + 恒同盘不变、系统索引的刷新规则同步——见布局决策 4 与 OQ11)
|
> **上游修订依赖**: 弃图刷新挖掘期受理依赖上游现行规则(行动经济 Active 受理 + 每轮上限 2 次、排雷玩法 Active·仅刷新路径装板、战斗结算的挖掘期刷新编排 + 恒同盘不变、系统索引的刷新规则同步——见布局决策 4 与 OQ11)
|
||||||
> **Template**: UX Spec
|
> **Template**: UX Spec
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
本屏必须传达的全部信息,按注视优先级分五层:
|
本屏必须传达的全部信息,按注视优先级分五层:
|
||||||
|
|
||||||
1. **扫雷图本体**(第一注视点,挖掘期占视觉预算大头):两格态(已开格 / 未开格——排雷玩法×6② 一眼可辨)、数字、封印印记、小人、可挖域(8 向相邻常驻指示)、变异纹理
|
1. **扫雷图本体**(第一注视点,挖掘期占视觉预算大头):两格态(已开格 / 未开格——排雷玩法×6② 一眼可辨)、数字、封印印记、小人、可挖域(8 向相邻常驻指示)、变异纹理
|
||||||
2. **本轮行动资源**:AP 余量(决定还能挖几格)、RAP 池(弃图刷新货币)、停手/弃图刷新按钮——紧贴棋盘上缘(动作发生地)
|
2. **本轮行动资源**:AP 余量(决定还能挖几格)、RAP 池(弃图刷新货币)、停手/弃图刷新按钮——紧贴棋盘左右两侧(动作发生地;2026-11-07 顶栏搬两侧后由侧栏承载)
|
||||||
3. **战果兑现面**(结算期为第一注视点):敌人血条变化、逐行结算明细、高光(完美封印/封印标中)
|
3. **战果兑现面**(结算期为第一注视点):敌人血条变化、逐行结算明细、高光(完美封印/封印标中)
|
||||||
4. **规划面**(边缘注视,常读):攻击值与修正来源(C 区数据框)、敌人意图徽标与顺位(B 区站桩);HP 与状态效果由单位本体(B 区站桩)唯一承载——数据框不重复展示
|
4. **规划面**(边缘注视,常读):攻击值与修正来源(C 区数据框)、敌人意图徽标与顺位(B 区站桩);HP 与状态效果由单位本体(B 区站桩)唯一承载——数据框不重复展示
|
||||||
5. **进度语境**:轮次/阶段指示、图例入口(关卡节点进度常驻关卡画面,战斗屏不承载——见 Navigation Position)
|
5. **进度语境**:轮次/阶段指示、图例入口(关卡节点进度常驻关卡画面,战斗屏不承载——见 Navigation Position)
|
||||||
@@ -106,27 +106,69 @@
|
|||||||
- 护甲 AC(2026-09-26 二轮拍板补入——我方 AC 的唯一展示面;掷点判定轴,受击侧可读性)
|
- 护甲 AC(2026-09-26 二轮拍板补入——我方 AC 的唯一展示面;掷点判定轴,受击侧可读性)
|
||||||
- 秘宝槽(四槽壳在役、空槽占位——局内两步使用与关卡域库存随秘宝过渡形态退役;现行秘宝 = 营地同调装配件,本区展示内容归装配面重接)
|
- 秘宝槽(四槽壳在役、空槽占位——局内两步使用与关卡域库存随秘宝过渡形态退役;现行秘宝 = 营地同调装配件,本区展示内容归装配面重接)
|
||||||
- 奇物列表(**已实装**——现行标题「特性」;锻造/大奖励/关卡奖励节点获得的属性提升,逐件行「件名 ×N」呈现、零内部分类字样上屏;与战斗内状态效果分区呈现,防「战斗结束被清」误读)
|
- 奇物列表(**已实装**——现行标题「特性」;锻造/大奖励/关卡奖励节点获得的属性提升,逐件行「件名 ×N」呈现、零内部分类字样上屏;与战斗内状态效果分区呈现,防「战斗结束被清」误读)
|
||||||
- **D 区扫雷图 · AP 条**
|
- **D 区扫雷图 · 行动资源侧栏(原 AP 条,2026-11-07 顶栏搬两侧)**
|
||||||
- AP 点阵 + 停手按钮(现行)
|
- 左栏:AP 点阵 + 停手按钮
|
||||||
- **RAP 读数(点阵+数字)**——置于弃图刷新按钮旁(2026-09-26 拍板:RAP 唯一消费口 = 弃图刷新,资源数字贴消费按钮)
|
- 右栏:**RAP 读数(点阵+数字)** + 图例按钮 + 弃图刷新按钮——RAP 贴弃图刷新(2026-09-26 拍板:RAP 唯一消费口 = 弃图刷新,资源数字贴消费按钮)
|
||||||
- **战斗屏不承载(2026-09-26 二轮拍板)**
|
- **战斗屏不承载(2026-09-26 二轮拍板)**
|
||||||
- GP(中循环资源——商店房消费):**关卡画面常驻总量** + **战斗总结结算(总量+增量)**(呈现 spec:[settlement-summary.md](settlement-summary.md))
|
- GP(中循环资源——商店房消费):**关卡画面常驻总量** + **战斗总结结算(总量+增量)**(呈现 spec:[settlement-summary.md](settlement-summary.md))
|
||||||
- 钥石(大循环永久资源):**战斗总结结算(Boss/精英击杀增量行)+ 冒险总结结算(收束明细)+ 营地**(呈现 spec:[settlement-summary.md](settlement-summary.md))
|
- 钥石(大循环永久资源):**战斗总结结算(Boss/精英击杀增量行)+ 冒险总结结算(收束明细)+ 营地**(呈现 spec:[settlement-summary.md](settlement-summary.md))
|
||||||
|
|
||||||
### Layout Zones
|
### Layout Zones
|
||||||
|
|
||||||
采用用户拍板的布局图(2026-09-12),按 1280×800 基座落尺寸。**分区几何的唯一事实源 = `game/data/tables/battle_layout.tres`**(经 `ConfigDb.presentation.battle_layout` 读取;字段 `stage_h` / `ground_h`(B 区连续地面层高)/ `info_panel_w` / `ap_bar_h` / `log_band_h_dig` / `log_band_h_settle`)。本节只写结构关系与内容职责,不复写数值;任何文档与代码不另立第二份布局值。
|
采用用户拍板的布局图(2026-09-12),按 1280×800 基座落尺寸。**分区几何的唯一事实源 = `game/data/tables/battle_layout.tres`**(经 `ConfigDb.presentation.battle_layout` 读取;字段 `stage_h` / `ground_h`(B 区连续地面层高)/ `info_panel_w` / `side_rail_w`(D 区行动资源侧栏宽,2026-11-07 顶栏搬两侧后新增)/ `log_band_h_dig` / `log_band_h_settle`;游戏视图不再读 `ap_bar_h`;布局表字段暂留供样张渲染工具,删除归工具批)。本节只写结构关系与内容职责,不复写数值;任何文档与代码不另立第二份布局值。
|
||||||
|
|
||||||
| 区 | 位置与几何 | 内容 |
|
| 区 | 位置与几何 | 内容 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **B 战斗画面** | 全宽,高读 `stage_h`(2026-10-06 方案二拍板:演出 ≈1/3 屏) | 主角站桩立绘(左)+ 兑现演出区(中)+ 敌人站桩立绘 ×1–3(右)——**全站桩形态(2026-09-20 用户拍板):主角与敌人均为无框立绘+底座,零卡片**;主角与敌人站桩 = **HP 与状态效果的唯一展示面(2026-09-26 信息归属拍板)**;底部结算明细带(挖掘期收起高读 `log_band_h_dig`,结算期展开高读 `log_band_h_settle`);顶部中央轮次·阶段指示 |
|
| **B 战斗画面** | 全宽,高读 `stage_h`(2026-10-06 方案二拍板:演出 ≈1/3 屏) | 主角站桩立绘(左)+ 兑现演出区(中)+ 敌人站桩立绘 ×1–3(右)——**全站桩形态(2026-09-20 用户拍板):主角与敌人均为无框立绘+底座,零卡片**;主角与敌人站桩 = **HP 与状态效果的唯一展示面(2026-09-26 信息归属拍板)**;底部结算明细带(挖掘期收起高读 `log_band_h_dig`,结算期展开高读 `log_band_h_settle`);顶部中央轮次·阶段指示 |
|
||||||
| **C 角色信息** | 左下,宽读 `info_panel_w`,高 = 基准屏高 − B 区高 | 攻击值(含修正显示)、护甲 AC;秘宝槽、奇物列表(现行标题「特性」)——HP 条/RAP 池/状态效果槽/立绘占位/钱包行退役(2026-09-26 信息归属拍板:HP 与状态唯一展示面 = B 区站桩;RAP 迁 D 区 AP 条;GP/钥石迁出战斗屏) |
|
| **C 角色信息** | 左下,宽读 `info_panel_w`,高 = 基准屏高 − B 区高 | 攻击值(含修正显示)、护甲 AC;秘宝槽、奇物列表(现行标题「特性」)——HP 条/RAP 池/状态效果槽/立绘占位/钱包行退役(2026-09-26 信息归属拍板:HP 与状态唯一展示面 = B 区站桩;RAP 迁 D 区右栏;GP/钥石迁出战斗屏) |
|
||||||
| **D 扫雷图** | 中下,宽 = 基准屏宽 − C 区宽 − 列间距,高同 C 区(2026-10-06 方案二:底行压缩全部由面板空档吸收,**棋盘原尺寸不缩、格子不变**) | 顶部 AP 条(高读 `ap_bar_h`:左——AP 点阵 + 停手按钮;中——RAP 点阵+数字〔贴弃图刷新按钮,2026-09-26 拍板〕;右——图例按钮 + 弃图刷新按钮〔雷图右上角,2026-09-12 拍板〕);棋盘主体(居中,格边长见下方「棋盘格尺寸公式」);toast 槽(上缘内侧) |
|
| **D 扫雷图** | 中下,宽 = 基准屏宽 − C 区宽 − 列间距,高同 C 区(2026-11-07 顶栏搬两侧:**D 区全高归棋盘**,不再让出 AP 条高度;棋盘不缩,格边按公式现算) | 左栏(宽读 `side_rail_w`,贴棋盘左缘):AP 点阵 + 停手按钮;右栏(同宽,贴棋盘右缘):RAP 点阵+数字 + 图例按钮 + 弃图刷新按钮(RAP 贴唯一消费口,2026-09-26 拍板);棋盘主体居中(格边长见下方「棋盘格尺寸公式」;上方留 44px 给浮空数字越出棋盘,下方 12px+悬崖 8px);toast 槽(D 区上缘内侧左栏顶部,不覆盖棋盘与浮空数字);棋盘底常驻操作提示条退役(2026-11-07 用户裁,不占棋盘高度) |
|
||||||
|
|
||||||
> 布局为 B/C/D 三区——关卡进度条不在战斗屏(节点链进度常驻关卡画面,见 Navigation Position;字母不重编沿用 B/C/D)。
|
> 布局为 B/C/D 三区——关卡进度条不在战斗屏(节点链进度常驻关卡画面,见 Navigation Position;字母不重编沿用 B/C/D)。
|
||||||
|
|
||||||
> 呈现术语注记(2026-09-25):封印 = 正式动作名(全库统一;登记册术语与术语表;印记 = 封印印记,art-bible §3.2)——机制与键名不变;印记贴图已落位(`seal_mark.png`,环+十字法阵,形与定值见 art-bible §3.2/§8.2),缺图时回落封印黑「封」字形(棋盘视图程序化回退);封印特效的施印瞬间一件未实装。封印色 = 封印黑(现行)。
|
> 呈现术语注记(2026-09-25):封印 = 正式动作名(全库统一;登记册术语与术语表;印记 = 封印印记,art-bible §3.2)——机制与键名不变;印记贴图已落位(`seal_mark.png`,环+十字法阵,形与定值见 art-bible §3.2/§8.2),缺图时回落封印黑「封」字形(棋盘视图程序化回退);封印特效的施印瞬间一件未实装。封印色 = 封印黑(现行)。
|
||||||
|
|
||||||
|
### 封印格呈现预览(2026-11-07 用户裁「封印受理即揭示」的呈现规格;2026-11-07 用户人审通过——按此先落实现,观感细化后置,不阻塞基线冻结)
|
||||||
|
|
||||||
|
封印受理后格子进入**已揭示+封印**态:墙格换已揭示连续地面,封印法阵(环+十字)叠在其上,格下身份字形(危险格「危」朱字/安全格数字)按既有绘制优先级(数字 > 小人 > 封印印记)叠于法阵之上、垫既有色牌机制保可读。棋盘重做批后承载面取本关受光棱色封印石(新连续地面 `#695038` 系对封印黑仅 2.35–2.98:1,不达 ≥4.5:1;受光棱系 6.45–9.94:1,零新增色,见 art-bible §3.2/§4.1)。轮末判定后印记不撤,随图存续。
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 128" width="560" height="128">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="sealhalo">
|
||||||
|
<stop offset="0.68" stop-color="#000000" stop-opacity="0"/>
|
||||||
|
<stop offset="0.82" stop-color="#000000" stop-opacity="0.5"/>
|
||||||
|
<stop offset="1" stop-color="#000000" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
<rect x="0" y="0" width="560" height="128" fill="#2E2620"/>
|
||||||
|
<g font-family="monospace" font-size="12" fill="#C9AF83" text-anchor="middle">
|
||||||
|
<text x="52" y="122">未开(对照)</text>
|
||||||
|
<text x="148" y="122">封印·标中(危险格)</text>
|
||||||
|
<text x="244" y="122">封印·标空(安全格)</text>
|
||||||
|
<text x="340" y="122">已开(对照)</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect x="28" y="20" width="48" height="48" fill="#C9AF83"/>
|
||||||
|
<rect x="124" y="20" width="48" height="48" fill="#B39A78"/>
|
||||||
|
<circle cx="148" cy="44" r="24" fill="url(#sealhalo)"/>
|
||||||
|
<circle cx="148" cy="44" r="19.7" fill="none" stroke="#000000" stroke-width="4.3"/>
|
||||||
|
<rect x="143.9" y="28" width="8.2" height="32" fill="#000000"/>
|
||||||
|
<rect x="132" y="39.9" width="32" height="8.2" fill="#000000"/>
|
||||||
|
<rect x="136" y="32" width="24" height="24" fill="#D8C6A4"/>
|
||||||
|
<text x="148" y="52" font-family="monospace" font-size="17" font-weight="bold" fill="#962C24" text-anchor="middle">危</text>
|
||||||
|
<rect x="220" y="20" width="48" height="48" fill="#B39A78"/>
|
||||||
|
<circle cx="244" cy="44" r="24" fill="url(#sealhalo)"/>
|
||||||
|
<circle cx="244" cy="44" r="19.7" fill="none" stroke="#000000" stroke-width="4.3"/>
|
||||||
|
<rect x="239.9" y="28" width="8.2" height="32" fill="#000000"/>
|
||||||
|
<rect x="228" y="39.9" width="32" height="8.2" fill="#000000"/>
|
||||||
|
<rect x="232" y="32" width="24" height="24" fill="#D8C6A4"/>
|
||||||
|
<text x="244" y="52" font-family="monospace" font-size="17" font-weight="bold" fill="#33261B" text-anchor="middle">3</text>
|
||||||
|
<rect x="316" y="20" width="48" height="48" fill="#B39A78"/>
|
||||||
|
<text x="340" y="52" font-family="monospace" font-size="17" font-weight="bold" fill="#33261B" text-anchor="middle">2</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
像素级判据句(实现批验收锚):①印记参数沿用现行五常量单点(环外径 0.82 格边、环壁 0.11 环径、十字臂宽 0.156 环径、光圈 alpha 0.50/γ1.6),零新增美术件、零参数改动;②封印格承载 = 已揭示地面(棋盘重做批后为本关受光棱色封印石),印记居格心、环外留 9% 格宽光圈、光圈不外溢邻格;③身份字形(危/数字)垫既有色牌件叠于法阵之上——色牌取现行色板素色小牌件,墨字对色牌对比 ≥4.5:1;④封印黑对承载面对比:旧裸土 ≈7.8:1,棋盘重做批后受光棱 6.45–9.94:1(均 ≥4.5:1);⑤未开格与已开普通格观感按棋盘重做批新地形规格(对照列)。
|
||||||
|
|
||||||
> 可挖域微光画法定稿(2026-09-25 用户拍板):**接触带·空间侧 + 蓝族**——光画英雄格周界接触面(正交邻墙=整边,斜向邻墙=角点+两半边),详见 art-bible §3.2;现行墙格整框绿相呼吸为待退役占位,切换待表现侧实现(含探针断言)。
|
> 可挖域微光画法定稿(2026-09-25 用户拍板):**接触带·空间侧 + 蓝族**——光画英雄格周界接触面(正交邻墙=整边,斜向邻墙=角点+两半边),详见 art-bible §3.2;现行墙格整框绿相呼吸为待退役占位,切换待表现侧实现(含探针断言)。
|
||||||
|
|
||||||
**布局决策 1(本 spec 最大决策,用户拍板)**:**常驻双舞台分屏**——战斗画面与扫雷图同屏常驻,挖掘期敌人待机可见,结算期不切场景。
|
**布局决策 1(本 spec 最大决策,用户拍板)**:**常驻双舞台分屏**——战斗画面与扫雷图同屏常驻,挖掘期敌人待机可见,结算期不切场景。
|
||||||
@@ -137,13 +179,14 @@
|
|||||||
**棋盘格尺寸公式**(本节是格边长口径的唯一出处;其他文档只写规则与指针,不复制算例):
|
**棋盘格尺寸公式**(本节是格边长口径的唯一出处;其他文档只写规则与指针,不复制算例):
|
||||||
|
|
||||||
```
|
```
|
||||||
格边长 = clampi( floor((min(棋盘区宽 − 12 − 悬崖厚度, 棋盘区高 − 24 − 悬崖厚度) − (N−1) × 格间距) / N), 26, 46 )
|
格边长 = clampi( floor((min(棋盘区宽 − 2 × 侧栏宽 − 12 − 悬崖厚度, 棋盘区高 − 44 − 12 − 悬崖厚度) − (N−1) × 格间距) / N), 26, 46 )
|
||||||
```
|
```
|
||||||
|
|
||||||
- N = 棋盘长宽两边的较大者;格间距 2px;垂直预留 24px(上 12 / 下 12);悬崖厚度 8px;结构钳制区间 [26, 46]px。
|
- **棋盘区** = D 区矩形(宽 = 基准屏宽 − C 区宽 − 列间距,高 = 基准屏高 − B 区高);2026-11-07 顶栏搬两侧后,D 区全高归棋盘,AP 条高度不再参与算式。
|
||||||
- 格边长可读性以用户验收的现行画面为锚点(2026-11-01 用户裁——现行渲染值即基准,基座档 14×14=28px 达标);全域不设人造的格边长可读阈值。结构钳制 [26, 46] 只管算式结果不越界;格边长接线守卫=生产写入值与上式单点算式的返回值严格相等,最大板型的推定读数仅留痕观察、不作判红依据。
|
- N = 棋盘长宽两边的较大者;格间距 2px;侧栏宽读布局表 `side_rail_w`(基座档 200);水平预留 12px(左右各 6);垂直预留 56px(**上 44 / 下 12**——上方 44px 给浮空数字越出棋盘上缘,推导 = 字高 21+字底距格顶 15+描边 2+余量 6);悬崖厚度 8px;结构钳制区间 [26, 46]px。
|
||||||
- N 的取值与每关板型的对应关系读[棋盘生成](../systems/排雷循环/棋盘生成.md),现行值的事实源是 `data/tables/board_gen.tres`。
|
- 格边长可读性以用户验收的现行画面为锚点(2026-11-01 用户裁——现行渲染值即基准;2026-11-07 顶栏搬两侧后基座档 12×12=38px、14×14=32px);全域不设人造的格边长可读阈值。结构钳制 [26, 46] 只管算式结果不越界;格边长接线守卫=生产写入值与上式单点算式的返回值严格相等,最大板型的推定读数仅留痕观察、不作判红依据。
|
||||||
- 数字字号 = max(18, ceil(格边长 × 0.5)),像素字体整数倍缩放(canvas_items stretch 保证清晰)。
|
- N 的取值与每关板型的对应关系读[棋盘生成](../gdd/systems/排雷循环/棋盘生成.md),现行值的事实源是 `data/tables/board_gen.tres`。
|
||||||
|
- 浮空数字字高 = 21px(7px 像素字 ×3,固定,不随格边缩放)+2px 深墨描边;引导线 2px、字底距格顶 15px;旧「数字字号 = max(18, ceil(格边长 × 0.5))」随格内数字退役。
|
||||||
|
|
||||||
算例不入文档:棋盘区可用面积随布局表与板型变化,不是契约值——现算并绘在整屏样张上,本文件不复写。
|
算例不入文档:棋盘区可用面积随布局表与板型变化,不是契约值——现算并绘在整屏样张上,本文件不复写。
|
||||||
|
|
||||||
@@ -154,13 +197,15 @@
|
|||||||
| B | 主角站桩立绘 | 站桩(无框立绘+落影) | HP 条落底盘(2026-10-06 方案二拍板:站桩排式 = **立绘→血条→状态**,全场血条对齐一线;血条嵌石板位、台缘线留作地面线;不悬浮头顶——高盒下血条-立绘空洞,用户点名否决)、状态效果小图标一排挂血条正下方(形状+色相双通道、层数角标;空态不占位退化为空行)——**HP 与状态效果的唯一展示面(2026-09-26 信息归属拍板;悬停 tooltip〔来源+语义+剩余结算次数〕职责在本组件)**;攻击值等规划数据仍归 C 区数据框(2026-09-20 全站桩拍板,英雄卡退役) | 悬停状态小图标看 tooltip | HUD 视图拆分改造 |
|
| B | 主角站桩立绘 | 站桩(无框立绘+落影) | HP 条落底盘(2026-10-06 方案二拍板:站桩排式 = **立绘→血条→状态**,全场血条对齐一线;血条嵌石板位、台缘线留作地面线;不悬浮头顶——高盒下血条-立绘空洞,用户点名否决)、状态效果小图标一排挂血条正下方(形状+色相双通道、层数角标;空态不占位退化为空行)——**HP 与状态效果的唯一展示面(2026-09-26 信息归属拍板;悬停 tooltip〔来源+语义+剩余结算次数〕职责在本组件)**;攻击值等规划数据仍归 C 区数据框(2026-09-20 全站桩拍板,英雄卡退役) | 悬停状态小图标看 tooltip | HUD 视图拆分改造 |
|
||||||
| B | 敌人站桩立绘 ×1–3 | 站桩(无框立绘+落影) | 血条+顺位徽标落底盘(同主角排式,2026-10-06 方案二;**大体档〔显示 >150px 级:drider/duergar_king〕允许向上溢出盒顶 N px(N 由实装实算,溢出判定与背景无关),血条仍落底**)、状态小图标挂血条正下方(敌方增益按个体呈现——各立绘只显示它自己名下的状态实例〔蓄力/硬化/削弱/暴走/警觉,2026-11-02 个体化裁〕;数据源 = 战斗结算流水经增益状态投影,敌人系统×4④;无行为环点〔proposal §2.4〕,意图占位 = 本拍摇定结果的动画占位——普通攻击零表示 / 特殊技类型级提示,**意图徽标悬浮头顶上方,探顶档压胸**,敌方增益〔蓄力/硬化〕入状态图标行);死亡灰化加碎裂退场直接演在立绘上(2026-09-20 全站桩拍板,敌人卡退役);血条下名字行 = 纯名字 + 护甲类型图标(形状+色相双通道,与状态图标同行共存,状态空时为纯名字),AC 数值不展示——2026-09-26 终裁(用户口径:HP 信息已足够,攻防数值不直接写上;护甲类型图标保留克制对策可读性——类型可读、数值隐藏) | 只读 | 新建 |
|
| B | 敌人站桩立绘 ×1–3 | 站桩(无框立绘+落影) | 血条+顺位徽标落底盘(同主角排式,2026-10-06 方案二;**大体档〔显示 >150px 级:drider/duergar_king〕允许向上溢出盒顶 N px(N 由实装实算,溢出判定与背景无关),血条仍落底**)、状态小图标挂血条正下方(敌方增益按个体呈现——各立绘只显示它自己名下的状态实例〔蓄力/硬化/削弱/暴走/警觉,2026-11-02 个体化裁〕;数据源 = 战斗结算流水经增益状态投影,敌人系统×4④;无行为环点〔proposal §2.4〕,意图占位 = 本拍摇定结果的动画占位——普通攻击零表示 / 特殊技类型级提示,**意图徽标悬浮头顶上方,探顶档压胸**,敌方增益〔蓄力/硬化〕入状态图标行);死亡灰化加碎裂退场直接演在立绘上(2026-09-20 全站桩拍板,敌人卡退役);血条下名字行 = 纯名字 + 护甲类型图标(形状+色相双通道,与状态图标同行共存,状态空时为纯名字),AC 数值不展示——2026-09-26 终裁(用户口径:HP 信息已足够,攻防数值不直接写上;护甲类型图标保留克制对策可读性——类型可读、数值隐藏) | 只读 | 新建 |
|
||||||
| B | 轮次·阶段指示 | 标签 | "第 N 轮 · 挖掘中/结算中"(终局定格「战斗结束」;Boss 变体附 Boss 名) | 只读 | 新建 |
|
| B | 轮次·阶段指示 | 标签 | "第 N 轮 · 挖掘中/结算中"(终局定格「战斗结束」;Boss 变体附 Boss 名) | 只读 | 新建 |
|
||||||
| B | 结算明细带 | 滚动列表 | 结算期逐行流水([战斗结算](../systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋) 9 类行协议);挖掘期收起为上轮摘要 1 行 | 无明细回看——带保留单行摘要,冒险中回看归「生涯」 | 改造 |
|
| B | 结算明细带 | 滚动列表 | 结算期逐行流水([战斗结算](../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋) 9 类行协议);挖掘期收起为上轮摘要 1 行 | 无明细回看——带保留单行摘要,冒险中回看归「生涯」 | 改造 |
|
||||||
| B | 结算明细回看(已退役) | —— | 冒险中回看归「生涯」;回看覆盖层为未接线遗留件(待办清单登记) | —— | 未接线 |
|
| B | 结算明细回看(已退役) | —— | 冒险中回看归「生涯」;回看覆盖层为未接线遗留件(待办清单登记) | —— | 未接线 |
|
||||||
| C | 攻击数据框 | 直角细线数据框 | 攻击值 + 修正来源角标 + 护甲 AC(AC 二轮拍板 2026-09-26 补入——我方 AC 唯一展示面;HP 与状态归 B 区站桩、RAP 归 D 区 AP 条,不在本组件) | 只读 | HUD 视图拆分 |
|
| C | 攻击数据框 | 直角细线数据框 | 攻击值 + 修正来源角标 + 护甲 AC(AC 二轮拍板 2026-09-26 补入——我方 AC 唯一展示面;HP 与状态归 B 区站桩、RAP 归 D 区右栏,不在本组件) | 只读 | HUD 视图拆分 |
|
||||||
| C | 秘宝槽 | 图标槽 ×4 | 四槽壳在役、空槽占位(标题「秘宝」,悬停「秘宝槽(空)」);局内两步使用与关卡域库存随秘宝过渡形态退役——现行秘宝 = 营地同调装配件(秘宝.md),本区展示重接归装配面 | 悬停 tooltip | 已实装 |
|
| C | 秘宝槽 | 图标槽 ×4 | 四槽壳在役、空槽占位(标题「秘宝」,悬停「秘宝槽(空)」);局内两步使用与关卡域库存随秘宝过渡形态退役——现行秘宝 = 营地同调装配件(秘宝.md),本区展示重接归装配面 | 悬停 tooltip | 已实装 |
|
||||||
| C | 奇物列表(现行标题「特性」) | 列表/图标行 | 已实装——逐件行「件名 ×N」呈现、零内部分类字样;锻造/大奖励/关卡奖励节点获得的属性提升——中循环数据,因改变战斗数学且无其他展示面准入战斗屏;与战斗内状态效果(B 区站桩)分区,防「战斗结束被清」误读 | 只读 | 已实装 |
|
| C | 奇物列表(现行标题「特性」) | 列表/图标行 | 已实装——逐件行「件名 ×N」呈现、零内部分类字样;锻造/大奖励/关卡奖励节点获得的属性提升——中循环数据,因改变战斗数学且无其他展示面准入战斗屏;与战斗内状态效果(B 区站桩)分区,防「战斗结束被清」误读 | 只读 | 已实装 |
|
||||||
| D | AP 条 | 点阵 + 按钮组 | 本轮 AP 点阵、停手按钮(左)、**RAP 点阵+数字(RAP 唯一消费口 = 弃图刷新,资源数字贴消费按钮——2026-09-26 拍板;RAP 清零可见反馈〔行动经济〕)**、弃图刷新按钮(右端·雷图右上角;RAP−8 · 本轮剩 N 次,上限 2 次为行动经济口径) | 点击提交意图 | HUD 视图拆分 |
|
| D | 行动资源侧栏(原 AP 条) | 两侧点阵 + 按钮组 | 左栏:本轮 AP 点阵、停手按钮;右栏:**RAP 点阵+数字(RAP 唯一消费口 = 弃图刷新,资源数字贴消费按钮——2026-09-26 拍板;RAP 清零可见反馈〔行动经济〕)**、图例按钮、弃图刷新按钮(RAP−8 · 本轮剩 N 次,上限 2 次为行动经济口径)。2026-11-07 顶栏搬两侧——原顶部整条 AP 条退役,数据按左/右栏分置,D 区全高归棋盘 | 点击提交意图 | HUD 视图拆分改造 |
|
||||||
| D | 棋盘视图 | 网格 | 棋盘全部格态 + 小人 + 封印印记 + 变异纹带 + 奖励身份 icon(已开格;绘制优先级 数字>小人>封印印记>奖励徽章>变异纹带>底色——徽章不进数字区,样张验收项) | 左/右键意图提交 | ✅ 已实装 |
|
| D | 棋盘地形层 | 合并岩体/连续地面 | 地面连续无缝;连通未开格(四邻)合并为抬升岩体(岩顶大板+南/东崖面+四段投影+整板悬崖);岩顶向北偏西抬升(LIFT/ESHIFT 比例见 art-bible §3.2);三关八色见 art-bible §4.1「三关棋盘环境八色」;不铺逐格瓦片;深度对象按脚底 y 排序,南侧岩体可遮住小人脚底(2026-11-07 用户裁) | 只读 | 新建(替换 cell_base_layer/tile_palette) |
|
||||||
|
| D | 棋盘浮空数字层 | 最顶层文字层 | 数字与格面字形(危/?)浮在格上方:字高 21px、2px 深墨描边、1px 浮空投影、暖白字芯、2px 双色引导线;字底阴影圆 10×6 画在开启格地面(格顶+7,位于小人之下,小人站该格时遮住圆);顶行数字越出棋盘上缘(D 区上方预留 44px);数字与引导线 z 最高,任何地形/小人/特效不遮数字与引导线;封印格身份字形走色牌、不进浮空层;普通数字色牌退役 | 只读 | 新建 |
|
||||||
|
| D | 棋盘视图 | 网格 | 棋盘全部格态 + 小人 + 封印印记 + 变异纹带 + 奖励身份 icon(已开格;信息层叠放序 浮空数字>小人>封印印记>奖励徽章/类型微光>交互反馈>变异纹带>地形底色——浮空数字永不被遮,徽章不进数字区;屏幕层序按脚底行分档:北侧贴花低于小人、南侧随岩体在前;封印印记与封印格身份色牌固定低于小人,样张验收项) | 左/右键意图提交 | 改造 |
|
||||||
| D | 悬停预承诺光标 | 光标态 | 移动/挖/封印三语义光标 + 目标格边框高亮 | 自动 | 新建(排雷玩法×6③) |
|
| D | 悬停预承诺光标 | 光标态 | 移动/挖/封印三语义光标 + 目标格边框高亮 | 自动 | 新建(排雷玩法×6③) |
|
||||||
| D | 可挖域指示 | 常驻微高亮 | 小人 8 向相邻可操作格 | 自动 | 新建(排雷玩法×6③) |
|
| D | 可挖域指示 | 常驻微高亮 | 小人 8 向相邻可操作格 | 自动 | 新建(排雷玩法×6③) |
|
||||||
| D | 移动路径预览 | 路径高亮 | 悬停已开格显示 BFS 路径(合法性指示) | 自动 | 新建(排雷玩法×6⑤,裁决见下) |
|
| D | 移动路径预览 | 路径高亮 | 悬停已开格显示 BFS 路径(合法性指示) | 自动 | 新建(排雷玩法×6⑤,裁决见下) |
|
||||||
@@ -174,7 +219,7 @@
|
|||||||
**布局决策 3 — 移动路径预览 = 合法性指示**(排雷玩法×6⑤ 悬案裁决):悬停已开格时高亮 BFS 路径(小人蓝细线点迹),移动执行为 ≤150ms 短滑。
|
**布局决策 3 — 移动路径预览 = 合法性指示**(排雷玩法×6⑤ 悬案裁决):悬停已开格时高亮 BFS 路径(小人蓝细线点迹),移动执行为 ≤150ms 短滑。
|
||||||
- 备选(不采纳):穿行动画轨道——移动免费高频,动画时间税违反 P4 点击摩擦护栏(每轮输入动作:AP ≤2 的观测假设);正式版若 playtest 反馈"移动太瞬"再议
|
- 备选(不采纳):穿行动画轨道——移动免费高频,动画时间税违反 P4 点击摩擦护栏(每轮输入动作:AP ≤2 的观测假设);正式版若 playtest 反馈"移动太瞬"再议
|
||||||
|
|
||||||
**布局决策 4 — 弃图刷新 = 挖掘期当场换图(2026-09-12 用户拍板)**:按钮置 AP 条右端(雷图右上角)。点击即当轮就地换新图继续挖——AP 不重置、剩余 AP 保留,RAP−8,本轮上限 2 次。
|
**布局决策 4 — 弃图刷新 = 挖掘期当场换图(2026-09-12 用户拍板;2026-11-07 按钮位随顶栏搬两侧改到 D 区右栏)**:按钮置 D 区右栏(贴棋盘右缘)。点击即当轮就地换新图继续挖——AP 不重置、剩余 AP 保留,RAP−8,本轮上限 2 次。
|
||||||
- **上游修订(OQ11)**:① 行动经济 Active 相位受理刷新意图 + 每轮上限 2 次(Waiting 代理退役)② 排雷玩法装板受理域增 Active·仅刷新路径 ③ 编排 owner = **战斗结算的挖掘期刷新编排**(行动经济扣费 → 排雷玩法退役旧板 → 棋盘生成出新图 → 排雷玩法装板 → 地图战斗资源摇奖励恰一次;无结算段、无轮次结束——战斗结算编排唯一性原则保持)④ 旧板封印印记随旧板**作废**(零兑付、封印 AP 不返还——排雷玩法 EC11 全量重置承载;确认微交互须显式提示)。**经济预警**:当场刷新无结算发生,原「敌方时间税」自惩失效——行动经济 OQ3 弃图率/刷新率预警阈值联动复核。
|
- **上游修订(OQ11)**:① 行动经济 Active 相位受理刷新意图 + 每轮上限 2 次(Waiting 代理退役)② 排雷玩法装板受理域增 Active·仅刷新路径 ③ 编排 owner = **战斗结算的挖掘期刷新编排**(行动经济扣费 → 排雷玩法退役旧板 → 棋盘生成出新图 → 排雷玩法装板 → 地图战斗资源摇奖励恰一次;无结算段、无轮次结束——战斗结算编排唯一性原则保持)④ 旧板封印印记随旧板**作废**(零兑付、封印 AP 不返还——排雷玩法 EC11 全量重置承载;确认微交互须显式提示)。**经济预警**:当场刷新无结算发生,原「敌方时间税」自惩失效——行动经济 OQ3 弃图率/刷新率预警阈值联动复核。
|
||||||
- 备选(已否决):结算期决策提示(Waiting 内联)——结算期不做刷新决策(用户拍板);挖掘期预承诺 stop+reroll 复合——决策即终轮,不符「换图继续挖」语义。
|
- 备选(已否决):结算期决策提示(Waiting 内联)——结算期不做刷新决策(用户拍板);挖掘期预承诺 stop+reroll 复合——决策即终轮,不符「换图继续挖」语义。
|
||||||
|
|
||||||
@@ -205,20 +250,109 @@
|
|||||||
│ ├─ 结算明细带 ────────────────────────────────────────────────────────────┤ │
|
│ ├─ 结算明细带 ────────────────────────────────────────────────────────────┤ │
|
||||||
│ │ ▸上轮: 主角攻击3→蛆虫-3 | 攻击+50%(1结算) | 警觉+1×2 … │ │
|
│ │ ▸上轮: 主角攻击3→蛆虫-3 | 攻击+50%(1结算) | 警觉+1×2 … │ │
|
||||||
│ └────────────────────────────────────────────────────────────────────────┘ │
|
│ └────────────────────────────────────────────────────────────────────────┘ │
|
||||||
├─[C] 角色信息 ─────────┬─[D] 扫雷图 ───────────────────────────────────────────┤
|
├─[C] 角色信息 ─────────┬─[D] 扫雷图(顶栏已搬两侧) ───────────────────────────┤
|
||||||
│ ┌──────────────────┐ │ ┌─────────────────────────────────────────────────┐ │
|
│ ┌──────────────────┐ │ ┌──────┐ ┌───────────────────────────┐ ┌──────┐ │
|
||||||
│ │ 攻击 6 (+50%) │ │ │ AP ●●●●●○○○ 5/8 RAP ▓▓▓░ 3/8 │ │
|
│ │ 攻击 6 (+50%) │ │ │ AP │ │ (上方 44px 留白) │ │ RAP │ │
|
||||||
│ │ 护甲 AC 12 │ │ │ [⏹停手] [?图例] [↻刷新 8|剩2] │ │
|
│ │ 护甲 AC 12 │ │ │ ●●●● │ │ 1 2 ░ 3 ... │ │ ▓▓▓░ │ │
|
||||||
│ ├──────────────────┤ │ │ ┌─toast────────────┐ │ │
|
│ ├──────────────────┤ │ │ ●○○○ │ │ ╱│ ╱│ ... │ │ 3/8 │ │
|
||||||
│ │ 秘宝槽 │ │ │ │AP不足·剩0点 │ 12 12 1 ░ 2 ▓▓ ▓▓ │ │
|
│ │ 秘宝槽 │ │ │ 5/8 │ │ ┌───────────────────────┐ │ │[?图例]│ │
|
||||||
│ │ ◇ ◇ ◇ ◇ │ │ │ └──────────────────┘ 12 █ 1 1 2 ▓▓ ▓▓ │ │
|
│ │ ◇ ◇ ◇ ◇ │ │ │ │ │ │ 岩体顶面(合并岩体) │ │ │[↻刷新]│ │
|
||||||
│ ├──────────────────┤ │ │ 1 2 2 🚩 █ 2 1 1 ▓▓ 👫 1 1 ░ │ │
|
│ ├──────────────────┤ │ │[⏹停手]│ │ │ 南/东崖面+四段投影 │ │ │ 8|剩2 │ │
|
||||||
│ │ 特性(奇物) │ │ │ ░ 1 ▓▓ 👫 1 1 ░ ▓▓ 1 1 ░ ░ 2 │ │
|
│ │ 特性(奇物) │ │ │ │ │ │ 1 2 👫 1 1 ░ 2 │ │ └──────┘ │
|
||||||
│ │ 锻造+2攻 │ │ │ ▓▓ 1 1 ░ ░ 2 ▓▓ │ │
|
│ │ 锻造+2攻 │ │ │ │ │ │ ▓▓ 1 1 ░ ░ 2 ▓▓ │ │ │
|
||||||
│ │ (空态=隐藏) │ │ │ ( █=可挖域微光 👫=小人) │ │
|
│ │ (空态=隐藏) │ │ └──────┘ └───────────────────────────┘ │ │
|
||||||
│ └──────────────────┘ │ └─────────────────────────────────────────────────┘ │
|
│ └──────────────────┘ │ 左栏 AP 棋盘居中·浮空数字最顶 右栏 RAP │
|
||||||
└───────────────────────┴──────────────────────────────────────────────────────┘
|
└───────────────────────┴──────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
> **D 区结构注记(2026-11-07 用户裁)**:原顶部 AP 条整条退役,AP 在左栏、RAP/图例/弃图刷新在右栏;棋盘占 D 区全高,上方 44px 留白给顶行浮空数字越出棋盘;棋盘地形为合并岩体+南/东崖面,浮空数字+引导线为最顶层。
|
||||||
|
|
||||||
|
### D 区布局与棋盘画法预览(2026-11-07 用户人审通过,内嵌备查)
|
||||||
|
|
||||||
|
> 预览依据 = art-bible §3.2/§4.1(v3.51)+本节布局表与格边公式。效果图是目标画面;像素判据以 1280×800 基座档钉死,实现批按此冻结基线(test-conventions §8.2)。
|
||||||
|
|
||||||
|
<svg viewBox="0 0 1036 548" width="100%" style="min-width:760px" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="battle-d-title battle-d-desc">
|
||||||
|
<title id="battle-d-title">D 区布局——顶栏搬两侧、棋盘全高、上方 44px 浮空数字预留</title>
|
||||||
|
<desc id="battle-d-desc">D 区 1036×548:左栏 200px 放 AP 与停手,右栏 200px 放 RAP、图例、弃图刷新;棋盘 12×12 格 38px 居中,上方留白 44px,下方 12px+悬崖 8px。</desc>
|
||||||
|
<rect width="1036" height="548" fill="#221C15"/>
|
||||||
|
<rect x="0" y="0" width="200" height="548" fill="#1F1A14"/>
|
||||||
|
<rect x="836" y="0" width="200" height="548" fill="#1F1A14"/>
|
||||||
|
<text x="16" y="28" font-size="14" fill="#E8DCC8">左栏 · AP</text>
|
||||||
|
<text x="852" y="28" font-size="14" fill="#E8DCC8">右栏 · RAP</text>
|
||||||
|
<g fill="#E8C878">
|
||||||
|
<circle cx="24" cy="70" r="7"/><circle cx="50" cy="70" r="7"/><circle cx="76" cy="70" r="7"/><circle cx="102" cy="70" r="7"/><circle cx="128" cy="70" r="7"/>
|
||||||
|
<circle cx="24" cy="96" r="7"/><circle cx="50" cy="96" r="7"/><circle cx="76" cy="96" r="7" opacity="0.35"/><circle cx="102" cy="96" r="7" opacity="0.35"/><circle cx="128" cy="96" r="7" opacity="0.35"/>
|
||||||
|
</g>
|
||||||
|
<rect x="16" y="126" width="120" height="34" rx="5" fill="#342B20" stroke="#60503A"/>
|
||||||
|
<text x="76" y="148" font-size="14" fill="#E8DCC8" text-anchor="middle">停手</text>
|
||||||
|
<g fill="#7EBAF0"><circle cx="856" cy="70" r="6"/><circle cx="880" cy="70" r="6"/><circle cx="904" cy="70" r="6"/><circle cx="928" cy="70" r="6" opacity="0.35"/></g>
|
||||||
|
<text x="944" y="76" font-size="15" fill="#CBE4FA">3</text>
|
||||||
|
<rect x="852" y="100" width="100" height="34" rx="5" fill="#342B20" stroke="#60503A"/><text x="902" y="122" font-size="14" fill="#E8DCC8" text-anchor="middle">图例</text>
|
||||||
|
<rect x="852" y="144" width="150" height="34" rx="5" fill="#342B20" stroke="#60503A"/><text x="927" y="166" font-size="14" fill="#E8DCC8" text-anchor="middle">弃图刷新</text>
|
||||||
|
<text x="852" y="198" font-size="12" fill="#9C8A6C">RAP−8 · 剩 2 次</text>
|
||||||
|
|
||||||
|
<rect x="200" y="0" width="636" height="548" fill="#221C15"/>
|
||||||
|
<line x1="279" y1="44" x2="757" y2="44" stroke="#F2C14E" stroke-width="2" stroke-dasharray="6 4"/>
|
||||||
|
<text x="518" y="30" font-size="14" fill="#F2C14E" text-anchor="middle">上方 44px · 浮空数字越出棋盘</text>
|
||||||
|
|
||||||
|
<rect x="279" y="44" width="478" height="478" fill="#695038"/>
|
||||||
|
<!-- 合并岩体示意:顶面上移 17、左移 4;南/东崖面沉在格内 -->
|
||||||
|
<g>
|
||||||
|
<rect x="275" y="27" width="120" height="38" fill="#9C8462"/>
|
||||||
|
<rect x="275" y="65" width="120" height="17" fill="#403325"/>
|
||||||
|
<rect x="275" y="65" width="120" height="2" fill="#C9AF83"/>
|
||||||
|
<rect x="275" y="82" width="120" height="16" fill="#000" opacity="0.18"/>
|
||||||
|
<rect x="355" y="27" width="38" height="38" fill="#9C8462"/>
|
||||||
|
<rect x="389" y="27" width="4" height="38" fill="#403325"/>
|
||||||
|
<rect x="393" y="27" width="16" height="38" fill="#000" opacity="0.16"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect x="435" y="27" width="38" height="38" fill="#9C8462"/>
|
||||||
|
<rect x="435" y="65" width="38" height="17" fill="#403325"/>
|
||||||
|
<rect x="435" y="65" width="38" height="2" fill="#C9AF83"/>
|
||||||
|
<rect x="435" y="82" width="38" height="16" fill="#000" opacity="0.18"/>
|
||||||
|
<rect x="555" y="27" width="80" height="38" fill="#9C8462"/>
|
||||||
|
<rect x="555" y="65" width="80" height="17" fill="#403325"/>
|
||||||
|
<rect x="555" y="65" width="80" height="2" fill="#C9AF83"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect x="275" y="107" width="78" height="38" fill="#9C8462"/>
|
||||||
|
<rect x="275" y="145" width="78" height="17" fill="#403325"/>
|
||||||
|
<rect x="275" y="145" width="78" height="2" fill="#C9AF83"/>
|
||||||
|
<rect x="353" y="107" width="4" height="38" fill="#403325"/>
|
||||||
|
</g>
|
||||||
|
<!-- 浮空数字示意:暖白字芯 + 2px 深墨描边(八向偏移)+ 双色引导线 + 阴影圆 -->
|
||||||
|
<g>
|
||||||
|
<circle cx="434" cy="51" r="5" fill="#100C08" opacity="0.55"/>
|
||||||
|
<line x1="433" y1="32" x2="433" y2="48" stroke="#1A140E" stroke-width="2"/>
|
||||||
|
<line x1="434" y1="32" x2="434" y2="48" stroke="#E8D3AB" stroke-width="1"/>
|
||||||
|
<g font-family="monospace" font-size="21" text-anchor="middle" fill="#1A140E">
|
||||||
|
<text x="426" y="27">2</text><text x="430" y="27">2</text>
|
||||||
|
<text x="426" y="31">2</text><text x="430" y="31">2</text>
|
||||||
|
<text x="424" y="29">2</text><text x="432" y="29">2</text>
|
||||||
|
<text x="428" y="25">2</text><text x="428" y="33">2</text>
|
||||||
|
</g>
|
||||||
|
<text x="428" y="29" font-family="monospace" font-size="21" text-anchor="middle" fill="#F0E2C8">2</text>
|
||||||
|
</g>
|
||||||
|
<text x="279" y="540" font-size="12" fill="#9C8A6C">棋盘 478×478(12×12 · 格 38 · 间距 2)</text>
|
||||||
|
<text x="757" y="540" font-size="12" fill="#9C8A6C" text-anchor="end">悬崖 8 · 下方 12</text>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
**像素判据(1280×800 基座档;实现批按此冻结基线)**
|
||||||
|
|
||||||
|
| 判据 | 读数 |
|
||||||
|
|---|---|
|
||||||
|
| D 区 | x 244–1280、y 252–800,1036×548 |
|
||||||
|
| 侧栏 | 左栏 x 244–444、右栏 x 1080–1280,各宽 200(布局表 `side_rail_w`) |
|
||||||
|
| 棋盘 12×12 | 格边 38、格间距 2、外框 478×478;原点 x=523、y=296;棋盘底 774、悬崖到 782、屏底余 18 |
|
||||||
|
| 棋盘 14×14 | 格边 32、外框 474×474;原点 x=525、y=296;棋盘底 770、悬崖到 778、屏底余 22 |
|
||||||
|
| 上方预留 | y 252–296 共 44;顶行字视觉顶 y=258(含 2px 描边),距 D 区上缘 6 |
|
||||||
|
| 浮空字 | 字高 21、字底距格顶 15、视觉顶距格顶 38;2px 深墨描边+1px 浮空投影;引导线 2px(左深右浅),自格顶−12 到格顶+4;字底阴影圆 10×6、圆心格顶+7,画在开启格地面、位于小人之下 |
|
||||||
|
| 岩体投影 | LIFT=round(38×0.435)=17;ESHIFT=round(38×0.109)=4;相邻岩顶搭接 2;板边岩顶外延 ESHIFT;南崖高 17、宽 42(38+4)、顶缘 2px 口沿高光取本关受光棱(dungeon #C9AF83)+1px 深墨线;东崖宽 4、高 55(38+17);北/西临空缘 2px 主亮棱+2px 次亮棱+外 2px 深墨边;南/东临空缘 2px 深墨内缘+3 段×2px 内阴影(自缘内 0.217×格边起,α0.27/0.16/0.08);南/东投影 4 段×4px 渐隐(α0.44/0.30/0.16/0.07);整板悬崖 8 |
|
||||||
|
| 深度遮挡 | 深度键 = 脚底格底 y;岩体取最南格格底;升序绘制;南侧岩体(键更大)画在小人之后、遮住小人脚底 |
|
||||||
|
| 层序 | 地面(封印格地面铺受光棱色封印石)→投影→开启格地面阴影圆(小人之下)→深度对象(岩体+小人;格件顶面贴花〔微光/变异〕与交互反馈随脚底行同序——北侧低于小人、南侧随岩体在前;封印印记与封印格身份色牌固定低于小人)→浮空数字+引导线(z 最高) |
|
||||||
|
| 顶面/视觉 rect | 墙格顶面 rect = 格矩形左上偏移 (−ESHIFT,−LIFT)、边长=格边;整格视觉 rect = 顶面向右补 ESHIFT、向下补 LIFT;微光/变异锚顶面 rect;封印锚逻辑格心;迷雾黑罩覆盖顶面+南面+东面三块 |
|
||||||
|
| 悬停/路径 rect | 墙格悬停金框按顶面 rect;已开地面格悬停/路径点迹按逻辑 rect(不偏移) |
|
||||||
|
| 禁裁切 | 顶行数字、引导线、阴影圆全部落在 D 区内;任何地形/小人/特效不遮浮空数字与引导线 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -226,7 +360,7 @@
|
|||||||
|
|
||||||
| State / Variant | Trigger | What Changes |
|
| State / Variant | Trigger | What Changes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **挖掘阶段(默认态)** | 轮次开始 / 结算完毕回 Active 相位 | B 区敌人待机(意图徽标全程可见——敌人系统 Rule 8⑤),D 区棋盘可交互,AP 条点亮;能量 2/10,唯悬停呼吸微光在动(§2.1) |
|
| **挖掘阶段(默认态)** | 轮次开始 / 结算完毕回 Active 相位 | B 区敌人待机(意图徽标全程可见——敌人系统 Rule 8⑤),D 区棋盘可交互,左右行动资源侧栏点亮;能量 2/10,唯悬停呼吸微光在动(§2.1) |
|
||||||
| **结算阶段** | round_end 触发(AP 尽/停手/清图) | D 区锁输入(棋盘去饱和 + 金橙色相偏移,明度不变,数字保持全对比);B 区播放五段编排演出(授予段 → 增益/减益段 → 战斗段 → 衰减段 → 判定段,战斗结算 段序冻结);明细带按结算期档展开(高读 `log_band_h_settle`)逐行滚动;阶段指示→"结算中";能量 7/10 |
|
| **结算阶段** | round_end 触发(AP 尽/停手/清图) | D 区锁输入(棋盘去饱和 + 金橙色相偏移,明度不变,数字保持全对比);B 区播放五段编排演出(授予段 → 增益/减益段 → 战斗段 → 衰减段 → 判定段,战斗结算 段序冻结);明细带按结算期档展开(高读 `log_band_h_settle`)逐行滚动;阶段指示→"结算中";能量 7/10 |
|
||||||
| **清图瞬间** | 全部安全格开完 | 金粒喷泉 + 彩纸 3–5s 即收(§2.3);清图奖励行强调呈现(H2,地图战斗资源×④——金框高亮行);随后换新图 install |
|
| **清图瞬间** | 全部安全格开完 | 金粒喷泉 + 彩纸 3–5s 即收(§2.3);清图奖励行强调呈现(H2,地图战斗资源×④——金框高亮行);随后换新图 install |
|
||||||
| **完美封印高光** | 战斗结算高光判定(全图标中/零误标类) | 全屏喝彩级反馈(§2.2 最高档):金光带加倍扫射 + 「完美封印 ×2」横幅——P2 爆发兑现节点(创意风险 #2 落点) |
|
| **完美封印高光** | 战斗结算高光判定(全图标中/零误标类) | 全屏喝彩级反馈(§2.2 最高档):金光带加倍扫射 + 「完美封印 ×2」横幅——P2 爆发兑现节点(创意风险 #2 落点) |
|
||||||
@@ -239,7 +373,7 @@
|
|||||||
| **调试变体** | 测试模式 | 调试浮窗入口发布态恒隐(无 UI 开启口;开发期临时启用=本地改该字段缺省、不提交——调参面板已退役);Playtest 诊断按钮(卡死转储) |
|
| **调试变体** | 测试模式 | 调试浮窗入口发布态恒隐(无 UI 开启口;开发期临时启用=本地改该字段缺省、不提交——调参面板已退役);Playtest 诊断按钮(卡死转储) |
|
||||||
|
|
||||||
**拒绝/作废子态**(排雷玩法×6⑥、行动经济双源——每次拒绝玩家可感知):
|
**拒绝/作废子态**(排雷玩法×6⑥、行动经济双源——每次拒绝玩家可感知):
|
||||||
- 棋盘面拒绝(细分原因:非相邻/挖封印格等)→ 目标格 危险红 #A8321F 边框闪 + toast 文案(拒绝语义红族——现行封印黑)(图标+文案冗余,色弱清单 #7)
|
- 棋盘面拒绝(细分原因:非相邻/挖已封印格等)→ 目标格 危险红 #A8321F 边框闪 + toast 文案(拒绝语义红族——现行封印黑)(图标+文案冗余,色弱清单 #7)
|
||||||
- 资源面拒绝(AP 不足/RAP 不足)→ AP/RAP 数字脉冲 + toast「AP 不足 · 剩 0 点」
|
- 资源面拒绝(AP 不足/RAP 不足)→ AP/RAP 数字脉冲 + toast「AP 不足 · 剩 0 点」
|
||||||
- voided(stop 被作废等)→ toast「本轮已清图,停手未执行 · 剩余 AP 已作废」——防静默改判读感欺骗
|
- voided(stop 被作废等)→ toast「本轮已清图,停手未执行 · 剩余 AP 已作废」——防静默改判读感欺骗
|
||||||
|
|
||||||
@@ -253,9 +387,10 @@
|
|||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| 未开相邻格 | 挖掘 | 左键 | 格碎裂 + 连锁展开(免费)+ 奖励身份揭显 | 意图入当帧批次 → 排雷玩法的意图批次提交 |
|
| 未开相邻格 | 挖掘 | 左键 | 格碎裂 + 连锁展开(免费)+ 奖励身份揭显 | 意图入当帧批次 → 排雷玩法的意图批次提交 |
|
||||||
| 已开格 | 移动 | 左键 | 悬停时路径预览高亮(布局决策 3);执行 ≤150ms 短滑 | 意图入批(BFS 移动,免费) |
|
| 已开格 | 移动 | 左键 | 悬停时路径预览高亮(布局决策 3);执行 ≤150ms 短滑 | 意图入批(BFS 移动,免费) |
|
||||||
| 未开格 | 封印 | 右键 | 封印印记落下(封印黑) | 意图入批(1 AP / 免费;已封印格右键无操作——封印印记无移除手段,封印不可逆) |
|
| 未开格 | 封印 | 右键 | **受理即揭示**:墙格换已揭示地面 + 封印印记落下(封印黑)+ 格下身份揭显(危/数字,垫色牌) | 意图入批(1 AP / 免费;受理当场零兑付——兑付在轮末判定批) |
|
||||||
|
| 已封印格(已揭示) | 无 | 左键/右键 | 禁止光标 + 悬停说明(封印格无可用动作) | 零意图(不入批——封印格拒绝挖掘、不可通行、不可再封印;封印印记无移除手段,封印不可逆) |
|
||||||
| 停手按钮 | 主动结束轮次 | 左键 | 按钮下压 + AP→RAP 飞行数字 | 停手随当帧意图批次提交(**经排雷玩法批次,不直调行动经济**——单意图帧批次契约) |
|
| 停手按钮 | 主动结束轮次 | 左键 | 按钮下压 + AP→RAP 飞行数字 | 停手随当帧意图批次提交(**经排雷玩法批次,不直调行动经济**——单意图帧批次契约) |
|
||||||
| 弃图刷新按钮(雷图右上角) | 当轮就地换图继续挖 | 左键 | 确认微交互(RAP−8 代价显式 + 旧板弃置提示);RAP<8 → 资源面拒绝可见(行动经济 EC13) | 刷新意图提交(**Active 相位当场换图继续挖**——AP 不重置、本轮剩 N 次扣减;受理口径见布局决策 4/OQ11) |
|
| 弃图刷新按钮(D 区右栏) | 当轮就地换图继续挖 | 左键 | 确认微交互(RAP−8 代价显式 + 旧板弃置提示);RAP<8 → 资源面拒绝可见(行动经济 EC13) | 刷新意图提交(**Active 相位当场换图继续挖**——AP 不重置、本轮剩 N 次扣减;受理口径见布局决策 4/OQ11) |
|
||||||
| 图例按钮 | 开图例 | 左键 | 模态 overlay | 恒可开(图例条目恒在) |
|
| 图例按钮 | 开图例 | 左键 | 模态 overlay | 恒可开(图例条目恒在) |
|
||||||
| 状态小图标(B 区站桩) | 悬停 | hover | 状态 tooltip(来源+语义+剩余结算次数) | 只读 |
|
| 状态小图标(B 区站桩) | 悬停 | hover | 状态 tooltip(来源+语义+剩余结算次数) | 只读 |
|
||||||
| 胜利 overlay | 下一节点 | 左键 | → 关卡画面(选路枢纽)/ 关卡结算(末节点) | 关卡推进方推进 |
|
| 胜利 overlay | 下一节点 | 左键 | → 关卡画面(选路枢纽)/ 关卡结算(末节点) | 关卡推进方推进 |
|
||||||
@@ -265,7 +400,7 @@
|
|||||||
|
|
||||||
**复合意图(排雷玩法评估项)**:点击远格 = 自动 move+dig 的两击摩擦消解——**MVP 不做**(免费移动高频,两击摩擦符合 P4 ≤2 观测假设;排雷玩法 L298 评估项在案)。
|
**复合意图(排雷玩法评估项)**:点击远格 = 自动 move+dig 的两击摩擦消解——**MVP 不做**(免费移动高频,两击摩擦符合 P4 ≤2 观测假设;排雷玩法 L298 评估项在案)。
|
||||||
|
|
||||||
**可挖域常驻指示**:小人 8 向相邻未开格呼吸微光(§2.1 唯一在动的元素);不可挖域(非相邻)悬停显示禁止光标 + 首次 toast 提示「需先走近(点击已开格移动,免费)」。
|
**可挖域常驻指示**:小人 8 向相邻未开格呼吸微光(§2.1 唯一在动的元素);不可挖域(非相邻)悬停显示禁止光标 + 首次 toast 提示「需先走近(点击已开格移动,免费)」。已封印格(含相邻)悬停显示禁止光标——封印格拒绝挖掘、不可通行、不可再封印,无动作可发(封印格呈现规格见「封印格呈现预览」节)。
|
||||||
|
|
||||||
**chord 肌肉记忆首遇提示**(排雷玩法×6③):经典扫雷玩家首日尝试双击快开时,非模态 toast 每 run 一次:「本作无双击快开——封印后轮末自动判定标中;点数字格可移动小人」(含排雷玩法登记锚点「点击数字格 = 移动小人」)。文案定稿权归实现期文案 pass。
|
**chord 肌肉记忆首遇提示**(排雷玩法×6③):经典扫雷玩家首日尝试双击快开时,非模态 toast 每 run 一次:「本作无双击快开——封印后轮末自动判定标中;点数字格可移动小人」(含排雷玩法登记锚点「点击数字格 = 移动小人」)。文案定稿权归实现期文案 pass。
|
||||||
|
|
||||||
@@ -282,7 +417,7 @@
|
|||||||
| 弃图刷新(挖掘期,非轮出口) · 刷新尝试遥测 | 刷新使用(难度曲线与Boss OQ6)与行动经济 OQ3 预警阈值观测;每轮 0–2 次(布局决策 4 cap=2) | {受理结果: 受理 / 拒因 RAP 不足 / 拒因触上限, 本轮第几次刷新: 1..2} |
|
| 弃图刷新(挖掘期,非轮出口) · 刷新尝试遥测 | 刷新使用(难度曲线与Boss OQ6)与行动经济 OQ3 预警阈值观测;每轮 0–2 次(布局决策 4 cap=2) | {受理结果: 受理 / 拒因 RAP 不足 / 拒因触上限, 本轮第几次刷新: 1..2} |
|
||||||
| 拒绝/voided · 拒绝遥测 | 拒绝来源(板面/资源/相位三源)与细分原因 | {拒绝来源: 板面/资源/相位, 细分原因} |
|
| 拒绝/voided · 拒绝遥测 | 拒绝来源(板面/资源/相位三源)与细分原因 | {拒绝来源: 板面/资源/相位, 细分原因} |
|
||||||
| 提示触发/关闭 · 提示展示遥测 | 提示类型 | {提示类型: chord 提示 / 无相邻可挖格} |
|
| 提示触发/关闭 · 提示展示遥测 | 提示类型 | {提示类型: chord 提示 / 无相邻可挖格} |
|
||||||
| 呈现订阅(不改核心) | 排雷玩法三事件 / [战斗结算](../systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)步骤流(9 类行协议,含终局判定行) / 战斗结束 / 关卡完成 | 载荷 schema 成文义务见 §Data Requirements(HUD框架硬性要求) |
|
| 呈现订阅(不改核心) | 排雷玩法三事件 / [战斗结算](../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)步骤流(9 类行协议,含终局判定行) / 战斗结束 / 关卡完成 | 载荷 schema 成文义务见 §Data Requirements(HUD框架硬性要求) |
|
||||||
|
|
||||||
**持久状态写入**全部经组合根唯一路径(意图批次提交 / 刷新意图提交 / 关卡推进)——UI 层禁直调核心写(架构七原则"依赖单向组合根")。
|
**持久状态写入**全部经组合根唯一路径(意图批次提交 / 刷新意图提交 / 关卡推进)——UI 层禁直调核心写(架构七原则"依赖单向组合根")。
|
||||||
|
|
||||||
@@ -296,7 +431,7 @@
|
|||||||
| 挖掘→结算 | 明细带自底展开(150ms)+ 棋盘去饱和 + 金橙色相偏移 + 阶段指示翻转 | §2.2 色彩转金橙主导、饱和拉高、明度不变(状态区分经饱和/色相——art-bible §2) |
|
| 挖掘→结算 | 明细带自底展开(150ms)+ 棋盘去饱和 + 金橙色相偏移 + 阶段指示翻转 | §2.2 色彩转金橙主导、饱和拉高、明度不变(状态区分经饱和/色相——art-bible §2) |
|
||||||
| 结算逐行兑现 | 光带自棋盘行起点横扫 → 开格化箭雨/印记化暴击弹道飞向敌人立绘 → 受击闪白 + 血条直角递减 | §2.2 承载元素;因果全程可见可归因(P2) |
|
| 结算逐行兑现 | 光带自棋盘行起点横扫 → 开格化箭雨/印记化暴击弹道飞向敌人立绘 → 受击闪白 + 血条直角递减 | §2.2 承载元素;因果全程可见可归因(P2) |
|
||||||
| 清图换新图 | 金粒喷泉 3–5s → 旧图碎裂淡出 → 新图 install 淡入 | §2.3 短促丰收不拖节奏 |
|
| 清图换新图 | 金粒喷泉 3–5s → 旧图碎裂淡出 → 新图 install 淡入 | §2.3 短促丰收不拖节奏 |
|
||||||
| RAP 清零(战斗结束) | RAP 数字滚动归零(D 区 AP 条)+ 「随战斗结束消散」微文案 | 行动经济可见反馈义务 |
|
| RAP 清零(战斗结束) | RAP 数字滚动归零(D 区右栏)+ 「随战斗结束消散」微文案 | 行动经济可见反馈义务 |
|
||||||
| 敌人死亡 | 血条直角递减至零 → 卡体灰化 + 碎裂退场(禁瞬消) | 敌人系统资产下限(同等 blocking);动画密度归战斗表现 |
|
| 敌人死亡 | 血条直角递减至零 → 卡体灰化 + 碎裂退场(禁瞬消) | 敌人系统资产下限(同等 blocking);动画密度归战斗表现 |
|
||||||
| 状态图标行全清(战斗结束) | 状态逐枚化光收回(B 区站桩图标行)+ 「状态随战斗结束消散」微文案 | 增益状态×4④;RAP 清零同款先例 |
|
| 状态图标行全清(战斗结束) | 状态逐枚化光收回(B 区站桩图标行)+ 「状态随战斗结束消散」微文案 | 增益状态×4④;RAP 清零同款先例 |
|
||||||
| 胜利 | 蜡封自上落下弹跳定格 → 碎砖拼纹章 → overlay 暖金渐显 | §2.4 克制不狂欢 |
|
| 胜利 | 蜡封自上落下弹跳定格 → 碎砖拼纹章 → overlay 暖金渐显 | §2.4 克制不狂欢 |
|
||||||
@@ -313,7 +448,7 @@
|
|||||||
| BFS 移动路径 | 排雷玩法 路径规划只读面 | Read | 布局决策 3 合法性指示消费 |
|
| BFS 移动路径 | 排雷玩法 路径规划只读面 | Read | 布局决策 3 合法性指示消费 |
|
||||||
| 拒绝原因 | 排雷玩法 细分原因封闭枚举 + 行动经济 资源面 | Read | 三源(板面/资源/相位)映射文案——呈现层契约成文;资源面原因无上游载荷(行动经济仅回受理与否,细分原因仅调试诊断可见),客户端按动作上下文推断 |
|
| 拒绝原因 | 排雷玩法 细分原因封闭枚举 + 行动经济 资源面 | Read | 三源(板面/资源/相位)映射文案——呈现层契约成文;资源面原因无上游载荷(行动经济仅回受理与否,细分原因仅调试诊断可见),客户端按动作上下文推断 |
|
||||||
| AP / RAP / 本轮刷新计数 | 行动经济 | Read | 常显;刷新入口可用性 = RAP 读数客户端预判(RAP≥8)+ 刷新意图提交的受理回执(行动经济 无刷新可用性预查询——仅受理与否的回执 + 只读观测量;行动经济 EC13 拒绝合法可见) |
|
| AP / RAP / 本轮刷新计数 | 行动经济 | Read | 常显;刷新入口可用性 = RAP 读数客户端预判(RAP≥8)+ 刷新意图提交的受理回执(行动经济 无刷新可用性预查询——仅受理与否的回执 + 只读观测量;行动经济 EC13 拒绝合法可见) |
|
||||||
| 结算流水行(9 类封闭协议) | [战斗结算](../systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋) 流水协议 | Read | 逐行来源标注(P2);未生效类行(奖励未生效)聚合计数呈现 |
|
| 结算流水行(9 类封闭协议) | [战斗结算](../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋) 流水协议 | Read | 逐行来源标注(P2);未生效类行(奖励未生效)聚合计数呈现 |
|
||||||
| 判定胜负 | 战斗结算 判定段 | Read | 终局画面数据锚 |
|
| 判定胜负 | 战斗结算 判定段 | Read | 终局画面数据锚 |
|
||||||
| 敌单位 生命/顺位/摇定动作(技能标识·类型·名称)/敌方增益/敌单位标识/存活 | 敌人系统 只读面(经战斗结算呈现快照) | Read | 意图线索映射全局恒定(敌人系统×4②,技能池批三档口径);**销毁前捕获**(缺陷②教训) |
|
| 敌单位 生命/顺位/摇定动作(技能标识·类型·名称)/敌方增益/敌单位标识/存活 | 敌人系统 只读面(经战斗结算呈现快照) | Read | 意图线索映射全局恒定(敌人系统×4②,技能池批三档口径);**销毁前捕获**(缺陷②教训) |
|
||||||
| 状态效果投影(含空态/极性/溢出) | 增益状态 投影口径 | Read | 极性映射数据源 = 战斗结算效果表语义,非幅度符号(增益状态×③) |
|
| 状态效果投影(含空态/极性/溢出) | 增益状态 投影口径 | Read | 极性映射数据源 = 战斗结算效果表语义,非幅度符号(增益状态×③) |
|
||||||
@@ -332,13 +467,13 @@
|
|||||||
|
|
||||||
## Accessibility
|
## Accessibility
|
||||||
|
|
||||||
无障碍基线权威 = [HUD框架](../systems/表现与支撑/HUD框架.md)「可访问性基线」节;不再另立专项文档(2026-09-27 拍板,见 OQ2)。本 spec 内建基线承诺(呈现侧落地):
|
无障碍基线权威 = [HUD框架](../gdd/systems/表现与支撑/HUD框架.md)「可访问性基线」节;不再另立专项文档(2026-09-27 拍板,见 OQ2)。本 spec 内建基线承诺(呈现侧落地):
|
||||||
|
|
||||||
- **对比**:全部格底/面板底对数字墨 ≥4.5:1(WCAG AA)——art-bible §4.1 硬指标已可测(#33261B/#C9AF83 = 6.9:1 实测);UI 数据一律墨族素面
|
- **对比**:浮空数字按 art-bible §1.4 第一验收项的复合判据过门(四类底上 max(字芯对底,描边对底) ≥4.5 且字芯对描边 ≥4.5;最亮底岩顶实测描边对底 5.1:1);UI 数据一律墨族素面对面板底 ≥4.5:1
|
||||||
- **色弱冗余**:无任何信息仅靠色相承载——格态靠完整/碎裂形;奖励金 vs 危险红靠剪影+运动;UI 红/金强调对加图标+文案冗余;Boss 靠形状独占(art-bible §4.5 清单逐项成立)
|
- **色弱冗余**:无任何信息仅靠色相承载——格态靠完整/碎裂形;奖励金 vs 危险红靠剪影+运动;UI 红/金强调对加图标+文案冗余;Boss 靠形状独占(art-bible §4.5 清单逐项成立)
|
||||||
- **灰度可辨**:变异格纹带、格态在灰度截图下可分类(art-bible §3.2 验收标准)
|
- **灰度可辨**:变异格纹带、格态在灰度截图下可分类(art-bible §3.2 验收标准)
|
||||||
- **非色彩破坏性确认**:弃图刷新(消耗 RAP 8 点)的确认交互与常规确认**不同位**(位置通道,色弱清单 #7)
|
- **非色彩破坏性确认**:弃图刷新(消耗 RAP 8 点)的确认交互与常规确认**不同位**(位置通道,色弱清单 #7)
|
||||||
- **字号下限**:棋盘数字 ≥18px、明细带正文 ≥14px、tooltip ≥13px(1280×800 基座)
|
- **字号下限**:浮空数字字高 21px(固定,含描边视觉 25px)、明细带正文 ≥14px、tooltip ≥13px(1280×800 基座)
|
||||||
- **运动**:无闪烁 >3次/秒;结算光带为方向性扫动非频闪;提供减动效选项(§Transitions)
|
- **运动**:无闪烁 >3次/秒;结算光带为方向性扫动非频闪;提供减动效选项(§Transitions)
|
||||||
- **键盘/Gamepad**:MVP 纯鼠标可完成全部操作(technical-preferences 平台注记);**MVP 纯键盘导航/焦点序不做**(2026-09-12 拍板——回合制点击驱动,平台仅承诺纯鼠标);gamepad 导航序延后(Open Questions)
|
- **键盘/Gamepad**:MVP 纯鼠标可完成全部操作(technical-preferences 平台注记);**MVP 纯键盘导航/焦点序不做**(2026-09-12 拍板——回合制点击驱动,平台仅承诺纯鼠标);gamepad 导航序延后(Open Questions)
|
||||||
|
|
||||||
@@ -358,12 +493,16 @@
|
|||||||
|
|
||||||
**布局与可读**
|
**布局与可读**
|
||||||
|
|
||||||
- [ ] 1280×800 与 16:9 全屏(canvas_items/expand)下三区(B/C/D)无遮挡、无重叠、无内容裁切(棋盘 12×12 全部格子 + 数字完整可见)
|
- [ ] 1280×800 与 16:9 全屏(canvas_items/expand)下三区(B/C/D)无遮挡、无重叠、无内容裁切(棋盘 12×12 全部格子 + 浮空数字与引导线完整可见)
|
||||||
|
- [ ] D 区基座档读数落预览判据:左/右栏各 200、棋盘 12×12 格 38(原点 x=523、y=296)、14×14 格 32;上方 44px 预留内顶行字完整、无裁切
|
||||||
|
- [ ] 棋盘地形为合并岩体+连续地面:连通未开格共享岩顶/崖面无逐格拼缝;北/西受光棱、南/东崖面与四段投影在位;旧 16+5 瓦片路径零引用、零在库
|
||||||
|
- [ ] 浮空数字+引导线 z 最高:任何地形/小人/特效不遮数字与引导线;格顶阴影圆标出数字所属格
|
||||||
|
- [ ] 深度排序:南侧岩体画在小人之后并自然遮住小人脚底;小人所在格数字仍完整可见
|
||||||
- [ ] 进入战斗屏 ≤500ms 内可交互(棋盘 install 淡入完成后首格可点);同屏 draw calls < 200(technical-preferences 预算)
|
- [ ] 进入战斗屏 ≤500ms 内可交互(棋盘 install 淡入完成后首格可点);同屏 draw calls < 200(technical-preferences 预算)
|
||||||
- [ ] 两种格态(已开格 / 未开格)灰度截图下一眼可辨(排雷玩法×6②)
|
- [ ] 两种格态(已开格 / 未开格)灰度截图下一眼可辨(排雷玩法×6②)
|
||||||
- [ ] 悬停光标区分移动/挖/封印三语义;可挖域(8 向相邻)常驻指示;非相邻格悬停显禁止反馈(排雷玩法×6③)
|
- [ ] 悬停光标区分移动/挖/封印三语义;可挖域(8 向相邻)常驻指示;非相邻格悬停显禁止反馈(排雷玩法×6③)
|
||||||
- [ ] 已引爆危险格呈"可通行可读"(排雷玩法×6④)
|
- [ ] 已引爆危险格呈"可通行可读"(排雷玩法×6④)
|
||||||
- [ ] 全部数字对所在格底对比 ≥4.5:1;明度分层规则无违例(art-bible §2/§4.1——格底功能分档合法,格态语义由形与色相承载)
|
- [ ] 浮空数字按 art-bible §1.4 第一验收项的复合对比判据过门(四类底上 max(字芯对底,描边对底) ≥4.5 且字芯对描边 ≥4.5);明度分层规则无违例(art-bible §2/§4.1——岩顶/地面功能分档合法,格态语义由形与色相承载);棋盘普通数字绘制路径零色牌调用(封印格身份字形色牌为唯一例外)
|
||||||
|
|
||||||
**交互与反馈**
|
**交互与反馈**
|
||||||
|
|
||||||
@@ -383,7 +522,7 @@
|
|||||||
- [ ] 零合法板(棋盘生成 EC5 降级)出现时玩家侧诚实提示(toast,非静默)
|
- [ ] 零合法板(棋盘生成 EC5 降级)出现时玩家侧诚实提示(toast,非静默)
|
||||||
- [ ] 效果行数值为单次贡献值,禁止与池合成值相加呈现;零值伤害行可见不被吞;衰减行按聚合计数呈现(战斗结算 呈现细则)
|
- [ ] 效果行数值为单次贡献值,禁止与池合成值相加呈现;零值伤害行可见不被吞;衰减行按聚合计数呈现(战斗结算 呈现细则)
|
||||||
- [ ] 未生效类行(奖励未生效)携带形状冗余(icon/划线),非色相独载
|
- [ ] 未生效类行(奖励未生效)携带形状冗余(icon/划线),非色相独载
|
||||||
- [ ] 奖励徽章绘制优先级:封印印记之下、变异纹带之上、不进数字区;拾取瞬间 tier 档位可读(地图战斗资源 H1)
|
- [ ] 奖励徽章绘制优先级:封印印记之下、变异纹带之上、不遮浮空数字与引导线;拾取瞬间 tier 档位可读(地图战斗资源 H1)
|
||||||
|
|
||||||
**场景级测试**(缺项即 blocking)
|
**场景级测试**(缺项即 blocking)
|
||||||
|
|
||||||
@@ -397,8 +536,8 @@
|
|||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
1. **Player journey map——已完成(2026-09-27 拍板:不建)**:实现前补建的前提随战斗屏实装失效;情绪曲线事实源 = art-bible §2 能量档,真人体验观测与结论回流 = [体验验证清单](../../../体验验证清单.md)
|
1. **Player journey map——已完成(2026-09-27 拍板:不建)**:实现前补建的前提随战斗屏实装失效;情绪曲线事实源 = art-bible §2 能量档,真人体验观测与结论回流 = [体验验证清单](../../体验验证清单.md)
|
||||||
2. **无障碍专项文档——已完成(2026-09-27 拍板:不另立 design/accessibility-requirements.md)**:基线(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体)权威 = [HUD框架](../systems/表现与支撑/HUD框架.md)「可访问性基线」节;正式分层(文本缩放/色盲模式/按键重映射)归 [设置与本地化](../systems/表现与支撑/设置与本地化.md) 待设计问题清单 #1(设置项全集裁决时定);本 spec §Accessibility 为呈现侧落地承诺
|
2. **无障碍专项文档——已完成(2026-09-27 拍板:不另立 design/accessibility-requirements.md)**:基线(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体)权威 = [HUD框架](../gdd/systems/表现与支撑/HUD框架.md)「可访问性基线」节;正式分层(文本缩放/色盲模式/按键重映射)归 [设置与本地化](../gdd/systems/表现与支撑/设置与本地化.md) 待设计问题清单 #1(设置项全集裁决时定);本 spec §Accessibility 为呈现侧落地承诺
|
||||||
3. **interaction-patterns.md——已建成**:本 spec 引入的四 pattern(双源拒绝反馈/逐行兑现明细带/悬停预承诺光标/点阵资源显示)均已入库成文(pattern 1/3/4/5)
|
3. **interaction-patterns.md——已建成**:本 spec 引入的四 pattern(双源拒绝反馈/逐行兑现明细带/悬停预承诺光标/点阵资源显示)均已入库成文(pattern 1/3/4/5)
|
||||||
4. **战斗表现美术测试**(game-concept 已登记,战斗表现前强制):本 spec 的常驻双舞台分屏(布局决策 1)是测试的布局输入——**敌人卡形态已裁决(2026-09-20 用户看对照样张拍板):全站桩式(无框立绘+底座),主角同样站桩、状态小图标挂血条下,卡片式整体退役**;站桩式不改变分区结构。对照样张已存档(敌人卡与站桩式对照样张)
|
4. **战斗表现美术测试**(game-concept 已登记,战斗表现前强制):本 spec 的常驻双舞台分屏(布局决策 1)是测试的布局输入——**敌人卡形态已裁决(2026-09-20 用户看对照样张拍板):全站桩式(无框立绘+底座),主角同样站桩、状态小图标挂血条下,卡片式整体退役**;站桩式不改变分区结构。对照样张已存档(敌人卡与站桩式对照样张)
|
||||||
5. **移动动画形态**(布局决策 3):≤150ms 短滑为推荐值,playtest 观测「移动太瞬/太拖」反馈后调
|
5. **移动动画形态**(布局决策 3):≤150ms 短滑为推荐值,playtest 观测「移动太瞬/太拖」反馈后调
|
||||||
@@ -426,7 +565,7 @@
|
|||||||
| 排雷玩法×6 | ④ 引爆危险格可通行可读 | §AC |
|
| 排雷玩法×6 | ④ 引爆危险格可通行可读 | §AC |
|
||||||
| 排雷玩法×6 | ⑤ 路径预览裁决 | 布局决策 3 |
|
| 排雷玩法×6 | ⑤ 路径预览裁决 | 布局决策 3 |
|
||||||
| 排雷玩法×6 | ⑥ 单意图帧+voided+拒绝可感知 | §Interaction Map + §States 拒绝子态 + AC |
|
| 排雷玩法×6 | ⑥ 单意图帧+voided+拒绝可感知 | §Interaction Map + §States 拒绝子态 + AC |
|
||||||
| 行动经济 | AP/RAP 常显+刷新入口+清零反馈+双源 | §Layout D 区 AP 条(RAP 贴弃图刷新按钮——2026-09-26 信息归属拍板)+ §Transitions + AC |
|
| 行动经济 | AP/RAP 常显+刷新入口+清零反馈+双源 | §Layout D 区行动资源侧栏(RAP 贴弃图刷新按钮——2026-09-26 信息归属拍板;2026-11-07 顶栏搬两侧)+ §Transitions + AC |
|
||||||
| 战斗结算×3 | ①高光行强调呈现(封印标中金框行/清图 H2 金框行)②完美封印呈现形态 ③棋盘生成 EC5 零合法板提示/补偿/回退形态(toast 提示;补偿/回退不提供——2026-09-12 选型) | §States 高光/清图 + §States 拒绝子态 + §AC;注:结算明细屏 = 战斗结算 UX Flag 事项,由本 spec 承载 |
|
| 战斗结算×3 | ①高光行强调呈现(封印标中金框行/清图 H2 金框行)②完美封印呈现形态 ③棋盘生成 EC5 零合法板提示/补偿/回退形态(toast 提示;补偿/回退不提供——2026-09-12 选型) | §States 高光/清图 + §States 拒绝子态 + §AC;注:结算明细屏 = 战斗结算 UX Flag 事项,由本 spec 承载 |
|
||||||
| 敌人系统×4 | 意图映射/恒定/顺位/敌方池 | §Component Inventory 敌人站桩立绘 + **意图线索映射目录(敌人系统×4① 成文占位,资产定稿归战斗表现)** + AC |
|
| 敌人系统×4 | 意图映射/恒定/顺位/敌方池 | §Component Inventory 敌人站桩立绘 + **意图线索映射目录(敌人系统×4① 成文占位,资产定稿归战斗表现)** + AC |
|
||||||
| 增益状态×4 | 常显+空态/来源标注/溢出/去留 | §States 空态 + §AC |
|
| 增益状态×4 | 常显+空态/来源标注/溢出/去留 | §States 空态 + §AC |
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# 营地场景 UX spec(camp)
|
# 营地场景 UX spec(camp)
|
||||||
|
|
||||||
> 状态:v2.7(现行)
|
> 状态:v2.8(现行)
|
||||||
> 事实源:本 spec(呈现)+ [元进度](../systems/跨局循环/元进度.md)(机制)
|
> 事实源:本 spec(呈现)+ [元进度](../gdd/systems/跨局循环/元进度.md)(机制)
|
||||||
> 美术画法:[art-bible](../../art/art-bible.md) §6.2/§7.5;素材命名与路径:[asset-path-map](../../art/asset-path-map.md)
|
> 美术画法:[art-bible](../art/art-bible.md) §6.2/§7.5;素材命名与路径:[asset-path-map](../art/asset-path-map.md)
|
||||||
> 相邻:[level-map.md](level-map.md)(主菜单语境)
|
> 相邻:[level-map.md](level-map.md)(主菜单语境)
|
||||||
|
|
||||||
## 定位
|
## 定位
|
||||||
@@ -20,15 +20,15 @@
|
|||||||
| 木桩 | 天赋树 | |
|
| 木桩 | 天赋树 | |
|
||||||
| 布告板 | 奖励格图鉴 | 内容冻结未激活,点进看占位——**不是禁用态** |
|
| 布告板 | 奖励格图鉴 | 内容冻结未激活,点进看占位——**不是禁用态** |
|
||||||
| 篝火 | 离开营地回主菜单 | **必须二次确认**;命中区只含火堆、不含火焰 |
|
| 篝火 | 离开营地回主菜单 | **必须二次确认**;命中区只含火堆、不含火焰 |
|
||||||
| 帐篷 | — | 承载件,**不可点**;落地尺寸与占位范围待作者重定(待裁口径见 art-bible §6.2) |
|
| 帐篷 | — | 承载件,**不可点**;251×170 落位 (982, 335),上端遮住围墙下部;笔记本在其左下方外侧、两者不重叠 |
|
||||||
|
|
||||||
纵深=远景天空与远山/中景木围墙与营地大门/近景篝火与左右物件(作者纵深稿)。中景围墙是横贯全宽的密排竖木桩墙——木桩一根挨一根无缝、桩顶削尖、无横木,只在中段留缺口给大门。
|
纵深=远景天空与远山/中景木围墙与营地大门/近景篝火与左右物件(作者纵深稿)。中景围墙是横贯全宽的密排竖木桩墙——木桩一根挨一根无缝、桩顶削尖、无横木,只在中段留缺口给大门。
|
||||||
|
|
||||||
**场景按要素分层(10 张)**:远景天空/远山/整片地面/门洞内的小路合成 `scene_camp_bg` 背景层(z0,不透明全幅);中景木围墙独立成 `scene_camp_wall` 围墙层(z1,透明底,门洞处留透明缺口);其余八个物件层各一张、由上往下叠。门洞是围墙层的透明缺口,透出背景层画的**一条通向远处的小路**,不可填死。
|
**场景按要素分层(10 张)**:远景天空/远山/整片地面/门洞内的小路合成 `scene_camp_bg` 背景层(z0,不透明全幅);中景木围墙独立成 `scene_camp_wall` 围墙层(z1,透明底,门洞处留透明缺口);其余八个物件层各一张、由上往下叠。门洞是围墙层的透明缺口,透出背景层画的**一条通向远处的小路**,不可填死。
|
||||||
|
|
||||||
**中景带自画面底部往上约 2/3 处起**;近景物件允许压住围墙(围墙不可点,z 序在近景物件之下),**唯一例外=中间门洞必须留空、不被任何物件遮挡**。围墙形态、门扇比例与帐篷尺寸的现行口径归 [art-bible](../../art/art-bible.md) §6.2,本 spec 不再复述。
|
**地平线在终稿 y367**(自画面底部往上约 46%),其上是天空与远山、其下整片地面;**中景围墙带 y220–420(高 200)**,素材 1280×164 按 200 高显示拉伸(桩身/门柱比例随缩放);**墙脚压入地面纹理(入土线,2026-11-07)**;近景物件允许压住围墙(围墙不可点,z 序在近景物件之下),**唯一例外=中间门洞必须留空、不被任何物件遮挡**。围墙形态、门扇比例与帐篷尺寸的现行口径归 [art-bible](../art/art-bible.md) §6.2,本 spec 不再复述。
|
||||||
|
|
||||||
坐标草案与分层验收判据见 [camp-scene-prompts](../../art/camp-scene-prompts.md) §2.3/§4(10 张口径现行事实源);2026-10-22 美术方案讨论沿革查 git 提交史。
|
坐标草案与分层验收判据见 [camp-scene-prompts](../art/camp-scene-prompts.md) §2.3/§4(10 张口径现行事实源);2026-10-22 美术方案讨论沿革查 git 提交史。
|
||||||
|
|
||||||
## 点选反馈(根态)
|
## 点选反馈(根态)
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
## 顶栏
|
## 顶栏
|
||||||
|
|
||||||
钥石余额常驻画面顶部一行小 HUD 栏(高 48px、全宽窄条、**浮层覆盖在场景图上层,不挤压画面**)。刷新入口已实装=营地刷新单口(进档与营地内写口尾触发,现开界面与顶栏余额同步取现值)。
|
钥石余额常驻画面顶部一行小 HUD 栏:高 48px、全宽窄条、**浮层覆盖在场景图上层,不挤压画面**。栏体底=营地头带深棕 `#6E4526`(token `CAMP_HEADER_BAND`,色值出处 [art-bible](../art/art-bible.md) §7.2 五 token 对齐表)× **不透明度 0.80**——半透明系定值,底下画面透出 20%。栏内**只放钥石徽章一件**,右位、顶格落座(徽章自高 48px=栏高,无顶距可言),左位不放件。验收:目检〈顶栏成一条可辨窄带、徽章落在带内〉+机检〈栏体呈色对其下方落位带底色对比 ≥3:1〉。刷新入口已实装=营地刷新单口(进档与营地内写口尾触发,现开界面与顶栏余额同步取现值)。
|
||||||
|
|
||||||
## 叠层与开合
|
## 叠层与开合
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
> **Author**: user + ux-designer
|
> **Author**: user + ux-designer
|
||||||
> **Last Updated**: 2026-10-29
|
> **Last Updated**: 2026-10-29
|
||||||
> **Template**: Interaction Pattern Library
|
> **Template**: Interaction Pattern Library
|
||||||
> **来源**: `design/gdd/ux/battle.md` 已拍板内容的成文固化——本库不引入新设计决策
|
> **来源**: `design/ux/battle.md` 已拍板内容的成文固化——本库不引入新设计决策
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ MVP 未使用标准控件(不入库):toggle / dropdown / input field / tab
|
|||||||
**Description**: 轮末结算逐行流水实时呈现——「扫雷之因逐行兑现为战果」(P2 归因)的承载面。挖掘期收起为 1 行上轮摘要;结算期展开为实时流(带高读 `log_band_h_settle`)。
|
**Description**: 轮末结算逐行流水实时呈现——「扫雷之因逐行兑现为战果」(P2 归因)的承载面。挖掘期收起为 1 行上轮摘要;结算期展开为实时流(带高读 `log_band_h_settle`)。
|
||||||
|
|
||||||
**Specification**:
|
**Specification**:
|
||||||
- 数据源:[战斗结算](../systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)步骤流(9 类行封闭协议(现行);公共字段:来源类别 / 来源格 / 轮次 / 显示名 / 数值 / 可空高光标记);**无来源行 = 断言失败**
|
- 数据源:[战斗结算](../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)步骤流(9 类行封闭协议(现行);公共字段:来源类别 / 来源格 / 轮次 / 显示名 / 数值 / 可空高光标记);**无来源行 = 断言失败**
|
||||||
- 行模板:「{行为} {值} → {目标}(来源)」——来源标注(第 N 轮 · 安全格式);行文案最长 token = 来源标签(4 汉字封闭枚举),模板预留 40% 膨胀宽度
|
- 行模板:「{行为} {值} → {目标}(来源)」——来源标注(第 N 轮 · 安全格式);行文案最长 token = 来源标签(4 汉字封闭枚举),模板预留 40% 膨胀宽度
|
||||||
- 聚合纪律:未生效类行(奖励未生效——现行 9 类行协议唯一未生效型)按聚合计数呈现(防逐行惩罚轰炸);衰减行聚合计数;效果行数值 = 单次贡献值、禁与池合成值相加呈现;零值行可见不吞(免伤轮归因不断点)
|
- 聚合纪律:未生效类行(奖励未生效——现行 9 类行协议唯一未生效型)按聚合计数呈现(防逐行惩罚轰炸);衰减行聚合计数;效果行数值 = 单次贡献值、禁与池合成值相加呈现;零值行可见不吞(免伤轮归因不断点)
|
||||||
- 高亮:高亮标记(封印标中、清图奖励、完美破除) → 金框强调;完美封印 = 独立高光行 + 全屏喝彩级反馈。「完美破除」的判据句读作「本板首次标错受检」,不等于完美资格已失——专长「完美保险」可在本场首次标错时豁免,实际资格按有效误标(误标总数 − 豁免数)判定
|
- 高亮:高亮标记(封印标中、清图奖励、完美破除) → 金框强调;完美封印 = 独立高光行 + 全屏喝彩级反馈。「完美破除」的判据句读作「本板首次标错受检」,不等于完美资格已失——专长「完美保险」可在本场首次标错时豁免,实际资格按有效误标(误标总数 − 豁免数)判定
|
||||||
@@ -92,7 +92,7 @@ MVP 未使用标准控件(不入库):toggle / dropdown / input field / tab
|
|||||||
- 击杀标记呈现(H3 数据源 = 战斗结算流水击杀结果字段)
|
- 击杀标记呈现(H3 数据源 = 战斗结算流水击杀结果字段)
|
||||||
|
|
||||||
**When to Use**: 任何「因果可归因」的逐行流水呈现
|
**When to Use**: 任何「因果可归因」的逐行流水呈现
|
||||||
**When NOT to Use**: 自造行类型/字段(9 类封闭枚举(现行)——增删 = 接口漂移,须走[《战斗结算》](../systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)修订)
|
**When NOT to Use**: 自造行类型/字段(9 类封闭枚举(现行)——增删 = 接口漂移,须走[《战斗结算》](../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)修订)
|
||||||
|
|
||||||
**Reference**: battle.md §Component Inventory 结算明细带、§AC 信息与归因;归档《战斗结算》(b1-settlement.md)Core Rule 14 / Visual Req
|
**Reference**: battle.md §Component Inventory 结算明细带、§AC 信息与归因;归档《战斗结算》(b1-settlement.md)Core Rule 14 / Visual Req
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
## 现行载体与目标形态(重要边界)
|
## 现行载体与目标形态(重要边界)
|
||||||
|
|
||||||
本屏**没有独立新屏**:现行与 MVP 目标载体都是关卡收束时刻的覆盖层反馈([HUD框架](../systems/表现与支撑/HUD框架.md) P1 行「相邻域屏完整屏形态:MVP 以覆盖层反馈承载」)。本 spec 锁义务与数据锚,不锁视觉形态;完整屏形态待 P1 屏实装时定。
|
本屏**没有独立新屏**:现行与 MVP 目标载体都是关卡收束时刻的覆盖层反馈([HUD框架](../gdd/systems/表现与支撑/HUD框架.md) P1 行「相邻域屏完整屏形态:MVP 以覆盖层反馈承载」)。本 spec 锁义务与数据锚,不锁视觉形态;完整屏形态待 P1 屏实装时定。
|
||||||
|
|
||||||
| 时刻 | 载体(目标形态) | 呈现内容 |
|
| 时刻 | 载体(目标形态) | 呈现内容 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
## Accessibility
|
## Accessibility
|
||||||
|
|
||||||
沿用 [HUD框架](../systems/表现与支撑/HUD框架.md)「可访问性基线」节全量(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体)——本屏无新增承诺。结算数字是本屏信息主载体,遵守同一字号下限与对比硬指标。
|
沿用 [HUD框架](../gdd/systems/表现与支撑/HUD框架.md)「可访问性基线」节全量(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体)——本屏无新增承诺。结算数字是本屏信息主载体,遵守同一字号下限与对比硬指标。
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
> **Template**: UX Spec
|
> **Template**: UX Spec
|
||||||
> **覆盖范围**: 独立屏形态(关卡停点全景)· 入口停点 · 岔路停点 · 单链停点 · 放弃冒险入口
|
> **覆盖范围**: 独立屏形态(关卡停点全景)· 入口停点 · 岔路停点 · 单链停点 · 放弃冒险入口
|
||||||
> **不覆盖**: 节点覆盖层(NodeOverlay——奖励/恢复兑付反馈,spec:[node-reward.md](node-reward.md))、商店覆盖层(spec:[shop.md](shop.md))、关卡结算屏([level-clear.md](level-clear.md))、战斗屏([battle.md](battle.md))
|
> **不覆盖**: 节点覆盖层(NodeOverlay——奖励/恢复兑付反馈,spec:[node-reward.md](node-reward.md))、商店覆盖层(spec:[shop.md](shop.md))、关卡结算屏([level-clear.md](level-clear.md))、战斗屏([battle.md](battle.md))
|
||||||
> **机制权威**: [关卡节点地图](../systems/冒险循环/关卡节点地图.md)(选路、兑付、停点语义);图的来源 = [关卡节点图生成](../systems/冒险循环/关卡节点图生成.md)(参数化长图——只换图的来源与形态,不换本屏的呈现语义;多终点时各终点均带 Boss 标记,标记语义不变、数量随图;图形态随参数变化,布局自适应,形态不进呈现代码);**系统契约**: [HUD框架](../systems/表现与支撑/HUD框架.md)(订阅纪律、模态层级、可访问性基线)
|
> **机制权威**: [关卡节点地图](../gdd/systems/冒险循环/关卡节点地图.md)(选路、兑付、停点语义);图的来源 = [关卡节点图生成](../gdd/systems/冒险循环/关卡节点图生成.md)(参数化长图——只换图的来源与形态,不换本屏的呈现语义;多终点时各终点均带 Boss 标记,标记语义不变、数量随图;图形态随参数变化,布局自适应,形态不进呈现代码);**系统契约**: [HUD框架](../gdd/systems/表现与支撑/HUD框架.md)(订阅纪律、模态层级、可访问性基线)
|
||||||
> **生成图随动登记**:入口停点候选数=入口个数(1 或多,多入口并列呈现,首跳即选从哪个入口进场);节点数字=图内句柄 id(非节点深度、非数组序);生成图深度域 L3 上探至 0–13——卷轴视口范式(布局决策 5)下画布随图生长、屏为窗口,深度不再受屏预算约束(2026-11-05 用户裁:滚动视口案落地、等比缩放案否决;原「超预算」挂账闭合)。
|
> **生成图随动登记**:入口停点候选数=入口个数(1 或多,多入口并列呈现,首跳即选从哪个入口进场);节点数字=图内句柄 id(非节点深度、非数组序);生成图深度域 L3 上探至 0–13——卷轴视口范式(布局决策 5)下画布随图生长、屏为窗口,深度不再受屏预算约束(2026-11-05 用户裁:滚动视口案落地、等比缩放案否决;原「超预算」挂账闭合)。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
- **到达时机**:关卡开始即出图(停点前移——入口不自动进入,第一次选路就是「出发」);或每次兑付确认后返回(战后回图、奖励/恢复反馈确认后回图、商店覆盖层离开后回图)
|
- **到达时机**:关卡开始即出图(停点前移——入口不自动进入,第一次选路就是「出发」);或每次兑付确认后返回(战后回图、奖励/恢复反馈确认后回图、商店覆盖层离开后回图)
|
||||||
- **到达前刚在做**:上一场战斗的结算画面,或奖励/恢复/商店覆盖层的确认动作
|
- **到达前刚在做**:上一场战斗的结算画面,或奖励/恢复/商店覆盖层的确认动作
|
||||||
- **情绪状态**:谋定后动——[art-bible](../../art/art-bible.md) §2.7 下探过渡的「纵深的期待」(能量 4/10);画面应安静可读,不给选路决策添噪
|
- **情绪状态**:谋定后动——[art-bible](../art/art-bible.md) §2.7 下探过渡的「纵深的期待」(能量 4/10);画面应安静可读,不给选路决策添噪
|
||||||
- **到达方式**:游戏推进送入(屏级切换——独立屏激活期战斗屏整体隐藏)
|
- **到达方式**:游戏推进送入(屏级切换——独立屏激活期战斗屏整体隐藏)
|
||||||
|
|
||||||
## Navigation Position
|
## Navigation Position
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
本屏必须传达的全部信息,按注视优先级分六层:
|
本屏必须传达的全部信息,按注视优先级分六层:
|
||||||
|
|
||||||
1. **节点图本体**(第一注视点):节点方块(五类型字面:战/赏/疗/王/商)、通道连线、当前位置、可选去路;类型可见性=邻近 N 层内显示类型,范围外只见结构(机制见[关卡节点地图](../systems/冒险循环/关卡节点地图.md))
|
1. **节点图本体**(第一注视点):节点方块(五类型字面:战/赏/疗/王/商)、通道连线、当前位置、可选去路;类型可见性=邻近 N 层内显示类型,范围外只见结构(机制见[关卡节点地图](../gdd/systems/冒险循环/关卡节点地图.md))
|
||||||
2. **候选选路口**:亮金候选通道 + 候选节点亮金描边——「下一步能去哪」的图上双冗余(2026-09-27 拍板:候选按钮退役,图上点击为唯一提交通道)
|
2. **候选选路口**:亮金候选通道 + 候选节点亮金描边——「下一步能去哪」的图上双冗余(2026-09-27 拍板:候选按钮退役,图上点击为唯一提交通道)
|
||||||
3. **常驻语境**(顶栏):关卡名(第 N 层·名称)、GP 常驻总量(2026-09-26 二轮拍板:GP = 关卡画面常驻总量)
|
3. **常驻语境**(顶栏):关卡名(第 N 层·名称)、GP 常驻总量(2026-09-26 二轮拍板:GP = 关卡画面常驻总量)
|
||||||
4. **状态展示**(底栏,2026-09-27 拍板):生命(当前/上限)、属性(攻击 / 护甲 AC 有效值)、本关已选加成(统一冒险加算区增量)——选路规划原料常读
|
4. **状态展示**(底栏,2026-09-27 拍板):生命(当前/上限)、属性(攻击 / 护甲 AC 有效值)、本关已选加成(统一冒险加算区增量)——选路规划原料常读
|
||||||
@@ -233,7 +233,7 @@
|
|||||||
|
|
||||||
## Accessibility
|
## Accessibility
|
||||||
|
|
||||||
无障碍基线权威 = [HUD框架](../systems/表现与支撑/HUD框架.md)「可访问性基线」节,本屏无新增豁免。呈现侧内建承诺:
|
无障碍基线权威 = [HUD框架](../gdd/systems/表现与支撑/HUD框架.md)「可访问性基线」节,本屏无新增豁免。呈现侧内建承诺:
|
||||||
|
|
||||||
- **节点态形状冗余**(全局语义红线「无任何信息仅靠色相承载」的合规项):已过 = 暗金无描边、当前 = 金填充 + 唯一焦点方块、候选 = 亮金粗描边、未来 = 暗底无描边;Boss = 紫赤描边 + 外缘 1px 深墨环(**灰度冗余通道**——紫赤灰度对石纹噪底不可辨)+ 图标冗余。四态在灰度截图下可分类(AC,样张 L2 断言承载)
|
- **节点态形状冗余**(全局语义红线「无任何信息仅靠色相承载」的合规项):已过 = 暗金无描边、当前 = 金填充 + 唯一焦点方块、候选 = 亮金粗描边、未来 = 暗底无描边;Boss = 紫赤描边 + 外缘 1px 深墨环(**灰度冗余通道**——紫赤灰度对石纹噪底不可辨)+ 图标冗余。四态在灰度截图下可分类(AC,样张 L2 断言承载)
|
||||||
- **对比**:节点图标对方块底(双色墨制:暗底态暖白/当前金底深墨,各态 ≥4.5:1)、顶栏数字对底 ≥4.5:1(样张 L3 断言承载);色值取 art-bible §4.1 冻结色板(已过暗金 = GOLD_DONE #68562C 冻结新值)
|
- **对比**:节点图标对方块底(双色墨制:暗底态暖白/当前金底深墨,各态 ≥4.5:1)、顶栏数字对底 ≥4.5:1(样张 L3 断言承载);色值取 art-bible §4.1 冻结色板(已过暗金 = GOLD_DONE #68562C 冻结新值)
|
||||||
@@ -295,12 +295,12 @@
|
|||||||
|
|
||||||
| 义务源 | 义务 | 本 spec 承载落点 |
|
| 义务源 | 义务 | 本 spec 承载落点 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [关卡节点地图](../systems/冒险循环/关卡节点地图.md) | 呈现侧口径:方块地牢观感、节点态四色、不另设进度条 | Information Hierarchy 第 5 层 + 图区组件行 |
|
| [关卡节点地图](../gdd/systems/冒险循环/关卡节点地图.md) | 呈现侧口径:方块地牢观感、节点态四色、不另设进度条 | Information Hierarchy 第 5 层 + 图区组件行 |
|
||||||
| 关卡节点地图 | 零自动推进、兑付后确认、选路只读 | Interaction Map + Data Requirements + AC |
|
| 关卡节点地图 | 零自动推进、兑付后确认、选路只读 | Interaction Map + Data Requirements + AC |
|
||||||
| 关卡节点地图 | 呈现只读(节点图/当前位置/可选下一跳对呈现层只读可见) | Data Requirements 只读出口清单 |
|
| 关卡节点地图 | 呈现只读(节点图/当前位置/可选下一跳对呈现层只读可见) | Data Requirements 只读出口清单 |
|
||||||
| [HUD框架](../systems/表现与支撑/HUD框架.md) | 模态 overlay 层级纪律、订阅纪律(推进信号两线之一) | Navigation Position + Data Requirements 架构注记 |
|
| [HUD框架](../gdd/systems/表现与支撑/HUD框架.md) | 模态 overlay 层级纪律、订阅纪律(推进信号两线之一) | Navigation Position + Data Requirements 架构注记 |
|
||||||
| HUD框架 | 可访问性基线全量(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体) | Accessibility |
|
| HUD框架 | 可访问性基线全量(对比/色弱/字号/闪烁/减动效/纯鼠标/中文字体) | Accessibility |
|
||||||
| [battle.md](battle.md) OQ14 二轮拍板 | GP = 关卡画面常驻总量 | 顶栏 GP 常驻徽章 |
|
| [battle.md](battle.md) OQ14 二轮拍板 | GP = 关卡画面常驻总量 | 顶栏 GP 常驻徽章 |
|
||||||
| [art-bible](../../art/art-bible.md) | 方块地牢观感(§3.2 圆角方形世界侧)、色板冻结(§4.1)、半拟物(§7.1)、明度分层(§2) | 图区组件 + Accessibility 对比条 |
|
| [art-bible](../art/art-bible.md) | 方块地牢观感(§3.2 圆角方形世界侧)、色板冻结(§4.1)、半拟物(§7.1)、明度分层(§2) | 图区组件 + Accessibility 对比条 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> 状态:v3.0(现行)
|
> 状态:v3.0(现行)
|
||||||
> 事实源:本 spec(呈现)+ 三选一覆盖层(共用呈现件)+ 头部行文案(旁白条目)
|
> 事实源:本 spec(呈现)+ 三选一覆盖层(共用呈现件)+ 头部行文案(旁白条目)
|
||||||
> 相邻:[level-clear](level-clear.md)(关卡完成三选一面——同一覆盖层的另一上下文)/ [level-map](level-map.md)(关卡画面)/ [秘宝](../systems/跨局循环/秘宝.md)(道具件内容权威——局外同调件,不再入三选一牌库)/ [冒险结构](../systems/冒险循环/冒险结构.md)(共享池令牌库账本)
|
> 相邻:[level-clear](level-clear.md)(关卡完成三选一面——同一覆盖层的另一上下文)/ [level-map](level-map.md)(关卡画面)/ [秘宝](../gdd/systems/跨局循环/秘宝.md)(道具件内容权威——局外同调件,不再入三选一牌库)/ [冒险结构](../gdd/systems/冒险循环/冒险结构.md)(共享池令牌库账本)
|
||||||
|
|
||||||
## 定位
|
## 定位
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
- 载体 = 提升三选一覆盖层(与 [level-clear](level-clear.md) 共用组件——零新增交互原语)。
|
- 载体 = 提升三选一覆盖层(与 [level-clear](level-clear.md) 共用组件——零新增交互原语)。
|
||||||
- 头部行:「关卡奖励点 / 从冒险牌库抽三选一(属性值提升与补给;与通关专长三选一同库分流):选择一件带走:」(旁白条目)。
|
- 头部行:「关卡奖励点 / 从冒险牌库抽三选一(属性值提升与补给;与通关专长三选一同库分流):选择一件带走:」(旁白条目)。
|
||||||
- 三卡点选(✓ 高亮,确认前可改选)→「确认选择」→ 兑付反馈(选中件效果 + 丢弃提示)→「继续」→ 回图选路(零自动推进同款)。
|
- 三卡点选(✓ 高亮,确认前可改选)→「确认选择」→ 兑付反馈(选中件效果 + 丢弃提示)→「继续」→ 回图选路(零自动推进同款)。
|
||||||
- **三选一刷新**(X/Y 双源;机制现行事实源=[秘宝](../systems/跨局循环/秘宝.md)「三选一刷新双源」节,X 源承载件=现行目录「刷新练习」):装配「三选一刷新件」给 X 次(每次碰三选一重给、优先消耗、不结转)+ 营地「刷新升级」给 Y 次(每冒险开局注入冒险周期池、用完即无);刷新钮余量 >0 时现形,点按重抽三候选(奖励抽取既有洗牌流,池规则全保留:不放回/达上限剔牌/掷定前置直显/停点可中断)。自动演示默认不刷(钓鱼归玩家)。
|
- **三选一刷新**(X/Y 双源;机制现行事实源=[秘宝](../gdd/systems/跨局循环/秘宝.md)「三选一刷新双源」节,X 源承载件=现行目录「刷新练习」):装配「刷新练习」给 X 次(每次碰三选一重给、优先消耗、不结转)+ 营地「刷新升级」给 Y 次(每冒险开局注入冒险周期池、用完即无);刷新钮余量 >0 时现形,点按重抽三候选(奖励抽取既有洗牌流,池规则全保留:不放回/达上限剔牌/掷定前置直显/停点可中断)。自动演示默认不刷(钓鱼归玩家)。
|
||||||
|
|
||||||
## 口径
|
## 口径
|
||||||
|
|
||||||
- **同库同池耗**:池=固定配额令牌库(档位=四级框架 普通/优秀/稀有/传说,传说=头奖位留空〔稀有档现投放为行动点件〕;各 kind 现行配额读 `game/data/tables/adventure.tres`);洗牌不放回抽 3(**同 kind 去重每 kind 至多一枚**——「三种不同选项」体验延续,kind 出现率∝剩余令牌数)、选中踢池未选回池、池耗即枯竭(余库不足出齐剩余,空库=零候选合法态直通);**种类次数上限退役**(池消耗即上限)。数值对:小GP 20/大GP 50、小增伤 +1/大 +2、小护甲 +1/大 +2、小生命 +5/大 +10、恢复 +6 当即回血(封顶生效上限)、AP +1。**MC 策略 316-f**:1 级优先度=最稀有(legendary>rare>excellent>common,头奖位现行留空)、2 级=最左(并列同档取最左)。配额结构锚与档位构成读冒险表(结构校验归实现侧)。商店货架=同库付费渠道(令牌级货架,买一件=奖励面少一件),库存=剩余令牌数,账本语义与切边注记归[冒险结构](../systems/冒险循环/冒险结构.md)共享池账本节。
|
- **同库同池耗**:池=固定配额令牌库(档位=四级框架 普通/优秀/稀有/传说,传说=头奖位留空〔稀有档现投放为行动点件〕;各 kind 现行配额读 `game/data/tables/adventure.tres`);洗牌不放回抽 3(**同 kind 去重每 kind 至多一枚**——「三种不同选项」体验延续,kind 出现率∝剩余令牌数)、选中踢池未选回池、池耗即枯竭(余库不足出齐剩余,空库=零候选合法态直通);**种类次数上限退役**(池消耗即上限)。数值对:小GP 20/大GP 50、小增伤 +1/大 +2、小护甲 +1/大 +2、小生命 +5/大 +10、恢复 +6 当即回血(封顶生效上限)、AP +1。**MC 策略 316-f**:1 级优先度=最稀有(legendary>rare>excellent>common,头奖位现行留空)、2 级=最左(并列同档取最左)。配额结构锚与档位构成读冒险表(结构校验归实现侧)。商店货架=同库付费渠道(令牌级货架,买一件=奖励面少一件),库存=剩余令牌数,账本语义与切边注记归[冒险结构](../gdd/systems/冒险循环/冒险结构.md)共享池账本节。
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
- 触发:主角倒下(判负)/ 末关完成 / 玩家放弃——三结局同面(由冒险收束信号统一触发)。
|
- 触发:主角倒下(判负)/ 末关完成 / 玩家放弃——三结局同面(由冒险收束信号统一触发)。
|
||||||
- 载体:与战斗面同一个战斗结束覆盖层——末关关卡完成走胜利态开屏(金蜡封 +「本局 GP 入账 · 合计 N」行,GP 收束清零前的呈现侧影子账);倒下 / 放弃走失败态开屏(暮蓝)。无独立「冒险终局面板」实体。
|
- 载体:与战斗面同一个战斗结束覆盖层——末关关卡完成走胜利态开屏(金蜡封 +「本局 GP 入账 · 合计 N」行,GP 收束清零前的呈现侧影子账);倒下 / 放弃走失败态开屏(暮蓝)。无独立「冒险终局面板」实体。
|
||||||
- 呈现内容:冒险摘要五件事(定义归[冒险结构](../systems/冒险循环/冒险结构.md))+ 钥石写入明细(= 本局逐杀 Boss 掉落合计;消费归[元进度](../systems/跨局循环/元进度.md) 的冒险结算入账——大奖励面不产钥石)+ GP 合计行。
|
- 呈现内容:冒险摘要五件事(定义归[冒险结构](../gdd/systems/冒险循环/冒险结构.md))+ 钥石写入明细(= 本局逐杀 Boss 掉落合计;消费归[元进度](../gdd/systems/跨局循环/元进度.md) 的冒险结算入账——大奖励面不产钥石)+ GP 合计行。
|
||||||
- 出口:确认 → 回存档首页。
|
- 出口:确认 → 回存档首页。
|
||||||
|
|
||||||
## 口径
|
## 口径
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> 状态:v1.2(现行)
|
> 状态:v1.2(现行)
|
||||||
> 事实源:本 spec(呈现)+ 商店覆盖层(呈现件)
|
> 事实源:本 spec(呈现)+ 商店覆盖层(呈现件)
|
||||||
> 机制权威:[关卡节点地图](../systems/冒险循环/关卡节点地图.md)(商店房编排:每关恰 1/Boss 前一位必经/兑付触发);定价数值归[难度曲线与Boss](../systems/冒险循环/难度曲线与Boss.md)(shop.tres,provisional)
|
> 机制权威:[关卡节点地图](../gdd/systems/冒险循环/关卡节点地图.md)(商店房编排:每关恰 1/Boss 前一位必经/兑付触发);定价数值归[难度曲线与Boss](../gdd/systems/冒险循环/难度曲线与Boss.md)(shop.tres,provisional)
|
||||||
|
|
||||||
## 定位
|
## 定位
|
||||||
|
|
||||||
@@ -17,6 +17,6 @@
|
|||||||
|
|
||||||
## 口径
|
## 口径
|
||||||
|
|
||||||
- GP 余额读数 = runner 钱包投影(GP 归[冒险结构](../systems/冒险循环/冒险结构.md) GP 节);本层不作计算。
|
- GP 余额读数 = runner 钱包投影(GP 归[冒险结构](../gdd/systems/冒险循环/冒险结构.md) GP 节);本层不作计算。
|
||||||
- 与关卡画面 GP 常驻徽章的关系:进店语境余额与选路常驻总量不同义(本层带购买语境),不构成重复展示——钥石「写入/存量」拆名逻辑同款。
|
- 与关卡画面 GP 常驻徽章的关系:进店语境余额与选路常驻总量不同义(本层带购买语境),不构成重复展示——钥石「写入/存量」拆名逻辑同款。
|
||||||
- 购买确认交互:现行直接购买(无二次确认步);是否需破坏性确认异位(pattern 7)未裁决,本 spec 只登记现状不立新裁。
|
- 购买确认交互:现行直接购买(无二次确认步);是否需破坏性确认异位(pattern 7)未裁决,本 spec 只登记现状不立新裁。
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 450 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 46 KiB |
@@ -79,7 +79,7 @@ func try_spend(action_kind: String) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
# 排雷玩法 挖掘专用:chain_size = 连锁附加格数(不含首格);clears_map = 本次动作后全图安全格开完。
|
# 排雷玩法 挖掘专用:chain_size = 连锁附加格数(不含首格);clears_map = 本次动作后全图安全格开完。
|
||||||
# 深挖钻头付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎
|
# 付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎
|
||||||
# 计数器=授予段追加产出配额取数面);AP 不足全价时 fallback 降级只付基础 1 照常开格、不积计数
|
# 计数器=授予段追加产出配额取数面);AP 不足全价时 fallback 降级只付基础 1 照常开格、不积计数
|
||||||
# ——持有钻头永不锁死普通挖格(散件保底 B-2)。
|
# ——持有钻头永不锁死普通挖格(散件保底 B-2)。
|
||||||
func request_dig(chain_size: int, clears_map: bool) -> bool:
|
func request_dig(chain_size: int, clears_map: bool) -> bool:
|
||||||
@@ -142,6 +142,15 @@ func _spend_cost_and_arbitrate(cost: int, clears_map: bool) -> bool:
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
# 封印路径清图事实上报(排雷玩法 _do_seal_place 受理后清图判定成立时调用):
|
||||||
|
# 轮末仲裁与 request_dig 的 cleared 语义同源——剩余 AP 当场清零作废、不进 RAP(EC7/EC10),
|
||||||
|
# 同帧 cleared > ap_exhausted 胜出(覆盖写 _last_round_end)。封印不产挖掘计费,
|
||||||
|
# 清图事实经独立上报口进入仲裁(硬塞 request_dig 会引入假挖掘记账)。
|
||||||
|
func notify_cleared() -> void:
|
||||||
|
_ap = 0
|
||||||
|
_finish_round("cleared", "new_board")
|
||||||
|
|
||||||
|
|
||||||
func _spend_and_arbitrate(action_kind: String, clears_map: bool) -> bool:
|
func _spend_and_arbitrate(action_kind: String, clears_map: bool) -> bool:
|
||||||
var cost := _cost(action_kind)
|
var cost := _cost(action_kind)
|
||||||
if _ap < cost:
|
if _ap < cost:
|
||||||
@@ -221,7 +230,7 @@ func notify_settlement_done(next_round_mode: String) -> bool:
|
|||||||
|
|
||||||
# 下轮行动点修正排队:action 型正负行结算期调用,同轮多次授予累加;
|
# 下轮行动点修正排队:action 型正负行结算期调用,同轮多次授予累加;
|
||||||
# 相位无关(授予发生在结算段,此时本类可能处于 ACTIVE/WAITING 任一相位)
|
# 相位无关(授予发生在结算段,此时本类可能处于 ACTIVE/WAITING 任一相位)
|
||||||
# 第 9 API(registry 行动经济×① 接口漂移预授权):ap_grant 道具的
|
# 第 9 API(registry 行动经济×① 接口漂移预授权):行动点授予型道具的
|
||||||
# 当轮行动点加量(GDD「加行动点效果给当轮」——区别于 queue_ap_delta 的下轮排队语义)。Active 受理、
|
# 当轮行动点加量(GDD「加行动点效果给当轮」——区别于 queue_ap_delta 的下轮排队语义)。Active 受理、
|
||||||
# 无上限域、零随机;使用道具本身零扣费(成本在获取时已付——捡道具格不出战斗奖励)。
|
# 无上限域、零随机;使用道具本身零扣费(成本在获取时已付——捡道具格不出战斗奖励)。
|
||||||
func grant_ap(amount: int) -> bool:
|
func grant_ap(amount: int) -> bool:
|
||||||
|
|||||||
@@ -274,15 +274,9 @@ func present_node_curio(candidates: Array) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# 点选兑付(节点域——编排归停点件;呈现层直调面 T5 改 stop())
|
# 点选兑付(节点域——编排归停点件;呈现层直调面 T5 改 stop())
|
||||||
# 刷新件余量基数(kind 分发查询——装配集内 effect_kinds 含 bonus_refresh 的行 magnitude 合计;
|
# 刷新件余量基数(现役目录无行源——X 机制保留恒 0 空转;停点件 X 重置基数经 start/resume 预算注入)
|
||||||
# 刷新件类加件零 id 分支;停点件 X 重置基数经 start/resume 预算注入)
|
|
||||||
func _attune_refresh_x_total() -> int:
|
func _attune_refresh_x_total() -> int:
|
||||||
var total := 0
|
return 0
|
||||||
for iid_v in _attunement:
|
|
||||||
var arow: Dictionary[Variant, Variant] = db.crossrun.treasure_items.row_by_id(String(iid_v))
|
|
||||||
if (arow.get("effect_kinds", []) as Array).has("bonus_refresh"):
|
|
||||||
total += int(arow.get("magnitude", 0))
|
|
||||||
return total
|
|
||||||
|
|
||||||
|
|
||||||
# 同调行投行分派(关卡域库存就位时点——每关一次;首关=种行或旧档行集为源、后续关=快照补行)
|
# 同调行投行分派(关卡域库存就位时点——每关一次;首关=种行或旧档行集为源、后续关=快照补行)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
## 同调配装件:装备中的秘宝件对象集唯一所有者(每件内含充能单位与重置周期——冒险域拆分姊妹批自共享充能账字典轨迁移)。
|
## 同调配装件:装备中的秘宝件对象集唯一所有者(每件内含充能单位与重置周期)。
|
||||||
## 同调充能单源化:物化行(treasure_inventory 内 source_class="attunement" 行)为使用面唯一事实源——
|
## 同调充能单源化:物化行(treasure_inventory 内 source_class="attunement" 行)为使用面唯一事实源——
|
||||||
## 剩余次数由行的未用数派生(唯一读法,无影子账);字典轨与三处事后差额对账退役,改「写时种行/补行」。
|
## 剩余次数由行的未用数派生(唯一读法,无影子账);字典轨与三处事后差额对账退役,改「写时种行/补行」。
|
||||||
## 种行/补行写时同步:冒险开始全量种行(不筛周期——battle/level 周期件开局即有行,C 区投影行数不变);
|
## 种行/补行写时同步:冒险开始全量种行(不筛周期——battle/level 周期件开局即有行,C 区投影行数不变);
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ var _enemy_system: UnitContainer
|
|||||||
var _status_effects: StatusContainer
|
var _status_effects: StatusContainer
|
||||||
var _reward_economy: RewardEconomy
|
var _reward_economy: RewardEconomy
|
||||||
var _damage: DamageController # 伤害控制器(单据唯一兑付管线)
|
var _damage: DamageController # 伤害控制器(单据唯一兑付管线)
|
||||||
var _fx_host: BattleFxHost # 效果引擎宿主件(fx 族持有与兑付——拆件定稿轴件一)
|
var _fx_host: BattleFxHost # 效果引擎宿主件(fx 族持有与兑付)
|
||||||
var _reward_grant: RewardGrant # 奖励授予件(授予管线与秘宝使用——拆件定稿轴件二)
|
var _reward_grant: RewardGrant # 奖励授予件(授予管线与秘宝使用)
|
||||||
|
|
||||||
var round_index := 0
|
var round_index := 0
|
||||||
var battle_result := "" # "" / "victory" / "defeat" / "fatal_error"
|
var battle_result := "" # "" / "victory" / "defeat" / "fatal_error"
|
||||||
@@ -156,7 +156,7 @@ func attune_has(item_id: String) -> bool:
|
|||||||
# 装备件表值读取(charge_n 等——TreasureItemTable 行;未装配不读表。
|
# 装备件表值读取(charge_n 等——TreasureItemTable 行;未装配不读表。
|
||||||
# 行值经 value_from 在 rebuild 定影,零运行期按件取值)
|
# 行值经 value_from 在 rebuild 定影,零运行期按件取值)
|
||||||
# 装配集参数合计(常时参数面 kind 的装配集 Σmagnitude 读数口;
|
# 装配集参数合计(常时参数面 kind 的装配集 Σmagnitude 读数口;
|
||||||
# kind 分发查询先例=_attune_refresh_x_total bonus_refresh。零装配=0)
|
# kind 分发查询同形先例见刷新账 X 基数注入面;零装配=0)
|
||||||
func attune_param_sum(kind: String) -> int:
|
func attune_param_sum(kind: String) -> int:
|
||||||
var total := 0
|
var total := 0
|
||||||
for iid_v in _facts.attunement:
|
for iid_v in _facts.attunement:
|
||||||
@@ -255,7 +255,7 @@ func begin_battle(enc: Dictionary) -> bool:
|
|||||||
_begin_battle_fx_state(enc)
|
_begin_battle_fx_state(enc)
|
||||||
_begin_battle_attune_params(enc)
|
_begin_battle_attune_params(enc)
|
||||||
_begin_battle_preview_economy(enc)
|
_begin_battle_preview_economy(enc)
|
||||||
# 工兵晨令=round_start grant_ap(mode:queue) 订阅行承载(when round_index ≤ effective_rounds
|
# 晨间 AP=round_start grant_ap(mode:queue) 订阅行承载(when round_index ≤ effective_rounds
|
||||||
# value_from 定影);round_start 发射先于行动经济轮切换=树规则 queue 型当轮入队当轮兑现
|
# value_from 定影);round_start 发射先于行动经济轮切换=树规则 queue 型当轮入队当轮兑现
|
||||||
# (先手压制=首轮 AP+1 语义锚);计数器 round_start 重置点同点生效
|
# (先手压制=首轮 AP+1 语义锚);计数器 round_start 重置点同点生效
|
||||||
round_index = 1
|
round_index = 1
|
||||||
@@ -535,7 +535,7 @@ func _exit_distribution() -> void:
|
|||||||
if not _install_and_reset():
|
if not _install_and_reset():
|
||||||
_fatal("换图编排失败")
|
_fatal("换图编排失败")
|
||||||
return
|
return
|
||||||
# 工兵晨令续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注)
|
# 晨间 AP 续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注)
|
||||||
action_economy.notify_settlement_done(mode)
|
action_economy.notify_settlement_done(mode)
|
||||||
# round_start 发射先于行动经济轮切换(queue 型 grant_ap 当轮入队当轮兑现——与首轮同口径)
|
# round_start 发射先于行动经济轮切换(queue 型 grant_ap 当轮入队当轮兑现——与首轮同口径)
|
||||||
round_index += 1
|
round_index += 1
|
||||||
|
|||||||
@@ -43,6 +43,14 @@ func is_safe(c: Vector2i) -> bool:
|
|||||||
func digit_of(c: Vector2i) -> int:
|
func digit_of(c: Vector2i) -> int:
|
||||||
return digits.get(c, -1)
|
return digits.get(c, -1)
|
||||||
|
|
||||||
|
## 格身份事实(封闭枚举):kind = "mine"(digit 恒 -1)| "safe"(digit = 邻雷数)。
|
||||||
|
## 封印受理即揭示的消费形态 = 呈现/测量侧按封印态(MinesweeperRules.has_seal)取本读数拼装——
|
||||||
|
## 身份事实单点在板数据(is_mine/digit_of 同源),禁消费方各自拼 kind 枚举。
|
||||||
|
func cell_identity(c: Vector2i) -> Dictionary:
|
||||||
|
if is_mine(c):
|
||||||
|
return {"kind": "mine", "digit": -1}
|
||||||
|
return {"kind": "safe", "digit": digit_of(c)}
|
||||||
|
|
||||||
|
|
||||||
func variant_ids(c: Vector2i) -> Array:
|
func variant_ids(c: Vector2i) -> Array:
|
||||||
return variants.get(c, [])
|
return variants.get(c, [])
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ func validate_skill_pool_links(skill_table: SkillTable, enemy_table: EnemyTable,
|
|||||||
for row in enemy_table.rows:
|
for row in enemy_table.rows:
|
||||||
var eid: String = String(row.get("enemy_id", ""))
|
var eid: String = String(row.get("enemy_id", ""))
|
||||||
var pool_n := {"basic": 0, "buff": 0, "debuff": 0, "uncond_special": 0}
|
var pool_n := {"basic": 0, "buff": 0, "debuff": 0, "uncond_special": 0}
|
||||||
for entry in row.get("pool", []):
|
for entry in enemy_table.effective_pool(row): # 合并池(elite=基础池+附加技;battle/boss=自身 pool——池构成纪律校验合并后的池)
|
||||||
var sid: String = String(entry.get("skill_id", ""))
|
var sid: String = String(entry.get("skill_id", ""))
|
||||||
if not skill_types.has(sid):
|
if not skill_types.has(sid):
|
||||||
errs.append({"category": "dangling_skill", "message": "EnemyTable %s 池引用不存在的 skill_id: %s(悬空致命)" % [eid, sid]})
|
errs.append({"category": "dangling_skill", "message": "EnemyTable %s 池引用不存在的 skill_id: %s(悬空致命)" % [eid, sid]})
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func resolve_enemy_rowset(L: int, D: int, row_kind: String) -> Array[Dictionary]
|
|||||||
if L < 1 or D < 0:
|
if L < 1 or D < 0:
|
||||||
_diag.call("fatal", "request_oob", "enemy 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [L, D])
|
_diag.call("fatal", "request_oob", "enemy 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [L, D])
|
||||||
return []
|
return []
|
||||||
if not EnemyTable.ROW_KINDS.has(row_kind):
|
if not EnemyTable.ENCOUNTER_ROW_KINDS.has(row_kind): # 开战寻址行类门——elite 行静置合法、任何寻址拿不到它(敌人系统.md:151)
|
||||||
_diag.call("fatal", "request_oob", "enemy 请求行类非法 (%d,%d,\"%s\")——row_kind 域 {battle, boss}" % [L, D, row_kind])
|
_diag.call("fatal", "request_oob", "enemy 请求行类非法 (%d,%d,\"%s\")——row_kind 域 {battle, boss}" % [L, D, row_kind])
|
||||||
return []
|
return []
|
||||||
var rows: Array[Dictionary] = []
|
var rows: Array[Dictionary] = []
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func _per_value(name: String, payload: Dictionary) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
# 巢穴控制数(fact nest_count 取数面——敌方名下 weaken 实例总数,猎巢人订阅面;
|
# 巢穴控制数(fact nest_count 取数面——敌方名下 weaken 实例总数,nest_count 订阅消费面;
|
||||||
# 个体化后削弱为累加行、每体各持一条——总数 = 被削弱个体数)
|
# 个体化后削弱为累加行、每体各持一条——总数 = 被削弱个体数)
|
||||||
func _nest_count() -> int:
|
func _nest_count() -> int:
|
||||||
var n := 0
|
var n := 0
|
||||||
@@ -135,7 +135,7 @@ func submit(t: Dictionary) -> int:
|
|||||||
# attack_commit 发射点(我方伤害单据开立入口;
|
# attack_commit 发射点(我方伤害单据开立入口;
|
||||||
# 命中挂单据 context 随行——施加面在 _resolve_hero_attack 管线算术前逐族施加,开单时点=主角攻击
|
# 命中挂单据 context 随行——施加面在 _resolve_hero_attack 管线算术前逐族施加,开单时点=主角攻击
|
||||||
# 单恒为段内首单(结账现场与开单现场一致)。载荷 atk/target/matchup + 挖掘 streak 事实
|
# 单恒为段内首单(结账现场与开单现场一致)。载荷 atk/target/matchup + 挖掘 streak 事实
|
||||||
# (执拗订阅面)+巢穴控制数〔猎巢人〕)
|
# (开格 streak 订阅面)+巢穴控制数〔nest_count 订阅面〕)
|
||||||
# spec 束必载键(缺载 assert——fail-fast):channel/base_value/target_rule/ri;
|
# spec 束必载键(缺载 assert——fail-fast):channel/base_value/target_rule/ri;
|
||||||
# 可选键缺省=原形缺省:origin_cell=(-1,-1)/attack_type=""/rider=0/highlight=""/context={}。
|
# 可选键缺省=原形缺省:origin_cell=(-1,-1)/attack_type=""/rider=0/highlight=""/context={}。
|
||||||
# 返回单据字典九栏目+requires/source_unit 逐字不变(契约 8)。
|
# 返回单据字典九栏目+requires/source_unit 逐字不变(契约 8)。
|
||||||
@@ -247,9 +247,9 @@ func _resolve(t: Dictionary) -> void:
|
|||||||
|
|
||||||
# 主角先手攻击:掷点 → 折扣/暴击 → 克制点数 → hero_offense×enemy_defense 池乘区 → 下限 → 交付
|
# 主角先手攻击:掷点 → 折扣/暴击 → 克制点数 → hero_offense×enemy_defense 池乘区 → 下限 → 交付
|
||||||
# (attack_commit/clamp_check/armor_roll 订阅施加面:命中=开单入口随单
|
# (attack_commit/clamp_check/armor_roll 订阅施加面:命中=开单入口随单
|
||||||
# context 携带,按固定算序逐族施加——命中序=数据表声明序,确定性)。
|
# context 携带,按固定算序逐族施加——命中序=数据表声明序,确定性;掷点折扣读数→克制点数两拍)。
|
||||||
# 四步分段:命中面(_hero_attack_ctx,目标/护甲/
|
# 四步分段:命中面(_hero_attack_ctx,目标/护甲/
|
||||||
# 掷点/按序改写族四拍/克制点数) → 基值装配(_hero_attack_base_value,加法族/计数器施加/倍乘) →
|
# 掷点/掷点折扣读数/克制点数) → 基值装配(_hero_attack_base_value,加法族/计数器施加) →
|
||||||
# 掷点兑现(_hero_attack_redeem,rolled/池乘/下限/rider/落地/击杀发射) → 交付(_hero_attack_deliver,
|
# 掷点兑现(_hero_attack_redeem,rolled/池乘/下限/rider/落地/击杀发射) → 交付(_hero_attack_deliver,
|
||||||
# 状态施加/标签/明细行)。步骤间经 ctx/redemption 字典穿线——算序/取值固定(🔴 逐位一致契约)。
|
# 状态施加/标签/明细行)。步骤间经 ctx/redemption 字典穿线——算序/取值固定(🔴 逐位一致契约)。
|
||||||
func _resolve_hero_attack(t: Dictionary) -> void:
|
func _resolve_hero_attack(t: Dictionary) -> void:
|
||||||
@@ -261,7 +261,7 @@ func _resolve_hero_attack(t: Dictionary) -> void:
|
|||||||
_hero_attack_deliver(t, ctx, redemption)
|
_hero_attack_deliver(t, ctx, redemption)
|
||||||
|
|
||||||
|
|
||||||
# 命中面(目标/护甲克制 matchup/armor_roll 发射→按序改写族四拍→克制点数读值+订阅改写;
|
# 命中面(目标/护甲克制 matchup/armor_roll 发射→掷点折扣读数→克制点数读值+订阅改写;
|
||||||
# 后两步各由 _ctx_rewrites/_ctx_clamp_delta 承载)。返回穿线 ctx(空=目标不可达)。
|
# 后两步各由 _ctx_rewrites/_ctx_clamp_delta 承载)。返回穿线 ctx(空=目标不可达)。
|
||||||
# clamp_check 只在 _ctx_rewrites 内发射一次——_ctx_clamp_delta 消费同批命中(禁重复发射)。
|
# clamp_check 只在 _ctx_rewrites 内发射一次——_ctx_clamp_delta 消费同批命中(禁重复发射)。
|
||||||
func _hero_attack_ctx(t: Dictionary) -> Dictionary:
|
func _hero_attack_ctx(t: Dictionary) -> Dictionary:
|
||||||
@@ -278,54 +278,25 @@ func _hero_attack_ctx(t: Dictionary) -> Dictionary:
|
|||||||
return {"target": target, "armor": armor, "atk_type": atk_type,
|
return {"target": target, "armor": armor, "atk_type": atk_type,
|
||||||
"ac_hits": (t.context.get("fx_attack_hits", []) as Array), "ac_payload": ac_payload,
|
"ac_hits": (t.context.get("fx_attack_hits", []) as Array), "ac_payload": ac_payload,
|
||||||
"roll_read": rewrites["roll_read"], "threshold": rewrites["threshold"],
|
"roll_read": rewrites["roll_read"], "threshold": rewrites["threshold"],
|
||||||
"crit": rewrites["crit"], "discount": rewrites["discount"],
|
"crit": rewrites["crit"], "discount": rewrites["discount"], "cdelta": cdelta}
|
||||||
"spike_ready": rewrites["spike_ready"], "cdelta": cdelta}
|
|
||||||
|
|
||||||
|
|
||||||
# 按序改写族四拍+掷点快照(armor_roll 发射点在此):第一拍矿工重锤命中交换(正负双修原生形态:
|
# 掷点折扣读数+克制点数命中批(armor_roll 发射点在此):一拍护甲掷骰折扣读数(掷点对照
|
||||||
# 命中判定减成 trade_hit 点〔更易命中〕换攻击增伤 trade_atk%——高 AC 负期望/低 AC 正期望;
|
# 防御阈值定折扣档——阈值=防御 AC+攻击加值,nat 面沿折扣表)→ 二拍 clamp_check 发射
|
||||||
# 改写位先于掷点折扣读数)→ 第二拍专注免掷骰恒定折扣(方差买断成期望——稳定器人格;roll 记 0 归因)
|
# (唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。
|
||||||
# → 第三拍满层必中(spike ready 时 discount 恒全额、暴击面走倍乘不加掷)→ 第四拍猎弱本能对轻甲敌折扣档改善 value 档
|
|
||||||
# (对冲 pierce 列 L1 −1 开局罚;改善 = 折扣表向全额方向移档,nat 最大面/已全额不重复)。
|
|
||||||
# clamp_check 同在此发射(唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。
|
|
||||||
func _ctx_rewrites(t: Dictionary, target: Dictionary, armor: String, matchup: String) -> Dictionary:
|
func _ctx_rewrites(t: Dictionary, target: Dictionary, armor: String, matchup: String) -> Dictionary:
|
||||||
var ac_hits: Array[Variant] = (t.context.get("fx_attack_hits", []) as Array)
|
|
||||||
var roll_read: Dictionary[Variant, Variant] = _armor_roll()
|
var roll_read: Dictionary[Variant, Variant] = _armor_roll()
|
||||||
var threshold: int = defender_ac(target) + int(db.combat.settlement.damage_roll.attack_bonus)
|
var threshold: int = defender_ac(target) + int(db.combat.settlement.damage_roll.attack_bonus)
|
||||||
# armor_roll 发射点(敌护甲掷骰判定;免掷恒折扣订阅面)
|
# armor_roll 发射点(敌护甲掷骰判定——事件在册、现役零订阅行,发射面保留)
|
||||||
var ar_hits := _fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)})
|
_fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)})
|
||||||
var trade_hit := 0
|
|
||||||
for h in ac_hits:
|
|
||||||
if String(h.get("kind", "")) == "modify_ticket" and int(h.get("trade_hit", 0)) > 0:
|
|
||||||
trade_hit += int(h.trade_hit)
|
|
||||||
if trade_hit > 0:
|
|
||||||
threshold = maxi(1, threshold - trade_hit)
|
|
||||||
var crit: bool = bool(roll_read.crit)
|
var crit: bool = bool(roll_read.crit)
|
||||||
var discount: int = _roll_discount(int(roll_read.roll), threshold)
|
var discount: int = _roll_discount(int(roll_read.roll), threshold)
|
||||||
for h in ar_hits:
|
|
||||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "armor_rewrite":
|
|
||||||
discount = int(h.get("value", 0))
|
|
||||||
crit = false
|
|
||||||
roll_read["roll"] = 0
|
|
||||||
var spike_ready := false
|
|
||||||
for h in ac_hits:
|
|
||||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "spike":
|
|
||||||
spike_ready = true
|
|
||||||
discount = 100
|
|
||||||
var clamp_hits := _fx_hits("clamp_check", {"matchup": matchup})
|
var clamp_hits := _fx_hits("clamp_check", {"matchup": matchup})
|
||||||
var shift := 0
|
|
||||||
for h in clamp_hits:
|
|
||||||
if String(h.get("kind", "")) != "modify_ticket":
|
|
||||||
continue
|
|
||||||
if String(h.get("mode", "")) == "discount_shift":
|
|
||||||
shift += int(h.get("value", 0))
|
|
||||||
if shift > 0 and armor == "light" and discount < 100:
|
|
||||||
discount = _discount_shift_up(discount, shift)
|
|
||||||
return {"roll_read": roll_read, "threshold": threshold, "crit": crit,
|
return {"roll_read": roll_read, "threshold": threshold, "crit": crit,
|
||||||
"discount": discount, "spike_ready": spike_ready, "clamp_hits": clamp_hits}
|
"discount": discount, "clamp_hits": clamp_hits}
|
||||||
|
|
||||||
|
|
||||||
# 克制点数读值+订阅改写(魔网织者/湛蓝誓约/猎手刺剑 clamp_check modify delta——克制矩阵查表值
|
# 克制点数读值+订阅改写(clamp_check 带模式行 modify delta——克制矩阵查表值
|
||||||
# 后的直调;hero_attack 与 board_typed 两消费面同享)。命中批由 _ctx_rewrites 单次发射后传入。
|
# 后的直调;hero_attack 与 board_typed 两消费面同享)。命中批由 _ctx_rewrites 单次发射后传入。
|
||||||
# 淬毒刃纹(行 triggers clamp_check
|
# 淬毒刃纹(行 triggers clamp_check
|
||||||
# modify(mode:clamp_bonus) 订阅命中并入本处 delta 合计;mode 路由=主角攻击面专享,
|
# modify(mode:clamp_bonus) 订阅命中并入本处 delta 合计;mode 路由=主角攻击面专享,
|
||||||
@@ -338,8 +309,8 @@ func _ctx_clamp_delta(atk_type: String, armor: String, clamp_hits: Array) -> int
|
|||||||
return cdelta
|
return cdelta
|
||||||
|
|
||||||
|
|
||||||
# 基值装配(基值+单位标记加伤+矿工重锤增伤面+加法族(attack_bonus/
|
# 基值装配(基值+单位标记加伤+加法族(attack_bonus/
|
||||||
# value_counter 层值)+计数器施加(attack_commit 用后清零行——命中序=声明序)+spike 倍乘。
|
# value_counter 层值)+计数器施加(attack_commit 用后清零行——命中序=声明序)。
|
||||||
func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
||||||
var ac_hits: Array[Variant] = ctx["ac_hits"]
|
var ac_hits: Array[Variant] = ctx["ac_hits"]
|
||||||
var ac_payload: Dictionary[Variant, Variant] = ctx["ac_payload"]
|
var ac_payload: Dictionary[Variant, Variant] = ctx["ac_payload"]
|
||||||
@@ -347,10 +318,6 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
|||||||
# 单位标记加伤(处刑台 target_attack_bonus 挂单位字典 fx_atk_bonus 键;
|
# 单位标记加伤(处刑台 target_attack_bonus 挂单位字典 fx_atk_bonus 键;
|
||||||
# 阈值沿发射点已写入,本处通用消费——对该敌伤害加算)
|
# 阈值沿发射点已写入,本处通用消费——对该敌伤害加算)
|
||||||
base_value += float(int((ctx["target"] as Dictionary).get("fx_atk_bonus", 0)))
|
base_value += float(int((ctx["target"] as Dictionary).get("fx_atk_bonus", 0)))
|
||||||
# 按序改写族第五拍:矿工重锤增伤面(交换的正向侧)
|
|
||||||
for h in ac_hits:
|
|
||||||
if String(h.get("kind", "")) == "modify_ticket" and int(h.get("trade_atk", 0)) > 0:
|
|
||||||
base_value *= 1.0 + float(int(h.trade_atk)) / 100.0
|
|
||||||
# 加法族:attack_bonus per 计数器层值(层数×value 加算)。
|
# 加法族:attack_bonus per 计数器层值(层数×value 加算)。
|
||||||
# value_counter 扩展〔疼痛记忆/弃图兑换/陷阱本能——rider 值=计数器账面,
|
# value_counter 扩展〔疼痛记忆/弃图兑换/陷阱本能——rider 值=计数器账面,
|
||||||
# 值读于施加时点=命中序先行 rider 后清零行〕
|
# 值读于施加时点=命中序先行 rider 后清零行〕
|
||||||
@@ -365,11 +332,6 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
|||||||
if String(h.get("kind", "")) == "counter_add":
|
if String(h.get("kind", "")) == "counter_add":
|
||||||
var set_v = h.get("set", null)
|
var set_v = h.get("set", null)
|
||||||
_port.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
|
_port.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
|
||||||
# 任意真族:modify_ticket mode=spike 满层倍乘(强制必中已在折扣拍承载)
|
|
||||||
if ctx["spike_ready"]:
|
|
||||||
for h in ac_hits:
|
|
||||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "spike":
|
|
||||||
base_value *= float(int(h.get("value", 1)))
|
|
||||||
return base_value
|
return base_value
|
||||||
|
|
||||||
|
|
||||||
@@ -391,7 +353,7 @@ func _hero_attack_redeem(t: Dictionary, ctx: Dictionary, base_value: float) -> D
|
|||||||
var pooled: int = DamageMath.pool_damage(rolled, clamped_pool("hero_offense", StatusContainer.OWNER_HERO), clamped_pool("enemy_defense", StatusContainer.owner_key_for(target)))
|
var pooled: int = DamageMath.pool_damage(rolled, clamped_pool("hero_offense", StatusContainer.OWNER_HERO), clamped_pool("enemy_defense", StatusContainer.owner_key_for(target)))
|
||||||
var landed: int = maxi(int(db.combat.settlement.damage_roll.damage_floor), pooled)
|
var landed: int = maxi(int(db.combat.settlement.damage_roll.damage_floor), pooled)
|
||||||
# 加法族:英雄侧 rider(enemy_skill rider 对称位补齐口径)——后置必中附加,独立于掷点与乘区
|
# 加法族:英雄侧 rider(enemy_skill rider 对称位补齐口径)——后置必中附加,独立于掷点与乘区
|
||||||
# (奥术余烬「普攻命中后恒定结算」语义);猎巢人巢控光环(per nest_count)/矿工的执拗开格加成
|
# (普攻命中后恒定结算语义);巢控光环(per nest_count)/开格 streak 加成
|
||||||
# (per dig_streak、cap 封顶)同通道合计;档一质变 rider+1 / 档二(crit 时)rider 乘暴击倍率。
|
# (per dig_streak、cap 封顶)同通道合计;档一质变 rider+1 / 档二(crit 时)rider 乘暴击倍率。
|
||||||
# rider 不改变下限语义(landed 含 rider 后不再过 floor)。
|
# rider 不改变下限语义(landed 含 rider 后不再过 floor)。
|
||||||
var hero_rider := int(_fact_or("rider_tier_bonus") or 0) # or 0=未绑缺省与 int(null) 缺省同值(int() 构造拒 null——端口缺省 null 面的空值合并)
|
var hero_rider := int(_fact_or("rider_tier_bonus") or 0) # or 0=未绑缺省与 int(null) 缺省同值(int() 构造拒 null——端口缺省 null 面的空值合并)
|
||||||
@@ -421,7 +383,7 @@ func _kill_effects(t: Dictionary, target: Dictionary) -> void:
|
|||||||
_port.reveal_effect() # 斩首学者——击杀揭示 1 格(端口路由宿主入队,授予段末兑付)
|
_port.reveal_effect() # 斩首学者——击杀揭示 1 格(端口路由宿主入队,授予段末兑付)
|
||||||
|
|
||||||
|
|
||||||
# 交付:即时执行族(碎甲震击打重甲附加「护甲裂解」——复用 off_guard,零新状态行;
|
# 交付:即时执行族(重甲附加「护甲裂解」——复用 off_guard,零新状态行;
|
||||||
# apply_effect 域闭/重复授予由状态容器自行守卫)/标签装配/明细行发射/兑现登记。
|
# apply_effect 域闭/重复授予由状态容器自行守卫)/标签装配/明细行发射/兑现登记。
|
||||||
func _hero_attack_deliver(t: Dictionary, ctx: Dictionary, redemption: Dictionary) -> void:
|
func _hero_attack_deliver(t: Dictionary, ctx: Dictionary, redemption: Dictionary) -> void:
|
||||||
var payload: Dictionary[Variant, Variant] = redemption["payload"]
|
var payload: Dictionary[Variant, Variant] = redemption["payload"]
|
||||||
@@ -524,11 +486,11 @@ func _resolve_board_typed(t: Dictionary) -> void:
|
|||||||
var armor_b: String = String(target.get("armor_type", "light"))
|
var armor_b: String = String(target.get("armor_type", "light"))
|
||||||
var atk_b: String = String(t.attack_type)
|
var atk_b: String = String(t.attack_type)
|
||||||
# clamp_check 发射+施加(克制判定修正点棋盘面;与 hero_attack 同表同点:
|
# clamp_check 发射+施加(克制判定修正点棋盘面;与 hero_attack 同表同点:
|
||||||
# modify delta 订阅改写合计进克制点数;discount_shift 档位面属主角攻击专享,本面不施加)
|
# modify delta 订阅改写合计进克制点数;带模式行只施放于主角攻击面,本面不施加)
|
||||||
var cdelta: int = _counter_delta(atk_b, armor_b)
|
var cdelta: int = _counter_delta(atk_b, armor_b)
|
||||||
if atk_b != "":
|
if atk_b != "":
|
||||||
for h in _fx_hits("clamp_check", {"matchup": atk_b + "_vs_" + armor_b}):
|
for h in _fx_hits("clamp_check", {"matchup": atk_b + "_vs_" + armor_b}):
|
||||||
# 无模式 delta 才入棋盘窗(mode 路由:clamp_bonus=主角攻击面专享、discount_shift=折扣档面)
|
# 无模式 delta 才入棋盘窗(mode 路由:带模式行=主角攻击面专享,棋盘窗只吃无模式 delta)
|
||||||
if String(h.get("kind", "")) == "modify_ticket" and h.has("delta") and String(h.get("mode", "")) == "":
|
if String(h.get("kind", "")) == "modify_ticket" and h.has("delta") and String(h.get("mode", "")) == "":
|
||||||
cdelta += int(h.delta)
|
cdelta += int(h.delta)
|
||||||
var dealt: int = DamageMath.counter_component(int(t.base_value), cdelta, int(db.combat.settlement.damage_roll.damage_floor))
|
var dealt: int = DamageMath.counter_component(int(t.base_value), cdelta, int(db.combat.settlement.damage_roll.damage_floor))
|
||||||
@@ -619,15 +581,6 @@ func _counter_delta(attack_type: String, armor: String) -> int:
|
|||||||
return int(row.get(armor, 0))
|
return int(row.get(armor, 0))
|
||||||
|
|
||||||
|
|
||||||
# 折扣档改善(猎弱本能——折扣表向全额方向移 value 档;查不到当前档 = 不动防御口径)
|
|
||||||
func _discount_shift_up(discount: int, shift: int) -> int:
|
|
||||||
var tbl: Array[Variant] = db.combat.settlement.damage_roll.roll_tier_discounts
|
|
||||||
var idx := tbl.find(discount)
|
|
||||||
if idx < 0:
|
|
||||||
return discount
|
|
||||||
return int(tbl[mini(tbl.size() - 1, idx + shift)])
|
|
||||||
|
|
||||||
|
|
||||||
# 池内加算 → clamp [-100,+100](池间乘算归 DamageMath.pool_damage 调用侧);
|
# 池内加算 → clamp [-100,+100](池间乘算归 DamageMath.pool_damage 调用侧);
|
||||||
# 池按个体读(增益状态 v1.5):主角侧池传 OWNER_HERO,敌方侧池传被打者/施放者个体键——
|
# 池按个体读(增益状态 v1.5):主角侧池传 OWNER_HERO,敌方侧池传被打者/施放者个体键——
|
||||||
# 乘区只合计该个体名下实例(B 敌的削弱不进 A 敌的账)
|
# 乘区只合计该个体名下实例(B 敌的削弱不进 A 敌的账)
|
||||||
@@ -668,4 +621,4 @@ func _target_for(rule: String) -> Variant:
|
|||||||
|
|
||||||
func _ineffective_row(t: Dictionary, reason: String) -> void:
|
func _ineffective_row(t: Dictionary, reason: String) -> void:
|
||||||
emit_row_cb.call({"type": "reward_ineffective", "source_class": String(t.source_class), "origin_cell": t.origin_cell, "highlight": String(t.highlight)}, int(t.round_index),
|
emit_row_cb.call({"type": "reward_ineffective", "source_class": String(t.source_class), "origin_cell": t.origin_cell, "highlight": String(t.highlight)}, int(t.round_index),
|
||||||
"%s 未生效(%s)" % [String(t.display), reason], 0, {"batch_key": String(t.context.get("batch_key", "")), "deferred": true})
|
"%s 未生效(%s)" % [String(t.display), reason], 0, {"batch_key": String(t.context.get("batch_key", "")), "deferred": true, "reason": "no_enemy_alive"})
|
||||||
+10
-10
@@ -23,11 +23,11 @@ const MINE_EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "seal_se
|
|||||||
"refresh_request", "board_refreshed"]
|
"refresh_request", "board_refreshed"]
|
||||||
|
|
||||||
## 效果类型词汇(解释器 switch 闭集——词表实数以 EFFECT_KINDS 常量为准,含共享行拆型:
|
## 效果类型词汇(解释器 switch 闭集——词表实数以 EFFECT_KINDS 常量为准,含共享行拆型:
|
||||||
## grant_gp/bias_wallet、counter_add/counter_spend、reveal_tiles/remove_mines/refresh_pick、
|
## counter_add/counter_spend、reveal_tiles/remove_mines/refresh_pick、
|
||||||
## bias_rewards/preview。需求卡片标题计 23 系笔误,落码按行内容全收——commit 留痕)
|
## bias_rewards/preview。需求卡片标题计 23 系笔误,落码按行内容全收——commit 留痕)
|
||||||
const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open_ticket",
|
const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open_ticket",
|
||||||
"attack_bonus", "yield_mult", "spawn_spell", "grant_material",
|
"attack_bonus", "yield_mult", "spawn_spell", "grant_material",
|
||||||
"grant_ap", "grant_gp", "bias_wallet", "shield", "spike", "apply_status", "counter_add",
|
"grant_ap", "grant_gp", "shield", "apply_status", "counter_add",
|
||||||
"counter_spend", "reveal_tiles", "remove_mines", "refresh_pick",
|
"counter_spend", "reveal_tiles", "remove_mines", "refresh_pick",
|
||||||
"bias_rewards", "preview",
|
"bias_rewards", "preview",
|
||||||
# 六型效果(奇物.md 基础件表 27 件声明清单):
|
# 六型效果(奇物.md 基础件表 27 件声明清单):
|
||||||
@@ -52,17 +52,17 @@ const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open
|
|||||||
|
|
||||||
## fact 条件词汇(封闭枚举——payload 同名键直读面〔fact 取值序 payload
|
## fact 条件词汇(封闭枚举——payload 同名键直读面〔fact 取值序 payload
|
||||||
## 优先——effect_engine._fact_value 既有机制〕。new_resource_type=首开资源类型〔地质学家〕;
|
## 优先——effect_engine._fact_value 既有机制〕。new_resource_type=首开资源类型〔地质学家〕;
|
||||||
## is_edge_cell=边缘格〔边陲矿工〕;is_blank_zero=空白连锁〔跳格采掘〕;dug_under_seal=被挖格
|
## is_edge_cell=边缘格〔边陲矿工〕;is_blank_zero=空白连锁〔跳格采掘〕;ap_exhausted_last=上轮
|
||||||
## 当时有封印〔破封一击〕;ap_exhausted_last=上轮 AP 耗尽〔一滴不剩〕;hp_ratio=生命比例〔背水
|
## AP 耗尽〔一滴不剩〕;hp_ratio=生命比例〔背水
|
||||||
## 06 前置条兑付〕;amount=单次伤害量〔保险丝〕;ap_left=停手剩余 AP〔弃图兑换〕)
|
## 06 前置条兑付〕;amount=单次伤害量〔保险丝〕;ap_left=停手剩余 AP〔弃图兑换〕)
|
||||||
const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_armor_class",
|
const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_armor_class",
|
||||||
"seals_count", "nest_count", "round_index", "counter",
|
"seals_count", "nest_count", "round_index", "counter",
|
||||||
"new_resource_type", "is_edge_cell", "is_blank_zero", "dug_under_seal",
|
"new_resource_type", "is_edge_cell", "is_blank_zero",
|
||||||
"ap_exhausted_last", "hp_ratio", "amount", "ap_left", "pct",
|
"ap_exhausted_last", "hp_ratio", "amount", "ap_left", "pct",
|
||||||
"battle_index"] # 关卡域战斗序(1 基,enc 携带;开局姿态组「每关首轮窗」条件面)
|
"battle_index"] # 关卡域战斗序(1 基,enc 携带;开局姿态组「每关首轮窗」条件面)
|
||||||
|
|
||||||
## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满〔掘进蓄能〕、
|
## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满、
|
||||||
## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较〔深挖钻头配额〕、
|
## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较(计数器配额面)、
|
||||||
## ends_with=后缀匹配〔对某甲族的泛条件〕、mod_eq=取模余数判定〔双管镐每第 2 次——value=模数
|
## ends_with=后缀匹配〔对某甲族的泛条件〕、mod_eq=取模余数判定〔双管镐每第 2 次——value=模数
|
||||||
## ref=余数;dispatch 预评估口径〔when 于命中前读计数器现值〕下「每第 N 次」系用 ref=N-1 表达〕。
|
## ref=余数;dispatch 预评估口径〔when 于命中前读计数器现值〕下「每第 N 次」系用 ref=N-1 表达〕。
|
||||||
## 均系映射表现状条件装进 fact 的查询面落法,白名单覆盖)
|
## 均系映射表现状条件装进 fact 的查询面落法,白名单覆盖)
|
||||||
@@ -79,7 +79,7 @@ const WHEN_KEYS := ["fact", "op", "value", "id", "ref", "value_from"]
|
|||||||
## axis=bonus_delta 加算区轴向)
|
## axis=bonus_delta 加算区轴向)
|
||||||
const DO_KEYS := ["kind", "value", "value_from", "delta", "delta_from", "mult", "mult_from",
|
const DO_KEYS := ["kind", "value", "value_from", "delta", "delta_from", "mult", "mult_from",
|
||||||
"cap", "cap_from", "cost_mult", "per", "divisor", "dtype", "mode", "channel", "counter_id",
|
"cap", "cap_from", "cost_mult", "per", "divisor", "dtype", "mode", "channel", "counter_id",
|
||||||
"set", "status_id", "label", "fallback", "target_kinds", "trade_atk", "trade_hit",
|
"set", "status_id", "label", "fallback", "target_kinds",
|
||||||
"value_event", "value_counter", "axis"]
|
"value_event", "value_counter", "axis"]
|
||||||
|
|
||||||
## 主动件分发通道(不经事件订阅——刷新/显影/移除是玩家主动动作;use_treasure 按 kind 分发)
|
## 主动件分发通道(不经事件订阅——刷新/显影/移除是玩家主动动作;use_treasure 按 kind 分发)
|
||||||
@@ -154,7 +154,7 @@ func _push_tree_rule(rk: String, params: Dictionary[Variant, Variant]) -> void:
|
|||||||
"do": {"kind": "shield", "value": int(params["shield"])}}, {})
|
"do": {"kind": "shield", "value": int(params["shield"])}}, {})
|
||||||
"sense_sharp":
|
"sense_sharp":
|
||||||
# 锋=踩中危险格伤害减半·每关限次——mine_hit 挂点现成(damage_mult 收集→halve_pct,
|
# 锋=踩中危险格伤害减半·每关限次——mine_hit 挂点现成(damage_mult 收集→halve_pct,
|
||||||
# 与惊巢反制同路径;伤害在结算战斗段末兑付,探索阶段零改动)
|
# 与挖掘惩罚减半同路径;伤害在结算战斗段末兑付,探索阶段零改动)
|
||||||
_push_trigger("tree", rk, {"on": "mine_hit",
|
_push_trigger("tree", rk, {"on": "mine_hit",
|
||||||
"when": [{"fact": "counter", "id": "lvl_tree_sense_sharp_used", "op": "lt", "value": int(params["cap_per_level"])}],
|
"when": [{"fact": "counter", "id": "lvl_tree_sense_sharp_used", "op": "lt", "value": int(params["cap_per_level"])}],
|
||||||
"do": {"kind": "damage_mult", "value": int(params["halve_pct"])}}, {})
|
"do": {"kind": "damage_mult", "value": int(params["halve_pct"])}}, {})
|
||||||
@@ -449,7 +449,7 @@ static func _vtr_from_refs(rid: String, tr: Dictionary, row: Dictionary, errs: A
|
|||||||
## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap、
|
## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap、
|
||||||
## counter_add、shield——发射点逐条累加收集器。
|
## counter_add、shield——发射点逐条累加收集器。
|
||||||
## 乘法族(收集后一次施加,正负分桶):yield_mult、damage_mult。
|
## 乘法族(收集后一次施加,正负分桶):yield_mult、damage_mult。
|
||||||
## 任意真族(任一命中即生效):spawn_spell、spike。
|
## 任意真族(任一命中即生效):spawn_spell。
|
||||||
## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。
|
## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。
|
||||||
## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。
|
## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。
|
||||||
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、
|
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ extends RefCounted
|
|||||||
## 揭示事实流:每格首次进入已开集恰发一次(已开格零事件)。
|
## 揭示事实流:每格首次进入已开集恰发一次(已开格零事件)。
|
||||||
## 载荷键集(四处发射位并集):cell: Vector2i/kind: "safe"|"mine"/digit: int(安全格邻雷数;危险格 -1)/
|
## 载荷键集(四处发射位并集):cell: Vector2i/kind: "safe"|"mine"/digit: int(安全格邻雷数;危险格 -1)/
|
||||||
## variant_ids: Array(地形变异身份,危险格空集)/channel: "initial"|"dig"|"chain"|"fx_reveal"/
|
## variant_ids: Array(地形变异身份,危险格空集)/channel: "initial"|"dig"|"chain"|"fx_reveal"/
|
||||||
## resource: bool(格面资源兑付资格:initial=false,其余 true)/dug_under_seal: bool(首格带封印直挖标记——
|
## resource: bool(格面资源兑付资格:initial=false,其余 true)。
|
||||||
## initial 通道不发此键)。
|
|
||||||
## 发送时点:initial=install_board 初始展开逐格;dig/chain=_do_dig 揭示闭包内(本格 AP 扣费在其后);
|
## 发送时点:initial=install_board 初始展开逐格;dig/chain=_do_dig 揭示闭包内(本格 AP 扣费在其后);
|
||||||
## fx_reveal=fx_reveal 闭包内(零 AP 消耗零相位要求)。
|
## fx_reveal=fx_reveal 闭包内(零 AP 消耗零相位要求)。
|
||||||
## 消费方依赖:战斗结算 _on_cell_revealed 以 resource 分流缓冲(fx_reveal 由兑付点直入账,禁二次缓冲)、
|
## 消费方依赖:战斗结算 _on_cell_revealed 以 resource 分流缓冲(fx_reveal 由兑付点直入账,禁二次缓冲)、
|
||||||
@@ -94,14 +93,16 @@ func has_seal(c: Vector2i) -> bool:
|
|||||||
return _seals.has(c)
|
return _seals.has(c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func revealed_cells() -> Array:
|
func revealed_cells() -> Array:
|
||||||
return _revealed.keys()
|
return _revealed.keys()
|
||||||
|
|
||||||
|
|
||||||
func _safe_remaining() -> int:
|
func _safe_remaining() -> int:
|
||||||
|
# 清图口径 = 已挖 ∪ 已封印(封印受理即揭示改版——封掉的安全格计入完成)
|
||||||
var n := 0
|
var n := 0
|
||||||
for c in _board.safe_cells():
|
for c in _board.safe_cells():
|
||||||
if not _revealed.has(c):
|
if not _revealed.has(c) and not _seals.has(c):
|
||||||
n += 1
|
n += 1
|
||||||
return n
|
return n
|
||||||
|
|
||||||
@@ -266,25 +267,41 @@ func settle_batch(intents: Array) -> Array:
|
|||||||
|
|
||||||
func _classify(intent: Dictionary) -> int:
|
func _classify(intent: Dictionary) -> int:
|
||||||
# 0 = C_dig(执行后清图——真模拟,禁计数器捷径);1 = C_stop;2 = C_other
|
# 0 = C_dig(执行后清图——真模拟,禁计数器捷径);1 = C_stop;2 = C_other
|
||||||
|
# 清图口径 = 已挖 ∪ 已封印(封印受理即揭示改版——「能清图的挖或封」同归最先类)
|
||||||
if intent.get("action", "") == "dig":
|
if intent.get("action", "") == "dig":
|
||||||
var c: Vector2i = intent.get("cell", Vector2i(-9, -9))
|
var c: Vector2i = intent.get("cell", Vector2i(-9, -9))
|
||||||
if _board_face_dig(c) == "" and not _board.is_mine(c):
|
if _board_face_dig(c) == "" and not _board.is_mine(c):
|
||||||
# 模拟 Chain(O, c) 后清图判定——挖封印格同口径:本格封印视为已隐式退役(其余封印照挡)
|
# 模拟 Chain(O, c) 后清图判定——真模拟禁计数器捷径(连锁不越封印,真封印集口径)
|
||||||
var sim_seals: Dictionary[Variant, Variant] = _seals.duplicate()
|
var chain := _chain_closure(c, _seals)
|
||||||
sim_seals.erase(c)
|
|
||||||
var chain := _chain_closure(c, sim_seals) # 与真实执行同口径——空封印集捷径会在封印挡连锁时误判 C_dig(排雷玩法:真模拟)
|
|
||||||
var remaining := 0
|
var remaining := 0
|
||||||
for sc in _board.safe_cells():
|
for sc in _board.safe_cells():
|
||||||
if not _revealed.has(sc) and not chain.has(sc):
|
if not _revealed.has(sc) and not chain.has(sc) and not _seals.has(sc):
|
||||||
remaining += 1
|
remaining += 1
|
||||||
if remaining == 0:
|
if remaining == 0:
|
||||||
return 0
|
return 0
|
||||||
return 2
|
return 2
|
||||||
|
if intent.get("action", "") == "seal_place":
|
||||||
|
return _classify_seal(intent.get("cell", Vector2i(-9, -9)))
|
||||||
if intent.get("action", "") == "stop":
|
if intent.get("action", "") == "stop":
|
||||||
return 1
|
return 1
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
# 封印意图的清图预判分类(批次语义序「能清图的封」取数面——受理合法性模拟与清图口径模拟)
|
||||||
|
func _classify_seal(c: Vector2i) -> int:
|
||||||
|
if not _board.in_bounds(c) or is_revealed(c) or has_seal(c) or _removed.has(c):
|
||||||
|
return 2
|
||||||
|
if _board.is_mine(c):
|
||||||
|
return 2 # 封危险格不清图(封印受理即揭示——身份当场可见但安全格分母不减)
|
||||||
|
# 模拟封印受理后清图判定(换装口径:安全格完成 = 已揭示 ∪ 已封印)
|
||||||
|
var sim_seals: Dictionary[Variant, Variant] = _seals.duplicate()
|
||||||
|
sim_seals[c] = true
|
||||||
|
for sc in _board.safe_cells():
|
||||||
|
if not _revealed.has(sc) and not sim_seals.has(sc):
|
||||||
|
return 2
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
func _execute(intent: Dictionary) -> Dictionary:
|
func _execute(intent: Dictionary) -> Dictionary:
|
||||||
match intent.get("action", ""):
|
match intent.get("action", ""):
|
||||||
"dig":
|
"dig":
|
||||||
@@ -305,16 +322,8 @@ func _do_dig(c: Vector2i) -> Dictionary:
|
|||||||
var sub := _board_face_dig(c)
|
var sub := _board_face_dig(c)
|
||||||
if sub != "":
|
if sub != "":
|
||||||
return _outcome(false, "rejected", "board_face", sub)
|
return _outcome(false, "rejected", "board_face", sub)
|
||||||
# 挖封印格(封印不可逆):本格封印事务内隐式退役——链闭包按「本格无封印、其余封印照挡」
|
# 真模拟连锁与清图(F2/F1——单一实现两名字;连锁不越封印,挖封印格已被合法性表拒绝)
|
||||||
# 计算(封印格为 0 时连锁照常外扩);request_dig 被拒则封印原地保留(事务性),受理后该封印轮末不判
|
var chain := _chain_closure(c, _seals)
|
||||||
# (发射面基线 = 在场封印——标中/标空兑付让位于挖掘本体结局,四情况②④)。
|
|
||||||
var was_sealed := has_seal(c)
|
|
||||||
var eff_seals: Dictionary[Variant, Variant] = _seals
|
|
||||||
if was_sealed:
|
|
||||||
eff_seals = _seals.duplicate()
|
|
||||||
eff_seals.erase(c)
|
|
||||||
# 真模拟连锁与清图(F2/F1——单一实现两名字)
|
|
||||||
var chain := _chain_closure(c, eff_seals)
|
|
||||||
var clears: bool = _cleared_after(chain)
|
var clears: bool = _cleared_after(chain)
|
||||||
# F2 口径:chain_size = |O′ ∖ (O ∪ {c})|——闭包含已开集 O,只数新开格(不含首格)
|
# F2 口径:chain_size = |O′ ∖ (O ∪ {c})|——闭包含已开集 O,只数新开格(不含首格)
|
||||||
var chain_size := 0
|
var chain_size := 0
|
||||||
@@ -325,10 +334,8 @@ func _do_dig(c: Vector2i) -> Dictionary:
|
|||||||
if not action_economy.request_dig(chain_size, clears):
|
if not action_economy.request_dig(chain_size, clears):
|
||||||
return _outcome(false, "rejected", "resource_face", "")
|
return _outcome(false, "rejected", "resource_face", "")
|
||||||
# 事务内执行:首格 + 连锁新格揭示(BFS 规范序,零特判);事件 = O′ ∖ O
|
# 事务内执行:首格 + 连锁新格揭示(BFS 规范序,零特判);事件 = O′ ∖ O
|
||||||
if was_sealed:
|
var reveal_order: Array[Variant] = _chain_reveal_order(c, _seals)
|
||||||
_seals.erase(c)
|
_reveal_chain(c, reveal_order)
|
||||||
var reveal_order: Array[Variant] = _chain_reveal_order(c, eff_seals)
|
|
||||||
_reveal_chain(c, reveal_order, was_sealed)
|
|
||||||
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
||||||
_emit_round_end_seals_and_payload()
|
_emit_round_end_seals_and_payload()
|
||||||
return _outcome(true, "executed", "", "")
|
return _outcome(true, "executed", "", "")
|
||||||
@@ -337,8 +344,7 @@ func _do_dig(c: Vector2i) -> Dictionary:
|
|||||||
## 连锁揭示域:首格+连锁新格揭示(BFS 规范序——cell_revealed 发射序即链序,整体随段搬迁)。
|
## 连锁揭示域:首格+连锁新格揭示(BFS 规范序——cell_revealed 发射序即链序,整体随段搬迁)。
|
||||||
## 格面资源资格:chain/dig 恒 true——安全格与危险格一视同仁(危险格亦携带,
|
## 格面资源资格:chain/dig 恒 true——安全格与危险格一视同仁(危险格亦携带,
|
||||||
## 负向兑付归 战斗结算 极性路由);initial(封锁格)恒 false。资源本体与极性不在本系统。
|
## 负向兑付归 战斗结算 极性路由);initial(封锁格)恒 false。资源本体与极性不在本系统。
|
||||||
## dug_under_seal = 首格带封印直挖标记(战斗结算 情况④兑付改判消费;连锁格恒 false——连锁不越封印)
|
func _reveal_chain(c: Vector2i, reveal_order: Array) -> void:
|
||||||
func _reveal_chain(c: Vector2i, reveal_order: Array, was_sealed: bool) -> void:
|
|
||||||
for rc in reveal_order:
|
for rc in reveal_order:
|
||||||
if _revealed.has(rc):
|
if _revealed.has(rc):
|
||||||
continue # 闭包可穿过已开区——已开格零事件(cell_revealed × |O′ ∖ O|)
|
continue # 闭包可穿过已开区——已开格零事件(cell_revealed × |O′ ∖ O|)
|
||||||
@@ -348,14 +354,12 @@ func _reveal_chain(c: Vector2i, reveal_order: Array, was_sealed: bool) -> void:
|
|||||||
cell_revealed.emit({
|
cell_revealed.emit({
|
||||||
"cell": rc, "kind": "mine", "digit": -1,
|
"cell": rc, "kind": "mine", "digit": -1,
|
||||||
"variant_ids": [], "channel": channel, "resource": true,
|
"variant_ids": [], "channel": channel, "resource": true,
|
||||||
"dug_under_seal": was_sealed and rc == c,
|
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
_revealed[rc] = {"kind": "safe", "digit": _board.digit_of(rc)}
|
_revealed[rc] = {"kind": "safe", "digit": _board.digit_of(rc)}
|
||||||
cell_revealed.emit({
|
cell_revealed.emit({
|
||||||
"cell": rc, "kind": "safe", "digit": _board.digit_of(rc),
|
"cell": rc, "kind": "safe", "digit": _board.digit_of(rc),
|
||||||
"variant_ids": _board.variant_ids(rc), "channel": channel, "resource": true,
|
"variant_ids": _board.variant_ids(rc), "channel": channel, "resource": true,
|
||||||
"dug_under_seal": was_sealed and rc == c,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -366,9 +370,10 @@ func _board_face_dig(c: Vector2i) -> String:
|
|||||||
return "not_adjacent"
|
return "not_adjacent"
|
||||||
if is_revealed(c):
|
if is_revealed(c):
|
||||||
return "target_revealed"
|
return "target_revealed"
|
||||||
|
if has_seal(c):
|
||||||
|
return "target_sealed" # 封印受理即揭示、不可再挖开(封印承诺 = 对该格的最终处置——改判路径已退役)
|
||||||
if _removed.has(c):
|
if _removed.has(c):
|
||||||
return "target_removed" # 中立移除格不可交互(拒绝先于消耗,pattern 1 board_face 腿)
|
return "target_removed" # 中立移除格不可交互(拒绝先于消耗,pattern 1 board_face 腿)
|
||||||
# 封印不拦挖掘(封印不可逆):有封印格直接挖 = 对承诺的兑现,兑付改判归 战斗结算。
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@@ -387,17 +392,14 @@ func fx_reveal(c: Vector2i) -> bool:
|
|||||||
cell_revealed.emit({
|
cell_revealed.emit({
|
||||||
"cell": rc, "kind": "safe", "digit": _board.digit_of(rc),
|
"cell": rc, "kind": "safe", "digit": _board.digit_of(rc),
|
||||||
"variant_ids": _board.variant_ids(rc), "channel": "fx_reveal", "resource": true,
|
"variant_ids": _board.variant_ids(rc), "channel": "fx_reveal", "resource": true,
|
||||||
"dug_under_seal": false,
|
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
## 挖一格→真实翻开集只读预览(sim 信息面出口——与 _classify 同口径:本格封印视为已隐式退役、
|
## 挖一格→真实翻开集只读预览(sim 信息面出口——与 _classify 同口径:连锁不越封印、
|
||||||
## 其余封印照挡;复用 _chain_closure 闭包;零状态写入、零事件发射)
|
## 真封印集口径;复用 _chain_closure 闭包;零状态写入、零事件发射)
|
||||||
func preview_reveal(c: Vector2i) -> Array[Vector2i]:
|
func preview_reveal(c: Vector2i) -> Array[Vector2i]:
|
||||||
var sim_seals := _seals.duplicate()
|
var closure := _chain_closure(c, _seals)
|
||||||
sim_seals.erase(c)
|
|
||||||
var closure := _chain_closure(c, sim_seals)
|
|
||||||
var out: Array[Vector2i] = []
|
var out: Array[Vector2i] = []
|
||||||
for cc in closure.keys():
|
for cc in closure.keys():
|
||||||
if cc != c and not _revealed.has(cc):
|
if cc != c and not _revealed.has(cc):
|
||||||
@@ -436,34 +438,44 @@ func _chain_reveal_order(start: Vector2i, seal_set: Dictionary) -> Array:
|
|||||||
|
|
||||||
|
|
||||||
func _cleared_after(chain: Dictionary) -> bool:
|
func _cleared_after(chain: Dictionary) -> bool:
|
||||||
|
# 清图口径 = 已挖 ∪ 已封印(与 _safe_remaining 同源——私有共享口径单点,禁第三处重复实现)
|
||||||
for c in _board.safe_cells():
|
for c in _board.safe_cells():
|
||||||
if not _revealed.has(c) and not chain.has(c):
|
if not _revealed.has(c) and not chain.has(c) and not _seals.has(c):
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
# ---- 封印 ----
|
# ---- 封印 ----
|
||||||
|
|
||||||
func _do_seal_place(c: Vector2i) -> Dictionary:
|
# 封印棋盘面合法性(board_face 拒绝情形序:目录外/不相邻/已开/已有封印/已移除——与挖掘合法性同构分域)
|
||||||
var sub := ""
|
func _seal_face_reject(c: Vector2i) -> String:
|
||||||
if not _board.in_bounds(c):
|
if not _board.in_bounds(c):
|
||||||
sub = "out_of_catalog"
|
return "out_of_catalog"
|
||||||
elif not (seal_range_free or _adjacent_to_hero(c)):
|
if not (seal_range_free or _adjacent_to_hero(c)):
|
||||||
sub = "not_adjacent" # 信标网络装配时豁免(封印不限相邻——封印动作仍按标准价计费,规则放宽仅可达性)
|
return "not_adjacent" # 信标网络装配时豁免(封印不限相邻——封印动作仍按标准价计费,规则放宽仅可达性)
|
||||||
elif is_revealed(c):
|
if is_revealed(c):
|
||||||
sub = "target_revealed"
|
return "target_revealed"
|
||||||
elif has_seal(c):
|
if has_seal(c):
|
||||||
sub = "seal_present"
|
return "seal_present"
|
||||||
elif _removed.has(c):
|
if _removed.has(c):
|
||||||
sub = "target_removed" # 中立移除格不可交互
|
return "target_removed" # 中立移除格不可交互
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
func _do_seal_place(c: Vector2i) -> Dictionary:
|
||||||
|
var sub := _seal_face_reject(c)
|
||||||
if sub != "":
|
if sub != "":
|
||||||
return _outcome(false, "rejected", "board_face", sub)
|
return _outcome(false, "rejected", "board_face", sub)
|
||||||
if not action_economy.try_spend("seal_place"):
|
if not action_economy.try_spend("seal_place"):
|
||||||
return _outcome(false, "rejected", "resource_face", "")
|
return _outcome(false, "rejected", "resource_face", "")
|
||||||
_seals[c] = true # 封印动作零格子事件外发(发射面封闭;反馈经调用返回值命令式驱动)
|
_seals[c] = true # 封印动作零格子事件外发(发射面封闭;反馈经调用返回值命令式驱动)
|
||||||
|
if _cleared_after({}):
|
||||||
|
# 封印受理即揭示改版:封掉最后安全格 = 清图完成——轮末仲裁走 cleared(行动经济
|
||||||
|
# notify_cleared 独立上报口,与 request_dig 的 cleared 语义同源;同帧覆盖 ap_exhausted)
|
||||||
|
action_economy.notify_cleared()
|
||||||
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
||||||
# 封印动作花完末点 AP 同样终结轮次(行动经济 三出口——AP 用完与动作种类无关;缺漏使 round_end
|
# 封印动作花完末点 AP 同样终结轮次(行动经济 三出口——AP 用完与动作种类无关;缺漏使 round_end
|
||||||
# 永不发出、战斗结算 的 Waiting 结算点永不到达 = 整局软锁)
|
# 永不发出、战斗结算 的 Waiting 结算点永不到达 = 整局软锁);清图收轮同此出口发判定批
|
||||||
_emit_round_end_seals_and_payload()
|
_emit_round_end_seals_and_payload()
|
||||||
return _outcome(true, "executed", "", "")
|
return _outcome(true, "executed", "", "")
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ var _refresh_x := 0 # 刷新件余量(每碰三选一重
|
|||||||
var _refresh_y := 0 # Y 冒险周期池(开局参数面注入,用完即无——营地升级行表值)
|
var _refresh_y := 0 # Y 冒险周期池(开局参数面注入,用完即无——营地升级行表值)
|
||||||
var _paid_refreshes := 0 # 本次停点已付费刷新次数(对齐商店 MC-1——GP 刷新价曲线输入,随停点创建清零=与商店进店清零同构)
|
var _paid_refreshes := 0 # 本次停点已付费刷新次数(对齐商店 MC-1——GP 刷新价曲线输入,随停点创建清零=与商店进店清零同构)
|
||||||
var _refresh_stock := 0 # 刷新存量账(冒险级——刷新券加仓;**不经 _refresh_x**:X 每停点重置会吞存量=写错账缺陷 F-1)
|
var _refresh_stock := 0 # 刷新存量账(冒险级——刷新券加仓;**不经 _refresh_x**:X 每停点重置会吞存量=写错账缺陷 F-1)
|
||||||
var _refresh_x_cap := 0 # 刷新件余量基数(装配集 effect_kinds 含 bonus_refresh 的行 magnitude 合计——
|
var _refresh_x_cap := 0 # 刷新件余量基数(现役目录无行源,恒 0;
|
||||||
# 宿主冒险开始时预算注入;装配集冒险期间锁死〔契约 8〕故预算与逐停点查询等价)
|
# 宿主冒险开始时预算注入;装配集冒险期间锁死〔契约 8〕故预算与逐停点查询等价)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+15
-26
@@ -1,5 +1,5 @@
|
|||||||
## 奖励授予件(自 battle_orchestrator 收编 grant 族):极性字典路由兑付(grant_routed——含封印溢价
|
## 奖励授予件(自 battle_orchestrator 收编 grant 族):极性字典路由兑付(grant_routed——含封印溢价
|
||||||
## 与惊巢反制减半)、三种行应用(flat 四分支/percent/gp)、伤害单据提交面(submit——案C 暂存闸承载)、
|
## 与挖掘惩罚减半)、三种行应用(flat 四分支/percent/gp)、伤害单据提交面(submit——案C 暂存闸承载)、
|
||||||
## 清图奖励与身份授予(完美封印第二份)、战斗内 GP 缓冲 escrow、秘宝使用四步编排(use_treasure——
|
## 清图奖励与身份授予(完美封印第二份)、战斗内 GP 缓冲 escrow、秘宝使用四步编排(use_treasure——
|
||||||
## 相位闸→校验→受理闸→逐 kind 应用→消耗)、揭示奖励兑付(reveal_redeem——fx_host flush 的兑付回调面)。
|
## 相位闸→校验→受理闸→逐 kind 应用→消耗)、揭示奖励兑付(reveal_redeem——fx_host flush 的兑付回调面)。
|
||||||
## 生命周期=随编排器(编排器 _init 同建同灭,每战新建)。
|
## 生命周期=随编排器(编排器 _init 同建同灭,每战新建)。
|
||||||
@@ -92,7 +92,7 @@ func reveal_redeem(cell: Vector2i, ri: int) -> void:
|
|||||||
# use_treasure 四步受理(registry use_orchestration 规范序——序即原子:
|
# use_treasure 四步受理(registry use_orchestration 规范序——序即原子:
|
||||||
# ① 相位 gate(Active——行动经济 phase getter)→ ② validate_use(目标校验读排雷玩法只读面,零消耗)→
|
# ① 相位 gate(Active——行动经济 phase getter)→ ② validate_use(目标校验读排雷玩法只读面,零消耗)→
|
||||||
# ②半 treasure_used 受理闸(counter_spend 订阅——消耗成功才受理)→ ③ 逐 kind 应用(顺序钉死:空间先、
|
# ②半 treasure_used 受理闸(counter_spend 订阅——消耗成功才受理)→ ③ 逐 kind 应用(顺序钉死:空间先、
|
||||||
# ap_grant 后——effect_kinds 列表序非运行时语义)→ ④ consume。
|
# 行动点授予后——effect_kinds 列表序非运行时语义)→ ④ consume。
|
||||||
# 拒绝全部发生在 ①②③(④合法输入下无失败路径);使用零 AP 成本(不经 try_spend)。
|
# 拒绝全部发生在 ①②③(④合法输入下无失败路径);使用零 AP 成本(不经 try_spend)。
|
||||||
# 结算明细无道具行(GDD——效果即时可见:overlay 呈现+AP 条刷新;AP 过账本 grant_ap 走 _reject 面)。
|
# 结算明细无道具行(GDD——效果即时可见:overlay 呈现+AP 条刷新;AP 过账本 grant_ap 走 _reject 面)。
|
||||||
func use_treasure(handle: int, target: Vector2i) -> Dictionary:
|
func use_treasure(handle: int, target: Vector2i) -> Dictionary:
|
||||||
@@ -127,7 +127,7 @@ func use_treasure(handle: int, target: Vector2i) -> Dictionary:
|
|||||||
return {"ok": true, "item_id": v.item_id, "resolved": v.resolved, "record": rec}
|
return {"ok": true, "item_id": v.item_id, "resolved": v.resolved, "record": rec}
|
||||||
|
|
||||||
|
|
||||||
# 受理闸(treasure_used 发射+施加:counter_spend 订阅=掘进蓄能积点账本,积点不足拒绝零消耗。
|
# 受理闸(treasure_used 发射+施加:counter_spend 订阅=付费积点账本,积点不足拒绝零消耗。
|
||||||
# 零 item_id 特判;拒绝文案读装配集积点进度——宿主 attune 读投影)
|
# 零 item_id 特判;拒绝文案读装配集积点进度——宿主 attune 读投影)
|
||||||
func _charge_gate(v: Dictionary, target: Vector2i) -> Dictionary:
|
func _charge_gate(v: Dictionary, target: Vector2i) -> Dictionary:
|
||||||
var tu_hits := fx_host.fx_emit("treasure_used", {"item_id": String(v.item_id), "target": target})
|
var tu_hits := fx_host.fx_emit("treasure_used", {"item_id": String(v.item_id), "target": target})
|
||||||
@@ -141,7 +141,7 @@ func _charge_gate(v: Dictionary, target: Vector2i) -> Dictionary:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
# ③ 逐 kind 应用(顺序钉死:空间先、ap_grant 后;拒收字典/空字典=受理——④ consume 前零消耗分支)
|
# ③ 逐 kind 应用(顺序钉死:空间先、行动点授予后;拒收字典/空字典=受理——④ consume 前零消耗分支)
|
||||||
func _apply_use_kinds(v: Dictionary, _target: Vector2i) -> Dictionary:
|
func _apply_use_kinds(v: Dictionary, _target: Vector2i) -> Dictionary:
|
||||||
var kinds: Array[Variant] = v.kinds
|
var kinds: Array[Variant] = v.kinds
|
||||||
if kinds.has("mine_reveal") or kinds.has("reveal_tiles"):
|
if kinds.has("mine_reveal") or kinds.has("reveal_tiles"):
|
||||||
@@ -157,10 +157,6 @@ func _apply_use_kinds(v: Dictionary, _target: Vector2i) -> Dictionary:
|
|||||||
var dig_reject := _safe_dig_open(v)
|
var dig_reject := _safe_dig_open(v)
|
||||||
if not dig_reject.is_empty():
|
if not dig_reject.is_empty():
|
||||||
return dig_reject
|
return dig_reject
|
||||||
if kinds.has("cell_removal"):
|
|
||||||
var blast_reject := _cell_removal_open(v)
|
|
||||||
if not blast_reject.is_empty():
|
|
||||||
return blast_reject
|
|
||||||
return {} # 空字典=受理
|
return {} # 空字典=受理
|
||||||
|
|
||||||
|
|
||||||
@@ -172,7 +168,7 @@ func _safe_dig_open(v: Dictionary) -> Dictionary:
|
|||||||
for c_v in v.resolved:
|
for c_v in v.resolved:
|
||||||
var c := Vector2i(c_v)
|
var c := Vector2i(c_v)
|
||||||
if fx_host.minesweeper.has_seal(c):
|
if fx_host.minesweeper.has_seal(c):
|
||||||
continue
|
continue # 封印格不代开(封印受理即揭示——天眼揭示绕开承诺格,零动作)
|
||||||
if fx_host.minesweeper.fx_reveal(c):
|
if fx_host.minesweeper.fx_reveal(c):
|
||||||
opened_any = true
|
opened_any = true
|
||||||
if not opened_any:
|
if not opened_any:
|
||||||
@@ -180,16 +176,6 @@ func _safe_dig_open(v: Dictionary) -> Dictionary:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
# 爆破工兵包兑付(中立移除危险格:未揭示/无封印/是雷过滤归排雷玩法;
|
|
||||||
# 邻接数字冻结零重算、清图分母零涉(危险格不入分母);空集拒绝零消耗——
|
|
||||||
# consume 之前 return(拒绝面注记扩「③内零消耗分支」),拒绝 reason 可呈现)
|
|
||||||
func _cell_removal_open(v: Dictionary) -> Dictionary:
|
|
||||||
var blasted: Array[Variant] = fx_host.minesweeper.remove_mines_in(v.resolved)
|
|
||||||
if blasted.is_empty():
|
|
||||||
return {"ok": false, "reason": "爆破工兵包:3×3 区域内无可移除危险格(须未揭示且未封印)"}
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
# 极性路由兑付(「动作 × 格型」矩阵的执行面:snap = 缓冲期冻结身份快照〔cell_type = 该格装板期
|
# 极性路由兑付(「动作 × 格型」矩阵的执行面:snap = 缓冲期冻结身份快照〔cell_type = 该格装板期
|
||||||
# 摇定的类型身份〕,polarity 由动作决定(开安全格/封印命中 = positive,开危险格/标错封印 = negative),
|
# 摇定的类型身份〕,polarity 由动作决定(开安全格/封印命中 = positive,开危险格/标错封印 = negative),
|
||||||
# 兑付行 = 奖励字典(类型, 极性)行。返回 true = percent 行实际生效(flat 行恒 false——兑付结果由行协议承载)。
|
# 兑付行 = 奖励字典(类型, 极性)行。返回 true = percent 行实际生效(flat 行恒 false——兑付结果由行协议承载)。
|
||||||
@@ -218,12 +204,12 @@ func grant_routed(snap: Dictionary, polarity: String, att: Dictionary) -> bool:
|
|||||||
row = row.duplicate()
|
row = row.duplicate()
|
||||||
row["power"] = int(round(int(row.power) * prem_pct / 100.0))
|
row["power"] = int(round(int(row.power) * prem_pct / 100.0))
|
||||||
row["premium_pct"] = prem_pct
|
row["premium_pct"] = prem_pct
|
||||||
# 惊巢反制(减半系数=mine_hit damage_mult 订阅命中〔行 value 50=减 50%,取整 ceil〕;
|
# 挖掘惩罚减半(减半系数=mine_hit damage_mult 订阅命中〔行 value 50=减 50%,取整 ceil〕;
|
||||||
# duplicate 隔离——减半不回写极性字典)
|
# duplicate 隔离——减半不回写极性字典)
|
||||||
if halve_pct > 0 and polarity == "negative" and source_class == "mine_hit":
|
if halve_pct > 0 and polarity == "negative" and source_class == "mine_hit":
|
||||||
row = row.duplicate()
|
row = row.duplicate()
|
||||||
var half: int = int(ceil(float(int(row.power)) * float(100 - halve_pct) / 100.0))
|
var half: int = int(ceil(float(int(row.power)) * float(100 - halve_pct) / 100.0))
|
||||||
emit_cb.call({"type": "effect", "source_class": source_class, "origin_cell": cell}, ri, "惊巢反制——危险格挖掘惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_counter"})
|
emit_cb.call({"type": "effect", "source_class": source_class, "origin_cell": cell}, ri, "挖掘惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_halve"})
|
||||||
row.power = half
|
row.power = half
|
||||||
return _dispatch_row(row, att)
|
return _dispatch_row(row, att)
|
||||||
|
|
||||||
@@ -268,7 +254,7 @@ func _apply_percent_row(row: Dictionary, att: Dictionary) -> bool:
|
|||||||
return true
|
return true
|
||||||
emit_cb.call({"type": "reward_ineffective", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
emit_cb.call({"type": "reward_ineffective", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
||||||
int(att.get("ri", 0)), "奖励未生效(满层)%s" % String(att.get("label_suffix", "")), 0,
|
int(att.get("ri", 0)), "奖励未生效(满层)%s" % String(att.get("label_suffix", "")), 0,
|
||||||
{"batch_key": eff})
|
{"batch_key": eff, "reason": "full_layers"})
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
||||||
@@ -361,12 +347,12 @@ func _flat_heal(row: Dictionary, display: String, att: Dictionary, sync: bool) -
|
|||||||
# 主角已倒下(同轮更早的负向直伤致死)——治疗不再合法作用,按"奖励未生效"留痕
|
# 主角已倒下(同轮更早的负向直伤致死)——治疗不再合法作用,按"奖励未生效"留痕
|
||||||
emit_cb.call({"type": "reward_ineffective", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
emit_cb.call({"type": "reward_ineffective", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
||||||
int(att.get("ri", 0)), "%s 未生效(主角已倒下)" % display, 0,
|
int(att.get("ri", 0)), "%s 未生效(主角已倒下)" % display, 0,
|
||||||
{"batch_key": String(row.reward_id)})
|
{"batch_key": String(row.reward_id), "reason": "hero_down"})
|
||||||
return "zero"
|
return "zero"
|
||||||
if int(units.hero_unit().hp) >= int(units.hero_unit().max_hp):
|
if int(units.hero_unit().hp) >= int(units.hero_unit().max_hp):
|
||||||
emit_cb.call({"type": "reward_ineffective", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
emit_cb.call({"type": "reward_ineffective", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
||||||
int(att.get("ri", 0)), "%s 未生效(满血)" % display, 0,
|
int(att.get("ri", 0)), "%s 未生效(满血)" % display, 0,
|
||||||
{"batch_key": String(row.reward_id)})
|
{"batch_key": String(row.reward_id), "reason": "full_hp"})
|
||||||
return "zero"
|
return "zero"
|
||||||
var healed: int = units.heal(units.hero_unit(), power) # clamp 归 战斗结算
|
var healed: int = units.heal(units.hero_unit(), power) # clamp 归 战斗结算
|
||||||
emit_cb.call({"type": "heal", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
emit_cb.call({"type": "heal", "source_class": String(att.get("source_class", "")), "origin_cell": att.get("cell", Vector2i(-1, -1)), "highlight": String(att.get("highlight", ""))},
|
||||||
@@ -414,12 +400,15 @@ func grant_clear_reward(ri: int, skip_on_refresh: bool, perfect: bool) -> void:
|
|||||||
if not (snap is Dictionary):
|
if not (snap is Dictionary):
|
||||||
return
|
return
|
||||||
var first_ok := _grant_clear_identity(snap, ri, "(清图奖励)")
|
var first_ok := _grant_clear_identity(snap, ri, "(清图奖励)")
|
||||||
|
# 完美封印追加兑付倍率读表(数值单一事实源——p_perfect 经 ConfigDB settlement_core 行,
|
||||||
|
# 载体域 {100,200}:200=×2 追加第二份、100=×1 单份不发。追加份数结构上限 1 份不变)
|
||||||
|
var perfect_mult := int(db.combat.settlement.core.p_perfect) / 100
|
||||||
var second_ok := false
|
var second_ok := false
|
||||||
if perfect and first_ok:
|
if perfect and first_ok and perfect_mult >= 2:
|
||||||
second_ok = _grant_clear_identity(snap, ri, "(完美第二份)")
|
second_ok = _grant_clear_identity(snap, ri, "(完美第二份)")
|
||||||
if perfect and first_ok:
|
if perfect and first_ok:
|
||||||
emit_cb.call({"type": "highlight", "source_class": "clear_reward", "origin_cell": Vector2i(-1, -1), "highlight": "perfect_sweep"},
|
emit_cb.call({"type": "highlight", "source_class": "clear_reward", "origin_cell": Vector2i(-1, -1), "highlight": "perfect_sweep"},
|
||||||
ri, "完美封印!清图奖励 ×2", (2 if second_ok else 1), {})
|
ri, "完美封印!清图奖励 ×%d" % perfect_mult, (1 + (1 if second_ok else 0)), {})
|
||||||
|
|
||||||
|
|
||||||
# 清图奖励 = 整图独立对象(不属于任何一格):兑付形态按其 cell_type 的正向字典形态走,
|
# 清图奖励 = 整图独立对象(不属于任何一格):兑付形态按其 cell_type 的正向字典形态走,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
## 掷格件:装配期格面资源摇号——池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影)。
|
## 掷格件:装配期格面资源摇号——池行装配、区间行 roll、权重合成(订阅加权/board_skew 两路投影)。
|
||||||
## 自 RewardEconomy 迁出掷格面(architecture v1.29 轴戊②);受理账面(grant/身份查询/快照/retire/
|
## 自 RewardEconomy 迁出掷格面(architecture v1.29 轴戊②);受理账面(grant/身份查询/快照/retire/
|
||||||
## polarity_row)留守 RewardEconomy——衔接面=格→奖励身份映射批束(本件产出、受理件接收)。
|
## polarity_row)留守 RewardEconomy——衔接面=格→奖励身份映射批束(本件产出、受理件接收)。
|
||||||
## 取号流声明:roll 每批恰开一 reward_roll 流(scope=每次 install 批不变),体序=normalize(行主序
|
## 取号流声明:roll 每批恰开一 reward_roll 流(scope=每次 install 批不变),体序=normalize(行主序
|
||||||
@@ -38,12 +38,12 @@ func _init(bundle: Dictionary) -> void:
|
|||||||
func roll(eligible: Array) -> Dictionary[Variant, Variant]:
|
func roll(eligible: Array) -> Dictionary[Variant, Variant]:
|
||||||
var list: Array[Dictionary] = _normalize_eligible(eligible)
|
var list: Array[Dictionary] = _normalize_eligible(eligible)
|
||||||
var stream: RandomNumberGenerator = rng.open_stream("reward_roll") # 恰一 scope 批(格批 + 清图批尾 + 区间行追加取号)
|
var stream: RandomNumberGenerator = rng.open_stream("reward_roll") # 恰一 scope 批(格批 + 清图批尾 + 区间行追加取号)
|
||||||
# reward_roll 发射归 BattleFxHost(偏运硬币 bias_rewards 订阅命中合计经注入查询口取回);
|
# reward_roll 发射归 BattleFxHost(bias_rewards 订阅命中合计经注入查询口取回);
|
||||||
# 零命中/未接线=0=原行集零扰动
|
# 零命中/未接线=0=原行集零扰动
|
||||||
var luck_bias := 0
|
var luck_bias := 0
|
||||||
if luck_bias_query.is_valid():
|
if luck_bias_query.is_valid():
|
||||||
luck_bias = luck_bias_query.call(list.size())
|
luck_bias = luck_bias_query.call(list.size())
|
||||||
var cell_rows: Array[Variant] = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(偏运硬币装配时稀有正向 kinds 权重 +N——池结构零触碰)
|
var cell_rows: Array[Variant] = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(订阅件装配时稀有正向 kinds 权重 +N——池结构零触碰)
|
||||||
var clear_rows: Array[Variant] = _pool_rows("clear_default")
|
var clear_rows: Array[Variant] = _pool_rows("clear_default")
|
||||||
# ① 身份批:每非封锁格恰一类型身份(雷安同池——同一行集同一权重分布)
|
# ① 身份批:每非封锁格恰一类型身份(雷安同池——同一行集同一权重分布)
|
||||||
var draft := {}
|
var draft := {}
|
||||||
@@ -83,7 +83,7 @@ func _normalize_eligible(eligible: Array) -> Array[Dictionary]:
|
|||||||
return list
|
return list
|
||||||
|
|
||||||
|
|
||||||
# 偏运硬币权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动)
|
# 订阅加权权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动)
|
||||||
# 合成序:先经图级偏斜投影再叠件级加法——合成序锚=图级先、件级后
|
# 合成序:先经图级偏斜投影再叠件级加法——合成序锚=图级先、件级后
|
||||||
#(环境事实先定型、玩家构筑叠其上;两投影均为池内权重面,雷安同池与取号次数零变化)
|
#(环境事实先定型、玩家构筑叠其上;两投影均为池内权重面,雷安同池与取号次数零变化)
|
||||||
func _biased_cell_rows(bias: int) -> Array:
|
func _biased_cell_rows(bias: int) -> Array:
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ func _board_deferred_settle(ri: int) -> void:
|
|||||||
if int(units.hero_unit().get("hp", 0)) <= 0:
|
if int(units.hero_unit().get("hp", 0)) <= 0:
|
||||||
for t in (reward_grant.defer["queue"] as Array):
|
for t in (reward_grant.defer["queue"] as Array):
|
||||||
emit_row_cb.call({"type": "reward_ineffective", "source_class": String(t.get("source_class", "")), "origin_cell": t.get("origin_cell", Vector2i(-1, -1))}, ri,
|
emit_row_cb.call({"type": "reward_ineffective", "source_class": String(t.get("source_class", "")), "origin_cell": t.get("origin_cell", Vector2i(-1, -1))}, ri,
|
||||||
"%s 未生效(主角已倒下)" % String(t.get("display", "")), 0, {"forfeit": "hero_down"})
|
"%s 未生效(主角已倒下)" % String(t.get("display", "")), 0, {"forfeit": "hero_down", "reason": "hero_down"})
|
||||||
else:
|
else:
|
||||||
for t in (reward_grant.defer["queue"] as Array):
|
for t in (reward_grant.defer["queue"] as Array):
|
||||||
damage.submit(t)
|
damage.submit(t)
|
||||||
|
|||||||
@@ -93,15 +93,12 @@ func _reveal_batch(ri: int) -> void:
|
|||||||
_reveal_mine(evt, snap, ri)
|
_reveal_mine(evt, snap, ri)
|
||||||
|
|
||||||
|
|
||||||
# safe 事件兑付(封印不可逆四情况④:插安全格再挖开 = 零惩罚零奖励——正向兑付作废〔归因行在案〕;
|
# safe 事件兑付(封印受理即揭示改版:挖封印格已被规则合法性表拒绝——改判路径整体退役,
|
||||||
# 标空判定已随封印擦除自然缺席——被挖的封印不在轮末在场基线。dig_reveal 发射+施加序:
|
# 本函数只受理真实揭示的 safe 事件。dig_reveal 发射+施加序:
|
||||||
# 乘区收集 → 正向兑付 → 施加面〔计数器/揭示入队/追加产出/奥术矢〕。
|
# 乘区收集 → 正向兑付 → 施加面〔计数器/揭示入队/追加产出/奥术矢〕。
|
||||||
# payload 携 is_edge_cell〔边陲矿工〕/is_blank_zero〔跳格采掘〕/
|
# payload 携 is_edge_cell〔边陲矿工〕/is_blank_zero〔跳格采掘〕/
|
||||||
# new_resource_type〔地质学家——快照 cell_type 首见判定,见后集登记〕)
|
# new_resource_type〔地质学家——快照 cell_type 首见判定,见后集登记〕)
|
||||||
func _reveal_safe(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
func _reveal_safe(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
||||||
if bool(evt.get("dug_under_seal", false)):
|
|
||||||
emit_row_cb.call({"type": "reward_ineffective", "source_class": "safe_cell", "origin_cell": evt.cell}, ri, "奖励作废(封印格直接挖开——零惩罚零奖励)", 0, {})
|
|
||||||
return
|
|
||||||
var board_b: BoardData = minesweeper.current_board()
|
var board_b: BoardData = minesweeper.current_board()
|
||||||
var ctype := String(snap.get("cell_type", ""))
|
var ctype := String(snap.get("cell_type", ""))
|
||||||
var is_new_type := fx_host.mark_new_resource_type(ctype)
|
var is_new_type := fx_host.mark_new_resource_type(ctype)
|
||||||
@@ -124,8 +121,8 @@ func _reveal_safe(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# dig_reveal 施加面(序=计数器〔连击计数——乘区收集后执行=本格兑付用旧值〕→ 揭示入队〔地质学家/
|
# dig_reveal 施加面(序=计数器〔连击计数——乘区收集后执行=本格兑付用旧值〕→ 揭示入队〔地质学家/
|
||||||
# 跳格采掘 reveal_tiles 订阅面,授予段末统一掷格兑付〕→ 追加产出〔深挖钻头 v2 双份制:grant_material
|
# 跳格采掘 reveal_tiles 订阅面,授予段末统一掷格兑付〕→ 追加产出〔双份制:grant_material
|
||||||
# 命中=配额内追加第二份〕→ 奥术矢〔魔能共鸣——每战首次开安全格追加魔法矢;任意真族单次生效〕)
|
# 命中=配额内追加第二份〕→ 奥术矢(每战首次开安全格追加魔法矢;任意真族单次生效))
|
||||||
func _reveal_safe_apply(dr_hits: Array, evt: Dictionary, ri: int) -> void:
|
func _reveal_safe_apply(dr_hits: Array, evt: Dictionary, ri: int) -> void:
|
||||||
for h in dr_hits:
|
for h in dr_hits:
|
||||||
if String(h.get("kind", "")) == "counter_add":
|
if String(h.get("kind", "")) == "counter_add":
|
||||||
@@ -145,12 +142,12 @@ func _reveal_safe_apply(dr_hits: Array, evt: Dictionary, ri: int) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# mine 事件兑付(封印不可逆四情况②:插危险格再挖开 = 只受挖雷一层惩罚——mine_hit 照常兑付惊动巢穴,
|
# mine 事件兑付(封印不可逆四情况②:插危险格再挖开 = 只受挖雷一层惩罚——mine_hit 照常兑付惊动巢穴,
|
||||||
# 标中不发〔封印已随挖掘擦除、不入轮末判定基线〕。mine_hit 发射+施加序:施加面收集 → 减伤落快照 →
|
# mine_hit 发射+施加序:施加面收集 → 减伤落快照 →
|
||||||
# 计数器 → 揭示入队 → 负向兑付〔带减半系数〕→ 反打开单)
|
# 计数器 → 揭示入队 → 负向兑付〔带减半系数〕→ 反打开单)
|
||||||
func _reveal_mine(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
func _reveal_mine(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
||||||
var mine_power := int(snap.get("power", 0))
|
var mine_power := int(snap.get("power", 0))
|
||||||
var mh_hits := fx_host.fx_emit("mine_hit", {"cell": evt.cell, "round": ri,
|
var mh_hits := fx_host.fx_emit("mine_hit", {"cell": evt.cell, "round": ri,
|
||||||
"damage": mine_power, "dug_under_seal": bool(evt.get("dug_under_seal", false)),
|
"damage": mine_power,
|
||||||
"hp_ratio": int(round(100.0 * float(int(units.hero_unit().get("hp", 0))) / float(maxi(1, int(units.hero_unit().get("max_hp", 1))))))})
|
"hp_ratio": int(round(100.0 * float(int(units.hero_unit().get("hp", 0))) / float(maxi(1, int(units.hero_unit().get("max_hp", 1))))))})
|
||||||
var applied := _reveal_mine_apply(mh_hits, snap, evt.cell, ri)
|
var applied := _reveal_mine_apply(mh_hits, snap, evt.cell, ri)
|
||||||
if int(applied["mine_reduce"]) > 0:
|
if int(applied["mine_reduce"]) > 0:
|
||||||
@@ -163,7 +160,7 @@ func _reveal_mine(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
|||||||
reward_grant.grant_routed(reward_grant.feat_yield_adjust(snap, false, 0, 0), "negative", {"source_class": "mine_hit", "cell": evt.cell, "ri": ri, "halve_pct": int(applied["halve_pct"])})
|
reward_grant.grant_routed(reward_grant.feat_yield_adjust(snap, false, 0, 0), "negative", {"source_class": "mine_hit", "cell": evt.cell, "ri": ri, "halve_pct": int(applied["halve_pct"])})
|
||||||
for h in mh_hits:
|
for h in mh_hits:
|
||||||
if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "reflect":
|
if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "reflect":
|
||||||
var nct := damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_counter", "惊巢反制·反弹",
|
var nct := damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_halve", "反弹伤害",
|
||||||
{"channel": "board", "base_value": int(h.get("value", 0)), "target_rule": DamageController.TARGET_ALL_ALIVE,
|
{"channel": "board", "base_value": int(h.get("value", 0)), "target_rule": DamageController.TARGET_ALL_ALIVE,
|
||||||
"ri": ri, "origin_cell": evt.cell})
|
"ri": ri, "origin_cell": evt.cell})
|
||||||
reward_grant.submit(nct, false)
|
reward_grant.submit(nct, false)
|
||||||
@@ -201,8 +198,8 @@ func _reveal_mine_apply(mh_hits: Array, snap: Dictionary, cell: Vector2i, ri: in
|
|||||||
|
|
||||||
# 地形变异 兑付批(授予段尾——触发枚举 on_open:挖开即伤、chain 通道同口径;伤害单据案C 暂存到
|
# 地形变异 兑付批(授予段尾——触发枚举 on_open:挖开即伤、chain 通道同口径;伤害单据案C 暂存到
|
||||||
# 战斗段末兑付〔案C〕;信息型 hide_number 不进结算——呈现层读取,见 board_view 数字遮蔽;
|
# 战斗段末兑付〔案C〕;信息型 hide_number 不进结算——呈现层读取,见 board_view 数字遮蔽;
|
||||||
# 危险格恒无变异——布置段排除,双层叠罚不存在;封印格直挖照吃变异伤害——地形后果同 mine_hit 口径,
|
# 危险格恒无变异——布置段排除,双层叠罚不存在;封印格不可挖(封印受理即揭示——变异伤害只随
|
||||||
# 非奖励不作废;吞噬流资源兑付〔荆棘编织/地脉补偿〕中伤害形态行同样经案C闸暂存,非伤害形态照常当场)
|
# 真实揭示兑付);吞噬流资源兑付〔荆棘编织/地脉补偿〕中伤害形态行同样经案C闸暂存,非伤害形态照常当场)
|
||||||
func _terrain_batch(ri: int) -> void:
|
func _terrain_batch(ri: int) -> void:
|
||||||
for evt in facts.reveals:
|
for evt in facts.reveals:
|
||||||
var vids: Array[Variant] = evt.get("variant_ids", [])
|
var vids: Array[Variant] = evt.get("variant_ids", [])
|
||||||
@@ -229,7 +226,7 @@ func _terrain_batch(ri: int) -> void:
|
|||||||
|
|
||||||
# 封印判定批+战封印军规开单段(封印流:seal_judged 批后统一开单:轮末每面封印命中对最前存活敌
|
# 封印判定批+战封印军规开单段(封印流:seal_judged 批后统一开单:轮末每面封印命中对最前存活敌
|
||||||
# 结算 board_typed 必中伤害〔复用零新配方;「封印所在巢穴敌」简化为 default_target 最前存活敌——
|
# 结算 board_typed 必中伤害〔复用零新配方;「封印所在巢穴敌」简化为 default_target 最前存活敌——
|
||||||
# 台账披露待追认〕;完美布防=本轮封印批全中(hit>0 且 miss==0)时封印伤 ×mult——全对推理奖励)。
|
# 台账披露待追认〕;封印全中倍率=本轮 hit>0 且 miss==0 时封印伤 ×mult——全对推理奖励)。
|
||||||
# 伤害单据案C 暂存战斗段末兑付。
|
# 伤害单据案C 暂存战斗段末兑付。
|
||||||
func _seal_batch(ri: int) -> void:
|
func _seal_batch(ri: int) -> void:
|
||||||
for evt in facts.seals:
|
for evt in facts.seals:
|
||||||
@@ -237,7 +234,7 @@ func _seal_batch(ri: int) -> void:
|
|||||||
_seal_strike_batch(ri)
|
_seal_strike_batch(ri)
|
||||||
|
|
||||||
|
|
||||||
# seal_settle 发射+施加(战封印 open_ticket + 完美布防 modify_ticket 改写窗口:封印伤基值×完美倍率后
|
# seal_settle 发射+施加(战封印 open_ticket + 封印全中倍率 modify_ticket 改写窗口:封印伤基值×完美倍率后
|
||||||
# 逐封印开单)
|
# 逐封印开单)
|
||||||
func _seal_strike_batch(ri: int) -> void:
|
func _seal_strike_batch(ri: int) -> void:
|
||||||
var fs_hits := 0
|
var fs_hits := 0
|
||||||
@@ -262,7 +259,7 @@ func _seal_strike_batch(ri: int) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# 战封印军规基值决议(attack 通道 open_ticket 首命中取基值;seal_mult modify_ticket 连乘;
|
# 战封印军规基值决议(attack 通道 open_ticket 首命中取基值;seal_mult modify_ticket 连乘;
|
||||||
# 完美布防=miss==0 且 hit>0 时基值×倍率。空旗集=空字典〔不开单合法态〕)
|
# 封印全中倍率=miss==0 且 hit>0 时基值×倍率。空旗集=空字典〔不开单合法态〕)
|
||||||
func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionary:
|
func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionary:
|
||||||
var banner_hits: Array[Variant] = []
|
var banner_hits: Array[Variant] = []
|
||||||
for h in fs_fx:
|
for h in fs_fx:
|
||||||
@@ -276,11 +273,11 @@ func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionar
|
|||||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "seal_mult":
|
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "seal_mult":
|
||||||
seal_mult *= maxi(1, int(h.get("value", 1)))
|
seal_mult *= maxi(1, int(h.get("value", 1)))
|
||||||
if fs_misses == 0 and fs_hits > 0 and seal_mult > 1:
|
if fs_misses == 0 and fs_hits > 0 and seal_mult > 1:
|
||||||
strike_value *= seal_mult # 完美布防:同轮全中封印伤倍增(全对推理奖励)
|
strike_value *= seal_mult # 封印全中:同轮全中封印伤倍增(全对推理奖励)
|
||||||
return {"value": strike_value}
|
return {"value": strike_value}
|
||||||
|
|
||||||
|
|
||||||
# round_end 发射+施加(每轮结算收口:熔火之躯反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add
|
# round_end 发射+施加(每轮结算收口:轮末反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add
|
||||||
# set〕;停手侧 AP 已在 request_stop 记账,finish_round_stop 按转存率转存 RAP)+施加面:grant_gp〔爆破会计/收盘——escrow 战斗域
|
# set〕;停手侧 AP 已在 request_stop 记账,finish_round_stop 按转存率转存 RAP)+施加面:grant_gp〔爆破会计/收盘——escrow 战斗域
|
||||||
# 缓冲,随 gp_dropped 上抛〕/grant_ap mode:queue〔封印回响——返 1 AP 下轮,queue_ap_delta 通道与轮始
|
# 缓冲,随 gp_dropped 上抛〕/grant_ap mode:queue〔封印回响——返 1 AP 下轮,queue_ap_delta 通道与轮始
|
||||||
# 加成同面〕+段界收口(转存率入参、清图奖励、揭示兑付、段界结账)
|
# 加成同面〕+段界收口(转存率入参、清图奖励、揭示兑付、段界结账)
|
||||||
@@ -318,7 +315,7 @@ func _round_end_heal_value_counter(re_fx: Array, ri: int) -> void:
|
|||||||
continue
|
continue
|
||||||
var hu: Dictionary[Variant, Variant] = units.hero_unit()
|
var hu: Dictionary[Variant, Variant] = units.hero_unit()
|
||||||
if int(hu.get("hp", 0)) >= int(hu.get("max_hp", 1)):
|
if int(hu.get("hp", 0)) >= int(hu.get("max_hp", 1)):
|
||||||
emit_row_cb.call({"type": "reward_ineffective", "source_class": "fx_board_refresh", "origin_cell": Vector2i(-1, -1)}, ri, "坑道小憩 未生效(满血)", 0, {"batch_key": String(h.get("value_counter", ""))})
|
emit_row_cb.call({"type": "reward_ineffective", "source_class": "fx_board_refresh", "origin_cell": Vector2i(-1, -1)}, ri, "坑道小憩 未生效(满血)", 0, {"batch_key": String(h.get("value_counter", "")), "reason": "full_hp"})
|
||||||
continue
|
continue
|
||||||
var healed: int = units.heal(hu, layers)
|
var healed: int = units.heal(hu, layers)
|
||||||
emit_row_cb.call({"type": "heal", "source_class": "fx_board_refresh", "origin_cell": Vector2i(-1, -1)}, ri, "坑道小憩 回复", healed, {"target": "hero"})
|
emit_row_cb.call({"type": "heal", "source_class": "fx_board_refresh", "origin_cell": Vector2i(-1, -1)}, ri, "坑道小憩 回复", healed, {"target": "hero"})
|
||||||
@@ -348,7 +345,7 @@ func _judge_seal(evt: Dictionary, ri: int) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# 封印命中(资格以危险格实例为键去重——排雷玩法 诚实重复上报的对侧;seal_hit 发射序:
|
# 封印命中(资格以危险格实例为键去重——排雷玩法 诚实重复上报的对侧;seal_hit 发射序:
|
||||||
# 殉爆票据 → 施加面 → 雷区图谱额外兑付 → 基线正向兑付)
|
# 标中雷反打票据 → 施加面 → 标中雷额外兑付 → 基线正向兑付)
|
||||||
func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
||||||
var cell: Vector2i = evt.cell
|
var cell: Vector2i = evt.cell
|
||||||
if facts.seal_consumed.has(cell):
|
if facts.seal_consumed.has(cell):
|
||||||
@@ -359,7 +356,7 @@ func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
|||||||
"terrain_kind": minesweeper.harmful_adjacent(cell)})
|
"terrain_kind": minesweeper.harmful_adjacent(cell)})
|
||||||
_seal_burst_tickets(fh_hits, cell, ri)
|
_seal_burst_tickets(fh_hits, cell, ri)
|
||||||
_seal_hit_effects(fh_hits, cell, ri)
|
_seal_hit_effects(fh_hits, cell, ri)
|
||||||
# 雷区图谱(封印流——标中雷额外获得一份格面资源:封印开始产出对标开格;
|
# 标中雷追加(封印流——标中雷额外获得一份格面资源:封印开始产出对标开格;
|
||||||
# 复用 grant 单点,额外兑付走同一 grant_routed 正向路由)
|
# 复用 grant 单点,额外兑付走同一 grant_routed 正向路由)
|
||||||
for h in fh_hits:
|
for h in fh_hits:
|
||||||
if String(h.get("kind", "")) == "grant_material":
|
if String(h.get("kind", "")) == "grant_material":
|
||||||
@@ -370,7 +367,7 @@ func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
|||||||
reward_grant.grant_routed(snap, "positive", {"source_class": "seal_hit", "cell": cell, "ri": ri, "highlight": "seal_hit"})
|
reward_grant.grant_routed(snap, "positive", {"source_class": "seal_hit", "cell": cell, "ri": ri, "highlight": "seal_hit"})
|
||||||
|
|
||||||
|
|
||||||
# 标中殉爆票据(行 triggers open_ticket channel blast value_from magnitude——每标中一面封印全体存活敌
|
# 标中雷反打票据(行 triggers open_ticket channel blast value_from magnitude——每标中一面封印全体存活敌
|
||||||
# 吃 N 群伤,无类型走 blast 通道;封印爆裂〔专长〕同面消费)
|
# 吃 N 群伤,无类型走 blast 通道;封印爆裂〔专长〕同面消费)
|
||||||
func _seal_burst_tickets(fh_hits: Array, cell: Vector2i, ri: int) -> void:
|
func _seal_burst_tickets(fh_hits: Array, cell: Vector2i, ri: int) -> void:
|
||||||
for h in DamageController.hits_of(fh_hits, "open_ticket"):
|
for h in DamageController.hits_of(fh_hits, "open_ticket"):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ extends Resource
|
|||||||
@export var canvas := Vector2(1280, 800) # 终稿画布(工程档同幅面)
|
@export var canvas := Vector2(1280, 800) # 终稿画布(工程档同幅面)
|
||||||
@export var hud_band_h := 48 # 顶栏禁区高度(命中不侵)
|
@export var hud_band_h := 48 # 顶栏禁区高度(命中不侵)
|
||||||
@export var gate_gap := Vector2i(520, 760) # 门洞缺口 x 范围(透出背景层小路,禁填死)
|
@export var gate_gap := Vector2i(520, 760) # 门洞缺口 x 范围(透出背景层小路,禁填死)
|
||||||
@export var wall_band := Rect2(0, 240, 1280, 70) # 围墙带包络(门柱顶 240—桩底 310;围墙贴图须落在其内)
|
@export var wall_band := Rect2(0, 220, 1280, 200) # 围墙带包络(显示矩形 (0,220,1280,200);围墙贴图须落在其内)
|
||||||
@export var layers: Array[CampSceneLayerSpec] = []
|
@export var layers: Array[CampSceneLayerSpec] = []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ extends Resource
|
|||||||
|
|
||||||
@export var rows: Array[Dictionary] = [] # Array[Dictionary]
|
@export var rows: Array[Dictionary] = [] # Array[Dictionary]
|
||||||
|
|
||||||
# 行类封闭枚举(对齐关卡节点 type 词表):battle = 战斗节点配池,boss = 终点行集
|
# 行类封闭枚举:表内允许出现的行类(battle/boss 对齐关卡节点 type 词表,elite=精英行)
|
||||||
const ROW_KINDS := ["battle", "boss"]
|
const ROW_KINDS := ["battle", "boss", "elite"]
|
||||||
|
# 开战寻址可读的行类——elite 接线前不在此列(敌人系统 v1.9 暂不接线;resolver 行类门单点消费)
|
||||||
|
const ENCOUNTER_ROW_KINDS := ["battle", "boss"]
|
||||||
|
|
||||||
# 护甲类型封闭枚举(克制矩阵本体在 SettlementTable;
|
# 护甲类型封闭枚举(克制矩阵本体在 SettlementTable;
|
||||||
# 语义键 {light, ward, heavy} = 轻甲 / 魔法护甲 / 重甲)
|
# 语义键 {light, ward, heavy} = 轻甲 / 魔法护甲 / 重甲)
|
||||||
@@ -49,6 +51,7 @@ func validate() -> Array:
|
|||||||
errs.append_array(_validate_row_numbers(row, eid2))
|
errs.append_array(_validate_row_numbers(row, eid2))
|
||||||
errs.append_array(_validate_row_atk_range(row, eid2))
|
errs.append_array(_validate_row_atk_range(row, eid2))
|
||||||
errs.append_array(_validate_row_pool(row, eid2))
|
errs.append_array(_validate_row_pool(row, eid2))
|
||||||
|
errs.append_array(_validate_elite_fields(row, eid2))
|
||||||
errs.append_array(_validate_row_types(row, eid2))
|
errs.append_array(_validate_row_types(row, eid2))
|
||||||
# 行集构成纪律②(行序即契约,敌人系统 v0.15):同带键多行必须
|
# 行集构成纪律②(行序即契约,敌人系统 v0.15):同带键多行必须
|
||||||
# 文件内相邻。迭代中记录上一行行集键;当前行集键曾出现过但 ≠ 上一行行集键 = 同带键行被隔断,报错。
|
# 文件内相邻。迭代中记录上一行行集键;当前行集键曾出现过但 ≠ 上一行行集键 = 同带键行被隔断,报错。
|
||||||
@@ -67,6 +70,7 @@ func validate() -> Array:
|
|||||||
boss_ok[L2] = true
|
boss_ok[L2] = true
|
||||||
if not anchor_ok.has(L2):
|
if not anchor_ok.has(L2):
|
||||||
anchor_ok[L2] = false
|
anchor_ok[L2] = false
|
||||||
|
errs.append_array(_validate_elite_refs())
|
||||||
errs.append_array(_validate_anchor_rows(anchor_ok, boss_ok))
|
errs.append_array(_validate_anchor_rows(anchor_ok, boss_ok))
|
||||||
return errs
|
return errs
|
||||||
|
|
||||||
@@ -85,7 +89,7 @@ func _validate_row_base(row: Dictionary, seen: Dictionary) -> Array[Dictionary]:
|
|||||||
if L < 1 or band < 0:
|
if L < 1 or band < 0:
|
||||||
errs.append({"category": "domain", "message": "进度键越域 (%d,band %d)" % [L, band]})
|
errs.append({"category": "domain", "message": "进度键越域 (%d,band %d)" % [L, band]})
|
||||||
if not ROW_KINDS.has(rk):
|
if not ROW_KINDS.has(rk):
|
||||||
errs.append({"category": "domain", "message": "%s row_kind 未知枚举: \"%s\"(域 {battle, boss})" % [eid, rk]})
|
errs.append({"category": "domain", "message": "%s row_kind 未知枚举: \"%s\"(域 {battle, boss, elite})" % [eid, rk]})
|
||||||
if eid == "":
|
if eid == "":
|
||||||
errs.append({"category": "domain", "message": "enemy_id 空"})
|
errs.append({"category": "domain", "message": "enemy_id 空"})
|
||||||
if String(row.get("display_name", "")) == "":
|
if String(row.get("display_name", "")) == "":
|
||||||
@@ -136,25 +140,99 @@ func _validate_row_atk_range(row: Dictionary, eid: String) -> Array[Dictionary]:
|
|||||||
## 非空池 + 条目 {skill_id 非空, weight > 0} + 池内 skill_id 不重复。
|
## 非空池 + 条目 {skill_id 非空, weight > 0} + 池内 skill_id 不重复。
|
||||||
## 普攻冷却恒 0(SkillTable schema 锁死)→ 可摇集合恒非空,"空池不可能"由此结构保证。
|
## 普攻冷却恒 0(SkillTable schema 锁死)→ 可摇集合恒非空,"空池不可能"由此结构保证。
|
||||||
func _validate_row_pool(row: Dictionary, eid: String) -> Array[Dictionary]:
|
func _validate_row_pool(row: Dictionary, eid: String) -> Array[Dictionary]:
|
||||||
|
var no_errs: Array[Dictionary] = []
|
||||||
|
if String(row.get("row_kind", "")) == "elite":
|
||||||
|
return no_errs # elite 行不带 pool 键(pool_extra 承载附加技——条目域校验随 _validate_elite_fields)
|
||||||
var errs: Array[Dictionary] = []
|
var errs: Array[Dictionary] = []
|
||||||
var pool: Array[Variant] = row.get("pool", [])
|
var pool: Array[Variant] = row.get("pool", [])
|
||||||
if pool.is_empty():
|
if pool.is_empty():
|
||||||
errs.append({"category": "domain", "message": "%s pool 空池(禁——技能池行必带池模板)" % eid})
|
errs.append({"category": "domain", "message": "%s pool 空池(禁——技能池行必带池模板)" % eid})
|
||||||
|
errs.append_array(_validate_pool_entries(pool, eid, "pool"))
|
||||||
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
## 池条目域共用校验(pool 与 pool_extra 共用——权重上限 9999 不出现第二份,契约 3 单点);
|
||||||
|
## field 承载报错定位段("pool"=既有文案逐字不变,"pool_extra"=附加技清单定位)。
|
||||||
|
func _validate_pool_entries(entries: Array, eid: String, field: String) -> Array[Dictionary]:
|
||||||
|
var errs: Array[Dictionary] = []
|
||||||
var pool_ids := {}
|
var pool_ids := {}
|
||||||
for entry_v in pool:
|
for entry_v in entries:
|
||||||
if not (entry_v is Dictionary):
|
if not (entry_v is Dictionary):
|
||||||
errs.append({"category": "domain", "message": "%s pool 条目非字典: %s" % [eid, str(entry_v)]})
|
errs.append({"category": "domain", "message": "%s %s 条目非字典: %s" % [eid, field, str(entry_v)]})
|
||||||
continue
|
continue
|
||||||
var entry: Dictionary[Variant, Variant] = entry_v
|
var entry: Dictionary[Variant, Variant] = entry_v
|
||||||
var sid: String = String(entry.get("skill_id", ""))
|
var sid: String = String(entry.get("skill_id", ""))
|
||||||
if sid == "":
|
if sid == "":
|
||||||
errs.append({"category": "domain", "message": "%s pool 条目 skill_id 空" % eid})
|
errs.append({"category": "domain", "message": "%s %s 条目 skill_id 空" % [eid, field]})
|
||||||
elif pool_ids.has(sid):
|
elif pool_ids.has(sid):
|
||||||
errs.append({"category": "dup_key", "message": "%s pool 内 skill_id 重复: %s" % [eid, sid]})
|
errs.append({"category": "dup_key", "message": "%s %s 内 skill_id 重复: %s" % [eid, field, sid]})
|
||||||
pool_ids[sid] = true
|
pool_ids[sid] = true
|
||||||
var w: int = int(entry.get("weight", 0))
|
var w: int = int(entry.get("weight", 0))
|
||||||
if w <= 0 or w > 9999:
|
if w <= 0 or w > 9999:
|
||||||
errs.append({"category": "domain", "message": "%s pool 权重越域 (0,9999]: %d" % [eid, w]})
|
errs.append({"category": "domain", "message": "%s %s 权重越域 (0,9999]: %d" % [eid, field, w]})
|
||||||
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
## 精英行字段互锁(敌人系统 v1.9 :281/:282/:283):elite 行必备 base_ref/pool_extra、禁 pool、
|
||||||
|
## enemy_id 不与 base_ref 同名;非 elite 行禁带 base_ref/pool_extra。base_ref 引用存在性归 _validate_elite_refs。
|
||||||
|
func _validate_elite_fields(row: Dictionary, eid: String) -> Array[Dictionary]:
|
||||||
|
var errs: Array[Dictionary] = []
|
||||||
|
if String(row.get("row_kind", "")) == "elite":
|
||||||
|
var base_ref := String(row.get("base_ref", ""))
|
||||||
|
if base_ref == "":
|
||||||
|
errs.append({"category": "cross_field", "message": "%s elite 行 base_ref 缺或空(基础敌种引用必带)" % eid})
|
||||||
|
if base_ref == eid:
|
||||||
|
errs.append({"category": "cross_field", "message": "%s elite 行 base_ref 与自身 enemy_id 同名(禁)" % eid})
|
||||||
|
if not row.has("pool_extra") or (row.get("pool_extra") as Array).is_empty():
|
||||||
|
errs.append({"category": "cross_field", "message": "%s elite 行 pool_extra 缺键或空(附加技清单非空必带)" % eid})
|
||||||
|
if row.has("pool"):
|
||||||
|
errs.append({"category": "cross_field", "message": "%s elite 行带 pool 键(禁——池走继承+附加)" % eid})
|
||||||
|
if row.has("pool_extra") and (row.get("pool_extra") as Array).size() > 0:
|
||||||
|
errs.append_array(_validate_pool_entries(row.get("pool_extra"), eid, "pool_extra"))
|
||||||
|
else:
|
||||||
|
if row.has("base_ref"):
|
||||||
|
errs.append({"category": "cross_field", "message": "%s 非 elite 行带 base_ref 键(禁——基础敌种引用为 elite 行专属)" % eid})
|
||||||
|
if row.has("pool_extra"):
|
||||||
|
errs.append({"category": "cross_field", "message": "%s 非 elite 行带 pool_extra 键(禁——附加技清单为 elite 行专属)" % eid})
|
||||||
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
## 精英行跨行引用校验(敌人系统 v1.9 :148/:282):base_ref 指向同关 battle 行类敌种(缺/空已由
|
||||||
|
## _validate_elite_fields 报——此处跳过);指向 elite 行判别同门 _min_band_row;附加技与基础池
|
||||||
|
## skill_id 交集非空报 dup_key(敌人系统.md:149 附加技与基础池重复拒绝)。
|
||||||
|
func _validate_elite_refs() -> Array[Dictionary]:
|
||||||
|
var errs: Array[Dictionary] = []
|
||||||
|
for row in rows:
|
||||||
|
if String(row.get("row_kind", "")) != "elite":
|
||||||
|
continue
|
||||||
|
var base_ref := String(row.get("base_ref", ""))
|
||||||
|
if base_ref == "":
|
||||||
|
continue
|
||||||
|
var level := int(row.get("level_index", 0))
|
||||||
|
var eid := String(row.get("enemy_id", ""))
|
||||||
|
var base := _min_band_row(level, base_ref, "battle")
|
||||||
|
if base.is_empty():
|
||||||
|
if not _min_band_row(level, base_ref, "elite").is_empty():
|
||||||
|
errs.append({"category": "dangling_base", "message": "%s base_ref 指向 elite 行: %s(基础敌种须为 battle 行类)" % [eid, base_ref]})
|
||||||
|
else:
|
||||||
|
errs.append({"category": "dangling_base", "message": "%s base_ref 同关 battle 行类无此敌种: %s" % [eid, base_ref]})
|
||||||
|
continue
|
||||||
|
errs.append_array(_extra_overlap_errs(row, base, eid))
|
||||||
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
## 附加技与基础池重叠判(_validate_elite_refs 交集段提出——分支预算内聚)
|
||||||
|
func _extra_overlap_errs(row: Dictionary, base_row: Dictionary, eid: String) -> Array[Dictionary]:
|
||||||
|
var errs: Array[Dictionary] = []
|
||||||
|
var base_ids := {}
|
||||||
|
for entry_v in base_row.get("pool", []):
|
||||||
|
if entry_v is Dictionary:
|
||||||
|
base_ids[String(entry_v.get("skill_id", ""))] = true
|
||||||
|
for entry_v in row.get("pool_extra", []):
|
||||||
|
if entry_v is Dictionary:
|
||||||
|
var sid := String(entry_v.get("skill_id", ""))
|
||||||
|
if sid != "" and base_ids.has(sid):
|
||||||
|
errs.append({"category": "dup_key", "message": "%s pool_extra 与基础池 skill_id 重复: %s" % [eid, sid]})
|
||||||
return errs
|
return errs
|
||||||
|
|
||||||
|
|
||||||
@@ -193,6 +271,43 @@ func _validate_anchor_rows(anchor_ok: Dictionary, boss_ok: Dictionary) -> Array[
|
|||||||
return errs
|
return errs
|
||||||
|
|
||||||
|
|
||||||
|
# 基础行查找单点(按 (关, 敌种, 行类) 取深度带最小行——精英有效池与「指向 elite 判别」共用,
|
||||||
|
# 禁第二份查找算法):无匹配返回空字典。行字段一律 row.get 读取(夹具行可缺键)。
|
||||||
|
func _min_band_row(level: int, eid: String, kind: String) -> Dictionary:
|
||||||
|
var best := {}
|
||||||
|
var best_band := -1
|
||||||
|
for row in rows:
|
||||||
|
if int(row.get("level_index", -1)) != level or String(row.get("row_kind", "")) != kind \
|
||||||
|
or String(row.get("enemy_id", "")) != eid:
|
||||||
|
continue
|
||||||
|
var band := int(row.get("depth_band", -1))
|
||||||
|
if best.is_empty() or band < best_band:
|
||||||
|
best = row
|
||||||
|
best_band = band
|
||||||
|
return best
|
||||||
|
|
||||||
|
|
||||||
|
## 精英有效池(按需现算、零缓存零写回——敌人系统.md:149 继承不复制):非 elite 行 = 自身 pool
|
||||||
|
## 字典条目副本;elite 行 = 基础行(同关 battle 行类基础敌种深度带最小行)pool 条目 + 本行
|
||||||
|
## pool_extra 条目(均只取 is Dictionary 条目并 duplicate——返回值改写不回灌表内行)。
|
||||||
|
func effective_pool(row: Dictionary) -> Array[Dictionary]:
|
||||||
|
var out: Array[Dictionary] = []
|
||||||
|
if String(row.get("row_kind", "")) != "elite":
|
||||||
|
for entry_v in row.get("pool", []):
|
||||||
|
if entry_v is Dictionary:
|
||||||
|
out.append((entry_v as Dictionary).duplicate())
|
||||||
|
return out
|
||||||
|
var base := _min_band_row(int(row.get("level_index", 0)), String(row.get("base_ref", "")), "battle")
|
||||||
|
if not base.is_empty():
|
||||||
|
for entry_v in base.get("pool", []):
|
||||||
|
if entry_v is Dictionary:
|
||||||
|
out.append((entry_v as Dictionary).duplicate())
|
||||||
|
for entry_v in row.get("pool_extra", []):
|
||||||
|
if entry_v is Dictionary:
|
||||||
|
out.append((entry_v as Dictionary).duplicate())
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
# 深度带切法单点(唯一实现,禁第二份算法):band_keys = 该 (level_index, row_kind) 的
|
# 深度带切法单点(唯一实现,禁第二份算法):band_keys = 该 (level_index, row_kind) 的
|
||||||
# depth_band 键升序数组;返回首个 ≥ D 的键(请求落带取偏难一侧)。
|
# depth_band 键升序数组;返回首个 ≥ D 的键(请求落带取偏难一侧)。
|
||||||
# D 高于全部键 → 返回 -1——resolver 侧 clamp 顶带+warning,跨表校验侧判「顶 clamp 消解」违例;
|
# D 高于全部键 → 返回 -1——resolver 侧 clamp 顶带+warning,跨表校验侧判「顶 clamp 消解」违例;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
## 关卡节点图参数档 schema(节点图生成器核心批 卡① T1):五旋钮+战斗保底+岔口去路数的行式数据表。
|
## 关卡节点图参数档 schema(节点图生成器核心批 卡① T1):五旋钮+战斗保底+岔口去路数的行式数据表。
|
||||||
## 键 = level_index(关卡行集单点),消费面经 ConfigDB.run.level_gen_params.row_by_level_index() 读取;生成器只吃参数档、不认关卡号(契约 6)。
|
## 键 = level_index(关卡行集单点),消费面经 ConfigDB.run.level_gen_params.row_by_level_index() 读取;生成器只吃参数档、不认关卡号(契约 6)。
|
||||||
## 数值全 provisional(定值批落终值);域校验沿关卡节点图生成.md v1.1 调参表已锁条款——层深 L1≥6 递增增幅变大、
|
## 数值全 provisional(定值批落终值);取值域与字段契约单点=本文件域校验(概念与设计意图指针=
|
||||||
|
## 关卡节点图生成.md v1.5 参数契约节)——层深 L1≥6 递增增幅变大、
|
||||||
## 配比四类合计 1、出口 L1 恒 1/L2-L3 1-3、岔口去路数恒 2/3、战斗保底≥0。
|
## 配比四类合计 1、出口 L1 恒 1/L2-L3 1-3、岔口去路数恒 2/3、战斗保底≥0。
|
||||||
class_name LevelGenParams
|
class_name LevelGenParams
|
||||||
extends Resource
|
extends Resource
|
||||||
@@ -66,7 +67,7 @@ func _validate_row_shape(row: Dictionary, L: int, key: String, layers_by_level:
|
|||||||
var bd: float = float(row.get("branch_density", -1.0))
|
var bd: float = float(row.get("branch_density", -1.0))
|
||||||
if bd < 0.0 or bd > 1.0:
|
if bd < 0.0 or bd > 1.0:
|
||||||
errs.append({"category": "domain", "message": "%s 分支密度 %f 越域 [0,1]" % [key, bd]})
|
errs.append({"category": "domain", "message": "%s 分支密度 %f 越域 [0,1]" % [key, bd]})
|
||||||
# 域并单点(关卡节点图生成.md v1.4 调参表——生成器侧域校验退役,唯此一处)
|
# 取值域单点=本文件域校验(概念与设计意图指针=关卡节点图生成.md v1.5 参数契约节)
|
||||||
var ftw: float = float(row.get("fork_third_way_pct", -1.0))
|
var ftw: float = float(row.get("fork_third_way_pct", -1.0))
|
||||||
if ftw < 0.0 or ftw > 100.0:
|
if ftw < 0.0 or ftw > 100.0:
|
||||||
errs.append({"category": "domain", "message": "%s fork_third_way_pct %f 越域 [0,100]" % [key, ftw]})
|
errs.append({"category": "domain", "message": "%s fork_third_way_pct %f 越域 [0,100]" % [key, ftw]})
|
||||||
|
|||||||
@@ -16,15 +16,11 @@ extends Resource
|
|||||||
const UNLOCK_COUNTER_KEYS := ["adventure_cleared", "boss_kill_count", "vision_used"]
|
const UNLOCK_COUNTER_KEYS := ["adventure_cleared", "boss_kill_count", "vision_used"]
|
||||||
|
|
||||||
const DIMENSIONS := ["info", "risk", "action", "plan", "counter"]
|
const DIMENSIONS := ["info", "risk", "action", "plan", "counter"]
|
||||||
# enum 九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。
|
# enum kind 全部条件触发/机制修正类;词面只收现役效果类型。
|
||||||
# cell_removal = 爆破工兵包中立移除格;mine_hit_halve 系固定
|
|
||||||
# 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。
|
|
||||||
# 主动件 kind 词族(reveal_tiles/preview/grant_ap/remove_mines/
|
# 主动件 kind 词族(reveal_tiles/preview/grant_ap/remove_mines/
|
||||||
# refresh_pick——效果引擎 ACTIVE_KINDS 同名闭集);被动件不走 effect_kinds 词族
|
# refresh_pick——效果引擎 ACTIVE_KINDS 同名闭集);被动件不走 effect_kinds 词族
|
||||||
# (passive 行走 triggers 事件订阅形态);旧词保留共存至迁移完成。
|
# (passive 行走 triggers 事件订阅形态)。
|
||||||
const EFFECT_KINDS := ["mine_reveal", "reward_preview", "ap_grant",
|
const EFFECT_KINDS := ["ap_charge_safe",
|
||||||
"mine_hit_halve", "reflect_damage", "ap_rounds_front", "ap_charge_safe", "cell_removal",
|
|
||||||
"reward_weight_bias", "bonus_refresh",
|
|
||||||
"reveal_tiles", "preview", "grant_ap", "remove_mines", "refresh_pick",
|
"reveal_tiles", "preview", "grant_ap", "remove_mines", "refresh_pick",
|
||||||
# 以下八型:
|
# 以下八型:
|
||||||
# 常时参数面六型(无事件订阅——开局/装板参数注入,注入面按装配集 kind 分发读取):
|
# 常时参数面六型(无事件订阅——开局/装板参数注入,注入面按装配集 kind 分发读取):
|
||||||
@@ -45,12 +41,11 @@ const TIER_RANK := {"common": 1, "excellent": 2, "rare": 3, "legendary": 4}
|
|||||||
# 充能重置周期(现役仅 adventure=每冒险;battle=每战重置〔线香〕/level=每关重置〔天眼〕)
|
# 充能重置周期(现役仅 adventure=每冒险;battle=每战重置〔线香〕/level=每关重置〔天眼〕)
|
||||||
const CHARGE_RESETS := ["adventure", "battle", "level"]
|
const CHARGE_RESETS := ["adventure", "battle", "level"]
|
||||||
# magnitude 消费面(≥1 校验):grant_ap 与同调 N 值 kind;其余 kind 活行 magnitude 恒 0
|
# magnitude 消费面(≥1 校验):grant_ap 与同调 N 值 kind;其余 kind 活行 magnitude 恒 0
|
||||||
const MAGNITUDE_KINDS := ["ap_grant", "reflect_damage", "ap_rounds_front",
|
const MAGNITUDE_KINDS := ["ap_charge_safe", "grant_ap",
|
||||||
"ap_charge_safe", "reward_weight_bias", "bonus_refresh", "grant_ap",
|
|
||||||
"light_radius_bonus", "rap_transfer_mult", "dig_range_bonus", "seal_range_free",
|
"light_radius_bonus", "rap_transfer_mult", "dig_range_bonus", "seal_range_free",
|
||||||
"refresh_stock_grant", "shop_refresh_bonus"]
|
"refresh_stock_grant", "shop_refresh_bonus"]
|
||||||
# 真视类 kind(护栏:活行 target 必须 ∈ {area_3x3, cell}:真视窄域 ≤3×3 契约)
|
# 真视类 kind(护栏:活行 target 必须 ∈ {area_3x3, cell}:真视窄域 ≤3×3 契约)
|
||||||
const REVEAL_KINDS := ["mine_reveal", "reveal_tiles"]
|
const REVEAL_KINDS := ["reveal_tiles"]
|
||||||
# 🔴 零裸 flat 结构护栏:行键白名单封闭(键出域=加载致命)——机制轴禁无条件属性加项的表结构承载
|
# 🔴 零裸 flat 结构护栏:行键白名单封闭(键出域=加载致命)——机制轴禁无条件属性加项的表结构承载
|
||||||
const KEY_WHITELIST := ["item_id", "display_name", "dimension_tags", "effect_kinds", "target",
|
const KEY_WHITELIST := ["item_id", "display_name", "dimension_tags", "effect_kinds", "target",
|
||||||
"magnitude", "use_phase", "retired", "deferred", "form", "charges_per_adventure", "slot_cost",
|
"magnitude", "use_phase", "retired", "deferred", "form", "charges_per_adventure", "slot_cost",
|
||||||
@@ -119,7 +114,7 @@ func _validate_row_head(row: Dictionary, iid: String) -> Array[Variant]:
|
|||||||
|
|
||||||
## 订阅形态域:triggers 事件订阅行判据与行级触发词表校验(被动件形态;与 effect_kinds 互斥校验
|
## 订阅形态域:triggers 事件订阅行判据与行级触发词表校验(被动件形态;与 effect_kinds 互斥校验
|
||||||
## 面=passive 行(单形态——效果行为只走订阅);active_charged 行两形合法并存
|
## 面=passive 行(单形态——效果行为只走订阅);active_charged 行两形合法并存
|
||||||
## (effect_kinds=主动分发通道 + triggers=受理闸订阅,掘进蓄能先例))
|
## (effect_kinds=主动分发通道 + triggers=受理闸订阅,积点解锁先例))
|
||||||
func _validate_row_triggers(row: Dictionary, iid: String) -> Array[Variant]:
|
func _validate_row_triggers(row: Dictionary, iid: String) -> Array[Variant]:
|
||||||
var errs: Array[Variant] = []
|
var errs: Array[Variant] = []
|
||||||
if row.has("triggers"):
|
if row.has("triggers"):
|
||||||
@@ -149,13 +144,13 @@ func _validate_row_active(row: Dictionary, iid: String, kind_seen: Dictionary) -
|
|||||||
if kind_seen.has(String(rv)) and not (target == "area_3x3" or target == "cell"):
|
if kind_seen.has(String(rv)) and not (target == "area_3x3" or target == "cell"):
|
||||||
errs.append({"category": "load_bearing", "message": "%s 真视窄域护栏:%s 行 target 必须 area_3x3 或 cell,实得 %s(秘宝 GDD 结构冻结)" % [iid, String(rv), target]})
|
errs.append({"category": "load_bearing", "message": "%s 真视窄域护栏:%s 行 target 必须 area_3x3 或 cell,实得 %s(秘宝 GDD 结构冻结)" % [iid, String(rv), target]})
|
||||||
# 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果
|
# 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果
|
||||||
if target == "board_wide" and kind_seen.has("mine_reveal"):
|
if target == "board_wide" and kind_seen.has("reveal_tiles"):
|
||||||
errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 mine_reveal(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid})
|
errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 reveal_tiles(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid})
|
||||||
errs.append_array(_validate_row_magnitude(row, iid, kind_seen))
|
errs.append_array(_validate_row_magnitude(row, iid, kind_seen))
|
||||||
return errs
|
return errs
|
||||||
|
|
||||||
|
|
||||||
## N 值语义域:magnitude 越域与 MAGNITUDE_KINDS 行消费(≥1);其余活行恒 0(同调批 T1——消费面自 ap_grant 扩至 N 值 kind)
|
## N 值语义域:magnitude 越域与 MAGNITUDE_KINDS 行消费(≥1);其余活行恒 0(同调批 T1——消费面覆盖 N 值 kind)
|
||||||
func _validate_row_magnitude(row: Dictionary, iid: String, kind_seen: Dictionary) -> Array[Variant]:
|
func _validate_row_magnitude(row: Dictionary, iid: String, kind_seen: Dictionary) -> Array[Variant]:
|
||||||
var errs: Array[Variant] = []
|
var errs: Array[Variant] = []
|
||||||
var mag: int = int(row.get("magnitude", 0))
|
var mag: int = int(row.get("magnitude", 0))
|
||||||
@@ -233,10 +228,8 @@ func _validate_row_effect_numbers(row: Dictionary, iid: String, kind_seen: Dicti
|
|||||||
var eff_rounds: int = int(row.get("effective_rounds", 0))
|
var eff_rounds: int = int(row.get("effective_rounds", 0))
|
||||||
if eff_rounds < 0 or eff_rounds > 999:
|
if eff_rounds < 0 or eff_rounds > 999:
|
||||||
errs.append({"category": "domain", "message": "%s effective_rounds 越域 [0,999]: %d" % [iid, eff_rounds]})
|
errs.append({"category": "domain", "message": "%s effective_rounds 越域 [0,999]: %d" % [iid, eff_rounds]})
|
||||||
if kind_seen.has("ap_rounds_front") and eff_rounds < 1:
|
if eff_rounds != 0 and not row.has("triggers"):
|
||||||
errs.append({"category": "cross_field", "message": "%s ap_rounds_front 行 effective_rounds 应 ≥1(P4 甲表值化),实得 %d" % [iid, eff_rounds]})
|
errs.append({"category": "cross_field", "message": "%s 无 triggers 行 effective_rounds 应 0(trigger 行=when value_from 取数源豁免),实得 %d" % [iid, eff_rounds]})
|
||||||
if not kind_seen.has("ap_rounds_front") and eff_rounds != 0 and not row.has("triggers"):
|
|
||||||
errs.append({"category": "cross_field", "message": "%s 非 ap_rounds_front 行 effective_rounds 应 0(trigger 行=when value_from 取数源豁免),实得 %d" % [iid, eff_rounds]})
|
|
||||||
var charge_n: int = int(row.get("charge_n", 0))
|
var charge_n: int = int(row.get("charge_n", 0))
|
||||||
if charge_n < 0 or charge_n > 999:
|
if charge_n < 0 or charge_n > 999:
|
||||||
errs.append({"category": "domain", "message": "%s charge_n 越域 [0,999]: %d" % [iid, charge_n]})
|
errs.append({"category": "domain", "message": "%s charge_n 越域 [0,999]: %d" % [iid, charge_n]})
|
||||||
|
|||||||
@@ -13,64 +13,64 @@ hotspot_key = &""
|
|||||||
[sub_resource type="Resource" id="2"]
|
[sub_resource type="Resource" id="2"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"wall"
|
key = &"wall"
|
||||||
texture_rect = Rect2(0, 261, 1280, 49)
|
texture_rect = Rect2(0, 220, 1280, 200)
|
||||||
hotspot = Rect2(0, 0, 0, 0)
|
hotspot = Rect2(0, 0, 0, 0)
|
||||||
hotspot_key = &""
|
hotspot_key = &""
|
||||||
|
|
||||||
[sub_resource type="Resource" id="3"]
|
[sub_resource type="Resource" id="3"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"board"
|
key = &"board"
|
||||||
texture_rect = Rect2(845, 268, 130, 121)
|
texture_rect = Rect2(845, 241, 130, 121)
|
||||||
hotspot = Rect2(845, 268, 130, 140)
|
hotspot = Rect2(845, 241, 130, 140)
|
||||||
hotspot_key = &"board"
|
hotspot_key = &"board"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="4"]
|
[sub_resource type="Resource" id="4"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"gate"
|
key = &"gate"
|
||||||
texture_rect = Rect2(520, 250, 240, 211)
|
texture_rect = Rect2(520, 282, 240, 138)
|
||||||
hotspot = Rect2(520, 250, 240, 220)
|
hotspot = Rect2(520, 282, 240, 147)
|
||||||
hotspot_key = &"gate"
|
hotspot_key = &"gate"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="5"]
|
[sub_resource type="Resource" id="5"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"dummy"
|
key = &"dummy"
|
||||||
texture_rect = Rect2(340, 520, 120, 180)
|
texture_rect = Rect2(340, 474, 120, 180)
|
||||||
hotspot = Rect2(340, 520, 120, 180)
|
hotspot = Rect2(340, 474, 120, 180)
|
||||||
hotspot_key = &"dummy"
|
hotspot_key = &"dummy"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="6"]
|
[sub_resource type="Resource" id="6"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"forge"
|
key = &"forge"
|
||||||
texture_rect = Rect2(40, 467, 240, 193)
|
texture_rect = Rect2(40, 421, 240, 193)
|
||||||
hotspot = Rect2(40, 420, 240, 240)
|
hotspot = Rect2(40, 374, 240, 240)
|
||||||
hotspot_key = &"forge"
|
hotspot_key = &"forge"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="7"]
|
[sub_resource type="Resource" id="7"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"tent"
|
key = &"tent"
|
||||||
texture_rect = Rect2(982, 520, 251, 170)
|
texture_rect = Rect2(982, 335, 251, 170)
|
||||||
hotspot = Rect2(0, 0, 0, 0)
|
hotspot = Rect2(0, 0, 0, 0)
|
||||||
hotspot_key = &""
|
hotspot_key = &""
|
||||||
|
|
||||||
[sub_resource type="Resource" id="8"]
|
[sub_resource type="Resource" id="8"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"chest"
|
key = &"chest"
|
||||||
texture_rect = Rect2(1097, 700, 106, 90)
|
texture_rect = Rect2(1097, 654, 106, 90)
|
||||||
hotspot = Rect2(1085, 700, 130, 90)
|
hotspot = Rect2(1085, 654, 130, 90)
|
||||||
hotspot_key = &"chest"
|
hotspot_key = &"chest"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="9"]
|
[sub_resource type="Resource" id="9"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"notebook"
|
key = &"notebook"
|
||||||
texture_rect = Rect2(818, 704, 100, 66)
|
texture_rect = Rect2(870, 515, 100, 66)
|
||||||
hotspot = Rect2(818, 690, 100, 80)
|
hotspot = Rect2(870, 501, 100, 80)
|
||||||
hotspot_key = &"notebook"
|
hotspot_key = &"notebook"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="10"]
|
[sub_resource type="Resource" id="10"]
|
||||||
script = ExtResource("2")
|
script = ExtResource("2")
|
||||||
key = &"campfire"
|
key = &"campfire"
|
||||||
texture_rect = Rect2(560, 571, 160, 149)
|
texture_rect = Rect2(560, 525, 160, 149)
|
||||||
hotspot = Rect2(560, 640, 160, 80)
|
hotspot = Rect2(560, 594, 160, 80)
|
||||||
hotspot_key = &"campfire"
|
hotspot_key = &"campfire"
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
@@ -78,5 +78,5 @@ script = ExtResource("1")
|
|||||||
canvas = Vector2(1280, 800)
|
canvas = Vector2(1280, 800)
|
||||||
hud_band_h = 48
|
hud_band_h = 48
|
||||||
gate_gap = Vector2i(520, 760)
|
gate_gap = Vector2i(520, 760)
|
||||||
wall_band = Rect2(0, 240, 1280, 70)
|
wall_band = Rect2(0, 220, 1280, 200)
|
||||||
layers = [SubResource("1"), SubResource("2"), SubResource("3"), SubResource("4"), SubResource("5"), SubResource("6"), SubResource("7"), SubResource("8"), SubResource("9"), SubResource("10")]
|
layers = [SubResource("1"), SubResource("2"), SubResource("3"), SubResource("4"), SubResource("5"), SubResource("6"), SubResource("7"), SubResource("8"), SubResource("9"), SubResource("10")]
|
||||||
@@ -207,6 +207,25 @@ rows = [{
|
|||||||
"armor_type": "light",
|
"armor_type": "light",
|
||||||
"armor_class": 8
|
"armor_class": 8
|
||||||
}, {
|
}, {
|
||||||
|
"level_index": 1,
|
||||||
|
"row_kind": "elite",
|
||||||
|
"depth_band": 0,
|
||||||
|
"enemy_id": "goblin_elite",
|
||||||
|
"display_name": "精英·地精",
|
||||||
|
"unit_count": 1,
|
||||||
|
"hp": 20,
|
||||||
|
"atk": 2,
|
||||||
|
"atk_min": 1,
|
||||||
|
"atk_max": 3,
|
||||||
|
"base_ref": "goblin",
|
||||||
|
"pool_extra": [{
|
||||||
|
"skill_id": "heavy",
|
||||||
|
"weight": 2
|
||||||
|
}],
|
||||||
|
"attack_type": "normal",
|
||||||
|
"armor_type": "light",
|
||||||
|
"armor_class": 2
|
||||||
|
}, {
|
||||||
"level_index": 2,
|
"level_index": 2,
|
||||||
"row_kind": "battle",
|
"row_kind": "battle",
|
||||||
"depth_band": 0,
|
"depth_band": 0,
|
||||||
@@ -943,6 +962,7 @@ rows = [{
|
|||||||
; 不做差异化(pierce/magic 属新设计另立项)。全局平移效应=主角穿重甲受伤 −1 / 魔法护甲 +1 / 轻甲 0,
|
; 不做差异化(pierce/magic 属新设计另立项)。全局平移效应=主角穿重甲受伤 −1 / 魔法护甲 +1 / 轻甲 0,
|
||||||
; 锻造甲路线首次具备战斗意义;克制矩阵数值零触碰(settlement.tres armor_effectiveness 不改)。
|
; 锻造甲路线首次具备战斗意义;克制矩阵数值零触碰(settlement.tres armor_effectiveness 不改)。
|
||||||
;
|
;
|
||||||
; 行键 = (level_index, row_kind, depth_band, enemy_id);row_kind ∈ {battle, boss}——battle=战斗节点配池,boss=终点行集;
|
; 行键 = (level_index, row_kind, depth_band, enemy_id);row_kind ∈ {battle, boss, elite}——battle=战斗节点配池,boss=终点行集,elite=精英行(独立 enemy_id、池走继承+附加,暂不接线任何节点寻址);
|
||||||
; depth_band=节点深度所在的带键,请求落带取首个 ≥ 深度的键(偏难一侧);越顶带由 resolver clamp、跨表校验判为调参事故。
|
; depth_band=节点深度所在的带键,请求落带取首个 ≥ 深度的键(偏难一侧);越顶带由 resolver clamp、跨表校验判为调参事故。
|
||||||
; (1,3) 大地精行 2026-11-04 用户裁退役,改地精+熊地精混编(行序熊地精在前、行值整行复用 (1,2)/(1,0)、静态骰和 3);沿革见 git 提交史
|
; (1,3) 大地精行 2026-11-04 用户裁退役,改地精+熊地精混编(行序熊地精在前、行值整行复用 (1,2)/(1,0)、静态骰和 3);沿革见 git 提交史
|
||||||
|
; 精英专属池批首只精英=地精精英(1,elite,0,goblin_elite),行值 provisional(投值所有权归难度曲线与Boss 统一修正),来源=2026-11-06 用户点头草案 v0
|
||||||
@@ -619,30 +619,6 @@ rows = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"feat_id": "breaker_strike",
|
|
||||||
"display_name": "破封一击",
|
|
||||||
"rarity": "excellent",
|
|
||||||
"cap": 1,
|
|
||||||
"desc": "挖开带封印的危险格:+1 层(疼痛记忆同账)",
|
|
||||||
"triggers": [
|
|
||||||
{
|
|
||||||
"on": "mine_hit",
|
|
||||||
"when": [
|
|
||||||
{
|
|
||||||
"fact": "dug_under_seal",
|
|
||||||
"op": "eq",
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"do": {
|
|
||||||
"kind": "counter_add",
|
|
||||||
"counter_id": "pain_layers",
|
|
||||||
"value": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"feat_id": "map_exchange",
|
"feat_id": "map_exchange",
|
||||||
"display_name": "弃图兑换",
|
"display_name": "弃图兑换",
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ static func outcome_text(outcome: Dictionary) -> String:
|
|||||||
"not_adjacent": "不能执行:目标与小人不相邻",
|
"not_adjacent": "不能执行:目标与小人不相邻",
|
||||||
"target_revealed": "不能执行:目标已开",
|
"target_revealed": "不能执行:目标已开",
|
||||||
"target_concealed": "不能移动:目标未开",
|
"target_concealed": "不能移动:目标未开",
|
||||||
"seal_present": "不能封印:此格已有封印印记(封印为一次性承诺——相邻时左键直接挖开)",
|
"target_sealed": "不能挖:此格已封印(封印受理即揭示——不可再挖开)",
|
||||||
|
"seal_present": "不能封印:此格已有封印印记(封印受理即揭示——印记随图存续)",
|
||||||
"no_path": "不能移动:已探明区不连通",
|
"no_path": "不能移动:已探明区不连通",
|
||||||
"out_of_catalog": "无效目标",
|
"out_of_catalog": "无效目标",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,8 +190,8 @@ func _start_adventure_from_menu() -> void:
|
|||||||
# 主菜单「开始冒险」钮已随三入口化撤出(卡② mn6——主菜单侧断点互斥确认链同步摘除,
|
# 主菜单「开始冒险」钮已随三入口化撤出(卡② mn6——主菜单侧断点互斥确认链同步摘除,
|
||||||
# 弹窗本体与两分支逻辑归卡④大门承接)。本函数为探针直调中间态保留(mn10——冒险段探针
|
# 弹窗本体与两分支逻辑归卡④大门承接)。本函数为探针直调中间态保留(mn10——冒险段探针
|
||||||
# 直调位点逐个登记实现报告「已知中间态」;卡④到位后由大门两分支换代)。无激活态写盘拒绝
|
# 直调位点逐个登记实现报告「已知中间态」;卡④到位后由大门两分支换代)。无激活态写盘拒绝
|
||||||
# 由卡① sv3 承接(结算不落盘)。
|
# 由卡① sv3 承接(结算不落盘)。开始层隐藏已收进 _start_adventure()(营地交互修复批契约 1
|
||||||
ui.screens.start_overlay.visible = false
|
# ——开局路径隐藏点唯一出口)。
|
||||||
_start_adventure()
|
_start_adventure()
|
||||||
|
|
||||||
|
|
||||||
@@ -249,7 +249,6 @@ func _resume_from_menu() -> void:
|
|||||||
run_scope.level_active = true
|
run_scope.level_active = true
|
||||||
sync_status_entry() # 续玩恢复点亮状态面板入口角标
|
sync_status_entry() # 续玩恢复点亮状态面板入口角标
|
||||||
ui.modals.run.level_screen.set_abandon_available(true)
|
ui.modals.run.level_screen.set_abandon_available(true)
|
||||||
ui.battle.log_view.clear()
|
|
||||||
logger.start_session(int(bp.get("master_seed", 0)))
|
logger.start_session(int(bp.get("master_seed", 0)))
|
||||||
run_scope.adventure.set_hero_override(ui.modals.menu.debug_overlay.atk_pct(), ui.modals.menu.debug_overlay.hp_pct())
|
run_scope.adventure.set_hero_override(ui.modals.menu.debug_overlay.atk_pct(), ui.modals.menu.debug_overlay.hp_pct())
|
||||||
# 同调三键随续玩下传(build_adventure_params 统一构造,与开新局同源同口径)
|
# 同调三键随续玩下传(build_adventure_params 统一构造,与开新局同源同口径)
|
||||||
@@ -290,13 +289,13 @@ static func build_adventure_params(save_manager_ref: SaveManagerCore, meta_ref:
|
|||||||
# 冒险模式(三关连探——AdventureRunner 编排;转发信号签名与 runner 一致,接线照原样对接;
|
# 冒险模式(三关连探——AdventureRunner 编排;转发信号签名与 runner 一致,接线照原样对接;
|
||||||
# 信号连接只在组合根)
|
# 信号连接只在组合根)
|
||||||
func _start_adventure() -> void:
|
func _start_adventure() -> void:
|
||||||
|
ui.screens.start_overlay.visible = false # 开局路径开始层隐藏唯一出口(营地交互修复批契约 1——三处调用方经此收口;失败分支开始层终态=隐藏,致命屏接管)
|
||||||
ui.flow.close(ui.modals.menu.debug_overlay) # 开冒险路径显式关浮窗(调试浮窗默认开态下开局不带窗;对局中经角标再开)
|
ui.flow.close(ui.modals.menu.debug_overlay) # 开冒险路径显式关浮窗(调试浮窗默认开态下开局不带窗;对局中经角标再开)
|
||||||
begin_session(true)
|
begin_session(true)
|
||||||
_wire_adventure()
|
_wire_adventure()
|
||||||
run_scope.level_active = true
|
run_scope.level_active = true
|
||||||
sync_status_entry() # 进对局点亮状态面板入口角标
|
sync_status_entry() # 进对局点亮状态面板入口角标
|
||||||
ui.modals.run.level_screen.set_abandon_available(true) # 放弃入口挂选路停点(天然非战斗期)
|
ui.modals.run.level_screen.set_abandon_available(true) # 放弃入口挂选路停点(天然非战斗期)
|
||||||
ui.battle.log_view.clear()
|
|
||||||
var seed_val := seed_value()
|
var seed_val := seed_value()
|
||||||
logger.start_session(seed_val)
|
logger.start_session(seed_val)
|
||||||
run_scope.adventure.set_hero_override(ui.modals.menu.debug_overlay.atk_pct(), ui.modals.menu.debug_overlay.hp_pct())
|
run_scope.adventure.set_hero_override(ui.modals.menu.debug_overlay.atk_pct(), ui.modals.menu.debug_overlay.hp_pct())
|
||||||
@@ -431,13 +430,8 @@ func pace_delay_for(prev_seg: String, next_seg: String) -> float:
|
|||||||
|
|
||||||
|
|
||||||
func _on_round_started(ri: int) -> void:
|
func _on_round_started(ri: int) -> void:
|
||||||
# 轮首分隔行随排播队列走(落在前轮各行之后——带序正确);轮横幅即轮切换时刻发射
|
# 轮横幅即轮切换时刻发射(view 内判减动效=静态化变体);逐行文字列表退役后
|
||||||
#(view 内判减动效=静态化变体)。减动效快路=分隔行同帧直落(不跳过——consume_now 复用
|
# 轮首分隔行不再入队(B 区明细带承载面已撤)。
|
||||||
# _consume_row 轮首分隔行分支)。
|
|
||||||
if UiKit.motion_scale < 1.0:
|
|
||||||
ui.screens.row_pacer.consume_now({"__round_line": ri})
|
|
||||||
else:
|
|
||||||
ui.screens.row_pacer.enqueue({"__round_line": ri})
|
|
||||||
ui.battle.settlement_fx.play_round_banner(ri)
|
ui.battle.settlement_fx.play_round_banner(ri)
|
||||||
# 秘宝呈现同步:每战首轮装配链
|
# 秘宝呈现同步:每战首轮装配链
|
||||||
# 显式重算〔🔴 契约复原语义:下一战装配链重算即含「未装配→写 0」复原〕。
|
# 显式重算〔🔴 契约复原语义:下一战装配链重算即含「未装配→写 0」复原〕。
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ static func _build_screens(root: Variant) -> void:
|
|||||||
static func _build_battle_wiring(root: Variant, handlers: Dictionary) -> void:
|
static func _build_battle_wiring(root: Variant, handlers: Dictionary) -> void:
|
||||||
# 结算行排播泵(本体在 row_pacer.gd;本类注入视图句柄与呈现刷新回调,零信号连接)
|
# 结算行排播泵(本体在 row_pacer.gd;本类注入视图句柄与呈现刷新回调,零信号连接)
|
||||||
root.ui.screens.row_pacer = RowPacer.new()
|
root.ui.screens.row_pacer = RowPacer.new()
|
||||||
root.ui.screens.row_pacer.log_view = root.ui.battle.log_view
|
|
||||||
root.ui.screens.row_pacer.stage = root.ui.battle.stage
|
root.ui.screens.row_pacer.stage = root.ui.battle.stage
|
||||||
root.ui.screens.row_pacer.board_zone = root.ui.battle.board_zone
|
root.ui.screens.row_pacer.board_zone = root.ui.battle.board_zone
|
||||||
root.ui.screens.row_pacer.settlement_fx = root.ui.battle.settlement_fx
|
root.ui.screens.row_pacer.settlement_fx = root.ui.battle.settlement_fx
|
||||||
|
|||||||
@@ -129,15 +129,18 @@ func log_level_end(payload: Dictionary) -> void:
|
|||||||
|
|
||||||
func _on_step_row(row: Dictionary) -> void:
|
func _on_step_row(row: Dictionary) -> void:
|
||||||
_ring(_recent_steps, {"t": row.type, "src": row.source_class, "v": int(row.value), "r": int(row.round_index)})
|
_ring(_recent_steps, {"t": row.type, "src": row.source_class, "v": int(row.value), "r": int(row.round_index)})
|
||||||
# 结算明细行逐行落盘(五段结算完整回放数据面);
|
# 结算明细行逐行落盘(五段结算完整回放数据面);零中文文案——text/display_name 两份
|
||||||
|
# 玩家文案不落盘(日志零文案裁定 2026-11-07),未生效原因走结构化 reason 键;
|
||||||
# 公共七字段之外的全部行字段(payload:roll/ac/tier/crit/normal/pierce/magic/baseline/rider/target/
|
# 公共七字段之外的全部行字段(payload:roll/ac/tier/crit/normal/pierce/magic/baseline/rider/target/
|
||||||
# effect_id/pool_value 等)随行平铺落盘(无 payload 时反事实只能
|
# effect_id/pool_value 等)随行平铺落盘(无 payload 时反事实只能
|
||||||
# 比例近似,带 payload 可精确重算)。
|
# 比例近似,带 payload 可精确重算)。
|
||||||
var line := {"kind": "step", "type": row.type, "source": row.source_class,
|
var line := {"kind": "step", "type": row.type, "source": row.source_class,
|
||||||
"cell": row.origin_cell, "round": int(row.round_index),
|
"cell": row.origin_cell, "round": int(row.round_index),
|
||||||
"text": String(row.display_name), "value": int(row.value),
|
"value": int(row.value),
|
||||||
"highlight": String(row.get("highlight", ""))}
|
"highlight": String(row.get("highlight", ""))}
|
||||||
for k in row.keys():
|
for k in row.keys():
|
||||||
|
if k == "display_name":
|
||||||
|
continue # 日志零文案:display_name 平铺跳过(toast 等呈现面消费,日志不落)
|
||||||
if not line.has(k):
|
if not line.has(k):
|
||||||
line[k] = row[k]
|
line[k] = row[k]
|
||||||
_append(line)
|
_append(line)
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
## VERTICAL SLICE - NOT FOR PRODUCTION
|
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
## 结算行排播泵:逻辑先行零回压,行按段分组阶梯延迟进明细带。
|
## 结算行排播泵:逻辑先行零回压,行按段分组阶梯延迟驱动演出链(伤害飘字/弹道/站桩反馈)。
|
||||||
## 硬契约:只做信号的后置消费——结算顺序/结果/时序逻辑零改动;减动效开=延迟归零同帧直落,行呈现不跳过。
|
## 硬契约:只做信号的后置消费——结算顺序/结果/时序逻辑零改动;减动效开=延迟归零同帧直落,演出不跳过。
|
||||||
## 开模态前必须 flush()——明细回看/停点/终局面所见明细带恒完整。
|
## 开模态前必须 flush()——停点/终局面演出链逐行消费恒完整。
|
||||||
## 视图句柄与 refresh_request/pump_ended 回调由组合根注入——本类零信号连接。
|
## 视图句柄与 refresh_request/pump_ended 回调由组合根注入——本类零信号连接。
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
const PACE_SEGMENT_GAP := 0.3 # 段间阶梯延迟(取值须落白名单 0.2–0.4s 档位带内)
|
const PACE_SEGMENT_GAP := 0.3 # 段间阶梯延迟(取值须落白名单 0.2–0.4s 档位带内)
|
||||||
const PACE_ROW_GAP := 0.22 # 段内间隔(三轮 #3 上调 0.06→0.22——逐条演出可感知,配合数字浮现/状态脉冲)
|
const PACE_ROW_GAP := 0.22 # 段内间隔(三轮 #3 上调 0.06→0.22——逐条演出可感知,配合数字浮现/状态脉冲)
|
||||||
|
|
||||||
var _rows: Array[Variant] = [] # 待排播行(step_row 载荷原样入队;__round_line 标记=轮首分隔行)
|
var _rows: Array[Variant] = [] # 待排播行(step_row 载荷原样入队)
|
||||||
var _pace_wait := 0.0 # 距下一行排播的剩余秒(_process 消耗)
|
var _pace_wait := 0.0 # 距下一行排播的剩余秒(_process 消耗)
|
||||||
var _prev_segment := "" # 上一排播行的段型(段间/段内延迟判据)
|
var _prev_segment := "" # 上一排播行的段型(段间/段内延迟判据)
|
||||||
var _was_pumping := false # 排播活跃边沿(T17——末行消费帧触发结算视觉回挖掘态刷新)
|
var _was_pumping := false # 排播活跃边沿(T17——末行消费帧触发结算视觉回挖掘态刷新)
|
||||||
|
|
||||||
# 组合根注入面(_build_ui 装配——呈现句柄 + 演播完边沿的呈现刷新回调)
|
# 组合根注入面(_build_ui 装配——呈现句柄 + 演播完边沿的呈现刷新回调)
|
||||||
var log_view: BattleLogView
|
|
||||||
var stage: BattleStageView
|
var stage: BattleStageView
|
||||||
var board_zone: BoardZoneView
|
var board_zone: BoardZoneView
|
||||||
var settlement_fx: SettlementFxView
|
var settlement_fx: SettlementFxView
|
||||||
@@ -79,13 +78,8 @@ func _process(delta: float) -> void:
|
|||||||
_prev_segment = seg
|
_prev_segment = seg
|
||||||
|
|
||||||
|
|
||||||
# 行消费(排播队列的出队步 / 减动效快路共用):明细带入带+演出链+呈现刷新
|
# 行消费(排播队列的出队步 / 减动效快路共用):演出链+呈现刷新
|
||||||
func _consume_row(row: Dictionary) -> void:
|
func _consume_row(row: Dictionary) -> void:
|
||||||
if row.has("__round_line"):
|
|
||||||
log_view.finish_settlement_round() # 上轮摘要行(明细带 pattern 3)随轮首分隔行落带
|
|
||||||
log_view.append_bb("[color=#e0b860]── 第 %d 轮 ──[/color]" % int(row["__round_line"]))
|
|
||||||
return
|
|
||||||
log_view.append_row(row)
|
|
||||||
stage.on_step_row_fx(row)
|
stage.on_step_row_fx(row)
|
||||||
_play_cross_zone_fx(row) # 跨区因果演出(结算演出链批):开格之因 → 站桩之果
|
_play_cross_zone_fx(row) # 跨区因果演出(结算演出链批):开格之因 → 站桩之果
|
||||||
_play_settlement_mark(row) # 三轮 #3——逐条标出:Buff/Debuff 色环脉冲 → 伤害/治疗数字浮现
|
_play_settlement_mark(row) # 三轮 #3——逐条标出:Buff/Debuff 色环脉冲 → 伤害/治疗数字浮现
|
||||||
|
|||||||
@@ -189,20 +189,10 @@ func is_refresh_ready() -> bool:
|
|||||||
return not _btn_refresh.disabled
|
return not _btn_refresh.disabled
|
||||||
|
|
||||||
|
|
||||||
# 探针接缝(合成输入走真实翻译出口口径):刷新按钮点击 → 确认 chips 全链路
|
|
||||||
func press_refresh_for_probe() -> void:
|
|
||||||
_on_refresh_pressed()
|
|
||||||
|
|
||||||
|
|
||||||
func confirm_visible() -> bool:
|
func confirm_visible() -> bool:
|
||||||
return _confirm_row.visible
|
return _confirm_row.visible
|
||||||
|
|
||||||
|
|
||||||
func press_confirm_for_probe() -> void:
|
|
||||||
if _arm_timer.is_armed():
|
|
||||||
_disarm_and_fire()
|
|
||||||
|
|
||||||
|
|
||||||
func refresh_remaining_text() -> String:
|
func refresh_remaining_text() -> String:
|
||||||
return _refresh_sub.text
|
return _refresh_sub.text
|
||||||
|
|
||||||
|
|||||||
@@ -191,10 +191,11 @@ func close() -> void:
|
|||||||
st.seal.visible = false
|
st.seal.visible = false
|
||||||
st.seal.modulate = Color.WHITE
|
st.seal.modulate = Color.WHITE
|
||||||
st.cele.visible = false
|
st.cele.visible = false
|
||||||
var tw: Tween = get_meta(&"celebrate_tw", null) # 循环句柄随节点存(跨 open/close,close 必杀)
|
if has_meta(&"celebrate_tw"): # 循环句柄随节点存(跨 open/close:有则必杀、无则无事——缺 meta 跳过)
|
||||||
if tw != null and tw.is_valid():
|
var tw: Tween = get_meta(&"celebrate_tw")
|
||||||
tw.kill()
|
if tw.is_valid():
|
||||||
remove_meta(&"celebrate_tw")
|
tw.kill()
|
||||||
|
remove_meta(&"celebrate_tw")
|
||||||
_clear_crest_bricks()
|
_clear_crest_bricks()
|
||||||
|
|
||||||
|
|
||||||
@@ -328,9 +329,10 @@ func _spawn_dust_mote(i: int, base: Vector2) -> void:
|
|||||||
func _play_celebrate() -> void:
|
func _play_celebrate() -> void:
|
||||||
if UiKit.motion_scale < 1.0:
|
if UiKit.motion_scale < 1.0:
|
||||||
return
|
return
|
||||||
var prev: Tween = get_meta(&"celebrate_tw", null)
|
if has_meta(&"celebrate_tw"): # 有句柄才取并 kill(缺 meta 静默跳过——败走后首次胜利同款容错)
|
||||||
if prev != null and prev.is_valid():
|
var prev: Tween = get_meta(&"celebrate_tw")
|
||||||
prev.kill()
|
if prev.is_valid():
|
||||||
|
prev.kill()
|
||||||
var tw := st.cele.create_tween()
|
var tw := st.cele.create_tween()
|
||||||
set_meta(&"celebrate_tw", tw)
|
set_meta(&"celebrate_tw", tw)
|
||||||
tw.set_loops()
|
tw.set_loops()
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
## VERTICAL SLICE - NOT FOR PRODUCTION
|
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
## B 区结算明细带——战斗结算步骤流到玩家文案的全部行格式化规则内聚于此(挖掘期收起 1 行上轮摘要、结算期实时流)。
|
## B 区结算明细带壳——结算期逐行文字列表退役后保留挖掘期摘要位与冒险流程叙述行承载(append_bb)。
|
||||||
class_name BattleLogView
|
class_name BattleLogView
|
||||||
extends PanelContainer
|
extends PanelContainer
|
||||||
|
|
||||||
|
|
||||||
const AGG_TYPES := ["reward_ineffective"]
|
|
||||||
const COL_GOLD := UiKit.HEX_GOLD
|
|
||||||
|
|
||||||
var _db
|
var _db
|
||||||
var _band_h_dig := 0
|
var _band_h_dig := 0
|
||||||
var _band_h_settle := 0
|
var _band_h_settle := 0
|
||||||
var _log: RichTextLabel
|
var _log: RichTextLabel
|
||||||
var _summary: Label
|
var _summary: Label
|
||||||
var _hint: Label
|
var _hint: Label
|
||||||
var _mode := "dig" # dig = 收起摘要 / settle = 实时流(模式归组合根驱动)
|
var _mode := "dig" # dig = 收起摘要 / settle = 展开空带(模式归组合根驱动;逐行流退役后 settle 态无逐行内容)
|
||||||
var _round_rows: Array[String] = [] # 本结算轮行缓冲(上轮摘要构建源——append 的是 _format_row 格式化产物 String)
|
|
||||||
var _pending_agg := {} # 聚合计数行 pending(type+batch_key → {row, count})
|
|
||||||
|
|
||||||
|
|
||||||
func _init(db_ref, layout: BattleLayoutTable) -> void:
|
func _init(db_ref, layout: BattleLayoutTable) -> void:
|
||||||
@@ -64,213 +59,12 @@ func mode() -> String:
|
|||||||
|
|
||||||
func clear() -> void:
|
func clear() -> void:
|
||||||
_log.clear()
|
_log.clear()
|
||||||
_round_rows.clear()
|
|
||||||
_pending_agg = {}
|
|
||||||
_summary.text = ""
|
_summary.text = ""
|
||||||
|
|
||||||
|
|
||||||
# 每结算轮结束(下一轮开始/终局)——刷新挖掘期"上轮摘要"行
|
|
||||||
func finish_settlement_round() -> void:
|
|
||||||
_flush_pending_agg()
|
|
||||||
if _round_rows.is_empty():
|
|
||||||
return
|
|
||||||
var parts: Array[String] = []
|
|
||||||
for bb in _round_rows:
|
|
||||||
parts.append(_strip_bb(str(bb)))
|
|
||||||
var text := "上轮: " + " | ".join(parts)
|
|
||||||
if text.length() > 190:
|
|
||||||
text = text.substr(0, 190) + "…"
|
|
||||||
_summary.text = text
|
|
||||||
_round_rows.clear()
|
|
||||||
|
|
||||||
|
|
||||||
func append_bb(bb: String) -> void:
|
func append_bb(bb: String) -> void:
|
||||||
_flush_pending_agg()
|
|
||||||
_log.append_text(bb + "\n")
|
|
||||||
|
|
||||||
|
|
||||||
func append_row(row: Dictionary) -> void:
|
|
||||||
if AGG_TYPES.has(String(row.get("type", ""))):
|
|
||||||
_accumulate_agg(row)
|
|
||||||
return
|
|
||||||
_flush_pending_agg()
|
|
||||||
var bb := _format_row(row)
|
|
||||||
_round_rows.append(bb)
|
|
||||||
_log.append_text(bb + "\n")
|
_log.append_text(bb + "\n")
|
||||||
|
|
||||||
|
|
||||||
func parsed_text() -> String:
|
func parsed_text() -> String:
|
||||||
return _log.get_parsed_text()
|
return _log.get_parsed_text()
|
||||||
|
|
||||||
|
|
||||||
# 无点击回看入口——冒险中不给数据回看(归「生涯」06 登记);带保留单行摘要显示
|
|
||||||
|
|
||||||
|
|
||||||
# ---- 聚合计数(未生效类行防逐行惩罚轰炸——pattern 3 聚合纪律) ----
|
|
||||||
|
|
||||||
func _accumulate_agg(row: Dictionary) -> void:
|
|
||||||
var key := "%s|%s" % [String(row.get("type", "")), String(row.get("batch_key", ""))]
|
|
||||||
if _pending_agg.has(key):
|
|
||||||
_pending_agg[key]["count"] = int(_pending_agg[key]["count"]) + 1
|
|
||||||
else:
|
|
||||||
_flush_pending_agg()
|
|
||||||
_pending_agg[key] = {"row": row, "count": 1}
|
|
||||||
|
|
||||||
|
|
||||||
func _flush_pending_agg() -> void:
|
|
||||||
if _pending_agg.is_empty():
|
|
||||||
return
|
|
||||||
for key in _pending_agg:
|
|
||||||
var item: Dictionary[Variant, Variant] = _pending_agg[key]
|
|
||||||
var row: Dictionary[Variant, Variant] = item["row"]
|
|
||||||
var count: int = item["count"]
|
|
||||||
var bb := _format_row(row, count)
|
|
||||||
_round_rows.append(bb)
|
|
||||||
_log.append_text(bb + "\n")
|
|
||||||
_pending_agg = {}
|
|
||||||
|
|
||||||
|
|
||||||
# ---- 行格式化(模板「{行为} {值} → {目标}(来源)」) ----
|
|
||||||
|
|
||||||
func _source_label(src_key: String) -> String:
|
|
||||||
if src_key == "":
|
|
||||||
return ""
|
|
||||||
return String(_db.combat.settlement.core.source_label_map.get(src_key, src_key))
|
|
||||||
|
|
||||||
|
|
||||||
func _gold_frame(text: String) -> String:
|
|
||||||
# highlight 金框强调(形状+色彩双通道:■ 前缀 + 金底)
|
|
||||||
return "[bgcolor=%s][color=#%s]■ %s[/color][/bgcolor]" % [COL_GOLD, UiKit.HEX_ON_GOLD, text]
|
|
||||||
|
|
||||||
|
|
||||||
func _format_row(row: Dictionary, agg_count := -1) -> String:
|
|
||||||
var src := _source_label(String(row.get("source_class", "")))
|
|
||||||
var round_no: int = int(row.get("round_index", 0))
|
|
||||||
var prefix := " [color=#%s]R%d%s[/color] " % [UiKit.HEX_LOG_ROUND, round_no, ("·" + src) if src != "" else ""]
|
|
||||||
var suffix := "(%s)" % src if src != "" else ""
|
|
||||||
var kind := String(row.get("type", ""))
|
|
||||||
var body := ""
|
|
||||||
match kind:
|
|
||||||
"effect":
|
|
||||||
body = _fmt_effect(row, prefix, suffix)
|
|
||||||
"damage":
|
|
||||||
body = _fmt_damage(row, prefix, suffix)
|
|
||||||
"heal", "cast", "decay":
|
|
||||||
body = _fmt_simple(kind, row, prefix, suffix)
|
|
||||||
"reward_ineffective":
|
|
||||||
body = _fmt_ineffective(row, prefix, suffix, agg_count)
|
|
||||||
"seal_miss":
|
|
||||||
body = _fmt_seal_miss(row, prefix)
|
|
||||||
"verdict":
|
|
||||||
body = _fmt_verdict(row)
|
|
||||||
_:
|
|
||||||
body = _fmt_default(row, prefix, suffix)
|
|
||||||
return body
|
|
||||||
|
|
||||||
|
|
||||||
## 简单行域(heal/cast/decay 三型——单行单墨直排)
|
|
||||||
func _fmt_simple(kind: String, row: Dictionary, prefix: String, suffix: String) -> String:
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
match kind:
|
|
||||||
"heal":
|
|
||||||
return prefix + "[color=#%s]%s +%d%s%s[/color]" % [UiKit.HEX_LOG_HEAL, name_, int(row.get("value", 0)), _tail_of(row), suffix]
|
|
||||||
"cast":
|
|
||||||
# 施放行:增益技 0 伤害施放,具名技能
|
|
||||||
return prefix + "[color=#%s]✦ %s%s[/color]" % [UiKit.HEX_LOG_CAST, name_, suffix]
|
|
||||||
"decay":
|
|
||||||
return prefix + "[color=#%s]状态衰减 ×%d[/color]" % [UiKit.HEX_LOG_DECAY, int(row.get("value", 0))]
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
## 默认行域(未知型/高亮星标——未知型=名行直排)
|
|
||||||
func _fmt_default(row: Dictionary, prefix: String, suffix: String) -> String:
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
if String(row.get("type", "")) == "highlight":
|
|
||||||
return prefix + _gold_frame("★ %s" % name_)
|
|
||||||
return prefix + name_ + suffix
|
|
||||||
|
|
||||||
|
|
||||||
## 尾注域:目标格指向(行文附加)
|
|
||||||
func _tail_of(row: Dictionary) -> String:
|
|
||||||
var target := String(row.get("target", ""))
|
|
||||||
return " → %s" % target if target != "" else ""
|
|
||||||
|
|
||||||
|
|
||||||
## GP 型效果行域:「GP 袋 +3」兑付反馈——value = 本行 ±power,
|
|
||||||
## escrow = 战斗内缓冲现值(入钱包在战斗末一次上抛——呈现语义与增益池分账)
|
|
||||||
func _fmt_effect(row: Dictionary, prefix: String, suffix: String) -> String:
|
|
||||||
var v: int = int(row.get("value", 0))
|
|
||||||
var hl := String(row.get("highlight", ""))
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
if String(row.get("effect_id", "")) in ["gp_gain", "gp_loss"]:
|
|
||||||
var gp_col := UiKit.HEX_LOG_GAIN if v > 0 else UiKit.HEX_LOG_LOSS
|
|
||||||
var gp_body := "%s %+d(战斗暂存 %+d)%s" % [name_, v, int(row.get("escrow", 0)), suffix]
|
|
||||||
return prefix + (_gold_frame(gp_body) if hl != "" else "[color=%s]%s[/color]" % [gp_col, gp_body])
|
|
||||||
# 效果行 value = 单次贡献值,pool_value = 池合成值——禁相加呈现(战斗结算 呈现细则)
|
|
||||||
var pool: int = int(row.get("pool_value", 0))
|
|
||||||
var col := UiKit.HEX_LOG_HEAL if v > 0 else UiKit.HEX_LOG_LOSS
|
|
||||||
var body := "%s 单次%+d(池 %+d)%s" % [name_, v, pool, suffix]
|
|
||||||
return prefix + (_gold_frame(body) if hl != "" else "[color=%s]%s[/color]" % [col, body])
|
|
||||||
|
|
||||||
|
|
||||||
## 伤害行域:行上归因读数只剩掷点档位随行(护甲等级掷点留档——掷点读数与档位随行可读;
|
|
||||||
## 吃掷点分量恒带,棋盘来源行不带)。伤害数字不明显——伤害值放大加色独立于行文(朱红大一号)
|
|
||||||
func _fmt_damage(row: Dictionary, prefix: String, suffix: String) -> String:
|
|
||||||
var v: int = int(row.get("value", 0))
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
var tail := _tail_of(row)
|
|
||||||
var roll_txt := ""
|
|
||||||
if row.get("roll", null) != null:
|
|
||||||
roll_txt = "〔掷 %d vs 护甲 %d" % [int(row.roll), int(row.ac)]
|
|
||||||
if bool(row.get("crit", false)):
|
|
||||||
roll_txt += " · 暴击×%d" % int(_db.combat.settlement.damage_roll.crit_multiplier)
|
|
||||||
elif int(row.tier) < 100:
|
|
||||||
roll_txt += " · ×%d%%" % int(row.tier)
|
|
||||||
roll_txt += "〕"
|
|
||||||
var kill := " ⚔击杀!" if row.get("killed", false) else ""
|
|
||||||
var body := "%s [color=#%s][size=17]-%d[/size][/color]%s%s%s%s" % [name_, UiKit.HEX_LOG_DMG_NUM, v, roll_txt, tail, kill, suffix]
|
|
||||||
if bool(row.get("crit", false)):
|
|
||||||
return prefix + _gold_frame(body) # nat 最大面暴击 = 金框高亮行
|
|
||||||
var body_col := UiKit.HEX_LOG_DMG_KILL if row.get("killed", false) else (UiKit.HEX_LOG_ROUND if v == 0 else UiKit.HEX_LOG_DMG_BODY)
|
|
||||||
return prefix + "[color=%s]%s[/color]" % [body_col, body]
|
|
||||||
|
|
||||||
|
|
||||||
## 未生效行域:⚠ icon + 划线形状冗余(非色相独载)+ 聚合计数
|
|
||||||
func _fmt_ineffective(row: Dictionary, prefix: String, suffix: String, agg_count: int) -> String:
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
var n := (" ×%d" % agg_count) if agg_count > 1 else ""
|
|
||||||
return prefix + "[s][color=#%s]⚠ %s%s[/color][/s]%s" % [UiKit.HEX_LOG_VOIDED, name_, n, suffix]
|
|
||||||
|
|
||||||
|
|
||||||
## 封印落空行域:完美破/首失豁免两注记分档(金框=破完美/普通墨=豁免)
|
|
||||||
func _fmt_seal_miss(row: Dictionary, prefix: String) -> String:
|
|
||||||
var hl := String(row.get("highlight", ""))
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
var miss_note := ""
|
|
||||||
if hl == "perfect_broken":
|
|
||||||
miss_note = "(本图完美封印已破——清图奖励不再加倍)"
|
|
||||||
elif hl == "":
|
|
||||||
miss_note = "(首次封印落空已豁免——不计入完美封印判定)"
|
|
||||||
var body := "✗ %s%s" % [name_, miss_note]
|
|
||||||
return prefix + (_gold_frame(body) if hl == "perfect_broken" else "[color=#%s]%s[/color]" % [UiKit.HEX_LOG_ROUND, body])
|
|
||||||
|
|
||||||
|
|
||||||
## 裁定行域:胜金/负绿双墨(粗体菱形头)
|
|
||||||
func _fmt_verdict(row: Dictionary) -> String:
|
|
||||||
var name_: String = String(row.get("display_name", ""))
|
|
||||||
if int(row.value) == 1:
|
|
||||||
return "[color=#%s][b]◆ %s[/b][/color]" % [UiKit.HEX_LOG_WIN, name_]
|
|
||||||
return "[color=#%s][b]◆ %s[/b][/color]" % [UiKit.HEX_LOG_GAIN, name_]
|
|
||||||
|
|
||||||
|
|
||||||
func _strip_bb(bb: String) -> String:
|
|
||||||
var out := ""
|
|
||||||
var in_tag := false
|
|
||||||
for ch in bb:
|
|
||||||
if ch == "[":
|
|
||||||
in_tag = true
|
|
||||||
elif ch == "]":
|
|
||||||
in_tag = false
|
|
||||||
elif not in_tag:
|
|
||||||
out += ch
|
|
||||||
return out.replace(" ", " ").strip_edges()
|
|
||||||
@@ -108,7 +108,7 @@ func _apply_hover_visuals(c: Vector2i) -> void:
|
|||||||
_show_path_preview(c)
|
_show_path_preview(c)
|
||||||
elif adjacent:
|
elif adjacent:
|
||||||
u.face.hl_visible = true
|
u.face.hl_visible = true
|
||||||
u.face.hl_color = COL_HL_TARGET # 挖掘目标格边框(相邻封印格同此——左键直接挖)
|
u.face.hl_color = COL_HL_TARGET # 挖掘目标格边框(已封印格不入 _diggable——落下方封印禁入分支)
|
||||||
_set_cursor_shape(c, CURSOR_DIG)
|
_set_cursor_shape(c, CURSOR_DIG)
|
||||||
elif seal:
|
elif seal:
|
||||||
u.face.hl_visible = true
|
u.face.hl_visible = true
|
||||||
|
|||||||
@@ -300,8 +300,8 @@ func refresh() -> void:
|
|||||||
var hero: Vector2i = _minesweeper.hero_pos()
|
var hero: Vector2i = _minesweeper.hero_pos()
|
||||||
_diggable.clear()
|
_diggable.clear()
|
||||||
for n in _board.neighbors8(hero):
|
for n in _board.neighbors8(hero):
|
||||||
if not _minesweeper.is_revealed(n) and not _minesweeper.is_removed(n):
|
if not _minesweeper.is_revealed(n) and not _minesweeper.is_removed(n) and not _minesweeper.has_seal(n):
|
||||||
_diggable[n] = true
|
_diggable[n] = true # 已封印格不入可挖域(封印受理即揭示——挖封印格被拒)
|
||||||
_recompute_glow(hero)
|
_recompute_glow(hero)
|
||||||
for y in _board.height:
|
for y in _board.height:
|
||||||
for x in _board.width:
|
for x in _board.width:
|
||||||
@@ -474,14 +474,15 @@ func _on_cell_input(c: Vector2i, ev: InputEvent) -> void:
|
|||||||
if ev.button_index == MOUSE_BUTTON_LEFT:
|
if ev.button_index == MOUSE_BUTTON_LEFT:
|
||||||
if _minesweeper.is_revealed(c):
|
if _minesweeper.is_revealed(c):
|
||||||
action_requested.emit(c, "move")
|
action_requested.emit(c, "move")
|
||||||
|
elif _minesweeper.has_seal(c):
|
||||||
|
pass # 已封印格零动作(封印受理即揭示——挖封印格被拒,左右键同零意图)
|
||||||
else:
|
else:
|
||||||
action_requested.emit(c, "dig")
|
action_requested.emit(c, "dig")
|
||||||
_hover_comp.detect_chord(c)
|
_hover_comp.detect_chord(c)
|
||||||
elif ev.button_index == MOUSE_BUTTON_RIGHT:
|
elif ev.button_index == MOUSE_BUTTON_RIGHT:
|
||||||
if not _minesweeper.has_seal(c):
|
if not _minesweeper.has_seal(c):
|
||||||
action_requested.emit(c, "seal_place")
|
action_requested.emit(c, "seal_place")
|
||||||
# 封印 = 一次性承诺:右键对封印格零动作(无撤封印);
|
# 封印 = 受理即揭示的最终承诺:右键对封印格零动作(无撤封印),左键同零动作。
|
||||||
# 左键相邻封印格直接挖(规则引擎放行)。
|
|
||||||
|
|
||||||
|
|
||||||
# ---- 奖励徽章(已开格身份 icon——封印之下、纹带之上、不进数字区) ----
|
# ---- 奖励徽章(已开格身份 icon——封印之下、纹带之上、不进数字区) ----
|
||||||
@@ -536,20 +537,22 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
|
|||||||
var seal: bool = _minesweeper.has_seal(c)
|
var seal: bool = _minesweeper.has_seal(c)
|
||||||
var removed: bool = _minesweeper.is_removed(c) # 中立移除格(退色降档)
|
var removed: bool = _minesweeper.is_removed(c) # 中立移除格(退色降档)
|
||||||
var is_hero: bool = c == hero
|
var is_hero: bool = c == hero
|
||||||
# 封印印记下发(卡④ 法阵化):封印格=未开且未移除 → CellUnit 封印子件绘制(着色器参数化);
|
# 封印印记下发(卡④ 法阵化+封印受理即揭示改版):封印格(未移除)→ CellUnit 封印子件绘制
|
||||||
# 其余格撤子件。层序与迷雾门控在 CellUnit 侧承载(seal_mark_layer/fog_state 联动)。
|
# (着色器参数化)——印记可见性不依赖揭示态(已揭示格承载=新组合态);其余格撤子件。
|
||||||
u.seal_on = seal and not revealed
|
# 层序与迷雾门控在 CellUnit 侧承载(seal_mark_layer/fog_state 联动)。
|
||||||
|
u.seal_on = seal
|
||||||
if removed:
|
if removed:
|
||||||
revealed = false # 移除格固定未开呈现基座(退色暗幕层承载;危险格本无数字,周边数字冻结)
|
revealed = false # 移除格固定未开呈现基座(退色暗幕层承载;危险格本无数字,周边数字冻结)
|
||||||
seal = false
|
seal = false
|
||||||
u.seal_on = false
|
u.seal_on = false
|
||||||
# 绘制层五段(字形与色牌→基底瓦片→立面投影→秘宝/变异叠加→迷雾)——段间交换经单元状态面
|
# 绘制层五段(字形与色牌→基底瓦片→立面投影→秘宝/变异叠加→迷雾)——段间交换经单元状态面
|
||||||
#(u.base/u.face 域件与 u.glyph/u.glyph_color),唯一例外=基底色 bg 经 ink 段返回值交 base 段(无单元场域承载)
|
#(u.base/u.face 域件与 u.glyph/u.glyph_color),唯一例外=基底色 bg 经 ink 段返回值交 base 段(无单元场域承载)
|
||||||
|
var shown: bool = revealed or seal # 呈现揭示态(封印受理即揭示——地板瓦片/身份字形/迷雾开启)
|
||||||
var bg: Color = _paint_cell_ink(c, u, revealed, seal)
|
var bg: Color = _paint_cell_ink(c, u, revealed, seal)
|
||||||
_paint_cell_base(c, u, revealed, is_hero, bg)
|
_paint_cell_base(c, u, shown, is_hero, bg)
|
||||||
_paint_cell_facade(c, u, revealed)
|
_paint_cell_facade(c, u, shown)
|
||||||
_paint_cell_overlays(c, u, revealed)
|
_paint_cell_overlays(c, u, revealed)
|
||||||
_paint_cell_fog(c, u, revealed, hero)
|
_paint_cell_fog(c, u, shown, hero)
|
||||||
u.face.removed_dim = removed
|
u.face.removed_dim = removed
|
||||||
u.queue_redraw()
|
u.queue_redraw()
|
||||||
|
|
||||||
@@ -575,11 +578,19 @@ func _paint_cell_ink(c: Vector2i, u: Node2D, revealed: bool, seal: bool) -> Colo
|
|||||||
else:
|
else:
|
||||||
glyph = str(d)
|
glyph = str(d)
|
||||||
digit_col = _digit_ink(d) # 数字墨三档色温(§4.1)
|
digit_col = _digit_ink(d) # 数字墨三档色温(§4.1)
|
||||||
|
elif seal:
|
||||||
|
# 封印受理即揭示:身份字形按板事实当场可见(cell_identity 单点——不用等轮末判定;
|
||||||
|
# 数字遮蔽不适用——遮蔽打脸受理即揭示)。
|
||||||
|
bg = COL_FLOOR
|
||||||
|
var ident := _board.cell_identity(c) # 推断形态(规约§76 合法面)——参数化注解拒收函数返回的裸 Dictionary
|
||||||
|
if String(ident.get("kind", "")) == "mine":
|
||||||
|
glyph = "危"
|
||||||
|
digit_col = UiKit.RED_MINE
|
||||||
|
elif int(ident.get("digit", 0)) > 0:
|
||||||
|
glyph = str(int(ident.get("digit", 0)))
|
||||||
|
digit_col = _digit_ink(int(ident.get("digit", 0)))
|
||||||
else:
|
else:
|
||||||
if seal:
|
bg = COL_BRICK
|
||||||
bg = COL_BRICK # 封印印记由 CellUnit 封印子件绘制(卡④ 法阵化——缺图字形回退随贴图路径退役)
|
|
||||||
else:
|
|
||||||
bg = COL_BRICK
|
|
||||||
u.glyph = glyph
|
u.glyph = glyph
|
||||||
u.glyph_color = digit_col
|
u.glyph_color = digit_col
|
||||||
# 色牌后备(数字直画退牌;「危」/「?」维持牌载保读性)+ v3.4:双峰纹理板
|
# 色牌后备(数字直画退牌;「危」/「?」维持牌载保读性)+ v3.4:双峰纹理板
|
||||||
@@ -588,7 +599,7 @@ func _paint_cell_ink(c: Vector2i, u: Node2D, revealed: bool, seal: bool) -> Colo
|
|||||||
if plate_digit:
|
if plate_digit:
|
||||||
digit_col = COL_DIGIT # 牌上深墨族(素牌 12:1——双峰纹理免疫)
|
digit_col = COL_DIGIT # 牌上深墨族(素牌 12:1——双峰纹理免疫)
|
||||||
u.glyph_color = digit_col
|
u.glyph_color = digit_col
|
||||||
u.plate = revealed and (glyph == "危" or glyph == "?" or plate_digit)
|
u.plate = (revealed or seal) and (glyph == "危" or glyph == "?" or plate_digit)
|
||||||
return bg
|
return bg
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func _build_board_children(board_area: Control, vb: VBoxContainer) -> void:
|
|||||||
hint.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
hint.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||||
hint.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
hint.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
vb.add_child(hint)
|
vb.add_child(hint)
|
||||||
var hl := UiKit.label("左键 挖掘 / 移动 · 右键 封印(不可逆) · 同格双击 快开",UiKit.FS_CAPTION, false, UiKit.WARM_FAINT)
|
var hl := UiKit.label("左键 挖掘 / 移动 · 右键 封印(受理即揭示·不可逆)",UiKit.FS_CAPTION, false, UiKit.WARM_FAINT)
|
||||||
hint.add_child(hl)
|
hint.add_child(hl)
|
||||||
# 信号转发(组合根只接线一处)
|
# 信号转发(组合根只接线一处)
|
||||||
board_view.action_requested.connect(_forward_action)
|
board_view.action_requested.connect(_forward_action)
|
||||||
|
|||||||
@@ -11,10 +11,15 @@ func _init() -> void:
|
|||||||
set_anchors_preset(Control.PRESET_TOP_WIDE)
|
set_anchors_preset(Control.PRESET_TOP_WIDE)
|
||||||
custom_minimum_size = Vector2(0, 48) # 高 48px 浮层覆盖、不挤压画面(camp.md §顶栏)
|
custom_minimum_size = Vector2(0, 48) # 高 48px 浮层覆盖、不挤压画面(camp.md §顶栏)
|
||||||
mouse_filter = Control.MOUSE_FILTER_IGNORE # HUD 栏不挡场景命中区(浮层覆盖语义)
|
mouse_filter = Control.MOUSE_FILTER_IGNORE # HUD 栏不挡场景命中区(浮层覆盖语义)
|
||||||
|
UiKit.camp_hud_band_surface(self) # 栏体色面——整件外观单一出口(色值与 α、铺满、不吃点击、挂载全在出口内);先入=绘制序底,徽章后入不被盖
|
||||||
_badge = UiKit.keystone_badge("钥石 0")
|
_badge = UiKit.keystone_badge("钥石 0")
|
||||||
_badge.set_anchors_preset(Control.PRESET_CENTER_RIGHT)
|
var dock := HBoxContainer.new() # 右对齐容器承载徽章(Q2 已裁乙——位数增宽自然向左展;摆位机制先例=confirm_dialog 钮行同款容器 alignment)
|
||||||
_badge.position = Vector2(-160, 8) # 顶栏右位次(UiKit 现行件域内——代拍板 3)
|
dock.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||||
add_child(_badge)
|
dock.offset_right = -12.0 # 右缘内缩 12px(UiKit 钮间距同档——白名单 3)
|
||||||
|
dock.alignment = BoxContainer.ALIGNMENT_END
|
||||||
|
dock.mouse_filter = Control.MOUSE_FILTER_IGNORE # 容器自身默认 STOP——与出口内 IGNORE 是两个点,必须同批落(漏一处顶排物件点不动)
|
||||||
|
dock.add_child(_badge)
|
||||||
|
add_child(dock)
|
||||||
|
|
||||||
|
|
||||||
## 余额写入(格式串=既有消费面同款「钥石 %d」——badge 工厂约定单点,禁第二格式串)
|
## 余额写入(格式串=既有消费面同款「钥石 %d」——badge 工厂约定单点,禁第二格式串)
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ func _build_layer_node(spec: CampSceneLayerSpec) -> Control:
|
|||||||
if tex != null:
|
if tex != null:
|
||||||
var tr := TextureRect.new()
|
var tr := TextureRect.new()
|
||||||
tr.texture = tex
|
tr.texture = tex
|
||||||
|
tr.expand_mode = TextureRect.EXPAND_IGNORE_SIZE # 允许节点小于贴图原尺寸(门扇 240×211→矩形 138 高)
|
||||||
tr.stretch_mode = TextureRect.STRETCH_SCALE
|
tr.stretch_mode = TextureRect.STRETCH_SCALE
|
||||||
node = tr
|
node = tr
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -30,13 +30,15 @@ func _init() -> void:
|
|||||||
box.add_child(btn_row)
|
box.add_child(btn_row)
|
||||||
_cancel_btn = UiKit.button("取消")
|
_cancel_btn = UiKit.button("取消")
|
||||||
_cancel_btn.pressed.connect(_emit_cancelled)
|
_cancel_btn.pressed.connect(_emit_cancelled)
|
||||||
btn_row.add_child(_cancel_btn)
|
|
||||||
_secondary_btn = UiKit.button("次选项")
|
_secondary_btn = UiKit.button("次选项")
|
||||||
_secondary_btn.pressed.connect(_emit_secondary)
|
_secondary_btn.pressed.connect(_emit_secondary)
|
||||||
btn_row.add_child(_secondary_btn)
|
|
||||||
_confirm_btn = UiKit.button("确认")
|
_confirm_btn = UiKit.button("确认")
|
||||||
_confirm_btn.pressed.connect(_emit_confirmed)
|
_confirm_btn.pressed.connect(_emit_confirmed)
|
||||||
|
# 位次定值(HUD框架.md:90 三条纪律·其三——推进钮在左、次推进居中、维持在右;四处消费方
|
||||||
|
# 共用本件同一序。信号按按钮对象路由、不按位次——换序不改路由〔营地交互修复批契约 3〕)
|
||||||
btn_row.add_child(_confirm_btn)
|
btn_row.add_child(_confirm_btn)
|
||||||
|
btn_row.add_child(_secondary_btn)
|
||||||
|
btn_row.add_child(_cancel_btn)
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -153,26 +153,6 @@ func _on_confirm_pressed() -> void:
|
|||||||
pick_confirmed.emit(_selected)
|
pick_confirmed.emit(_selected)
|
||||||
|
|
||||||
|
|
||||||
# 探针/测试复用:以真实按钮路径触发点选、确认与继续(树序遮挡纪律——断言走真实信号路径)
|
|
||||||
func press_card(index: int) -> void:
|
|
||||||
# M7:卡载体 Button→bcard(gui_input 点选)——真实路径=同一 _select_card 处理器,探针语义不变
|
|
||||||
if index >= 0 and index < _card_meta.size():
|
|
||||||
_select_card(String(_card_meta[index].get("id", "")))
|
|
||||||
|
|
||||||
|
|
||||||
func press_confirm() -> void:
|
|
||||||
_confirm_btn.pressed.emit()
|
|
||||||
|
|
||||||
|
|
||||||
func press_continue() -> void:
|
|
||||||
_continue_btn.pressed.emit()
|
|
||||||
|
|
||||||
|
|
||||||
# 探针/测试复用:以真实按钮路径触发刷新意图(信号外发——受理归组合根)
|
|
||||||
func press_refresh() -> void:
|
|
||||||
_refresh_btn.pressed.emit()
|
|
||||||
|
|
||||||
|
|
||||||
# 兑付反馈态(curio_resolved 到达——结果行追加在头部之后;唯一出口 = 继续)
|
# 兑付反馈态(curio_resolved 到达——结果行追加在头部之后;唯一出口 = 继续)
|
||||||
func show_result(text: String) -> void:
|
func show_result(text: String) -> void:
|
||||||
_label.text = _header + "\n" + text
|
_label.text = _header + "\n" + text
|
||||||
|
|||||||
@@ -123,20 +123,6 @@ func output_text() -> String:
|
|||||||
return st.sim_out.get_parsed_text()
|
return st.sim_out.get_parsed_text()
|
||||||
|
|
||||||
|
|
||||||
# ---- 探针接缝(真实翻译出口——按钮 pressed 信号路径,非直调组合根)----
|
|
||||||
|
|
||||||
func press_apply_for_probe() -> void:
|
|
||||||
_apply_btn_pressed()
|
|
||||||
|
|
||||||
|
|
||||||
func press_reset_for_probe() -> void:
|
|
||||||
_reset_btn_pressed()
|
|
||||||
|
|
||||||
|
|
||||||
func press_simulate_for_probe() -> void:
|
|
||||||
_sim_btn.pressed.emit()
|
|
||||||
|
|
||||||
|
|
||||||
# ---- 内部(信号 → 外发)----
|
# ---- 内部(信号 → 外发)----
|
||||||
|
|
||||||
func _apply_btn_pressed() -> void:
|
func _apply_btn_pressed() -> void:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ signal closed
|
|||||||
const ENTRIES := [
|
const ENTRIES := [
|
||||||
["#C9AF83", "完整覆尘地砖", "未开格——左键挖开(1AP,须相邻)· 右键封印(1AP)"],
|
["#C9AF83", "完整覆尘地砖", "未开格——左键挖开(1AP,须相邻)· 右键封印(1AP)"],
|
||||||
["#B39A78", "碎裂裸土", "已开 0 格——可通行,左键移动(免费)"],
|
["#B39A78", "碎裂裸土", "已开 0 格——可通行,左键移动(免费)"],
|
||||||
["#000000", "封印", "封印印记(呈现名·不能拔)——轮末自动判定标中;标空可左键直接挖开(安全格零奖励、危险格受挖掘惩罚)"],
|
["#000000", "封印", "封印印记(受理即揭示——落定当场可见格下身份,随图存续不能拔)——轮末自动判定标中/标空;已封印格零动作(不可再挖开)"],
|
||||||
["#2e86de", "小人", "探险者——8 向相邻未开格常驻微光 = 可挖域"],
|
["#2e86de", "小人", "探险者——8 向相邻未开格常驻微光 = 可挖域"],
|
||||||
["#F0A828", "金徽章", "已开格奖励身份 icon(封印之下、数值之上,不进数字区)"],
|
["#F0A828", "金徽章", "已开格奖励身份 icon(封印之下、数值之上,不进数字区)"],
|
||||||
["#F0A828", "九徽章解码", "攻=攻击 · 守=护甲 · 爆=爆裂 · 医=回复 · 弱=削弱 · 穿=穿刺 · 魔=魔法 · 行=行动点 · 金=GP"],
|
["#F0A828", "九徽章解码", "攻=攻击 · 守=护甲 · 爆=爆裂 · 医=回复 · 弱=削弱 · 穿=穿刺 · 魔=魔法 · 行=行动点 · 金=GP"],
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ const SLOT_STEP_Y := 58 # 同层槽位纵向步距
|
|||||||
const HIT_PAD := 6.0 # 图上命中外扩(指宽容差)
|
const HIT_PAD := 6.0 # 图上命中外扩(指宽容差)
|
||||||
const CONFIRM_WINDOW_S := 3.0 # 放弃确认态窗口(秒——超时回落)
|
const CONFIRM_WINDOW_S := 3.0 # 放弃确认态窗口(秒——超时回落)
|
||||||
const COL_HP_BAR_BACK := UiKit.HP_BAR_BACK # 迷你血条深底(对暗面板可辨;值单点收 UiKit)
|
const COL_HP_BAR_BACK := UiKit.HP_BAR_BACK # 迷你血条深底(对暗面板可辨;值单点收 UiKit)
|
||||||
|
const DRAG_THRESHOLD := 8.0 # 拖动距离阈值(布局决策 5 provisional——超阈值进拖拽态,拖拽不触发选路)
|
||||||
|
const WHEEL_STEP := 60.0 # 滚轮横滚单档步进(provisional 实现期定值;方向映射=代拍板:下/右=向右前进向)
|
||||||
|
|
||||||
## 内部状态件(u2 子域拆件——契约 9 职责轴):_MapState=选路屏运行态与图绘制态(单一变化原因=
|
## 内部状态件(u2 子域拆件——契约 9 职责轴):_MapState=选路屏运行态与图绘制态(单一变化原因=
|
||||||
## 选路呈现)。layer_decor 域字典承载换层装饰三件(图标贴图/石纹面/tint 层号——装饰域归并形态)。
|
## 选路呈现)。layer_decor 域字典承载换层装饰三件(图标贴图/石纹面/tint 层号——装饰域归并形态)。
|
||||||
@@ -39,6 +41,7 @@ class _MapState extends RefCounted:
|
|||||||
var runner = null
|
var runner = null
|
||||||
var title: Label
|
var title: Label
|
||||||
var canvas: Control
|
var canvas: Control
|
||||||
|
var viewport: LevelMapViewport # 卷轴视口承载件(布局决策 5——画布宿主/裁切/clamp/跟随/指引)
|
||||||
var level_label: Label
|
var level_label: Label
|
||||||
var gp_value: Label
|
var gp_value: Label
|
||||||
var hp_value: Label
|
var hp_value: Label
|
||||||
@@ -54,6 +57,8 @@ class _MapState extends RefCounted:
|
|||||||
var _cand_ids: Array[int] = [] # 本停点候选 id 集(图上命中合法集;探针直读冻结——住宿主)
|
var _cand_ids: Array[int] = [] # 本停点候选 id 集(图上命中合法集;探针直读冻结——住宿主)
|
||||||
var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它;探针直读冻结)
|
var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它;探针直读冻结)
|
||||||
var _hover_id := -1 # 悬停预承诺候选(-1 = 无;探针直读冻结)
|
var _hover_id := -1 # 悬停预承诺候选(-1 = 无;探针直读冻结)
|
||||||
|
var _drag_active := false # 拖拽态(超阈值至抬杆——拖拽不触发选路,布局决策 5)
|
||||||
|
var _drag_press_pos := Vector2(-1, -1) # 拖距判定基准(按下点画布局部坐标;-1 = 无按下跟踪)
|
||||||
var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——只在冒险模式开;探针直读冻结)
|
var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——只在冒险模式开;探针直读冻结)
|
||||||
var status_badge: Button # 状态面板入口角标(顶栏 GP 徽右侧;连接归组合根;探针直读冻结)
|
var status_badge: Button # 状态面板入口角标(顶栏 GP 徽右侧;连接归组合根;探针直读冻结)
|
||||||
var _layout_cache := {"nodes": [], "canvas_size": Vector2.ZERO, "pos": {}} # 布局缓存(_layout 纯函数于 (nodes, canvas)——键=nodes 内容等价+画布尺寸,图态换代或画布尺寸变即自然失效;探针直读冻结)
|
var _layout_cache := {"nodes": [], "canvas_size": Vector2.ZERO, "pos": {}} # 布局缓存(_layout 纯函数于 (nodes, canvas)——键=nodes 内容等价+画布尺寸,图态换代或画布尺寸变即自然失效;探针直读冻结)
|
||||||
@@ -74,15 +79,15 @@ func _init() -> void:
|
|||||||
base.add_child(tex)
|
base.add_child(tex)
|
||||||
_map.layer_decor.noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档)
|
_map.layer_decor.noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档)
|
||||||
base.add_child(UiKit.vignette_rect())
|
base.add_child(UiKit.vignette_rect())
|
||||||
var center := CenterContainer.new()
|
# 三段纵排页(布局决策 5 卷轴视口:顶栏/标题在上、图区视口扩张充盈、底栏在下——
|
||||||
center.set_anchors_preset(Control.PRESET_FULL_RECT)
|
# 视口为窗口屏为框,画布随图生长可超屏)
|
||||||
base.add_child(center)
|
var page := VBoxContainer.new()
|
||||||
var box := VBoxContainer.new()
|
page.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||||
box.add_theme_constant_override("separation", 10)
|
page.add_theme_constant_override("separation", 10)
|
||||||
center.add_child(box)
|
base.add_child(page)
|
||||||
_build_top_bar(box)
|
_build_top_bar(page)
|
||||||
_build_canvas(box)
|
_build_canvas(page)
|
||||||
_build_status_bar(box)
|
_build_status_bar(page)
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
|
|
||||||
@@ -122,14 +127,21 @@ func _build_top_bar(box: VBoxContainer) -> void:
|
|||||||
box.add_child(_map.title)
|
box.add_child(_map.title)
|
||||||
|
|
||||||
|
|
||||||
## 节点图画布域(图上点击 = 唯一提交通道——布局决策 2;mouse_filter STOP 接悬停/点击)
|
## 节点图区(卷轴视口承载——布局决策 5):视口件为窗口(裁切/offset/clamp/跟随/指引),
|
||||||
|
## 画布为其子件;图上点击 = 唯一提交通道(布局决策 2),拖拽/滚轮判定留在画布 _gui_input
|
||||||
|
## (事件流同源——悬停/选路同源,视口件不做父子事件路由)
|
||||||
func _build_canvas(box: VBoxContainer) -> void:
|
func _build_canvas(box: VBoxContainer) -> void:
|
||||||
_map.canvas = Control.new()
|
_map.canvas = Control.new()
|
||||||
_map.canvas.custom_minimum_size = Vector2(620, 240)
|
_map.canvas.custom_minimum_size = Vector2(620, 240)
|
||||||
_map.canvas.mouse_filter = Control.MOUSE_FILTER_STOP
|
_map.canvas.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||||
_map.canvas.draw.connect(_draw_graph.bind(_map.canvas))
|
_map.canvas.draw.connect(_draw_graph.bind(_map.canvas))
|
||||||
_map.canvas.gui_input.connect(_on_canvas_input)
|
_map.canvas.gui_input.connect(_on_canvas_input)
|
||||||
box.add_child(_map.canvas)
|
_map.canvas.mouse_exited.connect(_on_canvas_mouse_exited)
|
||||||
|
_map.viewport = LevelMapViewport.new()
|
||||||
|
_map.viewport.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
_map.viewport.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||||
|
box.add_child(_map.viewport)
|
||||||
|
_map.viewport.setup(_map.canvas, _viewport_anchor, Vector2(1280, 800)) # 兜底尺寸=设计基座(实况窗口以布局为准)
|
||||||
|
|
||||||
|
|
||||||
## 底部状态栏域(合并单条:亮米面板一站读齐=头像+生命+属性+本关加成/流派件——demo ④;
|
## 底部状态栏域(合并单条:亮米面板一站读齐=头像+生命+属性+本关加成/流派件——demo ④;
|
||||||
@@ -297,6 +309,9 @@ func open_choices(cands: Array, runner: LevelRunner) -> void:
|
|||||||
_fit_canvas(_map.runner.nodes())
|
_fit_canvas(_map.runner.nodes())
|
||||||
_apply_level_tint(int(_map.runner.level_row.get("level_index", 0)))
|
_apply_level_tint(int(_map.runner.level_row.get("level_index", 0)))
|
||||||
visible = true
|
visible = true
|
||||||
|
# 视口锚定(布局决策 5):入口停点(尚无当前节点)=首锚即达;其余停点/兑付回图=平滑跟随
|
||||||
|
# (停点切换与兑付确认回图——减动效开由视口件跳终态)
|
||||||
|
_map.viewport.reanchor(_map.runner.current_node_id() >= 0)
|
||||||
if not was_visible:
|
if not was_visible:
|
||||||
# 独立屏淡入(spec Transitions:约 200ms;alpha 淡入非明度变化——art-bible §2 明度恒定)
|
# 独立屏淡入(spec Transitions:约 200ms;alpha 淡入非明度变化——art-bible §2 明度恒定)
|
||||||
modulate.a = 0.0
|
modulate.a = 0.0
|
||||||
@@ -323,6 +338,7 @@ func _fit_canvas(nodes: Array) -> void:
|
|||||||
SLOT_BASE_Y + maxslot * SLOT_STEP_Y + NODE_HALF.y + 24.0) # +24 = 类型文字标签行
|
SLOT_BASE_Y + maxslot * SLOT_STEP_Y + NODE_HALF.y + 24.0) # +24 = 类型文字标签行
|
||||||
_content_size = _content_size.max(Vector2(620, 256)) # 下限(抬高容纳标签行)
|
_content_size = _content_size.max(Vector2(620, 256)) # 下限(抬高容纳标签行)
|
||||||
_map.canvas.custom_minimum_size = _content_size
|
_map.canvas.custom_minimum_size = _content_size
|
||||||
|
_map.canvas.size = _content_size # 同帧收敛(视口锚点/包络数学与 _layout 同源读画布尺寸——容器延迟收敛不等锚点)
|
||||||
|
|
||||||
|
|
||||||
# 换层色板渐变挂点(art-bible §2.7 下探过渡切片档——关卡结算确认→下一关→独立屏淡入链路上的
|
# 换层色板渐变挂点(art-bible §2.7 下探过渡切片档——关卡结算确认→下一关→独立屏淡入链路上的
|
||||||
@@ -356,20 +372,70 @@ func apply_status(payload: Dictionary) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# ---- 图上命中(布局决策 2——唯一提交通道;探针 press_candidate 同路径) ----
|
# ---- 图上命中(布局决策 2——唯一提交通道;探针 press_candidate 同路径) ----
|
||||||
|
# 拖拽与点击以拖动距离阈值区分(布局决策 5):按下起跟踪拖距,超阈值进拖拽态逐帧平移视口,
|
||||||
|
# 抬杆不提交;未超阈值的完整点击(按下→抬杆)=提交沿——命中候选即提交,语义零改动。
|
||||||
|
|
||||||
func _on_canvas_input(ev: InputEvent) -> void:
|
func _on_canvas_input(ev: InputEvent) -> void:
|
||||||
if _map.runner == null or not visible:
|
if _map.runner == null or not visible:
|
||||||
return
|
return
|
||||||
if ev is InputEventMouseMotion:
|
if ev is InputEventMouseButton and ev.pressed and _wheel_pan_step(ev.button_index) != 0.0:
|
||||||
var nid := _candidate_at(ev.position) # gui_input 事件坐标 = 接收控件局部坐标(push_input 同成立)
|
_map.viewport.pan_by(Vector2(_wheel_pan_step(ev.button_index), 0))
|
||||||
if nid != _hover_id:
|
elif ev is InputEventMouseMotion:
|
||||||
_hover_id = nid
|
_on_canvas_motion(ev)
|
||||||
_map.canvas.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND if nid >= 0 else Control.CURSOR_ARROW
|
elif ev is InputEventMouseButton and ev.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
_on_canvas_click(ev)
|
||||||
|
|
||||||
|
|
||||||
|
## 悬停预承诺与拖拽态推进沿(画布局部坐标——gui_input 事件流同源)
|
||||||
|
func _on_canvas_motion(ev: InputEventMouseMotion) -> void:
|
||||||
|
if _drag_active:
|
||||||
|
_map.viewport.pan_by(ev.relative) # 拖拽态逐帧平移(视口件执行 clamp——本屏只判定)
|
||||||
|
return
|
||||||
|
if _drag_press_pos.x >= 0.0 and ev.position.distance_to(_drag_press_pos) >= DRAG_THRESHOLD:
|
||||||
|
_drag_active = true
|
||||||
|
_drag_press_pos = Vector2(-1, -1)
|
||||||
|
if _hover_id != -1: # 进拖拽态清悬停预承诺(拖拽非选路意图)
|
||||||
|
_hover_id = -1
|
||||||
|
_map.canvas.mouse_default_cursor_shape = Control.CURSOR_ARROW
|
||||||
_map.canvas.queue_redraw()
|
_map.canvas.queue_redraw()
|
||||||
elif ev is InputEventMouseButton and ev.button_index == MOUSE_BUTTON_LEFT and ev.pressed:
|
_map.viewport.pan_by(ev.relative) # 跨阈值帧位移计入平移(拖距全长=平移全长)
|
||||||
var nid2 := _candidate_at(ev.position)
|
return
|
||||||
if nid2 >= 0:
|
var nid := _candidate_at(ev.position) # gui_input 事件坐标 = 接收控件局部坐标(push_input 同成立)
|
||||||
_submit_choice(nid2)
|
if nid != _hover_id:
|
||||||
|
_hover_id = nid
|
||||||
|
_map.canvas.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND if nid >= 0 else Control.CURSOR_ARROW
|
||||||
|
_map.canvas.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
|
## 点击沿与拖拽抬杆(未超阈值的完整点击=提交沿——布局决策 2 语义零改动)
|
||||||
|
func _on_canvas_click(ev: InputEventMouseButton) -> void:
|
||||||
|
if ev.pressed:
|
||||||
|
_drag_press_pos = ev.position
|
||||||
|
_drag_active = false
|
||||||
|
return
|
||||||
|
_drag_press_pos = Vector2(-1, -1)
|
||||||
|
if _drag_active:
|
||||||
|
_drag_active = false # 拖拽抬杆=平移结束,不触发选路提交(布局决策 5)
|
||||||
|
return
|
||||||
|
var nid2 := _candidate_at(ev.position)
|
||||||
|
if nid2 >= 0:
|
||||||
|
_submit_choice(nid2)
|
||||||
|
|
||||||
|
|
||||||
|
## 滚轮横滚步进(代拍板:下/右=向右前进向——视线移向深层,画布左移;上/左反向;非滚轮=0)
|
||||||
|
func _wheel_pan_step(button_index: int) -> float:
|
||||||
|
if button_index == MOUSE_BUTTON_WHEEL_DOWN or button_index == MOUSE_BUTTON_WHEEL_RIGHT:
|
||||||
|
return -WHEEL_STEP
|
||||||
|
if button_index == MOUSE_BUTTON_WHEEL_UP or button_index == MOUSE_BUTTON_WHEEL_LEFT:
|
||||||
|
return WHEEL_STEP
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
|
||||||
|
## 拖距跟踪器生命周期清理(按下即武装——鼠标离画布且未入拖拽态时解除,
|
||||||
|
## 防丢失 release 沿后的残留 armed 态把后续 motion 误判成拖拽激活)
|
||||||
|
func _on_canvas_mouse_exited() -> void:
|
||||||
|
if not _drag_active:
|
||||||
|
_drag_press_pos = Vector2(-1, -1)
|
||||||
|
|
||||||
|
|
||||||
# 候选命中:位置 = 布局公式(与 _draw_graph 同源),矩形 = 节点方块 + 外扩容差;非候选格不响应
|
# 候选命中:位置 = 布局公式(与 _draw_graph 同源),矩形 = 节点方块 + 外扩容差;非候选格不响应
|
||||||
@@ -399,18 +465,56 @@ func _submit_choice(nid: int) -> void:
|
|||||||
route_chosen.emit(nid)
|
route_chosen.emit(nid)
|
||||||
|
|
||||||
|
|
||||||
# 探针复用:按候选序号走图上命中同路径(候选节点中心坐标 → 命中检测 → 提交——布局决策 2 探针面改造)
|
# 探针面命中矩形读口:候选节点的图上命中矩形(全局坐标——真输入 push_click_at 落点)。
|
||||||
func press_candidate(index: int) -> void:
|
# 命中面与 _candidate_at 同源(节点方块+外扩容差);index 越界或候选未就绪返回空 Rect2(调用方跳过)。
|
||||||
|
func candidate_rect(index: int) -> Rect2:
|
||||||
if index < 0 or index >= _cand_ids.size() or _map.runner == null:
|
if index < 0 or index >= _cand_ids.size() or _map.runner == null:
|
||||||
return
|
return Rect2()
|
||||||
var nodes: Array[Variant] = _map.runner.nodes()
|
var nodes: Array[Variant] = _map.runner.nodes()
|
||||||
var node := _node_by_id(int(_cand_ids[index]), nodes)
|
var node := _node_by_id(int(_cand_ids[index]), nodes)
|
||||||
if node.is_empty():
|
if node.is_empty():
|
||||||
return
|
return Rect2()
|
||||||
var pos: Vector2 = _layout(nodes, _map.canvas)[node]
|
var pos: Vector2 = _layout(nodes, _map.canvas)[node]
|
||||||
var nid := _candidate_at(pos) # 节点中心必命中自身(命中面含节点方块)
|
var half := NODE_HALF + Vector2(HIT_PAD, HIT_PAD)
|
||||||
if nid >= 0:
|
var local := Rect2(pos - half, half * 2.0)
|
||||||
_submit_choice(nid)
|
var xform := _map.canvas.get_global_transform()
|
||||||
|
return Rect2(xform * local.position, local.size)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 视口锚点(布局决策 5:当前节点居中;入口停点尚无当前节点=锚入口组包围盒居中) ----
|
||||||
|
|
||||||
|
## 锚点画布坐标提供方(构造注入视口件——本屏供数,视口件只消费)
|
||||||
|
func _viewport_anchor() -> Vector2:
|
||||||
|
if _map.runner == null:
|
||||||
|
return _content_size / 2.0
|
||||||
|
var nodes: Array[Variant] = _map.runner.nodes()
|
||||||
|
var pos := _layout(nodes, _map.canvas)
|
||||||
|
var cur_id: int = _map.runner.current_node_id()
|
||||||
|
if cur_id < 0:
|
||||||
|
return _entry_group_center(nodes, pos) # 入口停点(尚未走出第一步)
|
||||||
|
var cur := _node_by_id(cur_id, nodes)
|
||||||
|
if cur.is_empty():
|
||||||
|
return _content_size / 2.0
|
||||||
|
return pos[cur]
|
||||||
|
|
||||||
|
|
||||||
|
func _entry_group_center(nodes: Array, pos: Dictionary) -> Vector2:
|
||||||
|
# 入口组 = 全部无入边节点(与 _assign_layers 入口判据同源);多入口取包围盒居中
|
||||||
|
var inbound := {}
|
||||||
|
for node in nodes:
|
||||||
|
for tid in _out_ids(node, nodes):
|
||||||
|
inbound[tid] = true
|
||||||
|
var lo := Vector2(INF, INF)
|
||||||
|
var hi := Vector2(-INF, -INF)
|
||||||
|
for node in nodes:
|
||||||
|
if inbound.has(_id_of(node)):
|
||||||
|
continue
|
||||||
|
var p: Vector2 = pos[node]
|
||||||
|
lo = lo.min(p)
|
||||||
|
hi = hi.max(p)
|
||||||
|
if lo.x > hi.x:
|
||||||
|
return _content_size / 2.0 # 空图兜底(无入口——不达路径,防御位)
|
||||||
|
return (lo + hi) / 2.0
|
||||||
|
|
||||||
|
|
||||||
func _id_of(node: Dictionary) -> int:
|
func _id_of(node: Dictionary) -> int:
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
## 卷轴视口承载件(level-map.md 布局决策 5——关卡画面选路屏):画布宿主与裁切、平移状态
|
||||||
|
## 与 clamp、锚点跟随与平滑滚动、指引件(屏缘渐隐带+平移提示 chip)。
|
||||||
|
## 纯呈现态:平移位置零核心写、不进存档(重进本屏按锚点规则重新定位);跟随只随停点切换/
|
||||||
|
## 兑付回图发生(零自动推进)。拖拽/滚轮判定留画布 _gui_input(事件流同源——悬停/选路同源),
|
||||||
|
## 本件只管裁切/offset/clamp/跟随/指引;画布包络=画布实际尺寸(open_choices 拟合后同帧收敛)。
|
||||||
|
class_name LevelMapViewport
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
const SCROLL_DUR := 0.3 # 平滑滚动时长(布局决策 5 provisional 0.3s 单段缓动)
|
||||||
|
const FADE_BAND_W := 70.0 # 屏缘渐隐带宽(布局决策 5/像素级判据②)
|
||||||
|
const CHIP_SIZE := Vector2(240, 30) # 平移提示 chip(像素级判据③——图区底部居中)
|
||||||
|
const CHIP_CORNER := 6 # chip 圆角(布局决策 5)
|
||||||
|
const CHIP_BOTTOM_GAP := 24.0 # chip 距视口底缘(效果图档同族取值)
|
||||||
|
const CHIP_TEXT := "◄ 拖拽画布 / 滚轮平移 ►" # 14px(FS_HINT 档——布局决策 5)
|
||||||
|
const EDGE_EPS := 0.5 # 包络边界判定容差(浮点平移累积)
|
||||||
|
|
||||||
|
var _canvas: Control
|
||||||
|
var _anchor_provider: Callable # () -> Vector2 锚点画布坐标(screen 提供——当前节点/入口组)
|
||||||
|
var _viewport_size := Vector2.ZERO # 窗口尺寸兜底(setup 注入设计基座——实况窗口以控件 size 为准,布局晚于构造)
|
||||||
|
var _offset := Vector2.ZERO: # 画布左上角在视口件坐标系的位置(纯呈现态——直驱画布 position)
|
||||||
|
set(value):
|
||||||
|
_offset = value
|
||||||
|
if _canvas != null:
|
||||||
|
_canvas.position = _offset
|
||||||
|
var _view_tween: Tween
|
||||||
|
var _guided_visible := false # 指引件可见态(画布超窗才暗示——浅图无平移余量即隐藏)
|
||||||
|
|
||||||
|
|
||||||
|
## 一次交齐注入(code-conventions §1.6 拆分交接:画布宿主、锚点来源、窗口兜底尺寸)
|
||||||
|
func setup(canvas: Control, anchor_provider: Callable, viewport_size: Vector2) -> void:
|
||||||
|
_canvas = canvas
|
||||||
|
_anchor_provider = anchor_provider
|
||||||
|
_viewport_size = viewport_size
|
||||||
|
clip_contents = true
|
||||||
|
add_child(canvas)
|
||||||
|
_build_guidance()
|
||||||
|
|
||||||
|
|
||||||
|
func _notification(what: int) -> void:
|
||||||
|
# 窗口实况尺寸落定/变化即重锚(首开布局晚于 open_choices 的锚定——隐藏子树容器排序
|
||||||
|
# 首个可见帧才传播,4.7 行为;实况窗口以本件 size 为准,落定即收敛锚点)
|
||||||
|
if what == NOTIFICATION_RESIZED and _canvas != null and _anchor_provider.is_valid():
|
||||||
|
reanchor(false)
|
||||||
|
|
||||||
|
|
||||||
|
## 锚点跟随(布局决策 5:锚点居中;smooth=停点切换/兑付回图平滑滚动,减动效开=跳终态;
|
||||||
|
## 重入先杀在飞 tween 再建新——快速连续停点切换防叠加)
|
||||||
|
func reanchor(smooth: bool) -> void:
|
||||||
|
if _canvas == null or not _anchor_provider.is_valid():
|
||||||
|
return
|
||||||
|
var target := _clamped_center_offset(_anchor_provider.call())
|
||||||
|
_kill_scroll_tween()
|
||||||
|
if not smooth or ArmedTimer.motion_still():
|
||||||
|
_offset = target
|
||||||
|
_sync_guidance()
|
||||||
|
return
|
||||||
|
_view_tween = create_tween()
|
||||||
|
_view_tween.tween_property(self, "_offset", target, UiKit.motion(SCROLL_DUR)) \
|
||||||
|
.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
|
||||||
|
_sync_guidance()
|
||||||
|
|
||||||
|
|
||||||
|
## 手动平移(画布 _gui_input 判定后调用——拖拽沿逐帧/滚轮步进;纯呈现零核心写)
|
||||||
|
func pan_by(delta: Vector2) -> void:
|
||||||
|
if _canvas == null:
|
||||||
|
return
|
||||||
|
_kill_scroll_tween()
|
||||||
|
var win := _window_size()
|
||||||
|
_offset = Vector2(
|
||||||
|
_axis_pan_offset(_offset.x, delta.x, _canvas.size.x, win.x),
|
||||||
|
_axis_pan_offset(_offset.y, delta.y, _canvas.size.y, win.y))
|
||||||
|
_sync_guidance()
|
||||||
|
|
||||||
|
|
||||||
|
## 视口中线的画布坐标(锚点居中判据投影面——浅图=画布中心,深图=夹紧域内当前注视点)
|
||||||
|
func viewport_center_canvas_pos() -> Vector2:
|
||||||
|
return _window_size() / 2.0 - _offset
|
||||||
|
|
||||||
|
|
||||||
|
## 视口是否钉在画布包络边界(任一超窗轴 offset 顶边——clamp 判据面)
|
||||||
|
func is_clamped_at_edge() -> bool:
|
||||||
|
var win := _window_size()
|
||||||
|
if _canvas == null:
|
||||||
|
return false
|
||||||
|
return _axis_at_edge(_offset.x, _canvas.size.x, win.x) \
|
||||||
|
or _axis_at_edge(_offset.y, _canvas.size.y, win.y)
|
||||||
|
|
||||||
|
|
||||||
|
func _kill_scroll_tween() -> void:
|
||||||
|
if _view_tween != null and _view_tween.is_valid():
|
||||||
|
_view_tween.kill()
|
||||||
|
_view_tween = null
|
||||||
|
|
||||||
|
|
||||||
|
## 单轴锚定 offset:画布不超窗=居中分支(夹紧域退化——布局决策 5);
|
||||||
|
## 超窗=锚点夹紧在画布包络内,锚点落视口中线(offset = 半窗 − 锚点)
|
||||||
|
func _axis_center_offset(anchor: float, canvas_len: float, half_win: float) -> float:
|
||||||
|
if canvas_len <= half_win * 2.0:
|
||||||
|
return half_win - canvas_len / 2.0
|
||||||
|
return half_win - clampf(anchor, half_win, canvas_len - half_win)
|
||||||
|
|
||||||
|
|
||||||
|
func _clamped_center_offset(anchor: Vector2) -> Vector2:
|
||||||
|
var half := _window_size() / 2.0
|
||||||
|
return Vector2(
|
||||||
|
_axis_center_offset(anchor.x, _canvas.size.x, half.x),
|
||||||
|
_axis_center_offset(anchor.y, _canvas.size.y, half.y))
|
||||||
|
|
||||||
|
|
||||||
|
## 单轴平移收敛:居中轴零平移余量不动;超窗轴 offset 收敛在 [半窗−画布, 0](不出露屏底空档)
|
||||||
|
func _axis_pan_offset(cur: float, delta: float, canvas_len: float, win_len: float) -> float:
|
||||||
|
if canvas_len <= win_len:
|
||||||
|
return cur
|
||||||
|
return clampf(cur + delta, win_len - canvas_len, 0.0)
|
||||||
|
|
||||||
|
|
||||||
|
func _axis_at_edge(offset: float, canvas_len: float, win_len: float) -> bool:
|
||||||
|
if canvas_len <= win_len:
|
||||||
|
return false
|
||||||
|
return offset >= -EDGE_EPS or offset <= win_len - canvas_len + EDGE_EPS
|
||||||
|
|
||||||
|
|
||||||
|
## 实况窗口优先(容器布局晚于构造——注入值只兜构造帧数学)
|
||||||
|
func _window_size() -> Vector2:
|
||||||
|
if size.x > 0.0 and size.y > 0.0:
|
||||||
|
return size
|
||||||
|
return _viewport_size
|
||||||
|
|
||||||
|
|
||||||
|
## 指引件(布局决策 5/像素级判据②③):屏缘渐隐带盖在画布之上+图区底部居中提示 chip;
|
||||||
|
## 可见性=画布超窗(_sync_guidance 随锚定/平移刷新)
|
||||||
|
func _build_guidance() -> void:
|
||||||
|
var band_l := TextureRect.new()
|
||||||
|
band_l.name = "FadeL"
|
||||||
|
band_l.texture = _fade_gradient(false)
|
||||||
|
band_l.set_anchors_preset(Control.PRESET_LEFT_WIDE)
|
||||||
|
band_l.offset_right = FADE_BAND_W
|
||||||
|
band_l.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||||
|
band_l.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
add_child(band_l)
|
||||||
|
var band_r := TextureRect.new()
|
||||||
|
band_r.name = "FadeR"
|
||||||
|
band_r.texture = _fade_gradient(true)
|
||||||
|
band_r.set_anchors_preset(Control.PRESET_RIGHT_WIDE)
|
||||||
|
band_r.offset_left = -FADE_BAND_W
|
||||||
|
band_r.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||||
|
band_r.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
add_child(band_r)
|
||||||
|
var chip := PanelContainer.new()
|
||||||
|
chip.name = "PanHint"
|
||||||
|
chip.add_theme_stylebox_override("panel",
|
||||||
|
UiKit.panel_flat(UiKit.HP_BAR_BACK, UiKit.STONE, CHIP_CORNER, 1, Vector4(12, 5, 12, 5)))
|
||||||
|
chip.set_anchors_preset(Control.PRESET_CENTER_BOTTOM)
|
||||||
|
chip.offset_left = -CHIP_SIZE.x / 2.0
|
||||||
|
chip.offset_right = CHIP_SIZE.x / 2.0
|
||||||
|
chip.offset_top = -CHIP_SIZE.y - CHIP_BOTTOM_GAP
|
||||||
|
chip.offset_bottom = -CHIP_BOTTOM_GAP
|
||||||
|
chip.custom_minimum_size = CHIP_SIZE
|
||||||
|
chip.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
var chip_label := UiKit.label(CHIP_TEXT, UiKit.FS_HINT, false, UiKit.WARM)
|
||||||
|
chip_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
chip_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
chip.add_child(chip_label)
|
||||||
|
add_child(chip)
|
||||||
|
_sync_guidance()
|
||||||
|
|
||||||
|
|
||||||
|
## 屏缘渐隐渐变(色取屏底同族 BG_ROOT——代拍板:不透明端 0.9 单段衰减)
|
||||||
|
func _fade_gradient(transparent_at_left: bool) -> GradientTexture2D:
|
||||||
|
var grad := Gradient.new()
|
||||||
|
grad.offsets = PackedFloat32Array([0.0, 1.0])
|
||||||
|
grad.colors = PackedColorArray([Color(UiKit.BG_ROOT, 0.9), Color(UiKit.BG_ROOT, 0.0)])
|
||||||
|
var tex := GradientTexture2D.new()
|
||||||
|
tex.gradient = grad
|
||||||
|
tex.fill_from = Vector2(1, 0.5) if transparent_at_left else Vector2(0, 0.5)
|
||||||
|
tex.fill_to = Vector2(0, 0.5) if transparent_at_left else Vector2(1, 0.5)
|
||||||
|
tex.width = int(FADE_BAND_W)
|
||||||
|
return tex
|
||||||
|
|
||||||
|
|
||||||
|
func _sync_guidance() -> void:
|
||||||
|
var win := _window_size()
|
||||||
|
var over := _canvas != null and (_canvas.size.x > win.x or _canvas.size.y > win.y)
|
||||||
|
if over == _guided_visible:
|
||||||
|
return
|
||||||
|
_guided_visible = over
|
||||||
|
for nm in ["FadeL", "FadeR", "PanHint"]:
|
||||||
|
var node := get_node_or_null(NodePath(nm)) as Control
|
||||||
|
if node != null:
|
||||||
|
node.visible = over
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dgin6f6214cbg
|
||||||
@@ -29,10 +29,6 @@ func show_rest(healed: int, hp_after: int, max_hp: int) -> void:
|
|||||||
_btn.text = "休息完毕,继续"
|
_btn.text = "休息完毕,继续"
|
||||||
visible = true
|
visible = true
|
||||||
|
|
||||||
# 探针复用:以真实按钮路径触发继续
|
|
||||||
func press_continue() -> void:
|
|
||||||
_btn.pressed.emit()
|
|
||||||
|
|
||||||
|
|
||||||
func _emit_continue_pressed() -> void:
|
func _emit_continue_pressed() -> void:
|
||||||
continue_pressed.emit()
|
continue_pressed.emit()
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// 封印印记(卡④ 法阵化批)——环+十字+环外压暗光圈,canvas_item 距离场实时绘制(无贴图缩放,
|
// 封印印记(卡④ 法阵化批)——环+十字+环外压暗光圈,canvas_item 距离场实时绘制(无贴图缩放,
|
||||||
// 格边 26–46px 连续可变下任意格边清晰)。
|
// 格边 26–46px 连续可变下任意格边清晰)。
|
||||||
// 事实源:art-bible v3.41 §3.2「封印印记」(形/画法/光圈/层序纪律)+ §8.2「封印印记参数表」;
|
// 事实源:art-bible v3.41 §3.2「封印印记」(形/画法/光圈/层序纪律)+ §8.2「封印印记参数表」;
|
||||||
// gdd/ux/battle.md「棋盘格尺寸公式」(格边 clampi 26–46)。
|
// design/ux/battle.md「棋盘格尺寸公式」(格边 clampi 26–46)。
|
||||||
// 纪律:参数五枚+色全由 gd 侧逐次注入(参数单点 = ui_kit SEAL_* 五常量——禁在此改值,
|
// 纪律:参数五枚+色全由 gd 侧逐次注入(参数单点 = ui_kit SEAL_* 五常量——禁在此改值,
|
||||||
// 下方默认值仅为兜底且与 §8.2 同值);光圈不出格(半径夹 cell_px/2);
|
// 下方默认值仅为兜底且与 §8.2 同值);光圈不出格(半径夹 cell_px/2);
|
||||||
// 零动效(不呼吸不脉冲——§2.1 挖掘期唯一在动 = 接触带微光);印记与光圈同用一色(光圈只改 alpha)。
|
// 零动效(不呼吸不脉冲——§2.1 挖掘期唯一在动 = 接触带微光);印记与光圈同用一色(光圈只改 alpha)。
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ const TIP_BG := Color(0.16, 0.12, 0.09, 0.96) # tooltip 深底
|
|||||||
const STAND_STONE := Color8(150, 130, 100) # 站桩石板地台·板身(standee_body 方向稿取色)
|
const STAND_STONE := Color8(150, 130, 100) # 站桩石板地台·板身(standee_body 方向稿取色)
|
||||||
const PLAZA_EDGE := Color8(76, 64, 56) # 小石台描边(art-bible §4.1 换色合并②合并目标——贴图已落此值,缺位回退同值)
|
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_HEADER_BAND := Color8(110, 69, 38) # 营地柜台头带深棕 #6E4526(4-camp.png 方向稿取色;对齐 demo --wood-deep)
|
||||||
|
const CAMP_HUD_BAND := Color(CAMP_HEADER_BAND, 0.80) # 营地顶栏栏体=头带深棕×α0.80(camp.md §顶栏定值——派生收口单点,非色板新增;同文件 TOAST_BG/TIP_BG 带 α 先例)
|
||||||
const CAMP_ROW_PLATE := Color8(240, 230, 206) # 营地行板暖米(同上)
|
const CAMP_ROW_PLATE := Color8(240, 230, 206) # 营地行板暖米(同上)
|
||||||
const CAMP_BADGE_PANEL := Color8(40, 32, 24) # 营地钥石徽暗底(同上)
|
const CAMP_BADGE_PANEL := Color8(40, 32, 24) # 营地钥石徽暗底(同上)
|
||||||
const HP_BAR_BACK := Color8(40, 34, 32) # 迷你血条深底 #282220(兼血数垫牌;站桩名字行素底同源——§6.1/§7.2 文字禁压地台)
|
const HP_BAR_BACK := Color8(40, 34, 32) # 迷你血条深底 #282220(兼血数垫牌;站桩名字行素底同源——§6.1/§7.2 文字禁压地台)
|
||||||
@@ -656,6 +657,19 @@ static func keystone_badge(text: String, icon_path := TEX_ICON_KEYSTONE, icon_px
|
|||||||
return KeystoneBadge.new(text, icon_path, icon_px)
|
return KeystoneBadge.new(text, icon_path, icon_px)
|
||||||
|
|
||||||
|
|
||||||
|
## 营地顶栏栏体面(整件外观单一出口——营地交互修复批契约 4/5):色值与 α、铺满、不吃点击、
|
||||||
|
## 挂上宿主五件事全写死在体内;形参只有 host——调用方没有可以忘记的形参。返回句柄供调用方
|
||||||
|
## 读取与断言;徽章摆位不由本出口负责(归顶栏件内右对齐容器)。须在宿主入树前调用
|
||||||
|
## (set_anchors_preset 是入树前动作——_modal_dim/overlay_bg 同形)。
|
||||||
|
static func camp_hud_band_surface(host: Control) -> ColorRect:
|
||||||
|
var rect := ColorRect.new()
|
||||||
|
rect.color = CAMP_HUD_BAND
|
||||||
|
rect.set_anchors_preset(Control.PRESET_FULL_RECT) # 四边 offset 归零铺满宿主
|
||||||
|
rect.mouse_filter = Control.MOUSE_FILTER_IGNORE # 栏体不吃点击(顶排物件命中区不受阻——契约 5)
|
||||||
|
host.add_child(rect)
|
||||||
|
return rect
|
||||||
|
|
||||||
|
|
||||||
# 按钮皮·五态矩阵(逐实例 override 不动主题层)
|
# 按钮皮·五态矩阵(逐实例 override 不动主题层)
|
||||||
# 悬停:常态图+modulate 提亮(0.06 档与 primary_button 现行 lightened(0.06) 同纪律,零新素材);
|
# 悬停:常态图+modulate 提亮(0.06 档与 primary_button 现行 lightened(0.06) 同纪律,零新素材);
|
||||||
# 禁用:本族底+α0.45 幽灵化(与 font_disabled_color 同纪律);
|
# 禁用:本族底+α0.45 幽灵化(与 font_disabled_color 同纪律);
|
||||||
|
|||||||
@@ -23,9 +23,77 @@ var _level_readings := {} # 关 → 双帧比对读数(实现报告读数表
|
|||||||
var _cur_settlement = null # 当关 settlement(身份回调读取面——仿生产 run_scope.settlement 现值;
|
var _cur_settlement = null # 当关 settlement(身份回调读取面——仿生产 run_scope.settlement 现值;
|
||||||
# 不用 Callable.bind 传参:bind 的 Callable 动态派发时对类型化参数做 Object 硬校验,
|
# 不用 Callable.bind 传参:bind 的 Callable 动态派发时对类型化参数做 Object 硬校验,
|
||||||
# 报「Cannot convert argument 2 from Object to Vector2i」——直接方法引用+成员现值无此坑)
|
# 报「Cannot convert argument 2 from Object to Vector2i」——直接方法引用+成员现值无此坑)
|
||||||
|
var _cur_mark_counts := {} # 当关 cell_mark_overlay 绘制域逐类型格计数(注入后读数——V14 采集态核对)
|
||||||
|
|
||||||
|
|
||||||
|
func _probe_settlement_getter():
|
||||||
|
return _cur_settlement
|
||||||
|
|
||||||
|
|
||||||
|
# 绘制域缺型注入(确定性直构——每关固定选格,同种子同态可复现):
|
||||||
|
# 真视框=首个未开未封印危险格;预读徽章=身份查询命中的未开格(循环挑到命中,全空记零);
|
||||||
|
# 移除退色=remove_mines_in 真实写口移除一个未揭示危险格;点迹/高亮=英雄格 face 直设定格。
|
||||||
|
func _mark_domain_inject(view: Node, settlement: Object) -> void:
|
||||||
|
var ms = settlement.minesweeper
|
||||||
|
var board = ms.current_board()
|
||||||
|
var reveal_cell := Vector2i(-9, -9)
|
||||||
|
var preview_cell := Vector2i(-9, -9)
|
||||||
|
var remove_cell := Vector2i(-9, -9)
|
||||||
|
for y in board.height:
|
||||||
|
for x in board.width:
|
||||||
|
var c := Vector2i(x, y)
|
||||||
|
if ms.is_revealed(c) or ms.has_seal(c) or ms.is_removed(c):
|
||||||
|
continue
|
||||||
|
if board.is_mine(c):
|
||||||
|
if reveal_cell.x < 0:
|
||||||
|
reveal_cell = c
|
||||||
|
if remove_cell.x < 0:
|
||||||
|
remove_cell = c
|
||||||
|
elif preview_cell.x < 0 and _probe_identity_lookup(c) != null:
|
||||||
|
preview_cell = c
|
||||||
|
if remove_cell.x >= 0:
|
||||||
|
ms.remove_mines_in([remove_cell])
|
||||||
|
view.set_treasure_overlays([reveal_cell] if reveal_cell.x >= 0 else [],
|
||||||
|
[preview_cell] if preview_cell.x >= 0 else [])
|
||||||
|
view.refresh()
|
||||||
|
var hero: Vector2i = ms.hero_pos()
|
||||||
|
var cells: Dictionary = view.cells_probe()
|
||||||
|
if cells.has(hero):
|
||||||
|
(cells[hero] as Node2D).face.dot_visible = true
|
||||||
|
var nb: Vector2i = hero + Vector2i(1, 0)
|
||||||
|
if not cells.has(nb):
|
||||||
|
nb = hero + Vector2i(0, 1)
|
||||||
|
if cells.has(nb):
|
||||||
|
(cells[nb] as Node2D).face.hl_visible = true
|
||||||
|
_cur_mark_counts = {"injected": {"reveal": str(reveal_cell), "preview": str(preview_cell),
|
||||||
|
"remove": str(remove_cell), "dot": str(hero)}}
|
||||||
|
|
||||||
|
|
||||||
|
# 逐类型格计数读数(off 帧呈现态——face 现值直读,CellUnit 在册探针读口同面)
|
||||||
|
func _mark_domain_counts(view: Node, tag: String) -> Dictionary:
|
||||||
|
var counts := {"mutation_mark": 0, "treasure_mark": 0, "badge_glyph": 0,
|
||||||
|
"dot_visible": 0, "hl_visible": 0, "removed_dim": 0}
|
||||||
|
var cells: Dictionary = view.cells_probe()
|
||||||
|
for c in cells:
|
||||||
|
var f = (cells[c] as Node2D).face
|
||||||
|
if String(f.mutation_mark) != "":
|
||||||
|
counts["mutation_mark"] = int(counts["mutation_mark"]) + 1
|
||||||
|
if String(f.treasure_mark) != "":
|
||||||
|
counts["treasure_mark"] = int(counts["treasure_mark"]) + 1
|
||||||
|
if String(f.badge_glyph) != "":
|
||||||
|
counts["badge_glyph"] = int(counts["badge_glyph"]) + 1
|
||||||
|
if bool(f.dot_visible):
|
||||||
|
counts["dot_visible"] = int(counts["dot_visible"]) + 1
|
||||||
|
if bool(f.hl_visible):
|
||||||
|
counts["hl_visible"] = int(counts["hl_visible"]) + 1
|
||||||
|
if bool(f.removed_dim):
|
||||||
|
counts["removed_dim"] = int(counts["removed_dim"]) + 1
|
||||||
|
print("[board_shot] mark_domain %s: %s" % [tag, counts])
|
||||||
|
return counts
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
# 判据出处: design/engineering/test-conventions.md:84 (棋盘截图取证——渲染闸采集组)
|
||||||
# 运行前提=窗口化真渲染面(shot_probe 同款护栏——headless 下 frame_post_draw 永不触发+视口纹理恒空)
|
# 运行前提=窗口化真渲染面(shot_probe 同款护栏——headless 下 frame_post_draw 永不触发+视口纹理恒空)
|
||||||
if DisplayServer.get_name() == "headless":
|
if DisplayServer.get_name() == "headless":
|
||||||
print("[board_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);现行事实源=tools/render_gate.sh 取证段")
|
print("[board_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);现行事实源=tools/render_gate.sh 取证段")
|
||||||
@@ -74,7 +142,7 @@ func _ready() -> void:
|
|||||||
# 全拒则免邻接旗标+任意未开格重试,AP 不足先 grant_ap 兜底;拒绝全数=取证段红)----
|
# 全拒则免邻接旗标+任意未开格重试,AP 不足先 grant_ap 兜底;拒绝全数=取证段红)----
|
||||||
var seal_cell := Vector2i(-9, -9)
|
var seal_cell := Vector2i(-9, -9)
|
||||||
for c in settlement.minesweeper.current_board().safe_cells():
|
for c in settlement.minesweeper.current_board().safe_cells():
|
||||||
if settlement.minesweeper.has_seal(c) and not settlement.minesweeper.is_revealed(c):
|
if settlement.minesweeper.has_seal(c): # 取证选择器换代〔封印改 V8〕——印记可见性不依赖揭示态(受理即揭示)
|
||||||
seal_cell = c
|
seal_cell = c
|
||||||
break
|
break
|
||||||
if seal_cell.x < 0:
|
if seal_cell.x < 0:
|
||||||
@@ -119,7 +187,17 @@ func _ready() -> void:
|
|||||||
# 双帧比对空转、PASS 假绿)。现值经 _cur_settlement 成员读入
|
# 双帧比对空转、PASS 假绿)。现值经 _cur_settlement 成员读入
|
||||||
# (仿生产 run_scope.settlement;bind 传参有 Callable 类型校验坑,见成员注)。
|
# (仿生产 run_scope.settlement;bind 传参有 Callable 类型校验坑,见成员注)。
|
||||||
view.set_identity_resolver(_probe_identity_lookup)
|
view.set_identity_resolver(_probe_identity_lookup)
|
||||||
|
# 变异角标 resolver(生产同源——main_ui_build:262 set_variant_mark_resolver 接线同款):
|
||||||
|
# 裸视图不接 = mutation_mark 恒空 = L3 伤害型变异角标缺帧。rebuild 前接(paint 链读回调)。
|
||||||
|
var resolvers = load("res://presentation/board_resolvers.gd").new(db, null, _probe_settlement_getter)
|
||||||
|
view.set_variant_mark_resolver(resolvers.variant_mark_lookup)
|
||||||
view.rebuild(settlement.minesweeper.current_board(), settlement.minesweeper)
|
view.rebuild(settlement.minesweeper.current_board(), settlement.minesweeper)
|
||||||
|
# ---- cell_mark_overlay 绘制域采集态注入(卡修轮 2 V14——确定性直构,缺型补进采集态)----
|
||||||
|
# 五类型注入全走真链/生产同源:真视框与预读徽章=set_treasure_overlays(生产呈现链);
|
||||||
|
# 移除退色=remove_mines_in(核心真实写口——移除集=未揭示无封印是雷,判定基线零回溯);
|
||||||
|
# 点迹/高亮=u.face 直设(CellUnit 探针读口同面的写侧,交互瞬态的定格化)。
|
||||||
|
_mark_domain_inject(view, settlement)
|
||||||
|
var mark_counts := _mark_domain_counts(view, tag)
|
||||||
# 进挖掘相位(生产态 = hud_presenter.set_dig_glow_enabled(not settling) 接线——裸视图默认
|
# 进挖掘相位(生产态 = hud_presenter.set_dig_glow_enabled(not settling) 接线——裸视图默认
|
||||||
# _dig_glow=false,接触带与类型微光同源门控都不渲染;golden 基线即捕获于
|
# _dig_glow=false,接触带与类型微光同源门控都不渲染;golden 基线即捕获于
|
||||||
# 该裸态。双帧取证要求生产默认态,故显式开——两帧均含静态接触带(motion_scale=0.5 停格),
|
# 该裸态。双帧取证要求生产默认态,故显式开——两帧均含静态接触带(motion_scale=0.5 停格),
|
||||||
@@ -181,6 +259,7 @@ func _ready() -> void:
|
|||||||
# 判据:环外径像素 ÷ 格边 落 0.82±1px;封印格最外圈 1px 框最暗值与相邻未封印未开格同位框最暗值差 ≤1/255
|
# 判据:环外径像素 ÷ 格边 落 0.82±1px;封印格最外圈 1px 框最暗值与相邻未封印未开格同位框最暗值差 ≤1/255
|
||||||
#(halo 在 0.455×格边归零——格边框不应被压暗;相邻未开格同砖纹理同套瓦片为无封印参照)。
|
#(halo 在 0.455×格边归零——格边框不应被压暗;相邻未开格同砖纹理同套瓦片为无封印参照)。
|
||||||
func _seal_evidence(tag: String, view: Node, settlement: Object, off_img: Image, out: String) -> void:
|
func _seal_evidence(tag: String, view: Node, settlement: Object, off_img: Image, out: String) -> void:
|
||||||
|
# 判据出处: design/engineering/test-conventions.md:84 (封印印记像素取证组)
|
||||||
var ms = settlement.minesweeper
|
var ms = settlement.minesweeper
|
||||||
var seal_cell := Vector2i(-9, -9)
|
var seal_cell := Vector2i(-9, -9)
|
||||||
var ref_cell := Vector2i(-9, -9)
|
var ref_cell := Vector2i(-9, -9)
|
||||||
@@ -288,6 +367,7 @@ func _probe_identity_lookup(c: Vector2i):
|
|||||||
# 双帧逐像素比对:所有变化像素必须落在生效格的内缘带内
|
# 双帧逐像素比对:所有变化像素必须落在生效格的内缘带内
|
||||||
# (de < cell÷8——带外含砖心零侵入=禁整格染色/禁越圈);每个生效格须有实绘像素(不空转)。
|
# (de < cell÷8——带外含砖心零侵入=禁整格染色/禁越圈);每个生效格须有实绘像素(不空转)。
|
||||||
func _check_dual_frames(tag: String, view, glow_cells: Dictionary, off_img: Image, on_img: Image) -> void:
|
func _check_dual_frames(tag: String, view, glow_cells: Dictionary, off_img: Image, on_img: Image) -> void:
|
||||||
|
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
|
||||||
var board = view.board()
|
var board = view.board()
|
||||||
if board == null:
|
if board == null:
|
||||||
_problems.append("%s 双帧比对取板失败(view.board() 为 null)" % tag)
|
_problems.append("%s 双帧比对取板失败(view.board() 为 null)" % tag)
|
||||||
@@ -339,7 +419,8 @@ func _check_dual_frames(tag: String, view, glow_cells: Dictionary, off_img: Imag
|
|||||||
if first_outside == "":
|
if first_outside == "":
|
||||||
first_outside = "%s 非生效格" % str(c2)
|
first_outside = "%s 非生效格" % str(c2)
|
||||||
_level_readings[tag] = {"glow_cells": glow_cells.size(), "changed_total": changed_total,
|
_level_readings[tag] = {"glow_cells": glow_cells.size(), "changed_total": changed_total,
|
||||||
"changed_outside": changed_outside, "band_px": band_px}
|
"changed_outside": changed_outside, "band_px": band_px,
|
||||||
|
"mark_domain": _cur_mark_counts}
|
||||||
print("[board_shot] %s 双帧读数 glow=%d changed=%d outside=%d band=%.0fpx"
|
print("[board_shot] %s 双帧读数 glow=%d changed=%d outside=%d band=%.0fpx"
|
||||||
% [tag, glow_cells.size(), changed_total, changed_outside, band_px])
|
% [tag, glow_cells.size(), changed_total, changed_outside, band_px])
|
||||||
if changed_outside != 0:
|
if changed_outside != 0:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ extends Node
|
|||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
# 判据出处: design/gdd/systems/战斗循环/战斗表现.md:148 (结算演出——挖掘期零打扰组)
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
var problems: Array = []
|
var problems: Array = []
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ var _problems: Array = []
|
|||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
# 判据出处: design/engineering/test-conventions.md:84 (特效截图取证——渲染闸采集组)
|
||||||
var args := OS.get_cmdline_user_args()
|
var args := OS.get_cmdline_user_args()
|
||||||
out_dir = args[0] if args.size() >= 1 and args[0] != "" else "user://qa-fx"
|
out_dir = args[0] if args.size() >= 1 and args[0] != "" else "user://qa-fx"
|
||||||
DirAccess.make_dir_recursive_absolute(out_dir)
|
DirAccess.make_dir_recursive_absolute(out_dir)
|
||||||
@@ -44,7 +45,7 @@ func _ready() -> void:
|
|||||||
return
|
return
|
||||||
for i in 5:
|
for i in 5:
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
main.ui.modals.run.level_screen.press_candidate(0)
|
ProbeUiUtil.push_click_at(main, main.ui.modals.run.level_screen.candidate_rect(0).get_center())
|
||||||
for i in 20:
|
for i in 20:
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
var st = main.run_scope.settlement
|
var st = main.run_scope.settlement
|
||||||
@@ -107,6 +108,7 @@ func _ready() -> void:
|
|||||||
|
|
||||||
|
|
||||||
func _snap(tag: String) -> void:
|
func _snap(tag: String) -> void:
|
||||||
|
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
|
||||||
await RenderingServer.frame_post_draw
|
await RenderingServer.frame_post_draw
|
||||||
var img: Image = get_viewport().get_texture().get_image()
|
var img: Image = get_viewport().get_texture().get_image()
|
||||||
if img == null or img.is_empty():
|
if img == null or img.is_empty():
|
||||||
@@ -116,6 +118,7 @@ func _snap(tag: String) -> void:
|
|||||||
|
|
||||||
|
|
||||||
func _fail(msg: String) -> void:
|
func _fail(msg: String) -> void:
|
||||||
|
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
|
||||||
_problems.append(msg)
|
_problems.append(msg)
|
||||||
push_error("[fx_shot_probe] FAIL — " + msg)
|
push_error("[fx_shot_probe] FAIL — " + msg)
|
||||||
get_tree().quit(1)
|
get_tree().quit(1)
|
||||||
Loaded 100 of 289 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user