Show move attack targets
This commit is contained in:
@@ -3460,12 +3460,13 @@ func _draw_units() -> void:
|
||||
|
||||
|
||||
func _draw_target_selection_markers() -> void:
|
||||
if not _is_targeting_mode():
|
||||
var markers := _target_selection_marker_entries()
|
||||
if markers.is_empty():
|
||||
return
|
||||
var font := _draw_ui_font(true)
|
||||
for marker in _target_selection_marker_entries():
|
||||
for marker in markers:
|
||||
var cell: Vector2i = marker.get("cell", Vector2i(-1, -1))
|
||||
if not state.is_inside(cell):
|
||||
if not state.is_inside(cell) or not _cell_is_in_visible_bounds(cell):
|
||||
continue
|
||||
var rect := _rect_for_cell(cell)
|
||||
var marker_rect := Rect2(rect.position + Vector2(7.0, TILE_SIZE - 24.0), Vector2(TILE_SIZE - 14.0, 18.0))
|
||||
@@ -3521,9 +3522,49 @@ func _attack_target_marker_entries() -> Array[Dictionary]:
|
||||
"text": "%s %d%%" % [result_text, hit_chance],
|
||||
"kind": _attack_preview_badge_kind(preview)
|
||||
})
|
||||
if not basic_attack_targeting and not _has_pending_move():
|
||||
_append_auto_attack_target_marker_entries(result, selected)
|
||||
return result
|
||||
|
||||
|
||||
func _append_auto_attack_target_marker_entries(result: Array[Dictionary], selected: Dictionary) -> void:
|
||||
if selected.is_empty() or bool(selected.get("moved", false)) or bool(selected.get("acted", false)):
|
||||
return
|
||||
var current_cell: Vector2i = selected.get("pos", Vector2i(-1, -1))
|
||||
for target in state.units:
|
||||
if not bool(target.get("alive", false)) or not bool(target.get("deployed", true)):
|
||||
continue
|
||||
if target.get("team", "") == selected.get("team", ""):
|
||||
continue
|
||||
var target_id := str(target.get("id", ""))
|
||||
if target_id.is_empty() or _marker_entries_have_target(result, target_id):
|
||||
continue
|
||||
var attack_origin := _best_auto_attack_origin(selected, target)
|
||||
if attack_origin == Vector2i(-1, -1) or attack_origin == current_cell:
|
||||
continue
|
||||
var target_cell: Vector2i = target.get("pos", Vector2i(-1, -1))
|
||||
if not state.is_inside(target_cell):
|
||||
continue
|
||||
var badge := _auto_attack_target_preview_badge_for_origin(selected, target, attack_origin)
|
||||
if badge.is_empty():
|
||||
continue
|
||||
result.append({
|
||||
"cell": target_cell,
|
||||
"target_id": target_id,
|
||||
"text": "행공",
|
||||
"kind": str(badge.get("kind", "advance")),
|
||||
"origin": attack_origin,
|
||||
"requires_move": true
|
||||
})
|
||||
|
||||
|
||||
func _marker_entries_have_target(entries: Array[Dictionary], target_id: String) -> bool:
|
||||
for entry in entries:
|
||||
if str(entry.get("target_id", "")) == target_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _skill_target_marker_entries() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
if selected_skill_id.is_empty():
|
||||
@@ -3630,7 +3671,11 @@ func _try_auto_move_attack(selected: Dictionary, target: Dictionary) -> bool:
|
||||
|
||||
func _best_auto_attack_origin(selected: Dictionary, target: Dictionary) -> Vector2i:
|
||||
var unit_id := str(selected.get("id", ""))
|
||||
if unit_id.is_empty():
|
||||
var target_id := str(target.get("id", ""))
|
||||
if unit_id.is_empty() or target_id.is_empty():
|
||||
return Vector2i(-1, -1)
|
||||
var base_preview := state.get_damage_preview(unit_id, target_id)
|
||||
if base_preview.is_empty() or bool(base_preview.get("attack_locked", false)):
|
||||
return Vector2i(-1, -1)
|
||||
var current_cell: Vector2i = selected.get("pos", Vector2i(-1, -1))
|
||||
var target_cell: Vector2i = target.get("pos", Vector2i(-1, -1))
|
||||
@@ -4605,6 +4650,11 @@ func _target_preview_badge() -> Dictionary:
|
||||
if _has_pending_move() and not basic_attack_targeting:
|
||||
return {}
|
||||
var attack_badge := _attack_target_preview_badge(selected, target)
|
||||
if not attack_badge.is_empty() and (str(attack_badge.get("kind", "")) != "invalid" or basic_attack_targeting or _has_pending_move()):
|
||||
return attack_badge
|
||||
var auto_attack_badge := _auto_attack_target_preview_badge(selected, target)
|
||||
if not auto_attack_badge.is_empty():
|
||||
return auto_attack_badge
|
||||
if not attack_badge.is_empty():
|
||||
return attack_badge
|
||||
return _hover_intent_preview_badge(selected, target)
|
||||
@@ -4645,6 +4695,59 @@ func _attack_preview_badge_kind(preview: Dictionary) -> String:
|
||||
return "damage"
|
||||
|
||||
|
||||
func _auto_attack_target_preview_badge(selected: Dictionary, target: Dictionary) -> Dictionary:
|
||||
if selected.is_empty() or target.is_empty():
|
||||
return {}
|
||||
if selected.get("team", "") == target.get("team", ""):
|
||||
return {}
|
||||
if bool(selected.get("moved", false)) or bool(selected.get("acted", false)):
|
||||
return {}
|
||||
var current_cell: Vector2i = selected.get("pos", Vector2i(-1, -1))
|
||||
var attack_origin := _best_auto_attack_origin(selected, target)
|
||||
if attack_origin == Vector2i(-1, -1) or attack_origin == current_cell:
|
||||
return {}
|
||||
return _auto_attack_target_preview_badge_for_origin(selected, target, attack_origin)
|
||||
|
||||
|
||||
func _auto_attack_target_preview_badge_for_origin(selected: Dictionary, target: Dictionary, attack_origin: Vector2i) -> Dictionary:
|
||||
var target_cell: Vector2i = target.get("pos", Vector2i(-1, -1))
|
||||
if not state.is_inside(attack_origin) or not state.is_inside(target_cell):
|
||||
return {}
|
||||
var candidate_attacker := selected.duplicate(true)
|
||||
candidate_attacker["pos"] = attack_origin
|
||||
var damage := state.calculate_damage(candidate_attacker, target)
|
||||
var hit_chance := state.calculate_hit_chance(candidate_attacker, target)
|
||||
var result_text := "행공 퇴각" if int(target.get("hp", 0)) - damage <= 0 else "행공 -%d" % damage
|
||||
var counter_text := _format_auto_attack_counter_badge_suffix(candidate_attacker, target, damage)
|
||||
return _make_target_preview_badge_at("%s %d%%%s" % [result_text, hit_chance, counter_text], _auto_attack_preview_badge_kind(candidate_attacker, target, damage), target_cell)
|
||||
|
||||
|
||||
func _format_auto_attack_counter_badge_suffix(candidate_attacker: Dictionary, target: Dictionary, damage: int) -> String:
|
||||
if int(target.get("hp", 0)) - damage <= 0:
|
||||
return ""
|
||||
var origin: Vector2i = candidate_attacker.get("pos", Vector2i(-1, -1))
|
||||
var target_cell: Vector2i = target.get("pos", Vector2i(-1, -1))
|
||||
if not _can_attack_target_from(target, target_cell, origin):
|
||||
return ""
|
||||
var counter_damage := state.calculate_damage(target, candidate_attacker)
|
||||
if int(candidate_attacker.get("hp", 0)) - counter_damage <= 0:
|
||||
return " 반격!"
|
||||
return " 반%d" % counter_damage
|
||||
|
||||
|
||||
func _auto_attack_preview_badge_kind(candidate_attacker: Dictionary, target: Dictionary, damage: int) -> String:
|
||||
if int(target.get("hp", 0)) - damage <= 0:
|
||||
return "advance"
|
||||
var origin: Vector2i = candidate_attacker.get("pos", Vector2i(-1, -1))
|
||||
var target_cell: Vector2i = target.get("pos", Vector2i(-1, -1))
|
||||
if not _can_attack_target_from(target, target_cell, origin):
|
||||
return "advance"
|
||||
var counter_damage := state.calculate_damage(target, candidate_attacker)
|
||||
if int(candidate_attacker.get("hp", 0)) - counter_damage <= 0:
|
||||
return "danger"
|
||||
return "counter"
|
||||
|
||||
|
||||
func _skill_target_preview_badge(selected: Dictionary, target: Dictionary) -> Dictionary:
|
||||
return _skill_target_preview_badge_for_cell(selected, target, hover_cell)
|
||||
|
||||
@@ -4810,6 +4913,8 @@ func _target_preview_badge_color(kind: String) -> Color:
|
||||
return Color(1.0, 0.64, 0.22)
|
||||
if kind == "danger":
|
||||
return Color(1.0, 0.18, 0.14)
|
||||
if kind == "advance":
|
||||
return Color(0.44, 0.82, 0.76)
|
||||
if kind == "move":
|
||||
return Color(0.38, 0.70, 1.0)
|
||||
if kind == "select":
|
||||
|
||||
Reference in New Issue
Block a user