44 lines
1.4 KiB
GDScript
44 lines
1.4 KiB
GDScript
extends Node3D
|
|
class_name Detector
|
|
|
|
@export var enabled: bool = true
|
|
@export var detection_range: float = 200.0
|
|
@export var requires_los: bool = true
|
|
@export_flags_3d_physics var los_physics_layers: int = 0b001
|
|
@export var detected_group_name: StringName = "Enemies"
|
|
@export var scan_period: float = 0.1
|
|
@export var debug_draw: bool = true
|
|
|
|
var scan_timer: float = 0.0
|
|
|
|
func _process(delta: float) -> void:
|
|
if enabled:
|
|
scan_timer += delta
|
|
if scan_timer >= scan_period:
|
|
scan_timer -= scan_period
|
|
scan()
|
|
|
|
func scan() -> void:
|
|
for node in get_tree().get_nodes_in_group(detected_group_name):
|
|
var enemy: Enemy = node as Enemy
|
|
if enemy != null and !enemy.sighted and can_see(enemy):
|
|
enemy.sighted = true
|
|
|
|
func can_see(enemy: Enemy) -> bool:
|
|
var distance: float = enemy.global_position.distance_to(global_position)
|
|
if distance >= detection_range:
|
|
return false
|
|
if requires_los:
|
|
var params: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(global_position, enemy.global_position)
|
|
params.collision_mask = los_physics_layers
|
|
var result: Dictionary = get_world_3d().direct_space_state.intersect_ray(params)
|
|
if debug_draw:
|
|
TowerUtil.draw_raycast_hit(params, result, 1.0)
|
|
#DebugDraw3D.draw_line_hit(global_position, enemy.global_position, result[''] is_hit)
|
|
if result.has("collider"):
|
|
if result.get("collider") == enemy:
|
|
return true
|
|
return false # something's in the way
|
|
return true
|
|
|