Compact selected unit HUD with hover badges
This commit is contained in:
@@ -103,7 +103,9 @@ const SHOP_ITEM_ICON_SIZE := Vector2(48, 48)
|
|||||||
const HUD_UNIT_PORTRAIT_SIZE := Vector2(92, 104)
|
const HUD_UNIT_PORTRAIT_SIZE := Vector2(92, 104)
|
||||||
const HUD_UNIT_PORTRAIT_STACK_SIZE := Vector2(88, 100)
|
const HUD_UNIT_PORTRAIT_STACK_SIZE := Vector2(88, 100)
|
||||||
const HUD_UNIT_INFO_SIZE := Vector2(320, 126)
|
const HUD_UNIT_INFO_SIZE := Vector2(320, 126)
|
||||||
const HUD_UNIT_SUMMARY_SIZE := Vector2(320, 58)
|
const HUD_UNIT_SUMMARY_SIZE := Vector2(320, 42)
|
||||||
|
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 HUD_UNIT_BAR_SIZE := Vector2(252, 12)
|
||||||
const HUD_COMMAND_GRID_SIZE := Vector2(420, 46)
|
const HUD_COMMAND_GRID_SIZE := Vector2(420, 46)
|
||||||
const HUD_COMMAND_BUTTON_SIZE := Vector2(72, 42)
|
const HUD_COMMAND_BUTTON_SIZE := Vector2(72, 42)
|
||||||
@@ -323,6 +325,7 @@ var hud_unit_portrait_panel: PanelContainer
|
|||||||
var hud_unit_portrait_texture: TextureRect
|
var hud_unit_portrait_texture: TextureRect
|
||||||
var hud_unit_portrait_label: Label
|
var hud_unit_portrait_label: Label
|
||||||
var hud_unit_info_column: VBoxContainer
|
var hud_unit_info_column: VBoxContainer
|
||||||
|
var hud_unit_badge_row: HBoxContainer
|
||||||
var hud_unit_hp_bar: ProgressBar
|
var hud_unit_hp_bar: ProgressBar
|
||||||
var hud_unit_mp_bar: ProgressBar
|
var hud_unit_mp_bar: ProgressBar
|
||||||
var selected_label: Label
|
var selected_label: Label
|
||||||
@@ -887,6 +890,210 @@ func _make_hud_unit_resource_row(label_text: String, fill_color: Color) -> Dicti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func _clear_hud_unit_badges() -> void:
|
||||||
|
if hud_unit_badge_row == null:
|
||||||
|
return
|
||||||
|
for child in hud_unit_badge_row.get_children():
|
||||||
|
hud_unit_badge_row.remove_child(child)
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func _update_hud_unit_badges(unit: Dictionary, detail_text: String) -> void:
|
||||||
|
if hud_unit_badge_row == null:
|
||||||
|
return
|
||||||
|
_clear_hud_unit_badges()
|
||||||
|
hud_unit_badge_row.tooltip_text = detail_text
|
||||||
|
hud_unit_badge_row.visible = not unit.is_empty()
|
||||||
|
if unit.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
hud_unit_badge_row.add_child(_make_hud_unit_badge(
|
||||||
|
_hud_unit_team_badge_text(unit),
|
||||||
|
_hud_unit_badge_tooltip(_unit_team_text(str(unit.get("team", ""))), detail_text),
|
||||||
|
_hud_unit_team_badge_color(unit)
|
||||||
|
))
|
||||||
|
hud_unit_badge_row.add_child(_make_hud_unit_badge(
|
||||||
|
_hud_unit_class_badge_text(unit),
|
||||||
|
_hud_unit_badge_tooltip("%s · %s" % [_unit_class_display_name(unit), _unit_role_text(unit)], detail_text),
|
||||||
|
_hud_unit_class_badge_color(unit)
|
||||||
|
))
|
||||||
|
hud_unit_badge_row.add_child(_make_hud_unit_badge(
|
||||||
|
"동" if _unit_pixel_facing(unit) >= 0 else "서",
|
||||||
|
_hud_unit_badge_tooltip("시선 %s\n등 뒤를 잡히면 피해가 커집니다." % _unit_facing_text(unit), detail_text),
|
||||||
|
Color(0.24, 0.20, 0.12, 0.98)
|
||||||
|
))
|
||||||
|
|
||||||
|
var hp_max := maxi(1, int(unit.get("max_hp", 1)))
|
||||||
|
var hp_ratio := float(clampi(int(unit.get("hp", 0)), 0, hp_max)) / float(hp_max)
|
||||||
|
if hp_ratio <= LOW_HP_WARNING_RATIO:
|
||||||
|
hud_unit_badge_row.add_child(_make_hud_unit_badge(
|
||||||
|
"위",
|
||||||
|
_hud_unit_badge_tooltip("병력이 크게 낮습니다.", detail_text),
|
||||||
|
Color(0.56, 0.055, 0.028, 0.99)
|
||||||
|
))
|
||||||
|
|
||||||
|
var marker_kinds := _unit_status_marker_kinds(unit)
|
||||||
|
if not marker_kinds.is_empty():
|
||||||
|
var marker_kind := marker_kinds[0]
|
||||||
|
hud_unit_badge_row.add_child(_make_hud_unit_badge(
|
||||||
|
_unit_status_marker_glyph(marker_kind),
|
||||||
|
_hud_unit_badge_tooltip("상태 표식\n자세한 효과는 아래 상세를 확인합니다.", detail_text),
|
||||||
|
_unit_status_marker_color(marker_kind),
|
||||||
|
"",
|
||||||
|
_unit_status_marker_text_color(marker_kind)
|
||||||
|
))
|
||||||
|
|
||||||
|
for action_badge in _hud_unit_action_badges(unit, detail_text):
|
||||||
|
var action_color: Color = action_badge.get("color", Color(0.18, 0.10, 0.04, 0.98))
|
||||||
|
hud_unit_badge_row.add_child(_make_hud_unit_badge(
|
||||||
|
str(action_badge.get("text", "")),
|
||||||
|
str(action_badge.get("tooltip", "")),
|
||||||
|
action_color,
|
||||||
|
str(action_badge.get("icon", ""))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
func _make_hud_unit_badge(
|
||||||
|
label_text: String,
|
||||||
|
tooltip: String,
|
||||||
|
fill_color: Color,
|
||||||
|
icon_kind: String = "",
|
||||||
|
text_color: Color = UI_PARCHMENT_TEXT
|
||||||
|
) -> PanelContainer:
|
||||||
|
var panel := PanelContainer.new()
|
||||||
|
panel.custom_minimum_size = HUD_UNIT_BADGE_SIZE
|
||||||
|
panel.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||||
|
panel.tooltip_text = tooltip
|
||||||
|
panel.add_theme_stylebox_override(
|
||||||
|
"panel",
|
||||||
|
_make_panel_style(fill_color, fill_color.lightened(0.34), 1, 2, 2, 0)
|
||||||
|
)
|
||||||
|
if not icon_kind.strip_edges().is_empty():
|
||||||
|
var icon := TextureRect.new()
|
||||||
|
icon.custom_minimum_size = Vector2(22, 18)
|
||||||
|
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||||
|
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||||
|
icon.texture = _make_toolbar_icon(icon_kind)
|
||||||
|
icon.tooltip_text = tooltip
|
||||||
|
panel.add_child(icon)
|
||||||
|
return panel
|
||||||
|
|
||||||
|
var label := Label.new()
|
||||||
|
label.text = label_text
|
||||||
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
label.custom_minimum_size = Vector2(HUD_UNIT_BADGE_SIZE.x - 4.0, HUD_UNIT_BADGE_SIZE.y - 4.0)
|
||||||
|
label.tooltip_text = tooltip
|
||||||
|
_apply_label_style(label, text_color, 11)
|
||||||
|
panel.add_child(label)
|
||||||
|
return panel
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_badge_tooltip(primary_text: String, detail_text: String) -> String:
|
||||||
|
if detail_text.strip_edges().is_empty():
|
||||||
|
return primary_text
|
||||||
|
return "%s\n%s" % [primary_text, detail_text]
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_team_badge_text(unit: Dictionary) -> String:
|
||||||
|
var team := str(unit.get("team", ""))
|
||||||
|
if team == BattleState.TEAM_PLAYER:
|
||||||
|
return "아"
|
||||||
|
if team == BattleState.TEAM_ENEMY:
|
||||||
|
return "적"
|
||||||
|
return "중"
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_team_badge_color(unit: Dictionary) -> Color:
|
||||||
|
var team := str(unit.get("team", ""))
|
||||||
|
if team == BattleState.TEAM_PLAYER:
|
||||||
|
return Color(0.11, 0.30, 0.22, 0.99)
|
||||||
|
if team == BattleState.TEAM_ENEMY:
|
||||||
|
return Color(0.48, 0.045, 0.028, 0.99)
|
||||||
|
return Color(0.24, 0.22, 0.16, 0.99)
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_class_badge_text(unit: Dictionary) -> String:
|
||||||
|
var class_id := str(unit.get("class_id", "")).to_lower()
|
||||||
|
if class_id.contains("cavalry"):
|
||||||
|
return "기"
|
||||||
|
if class_id.contains("archer") or class_id.contains("marksman"):
|
||||||
|
return "궁"
|
||||||
|
if class_id.contains("strategist") or class_id.contains("advisor"):
|
||||||
|
return "책"
|
||||||
|
if class_id.contains("hero") or class_id.contains("commander"):
|
||||||
|
return "장"
|
||||||
|
if class_id.contains("warrior") or class_id.contains("champion") or class_id.contains("bandit"):
|
||||||
|
return "무"
|
||||||
|
return "보"
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_class_badge_color(unit: Dictionary) -> Color:
|
||||||
|
var class_id := str(unit.get("class_id", "")).to_lower()
|
||||||
|
if class_id.contains("cavalry"):
|
||||||
|
return Color(0.52, 0.24, 0.070, 0.99)
|
||||||
|
if class_id.contains("archer") or class_id.contains("marksman"):
|
||||||
|
return Color(0.18, 0.31, 0.14, 0.99)
|
||||||
|
if class_id.contains("strategist") or class_id.contains("advisor"):
|
||||||
|
return Color(0.15, 0.22, 0.38, 0.99)
|
||||||
|
if class_id.contains("hero") or class_id.contains("commander"):
|
||||||
|
return Color(0.44, 0.055, 0.032, 0.99)
|
||||||
|
if class_id.contains("warrior") or class_id.contains("champion") or class_id.contains("bandit"):
|
||||||
|
return Color(0.37, 0.15, 0.055, 0.99)
|
||||||
|
return Color(0.24, 0.19, 0.10, 0.99)
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_action_badges(unit: Dictionary, detail_text: String) -> Array:
|
||||||
|
var result := []
|
||||||
|
var unit_id := str(unit.get("id", ""))
|
||||||
|
if unit_id.is_empty():
|
||||||
|
result.append(_hud_unit_action_badge("봉", "", "봉인", "명령할 수 없는 표식입니다.", detail_text, Color(0.20, 0.16, 0.11, 0.98)))
|
||||||
|
return result
|
||||||
|
var team := str(unit.get("team", ""))
|
||||||
|
if team != BattleState.TEAM_PLAYER:
|
||||||
|
result.append(_hud_unit_action_badge("적", "threat", "적군", "직접 명령할 수 없습니다.", detail_text, Color(0.48, 0.045, 0.028, 0.99)))
|
||||||
|
return result
|
||||||
|
if not bool(unit.get("controllable", true)):
|
||||||
|
result.append(_hud_unit_action_badge("호", "", "호위", "호위 대상은 직접 명령할 수 없습니다.", detail_text, Color(0.31, 0.23, 0.12, 0.98)))
|
||||||
|
return result
|
||||||
|
if not bool(unit.get("alive", true)) or not bool(unit.get("deployed", true)) or bool(unit.get("acted", false)):
|
||||||
|
result.append(_hud_unit_action_badge("봉", "", "봉인", "이 부대는 이미 행동했거나 출진하지 않았습니다.", detail_text, Color(0.20, 0.16, 0.11, 0.98)))
|
||||||
|
return result
|
||||||
|
var phase_block := _action_phase_block_reason()
|
||||||
|
if not phase_block.is_empty():
|
||||||
|
result.append(_hud_unit_action_badge("대", "", str(phase_block.get("label", "대기")), str(phase_block.get("tooltip", "")), detail_text, Color(0.20, 0.16, 0.11, 0.98)))
|
||||||
|
return result
|
||||||
|
if not bool(unit.get("moved", false)) and not state.get_movement_range(unit_id).is_empty():
|
||||||
|
result.append(_hud_unit_action_badge("행", "move", "행군", "이동 가능한 칸이 있습니다.", detail_text, Color(0.34, 0.23, 0.070, 0.99)))
|
||||||
|
if not state.get_attack_cells(unit_id).is_empty():
|
||||||
|
result.append(_hud_unit_action_badge("타", "attack", "타격", "무기로 공격할 수 있습니다.", detail_text, Color(0.46, 0.055, 0.032, 0.99)))
|
||||||
|
var skill_id := state.get_first_usable_skill_id(unit_id)
|
||||||
|
if not skill_id.is_empty() and _unit_has_usable_skill_target(unit_id):
|
||||||
|
result.append(_hud_unit_action_badge("책", "tactic", "책략", "쓸 수 있는 책략 표식이 있습니다.", detail_text, Color(0.12, 0.24, 0.36, 0.99)))
|
||||||
|
if _unit_has_usable_item_target(unit_id):
|
||||||
|
result.append(_hud_unit_action_badge("도", "item", "도구", "사용 가능한 도구 대상이 있습니다.", detail_text, Color(0.18, 0.31, 0.16, 0.99)))
|
||||||
|
if not bool(unit.get("moved", false)):
|
||||||
|
result.append(_hud_unit_action_badge("병", "equip", "병장", "행군 전 병장을 바꿀 수 있습니다.", detail_text, Color(0.33, 0.18, 0.060, 0.99)))
|
||||||
|
result.append(_hud_unit_action_badge("대", "wait", "대기", "이 부대의 행동을 마칠 수 있습니다.", detail_text, Color(0.22, 0.16, 0.09, 0.99)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func _hud_unit_action_badge(
|
||||||
|
text: String,
|
||||||
|
icon_kind: String,
|
||||||
|
label: String,
|
||||||
|
hint: String,
|
||||||
|
detail_text: String,
|
||||||
|
color: Color
|
||||||
|
) -> Dictionary:
|
||||||
|
return {
|
||||||
|
"text": text,
|
||||||
|
"icon": icon_kind,
|
||||||
|
"color": color,
|
||||||
|
"tooltip": _hud_unit_badge_tooltip("%s\n%s" % [label, hint], detail_text)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func _format_local_command_tooltip(label: String, hint: String) -> String:
|
func _format_local_command_tooltip(label: String, hint: String) -> String:
|
||||||
var normalized_label := label.strip_edges()
|
var normalized_label := label.strip_edges()
|
||||||
var normalized_hint := hint.strip_edges()
|
var normalized_hint := hint.strip_edges()
|
||||||
@@ -904,6 +1111,13 @@ func _make_toolbar_icon(kind: String) -> Texture2D:
|
|||||||
var shadow := Color(0.07, 0.028, 0.012, 0.82)
|
var shadow := Color(0.07, 0.028, 0.012, 0.82)
|
||||||
var red := Color(UI_SEAL_RED.r, UI_SEAL_RED.g, UI_SEAL_RED.b, 1.0)
|
var red := Color(UI_SEAL_RED.r, UI_SEAL_RED.g, UI_SEAL_RED.b, 1.0)
|
||||||
match kind:
|
match kind:
|
||||||
|
"move":
|
||||||
|
_icon_line(image, Vector2i(8, 22), Vector2i(16, 9), shadow, 5)
|
||||||
|
_icon_line(image, Vector2i(16, 9), Vector2i(24, 22), shadow, 5)
|
||||||
|
_icon_line(image, Vector2i(8, 22), Vector2i(16, 9), ink, 3)
|
||||||
|
_icon_line(image, Vector2i(16, 9), Vector2i(24, 22), ink, 3)
|
||||||
|
_icon_line(image, Vector2i(11, 22), Vector2i(21, 22), ink, 3)
|
||||||
|
_icon_circle(image, Vector2i(16, 9), 3, red)
|
||||||
"end_turn":
|
"end_turn":
|
||||||
_icon_line(image, Vector2i(7, 10), Vector2i(22, 10), shadow, 4)
|
_icon_line(image, Vector2i(7, 10), Vector2i(22, 10), shadow, 4)
|
||||||
_icon_line(image, Vector2i(21, 10), Vector2i(21, 22), shadow, 4)
|
_icon_line(image, Vector2i(21, 10), Vector2i(21, 22), shadow, 4)
|
||||||
@@ -1631,6 +1845,12 @@ func _create_hud() -> void:
|
|||||||
_apply_label_style(selected_label, UI_PARCHMENT_TEXT, 13)
|
_apply_label_style(selected_label, UI_PARCHMENT_TEXT, 13)
|
||||||
hud_unit_info_column.add_child(selected_label)
|
hud_unit_info_column.add_child(selected_label)
|
||||||
|
|
||||||
|
hud_unit_badge_row = HBoxContainer.new()
|
||||||
|
hud_unit_badge_row.custom_minimum_size = HUD_UNIT_BADGE_ROW_SIZE
|
||||||
|
hud_unit_badge_row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
hud_unit_badge_row.add_theme_constant_override("separation", 3)
|
||||||
|
hud_unit_info_column.add_child(hud_unit_badge_row)
|
||||||
|
|
||||||
var hp_row := _make_hud_unit_resource_row("병력", Color(0.66, 0.12, 0.075, 1.0))
|
var hp_row := _make_hud_unit_resource_row("병력", Color(0.66, 0.12, 0.075, 1.0))
|
||||||
hud_unit_hp_bar = hp_row["bar"] as ProgressBar
|
hud_unit_hp_bar = hp_row["bar"] as ProgressBar
|
||||||
hud_unit_info_column.add_child(hp_row["row"] as Control)
|
hud_unit_info_column.add_child(hp_row["row"] as Control)
|
||||||
@@ -6131,11 +6351,13 @@ func _update_hud() -> void:
|
|||||||
if hovered_unit.is_empty():
|
if hovered_unit.is_empty():
|
||||||
selected_label.text = "전장 관망"
|
selected_label.text = "전장 관망"
|
||||||
selected_label.tooltip_text = "마우스를 부대 위에 올리면 상세 군세가 표시됩니다."
|
selected_label.tooltip_text = "마우스를 부대 위에 올리면 상세 군세가 표시됩니다."
|
||||||
|
_update_hud_unit_badges({}, selected_label.tooltip_text)
|
||||||
_update_hud_unit_resource_bars({}, selected_label.tooltip_text)
|
_update_hud_unit_resource_bars({}, selected_label.tooltip_text)
|
||||||
else:
|
else:
|
||||||
var hover_detail := _format_unit_focus_text(hovered_unit, "Hover")
|
var hover_detail := _format_unit_focus_text(hovered_unit, "Hover")
|
||||||
selected_label.text = _format_unit_focus_summary_text(hovered_unit, "Hover")
|
selected_label.text = _format_unit_focus_summary_text(hovered_unit, "Hover")
|
||||||
selected_label.tooltip_text = hover_detail
|
selected_label.tooltip_text = hover_detail
|
||||||
|
_update_hud_unit_badges(hovered_unit, hover_detail)
|
||||||
_update_hud_unit_resource_bars(hovered_unit, hover_detail)
|
_update_hud_unit_resource_bars(hovered_unit, hover_detail)
|
||||||
_update_wait_button({})
|
_update_wait_button({})
|
||||||
_update_tactic_button({})
|
_update_tactic_button({})
|
||||||
@@ -6149,6 +6371,7 @@ func _update_hud() -> void:
|
|||||||
var selected_detail := _format_unit_focus_text(selected, "Selected")
|
var selected_detail := _format_unit_focus_text(selected, "Selected")
|
||||||
selected_label.text = _format_unit_focus_summary_text(selected, "Selected")
|
selected_label.text = _format_unit_focus_summary_text(selected, "Selected")
|
||||||
selected_label.tooltip_text = selected_detail
|
selected_label.tooltip_text = selected_detail
|
||||||
|
_update_hud_unit_badges(selected, selected_detail)
|
||||||
_update_hud_unit_resource_bars(selected, selected_detail)
|
_update_hud_unit_resource_bars(selected, selected_detail)
|
||||||
_update_wait_button(selected)
|
_update_wait_button(selected)
|
||||||
_update_tactic_button(selected)
|
_update_tactic_button(selected)
|
||||||
@@ -6264,21 +6487,13 @@ func _format_unit_focus_summary_text(unit: Dictionary, prefix: String) -> String
|
|||||||
return "표식 없는 빈 전장입니다."
|
return "표식 없는 빈 전장입니다."
|
||||||
var name := str(unit.get("name", "부대"))
|
var name := str(unit.get("name", "부대"))
|
||||||
var control_label := " 호위" if not bool(unit.get("controllable", true)) else ""
|
var control_label := " 호위" if not bool(unit.get("controllable", true)) else ""
|
||||||
var status_text := _unit_action_status_text(unit).replace("군령: ", "")
|
return "%s: %s%s\n%s 품계 %d · %s" % [
|
||||||
var status_parts := status_text.split(",", false)
|
|
||||||
if status_parts.size() > 3:
|
|
||||||
var visible_parts: Array[String] = []
|
|
||||||
for index in range(3):
|
|
||||||
visible_parts.append(str(status_parts[index]).strip_edges())
|
|
||||||
status_text = "%s 외 %d" % [_join_strings(visible_parts, ", "), status_parts.size() - 3]
|
|
||||||
return "%s: %s%s\n%s 품계 %d · %s\n군령: %s" % [
|
|
||||||
_unit_focus_prefix_text(prefix),
|
_unit_focus_prefix_text(prefix),
|
||||||
name,
|
name,
|
||||||
control_label,
|
control_label,
|
||||||
_unit_team_text(str(unit.get("team", ""))),
|
_unit_team_text(str(unit.get("team", ""))),
|
||||||
int(unit.get("level", 1)),
|
int(unit.get("level", 1)),
|
||||||
_unit_class_display_name(unit),
|
_unit_class_display_name(unit)
|
||||||
status_text
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -10013,14 +10228,14 @@ func _format_inventory_status_summary_text() -> String:
|
|||||||
other_count += count
|
other_count += count
|
||||||
var parts: Array[String] = []
|
var parts: Array[String] = []
|
||||||
if consumable_count > 0:
|
if consumable_count > 0:
|
||||||
parts.append("소모 %d" % consumable_count)
|
parts.append("소 %d" % consumable_count)
|
||||||
if equipment_count > 0:
|
if equipment_count > 0:
|
||||||
parts.append("병장 %d" % equipment_count)
|
parts.append("병 %d" % equipment_count)
|
||||||
if other_count > 0:
|
if other_count > 0:
|
||||||
parts.append("잡물 %d" % other_count)
|
parts.append("잡 %d" % other_count)
|
||||||
if parts.is_empty():
|
if parts.is_empty():
|
||||||
return "군수: 없음"
|
return "군수 없음"
|
||||||
return "군수: %s" % _join_strings(parts, " · ")
|
return _join_strings(parts, " · ")
|
||||||
|
|
||||||
|
|
||||||
func _format_reward_items(items: Array) -> String:
|
func _format_reward_items(items: Array) -> String:
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ func _check_hud_reuses_status_summary(failures: Array[String]) -> void:
|
|||||||
if scene.selected_label.text.contains("상태:"):
|
if scene.selected_label.text.contains("상태:"):
|
||||||
failures.append("selected HUD should keep status effects in tooltip/markers, not visible text: %s" % scene.selected_label.text)
|
failures.append("selected HUD should keep status effects in tooltip/markers, not visible text: %s" % scene.selected_label.text)
|
||||||
_check_contains(failures, "selected HUD status tooltip", scene.selected_label.tooltip_text, "상태: 방비 -2 (2회)")
|
_check_contains(failures, "selected HUD status tooltip", scene.selected_label.tooltip_text, "상태: 방비 -2 (2회)")
|
||||||
|
if scene.hud_unit_badge_row == null or not scene.hud_unit_badge_row.visible:
|
||||||
|
failures.append("selected HUD should keep status effects discoverable through compact badges")
|
||||||
|
else:
|
||||||
|
_check_contains(failures, "selected badge status tooltip", scene.hud_unit_badge_row.tooltip_text, "상태: 방비 -2 (2회)")
|
||||||
_check_contains(failures, "selected HP bar status tooltip", scene.hud_unit_hp_bar.tooltip_text, "상태: 방비 -2 (2회)")
|
_check_contains(failures, "selected HP bar status tooltip", scene.hud_unit_hp_bar.tooltip_text, "상태: 방비 -2 (2회)")
|
||||||
_check_contains(failures, "hover tile tooltip status", scene.cell_info_label.tooltip_text, "상태: 방비 -2 (2회)")
|
_check_contains(failures, "hover tile tooltip status", scene.cell_info_label.tooltip_text, "상태: 방비 -2 (2회)")
|
||||||
scene.state.clear_selection()
|
scene.state.clear_selection()
|
||||||
|
|||||||
@@ -3058,6 +3058,24 @@ func _check_hud_focus_text(failures: Array[String]) -> void:
|
|||||||
failures.append("selected HP bar tooltip should preserve unit detail: %s" % scene.hud_unit_hp_bar.tooltip_text)
|
failures.append("selected HP bar tooltip should preserve unit detail: %s" % scene.hud_unit_hp_bar.tooltip_text)
|
||||||
if scene.selected_label.text.contains("병력") or scene.selected_label.text.contains("기력"):
|
if scene.selected_label.text.contains("병력") or scene.selected_label.text.contains("기력"):
|
||||||
failures.append("selected label should not duplicate HP/MP bars: %s" % scene.selected_label.text)
|
failures.append("selected label should not duplicate HP/MP bars: %s" % scene.selected_label.text)
|
||||||
|
if scene.selected_label.text.contains("군령:"):
|
||||||
|
failures.append("selected label should move command availability into visual badges: %s" % scene.selected_label.text)
|
||||||
|
if scene.inventory_label == null or scene.inventory_label.text.contains("군수:") or scene.inventory_label.text.contains("소모") or scene.inventory_label.text.contains("병장"):
|
||||||
|
failures.append("inventory HUD summary should stay compact and leave details to tooltip: %s" % ("" if scene.inventory_label == null else scene.inventory_label.text))
|
||||||
|
elif not scene.inventory_label.tooltip_text.contains("군수:"):
|
||||||
|
failures.append("inventory HUD tooltip should preserve full inventory detail: %s" % scene.inventory_label.tooltip_text)
|
||||||
|
if scene.hud_unit_badge_row == null or not scene.hud_unit_badge_row.visible:
|
||||||
|
failures.append("selected unit HUD should expose compact hover badges")
|
||||||
|
else:
|
||||||
|
var badge_tooltips := _collect_child_tooltips(scene.hud_unit_badge_row)
|
||||||
|
if scene.hud_unit_badge_row.get_child_count() < 6:
|
||||||
|
failures.append("selected unit HUD should show role/facing/action badges, got %d" % scene.hud_unit_badge_row.get_child_count())
|
||||||
|
if not badge_tooltips.contains("시선 동쪽") or not badge_tooltips.contains("등 뒤"):
|
||||||
|
failures.append("selected unit facing badge should explain directional defense: %s" % badge_tooltips)
|
||||||
|
if not badge_tooltips.contains("행군") or not badge_tooltips.contains("타격") or not badge_tooltips.contains("대기"):
|
||||||
|
failures.append("selected unit action badges should expose available commands through tooltips: %s" % badge_tooltips)
|
||||||
|
if not _has_descendant_texture(scene.hud_unit_badge_row):
|
||||||
|
failures.append("selected unit action badges should use icon imagery, not only text")
|
||||||
var xiahou_dun: Dictionary = scene.state.get_unit("xiahou_dun")
|
var xiahou_dun: Dictionary = scene.state.get_unit("xiahou_dun")
|
||||||
xiahou_dun["pos"] = Vector2i(4, 1)
|
xiahou_dun["pos"] = Vector2i(4, 1)
|
||||||
var forest_text := scene._unit_current_terrain_text(xiahou_dun)
|
var forest_text := scene._unit_current_terrain_text(xiahou_dun)
|
||||||
@@ -3468,6 +3486,36 @@ func _find_descendant_by_name(root: Node, node_name: String) -> Node:
|
|||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
func _collect_child_tooltips(root: Node) -> String:
|
||||||
|
if root == null:
|
||||||
|
return ""
|
||||||
|
var parts: Array[String] = []
|
||||||
|
_collect_child_tooltips_into(root, parts)
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
func _collect_child_tooltips_into(root: Node, parts: Array[String]) -> void:
|
||||||
|
if root == null:
|
||||||
|
return
|
||||||
|
if root is Control:
|
||||||
|
var tooltip := str((root as Control).tooltip_text).strip_edges()
|
||||||
|
if not tooltip.is_empty():
|
||||||
|
parts.append(tooltip)
|
||||||
|
for child in root.get_children():
|
||||||
|
_collect_child_tooltips_into(child, parts)
|
||||||
|
|
||||||
|
|
||||||
|
func _has_descendant_texture(root: Node) -> bool:
|
||||||
|
if root == null:
|
||||||
|
return false
|
||||||
|
if root is TextureRect and (root as TextureRect).texture != null:
|
||||||
|
return true
|
||||||
|
for child in root.get_children():
|
||||||
|
if _has_descendant_texture(child):
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
func _check_local_command_icon_button(failures: Array[String], button: Button, expected_label: String, expected_icon: String) -> void:
|
func _check_local_command_icon_button(failures: Array[String], button: Button, expected_label: String, expected_icon: String) -> void:
|
||||||
if button == null:
|
if button == null:
|
||||||
failures.append("local command button missing: %s" % expected_label)
|
failures.append("local command button missing: %s" % expected_label)
|
||||||
|
|||||||
Reference in New Issue
Block a user