forked from unfa/liblast
306 lines
10 KiB
GDScript
306 lines
10 KiB
GDScript
extends CharacterBody3D
|
|
|
|
@export var mouse_sensitivity := 0.15
|
|
|
|
@onready var main = get_tree().root.get_node("Main")
|
|
@onready var hud = main.get_node("HUD")
|
|
@onready var crosshair = hud.get_node("Crosshair")
|
|
@onready var vignette = hud.get_node("Vignette")
|
|
|
|
@onready var head = $Head
|
|
@onready var camera = $Head/Camera
|
|
@onready var tween = $Head/Camera/Tween
|
|
|
|
@onready var ground_check = $GroundCheck
|
|
@onready var climb_tween = $ClimbTween # undergoing redesign in Godot 4
|
|
@onready var climb_check = $ClimbCheck
|
|
@onready var body = $Body
|
|
@onready var mesh = $Mesh
|
|
|
|
@onready var weapon = $Head/Camera/Hand/Weapon
|
|
|
|
var gibs_vfx = preload("res://Assets/Effects/Gibs.tscn")
|
|
|
|
# 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
|
|
@onready var ground_check_y = ground_check.position.y
|
|
|
|
var input_active = false
|
|
|
|
var base_fov = 90
|
|
var view_zoom_target := 1.0
|
|
var view_zoom_direction = true
|
|
var view_zoom := view_zoom_target :
|
|
set(zoom):
|
|
view_zoom = zoom
|
|
camera.fov = base_fov / zoom
|
|
crosshair.modulate.a = clamp(1 - (zoom - 1), 0, 1)
|
|
vignette.modulate.a = (zoom - 1) / 3
|
|
|
|
# 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
|
|
|
|
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 := {
|
|
"ground": 10,
|
|
"air": 10,
|
|
"water": 5
|
|
}
|
|
var gravity := 28
|
|
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
|
|
var jetpack_min = 1/4
|
|
var jetpack_was_active = false
|
|
|
|
var velocity := Vector3.ZERO
|
|
var gravity_vec := Vector3.ZERO
|
|
|
|
@rpc(nosync,unreliable) func update_movement(player_transform, head_rotation, lin_velocity, jetpack):
|
|
global_transform = player_transform
|
|
head.set_rotation(head_rotation)
|
|
jetpack_active = jetpack
|
|
linear_velocity = lin_velocity
|
|
|
|
func _ready() -> void:
|
|
#Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
|
view_zoom_target = 1.0
|
|
|
|
# generate_info()
|
|
|
|
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)
|
|
|
|
# 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)
|
|
|
|
if is_network_authority(): # prevent puppets from attempting to steer the authority - this just causes RPC errors
|
|
input_active = true
|
|
else:
|
|
input_active = false
|
|
|
|
func aim(event) -> void:
|
|
var mouse_motion = event as InputEventMouseMotion
|
|
|
|
if mouse_motion:
|
|
rotation.y -= deg2rad(mouse_motion.relative.x * mouse_sensitivity / view_zoom)
|
|
|
|
var current_tilt: float = head.rotation.x
|
|
current_tilt -= deg2rad(mouse_motion.relative.y * mouse_sensitivity / view_zoom)
|
|
head.rotation.x = clamp(current_tilt, deg2rad(-90), deg2rad(90))
|
|
|
|
func _input(event) -> void:
|
|
if not input_active:
|
|
return
|
|
|
|
#assert(is_network_authority() == true, "input_active is true, even though the node is not network_authority")
|
|
|
|
if Input.is_action_just_pressed("view_zoom"):
|
|
# tween.remove_all()
|
|
# tween.interpolate_property(self, "view_zoom", view_zoom, 4.0, 0.5, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
|
|
# tween.start()
|
|
view_zoom_direction = true
|
|
view_zoom_target = 4.0
|
|
|
|
if Input.is_action_just_released("view_zoom"):
|
|
# tween.remove_all()
|
|
# tween.interpolate_property(self, "view_zoom", view_zoom, 1.0, 0.25, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
|
|
# tween.start()
|
|
view_zoom_direction = false
|
|
view_zoom_target = 1.0
|
|
|
|
aim(event)
|
|
|
|
if Input.is_action_just_pressed("trigger_primary"):
|
|
weapon.trigger(0, true)
|
|
elif Input.is_action_just_released("trigger_primary"):
|
|
weapon.trigger(0, false)
|
|
if Input.is_action_just_pressed("trigger_secondary"):
|
|
weapon.trigger(1, true)
|
|
elif Input.is_action_just_released("trigger_secondary"):
|
|
weapon.trigger(1, false)
|
|
|
|
|
|
func _process(delta):
|
|
$Jetpack/GPUParticles3D.emitting = jetpack_active
|
|
|
|
if not input_active:
|
|
return
|
|
|
|
#assert(is_network_authority() == true, "input_active is true, even though the node is not network_authority")
|
|
|
|
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)
|
|
|
|
|
|
func damage(hp: int):
|
|
var target = main.player_list.players[self.get_network_authority()]
|
|
target.health -= hp
|
|
# if target.health <= 0: # int(name) is the player instance node name signifying owner's PID
|
|
# die()
|
|
|
|
func die(killer_pid: int):
|
|
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():
|
|
# print ("Death requested by a non-master. Ignoring")
|
|
# return
|
|
main.rpc(&'destroy_player', self.get_network_authority())
|
|
|
|
|
|
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 )
|
|
#queue_free()
|
|
|
|
func update_color(pid) -> void: #change player's wolrdmodel color
|
|
## @onready var player_material =
|
|
## var material = player_material
|
|
if pid != self.get_network_authority():
|
|
print("Requesting color change for a different PID")
|
|
return
|
|
|
|
var player_material = mesh.mesh.surface_get_material(0).duplicate()
|
|
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 )
|
|
mesh.mesh.surface_set_material(0, player_material)
|
|
|
|
func _physics_process(delta):
|
|
# rpc_unreliable(&'set_global_transform', global_transform)
|
|
# head.rpc_unreliable(&'set_rotation', head.get_rotation())
|
|
#rpc(&'set_global_transform', global_transform)
|
|
#head.rpc(&'set_rotation', head.get_rotation())
|
|
|
|
if not is_network_authority():
|
|
move_and_slide()
|
|
return
|
|
|
|
direction = Vector3.ZERO
|
|
|
|
if is_on_floor() and ground_check.is_colliding() and not jetpack_active:
|
|
snap = -get_floor_normal()
|
|
medium = "ground"
|
|
gravity_vec = Vector3.ZERO
|
|
else:
|
|
snap = Vector3.DOWN
|
|
medium = "air"
|
|
gravity_vec += Vector3.DOWN * gravity * delta
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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)
|
|
|
|
print("Jetpack fuel: ", jetpack_fuel, " active: ", jetpack_active, " delta: ", delta, " gravity vec: ", gravity_vec)
|
|
|
|
if direction.length() > 0: # normalized() will return a null
|
|
direction = direction.normalized()
|
|
|
|
speed = speed_type[medium]
|
|
accel = accel_type[medium]
|
|
|
|
velocity = velocity.lerp(direction * speed, accel * delta)
|
|
|
|
linear_velocity = velocity + gravity_vec
|
|
#slide = move_and_slide_with_snap(movement, snap, Vector3.UP)
|
|
# rpc_unreliable(&'set_linear_velocity', linear_velocity)
|
|
# rpc_unreliable(&"move_and_slide")
|
|
# rpc(&'set_linear_velocity', linear_velocity)
|
|
# rpc(&'move_and_slide')
|
|
move_and_slide()
|
|
|
|
if not is_on_floor() and not ground_check.is_colliding(): # while in mid-air collisions affect momentum
|
|
velocity.x = linear_velocity.x
|
|
velocity.z = linear_velocity.z
|
|
gravity_vec.y = linear_velocity.y
|
|
|
|
# update puppets
|
|
# if get_tree().multiplayer.get_network_unique_id() == 1:
|
|
# rpc(&'update_movement', global_transform, head.get_rotation())
|
|
# else:
|
|
# rpc_id(1, &'update_movement', global_transform, head.get_rotation())
|
|
#
|
|
rpc(&'update_movement', global_transform, head.get_rotation(), linear_velocity, jetpack_active)
|
|
|
|
# (stair) climbing
|
|
# ↓ 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()
|