mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-15 13:00:07 +01:00
124 lines
2.5 KiB
GDScript
124 lines
2.5 KiB
GDScript
extends Area2D
|
|
|
|
signal attack_finished
|
|
|
|
enum States {
|
|
IDLE,
|
|
ATTACK,
|
|
}
|
|
|
|
enum AttackInputStates {
|
|
IDLE,
|
|
LISTENING,
|
|
REGISTERED,
|
|
}
|
|
|
|
var state: States = States.IDLE
|
|
var attack_input_state := AttackInputStates.IDLE
|
|
var ready_for_next_attack: bool = false
|
|
const MAX_COMBO_COUNT = 3
|
|
var combo_count := 0
|
|
|
|
var attack_current := {}
|
|
var combo := [{
|
|
"damage": 1,
|
|
"animation": "attack_fast",
|
|
"effect": null,
|
|
},
|
|
{
|
|
"damage": 1,
|
|
"animation": "attack_fast",
|
|
"effect": null,
|
|
},
|
|
{
|
|
"damage": 3,
|
|
"animation": "attack_medium",
|
|
"effect": null,
|
|
}
|
|
]
|
|
|
|
var hit_objects := []
|
|
|
|
|
|
func _ready() -> void:
|
|
$AnimationPlayer.animation_finished.connect(_on_animation_finished)
|
|
body_entered.connect(_on_body_entered)
|
|
_change_state(States.IDLE)
|
|
|
|
|
|
func _change_state(new_state: States) -> void:
|
|
match state:
|
|
States.ATTACK:
|
|
hit_objects = []
|
|
attack_input_state = AttackInputStates.LISTENING
|
|
ready_for_next_attack = false
|
|
|
|
match new_state:
|
|
States.IDLE:
|
|
combo_count = 0
|
|
$AnimationPlayer.stop()
|
|
visible = false
|
|
monitoring = false
|
|
States.ATTACK:
|
|
attack_current = combo[combo_count -1]
|
|
$AnimationPlayer.play(attack_current["animation"])
|
|
visible = true
|
|
monitoring = true
|
|
|
|
state = new_state
|
|
|
|
|
|
func _unhandled_input(input_event: InputEvent) -> void:
|
|
if not state == States.ATTACK:
|
|
return
|
|
if attack_input_state != AttackInputStates.LISTENING:
|
|
return
|
|
if input_event.is_action_pressed(&"attack"):
|
|
attack_input_state = AttackInputStates.REGISTERED
|
|
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack:
|
|
attack()
|
|
|
|
|
|
func attack() -> void:
|
|
combo_count += 1
|
|
_change_state(States.ATTACK)
|
|
|
|
|
|
# Use with AnimationPlayer func track.
|
|
func set_attack_input_listening() -> void:
|
|
attack_input_state = AttackInputStates.LISTENING
|
|
|
|
|
|
# Use with AnimationPlayer func track.
|
|
func set_ready_for_next_attack() -> void:
|
|
ready_for_next_attack = true
|
|
|
|
|
|
func _on_body_entered(body: Node2D) -> void:
|
|
if not body.has_node(^"Health"):
|
|
return
|
|
if body.get_rid().get_id() in hit_objects:
|
|
return
|
|
|
|
hit_objects.append(body.get_rid().get_id())
|
|
body.take_damage(self, attack_current["damage"], attack_current["effect"])
|
|
|
|
|
|
func _on_animation_finished(_name: String) -> void:
|
|
if attack_current.is_empty():
|
|
return
|
|
|
|
if attack_input_state == AttackInputStates.REGISTERED and combo_count < MAX_COMBO_COUNT:
|
|
attack()
|
|
else:
|
|
_change_state(States.IDLE)
|
|
attack_finished.emit()
|
|
|
|
|
|
func _on_StateMachine_state_changed(current_state: Node) -> void:
|
|
if current_state.name == "Attack":
|
|
attack()
|