extends KinematicBody onready var camera = $Camera onready var ray = $Camera/RayCast onready var ladder_area = $ladder_detector export var walk_speed : int = 10 export var accel : float = 0.2 export var gravity : int = -1 export var term_velocity : int = -35 export var jump_strength : int = 20 export var inertia : int = 5 var velocity : Vector3 var is_climbing : bool = false func _ready(): Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func _process(_delta): get_input() func _physics_process(_delta): handle_movement() handle_jumping() handle_collision() func get_input(): var dir : Vector3 = Vector3.ZERO #Get base movement input if Input.is_action_pressed("forward"): dir += -global_transform.basis.z if is_climbing: dir += global_transform.basis.y if Input.is_action_pressed("backward"): dir += global_transform.basis.z if is_climbing: dir += -global_transform.basis.y if Input.is_action_pressed("left"): dir += -global_transform.basis.x if Input.is_action_pressed("right"): dir += global_transform.basis.x dir = dir.normalized() #Pull X and Z values from directional input. Velocity.y will be handled in physics loop unless climbing. if is_climbing: velocity.y = lerp(velocity.y, dir.y * walk_speed, accel) velocity.x = lerp(velocity.x, dir.x * walk_speed, accel) velocity.z = lerp(velocity.z, dir.z * walk_speed, accel) func handle_movement(): #Apply gravity if !is_climbing: velocity.y += gravity if velocity.y < term_velocity: velocity.y = term_velocity velocity = move_and_slide_with_snap(velocity, Vector3.DOWN if velocity.y <= 0.0 else Vector3.ZERO, Vector3.UP, true, 4, PI/4, false) func _input(event): #Handle mouse movement for camera if event is InputEventMouseMotion: self.rotate_y(-event.relative.x * Settings.mouse_sens) camera.rotate_x(-event.relative.y * Settings.mouse_sens) camera.rotation.x = clamp(camera.rotation.x, -1.2, 1.2) func handle_jumping(): if Input.is_action_just_pressed("jump") and is_on_floor(): velocity.y = jump_strength func handle_collision(): for index in get_slide_count(): var collision = get_slide_collision(index) var collider = collision.collider if (collider.get_class() == "RigidBody"): var col_force_vec = -collision.normal * inertia # rotate the force along collision normal # collision pos # > RigidBody.add_force(force, pos) > The position uses the rotation of the global coordinate system, but is centered at the object's origin. # > KinematicCollision.position() > The point of collision, in global coordinates. # So to add force at collision position, substract colliders pos from collision.position var col_pos = collision.position - collider.transform.origin collider.add_force(col_force_vec, col_pos) func _on_ladder_detector_body_entered(body): if body.is_in_group("ladder"): is_climbing = true func _on_ladder_detector_body_exited(body): if body.is_in_group("ladder"): is_climbing = false