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