diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index 71ac223..36970a9 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -6667,7 +6667,8 @@ func _attack_target_marker_entries() -> Array[Dictionary]: "text": marker_text, "kind": marker_kind, "icon": _target_preview_badge_icon_kind(marker_kind), - "panel": _target_marker_panel_key() + "panel": _target_marker_panel_key(), + "tooltip": _format_attack_target_hint(preview) }) if not basic_attack_targeting and not _has_pending_move(): _append_auto_attack_target_marker_entries(result, selected) @@ -8153,7 +8154,9 @@ func _attack_target_preview_badge(selected: Dictionary, target: Dictionary) -> D var result_text := "퇴각" if bool(preview.get("would_defeat", false)) else "-%d" % int(preview.get("damage", 0)) var directional_text := _format_directional_badge_suffix(preview) var counter_text := _format_attack_counter_badge_suffix(preview) - return _make_target_preview_badge("%s%s %d%%%s" % [result_text, directional_text, hit_chance, counter_text], _attack_preview_badge_kind(preview)) + var badge := _make_target_preview_badge("%s%s %d%%%s" % [result_text, directional_text, hit_chance, counter_text], _attack_preview_badge_kind(preview)) + badge["tooltip"] = _format_attack_target_hint(preview) + return badge func _format_directional_badge_suffix(preview: Dictionary) -> String: @@ -8242,6 +8245,31 @@ func _format_auto_attack_target_hint(preview: Dictionary) -> String: int(preview.get("damage", 0)), int(preview.get("hit_chance", 0)) ]) + var directional_line := _format_directional_tooltip_line(preview) + if not directional_line.is_empty(): + parts.append(directional_line) + if bool(preview.get("counter_in_range", false)): + var counter_text := "반격 %d, 명중 %d%%" % [ + int(preview.get("counter_damage", 0)), + int(preview.get("counter_hit_chance", 0)) + ] + if bool(preview.get("counter_would_defeat", false)): + counter_text += ", 아군 퇴각 위험" + parts.append(counter_text) + return "\n".join(parts) + + +func _format_attack_target_hint(preview: Dictionary) -> String: + if preview.is_empty(): + return "" + var parts: Array[String] = ["공격 예측"] + parts.append("피해 %d, 명중 %d%%" % [ + int(preview.get("damage", 0)), + int(preview.get("hit_chance", 0)) + ]) + var directional_line := _format_directional_tooltip_line(preview) + if not directional_line.is_empty(): + parts.append(directional_line) if bool(preview.get("counter_in_range", false)): var counter_text := "반격 %d, 명중 %d%%" % [ int(preview.get("counter_damage", 0)), @@ -10071,7 +10099,22 @@ func _format_directional_forecast_text(preview: Dictionary, bonus_key: String, l var label := str(preview.get(label_key, "방향")).strip_edges() if label.is_empty(): label = "방향" - return " (%s +%d)" % [label, bonus] + return " (%s 공격 +%d)" % [label, bonus] + + +func _format_directional_tooltip_line(preview: Dictionary, bonus_key: String = "directional_bonus", label_key: String = "directional_label") -> String: + var bonus := int(preview.get(bonus_key, 0)) + if bonus <= 0: + return "" + var label := str(preview.get(label_key, "방향")).strip_edges() + if label.is_empty(): + label = "방향" + var detail := "방향 보정으로 피해가 늘어납니다." + if label.contains("후"): + detail = "대상의 등 뒤에서 공격합니다." + elif label.contains("측"): + detail = "대상의 측면을 찌릅니다." + return "%s 공격 +%d 피해: %s" % [label, bonus, detail] func _update_skill_forecast(selected: Dictionary) -> void: diff --git a/tools/smoke_directional_combat.gd b/tools/smoke_directional_combat.gd index 93da8c3..717dea6 100644 --- a/tools/smoke_directional_combat.gd +++ b/tools/smoke_directional_combat.gd @@ -195,12 +195,18 @@ func _check_scene_directional_attack_badges(failures: Array[String]) -> void: var badge := scene._target_preview_badge() if not str(badge.get("text", "")).contains("후+%d" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): failures.append("rear attack hover badge should expose compact rear bonus: %s" % str(badge)) + if not str(badge.get("tooltip", "")).contains("후방 공격 +%d 피해" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): + failures.append("rear attack hover badge should explain rear damage in tooltip: %s" % str(badge)) var marker_text := "" + var marker_tooltip := "" for marker in scene._attack_target_marker_entries(): if str(marker.get("target_id", "")) == "yellow_turban_1": marker_text = str(marker.get("text", "")) + marker_tooltip = str(marker.get("tooltip", "")) if not marker_text.contains("후+%d" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): failures.append("rear attack target marker should expose compact rear bonus: %s" % marker_text) + if not marker_tooltip.contains("후방 공격 +%d 피해" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): + failures.append("rear attack target marker should explain rear damage in tooltip: %s" % marker_tooltip) attacker["pos"] = Vector2i(5, 8) scene._refresh_ranges() @@ -208,6 +214,8 @@ func _check_scene_directional_attack_badges(failures: Array[String]) -> void: var side_badge: Dictionary = scene._target_preview_badge() if not str(side_badge.get("text", "")).contains("측+%d" % BattleStateScript.DIRECTIONAL_SIDE_DAMAGE_BONUS): failures.append("side attack hover badge should expose compact side bonus: %s" % str(side_badge)) + if not str(side_badge.get("tooltip", "")).contains("측면 공격 +%d 피해" % BattleStateScript.DIRECTIONAL_SIDE_DAMAGE_BONUS): + failures.append("side attack hover badge should explain side damage in tooltip: %s" % str(side_badge)) attacker["pos"] = Vector2i(2, 9) attacker["facing_x"] = -1 @@ -220,9 +228,16 @@ func _check_scene_directional_attack_badges(failures: Array[String]) -> void: failures.append("auto-move attack hover badge should use a clear hint instead of jargon: %s" % str(auto_badge)) if not str(auto_badge.get("text", "")).contains("후+%d" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): failures.append("auto-move attack hover badge should expose compact rear bonus: %s" % str(auto_badge)) + if not str(auto_badge.get("tooltip", "")).contains("후방 공격 +%d 피해" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): + failures.append("auto-move attack hover badge should explain rear damage in tooltip: %s" % str(auto_badge)) if scene._compact_directional_badge_label(BattleStateScript.DIRECTIONAL_SIDE_ATTACK) != "측": failures.append("directional badge helper should compact side attacks") + if not scene._format_directional_forecast_text({ + "directional_bonus": BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS, + "directional_label": "후방" + }, "directional_bonus", "directional_label").contains("후방 공격 +%d" % BattleStateScript.DIRECTIONAL_BACK_DAMAGE_BONUS): + failures.append("directional forecast helper should explain rear attack bonus") if scene._format_directional_badge_suffix({ "directional_attack": BattleStateScript.DIRECTIONAL_FRONT_ATTACK, "directional_bonus": 0,