extends Node3D const DOOR_OPEN_X := 1.154 const DOOR_CLOSED_X := 0.7 const DOOR_DEFAULT_TIME := 3.0 const DOOR_FAST_CLOSE_TIME := 1.0 const DOOR_REOPEN_TIME := 0.4 const PULSE_CLOSE_LAG_TOP := 1.0 const PULSE_CLOSE_LAG_PER_FLOOR := 0.09 const PULSE_CLOSE_LAG_MIN := 0.2 const DOORS_NEARLY_OPEN_LEAD := 0.4 var _tween: Tween = null var _pulse_close_pending: bool = false var _current_floor: int = EventBus.STARTING_FLOOR func _ready(): $ElevatorDoorRight.position = Vector3(DOOR_CLOSED_X, 0, 0) $ElevatorDoorLeft.position = Vector3(-DOOR_CLOSED_X, 0, 0) _set_door_collision(true) EventBus.doors_opened.connect(_on_doors_opened) EventBus.doors_closed.connect(_on_doors_closed) EventBus.pulse_started.connect(_on_pulse_started) EventBus.pulse_blocked.connect(_on_pulse_blocked) EventBus.floor_changed.connect(func(f): _current_floor = f) func _on_doors_opened(): _pulse_close_pending = false _set_door_collision(false) _tween_doors(DOOR_OPEN_X, DOOR_DEFAULT_TIME) _tween.chain().tween_callback(func(): EventBus.doors_fully_opened.emit()) get_tree().create_timer(DOOR_DEFAULT_TIME - DOORS_NEARLY_OPEN_LEAD, false).timeout.connect( func(): EventBus.doors_nearly_opened.emit(), CONNECT_ONE_SHOT ) func _on_doors_closed(fast: bool): _pulse_close_pending = false _set_door_collision(true) _tween_doors(DOOR_CLOSED_X, DOOR_FAST_CLOSE_TIME if fast else DOOR_DEFAULT_TIME) _tween.chain().tween_callback(func(): EventBus.doors_fully_closed.emit()) func _on_pulse_started(duration: float): _set_door_collision(true) _pulse_close_pending = true var floors_descended = EventBus.STARTING_FLOOR - _current_floor var lag = max(PULSE_CLOSE_LAG_MIN, PULSE_CLOSE_LAG_TOP - floors_descended * PULSE_CLOSE_LAG_PER_FLOOR) get_tree().create_timer(lag, false).timeout.connect( func(): if not _pulse_close_pending: return if $ElevatorDoorRight.position.x < DOOR_OPEN_X - 0.001: _pulse_close_pending = false return _pulse_close_pending = false _tween_doors(DOOR_CLOSED_X, duration), CONNECT_ONE_SHOT ) func _on_pulse_blocked(): _pulse_close_pending = false _set_door_collision(false) _tween_doors(DOOR_OPEN_X, DOOR_REOPEN_TIME) func _set_door_collision(enabled: bool): $ElevatorDoorRight/CollisionShape3D.disabled = not enabled $ElevatorDoorLeft/CollisionShape3D.disabled = not enabled func get_door_close_progress() -> float: var cur: float = $ElevatorDoorRight.position.x return clamp((DOOR_OPEN_X - cur) / (DOOR_OPEN_X - DOOR_CLOSED_X), 0.0, 1.0) func _tween_doors(target_x: float, duration: float): if _tween: _tween.kill() _tween = create_tween() _tween.set_parallel(true) _tween.tween_property($ElevatorDoorRight, "position:x", target_x, duration) _tween.tween_property($ElevatorDoorLeft, "position:x", -target_x, duration)