stick-the-quick/characters/abilities/FlyAbility.gd

96 lines
2.5 KiB
GDScript3
Raw Normal View History

class_name FlyAbility extends RunnerAbility
const LIFT_SCALE: float = 10000.0
const TILT_LIFT_SCALE: float = 13.0
const MAX_BACKWARD_IMPETUS: float = 0.5
@export var tilt: float = 0.375
@export var thrust: float = 0.5
@export var lift: float = 1.0
var saved_gravity_scale: float = -1.0
var saved_deceleration: float = -1.0
var saved_speed_cap: float = -1.0
func begin(runner: Runner) -> void:
if runner.floor_normal.is_zero_approx():
saved_gravity_scale = runner.gravity_scale
saved_deceleration = runner.run_deceleration
saved_speed_cap = runner.top_run_speed
runner.gravity_scale /= 4.0
runner.run_deceleration = 0.0
runner.top_run_speed = INF
else:
runner.change_state(&'jump')
func integrate_forces(
runner: Runner,
body_state: PhysicsDirectBodyState3D
) -> void:
if not runner.floor_normal.is_zero_approx():
runner.change_state(&'fall')
elif not runner.wall_normal.is_zero_approx():
runner.change_state(&'wall_slide')
else:
body_state.linear_velocity -= (
impetus_multiplier *
runner.impetus.project(runner.basis.z) *
runner.run_acceleration *
body_state.step
)
var speed_factor = (
body_state.linear_velocity.slide(
Vector3.UP
).length() /
saved_speed_cap
)
var local_impetus := runner.impetus*runner.basis
var real_tilt: float = local_impetus.z*tilt/(
1.0 + lift*TILT_LIFT_SCALE*(speed_factor**2.0)
)
if real_tilt < 0.0:
runner.up_normal = runner.up_normal.lerp(
Vector3.UP - runner.basis.z, -real_tilt
).normalized()
else:
runner.up_normal = runner.up_normal.lerp(
Vector3.UP + runner.basis.z, real_tilt
).normalized()
body_state.linear_velocity = (
body_state.linear_velocity.slide(Vector3.UP)
)
body_state.linear_velocity += (
runner.basis.z *
thrust *
runner.run_acceleration *
max(local_impetus.z, -MAX_BACKWARD_IMPETUS) *
body_state.step
)
body_state.linear_velocity -= (
Vector3.UP *
lift*LIFT_SCALE *
real_tilt *
(speed_factor**2.0) *
body_state.step
)
func orientation(runner: Runner) -> Vector3:
return runner.linear_velocity
func animation_speed(runner: Runner) -> float:
return 1.0 + runner.linear_velocity.length()/10.0
func end(runner: Runner) -> void:
if saved_gravity_scale > 0.0:
runner.gravity_scale = saved_gravity_scale
saved_gravity_scale = -1.0
if saved_deceleration > 0.0:
runner.run_deceleration = saved_deceleration
saved_deceleration = -1.0
if saved_speed_cap > 0.0:
runner.top_run_speed = saved_speed_cap
saved_speed_cap = -1.0
func on_repeated_input(runner: Runner) -> void:
runner.change_state(&'fall')