59 lines
1.6 KiB
GDScript
59 lines
1.6 KiB
GDScript
extends CharacterBody3D
|
|
|
|
enum State { IDLE, CHASE, ATTACK, RETURN }
|
|
|
|
var state: int = State.IDLE
|
|
var target: Node3D = null
|
|
var spawn_position: Vector3
|
|
var portal: Node3D = null
|
|
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
|
|
|
@onready var health: Node = $Health
|
|
|
|
func _ready() -> void:
|
|
spawn_position = global_position
|
|
add_to_group("enemies")
|
|
add_to_group("targetable")
|
|
EventBus.entity_died.connect(_on_entity_died)
|
|
|
|
func _on_entity_died(entity: Node) -> void:
|
|
if entity == self:
|
|
queue_free()
|
|
elif entity == target:
|
|
target = null
|
|
state = State.RETURN
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if not is_on_floor():
|
|
velocity.y -= gravity * delta
|
|
move_and_slide()
|
|
|
|
func _engage(new_target: Node3D) -> void:
|
|
if state == State.CHASE or state == State.ATTACK:
|
|
return
|
|
target = new_target
|
|
state = State.CHASE
|
|
var aggro: Node = get_node_or_null("EnemyAggro")
|
|
if aggro:
|
|
aggro.add_aggro(new_target, 1.0)
|
|
_alert_nearby()
|
|
|
|
func _alert_nearby() -> void:
|
|
var enemies := get_tree().get_nodes_in_group("enemies")
|
|
for enemy in enemies:
|
|
if enemy != self and is_instance_valid(enemy) and "state" in enemy:
|
|
if enemy.state == enemy.State.IDLE:
|
|
var dist: float = global_position.distance_to(enemy.global_position)
|
|
if dist <= 3.0:
|
|
enemy._engage(target)
|
|
|
|
func _on_detection_area_body_entered(body: Node3D) -> void:
|
|
if body is CharacterBody3D and body.name == "Player":
|
|
_engage(body)
|
|
EventBus.enemy_engaged.emit(self, body)
|
|
|
|
func _on_detection_area_body_exited(body: Node3D) -> void:
|
|
if body == target and state == State.CHASE:
|
|
state = State.RETURN
|
|
target = null
|