106 lines
2.5 KiB
GDScript
106 lines
2.5 KiB
GDScript
extends KinematicBody2D
|
|
|
|
signal enemy_killed
|
|
signal enemy_damaged
|
|
|
|
var navi : Navigation2D
|
|
onready var sprite : AnimatedSprite = $AnimatedSprite
|
|
onready var aggro_area : Area2D = $AggroArea
|
|
onready var look : RayCast2D = $Look
|
|
onready var collision_shape : CollisionShape2D = $CollisionShape2D
|
|
onready var aggro_collision : CollisionShape2D = $AggroArea/AggroRadius
|
|
onready var attack_area : Area2D = $AttackArea
|
|
onready var stun_timer : Timer = $StunTimer
|
|
|
|
var target : Player
|
|
var input_vec : Vector2 = Vector2.ZERO
|
|
var player_seen : bool = false
|
|
export var hp : int = 3
|
|
export var attack_speed : float = 3.0
|
|
var since_attack : float = 0
|
|
var stunned : bool = false
|
|
|
|
func take_damage(damage : int):
|
|
hp -= damage
|
|
stun_timer.start()
|
|
stunned = true
|
|
if hp <= 0:
|
|
emit_signal("enemy_killed")
|
|
queue_free()
|
|
return
|
|
emit_signal("enemy_damaged")
|
|
player_seen = true
|
|
|
|
func _ready():
|
|
look.add_exception(collision_shape)
|
|
look.add_exception(aggro_collision)
|
|
|
|
func set_nav(nav : Navigation2D):
|
|
navi = nav
|
|
|
|
func search_player():
|
|
if target != null:
|
|
var enemy_to_player = target.global_position - self.global_position
|
|
look.cast_to = enemy_to_player
|
|
if look.is_colliding():
|
|
var collider = look.get_collider()
|
|
if collider == target:
|
|
player_seen = true
|
|
|
|
func try_attack() -> bool:
|
|
if target == null:
|
|
return false
|
|
if !target.is_alive():
|
|
return true
|
|
if attack_area.overlaps_body(target):
|
|
if target.has_method("take_damage") and since_attack <= 0:
|
|
target.take_damage(1)
|
|
since_attack = attack_speed
|
|
return true
|
|
return false
|
|
|
|
func _process(delta):
|
|
since_attack -= delta
|
|
if since_attack < 0:
|
|
since_attack = 0
|
|
if target == null:
|
|
return
|
|
elif navi != null and player_seen:
|
|
var path : PoolVector2Array = navi.get_simple_path(self.global_position, target.global_position)
|
|
if path.size() >= 1:
|
|
input_vec = (path[1] - position).normalized()
|
|
|
|
var abs_y = abs(input_vec.y)
|
|
var abs_x = abs(input_vec.x)
|
|
|
|
if input_vec.x < 0:
|
|
sprite.animation = "side"
|
|
sprite.flip_h = true
|
|
elif input_vec.x > 0:
|
|
sprite.animation = "side"
|
|
sprite.flip_h = false
|
|
|
|
if input_vec.y < 0:
|
|
sprite.animation = "up"
|
|
elif input_vec.y > 0:
|
|
sprite.animation = "down"
|
|
|
|
if abs_y < abs_x:
|
|
sprite.animation = "side"
|
|
|
|
func _physics_process(delta):
|
|
if !player_seen:
|
|
search_player()
|
|
elif try_attack():
|
|
return
|
|
var speed = 80
|
|
if stunned:
|
|
speed = 40
|
|
move_and_slide(input_vec.normalized() * speed, Vector2.UP)
|
|
|
|
func _on_AggroArea_body_entered(body):
|
|
if body.has_method("is_player") and body.is_player():
|
|
target = body
|
|
|
|
func _on_StunTimer_timeout():
|
|
stunned = false
|