Update hints system
This commit is contained in:
parent
65ccb1905c
commit
fc5afc8ca5
|
|
@ -22,7 +22,6 @@ signal candidate_changed(sent : SentPokemon) #pokemon montable a portee (null =
|
||||||
|
|
||||||
@export_group("Hints HUD")
|
@export_group("Hints HUD")
|
||||||
@export var mount_hint_text : String = "Grimper"
|
@export var mount_hint_text : String = "Grimper"
|
||||||
@export var dismount_hint_text : String = "Descendre"
|
|
||||||
@export var hint_priority : int = 10
|
@export var hint_priority : int = 10
|
||||||
|
|
||||||
const GROUNDED_STATES : Array[String] = ["Idle", "Walk", "Run"] #monter / descendre n'est possible que depuis ces etats
|
const GROUNDED_STATES : Array[String] = ["Idle", "Walk", "Run"] #monter / descendre n'est possible que depuis ces etats
|
||||||
|
|
@ -70,7 +69,7 @@ func is_mounted() -> bool:
|
||||||
func _physics_process(_delta : float) -> void:
|
func _physics_process(_delta : float) -> void:
|
||||||
if mount != null:
|
if mount != null:
|
||||||
var can_dismount : bool = _can_switch_now()
|
var can_dismount : bool = _can_switch_now()
|
||||||
if can_dismount: Hints.set_context(self, dismount_action, dismount_hint_text, hint_priority)
|
if can_dismount: Hints.set_context(self, dismount_action, "", hint_priority)
|
||||||
else: Hints.clear_context(self)
|
else: Hints.clear_context(self)
|
||||||
if Input.is_action_just_pressed(dismount_action) and can_dismount:
|
if Input.is_action_just_pressed(dismount_action) and can_dismount:
|
||||||
dismount()
|
dismount()
|
||||||
|
|
@ -146,7 +145,7 @@ func mount_up(s : SentPokemon) -> void:
|
||||||
s.rider = player
|
s.rider = player
|
||||||
s.recalled.connect(_on_mount_recalled)
|
s.recalled.connect(_on_mount_recalled)
|
||||||
_set_candidate(null)
|
_set_candidate(null)
|
||||||
Hints.set_context(self, dismount_action, dismount_hint_text, hint_priority)
|
Hints.set_context(self, dismount_action, "", hint_priority)
|
||||||
|
|
||||||
player.is_mounted = true
|
player.is_mounted = true
|
||||||
player.enter_mount_stats(profile.mount_speed, profile.mount_accel, profile.mount_deccel,
|
player.enter_mount_stats(profile.mount_speed, profile.mount_accel, profile.mount_deccel,
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,15 @@ initial_state = NodePath("IdleState")
|
||||||
|
|
||||||
[node name="IdleState" type="Node" parent="StateMachine" unique_id=1417869633]
|
[node name="IdleState" type="Node" parent="StateMachine" unique_id=1417869633]
|
||||||
script = ExtResource("4_38lxl")
|
script = ExtResource("4_38lxl")
|
||||||
|
hints = Array[StringName]([&"player_jump"])
|
||||||
|
|
||||||
[node name="WalkState" type="Node" parent="StateMachine" unique_id=1524475809]
|
[node name="WalkState" type="Node" parent="StateMachine" unique_id=1524475809]
|
||||||
script = ExtResource("4_lg056")
|
script = ExtResource("4_lg056")
|
||||||
|
hints = Array[StringName]([&"player_jump"])
|
||||||
|
|
||||||
[node name="JumpState" type="Node" parent="StateMachine" unique_id=711160985]
|
[node name="JumpState" type="Node" parent="StateMachine" unique_id=711160985]
|
||||||
script = ExtResource("6_lwgph")
|
script = ExtResource("6_lwgph")
|
||||||
|
hints = Array[StringName]([&"player_jump"])
|
||||||
|
|
||||||
[node name="AimState" type="Node" parent="StateMachine" unique_id=296560188]
|
[node name="AimState" type="Node" parent="StateMachine" unique_id=296560188]
|
||||||
script = ExtResource("7_kxr4l")
|
script = ExtResource("7_kxr4l")
|
||||||
|
|
@ -96,6 +99,7 @@ script = ExtResource("8_k0r6x")
|
||||||
|
|
||||||
[node name="RunState" type="Node" parent="StateMachine" unique_id=1345421775]
|
[node name="RunState" type="Node" parent="StateMachine" unique_id=1345421775]
|
||||||
script = ExtResource("8_j4mf1")
|
script = ExtResource("8_j4mf1")
|
||||||
|
hints = Array[StringName]([&"player_jump"])
|
||||||
|
|
||||||
[node name="DodgeState" type="Node" parent="StateMachine" unique_id=232179400]
|
[node name="DodgeState" type="Node" parent="StateMachine" unique_id=232179400]
|
||||||
script = ExtResource("9_6abew")
|
script = ExtResource("9_6abew")
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,11 @@ var auto_lock_blocked : bool = false #true apres un deverrouillage manuel, tant
|
||||||
var dodging_from_aim : bool = false #true quand on quitte Aim pour rouler, pour ne pas relacher la cible verrouillee
|
var dodging_from_aim : bool = false #true quand on quitte Aim pour rouler, pour ne pas relacher la cible verrouillee
|
||||||
var came_from_crouch : bool = false #true si Aim a ete declenche depuis CrouchState, pour y retourner en sortant
|
var came_from_crouch : bool = false #true si Aim a ete declenche depuis CrouchState, pour y retourner en sortant
|
||||||
var keep_aim_on_exit : bool = false #true quand on part vers ThrowState : camera et verrouillage restent en place
|
var keep_aim_on_exit : bool = false #true quand on part vers ThrowState : camera et verrouillage restent en place
|
||||||
var charging_throw : bool = false #true quand on arrive depuis ThrowState en pleine charge : RT est encore maintenue
|
var charging_throw : bool = false: #true quand on arrive depuis ThrowState en pleine charge : RT est encore maintenue
|
||||||
|
set(value):
|
||||||
|
if charging_throw == value: return
|
||||||
|
charging_throw = value
|
||||||
|
hints_changed.emit()
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
if InputMap.has_action(throw_action): return
|
if InputMap.has_action(throw_action): return
|
||||||
|
|
@ -236,6 +240,6 @@ func release_target() -> void:
|
||||||
play_char.cam_holder.set_lock_target(null)
|
play_char.cam_holder.set_lock_target(null)
|
||||||
|
|
||||||
func get_hints() -> Array:
|
func get_hints() -> Array:
|
||||||
return [
|
var list : Array[StringName] = [switch_target_action]
|
||||||
{"action": switch_target_action, "text": "Changer de cible"}
|
if charging_throw: list.append(cancel_action)
|
||||||
]
|
return list
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,3 @@ func end_dodge() -> void:
|
||||||
transitioned.emit(self, play_char.walk_or_run)
|
transitioned.emit(self, play_char.walk_or_run)
|
||||||
else:
|
else:
|
||||||
transitioned.emit(self, "IdleState")
|
transitioned.emit(self, "IdleState")
|
||||||
|
|
||||||
func get_hints() -> Variant:
|
|
||||||
return null
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,3 @@ func move(delta : float) -> void:
|
||||||
#apply smooth stop
|
#apply smooth stop
|
||||||
play_char.velocity.x = lerp(play_char.velocity.x, 0.0, play_char.move_deccel * delta)
|
play_char.velocity.x = lerp(play_char.velocity.x, 0.0, play_char.move_deccel * delta)
|
||||||
play_char.velocity.z = lerp(play_char.velocity.z, 0.0, play_char.move_deccel * delta)
|
play_char.velocity.z = lerp(play_char.velocity.z, 0.0, play_char.move_deccel * delta)
|
||||||
|
|
||||||
func get_hints() -> Array:
|
|
||||||
return [{"action": &"player_jump", "text": "Sauter"}]
|
|
||||||
|
|
|
||||||
|
|
@ -110,5 +110,3 @@ func jump() -> void:
|
||||||
play_char.squash_and_strech(1.12, 0.1)
|
play_char.squash_and_strech(1.12, 0.1)
|
||||||
#play_char.particles_manager.display_particles(play_char.jump_particles, play_char)
|
#play_char.particles_manager.display_particles(play_char.jump_particles, play_char)
|
||||||
|
|
||||||
func get_hints() -> Variant:
|
|
||||||
return null
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,3 @@ func move(delta : float) -> void:
|
||||||
else:
|
else:
|
||||||
if !play_char.continious_run: play_char.walk_or_run = "WalkState"
|
if !play_char.continious_run: play_char.walk_or_run = "WalkState"
|
||||||
transitioned.emit(self, "IdleState")
|
transitioned.emit(self, "IdleState")
|
||||||
|
|
||||||
func get_hints() -> Variant:
|
|
||||||
return null
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ extends Node
|
||||||
class_name State
|
class_name State
|
||||||
|
|
||||||
signal transitioned #it's normal if this signal isn't used in this script, because it's purpose is to be used in the scripts that extends from the State class
|
signal transitioned #it's normal if this signal isn't used in this script, because it's purpose is to be used in the scripts that extends from the State class
|
||||||
|
signal hints_changed #à émettre quand get_hints() change pendant que l'état est actif
|
||||||
|
|
||||||
|
@export var hints : Array[StringName] = [] #hints simples, réglables dans l'inspecteur
|
||||||
|
|
||||||
func enter(_char_reference : CharacterBody3D) -> void:
|
func enter(_char_reference : CharacterBody3D) -> void:
|
||||||
#enter state
|
#enter state
|
||||||
|
|
@ -20,5 +23,5 @@ func physics_update(_delta : float) -> void:
|
||||||
#physics_process update
|
#physics_process update
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func get_hints() -> Variant:
|
func get_hints() -> Array:
|
||||||
return []
|
return hints #à surcharger seulement si les hints dépendent d'une condition
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ func _ready() -> void:
|
||||||
if child is State:
|
if child is State:
|
||||||
states[child.name.to_lower()] = child
|
states[child.name.to_lower()] = child
|
||||||
child.transitioned.connect(on_state_child_transition)
|
child.transitioned.connect(on_state_child_transition)
|
||||||
|
child.hints_changed.connect(_on_hints_changed.bind(child))
|
||||||
|
|
||||||
#if initial state, transition to it
|
#if initial state, transition to it
|
||||||
if initial_state:
|
if initial_state:
|
||||||
|
|
@ -27,8 +28,7 @@ func _ready() -> void:
|
||||||
initial_state.enter(char_ref)
|
initial_state.enter(char_ref)
|
||||||
curr_state = initial_state
|
curr_state = initial_state
|
||||||
curr_state_name = curr_state.state_name
|
curr_state_name = curr_state.state_name
|
||||||
var hints = curr_state.get_hints()
|
publish_hints()
|
||||||
if hints != null: Hints.set_state_hints(hints)
|
|
||||||
|
|
||||||
func _process(delta : float) -> void:
|
func _process(delta : float) -> void:
|
||||||
if curr_state: curr_state.update(delta)
|
if curr_state: curr_state.update(delta)
|
||||||
|
|
@ -75,9 +75,17 @@ func on_state_child_transition(state : State, new_state_name : String) -> void:
|
||||||
|
|
||||||
curr_state = new_state
|
curr_state = new_state
|
||||||
curr_state_name = curr_state.state_name
|
curr_state_name = curr_state.state_name
|
||||||
var hints = curr_state.get_hints()
|
publish_hints()
|
||||||
if hints != null: Hints.set_state_hints(hints)
|
|
||||||
|
|
||||||
func set_state_blocked(state_name : String, blocked : bool) -> void:
|
func set_state_blocked(state_name : String, blocked : bool) -> void:
|
||||||
if blocked: blocked_states[state_name.to_lower()] = true
|
if blocked: blocked_states[state_name.to_lower()] = true
|
||||||
else: blocked_states.erase(state_name.to_lower())
|
else: blocked_states.erase(state_name.to_lower())
|
||||||
|
|
||||||
|
func _on_hints_changed(state : State) -> void:
|
||||||
|
if state == curr_state: publish_hints()
|
||||||
|
|
||||||
|
func publish_hints() -> void:
|
||||||
|
if !curr_state: return
|
||||||
|
var actions = curr_state.get_hints()
|
||||||
|
if actions != null: Hints.set_state_hints(actions) #null = on garde les hints précédents (si tu as gardé cette option pour Dodge)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,6 @@ func _release_aim() -> void:
|
||||||
play_char.cam_holder.cam_aimed = false
|
play_char.cam_holder.cam_aimed = false
|
||||||
|
|
||||||
func get_hints() -> Array:
|
func get_hints() -> Array:
|
||||||
return [
|
var list : Array[StringName] = []
|
||||||
{"action": cancel_action, "text": "Annuler le lancer"},
|
if !_thrown: list.append(cancel_action) #plus d'annulation possible une fois la balle partie
|
||||||
]
|
return list
|
||||||
|
|
|
||||||
|
|
@ -71,5 +71,3 @@ func move(delta : float) -> void:
|
||||||
else:
|
else:
|
||||||
transitioned.emit(self, "IdleState")
|
transitioned.emit(self, "IdleState")
|
||||||
|
|
||||||
func get_hints() -> Variant:
|
|
||||||
return null
|
|
||||||
|
|
|
||||||
|
|
@ -2,32 +2,44 @@ extends Node
|
||||||
|
|
||||||
signal changed
|
signal changed
|
||||||
|
|
||||||
var _state_hints : Array = [] # [{action, text}]
|
#catalogue unique : action -> libellé affiché
|
||||||
var _context_hints : Dictionary = {} # clé (objet source) -> {action, text, priority}
|
const LABELS : Dictionary = {
|
||||||
|
&"player_jump": "Sauter",
|
||||||
|
&"player_dismount": "Descendre",
|
||||||
|
&"player_aim_switch_target": "Changer de cible",
|
||||||
|
&"player_aim_unlock": "Libérer la cible",
|
||||||
|
&"player_throw_cancel": "Annuler le lancer",
|
||||||
|
}
|
||||||
|
|
||||||
|
var _state_actions : Array = [] # [action, ...]
|
||||||
|
var _context_hints : Dictionary = {} # clé (objet ou StringName) -> {action, text, priority}
|
||||||
|
|
||||||
|
func label_for(action : StringName) -> String:
|
||||||
|
return LABELS.get(action, String(action)) #sans entrée : le nom de l'action, bien visible
|
||||||
|
|
||||||
#---------- hints d'état (appelés par la StateMachine) ----------
|
#---------- hints d'état (appelés par la StateMachine) ----------
|
||||||
|
|
||||||
func set_state_hints(list : Array) -> void:
|
func set_state_hints(actions : Array) -> void:
|
||||||
_state_hints = list
|
_state_actions = actions
|
||||||
changed.emit()
|
changed.emit()
|
||||||
|
|
||||||
#---------- hints de contexte (appelés par monture, PNJ, etc.) ----------
|
#---------- hints de contexte (monture, PNJ, etc.) ----------
|
||||||
|
#text vide : le libellé vient du catalogue. À renseigner quand le sens dépend du contexte (Grimper / Parler sur la même action)
|
||||||
|
|
||||||
func set_context(source : Object, action : StringName, text : String, priority : int = 0) -> void:
|
func set_context(source : Variant, action : StringName, text : String = "", priority : int = 0) -> void:
|
||||||
var h : Dictionary = {"action": action, "text": text, "priority": priority}
|
var h : Dictionary = {"action": action, "text": text if text != "" else label_for(action), "priority": priority}
|
||||||
if _context_hints.get(source) == h: return
|
if _context_hints.get(source) == h: return
|
||||||
_context_hints[source] = h
|
_context_hints[source] = h
|
||||||
changed.emit()
|
changed.emit()
|
||||||
|
|
||||||
func clear_context(source : Object) -> void:
|
func clear_context(source : Variant) -> void:
|
||||||
if _context_hints.erase(source): changed.emit()
|
if _context_hints.erase(source): changed.emit()
|
||||||
|
|
||||||
#---------- lecture (par le HUD) ----------
|
#---------- lecture (par le HUD) ----------
|
||||||
|
|
||||||
func get_visible() -> Array:
|
func get_visible() -> Array:
|
||||||
#nettoie les sources détruites sans avoir appelé clear_context
|
|
||||||
for key in _context_hints.keys():
|
for key in _context_hints.keys():
|
||||||
if !is_instance_valid(key): _context_hints.erase(key)
|
if typeof(key) == TYPE_OBJECT and !is_instance_valid(key): _context_hints.erase(key)
|
||||||
|
|
||||||
var ctx : Array = _context_hints.values()
|
var ctx : Array = _context_hints.values()
|
||||||
ctx.sort_custom(func(a, b): return a.priority > b.priority)
|
ctx.sort_custom(func(a, b): return a.priority > b.priority)
|
||||||
|
|
@ -35,8 +47,12 @@ func get_visible() -> Array:
|
||||||
#le contexte passe avant l'état ; une même action n'apparaît qu'une fois
|
#le contexte passe avant l'état ; une même action n'apparaît qu'une fois
|
||||||
var result : Array = []
|
var result : Array = []
|
||||||
var used : Dictionary = {}
|
var used : Dictionary = {}
|
||||||
for h in ctx + _state_hints:
|
for h in ctx:
|
||||||
if used.has(h.action): continue
|
if used.has(h.action): continue
|
||||||
used[h.action] = true
|
used[h.action] = true
|
||||||
result.append(h)
|
result.append(h)
|
||||||
|
for action in _state_actions:
|
||||||
|
if used.has(action): continue
|
||||||
|
used[action] = true
|
||||||
|
result.append({"action": action, "text": label_for(action)})
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue