diff --git a/Main.tscn b/Main.tscn index 70f0760..267187c 100644 --- a/Main.tscn +++ b/Main.tscn @@ -1,14 +1,14 @@ [gd_scene load_steps=3 format=2] -[ext_resource path="res://src/actors/players/playerD/Player.tscn" type="PackedScene" id=1] +[ext_resource path="res://lib/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=1] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 208, 20 ) [node name="Main" type="Node2D"] -[node name="Player" parent="." instance=ExtResource( 1 )] -position = Vector2( 147, 101 ) +[node name="ActorTemplate" parent="." instance=ExtResource( 1 )] +position = Vector2( 152, 64 ) [node name="ColorRect" type="ColorRect" parent="."] margin_top = 160.0 diff --git a/assets/actors/players/playerE/Player Idle 48x48.png b/assets/actors/players/playerE/Player Idle 48x48.png new file mode 100644 index 0000000..4f33161 Binary files /dev/null and b/assets/actors/players/playerE/Player Idle 48x48.png differ diff --git a/assets/actors/players/playerE/Player Idle 48x48.png.import b/assets/actors/players/playerE/Player Idle 48x48.png.import new file mode 100644 index 0000000..6d285fa --- /dev/null +++ b/assets/actors/players/playerE/Player Idle 48x48.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/Player Idle 48x48.png-eec2a2bcc99a731fac49b2105239676a.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/actors/players/playerE/Player Idle 48x48.png" +dest_files=[ "res://.import/Player Idle 48x48.png-eec2a2bcc99a731fac49b2105239676a.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/lib/classes/actor.gd b/lib/classes/actor.gd index 5e14cc1..6cbad85 100644 --- a/lib/classes/actor.gd +++ b/lib/classes/actor.gd @@ -75,10 +75,11 @@ func play_sound_frame(animation: String, frame: int ): func attack(): #print(self.name, ": It's not inheritence, it's funcrefs") - if movement_state_machine.current_state.name != 'attack': - if($movement_state_machine/attack): - movement_state_machine.change_state($movement_state_machine/attack) - if ($Hitbox_Component/CollisionShape2D): - #print(self.name, ": Found a hitbox") - var hit_box = $Hitbox_Component - hit_box.set_hitbox(true) +# if movement_state_machine.current_state.name != 'attack': +# if($movement_state_machine/attack): +# movement_state_machine.change_state($movement_state_machine/attack) +# if ($Hitbox_Component/CollisionShape2D): +# #print(self.name, ": Found a hitbox") +# var hit_box = $Hitbox_Component +# hit_box.set_hitbox(true) + pass diff --git a/lib/classes/state.gd b/lib/classes/state.gd index 640d7c1..994aede 100644 --- a/lib/classes/state.gd +++ b/lib/classes/state.gd @@ -1,5 +1,5 @@ class_name State -extends Node +extends Resource export var debug_state: bool = false export var timeout_seconds: float = 0.0 @@ -8,27 +8,46 @@ signal state_entered() signal state_exited() # Declare member variables here. Examples: -#var modifier_stack_ref: Array # Well this didn't work + var state_timeout: Timer var state_ready: bool = true -# Called when the node enters the scene tree for the first time. -func _ready(): - pass # Replace with function body. +var name: String +# Called when the node enters the scene tree for the first time. +# Resources don't have _ready callbacks I think +# You'd have to use the constructor callback _init +#func _ready(): +# pass # Replace with function body. + +#func _init(): +# print ("Am I really a parent's constructor?") + +func _init(): + ##TODO: this bit me in the butt. Should add a safety or something. + # Only add timout node if timer value was specified. + if(timeout_seconds > 0.0): + state_timeout = Timer.new() + state_timeout.wait_time = timeout_seconds + state_timeout.one_shot = true + state_timeout.autostart = false + #add_child(state_timeout) + #get_tree().get_root().add_child(state_timeout) + #TODO: Need to figure out how to add this to tree + print ("State init called for no reason?") + #modifier = StateModifier.new() func enter() -> void: pass - func exit() -> void: pass -func process_input(_event: InputEvent) -> State: - return null +func process_input(_event: InputEvent) -> String: + return '' -func process_frame(_delta: float) -> State: - return null +func process_frame(_delta: float) -> String: + return '' -func process_physics(_delta: float) -> State: - return null +func process_physics(_delta: float) -> String: + return '' diff --git a/lib/classes/state_animated_actor.gd b/lib/classes/state_animated_actor.gd index 4305a91..cd5355a 100644 --- a/lib/classes/state_animated_actor.gd +++ b/lib/classes/state_animated_actor.gd @@ -65,21 +65,6 @@ var previous_speed_multiplier: float var modifier: StateModifier -#var animation_sequence_timer: Timer - - - -func _ready(): - ##TODO: this bit me in the butt. Should add a safety or something. - # Only add timout node if timer value was specified. - if(timeout_seconds > 0.0): - state_timeout = Timer.new() - state_timeout.wait_time = timeout_seconds - state_timeout.one_shot = true - state_timeout.autostart = false - add_child(state_timeout) - - #modifier = StateModifier.new() # If called, this will attempt to make the most appropriate animation change # would likely be triggered from an animation sequence finishing or a @@ -192,8 +177,8 @@ func transfer_modifiers(exiting_state_modifier : StateModifier): else: print("Insert modifier merge function here...") -func process_input(_event: InputEvent) -> State: - return null +func process_input(_event: InputEvent) -> String: + return '' func process_animations(): @@ -249,12 +234,12 @@ func process_animations(): else: frame_signal_emitted = false -func process_frame(_delta: float) -> State: - return null +func process_frame(_delta: float) -> String: + return '' -func process_physics(_delta: float) -> State: +func process_physics(_delta: float) -> String: move_actor_as_desired(_delta) - return null + return '' #func _on_AnimatedSprite_animation_finished(): # if animations.frames.get_animation_loop(animations.animation) == false: diff --git a/lib/classes/state_machine.gd b/lib/classes/state_machine.gd index 3e4a6c2..48c7d04 100644 --- a/lib/classes/state_machine.gd +++ b/lib/classes/state_machine.gd @@ -1,24 +1,34 @@ class_name StateMachine extends Node -export (NodePath) var starting_state +#export (NodePath) var starting_state export var debug_state_machine: bool = false +# I guess I would declare a number of states here +#export (Reference) var states # Doesn't work +#var starting_state: State + var current_state: State #var state_modifiers: Array +export(Dictionary) var states :Dictionary # Initialize the state machine by giving each child state a reference to the # parent object it belongs to and enter the default starting_state. func init() -> void: - for child in get_children(): - if child is State: - if debug_state_machine: - print("Initializing State Node: ", child.name) -# child.modifier_stack_ref = state_modifiers - if debug_state_machine: - child.debug_state = true +# for child in get_children(): +# if child is State: +# if debug_state_machine: +# print("Initializing State Node: ", child.name) +## child.modifier_stack_ref = state_modifiers +# if debug_state_machine: +# child.debug_state = true + + for s in states.keys(): + var this_state = states.s + if this_state is State: + if debug_state_machine: + print("Initializing State Node: ", s) + this_state.debug_state = true - # Initialize to the default state - change_state(get_node(starting_state)) # Change to the new state by first calling any exit logic on the current state. func change_state(new_state: State) -> void: @@ -31,13 +41,19 @@ func change_state(new_state: State) -> void: # print("Active Modifiers:") # for mods in state_modifiers: # print(mods.name) + +func change_to_known_state(new_state_name: String) -> void: + if new_state_name.empty() == false: + if states.has(new_state_name): + change_state(states[new_state_name]) + else: + push_warning("Attempt to switch state to unknown: " + new_state_name + get_parent().name) + change_state(states["default"]) # Pass through functions for the Player to call, # handling state changes as needed. func process_physics(delta: float) -> void: - var new_state = current_state.process_physics(delta) - if new_state: - change_state(new_state) + change_to_known_state( current_state.process_physics(delta) ) func process_input(event: InputEvent) -> void: var new_state = current_state.process_input(event) diff --git a/lib/classes/state_machine_animated_actor.gd b/lib/classes/state_machine_animated_actor.gd index cc7cf30..3b47d50 100644 --- a/lib/classes/state_machine_animated_actor.gd +++ b/lib/classes/state_machine_animated_actor.gd @@ -1,7 +1,5 @@ class_name StateMachineAnimatedActor extends StateMachine -#var physics_modifier : StateModifier - func change_state(new_state: State) -> void: if new_state.state_ready == false: # Don't transition to unready state @@ -39,19 +37,43 @@ func set_previous_animation( old_state: StateAnimatedActor, new_state: StateAnim # parent object it belongs to and enter the default starting_state. func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, move_component: MovementComponent) -> void: animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished") - for child in get_children(): +# for child in get_children(): +# if child is StateAnimatedActor: +# if debug_state_machine: +# print("Initializing State Node for ", parent.name, ": ", child.name) +# child.parent = parent +# child.animations = animations +# child.move_component = move_component +## child.modifier_stack_ref = state_modifiers +# if debug_state_machine: +# child.debug_state = true + #states["default"] = StateAnimatedActor.new() + for s in states.keys(): + var child = states[s] if child is StateAnimatedActor: if debug_state_machine: - print("Initializing State Node for ", parent.name, ": ", child.name) + print("Initializing State Node for ", parent.name, ": ", s) + child.debug_state = true child.parent = parent child.animations = animations child.move_component = move_component -# child.modifier_stack_ref = state_modifiers - if debug_state_machine: - child.debug_state = true + child.name = s + + if states.has("default"): + print("I still haz default state") + change_state(states.default) +# current_state = states.default +# if current_state is StateAnimatedActor: +# current_state.animations = animations +# current_state.parent = parent +# current_state.move_component = move_component +# current_state.enter() +# #current_state.set_script("res://lib/templates/Actor/states/idle.gd") # Initialize to the default state - change_state(get_node(starting_state)) + #change_state(get_node(starting_state)) + + #change_state(states.default) func process_frame(delta: float) -> void: @@ -89,10 +111,8 @@ func process_frame(delta: float) -> void: # state_modifiers.pop_at(i) if current_state is StateAnimatedActor: current_state.process_animations() - var new_state = current_state.process_frame(delta) - if new_state: - change_state(new_state) - + change_to_known_state( current_state.process_frame(delta) ) + func _on_AnimatedSprite_animation_finished(): # if debug_state_machine: diff --git a/lib/templates/Actor/ActorTemplate.tscn b/lib/templates/Actor/ActorTemplate.tscn index c9d86f8..b06774b 100644 --- a/lib/templates/Actor/ActorTemplate.tscn +++ b/lib/templates/Actor/ActorTemplate.tscn @@ -1,44 +1,44 @@ -[gd_scene load_steps=17 format=2] +[gd_scene load_steps=15 format=2] [ext_resource path="res://lib/components/Hurtbox_Component.tscn" type="PackedScene" id=1] [ext_resource path="res://lib/classes/state_machine_animated_actor.gd" type="Script" id=2] -[ext_resource path="res://lib/templates/Actor/states/fall.gd" type="Script" id=3] -[ext_resource path="res://lib/templates/Actor/states/idle.gd" type="Script" id=4] +[ext_resource path="res://lib/templates/Actor/states/idle.tres" type="Resource" id=4] [ext_resource path="res://src/classes/movement_component.gd" type="Script" id=5] -[ext_resource path="res://lib/templates/Actor/resources/Smiley.png" type="Texture" id=6] -[ext_resource path="res://lib/templates/Actor/states/move.gd" type="Script" id=7] [ext_resource path="res://lib/classes/actor.gd" type="Script" id=8] -[sub_resource type="AtlasTexture" id=76] -atlas = ExtResource( 6 ) -region = Rect2( 0, 0, 32, 32 ) +[sub_resource type="StreamTexture" id=83] +load_path = "res://.import/Player Idle 48x48.png-eec2a2bcc99a731fac49b2105239676a.stex" -[sub_resource type="AtlasTexture" id=77] -atlas = ExtResource( 6 ) -region = Rect2( 32, 0, 32, 32 ) +[sub_resource type="AtlasTexture" id=84] +atlas = SubResource( 83 ) +region = Rect2( 0, 0, 48, 48 ) -[sub_resource type="AtlasTexture" id=78] -atlas = ExtResource( 6 ) -region = Rect2( 64, 0, 32, 32 ) +[sub_resource type="AtlasTexture" id=85] +atlas = SubResource( 83 ) +region = Rect2( 48, 0, 48, 48 ) -[sub_resource type="AtlasTexture" id=79] -atlas = ExtResource( 6 ) -region = Rect2( 0, 32, 32, 32 ) +[sub_resource type="AtlasTexture" id=86] +atlas = SubResource( 83 ) +region = Rect2( 96, 0, 48, 48 ) -[sub_resource type="AtlasTexture" id=80] -atlas = ExtResource( 6 ) -region = Rect2( 32, 32, 32, 32 ) +[sub_resource type="AtlasTexture" id=87] +atlas = SubResource( 83 ) +region = Rect2( 0, 48, 48, 48 ) -[sub_resource type="AtlasTexture" id=81] -atlas = ExtResource( 6 ) -region = Rect2( 64, 32, 32, 32 ) +[sub_resource type="AtlasTexture" id=88] +atlas = SubResource( 83 ) +region = Rect2( 48, 48, 48, 48 ) -[sub_resource type="SpriteFrames" id=75] +[sub_resource type="AtlasTexture" id=89] +atlas = SubResource( 83 ) +region = Rect2( 96, 48, 48, 48 ) + +[sub_resource type="SpriteFrames" id=90] animations = [ { -"frames": [ SubResource( 76 ), SubResource( 77 ), SubResource( 78 ), SubResource( 79 ), SubResource( 80 ), SubResource( 81 ) ], +"frames": [ SubResource( 84 ), SubResource( 85 ), SubResource( 86 ), SubResource( 87 ), SubResource( 87 ), SubResource( 88 ), SubResource( 84 ), SubResource( 89 ), SubResource( 89 ), SubResource( 89 ) ], "loop": true, "name": "default", -"speed": 5.0 +"speed": 11.0 } ] [sub_resource type="CircleShape2D" id=82] @@ -48,20 +48,18 @@ collision_layer = 2 script = ExtResource( 8 ) [node name="AnimatedSprite" type="AnimatedSprite" parent="."] -frames = SubResource( 75 ) -frame = 3 +frames = SubResource( 90 ) playing = true -flip_h = true __meta__ = { "_aseprite_wizard_config_": { "layer": "", -"o_ex_p": "", -"o_folder": "res://assets", +"o_ex_p": "BG", +"o_folder": "res://assets/actors/players/playerE", "o_name": "", "only_visible": true, -"op_exp": false, +"op_exp": true, "slice": "", -"source": "E:/Godot/Art/MegaMan.aseprite" +"source": "/home/relay01/Assets/Library/Asset Packs 1-5/Asset Packs 1-4 (final)/Asset Pack-V1/Player Idle/Player Idle 48x48.aseprite" } } @@ -70,24 +68,10 @@ script = ExtResource( 5 ) [node name="movement_state_machine" type="Node" parent="."] script = ExtResource( 2 ) -starting_state = NodePath("idle") - -[node name="idle" type="Node" parent="movement_state_machine"] -script = ExtResource( 4 ) -animation_sequence = [ "default" ] -fall_node = NodePath("../fall") -move_node = NodePath("../move") - -[node name="fall" type="Node" parent="movement_state_machine"] -script = ExtResource( 3 ) -animation_sequence = [ "default" ] -idle_node = NodePath("../idle") - -[node name="move" type="Node" parent="movement_state_machine"] -script = ExtResource( 7 ) -animation_sequence = [ "default" ] -fall_node = NodePath("../fall") -idle_node = NodePath("../idle") +debug_state_machine = true +states = { +"default": ExtResource( 4 ) +} [node name="Hurtbox_Component" parent="." instance=ExtResource( 1 )] diff --git a/lib/templates/Actor/states/idle.gd b/lib/templates/Actor/states/idle.gd index 250c59c..ae16522 100644 --- a/lib/templates/Actor/states/idle.gd +++ b/lib/templates/Actor/states/idle.gd @@ -1,20 +1,18 @@ extends StateAnimatedActor -export (NodePath) var fall_node -export (NodePath) var move_node - -onready var fall_state: State = get_node(fall_node) -onready var move_state: State = get_node(move_node) +# Do states need to have references to the states they want to transition +# to? I suppose if on exit/entrance we needed to do something func enter() -> void: - .enter() + #.enter() # parent.set_hurtbox(true) move_component.velocity.x = 0 - if debug_state: - print(owner.name, " Move Component: ", move_component.desired_movement_vector.x) - -func process_physics(delta: float) -> State: + print ("this doesn't work does it? ") +# if debug_state: +# print(owner.name, " Move Component: ", move_component.desired_movement_vector.x) +func process_physics(delta: float) -> String: + return '' # parent.velocity.y += gravity * delta # #parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1)) # parent.velocity.x = move_component.desired_movement_vector.x * move_speed @@ -23,8 +21,8 @@ func process_physics(delta: float) -> State: move_actor_as_desired(delta) if move_component.velocity.x != 0.0: - return move_state + return 'move' if !parent.is_on_floor(): - return fall_state - return null + return 'fall' + return '' diff --git a/lib/templates/Actor/states/idle.tres b/lib/templates/Actor/states/idle.tres new file mode 100644 index 0000000..0014cb2 --- /dev/null +++ b/lib/templates/Actor/states/idle.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=2] + +[ext_resource path="res://lib/templates/Actor/states/idle.gd" type="Script" id=1] + +[resource] +resource_local_to_scene = true +script = ExtResource( 1 ) +debug_state = false +timeout_seconds = 0.0 +move_speed = 60.0 +move_acceleration = 20.0 +move_speed_modifier = 0.0 +move_modifier_move_acceleration = 0.0 +jerk_factor = 0.0 +animation_sequence = [ "idle" ] +emitter_frame_subscriptions = { +} diff --git a/project.godot b/project.godot index a8e35b9..abea56d 100644 --- a/project.godot +++ b/project.godot @@ -54,7 +54,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://src/classes/movement_component.gd" }, { -"base": "Node", +"base": "Resource", "class": "State", "language": "GDScript", "path": "res://lib/classes/state.gd" diff --git a/src/actors/players/playerD/Player.tscn b/src/actors/players/playerD/Player.tscn index d7f3eb1..277d3b0 100644 --- a/src/actors/players/playerD/Player.tscn +++ b/src/actors/players/playerD/Player.tscn @@ -1,21 +1,11 @@ -[gd_scene load_steps=126 format=2] +[gd_scene load_steps=116 format=2] [ext_resource path="res://lib/templates/Actor/ActorTemplate.tscn" type="PackedScene" id=1] [ext_resource path="res://src/actors/players/playerD/movement_component.gd" type="Script" id=2] [ext_resource path="res://src/actors/players/playerD/Player.gd" type="Script" id=3] -[ext_resource path="res://src/actors/players/playerD/states/idle.gd" type="Script" id=4] -[ext_resource path="res://src/actors/players/playerD/states/move.gd" type="Script" id=5] -[ext_resource path="res://src/actors/players/playerD/states/fall.gd" type="Script" id=6] [ext_resource path="res://lib/components/Health_Component.tscn" type="PackedScene" id=7] -[ext_resource path="res://src/actors/players/playerD/states/jump.gd" type="Script" id=8] [ext_resource path="res://lib/components/Modifier_Receiver.tscn" type="PackedScene" id=9] -[ext_resource path="res://src/actors/players/playerD/states/attack.gd" type="Script" id=10] -[ext_resource path="res://src/actors/players/playerD/states/dash.gd" type="Script" id=11] -[ext_resource path="res://src/actors/players/playerD/states/hurt.gd" type="Script" id=12] -[ext_resource path="res://src/actors/players/playerD/states/roll.gd" type="Script" id=14] -[ext_resource path="res://src/actors/players/playerD/states/die.gd" type="Script" id=15] [ext_resource path="res://lib/templates/Interactable/Interactable_Receiver.gd" type="Script" id=16] -[ext_resource path="res://src/actors/players/playerD/states/climb.gd" type="Script" id=17] [sub_resource type="RectangleShape2D" id=197] extents = Vector2( 13, 18.5 ) @@ -557,7 +547,6 @@ shape = SubResource( 197 ) position = Vector2( -1, -51 ) frames = SubResource( 196 ) animation = "idle_shoot" -flip_h = false __meta__ = { "_aseprite_wizard_config_": { "layer": "", @@ -576,89 +565,6 @@ script = ExtResource( 2 ) player_number = 1 interactable_node = NodePath("../Interactable_Receiver") -[node name="idle" parent="movement_state_machine" index="0"] -script = ExtResource( 4 ) -debug_state = true -move_speed = 0.0 -animation_sequence = [ "idle" ] -jump_node = NodePath("../jump") -attack_node = NodePath("../attack") -dash_node = NodePath("../dash") -roll_node = NodePath("../roll") -climb_node = NodePath("../climb") - -[node name="fall" parent="movement_state_machine" index="1"] -script = ExtResource( 6 ) -move_speed = 90.0 -animation_sequence = [ "jump" ] -landing_node = NodePath("") - -[node name="move" parent="movement_state_machine" index="2"] -script = ExtResource( 5 ) -move_speed = 90.0 -animation_sequence = [ "step", "run" ] -jump_node = NodePath("../jump") -attack_node = NodePath("../attack") - -[node name="jump" type="Node" parent="movement_state_machine" index="3"] -script = ExtResource( 8 ) -move_speed = 90.0 -move_modifier_move_acceleration = -100.0 -animation_sequence = [ "jump" ] -idle_node = NodePath("../idle") -fall_node = NodePath("../fall") -attack_node = NodePath("../attack") -jump_force = 250.0 - -[node name="attack" type="Node" parent="movement_state_machine" index="4"] -script = ExtResource( 10 ) -timeout_seconds = 1.5 -move_speed = 90.0 -animation_sequence = [ "shoot" ] -jump_node = NodePath("../jump") -idle_node = NodePath("../idle") -fall_node = NodePath("../fall") -move_node = NodePath("../move") - -[node name="hurt" type="Node" parent="movement_state_machine" index="5"] -script = ExtResource( 12 ) -timeout_seconds = 2.0 -move_speed = -10.0 -animation_sequence = [ "hurt" ] -idle_node = NodePath("../idle") - -[node name="dash" type="Node" parent="movement_state_machine" index="6"] -script = ExtResource( 11 ) -move_speed = 90.0 -move_speed_modifier = 90.0 -move_modifier_move_acceleration = -100.0 -jerk_factor = -20.0 -animation_sequence = [ "dash" ] -fall_node = NodePath("../fall") -idle_node = NodePath("../idle") -attack_node = NodePath("../attack") -jump_node = NodePath("../jump") - -[node name="roll" type="Node" parent="movement_state_machine" index="7"] -script = ExtResource( 14 ) -move_speed = 150.0 -animation_sequence = [ "roll" ] -emitter_frame_subscriptions = { -2: "roll" -} -fall_node = NodePath("../fall") -idle_node = NodePath("../idle") - -[node name="die" type="Node" parent="movement_state_machine" index="8"] -script = ExtResource( 15 ) -animation_sequence = [ "die" ] - -[node name="climb" type="Node" parent="movement_state_machine" index="9"] -script = ExtResource( 17 ) -debug_state = true -animation_sequence = [ "climb_step", "climb", "climb_upstep" ] -idle_node = NodePath("../idle") - [node name="Hurtbox_Component" parent="." index="4"] collision_layer = 16 collision_mask = 128 @@ -688,8 +594,4 @@ collision_mask = 1024 collide_with_areas = true collide_with_bodies = false -[connection signal="do_attack" from="movement_state_machine/attack" to="." method="_on_attack_do_attack"] -[connection signal="frame_reached" from="movement_state_machine/roll" to="." method="_on_roll_frame_reached"] -[connection signal="state_exited" from="movement_state_machine/roll" to="." method="_on_roll_state_exited"] -[connection signal="state_entered" from="movement_state_machine/die" to="." method="_on_die_state_entered"] [connection signal="health_depleted" from="Health_Component" to="." method="_on_Health_Component_health_depleted"]