卡①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:
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}))
|
||||
|
||||
Reference in new issue
Block a user