extends CharacterBody3D

const SPEED = 5.0
const JUMP_SPEED = 3.0
const BOOSTED_SPEED = 10.0
const BLEND_TIME = 0.5
const ROTATION_SPEED = 3.0
const STOP_DELAY = 0.5
const SIZE_INCREASE_PER_CANDY = 0.000005
const MAX_SIZE = 5.0
const BASE_PRIORITY_RANGE = 10.0  # Базовый радиус приоритета
const PRIORITY_RANGE_PER_CANDY = 0.0001  # Увеличение радиуса приоритета за каждую конфету

var candy_count = 0
signal player_removed
signal candy_collected

@onready var candy_label = $Label3D
@onready var animation_player: AnimationPlayer = $AnimationPlayer

var is_stopped: bool = false
var collision_handled: bool = false
var current_direction: Vector3 = Vector3.ZERO
var target_direction: Vector3 = Vector3.ZERO

# List of names to choose from
var names = ["Джек-О'-Фонарь", "Леди Вампирша", "Сэр Скелетон", "Барон Бат",
	"Мисс Мумиё", "Кот Баскервилей", "Зомби Захар", "Ведьма Вика", "Призрак Паша",
	"Гаргулья Гена", "Мистер Мрак", "Леди Летающая Тыква", "Чудище Чарли", "Гоблин Гоша",
	"Вурдалак Вова","Pumpkin Pete", "Ghostly Gary", "Witchy Wendy", "Boo Barry",
	"Creepy Carl", "Mystic Mandy", "Spooky Steve", "Haunted Hannah", "Ghoul Greg",
	"Vampire Vicky", "Zombie Zack", "Frankie Frankenstein", "Dracula Dan", "Mummy Mike",
	"Skeleton Sam", "Batty Betty", "Wraith Roger", "Ghastly Gina", "Phantom Phil", "Wicked Will"]

# Global variable or singleton to keep track of used names
var used_names = []

func _ready():
	# Randomly select a name
	var name = get_unique_name()
	
	# Set the initial label text to the name
	if candy_label:
		candy_label.text = name + "\n" + str(candy_count)
	
	# Найдите всех персонажей в группе "players"
	var players = get_tree().get_nodes_in_group("players")
	
	# Найдите персонажа с самым большим количеством конфет
	var max_candy_count = 0
	for player in players:
		if player.candy_count > max_candy_count:
			max_candy_count = player.candy_count
	
	# Установите случайное количество конфет для нового персонажа
	candy_count = randi_range(0, max_candy_count)
	
	$Area3D.body_entered.connect(_on_body_entered)
	update_candy_count()
	# Initialize the label's scale to counteract the initial character scale
	if candy_label:
		candy_label.scale = Vector3.ONE / scale
	# Add the name to the used names list
	used_names.append(name)
	
func _on_body_entered(body):
	if body.is_in_group("players") and body != self:
		handle_collision(body)
	elif body.is_in_group("candies"):
		collect_candy(body.candy_value)
		body.queue_free()
		emit_signal("candy_collected", body)

func handle_collision(other_player):
	if collision_handled:
		return

	collision_handled = true

	if candy_count > other_player.candy_count:
		var other_candy_count = other_player.candy_count
		collect_candy(other_candy_count)
		
		other_player.remove_from_game()
		
		print("Collision handled: Added ", other_candy_count, " candies. New candy count: ", candy_count)
	else:
		print("Collision handled: No absorption. The other player has more or equal candies.")

	await get_tree().create_timer(0.1).timeout
	collision_handled = false

func update_candy_count():
	if candy_label:
		# Update only the candy count part of the label
		var name = candy_label.text.split("\n")[0]
		candy_label.text = name + "\n" + str(candy_count)
	
func collect_candy(value):
	# Увеличиваем количество конфет на value
	candy_count += value
	update_candy_count()
	update_size()

func update_size():
	var size_increase = candy_count * SIZE_INCREASE_PER_CANDY
	var new_scale = Vector3.ONE + Vector3.ONE * size_increase

	# Проверяем, не превышает ли новый размер максимальный размер
	if new_scale.length() > MAX_SIZE:
		new_scale = new_scale.normalized() * MAX_SIZE

	# Применяем новый масштаб к персонажу
	scale = new_scale

	# Корректируем масштаб метки, чтобы сохранить ее оригинальный размер в мировом пространстве
	if candy_label:
		var label_scale = Vector3.ONE / new_scale
		candy_label.scale = label_scale

func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity += get_gravity() * delta

	var candies = get_tree().get_nodes_in_group("candies")
	var players = get_tree().get_nodes_in_group("players")
	var closest_target = null
	var closest_distance = INF
	var target_is_candy = true

	# Вычисляем радиус приоритета на основе количества конфет
	var dynamic_priority_range = BASE_PRIORITY_RANGE + (candy_count * PRIORITY_RANGE_PER_CANDY)

	# Находим ближайшую конфету
	for candy in candies:
		var distance = global_transform.origin.distance_to(candy.global_transform.origin)
		if distance < closest_distance:
			closest_distance = distance
			closest_target = candy
			target_is_candy = true

	# Находим ближайшего игрока для преследования, с учетом приоритета
	for player in players:
		if player != self:
			var distance = global_transform.origin.distance_to(player.global_transform.origin)
			
			# Проверяем, что у игрока меньше конфет и он ближе, чем конфета
			if distance < closest_distance and player.candy_count < candy_count:
				closest_distance = distance
				closest_target = player
				target_is_candy = false
			
			# Проверяем, что игрок находится в пределах радиуса приоритета и у вас больше конфет
			elif distance < dynamic_priority_range and candy_count > player.candy_count:
				closest_distance = distance
				closest_target = player
				target_is_candy = false

	if closest_target:
		target_direction = (closest_target.global_transform.origin - global_transform.origin).normalized()
		var speed = SPEED if not target_is_candy else SPEED
		
		# Плавно изменяем направление движения
		current_direction = current_direction.lerp(target_direction, ROTATION_SPEED * delta)
		current_direction = current_direction.normalized()

		velocity.x = current_direction.x * speed
		velocity.z = current_direction.z * speed
		
		if current_direction != Vector3.ZERO:
			look_at(global_transform.origin + Vector3(current_direction.x, 0, current_direction.z), Vector3.UP)
		
		if animation_player.current_animation != "move":
			animation_player.play("move", BLEND_TIME)
	else:
		# Постепенно уменьшаем скорость, когда нет цели
		velocity.x = move_toward(velocity.x, 0, SPEED * delta)
		velocity.z = move_toward(velocity.z, 0, SPEED * delta)
		if abs(velocity.x) < 0.1 and abs(velocity.z) < 0.1:
			velocity.x = 0
			velocity.z = 0
			if animation_player.current_animation != "stop":
				animation_player.play("stop", BLEND_TIME)

	move_and_slide()

func remove_from_game():
	remove_from_group("players")
	if animation_player:
		animation_player.stop()
	$Area3D.body_entered.disconnect(_on_body_entered)
	emit_signal("player_removed", self)
	queue_free()

func get_unique_name():
	var name = names[randi() % names.size()]
	while used_names.has(name):
		# If the name is already in use, try another one
		name = names[randi() % names.size()]
	return name
	
func _exit_tree():
	# When the character is removed from the scene, remove its name from the used names list
	if used_names.has(candy_label.text.split("\n")[0]):
		used_names.erase(candy_label.text.split("\n")[0])
проанализируй код,   сохраняя функционал кода, оптимизируй и по возможности упрости код что бы было меньше мусора