From 60bd716d25d67baf482ec76303a3d9c09505888c Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sat, 20 Jun 2026 19:44:42 +0900 Subject: [PATCH] Improve battle text readability --- scripts/scenes/battle_scene.gd | 101 +++++++++++++++++++++++++--- tools/capture_readability_frames.gd | 6 +- tools/smoke_visual_assets.gd | 12 ++++ 3 files changed, 106 insertions(+), 13 deletions(-) diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index 329d93f..4600fd5 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -159,7 +159,8 @@ const BRIEFING_OVERVIEW_MIN_FONT_SIZE := 14 const BRIEFING_VISIBLE_BODY_LINES := 2 const BRIEFING_VISIBLE_BODY_CHARS := 50 const COMMAND_NOTICE_VISIBLE_BODY_LINES := 2 -const COMMAND_NOTICE_VISIBLE_BODY_CHARS := 44 +const BATTLE_START_NOTICE_VISIBLE_BODY_LINES := 3 +const COMMAND_NOTICE_VISIBLE_BODY_CHARS := 34 const DIALOGUE_SPEAKER_FONT_SIZE := 20 const DIALOGUE_SPEAKER_MIN_FONT_SIZE := 16 const DIALOGUE_TEXT_FONT_SIZE := 20 @@ -3598,8 +3599,8 @@ func _create_hud() -> void: objective_notice_panel = PanelContainer.new() objective_notice_panel.visible = false objective_notice_panel.position = Vector2(338, 88) - objective_notice_panel.size = Vector2(604, 206) - objective_notice_panel.custom_minimum_size = Vector2(604, 206) + objective_notice_panel.size = Vector2(604, 232) + objective_notice_panel.custom_minimum_size = Vector2(604, 232) objective_notice_panel.mouse_filter = Control.MOUSE_FILTER_PASS _apply_panel_style(objective_notice_panel, "notice_edict") root.add_child(objective_notice_panel) @@ -3622,7 +3623,7 @@ func _create_hud() -> void: objective_notice_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER objective_notice_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER objective_notice_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART - objective_notice_label.custom_minimum_size = Vector2(548, 90) + objective_notice_label.custom_minimum_size = Vector2(548, 116) _apply_label_style(objective_notice_label, UI_AGED_INK, OBJECTIVE_NOTICE_FONT_SIZE) objective_notice_column.add_child(objective_notice_label) objective_notice_column.add_child(_make_scroll_rod(548, 3)) @@ -10298,14 +10299,57 @@ func _team_hud_short_text(team: String) -> String: func _format_objective_hud_text() -> String: var progress_lines := state.get_objective_progress_lines(false, false) - if not progress_lines.is_empty(): - return _join_strings(progress_lines, " · ") + var progress_summary := _format_compact_objective_hud_progress_text(progress_lines) + if not progress_summary.is_empty(): + return progress_summary var victory := String(state.objectives.get("victory", "적군을 모두 격파하라.")).strip_edges() if victory.is_empty(): return "대기" return _truncate_hud_text(victory, 34) +func _format_compact_objective_hud_progress_text(progress_lines: Array[String]) -> String: + var parts: Array[String] = [] + for mode in ["destination", "turn_gate", "active", "any"]: + var part := _first_objective_hud_summary_line(progress_lines, mode) + if not part.is_empty() and not parts.has(part): + parts.append(part) + if parts.size() >= 2: + break + if parts.is_empty(): + return "" + return _truncate_hud_text(_join_strings(parts, " · "), 44) + + +func _first_objective_hud_summary_line(progress_lines: Array[String], mode: String) -> String: + for line in progress_lines: + var text := _sanitize_objective_hud_line(str(line)) + if text.is_empty(): + continue + match mode: + "destination": + if not line.contains("(대기)") and (text.contains(" · 미도달") or text.contains(" · 도달")): + return text + "turn_gate": + if text.contains("군령") and text.contains("전공 갱신"): + return text + "active": + if not line.contains("(대기)"): + return text + "any": + return text + return "" + + +func _sanitize_objective_hud_line(line: String) -> String: + var text := line.strip_edges() + if text.is_empty(): + return "" + text = text.replace(" (대기)", "") + text = text.replace("에 전공 갱신", " 전공 갱신") + return text + + func _format_objective_hud_detail_text() -> String: var lines := [] var victory := String(state.objectives.get("victory", "적군을 모두 격파하라.")) @@ -10314,6 +10358,12 @@ func _format_objective_hud_detail_text() -> String: var defeat := String(state.objectives.get("defeat", "")) if not defeat.is_empty(): lines.append("패배: %s" % defeat) + var progress := state.get_objective_progress_text(false, true) + if not progress.is_empty(): + lines.append("진행: %s" % progress) + var risks := state.get_defeat_progress_text() + if not risks.is_empty(): + lines.append("주의: %s" % risks) if lines.is_empty(): return "목표 대기" return _join_strings(lines, "\n") @@ -11766,9 +11816,9 @@ func _format_battle_start_notice_body() -> String: lines.append("목표: %s" % goal_summary) elif not risk_summary.is_empty(): lines.append("주의: %s" % risk_summary) - var marker_summary := _format_battle_start_marker_summary() - if not marker_summary.is_empty(): - lines.append("표식: %s" % marker_summary) + var marker_lines := _format_battle_start_marker_notice_lines() + for marker_line in marker_lines: + lines.append(marker_line) if lines.is_empty(): lines.append("목표를 확인하고 첫 군령을 내리십시오.") return _join_strings(lines, "\n") @@ -11819,6 +11869,28 @@ func _battle_start_risk_notice_summary() -> String: func _format_battle_start_marker_summary() -> String: + return _join_strings(_battle_start_marker_text_entries(), " · ") + + +func _format_battle_start_marker_notice_lines() -> Array[String]: + var labels := _battle_start_marker_text_entries() + var lines: Array[String] = [] + if labels.is_empty(): + return lines + var first_line_count := mini(2, labels.size()) + var first_line_parts: Array[String] = [] + for index in range(first_line_count): + first_line_parts.append(labels[index]) + lines.append("표식: %s" % _join_strings(first_line_parts, " · ")) + if labels.size() > first_line_count: + var remaining_parts: Array[String] = [] + for index in range(first_line_count, labels.size()): + remaining_parts.append(labels[index]) + lines.append("표식: %s" % _join_strings(remaining_parts, " · ")) + return lines + + +func _battle_start_marker_text_entries() -> Array[String]: var labels: Array[String] = [] var seen := {} for marker in state.get_event_markers(): @@ -11836,7 +11908,7 @@ func _format_battle_start_marker_summary() -> String: labels.append(text) if labels.size() >= BRIEFING_TACTICAL_MARKER_MAX_COUNT: break - return _join_strings(labels, " · ") + return labels func _battle_start_marker_is_tactical(label: String, kind: String) -> bool: @@ -11860,9 +11932,10 @@ func _battle_start_marker_text(label: String, kind: String, hint: String = "") - func _show_command_notice(title: String, body: String) -> void: var notice_lines := [title] var normalized_body := body.strip_edges() + var visible_line_budget := _command_notice_visible_body_line_budget(title, normalized_body) var visible_body := _compact_visible_text( normalized_body, - COMMAND_NOTICE_VISIBLE_BODY_LINES, + visible_line_budget, COMMAND_NOTICE_VISIBLE_BODY_CHARS ) if not normalized_body.is_empty(): @@ -11890,6 +11963,12 @@ func _show_command_notice(title: String, body: String) -> void: queue_redraw() +func _command_notice_visible_body_line_budget(title: String, body: String) -> int: + if title == "전투 개시" and body.contains("표식:"): + return BATTLE_START_NOTICE_VISIBLE_BODY_LINES + return COMMAND_NOTICE_VISIBLE_BODY_LINES + + func _rebuild_command_notice_icon_strip(title: String, body: String) -> void: if objective_notice_icon_strip == null: return diff --git a/tools/capture_readability_frames.gd b/tools/capture_readability_frames.gd index 6df7336..bac0f57 100644 --- a/tools/capture_readability_frames.gd +++ b/tools/capture_readability_frames.gd @@ -94,16 +94,18 @@ func _capture_viewport_set(spec: Dictionary, output_dir: String, captures: Array scene._advance_dialogue() guard += 1 await _settle() + if scene.objective_notice_panel != null and scene.objective_notice_panel.visible: + await _capture_frame(scene, output_dir, label, "06_battle_start_notice", captures, failures) if scene.objective_notice_panel != null: scene.objective_notice_panel.visible = false scene._update_hud() await _settle() - await _capture_frame(scene, output_dir, label, "06_battle_idle", captures, failures) + await _capture_frame(scene, output_dir, label, "07_battle_idle", captures, failures) scene._update_threat_button() scene._on_command_hint_button_mouse_entered(scene.threat_button) await _settle() - await _capture_frame(scene, output_dir, label, "07_battle_threat_hint", captures, failures) + await _capture_frame(scene, output_dir, label, "08_battle_threat_hint", captures, failures) scene.queue_free() await _settle() diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 57926f5..52f37fc 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3702,8 +3702,14 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: var hud_objective_detail := scene._format_objective_hud_detail_text() if hud_objective.begins_with("목표:") or hud_objective.contains("승리 조건") or hud_objective.contains("패배 조건"): failures.append("HUD objective should hide labels and keep only a concise current-goal summary: %s" % hud_objective) + if not hud_objective.contains("성채 장악") or not hud_objective.contains("제11군령"): + failures.append("HUD objective should show the current destination and turn-gated objective first: %s" % hud_objective) + if hud_objective.contains("적군 격파 0/") or hud_objective.contains("(대기)"): + failures.append("HUD objective should hide pending defeat counts from the visible top chip: %s" % hud_objective) if not hud_objective_detail.contains("승리:") or not hud_objective_detail.contains("패배:"): failures.append("HUD objective tooltip should retain win/loss details: %s" % hud_objective_detail) + if not hud_objective_detail.contains("진행:") or not hud_objective_detail.contains("적군 격파") or not hud_objective_detail.contains("조조 건재"): + failures.append("HUD objective tooltip should preserve full progress and risk details: %s" % hud_objective_detail) scene.battle_started = true scene.briefing_panel.visible = false scene.result_panel.visible = false @@ -3718,6 +3724,8 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: failures.append("top campaign status tooltip should retain full campaign progress: %s" % scene.campaign_status_label.tooltip_text) if scene.objective_label == null or scene.objective_label.text.begins_with("목표:"): failures.append("top objective label should avoid repeated visible heading: %s" % ("" if scene.objective_label == null else scene.objective_label.text)) + elif scene.objective_label.text.contains("적군 격파 0/") or scene.objective_label.text.contains("(대기)"): + failures.append("top objective label should keep pending counts in tooltip only: %s" % scene.objective_label.text) elif not scene.objective_label.tooltip_text.contains("승리:") or not scene.objective_label.tooltip_text.contains("패배:"): failures.append("top objective tooltip should retain objective detail: %s" % ("" if scene.objective_label == null else scene.objective_label.tooltip_text)) _check_top_hud_chip(failures, scene, "TopStatusChip", scene.status_label, "군령") @@ -3998,6 +4006,10 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: scene._on_objective_updated("동문에 깃발을 세워라.", "조조가 퇴각하면 패전이다.") if scene.objective_notice_label == null or not scene.objective_notice_label.text.contains("목표:") or not scene.objective_notice_label.text.contains("주의:"): failures.append("objective update notice should use Korean annotation wording") + elif scene.objective_notice_label.text.split("\n").size() > 3: + failures.append("objective update notice should stay within a title plus two readable body lines: %s" % scene.objective_notice_label.text) + elif not scene.objective_notice_label.tooltip_text.contains("동문에 깃발") or not scene.objective_notice_label.tooltip_text.contains("조조가 퇴각"): + failures.append("objective update notice tooltip should keep the full notice text: %s" % scene.objective_notice_label.tooltip_text) if scene.objective_notice_icon_strip == null or not scene.objective_notice_icon_strip.visible or scene.objective_notice_icon_strip.get_child_count() < 2: failures.append("objective update notice should show objective and warning icons") elif not _has_descendant_texture(scene.objective_notice_icon_strip):