2021-06-07 19:11:42 +02:00
extends CharacterBody3D
2021-05-19 00:56:18 +02:00
2021-09-07 23:23:48 +02:00
@ export var mouse_sensitivity : = 0.15
2021-05-19 00:56:18 +02:00
2021-08-21 15:03:51 +02:00
@ onready var main = get_tree ( ) . root . get_node ( " Main " )
2021-09-11 15:52:09 +02:00
@ onready var gui = main . get_node ( " GUI " )
@ onready var settings = gui . settings
2021-08-21 15:03:51 +02:00
@ onready var hud = main . get_node ( " HUD " )
2021-07-16 02:52:18 +02:00
@ onready var crosshair = hud . get_node ( " Crosshair " )
@ onready var vignette = hud . get_node ( " Vignette " )
2021-05-19 00:56:18 +02:00
@ onready var head = $ Head
2021-05-24 21:57:19 +02:00
@ onready var camera = $ Head / Camera
@ onready var tween = $ Head / Camera / Tween
2021-05-22 02:10:00 +02:00
@ onready var ground_check = $ GroundCheck
2021-07-12 22:40:23 +02:00
@ onready var climb_tween = $ ClimbTween # undergoing redesign in Godot 4
2021-05-24 21:57:19 +02:00
@ onready var climb_check = $ ClimbCheck
@ onready var body = $ Body
2021-05-25 01:14:37 +02:00
@ onready var mesh = $ Mesh
2021-06-18 01:43:10 +02:00
@ onready var weapon = $ Head / Camera / Hand / Weapon
2021-09-08 23:25:52 +02:00
var gibs_vfx = preload ( " res://Assets/Effects/Gibs.tscn " )
2021-09-04 22:37:13 +02:00
# climb functions - temporarily disabled
#@onready var body_height = body.shape.height
#@onready var body_y = body.position.y
#@onready var mesh_height = mesh.mesh.mid_height
#@onready var mesh_y = mesh.position.y
#@onready var climb_check_y = climb_check.position.y
2021-06-07 19:11:42 +02:00
@ onready var ground_check_y = ground_check . position . y
2021-05-24 21:57:19 +02:00
2021-06-03 17:44:25 +02:00
var input_active = false
2021-05-24 21:57:19 +02:00
var base_fov = 90
2021-07-26 20:51:54 +02:00
var view_zoom_target : = 1.0
var view_zoom_direction = true
var view_zoom : = view_zoom_target :
2021-05-24 21:57:19 +02:00
set ( zoom ) :
view_zoom = zoom
camera . fov = base_fov / zoom
2021-05-24 22:18:46 +02:00
crosshair . modulate . a = clamp ( 1 - ( zoom - 1 ) , 0 , 1 )
vignette . modulate . a = ( zoom - 1 ) / 3
2021-05-24 21:57:19 +02:00
2021-09-04 22:37:13 +02:00
# climbing code - disabled for now
#var climb_height := 0.75
#var climb_time := 0.15
#var climb_state := 0.0 :
# set(factor):
# #print("climb_state is now ", factor)
# climb_state = factor
# body.shape.height = body_height - factor * climb_height
# body.position.y = body_y + factor * climb_height / 2
#
# mesh.mesh.mid_height = mesh_height - factor * climb_height
# mesh.position.y = mesh_y + factor * climb_height / 2
#
# ground_check.position.y = ground_check_y + factor * climb_height / 2
# climb_check.position.y = climb_check_y + factor * climb_height / 2
2021-05-19 00:56:18 +02:00
2021-05-19 01:59:58 +02:00
var direction : = Vector3 . ZERO
var accel : = 0
var speed : = 0
var medium = " ground "
var accel_type : = {
" ground " : 12 ,
" air " : 1 ,
" water " : 4
}
var speed_type : = {
2021-05-24 21:57:19 +02:00
" ground " : 10 ,
" air " : 10 ,
" water " : 5
2021-05-19 01:59:58 +02:00
}
2021-05-19 00:56:18 +02:00
var gravity : = 28
2021-09-07 23:23:48 +02:00
var jump : = 14 * 1
var jetpack_active = false
var jetpack_thrust = 48 # force applied against gravity
var jetpack_tank = 0.5 # maximum fuel (jetpack use time
var jetpack_fuel = jetpack_tank # current fuel (use time) left
var jetpack_recharge = 0.25 # how long to recharge to full
2021-09-08 23:54:04 +02:00
var jetpack_min = 1 / 4
var jetpack_was_active = false
2021-05-19 00:56:18 +02:00
2021-05-19 01:59:58 +02:00
var velocity : = Vector3 . ZERO
2021-05-19 00:56:18 +02:00
var gravity_vec : = Vector3 . ZERO
2021-09-08 21:36:43 +02:00
@ rpc ( nosync , unreliable ) func update_movement ( player_transform , head_rotation , lin_velocity , jetpack ) :
2021-07-12 22:40:23 +02:00
global_transform = player_transform
head . set_rotation ( head_rotation )
2021-09-07 23:23:48 +02:00
jetpack_active = jetpack
2021-09-08 21:36:43 +02:00
linear_velocity = lin_velocity
2021-06-19 03:40:10 +02:00
2021-05-19 00:56:18 +02:00
func _ready ( ) - > void :
2021-06-03 17:44:25 +02:00
#Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
2021-07-26 20:51:54 +02:00
view_zoom_target = 1.0
2021-06-19 00:31:22 +02:00
2021-08-21 15:03:51 +02:00
# generate_info()
2021-07-12 22:40:23 +02:00
2021-09-04 22:37:13 +02:00
rpc_config ( & ' move_and_slide ' , MultiplayerAPI . RPC_MODE_ANY )
rpc_config ( & " aim " , MultiplayerAPI . RPC_MODE_ANY )
rpc_config ( & " set_global_transform " , MultiplayerAPI . RPC_MODE_ANY )
rpc_config ( & " set_linear_velocity " , MultiplayerAPI . RPC_MODE_ANY )
head . rpc_config ( & " set_rotation " , MultiplayerAPI . RPC_MODE_ANY )
rpc_config ( & " set_info " , MultiplayerAPI . RPC_MODE_ANY )
2021-07-12 22:40:23 +02:00
# rpc_config(&'move_and_slide', MultiplayerAPI.RPC_MODE_PUPPETSYNC)
# rpc_config(&"aim", MultiplayerAPI.RPC_MODE_PUPPETSYNC)
# rpc_config(&"set_global_transform", MultiplayerAPI.RPC_MODE_PUPPET)
# rpc_config(&"set_linear_velocity", MultiplayerAPI.RPC_MODE_PUPPET)
# head.rpc_config(&"set_rotation", MultiplayerAPI.RPC_MODE_PUPPETSYNC)
# rpc_config(&"set_info", MultiplayerAPI.RPC_MODE_PUPPETSYNC)
2021-09-10 02:04:27 +02:00
if is_network_authority ( ) : # prevent puppets from attempting to steer the authority - this just causes RPC errors
input_active = true
else :
input_active = false
2021-06-09 19:41:52 +02:00
2021-05-19 00:56:18 +02:00
func aim ( event ) - > void :
var mouse_motion = event as InputEventMouseMotion
if mouse_motion :
2021-09-11 15:52:09 +02:00
var adjusted_mouse_sensitivity = 1.0
if " Sensitivity " in settings . keys ( ) :
adjusted_mouse_sensitivity = mouse_sensitivity * settings [ " Sensitivity " ]
rotation . y -= deg2rad ( mouse_motion . relative . x * adjusted_mouse_sensitivity / view_zoom )
2021-05-19 00:56:18 +02:00
2021-07-04 00:42:42 +02:00
var current_tilt : float = head . rotation . x
2021-09-11 15:52:09 +02:00
current_tilt -= deg2rad ( mouse_motion . relative . y * adjusted_mouse_sensitivity / view_zoom )
2021-07-04 00:42:42 +02:00
head . rotation . x = clamp ( current_tilt , deg2rad ( - 90 ) , deg2rad ( 90 ) )
2021-05-19 00:56:18 +02:00
func _input ( event ) - > void :
2021-06-03 17:44:25 +02:00
if not input_active :
return
2021-05-19 00:56:18 +02:00
2021-09-11 15:52:09 +02:00
assert ( is_network_authority ( ) == true , " input_active is true, even though the node is not network_authority " )
2021-09-11 14:35:07 +02:00
2021-05-24 21:57:19 +02:00
if Input . is_action_just_pressed ( " view_zoom " ) :
2021-07-16 02:52:18 +02:00
# tween.remove_all()
# tween.interpolate_property(self, "view_zoom", view_zoom, 4.0, 0.5, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
# tween.start()
2021-07-26 20:51:54 +02:00
view_zoom_direction = true
view_zoom_target = 4.0
2021-05-24 21:57:19 +02:00
if Input . is_action_just_released ( " view_zoom " ) :
2021-07-16 02:52:18 +02:00
# tween.remove_all()
# tween.interpolate_property(self, "view_zoom", view_zoom, 1.0, 0.25, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
# tween.start()
2021-07-26 20:51:54 +02:00
view_zoom_direction = false
view_zoom_target = 1.0
2021-07-16 02:52:18 +02:00
2021-07-12 22:40:23 +02:00
aim ( event )
2021-07-26 20:51:54 +02:00
2021-06-18 01:43:10 +02:00
if Input . is_action_just_pressed ( " trigger_primary " ) :
2021-08-25 12:03:35 +02:00
weapon . trigger ( 0 , true )
2021-06-18 01:43:10 +02:00
elif Input . is_action_just_released ( " trigger_primary " ) :
2021-08-25 12:03:35 +02:00
weapon . trigger ( 0 , false )
2021-06-18 01:43:10 +02:00
if Input . is_action_just_pressed ( " trigger_secondary " ) :
2021-08-25 12:03:35 +02:00
weapon . trigger ( 1 , true )
2021-06-18 01:43:10 +02:00
elif Input . is_action_just_released ( " trigger_secondary " ) :
2021-08-25 12:03:35 +02:00
weapon . trigger ( 1 , false )
2021-07-26 20:51:54 +02:00
func _process ( delta ) :
2021-09-11 14:35:07 +02:00
$ Jetpack / GPUParticles3D . emitting = jetpack_active
if not input_active :
return
2021-09-11 15:52:09 +02:00
assert ( is_network_authority ( ) == true , " input_active is true, even though the node is not network_authority " )
2021-09-11 14:35:07 +02:00
2021-07-26 20:51:54 +02:00
if view_zoom_direction and view_zoom < view_zoom_target :
view_zoom = min ( view_zoom_target , view_zoom + delta * 4 )
elif not view_zoom_direction and view_zoom > view_zoom_target :
view_zoom = max ( view_zoom_target , view_zoom - delta * 4 )
2021-09-07 23:23:48 +02:00
2021-07-26 20:51:54 +02:00
2021-08-23 01:57:47 +02:00
func damage ( hp : int ) :
2021-09-04 22:37:13 +02:00
var target = main . player_list . players [ self . get_network_authority ( ) ]
2021-08-25 12:03:35 +02:00
target . health -= hp
2021-09-11 14:35:07 +02:00
# if target.health <= 0: # int(name) is the player instance node name signifying owner's PID
# die()
2021-08-29 20:32:46 +02:00
2021-08-29 22:47:40 +02:00
func die ( killer_pid : int ) :
2021-09-08 23:25:52 +02:00
var gibs = gibs_vfx . instantiate ( )
get_tree ( ) . root . add_child ( gibs )
gibs . global_transform = self . global_transform #
#if get_tree().get_rpc_sender_id() != get_network_authority():
2021-08-29 20:32:46 +02:00
# print ("Death requested by a non-master. Ignoring")
# return
2021-09-04 22:37:13 +02:00
main . rpc ( & ' destroy_player ' , self . get_network_authority ( ) )
2021-09-08 23:25:52 +02:00
2021-08-29 22:47:40 +02:00
2021-09-04 22:37:13 +02:00
main . chat . rpc ( & ' chat_notification ' , " Player [/i][b][color= " + main . player_list . players [ self . get_network_authority ( ) ] . color . to_html ( ) + " ] " + main . player_list . players [ self . get_network_authority ( ) ] . name + " [/color][/b][i] was killed by " + main . player_list . players [ killer_pid ] . name )
2021-08-29 20:32:46 +02:00
#queue_free()
2021-08-29 22:47:40 +02:00
func update_color ( pid ) - > void : #change player's wolrdmodel color
2021-08-29 21:41:20 +02:00
## @onready var player_material =
## var material = player_material
2021-09-04 22:37:13 +02:00
if pid != self . get_network_authority ( ) :
2021-08-29 22:47:40 +02:00
print ( " Requesting color change for a different PID " )
return
2021-08-29 21:41:20 +02:00
var player_material = mesh . mesh . surface_get_material ( 0 ) . duplicate ( )
2021-09-04 22:37:13 +02:00
player_material . albedo_color = main . player_list . get ( self . get_network_authority ( ) ) . color
print ( " Updating color of player pid " , self . get_network_authority ( ) , " to " , player_material . albedo_color )
2021-08-29 21:41:20 +02:00
mesh . mesh . surface_set_material ( 0 , player_material )
2021-07-26 20:51:54 +02:00
2021-05-19 00:56:18 +02:00
func _physics_process ( delta ) :
2021-07-01 13:53:05 +02:00
# rpc_unreliable(&'set_global_transform', global_transform)
# head.rpc_unreliable(&'set_rotation', head.get_rotation())
2021-07-12 22:40:23 +02:00
#rpc(&'set_global_transform', global_transform)
#head.rpc(&'set_rotation', head.get_rotation())
2021-09-08 21:36:43 +02:00
if not is_network_authority ( ) :
move_and_slide ( )
return
2021-05-19 01:59:58 +02:00
direction = Vector3 . ZERO
2021-05-19 00:56:18 +02:00
2021-09-07 23:23:48 +02:00
if is_on_floor ( ) and ground_check . is_colliding ( ) and not jetpack_active :
2021-05-19 01:59:58 +02:00
snap = - get_floor_normal ( )
medium = " ground "
gravity_vec = Vector3 . ZERO
2021-05-19 00:56:18 +02:00
else :
2021-05-19 01:59:58 +02:00
snap = Vector3 . DOWN
medium = " air "
2021-05-19 00:56:18 +02:00
gravity_vec += Vector3 . DOWN * gravity * delta
2021-06-06 01:58:04 +02:00
if input_active :
if Input . is_action_just_pressed ( " move_jump " ) and is_on_floor ( ) :
snap = Vector3 . ZERO
gravity_vec = Vector3 . UP * jump
if Input . is_action_pressed ( " move_forward " ) :
direction -= transform . basis . z
if Input . is_action_pressed ( " move_backward " ) :
direction += transform . basis . z
if Input . is_action_pressed ( " move_left " ) :
direction -= transform . basis . x
if Input . is_action_pressed ( " move_right " ) :
direction += transform . basis . x
2021-09-07 23:23:48 +02:00
2021-09-08 23:54:04 +02:00
jetpack_was_active = jetpack_active
if jetpack_was_active :
jetpack_active = Input . is_action_pressed ( " move_special " ) if jetpack_fuel > 0 else false
else :
jetpack_active = Input . is_action_just_pressed ( " move_special " ) if jetpack_fuel > jetpack_min else false
2021-09-07 23:23:48 +02:00
if jetpack_active :
gravity_vec [ 1 ] += jetpack_thrust * delta
jetpack_fuel -= delta
elif jetpack_fuel < jetpack_tank :
jetpack_fuel = min ( jetpack_tank , jetpack_fuel + jetpack_recharge * delta )
2021-05-19 01:59:58 +02:00
2021-09-11 15:49:59 +02:00
#print("Jetpack fuel: ", jetpack_fuel, " active: ", jetpack_active, " delta: ", delta, " gravity vec: ", gravity_vec)
2021-09-07 23:23:48 +02:00
2021-05-19 01:59:58 +02:00
if direction . length ( ) > 0 : # normalized() will return a null
direction = direction . normalized ( )
2021-05-19 00:56:18 +02:00
2021-05-19 01:59:58 +02:00
speed = speed_type [ medium ]
accel = accel_type [ medium ]
2021-05-19 00:56:18 +02:00
2021-05-19 01:59:58 +02:00
velocity = velocity . lerp ( direction * speed , accel * delta )
2021-05-19 00:56:18 +02:00
2021-06-07 19:11:42 +02:00
linear_velocity = velocity + gravity_vec
#slide = move_and_slide_with_snap(movement, snap, Vector3.UP)
2021-07-01 13:53:05 +02:00
# rpc_unreliable(&'set_linear_velocity', linear_velocity)
# rpc_unreliable(&"move_and_slide")
2021-07-04 21:50:13 +02:00
# rpc(&'set_linear_velocity', linear_velocity)
2021-07-12 22:40:23 +02:00
# rpc(&'move_and_slide')
move_and_slide ( )
2021-05-19 00:56:18 +02:00
2021-05-22 18:08:26 +02:00
if not is_on_floor ( ) and not ground_check . is_colliding ( ) : # while in mid-air collisions affect momentum
2021-06-07 19:11:42 +02:00
velocity . x = linear_velocity . x
velocity . z = linear_velocity . z
gravity_vec . y = linear_velocity . y
2021-07-12 22:40:23 +02:00
# update puppets
2021-09-04 22:37:13 +02:00
# if get_tree().multiplayer.get_network_unique_id() == 1:
2021-08-23 01:57:47 +02:00
# rpc(&'update_movement', global_transform, head.get_rotation())
# else:
# rpc_id(1, &'update_movement', global_transform, head.get_rotation())
#
2021-09-08 21:36:43 +02:00
rpc ( & ' update_movement ' , global_transform , head . get_rotation ( ) , linear_velocity , jetpack_active )
2021-07-12 22:40:23 +02:00
2021-05-25 01:14:37 +02:00
# (stair) climbing
2021-09-04 22:37:13 +02:00
# ↓ disabled - Tween is undergoing redesign in Godot 4
# if get_slide_count() > 1 and climb_check.is_colliding() and false:
# #print("climb started at climb state: ", climb_state)
# var test_y = climb_height * (1 - climb_state)
# #print("test_y: ", test_y)
# var climb_test_start = global_transform.translated(Vector3(0, test_y, 0))
# var climb_test_step = Vector3(0,0,-0.1).rotated(Vector3.UP, rotation.y)
# if not test_move(climb_test_start, climb_test_step): # no collision
# var step = climb_check.get_collision_point().y
# var start = global_transform.origin.y
## print("step: ", step, " start: ", start)
# climb_state = clamp((step - start) / climb_height, 0, 1)
# global_transform.origin.y += climb_height * climb_state
# #print("climb state to start: ", climb_state)
## print("Climb height: ", step - start, " Climb state: ", climb_state)
# climb_tween.remove_all()
# climb_tween.interpolate_property(self, "climb_state", climb_state, 0.0, climb_time, Tween.TRANS_CUBIC, Tween.EASE_IN)
# climb_tween.start()