I am adding wallrunning to my game, why do i get stuck when trying to perform a wall jump?

22 Views Asked by At

im a newbie dev using godot 4, and ive been following tutorials for certain aspects of my game, lets say for this problem, wallrunning. Wallrunning by itself is working great, but the wall jumping however, is not. I know its something to do with me using the direction variable somehwere under the # Wallrun jump comment i made

extends CharacterBody3D

# Player Nodes
@onready var neck = $neck
@onready var head = $neck/Head
@onready var eyes = $neck/Head/eyes
@onready var camera = $neck/Head/eyes/Camera3D
@onready var standing_collision_shape = $standing_collision_shape
@onready var crouching_collision_shape = $crouching_collision_shape
@onready var crouching_raycast = $crouching_raycast
@onready var animation_player = $neck/Head/eyes/AnimationPlayer

# Speed Variables
var current_speed = 5.0

const walking_speed = 5.0
const sprinting_speed = 8.0
const crouching_speed = 3.0
const wallrun_speed = 4.0

# States
var walking = false
var sprinting = false
var crouching = false
var freelooking = false
var sliding = false
var jumping = false
var wallrunning = false

# Slide Vars
var slide_timer = 0.0
var slide_timer_max = 1.0
var slide_vector = Vector2.ZERO
var slide_speed = 10.0

# Headbobbing vars
const head_bobbing_sprinting_speed = 22.0
const head_bobbing_walking_speed = 14.0
const head_bobbing_crouching_speed = 10.0

const head_bobbing_sprinting_instensity = 0.2
const head_bobbing_walking_instensity = 0.1
const head_bobbing_crouching_instensity = 0.05

var head_bobbing_current_intensity = 0.0

var head_bobbing_vector = Vector2.ZERO
var head_bobbing_index = 0.0

# Wallrunning vars
var can_wallrun = false
var wallrun_delay = 0.2
@onready var wallrun_delay_default = wallrun_delay
@export var wallrun_angle = 15.0
var wallrun_current_angle = 0.0
var side = ""
var is_wallrun_jumping = false
var wall_jump_dir = Vector3.ZERO
@export var wall_jump_horizontal_power = 1.5
@export var wall_jump_vertical_power = 0.75
@export_flags_3d_physics var wall_jump_factor = 0.4

# Movement Variables
const jump_velocity = 4.5
var crouching_depth = -0.5
var freelook_lerp_speed = 15.0
var lerp_speed = 10.0
var air_lerp_speed = 3.0
var freelook_tilt_amount = 6.0
var last_velocity = Vector3.ZERO


# Input Variables
var direction = Vector3.ZERO
@export var mouse_sens = 0.25

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

func _ready():
    Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event):
# Mouse Movement
    if event is InputEventMouseMotion:
        if freelooking:
            neck.rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
            neck.rotation.y = clamp(neck.rotation.y,deg_to_rad(-120),deg_to_rad(120))
        else:
            rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
            head.rotate_x(deg_to_rad(-event.relative.y * mouse_sens))
            head.rotation.x = clamp(head.rotation.x,deg_to_rad(-89),deg_to_rad(89))

func _process(delta):
    if Input.is_action_just_pressed("quit"):
        get_tree().quit()

func _physics_process(delta):
    # getting movement input
    var input_dir = Input.get_vector("left", "right", "forward", "backward")

    #Handle movement state

    # crouching
    if Input.is_action_pressed("crouch") || sliding:
        
        current_speed = lerp(current_speed, crouching_speed, delta * lerp_speed)
        head.position.y = lerp(head.position.y,crouching_depth, delta * lerp_speed)

        # Slide begin logic

        if sprinting && input_dir != Vector2.ZERO:
            sliding = true
            slide_timer = slide_timer_max
            slide_vector = input_dir
            freelooking = true

        standing_collision_shape.disabled = true
        crouching_collision_shape.disabled = false

        walking = false
        sprinting = false
        crouching = true

    elif !crouching_raycast.is_colliding():
    # Standing
        standing_collision_shape.disabled = false
        crouching_collision_shape.disabled = true

        head.position.y = lerp(head.position.y, 0.0, delta * lerp_speed)

        if Input.is_action_pressed("sprint"):
    # Sprinting and Walking
            current_speed = lerp(current_speed, sprinting_speed, delta * lerp_speed)

            walking = false
            sprinting = true
            crouching = false
        else:
            current_speed = lerp(current_speed, walking_speed, delta * lerp_speed)

            walking = true
            sprinting = false
            crouching = false

    # Handle Freelooking
    if Input.is_action_pressed("freelook") || sliding:
        freelooking = true
        
        if sliding:
            eyes.rotation.z = lerp(eyes.rotation.z, -deg_to_rad(7.0), lerp_speed * delta)
        else:
            eyes.rotation.z = -deg_to_rad(neck.rotation.y*freelook_tilt_amount)
    else:
        freelooking = false
        neck.rotation.y = lerp(neck.rotation.y,0.0,freelook_lerp_speed * delta)
        eyes.rotation.z = lerp(eyes.rotation.y,0.0,freelook_lerp_speed*delta)

    # Add Gravity
    if !is_on_floor():
        velocity.y -= gravity * delta

    # Handle Wallrunning
    if is_on_floor():
        wallrunning = false
        can_wallrun = false
        is_wallrun_jumping = false
        wallrun_delay = wallrun_delay_default
    else:
        wallrun_delay = clamp(wallrun_delay - delta, 0 , wallrun_delay_default)
        
        if wallrun_delay == 0.0:
            can_wallrun = true

    # Wallrun jump
    if Input.is_action_just_pressed("jump") && wallrunning:
        can_wallrun = false
        wallrunning = false
        
        velocity.y = jump_velocity * wall_jump_vertical_power
        is_wallrun_jumping = true
        
        if side == "LEFT":
            wall_jump_dir = global_transform.basis.x * wall_jump_horizontal_power
        elif side == "RIGHT":
            wall_jump_dir = -global_transform.basis.x * wall_jump_horizontal_power
        
        wall_jump_dir *= wall_jump_factor

    if is_wallrun_jumping:
        direction = (direction * (1 - wall_jump_factor)) + wall_jump_dir
        return

    process_wallrun()
    wallrun_anims(delta)

    # Handle jump.
    if Input.is_action_pressed("jump") and is_on_floor():
        velocity.y = jump_velocity
        jumping = true
        sliding = false
        animation_player.play("jumping")
    elif is_on_floor() && jumping:
        jumping = false

    # Handle Landing
    if is_on_floor():
        if last_velocity.y < -10.0:
            animation_player.play("roll")
        elif last_velocity.y < -4.0:
            animation_player.play("landing")

    # Handle Sliding
    if sliding:
        slide_timer -= delta
        if slide_timer <= 0:
            sliding = false
            freelooking = false

    # Handle Head Bobbing
    if sprinting:
        head_bobbing_current_intensity = head_bobbing_sprinting_instensity
        head_bobbing_index += head_bobbing_sprinting_speed * delta
    elif walking:
        head_bobbing_current_intensity = head_bobbing_walking_instensity
        head_bobbing_index += head_bobbing_walking_speed * delta
    elif crouching:
        head_bobbing_current_intensity = head_bobbing_crouching_instensity
        head_bobbing_index += head_bobbing_crouching_speed * delta

    if is_on_floor() && !sliding && input_dir != Vector2.ZERO:
        head_bobbing_vector.y = sin(head_bobbing_index)
        head_bobbing_vector.x = sin(head_bobbing_index/2) + 0.5

        eyes.position.y = lerp(eyes.position.y, head_bobbing_vector.y * (head_bobbing_current_intensity / 2.0), delta * lerp_speed)
        eyes.position.x = lerp(eyes.position.x, head_bobbing_vector.x * head_bobbing_current_intensity, delta * lerp_speed)
    else:
        eyes.position.y = lerp(eyes.position.y, 0.0, delta * lerp_speed)
        eyes.position.x = lerp(eyes.position.x, 0.0, delta * lerp_speed)

    # Get the input direction and handle the movement/deceleration.
    # As good practice, you should replace UI actions with custom gameplay actions.

    if is_on_floor():
        direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta*lerp_speed)
    else:
        if input_dir != Vector2.ZERO:
            direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta*air_lerp_speed)

    if sliding:
        direction = (transform.basis * Vector3(slide_vector.x,0,slide_vector.y)).normalized()
        current_speed = direction.x * (slide_timer + 0.1) * slide_speed

    if direction:
        velocity.x = direction.x * current_speed
        velocity.z = direction.z * current_speed

        if sliding:
            velocity.x = direction.x * (slide_timer + 0.1) * slide_speed
            velocity.z = direction.z * (slide_timer + 0.1) * slide_speed
    else:
        velocity.x = move_toward(velocity.x, 0, current_speed)
        velocity.z = move_toward(velocity.z, 0, current_speed)

    last_velocity = velocity

    move_and_slide()

func process_wallrun():
    if can_wallrun:
        if is_on_wall() && Input.is_action_pressed("forward") && Input.is_action_pressed("sprint"):
            # Get collision data, and its normal
            var collision = get_slide_collision(0)
            var normal = collision.get_normal()
            
            # Calculate direction on which we have to move
            var wallrun_dir = Vector3.UP.cross(normal)
            
            var player_view_dir = -camera.global_transform.basis.z
            var dot = wallrun_dir.dot(player_view_dir)
            if dot < 0:
                wallrun_dir = -wallrun_dir
                
            # Push against wall for stability
            wallrun_dir += -normal * 0.01
            
            # Enable Wallrunning
            wallrunning = true
            
            # sets side to a string, thats tells where the wall is
            side = get_side(collision.get_position())
            
            # Set gravity close to 0, and movement direction to new calculated wallrun direction
            velocity.y = -0.01
            direction = wallrun_dir
        else:
            wallrunning = false
            
func wallrun_anims(delta):
    # Tilt the view
    if wallrunning:
        if side == "RIGHT":
            wallrun_current_angle += delta * 60
            wallrun_current_angle = clamp(wallrun_current_angle, -wallrun_angle, wallrun_angle)
        elif side == "LEFT":
            wallrun_current_angle -= delta * 60
            wallrun_current_angle = clamp(wallrun_current_angle, -wallrun_angle, wallrun_angle)
            
    # Return to normal view
    else:
        if wallrun_current_angle > 0:
            wallrun_current_angle -= delta * 40
            wallrun_current_angle = max(0, wallrun_current_angle)
        elif wallrun_current_angle < 0:
            wallrun_current_angle += delta * 40
            wallrun_current_angle = min(wallrun_current_angle, 0)
            
    neck.rotation_degrees = Vector3(0, 0, 1) * wallrun_current_angle

func get_side(point):
    point = to_local(point)
    
    if point.x > 0:
        return "RIGHT"
    elif point.x < 0:
        return "LEFT"
    else:
        return "CENTER"

ive tried cutting the code, to figure out where the problem was happening. I also looked over the tutorials code 16 quadrillion times, to no avail

0

There are 0 best solutions below