48 lines
1.6 KiB
GDScript
48 lines
1.6 KiB
GDScript
extends Node3D
|
|
## Door entity. Place at a cell center in TrenchBroom (normal 64 grid).
|
|
## The door's local -Z is "forward" (the direction the player approaches from).
|
|
## At runtime the mesh/collision shift forward to the cell boundary so the door
|
|
## sits flush against the wall the player is facing.
|
|
|
|
## If true the door swings toward its local +Z (outward). If false it swings
|
|
## toward -Z (inward).
|
|
@export var opens_outward := true
|
|
|
|
@onready var hinge_pivot: Node3D = $HingePivot
|
|
@onready var door_collision: CollisionShape3D = $DoorBody/DoorCollision
|
|
@onready var interact_area: Area3D = $InteractArea
|
|
|
|
var _is_open := false
|
|
var _tween: Tween
|
|
|
|
const SWING_DURATION := 0.5
|
|
## How far forward (local -Z) to shift everything so the door sits on the cell boundary.
|
|
const BOUNDARY_OFFSET := 0.0
|
|
|
|
|
|
func _ready() -> void:
|
|
add_to_group("facing_interactable")
|
|
# Shift children to the cell boundary along the door's forward axis.
|
|
var offset := -transform.basis.z.normalized() * BOUNDARY_OFFSET
|
|
for child: Node3D in [hinge_pivot, $DoorBody, interact_area]:
|
|
child.global_position += offset
|
|
|
|
|
|
func try_interact(player: CharacterBody3D) -> bool:
|
|
if not interact_area.overlaps_body(player):
|
|
return false
|
|
if _tween and _tween.is_running():
|
|
return true
|
|
|
|
_is_open = !_is_open
|
|
_tween = create_tween()
|
|
|
|
var swing := -PI / 2.0 if opens_outward else PI / 2.0
|
|
var target_angle := swing if _is_open else 0.0
|
|
_tween.tween_property(hinge_pivot, "rotation:y", target_angle, SWING_DURATION)
|
|
|
|
if _is_open:
|
|
door_collision.disabled = true
|
|
else:
|
|
_tween.tween_callback(func(): door_collision.disabled = false)
|
|
return true
|