Trying To Make A Momentum Based Roguelike Game

Godot Version

4.6.2

Question

When I’m sprinting backwards and my state is sprint state and my velocity is more than 30 , I tend to jump continuously even while not being on the floor and i feel like the vault might be bugging as after turning the facecast off all of these problems stop happening

sprinting forwards and sideways is normal but the backwards sprinting is where the problem arises
If my velocity is greater than 30 while sprinting backwards, it starts jumping
It only stops when i leave the back button or the velocity is less than 30

PLS HELP !!!

extends CharacterBody3D


enum  State {   IDLE,
				MOVE,
				SPRINT,
				JUMP,
				FALL,
				SLIDE, 
				VAULT,
				WALLRUN,
				}

@export_group("STATES")
@export var cur_state = State.IDLE


## PLAYER COLLISION ON READY ##
@onready var collision_shape_3d = $CollisionShape3D
@onready var slide_shape = $SlideShape
@onready var standbody = $Standbody
@onready var slidebody = $Slidebody

## PLAYER LEDGE CAST ON READY ##
@onready var upcast = $"Vault Check/upcast"
@onready var downcast = $"Vault Check/downcast"
@onready var facecast = $"Vault Check/facecast"



## PLAYER CAMERA ONREADY ##
@onready var neck = $Neck
@onready var camera = $CanvasLayer/Camera
@onready var camera_3d = $Neck/Camera3D

## CANVAS LAYER ONREADY ##
@onready var speed = $CanvasLayer/Speed


## TIMERS ONREADY ##
 ##JUMPBUFFER##
@onready var jumpbuffer = $Timers/JUMPBUFFER


## ABSTRACT VARIABLES ##
var direction: Vector3= Vector3(1,0,1)



## MOUSE SENSITIVITY ##
@export_group("MOUSE SENSITIVITY")
@export var mouse_sensi = 0.009

## HEAD BOB ## 
@export_group("HEAD BOB VAR")
@export var bob_freq = 3.0
@export var bob_amp = 0.07
@export var t_bob = 0.0


## PLAYER MOVEMENT VARIABLES (X-Z) ##
@export_group("MOVEMENT VAR (X-Z)")
######
@export var CUR_SPEED = 0.0
@export var use_speed = 0.0
######
@export var walk_speed = 12.0
@export var sprint_speed = 40.0
@export var slide_boost = 20.0
@export var ledge_hop = 25.0
@export var ledge_boost = 12.0

@export var last_ground_speed = 0.0


## ACCEL/DECEL ##
@export_group("ACCEL_DECEL")
@export var ground_accel = 120.0
@export var air_accel = 50.0
@export var decel = 150.0
@export var slide_decel = 10.0

## PLAYER MOVEMENT VARIABLES (Y) ##
@export_group("MOVEMENT VAR (Y)")
@export var JUMP_VELOCITY = 30.0
@export var ledge_bump = 15.0
@export var gravity = -80.0




func _ready():
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _unhandled_input(event):
	if event is InputEventMouseMotion:
		
		rotate_y(-event.relative.x * mouse_sensi)
		
		camera_3d.rotate_x(-event.relative.y * mouse_sensi)
		
		camera_3d.rotation.x = clamp(camera_3d.rotation.x, deg_to_rad(-85), deg_to_rad(+80))
		
	if event.is_action_pressed("escape") and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
		Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	elif event.is_action_pressed("escape") and Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
		Input.mouse_mode = Input.MOUSE_MODE_CAPTURED


func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta
	
	# Reset ledge state if we somehow get stuck
	if cur_state == State.VAULT and is_on_floor():
		change_state(State.SPRINT)
	
	if Input.is_action_just_pressed("jump"):
		if is_on_floor():
			change_state(State.JUMP)
		elif not is_on_floor():
			jumpbuffer.start()
			
	if not jumpbuffer.is_stopped() and is_on_floor():
		change_state(State.JUMP)
		
	if is_on_floor() and cur_state != State.SLIDE:
		camera_3d.transform.origin = _headbob(t_bob)
		last_ground_speed = Vector3(velocity.x, 0, velocity.z).length()

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir = Input.get_vector("left", "right", "forward", "backward")
	direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	
	# Gives the current velocity
	var current_speed = Vector3(velocity.x,0.0, velocity.z).length()
	
	# The stopping velocity
	var target_velocity := Vector3(0.0, 0.0, 0.0)
	
	
	
	match cur_state:
		State.IDLE:
			CUR_SPEED = 0.0
			
			if direction:
				if Input.is_action_just_pressed("sprint"):
					change_state(State.SPRINT)
				else:
					change_state(State.MOVE)
					
			if Input.is_action_just_pressed("jump"):
				change_state(State.JUMP)
				
				
			elif not is_on_floor():
				change_state(State.FALL)
				
		State.MOVE:
			CUR_SPEED = walk_speed
			
			t_bob += delta * velocity.length() 
			
			
			if Input.is_action_just_pressed("sprint"):
				change_state(State.SPRINT)
				
			elif !direction:
				change_state(State.IDLE)
				
			elif not is_on_floor():
				change_state(State.FALL)
				
			
		State.JUMP:
			
			
			if velocity.y <= 0.0 or Input.is_action_just_released("jump"):
				change_state(State.FALL)
				
			if is_on_wall_only():
				change_state(State.WALLRUN)
				
				
		State.FALL:
			if is_on_floor():
				if direction:
					change_state(State.SPRINT)
				
				else:
					change_state(State.IDLE)
					
		State.SPRINT:
			CUR_SPEED = sprint_speed
			t_bob += delta * velocity.length() * 0.6
			
			if Input.is_action_just_pressed("sprint"):
				change_state(State.MOVE)
				
				
			elif not is_on_floor():
				change_state(State.FALL)
				
			if Input.is_action_pressed("crouch_slide"):
				change_state(State.SLIDE)
				
		State.SLIDE:
			## Stick To The Floor While Sliding
			floor_snap_length = 1.0
			
			## Returns the angle of the slope 
			var floor_angle = get_floor_angle()
			
			## slide when the slope is big (Avoid micro slopes)
			if floor_angle > 0.05:
				
				var floor_norm = get_floor_normal()
				var gravity_vel = Vector3(0.0,gravity,0.0)
				var slope_force = gravity_vel - floor_norm * gravity_vel.dot(floor_norm) * 0.5
				
				velocity.x += slope_force.x * delta
				velocity.z += slope_force.z * delta
			else:
				velocity = velocity.move_toward(target_velocity, slide_decel * delta)
			
			if Input.is_action_just_released("crouch_slide"):
				change_state(State.SPRINT)
				
			if not is_on_floor():
				change_state(State.FALL)
				
		State.VAULT:
			
			
			if is_on_floor():
				change_state(State.SPRINT)
				
			elif velocity.y <= 0.0:
				change_state(State.FALL)
				
		State.WALLRUN:
			pass
	
	######## VAULTING ##############
	vaulting(delta)
	vault_boost(delta)
	######## VAULTING ##############
			
	var final_ground_vel = move_toward(current_speed, CUR_SPEED, ground_accel * delta) 
	var air_target = Vector3(direction.x * CUR_SPEED, 0.0, direction.z * CUR_SPEED)
	var air_vel = Vector3(velocity.x,0.0,velocity.z)
	
	
	## STATE AND MOVEMENT CONDITIONS ##
	
	## MOVEMENT CONDITIONS ##
	if direction:
		if is_on_floor() and cur_state != State.SLIDE:
			velocity.x = direction.x * final_ground_vel
			velocity.z = direction.z * final_ground_vel
		elif not is_on_floor():
			var air_max_speed = max(last_ground_speed, walk_speed)  # or whatever base you prefer
			air_target = direction * air_max_speed
			
			air_vel = air_vel.move_toward(air_target, air_accel * delta)
			velocity.x = air_vel.x
			velocity.z = air_vel.z
	elif is_on_floor():
		velocity = velocity.move_toward(target_velocity, decel * delta)
		
		
	## STATE CONDITIONS ##
	
	# LEDGE CONDITION #
	# SLIDE STATE #
	if cur_state == State.SLIDE:
		collision_shape_3d.disabled = true
		slide_shape.disabled = false
		standbody.visible = false
		slidebody.visible = true
		camera_3d.position.y = move_toward(camera_3d.position.y, -0.5, 3.0 * delta)
	elif cur_state != State.SLIDE:
		collision_shape_3d.disabled = false
		slide_shape.disabled =true
		standbody.visible =true
		slidebody.visible = false
		camera_3d.position.y = move_toward(camera_3d.position.y, 0.5, 3.0 * delta)


	
		
	var flat_speed = Vector2(velocity.x, velocity.z).length()
	speed.text = "Speed: " + str(snappedf(flat_speed, 0.1))
	
	camera.text = "POSITION.Y" + str(camera_3d.position.y)

	move_and_slide()

func change_state(to_state: State):
	cur_state =to_state

	match cur_state:
		State.IDLE:
			pass
		
		State.MOVE:
			pass
			
		State.SPRINT:
			pass
			
		State.JUMP:
			velocity.y += JUMP_VELOCITY
			
		State.FALL:
			pass
			
		State.SLIDE:
			velocity.x += direction.x * slide_boost
			velocity.z += direction.z * slide_boost
			
		State.VAULT:
			velocity.y += ledge_hop
			position.y = move_toward(position.y, position.y + 1, 2.0)
			
		State.WALLRUN:
			pass


######  LEDGE HOP FUNCTION ######
func vaulting(_delta):
	if cur_state == State.VAULT:
		return
		
	if facecast.is_colliding() and not upcast.is_colliding() and cur_state != State.SLIDE and cur_state != State.JUMP and direction.length() > 0.1:
		change_state(State.VAULT)
		print("VAULTING")

func vault_boost(_delta):
	if downcast.is_colliding() and cur_state == State.VAULT:
		velocity.x += direction.x * ledge_boost
		velocity.z += direction.z * ledge_boost
		print("VAULT BOOSTING")
#########################################

func _headbob(time) -> Vector3:
	var pos = Vector3.ZERO
	pos.y = sin(time * bob_freq) * bob_amp
	pos.y = cos(time * bob_freq/2) * bob_amp
	return pos