From db65b73bc7d7020ae5edb49f276b00989bc68cca Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Sun, 4 Oct 2026 01:51:55 +0800 Subject: [PATCH] =?UTF-8?q?T4=E7=A9=BF=E5=88=BA=E6=B5=81+=E6=99=AE?= =?UTF-8?q?=E6=94=BB=E6=B5=81=E5=85=AB=E4=BB=B6=EF=BC=88=E8=BF=AD=E4=BB=A3?= =?UTF-8?q?12=E2=80=94=E2=80=94=E6=95=B4=E5=90=88=E5=AE=9A=E7=A8=BFS2/S3?= =?UTF-8?q?=EF=BC=89=EF=BC=9Arelics.tres=E5=A1=AB8=E8=A1=8C=EF=BC=88?= =?UTF-8?q?=E8=B4=AF=E7=A9=BF=E5=B0=84=E5=87=BBrarest=E9=94=9A=E7=82=B9?= =?UTF-8?q?=C2=B7=E5=87=BB=E6=9D=80=E5=BC=B9=E5=B0=84/=E8=BF=9E=E7=8F=A0?= =?UTF-8?q?=E7=9F=A2rare=C2=B7=E5=BC=80=E6=A0=BC=E8=8A=82=E5=A5=8F?= =?UTF-8?q?=E8=BD=AC=E6=AE=B5=E6=95=B0/=E7=8C=8E=E5=BC=B1=E6=9C=AC?= =?UTF-8?q?=E8=83=BDrare=C2=B7=E6=8A=98=E6=89=A3=E6=A1=A3=E5=89=8D?= =?UTF-8?q?=E7=A7=BB/=E7=8C=8E=E6=89=8B=E5=88=BA=E5=89=91common=C2=B7pierc?= =?UTF-8?q?e-vs-light+1=E2=80=94=E2=80=94=E5=AF=B9=E9=87=8D=E7=94=B2?= =?UTF-8?q?=E6=97=A0=E5=A2=9E=E7=9B=8A=E6=AD=A3=E8=B4=9F=E5=8F=8C=E4=BF=AE?= =?UTF-8?q?+=E7=9F=BF=E5=B7=A5=E7=9A=84=E6=89=A7=E6=8B=97common=C2=B7?= =?UTF-8?q?=E8=BD=AE=E5=86=85=E5=BC=80=E6=A0=BC=E6=95=B0=E8=BD=AC=E6=94=BB?= =?UTF-8?q?=E5=87=BB=E8=B8=A9=E9=9B=B7=E6=B8=85=E9=9B=B6/=E7=9F=BF?= =?UTF-8?q?=E5=B7=A5=E9=87=8D=E9=94=A4common=C2=B7=E5=91=BD=E4=B8=AD?= =?UTF-8?q?=E4=BA=A4=E6=8D=A2+25%=E5=AF=B9-2AC/=E4=B8=93=E6=B3=A8rare?= =?UTF-8?q?=C2=B7=E5=85=8D=E6=8E=B7=E9=AA=B0=E6=81=9275%=E6=96=B9=E5=B7=AE?= =?UTF-8?q?=E4=B9=B0=E6=96=AD/=E7=A2=8E=E7=94=B2=E9=9C=87=E5=87=BBrare?= =?UTF-8?q?=C2=B7=E5=91=BD=E4=B8=AD=E9=87=8D=E7=94=B2=E6=8E=88=E4=BA=88off?= =?UTF-8?q?=5Fguard=E5=A4=8D=E7=94=A8=E9=9B=B6=E6=96=B0=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E8=A1=8C=EF=BC=89=EF=BC=9Bdamage=5Fcontroller=E6=8E=B7?= =?UTF-8?q?=E9=AA=B0=E9=9D=A2=E5=9B=9B=E6=94=B9=E5=86=99=EF=BC=88=E9=87=8D?= =?UTF-8?q?=E9=94=A4threshold=E5=87=8F/=E4=B8=93=E6=B3=A8roll=E6=94=B9?= =?UTF-8?q?=E5=86=99roll=E8=AE=B00=E5=BD=92=E5=9B=A0/=E7=8C=8E=E5=BC=B1=5F?= =?UTF-8?q?discount=5Fshift=5Fup=E6=8A=98=E6=89=A3=E8=A1=A8=E5=90=91?= =?UTF-8?q?=E5=85=A8=E9=A2=9D=E7=A7=BB=E6=A1=A3/clamp=E6=89=A9pierce=5Fvs?= =?UTF-8?q?=5Flight=EF=BC=89+=E6=89=A7=E6=8B=97=E5=8A=A8=E6=80=81rider?= =?UTF-8?q?=EF=BC=88dig=5Fstreak=C3=97value=E4=B8=8A=E9=99=90cap=EF=BC=89+?= =?UTF-8?q?=E7=A2=8E=E7=94=B2apply=5Feffect+=E8=B4=AF=E7=A9=BF=E5=B0=84?= =?UTF-8?q?=E5=87=BB=E5=87=BB=E6=9D=80=E5=8D=8A=E9=A2=9D=E5=BC=B9=E5=B0=84?= =?UTF-8?q?=EF=BC=88B=E6=A8=A1=E5=BC=8F=E5=85=A5=E9=98=9F/A=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E9=80=92=E5=BD=92=E2=80=94=E2=80=94=E3=80=8C=E6=BA=A2?= =?UTF-8?q?=E5=87=BA=E8=BF=BD=E8=B8=AA=E3=80=8D=E5=8D=95=E5=88=86=E9=87=8F?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E4=B8=8D=E5=8F=AF=E8=A1=8C=E5=8D=8A=E9=A2=9D?= =?UTF-8?q?=E8=A3=81=E5=AE=9A=E6=8A=AB=E9=9C=B2=E5=BE=85=E8=BF=BD=E8=AE=A4?= =?UTF-8?q?=EF=BC=89=EF=BC=9Borchestrator=E6=9C=AC=E8=BD=AE=E6=89=AB?= =?UTF-8?q?=E9=9B=B7=E4=BA=8B=E5=AE=9E=E6=8E=A8=E5=AF=BC=EF=BC=88safe?= =?UTF-8?q?=E8=AE=A1=E6=95=B0/=E8=B8=A9=E9=9B=B7=E6=B8=85=E9=9B=B6?= =?UTF-8?q?=E2=80=94=E2=80=94=E6=89=A7=E6=8B=97=E8=BF=9E=E7=8F=A0=E7=9F=A2?= =?UTF-8?q?=E5=85=B1=E7=94=A8=E5=8F=96=E6=95=B0=E9=9D=A2=EF=BC=89+?= =?UTF-8?q?=E8=BF=9E=E7=8F=A0=E7=9F=A2=E6=AE=B5=E6=95=B0=E6=94=BB=E5=87=BB?= =?UTF-8?q?=E5=90=8E=E9=99=84=E5=8A=A0=E5=8D=95=EF=BC=88origin=3D=E8=8B=B1?= =?UTF-8?q?=E9=9B=84=E6=A0=BC=E2=80=94=E2=80=94(-1,-1)=E8=B6=8A=E7=95=8C?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E9=94=99=E8=AF=AF=E4=BA=8B=E6=95=85=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=95=99=E7=97=95=EF=BC=89=EF=BC=9B=E5=86=92=E7=83=9F?= =?UTF-8?q?+2=E6=96=AD=E8=A8=80=E8=A1=A8=E6=8D=A2=E4=BB=A316=E8=A1=8C?= =?UTF-8?q?=E2=86=92692/0=E4=B8=89=E9=97=B8+run=5Fall=E5=85=A8=E7=BB=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/core/battle_orchestrator.gd | 40 +++++++++++++++++ game/core/damage_controller.gd | 76 +++++++++++++++++++++++++++----- game/data/tables/relics.tres | 76 ++++++++++++++++++++++++++++++++ game/smoke/smoke_all.gd | 23 ++++++++-- 4 files changed, 201 insertions(+), 14 deletions(-) diff --git a/game/core/battle_orchestrator.gd b/game/core/battle_orchestrator.gd index d040dede..543a633a 100644 --- a/game/core/battle_orchestrator.gd +++ b/game/core/battle_orchestrator.gd @@ -111,6 +111,8 @@ func _relic_flags_for(relic_ids: Array) -> void: 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)) @@ -122,6 +124,23 @@ func _relic_flags_for(relic_ids: Array) -> void: 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)) var mt := int(tiers.get("magic", 0)) if mt >= 1: flags["rider_flat"] = int(flags.get("rider_flat", 0)) + 1 # 档一质变(≥2 件):rider +1(provisional) @@ -747,6 +766,17 @@ func _roll_round_actions() -> void: # 停开(B 模式下若 flush 中主角倒下,由控制器死亡事件终止余单——两模式同一结果)。 func _combat_segment(ri: int) -> void: + # 本轮扫雷事实推导(迭代 12 T4——执拗 streak/连珠矢段数共用取数面):本轮 safe 事件数= + # streak;踩雷即清零(mine_hit 监听同口——执拗「踩雷清零」承载)。攻击在战斗段=授予段后 + # 同一次 _settle 内,facts 已定。 + var round_safe := 0 + var round_mine := false + for evt in _facts_reveals: + if evt.kind == "safe": + round_safe += 1 + elif evt.kind == "mine": + round_mine = true + _damage.relic_flags["dig_streak"] = 0 if round_mine else round_safe # ⓪ 主角先手攻击(基础攻击恒存在——2026-09-11 用户裁决;先于敌方行动;授予段负向直伤致死 → 致电短路不先手)。 # 单分量伤害构成(2026-09-19 充能退役批·用户拍板):主角攻击 = 唯一基础分量(atk,吃掷点含暴击; # 类型 = 主角 attack_type 表值——2026-09-18 营地扩展前置批:量与类型抽象分离;查甲效矩阵对应行取克制修正)。 @@ -760,6 +790,16 @@ 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.relic_flags.get("chain_value", 0)) + if chain_value > 0: + var segments := mini(int(_damage.relic_flags.get("chain_cap", 2)), int(_damage.relic_flags.get("dig_streak", 0)) / 3) + for s in segments: + var ct := _damage.open_ticket(DamageController.KIND_BOARD_TYPED, "relic_chain_arrows", + "连珠矢", "board", chain_value, DamageController.TARGET_FRONT_ALIVE, ri, + minesweeper.hero_pos(), "pierce") + _damage.submit(ct) # 敌方行动(敌人技能池批——本拍动作开轮已摇定,此处按技能行兑现;行序 = 生成序)。 # 死亡即不动手:摇定后、兑现前死亡的敌不在存活序中——本拍技能作废,不 commit、不进冷却。 for u in _enemy_system.query_alive("enemy"): diff --git a/game/core/damage_controller.gd b/game/core/damage_controller.gd index 2db2e5e4..29b05326 100644 --- a/game/core/damage_controller.gd +++ b/game/core/damage_controller.gd @@ -198,14 +198,34 @@ func _resolve_hero_attack(t: Dictionary) -> void: var atk_type: String = String(t.attack_type) 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(relic_flags.get("hit_trade_hit", 0)) + 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(relic_flags.get("armor_roll_rewrite", 0)) + if rewrite > 0: + discount = rewrite + crit = false + roll_read["roll"] = 0 + # 猎弱本能(迭代 12 T4 穿刺流——对轻甲敌折扣档改善 value 档:对冲 pierce 列 L1 −1 开局罚; + # 改善 = 折扣表向全额方向移档,nat 最大面/已全额不重复) + var shift := int(relic_flags.get("discount_shift", 0)) + if shift > 0 and armor == "light" and discount < 100: + discount = _discount_shift_up(discount, shift) var cdelta: int = _counter_delta(atk_type, armor) + _relic_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 - var rolled: int = DamageMath.rolled_component(float(t.base_value), discount, crit, int(db.settlement.crit_multiplier), cdelta) + var base_value := float(t.base_value) + var trade_atk := int(relic_flags.get("hit_trade_atk", 0)) + if trade_atk > 0: + base_value *= 1.0 + float(trade_atk) / 100.0 # 重锤增伤面(交换的正向侧) + 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 # 分量键 = 实际攻击类型(归因字段,单分量模型) payload["roll"] = int(roll_read.roll) @@ -227,6 +247,11 @@ func _resolve_hero_attack(t: Dictionary) -> void: for eff in effects.query_active("enemy"): if String(eff.effect_id) == "weaken": hero_rider += nest_aura + # 矿工的执拗(迭代 12 T4 普攻流——「排雷排得多好,打得就有多疼」):本轮安全开格 streak + # 〔编排器授予段实时写入 relic_flags.dig_streak;踩雷清零〕×value,上限 cap。 + var rdig := int(relic_flags.get("round_dig_value", 0)) + if rdig > 0: + hero_rider += mini(int(relic_flags.get("round_dig_cap", 5)), int(relic_flags.get("dig_streak", 0)) * rdig) if hero_rider > 0: if crit and bool(relic_flags.get("rider_crit", false)): hero_rider = int(round(float(hero_rider) * float(db.settlement.crit_multiplier))) @@ -234,10 +259,29 @@ func _resolve_hero_attack(t: Dictionary) -> void: 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(relic_flags.get("crack_value", 0)) + if crack > 0 and armor == "heavy": + effects.apply_effect("off_guard", {"source_class": "relic_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(relic_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, "relic_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" @@ -355,20 +399,32 @@ func _counter_delta(attack_type: String, armor: String) -> int: return int(row.get(armor, 0)) -# 克制点直调(迭代 12 T2 魔法流 clamp_modifier 件——克制矩阵查表值后的流派件调整;空旗=0 零扰动): -# 魔网织者=magic vs magic(矩阵罚 −1 → 0/正——「对魔法护甲敌获得克制加成」);湛蓝誓约=magic vs -# heavy(+1 → +2——「对重甲敌所有魔法伤害克制点 +1」)。hero_attack 与 board_typed 两消费面同享。 +# 克制点直调(迭代 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 _relic_clamp_bonus(attack_type: String, armor: String) -> int: - if attack_type != "magic": - return 0 var bonus := 0 - if armor == "magic": - bonus += int(relic_flags.get("clamp_magic_magic", 0)) - elif armor == "heavy": - bonus += int(relic_flags.get("clamp_magic_heavy", 0)) + if attack_type == "magic": + if armor == "magic": + bonus += int(relic_flags.get("clamp_magic_magic", 0)) + elif armor == "heavy": + bonus += int(relic_flags.get("clamp_magic_heavy", 0)) + elif attack_type == "pierce": + if armor == "light": + bonus += int(relic_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 + var idx := tbl.find(discount) + if idx < 0: + return discount + return int(tbl[mini(tbl.size() - 1, idx + shift)]) + + # 淬毒刃纹 N(迭代 11 同调批 T5——战斗结算 begin_battle 注入;0 = 未装配零扰动) var attune_venom: int = 0 diff --git a/game/data/tables/relics.tres b/game/data/tables/relics.tres index 0c07a881..1f53600b 100644 --- a/game/data/tables/relics.tres +++ b/game/data/tables/relics.tres @@ -78,6 +78,82 @@ rows = [{ "effects": { "value": 2 } +}, { +"relic_id": "pierce_shot", +"display_name": "贯穿射击", +"rarity": "rarest", +"archetype": "pierce", +"hook": "kill_overflow", +"effects": { +"value": 1 +} +}, { +"relic_id": "chain_arrows", +"display_name": "连珠矢", +"rarity": "rare", +"archetype": "pierce", +"hook": "dig_count_segments", +"effects": { +"value": 2, +"cap": 2 +} +}, { +"relic_id": "weak_instinct", +"display_name": "猎弱本能", +"rarity": "rare", +"archetype": "pierce", +"hook": "roll_discount", +"effects": { +"value": 1 +} +}, { +"relic_id": "hunter_rapier", +"display_name": "猎手刺剑", +"rarity": "common", +"archetype": "pierce", +"hook": "clamp_modifier", +"effects": { +"value": 1, +"polarity": "pierce_vs_light" +} +}, { +"relic_id": "miner_stubborn", +"display_name": "矿工的执拗", +"rarity": "common", +"archetype": "normal", +"hook": "round_dig_bonus", +"effects": { +"value": 1, +"cap": 5 +} +}, { +"relic_id": "miner_hammer", +"display_name": "矿工重锤", +"rarity": "common", +"archetype": "normal", +"hook": "hit_trade", +"effects": { +"trade_atk": 25, +"trade_hit": 2 +} +}, { +"relic_id": "focus_mind", +"display_name": "专注", +"rarity": "rare", +"archetype": "normal", +"hook": "armor_roll_rewrite", +"effects": { +"value": 75 +} +}, { +"relic_id": "armor_crack", +"display_name": "碎甲震击", +"rarity": "rare", +"archetype": "normal", +"hook": "heavy_debuff", +"effects": { +"value": 25 +} }] ; 双层 BD 实施批(2026-10-04):机制件表——行 = 流派件定义 diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index e1d041ae..c5e53887 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -602,8 +602,8 @@ func _smoke_adventure() -> void: func _smoke_relics() -> void: print("--- 机制件基建(relic_table · 档位激活引擎 · 机制件带接线)---") - # ① 现行表牌库构成:T2 magic 四件+T3 flag 四件入池——98 数值令牌+8 relic 令牌(投放档 rare×6/rarest×2) - check(_db.relics != null and (_db.relics.rows as Array).size() == 8, "relic_table 已加载(T2 magic 4+T3 flag 4 在池——T4-T6 逐流派续填)") + # ① 现行表牌库构成:T2 magic 4+T3 flag 4+T4 pierce 4/normal 4 入池——98 数值令牌+16 relic 令牌 + check(_db.relics != null and (_db.relics.rows as Array).size() == 16, "relic_table 已加载(T2/T3/T4 四流派 16 件在池——T5/T6 续填)") var a_r0 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(71)) check(a_r0.start_adventure(71, {"first_script": true}), "机制件带场景:冒险启动(seed 71)") var relic_tokens := 0 @@ -613,8 +613,8 @@ func _smoke_relics() -> void: relic_tokens += 1 if String((t as Dictionary).get("tier", "")) == "rarest": rarest_tokens += 1 - check(relic_tokens == 8 and rarest_tokens == 2 and a_r0._bonus_deck.size() == 106, - "机制件带入池:8 件(rare 档 6 + rarest 锚点 2)——牌库 98+8=106") + check(relic_tokens == 16 and rarest_tokens == 3 and a_r0._bonus_deck.size() == 114, + "机制件带入池:16 件(rare 档 13 + rarest 锚点 3)——牌库 98+16=114") check(_db.relics.validate().is_empty(), "relic_table.validate 零违例(有行流派扫雷端铁律——magic first_dig_spell 在案)") # ② 档位激活引擎(纯函数直测——构造表 4 件 magic + 1 件 flag + 1 件 rarest 锚点) var rt := RelicTable.new() @@ -691,6 +691,21 @@ func _smoke_relics() -> void: check(int(rf8.get("flag_resource_extra", -1)) == 1 and int(rf8.get("nest_aura_value", -1)) == 1 and int(rf8.get("flag_all_hit_mult", -1)) == 2 and int(rf8.get("flag_strike_value", -1)) == 2, "标旗流求值:雷区图谱额外资源 1 · 猎巢人光环 +1/巢 · 完美布防 ×2 · 战旗军规旗伤 2(复用 board_typed 零新配方)") + # ⑥ T4 穿刺/普攻流求值面(全 16 件持有——四流派档位成型) + orch._relic_flags_for(["arcane_ember", "mana_weaver", "azure_oath", "mana_resonance", + "mine_atlas", "nest_hunter", "perfect_defense", "war_banner", + "pierce_shot", "chain_arrows", "weak_instinct", "hunter_rapier", + "miner_stubborn", "miner_hammer", "focus_mind", "armor_crack"]) + var rf16: Dictionary = orch._damage.relic_flags + check(bool(rf16.get("kill_overflow", false)) and int(rf16.get("chain_value", -1)) == 2 + and int(rf16.get("discount_shift", -1)) == 1 and int(rf16.get("clamp_pierce_light", -1)) == 1, + "穿刺流求值:贯穿射击弹射旗 · 连珠矢段值 2 上限 2 · 猎弱本能折扣改善 1 档 · 猎手刺剑 pierce-vs-light +1") + check(int(rf16.get("round_dig_value", -1)) == 1 and int(rf16.get("hit_trade_atk", -1)) == 25 + and int(rf16.get("hit_trade_hit", -1)) == 2 and int(rf16.get("armor_roll_rewrite", -1)) == 75 + and int(rf16.get("crack_value", -1)) == 25, + "普攻流求值:执拗 +1/格上限 5 · 重锤交换 +25%/−2AC · 专注恒 75% 免掷骰 · 碎甲震击 off_guard 授予旗") + check(bool(rf16.get("rider_crit", false)) and bool(rf16.get("rider_crit", false)), + "档位质变:magic/pierce/normal/flag 四流派档二(16 件混合——同标签 ≥4 判档二确定性)") var orch0 = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(74)) orch0._relic_flags_for([]) check((orch0._damage.relic_flags as Dictionary).is_empty(),