17 KiB
17 KiB
M80 · 战斗模拟(脚本演示 → 真模拟)
Owner 决定(2026-09-15):选 B 继续——把战斗从"固定 9 拍脚本"变成读取内容规则的真模拟 (320 装备/100 敌人/60 遗物/36 特质/职业基础行动真正起作用),先做最小可玩循环。
Player-visible stopping point
一场战斗由 02_GAMEPLAY_AND_BALANCE.md 的规则决定:100ms tick 与固定优先级、Ready/Tempo 节奏、
reach/目标选择、Guard/护盾、伤害公式(含暴击与标签化随机)、击倒与线列收缩、目标/胜负判定;
玩家能看到的结果由内容决定(敌人规则、装备触发、职业基础行动、特质),而不是固定剧情演出。
表现层(战场/节拍/音效)继续由事件流驱动,视觉方向不变。
Authority
docs/02_GAMEPLAY_AND_BALANCE.md:§8 时间/事件/随机、§9 属性、§10 Ready 与自动行动、§11 目标/reach、 §13 治疗与保护、§14 移动/推拉、§15 伤害、§16 状态、§17 装备钩子、§18 死亡与替换、§19 控制/撤退/超时/胜负、§24 固定测试向量。docs/05_CONTENT_CATALOG.md:职业基础行动与资源、特质、装备效果、敌人规则(逐行)。- 现有表现层事件契约(
battle_live_art的 kind/actor/target/amount 与 BAT 音效)保持不变。
Ordered steps(每步一个提交 + 一个窄门)
- B1(COMPLETE)战斗内核:
runtime/domain/battle_simulation.gd—— tick 循环与优先级、 属性→派生(§9 公式)、Ready/Tempo、基础行动、reach/目标、Guard、§15 伤害(含暴击与标签化掷骰)、 击倒/线列收缩、胜负与日志;runtime/tests/battle/battle_core_test.gd(公式抽查 + 同种子逐字节一致 + 不同种子只改对应标签流 + 击倒→收缩→胜负)。 - B2(职业 COMPLETE)职业与特质:12 基础职业的行动表已就位——
runtime/domain/profession_actions.gd(12 表 × 3 优先级行 = 36 行、12 个本地资源、reach 1/2/line 与 projectile/area/restore 语义,出处为05_CONTENT_CATALOG.md的 rules/cadence 与02_GAMEPLAY_AND_BALANCE.md§5/§10),模拟按优先级行从下往上扫描:ABG_M80_PROFESSION_ACTIONS_OK tables=12 rows=36 resources=12 reach=2-line healing=true deterministic=true。 B2b(COMPLETE)特质:runtime/domain/trait_hooks.gd覆盖全部 36 条特质——每行声明一个 §17 合法钩子 (before_target/after_damage/after_heal/on_*…)+ 源自benefit的声明式效果,并标记implemented; 当前 6 条已实现(TR-001/017 reach、TR-010 治疗、TR-022 Guard、TR-025 资源、TR-018 加速等),其余待其系统 (construct/summon/sound/装备冷却/区域危害)在 B3/B4 落地后逐行启用(见M80-I03)。 门:ABG_M80_TRAIT_HOOKS_OK traits=36 hooks=legal implemented=6 effect=measurable deterministic=true - B3 装备与敌人:320 装备按触发类别实现(首次受击/换位联动/护卫转移/治疗联动/冷却…); 区域 1 的 12 条敌人规则;Boss 规则最小集。
- B4 合同结构与区域语法:12 回合制(
round_count)、区域 1 的遭遇语法(reach/保护/推/弹幕屏)、 难度参数只改数值不改隐藏规则(§20)。 4b. B5-lite(IN_PROGRESS)数值作者化 + 接线:- 已补:
runtime/domain/battle_stat_authoring.gd—— 12 基础职业的基础数值(在文档带内:BaseHP 140-420 / BaseTempo 24-55 / BaseInitiative 0-45)与普通/精英/Boss 三档敌人基础数值 + 区域压力 ×1.00-1.45; 门ABG_M80_STAT_AUTHORING_OK professions=12 classes=3 bands=declared deterministic=true。 - 已补:
runtime/entry/battle_sim_bridge.gd—— 真实远征团(职业/特质/等级/属性)+ 敌人报价 + 区域压力 → 模拟演员行 → 运行 → 九拍呈现事件(开场 / 7 个节拍 / 结果)与击倒列表。 - 已接线(COMPLETE):
battle_service在开战时跑一次模拟并把结果存为sim_events(计划)+sim_outcome/sim_knockouts;_event_for_phase优先返回计划中的对应相位事件(仍保持"每次推进追加一条"的 不变量 ✓),因此观察/结算校验与回执/快照/结果锁全部保持不变 ✓。首版曾预填phase_events从而破坏 该不变量(实测战斗停住)——已改为计划式取用 ✓。 - 全流程门:34 步 0 阻断 ✓ 首通事实/声望 ✓ 图鉴 ✓ 战斗场/墨迹/节拍 ✓ 音频族 ✓(音频门已按"真战斗内容可变" 改为:开战 + 战斗族 + ≥1 个映射节拍,不再要求固定出现远程/治疗拍)。
- 已补:
- B5 接线与门:用模拟事件流驱动现有战场表现/节拍/BAT 音效;全流程驱动换到真模拟; 双档双语探针 + 源绑定 attempt;真机可玩性由 Owner 验收。
Frozen scope
- 表现层、页面、音频与内容数据不改(只改战斗的"规则来源")。
- 不新增内容行;不实现设计文档之外的自创机制;数值一律取自文档公式。
- 登录/联机、付费、语音等内容不在本里程碑。
B1 产出(2026-09-15)
runtime/domain/battle_simulation.gd:纯净、无引擎依赖的 tick 模拟(100ms/优先级简化、§9 派生(1/100 向下取整)、 §10 Ready/Tempo 与溢出保留、§11 side→reach→protection→frontmost 与target_tie、§15 伤害与暴击、 Guard 吸收、§18 Fallen→线列收缩、§19 胜负、标签化掷骰与日志)。runtime/tests/battle/battle_core_test.gd:派生/伤害公式抽查、同种子日志逐字节一致、跨种子 "首个目标一致 + 暴击流不同"、结果/收缩断言 →ABG_M80_BATTLE_CORE_OK derived=formula damage=formula deterministic=true labels=independent outcome=victory ticks=224。
Acceptance checks
- B1:公式抽查与文档一致;同种子两次运行日志逐字节一致;标签化掷骰只影响自己的流; 0 HP → Fallen → 线列收缩 → 目标判定;无随机伤害方差、无隐藏命中率。
- B2-B4:每条实现的规则可在
05_CONTENT_CATALOG.md找到出处,且有对应断言。 - B5:既有 30 个 marker 不回归;战斗探针(墨迹/尺度/节拍/音频)继续全绿。
Issue register
| ID | 状态 | 说明 |
|---|---|---|
M80-I01 |
OPEN | 旧 battle_service 的 9 拍脚本是历史演示层;B5 接线后保留其回执/快照边界,替换事件来源 |
M80-I04 |
RESOLVED(2026-09-15) | 目录只有规则文本、无逐条战斗数值(文档只给职业数值带与敌人 rank 语义)→ 新增 |
battle_stat_authoring.gd 在一个可复核处作者化数值并带带内校验;round_count/敌人 rank 的表值仍待设计补全 |
||
M80-I06 |
OPEN | 区域 1 的 12 条敌人档案已可执行(basic/reach/target/hook),但每条的签名机制 |
| (投射屏反射、标签吞噬、带位延迟、双足印旋转…)仍需 B3 后续把它实现为效果类而非仅声明 | ||
M80-I05 |
RESOLVED(2026-09-15) | 320/320 行全部声明 §17 合法钩子 + 效果类(230 行关键词分类 + 90 行逐行点名; |
| 233 行落在模拟已实现的效果类,其余按未实现效果类登记,绝不猜);后续把未实现效果类逐类落地即可 | ||
M80-I10 |
OPEN((a)-(d) 均已落地,曲线仍偏易) | (b) 温和版已落地:Guard 吸收上限 35%/击、治疗每场限 2 次、消耗在选行时结算; |
| (a) 轻度版:第 7 回合起 +1 敌、第 10 回合起再 +1(上限队伍+2)。实测(1/8 区):时长 28-40 s → 后期 59 s, | ||
| 第 8 区后期生还 3.7/10、通关率 0.90;探针改为走容量/等级阶梯后 12/12 + Boss 击破(0 重试)。仍差目标: | ||
| 后期 60-90 s、通关率 0.4-0.7。下一杠杆:遭遇敌方总量再上调(队伍+3~+4)或敌人 rank HP 再乘系数;需实机试玩判断手感 | ||
M80-I10b |
DONE(记录) | (d) 回合间 HP 延续(有文档依据:§5"晋升保留 HP 百分比"、§9"MaxHP 变化保留 HP 百分比且不治疗")已进领域层 |
(ContractRun.apply_carry/carry_from/casualties)+ 桥读取 + 扫描使用;(c) 敌人 tempo/initiative +4。实测:第 1/8 区时长 28-34 s、 |
||
| 仍 100% 通关 → (d)+(c) 不足以拉开难度。剩余杠杆均为产品决策:(a) 敌方总量超容量;(b) 削弱满编职业组合的治疗/护卫/资源循环 | ||
M80-I10a |
DONE(记录) | 第一版加强已落地(敌人规模上限=队伍人数;rank HP 150/260/520→260/420/780、power 10/16/22→13/20/26): |
| 时长 20-27 s → 28-34 s,仍 100% 通关、几乎无伤亡。结论:满容量 12 职业队对同数敌人是碾压, | ||
| 继续加数值收益递减。需要 owner 定调的是产品选择:(a) 遭遇敌方总量显著超过我方容量(可读性风险); | ||
| (b) 削弱满编强度(职业/治疗/护卫的资源循环太强);(c) 提高敌方行动频率(tempo/initiative); | ||
(d) 合同层面加压(连续回合损耗、Market 后不自动回复)。测量方法已就绪:tools/m80_balance_sweep.gd -- <region> <from> <to> <attempts> |
||
M80-I10x |
SUPERSEDED | 修正夹具后实测:完整 12 职业队(容量 4→10 + 等级阶梯 + 装备 + 已启用条件行)对现遭遇 100% 通关、20-27 s、几乎无伤亡。 |
早期"曲线"作废——两处夹具缺陷已被抓出并修掉:(1) 桥按 recruit_id 匹配而扫描/探针夹具用 id → 整队退化为默认 PF-B01;桥已改为兼容匹配; |
||
| (2) 敌人属性固定 8(不随等级成长)→ 已改为按档位偏移 + 每级同斜率成长。下一步(数值工作):遭遇规模/档位/HP 总量按公司容量重排,战斗时长向 §13 的 90 s 区间靠拢 | ||
M80-I09 |
RESOLVED(2026-09-15) | §14.1 强制位移已落地:push/pull 相邻换位、Immovable 与边界阻挡、 |
被挡一次碰撞伤害 max(1, floor(0.08 * PhysicalPower))、footprint/rooted 字段已进演员行;门 ABG_M80_MOVEMENT_OK。 |
||
| 尚未实现:多足印整块移动、同时意图优先级仲裁(DESTINATION_RESERVED)、summon/return | ||
M80-I11 |
RESOLVED(2026-09-15) | 状态系统落地(§15 的施加/抵抗判定 + 目标选择器 ally_status/enemy_status + 动作字段 cleanse/extend_status/apply_hindered, |
已在 PF-B10 与 EN-R1-04/EN-R1-09 上接线):时钟逐 tick 递减、到期触发 on_status_expire 钩子、新增 status/status_expired/status_resisted 日志。 |
||
门 ABG_M80_STATUS_OK;优先条件 enabled 14→18(剩 5 个 PENDING 依赖召唤/设备/链接/蓄力) |
||
M80-I12 |
RESOLVED(2026-09-15) | 召唤/设备落地(§14.2):committed + 2 足印配额、越额拒绝记 NO_SUMMON_SPACE 且不消耗、 |
插入在源旁并重排位置、召唤钟到期移除并计入设备损失;deploy/summon_footprint/summon_ticks 动作字段接上 PF-B09 三行。 |
||
条件 enabled 18→21(剩 link_broken/enemy_major_windup);门 ABG_M80_SUMMON_OK |
||
M80-I13 |
RESOLVED(2026-09-15) | 蓄力/施法落地:windup 单位 ×4 tick(steady 0.8 s / slow 2.0 s,落在文档 0.3-4.0 s 通道带内)、 |
cast_start/cast_resolve/cast_cancelled(TARGET_FALLEN)、interrupt 取消记 AO_INTERRUPTED、目标选择器 active_cast、 |
||
条件 enemy_major_windup(major = ≥12 tick);门 ABG_M80_WINDUP_OK |
||
M80-I14 |
RESOLVED(2026-09-15) | 链接落地:link/relink 字段、link_id 绑定、link_broken 条件随绑定单位倒下而成立、PF-B08 三行可跑; |
门 ABG_M80_LINK_OK。至此 23 个优先条件全部 enabled(pending=0) |
||
M80-I24 |
RESOLVED(2026-09-16) | 装备效果类 ⑥ 传承(transfer):transfer 把携带池交给资源最低的幸存同伴 |
(资源为 0 时按护盾兜底);站点=行动完成(on_cast_complete)、资源获得(on_resource_gain)、倒下(on_fallen)。 |
||
4 行改点(EQ-237/265/274/282),implemented 252→256;新门 ABG_M80_TRANSFER_OK moved=12 received=11 |
||
(差额 1 = 第一条按设计走护盾兜底,非丢数据)。economy/planning 两类全部挂在 on_signature,无站点,继续 pending |
||
M80-I23 |
RESOLVED(2026-09-16) | 装备效果类 ⑤ 冷却(cooldown):cooldown_cut 退还准备度(value × tempo × 0.1, |
单位=十分之一秒);站点=行动完成(after_target/on_cast_complete)、前进(on_advance)、召唤成功(on_summon)、 |
||
蓄力被打断(on_interrupt)。9 行改点(EQ-015/016/018/070/190/200/214/260/286),implemented 243→252; |
||
新门 ABG_M80_COOLDOWN_OK plain=736 cooled=642(同一场仗快 13%)。EQ-078/276(on_signature)仍 pending |
||
M80-I21 |
RESOLVED(2026-09-16) | 装备效果类 ④ 目标规则(targeting):_target_rules() 读取已应用行的 rule, |
| EQ-025 平手改判(按作者线序取末位,替换随机掷)、EQ-030 原目标倒下后追其最近幸存邻居;新门 | ||
ABG_M80_TARGETING_OK tie=rearmost neighbour=continues;implemented 241→243 |
||
M80-I22 |
OPEN(2026-09-16) | 发现:战斗开始时会规范化位置,平手在日常战斗中不可达,因此 EQ-025 的决策改动目前只存在于决策函数层。 |
需要产品决策:要么让位置真能并列(如双足印/夹击占位),要么把这行改点成别的机制。targeting 类其余 11 行(EQ-029/031/088/172/199/217/248/254/256/259/275) |
||
仍 implemented: false,原因是它们需要尚不存在的窗口(施法前后重取目标、状态到期重取、敌人复制穿戴者目标规则) |
||
M80-I20 |
RESOLVED(2026-09-16) | 装备效果类 ③ 位移:movement 类落地——推/拉距离 + 前进后蓄势(momentum_bonus 下一次位移消耗) |
与命中后前压(after_damage);8 行改点(EQ-005/006/017/101/103/112/114/118),implemented 233→241; |
||
位移门新增断言 bonus=applied(带 movement_bonus 的推击实测多走一步)。EQ-317(after_collapse)维持未实现 |
||
M80-I19 |
RESOLVED(2026-09-16) | 钩子站点再补两个:on_critical(暴击为该次攻击加值)、on_barrier_break(护盾池被一次打空时回填)。 |
剩余未接站点均为无声明行的钩子(on_signature/on_summon/on_withdraw 等) |
||
M80-I18 |
RESOLVED(2026-09-16) | 钩子站点补齐:on_fallen / after_collapse(倒下时对幸存者结算并记 death_trigger)、 |
on_advance(被拉向阵前时触发)。§17 的 23 个钩子中,未接站点的只剩 on_signature/on_summon/on_withdraw/ |
||
on_critical/before_heal/on_barrier_break/on_resource_gain 等无声明行的钩子 |
||
M80-I17 |
RESOLVED(2026-09-16) | 敌人签名机制接入:钩子站点补 before_target(标记)与 on_protection_change(护屏),on_push 触发推击者的护盾; |
6 条区域 1 档案(EN-R1-03/05/06/07/12 等)从"声明"变为可触发;EN-R1-09 的 on_advance 如实退回未实现(其 action 已带妨碍)。 |
||
门 ABG_M80_ENEMY_ACTIONS_OK … signature_events=12 —— 签名在真实战斗中被观测到 |
||
M80-I16 |
RESOLVED(2026-09-16) | 装备效果类第二批:新增 减伤护屏(damage_reduction,在伤害预览里生效) |
与 节奏加成(tempo_bonus,施法行生效)两类;8 行从"声明类"改点到这两类;implemented 现在严格由 |
||
"核心是否应用该效果类"推导(不再依赖逐行标记);门 ABG_M80_EQUIPMENT_HOOKS_OK 保持绿 |
||
M80-I15 |
RESOLVED(2026-09-16) | 正式 attempt m80-battle-rules 通过:13 个战斗门 + 全流程 18 个 marker 各恰好一次,rc=0,证据已归档 |
M80-I03 |
OPEN | 职业优先级行的条件中有一批依赖 B3/B4 的系统(敌方预警/设备/链接/资源阈值);当前按“条件不成立”跳过,落地后逐行启用并补断言 |
M80-I08 |
RESOLVED(2026-09-15) | 两个真缺陷已修:(1) 桥的 _ally_row 合并短键 hp/tempo/initiative,模拟读 profession_base_* → 职业基础值从未生效; |
(2) kind: "guard" 的动作用了伤害路径(自伤且 Guard 池不恢复)→ self_guard_below_half 永真,角色整场循环 refresh_guard 不再攻击。 |
||
| 修复后合同探针 6→12/12 全清 + Boss 击破(4 次重试);平衡扫描重出(无断崖) | ||
M80-I08x |
RESOLVED(历史记录) | 装备数值不改变战斗:桥构建的友军行确实带上了装备数值(实测 wp=10 guard=8),但同一 seed/同一敌人下 |
item="" / EQ-002 / EQ-001 三种配置的 tick 完全相同(305)→ 模拟未按 §9/§15 消费 weapon_power/armor_guard(或消费路径与行字段不一致)。 |
||
| 复现脚本已在本轮记录;修复前所有平衡跑数(M80-I02/I07)无效 | ||
M80-I07 |
OPEN(曲线已校准) | I08 修复后按 §17 容量向量(4→10)重扫全区 8 区 ×12 回合 ×8 次: |
| 通关率 1.00(区1) → 0.33(区8 后段),时长 34→102 s(趋近文档 90 s 区间),生还 4.5→2.2;Boss 集合带 4 护卫后 | ||
| 第 8 区为最难战(38%)。仍需:Boss/精英顺序的人工试玩确认;时长区间逐区对齐 | ||
M80-I02 |
OPEN | 12 回合 × 16 合同的完整跑量平衡需在 B4 后用模拟批量跑数(经济/时长)复核 |