extends CharacterBody2D #Rootmotion var rootmotion_prev := Vector2.ZERO @onready var RootMotion := $RootMotion @onready var mainbody := $mainbody @export var speed = 400 #350 init @export var grav = 40 @export var fallgrav = 60 #gravity only applied when falling @export var jump_force = 800 @export var fallvelocity_cap = 1500 # How fast the player can get when falling @export var max_air_jumps = 1 # Number of total jumps allowed (1 = normal, 2 = double jump) var jumps_done = 0 var air_jumps_done = 0 var coyote_timer = 0.0 var coyote_time = 0.2 var jump_buffered := false var jump_buffer_timer = 0.0 var jump_buffer_time = 0.2 var input_direction = 0 var direction_locked = false var facing_direction = 1 # 1 = right, -1 = left @export var sprint_mult = 1.5 @export var crouch_mult = 0.4 @export var roll_mult = 1.5 @export var jump_mult = 1.3 @onready var ap = $AnimationPlayer @onready var sprite = $Sprite2D @onready var cshape = $mainbody @onready var topcheck1 = $topcheck1 @onready var topcheck2 = $topcheck2 @onready var statemachine = $StateMachine @onready var wallrun_raycast_left1 = $wallrunrcleft1 @onready var wallrun_raycast_left2 = $wallrunrcleft2 @onready var wallrun_raycast_right1 = $wallrunrcright1 @onready var wallrun_raycast_right2 = $wallrunrcright2 @onready var wallcheckright = $wallcheckright @onready var wallcheckleft = $wallcheckleft @onready var floorcheck = $floorcheck var horizontal_direction = 0 var v_mult = 1 #velocity multiplier var v_push = 0 #velocity push in either direction var stuck_under_object = false #wallrun and pushoff var wallrun_available := true var wallrun_timer := 0.0 #:= bedeutet, dass der Typ fest festgelegt ist (z.B int, bool etc.) var wallrun_time := 0.7 # Dauer des Wallruns in Sekunden var wallrun_speed := -400.0 # Geschwindigkeit nach oben (negativ wegen y-Achse) var wallpushoff_force := 450 # Stärke des Abstoßens var wallpushoff_mult := 0.3 # schränkt die velocity.x Kontrolle des Spielers ein. var wallpushoff_timer := 0.0 var wallpushoff_time := 0.5 # dauer des pushoffs #dash var dash_available := false var dash_timer := 0.0 var dash_time := 0.2 var dash_mult := 2 #climbup var climbup_speed_y = 100 var climbup_speed_x = 500 #obstacle vault var can_vault := false var vault_direction := Vector2.ZERO var vault_mult := 1.3 #fallroll var fallroll_timer := 0.0 var fallroll_input_timer := 0.0 var fallroll_time := 0.5 #time till you need to fallroll var fallroll_input_time := 0.5 #timewindow in which the fallroll works var fallrolling := false var can_fallroll := true var fallroll_mult := 0.8 #velocity mult of fallroll differs from roll var land_delay_timer := 0.0 var land_delay_time := 0.1 #time in which player will stay in falling state after hitting the ground func _process(delta): #turnmovement() pass func _physics_process(delta): #print("jump buffered: ", jump_buffered) #move_and_collide() move_and_slide() if !direction_locked: input_direction = Input.get_axis("move_left", "move_right") else: input_direction = facing_direction #print(statemachine.current_state.get_state_name()) # zum debuggen aktivieren if statemachine.current_state.get_state_name() not in ["PlayerClimbUp", "PlayerVault", "PlayerDash"]: gravity(delta) if statemachine.current_state.get_state_name() not in ["PlayerWallrun", "PlayerWallrunPushoff", "PlayerLedgeGrab", "PlayerClimbUp"]: turnmovement() $ledgecollision.disabled = statemachine.current_state.get_state_name() in ["PlayerIdle", "PlayerRun", "PlayerCrouch", "PlayerCrouchWalk", "PlayerJump", "PlayerWallrun", "PlayerClimbUp", "PlayerRoll", "PlayerVault"] or velocity.y < 0 or Input.is_action_pressed("crouch") or(topcheck1.is_colliding() and topcheck2.is_colliding() and statemachine.current_state.get_state_name() != "PlayerLedgeGrab") $mainbody.disabled = statemachine.current_state.get_state_name() in ["PlayerClimbUp"] func movement(): velocity.x = speed * input_direction * v_mult + v_push func turnmovement(): movement() if direction_locked: return if input_direction != 0 and sign(input_direction) != facing_direction: switch_direction(sign(input_direction)) func switch_direction(new_direction): facing_direction = new_direction sprite.flip_h = (facing_direction == -1) func set_facing_direction(dir: int): #manual flip if direction_locked: return if dir in [-1, 1] and dir != facing_direction: switch_direction(dir) func gravity(delta): velocity.y += grav if velocity.y > fallvelocity_cap: velocity.y = fallvelocity_cap func head_clear() -> bool: var result = !topcheck1.is_colliding() && !topcheck2.is_colliding() return result func wall_detected_left() -> bool: var result = wallrun_raycast_left1.is_colliding() && wallrun_raycast_left2.is_colliding() return result func wall_detected_right() -> bool: var result = wallrun_raycast_right1.is_colliding() && wallrun_raycast_right2.is_colliding() return result func _on_vault_trigger_entered(trigger_name: String) -> void: print("vault trigger entered:", trigger_name) can_vault = true if trigger_name == "triggerzone_left": vault_direction = Vector2.RIGHT elif trigger_name == "triggerzone_right": vault_direction = Vector2.LEFT else: vault_direction = Vector2.ZERO func _on_vault_trigger_exited(trigger_name: String) -> void: print("vault trigger exited:", trigger_name) can_vault = false vault_direction = Vector2.ZERO func is_facing_vault_direction() -> bool: var input_dir := Input.get_action_strength("move_right") - Input.get_action_strength("move_left") # only allow vault if input matches vault_direction if vault_direction == Vector2.RIGHT and input_dir > 0: return true elif vault_direction == Vector2.LEFT and input_dir < 0: return true return false func jumpbuffer(delta): if Input.is_action_just_pressed("jump"): jump_buffered = true jump_buffer_timer = 0.0 if jump_buffered: jump_buffer_timer += delta if jump_buffer_timer >= jump_buffer_time: jump_buffered = false # transition functions func transitionidle() -> bool: var result = Input.get_axis("move_left", "move_right") == 0 && is_on_floor() return result func transitionrun() -> bool: var result = Input.get_axis("move_left", "move_right") != 0 && is_on_floor() return result func transitioncoyotejump() -> bool: var result = coyote_time >= coyote_timer and Input.is_action_just_pressed("jump") and (jumps_done == 0) return result func transitionjump() -> bool: var result = (Input.is_action_just_pressed("jump") or jump_buffered) and is_on_floor() return result func transitiondoublejump() -> bool: var result = Input.is_action_just_pressed("jump") && !is_on_floor() && (air_jumps_done < max_air_jumps) return result func transitionfall() -> bool: var result = velocity.y > 0 && !is_on_floor() return result func transitionledgegrab() -> bool: var result = !floorcheck.is_colliding() && velocity.y - grav == 0 && (wallcheckright.is_colliding() or wallcheckleft.is_colliding()) return result func transitioncrouch() -> bool: var result = is_on_floor() && Input.is_action_pressed("crouch") return result func transitioncrouchwalk() -> bool: var result = is_on_floor() && Input.is_action_pressed("crouch") && Input.get_axis("move_left", "move_right") != 0 return result func transitionwallrun() -> bool: var result = Input.is_action_just_pressed("jump") and ((Input.is_action_pressed("move_right") && wall_detected_right()) or (Input.is_action_pressed("move_left") && wall_detected_left())) and wallrun_available return result func transitionroll() -> bool: var result = Input.is_action_just_pressed("sprint") and is_on_floor() return result #func transitionfallroll() -> bool: #func transitionhardlanding() -> bool: func transitiondash() -> bool: var result = Input.is_action_just_pressed("sprint") and !is_on_floor() and dash_available and fallroll_timer < fallroll_time return result