Signal 'changed' is already connected to given callable 'Button::_texture_changed' in that object.
  res://Scripts/Characters/Player/player.gd:30 - Parse Error: Invalid argument for "connect()" function: argument 2 should be "Callable" but is "Player2D".
  res://Scripts/Characters/Player/player.gd:30 - Parse Error: Cannot pass a value of type "String" as "int".
  res://Scripts/Characters/Player/player.gd:30 - Parse Error: Invalid argument for "connect()" function: argument 3 should be "int" but is "String".
  res://Scripts/Characters/Player/player.gd:41 - Parse Error: Too many arguments for "move_and_slide()" call. Expected at most 0 but received 2.
  res://Scripts/Characters/Player/player.gd:41 - Parse Error: Value of type "bool" cannot be assigned to a variable of type "Vector2".
  res://Scripts/Characters/Player/player.gd:117 - Parse Error: Identifier "health" not declared in the current scope.
  res://addons/sprite_painter/src/main.gd:58 - Invalid get index 'resource_path' (on base: 'null instance').
  res://addons/sprite_painter/src/main.gd:58 - Invalid get index 'resource_path' (on base: 'null instance').


extends CharacterBody2D
class_name Player2D
enum State { IDLE, RUN, JUMP, ATTACK }
var state = State.IDLE
var player_base: PlayerBase
# Data (now stats will come from PlayerBase health)
var bullets_amount: int = 30
var attack_animation: String = "Attack1"
@export var movement_data: MovementData
var stats: Stats = null

# References
@onready var animator : AnimatedSprite2D = $AnimatedSprite2D
@onready var guns_animator : AnimationPlayer = $ShootingAnimationPlayer
@onready var hit_animator : AnimationPlayer = $HitAnimationPlayer
@onready var hand : Node2D = $Hand
@onready var pistol : Sprite2D = $Hand/Pivot/Pistol
@onready var pistol_bullet_marker : Marker2D = $Hand/Pivot/Pistol/PistolBulletMarker
@onready var attacking: bool = false
@export var camera: Camera2D

# Load Scenes
@onready var muzzle_load: PackedScene = preload("res://Scenes/Particles/muzzle.tscn")
@onready var bullet_load: PackedScene = preload("res://Scenes/Props/bullet.tscn")
@onready var death_particle_load: PackedScene = preload("res://Scenes/Particles/player_death_particle.tscn")

func _ready():
	player_base = PlayerBase.new()
	add_child(player_base)
	player_base.connect("health_changed", self, "_on_health_changed")

	EventManager.bullets_amount = bullets_amount
	EventManager.update_bullet_ui.emit()
	

func _physics_process(delta):
	process_gravity(delta)
	process_movement_input(delta)
	process_actions()
	
	velocity = move_and_slide(velocity, Vector2.UP)
	animate()

func process_gravity(delta):
	if not is_on_floor():
		velocity.y += movement_data.gravity * movement_data.gravity_scale * delta

func process_movement_input(delta):
	var input_vector = Input.get_axis("move_left", "move_right")
	if input_vector != 0:
		velocity.x = move_toward(velocity.x, movement_data.max_speed * input_vector, movement_data.acceleration * delta)
	else:
		velocity.x = move_toward(velocity.x, 0, movement_data.friction * delta)

func process_actions():
	if Input.is_action_just_pressed("jump") and is_on_floor():
		perform_jump()
	if Input.is_action_just_pressed("shoot"):
		perform_attack()

func animate():
	var looking_direction = get_global_mouse_position().x > global_position.x
	animator.flip_h = looking_direction
	hand.rotation = (get_global_mouse_position() - global_position).angle()
	update_animation_state()

func perform_jump():
	velocity.y = -movement_data.jump_strength
	AudioManager.play_sound(AudioManager.JUMP)

func perform_attack():
	if not bullets_amount: return
	state = State.ATTACK
	animator.play("Attacking")
	guns_animator.play("Shoot")
	shoot()

func shoot():
	# Shooting logic goes here
	
	state = State.IDLE
	EventManager.update_bullet_ui.emit()

func update_animation_state():
	if state == State.ATTACK:
		return
	
	if is_on_floor():
		if velocity.x != 0:
			animator.play("Run")
		else:
			animator.play("Idle")
	else:
		animator.play("Jump") if velocity.y < 0 else animator.play("Fall")

func _on_hurtbox_area_entered(_area):
	if not _area.is_in_group("Bullet"):
		hit_animator.play("Hit")
		take_damage(1)  # If damage is to be variable, extract value from _area
		EventManager.frame_freeze.emit()

func die():
	AudioManager.play_sound(AudioManager.DEATH)
	animator.play("Died")
	spawn_death_particle()
	EventManager.player_died.emit()
	queue_free()

func spawn_death_particle():
	var death_particle = death_particle_load.instantiate()
	death_particle.global_position = global_position
	get_tree().current_scene.add_child(death_particle)

# Override PlayerBase method
func take_damage(damage: int) -> void:
	self.health -= damage  # This now calls the setter method declared in PlayerBase
	emit_signal("health_changed", health)  # You may want to call update_health_ui
	if self.health <= 0:
		die()
	else:
		AudioManager.play_sound(AudioManager.HURT)
func _on_swapPlane():
	PlayerState.set_last_2d_position(global_position); 
	get_tree().change_scene_to_file("res://demo/Scenes/main_scene.tscn")

# Implement the move method required by PlayerBase, the actual movement
# logic is in the _physics_process function above.
func move(input_dir: Vector2) -> void:
	# For Player2D, the move function is handled by process_movement_input,
	# so no additional logic is needed here.
	pass

# Implement the attack method required by PlayerBase. This is a placeholder
# and the actual logic for starting an attack is in the perform_attack function.
func attack() -> void:
	perform_attack()
	
	
	

func _on_health_changed(new_health: int) -> void:
	player_base.health = new_health  # Make sure to update it when health changes
	# Handle health change (e.g., update UI)




extends CharacterBody2D
class_name Player2D
enum State { IDLE, RUN, JUMP, ATTACK }
var state = State.IDLE
var player_base: PlayerBase
# Data (now stats will come from PlayerBase health)
var bullets_amount: int = 30
var attack_animation: String = "Attack1"
@export var movement_data: MovementData
var stats: Stats = null

# References
@onready var animator : AnimatedSprite2D = $AnimatedSprite2D
@onready var guns_animator : AnimationPlayer = $ShootingAnimationPlayer
@onready var hit_animator : AnimationPlayer = $HitAnimationPlayer
@onready var hand : Node2D = $Hand
@onready var pistol : Sprite2D = $Hand/Pivot/Pistol
@onready var pistol_bullet_marker : Marker2D = $Hand/Pivot/Pistol/PistolBulletMarker
@onready var attacking: bool = false
@export var camera: Camera2D

# Load Scenes
@onready var muzzle_load: PackedScene = preload("res://Scenes/Particles/muzzle.tscn")
@onready var bullet_load: PackedScene = preload("res://Scenes/Props/bullet.tscn")
@onready var death_particle_load: PackedScene = preload("res://Scenes/Particles/player_death_particle.tscn")

func _ready():
	player_base = PlayerBase.new()
	add_child(player_base)
	player_base.connect("health_changed", self, "_on_health_changed")

	EventManager.bullets_amount = bullets_amount
	EventManager.update_bullet_ui.emit()
	

func _physics_process(delta):
	process_gravity(delta)
	process_movement_input(delta)
	process_actions()
	
	velocity = move_and_slide(velocity, Vector2.UP)
	animate()

func process_gravity(delta):
	if not is_on_floor():
		velocity.y += movement_data.gravity * movement_data.gravity_scale * delta

func process_movement_input(delta):
	var input_vector = Input.get_axis("move_left", "move_right")
	if input_vector != 0:
		velocity.x = move_toward(velocity.x, movement_data.max_speed * input_vector, movement_data.acceleration * delta)
	else:
		velocity.x = move_toward(velocity.x, 0, movement_data.friction * delta)

func process_actions():
	if Input.is_action_just_pressed("jump") and is_on_floor():
		perform_jump()
	if Input.is_action_just_pressed("shoot"):
		perform_attack()

func animate():
	var looking_direction = get_global_mouse_position().x > global_position.x
	animator.flip_h = looking_direction
	hand.rotation = (get_global_mouse_position() - global_position).angle()
	update_animation_state()

func perform_jump():
	velocity.y = -movement_data.jump_strength
	AudioManager.play_sound(AudioManager.JUMP)

func perform_attack():
	if not bullets_amount: return
	state = State.ATTACK
	animator.play("Attacking")
	guns_animator.play("Shoot")
	shoot()

func shoot():
	# Shooting logic goes here
	
	state = State.IDLE
	EventManager.update_bullet_ui.emit()

func update_animation_state():
	if state == State.ATTACK:
		return
	
	if is_on_floor():
		if velocity.x != 0:
			animator.play("Run")
		else:
			animator.play("Idle")
	else:
		animator.play("Jump") if velocity.y < 0 else animator.play("Fall")

func _on_hurtbox_area_entered(_area):
	if not _area.is_in_group("Bullet"):
		hit_animator.play("Hit")
		take_damage(1)  # If damage is to be variable, extract value from _area
		EventManager.frame_freeze.emit()

func die():
	AudioManager.play_sound(AudioManager.DEATH)
	animator.play("Died")
	spawn_death_particle()
	EventManager.player_died.emit()
	queue_free()

func spawn_death_particle():
	var death_particle = death_particle_load.instantiate()
	death_particle.global_position = global_position
	get_tree().current_scene.add_child(death_particle)

# Override PlayerBase method
func take_damage(damage: int) -> void:
	self.health -= damage  # This now calls the setter method declared in PlayerBase
	emit_signal("health_changed", health)  # You may want to call update_health_ui
	if self.health <= 0:
		die()
	else:
		AudioManager.play_sound(AudioManager.HURT)
func _on_swapPlane():
	PlayerState.set_last_2d_position(global_position); 
	get_tree().change_scene_to_file("res://demo/Scenes/main_scene.tscn")

# Implement the move method required by PlayerBase, the actual movement
# logic is in the _physics_process function above.
func move(input_dir: Vector2) -> void:
	# For Player2D, the move function is handled by process_movement_input,
	# so no additional logic is needed here.
	pass

# Implement the attack method required by PlayerBase. This is a placeholder
# and the actual logic for starting an attack is in the perform_attack function.
func attack() -> void:
	perform_attack()
	
	
	

func _on_health_changed(new_health: int) -> void:
	player_base.health = new_health  # Make sure to update it when health changes
	# Handle health change (e.g., update UI)