stick-the-quick/zones/LoadingZone/LoadingZone.gd

64 lines
1.7 KiB
GDScript

class_name LoadingZone extends Area3D
const FLOOR_CHECK_DISTANCE: float = 100.0
const FLOOR_ANTICLIP: float = 0.25
const RAYCAST_ANTICLIP: float = 5.0
const AREA_ANTICLIP: float = 1.0
const SCENE_START_TIMEOUT: float = 1.0
enum ActiveState {
DISABLED,
ENABLED,
DROPOFF_ONLY
}
@export var active_state := ActiveState.ENABLED
@onready var bounds := (
$'CollisionShape3D' as CollisionShape3D
).shape as BoxShape3D
func dropoff_site() -> Transform3D:
var raycast := PhysicsRayQueryParameters3D.new()
raycast.from = (
global_position + basis.z*(bounds.size.z/2.0 + AREA_ANTICLIP) +
basis.y*RAYCAST_ANTICLIP
)
raycast.to = raycast.from - basis.y*FLOOR_CHECK_DISTANCE
var chk := get_world_3d().direct_space_state.intersect_ray(raycast)
return Transform3D(basis.orthonormalized(), (
global_position if chk.is_empty()
else chk.position + basis.y*FLOOR_ANTICLIP
))
func dropoff(what: Node3D, use_model_front: bool = true) -> void:
what.transform = dropoff_site()
if use_model_front:
what.basis = what.basis.rotated(what.basis.y, PI)
func pickup(node: Node) -> void:
if (
active_state == ActiveState.ENABLED and
PlayerControl.enabled() and
node == PlayerControl.get_runner()
):
Storyboard.try_follow_map_connection(name)
func enable() -> void:
if active_state != ActiveState.DROPOFF_ONLY:
active_state = ActiveState.ENABLED
func disable() -> void:
if active_state != ActiveState.DROPOFF_ONLY:
active_state = ActiveState.DISABLED
func enabled() -> bool:
return bool(active_state == ActiveState.ENABLED)
func _ready() -> void:
_connect_pickup_after_timeout.call_deferred()
func _connect_pickup_after_timeout() -> void:
await Wait.seconds(SCENE_START_TIMEOUT)
body_entered.connect(pickup)