From b4f3b28ef3144a26334f738073de4fef3fbe2828 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Thu, 18 Jun 2026 23:08:58 +0900 Subject: [PATCH] Show next camp preview in results --- scripts/scenes/battle_scene.gd | 73 +++++++++++++++++++++++++++++++++- tools/smoke_result_summary.gd | 27 ++++++++++++- 2 files changed, 97 insertions(+), 3 deletions(-) diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index c5e1733..7f415e6 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -3222,8 +3222,7 @@ func _update_result_panel() -> void: _rebuild_result_choices() if result_restart_button != null: result_restart_button.visible = true - if next_battle_button != null: - next_battle_button.visible = not str(battle_result_summary.get("next_scenario_id", "")).is_empty() and bool(battle_result_summary.get("choice_applied", true)) and bool(battle_result_summary.get("saved", false)) + _update_result_next_button_visibility() result_label.text = "Victory\n%s\n%s" % [ state.objectives.get("victory", ""), _format_battle_result_summary() @@ -5656,6 +5655,12 @@ func _on_post_battle_choice_pressed(choice: Dictionary) -> void: _play_ui_cancel() _on_log_added("Could not save campaign choice.") _rebuild_result_choices() + _update_result_next_button_visibility() + if result_label != null and state.battle_status == BattleState.STATUS_VICTORY: + result_label.text = "Victory\n%s\n%s" % [ + state.objectives.get("victory", ""), + _format_battle_result_summary() + ] _update_hud() @@ -5701,6 +5706,9 @@ func _format_battle_result_summary() -> String: ] if not already_next.is_empty(): replay_lines.append("Next\n %s" % already_next) + var replay_preview := _format_next_camp_preview_text(str(battle_result_summary.get("next_scenario_id", ""))) + if not replay_preview.is_empty(): + replay_lines.append("Next Camp\n %s" % replay_preview) return _join_strings(replay_lines, "\n") var items: Array = battle_result_summary.get("items", []) @@ -5745,9 +5753,70 @@ func _format_battle_result_summary() -> String: sections.append("Choice\n Select a campaign response.") elif not str(battle_result_summary.get("choice_label", "")).is_empty(): sections.append("Choice\n %s" % str(battle_result_summary.get("choice_label", ""))) + var next_preview := _format_next_camp_preview_text(str(battle_result_summary.get("next_scenario_id", ""))) + if not next_preview.is_empty() and bool(battle_result_summary.get("saved", false)): + sections.append("Next Camp\n %s" % next_preview) return _join_strings(sections, "\n") +func _update_result_next_button_visibility() -> void: + if next_battle_button == null: + return + next_battle_button.visible = ( + not str(battle_result_summary.get("next_scenario_id", "")).is_empty() + and bool(battle_result_summary.get("choice_applied", true)) + and bool(battle_result_summary.get("saved", false)) + ) + + +func _format_next_camp_preview_text(next_scenario_id: String) -> String: + var scenario_id := next_scenario_id.strip_edges() + if scenario_id.is_empty(): + return "" + var scenario_path := campaign_state.get_scenario_path(scenario_id) + if scenario_path.is_empty(): + return "" + var preview_state := BattleStateScript.new() + if not preview_state.load_battle( + scenario_path, + campaign_state.get_roster_overrides(), + campaign_state.get_inventory_snapshot(), + campaign_state.get_flags_snapshot(), + campaign_state.get_joined_officers_snapshot() + ): + return "" + var parts := [] + var briefing := preview_state.get_briefing() + var location := str(briefing.get("location", "")).strip_edges() + if not location.is_empty(): + parts.append(location) + var talk_count := _briefing_camp_conversation_count(briefing) + if talk_count > 0: + parts.append("Talk %d" % talk_count) + var shop_count := preview_state.get_shop_item_ids().size() + if shop_count > 0: + parts.append("Shop %d goods" % shop_count) + if preview_state.has_deployment_roster(): + parts.append("Deploy %d/%d" % [ + preview_state.get_deployed_player_count(), + preview_state.get_deployment_max_units() + ]) + var formation_count := preview_state.get_formation_cells().size() + if formation_count > 0: + parts.append("Formation %d tiles" % formation_count) + return _join_strings(parts, " | ") + + +func _briefing_camp_conversation_count(briefing: Dictionary) -> int: + var conversations = briefing.get("camp_conversations", []) + if typeof(conversations) == TYPE_ARRAY and not conversations.is_empty(): + return conversations.size() + var lines = briefing.get("camp_dialogue", []) + if typeof(lines) == TYPE_ARRAY and not lines.is_empty(): + return 1 + return 0 + + func _format_progression_events(events) -> String: if typeof(events) != TYPE_ARRAY: return "" diff --git a/tools/smoke_result_summary.gd b/tools/smoke_result_summary.gd index ffc7286..fe3a43c 100644 --- a/tools/smoke_result_summary.gd +++ b/tools/smoke_result_summary.gd @@ -10,6 +10,11 @@ func _init() -> void: push_error("Could not load smoke scenario.") quit(1) return + if not scene.campaign_state.load_campaign("res://data/campaign/campaign.json"): + push_error("Could not load smoke campaign.") + quit(1) + return + scene.campaign_state.start_new("001_yellow_turbans") scene.campaign_state.gold = 320 scene.battle_result_summary = { @@ -24,6 +29,7 @@ func _init() -> void: "progression_events": [ {"type": "level_up", "name": "Cao Cao", "to_level": 2} ], + "next_scenario_id": "002_sishui_gate", "next_scenario_title": "Sishui Gate", "choice_applied": true, "choice_label": "" @@ -35,6 +41,11 @@ func _init() -> void: _check_contains(failures, "roster section", result_text, "Joined: Dian Wei") _check_contains(failures, "growth section", result_text, "Cao Cao Lv.2") _check_contains(failures, "campaign section", result_text, "Next: Sishui Gate") + _check_contains(failures, "next camp section", result_text, "Next Camp") + _check_contains(failures, "next camp location", result_text, "Sishui Gate, 190 CE") + _check_contains(failures, "next camp shop", result_text, "Shop 6 goods") + _check_contains(failures, "next camp deploy", result_text, "Deploy 2/3") + _check_contains(failures, "next camp formation", result_text, "Formation 6 tiles") scene.battle_result_summary = { "saved": false, @@ -57,14 +68,22 @@ func _init() -> void: scene.battle_result_summary = { "saved": true, "pending_choice": true, + "next_scenario_id": "002_sishui_gate", "next_scenario_title": "Qingzhou Campaign" } + var pending_choice_text := scene._format_battle_result_summary() _check_contains( failures, "pending choice prompt", - scene._format_battle_result_summary(), + pending_choice_text, "Select a campaign response" ) + _check_not_contains( + failures, + "pending choice should wait for response before next camp preview", + pending_choice_text, + "Next Camp" + ) scene.battle_result_summary = { "saved": true, @@ -103,3 +122,9 @@ func _check_contains(failures: Array[String], label: String, text: String, expec if text.contains(expected): return failures.append("%s expected `%s` in `%s`" % [label, expected, text]) + + +func _check_not_contains(failures: Array[String], label: String, text: String, unexpected: String) -> void: + if not text.contains(unexpected): + return + failures.append("%s did not expect `%s` in `%s`" % [label, unexpected, text])