57 lines
1.8 KiB
GDScript
57 lines
1.8 KiB
GDScript
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
|