extends Node class_name StateDash ## Short burst dash. Cooldown lives on the machine (per-player instance) and is ## checked by the states that enter dash, so entering this state always dashes. ## Momentum is fully preserved on exit — the dash ADDS speed to your run. var machine: MovementStateMachine var params: MovementParams: get: return machine.params var elapsed: float = 0.0 var direction: Vector3 = Vector3.ZERO var _dash_speed: float = 0.0 func enter(_data: Dictionary = {}) -> void: elapsed = 0.0 machine.consume_dash_charge() var player := machine.player if player.dash_player: player.dash_player.play() # Direction: use wish direction if available, else player forward var wish := machine.wish_dir_world if wish.length_squared() > 0.01: direction = wish.normalized() else: direction = -machine.player.global_transform.basis.z direction.y = 0.0 direction = direction.normalized() machine.register_chain_mechanic("dash") machine.movement_event.emit("dash", {}) var current_hvel := Vector3(machine.player.velocity.x, 0.0, machine.player.velocity.z) var current_speed := current_hvel.length() var proj := current_hvel.dot(direction) var base_dash_speed = machine.get_effective_speed(params.dash_speed) if proj >= 0.0: # Dashing forward or diagonally forward: add base dash speed to the projected speed _dash_speed = proj + base_dash_speed else: # Dashing backward or diagonally backward: # Reflect current momentum into the new direction, smoothly scaling from # base_dash_speed (at sideways) to current_speed (at exactly backward). var backward_factor = -proj / current_speed if current_speed > 0.001 else 0.0 _dash_speed = lerpf(base_dash_speed, maxf(current_speed, base_dash_speed), backward_factor) machine.player.velocity = direction * _dash_speed machine.on_ground = false func exit() -> void: pass func update(delta: float) -> void: elapsed += delta var player := machine.player if elapsed > params.dash_duration: # Keep the full dash velocity — the dash is a speed investment player.velocity = direction * _dash_speed if player.is_on_floor(): machine.on_ground = true machine.switch_to("ground") else: machine.switch_to("air") return # Maintain dash velocity, flat trajectory var vel := direction * _dash_speed if player.is_on_floor(): vel.y = -0.5 # Snap to floor to handle ramps player.velocity = vel player.move_and_slide()