# VERTICAL SLICE - NOT FOR PRODUCTION # 结算行排播泵(迭代 8 卡⑦;T3 拆件批 2026-10-02 自 main.gd 整体迁出——规范 1.1 单一职责): # 演出层排播:逻辑先行零回压,行按段分组阶梯延迟进明细带。 # 硬契约:核心层零 await 不破——本队列只做信号的"后置消费",结算顺序/结果/时序逻辑零改动(§3 契约 1); # 减动效开=延迟归零走同帧直落快路(行呈现不跳过——§3 契约 5);模态开启前强制排空(明细回看/停点 # 覆盖层所见明细带恒完整——排空入口在组合根 _open_modal)。 # 装配纪律:视图句柄与呈现刷新回调由组合根注入(ADR-0001——本类零信号连接,仅做信号后置消费); # 行消费与卡⑦前逐位一致(_consume_row 原文迁入,语义零改动)。 extends Node const PACE_SEGMENT_GAP := 0.3 # 段间阶梯延迟(代拍板:白名单 0.2–0.4s 内取值,追认清单呈报) const PACE_ROW_GAP := 0.22 # 段内间隔(三轮 #3 上调 0.06→0.22——逐条演出可感知,配合数字浮现/状态脉冲) var _rows: Array = [] # 待排播行(step_row 载荷原样入队;__round_line 标记=轮首分隔行) var _pace_wait := 0.0 # 距下一行排播的剩余秒(_process 消耗) var _prev_segment := "" # 上一排播行的段型(段间/段内延迟判据) var _was_pumping := false # 排播活跃边沿(T17——末行消费帧触发结算视觉回挖掘态刷新) # 组合根注入面(_build_ui 装配——呈现句柄 + 演播完边沿的呈现刷新回调) var log_view: BattleLogView var stage: BattleStageView var board_zone: BoardZoneView var settlement_fx: SettlementFxView var board_view: BoardView var refresh_request := Callable() # () → 组合根 _refresh_presentations(行尾直呼/演播完边沿 call_deferred) var pump_ended := Callable() # () → 组合根锁期点击重放入口(T17 v3.1——演播完边沿 call_deferred;空回调安全) # 队列只读面(探针/测试经组合根委托属性读——共享同一 Array 引用,读数即实况) func pending_rows() -> Array: return _rows # 入队(常态路径——减动效关;step_row 载荷原样,零加工) func enqueue(row: Dictionary) -> void: _rows.append(row) # 同帧直落(减动效快路——延迟归零,行呈现不跳过;轮首分隔行减动效分支同用此口) func consume_now(row: Dictionary) -> void: _consume_row(row) # 段间延迟取数面(减动效双态断言用——开=0 归零,行不跳过;常态=段间/段内两档) func pace_delay_for(prev_seg: String, next_seg: String) -> float: if UiKit.motion_scale < 1.0: return 0.0 return PACE_SEGMENT_GAP if prev_seg != next_seg else PACE_ROW_GAP # 强制排空(模态开启前调用——明细回看/停点覆盖层/终局面所见明细带恒完整) func flush() -> void: while not _rows.is_empty(): _consume_row(_rows.pop_front()) _pace_wait = 0.0 _prev_segment = "" func _process(delta: float) -> void: # 排播泵(卡⑦——演出层帧驱动;队列空=零开销直返) if _rows.is_empty(): _pace_wait = 0.0 _prev_segment = "" if _was_pumping: # 演播完边沿:结算视觉期由排播队列承载(_is_settling 排播项),队列排空的翻转 # 无核心信号驱动——此处主动刷回挖掘态(去饱和解除/明细带收起/mode=dig)。 _was_pumping = false refresh_request.call_deferred() # 锁期点击重放(T17 v3.1——玩家操作零丢失):最后一次锁期点击延迟一帧重入 # _on_board_action(此刻队列已空=锁已解,正常受理;重放入口由组合根注入)。 if pump_ended.is_valid(): pump_ended.call_deferred() return _was_pumping = true _pace_wait -= delta if _pace_wait > 0.0: return var entry: Dictionary = _rows.pop_front() _consume_row(entry) var seg := String(entry.get("type", "")) _pace_wait = 0.0 if UiKit.motion_scale < 1.0 else (PACE_SEGMENT_GAP if seg != _prev_segment else PACE_ROW_GAP) _prev_segment = seg # 行消费(排播队列的出队步 / 减动效快路共用):明细带入带+演出链+呈现刷新——与卡⑦前排位逐位一致 func _consume_row(row: Dictionary) -> void: if row.has("__round_line"): log_view.finish_settlement_round() # 上轮摘要行(明细带 pattern 3)随轮首分隔行落带 log_view.append_bb("[color=#e0b860]── 第 %d 轮 ──[/color]" % int(row["__round_line"])) return log_view.append_row(row) stage.on_step_row_fx(row) _play_cross_zone_fx(row) # 跨区因果演出(结算演出链批):开格之因 → 站桩之果 _play_settlement_mark(row) # 三轮 #3——逐条标出:Buff/Debuff 色环脉冲 → 伤害/治疗数字浮现 # 高光演出(战斗结算×3①② 占位):完美排雷横幅 / 标中旗加重弹道 if String(row.get("type", "")) == "highlight": board_zone.fx.play_perfect_sweep() elif String(row.get("highlight", "")) == "flag_hit": board_zone.fx.play_flag_hit_projectile(true) refresh_request.call() # 逐条结算标出(三轮 #3——用户裁决按结算顺序演出:先 Buff/Debuff 特效、再基础伤害数字; # 打中谁标谁、主角被打标主角;道具/奖励行逐条冒出)。目标解析失败兜底棋盘中心。 func _play_settlement_mark(row: Dictionary) -> void: var mark_type := String(row.get("type", "")) if mark_type != "effect" and mark_type != "damage" and mark_type != "heal": return var target := String(row.get("target", "")) var center: Vector2 if target == "hero": center = stage.hero_standee_center() else: var v = stage.enemy_standee_center(target) if target != "" and target != "all_enemies" else null center = v if v != null else board_view.get_global_rect().get_center() match mark_type: "effect": var col: Color = Color("7cc47c") if int(row.get("value", 0)) > 0 else Color("c47c7c") settlement_fx.play_status_pulse(center, col) "damage": settlement_fx.play_damage_number(center, "-%d" % int(row.get("value", 0)), Color("d9402a"), bool(row.get("crit", false))) "heal": settlement_fx.play_damage_number(center, "+%d" % int(row.get("value", 0)), Color("7cc47c"), false) # 跨区因果演出(§Transitions 结算逐行兑现——动画密度终稿归战斗表现样张批): # 伤害行 → ⚔ 弹道自棋盘飞向目标敌方站桩(crit 金档加重);治疗行 → ✚ 弹道飞向主角站桩; # 命中反馈(闪白/血条递减/灰化)由站桩侧 on_step_row_fx/set_data 承接 func _play_cross_zone_fx(row: Dictionary) -> void: var from_v: Vector2 = board_view.get_global_rect().get_center() match String(row.get("type", "")): "damage": var target := String(row.get("target", "")) var crit := bool(row.get("crit", false)) if target == "" or target == "hero": # 主角受击弹道(迭代 6 T5 拆「敌→主角零反馈」早退):⚔ 危险红飞向主角站桩; # crit 只加重字号不加金(金=收益/胜利语义位,不用于敌方对主角输出) settlement_fx.play_projectile(from_v, stage.hero_standee_center(), "⚔", UiKit.RED_MINE, crit) return var to_v = stage.enemy_standee_center(target) if to_v != null: settlement_fx.play_projectile(from_v, to_v, "⚔", UiKit.GOLD if crit else UiKit.RED_MINE, crit) "heal": if String(row.get("target", "")) != "hero" and String(row.get("target", "")) != "": return settlement_fx.play_projectile(from_v, stage.hero_standee_center(), "✚", Color("7cc47c"))