class_name BattleRefreshFlow extends RefCounted ## 换图刷新流程件(迭代 46 卡A T3/T4 自编排器拆出):刷新可用性门、折价扣费、换图执行与成功事实登记。 ## 拆分边界(需求卡片 C13):本件只负责可用性、扣费、换图与成功事实登记——七件效果的算法留在 ## 效果引擎、授予段与伤害控制器。调用路径=呈现层→编排器单行转发→本件→行动经济/装板壳/授予段。 ## 反自动刷新(C11):只经玩家入口发起,禁 RAP 满自动刷——编排器公开面单行转发,无自动调用点。 ## 成功序钉死(T4):折价扣 RAP→refresh_used+1→旧资源退役→旧板退役→装新板→授予段成功事实发射; ## 装板失败返回 false 且零效果——成功事实只在新板就位后发射。 ## 折价成本读数(refresh_request 命中省力周转 apply_discount——只认 kind==apply_discount 且 ## mode==refresh,取声明序第一命中,floor(base×cost_mult/100);无命中=表基线逐位不变。 ## can_refresh 与 execute 同源取数〔V3——can 与执行同源判断〕;折扣只改变门槛与扣费, ## 不改变拒绝判据〔C2——每轮上限与相位判据照旧〕) static func _effective_refresh_cost(oc: BattleOrchestrator) -> int: var base := int(oc.db.run.action_economy.rap_refresh_cost) for h in oc.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 抵折后价。 static func can_refresh(oc: BattleOrchestrator) -> bool: return oc.battle_result == "" \ and oc._facts.refresh_used < int(oc.db.run.action_economy.refresh_cap_per_round) \ and oc.action_economy.phase == oc.action_economy.PHASE_ACTIVE \ and oc.action_economy.rap >= _effective_refresh_cost(oc) ## 执行(玩家请求刷新唯一通道体):扣费受理后继续;扣费拒绝/门拒零效果零事实。 static func execute(oc: BattleOrchestrator) -> bool: if not can_refresh(oc): return false if not oc.action_economy.request_refresh(_effective_refresh_cost(oc)): return false oc._facts.refresh_used += 1 oc._reward_economy.retire_mapping() # 旧图批次退役(地图战斗资源 Ready→retired;E6 新批重置前提) oc.minesweeper.retire_board(true) # 旧板退役(轮内通道) if not oc._install_and_reset(true): # 当场换图——失败即编排违例 fail-fast(零成功事实) return false oc._rounds._grant_seg.apply_board_refreshed(oc.round_index) # 成功事实:新板就位后一次发射 return true