From 3fa58bc6df66fc1b5fe3e94762328ab9b2da46f3 Mon Sep 17 00:00:00 2001 From: Nekojimi Date: Mon, 12 May 2025 11:19:52 +0100 Subject: [PATCH] Add "Chase" unit action, and make enemies use it to chase citizens. --- scripts/units/action.gd | 41 +++++++++++++++++++++++++++++++++++++++++ scripts/units/enemy.gd | 8 +++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/scripts/units/action.gd b/scripts/units/action.gd index e1a7e5d..a341522 100644 --- a/scripts/units/action.gd +++ b/scripts/units/action.gd @@ -53,6 +53,47 @@ class MoveAction extends UnitAction: #DebugDraw3D.draw_text(global_position + Vector3(0,1,0), "%f" % nav_agent_3d.distance_to_target()) return Unit.TaskStatus.IN_PROGRESS +class ChaseAction extends UnitAction: + var target: Unit + var target_position: Vector3 + var last_distance_to_target: float = 99999999.9 + var stuck_timer: float = 0.0 + + func process(delta: float) -> Unit.TaskStatus: + if target == null or target.is_queued_for_deletion(): + return Unit.TaskStatus.IMPOSSIBLE + if target.global_position.distance_squared_to(target_position) >= 4.0: + # TODO: we could try to intercept the target by: + # - calculating our approximate time to reach the target + # - forcasting the target's position that time in the future based on it's velocity + # - do a raycast in that direction to prevent the future position from going through a wall + target_position = target.global_position + unit.nav_agent_3d.target_position = target_position + + if unit.nav_agent_3d.is_navigation_finished(): + if unit.nav_agent_3d.is_target_reachable(): + return Unit.TaskStatus.DONE + else: + return Unit.TaskStatus.IMPOSSIBLE + else: + var next_point: Vector3 = unit.nav_agent_3d.get_next_path_position() + if unit.shapecast_3d.is_colliding(): + var distance_to_target: float = unit.global_position.distance_to(next_point) + var progress_rate: float = (last_distance_to_target - distance_to_target) / delta + last_distance_to_target = distance_to_target + if progress_rate < unit.minimum_progress_rate: + stuck_timer += delta + if stuck_timer >= unit.stuck_time: + unit.unstuck() + else: + unit.label_3d.modulate = Color.WHITE + stuck_timer = 0 + DebugDraw3D.draw_sphere(unit.nav_agent_3d.target_position, 0.5, Color.RED) + var direction: Vector3 = (next_point - unit.global_position).normalized() + unit.target_velocity = direction * unit.max_speed + unit.nav_agent_3d.velocity = unit.target_velocity + return Unit.TaskStatus.IN_PROGRESS + class BuildAction extends UnitAction: var building: Building diff --git a/scripts/units/enemy.gd b/scripts/units/enemy.gd index aeca187..d19afaa 100644 --- a/scripts/units/enemy.gd +++ b/scripts/units/enemy.gd @@ -8,4 +8,10 @@ var sighted: bool = true: func _ready() -> void: sighted = false - go_to_destination(Vector3(17,1,15)) + var target_citizen: Citizen = get_tree().get_nodes_in_group("Citizens").pick_random() as Citizen + if target_citizen != null: + var chase_action: UnitAction.ChaseAction = UnitAction.ChaseAction.new() + chase_action.unit = self + chase_action.target = target_citizen + action = chase_action + #go_to_destination(Vector3(17,1,15))