iter10 T3-T9: 奖励重构实装——adventure表扩列(回血20/池六种/权重/上限/同调位过渡键)+boss_keystone重锚3-2+rng扩签reward_pick+E-S加权洗牌+三选一停点(零自动推进/可中断)+加算区四轴AP(BattleOrchestrator排队兑现)+钥石逐杀掉落(收束无二次派生)+同调位约束(停点替换两路/战斗沉没/节点拒绝)+BonusPickOverlay+Narrator文案族+save v3迁移+冒烟619/0(+23断言)+断点P5往返单测+run_all 15套全绿

This commit is contained in:
DKChan committed 2026-10-01 04:30:13 +08:00
1 parent 49b263fbc8
commit 71502ceecd
18 files changed
+992 -169

No files matched your search

+95 -10
View File
@@ -44,6 +44,8 @@ var confirm_dialog: ConfirmDialog # 通用确认弹窗(二轮修改批 A
var _settlement_stop_pending := false # 卡⑥ 战斗胜利总结结算框挂起态(确认「下一节点」后进选路页)
var _pending_candidates: Array = [] # 结算框挂起期的选路候选暂存(choices_presented 载荷)
var _last_gain_amount := 0 # 最近一笔钱包入账(卡⑥ GP 增量取数面——wallet_changed gain 载荷)
var _pending_bonus := {} # 三选一停点载荷暂存(迭代 10——战斗总结结算确认后开三选一面;续玩停点复用)
var bonus_overlay: BonusPickOverlay # 提升三选一覆盖层(迭代 10——level-clear.md v2 选择面承载)
var _start_overlay: Control
var _end_overlay: BattleEndOverlay
var _inter_overlay: Control
@@ -191,8 +193,15 @@ func _build_ui() -> void:
add_child(confirm_dialog)
confirm_dialog.confirmed.connect(_on_confirm_new_adventure)
confirm_dialog.cancelled.connect(_on_confirm_cancelled)
# 提升三选一覆盖层(迭代 10——z 序 = 节点层之上、终局层之下;确认后同拍推进)
bonus_overlay = BonusPickOverlay.new()
add_child(bonus_overlay)
bonus_overlay.pick_confirmed.connect(_on_bonus_pick_confirmed)
bonus_overlay.replace_chosen.connect(_on_bonus_replace_chosen)
bonus_overlay.continue_pressed.connect(_on_bonus_continue)
move_child(bonus_overlay, _end_overlay.get_index())
_modals = ModalStack.new()
for m: Control in [legend_overlay, review_overlay, node_overlay, level_screen, _end_overlay, shop_overlay, camp_overlay, tune_panel, settings_overlay, confirm_dialog]:
for m: Control in [legend_overlay, review_overlay, node_overlay, bonus_overlay, level_screen, _end_overlay, shop_overlay, camp_overlay, tune_panel, settings_overlay, confirm_dialog]:
_register_modal(m)
_tune_sim = TuneSimController.new(db, tune_panel, int(db.hero.max_hp))
@@ -329,7 +338,10 @@ func _wire_adventure() -> void:
adventure.node_entered.connect(_on_runner_node)
adventure.choices_presented.connect(_on_choices_presented)
adventure.wallet_changed.connect(_on_wallet_changed)
adventure.big_reward_paid.connect(_on_big_reward)
# 迭代 10 奖励重构批——big_reward_paid 退役,三选一信号族接线
adventure.bonus_choice_presented.connect(_on_bonus_presented)
adventure.bonus_resolved.connect(_on_bonus_resolved)
adventure.aux_replace_presented.connect(_on_aux_replace_presented)
adventure.adventure_finished.connect(_on_adventure_finished)
adventure.level_started.connect(_on_adventure_level_started)
adventure.set_save_manager(save_manager) # 断点承载注入(迭代 8 卡①——停点快照写盘;调试/模拟不经过此路径)
@@ -402,18 +414,87 @@ func _on_runner_node(node: Dictionary, info: Dictionary) -> void:
_refresh_presentations()
# ---- 冒险模式终局面(大奖励屏 / 冒险结算屏——冒险结构实现批)----
# ---- 冒险模式终局面(三选一选择面 / 冒险结算屏——迭代 10 奖励重构批)----
# 大奖励兑付(非末关通关恰一次):复用 _inter_overlay(label + 确认按钮,零新增交互范式);
# 文案装配归 Narrator
func _on_big_reward(reward: Dictionary) -> void:
if int(reward.get("aux_cleared", 0)) > 0:
board_zone.toast.show_toast("上关剩余 %d 件魔法道具已随关卡结束清空" % int(reward.get("aux_cleared", 0)), "info") # 迭代 7 T4 清空反馈
_inter_label.text = Narrator.big_reward_text(reward)
_inter_overlay.visible = true
# 三选一停点(非末关通关恰一次):Boss 胜利先经战斗总结结算面(settlement-summary v1.1——钥石
# 增量行在其上),确认后进三选一面(level-clear.md v2);续玩停点恢复同入口(零自动推进契约)
func _on_bonus_presented(payload: Dictionary) -> void:
if int(payload.get("aux_cleared", 0)) > 0:
board_zone.toast.show_toast("上关剩余 %d 件魔法道具已随关卡结束清空" % int(payload.get("aux_cleared", 0)), "info") # 迭代 7 T4 清空反馈
_pending_bonus = payload.duplicate(true)
if bool(payload.get("replace_pending", false)):
# 续玩:替换子交互在途中断——重建三选一面后直落替换子态(候选不重抽)
_show_bonus_pick()
return
_end_overlay.open_victory(Narrator.battle_end_text("victory", false), "继续",
board_view.get_global_rect(),
"%s\n%s" % [_gp_summary_text({"gp_dropped": _last_gain_amount}), Narrator.bonus_keystone_line(payload)])
_open_modal(_end_overlay)
_refresh_presentations()
# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 aux_replace_presented 续发直落子态)
func _show_bonus_pick() -> void:
var payload: Dictionary = _pending_bonus
_open_modal(bonus_overlay)
bonus_overlay.open_pick(Narrator.bonus_pick_header(payload), _bonus_card_texts(payload.get("candidates", []) as Array))
_refresh_presentations()
var _last_replace_items: Array = [] # 替换子态续玩重建缓存(aux_replace_presented 载荷)
var _last_replace_incoming := {} # 同上——incoming 记录
func _bonus_card_texts(candidates: Array) -> Array:
var out: Array = []
for id in candidates:
out.append({"id": String(id), "text": Narrator.bonus_card_text(String(id), int(db.adventure.bonus_value(String(id))))})
return out
func _on_bonus_pick_confirmed(item_id: String) -> void:
if adventure == null or not adventure.pick_bonus(item_id):
push_error("[组合根] 三选一兑付被拒——见输出日志")
func _on_aux_replace_presented(items: Array, incoming: Dictionary) -> void:
_last_replace_items = items.duplicate(true)
_last_replace_incoming = incoming.duplicate(true)
if not bonus_overlay.visible:
_open_modal(bonus_overlay) # 续玩替换在途直落——三选一面未开时先入栈(模态栈纪律)
_open_bonus_replace(items, incoming)
func _open_bonus_replace(items: Array, incoming: Dictionary) -> void:
var named: Array = []
for it in items:
var rec: Dictionary = it.duplicate()
rec["display_name"] = String(_item_name_lookup().get(String(rec.get("item_id", "")), String(rec.get("item_id", ""))))
named.append(rec)
bonus_overlay.open_replace(named, String(_item_name_lookup().get(String(incoming.get("item_id", "")), String(incoming.get("item_id", "")))),
named.size(), int(db.adventure.transitional_sync_slots))
func _on_bonus_replace_chosen(discard_index: int) -> void:
if adventure == null or not adventure.resolve_aux_replace(discard_index):
push_error("[组合根] 同调位替换受理被拒——见输出日志")
# 兑付反馈(bonus_resolved 到达——结果行上屏,唯一出口 = 继续)
func _on_bonus_resolved(result: Dictionary) -> void:
_pending_bonus = {}
bonus_overlay.show_result(Narrator.bonus_result_text(result))
_refresh_presentations()
# 继续钮:收三选一面 → 推进下一关(零自动推进——兑付后受理)
func _on_bonus_continue() -> void:
_close_modal(bonus_overlay)
bonus_overlay.close_pick()
if _adventure_mode and adventure != null:
if not adventure.continue_to_next_level():
_fatal_screen("关卡推进失败——见输出日志")
# 冒险结算(completed/failed/abandoned):复用 BattleEndOverlay——摘要五件事 + 钥石入账明细进文案
func _on_adventure_finished(summary: Dictionary) -> void:
_level_active = false
@@ -457,6 +538,10 @@ func _on_battle_end_continue() -> void:
# 终局出口:返回开始界面(冒险摘要留档试玩日志;钥石已在收束时入存档——存档序列化批)
_close_modal(_end_overlay)
_end_overlay.close()
# 迭代 10——三选一停点挂起分支:战斗总结结算(Boss 胜利钥石增量行)确认后进三选一面
if not _pending_bonus.is_empty():
_show_bonus_pick()
return
# 卡⑥ 挂起分派:战斗胜利总结结算框的「下一节点」≠ 终局——进选路页(暂存候选恢复呈现)
if _settlement_stop_pending:
_settlement_stop_pending = false