extends CharacterBody3D const WALK_TRANSITION_SPEED = 8 const MAX_AIR_DASH = 1 const FLASHLIGHT_BRIGHTNESS = 30 const KICK_AMOUNT = 10 const LAND_CAMERA_TILT : Vector3 = Vector3(-1,0,0) 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)) #walking 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) #ladder movement 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) #movement in air else: velocity.x = lerp(velocity.x, direction.x * speed, delta * 3) velocity.z = lerp(velocity.z, direction.z * speed, delta * 3) # 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