69 lines
1.9 KiB
GDScript3
69 lines
1.9 KiB
GDScript3
|
class_name FollowerThinker extends NPCRunnerThinker
|
||
|
|
||
|
@export var target: Node3D
|
||
|
@export var target_distance: float = 0.0
|
||
|
|
||
|
var raycast: PhysicsRayQueryParameters3D
|
||
|
|
||
|
func _ready() -> void:
|
||
|
raycast = PhysicsRayQueryParameters3D.new()
|
||
|
|
||
|
func impetus() -> Vector3:
|
||
|
var displacement := (
|
||
|
target.global_position - runner.global_position
|
||
|
).slide(runner.up_normal)
|
||
|
if displacement.length() <= target_distance:
|
||
|
return Vector3.ZERO
|
||
|
else:
|
||
|
return displacement.limit_length()
|
||
|
|
||
|
func should_jump() -> bool:
|
||
|
if (
|
||
|
runner.state == &'jump' or
|
||
|
runner.state == &'wall_jump' or
|
||
|
runner.state == &'ability'
|
||
|
):
|
||
|
return false
|
||
|
var displacement := (
|
||
|
target.global_position - runner.global_position
|
||
|
)
|
||
|
var vertical_displacement := displacement.project(runner.up_normal)
|
||
|
var horizontal_displacement := displacement - vertical_displacement
|
||
|
if vertical_displacement.normalized().dot(runner.up_normal) <= 0.0:
|
||
|
vertical_displacement = Vector3.ZERO
|
||
|
if displacement.length() <= target_distance:
|
||
|
return false
|
||
|
if vertical_displacement.length() > target_distance:
|
||
|
return true
|
||
|
if runner.state == &'wall_slide':
|
||
|
return (
|
||
|
runner.wall_normal.dot(
|
||
|
horizontal_displacement.normalized()
|
||
|
) > 0.25 or
|
||
|
runner.linear_velocity.normalized().dot(Vector3.UP) < -0.25
|
||
|
)
|
||
|
if not runner.wall_normal.is_zero_approx():
|
||
|
return true
|
||
|
if target is PhysicsBody3D:
|
||
|
raycast.exclude = [self, target]
|
||
|
else:
|
||
|
raycast.exclude = [self]
|
||
|
raycast.from = runner.global_position
|
||
|
raycast.to = runner.global_position + horizontal_displacement
|
||
|
var raycast_result := (
|
||
|
runner.get_world_3d().direct_space_state.intersect_ray(raycast)
|
||
|
)
|
||
|
if raycast_result.is_empty():
|
||
|
return false
|
||
|
if (
|
||
|
raycast_result[&'normal'].dot(-horizontal_displacement.normalized()) >
|
||
|
0.25
|
||
|
):
|
||
|
return true
|
||
|
return false
|
||
|
|
||
|
func should_do_ability() -> bool:
|
||
|
return runner.state == &'ability' and (
|
||
|
target.global_position - runner.global_position
|
||
|
).normalized().dot(runner.up_normal) < -0.25
|