extends CharacterBody3D const JUMP_SPEED: float = 5 const MOUSE_SENSITIVITY: float = 0.002 const CROUCH_MOVE_SPEED: float = 3 const BASE_MOVE_SPEED: float = 5 const SPRINT_MOVE_SPEED: float = 8 const BASE_HEIGHT: float = 2.0 const CROUCH_HEIGHT: float = 1.0 enum MovementMode { Crouching, Sprinting, Walking, } var current_movement := MovementMode.Walking var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") var move_speed: float = BASE_MOVE_SPEED @onready var body_collision_shape: CollisionShape3D = $BodyCollisionShape @onready var fps_camera: Camera3D = $FPSCamera @onready var head_collision_shape: CollisionShape3D \ = $HeadCollider/HeadCollisionShape @onready var head_collider: Area3D = $HeadCollider func _ready() -> void: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED head_collision_shape.set_deferred("disabled", true) func _process(delta: float) -> void: if Input.is_action_just_pressed("pause"): if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE else: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED func _physics_process(delta: float) -> void: velocity.y += -gravity * delta var input = Input.get_vector("strafe_left", "strafe_right", "move_forward", "move_backward") if Input.is_action_pressed("sprint") \ and current_movement != MovementMode.Crouching: move_speed = SPRINT_MOVE_SPEED current_movement = MovementMode.Sprinting elif Input.is_action_pressed("crouch") \ and current_movement != MovementMode.Sprinting: move_speed = CROUCH_MOVE_SPEED current_movement = MovementMode.Crouching else: move_speed = BASE_MOVE_SPEED current_movement = MovementMode.Walking if current_movement == MovementMode.Crouching: body_collision_shape.shape.height = CROUCH_HEIGHT head_collision_shape.set_deferred("disabled", false) elif not head_collider.has_overlapping_bodies(): body_collision_shape.shape.height = BASE_HEIGHT head_collision_shape.set_deferred("disabled", true) var movement_dir := transform.basis * Vector3(input.x, 0, input.y) velocity.x = movement_dir.x * move_speed velocity.z = movement_dir.z * move_speed move_and_slide() if is_on_floor() and Input.is_action_just_pressed("jump"): velocity.y = JUMP_SPEED func _input(event: InputEvent) -> void: if event is InputEventMouseMotion \ and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: rotate_y(-event.relative.x * MOUSE_SENSITIVITY) fps_camera.rotate_x(-event.relative.y * MOUSE_SENSITIVITY) fps_camera.rotation.x = clampf(fps_camera.rotation.x, -deg_to_rad(70), deg_to_rad(70))