extends RigidBody3D var has_stage: bool = false: set(focused): if has_stage != focused: if focused: has_stage = true if is_inside_tree(): camera.make_current() get_viewport().gui_release_focus() Input.mouse_mode = Input.MOUSE_MODE_CAPTURED var jitter_tween: Tween = create_tween() jitter_tween.tween_property(self, "jitter_strength", 1, 1) if has_entered: emit_signal("ui_entered") elif has_stage: camera.current = true jitter_strength = 1 else: if is_inside_tree() and has_stage: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE var jitter_tween: Tween = create_tween() jitter_tween.tween_property(self, "jitter_strength", 0, 0.5) if has_entered: emit_signal("ui_exited") else: jitter_strength = 0 has_stage = false sleeping = has_stage @export_range (0, 10) var max_speed: float = 3 @export_range (0, 10) var max_acceleration: float = 5 @export_range (0, 20) var damp: float = 10 @export_range (0.1, 1) var mouse_jerk:float = 0.5 @export_range (10, 100) var gamepad_response = 50 @export_range (50, 500) var mouse_jerk_rejection = 200 @export var max_angle:float = 75 @export var camera_jitter_speed:float = 3 @export var angular_jitter:Vector3 = Vector3(0.1, 0, 0.05) @export var angular_jitter_speed:Vector3 = Vector3(2, 1, 1) @export var location_jitter:Vector3 = Vector3(0.05, 0.05, 0.05) @export var location_jitter_speed:Vector3 = Vector3(2, 0.3, 1) var jitter_strength: float = 0 var loc_noise_spot: Vector3 = Vector3.ZERO var rot_noise_spot: Vector3 = Vector3.ZERO var rotation_speed: Vector2 = Vector2.ZERO var current_mouse_rotation: Vector2 = Vector2.ZERO var mouse_sensitivity: Vector2 = Vector2(3, 3) var noise: Noise = FastNoiseLite.new() var crouched:bool = false var on_crouch_cooldown:bool = false @onready var yaw:Node3D = $Yaw @onready var pitch:Node3D = $Yaw/Pitch @onready var mount:Node3D = $Yaw/Pitch/Mount @onready var camera:Camera3D = $Yaw/Pitch/Mount/Camera3D @onready var focus_ray: RayCast3D = $Yaw/Pitch/Mount/Camera3D/RayCast3D signal ui_entered var has_entered:bool = false signal ui_exited func _ready(): _handle_jitter(0) func _on_ini_room(): State.take_stage(self) get_tree().call_group("animation_player", "play_scene", Scenes.id.YOUTH_DRAEVEN, false) State.queue_for_stage(self) func _process(_delta): if focus_ray.get_collider() != null: emit_signal("ui_entered") has_entered = true focus_ray.get_collider().reveal() if has_entered and has_stage: if focus_ray.get_collider() == null: emit_signal("ui_exited") has_entered = false if Input.is_action_just_pressed("ui_accept"): State.pass_stage_to(focus_ray.get_collider()) func _physics_process(delta:float): if has_stage: _handle_movement(delta) _handle_rotation(delta) if jitter_strength > 0: _handle_jitter(delta) func _handle_movement(delta:float): var input:Vector2 = Vector2(Input.get_action_strength("player_right") - Input.get_action_strength("player_left"), Input.get_action_strength("player_backwards")*0.8 - Input.get_action_strength("player_forwards")) if input.length()>1: input = input.normalized() var direction: Vector3 = Vector3(input.x, 0, input.y) direction = yaw.global_transform.basis.x * direction.x + transform.basis.y * direction.y + yaw.global_transform.basis.z * direction.z if linear_velocity.length() > (linear_velocity + (direction*max_speed - linear_velocity)).length(): direction = Vector3.ZERO else: direction *= (direction*max_speed - linear_velocity).length()*max_acceleration linear_damp = damp * max(0.5, 1 - input.length()) apply_central_impulse(direction*delta) func _handle_rotation(delta:float): var smoothness = min(3, 60.0/Engine.get_frames_per_second()) var input_speed = Vector2( Input.get_action_strength("look_right")-Input.get_action_strength("look_left"), Input.get_action_strength("look_up")-Input.get_action_strength("look_down")) * gamepad_response if current_mouse_rotation.length()>0: input_speed = current_mouse_rotation current_mouse_rotation = Vector2.ZERO rotation_speed = rotation_speed * (1-mouse_jerk*smoothness) + input_speed * mouse_jerk * smoothness if rotation_speed.y > 0 and pitch.rotation_degrees.x < 0: rotation_speed.y *= 1-pow(pitch.rotation_degrees.x/-max_angle, 4) elif rotation_speed.y < 0 and pitch.rotation_degrees.x > 0 : rotation_speed.y *= 1-pow(pitch.rotation_degrees.x/max_angle, 4) yaw.rotate_y(deg_to_rad(-rotation_speed.x * delta * mouse_sensitivity.x)) pitch.rotate_x(deg_to_rad(-rotation_speed.y * delta * mouse_sensitivity.y)) func _handle_jitter(delta): loc_noise_spot += Vector3(delta * camera_jitter_speed * location_jitter_speed) rot_noise_spot += Vector3(delta * camera_jitter_speed * angular_jitter_speed) pitch.position = Vector3( noise.get_noise_1d(loc_noise_spot.x), noise.get_noise_1d(loc_noise_spot.y), noise.get_noise_1d(loc_noise_spot.z) ) * location_jitter * jitter_strength mount.rotation = Vector3( noise.get_noise_1d(rot_noise_spot.x), noise.get_noise_1d(rot_noise_spot.y), noise.get_noise_1d(rot_noise_spot.z) ) * angular_jitter * jitter_strength func _handle_mouse_input(event:InputEventMouseMotion): if event.relative.length() < mouse_jerk_rejection: current_mouse_rotation = event.relative func _input(event:InputEvent): if has_stage: if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: _handle_mouse_input(event) get_viewport().set_input_as_handled() if event is InputEventMouseButton and event.pressed: State.free_focus() get_tree().call_group("interactables", "reveal") #if event.is_action_pressed("ui_accept"): # State.pass_stage_to(focus_ray.get_collider()) # get_viewport().set_input_as_handled() else: if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed: if !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): State.take_stage(self, true) get_tree().call_group("interactables", "collapse") func play_scene(id: int, _repeat): if id == Scenes.id.YOUTH_DRAEVEN: var rotation_tween = create_tween() func scene_finished(_id, repeat: bool): if repeat: State.take_stage(self, true) func _on_bed_enter(_body): if not (crouched or on_crouch_cooldown): $PlayerAnimationPlayer.queue("crouch") var tween = create_tween() tween.tween_property(self, "max_speed", max_speed/2, 0.3) crouched = true func _on_bed_exit(_body): if crouched: crouched = false $PlayerAnimationPlayer.queue("stand_up") var tween = create_tween() tween.tween_property(self, "max_speed", max_speed*2, 1) on_crouch_cooldown = true await get_tree().create_timer(1.0).timeout on_crouch_cooldown = false