161 lines
4.9 KiB
GDScript3
161 lines
4.9 KiB
GDScript3
|
extends RigidBody2D
|
||
|
|
||
|
class_name Unit
|
||
|
|
||
|
enum TaskStatus {
|
||
|
INTERRUPTED,
|
||
|
DESTINATION_REACHED,
|
||
|
ITEM_PICKED_UP,
|
||
|
ITEM_DROPPED,
|
||
|
}
|
||
|
signal task_updated(task_status: TaskStatus)
|
||
|
|
||
|
@export var movement_force: float = 100
|
||
|
@export var max_speed: float = 10
|
||
|
@export var path_give_up_theshold: float = 96.0
|
||
|
@export var stuck_speed: float = 5.0
|
||
|
@export var stuck_time: float = 1.0
|
||
|
@export var target_distance: float = 64.0
|
||
|
|
||
|
static var splat_scene: PackedScene = preload("res://objects/splat.tscn")
|
||
|
var moving: bool = false
|
||
|
var target: Vector2 = Vector2(1628, 1565):
|
||
|
set(value):
|
||
|
moving = true
|
||
|
target = value
|
||
|
find_path()
|
||
|
var path: PackedVector2Array
|
||
|
var path_ptr: int = 0
|
||
|
var stuck_timer: float = 0.0
|
||
|
var stuck: bool = false
|
||
|
|
||
|
var facing: float = 0.1
|
||
|
|
||
|
func _process(delta: float) -> void:
|
||
|
#$PathDebugLine.global_position = Vector2()
|
||
|
if moving:
|
||
|
if global_position.distance_squared_to(target) > target_distance**2:
|
||
|
move(delta)
|
||
|
else:
|
||
|
moving = false
|
||
|
send_task_update(TaskStatus.DESTINATION_REACHED)
|
||
|
|
||
|
func move(delta: float) -> void:
|
||
|
var direction: Vector2
|
||
|
if !stuck:
|
||
|
var last_path_point: Vector2 = get_last_path_point()
|
||
|
var path_point: Vector2 = get_next_path_point()
|
||
|
# find out how far we are from the path
|
||
|
var prev_dist_sqr: float = position.distance_squared_to(last_path_point) if !last_path_point.is_zero_approx() else 999999
|
||
|
var next_dist_sqr: float = position.distance_squared_to(path_point)
|
||
|
# if we're too far from the path, give up on it and find a new one
|
||
|
if next_dist_sqr > (path_give_up_theshold ** 2):
|
||
|
find_path()
|
||
|
path_point = get_next_path_point()
|
||
|
# if we've reached the path point, move to the next one
|
||
|
if next_dist_sqr < prev_dist_sqr:
|
||
|
path_ptr += 1
|
||
|
path_point = get_next_path_point()
|
||
|
|
||
|
#var direction: Vector2 = (Vector2(randf() - 0.5, randf() - 0.5) * 2) * 10000
|
||
|
direction = (path_point - position).normalized()
|
||
|
else:
|
||
|
direction = (Vector2(randf() - 0.5, randf() - 0.5) * 2)
|
||
|
|
||
|
facing = direction.angle()
|
||
|
|
||
|
var target_velocity: Vector2 = direction * max_speed
|
||
|
var force: Vector2 = ((target_velocity - linear_velocity) / max_speed) * movement_force
|
||
|
apply_force(force)
|
||
|
#$ForceDebugLine.points[1] = force
|
||
|
|
||
|
if linear_velocity.length() < stuck_speed:
|
||
|
stuck_timer += delta
|
||
|
if stuck_timer >= stuck_time:
|
||
|
global_position = get_next_path_point()
|
||
|
stuck_timer = 0
|
||
|
#set_stuck_mode(true)
|
||
|
else:
|
||
|
#if stuck:
|
||
|
#set_stuck_mode(false)
|
||
|
stuck_timer = 0
|
||
|
|
||
|
func get_last_path_point() -> Vector2:
|
||
|
if path == null or path.is_empty():
|
||
|
find_path()
|
||
|
if path_ptr >= path.size() and path.size() >= 2:
|
||
|
return path[-2]
|
||
|
if path.size() <= 1:
|
||
|
return Vector2()
|
||
|
if path != null and !path.is_empty():
|
||
|
return $"..".map_to_local(path[path_ptr - 1])
|
||
|
else:
|
||
|
return Vector2()
|
||
|
|
||
|
func get_next_path_point() -> Vector2:
|
||
|
if path == null or path.is_empty():
|
||
|
find_path()
|
||
|
if path_ptr >= path.size() and !path.is_empty():
|
||
|
return path[-1]
|
||
|
if path != null and !path.is_empty():
|
||
|
return $"..".map_to_local(path[path_ptr])
|
||
|
else:
|
||
|
return position
|
||
|
|
||
|
func find_path() -> void:
|
||
|
path_ptr = 0
|
||
|
var astar_grid: AStarGrid2D = $"..".astar_grid
|
||
|
if astar_grid == null:
|
||
|
return
|
||
|
var source_coords: Vector2i = $"..".local_to_map(position)
|
||
|
var target_coords: Vector2i = $"..".local_to_map(target)
|
||
|
path = astar_grid.get_point_path(source_coords, target_coords, true)
|
||
|
|
||
|
var debug_points: PackedVector2Array
|
||
|
#debug_points.resize(path.size())
|
||
|
for point in path:
|
||
|
#var point: Vector2 = path[idx]
|
||
|
var global_point: Vector2 = $"..".map_to_local(point)
|
||
|
debug_points.append(global_point)
|
||
|
#$PathDebugLine.points = debug_points
|
||
|
|
||
|
func set_stuck_mode(stk: bool) -> void:
|
||
|
stuck = stk
|
||
|
$Sprite2D.modulate = Color(0.75, 0.25, 1.0) if stuck else Color(1,1,1,1)
|
||
|
var astar_grid: AStarGrid2D = $"..".astar_grid
|
||
|
if astar_grid == null:
|
||
|
return
|
||
|
var source_coords: Vector2i = $"..".local_to_map(position)
|
||
|
if stuck:
|
||
|
astar_grid.set_point_weight_scale(source_coords, astar_grid.get_point_weight_scale(source_coords) * 50)
|
||
|
else:
|
||
|
astar_grid.set_point_weight_scale(source_coords, astar_grid.get_point_weight_scale(source_coords) / 50)
|
||
|
|
||
|
func send_task_update(task_status: TaskStatus) -> void:
|
||
|
task_updated.emit(task_status)
|
||
|
|
||
|
func wait_for_task_status(task_status: TaskStatus) -> bool:
|
||
|
while true:
|
||
|
var status_received: TaskStatus = await task_updated;
|
||
|
if status_received == task_status:
|
||
|
return true
|
||
|
elif status_received == TaskStatus.INTERRUPTED:
|
||
|
return false
|
||
|
return false
|
||
|
|
||
|
func go_to_destination(destination: Vector2) -> bool:
|
||
|
target = destination
|
||
|
return await wait_for_task_status(TaskStatus.DESTINATION_REACHED)
|
||
|
|
||
|
func kill() -> void:
|
||
|
#var astar_grid: AStarGrid2D = $"..".astar_grid
|
||
|
#var source_coords: Vector2i = $"..".local_to_map(position)
|
||
|
#var scale: float = astar_grid.get_point_weight_scale(source_coords)
|
||
|
#print("Tile %s weight scale read: %f" % [source_coords, scale])
|
||
|
#astar_grid.set_point_weight_scale(source_coords, scale + 0.1)
|
||
|
var splat: Node2D = splat_scene.instantiate()
|
||
|
splat.global_position = global_position
|
||
|
add_sibling(splat)
|
||
|
|
||
|
queue_free()
|