extends Node3D @export var noise: FastNoiseLite @onready var enemy: PoliceCar = get_parent() const CHARGE_COOLDOWN := 5. # time charger has to wait between charges before being able to charge again const CHARGE_COOLUP := 0.5 # time the charger has to see the player before charging const CHARGE_SPEED := 50. const HOLD_TIME := 1. const CHARGE_TIME := 16. / CHARGE_SPEED var cooldown := 0. var coolup := 0. var charge_clock := 0. func _start_charge() -> void: charge_clock = 0. enemy.default_movement = false enemy.velocity = global_position.direction_to(Player.instance.global_position) enemy.velocity *= CHARGE_SPEED enemy.set_rotation_to_velocity() func _end_charge() -> void: charge_clock = 0. cooldown = CHARGE_COOLDOWN enemy.default_movement = true enemy.set_collision_mask_value(4, true) %KnockUpArea.monitoring = false %Meshes.position = Vector3.ZERO func _not_charging_process(delta: float) -> void: cooldown -= delta if cooldown > 0.: return var player_pos := Player.instance.global_position if global_position.distance_to(player_pos) > 15.: print("too far") coolup = 0. return var params := PhysicsRayQueryParameters3D.create( global_position, player_pos, 4294967295, [enemy] ) var raycast := get_world_3d().direct_space_state.intersect_ray(params) if not raycast.is_empty() and raycast.collider is Player: coolup += delta if coolup > CHARGE_COOLUP: _start_charge() else: print("raycast failed") coolup = 0. func _charging_process(delta: float) -> void: charge_clock += delta if charge_clock > HOLD_TIME + CHARGE_TIME: _end_charge() return if charge_clock < HOLD_TIME: var x := noise.get_noise_1d(charge_clock * 10000) var y := noise.get_noise_1d(-charge_clock * 10000) %Meshes.position = Vector3(x, 0, y) else: %KnockUpArea.monitoring = true enemy.set_collision_mask_value(4, false) enemy.move_and_slide() func _process(delta: float) -> void: if enemy.default_movement: _not_charging_process(delta) else: _charging_process(delta) func _on_knock_up_area_body_entered(body: Node3D) -> void: if body is PoliceCar and body != enemy and body.default_movement: var e := body as PoliceCar e.stunned = true var t := e.create_tween() t.set_trans(Tween.TRANS_QUAD) t.tween_property(e, "position:y", e.position.y + 7.5, .6).set_ease(Tween.EASE_OUT) t.tween_property(e, "position:y", e.position.y, .6).set_ease(Tween.EASE_IN) await t.finished e.stunned = false