1extends KinematicBody
2
3# Walking variables.
4const norm_grav = -38.8
5const MAX_SPEED = 22
6const JUMP_SPEED = 26
7const ACCEL= 8.5
8# Sprinting variables. Similar to the varibles above, just allowing for quicker movement
9const MAX_SPRINT_SPEED = 34
10const SPRINT_ACCEL = 18
11# How fast we slow down, and the steepest angle we can climb.
12const DEACCEL= 28
13const MAX_SLOPE_ANGLE = 40
14# How fast the bullets launch
15const LEFT_MOUSE_FIRE_TIME = 0.15
16const BULLET_SPEED = 100
17
18var vel = Vector3()
19# A vector for storing the direction the player intends to walk towards.
20var dir = Vector3()
21# A boolean to track whether or not we are sprinting
22var is_sprinting = false
23
24
25# You may need to adjust depending on the sensitivity of your mouse
26var MOUSE_SENSITIVITY = 0.08
27
28# A boolean for tracking whether the jump button is down
29var jump_button_down = false
30
31# The current lean value (our position on the lean track) and the path follow node
32var lean_value = 0.5
33
34# A variable for tracking if the right mouse button is down.
35var right_mouse_down = false
36# A variable for tracking if we can fire using the left mouse button
37var left_mouse_timer = 0
38
39# A boolean for tracking whether we can change animations or not
40var anim_done = true
41# The current animation name
42var current_anim = "Starter"
43
44# The simple bullet rigidbody
45var simple_bullet = preload("res://fps/simple_bullet.tscn")
46
47
48# We need the camera for getting directional vectors. We rotate ourselves on the Y-axis using
49# the camera_holder to avoid rotating on more than one axis at a time.
50onready var camera_holder = $CameraHolder
51onready var camera = $CameraHolder/LeanPath/PathFollow/IK_LookAt_Chest/Camera
52onready var path_follow_node = $CameraHolder/LeanPath/PathFollow
53# The animation player for aiming down the sights.
54onready var anim_player = $CameraHolder/AnimationPlayer
55# The end of the pistol.
56onready var pistol_end = $CameraHolder/Weapon/Pistol/PistolEnd
57
58
59func _ready():
60	anim_player.connect("animation_finished", self, "animation_finished")
61
62	set_physics_process(true)
63	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
64	set_process_input(true)
65
66
67func _physics_process(delta):
68	process_input(delta)
69	process_movement(delta)
70
71
72func process_input(delta):
73
74	# Reset dir, so our previous movement does not effect us
75	dir = Vector3()
76	# Get the camera's global transform so we can use its directional vectors
77	var cam_xform = camera.get_global_transform()
78
79	# ----------------------------------
80	# Walking
81	if Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_W):
82		dir += -cam_xform.basis[2]
83	if Input.is_key_pressed(KEY_DOWN) or Input.is_key_pressed(KEY_S):
84		dir += cam_xform.basis[2]
85	if Input.is_key_pressed(KEY_LEFT) or Input.is_key_pressed(KEY_A):
86		dir += -cam_xform.basis[0]
87	if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D):
88		dir += cam_xform.basis[0]
89
90	if Input.is_action_just_pressed("ui_cancel"):
91		if Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE:
92			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
93		else:
94			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
95
96	if Input.is_mouse_button_pressed(2):
97		if not right_mouse_down:
98			right_mouse_down = true
99
100			if anim_done:
101				if current_anim != "Aiming":
102					anim_player.play("Aiming")
103					current_anim = "Aiming"
104				else:
105					anim_player.play("Idle")
106					current_anim = "Idle"
107
108				anim_done = false
109	else:
110		right_mouse_down = false
111
112	if Input.is_mouse_button_pressed(1):
113		if left_mouse_timer <= 0:
114			left_mouse_timer = LEFT_MOUSE_FIRE_TIME
115
116			# Create a bullet
117			var new_bullet = simple_bullet.instance()
118			get_tree().root.add_child(new_bullet)
119			new_bullet.global_transform = pistol_end.global_transform
120			new_bullet.linear_velocity = new_bullet.global_transform.basis.z * BULLET_SPEED
121	if left_mouse_timer > 0:
122		left_mouse_timer -= delta
123	# ----------------------------------
124
125
126	# ----------------------------------
127	# Sprinting
128	if Input.is_key_pressed(KEY_SHIFT):
129		is_sprinting = true
130	else:
131		is_sprinting = false
132	# ----------------------------------
133
134	# ----------------------------------
135	# Jumping
136	if Input.is_key_pressed(KEY_SPACE):
137		if not jump_button_down:
138			jump_button_down = true
139			if is_on_floor():
140				vel.y = JUMP_SPEED
141	else:
142		jump_button_down = false
143	# ----------------------------------
144
145
146	# ----------------------------------
147	# Leaninng
148	if Input.is_key_pressed(KEY_Q):
149		lean_value += 1.2 * delta
150	elif Input.is_key_pressed(KEY_E):
151		lean_value -= 1.2 * delta
152	else:
153		if lean_value > 0.5:
154			lean_value -= 1 * delta
155			if lean_value < 0.5:
156				lean_value = 0.5
157		elif lean_value < 0.5:
158			lean_value += 1 * delta
159			if lean_value > 0.5:
160				lean_value = 0.5
161
162	lean_value = clamp(lean_value, 0, 1)
163	path_follow_node.unit_offset = lean_value
164	if lean_value < 0.5:
165		var lerp_value = lean_value * 2
166		path_follow_node.rotation_degrees.z = (20 * (1 - lerp_value))
167	else:
168		var lerp_value = (lean_value - 0.5) * 2
169		path_follow_node.rotation_degrees.z = (-20 * lerp_value)
170	# ----------------------------------
171
172
173func process_movement(delta):
174
175	var grav = norm_grav
176
177	dir.y = 0
178	dir = dir.normalized()
179
180	vel.y += delta*grav
181
182	var hvel = vel
183	hvel.y = 0
184
185	var target = dir
186	if is_sprinting:
187		target *= MAX_SPRINT_SPEED
188	else:
189		target *= MAX_SPEED
190
191
192	var accel
193	if dir.dot(hvel) > 0:
194		if not is_sprinting:
195			accel = ACCEL
196		else:
197			accel = SPRINT_ACCEL
198	else:
199		accel = DEACCEL
200
201	hvel = hvel.linear_interpolate(target, accel*delta)
202
203	vel.x = hvel.x
204	vel.z = hvel.z
205
206	vel = move_and_slide(vel,Vector3(0,1,0))
207
208
209# Mouse based camera movement
210func _input(event):
211
212	if event is InputEventMouseMotion && Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
213
214		rotate_y(deg2rad(event.relative.x * MOUSE_SENSITIVITY * -1))
215		camera_holder.rotate_x(deg2rad(event.relative.y * MOUSE_SENSITIVITY))
216
217		# We need to clamp the camera's rotation so we cannot rotate ourselves upside down
218		var camera_rot = camera_holder.rotation_degrees
219		if camera_rot.x < -40:
220			camera_rot.x = -40
221		elif camera_rot.x > 60:
222			camera_rot.x = 60
223
224		camera_holder.rotation_degrees = camera_rot
225
226	else:
227		pass
228
229
230func animation_finished(_anim):
231	anim_done = true
232