extends KinematicBody ###################-VARIABLES-#################### # Camera export var mouse_sensitivity := 10.0 export var head_path: NodePath export var cam_path: NodePath export var FOV := 80.0 var mouse_axis := Vector2() onready var head: Spatial = get_node(head_path) onready var cam: Camera = get_node(cam_path) # Move var velocity := Vector3() var direction := Vector3() var move_axis := Vector2() var can_sprint := true var sprinting := false # Walk const FLOOR_NORMAL := Vector3(0, 1, 0) export var gravity := 30.0 export var walk_speed := 50 export var sprint_speed := 16 export var acceleration := 8 export var deacceleration := 10 export(float, 0.0, 1.0, 0.05) var air_control := 0.3 export var jump_height := 10 # Fly export var fly_speed := 20 export var fly_accel := 2 var flying := false # Slopes export var floor_max_angle := 90.0 var mouse_press = false var capture_mouse = false var process_3d_inputs = true #### custom amazed var target: Dictionary var weapon_held: Weapon onready var weapon_refpt_right = $Reaper2/Armature/Skeleton/righthand onready var weapon_refpt_left = $Reaper2/Armature/Skeleton/lefthand var weapons = [ preload("res://weapons/sword.tscn"), preload("res://weapons/bow.tscn"), preload("res://weapons/bow_rpg.tscn"), ] var weapon_slot = 0 export var draw_debug_lines: bool = false var state_initialized: bool = true var current_movement_vector: Vector2 = Vector2.ZERO onready var camera_trans = $Head/Camera.transform ################################################## func get_weapon() -> Weapon: return weapon_held func create_empty_collision_dictionnary(to: Vector3) -> Dictionary: return { "position": to, "normal": null, "collider_id": null, "collider": null, "shape": null, "rid": null } func draw_line(ig: ImmediateGeometry, a: Vector3, b: Vector3): if draw_debug_lines: ig.points = [a, b] func get_target() -> Dictionary: var weapon = get_weapon() # var ray_from = weapon.global_transform.origin var ray_from = cam.global_transform.origin var ray_to = cam.global_transform.basis.z * -20000 var space_state = get_world().direct_space_state var result = space_state.intersect_ray(ray_from, ray_to, [self, weapon]) if not result: return create_empty_collision_dictionnary(ray_to) else: return result # Called when the node enters the scene tree func _ready() -> void: cam.fov = FOV Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) set_weapon(weapons[weapon_slot]) if not draw_debug_lines: $LineRenderercamera.queue_free() $LineRendererweapon.queue_free() func set_weapon(weapon_scene: PackedScene): if weapon_held: weapon_held.queue_free() var weapon = weapon_scene.instance() if weapon.held_hand == "left": weapon_refpt_left.add_child(weapon) else: weapon_refpt_right.add_child(weapon) weapon_held = weapon weapon_held.holder = self # Called every frame. 'delta' is the elapsed time since the previous frame func _process(_delta: float) -> void: if process_3d_inputs: 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") camera_rotation() # Called every physics tick. 'delta' is constant func _physics_process(delta: float) -> void: if flying: fly(delta) else: walk(delta) $fps.text = "FPS: " + str(Engine.get_frames_per_second()) + " | Objects: " + str(Performance.get_monitor(Performance.OBJECT_COUNT)) target = get_target() if draw_debug_lines: draw_line($LineRenderercamera, cam.global_transform.origin, target["position"]) draw_line($LineRendererweapon, weapon_held.global_transform.origin, target["position"]) if target["collider"] and target["collider"] is Entity: $UI/cursor_no_enemy.visible = false $UI/cursor_enemy.visible = true else: $UI/cursor_enemy.visible = false $UI/cursor_no_enemy.visible = true var movement_vector = Vector2.ZERO if process_3d_inputs and Input.is_action_pressed("move_forward"): movement_vector.y = 1 if process_3d_inputs and Input.is_action_pressed("move_backward"): movement_vector.y = -1 if process_3d_inputs and Input.is_action_pressed("move_right"): movement_vector.x = 1 if process_3d_inputs and Input.is_action_pressed("move_left"): movement_vector.x = -1 var res = current_movement_vector.linear_interpolate(movement_vector, delta*10) $Reaper2/AnimationTree.set("parameters/movement/blend_position", res) current_movement_vector = res # Called when there is an input event func _input(event: InputEvent) -> void: if not process_3d_inputs: return if event is InputEventMouseMotion: mouse_axis = event.relative if Input.is_action_just_pressed("inp_fire"): weapon_held.activate(target["position"]) if Input.is_action_just_released("inp_fire"): weapon_held.deactivate(target["position"]) if Input.is_action_just_pressed("weapon_forward"): $player_audio.play() if weapon_slot == len(weapons) - 1: weapon_slot = 0 else: weapon_slot += 1 set_weapon(weapons[weapon_slot]) if Input.is_action_pressed("camera_front"): var camera_front_transform = camera_trans camera_front_transform = camera_trans.translated(Vector3(5, 0, -5)) camera_front_transform = camera_front_transform.rotated(Vector3.UP, deg2rad(-180)) $Head/Camera.transform = camera_front_transform else: $Head/Camera.transform = camera_trans if process_3d_inputs and Input.is_action_just_pressed("ui_cancel"): var ingame_menu = preload("res://ui/ingame_menu.tscn").instance() Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED) add_child(ingame_menu) ingame_menu.connect("tree_exited", self, "_ingamemenu_closed") process_3d_inputs = false func _ingamemenu_closed(): process_3d_inputs = true Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func walk(delta: float) -> void: # Input direction = Vector3() var aim: Basis = get_global_transform().basis if move_axis.x >= 0.5: direction -= aim.z if move_axis.x <= -0.5: direction += aim.z if move_axis.y <= -0.5: direction -= aim.x if move_axis.y >= 0.5: direction += aim.x direction.y = 0 direction = direction.normalized() # Jump var _snap: Vector3 if is_on_floor(): _snap = Vector3(0, -1, 0) if process_3d_inputs and Input.is_action_just_pressed("move_jump"): _snap = Vector3(0, 0, 0) velocity.y = jump_height # Apply Gravity velocity.y -= gravity * delta # Sprint var _speed: int if (process_3d_inputs and Input.is_action_pressed("move_sprint") and can_sprint and move_axis.x == 1): _speed = sprint_speed cam.set_fov(lerp(cam.fov, FOV * 1.2, delta * 8)) sprinting = true else: _speed = walk_speed cam.set_fov(lerp(cam.fov, FOV, delta * 8)) sprinting = false # Acceleration and Deacceleration # where would the player go var _temp_vel: Vector3 = velocity _temp_vel.y = 0 var _target: Vector3 = direction * _speed var _temp_accel: float if direction.dot(_temp_vel) > 0: _temp_accel = acceleration else: _temp_accel = deacceleration if not is_on_floor(): _temp_accel *= air_control # interpolation _temp_vel = _temp_vel.linear_interpolate(_target, _temp_accel * delta) velocity.x = _temp_vel.x velocity.z = _temp_vel.z # clamping (to stop on slopes) if direction.dot(velocity) == 0: var _vel_clamp := 0.1 if velocity.x < _vel_clamp and velocity.x > -_vel_clamp: velocity.x = 0 if velocity.z < _vel_clamp and velocity.z > -_vel_clamp: velocity.z = 0 # Move velocity.y = move_and_slide_with_snap(velocity, _snap, FLOOR_NORMAL, true, 4, deg2rad(floor_max_angle)).y func fly(delta: float) -> void: # Input direction = Vector3() var aim = head.get_global_transform().basis if move_axis.x == 1: direction -= aim.z if move_axis.x == -1: direction += aim.z if move_axis.y == -1: direction -= aim.x if move_axis.y == 1: direction += aim.x direction = direction.normalized() # Acceleration and Deacceleration var _target: Vector3 = direction * fly_speed velocity = velocity.linear_interpolate(_target, fly_accel * delta) # Move velocity = move_and_slide(velocity) func camera_rotation() -> void: if mouse_axis.length() > 0: var _smoothness := 80 # Get mouse delta var horizontal: float = -(mouse_axis.x * mouse_sensitivity) / _smoothness var vertical: float = -(mouse_axis.y * mouse_sensitivity) / _smoothness mouse_axis = Vector2() rotate_y(deg2rad(horizontal)) head.rotate_x(deg2rad(vertical)) # Clamp mouse rotation var temp_rot: Vector3 = head.rotation_degrees temp_rot.x = clamp(temp_rot.x, -75, 75) head.rotation_degrees = temp_rot