127 lines
4.2 KiB
GDScript
127 lines
4.2 KiB
GDScript
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
|