extends Node class_name StateWallCling var machine: MovementStateMachine var params: MovementParams: get: return machine.params var elapsed: float = 0.0 var stamina: float = 0.0 func enter(_data: Dictionary = {}) -> void: elapsed = 0.0 stamina = params.wall_cling_max_stamina machine.register_chain_mechanic("wall_cling") # Kill most velocity but keep slight downward machine.player.velocity = Vector3.ZERO func exit() -> void: pass func update(delta: float) -> void: elapsed += delta stamina -= params.wall_cling_stamina_drain * delta var player := machine.player var vel: Vector3 = player.velocity # ── Slow slide down ─────────────────────────────────────────────────── var slide_factor := 1.0 - (stamina / params.wall_cling_max_stamina) # 0→1 as stamina drains vel.x = 0.0 vel.z = 0.0 vel.y = params.wall_cling_slide_speed * (1.0 + slide_factor * 2.0) # Push into wall to maintain contact vel -= machine.wall_normal * 1.0 player.velocity = vel player.move_and_slide() # ── Stamina depleted → fall ─────────────────────────────────────────── if stamina <= 0.0: machine.wall_normal = Vector3.ZERO machine.wall_side = 0.0 machine.switch_to("air") return # ── Jump off wall ───────────────────────────────────────────────────── if machine.input_jump_just_pressed and machine.jump_cooldown_timer <= 0.0: var push_dir := machine.wall_normal * params.wall_run_jump_off_normal player.velocity = Vector3(push_dir.x, params.jump_velocity, push_dir.z) machine.wall_normal = Vector3.ZERO machine.wall_side = 0.0 machine.wall_cooldown_timer = 0.3 machine.register_chain_mechanic("wall_cling_jump") machine.jump_cooldown_timer = params.jump_cooldown machine.switch_to("air") return # ── Re-enter wall run with movement input ───────────────────────────── if machine.input_dir.length() > 0.1: machine.switch_to("wall_run") return # ── Lost wall contact ───────────────────────────────────────────────── var wall := machine.detect_wall_horizontal() if wall == Vector3.ZERO: machine.wall_normal = Vector3.ZERO machine.wall_side = 0.0 machine.switch_to("air") return # ── Hit floor ───────────────────────────────────────────────────────── if player.is_on_floor(): machine.on_ground = true machine.wall_normal = Vector3.ZERO machine.wall_side = 0.0 machine.switch_to("ground")