extends CharacterBody2D signal health_changed(current_hp: int, max_hp: int) var camera var is_casting = false var fireball = preload("res://scenes/fireball.tscn") var shuriken = preload("res://scenes/shuriken.tscn") var fire_swirl = preload("res://scenes/fire_swirl.tscn") var shuriken_count = 1 var max_hp: int = 100 var current_hp: int = 100 var is_invincible: bool = false const HP_BAR_WIDTH = 20 const HP_BAR_HEIGHT = 3 var _hp_bar_fill: ColorRect func _ready() -> void: $CauldronBar.witch = self camera = get_node("/root/Game/Camera2D") _setup_hp_bar() func _setup_hp_bar() -> void: var bg = ColorRect.new() bg.color = Color(0.15, 0.15, 0.15, 0.85) bg.size = Vector2(HP_BAR_WIDTH, HP_BAR_HEIGHT) bg.position = Vector2(-HP_BAR_WIDTH / 2.0, 18) add_child(bg) _hp_bar_fill = ColorRect.new() _hp_bar_fill.color = Color(0.85, 0.1, 0.1, 1.0) _hp_bar_fill.size = Vector2(HP_BAR_WIDTH, HP_BAR_HEIGHT) _hp_bar_fill.position = Vector2(-HP_BAR_WIDTH / 2.0, 18) add_child(_hp_bar_fill) func _update_hp_bar() -> void: _hp_bar_fill.size.x = HP_BAR_WIDTH * (float(current_hp) / float(max_hp)) func _physics_process(delta: float) -> void: # Add the gravity. pass func _on_collect(DropsBase): if is_casting: return $CauldronBar.progres_bar(DropsBase) func shoot_fireballs(): var enemies = get_tree().get_nodes_in_group("enemies") for enemy in enemies: var fb = fireball.instantiate() fb.global_position = global_position get_parent().add_child(fb) fb.launch(enemy.global_position) camera.shake(0.3,0.8) func shoot_fire_swirl(): var fs = fire_swirl.instantiate() fs.global_position = global_position get_parent().add_child(fs) camera.shake(0.3, 0.8) func shoot_shuriken(): for i in range(shuriken_count): var sh = shuriken.instantiate() sh.global_position = global_position get_parent().add_child(sh) await get_tree().create_timer(0.2).timeout func take_damage(amount: int) -> void: if is_invincible: return current_hp -= amount current_hp = max(current_hp, 0) health_changed.emit(current_hp, max_hp) _update_hp_bar() if current_hp <= 0: get_tree().call_deferred("reload_current_scene") return is_invincible = true await get_tree().create_timer(1.0).timeout is_invincible = false func get_nearest_enemy(from: Vector2, filter: Callable = Callable()) -> Node: var nearest = null var min_distance = INF for enemy in get_tree().get_nodes_in_group("enemies"): if filter.is_valid() and not filter.call(enemy): continue var dist = from.distance_to(enemy.global_position) if dist < min_distance: min_distance = dist nearest = enemy return nearest