93 lines
2.5 KiB
GDScript
93 lines
2.5 KiB
GDScript
extends Node
|
|
class_name StateDash
|
|
|
|
var machine: MovementStateMachine
|
|
var params: MovementParams:
|
|
get: return machine.params
|
|
|
|
var elapsed: float = 0.0
|
|
var direction: Vector3 = Vector3.ZERO
|
|
var _exit_speed: float = 0.0
|
|
var _last_vel: Vector3 = Vector3.ZERO
|
|
|
|
# Cooldown tracked across dash instances
|
|
static var _last_dash_time: float = -999.0
|
|
|
|
|
|
func enter(_data: Dictionary = {}) -> void:
|
|
# Check cooldown
|
|
var now := Time.get_ticks_msec() / 1000.0
|
|
if now - _last_dash_time < params.dash_cooldown:
|
|
machine.switch_to("air")
|
|
return
|
|
|
|
elapsed = 0.0
|
|
_last_dash_time = now
|
|
|
|
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")
|
|
|
|
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
|
|
_exit_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
|
|
_exit_speed = lerpf(base_dash_speed, maxf(current_speed, base_dash_speed), backward_factor)
|
|
|
|
machine.player.velocity = direction * _exit_speed
|
|
machine.on_ground = false
|
|
_last_vel = machine.player.velocity
|
|
|
|
|
|
func exit() -> void:
|
|
# Preserve dash velocity on exit (don't cut speed abruptly)
|
|
pass
|
|
|
|
|
|
func update(delta: float) -> void:
|
|
elapsed += delta
|
|
if elapsed > params.dash_duration:
|
|
machine.player.velocity = direction * _exit_speed * 0.85
|
|
if machine.player.is_on_floor():
|
|
machine.on_ground = true
|
|
machine.switch_to("ground")
|
|
else:
|
|
machine.switch_to("air")
|
|
return
|
|
|
|
# Maintain dash velocity
|
|
var player := machine.player
|
|
var vel: Vector3 = player.velocity
|
|
|
|
if vel.distance_squared_to(_last_vel) > 100.0:
|
|
machine.switch_to("air")
|
|
return
|
|
|
|
vel = direction * _exit_speed
|
|
if player.is_on_floor():
|
|
vel.y = -0.5 # Snap to floor to handle ramps
|
|
|
|
player.velocity = vel
|
|
player.move_and_slide()
|
|
_last_vel = player.velocity
|