extends CharacterBody3D class_name PlayerCharacter var aceleration: float = 4.32 #Current aceleration var maxSpeed: float = 6.2 #Maximum Speed var sprintSpeed: float = 4.34 #Additional Speed gained while Sprinting var slowdownSpeedLimit: float = 0.8 #How fast the player can go when slowed var gear: String = "neutral" #Weather the player is going forward, backward or standing still var isMoving: bool = false var slowed: bool = false var momentum: float = 0 var moveDirection: Vector3 = Vector3(0,0,0) var lastMoveDirection: Vector3 = Vector3(0,0,0) var deceleration: float = 3.3 var turnSpeed: float = 0.669 #Speed at wich legs turn sideways var sprintStillTurnSpeed: float = 1.169 #Speed at wich the legs turns sideways when holding sprint and standing still var drivingTurnSpeed: float = 0.4569 #Speed at wich legs turn sideways while driving var driftingTurnSpeed: float = 1.5 #Speed increase of turn while drifting var facingDirection = Vector2(0,1) #Where the legs are facing var sprinting = false #While Player is sprinting var sprintEnergy: float = 100 #Energy used for Sprinting var sprintEnergyUse: float = 17.5 #How much % energy is used per 1 sec of sprint var sprintEnergyGain: float = 30 #How much % energy is gained per 1 sec of recovery var maxDriftAngle = 0.12 #Quaternion(0,0,0.06,0.998).normalized() #How much the playesr turns to the side while drifting (radians) var rightLeftLean: float = 0.0 #How much the player leans right or left from -1 to 1 with negative numbers being left and 0 being no lean var currentControlState: int = 0 enum controls {DEFAULT,STANDARD_MINIGAME} var health: float = 100.0 var invoulnerable: bool = false var alive: bool = true @onready var camera: Camera3D = $CameraPivot/Camera3D @onready var cameraPivot: Marker3D = $CameraPivot @onready var flashlight: SpotLight3D = $CameraPivot/Camera3D/flashlight #@onready var backlightR := $pivot/pivotRightLeg/pivotLeftLeg/body/BacklightR #@onready var backlightL := $pivot/pivotRightLeg/pivotLeftLeg/body/BacklightL @onready var pivot: = $pivot @onready var headPivot: = $pivot/HeadBinoculars/HeadPivot @onready var headBinoculars: = $pivot/HeadBinoculars @onready var legs := $pivot/BodyPivot/CaterpillarLegs @onready var body: = $pivot/BodyPivot/body @onready var hud = $/root/Main/Hud @onready var interactCross := $/root/Main/Hud/InteractCross @onready var sprintBar := $/root/Main/Hud/TextureProgressBar @onready var grabRaycast: = $CameraPivot/Camera3D/GrabDetector @onready var grabPivot: = $pivot/BodyPivot/body/GrabPivot @onready var grabBox: = $pivot/BodyPivot/body/GrabBox var grabbedObject: GrabableObject @onready var interactRaycast = $CameraPivot/Camera3D/InteractDetector @onready var VoiceChat = $VoiceChat @onready var bodyPivot: Node3D = $pivot/BodyPivot var mouseSensetivity := 0.1 #How much mouse movement affects ingame camera movement var spectatorScene: PackedScene = preload("res://actors/Player/Spectator.tscn") var spectatorParent: Node3D var mapLogic: MapLogic #Camera Shake Stuff var traumaReductionRate:float = 0.34 var trauma: float = 0 @export var maxX = 12 @export var maxY = 12 @export var maxZ = 7 @export var shakeIntensety : float = 7.0 var time: float = 0 @export var noise: Noise var noiseSpeed: float = 50 var initialRotation = rotation_degrees as Vector3 # Camera Shake Stuff end func _enter_tree() -> void: set_multiplayer_authority(name.to_int()) if is_multiplayer_authority(): $CameraPivot/Camera3D.make_current() $pivot/HeadBinoculars.hide() $/root/Main/Hud/TextureProgressBar.show() func _ready() -> void: Multiplayer.player_ready.emit(int(name)) Input.mouse_mode = Input.MOUSE_MODE_CAPTURED mapLogic = Multiplayer.currentMapLogic spectatorParent = get_node("/root/Main/Spectators") if mapLogic: mapLogic.onCollision.connect(onCollision) if is_multiplayer_authority(): position.y += 2 return func _process(delta: float) -> void: if not is_multiplayer_authority(): return if not alive: return if invoulnerable and trauma == 0.0: invoulnerable = false if Input.is_action_just_pressed("debug"): ##Debug die() match currentControlState: controls.DEFAULT: regularControlsIdle(delta) controls.STANDARD_MINIGAME: standardMinigameControlsIdle(delta) func _physics_process(delta: float) -> void: if not is_multiplayer_authority(): return if not alive: return match currentControlState: controls.DEFAULT: regularControlsPhysics(delta) controls.STANDARD_MINIGAME: endOfPhysicsCleanup(delta) func standardMinigameControlsIdle(_delta:float): if Input.is_action_just_pressed("moveDown") or Input.is_action_just_pressed("interact"): currentControlState = controls.DEFAULT func regularControlsIdle(_delta:float): #Interacting Logic var InteractCollider: InteractBox = interactRaycast.get_collider() if InteractCollider and Input.is_action_just_pressed("interact"): InteractCollider.playerRef = self InteractCollider.interact() if InteractCollider.type == "minigame": currentControlState = controls.STANDARD_MINIGAME momentum = 0 #Grabbing Logic var GrabCollider: GrabBox = grabRaycast.get_collider() var grabBoxCollider: Array[Area3D] = grabBox.get_overlapping_areas() if(grabBoxCollider and Input.is_action_just_pressed("interact") and !grabbedObject): if grabBoxCollider.has(GrabCollider): #If the player is looking at an object and it is in the grab box grabbedObject = GrabCollider.grab() else: #If the player is not looking at an object, grab the closet one in the grab box var closestObj: GrabBox var distanceToClosestObj: float = 100 for grabObj in grabBoxCollider: if (getDistance(self,grabObj) < distanceToClosestObj): closestObj = grabObj distanceToClosestObj = getDistance(self, grabObj) grabbedObject = closestObj.grab() if InteractCollider or grabBoxCollider: interactCross.show() else: interactCross.hide() if Input.is_action_just_pressed("flashlight"): flashlight.visible = !flashlight.visible #if gear == "backward": #backlightL.show() #backlightR.show() #else: #backlightR.hide() #backlightL.hide() if grabbedObject: grabbedObject.global_position = grabPivot.global_position# + grabbedObject.grabPositionPositionOffset grabbedObject.rotation = grabPivot.global_rotation + grabbedObject.grabPositionRotationOffset if grabbedObject.grabBox.heavy: slowed = true if Input.is_action_just_pressed("drop"): grabbedObject.release.rpc() grabbedObject = null slowed = false momentum = 0 if Input.is_action_just_pressed("throw"): grabbedObject.release.rpc() grabbedObject.throw.rpc_id(1,facingDirection.x,facingDirection.y,camera.rotation.x) grabbedObject = null slowed = false momentum = 0 func regularControlsPhysics(delta: float): isMoving = false if Input.is_action_pressed("Sprint"): sprinting = true else: sprinting = false if sprinting: sprintEnergy = clamp(sprintEnergy - sprintEnergyUse * delta, 0 , 100) else: sprintEnergy = clamp(sprintEnergy + sprintEnergyGain * delta, 0 , 100) if not is_on_floor(): velocity += get_gravity() moveDirection = Vector3(0,0,0) if Input.is_action_pressed("moveUp"): isMoving = true moveDirection += Vector3(facingDirection.x,0,facingDirection.y) if Input.is_action_pressed("moveRight"): isMoving = true moveDirection -= Vector3(facingDirection.x,0,facingDirection.y).rotated(up_direction,PI/2) if Input.is_action_pressed("moveLeft"): isMoving = true moveDirection += Vector3(facingDirection.x,0,facingDirection.y).rotated(up_direction,PI/2) if Input.is_action_pressed("moveDown"): isMoving = true moveDirection -= Vector3(facingDirection.x,0,facingDirection.y) if moveDirection != Vector3(0,0,0): lastMoveDirection = moveDirection endOfPhysicsCleanup(delta) #Momentum stuff if isMoving: momentum = clamp(momentum + aceleration * delta,0,maxSpeed) else: momentum = clamp(momentum - deceleration * delta,0,maxSpeed) if sprinting: velocity = clampVectorLength(moveDirection.normalized() * (momentum + sprintSpeed),0,maxSpeed+sprintSpeed) else: velocity = clampVectorLength(lastMoveDirection.normalized() * momentum,0,maxSpeed) bodyPivot.rotation.y = -atan2(lastMoveDirection.z,lastMoveDirection.x) + PI/2 move_and_slide() #applies movement func endOfPhysicsCleanup(delta: float): trauma = max(trauma-delta*traumaReductionRate,0) time += delta rotation_degrees.x = initialRotation.x + maxX * getShakeIntensity() * getNoiseFromSeed(343) rotation_degrees.y = initialRotation.y + maxY * getShakeIntensity() * getNoiseFromSeed(123) rotation_degrees.z = initialRotation.z + maxZ * getShakeIntensity() * getNoiseFromSeed(234) #Rotate head based on camera movement headPivot.rotation.y = cameraPivot.rotation.y headPivot.rotation.x = -camera.rotation.x if trauma == 0.0: headPivot.rotation.z = 0.0 headBinoculars.rotation.z = 0.0 sprintBar.value = sprintEnergy func useSprintEnergy(delta: float): sprintEnergy = clamp(sprintEnergy - sprintEnergyUse * delta, 0, 100) func setRightLeftLean(direction: int, strength: float, delta: float) -> void: if direction > 0 and rightLeftLean < 0: rightLeftLean = 0 elif direction < 0 and rightLeftLean > 0: rightLeftLean = 0 rightLeftLean = clamp(rightLeftLean + strength * delta * direction,-1,1) func getDistance(a: Node3D, b: Node3D) -> float: var distanceVector: Vector3 distanceVector = b.global_position - a.global_position return distanceVector.length() func clampVectorLength(Vector: Vector3, minLength: float, maxLength: float) -> Vector3: #scales Vector up/ down to the max/ min length givin. If the Vector has a length of 0 it will be returned without being scaled. if Vector.length() == 0: return Vector if Vector.length() < minLength: return Vector * minLength / Vector.length() elif Vector.length() > maxLength: return Vector * maxLength / Vector.length() return Vector func onCollision() -> void: trauma = 1 func addTrauma(traumaAmount: float): trauma = clamp(trauma+traumaAmount,0,1) func getShakeIntensity() -> float: return shakeIntensety * trauma * trauma func getNoiseFromSeed(seed_: int) -> float: noise.seed = seed_ return noise.get_noise_1d(time*noiseSpeed) func _input(event: InputEvent) -> void: #Camera movement with mouse if event is InputEventMouseMotion && Input.mouse_mode == 2: camera.rotation.x -= clamp(deg_to_rad(event.relative.y * mouseSensetivity),-180,180) cameraPivot.rotation.y -= deg_to_rad(event.relative.x * mouseSensetivity) facingDirection = facingDirection.rotated(deg_to_rad(event.relative.x * mouseSensetivity)) camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, -70, 70) cameraPivot.rotation.z = 0 func _on_hurt_box_hit_taken(attack: Attack) -> void: if invoulnerable: return trauma = attack.trauma health -= attack.damage if health <= 0.0: die() invoulnerable = true func die() -> void: Multiplayer.alivePlayerDict.erase(int(name)) headBinoculars.show() headPivot.position = Vector3(0,0.382,0.063) headPivot.rotation = Vector3(0,0,0) $"pivot/pivotRightLeg/pivotLeftLeg/body/Grabby Arms_L".rotation.x = deg_to_rad(90) $"pivot/pivotRightLeg/pivotLeftLeg/body/Grabby Arms_R".rotation.x = deg_to_rad(90) var spectator = spectatorScene.instantiate() spectatorParent.add_child(spectator) camera.current = false alive = false