class_name Player extends CharacterBody3D const RUN_SPEED := 80.0 const SPRINT_SPEED := 160.0 const AIR_SPEED := 10.0 const JUMP_FORCE := 4.5 const GROUND_FRICTION := 0.3 const AIR_FRICTION := 0.03 const SPRAY_SCALE := 8 var gravity: Vector3 = ( ProjectSettings.get_setting("physics/3d/default_gravity") * ProjectSettings.get_setting("physics/3d/default_gravity_vector") ) @onready var camera_pivot: Node3D = %CameraPivot @onready var spray_muzzle: Marker3D = %SprayMuzzle @onready var ray_cast_left: RayCast3D = %RayCastLeft @onready var ray_cast_right: RayCast3D = %RayCastRight @onready var spray_effect: MeshInstance3D = %SprayEffect func get_speed() -> float: if is_on_floor(): if Input.is_action_pressed("sprint"): return SPRINT_SPEED return RUN_SPEED return AIR_SPEED func get_friction() -> float: if is_on_floor(): return GROUND_FRICTION return AIR_FRICTION func _scale_spray_point(point: Vector3) -> float: return point.distance_to(spray_muzzle.global_position) * SPRAY_SCALE func fire_spray() -> void: if ray_cast_left.is_colliding() and ray_cast_right.is_colliding(): var collider := ray_cast_left.get_collider() if collider is GunkBody and collider == ray_cast_right.get_collider(): var point_left := ray_cast_left.get_collision_point() var point_right := ray_cast_right.get_collision_point() (collider as GunkBody).paint_bar( point_left, ray_cast_left.get_collision_normal(), _scale_spray_point(point_left), point_right, ray_cast_right.get_collision_normal(), _scale_spray_point(point_right) ) func _physics_process(delta: float) -> void: if Input.is_action_pressed("fire"): fire_spray() spray_effect.visible = true else: spray_effect.visible = false # Gravity if not is_on_floor(): velocity += gravity * delta # Input movement var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_back") var direction := ( (camera_pivot.global_basis * Vector3(input_dir.x, 0, input_dir.y) * Vector3(1, 0, 1)) . normalized() ) var movement := direction * get_speed() * delta velocity.x += movement.x velocity.z += movement.z if Input.is_action_just_pressed("jump") and is_on_floor(): velocity.y = JUMP_FORCE # Friction var friction := get_friction() velocity.x = lerpf(velocity.x, 0, friction) velocity.z = lerpf(velocity.z, 0, friction) move_and_slide()