merge: 并入 master 推进 80 提交(06-待办清单冲突解一处——master「优先级再降+playnote 立绘批评」注记与本批「方案二收口」注记并存,并指明 playnote 两条批评已由本批承接兑现)

This commit is contained in:
DKChan committed 2026-10-07 02:02:37 +08:00
commit 5953af3580
116 files changed
+4156 -1038

No files matched your search

+25
View File
@@ -64,6 +64,31 @@
3. **豁免面(仅这两处允许主工作区直改)**:根目录 `active.md`(会话收口)与 `.zcode/`(钩子配置)——其余一律走 worktree;主工作区 `git commit` 会被钩子直接拦截
4. 本铁律由 PreToolUse 钩子 `.zcode/hooks/worktree-guard.sh` 强制兜底;钩子只约束 agent 侧,用户本人手工改动不受限
## 批次工作流标准清单(2026-10-06 用户确认固化)
每个开发/设计批次按以下十三条链路执行。本清单是总索引,各步细则散见上文各节与 `design/dev/` 子文档;与任一细则冲突时以细则为准,发现清单本身过时须同批修订。
**开工前**
1. **先检索后提问**——动手前先查在册记忆与正主文档,防止把已裁决事项当新问题重问,或重踩已记录的坑
2. **任务书全列备选案**——批任务书里每个待拍板点列出全部备选方案与各自代价,交用户裁决,不在任务书内自行定夺
3. **用户发开工令才动手**——任务书经用户批准(U0)后方开工
**环境与基线**
4. **独立 worktree + 拷导入缓存**——按分支纪律建 worktree;新 worktree 先拷主区 `.godot/` 目录与字体 `.import` 边车文件再跑测试,否则每套测试全量重新导入资源、近似卡死
5. **改码前定基线三查**——记录改动前的冒烟全绿数目、单元测试套数、现行模拟基线读数是哪份;改完用同一口径对拍,红绿才能归因到本批改动
6. **涉数值改动先采改前读数**——批次要改游戏数值的,改码前先采「改前」模拟读数(与改后同随机种子配对比较),并写明对拍口径;无数值改动禁跑模拟(触发细则见硬性红线)
**实施**
7. **新功能必配新测试**——按任务书卡片写码,新增玩法/机制必须配套新增测试套件进 `tests/run_all`;没有对应测试的变更不许合并
8. **验收改动先行声明**——逻辑变更对应的验收变化(模拟基线换代、探针用例增改、旧断言改判)在任务书里预先写明,不事后补
**收口**
9. **批末四闸全绿才合并**——冒烟 + 单元测试 + 场景探针 + 改前改后读数对拍,四项全绿方可在主工作区合并
10. **合并后主区全量复跑**——合并本身可能引入冲突或环境差异,落回 master 后再跑一遍全套验证
11. **会话收口落记**——`active.md` 快照与工作日志更新;跨会话有效的教训写入记忆库
12. **实机目检归用户**——真机人闸由用户执行,用户亲口确认才算验收通过
13. **中间产物吸收即死**——结论先迁入正主文档(GDD/待办清单/路线图),中间文件即删且永不提交(细则见硬性红线)
## 硬性红线(勿违反)
- **worktree 铁律**:主工作区禁止直接改动与提交(细则见上节;并行会话各占 worktree 互不踩踏)
+46
View File
@@ -11,6 +11,23 @@
- **工程路线图**:`production/roadmap.md`(2026-09-17 建——里程碑时间线 + 路线图;实时状态看下方快照节)
## 当前状态快照(收口批先更新本节,再追加台账;≤10 行)
- **更新于**:2026-10-07(**迭代18卡⑦两裁点全裁+调试浮窗目标态落籍 master 49ee98f**,worktree g-plan2-seedrule 单提交 56d996c+主区 merge --no-ff,工作日志 384;纯文档零代码零测试):种子三裁=首次冒险维持固定/测试调试接口显式指定/种子不进玩家UI(玩家入口随机生成);卡⑦扩为种子随机化+调试浮窗升级双件——浮窗目标态=独立最高层浮窗〔对局中可开,修订迭代15卡①P3甲〕+DS_DEBUG=1 默认打开+当局数据只读区块〔种子唯一查看位〕;现行考证六点在册〔角标门控/1189门禁/非最高层/非默认开/无当局数据面〕;卡①落地门随卡⓪落籍〔e5354366〕自然解除
- **更新于**:2026-10-07(**迭代18增卡⑦新冒险种子随机化落籍 master 7a7d873**,worktree g-plan2-seedcard 单提交 997bcc9+主区 merge --no-ff,工作日志 382;纯文档零代码零测试):用户令——现状实查 main.gd:1210 种子框空硬编码 42=每次新冒险同种子全程复现;卡⑦=默认分支改随机生成+调试浮窗种子框保留手动覆盖,断点续玩/冒烟锚/⑥收官批三面零影响考证在册;裁点两项随任务书(首次冒险教学态是否随机/种子进 UI 展示位);⑥门改「内容卡①-⑤⑦出口」;下一步=迭代 18 任务书讨论
- **更新于**:2026-10-06(**内容数据驱动扩展批实施完成落籍 master**(worktree iter17-dd 分支 iter17-dd-20261006,主区 merge --no-ff),工作日志 383〔预配号 381 撞号改登——381/382 系并行迭代 18 规划批与增卡⑦两批先落,先例同台账 374〕):迭代 17 卡⓪ 当日立项当日落地——T1 效果引擎框架+16 发射点(7d157b3)/T2 词汇落码(225765f)系前任完成,续跑会话接手 T3 断点三脏文件收口:T3 专长 27 行 triggers 全量迁移+旧 23 挂点枚举消亡+消费点拆除+文案入表+断言面随迁(e28a6cb,承接修正四处=perfect_defense 事实出域/has 算子语义/漏写 _harmful_adjacent/counter set 键 bool 吞零);T4+T5 秘宝六件按 id 硬编码清零(淬毒 clamp_bonus 模式路由/偏运经 reward_roll/晨令 round_start 订阅+when 行字段定影/惊巢 halve_pct/殉爆订阅开单/掘进蓄能受理闸 counter_spend 订阅)+令牌兑付 match 收敛进效果类型路由表(a33ddaf);闸=冒烟 800 项 0 失败+单元 17 套+探针闸含 click 全绿+MC 二档对拍 40 局同种子**逐位一致**(pre/post 锚 83000 段留盘 sim-data/);T7 文档换代=奇物 v2.8/秘宝 v1.0/敌人系统 v0.14+registry 两件+06 收口+roadmap 卡⓪行+出口报告(design/qa/iter17-datadrive-exit-report-2026-10-06.md);遗留人闸两项随报告(掘进蓄能模判定留编排器侧=词汇表边界/主动件 kind 词族全量 rename 不随批)+实机目检归用户。**下一步待用户=实机抽查**。
- **更新于**:2026-10-06(**迭代18规划批落籍 master 018435e**,worktree g-plan2-iter18plan 单提交 0d80626+主区 merge --no-ff,工作日志 381;纯文档零代码零测试):用户令——M4 数值批移 Alpha 阶段最后=迭代 18 ⑥收官卡(门=内容卡①-⑤出口,内容补全先行、统一数值调整殿后)+五内容卡立项:①奇物内容补全·文档先行(charge 补件设计〔实查现恰 3 件〕+06 资源入池条收窄收口〔刷新件与门票实已随迭代 15②入池〕)/②呈现优化六件(与迭代 16 语义零重合=其 token 下游)/③武器锻造系统设计提案(06 新立专条)/④生涯实装(门=卡④提纲评审)/⑤混编遭遇首批投放(MC 取证顺延⑥收官批);06 七处+07 一处状态随迁;资产升档批优先级再降维持挂起;**下一步待用户=讨论迭代 18 各卡任务书**(B 文档批零代码成立、C 与迭代 16 零重合两问结论已呈报)
- **更新于**:2026-10-06(**暂停层只读入口批完成**,迭代 17 卡③功能性 UI 交互批——纯呈现零数值改动=零 MC,worktree iter17-pause-20261006 基点 44328b1,两会话接力〔前任完成 T0/T1+组 B 代码后额度中断,续跑会话收尾跑闸+T3-T5〕,全部提交在 worktree 内未合并,台账 380):战斗屏/关卡地图屏各一枚「暂停」常驻角标开只读层(余额徽+三柜台进度+「继续」,零购买零写通路;badge 已工厂化入 ui_kit,营地钥石徽同步迁移观感零变化);他模态开着角标置灰不可点(has_open_excluding)。闸=冒烟 788/0(基线 783/0)+run_all 17 套+四探针全绿(含输入锁 case⑯/只读巡检/零动效契约/对比度新对)+doc 三闸零新增;存量移交两项=熵增闸 design/diagrams 越界(00712d5 落籍漏步,主区同红)+06/07 gdd_lint 存量注记红(本批零触碰)。出口报告=design/qa/iter17-pause-exit-report-2026-10-06.md。**下一步待用户=实机目检**(design/qa/iter17-pause-human-gate-checklist-2026-10-06.md,重点含排播排空副作用确认项 D2);过闸后合并落 master、06 目标条销号。
- **更新于**:2026-10-06(**生涯界面设计提纲批完成**,迭代 17 卡④纯设计批——零代码、零数据面、零测试执行,worktree iter17-career-20261006 基点 fc4dbde,全部提交在 worktree 内未合并):设计提纲已按 P0 甲裁定写成正式设计文档 design/gdd/systems/跨局循环/生涯.md v0.1(状态=范围草案),五节写全(信息架构/承载内容清单/与既有界面关系/分期实装建议/待裁点);P0-P5 六个已裁决结论全部落进对应章节,任务书 §2 十条现状事实(F1-F10)逐条对照代码复核全绿;复核新发现一项待用户裁决点「P6 营地底栏『最近冒险』条带去留」(数据源与生涯历史回看同一份存档摘要、条带拼行无上限,扩容后会爆——建议期二时撤下、逐局回看整体归生涯)。同批改动:02-系统清单.md 根索引补生涯行与 CAREER 代号行、06 生涯条状态行改「设计提纲已成文待评审」、roadmap 迭代 17 卡④行改已交付待评审、出口报告落 design/qa/iter17-career-exit-report-2026-10-06.md。**下一步待用户=评审设计提纲**(评审时随裁 P6);评审通过后期一/二/三实装批另行立项,本批未预占任何排期。
- **更新于**:2026-10-06(**迭代17五任务书联审修订落籍 master 68b8f15**,纯文档零代码零测试,工作日志 378):五个 subagent 并行审查五份任务书(卡0①②③④),挖出约 50 处问题、8 处开工即停机级;用户十裁(Q1-Q10)全落——卡0 v1.1 效果闭集扩 2 型+charge_full 事件+level_clear 归登记+对拍判据两套(确定性复放=逐位/MC 统计量=同带 m4iter12 口径)+映射表五处修正;卡① v1.1 **P3 改裁丙撤投放**(一裁乙与首遇教学位纪律三面冲突)+P1 补遭遇骰交互(每行一骰·RNG 扩签先报批)+实例总数≤4 消歧+R6 行序契约+F7 勘误 19 行 9 种,估时 3.75d;卡② v1.2 P3 转正顺延重扫读数后+检算工具 WEAKEN_PCT 入同步面+T3/T5 并账+估时勘误段一 4.25d;卡③ v1.1 R4 快照口径收敛+Q10 甲 badge 工厂化(营地徽迁入 ui_kit)+P1 丁 06 Esc 登记补办+基线换代 iter16ui 后;卡④ v1.1 F4 事实改正(recent_summaries 现役 cap=10,非「无历史记录面」)+P2 甲口径重述(扩容+补用时埋点)+总局数/通关局数涉 save v6;roadmap 四行+06 四处+07 两条义务(T7 判读带案C 复核+后续内容批投放六面)随批换代;**五卡零待裁点重建,开工门=U0**。
- **更新于**:2026-10-06(**迭代17四卡18项裁点全裁落籍 master d5df1f6**,纯文档零代码零测试,工作日志 376):卡①P1甲/P2甲/P3乙投放教学位行/P4乙否推荐Boss行亦放开(零内容投放不变,Boss多行内容归后续批);卡②P1甲维持2场·magnitude[60,85]当量锚复算/P2甲不对称有意/P3甲转正/P4甲不立直购价;卡③P1丁/P2甲/P3甲/P4甲;卡④甲×6;四任务书裁决回填+roadmap四行+06六处换代,**四卡全部零待裁点,开工门=U0**;四段发射prompt已交付chat(用户逐卡贴goal,卡0段本会话早前已交付)。
- **更新于**:2026-10-06(**批次工作流标准清单固化进 CLAUDE.md**,worktree g-plan2-workflow-checklist 单提交 8438d4c+主区 merge --no-ff,工作日志 375;纯文档零代码零测试):用户确认十三条链路工作流无问题并选 A 案固化——CLAUDE.md 新增「批次工作流标准清单」节(开工前三步/环境与基线三步/实施两步/收口四步,每步附既往事故出处,总索引定位与细则冲突以细则为准)。
- **更新于**:2026-10-06(**内容数据驱动扩展批任务书 v1.0 落籍 master 52c8bea**,迭代 17 卡⓪头卡插队,四卡顺延;纯文档零代码零测试,台账 373):用户盘问轮八裁决全落(发布订阅同步 emit/一个改写窗口/组合规则封冲突/旧 23 挂点枚举删除/现有实现全改造+06 在册只登记 3 事件/框架先行/一迭代四模块垂直切/术语纪律禁自造词);词汇表定稿=实施 17 事件+效果类型 16+组合规则 5+23 挂点逐行移植映射表;T0-T7≈4.5d **零待裁点,开工门=U0**;任务书=design/research/任务书-内容数据驱动扩展批-2026-10-06.md;roadmap 插队行+06 提案条目换代已立项。**下一步待用户=发令开工(U0)**。
- **更新于**:2026-10-06(**营地内滚提前断流修落籍 master 7d3e88f**,worktree g-plan2-uialign 单提交 a650fd3+主区 merge --no-ff,工作日志 374〔撞号改登——373 系并行数据驱动任务书批先落,先例同台账 335/96/90〕):用户实测「列表没展示到框底、底下空一大段就出现滚动条」——根因=工坊/图鉴树两处 ScrollContainer 写死固定高(336/200),面板本体撑满中段全高,行只滚到固定高处断流;修=size_flags_vertical EXPAND_FILL 撑满面板余高(内容超出才滚动);闸=冒烟+probe_gate --click 全绿+审计探针问题=0+pair_2 重摄+主区复跑同绿。
- **更新于**:2026-10-06(**用户实机营地两缺陷修落籍 master 6089e79**,worktree g-plan2-uialign 单提交 dd19c48+主区 merge --no-ff,工作日志 372):用户实机截图反馈两缺陷——①营地背景透出战斗画面(根因=T5 石纹降 0.14 后 0.45 半透 dim 失去遮蔽,对局中开营地底下棋盘/战斗提示条全透出;修=底改不透明暖亮档 BG_BRIGHT,demo #v-camp 实底同款)②右柜奖励格图鉴裁出屏(根因=柜台行标签按文字全宽算最小宽度,「累计通关 28/2 次·已解锁·能力封存中」长文案随档变长把三柜总宽撑爆 1248 可用宽;修=三柜 EXPAND_FILL 等宽分屏+五处行标签 clip+ellipsis 截断兜底+进度列 110→150+状态列 tooltip 全文兜底+锻造行距 12→8);判官(visual-judge)复判 pair_2 pass 零保留(三柜实测 406/359/441 均入屏、背景无透出);闸=冒烟 782/0+probe_gate --click 全绿+ui_audit_probe 问题=0+主区复跑同绿;审计报告 ②营地行换代(design/qa/ui-audit-vs-demo-2026-10-06.md)。
- **更新于**:2026-10-06(**/goal UI 对齐批全落籍 master 7356105**,worktree g-plan2-uialign 分支 uialign-20261006 七提交 58e8903..98493c8,两轮主区 merge --no-ff 2ca6288/7356105,工作日志 371):goal 令「将游戏的 UI 对齐 demo 的 UI」收官——实机九屏对齐 demo v2.1(基准=artwork/ui-redesign-2026-10-04/src/ui-prototype.html md5 78ebbee0):①底栏 85px 定高单条(放弃 90 小钮+特性行限宽截断+tooltip 全文+深墨,爆栏根除)②结算 DIM_NIGHT 0.62/0.6 压暗+两列账行+紧凑钮 ③标题屏主操作反转(有档=继续上局主黄钮)④E5 回滚 blast→TG_MAGIC(TG_AOE 只接 aoe)⑤背景氛围层 UiKit 单点(石纹 0.14+径向暗角+斜光带+地图渐变 #4A3B2A→#3A2E22;start/map/camp 旧满铺石纹退役,换层 tint 保 0.14 档)⑥D1 竖卡 232×352+图标槽 76/60+类型脚注行 ⑦D2 商店全屏页 page_shell(56px 通栏顶条+爬价规则行实数投喂 shop_bp_visit_buys×shop_price_a+底注池源;三选一同壳根底档)⑧设置两列对齐+主音量滑轨实高修(HSlider 槽按 stylebox min 高绘制、零 margin=不可见实测)+减动效核证(reduced_motion 单设置不拆行)⑨地图顶栏关卡名框板+GP 烛光胶囊;**自验=goal 判官(visual-judge)两轮独立目检 9/9 pass**(初判 7pass/2partial/1fail→四修→复判全 pass,对比图 design/qa/ui-audit-2026-10-06/ real+pairs 终态);06 两条换代(D1/D2 三项已落地/审计差距清单六项闭环+五项留档)+审计报告批末判定节;闸=开工基线 782/0(4336fd2 净态)+每轮冒烟 782/0+批末 run_all 16 套+全探针绿+doc 三闸零新增(2 处 06 陈旧断链=基线随 merge 自愈)+主区复跑(冒烟 782/0+click 全绿+run_all 17 套);**并行冲突实录**=ff23023 三选一刷新批 mid-flight 落 master,curio_pick_overlay.gd 五处冲突 union 解(页壳+付费刷新两保,探针零改过闸);**遗留留档(06+报告 §批末判定)**=camp 面板明度/战斗棋盘底板(样张冻结域)/地图道具槽(台账 352 功能件)/稀有度脚注词(数据面无投喂)——实机终验归用户(F5 逐屏目检)。
- **更新于**:2026-10-06(**三选一刷新对齐商店落籍 master**,worktree g-plan2-curio-refresh-gp 分支 m4-curio-refresh-gp 单提交,主区 merge --no-ff,工作日志 370):用户令「三选一对齐商店,得有刷新」——刷新钮此前只有免费双源(刷新件 X/冒险池 Y)且余量 0 整钮隐藏、无付费档=常态看不见;本批=免费位用尽转 GP 付费档(价 ceil(20×1.8^已付费刷) 读商店同两旋钮、扣同一冒险钱包、重抽同共享池、付费刷计数每停点清零)+钮常驻选择态(两源皆穷禁用不隐藏)+通关停点刷新重发直落选择面(不再重开胜利总结面);店内门票专长三选一维持无刷新(扩面须先裁门票保底计数交互,已注记);落文=秘宝.md 双源节+冒险结构 v0.16+06 商店刷新条目换代;闸=run_all 17 套(新增 curio_refresh_paid_test)+冒烟 782/0+probe_gate --click 全绿+主区复跑同绿;实机目检已过(2026-10-06 用户确认验收,会话收口)。
- **更新于**:2026-10-06(**内容数据驱动扩展架构调研落籍 master ced5fb7**,worktree g-plan2-research-ext 分支 research-content-ext-20261006 单提交 d2dacc5,工作日志 369,零代码零测试):用户两问=改已有物品数值/名字/稀有度**纯配置成立**、换新效果/机制类新专长**现状必改代码**(专长 23 挂点封闭枚举+match 翻译段 battle_orchestrator.gd:101-179+消费点约 24 处散布;秘宝被动件按 id 硬编码六件;效果文案硬编码三处;**技能池=全数据驱动范本**);mod 游戏四共性(Minecraft 数据包/Factorio 原型/RimWorld Defs,前两者官方文档核对);备选案甲(清秘宝+文案入表≈1天)/乙(效果类型统一+时机埋点≈3-4天分期①专长②秘宝③令牌,荐)/丙(外挂脚本层挂账)三列全备选;**待用户**=四拍板点(立项选择/排期/词汇表范围/文案表值化)+疑似缺陷 main.gd:475 未传 attunement/tree_rules(营地装配疑似不生效,已复核传参面未实机复验)——两项均登记 06;报告=design/research/研究-内容数据驱动扩展架构-2026-10-06.md。
- **更新于**:2026-10-06(**实机反馈三连修+全屏 UI 审计落籍 master 797bb2f**,工作日志 366-368):①标题屏玩法文字墙删除(用户令:界面禁玩法说明文字墙——教学内容归 Beta 帮助手册〔教学引导定稿批 P4 丙〕)+钮高纪律 BUTTON_MIN_H=40 单点+ui_struct_probe equal_height 同容器钮高断言族(f823abf,附 ui_contrast_probe .uid 侧车补 127a502);②续玩停点恢复 main.gd:717 崩值修(a2b7c21——resume 三选一停点分支先于 level_started 同步 emit,GP 总结 lambda 求值时 runner 未赋值;修=runner 缺位守卫+断点快照 gp 兜底;ui_struct_probe⑦resume 回归专项先红后绿实证);③全屏 UI 审计(f523036/797bb2f——实机十二屏窗口化截图 ui_audit_probe × demo v2.1 纯净模式浏览器现截九屏,逐屏并排对比图九组+差距报告=design/qa/ui-audit-vs-demo-2026-10-06.md);**下一步待用户裁决**=底栏按 demo 88px 重设计草案(放弃小钮/特性行限宽/淡墨换深墨)/E5 爆破带回滚(demo 紫带证据:blast 应归 TG_MAGIC)/标题屏主操作语义/结算仪式感/背景处理——清单已登记 06;并行在飞 worktree g-plan2-standee-tier(art-standee-20261006,非本会话)勿碰。
- **更新于**:2026-10-06(**三选一空池降级修复落籍 master 02fcc55**,用户令 bug 修复 mini-loop,worktree fix-curio-empty-skip 单提交 059b545+主区 merge --no-ff,worktree 已清,工作日志 365):专长零配置形态下 Boss 后「战利品三选一」空池死面卡死修复——core skip_empty_curio 停点消化出口(仅空候选放行,零自动推进契约不破)+controller 三入口(通关停点/奖励节点/店内门票)空池不开面直落后续推进+跳过 toast;「有 3 显 3 有多少显多少」系既有行为零改动(本批唯一新增=0 件跳过);两呈报=feats.tres 在册 27 行与用户「零配置」口径不符(疑实机跑旧版本/旧档)+问号卡=feat_row 查空兜底「特性\n???」非空池形态(复发须用户给版本/档龄对拍 resume 的 bonus_deck 令牌);未跑闸(测试执行两入口铁规挂账),实机验证归用户(新档打第一关 Boss:总结点继续应直进下一关+跳过 toast)。
- **更新于**:2026-10-06(**迭代改号批:迭代 16=UI 设计对齐批、原四卡顺延迭代 17**,纯文档零代码零测试,主区直改未提交,工作日志 363):roadmap 原迭代 16 四行(敌人行集多行/M4 数值/暂停层只读/生涯设计)改号迭代 17,原位新立迭代 16=UI 设计对齐批(事实源=UI预览demo三路改进整合对照-2026-10-04.md;红线=零美术资源改动只改 UI 设计代码;状态=待办阶段待六分歧裁决与任务书);四份任务书 13 处+06 七处状态行同步改 17;UI 任务书 P1-P11 裁决落文审计(只读)=11 点全裁齐可发令,5 处陈旧标记待用户「清」令(标题草稿字样/§8.2 节头/P10·P11 小节「未裁」/T6 依赖列)。
- **更新于**:2026-10-05(**奇物词族对齐与渠道分离批 T0-T8 全落籍 master 3c6f2c9**,worktree curio-wordfamily 八提交 d4cde73..33f1842 含 master 同步,主区 merge --no-ff 3c6f2c9,台账 362):迭代15②号卡收官——三套词族代码层全换(feature_→curio_ 93 处;bonus_ 运行层→curio_ 全族+两文件改名;relic_→feat_ 三文件改名);渠道白名单分离(总池-渠道子集多级缓存形=用户裁);门票入表(provisional 20%/2/1/5+拿到即开+保底/限购/共享计数+autoplay 分支缺陷批内修复);refresh 入池(B案 heal 5→3 挤占);shop 补 heal 行;T2 裁点甲案=六存档键禁改(含漏登记 "relics" 键);charge 缺陷登记不硬补;reward_overlay 基线红红转绿(M7 bcard 成因)——**run_all 16 套历史首次全绿**;闸=主区冒烟 782/0(+10)+五探针绿+doc 三闸零新增+MC n200 只测不判(82000 锚留盘);遗留=07⑰ 目检+C1/C2/C3/C4 四移交;出口报告=design/qa/iter15-2-curio-exit-report-2026-10-05.md。
- **更新于**:2026-10-05(**迭代 16 四份任务书起草并登记入册**,纯文档批零代码零测试,worktree iter16-taskbooks-20261005 单提交 ffd45eb+主区 merge --no-ff 446d5f9,工作日志 361):四份任务书落 design/research/——①敌人表行集多行批(同一坐标行集恰一敌种校验放开,enemy_table.gd:108-112 校验点/config_db_resolver.gd ceil 解析/unit_container.gd:47 spawn 等代码考证在册;T0-T8≈4.25d,4 项待用户裁点〔混编数量语义/行集解析双算法处置/首行投放与否/Boss 行放开与否〕)②M4 数值批(削弱终值+数值点评五条+迭代 10 联动欠账①②+元进度定价剩余面四件合一,T6 四带复算与 T7 节奏重测两件读数义务随批,damage_probe A1 改前既有红灯顺路修;T0-T8≈6.0d,跑批一律先报批,4 项待裁点)③暂停层只读入口批(局内暂停层只读看钥石余额与三柜台进度,复用 UiKit 公共件零新素材;T0-T5≈3.0d,4 项待裁点)④生涯界面设计立项(只做设计提纲不做实装,T0-T2≈1.25d,6 项待裁点);roadmap M-4 表追加迭代 16 四行(门=迭代 15 出口)+迭代 15②卡标注修正为「文档+数据层落籍(c571af2),渠道分离与入池实施段+curio 换名回归迭代 15 继续完成(2026-10-05 用户令)」、迭代 15 整行保持开放;06 七条目状态行追加「已编入 roadmap 迭代 16(任务书已成文待 U0)」注记。**考证差异两处已呈报**:任务背景称 master 头=8944dca,起草时点实际=413c936(ui-struct-probe mini-loop 与 archify 两批在背景成文后落籍,任务书基线数字一律写 T0 重测回填);「调参批数值点评八条」与 06 条目现行登记五条不符,任务书以条目五条为准(任务书 §2.2 F6)。
@@ -832,3 +849,32 @@
363. **迭代改号批:迭代 16=UI 设计对齐批、原四卡顺延迭代 17(2026-10-06,用户令「迭代 16 改实现 UI 优化需求、原四卡顺延 17」;纯文档零代码零测试,主区直改未提交)**:①roadmap.md——原迭代 16 四行(①敌人表行集多行②M4 数值③暂停层只读入口④生涯界面设计)逐行改号迭代 17,原位新立迭代 16=UI 设计对齐批行(事实源=design/research/UI预览demo三路改进整合对照-2026-10-04.md;**红线=不修改美术资源**:只改 ui_kit 色板 token/字号档/布局/对比度/抖动/panel_skinned 接线等设计代码;无分歧可直接收项与六分歧前置点写入行内;状态=待办阶段零任务书)②四份任务书「迭代 16」字样 13 处改「迭代 17」(含卡间互引卡③卡④)③06-待办清单 七处「已编入 roadmap 迭代 16」状态行改 17④active.md 两处「迭代 16」系历史工作日志记录未动(只呈报)⑤交付迭代 16 开发发射 prompt(chat,自包含含 U0 预批准+裁决点收口第〇步+worktree iter16ui 纪律+T0 重测回填)⑥UI 任务书 P1-P11 裁决落文审计(只读核查,另一会话落文):11 点全裁齐(P1=甲/P2=丁 10-05;P3 甲/P4 乙/P5 甲/P6 甲/P7 乙/P8 甲/P10 乙/P11 甲 10-06 采纳推荐;P9=注销清单)与 §8.3 三层优先级栈一致、估时重算≈6.75d 三段切分、迭代 17 改号已传导——**可发令开工**;5 处陈旧标记呈报待清(标题「v1.0 草稿待裁」/第 9 行「裁点未决前不实施」/§8.2 节头「待用户裁点」/P10·P11 小节标题「未裁」/T6 依赖列「**P3**」未改✅格式);知情两点=任务书基线 446d5f9 已漂至 3c6f2c9(T0 重测回填覆盖,15② 落籍后「不触碰在飞」停机点自动解除)+§8.3-D 三条结构级差异「未裁」系设计如此(已登记 06 不入本批)。**遗留**:5 处陈旧标记待用户发令清理;开发 session 发射待用户贴 prompt。
364. **UI 设计对齐批 T0-T11 全落籍(2026-10-06,迭代 16;开工令 prompt=U0 预批准;worktree g-plan2-iter16ui 分支 iter16-ui-20261005 十二提交 85ea024 T0/a55a302 T1/b38ae07 T2/4e7aa83 T3/af5f317 T4a/b26e3fb T4b/2f74da8 T5/e0fd7cb T6/1b2ecf6 T7/e5427af T8/ce3dab9 T9+T10/33defc0 T11 收口,主区 merge --no-ff fa54de1)**:任务书=design/research/任务书-UI设计对齐批-2026-10-05.md(v1.0 定稿,P1-P11 裁决已齐;五处陈旧标记随第〇步文档批擦除)。**第〇步文档批先行落籍(a39d044;临时分支 iter16-docbatch-20261006 承载提交后快进回 master——主区直提系 worktree 铁律守卫拦断面,按守卫「提交在任务分支完成」语义处置;七指名文档逐文件 diff 复核后指名 add)**。**T0 基线重测回填**=冒烟 782/0+run_all 16 套全绿+probe_gate --click 绿+layout exit0+doc 四闸基线定性(gdd_lint 2 文件/死链 2 真实+2 环境假红〔.zcode/plans+archive 不入库〕/term 218/熵增 diagrams——全部既有在册守零新增)+demo md5 零漂移(78ebbee0,Q9 丙留痕后未回读)+事实表 15 项复核(五漂移注记:clampi 实在 :254/RED_MINE 实值 #962C24/字号普查 78→107/INK_LABEL 定义 :19/_register_modal :346)+**七点对比度实机复算三处修法改向**(意图徽标直背=暗舞台底 1.5-3.3:1→demo「换墨降档」实机反向→改 PANEL_DATA 垫牌:atk 零换墨 5.27/buf 换 HERO_BLUE_DEEP #1E5A96=4.78/charge 换 GOLD_INK #74500B=4.88/debuff 随牌 4.66;槽两态字直背=亮石皮→demo「提亮 WARM_FAINT」反向→改深化 STONE_DEEP #554D41=5.60+INK_LABEL=10.40;RAP 实机 10.40 已合规=零改动,仅显式传色)+15② 交集零命中。**T1-T8 实施**=T1 status_slot_row 九枚 preload→load_tex(呈现层素材 preload=0);T2 七处修法落码+**ui_contrast_probe 新增入 probe_gate 默认段**(11 对测点 WCAG 实算+裸 Color8 白名单静态段+preload 红线段)+art-bible §7.4 合并豁免条款(P11 caption 12px+血数条带内读数同条);T3 站桩纵向余量(STANDEE_FOOT_MARGIN=12·名行基线 -1→-13·底座矩形收单一来源)+ui_struct_probe ⑥standee 断言族(内容矩形⊆舞台+底缘≥8px——首跑抓左右 6px 容器边距系断言语义过严改任务书口径);T4a 裸 Color8 全量 25 处/10 文件原值搬运收 ui_kit(任务书 N4a 记 5 处系漏记)+TG_* 五族立项+tg_band() 同源分族判定(Q4 甲三选一/货架同判;aoe/blast→TG_AOE #E25676=reward.tres 现成 spark_aoe/clear_blast 消费面;max_hp 归回复族);T4b P7 乙五 token 改向 demo 值(Δ≤6/255)+§7.2 五件对齐注记;T5 P4 乙 panel 切片 8→16(PANEL_SLICE 单点)+Q1 丙工厂 content margin clamp(9 消费面 7 处自动抬平调用点零改)+P5 甲 RADIUS_OBJECT=5 收敛 26 处(例外 17 底座/200 金印/100 脉冲环保留)+§7.1 两条注记;T6 P3 甲 FS_* 六档全库归档 107 位点(就近映射 40→34/26→24/22→24/20→18/13→14/11→12;11px 六处提 FS_CAPTION 并入豁免清单;settlement_fx span 错位写入两处当批发现当批修复)+art-bible §7.4 档位表+逐处豁免清单;T7 P6 甲缩放纪律(状态九枚常规档 32px=1×·mini 16 维持/柜台四枚 64 源 32px=0.5×/BCard 槽 40px=2×/地图头像定高 48 宽随源比=纵横异倍消除)+P10 乙记忆态换装「地板纹理+灰罩 α.66」(平涂退役;记忆墨对合成底 6.71:1 实测复算)+art-bible §8.2 例外登记+§6.5 记忆态条款换代;T8 P8 甲 bcard 卡顶 DitherBand Bayer 4×4 抖动带试点(平涂 ColorRect 退役;全站/B 区范围留后批)。**T9 重闸全绿**=冒烟 782/0(断言数持平)+run_all 16 套全绿+探针五件(click done=true 问题=0)+layout+doc 三闸/熵增零新增+素材零触碰(art/artwork 未改一字节)+MC 零跑(纯呈现批——核心/数据层 diff=0 实证)。**T10 人闸材料包**=design/qa/iter16-ui-human-gate-checklist-2026-10-06.md(A 整屏样张四项〔Q2 乙并入〕+B 八屏对比+C 十专项+D 减动效+E 代拍板追认八项〔RADIUS_OBJECT=5/三新墨/TG_AOE 归族/牌宽 8/抖动参数〕)——实机目检归用户。**T11 收口**=roadmap 迭代 16 行落籍标注+06 新登记「呈现层残余 <4.5:1 文字位」(站桩名行四墨/敌顺位徽标 GOLD_DEEP/RAP 反馈 STONE_FAINT——批外邻接发现待后批)+出口报告=design/qa/iter16-ui-exit-report-2026-10-06.md(T0 基线回填表/逐卡落点/N5 面板皮造册〔穿戏服 9 面+素面零补皮〕/重闸读数表/偏差八条汇总)。**美术红线全批合规**(素材字节零改动);预算 6.9d 实际单会话一次跑完(三段并一次合并=Q7 甲);worktree 待清。
365. **三选一空池降级修复落籍(2026-10-06,用户令 bug 修复 mini-loop;worktree g-plan2-curio-skip 分支 fix-curio-empty-skip 单提交 059b545,主区 merge --no-ff 02fcc55,worktree 已 remove+分支已删)**:用户实机报缺陷=打完 Boss 弹「战利品三选一」全问号且无法选择,进程卡死(用户令降级策略:向池子取备选项有多少显多少、0 个直接跳过环节)。**成因核证**=CurioPickOverlay 空候选死面:通关渠道白名单过滤后只出 relic 令牌(迭代15② T4),专长池空时 _draw_curio_candidates("level_clear") 返回空集仍挂三选一停点,open_pick(空 cards)=无卡无确认钮无继续钮。**修法四处**:①core adventure_runner.skip_empty_curio() 新增=停点空候选消化出口(仅空候选放行——continue_to_next_level「停点未兑付拒推进」守卫因此放行;非空停点拒绝=零自动推进契约不破,正常消化仍只走 pick_curio/apply_node_curio 兑付);②controller resume_if_pending() 空候选不开面,消化停点后按上下文直落后续推进(level_clear=推进下一关/reward_node=continue_after_node 回图选路/feat_ticket=只消化关面回店,与 on_continue 分派同构)+toast「可用战利品为空——本次三选一跳过」;③controller present_node_curio() 奖励节点空池不开面不挂节点停点,兑付确认直落回图选路(auto-sim「node_entered 内立即 continue_after_node」先例);④on_presented() feat_ticket 分支末道防御(core _redeem_feat_ticket 空集守卫外)。**「有 3 显 3 有多少显多少」系既有行为零改动**(洗牌收集至池空为止,上限 curio_candidate_count=3;卡片渲染按候选数遍历)——本批唯一新增=0 件跳过。**两呈报待用户**:①feats.tres 在册 27 行(迭代12 T1 批 2026-10-04 落),用户「还没配置任何专长」口径与仓库现状不符,疑实机跑旧版本/旧档;②「界面全是问号」唯一代码来源=feat_card_text 空 row 兜底「特性\n???」=候选非空但 feat_row 查空形态(疑旧档 bonus_deck 令牌 feat_id 与现行表不匹配)——空池跳过对该形态无效(候选非空不跳,但可点选兑付不卡死);复发须用户提供运行版本/存档档龄对拍。闸=未跑(测试执行两入口铁规——非 loop 批收口跑闸当场问,自主会话无法问故挂账);验证路径=实机新档打第一关 Boss:战斗总结点「继续」应直进下一关+跳过 toast(约 2 分钟)。存档键/存档格式/数值零改动。
366. **实机反馈两缺陷修(2026-10-06,用户截图裁决;worktree g-plan2-iter16fix 分支 iter16-fix-20261006 两提交 8e490b4/9fb8b74,主区 merge --no-ff f823abf/127a502)**:①标题屏「玩法说明」文字墙=用户痛斥**删除**(非修裁切——问题本体=文案不该存在;设计铁规:界面禁玩法说明文字墙,教学内容归 Beta 帮助手册〔教学引导定稿批 P4 丙「零再教」〕;ui_assembler 帮助牌块删+M2 注记换代,历史文案在 git);②钮高纪律 **BUTTON_MIN_H=40** 单点立(主/危/常规钮统一最小高——标题屏主钮 26px 对常规 38px 不齐治根;min_w=0 紧凑位豁免同宽度纪律)+ui_struct_probe **equal_height** 同容器钮高断言族(width 216 有纪律而 height 无纪律=漏机根因);轻闸=冒烟 782/0+三探针绿(equal_height 全屏首跑零红);附=ui_contrast_probe.gd.uid 侧车补提交(.uid 必须入库规约——worktree 编辑器导入才生成致上批漏随,主区跑测再生一份撞合并,diff 同哈希后删未跟踪件再并)。
367. **续玩停点恢复 main.gd:717 崩值修(2026-10-06,用户实机 F5 抓到——真 bug 用例漏了;worktree g-plan2-iter16fix2 分支 iter16-fix2-20261006 单提交 c32bb6c,主区 merge --no-ff a2b7c21)**:resume_adventure 的 bonus_pending 分支在 level_started 之前同步 curio_choice_presented.emit(adventure_runner:250 提前 return true)→ 胜利总结 GP 行 lambda 求值时 runner 尚未赋值(null.gp 炸,调试器停 717);修=_gp_summary_text runner 缺位守卫+断点快照 gp 兜底(合计语义=恢复面合计即存档合计;与 _bonus_summary_text 同款守卫式);回归=ui_struct_probe⑦resume 专项**先红后绿实证**(夹具显式 main.runner=null 置全新启动态——首版夹具推过冒险残留 runner 非空,红因不合真机已修正;Nil.gp 同栈复现 resume_adventure:250←_resume_from_menu:437→修后总结面开+「合计 24」断言);轻闸=冒烟 782/0+run_all 16 套+probe_gate --click 全绿+主区复跑同绿。**用例漏了**的空档=呈现层「续玩恢复到停点」组合根链路此前零覆盖(core 断点往返有测、lambda 面无测)——凡新停点/恢复分支必须带呈现层 resume 断言。
368. **全屏 UI 审计(2026-10-06 用户令返工「每个界面截图和 demo 对比」;worktree g-plan2-uiaudit 分支 uiaudit-20261006 两提交 34eb460/9d0410e,主区 merge --no-ff f523036/797bb2f;零代码修改)**:实机十二屏窗口化程序截图(新探针 game/smoke/ui_audit_probe.gd——shot_probe 十二屏扩展形,真实信号路径+拟真数据,2304×1440 DPI 归一 1280×800)×demo v2.1 浏览器现截九屏(本地 HTTP+纯净模式 body.clean+全视口 PIL 裁剪——IAB 同单元格连拍 clip 会平铺花屏的坑在册);九组并排对比图+逐屏差距报告=design/qa/ui-audit-vs-demo-2026-10-06.md(差距排序:①地图底栏〔demo 85px 单条+放弃小钮 vs 实机特性行爆栏+216 红砖+特性组暖白淡墨 §7.2 违例;重设计草案=定高 88/放弃小钮/特性行限宽+深墨,待裁〕②商店/三选一形态级 D1/D2 坐实③结算仪式感④背景全局差距〔demo 暖渐变聚焦 vs 实机全铺石纹〕⑤标题屏主操作语义反转⑥E5 反证=demo 爆破卡紫带应归 TG_MAGIC;demo 无映射三屏=调试浮窗/图例/确认框仅存档;demo 有玩法速览牌=实机按用户令删除不回补);06 新登记「全屏 UI 审计差距清单」条目汇总待裁项。
369. **内容数据驱动扩展架构调研(2026-10-06 用户问「改物品设计是否只改配置/机制类专长能否零代码」并令学习 mod 扩展游戏实现;worktree g-plan2-research-ext 分支 research-content-ext-20261006 单提交 d2dacc5,主区 merge --no-ff ced5fb7,worktree 已清;零代码修改零测试)**:现状核证(Explore 代理全库扫描+本人抽查 feat_table.gd/battle_orchestrator.gd/treasure_item_table.gd 三面复核)——①改已有内容数值/名字/稀有度/投放=纯配置成立(全内容族 .tres 数据表+schema 封闭枚举校验+悬空引用加载致命,config_db.gd:12-31 统一装载);②新效果行为必改代码:专长 23 挂点封闭枚举(feat_table.gd:36-67)+求值段逐个 match 展开(battle_orchestrator.gd:101-179)+damage_controller/orchestrator 消费点约 24 处+流派档位质变硬编码:171-175;秘宝主动件按 effect_kinds 通用分发(battle_orchestrator.gd:648-666,好形态)但被动件按 id 硬编码六件(venom_edge/luck_coin/dawn_order/nest_counter/flag_burst/pick_refresh)+dig_charge 特判:643;奇物令牌 match 分发(adventure_runner.gd:412-449);效果文案硬编码三处(battle_narrator.gd:104-166/curio_interact_controller.gd:185-204)=新件无名无声根因;③**技能池=全数据驱动范本**(skills.tres 加行+enemy.tres pool 引用全链路零代码,Boss 半血解锁=unlock_hp_pct 字段)——差距=把专长/秘宝/令牌提到同等水平;④mod 游戏查证=minecraft.wiki/w/Data_pack+wiki.factorio.com/Modding 官方原文核对(rimworldwiki 反爬只取入口页按通行记载表述)——四共性:内容=数据/机制=通用解释器、语义事件时机+内容订阅、条件通用词汇跨内容复用、加载期注册+校验闸(我方已有);边界共识=「新机制」仍属代码但压成低频加类型,「新内容」高频零代码(Minecraft 数据包亦不能加新机制);⑤备选案三列=案甲最小修(清秘宝 id 硬编码+文案入表≈1 天)/案乙效果类型统一+时机埋点(专长秘宝令牌统一「触发时机+条件+效果类型+参数」数据形态+结算段语义事件点,≈3-4 天分期①专长②秘宝③令牌;MC 模拟器共用 battle_orchestrator 零改动自动受益;**荐**)/案丙外挂 GDScript 效果脚本层(真 mod 支持≈5 天+,Alpha 前挂账);**四拍板点+疑似缺陷两项登记 06**(数据驱动扩展四拍板点条〔立项/排期/词汇表范围/文案表值化〕+main.gd:475 未传 attunement/attune_refresh_y/tree_rules 疑似缺陷条〔runner 受理面 adventure_runner.gd:128-137 在、smoke 直呼参数面故未拦,本人已复核传参面、未实机复验待令〕);报告=design/research/研究-内容数据驱动扩展架构-2026-10-06.md(主区 Write 被 worktree 钩子拦,按钩子指路 worktree 执行合回)。
370. **三选一刷新对齐商店批(2026-10-06 用户令「三选一对齐商店,和商店的购买一样得有刷新」;worktree g-plan2-curio-refresh-gp 分支 m4-curio-refresh-gp 单提交,主区 merge --no-ff,worktree 已清)**:现状核证=CurioPickOverlay 刷新钮迭代11第①批 T5b 已在(X/Y 免费双源:刷新件+营地升级冒险池),但余量 0 整钮隐藏且无付费档=常态玩家永不看见(本次用户愤讯根因);需求检索=06「商店独立刷新机制」条只记商店侧 SR-1,三选一同款付费档全库零成文(口头裁决未落文丢失,本批当场落文)。机制落码四处:①adventure_runner——_curio_paid_refreshes 付费刷计数(每停点清零=与商店进店清零同构,两处停点创建位随 X 余量重置同点清)+refresh_curio 拆 _refresh_curio_common(paid)(免费/付费共用同一重抽体,池规则全保留)+新口 refresh_curio_paid/curio_refresh_gp_cost(读同 shop_refresh_cost_base/curve 两旋钮=与商店单点调参)/curio_stop_pending 谓词(付费扣费前置校验防空转烧钱包);②level_runner——spend_gp 钱包单口(与商店刷新同一 GP 冒险钱包,余额不足 false 零副作用);③curio_pick_overlay——set_refresh_info 换代 set_refresh_display(免费余量,GP价,可付) 与商店同名同构(钮常驻选择态、免费与付费两源皆穷=禁用不隐藏;角标=免费余量、免费行「免费·不消耗 AP」、穷尽后价签行「刷新 N 金币」、tooltip 含池源同源句)+结果态/替换子态/收屏三处收刷新钮(选择态专属,停点已兑付残钮零意图可点)+press_refresh 探针复用口;④curio_interact_controller——on_refresh 免费位先试、穷尽转 GP 付费档(spend_gp 成功才 refresh_curio_paid,拒绝 toast「金币不足——刷新失败」,成交后刷新呈现投喂)+_feed_refresh_display 投喂单点;连带修=通关停点刷新重发载荷带 refreshed 标、on_presented 直落选择面(原路径会重开胜利总结面=迭代11遗留呈现缺陷,免费位常态 0 故从未暴露)。边界=店内门票专长三选一维持无刷新(扩面须先裁门票保底「刷新后重新展示计入」的计数交互,秘宝.md 注记在册);断点快照不载付费计数(续玩回基价——商店进店清零同构口径,X/Y 本就不入档)。测试=新单测 curio_refresh_paid_test 六面(停点谓词/免费优先序 X→Y/付费零触碰免费位/价曲线 ceil(基价×曲线^已付费刷)/停点重建清零/spend_gp 三态)+reward_overlay_test 刷新面断言(投喂前隐藏/付费禁用态/免费点亮/余额可付点亮/press_refresh 外发/结果态收钮);闸=run_all 17 套全绿(历史首次)+冒烟 782/0 三闸过+probe_gate --click 全绿(input 十六断言/struct/contrast 11 测点/click done=true 问题=0/残留 Godot=0)+主区合并后复跑同绿。落文三处=秘宝.md「三选一刷新双源」节 GP 付费档段+冒险结构.md v0.16 行(共享池账本节同款句)+06「商店独立刷新机制」条换代(机制已落码态=SR-1+本批;剩=shop_refresh_free 与曲线两参数调参归 M4 数值批+天赋侧刷新增益形态未定)。worktree 坑在册=新工作树缺 .godot 导入缓存致 run_all 每套件全量重导近似卡死(解法=主区 .godot 整目录+gitignored 字体 .ttf.import 边车拷贝;probe_gate 有冷导入路径而 run_all 无)。
371. **地图伤害账殿后批(2026-10-06 用户裁案C——「主角先手攻击一次」歧义质询三轮触发;worktree g-plan2-mapdmg-combatend 分支 mapdmg-combatend 单提交 58dfb56,主区 merge --no-ff)**:用户质询结算顺序出处→考证=顺序自 initial commit(da157e3 前身 09-14 squash 前即成文)代码注释引「2026-09-11 用户裁决」但一手记录在 git 前不可出示;用户定性=「主角先基础攻击→怪物结算」句不含地图伤害时点、地图奖励伤害不算主角攻击(无此定义)、实施序非其设计,令「把有歧义的东西改对」;AskUserQuestion 两裁=时点案C(战斗段末怪物还手后)+修法全仓扫。**裁决落文**=每轮结算定死「①授予段兑非伤害账(资源/增益/治疗/行动点/GP/警觉;伤害形态单据暂存不兑)→②增益/减益→③战斗段〔主角先基础攻击→敌人按生成序逐个还手→地图伤害账殿后〕→④衰减→⑤判定」;主角死于敌方还手→暂存单整体不兑逐单留「未生效(主角已倒下)」行(forfeit=hero_down 载荷)。**切片**=battle_orchestrator 暂存闸 _defer_board_damage/_deferred_board+_submit 案C分流(sync 同闸——清图批 clear_blast 一致延后)+_outcome_of(暂存单「将兑付」回报——完美第二份/高光份数依据开单时点事实,实兑若目标已灭控制器自记未生效行)+授予段四处直提改走闸+战斗段末补提交块+授予段界 flush 保留空队防御位;smoke 分类器换代(damage 恒战斗段/reward_ineffective 按 forfeit 分流)+先手断言收紧(「存在或授予段终局」→「必存在」)+新增案C 段内序断言。**文档**=战斗结算 v0.26(五段表①③行/授予段节/兑付形态表 blast 正向 heal 负向时点/结账时机双模式改「段界结账+地图账殿后」/战斗段节/P0 闭环第5步;顺手清充能退役遗留=三分量句改单分量+三处「主角普通分量」改「基础分量」)+敌人系统(P0 第4步战斗段限定+地图账+死亡来源「授予段直伤」改「更早兑现的敌方伤害技」)+地图战斗资源(流程图/负向恒即时节/五步清单)+01-核心循环(「怪物的先手」用词相撞改「警觉」)+game/README 案C批节+registry entities 两处案C注记(map_reward 负向恒即时节/settlement 段内伤害序)+编排器头部注释。**闸**=冒烟 783/0 三闸过(782+1 新断言)+run_all 17 套全绿+probe_gate --click 全绿残留 0+gdd_lint 与基线一致(8 文件 2 存量);**旧行为 MC 锚全数作废**(授予段伤害致死短路先手语义消失——锚重采归数值批,未跑 MC 遵两入口铁规);**worktree 坑续录**=新树除 .godot 整目录外还须拷 .import 侧车族(gitignored,缺则 ui_font_asset_test「No loader found」红——find -exec cp --parents 解)。**另账在册**=清查报告附注四件(战斗结算 :204 三分量句已顺手清/architecture.md:190 退役 API 名/query_attack 系欠同步/docs/ 悬空路径四文档头注——后三件未动待用户发令);清查正主=歧义三处(战斗结算 :64 原点+五段总览①行+敌人系统 :205)+相邻一处(01-核心循环)全部随批闭合。
372. **另账修正批(2026-10-06 用户令「文档修改现在就修正,不需要独立迭代」;worktree g-plan2-docfix-ref 分支 docfix-ref-20261006 单提交 ffb0e36,主区 merge --no-ff ac61b34,worktree 已清)**:①悬空指路句 13 处改写——docs/proposal-skill-pool.md / proposal-status-vocabulary.md 两提案(7f24b640 三层收敛迁 design/research→a6833b6a 死亡清单批依吸收即死删除,引用点漏改=该批提交信息自登记「余 7 条全为搬前幽灵链」的遗留)现指路句〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节/词汇表〕,落点=敌人系统 4+战斗结算版本史 2+增益状态版本史 1+registry 2+game/README 批节头 2+unit_container/enemy_table/skill_table/smoke_all 代码注释 4;②architecture.md 活契约面旧 API 三处换代——:190 调用序(query_attack→apply_damage→advance → 按摇定技能行兑现→apply_damage→commit_action+案C 段内序注)、:152 数据流图示行(stock/advance 退役→伤害单据 submit)、:176 关卡末行(clear_inventory 随库存轴 2026-09-15 下线→通关结算指路冒险结构;:105 已自带待复核注记/:222/:252 系 OQ/ADR 历史记录不动);③06-待办清单新登记「旧行为 MC 行为锚全数作废——重锚归数值批」(现状/归属 M-4/状态三段式;用户确认系影响数值难度重要变量)。闸=gdd_lint 对基线零新增(8 文件 2 存量)+合并后主区冒烟 783/0 三闸过(run_all/probe 零行为改动不跑——纯文档+注释批)。
373. **内容数据驱动扩展批任务书 v1.0 落籍(2026-10-06,用户令「生成任务书+改写 roadmap」;worktree g-plan2-taskbook-ext 分支 taskbook-datadriven-20261006 单提交 6f9e010,主区 merge --no-ff 52c8bea,worktree 已清;纯文档零代码零测试)**:继台账 369 调研落籍后的盘问轮裁决全落——架构模型定稿=发布订阅(结算管线同步 emit 事件→EffectEngine 遍历持有集匹配订阅→执行数据行声明的效果;非代码级插件非拦截器链,仅伤害单据一个改写窗口按声明序施加);用户八裁决 R1-R8 全录任务书 §二(含 R4 旧 23 挂点枚举删除/first_dig_spell 与 terrain_dig_double 退化条件行/R5 范围判据=现有实现全改造·06 在册只登记〔curio_roll/shop_purchase/gp_settle 三事件〕/R7 一个迭代四模块垂直切不分批/R8 术语纪律=事件 topic·效果类型·组合规则,禁 hook/合并律/挂账自造词);词汇表定稿=实施 17 事件(扫雷 5/战斗 6/轮结算 3/抽取经济 3)+效果类型 16+组合规则 5(加法/乘法/取真/按序改写/按序消耗)+fact 条件表 ~15;23 挂点逐行移植映射表+秘宝六件迁移落点全列(等价性对拍底单);数据行形态 on/when/do+存档零改动+护栏五条全保留(MINE_HOOKS 改同义校验);T0-T7≈4.5d 软盒、零待裁点、🔴 契约 5 条(存档零破坏/MC 对拍逐位等价/确定性/护栏保留/worktree 脏件)、停机点 S1 首流派对拍 S2 批末闸、代拍板白名单 4 项;**排期=迭代 17 卡⓪头卡插队(用户裁)**,原①-④卡顺延任务书与裁点原样保留;roadmap 插队行+06 提案条目换代「已立项待 U0」+疑似缺陷条保留。开工门=U0 用户发令。
373. **M4 数值批任务书 v1.1 案C增补(2026-10-06 用户问「文档改完可否出任务书转迭代」→考证=任务书 v1.0 已在(任务书-M4数值批-2026-10-05.md,编入 roadmap 迭代 17 卡②待 U0),增补而非新写;worktree g-plan2-m4tb11 分支 m4tb-v11-20261006 单提交,主区 merge --no-ff 0bfaef7,worktree 已清)**:①任务书 §2.6 新增案C 三事实——F18 行为序换代(案C 7ef18ac/战斗结算 v0.26)、F19 旧行为 MC 锚与对拍锚全作废(06 2026-10-06 条正主;四带复算跑批未发起零沉没成本)、F20 难度走向预判(案C 主角更安全=挖掘期不再先手致死+保底先手,通关率预期上行;越带归 R1 呈报禁自动调);②T0 推算稿四件→五件(第五件=对拍锚按案C 新序重推导;0.75→1.0d,合计 6.0→6.25d,切分点 T4 末不变=段一 T0-T4≈4.5d/段二 T5-T8≈2.0d);③T5 读数卡 T6 四带复算注明案C 新行为首采立新锚(注意:MC 复算代号 T6 在 T5 读数卡内,卡片 T6=damage_probe 修复——增补时锚点写错卡被断言拦下一轮改正);④基线纪律注换代(master 7d3e88fc/冒烟 783/0/run_all 17 套);⑤§10 留痕+3 条(06 正主条/编排器暂存闸载体)+§11 版本记录节新立;⑥06 状态行+roadmap 迭代 17 卡②行同步 v1.1 口径。闸=gdd_lint 对基线零新增(纯文档零代码零测试)。**转入迭代就绪态:待用户 U0 开工令+发令时顺带裁切分(整批 vs T4 末切段)**。
375. **批次工作流标准清单固化进 CLAUDE.md(2026-10-06 用户确认 A 案「整条链成文」;worktree g-plan2-workflow-checklist 分支 doc/workflow-checklist 单提交 8438d4c,主区 merge --no-ff,worktree 已清;纯文档零代码零测试)**:起因=用户问 goal 执行日志「先读两份在册记忆+看 smoke 目录与 sim-data README」系何意→三轮问答厘清现行流程(在册记忆=既往事故教训防重踩;看 smoke/sim-data=定基线跑法;非 TDD 而是「规格先行、测试随批」)→用户确认流程无问题并选 A 案固化。CLAUDE.md 新增「批次工作流标准清单」节(插于分支纪律与硬性红线之间):十三条链路五段=开工前三步(先检索后提问/任务书全列备选案/用户发开工令才动手)+环境与基线三步(worktree 拷导入缓存/改码前基线三查/涉数值先采改前读数)+实施两步(新功能必配新测试/验收改动先行声明)+收口四步(批末四闸全绿才合并/合并后主区全量复跑/会话收口落记/实机目检归用户+中间产物吸收即死);每步附既往事故出处;定位=总索引,与细则冲突以细则为准。闸=gdd_lint 不适用(纯文档零测试)。
376. **迭代17四卡18项裁点全裁落文(2026-10-06,用户在本会话逐卡裁断:卡①P4乙否决推荐其余按推荐/卡②P1甲其余按推荐/卡③卡④全按推荐;worktree g-plan2-rulings4 分支 rulings-iter17-cards-20261006 单提交 de44416,主区 merge --no-ff d5df1f6,worktree 已清;纯文档零代码零测试)**:四份任务书 §8 待裁点逐项裁决回填——卡①敌人行集多行批 P1甲(每行各自 unit_count·行集总数≤4·UNIT_COUNT_MAX 改单种数语义)/P2甲(floor 版退役全仓统 ceil,工作日志 312 待裁销号)/P3乙(投放 L2 教学位混编行巨蜘蛛1+钩爪恐魔1·行值 provisional·MC 取证先报批)/P4乙(**用户否决推荐甲**——Boss 行集校验同样放开;知情代价=半血解锁/难度带读数面可被 Boss 行内容变量影响;本批零内容投放不变、Boss 多行内容投放归后续内容批、节奏重测义务 07 在册);卡②M4数值批 P1甲(维持 2 场·magnitude 终值当量锚复算 [60,85] 带内落定随出口追认)/P2甲(不对称有意落文设计立场零改动)/P3甲(钥石 3-3-3·2-2-3 转正)/P4甲(不立直购价维持次数阈值单一渠道);卡③暂停层 P1丁/P2甲/P3甲/P4甲;卡④生涯设计 P0甲/P1甲/P2甲(N=20/50 实装期定)/P3甲/P4甲/P5甲;roadmap 四行换代「✅ 裁点全裁+开工=U0」+06 状态行全收;**迭代17五卡全部零待裁点**(卡0 早零裁点),发射 prompt 四段交付 chat,用户逐卡串行贴 goal。
377. **M4 数值批移批迭代 18(2026-10-06 用户令「不要影响迭代17,放到迭代18中」;worktree g-plan2-m4move 分支 m4-to-iter18 单提交 c38489a7,主区 merge --no-ff ed38c54,worktree 已清)**:缘起=用户质询「迭代17已在另一会话开发且编排封板,你的修改是否影响别人开发」——查证=iter17dd worktree(⓪数据驱动扩展头卡在飞,基线 7d3e88f 零提交)与我的改动执行路径零交集但 roadmap/06 共享文档构成合并冲突候选+②M4 行被我 v1.1 增补时提前改写(封板越权);用户裁=移批。落面:①roadmap 迭代 17 删 ②M4 行(余 ⓪①③④,③④卡号维持原号不重排=零影响在飞引用),行尾新立迭代 18 行=M4 全量内容原样迁移(含 v1.1 案C 增补+用户四裁点全裁注记 P1甲/P2甲/P3甲/P4甲——该注记系并行会话 d5df1f6 迭代17四卡18项裁点全裁落籍所加,迁移时原样保留),前置列改「迭代 17 出口」;②任务书归属行改迭代 18;③06 五处「迭代 17 卡② M4 数值批」状态行改「迭代 18」+移出注记。**台账撞号史实**=master 现存两个 373(并行会话 373=数据驱动扩展任务书 v1.0、本线 373=M4 任务书 v1.1——本线未提交行被并行快照 9c6d5e2「原样落籍零丢失」吸收所致),不改史只登记;下个空号=377。闸=gdd_lint 对基线零新增(纯文档)。**现行编排态**=迭代 17(⓪①③④,iter17dd 在飞)→ 迭代 18(M4 数值批,任务书 v1.1+四裁点全裁,开工=U0 待发令)。
379. **生涯界面设计提纲批完成(2026-10-06,迭代 17 卡④纯设计批——零代码、零数据面、零测试执行;worktree g-plan2-iter17-career 分支 iter17-career-20261006 基点 fc4dbde,提交 10df8ba 加批次收尾提交;本条为编排会话预配号,落籍序以合并为准)**:设计提纲写成正式设计文档 design/gdd/systems/跨局循环/生涯.md v0.1(状态=范围草案,2026-10-06 用户裁 P0 甲案)——五节写全:信息架构(主菜单一级入口与营地平级=P1 甲,局内不放入口、生涯内零跳转=P4 甲)、承载内容清单(跨局汇总/历史冒险回看/图鉴三段逐项标数据源与可行性,历史回看=P2 甲每局一行摘要加扩容加补用时埋点,图鉴=P3 甲敌人优先、奖励格图鉴只登记不激活,单局明细由 settlement_review_overlay 复活承接=P5 甲)、与既有界面的关系(营地/暂停层/结算屏/帮助手册/图例五界分工矩阵)、分期实装建议(期一汇总页/期二历史回看/期三图鉴,均为另行立项不预占排期,实装批前置义务=对齐迭代 16 UI 基线与 N 终值读数、用时埋点口径呈报)、待裁点(新发现 P6=营地底栏「最近冒险」条带去留,三案全列含淘汰依据,建议期二撤下归生涯——该条带与生涯历史回看读同一份存档摘要且拼行无上限,扩容后会把底栏撑爆,是本批复核发现的实际耦合)。任务书 §2 十条现状事实 F1-F10 逐条对照代码静态复核全绿(回看退役三处注记、settlement_review 遗留件在盘无引用、recent_summaries 现役 cap=10、用时零采集点、终身计数域缺失、营地最近冒险清单渲染行等全实证;一处既有滞后顺带记录=registry 存档条目版本注记停在 v4 而代码已 v5,不属本批范围移交后续对齐批)。同批落:02-系统清单.md 根索引补生涯行+CAREER 代号行+v1.12 版本行、06 生涯条状态行改「设计提纲已成文待评审」、roadmap 迭代 17 卡④行改已交付待评审、出口报告=design/qa/iter17-career-exit-report-2026-10-06.md(完成定义五条判定+事实复核差异记录+提交哈希)。**下一步待用户=评审设计提纲**(评审时随裁 P6);实装批另行立项。
380. **暂停层只读入口批完成(2026-10-06,迭代 17 卡③功能性 UI 交互批——纯呈现零数值改动=零 MC;worktree g-plan2-iter17-pause 分支 iter17-pause-20261006,基点 44328b1,两会话接力:前任会话完成 T0/T1+组 B 代码后因额度中断,续跑会话收尾组 B 跑闸+T3-T5;本条为编排会话预配号,落籍序以合并为准)**:局内暂停层交付——战斗屏 HUD 右下角与关卡地图屏顶栏各一枚「暂停」常驻角标(P1 丁,debug 角标同形制紧凑钮;主菜单不误现),点击开只读层(P2 甲=登记 modal_stack 登记册设置层同档带 dim 遮罩、确认弹窗之前),层内=钥石余额徽+属性锻造三行已购等级+道具工坊六行解锁态+天赋树已购概览+「继续」关闭钮(P3 甲,行序复用营地屏同序),零购买零切换零写通路。badge 按 Q10 甲工厂化:UiKit 新增 KeystoneBadge 工厂件,营地顶栏钥石徽本地拼装同步迁工厂调用(观感零变化,消单点重复);零新素材零新色值零新字体。守卫=其他模态开着两角标置灰不可点(modal_stack 新增 has_open_excluding 排除式开态查询——地图屏自身开态不计;组合根 _on_pause_badge_pressed 处理器兜底+_sync_pause_entry 单一同步点挂模态开合单口与屏级互斥口五路径)。断言四面=ui_struct(pause 结构+只读性契约〔游戏语义信号十二名清单巡检,白名单外零连接,合法连接恰 2〕+零动效契约〔子树零 AnimationPlayer+源码零 tween〕)+ui_input case⑯(角标真点击开层/锁期挖掘零穿透/关后恢复无残留——R3)+ui_click(战斗屏开合守卫+地图屏一次性 case)+ui_contrast(钥石徽深墨/烛光黄对)+冒烟投影一致性 5 断言(展示值==MetaProgression 访问器逐项——R4)。续跑首轮两处 L1 探针红均系断言口径(全集巡检误判引擎布局生命线连接/域恰 2 枚时零无旗格可取),修正一轮全绿无复发。闸=冒烟 788/0(基线 783/0,+5 本批)+run_all 17 套+probe_gate --click 全绿+ui_layout exit0+doc 三闸零新增;存量移交两项(非本批产生,主区同红)=熵增闸 design/diagrams 越界〔00712d5 总图批落籍未同批修白名单〕+06/07 gdd_lint 存量注记红〔本分支零触碰〕。代拍板五项=关闭钮「继续」/层内行序营地同序/角标文案与落点/断言 case 命名/巡检信号清单(目检清单 F 节追认单)。出口报告=design/qa/iter17-pause-exit-report-2026-10-06.md;**人闸=用户实机目检** design/qa/iter17-pause-human-gate-checklist-2026-10-06.md(A-H 八节,重点=双屏入口/守卫态/只读性/零动效/排播队列排空副作用确认项 D2——开层瞬间待播明细行瞬时入带与「暂停」直觉之差系既有弹层同款行为,待用户确认可接受)。
381. **迭代18规划批完成(2026-10-06,用户令——纯文档零代码零测试;worktree g-plan2-iter18plan 分支 iter18-plan-20261006 单提交 0d80626,主区 merge --no-ff 018435e,worktree 与分支已清)**:roadmap 迭代 18 重组——⑥M4 数值批移 Alpha 阶段最后=收官卡(门改「迭代 18 内容卡①-⑤出口——重锚窗口须收尽全部内容批行为变更」;标题增二次令注记=内容补全先行、统一数值调整殿后,内容卡若溢出后续迭代则本批随之顺延);新立五卡:①奇物内容补全·文档先行(charge 补件设计——实查 feats.tres 现恰 3 件〔整备军备/铁壁整备/厚积薄发,表注释自证〕;06「资源两个新种类入池」条收口核对——实查刷新次数〔treasure_items.tres 三选一刷新件行〕与专长获取门票〔shop.tres+adventure_table.gd 门票行〕均已随迭代 15②/三选一刷新批入池、该条现状文本滞后即日收窄;本卡纯文档零代码,落地批=纯 .tres 数据行估 0.5d 内,门=文档出口+用户裁件+迭代 17 卡⓪落籍避表结构撞车)/②呈现优化六件(与迭代 16 语义零重合=16 系样式对齐、本批系内容与观感改版,动的是 16 落好的 token 单点;(a) 流派名三处+档位呈现三路待裁/(b) L1 直画观感/(c) 高墙阴线/(d) 残余对比度三处/(e) L2L3 棋盘观感开工先定性素材轴 vs UI 轴/(f) 关卡节点图展示改版先出「哥布林弹珠」参考调研+方案人闸;随批义务=07⑮ 渲染像素五闸补跑)/③武器锻造系统设计提案(playnote 2026-10-06 用户提案=攻击力提升改造武器锻造〔剑/长枪/法杖×穿刺/魔法+轻甲→重甲/魔法甲〕,纯文档,06 新立专条,实装批另行立项,数值框架 provisional 终值归⑥)/④生涯界面实装(按卡④提纲 design/gdd/systems/跨局循环/生涯.md v0.1 实装,门=用户评审提纲+设计定稿)/⑤混编遭遇首批投放(07「后续内容批义务」落地,门=迭代 17 卡①落籍;读数义务随批登记 07、MC 取证跑批顺延⑥收官批统一执行);06 状态行七处随迁+07 混编义务编入注;同批用户裁决落文=B 奇物内容补充先文档(零代码结论成立)、C 呈现优化立项(与迭代 16 零重合)、D 资产升档优先级再降维持挂起(06 增降级注+playnote 立绘批评记为重启输入)、F 道具重设计同 B 先不处理、G 成长曲线/H L1 第二节点暂不讨论留 playnote;遗留提示=A 菜单开局传参缺陷〔main.gd:475 只传四键,本会话代码复核属实〕未入迭代 18(用户未议)——将来修复须排在⑥M4 之前,否则案C 后重锚再作废一次;**下一步待用户=讨论迭代 18 各卡任务书**。
382. **迭代18增卡⑦新冒险种子随机化(2026-10-07,用户令——纯文档零代码零测试;worktree g-plan2-seedcard 分支 iter18-seedcard-20261007 单提交 997bcc9,主区 merge --no-ff 7a7d873,worktree 与分支已清)**:用户指出现状=每次展开冒险种子固定不随机(实查 main.gd:1210 _seed_value() 调试种子框为空时硬编码返回 42——每次新冒险同一种子全程可复现;同日答用户问=核心循环全固定的 roguelike 不存在,固定种子只在每日挑战/调试特设模式)→ 卡⑦=新冒险主种子改随机生成(默认分支),调试浮窗种子输入框保留手动覆盖(_seed_value 唯一消费点不变,迭代 15 卡①既有读取面);三面零影响考证在册=断点续玩存档已载 master_seed 回填〔main.gd:447 现役〕/冒烟·MC·探针全链显式传种子〔锚零作废〕/单种子内行为不变、与⑥收官批零耦合排序自由;裁点两项随任务书=①首次冒险是否也随机〔现行 42+固定模板 0=首次冒险全程复现的教学态;A6 首遇教学位系节点模板面不受种子影响,但板面雷位/资源摇号会随种子变〕②种子是否进 UI 展示〔局摘要已携带 master_seed,展示=分享/日后每日挑战位候选〕;⑥M4 门同步改「迭代 18 内容卡①-⑤⑦出口」;**下一步待用户=迭代 18 任务书讨论**。
383. **内容数据驱动扩展批完成(2026-10-06/07,迭代 17 卡⓪——效果引擎框架落地;worktree g-plan2-iter17-dd 分支 iter17-dd-20261006 基点 fc4dbde,五提交 7d157b3/225765f/e28a6cb/a33ddaf/6e7b5d1,两会话接力〔前任完成 T1 效果引擎框架+16 发射点与 T2 词汇落码后额度中断,续跑会话接手 T3 断点三脏文件收口并完成 T4-T7〕;本条为编排会话代记——预配号 381 撞号改登 383,381/382 系并行迭代 18 规划批与增卡⑦两批先占,先例同台账 374)**:内容效果行为从结算代码硬编码搬进数据行「订阅事件 on+条件 when+效果 do」三字段,EffectEngine 发布订阅解释器统一执行——16 发射点埋点+19 行 23 效果类型+组合规则 6 条+改写窗口单点;专长 27 行全量迁 triggers 订阅形态、旧 23 挂点枚举消亡、伤害控制器 13 处消费点拆除、秘宝六件按 id 硬编码清零(淬毒/偏运经 reward_roll/晨令/惊巢/殉爆/掘进蓄能受理闸)、令牌兑付 match 收敛进效果类型路由表、树规则键同面、文案表值化、断言面随迁净增 17;续跑承接修正四处(perfect_defense 事实出域/has 算子语义/漏写 _harmful_adjacent/counter set 键 bool 吞零)。闸=冒烟 800/0(基线 783/0,+17 本批)+run_all 17 套+probe_gate 含 click 全绿+MC 二档对拍 40 局同种子逐位一致(pre/post 锚 83000 段留盘 sim-data/,判据两套全过:确定性复放与冒烟=逐位、MC 统计量=同带)+doc 三闸/熵增存量红零新增。文档换代=奇物 v2.8/秘宝 v1.0/敌人系统 v0.14+registry 两件+06 收口+roadmap 卡⓪行换代;出口报告=design/qa/iter17-datadrive-exit-report-2026-10-06.md(代拍板八项随报告)。遗留=掘进蓄能积点模判定留编排器侧(发射点施加架构下无法行内表达,行为逐位一致,彻底行内化归词汇表扩展批裁决)+主动件 kind 词族全量改名不随批(零行为收益)+实机目检归用户。
384. **迭代18卡⑦两裁点全裁+调试浮窗目标态落文(2026-10-07,用户令——纯文档零代码零测试;worktree g-plan2-seedrule 分支 iter18-seedrule-20261007 单提交 56d996c,主区 merge --no-ff 49ee98f,worktree 与分支已清)**:用户裁种子两裁点=①首次冒险维持固定种子(教学态可复现)②测试脚本与调试接口显式指定种子(冒烟/MC/探针全链显式传种子零影响)③种子不进玩家 UI——玩家界面入口随机生成;调试浮窗目标态同令落文=独立于整体界面的最高层浮窗(对局中也可开——**修订迭代 15 卡① P3 甲「仅开始菜单可开·对局不可达」裁决**)+DS_DEBUG=1 调试态默认打开+新增当局数据只读区块(当前局种子/关卡/节点/HP/GP/钥石——种子唯一查看位);卡⑦随之扩为「种子随机化+调试浮窗升级」双件估≈1d。**现行考证六点(2026-10-07 实查)**:入口=开始覆盖层角标 main.gd:292-293(DS_DEBUG=1 才点亮——现行非「默认打开」,仅入口点亮);门禁=main.gd:1189 `if not _start_overlay.visible: return`(对局中不可达);形态=Dialog 走 ModalStack 模态栈登记(非最高层,登记序在确认弹窗之前);初始 visible=false(debug_overlay.gd:40);五区块=胜利演出/种子输入〔默认文本 42〕/数值滑条/批量模拟/两层调试入口——无当局数据面;对局发起随开随收〔main.gd:609〕。任务书待裁点五项在册(最高层 vs 模态栈登记制/输入吞噬边界/随开随收改向/ui_tune_probe 断言换代/入口形态)。同批核证:迭代 17 卡⓪数据驱动批已落籍 master e5354366〔台账 383,381/382 系本会话迭代18两批先占撞号自解〕——迭代 18 卡①落地门「卡⓪落籍」自然解除。
+3 -3
View File
@@ -149,7 +149,7 @@ Input(鼠标)→ D1 输入翻译 → 意图对象 → A2.settle_batch(唯
A2 ──cell_revealed / flag_judged / round_end(棋盘路径)──▶ B1(轮 facts 缓冲)
A3 ──round_end(stopped 直发,payload 同构)──────────────▶ B1
B1 ──notify_settlement_done(next_round_mode) / notify_combat_end──▶ A3
B1 ──apply_effect / apply_damage / grant / stock / advance...──▶ B3/B2/B4(唯一调用方)
B1 ──apply_effect / apply_damage / grant / 伤害单据 submit…──▶ B3/B2/B4(唯一调用方;段内伤害序=主角先手→逐敌还手→地图账殿后〔案C 2026-10-06〕)
B1 ──install_board / retire_board──▶ A2 B1 ──generate(L,D)──▶ A1
D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB display_name
```
@@ -173,7 +173,7 @@ D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB
→ C2 begin_run:RngService.set_master_seed()(唯一接线方;两流计数器全零前提)
→ B1.begin_battle(encounter):set_reload_gate(true) → B3 开域 → B2 spawn → A2 install_board(A1.generate) + B4 roll_board(恰一次)→ A3 notify_round_start
→ 挖掘循环 …… → battle_over 清理序列 → set_reload_gate(false)
→ 关卡末:level_clear()(clear_inventory 恰一次 + 快照计数)
→ 关卡末:通关结算(钥石/GP/专长 level_clear 渠道——现行语义归 冒险结构 GDD;原 clear_inventory 随库存轴下线退役 2026-09-15)
```
---
@@ -187,7 +187,7 @@ D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB
| D1 → A2 | 意图经 `settle_batch(intents)` 提交;不直调 A3 | 单意图帧收集;stop 经批次委托 | 语义序仲裁 + voided 零副作用 |
| A2 → A3 | 挖/插/拔 = 先棋盘面判定后 `try_spend`;A2 不可自行扣减 | 相位判定两侧一致(同一矩阵) | 原子事务(余量+扣减+仲裁一体) |
| A2 → 下游 | 只外发三事件,payload 字段封闭(digit 恒真透传 / reward_eligible / variant_ids) | 增删事件 = 接口漂移 | 发射面封闭 + 规范序 |
| B1 → B2/B3/B4 | 全调用面集中 B1;调用序钉死(query_attack→apply_damage→advance;先兑付后衰减) | 禁第二调用方(静态扫描域:API 符号命中文件 ⊆ B1 文件集) | 恰一次编排纪律(roll_board/decay/清理全序) |
| B1 → B2/B3/B4 | 全调用面集中 B1;调用序钉死(按摇定技能行兑现→apply_damage→commit_action;先兑付后衰减;段内伤害序=主角先手→逐敌还手→地图账殿后〔案C 2026-10-06〕) | 禁第二调用方(静态扫描域:API 符号命中文件 ⊆ B1 文件集) | 恰一次编排纪律(roll_board/decay/清理全序) |
| 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 致命 |
| A1 → A2 | Board 产物 class_name 数据契约 | install 四不变式校验(violation = 拒绝 + 五类诊断枚举) | 生成期合法性闸(R₀≠S / clearable / min_safe) |
+1 -1
View File
@@ -8,7 +8,7 @@
1. 开局一张新雷图,每轮发给你若干行动点。
2. 用行动点做排雷决策:挖开安全格,拿增益和道具;控制(插旗)巢穴,削弱里面的怪物;点错惊动巢穴,怪物反而变强。
3. 行动点用尽——或者你主动停手——这一轮结束,轮末自动结算:你这一轮扫雷攒下的因,逐行兑现成战斗的果。你拿的增益打了出去,你控制的巢穴变成怪物的虚弱,你惊动的巢穴变成怪物的先手。
3. 行动点用尽——或者你主动停手——这一轮结束,轮末自动结算:你这一轮扫雷攒下的因,逐行兑现成战斗的果。你拿的增益打了出去,你控制的巢穴变成怪物的虚弱,你惊动的巢穴变成怪物的警觉(护甲变硬、伤害账轮末才落)。
4. 敌人没死光、你还活着,就进下一轮,同一张图接着挖;图开完了,发清图奖励,换一张新图接着打。
所以自动战斗不是过场,是阅卷:每一行结算都能指回你刚才的哪一步棋。
+3
View File
@@ -52,6 +52,7 @@
| 文件 | 一句话概要 | 状态 |
|---|---|---|
| `元进度.md` | 跨局成长(旧体系未单独成文) | 已定稿·已实现 |
| `生涯.md` | 主菜单一级的局外只读界面——跨局汇总、历史冒险回看、图鉴承接(冒险中数据回看的唯一承接处,P-C7 裁决) | 范围草案·待评审 |
### 表现与支撑(`systems/表现与支撑/`)
@@ -99,6 +100,7 @@
| 冒险循环 | 难度曲线与Boss | `DIFFICULTY_CURVE` | c3 |
| 冒险循环 | 奇物 | `ADVENTURE_CURIO` | `ADVENTURE_FEATURE`(v1.0)→ `ADVENTURE_REWARD`(v2.0,v2.4 退役) |
| 跨局循环 | 元进度 | `META_PROGRESS` | c4 |
| 跨局循环 | 生涯 | `CAREER` | —(新立无旧代号,无代码实现面) |
| 表现与支撑 | HUD框架 | `HUD_FRAMEWORK` | d1 |
| 表现与支撑 | 数据配置 | `DATA_CONFIG` | d2 |
| 表现与支撑 | 存档序列化 | `SAVE_SERIALIZATION` | d3 |
@@ -137,3 +139,4 @@
| v1.9 | 2026-10-05 | 《奖励》改名为《奇物》并升 v2.4:顶层定名 Wondrous Item(DND 魔法物品九分类中的兜底杂类,官方中文译名「奇物」)。文档树冒险循环行改名;命名对照表 `ADVENTURE_REWARD` → `ADVENTURE_CURIO`(**不用 `reward_*`**——`reward_pick` 流 / `reward_node` context / `reward_preview` kind 已占用该词族) |
| v1.10 | 2026-10-05 | 《奇物》v2.5:第三类定名「资源」(资源偏泛,故在命名出处节写死判据句——给的是可消耗或可重掷的余量,不是属性永久抬升);回复归属定案留在本类不拆第四类;修复 1.5 段末与渠道轴标题粘连 |
| v1.11 | 2026-10-05 | 《奇物》v2.7 三个子节点正式定名:专长(Feat)/ 属性值提升(ASI)/ 资源——去「类」字后缀,此前是描述式叫法不是专名;新增 1.6 节「三层结构与命名」,定玩家可见的三层(奇物 / 三个分类 / 具体单件),并明确命名与呈现是两件事 |
| v1.12 | 2026-10-06 | 生涯设计立项批(迭代 17 卡④,纯文档):新建 `systems/跨局循环/生涯.md` 设计提纲 v0.1(信息架构 / 承载内容清单 / 与既有界面关系 / 分期实装建议 / 待裁点五节;状态=范围草案待评审——P0-P5 已裁结论落文,新发现待裁点 P6 营地最近冒险条带去留)。文档树跨局循环补行 + 命名对照表补 `CAREER` 行(无代码实现面,代号随实装批对齐) |
+63 -21
View File
@@ -2,6 +2,32 @@
本清单是全项目待办事项的**唯一登记处**:各系统文档不再自建「待办」条目节,只留一行指路存根;新增待办事项一律直接登记本清单。条目按四个循环分组,组内按系统分节;每条事项一个四级标题,其下用粗体属性名成段——**现状**(现状与失义原因,自各系统文档原样搬运、措辞不改;跨文档重复条目合并为一条,登记在建议归属主责方名下,其余来源在现状中注明出处;相关但不同面的条目各自保留,现状末尾互相指认;搬运时仅将原文中的「本文 / 本系统」替换为对应系统名,并把相对链接改写为本文件位置可用的路径)、**归属**、**状态**。事项解决后**从本清单移除**(2026-09-18 用户拍板改口径,原"改状态留痕"废止):去向与依据登记当批台账与 active.md 快照,git 历史即留痕。
#### 旧行为 MC 行为锚全数作废——重锚归数值批(2026-10-06 登记)
**现状**:案C 地图伤害账殿后批(git 7ef18ac,台账 371)改变每轮结算行为序——授予段不再兑付任何伤害(伤害形态单据暂存至战斗段末,段内序=主角先手→逐敌还手→地图账),主角死亡短路语义随之换代(「授予段伤害致死短路先手」路径消失)。既有全部 MC 行为锚与对拍锚所锚行为已不存在,**全数作废**;新段内序断言已入冒烟闸。按 sim-data MC 缓存层规则(无数值调整禁重跑),重锚不在改动批执行。
**归属**:M-4 数值批(用户 2026-10-06 确认此为影响数值难度的重要变量)。
**状态**:待数值批触发时重采;重锚前一切 MC 旧读数只作历史存档,不得与新行为对拍。——**已增补进 roadmap 迭代 18 M4 数值批〔2026-10-06 用户令自迭代 17 卡②移出——不影响 17 在飞开发〕任务书 v1.1(2026-10-06:T0 推算稿第五件+T6 四带复算按案C 新行为首采;design/research/任务书-M4数值批-2026-10-05.md)**
#### 内容数据驱动扩展批——已立项迭代 17 头卡(2026-10-06 登记,同日全裁)
**现状**:调研报告落籍 master(=[研究-内容数据驱动扩展架构-2026-10-06](../research/研究-内容数据驱动扩展架构-2026-10-06.md))——用户两问结论:①改已有物品数值/名字/稀有度/投放渠道=**纯配置成立**(全内容族 `.tres` 数据表+schema 加载校验+悬空引用致命);②换全新效果行为/加带新效果的新物品/加机制类新专长=**现状必改代码**(专长 23 挂点封闭枚举 `feat_table.gd:36-67`+求值段逐个 match 展开 `battle_orchestrator.gd:101-179`+消费点约 24 处散布;秘宝被动件按 id 硬编码六件;效果文案硬编码三处)。项目内已有完全数据驱动范本=技能池(`skills.tres` 加行+`enemy.tres` pool 引用零代码)。mod 成熟游戏四共性(Minecraft 数据包/Factorio 原型/RimWorld Defs,前两者官方文档核对):内容=数据+机制=通用解释器、语义事件时机+内容订阅、条件通用词汇复用、加载期注册校验闸。
**裁决实录(2026-10-06 用户盘问轮逐条裁定,全落任务书 §二)**:案乙当选;架构=发布订阅同步 emit(事件=`.on("xxx")` 的 topic;订阅后逻辑=效果类型;叠加=组合规则,禁自造词);仅一个改写窗口不做拦截器链;一事件多订阅常态、冲突由 5 条组合规则封死;旧 23 挂点枚举删除(2 个退化条件行);**范围判据=现有实现全改造(含 luck_coin 经 reward_roll 迁移+文案表值化),06 在册待办只登记不实施**(curio_roll/shop_purchase/gp_settle 三事件登记暂不做);框架先行发射点全埋;一个迭代四模块垂直切一次合并;词汇表定稿=实施 17 事件+效果类型 16+组合规则 5。
**归属**:迭代 17 卡⓪(头卡,用户令插队——①-④卡顺延);任务书=[任务书-内容数据驱动扩展批-2026-10-06](../research/任务书-内容数据驱动扩展批-2026-10-06.md)(T0-T7≈4.5d,零待裁点)
**状态**:**已实施完成(2026-10-06 当日立项当日落地——worktree iter17-dd 分支待合并)**:T1 框架(效果引擎+16 发射点,commit 7d157b3)→T2 词汇落码(225765f)→T3 专长 27 行迁移+旧挂点枚举消亡(e28a6cb)→T4/T5 秘宝六件+掘进蓄能受理闸+令牌兑付收敛(a33ddaf)→T6 回归闸全绿(冒烟 800 项 0 失败、单元 17 套、探针闸含 click、MC 二档对拍 40 局同种子**逐位一致**——post 锚 `sim-data/runsum_iter17dd_post_{off,formed}_n20_20261006.jsonl` 留盘);出口报告=[iter17-datadrive-exit-report-2026-10-06](../qa/iter17-datadrive-exit-report-2026-10-06.md)。遗留人闸两项随报告呈报(dig_charge 积点模判定留编排器侧=词汇表边界;主动件 kind 词族全量 rename 不随批)
#### 菜单开局未传同调装配与局外树规则——疑似缺陷待复验(2026-10-06 登记)
**现状**:`main.gd:475` `_start_adventure` 参数面只传 `hero_override`/`first_script`/`treasure_unlocked`/`shop_mode` 四键,未传 `attunement`/`attune_refresh_y`/`tree_rules`;runner 受理面存在(`adventure_runner.gd:128-137`,缺省空数组=白板开局);营地装配持久化于 `save.attunement_equipped`(`meta_progression.gd:354-366`)但呈现层开局无传参调用——**主菜单开新局时,营地装配的同调件与局外天赋树规则键疑似不生效**。冒烟未拦系 smoke_all 直呼 runner 参数面(`smoke_all.gd:4304` 有传参)跳过了呈现层。2026-10-06 数据驱动架构调研顺带发现,本人已复核传参面代码,未实机复验。
**归属**:缺陷修复 mini-loop(复验+修复待用户令)
**状态**:待办(疑似缺陷,未实机复验)
#### 双层 BD 延期与备选内容总登记(2026-10-03 立项——任务书退役保险)
**目的**:任务书/整合定稿系中间文档,落地完成后按吸收即死退役——用户令「只删除已完成落地的内容」,本条自承载全部**未落地**内容防丢失(每项自包含,不依赖指针)。
@@ -67,7 +93,7 @@
**回复应在商店内**(用户 2026-10-05 定):回复不是计价物,套不上「计价物不自售」,按默认原则它应当在商店出现。现行 `shop.tres` 货架只有 attack / max_hp / armor / ap 四项,**现状与表格不对齐,须在实施批补上**。
**待拍板/待观察两项**:① ~~资源的命名~~ 与 ~~回复是否属该类~~ **已定(v2.5)=资源,回复留在其中不拆第四类**(它与金币同为即时兑付、判据同源;拆出去第四类只剩两项)。② **专长门票尚未入表**:出现概率 / 配额 / 全局限量三个参数都没有事实源,入池同样受档位结构锚约束。③ **专长总量与档位阈值的匹配——延后复裁**(用户 2026-10-05 定"先不调整"):终局 Boss 不给已定,一局确定性专长次数=终局前 Boss 个数;**三关结构下是两次,加门票最多三次**,而档位阈值是同标签 ≥2 档一 / ≥4 档二——**档二(完全体)在三关结构下几乎不可达**。用户决定不动,理由是**后续会有第四关**,且届时可能另做获取侧调整。**复裁触发:第四关内容批落地后实测,配合仍太少再调。** 先不调≠不成问题,登记于此防忘。
④ **charge 标签件数不足(数据缺陷,独立登记,勿被上条盖掉)**:档二要求同标签 ≥4 件,而 `relics.tres` 里 charge 标签**只有 3 件**——即使获取次数无限,charge 流派也永远达不到档二。这与渠道结构无关,是数据层缺陷。
④ **charge 标签件数不足(数据缺陷,独立登记,勿被上条盖掉)**:档二要求同标签 ≥4 件,而 `relics.tres` 里 charge 标签**只有 3 件**——即使获取次数无限,charge 流派也永远达不到档二。这与渠道结构无关,是数据层缺陷。**编入注(2026-10-06 用户令)**:补件设计编入 roadmap 迭代 18 卡①奇物内容补全批·文档先行(落地=纯 .tres 数据行,新件限现有效果 hook 则零代码)
⑤ ~~顶层命名待定~~ **已定(v2.4)=「奇物」Wondrous Item**:DND 魔法物品九分类中的兜底杂类,官方中文译名即「奇物」,专装"不好归类但有奇效之物"——正好对应三个互不相干的分类。落选:Treasure(偏财物,装不下专长)、Relic(品类惯例,用户否决「遗物」)、全部自造词(进益/造化/机缘/遇获)。**代码词族随之定为 `curio_*` / `ADVENTURE_CURIO`**——原计划的 `feature_* → reward_*` 对齐**作废**:`reward_pick` 流 / `reward_node` context / `reward_preview` kind 已占用 reward 词族,照做会撞车。
**归属**:[奇物](systems/冒险循环/奇物.md)(定义与交叉开关表)+ [node-reward](ux/node-reward.md)(令牌池与奖励面)+ [冒险结构](systems/冒险循环/冒险结构.md)(商店货架保底与货架过滤)+ [关卡节点地图](systems/冒险循环/关卡节点地图.md)(节点类型词表);与上条「双层 BD 延期与备选内容总登记」二期件组相关但不同面。
@@ -82,7 +108,15 @@
**归属**:[奇物](systems/冒险循环/奇物.md) 调参表 + [冒险结构](systems/冒险循环/冒险结构.md) 共享池账本节;数值所有权归 [难度曲线与Boss](systems/冒险循环/难度曲线与Boss.md)
**状态**:待排批——须在可跑冒烟的迭代批次内完成
**状态**:待排批——须在可跑冒烟的迭代批次内完成——**实查更新+收窄+编入(2026-10-06)**:两项实已随迭代 15②/三选一刷新批入池(刷新次数=treasure_items.tres「三选一刷新件」行;专长获取=shop.tres+adventure_table.gd 门票行),本条收窄为边界核对与条目收口,**已编入 roadmap 迭代 18 卡①奇物内容补全批·文档先行〔2026-10-06 用户令:先文档后落地,数值只设计不调终值归⑥M4 收官批〕**
#### 武器锻造系统——攻击/护甲成长差异化提案(2026-10-06 playnote 用户提案,同日令入迭代 18)
**现状**:用户提案(playnote 2026-10-06):攻击力提升改造为「武器锻造」系统——① 剑(普通攻击):锻造升级增加攻击力,最高等级附带额外效果;② 长枪/法杖:后续新增武器,攻击类型分别变为穿刺/魔法,同样满级带特殊效果——实现武器间差异化;③ 护甲同理:初始只有轻甲(升级只提 AC),最高等级后可解锁重甲/魔法甲——基础 AC 各不相同、可继续升级、各带不同额外效果。
**归属**:待提案批定(候选=[奇物](systems/冒险循环/奇物.md) 属性值提升分类修订 + [战斗结算](systems/战斗循环/战斗结算.md) 攻击类型轴 + [元进度](systems/跨局循环/元进度.md) 营地柜台锻造经济)
**状态**:已立项设计提案批=roadmap 迭代 18 卡③(2026-10-06 用户令;纯文档零代码,裁点呈用户裁决,实装批另行立项;数值框架 provisional 终值归迭代 18 卡⑥ M4 收官批统一调整)
#### 内部分类禁写入玩家可见面——奇物呈现三处违规待改(2026-10-04 用户立意登记)
@@ -92,7 +126,7 @@
**归属**:[battle.md](ux/battle.md) C 区 + [level-map.md](ux/level-map.md) 底栏 + [node-reward](ux/node-reward.md) 卡面文案;RelicsEngine 求值与档位机制零改动(纯呈现面)。
**状态**:方向已明确(禁写类别),违规改法与档位呈现三路待讨论(2026-10-04 登记,后续展开)
**状态**:方向已明确(禁写类别),违规改法与档位呈现三路待讨论(2026-10-04 登记,后续展开)——**违规三处清除+档位呈现已编入 roadmap 迭代 18 卡②呈现优化批(2026-10-06 用户令;档位三路仍待裁,随任务书呈报)**
#### 奇物命名统一后续——代码标识符与文件名的对齐(2026-10-05 立)
@@ -110,7 +144,7 @@
**归属**:[排雷玩法](systems/排雷循环/排雷玩法.md)(动作语义与 8 向目标规则主责)+ [HUD 框架](systems/表现与支撑/HUD框架.md)(键盘光标与合法性反馈呈现)+ [设置与本地化](systems/表现与支撑/设置与本地化.md)(键位自定义,可选面)
**状态**:待办——排期 **Beta 阶段**(2026-10-04 登记;可行性已核毕,立项时按 roadmap 开卡)
**状态**:待办——排期 **Beta 阶段**(2026-10-04 登记;可行性已核毕,立项时按 roadmap 开卡)。**2026-10-06 增补登记**:暂停层 Esc 快捷通道并入本条随键盘批统一实施(迭代 17 卡③暂停层批 P1 裁决=常驻角标本批落码、Esc 键不单独开通道;批出全屏弹层后本条③「弹层界面现行全鼠标」清单 +1 项=暂停层)
#### 挖掘风险不等式对账破线
@@ -128,7 +162,7 @@
**归属**:随[关卡节点地图](systems/冒险循环/关卡节点地图.md)定稿改键一并裁决
**状态**:部分收口(2026-09-17)——同层多遭遇问题已由关卡节点地图 v1.0 的**节点编号升级**消解(`node_depth` 语义 = 关卡内唯一节点编号,同层不同节点各查各行,键结构零改动);**不设精英 / Boss 编码位**(Boss = 最大编号节点,精英 P2 内容承载)。剩余面继续待办并改归属:同场多敌种(同一编号行集多行)的行集校验放开 ——归属**敌人表行集多行批(战斗侧,排技能池实施批落地后)**(混编伏击上限取值口径面已随 2026-09-20 单轮上限删除消解)。**已编入 roadmap 迭代 17 卡①(2026-10-05——任务书已成文待 U0:design/research/任务书-敌人表行集多行批-2026-10-05.md;前置「技能池实施批落地」已于 2026-10-05 满足〔d3fa887〕,开工门已解,余 4 项待用户裁点)**
**状态**:部分收口(2026-09-17)——同层多遭遇问题已由关卡节点地图 v1.0 的**节点编号升级**消解(`node_depth` 语义 = 关卡内唯一节点编号,同层不同节点各查各行,键结构零改动);**不设精英 / Boss 编码位**(Boss = 最大编号节点,精英 P2 内容承载)。剩余面继续待办并改归属:同场多敌种(同一编号行集多行)的行集校验放开 ——归属**敌人表行集多行批(战斗侧,排技能池实施批落地后)**(混编伏击上限取值口径面已随 2026-09-20 单轮上限删除消解)。**已编入 roadmap 迭代 17 卡①(2026-10-05——任务书已成文待 U0:design/research/任务书-敌人表行集多行批-2026-10-05.md;前置「技能池实施批落地」已于 2026-10-05 满足〔d3fa887〕,开工门已解,4 项裁点已全裁并经 2026-10-06 联审二裁修订:P1甲〔Q8/Q9 补全=每行一骰·RNG 扩签先报批·实例总数≤4〕/P2甲/P3丙〔改裁撤投放——首混编行连同 Boss 多行归后续内容批,投时 MC 取证先报批+难度带读数义务随批登记 07〕/P4乙 Boss 行亦放开·零内容投放不变)**
#### 技能池情境条件触发器
@@ -177,7 +211,7 @@
**归属**:战斗结算与地图战斗资源共裁(数值终值归状态层重设计批)
**状态**:待办(语义已定案,数值未闭合)——**已编入 roadmap 迭代 17 卡② M4 数值批(2026-10-05——任务书已成文待 U0:design/research/任务书-M4数值批-2026-10-05.md;duration 终值与当量锚复算 = 件①,跑批发起前须用户批准)**
**状态**:待办(语义已定案,数值未闭合)——**已编入 roadmap 迭代 18 M4 数值批〔2026-10-06 用户令自迭代 17 卡②移出——不影响 17 在飞开发〕(2026-10-05——裁点已全裁并经同日联审二裁修订:P1甲〔带内落定随出口追认〕/P2甲/P3甲〔转正顺延至重扫读数到账且带内〕/P4甲〕待 U0:design/research/任务书-M4数值批-2026-10-05.md〔v1.2〕;duration 终值与当量锚复算 = 件①,跑批发起前须用户批准)**
#### 单体寻址的接口扩展位
@@ -223,7 +257,7 @@
**归属**:①元进度设计批 + 曲线调参批 ②曲线调参批(现行窗) ③~~秘宝同调实施批~~(已清偿 2026-10-03)
**状态**:已登记(2026-10-01,迭代 10 批随批)——**①②已编入 roadmap 迭代 17 卡② M4 数值批(2026-10-05——任务书已成文待 U0:design/research/任务书-M4数值批-2026-10-05.md;钥石产出重标 + 通关率带重扫 = 件③,跑批发起前须用户批准)**
**状态**:已登记(2026-10-01,迭代 10 批随批)——**①②已编入 roadmap 迭代 18 M4 数值批〔2026-10-06 用户令自迭代 17 卡②移出——不影响 17 在飞开发〕(2026-10-05——裁点已全裁〔2026-10-06 用户令:P1甲/P2甲/P3甲/P4甲〕待 U0:design/research/任务书-M4数值批-2026-10-05.md;钥石产出重标 + 通关率带重扫 = 件③,跑批发起前须用户批准)**
#### 调参批数值点评登记(八型批随批登记)
@@ -231,7 +265,7 @@
**归属**:[难度曲线与Boss](systems/冒险循环/难度曲线与Boss.md)难度曲线调参批
**状态**:待办(随调参批一并裁决)——**已编入 roadmap 迭代 17 卡② M4 数值批(2026-10-05——任务书已成文待 U0:design/research/任务书-M4数值批-2026-10-05.md;五条点评逐条裁决 = 件②)**
**状态**:待办(随调参批一并裁决)——**已编入 roadmap 迭代 18 M4 数值批〔2026-10-06 用户令自迭代 17 卡②移出——不影响 17 在飞开发〕(2026-10-05——裁点已全裁〔2026-10-06 用户令:P1甲/P2甲/P3甲/P4甲〕待 U0:design/research/任务书-M4数值批-2026-10-05.md;五条点评逐条裁决 = 件②)**
#### 基线通关率越带,加难杠杆扫描未执行
@@ -247,22 +281,22 @@
**归属**:元进度设计批
**状态**:部分收口(2026-09-21 元进度实现批再收窄;2026-09-23 换算率标定批再收窄)——**三柜台结构与 provisional 定价已落地**(属性锻造三档血+3/攻+1/甲+1、base 10 公比 150;Boss 两档 L1 5/1·L2 8/2·L3 12/3;工坊六件阈值 1/1/2/2/3/3 按总通关次数——全部读 `data/tables/meta.tres`);换算率三行已投值 6/9/1(同批,冒险条件口径实测,护甲行强条目重测履行);剩余面 = 定价数字与 Boss 两档——**已编入 roadmap 迭代 17 卡② M4 数值批(2026-10-05——任务书已成文待 U0:design/research/任务书-M4数值批-2026-10-05.md;定价数字与 Boss 两档终值 = 件④。注:本条「base 10 公比 150」文本滞后——meta.tres 现行 forge base_price=20(2026-09-22 数值设计批对齿 10→20),随件④收口时刷新)**
**状态**:部分收口(2026-09-21 元进度实现批再收窄;2026-09-23 换算率标定批再收窄)——**三柜台结构与 provisional 定价已落地**(属性锻造三档血+3/攻+1/甲+1、base 10 公比 150;Boss 两档 L1 5/1·L2 8/2·L3 12/3;工坊六件阈值 1/1/2/2/3/3 按总通关次数——全部读 `data/tables/meta.tres`);换算率三行已投值 6/9/1(同批,冒险条件口径实测,护甲行强条目重测履行);剩余面 = 定价数字与 Boss 两档——**已编入 roadmap 迭代 18 M4 数值批〔2026-10-06 用户令自迭代 17 卡②移出——不影响 17 在飞开发〕(2026-10-05——裁点已全裁〔2026-10-06 用户令:P1甲/P2甲/P3甲/P4甲〕待 U0:design/research/任务书-M4数值批-2026-10-05.md;定价数字与 Boss 两档终值 = 件④。注:本条「base 10 公比 150」文本滞后——meta.tres 现行 forge base_price=20(2026-09-22 数值设计批对齿 10→20),随件④收口时刷新)**
#### 解锁界面与钥石呈现的交互形态(残余:暂停层只读入口)
**现状**:视觉终稿半已兑现——营地界面视觉终稿随 M-3 迭代 9 卡⑭落码(石纹全屏底+顶栏铭牌/钥石徽+三柜台列,前置样张闸过审);功能界面(营地入口/CampOverlay 三柜台/A 区顶栏钥石余额常驻/结算屏入账明细)2026-09-21 已落地。**剩余面=局内暂停层只读入口**:现行无暂停层,局内无可暂停查看钥石与解锁态的入口。
**归属**:HUD 批(M-4,批未立项)
**归属**:HUD 批(M-4,批未立项)——已随迭代 17 卡③实施
**状态**:待办(2026-10-03 06 清账批瘦身——视觉终稿半兑现销号,本条仅存暂停层残余)——**已编入 roadmap 迭代 17 卡③(2026-10-05——任务书已成文待 U0:design/research/任务书-暂停层只读入口批-2026-10-05.md;4 项待用户裁点〔入口位置/与既有弹窗层关系/展示范围/减动效联动〕,美术红线=复用现行公共件零新素材)**
**状态**:✅ 代码面已交付待实机目检(2026-10-06,迭代 17 卡③暂停层只读入口批——worktree g-plan2-iter17-pause 分支 iter17-pause-20261006,提交 c08a901/fc9eb1e/d44fdd5+收口笔;P1丁常驻角标/P2甲设置层同档 dim 遮罩/P3甲余额+三柜台进度/P4甲零动效直开直关全落;badge 已按 Q10 甲工厂化入 ui_kit 并同步迁营地钥石徽;机检=冒烟 788/0+run_all 17 套+四探针全绿〔含输入锁 case⑯/只读巡检/零动效契约/钥石徽对比度对〕+doc 三闸零新增;**人闸=用户实机目检** design/qa/iter17-pause-human-gate-checklist-2026-10-06.md——过闸后本条销号;Esc 快捷通道维持本清单键盘/手柄条登记随键盘批办理)
#### 第一关亮墨数字直画观感优化(2026-10-01 T17 目检体感登记)
**现状**:迭代 9 T4 数字承载切换后第一关=亮墨三档直画(白亮字直接印棕色地板、无色牌垫底),机制可读性过闸(用户实机确认三档冷暖可分、凑近与离屏均可读);同日 T17 目检体感「表现和描述一样,但非常难看」——直画字与地板的组合观感待优化。第二/三关米色小牌形态未获同类反馈。
**归属**:呈现优化批(与高墙墙底阴线观感同批裁量;排 M-4 后排,不卡迭代 9 出口)
**状态**:待办(2026-10-01 登记;机制/可读轴零触碰,纯观感轴)。**2026-10-05 注**:迭代 16「UI 设计对齐批」任务书已起草(`design/research/任务书-UI设计对齐批-2026-10-05.md`)——棋盘数字墨三档与色牌垫底属本批 §3-N1 对比度收项面(实查 `board_cell_unit.gd:238/262` 字号公式已合规、`:229-234` 垫牌在位),裁点裁决后随批一并呈报。本条维持待办。
**状态**:待办(2026-10-01 登记;机制/可读轴零触碰,纯观感轴)。**2026-10-05 注**:迭代 16「UI 设计对齐批」任务书已起草(`design/research/任务书-UI设计对齐批-2026-10-05.md`)——棋盘数字墨三档与色牌垫底属本批 §3-N1 对比度收项面(实查 `board_cell_unit.gd:238/262` 字号公式已合规、`:229-234` 垫牌在位),裁点裁决后随批一并呈报。本条维持待办。**2026-10-06 编入注**:已编入 roadmap 迭代 18 卡②呈现优化批(观感重设计,机制/可读轴零触碰)。
#### 高墙墙底细阴线观感优化(2026-10-01 T17 目检体感登记)
@@ -270,7 +304,7 @@
**归属**:呈现优化批(与数字直画观感同批;排 M-4 后排,不卡迭代 9 出口)
**状态**:待办(2026-10-01 登记;机制轴零触碰,纯观感轴)。**2026-10-05 注**:墙脚阴线色 `E_FACADE_FOOT_COL #342A20` 已列为迭代 16「UI 设计对齐批」§3-N4a 五处漏网裸色之一(`board_cell_unit.gd:79`),收进 `ui_kit.gd` 时原值搬运、零观感变化;任务书=`design/research/任务书-UI设计对齐批-2026-10-05.md`。本条维持待办。
**状态**:待办(2026-10-01 登记;机制轴零触碰,纯观感轴)。**2026-10-05 注**:墙脚阴线色 `E_FACADE_FOOT_COL #342A20` 已列为迭代 16「UI 设计对齐批」§3-N4a 五处漏网裸色之一(`board_cell_unit.gd:79`),收进 `ui_kit.gd` 时原值搬运、零观感变化;任务书=`design/research/任务书-UI设计对齐批-2026-10-05.md`。本条维持待办。**2026-10-06 编入注**:已编入 roadmap 迭代 18 卡②呈现优化批(阴线形制改版;token 单点已就位)。
#### 未开格类型徽章呈现时机(2026-09-18 方向已拍板,待实施批)
@@ -284,9 +318,9 @@
**现状**:迭代 16「UI 设计对齐批」T0 实机复算中,七点测点范围外的邻接文字位实测对直背景 <4.5:1(§7.2 无区域例外)——①B 区站桩名行/护甲徽标四墨(WARM_FAINT≈6.2 过/HERO_BLUE 3.23/GOLD_DEEP 3.26/WARM 过,直背=舞台底 `STAGE_BG #3E342A`);②敌顺位徽标 ①②③ `GOLD_DEEP` 13px;③RAP 反馈行 `STONE_FAINT` 对 PANEL_DATA(2.73)。均系批前既有呈现、非迭代 16 引入;迭代 16 七点修法面已收口(站桩血数/意图徽标四色/C区槽两态/RAP 主标签),本条为其漏出范围,未动。来源=`design/qa/iter16-ui-exit-report-2026-10-06.md` §T0。
**归属**:呈现优化后续批(或 UI 设计对齐批第二轮);开工 = 用户点名
**归属**:呈现优化后续批(或 UI 设计对齐批第二轮);开工 = 用户点名——**已编入 roadmap 迭代 18 卡②呈现优化批(2026-10-06 用户令)**
**状态**:待办
**状态**:已编入迭代 18 卡②(待任务书)
#### 棋盘格边长三方取值不一致——待扩板定档处置(2026-10-06 登记)
@@ -302,7 +336,15 @@
**归属**:UI 设计对齐批后续专项(或独立呈现批);开工 = 用户点名
**状态**:待办
**状态**:**已全部落地(2026-10-06 /goal UI 对齐批,merge 2ca6288 链)**——①卡片 232×352=ui_kit BCard(D1,图标槽 76/60 随批)②商店全屏页=UiKit.page_shell(D2,56px 通栏顶条+爬价规则行+底注;三选一同壳)③地图底栏=85px 定高单条(放弃 90 小钮+特性行限宽截断+深墨)。用户令(/goal)立项即发令,无须另批。
#### 全屏 UI 审计差距清单(实机×demo 逐屏对比,2026-10-06 登记)
**现状**:用户令全屏截图对比审计落籍(报告=[ui-audit-vs-demo-2026-10-06](../qa/ui-audit-vs-demo-2026-10-06.md),并排图=design/qa/ui-audit-2026-10-06/pairs/ 九组)——①**关卡地图底栏**:demo 85px 单条+放弃小钮 vs 实机特性行无限换行爆栏(130px+)+放弃 216 红砖+特性组暖白淡墨对亮板 §7.2 违例;重设计草案(定高 88px/放弃小钮/特性行限宽省略+深墨)在报告待裁;②**E5 证据更新**:demo「工兵爆破」卡=紫带(magic 族),T4a 的 blast→TG_AOE 判定与 demo 相反,建议回滚;③标题屏主操作语义反转(demo 继续上局=主黄钮);④结算仪式感(demo 全屏 dim+石皮框板+两列对齐账目);⑤背景全局差距(demo 暖渐变聚焦 vs 实机全屏铺石纹);⑥D1/D2(商店全屏化/卡片 232×352)截图坐实(原条目在册不重复)。审计截图与探针=game/smoke/ui_audit_probe.gd(窗口化十二屏)。
**归属**:UI 设计对齐批后续轮(或独立呈现批);开工 = 用户逐项裁决
**状态**:**六项已闭环(2026-10-06 /goal UI 对齐批)**——①底栏重设计全落(85px 定高+放弃 90 小钮+特性行限宽截断+深墨)②E5 已回滚(blast→TG_MAGIC,TG_AOE 只接 aoe 键)③主操作语义已反转(有档=继续上局主黄钮)④结算仪式感已落(DIM_NIGHT 0.62 压暗+两列账行+紧凑钮)⑤背景全局已落(石纹 0.14 弱质感+暗角+地图渐变+标题光带,UiKit 氛围层单点)⑥D1/D2 已落(见上条)。**遗留(已判定并留档)**:营地面板明度/行密度与关闭钮位(camp ⑦)、战斗棋盘底板融景(battle ⑤①)、道具槽段位(台账 352 功能欠账)、立绘比例(资产升档批在册)——归各自在册条目,不在 UI 对齐轮再开。复判记录=design/qa/ui-audit-vs-demo-2026-10-06.md 批末判定节。
#### 资产升档重产批(art-bible v3.0 中修挂账③,2026-09-29 登记)
@@ -310,7 +352,7 @@
**归属**:[art-bible](../art/art-bible.md) §8.2 · 资产管线批
**状态**:**已裁决案乙(2026-09-30 迭代 9 三裁决,用户「按推荐来」)**——本迭代不升档,先收 Alpha 真人读数再定(B 区舞台落影已改善存在感;T10 黄金图基准本迭代内建成不被作废);升档批=M-4 候选位,届时提灯点亮解禁候选一并重议;A4 尺寸基线冻结(立绘 46×48/小人源 32×32)维持有效。**2026-10-04 用户令:暂不做、先忽略**(真人读数虽已收,用户裁不编入当前迭代表、挂起不讨论;重启=用户点名)。**2026-10-06 方案二批收口注记**:v3.0 的「档位上调方向候选」已被 art-bible v3.7 八敌逐键定档(源档 36–94、显示 ×2 整数)**实质收口**——存在感问题改经方案二(B 区 270/立绘显示上限 188/血条状态落底排)解决,不再走 64/96/128 升档路线;本条剩余挂起项 = 提灯点亮解禁候选(重启=用户点名或 M-4 升档批)。
**状态**:**已裁决案乙(2026-09-30 迭代 9 三裁决,用户「按推荐来」)**——本迭代不升档,先收 Alpha 真人读数再定(B 区舞台落影已改善存在感;T10 黄金图基准本迭代内建成不被作废);升档批=M-4 候选位,届时提灯点亮解禁候选一并重议;A4 尺寸基线冻结(立绘 46×48/小人源 32×32)维持有效。**2026-10-04 用户令:暂不做、先忽略**(真人读数虽已收,用户裁不编入当前迭代表、挂起不讨论;重启=用户点名)。**2026-10-06 用户令:优先级再降**(维持挂起;同日 playnote 立绘批评〔像素粒度过低看不清 / 怪物大小比例不合理〕留 playnote 在案,重启时并入设计输入——**该批评实已由同日「立绘逐键定档批」承接兑现**:①像素粒度过低 → 派生管线改「pixel-1 紧裁 → 等比缩至各自档高 → dom_block_resize」,八敌源档 36–94 全过可读门槛(实测 24 糊 / 32 可读 / 48 清楚);②怪物大小比例不合理 → 体量语义改**生物体型**(character-design §5.2,弃强度线性映射)+ 八敌逐键定档〔art-bible §8.2〕)。**2026-10-06 方案二批收口注记**:v3.0 的「档位上调方向候选」已被 art-bible v3.7 八敌逐键定档(源档 36–94、显示 ×2 整数)**实质收口**——存在感问题改经方案二(B 区 270 / 立绘显示上限 188 / 血条状态落底排)解决,不再走 64/96/128 升档路线;本条剩余挂起项 = 提灯点亮解禁候选(重启=用户点名或 M-4 升档批)。
#### 站桩帧动画——Alpha 定版闸前完成(2026-10-06 P0-3 延后登记,用户拍板)
@@ -399,14 +441,14 @@
**归属**:新界面立项(用户发令后排批);退役落码随 UI 落码批 M8/M9
**状态**:待办(生涯未做前,冒险中无任何历史回看入口——已知代价,用户知情裁决)——**已编入 roadmap 迭代 17 卡④(2026-10-05——设计提纲版任务书已成文待 U0:design/research/任务书-生涯界面设计立项-2026-10-05.md;只做设计不做实装,6 项待用户裁点,实装批另行立项)**
**状态**:待办(生涯未做前,冒险中无任何历史回看入口——已知代价,用户知情裁决)——**设计提纲已成文待评审**(2026-10-06 迭代 17 卡④设计批完成:提纲 = [systems/跨局循环/生涯.md](systems/跨局循环/生涯.md) v0.1 范围草案,五节成文〔信息架构/承载内容清单/与既有界面关系/分期实装建议/待裁点〕,现状描述经代码级复核;P0-P5 六裁点已全裁落文〔P0甲 提纲落正主 / P1甲 主菜单一级入口 / P2甲 每局一行摘要+cap 扩容 N+补用时埋点 / P3甲 敌人图鉴优先 / P4甲 局内不放入口+生涯零跳转 / P5甲 settlement_review 复活承接〕,新发现待裁点 P6 营地最近冒险条带去留随评审一并裁。**人闸 = 用户评审提纲**;实装批另行立项,期一/二/三均未预占排期)——**实装批已编入 roadmap 迭代 18 卡④生涯界面实装批(2026-10-06 用户令;门=本提纲用户评审+设计定稿)**
### GP 经济
#### 商店独立刷新机制——两参数待调参 + 机制文档回写
**现状**:2026-10-04 用户裁决(P-C2+Q2 二次裁)推翻关卡节点地图 v1.5「无独立刷新、重抽绑购买」口径,定案=**基础免费 0 次 + GP 刷新(ceil(20×1.8^已付费刷) provisional)+ 池源同源(共享池,与三选一同一账本)**;**天赋/营地侧「刷新次数」增益=用户既有意向(口头裁决,曾因未落文丢失——Q2 追认),后续由用户调整添加,实现面预留 free_count=天赋增益位**。未定:天赋增益的具体形态与数值。机制回写面=[冒险结构](systems/冒险循环/冒险结构.md) 共享池账本节 + [关卡节点地图](systems/冒险循环/关卡节点地图.md) 商店节点行 v1.5 换代;实现面=shop_draw/runner(核心小批,非呈现批)。来源=同上 §七
**现状**:2026-10-04 用户裁决(P-C2+Q2 二次裁)推翻关卡节点地图 v1.5「无独立刷新、重抽绑购买」口径,定案=**基础免费 0 次 + GP 刷新(ceil(20×1.8^已付费刷) provisional)+ 池源同源(共享池,与三选一同一账本)**;**天赋/营地侧「刷新次数」增益=用户既有意向(口头裁决,曾因未落文丢失——Q2 追认),后续由用户调整添加,实现面预留 free_count=天赋增益位**。未定:天赋增益的具体形态与数值。**机制已落码(SR-1 随 UI 落码批收官,2026-10-04/05)**。**三选一同款付费刷新(2026-10-06 用户令——「三选一对齐商店,得有刷新」)已落码**:免费双源(刷新件 X/冒险池 Y)用尽后 GP 付费刷新,同旋钮同曲线同钱包,钮常驻选择态、两源皆穷=禁用;机制登记归[秘宝](systems/排雷循环/秘宝.md)「三选一刷新双源」节。剩余待办=①调参(shop_refresh_free/曲线两参数 provisional);②天赋增益形态与数值;③机制文档回写(冒险结构共享池账本节/关卡节点地图商店行 v1.6 已记,本条收口时核对三处同步)。来源=同上 §七
**归属**:商店刷新核心小批(UI 落码计划 SR-1(商店刷新批);开工待用户发令)
**归属**:M4 数值批(调参两参数随批);天赋增益随天赋侧内容批
**状态**:待办(机制已裁、参数与文档回写未落)
**状态**:待办(机制已落码;调参、天赋增益与文档回写未落)
+3 -1
View File
@@ -169,4 +169,6 @@
**已履行**(按序换代,旧读数各随其批作废留痕不入本单):①验收读数重测批(2026-09-19——Boss 单独出列/承伤带/通关率基线全量重测,硬化翻倍期·乏力死效果期·充能期旧读数作废);②迭代 5 基线重测(统一随机流后 MC+verifier 双窗);③**数值修复批新尺重测(2026-10-01)**——模拟档位重构后全量重测,新锚 `sim-data/runsum_numfix_final_n200_20261001.jsonl`,全旧带作废只测不判([numfix 报告](../qa/numfix-newruler-readings-2026-10-01.md));④**迭代 10 奖励重构批重锚(2026-10-01)**——四代锚 77000/78000/79000/80000(改前/重构后/共享池后/掷定前置后,各 400 局),普通 L1 41.8%/L2 10.2% 带内([读数报告](../qa/m3-iter10-clear-rate-readings-2026-10-01.md));⑤**T19 真人标定局收口(2026-10-03 用户裁)**——有效局 2(1 通关 1 死于 L3 首战,[读数报告](../qa/t19-real-playtest-readings-2026-10-02.md)),用户裁定**佐证级收口不再补局**;k 预期带同日立(**正常 >0.5、预警 <0.3**),字段随 81000 重锚入库后补算终值。
**现行义务**:**T7 技能池节奏重测(2026-10-05 技能池执行批挂单)**——≥50 distinct seeds 节奏重测(过涝判读带=Boss 半血后特殊技密度上探;跑批须用户批准;S2 过涝越带→解锁技权重/倍率回调呈报禁自动调)→ ~~T19 真人标定局~~(⑤已收口)→ 真人侧读数换 81000 锚补算 k 终值(随迭代 9 出口重锚批出,模拟锚 2026-09-19 判读报告的现行锚地位由 81000 锚+真人两局承接)。工具面:`analyze_playtest.py` / `balance_verifier.py` 冒险段 / JSONL 日志现役。
**现行义务**:**T7 技能池节奏重测(2026-10-05 技能池执行批挂单)**——≥50 distinct seeds 节奏重测(过涝判读带=Boss 半血后特殊技密度上探;跑批须用户批准;S2 过涝越带→解锁技权重/倍率回调呈报禁自动调;**2026-10-06 联审批注:判读带立单于案C 行为换代前,执行前须按案C 新行为复核「半血后」窗口与密度分母是否仍有效,失权即停机呈报重立带**)→ ~~T19 真人标定局~~(⑤已收口)→ 真人侧读数换 81000 锚补算 k 终值(随迭代 9 出口重锚批出,模拟锚 2026-09-19 判读报告的现行锚地位由 81000 锚+真人两局承接)。工具面:`analyze_playtest.py` / `balance_verifier.py` 冒险段 / JSONL 日志现役。
**后续内容批义务(2026-10-06 敌人表行集多行批 P3 丙二裁挂单)**:首个混编遭遇行投放(连同 Boss 多行内容,敌种候选与坐标由内容批裁)——投时 MC 取证先报批(数值验证场景二档起)、难度带读数义务随投登记、首遇教学位纪律与 expect_pools 断言面逐项复核(巨蜘蛛首遇位「固定 2 不加骰」等表注释为准)、Boss 多行投放时 Boss 名取首行显示/Boss 遭遇骰读首行区间/半血解锁/独占技/难度带六面读数逐项过。——**已编入 roadmap 迭代 18 卡⑤混编遭遇首批投放批(2026-10-06 用户令;读数义务维持随批登记,MC 取证跑批顺延迭代 18 卡⑥ M4 收官批统一执行〔数值统一调整殿后〕)**
@@ -151,7 +151,7 @@ GP(显示名「金币」)是冒险内的一次性属性提升货币:战斗
掉落掷定消费 gp_drop 封闭随机流(主种子派生、可回放)。**商店货架抽签消费 shop_draw 封闭随机流**(v0.13 扩签——每次抽 3〔进店+每次买后重抽〕恰一 scope,与 reward_pick 分签防取数序互扰)。掉落与价格的现行行值读商店表(registry 为准),数值所有权归[难度曲线与Boss](难度曲线与Boss.md)曲线调参批——本批骨架先行,全部数值 provisional。
**共享池账本(v0.13 P1 共享池单点;v0.14 令牌库换代)**:商店货架与提升三选一是**同一个池**——货架候选 = 池∖{GP 袋}(用钱买钱恒负交易)= {攻击, 生命上限, 护甲, 行动点} 四种(秘宝件已随同调批出池);**库存 = 剩余令牌数**(TP0——「池消耗即上限」,种类次数上限退役,与奖励兑付摘牌同一令牌库承载,全冒险一次性跨关卡不补给):商店买一件,奖励面就少一枚;「无限购买」收敛为**钱尽或池空为止**(池空=硬闸、A 链爬价=软闸),空货架合法态。货架 = **令牌级抽签**(同 kind 去重每 kind 至多一卡,价格公式 tier-blind 维持批②裁定,购买消费在架令牌本体 kind+tier)。两渠道不得各自私记库存——消费走同一入口写同一令牌库(实现=AdventureRunner._bonus_deck 单点,冒险结构 owner;kind 维度派生计数 _bonus_taken 承载断点附随件与读数)。**货架独立刷新(v0.15 MC-1 2026-10-04——P-C2+Q2 裁)**:进店免费刷新次数(基础 0,天赋/营地侧增益位预留)用尽后 GP 付费刷新(ceil(20×1.8^已付费刷) provisional——调参表旋钮 shop_refresh_*);重抽=同 pool_draw 共享池抽签(shop_draw 恰一新 scope),池空=不可刷新合法态;进店/离开双向清零付费刷计数。
**共享池账本(v0.13 P1 共享池单点;v0.14 令牌库换代)**:商店货架与提升三选一是**同一个池**——货架候选 = 池∖{GP 袋}(用钱买钱恒负交易)= {攻击, 生命上限, 护甲, 行动点} 四种(秘宝件已随同调批出池);**库存 = 剩余令牌数**(TP0——「池消耗即上限」,种类次数上限退役,与奖励兑付摘牌同一令牌库承载,全冒险一次性跨关卡不补给):商店买一件,奖励面就少一枚;「无限购买」收敛为**钱尽或池空为止**(池空=硬闸、A 链爬价=软闸),空货架合法态。货架 = **令牌级抽签**(同 kind 去重每 kind 至多一卡,价格公式 tier-blind 维持批②裁定,购买消费在架令牌本体 kind+tier)。两渠道不得各自私记库存——消费走同一入口写同一令牌库(实现=AdventureRunner._bonus_deck 单点,冒险结构 owner;kind 维度派生计数 _bonus_taken 承载断点附随件与读数)。**货架独立刷新(v0.15 MC-1 2026-10-04——P-C2+Q2 裁)**:进店免费刷新次数(基础 0,天赋/营地侧增益位预留)用尽后 GP 付费刷新(ceil(20×1.8^已付费刷) provisional——调参表旋钮 shop_refresh_*);重抽=同 pool_draw 共享池抽签(shop_draw 恰一新 scope),池空=不可刷新合法态;进店/离开双向清零付费刷计数。**三选一同款付费档(v0.16 2026-10-06 用户令——刷新对齐商店)**:提升三选一免费双源(刷新件 X/冒险池 Y,机制正主=[秘宝](../排雷循环/秘宝.md)三选一刷新双源节)用尽后 GP 付费刷新——读同 shop_refresh_* 两旋钮(单点调参)、扣同一 GP 冒险账本(LevelRunner.spend_gp 单口)、重抽同 reward_pick 共享池抽签;付费刷计数每停点清零(与进店清零同构);钮常驻选择态、免费与付费两源皆穷=禁用。
### 关卡大奖励:通关回血 + 提升三选一(钥石退役出大奖励)
@@ -332,3 +332,4 @@ GP(显示名「金币」)是冒险内的一次性属性提升货币:战斗
| v0.12 | 2026-10-01 | **关卡大奖励重构批(迭代 10——用户 2026-09-30 拍板案丙 + P-A~P-E 全裁毕;冒险表扩列 / meta.tres 重锚 / registry / 行动经济 / 元进度 / 01-核心循环 / 03-内容规模 / 难度曲线与Boss / 关卡节点地图 / 06 同批落文)**:①大奖励「固定三件套」退役改两层兑付——非末关通关 = 部分回血(clear_heal_pct 20 provisional)+ 提升三选一(池六种:攻击/生命上限/护甲/GP 袋/秘宝/行动点件;加权洗牌不放回 E-S weight-key 消费 reward_pick 封闭流;属性件上限各 3、AP 件上限 2,达上限先剔牌库);②统一冒险加算区三轴扩四轴 +行动点(AP 件 = 每场战斗开始首轮基线 +1);③钥石退役出大奖励改 Boss/精英击杀逐杀掉落(boss_keystone 重锚首杀 3/复杀 2,末关照常入账,精英掉 1 预留);④秘宝件受同调位约束(过渡键 transitional_sync_slots=1 provisional,正主 = 同调实施批谓词表;超位替换交互 N+1 选 N、战斗内渠道沉没不入);⑤断点附随件扩奖励选择态 + 件获取次数计数;⑥选择停点零自动推进/可中断。渲染层验证冻结(用户 2026-10-01 提前开工拍板——不合入 master、目检待批),目检清单随批交付 |
| v0.13 | 2026-10-03 | **GP 商店房重构批(迭代 11 第②批——任务书 v1.3 全裁 P1 共享池/P1-a/P1-b 双甲/P2 甲/P3 甲/P4 ceil/P5 甲;06「GP 商店房重构」条 2026-10-02 用户裁决取代 09-20 无刷新裁决)**:①GP 冒险账本节商店购买行换代——价格公式 = ceil(基价 × b^(关序−1) × A^(本次进店已购次数))(A/b provisional 1.8/1.1;legacy 旧式随对照模式保留注记);②新增「共享池账本」段——商店货架 = 池∖{GP 袋}∖{秘宝件} 四种,库存=上限即库存全冒险一次性,两渠道同一账本(买一件=奖励面少一件),池空硬闸+空架合法态;③shop_draw 扩签登记;④统一冒险加算区段——pool 模式买上限不回血(池件=奖励件本体)、AP 件累加源并商店;⑤断点附随件扩商店货架态(shop_shelf/shop_visit_buys,P2 甲;确定性重放承载注记);⑥调参表 GP 经济参数行随表换代。实现=AdventureRunner/LevelRunner 池模式(缺省 legacy 对照承载,真实入口投 pool) |
| v0.14 | 2026-10-03 | **令牌池落地批(迭代 12 TP0——node-reward v2.2 追认 b 实施批)**:①提升池改**固定配额令牌池**——普通 70/稀有 25/罕见 3=98 张〔罕见档原列「道具件 2」随 aux_item 池种退役〔迭代 11 第①批 T7,落地晚于追认 b〕收窄,池总量 100→98——台账自决披露项〕;②抽取机制换代——Fisher-Yates 不放回抽 3 同 kind 去重每 kind 至多一枚(取代 E-S 加权洗牌),选中踢池未选回池、池耗即枯竭、**种类次数上限退役**;③恢复件新入池(rare 档 +6 当即回血封顶生效上限)+ 数值对(小GP 20/大GP 50 等);④MC 策略 316-f 落地(autoplay 1 级最稀有/2 级最左);⑤共享池账本段换代——库存=剩余令牌数,货架=令牌级抽签(价格公式 tier-blind 维持批②裁定),消费=AdventureRunner._bonus_deck 单点;⑥断点附随件扩令牌池余库(bonus_deck 逐枚还原;旧断点缺键=满库重建防御口径单版本周期);⑦现行基线锚换代=runsum_m4iter12_tp0_n20_20261003(normal 档配对读数同带 0/5/0) |
| v0.16 | 2026-10-06 | **三选一刷新对齐商店批(用户令——「三选一对齐商店,得有刷新」;机制正主=秘宝.md 三选一刷新双源节同批落文)**:免费双源(刷新件 X/冒险池 Y)用尽后 GP 付费刷新——同 shop_refresh_* 两旋钮(curio_refresh_gp_cost 单点调参)、扣同一 GP 冒险账本(LevelRunner.spend_gp 新单口)、重抽同 reward_pick 共享池抽签;付费刷计数每停点清零;呈现=CurioPickOverlay.set_refresh_display 与商店 set_refresh_display 同构(钮常驻选择态、两源皆穷禁用不隐藏、角标=免费余量、价签行示 GP 价);通关停点刷新重发载荷带 refreshed 标直落选择面(不再重开胜利总结面)。店内门票专长三选一暂不挂刷新面(维持现状)。单测=tests/unit/core/curio_refresh_paid_test.gd |
+6 -5
View File
@@ -29,7 +29,7 @@
| 负责 | 不负责 |
|---|---|
| 奇物的定义、三个分类、以及分类与渠道的交叉开关 | 每件效果怎么接入结算——归挂点所属文档([战斗结算](../战斗循环/战斗结算.md)、[行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md)) |
| 奇物的定义、三个分类、以及分类与渠道的交叉开关 | 每件效果怎么接入结算——归订阅事件所属文档([战斗结算](../战斗循环/战斗结算.md)、[行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md)) |
| 生命周期边界:何时出现、何时生效、何时清零 | 卡面排版与界面呈现细则——见 [HUD框架](../表现与支撑/HUD框架.md) |
| 获取渠道的口径与约束 | 魔法道具与元进度——归上表两份文档 |
| 与相邻概念的边界 | 格面资源、关卡节点、商店本身的规则——归各自所属文档 |
@@ -61,7 +61,7 @@
| 分类 | 它给的是什么 | 落点 | 事实源 |
|---|---|---|---|
| **专长**(Feat) | 给规则。在结算管线某个挂点上给自己加一条规则;同一标签的持有件数达阈值时质变 | 各结算段挂点;标签与档位由求值服务统一算 | `relics.tres`(逐项定义) |
| **专长**(Feat) | 给规则。订阅结算管线的某个事件(订阅哪个事件 / 什么条件 / 什么效果三字段声明);同一标签的持有件数达阈值时质变 | 各结算段事件发射点;标签与档位由求值服务统一算 | `feats.tres`(逐项定义) |
| **属性值提升**(ASI) | 给数字。抬高角色某项战斗属性的基础值 | 冒险加算区的生命上限 / AC / 攻击三轴 | `adventure.tres`(种类配额与值) |
| **资源** | 给"可用的量"。不抬高战斗属性,也不改规则,而是扩充你能调动的余量与机会 | 行动经济、三选一界面、局内钱包;**不进加算区、多数不进持有集** | `adventure.tres`(种类配额与值) |
@@ -272,8 +272,8 @@
|---|---|
| [魔法道具](../排雷循环/秘宝.md) | 最需要分清的一对,判据是生命周期:**奇物当局清零,魔法道具跨冒险保留**。两者互不相通——奇物永不进同调位,魔法道具永不进当局随机渠道。 |
| [元进度](../跨局循环/元进度.md)(树) | 树管账号永久的规则与容量,奇物管当局构筑,两层互不代替。 |
| [战斗结算](../战斗循环/战斗结算.md) | 专长的挂点位于结算管线的各段;挂点清单与语义归结算文档。 |
| [行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md) | 部分挂点落在行动点结转与地形处理上,语义归各自文档。 |
| [战斗结算](../战斗循环/战斗结算.md) | 专长订阅的事件发射点位于结算管线的各段;事件词汇与发射时机归结算文档。 |
| [行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md) | 部分事件(付费开掘 / 地形受伤)落在行动点收对价与地形处理上,语义归各自文档。 |
| [关卡节点地图](关卡节点地图.md) | 是渠道的载体,不是奇物的属性。专长挂在 Boss 节点兑付面上,节点类型词表零扩类。 |
| [地图战斗资源](../战斗循环/地图战斗资源.md)(格面资源) | 无关:格面资源是单格的一次性产出,不进持有集,也不是渠道给的。 |
| [存档序列化](../表现与支撑/存档序列化.md) | 断点负载记录持有集与剩余候选池;键名与版本迁移策略归存档文档。 |
@@ -299,7 +299,7 @@
| 参数 | 取值域 | 事实源 |
|---|---|---|
| 专长定义行(标识 / 显示名 / 稀有度 / 标签 / 挂点 / 效果字典) | 各字段封闭枚举,行键白名单封闭 | `game/data/tables/feats.tres` |
| 专长定义行(标识 / 显示名 / 稀有度 / 标签 / 效果说明 / 订阅行〔订阅哪个事件 on / 什么条件 when / 什么效果 do〕) | 各字段封闭枚举,行键白名单封闭;事件 / 效果类型 / 条件事实 / 算子四词表封闭(效果引擎单一事实源) | `game/data/tables/feats.tres` |
| 专长门票(出现概率 / 配额 / 全局限量) | 整数 | **尚未入表**,见待办 |
| 属性值提升种类 | 封闭三项:生命上限 / AC / 攻击,扩项走文档修订 | `game/data/schemas/adventure_table.gd` |
| 资源种类 | 行动点上限 / 金币 / 回复(**刷新次数与专长获取两项尚未入表**,见待办) | 同上 |
@@ -345,6 +345,7 @@
| v2.1 | 2026-10-05 | **交叉表收口(用户拍板)**:Boss 渠道**只出专长**,属性值提升与资源在此均不出现——三条渠道的形状定为"一块独占 + 两块并行",专长靠打赢、其余靠抽取与购买。Boss 兑付明确为**终局前**的 Boss,终局 Boss 不给(无后续关卡可消费)。新增 2.4 节**「计价物不自售」规则**:金币不进商店既不拆分类也不开特例,而是写成两轴交叉处的一条约束——商店的计价物是金币,故金币不进商店;按"能不能进商店"反推分类等于用渠道轴去切分类轴,两根轴会缠回去。 |
| v2.2 | 2026-10-05 | **门票形态 + 约束分层 + 默认原则**。① 用户明确:奖励节点与商店不直接给专长,而是给一个**「专长获取」道具**,拿到后开专长三选一——交叉表专长在两渠道由"不出现"改为"**门票形式**";门票归专长(给的是一件以前不会的事,只是把选择推迟),理由是防止用钱定点买构筑。② 用户质疑「计价物不自售」本质是特判——**承认成立**:它确实是在分类白名单之外加的一道过滤,与死特判的区别在于把"枚举例外"变成"**可计算谓词**"(新渠道/新奖励自动判定)。2.4 改写为**三层约束**(分类白名单 / 可计算谓词 / 显式例外清单),并给出判断标准:结构性原因可写成谓词,设计性原因只能进清单且每条须写理由;三个方案(单独分类 / 谓词 / 死特判)的代价并列摆出,不藏折中。③ 用户定**默认原则**:除已登记的特殊规则外,分类内的东西都要在池子里——据此**回复应在商店内**,现行 shop.tres 货架缺它是"现状与表格不对齐",须在实施批补上。 |
| v2.3 | 2026-10-05 | **门票机制细化 + 默认原则表述修正**。① 门票**拿到即开、不可囤积**(用户定)——不进持有集,防止玩家把关键决策无限推迟,也防持有物语义从后门回来。② 门票的"罕见"**只在概率不在价格**,一局限购一次,并加**计步保底**:连续 5 次三选一展示未出现则第 6 次必出;计数跨奖励节点与商店共享、**刷新后的重新展示计入**(用户明定含刷新),限购用满后保底不再触发。③ **修正 v2.2 的误读**:把"分类在某渠道不出现"当成需要理由的缺格是错的——渠道出哪些分类是渠道轴的定位(Boss 只出专长),不是例外;默认原则只管**分类内部**的成员齐不齐。④ 专长总量与档位阈值的匹配按用户决定**延后**(待第四关内容批后实测复裁),另单独登记 charge 标签仅 3 件、永远达不到档二的数据缺陷。 |
| **v2.8** | 2026-10-06 | **效果行为数据驱动换代(内容数据驱动扩展批)**:专长的效果声明从「挂点+效果字典」换为「订阅行」——每件声明**订阅哪个事件(on)/ 什么条件(when)/ 什么效果(do)**,由效果引擎统一解释执行;旧挂点枚举消亡(事件名+效果类型取代)。配套事实:效果引擎 `game/core/effect_engine.gd`(事件 16 / 效果类型 24 / 条件事实 9 / 算子封闭词表);专长行 `feats.tres` 27 件全量迁移,秘宝被动六件同批订阅化;行为与迁移前逐位一致(MC 同种子 40 局逐位对拍实证)。
| **v2.7** | 2026-10-05 | **三个子节点正式定名(用户拍板:去「类」字后缀)**。此前三个分类只有带后缀的描述(机制类 / 属性提升类 / 资源类),是文档层临时叫法,既非专名也非玩家可读的词。现定专名:**专长**(Feat)/ **属性值提升**(ASI)/ **资源**。定名依据:前两个是 DND 规则书官方中文,且与用户 v1.1 原话一致(当时原话就是「属性提升(ASI)」与「专长」,v1.1 落文时被加了「类」字后缀而退化成描述)。「机制类」这个叫法本身还有硬伤——它的 28 个成员里没有一件是"机制",实际是"在结算挂点上改一条规则",读者看到会误解为游戏机制。
**新增 1.6 节「三层结构与命名」**(用户 2026-10-05 拍板做玩家可见的三层):奇物(总称)/三个分类/具体单件。明确**命名是本节规矩、呈现是另一件事**——分类名在卡面不出现(归 battle.md / node-reward.md 裁决),但帮百科、成就名、效果描述的指代三处都要用,所以它必须是玩家读一遍就懂的正式名词。连带:修掉批量替换撞出的五处「专长(专长)」类自撞、v2.0 历史行内的自撞并标注当时的旧称、registry 的「资源(命名待定)」过期标注。
| **v2.6** | 2026-10-05 | **修正核心循环位置图:奇物不是打一场战斗给一份**(用户纠错)。原图把"关内 排雷推理 → 战斗结算 → 通关 → 得到一份奇物"画成一条链,读起来就是每场战斗通关都给一份——**错在把关内普通战斗的通关与关底 Boss 的通关混为一谈**。按 [冒险结构](冒险结构.md) 的定义,**通关一关 = 该关关底 Boss 被击杀**,所以"击败 Boss"与"通过这一关"是同一个时刻、不是一条链上的两步。改法:① 图改为分支结构(普通战斗节点→不给、往下走;关底 Boss 击败→专长三选一+通关回血);② **一关只兑付一次**写成显式口径;③ 2.1 节渠道名由"终局前 Boss 击败后"改为"关底 Boss 击败(即通过这一关)",并写明触发点就是关卡推进本身那一刻;④ 文首引言加"兑付频率"条,交叉表渠道名与 registry 同步;⑤ 连带修掉一处污染——节点类型封闭枚举五种里的"奖励"曾被 v2.4 批量替换误伤成"奇物"(节点类型里没有奇物这一类),已复原。 |
@@ -40,7 +40,7 @@
## 在核心循环中的位置
```
装板 ──(一次摇号定全图资源身份 + 清图对象)──▶ 挖掘期(身份恒定可读,只揭晓不兑付)──▶ 轮末授予段(极性路由逐格兑付)──▶ 战斗段
装板 ──(一次摇号定全图资源身份 + 清图对象)──▶ 挖掘期(身份恒定可读,只揭晓不兑付)──▶ 轮末授予段(极性路由逐格兑付;伤害形态单据暂存)──▶ 战斗段(段末地图伤害账统一落地——案C 2026-10-06 用户裁)
```
本系统横跨挖掘期与轮末结算的头部:装板时全图资源身份一次摇定;挖掘期只揭晓身份,轮末授予段(结算里逐格兑付的段落)按极性矩阵把当轮的因兑现——正向当场生效,负向也当场生效(负向恒即时,无库存语义)。段序编排归[战斗结算](战斗结算.md)。
@@ -125,7 +125,7 @@
### 负向恒即时:惩罚没有库存语义
负向兑付全部在授予段当场执行,不入库、不出窗口——惩罚不设库存、不留存量。正向里的 percent 类(增益行)进[增益状态](增益状态.md)的容器;flat 类(群伤、治疗、直伤)当场结算;gp 正负两向(金币袋 / 破财)同样当场执行——记入战斗内 GP 缓冲,战斗完成随 gp_dropped 与钱包结算(账本归[冒险结构](../冒险循环/冒险结构.md)),同样无库存语义。叠层饱和由战斗结算既有池 clamp 承载;blast 负向(警觉)与 action 负向(迟滞)直授无上限。负向直伤使主角生命归零时,结算按战斗结算的致死短路规则处理。
负向兑付的账户动作全部在授予段受理,不入库、不出窗口——惩罚不设库存、不留存量;其中**伤害形态(群伤/直伤类负向行)的扣血落地殿后到战斗段末**(2026-10-06 用户裁,单据暂存,见[战斗结算](战斗结算.md));主角在敌方还手中倒下则地图伤害账整体不兑(逐单留「未生效」行)。正向里的 percent 类(增益行)进[增益状态](增益状态.md)的容器;heal 正向当场结算;gp 正负两向(金币袋 / 破财)当场执行——记入战斗内 GP 缓冲,战斗完成随 gp_dropped 与钱包结算(账本归[冒险结构](../冒险循环/冒险结构.md)),同样无库存语义。叠层饱和由战斗结算既有池 clamp 承载;blast 负向(警觉)与 action 负向(迟滞)直授无上限。
举证:本节为兑付语义,无计算。
@@ -169,7 +169,7 @@
1. 战斗结算装上新图后、玩家开挖前调用一次摇号:全部非封锁格的资源类型与清图对象身份摇定,映射进入只读。
2. 玩家挖掘:挖开的格子当场揭晓类型身份;已开格的身份随时可读。
3. 轮末授予段按极性矩阵逐格兑付:正向 percent 挂状态、正向 flat 当场结算,负向全部当场兑付。
3. 轮末授予段按极性矩阵逐格兑付:正向 percent 挂状态、heal 正向当场结算,非伤害负向当场兑付;伤害形态正负单据暂存,战斗段末统一落地。
4. 清图轮兑付清图奖励对象,恒非空;完美排雷追加第二份。
5. 战斗结束:板级映射退役。换图按新板重摇。
@@ -254,6 +254,6 @@ empower 与 fortify 是敌方技能池增益技在容器侧的数据落点(技
| v0.7 | 2026-09-17 | **数值压缩批·文档同步(与 doc-conventions.md §5 数值纪律·强制收口条款同批)**:ambush 幅度 +3 flat → +1 flat(量纲未变、压缩倍数三阶下发,参见 `data/tables/status_effects.tres` 注释)。**双写失同步收口**:① 状态行表与调参表数值列改指路存根(指向 `data/tables/status_effects.tres` 与 `registry/entities.yaml` status_effect mvp_content);② 调参表删除「现行值」列(敌人系统 v0.6 先例),仅保留 schema 模板与取值域;③ 与 `地图战斗资源.md` v0.7 / `registry/entities.yaml` 同批落地——五步收口一并兑现 |
| v0.8 | 2026-09-17 | **数值纪律收口批:正文与调参表 knob 现行值改指路存根(事实源 `data/tables/*.tres` 与 registry),8 处失同步值修正**——幅度例"两层 +50% 合计 +100"改"2 × 单行幅度(读表)";削弱例"−130 个百分点"改"−(2 × weaken 行幅度)(读表)";护甲例"AC10 → AC12(期望减免 21.25% → 28.75%)"改"基准 AC(读 hero 表)+ 层数"、派生读数删除;状态行表"时限/合并"列 1 次/×2/×16/×1 字面量改读表措辞;defense_up 退役条目删"−30%"数值;"两行 duration = 2"改"duration 表值(读表)";empower"×2"幅度与调参表"AC10 → 11 → 12"、"2 次 = 1 个有效增益拍"同步指路化 |
| v0.9 | 2026-09-18 | **战斗数值结构修复批(2026-09-18 盘问会话用户拍板,与战斗结算 / registry / 切片代码同批)**:三行语义改写(数值全部 provisional 归状态层重设计批)——① off_guard(失衡)换装 AC 轴:unit percent→ac、退出 hero_defense 池(effect_pool_map 删键,池清空结构保留),状态行表与调参表同步,"标错反噬三池"措辞改"三行";② fortify(硬化)符号纠正:旧正值入池实际 ×2 翻倍与"硬化=减伤"语义相反,改负值后主角攻击折半(正负号语义成文:负值 = 减伤方向);③ weaken(削弱)叠层改续时:stack→refresh、duration 表值 2——同名重复授予只刷新剩余次数、层数恒 1,×2 叠满池触底 ×0 的免伤轮结构性根治;消费侧例子表"削弱叠两层压地板"改"暴走叠两层封顶 ×2"(削弱叠层读法退役);"叠层不续命"对削弱不再适用,行动经济联动句随之失效;调参表一次性/叠层上限两行措辞同步 |
| v0.10 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0,与 敌人系统 / 战斗结算 / registry / 切片代码同批)**:off_guard(失衡)新增第二来源类别 = 敌方技能施放(妨害技"蛛网束缚"的容器落点——首实装于 L2 Boss 蛛化卓尔精灵池;duration 由技能行 buff_duration=2 覆盖 = 1 个有效结算,empower/fortify 同款口径);容器语义零改动——同构实例、side 路由照常,妨害技零新状态行(乏力 sapped 留作妨害第二词汇,暂无载体) |
| v0.10 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0,与 敌人系统 / 战斗结算 / registry / 切片代码同批)**:off_guard(失衡)新增第二来源类别 = 敌方技能施放(妨害技"蛛网束缚"的容器落点——首实装于 L2 Boss 蛛化卓尔精灵池;duration 由技能行 buff_duration=2 覆盖 = 1 个有效结算,empower/fortify 同款口径);容器语义零改动——同构实例、side 路由照常,妨害技零新状态行(乏力 sapped 留作妨害第二词汇,暂无载体) |
| v0.11 | 2026-09-20 | **格面资源八型批(用户拍板——与敌人系统 / 战斗结算 / registry / 切片代码同批)**:① 状态行表 ambush 行 → alert 警觉行(敌方护甲等级 +1,ac 量纲,side-wide);② 标空旗路由措辞纠正(2026-09-15 极性矩阵后已无三选一反噬,本批顺手收口);③ 敌人系统的伏击量纲定义/上限锚义务面随伏击退役移除 |
| v0.12 | 2026-09-20 | **主角增益只续时不叠层批(用户拍板「主角的其实也一样,都是按照叙事的方式,不要有叠层;只续时不叠层,变相削弱主角性能可接受」;与 status_effects.tres / smoke / registry / 06 清单同批)**:① attack_up(增伤)/ ac_up(护甲强化)两行 stack_policy stack→refresh——重复授予层数恒 1、剩余结算次数重置,对齐削弱 2026-09-18 续时定案;至此主角可重复获取的增益与减益合并语义统一(叠层策略仅剩敌侧 alert / enrage / off_guard / sapped 等行);② duration 表值 1 与 max_stack 2 不动(refresh 下 max_stack 不消费——weaken 先例;dur=1 下续时表现为重复拿重置当轮倒数,跨轮延续随将来 duration 拉长自然显形,数值归状态层重设计批);③ 影响面:增伤不再 +100%(hero_offense 池单层封顶 +50)、护甲强化不再 +2 AC(局内可达 AC 上限 11,AC12 折扣档采样探针随行降为 AC11)、这两行不再可达满层拒绝行;④ 同名状态合并策略表/幅度量纲例子表/调参表两行/联动纪律句/验收"叠层不减钟"条改述;06 清单「叠层不续命的读感」条目解决移除;冒烟三闸全过(ac_up 行断言与 AC 探针改形,无净增断言) |
+17 -16
View File
@@ -51,7 +51,7 @@
### 轮末五段结算:一轮从收场走到判定
玩家行动点花完、主动停手,或开完整张图时,[行动经济](../排雷循环/行动经济.md)宣布本轮结束,本系统随即自动发起一次整轮结算。结算严格按五段固定顺序执行;核心相对次序"增益减益先于战斗"不变——先合成修正再动刀,任何结局都能归因。
玩家行动点花完、主动停手,或开完整张图时,[行动经济](../排雷循环/行动经济.md)宣布本轮结束,本系统随即自动发起一次整轮结算。结算严格按五段固定顺序执行;核心相对次序"增益减益先于战斗"不变——先合成修正再动刀,任何结局都能归因。地图奖励与惩罚中的**伤害形态兑付一律殿后到战斗段末**(2026-10-06 用户裁):授予段只清资源、增益、治疗、行动点、GP 等非伤害账,刀落完后地图伤害账才统一落地。
```
① 授予段 → ② 增益/减益段 → ③ 战斗段 → ④ 衰减段 → ⑤ 判定段
@@ -59,9 +59,9 @@
| 段 | 干什么 |
|---|---|
| ① 授予段 | 结算队列先过滤再分批兑换:开格、旗判定、清图,按极性矩阵路由(详见授予段一节) |
| ① 授予段 | 结算队列先过滤再分批兑换:开格、旗判定、清图,按极性矩阵路由(资源/增益/治疗/行动点/GP 当场兑付;伤害形态单据暂存不兑,详见授予段一节) |
| ② 增益/减益段 | 把主角与敌人身上的活跃效果一次性合成本结算的修正池(同侧百分比修正的加总桶) |
| ③ 战斗段 | 主角先手攻击一次,随后敌人按行序逐个还手(详见战斗段一节) |
| ③ 战斗段 | 主角先基础攻击一次,随后敌人按行序逐个结算攻击,最后地图奖励与惩罚的伤害兑付在段末统一落地(详见战斗段一节) |
| ④ 衰减段 | 移除到期的临时效果;每轮恰好一次,含末轮——清图奖励先兑付、效果后衰减 |
| ⑤ 判定段 | 先判主角倒下(负),再判敌人清空(胜),都不满足则继续下一轮 |
@@ -139,16 +139,16 @@ percent 类(每结算、每层): E = |层数 × 行值| ÷ 100 ×
| 旗判定批 | 标中则兑该雷格资源的正向,每颗雷的资格只兑一次;标空则记"标旗未中"归因行,并兑该安全格资源的负向 |
| 清图批 | 清图奖励对象恰好发一次;完美排雷追加第二份同身份兑付 |
授予段内的伤害兑付(爆裂、直伤、反噬)以伤害单据入队,攒到授予段尾统一结账;清图批为段内同步结账点——开单前段内排队单先按开单序兑现(见[伤害单据与伤害控制器](#伤害单据与伤害控制器所有伤害走同一道门)一节)。
授予段当场只兑非伤害形态(增益、治疗、行动点、GP 缓冲、警觉加层);**伤害形态兑付(爆裂、直伤、反噬)以伤害单据暂存,攒到战斗段末统一结账**(2026-10-06 用户裁——地图伤害账殿后,见[伤害单据与伤害控制器](#伤害单据与伤害控制器所有伤害走同一道门)与战斗段两节)。暂存单在授予段按「将兑付」回报——授予段内依赖兑付读数的流程决策(完美排雷第二份、高光份数)依据开单时点事实判定,该时点敌人存活有保证;战斗段末实际结账若目标已灭,控制器自记「奖励未生效」行。
**充能已退役(2026-09-19 用户拍板)**:原"挖格/标中旗给充能计数 → 战斗段折算穿刺/魔法分量"的弹药系统整体移除——主角攻击回归单分量,克制策略归冒险前配置(主角 attack_type 表值,营地换型 = 改字段;未来冒险前参数面承接策略位)。攻防两条抽象分离纪律保留:攻击类型是伤害的属性轴,棋盘事实只是奖励触发源。
| 兑付形态 | 覆盖 | 兑付方式 | 拒绝语义 |
|---|---|---|---|
| 增益(percent) | attack / defense / weaken 的正负两向 | 进入[增益状态](增益状态.md)的容器,本结算生效 | 叠层已满时拒收,记"奖励未生效"行 |
| 即时全体伤害(flat) | blast 正向 | 当场对全体存活敌各扣表值生命 | 场上无敌可打时零兑付,记"奖励未生效"行 |
| 即时全体伤害(flat) | blast 正向 | 战斗段末对全体存活敌各扣表值生命(暂存单殿后统一落地) | 场上无敌可打时零兑付,记"奖励未生效"行 |
| 即时治疗(flat) | heal 正向 | 主角按表值回复并封顶上限 | 满血时零兑付,记"奖励未生效"行 |
| 直伤(flat) | heal 负向 | 主角当场扣表值生命,不经增益状态 | 生命归零即走致死短路 |
| 直伤(flat) | heal 负向 | 主角在战斗段末扣表值生命(暂存单殿后统一落地),不经增益状态 | 主角倒下则地图账整体不兑,逐单留"未生效"行 |
| 警觉加层 | blast 负向 | 敌方全体护甲等级 +1/层(读 `reward.tres` enemy_alert 行 → `status_effects.tres` alert 行),入增益状态容器 | 直授无上限;战斗段由防守方护甲等级读数消费 |
| GP 缓冲(flat) | gp 正 / 负向 | 金币袋 / 破财按 power 记入战斗内 GP 缓冲(+power / −power);缓冲随战斗完成折进 battle_finished 的 gp_dropped 统一到账(钱包账本归[冒险结构](../冒险循环/冒险结构.md)) | 无拒收态——缓冲只在战斗边界与钱包结算,战斗域零钱包状态 |
| 行动点修正 | action 正/负向 | 下轮行动点 ±power(action_economy 排队,下一轮开始兑现后清零;下限 0) | 排队净值不跨轮保留;明细记效果行(effect_id=ap_delta) |
@@ -181,13 +181,13 @@ percent 类(每结算、每层): E = |层数 × 行值| ÷ 100 ×
**死亡事件由单位自行宣布**:单位生命归零的那一刻自己发出死亡事件(不由流程代查、不由控制器推断)。怪死 → 队列中该敌为来源的未结单据作废(死亡即不动手——静默零行、不进冷却、不进保底计数,同既有口径);主角死 → 兑付终止、余单作废,Game Over 仍归判定段的生命读数路径。
**结账时机双模式(结构位,非调参项)**:单据开出后何时兑现由控制器政策承载。现行 = **段界结账**:授予段的伤害单攒到授予段尾统一兑现;清图批是段内同步结账点——开单前先按序结清段内排队单、随后即开即结(完美第二份与高光份数的流程依赖需要同步读数);战斗段的单攒到战斗段尾统一兑现。保留位 = **开单即结**:提交当场兑现,逐位等价 2026-09-24 之前的行为,作回切结构位。两模式同种子同操作均逐位复现(兑现次序 = 开单次序);同一输入在两模式下结果可不同(兑现时机的语义差异),历史基线读数以段界结账口径为准。切换 = 改控制器政策常量,走代码修订不走调参。
**结账时机双模式(结构位,非调参项)**:单据开出后何时兑现由控制器政策承载。现行 = **段界结账 + 地图账殿后**(2026-10-06 用户裁):授予段不开具任何当场兑现的伤害单——全部伤害形态单据暂存(含清图批),战斗段按「主角先手 → 逐敌还手 → 地图账」的顺序补提交,攒到战斗段尾统一兑现;主角在敌方还手中倒下 → 暂存单整体不兑,逐单留「未生效(主角已倒下)」行。清图批的完美第二份与高光份数决策依据开单时点事实(该时点敌人存活有保证),暂存单按「将兑付」回报。保留位 = **开单即结**:提交当场兑现,逐位等价 2026-09-24 之前的行为,作回切结构位。两模式同种子同操作均逐位复现(兑现次序 = 开单次序);同一输入在两模式下结果可不同(兑现时机的语义差异),历史基线读数以 2026-10-06 之前的授予段结账口径为准——该口径已随案C退役,新读数一律按地图账殿后重采。切换 = 改控制器政策常量,走代码修订不走调参。
举证:本节为管线编排约定,无新计算;掷点、折扣、克制与池乘区的算术口径见战斗段一节。
### 战斗段与胜负判定:谁先动手、怎么扣血、怎么定胜负
战斗段是兑现的最后一刀。主角的基础攻击恒存在——这是项目拍板:若基线为零,百分比增益乘上去永远是零,增益系统就空转了。攻击力域 [1, 999]、0 于加载期拒绝,行值读主角表。顺序固定:主角先手攻击顺位最前的存活敌人,随后按行序逐个存活敌人按本拍摇定技能还手;每个敌人依次走"按技能行兑现、结算伤害、执行上报(技能进冷却 + 保底计数)"三步且恰行动一次,主角不在其列。主角中途倒下,剩余敌人全部停手,直接进判定段。本段只开单——主角先手单与逐敌伤害技单攒到战斗段尾统一结账(见[伤害单据与伤害控制器](#伤害单据与伤害控制器所有伤害走同一道门)一节);施放技不涉伤害、照旧当场落行。
战斗段是兑现的最后一刀。主角的基础攻击恒存在——这是项目拍板:若基线为零,百分比增益乘上去永远是零,增益系统就空转了。攻击力域 [1, 999]、0 于加载期拒绝,行值读主角表。顺序固定:主角先基础攻击顺位最前的存活敌人,随后按行序逐个存活敌人按本拍摇定技能还手;每个敌人依次走"按技能行兑现、结算伤害、执行上报(技能进冷却 + 保底计数)"三步且恰行动一次,主角不在其列;**最后兑地图伤害账**——授予段暂存的全部伤害单按授予段事件序补提交,与主角单、敌方单一起攒到战斗段尾统一结账(见[伤害单据与伤害控制器](#伤害单据与伤害控制器所有伤害走同一道门)一节)。主角中途倒下,剩余敌人全部停手,地图伤害账整体不兑(逐单留「未生效(主角已倒下)」行),直接进判定段。施放技不涉伤害、照旧当场落行。案C 后授予段不产出伤害,主角进入战斗段时恒存活、场上恒有敌——先手必兑。
**开轮摇号与敌方技能兑现**(2026-09-16 敌人技能池批):敌人每拍做什么由开轮摇号决定——每轮轮次开始时,本系统在换算层排除冷却中技能,按行序逐敌从 `behavior_roll` 封闭流的独立子流摇定本拍动作写入实例池(首轮同样摇号;每轮恰摇一次;轮内刷新换图不重摇),随后冷却递减。摇定后、兑现前死亡 → 本拍技能作废、不动手(死亡即不动手)。结算战斗段只按技能行兑现:伤害技走三乘法链(见下),增益技记一行施放行并把状态效果按技能行持续回合挂入[增益状态](增益状态.md)容器——0 伤害动作不掷不折。池模板、技能行、冷却与保底语义归[敌人系统](敌人系统.md)(引用不转述)。
@@ -201,7 +201,7 @@ percent 类(每结算、每层): E = |层数 × 行值| ÷ 100 ×
增益池乘区(含敌方防御池)→ 向下取整 → 伤害下限 max(1,·) → 必中附加分量 rider(2026-09-19 新效应词汇批——伤害技 rider_mult 字段:max(伤害下限, floor(攻击基线 × rider_mult)),独立必中加项、不进乘区、不出暴击;无字段 = 无此步)
```
主角先手攻击由三个分量逐项取整后相加:基础分量(攻击力经增益修正,可被池封顶压到零;**类型 = 主角 `attack_type` 表值**——2026-09-18 营地扩展前置批:基础攻击量与攻击类型抽象分离,基础分量不再恒属普通,缺省 normal 向后兼容)、穿刺分量、魔法分量。**攻击类型是伤害的属性轴**——它只决定这个分量查甲效表的哪一行,定义里不含任何棋盘来源。分量各自查表后取整相加;甲效表把攻击类型与敌方护甲类型交叉成一张 3×3 **克制修正矩阵(加法点数)**——2026-09-18 加法核换装:每个分量在掷点/暴击折算取整后 **+ 克制修正点数**(原百分比乘区退役):
主角先手攻击 = 单一基础分量(2026-09-19 充能退役批定稿;量 = 攻击力经增益修正,可被池封顶压到零;**类型 = 主角 `attack_type` 表值**——2026-09-18 营地扩展前置批:基础攻击量与攻击类型抽象分离,基础分量不再恒属普通,缺省 normal 向后兼容)。**攻击类型是伤害的属性轴**——它只决定这个分量查甲效表的哪一行,定义里不含任何棋盘来源。分量查表取整;甲效表把攻击类型与敌方护甲类型交叉成一张 3×3 **克制修正矩阵(加法点数)**——2026-09-18 加法核换装:每个分量在掷点/暴击折算取整后 **+ 克制修正点数**(原百分比乘区退役):
| 攻击类型 \ 护甲类型 | 轻甲 | 魔法护甲 | 重甲 | 语义 |
|---|---|---|---|---|
@@ -213,7 +213,7 @@ percent 类(每结算、每层): E = |层数 × 行值| ÷ 100 ×
主角攻击 = 单一基础分量(2026-09-19 充能退役批):量 = 攻击力基线(表值),类型 = 主角表 `attack_type`(营地永久强化换型 = 改字段;未来冒险前参数面承接"按关配型"的策略位)。原"普通 + 穿刺/魔法充能三分量"模型整体退役——挖掘期与战斗期之间不再有弹药供给线,克制应对从局内攒桶改为冒险前配型 + 棋盘火力(穿刺弹/魔法矢等直伤奖励道具,消费面不变)。
**护甲等级掷点:必中、非归零,只吃基础攻击分量**(2026-09-16 定稿落地,判定式与全部数值已拍板;判定对象措辞随敌人技能池批改述)。防守方由此多了一条数值轴——护甲等级(数据键 `armor_class`):攻击永远命中,没有 miss、没有零收益白回合;只有吃掷点的分量在掷点低于防守方护甲等级时按减伤档位打折,档位再重也不归零。判定式:攻击结算时掷单骰(骰面读表),掷点 ≥ 防守方护甲等级 + 攻击加成 → 全额;掷点 < 护甲等级按缺口(护甲等级 − 掷点)查减伤档位表打折——边界与档值读 `settlement.tres` 减伤档位表,三档皆非零档。暴击:天然最大面(读表)使该次基础攻击分量 ×暴击倍率(读表),双方同规,且天然最大面恒全额(暴击与折扣互斥;天然最大面〔nat20〕暴击是掷点层概念,与技能重击〔池技能〕严格区分——两层不得混述)。伤害下限:**任何来源的伤害落地**至少 damage_floor(读表,全局 max(damage_floor, ·)——2026-09-20 用户拍板扩全来源:攻击双方、棋盘直伤与爆裂、地形变异、负向反噬;伤害取值域 [1, +∞),**不设上限**)——"被减伤归零 v=0"零值伤害行语义随批退役,重档折扣的攻击行在行文本记"被压制"。掷点范围:只有基础攻击分量吃掷点——主角先手攻击的普通分量,敌方技能的基础伤害分量(= 攻击基线 × 技能伤害倍率,普通攻击倍率 1 为特例);无伤害分量的技能(增益/妨害类)不掷不折;棋盘来源一律无视护甲等级——爆裂、清障炸药、奖励即时伤害、技能必中附加分量(rider,2026-09-19)全部必中全额不掷,这是本机制的边界切口,与"奖励/惩罚必中"同构。护甲等级(数值轴,掷点打折)与护甲类型(属性轴,克制修正)严格分离:护甲类型不做护甲等级映射,克制修正点数读表、消费面不变,两概念在文档、表字段与代码键中不得混用。数值载体:主角与敌方护甲等级行值读 hero / enemy 表的 armor_class 列(正式行值归怪物设定批,登记[待办清单](../../06-待办清单.md)),ac_up(护甲强化)在其上加算(幅度/层数读 `status_effects.tres`)。攻击加成(`attack_bonus`)为结构位预留字段,切片恒 0,未来归元进度 / 武器附魔投值。掷点时机在结算战斗段内、每次基础攻击伤害计算时判定,消费 `armor_roll` 封闭流(逐次掷逐次取号,可逐位回放)。
**护甲等级掷点:必中、非归零,只吃基础攻击分量**(2026-09-16 定稿落地,判定式与全部数值已拍板;判定对象措辞随敌人技能池批改述)。防守方由此多了一条数值轴——护甲等级(数据键 `armor_class`):攻击永远命中,没有 miss、没有零收益白回合;只有吃掷点的分量在掷点低于防守方护甲等级时按减伤档位打折,档位再重也不归零。判定式:攻击结算时掷单骰(骰面读表),掷点 ≥ 防守方护甲等级 + 攻击加成 → 全额;掷点 < 护甲等级按缺口(护甲等级 − 掷点)查减伤档位表打折——边界与档值读 `settlement.tres` 减伤档位表,三档皆非零档。暴击:天然最大面(读表)使该次基础攻击分量 ×暴击倍率(读表),双方同规,且天然最大面恒全额(暴击与折扣互斥;天然最大面〔nat20〕暴击是掷点层概念,与技能重击〔池技能〕严格区分——两层不得混述)。伤害下限:**任何来源的伤害落地**至少 damage_floor(读表,全局 max(damage_floor, ·)——2026-09-20 用户拍板扩全来源:攻击双方、棋盘直伤与爆裂、地形变异、负向反噬;伤害取值域 [1, +∞),**不设上限**)——"被减伤归零 v=0"零值伤害行语义随批退役,重档折扣的攻击行在行文本记"被压制"。掷点范围:只有基础攻击分量吃掷点——主角先手攻击的基础分量,敌方技能的基础伤害分量(= 攻击基线 × 技能伤害倍率,普通攻击倍率 1 为特例);无伤害分量的技能(增益/妨害类)不掷不折;棋盘来源一律无视护甲等级——爆裂、清障炸药、奖励即时伤害、技能必中附加分量(rider,2026-09-19)全部必中全额不掷,这是本机制的边界切口,与"奖励/惩罚必中"同构。护甲等级(数值轴,掷点打折)与护甲类型(属性轴,克制修正)严格分离:护甲类型不做护甲等级映射,克制修正点数读表、消费面不变,两概念在文档、表字段与代码键中不得混用。数值载体:主角与敌方护甲等级行值读 hero / enemy 表的 armor_class 列(正式行值归怪物设定批,登记[待办清单](../../06-待办清单.md)),ac_up(护甲强化)在其上加算(幅度/层数读 `status_effects.tres`)。攻击加成(`attack_bonus`)为结构位预留字段,切片恒 0,未来归元进度 / 武器附魔投值。掷点时机在结算战斗段内、每次基础攻击伤害计算时判定,消费 `armor_roll` 封闭流(逐次掷逐次取号,可逐位回放)。
EV 参考数不入正文(派生读数,需要时按判定式与现行表值自行复算);旧 defense_up 的减伤墙已整体退役换装为 AC(无双轨,见版本历史)。微调旋钮 = 档位边界与档位值,不动护甲等级值。换装点锚定:基准 AC(读 hero 表)自带的方向性偏移与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)已登记的加难杠杆扫描合并处理;其生存链区间模型按掷点带宽口径复核(带宽含暴击档与折扣档),"零红档"验收保留。
@@ -227,7 +227,7 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
护甲等级掷点:掷单骰(骰面读表),掷点 ≥ 护甲等级 + 攻击加成 → 全额;低掷按缺口查减伤档位表(边界与档值读表,无零档)
暴击:天然最大面(读表)→ 该次基础攻击分量 ×暴击倍率(读表)且恒全额(双方同规;掷点层概念,与技能重击严格区分)
伤害下限:任何来源的伤害落地 ≥ damage_floor(读表,全局 max(damage_floor, ·)——折扣与池归零都不产生 v=0 伤害行;2026-09-20 扩全来源,取值域 [1, +∞))
吃掷点分量 = 主角普通分量 / 敌方技能基础伤害分量;穿刺、魔法、增益/妨害施放、必中附加分量与棋盘来源伤害不掷不折
吃掷点分量 = 主角基础分量 / 敌方技能基础伤害分量;穿刺、魔法、增益/妨害施放、必中附加分量与棋盘来源伤害不掷不折
治疗量 = min( 当前生命 + 表值, 生命上限 )
```
@@ -235,7 +235,7 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
|---|---|
| 修正池封顶 | 同侧百分比修正加算后每池独立收口 ±100 百分点;乘数可为 0——输出压制触池底时落地伤害由全局下限保底 damage_floor(读表)(叠满免伤归零的结构面已随护甲等级换装消失) |
| 伤害下限 | 任何来源的伤害落地至少 damage_floor(读表,全局 max(damage_floor, ·)——2026-09-20 扩全来源:攻击双方/棋盘直伤/地形变异/负向反噬,取值域 [1, +∞) 不设上限);"被减伤归零 v=0"零值伤害行语义退役,重档折扣行文本记"被压制"——免伤与零输出仍逐行可见 |
| 护甲等级掷点 | 必中非归零:掷单骰(骰面读表)对防守方护甲等级 + 攻击加成(恒 0),低掷按缺口查减伤档位表(读表)三档折扣、档位不设零档;天然最大面暴击 ×暴击倍率(读表)恒全额;只吃基础攻击分量(主角普通分量、敌方技能基础伤害分量),棋盘来源伤害与增益施放不掷不折 |
| 护甲等级掷点 | 必中非归零:掷单骰(骰面读表)对防守方护甲等级 + 攻击加成(恒 0),低掷按缺口查减伤档位表(读表)三档折扣、档位不设零档;天然最大面暴击 ×暴击倍率(读表)恒全额;只吃基础攻击分量(主角基础分量、敌方技能基础伤害分量),棋盘来源伤害与增益施放不掷不折 |
| 溢杀 | 一刀超出目标剩余生命的部分丢弃:不转移给下一个敌人、不存续、无负生命中间态 |
| 治疗 | 生命不溢出上限;满血正向治疗零兑付,记"奖励未生效"行 |
| 死亡判定 | 生命归 0 即倒下;敌人受击即死;主角倒下战斗段立即短路;判定段先判主角、再判敌人(防御性次序) |
@@ -301,7 +301,7 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
2. 挖掘期本系统只缓冲事实流(开格、标旗入结算队列),不做任何兑付。
3. 轮末自动触发五段结算,触发与事件到达序无关。
4. 授予段按判定基线过滤(被挖开的旗不入判定),再按极性矩阵三批兑现:开安全格兑正向(插旗安全格直挖 = 四情况④零奖励作废行)、开雷格 / 标错旗兑负向(插旗雷格直挖照常——四情况②)、清图发清图奖励对象(完美乘数读 settlement.tres p_perfect)。
5. 增益合成、主角先手加逐敌按摇定技能兑付(伤害技三乘法链 / 增益技施放行)、衰减恰好一次。
5. 增益合成、主角先手加逐敌按摇定技能兑付(伤害技三乘法链 / 增益技施放行)加地图伤害账殿后(暂存单随战斗段末统一结账)、衰减恰好一次。
6. 判定段先主角后敌人:继续通知同图、清图换图续轮、胜负走战斗结束清理(秘宝背包不清)。
7. 明细流水全程落行,供呈现、回放与导出。
@@ -344,7 +344,7 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
- 完美排雷:零误标且至少一面标中时第二份兑付恰一次并发高光行;出现误标或零标中则无高光;计数换图重置。
- 开轮摇号:每轮恰摇一次(首轮同样;轮内刷新换图不重摇);摇定后兑现前死亡 → 本拍技能作废(零敌方行动行)、不进冷却不进保底计数;已兑现技能进冷却、保底计数按执行结果更新。
- 战斗段次序:主角先手后逐敌"按摇定技能行兑现、结算伤害、执行上报"各恰一次;主角倒下立即短路,剩余敌人不行动。
- 护甲等级掷点:吃掷点分量(主角普通分量、敌方技能基础伤害分量)逐次掷单骰(骰面读表)——掷点 ≥ 防守方护甲等级 + 攻击加成全额兑付;低掷按缺口查减伤档位表(边界与档值读表),档位不设零档;天然最大面暴击该分量 ×暴击倍率(读表)且恒全额;穿刺/魔法分量与棋盘来源伤害(爆裂、清障炸药、奖励即时)、必中附加分量及增益/妨害施放不掷不折。
- 护甲等级掷点:吃掷点分量(主角基础分量、敌方技能基础伤害分量)逐次掷单骰(骰面读表)——掷点 ≥ 防守方护甲等级 + 攻击加成全额兑付;低掷按缺口查减伤档位表(边界与档值读表),档位不设零档;天然最大面暴击该分量 ×暴击倍率(读表)且恒全额;穿刺/魔法分量与棋盘来源伤害(爆裂、清障炸药、奖励即时)、必中附加分量及增益/妨害施放不掷不折。
- 新效应词汇(2026-09-19):伤害技 rider_mult 行的每次攻击,伤害行携带 rider 值且终值 = max(伤害下限, 主分量链结果) + rider(停手轮零池下逐拍精确复算);rider 键只随带 rider_mult 的技能行出现;妨害技 = 施放行 + 状态按 target_side 落主角(投掷阈值随行可读下调),冷却/保底/死亡作废三闸无一例外。
- 伤害下限与留档:任何来源的伤害落地 ≥ damage_floor(读表,2026-09-20 扩全来源),全流水零 v=0 伤害行、零"被减伤归零"行;掷点读数、护甲等级与档位随伤害行留档,天然最大面(nat20)行带暴击标记。
- 数值边界:伤害下限保底后全程无零值/负值伤害;溢杀丢弃不转移;治疗封顶不溢出。
@@ -374,13 +374,13 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
| v0.8 | 2026-09-15 | **护甲等级批(用户拍板登记,只改文档与 registry、不动代码)**:战斗段新增护甲等级掷点规则——必中、非归零,掷点低于防守方护甲等级按减伤档位折扣,没有 miss、没有零收益白回合;只吃基础攻击分量(主角普通分量 / 敌方攻击拍与重击拍基线),穿刺/魔法充能分量不吃;棋盘来源(伏击附加、道具、清障炸药、奖励即时)一律无视;护甲等级(数值轴,数据键 `armor_class`)与护甲类型(克制属性轴)命名区分成文。随机口径修订:结算换算层首次引入回合内随机,可回放契约从"结算路径零随机"改为"封闭随机流可回放"(同种子同输入逐位复现);开战掷骰属初始化随机维持不变。调参表新增护甲等级掷点 / 减伤档位表 / `armor_class` 三行(全部 provisional 未定值);伤害行补掷点读数与折扣档位随行留档(行型 10 类封闭不变);验收标准新增护甲等级掷点与折扣零值归路两条、可回放条改封闭随机流口径;EV 中性引入成文(期望伤害对齐现行表值,"零红档"验收保留);待拍板新增"掷点形式与数值域""掷点的随机流归属"两条 |
| v0.9 | 2026-09-16 | 新增「呈现只读面」节(06 清单「呈现只读面契约登记缺口」闭合):把切片已实现的呈现面函数与信号登记为对外契约——呈现状态快照 `presentation_snapshot`、战斗进行中谓词 `is_battle_live`、奖励身份查询 `query_reward_identity`、结算快照信号 `settlement_snapshot`、战斗结束信号 `battle_finished` 五件成文(载荷字段、消费方、销毁前捕获语义),并登记"呈现层唯一状态读取出口、禁链式穿透"的出口纪律与诊断观测面的非契约定位;依赖与输出表 HUD 框架下游行补指路 |
| v0.10 | 2026-09-16 | **护甲等级掷点批·定稿落地(用户拍板,数字即规范——与敌人系统 / 难度曲线与Boss / registry / 切片代码同批)**:判定式定稿——掷 1d20,掷点 ≥ 防守方护甲等级 + 攻击加成(结构位 `attack_bonus`,切片恒 0)→ 全额,低掷按缺口三档折扣(1-3 → ×0.75 · 4-7 → ×0.5 · 8+ → ×0.25,无零档);nat20 暴击该基础攻击分量 ×2 且恒全额(双方同规);伤害下限全局 max(1, ·)(`damage_floor` = 1)——"被减伤归零 v=0"零值伤害行语义退役,重档折扣行文本记"被压制";百分比减伤增益 defense_up 整体退役换装 ac_up(护甲强化 +1 AC/层 ×2 层,`unit=ac` 新量纲、不入任何池,无双轨),off_guard 与池结构零改动;护甲等级与护甲类型分离成文(数值轴 / 属性轴,不做映射)。数值载体:主角 armor_class 10(暂定)、敌方首关 0(暂定,正式行值归怪物设定批,登记待办清单);掷点流归属定稿 = `armor_roll` 封闭流(逐次掷逐次取号,可逐位回放),调参表掷点/档位/下限/加成五行由未定改拍板值;EV 参考数成文(AC10 21.25% / AC11 25% / AC12 28.75%,按判定式复算),换装点锚定(基准 AC10 自带约 −21% 敌方输出期望)与加难杠杆扫描合并处理;验收标准改写掷点条目 + 新增伤害下限与留档条目;切片同批:settlement.tres 七参数入表、战斗段掷点判定/暴击/下限/行留档(roll/ac/tier/crit 字段)、armor_roll 流接入 rng_service(黄金向量 m=42 scope0 = 4806095330042243845)、零值伤害行分支删除、冒烟护栏与掷点行为断言(nat20 种子 / AC12 档位分布 / 池触底保底 / 棋盘必中)、英雄卡与敌人卡 AC 展示、ac_up 状态槽图标、nat20 金框高亮 |
| v0.11 | 2026-09-16 | **敌人技能池批(用户拍板,设计权威 docs/proposal-skill-pool.md v1.0——与敌人系统 / 增益状态 / 难度曲线与Boss / 战斗表现 / HUD框架 / registry / 切片代码同批)**:① 随机口径两处 → 三处——技能摇号 `behavior_roll` 封闭流(回合内、开轮时点、步骤流之外,每敌按生成序派生独立子流、单敌轨迹可独立复放)入册,可回放契约扩写为"三处皆封闭流,同种子同输入逐位复现";② 战斗段成文开轮摇号与敌方技能兑现(每轮恰摇一次、轮内刷新不重摇、摇定后兑现前死亡作废)、增益技 = 施放行 + 状态授予(0 伤害不掷不折不兑伏击);③ 三乘法链成文(技能倍率乘在最前:基线 × 倍率 → AC 掷点 → 甲效 → 既有链不动);④ AC 判定对象措辞四处改述("敌方攻击拍与重击拍基线" → "敌方技能基础伤害分量",含正文/公式行/边界表/验收标准);⑤ 敌方防御池入乘区(`enemy_defense` 新池——硬化载体):主角攻击 Σ三分量后 ×(100+enemy_defense)/100,四池对称成文(hero_offense 现行走普通分量直乘的切片现状登记待办);⑥ 行型改型:蓄力行 `charge` → 施放行 `cast`(10 类封闭不变);⑦ 呈现快照敌人数组字段定稿(当前拍/行动环进度 → 摇定动作三字段 + 敌方增益 effects);验收标准新增开轮摇号条目、战斗段次序与可回放条目改写;切片同批:`_roll_round_actions` 开轮编排、技能摇号器独立服务类、单位容器实例池/冷却/执行上报、settlement.tres effect_pool_map 增 empower/fortify、施放行格式化、摇定动画位 |
| v0.11 | 2026-09-16 | **敌人技能池批(用户拍板,设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0——与敌人系统 / 增益状态 / 难度曲线与Boss / 战斗表现 / HUD框架 / registry / 切片代码同批)**:① 随机口径两处 → 三处——技能摇号 `behavior_roll` 封闭流(回合内、开轮时点、步骤流之外,每敌按生成序派生独立子流、单敌轨迹可独立复放)入册,可回放契约扩写为"三处皆封闭流,同种子同输入逐位复现";② 战斗段成文开轮摇号与敌方技能兑现(每轮恰摇一次、轮内刷新不重摇、摇定后兑现前死亡作废)、增益技 = 施放行 + 状态授予(0 伤害不掷不折不兑伏击);③ 三乘法链成文(技能倍率乘在最前:基线 × 倍率 → AC 掷点 → 甲效 → 既有链不动);④ AC 判定对象措辞四处改述("敌方攻击拍与重击拍基线" → "敌方技能基础伤害分量",含正文/公式行/边界表/验收标准);⑤ 敌方防御池入乘区(`enemy_defense` 新池——硬化载体):主角攻击 Σ三分量后 ×(100+enemy_defense)/100,四池对称成文(hero_offense 现行走普通分量直乘的切片现状登记待办);⑥ 行型改型:蓄力行 `charge` → 施放行 `cast`(10 类封闭不变);⑦ 呈现快照敌人数组字段定稿(当前拍/行动环进度 → 摇定动作三字段 + 敌方增益 effects);验收标准新增开轮摇号条目、战斗段次序与可回放条目改写;切片同批:`_roll_round_actions` 开轮编排、技能摇号器独立服务类、单位容器实例池/冷却/执行上报、settlement.tres effect_pool_map 增 empower/fortify、施放行格式化、摇定动画位 |
| v0.12 | 2026-09-17 | **数值纪律收口批:正文与调参表 knob 现行值改指路存根(事实源 `data/tables/*.tres` 与 registry),20 余处失同步值修正**——收益对照表参考敞口 12 / 完美乘数 200 改指路 settlement.tres(equivalence_ref_damage / p_perfect);伏击加层"+2 层"改"+stacks 层(读 reward.tres ambush_double 行)";充能供给表与 charge_grants 行"每格 1 / 上限 8 / 每雷 2"改 per_unit/cap 读表;三乘法链与甲效矩阵 1.5/1.0/0.5、150/100/50 改三档读表;掷点判定 1d20 / nat20 ×2 / 缺口档 ×0.75/×0.5/×0.25 / 边界 [3,7] / 档位 [75,50,25] / damage_floor=1 / AC 10·0 / ac_up +1×2 层全部改指路 settlement.tres·status_effects.tres·hero/enemy 表;EV 参考数(AC10 21.25% 等)与"旧 defense_up 满层 −60%"删除(派生读数 / 退役值,版本历史可查);调参表与验收标准同步 |
| v0.13 | 2026-09-18 | **营地扩展前置批·主角双轴可配置(用户指令,与敌人系统 / registry / 切片代码同批)**:① hero 表新增 armor_type({light, ward, heavy},缺省 light)——主角护甲类型轴可配置可修改,消费面 = 甲效矩阵(现行敌方攻击恒 normal 档 = 数值中性的结构位,轴生效待敌方技能攻击类型批);② hero 表新增 attack_type({normal, pierce, magic},缺省 normal)——**基础攻击量与攻击类型抽象分离**:基础分量类型不再硬编码普通、改读主角表值,营地永久强化"换成魔法/穿刺攻击"= 改字段,atk 量轴与掷点口径零改动;③ 同桶充能照加语义成文(基础分量与充能同型时,充能分量保持不掷不折);正文三分量表述、甲效矩阵"普通"行注记、分量固有属性措辞三处同步 |
| v0.14 | 2026-09-18 | **战斗数值结构修复批(2026-09-18 盘问会话用户拍板,与增益状态 / registry / 切片代码同批)**:① 主角侧乘区接线——hero_offense 池入主角攻击乘区:Σ三分量后 ×(100+hero_offense)/100 ×(100+enemy_defense)/100 两池串乘,增伤/乏力覆盖面 = 普通+穿刺+魔法 合计;attack_up 普通分量直乘旁路退役(正文甲效矩阵"普通"行注记、池乘区公式行、v0.11 切片现状注记三处同步销项);② off_guard(失衡)换装 AC 轴——unit percent→ac(幅度 provisional 归状态层重设计批),effect_pool_map 删 off_guard 键,hero_defense 池清空、结构保留,消费走既有掷点判定读法零改动;③ fortify(硬化)符号纠正——旧 +100 入敌方防御池实际 ×2 翻倍与"硬化=减伤"语义相反,改负值(读表)后主角攻击折半;④ weaken(削弱)叠层改续时——同名重复授予只刷新剩余结算数、层数恒 1,×2 叠满池触底 ×0 的免伤轮结构性根治(消饱和);duration 终值、off_guard 幅度、当量锚复算全部归状态层重设计批。切片同批:battle_orchestrator 池接线与直乘删除、status_effects.tres 三行、settlement.tres 删键、冒烟护栏(削弱续时 / 乘区接线 ×1.5·×0.75 / 硬化折半方向三组新断言,旧"削弱×2 池触底"采样通道随批退役) |
| v0.15 | 2026-09-18 | **甲效矩阵用户调参批(用户逐格给值,事实源 settlement.tres 五格改值、四格不动,零代码)**:普通行 ward 100→120 / heavy 100→50;穿刺行 light 100→80 / ward 150→120 / heavy 50→80;魔法行与普通-轻甲不动——「克制/中性/被克」三档结构与「普通行恒中性」退役,改五档(克制 / 弱克制 / 中性 / 弱被克 / 被克,档值读表)。矩阵消费面成文 = 主角侧(奖励直伤道具 / 主角攻击三分量 / 充能分量),敌方攻击不查矩阵、主角 armor_type 轴仍休眠(v0.13「敌方攻击恒 normal 档故中性」的归因改述——轴休眠是结构性的非数值性的)。语义列两行同步(穿刺「破不开重甲」重压语义弱化为与轻甲同档折损)。切片同批:settlement.tres 批注、冒烟矩阵三行断言改五档读数 + 乘区接线穿刺分量 3→2(3 点 ×80% 取整)随批改形,冒烟 300 项 0 失败 + 四探针 PASS;registry(enemy/hero armor_type 两行注记)与 敌人系统 / 难度曲线与Boss 三档措辞同步 |
| v0.16 | 2026-09-18 | **甲效矩阵加法核换装批(用户拍板数值语言——小整数加法核,与 01-核心循环 数值语言条款 / registry / 切片代码同批)**:量纲 percent→整数点数,三档(克制 +1/中性 0/被克 −1)九格改值〔normal 0/+1/−1、pierce −1/+1/0、magic 0/−1/+1〕,pierce×heavy = 0 中性为用户特别拍板;五档词表与百分比乘区退役(v0.15 的五档表随批短命退役,理由=个位数刻度假粒度);分量算术改述=折算取整后加修正点数;缺项回退 100→0;奖励直伤行 payload 键 effectiveness 保留、值语义改点数;池乘区/AC 折扣档/暴击保留百分比并成文粒度口径(数值语言条款:百分比仅此三处既有粗档+开发侧工具);切片同批:settlement.tres/settlement_table.gd/damage_math/battle_orchestrator/smoke/registry/01-核心循环同步 |
| v0.17 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0,与 敌人系统 / 增益状态 / registry / 切片代码同批)**:① 三乘法链尾部 +必中附加分量 rider(伤害技 rider_mult 字段:max(伤害下限, floor(攻击基线 × rider_mult))——后置加法、必中全额、不进乘区不出暴击、价位锚 0.75 = AC 折扣档最轻档;"固定值伤害"改形——固定值不随基线缩放与共享技能表前提冲突);② 增益/妨害技 = 同族施放行(0 伤害不掷不折不兑伏击),妨害状态按状态行 target_side 落主角——零新授予通道;③ 必中家族清单 +rider(掷点边界切口);④ 公式行/吃掷点行/验收标准三处同步 + 新效应词汇验收条目(rider 逐拍精确复算 + rider 键封闭 + 妨害落主角端到端);⑤ 实装面 = 仅 L2 Boss 卓尔(毒爆 +rider、新行蛛网束缚妨害→失衡),其余敌种不动;多段命中经用户拍板退役不入词汇表 |
| v0.17 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0,与 敌人系统 / 增益状态 / registry / 切片代码同批)**:① 三乘法链尾部 +必中附加分量 rider(伤害技 rider_mult 字段:max(伤害下限, floor(攻击基线 × rider_mult))——后置加法、必中全额、不进乘区不出暴击、价位锚 0.75 = AC 折扣档最轻档;"固定值伤害"改形——固定值不随基线缩放与共享技能表前提冲突);② 增益/妨害技 = 同族施放行(0 伤害不掷不折不兑伏击),妨害状态按状态行 target_side 落主角——零新授予通道;③ 必中家族清单 +rider(掷点边界切口);④ 公式行/吃掷点行/验收标准三处同步 + 新效应词汇验收条目(rider 逐拍精确复算 + rider 键封闭 + 妨害落主角端到端);⑤ 实装面 = 仅 L2 Boss 卓尔(毒爆 +rider、新行蛛网束缚妨害→失衡),其余敌种不动;多段命中经用户拍板退役不入词汇表 |
| v0.18 | 2026-09-19 | **插旗不可逆批(用户拍板全套落地,2026-09-18 提案转正;与排雷玩法 v0.5 / 行动经济 v0.4 / 地图战斗资源 v0.12 / registry / 切片代码同批)**:① 授予段「抵消过滤」改述「判定基线」——撤旗动作退役,旗判定以轮末在场旗为基线,被挖开的旗不入基线;② 新增插旗不可逆四情况兑付表:①标中照常 / ②插旗雷格直挖只吃挖雷惩罚标中不发 / ③标空照常 / ④插旗安全格直挖零惩罚零奖励(正向作废 + reward_ineffective 归因行);③ 挖格批兑付表补四情况分支;④ 标中资格措辞改「旗无移除手段」(拔旗重插通道消失);⑤ P0 闭环第 2/4 步与验收标准同步(「抵消过滤」条改「挖旗格兑付改判」)。切片同批:minesweeper_rules 挖旗格放行 + flag_pull 出目录 + dug_under_flag 事件标记、battle_orchestrator 情况④零奖励抑制、action_economy 表 flag_pull_ap_cost 删除、冒烟 317→327 项 0 失败(四情况探针 `_smoke_flag_irreversible_quadrants`) |
| v0.19 | 2026-09-20 | **伤害下限全来源批(用户拍板「任何伤害取值域 [1,+∞),最小值一定是 1」;与 06 清单「零伤害/无威胁组合的跨字段护栏」收口 / registry / 切片代码同批,台账 100)**:① 下限语义从"任何攻击落地伤害"扩为"任何来源的伤害落地"——攻击双方(原有)+棋盘克制直伤(counter_component 增 landed_floor 参数,空桶不吃修正恒 0 边界不变)+爆裂正向+负向反噬(穿刺陷阱/魔法反噬/heal 反噬)+地形变异 flat_damage,全部收进 damage_floor 闸内;② 取值域成文 [1, +∞) **不设上限**——「零伤害/无威胁组合」条目的跨表上界护栏半边随拍板裁决为不设(上不封顶),敌种攻击基线 0 的退化态经下限自然消解(0 基线攻击落地仍 ≥1,"无威胁敌"结构性不存在);③ 现行表值下零行为变更(棋盘直伤贴底值 2−1=1 本就在闸内),本批=结构保证+调参防误配;④ 判读口径/约束表/调参表/验收四处措辞同步;冒烟 352→355 项 0 失败(+贴底/穿透/空桶三断言)。版本号注记:v0.19 在伏击上限删除批(未合并分支)中已被占用,本条与之合并时以先落籍者为准顺延避让 |
| v0.20 | 2026-09-20 | **伏击单轮上限删除批(用户拍板——与 敌人系统 / 地图战斗资源 / 难度曲线与Boss / registry / 切片代码同批)**:① 行型协议 10 类→9 类——溢出未生效行下线(唯一发射源 = 伏击上限截流,上限删除后零发射面);② 授予段伏击加层改直授无上限(反灾难护栏退役——一轮踩雷数由行动点预算天然封顶);③ 核验清单伏击守恒条改伏击池共享;④ 切片同批:enemy.tres 12 行字段删除、敌表校验/编排器截流/单位容器 F3 计划函数/日志视图 overflow 格式化删除、冒烟 blast 负向断言改直授累加(330 项 0 失败) |
@@ -389,3 +389,4 @@ EV 参考数不入正文(派生读数,需要时按判定式与现行表值
| v0.23 | 2026-09-20 | **GP+商店房批(用户拍板——与 关卡节点地图 v1.1 / 冒险结构 v0.5 / 地图战斗资源 v0.15 / 难度曲线与Boss v0.18 / registry / 切片代码同批;版本号注记:v0.22 已被充能退役批占用,表尾顺延)**:① 呈现只读面表 battle_finished 载荷 +gp_dropped(掉落掷定 + 关级加值 + 战斗内缓冲的合计——字段增删走本文修订条款兑现);② 授予段兑付形态表新增 GP 缓冲行:gp 正/负向(金币袋 / 破财——九型批)兑付 = 战斗内 GP 缓冲 ±power,战斗完成统一上抛入钱包账本(账本归冒险结构),战斗域零钱包状态;③ 随机口径六处→七处:战斗结束掉落掷定消费 `gp_drop` 封闭流(出口随机、步骤流之外);九型字典措辞与验收标准可回放条目同步 |
| v0.24 | 2026-09-24 | **伤害管线单据化批(用户三裁决——与切片代码同批,06 台账 148)**:新增「伤害单据与伤害控制器」一节——伤害对象抽象补全:五族伤害来源收口伤害控制器单点管线、兑付配方封闭五种;三裁决落文——①结账时机双模式(现行 = 段界结账:授予段尾 / 清图批同步点 / 战斗段尾;开单即结保留为回切结构位,切换走代码不走调参)②目标结账时刻照规则解析③死亡事件由单位自行宣布(怪死其未结单据作废、主角死兑付终止);授予段兑付与战斗段两节补结账时点句;验收标准 +伤害单据管线条目。切片同批:`core/damage_controller.gd` 新建(单据构造/开单/结账/死亡事件消费/管线算术收口)、battle_orchestrator 六调用点改开单、掷点/折扣/克制/池乘/攻击行文本助手迁出(`_defender_ac`/`_clamped_pool` 留薄委托)、unit_container 增 `unit_died` 信号;冒烟 557 项 0 失败双模式全绿 + A/B 对拍四配置全确定且真实分岔(行数恒等、纯次序位移);历史基线读数自本批起以段界结账口径为准(重测归曲线调参批) |
| v0.25 | 2026-10-05 | **挖掘风险不等式判式换代(迭代14②号卡 T3/T4——与行动经济/难度曲线与Boss/registry 同批)**:①收益对照表补 gp/ap 当量口径注记(gp=flat power 代理 3/2 假设 A5 口径空白登记、ap=flat 表值 1 机会成本口径仅登记假设 A6,精确口径归商店批复核);②验收标准 +条款3 对账条(聚合健康式+β 带逐 u 检算 / 旗溢价兑付三形态覆盖·标空与挖格不乘·同池零触碰);③T4 机制载体 = settlement.tres 新键 flag_hit_premium=125(percent 域 provisional)——标中旗正向兑付 ×(1+δ),整数四舍五入取整与伤害管线 floor 分域(registry 随批登记);DamageController 零改、雷安同池冻结不动、直伤雷 6/8/8 与 p_perfect 不动 |
| v0.26 | 2026-10-06 | **地图伤害账殿后批(案C,用户裁——歧义质询触发)**:①五段总览①③行改写——授予段只兑非伤害形态,伤害形态兑付(爆裂/直伤/反噬/地形变异/战旗军规/熔火反噬等)暂存到战斗段末、按「主角先手→逐敌还手→地图账」统一落地;②战斗段节补地图账殿后与死亡守卫(主角死于怪物→暂存单整体不兑,逐单留「未生效(主角已倒下)」行);③结账时机双模式改述:现行=段界结账+地图账殿后,清图批同步读数改「将兑付」回报口径(完美第二份依据开单时点事实),历史基线读数以 2026-10-06 前授予段结账口径封存;④兑付形态表 blast 正向/heal 负向兑付时点改战斗段末;⑤P0 闭环第 5 步补地图账;⑥顺手清充能退役遗留:三分量句改单分量、三处「主角普通分量」改「基础分量」。切片同批:battle_orchestrator 暂存闸 `_defer_board_damage`/`_deferred_board` + `_submit` 案C 分流 + `_outcome_of` + 战斗段末补提交块 + 授予段四处直提改走闸;冒烟 783 项 0 失败(新增案C 段内序断言+行相位分类器换代)+ run_all 17 套全绿 + probe_gate --click 全绿;旧行为 MC 锚全数作废,重锚归数值批 |
@@ -110,7 +110,7 @@
|---|---|---|
| skill_id | 全部 | 主键,池条目引用键 |
| display_name | 全部 | 玩家可见名(明细行与动画共用) |
| type | 全部 | 封闭枚举 {普通攻击, 伤害, 增益, 妨害}——**新效应词汇批 2026-09-19 由三扩四**(设计权威 docs/proposal-status-vocabulary.md v1.0;多段命中经用户拍板退役不入枚举);新类型走本文修订 |
| type | 全部 | 封闭枚举 {普通攻击, 伤害, 增益, 妨害}——**新效应词汇批 2026-09-19 由三扩四**(设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0;多段命中经用户拍板退役不入枚举);新类型走本文修订 |
| damage_mult | 仅伤害 | 伤害倍率;域 [1.1, 16] provisional。普通攻击恒 1、不可配 |
| rider_mult | 仅伤害、可省 | **必中附加分量(2026-09-19 新增)**:域 (0, 1],缺省无字段 = 无附加;分量值 = max(伤害下限, floor(攻击基线 × rider_mult))——随施放者攻击基线缩放,后置加法、必中全额、不进乘区、不出暴击(后置加法同族);价位锚 0.75 = AC 折扣档最轻档"不掉档的稳定伤害" |
| cooldown_beats | 全部 | 施放后连续 N 拍不可摇中;普通攻击恒 0、不可配 |
@@ -141,7 +141,7 @@
首轮同样摇号;每轮恰摇一次,轮内刷新换图不重摇。摇号随机走封闭随机流、每敌按生成序派生独立子流——单敌出招轨迹可独立复放、互不穿插;本系统自身语义零随机不变,单位容器收到的是确定结果(armor_roll 先例同构)。
死亡即不动手(保留):摇定后、兑现前死亡(主角先手 / 授予段直伤),本拍技能作废——不动手、不进冷却、不进保底计数;其余存活敌人照常。拍结构保留:**每结算每存活敌恰行动一次、按行序、先作用后推进**——变的只是"轮到什么",由固定剧本改为摇号。同种敌人不再锁步:各自实例池独立摇号、独立冷却,怪物 1 的重击在冷却里不影响怪物 2,轨迹分歧是涌现,不设开战分配机制。
死亡即不动手(保留):摇定后、兑现前死亡(主角先手 / 更早兑现的敌方伤害技),本拍技能作废——不动手、不进冷却、不进保底计数;其余存活敌人照常。拍结构保留:**每结算每存活敌恰行动一次、按行序、先作用后推进**——变的只是"轮到什么",由固定剧本改为摇号。同种敌人不再锁步:各自实例池独立摇号、独立冷却,怪物 1 的重击在冷却里不影响怪物 2,轨迹分歧是涌现,不设开战分配机制。
蓄力语义(2026-09-16 纠偏定稿):蓄力不是重击前奏——它是一行增益技:0 伤害动作,施加 empower 状态(幅度读 `status_effects.tres`),持续 1 个有效结算(provisional)。旧环"蓄力→猛击"的固定配对是哥布林弹珠的拷贝(给玩家输出窗口用的),随行为环一并退役;蓄力与重击之间**没有任何组合语义**——增益与技能倍率恰好同拍只是增益倍率 × 技能倍率的两层乘法共存(增益幅度 × 增益幅度 = 两层乘法读表可得),蓄力后摇中普通攻击则是增益倍率的加成平砍,两者同为平常事,不是设计的连招。技能冷却(几拍内不能再摇中,技能行属性)与增益持续(状态挂几回合,状态行属性)是两个计时器,互不相干。施放行 = 0 伤害动作,不掷不折(原"零兑付、不读伏击"的读怪奖励语义随伏击退役作废——2026-09-20 八型批)。
@@ -167,7 +167,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
即:普攻完全不可预测;特殊技有一次类型级预告,不可撤销,但给"继续挖还是停手"的决策依据。
**半血解锁弹出规格(2026-10-05 技能池执行批,D8 用户裁)**:Boss 血量降至 `unlock_hp_pct` 阈值(池条目字段,域 [1,99],缺省无字段=无门槛)时,下一个开轮摇号前出一次归因明细行「XX 解锁了 YY」(高光键 `skill_unlock`,行型复用 highlight 零新增);呈现层对该行弹**一次性技能名 toast**(轻量提示,非演出——零动画资产、不改演出规格),只报技能名不报数值,池与权重不公开纪律不变。解锁=单向闩(治疗抬血不解锁);锁定条目双面过滤(不进可摇集合与保底特殊技集合——保底不得逼出未解锁技);解锁后冷却初值 0 即可摇。投放纪律=字段通用、仅 Boss 行投放(enemy 表无 boss 编码位,硬闸须跨表查节点类型——不做硬闸,本句即文档纪律登记)。旧环"下一拍全程亮出(意图徽标 + 环点)"的预告粒度随行为环退役。技能动画的攻/防系映射归[战斗表现](战斗表现.md),敌人侧摇定动画位归[HUD 框架](../表现与支撑/HUD框架.md)(呈现载体 = 站桩立绘,2026-09-20 全站桩拍板),本系统只锁上面这张三档规格。
**半血解锁弹出规格(2026-10-05 技能池执行批,D8 用户裁;内容数据驱动扩展批 T1 补登记——解锁判定点=通用事件「血量阈值 `enemy_hp_threshold`」的发射点,对所有带 `unlock_hp_pct` 字段的敌人逐个发射、非 Boss 专属——Boss 语义留给订阅条件判定)**:Boss 血量降至 `unlock_hp_pct` 阈值(池条目字段,域 [1,99],缺省无字段=无门槛)时,下一个开轮摇号前出一次归因明细行「XX 解锁了 YY」(高光键 `skill_unlock`,行型复用 highlight 零新增);呈现层对该行弹**一次性技能名 toast**(轻量提示,非演出——零动画资产、不改演出规格),只报技能名不报数值,池与权重不公开纪律不变。解锁=单向闩(治疗抬血不解锁);锁定条目双面过滤(不进可摇集合与保底特殊技集合——保底不得逼出未解锁技);解锁后冷却初值 0 即可摇。投放纪律=字段通用、仅 Boss 行投放(enemy 表无 boss 编码位,硬闸须跨表查节点类型——不做硬闸,本句即文档纪律登记)。旧环"下一拍全程亮出(意图徽标 + 环点)"的预告粒度随行为环退役。技能动画的攻/防系映射归[战斗表现](战斗表现.md),敌人侧摇定动画位归[HUD 框架](../表现与支撑/HUD框架.md)(呈现载体 = 站桩立绘,2026-09-20 全站桩拍板),本系统只锁上面这张三档规格。
| 规格 | 含义 |
|---|---|
@@ -202,7 +202,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
1. 战斗开始:战斗结算按遭遇坐标调本系统生成单位——读表快照实例化本战数量的敌人(池模板快照成实例池、冷却全零),主角以血量入参生成。
2. 开轮摇号:战斗结算换算层排除冷却中技能、按行序逐敌摇定本拍动作写入实例池,随后冷却递减(首轮同样摇;轮内刷新换图不重摇)。
3. 挖掘期踩雷:事实经战斗结算转化为警觉施加——每颗雷恰一次、逐层记账(无上限)。
4. 每轮结算:主角先手攻击顺位最前的存活敌人;每个存活敌人按摇定技能行兑付(伤害技 = 基线 × 倍率,增益技 = 施放行 + 状态授予)。
4. 每轮结算战斗段:主角先基础攻击顺位最前的存活敌人,随后每个存活敌人按摇定技能行兑付(伤害技 = 基线 × 倍率,增益技 = 施放行 + 状态授予);地图奖励与惩罚的伤害兑付殿后到战斗段末统一落地(案C 2026-10-06 用户裁,见战斗结算)。
5. 受击上报、血量递减;归 0 即移出顺位(摇定后兑现前死亡 → 本拍作废不进账)。
6. 执行上报:已兑现的技能进冷却、保底计数更新(普攻 +1 / 特殊技归零)。
7. 敌全灭或主角归零,回流战斗结算作胜负判定素材。
@@ -215,7 +215,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
| P1 | 情境条件触发器(低血触发防御、玩家停手时偷袭技等) | 载体 = 技能行触发条件字段加列;登记[待办清单](../../06-待办清单.md) |
| P1 | 个体化变体池(A 型好斗 / B 型守势、精英专属池) | 共识点 A 的 A2 案;登记[待办清单](../../06-待办清单.md) |
| P1 | 全局特殊间隔旋钮 | 特殊技背靠背实测仍嫌时的备用闸;登记[待办清单](../../06-待办清单.md) |
| P1 | 新效应词汇批(妨害技 + 必中附加分量已实装 2026-09-19——设计权威 docs/proposal-status-vocabulary.md v1.0,实装面 = L2 Boss 卓尔;多段命中经用户拍板退役) | 妨害类型 + rider_mult 字段已落地;登记[待办清单](../../06-待办清单.md)(已解决移除,去向见台账) |
| P1 | 新效应词汇批(妨害技 + 必中附加分量已实装 2026-09-19——设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0,实装面 = L2 Boss 卓尔;多段命中经用户拍板退役) | 妨害类型 + rider_mult 字段已落地;登记[待办清单](../../06-待办清单.md)(已解决移除,去向见台账) |
| P1 | 敌种名录扩容与投放节奏(含第二关池与投放) | 投放节奏是关卡命脉,归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
| P1 | 单体寻址("只打某一个敌人"的目标指定) | 首个单体效果上线时随批裁决归集语义与呈现 |
| P2 | 敌方技能图鉴 / 学习呈现(玩家侧技能知识系统) | 池不公开口径下的进阶信息面;登记[待办清单](../../06-待办清单.md) |
@@ -289,12 +289,13 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
| v0.2 | 2026-09-15 | 教学位掷骰口径自洽(随[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)同批修订):unit_count 字段说明、地精敌种定位与现行行值句中"教学位固定 1 只/固定不掷"改为 ×[1,2] 开战掷定 |
| v0.3 | 2026-09-15 | **护甲等级批(用户拍板登记,与战斗结算 / 难度曲线与Boss / registry 同批,不动代码)**:敌人表与主角表 schema 各增 armor_class(护甲等级)字段(取值域随掷点形式定稿,provisional);三敌种表补护甲等级列(行值未定);护甲等级(数值轴)与护甲类型(克制属性轴)命名区分成文;结构冻结清单"零随机"措辞按新口径修订——本系统自身语义零随机不变,掷点随机在战斗结算换算层按封闭随机流消费、可回放契约 = 同种子同输入逐位复现;待拍板新增"护甲等级行值未定"条目 |
| v0.4 | 2026-09-16 | **护甲等级掷点批·定稿落地(与战斗结算 / 难度曲线与Boss / registry / 切片代码同批)**:armor_class 域定稿 [0, 999](缺省 0 向后兼容);主角行值 10(暂定)、三敌种首关行值 0(暂定)——"行值未定"改"暂定值 + 待办",敌方正式行值归怪物设定批(第一关怪物 AC 相对较低,值待怪物设定投值,登记待办清单);敌种表护甲等级列同步落值;调参表两行改域与现行值 |
| v0.5 | 2026-09-16 | **敌人技能池批(用户拍板,设计权威 docs/proposal-skill-pool.md v1.0;与战斗结算 / 增益状态 / 难度曲线与Boss / 战斗表现 / HUD框架 / registry / 切片代码同批)**:行为环章节整体退役——固定出招剧本、拍枚举(攻击/蓄力/重击)、环指针、同种锁步、heavy_multiplier 字段全部废除;技能池语义成文(三层对象〔技能行/池模板/实例池〕、技能行词汇表、池构成纪律、两道闸〔全技能各自冷却 + 保底〕、开轮摇号时序、死亡作废、独立子流);蓄力语义改写(纯攻击增益技、与重击无组合语义——纠偏二;施放行继承零兑付伏击);Boss 专属身份改专属池承载;意图呈现改三档可见性(普攻零表示 / 特殊技类型级预告 / 暴击掷点层);敌人表 schema pattern → pool;调参表增技能表与池 EV 锚(含闸长期速率实测登记);验收标准按摇号口径重写 |
| v0.5 | 2026-09-16 | **敌人技能池批(用户拍板,设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0;与战斗结算 / 增益状态 / 难度曲线与Boss / 战斗表现 / HUD框架 / registry / 切片代码同批)**:行为环章节整体退役——固定出招剧本、拍枚举(攻击/蓄力/重击)、环指针、同种锁步、heavy_multiplier 字段全部废除;技能池语义成文(三层对象〔技能行/池模板/实例池〕、技能行词汇表、池构成纪律、两道闸〔全技能各自冷却 + 保底〕、开轮摇号时序、死亡作废、独立子流);蓄力语义改写(纯攻击增益技、与重击无组合语义——纠偏二;施放行继承零兑付伏击);Boss 专属身份改专属池承载;意图呈现改三档可见性(普攻零表示 / 特殊技类型级预告 / 暴击掷点层);敌人表 schema pattern → pool;调参表增技能表与池 EV 锚(含闸长期速率实测登记);验收标准按摇号口径重写 |
| v0.6 | 2026-09-17 | **文档降级为模板批(用户拍板,与难度曲线与Boss / 战斗结算同批)**:数值纪律定稿——本文只锁字段、取值域与规则,全部具体行值(敌种表池权重 / 护甲等级行值 / 两道闸表值 / 伏击每层附加与上限 / 技能行倍率与冷却 / 主角三字段 / 三敌种行值与池 EV 实测读数)自本文移除、一律读配置表(切片 `data/tables/` 与 registry);调参表三表删除"现行值"列改纯 schema 模板;伏击公式与验算改符号化(a = 每层伏击表值);验收标准同步去数值。背景:切片 `.tres` 数值压缩批后文档行值已滞后,双写失同步被实证 |
| v0.7 | 2026-09-17 | **数值纪律收口批:正文与调参表 knob 现行值改指路存根(事实源 `data/tables/*.tres` 与 registry),2 处失同步值修正**——共享技能表示例"熊地精 9×2=18"改符号化"基线 A × 技能倍率 M(行值读 enemy.tres / skills.tres)";蓄力语义"施加'攻击×2'状态""×2 遇 ×2 = ×4"改"施加 empower 状态(幅度读 status_effects.tres)",两层乘法组合语义保留符号表述 |
| v0.8 | 2026-09-18 | **营地扩展前置批 + 护甲类型重配(用户指令,与战斗结算 / registry / 切片代码同批)**:① hero 表新增 armor_type / attack_type 两根可配置轴(缺省 light / normal;主角字段表同步两行)——护甲类型轴入矩阵消费面(敌方技能攻击类型轴未开前数值中性),基础攻击类型轴 = 量与类型抽象分离的营地换型落点;② 敌种护甲类型行值重配(数据面):关卡 1 全部轻甲(食人魔酋长 heavy→light、熊地精两行 ward→light),关卡 2 除 Boss 蛛化卓尔精灵 heavy→ward(魔法甲)外全部轻甲(熊地精四行 ward→light,巨蜘蛛既有 light 不动);现行克制三角读数效果 = L1 克制轴中性化、L2 仅 Boss 战非中性(魔法矢 ×150 / 穿刺弹 ×50 对 Boss) |
| v0.9 | 2026-09-18 | **甲效矩阵用户调参批同步(零代码,事实源 settlement.tres 五格改值——详见[战斗结算](战斗结算.md) v0.15)**:主角字段表 armor_type 行注记归因改述——轴休眠的理由由「敌方攻击恒 normal 档故中性」(依赖普通行恒 100 的旧数值结构)改为「矩阵消费面 = 主角侧、敌方攻击不查克制矩阵」(结构性,与数值无关),轴生效仍待敌方技能攻击类型批。历史注记:v0.8 行「魔法矢 ×150 / 穿刺弹 ×50 对 Boss」与当时矩阵(穿刺×魔法甲=150 / 魔法×魔法甲=50)正反互倒,系当批笔误,按历史不改写留档,正确读数见战斗结算 |
| v0.10 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0,与 战斗结算 / 增益状态 / registry / 切片代码同批)**:① 技能类型枚举三→四(+妨害 debuff——对主角施减益的 0 伤害施放动作,字段复用 buff_ref/buff_duration,落点由状态行 target_side 路由〔增益 → 敌方侧 / 妨害 → 主角侧,施放类 side 守卫加载拒绝〕,执行与增益技同族施放行语义——不掷不折不兑付伏击);② 伤害技新字段 rider_mult(必中附加分量——"固定值伤害"改形:固定值不随基线缩放与共享技能表前提冲突,必中小倍率承载"躲不掉的稳定伤害");③ 池构成纪律 +每池妨害 ≤1;④ 意图三档特殊技预告扩三族(攻击系 ⚔ / 增益系 ✦ / 妨害系 ☠);⑤ 三词收敛两词——多段命中经用户拍板退役(无防御磨损体系,无对照机制),P1 字段位「命中段数」保留;⑥ 实装面 = 仅 L2 Boss 蛛化卓尔精灵(venom_burst + rider_mult 0.75;新行 web_snare 蛛网束缚 debuff→off_guard,首发载荷 = 失衡〔用户拍板〕,乏力 sapped 留作第二词汇),其余敌种不动 |
| v0.10 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0,与 战斗结算 / 增益状态 / registry / 切片代码同批)**:① 技能类型枚举三→四(+妨害 debuff——对主角施减益的 0 伤害施放动作,字段复用 buff_ref/buff_duration,落点由状态行 target_side 路由〔增益 → 敌方侧 / 妨害 → 主角侧,施放类 side 守卫加载拒绝〕,执行与增益技同族施放行语义——不掷不折不兑付伏击);② 伤害技新字段 rider_mult(必中附加分量——"固定值伤害"改形:固定值不随基线缩放与共享技能表前提冲突,必中小倍率承载"躲不掉的稳定伤害");③ 池构成纪律 +每池妨害 ≤1;④ 意图三档特殊技预告扩三族(攻击系 ⚔ / 增益系 ✦ / 妨害系 ☠);⑤ 三词收敛两词——多段命中经用户拍板退役(无防御磨损体系,无对照机制),P1 字段位「命中段数」保留;⑥ 实装面 = 仅 L2 Boss 蛛化卓尔精灵(venom_burst + rider_mult 0.75;新行 web_snare 蛛网束缚 debuff→off_guard,首发载荷 = 失衡〔用户拍板〕,乏力 sapped 留作第二词汇),其余敌种不动 |
| v0.11 | 2026-09-20 | **伏击单轮上限删除批(用户拍板——与 战斗结算 / 地图战斗资源 / 难度曲线与Boss / registry / 切片代码同批)**:① 伏击节上限段与溢出可见行删除,一轮踩雷数由行动点预算天然封顶成文;② 字段表 advantage_per_round_cap 行删除(原 0 = 免疫伏击语义作废);③ 结构冻结联动纪律去单轮上限 × 攻击基线、数量 × 上限两条;④ 验收标准伏击授予与表校验条同步 |
| v0.12 | 2026-09-20 | **格面资源八型批(用户拍板——与战斗结算 / 地图战斗资源 / 行动经济 / registry / 切片代码同批)**:① 伏击节整体退役改写(复利集中单血条与群伤奖励双重不对称,用户裁决);② 责任表/结构冻结/验收标准的伏击词条目拆除;③ 群伤负向现况 = 警觉(敌方护甲等级 +1),定义与承载移交增益状态 |
| v0.14 | 2026-10-06 | **事件发射点登记(内容数据驱动扩展批)**:半血解锁判定点升级为通用事件 `enemy_hp_threshold` 发射点(对所有带 unlock_hp_pct 字段的敌人逐个发射——非 Boss 专属,Boss 语义留给订阅者条件判定;本批零订阅者,登记归效果引擎事件词汇 16 发射点之一,后续内容批随批接线)。零行为变化。
| v0.13 | 2026-10-05 | **技能池执行批(迭代14④——D1-D8 全裁零待裁,与 skills.tres/enemy.tres/registry 同批)**:①池构成表 8 敌种全覆盖(补 L2+L3 五敌种行:巨蜘蛛/蛛化卓尔精灵/灰矮人/钩爪恐魔/石君王——池构成轮廓+定位列,权重数值不登)+护甲列改读表口径(失同步欠账清偿);②Boss 句改三代错峰口径;③意图呈现节补半血解锁弹出规格句(**Boss 半血解锁新独占伤害技**:字段 unlock_hp_pct〔1,99] 缺省无=无门槛/单向闩/双面过滤/保底不逼锁定/解锁出一次归因行+一次性技能名 toast——D8 只报名不报数值零演出;三 Boss=震地怒击 ×2.5/CD4·遏毒 ×2.0/CD3·岩崩 ×2.5/CD4 案甲 provisional 归调参);④首拍加权取消〔D2〕杂鱼纹理注销不立文 |
+4 -1
View File
@@ -18,7 +18,7 @@
- **目录九件**(值全 provisional 归难度曲线与Boss):被动六件=淬毒刃纹(克制面穿刺/魔法直伤 +N)/标中殉爆(每标中一旗全体存活敌吃 N 群伤)/惊巢反制(挖雷惩罚减半+反弹 N)/工兵晨令(前 effective_rounds 轮每轮 +1 AP,P4 甲表值化)/偏运硬币(装板摇号稀有正向 kinds 权重 +N,池结构零触碰)/三选一刷新件(X 次/每碰三选一);主动三件=掘进蓄能(每开够 N 安全格积 1 点发起临时 AP,charges 2/冒险)/探巢摆钟(3×3 真视窄域,charges 2/冒险)/爆破工兵包(3×3 真视 + 4 AP + **中立移除雷格**,active_charged 装配件 charges 2/冒险——迭代 13 实装,见下「中立移除」注)。
> **中立移除(迭代 13 T7/T8 实装口径;裁决事实源=任务书-工程债与测试基建批-2026-10-04.md P1/P2 甲,随批吸收本节为正主)**:使用时对 3×3 区域做**中立移除**——只移除「未揭示、无旗、是雷」的格:不引爆、不揭示、不进连锁;被移除格退色降档呈现(暗淡记忆态同族)、不可挖掘不可插旗(拒绝零消耗);**周边邻接数字=原始雷数冻结不重算(P1 甲)**,移除格自身无数字可保留(未揭示雷格本无数字,P2 甲空集真)。清图判定零涉(分母只数安全格,雷格不入);旗判定基线零回溯(有旗格跳过移除)。获得渠道=营地同调位装配(不入掉落投放池——form 非空行永不入过渡渠道,模拟/自动档零涉,MC 读数零扰动)。
- **三选一刷新双源**(P1 甲):X=刷新件每碰三选一重给(优先消耗、不结转)+ Y=营地刷新升级行(每冒险开局注入冒险周期池、用完即无;meta.tres attune_refresh_upgrade 行族);重抽消费 reward_pick 既有洗牌流,池规则全保留;autoplay 默认不刷(钓鱼归玩家)。
- **三选一刷新双源**(P1 甲):X=刷新件每碰三选一重给(优先消耗、不结转)+ Y=营地刷新升级行(每冒险开局注入冒险周期池、用完即无;meta.tres attune_refresh_upgrade 行族);重抽消费 reward_pick 既有洗牌流,池规则全保留;autoplay 默认不刷(钓鱼归玩家)。**GP 付费档(2026-10-06 用户令——三选一刷新对齐商店独立刷新)**:免费双源用尽后可 GP 付费刷新,价=ceil(20×1.8^本次停点已付费刷) provisional(与商店货架刷新读同两个调参旋钮 shop_refresh_*,单点调参);付费刷计数每停点清零(与商店进店清零同构);钱包=冒险 GP 同一账本(LevelRunner.spend_gp 单口);余额不足=钮禁用(不隐藏,对齐商店)。店内门票专长三选一暂不挂刷新面(维持现状,扩面须先裁门票保底计数交互)。
- **🔴 承重契约**(schema 加载期强制):机制轴禁裸 flat 数值(行键白名单封闭);真视窄域 ≤3×3;核心层零 await;零随机;排雷玩法零特判;雷安同池冻结(硬币只动权重投影)。
- **验收分层**:attune=off 续用现行带;attune=on 带平移归难度曲线与Boss 投值(商店 shop=off/on 分层先例同法)。
@@ -176,6 +176,8 @@
结构冻结(非调参项,改动走本文修订流程):真视窄域护栏、零信息目标不消耗、边缘窗口照常受理、使用零行动点成本、库存关卡域、用后不可逆、零随机。
效果声明形态(内容数据驱动扩展批换代,2026-10-06):被动件的效果行为从按件 id 硬编码换为**订阅行**——行内声明**订阅哪个事件(on)/ 什么条件(when)/ 什么效果(do)**,由效果引擎统一解释执行(淬毒刃纹=克制判定事件、标中殉爆=标旗事件、惊巢反制=踩雷事件、工兵晨令=每轮开始事件、偏运硬币=资源掷定事件);主动件保持按效果类型通用分发(掘进蓄能的受理闸=使用事件订阅+积点计数器账本)。事件 / 效果类型 / 条件事实 / 算子四词表封闭(效果引擎单一事实源),卡面效果摘要=行 `desc` 字段直读(文案表值化)。
playtest 预警(预注册,归难度曲线与Boss):
| 预警 | 指标与读法 |
@@ -214,4 +216,5 @@ playtest 预警(预注册,归难度曲线与Boss):
| v0.6 | 2026-09-30 | **拍板点 1 收口批(2026-09-30 用户裁决甲:同调=终局方向)**:①新增「定位与形态沿革」节——现行正文定性=切片期过渡形态、终局=局外同调件(设计权威底稿=原提案八拍板,git 57da58c 已退役),两态关系=形态替换、衔接纪律与事故留痕入节;②正文口径回写四处:五维度表信息/规划/反制三行改现行态(罗盘退役/显影件封存/豁免面入正文)、覆盖检查改投放维度覆盖口径、掉落池获取节补解锁门控(2026-09-29 拍板③甲)、板级叠加层预读集改「机制在案无投放来源」;③验收两条(护栏/覆盖检查)与调参表投放态注记、地形变异依赖行同步;④实施批登记见 06「秘宝同调实施批」条。审计冲突 C19/C29 随批收口(全录见审计报告 git 提交 c095916,报告已退役) |
| v0.7 | 2026-10-01 | **奖励节点渠道改写注记(迭代 10 追加批——用户拍板「奖励节点与通关三选一共享同池」)**:①「奖励节点三选一构筑点」形态(v0.5 ④)退役——奖励节点改提升三选一共享池(秘宝件为池中 1/6 权重选项,同调位满位替换交互随 BonusPickOverlay 共用面生效,spec:node-reward.md v2.0);②道具件经节点渠道入本关库存(来源归因 reward_node,与掉落/三选一渠道同受 transitional_sync_slots 过渡上限约束);③战斗掉落渠道零改动;④本批过渡约束形态与切换义务注记见 registry aux_items 条同日批注;同调实施批的全渠道统一收口义务不变 |
| v0.8 | 2026-10-03 | **反制契约作废批(2026-10-03 用户终裁——层级错配失败设计)**:①五维度「反制」行与豁免面 {plan, info, counter} 的 counter 注记改终裁态(原框架契约「每变异≥1反制道具」作废,终裁理由见地形变异.md v0.6/本文件 v0.8 版本行(原 06 条目已收口移除));②上游地形变异依赖行、P2 后置行同步改「迭代 12 调研前置重定」;③地形变异.md v0.6 同批落义务作废注记;④迭代 11 范围裁定(同调→商店→迷雾三批)见 roadmap 迭代 11+ 行——反制批移迭代 12 |
| v1.0 | 2026-10-06 | **效果声明换代(内容数据驱动扩展批)**:被动六件(淬毒刃纹/偏运硬币/工兵晨令/惊巢反制/标中殉爆)改订阅行+掘进蓄能受理闸数据化(使用事件订阅+积点计数器)——按件 id 硬编码清零;结构冻结六条零触碰,行为与迁移前逐位一致(MC 同种子 40 局对拍实证)。
| v0.9 | 2026-10-05 | **消歧更名批(用户拍板 2026-10-05):系统更名「魔法道具」→「秘宝」**。**更名理由**:「魔法」一词在本作已被征用为敌方侧伤害/护甲语汇(`magic_bolt 魔法矢` / `magic_recoil 魔法反噬` / `magic 魔法族` 格面微光 / `ward 魔法护甲`),「魔法道具」易被读成"魔法属性的道具";「秘宝」取"神秘·强大·稀有"义,与九件内容气质(工兵/工程/手艺向)契合,且与局内道具(奇物)不冲突。**同调位机制名保留不变**(attunement 仍为 DND 词,机制血统不受更名影响)。**本批仅改文档称谓,代码不动**——代码标识符仍为 `aux_*` / `AUXILIARY_ITEMS`(auxiliary 词根为过渡形态遗留,与中文名不同步属已知欠债,另批处理);退役路径残留玩家可见文案(`battle_narrator.gd:117-118`、`bonus_interact_controller.gd:76`)亦留另批。历史定稿文档(research/ 提案与任务书、qa/ 检查单、archive/ 归档)按换名先例原样保留不改。 |
+105
View File
@@ -0,0 +1,105 @@
# 生涯
> **一句话定位**:主菜单里与营地平级的**局外只读界面**——营地管「花」(花钥石买永久强化),生涯管「看」(看自己跨局攒下的一切:累计战绩、历史冒险、图鉴收集)。冒险进行中不给任何数据回看(2026-10-04 用户裁决 P-C7 的延续),生涯是历史数据唯一的家。
> **状态**:范围草案(2026-10-06 迭代 17 卡④设计提纲批成文,待用户评审;评审通过后期一/二/三实装批另行立项,本文不预占排期)。
> **来源**:[06-待办清单「『生涯』界面——冒险中数据回看的唯一承接处」条](../../06-待办清单.md)(2026-10-04 用户裁决 P-C7——冒险中不给数据回看,历史战报与结算明细的查看去向 = 新「生涯」界面)。
## 一、信息架构
生涯入口是主菜单一级按钮,与营地平级(2026-10-06 用户裁,备选案与淘汰依据见任务书 P1)。现行主菜单按钮组由 `build_start_overlay` 构造(`game/presentation/ui_assembler.gd:104`):「冒险」组(继续上局 :138 / 开始冒险 :144)与「营地与系统」组(营地 :150 / 设置 :152 / 退出游戏 :156),另有右下角调试角标(DS_DEBUG=1 门控,与主按钮组非平级)。生涯按钮与营地平级同列一级;具体组帽归属与按钮排位属布局细节,归期一实装批(本文不画布局稿)。
```
主菜单(开始覆盖层)
├─ 冒险组:继续上局 · 开始冒险
├─ 营地与系统组:营地 · 生涯(本提纲新增) · 设置 · 退出游戏
└─ 调试角标(DS_DEBUG=1 门控,非平级)
生涯(局外只读面)
├─ 跨局汇总(累计战绩与解锁总览)
├─ 历史冒险回看(逐局摘要与单局明细)
└─ 图鉴(敌人优先,秘宝/奇物随后)
```
边界三条(均为 2026-10-06 用户裁 P4 甲):
1. **局内不放生涯入口**。冒险进行中玩家只看暂停层(迭代 17 卡③并行批——局内只读查看钥石与解锁进度);若历史回看能从局内到达,等于绕回 P-C7 退役前的形态,禁止。
2. **生涯内零跳转**。不放「去营地」之类的操作引导,生涯纯只读。
3. **与 P-C7 的关系**:生涯的成立正是 P-C7 裁决的补偿面——「冒险中无回看」的已知代价由生涯承接(06 条目原文口径),本文不提议在冒险中恢复任何回看入口。
## 二、承载内容清单(逐段标数据可行性)
生涯装三段内容:跨局汇总、历史冒险回看、图鉴。这三段是 06 条目给定的骨架,本节在其上逐项落到数据源。跨局汇总与图鉴的收集类数据大多现成;历史回看的数据面已在存(见下),缺口只有三件,已随 P2 甲裁决定方向。
### 跨局汇总(期一)
| 内容 | 数据源 | 现状 |
|---|---|---|
| 冒险总局数 / 通关局数 | 无现成数据源——`first_adventure_done` 是布尔(`save_manager.gd:117`)、`level_clear_counts` 按关计次(`:109`)反推不出总局数、`recent_summaries` 有上限截断不能累总 | 须新增两个终身计数域,涉存档 schema 迁移(save v6 义务,2026-10-06 用户裁归期一实装批) |
| 各关通关次数 | `clear_count(level_index)`(`save_manager.gd:238`) | 现成 |
| Boss 首杀与总击杀 | `boss_first_kill_marked`(`save_manager.gd:242`)/ `boss_kill_count`(`:250`) | 现成 |
| 钥石余额 | `keystone_balance`(`save_manager.gd:202`) | 现成。累计收支流水不在存(加钥石与花钥石只动余额,`:206`/`:211`)——如要做属新增流水域,期一实装批另呈报,本文只登记 |
| 三柜台解锁完成度概览 | 锻造 `forge_level`(`save_manager.gd:218`)/ 工坊 `workshop_status`(`meta_progression.gd:90`)/ 天赋树 `tree_nodes`(`save_manager.gd:256`) | 现成只读投影 |
### 历史冒险回看(期二)
数据面现役事实:每局冒险收束时已有逐局摘要自动入档——`recent_summaries`(默认域 `save_manager.gd:116`、值拷贝访问器 `:316`、入账原语 `:325-338` 逐局插最前并按上限截断),上限 `SUMMARY_CAP := 10`(`:40`)。摘要字段在冒险收束时组装(`adventure_runner.gd:1005-1018`:结局 result、通关关数 levels_cleared、止步关 stopped_at、钥石合计 keystone_total、本局主种子 master_seed,另附逐杀掉落 keystone_drops 与终局特性 relics 等);摘要的内容口径 owner = [冒险结构](../冒险循环/冒险结构.md),本文不复述其口径。
2026-10-06 用户裁(P2 甲):每局一行摘要,行内给**结局 / 到达关卡 / 钥石收入 / 用时**四件事,上限存最近 N 局。对应三件实绩(本批代码级复核确认的缺口,非新建数据面):
1. **扩容**:cap 10 → N。N 候选 20 / 50 / 维持 10,实装期按存档体积读数三选一;读数方法与列表形态的参数化维度由设计稿给出、实装期执行。
2. **补「用时」埋点**:全仓现在没有任何用时采集点(`game/core/` 内 grep elapsed / ticks / duration / Time 零命中;摘要字段集 `adventure_runner.gd:1007-1018` 无此项)——属新增埋点,随期二。
3. **旧档迁移**:旧档既有 ≤10 条摘要原样保留迁移,向后兼容。
单局结算明细回看:遗留件 `settlement_review_overlay.gd`(`game/presentation/views/`,文件本体在盘、全仓无实例化引用——仅 `ui_kit.gd:356` 样式注记提及)由期二实装批复活承接,改挂生涯(2026-10-06 用户裁 P5 甲)。
可选增强(不占期、不上列):关键构筑列——摘要已附终局特性集 relics(`adventure_runner.gd:1017`),实装期评估是否呈现。
### 图鉴(期三)
- **敌人图鉴(优先,2026-10-06 用户裁 P3 甲)**:直接承接 06 在册「敌方技能图鉴 / 学习呈现」条(P2——见过 → 认得 → 记谱;归属 [HUD 框架](../表现与支撑/HUD框架.md) 与 [敌人系统](../战斗循环/敌人系统.md))。「见过」记账面 = 新增 meta 域,涉存档 schema 迁移(与期一终身计数域同属 schema 义务面;版本号按实装时点的现行版本顺延)。
- **秘宝 / 奇物图鉴(随后)**:无在册条目,立项时另行登记。
- **奖励格图鉴:只登记不激活**(P3 甲)。营地柜台三「奖励格图鉴」现况 = 柜台框在(`camp_overlay_view.gd:121`)、下段由天赋树行占用(`:128` 注记),图鉴本体空置;该柜台已随配比预设批整体挂起冻结(2026-10-05 用户令,06 在册),重启须用户另行发令。
## 三、与既有界面的关系
| 界面 | 管什么(现状指证) | 与生涯的边界 |
|---|---|---|
| 营地([camp UX spec](../../ux/camp.md)) | 跨局成长**操作**面(花钥石买强化 / 装配 / 点树)+ 底栏「最近冒险」条带——`camp_overlay_view.gd:431` `_rebuild_recent()` 逐局拼行(`:442`「完成/放弃/失败 · 通关 N 关 · 钥石 +N · 种子 N」,无截断上限),数据源 = `camp_shop_presenter.gd:85` 投影的同一份 `recent_summaries` | 营地不改生涯只读定位;生涯不做任何购买入口,也不放「去买」按钮。营地条带的去留是本提纲必答项——见 §五 P6 |
| 暂停层(迭代 17 卡③,并行批开发中) | **局内**只读查看这一局进行中的钥石与解锁进度 | 暂停层看当局当前值,生涯看跨局累计与历史;局内无生涯入口(P4 甲) |
| 结算屏([settlement-summary UX spec](../../ux/settlement-summary.md)) | 冒险收束当下的入账明细——`main.gd:537` `_on_adventure_finished` 收束时呈现摘要与钥石明细(复用终局面账行,`battle_end_overlay.gd:118-129`) | 收束当下的呈现保留不动;生涯承接的是收束之后的任意时刻回看 |
| 帮助手册(Beta 批,未实装——教学内容归 Beta 帮助手册,`ui_assembler.gd:99` 注记) | 讲「怎么玩」 | 生涯讲「我玩过什么」。图鉴条目文案与手册是否共用内容源,接口登记归 Beta 批一并裁 |
| 图例面板(legend_overlay) | 局内符号/徽标即时解码 | 不合并——图例是局内解码面,图鉴是跨局收集面 |
## 四、分期实装建议
三期均为**另行立项**的实装批,下表是建议不是排期,roadmap 迭代位由用户逐期点名。本提纲不含布局稿、视觉稿、素材需求清单(美术由用户独立成批自理,2026-10-05 立规)。
| 期 | 内容 | 前置 | 建议窗口(候选) |
|---|---|---|---|
| 期一 | 跨局汇总页 + 主菜单生涯入口落位。总局数/通关局数两个终身计数域随该批做存档 schema 迁移 | 提纲评审通过。实装批前置义务 = 对齐迭代 16 UI 批后的现行基线:`FS_*` 六档字号 / `TG_*` 语义色 / `BUTTON_MIN_H=40`(`ui_kit.gd:437`)/ 色板单源 / `page_shell` 模态栈纪律(`ui_kit.gd:394`)——与卡③任务书同款红线,本文只登记、不展开 | Alpha 后最近一个 UI 窗口 |
| 期二 | 历史冒险回看整段:N 扩容 + 用时埋点 + 旧档摘要迁移 + 逐局列表 + 单局明细(`settlement_review_overlay.gd` 复活承接)+ 营地条带处置(P6 裁案落地) | 期一。实装批开工前须向用户呈报两件:N 终值读数(20 / 50 / 维持 10 三选一)与「用时」埋点口径(计时起点、暂停是否计入——字段级细节本文不做) | 期一落地后独立批 |
| 期三 | 图鉴承接(敌人优先,范围与顺序随 P3 甲);「见过」记账面 schema 义务随该批执行 | 期二或独立评估 | Beta 窗口候选(与教学引导同段评估——图鉴的「认得」轴与教学相关;06 教学引导节各条 2026-10-04 起已整体标 Beta 阶段) |
本地化文案权:生涯界面本体按钮、页签、空态文案归[设置与本地化](../表现与支撑/设置与本地化.md)线(全仓无多语言实装——`game/` 内 grep TranslationServer 零命中;文案权先例 = 教学文案定稿权登记于 06),实装批承接。
## 五、待裁点
P0-P5 六点已于 2026-10-06 用户全裁(案甲 × 6,备选案与淘汰依据在任务书 §8),结论已落文上文对应节,不重复列。本批新发现的待裁点一项:
### P6 · 营地底栏「最近冒险」条带去留(期二必答项)
**现状与问题**:营地底栏「最近冒险」条带把传入的摘要逐行全部拼进一个 Label(`camp_overlay_view.gd:431-443`,`:442` 行模板,无截断上限),数据源与生涯历史回看是同一份 `recent_summaries`(`camp_shop_presenter.gd:85`)。生涯期二把上限扩到 N 后,条带按现行逻辑会把 N 行全拼进底栏——这是本批复核发现的实际耦合点,期二落地时必须给条带一个去处。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(建议) | 期二生涯历史回看落地时,营地条带撤下、逐局回看整体归生涯;期一(汇总页上线、数据面未动)期间条带原样保留零改动 | 分工矩阵干净——「看」归生涯、「买」归营地;逐局历史只剩一个权威呈现面,去重问题自然消解;顺带解开 N 扩容后底栏无上限拼行的实耦合 |
| 乙 | 两处并存——营地留最近几条速览、生涯给完整列表 | 营地顺手一眼仍有价值;淘汰候选:同一数据两处呈现,玩家要猜哪边全;条带须另加截断逻辑 = 新增一处维护面;「看」留在操作面违反分工矩阵 |
| 丙 | 条带原样永久保留(固定存 10 条,不随 N 动) | 改动最小;淘汰候选:与生涯列表长期双轨,上限语义分裂(营地固定 10 / 生涯 N),N 大于 10 后两处看到的条数对不上 |
裁决方式:随本提纲评审一并定案,期二实装批执行。
## 版本历史
| 版本 | 日期 | 说明 |
|---|---|---|
| v0.1 | 2026-10-06 | 设计提纲首版(迭代 17 卡④设计批,纯文档):五节成文;P0-P5 已裁结论落文;新发现待裁点 P6(营地最近冒险条带去留);现状描述全部经代码级复核(F1-F10,见 design/qa/iter17-career-exit-report-2026-10-06.md)。状态 = 范围草案待评审 |
@@ -0,0 +1,61 @@
# 出口报告:生涯界面设计立项(迭代 17 卡④设计批)
> 批次:纯设计批(零代码、零数据面、零测试执行——两入口铁规:非 loop 实施批且用户未点名)。
> worktree:`g-plan2-iter17-career`(分支 `iter17-career-20261006`,基点 = master fc4dbde)。
> 任务书:`design/research/任务书-生涯界面设计立项-2026-10-05.md`(v1.1 零待裁点,U0 已发)。
> 本报告按「吸收即死」纪律属中间文档,寿命 = 迭代寿命;五条判定与 F1-F10 复核结论已同步写进各正式文档(生涯.md / 06 / roadmap)。
## 一、完成定义五条逐条判定(任务书 §1.2)
| # | 判定项 | 判定 | 依据 |
|---|---|---|---|
| 1 | 提纲成文 | ✅ | `design/gdd/systems/跨局循环/生涯.md` v0.1(P0 甲裁定的载体,状态=范围草案),五节齐:一、信息架构;二、承载内容清单;三、与既有界面的关系;四、分期实装建议;五、待裁点 |
| 2 | 事实对齐 | ✅ | §2 事实表 F1-F10 逐条代码级复核全绿(见本报告 §二);提纲中每句现状描述带 file:line 指证(R1) |
| 3 | 裁点齐备 | ✅ | P0-P5 已裁结论全部落文对应节;本批新发现待裁点一项(P6 营地最近冒险条带去留),三案全列含淘汰依据、有明确建议案;全文无「待定」悬空 |
| 4 | 零实装 | ✅ | diff 仅含:新建生涯.md、02-系统清单.md 三行(树行/代号行/版本行)、06 状态行、roadmap 卡④行、active.md、本报告;`game/` 零改动、存档零改动、零测试执行 |
| 5 | 人闸 | ✅(待用户执行) | 06 状态行已更新为「设计提纲已成文待评审」;**人闸 = 用户评审提纲**(评审时随裁 P6) |
## 二、T0 事实复核 F1-F10(2026-10-06 静态阅读,行号以实核为准)
| # | 事实 | 结论 | 实核证据(file:line) |
|---|---|---|---|
| F1 | 冒险中回看已退役 | ✅ 绿 | `battle_end_overlay.gd:9`(signal continue_pressed,注记 review_pressed 退役)、`:106`(明细回看钮退役注记)、`:90` 现为 GP 账目行 add_child——任务书 v1.0 的 :90 漂移勘误属实;`battle_log_view.gd:47`(「上轮摘要(回看归「生涯」」提示)、`:115`(带点击回看入口退役注记);`ui_assembler.gd:67`(明细回看 overlay 退役注记) |
| F2 | settlement_review_overlay.gd 在盘 | ✅ 绿 | `game/presentation/views/settlement_review_overlay.gd` 在盘(含 .uid);全仓无实例化引用——仅 `ui_kit.gd:356` 样式注记提及「settlement_review 同款」;无 .tscn 引用 |
| F3 | 跨局持久面 = save v5 meta 域 | ✅ 绿 | `save_manager.gd:39`(SAVE_FORMAT_VERSION=5 版本链注记)、meta 默认域键集 `:106-117`(keystone_balance/forge_levels/item_unlocks/level_clear_counts/boss_first_kill/boss_kill_count/attunement_equipped/attune_refresh_level/tree_nodes/fork_sides/recent_summaries/first_adventure_done)+ 访问器面 :202-:316 |
| F4 | recent_summaries 现役 + 三件真实缺口 | ✅ 绿 | `save_manager.gd:40` SUMMARY_CAP=10;`:316` 值拷贝访问器;`:325-338` apply_adventure_summary(push_front + cap 截断 + boss_drops 副本 :334);`meta_progression.gd:129` settle_adventure 经 `:133` 归档(:125 注记)。缺口①cap 扩容、②用时零采集点(game/core grep elapsed/ticks/duration/Time 零命中;摘要字段集 `adventure_runner.gd:1007-1018` 无用时)、③总局数/通关局数无 lifetime 域(first_adventure_done 布尔 :117、level_clear_counts 按关 :109)——三条全实证 |
| F5 | 当局结算呈现仍在 | ✅ 绿 | `main.gd:537` `_on_adventure_finished` 收束当下呈现摘要五件事+钥石入账明细;终局面三行账 `battle_end_overlay.gd:118-129`(open_victory 账行装配) |
| F6 | 跨局汇总数据源现状 | ✅ 绿 | 各关通关次数 `save_manager.gd:238`、Boss 首杀/总击杀 :242/:250、钥石余额 :202(累计收支无流水——:206/:211 只动余额)、锻造/工坊/天赋树访问器 :218/:230/:256;总局数/通关局数两格无数据源(同 F4③) |
| F7 | 图鉴承接候选内容 | ✅ 绿 | 06:192「敌方技能图鉴 / 学习呈现」(P2,见过→认得→记谱);奖励格图鉴柜台空置——06:244(随配比预设批挂起冻结)、`camp_overlay_view.gd:121`(柜台三框在)、`:128`(下段天赋树行占用注记) |
| F8 | 相邻界面分工现状 | ✅ 绿 | 营地 `camp_overlay_view.gd:431` `_rebuild_recent()`、`:442` 行模板「完成/放弃/失败 · 通关 N 关 · 钥石 +N · 种子 N」(无截断上限)、`camp_shop_presenter.gd:85` recent 投影;主菜单按钮组 `ui_assembler.gd:104-160`(营地 :150);设置面 :152;暂停层 = 迭代 17 卡③并行批(本 worktree 基点未含其实码,提纲按任务书口径引用) |
| F9 | 06 条目原文口径 | ✅ 绿 | 06:400「新「生涯」界面(跨局汇总/历史冒险回看/图鉴承接)」三段骨架原文在册 |
| F10 | 阶段语境 | ✅ 绿 | 06 教学引导节各条状态行 Beta 阶段注记(:375/:383/:391,2026-10-04 拍板改排);生涯条目(06:396-404)无阶段标注——提纲分期建议以候选窗口作答 |
**差异记录(两处,均不阻塞)**:
1. `ui_assembler.gd` 实际路径为 `game/presentation/ui_assembler.gd`(任务书 F1 只写文件名未带路径,无歧义;提纲已用全路径引证)。
2. 复核顺带发现一处**既有**登记滞后(非本批引入、不属本批范围):`design/registry/entities.yaml` 存档条目 version 注记仍写「SAVE_FORMAT_VERSION=4 / v1→v4 迁移链」,代码已至 v5(`save_manager.gd:39`,v5=天赋树域,迭代 12);domains 行的 meta 域九件明列与 recent_summaries cap 10 记载仍准确。属 registry 与代码的同步欠账,owner 文档 = 存档序列化.md,建议归后续文档对齐批或 doc 一致性检查呈报——本批 diff 范围不含 registry,未动。
## 三、交付物与落点
| 交付物 | 落点 | 状态 |
|---|---|---|
| 设计提纲(本批主体) | `design/gdd/systems/跨局循环/生涯.md` v0.1 | 范围草案,待用户评审 |
| 根索引同步 | `design/gdd/02-系统清单.md`(跨局循环树行 + 命名对照表 CAREER 行 + v1.12 版本行) | 已落 |
| 06 状态行 | `design/gdd/06-待办清单.md` 生涯条 →「设计提纲已成文待评审」 | 已落 |
| roadmap 卡④行 | `roadmap.md` 迭代 17 卡④ →「✅ 设计提纲已成文待用户评审……人闸=用户评审提纲」 | 已落 |
| 会话记录 | `active.md`(快照节追加 + 台账 379) | 已落 |
## 四、提交哈希清单
| 提交 | 内容 |
|---|---|
| 10df8ba | T1:生涯.md v0.1 成文 + 02 根索引三处(树行/CAREER 行/v1.12) |
| (本提交) | T2 加批次收尾:06 状态行、roadmap 卡④行、active.md、本报告 |
终态 = worktree 内全部提交完成,**未合并、未 push**(合并落回 master 由用户/编排会话执行)。
## 五、遗留与移交
1. **人闸(唯一)**:用户评审设计提纲 `design/gdd/systems/跨局循环/生涯.md`,评审时随裁新发现的 P6(营地底栏「最近冒险」条带去留——建议甲:期二时撤下归生涯)。评审通过后期一/二/三实装批另行立项。
2. 实装批前置义务已在提纲 §四登记(非本批工作):期一=对齐迭代 16 UI 基线 + save v6 两个终身计数域;期二=N 终值读数呈报(20/50/维持 10 三选一)与用时埋点口径呈报;期三=「见过」记账面 schema 义务。
3. registry 存档条目 version 注记滞后(§二差异记录 2)——移交后续文档对齐批,非本批范围。
@@ -0,0 +1,70 @@
# 出口报告——内容数据驱动扩展批(迭代 17 卡⓪,2026-10-06)
状态:**批内全部提交完成、六闸全绿、终态=worktree(iter17-dd-20261006 分支)全部提交,待用户合并落 master**。
执行事实源:[任务书-内容数据驱动扩展批-2026-10-06](../research/任务书-内容数据驱动扩展批-2026-10-06.md)(v1.1);设计权威:[研究-内容数据驱动扩展架构-2026-10-06](../research/研究-内容数据驱动扩展架构-2026-10-06.md)。
执行形态:前任 subagent 完成 T0-T2 后因额度中断,续跑 subagent 接手 T3 断点(三个脏文件半成品)收口并完成 T4-T7。
## 一、提交清单(worktree 内全部提交,按卡)
| 卡 | 提交 | 内容 |
|---|---|---|
| T1(前任) | `7d157b3` | 效果引擎框架:事件发布订阅解释器+16 发射点埋点+组合规则六族+计数器账本 |
| T2(前任) | `225765f` | 词汇表落码:feats/treasure 两表 trigger 订阅形态 schema 换代+护栏迁移 |
| T3 | `e28a6cb` | 专长迁移:27 行 triggers 全量生效+旧 23 挂点枚举消亡+_feat_flags_for 退役+消费点拆除(伤害控制器 13 处+编排器全部旗面)+文案入表(专长卡 desc)+断言面随迁(冒烟 ④-⑧ 全量改写) |
| T4+T5 | `a33ddaf` | 秘宝六件迁移(淬毒/偏运/晨令/惊巢/殉爆/掘进蓄能受理闸)+按 id 特判清零+pick_refresh kind 分发+curio 卡片文案入表;令牌兑付 match 收敛进效果类型路由表+树规则键同面收口 |
| T7 | 本批终提交 | 文档正主换代(奇物.md v2.8/秘宝.md v1.0/敌人系统.md v0.14+registry 两件+06 状态收口+roadmap 卡⓪行)+本报告 |
T0 断点核查记录:前任已留 pre 锚(见 §三),T0 三查其余项随续跑开工复读完成。
## 二、闸读数(T6 回归闸全绿)
| 闸 | 读数 | 结论 |
|---|---|---|
| 冒烟(三闸) | **800 项检查,0 项失败**,退出码 0,无 SCRIPT ERROR | 绿(断言数 783→800:T3 断言面随迁净增 17 项,漂移追认随 T3 commit 留痕) |
| 单元(run_all) | **17 套全绿** | 绿 |
| 探针闸(probe_gate --click) | ui_input/ui_struct/ui_contrast/click 四段全 PASS,批末残留 Godot=0 | 绿(本批触碰呈现层——battle_narrator/curio_interact 文案面,故带 click) |
| MC 二档对拍 | 见 §三 | 绿——逐位一致 |
| 确定性复放 | 同种子改前/改后两次采集逐位一致(40 局全对) | 绿(强于「同码两遍」口径) |
| doc 三闸 | doc_link_audit 过(exit 0);doc_term_audit 过(exit 0);gdd_lint 2 处失败=**基线既有**(06-待办清单/07-体验验证清单结构性指标,stash 对比实证改前改后同为 2 处零新增) | 绿(零新增) |
| 熵增闸(repo_structure_audit) | 1 处违例=design/diagrams 子目录越界——**基线既有**(前批「GDD系统架构总图批」00712d5 产物,非本批引入;归该批主自证或后续清理) | 绿(零新增) |
## 三、MC 锚与对拍结论(二档合规)
- 判据口径:契约 2 两套(确定性复放与冒烟=**逐位一致**;MC 统计量=**成型画像同带**,正主=design/qa/m4iter12-t7-batch1-readings-2026-10-04.md)。
- 改前锚(前任 T0 采集,留盘未补跑):`sim-data/runsum_iter17dd_pre_off_n20_20261006.jsonl` / `runsum_iter17dd_pre_formed_n20_20261006.jsonl`(seed0=83000、N=20/档、normal 档、route=min、attune=off、off/formed 同种子配对;formed=七流派各 2 件档一成型注入画像——14 件全部系本批迁移行)。
- 改后锚(T6 采集):`sim-data/runsum_iter17dd_post_off_n20_20261006.jsonl` / `runsum_iter17dd_post_formed_n20_20261006.jsonl`(同 seed0 同口径;新锚去前缀纯 JSONL 按种子升序)。
- **结论:40 局(2×20)同种子逐位一致**——每局 RUNSUM 全字段(通关数/承伤/踩雷/旗经济/资源事件/钥匙石/逐战上限序列等 33 字段)改前改后零差。统计量同带判据自动满足(逐位一致蕴含同带):L1 通关率 off 20%(4/20)、formed 80%(16/20),与改前逐位同值。
- 档位合规:总量 40(每档 20)=二档上限贴边;另有 T3 段末 S1 预检 2×5 局(三档只测不判,未留锚)——S1 停机点未触发。
## 四、代拍板记录(任务书 §八白名单四项+呈报不停机级,全部 commit 留痕)
1. **fact 查询面落法**:`has` 算子=在场判定(value 缺省=非空;value 给定=数组包含)——地形伤/伤害型地形四行订阅的查询面(T3 commit)。
2. **fact 查询面落法**:perfect_defense「全中」装不进封闭 9 项事实——when 落 flags_count≥1 保守判定,全中闸=flag_settle 发射点施加面承载(禁私开 fact 停机点纪律保持;T3 commit)。
3. **事件载荷字段**:attack_commit 发射点从 resolve 内移至开单入口(任务书 §3.1 定稿位),命中随单据 context 携带;damage_taken 补 terrain_kind、flag_hit 改 terrain_kind=邻接伤害型变异集(T3/T4 commit)。
4. **发射点微调(±1)**:round_start 发射位前移至行动经济轮切换之前(树规则 grant_ap queue 当轮兑现=先手压制首轮语义锚);attack_commit 单发射点、命中两处消费(编排器段序承载连珠矢开单位/控制器管线算术承载其余施加面——dispatch 纯读零副作用)。
5. **效果类型落法对拍注记(映射表五处语义修正的随批追加,行为等价优先)**:猎巢人/矿工的执拗=必中附加通道(映射表标 modify_ticket/attack_bonus 与现状不符,落 add_ticket_rider per 载荷);整备军备双效果两行订阅;厚积薄发=满层持续状态(非沿触发);荆棘编织者=伤害兑付位第二份产出(非 ×2 乘区);完美布防=旗伤单值倍增(非 yield 乘区)——全部随 .tres 尾注+commit 留痕。
6. **冒烟断言数漂移追认**:783→800(断言面随迁净增 17 项)。
7. **文案微调**:掘进蓄能/失义件秘宝卡补实际摘要(原 kind 硬编码面无文案);其余 desc 措辞与旧映射逐字一致。
8. **效果类型计数**:24 型(任务书标题 23 系笔误——T1 前任已代拍留痕,沿用)。
## 五、文档正主换代清单(T7)
- 奇物.md **v2.8**:专长效果声明换代(挂点→订阅行)五处+版本行;事实源表 feats.tres 行结构换代。
- 秘宝.md **v1.0**:效果声明形态节(被动件订阅行+主动件 kind 分发+掘进蓄能受理闸数据化+desc 文案表值化)+版本行。
- 敌人系统.md **v0.14**:半血解锁判定点=通用事件 enemy_hp_threshold 发射点登记(非 Boss 专属,零行为变化)+版本行。
- registry/entities.yaml:专长 data_sources 换代+effect_declaration 新条(四词表封闭/组合规则/遍历序/重建时机)。
- registry/architecture.yaml:core_decisions 新条 effect_engine_interpreter(ADR-0011 候选)。
- 06-待办清单:数据驱动批状态=已实施完成收口(提交号+闸读数+遗留两项)。
- roadmap:迭代 17 卡⓪行换代(状态=已实施完成)。
## 六、遗留人闸项(呈报不停机级,均为显式拍板请求非缺陷)
1. **掘进蓄能积点模判定留编排器侧**:use_treasure 受理闸已数据化(treasure_used counter_spend 订阅),但「每 charge_n 安全格积 1 点」的模判定留在战斗编排器授予段——「先增后判」在发射点施加架构下无法行内表达(when 于 dispatch 预评估,先增后判需引擎内联过账=会破坏矿脉直觉连击的施加序等价)。行为与迁移前逐位一致(charge_n 读行零字面量);若要求彻底行内化,需效果引擎增设「计数器种子/内联过账」机制,归后续词汇表扩展批裁决。
2. **主动件 kind 词族全量 rename 不随批**:新词(reveal_tiles/preview/grant_ap/remove_mines/refresh_pick)已在闭集与旧词共存(T2),本批只完成 pick_refresh kind 分发合流;mine_reveal→reveal_tiles 等全词族 rename 波及库存/呈现标记/单测约 15 处零行为收益,显式不在本批(出口呈报,归后续清理批或随批裁决)。
3. **实机目检归用户**(批次工作流第 12 步):呈现面改动=专长卡与秘宝卡文案源(desc 直读,措辞逐字迁移)——建议实机抽查一张专长卡+一张秘宝卡。
## 七、风险与边界声明
- 存档零触碰:存档键/格式/断点结构一字未改(持有集/装备存 id 不变,换的只是解释方式)。
- 护栏全保留:四词表封闭校验、行键白名单、悬空引用致命、零裸 flat 禁令、流派扫雷触发铁律(MINE_EVENTS 同义形态)全部以新形态延续;本批新增封闭面=when value_from 悬空校验。
- 主区零直改:全部改动在 worktree iter17-dd-20261006;并行在飞三线(iter17-pause 卡③/standee-tier/uialign)未触碰。
@@ -0,0 +1,81 @@
# 出口报告:暂停层只读入口批(迭代 17 卡③)
> 批次:功能性 UI 交互新增(纯呈现零数值改动=零 MC;核心层零改动)。
> worktree:`g-plan2-iter17-pause`(分支 `iter17-pause-20261006`,基点 = master 44328b1)。
> 任务书:`design/research/任务书-暂停层只读入口批-2026-10-05.md`(v1.1 零待裁点,U0 已发;T0 基线回填已落任务书头注)。
> 本报告按「吸收即死」纪律属中间文档,寿命=迭代寿命;结论已同步写进 06 / roadmap / active.md。
> 执行备注:本批由两次会话接力完成——T0/T1 与组 B 大部系前任会话(因额度中断),断点续跑会话完成组 B 收尾(两处探针断言口径 L1 修正)与 T3-T5。
## 一、完成定义五条逐条判定(任务书 §1.2)
| # | 判定项 | 判定 | 依据 |
|---|---|---|---|
| 1 | 入口可达 | ✅ | 战斗屏 HUD 右下角+关卡地图屏顶栏各一枚「暂停」常驻角标(P1 丁);主菜单零角标(`_sync_pause_entry` 以 `_level_active`∧屏态门可见性);ui_input case⑯ 角标真点击开层绿、ui_click 两屏 case 绿 |
| 2 | 只读数据正确 | ✅ | 冒烟 `_pause_overlay_projection` 5 断言(余额徽/锻造三行/工坊六行/天赋树概览 == MetaProgression 访问器逐项);结构探针只读巡检=层子树游戏语义信号连接白名单外零连接,合法连接恰 2(关闭钮+关层外发);层内唯一控件=「继续」 |
| 3 | 公共件复用 | ✅ | 全部构成件经 UiKit 工厂(modal_shell/panel_skinned/label/button/keystone_badge)+现行色板 token;badge 工厂件 Q10 甲收编入 ui_kit 并同步迁营地钥石徽(观感零变化);零新素材零新色值零新字体;ui_contrast 12 对含钥石徽深墨/烛光黄新对 |
| 4 | 模态纪律 | ✅ | PauseOverlay 登记进 main.gd 登记册设置层同档、确认弹窗之前(P2 甲);登记序=树序=z 序注记同步换代;带 dim 遮罩;开合走 `_open_modal`/`_close_modal` 单口;`has_open_excluding` 排除式开态查询(只读零副作用);ui_click 守卫 case 绿(他层开着=置灰+emit 兜底拒开) |
| 5 | 重闸全绿+人闸 | ✅(机检半)/⏳(人闸待用户) | 机检读数见 §三;实机目检清单=`design/qa/iter17-pause-human-gate-checklist-2026-10-06.md`(A-H 八节:双屏入口/守卫态/只读性数据正确/零动效与排播副作用观察/与设置面关系/代拍板追认/R4 口径披露/机检佐证),**人闸=用户实机目检** |
## 二、任务卡完成态(T0-T5)
| 卡 | 状态 | 提交/落点 |
|---|---|---|
| T0 | ✅(前任) | worktree 建立+基线回填任务书头注(冒烟 783/0·run_all 17 套·probe_gate 默认段绿·F1-F10 实核绿·迭代 15② 交集零命中);HEAD 时点=44328b1 |
| T1 | ✅(前任) | c08a901(组 A:pause_overlay.gd 本体+badge 工厂件收编+营地钥石徽迁移+main.gd 接线)+ fc9eb1e(pause_overlay.gd.uid 边车随批) |
| T2 | ✅(续跑会话收尾) | d44fdd5(组 B:两屏角标+has_open_excluding+守卫处理器与 _sync_pause_entry 单一同步点+四探针断言+冒烟投影断言+任务书 T0 注记随批)。前任中断于代码写完未跑闸态;续跑两处 L1 修正(见 §四)后全闸绿 |
| T3 | ✅(续跑会话) | 无代码改动,闸读数见 §三 |
| T4 | ✅(续跑会话) | `design/qa/iter17-pause-human-gate-checklist-2026-10-06.md` |
| T5 | ✅(续跑会话) | 本报告+06 状态行+roadmap 卡③行+active.md 快照/台账 380 |
## 三、闸读数(T0 基线 → 批末)
| 闸 | 基线(T0) | 批末 | 判 |
|---|---|---|---|
| 冒烟(run_smoke 全量) | 783/0 | **788/0**(+5=本批投影断言) | ✅ |
| run_all | 17 套全绿 | 17 套全绿(exit 0) | ✅ |
| ui_input_probe | 默认段绿 | **十七断言 PASS**(+⑯暂停层输入锁:真点击开层/锁期零穿透/关后恢复无残留) | ✅ |
| ui_struct_probe | 默认段绿 | 全屏零红(+pause 结构断言+只读性契约+零动效契约) | ✅ |
| ui_contrast_probe | 默认段绿 | **12 对测点 PASS**(+钥石徽深墨/烛光黄对,≥4.5:1) | ✅ |
| ui_click_probe | 轻闸三件外 | done=true 问题=0(+战斗屏开合守卫 case+地图屏一次性 case) | ✅ |
| ui_layout_probe | — | exit 0(观察型布局树工具,无断言判语) | ✅ |
| doc 三闸 | — | doc_link_audit 绿 / doc_term_audit 绿 / gdd_lint **存量红**(见 §五-2,本批零新增——06/07 两文件本分支零触碰) | ✅(零新增口径) |
| 熵增闸 | — | **存量红**(见 §五-1,主区同红佐证) | 移交披露 |
| MC | — | 零跑(纯呈现零数值改动——两入口铁规) | ✅ |
## 四、L1 修正记录(T2 续跑首轮探针红两处,均为断言口径、非产品代码缺陷)
1. **ui_struct_probe 只读巡检**:前任落码为「子树全控件 × get_signal_list() 全集」巡检——首跑把 Godot 容器系统对每控件自动建立的布局生命线连接(child_order_changed/item_rect_changed/visibility_changed/size_flags_changed/minimum/maximum_size_changed → 引擎内部脏标记方法)全数误判非法。修正=收敛为**游戏语义信号名清单**(pressed/button_down/button_up/toggled/text_changed/text_submitted/value_changed/item_selected/gui_input/focus_entered/focus_exited/closed 十二名)——这正是任务书 v1.1「巡检信号名清单 T2 落码时列全进探针」的本意;清单外任何新连接一律红须入册。
2. **ui_input_probe case⑯ 取格**:原逻辑假设 case⑥ 后域内必余「无旗可挖格」——首跑实测踩中「域恰 2 枚」形态(flag_t 已插旗+dig_t 已揭开后域内零无旗格;旗不可拔=`flag_present` 拒绝在册)。修正=case 挪至全 case 之尾(板面扰动零波及)+域空时前沿移位兜底(真实点击 move 扩大可挖域,复用探针既有 `_pick_frontier` 手法)。修正后一轮全绿,无复发。
## 五、存量问题移交(均非本批产生,主区 master 同态)
1. **熵增闸红:`design/diagrams` 子目录越界**——00712d5(2026-10-05 GDD 系统架构总图批)落籍时新增 `design/diagrams/`(JSON+HTML 两件)但未同批修订 CLAUDE.md Project Layout 与 `repo_structure_audit.py` 白名单,属该批收尾漏步;主区现跑同红已实证。处置建议=用户拍板「diagrams 收编为合法类别」或「两件归位」,随下一文档批或直接小批办理;本批不代修(最小批面)。
2. **gdd_lint 存量红:06/07 两文件** R3 修订注记/删除线残留/R4 缺版本历史/R7 括号跨度超限——全为历史批次落文注记(本分支对两文件零 diff);doc 三闸「零新增」口径达成。
3. **registry 存档版本注记滞后 v4→v5**——生涯批(台账 379)已登记移交,本批未触碰 registry,维持在册。
## 六、代拍板记录(白名单内决断,commit 留痕,目检可推翻——追认单见目检清单 F 节)
| # | 项 | 决断 | 出处 |
|---|---|---|---|
| 1 | 关闭钮文案 | 「继续」(紧凑 90 宽返回钮,设置面先例形制) | T1 c08a901 |
| 2 | 层内行序 | 余额徽→属性锻造→道具工坊→天赋树(营地屏同序,MetaTable.FORGE_ATTRS 序) | T1 c08a901 |
| 3 | 角标文案与落点 | 「暂停」;战斗屏=HUD 右下角(角距 16px,debug 角标同形制);地图屏=顶栏 GP 徽右侧 | T2 d44fdd5 |
| 4 | 断言编号与 case 命名 | ui_input case⑯;ui_struct 契约 ⑧只读⑨零动效;冒烟 `_pause_overlay_projection` | T2 d44fdd5 |
| 5 | 只读巡检信号清单 | 十二名游戏语义信号(§四-1) | T2 d44fdd5 |
## 七、提交哈希清单(worktree 内全部,含前任)
| 提交 | 内容 |
|---|---|
| c08a901 | T1:暂停层组 A(pause_overlay 本体+badge 工厂收编+营地钥石徽迁移+main 接线) |
| fc9eb1e | T1:pause_overlay.gd.uid 边车随批 |
| d44fdd5 | T2:暂停层组 B(两屏角标+守卫+四探针断言+冒烟投影断言+任务书 T0 注记) |
| (收口提交) | T4+T5:目检清单+本报告+06 状态行+roadmap 卡③行+active.md |
## 八、遗留人闸项
1. **实机目检**(唯一硬人闸):`design/qa/iter17-pause-human-gate-checklist-2026-10-06.md` A-H 八节,重点=双屏入口/守卫态/只读性/零动效/**排播队列排空副作用确认项**(D2——开层瞬间待播明细行瞬时入带,与「暂停」直觉之差,既有各弹层同款行为)。
2. 存量移交三项(§五),均不阻塞本批。
3. Esc 快捷通道=已在 06 键盘/手柄条登记(P1 丁裁点),随键盘批统一办理,本批不落码。
终态 = worktree 内全部提交,**未合并、未 push**(合并落回 master 由用户/编排会话执行)。
@@ -0,0 +1,63 @@
# 人闸目检清单:暂停层只读入口批(迭代 17 卡③)· 2026-10-06
> 执行=用户实机。启动:Godot 打开 `game/project.godot` 运行即可;逐项勾选,不过项随批登记返工。
> 批区间:T0 基线 HEAD=44328b1 → 批末 d44fdd5(T1 c08a901 暂停层本体 / T2 d44fdd5 入口与断言)。
> 任务书:`design/research/任务书-暂停层只读入口批-2026-10-05.md`(v1.1)。事实源=06-待办清单「解锁界面与钥石呈现的交互形态(残余:暂停层只读入口)」条。
## 怎么走到暂停层(操作路径)
开始冒险 → 选一个战斗节点进战斗 → 战斗屏**右下角**「暂停」小钮(或:打完战斗到关卡地图屏 → 顶栏 GP 徽**右侧**「暂停」小钮)→ 弹出「暂停」只读层 → 看完点「继续」关闭。
## A · 双屏入口可达(P1 丁——常驻角标主入口)
- [ ] A1 战斗屏 HUD 右下角有「暂停」角标,点击直接开层(无过渡动画)
- [ ] A2 关卡地图屏顶栏「暂停」角标可见可点,点击开层;层叠在地图屏之上,地图屏仍可见
- [ ] A3 主菜单(开始菜单)**无**暂停角标——入口只在对局内出现
- [ ] A4 冒险结束回主菜单后角标消失(离局熄灭,不误现)
- [ ] A5 暂停层开着时点「继续」原样回战斗屏/地图屏,可继续挖格/选路(无状态残留)
## B · 入口守卫(他层开着=角标置灰不可点)
- [ ] B1 战斗中先开图例(或触发三选一/商店/营地等任一弹层)→ 暂停角标置灰,点击无反应
- [ ] B2 关闭该弹层后角标恢复可点
- [ ] B3 地图屏自身开着时地图屏角标仍可点(地图屏是常态屏,不算「其他模态」)
- [ ] B4 暂停层自己开着时,再点任一处角标无反应(不可叠开第二层)
## C · 只读性与数据正确(P3 甲——余额+三柜台进度)
- [ ] C1 层内唯一可点控件=「继续」关闭钮;无任何购买/切换/滑杆类控件
- [ ] C2 钥石余额徽与营地屏顶栏钥石徽同形制(烛光黄底+深墨字+钥石图标),数字=当前真实余额
- [ ] C3 属性锻造三行(攻击/生命/防守族)= 已购等级「Lv n」,与营地柜台一读数一致
- [ ] C4 道具工坊六行解锁态(未解锁/已解锁/已解锁·能力封存中/已退役)与累计通关进度分数,与营地柜台二一致
- [ ] C5 天赋树概览=已购节点聚合文案(零已购时显示空态句「尚未购买任何节点」),与营地柜台三一致
- [ ] C6 层开着时回营地柜台改数值(如买一级锻造)不可行(层无通路);关闭层后重新打开,显示为新值(实时读数)
## D · 零动效与排播副作用观察(P4 甲 + T4 指定观察项)
- [ ] D1 层进出均为直开直关——无淡入淡出/滑入等过渡动画
- [ ] D2 **排播排空副作用**(确认项):战斗明细演播进行中(连续挖格后立刻)开暂停层——待播明细行会被瞬时排空入带(跳过演播节奏,行带直接补完整)。这是与「暂停」直觉的差异点:**本层只是查看层,不冻结战斗演算与演播**(既有各弹层同款行为)。确认此表现可接受,或登记异议
- [ ] D3 减动效开关开/关两态下,层进出表现一致(本层零动效,开关无新增消费)
## E · 与设置面的关系(P2 甲——登记同档)
- [ ] E1 主菜单开设置面:无暂停角标出现(两层面不共存——设置入口在主菜单,暂停入口在对局内)
- [ ] E2 层级遮挡关系抽检:确认弹窗盖在暂停层之上、暂停层盖在图例/商店/营地之上(登记序=树序=遮挡序)
## F · 代拍板追认单(白名单内已落,目检可推翻)
| # | 项 | 已落值 | 推翻改法 |
|---|---|---|---|
| F1 | 关闭钮文案 | 「继续」(紧凑 90 宽返回钮,设置面先例形制) | 改「返回」等一词换文案一处 |
| F2 | 层内行序 | 余额徽 → 属性锻造 → 道具工坊 → 天赋树(营地屏同序) | 顺序对调=一处移动 |
| F3 | 角标文案与位置 | 「暂停」;战斗屏=HUD 右下角(角距 16px)、地图屏=顶栏 GP 徽右侧 | 换角/换角距=锚点一处 |
| F4 | 层标题与副题 | 「暂停」+「查看本局钥石与永久强化进度(只读——购买请回营地)」 | 文案一处 |
| F5 | 天赋树空态句 | 「尚未购买任何节点(天赋树在营地柜台三)」 | 文案一处 |
| F6 | 断言编号与 case 命名 | 探针 case⑯/struct 契约 ⑧⑨(机检面,不涉观感) | 仅重命名时改 |
## G · 数据口径披露(R4 快照口径,机检佐证外的人闸知情项)
暂停层展示值=**每次开层瞬间**实时读取元进度访问器拼装的快照(余额/锻造三行/工坊六行/天赋树概览七类访问器),快照只活到本次关层,重开重取——层开着期间外部数值不会变动(层内零写通路),不存在「层数字过期」问题。机检侧:冒烟投影一致性 5 断言(展示值==访问器逐项)+ 结构探针只读巡检(层子树游戏语义信号连接白名单外零连接,合法连接恰 2=关闭钮与关层外发)全绿。
## H · 机检佐证(已全绿,实机只抽核)
冒烟 788/0(基线 783/0,+5=本批投影断言)· run_all 17 套全绿 · ui_input 17 断言(含⑯暂停层输入锁)/ui_struct 全屏零红(含 pause 结构+只读巡检+零动效契约)/ui_contrast 12 对测点(含钥石徽新对)/ui_click done=true 问题=0/ui_layout exit0 · doc 三闸零新增(06/07 存量注记红系历史批次落文,本批零触碰;design/diagrams 熵增越界系 00712d5 总图批落籍漏步,主区同红——两存量均已移交登记,非本批产生)· 素材零触碰(零新素材零新色值零新字体,全部构成件=UiKit 工厂件+现行色板 token)· MC 零跑(纯呈现零数值改动)
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

+96
View File
@@ -0,0 +1,96 @@
# 全屏 UI 审计:实机 vs demo v2.1(2026-10-06 用户令返工)
> 方法:实机十二屏窗口化程序截图(`game/smoke/ui_audit_probe.gd`,真实信号路径+拟真数据,1280×800 归一)× demo 原型 v2.1 浏览器现截九屏(纯净模式,与 HTML md5 `78ebbee0…` 同代现渲染)。逐屏并排图=`pairs/pair_*.png`(左实机右 demo),原图在 `real/` 与 `demo/`。
> 输入:用户截图的红砖「放弃」按钮(第二层地图屏,特性持有态)+「底栏重设计是根本解、不是限制按钮」裁决。
## 逐屏差距(demo 八映射屏)
### ① 关卡地图(pair_4_map)——用户点名核心屏,差距最大
| # | 差距 | demo | 实机 |
|---|---|---|---|
| 1 | **底栏** | 单条 **~85px** 紧凑亮条:头像+生命轨 \| 属性(含攻击加成副行) \| 本关加成(含持有行) \| 道具槽×2 \| **放弃=小号危险钮 ~90×38** | 亮条 + **放弃=216×50+ 危险钮**;特性持有行无限宽换行把栏爆到 130px+(用户截图实证),全栏跟着涨 |
| 2 | 底栏内容 | 五段齐装(含道具槽与持有行) | 少道具槽、少持有行展示态(特性行爆栏);空态大片留白由放弃钮填充 |
| 3 | 底栏淡墨 | 加成副行用 wood-deep 深棕(亮板上可读) | 特性组用 WARM/WARM_SOFT 暖白系(亮板上 ≈1:1,**不可读——§7.2 违例**) |
| 4 | 背景 | 暖棕渐变聚焦、无纹理平铺 | 全屏石纹平铺(/busy,视觉焦点弱) |
| 5 | 顶栏 | 关卡头与 GP 徽章均有框板(plate 感) | 裸文本浮在纹理上 |
| 6 | 节点图 | 分支树多行多列+连线,分支结构一目了然 | 第一层为单行线性排布(深层有分支但连线视觉弱) |
**底栏重设计草案(待用户裁决后实施,本批未动代码)**:对齐 demo——①底栏定高 88px 单条,五个信息段一行排齐;②放弃改小号危险钮(~90×38,右端);③特性持有行限宽(固定栏宽内 1-2 行省略+tooltip 全文),杜绝爆栏;④特性组墨色换深墨系(INK_HINT/INK_TITLE)修 §7.2 违例;⑤道具槽段位预留(道具读数出口=台账 352 在册项)。
### ② 商店(pair_7_shop)
demo=**全屏页**(顶部标题+刷新徽+GP 框+池源/涨价规则行)+**竖卡三张**(色带/图标/名/效/价/类型脚注);实机=**战斗屏上的小模态**(dim 0.6)+三横行(名+现价+已购档+购买钮),标题与 HUD 行叠压。→ 即 06 在册 D1(卡片 232×352)/D2(商店全屏化)结构级差异,本次截图实证差距量级。实机独有「已购 N 档」档位语义 demo 无。
### ③ 三选一(pair_6_bonus)
demo=全屏页:标题+**GP 汇总行**+三张竖卡(色带/图标/名/效/类型脚注/**选中✓**)+确认选择钮+免费选择注记。实机=战斗内浮层:标题+三行引导文字(关卡奖励点/从提升池抽…/选择一件带走)+窄条卡(~140×220,无脚注无选中✓)+无确认钮(点卡即选)。
**新证据(E5 追认)**:demo 的「工兵爆破」卡=**紫带(magic 族)**,实机按 T4a 归 TG_AOE=粉带——demo 自身的 blast 归属与 T4a 判定相反,建议回滚 E5(blast 归回 TG_MAGIC),随用户裁决。
### ④ 战斗结算·胜利(pair_8_end_victory;失败态同族)
demo=全屏 dim(仪式感)+石皮框板卡:标题+三行**两列对齐账目**(战利品/钥石/本关加成)+紧凑主钮「下一节点」;实机=**无 dim**(战斗屏裸露)+素面板+居中堆叠文本行+全宽黄钮「返回」。仪式感与排版差距大。
### ⑤ 战斗(pair_5_battle)
结构对齐度高(舞台/上轮摘要行/AP·RAP 行/左栏/提示条均在位)。差距:①demo 棋盘融进深棕场景、实机=亮米大平板+四周大片空白(观感最大点);②demo 左栏三段齐装(探险者+魔法道具槽有货+本关强化+流派件),实机左栏=探险者+秘宝空槽(强化/流派件编排不同源);③demo 站桩带名牌与头顶 HP 轨更紧凑。
### ⑥ 标题屏(pair_1_start)
1. **主操作语义反转**:demo=「继续上局」黄色主钮(有存档时继续是首动作)、「开始冒险」石钮;实机=「开始冒险」主黄钮、「继续上局」石钮。
2. 主标题:demo 粗像素体大字+烛光副题装饰线;实机细体。
3. 背景:demo 暗棕渐变+聚光;实机全铺石纹。
4. demo 有「玩法速览」牌——**实机已按用户令删除,不回补**。
5. 立绘/敌人群比例 demo 更大更聚中。
### ⑦ 营地(pair_2_camp)
面板明度关系相反(demo 暗石皮面板浮于暖渐变;实机亮米大板浮于石纹);demo 行带图标/Lv 徽章/价格按钮一格齐,实机行松、工坊行为纯文字行;关闭钮 demo 底部居中、实机左下;实机独有累计通关解锁进度列(功能差异非缺陷)。
### ⑧ 设置(pair_3_settings)
demo 石皮框板+两列对齐行(label 列/控制列)+减动效行;实机素面板+行内流式布局无列对齐+**减动效行缺失**(实机仅 主音量/全屏/结算演出动画 三行——减动效语义由结算行承担与否待核);返回钮 demo 紧凑、实机 216 宽。
### demo 无映射的实机屏(三屏,无对比基线)
调试浮窗(real_9_debug)· 图例(real_10_legend)· 确认框(real_11_confirm)——demo 八屏不含,维持现状,仅存档截图。
## 总体结论(差距量级排序)
1. **关卡地图底栏**(用户点名)——放弃钮尺寸语义错+特性行爆栏+淡墨违例;根本解=按 demo 88px 单条重设计(草案见上)。
2. **商店/三选一形态级差距**(D1/D2 在册):全屏化+竖卡 232×352——06 已登记待立项,本轮截图把量级坐实。
3. **结算仪式感**(dim+石皮框板+两列账目)——呈现批量级。
4. **背景处理全局差距**:demo 暖渐变聚焦、石纹只作局部质感;实机全屏铺石纹——跨屏共通改。
5. **标题屏主操作语义**(继续上局应为主钮)。
6. 战斗屏结构对齐度最高,仅棋盘底色处理与左栏编排差距。
7. E5 证据更新:demo 爆破卡紫带 → 建议 blast 归回 TG_MAGIC(推翻 T4a 的 blast→TG_AOE),随用户裁决。
## 批末判定(2026-10-06 /goal UI 对齐批收口——逐项复判全记)
/goal 令(「将游戏的 UI 对齐 demo 的 UI;完成后自验:ui_audit_probe 逐屏实机截图×demo 浏览器截图,重建并排对比图逐项判定;全部差距闭环或列明不可对齐原因」)执行完毕。判官=documents:visual-judge 两轮独立目检(初判 7 pass/2 partial/1 fail → 修复后复判 4 张全部转 pass),九组并排图已按合后态重摄重建(real/ 与 pairs/ 现内容=最终态)。
### 逐屏判定终态
| 屏 | 判定 | 闭环内容 | 留档差异(非本轮差距) |
|---|---|---|---|
| ①标题 | **pass** | 主操作语义反转(有档=继续上局主黄钮);背景=暖棕底+石纹 0.14+斜光带+暗角 | demo 玩法速览牌已按用户令删除,不回补 |
| ②营地 | **pass**(用户实机复检后二次修复) | 背景氛围层(可见处石纹微弱+暗角);**用户实机两缺陷修(2026-10-06)**:①底改不透明暖亮档(原 0.45 半透 dim 在石纹降 0.14 后底下对局画面透出——demo #v-camp=bg-bright 实底同款)②三柜 EXPAND_FILL 等宽分屏+行标签截断兜底(原行标签按文字全宽算 min,进度/状态长文案随档变长把三柜总宽撑爆 1248=右柜裁出屏)+状态列 tooltip 兜底 | 面板明度/行密度/关闭钮位=camp ⑦ 遗留(06 留档) |
| ③设置 | **pass** | 两列对齐(label 定宽 140)+返回钮紧凑 90+主音量滑轨实高修(HSlider 槽按 stylebox min 高绘制缺陷) | 减动效行不拆=reduced_motion 单设置同驱 motion_scale+结算演播(语义命名批裁决,demo 两行=同一设置) |
| ④地图 | **pass** | 底栏 85px 定高单条+放弃 90 小钮+特性行限宽截断+深墨;顶栏关卡名框板+GP 烛光胶囊+两极排布;背景暖棕渐变 | 道具槽段位=台账 352 功能欠账(非呈现层) |
| ⑤战斗 | **pass** | 背景氛围层成立;轮次条/上轮摘要结构一致 | 棋盘底板融景、左栏编排、站桩紧凑度=battle ⑤ 遗留(06 留档) |
| ⑥三选一 | **pass** | 全屏页(page_shell 根底档)+D1 竖卡 232×352+类型脚注行+底注 | 稀有度词缺=数据面无投喂(词表随数据批补) |
| ⑦商店 | **pass** | 全屏页(D2)+56px 通栏顶条+爬价规则行(实数投喂 shop_bp_visit_buys×shop_price_a)+D1 竖卡+底注池源 | 「已购 N 档」=实机独有档位语义(功能差异非缺陷) |
| ⑧结算·胜/败 | **pass** | DIM_NIGHT 0.62/0.6 全屏压暗(判官实测亮度 218→97)+两列对齐账行+紧凑主钮 | 账行文案词序差异=Narrator 文案域 |
| 无映射三屏 | 存档 | 调试浮窗/图例/确认框维持现状(demo 无基线) | — |
### 不可对齐/留档原因清单
1. **营地面板明度与行密度、关闭钮位**:camp 布局属 M 批落码形制,重排=独立呈现批量级,本批只落背景氛围层;06 留档。
2. **战斗棋盘底板**:棋盘视觉=样张 v2 机检冻结域(golden 断言),动底板需过样张闸;06 留档。
3. **地图道具槽**:道具读数无关卡画面=成文出口(台账 352),功能件非呈现层。
4. **稀有度脚注词**:候选数据面无稀有度字段投喂,随数据批补。
5. **减动效独立行**:与结算演出动画=同一设置(语义命名批 T17 裁决合并),拆行=一设置双行重复,不拆。
### 闸门记录
开工基线冒烟 782/0(4336fd2 净态)→ 每轮轻闸冒烟 782/0+probe_gate --click 全绿 → 批末 run_all 16 套全绿+全探针绿+doc 三闸零新增(2 处 06 陈旧断链系基线随 merge 自愈,非本批引入)→ 合 master 2ca6288 主区复跑(冒烟 782/0+click 全绿+run_all 17 套全绿〔含并行批新落 curio_refresh_paid_test〕)→ 判官修复轮复验全绿。
+6
View File
@@ -39,6 +39,12 @@ api_decisions:
adr: ADR-0005
decision: SCHEMA_VERSION 比较逻辑归 存档序列化(存档版本 > 当前 = 拒读);RNG 快照 = master_seed + 各流 scope 计数器 + 意图/窗口选择序列,切出须在 scope 事件边界外(无在飞 open_stream 实例——战斗结算 编排保证)
core_decisions:
- name: effect_engine_interpreter
adr: ADR-0011(候选——内容数据驱动扩展批 2026-10-06)
decision: 内容效果行为=发布订阅解释器(EffectEngine)——结算管线同步 emit 事件(无队列无异步),内容行以「订阅哪个事件 on / 什么条件 when / 什么效果 do」声明订阅,解释器遍历持有订阅集返回按声明序排列的命中,发射点按组合规则施加;旧 23 挂点枚举与按件 id 特判消亡
note: 事件/效果类型/条件事实/算子四词表封闭于 EffectEngine 常量(单一事实源,schema 校验引用);遍历序=数据表声明序写死保种子复放;订阅重建=每战 begin_battle(中途获得下一战生效);不做通用拦截器链,改写窗口=判定点就地按声明序施加(R2 裁决)
forbidden_patterns:
- pattern: autoload_global_event_bus
adr: ADR-0001
+6 -5
View File
@@ -339,7 +339,7 @@ entities:
pool_tag: enum {cell, clear_default}(cell = 格面资源单一池——安全格与雷格一视同仁同池同分布;clear_<biome> 命名空间预留、校验拒绝——棋盘生成 elite_ 同款) # 2026-09-15 safe_cell→cell 更名 + active_inject 删除
tier: int [1, 8](knob)——强度档位序数(与当量零耦合)
cross_field_validation: 加载期致命族——池空(cell 池 ≥1 正向行 weight>0)· 九型正向行齐备 · 九型负向行齐备(字典完整性——缺任一极性行致命——2026-09-20 八型批、同日 GP+商店房批随九型同步)· clear_default 恒正当量(≥1 活行 ∧ power≥1 ∨ effect_id 非空——行动经济 条款④"清图奖励>0"的行级兑现口径)· percent 行 effect_id 必填/flat 行恒空 · flat 行 power≥1 # 2026-09-15 重写——旧 floor_supply_missing / no_damage_row 随可选类删除失义退役
mechanics: 格面资源身份 install 期预分配(roll_board 恰一次、行主序、消费 reward_roll 封闭流恰一 scope 批〔格批 + 清图批尾一号〕;全部非封锁格逐一摇定类型——安全格与雷格同池同分布、封锁格不入摇号清单;Ready 后只读、无重掷 API)· **极性不在资源内**——「动作 × 格型」矩阵(开安全格/标中雷 = 正向、开雷格/标错安全格 = 负向、插旗安全格直挖 = 零兑付〔四情况④〕;撤旗动作随插旗不可逆批 2026-09-19 退役)字典定义归 地图战斗资源、路由执行归 战斗结算 授予段(结算队列 + 轮末在场旗判定基线——被挖开的旗不入基线)· 授予期零随机(身份恒定跨轮;换图映射消亡)· 负向恒即时(不入库、无库存语义——库存已随可选类删除下线)· 满层零兑付 = 合法例外 + "奖励未生效"行 · 重复受理幂等(同格重复 grant / 同批次重复 grant_clear → 同一快照/身份 + 诊断;受理/兑付恰一次归 战斗结算×②③)
mechanics: 格面资源身份 install 期预分配(roll_board 恰一次、行主序、消费 reward_roll 封闭流恰一 scope 批〔格批 + 清图批尾一号〕;全部非封锁格逐一摇定类型——安全格与雷格同池同分布、封锁格不入摇号清单;Ready 后只读、无重掷 API)· **极性不在资源内**——「动作 × 格型」矩阵(开安全格/标中雷 = 正向、开雷格/标错安全格 = 负向、插旗安全格直挖 = 零兑付〔四情况④〕;撤旗动作随插旗不可逆批 2026-09-19 退役)字典定义归 地图战斗资源、路由执行归 战斗结算 授予段(结算队列 + 轮末在场旗判定基线——被挖开的旗不入基线)· 授予期零随机(身份恒定跨轮;换图映射消亡)· 负向恒即时(不入库、无库存语义——库存已随可选类删除下线)〔案C 2026-10-06 用户裁:伤害形态正负单据的扣血落地暂存至战斗段末统一执行——账户受理仍在授予段,兑付时点归 战斗结算〕· 满层零兑付 = 合法例外 + "奖励未生效"行 · 重复受理幂等(同格重复 grant / 同批次重复 grant_clear → 同一快照/身份 + 诊断;受理/兑付恰一次归 战斗结算×②③)
api: 封闭枚举入口(provisional,实现期 ADR 定名)——roll_board / query_identity(返回 {reward_id, cell_type, tier} 引用级投影;未开格恒可查——秘宝 桥接结构前提;清单外坐标 → null + 诊断)/ grant(同格重复受理幂等 + 诊断)/ grant_clear(同批次重调幂等 + 诊断)/ retire_mapping / equivalence_supply(全活行投影 + tier_min_buff)+ weighted_pick 纯函数面;新增入口 = 接口漂移,新增入口须随附全输入域语义表 # 2026-09-15 删 stock/use/query_inventory/clear_inventory(库存轴下线)
mvp_content: 十八行(2026-09-15 格面资源批十行;2026-09-18 伤害道具批增补四行;2026-09-20 格面资源八型批 ambush_double→enemy_alert 换装 + ap_up/ap_drain 两行新增;同日 GP+商店房批 +gp_gain/gp_loss 两行)——格面池正向九行(attack_up / ac_up〔2026-09-16 护甲等级掷点批换装,原 defense_up 减伤 −30% 退役;cell_type defense/权重/档位零改动〕/ spark_aoe / heal_minor / weaken / pierce_strike / magic_bolt〔attack_type 字段载攻击类型轴,查战斗结算克制矩阵、单目标必中全额〕/ ap_up action〔下轮行动点 +1——2026-09-20 八型批新增〕/ gp_gain gp 金币袋〔战斗内 GP 缓冲 +power,兑付编排归 战斗结算、钱包账本归 冒险结构——GP+商店房批新增〕)+ 负向九行纯字典(enrage / off_guard / heal_backlash 直伤〔不经增益状态〕/ enemy_alert blast〔effect_id=alert,敌方护甲等级 +1——2026-09-20 八型批 ambush_double 退役换装〕/ ap_drain action〔下轮行动点 −1〕/ sapped / pierce_snare / magic_recoil〔均主角直伤,不经增益状态〕/ gp_loss gp 破财〔战斗内 GP 缓冲 −power——GP+商店房批新增〕)+ clear_blast(clear_default);类型频次 = 正向行权重合计;tier_min_buff = 2。**2026-09-17 数值压缩批·文档同步——具体数值列(power/weight/power_min/power_max)改指路存根**:现行行值读 `data/tables/reward.tres`(压缩后锚行:spark_aoe power=1 / heal_minor power=[1,1] 定值(原 [2,6] 区间压缩)/ heal_backlash power=1 / clear_blast power_min=8 power_max=18 power=13 中点 / ambush_double stacks=2;类型频次合计 79→67〔heal 权重 15→3〕;2026-09-20 八型批后 67→74——attack 14 / defense 11 / blast 16 / heal 2 / weaken 8 / pierce 8 / magic 8 / 清障炸药 1 / action 6;同日 GP+商店房批九型后 74→76——+gp_gain weight 2)
direction_precheck: **刀供给方向预检随可选类删除失义退役(2026-09-15)**——历史读数见底部修订记录;新对账锚 = 行动经济 条款②③ 左臂(正向格面资源当量供给)随格面资源批重推,义务归 难度曲线与Boss 调参批
@@ -373,7 +373,7 @@ entities:
ac_roll: 护甲等级掷点(**2026-09-16 护甲等级掷点批定稿,数字即规范**——骰面 roll_faces=20、nat 最大面 crit_roll=20、暴击倍率 crit_multiplier=200、攻击加成 attack_bonus=0〔结构位,元进度/武器附魔未来投值〕、伤害下限 damage_floor=1、流名 armor_roll_stream="armor_roll";判定式:掷 1d20,掷点 ≥ 防守方护甲等级 + 攻击加成 → 全额、低掷按缺口查档〔见 ac_discount_tiers〕,nat20 暴击该基础攻击分量 ×2 且恒全额〔双方同规〕;任何攻击落地伤害 ≥ damage_floor〔**2026-09-20 伤害下限全来源批(用户拍板)**:语义扩为任何来源的伤害落地——攻击双方/棋盘克制直伤/爆裂/地形变异/负向反噬全部收进闸内,伤害取值域 [1, +∞) 不设上限;全局 max(1,·)——零值伤害行语义退役,重档折扣行文本记"被压制"〕;吃掷点分量 = 主角先手攻击普通分量 / 敌方技能基础伤害分量〔= 攻击基线 × 技能伤害倍率——2026-09-16 敌人技能池批改述,原"敌方攻击拍与重击拍基线伤害"退役;无伤害分量的增益技不掷不折〕,棋盘来源伤害〔爆裂 / 清障炸药 / 奖励即时——2026-09-19 充能退役后无充能分量;伏击附加项随 2026-09-20 八型批伏击退役移除〕必中全额不掷;回合内随机、消费 armor_roll 封闭流逐次掷逐次取号,可逐位回放)
ac_discount_tiers: Dictionary 缺口档边界→档位值 percent(**2026-09-16 定稿**——roll_tier_bounds=[3,7] · roll_tier_discounts=[75,50,25],档数 = 边界数 + 1;缺口 1-3 → ×0.75 · 4-7 → ×0.5 · 8+ → ×0.25,档位不设零档〔非归零〕,取整沿全局 floor;EV 参考数〔按判定式复算〕= AC10 期望减免 21.25% / AC11 25% / AC12 28.75%;微调旋钮 = 边界与档位值,不动 AC 值;难度曲线与Boss 生存链区间带宽补扫含暴击档与折扣档、"零红档"验收保留)
validation: segment_order 违例致命 · effect_pool_map 悬空致命 · p_perfect 域 {100,200}(2026-09-10 载体域——100 = "完美必须 ≥ 不加倍"机制语义下界,200 = 双份交付)——战斗结算 冒烟三行致命 manifest(segorder_violation / poolmap_dangling / pperfect_oob)
mechanics: 结算段序骨架唯一权威载体(授予→增益/减益→战斗→衰减→判定——2026-09-15 格面资源批五段,item_window/item 两段随可选类删除下线)· **随机口径(2026-09-15 护甲等级批修订)**:结算换算层引入回合内随机(ac_roll 护甲等级掷点——必中非归零、低掷按 ac_discount_tiers 档位折扣),掷点流归属未定〔rng_service 流封闭清单 board_gen/reward_roll/encounter 不含结算内消费——新增流须改代码+P1 支柱评审、复用 encounter 则改"实例化期恰一 scope"绑定,登记 战斗结算「待办」,rng_service 条目随定稿批修订〕· 可回放契约 = **封闭随机流可回放**(同 master_seed 同意图序列 ⇒ 步骤流逐位复现——数据配置 AC-15 落点,原"结算路径零随机 / 步骤流逐行相同"口径随批作废;开战掷区间 / 装板摇号属初始化随机维持不变)· 调用序钉死 按摇定技能行兑现→apply_damage→commit_action(2026-09-16 技能池批改型——原 query_attack→apply_damage→advance 随行为环退役;行型 10 类同批改型:蓄力行 charge → 施放行 cast〔增益技 0 伤害施放、具名技能、不掷不折——原"不兑伏击"语义随 2026-09-20 八型批伏击退役改述〕)· 衰减恒执行含末轮 · 高光双落载体(perfect_sweep P_perfect——2026-09-10 修订为真实双份兑付载体 / 标中旗 highlight 标记)· 流水行协议字段分层(公共 7 字段 + 行类型特有 target/effect_id/pool_value/聚合计数——2026-09-10 评审批修订;行类型封闭枚举 9 类(2026-09-20 伏击上限删除批下线溢出未生效行 overflow)——2026-09-15 格面资源批由 15 类收拢:删道具行 / 已消耗未生效行 / 使用被拒行 / 窗口打开锚行 window_open / 窗口跳过锚行 window_skip 五类随可选类删除下线〔2026-09-15 窗口锚行批曾由 13 扩为 15,同日回撤〕;行来源断言两层豁免集合同批修订 = 行型豁免 {decay, verdict} × 来源类别豁免 {hero_attack, enemy_action, clear_reward},豁免不等于免检——豁免行仍受公共字段与各自语义约束,清单改动须同步 战斗结算 明细流水一节与 battle_log_view 格式化)· **类型化克制结算规格 = 战斗结算 GDD F6(W3 补全,2026-09-14 重算批;2026-09-15 命名统一批;2026-09-19 充能退役批——挖掘期充能/战斗段消费半边废止,加法核点数修正)**——逐分量 armor_effectiveness 查表(奖励直伤道具消费方保留)
mechanics: 结算段序骨架唯一权威载体(授予→增益/减益→战斗→衰减→判定——2026-09-15 格面资源批五段,item_window/item 两段随可选类删除下线)· **随机口径(2026-09-15 护甲等级批修订)**:结算换算层引入回合内随机(ac_roll 护甲等级掷点——必中非归零、低掷按 ac_discount_tiers 档位折扣),掷点流归属未定〔rng_service 流封闭清单 board_gen/reward_roll/encounter 不含结算内消费——新增流须改代码+P1 支柱评审、复用 encounter 则改"实例化期恰一 scope"绑定,登记 战斗结算「待办」,rng_service 条目随定稿批修订〕· 可回放契约 = **封闭随机流可回放**(同 master_seed 同意图序列 ⇒ 步骤流逐位复现——数据配置 AC-15 落点,原"结算路径零随机 / 步骤流逐行相同"口径随批作废;开战掷区间 / 装板摇号属初始化随机维持不变)· 段内伤害序(案C 2026-10-06 用户裁)= 主角先手→逐敌还手→地图伤害账殿后(授予段伤害形态单据暂存、战斗段末按事件序补提交统一结账;主角倒下暂存单整体不兑逐单留「未生效」行)· 调用序钉死 按摇定技能行兑现→apply_damage→commit_action(2026-09-16 技能池批改型——原 query_attack→apply_damage→advance 随行为环退役;行型 10 类同批改型:蓄力行 charge → 施放行 cast〔增益技 0 伤害施放、具名技能、不掷不折——原"不兑伏击"语义随 2026-09-20 八型批伏击退役改述〕)· 衰减恒执行含末轮 · 高光双落载体(perfect_sweep P_perfect——2026-09-10 修订为真实双份兑付载体 / 标中旗 highlight 标记)· 流水行协议字段分层(公共 7 字段 + 行类型特有 target/effect_id/pool_value/聚合计数——2026-09-10 评审批修订;行类型封闭枚举 9 类(2026-09-20 伏击上限删除批下线溢出未生效行 overflow)——2026-09-15 格面资源批由 15 类收拢:删道具行 / 已消耗未生效行 / 使用被拒行 / 窗口打开锚行 window_open / 窗口跳过锚行 window_skip 五类随可选类删除下线〔2026-09-15 窗口锚行批曾由 13 扩为 15,同日回撤〕;行来源断言两层豁免集合同批修订 = 行型豁免 {decay, verdict} × 来源类别豁免 {hero_attack, enemy_action, clear_reward},豁免不等于免检——豁免行仍受公共字段与各自语义约束,清单改动须同步 战斗结算 明细流水一节与 battle_log_view 格式化)· **类型化克制结算规格 = 战斗结算 GDD F6(W3 补全,2026-09-14 重算批;2026-09-15 命名统一批;2026-09-19 充能退役批——挖掘期充能/战斗段消费半边废止,加法核点数修正)**——逐分量 armor_effectiveness 查表(奖励直伤道具消费方保留)
closure_receipt: 行动经济 F1 条款①②③⑤闭合 owner = 战斗结算(2026-09-10 F0–F5 首版验算完成——F0 瞬时当量口径 + m_w 值域裁决见 status_effect.anchor_warning;条款③ clause3_supply 闭合回执;条款⑤ clause5_dominance 条目;actuals p10 交付后强制重跑)
referenced_by: [HUD框架, 战斗表现, 音频, 教学引导, 难度曲线与Boss]
@@ -600,7 +600,8 @@ entities:
lifecycle: 候选池构建(冒险开局一次)→ 在渠道上出现(三选一形式)→ 选定(自池中剔除不再复现;选到「专长获取」时立刻再开一次专长 N 选一)→ 持有生效或即时兑付 → 冒险以任一结局收束时整集清零;断点记录持有集与剩余候选池
acquisition: 三条渠道的**目标分工(交叉开关,v2.2 收口)**——专长:主渠道=**关底 Boss 击败=通过这一关**(**唯一直接给的渠道**;不新增节点类型、挂 Boss 节点兑付面;末关的 Boss 击败后不给——无后续关卡可消费)。**兑付频率**:奇物不是打一场战斗给一份,关内普通战斗节点不给任何奇物,一关之内只兑付一次(奖励节点与商店同理,各节点各自兑付),奖励节点与商店**只给「专长获取」门票**——**拿到即开、不可囤积**,不进持有集(选中/买下同一时刻开专长三选一;可囤积会让玩家无限推迟关键决策,且把持有物语义从后门放回)。门票归专长(给的是一件以前不会的事,只是把选择推迟)。罕见**只在概率不在价格**,一局限购一次,**计步保底**:连续 5 次三选一展示未出现→第 6 次必出(计数=展示次数、刷新重展计入、奖励节点与商店共享、触发清零、限购用满后不再触发);属性值提升:奖励节点 + 商店(口径「训练」);资源:奖励节点 + 商店(**金币除外、回复在内**);后两类均不出现在 Boss 渠道。形状=「一块独占 + 两块并行」,专长靠打赢、其余靠抽取与购买。**默认原则**:除已登记的特殊规则外,分类内的东西都要在它该出现的渠道池子里——任何不出现都须登记理由**现行实现三渠道共用同一候选池、三类混编**,分工尚未实施,登记于 06-待办清单 BD 分层条目
boundary: 判据走生命周期——**一次冒险内获得、冒险收束即清零的是奇物;跨冒险跟着你走的是魔法道具**。奇物永不进同调位,魔法道具永不进当局随机渠道;与元进度天赋树两层互不代位
data_sources: feats.tres(专长定义行)/ adventure.tres(属性值提升与资源的种类配额与值)/ shop.tres(货架取舍)
data_sources: feats.tres(专长定义行——效果声明=triggers 订阅行〔订阅哪个事件 on / 什么条件 when / 什么效果 do〕,旧挂点+效果字典形态 2026-10-06 内容数据驱动扩展批退役)/ adventure.tres(属性值提升与资源的种类配额与值)/ shop.tres(货架取舍)
effect_declaration: **效果行为=事件订阅(2026-10-06 内容数据驱动扩展批换代)**——事件/效果类型/条件事实/算子四词表封闭于效果引擎 `game/core/effect_engine.gd`(事件 16 发射点 / 效果类型 24 / 条件事实 9 / 算子封闭;四词表出域=加载期校验致命);组合规则六族(加法/乘法/任意真/按序改写/按序消耗/即时执行)为效果类型必填属性;遍历序=数据表声明序写死保种子复放;订阅重建=每战开始从持有集/装备集重建(中途获得下一战生效)
charge_defect: **charge 档二不可达登记(T7 奇物批迭代15②——数据缺陷留痕,白名单4授权「只登记不硬补」)**:feats.tres 现行 charge 标签仅 3 件(<4),档二激活要求同标签 ≥4 件——charge 流派永远达不到档二,即使获取次数无限。补哪几件系内容裁决,转独立内容批(硬补占位件已否决);档二可达性复裁=第四关内容批落地后实测(C2 待裁点)。
pool_architecture: **池架构=总池-渠道子集(多级缓存形,用户 2026-10-05 裁 T6 时确立)**:总池=单一令牌库(TIER_QUOTAS 70/25/3=98 + 专长活行追加);三渠道按分类白名单从总池取**子集视图**(关底 Boss 击败=只出专长子集;奖励节点/商店=属性值提升+资源子集,专长只以门票形态出现)——渠道不各建物理池,白名单在候选视图层生效(T4 过滤式)。配额挤占重裁:heal rare 5→3、refresh rare 0→2(方案B,总量 98 锚不变;用户裁「渠道从总量里拿子集」时同步裁)。
refresh_boundary: **刷新次数边界写死(T6 奇物批迭代15②——防后续混淆结算)**:「商店独立刷新机制」(shop_refresh_free/shop_refresh_cost_base/shop_refresh_cost_curve 三旋钮——进店后的免费次数+GP 付费刷新)系**商店自身服务**,作用对象=货架重抽;奇物 refresh 件(资源类成员,作为奇物授予的重抽次数)作用对象=**三选一界面**(兑付即 _attune_refresh_x 增量,X 余量=三选一重抽次数),不进加算区(§2.2 加算区四轴不含它)。两者不是一回事,禁止混算。
@@ -815,7 +816,7 @@ entities:
# ④ status_effect:defense_up 行退役换装 ac_up(护甲强化 +1 ac ×2 层,unit=ac 新量纲,不入任何池);
# ⑤ reward_table:defense 型正向行 defense_up → ac_up(显示名暂定"护甲强化",权重/档位/cell_type 零改动);
# ⑥ settlement_table.effect_pool_map 删 defense_up 键(hero_defense 池现仅 off_guard 正向行——×0 免伤墙结构面消失)。
# 2026-09-16 敌人技能池批(用户拍板 2026-09-16,设计权威 docs/proposal-skill-pool.md v1.0——与 敌人系统 v0.5 /
# 2026-09-16 敌人技能池批(用户拍板 2026-09-16,设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0——与 敌人系统 v0.5 /
# 战斗结算 v0.11 / 增益状态 v0.5 / 难度曲线与Boss v0.6 / 战斗表现 v0.3 / HUD框架 v0.4 / 数据配置 / 03-内容规模 /
# 02-系统清单 / 关卡节点地图 / 06-待办清单 / ux battle.md / architecture.md / 切片代码同批):
# ① rng_service 增流 behavior_roll(开轮摇号——回合内随机、时点前置到每轮开轮;派生向量 = spawn_index×1000000 +
@@ -901,7 +902,7 @@ entities:
# 五档百分比词表退役);enemy/hero armor_type 两行注记同步;
# ③ 切片同批:settlement.tres 九格/settlement_table.gd 域与哨兵/damage_math 两函数改加法/battle_orchestrator
# _counter_delta 改名与回退 0/smoke 矩阵断言改形;元进度投值语言锁 flat;GP 提案档位词汇免议注记落 06 清单。
# 2026-09-19 技能池新效应词汇批(用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0;与 敌人系统 /
# 2026-09-19 技能池新效应词汇批(用户拍板——设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0;与 敌人系统 /
# 战斗结算 / 增益状态 / 06-待办清单 / 切片代码同批;06 清单「技能池新效应词汇批」解决移除):
# ① skill 条目:type 枚举三→四(+debuff 妨害——多段命中经用户拍板退役不入枚举);新增 rider_mult 字段
# (必中附加分量——固定值伤害改形:不通用/跨关稀释析出,价位锚 0.75 = AC 折扣档最轻档);池纪律 +
@@ -1,7 +1,7 @@
# 任务书:M4 数值批(v1.0 定稿,待发令开工)
# 任务书:M4 数值批(v1.2 定稿——案C 增补+联审修订,开工门=U0 用户发令)
> 成文 2026-10-05。**性质**:四件数值收口合一批 + 两件读数义务随批跑 + 一件既有探针红灯顺路修复。
> 归属迭代:**迭代 17 · 卡②**(迭代 17 四卡:①敌人表行集多行批 ②本批 ③暂停层只读入口批 ④生涯界面设计立项)。
> 成文 2026-10-05,v1.2 修订 2026-10-06(五任务书联审:P3 转正顺延、检算工具入留痕、T3/T5 跑批并账、06 死数字补登记、R5/F19 调停、估时勘误)。**性质**:四件数值收口合一批 + 两件读数义务随批跑 + 一件既有探针红灯顺路修复。
> 归属迭代:**迭代 18**(2026-10-06 用户令自迭代 17 卡②移出独立成批——不影响迭代 17 在飞开发;迭代 17 余卡=⓪内容数据驱动扩展 ①敌人表行集多行批 ③暂停层只读入口批 ④生涯界面设计立项)。
> 满足 loop engineering 八件(见 §9 逐条对照)。
> 🔴 **铁规前置(违反即返工)**:①本批一切 MC / verifier 跑批**发起前须用户批准**(先推算后重跑铁规 + MC 触发细则:数值验证场景才触发,四档硬闸在册);②**调参联动禁独立调参网络**——行动经济 F1 条款3 v0.8 已立 β 带 [1.2,2.5] 逐 u 检算口径,任何数值调整须按调参联动表同窗检算,禁单参数孤立改。
@@ -21,9 +21,9 @@
| 2 | 读数义务两件履行 | T6 MC 四带复算读数出报告;T7 技能池节奏重测读数出报告(均须用户批准后发起) |
| 3 | damage_probe A1 转绿 | 「fresh 池 Boss 21 拍攻击链」断言修复或通过断言换代诚实关闭(换代须呈报依据),damage_probe 七项全绿 |
| 4 | 文档三类同步 | 凡动数值:`.tres` + GDD 正文表格 + registry entities.yaml + 06 状态行四类同步(doc-conventions §5 双写失同步禁止条款) |
| 5 | 重闸全绿 + 人闸完成 | 冒烟全量(基线 T0 重测回填)· run_all 十五套件 · doc 三闸零新增 · 熵增闸 PASS;provisional 追认清单与读数报告交付用户 |
| 5 | 重闸全绿 + 人闸完成 | 冒烟全量(基线 T0 重测回填)· run_all 十七套件 · doc 三闸零新增 · 熵增闸 PASS;provisional 追认清单与读数报告交付用户 |
> ⚠️ **基线纪律**:起草时点 master 头 = 413c936,冒烟基线 772/0,run_all 14/15(reward_overlay_test 红 = 迭代 15② 奇物批遗留基线红,与本批无关,对照口径 = 零新增)。T0 重测回填,禁止沿用本文数字。
> ⚠️ **基线纪律**:起草时点 master 头 = 413c936,冒烟基线 772/0,run_all 14/15(reward_overlay_test 红 = 迭代 15② 奇物批遗留基线红,与本批无关,对照口径 = 零新增)。**v1.1 增补时点(2026-10-06)master 头 = 7d3e88fc,冒烟 783/0,run_all 17 套全绿——案C 地图伤害账殿后批已换代每轮结算行为序,本批一切 MC 读数按新行为首采**。T0 重测回填,禁止沿用本文数字。
## 2. 现状事实(代码级考证,2026-10-05 起草时点;T0 须自行复核)
@@ -33,8 +33,9 @@
|---|---|---|
| F1 | 现行表值 | `status_effects.tres`:`weaken` magnitude **−65**(percent)· `duration_settlements` **2** · `stack_policy` refresh(叠层改续时语义已定案,2026-09-18 盘问会话 + 结构修复批落地)· max_stack 16(续时语义下结构性不触顶) |
| F2 | 欠账内容 | duration 终值(现值 2 为临时值)+ 当量锚复算(「标中旗必须比随便挖一格更值」的当量终值,战斗结算与地图战斗资源共裁) |
| F3 | 取值域 | [60,85](06 条目登记,源自旧体系裁决);复算须按 β 带 [1.2,2.5] 逐 u 检算口径(行动经济 F1 条款3 v0.8) |
| F3 | 取值域 | [60,85](06 条目登记,源自旧体系裁决);复算须按 β 带 [1.2,2.5] 逐 u 检算口径(行动经济 F1 条款3 v0.8)。⚠️ **带有效性未复核(v1.2 补)**:[60,85] 是案C 行为换代+收窄批两层变更前的旧裁决产物,weaken 计入收益侧、magnitude 越大 β 越高——T0 推算稿须给出「β 约束下的 magnitude 可行子区间」,若 85 处逐 u 破带则可行带收窄,按 L3 呈报用户裁带,禁默认全带可用 |
| F4 | 关联新变量 | 2026-10-05 判式换代批已投 `flag_hit_premium=125`(provisional,旗溢价 ×1.25)——削弱当量复算须把旗溢价纳入同窗检算(难度曲线与Boss 调参联动表已登记 δ↔p_perfect↔ap_per_round 联动面) |
| F4b | 检算工具载体(v1.2 补) | 当量锚/β 带复算的常设重跑入口 = `tools/clear_dominance_audit.py`(行动经济.md:134 明文),该工具 **51 行硬编码 `WEAKEN_PCT = 65`**——magnitude 投到非 65 值而工具常量不同步,投值前后全部复算读数按旧值错算。**工具常量随投值同步**是 T1 完成判据之一,且该文件入 §10 留痕清单、常量刷新入四类同步面 |
### 2.2 件② 调参批数值点评(06「调参批数值点评登记」条)
@@ -56,7 +57,7 @@
| # | 事实 | 读数 |
|---|---|---|
| F11 | 柜台定价现值 | `meta.tres` forge_products 三行:`base_price` **20** · `price_ratio_pct` **150**(血+3/攻+1/甲+1 不变)——⚠️ **06 条目文本写「base 10 公比 150」,与表值不符**:2026-09-22 数值设计批(关卡成长×永久成长对齿)已把 base_price 10→20,06 条目文本滞后未刷新,本批随件④收口时一并刷新该句 |
| F11 | 柜台定价现值 | `meta.tres` forge_products 三行:`base_price` **20** · `price_ratio_pct` **150**(血+3/攻+1/甲+1 不变)——⚠️ **06 条目同一句有两处死文本**(v1.2 补全):「base 10 公比 150」(2026-09-22 数值设计批已 10→20,文本滞后)+「Boss 两档 L1 5/1·L2 8/2·L3 12/3」(迭代 10 重锚前死数字,现值 3/3/3·2/2/3)。T4 判据「06 文本滞后句刷新(F11)」按两句全刷执行,只刷 base 句出口后 06 仍带死值 |
| F12 | Boss 两档现值 | 同 F7(首杀 3/3/3 · 复杀 2/2/3,provisional);剩余面 = 定价数字与 Boss 两档**终值**投定 |
| F13 | 工坊六件 | 阈值 1/1/2/2/3/3 按总通关次数(channel=total_clears)已落地;06 注记「钥石直购价随定价批后补」——直购价是否立列随批裁(P4) |
| F14 | 换算率 | conversion 三行已投 6/9/1(2026-09-23 标定批,冒险条件口径实测)——不在本批范围,除非重标读数破带 |
@@ -65,10 +66,18 @@
| # | 事实 | 读数 |
|---|---|---|
| F15 | 读数义务 A | **T6 MC 四带复算**(初始展开收窄批后置,2026-10-05 落籍时按切分预案挂 07 现行义务):收窄批(剃雷域 r=1 + R₀≤cap 重掷闸)后的四带通关率复算 |
| F16 | 读数义务 B | **T7 技能池节奏重测**(07 现行义务,技能池执行批挂单):≥50 distinct seeds 节奏重测,过涝判读带 = Boss 半血后特殊技密度上探;S2 过涝越带 → 解锁技权重/倍率回调**呈报禁自动调** |
| F15 | 读数义务 A | **T6 MC 四带复算**(初始展开收窄批后置,2026-10-05 落籍时按切分预案挂 07 现行义务):收窄批(剃雷域 r=1 + R₀≤cap 重掷闸)后的四带通关率复算。⚠️ **与 F8 同一测量(v1.2 并账)**:件③「通关率带重扫」与本义务口径同为现行构建四带通关率(balance_verifier 冒险段派生),**一次跑批双认账**,禁两个卡各跑一遍(R3 先推算后重跑)。另:07「现行义务」节尾还有「真人侧读数换 81000 锚补算 k 终值」一段,是否随 T5 履行 T0 呈报定性,禁默认顺延 |
| F16 | 读数义务 B | **T7 技能池节奏重测**(07 现行义务,技能池执行批挂单):≥50 distinct seeds 节奏重测,过涝判读带 = Boss 半血后特殊技密度上探;S2 过涝越带 → 解锁技权重/倍率回调**呈报禁自动调**。⚠️ **判读带换代复核(v1.2 补)**:判读带挂单于 2026-10-05(案C 之前),案C 移动地图伤害兑付时点 → 战斗轮数与 Boss 血量曲线移位 → 「半血后」窗口与密度分母都漂——T7 执行前先复核判读带在案C 新行为下是否仍有权,失权即停机呈报重立带 |
| F17 | 顺路修复 | **damage_probe A1 红灯**(`smoke/damage_probe.gd:72`「A1 攻击链健康(fresh 池·掷点口径):非蓄力拍 d_tick = max(下限, 掷点档位基线+附加)」)——判式换代批出口报告 §四.7 在册:**改前既有红**(26374ac 复跑同败,非任何在册批引入),原登记「归独立 mini-loop 处置」,现按用户令编入本批顺路修复 |
### 2.6 案C 行为换代事实(v1.1 增补——2026-10-06 起草时点后发生)
| # | 事实 | 出处 |
|---|---|---|
| F18 | **每轮结算行为序换代**(案C,用户裁 git 7ef18ac/58dfb56,台账 371):①授予段只兑非伤害账(资源/增益/治疗/行动点/GP/警觉;伤害形态单据暂存)→③战斗段=主角先基础攻击→敌人按生成序逐个还手→**地图伤害账殿后**统一结账;主角死于敌方还手→暂存单整体不兑逐单留「未生效(主角已倒下)」行(forfeit=hero_down)。事实源=战斗结算.md **v0.26** | 战斗结算.md v0.26 / 台账 371 |
| F19 | **旧行为 MC 锚与对拍锚全数作废**(06 条目 2026-10-06 登记)——「授予段伤害致死短路先手」路径消失,旧锚所锚行为已不存在;重锚前旧读数只作历史存档,不得与新行为对拍。四带复算跑批本就未发起,零沉没成本——直接按新行为首采立新锚 | 06-待办清单 2026-10-06 条 |
| F20 | 难度走向预判(供 T6 读数判读参照,非结论):案C 使主角更安全——挖掘期踩雷/反噬不再能先手致死+主角保底先手,同表值下通关率预期上行;若四带复算越带,调参方向归 T2/复算后按 R1 呈报禁自动调 | 本任务书判读框架 |
## 3. 范围边界(🔴 不可越界)
| 禁项 | 理由 |
@@ -79,6 +88,7 @@
| **双写失同步禁止** | 动任何数值必须 `.tres` + GDD 正文 + registry + 06 状态行四类同步,缺步即视为未完成(doc-conventions §5) |
| **非数值面零触碰** | 本批不改机制、不改呈现、不改存档 schema |
| **迭代 15② 奇物批不交叉** | 渠道分离与入池实施段归迭代 15 继续完成,与本批无关;reward_overlay_test 基线红归②批处置,本批只守零新增 |
| **与迭代 17 卡⓪/卡① 的交叠声明(v1.2 补)** | 卡⓪重写 battle_orchestrator 事件挂点+授予/兑付分支、卡①放开行集多行改遭遇构成——两者都在本批 T6 damage_probe A1 归因、对拍锚重推导、四带通关率分母的同文件同管线上。时序安全(本批前置=迭代 17 出口),但:①A1 红灯归因与修法在卡⓪落地后可能变样,T6 执行时按卡⓪出口报告重对账;②T0 事实表复核清单含「按卡⓪/卡①出口报告重取受影响事实」,禁照抄本文行号 |
## 4. 设计契约(🔴 触碰 = L3 停机)
@@ -88,23 +98,23 @@
| 🔴 R2 | **联动检算**:每个投值点附 β 带逐 u 检算行(u=1/2/3),破带不擅调、呈报 | 投值 commit 随附检算 |
| 🔴 R3 | **先推算后重跑**:所有读数先给静态推算/预期区间,批不准不动模拟器 | 读数报告含推算节 |
| 🔴 R4 | **provisional 纪律**:新投值一律 provisional 标注并归出口追认清单;摘除 provisional 须读数支撑 | 出口追认清单 |
| 🔴 R5 | **改前锚留盘禁补跑**:凡改前/改后对比,改前锚同 seed0 配对留盘,禁补跑禁覆盖 | sim-data 锚清单 |
| 🔴 R5 | **改前锚留盘禁补跑**:凡改前/改后对比,改前锚同 seed0 配对留盘,禁补跑禁覆盖。**口径调停(v1.2)**:本批合法的「改前锚」= T0 按案C 新行为新立的锚(F19:sim-data 在盘旧锚全作废、只作历史存档)——禁拿在盘旧锚充当改前配对,两节字面冲突以此为准 | sim-data 锚清单 |
## 5. 任务卡(逐卡一个 loop 轮次)
| 卡 | 内容 | 估时 | 轻闸 | 完成判据 |
|---|---|---|---|---|
| **T0** | 开工:worktree + 基线重测回填 + §2 事实表复核(重点 F1/F7/F11/F17)+ 四件欠账的静态推算稿(每件先给推算结论与建议值区间) | 0.75d | 冒烟基线 | 推算稿四件齐 + 基线回填;推算结论呈用户并**请批跑批计划**(R1/R3) |
| **T1** | 件①削弱终值:duration 终值与当量锚复算(推算 → 用户批跑批 → 投值)+ 文档四类同步 | 0.75d | 冒烟 | β 带检算行随 commit;provisional 归出口追认 |
| **T0** | 开工:worktree + 基线重测回填 + §2 事实表复核(重点 F1/F7/F11/F17/F19 + 按卡⓪/卡①出口报告重取受影响事实)+ 四件欠账的静态推算稿(每件先给推算结论与建议值区间;**件①含 β 约束下的 magnitude 可行子区间推算**——[60,85] 带有效性复核,v1.2 补)+ 对拍锚按案C 新序重推导(F19) | 1.0d | 冒烟基线 | 推算稿五件齐(含对拍锚按案C 新序重推导+可行子区间)+ 基线回填;推算结论呈用户并**请批跑批计划**(R1/R3) |
| **T1** | 件①削弱终值:duration 终值与当量锚复算(推算 → 用户批跑批 → 投值;**投值值非 65 时同步刷新 `tools/clear_dominance_audit.py` WEAKEN_PCT 常量**,v1.2 补)+ 文档四类同步 | 0.75d | 冒烟 | β 带检算行随 commit;工具常量同步或值=65 的说明随 commit;provisional 归出口追认 |
| **T2** | 件②数值点评五条逐条裁决呈报(每条:维持/调整 + 依据;调整项推算先行) | 0.75d | 冒烟(动值轮) | 五条全有结论落文(难度曲线与Boss.md 或对应正主文档 + 06 状态行) |
| **T3** | 件③联动欠账:钥石产出重标(F7 读数推算 + 现行产出结构对账)+ 通关率带重扫(F8,须用户批跑批) | 1.0d | 冒烟 | ①②两条 06 状态行收口;重扫读数落报告 |
| **T4** | 件④定价剩余面:柜台定价数字终值 + Boss 两档终值(推算 → 批跑 → 投值)+ 06 文本滞后句刷新(F11) | 0.75d | 冒烟 | meta.tres 终值落 + 四类同步 |
| **T5** | 读数义务两件:T6 MC 四带复算 + T7 技能池节奏重测(用户批准后发起,可与其他卡窗口期并行等结果) | 0.75d | — | 两份读数报告落 design/qa/;S2 越带按呈报口径处理 |
| **T3** | 件③联动欠账:钥石产出重标(F7 读数推算 + 现行产出结构对账)+ 通关率带重扫(F8——**与 T5 的 T6 四带复算并账,一次跑批双认账,v1.2**;须用户批跑批) | 1.0d | 冒烟 | ①②两条 06 状态行收口;重扫读数落报告 |
| **T4** | 件④定价剩余面:柜台定价数字终值 + Boss 两档终值(推算 → 批跑 → 投值)+ 06 文本滞后句刷新(F11,**两句全刷**——base 句+Boss 两档死数字句) | 0.75d | 冒烟 | meta.tres 终值落 + 四类同步 |
| **T5** | 读数义务两件:T6 MC 四带复算(案C 新行为首采——旧锚全作废,新锚自本批立,F19;**与 T3 重扫并账同一次跑批**)+ T7 技能池节奏重测(用户批准后发起,判读带先按 F16 换代复核;可与其他卡窗口期并行等结果) | 0.75d | — | 两份读数报告落 design/qa/;S2 越带按呈报口径处理 |
| **T6** | damage_probe A1 修复:归因(fresh 池 21 拍攻击链判式与判式换代后口径对账)→ 修探针或修判式换代断言 | 0.5d | damage_probe 七项 | 七项全绿;若判断言换代,换代依据落报告 |
| **T7** | 重闸 + 人闸材料:全量闸 + provisional 追认清单 + 读数报告三件打包 | 0.5d | 重闸全绿 | §1.2 判定 5 |
| **T8** | 收口五步 + 06 四条状态行收口 | 0.25d | — | 收口五步齐 |
> 估时合计 ≈ **6.0d**,显著超软时间盒 3 日上限——知情预挂:**天然切分点 = T4 末**(段一 T0-T4 四件欠账 ≈4.25d / 段二 T5-T8 读数与修复 ≈2.0d);超限即按 L3 呈报切点,不擅切。读数跑批的墙钟时间不计估时(用户批准后后台跑)。
> 估时合计 ≈ **6.25d**(v1.1 增补 +0.25d),显著超软时间盒 3 日上限——知情预挂:**天然切分点 = T4 末**(段一 T0-T4 四件欠账 ≈**4.25d**——v1.2 算术勘误:1.0+0.75+0.75+1.0+0.75=4.25,v1.0/v1.1 写 4.5 系加总错误且已传播进 roadmap,同批修正 / 段二 T5-T8 读数与修复 ≈2.0d);超限即按 L3 呈报切点,不擅切。读数跑批的墙钟时间不计估时(用户批准后后台跑)。
## 6. 验证闸
@@ -123,6 +133,8 @@
### P1 · 削弱 duration 终值候选(推算后回填,起草期先呈框架)
**✅ 裁决(2026-10-06 用户令):案甲**——维持 2 场结算;magnitude 终值由 T1 当量锚复算在 [60,85] 带内落定,带由用户授权、具体值随出口 provisional 追认。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 维持 2 场结算,magnitude 在 [60,85] 内按当量锚复算终值 | 改动面最小;续时语义下 2 场已覆盖大多数战斗长度 |
@@ -133,6 +145,8 @@
### P2 · 数值点评①②的「不对称是否有意」裁决方向
**✅ 裁决(2026-10-06 用户令):案甲**——承认不对称有意(奖励厚于惩罚),落文为设计立场,零数值改动。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 承认不对称是有意(奖励厚于惩罚),落文为设计立场 | 与「奖励驱动挖掘」的现行体验方向一致;零数值改动 |
@@ -141,14 +155,18 @@
### P3 · 钥石产出重标的终值方向
**✅ 改裁(2026-10-06 二裁,用户令,Q4 甲):维持案甲方向、转正时点顺延**——首杀 3/3/3 · 复杀 2/2/3 维持、摘 provisional 的时点改为 **T3/T5 重扫读数到账且带内后随出口追认**。改裁依据:一裁的支撑读数「迭代 10 四代锚钥石 1.38/3.01」出自 F19 宣告全数作废的旧行为锚(且先于收窄批一层),按本批自家契约 R4「摘除 provisional 须读数支撑」,该依据在重扫读数到账前不成立;且 per-run 钥石收入=通关率×掉落值,案C 后通关率预期上行(F20),产出账须按新行为读数重验。**零改动落码不变,变的只是摘 provisional 的合法时点。**
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 维持首杀 3/3/3 · 复杀 2/2/3 转正 | 现行读数(迭代 10 四代锚钥石 1.38/3.01)未显示失衡;零改动 |
| 甲 | 维持首杀 3/3/3 · 复杀 2/2/3,转正顺延至重扫读数到账且带内(二裁生效) | 零改动;读数支撑面按 R4 合法补齐 |
| 乙 | 按定价终值(P4 联动)倒推产出重锚 | 产出与定价同账收口最彻底;代价是定价未定前产出无法先定,两裁点强耦合 |
| 丙 | 精英掉落行实装并纳入产出账 | 淘汰候选:精英属 P2 内容承载(06 已裁不设精英编码位),本批不引新内容轴 |
### P4 · 工坊六件是否立钥石直购价
**✅ 裁决(2026-10-06 用户令):案甲**——维持总通关次数阈值单一渠道,不立直购价。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 维持总通关次数阈值单一渠道,不立直购价 | 门槛语义清晰(玩得多自然解锁);零新定价面 |
@@ -186,5 +204,16 @@
4. design/gdd/systems/排雷循环/行动经济.md F1 条款3 v0.8(判式换代后现行口径)
5. design/gdd/07-体验验证清单.md「验收读数重测义务」节(T6/T7 挂单原文)
6. design/qa/m4iter14-mineq-exit-report-2026-10-05.md §四.7(damage_probe A1 改前既有红的在册登记)
7. design/qa/m4iter14-narrow 相关读数与 design/qa/m3-iter10-clear-rate-readings-2026-10-01.md(重扫基线)
7. design/qa/m4iter14-narrow 相关读数与 design/qa/m3-iter10-clear-rate-readings-2026-10-01.md(重扫基线——仅历史参照,锚已随 F19 作废)
8. 06-待办清单「旧行为 MC 行为锚全数作废——重锚归数值批」条(2026-10-06 登记——F19 正主)
9. game/core/battle_orchestrator.gd 暂存闸 `_defer_board_damage`/`_deferred_board`(案C 实现载体——T6 读数判读前须读案C 批提交 58dfb56 diff)
10. tools/clear_dominance_audit.py(β 带/当量锚复算常设工具,:51 WEAKEN_PCT 硬编码——F4b/T1 同步义务载体,v1.2 补)
```
## 11. 版本记录
| 版本 | 日期 | 记 |
|---|---|---|
| v1.0 | 2026-10-05 | 初稿定稿(四件欠账+两件读数+damage_probe A1 顺路修;P1-P4 拍板点框架) |
| v1.1 | 2026-10-06 | **案C 增补**:§2.6 三事实(F18 行为换代/F19 锚全作废/F20 难度走向预判);T0 推算稿四件→五件(+对拍锚按新序重推导,估时 0.75→1.0d,合计 6.0→6.25d);T5 读数卡 T6 项注明案C 新行为首采立新锚;基线纪律注换代(783/0+17 套全绿);§10 留痕 +3 条。增补动因=案C 地图伤害账殿后批(git 7ef18ac)换代结算行为序,06 2026-10-06 条登记重锚义务归本批 |
| v1.2 | 2026-10-06 | **五任务书联审修订**:P3 转正顺延至重扫读数后(一裁依据系 F19 作废锚);F3 带有效性复核+F4b 检算工具(clear_dominance_audit.py WEAKEN_PCT)入留痕与 T1 判据;F11 补 Boss 两档死数字、T4 两句全刷;F15 与 F8 并账一次跑批双认账;F16 判读带案C 换代复核;§3 交叠声明(卡⓪/卡①同管线);R5 与 F19 调停(改前锚=本批新立案C 锚);run_all 十五→十七;估时段一 4.5→4.25d 算术勘误(roadmap 同步)。裁决 Q4 甲随批落文 |
@@ -0,0 +1,171 @@
# 任务书-内容数据驱动扩展批(迭代 17 卡⓪)-2026-10-06
状态:任务书 v1.1(**全部裁决已落、零待裁点**,开工门=U0 用户发令)。设计权威=调研报告 [研究-内容数据驱动扩展架构-2026-10-06](研究-内容数据驱动扩展架构-2026-10-06.md)+本会话盘问裁决实录(台账 370)。
排期:**迭代 17 头卡(2026-10-06 用户令插队)**,迭代 17 现=卡⓪①③④四卡(M4 数值批已移迭代 18,roadmap 现行口径)。
**v1.1 修订记录(2026-10-06 五任务书联审,用户裁决 Q2 甲/Q6/Q7 + 事实勘误)**:①效果类型闭集扩两型(`damage_mult` 伤害倍率修正、`open_ticket` 新建伤害单)——nest_counter/flag_burst/war_banner 三处现状行为原词汇表装不下;②事件词汇补 `charge_full`(charge 满层沿);③pick_refresh 改走主动件分发通道不入事件订阅;④level_clear 归登记不实施(用户裁 Q6,§3.1 起草越界已删);⑤对拍判据两套口径落文(Q7,正主读数档升格为引用件);⑥计数勘误(事件/效果类型/消费点三处);⑦映射表五处语义修正(luck_coin 归属、deep_drill 降级、armory_prep 转移、boss 血量阈值事件改名通用化、first_dig fact 改每战口径);⑧断言面随迁与订阅重建时机补列。
---
## 一、迭代目标与完成定义
把「内容的效果行为」从散布在结算代码里的硬编码分支,搬进内容数据行的三个字段——**订阅哪个事件(on)/ 什么条件(when)/ 什么效果(do)**——由一个通用解释器(EffectEngine)统一执行。完成后:加一件「已有效果类型」的新专长/新秘宝=只改 `.tres` 数据行,零代码。
**完成定义**:①旧 23 挂点枚举删除,27 行专长数据全部迁为事件订阅形态且行为等价(对拍判据两套,见 §六 T6 与 §八);②六件按 id 硬编码的被动秘宝迁毕、按 id 特判清零;③文案表值化(效果说明进数据行);④一个迭代内完成、一次合并登记。
## 二、裁决实录(2026-10-06 用户逐条裁定,全数有效)
| # | 裁决 | 内容 |
|---|---|---|
| R1 | 架构模型 | 发布订阅:结算管线同步 emit 事件(无队列无异步,确定性优先)→ EffectEngine 遍历持有集匹配订阅 → 执行数据行里声明的效果。**不是**代码级插件/监听器类——订阅关系本身是配置 |
| R2 | 拦截能力 | 不做通用拦截器链;只保留**改写窗口**(伤害单据 open_ticket 后、submit 前,modify 类效果收集后单点按声明序施加)。断链/否决能力不建,将来需要时加 veto 位。**窗口归属澄清(v1.1)**:armor_roll_rewrite / roll_discount 的现行消费点在护甲掷骰与克制判定的判定点内部,不在 open→submit 单点窗口——它们随各自事件(armor_roll / clamp_check)在判定点就地按声明序施加;modify_ticket 的「单点窗口」仅指 attack_commit 系单据 |
| R3 | 多订阅与冲突 | 一事件多订阅=常态(持有集即订阅集);冲突在**效果类型层用组合规则封死**(见 §四),内容行只能选类型不能自定义合并行为。遍历顺序=数据表声明序,写死保种子复放 |
| R4 | 旧挂点处置 | 23 个 hook 枚举**删除**(概念消亡:事件名+效果类型取代);其中 first_dig_spell、terrain_dig_double 退化为纯条件行;dig_count_segments 与 round_dig_bonus 保留为**两件独立内容**(效果类型不同:攻击分段 vs 攻击加值),订阅同事件 |
| R5 | 范围判据 | **现有实现全部改造**(含 luck_coin 偏运硬币→reward_roll 事件、文案硬编码、令牌 match、树规则键);**06 在册待办只登记不实施**(curio_roll/shop_purchase/gp_settle/level_clear 四事件只登记事件名与发射点设计,哪个 06 内容开工时随批加) |
| R6 | 框架先行 | round_start / enemy_hp_threshold / treasure_used 等发射点一律埋进本批,不论当前有无订阅者 |
| R7 | 交付形态 | **一个迭代完成**,按模块垂直切需求卡(框架/专长/秘宝/令牌树),不分批不分迭代、批末一次合并 |
| R8 | 术语纪律 | 事件=`.on("xxx")` 的 "xxx";订阅后逻辑=效果类型;多订阅叠加规则=组合规则。禁用「挂点/hook/合并律/挂账」等自造词(存量文档随 T7 换代) |
## 三、事件词汇表(定稿:实施 16,登记暂不做 4)
### 3.1 本批实施(16 个发射点)
| 事件名 | 发布时机(发射点,现有代码位置) | 载荷要点 |
|---|---|---|
| `dig_reveal` | 安全开格结算完成(battle_orchestrator 挖格段) | cell、round、is_first_dig_of_battle、terrain_kind |
| `dig_paid` | 付费开掘发起、动作经济闸收对价前 | cell、ap_cost、ap_surplus |
| `flag_hit` | 标中雷兑付时 | cell、round、adjacent_terrain |
| `mine_hit` | 踩雷时(含计数清零语义面) | cell、round、damage |
| `attack_commit` | 我方伤害单据开立(damage_controller.open_ticket 入口) | atk、target、matchup、feats_ctx |
| `clamp_check` | 克制关系判定修正点 | matchup(magic_vs_magic/magic_vs_heavy/pierce_vs_light/…) |
| `armor_roll` | 敌护甲掷骰判定 | target_ac、roll |
| `kill` | 敌人死亡确认 | target、overflow余量 |
| `damage_taken` | 我方受到伤害(kind ∈ {enemy_skill, terrain};雷伤走 mine_hit 不重复发) | kind、amount、source |
| `enemy_hp_threshold` | 敌人血量跌破其 unlock_hp_pct 阈值(unit_container.check_skill_unlocks 同点,开轮摇号前;**对所有带该字段的敌人逐个发射,非 Boss 专属**——Boss 语义留给订阅者 when 判定) | unit、pct、is_boss |
| `round_start` | 每轮开始 | round |
| `flag_settle` | 轮末旗伤结算(轮末序:旗伤开单→AP结转→积层反打,顺序显式在发射代码) | flags_hit_all、flags_count |
| `round_end` | 每轮结算收口 | round |
| `reward_roll` | 格面资源掷定(摇号前权重合成层,luck_coin 迁移落点) | cell、polarity、weights |
| `treasure_used` | 使用主动秘宝(use_treasure 受理面) | item_id、target |
| `charge_full` | charge 积层到达上限的沿(patient_burst 触发点,v1.1 补入) | unit、layers |
| (`curio_roll` 邻位)三选一候选生成现有钩位仅供**对拍观测**,不改发布面(观测行不计入发射点数) | —— | —— |
### 3.2 登记暂不做(4 个,发射点设计一行,随对应 06 内容批实施;R5 裁决 + Q6 裁决)
`curio_roll`(三选一候选生成时发布→服务「战利品鉴定」)/ `shop_purchase`(商店成交时发布→服务「符文重铸」)/ `gp_settle`(金币结算入账时发布→服务「贪婪契约」)/ `level_clear`(一张图清空兑付时发布,载荷含 round 与清图统计→服务后续内容批;**本批不写发射代码**——Q6 裁决:R5 原文有效,v1.0 §3.1 的实施行系起草越界,已删)。四者均系 06 在册内容件的前置,本批只在本文登记。
### 3.3 效果类型词汇表(定稿:19 行 23 个,解释器 switch 闭集;v1.0 计数「16」系勘误,v1.1 扩 `damage_mult`/`open_ticket` 两型)
| 效果类型 | 语义 | 收编的现状 |
|---|---|---|
| `add_ticket_rider` | 单据追加固定伤 | hero_attack_rider、venom_edge |
| `modify_ticket` | 改写单据数值(改写窗口,按序施加;窗口归属见 R2 澄清) | clamp_modifier×3、roll_discount、nest_aura、hit_trade、armor_roll_rewrite |
| `damage_mult` | **伤害倍率修正(v1.1 新增)**:对指定来向伤害乘系数(乘法族,正负分桶) | nest_counter 的踩雷减半面(mine_hit_halve) |
| `open_ticket` | **新建一张伤害单(v1.1 新增)**:从事件现场按通道开新单(attack/board_blast 等),与 add_ticket_rider(向已有单追加)相区分 | flag_burst 爆板(open_ticket(KIND_BOARD_BLAST))、war_banner 战旗轮末自开单 |
| `attack_bonus` | 攻击力加值 | round_dig_bonus |
| `attack_segments` | 攻击拆多段 | dig_count_segments(连珠矢) |
| `yield_mult` | 开格产出乘区(正负分桶) | dig_yield_mult×3、terrain_dig_double(条件行) |
| `spawn_spell` | 生成一次必中魔法矢 | first_dig_spell(条件行) |
| `overflow` | 击杀溢出弹射 | kill_overflow |
| `grant_material` | 掉落格面资源 | flag_resource、terrain_refund |
| `grant_ap` | 给行动点。**转移形态声明(v1.1)**:`mode:"transfer"`=轮末剩余 AP 转蓄力层(上限 3)**替代** RAP 转存并作废 cleared 口径——是转移非加法,不入加法族、按序单独施加 | ap_carry |
| `grant_gp` / `bias_wallet` | 金币面(**本批无现状收编,预留型**;luck_coin 实际归 bias_rewards,见下行——v1.1 勘误) | —— |
| `shield` | 减伤层 | charge_shield |
| `spike` | 满层反打 | charge_spike(触发事件=charge_full) |
| `apply_status` | 授予状态(复用 status_effects.tres 词汇) | heavy_debuff |
| `counter_add` / `counter_spend` | 计数器增减(重置点数据声明:round_start/round_end/level) | round_dig 计数、variant_counter、dig_charge 积点(nest_counter 移出本行——其真身是减半+反打,见 damage_mult/open_ticket 两型,v1.1 勘误) |
| `rewrite_board` | 改写棋盘格状态 | flag_neutralize |
| `reveal_tiles` / `remove_mines` / `refresh_pick` | 显影/移除/刷新(**主动件 kind 分发通道**,不经事件订阅——刷新是玩家主动动作,v1.1 澄清) | mine_reveal、cell_removal、pick_refresh |
| `bias_rewards` / `preview` | 抽取面 | reward_weight_bias(=luck_coin 现行 effect_kinds,经 reward_roll)、bonus_refresh |
### 3.4 组合规则(6 条,效果类型的必填属性,解释器内置)
| 规则 | 语义 | 适用 |
|---|---|---|
| 加法族 | 数值相加(可交换,顺序无关) | add_ticket_rider、attack_bonus、grant_material、grant_ap(非 transfer)、counter_add、shield |
| 乘法族 | 收集后一次施加(正负分桶) | yield_mult、damage_mult |
| 任意真族 | 任一命中即生效 | spawn_spell、overflow、spike |
| 按序改写族 | 收集→单点按声明序施加 | modify_ticket 及一切改写窗口效果 |
| 按序消耗族 | 按订阅序消耗共享资源,耗尽即止、拒绝走 reason 通道;**可选声明 `fallback`**(v1.1):资源不足时改付声明的基础对价(deep_drill 降级面——AP 富余付全价积计数、不足只付常规基础 1) | counter_spend |
| 即时执行族 | 每条命中订阅各自执行一次,天然可叠加、执行序=声明序 | open_ticket、grant_ap(mode:transfer) |
## 四、数据行目标形态与 schema
```
# feats.tres 一行(示例:奥术余烬 + 魔网织者)
{feat_id:"arcane_ember", rarity:"common", archetype:"magic",
desc:"普攻命中后追加 1 点必中魔法伤",
triggers:[
{on:"attack_commit", do:{kind:"add_ticket_rider", value:1, dtype:"magic"}} ]}
{feat_id:"mana_weaver", rarity:"rare", archetype:"magic",
triggers:[
{on:"clamp_check", when:[{fact:"matchup", op:"eq", value:"magic_vs_magic"}],
do:{kind:"modify_ticket", delta:-1}} ]}
```
- schema 校验照旧封闭且保留全部现有护栏:`on` ∈ 事件词汇、`do.kind` ∈ 效果词汇、`when.fact` ∈ fact 表、行键白名单、悬空引用加载致命、零裸 flat 禁令、流派扫雷触发点铁律(MINE_HOOKS 改为「每流派 ≥1 行订阅扫雷侧事件」同义校验)。
- **存档零改动**:持有集/装备存 id 不变,换的只是解释方式——纯重构可对拍的前提。
- fact 表(条件词汇,**封闭枚举 9 项**,v1.0「~15 等」开放写法系勘误):`matchup`、`is_first_dig_of_battle`(**现行口径=每战首次开格**,begin_battle 归零——v1.0 的 `is_first_dig_of_level` 与现行语义相反,已随 provisional 定案改正)、`terrain_kind`、`target_armor_class`、`flags_count`、`charge_layers`、`nest_count`、`round_index`、`counter`(按 counter_id 取值)。T2 落码时若发现 9 项装不下现状条件,属闭集缺口——停机呈报补表,禁在行内私开 fact。
## 五、23 挂点逐行移植映射表(等价性对拍底单)
| 旧 hook | 持有内容(feats.tres 实据) | 新形态 |
|---|---|---|
| hero_attack_rider | arcane_ember | on:attack_commit → add_ticket_rider |
| clamp_modifier | mana_weaver / azure_oath / hunter_rapier(穿刺) | on:clamp_check + when(matchup) → modify_ticket |
| first_dig_spell | mana_resonance | on:dig_reveal + when(is_first_dig_of_battle) → spawn_spell |
| kill_overflow | pierce_shot | on:kill → overflow |
| dig_count_segments | chain_arrows | on:dig_reveal→counter_add;on:attack_commit→attack_segments |
| roll_discount | weak_instinct | on:clamp_check → modify_ticket(档位移) |
| round_dig_bonus | miner_stubborn | on:dig_reveal→counter_add;on:mine_hit→counter 清零;on:attack_commit→attack_bonus |
| hit_trade | miner_hammer | on:attack_commit → modify_ticket(攻受交换) |
| armor_roll_rewrite | focus_mind | on:armor_roll → modify_ticket(免掷恒折扣) |
| heavy_debuff | armor_crack | on:attack_commit + when(重甲) → apply_status |
| dig_yield_mult | greedy_lantern / vein_intuition / gambler_pact | on:dig_reveal → yield_mult(乘法族) |
| deep_dig | deep_drill | on:dig_paid + when(ap 富余) → counter_spend(对价,fallback=常规基础 1);深层产出配额=counter fact 条件(cap=4) |
| flag_resource | mine_atlas | on:flag_hit → grant_material |
| nest_aura | nest_hunter | on:attack_commit + fact(nest_count) → modify_ticket |
| flag_all_hit | perfect_defense | on:flag_settle + when(全中) → yield_mult(旗伤乘区) |
| flag_strike | war_banner | on:flag_settle → open_ticket(attack 通道)(v1.1 改:战旗是自开单,非向已有单追加) |
| ap_carry | armory_prep | on:round_end → grant_ap(mode:transfer)(转蓄力层上限 3、替代 RAP 转存——转移非加法,v1.1 改) |
| charge_shield | iron_wall | on:damage_taken + fact(charge_layers) → shield |
| charge_spike | patient_burst | on:charge_full(满层沿)→ spike(v1.1 改:charge 事件原不在词汇表,已补入) |
| terrain_refund | ley_harvest | on:damage_taken(kind=terrain) → grant_material |
| terrain_dig_double | thorn_weaver | on:dig_reveal + when(伤害型地形) → yield_mult(×2) |
| flag_neutralize | purge_sapper | on:flag_hit + when(邻伤害地形) → rewrite_board |
| variant_counter | magma_body | on:damage_taken→counter_add;on:round_end→counter_spend 反打 |
秘宝侧六件:venom_edge(attack_commit→add_ticket_rider)、luck_coin(reward_roll→**bias_rewards**,现行 effect_kinds=reward_weight_bias;v1.1 勘误:原误归 bias_wallet)、dawn_order(round_start→grant_ap 队列)、dig_charge(dig_reveal→counter_add + dig_paid→counter_spend)、nest_counter(mine_hit→damage_mult(0.5) 减半 + open_ticket(reflect 通道) 反打——v1.1 改:原 counter_add 归类与现状不符,现实现无计数器)、flag_burst(flag_hit→open_ticket(board_blast));pick_refresh(**主动件 kind 分发→refresh_pick,不经事件订阅**)。
## 六、任务卡(T0-T7 ≈4.5d,软时间盒超限 L3 呈报切点)
| 卡 | 内容 | 估时 |
|---|---|---|
| T0 | 开工三查:worktree+基线复读(冒烟/探针/run_all/MC 对拍锚)+git status 归属核对(在飞 mapdmg/standee/uialign 只标旗不碰) | 0.25d |
| T1 | EffectEngine 框架:事件枚举+发射点 16 处埋点+订阅装载(**重建时机(v1.1 补)=每战 begin_battle 从持有集/装备集重建 trigger 列表**——冒险中途获得/换取的专长下一战生效,同战内不热载,确定性优先)+组合规则+改写窗口+计数器账本+确定性声明序 | 1.0d |
| T2 | 词汇表落码:schema 换代(feats/treasure 两表 trigger 形态+校验规则换代+fact 表)+护栏迁移(MINE_HOOKS 同义校验等) | 0.5d |
| T3 | 专长迁移:27 行数据改写(§五映射表逐行)+旧枚举删除+_feat_flags_for 退役+消费点拆除(**口径=研究文档的 23 个消费点,v1.0「24 处」系勘误;执行时逐处 grep 清点对账**)+文案入表(battle_narrator.gd:142 一处;v1.0「两处」系与 T4 重复计数)+**断言面随迁(v1.1 补)**:smoke_all 直呼断言(含「27 件」计数断言与 _feat_flags_for/HOOKS 直呼)与 damage_math_test 6 处 hook 引用同步改写,不列修断言工作项即开工=必红 | 1.25d |
| T4 | 秘宝迁移:六件被动+dig_charge 特判+主动件 kind 分发合流+luck_coin 经 reward_roll+curio_interact_controller 文案入表 | 0.75d |
| T5 | 令牌/树收尾:_apply_curio_pick match 收敛进效果类型+meta_tree 规则键走同面 | 0.5d |
| T6 | 回归闸(**对拍判据两套,v1.1 落文(Q7 裁决)**:①确定性复放与冒烟断言=**逐位一致**;②MC 统计量(通关率/画像)=**成型画像同带**——统计量无「逐位」可言,禁混用。锚口径正主=`design/qa/m4iter12-t7-batch1-readings-2026-10-04.md`(runsum 锚、seed0=90000、N=20、off/formed 配对、L1 通关率判读带),T0 按该口径自采 pre 锚留盘、T6 采 post 锚配对)+冒烟+run_all+探针+确定性复放 | 0.5d |
| T7 | 文档正主换代+出口报告:奇物.md/秘宝.md/敌人系统.md 词汇换代+registry 条目+06 状态收口+退出人闸材料包 | 0.25d |
## 七、契约红线(🔴 违反即停机呈报)
1. **存档零破坏**:存档键/存档格式/断点结构一字不改;换的只是运行时解释方式。
2. **数值等价**:迁移前后行为等价——判据两套(T6/v1.1):确定性复放与冒烟断言逐位一致;MC 统计量同带(m4iter12 口径)。发现必要偏差(如旧实现 bug 被顺带修正)必须停机呈报,禁静默吸收。
3. **确定性**:全同步调用、无队列无异步无 signal 时序依赖;遍历序=数据声明序。
4. **护栏保留**:封闭枚举校验/键白名单/悬空引用致命/零裸 flat 禁令/流派扫雷触发铁律全部以新形态延续,禁以「数据驱动」名义放开任何护栏。
5. **battle_orchestrator 历史脏件**:全程 worktree 批、主区禁直改;并行在飞三线(mapdmg/standee/uialign)只标旗不碰,T0 重取基线。
## 八、停机点与验证闸
- **S1**(T3 段末):首个流派(魔法流)迁移完跑对拍——若确定性复放非逐位一致且定位超出映射表误差,停机呈报。
- **S2**(T6):确定性复放不一致/成型画像越带/冒烟红——任一命中停机,禁带病合并。
- 验证闸:冒烟全量+run_all 全套+五探针+MC 对拍+确定性复放(同种子两次逐位一致)。
- 代拍板白名单:事件载荷字段命名、fact 表个别查询面落法、smoke 断言数漂移追认、发射点微调(±1 处)。
- 呈报不停机级:文案措辞、注释层、台账撞号顺延。
## 九、范围边界(明确不做)
- 4 个登记事件不实施(§3.2);外挂脚本层(调研案丙)不做;luck_coin 之外的数值重调不做(归 M4 数值批);relic/feat 存档键更名不做(06 在册命名统一条,存档键铁律);main.gd:475 疑似缺陷不随批(06 在册独立 mini-loop 待令)。
@@ -1,8 +1,9 @@
# 任务书:敌人表行集多行批(v1.0 定稿,待发令开工)
# 任务书:敌人表行集多行批(v1.1 定稿,零待裁点,开工门=U0 用户发令)
> 成文 2026-10-05。**性质**:数据表校验与生成机制放开 + 配套呈现适配,允许同一场遭遇混编多种敌人。
> 成文 2026-10-05,v1.1 修订 2026-10-06(五任务书联审:P3 改裁丙撤投放、P1 补遭遇骰机制与实例总数语义、F2/F5/F7 事实勘误、套件数与头注换代、expect_pools 与行序契约补列)。
> **性质**:数据表校验与生成机制放开 + 配套呈现适配,允许同一场遭遇混编多种敌人。
> 事实源 = [06-待办清单](../gdd/06-待办清单.md)「同深度第二敌种与精英 / Boss 编码位」条剩余面(该条前半「同层多遭遇」已由关卡节点地图 v1.0 节点编号升级消解,剩余即本卡);设计权威 = [敌人系统](../gdd/systems/战斗循环/敌人系统.md) v0.13(技能池执行批已落籍,Boss 半血解锁技已入表)。
> 归属迭代:**迭代 17 · 卡①**(迭代 17 四卡:①本批 ②M4 数值批 ③暂停层只读入口批 ④生涯界面设计立项)。
> 归属迭代:**迭代 17 · 卡①**(迭代 17 现=卡⓪数据驱动扩展批+①本批+③暂停层只读入口批+④生涯界面设计立项;M4 数值批已移迭代 18,roadmap 现行口径)。
> 满足 loop engineering 八件(见 §9 逐条对照)。
> 开工门:**已解**——前置「技能池实施批落地」已于 2026-10-05 完成(技能池执行批合并进 master,提交 d3fa887,冒烟 772/0)。
@@ -21,7 +22,7 @@
| 1 | 校验放开 | 敌人表同一行集配两种以上敌人不再触发加载期致命错误;新的行集构成纪律(§5 R2 的具体条款,先随 P1/P4 裁决落文再落码)由加载期校验兜底 |
| 2 | 生成链接通 | 混编行集开战后,各敌种按裁决后的数量语义(P1)实例化上场,各自实例池独立摇号;固定顺位、死亡顺延、范围效果全体现行语义不破 |
| 3 | 零内容期零漂移 | 在未投放任何混编行的表状态下,MC 与冒烟数值断言对基线**逐位一致**(机制放开但表内容不变 = 行为必须不变) |
| 4 | 重闸全绿 | 冒烟全量(基线数字 T0 重测回填,禁止沿用本文历史数字)· run_all 十五套件 · 场景探针(触呈现加 ui_struct_probe / ui_click_probe / ui_layout_probe)· doc 三闸对基线零新增 · 熵增闸 PASS |
| 4 | 重闸全绿 | 冒烟全量(基线数字 T0 重测回填,禁止沿用本文历史数字)· run_all 十七套件 · 场景探针(触呈现加 ui_struct_probe / ui_click_probe / ui_layout_probe)· doc 三闸对基线零新增 · 熵增闸 PASS |
| 5 | 人闸完成 | 混编遭遇实机目检清单过(若在 P3 裁「本批投放首个混编行」)+ 代拍板追认清单过;收口五步齐 |
> ⚠️ **基线纪律**:本任务书起草时 master 头 = 413c936(ui-struct-probe mini-loop 合并后),冒烟基线 772/0。开工 T0 必须重测基线取实际值回填,禁止把本文数字当闸门。
@@ -31,12 +32,12 @@
| # | 事实 | 读数 |
|---|---|---|
| F1 | 「每行集恰一敌种」校验位置 | `game/data/schemas/enemy_table.gd:108-112`——按 `(level_index, node_depth)` 聚合,行集内出现第二个 `enemy_id` 即报 `rowset_rule` 类错误,加载期致命中止 |
| F2 | 行集解析双算法共存 | ①`EnemyTable.resolve_rowset`(`enemy_table.gd:121-132`)= **floor 语义**(取 ≤ 请求坐标的最近行),仅 `smoke_all.gd:3383/3385/3415/3418` 四处使用;②`ConfigDbResolver.resolve_enemy_rowset`(`config_db_resolver.gd:33-34` → `_resolve_progress`)= **ceil 语义**(向上取整保证偏难,2026-09-18 拍板),是全部生产消费面入口。两函数都**只返回单行** |
| F2 | 行集解析双算法共存 | ①`EnemyTable.resolve_rowset`(`enemy_table.gd:121-132`)= **floor 语义**(取 ≤ 请求坐标的最近行),仅 `smoke_all.gd:3452/3454/3484/3487` 四处使用(v1.0 行号 3383/3385/3415/3418 系起草后漂移,2026-10-06 复核);②`ConfigDbResolver.resolve_enemy_rowset`(`config_db_resolver.gd:33-34` → `_resolve_progress`)= **ceil 语义**(向上取整保证偏难,2026-09-18 拍板),是全部生产消费面入口。两函数都**只返回单行** |
| F3 | 双算法处置是既有待裁项 | 工作日志 312(2026-10-02 代码质量修复批)呈报的七拍板点之一「enemy_table.resolve_rowset 双算法」至今未裁——本批动行集解析必然擦到这条,列入 §8 待裁点 P2 |
| F4 | 生成消费点 | `unit_container.gd:47` `spawn()` 取单行后按 `unit_count`(或遭遇骰传入的数量)生成 count 个**同种**实例;数量域常量 `EnemyTable.UNIT_COUNT_MIN/MAX = [1,3]`,表校验与 spawn 守卫共用(`enemy_table.gd:18-21`) |
| F5 | 其余消费点 | `battle_orchestrator.gd:220`(战前预取行 erow_pre)· `battle_narrator.gd:75`(叙述取敌种)· `smoke/skill_rhythm_probe.gd:17` · `smoke/damage_probe.gd:270/421` · `smoke_all.gd` 十余处 · `tests/unit/data_config/config_db_test.gd:59-61`(双表精确行契约断言) |
| F5 | 其余消费点 | `battle_orchestrator.gd:225`(战前预取行 erow_pre;v1.0 写 220 系漂移,2026-10-06 复核)· `battle_narrator.gd:75`(叙述取敌种)· `smoke/skill_rhythm_probe.gd:17` · `smoke/damage_probe.gd:270/421` · `smoke_all.gd` 十余处 · `tests/unit/data_config/config_db_test.gd:59-61`(双表精确行契约断言) |
| F6 | GDD 侧结构冻结 | 敌人系统.md 规则表「每个坐标只出一种敌种」(:75)+ 结构冻结条款含「每坐标恰一敌种」(:263)——属**结构冻结面**,修订须先走 GDD 修订流程落文再落码,禁止码先文后 |
| F7 | 表内容现状 | `enemy.tres` 共 21 行、8 敌种(地精/熊地精/食人魔酋长/巨蜘蛛/蛛化卓尔精灵/灰矮人/钩爪恐魔/灰矮人石君王),现行每行集恰一行 |
| F7 | 表内容现状 | `enemy.tres` 共 **19 行、9 敌种**(地精/熊地精/霍布地精/食人魔酋长/巨蜘蛛/蛛化卓尔精灵/灰矮人/钩爪恐魔/灰矮人石君王;v1.0 写「21 行 8 敌种」系事实错误,漏霍布地精,2026-10-06 复核 `grep -c '"enemy_id"'`=19,冒烟断言文案自证「十九行」),现行每行集恰一行 |
| F8 | 遭遇骰与数量骰 | 数量区间(`unit_count`/`unit_count_max`)由战斗结算遭遇骰同流在 spawn 期掷定一次传入确定值(敌人系统零随机纪律——本系统只收确定结果);攻击区间同理。混编不改这条纪律 |
| F9 | 难度修饰 | `resolve_difficulty_modifiers` 按 (L,D) 精确匹配返回 hp_mult/atk_mult,施加于行值快照之前(`unit_container.gd:61-63`)——混编后该修饰**对行集内全部敌种同乘**,不改变异 |
| F10 | 范围效果语义 | 敌人系统.md:75「敌方效果对全体生效」规则的前提是「场上敌人全同种,范围效果作用于所有存活敌人是天然兼容的默认」——混编后「全体存活敌人共享」的结算语义**不需要改**(效果本就按存活单位逐一生效),但 GDD 该句前提描述须随批修订 |
@@ -66,14 +67,14 @@
| 文件 | 改动 |
|---|---|
| `unit_container.gd` | `spawn()` 改受理行集:逐行按各自数量语义实例化,行主序生成序保持(`default_target` 固定顺位语义自然兼容);实例池快照逐行独立(现行逐实例快照逻辑天然兼容);数量域守卫改为行集级(上限随 P1) |
| `battle_orchestrator.gd:220` | 战前预取改行集形态 |
| `battle_orchestrator.gd:225` | 战前预取改行集形态 |
| `battle_narrator.gd:75` | 叙述取敌种改行集形态(混编遭遇的开战叙述口径——逐种列名还是取首种,随批定,属呈现文案) |
### 组 D · 断言与探针
| 文件 | 改动 |
|---|---|
| `smoke_all.gd` | 行集结构断言换代:「行集恰一敌种」相关断言(:2900 注释口径、L2/L3 定点行集断言 :3383-3420 等)改断言新构成纪律;「双表精确行契约」断言改「精确行集」口径;新增混编正反断言(违规构成定位到类别) |
| `smoke_all.gd` | 行集结构断言换代:「行集恰一敌种」相关断言(:2900 注释口径、L2/L3 定点行集断言 :3452-3487 段等)改断言新构成纪律;「双表精确行契约」断言改「精确行集」口径;**expect_pools 逐坐标池模板断言(:2973-2996)换代**——现行按 `"L_D"` 键每坐标一池精确比对,同坐标第二行即红,须改 `(L,D,enemy_id)` 键口径,且「十九行池模板」等文案随 F7 换代(v1.1 补列,原漏);新增混编正反断言(违规构成定位到类别) |
| `config_db_test.gd:59-61` | 同通道断言换代 |
| `skill_rhythm_probe.gd` / `damage_probe.gd` | 取数面随行集形态适配(行为零变更期逐位一致是验收条件) |
@@ -82,10 +83,10 @@
| 禁项 | 理由 |
|---|---|
| **零混编内容期行为零漂移** | 本批的默认形态 = 机制放开 + 表内容不变。P3 若裁「本批投放首个混编行」,投放行本身属内容变更,须单独 MC 取证(先推算后重跑铁规:跑批发起前须用户批准) |
| **不改遭遇骰/数量骰随机流** | 敌人系统零随机纪律与 RNG 单点红线不变;混编的数量语义若需新摇号,必须走既有封闭流扩签并先经用户裁决(列入 P1 子项) |
| **不改遭遇骰/数量骰随机流** | 敌人系统零随机纪律与 RNG 单点红线不变;P1 已裁混编需新摇号(每行一骰),必须走既有封闭流扩签并先经用户批准(P1 裁决补充段已含此门) |
| **不改键结构与存档** | `(L,D,enemy_id)` 键、断点存档、跨局存档零触碰 |
| **不设精英/Boss 编码位** | 06 条目已裁「不设精英 / Boss 编码位」(精英 P2 内容承载),本批不重开 |
| **技能池构成纪律不动** | 每池恰一普攻、增益 ≤1、unlock_hp_pct 投放纪律(仅 Boss 行)原样 |
| **技能池构成纪律不动** | 每池恰一普攻、增益 ≤1、unlock_hp_pct 投放纪律(仅 Boss 行)原样。**知悉(v1.1)**:「原样」实为无硬闸——`enemy_table.gd:94-95` 注释明写纪律系文档登记非校验;P4 乙放开 Boss 多行后,「Boss 行带 unlock_hp_pct 可静默过校验」的无闸面随之扩大,后续内容批投放 Boss 多行时须逐行人工复核此面 |
| **数值零触碰** | hp/atk/unit_count/权重行值一律不动(P3 投新行除外,且新行行值 provisional 归调参) |
## 5. 设计契约(🔴 触碰 = L3 停机)
@@ -97,6 +98,7 @@
| 🔴 R3 | **fail-fast 语义保持**:行集构成违例仍加载期致命中止,错误类别可定位;禁软回退 | 组 D 正反断言 |
| 🔴 R4 | **RNG 单点**:不新增 `randomize()`/自建随机源;如需新摇号点一律经 RngService 封闭流并先报批 | 静态审查 + rng 日志比对 |
| 🔴 R5 | **双表精确行契约不破**:board_gen × enemy 同坐标覆盖义务(`smoke_all.gd:294-311`)在混编口径下仍成立 | 组 D 断言换代后全绿 |
| 🔴 R6 | **混编行文件行序纪律(v1.1 补)**:同一 (L,D) 的多行在表文件内必须相邻且行序=声明序=生成序——resolver 返回序、battle_narrator 取首行叙述、expect_pools 断言、spawn 行主序全部依赖文件行序,行序即契约 | 组 B 校验(同坐标行不相邻即报错)+ 组 D 断言 |
## 6. 任务卡(逐卡一个 loop 轮次)
@@ -106,19 +108,19 @@
| **T1** | 组 A:GDD 修订(敌人系统.md 混编口径 + 结构冻结条款 + F10 前提句 + 版本历史)+ registry + 06 状态行 | 0.5d | doc 三闸 | 三闸零新增;修订句读者测试过(只读该节能答三问) |
| **T2** | 组 B:schema 校验换代 + resolver 行集数组化(P1/P2 裁决后) | 0.75d | 冒烟 | 正反断言红绿各验;旧「恰一敌种」违例行按新纪律判定正确 |
| **T3** | 组 C:spawn 行集受理 + battle_orchestrator/narrator 适配 | 0.75d | 冒烟 + ui_struct_probe | 零内容期冒烟逐位绿 |
| **T4** | 组 D:smoke/单测/探针断言面换代 + 新增混编构成断言 | 0.5d | 冒烟 + run_all | 十五套件绿;新断言负向验证红(故意配违规行集能抓到) |
| **T5** | (条件卡,P3 裁投放才执行)首个混编遭遇行投放 + 行值 provisional 登记 | 0.5d | 冒烟 + MC(先报批) | 混编遭遇开战/结算/胜利全链断言过 |
| **T6** | 重闸:全量轻闸 + doc 三闸 + 熵增闸 + MC 逐项比对(零内容期) | 0.5d | 重闸全绿 | §1.2 判定 3/4 |
| **T4** | 组 D:smoke/单测/探针断言面换代 + 新增混编构成断言 | 0.5d | 冒烟 + run_all | 十七套件绿;新断言负向验证红(故意配违规行集能抓到) |
| **T5** | (条件卡,**P3 二裁丙=本批不触发,不执行**——投放连同 Boss 多行归后续内容批,该批开工时按本卡口径执行+MC 取证先报批+难度带读数义务) | 0.5d | — | — |
| **T6** | 重闸:全量轻闸 + doc 三闸 + 熵增闸 + MC 逐项比对(零内容期——本批唯一 MC 面;先报批) | 0.5d | 重闸全绿 | §1.2 判定 3/4 |
| **T7** | 人闸:目检清单(T5 执行时含混编遭遇实机目检)+ 代拍板追认 | 0.5d | 目检过 | §1.2 判定 5 |
| **T8** | 收口五步(active.md 快照 → 工作日志 → roadmap 迭代 17 行标注 → 06 收口 → 闸序列留痕) | 0.25d | — | 收口五步齐 |
> 估时合计 ≈ **4.25d**(含 T5)/ **3.75d**(不含 T5),超 roadmap 软时间盒 3 日上限——知情预挂:T4 后按 L3 呈报切点,不擅切(沿迭代 9/秘宝批先例)。
> 估时合计 ≈ **3.75d**(T5 撤投放后全批;v1.0「含 T5 4.25d」口径随 P3 改裁作废),超 roadmap 软时间盒 3 日上限——知情预挂:T4 后按 L3 呈报切点,不擅切(沿迭代 9/秘宝批先例)。
## 7. 验证闸
- **轻闸**(每轮):run_smoke 全量 + ui_input_probe;触 presentation 的轮次(T3/T5)加 ui_click_probe + ui_layout_probe + ui_struct_probe(2026-10-05 起 ui_struct_probe 已入默认必跑段)。
- **重闸**(T6):全量轻闸 + doc 三闸(doc_link / gdd_lint / doc_term,对基线零新增)+ 熵增闸 + MC 逐项比对。
- **MC 触发**:零内容期对拍属「结构位移类存档锚」,**发起前先向用户请示定性**(CLAUDE.md MC 触发细则);T5 投放行属数值验证场景,同样先报批。两入口铁规全程有效。
- **MC 触发**:零内容期对拍属「结构位移类存档锚」,**发起前先向用户请示定性**(CLAUDE.md MC 触发细则);T5 本批不触发(P3 丙),后续内容批投放时属数值验证场景、同样先报批。两入口铁规全程有效。
## 8. 代拍板白名单与待用户裁点
@@ -131,14 +133,20 @@
### P1 · 混编数量语义
**✅ 裁决(2026-10-06 用户令):案甲**——每行各自 unit_count 独立实例化;**行集实例总数(各行骰后数量求和)≤4**(Q9 二裁消歧:「总数」=实例数非行数,行数不另设上限);UNIT_COUNT_MAX 语义改「单种数」随批换代校验与 spawn 守卫。
**裁决补充·遭遇骰交互(Q8 二裁,v1.0 漏裁)**:混编行集落地后**每行各掷一次数量骰**(与「每行各自 unit_count」语义自洽),单一行集仍吃单个 `unit_count_override` 且仅作用于该行集整体传入值按行分配的现行路径不存在——override 命中时跳过行内掷骰直接取值;每行一骰=遭遇骰封闭流新增消费点,**实现前须按 R4 报批扩签**(随机流消费次数变化牵动全部种子面),未获批准前 T2/T3 不得落码。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 每行各自 `unit_count` 独立实例化,行集总数上限另立(如 ≤4);数量域 [1,3] 仍约束单行 | 表意最直白,作者按行写数即可;代价是 UNIT_COUNT_MAX 语义从「单场总数」改为「单种数」,须同步改校验与 spawn 守卫 |
| 甲(推荐,已裁) | 每行各自 `unit_count` 独立实例化,行集实例总数上限 ≤4;数量域 [1,3] 仍约束单行 | 表意最直白,作者按行写数即可;代价是 UNIT_COUNT_MAX 语义从「单场总数」改为「单种数」,须同步改校验与 spawn 守卫 |
| 乙 | 行集总数仍 ≤3,按行权重或行序分配各种只数 | 场上规模完全不变、数值面最稳;淘汰理由:分配规则本身是新的隐性机制,作者无法直接表达「我要 1 蜘蛛 + 2 地精」,表意失真 |
| 丙 | 每种恒 1 只 | 最简;淘汰理由:混编的主要价值(强弱搭配的数量结构)被阉割,等于只允许「2-3 种各 1 只」一种形态 |
### P2 · 行集解析双算法处置(工作日志 312 既有待裁项随批)
**✅ 裁决(2026-10-06 用户令):案甲**——floor 版退役,全仓统走 resolver ceil 版(工作日志 312 待裁项随之销号)。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 本批顺带统一:`EnemyTable.resolve_rowset`(floor 版,仅冒烟四处用)退役,全仓统走 resolver ceil 版 | 行集解析本来就要换代,双算法一起收是最便宜时点;一次批内只多 4 处调用点改动 |
@@ -146,13 +154,18 @@
### P3 · 本批是否投放首个混编遭遇行
**✅ 改裁(2026-10-06 二裁,用户令,推翻一裁案乙):案丙(撤投放)**——本批回到纯结构批,混编行只建机制不投内容;首个混编遭遇行(连同 Boss 多行内容)归后续内容批统一投放。改裁依据(联审实据):一裁案乙的「巨蜘蛛 1+钩爪恐魔 1」与现行首遇教学位纪律正面冲突——巨蜘蛛首遇位 (2,4) 表注释与冒烟断言均为「固定 2 只不加骰」,投 1 只直接违反;钩爪恐魔真首遇位在 L3 (3,1) 固定不加骰,L2 投放使其名存实亡;且 L2 每个 battle 坐标都有断言撞面((2,0) 撞首遇绿档 12 种子扫描、(2,4) 撞固定 2 断言、(2,5/6/7) 撞 expect_pools 精确池),一裁「L2 某普通节点」无可落地坐标。投放义务随批登记 07(后续内容批连同 Boss 多行一起投、投时 MC 取证先报批、难度带读数义务同登记)。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 本批只放开机制、零内容投放;首个混编遭遇归后续难度曲线/内容批 | 机制批零数值变更,MC 零跑或仅零扰动对拍,批面最干净 |
| 乙(推荐) | 本批顺带投放一个教学位混编行(候选:L2 某普通战斗节点,巨蜘蛛 1 + 钩爪恐魔 1,行值 provisional 归调参) | 机制没有内容验证等于没验收;一个定点行即覆盖全链(生成/叙述/结算/胜利);代价是需 MC 取证(先报批)与行值 provisional 登记 |
| 甲 | 本批只放开机制、零内容投放;首个混编遭遇归后续难度曲线/内容批 | 与丙同向但未点名承接批,义务易悬空 |
| 乙(一裁,已推翻) | 本批顺带投放教学位混编行(L2 某普通节点,巨蜘蛛 1 + 钩爪恐魔 1,行值 provisional) | 推翻理由见上:与首遇教学位纪律/表注释/冒烟断言三面冲突,无合法坐标 |
| 丙(二裁,生效) | 撤投放,纯结构批;混编行内容归后续内容批(与 Boss 多行同批),投放时 MC 取证先报批 + 难度带读数义务随批登记 07 | 机制批零数值变更零 MC;投放的教学价值不抵三面断言/纪律/读数连带代价 |
### P4 · Boss 行集是否允许多行
**✅ 裁决(2026-10-06 用户令):案乙(否决推荐案甲)**——Boss 行集校验同样放开(多行合法)。知情代价随批登记:Boss 半血解锁/独占技/难度带读数面自此可被 Boss 行内容变量影响;**另有两个具体读数面(v1.1 补列)**:①`battle_narrator.gd:70-77` `boss_name()` 取行集**首个命中行**的 display_name——Boss 行集多行后 Boss 名显示可能变成护卫名(取决于文件行序,R6 纪律的呈现面后果);②Boss 节点遭遇骰同样读首行 `unit_count` 区间(`battle_orchestrator.gd:225`),多行后首行区间即全行集骰域。**本批零内容投放不变**(P3 已改裁丙=撤投放),Boss 多行的实际内容投放归后续内容批,投放时节奏重测义务 07 在册、上述读数面逐项复核。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 本批仅普通战斗节点放开;Boss 节点行集仍恰一行(加载期校验保留 Boss 行单行约束) | Boss 半血解锁技刚落籍、节奏重测(T7 读数)未跑,Boss 战形态此时不应再加变量;护卫型 Boss 属内容设计,归后续批单议 |
@@ -177,7 +190,7 @@
|---|---|---|
| **L1** | 单轮轻闸红 | 一次重试(自查漏改/调用点遗漏);仍红 → L2 |
| **L2** | 同类错误连续 3 轮 / 事实表与 §2 不符 | 记录进本任务书与工作日志,修订事实表后继续;不阻断全批 |
| **L3** | 任一 🔴 R1–R5 破 / P1–P4 久决不下 / 发现需要新增随机消费点或改存档 | 停机写报告(列事实 + 影响面 + 方案对比),等用户发令;不自行决断 |
| **L3** | 任一 🔴 R1–R6 破 / P1–P4 久决不下 / 发现需要新增随机消费点或改存档 | 停机写报告(列事实 + 影响面 + 方案对比),等用户发令;不自行决断 |
## 11. 现状留痕(供执行会话读序)
@@ -1,8 +1,11 @@
# 任务书:暂停层只读入口批(v1.0 定稿,待发令开工)
# 任务书:暂停层只读入口批(v1.1 定稿,零待裁点,开工门=U0 用户发令)
> 成文 2026-10-05。**性质**:功能性 UI 交互新增——局内暂停层,承载钥石余额与营地柜台解锁进度的**只读**查看。
> **T0 基线回填(2026-10-06 执行会话实测,HEAD=44328b1)**:冒烟 **783/0**(§1.2 注记 782 系 ed38c54 时点参考值,卡④落籍后 +1,以本读数为对拍基线)· run_all **17 套全绿** · probe_gate 默认段(ui_input+ui_struct+ui_contrast)全绿。§2 事实表 F1-F10 逐条实核全绿(F2 登记册=main.gd:332、z 序注记=:242-243;F3 badge 工厂缺位+营地本地拼装=camp_overlay_view.gd:79-92;F5 访问器行号逐一符合、boss_kill_count=save_manager.gd:250 精确;F8 settings=main.gd:260;F10 dbgbtn=ui_assembler.gd:161-164)。**迭代 15② 交集核对:零命中**——卡②/卡③均已 2026-10-05 落籍(roadmap 现行口径,无在飞面);在飞 worktree 三件(iter17-dd 卡⓪〔尚无超前提交〕/uialign/standee〔均零 diff〕)与本批文件面零交集。
> 成文 2026-10-05,v1.1 修订 2026-10-06(五任务书联审:R4 快照口径收敛、badge 工厂路径裁决〔Q10 甲〕、P1 丁的 06 Esc 登记补办、基线换代 iter16ui 批后、F5/F10 事实勘误、入口守卫与只读断言口径补列)。
> **性质**:功能性 UI 交互新增——局内暂停层,承载钥石余额与营地柜台解锁进度的**只读**查看。
> 事实源 = [06-待办清单](../gdd/06-待办清单.md)「解锁界面与钥石呈现的交互形态(残余:暂停层只读入口)」条。
> 归属迭代:**迭代 17 · 卡③**(迭代 17 四卡:①敌人表行集多行批 ②M4 数值批 ③本批 ④生涯界面设计立项)。
> 归属迭代:**迭代 17 · 卡③**(迭代 17 现=卡⓪数据驱动扩展批+①敌人表行集多行批+③本批+④生涯界面设计立项;M4 数值批已移迭代 18,roadmap 现行口径)。
> 满足 loop engineering 八件(见 §9 逐条对照)。
> **美术红线(2026-10-05 用户立规)**:本批不得包含观感类、素材类内容;呈现必须复用现行公共件(UiKit 工厂件)与 ui_kit 色板 token,**不新画任何素材、不新建任何色值**。功能性 UI 交互不算美术。
@@ -20,11 +23,11 @@
|---|---|---|
| 1 | 入口可达 | 局内两个主屏(战斗屏 / 关卡地图屏)均可按 P1 裁决的形态打开暂停层;入口在对局外(主菜单)不误出现 |
| 2 | 只读数据正确 | 暂停层展示的钥石余额、三柜台进度与 `MetaProgression` 访问器读数逐项一致;无任何可点购买/切换控件 |
| 3 | 公共件复用 | 全部构成件来自 UiKit 现行工厂(modal_shell / bcard / label / badge / icon_rect / verb_button 等)与色板 token;零新素材、零新色值、零新字体 |
| 3 | 公共件复用 | 全部构成件来自 UiKit 工厂(modal_shell / bcard / label / icon_rect / verb_button 等)与色板 token;**badge 由本批在 ui_kit 新增工厂件并同步迁入营地钥石徽(Q10 甲裁决)**;零新素材、零新色值、零新字体 |
| 4 | 模态纪律 | 登记进 modal_stack 登记册(main.gd:332 同款),z 序与输入锁行为符合缺陷⑤纪律;与既有弹窗层的关系按 P2 裁决落实 |
| 5 | 重闸全绿 + 人闸 | 冒烟全量(基线 T0 重测回填)· run_all 十五套件 · ui_struct_probe / ui_click_probe / ui_input_probe 全绿 · doc 三闸零新增 · 熵增闸 PASS;实机目检清单过 |
| 5 | 重闸全绿 + 人闸 | 冒烟全量(基线 T0 重测回填)· run_all 十七套件 · ui_struct_probe / ui_click_probe / ui_input_probe / ui_contrast_probe 全绿 · doc 三闸零新增 · 熵增闸 PASS;实机目检清单过 |
> ⚠️ **基线纪律**:起草时点 master 头 = 413c936,冒烟 772/0,run_all 14/15(reward_overlay_test 基线红归迭代 15②批,本批守零新增)。T0 重测回填。
> ⚠️ **基线纪律(v1.1 换代)**:起草时点 master 头 = 413c936(冒烟 772/0);**v1.1 修订时点现行头 = ed38c54**,中间落了整个 iter16ui 批(12+ 提交触 ui_kit.gd,F3 行号全部漂移失效)+ M4 移批,现行基线读数=冒烟 782/0、run_all 17 套件、**ui_contrast_probe 已入 probe_gate 默认必跑段**(新增文字层必须过对比度机检)。§2 行号系 413c936 时点考证,T0 按现行 HEAD 重取回填,禁止沿用本文行号与数字。
## 2. 现状事实(代码级考证,2026-10-05 起草时点;T0 须自行复核)
@@ -32,14 +35,14 @@
|---|---|---|
| F1 | 现行无暂停层 | 全仓无 pause/暂停 实现;局内模态层 = 图例 / 节点兑付 / 关卡画面 / 三选一 / 终局 / 商店 / 营地 / 设置 / 确认弹窗 / 调试浮窗(main.gd:332 登记册 + :242 z 序注记) |
| F2 | 模态基础设施现成 | `modal_stack.gd` 状态机 + `_open_modal`/`_close_modal` 单口(main.gd:353 起)+ 输入锁 = `modal_stack.has_open()` 开态查询;新层照登记册追加即可,零新机制 |
| F3 | 公共件清单 | `presentation/views/ui_kit.gd`:`modal_shell`(:229)· `verb_button`(:343,图标+动词+tooltip 三件套)· `bcard`(:455,BCard 竖卡:色带/图标槽/价签/底注参数化)· `switch_toggle`(:484)· `styled_slider`(:489)· label / badge / icon_rect 等;色板 token(WARM / STONE / INK_ON_GOLD / 烛光黄徽章形制等)同文件单点 |
| F3 | 公共件清单 | `presentation/views/ui_kit.gd`:`modal_shell` · `verb_button`(图标+动词+tooltip 三件套)· `bcard`(BCard 竖卡:色带/图标槽/价签/底注参数化)· `switch_toggle` · `styled_slider` · label / icon_rect 等;色板 token(WARM / STONE / INK_ON_GOLD / CANDLE 等)同文件单点。**badge 工厂现状不存在(v1.1 勘误)**:营地钥石徽系 camp_overlay_view.gd:80-93 本地拼装(panel_flat+icon_rect+label)非公共件——处置=Q10 甲裁决,见 §3 组 A |
| F4 | 按钮宽度纪律 | `UiKit.button(text, min_w=216)` 全站最小宽度基准 + SIZE_FILL(2026-10-05 ui-struct-probe 批);行板/角标/图标钮豁免 9 处先例在册;ui_struct_probe 已入轻闸默认必跑段(按钮互压/等宽/出屏/零尺寸断言) |
| F5 | 数据面现成 | `meta_progression.gd` 只读访问器齐全:`keystone_balance()`(:28)· `forge_level/forge_flat/forge_price`(:34-44)· `workshop_status()`(:90)· `is_item_unlocked`(:85)· `attune_camp_status()`(:370)· `attune_refresh_charges()`(:397)· `tree_camp_rows()`(:260)· Boss 击杀计数面(`boss_kill_count` 等)——暂停层只读消费,零核心层改动 |
| F6 | 钥石呈现现状 | 营地屏顶栏钥石徽(camp_overlay_view.gd:82-93,烛光黄底+深墨字徽章形制)与结算屏入账明细已落地;**战斗屏内 GP/钥石已迁出**(hero_info_panel_view.gd:4-6 注记)——局内想看钥石余额没有任何入口,正是 06 条残余面的由来 |
| F5 | 数据面现成 | `meta_progression.gd` 只读访问器齐全:`keystone_balance()`(:28)· `forge_level/forge_flat/forge_price`(:34-44)· `workshop_status()`(:90)· `is_item_unlocked`(:85)· `attune_camp_status()`(:370)· `attune_refresh_charges()`(:397)· `tree_camp_rows()`(:260);**Boss 击杀计数 `boss_kill_count` 实际在 `core/save_manager.gd:250`(v1.0 误记 meta_progression.gd,2026-10-06 勘误)**——暂停层只读消费,零核心层改动 |
| F6 | 钥石呈现现状 | 营地屏顶栏钥石徽(camp_overlay_view.gd:80-93,烛光黄底+深墨字徽章形制,**本地拼装**——badge 工厂化后迁入 ui_kit)与结算屏入账明细已落地;**战斗屏内 GP/钥石已迁出**(hero_info_panel_view.gd:4-6 注记)——局内想看钥石余额没有任何入口,正是 06 条残余面的由来 |
| F7 | 营地三柜台现行构成 | 属性锻造(forge 三行)· 道具工坊(workshop 六件按总通关次数解锁)· 天赋树(迭代 12 批次二营地树 UI);另有同调装配面(attune)。暂停层展示范围见 P3 裁点 |
| F8 | 设置面先例 | `settings_overlay.gd` = 最小设置面(音量/全屏/减动效),SettingsOverlay 实例由 main.gd:260 创建并登记模态——暂停层与其关系见 P2 裁点 |
| F9 | 减动效开关 | 已转正(迭代 8 卡④,settings_store 承载);排播队列与轮横幅在减动效开时延迟归零——暂停层进出呈现须遵守同一开关(P4 裁点) |
| F10 | 调试浮窗先例 | debug_overlay(迭代 15①)= 悬浮 Dialog 形态、DS_DEBUG 门控、仅开始菜单可开——其「角标入口 + Dialog 层」形态是暂停层的最近先例,但门控与可达域不同(暂停层 = 玩家常态功能,对局内可达) |
| F10 | 调试浮窗先例 | debug_overlay(**迭代 14.5 调试整合批,git 48c0b34**——v1.0 误记迭代 15①,2026-10-06 勘误)= 悬浮 Dialog 形态、DS_DEBUG 门控、仅开始菜单可开——其「角标入口 + Dialog 层」形态是暂停层的最近先例,但门控与可达域不同(暂停层 = 玩家常态功能,对局内可达) |
## 3. 改动清单(两组)
@@ -47,15 +50,16 @@
| 文件 | 改动 |
|---|---|
| `presentation/views/pause_overlay.gd`(新) | 只读覆盖层:标题区 + 钥石余额行(复用营地同款徽章形制:icon_rect(TEX_ICON_KEYSTONE) + label,色板 token 取现行值)+ 三柜台进度区(范围随 P3)+ 关闭钮;全部经 UiKit 工厂件拼装,零自绘 |
| `presentation/views/ui_kit.gd` | **新增 badge 工厂件(Q10 甲裁决)**:钥石徽形制(icon_rect+label 徽章)参数化收编;营地钥石徽(camp_overlay_view.gd:80-93 本地拼装)同步迁入工厂调用,消单点重复——营地侧改动仅替换拼装为工厂调用,观感零变化 |
| `presentation/views/pause_overlay.gd`(新) | 只读覆盖层:标题区 + 钥石余额行(badge 工厂件:icon_rect(TEX_ICON_KEYSTONE) + label,色板 token 取现行值)+ 三柜台进度区(范围随 P3)+ 关闭钮;全部经 UiKit 工厂件拼装,零自绘 |
| `main.gd` | 实例化 + 登记 modal_stack 登记册(z 序位置随 P2)+ 打开/关闭接线 |
### 组 B · 入口与断言
| 文件 | 改动 |
|---|---|
| 入口挂点(随 P1 裁决:战斗屏 HUD / 关卡地图屏 / Esc 通道) | 入口控件复用 verb_button 或角标先例(debug 角标形制),宽度纪律遵守 min_w=216 或申请豁免(角标类已有豁免先例) |
| `smoke/ui_struct_probe.gd` / `ui_click_probe.gd` / `ui_input_probe.gd` | 暂停层结构断言(不出屏/零尺寸/按钮宽度)+ 打开关闭行为断言 + 只读性断言(层内无购买信号连接) |
| 入口挂点(P1 已裁丁=**常驻角标**,Esc 不落码) | 战斗屏 HUD 与关卡地图屏各一角标(复用 debug 角标形制);**装配落点 T0 复核后在 ui_assembler / 两屏装配段中定点(白名单内决断)**;宽度纪律遵守 min_w=216 或申请豁免(角标类已有豁免先例)。**入口守卫(v1.1 补)**:其他模态(商店/三选一/营地/设置等)开启时角标置灰不可点(has_open 守卫)——iter16ui 后商店/三选一系全屏 page_shell 会盖住角标,守卫防「看得见点不着」态 |
| `smoke/ui_struct_probe.gd` / `ui_click_probe.gd` / `ui_input_probe.gd` | 暂停层结构断言(不出屏/零尺寸/按钮宽度)+ 打开关闭行为断言 + 只读性断言(**口径(v1.1 补)=巡检层内控件的 signal 连接清单(get_signal_connection_list),断言无任何指向购买/解锁/写入路径的连接;巡检信号名清单 T2 落码时列全进探针**) |
| `smoke_all.gd` | 数据一致性断言(暂停层投影 = MetaProgression 访问器读数) |
## 4. 范围边界(🔴 不可越界)
@@ -76,8 +80,8 @@
| 🔴 R1 | **公共件单点**:一切面板/按钮/徽章/卡片经 UiKit 工厂产出;禁裸色值字面量、禁自建 PanelContainer 样式 | ui_struct_probe + 静态审查 |
| 🔴 R2 | **模态登记纪律**:新层必须登记 modal_stack 登记册,z 序=树序=登记序(缺陷⑤纪律);禁绕模态栈直开(迭代 6 卡⑨事故先例) | ui_click_probe 断言 |
| 🔴 R3 | **输入锁语义**:暂停层开启时棋盘/节点输入锁定(has_open 开态查询),关闭后恢复原屏交互,无状态残留 | ui_input_probe 断言 |
| 🔴 R4 | **数据只读同源**:展示值一律实时读访问器,禁止开层时拷贝快照后长期持有(余额在层开启期间不变化的前提是层内无操作——快照可接受但须随 P3 一并披露口径) | 冒烟断言 |
| 🔴 R5 | **减动效遵守**:层进出若有动效,减动效开 = 动效归零(settings_store 现行开关消费) | 探针双态断言 |
| 🔴 R4 | **数据只读同源**:展示值一律实时读访问器;**快照口径(v1.1 收敛,原句先禁后允系起草矛盾)**——开层时预取快照仅允许在**单次开层生命周期**内使用,禁跨开层持有,采用快照时须在 T4 目检材料中披露口径(读哪几个访问器、何时取值) | 冒烟断言 |
| 🔴 R5 | **减动效遵守**:P4 已裁零动效直开直关——本契约收敛为「**零动效路径存在断言**」(探针断言层进出无过渡动画节点/时长归零路径),减动效开关无新增消费 | 探针断言 |
## 6. 任务卡(逐卡一个 loop 轮次)
@@ -87,14 +91,14 @@
| **T1** | 组 A:pause_overlay.gd 本体(按 P1-P4 裁决落形态)+ main.gd 登记接线 | 1.0d | 冒烟 + ui_struct_probe | 层可开关;结构断言绿 |
| **T2** | 组 B:入口挂点 + 三探针断言(结构/点击/输入)+ 冒烟数据一致性断言 | 0.75d | 冒烟 + 三探针 | §1.2 判定 1/2/4 |
| **T3** | 重闸:全量轻闸(含 ui_struct/ui_click/ui_layout)+ doc 三闸 + 熵增闸 | 0.25d | 重闸全绿 | §1.2 判定 5 前半 |
| **T4** | 人闸:实机目检清单(双屏入口/只读性/数据正确/减动效双态/与设置面关系)+ 代拍板追认 | 0.5d | 目检过 | §1.2 判定 5 |
| **T4** | 人闸:实机目检清单(双屏入口/**其他模态开着时角标守卫态**/只读性/数据正确/零动效直开直关/**开层时排播队列排空副作用观察**〔_open_modal 开层前 _flush_row_queue 系既有层同款行为,与玩家「暂停」预期之差记入目检确认项〕/与设置面关系)+ 代拍板追认 | 0.5d | 目检过 | §1.2 判定 5 |
| **T5** | 收口五步 + 06 状态行收口 | 0.25d | — | 收口五步齐 |
> 估时合计 ≈ **3.0d**,贴软时间盒上限——知情预挂:T2 末为天然切分点,超限按 L3 呈报不擅切。
## 7. 验证闸
- **轻闸**(每轮):run_smoke 全量 + ui_input_probe + ui_struct_probe(本批触 presentation,三轮加 ui_click_probe + ui_layout_probe)。
- **轻闸**(每轮):run_smoke 全量 + ui_input_probe + ui_struct_probe + **ui_contrast_probe(v1.1 补——已入 probe_gate 默认必跑段,本批新增文字层必须过对比度机检)**(本批触 presentation,三轮加 ui_click_probe + ui_layout_probe)。
- **重闸**(T3):全量轻闸 + doc 三闸零新增 + 熵增闸。
- **MC**:纯呈现批,零数值改动 → **零 MC**(两入口铁规 + 无数值改动禁跑 MC)。
@@ -109,6 +113,8 @@
### P1 · 暂停入口位置与唤起形态
**✅ 裁决(2026-10-06 用户令):案丁**——常驻角标为主入口,Esc 附加快捷通道登记 06 排期 Beta 随键盘批统一接(**06 登记已于 2026-10-06 联审批补办落文**——v1.0 裁后未执行,属行政漏步;另注:该登记同时使 06 键盘条目「弹层界面现行全鼠标」清单 +1 项,属本批连带披露)。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 战斗屏与关卡地图屏各加一个角标按钮(复用 debug 角标形制,玩家常态可见、无门控) | 发现性最好,触屏/鼠标直点;代价是两个屏各加一个常驻控件 |
@@ -118,6 +124,8 @@
### P2 · 与既有弹窗层的关系(modal 登记序位置与遮罩)
**✅ 裁决(2026-10-06 用户令):案甲**——登记设置层同档带 dim 遮罩,开启时不可再开其他层。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 登记在设置层同档(登记册尾段、确认弹窗之前),带 dim 遮罩(modal_shell 现行 dim 参数),开启时不可再开其他层 | 与设置/确认同语义档,z 序行为可预期;modal_shell 现成 |
@@ -126,6 +134,8 @@
### P3 · 展示内容范围
**✅ 裁决(2026-10-06 用户令):案甲**——钥石余额 + 三柜台进度。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 钥石余额 + 三柜台进度(属性锻造三行已购等级 / 道具工坊六件解锁态 / 天赋树已购概览) | 与 06 条「钥石余额与解锁态(营地三柜台进度)」字面一致 |
@@ -134,6 +144,8 @@
### P4 · 减动效联动口径
**✅ 裁决(2026-10-06 用户令):案甲**——进出零动效直开直关。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 暂停层进出默认零动效(直开直关),减动效开关无新增消费 | 最简且天然合规;只读查看层本无演出需求 |
@@ -1,8 +1,9 @@
# 任务书:生涯界面设计立项(v1.0 设计提纲版,只做设计不做实装)
# 任务书:生涯界面设计立项(v1.1 设计提纲版,零待裁点,开工门=U0 用户发令)
> 成文 2026-10-05。**性质**:纯设计批——产出「生涯」界面的设计提纲(信息架构 + 承载内容清单 + 与既有界面的关系 + 分期实装建议 + 待裁点),**本批零实装、零代码、零数据面改动**。
> 成文 2026-10-05,v1.1 修订 2026-10-06(五任务书联审:F4 事实改正——recent_summaries 现役在存、P2 甲口径重述〔Q5 甲〕、总局数/通关局数标注涉存档 schema、营地既有最近冒险清单列入设计稿必答项、N 候选补「维持 10」、文件名与行号勘误、UiKit 对齐与 save v6 义务补登记)。
> **性质**:纯设计批——产出「生涯」界面的设计提纲(信息架构 + 承载内容清单 + 与既有界面的关系 + 分期实装建议 + 待裁点),**本批零实装、零代码、零数据面改动**。
> 事实源 = [06-待办清单](../gdd/06-待办清单.md)「『生涯』界面——冒险中数据回看的唯一承接处」条(2026-10-04 用户裁决 P-C7:冒险中不给数据回看,历史战报/结算明细的查看去向 = 新「生涯」界面;生涯未做前冒险中无历史回看入口 = 已知代价,用户知情裁决)。
> 归属迭代:**迭代 17 · 卡④**(迭代 17 四卡:①敌人表行集多行批 ②M4 数值批 ③暂停层只读入口批 ④本批)。
> 归属迭代:**迭代 17 · 卡④**(迭代 17 现=卡⓪数据驱动扩展批+①敌人表行集多行批+③暂停层只读入口批+④本批;M4 数值批已移迭代 18,roadmap 现行口径)。
> **实装批另行立项**:本任务书只交付设计提纲文档与裁点呈报;任何实装(数据面/界面/存档域)须用户审毕提纲后另行发令立项。
> 满足 loop engineering 八件(按设计批形态适配,见 §9 逐条对照)。
@@ -28,14 +29,14 @@
| # | 事实 | 读数 |
|---|---|---|
| F1 | 冒险中回看已退役 | M9(P-C7 裁)落码:`battle_end_overlay.gd:90` 明细回看钮退役、`review_pressed` 信号退役;`battle_log_view.gd:47` 战报带改单行「上轮摘要(回看归「生涯」)」、:115 带点击回看入口退役;`ui_assembler.gd:67` 注记「明细回看 overlay 已随 M9/P-C7 退役——冒险中回看归「生涯」06 登记」 |
| F1 | 冒险中回看已退役 | M9(P-C7 裁)落码:`battle_end_overlay.gd:106` 明细回看钮退役(v1.0 写 :90 系漂移,:90 现为 GP 账目行;signal 退役注记在 :9)、`review_pressed` 信号退役;`battle_log_view.gd:47` 战报带改单行「上轮摘要(回看归「生涯」)」、:115 带点击回看入口退役;`ui_assembler.gd:67` 注记「明细回看 overlay 已随 M9/P-C7 退役——冒险中回看归「生涯」06 登记」 |
| F2 | 遗留文件 | `presentation/views/settlement_review_overlay.gd` 文件本体仍在,冒险中已无入口(处置见 P5 裁点:实装期复活承接还是退役删除) |
| F3 | 跨局持久面 = save v5 meta 域 | `keystone_balance` / `forge_levels` / `item_unlocks` / `level_clear_counts` / `boss_first_kill` / `boss_kill_count` / `tree_nodes` / `fork_sides` / `attunement_equipped` / `attune_refresh_level` / `first_adventure_done`(save_manager.gd:39 schema 注记 + meta_progression.gd 访问器面) |
| F4 | 🔴 **无历史冒险记录面** | `settle_adventure()`(meta_progression.gd:129)只做入账(钥石余额累加、工坊解锁刷新、通关计数),**每局摘要不留痕**——历史冒险回看需要新建数据面(每局摘要的持久化域),这是本设计提纲最大的数据设计题 |
| F3 | 跨局持久面 = save v5 meta 域 | `keystone_balance` / `forge_levels` / `item_unlocks` / `level_clear_counts` / `boss_first_kill` / `boss_kill_count` / `tree_nodes` / `fork_sides` / `attunement_equipped` / `attune_refresh_level` / `first_adventure_done` / **`recent_summaries`**(save_manager.gd:39 schema 注记 + meta_progression.gd 访问器面;v1.0 键集漏列 recent_summaries,v1.1 补) |
| F4 | ⚠️ **历史冒险记录面现状(v1.1 事实改正——v1.0 误记「无历史冒险记录面」)** | **`recent_summaries` 现役在存**:`save_manager.gd:40` `const SUMMARY_CAP := 10`(注释「最近冒险摘要保留条数(最新在前)」)、`:325-338` `apply_adventure_summary()` 逐局 push_front 归档(附 boss_drops 副本)、`:316` `recent_summaries()` 访问器;`settle_adventure()`(meta_progression.gd:129)**经** `apply_adventure_summary` 留痕(:125 注记「keystone_drops 副本随摘要入 recent_summaries」);registry entities.yaml:73 meta 域九件明列。**真实缺口只有三件**:①cap 10→N 扩容(P2 甲);②摘要五件事(结局/到达关卡/钥石合计/种子)**无「用时」字段**——全仓 grep elapsed/ticks/duration 零采集点,补用时=新增埋点;③**冒险总局数/通关局数无 lifetime 计数域**(`first_adventure_done` 是布尔、`level_clear_counts` 按关计次反推不出局数、cap 10 摘要不能累 lifetime)——总局数/通关局数须新增计数域,**涉存档 schema(save v6 迁移义务)**,归期一实装批 |
| F5 | 当局结算呈现仍在 | 冒险收束时结算屏入账明细(钥石 +N、新解锁)现行保留——退役的只是「局后任意时刻回看」,不是收束当下 |
| F6 | 跨局汇总数据源现成 | 总通关次数(level_clear_counts 按关)、Boss 首杀/总击杀、钥石余额与累计流(余额在,累计收支无流水)、锻造/工坊/天赋树解锁态——「跨局汇总」页大部分字段可直接读访问器,零新数据面 |
| F6 | 跨局汇总数据源现状 | 总通关次数(level_clear_counts 按关)、Boss 首杀/总击杀、钥石余额与累计流(余额在,累计收支无流水)、锻造/工坊/天赋树解锁态——大半字段可直接读访问器;**「冒险总局数 / 通关局数」两格无数据源(v1.1 勘误——v1.0 误标「全现成·零新数据面」)**:须新增 lifetime 计数域,涉存档 schema,见 F4③ |
| F7 | 图鉴承接的候选内容 | 06 在册相关条目:「敌方技能图鉴 / 学习呈现」(P2,见过→认得→记谱);奖励格图鉴柜台空置(2026-10-04 配比预设批裁决该柜台承接配比容量,后随配比预设整体挂起——柜台仍空);秘宝/奇物均无图鉴面 |
| F8 | 相邻界面分工现状 | 营地 = 跨局成长**操作**面(花钥石买强化);主菜单 = 入口面(新冒险/继续上局/营地/设置/调试);设置面 = 环境开关;教学「帮助」手册(Beta 批初裁:全部内容放一个文档,未实装);暂停层(迭代 17 卡③)= 局内只读查看钥石与解锁进度 |
| F8 | 相邻界面分工现状 | 营地 = 跨局成长**操作**面(花钥石买强化)**+ 既有只读「最近冒险」清单**(camp_overlay_view.gd:431 `_rebuild_recent()` 渲染逐局「完成/放弃/失败 · 通关 N 关 · 钥石 +N · 种子 N」,camp_shop_presenter.gd:85 投影 `"recent"`——生涯期二落地后此清单去留/迁移/去重是设计稿必答项,v1.1 补);主菜单 = 入口面(新冒险/继续上局/营地/设置/调试);设置面 = 环境开关;教学「帮助」手册(Beta 批初裁:全部内容放一个文档,未实装);暂停层(迭代 17 卡③)= 局内只读查看钥石与解锁进度 |
| F9 | 06 条目原文口径 | 「跨局汇总 / 历史冒险回看 / 图鉴承接」三段内容清单是 06 条目给定骨架,本提纲在其上展开,不另起炉灶 |
| F10 | 阶段语境 | 教学引导五条目已整体改排 Beta(2026-10-04 拍板);生涯未标阶段——分期建议须回答「生涯第几期落在 Alpha 后哪个窗口」 |
@@ -61,15 +62,15 @@
| 段 | 内容 | 数据源 | 可行性 |
|---|---|---|---|
| 跨局汇总 | 冒险总局数 / 通关局数 / 各关通关次数 / Boss 首杀与总击杀 / 钥石余额(累计收支流水可选)/ 三柜台解锁完成度概览 | F6 全现成(除累计流水) | **期一即可做,零新数据面**(累计流水若做需补记账点,随 P2) |
| 历史冒险回看 | 逐局摘要:第 N 局、结局(通关/失败/放弃)、走到哪、钥石收入、关键构筑(可选);单局结算明细回看(复活 settlement_review 承载) | F4 **需新建数据面**(每局摘要持久化) | **期二**,数据面范围是最大裁点(P2) |
| 图鉴承接 | 敌人图鉴(06 在册 P2 条目承接:见过→认得→记谱)/ 秘宝图鉴 / 奇物图鉴 / 奖励格图鉴(空置柜台) | 逐类立「见过」记账面 | **期三**,范围与顺序随 P3 |
| 跨局汇总 | 冒险总局数 / 通关局数 / 各关通关次数 / Boss 首杀与总击杀 / 钥石余额(累计收支流水可选)/ 三柜台解锁完成度概览 | F6 大半现成;**总局数/通关局数两格需新增 lifetime 计数域(涉存档 schema,F4③)** | 期一可做,但**非「零新数据面」**——两个计数域随期一实装批走 save v6 迁移(v1.1 勘误) |
| 历史冒险回看 | 逐局摘要:第 N 局、结局(通关/失败/放弃)、走到哪、钥石收入、关键构筑(可选)、用时;单局结算明细回看(复活 settlement_review 承接) | **F4 现役 recent_summaries(cap 10)+ 扩容 N + 补用时埋点(P2 甲口径重述)** | **期二**,数据面改动=扩容+加字段+迁移旧档摘要(P2) |
| 图鉴承接 | 敌人图鉴(06 在册 P2 条目承接:见过→认得→记谱)/ 秘宝图鉴 / 奇物图鉴 / 奖励格图鉴(空置柜台) | 逐类立「见过」记账面=**新增 meta 域,涉存档 schema(save v6 迁移义务,v1.1 补)** | **期三**,范围与顺序随 P3 |
### 3.3 与既有界面的关系(分工一句话矩阵)
| 界面 | 管什么 | 与生涯的边界 |
|---|---|---|
| 营地 | 跨局成长的**操作**(买/装配/点树) | 营地不改生涯只读定位;生涯不做任何购买入口,「去买」按钮也不放(跳转型入口随 P4) |
| 营地 | 跨局成长的**操作**(买/装配/点树)+ 既有只读「最近冒险」清单(F8) | 营地不改生涯只读定位;生涯不做任何购买入口,「去买」按钮也不放(跳转型入口随 P4);**营地「最近冒险」清单的去留/迁移/去重是设计稿必答项(v1.1 补)**——期二落地后两处逐局列表并存还是营地侧撤下并入生涯,设计稿须给明确建议 |
| 暂停层(迭代 17 卡③) | **局内**只读看钥石与解锁进度 | 暂停层看「这一局进行中的当前值」,生涯看「跨局累计与历史」;局内是否给生涯入口随 P4 |
| 结算屏 | 当局收束当下的入账明细 | 收束当下保留;生涯承接的是收束之后的任意时刻回看 |
| 帮助手册(Beta 批) | 规则与玩法的说明文档 | 手册讲「怎么玩」,生涯讲「我玩过什么」;图鉴条目文案与手册条目是否共用内容源,归 Beta 批一并裁(本提纲只登记接口) |
@@ -79,9 +80,11 @@
| 期 | 内容 | 前置 | 建议窗口 |
|---|---|---|---|
| 期一 | 跨局汇总页(零新数据面,纯只读投影)+ 生涯入口落位 | 本提纲裁决完毕 | Alpha 后最近一个 UI 窗口(可与暂停层批同迭代序列后续) |
| 期二 | 历史冒险回看(新建每局摘要数据面 + 逐局列表 + 单局明细,settlement_review 复活承接随 P5) | 期一 + P2 数据面裁决 | 期一落地后独立批 |
| 期三 | 图鉴承接(范围与顺序随 P3) | P3 裁决 + 对应「见过」记账面 | Beta 窗口候选(与教学引导同阶段评估——「认得」轴与教学相关) |
| 期一 | 跨局汇总页(大半只读投影;总局数/通关局数两个 lifetime 计数域走 save v6 迁移)+ 生涯入口落位 | 本提纲裁决完毕 + **实装批前置义务(v1.1 补):对齐 iter16ui 后现行 UI 基线**——FS_* 六档字号/TG_* 语义色/BUTTON_MIN_H=40/ui_kit 色板单源/page_shell 模态栈纪律(与卡③任务书同款红线);UI 基线对齐义务由本提纲登记、实装批承接 | Alpha 后最近一个 UI 窗口(可与暂停层批同迭代序列后续) |
| 期二 | 历史冒险回看(recent_summaries 扩容 N+补用时埋点+旧档摘要迁移 + 逐局列表 + 单局明细,settlement_review 复活承接随 P5;营地「最近冒险」清单去留一并落地) | 期一 + P2 数据面裁决 | 期一落地后独立批 |
| 期三 | 图鉴承接(范围与顺序随 P3;「见过」记账面新增 meta 域=**save v6 迁移义务**) | P3 裁决 + 对应「见过」记账面 | Beta 窗口候选(与教学引导同阶段评估——「认得」轴与教学相关) |
> 本地化文案权(v1.1 补):生涯界面本体按钮/页签/空态文案归「设置与本地化」线(全仓无 i18n 实装,先例=教学文案权登记),图鉴条目文案与手册共源已在 §3.3 登记接口——实装批承接。
### 3.5 本批不做
@@ -131,13 +134,17 @@
### P0 · 提纲与正主载体
**✅ 裁决(2026-10-06 用户令)**:案甲——提纲直接落 design/gdd/systems/跨局循环/生涯.md(状态=范围草案),同步 02-系统清单.md(**根索引正名,v1.0 误写「02-系统清单索引」,全仓无此文件名**)。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 提纲成文即落 `design/gdd/systems/跨局循环/生涯.md`(状态=范围草案),同步 02-系统清单索引 | 「吸收即死」纪律:中间文档不留;正主早立早受益(R3) |
| 甲(推荐) | 提纲成文即落 `design/gdd/systems/跨局循环/生涯.md`(状态=范围草案),同步 02-系统清单.md 根索引 | 「吸收即死」纪律:中间文档不留;正主早立早受益(R3) |
| 乙 | 提纲暂存 design/research/ 待评审后再转正 | 评审前不动 GDD 树;淘汰候选:与「吸收即死」纪律冲突,且评审意见最终还是要落正主,多一次搬运 |
### P1 · 生涯入口位置
**✅ 裁决(2026-10-06 用户令)**:案甲——主菜单一级入口,与营地平级。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 主菜单一级入口,与营地平级 | 「生涯 = 跨局数据的家」与营地同级最直白;主菜单按钮组有现行形制可复用(实装期) |
@@ -146,14 +153,18 @@
### P2 · 历史冒险回看的数据面范围(期二核心裁点,本批只呈框架)
**✅ 裁决(2026-10-06 用户令:案甲;同日 Q5 甲二裁口径重述)**:每局一行摘要(结局/到达关卡/钥石收入/用时),上限存最近 N 局;N=20/50 实装期按存档体积读数定。**口径重述(v1.1——一裁建立在 v1.0「无历史冒险记录面」误记上,实际 recent_summaries 现役 cap=10)**:本裁的实际工作量=①**扩容 cap 10→N**(非新建数据面,向后兼容);②**补「用时」字段埋点**(现无任何采集点,属新增数据面改动,随期二);③旧档既有 ≤10 条摘要原样保留迁移;④N 候选补第三案「**维持 10 不动**」——实装期读数三选一(20/50/维持 10),读数方法(谁测、体积门槛几何、何时测)与设计稿参数化维度(列表形态/滚动/分页/上限提示)由设计稿给出、实装期执行。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 每局一行摘要(结局/到达关卡/钥石收入/用时),上限存最近 N 局(N 候选 20/50) | 存储最小、实现最简;回看粒度到「局」不到「战」 |
| 甲 | 每局一行摘要(结局/到达关卡/钥石收入/用时),上限存最近 N 局(N 候选 20/50/维持 10) | 存储最小、实现最简;回看粒度到「局」不到「战」;现役面只需扩容+补字段 |
| 乙 | 甲 + 每局完整结算明细留痕(逐行结算单据全存) | 回看最完整;淘汰候选:单局结算单据量大,存档体积与 schema 复杂度显著上升,且 99% 的回看诉求摘要即可满足 |
| 丙 | 不存历史,历史回看段整段取消(生涯只做汇总+图鉴) | 淘汰候选:06 条目明列「历史冒险回看」,且 P-C7 裁决的代价(冒险中无回看)正是由它补偿 |
### P3 · 图鉴承接的内容范围与顺序(期三核心裁点)
**✅ 裁决(2026-10-06 用户令)**:案甲——敌人图鉴优先(06 在册条目承接),秘宝/奇物随后;奖励格图鉴只登记不激活。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲 | 敌人图鉴优先(06 在册 P2 条目「敌方技能图鉴/学习呈现」直接承接),秘宝/奇物随后 | 在册条目有先约,敌人是玩家信息需求最硬的一类 |
@@ -162,6 +173,8 @@
### P4 · 局内是否给生涯入口 / 生涯内是否放「去营地」跳转
**✅ 裁决(2026-10-06 用户令)**:案甲——均不放:局内只看暂停层,生涯纯只读零跳转。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 均不放:局内只看暂停层(卡③),生涯只在主菜单;生涯内纯只读零跳转 | 分工矩阵最干净;暂停层与生涯零重叠 |
@@ -170,6 +183,8 @@
### P5 · settlement_review_overlay.gd 遗留文件处置(实装期执行,本批只裁方向)
**✅ 裁决(2026-10-06 用户令)**:案甲——期二实装批复活承接(单局明细回看呈现载体,改挂生涯)。
| 案 | 内容 | 淘汰/保留依据 |
|---|---|---|
| 甲(推荐) | 期二实装批复活承接(作为单局明细回看的呈现载体,改挂生涯) | 现成件,结算明细的排版逻辑都在;复活成本远低于新画 |
@@ -203,6 +218,6 @@
1. design/gdd/06-待办清单.md「『生涯』界面——冒险中数据回看的唯一承接处」条(P-C7 裁决原文指路)
2. design/research/UI重设计原型v2落码-差异对照与改动计划-2026-10-04.md §七(P-C7 裁决记录出处)
3. game/presentation/views/battle_end_overlay.gd / battle_log_view.gd / settlement_review_overlay.gd(退役与遗留实态)
4. game/core/meta_progression.gd settle_adventure + save_manager.gd:39(跨局数据面与「无历史记录面」考证点)
4. game/core/meta_progression.gd settle_adventure + save_manager.gd:39-40/:316/:325-338(跨局数据面与 recent_summaries 现役面考证点)
5. design/gdd/06-待办清单.md「敌方技能图鉴 / 学习呈现」条(图鉴承接的在册先约)
```
@@ -0,0 +1,119 @@
# 研究-内容数据驱动扩展架构-2026-10-06
状态:调研+提案,**零代码修改**,待用户拍板。
问题原文(用户):「如果我们要对其物进行修改设计的话,是不是只要更改我们的配置文件就好了?如果是一些机制类的专长,也能够只改配置文件,不改动代码吗?我希望我们这里可以做得比较拓展一些……你可以学习一下各种支持mod扩展的游戏,他们是如何实现的。」
---
## 〇 结论(先答两问)
1. **改已有物品的数值/名字/稀有度/投放渠道 → 是,只改配置表就能生效**(所有内容族都已是 `.tres` 数据表,加载期校验,运行时通用读取)。
2. **给已有物品换一个全新效果行为 / 加一件带新效果的新物品 / 加机制类新专长 → 现状必须改代码**。因为「效果类型」是封闭枚举,每新增一个枚举值都要:改 schema 枚举 → 加一处 `match` 翻译分支 → 在结算代码里加消费点 → 在文案代码里加说明文字,共 3-4 处代码。
3. 项目里**已经有一个完全做到「只改配置」的范本:技能池**。`skills.tres` 加一行技能、`enemy.tres` 的 `pool` 里引用它(Boss 半血解锁只需 `unlock_hp_pct: 50` 字段),全链路零代码。差距是把专长/秘宝/令牌提到同等水平。
---
## 一 现状盘点:各内容族「改配置能走多远」
内容全部在 `game/data/tables/*.tres`,schema 在 `game/data/schemas/`,统一清单装载于 `game/core/config_db.gd:12-31`;表里没有任何回调/脚本路径,行为全部用封闭枚举字符串键+参数字典表达。表内数据与「配置」的分离没有问题,问题出在代码侧对数据的解释方式。
| 内容族 | 定义处 | 只改配置能做什么 | 必须改代码才能做什么 |
|---|---|---|---|
| 技能(技能池) | `skills.tres` + `enemy.tres` pool | **加新技能整件**(伤害/增益/妨害、权重、冷却、Boss半血解锁)——全链路数据驱动 | 新的技能大类(现仅 basic/damage/buff/debuff 四类) |
| 状态效果 | `status_effects.tres` | 加新状态行(技能/奖励格引用它) | 新的状态机制形态 |
| 专长(奇物·规则改写类) | `feats.tres`(27行) | 加「挂点已存在」的新专长:数值、稀有度、流派标签随写随生效;同挂点多件自动累加 | 新挂点(hook)=4处代码;现 23 挂点封闭(`feat_table.gd:36-67`) |
| 秘宝/同调件 | `treasure_items.tres`(13行) | 加「效果类型已存在」的新件(如又一个 3×3 显影件);改充能/占槽/解锁谓词 | 新效果类型=改枚举+执行分支;**被动件按物品 id 硬编码**(见二B) |
| 奇物令牌(属性/资源) | `adventure.tres` | 改配额/数值 | 新令牌种类(分发键=代码 match,`adventure_table.gd:84-114`) |
| 格面资源 | `reward.tres` | 加新资源行(percent 类经 `effect_id` 路由进状态系统) | 新格面行为 |
| 局外天赋树 | `meta_tree.tres`(33节点) | 数值/价格/前置/上限 | 新规则键(现仅 2 个规则键 wired,`battle_orchestrator.gd:261-264`) |
---
## 二 差距精确清单:效果行为硬编码在哪些代码位置
调查核证(file:line 均经抽查复核):
**A. 专长:两段式,翻译段硬编码。**
- 求值段(半通用):`_feat_flags_for` 对 23 个 hook 逐个 `match` 展开(`battle_orchestrator.gd:101-179`)。
- 消费段(硬编码):每个展开出的旗在结算代码里各有一处读取点——`damage_controller.gd` 13 处(rider_flat:253、nest_aura:257、round_dig:264、crack:276、shield:312、clamp:429-434、discount_shift:219-221、hit_trade:203/228、armor_roll_rewrite:209、spike:215/236 等);`battle_orchestrator.gd` 11 处(first_dig_spell:487、terrain_dig_double:519、flag_strike:537、dig_yield:604-615、chain_arrows:974-980 等)。
- 流派档位(≥2件/≥4件质变)硬编码在 `battle_orchestrator.gd:171-175`。
**B. 秘宝:主动件半通用,被动件按 id 硬编码。**
- 主动件:`use_treasure` 按 `effect_kinds` 通用分发(`battle_orchestrator.gd:648-666`)——这部分是好的;但混有按 id 的特判(`dig_charge` 积点闸,:643-647)。
- 被动件按件 id 硬编码:`venom_edge`(:248 → damage_controller.gd:225)、`luck_coin`(:249 → reward_economy.gd:195-207)、`dawn_order`(:272-273、:1098-1099)、`nest_counter`(:703-713)、`flag_burst`(:828-831)、`pick_refresh`(adventure_runner.gd:650)。
**C. 奇物令牌:** `_apply_curio_pick` 按 kind match(`adventure_runner.gd:412-449`)。
**D. 呈现文本硬编码(新内容会「无名无声」的直接原因):**
- 物品卡说明:`battle_narrator.gd:104-121`(令牌)、`:142-166`(专长逐 hook 文案)、`curio_interact_controller.gd:185-204`(秘宝只认 3 种 kind)。
- 无本地化/文本表:`display_name` 内联在 .tres 里(这本身没问题),但**效果说明文字**没有一处在数据行里,全在代码里。
**E. 基础设施(新词=代码,但这是合理边界):**
- 谓词表计数键 `COUNTER_KEYS`(`attunement_growth_table.gd:22`)、存档域(版本迁移 `save_manager.gd:50-57`)、渠道白名单(`adventure_runner.gd:757-763`,设计规格 `design/gdd/systems/冒险循环/奇物.md:200-217`)。
**F. 已经在做对的事(不需要改,是改造的地基):**
- 加载期校验+交叉校验悬空引用即致命(`config_db.gd:106-148`、`config_db_cross_validator.gd`);
- 行键白名单/零裸flat护栏(`treasure_item_table.gd:51-53`、`feat_table.gd:76-79`)——这些封闭校验是设计护栏,改造要保留它们,改的只是「枚举值↔代码分支」的绑定方式;
- MC 模拟器直接实例化真实的 battle_orchestrator(`monte_carlo.gd:20-22`)——**效果执行一旦数据化,模拟器自动看到新内容,调平衡不用双写**。
---
## 三 支持 mod 的成熟游戏是怎么实现的(官方文档查证)
| 游戏 | 内容加法 | 机制加法 | 机制要点 |
|---|---|---|---|
| Minecraft(数据包,官方) | 纯 JSON:配方/战利品表/进度/谓词/标签/附魔等几十类注册表 | 要写 Java mod | 战利品表=「条件对象+奖池条目」纯 JSON;进度=「触发器类型+条件+奖励」纯 JSON;谓词是跨系统复用的通用条件词汇 |
| Factorio(官方 mod API) | 数据阶段 prototype(Lua 表:物品/配方/实体)——官方内容本身就是 prototype | 要写运行阶段 Lua 脚本 | 数据/逻辑分两个阶段;运行期行为靠事件系统钩子 |
| RimWorld(官方 mod 体系) | XML Defs(defName 主键,加载期注册)+ XML 补丁操作改原版数据 | 要写 C# 程序集(Harmony 运行时补丁) | 纯数据 mod 能加特性/研究/动物等几乎所有「内容」;数据不够时才落代码,且补丁机制把改动隔离在数据层 |
(来源:minecraft.wiki/w/Data_pack、wiki.factorio.com/Modding、rimworldwiki.com/wiki/Modding——前两者已逐条核对原文,RimWorld 维基反爬只取到入口页,机制按通行记载表述。)
**四条共性,就是「改配置不改代码」的全部秘密:**
1. **内容=数据,机制=解释器。** 代码里只有一套通用的「效果类型+参数」解释器;每件内容是一行数据,声明自己是什么类型、带什么参数。
2. **游戏在稳定的时机对外喊一声(事件),内容声明「我在什么时机、什么条件下、发生什么效果」。** 时机词汇(开格/标旗/受击/击杀/轮末……)是封闭且稳定的,内容条目只是订阅者。
3. **条件是通用词汇,跨内容复用**(Minecraft 谓词、RimWorld 的条件类、我们已有的谓词表雏形)。
4. **加载期注册+校验闸兜底**:id 唯一、引用悬空、键出域,全部启动即报错——这一条我们已经在做。
5. **边界同样存在**:Minecraft 数据包加不了新机制,Factorio 的新行为也要写 Lua。mod 游戏不是「零代码」,而是**把「新机制」压缩成「往词汇表里加一个类型」(一次性、低频),让「新内容」完全数据化**(高频、零代码)。
---
## 四 改造方案(备选案全列)
### 案甲:最小修(清理性,约 1 天)
只消灭「按件 id 硬编码」(二B 被动件改造成 effect_kinds 通用分发)+ 把物品效果说明文字搬进数据行。
- 收益:秘宝族达到「同类件纯配置」;新件不再无名无声。
- 不解决:专长新挂点仍要改代码;令牌/树不变。
- 风险:低。纯重构+文案搬家,冒烟+MC 对拍可验。
### 案乙:效果类型统一+时机埋点(推荐,约 3-4 天,可分期)
把专长/秘宝/令牌统一到「**触发时机 + 条件 + 效果类型+参数**」的数据形态:
1. 定一份跨内容通用的**效果类型词汇表**(伤害修正/开单/资源授予/状态授予/改写/计数器……)——现 23 hook+12 kind 是这份词汇表的初稿素材,也是主要工作量所在(熔火之躯的积层反打、矿工重锤的命中交换这类需要词汇表有计数器/轮末/改写能力)。
2. 在结算段关键节点布**语义事件点**(开格/标旗/受击/击杀/轮末/Boss半血/使用道具……),一条内容行声明 `{on=时机, when=条件谓词, do=效果}`,由通用执行器解释。
3. 保留全部现有护栏:封闭词表、键白名单、悬空引用致命、零裸flat禁令照旧,只是校验对象从「枚举在 schema 里」变为「词汇表条目存在且已实现」。
4. MC 模拟器零改动自动受益(共用执行器)。
- 分期建议:①专长(23 hook 收敛)→②秘宝被动件并入 →③令牌/树规则键。每期独立冒烟可落籍。
- 风险:中。23 个消费点的等价性改写,需 MC 对拍锚+冒烟全绿兜底;触到 battle_orchestrator 历史脏件(惯例走 worktree 批)。
### 案丙:完整 mod 式(外挂脚本层,约 5 天以上)
案乙基础上允许数据行指向外挂 GDScript 效果脚本(Godot 支持运行时加载脚本),即真正意义上的第三方可扩展。
- 收益:任何行为都可外挂,词汇表不再是边界。
- 不建议现在做:导出安全、脚本沙箱、兼容矩阵、探针全覆盖都是额外工程;Alpha 前没有第三方 mod 需求,词汇表不够用时再加类型(案乙路径)成本远低于维护插件层。挂账待「mod 需求」立项再启。
**推荐:案乙,按 ①②③ 分期立项**(可并进现有 roadmap 排期,或作为迭代 17 候选卡)。
---
## 五 拍板点
1. **立项选择**:案甲(1天,只清秘宝)/ 案乙(3-4天,专长+秘宝+令牌全数据化,推荐)/ 案丙(挂账)。
2. **排期位置**:并入迭代 17 候选序列,还是单独立卡插队。
3. **案乙词汇表范围**:首批是否 23 hook+12 kind 全收敛,还是先收敛专长族试点后扩。
4. **文本表值化是否随批**(牵 UI 呈现,battle_narrator/curio_interact_controller 两处)。
---
## 六 附:顺带发现(非本议题,仅登记)
- 菜单开局路径 `main.gd:475` 未传 `attunement`/`tree_rules` 参数(营地装配后从主菜单开局可能丢同调装配/局外树规则;冒烟是直呼 runner 面故未拦住)——是否立项修复待用户令。
- relic 词族与 feat 词族命名统一已在 `design/gdd/06-待办清单.md:101` 在册,案乙动 feats.tres 时可顺路处理或明确避让。
+10 -2
View File
@@ -494,7 +494,7 @@ Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/a
---
## 2026-09-16 敌人技能池批(批 1+2+3 合并落地——设计权威 docs/proposal-skill-pool.md v1.0;文档面 v0.5/v0.11/v0.5/v0.6/v0.3/v0.4 同批)
## 2026-09-16 敌人技能池批(批 1+2+3 合并落地——设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0;文档面 v0.5/v0.11/v0.5/v0.6/v0.3/v0.4 同批)
**机制**:确定性出招剧本(行为环:拍枚举/环指针/同种锁步/heavy_multiplier)整体退役,改技能池 + 开轮摇号——每轮轮次开始排除冷却中技能、按行序逐敌摇定本拍动作(behavior_roll 封闭流,每敌子流 scope = spawn_index×1000000+摇号序),战斗段按技能行兑现(伤害技 = 三乘法链〔基线×倍率→d20 掷点→甲效→伏击后置→池乘区→max(1,·)〕,增益技 = 施放行 cast + 状态授予〔0 伤害不掷不折不兑伏击〕);两道闸 = 全技能各自冷却(普攻恒 0 锁死)+ 保底 M=4(连续 4 拍执行普攻 → 下拍必出特殊技、不受冷却限制);死亡即不动手改"摇定后兑现前死亡 → 作废不进账";拍结构保留(每结算每存活敌恰行动一次/行序/先作用后推进)。
@@ -514,7 +514,7 @@ Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/a
**实现决策登记(提案未定处的自行拍板,按封装纪律报告)**:① 保底 M 载体 = 技能表全局单字段 pity_threshold(不分敌种,难度曲线单旋钮);② 冷却"施放后连续 N 拍不可摇中"的实现 = 摇号按当前冷却值排除、递减在其后(与提案"递减→排除"的可摇集合逐拍恒等);③ 增益持续与技能冷却两计时器 = apply_effect duration_override 通道;④ 敌方防御池乘区落点 = 主角攻击 Σ三分量后(hero_offense 现行走普通分量直乘的切片现状不动——登记遗留);⑤ 摇号器类名 SkillLottery(core/skill_lottery.gd)。
## 2026-09-19 技能池新效应词汇批(用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0)
## 2026-09-19 技能池新效应词汇批(用户拍板——设计权威 proposal-status-vocabulary.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 词汇表/增益状态.md〕 v1.0)
**三词收敛两词**:妨害技(debuff 新类型)+ 必中附加分量(rider_mult,"固定值伤害"改形);多段命中经用户拍板退役(无防御磨损体系,无对照机制)。**实装面 = 仅 L2 Boss 蛛化卓尔精灵,其余敌种不动**:
- 毒爆 venom_burst + `rider_mult = 0.75`——必中毒分量 = max(1, floor(atk × 0.75))(atk 开战掷定 2–4 → 毒 1–3 点),后置加法、必中全额、不进乘区不出暴击;伤害行 payload 增 `rider` 键 + 行文本「+附加N(必中)」。
@@ -548,3 +548,11 @@ Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/a
**结账时机双模式(2026-09-24 用户三裁决之二三)**:目标 = 结账时刻照规则看现场解析(最前存活敌 / 主角 / 全体存活敌),开单不冻结对象;现行 = 段界结账(授予段尾 / 清图批同步点 / 战斗段尾统一兑现),开单即结保留为回切结构位(控制器 policy 常量一行切回=逐位还原迁移前行为)。同一输入两模式结果可不同(兑现时机语义差异),历史基线读数自本批以段界结账口径为准(重测归曲线调参批)。
**验证**:冒烟 557 项 0 失败双模式全绿三闸过;A/B 对拍探针四配置(L1/L2 × 双种子)两模式各自同种子逐位确定、四配置全部真实分岔(行数两两恒等、纯次序位移——分岔面 = 伤害行攒批位移与治疗满血判定时机,符合段界结账语义);三场景探针全 PASS。设计权威 = 战斗结算.md v0.24「伤害单据与伤害控制器」节。
## 2026-10-06 地图伤害账殿后批(案C,用户裁——「主角先手」歧义质询触发;设计权威 = 战斗结算.md v0.26)
**裁决**:每轮结算内三者顺序定死 = ①授予段兑非伤害账(资源/增益/治疗/行动点/GP/警觉)→ ③战斗段「主角先基础攻击 → 敌人按生成序逐个还手 → 地图伤害账殿后」→ ④衰减 → ⑤判定。授予段不再当场兑付任何伤害——全部伤害形态单据(爆裂/直伤/反噬/地形变异/战旗军规/熔火反噬/惊巢反制/魔能共鸣/清障炸药等)暂存,战斗段怪物还手后按授予段事件序补提交统一结账;主角死于敌方还手 → 暂存单整体不兑,逐单留「未生效(主角已倒下)」行(载荷 forfeit=hero_down)。
**切片落点**:`battle_orchestrator.gd` 暂存闸 `_defer_board_damage`/`_deferred_board` + `_submit` 案C 分流(sync 同闸——清图批一致延后)+ `_outcome_of`(暂存单按「将兑付」回报——完美第二份/高光份数依据开单时点事实)+ 授予段四处直提改走闸 + 战斗段末补提交块(死亡守卫+留痕);授予段界 flush 保留(对空队 no-op 防御位);`smoke_all.gd` 行相位分类器换代(damage 恒战斗段/reward_ineffective 按 forfeit 分流)+ 先手断言收紧(「存在或授予段终局」→「必存在」)+ 新增案C 段内序断言(地图账不得先于主角先手或插入敌方还手中间)。
**验证**:冒烟 783 项 0 失败三闸过 + run_all 17 套全绿 + probe_gate(ui_input/ui_struct/ui_contrast/--click 行为走查)全绿、残留 0。**旧行为 MC 锚全数作废**(死亡短路语义变化:授予段伤害不再能致死短路先手;读数重采归数值批)。
+43 -21
View File
@@ -35,19 +35,19 @@ var last_round_end: Dictionary:
var _settlement_consumed := false # AC-14 门:notify_settlement_done 消费后才受理 round_start
var _next_round_mode := "" # 调试观测量(同板续轮 / 换新图)
var _pending_ap_delta := 0 # 下轮行动点修正排队(格面资源八型批 2026-09-20——action 型 ±1 排队,轮开始兑现后清零)
# 蓄力流运行态(迭代 12 T5——relic 件注入面;false=关着零扰动):
# feat_ap_carry=整备军备(轮末剩余 AP 转蓄力层替代 RAP 转存——cleared 作废口径改写的停手侧承载);
# feat_dig_extra=深挖钻头付费开掘对价(R4 甲非信息税形态;2026-10-04 试玩缺陷修复——对价挂付费
# 开掘侧:AP 富余时挖掘付全价 1+extra 积付费计数、AP 不足时降级只付基础 1 照常开格不积计数——
# 原「持有期所有挖掘无条件 +1」实现把对价错挂成普通挖掘税,AP=1 锁死开格);charge_layers=蓄力层账本。
var feat_ap_carry := false
var feat_dig_extra := 0
# 蓄力流运行态(迭代 12 T5 → 内容数据驱动扩展批 T3 换代:旧 feat_ap_carry/feat_dig_extra 注入旗
# 退役——转蓄力=round_end grant_ap(mode:transfer) 订阅(finish_round_stop 定夺)、深挖对价=dig_paid
# counter_spend 订阅(request_dig 施加面);charge_layers=蓄力层账本)
var _charge_layers := 0
var charge_layers: int:
get: return _charge_layers
var _deep_paid_count := 0
var deep_paid_count: int:
get: return _deep_paid_count
# 效果引擎(内容数据驱动扩展批 T1——dig_paid/charge_full 发射面;round_end 转存决策面)
var _fx: EffectEngine = null
var _last_stop_ap := 0 # 停手侧剩余 AP 记账(转存决策移至 round_end 发射点——grant_ap(transfer) 订阅定夺)
func set_fx(fx: EffectEngine) -> void:
_fx = fx
func _init(db_ref: ConfigDb) -> void:
@@ -87,17 +87,25 @@ func try_spend(action_kind: String) -> bool:
# 排雷玩法 挖掘专用:chain_size = 连锁附加格数(不含首格);clears_map = 本次动作后全图安全格开完。
# 深挖钻头付费开掘(2026-10-04 缺陷修复——对价挂付费侧):AP 富余(≥基础+extra)时本动作付全价
# 并积付费开掘计数(orchestrator 深层产出配额取数面);AP 不足全价时**降级只付基础 1 照常开格**、
# 不积计数——持有钻头永不锁死普通挖格(散件保底 B-2)。
# 深挖钻头付费开掘(内容数据驱动扩展批 T3——dig_paid counter_spend 订阅施加面,2026-10-04 缺陷
# 修复口径不变):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎
# 计数器=授予段追加产出配额取数面);AP 不足全价时 fallback 降级只付基础 1 照常开格、不积计数
# ——持有钻头永不锁死普通挖格(散件保底 B-2)。
func request_dig(chain_size: int, clears_map: bool) -> bool:
if _phase != Phase.ACTIVE:
_reject("phase")
return false
var cost := _cost("dig")
if feat_dig_extra > 0 and _ap >= cost + feat_dig_extra:
cost += feat_dig_extra
_deep_paid_count += 1
# dig_paid 发射+施加(内容数据驱动扩展批 T3——付费开掘发起、动作经济闸收对价前:
# counter_spend 命中=尝试加收对价并积计数;资源不足走 fallback/耗尽即止=只付常规基础对价)
if _fx != null:
for h in _fx.dispatch("dig_paid", {"ap_cost": cost, "ap_surplus": _ap - cost}):
if String(h.get("kind", "")) != "counter_spend":
continue
var extra := int(h.get("value", 1))
if _ap >= cost + extra:
cost += extra
_fx.counter_add(String(h.get("counter_id", "")), 1)
if _ap < cost:
_reject("resource_face")
return false
@@ -137,21 +145,35 @@ func _spend_and_arbitrate(action_kind: String, clears_map: bool) -> bool:
# 停手:剩余 AP 1:1 转存 RAP;行动经济 直发 stopped 路径 round_end(双发射源)。
# 整备军备改写(迭代 12 T5——feat_ap_carry=true 时剩余 AP 转蓄力层〔上限 3〕替代 RAP 转存:
# 「不动也是行动」——cleared 作废口径改写的停手侧承载;cleared 分支 AP 恒清零维持既有作废语义)
# 「不动也是行动」——cleared 作废口径改写的停手侧承载;cleared 分支 AP 恒清零维持既有作废语义)。
# 内容数据驱动扩展批 T1:本方法改记账制——剩余 AP 存 _last_stop_ap 后清零,转存决策移至
# round_end 发射点 finish_round_stop(grant_ap(mode:transfer) 订阅定夺;双轨期旧旗 feat_ap_carry
# 并行生效,行为与迁移前逐位一致)。
func request_stop() -> bool:
if _phase != Phase.ACTIVE:
_reject("phase")
return false
if feat_ap_carry:
_charge_layers = mini(3, _charge_layers + _ap)
else:
_rap += _ap
_last_stop_ap = _ap
_ap = 0
_finish_round("stopped", "same_board")
round_end_stopped.emit({"path_tag": "stopped", "continuation_hint": "same_board"})
return true
# 轮末停手转存决策(round_end 发射点调用——编排器授予段尾):transfer=true=剩余 AP 转蓄力层
# (上限 3,整备军备面);false=1:1 转存 RAP(缺省)。非停手轮(cleared/耗尽)_last_stop_ap=0
# 两分支均零操作。转蓄后达上限的沿发 charge_full(R6 框架先行——现无订阅者)。
func finish_round_stop(transfer: bool) -> void:
if transfer:
var prev_layers := _charge_layers
_charge_layers = mini(3, _charge_layers + _last_stop_ap)
if _fx != null and _charge_layers >= 3 and prev_layers < 3:
_fx.dispatch("charge_full", {"layers": _charge_layers})
else:
_rap += _last_stop_ap
_last_stop_ap = 0
# 轮内刷新(2026-09-12 方案 A 用户拍板;等待期通道 2026-09-15 用户拍板整体移除):唯一入口 =
# Active 相位——仅扣 RAP,相位与 AP 均不动。刷新不打断轮次、不触发结算;换图编排归 战斗结算
# (retire + install 立即执行,玩家同轮继续挖新图)。决策主体 = 玩家(经 HUD框架发起)纪律不变。
+49 -20
View File
@@ -75,6 +75,7 @@ var _treasure_unlocked := {} # aux 解锁门控集(迭代 7
var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——params.attunement 接收面,start_level 外下传 LevelRunner)
var _attune_refresh_x := 0 # 刷新件余量(迭代 11 第①批 T5b P1 甲——每碰三选一重置=X 表值;优先消耗、不结转)
var _attune_refresh_y := 0 # Y 冒险周期池(开局参数面注入,用完即无——营地升级行表值)
var _curio_paid_refreshes := 0 # 本次停点已付费刷新次数(2026-10-06 用户令对齐商店 MC-1——GP 刷新价曲线输入,随停点创建清零=与商店进店清零同构)
var attune_charges := {} # 同调主动件冒险充能账本(迭代 11 第①批 T6——跨关卡共享 dict;settlement use_treasure 扣减直改同引用;断点随 attunement_charges 键入档)
var _save_manager = null # 断点承载注入(迭代 8 卡①——null = 不写断点;模拟/冒烟缺省)
var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递)
@@ -424,19 +425,15 @@ func _apply_curio_pick(kind: String, tier: String, value: int, feat_id: String =
_feats.append(feat_id)
_curio_taken["relic"] = int(_curio_taken.get("relic", 0)) + 1
return true
# 加算形态路由(内容数据驱动扩展批 T5——match 收敛进效果类型:属性值提升四类走
# adventure_table.CURIO_APPLY_ROUTES 声明路由(bonus 落点键),加新加算类令牌零代码)
var sink := db.adventure.curio_apply_route(kind)
if sink != "":
bonus[sink] = int(bonus.get(sink, 0)) + value
_curio_taken[kind] = int(_curio_taken.get(kind, 0)) + 1
return true
# 通道面(副作用形态——显式分支)
match kind:
"attack":
bonus["atk"] = int(bonus.get("atk", 0)) + value
_curio_taken["attack"] = int(_curio_taken.get("attack", 0)) + 1
"max_hp":
bonus["max_hp"] = int(bonus.get("max_hp", 0)) + value
_curio_taken["max_hp"] = int(_curio_taken.get("max_hp", 0)) + 1
"armor":
bonus["armor_class"] = int(bonus.get("armor_class", 0)) + value
_curio_taken["armor"] = int(_curio_taken.get("armor", 0)) + 1
"ap":
bonus["ap"] = int(bonus.get("ap", 0)) + value
_curio_taken["ap"] = int(_curio_taken.get("ap", 0)) + 1
"gp":
if _runner != null:
_runner.grant_curio_gp(value)
@@ -569,6 +566,7 @@ func node_curio_candidates() -> Dictionary:
func present_node_curio(candidates: Array, treasure_detail: Array = []) -> void:
_reset_refresh_x() # 迭代 11 第①批 T5b——碰三选一重置 X 余量(不结转)
_curio_paid_refreshes = 0 # 付费刷计数随停点清零(对齐商店进店清零——2026-10-06)
_node_curio_pending = {"candidates": candidates.duplicate(true), "aux_detail": treasure_detail.duplicate(true)}
@@ -647,7 +645,14 @@ func _seed_attune_charges() -> void:
# 达上限剔牌/掷定前置直显;停点可中断)----
func _attune_refresh_x_total() -> int:
return int(db.treasure_item_row("pick_refresh").get("magnitude", 0)) if _attunement.has("pick_refresh") else 0
# 内容数据驱动扩展批 T4——按 id 特判拆除:kind 分发查询(装配集内 effect_kinds 含 bonus_refresh
# 的行 magnitude 合计;刷新件类加件零 id 分支)
var total := 0
for iid_v in _attunement:
var arow: Dictionary = db.treasure_item_row(String(iid_v))
if (arow.get("effect_kinds", []) as Array).has("bonus_refresh"):
total += int(arow.get("magnitude", 0))
return total
func _reset_refresh_x() -> void:
@@ -667,30 +672,53 @@ func node_curio_pending_state() -> Dictionary:
}
# 三选一刷新(组合根唯一调用口;无停点/无余量 false 零副作用)。通关停点重抽后重发
# 三选一刷新(免费位 X/Y——组合根唯一调用口;无停点/无余量 false 零副作用)。通关停点重抽后重发
# curio_choice_presented(呈现层重建卡片+刷新余量);节点停点由组合根读 node_curio_pending_state 重 present。
func refresh_curio() -> bool:
if _attune_refresh_x <= 0 and _attune_refresh_y <= 0:
return _refresh_curio_common(false)
# 三选一 GP 付费刷新(2026-10-06 用户令对齐商店 MC-1——免费位 X/Y 用尽后转付费,同旋钮同曲线同钱包;
# 组合根先经 curio_stop_pending+钱包支出再调,本口只做计数与重抽)。池规则全保留——不放回/达上限剔牌/掷定前置直显。
func refresh_curio_paid() -> bool:
return _refresh_curio_common(true)
# 本次 GP 付费刷新价(与商店货架刷新同源:ceil(基价 × 曲线^本次停点已付费刷)——读同两个调参旋钮,单点调参)
func curio_refresh_gp_cost() -> int:
return int(ceil(float(db.adventure.shop_refresh_cost_base)
* pow(db.adventure.shop_refresh_cost_curve, float(_curio_paid_refreshes))))
# 三选一停点在途谓词(付费路径扣费前置校验——无停点禁扣钱,防空转烧钱包)
func curio_stop_pending() -> bool:
return not _curio_pending.is_empty() or not _node_curio_pending.is_empty()
func _refresh_curio_common(paid: bool) -> bool:
if not curio_stop_pending():
return false
if not _curio_pending.is_empty():
if paid:
_curio_paid_refreshes += 1
else:
if _attune_refresh_x <= 0 and _attune_refresh_y <= 0:
return false
if _attune_refresh_x > 0:
_attune_refresh_x -= 1
else:
_attune_refresh_y -= 1
if not _curio_pending.is_empty():
var cands: Array = _draw_curio_candidates("level_clear")
_curio_pending["candidates"] = cands.duplicate(true)
_curio_pending["aux_detail"] = _last_draw_treasure.duplicate()
var payload: Dictionary = (_curio_pending.get("payload", {}) as Dictionary).duplicate(true)
payload["candidates"] = cands
payload["aux_detail"] = _last_draw_treasure.duplicate()
payload["refreshed"] = true # 重发载荷带标——呈现层直落选择面,不再重开胜利总结面(2026-10-06)
curio_choice_presented.emit(payload) # 同信号重 present(零自动推进契约不破——停点仍在途)
_snapshot_breakpoint()
return true
if not _node_curio_pending.is_empty():
if _attune_refresh_x > 0:
_attune_refresh_x -= 1
else:
_attune_refresh_y -= 1
var cands2: Array = _draw_curio_candidates("reward_node")
_node_curio_pending["candidates"] = cands2.duplicate(true)
_node_curio_pending["aux_detail"] = _last_draw_treasure.duplicate()
@@ -954,6 +982,7 @@ func _on_level_finished(payload: Dictionary) -> void:
# 置位先于 emit(信号同步派发——处理器内立即确认时 _pending_next_level 必须已就位)
_pending_next_level = true
_reset_refresh_x() # 迭代 11 第①批 T5b——碰三选一重置 X 余量(不结转)
_curio_paid_refreshes = 0 # 付费刷计数随停点清零(对齐商店进店清零——2026-10-06)
var pick_payload: Dictionary = {
"level_index": level_index,
"candidates": _draw_curio_candidates("level_clear"), # T4 渠道白名单——关底 Boss 击败=通关渠道只出专长
+332 -248
View File
@@ -14,7 +14,10 @@
# 伤害管线单据化批(2026-09-24 用户三裁决,06 台账 148):伤害兑付全部收口 伤害控制器(DamageController
# 单点管线)——本类六调用点(主角先手/敌方伤害技/棋盘克制直伤/群伤/反噬/地形变异)退化为开单点
# (流程决定何时开单给谁开单;单据怎么算归控制器)。结账时机开关在控制器 policy:IMMEDIATE(A=开单
# 即结,逐位等价迁移前行为——回切位)/ SEGMENT(B=攒批到段界 flush:授予段尾〔含清图批前〕+ 战斗段尾)。
# 即结,逐位等价迁移前行为——回切位)/ SEGMENT(B=攒批到段界 flush:战斗段尾统一兑现)。
# 地图伤害账殿后批(案C 2026-10-06 用户裁——「主角先手」歧义质询触发):授予段不再当场兑付任何伤害——
# 全部伤害形态单据经 _submit 暂存闸入 _deferred_board(保授予段事件序),战斗段「主角先手→逐敌还手」后
# 补提交统一结账;主角死于敌方还手 → 暂存单整体不兑,逐单留「未生效(主角已倒下)」行(forfeit=hero_down)。
# 死亡事件 = 单位容器 unit_died(单位自行宣布)→ 控制器作废该敌未结单据〔死亡即不动手〕/ 主角死终止兑付。
# 切片登记:① 事件总线载体 = 直连信号(实现期 ADR 项,provisional)② Waiting 相位刷新通道 2026-09-15 用户拍板整体
# 拆除(仅 Active 挖掘期受理)③ 效果行协议 = 授予段逐 grant 行 + 增益/减益段续存实例组合行。
@@ -63,6 +66,8 @@ var _facts_reveals: Array[Dictionary] = []
var _facts_flags: Array[Dictionary] = []
var _facts_path := ""
var _settling := false
var _defer_board_damage := false # 案C 暂存闸(2026-10-06 用户裁:地图奖励伤害兑付迁战斗段末——怪物还手后)
var _deferred_board: Array[Dictionary] = [] # 授予段暂存伤害单据(保授予段事件序;战斗段怪物还手后按序补提交统一结账)
var _refresh_used_this_round := 0 # 每轮刷新计数(Active 相位合计,兜底上限 = ActionEconomyTable.refresh_cap_per_round)
var _board_seq := 0 # 板序号(本战斗第几张板——快照归因用)
var _board_from_midround_refresh := false # 装板 provenance:轮内刷新换来的图 = true(清图奖励守卫——刷新图不发清图奖励)
@@ -70,113 +75,65 @@ var _flag_consumed := {} # 兑付资格以雷格实例为键
# 同调装配运行态(迭代 11 第①批 T5——begin_battle 经 enc.attunement 注入;off=空集全部效果零扰动)
var attunement: Array = [] # 装备中同调件 item_id 集
var _attune_charges_ref: Dictionary = {} # 充能账本共享引用(迭代 11 第①批 T6——use_treasure 消费直改)
var _attune_bank := 0 # 掘进蓄能积点(battle 域——每 charge_n 安全格 +1 点)
var _attune_safe_seen := 0 # 掘进蓄能 battle 域安全开格计数
# 特性运行态(迭代 12 T2——relic 持有集经 enc.feats 注入;求值旗注 damage_controller.feat_flags;
# 魔矢每战首次计数 battle 域。空集=零扰动)
var _attune_safe_seen := 0 # 掘进蓄能 battle 域安全开格计数(进度呈现取数面;积点账本=效果引擎计数器 dig_charge_bank——行 triggers counter_spend 订阅同账本)
# 特性运行态(内容数据驱动扩展批 T3——relic 持有集经 enc.feats 注入:效果行为=数据行 triggers 经
# 效果引擎分发;魔矢每战首次计数 battle 域。空集=零扰动)
var _feat_first_dig_used := false
var _feat_combo := 0 # 矿脉直觉连击计数(battle 域——safe +1/mine 清零)
var _feat_deep_given := 0 # 深挖钻头本轮已追加份数(battle 域——v2 本格双份制:safe 事件按付费数上限)
var _feat_paid_at_round_start := 0 # 轮初付费计数快照(v2——本轮付费次数=当前值−快照)
var _feat_magma_layers := 0 # 熔火之躯积层(battle 域——受地形伤 +1,轮末反打清零)
# 效果引擎(内容数据驱动扩展批 T1——发布订阅解释器;begin_battle 从持有集/装备集重建订阅。
# T3 起施加面全量切换:发射点 dispatch 返回命中,发射点按组合规则施加——旧 feat_flags 旗注入消亡)
var _fx: EffectEngine
# 事件发射薄面(16 发射点统一入口——订阅空=零循环零扰动;确定性同步分发零 RNG)
func _fx_emit(event: String, payload: Dictionary) -> Array:
if _fx == null:
return []
return _fx.dispatch(event, payload, Callable(self, "_fx_fact"))
# round_start 发射+施加(内容数据驱动扩展批 T3——grant_ap mode:queue=当轮入队,行动经济轮切换
# 即兑现;计数器 round_start 重置点在 dispatch 内生效。调用点两处:begin_battle 首轮 / 轮始段续轮)
func _emit_round_start() -> void:
for h in _fx_emit("round_start", {"round": round_index}):
if String(h.get("kind", "")) == "grant_ap" and String(h.get("mode", "")) == "queue":
action_economy.queue_ap_delta(int(h.get("value", 0)))
# 补充事实面(fact 取值第二优先源——payload 未携带的运行态读数)
func _fx_fact(fact: String):
match fact:
"charge_layers":
return action_economy.charge_layers
"nest_count":
var n := 0
for eff in _status_effects.query_active("enemy"):
if String(eff.effect_id) == "weaken":
n += 1
return n
"round_index":
return round_index
"flags_count":
var hits_n := 0
for fevt in _facts_flags:
if bool(fevt.get("hit", false)):
hits_n += 1
return hits_n
return null
func _attune_has(item_id: String) -> bool:
return attunement.has(item_id)
# 装备件表值读取(magnitude/effective_rounds 等——TreasureItemTable 行;未装配不读表)
# 装备件表值读取(charge_n 等——TreasureItemTable 行;未装配不读表。magnitude 读数面随 T4
# 秘宝订阅迁移退役——行值经 value_from 在 rebuild 定影,零运行期按件取值)
func _attune_row(item_id: String) -> Dictionary:
return db.treasure_item_row(item_id) if _attune_has(item_id) else {}
func _attune_mag(item_id: String) -> int:
return int(_attune_row(item_id).get("magnitude", 0))
# 特性求值(迭代 12 T2——持有集 × feat_table → damage_controller.feat_flags 注入面):
# rider_flat = Σ rider 件 value(奥术余烬 +1 / 魔能共鸣 +2);magic 档一(≥2 件)rider +1、
# 档二(≥4 件)rider 可暴击;clamp 两件直调键;first_dig_spell 旗(魔能共鸣第二效果——魔矢值
# = 件 effects.value)。空集/空表 = 零旗零扰动。
func _feat_flags_for(feat_ids: Array) -> void:
var flags: Dictionary = {}
if not feat_ids.is_empty() and db.feats != null and not db.feats.rows.is_empty():
var hooks := FeatsEngine.hooks_for(feat_ids, db.feats)
var tiers := FeatsEngine.tiers_for(feat_ids, db.feats)
for h in hooks:
var hook: String = String(h.get("hook", ""))
var fx: Dictionary = h.get("effects", {}) as Dictionary
match hook:
"hero_attack_rider":
flags["rider_flat"] = int(flags.get("rider_flat", 0)) + int(fx.get("value", 0))
"clamp_modifier":
# clamp 方向按件 note 词分流(魔网=magic-vs-magic 罚修正 / 湛蓝=magic-vs-heavy 加成)
if String(fx.get("polarity", "")) == "magic_vs_magic":
flags["clamp_magic_magic"] = int(flags.get("clamp_magic_magic", 0)) + int(fx.get("value", 0))
elif String(fx.get("polarity", "")) == "magic_vs_heavy":
flags["clamp_magic_heavy"] = int(flags.get("clamp_magic_heavy", 0)) + int(fx.get("value", 0))
elif String(fx.get("polarity", "")) == "pierce_vs_light":
flags["clamp_pierce_light"] = int(flags.get("clamp_pierce_light", 0)) + int(fx.get("value", 0))
"first_dig_spell":
flags["first_dig_spell"] = true
flags["spell_value"] = int(fx.get("value", 0))
"flag_resource":
flags["flag_resource_extra"] = int(fx.get("value", 0))
"nest_aura":
flags["nest_aura_value"] = int(fx.get("value", 0))
"flag_all_hit":
flags["flag_all_hit_mult"] = int(fx.get("value", 0))
"flag_strike":
flags["flag_strike_value"] = int(fx.get("value", 0))
"kill_overflow":
flags["kill_overflow"] = true
"dig_count_segments":
flags["chain_value"] = int(fx.get("value", 0))
flags["chain_cap"] = int(fx.get("cap", 2))
"roll_discount":
flags["discount_shift"] = int(fx.get("value", 0))
"round_dig_bonus":
flags["round_dig_value"] = int(fx.get("value", 0))
flags["round_dig_cap"] = int(fx.get("cap", 5))
"hit_trade":
flags["hit_trade_atk"] = int(fx.get("trade_atk", 0))
flags["hit_trade_hit"] = int(fx.get("trade_hit", 0))
"armor_roll_rewrite":
flags["armor_roll_rewrite"] = int(fx.get("value", 0))
"heavy_debuff":
flags["crack_value"] = int(fx.get("value", 0))
"dig_yield_mult":
# 开格产出乘区族(贪婪矿灯/矿脉直觉/赌徒的血签——正负双向,同 hook 累加)
flags["dig_yield_pos_mult"] = int(flags.get("dig_yield_pos_mult", 0)) + int(fx.get("mult", 0))
flags["dig_yield_neg_mult"] = int(flags.get("dig_yield_neg_mult", 0)) + int(fx.get("cost_mult", 0))
if int(fx.get("cap", 0)) > 0:
flags["combo_cap"] = int(fx.get("cap", 0)) # 矿脉直觉连击上限
"deep_dig":
flags["deep_dig_cost"] = int(fx.get("ap_cost", 0))
flags["deep_dig_cap"] = int(fx.get("cap", 4))
"ap_carry":
flags["ap_carry_value"] = int(fx.get("value", 0))
"charge_shield":
flags["shield_per_layer"] = int(fx.get("shield_per_layer", 0))
"charge_spike":
flags["spike_mult"] = int(fx.get("value", 0))
"terrain_refund":
flags["terrain_refund"] = int(fx.get("value", 0))
"terrain_dig_double":
flags["terrain_dig_double"] = int(fx.get("value", 0))
"flag_neutralize":
flags["flag_neutralize"] = int(fx.get("value", 0))
"variant_counter":
flags["variant_counter_value"] = int(fx.get("value", 0))
var mt := int(tiers.get("magic", 0))
if mt >= 1:
flags["rider_flat"] = int(flags.get("rider_flat", 0)) + 1 # 档一质变(≥2 件):rider +1(provisional)
if mt >= 2:
flags["rider_crit"] = true # 档二质变(≥4 件):rider 可暴击(crit 时乘暴击倍率)
_damage.feat_flags = flags
# 蓄力流/深挖钻头 action_economy 注入(求值即注入——冒烟直呼 _feat_flags_for 同面生效)
action_economy.feat_ap_carry = int(flags.get("ap_carry_value", 0)) > 0
action_economy.feat_dig_extra = int(flags.get("deep_dig_cost", 0))
# 特性求值(内容数据驱动扩展批 T3——_feat_flags_for 挂点求值退役:效果行为=数据行 triggers 订阅,
# 效果引擎 dispatch 分发;旧 23 hook 枚举与旗注入消亡。流派档位质变=FeatsEngine 纯函数求值
# (档位机制本身系引擎基建非内容效果),两运行态注伤害控制器:档一 rider+1 / 档二 rider 可暴击)
var _flag_miss_seen := {} # 标旗未中行去重(每安全格实例一次)
var _perfect_hit_true := 0 # 板级完美排雷计数(install 重置)
var _perfect_hit_false := 0
@@ -186,6 +143,7 @@ var _hero_atk := 0 # 主角攻击基值快照(encounte
func _init(db_ref: ConfigDb, rng_ref: RngServiceCore) -> void:
db = db_ref
rng = rng_ref
_fx = EffectEngine.new(db_ref)
_board_generator = BoardGenerator.new()
action_economy = ActionEconomy.new(db)
minesweeper = MinesweeperRules.new(db, action_economy)
@@ -194,6 +152,9 @@ func _init(db_ref: ConfigDb, rng_ref: RngServiceCore) -> void:
_reward_economy = RewardEconomy.new(db, rng)
_damage = DamageController.new(db, rng, _enemy_system, _status_effects)
_damage.emit_row_cb = _emit_row # 行协议归属本类(9 类行协议 + 来源断言不外泄)
_damage.set_fx(_fx) # 效果引擎注入(attack_commit/clamp_check/armor_roll/kill/damage_taken 发射面)
action_economy.set_fx(_fx) # dig_paid/charge_full 发射面
_reward_economy.set_fx(_fx) # reward_roll 发射面
minesweeper.cell_revealed.connect(_on_cell_revealed)
minesweeper.flag_judged.connect(_on_flag_judged)
minesweeper.round_end_board.connect(_on_round_end)
@@ -243,38 +204,44 @@ func begin_battle(enc: Dictionary) -> bool:
# 伤害控制器、偏运 N 注入地图战斗资源——均须先于首板 install)
attunement = (enc.get("attunement", []) as Array).duplicate()
_attune_charges_ref = enc.get("attune_charges", {}) # 共享 dict 引用(level/adventure 同账本——use_treasure 扣减直改)
_attune_bank = 0
_attune_safe_seen = 0
_damage.attune_venom = _attune_mag("venom_edge") if _attune_has("venom_edge") else 0
_reward_economy.luck_bias = _attune_mag("luck_coin") if _attune_has("luck_coin") else 0
# 特性运行态注入(迭代 12 T2 魔法流——enc.feats 携带持有集;FeatsEngine 求值后注伤害控制器
# feat_flags;空集/空表=零扰动。魔矢每战首次开格计数同步归零)
_feat_flags_for((enc.get("feats", []) as Array))
# 淬毒/偏运注入拆除(内容数据驱动扩展批 T4——两件被动改 triggers 订阅行:淬毒=clamp_check
# modify 窗口、偏运=reward_roll bias_rewards;value 行字段 value_from 定影,零 begin_battle 注入)
# 特性运行态(内容数据驱动扩展批 T3——enc.feats 携带持有集:效果行为=数据行 triggers 经效果
# 引擎分发;流派档位=FeatsEngine 纯函数求值两运行态注伤害控制器。魔矢每战首次开格计数同步归零)
var feat_ids: Array = enc.get("feats", []) as Array
if not feat_ids.is_empty() and db.feats != null:
var tiers: Dictionary = FeatsEngine.tiers_for(feat_ids, db.feats)
var mt := int(tiers.get("magic", 0))
_damage.rider_tier_bonus = 1 if mt >= 1 else 0
_damage.rider_tier_crit = mt >= 2
else:
_damage.rider_tier_bonus = 0
_damage.rider_tier_crit = false
_feat_first_dig_used = false
_feat_combo = 0
_feat_deep_given = 0
_feat_paid_at_round_start = 0
_feat_magma_layers = 0
# 树 rule 键消费(迭代 12 T10——Fork 激活侧 effects;真实接线首期两键:先手压制=战斗首轮
# AP+1(queue_ap_delta——先手压制语义)/稳健拓荒=敌方攻击减 1(伤害控制器 flags bulwark);
# 其余 rule 键=stat 面投影不入战斗(T8 表内容 provisional 口径披露))
# 树 rule 键消费(迭代 12 T10 → 内容数据驱动扩展批 T3 换代:Fork 激活侧效果=效果引擎合成
# 订阅(rebuild 注入——round_start 首轮 AP+1 / damage_taken 减伤+1),旧直调拆除。其余 rule 键
# =stat 面投影不入战斗(T8 表内容 provisional 口径披露))
var tree_rules: Array = enc.get("tree_rules", []) as Array
if tree_rules.has("posture_first_strike"):
action_economy.queue_ap_delta(1)
_damage.feat_flags["bulwark"] = 1 if tree_rules.has("posture_bulwark") else 0
# 效果引擎订阅重建(内容数据驱动扩展批 T1——每战从持有集/装备集重建,中途获得下一战生效;
# 树规则合成订阅同面装载。装载序=feats 表序→treasure 表序→树规则,写死保种子复放)
_fx.rebuild(feat_ids, attunement, tree_rules)
# 迭代 10 奖励重构批——跨冒险行动点加成轴(统一冒险加算区第四轴):经排队修正通道兑现
# 「每场战斗开始首轮 AP +加成值」(queue_ap_delta = 下轮开轮基线加算、notify_round_start 兑现后
# 清零——首轮即消费,后续轮次不重复兑现;语义锚 = 行动经济 GDD「跨冒险行动点加成轴」节)
var ap_bonus: int = int(enc.get("hero_ap_bonus", 0))
if ap_bonus > 0:
action_economy.queue_ap_delta(ap_bonus)
# 工兵晨令(迭代 11 同调批 T5——前 effective_rounds 轮每轮 +1 AP;首轮在此入队,后续轮在轮始段续队)
if _attune_has("dawn_order"):
action_economy.queue_ap_delta(_attune_mag("dawn_order"))
# 工兵晨令直调拆除(内容数据驱动扩展批 T4——round_start grant_ap(mode:queue) 订阅行承载,
# when round_index ≤ effective_rounds 行字段 value_from 定影;发射位先于轮切换=当轮兑现)
# round_start 发射+施加(内容数据驱动扩展批 T3——发射位先于行动经济轮切换:树规则 grant_ap
# mode:queue 当轮入队、notify_round_start 即兑现(先手压制=首轮 AP+1 语义锚,与迁移前
# begin_battle 直调 queue_ap_delta 逐位一致);计数器 round_start 重置点同点生效)
round_index = 1
_emit_round_start()
if not action_economy.notify_round_start():
_fatal("行动经济 首轮 notify_round_start 被拒")
return false
round_index = 1
_roll_round_actions() # 开轮摇号(敌人技能池批——首轮同样摇;先于 round_started,挖掘期动画位可读)
round_started.emit(round_index)
return true
@@ -449,8 +416,9 @@ func _maybe_settle() -> void:
func _settle() -> void:
_settling = true
_defer_board_damage = true # 案C:授予段伤害单据只暂存不结账(2026-10-06 用户裁——兑付时点=战斗段末)
var ri := round_index
# ① 授予段:结算队列(开格/旗判定/清图)→ 极性路由逐批兑付。
# ① 授予段:结算队列(开格/旗判定/清图)→ 极性路由逐批兑付(伤害形态单据暂存——见 _submit 案C 闸)。
# 判定基线 = 轮末在场旗(发射面已过滤——被挖开的旗已随挖掘擦除零兑付,插旗不可逆批 2026-09-19;
# 开格事实不可撤)。
for evt in _facts_reveals:
@@ -465,45 +433,75 @@ func _settle() -> void:
# 作废(归因行在案);标空判定已随旗擦除自然缺席(被挖的旗不在轮末在场基线)。
_emit_row("reward_ineffective", "safe_cell", evt.cell, ri, "奖励作废(插旗格直接挖开——零惩罚零奖励)", 0, {}, "")
continue
_grant_routed(_feat_yield_adjust(snap, true), "positive", "safe_cell", evt.cell, ri, "")
# 开格流连击/深层产出(迭代 12 T5):矿脉直觉连击 = safe +1(mine 清零在负向分支);
# 深挖钻头深层产出 = 每 cap 格额外 grant 一份(收益面补偿额外 AP 成本——R4 甲非信息税对价)
_feat_combo += 1
# 深挖钻头 v2(2026-10-04 二次修正——用户实测「付 2AP 无可见提升纯挨打」:v1 配额制
# 4 次付费 8AP 换 1 份随机资源=净负期望+收益埋明细带不可感知):改**本格双份**——
# 付费挖掘的本格资源直接双份(多花 1AP 买多一份同格产出,账目直白期望微正)。
# 本轮付费次数 N=deep_paid_count−轮初快照;safe 事件按 N 上限逐格追加第二份(「深挖」)。
var dd_cost := int(_damage.feat_flags.get("deep_dig_cost", 0))
if dd_cost > 0:
var paid_this_round := int(action_economy.deep_paid_count) - _feat_paid_at_round_start
if paid_this_round > 0 and _feat_deep_given < paid_this_round:
_feat_deep_given += 1
# dig_reveal 发射+施加(内容数据驱动扩展批 T3——桶序固定承载等价:
# 乘区收集 → 正向兑付 → 计数器 → 追加产出(深挖)→ 奥术矢)
var dr_hits := _fx_emit("dig_reveal", {"cell": evt.cell, "round": ri,
"is_first_dig_of_battle": not _feat_first_dig_used,
"terrain_kind": _harmful_variants(evt.get("variant_ids", []) as Array)})
var pos_m := 0
var neg_m := 0
var combo_cap := -1
for h in dr_hits:
if String(h.get("kind", "")) != "yield_mult":
continue
pos_m += int(h.get("mult", 0))
neg_m += int(h.get("cost_mult", 0))
if int(h.get("cap", 0)) > 0:
combo_cap = int(h.cap) # 矿脉直觉连击上限
_grant_routed(_feat_yield_adjust(snap, true, pos_m, neg_m, combo_cap), "positive", "safe_cell", evt.cell, ri, "")
# 计数器执行(连击计数——加法族,乘区收集后执行=本格兑付用旧值,与迁移前逐位一致)
for h in dr_hits:
if String(h.get("kind", "")) == "counter_add":
var set_v = h.get("set", null)
_fx.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
# 追加产出(深挖钻头 v2——本格双份制:grant_material 命中=配额内追加第二份;标签随行)
for h in dr_hits:
if String(h.get("kind", "")) == "grant_material":
var dd_snap = _reward_economy.grant(evt.cell)
if dd_snap is Dictionary:
_grant_routed(dd_snap, "positive", "safe_cell", evt.cell, ri, "", "(深挖)")
# 魔能共鸣·每战首次开安全格追加魔法矢(迭代 12 T2——relic 件「每关首次开格必出魔法矢」
# 落地为每战首次〔战斗域单事务无跨战状态——「每关」字面改「每战」台账披露待追认〕;
# board_typed magic 必中,扫雷结算触发点=relic 挂 first_dig_spell 承载红线①)
if bool(_damage.feat_flags.get("first_dig_spell", false)) and not _feat_first_dig_used:
_grant_routed(dd_snap, "positive", "safe_cell", evt.cell, ri, "", String(h.get("label", "")))
# 奥术矢(魔能共鸣——每战首次开安全格追加魔法矢;任意真族单次生效)
var spell_hits: Array = _hits_of(dr_hits, "spawn_spell")
if not spell_hits.is_empty() and not _feat_first_dig_used:
_feat_first_dig_used = true
var spell_t := _damage.open_ticket(DamageController.KIND_BOARD_TYPED, "feat_first_dig_spell",
"奥术矢", "board", int(_damage.feat_flags.get("spell_value", 0)),
"奥术矢", "board", int((spell_hits[0] as Dictionary).get("value", 0)),
DamageController.TARGET_FRONT_ALIVE, ri, evt.cell, "magic")
_damage.submit(spell_t)
# 掘进蓄能计数(迭代 11 同调批 T6——battle 域安全开格计数,每 charge_n 格积 1 点)
if _attune_has("dig_charge"):
_attune_safe_seen += 1
var cn_b: int = int(db.treasure_item_row("dig_charge").get("charge_n", 999))
if cn_b > 0 and _attune_safe_seen % cn_b == 0:
_attune_bank += 1
_submit(spell_t, false)
# 掘进蓄能计数(迭代 11 同调批 T6 → 内容数据驱动扩展批 T4:积点账本迁效果引擎计数器
# dig_charge_bank——行 triggers counter_spend(treasure_used) 受理闸同账本。模判定留编排器侧:
# 「每 N 格积 1 点」在发射点施加架构下无法行内表达先增后判(when 于 dispatch 预评估),
# 逐位等价优先——词汇表边界注记随 commit 留痕;charge_n 读行零字面量)
if _attune_has("dig_charge"):
_attune_safe_seen += 1
var cn_b: int = int(db.treasure_item_row("dig_charge").get("charge_n", 999))
if cn_b > 0 and _attune_safe_seen % cn_b == 0:
_fx.counter_add("dig_charge_bank", 1)
elif evt.kind == "mine":
# 插旗不可逆四情况②:插雷格再挖开 = 只受挖雷一层惩罚(mine_hit 照常兑付——惊动巢穴),
# 标中不发(旗已随挖掘擦除、不入轮末判定基线)。
_grant_routed(_feat_yield_adjust(snap, false), "negative", "mine_hit", evt.cell, ri, "")
_feat_combo = 0 # 矿脉直觉连击清零(踩雷断连——「推理密度直接奖励」的对侧)
# 地形变异 兑付段(授予段尾——触发枚举 on_open:挖开即伤、chain 通道同口径,轮末结算逐行兑现;
# 信息型 hide_number 不进结算——呈现层读取,见 board_view 数字遮蔽;雷格恒无变异——布置段排除,
# 双层叠罚不存在;插旗格直挖照吃变异伤害——地形后果同 mine_hit 口径,非奖励不作废)
# mine_hit 发射+施加(内容数据驱动扩展批 T3——桶序固定承载等价:
# 减半收集 → 负向兑付〔带减半系数〕→ 反打开单 → 连击清零计数器)
var mh_hits := _fx_emit("mine_hit", {"cell": evt.cell, "round": ri,
"damage": int((snap as Dictionary).get("power", 0))})
var halve_pct := 0
for h in mh_hits:
if String(h.get("kind", "")) == "damage_mult":
halve_pct += int(h.get("value", 0))
for h in mh_hits:
if String(h.get("kind", "")) == "counter_add":
var set_v = h.get("set", null)
_fx.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
_grant_routed(_feat_yield_adjust(snap, false, 0, 0, -1), "negative", "mine_hit", evt.cell, ri, "", "", halve_pct)
for h in mh_hits:
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", "惊巢反制·反弹", "board",
int(h.get("value", 0)), DamageController.TARGET_ALL_ALIVE, ri, evt.cell, "", 0, "", {})
_submit(nct, false)
# 地形变异 兑付段(授予段尾——触发枚举 on_open:挖开即伤、chain 通道同口径;伤害单据案C 暂存到
# 战斗段末兑付〔2026-10-06 用户裁〕;信息型 hide_number 不进结算——呈现层读取,见 board_view 数字遮蔽;
# 雷格恒无变异——布置段排除,双层叠罚不存在;插旗格直挖照吃变异伤害——地形后果同 mine_hit 口径,
# 非奖励不作废;吞噬流资源兑付〔荆棘编织/地脉补偿〕中伤害形态行同样经案C闸暂存,非伤害形态照常当场)
for evt in _facts_reveals:
var vids: Array = evt.get("variant_ids", [])
for vid in vids:
@@ -513,63 +511,81 @@ func _settle() -> void:
# 地形变异伤害单据(伤害管线单据化批 2026-09-24)——无类型必中,下限保底在控制器管线内
var vt := _damage.open_ticket(DamageController.KIND_BOARD_FLAT_HERO, "地形变异", String(vrow.get("display_name", vid)), "board", \
int(vrow.get("effect_value", 0)), DamageController.TARGET_HERO, ri, evt.cell, "", 0, "", {"variant_id": String(vid)})
_damage.submit(vt)
# 吞噬流四面(迭代 12 T6——地形从纯税到第三资源带;伤害仍发生=乙稿判据 3 承载):
# ①荆棘编织者=挖开伤害型地形格额外掉落一次格面资源(主动吃地形换资源)
if int(_damage.feat_flags.get("terrain_dig_double", 0)) > 0:
var tw_snap = _reward_economy.grant(evt.cell)
if tw_snap is Dictionary:
_grant_routed(tw_snap, "positive", "safe_cell", evt.cell, ri, "", "(荆棘编织)")
# ②地脉采撷=受地形伤掉落小额资源补偿(薄矿化——每次受伤兑一份)
if int(_damage.feat_flags.get("terrain_refund", 0)) > 0:
var lh_snap = _reward_economy.grant(evt.cell)
if lh_snap is Dictionary:
_grant_routed(lh_snap, "positive", "safe_cell", evt.cell, ri, "", "(地脉补偿)")
# ③熔火之躯=受地形伤积层(触发键=「受地形伤」通用不按种类特化——定稿红线承载)
if int(_damage.feat_flags.get("variant_counter_value", 0)) > 0:
_feat_magma_layers += 1
_submit(vt, false)
# damage_taken(kind=terrain) 发射+施加(内容数据驱动扩展批 T3——荆棘/地脉 grant_material
# 即时执行 + 熔火积层 counter_add;行序随订阅声明序〔ley 表序在 thorn 前〕,兑付值逐位一致)
var dt_hits := _fx_emit("damage_taken", {"kind": "terrain", "amount": int(vrow.get("effect_value", 0)),
"source": String(vid), "cell": evt.cell, "round": ri, "terrain_kind": String(vid)})
for h in dt_hits:
match String(h.get("kind", "")):
"grant_material":
var tw_snap = _reward_economy.grant(evt.cell)
if tw_snap is Dictionary:
_grant_routed(tw_snap, "positive", "safe_cell", evt.cell, ri, "", String(h.get("label", "")))
"counter_add":
var set_v = h.get("set", null)
_fx.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
for evt in _facts_flags:
_judge_flag(evt, ri)
# 战旗军规开单段(迭代 12 T3 标旗流——flag_judged 批后统一开单:轮末每面标中旗对最前存活敌
# 结算 board_typed 必中伤害〔复用零新配方;「旗所在巢穴敌」简化为 default_target 最前存活敌——
# 台账披露待追认〕;完美布防=本轮旗批全中(hit>0 且 miss==0)时旗伤 ×mult——全对推理奖励)。
# 扫雷结算触发点=flag_strike/flag_all_hit/nest_aura 挂点承载红线①。
if int(_damage.feat_flags.get("flag_strike_value", 0)) > 0:
var hits := 0
var misses := 0
# 伤害单据案C 暂存战斗段末兑付。
# flag_settle 发射+施加(内容数据驱动扩展批 T3——战旗 open_ticket + 完美布防 modify_ticket
# 改写窗口:旗伤基值×完美倍率后逐旗开单,与迁移前算序一致)
var fs_hits := 0
var fs_misses := 0
for fevt in _facts_flags:
if bool(fevt.get("hit", false)):
fs_hits += 1
else:
fs_misses += 1
var fs_fx := _fx_emit("flag_settle", {"flags_hit_all": fs_hits > 0 and fs_misses == 0,
"flags_count": fs_hits, "round": ri})
var banner_hits: Array = []
for h in fs_fx:
if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "attack":
banner_hits.append(h)
if not banner_hits.is_empty():
var strike_value := int((banner_hits[0] as Dictionary).get("value", 0))
var flag_mult := 1
for h in fs_fx:
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "flag_mult":
flag_mult *= maxi(1, int(h.get("value", 1)))
if fs_misses == 0 and fs_hits > 0 and flag_mult > 1:
strike_value *= flag_mult # 完美布防:同轮全中旗伤倍增(全对推理奖励)
for fevt in _facts_flags:
if bool(fevt.get("hit", false)):
hits += 1
else:
misses += 1
if hits > 0:
var mult := int(_damage.feat_flags.get("flag_all_hit_mult", 1))
var strike_value := int(_damage.feat_flags.get("flag_strike_value", 0))
if misses == 0 and mult > 1:
strike_value *= mult # 完美布防:同轮全中旗伤倍增(全对推理奖励)
for fevt in _facts_flags:
if not bool(fevt.get("hit", false)):
continue
var st_t := _damage.open_ticket(DamageController.KIND_BOARD_TYPED, "feat_flag_strike",
"战旗军规", "board", strike_value, DamageController.TARGET_FRONT_ALIVE, ri,
fevt.cell, "normal")
_damage.submit(st_t)
# 熔火之躯轮末反打(迭代 12 T6 吞噬流——受地形伤积层,轮末每层对全体敌 ~1 必中反伤;
# 触发键=「受地形伤」通用不按地形种类特化——定稿红线承载;反打后清零)
var magma := int(_damage.feat_flags.get("variant_counter_value", 0))
if magma > 0 and _feat_magma_layers > 0:
var mg_t := _damage.open_ticket(DamageController.KIND_BOARD_BLAST, "feat_magma_body",
"熔火反噬 ×%d" % _feat_magma_layers, "board", magma * _feat_magma_layers,
DamageController.TARGET_ALL_ALIVE, ri, minesweeper.hero_pos(), "", 0, "", {})
_damage.submit(mg_t)
_feat_magma_layers = 0
if not bool(fevt.get("hit", false)):
continue
var st_t := _damage.open_ticket(DamageController.KIND_BOARD_TYPED, "feat_flag_strike",
"战旗军规", "board", strike_value, DamageController.TARGET_FRONT_ALIVE, ri,
fevt.cell, "normal")
_submit(st_t, false)
# round_end 发射+施加(内容数据驱动扩展批 T3——每轮结算收口:熔火之躯反打单开立〔open_ticket
# 即时执行〕+积层清零〔counter_add set〕;整备转蓄力由 finish_round_stop 承载——停手侧 AP 已在
# request_stop 记账,转存决策=grant_ap(mode:transfer) 订阅定夺,无订阅走 RAP 转存缺省)
var re_fx := _fx_emit("round_end", {"round": ri})
for h in re_fx:
if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "blast":
var mg_layers := _fx.counter(String(h.get("per", "")))
var mg_total := int(h.get("value", 0)) * mg_layers
if mg_total > 0:
var mg_t := _damage.open_ticket(DamageController.KIND_BOARD_BLAST, "feat_magma_body",
"熔火反噬 ×%d" % mg_layers, "board", mg_total,
DamageController.TARGET_ALL_ALIVE, ri, minesweeper.hero_pos(), "", 0, "", {})
_submit(mg_t, false)
for h in re_fx:
if String(h.get("kind", "")) == "counter_add":
var set_v = h.get("set", null)
_fx.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
action_economy.finish_round_stop(_fx != null and _fx.has_effect_on("round_end", "grant_ap", "transfer"))
if _facts_path == "cleared":
_grant_clear_reward(ri)
_damage.flush() # 授予段界结账(B 模式——段内开单攒批到此统一兑现;A 模式 no-op;清图批前另有同步结账点)
_damage.flush() # 授予段界结账(案C 后本段伤害单据全数暂存,此处对空队 no-op——保留作防御性段界)
# ② 增益/减益段(续存实例组合行;本结算新授予的已在授予段逐 grant 出行——增益状态 义务⑦)
_emit_composition_effects("hero", ri)
_emit_composition_effects("enemy", ri)
# ③ 战斗段(调用序:掷点判定 → apply_damage → commit_action;hero hp=0 短路)
# ③ 战斗段(调用序:主角先手 → 逐敌还手 → 地图伤害账殿后〔案C 2026-10-06 用户裁〕;hero hp=0 短路)
_combat_segment(ri)
# ④ 衰减段(恰一次恒执行含末轮——先兑付后衰减)
var k: int = _status_effects.decay_round()
@@ -591,31 +607,62 @@ func _settle() -> void:
return
_emit_row("verdict", "", Vector2i(-1, -1), ri, "下一轮次", 0, {}, "")
_exit_distribution()
# 深挖钻头 v2 轮初快照滚动(本轮付费次数已消费——下一轮 N=当前值−新快照)
_feat_paid_at_round_start = int(action_economy.deep_paid_count)
_settling = false
# ---- 授予段 helpers(极性路由)----
# 开格产出乘区(迭代 12 T5 开格流——贪婪矿灯/矿脉直觉/赌徒的血签;duplicate 隔离不回写快照):
# 开格产出乘区(内容数据驱动扩展批 T3 参数化——贪婪矿灯/矿脉直觉/赌徒的血签事件收集器注入):
# positive=power ×(1+静态 mult% + 矿脉直觉连击加成 min(cap,combo)×10%);negative=power ×(1+cost%)。
# 零旗=原快照原样返回(零扰动)。
func _feat_yield_adjust(snap: Dictionary, positive: bool) -> Dictionary:
var pos_m := int(_damage.feat_flags.get("dig_yield_pos_mult", 0))
var neg_m := int(_damage.feat_flags.get("dig_yield_neg_mult", 0))
if positive and pos_m <= 0 and not _damage.feat_flags.has("combo_cap"):
# 全零收集器=原快照原样返回(零扰动)。combo 读数=效果引擎 dig_combo 计数器(safe+1/mine 清零,
# 跨轮累计——与迁移前 _feat_combo 逐位一致)。
func _feat_yield_adjust(snap: Dictionary, positive: bool, pos_m: int, neg_m: int, combo_cap: int) -> Dictionary:
var combo_val := _fx.counter("dig_combo") if _fx != null else 0
if positive and pos_m <= 0 and combo_cap <= 0:
return snap
if not positive and neg_m <= 0:
return snap
var out: Dictionary = snap.duplicate()
var power := int(out.get("power", int(_reward_economy.polarity_row(String(out.get("cell_type", "")), "positive" if positive else "negative").power)))
var pct := pos_m if positive else neg_m
if positive and _damage.feat_flags.has("combo_cap"):
pct += mini(int(_damage.feat_flags.get("combo_cap", 5)), _feat_combo) * 10
if positive and combo_cap > 0:
pct += mini(combo_cap, combo_val) * 10
out["power"] = maxi(1, int(round(float(power) * (1.0 + float(pct) / 100.0))))
return out
# 伤害型变异过滤(terrain_kind fact 取数面——variation 表 effect=flat_damage 判据;
# 🔴 R4 甲永不对冲边界=仅限伤害型,信息型(hide_number 族)永不出现在本集)
func _harmful_variants(vids: Array) -> Array:
var out: Array = []
for vid_v in vids:
var vid := String(vid_v)
var vrow: Dictionary = db.variation.row_by_id(vid)
if String(vrow.get("effect", "")) == "flat_damage":
out.append(vid)
return out
# 邻接伤害型变异收集(terrain_kind fact 取数面——flag_hit 发射点用:标中旗相邻八格的伤害型变异集;
# 🔴 R4 甲永不对冲边界=仅限伤害型,信息型〔hide_number 族〕不入集)
func _harmful_adjacent(cell: Vector2i) -> Array:
var out: Array = []
var board: BoardData = minesweeper.current_board()
if board == null:
return out
for n in board.neighbors8(cell):
out.append_array(_harmful_variants(board.variant_ids(n)))
return out
# 效果命中过滤(按效果类型取命中子集——发射点分桶施加面)
func _hits_of(hits: Array, kind: String) -> Array:
var out: Array = []
for h in hits:
if String((h as Dictionary).get("kind", "")) == kind:
out.append(h)
return out
# 「动作 × 格型」矩阵的执行面:snap = 缓冲期冻结身份快照(cell_type = 该格装板期摇定的类型身份),
# polarity 由动作决定(开安全格/标中旗 = positive,开雷格/标错旗 = negative),
# 兑付行 = 奖励字典(类型, 极性)行。返回 true = percent 行实际生效(flat 行恒 false——兑付结果由行协议承载)。
@@ -639,12 +686,14 @@ func use_treasure(handle: int, target: Vector2i) -> Dictionary:
func(c: Vector2i): return not board.is_revealed(c))
if not bool(v.ok):
return v # ② 拒绝零消耗
# 掘进蓄能受理闸(迭代 11 同调批 T6——bank>0 才可发起,一行一点;积点不足拒绝零消耗)
if String(v.item_id) == "dig_charge" and _attune_has("dig_charge"):
if _attune_bank <= 0:
var cn_info: int = int(db.treasure_item_row("dig_charge").get("charge_n", 0))
return {"ok": false, "reason": "掘进蓄能:安全格积点未达(%d/%d)" % [_attune_safe_seen % cn_info if cn_info > 0 else 0, cn_info]}
_attune_bank -= 1
# treasure_used 发射+施加(内容数据驱动扩展批 T4——使用主动秘宝受理面:counter_spend 订阅=受理闸
# (掘进蓄能积点账本),消耗成功才受理;积点不足拒绝零消耗。按 item_id 特判随本批拆除)
var tu_hits := _fx_emit("treasure_used", {"item_id": String(v.item_id), "target": target})
for h in tu_hits:
if String(h.get("kind", "")) == "counter_spend":
if not _fx.counter_spend(String(h.get("counter_id", "")), int(h.get("value", 1))):
var cn_info: int = int(db.treasure_item_row("dig_charge").get("charge_n", 0))
return {"ok": false, "reason": "掘进蓄能:安全格积点未达(%d/%d)" % [_attune_safe_seen % cn_info if cn_info > 0 else 0, cn_info]}
var kinds: Array = v.kinds
if kinds.has("mine_reveal"):
treasure_inventory.apply_overlay("mine_reveal", v.resolved)
@@ -678,7 +727,7 @@ func set_treasure_unlocked(ids: Dictionary) -> void:
_reward_economy.set_treasure_unlocked(ids)
func _grant_routed(snap: Dictionary, polarity: String, source_class: String, cell: Vector2i, ri: int, highlight: String = "", label_suffix: String = "") -> bool:
func _grant_routed(snap: Dictionary, polarity: String, source_class: String, cell: Vector2i, ri: int, highlight: String = "", label_suffix: String = "", halve_pct: int = 0) -> bool:
# 迭代 11 第①批 T7——aux 授予分支随掉落/停点渠道退役拆除(reward 词表第十型 treasure_item 保留但零投放:
# 无 aux 行入池、CURIO_KINDS 词表已除名);剩余类型走极性字典路由。
var row: Dictionary = _reward_economy.polarity_row(String(snap.get("cell_type", "")), polarity)
@@ -698,18 +747,14 @@ func _grant_routed(snap: Dictionary, polarity: String, source_class: String, cel
row = row.duplicate()
row["power"] = int(round(int(row.power) * prem_pct / 100.0))
row["premium_pct"] = prem_pct
# 惊巢反制(迭代 11 同调批 T5——底稿 §3:挖开雷格该次惩罚减半 + 反弹 N;duplicate 隔离——减半
# 不回写极性字典;仅 source_class=mine_hit 受理,标错旗/负向字典行走原通道)
if polarity == "negative" and source_class == "mine_hit" and _attune_has("nest_counter"):
# 惊巢反制(迭代 11 同调批 T5 → 内容数据驱动扩展批 T4:按 id 特判拆除——减半系数=mine_hit
# damage_mult 订阅命中(行 value 50=减 50%,取整 ceil 与迁移前逐位一致);反弹单=mine_hit
# open_ticket channel reflect 订阅施加(编排器 mine_hit 施加段);duplicate 隔离——减半不回写极性字典)
if halve_pct > 0 and polarity == "negative" and source_class == "mine_hit":
row = row.duplicate()
var half: int = int(ceil(float(int(row.power)) / 2.0))
var half: int = int(ceil(float(int(row.power)) * float(100 - halve_pct) / 100.0))
_emit_row("effect", source_class, cell, ri, "惊巢反制——挖雷惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_counter"}, highlight)
row.power = half
var reflect: int = _attune_mag("nest_counter")
if reflect > 0:
var nct := _damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_counter", "惊巢反制·反弹", "board",
reflect, DamageController.TARGET_ALL_ALIVE, ri, cell, "", 0, highlight, {})
_submit(nct, false)
return _dispatch_row(row, source_class, cell, ri, highlight, label_suffix)
@@ -775,7 +820,7 @@ func _apply_flat_row(row: Dictionary, source_class: String, cell: Vector2i, ri:
if ctype == "blast":
var t := _damage.open_ticket(DamageController.KIND_BOARD_BLAST, source_class, display, "board", power, \
DamageController.TARGET_ALL_ALIVE, ri, cell, "", 0, highlight, {"batch_key": String(row.reward_id)})
return _damage.outcome(_submit(t, sync))
return _outcome_of(_submit(t, sync))
if ctype == "pierce" or ctype == "magic":
# 伤害道具批(2026-09-18)语义不变:正向 = 单目标克制直伤(必中全额不掷点——棋盘来源伤害既有口径);
# 负向 = 主角直伤(复用反噬通道)。
@@ -784,7 +829,7 @@ func _apply_flat_row(row: Dictionary, source_class: String, cell: Vector2i, ri:
var atk_type: String = String(row.get("attack_type", ctype))
var t2 := _damage.open_ticket(DamageController.KIND_BOARD_TYPED, source_class, display, "board", power, \
DamageController.TARGET_FRONT_ALIVE, ri, cell, atk_type, 0, highlight, {"batch_key": String(row.reward_id)})
return _damage.outcome(_submit(t2, sync))
return _outcome_of(_submit(t2, sync))
if ctype == "heal":
if String(row.get("polarity", "positive")) == "negative":
return _submit_flat_hero(source_class, display, power, cell, ri, highlight, sync)
@@ -805,14 +850,23 @@ func _apply_flat_row(row: Dictionary, source_class: String, cell: Vector2i, ri:
# 开单分流:sync(清图批)走控制器同步开单——先按序结清段内排队单据、再当场兑现本单;
# 常规开单按结账时机政策(A 即结 / B 入队)。
func _submit(t: Dictionary, sync: bool) -> int:
if _defer_board_damage:
_deferred_board.append(t) # 案C:授予段伤害单据暂存——战斗段怪物还手后按事件序补提交(sync 同闸,清图批一致延后)
return -1
return _damage.flush_submit(t) if sync else _damage.submit(t)
# 案C 结账读数:暂存单(_submit 返回 -1)以「将兑付」回报——授予段兑付决策(清图完美第二份等)只能
# 依据开单时点事实(该时点敌人存活有保证);战斗段末实际结账若目标已灭,控制器自记未生效行。
func _outcome_of(ticket_id: int) -> String:
return "redeemed" if ticket_id < 0 else _damage.outcome(ticket_id)
# 主角直伤单据(反噬/治疗包负向——无类型必中,下限保底在控制器管线内)
func _submit_flat_hero(source_class: String, display: String, power: int, cell: Vector2i, ri: int, highlight: String, sync := false) -> String:
var t := _damage.open_ticket(DamageController.KIND_BOARD_FLAT_HERO, source_class, display, "board", power, \
DamageController.TARGET_HERO, ri, cell, "", 0, highlight, {})
return _damage.outcome(_submit(t, sync))
return _outcome_of(_submit(t, sync))
# 旗判定批:标中 = 该雷格资源的正向兑付(每雷实例一次;高光 = 强制检查点);
@@ -824,15 +878,22 @@ func _judge_flag(evt: Dictionary, ri: int) -> void:
return # 去重跳过(资格以雷格实例为键——排雷玩法 诚实重复上报的对侧);零明细行
_flag_consumed[cell] = true
_perfect_hit_true += 1
# 标中殉爆(迭代 11 同调批 T5——底稿 §3:每标中一面旗,全体存活敌吃 N 群伤;无类型走 blast 通道)
if _attune_has("flag_burst"):
# flag_hit 发射+施加(内容数据驱动扩展批 T3——桶序固定承载等价:殉爆〔T4 秘宝面〕→
# 净化改写 → 图谱额外资源 → 基线兑付)
var fh_hits := _fx_emit("flag_hit", {"cell": cell, "round": ri,
"terrain_kind": _harmful_adjacent(cell)})
# 标中殉爆(迭代 11 同调批 T5 → 内容数据驱动扩展批 T4:订阅施加——行 triggers open_ticket
# channel blast value_from magnitude;每标中一面旗全体存活敌吃 N 群伤,无类型走 blast 通道)
for h in _hits_of(fh_hits, "open_ticket"):
if String(h.get("channel", "")) != "blast":
continue
var fbt := _damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_flag_burst", "标中殉爆", "board",
_attune_mag("flag_burst"), DamageController.TARGET_ALL_ALIVE, ri, cell, "", 0, "highlight", {})
int(h.get("value", 0)), DamageController.TARGET_ALL_ALIVE, ri, cell, "", 0, "highlight", {})
_submit(fbt, false)
# 净化工兵(迭代 12 T6 吞噬流——标中旗中和相邻伤害型地形格):🔴 R4 甲永不对冲边界=
# **仅限伤害型**(thorn/magma/rockfall——variation 表 effect=flat_damage 判据),信息型
# (hide_number 族)永不清除(红线①看门税不可对冲);中和=变普通格(BoardData.clear_variants)。
if int(_damage.feat_flags.get("flag_neutralize", 0)) > 0:
if not _hits_of(fh_hits, "rewrite_board").is_empty():
var board: BoardData = minesweeper.current_board()
for n in board.neighbors8(cell):
var vids_n: Array = board.variant_ids(n)
@@ -847,10 +908,11 @@ func _judge_flag(evt: Dictionary, ri: int) -> void:
_emit_row("terrain_neutralized", "feat_purge_sapper", n, ri, "净化工兵·地形中和", 0, {}, "")
# 雷区图谱(迭代 12 T3 标旗流——标中雷额外获得一份格面资源:插旗开始产出对标开格;
# 复用 grant 单点,额外兑付走同一 _grant_routed 正向路由)
if int(_damage.feat_flags.get("flag_resource_extra", 0)) > 0:
var extra_snap = _reward_economy.grant(cell)
if extra_snap is Dictionary:
_grant_routed(extra_snap, "positive", "flag_hit", cell, ri, "", "(雷区图谱)")
for h in fh_hits:
if String(h.get("kind", "")) == "grant_material":
var extra_snap = _reward_economy.grant(cell)
if extra_snap is Dictionary:
_grant_routed(extra_snap, "positive", "flag_hit", cell, ri, "", String(h.get("label", "")))
var snap = _reward_economy.grant(cell)
if not (snap is Dictionary):
return
@@ -925,6 +987,15 @@ func _roll_round_actions() -> void:
_emit_row("highlight", "enemy_action", Vector2i(-1, -1), round_index,
"%s 解锁了 %s" % [String(u.display_name), String(srow_u.get("display_name", sid))],
0, {"skill_id": sid}, "skill_unlock")
# enemy_hp_threshold 发射点(内容数据驱动扩展批 T1——血量阈值沿;对所有带该字段敌人逐个发射,
# 非 Boss 专属——Boss 语义留给订阅者 when 判定。pct=本次解锁条目的 unlock_hp_pct 表值)
var pct_v := 0
for pe in (u.get("pool", []) as Array):
if String((pe as Dictionary).get("skill_id", "")) == sid and (pe as Dictionary).has("unlock_hp_pct"):
pct_v = int((pe as Dictionary).unlock_hp_pct)
break
_fx_emit("enemy_hp_threshold", {"unit": String(u.enemy_id), "pct": pct_v,
"is_boss": String(encounter.get("node_type", "")) == "boss"})
var entries: Array = _enemy_system.rollable_skills(u)
if _enemy_system.basic_streak(u) >= pity_m:
var specials: Array = _enemy_system.special_skills(u)
@@ -942,6 +1013,7 @@ func _roll_round_actions() -> void:
# 停开(B 模式下若 flush 中主角倒下,由控制器死亡事件终止余单——两模式同一结果)。
func _combat_segment(ri: int) -> void:
_defer_board_damage = false # 案C 闸复位——战斗段起开单即入队(主角/敌方/补提交的地图单按开单序统一结账)
# 本轮扫雷事实推导(迭代 12 T4——执拗 streak/连珠矢段数共用取数面):本轮 safe 事件数=
# streak;踩雷即清零(mine_hit 监听同口——执拗「踩雷清零」承载)。攻击在战斗段=授予段后
# 同一次 _settle 内,facts 已定。
@@ -952,11 +1024,12 @@ func _combat_segment(ri: int) -> void:
round_safe += 1
elif evt.kind == "mine":
round_mine = true
_damage.feat_flags["dig_streak"] = 0 if round_mine else round_safe
# 蓄力层注入(迭代 12 T5——整备军备「每层下轮首段 +1」/厚积薄发满层 spike/铁壁整备减伤——
# 三件同读 action_economy.charge_layers;battle 域每轮刷新)
_damage.feat_flags["charge_layers"] = action_economy.charge_layers
# ⓪ 主角先手攻击(基础攻击恒存在——2026-09-11 用户裁决;先于敌方行动;授予段负向直伤致死 → 致电短路不先手)。
_damage.dig_streak = 0 if round_mine else round_safe
# 蓄力层注入(内容数据驱动扩展批 T3——整备军备「每层下轮首段 +1」/厚积薄发满层 spike/铁壁整备
# 减伤——三件 fact charge_layers 同读 action_economy;battle 域每轮刷新)
_damage.charge_layers = action_economy.charge_layers
# ⓪ 主角先手攻击(基础攻击恒存在——2026-09-11 用户裁决;先于敌方行动。案C 后授予段不再产出伤害,
# 主角进入战斗段时恒存活——先手必兑,除非场上无敌)。
# 单分量伤害构成(2026-09-19 充能退役批·用户拍板):主角攻击 = 唯一基础分量(atk,吃掷点含暴击;
# 类型 = 主角 attack_type 表值——2026-09-18 营地扩展前置批:量与类型抽象分离;查甲效矩阵对应行取克制修正)。
# 原"基础 + 穿刺/魔法充能三分量"模型随充能系统整体退役——克制策略归冒险前配置(营地换型 / 未来冒险前参数面),
@@ -969,14 +1042,14 @@ func _combat_segment(ri: int) -> void:
var ht := _damage.open_ticket(DamageController.KIND_HERO_ATTACK, "hero_attack", "主角攻击", "combat", _hero_atk, \
DamageController.TARGET_FRONT_ALIVE, ri, Vector2i(-1, -1), String(_enemy_system.hero_unit().get("attack_type", "normal")))
_damage.submit(ht)
# 连珠矢(迭代 12 T4 穿刺流——开格节奏变攻击段数):本轮每开 ~3 安全格 +1 段穿刺附加
# (上限 cap;段值 provisional 固定值不乘 atk——台账披露)。扫描雷结算触发点=dig_count_segments。
var chain_value := int(_damage.feat_flags.get("chain_value", 0))
if chain_value > 0:
var segments := mini(int(_damage.feat_flags.get("chain_cap", 2)), int(_damage.feat_flags.get("dig_streak", 0)) / 3)
# 连珠矢(内容数据驱动扩展批 T3——attack_commit 订阅施加面:开格节奏变攻击段数,本轮每开
# ~3 安全格 +1 段穿刺附加(上限 cap;段值 provisional 固定值不乘 atk——台账披露)。施加位
# 紧随主角攻击单开立=迁移前开单位(先于敌方行动单入队——flush 兑现序逐位一致)
for h in _hits_of(ht.context.get("fx_attack_hits", []) as Array, "attack_segments"):
var segments := mini(int(h.get("cap", 2)), _damage.dig_streak / maxi(1, int(h.get("divisor", 3))))
for s in segments:
var ct := _damage.open_ticket(DamageController.KIND_BOARD_TYPED, "feat_chain_arrows",
"连珠矢", "board", chain_value, DamageController.TARGET_FRONT_ALIVE, ri,
"连珠矢", "board", int(h.get("value", 0)), DamageController.TARGET_FRONT_ALIVE, ri,
minesweeper.hero_pos(), "pierce")
_damage.submit(ct)
# 敌方行动(敌人技能池批——本拍动作开轮已摇定,此处按技能行兑现;行序 = 生成序)。
@@ -1010,7 +1083,18 @@ func _combat_segment(ri: int) -> void:
et["source_unit"] = u
et["context"] = {"skill_id": skill_id, "baseline": baseline}
_damage.submit(et)
_damage.flush() # 战斗段界结账(B 模式——段内开单攒批到此统一兑现;A 模式 no-op)
# 地图伤害兑付(案C 2026-10-06 用户裁——战斗段末:怪物还手后按授予段事件序补提交统一结账;
# 主角死于怪物 → 地图账不兑,逐单留「未生效」行不作废静默——没生效也要留痕口径;
# 补提交后若地图直伤反杀主角,控制器 _halted 作废余单——战斗已败,胜负归判定段)
if int(_enemy_system.hero_unit().get("hp", 0)) <= 0:
for t in _deferred_board:
_emit_row("reward_ineffective", String(t.get("source_class", "")), t.get("origin_cell", Vector2i(-1, -1)), ri,
"%s 未生效(主角已倒下)" % String(t.get("display", "")), 0, {"forfeit": "hero_down"}, "")
else:
for t in _deferred_board:
_damage.submit(t)
_deferred_board.clear()
_damage.flush() # 战斗段界结账(B 模式——主角单+敌方单+地图单按开单序统一兑现;A 模式地图单补提交时即结)
# ---- 算术读数(伤害管线单据化批 2026-09-24 迁移注记)----
@@ -1094,14 +1178,14 @@ func _exit_distribution() -> void:
if not _install_new_board():
_fatal("换图编排失败")
return
# 工兵晨令续队(迭代 11 同调批 T5——upcoming 轮号 = round_index+1 ≤ effective_rounds 才续,P4 甲表值化)
if _attune_has("dawn_order") and round_index + 1 <= int(db.treasure_item_row("dawn_order").get("effective_rounds", 0)):
action_economy.queue_ap_delta(_attune_mag("dawn_order"))
# 工兵晨令续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注)
action_economy.notify_settlement_done(mode)
# round_start 发射先于行动经济轮切换(queue 型 grant_ap 当轮入队当轮兑现——与首轮同口径)
round_index += 1
_emit_round_start()
action_economy.notify_round_start()
_reset_round_facts()
_refresh_used_this_round = 0
round_index += 1
_roll_round_actions() # 开轮摇号——每轮恰摇一次(轮内刷新换图不重摇:refresh 不走本通道)
round_started.emit(round_index)
+194 -113
View File
@@ -60,10 +60,16 @@ var _outcomes := {} # ticket_id → "redeemed"/"zero"/"voided"(
var _seq := 0 # 流水号
var _halted := false # 主角倒下终止旗(死亡事件置位——flush 余单作废)
var _hero_ac_override := -1 # 主角护甲等级合流入参(begin_battle 显式设定——-1 = 表值兜底,口径同战斗编排器)
# 特性求值旗(迭代 12 T2——begin_battle 编排器经 FeatsEngine 求值后注入;空字典=零扰动。
# rider_flat=英雄侧必中附加值〔奥术余烬族〕/rider_crit=档二 rider 可暴击/first_dig_spell=每战首次
# 开安全格追加魔法矢〔消费在编排器授予段〕/clamp_magic_light·clamp_magic_heavy=克制点直调)
var feat_flags: Dictionary = {}
# 效果引擎(内容数据驱动扩展批 T1/T3——attack_commit/clamp_check/armor_roll/kill/damage_taken
# 发射+施加面:dispatch 返回命中,本类按组合规则施加——T3 起旧 feat_flags 旗消费点全部拆除)
var _fx: EffectEngine = null
# 战斗段运行态事实(编排器每轮刷新——fact 取数面:attack_commit 载荷 dig_streak /
# charge_layers facts〔猎巢人 per/整备 attack_bonus per/厚积薄发 when/铁壁 shield per〕;
# 流派档位两运行态〔magic 档一 rider+1 / 档二 rider 可暴击〕)
var dig_streak := 0
var charge_layers := 0
var rider_tier_bonus := 0
var rider_tier_crit := false
func _init(db_ref, rng_ref, units_ref, effects_ref) -> void:
@@ -79,14 +85,78 @@ func set_hero_ac_override(v: int) -> void:
_hero_ac_override = v
# 效果引擎注入(战斗编排器 _init——事件发射面接线)
func set_fx(fx: EffectEngine) -> void:
_fx = fx
# 事件发射薄面(发射+命中收集统一入口——订阅空=零循环零扰动;命中由各施加面按组合规则施加)
func _fx_hits(event: String, payload: Dictionary) -> Array:
if _fx == null:
return []
return _fx.dispatch(event, payload, Callable(self, "_fx_fact"))
# 事件发射薄面(免施加观测位——enemy_hp_threshold 等现无订阅者的事件保留零扰动面)
func _fx_dispatch(event: String, payload: Dictionary) -> void:
_fx_hits(event, payload)
# 补充事实面(fact 取值第二优先源——payload 未携带的运行态读数:charge_layers 编排器每轮注入)
func _fx_fact(fact: String):
match fact:
"charge_layers":
return charge_layers
"dig_streak":
return dig_streak
return null
# per 取数(per 字段解析——载荷同名字段优先,回落补充事实面;add_ticket_rider/attack_bonus/
# shield/open_ticket 的倍数承载:贡献值 = value × per 读数,cap 对乘积封顶)
func _per_value(name: String, payload: Dictionary) -> int:
if name == "":
return 1
if payload.has(name):
return int(payload[name])
if _fx_fact(name) != null:
return int(_fx_fact(name))
return 0
# 巢穴控制数(fact nest_count 取数面——敌方 weaken 实例数,猎巢人订阅面)
func _nest_count() -> int:
var n := 0
for eff in effects.query_active("enemy"):
if String(eff.effect_id) == "weaken":
n += 1
return n
# ---- 开单面(流程调用——编排器六调用点的唯一形态)----
# 开单:A 模式当场结账;B 模式入队待 flush。返回流水号(outcome() 查询键)。
func submit(t: Dictionary) -> int:
_seq += 1
t["ticket_id"] = _seq
_outcomes[_seq] = "pending"
if policy == POLICY_IMMEDIATE:
_resolve(t)
else:
_queue.append(t)
return _seq
# 单据构造(缺省填齐——调用点只写差异栏;context = kind 专用:enemy_skill 带 skill_id/baseline,
# board_flat_hero 的键并入行载荷,board_blast/board_typed 带 batch_key 供未生效行归因)
# board_flat_hero 的键并入行载荷,board_blast/board_typed 带 batch_key 供未生效行归因)。
# attack_commit 发射点(内容数据驱动扩展批 T3——我方伤害单据开立入口,任务书 §3.1 定稿位;
# 命中挂单据 context 随行——施加面在 _resolve_hero_attack 管线算术前逐族施加,开单时点=主角攻击
# 单恒为段内首单(结账现场与开单现场一致)。载荷 atk/target/matchup + 挖掘 streak 事实〔连珠矢/
# 执拗订阅面〕+巢穴控制数〔猎巢人〕)
func open_ticket(kind: String, source_class: String, display: String, channel: String, base_value: int,
target_rule: String, ri: int, origin_cell: Vector2i = Vector2i(-1, -1), attack_type: String = "",
rider: int = 0, highlight: String = "", context: Dictionary = {}) -> Dictionary:
return {
var t := {
"kind": kind,
"source_class": source_class,
"origin_cell": origin_cell,
@@ -102,18 +172,16 @@ func open_ticket(kind: String, source_class: String, display: String, channel: S
"requires": -1, # 前置单据 id(-1 = 无依赖)
"source_unit": {}, # enemy_skill 专用——来源敌句柄(作废判定 + commit)
}
# 开单:A 模式当场结账;B 模式入队待 flush。返回流水号(outcome() 查询键)。
func submit(t: Dictionary) -> int:
_seq += 1
t["ticket_id"] = _seq
_outcomes[_seq] = "pending"
if policy == POLICY_IMMEDIATE:
_resolve(t)
else:
_queue.append(t)
return _seq
if kind == KIND_HERO_ATTACK:
var tgt = _target_for(target_rule)
var armor_b: String = String(tgt.get("armor_type", "light")) if tgt != null else "light"
var matchup_o: String = (attack_type + "_vs_" + armor_b) if attack_type != "" else ""
var ac_payload := {"atk": int(base_value),
"target": String(tgt.get("display_name", "")) if tgt != null else "",
"matchup": matchup_o, "dig_streak": dig_streak, "nest_count": _nest_count()}
t.context["fx_attack_hits"] = _fx_hits("attack_commit", ac_payload)
t.context["fx_attack_payload"] = ac_payload
return t
# 同步开单(清图批专用——完美第二份与高光份数的流程依赖需要同步读数,开单权归流程 用户裁决③):
@@ -189,6 +257,8 @@ func _resolve(t: Dictionary) -> void:
# 主角先手攻击:掷点 → 折扣/暴击 → 克制点数 → hero_offense×enemy_defense 池乘区 → 下限 → 交付
# (内容数据驱动扩展批 T3——attack_commit/clamp_check/armor_roll 订阅施加面:命中=开单入口随单
# context 携带,本函数按迁移前算序逐族施加——命中序=数据表声明序,确定性)
func _resolve_hero_attack(t: Dictionary) -> void:
var target = _target_for(String(t.target_rule))
if target == null:
@@ -196,47 +266,70 @@ func _resolve_hero_attack(t: Dictionary) -> void:
return
var armor: String = String(target.get("armor_type", "light"))
var atk_type: String = String(t.attack_type)
var matchup := (atk_type + "_vs_" + armor) if atk_type != "" else ""
var ac_hits: Array = (t.context.get("fx_attack_hits", []) as Array)
var ac_payload: Dictionary = (t.context.get("fx_attack_payload", {}) as Dictionary)
var roll_read: Dictionary = _armor_roll()
var threshold: int = defender_ac(target) + int(db.settlement.attack_bonus)
# 矿工重锤·命中交换(迭代 12 T4 普攻流——正负双修原生形态:命中判定减成 trade_hit 点
# 〔更易命中〕换攻击增伤 trade_atk%——高 AC 负期望/低 AC 正期望)
var trade_hit := int(feat_flags.get("hit_trade_hit", 0))
# armor_roll 发射点(内容数据驱动扩展批 T1——敌护甲掷骰判定;免掷恒折扣订阅面)
var ar_hits := _fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)})
# 按序改写族第一拍:矿工重锤命中交换(正负双修原生形态:命中判定减成 trade_hit 点〔更易命中〕
# 换攻击增伤 trade_atk%——高 AC 负期望/低 AC 正期望;改写位先于掷点折扣读数,与迁移前一致)
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 discount: int = _roll_discount(int(roll_read.roll), threshold)
# 专注(迭代 12 T4 普攻流——免掷骰恒定折扣:方差买断成期望——稳定器人格;roll 记 0 归因)
var rewrite := int(feat_flags.get("armor_roll_rewrite", 0))
if rewrite > 0:
discount = rewrite
crit = false
roll_read["roll"] = 0
# 厚积薄发满层必中(迭代 12 T5 蓄力流——spike ready 时 discount 恒全额、暴击面走倍乘不加掷)
if int(feat_flags.get("spike_mult", 0)) > 0 and int(feat_flags.get("charge_layers", 0)) >= 3:
discount = 100
# 猎弱本能(迭代 12 T4 穿刺流——对轻甲敌折扣档改善 value 档:对冲 pierce 列 L1 −1 开局罚;
# 按序改写族第二拍:专注免掷骰恒定折扣(方差买断成期望——稳定器人格;roll 记 0 归因)
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
# 按序改写族第三拍:厚积薄发满层必中(spike ready 时 discount 恒全额、暴击面走倍乘不加掷;
# when charge_layers≥3 在 dispatch 判定——满层持续状态口径)
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
# 按序改写族第四拍:猎弱本能对轻甲敌折扣档改善 value 档(对冲 pierce 列 L1 −1 开局罚;
# 改善 = 折扣表向全额方向移档,nat 最大面/已全额不重复)
var shift := int(feat_flags.get("discount_shift", 0))
var shift := 0
var clamp_hits := _fx_hits("clamp_check", {"matchup": matchup})
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)
var cdelta: int = _counter_delta(atk_type, armor) + _feat_clamp_bonus(atk_type, armor)
# 淬毒刃纹(迭代 11 同调批 T5——底稿 §3:对被克制敌人的穿刺/魔法直伤 +N;条件 = 克制成立 ×
# 攻击类型限定,主角攻击面专属——棋盘克制直伤走 _resolve_board_typed 不吃本加成)
if attune_venom > 0 and (atk_type == "pierce" or atk_type == "magic") and cdelta > 0:
cdelta += attune_venom
# 克制点数读值+订阅改写(魔网织者/湛蓝誓约/猎手刺剑 clamp_check modify delta——克制矩阵查表值
# 后的直调;hero_attack 与 board_typed 两消费面同享)
var cdelta: int = _counter_delta(atk_type, armor)
for h in clamp_hits:
if String(h.get("kind", "")) == "modify_ticket" and h.has("delta"):
cdelta += int(h.delta)
# 淬毒刃纹(迭代 11 同调批 T5 → 内容数据驱动扩展批 T4:特判拆除——行 triggers clamp_check
# modify(mode:clamp_bonus) 订阅命中已并入上方 delta 合计;mode 路由=主角攻击面专享,
# 棋盘克制直伤窗只消费无模式 delta——棋盘不吃毒面与迁移前一致)
var base_value := float(t.base_value)
var trade_atk := int(feat_flags.get("hit_trade_atk", 0))
if trade_atk > 0:
base_value *= 1.0 + float(trade_atk) / 100.0 # 重锤增伤面(交换的正向侧)
# 蓄力流(迭代 12 T5):整备军备「每层下轮首段 +1」(层数×value 加算)+厚积薄发满层(≥3)
# spike 倍乘+强制必中(discount 100/crit 关闭掷骰面——方差买断的爆发出口)
var charge_layers := int(feat_flags.get("charge_layers", 0))
if charge_layers > 0:
base_value += float(charge_layers * int(feat_flags.get("ap_carry_value", 0)))
var spike_mult := int(feat_flags.get("spike_mult", 0))
var spike_ready := spike_mult > 0 and charge_layers >= 3
# 按序改写族第五拍:矿工重锤增伤面(交换的正向侧)
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
# 加法族:整备军备「每层下轮首段 +1」(层数×value 加算)——attack_bonus per charge_layers
for h in ac_hits:
if String(h.get("kind", "")) == "attack_bonus":
base_value += float(int(h.get("value", 0)) * _per_value(String(h.get("per", "")), ac_payload))
# 任意真族:厚积薄发满层 spike 倍乘(≥3 层——强制必中已在折扣拍承载)
if spike_ready:
base_value *= float(spike_mult)
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)))
var rolled: int = DamageMath.rolled_component(base_value, discount, crit, int(db.settlement.crit_multiplier), cdelta)
var payload: Dictionary = {"target": String(target.display_name)}
payload[atk_type] = rolled # 分量键 = 实际攻击类型(归因字段,单分量模型)
@@ -247,53 +340,49 @@ func _resolve_hero_attack(t: Dictionary) -> void:
payload["crit"] = true
var pooled: int = DamageMath.pool_damage(rolled, clamped_pool("hero_offense"), clamped_pool("enemy_defense"))
var landed: int = maxi(int(db.settlement.damage_floor), pooled)
# 英雄侧 rider(迭代 12 T2 魔法流——enemy_skill rider 对称位补齐):后置必中附加,独立于掷点
# 与乘区(奥术余烬「普攻命中后恒定结算」语义);档二(magic 4 件)rider 可暴击=当次 crit 时
# rider 值乘暴击倍率。rider 不改变下限语义(landed 含 rider 后不再过 floor)。
var hero_rider := int(feat_flags.get("rider_flat", 0))
# 猎巢人(迭代 12 T3 标旗流——巢穴控制数转伤害光环):控制数 = 敌方 weaken(削弱)实例数
# 〔八型批 side-wide 状态行——标中旗控制巢穴的既有承载;原设计「对其中敌伤害」简化为全体
# 先手攻击附加值——台账披露待追认〕,每控制 1 巢 rider +Z。
var nest_aura := int(feat_flags.get("nest_aura_value", 0))
if nest_aura > 0:
for eff in effects.query_active("enemy"):
if String(eff.effect_id) == "weaken":
hero_rider += nest_aura
# 矿工的执拗(迭代 12 T4 普攻流——「排雷排得多好,打得就有多疼」):本轮安全开格 streak
# 〔编排器授予段实时写入 feat_flags.dig_streak;踩雷清零〕×value,上限 cap。
var rdig := int(feat_flags.get("round_dig_value", 0))
if rdig > 0:
hero_rider += mini(int(feat_flags.get("round_dig_cap", 5)), int(feat_flags.get("dig_streak", 0)) * rdig)
# 加法族:英雄侧 rider(enemy_skill rider 对称位补齐口径)——后置必中附加,独立于掷点与乘区
# (奥术余烬「普攻命中后恒定结算」语义);猎巢人巢控光环(per nest_count)/矿工的执拗开格加成
# (per dig_streak、cap 封顶)同通道合计;档一质变 rider+1 / 档二(crit 时)rider 乘暴击倍率。
# rider 不改变下限语义(landed 含 rider 后不再过 floor)。
var hero_rider := rider_tier_bonus
for h in ac_hits:
if String(h.get("kind", "")) == "add_ticket_rider":
var contrib := int(h.get("value", 0)) * _per_value(String(h.get("per", "")), ac_payload)
if h.has("cap"):
contrib = mini(int(h.cap), contrib)
hero_rider += contrib
if hero_rider > 0:
if crit and bool(feat_flags.get("rider_crit", false)):
if crit and rider_tier_crit:
hero_rider = int(round(float(hero_rider) * float(db.settlement.crit_multiplier)))
landed += hero_rider
payload["hero_rider"] = hero_rider
units.apply_damage(target, landed)
payload["killed"] = not target.alive # 击杀标记在扣血后取(原语义不变)
# 碎甲震击(迭代 12 T4 普攻流——命中重甲附加「护甲裂解」):复用 off_guard(enemy percent
# +25 受伤加深——零新状态行);apply_effect 域闭/重复授予由状态容器自行守卫。
var crack := int(feat_flags.get("crack_value", 0))
if crack > 0 and armor == "heavy":
effects.apply_effect("off_guard", {"source_class": "feat_armor_crack"}, -1)
payload["cracked"] = true
# kill 发射+施加(内容数据驱动扩展批 T3——敌人死亡确认;贯穿射击溢出弹射订阅面:对下一存活敌
# 以穿刺类型弹射本体 value%〔无次敌=弹射落空〕。B 模式入队段尾 flush 兑现;A 模式递归 resolve)
if bool(payload.get("killed", false)):
for h in _fx_hits("kill", {"target": String(target.display_name), "overflow": landed}):
if String(h.get("kind", "")) != "overflow":
continue
var next_target = units.default_target()
if next_target != null:
var of_t := open_ticket(DamageController.KIND_BOARD_TYPED, "feat_pierce_shot",
"贯穿射击", "board", maxi(int(db.settlement.damage_floor), int(landed * int(h.get("value", 50)) / 100)),
DamageController.TARGET_FRONT_ALIVE, int(t.round_index), t.origin_cell, "pierce")
if policy == POLICY_SEGMENT:
_queue.append(of_t)
else:
_resolve(of_t)
# 即时执行族:碎甲震击打重甲附加「护甲裂解」(复用 off_guard——零新状态行;apply_effect 域闭/
# 重复授予由状态容器自行守卫)
for h in ac_hits:
if String(h.get("kind", "")) == "apply_status":
effects.apply_effect(String(h.get("status_id", "")), {"source_class": "feat_armor_crack"}, -1)
payload["cracked"] = true
var label := _attack_label(String(t.display), crit, discount)
if hero_rider > 0:
label += "+奥术%d(必中)" % hero_rider
emit_row_cb.call("damage", String(t.source_class), t.origin_cell, int(t.round_index), label, landed, payload, String(t.highlight))
# 贯穿射击(迭代 12 T4 穿刺流——击杀溢出弹射):击杀时对下一存活敌以穿刺类型弹射
# 本体半额〔原设计「溢出伤害」追踪在单分量模型不可行——半额弹射 provisional 裁定披露待追认;
# 无次敌=弹射落空〕。B 模式入队段尾 flush 兑现;A 模式递归 resolve(目标存活守卫内建)。
if bool(payload.get("killed", false)) and int(feat_flags.get("kill_overflow", 0)) > 0:
var next_target = units.default_target()
if next_target != null:
var of_t := open_ticket(DamageController.KIND_BOARD_TYPED, "feat_pierce_shot",
"贯穿射击", "board", maxi(int(db.settlement.damage_floor), int(landed / 2)),
DamageController.TARGET_FRONT_ALIVE, int(t.round_index), t.origin_cell, "pierce")
if policy == POLICY_SEGMENT:
_queue.append(of_t)
else:
_resolve(of_t)
_outcomes[int(t.ticket_id)] = "redeemed"
@@ -308,11 +397,14 @@ func _resolve_enemy_skill(t: Dictionary) -> void:
var rolled: int = DamageMath.rolled_component(float(t.base_value), discount, crit, int(db.settlement.crit_multiplier), 0)
var pooled: int = DamageMath.pool_damage(rolled, clamped_pool("hero_defense"), clamped_pool("enemy_output"))
var total: int = maxi(int(db.settlement.damage_floor), pooled) + int(t.rider) # rider 后置于伤害下限——独立必中加项,不进乘区
# 铁壁整备(迭代 12 T5 蓄力流——每层下轮开场 S 点减伤;减后过下限保底)
var shield := int(feat_flags.get("shield_per_layer", 0)) * int(feat_flags.get("charge_layers", 0))
# 稳健拓荒(迭代 12 T10——Fork posture B 侧 rule 键:受击减 1;两侧对称弱值=「不同强非强弱」)
if int(feat_flags.get("bulwark", 0)) > 0:
shield += 1
# damage_taken 发射+施加(内容数据驱动扩展批 T3——kind=enemy_skill;铁壁整备减伤订阅面:
# shield 加法族合计 value×per(charge_layers),稳健拓荒树规则同面(rebuild 合成订阅);
# 减后过下限保底)
var shield := 0
for h in _fx_hits("damage_taken", {"kind": "enemy_skill", "amount": total,
"source": String(t.context.get("skill_id", "")), "round": int(t.round_index)}):
if String(h.get("kind", "")) == "shield":
shield += int(h.get("value", 0)) * _per_value(String(h.get("per", "")), {})
if shield > 0:
total = maxi(int(db.settlement.damage_floor), total - shield)
units.apply_damage(hero, total)
@@ -337,11 +429,20 @@ func _resolve_board_typed(t: Dictionary) -> void:
_ineffective_row(t, "无存活敌人")
_outcomes[int(t.ticket_id)] = "zero"
return
var delta: int = _counter_delta(String(t.attack_type), String(target.get("armor_type", "light"))) + _feat_clamp_bonus(String(t.attack_type), String(target.get("armor_type", "light")))
var dealt: int = DamageMath.counter_component(int(t.base_value), delta, int(db.settlement.damage_floor))
var armor_b: String = String(target.get("armor_type", "light"))
var atk_b: String = String(t.attack_type)
# clamp_check 发射+施加(内容数据驱动扩展批 T3——克制判定修正点棋盘面;与 hero_attack 同表同点:
# modify delta 订阅改写合计进克制点数;discount_shift 档位面属主角攻击专享,本面不施加)
var cdelta: int = _counter_delta(atk_b, armor_b)
if atk_b != "":
for h in _fx_hits("clamp_check", {"matchup": atk_b + "_vs_" + armor_b}):
# 无模式 delta 才入棋盘窗(mode 路由:clamp_bonus=主角攻击面专享、discount_shift=折扣档面)
if String(h.get("kind", "")) == "modify_ticket" and h.has("delta") and String(h.get("mode", "")) == "":
cdelta += int(h.delta)
var dealt: int = DamageMath.counter_component(int(t.base_value), cdelta, int(db.settlement.damage_floor))
units.apply_damage(target, dealt)
emit_row_cb.call("damage", String(t.source_class), t.origin_cell, int(t.round_index), "%s → %s" % [String(t.display), String(target.display_name)], dealt,
{"target": String(target.display_name), "attack_type": String(t.attack_type), "effectiveness": delta}, String(t.highlight))
{"target": String(target.display_name), "attack_type": String(t.attack_type), "effectiveness": cdelta}, String(t.highlight))
_outcomes[int(t.ticket_id)] = "redeemed"
@@ -418,23 +519,6 @@ func _counter_delta(attack_type: String, armor: String) -> int:
return int(row.get(armor, 0))
# 克制点直调(迭代 12 T2 魔法流/T4 穿刺流 clamp_modifier 件——克制矩阵查表值后的特性调整;
# 空旗=0 零扰动):魔网织者=magic vs magic(矩阵罚 −1 → 0/正);湛蓝誓约=magic vs heavy(+1 → +2);
# 猎手刺剑=pierce vs light(+1——对轻甲敌穿刺提升,对重甲无增益=正负双修)。hero_attack 与
# board_typed 两消费面同享。
func _feat_clamp_bonus(attack_type: String, armor: String) -> int:
var bonus := 0
if attack_type == "magic":
if armor == "magic":
bonus += int(feat_flags.get("clamp_magic_magic", 0))
elif armor == "heavy":
bonus += int(feat_flags.get("clamp_magic_heavy", 0))
elif attack_type == "pierce":
if armor == "light":
bonus += int(feat_flags.get("clamp_pierce_light", 0))
return bonus
# 折扣档改善(迭代 12 T4 猎弱本能——折扣表向全额方向移 value 档;查不到当前档 = 不动防御口径)
func _discount_shift_up(discount: int, shift: int) -> int:
var tbl: Array = db.settlement.roll_tier_discounts
@@ -444,9 +528,6 @@ func _discount_shift_up(discount: int, shift: int) -> int:
return int(tbl[mini(tbl.size() - 1, idx + shift)])
# 淬毒刃纹 N(迭代 11 同调批 T5——战斗结算 begin_battle 注入;0 = 未装配零扰动)
var attune_venom: int = 0
# 池内加算 → clamp [-100,+100](池间乘算归 DamageMath.pool_damage 调用侧)
func clamped_pool(pool: String) -> int:
var total := 0
+343
View File
@@ -0,0 +1,343 @@
# VERTICAL SLICE - NOT FOR PRODUCTION
# Date: 2026-10-06(迭代 17 卡⓪ 内容数据驱动扩展批 T1——效果引擎框架)
# 内容数据驱动扩展(任务书 design/research/任务书-内容数据驱动扩展批-2026-10-06.md;设计权威
# design/research/研究-内容数据驱动扩展架构-2026-10-06.md):把「内容的效果行为」从散布在结算
# 代码里的硬编码分支搬进内容数据行三个字段——订阅哪个事件(on)/ 什么条件(when)/ 什么效果(do)
# ——由本解释器统一执行。完成后加一件「已有效果类型」的新专长/新秘宝=只改 .tres 数据行,零代码。
# 架构模型(R1 裁决):发布订阅——结算管线同步 emit 事件(无队列无异步,确定性优先)→ 本引擎遍历
# 持有订阅集匹配 → 返回按声明序排列的效果命中(do 列表),由发射点按组合规则施加。
# 多订阅与冲突(R3 裁决):一事件多订阅=常态;冲突在效果类型层用组合规则封死(§3.4 六族);遍历序
# =数据表声明序(feats 表序→treasure 表序→树规则合成行,装载时定死),写死保种子复放。
# 重建时机(v1.1 补):每战 begin_battle 从持有集/装备集重建 trigger 列表——冒险中途获得/换取的
# 专长下一战生效,同战内不热载,确定性优先。计数器账本随重建清零(battle 域)。
# 确定性契约:全同步调用、零 RNG、零 signal 时序依赖;同输入同命中序。
# 护栏保留:事件/效果/事实/算子四词表封闭(本文件常量),行内出域=加载期校验致命(schema 侧),
# 运行期 dispatch 对未知事件/效果类型 fail-fast(push_error+断言)。
class_name EffectEngine
extends RefCounted
## 事件词汇(16 个发射点——任务书 §3.1 定稿;4 个登记暂不做事件不入本表)
const EVENTS := ["dig_reveal", "dig_paid", "flag_hit", "mine_hit", "attack_commit", "clamp_check",
"armor_roll", "kill", "damage_taken", "enemy_hp_threshold", "round_start", "flag_settle",
"round_end", "reward_roll", "treasure_used", "charge_full"]
## 扫雷侧事件集(🔴 流派扫雷触发铁律新形态:每流派 ≥1 行订阅本集事件——schema 加载校验。
## 原 MINE_HOOKS 的同义迁移:挖掘/标旗/轮末结算面事件)
const MINE_EVENTS := ["dig_reveal", "dig_paid", "flag_hit", "mine_hit", "flag_settle", "round_end", "reward_roll"]
## 效果类型词汇(解释器 switch 闭集——任务书 §3.3 定稿 19 行;类型实数 24,含共享行拆型:
## grant_gp/bias_wallet、counter_add/counter_spend、reveal_tiles/remove_mines/refresh_pick、
## bias_rewards/preview。任务书标题计 23 系笔误,落码按行内容全收——commit 留痕)
const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open_ticket",
"attack_bonus", "attack_segments", "yield_mult", "spawn_spell", "overflow", "grant_material",
"grant_ap", "grant_gp", "bias_wallet", "shield", "spike", "apply_status", "counter_add",
"counter_spend", "rewrite_board", "reveal_tiles", "remove_mines", "refresh_pick",
"bias_rewards", "preview"]
## fact 条件词汇(封闭枚举 9 项——任务书 §四定稿)
const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_armor_class",
"flags_count", "charge_layers", "nest_count", "round_index", "counter"]
## when 算子词汇(封闭——fact 查询面落法随批登记:mod_zero=计数器取模判满〔掘进蓄能〕、
## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较〔深挖钻头配额〕、
## ends_with=后缀匹配〔对某甲族的泛条件〕。均系映射表现状条件装进 9 项 fact 的查询面落法,
## 代拍板白名单覆盖,commit 留痕)
const OPS := ["eq", "neq", "gt", "gte", "lt", "lte", "ends_with", "has", "mod_zero",
"advantageous", "gte_ref", "lt_ref"]
## when 条件键白名单(trigger 行 when 数组元素键)
const WHEN_KEYS := ["fact", "op", "value", "id", "ref", "value_from"]
## do 效果键白名单(trigger 行 do 字典键——零裸 flat 同族护栏:kind 外键全部参数引用面)
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",
"reset_at", "set", "status_id", "label", "fallback", "target_kinds", "trade_atk", "trade_hit"]
## 主动件分发通道(不经事件订阅——刷新/显影/移除是玩家主动动作;use_treasure 按 kind 分发)
const ACTIVE_KINDS := ["reveal_tiles", "preview", "grant_ap", "remove_mines", "refresh_pick"]
# ---- 订阅集与计数器账本 ----
var _triggers: Array = [] # [{source, id, on, when, do}](装载序=声明序,重建时定死)
var _counters: Dictionary = {} # counter_id → int(battle 域账本;重建清零;重置点由订阅行声明)
var _reset_on_round_start: Array[String] = [] # round_start 重置点计数器名单(装载时收集)
var db: ConfigDb # 矩阵/表读取(advantageous 算子消费)——可空(纯计数器用法零依赖)
func _init(db_ref: ConfigDb = null) -> void:
db = db_ref
## 订阅装载(每战 begin_battle 调用——重建时机 v1.1):feats 表序→treasure 表序(各按持有/装备
## 集过滤)→树规则合成行。同一数据行的多个 trigger 按行内数组序。计数器账本同步清零并按订阅行
## 声明收集重置点(round_start)。
func rebuild(feat_ids: Array, item_ids: Array, tree_rules: Array = []) -> void:
_triggers.clear()
_counters.clear()
_reset_on_round_start.clear()
if db != null and db.feats != null:
for row in db.feats.rows:
var fid := String(row.get("feat_id", ""))
if not feat_ids.has(fid):
continue
for tr in (row.get("triggers", []) as Array):
_push_trigger("feat", fid, tr, row)
if db != null:
for row in db.treasure_attunement_rows():
var iid := String(row.get("item_id", ""))
if not item_ids.has(iid):
continue
for tr in (row.get("triggers", []) as Array):
_push_trigger("attune", iid, tr, row)
# 树规则合成订阅(T5——规则键效果走同面:非数据行,词表同闭集)
for key_v in tree_rules:
var rk := String(key_v)
match rk:
"posture_first_strike":
_push_trigger("tree", rk, {"on": "round_start",
"when": [{"fact": "round_index", "op": "eq", "value": 1}],
"do": {"kind": "grant_ap", "mode": "queue", "value": 1}}, {})
"posture_bulwark":
_push_trigger("tree", rk, {"on": "damage_taken",
"do": {"kind": "shield", "value": 1}}, {})
func _push_trigger(source: String, id: String, tr: Dictionary, row: Dictionary) -> void:
var on := String(tr.get("on", ""))
assert(EVENTS.has(on), "[效果引擎] 订阅事件出域: %s(%s %s)" % [on, source, id])
var do_d: Dictionary = (tr.get("do", {}) as Dictionary).duplicate(true)
# *_from 解析(rebuild 时把行字段引用定影为值——value_from:"magnitude" → value=行 magnitude)
for pair in [["value_from", "value"], ["delta_from", "delta"], ["mult_from", "mult"], ["cap_from", "cap"]]:
if do_d.has(pair[0]):
do_d[pair[1]] = int(row.get(String(do_d[pair[0]]), 0))
do_d.erase(pair[0])
# when value_from 同面解析(行字段引用条件——dawn_order effective_rounds 先例:字面量出行=数值
# 单一事实源破面,行引用随 rebuild 定影)
var when_d: Array = (tr.get("when", []) as Array).duplicate(true)
for c_v in when_d:
var c: Dictionary = c_v as Dictionary
if c.has("value_from"):
c["value"] = int(row.get(String(c["value_from"]), 0))
c.erase("value_from")
var t := {"source": source, "id": id, "on": on,
"when": when_d,
"do": do_d}
_triggers.append(t)
# 计数器重置点收集(counter_add/counter_spend 行声明 reset_at)
if do_d.has("counter_id") and String(do_d.get("reset_at", "")) == "round_start":
var cid := String(do_d.counter_id)
if not _reset_on_round_start.has(cid):
_reset_on_round_start.append(cid)
## 订阅查询面(发射点缺省行为仲裁用——如 round_end 无 transfer 订阅时走 RAP 转存)
func has_effect_on(event: String, kind: String, mode: String = "") -> bool:
for tr in _triggers:
if String(tr.on) != event:
continue
var d: Dictionary = tr.do
if String(d.get("kind", "")) == kind and (mode == "" or String(d.get("mode", "")) == mode):
# 有 when 时不能预判命中(发射点缺省行为保守按「可能命中」计——命中由 dispatch 定夺)
return true
return false
## 事件分发(发射点唯一入口):返回命中效果列表(装载序=声明序;零命中=空数组零扰动)。
## payload = 事件现场(fact 取值第一优先源);facts = 补充事实面(charge_layers/nest_count 等
## 运行态读数 Callable——payload 未带时回落)。
func dispatch(event: String, payload: Dictionary, facts: Callable = Callable()) -> Array:
assert(EVENTS.has(event), "[效果引擎] 未知事件: %s(发射点出域)" % event)
if event == "round_start":
for cid in _reset_on_round_start:
_counters[cid] = 0
var hits: Array = []
for tr in _triggers:
if String(tr.on) != event:
continue
if not _when_ok(tr.when, payload, facts):
continue
hits.append(tr.do)
return hits
## 计数器读数(fact counter 与发射点配额面共用)
func counter(counter_id: String) -> int:
return int(_counters.get(counter_id, 0))
func counter_add(counter_id: String, value: int, set_mode: bool = false) -> void:
if set_mode:
_counters[counter_id] = value
else:
_counters[counter_id] = int(_counters.get(counter_id, 0)) + value
## 计数器消耗(counter_spend 组合规则——按订阅序消耗共享资源,耗尽即止):
## 返回 true=消耗成功;false=资源不足(调用方按 reason 通道拒绝)。
func counter_spend(counter_id: String, value: int) -> bool:
var cur := int(_counters.get(counter_id, 0))
if cur < value:
return false
_counters[counter_id] = cur - value
return true
# ---- when 判定(条件谓词——零随机全确定) ----
func _when_ok(when: Array, payload: Dictionary, facts: Callable) -> bool:
for c_v in when:
if not _cond_ok(c_v as Dictionary, payload, facts):
return false
return true
func _cond_ok(c: Dictionary, payload: Dictionary, facts: Callable) -> bool:
var fact := String(c.get("fact", ""))
var op := String(c.get("op", "eq"))
var val = c.get("value", null)
var actual = _fact_value(fact, c, payload, facts)
match op:
"eq":
return str(actual) == str(val)
"neq":
return str(actual) != str(val)
"gt":
return int(actual) > int(val)
"gte":
return int(actual) >= int(val)
"lt":
return int(actual) < int(val)
"lte":
return int(actual) <= int(val)
"ends_with":
if val is Array:
for v in (val as Array):
if String(actual).ends_with(String(v)):
return true
return false
return String(actual).ends_with(String(val))
"has":
# 在场判定(fact 查询面落法——代拍板白名单,commit 留痕):value 缺省=非空判定
# (terrain_kind fact:伤害型变异集非空=挖开伤害型地形格/邻格有伤害型地形/地形伤种类在场);
# value 给定=数组包含判定(保留泛用面)。
if c.has("value"):
if actual is Array:
return (actual as Array).has(val)
return false
if actual is Array:
return not (actual as Array).is_empty()
return String(actual) != ""
"mod_zero":
var m := int(val)
return m > 0 and int(actual) % m == 0
"advantageous":
# 克制矩阵正面判定(matchup = "{attack_type}_vs_{armor}"——矩阵值 > 0 = 克制成立)
return _counter_delta_of(String(actual)) > 0
"gte_ref":
return int(actual) >= counter(String(c.get("ref", "")))
"lt_ref":
return int(actual) < counter(String(c.get("ref", "")))
assert(false, "[效果引擎] when 算子出域: %s" % op)
return false
func _fact_value(fact: String, c: Dictionary, payload: Dictionary, facts: Callable):
match fact:
"counter":
return counter(String(c.get("id", "")))
_:
# fact 取值序:payload 同名字段优先 → 补充事实面(发射点注入的运行态读数)
if payload.has(fact):
return payload[fact]
if facts.is_valid():
return facts.call(fact)
return null
## 克制矩阵读值(advantageous 算子消费——与伤害控制器 _counter_delta 同源同表)
func _counter_delta_of(matchup: String) -> int:
if db == null or matchup == "" or not matchup.contains("_vs_"):
return 0
var parts := matchup.split("_vs_")
if parts.size() != 2:
return 0
var tbl: Dictionary = db.settlement.armor_effectiveness
var row: Dictionary = tbl.get(String(parts[0]), {})
return int(row.get(String(parts[1]), 0))
## ---- 加载期校验(schema 侧共用——单一事实源;悬空引用/词表出域=致命) ----
## trigger 行校验:返回该行是否含扫雷侧事件订阅(流派铁律聚合面)。
## row 用于 value_from 类引用的字段存在性判定(悬空=加载致命)。
static func validate_trigger_row(rid: String, row: Dictionary, triggers: Array, errs: Array) -> bool:
var mine_covered := false
for tr_v in triggers:
var tr: Dictionary = tr_v as Dictionary
for k in tr.keys():
if not ["on", "when", "do"].has(String(k)):
errs.append({"category": "zero_flat", "message": "%s trigger 键出白名单: %s" % [rid, String(k)]})
var on := String(tr.get("on", ""))
if not EVENTS.has(on):
errs.append({"category": "enum", "message": "%s 订阅事件出域(事件词汇封闭): %s" % [rid, on]})
elif MINE_EVENTS.has(on):
mine_covered = true
for c_v in (tr.get("when", []) as Array):
var c: Dictionary = c_v as Dictionary
for k in c.keys():
if not WHEN_KEYS.has(String(k)):
errs.append({"category": "zero_flat", "message": "%s when 键出白名单: %s" % [rid, String(k)]})
var fact := String(c.get("fact", ""))
if not FACTS.has(fact):
errs.append({"category": "enum", "message": "%s fact 出域(事实词汇封闭 9 项): %s" % [rid, fact]})
if not OPS.has(String(c.get("op", "eq"))):
errs.append({"category": "enum", "message": "%s when 算子出域: %s" % [rid, String(c.get("op", ""))]})
var do_d: Dictionary = tr.get("do", {}) as Dictionary
for k in do_d.keys():
if not DO_KEYS.has(String(k)):
errs.append({"category": "zero_flat", "message": "%s do 键出白名单: %s(机制轴禁无条件属性加项)" % [rid, String(k)]})
var kind := String(do_d.get("kind", ""))
if not EFFECT_KINDS.has(kind):
errs.append({"category": "enum", "message": "%s 效果类型出域(解释器闭集): %s" % [rid, kind]})
# value_from/delta_from/mult_from/cap_from 引用面:行字段存在性(悬空=加载致命)——
# do 与 when 两侧同面(when value_from=dawn_order effective_rounds 先例)
for vf_k in ["value_from", "delta_from", "mult_from", "cap_from"]:
if do_d.has(vf_k):
var fld := String(do_d.get(vf_k, ""))
if fld != "" and not row.has(fld):
errs.append({"category": "dangling", "message": "%s do.%s 悬空(行无字段 %s)" % [rid, vf_k, fld]})
for c_v in (tr.get("when", []) as Array):
var c_w: Dictionary = c_v as Dictionary
if c_w.has("value_from"):
var wfld := String(c_w.get("value_from", ""))
if wfld != "" and not row.has(wfld):
errs.append({"category": "dangling", "message": "%s when.value_from 悬空(行无字段 %s)" % [rid, wfld]})
return mine_covered
## 组合规则(任务书 §3.4 六族——效果类型的必填属性,发射点施加面引用)
## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap(非 transfer)、
## counter_add、shield——发射点逐条累加收集器。
## 乘法族(收集后一次施加,正负分桶):yield_mult、damage_mult。
## 任意真族(任一命中即生效):spawn_spell、overflow、spike。
## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。
## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、grant_ap(mode:transfer)、
## rewrite_board、apply_status——发射点逐条执行。
static func combo_of(kind: String) -> String:
match kind:
"add_ticket_rider", "attack_bonus", "grant_material", "counter_add", "shield":
return "additive"
"grant_ap":
return "additive" # mode:transfer 由发射点即时执行族承载(转移非加法)
"yield_mult", "damage_mult":
return "multiplicative"
"spawn_spell", "overflow", "spike":
return "any_true"
"modify_ticket":
return "ordered_write"
"counter_spend":
return "ordered_spend"
"open_ticket", "rewrite_board", "apply_status":
return "immediate"
return "immediate" # 默认即时执行(每条命中各自执行一次)
+1
View File
@@ -0,0 +1 @@
uid://dgo4b5frip3e5
+2 -15
View File
@@ -30,21 +30,8 @@ static func tiers_for(feat_ids: Array, table: FeatTable) -> Dictionary:
return out
## 挂点投影:持有集 → [{feat_id, hook, archetype, tier, effects}](表序稳定——同集合同投影,
## MC 逐位可复放承载)
static func hooks_for(feat_ids: Array, table: FeatTable) -> Array:
var out: Array = []
for rid in feat_ids:
var row: Dictionary = table.row_by_id(String(rid)) if table != null else {}
if row.is_empty():
continue
out.append({
"feat_id": String(row.get("feat_id", "")),
"hook": String(row.get("hook", "")),
"archetype": String(row.get("archetype", "")),
"effects": (row.get("effects", {}) as Dictionary).duplicate(true),
})
return out
## 挂点投影随 T3 退役(内容数据驱动扩展批——hook 词族消亡:订阅投影=效果引擎 rebuild 装载序
## (feats 表序),投影稳定性由 EffectEngine._triggers 声明序承载)
## 成型判读(读数面口径):流派 tier ≥1 = 成型(档一即判——任务书完成定义「标签+档位激活引擎可判成型」)
+8
View File
@@ -865,6 +865,14 @@ func shop_refresh() -> bool:
return true
# GP 冒险钱包单口支出(2026-10-06——三选一 GP 付费刷新与商店刷新共用同一钱包;余额不足 false 零副作用)
func spend_gp(amount: int) -> bool:
if amount <= 0 or gp < amount:
return false
gp -= amount
return true
# 购买(pool 模式唯一购买口):在架(kind→在架令牌)/余额前置校验零副作用 → handler 消费在架
# 令牌本体(kind+tier——_apply_curio_pick 同口写加算区+账本+摘牌,跨渠道共库)→ 出账 → 进店购买
# 次计数 → wallet 事件 → 三件全重抽(未买不保留——重抽绑购买,无独立刷新动作)
+19 -6
View File
@@ -23,6 +23,12 @@ var _granted := {} # Vector2i → 快照(重复受理幂等返
var _clear_identity := ""
var _clear_granted := false
var _clear_snapshot := {}
# 效果引擎(内容数据驱动扩展批 T1——reward_roll 发射面;偏运硬币 bias_rewards 订阅面)
var _fx: EffectEngine = null
func set_fx(fx: EffectEngine) -> void:
_fx = fx
func _init(db_ref: ConfigDb, rng_ref: RngServiceCore) -> void:
@@ -59,7 +65,14 @@ func roll_board(eligible: Array) -> bool:
_clear_granted = false
_clear_snapshot = {}
var stream: RandomNumberGenerator = rng.open_stream("reward_roll") # 恰一 scope 批(格批 + 清图批尾 + 区间行追加取号)
var cell_rows: Array = _biased_cell_rows() # cell 池正向行 weight>0(偏运硬币装配时稀有正向 kinds 权重 +N——池结构零触碰)
# reward_roll 发射+施加(内容数据驱动扩展批 T4——格面资源掷定、摇号前权重合成层:
# bias_rewards 订阅命中合计=偏运权重加算(行 value_from magnitude 定影);零命中=原行集零扰动)
var luck_bias := 0
if _fx != null:
for h in _fx.dispatch("reward_roll", {"polarity": "positive", "cell_count": list.size()}):
if String(h.get("kind", "")) == "bias_rewards":
luck_bias += int(h.get("value", 0))
var cell_rows: Array = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(偏运硬币装配时稀有正向 kinds 权重 +N——池结构零触碰)
var clear_rows: Array = _pool_rows("clear_default")
# ① 身份批:每非封锁格恰一类型身份(雷安同池——同一行集同一权重分布)
var draft := {}
@@ -174,8 +187,8 @@ func polarity_row(cell_type: String, polarity: String) -> Dictionary:
# ---- F1 选行算子纯函数 ----
# 偏运硬币 N(迭代 11 同调批 T5——战斗结算 begin_battle 注入;0 = 未装配零扰动)
var luck_bias: int = 0
# 偏运硬币 N(迭代 11 同调批 T5 → 内容数据驱动扩展批 T4:begin_battle 注入拆除——
# reward_roll bias_rewards 订阅命中合计经 _biased_cell_rows 入参;0 = 未装配零扰动)
# 稀有正向资源 kinds(底稿 §3——权重投影面,池结构零触碰)
const LUCK_BIAS_KINDS := ["heal", "gp", "pierce", "magic"]
@@ -192,15 +205,15 @@ const SKEW_UP_KINDS := ["attack", "blast", "pierce", "magic"]
# 偏运硬币权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动)
# 基座换源(首发批 2026-10-04):先经图级偏斜投影再叠件级加法——合成序锚=图级先、件级后
#(环境事实先定型、玩家构筑叠其上;两投影均为池内权重面,雷安同池与取号次数零变化)
func _biased_cell_rows() -> Array:
func _biased_cell_rows(bias: int) -> Array:
var base: Array = _skewed_cell_rows()
if luck_bias <= 0:
if bias <= 0:
return base
var out: Array = []
for row in base:
if LUCK_BIAS_KINDS.has(String(row.get("cell_type", ""))):
var biased: Dictionary = row.duplicate()
biased["weight"] = int(row.weight) + luck_bias
biased["weight"] = int(row.weight) + bias
out.append(biased)
else:
out.append(row)
+1 -1
View File
@@ -2,7 +2,7 @@
# Validation Question: 玩家能否无指导在一场完整战斗中经历「开战→挖掘规划→轮末结算逐行兑现→胜/负」并逐行归因(P2)
# Date: 2026-09-16
# 敌人系统·战斗单位容器:hero/enemy 统一受伤死亡接口 · 实例池状态机(敌人技能池批——2026-09-16 用户拍板,
# 设计权威 docs/proposal-skill-pool.md v1.0)· 行值快照抗热重载 · 编排被动零事件。
# 设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0)· 行值快照抗热重载 · 编排被动零事件。
# 实例池三层对象(proposal §2.2):定义层技能行(SkillTable)· 定义层池模板(EnemyTable.pool)·
# 本类持实例层——spawn 把模板快照为各实例池(冷却全零),此后冷却递减/待发动作/保底计数各自独立。
# 零随机零事件纪律(proposal 约束二):随机消费只在 战斗结算换算层抽签器(SkillLottery + behavior_roll 子流);
+17
View File
@@ -80,6 +80,23 @@ const TIER_QUOTAS := {"common": 70, "rare": 25, "rarest": 3}
@export var feat_ticket_pity_step: int = 5 # [1,99] knob(口径定死=5)——保底步数(连续未出展示次数)
## 令牌兑付路由表(内容数据驱动扩展批 T5——_apply_curio_pick match 收敛进效果类型:
## 属性值提升四类 = 「加算落点键」声明路由,加新加算类令牌 = 表行+配额/件值键,零代码;
## 通道面三类(gp 钱包/heal 台账/refresh 界面余量)+relic 持有集 = 副作用通道显式分支不进本表
## ——路由表只承载「纯加算落点」形态,与效果引擎组合规则加法族同构)
const CURIO_APPLY_ROUTES := {
"attack": "atk",
"max_hp": "max_hp",
"armor": "armor_class",
"ap": "ap",
}
## 令牌加算路由读数(空 = 非加算形态——调用方走通道面分支)
func curio_apply_route(kind: String) -> String:
return String(CURIO_APPLY_ROUTES.get(kind, ""))
## 令牌配额读数(未列 kind×tier 组合 = 0——heal 无普通档/ap 无普通稀有档按 v2.2 构成)
func curio_quota(kind: String, tier: String) -> int:
match [kind, tier]:
+1 -1
View File
@@ -3,7 +3,7 @@
# Date: 2026-09-10
# 数据配置 EnemyTable / HeroTable schema(敌人系统 回填值)。EnemyTable 键 (L,D,enemy_id),每行集恰一敌种;
# HeroTable 单行全局(Rule 4 豁免)。依据 design/gdd/systems/战斗循环/敌人系统.md Schema 节。
# 敌人技能池批(2026-09-16 用户拍板,设计权威 docs/proposal-skill-pool.md v1.0):pattern 行为环数组与
# 敌人技能池批(2026-09-16 用户拍板,设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0):pattern 行为环数组与
# heavy_multiplier 退役,改池模板 pool = [{skill_id, weight}](定义层——实例池快照与冷却状态在 单位容器)。
# 池构成纪律(每池恰一行普攻、增益 ≤1、skill_id 悬空致命)需跨表视野,校验在 ConfigDB 跨表通道。
class_name EnemyTable
+31 -74
View File
@@ -1,7 +1,8 @@
# VERTICAL SLICE - NOT FOR PRODUCTION
# Validation Question: 七核心流派各 ≥3 件入局内随机渠道后,标签+档位激活引擎能否机械判「成型」、
# 专长带能否挂进令牌池稀有/罕见档随机投放(P0——迭代 12 双层 BD 实施批 T1)
# Date: 2026-10-04(双层 BD 实施批 T1——任务书五裁定稿;设计权威 双层BD体系-整合定稿-2026-10-03 v3)
# Date: 2026-10-06(内容数据驱动扩展批 T3——行换代:hook/effects 挂点形态退役,triggers 事件订阅形态
# 唯一合法行形——旧 23 挂点枚举消亡:事件名+效果类型取代,任务书 R4 裁决)
# 概念指路:本表的专长,与 adventure.tres 的属性值提升、资源,同属一个对象——
# 「奇物」(一次冒险内各渠道给予玩家的增益总称)。定义见 design/gdd/systems/冒险循环/奇物.md。
# 它们是它分类轴上的枚举(专长 / 属性值提升 / 资源),不是三套系统;本表承载「专长」(专长 Feat)的逐项定义。
@@ -11,16 +12,15 @@
# 数据配置 FeatTable schema(奇物·专长定义表;行 = Dictionary 键 feat_id,Rule 4 豁免
# 定义表——TreasureItemTable 先例)。
# 行字段:feat_id 主键 / display_name / rarity ∈ {common, rare, rarest}(对齐令牌池三档命名——
# 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档=「挂稀有/罕见档」
# 追认 b 接线口径)/ archetype ∈ ARCHETYPES 七流派标签 / hook ∈ HOOKS 挂点枚举(结算段槽——整合定稿
# §2.1 哈迪斯恩赐槽同构)/ effects Dictionary(hook 消费参数,provisional 投值)。
# 正负双修(整合定稿 B2 判据):effects 允许负向键(cost_* 族)——纯增益件须专项论证(反例 B-3),加载期
# 仅校验键域不禁纯增益(专项论证件以 positive_only 批注登记,人工清单呈报)。
# 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档)/
# archetype ∈ ARCHETYPES 七流派标签 / desc 效果说明(文案表值化——呈现层读行,零硬编码)/
# triggers 订阅行数组(订阅哪个事件 on / 什么条件 when / 什么效果 do——效果引擎 EffectEngine
# 统一解释执行;四词表封闭校验=EffectEngine.validate_trigger_row 单一事实源)。
# 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二
# (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 FeatsEngine。
# 🔴 层级纪律(任务书红线 2):专长只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
# (treasure_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
# 违反=红线①触碰面)。
# (treasure_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行订阅扫雷侧事件
# (EffectEngine.MINE_EVENTS——加载校验,违反=红线①触碰面)。
class_name FeatTable
extends Resource
@@ -32,58 +32,20 @@ const ARCHETYPES := ["magic", "pierce", "normal", "dig", "flag", "charge", "devo
## 稀有度词表(对齐令牌池三档;投放档映射 relic→rare / rarest→rarest)
const RARITIES := ["common", "rare", "rarest"]
## 挂点枚举(结算段槽——首批 23 点位;每 hook 恰一流派域消费,T2-T6 接线)
const HOOKS := [
# 魔法流
"hero_attack_rider", # 普攻命中后追加必中魔法伤(奥术余烬/魔能共鸣)
"clamp_modifier", # 克制点直调(魔网织者/湛蓝誓约/猎手刺剑)
"first_dig_spell", # 每关首次开格必出魔法矢(魔能共鸣第二效果)
# 穿刺流
"kill_overflow", # 击杀溢出弹射(贯穿射击)
"dig_count_segments", # 开格计数转攻击段数(连珠矢)
"roll_discount", # 折扣档改写(猎弱本能前移一档)
# 普攻流
"round_dig_bonus", # 轮内安全开格数转攻击加成(矿工的执拗;踩雷清零=mine_hit 监听同口)
"hit_trade", # 命中交换(矿工重锤——正负双修原生形态)
"armor_roll_rewrite", # 免掷骰恒折扣(专注)
"heavy_debuff", # 命中重甲附加护甲裂解(碎甲震击)
# 开格流
"dig_yield_mult", # 开格产出乘区(贪婪矿灯/矿脉直觉/赌徒的血签——正负双向)
"deep_dig", # 深层资源掘取(深挖钻头——R4 甲非信息税形态:开掘额外 AP 代价)
# 标旗流
"flag_resource", # 标中雷获格面资源(雷区图谱)
"nest_aura", # 控制巢穴数转伤害光环(猎巢人)
"flag_all_hit", # 同轮全中旗伤倍增(完美布防)
"flag_strike", # 轮末旗伤开单(战旗军规——复用 board_typed)
# 蓄力流
"ap_carry", # 轮末 AP 结转蓄力(整备军备——改写 cleared 作废口径)
"charge_shield", # 蓄力层转减伤(铁壁整备)
"charge_spike", # 满层 spike(厚积薄发)
# 吞噬流
"terrain_refund", # 受地形伤掉落资源补偿(地脉采撷——伤害仍发生)
"terrain_dig_double", # 挖开伤害型地形格双产出(荆棘编织者)
"flag_neutralize", # 标中旗中和相邻伤害型地形格(净化工兵——🔴 R4 甲仅限伤害型)
"variant_counter", # 受地形伤积层轮末反打(熔火之躯——触发键不按地形种类特化)
]
## 行键白名单(🔴 零裸 flat 同族护栏——键出域=加载致命;triggers/desc=T3 换代新形态)
const ROW_KEYS := ["feat_id", "display_name", "rarity", "archetype", "triggers", "desc", "note"]
## 扫雷结算触发点 hook 集(🔴 红线①承载:每流派 ≥1 行 hook 命中本集——加载校验)
const MINE_HOOKS := ["first_dig_spell", "dig_count_segments", "round_dig_bonus", "dig_yield_mult",
"deep_dig", "flag_resource", "nest_aura", "flag_all_hit", "flag_strike", "ap_carry",
"terrain_refund", "terrain_dig_double", "flag_neutralize", "variant_counter"]
## effects 键白名单(🔴 零裸 flat 同族护栏——机制轴禁无条件属性加项;键出域=加载致命)
## 全部条件触发/机制修正参数;cost_* 族=正负双修负向面
const EFFECT_KEYS := ["value", "value2", "tier_value", "per_stack", "cap", "ap_cost", "chance",
"mult", "cost_mult", "cost_flat", "polarity", "spell_kind", "segment_cap", "discount_shift",
"trade_atk", "trade_hit", "shield_per_layer", "spike_mult", "layers_to_shield",
"neutralize_range", "counter_damage", "resource_kind", "rider_kind", "note"]
## trigger 行键(订阅行三字段:on/when?/do)
const TRIGGER_KEYS := ["on", "when", "do"]
func validate() -> Array:
var errs: Array = []
if rows.is_empty():
return errs # 空表合法态(T1 基建先行——T2 起逐流派填行)
return errs # 空表合法态(T1 基建先行——逐流派填行)
var seen := {}
# 流派扫雷覆盖聚合(🔴 红线①铁律——每流派 ≥1 行订阅扫雷侧事件)
var arch_mine := {} # archetype → bool
for row in rows:
var rid: String = row.get("feat_id", "")
if rid == "":
@@ -100,32 +62,27 @@ func validate() -> Array:
var arch := String(row.get("archetype", ""))
if not ARCHETYPES.has(arch):
errs.append({"category": "enum", "message": "%s archetype 出域 %s" % [rid, str(ARCHETYPES)]})
var hook := String(row.get("hook", ""))
if not HOOKS.has(hook):
errs.append({"category": "enum", "message": "%s hook 出域(挂点枚举封闭): %s" % [rid, hook]})
if not row.has("triggers"):
errs.append({"category": "domain", "message": "%s 缺 triggers(订阅形态唯一合法行形)" % rid})
elif EffectEngine.validate_trigger_row(rid, row, row.get("triggers", []) as Array, errs):
arch_mine[arch] = true
for k in row.keys():
if not ["feat_id", "display_name", "rarity", "archetype", "hook", "effects", "note"].has(String(k)):
if not ROW_KEYS.has(String(k)):
errs.append({"category": "zero_flat", "message": "%s 行键出白名单: %s" % [rid, String(k)]})
var fx: Dictionary = row.get("effects", {}) as Dictionary
for ek in fx.keys():
if not EFFECT_KEYS.has(String(ek)):
errs.append({"category": "zero_flat", "message": "%s effects 键出白名单: %s(机制轴禁无条件属性加项)" % [rid, String(ek)]})
# 🔴 红线① 扫雷触发点铁律:**有行的流派**各 ≥1 行 hook ∈ MINE_HOOKS(部分填充合法——T2-T6
# 逐流派渐进;七流派全量覆盖完成度由批次一出口断言承载,加载闸不卡渐进填行)
var archs_with_rows := {}
for row in rows:
archs_with_rows[String(row.get("archetype", ""))] = true
for arch in archs_with_rows.keys():
var covered := false
for row in rows:
if String(row.get("archetype", "")) == String(arch) and MINE_HOOKS.has(String(row.get("hook", ""))):
covered = true
break
if not covered:
errs.append({"category": "load_bearing", "message": "流派 %s 无扫雷结算触发点行(🔴 红线①铁律——每流派 ≥1 件挂扫雷端)" % String(arch)})
# 🔴 红线① 扫雷触发点铁律:**有行的流派**各 ≥1 行订阅扫雷侧事件(MINE_EVENTS 同义校验)
for arch in archs_with_rows():
if not bool(arch_mine.get(arch, false)):
errs.append({"category": "load_bearing", "message": "流派 %s 无扫雷结算触发点行(🔴 红线①铁律——每流派 ≥1 件订阅扫雷侧事件)" % String(arch)})
return errs
func archs_with_rows() -> Array:
var out := {}
for row in rows:
out[String(row.get("archetype", ""))] = true
return out.keys()
func row_by_id(feat_id: String) -> Dictionary:
for row in rows:
if String(row.get("feat_id", "")) == feat_id:
+1 -1
View File
@@ -2,7 +2,7 @@
# Validation Question: 玩家能否无指导在一场完整战斗中经历「开战→挖掘规划→轮末结算逐行兑现→胜/负」并逐行归因(P2)
# Date: 2026-09-16
# 数据配置 SkillTable schema(敌人技能池批——定义层"技能行",敌人系统 回填值;行 = Dictionary,键 skill_id;Rule 4 豁免)。
# 设计权威:docs/proposal-skill-pool.md v1.0 §2.2 字段词汇表。
# 设计权威:proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0 §2.2 字段词汇表。
# 三层对象:技能行(本表,多敌种共享)· 池模板(EnemyTable.pool:{skill_id, weight})· 实例池(单位容器 spawn 快照)。
# 池构成纪律的加载校验在 ConfigDB 跨表通道(每池恰一行普攻、增益 ≤1、skill_id 悬空致命——本表无池视野)。
class_name SkillTable
+21 -10
View File
@@ -38,19 +38,23 @@ const DIMENSIONS := ["info", "risk", "action", "plan", "counter"]
# 同调批扩 enum(迭代 11 第①批 T1)——新增九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。
# cell_removal = 爆破工兵包中立移除格(T7 原位换装时启用——T6 影响评估前置);mine_hit_halve 系固定
# 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。
# 内容数据驱动扩展批 T2 挂账:主动件 kind 词族换代(reveal_tiles/preview/grant_ap/remove_mines/
# refresh_pick——效果引擎 ACTIVE_KINDS 同名闭集),被动件 effect_kinds 词族随 T4 秘宝迁移退役
# (passive 行改 triggers 事件订阅形态);旧词保留共存至迁移完成。
const EFFECT_KINDS := ["mine_reveal", "reward_preview", "ap_grant", "venom_rider", "flag_burst",
"mine_hit_halve", "reflect_damage", "ap_rounds_front", "ap_charge_safe", "cell_removal",
"reward_weight_bias", "bonus_refresh"]
"reward_weight_bias", "bonus_refresh",
"reveal_tiles", "preview", "grant_ap", "remove_mines", "refresh_pick"]
const TARGETS := ["none", "area_3x3", "board_wide"]
const USE_PHASES := ["active_dig"]
const FORMS := ["", "passive", "active_charged"]
# magnitude 消费面(≥1 校验):ap_grant 与同调 N 值 kind;其余 kind 活行 magnitude 恒 0
# magnitude 消费面(≥1 校验):grant_ap 与同调 N 值 kind;其余 kind 活行 magnitude 恒 0
const MAGNITUDE_KINDS := ["ap_grant", "venom_rider", "flag_burst", "reflect_damage", "ap_rounds_front",
"ap_charge_safe", "reward_weight_bias", "bonus_refresh"]
"ap_charge_safe", "reward_weight_bias", "bonus_refresh", "grant_ap"]
# 🔴 零裸 flat 结构护栏:行键白名单封闭(键出域=加载致命)——机制轴禁无条件属性加项的表结构承载
const KEY_WHITELIST := ["item_id", "display_name", "dimension_tags", "effect_kinds", "target",
"magnitude", "use_phase", "retired", "deferred", "form", "charges_per_adventure", "slot_cost",
"unlock_requires", "effective_rounds", "charge_n"]
"unlock_requires", "effective_rounds", "charge_n", "triggers", "desc"]
func validate() -> Array:
@@ -90,6 +94,13 @@ func validate() -> Array:
for k in row.keys():
if not KEY_WHITELIST.has(String(k)):
errs.append({"category": "zero_flat", "message": "%s 行键出白名单: %s(KEY_WHITELIST 外键禁入)" % [iid, String(k)]})
# triggers 事件订阅行(内容数据驱动扩展批 T2/T4——被动件换代形态;与 effect_kinds 互斥校验
# 面=passive 行(换代单形态——效果行为只走订阅);active_charged 行两形合法并存
# (effect_kinds=主动分发通道 + triggers=受理闸订阅,掘进蓄能先例))
if row.has("triggers"):
if (row.get("effect_kinds", []) as Array).size() > 0 and String(row.get("form", "")) != "active_charged" and not bool(row.get("retired", false)):
errs.append({"category": "domain", "message": "%s triggers 与 effect_kinds 并存(换代单形态——被动件迁移期禁双挂)" % iid})
EffectEngine.validate_trigger_row(iid, row, row.get("triggers", []) as Array, errs)
var form: String = String(row.get("form", ""))
if not FORMS.has(form):
errs.append({"category": "enum", "message": "%s form 出域 %s: %s" % [iid, str(FORMS), form]})
@@ -97,8 +108,8 @@ func validate() -> Array:
# 退役/失义行:免 effect_kinds 非空与承重护栏校验(登记面保留,不入投放与 F2)
continue
# ---- 活行校验 ----
if kinds.is_empty():
errs.append({"category": "domain", "message": "%s effect_kinds 空(活行;失义件应标 deferred)" % iid})
if kinds.is_empty() and not row.has("triggers"):
errs.append({"category": "domain", "message": "%s effect_kinds 空(活行;失义件应标 deferred,被动件应挂 triggers 订阅)" % iid})
var kind_seen := {}
for k in kinds:
var kind: String = String(k)
@@ -123,8 +134,8 @@ func validate() -> Array:
mag_consuming = true
if mag_consuming and mag < 1:
errs.append({"category": "cross_field", "message": "%s N 值 kind 行 magnitude 应 ≥1,实得 %d" % [iid, mag]})
if not mag_consuming and mag != 0:
errs.append({"category": "cross_field", "message": "%s 非 N 值 kind 活行 magnitude 应 0,实得 %d" % [iid, mag]})
if not mag_consuming and mag != 0 and not row.has("triggers"):
errs.append({"category": "cross_field", "message": "%s 非 N 值 kind 活行 magnitude 应 0(trigger 行 magnitude=value_from 取数源豁免),实得 %d" % [iid, mag]})
# ---- 同调行约束(form 非空——装配面;过渡行 form="" 不校验)----
if form != "":
if int(row.get("slot_cost", 1)) != 1:
@@ -139,8 +150,8 @@ func validate() -> Array:
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:
errs.append({"category": "cross_field", "message": "%s ap_rounds_front 行 effective_rounds 应 ≥1(P4 甲表值化),实得 %d" % [iid, eff_rounds]})
if not kind_seen.has("ap_rounds_front") and eff_rounds != 0:
errs.append({"category": "cross_field", "message": "%s 非 ap_rounds_front 行 effective_rounds 应 0,实得 %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))
if charge_n < 0 or charge_n > 999:
errs.append({"category": "domain", "message": "%s charge_n 越域 [0,999]: %d" % [iid, charge_n]})
+390 -92
View File
@@ -9,266 +9,564 @@ rows = [{
"display_name": "奥术余烬",
"rarity": "common",
"archetype": "magic",
"hook": "hero_attack_rider",
"effects": {
"desc": "普攻附加必中伤害",
"triggers": [{
"on": "attack_commit",
"do": {
"kind": "add_ticket_rider",
"value": 1
}
}]
}, {
"feat_id": "mana_weaver",
"display_name": "魔网织者",
"rarity": "rare",
"archetype": "magic",
"hook": "clamp_modifier",
"effects": {
"value": 1,
"polarity": "magic_vs_magic"
"desc": "克制面强化",
"triggers": [{
"on": "clamp_check",
"when": [{
"fact": "matchup",
"op": "eq",
"value": "magic_vs_magic"
}],
"do": {
"kind": "modify_ticket",
"delta": 1
}
}]
}, {
"feat_id": "azure_oath",
"display_name": "湛蓝誓约",
"rarity": "rare",
"archetype": "magic",
"hook": "clamp_modifier",
"effects": {
"value": 1,
"polarity": "magic_vs_heavy"
"desc": "克制面强化",
"triggers": [{
"on": "clamp_check",
"when": [{
"fact": "matchup",
"op": "eq",
"value": "magic_vs_heavy"
}],
"do": {
"kind": "modify_ticket",
"delta": 1
}
}]
}, {
"feat_id": "mana_resonance",
"display_name": "魔能共鸣",
"rarity": "rarest",
"archetype": "magic",
"hook": "first_dig_spell",
"effects": {
"desc": "首格追加奥术矢",
"triggers": [{
"on": "dig_reveal",
"when": [{
"fact": "is_first_dig_of_battle",
"op": "eq",
"value": true
}],
"do": {
"kind": "spawn_spell",
"value": 2
}
}]
}, {
"feat_id": "mine_atlas",
"display_name": "雷区图谱",
"rarity": "common",
"archetype": "flag",
"hook": "flag_resource",
"effects": {
"value": 1
"desc": "标中雷额外得资源",
"triggers": [{
"on": "flag_hit",
"do": {
"kind": "grant_material",
"value": 1,
"label": "(雷区图谱)"
}
}]
}, {
"feat_id": "nest_hunter",
"display_name": "猎巢人",
"rarity": "rare",
"archetype": "flag",
"hook": "nest_aura",
"effects": {
"value": 1
"desc": "控巢攻击光环",
"triggers": [{
"on": "attack_commit",
"do": {
"kind": "add_ticket_rider",
"value": 1,
"per": "nest_count"
}
}]
}, {
"feat_id": "perfect_defense",
"display_name": "完美布防",
"rarity": "rare",
"archetype": "flag",
"hook": "flag_all_hit",
"effects": {
"value": 2
"desc": "全中标旗伤加倍",
"triggers": [{
"on": "flag_settle",
"when": [{
"fact": "flags_count",
"op": "gte",
"value": 1
}],
"do": {
"kind": "modify_ticket",
"value": 2,
"mode": "flag_mult"
}
}]
}, {
"feat_id": "war_banner",
"display_name": "战旗军规",
"rarity": "rarest",
"archetype": "flag",
"hook": "flag_strike",
"effects": {
"value": 2
"desc": "标中旗必中打敌",
"triggers": [{
"on": "flag_settle",
"when": [{
"fact": "flags_count",
"op": "gte",
"value": 1
}],
"do": {
"kind": "open_ticket",
"value": 2,
"channel": "attack"
}
}]
}, {
"feat_id": "pierce_shot",
"display_name": "贯穿射击",
"rarity": "rarest",
"archetype": "pierce",
"hook": "kill_overflow",
"effects": {
"value": 1
"desc": "击杀半额弹射",
"triggers": [{
"on": "kill",
"do": {
"kind": "overflow",
"value": 50
}
}]
}, {
"feat_id": "chain_arrows",
"display_name": "连珠矢",
"rarity": "rare",
"archetype": "pierce",
"hook": "dig_count_segments",
"effects": {
"value": 2,
"cap": 2
"desc": "开格积穿刺矢",
"triggers": [{
"on": "dig_reveal",
"do": {
"kind": "counter_add",
"counter_id": "chain_digs",
"value": 1,
"reset_at": "round_start"
}
}, {
"on": "attack_commit",
"do": {
"kind": "attack_segments",
"value": 2,
"cap": 2,
"per": "dig_streak",
"divisor": 3
}
}]
}, {
"feat_id": "weak_instinct",
"display_name": "猎弱本能",
"rarity": "rare",
"archetype": "pierce",
"hook": "roll_discount",
"effects": {
"value": 1
"desc": "打轻甲更易命中",
"triggers": [{
"on": "clamp_check",
"when": [{
"fact": "matchup",
"op": "ends_with",
"value": "vs_light"
}],
"do": {
"kind": "modify_ticket",
"value": 1,
"mode": "discount_shift"
}
}]
}, {
"feat_id": "hunter_rapier",
"display_name": "猎手刺剑",
"rarity": "common",
"archetype": "pierce",
"hook": "clamp_modifier",
"effects": {
"value": 1,
"polarity": "pierce_vs_light"
"desc": "克制面强化",
"triggers": [{
"on": "clamp_check",
"when": [{
"fact": "matchup",
"op": "eq",
"value": "pierce_vs_light"
}],
"do": {
"kind": "modify_ticket",
"delta": 1
}
}]
}, {
"feat_id": "miner_stubborn",
"display_name": "矿工的执拗",
"rarity": "common",
"archetype": "normal",
"hook": "round_dig_bonus",
"effects": {
"desc": "开格越多打得越疼",
"triggers": [{
"on": "dig_reveal",
"do": {
"kind": "counter_add",
"counter_id": "stubborn_digs",
"value": 1,
"cap": 5
"reset_at": "round_start"
}
}, {
"on": "mine_hit",
"do": {
"kind": "counter_add",
"counter_id": "stubborn_digs",
"set": 0
}
}, {
"on": "attack_commit",
"do": {
"kind": "add_ticket_rider",
"value": 1,
"cap": 5,
"per": "dig_streak"
}
}]
}, {
"feat_id": "miner_hammer",
"display_name": "矿工重锤",
"rarity": "common",
"archetype": "normal",
"hook": "hit_trade",
"effects": {
"desc": "加伤换命中",
"triggers": [{
"on": "attack_commit",
"do": {
"kind": "modify_ticket",
"trade_atk": 25,
"trade_hit": 2
}
}]
}, {
"feat_id": "focus_mind",
"display_name": "专注",
"rarity": "rare",
"archetype": "normal",
"hook": "armor_roll_rewrite",
"effects": {
"value": 75
"desc": "攻击恒75%折扣",
"triggers": [{
"on": "armor_roll",
"do": {
"kind": "modify_ticket",
"value": 75,
"mode": "armor_rewrite"
}
}]
}, {
"feat_id": "armor_crack",
"display_name": "碎甲震击",
"rarity": "rare",
"archetype": "normal",
"hook": "heavy_debuff",
"effects": {
"value": 25
"desc": "打重甲附加破防",
"triggers": [{
"on": "attack_commit",
"when": [{
"fact": "matchup",
"op": "ends_with",
"value": "vs_heavy"
}],
"do": {
"kind": "apply_status",
"status_id": "off_guard"
}
}]
}, {
"feat_id": "greedy_lantern",
"display_name": "贪婪矿灯",
"rarity": "common",
"archetype": "dig",
"hook": "dig_yield_mult",
"effects": {
"desc": "开格产出放大",
"triggers": [{
"on": "dig_reveal",
"do": {
"kind": "yield_mult",
"mult": 25,
"cost_mult": 25
}
}]
}, {
"feat_id": "vein_intuition",
"display_name": "矿脉直觉",
"rarity": "rare",
"archetype": "dig",
"hook": "dig_yield_mult",
"effects": {
"desc": "开格产出放大",
"triggers": [{
"on": "dig_reveal",
"do": {
"kind": "counter_add",
"counter_id": "dig_combo",
"value": 1
}
}, {
"on": "mine_hit",
"do": {
"kind": "counter_add",
"counter_id": "dig_combo",
"set": 0
}
}, {
"on": "dig_reveal",
"do": {
"kind": "yield_mult",
"mult": 10,
"cap": 5
}
}]
}, {
"feat_id": "gambler_pact",
"display_name": "赌徒的血签",
"rarity": "rarest",
"archetype": "dig",
"hook": "dig_yield_mult",
"effects": {
"desc": "开格产出放大",
"triggers": [{
"on": "dig_reveal",
"do": {
"kind": "yield_mult",
"mult": 50,
"cost_mult": 100
}
}]
}, {
"feat_id": "deep_drill",
"display_name": "深挖钻头",
"rarity": "rare",
"archetype": "dig",
"hook": "deep_dig",
"effects": {
"ap_cost": 1,
"cap": 4
"desc": "开格2AP·产出双份",
"triggers": [{
"on": "dig_paid",
"do": {
"kind": "counter_spend",
"counter_id": "deep_paid_round",
"value": 1,
"reset_at": "round_start",
"fallback": 1
}
}, {
"on": "dig_reveal",
"when": [{
"fact": "counter",
"id": "deep_paid_round",
"op": "gte",
"value": 1
}, {
"fact": "counter",
"id": "deep_given_round",
"op": "lt_ref",
"ref": "deep_paid_round"
}],
"do": {
"kind": "grant_material",
"label": "(深挖)"
}
}, {
"on": "dig_reveal",
"when": [{
"fact": "counter",
"id": "deep_paid_round",
"op": "gte",
"value": 1
}, {
"fact": "counter",
"id": "deep_given_round",
"op": "lt_ref",
"ref": "deep_paid_round"
}],
"do": {
"kind": "counter_add",
"counter_id": "deep_given_round",
"value": 1
}
}]
}, {
"feat_id": "armory_prep",
"display_name": "整备军备",
"rarity": "rarest",
"archetype": "charge",
"hook": "ap_carry",
"effects": {
"value": 1,
"cap": 3
"desc": "剩AP转下轮攻击",
"triggers": [{
"on": "round_end",
"do": {
"kind": "grant_ap",
"mode": "transfer"
}
}, {
"on": "attack_commit",
"do": {
"kind": "attack_bonus",
"value": 1,
"per": "charge_layers"
}
}]
}, {
"feat_id": "iron_wall",
"display_name": "铁壁整备",
"rarity": "rare",
"archetype": "charge",
"hook": "charge_shield",
"effects": {
"shield_per_layer": 1
"desc": "蓄力转减伤",
"triggers": [{
"on": "damage_taken",
"do": {
"kind": "shield",
"value": 1,
"per": "charge_layers"
}
}]
}, {
"feat_id": "patient_burst",
"display_name": "厚积薄发",
"rarity": "rare",
"archetype": "charge",
"hook": "charge_spike",
"effects": {
"value": 2
"desc": "蓄满下轮爆发",
"triggers": [{
"on": "attack_commit",
"when": [{
"fact": "charge_layers",
"op": "gte",
"value": 3
}],
"do": {
"kind": "modify_ticket",
"value": 2,
"mode": "spike"
}
}]
}, {
"feat_id": "ley_harvest",
"display_name": "地脉采撷",
"rarity": "common",
"archetype": "devour",
"hook": "terrain_refund",
"effects": {
"value": 1
"desc": "吃地形伤返资源",
"triggers": [{
"on": "damage_taken",
"when": [{
"fact": "terrain_kind",
"op": "has"
}],
"do": {
"kind": "grant_material",
"label": "(地脉补偿)"
}
}]
}, {
"feat_id": "thorn_weaver",
"display_name": "荆棘编织者",
"rarity": "rare",
"archetype": "devour",
"hook": "terrain_dig_double",
"effects": {
"value": 1
"desc": "挖伤害格双产出",
"triggers": [{
"on": "damage_taken",
"when": [{
"fact": "terrain_kind",
"op": "has"
}],
"do": {
"kind": "grant_material",
"label": "(荆棘编织)"
}
}]
}, {
"feat_id": "purge_sapper",
"display_name": "净化工兵",
"rarity": "rare",
"archetype": "devour",
"hook": "flag_neutralize",
"effects": {
"value": 1
"desc": "标旗中和伤害格",
"triggers": [{
"on": "flag_hit",
"when": [{
"fact": "terrain_kind",
"op": "has"
}],
"do": {
"kind": "rewrite_board"
}
}]
}, {
"feat_id": "magma_body",
"display_name": "熔火之躯",
"rarity": "rarest",
"archetype": "devour",
"hook": "variant_counter",
"effects": {
"desc": "吃地形伤反打全体",
"triggers": [{
"on": "damage_taken",
"when": [{
"fact": "terrain_kind",
"op": "has"
}],
"do": {
"kind": "counter_add",
"counter_id": "magma_layers",
"value": 1
}
}, {
"on": "round_end",
"when": [{
"fact": "counter",
"id": "magma_layers",
"op": "gte",
"value": 1
}],
"do": {
"kind": "open_ticket",
"value": 1,
"per": "magma_layers",
"channel": "blast"
}
}, {
"on": "round_end",
"when": [{
"fact": "counter",
"id": "magma_layers",
"op": "gte",
"value": 1
}],
"do": {
"kind": "counter_add",
"counter_id": "magma_layers",
"set": 0
}
}]
}]
; 双层 BD 实施批(2026-10-04):规则改写型特性表——行 = 特性定义
; (feat_id/display_name/rarity/archetype/hook/effects)。
; T2 魔法流四件(整合定稿 §2.3 S1):奥术余烬〔普通·rider+1 必中附加〕/魔网织者〔稀有·magic vs
; magic 克制罚修正〕/湛蓝誓约〔稀有·magic vs heavy 克制加成〕/魔能共鸣〔罕见锚点·rider+2+每战首次
; 开格奥术矢——「每关首次」字面落地为「每战首次」台账披露待追认〕;magic 档一(≥2 件)rider+1 /
; 档二(≥4 件)rider 可暴击——引擎 tiers_for 承载。T3-T6 逐流派续填(flag 4/pierce 4/normal 4/
; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派的件面)。
; 稀有度→投放档映射:common/rare → 稀有令牌档、rarest → 罕见令牌档(relic 永不入普通令牌档
; ——「规则改写型特性带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。
; 🔴 层级纪律:本表行永不入同调位(treasure_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。
; 数值全 provisional 归 M-4 数值批;effects 键白名单封闭(零裸 flat 同族护栏)。
; 内容数据驱动扩展批(2026-10-06 T3):专长表换代——行 = triggers 事件订阅形态
; (feat_id/display_name/rarity/archetype/desc/triggers——订阅哪个事件 on / 什么条件 when / 什么效果 do)。
; 旧 hook/effects 挂点形态随本批退役(挂点枚举消亡:事件名+效果类型取代——任务书 R4 裁决)。
; 23 挂点逐行移植映射=任务书 §五(等价性对拍底单);desc=文案表值化(呈现层读行,零硬编码)。
; 效果参数值直接写 do 字典(数值单一事实源=本表;效果引擎 DO_KEYS 白名单封闭)。
; 🔴 护栏全部保留:事件/效果/fact/算子四词表封闭(EffectEngine 常量)、行键白名单、悬空引用
; 致命、零裸 flat 禁令、流派扫雷触发铁律(每流派 ≥1 行订阅扫雷侧事件——MINE_EVENTS 同义校验)。
; 映射表对拍注记(T3 落地语义修正,行为等价优先——commit 留痕):
; - terrain_dig_double(荆棘编织者):映射表标 yield_mult(×2),现行为=第二份同格产出兑付
; (grant_material),×2 乘区对 percent 行不等价——落 grant_material。
; - flag_all_hit(完美布防):映射表标 yield_mult(旗伤乘区),现行为=旗伤单值倍增(战旗单据
; 数值改写)——落 modify_ticket(mode:flag_mult)。
; - 连珠矢/矿工的执拗 streak 取数:映射表 on:dig_reveal counter_add 形态与现行为「轮内踩雷全轮
; 清零」不等价(逐格清零后重积≠全轮判定)——计数器行保留(扫雷铁律承载),等价执行读
; attack_commit 载荷 dig_streak(战斗段全轮推导,与迁移前逐位一致)。
; - 厚积薄发:映射表 on:charge_full(满层沿)→spike,现行为=满层持续状态(层数无消耗点,沿触发
; 一次≠持续增强)——落 on:attack_commit + when(charge_layers ≥3) → modify_ticket(mode:spike),
; charge_full 事件仍埋点(R6 框架先行)。
; - 完美布防:「全中」条件装不进 fact 封闭 9 项(需 hits>0 且 misses==0 双读数)——when 落
; flags_count ≥1(可命中保守判定),全中闸=flag_settle 发射点施加面承载(载荷 flags_hit_all
; 仅供观测)——禁私开 fact(停机点纪律),查询面落法=代拍板白名单。
; - 猎巢人/矿工的执拗:映射表标 modify_ticket/attack_bonus,现行为=必中附加通道(伤害控制器
; hero_rider 后置于乘区与下限)——落 add_ticket_rider(per 取数载荷),乘区外恒定兑付逐位一致。
; - 整备军备:现行为双效果(轮末 AP 转蓄力层 + 每层下轮首段攻 +1)——两行订阅:
; round_end grant_ap(mode:transfer) + attack_commit attack_bonus(per:charge_layers)。
; 数值全 provisional 归 M-4 数值批;desc 文案=旧 summaries 表迁移(措辞零变化)。
+94 -11
View File
@@ -10,6 +10,7 @@ rows = [{
"item_id": "probe_dust",
"display_name": "显影尘",
"dimension_tags": ["info", "counter"],
"desc": "效果失义待重定",
"effect_kinds": [],
"target": "none",
"magnitude": 0,
@@ -19,6 +20,7 @@ rows = [{
"item_id": "sapper_order",
"display_name": "工兵令",
"dimension_tags": ["action"],
"desc": "AP +2",
"effect_kinds": ["ap_grant"],
"target": "none",
"magnitude": 2,
@@ -28,6 +30,7 @@ rows = [{
"item_id": "loot_compass",
"display_name": "探宝罗盘",
"dimension_tags": ["plan"],
"desc": "预读 3×3",
"effect_kinds": ["reward_preview"],
"target": "area_3x3",
"magnitude": 0,
@@ -37,6 +40,7 @@ rows = [{
"item_id": "nest_pendulum",
"display_name": "探巢摆钟",
"dimension_tags": ["risk"],
"desc": "真视 3×3",
"effect_kinds": ["mine_reveal"],
"target": "area_3x3",
"magnitude": 0,
@@ -48,6 +52,7 @@ rows = [{
"item_id": "catacomb_scroll",
"display_name": "地穴全图卷",
"dimension_tags": ["info", "plan"],
"desc": "效果失义待重定",
"effect_kinds": [],
"target": "board_wide",
"magnitude": 0,
@@ -57,6 +62,7 @@ rows = [{
"item_id": "blast_kit",
"display_name": "爆破工兵包",
"dimension_tags": ["action", "risk"],
"desc": "AP +4 真视 3×3 移除雷格",
"effect_kinds": ["ap_grant", "mine_reveal", "cell_removal"],
"target": "area_3x3",
"magnitude": 4,
@@ -68,47 +74,108 @@ rows = [{
"item_id": "venom_edge",
"display_name": "淬毒刃纹",
"dimension_tags": ["counter"],
"effect_kinds": ["venom_rider"],
"desc": "克制正面直伤+2",
"target": "none",
"magnitude": 2,
"use_phase": "active_dig",
"form": "passive",
"slot_cost": 1
"slot_cost": 1,
"triggers": [{
"on": "clamp_check",
"when": [{
"fact": "matchup",
"op": "eq",
"value": "pierce_vs_ward"
}],
"do": {
"kind": "modify_ticket",
"delta_from": "magnitude",
"mode": "clamp_bonus"
}
}, {
"on": "clamp_check",
"when": [{
"fact": "matchup",
"op": "eq",
"value": "magic_vs_heavy"
}],
"do": {
"kind": "modify_ticket",
"delta_from": "magnitude",
"mode": "clamp_bonus"
}
}]
}, {
"item_id": "flag_burst",
"display_name": "标中殉爆",
"dimension_tags": ["action"],
"effect_kinds": ["flag_burst"],
"desc": "每标中一旗全体敌受2",
"target": "none",
"magnitude": 2,
"use_phase": "active_dig",
"form": "passive",
"slot_cost": 1
"slot_cost": 1,
"triggers": [{
"on": "flag_hit",
"do": {
"kind": "open_ticket",
"value_from": "magnitude",
"channel": "blast"
}
}]
}, {
"item_id": "nest_counter",
"display_name": "惊巢反制",
"dimension_tags": ["risk"],
"effect_kinds": ["mine_hit_halve", "reflect_damage"],
"desc": "踩雷惩罚减半+反弹2",
"target": "none",
"magnitude": 2,
"use_phase": "active_dig",
"form": "passive",
"slot_cost": 1
"slot_cost": 1,
"triggers": [{
"on": "mine_hit",
"do": {
"kind": "damage_mult",
"value": 50
}
}, {
"on": "mine_hit",
"do": {
"kind": "open_ticket",
"value_from": "magnitude",
"channel": "reflect"
}
}]
}, {
"item_id": "dawn_order",
"display_name": "工兵晨令",
"dimension_tags": ["action"],
"effect_kinds": ["ap_rounds_front"],
"desc": "前3轮每轮AP+1",
"target": "none",
"magnitude": 1,
"use_phase": "active_dig",
"form": "passive",
"slot_cost": 1,
"effective_rounds": 3
"effective_rounds": 3,
"triggers": [{
"on": "round_start",
"when": [{
"fact": "round_index",
"op": "lte",
"value_from": "effective_rounds"
}],
"do": {
"kind": "grant_ap",
"mode": "queue",
"value_from": "magnitude"
}
}]
}, {
"item_id": "dig_charge",
"display_name": "掘进蓄能",
"dimension_tags": ["action"],
"desc": "积点换AP+1",
"effect_kinds": ["ap_charge_safe"],
"target": "none",
"magnitude": 1,
@@ -116,21 +183,37 @@ rows = [{
"form": "active_charged",
"slot_cost": 1,
"charges_per_adventure": 2,
"charge_n": 3
"charge_n": 3,
"triggers": [{
"on": "treasure_used",
"do": {
"kind": "counter_spend",
"counter_id": "dig_charge_bank",
"value": 1
}
}]
}, {
"item_id": "luck_coin",
"display_name": "偏运硬币",
"dimension_tags": ["risk"],
"effect_kinds": ["reward_weight_bias"],
"desc": "稀有资源权重+2",
"target": "none",
"magnitude": 2,
"use_phase": "active_dig",
"form": "passive",
"slot_cost": 1
"slot_cost": 1,
"triggers": [{
"on": "reward_roll",
"do": {
"kind": "bias_rewards",
"value_from": "magnitude"
}
}]
}, {
"item_id": "pick_refresh",
"display_name": "三选一刷新件",
"dimension_tags": ["info"],
"desc": "三选一刷新+1",
"effect_kinds": ["bonus_refresh"],
"target": "none",
"magnitude": 1,
+4 -28
View File
@@ -131,40 +131,16 @@ static func bonus_result_text(result: Dictionary) -> String:
return "已选择:%s\n其余选项已丢弃(不可反悔)" % name
# 特性卡片文案(迭代 12 T1;2026-10-04 呈现补强——第三行=hook 效果摘要,用户反馈「不知道件是
# 干嘛的」缺口承载;摘要=静态映射表 provisional 文案归代拍板白名单「件文案微调」)
# 特性卡片文案(迭代 12 T1;2026-10-04 呈现补强——第三行=效果摘要,用户反馈「不知道件是
# 干嘛的」缺口承载。内容数据驱动扩展批 T3 文案表值化:摘要=数据行 desc 字段,零硬编码映射——
# 新件写行即有名有姓,措辞与旧 summaries 表逐字一致)
static func feat_card_text(row: Dictionary) -> String:
if row.is_empty() or String(row.get("feat_id", "")) == "":
return "特性\n???"
var arch_names := {"magic": "魔法", "pierce": "穿刺", "normal": "普攻", "dig": "开格",
"flag": "标旗", "charge": "蓄力", "devour": "吞噬"}
var arch := String(arch_names.get(String(row.get("archetype", "")), "流派"))
var summaries := {
"hero_attack_rider": "普攻附加必中伤害",
"clamp_modifier": "克制面强化",
"first_dig_spell": "首格追加奥术矢",
"kill_overflow": "击杀半额弹射",
"dig_count_segments": "开格积穿刺矢",
"roll_discount": "打轻甲更易命中",
"round_dig_bonus": "开格越多打得越疼",
"hit_trade": "加伤换命中",
"armor_roll_rewrite": "攻击恒75%折扣",
"heavy_debuff": "打重甲附加破防",
"dig_yield_mult": "开格产出放大",
"deep_dig": "开格2AP·产出双份",
"flag_resource": "标中雷额外得资源",
"nest_aura": "控巢攻击光环",
"flag_all_hit": "全中标旗伤加倍",
"flag_strike": "标中旗必中打敌",
"ap_carry": "剩AP转下轮攻击",
"charge_shield": "蓄力转减伤",
"charge_spike": "蓄满下轮爆发",
"terrain_refund": "吃地形伤返资源",
"terrain_dig_double": "挖伤害格双产出",
"flag_neutralize": "标旗中和伤害格",
"variant_counter": "吃地形伤反打全体",
}
var summary := String(summaries.get(String(row.get("hook", "")), ""))
var summary := String(row.get("desc", ""))
if summary != "":
return "%s · %s\n%s" % [String(row.get("display_name", row.get("feat_id", ""))), arch, summary]
return "特性 · %s\n%s" % [arch, String(row.get("display_name", row.get("feat_id", "")))]
+2
View File
@@ -153,6 +153,7 @@ func on_shop_buy(product_id: String) -> void:
toast.show_toast("金币不足——买不起这件商品", "warn")
return
shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp))
shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行
shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost())
_refresh_presentations.call()
return
@@ -174,6 +175,7 @@ func on_shop_refresh() -> void:
toast.show_toast("金币不足——刷新失败", "warn")
return
shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp))
shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行
shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost())
_refresh_presentations.call()
+36 -23
View File
@@ -112,8 +112,9 @@ func on_presented(payload: Dictionary) -> void:
toast.show_toast("上关剩余 %d 件秘宝已随关卡结束清空" % int(payload.get("aux_cleared", 0)), "info") # 迭代 7 T4 清空反馈
_pending_curio = payload.duplicate(true)
_curio_context = "level_clear"
if bool(payload.get("replace_pending", false)):
if bool(payload.get("replace_pending", false)) or bool(payload.get("refreshed", false)):
# 续玩:替换子交互在途中断——重建三选一面后直落替换子态(候选不重抽)
# 刷新重发(2026-10-06):refreshed 标直落选择面——不再重开胜利总结面
show_pick()
return
end_overlay.open_victory(Narrator.battle_end_text("victory", false), "继续",
@@ -142,7 +143,7 @@ func present_node_curio() -> void:
_open_modal.call(curio_overlay)
curio_overlay.open_pick(Narrator.node_curio_header(), _curio_card_texts(node_cands, node_draw.get("aux_detail", []) as Array))
adventure.present_node_curio(node_cands, node_draw.get("aux_detail", []) as Array)
curio_overlay.set_refresh_info(adventure.attune_refresh_left()) # 迭代 11 第①批 T5b——刷新余量投喂
_feed_refresh_display(adventure) # 迭代 11 第①批 T5b + 2026-10-06 对齐商店——刷新面投喂单点
# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 treasure_replace_presented 续发直落子态)
@@ -151,10 +152,19 @@ func show_pick() -> void:
_open_modal.call(curio_overlay)
curio_overlay.open_pick(Narrator.curio_pick_header(payload), _curio_card_texts(payload.get("candidates", []) as Array, payload.get("aux_detail", []) as Array))
var adventure = _adventure_get.call()
curio_overlay.set_refresh_info(adventure.attune_refresh_left() if adventure != null else 0) # 迭代 11 第①批 T5b——刷新余量投喂
if adventure != null:
_feed_refresh_display(adventure) # 迭代 11 第①批 T5b + 2026-10-06 对齐商店——刷新面投喂单点
_refresh_presentations.call()
# 刷新呈现投喂单点(免费余量 X/Y + GP 付费价 + 冒险钱包可付——读数与商店 set_refresh_display 同构)
func _feed_refresh_display(adventure) -> void:
var runner = _runner_get.call()
var gp := int(runner.gp) if runner != null else 0
var cost: int = adventure.curio_refresh_gp_cost()
curio_overlay.set_refresh_display(adventure.attune_refresh_left(), cost, gp >= cost)
func _curio_card_texts(candidates: Array, treasure_detail: Array = []) -> Array:
# TP0 令牌池——候选 = {"kind","tier"} 令牌字典;卡片 id = "kind|tier|feat_id" 复合键(同 kind
# 大小两档/同档多 relic 可同屏,kind 单键不构成唯一身份),确认回程拆键(on_pick_confirmed)
@@ -181,41 +191,44 @@ func _curio_card_texts(candidates: Array, treasure_detail: Array = []) -> Array:
return out
# 道具件卡片行(掷定前置——具体道具名 + 效果摘要;空 iid = 无预掷回退态显示通用文案)
# 道具件卡片行(掷定前置——具体道具名 + 效果摘要;空 iid = 无预掷回退态显示通用文案)。
# 内容数据驱动扩展批 T4 文案表值化:效果摘要=数据行 desc 字段直读(零 kind 硬编码映射——
# 新件写行即有名有姓)
func _treasure_card_line(iid: String) -> String:
if iid == "":
return ""
var row: Dictionary = db.treasure_item_row(iid)
if row.is_empty():
return ""
var parts: Array[String] = []
for k in (row.get("effect_kinds", []) as Array):
if String(k) == "mine_reveal":
parts.append("真视")
elif String(k) == "reward_preview":
parts.append("预读")
elif String(k) == "ap_grant":
parts.append("AP +%d" % int(row.get("magnitude", 0)))
var tgt := String(row.get("target", "none"))
if tgt == "area_3x3":
parts.append("3×3")
elif tgt == "board_wide":
parts.append("全图")
return "%s · %s" % [String(row.get("display_name", iid)), " ".join(parts)]
var desc := String(row.get("desc", ""))
if desc != "":
return "%s · %s" % [String(row.get("display_name", iid)), desc]
return String(row.get("display_name", iid))
# 三选一刷新(迭代 11 第①批 T5b——P1 甲 X/Y 双源;通关停点经重发 curio_choice_presented 自然重建,
# 节点停点在此读在途态重 present——零自动推进契约不破,停点仍在途)
# 三选一刷新(迭代 11 第①批 T5b X/Y 双源 + 2026-10-06 用户令对齐商店 MC-1——免费位用尽转 GP 付费档:
# 同 shop_refresh_cost_base/curve 旋钮、同冒险钱包 runner.gp;通关停点经重发 curio_choice_presented 直落
# 选择面,节点停点在此读在途态重 present——零自动推进契约不破,停点仍在途)
func on_refresh() -> void:
var adventure = _adventure_get.call()
if adventure == null:
if adventure == null or not adventure.curio_stop_pending():
return
if not adventure.refresh_curio():
var runner = _runner_get.call()
var refreshed: bool = adventure.refresh_curio()
if not refreshed:
# 免费位(X/Y)已穷——GP 付费档(先扣钱包后重抽,余额不足拒绝零副作用)
var cost: int = adventure.curio_refresh_gp_cost()
if runner == null or not runner.spend_gp(cost):
toast.show_toast("金币不足——刷新失败", "warn")
return
refreshed = adventure.refresh_curio_paid()
_refresh_presentations.call() # 钱包变化上屏(对齐商店购买后刷新面)
if not refreshed:
return
if _curio_context == "reward_node":
var st: Dictionary = adventure.node_curio_pending_state()
curio_overlay.open_pick(Narrator.node_curio_header(), _curio_card_texts(st.get("candidates", []) as Array, st.get("aux_detail", []) as Array))
curio_overlay.set_refresh_info(adventure.attune_refresh_left())
_feed_refresh_display(adventure)
func on_pick_confirmed(item_id: String) -> void:
+76 -3
View File
@@ -117,6 +117,7 @@ var shop_overlay: ShopOverlay # 商店覆盖层(GP+商店房实施
var camp_overlay: CampOverlay # 营地覆盖层(元进度实现批——主菜单营地入口兑付呈现)
var settings_store # 系统级设置独立存储(迭代 8 卡④——音量/全屏/减动效)
var settings_overlay: SettingsOverlay # 设置覆盖层(迭代 8 卡④——最小设置面)
var pause_overlay: PauseOverlay # 局内暂停层·只读(迭代 17 卡③——钥石余额+营地三柜台进度查看;登记设置层同档)
var debug_overlay: DebugOverlay # 调试浮窗(迭代 14.5 调试整合批——种子/数值调整/批量模拟/两层调试入口收一)
var _modals = null # 模态层级状态机(modal_stack.gd——缺陷⑤纪律载体)
@@ -223,6 +224,7 @@ func _build_ui() -> void:
func() -> Variant: return settlement, func() -> Variant: return runner)
board_zone.action_requested.connect(_on_board_action)
board_zone.pause_badge.pressed.connect(_on_pause_badge_pressed) # 暂停层入口(迭代 17 卡③——战斗屏 HUD 角标)
info_panel.treasure_slot_clicked.connect(_treasure_ui.on_slot_clicked) # 迭代 7 T4——两步交互第一步
board_zone.stop_pressed.connect(_on_stop_pressed)
board_zone.refresh_confirmed.connect(_on_refresh_confirmed)
@@ -240,7 +242,7 @@ func _build_ui() -> void:
logger.ap_per_round = int(db.action_economy.ap_per_round)
# 模态覆盖层(登记序 = 树序 = z 遮挡序:图例 < 明细回看 < 节点 < 关卡画面 < 三选一 < 终局
# < 商店 < 营地 < 设置 < 确认弹窗 < 调试浮窗)
# < 商店 < 营地 < 设置 < 暂停(只读) < 确认弹窗 < 调试浮窗)
var overlays: Dictionary = UiAssembler.build_overlays(self, db)
legend_overlay = overlays.legend_overlay
node_overlay = overlays.node_overlay
@@ -255,11 +257,17 @@ func _build_ui() -> void:
legend_overlay.closed.connect(_on_modal_closed.bind(legend_overlay))
node_overlay.continue_pressed.connect(_on_node_continue)
level_screen.route_chosen.connect(_on_route_chosen)
level_screen.pause_badge.pressed.connect(_on_pause_badge_pressed) # 暂停层入口(迭代 17 卡③——地图屏顶栏角标)
level_screen.abandon_requested.connect(_on_abandon_requested) # 放弃入口(2026-09-21 用户拍板——台账 119)
_end_overlay.continue_pressed.connect(_on_battle_end_continue)
settings_overlay = SettingsOverlay.new(settings_store) # 迭代 8 卡④——最小设置面(音量/全屏/减动效)
add_child(settings_overlay)
settings_overlay.closed.connect(_on_settings_closed)
# 局内暂停层·只读(迭代 17 卡③——P2 甲:登记设置层同档带 dim 遮罩,确认弹窗之前;
# 数据=组合根开层实时读 MetaProgression 访问器喂入(R4),本层零写通路)
pause_overlay = PauseOverlay.new()
add_child(pause_overlay)
pause_overlay.closed.connect(_on_pause_closed)
# 提升三选一覆盖层(迭代 10——z 序 = 节点层之上、终局层之下;确认后同拍推进)
curio_overlay = CurioPickOverlay.new()
add_child(curio_overlay)
@@ -327,9 +335,10 @@ func _build_ui() -> void:
debug_overlay.simulate_requested.connect(_on_tune_simulate)
debug_overlay.debug_levels_requested.connect(_start_debug_levels)
# 模态登记(缺陷⑤纪律——登记序 = 树序:含 move_child 调位后的关卡画面/三选一终位)
# 模态登记(缺陷⑤纪律——登记序 = 树序:含 move_child 调位后的关卡画面/三选一终位;
# 暂停层设置层同档、确认弹窗之前——P2 甲)
_modals = ModalStack.new()
for m: Control in [legend_overlay, node_overlay, level_screen, curio_overlay, _end_overlay, shop_overlay, camp_overlay, settings_overlay, confirm_dialog, debug_overlay]:
for m: Control in [legend_overlay, node_overlay, level_screen, curio_overlay, _end_overlay, shop_overlay, camp_overlay, settings_overlay, pause_overlay, confirm_dialog, debug_overlay]:
_register_modal(m)
_tune_sim = TuneSimController.new(db, debug_overlay, int(db.hero.max_hp))
@@ -360,10 +369,12 @@ func _open_modal(m: Control) -> void:
# 打开时显式隐藏树序在其上方的可见层(遮挡物隐藏),关闭恢复——单一模态栈
_flush_row_queue() # 卡⑦——任何覆盖层开启前排空排播队列(明细带恒完整,回看/停点面不缺行)
_modals.open(m)
_sync_pause_entry() # 迭代 17 卡③——暂停层入口角标可见性/置灰随开态同步
func _close_modal(m: Control) -> void:
_modals.close(m)
_sync_pause_entry() # 迭代 17 卡③——关闭恢复角标可点态(无残留——R3 同源口径)
func _on_modal_closed(m: Control) -> void:
@@ -429,6 +440,7 @@ func _resume_from_menu() -> void:
_start_overlay.visible = false
_wire_adventure()
_level_active = true
_sync_pause_entry() # 迭代 17 卡③——续玩恢复点亮暂停入口角标
level_screen.set_abandon_available(true)
_reset_run_scope()
log_view.clear()
@@ -463,6 +475,7 @@ func _wire_adventure() -> void:
func _start_adventure() -> void:
_wire_adventure()
_level_active = true
_sync_pause_entry() # 迭代 17 卡③——进对局点亮暂停入口角标
level_screen.set_abandon_available(true) # 放弃入口挂选路停点(天然非战斗期——2026-09-21 用户拍板)
_reset_run_scope()
log_view.clear()
@@ -521,9 +534,11 @@ func _on_runner_node(node: Dictionary, info: Dictionary) -> void:
_open_modal(shop_overlay)
if runner.is_shop_pool():
shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp))
shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行
shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost()) # MC-1
else:
shop_overlay.open_shop(runner.shop_products(), int(runner.gp))
shop_overlay.set_visit_info(-1, 1.0) # legacy 面无爬价行(off 对照承载)
log_view.append_bb(Narrator.shop_line(int(runner.gp)))
logger.log_node(node, info, runner.node_index)
_refresh_presentations()
@@ -537,6 +552,7 @@ func _on_adventure_finished(summary: Dictionary) -> void:
var result: String = String(summary.get("result", ""))
settlement = null
_exit_level_screen() # 终局兜底:独立屏在开态(放弃入口)也先回战斗屏呈现摘要——屏级互斥单一出口
_sync_pause_entry() # 迭代 17 卡③——离局熄灭暂停入口角标(防菜单误现)
_sync_settlement_visuals() # → 全关
HudPresenter.battle_end_feedback(stage, ap_bar, false) # 灰化/idle 回正/状态全清——HUD 单通道(T3 收口批)
# 存档入账(元进度实现批):settle = Boss 两档入账 + 工坊解锁 + 摘要入档 + 写盘(唯一写档点不变——
@@ -887,6 +903,7 @@ func _enter_level_screen() -> void:
_level_screen_active = true
_battle_root.visible = false
_open_modal(level_screen)
_sync_pause_entry() # 迭代 17 卡③——屏级互斥切换同步(_open_modal 单口不识屏级状态)
func _exit_level_screen() -> void:
@@ -894,6 +911,7 @@ func _exit_level_screen() -> void:
_battle_root.visible = true
if level_screen.visible:
_close_modal(level_screen)
_sync_pause_entry() # 迭代 17 卡③——同上
func _on_abandon_requested() -> void:
@@ -922,6 +940,61 @@ func _on_settings_closed() -> void:
_refresh_resume_button()
# ---- 局内暂停层·只读(迭代 17 卡③——入口角标在两屏装配段〔组 B〕;开合与数据喂入归组合根)----
# 暂停层快照投影(R4 数据只读同源:每次开层实时读 MetaProgression 访问器现值拼装——
# 快照仅服务单次开层生命周期(open_pause 重建各行),跨开层零持有;零写调用)
func _pause_data() -> Dictionary:
var forge_rows: Array[Dictionary] = []
for attr in MetaTable.FORGE_ATTRS:
var row: Dictionary = db.meta_forge_row(attr)
forge_rows.append({
"attr": attr,
"display_name": String(row.get("display_name", "")),
"level": meta.forge_level(attr),
"flat": int(row.get("flat_value", 0)),
})
return {
"balance": meta.keystone_balance(),
"forge": forge_rows,
"workshop": meta.workshop_status(),
"tree": meta.tree_camp_rows(),
"fork_groups": meta.tree_fork_groups(),
}
func _open_pause_layer() -> void:
_open_modal(pause_overlay) # 模态栈单口(开层前排空排播队列——既有层同款行为,目检确认项)
pause_overlay.open_pause(_pause_data())
func _on_pause_closed() -> void:
_close_modal(pause_overlay) # 模态栈单口
# 入口角标点击(两屏同款处理器):P1 守卫兜底——其他模态开着即拒开(常态防线=角标置灰,
# 探针 pressed.emit 绕过 disabled 时由此兜住;地图屏自身的登记开态不计——has_open_excluding)
func _on_pause_badge_pressed() -> void:
var map_on: bool = level_screen != null and level_screen.visible
if _modals == null or (map_on and _modals.has_open_excluding(level_screen)) \
or (not map_on and _modals.has_open()):
return
_open_pause_layer()
# 入口角标可见性/置灰同步(P1 丁+守卫——单一同步点):战斗屏角标=对局内且地图屏未激活;
# 地图屏角标=随屏;置灰=登记册上除地图屏自身外任一层开着(防「看得见点不着」态)。
# 调用面=模态开合单口与屏级互斥口(凡影响开态/屏态的路径必经其一)。
func _sync_pause_entry() -> void:
if pause_overlay == null or _modals == null or board_zone == null or level_screen == null:
return
var map_on: bool = level_screen.visible
board_zone.pause_badge.visible = _level_active and not map_on
level_screen.pause_badge.visible = map_on
board_zone.pause_badge.disabled = _modals.has_open()
level_screen.pause_badge.disabled = _modals.has_open_excluding(level_screen)
# ---- 探针缝保缝(T4/D4 拆件——click/ui_probe 营地段直呼组合根面;实现归 camp_shop_presenter.gd)----
func _on_camp_closed() -> void:
+12
View File
@@ -41,3 +41,15 @@ func has_open() -> bool:
if is_instance_valid(m) and m.visible:
return true
return false
# 排除式开态查询(迭代 17 卡③ 2026-10-06——暂停层入口守卫判据):skip 层自身的开态不计入
#(关卡地图屏系登记册模态成员=常态屏态,其上的地图屏角标必须可点;其余任一层开着=角标置灰)。
# 只读查询零副作用——登记序/开合记账语义零改动。
func has_open_excluding(skip: Control) -> bool:
for m in _list:
if m == skip:
continue
if is_instance_valid(m) and m.visible:
return true
return false
+11 -11
View File
@@ -102,16 +102,13 @@ static func build_overlays(host: Control, db) -> Dictionary:
static func build_start_overlay(host: Control, db = null) -> Dictionary:
var overlay := overlay_bg(host, UiKit.BG_BRIGHT)
overlay.theme = UiKit.tooltip_theme()
# 石纹底噪底层(样张 v2 冻结批 T2——z 序=dim 之上/内容之下;缺位不挂即回退平色)
var bd_tex := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE)
if bd_tex != null:
var bd := TextureRect.new()
bd.texture = bd_tex
bd.stretch_mode = TextureRect.STRETCH_TILE
bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
bd.set_anchors_preset(Control.PRESET_FULL_RECT)
bd.mouse_filter = Control.MOUSE_FILTER_IGNORE
# 石纹弱质感+斜光带+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.beams/.vignette 三层;
# 旧满铺石纹不透退役。缺位不挂即回退平色)
var bd := UiKit.backdrop_tile()
if bd != null:
overlay.add_child(bd)
overlay.add_child(UiKit.beams_rect())
overlay.add_child(UiKit.vignette_rect())
# 双列骨架(M2):左=操作列 56% / 右=舞台+速览
var cols := HBoxContainer.new()
cols.set_anchors_preset(Control.PRESET_FULL_RECT)
@@ -138,11 +135,14 @@ static func build_start_overlay(host: Control, db = null) -> Dictionary:
# 组帽·冒险(M2 分组)
box.add_child(UiKit.label("── 冒 险 ──",UiKit.FS_CAPTION, false, UiKit.WARM_FAINT))
# 唯一试玩入口 = 正式「开始冒险」(三关序列);单关测试直入口(L2/L3)退役(2026-09-23 用户拍板)
var resumebtn := UiKit.button("▶ 继续上局") # 迭代 8 卡②——有断点才亮(可见性与关数文案归组合根刷新)
var resumebtn := UiKit.primary_button("▶ 继续上局") # 迭代 8 卡②——有断点才亮(可见性与关数文案归组合根刷新);主操作钮=审计差距⑤对齐 demo
resumebtn.tooltip_text = "自最近停点恢复"
resumebtn.visible = false
box.add_child(resumebtn)
var lvbtn := UiKit.primary_button("▶ 开始冒险", "三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城")
# 主操作语义对齐 demo(2026-10-06 审计差距⑤——有档时「继续上局」才是首动作=主黄钮,
# 「开始冒险」=常规石钮;tooltip 保留)
var lvbtn := UiKit.button("▶ 开始冒险")
lvbtn.tooltip_text = "三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城"
box.add_child(lvbtn)
# 组帽·营地与系统
+73 -17
View File
@@ -15,10 +15,16 @@ const COL_WARM := UiKit.WARM
var _dim: ColorRect
var _seal: Panel
var _verdict: Label
var _rows_box: VBoxContainer # M9 三行账(GP/钥石/本关加成——demo ⑧;失败侧整行隐藏=P-C4 维持 OQ14)
var _gp_row: Label
var _ks_row: Label
var _bonus_row_l: Label
var _rows_box: VBoxContainer # M9 三行账(GP/钥石/本关加成——demo ⑧两列对齐 2026-10-06 审计差距④;失败侧整行隐藏=P-C4 维持 OQ14)
var _gp_row: HBoxContainer
var _gp_name: Label
var _gp_val: Label
var _ks_row: HBoxContainer
var _ks_name: Label
var _ks_val: Label
var _bonus_row_l: HBoxContainer
var _bonus_name: Label
var _bonus_val: Label
var _cele: TextureRect # M9 庆祝立绘(idle 占位浮动——正式帧待资产批)
var _btn: Button
var _board_rect := Rect2()
@@ -75,20 +81,32 @@ func _init() -> void:
_rows_box.add_theme_constant_override("separation", 6)
_rows_box.visible = false
box.add_child(_rows_box)
_gp_row = UiKit.label("",UiKit.FS_SUB, true, UiKit.GOLD_DEEP)
_gp_row.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
# 两列对齐账行(审计差距④对齐 demo ⑧——项目名左/数值右,定宽 360)
_gp_row = _ledger_row()
_gp_name = _ledger_name(UiKit.FS_SUB, UiKit.GOLD_DEEP, true)
_gp_val = _ledger_value(UiKit.FS_SUB, UiKit.GOLD_DEEP, true)
_gp_row.add_child(_gp_name)
_gp_row.add_child(_gp_val)
_rows_box.add_child(_gp_row)
_ks_row = UiKit.label("",UiKit.FS_BODY, true, UiKit.INK_LABEL)
_ks_row.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_ks_row = _ledger_row()
_ks_name = _ledger_name(UiKit.FS_BODY, UiKit.INK_LABEL, false)
_ks_val = _ledger_value(UiKit.FS_BODY, UiKit.INK_LABEL, true)
_ks_row.add_child(_ks_name)
_ks_row.add_child(_ks_val)
_ks_row.visible = false
_rows_box.add_child(_ks_row)
_bonus_row_l = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL)
_bonus_row_l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_bonus_row_l = _ledger_row()
_bonus_name = _ledger_name(UiKit.FS_HINT, UiKit.INK_LABEL, false)
_bonus_val = _ledger_value(UiKit.FS_HINT, UiKit.INK_LABEL, true)
_bonus_row_l.add_child(_bonus_name)
_bonus_row_l.add_child(_bonus_val)
_bonus_row_l.visible = false
_rows_box.add_child(_bonus_row_l)
box.add_child(HSeparator.new())
# M9:明细回看钮退役(P-C7——冒险中回看归「生涯」)
_btn = UiKit.primary_button("继续")
_btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER # 审计差距④——紧凑钮(原全宽)
_btn.custom_minimum_size.x = 150
_btn.pressed.connect(_emit_continue_pressed)
box.add_child(_btn)
visible = false
@@ -99,14 +117,14 @@ func _init() -> void:
# 传入(入账次序 = LevelRunner 入账先于组合根 handler,runner.gp 即战后总量);空串 = 不显示(失败侧恒空)。
func open_victory(verdict_line: String, continue_label: String, board_rect: Rect2, gp_summary: String = "",
ks_summary: String = "", bonus_summary: String = "", gp_gain := -1, gp_total := -1) -> void:
_dim.color = Color(COL_WARM, 0.28)
_dim.color = Color(UiKit.DIM_NIGHT, 0.62) # 审计差距④——全屏压暗对齐 demo(原 0.28 暖纱透底)
_verdict.text = verdict_line
_seal.visible = true # 胜利徽记(面板头部静态)
_seal.modulate = Color.WHITE
_gp_row.text = gp_summary
_ks_row.text = ks_summary
_set_ledger_row(_gp_name, _gp_val, gp_summary, true) # GP 行=固定名「战利品 GP」(滚动/整串均只入值列)
_set_ledger_row(_ks_name, _ks_val, ks_summary)
_ks_row.visible = ks_summary != ""
_bonus_row_l.text = bonus_summary
_set_ledger_row(_bonus_name, _bonus_val, bonus_summary)
_bonus_row_l.visible = bonus_summary != ""
_rows_box.visible = gp_summary != "" or ks_summary != "" or bonus_summary != ""
_btn.text = continue_label
@@ -125,7 +143,7 @@ func open_victory(verdict_line: String, continue_label: String, board_rect: Rect
func open_defeat(verdict_line: String, continue_label: String, board_rect: Rect2) -> void:
# 明度不变的暮蓝色相氛围(全屏唯一暮蓝档——§2.5 最静一拍)
_dim.color = Color(COL_DUSK, 0.45)
_dim.color = Color(COL_DUSK, 0.6) # 审计差距④同族压暗(原 0.45)
_verdict.text = verdict_line
_board_rect = board_rect
visible = true
@@ -153,6 +171,44 @@ func verdict_text() -> String:
return _verdict.text
# 两列账行工厂(审计差距④——名左/值右,定宽 360)
func _ledger_row() -> HBoxContainer:
var r := HBoxContainer.new()
r.custom_minimum_size = Vector2(360, 0)
return r
func _ledger_name(size: int, col: Color, _bold: bool) -> Label:
var l := UiKit.label("", size, true, col)
l.size_flags_horizontal = Control.SIZE_EXPAND_FILL
return l
func _ledger_value(size: int, col: Color, bold: bool) -> Label:
return UiKit.label("", size, bold, col)
# 拆名/值(组合根传入整串):gp_shape=固定名「战利品 GP」值取余串;其余行按「:」或「 · 」切
#(全角冒号不入值列——T7 实机「:攻击 +1」缩进 Corrections);无分隔符=整串入值列、名空
func _set_ledger_row(name_l: Label, val_l: Label, s: String, gp_shape := false) -> void:
if gp_shape and s.begins_with("战利品 GP"):
name_l.text = "战利品 GP"
val_l.text = s.substr(6).strip_edges()
return
var sep := s.find(":")
if sep >= 0:
name_l.text = s.substr(0, sep)
val_l.text = s.substr(sep + 1).strip_edges()
return
sep = s.find(" · ")
if sep >= 0:
name_l.text = s.substr(0, sep)
val_l.text = s.substr(sep).strip_edges()
else:
name_l.text = ""
val_l.text = s
func _fx_center() -> Vector2:
return get_viewport_rect().size * 0.5
@@ -254,11 +310,11 @@ func _play_victory_dust() -> void:
# M9 GP 行数字滚动(demo ⑧——0.8s 三次缓出;减动效直出终值)
func _roll_gp(gp_gain: int, gp_total: int) -> void:
if UiKit.motion_scale < 1.0:
_gp_row.text = "战利品 GP +%d · 合计 %d" % [gp_gain, gp_total]
_gp_val.text = "+%d · 合计 %d" % [gp_gain, gp_total]
return
var tw := create_tween()
tw.tween_method(func(v: float) -> void:
_gp_row.text = "战利品 GP +%d · 合计 %d" % [roundi(gp_gain * v), gp_total],
_gp_val.text = "+%d · 合计 %d" % [roundi(gp_gain * v), gp_total],
0.0, 1.0, UiKit.motion(0.8)).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
@@ -11,6 +11,7 @@ var ap_bar: ApBarView
var board_view: BoardView
var toast: ToastStack
var fx: BoardFxView
var pause_badge: Button # 暂停层入口角标(迭代 17 卡③ P1 丁——debug 角标同形制;连接归组合根)
var _board_area: Control # resized 命名转发用(原 lambda 局部捕获——P1-3 转命名 2026-09-29)
signal action_requested(cell: Vector2i, kind: String)
@@ -41,6 +42,15 @@ func _init() -> void:
board_area.add_child(fx)
toast = ToastStack.new()
board_area.add_child(toast)
# 暂停层入口角标(迭代 17 卡③ P1 丁——战斗屏 HUD 右下角常驻;debug 角标同形制:紧凑钮豁免
# 宽度基准+字号降档+角距 16px。可见性/置灰归组合根 _sync_pause_entry(其他模态开着=置灰
# 不可点——has_open 守卫);信号连接归组合根(ADR-0001——装配器/视图零连接)
pause_badge = UiKit.button("暂停", 0.0) # 角落小件豁免宽度基准(同调试角标)
pause_badge.add_theme_font_size_override("font_size", UiKit.FS_HINT)
pause_badge.tooltip_text = "查看钥石与永久强化进度(只读)"
pause_badge.visible = false # 显式初始化——非对局期不误现(可见性归组合根同步)
pause_badge.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_RIGHT, Control.PRESET_MODE_MINSIZE, 16)
board_area.add_child(pause_badge)
# M8(UI 落码批):棋盘底常驻操作提示条(demo ⑦——文案经 board_view 输入代码证实;
# 旧 chord 一次性 toast 提示退役归此常驻条;审计第 7 条用户批)
var hint := PanelContainer.new()
+43 -28
View File
@@ -38,17 +38,15 @@ var _recent_list: Label # 最近冒险(逐行拼接 label——只读
func _init() -> void:
var dim := UiKit.modal_dim(self, Color(0, 0, 0, 0.45)) # 方向稿=石纹底透出(浅 dim——石纹全屏底担当氛围)
# 石纹底噪(样张 v2 冻结件——start overlay 同款;缺位不挂即回退平 dim)
var bd_tex := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE)
if bd_tex != null:
var bd := TextureRect.new()
bd.texture = bd_tex
bd.stretch_mode = TextureRect.STRETCH_TILE
bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
bd.set_anchors_preset(Control.PRESET_FULL_RECT)
bd.mouse_filter = Control.MOUSE_FILTER_IGNORE
# 底=不透明暖亮档(2026-10-06 用户实测缺陷修——原形制=0.45 半透 dim+满铺石纹遮底,T5 石纹降 0.14
# 后底下屏幕透出〔用户实机:对局中开营地见棋盘/战斗提示条〕;demo #v-camp=bg-bright 实底,
# 遮蔽语义由组合根输入锁兜底)
var dim := UiKit.modal_dim(self, UiKit.BG_BRIGHT)
# 石纹弱质感+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.vignette;缺位不挂即回退平色)
var bd := UiKit.backdrop_tile()
if bd != null:
dim.add_child(bd)
dim.add_child(UiKit.vignette_rect())
var root := MarginContainer.new()
root.set_anchors_preset(Control.PRESET_FULL_RECT)
@@ -78,22 +76,17 @@ func _init() -> void:
var spacer := Control.new()
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
top.add_child(spacer)
var badge := PanelContainer.new()
# M3(UI 落码批 2026-10-04):钥石徽章烛光黄底+深墨字(demo ②——旧暗底 CAMP_BADGE_PANEL 退役;
# BADGE_PANEL_COL 常量保留他用不动)
badge.add_theme_stylebox_override("panel",
UiKit.panel_flat(UiKit.CANDLE, UiKit.CAMP_HEADER_BAND,UiKit.RADIUS_OBJECT, 1, Vector4(14, 8, 14, 8)))
# M3(UI 落码批):钥石徽章烛光黄底+深墨字(demo ②——旧暗底 CAMP_BADGE_PANEL 退役;
# BADGE_PANEL_COL 常量保留他用不动)。Q10 甲(2026-10-06):本地拼装迁 UiKit.keystone_badge
# 工厂调用(badge 单点化——暂停层同款消费);形制参数逐项同原装配,观感零变化
var badge := UiKit.keystone_badge("钥石 0")
top.add_child(badge)
var bal_row := HBoxContainer.new()
bal_row.add_theme_constant_override("separation", 6)
badge.add_child(bal_row)
var keystone_icon := UiKit.icon_rect(UiKit.TEX_ICON_KEYSTONE, 32) # P6 甲②(2026-10-06):64 源 0.5×(原 20=0.3125× 违 §8.2);缺位 null → 纯文本回退
if keystone_icon != null:
bal_row.add_child(keystone_icon)
_balance_label = UiKit.label("钥石 0",UiKit.FS_SUB, true, UiKit.INK_ON_GOLD)
bal_row.add_child(_balance_label)
_balance_label = badge.value_label
# ── 三柜台列(方向稿同构:头带深棕+米色板身)──
# 三柜等宽分配(2026-10-06 用户实测缺陷修——原定宽 356+行标签按文字全宽算 min,进度行文案
# 「累计通关 28/2 次·能力封存中」随档变长把面板撑爆,三柜总宽溢出 1248 可用宽=右柜裁出屏;
# 改=EXPAND_FILL 等比分屏宽+行标签截断兜底,min 恒 ≤ 定宽)
var mid := HBoxContainer.new()
mid.add_theme_constant_override("separation", 18)
mid.alignment = BoxContainer.ALIGNMENT_CENTER
@@ -101,18 +94,25 @@ func _init() -> void:
col.add_child(mid)
_forge_holder = VBoxContainer.new()
_forge_holder.add_theme_constant_override("separation", 6)
mid.add_child(_counter_panel("属性锻造", UiKit.TEX_ICON_FORGE, _forge_holder, 356))
var forge_panel := _counter_panel("属性锻造", UiKit.TEX_ICON_FORGE, _forge_holder, 356)
forge_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
mid.add_child(forge_panel)
# 迭代 11 第①批 T4 工坊扩容(P2 甲程序占位——同调装配段+Y 升级行入工坊柜台,行板复用;行数增长以
# 柜台内滚承载,冻结三柜台版式与另两柜台零触碰,视觉终稿归营地批)
var ws_scroll := ScrollContainer.new()
ws_scroll.custom_minimum_size = Vector2(340, 336)
ws_scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL # 2026-10-06 用户实测修——纵向撑满面板余高(固定 336=行断流但面板下半空着,滚动条提前出现)
ws_scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
_workshop_holder = VBoxContainer.new()
_workshop_holder.add_theme_constant_override("separation", 6)
ws_scroll.add_child(_workshop_holder)
mid.add_child(_counter_panel("道具工坊", UiKit.TEX_ICON_WORKSHOP, ws_scroll, 356))
var ws_panel := _counter_panel("道具工坊", UiKit.TEX_ICON_WORKSHOP, ws_scroll, 356)
ws_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
mid.add_child(ws_panel)
var atlas_holder := VBoxContainer.new()
mid.add_child(_counter_panel("奖励格图鉴", UiKit.TEX_ICON_ATLAS, atlas_holder, 356))
var atlas_panel := _counter_panel("奖励格图鉴", UiKit.TEX_ICON_ATLAS, atlas_holder, 356)
atlas_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
mid.add_child(atlas_panel)
var lock_l := UiKit.label(" —— 柜台结构位预留:内容排 Alpha(地图战斗资源差异化批)",UiKit.FS_HINT, false, UiKit.STONE)
lock_l.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
lock_l.custom_minimum_size = Vector2(300, 0)
@@ -123,6 +123,7 @@ func _init() -> void:
_tree_holder.add_theme_constant_override("separation", 6)
var tree_scroll := ScrollContainer.new()
tree_scroll.custom_minimum_size = Vector2(300, 200)
tree_scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL # 2026-10-06 同修——树段内滚撑满图鉴柜余高
tree_scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
tree_scroll.add_child(_tree_holder)
atlas_holder.add_child(tree_scroll)
@@ -277,6 +278,7 @@ func refresh_camp(data: Dictionary) -> void:
st_col = UiKit.GOLD_DEEP
card.status_l.text = st_text
card.status_l.add_theme_color_override("font_color", st_col)
card.status_l.tooltip_text = st_text # 截断兜底(状态列 EXPAND_FILL 吸余宽——悬停看全文)
# 同调装配段状态就地刷(迭代 11 第①批 T4——Slots 点亮/满位禁选/Y 升级行余额联动)
var att: Dictionary = data.get("attune", {})
if _attune_header_l != null:
@@ -309,7 +311,7 @@ func _build_forge_row(holder: VBoxContainer, row: Dictionary) -> Dictionary:
var card := PanelContainer.new()
card.add_theme_stylebox_override("panel", UiKit.panel_flat(ROW_PLATE_COL, UiKit.PANEL_BORDER,UiKit.RADIUS_OBJECT, 1, Vector4(10, 4, 10, 4)))
var line := HBoxContainer.new()
line.add_theme_constant_override("separation", 12)
line.add_theme_constant_override("separation", 8) # 2026-10-06 营地溢出修(12→8——行 min 压回定宽内)
card.add_child(line)
var attr := String(row.get("attr", ""))
# M3(UI 落码批):行首 20px 语义图标(图标+形状+颜色三通道——demo ②;子串映射容错 attr 键名演进)
@@ -329,6 +331,8 @@ func _build_forge_row(holder: VBoxContainer, row: Dictionary) -> Dictionary:
line.add_child(ic)
var name_l := UiKit.label("%s %+d/级" % [String(row.get("display_name", "")), int(row.get("flat", 0))], 14, true, UiKit.INK)
name_l.custom_minimum_size = Vector2(112, 0)
name_l.clip_text = true # 2026-10-06 营地溢出修——文字全宽不入 min(三柜等宽分配前提)
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(name_l)
var level_l := UiKit.label("",UiKit.FS_HINT, true, UiKit.INK_ON_DEEP)
# M3:Lv 章化(木底小章——demo lvtag;Label normal 槽挂样式盒)
@@ -337,6 +341,8 @@ func _build_forge_row(holder: VBoxContainer, row: Dictionary) -> Dictionary:
line.add_child(level_l)
var price_l := UiKit.label("",UiKit.FS_HINT, false, UiKit.STONE)
price_l.custom_minimum_size = Vector2(64, 0)
price_l.clip_text = true
price_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(price_l)
var btn := UiKit.button("锻造 +1 级", 0.0) # 柜台行板紧凑钮豁免宽度基准
btn.pressed.connect(_emit_buy_requested.bind(attr))
@@ -357,12 +363,19 @@ func _rebuild_workshop(data: Dictionary) -> void:
card.add_child(line)
var name_l := UiKit.label(String(row.get("display_name", "")),UiKit.FS_HINT, true, UiKit.INK)
name_l.custom_minimum_size = Vector2(132, 0)
name_l.clip_text = true
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(name_l)
var progress_l := UiKit.label("",UiKit.FS_HINT, false, UiKit.STONE)
progress_l.custom_minimum_size = Vector2(110, 0)
progress_l.custom_minimum_size = Vector2(150, 0) # 2026-10-06 修——110 截掉阈值数字(「累计通关 28 / 2 次」≈154px)
progress_l.clip_text = true # 营地溢出修——文字全宽不撑柜
progress_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(progress_l)
# 状态色随卡⑭ 亮板双色墨制(深墨族替代暖白族)——色随刷新态条件赋值,非机械两行式(T4 收口保留)
var status_l := UiKit.label("",UiKit.FS_HINT, true, UiKit.STONE)
status_l.clip_text = true # 同上——「已解锁 · 能力封存中」不撑柜(余宽吸收者)
status_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
status_l.size_flags_horizontal = Control.SIZE_EXPAND_FILL
line.add_child(status_l)
_workshop_holder.add_child(card)
_workshop_rows.append({"item_id": String(row.get("item_id", "")), "progress_l": progress_l, "status_l": status_l})
@@ -384,6 +397,8 @@ func _rebuild_attune(data: Dictionary) -> void:
line.add_theme_constant_override("separation", 6)
var name_l := UiKit.label(String(row.get("display_name", "")),UiKit.FS_HINT, true, UiKit.INK)
name_l.custom_minimum_size = Vector2(96, 0)
name_l.clip_text = true
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(name_l)
var form_l := UiKit.label("被动" if String(row.get("form", "")) == "passive" else "主动·充能",UiKit.FS_CAPTION, false, UiKit.STONE)
form_l.custom_minimum_size = Vector2(58, 0)
+63 -22
View File
@@ -20,7 +20,9 @@ var _continue_btn: Button # 继续钮(兑付反馈态唯一
var _refresh_btn: Button # 刷新钮(迭代 11 第①批 T5b——余量>0 才显示;M7 升顶条图标钮)
var _refresh_badge: Label # M7 余量角标(图标钮右上——demo ⑥ 同构)
var _refresh_l: Label # 刷新余量读数(X 优先 + Y 冒险池)
var _refresh_allowance := 0 # 组合根投喂余量(本视图零核心引用)
var _foot_hint: Label # T7 底注(demo .bonus-foot .hint——pick 态显隐)
var _refresh_allowance := 0 # 组合根投喂免费余量(X/Y——本视图零核心引用)
var _refresh_gp_cost := 0 # 组合根投喂 GP 刷新价(免费位用尽后的付费档读数)
var _selected := "" # 点选暂存(确认前可改选)
var _header := "" # 停点头部文案(选择态保持显示)
var _card_meta: Array = [] # open_pick 缓存 [{id, text}]——高亮还原读面
@@ -28,12 +30,12 @@ var _bcards: Array = [] # M7 bcard 引用列(select 高亮
func _init() -> void:
# M7(UI 落码批):与商店同构(demo ⑥ 用户令两屏一致)——通栏顶条(标题+刷新图标钮/角标)+
# 居中入账信息行 + bcard 三竖卡 + 底部唯一主钮「确认选择」;差异白名单=免费选择/✓章/无价签
var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box
var top := HBoxContainer.new()
top.add_theme_constant_override("separation", 12)
box.add_child(top)
# T7(UI 设计对齐批 2026-10-06):全屏页形态(demo ⑥ #v-bonus——与商店 T6 同壳 page_shell,
# 根底暗档)——56px 通栏顶条(标题+刷新图标钮/角标)+ 居中入账信息行(GP 汇总行承载)+
# bcard 三竖卡(D1 232×352)+ 底部确认主钮与免费选择注记。差异白名单=免费选择/✓章/无价签。
# 状态机不变:pick→[replace]→result。M7 同构裁决遗产保留。
var page: Dictionary = UiKit.page_shell(self, false)
var top: HBoxContainer = page.top_row
top.add_child(UiKit.label("战利品三选一",UiKit.FS_TITLE, true, UiKit.WARM))
var top_sp := Control.new()
top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
@@ -54,25 +56,34 @@ func _init() -> void:
_refresh_l = UiKit.label("",UiKit.FS_CAPTION, false, UiKit.WARM_SOFT)
_refresh_l.visible = false
top.add_child(_refresh_l)
var box: VBoxContainer = page.box
_label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT)
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_label)
_choice_box = HBoxContainer.new()
_choice_box.add_theme_constant_override("separation", 20)
_choice_box.add_theme_constant_override("separation", 26) # demo .cards gap 26(T7 对齐)
_choice_box.alignment = BoxContainer.ALIGNMENT_CENTER
_choice_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
box.add_child(_choice_box)
var foot := HBoxContainer.new()
foot.alignment = BoxContainer.ALIGNMENT_CENTER
foot.add_theme_constant_override("separation", 16)
box.add_child(foot)
_confirm_btn = UiKit.primary_button("确认选择")
_confirm_btn.pressed.connect(_on_confirm_pressed)
_confirm_btn.visible = false
box.add_child(_confirm_btn)
_replace_box = VBoxContainer.new()
_replace_box.add_theme_constant_override("separation", 8)
_replace_box.alignment = BoxContainer.ALIGNMENT_CENTER
box.add_child(_replace_box)
foot.add_child(_confirm_btn)
_continue_btn = UiKit.button("继续")
_continue_btn.pressed.connect(_emit_continue_pressed)
_continue_btn.visible = false
box.add_child(_continue_btn)
foot.add_child(_continue_btn)
_foot_hint = UiKit.label("免费选择 · 刷新不消耗 AP",UiKit.FS_HINT, false, UiKit.WARM_FAINT)
foot.add_child(_foot_hint)
_replace_box = VBoxContainer.new()
_replace_box.add_theme_constant_override("separation", 8)
_replace_box.alignment = BoxContainer.ALIGNMENT_CENTER
_replace_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
box.add_child(_replace_box)
visible = false
@@ -94,7 +105,8 @@ func open_pick(header: String, cards: Array) -> void:
var desc := "\n".join(lines.slice(1)) if lines.size() > 1 else ""
var idl := cid.to_lower()
var band := UiKit.tg_band(idl) # 类型色带单点(N4c 2026-10-06——TG_* 五族同源判定;aoe/blast 归 TG_AOE)
var card := UiKit.bcard(title, desc, band, _icon_for_id(idl))
# 类型脚注(T7 判官 checkpoint:demo .bcard .src 底部类型行——实机缺=卡下半空底;词=demo 同款)
var card := UiKit.bcard(title, desc, band, _icon_for_id(idl), "", _type_label(idl))
card.gui_input.connect(func(ev: InputEvent) -> void:
if ev is InputEventMouseButton and ev.pressed and ev.button_index == MOUSE_BUTTON_LEFT:
_select_card(cid))
@@ -105,18 +117,23 @@ func open_pick(header: String, cards: Array) -> void:
_confirm_btn.visible = false
_replace_box.visible = false
_continue_btn.visible = false
_refresh_btn.visible = false # 刷新余量随 set_refresh_info 投喂后现形(open 先归零防残留)
_foot_hint.visible = true # T7 底注=pick 态专属(replace/result 态让位)
_refresh_btn.visible = false # 刷新面随 set_refresh_display 投喂后现形(open 先归零防残留;店内门票面不投喂=无刷新)
_refresh_l.text = ""
visible = true
# 三选一刷新余量投喂(组合根读 adventure.attune_refresh_left()——0 = 刷新面隐藏)
func set_refresh_info(allowance: int) -> void:
_refresh_allowance = maxi(0, int(allowance))
_refresh_btn.visible = _refresh_allowance > 0
# 三选一刷新呈现投喂(2026-10-06 用户令对齐商店 MC-1 同构——free_left=X/Y 免费位余量〔基础 0〕,
# 免费位用尽转 GP 付费档:gp_cost=本次 GP 刷新价、can_afford=冒险钱包可付;钮常驻选择态,两源皆穷=禁用不隐藏)
func set_refresh_display(free_left: int, gp_cost: int, can_afford: bool) -> void:
_refresh_allowance = maxi(0, int(free_left))
_refresh_gp_cost = maxi(0, int(gp_cost))
_refresh_btn.visible = _refresh_allowance > 0 or _refresh_gp_cost > 0
_refresh_badge.text = str(_refresh_allowance)
_refresh_l.text = "免费 · 不消耗 AP" if _refresh_allowance > 0 else ""
_refresh_l.visible = _refresh_allowance > 0
_refresh_l.text = "免费 · 不消耗 AP" if _refresh_allowance > 0 else ("刷新 %d 金币" % _refresh_gp_cost if _refresh_gp_cost > 0 else "")
_refresh_l.visible = _refresh_l.text != ""
_refresh_btn.tooltip_text = "刷新候选——换一批战利品\n免费 %d 次(刷新件 X 优先 + 冒险池 Y)\nGP 刷新 %d 金币\n池源=共享池,与商店货架同源" % [_refresh_allowance, _refresh_gp_cost]
_refresh_btn.disabled = _refresh_allowance <= 0 and not can_afford
func _emit_refresh_requested() -> void:
@@ -152,6 +169,11 @@ func press_continue() -> void:
_continue_btn.pressed.emit()
# 探针/测试复用:以真实按钮路径触发刷新意图(信号外发——受理归组合根)
func press_refresh() -> void:
_refresh_btn.pressed.emit()
func selected_id() -> String:
return _selected
@@ -163,6 +185,8 @@ func show_result(text: String) -> void:
_confirm_btn.visible = false
_replace_box.visible = false
_continue_btn.visible = true
_refresh_btn.visible = false # 刷新=选择态专属功能(结果态停点已兑付——残钮零意图可点)
_foot_hint.visible = false
visible = true
@@ -184,6 +208,8 @@ func open_replace(items: Array, incoming_name: String, holding: int, slots: int)
_confirm_btn.visible = false
_replace_box.visible = true
_continue_btn.visible = false
_refresh_btn.visible = false # 刷新=选择态专属功能(替换子态不换候选)
_foot_hint.visible = false
visible = true
@@ -193,6 +219,8 @@ func close_pick() -> void:
_replace_box.visible = false
_continue_btn.visible = false
_confirm_btn.visible = false
_refresh_btn.visible = false
_foot_hint.visible = false
visible = false
@@ -219,3 +247,16 @@ func _icon_for_id(idl: String) -> String:
if idl.contains("ap") or idl.contains("action"):
return UiKit.TEX_ICON_POUCH
return UiKit.TEX_ICON_COINBAG
# T7 类型脚注词(demo .bcard .src 同款五族——与 tg_band 同域子串判定,卡底填空对齐)
func _type_label(idl: String) -> String:
if idl.contains("heal"):
return "治疗"
if idl.contains("blast") or idl.contains("magic"):
return "魔法"
if idl.contains("pierce"):
return "穿甲"
if idl.contains("aoe"):
return "群伤"
return "通用增益"
+46 -23
View File
@@ -61,6 +61,7 @@ var _cand_ids: Array[int] = [] # 本停点候选 id 集(图上命
var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它)
var _hover_id := -1 # 悬停预承诺候选(-1 = 无)
var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——只在冒险模式开)
var pause_badge: Button # 暂停层入口角标(迭代 17 卡③ P1 丁——顶栏 GP 徽右侧;连接归组合根)
var _abandon_timer := ArmedTimer.new() # 放弃确认窗(T3/D3 P4 乙——_process 帧驱动倒计时机制收口;窗口=CONFIRM_WINDOW_S)
var _node_icons := {} # 节点图标贴图(load_tex 守卫——缺位 null → 字形回退,冒烟/无素材检出安全)
var _noise_rect: TextureRect # 屏底石纹(换层色板渐变承载面——null = 纯色回退无挂点)
@@ -72,42 +73,54 @@ func _init() -> void:
# 节点图标贴图装载(样张 v1 冻结形制——load_tex 守卫,缺位回退现行字形)
for t in TEX_NODE_ICONS:
_node_icons[t] = UiKit.load_tex(TEX_NODE_ICONS[t])
# 独立屏底(形态升格 2026-09-28——spec Layout:深底+石纹底噪铺满;底纹缺位回退纯色——load_tex 守卫)
var base := ColorRect.new()
base.color = UiKit.BG_ROOT
base.set_anchors_preset(Control.PRESET_FULL_RECT)
# 独立屏底(形态升格 2026-09-28——spec Layout;UI 对齐批 T5 2026-10-06:demo #v-map 暖棕竖向
# 渐变(#4A3B2A 0%→#3A2E22 40%)+石纹弱质感 0.14+暗角聚焦;旧满铺石纹不透退役;底纹缺位回退纯色)
var base := UiKit.gradient_base(UiKit.BG_MAP_TOP, UiKit.BG_ROOT)
add_child(base)
var noise := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE)
if noise != null:
var tex := TextureRect.new()
tex.texture = noise
tex.stretch_mode = TextureRect.STRETCH_TILE
tex.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
tex.set_anchors_preset(Control.PRESET_FULL_RECT)
tex.mouse_filter = Control.MOUSE_FILTER_IGNORE
var tex := UiKit.backdrop_tile()
if tex != null:
base.add_child(tex)
_noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档)
base.add_child(UiKit.vignette_rect())
var center := CenterContainer.new()
center.set_anchors_preset(Control.PRESET_FULL_RECT)
base.add_child(center)
var box := VBoxContainer.new()
box.add_theme_constant_override("separation", 10)
center.add_child(box)
# 顶栏语境(spec Layout:左关卡名 / 右 GP 常驻徽章——直角细线数据框)
# 顶栏语境(spec Layout:左关卡名 / 右 GP 常驻徽章——直角细线数据框;
# T5 判官 checkpoint 对齐 demo ④:关卡名入框板(裸文本退役)+GP 徽章=烛光胶囊(同商店金币框)+
# 左右两极排布(原居中悬置))
var top := HBoxContainer.new()
top.add_theme_constant_override("separation", 12)
top.size_flags_horizontal = Control.SIZE_EXPAND_FILL
box.add_child(top)
var lvl_plate := PanelContainer.new()
lvl_plate.add_theme_stylebox_override("panel",
UiKit.panel_flat(UiKit.DARK_UPCOMING, UiKit.PANEL_BORDER, 0, 1, Vector4(12, 3, 12, 3)))
top.add_child(lvl_plate)
_level_label = UiKit.label("",UiKit.FS_BODY, true, UiKit.WARM)
_level_label.custom_minimum_size.x = 420
top.add_child(_level_label)
lvl_plate.add_child(_level_label)
var top_sp := Control.new()
top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
top.add_child(top_sp)
var gp_box := PanelContainer.new()
gp_box.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.DARK_UPCOMING, UiKit.PANEL_BORDER, 0, 1))
gp_box.add_theme_stylebox_override("panel",
UiKit.panel_flat(UiKit.CANDLE, UiKit.CAMP_HEADER_BAND,UiKit.RADIUS_OBJECT, 1, Vector4(12, 4, 12, 4)))
top.add_child(gp_box)
var gp_row := HBoxContainer.new()
gp_row.add_theme_constant_override("separation", 6)
gp_box.add_child(gp_row)
_gp_value = UiKit.label("",UiKit.FS_BODY, true, UiKit.GOLD)
_gp_value = UiKit.label("",UiKit.FS_BODY, true, UiKit.INK_ON_GOLD)
gp_row.add_child(_gp_value)
# 暂停层入口角标(迭代 17 卡③ P1 丁——顶栏常驻;debug 角标同形制:紧凑钮豁免宽度基准+字号降档。
# 置灰守卫归组合根 _sync_pause_entry(其他模态开着=不可点;本屏自身的登记开态不计——has_open_excluding);
# 信号连接归组合根(ADR-0001——视图零连接))
pause_badge = UiKit.button("暂停", 0.0)
pause_badge.add_theme_font_size_override("font_size", UiKit.FS_HINT)
pause_badge.tooltip_text = "查看钥石与永久强化进度(只读)"
pause_badge.size_flags_vertical = Control.SIZE_SHRINK_CENTER
top.add_child(pause_badge)
_title = UiKit.label(TITLE_FORK,UiKit.FS_SUB, true, UiKit.WARM)
_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_title)
@@ -121,7 +134,11 @@ func _init() -> void:
# 底部状态栏(M5 合并单条:亮米面板一站读齐=头像+生命+属性+本关加成/流派件——demo ④;
# 道具槽不摆=道具读数无关卡画面成文出口(读快照私域越权),随 runner 出口批补——台账 352 注记;
# _hp_value/_attr_value/_bonus_value/_feat_value 投喂键全部保留)
# 底栏定高纪律(2026-10-06 审计差距①对齐 demo——单条 ~85px 紧凑亮条;任何子件不再能把栏撑爆:
# 特性持有行限宽截断+tooltip 全文,旧「autowrap 无限宽→最小高度逐字竖排爆栏」形态根除)
var bottom := PanelContainer.new()
bottom.custom_minimum_size = Vector2(0, 85)
bottom.size_flags_vertical = Control.SIZE_SHRINK_END
bottom.add_theme_stylebox_override("panel",
UiKit.panel_flat(UiKit.MAP_BAR_PLATE, UiKit.CAMP_HEADER_BAND, 0, 2, Vector4(12, 6, 12, 6)))
box.add_child(bottom)
@@ -165,18 +182,22 @@ func _init() -> void:
_bonus_row.add_child(bonus_box)
var bonus_inner := VBoxContainer.new()
bonus_box.add_child(bonus_inner)
var bonus_cap := UiKit.label("特性",UiKit.FS_CAPTION, false, UiKit.WARM_SOFT)
var bonus_cap := UiKit.label("特性",UiKit.FS_CAPTION, false, UiKit.INK_HINT) # 淡墨→深墨(亮板可读,审计差距①)
bonus_inner.add_child(bonus_cap)
_bonus_value = UiKit.label("",UiKit.FS_BODY, true, UiKit.WARM)
_bonus_value = UiKit.label("",UiKit.FS_BODY, true, UiKit.INK_TITLE) # 淡墨→深墨(同上)
bonus_inner.add_child(_bonus_value)
# 特性持有行(迭代 12 呈现补齐 2026-10-04——用户反馈关卡选择页看不到局内奖励;组合根投喂)
_feat_value = UiKit.label("",UiKit.FS_HINT, false, UiKit.WARM_SOFT)
_feat_value.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
# 审计差距①修(2026-10-06):限宽单行截断+tooltip 全文(旧 autowrap 无限宽=爆栏元凶);
# 墨色 WARM_SOFT→INK_HINT(暖白系对亮板 ≈1:1 不可读——§7.2 违例修复)
_feat_value = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_HINT)
_feat_value.custom_minimum_size = Vector2(240, 0)
_feat_value.clip_text = true
_feat_value.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
bonus_box.add_child(_feat_value)
var spacer := Control.new()
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
strip.add_child(spacer)
abandon_btn = UiKit.danger_button("放弃") # 打磨包 2026-09-29 文案 + M5 危险钮皮(M10 公共件)
abandon_btn = UiKit.danger_button("放弃", "", 90.0) # 审计差距①对齐 demo:小号危险钮 ~90×38(原 216 宽砖);打磨包 2026-09-29 文案 + M5 危险钮皮
abandon_btn.pressed.connect(_on_abandon_pressed)
abandon_btn.visible = false
strip.add_child(abandon_btn)
@@ -211,6 +232,7 @@ func _draw_hp_bar(bar: Control) -> void:
# 特性持有投影(迭代 12 呈现补齐——组合根投喂聚合文案;空文案=行隐藏)
func set_feat_holdings(text: String) -> void:
_feat_value.text = text
_feat_value.tooltip_text = text # 截断全量兜底(限宽单行省略——悬停看全文)
func set_abandon_available(v: bool) -> void:
@@ -313,7 +335,8 @@ func _apply_level_tint(level_index: int) -> void:
_tint_level = level_index
var target: Color = BOARD_TINTS.get(level_index, Color(1, 1, 1))
var tw := create_tween()
tw.tween_property(_noise_rect, "modulate", target, UiKit.motion(0.45))
tw.tween_property(_noise_rect, "modulate",
Color(target.r, target.g, target.b, UiKit.BACKDROP_TILE_ALPHA), UiKit.motion(0.45)) # 0.14 弱质感档随 tint 保持(T5)
# 状态栏刷新(命令式纪律——组合根打开本屏/兑付确认回执后重查;零推送信号订阅)
+166
View File
@@ -0,0 +1,166 @@
# VERTICAL SLICE - NOT FOR PRODUCTION
# 局内暂停层·只读(迭代 17 卡③ 暂停层只读入口批 2026-10-06——任务书 v1.1;事实源=06-待办清单
# 「解锁界面与钥石呈现的交互形态(残余:暂停层只读入口)」)。
# 裁决落形:P1 丁=入口为战斗屏 HUD / 关卡地图屏常驻角标(入口装配在 ui_assembler/两屏,本类不含入口);
# P2 甲=登记 modal_stack 设置层同档(确认弹窗之前)带 dim 遮罩;P3 甲=展示钥石余额+三柜台进度
# (属性锻造三行已购等级 / 道具工坊六件解锁态 / 天赋树已购概览——层内行序与分组复用营地屏同序);
# P4 甲=进出零动效直开直关(无 tween 无 AnimationPlayer——R5)。
# 只读契约:R4 数据只读同源——账面快照由组合根 open_pause 喂入(每次开层实时读 MetaProgression
# 访问器重建,快照仅用单次开层生命周期,跨开层零持有);本类零核心访问、零写通路——唯一信号
# closed(关闭意图,组合根经模态栈单口收口)。R1 公共件单点:全部构成件经 UiKit 工厂产出
#(modal_shell/panel_skinned/label/button/keystone_badge),零裸色值零自建样式。
class_name PauseOverlay
extends Control
signal closed
var _balance_badge: UiKit.KeystoneBadge # 钥石余额徽(badge 工厂件——Q10 甲)
var _forge_holder: VBoxContainer
var _workshop_holder: VBoxContainer
var _tree_label: Label
func _init() -> void:
var shell: Dictionary = UiKit.modal_shell(self, Color(UiKit.DIM, 0.55), Vector2(560, 0), 10, true,
UiKit.panel_skinned(Vector4(20, 16, 20, 16))) # 石板皮(缺位回退数据板——同设置面先例)
var box: VBoxContainer = shell.box
var title := UiKit.label("暂停",UiKit.FS_TITLE, true, UiKit.INK_TITLE)
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(title)
var hint := UiKit.label("查看本局钥石与永久强化进度(只读——购买请回营地)",UiKit.FS_HINT, false, UiKit.INK_HINT)
hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(hint)
# 钥石余额行(badge 工厂件——与营地顶栏钥石徽同形制)
var bal_row := HBoxContainer.new()
bal_row.alignment = BoxContainer.ALIGNMENT_CENTER
box.add_child(bal_row)
_balance_badge = UiKit.keystone_badge("钥石 0")
bal_row.add_child(_balance_badge)
box.add_child(HSeparator.new())
_section_head(box, "属性锻造 · 已购等级")
_forge_holder = _section_holder(box)
_section_head(box, "道具工坊 · 解锁态")
_workshop_holder = _section_holder(box)
_section_head(box, "天赋树 · 已购概览")
_tree_label = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL)
_tree_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
box.add_child(_tree_label)
box.add_child(HSeparator.new())
var close_row := HBoxContainer.new()
close_row.alignment = BoxContainer.ALIGNMENT_CENTER
box.add_child(close_row)
var close_btn := UiKit.button("继续", 90.0) # 紧凑返回钮(设置面先例形制;文案=代拍板白名单「继续」级措辞)
close_btn.tooltip_text = "关闭暂停层,继续当前冒险(本层只读,不发生任何购买或修改)"
close_btn.pressed.connect(_emit_closed)
close_row.add_child(close_btn)
visible = false # 显式初始化——不靠树序巧合(缺陷⑤家族纪律)
# 分组小节头(营地屏分组同构——fs 副标题档深墨)
func _section_head(box: VBoxContainer, text: String) -> void:
var head := UiKit.label(text,UiKit.FS_BODY, true, UiKit.INK_LABEL)
box.add_child(head)
func _section_holder(box: VBoxContainer) -> VBoxContainer:
var holder := VBoxContainer.new()
holder.add_theme_constant_override("separation", 4)
box.add_child(holder)
return holder
# ---- 开层(组合根唯一调用口——快照随开随建,R4 单次开层生命周期口径)----
func open_pause(data: Dictionary) -> void:
_balance_badge.set_text("钥石 %d" % int(data.get("balance", 0)))
_rebuild_forge(data)
_rebuild_workshop(data)
_rebuild_tree(data)
visible = true
# 属性锻造三行(营地屏同序同文案族——名称+每级 flat / 已购等级;只读零价格零按钮)
func _rebuild_forge(data: Dictionary) -> void:
for c in _forge_holder.get_children():
c.queue_free()
for row in (data.get("forge", []) as Array):
var line := HBoxContainer.new()
line.add_theme_constant_override("separation", 8)
var name_l := UiKit.label("%s %+d/级" % [String(row.get("display_name", "")), int(row.get("flat", 0))],UiKit.FS_HINT, true, UiKit.INK)
name_l.custom_minimum_size = Vector2(150, 0)
name_l.clip_text = true
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(name_l)
var spacer := Control.new()
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
line.add_child(spacer)
var lvl_l := UiKit.label("Lv %d" % int(row.get("level", 0)),UiKit.FS_HINT, true, UiKit.INK_TITLE)
line.add_child(lvl_l)
_forge_holder.add_child(line)
# 道具工坊六行(解锁态文案与营地柜台同口径——退役/封存/已解锁/未解锁;进度=解锁判定量读数)
func _rebuild_workshop(data: Dictionary) -> void:
for c in _workshop_holder.get_children():
c.queue_free()
for row in (data.get("workshop", []) as Array):
var line := HBoxContainer.new()
line.add_theme_constant_override("separation", 8)
var name_l := UiKit.label(String(row.get("display_name", "")),UiKit.FS_HINT, true, UiKit.INK)
name_l.custom_minimum_size = Vector2(120, 0)
name_l.clip_text = true
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(name_l)
var prog_l := UiKit.label("累计通关 %d/%d 次" % [int(row.get("progress", 0)), int(row.get("threshold", 0))],UiKit.FS_HINT, false, UiKit.INK_HINT)
prog_l.custom_minimum_size = Vector2(150, 0)
prog_l.clip_text = true
prog_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
line.add_child(prog_l)
var st_l := UiKit.label(_workshop_state_text(row),UiKit.FS_HINT, true, UiKit.INK_LABEL)
st_l.size_flags_horizontal = Control.SIZE_EXPAND_FILL
line.add_child(st_l)
_workshop_holder.add_child(line)
# 解锁态文案(camp_overlay_view.refresh_camp 同款判据——退役 > 封存 > 已解锁 > 未解锁)
func _workshop_state_text(row: Dictionary) -> String:
if bool(row.get("retired", false)):
return "已退役"
if bool(row.get("deferred", false)) and bool(row.get("unlocked", false)):
return "已解锁 · 能力封存中"
if bool(row.get("unlocked", false)):
return "已解锁"
return "未解锁"
# 天赋树已购概览(单条聚合文案——已购节点等级 + Fork 组激活侧;零已购=空态句)
func _rebuild_tree(data: Dictionary) -> void:
var owned: Array[String] = []
for row in (data.get("tree", []) as Array):
var lvl := int(row.get("level", 0))
if lvl > 0:
owned.append("%s Lv%d/%d" % [String(row.get("display_name", "")), lvl, int(row.get("cap", 1))])
for fg in (data.get("fork_groups", []) as Array):
var active := String(fg.get("active_side", ""))
if active == "":
continue
var side_name := active
for sd in (fg.get("sides", []) as Array):
if String(sd.get("side", "")) == active:
side_name = String(sd.get("display_name", active))
break
owned.append("%s·激活 %s" % [String(fg.get("display_name", "")), side_name])
if owned.is_empty():
_tree_label.text = "尚未购买任何节点(天赋树在营地柜台三)"
else:
_tree_label.text = "已购 %d 项:%s" % [owned.size(), " · ".join(owned)]
func _emit_closed() -> void:
closed.emit()
@@ -0,0 +1 @@
uid://dgmv0kar3ualk
+18 -8
View File
@@ -34,7 +34,9 @@ func retarget(store) -> void:
func _build() -> void:
# M4(UI 落码批):石板面板化(demo ③)+行牌化(标签+拨杆+状态字+后果说明行);
# 设置项零增减(P-C6:只有主音量——demo 音效音量行系原型发明已撤);
# 减动效与结算演出动画=同一设置(语义命名批合并),一行承载
# 减动效与结算演出动画=同一设置(语义命名批合并),一行承载。
# T8(UI 设计对齐批 2026-10-06):两列对齐(label 列定宽 140——demo .setrow label/控制两列)+
# 后果说明内联随行(demo .why 同排)+返回钮紧凑化(demo .btn9 紧凑——原 216 宽砖)。
var shell: Dictionary = UiKit.modal_shell(self, UiKit.BG_BRIGHT, Vector2(560, 0), 8, true,
UiKit.panel_skinned(Vector4(20, 16, 20, 16)))
var box: VBoxContainer = shell.box
@@ -51,9 +53,12 @@ func _build() -> void:
var vol_row := HBoxContainer.new()
vol_row.add_theme_constant_override("separation", 14)
box.add_child(vol_row)
vol_row.add_child(UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL))
var vol_lab := UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL)
vol_lab.custom_minimum_size = Vector2(140, 0) # T8 label 列定宽(两列对齐)
vol_row.add_child(vol_lab)
_volume = UiKit.styled_slider(100.0, 0.0, 100.0)
_volume.step = 1
_volume.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_volume.value_changed.connect(_on_volume_changed)
vol_row.add_child(_volume)
_volume_val = UiKit.label("100%",UiKit.FS_BODY, true, UiKit.INK_TITLE)
@@ -64,33 +69,38 @@ func _build() -> void:
var fs_row := HBoxContainer.new()
fs_row.add_theme_constant_override("separation", 14)
box.add_child(fs_row)
fs_row.add_child(UiKit.label("全屏",UiKit.FS_BODY, false, UiKit.INK_LABEL))
var fs_lab := UiKit.label("全屏",UiKit.FS_BODY, false, UiKit.INK_LABEL)
fs_lab.custom_minimum_size = Vector2(140, 0) # T8 同上
fs_row.add_child(fs_lab)
_fs_btn = UiKit.switch_toggle(false)
_fs_btn.toggled.connect(_on_fullscreen_toggled)
fs_row.add_child(_fs_btn)
_fs_st = UiKit.label("关",UiKit.FS_HINT, true, UiKit.INK_LABEL)
fs_row.add_child(_fs_st)
# 结算演出动画(=减动效实称——语义命名批 T17;拨杆 on=完整,off=快速时长减半)
# 结算演出动画(=减动效实称——语义命名批 T17;拨杆 on=完整,off=快速时长减半。
# T8 核证:reduced_motion 单设置同驱 UiKit.motion_scale 与结算演播——demo「减动效」行与
# 本行系同一设置,不另立行(拆两行=一设置双行重复,违语义命名批裁决)
var motion_row := HBoxContainer.new()
motion_row.add_theme_constant_override("separation", 14)
box.add_child(motion_row)
motion_row.add_child(UiKit.label("结算演出动画",UiKit.FS_BODY, false, UiKit.INK_LABEL))
var motion_lab := UiKit.label("结算演出动画",UiKit.FS_BODY, false, UiKit.INK_LABEL)
motion_lab.custom_minimum_size = Vector2(140, 0) # T8 同上
motion_row.add_child(motion_lab)
_motion_btn = UiKit.switch_toggle(true)
_motion_btn.toggled.connect(_on_motion_toggled)
motion_row.add_child(_motion_btn)
_motion_st = UiKit.label("完整",UiKit.FS_HINT, true, UiKit.INK_LABEL)
motion_row.add_child(_motion_st)
var why := UiKit.label("快速 = 时长减半(运动敏感 / 演示用)",UiKit.FS_CAPTION, false, UiKit.INK_HINT)
why.position.y = 0
box.add_child(why)
motion_row.add_child(why) # T8 内联随行(demo .why 同排;原独立行换排)
box.add_child(HSeparator.new())
# 退出游戏已提级开始菜单(D1——设置面不再承载,用户裁决「退出只在一级菜单出现」)
var close_row := HBoxContainer.new()
close_row.alignment = BoxContainer.ALIGNMENT_CENTER
box.add_child(close_row)
var close_btn := UiKit.button("返回")
var close_btn := UiKit.button("返回", 90.0) # T8 紧凑返回钮(demo 紧凑形;原 216 宽砖)
close_btn.pressed.connect(_emit_closed)
close_row.add_child(close_btn)
Loaded 100 of 116 files, more files were not shown because too many files have changed in this diff. Show more