feat(ai-specific): Implement combat resolution logic for WildCreatureAI to enhance strategic behavior during combat

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-16 00:36:54 -07:00
parent 75a5cdc0cf
commit 2a3f459bb2

View file

@ -9,6 +9,7 @@ const UnitScript = preload("res://engine/src/entities/unit.gd")
const HexUtilsScript = preload("res://engine/src/map/hex_utils.gd")
const PathfinderScript = preload("res://engine/src/map/pathfinder.gd")
const UnitManagerScript = preload("res://engine/src/modules/management/unit_manager.gd")
const CombatResolverScript = preload("res://engine/src/modules/combat/combat_resolver.gd")
const DEFAULT_DETECTION_RADIUS: int = 4
const DEFAULT_LEASH_RADIUS: int = 5
@ -93,10 +94,21 @@ func _act(
var home_pos: Vector2i = _find_nearest_lair(
unit.position, leash_radius + detection_radius
)
var target_pos: Variant = _find_attack_target(unit, detection_radius)
var target: RefCounted = _find_attack_target(unit, detection_radius)
if target_pos != null:
_move_toward(unit, target_pos, game_map)
if target != null:
# Step toward target, then attack if adjacent and still able.
if HexUtilsScript.hex_distance(unit.position, target.position) > 1:
_move_toward(unit, target.position, game_map)
if (
HexUtilsScript.hex_distance(unit.position, target.position) <= 1
and not unit.has_attacked
):
var all_units: Array = GameState.get_primary_layer().get("units", [])
var resolver: RefCounted = CombatResolverScript.new()
resolver.resolve(unit, target, game_map, all_units)
unit.has_attacked = true
unit.movement_remaining = 0
elif _is_outside_leash(unit.position, home_pos, leash_radius):
_move_toward(unit, home_pos, game_map)
elif _rng.randi_range(1, 100) <= ROAM_CHANCE:
@ -106,26 +118,21 @@ func _act(
func _find_attack_target(
unit: RefCounted,
detection_radius: int,
) -> Variant:
) -> RefCounted:
## Returns the nearest player-owned unit within detection_radius, or null.
var primary_layer: Dictionary = GameState.get_primary_layer()
var candidates: Array[Dictionary] = []
var best: RefCounted = null
var best_dist: int = 999999
for other: Variant in primary_layer.get("units", []):
if not other is UnitScript:
continue
if other.owner < 0:
if not other is UnitScript or other.owner < 0 or not other.is_alive():
continue
var dist: int = HexUtilsScript.hex_distance(unit.position, other.position)
if dist <= detection_radius:
candidates.append({"pos": other.position, "dist": dist})
if dist <= detection_radius and dist < best_dist:
best_dist = dist
best = other
if candidates.is_empty():
return null
candidates.sort_custom(func(a: Dictionary, b: Dictionary) -> bool:
return a["dist"] < b["dist"]
)
return candidates[0]["pos"]
return best
func _find_nearest_lair(from_pos: Vector2i, search_radius: int) -> Vector2i: