305 lines
8.4 KiB
GDScript
305 lines
8.4 KiB
GDScript
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
|
|
|