Add portrait formation rows
This commit is contained in:
@@ -24,7 +24,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr
|
||||
- Pre-battle Talk can list scenario camp conversations by officer or topic, branch them from saved campaign choices, grant one-time pre-battle supplies, and shop stock can include merchant flavor lines before a battle.
|
||||
- Pre-battle Armory equipment changes, including unequipping gear back into stock, save immediately and sync roster equipment plus inventory stock, with portrait and item-icon rows plus hover change details.
|
||||
- Pre-battle Roster can move optional officers between sortie and reserve within scenario limits, using portrait rows, compact status badges, and hover details.
|
||||
- Pre-battle Formation lets deployed officers swap starting positions inside scenario-defined cells.
|
||||
- Pre-battle Formation lets deployed officers swap starting positions inside scenario-defined cells, with portrait rows, coordinate badges, and hover placement instructions.
|
||||
- Pre-battle briefing shows the campaign chapter, chapter battle number, location, victory/defeat summary, and first-clear reward preview.
|
||||
- Pre-battle Chapters overview shows story-arc progress and can open completed or current battles.
|
||||
- Pre-battle Save menu can write and load one manual campaign checkpoint separate from the automatic save.
|
||||
|
||||
@@ -11381,11 +11381,10 @@ func _rebuild_formation_menu() -> void:
|
||||
var selected := state.get_unit(formation_unit_id)
|
||||
if selected.is_empty():
|
||||
formation_status_label.text = "진형"
|
||||
formation_status_label.tooltip_text = "출진 장수를 고른 뒤 전장도의 금빛 진형 칸을 클릭해 배치합니다."
|
||||
else:
|
||||
formation_status_label.text = "진형: %s · %s" % [
|
||||
str(selected.get("name", "장수")),
|
||||
_format_cell_label(selected.get("pos", Vector2i.ZERO))
|
||||
]
|
||||
formation_status_label.text = "진형: %s" % str(selected.get("name", "장수"))
|
||||
formation_status_label.tooltip_text = _format_formation_unit_tooltip(selected, true)
|
||||
|
||||
if units.is_empty():
|
||||
var empty_label := Label.new()
|
||||
@@ -11396,12 +11395,7 @@ func _rebuild_formation_menu() -> void:
|
||||
|
||||
for unit in units:
|
||||
var unit_id := str(unit.get("id", ""))
|
||||
var unit_button := Button.new()
|
||||
unit_button.text = _format_formation_unit_button_text(unit)
|
||||
_apply_button_style(unit_button)
|
||||
unit_button.disabled = unit_id == formation_unit_id
|
||||
unit_button.pressed.connect(_on_formation_unit_pressed.bind(unit_id))
|
||||
formation_list.add_child(unit_button)
|
||||
_add_formation_unit_row(unit, unit_id == formation_unit_id)
|
||||
|
||||
|
||||
func _clear_formation_list() -> void:
|
||||
@@ -11411,14 +11405,73 @@ func _clear_formation_list() -> void:
|
||||
|
||||
|
||||
func _format_formation_unit_button_text(unit: Dictionary) -> String:
|
||||
var marker := "> " if str(unit.get("id", "")) == formation_unit_id else ""
|
||||
return "%s%s %s" % [
|
||||
marker,
|
||||
str(unit.get("name", "장수")),
|
||||
_format_cell_label(unit.get("pos", Vector2i.ZERO))
|
||||
return str(unit.get("name", "장수"))
|
||||
|
||||
|
||||
func _add_formation_unit_row(unit: Dictionary, selected: bool) -> void:
|
||||
var unit_id := str(unit.get("id", ""))
|
||||
var tooltip_text := _format_formation_unit_tooltip(unit, selected)
|
||||
var row := HBoxContainer.new()
|
||||
row.custom_minimum_size = Vector2(580, 62)
|
||||
row.add_theme_constant_override("separation", 8)
|
||||
row.tooltip_text = tooltip_text
|
||||
formation_list.add_child(row)
|
||||
|
||||
row.add_child(_make_roster_unit_portrait(unit, tooltip_text))
|
||||
|
||||
var column := VBoxContainer.new()
|
||||
column.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
column.add_theme_constant_override("separation", 4)
|
||||
column.tooltip_text = tooltip_text
|
||||
row.add_child(column)
|
||||
|
||||
var unit_button := Button.new()
|
||||
unit_button.text = _format_formation_unit_button_text(unit)
|
||||
unit_button.custom_minimum_size = Vector2(500, 30)
|
||||
unit_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
unit_button.disabled = selected
|
||||
unit_button.tooltip_text = tooltip_text
|
||||
_apply_button_style(unit_button)
|
||||
unit_button.pressed.connect(_on_formation_unit_pressed.bind(unit_id))
|
||||
column.add_child(unit_button)
|
||||
|
||||
var badge_row := HBoxContainer.new()
|
||||
badge_row.custom_minimum_size = Vector2(500, 22)
|
||||
badge_row.add_theme_constant_override("separation", 5)
|
||||
badge_row.tooltip_text = tooltip_text
|
||||
column.add_child(badge_row)
|
||||
|
||||
for badge_text in _format_formation_unit_badges(unit, selected):
|
||||
var text := str(badge_text).strip_edges()
|
||||
if text.is_empty():
|
||||
continue
|
||||
badge_row.add_child(_make_armory_info_badge(text, tooltip_text))
|
||||
|
||||
|
||||
func _format_formation_unit_badges(unit: Dictionary, selected: bool) -> Array:
|
||||
return [
|
||||
"선택" if selected else "대상",
|
||||
"좌표 %s" % _format_cell_label(unit.get("pos", Vector2i.ZERO)),
|
||||
_unit_class_display_name(unit)
|
||||
]
|
||||
|
||||
|
||||
func _format_formation_unit_tooltip(unit: Dictionary, selected: bool) -> String:
|
||||
var lines := [
|
||||
"%s · 품계 %d · %s" % [
|
||||
str(unit.get("name", "장수")),
|
||||
int(unit.get("level", 1)),
|
||||
_unit_class_display_name(unit)
|
||||
],
|
||||
"현재 위치: %s" % _format_cell_label(unit.get("pos", Vector2i.ZERO))
|
||||
]
|
||||
if selected:
|
||||
lines.append("전장도의 금빛 진형 칸을 클릭하면 이 장수를 옮깁니다.")
|
||||
else:
|
||||
lines.append("클릭하면 배치할 장수로 선택합니다.")
|
||||
return _join_strings(lines, "\n")
|
||||
|
||||
|
||||
func _format_cell_label(value) -> String:
|
||||
if typeof(value) == TYPE_VECTOR2I:
|
||||
return "%d,%d" % [value.x + 1, value.y + 1]
|
||||
|
||||
@@ -3008,6 +3008,19 @@ func _check_scene_texture_loading(failures: Array[String]) -> void:
|
||||
failures.append("shop row tooltip should retain full item detail: %s" % shop_tooltips)
|
||||
if not _has_descendant_texture(scene.shop_list):
|
||||
failures.append("shop rows should use item icon artwork")
|
||||
scene._rebuild_formation_menu()
|
||||
var formation_visible_text := _collect_child_text(scene.formation_list)
|
||||
var formation_tooltips := _collect_child_tooltips(scene.formation_list)
|
||||
if not formation_visible_text.contains("조조") or not formation_visible_text.contains("좌표") or not formation_visible_text.contains("선택"):
|
||||
failures.append("formation rows should show officer name and compact placement badges: %s" % formation_visible_text)
|
||||
if formation_visible_text.contains("전장도의") or formation_visible_text.contains("클릭하면"):
|
||||
failures.append("formation rows should keep placement instructions in hover text: %s" % formation_visible_text)
|
||||
if not formation_tooltips.contains("금빛 진형 칸") or not formation_tooltips.contains("현재 위치"):
|
||||
failures.append("formation row tooltip should retain placement instructions: %s" % formation_tooltips)
|
||||
if not _has_descendant_texture(scene.formation_list):
|
||||
failures.append("formation rows should reuse officer portrait artwork")
|
||||
if scene._format_formation_unit_button_text(scene.state.get_unit("cao_cao")).contains(","):
|
||||
failures.append("formation unit button text should stay compact")
|
||||
scene.free()
|
||||
|
||||
_check_scenario_background_texture_loading(failures)
|
||||
|
||||
Reference in New Issue
Block a user