extends CharacterBody2D @export var speed := 75.0 @export var gravity := 980.0 @export var max_health := 3 @export var attack_range := 40.0 @export var memory_piece_scene: PackedScene @export var memory_texture: Texture2D @export var memory_return_spawn: Marker2D @export var memory_wardrobe: Node2D @onready var sprite: AnimatedSprite2D = $AnimatedSprite2D @onready var detection_area: Area2D = $DetectionArea @onready var attack_hitbox = $AttackHitbox var health := 3 var player: Player = null var is_dead := false var is_hurt := false var is_attacking := false var attack_cooldown := false var knockback_velocity := Vector2.ZERO func _ready() -> void: health = max_health attack_hitbox.monitoring = false sprite.play("idle") detection_area.body_entered.connect(_on_detection_body_entered) detection_area.body_exited.connect(_on_detection_body_exited) sprite.animation_finished.connect(_on_animation_finished) func _physics_process(delta: float) -> void: if is_dead: return if not is_on_floor(): velocity.y += gravity * delta if is_hurt: velocity = knockback_velocity knockback_velocity = knockback_velocity.move_toward( Vector2.ZERO, 800 * delta ) move_and_slide() return if is_attacking: velocity.x = 0 move_and_slide() return if player: var direction := player.global_position.x - global_position.x if abs(direction) > attack_range: velocity.x = sign(direction) * speed sprite.play("walk") if velocity.x < 0: sprite.flip_h = true elif velocity.x > 0: sprite.flip_h = false else: velocity.x = 0 attack() else: velocity.x = move_toward(velocity.x, 0, speed) sprite.play("idle") move_and_slide() func attack() -> void: if is_attacking: return if attack_cooldown: return is_attacking = true attack_cooldown = true velocity.x = 0 sprite.play("attack") await get_tree().create_timer(0.2).timeout do_attack_damage() func do_attack_damage() -> void: print("Checking attack hit") attack_hitbox.monitoring = true await get_tree().physics_frame await get_tree().physics_frame var bodies = attack_hitbox.get_overlapping_bodies() print("Bodies found: ", bodies.size()) for body in bodies: if body is Player: print("PLAYER HIT") body.playerTakesDamage(1) attack_hitbox.monitoring = false func take_damage(amount: int = 1) -> void: if is_dead: return health -= amount print("Skeleton health:", health) if health <= 0: die() else: is_hurt = true if player: var knockback_direction = sign(global_position.x - player.global_position.x) knockback_velocity = Vector2(knockback_direction * 125, 0) sprite.play("hurt") await get_tree().create_timer(0.3).timeout is_hurt = false knockback_velocity = Vector2.ZERO func die() -> void: if is_dead: return is_dead = true velocity.x = 0 sprite.play("death") print("Skeleton died") func _on_detection_body_entered(body: Node) -> void: if body is Player: player = body print("Skeleton detected player") func _on_detection_body_exited(body: Node) -> void: if body == player: player = null print("Skeleton lost player") func _on_animation_finished() -> void: if sprite.animation == "hurt": is_hurt = false knockback_velocity = Vector2.ZERO if sprite.animation == "attack": is_attacking = false await get_tree().create_timer(1.0).timeout attack_cooldown = false if sprite.animation == "death": if memory_piece_scene: var piece = memory_piece_scene.instantiate() get_parent().add_child(piece) piece.global_position = global_position piece.memory_texture = memory_texture piece.return_spawn = memory_return_spawn piece.wardrobe = memory_wardrobe queue_free()