2025-05-11 20:00:22 +01:00
|
|
|
extends RefCounted
|
|
|
|
class_name UnitAction
|
|
|
|
|
|
|
|
var unit: Unit = null
|
|
|
|
var time_limit: float = 300.0
|
|
|
|
|
|
|
|
func process(delta: float) -> Unit.TaskStatus:
|
|
|
|
time_limit -= delta
|
|
|
|
if time_limit <= 0:
|
|
|
|
return Unit.TaskStatus.TIMED_OUT
|
|
|
|
return Unit.TaskStatus.DONE
|
|
|
|
|
|
|
|
class MoveAction extends UnitAction:
|
|
|
|
var last_distance_to_target: float = 99999999.9
|
|
|
|
var stuck_timer: float = 0.0
|
|
|
|
var move_target: Vector3 = Vector3(16, 1, 13):
|
|
|
|
set(target):
|
|
|
|
move_target = target
|
|
|
|
unit.nav_agent_3d.target_position = move_target
|
|
|
|
|
|
|
|
func process(delta: float) -> Unit.TaskStatus:
|
|
|
|
if unit.nav_agent_3d.is_navigation_finished():
|
|
|
|
#task_updated.emit(TaskStatus.DONE)
|
|
|
|
unit.target_velocity = Vector3()
|
|
|
|
#nav_agent_3d.target_position = move_target + Vector3(randfn(0, move_radius), 0, randfn(0, move_radius))
|
|
|
|
#nav_agent_3d.target_position = NavigationServer3D.map_get_random_point(NavigationServer3D.get_maps()[0], 1, true)
|
|
|
|
#last_distance_to_target = nav_agent_3d.distance_to_target()
|
|
|
|
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)
|
|
|
|
#DebugDraw3D.draw_sphere(next_point, 0.1, Color.YELLOW)
|
|
|
|
var direction: Vector3 = (next_point - unit.global_position).normalized()
|
|
|
|
#basis = Basis.looking_at(direction)
|
|
|
|
#DebugDraw3D.draw_line(global_position, global_position + linear_velocity, Color.BLUE)
|
|
|
|
unit.target_velocity = direction * unit.max_speed
|
|
|
|
unit.nav_agent_3d.velocity = unit.target_velocity
|
|
|
|
#DebugDraw3D.draw_line(global_position, global_positiaon + target_velocity, Color.MAGENTA)
|
|
|
|
#DebugDraw3D.draw_text(global_position + Vector3(0,1,0), "%f" % nav_agent_3d.distance_to_target())
|
|
|
|
return Unit.TaskStatus.IN_PROGRESS
|
|
|
|
|
2025-05-12 11:19:52 +01:00
|
|
|
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
|
|
|
|
|
2025-05-11 20:00:22 +01:00
|
|
|
class BuildAction extends UnitAction:
|
|
|
|
var building: Building
|
|
|
|
|
|
|
|
func process(delta: float) -> Unit.TaskStatus:
|
|
|
|
if building == null or building.is_queued_for_deletion():
|
|
|
|
return Unit.TaskStatus.IMPOSSIBLE
|
|
|
|
building.build_progress += delta
|
|
|
|
if building.build_state == Building.BuildState.READY:
|
|
|
|
return Unit.TaskStatus.DONE
|
|
|
|
elif building.build_state != Building.BuildState.BUILDING:
|
|
|
|
return Unit.TaskStatus.IMPOSSIBLE # can't build if the building's not there
|
|
|
|
else:
|
|
|
|
return Unit.TaskStatus.IN_PROGRESS
|
|
|
|
|
|
|
|
class RepairAction extends UnitAction:
|
|
|
|
var building: Building
|
|
|
|
|
|
|
|
func process(delta: float) -> Unit.TaskStatus:
|
|
|
|
if building == null or building.is_queued_for_deletion() or building.build_state != Building.BuildState.READY:
|
|
|
|
return Unit.TaskStatus.IMPOSSIBLE
|
|
|
|
building.hp += delta * 10.0
|
|
|
|
if building.hp >= building.max_hp:
|
|
|
|
building.hp = building.max_hp
|
|
|
|
return Unit.TaskStatus.DONE
|
|
|
|
return Unit.TaskStatus.IN_PROGRESS
|