Refine battle flow prompts and opening

This commit is contained in:
2026-06-19 22:47:32 +09:00
parent 4b22c13ca9
commit 3b91344b6f
5 changed files with 396 additions and 60 deletions

View File

@@ -108,6 +108,7 @@ const HUD_UNIT_BADGE_ROW_SIZE := Vector2(320, 22)
const HUD_UNIT_BADGE_SIZE := Vector2(26, 22)
const HUD_UNIT_BAR_SIZE := Vector2(252, 12)
const TOP_HUD_CHIP_ICON_SIZE := Vector2(28, 28)
const SIDE_INFO_CHIP_ICON_SIZE := Vector2(26, 26)
const HUD_COMMAND_GRID_SIZE := Vector2(420, 46)
const HUD_COMMAND_BUTTON_SIZE := Vector2(72, 42)
const HUD_COMMAND_GRID_COLUMNS := 4
@@ -334,8 +335,10 @@ var hud_unit_hp_bar: ProgressBar
var hud_unit_mp_bar: ProgressBar
var selected_label: Label
var cell_info_panel: PanelContainer
var cell_info_icon: TextureRect
var cell_info_label: Label
var forecast_panel: PanelContainer
var forecast_icon: TextureRect
var forecast_label: Label
var inventory_label: Label
var briefing_panel: PanelContainer
@@ -408,6 +411,11 @@ var result_seal_ribbon: HBoxContainer
var result_choice_list: VBoxContainer
var result_restart_button: Button
var next_battle_button: Button
var auto_end_turn_prompt_panel: PanelContainer
var auto_end_turn_prompt_label: Label
var auto_end_turn_yes_button: Button
var auto_end_turn_no_button: Button
var auto_end_turn_prompt_declined_turn := -1
var end_turn_button: Button
var wait_button: Button
var tactic_button: Button
@@ -1137,6 +1145,17 @@ func _make_top_hud_chip_icon(icon_kind: String) -> TextureRect:
return icon
func _make_side_info_chip_icon(icon_kind: String) -> TextureRect:
var icon := TextureRect.new()
icon.name = "SideInfoChipIcon"
icon.custom_minimum_size = SIDE_INFO_CHIP_ICON_SIZE
icon.size_flags_vertical = Control.SIZE_SHRINK_CENTER
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
icon.texture = _make_toolbar_icon(icon_kind)
return icon
func _set_top_hud_chip_tooltip(chip: PanelContainer, tooltip: String) -> void:
if chip == null:
return
@@ -1183,6 +1202,21 @@ func _make_toolbar_icon(kind: String) -> Texture2D:
_icon_rect(image, Rect2i(10, 15, 10, 2), Color(0.16, 0.07, 0.03, 1.0))
_icon_rect(image, Rect2i(10, 20, 8, 2), Color(0.16, 0.07, 0.03, 1.0))
_icon_circle(image, Vector2i(24, 9), 3, red)
"terrain":
_icon_line(image, Vector2i(5, 22), Vector2i(13, 12), shadow, 5)
_icon_line(image, Vector2i(13, 12), Vector2i(18, 18), shadow, 5)
_icon_line(image, Vector2i(18, 18), Vector2i(25, 8), shadow, 5)
_icon_line(image, Vector2i(5, 22), Vector2i(13, 12), ink, 3)
_icon_line(image, Vector2i(13, 12), Vector2i(18, 18), ink, 3)
_icon_line(image, Vector2i(18, 18), Vector2i(25, 8), ink, 3)
_icon_line(image, Vector2i(6, 24), Vector2i(26, 24), red, 3)
"forecast":
_icon_circle_outline(image, Vector2i(16, 16), 10, shadow, 4)
_icon_circle_outline(image, Vector2i(16, 16), 10, ink, 2)
_icon_line(image, Vector2i(6, 16), Vector2i(26, 16), red, 2)
_icon_line(image, Vector2i(16, 6), Vector2i(16, 26), red, 2)
_icon_circle(image, Vector2i(16, 16), 4, red)
_icon_circle(image, Vector2i(16, 16), 2, ink)
"move":
_icon_line(image, Vector2i(8, 22), Vector2i(16, 9), shadow, 5)
_icon_line(image, Vector2i(16, 9), Vector2i(24, 22), shadow, 5)
@@ -1879,6 +1913,49 @@ func _create_hud() -> void:
objective_notice_column.add_child(objective_notice_label)
objective_notice_column.add_child(_make_scroll_rod(548, 3))
auto_end_turn_prompt_panel = PanelContainer.new()
auto_end_turn_prompt_panel.name = "AutoEndTurnPrompt"
auto_end_turn_prompt_panel.visible = false
auto_end_turn_prompt_panel.mouse_filter = Control.MOUSE_FILTER_STOP
auto_end_turn_prompt_panel.position = Vector2(408, 112)
auto_end_turn_prompt_panel.size = Vector2(464, 154)
auto_end_turn_prompt_panel.custom_minimum_size = Vector2(464, 154)
_apply_panel_style(auto_end_turn_prompt_panel, "command_seal")
root.add_child(auto_end_turn_prompt_panel)
var auto_end_column := VBoxContainer.new()
auto_end_column.add_theme_constant_override("separation", 8)
auto_end_turn_prompt_panel.add_child(auto_end_column)
auto_end_column.add_child(_make_seal_ribbon(420, 10))
auto_end_turn_prompt_label = Label.new()
auto_end_turn_prompt_label.text = "모든 아군이 군령을 마쳤습니다.\n차례를 넘기시겠습니까?"
auto_end_turn_prompt_label.custom_minimum_size = Vector2(420, 56)
auto_end_turn_prompt_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
auto_end_turn_prompt_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
auto_end_turn_prompt_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
_apply_label_style(auto_end_turn_prompt_label, UI_PARCHMENT_TEXT, 17)
auto_end_column.add_child(auto_end_turn_prompt_label)
var auto_end_button_row := HBoxContainer.new()
auto_end_button_row.alignment = BoxContainer.ALIGNMENT_CENTER
auto_end_button_row.add_theme_constant_override("separation", 12)
auto_end_column.add_child(auto_end_button_row)
auto_end_turn_yes_button = Button.new()
auto_end_turn_yes_button.text = ""
auto_end_turn_yes_button.tooltip_text = "아군 차례를 마치고 적군 차례로 넘깁니다."
auto_end_turn_yes_button.custom_minimum_size = Vector2(122, 38)
auto_end_turn_yes_button.pressed.connect(_on_auto_end_turn_yes_pressed)
auto_end_button_row.add_child(auto_end_turn_yes_button)
auto_end_turn_no_button = Button.new()
auto_end_turn_no_button.text = "아니오"
auto_end_turn_no_button.tooltip_text = "이번 차례에는 자동 확인을 닫습니다."
auto_end_turn_no_button.custom_minimum_size = Vector2(122, 38)
auto_end_turn_no_button.pressed.connect(_on_auto_end_turn_no_pressed)
auto_end_button_row.add_child(auto_end_turn_no_button)
var side_panel := PanelContainer.new()
side_panel.position = SIDE_PANEL_POSITION
side_panel.size = SIDE_PANEL_SIZE
@@ -1988,30 +2065,46 @@ func _create_hud() -> void:
mission_detail_row.add_child(_make_bamboo_gutter(12, 112))
cell_info_panel = PanelContainer.new()
cell_info_panel.name = "CellInfoChip"
cell_info_panel.custom_minimum_size = Vector2(420, 58)
cell_info_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_panel_style(cell_info_panel, "hud_info")
side_column.add_child(cell_info_panel)
var cell_info_row := HBoxContainer.new()
cell_info_row.add_theme_constant_override("separation", 8)
cell_info_panel.add_child(cell_info_row)
cell_info_icon = _make_side_info_chip_icon("terrain")
cell_info_row.add_child(cell_info_icon)
cell_info_label = Label.new()
cell_info_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
cell_info_label.custom_minimum_size = Vector2(396, 38)
cell_info_label.custom_minimum_size = Vector2(354, 38)
cell_info_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_label_style(cell_info_label, Color(0.92, 0.78, 0.54, 1.0), 12)
cell_info_panel.add_child(cell_info_label)
cell_info_row.add_child(cell_info_label)
forecast_panel = PanelContainer.new()
forecast_panel.name = "ForecastChip"
forecast_panel.custom_minimum_size = Vector2(420, 66)
forecast_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_panel_style(forecast_panel, "hud_info")
side_column.add_child(forecast_panel)
var forecast_row := HBoxContainer.new()
forecast_row.add_theme_constant_override("separation", 8)
forecast_panel.add_child(forecast_row)
forecast_icon = _make_side_info_chip_icon("forecast")
forecast_row.add_child(forecast_icon)
forecast_label = Label.new()
forecast_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
forecast_label.custom_minimum_size = Vector2(396, 46)
forecast_label.custom_minimum_size = Vector2(354, 46)
forecast_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_apply_label_style(forecast_label, Color(0.95, 0.80, 0.56, 1.0), 13)
forecast_panel.add_child(forecast_label)
forecast_row.add_child(forecast_label)
inventory_label = Label.new()
inventory_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
@@ -3113,6 +3206,9 @@ func _cancel_pending_move() -> bool:
func _handle_cancel_input() -> bool:
if _is_auto_end_turn_prompt_visible():
_on_auto_end_turn_no_pressed()
return true
if _has_pending_move():
return _cancel_pending_move()
if post_move_picker_panel != null and post_move_picker_panel.visible:
@@ -6483,6 +6579,63 @@ func _update_hud() -> void:
_update_post_move_menu()
_update_post_move_picker()
_update_targeting_hint_panel()
_update_auto_end_turn_prompt()
func _update_auto_end_turn_prompt() -> void:
if auto_end_turn_prompt_panel == null:
return
if _should_show_auto_end_turn_prompt():
auto_end_turn_prompt_panel.visible = true
return
auto_end_turn_prompt_panel.visible = false
func _should_show_auto_end_turn_prompt() -> bool:
if campaign_complete_screen or not battle_started:
return false
if state.battle_status != BattleState.STATUS_ACTIVE:
return false
if state.current_team != BattleState.TEAM_PLAYER:
return false
if auto_end_turn_prompt_declined_turn == state.turn_number:
return false
if _is_dialogue_visible() or _has_active_battle_presentation_sequence():
return false
if briefing_panel != null and briefing_panel.visible:
return false
if result_panel != null and result_panel.visible:
return false
if _has_pending_move():
return false
if not selected_skill_id.is_empty() or not selected_item_id.is_empty() or basic_attack_targeting:
return false
if post_move_menu != null and post_move_menu.visible:
return false
if post_move_picker_panel != null and post_move_picker_panel.visible:
return false
if targeting_hint_panel != null and targeting_hint_panel.visible:
return false
return _all_controllable_player_units_acted()
func _all_controllable_player_units_acted() -> bool:
var has_active_unit := false
for unit in state.units:
if str(unit.get("team", "")) != BattleState.TEAM_PLAYER:
continue
if not bool(unit.get("alive", true)) or not bool(unit.get("deployed", true)):
continue
if not bool(unit.get("controllable", true)):
continue
has_active_unit = true
if not bool(unit.get("acted", false)):
return false
return has_active_unit
func _is_auto_end_turn_prompt_visible() -> bool:
return auto_end_turn_prompt_panel != null and auto_end_turn_prompt_panel.visible
func _format_status_hud_text() -> String:
@@ -6874,17 +7027,21 @@ func _update_cell_info() -> void:
if not state.is_inside(hover_cell):
cell_info_label.text = ""
cell_info_label.tooltip_text = "전장 칸 위에 올리면 지형과 부대 정보를 볼 수 있습니다."
if cell_info_panel != null:
_set_control_tree_tooltip(cell_info_panel, cell_info_label.tooltip_text)
return
var detail_text := _format_cell_info_detail_text(hover_cell)
cell_info_label.text = _format_cell_info_summary_text(hover_cell)
cell_info_label.tooltip_text = detail_text
if cell_info_panel != null:
_set_control_tree_tooltip(cell_info_panel, detail_text)
func _format_cell_info_summary_text(cell: Vector2i) -> String:
if not state.is_inside(cell):
return ""
var summary := state.get_cell_summary(cell)
var text := "%s ·%d · 방비 +%d · 회피 +%d%%" % [
var text := "%s%d +%d +%d%%" % [
_terrain_display_name(str(summary["terrain"])),
int(summary["move_cost"]),
int(summary["defense"]),
@@ -6895,14 +7052,14 @@ func _format_cell_info_summary_text(cell: Vector2i) -> String:
text += " · 회복 +%d" % heal
var objective_cell_label := state.get_objective_cell_label(cell)
if not objective_cell_label.is_empty():
text += "\n목표: %s" % objective_cell_label
text += "\n목표 %s" % objective_cell_label
var event_marker_label := state.get_event_marker_label(cell)
if not event_marker_label.is_empty():
text += "\n표식: %s" % event_marker_label
text += "\n표식 %s" % event_marker_label
if show_threat_overlay:
var threat_names := state.get_threatening_unit_names(cell, BattleState.TEAM_ENEMY)
if not threat_names.is_empty():
text += "\n감시: %s" % _compact_name_list(threat_names, 3)
text += "\n감시 %s" % _compact_name_list(threat_names, 3)
return text
@@ -7043,7 +7200,7 @@ func _compact_name_list(names: Array[String], limit: int) -> String:
func _update_forecast() -> void:
var selected := state.get_selected_unit()
if selected.is_empty() or not state.is_inside(hover_cell):
forecast_label.text = "전황: -"
_clear_forecast()
return
if not selected_skill_id.is_empty():
@@ -7055,22 +7212,22 @@ func _update_forecast() -> void:
var target := state.get_unit_at(hover_cell)
if target.is_empty() or target.get("team", "") == selected.get("team", ""):
forecast_label.text = "전황: -"
_clear_forecast()
return
var preview := state.get_damage_preview(selected["id"], target["id"])
if preview.is_empty():
forecast_label.text = "전황: -"
_clear_forecast()
return
if bool(preview.get("attack_locked", false)):
forecast_label.text = "전황: 병장 봉인\n무기로 공격할 수 없습니다."
_set_forecast_text("전황: 병장 봉인\n무기로 공격할 수 없습니다.")
return
if not bool(preview.get("in_range", false)):
var auto_attack_text := _format_auto_attack_forecast_text(selected, target)
if not auto_attack_text.is_empty():
forecast_label.text = auto_attack_text
var auto_attack_detail := _format_auto_attack_forecast_text(selected, target)
if not auto_attack_detail.is_empty():
_set_forecast_text(auto_attack_detail)
return
var range_text := "사거리 안" if preview["in_range"] else "사거리 밖"
@@ -7091,7 +7248,7 @@ func _update_forecast() -> void:
selected["max_hp"],
counter_defeat
]
forecast_label.text = "전황: %s\n피해 %d%s, 명중 %d%%, 적 병력 %d/%d.%s%s" % [
var detail_text := "전황: %s\n피해 %d%s, 명중 %d%%, 적 병력 %d/%d.%s%s" % [
range_text,
preview["damage"],
effective_text + directional_text,
@@ -7101,6 +7258,54 @@ func _update_forecast() -> void:
defeat_text,
counter_text
]
_set_forecast_text(detail_text)
func _clear_forecast() -> void:
if forecast_label == null:
return
forecast_label.text = "전황: -"
forecast_label.tooltip_text = "공격, 책략, 도구 대상을 가리키면 전황 예측이 표시됩니다."
if forecast_panel != null:
_set_control_tree_tooltip(forecast_panel, forecast_label.tooltip_text)
func _set_forecast_text(detail_text: String) -> void:
if forecast_label == null:
return
var compact_text := _format_forecast_summary_text(detail_text)
forecast_label.text = compact_text
forecast_label.tooltip_text = detail_text
if forecast_panel != null:
_set_control_tree_tooltip(forecast_panel, detail_text)
func _format_forecast_summary_text(detail_text: String) -> String:
var lines := detail_text.split("\n", false)
if lines.is_empty():
return "전황: -"
var first_line := str(lines[0]).strip_edges()
var second_line := ""
if lines.size() > 1:
second_line = str(lines[1]).strip_edges()
if first_line == "전황: -":
return first_line
if second_line.is_empty():
return first_line
var compact_second := second_line
compact_second = compact_second.replace("피해 ", "")
compact_second = compact_second.replace("명중 ", "")
compact_second = compact_second.replace("기력 ", "")
compact_second = compact_second.replace("적 병력 ", "")
compact_second = compact_second.replace("아군 병력 ", "")
compact_second = compact_second.replace("지목 병력 ", "지목")
compact_second = compact_second.replace("군기 병력 ", "")
compact_second = compact_second.replace("병력 ", "")
compact_second = compact_second.replace("회복", "")
compact_second = compact_second.replace(", ", " ")
compact_second = compact_second.replace("; ", " ")
compact_second = compact_second.replace(".", "")
return "%s\n%s" % [first_line, _truncate_hud_text(compact_second, 34)]
func _format_auto_attack_forecast_text(selected: Dictionary, target: Dictionary) -> String:
@@ -7165,24 +7370,24 @@ func _format_directional_forecast_text(preview: Dictionary, bonus_key: String, l
func _update_skill_forecast(selected: Dictionary) -> void:
var preview := state.get_skill_preview(selected["id"], selected_skill_id, hover_cell)
if preview.is_empty():
forecast_label.text = "전황: -"
_clear_forecast()
return
var range_text := "사거리 안" if preview["in_range"] else "사거리 밖"
var mp_text := "" if preview["has_mp"] else " 기력이 부족합니다."
if bool(preview.get("skill_locked", false)):
forecast_label.text = "%s: 봉인, 기력 %d.\n책략을 펼칠 수 없습니다." % [
_set_forecast_text("%s: 봉인, 기력 %d.\n책략을 펼칠 수 없습니다." % [
preview["skill_name"],
preview["mp_cost"]
]
])
return
if not preview["valid_target"]:
forecast_label.text = "%s: %s, 기력 %d.%s\n지목할 대상이 없습니다." % [
_set_forecast_text("%s: %s, 기력 %d.%s\n지목할 대상이 없습니다." % [
preview["skill_name"],
range_text,
preview["mp_cost"],
mp_text
]
])
return
var target := state.get_unit(str(preview.get("target_id", "")))
@@ -7193,7 +7398,7 @@ func _update_skill_forecast(selected: Dictionary) -> void:
if preview["kind"] == "heal":
var total_heal := int(preview.get("total_heal", preview.get("heal", 0)))
if not has_area:
forecast_label.text = "%s: %s, 기력 %d.%s\n병력 %d 회복, 군기 병력 %d/%d." % [
_set_forecast_text("%s: %s, 기력 %d.%s\n병력 %d 회복, 군기 병력 %d/%d." % [
preview["skill_name"],
range_text,
preview["mp_cost"],
@@ -7201,9 +7406,9 @@ func _update_skill_forecast(selected: Dictionary) -> void:
preview["heal"],
preview["target_hp_after"],
target_max_hp
]
])
return
forecast_label.text = "%s: %s, 기력 %d.%s%s\n총 병력 %d 회복, 지목 병력 %d/%d." % [
_set_forecast_text("%s: %s, 기력 %d.%s%s\n총 병력 %d 회복, 지목 병력 %d/%d." % [
preview["skill_name"],
range_text,
preview["mp_cost"],
@@ -7212,10 +7417,10 @@ func _update_skill_forecast(selected: Dictionary) -> void:
total_heal,
preview["target_hp_after"],
target_max_hp
]
])
elif preview["kind"] == "support":
var refresh_text := " 갱신." if bool(preview.get("already_active", false)) else ""
forecast_label.text = "%s: %s, 기력 %d.%s%s\n%s.%s" % [
_set_forecast_text("%s: %s, 기력 %d.%s%s\n%s.%s" % [
preview["skill_name"],
range_text,
preview["mp_cost"],
@@ -7223,14 +7428,14 @@ func _update_skill_forecast(selected: Dictionary) -> void:
area_text,
preview.get("effect_text", "지원"),
refresh_text
]
])
else:
var defeat_count := int(preview.get("defeat_count", 0))
var defeat_text := " 퇴각 %d" % defeat_count if defeat_count > 0 else ""
var total_damage := int(preview.get("total_damage", preview.get("damage", 0)))
if not has_area:
var single_defeat_text := " 퇴각" if bool(preview.get("would_defeat", false)) else ""
forecast_label.text = "%s: %s, 기력 %d.%s\n피해 %d, 적 병력 %d/%d.%s" % [
_set_forecast_text("%s: %s, 기력 %d.%s\n피해 %d, 적 병력 %d/%d.%s" % [
preview["skill_name"],
range_text,
preview["mp_cost"],
@@ -7239,9 +7444,9 @@ func _update_skill_forecast(selected: Dictionary) -> void:
preview["target_hp_after"],
target_max_hp,
single_defeat_text
]
])
return
forecast_label.text = "%s: %s, 기력 %d.%s%s\n총 피해 %d, 지목 병력 %d/%d.%s" % [
_set_forecast_text("%s: %s, 기력 %d.%s%s\n총 피해 %d, 지목 병력 %d/%d.%s" % [
preview["skill_name"],
range_text,
preview["mp_cost"],
@@ -7251,35 +7456,35 @@ func _update_skill_forecast(selected: Dictionary) -> void:
preview["target_hp_after"],
target_max_hp,
defeat_text
]
])
func _update_item_forecast(selected: Dictionary) -> void:
var preview := state.get_item_preview(selected["id"], selected_item_id, hover_cell)
if preview.is_empty():
forecast_label.text = "전황: -"
_clear_forecast()
return
var target := state.get_unit_at(hover_cell)
var range_text := "사거리 안" if preview["in_range"] else "사거리 밖"
var count_text := "잔량 %d" % int(preview.get("count", 0))
if target.is_empty() or not preview["valid_target"]:
forecast_label.text = "%s: %s, %s\n지목할 대상이 없습니다." % [
_set_forecast_text("%s: %s, %s\n지목할 대상이 없습니다." % [
preview["item_name"],
range_text,
count_text
]
])
return
var hp_heal := int(preview.get("heal", 0))
var mp_heal := int(preview.get("mp_heal", 0))
var cure_statuses: Array = preview.get("cure_statuses", [])
if hp_heal <= 0 and mp_heal <= 0 and cure_statuses.is_empty():
forecast_label.text = "%s: %s, %s\n보급 효과가 필요하지 않습니다." % [
_set_forecast_text("%s: %s, %s\n보급 효과가 필요하지 않습니다." % [
preview["item_name"],
range_text,
count_text
]
])
return
var recovery_parts := []
@@ -7298,12 +7503,12 @@ func _update_item_forecast(selected: Dictionary) -> void:
if not cure_statuses.is_empty():
recovery_parts.append("치료 %s" % _join_strings(cure_statuses, ", "))
forecast_label.text = "%s: %s, %s\n%s." % [
_set_forecast_text("%s: %s, %s\n%s." % [
preview["item_name"],
range_text,
count_text,
_join_strings(recovery_parts, "; ")
]
])
func _update_forecast_panel_visibility() -> void:
@@ -7844,14 +8049,12 @@ func _update_dialogue_controls() -> void:
dialogue_progress_label.text = "대화 %d/%d" % [active_dialogue_index + 1, active_dialogue_lines.size()]
if dialogue_previous_button != null:
dialogue_previous_button.disabled = active_dialogue_index <= 0
dialogue_continue_button.text = "닫기" if active_dialogue_index >= active_dialogue_lines.size() - 1 else "다음"
dialogue_continue_button.text = "다음"
func _apply_dialogue_side(side: String) -> void:
if dialogue_row == null or dialogue_portrait_panel == null or dialogue_column == null:
return
var portrait_index: int = maxi(0, dialogue_row.get_child_count() - 2) if side == "right" else 1
dialogue_row.move_child(dialogue_portrait_panel, portrait_index)
dialogue_speaker_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT if side == "right" else HORIZONTAL_ALIGNMENT_LEFT
dialogue_text_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT if side == "right" else HORIZONTAL_ALIGNMENT_LEFT
@@ -7987,6 +8190,21 @@ func _on_wait_pressed() -> void:
_play_ui_confirm()
func _on_auto_end_turn_yes_pressed() -> void:
if auto_end_turn_prompt_panel != null:
auto_end_turn_prompt_panel.visible = false
_on_end_turn_pressed()
func _on_auto_end_turn_no_pressed() -> void:
auto_end_turn_prompt_declined_turn = state.turn_number
if auto_end_turn_prompt_panel != null:
auto_end_turn_prompt_panel.visible = false
_play_ui_cancel()
_update_hud()
queue_redraw()
func _on_end_turn_pressed() -> void:
if state.can_player_act():
_play_ui_confirm()
@@ -10023,6 +10241,7 @@ func _is_input_locked() -> bool:
return (
campaign_complete_screen
or _is_dialogue_visible()
or _is_auto_end_turn_prompt_visible()
or _has_active_battle_presentation_sequence()
or not battle_started
or state.battle_status != BattleState.STATUS_ACTIVE