diff --git a/src/game/engine/src/modules/ai/wild_creature_ai.gd b/src/game/engine/src/modules/ai/wild_creature_ai.gd index 167aaed2..527edd73 100644 --- a/src/game/engine/src/modules/ai/wild_creature_ai.gd +++ b/src/game/engine/src/modules/ai/wild_creature_ai.gd @@ -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: