extends CharacterBody2D class_name Bunny @export var animation_player : AnimationPlayer @export var min_distance_to_player := 20.0 @export var max_distance_to_player := 500.0 @export var agent : NavigationAgent2D @export var speed := 3.0 @export var damage_given : float = 4.0 var health : int var team : int var player : Node2D var on_death_callbacks : Array var move_velocity : Vector2 var next_location : Vector2 var randomized_next_location : Vector2 var dir : Vector2 var time_since_got_player := 100.0 var time_since_got_move_location := 100.0 var last_player_velocity := 0.0 var last_target_position : Vector2 var max_pos_check_time := 0.5 var max_pos_check_time_inactive_scalar := 10.0 var max_get_move_location_time := 0.125 var random_goal_spread_factor := 2.5 var random_move_location_spread_factor := 8.0 var random_angle_change := deg_to_rad(4.0) @export var attack_delay : float = 6.0 var attack_cooldown_left : float = 0 var first_attack : bool = true func _ready(): pass func _physics_process(delta): randomize() attack_cooldown_left -= delta if abs(player.velocity.length() - last_player_velocity) > 100.0: time_since_got_player = max_pos_check_time if time_since_got_player >= max_pos_check_time and player.velocity.length() > 0.1: time_since_got_player = randf() * max_pos_check_time * 0.5 update_target_pos() if time_since_got_player >= max_pos_check_time * max_pos_check_time_inactive_scalar and player.velocity.length() < 0.1: time_since_got_player = -(randf() * max_pos_check_time * 0.5) update_target_pos() if self.global_position.distance_to(player.global_position) < max_distance_to_player and time_since_got_move_location > max_get_move_location_time: time_since_got_move_location = 0 if agent.is_target_reachable(): next_location = agent.get_next_path_position() randomized_next_location = next_location + Vector2(randf() - 0.5, randf() - 0.5 ) * 2 * random_move_location_spread_factor dir = self.global_position.direction_to(randomized_next_location).normalized().rotated((randf() - 0.5) * 2 * random_angle_change) if self.global_position.distance_to(player.global_position) >= min_distance_to_player: move_velocity = dir * delta * 60 * speed update_animation() if self.global_position.distance_to(next_location) < move_velocity.length(): self.global_position = next_location time_since_got_player = 10.0 time_since_got_move_location = 10.0 else: move_and_collide(move_velocity) elif attack_cooldown_left <= 0 and BunnyMaster.bunnies_attacking < BunnyMaster.max_bunnies_allowed_to_attack_at_once: BunnyMaster.bunnies_attacking += 1 attack_cooldown_left = attack_delay player.take_damage(damage_given) get_tree().create_timer(3.0).connect("timeout",Callable(self, "reduce_attack_count"), 0) else: animation_player.stop() time_since_got_player += delta time_since_got_move_location += delta last_player_velocity = player.velocity.length() last_target_position = agent.target_position pass func reduce_attack_count(): BunnyMaster.bunnies_attacking -= 1 func update_target_pos(): agent.target_position = Vector2(player.global_position) + Vector2(randf() - 0.5 , randf() - 0.5) * 2 * random_goal_spread_factor pass func damage(damage_amount : int): health -= damage_amount if(health <= 0): on_death() pass func heal(health_amount : int): self.health += health_amount pass func on_death(): for callback in on_death_callbacks: callback.call(self) BunnyMaster.bunnies_alive -= 1 if BunnyMaster.bunnies_alive <= 0: player.end_screen_displayer.call("show_victory_screen") get_tree().paused = true pass func sub_on_death(callback : Callable): on_death_callbacks.push_front(callback) pass func update_animation(): match self.move_velocity: Vector2.ZERO: animation_player.play("Idle") _: var left_dot = Vector2.LEFT.dot(self.move_velocity) var right_dot = Vector2.RIGHT.dot(self.move_velocity) var up_dot = Vector2.UP.dot(self.move_velocity) var down_dot = Vector2.DOWN.dot(self.move_velocity) var max_dot = maxf(left_dot, maxf(right_dot, maxf(up_dot, down_dot))) match max_dot: left_dot: animation_player.play("MoveLeft") right_dot: animation_player.play("MoveRight") up_dot: animation_player.play("MoveUp") down_dot: animation_player.play("MoveDown") pass