103 lines
3.1 KiB
GDScript
103 lines
3.1 KiB
GDScript
#*
|
|
#* player.gd
|
|
#* =============================================================================
|
|
#* Copyright (c) 2023-present Serhii Snitsaruk and the LimboAI contributors.
|
|
#*
|
|
#* Use of this source code is governed by an MIT-style
|
|
#* license that can be found in the LICENSE file or at
|
|
#* https://opensource.org/licenses/MIT.
|
|
#* =============================================================================
|
|
#*
|
|
extends "res://demo/agents/scripts/agent_base.gd"
|
|
|
|
## Player.
|
|
|
|
@export var dodge_cooldown: float = 0.4
|
|
|
|
@onready var hsm: LimboHSM = $LimboHSM
|
|
@onready var idle_state: LimboState = $LimboHSM/IdleState
|
|
@onready var move_state: LimboState = $LimboHSM/MoveState
|
|
@onready var attack_state: LimboState = $LimboHSM/AttackState
|
|
@onready var dodge_state: LimboState = $LimboHSM/DodgeState
|
|
|
|
var can_dodge: bool = true
|
|
var attack_pressed: bool = false
|
|
|
|
|
|
func _ready() -> void:
|
|
super._ready()
|
|
can_dodge = true
|
|
_init_input_events()
|
|
_init_state_machine()
|
|
death.connect(func(): remove_from_group(&"player"))
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event.is_echo():
|
|
return
|
|
if event.is_action_pressed("attack"):
|
|
attack_pressed = true
|
|
_process_attack_input()
|
|
if event.is_action_pressed("dodge"):
|
|
hsm.dispatch("dodge!")
|
|
|
|
|
|
func _process_attack_input() -> void:
|
|
if not attack_pressed or hsm.get_active_state() == attack_state:
|
|
return
|
|
hsm.dispatch("attack!")
|
|
attack_pressed = false
|
|
|
|
|
|
func _init_state_machine() -> void:
|
|
hsm.add_transition(idle_state, move_state, idle_state.EVENT_FINISHED)
|
|
hsm.add_transition(move_state, idle_state, move_state.EVENT_FINISHED)
|
|
hsm.add_transition(idle_state, attack_state, "attack!")
|
|
hsm.add_transition(move_state, attack_state, "attack!")
|
|
hsm.add_transition(attack_state, move_state, attack_state.EVENT_FINISHED)
|
|
hsm.add_transition(hsm.ANYSTATE, dodge_state, "dodge!")
|
|
hsm.add_transition(dodge_state, move_state, dodge_state.EVENT_FINISHED)
|
|
|
|
dodge_state.set_guard(_can_dodge)
|
|
attack_state.set_guard(attack_state.can_enter)
|
|
|
|
# Process attack input buffer when move_state is entered.
|
|
# This way we can buffer the attack button presses and chain the attacks.
|
|
move_state.call_on_enter(_process_attack_input)
|
|
|
|
hsm.initialize(self)
|
|
hsm.set_active(true)
|
|
|
|
|
|
func _init_input_events() -> void:
|
|
# Note: Ensures that input events are present even if project.godot wasn't imported.
|
|
_add_action(&"move_left", KEY_A)
|
|
_add_action(&"move_right", KEY_D)
|
|
_add_action(&"move_up", KEY_W)
|
|
_add_action(&"move_down", KEY_S)
|
|
_add_action(&"dodge", KEY_SPACE)
|
|
_add_action(&"attack", KEY_ENTER, KEY_F)
|
|
|
|
|
|
func _add_action(p_action: StringName, p_key: Key, p_alt: Key = KEY_NONE) -> void:
|
|
if not InputMap.has_action(p_action):
|
|
InputMap.add_action(p_action)
|
|
var event := InputEventKey.new()
|
|
event.keycode = p_key
|
|
InputMap.action_add_event(p_action, event)
|
|
if p_alt != KEY_NONE:
|
|
var alt := InputEventKey.new()
|
|
alt.keycode = p_alt
|
|
InputMap.action_add_event(p_action, alt)
|
|
|
|
|
|
func set_victorious() -> void:
|
|
idle_state.idle_animation = &"dance"
|
|
|
|
|
|
func _can_dodge() -> bool:
|
|
if can_dodge:
|
|
can_dodge = false
|
|
get_tree().create_timer(dodge_cooldown).timeout.connect(func(): can_dodge = true)
|
|
return true
|
|
return false
|