Files
mmo/scripts/enemy/enemy.gd
2026-03-29 16:51:06 +02:00

59 lines
1.7 KiB
GDScript

extends CharacterBody3D
enum State { IDLE, CHASE, ATTACK, RETURN }
var state: int = State.IDLE
var target: Node3D = null
var spawn_position: Vector3
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")
EventBus.entity_died.connect(_on_entity_died)
EventBus.damage_dealt.connect(_on_damage_dealt)
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 _on_damage_dealt(attacker: Node, damage_target: Node, _amount: float) -> void:
if damage_target == self and attacker.name == "Player":
_engage(attacker)
func _engage(new_target: Node3D) -> void:
if state == State.CHASE or state == State.ATTACK:
return
target = new_target
state = State.CHASE
_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):
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