96 lines
3.4 KiB
GDScript
96 lines
3.4 KiB
GDScript
extends State
|
|
|
|
class_name DodgeState
|
|
|
|
var state_name : String = "Dodge"
|
|
|
|
var play_char : CharacterBody3D
|
|
|
|
@export var dodge_speed_curve : Curve #optionnel : controle le "falloff" de vitesse pendant la roulade (1.0 = pleine vitesse, 0.0 = arret). Laisser vide pour une vitesse constante.
|
|
|
|
var dodge_dir : Vector2 = Vector2.ZERO
|
|
var dodge_timer : float = 0.0
|
|
var dodge_duration_ref : float = 0.0
|
|
var came_from_crouch : bool = false #true si l'esquive vient du crouch (directement, ou via Aim declenche depuis le crouch)
|
|
|
|
func enter(play_char_ref : CharacterBody3D) -> void:
|
|
play_char = play_char_ref
|
|
|
|
#curr_state_name n'est pas encore mis a jour a ce stade : il reflete encore l'etat qu'on quitte
|
|
var previous : String = play_char.state_machine.curr_state_name
|
|
if previous == "Crouch":
|
|
came_from_crouch = true
|
|
elif previous == "Aim":
|
|
var aim : Node = play_char.state_machine.states.get("aimstate")
|
|
came_from_crouch = aim != null and aim.came_from_crouch
|
|
else:
|
|
came_from_crouch = false
|
|
|
|
verifications()
|
|
|
|
func verifications() -> void:
|
|
play_char.floor_snap_length = 1.0
|
|
play_char.is_dodging = true
|
|
play_char.dodge_cooldown = play_char.dodge_cooldown_ref
|
|
|
|
#roule dans la direction actuelle de l'input, ou dans la derniere direction connue si aucune touche n'est tenue (comportement Arceus)
|
|
dodge_dir = play_char.move_dir if play_char.move_dir != Vector2.ZERO else play_char.last_input_dir
|
|
if dodge_dir == Vector2.ZERO: dodge_dir = Vector2.DOWN #direction par defaut si le perso n'a encore jamais bouge
|
|
dodge_dir = dodge_dir.normalized()
|
|
|
|
dodge_timer = play_char.dodge_duration
|
|
dodge_duration_ref = play_char.dodge_duration
|
|
|
|
#oriente immediatement le modele dans la direction de la roulade, verrouillee pour toute sa duree
|
|
play_char.visual_root.rotation.y = -dodge_dir.orthogonal().angle()
|
|
|
|
func exit() -> void:
|
|
play_char.is_dodging = false
|
|
|
|
func physics_update(delta : float) -> void:
|
|
applies()
|
|
|
|
play_char.gravity_apply(delta)
|
|
|
|
move(delta)
|
|
|
|
dodge_timer -= delta
|
|
if dodge_timer <= 0.0:
|
|
end_dodge()
|
|
|
|
func applies() -> void:
|
|
#si le perso quitte le sol en roulant (ex: roulade vers un bord), on bascule vers InairState comme les autres etats au sol
|
|
if !play_char.is_on_floor() and !play_char.is_on_wall():
|
|
if play_char.velocity.y < 0.0:
|
|
transitioned.emit(self, "InairState")
|
|
|
|
func move(_delta : float) -> void:
|
|
if !play_char.is_on_floor(): return
|
|
|
|
#falloff de vitesse : pleine vitesse par defaut, ou modele par dodge_speed_curve si assignee
|
|
var ratio : float = 1.0
|
|
if dodge_speed_curve:
|
|
ratio = dodge_speed_curve.sample(1.0 - (dodge_timer / dodge_duration_ref))
|
|
|
|
play_char.velocity.x = dodge_dir.x * play_char.dodge_speed * ratio
|
|
play_char.velocity.z = dodge_dir.y * play_char.dodge_speed * ratio
|
|
|
|
func end_dodge() -> void:
|
|
#a la fin de la roulade, retour a l'etat approprie
|
|
if !play_char.is_on_floor():
|
|
transitioned.emit(self, "InairState")
|
|
elif Input.is_action_pressed(play_char.aim_cam_action):
|
|
#AimState ne verra que "Dodge" comme etat precedent : on lui transmet l'origine crouch
|
|
var aim : Node = play_char.state_machine.states.get("aimstate")
|
|
if aim: aim.came_from_crouch = came_from_crouch
|
|
transitioned.emit(self, "AimState") #le joueur a garde la visee enfoncee pendant la roulade
|
|
elif came_from_crouch:
|
|
transitioned.emit(self, "CrouchState")
|
|
elif play_char.move_dir:
|
|
transitioned.emit(self, play_char.walk_or_run)
|
|
else:
|
|
transitioned.emit(self, "IdleState")
|
|
|
|
func get_hints() -> Variant:
|
|
return null
|