extends CharacterBody3D const STALK_DARK_DISTANCE := 19.0 const STALK_ILLUMINATE_DISTANCE := 15.0 const WALK_IN_DURATION := 1.5 var robot_win: bool = false var speed: float = 1.0 var doors_open: bool = true var stun_remaining: float = 0.0 var _stalking_close: bool = false var _walk_in_remaining: float = 0.0 var _game_lost_emitted: bool = false var _spawn_transform: Transform3D var safety_zone: Area3D func _ready() -> void: _spawn_transform = transform EventBus.doors_opened.connect(func(): doors_open = true) EventBus.doors_closed.connect(func(_fast: bool): doors_open = false) EventBus.robot_stun_requested.connect(func(d: float): stun_remaining += d) EventBus.robot_floor_started.connect(_on_floor_started) func _on_floor_started(delay: float, new_speed: float) -> void: if robot_win: return transform = _spawn_transform velocity = Vector3.ZERO stun_remaining = 0.0 speed = new_speed func _physics_process(delta): stalking_check() if robot_win: velocity = Vector3(0, 0, -speed) move_and_slide() if not _game_lost_emitted: _walk_in_remaining -= delta if _walk_in_remaining <= 0.0: _game_lost_emitted = true EventBus.game_lost.emit(Strings.LOSS_ROBOT) return if stun_remaining > 0.0: stun_remaining -= delta velocity = Vector3.ZERO move_and_slide() return velocity = Vector3(0, 0, -speed) move_and_slide() func _on_area_3d_area_entered(area: Area3D) -> void: var safety = safety_zone if area == safety and doors_open and not robot_win: robot_win = true _walk_in_remaining = WALK_IN_DURATION func stalking_check(): var robot_position = self.global_transform.origin var elevator = safety_zone.global_transform.origin var distance = robot_position.distance_to(elevator) var current_modulation = $Sprite3D.modulate if distance >= STALK_DARK_DISTANCE: $Sprite3D.modulate = Color(0.0, 0.0, 0.0) if distance <= STALK_ILLUMINATE_DISTANCE: if not _stalking_close: _stalking_close = true EventBus.robot_close_warning.emit() illuminate() func illuminate(): var tween = create_tween().parallel() tween.tween_property($Sprite3D, "modulate",Color(1,1,1), 5)