2025-03-26 18:55:43 +01:00
|
|
|
extends CharacterBody3D
|
|
|
|
|
class_name Enemy
|
|
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
|
2025-08-30 15:46:36 +02:00
|
|
|
signal died
|
|
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
|
2025-09-16 22:14:22 +02:00
|
|
|
const DEATH_PARTICLE : PackedScene = preload("uid://ddm57pv5ox171")
|
|
|
|
|
const SAD_PARTICLE : PackedScene = preload("uid://m0vj2ac5oesx")
|
|
|
|
|
|
2025-04-02 18:02:13 +02:00
|
|
|
|
2025-09-06 21:45:37 +02:00
|
|
|
@export var speed : float = 1
|
2025-04-04 17:56:56 +02:00
|
|
|
@export var base_attack_damage : int = 1
|
2025-09-02 19:49:40 +02:00
|
|
|
@export var max_life : int = 5
|
|
|
|
|
@export var money : int = 5
|
2025-06-18 12:19:43 +02:00
|
|
|
|
2025-04-02 18:02:13 +02:00
|
|
|
var health : int = 0 :
|
2025-03-26 18:55:43 +01:00
|
|
|
set(value):
|
|
|
|
|
health = value
|
2025-04-02 18:02:13 +02:00
|
|
|
if health >= max_life and is_alive:
|
2025-03-26 18:55:43 +01:00
|
|
|
death()
|
|
|
|
|
|
2025-09-04 02:54:37 +02:00
|
|
|
@onready var path : PathFollow3D = get_parent()
|
2025-09-02 19:49:40 +02:00
|
|
|
@onready var healthBar : ProgressBar = $HealthBar3D/SubViewport/HealthBar2D
|
2025-04-02 18:02:13 +02:00
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
var targets : Array[Node3D]
|
2025-03-26 18:55:43 +01:00
|
|
|
var is_alive : bool = true
|
2025-09-04 02:54:37 +02:00
|
|
|
|
2025-03-26 18:55:43 +01:00
|
|
|
|
2025-04-02 18:02:13 +02:00
|
|
|
func _ready() -> void:
|
2025-09-02 19:49:40 +02:00
|
|
|
healthBar.max_value = max_life
|
2025-03-26 18:55:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
2025-04-02 18:02:13 +02:00
|
|
|
if !is_alive:
|
|
|
|
|
return
|
2025-08-30 15:46:36 +02:00
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
if not attack():
|
2025-09-04 02:54:37 +02:00
|
|
|
path.progress += speed * delta
|
2025-03-26 18:55:43 +01:00
|
|
|
|
|
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
func take_damage(damage: int) -> void:
|
2025-04-02 18:02:13 +02:00
|
|
|
health += damage
|
2025-09-02 19:49:40 +02:00
|
|
|
healthBar.value = health
|
2025-03-26 18:55:43 +01:00
|
|
|
|
2025-09-04 02:54:37 +02:00
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
func attack() -> bool:
|
|
|
|
|
if targets.is_empty():
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
|
|
var cubeTarget : Array[Node3D] = targets.filter(func(b): return b is TheCube)
|
|
|
|
|
if $AttackCooldown.is_stopped() && not cubeTarget.is_empty():
|
|
|
|
|
cubeTarget[0].take_damage(base_attack_damage)
|
2025-04-04 17:56:56 +02:00
|
|
|
$AttackCooldown.start()
|
2025-09-06 17:32:46 +02:00
|
|
|
path.progress = 0
|
2025-09-14 01:31:18 +02:00
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
return false
|
2025-04-04 17:56:56 +02:00
|
|
|
|
2025-03-26 18:55:43 +01:00
|
|
|
|
|
|
|
|
func death() -> void:
|
|
|
|
|
is_alive = false
|
2025-08-30 15:46:36 +02:00
|
|
|
died.emit()
|
2025-09-04 17:59:23 +02:00
|
|
|
Game.money += money
|
2025-04-02 18:02:13 +02:00
|
|
|
$Sprite3D.visible = false
|
2025-09-16 22:14:22 +02:00
|
|
|
var death_vfx : CPUParticles3D = DEATH_PARTICLE.instantiate()
|
2025-04-02 18:02:13 +02:00
|
|
|
get_tree().current_scene.add_child(death_vfx)
|
|
|
|
|
death_vfx.global_position = global_position
|
2025-09-04 02:54:37 +02:00
|
|
|
path.queue_free()
|
2025-04-04 17:56:56 +02:00
|
|
|
|
|
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
func onAttackRangeBodyEntered(body: Node3D) -> void:
|
|
|
|
|
if (body is TheCube || body is Tower) && not targets.has(body):
|
|
|
|
|
targets.append(body)
|
2025-06-18 12:19:43 +02:00
|
|
|
|
|
|
|
|
|
2025-09-14 01:31:18 +02:00
|
|
|
func onAttackRangeBodyExited(body: Node3D) -> void:
|
|
|
|
|
targets.erase(body)
|