diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index a0d7785..ab8cb33 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -10934,6 +10934,36 @@ func _show_turn_notice_for_log(message: String) -> void: elif message == "아군 차례가 열렸습니다.": _play_ui_confirm() _show_command_notice("아군 군령", "제%d군령 · 아군 차례" % state.turn_number) + elif battle_started: + var event_notice := _battle_event_notice_for_log(message) + if not event_notice.is_empty(): + _show_command_notice(str(event_notice.get("title", "전장 변화")), str(event_notice.get("body", message))) + + +func _battle_event_notice_for_log(message: String) -> Dictionary: + var normalized := message.strip_edges() + if normalized.is_empty(): + return {} + if normalized.begins_with("군령 갱신:") or normalized.begins_with("패배 조건 갱신:"): + return {} + if _battle_event_log_matches(normalized, ["유인선", "끌려 나왔다", "경계"]): + return {"title": "적 경계 변화", "body": normalized} + if _battle_event_log_matches(normalized, ["잔병이 합류", "약탈대", "마지막 황건대", "마지막 반격", "잔당"]): + return {"title": "적 증원", "body": normalized} + if _battle_event_log_matches(normalized, ["보급고", "치료소", "창고", "전리품:", "군자금"]): + return {"title": "보급 확보", "body": normalized} + if _battle_event_log_matches(normalized, ["성채", "깃발"]): + return {"title": "거점 변화", "body": normalized} + if _battle_event_log_matches(normalized, ["선봉을 노린다", "본진을 노린다", "후미를 노린다", "시선이 몰립니다", "표적"]): + return {"title": "적 시선 변화", "body": normalized} + return {} + + +func _battle_event_log_matches(message: String, keywords: Array[String]) -> bool: + for keyword in keywords: + if message.contains(keyword): + return true + return false func _on_objective_updated(victory: String, defeat: String) -> void: @@ -10991,6 +11021,11 @@ func _command_notice_icon_entries(title: String, body: String) -> Array[Dictiona elif combined_text.contains("적군"): _append_command_notice_icon_entry(entries, seen, "toolbar", "threat", "적세") _append_command_notice_icon_entry(entries, seen, "toolbar", "forecast", "예측") + if combined_text.contains("증원") or combined_text.contains("잔병") or combined_text.contains("약탈대") or combined_text.contains("잔당") or combined_text.contains("반격"): + _append_command_notice_icon_entry(entries, seen, "toolbar", "threat", "적세") + _append_command_notice_icon_entry(entries, seen, "toolbar", "status", "주의") + if combined_text.contains("경계") or combined_text.contains("표적") or combined_text.contains("노린다") or combined_text.contains("시선"): + _append_command_notice_icon_entry(entries, seen, "toolbar", "threat", "적세") if combined_text.contains("목표") or combined_text.contains("성채") or combined_text.contains("깃발"): _append_command_notice_icon_entry(entries, seen, "badge", "objective", "목표") if combined_text.contains("유인"): diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 25fa66a..56284c6 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3669,6 +3669,29 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: failures.append("player turn notice should show generated visual command icons") elif not _has_descendant_texture(scene.objective_notice_icon_strip): failures.append("player turn notice icons should use generated textures") + if scene.objective_notice_panel != null: + scene.objective_notice_panel.visible = false + scene.battle_started = false + scene._on_log_added("동쪽 들판에서 황건 잔병이 합류했다.") + if scene.objective_notice_panel != null and scene.objective_notice_panel.visible: + failures.append("pre-battle event-like logs should not create battlefield command notices") + scene.battle_started = true + scene._on_log_added("조조군이 마을 앞 유인선에 닿았다.") + if scene.objective_notice_label == null or not scene.objective_notice_label.text.contains("적 경계 변화") or not scene.objective_notice_label.text.contains("유인선"): + failures.append("lure-line event log should become a readable battlefield notice: %s" % ("" if scene.objective_notice_label == null else scene.objective_notice_label.text)) + if scene.objective_notice_icon_strip == null or not scene.objective_notice_icon_strip.visible or not _has_descendant_texture(scene.objective_notice_icon_strip): + failures.append("lure-line event notice should show generated visual icons") + scene._on_log_added("동쪽 들판에서 황건 잔병이 합류했다.") + if scene.objective_notice_label == null or not scene.objective_notice_label.text.contains("적 증원") or not scene.objective_notice_label.text.contains("잔병"): + failures.append("reinforcement event log should become a battlefield notice: %s" % ("" if scene.objective_notice_label == null else scene.objective_notice_label.text)) + if scene.objective_notice_icon_strip == null or scene.objective_notice_icon_strip.get_child_count() < 2: + failures.append("reinforcement event notice should include threat and warning icons") + scene._on_log_added("북쪽 숲 보급고를 거두었다.") + if scene.objective_notice_label == null or not scene.objective_notice_label.text.contains("보급 확보") or not scene.objective_notice_label.text.contains("보급고"): + failures.append("supply event log should become a battlefield notice: %s" % ("" if scene.objective_notice_label == null else scene.objective_notice_label.text)) + scene._on_log_added("조조군이 동쪽 성채에 발을 들였다.") + if scene.objective_notice_label == null or not scene.objective_notice_label.text.contains("거점 변화") or not scene.objective_notice_label.text.contains("성채"): + failures.append("castle event log should become a battlefield notice: %s" % ("" if scene.objective_notice_label == null else scene.objective_notice_label.text)) var localized_lines := scene._normalized_dialogue_lines([{"speaker": "Cao Cao", "display_speaker": "조조", "text": "군령을 전하라."}]) if localized_lines.is_empty() or str((localized_lines[0] as Dictionary).get("speaker", "")) != "조조": failures.append("dialogue normalization should preserve display_speaker for localized names")