noticed bugs: killing an enemy as you die crashes the game, ear wind needs to be inaudible when standing still, recoil camera still sucks
362 lines
12 KiB
GDScript
362 lines
12 KiB
GDScript
extends CharacterBody3D
|
|
|
|
const WALK_TRANSITION_SPEED = 10
|
|
const MAX_AIR_DASH = 1
|
|
const FLASHLIGHT_BRIGHTNESS = 10
|
|
const KICK_AMOUNT = 10
|
|
|
|
var speed
|
|
var double_jump = true
|
|
var air_dash = MAX_AIR_DASH
|
|
var gravity = 9.8
|
|
var is_climbing = false
|
|
var ladder_center
|
|
var default_gravity = gravity
|
|
var moving_fast = false
|
|
var moving_fast_top_speed = 0.0
|
|
var mouse_input : Vector2
|
|
|
|
var rng = RandomNumberGenerator.new()
|
|
|
|
@export_group("Game Settings")
|
|
@export var AUDIO = true
|
|
@export var dead_player : Resource
|
|
@export_group("Player Movement")
|
|
@export var WALK_SPEED = 12.0
|
|
@export var SPRINT_SPEED = 15.0
|
|
@export var DASH_SPEED = 40
|
|
@export var DASH_STAM_REQ = 10
|
|
@export var MAX_STAMINA = 1800
|
|
@export var JUMP_VELOCITY = 6
|
|
@export var SENSITIVITY = .01
|
|
@export var sensitivity_shift = true
|
|
var start_sensitivity
|
|
@export_subgroup("Head Bob & Gun Sway")
|
|
@export var BOB_FREQ = 2.0
|
|
@export var BOB_AMP = 0.08
|
|
@export var t_bob = 1.0
|
|
@export var weapon_holder : Node3D
|
|
@export var weapon_sway_amount : float = .07
|
|
@export var weapon_rotation_amount : float = .07
|
|
@export_subgroup("FOV")
|
|
@export var BASE_FOV : float = 80
|
|
@export var FOV_CHANGE = 1.5
|
|
|
|
#@export_group("Gun") DELETE IF DOESNT CAUSE ISSUES
|
|
#@export
|
|
|
|
var gun : Node
|
|
|
|
@onready var gun_ray = $Head/Recoil/Camera3D/GunRay
|
|
@onready var level_control = get_tree().current_scene
|
|
@onready var interact_ray = $Head/Recoil/Camera3D/InteractRay
|
|
@onready var bullet_ray = $Head/Recoil/Camera3D/BulletRay
|
|
var instance_bullet
|
|
var instance_casing
|
|
var instance_mag
|
|
var reloading = false
|
|
var ammo
|
|
var ammo_reserve
|
|
var bullet_damage
|
|
var def_weapon_holder_pos : Vector3
|
|
var weapon_holder_start_rot
|
|
var weapon_holder_start_pos
|
|
var gun_folded = false
|
|
var recoiling_fade = 0
|
|
var bullet_destination
|
|
var gun_fire_pitch_starting
|
|
var current_weapon_index
|
|
var recoiling = false
|
|
var dead = false
|
|
|
|
# Slow Down Variables
|
|
const SLOWSPEED = .2
|
|
const STAMINA_DRAIN = 100
|
|
var remaining_stamina = MAX_STAMINA
|
|
# Pickups
|
|
var picked_up = false
|
|
var picked_up_text
|
|
var pickup_announce = load("res://assets/pickup_announce.tscn")
|
|
var dead_announce = load("res://assets/dead_announce.tscn")
|
|
var pickupmsg
|
|
|
|
@onready var crosshair = $Head/Recoil/Camera3D/Crosshair
|
|
@onready var head = $Head
|
|
@onready var camera = $Head/Recoil/Camera3D
|
|
@onready var world_environment = $"../WorldEnvironment"
|
|
@onready var pickup_sound = $Audio/PickupSound
|
|
@onready var ear_wind = $Audio/EarWind
|
|
@onready var land_sound: AudioStreamPlayer = $Audio/LandSound
|
|
@onready var hurt_audio = $Audio/Hurt
|
|
@onready var health_indicator = $HealthIndicator
|
|
@onready var ammo_counter = $Head/Recoil/Camera3D/AmmoCounter
|
|
@onready var stamina_counter = $Head/Recoil/Camera3D/StaminaCounter
|
|
@onready var recoil: Node3D = $Head/Recoil
|
|
@onready var weapon_spawner = $Head/Recoil/Camera3D/WeaponHolder/WeaponSpawner
|
|
@onready var pick_up_detection = $pick_up_detection
|
|
@onready var item_holder: Node3D = $Head/ItemHolder
|
|
@onready var flashlight: SpotLight3D = $Head/Recoil/Camera3D/WeaponHolder/Flashlight
|
|
@onready var flashlight_audio: AudioStreamPlayer3D = $Head/Recoil/Camera3D/WeaponHolder/FlashlightButton
|
|
@onready var kick_audio: AudioStreamPlayer3D = $Head/Recoil/Camera3D/Audio/Kick
|
|
@onready var weapon_pickup_audio: AudioStreamPlayer = $Audio/WeaponPickup
|
|
|
|
|
|
func _ready():
|
|
|
|
weapon_holder_start_rot = weapon_holder.rotation
|
|
weapon_holder_start_pos = weapon_holder.position
|
|
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
|
start_sensitivity = SENSITIVITY
|
|
|
|
var viewportWidth = get_viewport().size.x
|
|
var viewportHeight = get_viewport().size.y
|
|
health_indicator.size = Vector2(viewportWidth,viewportHeight)
|
|
health_indicator.color = Color(0.471, 0, 0, 0)
|
|
|
|
#turn off audio if unchecked in player
|
|
if AUDIO == false:
|
|
AudioServer.set_bus_volume_db(0,-80)
|
|
|
|
func _input(event) -> void:
|
|
if event is InputEventMouseMotion:
|
|
self.rotate_y(-event.relative.x * SENSITIVITY)
|
|
head.rotate_x(-event.relative.y * SENSITIVITY)
|
|
head.rotation.x = clamp(head.rotation.x, deg_to_rad(-90), deg_to_rad(85))
|
|
mouse_input = event.relative
|
|
|
|
func _physics_process(delta):
|
|
|
|
if !dead:
|
|
|
|
# Add the gravity.
|
|
if is_on_floor():
|
|
double_jump = true
|
|
air_dash = MAX_AIR_DASH
|
|
else:
|
|
velocity.y -= gravity * delta
|
|
if abs(velocity.y) >= .1:
|
|
moving_fast = true
|
|
|
|
# Handle jump.
|
|
if Input.is_action_just_pressed("jump") and is_on_floor() and !is_climbing:
|
|
velocity.y += JUMP_VELOCITY
|
|
elif Input.is_action_just_pressed("jump") and double_jump == true and !is_climbing:
|
|
velocity.y += JUMP_VELOCITY
|
|
double_jump = false
|
|
|
|
speed = WALK_SPEED #the fuck is this line doing
|
|
|
|
# Get the input direction and handle the movement/deceleration.
|
|
var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
|
var direction = (self.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
|
|
# Handle Sprint
|
|
if Input.is_action_just_pressed("sprint") and !is_on_floor():
|
|
if air_dash > 0:
|
|
velocity.x += direction.x * DASH_SPEED
|
|
velocity.z += direction.z * DASH_SPEED
|
|
air_dash -= 1
|
|
print("AIR DASH " +str(air_dash))
|
|
|
|
if is_on_floor() and !is_climbing:
|
|
if direction:
|
|
velocity.x = lerp(velocity.x, direction.x * speed, delta * WALK_TRANSITION_SPEED)
|
|
velocity.z = lerp(velocity.z, direction.z * speed, delta * WALK_TRANSITION_SPEED)
|
|
else:
|
|
velocity.x = lerp(velocity.x, direction.x * speed, delta * 6.5) + (direction.x * DASH_SPEED)
|
|
velocity.z = lerp(velocity.z, direction.z * speed, delta * 6.5) + (direction.z * DASH_SPEED)
|
|
|
|
elif is_climbing:
|
|
gravity = 0.0
|
|
if direction:
|
|
velocity.y = -direction.z * speed * .75
|
|
velocity.x = direction.x * speed * .3
|
|
else:
|
|
velocity.y = lerp(velocity.y, -direction.z * speed, delta * 6.5)
|
|
velocity.x = lerp(velocity.x, direction.x * speed, delta * 6.5)
|
|
else:
|
|
velocity.x = lerp(velocity.x, direction.x * speed, delta * 6.5)
|
|
velocity.z = lerp(velocity.z, direction.z * speed, delta * 6.5)
|
|
|
|
# Head bob
|
|
t_bob += delta * velocity.length() * float(is_on_floor())
|
|
camera.transform.origin = _headbob(t_bob)
|
|
|
|
# FOV
|
|
var velocity_clamped = clamp(velocity.length(), 0.5, SPRINT_SPEED * 2)
|
|
var target_fov = BASE_FOV + FOV_CHANGE * velocity_clamped
|
|
camera.fov = lerp(camera.fov, target_fov, delta * 8)
|
|
|
|
# Health Indicator
|
|
var health_opacity = 1.5 - level_control.health / level_control.start_health
|
|
if level_control.health < (level_control.start_health/2):
|
|
health_indicator.color = lerp(Color(0.471, 0, 0, 0), Color(0.471, 0, 0, .25),health_opacity)
|
|
|
|
# Moving Fast Sound
|
|
#initiate fast movement -- may be done with this block
|
|
#change sounds with speed
|
|
if moving_fast:
|
|
var wind_volume = clamp( velocity.length() - 20 ,-20,10)
|
|
ear_wind.volume_db = wind_volume
|
|
#reset at apex
|
|
|
|
#cache fastest speed
|
|
if abs(velocity.y) > moving_fast_top_speed:
|
|
moving_fast_top_speed = abs(velocity.y)
|
|
print("TOP SPEED = " + str(moving_fast_top_speed))
|
|
#Land Sound
|
|
if velocity.y < .1 and self.is_on_floor() and moving_fast == true:
|
|
print("LAND SOUND")
|
|
var land_volume = clamp( moving_fast_top_speed - 20 ,-10,0)
|
|
land_sound.volume_db = land_volume
|
|
land_sound.play()
|
|
moving_fast_top_speed = 0.0
|
|
moving_fast = false
|
|
|
|
# Game Speed
|
|
if Input.is_action_pressed("slow_down") and remaining_stamina >0:
|
|
Engine.time_scale = lerp(0, 1, SLOWSPEED)
|
|
gun.random_spread_amt = 0
|
|
AudioServer.set_bus_effect_enabled(0,0,true)
|
|
camera.fov = lerp(camera.fov, camera.fov * gun.fov_zoom_amt, delta * 100)
|
|
if sensitivity_shift == true:
|
|
SENSITIVITY = lerp(SENSITIVITY, SENSITIVITY * .998, delta * 100)
|
|
if remaining_stamina >0:
|
|
remaining_stamina -= 1000 * delta
|
|
else:
|
|
Engine.time_scale = 1
|
|
gun.random_spread_amt = gun.random_spread_start
|
|
AudioServer.set_bus_effect_enabled(0,0,false)
|
|
if sensitivity_shift == true:
|
|
camera.fov = lerp(camera.fov, BASE_FOV, delta * .5)
|
|
SENSITIVITY = start_sensitivity
|
|
if remaining_stamina < MAX_STAMINA:
|
|
remaining_stamina += STAMINA_DRAIN * delta
|
|
elif remaining_stamina > MAX_STAMINA * 1.01:
|
|
remaining_stamina -= (STAMINA_DRAIN)/2 * delta
|
|
|
|
# Reloading
|
|
if Input.is_action_just_pressed("reload"):
|
|
gun.reload(delta)
|
|
|
|
if Input.is_action_pressed("inspect") and !gun.anim_player.is_playing():
|
|
gun.anim_player.play("inspect")
|
|
|
|
if Input.is_action_just_pressed("flashlight"):
|
|
flashlight_audio.play()
|
|
if flashlight.light_energy == 0:
|
|
while flashlight.light_energy != FLASHLIGHT_BRIGHTNESS:
|
|
flashlight.light_energy = FLASHLIGHT_BRIGHTNESS
|
|
elif flashlight.light_energy > 0:
|
|
flashlight.light_energy = 0
|
|
|
|
|
|
# Shooting & fire modes
|
|
if Input.is_action_pressed("shoot"):
|
|
gun.shoot(delta)
|
|
|
|
if Input.is_action_just_released("shoot"):
|
|
gun.cycle_count = gun.cycle_count_start
|
|
|
|
# Gun folding out of the way
|
|
if gun_ray.is_colliding():
|
|
weapon_holder.rotation = lerp(weapon_holder.rotation, Vector3(2, -1, -1), delta * 7)
|
|
weapon_holder.position = lerp(weapon_holder.position, Vector3(-.02,-.1,.06),(delta * 7))
|
|
gun_folded = true
|
|
elif !gun_ray.is_colliding():
|
|
weapon_holder.rotation = lerp(weapon_holder.rotation, weapon_holder_start_rot,delta*7)
|
|
weapon_holder.position = lerp(weapon_holder.position, weapon_holder_start_pos,delta*7)
|
|
gun_folded = false
|
|
|
|
#Weapon Swap Up
|
|
if Input.is_action_just_pressed("scroll_up") and !gun.anim_player.is_playing():
|
|
if level_control.held_guns.size() > 1:
|
|
gun.anim_player.play("swap_out")
|
|
level_control.gun_spawn(level_control.current_gun_index + 1)
|
|
#Weapon Swap Down
|
|
if Input.is_action_just_pressed("scroll_down") and !gun.anim_player.is_playing():
|
|
if level_control.held_guns.size() > 1:
|
|
gun.anim_player.play("swap_out")
|
|
level_control.gun_spawn(level_control.current_gun_index - 1)
|
|
|
|
|
|
#interact button
|
|
if Input.is_action_just_pressed("interact"):
|
|
if interact_ray.is_colliding():
|
|
if interact_ray.get_collider().is_in_group("interact"):
|
|
var body = interact_ray.get_collider()
|
|
body.get_parent().interact()
|
|
|
|
|
|
#kick
|
|
if Input.is_action_just_pressed("kick"):
|
|
if interact_ray.is_colliding():
|
|
if interact_ray.get_collider().is_in_group("scene_rigidbody"):
|
|
kick_audio.play()
|
|
interact_ray.get_collider().linear_velocity += transform.basis * Vector3(0,0,-KICK_AMOUNT)
|
|
|
|
#quit game and eventually go to menu
|
|
if Input.is_action_just_pressed("escape"):
|
|
get_tree().quit()
|
|
|
|
if level_control.health <= 0:
|
|
level_control.die()
|
|
|
|
move_and_slide()
|
|
weapon_tilt(input_dir.x, delta)
|
|
weapon_sway(delta)
|
|
weapon_bob(velocity.length(), delta)
|
|
|
|
func _headbob(time) -> Vector3:
|
|
var pos = Vector3.ZERO
|
|
pos.y = sin(time * BOB_FREQ) * BOB_AMP
|
|
pos.x = cos(time * BOB_FREQ / 2) * BOB_AMP
|
|
return pos
|
|
|
|
|
|
func _on_pick_up_detection_body_entered(body):
|
|
|
|
if body.is_in_group("pickup"):
|
|
if body.pickupable:
|
|
body.picked_up()
|
|
if body.is_in_group("weapon_pickup"):
|
|
weapon_pickup_audio.play()
|
|
|
|
|
|
func ladder_collide(is_climbing):
|
|
|
|
if is_climbing == true:
|
|
gravity = 0.0
|
|
else:
|
|
gravity = default_gravity
|
|
|
|
func _on_pick_up_magnet_body_entered(body):
|
|
if body.is_in_group("pickup") and body.is_in_group("magnet"):
|
|
body.player_follow = self
|
|
body.collision_shape.disabled = true
|
|
|
|
func weapon_tilt(input_x, delta):
|
|
if weapon_holder:
|
|
weapon_holder.rotation.z = lerp(weapon_holder.rotation.z, -input_x * weapon_rotation_amount * 10, 4 * delta)
|
|
if camera:
|
|
camera.rotation.z = lerp(camera.rotation.z, -input_x * .075, 5 * delta)
|
|
|
|
func weapon_sway(delta):
|
|
mouse_input = lerp(mouse_input, Vector2.ZERO, 10 * delta)
|
|
weapon_holder.rotation.x = lerp(weapon_holder.rotation.x, mouse_input.y * weapon_sway_amount, 10 * delta)
|
|
weapon_holder.rotation.y = lerp(weapon_holder.rotation.y, mouse_input.x * weapon_sway_amount, 10 * delta)
|
|
|
|
func weapon_bob(vel : float, delta):
|
|
if weapon_holder:
|
|
if vel > 2 and is_on_floor():
|
|
var bob_amount : float = 0.05
|
|
var bob_freq : float = 0.01
|
|
weapon_holder.position.y = lerp(weapon_holder.position.y, def_weapon_holder_pos.y + sin(Time.get_ticks_msec() * bob_freq) * bob_amount, 10 * delta)
|
|
weapon_holder.position.x = lerp(weapon_holder.position.x, def_weapon_holder_pos.x + sin(Time.get_ticks_msec() * bob_freq) * bob_amount, 10 * delta)
|
|
else:
|
|
weapon_holder.position.y = lerp(weapon_holder.position.y, def_weapon_holder_pos.y, .1 * delta)
|
|
weapon_holder.position.x = lerp(weapon_holder.position.x, def_weapon_holder_pos.x, .1 * delta)
|
|
|
|
func weapon_recoil():
|
|
pass
|