extends KinematicBody ###################-VARIABLES-#################### # Camera export(float) var mouse_sensitivity = 12.0 export(NodePath) var cam_path export(NodePath) var ai_follower = null export(float) var FOV = 90.0 var mouse_axis := Vector2() onready var cam: Camera = get_node(cam_path) # Move var velocity := Vector3() var direction := Vector3() var move_axis := Vector2() # Walk const FLOOR_MAX_ANGLE: float = deg2rad(46.0) export(float) var gravity = 17.35 export(float) var jump_height = 1.084 var jump_vel = 5.89#sqrt(2 * gravity * jump_height) var has_control = true var vehicle = null export(float) var acceleration = 70 export(int) var walk_speed = 6 export(float) var _airspeed_cap = 1 export(float) var friction = 4 export(float) var air_control = 1 var grappling = false var grapple_length = 0 var grapple_point = Vector3.ZERO # Fly export(int) var fly_speed = 50 export(int) var fly_accel = 10 var flying := false # Crouch var is_duck = 0 const duck_height = .5*.6*1.8 #one half the hitbox duck height var duck_speed = 2.3 var knockback_mult = 1 var duck_progress = 0 var world # Shoot var countdown = 0; export(float) var firing_cooldown = .8 export(Vector3) var snap ################################################## # Called when the node enters the scene tree func _ready() -> void: if ai_follower != null: ai_follower = get_node(ai_follower) flying = true Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) cam.fov = FOV $Camera/UseRay.add_exception(self) $Camera/MeleeRay.add_exception(self) world = get_parent() # Called every frame. 'delta' is the elapsed time since the previous frame func _process(_delta: float) -> void: if Input.is_action_just_pressed("use"): initiate_use() if !has_control: return if Input.is_action_just_pressed("fly"): flying = !flying if Input.is_action_just_pressed("fire"): if $Camera/MeleeRay.is_colliding(): grappling = true grapple_point = $Camera/MeleeRay.get_collision_point() grapple_length = (grapple_point-global_transform.origin).length() + 1 elif Input.is_action_just_released("fire"): grappling = false if Input.is_action_just_pressed("altfire"): cam.fov = 20 if cam.fov == FOV else FOV if countdown > 0: countdown -= _delta move_axis.x = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward") move_axis.y = Input.get_action_strength("move_right") - Input.get_action_strength("move_left") is_duck = Input.get_action_strength("duck") # Called every physics tick. 'delta' is constant func _physics_process(delta: float) -> void: if !has_control: move_axis = Vector2.ZERO if flying: fly(delta) else: walk(delta) static func compare_floats(a, b, epsilon = 0.00001): return abs(a - b) <= epsilon func regain_control(gt): #world.add_child(self) global_transform.origin = gt has_control = true vehicle = null func initiate_use(): if !has_control: vehicle.relinquish_control() return if $Camera/UseRay.is_colliding(): var type = $Camera/UseRay.get_collider().name match type: "SteerArea": if flying or $Camera/UseRay.get_collider().get_parent().is_in_use(): return has_control = false vehicle = $Camera/UseRay.get_collider().get_parent().take_control(self) var gt = global_transform.origin velocity = Vector3.ZERO #get_parent().remove_child(self) #vehicle.add_child(self) global_transform.origin = gt _: pass # Called when there is an input event func _input(event: InputEvent) -> void: if event is InputEventMouseMotion: mouse_axis = event.relative camera_rotation() func walk(delta: float) -> void: knockback_mult = 1.35 if is_duck else 1 if grappling: var grapple_vec = global_transform.origin - grapple_point var grapple_dist = grapple_vec.length() if grapple_dist >= grapple_length: velocity -= grapple_vec.dot(velocity)*grapple_vec/(grapple_dist*grapple_dist) var v = velocity.abs() velocity -= grapple_vec.normalized()*delta*v*v/grapple_dist # Duck if not compare_floats(duck_progress, is_duck): var h = $CollisionBox.get_shape().get_extents().y var dir = -1 if is_duck else 1 var dh = dir*duck_speed*delta var desh = duck_height if is_duck else 0.9 if abs(h+dh - desh) < .05: dh = desh-h $CollisionBox.get_shape().set_extents(Vector3(.325,h+dh,.325)) $CollisionBox.translate_object_local(Vector3(0,-dh/2,0)) duck_progress = 1-(h+dh-duck_height)/(0.9-duck_height) # Input direction = Vector3() var aim: Basis = get_global_transform().basis if move_axis.x >= 0.5: direction -= aim.z elif move_axis.x <= -0.5: direction += aim.z if move_axis.y <= -0.5: direction -= aim.x elif move_axis.y >= 0.5: direction += aim.x direction.y = 0 direction = direction.normalized() # Jump if is_on_floor(): snap = Vector3.DOWN if Input.is_action_just_pressed("move_jump"): snap = Vector3.ZERO velocity.y += jump_vel velocity.y -= gravity * delta if abs(velocity.y) > 1: snap = Vector3.ZERO #max walk speed var _speed = walk_speed if not is_duck else walk_speed*0.5 var _temp_accel: float = acceleration if not is_on_floor() or Input.is_action_just_pressed("move_jump"): _temp_accel *= air_control else: #apply friction var _cspeed = sqrt(pow(velocity.x,2)+pow(velocity.z,2)) if _cspeed != 0: var walkdir = Vector2(velocity.x,velocity.z) var fvar = _cspeed*friction if direction.length() != 0 else _cspeed*2*friction #fvar *= 4 if is_duck else 1 velocity.x -= walkdir.normalized().x*fvar*delta velocity.z -= walkdir.normalized().y*fvar*delta var projVel = Vector2(velocity.x,velocity.z).dot(Vector2(direction.x,direction.z)) _temp_accel *= delta if is_on_floor(): if _speed - (projVel + _temp_accel) > 0: velocity.x += direction.x*_temp_accel velocity.z += direction.z*_temp_accel else: velocity.x += direction.x*(_speed-projVel) velocity.z += direction.z*(_speed-projVel) elif _airspeed_cap - projVel > 0: velocity.x += direction.x*_temp_accel velocity.z += direction.z*_temp_accel # clamping (to stop on slopes) if direction.dot(velocity) == 0: var _vel_clamp := 0.25 if abs(velocity.x) < _vel_clamp: velocity.x = 0 if abs(velocity.z) < _vel_clamp: velocity.z = 0 # Move var landed = is_on_floor() == false #remove_collision_exception_with(rigid_body) var moving = move_and_slide_with_snap(velocity, snap,Vector3.UP, true, 4, FLOOR_MAX_ANGLE, false) landed = landed and is_on_floor() # if is_on_wall(): # #velocity.x = moving.x # #velocity.z = moving.z # velocity = moving if landed: velocity -= get_slide_collision(0).collider_velocity else: velocity = moving func fly(delta: float) -> void: # Input direction = Vector3() var aim = cam.get_global_transform().basis if move_axis.x >= 0.5: direction -= aim.z elif move_axis.x <= -0.5: direction += aim.z if move_axis.y <= -0.5: direction -= aim.x elif move_axis.y >= 0.5: direction += aim.x direction = direction.normalized() # Acceleration and Deacceleration var target: Vector3 = direction * 300 velocity = velocity.linear_interpolate(target, fly_accel * delta) # Move velocity = move_and_slide(velocity, Vector3.UP, false, 4, 45.0, false) func camera_rotation() -> void: if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED: return if mouse_axis.length() > 0: var horizontal: float = -mouse_axis.x * (mouse_sensitivity / 100) var vertical: float = -mouse_axis.y * (mouse_sensitivity / 100) mouse_axis = Vector2() rotate_y(deg2rad(horizontal)) cam.rotate_x(deg2rad(vertical)) # Clamp mouse rotation var temp_rot: Vector3 = cam.rotation_degrees temp_rot.x = clamp(temp_rot.x, -90, 90) cam.rotation_degrees = temp_rot