@tool extends Node2D @export var launch_power: float @export var idle_radius: float @export var draw_back_distance: float @export var smash_distance: float @export_group("Timing", "time_") @export var time_draw_back: float @export var time_smash: float @export var time_recover: float @export_group("Internal References") @export var smash_effect: PackedScene @export var head: Node2D var _player: Player = null var _tween: Tween = null var _go_again: bool = false func _start_attack() -> void: # do nothing if already doing animation or player gone if not _go_again or (_tween and _tween.is_running()): return var effect = smash_effect.instantiate() as Node2D effect.position = to_local(_player.global_position) effect.rotation = randf() * TAU _tween = create_tween().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) # launch player _tween.tween_callback(_player.launch.bind( global_position.direction_to(_player.global_position) * launch_power )) # spawn smash effect _tween.tween_callback(add_child.bind(effect)) # draw back away from player _tween.tween_property(head.material, ^"shader_parameter/radius", 0.0, 0.1) _tween.parallel().tween_method(_move_facing_player, 0.0, -draw_back_distance, time_draw_back)\ .set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) # smash towards player _tween.tween_method(_move_facing_player, -draw_back_distance, smash_distance, time_smash)\ .set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC) # return to center _tween.tween_method(_move_facing_player, smash_distance, 0.0, time_recover)\ .set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BOUNCE) _tween.tween_property(head.material, ^"shader_parameter/radius", idle_radius, 0.1) _tween.tween_callback(_start_attack.call_deferred) ## move head this disatance from (0,0) towards (or away if negative) from player func _move_facing_player(distance: float) -> void: if not _player: return var dir = global_position.direction_to(_player.global_position) head.position = dir * distance func _on_player_detector_body_entered(body: Node2D) -> void: if body is Player: _player = body _go_again = true _start_attack() func _on_player_detector_body_exited(body: Node2D) -> void: if body is Player: _go_again = false