写卡(全局特殊间隔闸批·设计闭合卡成立): 待办清单「全局特殊间隔旋钮」条备选转正——敌人特殊技公共冷却(任一特殊技兑现后该敌K拍强制普攻,堵异名背靠背),三裁点用户2026-11-09计划批准在案(K=1/每敌独立计数/双面过滤+保底顺延)。落文: 敌人系统.md v1.9→v2.0(两道闸→三道闸+取值域special_interval行+P1备用行删除+摇号时序/举证/验收口径换代+池节奏三联动→四联动), 难度曲线与Boss.md v1.7→v1.8(技能池投值表增特殊间隔K行), 待办清单条目推进「文档设计已闭合+已写卡」。卡片: reports/需求卡片-全局特殊间隔闸批-2026-11-09.md(T0-T3估时1.75日/对照表A1-A8/验收档高/零待裁点/开工门=U0), 对抗复核1轮8发现(3补写5自判)全落卡内复核记录节。能力表增行「全局特殊间隔闸」。区内凭据: 流水线闸PASS(34条目/57行/2链/6卡全过)+文档域闸【验收通过】无新增红
This commit is contained in:
1 parent
57f28922a1
commit
a62d79efa6
5 files changed
+184
-20
No files matched your search
@@ -0,0 +1,161 @@
|
||||
# 需求卡片:全局特殊间隔闸批(2026-11-09)
|
||||
|
||||
> 来源:待办清单「全局特殊间隔旋钮」条目(2026-10-18 登记)。
|
||||
> 验收档:高(数值表结构校验+敌人出招行为随结算传播)。
|
||||
> 来源:设计事实源见下节(唯一事实源声明)。
|
||||
|
||||
## 1. 目标与完成定义
|
||||
|
||||
给敌人加**特殊技公共冷却**(全局特殊间隔闸):任一特殊技兑现后,该敌接下来 K 拍只能执行普通攻击——堵死「不同大招背靠背接力」(现行各技能自己的冷却只堵同招连发)。
|
||||
|
||||
完成定义(全部满足才算完):
|
||||
|
||||
1. 技能表新字段 `special_interval`(全局单旋钮,域 [0,99],0=关闭)在 schema 域校验与 `skills.tres` 行值两处落位,K=1。
|
||||
2. 敌人实例带间隔闸计数,闸期内特殊技不进可摇集合与保底集合(双面过滤,保底顺延)。
|
||||
3. 验证闸对照表 A1–A8 全部在当轮真实跑批执行并通过;代码域闸全绿。
|
||||
4. 同种子回放契约保持(新行为下逐位复现);EV 锚按新行为换代。
|
||||
|
||||
## 2. 设计事实源
|
||||
|
||||
`design/gdd/systems/战斗循环/敌人系统.md` v2.0「三道闸」表(全局特殊间隔行)+同文档「调参表」`special_interval` 行+同文档「验收标准·池节奏」;投值所有权=`design/gdd/systems/冒险循环/难度曲线与Boss.md` v1.8「调参表」特殊间隔 K 行。与待办清单条目闭合凭据一致(该条目状态=文档设计已闭合+已写卡)。
|
||||
|
||||
三裁点已随设计闭合裁死(用户 2026-11-09 批准在案,卡内不再开裁):**K=1**;**每敌独立计数**(全部敌人含 Boss);**双面过滤+保底顺延**。
|
||||
|
||||
## 3. 现状事实(开工自行复核)
|
||||
|
||||
- 开轮摇号主体在 `game/core/settlement/round_cycle.gd:91` `roll_round_actions(ri)`——逐存活敌:可摇集合(`units.rollable_skills`)→ 保底判定(`basic_streak >= pity_m` 时 `special_skills` 非空则整体替换)→ `SkillLottery.draw` 取号(behavior_roll 流,每敌每轮恰一次)→ 末尾 `tick_cooldowns()`(递减在摇号读值之后)。
|
||||
- 可摇集合过滤在 `game/core/unit_container.gd:227` `rollable_skills`——条目级排除触发条件不满足(`_entry_blocked`)与冷却中(`cooldown_left <= 0` 判断)。保底集合在 `game/core/unit_container.gd:242` `special_skills`——type≠basic 全部非锁定条目,不受冷却限制(注释明示「锁定条目双面过滤」先例)。
|
||||
- 执行上报在 `game/core/unit_container.gd:300` `commit_action`——按 `cooldown_beats` 置 `cooldown_left`(施放行),普攻 `basic_streak +1`/特殊技归零;摇定后兑现前死亡不经本方法=作废不进账。
|
||||
- 冷却递减在 `game/core/unit_container.gd:324` `tick_cooldowns`——时序口径(`:320` 注记):摇号按当前值排除、递减在其后=「施放后连续 N 拍不可摇中」的等价实现。间隔闸计数沿用同一时序口径。
|
||||
- 实例状态初始化在 `game/core/unit_container.gd` `_spawn_rowset`(`basic_streak = 0` 同点);保底读数 `basic_streak` 在 `:289`。
|
||||
- 表值:`game/data/tables/skills.tres` `pity_threshold = 4`;schema 在 `game/data/schemas/skill_table.gd`(`@export var pity_threshold: int = 4`,域校验 [1,99] 越域报 category=domain 止动,同函数即本卡新增校验的落点)。
|
||||
- ConfigDB 装配单点在 `game/core/config_db.gd`(`combat.skill` 整容器挂载)——新表字段零装配改动。
|
||||
- 既有测试面:`game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd`(`_smoke_skill_pool` 总入口、`_smoke_skill_pool_data` 表数据面、`_smoke_skill_pool_replay_independence` 同种子回放、`_smoke_skill_pool_ev_anchor` 5000 拍 EV 对锚〔内含保底替换逻辑复刻〕、`_smoke_skill_pool_death_void`、`_smoke_skill_pool_validation_reject`);`trigger_cond_test.gd`(保底不逼条件不满足技);`skill_unlock_test.gd`(保底不逼锁定技)。系统测试与探针无敌人出招节奏断言(`skill_rhythm_probe.gd`/`rhythm_batch.gd` 为零断言取数件,不在本卡面)。
|
||||
|
||||
## 4. 设计契约(违反即返工)
|
||||
|
||||
- 🔴 **双面过滤**:闸期内特殊技不进可摇集合、也不进保底集合——保底禁止逼出闸中技;闸期内保底集合可为空,保底不兑现、顺延到闸后满 M 首拍。
|
||||
- 🔴 **数值单点**:K 只存 `skills.tres` `special_interval`,经 ConfigDB 单点读;禁数值字面量、禁自建 load 路径。
|
||||
- 🔴 **随机零新增**:不加随机源、不改取号次数(每敌每轮恰一次 behavior_roll);过滤发生在取号前的集合组装面。同种子回放契约=新行为下逐位复现(旧种子轨迹因行为换代不续用,属预期换代非回归)。
|
||||
- 🔴 **两计时器独立**:`special_lock` 与各条目 `cooldown_left` 互不读写;死亡作废(未经 commit_action)不进闸、不清闸。
|
||||
- 🔴 **Core 零 UI**:改动全部落在 core/数据层与单元测试;零呈现面、零场景改动。
|
||||
- 🔴 **fail-fast**:`special_interval` 越域 [0,99] 加载期 domain 错误止动,无软回退。
|
||||
|
||||
## 5. 范围边界
|
||||
|
||||
做什么:上列 T0–T3。不做什么:呈现面(不碰);MC/verifier 重跑(读数类不属改完即测域,是否重测全冒险期望=合回后用户按 MC 档位表裁);池权重/冷却/倍率重投值(EV 重锚仅指测试锚换代,投值调参归难度曲线批);术语表增删(无新术语)。明示不收件去向:实测节奏读数需求归 `skill_rhythm_probe.gd`/`rhythm_batch.gd` 既有取数件,不在本卡。
|
||||
|
||||
## 6. 关联文档同步面
|
||||
|
||||
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|
||||
|---|---|---|
|
||||
| `design/gdd/systems/战斗循环/敌人系统.md` | 「三道闸」表与「调参表」special_interval 行(v2.0 已落文) | 设计权威文档——实现批禁直改;实现与条款失配→列 `reports/iter<N>-反哺点-<日期>.md` 由用户裁决后归文档批 |
|
||||
| `design/gdd/systems/冒险循环/难度曲线与Boss.md` | 「调参表」特殊间隔 K 投值行(v1.8 已落文) | 同上 |
|
||||
| `game/tests/README.md` | 能力表增行「全局特殊间隔闸」 | 本写卡批已随卡增行(机械面);实现批禁写,批末只核对表上名字与实际落地一致 |
|
||||
| `待办清单.md` | 「全局特殊间隔旋钮」条目状态 | 流水线面——实现批禁写;实现批完成入库后按退役规则整条删除(归收尾段) |
|
||||
|
||||
## 7. 卡前·文件结构图(全部既有件,零新增文件)
|
||||
|
||||
| 文件 | 职责 | 改动性质 |
|
||||
|---|---|---|
|
||||
| `game/data/schemas/skill_table.gd` | 技能表 schema:加 `special_interval` 字段与域校验 | 行为改动(A4、A5) |
|
||||
| `game/data/tables/skills.tres` | 技能表行值:`special_interval = 1` | 行为改动(A1 全部行为的表值源) |
|
||||
| `game/core/unit_container.gd` | 实例闸计数与双面过滤(rollable/special_skills/commit/tick/初始化) | 行为改动(A1、A2、A3) |
|
||||
| `game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd` | 新增节奏断言、数据面与校验扩展、EV 锚换代 | 行为改动(A1–A7 的测试面) |
|
||||
| `game/tests/README.md` | 能力表增行(本写卡批已做) | 非行为改动 |
|
||||
|
||||
## 8. 任务卡
|
||||
|
||||
估时总计 ≈1.75 个工作日(区间 1.5–2.0)。T 卡间接口:T1 产出 `special_lock` 实例键与双过滤行为(T2/T3 取用);T0 产出表字段与读数路径(T1 的 `db.combat.skill.special_interval` 取用)。
|
||||
|
||||
### T0 表与 schema(0.25d)
|
||||
|
||||
- [ ] `skill_table.gd` 加 `@export var special_interval: int = 1`(pity_threshold 同区;注释一行口径:全局特殊间隔 K——任一特殊技兑现后该敌连续 K 拍只能执行普通攻击,0=关闭;provisional 归难度曲线与Boss)。
|
||||
- [ ] `_validate_table_invariants` 加域校验:`special_interval` 出 [0,99] → `{"category": "domain", ...}` 止动(pity 同款句式)。
|
||||
- [ ] `skills.tres` `[resource]` 区加 `special_interval = 1`(pity_threshold 行下)。
|
||||
- [ ] `_smoke_skill_pool_data` 扩展:断言 `db.combat.skill.special_interval == 1`(表实一致读数面)。
|
||||
- [ ] 验证步:直跑单元套件(`--script res://tests/run_all.gd`)全绿,读数记录。
|
||||
|
||||
### T1 实例闸(0.5d)
|
||||
|
||||
- [ ] 实例创建处(`_spawn_rowset` 内 `basic_streak = 0` 同点)增 `special_lock = 0` 初始化。
|
||||
- [ ] `rollable_skills`:`int(u.get("special_lock", 0)) > 0` 时,非 basic 条目跳过(type 经 `db.combat.skill.row_by_id` 查——`special_skills` 同款查法);签名为既有签名零改。
|
||||
- [ ] `special_skills`:lock>0 时返回空数组(含注释一行:闸中特殊技不进保底集合——保底顺延)。
|
||||
- [ ] `commit_action`:`srow.type != "basic"` 分支置 `u.special_lock = int(db.combat.skill.special_interval)`;普攻分支不动 lock。
|
||||
- [ ] `tick_cooldowns`:逐敌 `u["special_lock"] = maxi(0, int(u.get("special_lock", 0)) - 1)`(与池条目冷却递减同轮同点)。
|
||||
- [ ] 验证步:直跑单元套件全绿,读数记录。
|
||||
|
||||
### T2 节奏断言(0.5d)
|
||||
|
||||
- [ ] 新增 `_smoke_skill_pool_interval_gate`:真实入口 `BattleOrchestrator.begin_battle()` → `roll_round_actions()`。**夹具钉死**:单敌实例、池=恰一普攻+恰一无条件特殊技、且该特殊技 `cooldown_beats = 0`(排除冷却混淆归因——无闸时背靠背才机制可能,有闸时交替的排除唯一来自闸)。调试接口设 `pity_threshold = 1`、`special_interval = 1`:断言执行行序列严格「特殊技/普攻」逐拍交替(保底每拍触发+闸强制普攻的合成节奏);再设 `special_interval = 0`:断言出现背靠背特殊技(连续两拍 special)=旧口径等价(种子与权重按本文件既有种子狩猎惯例定)。判据绑定面=行动执行行的 skill_id 逐拍序列(单特殊技池 → id 级确定)。测试毕恢复表值。
|
||||
- [ ] 新增 `_smoke_skill_pool_interval_pity`:`pity_threshold = 4`、`special_interval = 6`:断言特殊技兑现后 6 拍内零特殊技(其中 streak≥4 的拍保底不兑现)、第 7 拍保底兑现出特殊技。判据绑定面同上;表值直改收尾恢复(凡直改共享表值的测试函数一律收尾恢复——泄漏即污染同套件下游读数)。
|
||||
- [ ] 每敌独立断言(并入 `_smoke_skill_pool_interval_gate`):双实例同池(同 T2 首条钉死的零冷却池),容器 API 对 u1 先 `set_pending_action(u1, 特殊技 id)` 再 `commit_action`(无 pending 则 commit 空转——前置必写),断言 u1 可摇集合排除特殊技、u2 可摇集合含特殊技。
|
||||
- [ ] `_smoke_skill_pool_validation_reject` 扩展:`special_interval` 越域(−1 与 101 两例)加载期 domain 止动断言。
|
||||
- [ ] `_smoke_skill_pool_death_void` 扩展:摇定后兑现前死亡作废拍后断言 `special_lock` 保持 0(死亡作废不进闸)。
|
||||
- [ ] 验证步:直跑单元套件全绿,读数记录。
|
||||
|
||||
### T3 锚换代与收尾(0.5d)
|
||||
|
||||
- [ ] `_smoke_skill_pool_ev_anchor`:测试内保底替换复刻补 lock 过滤(与实现同口径);5000 拍重锚——新阈值按新行为实测读数推导(换代申报见「测试削弱申报」节)。
|
||||
- [ ] `_smoke_skill_pool_replay_independence` 复闸:观测窗覆盖保底与间隔闸共存段,同种子逐位复现绿。
|
||||
- [ ] 里程碑步(T 段)出口跑一次全套代码域闸;波内修复只做出红最小单元的最窄确认。
|
||||
- [ ] 产出物落位卡:轻闸全绿后、合并前写齐 `reports/iter<N>-实现报告-<日期>.md`(各卡状态+实机目检总清单〔本批零呈现面,目检清单登记「无」〕+遗留读数义务+实现决定记录)与 `reports/iter<N>-反哺点-<日期>.md`(同步面四条的落点逐条交代:两份 GDD 本卡批已落文无需同步、README 已增行、待办清单归收尾段删除)。
|
||||
|
||||
## 9. 验证闸(改动—验收对照表)
|
||||
|
||||
| # | 需求点(含判据出处锚) | 改动(文件/行为) | 验收测试(名称+落点) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| A1 | 兑现后 K 拍强制普攻、K=0 等价旧口径——`design/gdd/systems/战斗循环/敌人系统.md「技能池:每敌种一张带权技能池,每拍开轮摇号出招」全局特殊间隔 | `unit_container.gd` rollable/commit/tick+`skills.tres` 表值 | `round_flow_skill_pool_test.gd:_smoke_skill_pool_interval_gate` | 单元 | `BattleOrchestrator.begin_battle()` → 开轮摇号(调试接口 pity=1 配 K=1 与 K=0 两档;夹具零冷却单特殊技池) | 行动执行行 skill_id 逐拍序列(交替/背靠背两判据;单特殊技池 id 级确定) | 新增:全局特殊间隔闸 |
|
||||
| A2 | 保底顺延(闸期不兑现、闸后满 M 首拍兑现)——`design/gdd/systems/战斗循环/敌人系统.md「技能池:每敌种一张带权技能池,每拍开轮摇号出招」保底顺延 | `unit_container.gd` special_skills 排空+保底替换路径 | `round_flow_skill_pool_test.gd:_smoke_skill_pool_interval_pity` | 单元 | 同上(调试接口 pity=4 配 K=6) | 执行序:兑现后 6 拍零特殊技、第 7 拍保底兑现 | 新增:全局特殊间隔闸 |
|
||||
| A3 | 每敌独立计数——`design/gdd/systems/战斗循环/敌人系统.md「调参表」special_interval | per-instance `special_lock` | `_smoke_skill_pool_interval_gate` 内独立断言 | 单元 | `UnitContainer` 容器 API(commit→rollable 对照) | 双实例可摇集合返回差异 | 新增:全局特殊间隔闸 |
|
||||
| A4 | 越域加载期止动——`design/gdd/systems/战斗循环/敌人系统.md「调参表」special_interval | `skill_table.gd` 域校验 | `_smoke_skill_pool_validation_reject` 扩展 | 单元 | 表加载校验链(ConfigDB 装载) | category=domain 错误+止动 | 既有:技能池数据面与回放独立 |
|
||||
| A5 | 表实一致(字段在库、读数路径通)——`design/gdd/systems/战斗循环/敌人系统.md「调参表」special_interval | `skills.tres`+`skill_table.gd` | `_smoke_skill_pool_data` 扩展 | 单元 | `BattleOrchestrator.begin_battle()` 表读数 | `db.combat.skill.special_interval == 1` | 既有:技能池数据面与回放独立 |
|
||||
| A6 | 同种子回放契约保持——`design/gdd/systems/战斗循环/敌人系统.md「验收标准」摇号确定性 | 全部改动面 | `_smoke_skill_pool_replay_independence` 复闸 | 单元 | `begin_battle()` 同种子双跑 | 逐实例摇定轨迹逐位相同 | 既有:技能池数据面与回放独立 |
|
||||
| A7 | EV 锚随行为换代——`design/gdd/systems/冒险循环/难度曲线与Boss.md「调参表」特殊间隔 | 行为换代→测试内期望复刻同步 | `_smoke_skill_pool_ev_anchor` 重锚 | 单元 | `begin_battle()` 5000 拍模拟 | 复刻期望与模拟频率对锚通过 | 既有:技能池数据面与回放独立 |
|
||||
| A8 | 死亡作废不进闸——`design/gdd/systems/战斗循环/敌人系统.md「验收标准」死亡即不动手 | 作废路径零 lock 副作用 | `_smoke_skill_pool_death_void` 扩展 | 单元 | `begin_battle()`(摇定后兑现前击杀路径) | 作废拍后 `special_lock == 0` | 既有:技能池数据面与回放独立 |
|
||||
|
||||
测试方式两分法:A1–A7 全部走调试接口直改表值(能力验证),无正常流程体验项;实机目检登记「无」(零呈现面)。
|
||||
|
||||
**测试削弱申报**:`_smoke_skill_pool_ev_anchor` 对锚阈值换代(行为换代所致,断言形态不变)——此外零删零宽。
|
||||
|
||||
**独立验收审计**:入口=未参与实现的会话或子代理;报告落 `reports/iter<N>-验收审计-<日期>.md`;未过不得合并。验收档=高(审计深度按 test-conventions §8.7 高档执行)。
|
||||
|
||||
**回归措辞**:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。
|
||||
|
||||
## 10. 异常分级
|
||||
|
||||
- **L1 自救**:断言夹具表值恢复遗漏、测试函数内变量遮蔽之类自净问题——当场修,读数进提交信息。
|
||||
- **L2 记录继续**:EV 重锚一次不中(实测读数与推导偏差)——按读数修正推导再锚,连续 3 次不中升 L3。
|
||||
- **L3 停机呈报**:①闸语义与 GDD 条款失配(退回上游);②机检预算互斥=上游缺陷停卡退回写卡段;③保底×间隔时序出现设计未预见的死锁形态(保底永不兑现类)——停机写报告等用户。
|
||||
|
||||
## 11. 代拍板白名单
|
||||
|
||||
测试夹具的池配置(池构成纪律内的最小池);断言消息文案;EV 锚新阈值的具体推导取值(按实测读数);闸内代码注释措辞;提交信息措辞。超清单决定记入实现报告「实现决定记录」节。
|
||||
|
||||
## 12. 待裁点
|
||||
|
||||
零待裁点,开工门=U0。三裁点(K=1/每敌独立/双面过滤+保底顺延)已随设计段闭合由用户裁死(2026-11-09 计划批准在案),卡内不再重开。
|
||||
|
||||
## 13. 落位与可复用性预检
|
||||
|
||||
- **新增面清点**:零新增文件;新增 schema 字段 1 个(`special_interval`)、实例字典键 1 个(`special_lock`)、单元测试函数 2 个。
|
||||
- **复用面**:字段落点复用 `pity_threshold` 同区同款(全局单旋钮先例);实例闸计数复用 `basic_streak`/`cooldown_left` 的实例字典键与「commit 置值→tick 递减→摇号读值排除」既有三段式时序(`:320` 注记口径),不新增计时器机制——**为什么不是复用冷却本身**:冷却按技能行条目计,堵不住异名接力(本闸语义恰是跨条目),实例级单键是唯一落点。
|
||||
- **唯一面**:K 读数只在 `db.combat.skill.special_interval` 一处定义、`skills.tres` 一处存值;`special_lock` 读写集中在 `unit_container.gd` 四处(init/rollable+special_skills 过滤/commit 置值/tick 递减),无第二落点。
|
||||
- **分层与交互面**:改动全在 core 与数据层——ConfigDB 单点取值、零 UI、零事件、随机消费面不变(RngService/SkillLottery 零触碰);测试经既有 `begin_battle()` 真实装配链驱动。
|
||||
|
||||
## 14. 实现规范预算
|
||||
|
||||
零新增文件,新件三查不适用。存量触面:`skill_table.gd`(+1 export、+1 校验分支)、`unit_container.gd`(rollable +1 分支、special_skills +1 早退、commit +1 分支、tick +1 行、init +1 键)——增量均在 gdstyle 默认阈值内,S13 键较登记值只降不升预期;测试文件新增 2 函数(单函数分支 ≤8 内)。
|
||||
|
||||
## 15. 复核记录
|
||||
|
||||
| 轮次 | 复核者 | 发现 | 去向 | 处置结果 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 只读子代理(未参与撰写) | 锚 8 行全实读命中、现状 file:line 全对、时序推演严格等价(K=1 恰覆盖下拍/M4+K6 第 7 拍兑现/死亡路径零触碰 lock)、引擎面三查过、落位预算自洽 | 自判 | 核实为真,零改 |
|
||||
| 1 | 同上 | A1 双臂缺「夹具特殊技冷却=0」前提——K=0 臂机制不可能绿、K=1 臂排除归因被冷却混淆 | 补写 | T2 首条钉死夹具(恰一普攻+恰一无条件特殊技、cooldown_beats=0);A1 绑定面补「单特殊技池 id 级确定」 |
|
||||
| 1 | 同上 | A3 双实例对照受冷却冒领风险;commit 前置 set_pending_action 未写明 | 补写 | T2 独立断言条补零冷却夹具与 pending 前置 |
|
||||
| 1 | 同上 | `_interval_pity` 直改共享表值缺恢复义务(泄漏污染同套件下游) | 补写 | T2 补「凡直改共享表值的测试函数一律收尾恢复」 |
|
||||
| 1 | 同上 | K=0 臂背靠背是种子/权重依存非结构保证 | 自判 | 不改——种子狩猎=本文件既有惯例且在代拍板白名单,实现期定 |
|
||||
| 1 | 同上 | 回放观测窗可能整窗零特殊技(闸未被行使) | 自判 | 不改——种子狩猎惯例可解,T3 义务在卡 |
|
||||
| 1 | 同上 | A4/A5 真实入口措辞与直构 validate/直读 db 惯例有出入 | 自判 | 不改——既有单元面惯例内,语义不失真 |
|
||||
| 1 | 同上 | A7 锚行与 EV 重锚义务有语义距离(重锚落文在相邻表行) | 自判 | 不改——锚词命中节内、所有权读法成立 |
|
||||
Reference in new issue
Block a user