class_name BattleRefreshFlow extends RefCounted ## 换图刷新流程件(迭代 46 卡A T3/T4 自编排器拆出):刷新可用性门、折价扣费、换图执行与成功事实登记。 ## 拆分边界(需求卡片 C13):本件只负责可用性、扣费、换图与成功事实登记——七件效果的算法留在 ## 效果引擎、授予段与伤害控制器。调用路径=呈现层→编排器单行转发→RoundCycle.refresh_flow()→本件 ## →行动经济/装板壳/授予段(编排器入口与单行转发形态不变)。 ## 耦合边界(5.1 封装修复换代):去 static 改实例——构造收 RoundCycle 复制的引用束,断言 8 键 ## (facts/db/action_economy/fx_host/reward_economy/minesweeper/install_cb/grant_seg)解包同名成员; ## 变值标量(battle_result/round_index)走调用参数现值交付;授予段引用直接交换(段间引用, ## 不再穿编排器链式取段)——对编排器零引用。 ## 反自动刷新(C11):只经玩家入口发起,禁 RAP 满自动刷——编排器公开面单行转发,无自动调用点。 ## 成功序钉死(T4):折价扣 RAP→refresh_used+1→旧资源退役→旧板退役→装新板→授予段成功事实发射; ## 装板失败返回 false 且零效果——成功事实只在新板就位后发射。 ## 随编排器每战新建同灭(RoundCycle 持有)。 var facts: BattleFacts # 战斗事实件(refresh_used 受理计数) var db: ConfigDb var action_economy: ActionEconomy var fx_host: BattleFxHost # 效果宿主件(refresh_request 发射面) var reward_economy: RewardEconomy # 地图战斗资源(旧批退役面) var minesweeper: MinesweeperRules # 排雷玩法(旧板退役面) var install_cb: Callable # 宿主 _install_and_reset——装板受理薄壳(保留面) var grant_seg = null # GrantSegment 段间引用(成功事实发射——直接交接零链式) func _init(bundle: Dictionary) -> void: for k in ["facts", "db", "action_economy", "fx_host", "reward_economy", "minesweeper", "install_cb", "grant_seg"]: assert(bundle.has(k), "[换图刷新流程件] 引用束缺键: %s" % k) facts = bundle.facts db = bundle.db action_economy = bundle.action_economy fx_host = bundle.fx_host reward_economy = bundle.reward_economy minesweeper = bundle.minesweeper install_cb = bundle.install_cb grant_seg = bundle.grant_seg ## 折价成本读数(refresh_request 命中省力周转 apply_discount——只认 kind==apply_discount 且 ## mode==refresh,取声明序第一命中,floor(base×cost_mult/100);无命中=表基线逐位不变。 ## can_refresh 与 execute 同源取数〔V3——can 与执行同源判断〕;折扣只改变门槛与扣费, ## 不改变拒绝判据〔C2——每轮上限与相位判据照旧〕) func _effective_refresh_cost() -> int: var base := int(db.run.action_economy.rap_refresh_cost) for h in fx_host.fx_emit("refresh_request", {"mode": "refresh", "base": base}): if String(h.get("kind", "")) == "apply_discount" and String(h.get("mode", "")) == "refresh": return int(floor(float(base) * float(int(h.get("cost_mult", 100))) / 100.0)) return base ## 可用性门(HUD 刷新按钮同源判据):战斗未终局、每轮上限未满、Active 相位、RAP 抵折后价。 ## battle_result=调用参数现值交付。 func can_refresh(battle_result: String) -> bool: return battle_result == "" \ and facts.refresh_used < int(db.run.action_economy.refresh_cap_per_round) \ and action_economy.phase == action_economy.PHASE_ACTIVE \ and action_economy.rap >= _effective_refresh_cost() ## 执行(玩家请求刷新唯一通道体):扣费受理后继续;扣费拒绝/门拒零效果零事实。 ## battle_result/round_index=调用参数现值交付。 func execute(battle_result: String, round_index: int) -> bool: if not can_refresh(battle_result): return false if not action_economy.request_refresh(_effective_refresh_cost()): return false facts.refresh_used += 1 reward_economy.retire_mapping() # 旧图批次退役(地图战斗资源 Ready→retired;E6 新批重置前提) minesweeper.retire_board(true) # 旧板退役(轮内通道) if not bool(install_cb.call(true)): # 当场换图——失败即编排违例 fail-fast(零成功事实) return false grant_seg.apply_board_refreshed(round_index) # 成功事实:新板就位后一次发射 return true