The character refuses to the die and ranged attacks not working properly

Godot Version

Godot 4.2.2 Stable

Question

Greetings! I have made a finall boss character to the my top down 2d game but it acting weird. First problem im facing with is the boss is not processing ranged attacks properly, i mean, it only plays the animation, not spawning the projectiles. The other problem is lil bro refuses to die i mean, , it supposed to be call a death function when its hp reaches to 0 or below 0 but i think i made something wrong with the handling phase states, it's only doing ranged attacks and when the player's body collides with the boss's body, the player gets instantly one shot. I will drop the whole boss's code below for inspecting the code. Any suggestions/constructive criticism warmly welcomed, thanks in advance!

extends CharacterBody2D

# Constants for magic numbers
const MELEE_DISTANCE = 30.0
const SHOOTING_DISTANCE = 180
const INITIAL_HP = 2000.0
const BASE_ARMOR = 0
const PHASE_2_ARMOR = 2
const PHASE_DAMAGE_INCREMENT = 20

@export var movement_speed = 20.0
@export var hp = INITIAL_HP
@export var knockback_recovery = 3.5
@export var exp = 1
@export var enemy_damage = 1

var knockback = Vector2.ZERO

@onready var player = get_tree().get_first_node_in_group("player")
@onready var loot_base = get_tree().get_first_node_in_group("loot")
@onready var sprite = $AnimatedSprite2D
@onready var snd_hit = $golem_boss_death
@onready var hitBox = $HitBox
@onready var attack_timer = $PlayerDetectionArea/AttackCooldown
@onready var player_detection_area = $PlayerDetectionArea
@onready var ImmuneTimer = $ImmuneTimer

var golem_hand_scene = preload("res://scenes/golem_hand.tscn")
var golem_hand_glowing_scene = preload("res://scenes/golem_hand_glowing.tscn")
var exp_orb = preload("res://scenes/exp_orb.tscn")

signal remove_from_array(object)

# Phase management
var current_phase: int = 1
var armor: int = BASE_ARMOR

# HP thresholds for phases
var phase_thresholds = {
	1: [1500.0, 2000.0],
	2: [1000.0, 1500.0],
	3: [500.0, 1000.0],
	4: [0.0, 500.0]
}

# State management
enum BossState {
	MOVING,
	ATTACKING,
	IMMUNE
}

var current_state: BossState = BossState.MOVING
var is_attacking: bool = false

func _ready():
	hitBox.damage = enemy_damage
	player_detection_area.body_entered.connect(_on_player_detected)
	player_detection_area.body_exited.connect(_on_player_lost)
	player_detection_area.monitoring = false  # Disable monitoring in phases 1 and 2
	sprite.connect("animation_finished", Callable(self, "_on_animation_finished"))

func _physics_process(delta):
	if not is_instance_valid(player):
		return
	
	var direction = global_position.direction_to(player.global_position)
	var distance_to_player = global_position.distance_to(player.global_position)
	
	# Knockback gradually resets
	knockback = knockback.lerp(Vector2.ZERO, knockback_recovery * delta)

	# Handle immune state
	if current_state == BossState.IMMUNE:
			armor = BASE_ARMOR  # Reset armor after immune state
			return

	match current_state:
		BossState.MOVING:
			if current_phase < 2 and distance_to_player <= MELEE_DISTANCE:
				if attack_timer.is_stopped() and not is_attacking:
					velocity = Vector2.ZERO
					current_state = BossState.ATTACKING
					play_animation("melee_attack")
					handle_attack()
			elif current_phase >= 3 and distance_to_player <= SHOOTING_DISTANCE:
				if attack_timer.is_stopped() and not is_attacking:
					velocity = Vector2.ZERO
					current_state = BossState.ATTACKING
					play_animation("ranged_attack")
					handle_attack()
			else:
				velocity = direction * movement_speed + knockback
				play_animation("walk" if current_phase < 3 else "glow_move")
				is_attacking = false

		BossState.ATTACKING:
			if sprite.animation_finished:
				current_state = BossState.MOVING

	# Directly set velocity, so call move_and_slide()
	move_and_slide()
	sprite.flip_h = direction.x < -0.1

func _on_hurt_box_hurt(damage, angle, knockback_amount):
	if current_state == BossState.IMMUNE:
		return  # Ignore damage while in immune state
	else:
		damage = max(damage - armor, 0)  # Armor calculation
		hp -= damage
		knockback = angle * knockback_amount
		if hp <= 0:
			death()
		else:
			snd_hit.play()
		update_phase()

func attack():
	handle_attack()

func melee_attack():
	if player.global_position.distance_to(global_position) <= MELEE_DISTANCE:
		player.call_deferred("_on_hurt_box_hurt", enemy_damage, Vector2.ZERO, 0)
		play_animation("melee_attack")

func ranged_attack():
	if attack_timer.is_stopped():
		var projectile_scene = golem_hand_scene if current_phase < 4 else golem_hand_glowing_scene
		var projectile = projectile_scene.instantiate()
		projectile.global_position = global_position
		var direction = (player.global_position - global_position).normalized()
		projectile.velocity = direction 
		get_parent().add_child(projectile)
		attack_timer.start()  # Start the attack cooldown timer
		# Ensure the animation plays only once per attack
		play_animation("ranged_attack")  # Play the ranged attack animation

func handle_attack():
	if current_phase < 3:
		melee_attack()  # Allow melee attack in phases 1 and 2
	elif current_phase >= 3 and player_detection_area.monitoring:
		ranged_attack()  # Only allow ranged attack if monitoring is active

func _on_animation_finished():
	# Reset the attacking state when the animation finishes
	is_attacking = false

func determine_phase(hp: float) -> int:
	for phase in phase_thresholds.keys():
		var min_hp = phase_thresholds[phase][0]
		var max_hp = phase_thresholds[phase][1]
		if hp > min_hp and hp <= max_hp:
			return phase
	return 0  # Default for invalid values

func update_phase():
	var phase = determine_phase(hp)
	if phase != current_phase:  # Only update phase if it has changed
		set_phase(phase)

func set_phase(phase: int):
	if phase == current_phase:
		return
	current_phase = phase
	match phase:
		1:
			armor = BASE_ARMOR
		2:
			armor = PHASE_2_ARMOR
			play_animation("armor_up")
			await sprite.animation_finished
		3:
			armor += 1
			enemy_damage += PHASE_DAMAGE_INCREMENT
			play_animation("glow")  # Transition animation
			await sprite.animation_finished
			player_detection_area.monitoring = true  # Activate area in phase 3
		4:
			armor += 1
			enemy_damage += PHASE_DAMAGE_INCREMENT
			play_animation("immune")
			current_state = BossState.IMMUNE  # Change state to immune
			ImmuneTimer.start()
			await sprite.animation_finished
			play_animation("glow_move")

func death():
	emit_signal("remove_from_array", self)
	play_animation("death")
	await sprite.animation_finished
	var new_exp = exp_orb.instantiate()
	new_exp.global_position = global_position
	new_exp.exp = exp
	loot_base.call_deferred("add_child", new_exp)
	queue_free()

func play_animation(animation_name: String):
	if sprite.animation != animation_name:  # Prevent re-triggering the same animation
		sprite.play(animation_name)

func _on_attack_cooldown_timeout():
	attack()

func _on_player_detected(body: Node) -> void:
	if body.is_in_group("player"):
		attack_timer.start()

func _on_player_lost(body: Node) -> void:
	if body.is_in_group("player"):
		attack_timer.stop()

func _on_immune_timer_timeout():
	var distance_to_player = global_position.distance_to(player.global_position)
	if distance_to_player >= SHOOTING_DISTANCE and not is_attacking:
		velocity = Vector2.ZERO
		current_state = BossState.ATTACKING  # Change state to immune
	ImmuneTimer.stop()

073644