commit 8e7da96bfcd52b230feaf40fbc6d4a42b80c5723
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Sat Oct 17 18:55:14 2026 +0200
Make state machine more reusable
commit 37da7248b8c33ce95cff7ef9332c5ccf6e3cd418
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Sat Oct 17 18:44:34 2026 +0200
Change aim state into flag
commit fbb3a84a12e2cabff9b36390da7483b8de7e9379
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Sat Oct 17 18:33:08 2026 +0200
Replace fixed references with ui references
commit 913955b13e9980780ac88761845d9e1f165f0d0e
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Fri Oct 16 13:32:21 2026 +0200
Update camera action handling
commit 4ce0ac13ffea473cf62c2fefd1571e9df1fbbcaa
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Fri Oct 16 13:04:39 2026 +0200
Update mounting system
commit e410eca38760955b2866eecd6ac0281e2041e76d
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Fri Oct 16 12:57:25 2026 +0200
Update aiming system
commit 4c788df485ccbff5f91fd51d9f480e495f11da5f
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Thu Oct 15 21:50:26 2026 +0200
Centralize states names into constants
commit 6059479c87d749e986a48adb520ef33121104da5
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Thu Oct 15 21:25:32 2026 +0200
Refator Crouch state into flag
commit 08faec70e770042d36eed6f173a63f3aac1f67c6
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Wed Oct 14 10:19:35 2026 +0200
Update player input management and state machine
commit 11a0aecc58c50c5862a03b4fd0b55e8db024031f
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Wed Oct 14 10:17:06 2026 +0200
Delete charizard.tres
commit 399eac2b6c64f242a1c2e12360d811127f87681c
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Tue Oct 13 18:20:45 2026 +0200
Remove unused MountedState
commit 42a3668c52fe96a7509a74290a94fc5a8084b713
Author: TheThomaas <thethomaas@protonmail.ch>
Date: Tue Oct 13 18:18:08 2026 +0200
Group grounded states under common class
148 lines
6.3 KiB
GDScript
148 lines
6.3 KiB
GDScript
class_name MountRider
|
|
extends PlayerComponent
|
|
|
|
#composant a ajouter en enfant de PlayerCharacter (a cote de InputManagementComponent / RecallInput).
|
|
#gere la monte d'un SentPokemon dont l'espece a un MountProfile (voir MountRegistry) :
|
|
# - s'approcher + appuyer sur mount_action (A) pour monter, dismount_action pour descendre
|
|
# - le joueur garde ses etats Idle / Walk / Run / Jump / Aim / Throw
|
|
# - Dodge est refuse par la StateMachine et le crouch est desactive (player.can_crouch) tant qu'on est monte
|
|
# - vitesse, accel et saut sont remplaces par ceux du MountProfile
|
|
#
|
|
#le travail est reparti en trois classes :
|
|
# - MountRider (ici) : cycle monter / descendre, etats bloques, hints, signaux
|
|
# - MountDetector : trouve le pokemon montable le plus proche
|
|
# - MountSeat : la monture suit le joueur, le joueur est assis a la selle, la camera monte
|
|
#l'appui qui monte ou descend est consomme (InputManagementComponent.consume) : il ne declenche pas en plus un saut, une roulade ou un crouch.
|
|
|
|
signal mounted(sent : SentPokemon)
|
|
signal dismounted(sent : SentPokemon)
|
|
signal candidate_changed(sent : SentPokemon) #pokemon montable a portee (null = aucun) : pour afficher "A : Monter" dans le HUD
|
|
|
|
#@export var mount_action : StringName = &"player_interact" #A (manette) / E (clavier) : cree automatiquement s'il n'existe pas
|
|
#@export var dismount_action : StringName = &"player_dismount" #Y (manette) / F (clavier) : cree automatiquement s'il n'existe pas
|
|
@export var mount_range : float = 2.5 #distance horizontale max entre le joueur et le pokemon
|
|
@export var max_height_diff : float = 2.0
|
|
@export var blocked_states : PackedStringArray = [States.DODGE] #etats refuses pendant la monte
|
|
@export var swallow_jump_on_mount : bool = true #si A sert aussi a sauter : l'appui qui monte ne declenche pas de saut
|
|
@export var camera_follow_speed : float = 8.0 #vitesse a laquelle la camera monte a hauteur de selle
|
|
|
|
@export_group("Hints")
|
|
@export var mount_hint : Hint #mount.tres
|
|
@export var dismount_hint : Hint #dismount.tres
|
|
@export var jump_hint : Hint #jump.tres
|
|
|
|
var mount_action : StringName:
|
|
get: return mount_hint.action
|
|
var dismount_action : StringName:
|
|
get: return dismount_hint.action
|
|
|
|
var mount : SentPokemon = null
|
|
var profile : MountProfile = null
|
|
var candidate : SentPokemon = null
|
|
|
|
var _seat : MountSeat
|
|
var _could_dismount : bool = false #derniere valeur de _can_switch_now() pendant la monte : les hints ne sont rafraichis que si elle change
|
|
|
|
func _ready() -> void:
|
|
process_physics_priority = -10 #avant la StateMachine : l'appui qui monte est ainsi consomme avant que les etats ne le lisent
|
|
_seat = MountSeat.new(player, player.visual_root, player.cam_holder)
|
|
InputRegistry.ensure(mount_action, [InputRegistry.pad_button(JOY_BUTTON_A), InputRegistry.key(KEY_E)])
|
|
InputRegistry.ensure(dismount_action, [InputRegistry.pad_button(JOY_BUTTON_X), InputRegistry.key(KEY_F)])
|
|
|
|
func _exit_tree() -> void:
|
|
Hints.clear_hints(self)
|
|
|
|
func is_mounted() -> bool:
|
|
return mount != null
|
|
|
|
func _physics_process(_delta : float) -> void:
|
|
if mount != null:
|
|
var can_dismount : bool = _can_switch_now()
|
|
if can_dismount != _could_dismount: #le hint de descente apparait / disparait (pas de descente en plein vol)
|
|
_could_dismount = can_dismount
|
|
_refresh_hints()
|
|
if Input.is_action_just_pressed(dismount_action) and can_dismount:
|
|
dismount()
|
|
return
|
|
|
|
_set_candidate(MountDetector.find_candidate(player, mount_range, max_height_diff) if _can_switch_now() else null)
|
|
if candidate != null and Input.is_action_just_pressed(mount_action):
|
|
mount_up(candidate)
|
|
|
|
func _process(delta : float) -> void:
|
|
if mount != null and !is_instance_valid(mount):
|
|
dismount() #le pokemon a disparu sans passer par recall()
|
|
_seat.update(delta, camera_follow_speed)
|
|
|
|
func _can_switch_now() -> bool:
|
|
return player.is_on_floor() and !player.is_crouching and !player.is_aiming and player.state_machine.curr_state is GroundedState #ni accroupi ni en visant (monter / descendre : depuis le sol seulement)
|
|
|
|
#---------- hints ----------
|
|
|
|
func _refresh_hints() -> void:
|
|
#une seule source de verite pour les hints de la monture
|
|
var list : Array[Hint] = []
|
|
if mount != null:
|
|
if _can_switch_now(): list.append(dismount_hint) #pas de descente en plein vol
|
|
list.append(jump_hint)
|
|
elif candidate != null:
|
|
list.append(mount_hint)
|
|
Hints.show_hints(self, list)
|
|
|
|
func _set_candidate(s : SentPokemon) -> void:
|
|
if s == candidate: return
|
|
candidate = s
|
|
candidate_changed.emit(s)
|
|
_refresh_hints()
|
|
|
|
#---------- monter / descendre ----------
|
|
|
|
func mount_up(s : SentPokemon) -> void:
|
|
if mount != null: return
|
|
mount = s
|
|
profile = MountRegistry.get_profile(s.pokemon.species)
|
|
s.rider = player
|
|
s.recalled.connect(_on_mount_recalled)
|
|
_could_dismount = _can_switch_now()
|
|
_set_candidate(null)
|
|
_refresh_hints()
|
|
_seat.attach(s, profile)
|
|
|
|
player.is_mounted = true
|
|
player.enter_mount_stats(profile.mount_speed, profile.mount_accel, profile.mount_deccel,
|
|
-1.0 if profile.can_use_surface(MountProfile.Surface.AIR) else profile.mount_jump_height) #monture volante : le vol libre remplacera le saut
|
|
for state_name in blocked_states:
|
|
player.state_machine.set_state_blocked(state_name, true)
|
|
player.can_crouch = false #pas de crouch a dos de pokemon (voir GroundedState)
|
|
|
|
#l'appui qui monte ne doit pas faire sauter (si A sert aussi a sauter) : on le consomme jusqu'a ce que le bouton soit relache
|
|
if swallow_jump_on_mount: player.player_input.consume(player.player_input.jump_action)
|
|
|
|
mounted.emit(s)
|
|
|
|
func dismount() -> void:
|
|
if mount == null: return
|
|
var s : SentPokemon = mount if is_instance_valid(mount) else null #le pokemon a pu disparaitre sans passer par recall()
|
|
mount = null
|
|
profile = null
|
|
_refresh_hints()
|
|
_seat.detach()
|
|
|
|
player.is_mounted = false
|
|
player.exit_mount_stats()
|
|
|
|
#plus rien n'est bloque : l'appui qui descend ne declenche ni roulade ni crouch (consomme jusqu'au relachement du bouton)
|
|
for state_name in blocked_states:
|
|
player.state_machine.set_state_blocked(state_name, false)
|
|
player.can_crouch = true
|
|
player.player_input.consume(player.player_input.dodge_action)
|
|
player.player_input.consume(player.player_input.crouch_action)
|
|
|
|
if s != null:
|
|
s.rider = null
|
|
if s.recalled.is_connected(_on_mount_recalled): s.recalled.disconnect(_on_mount_recalled)
|
|
dismounted.emit(s)
|
|
|
|
func _on_mount_recalled() -> void:
|
|
dismount() #le pokemon monte vient d'etre rappele (ex : relance de ce meme pokemon depuis le HUD)
|