diff --git a/README.md b/README.md index 85db248..b209d74 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr - Ally and enemy phase changes raise compact command notices in the active battle HUD. - Enemy AI with movement, damage-aware physical attacks, multiple MP tactic choices, and scenario target priorities that events can retune mid-battle. - Hover tile and unit info with class, movement type, AGI, movement, range, and equipped gear. -- Active battle unit list opens from the top toolbar with ally/enemy tabs, portrait or sprite rows, compact HP/status/position badges, and hover combat details. +- Active battle unit list opens from the top toolbar with ally/enemy tabs, portrait or sprite rows, compact HP/status/zone badges, and hover combat details. - Enemy threat range overlay with tile-level threat source, physical damage hints, and hostile tactic hints. - Scrollable battle maps show a clickable minimap with terrain, unit, objective, and event hover badges. - Damage forecast for selected-unit attacks. @@ -32,7 +32,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr - Sishui Gate now opens with camp dialogue that turns the coalition briefing into a spoken march order. - 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, with portrait rows, coordinate badges, and hover placement instructions. +- Pre-battle Formation lets deployed officers swap starting positions inside scenario-defined cells, with portrait rows, readable zone 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 prep commands use compact icon buttons with active selection state and Korean hover labels for chapters, shop, talks, armory, roster, formation, and save records. - Core UI panels now use a calmer ink/wood/jade palette with restrained rounded corners instead of the earlier yellow, hard-edged frame treatment. diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index 6063233..e412e3e 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -11107,7 +11107,7 @@ func _format_battle_unit_list_row_badges(unit: Dictionary) -> Array: _unit_class_display_name(unit), "병 %d%%" % hp_percent, _battle_unit_action_state_text(unit), - "좌 %s" % _format_cell_label(unit.get("pos", Vector2i(-1, -1))) + _battle_zone_label(unit.get("pos", Vector2i(-1, -1))) ] @@ -12115,7 +12115,7 @@ func _add_formation_unit_row(unit: Dictionary, selected: bool) -> void: func _format_formation_unit_badges(unit: Dictionary, selected: bool) -> Array: return [ "선택" if selected else "대상", - "좌표 %s" % _format_cell_label(unit.get("pos", Vector2i.ZERO)), + "배치 %s" % _battle_zone_label(unit.get("pos", Vector2i.ZERO)), _unit_class_display_name(unit) ] @@ -12137,11 +12137,49 @@ func _format_formation_unit_tooltip(unit: Dictionary, selected: bool) -> String: func _format_cell_label(value) -> String: - if typeof(value) == TYPE_VECTOR2I: - return "%d,%d" % [value.x + 1, value.y + 1] + var cell := _cell_label_value_to_vector(value) + if cell.x >= 0 and cell.y >= 0: + return "%d,%d" % [cell.x + 1, cell.y + 1] return "-" +func _cell_label_value_to_vector(value) -> Vector2i: + if typeof(value) == TYPE_VECTOR2I: + return value + if typeof(value) == TYPE_ARRAY: + var array_value: Array = value + if array_value.size() >= 2: + return Vector2i(int(array_value[0]), int(array_value[1])) + return Vector2i(-1, -1) + + +func _battle_zone_label(value) -> String: + var cell := _cell_label_value_to_vector(value) + if cell.x < 0 or cell.y < 0 or state == null or not state.is_inside(cell): + return "위치 미상" + + var terrain_key := state.get_terrain_key(cell) + if terrain_key == "C": + return "성채" + if terrain_key == "T": + return "마을" + if terrain_key == "W": + return "하천" + if terrain_key == "F": + return "숲길" + if terrain_key == "H": + return "산지" + + var width := maxi(1, state.map_size.x) + var left_cut := int(floor(float(width) / 3.0)) + var right_cut := int(ceil(float(width) * 2.0 / 3.0)) + if cell.x < left_cut: + return "서측" + if cell.x >= right_cut: + return "동측" + return "중앙" + + func _on_formation_unit_pressed(unit_id: String) -> void: _play_ui_click() formation_unit_id = unit_id diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 60ce0ed..c3aa800 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3034,9 +3034,9 @@ func _check_scene_texture_loading(failures: Array[String]) -> void: 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("선택"): + 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("클릭하면"): + if formation_visible_text.contains("좌표") or 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) @@ -3821,8 +3821,10 @@ func _check_battle_unit_list_panel(failures: Array[String]) -> void: failures.append("ally battle unit list should show Cao Cao and Xiahou Dun") var ally_visible_text := _collect_child_text(scene.battle_unit_list_rows) var ally_tooltips := _collect_child_tooltips(scene.battle_unit_list_rows) - if not ally_visible_text.contains("지휘관") or not ally_visible_text.contains("병 ") or not ally_visible_text.contains("좌 "): - failures.append("ally battle unit list should show compact class, HP, and position badges: %s" % ally_visible_text) + if not ally_visible_text.contains("지휘관") or not ally_visible_text.contains("병 ") or not ally_visible_text.contains("서측"): + failures.append("ally battle unit list should show compact class, HP, and zone badges: %s" % ally_visible_text) + if ally_visible_text.contains("좌 "): + failures.append("ally battle unit list should keep raw coordinates out of visible badges: %s" % ally_visible_text) if ally_visible_text.contains("군령:") or ally_visible_text.contains("행군 4") or ally_visible_text.contains("타격 1-1"): failures.append("ally battle unit list rows should keep dense combat detail in hover text: %s" % ally_visible_text) if not ally_tooltips.contains("군세") or not ally_tooltips.contains("클릭하면 이 장수를 선택"): @@ -3846,8 +3848,12 @@ func _check_battle_unit_list_panel(failures: Array[String]) -> void: failures.append("enemy battle unit list should include the enemy commander") var enemy_visible_text := _collect_child_text(scene.battle_unit_list_rows) var enemy_tooltips := _collect_child_tooltips(scene.battle_unit_list_rows) - if not enemy_visible_text.contains("적") or not enemy_visible_text.contains("병 ") or not enemy_visible_text.contains("좌 "): + if not enemy_visible_text.contains("적") or not enemy_visible_text.contains("병 "): failures.append("enemy battle unit list should show compact status badges: %s" % enemy_visible_text) + if not enemy_visible_text.contains("성채") and not enemy_visible_text.contains("동측"): + failures.append("enemy battle unit list should show a readable zone badge instead of raw coordinates: %s" % enemy_visible_text) + if enemy_visible_text.contains("좌 "): + failures.append("enemy battle unit list should keep raw coordinates out of visible badges: %s" % enemy_visible_text) if enemy_visible_text.contains("군령:") or enemy_visible_text.contains("직접 명령"): failures.append("enemy battle unit list rows should keep dense enemy detail in hover text: %s" % enemy_visible_text) if not enemy_tooltips.contains("군령: 적군 군기") or not enemy_tooltips.contains("클릭하면 위치로 이동"):