I'm transferring the project from godot 3 to godot 4. Help please

I am trying to migrate the blocking algorithm from godot 3 to godot 4. I have birds that are duplicatedossible

extends CharacterBody2D

# these weights where defined through
# trial and error. You can play with them
# to check how they affect the flock.
var SEPARATION_WEIGHT = 0.5
var ALIGNMENT_WEIGHT = 0.5
var COHESION_WEIGHT = 0.1


var _max_speed = 2
var _speed = 2
var _direction = Vector2(0, 1)
var _separation_distance = 20

var _local_flockmates = []


func _physics_process(_delta):
	self.rotation = Vector2(0, 1).angle_to(_direction)
	var collision = self.move_and_collide(_direction * _speed)
	if collision:
		if collision is KinematicCollision2D:
			print("cool")
			_direction = _collision_reaction_direction(collision)
	else:
		_direction = _flock_direction()
		


# Inverts the direction when hitting a collider.
# This implementation handles colliding with Tilemaps specifically.
func _collision_reaction_direction(collision):
	
	return (global_position - collision.get_normal()).direction_to(self.global_position)


# This function is pretty much all you need for calculating
# the flocking movement
func _flock_direction():
	var separation = Vector2()
	var heading = _direction
	var cohesion = Vector2()

	for flockmate in _local_flockmates:
		cohesion += flockmate.position

		var distance = self.position.distance_to(flockmate.position)

		if distance < _separation_distance:
			separation -= (flockmate.position - self.position).normalized() * (_separation_distance / distance * _speed)

	if _local_flockmates.size() > 0:
		heading /= _local_flockmates.size()
		cohesion /= _local_flockmates.size()
		var center_direction = self.position.direction_to(cohesion)
		var center_speed = _max_speed * self.position.distance_to(cohesion) / $Area2D/CollisionShape2D.shape.radius
		cohesion = center_direction * center_speed
	return (
		_direction +
		separation * SEPARATION_WEIGHT +
		heading * ALIGNMENT_WEIGHT +
		cohesion * COHESION_WEIGHT
	).limit_length(_max_speed)


func get_direction():
	return _direction


func set_direction(direction):
	_direction = direction





func _on_area_2d_area_entered(body):
	if body == self:
		return

	if body.is_in_group("boid"):
		_local_flockmates.append(body)


func _on_area_2d_area_exited(body):
	if body.is_in_group("boid"):
		_local_flockmates.erase(body)



GODOT 4

extends KinematicBody2D

# these weights where defined through
# trial and error. You can play with them
# to check how they affect the flock.
const SEPARATION_WEIGHT = 0.5
const ALIGNMENT_WEIGHT = 0.5
const COHESION_WEIGHT = 0.1


var _max_speed = 2
var _speed = 2
var _direction = Vector2(0, 1)
var _separation_distance = 20

var _local_flockmates = []


func _physics_process(_delta):
	self.rotation = Vector2(0, 1).angle_to(_direction)
	var collision = self.move_and_collide(_direction * _speed)
	if collision:
		if collision.collider is TileMap:
			_direction = _collision_reaction_direction(collision)
	else:
		_direction = _flock_direction()


# Inverts the direction when hitting a collider.
# This implementation handles colliding with Tilemaps specifically.
func _collision_reaction_direction(collision):
	return (collision.position - collision.normal).direction_to(self.position)


# This function is pretty much all you need for calculating
# the flocking movement
func _flock_direction():
	var separation = Vector2()
	var heading = _direction
	var cohesion = Vector2()

	for flockmate in _local_flockmates:
		heading += flockmate.get_direction()
		cohesion += flockmate.position

		var distance = self.position.distance_to(flockmate.position)

		if distance < _separation_distance:
			separation -= (flockmate.position - self.position).normalized() * (_separation_distance / distance * _speed)

	if _local_flockmates.size() > 0:
		heading /= _local_flockmates.size()
		cohesion /= _local_flockmates.size()
		var center_direction = self.position.direction_to(cohesion)
		var center_speed = _max_speed * self.position.distance_to(cohesion) / $detection_radius/CollisionShape2D.shape.radius
		cohesion = center_direction * center_speed

	return (
		_direction +
		separation * SEPARATION_WEIGHT +
		heading * ALIGNMENT_WEIGHT +
		cohesion * COHESION_WEIGHT
	).clamped(_max_speed)


func get_direction():
	return _direction


func set_direction(direction):
	_direction = direction


func _on_detection_radius_body_entered(body):
	if body == self:
		return

	if body.is_in_group("boid"):
		_local_flockmates.push_back(body)


func _on_detection_radius_body_exited(body):
	if body.is_in_group("boid"):
		_local_flockmates.erase(body)

GODOT 3

and main scene with spawn

extends Node2D

@onready var Boid = load("res://fishka.tscn")

# add a boid on mouse click
func _ready():
	for x in range(50):
		_create_boid()

var rnd = RandomNumberGenerator.new()
func _create_boid():
	var boid = Boid.instantiate()
	boid.global_position = Vector2(rnd.randf_range(-250,250),rnd.randf_range(-250,250))
	add_child(boid)
	randomize()
	var direction = Vector2(rnd.randf(), rnd.randf())
	if direction == Vector2():
		direction = Vector2(0, 1)
	boid.set_direction(direction)

GODOT4

extends Node2D

const Boid = preload("res://boid.tscn")

# add a boid on mouse click
func _unhandled_input(event):
	if event is InputEventMouseButton and  event.button_index == BUTTON_LEFT and event.pressed:
		_create_boid()


func _create_boid():
	var boid = Boid.instance()
	add_child(boid)
	boid.global_position = self.get_global_mouse_position()
	randomize()
	var direction = Vector2(round(randf()), round(randf()))
	if direction == Vector2():
		direction = Vector2(0, 1)
	boid.set_direction(direction)

GODOT3

if need more information,ASK

If you use vs code, select both versions of the code in the open editor panel, or select both files in the file browser and use compare.

I suspect there is a logic issue somewhere. The compare tool can help you spot the small errors.

Seems like a lot of changes have been made, but you haven’t stated what the problem is. Walk us through what is supposed to happen, and what really happens?