extends Node3D class_name TowerNavigationAgent # How close do we want to get to the target before finishing navigation @export var target_distance: float = 2.0 # How close do we need to get to path points before advancing to the next one @export var next_position_distance: float = 2.0 # How far can we get from the path before giving up and recalculating @export var recalculate_distance: float = 5.0 var navigation_grid: NavigationGrid var target_position: Vector3 var last_target_position: Vector3 var path : PackedVector3Array = [] var next_point_idx: int = 0 var grid: NavigationGrid func _ready() -> void: var node: Node = self while !node is NavigationGrid and node.get_parent() != null: node = node.get_parent() grid = node as NavigationGrid func get_next_path_position() -> Vector3: if _ensure_path(): if global_position.distance_to(path[next_point_idx]) <= next_position_distance: next_point_idx = min(next_point_idx+1, path.size()-1) return path[next_point_idx] else: return Vector3() func get_movement_direction() -> Vector3: return get_next_path_position() - global_position func is_target_reachable() -> bool: return _ensure_path() func is_navigation_finished() -> bool: _ensure_path() return path.is_empty() func _ensure_path() -> bool: if target_position.is_zero_approx(): return false var recalculate_needed: bool = path.is_empty() \ or target_position.distance_to(last_target_position) >= target_distance \ or global_position.distance_to(path[next_point_idx]) >= recalculate_distance if recalculate_needed: var start_pos: int = grid.grid.get_closest_point(global_position) var end_pos: int = grid.grid.get_closest_point(target_position) path = grid.grid.get_point_path(start_pos, end_pos) next_point_idx = 0 return !path.is_empty() return true