卡①T4c(拆件批wr5/wr9/V12): settlement 拆两子 Resource 段——新建 settlement_core_table.gd(7列:source_label_map/effect_pool_map/pool_clamp_lo/pool_clamp_hi/round_direction/p_perfect/seal_hit_premium)+damage_roll_table.gd(10列:equivalence_ref_damage/armor_effectiveness/roll_faces/attack_bonus/roll_tier_bounds/roll_tier_discounts/crit_roll/crit_multiplier/damage_floor/armor_roll_stream)+.uid边车;主表三列形(segment_order留主表+core+damage_roll,类变量18→3,const四枚随主表),validate拆五私有(_validate_scalars/_validate_roll_scalars(9分支超阈续拆)/_validate_frozen/_validate_tier_table/_validate_armor_matrix)错误载荷逐字同构+段缺失fail-fast;settlement.tres单文件嵌套重建(两sub_resource,18列值与尾注批注史逐字—脚本比对18/18无diff+tail_equal);消费方改址97处(.settlement.<列>→.settlement.core./damage_roll. 链式95处+cross_validator局部2处,逐规则计数断言全中;segment_order直读1处零改址);测试改址9文件含G15清单(sim/probe/config_db交叉校验)。验收:gdstyle基线外0 NEW+16套件924 PASS+零SCRIPT ERROR〔拆件批 V12〕

This commit is contained in:
DKChan committed 2026-10-27 07:41:09 +08:00
1 parent bc7a171e3d
commit e2a2fbf3ee
23 files changed
+221 -160

No files matched your search

@@ -79,12 +79,12 @@ func _run_recipe_sequence(db) -> Array:
for e in units.all_enemies():
enemy_hp_before.append(int(e.hp))
var front = units.default_target()
var threshold_expected: int = ctrl.defender_ac(front) + int(h.db.settlement.attack_bonus)
var threshold_expected: int = ctrl.defender_ac(front) + int(h.db.settlement.damage_roll.attack_bonus)
var atk_type := ""
var eff_keys: Array = h.db.settlement.armor_effectiveness.keys()
var eff_keys: Array = h.db.settlement.damage_roll.armor_effectiveness.keys()
if eff_keys.size() > 0:
atk_type = String(eff_keys[0])
var floor_v: int = int(h.db.settlement.damage_floor)
var floor_v: int = int(h.db.settlement.damage_roll.damage_floor)
var t1: int = ctrl.submit(ctrl.open_ticket(DamageControllerScript.KIND_HERO_ATTACK, "hero_attack",
"T1主角攻击", "战斗段", int(h.db.hero.atk), DamageControllerScript.TARGET_FRONT_ALIVE, 1))
@@ -123,9 +123,9 @@ func _run_recipe_sequence(db) -> Array:
var r1: Dictionary = _row_by_display_prefix("T1主角攻击")
var ex1: Dictionary = r1.get("extra", {})
Kit.check("主角攻击行 AC = 防守方 AC + 攻击加成(开单前快照一致)", int(ex1.get("ac", -1)) == threshold_expected)
Kit.check("掷点 ∈ [1, 骰面]", int(ex1.get("roll", -1)) >= 1 and int(ex1.get("roll", -1)) <= int(h.db.settlement.roll_faces))
Kit.check("掷点 ∈ [1, 骰面]", int(ex1.get("roll", -1)) >= 1 and int(ex1.get("roll", -1)) <= int(h.db.settlement.damage_roll.roll_faces))
var tier_ok := false
for dv in h.db.settlement.roll_tier_discounts:
for dv in h.db.settlement.damage_roll.roll_tier_discounts:
if int(dv) == int(ex1.get("tier", -1)):
tier_ok = true
if int(ex1.get("tier", -1)) == 100:
@@ -158,7 +158,7 @@ func _run_recipe_sequence(db) -> Array:
continue
if String(r.source_class).is_empty() or String(r.display).is_empty():
protocol_ok = false
if int(r.value) < int(h.db.settlement.damage_floor):
if int(r.value) < int(h.db.settlement.damage_roll.damage_floor):
protocol_ok = false
if not (r.extra is Dictionary) or not r.extra.has("target"):
protocol_ok = false
@@ -186,7 +186,7 @@ func _test_policy_immediate_mode(db) -> void:
if not h.spawn_ok:
return
h.ctrl.policy = DamageControllerScript.POLICY_IMMEDIATE
var floor_v: int = int(h.db.settlement.damage_floor)
var floor_v: int = int(h.db.settlement.damage_roll.damage_floor)
var t: int = h.ctrl.submit(h.ctrl.open_ticket(DamageControllerScript.KIND_BOARD_FLAT_HERO, "mine_hit",
"A模式反噬", "棋盘兑付", floor_v, DamageControllerScript.TARGET_HERO, 1))
Kit.check("A 模式开单即结(无 flush 即 redeemed)", h.ctrl.outcome(t) == "redeemed")
@@ -282,7 +282,7 @@ func _test_requires_gate_and_zero(db) -> void:
var h = _harness(db)
if not h.spawn_ok:
return
var floor_v: int = int(h.db.settlement.damage_floor)
var floor_v: int = int(h.db.settlement.damage_roll.damage_floor)
# 先清场(flush_submit 同步开单——清图批专用通道的契约面同时被覆盖)
var front_hp: int = int(h.units.query_alive("enemy")[0].max_hp)
var big: int = front_hp * 10
@@ -326,7 +326,7 @@ func _test_ac_merge(db) -> void:
return
var base_ac: int = int(h.db.hero.armor_class)
Kit.check("缺省兜底:defender_ac(hero) = hero 表值", h.ctrl.defender_ac(h.units.hero_unit()) == base_ac)
var override_v: int = base_ac + int(h.db.settlement.damage_floor)
var override_v: int = base_ac + int(h.db.settlement.damage_roll.damage_floor)
h.ctrl.set_hero_ac_override(override_v)
Kit.check("override 合流入参生效", h.ctrl.defender_ac(h.units.hero_unit()) == override_v)
# ac 型状态效果叠其上(找 hero 侧 unit=ac 行)
@@ -351,15 +351,15 @@ func _test_pool_clamp(db) -> void:
var h = _harness(db)
if not h.spawn_ok:
return
var lo: int = int(h.db.settlement.pool_clamp_lo)
var hi: int = int(h.db.settlement.pool_clamp_hi)
var lo: int = int(h.db.settlement.core.pool_clamp_lo)
var hi: int = int(h.db.settlement.core.pool_clamp_hi)
Kit.check("空效果池读 0(表 clamp 域含 0 前提)", h.ctrl.clamped_pool("hero_offense") == 0 and lo <= 0 and hi >= 0)
# 找 hero_offense 池的 percent 型 hero 侧效果行
var pool_eff := {}
for row in h.db.status_effects.rows:
var eid := String(row.get("effect_id", ""))
if String(row.get("unit", "")) == "percent" and String(row.get("target_side", "")) == "hero" \
and String(h.db.settlement.effect_pool_map.get(eid, "")) == "hero_offense":
and String(h.db.settlement.core.effect_pool_map.get(eid, "")) == "hero_offense":
pool_eff = row
break
if pool_eff.is_empty():
@@ -24,7 +24,7 @@ func _init() -> void:
func _floor_val() -> int:
return int(db.settlement.damage_floor)
return int(db.settlement.damage_roll.damage_floor)
# ---- F2 乘区:池内加算 → 池间乘算 → floor(单一取整规则)----
@@ -32,11 +32,11 @@ func _floor_val() -> int:
func _test_pool_damage() -> void:
var d := _floor_val() + 9 # 表值推导的任意正探针量(非玩法行值)
Kit.check("中性双池 (0,0) 原样透传", DamageMathScript.pool_damage(d, 0, 0) == d)
Kit.check("负敌方池压低不增高", DamageMathScript.pool_damage(d, 0, int(db.settlement.pool_clamp_lo)) <= d)
Kit.check("正·主角池抬升不低于原值", DamageMathScript.pool_damage(d, int(db.settlement.pool_clamp_hi), 0) >= d)
Kit.check("负敌方池压低不增高", DamageMathScript.pool_damage(d, 0, int(db.settlement.core.pool_clamp_lo)) <= d)
Kit.check("正·主角池抬升不低于原值", DamageMathScript.pool_damage(d, int(db.settlement.core.pool_clamp_hi), 0) >= d)
Kit.check("主角池单调不减(+50% vs +49% 探针档)", DamageMathScript.pool_damage(d, 50, 0) >= DamageMathScript.pool_damage(d, 49, 0))
Kit.check("对称性:池值互换结果不变(乘算交换)", DamageMathScript.pool_damage(d, 30, -20) == DamageMathScript.pool_damage(d, -20, 30))
Kit.check("输出非负(maxi(0,·) 封底)", DamageMathScript.pool_damage(d, int(db.settlement.pool_clamp_lo), int(db.settlement.pool_clamp_lo)) >= 0)
Kit.check("输出非负(maxi(0,·) 封底)", DamageMathScript.pool_damage(d, int(db.settlement.core.pool_clamp_lo), int(db.settlement.core.pool_clamp_lo)) >= 0)
# ---- 克制分量:空桶不吃修正恒 0;落地下限保底([1,+∞) 全来源)----
@@ -54,8 +54,8 @@ func _test_counter_component() -> void:
func _test_roll_discount_percent() -> void:
var threshold := 10 # 查档探针阈值(夹具值——档位参数本身全部来自表)
var bounds: Array = db.settlement.roll_tier_bounds
var discounts: Array = db.settlement.roll_tier_discounts
var bounds: Array = db.settlement.damage_roll.roll_tier_bounds
var discounts: Array = db.settlement.damage_roll.roll_tier_discounts
Kit.check("前置:档位数 = 边界数 + 1(查档契约——档数 = 边界数 + 1)", discounts.size() == bounds.size() + 1 and discounts.size() > 0)
Kit.check("掷点 ≥ 阈值恒全额 100", DamageMathScript.roll_discount_percent(threshold, threshold, bounds, discounts) == 100
and DamageMathScript.roll_discount_percent(threshold + 5, threshold, bounds, discounts) == 100)
@@ -78,7 +78,7 @@ func _test_roll_discount_percent() -> void:
func _test_rolled_component() -> void:
var base := float(_floor_val() + 7) # 表值推导探针基线
var crit_mult: int = int(db.settlement.crit_multiplier)
var crit_mult: int = int(db.settlement.damage_roll.crit_multiplier)
Kit.check("满额折扣无暴击 = floor(基线) + 修正 0", DamageMathScript.rolled_component(base, 100, false, crit_mult, 0) == int(floor(base)))
Kit.check("满额折扣暴击按表倍率放大", DamageMathScript.rolled_component(base, 100, true, crit_mult, 0) == int(floor(base * float(crit_mult) / 100.0)))
Kit.check("折扣降低不高于满额", DamageMathScript.rolled_component(base, 50, false, crit_mult, 0) <= DamageMathScript.rolled_component(base, 100, false, crit_mult, 0))
@@ -0,0 +1 @@
uid://ehnthaqk7h12
@@ -109,7 +109,7 @@ func _smoke_armor_roll() -> void:
var dist := {100: 0, 75: 0, 50: 0, 25: 0}
var tier_ok := true
for roll in range(1, 21):
var d: int = DamageMath.roll_discount_percent(roll, cfg.ac, _db.settlement.roll_tier_bounds, _db.settlement.roll_tier_discounts)
var d: int = DamageMath.roll_discount_percent(roll, cfg.ac, _db.settlement.damage_roll.roll_tier_bounds, _db.settlement.damage_roll.roll_tier_discounts)
if not dist.has(d):
tier_ok = false
continue
@@ -117,7 +117,7 @@ func _smoke_armor_roll() -> void:
Kit.check("查档 AC%d 全掷点域分布(100/75/50/25 = %s)" % [cfg.ac, str([dist[100], dist[75], dist[50], dist[25]])], tier_ok and dist == cfg.expect)
var ev_sum := 0
for roll in range(1, 21):
ev_sum += DamageMath.roll_discount_percent(roll, 10, _db.settlement.roll_tier_bounds, _db.settlement.roll_tier_discounts)
ev_sum += DamageMath.roll_discount_percent(roll, 10, _db.settlement.damage_roll.roll_tier_bounds, _db.settlement.damage_roll.roll_tier_discounts)
Kit.check("AC10 EV 锚:期望系数合计 %d/2000 = 期望减免 21.25%%(nat20 恒全额含内)" % ev_sum, ev_sum == 1575)
# ② nat20 暴击(行为面):探针按行为面扫描
# 「主角先手首掷 = 20」的种子,不假设 armor_roll scope0 位
@@ -125,12 +125,12 @@ func _smoke_armor_roll() -> void:
var crit_rows := {}
for s in range(1, 800):
crit_rows = _first_hero_attack_rows(s)
if int(crit_rows.get("roll", -1)) == int(_db.settlement.crit_roll):
if int(crit_rows.get("roll", -1)) == int(_db.settlement.damage_roll.crit_roll):
crit_seed = s
break
Kit.check("nat20 种子可达(seed=%d——主角先手首掷命中 %d)" % [crit_seed, int(_db.settlement.crit_roll)], crit_seed > 0)
Kit.check("nat20 种子可达(seed=%d——主角先手首掷命中 %d)" % [crit_seed, int(_db.settlement.damage_roll.crit_roll)], crit_seed > 0)
Kit.check("nat20 → 行留档 roll=20 + crit 标记(主角先手普通分量)",
int(crit_rows.get("roll", -1)) == int(_db.settlement.crit_roll) and bool(crit_rows.get("crit", false)))
int(crit_rows.get("roll", -1)) == int(_db.settlement.damage_roll.crit_roll) and bool(crit_rows.get("crit", false)))
Kit.check("nat20 → 普通分量 ×2(%d = 2×%d,暴击倍率只乘该分量,穿刺/魔法不吃)" % [int(crit_rows.get("normal", -1)), int(_db.hero.atk)],
int(crit_rows.get("normal", -1)) == 2 * int(_db.hero.atk) and int(crit_rows.get("value", -1)) == 2 * int(_db.hero.atk))
# ③ 削弱续时(行为面):授予→衰减一轮→再授予 → 层数保持 1、剩余结算数重置
@@ -172,7 +172,7 @@ func _smoke_armor_roll() -> void:
Kit.check("棋盘来源伤害行零掷点字段(爆裂/直伤/清障炸药/奖励即时必中全额)", board_ok)
# ⑥ 全来源伤害下限(任何伤害落地取值域 [1,+∞) 无上限——棋盘克制直伤/反噬/地形变异/爆裂
# 全部收在 damage_floor 闸内)
var df: int = int(_db.settlement.damage_floor)
var df: int = int(_db.settlement.damage_roll.damage_floor)
Kit.check("棋盘克制直伤贴底 → 下限 1(点数 2 vs 不利修正 −1)", DamageMath.counter_component(2, -1, df) == 1)
Kit.check("克制修正触底穿透 → 下限 1(点数 1 vs 修正 −3)", DamageMath.counter_component(1, -3, df) == 1)
Kit.check("空桶不吃修正恒 0(零点数分量无伤害可落地——边界不变不受下限影响)", DamageMath.counter_component(0, 5, df) == 0)
@@ -351,7 +351,7 @@ func _smoke_damage_types() -> void:
Kit.check("ogre_chief 护甲 = light(Boss 行集——护甲类型重配批 2026-09-18:关卡 1 全轻甲)",
enemy_system_c.spawn(1, 4, int(_db.hero.max_hp), [], -1, -1, [], "", "boss") and String(enemy_system_c.all_enemies()[0].armor_type) == "light")
# ② 克制矩阵表值在位(三档点数 克制 +1 / 中性 0 / 被克 −1,加法核非 percent)
var am: Dictionary = _db.settlement.armor_effectiveness
var am: Dictionary = _db.settlement.damage_roll.armor_effectiveness
Kit.check("普通行:轻甲 0 / 魔法护甲 +1 / 重甲 −1(加法核)",
int(am.normal.light) == 0 and int(am.normal.ward) == 1 and int(am.normal.heavy) == -1)
Kit.check("穿刺行:轻甲 −1 / 魔法护甲 +1 / 重甲 0 中性(用户拍板)",
@@ -452,9 +452,9 @@ func _smoke_attack_chain_fresh_pool() -> void:
Kit.check("非施放攻击拍采样充足(%d 拍——增益施放行零兑付为设计语义不计)" % ticks.size(), ticks.size() >= 2)
var all_full := true
for t in ticks:
var base_factor: float = float(t.tier) * (float(_db.settlement.crit_multiplier) / 100.0 if t.crit else 1.0)
var base_factor: float = float(t.tier) * (float(_db.settlement.damage_roll.crit_multiplier) / 100.0 if t.crit else 1.0)
var rolled_base := int(floor(float(t.baseline) * base_factor / 100.0))
var expected: int = maxi(int(_db.settlement.damage_floor), rolled_base + int(t.get("attach", 0)))
var expected: int = maxi(int(_db.settlement.damage_roll.damage_floor), rolled_base + int(t.get("attach", 0)))
if int(t.tick) != expected or int(t.tick) <= 0:
all_full = false
Kit.check("fresh 池非蓄力拍 d_tick = max(1, 掷点档位基线)(Boss 攻击链健康——Bug#2 回归断言)", all_full)
@@ -667,8 +667,8 @@ func _smoke_skill_pool_data() -> void:
Kit.check("蓄力状态行 empower(enemy +100 percent——敌方输出 ×2 走既有 enemy_output 池)", not empower.is_empty() and String(empower.target_side) == "enemy" and int(empower.magnitude) == 100)
Kit.check("硬化状态行 fortify(enemy −50 percent——敌方防御池负值 = 主角攻击折半;+100 符号 bug 2026-09-18 纠正,provisional 归 状态层重设计批)", not fortify.is_empty() and String(fortify.target_side) == "enemy" and int(fortify.magnitude) == -50)
Kit.check("effect_pool_map 收编 empower/fortify(敌方防御池 enemy_defense 入表)",
String(_db.settlement.effect_pool_map.get("empower", "")) == "enemy_output" \
and String(_db.settlement.effect_pool_map.get("fortify", "")) == "enemy_defense")
String(_db.settlement.core.effect_pool_map.get("empower", "")) == "enemy_output" \
and String(_db.settlement.core.effect_pool_map.get("fortify", "")) == "enemy_defense")
# ② 同种子回放逐位复现(D3 大地精,多实例同种)
@@ -900,7 +900,7 @@ func _smoke_debuff_rider() -> void:
var snare_seed := -1
var base_ac: int = int(_db.hero.armor_class)
var off_m: int = int(_db.status_effect_row("off_guard").magnitude)
var floor_v: int = int(_db.settlement.damage_floor)
var floor_v: int = int(_db.settlement.damage_roll.damage_floor)
for s in range(1, 401):
if venom_seed > 0 and snare_seed > 0:
break
@@ -932,7 +932,7 @@ func _smoke_debuff_rider() -> void:
if rider_v != maxi(floor_v, int(floor(float(boss_atk) * 0.75))):
venom_check_ok = false
# 终值精确复算(停手轮池恒空):主分量链结果 + 必中附加后置
var base_factor: float = float(int(row.tier)) * (float(_db.settlement.crit_multiplier) / 100.0 if bool(row.get("crit", false)) else 1.0)
var base_factor: float = float(int(row.tier)) * (float(_db.settlement.damage_roll.crit_multiplier) / 100.0 if bool(row.get("crit", false)) else 1.0)
var rolled_main: int = int(floor(float(int(row.baseline)) * base_factor / 100.0))
var expected: int = maxi(floor_v, rolled_main + int(row.get("attach", 0))) + rider_v
if int(row.value) != expected:
@@ -494,7 +494,7 @@ func _smoke_polarity_routing() -> void:
# δ 读 settlement.seal_hit_premium(125 provisional);九型正向行值全固定(唯一区间行 clear_blast
# 系清图槽不入格池)⇒ 逐型期望全确定。整数量级四舍五入域注记:ac_up/action 1 点量纲取整后不变
# =整数粒度地板——等号压线判读在当量聚合面(audit 工具/registry clause3_inequality),非断言面。
var prem_pct: int = int(_db.settlement.seal_hit_premium)
var prem_pct: int = int(_db.settlement.core.seal_hit_premium)
Kit.check("封印溢价配置在位(seal_hit_premium=125 provisional——形态 a 兑付溢价)", prem_pct == 125)
var prem_rows := 0
var prem_ok := true
@@ -676,7 +676,7 @@ func _smoke_negative_dictionary() -> void:
not sapped.is_empty() and String(sapped.get("target_side", "")) == "hero" \
and int(sapped.get("magnitude", 0)) == -25 and int(sapped.get("duration_settlements", 0)) == 1 \
and int(sapped.get("max_stack", 0)) == 16 and String(sapped.get("stack_policy", "")) == "stack")
Kit.check("effect_pool_map 收编 sapped → hero_offense(attack_up 镜像池)", String(_db.settlement.effect_pool_map.get("sapped", "")) == "hero_offense")
Kit.check("effect_pool_map 收编 sapped → hero_offense(attack_up 镜像池)", String(_db.settlement.core.effect_pool_map.get("sapped", "")) == "hero_offense")
# 行为面:逐型负向兑付形态(真实板 + 真实路由路径)
# heal 权重低(无 heal 板概率 ≈1/3)——单板五型齐备不再必然:
# 本断言多板扫描,取第一块五型齐备的板做行为断言。
@@ -60,7 +60,7 @@ func _test_damage_controller_vocabularies() -> void:
# ---- D2↔B1:掷点用途标签 ∈ RngService 封闭词表(EC12——跨系统字面量契约的成员性断言) ----
func _test_rng_tag_closure(db) -> void:
var stream_label: String = String(db.settlement.armor_roll_stream)
var stream_label: String = String(db.settlement.damage_roll.armor_roll_stream)
Kit.check("settlement.armor_roll_stream ∈ RngService 封闭标签词表(EC12)",
RngServiceScript.PURPOSE_TAGS.has(stream_label))
Kit.check("RngService 用途标签词表非空且互异(封闭语义由流改标签)",
@@ -282,25 +282,25 @@ func _smoke_ac_swap_guard() -> void:
Kit.check("奖励表 defense 正向行 effect_id = ac_up(显示名盾牌加护,权重/tier 不变)",
String(ac_reward.get("effect_id", "")) == "ac_up" and String(ac_reward.get("display_name", "")) == "盾牌加护")
Kit.check("effect_pool_map 无 defense_up/ac_up 键(减伤不入池——AC 不经乘区)",
not _db.settlement.effect_pool_map.has("defense_up") and not _db.settlement.effect_pool_map.has("ac_up"))
not _db.settlement.core.effect_pool_map.has("defense_up") and not _db.settlement.core.effect_pool_map.has("ac_up"))
# ② 免伤墙归零护栏(泛化——BUG-0003 免疫)
var wall_ok := true
var wall_detail := ""
for eff_id in _db.settlement.effect_pool_map.keys():
if String(_db.settlement.effect_pool_map[eff_id]) != "hero_defense":
for eff_id in _db.settlement.core.effect_pool_map.keys():
if String(_db.settlement.core.effect_pool_map[eff_id]) != "hero_defense":
continue
var row: Dictionary = _db.status_effect_row(eff_id)
if row.is_empty() or String(row.get("unit", "")) != "percent":
continue
var floor_v: int = int(row.get("magnitude", 0)) * int(row.get("max_stack", 1))
if floor_v <= int(_db.settlement.pool_clamp_lo):
if floor_v <= int(_db.settlement.core.pool_clamp_lo):
wall_ok = false
wall_detail += " %s(%d)" % [eff_id, floor_v]
Kit.check("hero_defense 池 percent 行叠满不可触池底(墙最深%s > clamp_lo %d——单效果归零结构性不可达)" % [
wall_detail if wall_detail != "" else "(池内现无负向行)", int(_db.settlement.pool_clamp_lo)], wall_ok)
wall_detail if wall_detail != "" else "(池内现无负向行)", int(_db.settlement.core.pool_clamp_lo)], wall_ok)
var hd_maps := 0
for eff_id in _db.settlement.effect_pool_map.keys():
if String(_db.settlement.effect_pool_map[eff_id]) == "hero_defense":
for eff_id in _db.settlement.core.effect_pool_map.keys():
if String(_db.settlement.core.effect_pool_map[eff_id]) == "hero_defense":
hd_maps += 1
Kit.check("hero_defense 池映射数==0(绊线钉——红=已加映射,去核上方护栏是否已同步激活)", hd_maps == 0)
# ③ 单位表 armor_class:域内校验(配置推导——正式投值归怪物/难度批,改表不断锚)
@@ -370,12 +370,12 @@ func _smoke_ac_swap_guard() -> void:
Kit.check("第一关相邻深度带总量比 ≤ 2.5(12/10/22/35/72——迭代 24 N1 曲线护栏,带键升序;越带%s)" % [
curve_detail if curve_detail != "" else "无"], curve_ok)
# ④ 掷点参数域(加载校验已过——此处钉形状语义)
var bounds: Array = _db.settlement.roll_tier_bounds
var discounts: Array = _db.settlement.roll_tier_discounts
var bounds: Array = _db.settlement.damage_roll.roll_tier_bounds
var discounts: Array = _db.settlement.damage_roll.roll_tier_discounts
Kit.check("掷点参数拍板值在位(d20 / nat20 暴击 ×200%% / 下限 1 / attack_bonus 0 / armor_roll 流)",
int(_db.settlement.roll_faces) == 20 and int(_db.settlement.crit_roll) == 20 \
and int(_db.settlement.crit_multiplier) == 200 and int(_db.settlement.damage_floor) == 1 \
and int(_db.settlement.attack_bonus) == 0 and String(_db.settlement.armor_roll_stream) == "armor_roll")
int(_db.settlement.damage_roll.roll_faces) == 20 and int(_db.settlement.damage_roll.crit_roll) == 20 \
and int(_db.settlement.damage_roll.crit_multiplier) == 200 and int(_db.settlement.damage_roll.damage_floor) == 1 \
and int(_db.settlement.damage_roll.attack_bonus) == 0 and String(_db.settlement.damage_roll.armor_roll_stream) == "armor_roll")
Kit.check("档位表拍板值在位(缺口 1-3 → ×0.75 · 4-7 → ×0.5 · 8+ → ×0.25——无零档)",
bounds == [3, 7] and discounts == [75, 50, 25])
@@ -96,7 +96,7 @@ func _sweep_source_names() -> void:
row_view._tip_label.text.contains("来源:危险格"))
row_view._hide_tip()
Kit.check("结算表 source_label_map[mine_hit]==「危险格」(u6 换代——ConfigDB 真装载)〔wa7〕",
String(_db.settlement.source_label_map.get("mine_hit", "")) == "危险格")
String(_db.settlement.core.source_label_map.get("mine_hit", "")) == "危险格")
var log_view = load("res://presentation/views/battle_log_view.gd").new(_db)
var row_txt := String(log_view._format_row({"type": "effect", "source_class": "mine_hit",
"display_name": "挖掘反噬", "value": -5, "pool_value": -5, "round_index": 1}))