Advertisement
AriesOnThat

help

Mar 30th, 2024
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.73 KB | Source Code | 0 0
  1. extends CharacterBody3D
  2.  
  3. # Player Nodes
  4. @onready var neck = $neck
  5. @onready var head = $neck/Head
  6. @onready var eyes = $neck/Head/eyes
  7. @onready var camera = $neck/Head/eyes/Camera3D
  8. @onready var standing_collision_shape = $standing_collision_shape
  9. @onready var crouching_collision_shape = $crouching_collision_shape
  10. @onready var crouching_raycast = $crouching_raycast
  11. @onready var animation_player = $neck/Head/eyes/AnimationPlayer
  12.  
  13. # Speed Variables
  14. var current_speed = 5.0
  15.  
  16. const walking_speed = 5.0
  17. const sprinting_speed = 8.0
  18. const crouching_speed = 3.0
  19. const wallrun_speed = 4.0
  20.  
  21. # States
  22. var walking = false
  23. var sprinting = false
  24. var crouching = false
  25. var freelooking = false
  26. var sliding = false
  27. var jumping = false
  28. var wallrunning = false
  29.  
  30. # Slide Vars
  31. var slide_timer = 0.0
  32. var slide_timer_max = 1.0
  33. var slide_vector = Vector2.ZERO
  34. var slide_speed = 10.0
  35.  
  36. # Headbobbing vars
  37. const head_bobbing_sprinting_speed = 22.0
  38. const head_bobbing_walking_speed = 14.0
  39. const head_bobbing_crouching_speed = 10.0
  40.  
  41. const head_bobbing_sprinting_instensity = 0.2
  42. const head_bobbing_walking_instensity = 0.1
  43. const head_bobbing_crouching_instensity = 0.05
  44.  
  45. var head_bobbing_current_intensity = 0.0
  46.  
  47. var head_bobbing_vector = Vector2.ZERO
  48. var head_bobbing_index = 0.0
  49.  
  50. # Wallrunning vars
  51. var can_wallrun = false
  52. var wallrun_delay = 0.2
  53. @onready var wallrun_delay_default = wallrun_delay
  54. @export var wallrun_angle = 15.0
  55. var wallrun_current_angle = 0.0
  56. var side = ""
  57. var is_wallrun_jumping = false
  58. var wall_jump_dir = Vector3.ZERO
  59. @export var wall_jump_horizontal_power = 1.5
  60. @export var wall_jump_vertical_power = 0.75
  61. @export var wall_jump_factor = 0.4
  62.  
  63. # Movement Variables
  64. const jump_velocity = 4.5
  65. var crouching_depth = -0.5
  66. var freelook_lerp_speed = 15.0
  67. var lerp_speed = 10.0
  68. var air_lerp_speed = 3.0
  69. var freelook_tilt_amount = 6.0
  70. var last_velocity = Vector3.ZERO
  71.  
  72.  
  73. # Input Variables
  74. var direction = Vector3.ZERO
  75. @export var mouse_sens = 0.25
  76.  
  77. # Get the gravity from the project settings to be synced with RigidBody nodes.
  78. var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
  79.  
  80. func _ready():
  81. Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
  82.  
  83. func _input(event):
  84. # Mouse Movement
  85. if event is InputEventMouseMotion:
  86. if freelooking:
  87. neck.rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
  88. neck.rotation.y = clamp(neck.rotation.y,deg_to_rad(-120),deg_to_rad(120))
  89. else:
  90. rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
  91. head.rotate_x(deg_to_rad(-event.relative.y * mouse_sens))
  92. head.rotation.x = clamp(head.rotation.x,deg_to_rad(-89),deg_to_rad(89))
  93.  
  94. func _process(delta):
  95. if Input.is_action_just_pressed("quit"):
  96. get_tree().quit()
  97.  
  98. func _physics_process(delta):
  99. # getting movement input
  100. var input_dir = Input.get_vector("left", "right", "forward", "backward")
  101.  
  102. #Handle movement state
  103.  
  104. # crouching
  105. if Input.is_action_pressed("crouch") || sliding:
  106.  
  107. current_speed = lerp(current_speed, crouching_speed, delta * lerp_speed)
  108. head.position.y = lerp(head.position.y,crouching_depth, delta * lerp_speed)
  109.  
  110. # Slide begin logic
  111.  
  112. if sprinting && input_dir != Vector2.ZERO:
  113. sliding = true
  114. slide_timer = slide_timer_max
  115. slide_vector = input_dir
  116. freelooking = true
  117.  
  118. standing_collision_shape.disabled = true
  119. crouching_collision_shape.disabled = false
  120.  
  121. walking = false
  122. sprinting = false
  123. crouching = true
  124.  
  125. elif !crouching_raycast.is_colliding():
  126. # Standing
  127. standing_collision_shape.disabled = false
  128. crouching_collision_shape.disabled = true
  129.  
  130. head.position.y = lerp(head.position.y, 0.0, delta * lerp_speed)
  131.  
  132. if Input.is_action_pressed("sprint"):
  133. # Sprinting and Walking
  134. current_speed = lerp(current_speed, sprinting_speed, delta * lerp_speed)
  135.  
  136. walking = false
  137. sprinting = true
  138. crouching = false
  139. else:
  140. current_speed = lerp(current_speed, walking_speed, delta * lerp_speed)
  141.  
  142. walking = true
  143. sprinting = false
  144. crouching = false
  145.  
  146. # Handle Freelooking
  147. if Input.is_action_pressed("freelook") || sliding:
  148. freelooking = true
  149.  
  150. if sliding:
  151. eyes.rotation.z = lerp(eyes.rotation.z, -deg_to_rad(7.0), lerp_speed * delta)
  152. else:
  153. eyes.rotation.z = -deg_to_rad(neck.rotation.y*freelook_tilt_amount)
  154. else:
  155. freelooking = false
  156. neck.rotation.y = lerp(neck.rotation.y,0.0,freelook_lerp_speed * delta)
  157. eyes.rotation.z = lerp(eyes.rotation.y,0.0,freelook_lerp_speed*delta)
  158.  
  159. # Add Gravity
  160. if !is_on_floor():
  161. velocity.y -= gravity * delta
  162.  
  163. # Handle Wallrunning
  164. if is_on_floor():
  165. wallrunning = false
  166. can_wallrun = false
  167. is_wallrun_jumping = false
  168. wallrun_delay = wallrun_delay_default
  169. else:
  170. wallrun_delay = clamp(wallrun_delay - delta, 0 , wallrun_delay_default)
  171.  
  172. if wallrun_delay == 0.0:
  173. can_wallrun = true
  174.  
  175. # Wallrun jump
  176. if Input.is_action_just_pressed("jump") && wallrunning:
  177. can_wallrun = false
  178. wallrunning = false
  179.  
  180. velocity.y = jump_velocity * wall_jump_vertical_power
  181. is_wallrun_jumping = true
  182.  
  183. if side == "LEFT":
  184. wall_jump_dir = global_transform.basis.x * wall_jump_horizontal_power
  185. elif side == "RIGHT":
  186. wall_jump_dir = -global_transform.basis.x * wall_jump_horizontal_power
  187.  
  188. wall_jump_dir *= wall_jump_factor
  189.  
  190. if is_wallrun_jumping:
  191. direction = (direction * (1 - wall_jump_factor)) + wall_jump_dir
  192. return
  193.  
  194. process_wallrun()
  195. wallrun_anims(delta)
  196.  
  197. # Handle jump.
  198. if Input.is_action_pressed("jump") and is_on_floor():
  199. velocity.y = jump_velocity
  200. jumping = true
  201. sliding = false
  202. animation_player.play("jumping")
  203. elif is_on_floor() && jumping:
  204. jumping = false
  205.  
  206. # Handle Landing
  207. if is_on_floor():
  208. if last_velocity.y < -10.0:
  209. animation_player.play("roll")
  210. elif last_velocity.y < -4.0:
  211. animation_player.play("landing")
  212.  
  213. # Handle Sliding
  214. if sliding:
  215. slide_timer -= delta
  216. if slide_timer <= 0:
  217. sliding = false
  218. freelooking = false
  219.  
  220. # Handle Head Bobbing
  221. if sprinting:
  222. head_bobbing_current_intensity = head_bobbing_sprinting_instensity
  223. head_bobbing_index += head_bobbing_sprinting_speed * delta
  224. elif walking:
  225. head_bobbing_current_intensity = head_bobbing_walking_instensity
  226. head_bobbing_index += head_bobbing_walking_speed * delta
  227. elif crouching:
  228. head_bobbing_current_intensity = head_bobbing_crouching_instensity
  229. head_bobbing_index += head_bobbing_crouching_speed * delta
  230.  
  231. if is_on_floor() && !sliding && input_dir != Vector2.ZERO:
  232. head_bobbing_vector.y = sin(head_bobbing_index)
  233. head_bobbing_vector.x = sin(head_bobbing_index/2) + 0.5
  234.  
  235. eyes.position.y = lerp(eyes.position.y, head_bobbing_vector.y * (head_bobbing_current_intensity / 2.0), delta * lerp_speed)
  236. eyes.position.x = lerp(eyes.position.x, head_bobbing_vector.x * head_bobbing_current_intensity, delta * lerp_speed)
  237. else:
  238. eyes.position.y = lerp(eyes.position.y, 0.0, delta * lerp_speed)
  239. eyes.position.x = lerp(eyes.position.x, 0.0, delta * lerp_speed)
  240.  
  241. # Get the input direction and handle the movement/deceleration.
  242. # As good practice, you should replace UI actions with custom gameplay actions.
  243.  
  244. if is_on_floor():
  245. direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta*lerp_speed)
  246. else:
  247. if input_dir != Vector2.ZERO:
  248. direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta*air_lerp_speed)
  249.  
  250. if sliding:
  251. direction = (transform.basis * Vector3(slide_vector.x,0,slide_vector.y)).normalized()
  252. current_speed = direction.x * (slide_timer + 0.1) * slide_speed
  253.  
  254. if direction:
  255. velocity.x = direction.x * current_speed
  256. velocity.z = direction.z * current_speed
  257.  
  258. if sliding:
  259. velocity.x = direction.x * (slide_timer + 0.1) * slide_speed
  260. velocity.z = direction.z * (slide_timer + 0.1) * slide_speed
  261. else:
  262. velocity.x = move_toward(velocity.x, 0, current_speed)
  263. velocity.z = move_toward(velocity.z, 0, current_speed)
  264.  
  265. last_velocity = velocity
  266.  
  267. move_and_slide()
  268.  
  269. func process_wallrun():
  270. if can_wallrun:
  271. if is_on_wall() && Input.is_action_pressed("forward") && Input.is_action_pressed("sprint"):
  272. # Get collision data, and its normal
  273. var collision = get_slide_collision(0)
  274. var normal = collision.get_normal()
  275.  
  276. # Calculate direction on which we have to move
  277. var wallrun_dir = Vector3.UP.cross(normal)
  278.  
  279. var player_view_dir = -camera.global_transform.basis.z
  280. var dot = wallrun_dir.dot(player_view_dir)
  281. if dot < 0:
  282. wallrun_dir = -wallrun_dir
  283.  
  284. # Push against wall for stability
  285. wallrun_dir += -normal * 0.01
  286.  
  287. # Enable Wallrunning
  288. wallrunning = true
  289.  
  290. # sets side to a string, thats tells where the wall is
  291. side = get_side(collision.get_position())
  292.  
  293. # Set gravity close to 0, and movement direction to new calculated wallrun direction
  294. velocity.y = -0.01
  295. direction = wallrun_dir
  296. else:
  297. wallrunning = false
  298.  
  299. func wallrun_anims(delta):
  300. # Tilt the view
  301. if wallrunning:
  302. if side == "RIGHT":
  303. wallrun_current_angle += delta * 60
  304. wallrun_current_angle = clamp(wallrun_current_angle, -wallrun_angle, wallrun_angle)
  305. elif side == "LEFT":
  306. wallrun_current_angle -= delta * 60
  307. wallrun_current_angle = clamp(wallrun_current_angle, -wallrun_angle, wallrun_angle)
  308.  
  309. # Return to normal view
  310. else:
  311. if wallrun_current_angle > 0:
  312. wallrun_current_angle -= delta * 40
  313. wallrun_current_angle = max(0, wallrun_current_angle)
  314. elif wallrun_current_angle < 0:
  315. wallrun_current_angle += delta * 40
  316. wallrun_current_angle = min(wallrun_current_angle, 0)
  317.  
  318. neck.rotation_degrees = Vector3(0, 0, 1) * wallrun_current_angle
  319.  
  320. func get_side(point):
  321. point = to_local(point)
  322.  
  323. if point.x > 0:
  324. return "RIGHT"
  325. elif point.x < 0:
  326. return "LEFT"
  327. else:
  328. return "CENTER"
  329.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement