grunk/src/world/grunk_beast/grunk_beast.gd

89 lines
2.0 KiB
GDScript3
Raw Normal View History

2025-04-16 17:20:33 -06:00
class_name GrunkBeast extends CharacterBody3D
## Grunk beast controller
2025-04-17 10:02:01 -06:00
#region Constants
2025-04-17 13:41:06 -06:00
const STALKING_SOUND_LIMIT := 20.0
2025-04-17 10:02:01 -06:00
#endregion
#region Exported Properties
@export var base_speed := 60.0
@export var pursuit_speed := 180.0
#endregion
#region Member Variables
2025-04-16 17:20:33 -06:00
var gravity: Vector3 = (
ProjectSettings.get_setting("physics/3d/default_gravity")
* ProjectSettings.get_setting("physics/3d/default_gravity_vector")
)
2025-04-17 10:02:01 -06:00
var pathfinding := true
2025-04-16 17:20:33 -06:00
@onready var nav_agent: NavigationAgent3D = %NavAgent
2025-04-17 13:41:06 -06:00
@onready var nav_probe: NavigationAgent3D = %NavProbe
@onready var stalking_timer: Timer = %StalkingTimer
2025-04-16 17:20:33 -06:00
2025-04-17 13:41:06 -06:00
@onready var blackboard: Blackboard = %Blackboard
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
#endregion
2025-04-16 17:20:33 -06:00
2025-04-17 13:41:06 -06:00
#region Character Controller
2025-04-17 10:02:01 -06:00
2025-04-16 17:20:33 -06:00
2025-04-17 13:41:06 -06:00
func is_pursuing() -> bool:
return blackboard.has_value("pursuit_target")
2025-04-16 17:20:33 -06:00
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
func is_stalking() -> bool:
return false # TODO
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
func get_speed() -> float:
if is_pursuing():
return pursuit_speed
return base_speed
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
func path_shorter_than(target: Vector3, limit: float) -> bool:
2025-04-17 10:02:01 -06:00
var limit_sq := limit * limit
var length_sq := 0.0
var last_pos := global_position
2025-04-17 13:41:06 -06:00
nav_probe.target_position = target
for waypoint: Vector3 in nav_probe.get_current_navigation_path().slice(
nav_probe.get_current_navigation_path_index()
2025-04-17 10:02:01 -06:00
):
# Using distance squared to save a sqrt instruction
length_sq += last_pos.distance_squared_to(waypoint)
if length_sq > limit_sq:
return false
last_pos = waypoint
return true
2025-04-17 13:41:06 -06:00
func _physics_process(delta: float) -> void:
var motion := Vector3.ZERO
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
if pathfinding:
var path_pos := nav_agent.get_next_path_position()
var relative_pos := path_pos - global_position
motion = relative_pos.normalized() * get_speed() * delta
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
velocity.x = motion.x
velocity.z = motion.z
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
if not is_on_floor():
velocity += gravity * delta
2025-04-17 10:02:01 -06:00
2025-04-17 13:41:06 -06:00
move_and_slide()
2025-04-17 10:02:01 -06:00
func on_sound_detected(source: Vector3) -> void:
# Check that the source isn't too far away, e.g. a sound from another room
2025-04-17 13:41:06 -06:00
if path_shorter_than(source, STALKING_SOUND_LIMIT):
blackboard.set_value("stalking_target", source)
stalking_timer.start()
2025-04-17 10:02:01 -06:00
#endregion