diff --git a/Babushka.sln.DotSettings b/Babushka.sln.DotSettings index ed91201..a4c6213 100644 --- a/Babushka.sln.DotSettings +++ b/Babushka.sln.DotSettings @@ -1,4 +1,5 @@  + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy> Godot Signal [Signal] public delegate void $SignalName$EventHandler($END$); diff --git a/Babushka.sln.DotSettings.user b/Babushka.sln.DotSettings.user index 146655c..d333d51 100644 --- a/Babushka.sln.DotSettings.user +++ b/Babushka.sln.DotSettings.user @@ -1,18 +1,39 @@  ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded + ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded - ForceIncluded \ No newline at end of file + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + <SessionState ContinuousTestingMode="0" IsActive="True" Name="Tests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <TestAncestor> + <TestId>NUnit3x::A6EF2269-9E64-40D4-BA0A-33CB234E2503::net9.0::BabushkaTest.Tests</TestId> + </TestAncestor> +</SessionState> diff --git a/prefabs/fight/fight_scene_switcher.tscn b/prefabs/fight/fight_scene_switcher.tscn new file mode 100644 index 0000000..8680ba4 --- /dev/null +++ b/prefabs/fight/fight_scene_switcher.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://bcld43daavmrn"] + +[ext_resource type="Script" uid="uid://cql8mt5jsmcdl" path="res://scripts/CSharp/Common/Fight/FightSceneSwitcher.cs" id="1_5dt1r"] + +[node name="FightSceneSwitcher" type="Node"] +script = ExtResource("1_5dt1r") +_fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn" +_fightHappeningScene = "res://scenes/Babushka_scene_fight_happening.tscn" diff --git a/prefabs/fight/fight_world_autoload.tscn b/prefabs/fight/fight_world_autoload.tscn new file mode 100644 index 0000000..1692884 --- /dev/null +++ b/prefabs/fight/fight_world_autoload.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://n5cj71bxxjkk"] + +[ext_resource type="Script" uid="uid://dqe1i2qmpttwf" path="res://scripts/CSharp/Common/Fight/FightWorld.cs" id="1_tnyce"] + +[node name="FightWorldAutoload" type="Node2D"] +script = ExtResource("1_tnyce") diff --git a/prefabs/fight/fighterVisuals/blob_fighter_visual.tscn b/prefabs/fight/fighterVisuals/blob_fighter_visual.tscn new file mode 100644 index 0000000..6f61899 --- /dev/null +++ b/prefabs/fight/fighterVisuals/blob_fighter_visual.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=4 format=3 uid="uid://0vm3jb1hnkkb"] + +[ext_resource type="PackedScene" uid="uid://7jsxokx67gpq" path="res://prefabs/fight/fighterVisuals/vesna_fighter_visual.tscn" id="1_80xdf"] +[ext_resource type="Texture2D" uid="uid://ccrnmx6bd842k" path="res://art/characters/farm fäulnis blobs.png" id="2_ba6tr"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_ane0o"] +atlas = ExtResource("2_ba6tr") +region = Rect2(1133.19, 93.65, 460.526, 347.391) + +[node name="BlobFighterVisual" instance=ExtResource("1_80xdf")] + +[node name="Sprite2D" parent="Visuals" index="0"] +position = Vector2(23, -96) +scale = Vector2(0.547474, 0.547474) +texture = SubResource("AtlasTexture_ane0o") + +[node name="Sprite2D" parent="TargetSelection/HoverIndicator" index="0"] +position = Vector2(1, -126) diff --git a/prefabs/fight/fighterVisuals/vesna_fighter_visual.tscn b/prefabs/fight/fighterVisuals/vesna_fighter_visual.tscn new file mode 100644 index 0000000..2927637 --- /dev/null +++ b/prefabs/fight/fighterVisuals/vesna_fighter_visual.tscn @@ -0,0 +1,72 @@ +[gd_scene load_steps=9 format=3 uid="uid://7jsxokx67gpq"] + +[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/FighterVisual.cs" id="1_hai27"] +[ext_resource type="Texture2D" uid="uid://f7htcxiwvuup" path="res://art/animation/vesna/Side/S01-Idle/0001.png" id="2_6l7g5"] +[ext_resource type="Script" uid="uid://boprnfciqgixf" path="res://scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs" id="3_wil2y"] +[ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="4_8ldlc"] +[ext_resource type="Script" uid="uid://b2dx06p6i7pu0" path="res://scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs" id="5_xv37w"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_wil2y"] +atlas = ExtResource("2_6l7g5") +region = Rect2(60.818, 51.0213, 660.226, 945.537) + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_6l7g5"] +size = Vector2(250, 401) + +[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_6l7g5"] +radius = 173.0 +height = 588.0 + +[node name="VesnaFighterVisual" type="Node2D" node_paths=PackedStringArray("_visualParent", "_targetSelectionParent", "healthBarVisual")] +script = ExtResource("1_hai27") +_visualParent = NodePath("Visuals") +_targetSelectionParent = NodePath("TargetSelection") +healthBarVisual = NodePath("HealthBar") + +[node name="Visuals" type="Node2D" parent="."] + +[node name="Sprite2D" type="Sprite2D" parent="Visuals"] +position = Vector2(-31, -199) +scale = Vector2(0.451719, 0.451719) +texture = SubResource("AtlasTexture_wil2y") + +[node name="ChacacterSizeIndicator" type="CollisionShape2D" parent="Visuals"] +editor_description = "This is a reference to the space, a normal sized humanoid character should occupy" +visible = false +position = Vector2(0, -200.5) +shape = SubResource("RectangleShape2D_6l7g5") + +[node name="TargetSelection" type="Node2D" parent="."] +process_mode = 4 +visible = false + +[node name="Click" type="Area2D" parent="TargetSelection"] +script = ExtResource("3_wil2y") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetSelection/Click"] +position = Vector2(-3, -195) +shape = SubResource("CapsuleShape2D_6l7g5") + +[node name="HoverIndicator" type="Node2D" parent="TargetSelection"] +visible = false + +[node name="Sprite2D" type="Sprite2D" parent="TargetSelection/HoverIndicator"] +position = Vector2(-3, -227) +scale = Vector2(1.65625, 1.65625) +texture = ExtResource("4_8ldlc") + +[node name="HealthBar" type="Node2D" parent="." node_paths=PackedStringArray("_tmpHealthLabel")] +script = ExtResource("5_xv37w") +_tmpHealthLabel = NodePath("tmpLabel") + +[node name="tmpLabel" type="Label" parent="HealthBar"] +offset_left = -110.0 +offset_top = -528.0 +offset_right = 111.0 +offset_bottom = -431.0 +theme_override_font_sizes/font_size = 71 +text = "xx / xx" + +[connection signal="TargetSelected" from="TargetSelection/Click" to="." method="ClickedTarget"] +[connection signal="mouse_entered" from="TargetSelection/Click" to="TargetSelection/HoverIndicator" method="show"] +[connection signal="mouse_exited" from="TargetSelection/Click" to="TargetSelection/HoverIndicator" method="hide"] diff --git a/prefabs/fight/fighters/vesna_fighter.tscn b/prefabs/fight/fighters/vesna_fighter.tscn deleted file mode 100644 index 7e9f745..0000000 --- a/prefabs/fight/fighters/vesna_fighter.tscn +++ /dev/null @@ -1,123 +0,0 @@ -[gd_scene load_steps=11 format=3 uid="uid://cpanatqdjjpa3"] - -[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/Fighter.cs" id="1_f3j2x"] -[ext_resource type="Texture2D" uid="uid://om2axn1vfa5o" path="res://art/animation/Vesna2D/Vesna Anims Sequences/S01-Idle/0001.png" id="2_2ud32"] -[ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_80knd"] -[ext_resource type="AudioStream" uid="uid://ch4c1wh4ghxyo" path="res://audio/sfx/Battle/Vesna/SFX_Battle_Vesna_Defense_08.wav" id="5_4r2vf"] -[ext_resource type="Texture2D" uid="uid://6h85o7fj7gmu" path="res://art/animation/Vesna3D/vesna-more-tools.png" id="5_l04qi"] -[ext_resource type="Texture2D" uid="uid://crak7ton4lab0" path="res://art/ui/UI/EmptyFightButton.png" id="5_rjjub"] -[ext_resource type="Texture2D" uid="uid://c3wht0nakaki1" path="res://art/ui/UI/icons/icon-fruit-tomatoe.png" id="6_l04qi"] -[ext_resource type="AudioStream" uid="uid://ccionrfr6e3lb" path="res://audio/sfx/Battle/Vesna/SFX_Battle_Vesna_Attack_04.wav" id="6_u1ayv"] - -[sub_resource type="CircleShape2D" id="CircleShape2D_0tqnl"] -radius = 291.58 - -[sub_resource type="CircleShape2D" id="CircleShape2D_4r2vf"] -radius = 173.44 - -[node name="VesnaFighter" type="Node2D" node_paths=PackedStringArray("_attackButtons", "_targetButtons", "_targetMarker", "_healthText", "_visualSprite")] -script = ExtResource("1_f3j2x") -name = "Vesna" -maxHealth = 100 -attackStrength = 10 -_attackButtons = NodePath("FightButtons") -_targetButtons = NodePath("TargetButtons") -_targetMarker = NodePath("TargetButtons/TargetMarker") -_healthText = NodePath("HealthShow") -_visualSprite = NodePath("Sprite2D") - -[node name="Sprite2D" type="Sprite2D" parent="."] -texture = ExtResource("2_2ud32") -offset = Vector2(43, -379) - -[node name="TargetButtons" type="Node2D" parent="."] -visible = false - -[node name="TargetMarker" type="Sprite2D" parent="TargetButtons"] -visible = false -z_index = 200 -position = Vector2(8, -122) -scale = Vector2(4.245, 4.245) -texture = ExtResource("3_80knd") - -[node name="Area2D" type="Area2D" parent="TargetButtons"] -position = Vector2(3, -76) - -[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetButtons/Area2D"] -shape = SubResource("CircleShape2D_0tqnl") - -[node name="FightButtons" type="Node2D" parent="."] -position = Vector2(3, -714) - -[node name="CircleBackground" type="Sprite2D" parent="FightButtons"] -z_index = 200 -scale = Vector2(4.245, 4.245) -texture = ExtResource("3_80knd") - -[node name="AttackButton" type="Node2D" parent="FightButtons"] -position = Vector2(0, -536) - -[node name="ButtonBackground" type="Sprite2D" parent="FightButtons/AttackButton"] -z_index = 200 -scale = Vector2(2.48, 2.48) -texture = ExtResource("5_rjjub") - -[node name="Sprite2D" type="Sprite2D" parent="FightButtons/AttackButton/ButtonBackground"] -position = Vector2(6.04839, -10.0806) -rotation = -1.0088 -scale = Vector2(0.249373, 0.25079) -texture = ExtResource("5_l04qi") -region_enabled = true -region_rect = Rect2(291.897, 15.8974, 272.82, 479.385) - -[node name="Area2D" type="Area2D" parent="FightButtons/AttackButton"] -collision_layer = 16 - -[node name="CollisionShape2D" type="CollisionShape2D" parent="FightButtons/AttackButton/Area2D"] -shape = SubResource("CircleShape2D_4r2vf") - -[node name="HealButton" type="Node2D" parent="FightButtons"] -position = Vector2(427, -334) - -[node name="ButtonBackground" type="Sprite2D" parent="FightButtons/HealButton"] -z_index = 200 -scale = Vector2(2.48, 2.48) -texture = ExtResource("5_rjjub") - -[node name="Sprite2D" type="Sprite2D" parent="FightButtons/HealButton/ButtonBackground"] -position = Vector2(4.83871, 0) -scale = Vector2(0.279343, 0.279343) -texture = ExtResource("6_l04qi") - -[node name="Area2D" type="Area2D" parent="FightButtons/HealButton"] -collision_layer = 16 - -[node name="CollisionShape2D" type="CollisionShape2D" parent="FightButtons/HealButton/Area2D"] -shape = SubResource("CircleShape2D_4r2vf") - -[node name="HealthShow" type="Label" parent="."] -z_index = 200 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = -197.0 -offset_top = -947.0 -offset_right = 207.0 -offset_bottom = -801.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_font_sizes/font_size = 106 -text = "100/100" -horizontal_alignment = 1 -vertical_alignment = 1 - -[node name="HitAudio" type="AudioStreamPlayer" parent="."] -stream = ExtResource("5_4r2vf") - -[node name="AttackAudio" type="AudioStreamPlayer" parent="."] -stream = ExtResource("6_u1ayv") - -[connection signal="Attacking" from="." to="AttackAudio" method="play" binds= [0.0]] -[connection signal="DamageTaken" from="." to="HitAudio" method="play" binds= [0.0]] -[connection signal="input_event" from="FightButtons/AttackButton/Area2D" to="." method="AttackMouseEvent"] -[connection signal="input_event" from="FightButtons/HealButton/Area2D" to="." method="HealMouseEvent"] diff --git a/prefabs/fight/roaming_enemy_group.tscn b/prefabs/fight/roaming_enemy_group.tscn new file mode 100644 index 0000000..590b8ff --- /dev/null +++ b/prefabs/fight/roaming_enemy_group.tscn @@ -0,0 +1,51 @@ +[gd_scene load_steps=9 format=3 uid="uid://qfdiudt3vpai"] + +[ext_resource type="Script" uid="uid://lequnojtar76" path="res://scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs" id="1_t3mrx"] +[ext_resource type="Texture2D" uid="uid://ccrnmx6bd842k" path="res://art/characters/farm fäulnis blobs.png" id="2_6ftwg"] +[ext_resource type="Texture2D" uid="uid://bexymddkb6l0o" path="res://art/characters/Mavka/mavkha.png" id="3_xi5g8"] +[ext_resource type="PackedScene" uid="uid://cqc72e4hq6bcd" path="res://prefabs/interactions/interaction_area_2d.tscn" id="4_xi5g8"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_c8fs8"] +atlas = ExtResource("2_6ftwg") +region = Rect2(1747.17, 156.157, 311.249, 280.596) + +[sub_resource type="AtlasTexture" id="AtlasTexture_kbgcx"] +atlas = ExtResource("3_xi5g8") +region = Rect2(774.378, 151.512, 1097.48, 1412.67) + +[sub_resource type="AtlasTexture" id="AtlasTexture_6fvcb"] +atlas = ExtResource("2_6ftwg") +region = Rect2(1149.47, 92.492, 445.652, 353.692) + +[sub_resource type="CircleShape2D" id="CircleShape2D_xi5g8"] +resource_local_to_scene = true +radius = 402.0112 + +[node name="RoamingEnemyGroup" type="Node2D"] +script = ExtResource("1_t3mrx") + +[node name="Visuals" type="Node2D" parent="."] + +[node name="Sprite2D" type="Sprite2D" parent="Visuals"] +position = Vector2(99, -222) +texture = SubResource("AtlasTexture_c8fs8") + +[node name="Sprite2D3" type="Sprite2D" parent="Visuals"] +position = Vector2(-108, -337) +scale = Vector2(0.43, 0.43) +texture = SubResource("AtlasTexture_kbgcx") + +[node name="Sprite2D2" type="Sprite2D" parent="Visuals"] +position = Vector2(-41, -109) +texture = SubResource("AtlasTexture_6fvcb") + +[node name="InteractionArea" parent="." node_paths=PackedStringArray("_spritesToOutline") instance=ExtResource("4_xi5g8")] +_spritesToOutline = [NodePath("../Visuals/Sprite2D"), NodePath("../Visuals/Sprite2D3"), NodePath("../Visuals/Sprite2D2")] + +[node name="CollisionShape3D" parent="InteractionArea/Area2D" index="0"] +position = Vector2(-49, -174) +shape = SubResource("CircleShape2D_xi5g8") + +[connection signal="Interacted" from="InteractionArea" to="." method="StartFight"] + +[editable path="InteractionArea"] diff --git a/prefabs/fight/fight_base_scene.tscn b/prefabs/fightOld/fight_base_scene.tscn similarity index 93% rename from prefabs/fight/fight_base_scene.tscn rename to prefabs/fightOld/fight_base_scene.tscn index 6ed38f9..160f0f1 100644 --- a/prefabs/fight/fight_base_scene.tscn +++ b/prefabs/fightOld/fight_base_scene.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://hk8ahyp6dgl6"] -[ext_resource type="Script" uid="uid://c76mhhqyk4lgh" path="res://scripts/CSharp/Common/Fight/FightInstance.cs" id="1_ygesl"] -[ext_resource type="Script" uid="uid://oe1uypehqvr7" path="res://scripts/CSharp/Common/Fight/FightStateManager.cs" id="2_b0ivm"] +[ext_resource type="Script" uid="uid://c76mhhqyk4lgh" path="res://scripts/CSharp/Common/FightOld/FightInstance.cs" id="1_ygesl"] +[ext_resource type="Script" uid="uid://oe1uypehqvr7" path="res://scripts/CSharp/Common/FightOld/FightStateManager.cs" id="2_b0ivm"] [node name="FightBaseScene" type="Node2D" node_paths=PackedStringArray("_friendlyFightSpots", "_enemyFightSpots", "camPositionNode", "_fightStateManager", "_fightEndText")] script = ExtResource("1_ygesl") diff --git a/prefabs/fight/fight_manager_autoload.tscn b/prefabs/fightOld/fight_manager_autoload.tscn similarity index 70% rename from prefabs/fight/fight_manager_autoload.tscn rename to prefabs/fightOld/fight_manager_autoload.tscn index 8102fe1..a7d72f2 100644 --- a/prefabs/fight/fight_manager_autoload.tscn +++ b/prefabs/fightOld/fight_manager_autoload.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://cnjsepvaqdbyq"] -[ext_resource type="Script" uid="uid://j5ge24rk25wm" path="res://scripts/CSharp/Common/Fight/FightManager.cs" id="1_8p7ev"] -[ext_resource type="PackedScene" uid="uid://cpanatqdjjpa3" path="res://prefabs/fight/fighters/vesna_fighter.tscn" id="2_ak1vo"] +[ext_resource type="Script" uid="uid://j5ge24rk25wm" path="res://scripts/CSharp/Common/FightOld/FightManager.cs" id="1_8p7ev"] +[ext_resource type="PackedScene" uid="uid://cpanatqdjjpa3" path="res://prefabs/fightOld/fighters/vesna_fighter.tscn" id="2_ak1vo"] [node name="FightManagerAutoload" type="Node"] script = ExtResource("1_8p7ev") diff --git a/prefabs/fight/fighters/enemy_blob_fighter.tscn b/prefabs/fightOld/fighters/enemy_blob_fighter.tscn similarity index 91% rename from prefabs/fight/fighters/enemy_blob_fighter.tscn rename to prefabs/fightOld/fighters/enemy_blob_fighter.tscn index 087a7f6..bab5781 100644 --- a/prefabs/fight/fighters/enemy_blob_fighter.tscn +++ b/prefabs/fightOld/fighters/enemy_blob_fighter.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=10 format=3 uid="uid://bp64p6y72j71w"] [ext_resource type="Texture2D" uid="uid://ccrnmx6bd842k" path="res://art/characters/farm fäulnis blobs.png" id="1_vem8k"] -[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/Fighter.cs" id="2_4w1ab"] +[ext_resource type="Script" path="res://scripts/CSharp/Common/FightOld/Fighter.cs" id="2_4w1ab"] [ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_v4f83"] [ext_resource type="AudioStream" uid="uid://x7cc5woop5ec" path="res://audio/sfx/Battle/Enemies/SFX_Slime_Hit_V2_03.wav" id="5_v4f83"] [ext_resource type="Texture2D" uid="uid://bn56p0ytuo060" path="res://art/ui/UI/AttackButton.png" id="5_vbkts"] @@ -19,6 +19,7 @@ script = ExtResource("2_4w1ab") name = "Blob" maxHealth = 20 attackStrength = 10 +maxActions = null _attackButtons = NodePath("FightButtons") _targetButtons = NodePath("TargetButtons") _targetMarker = NodePath("TargetButtons/TargetMarker") @@ -95,9 +96,6 @@ stream = ExtResource("6_vbkts") [node name="AttackAudio" type="AudioStreamPlayer" parent="."] stream = ExtResource("6_oykh8") -[connection signal="Attacking" from="." to="AttackAudio" method="play" binds= [0.0]] -[connection signal="DamageTaken" from="." to="HitAudio" method="play" binds= [0.0]] -[connection signal="Dying" from="." to="DieAudio" method="play" binds= [0.0]] [connection signal="input_event" from="TargetButtons/Area2D" to="." method="TargetMouseEvent"] [connection signal="mouse_entered" from="TargetButtons/Area2D" to="." method="StartHoverTarget"] [connection signal="mouse_exited" from="TargetButtons/Area2D" to="." method="EndHoverTarget"] diff --git a/prefabs/fight/fighters/enemy_mavkha_fighter.tscn b/prefabs/fightOld/fighters/enemy_mavkha_fighter.tscn similarity index 88% rename from prefabs/fight/fighters/enemy_mavkha_fighter.tscn rename to prefabs/fightOld/fighters/enemy_mavkha_fighter.tscn index 2580ffe..d68c61d 100644 --- a/prefabs/fight/fighters/enemy_mavkha_fighter.tscn +++ b/prefabs/fightOld/fighters/enemy_mavkha_fighter.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=10 format=3 uid="uid://cr66tpdr5rma5"] -[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/Fighter.cs" id="1_t6th8"] +[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/FighterVisual.cs" id="1_t6th8"] [ext_resource type="Texture2D" uid="uid://bexymddkb6l0o" path="res://art/characters/Mavka/mavkha.png" id="2_shg7p"] [ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_nkuei"] [ext_resource type="Texture2D" uid="uid://bn56p0ytuo060" path="res://art/ui/UI/AttackButton.png" id="4_u3hw3"] @@ -14,16 +14,8 @@ radius = 388.063 [sub_resource type="CircleShape2D" id="CircleShape2D_s74nc"] radius = 173.44 -[node name="EnemyMavkhaFighter" type="Node2D" node_paths=PackedStringArray("_attackButtons", "_targetButtons", "_targetMarker", "_healthText", "_visualSprite")] +[node name="EnemyMavkhaFighter" type="Node2D"] script = ExtResource("1_t6th8") -name = "Mavkha" -maxHealth = 40 -attackStrength = 10 -_attackButtons = NodePath("FightButtons") -_targetButtons = NodePath("TargetButtons") -_targetMarker = NodePath("TargetButtons/TargetMarker") -_healthText = NodePath("HealthShow") -_visualSprite = NodePath("Visual") [node name="Visual" type="Node2D" parent="."] diff --git a/prefabs/fightOld/fighters/vesna_fighter.tscn b/prefabs/fightOld/fighters/vesna_fighter.tscn new file mode 100644 index 0000000..35bfa8f --- /dev/null +++ b/prefabs/fightOld/fighters/vesna_fighter.tscn @@ -0,0 +1,64 @@ +[gd_scene load_steps=7 format=3 uid="uid://cpanatqdjjpa3"] + +[ext_resource type="Script" path="res://scripts/CSharp/Common/FightOld/Fighter.cs" id="1_f3j2x"] +[ext_resource type="Texture2D" uid="uid://om2axn1vfa5o" path="res://art/animation/Vesna2D/Vesna Anims Sequences/S01-Idle/0001.png" id="2_2ud32"] +[ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_80knd"] +[ext_resource type="AudioStream" uid="uid://ch4c1wh4ghxyo" path="res://audio/sfx/Battle/Vesna/SFX_Battle_Vesna_Defense_08.wav" id="5_4r2vf"] +[ext_resource type="AudioStream" uid="uid://ccionrfr6e3lb" path="res://audio/sfx/Battle/Vesna/SFX_Battle_Vesna_Attack_04.wav" id="6_u1ayv"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_0tqnl"] +radius = 291.58 + +[node name="VesnaFighter" type="Node2D" node_paths=PackedStringArray("_attackButtons", "_targetButtons", "_targetMarker", "_healthText", "_visualSprite")] +script = ExtResource("1_f3j2x") +name = "Vesna" +maxHealth = 100 +attackStrength = 10 +maxActions = null +_attackButtons = NodePath("") +_targetButtons = NodePath("TargetButtons") +_targetMarker = NodePath("TargetButtons/TargetMarker") +_healthText = NodePath("HealthShow") +_visualSprite = NodePath("Sprite2D") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("2_2ud32") +offset = Vector2(43, -379) + +[node name="TargetButtons" type="Node2D" parent="."] +visible = false + +[node name="TargetMarker" type="Sprite2D" parent="TargetButtons"] +visible = false +z_index = 200 +position = Vector2(8, -122) +scale = Vector2(4.245, 4.245) +texture = ExtResource("3_80knd") + +[node name="Area2D" type="Area2D" parent="TargetButtons"] +position = Vector2(3, -76) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetButtons/Area2D"] +shape = SubResource("CircleShape2D_0tqnl") + +[node name="HealthShow" type="Label" parent="."] +z_index = 200 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -197.0 +offset_top = -947.0 +offset_right = 207.0 +offset_bottom = -801.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_font_sizes/font_size = 106 +text = "100/100" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="HitAudio" type="AudioStreamPlayer" parent="."] +stream = ExtResource("5_4r2vf") + +[node name="AttackAudio" type="AudioStreamPlayer" parent="."] +stream = ExtResource("6_u1ayv") diff --git a/prefabs/minigame/minigame.tscn b/prefabs/minigame/minigame.tscn new file mode 100644 index 0000000..5541b09 --- /dev/null +++ b/prefabs/minigame/minigame.tscn @@ -0,0 +1,38 @@ +[gd_scene load_steps=7 format=3 uid="uid://bydwj3pbvqrhb"] + +[ext_resource type="Script" uid="uid://ct7l4er2kljnc" path="res://scripts/CSharp/Common/Minigame/MinigameController.cs" id="1_17v35"] +[ext_resource type="PackedScene" uid="uid://dhfda4o386byp" path="res://prefabs/minigame/region_visual.tscn" id="2_rrvb1"] +[ext_resource type="Script" uid="uid://djkyrp24ljff0" path="res://scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs" id="3_86pvs"] +[ext_resource type="Texture2D" uid="uid://bgn2ci6nu85t5" path="res://addons/dialogic/Example Assets/next-indicator/next-indicator-dialogic-1.png" id="3_pe4tw"] +[ext_resource type="Script" uid="uid://dq7gahfp0lk7v" path="res://scripts/CSharp/Common/Util/ClickDetect.cs" id="5_86pvs"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_pe4tw"] +radius = 554.923 + +[node name="Minigame" type="Node2D" node_paths=PackedStringArray("_regionsParent")] +script = ExtResource("1_17v35") +_regionVisualPrefab = ExtResource("2_rrvb1") +_regionsParent = NodePath("RegionsParent") +_baseRegionColor = Color(0.176888, 0.482224, 0.338857, 1) + +[node name="RegionsParent" type="Node2D" parent="."] + +[node name="SpinnyArm" type="Node2D" parent="."] +script = ExtResource("3_86pvs") + +[node name="ArmVisual" type="Node2D" parent="SpinnyArm"] + +[node name="Sprite" type="Sprite2D" parent="SpinnyArm/ArmVisual"] +position = Vector2(0, -40) +rotation = -3.14159 +scale = Vector2(1, 2.08) +texture = ExtResource("3_pe4tw") + +[node name="Area2D" type="Area2D" parent="."] +script = ExtResource("5_86pvs") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +shape = SubResource("CircleShape2D_pe4tw") + +[connection signal="ArmMoved" from="." to="SpinnyArm" method="SetAngle"] +[connection signal="Click" from="Area2D" to="." method="Hit"] diff --git a/prefabs/minigame/region_visual.tscn b/prefabs/minigame/region_visual.tscn new file mode 100644 index 0000000..e2c36b8 --- /dev/null +++ b/prefabs/minigame/region_visual.tscn @@ -0,0 +1,52 @@ +[gd_scene load_steps=5 format=3 uid="uid://dhfda4o386byp"] + +[ext_resource type="Script" uid="uid://cdpsa4qrlai31" path="res://scripts/CSharp/Common/Minigame/RegionVisual.cs" id="1_4ymj8"] +[ext_resource type="Shader" uid="uid://d0dayn7dc885j" path="res://shader/minigame_pie_section.gdshader" id="1_8p2xn"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_86pvs"] +resource_local_to_scene = true +shader = ExtResource("1_8p2xn") +shader_parameter/textureSize = 400.0 +shader_parameter/fillColor = Color(0.285466, 0.685481, 0.880632, 1) +shader_parameter/borderColor = Color(1, 1, 1, 1) +shader_parameter/borderWidth = 0.025 +shader_parameter/angles = Vector2(0.01, 0.18) +shader_parameter/smoothWidth = 0.0052 + +[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_0navw"] +size = Vector2(400, 400) + +[node name="RegionVisual" type="Node2D" node_paths=PackedStringArray("_sliceSprite", "_textLabel", "_labelPivot")] +script = ExtResource("1_4ymj8") +_sliceSprite = NodePath("Sprite2D") +_textLabel = NodePath("LabelPivot/Label") +_labelPivot = NodePath("LabelPivot") +_fillColors = Dictionary[int, Color]({ +0: Color(0.427493, 0.427493, 0.427493, 1), +1: Color(0.675735, 0.105671, 0.0799616, 1), +2: Color(0.645128, 0.346481, 0.215967, 1), +3: Color(0.754619, 0.665655, 0.384568, 1), +4: Color(0.365769, 0.400285, 0.598083, 1), +5: Color(0.222174, 0.457454, 0.45483, 1), +6: Color(0.316126, 0.448834, 0.312852, 1), +7: Color(0.244391, 0.640687, 0.283315, 1) +}) + +[node name="Sprite2D" type="Sprite2D" parent="."] +material = SubResource("ShaderMaterial_86pvs") +texture = SubResource("PlaceholderTexture2D_0navw") + +[node name="LabelPivot" type="Node2D" parent="."] + +[node name="Label" type="Label" parent="LabelPivot"] +custom_minimum_size = Vector2(100, 40) +offset_left = -50.0 +offset_top = -240.0 +offset_right = 50.0 +offset_bottom = -200.0 +pivot_offset = Vector2(50, 20) +size_flags_horizontal = 0 +theme_override_font_sizes/font_size = 21 +text = "test" +horizontal_alignment = 1 +vertical_alignment = 1 diff --git a/project.godot b/project.godot index b456426..742ff84 100644 --- a/project.godot +++ b/project.godot @@ -28,10 +28,10 @@ buses/default_bus_layout="uid://b6dwkmkyb0axk" SceneTransition="*res://scenes/SceneTransition.tscn" Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd" InventoryManager="*res://scripts/CSharp/Common/Inventory/InventoryManager.cs" -QuestManager="*res://prefabs/quests/quest_manager_autoload.tscn" -FightManagerAutoload="*res://prefabs/fight/fight_manager_autoload.tscn" InputService="*res://scripts/CSharp/Common/Services/InputService.cs" +QuestManager="*res://prefabs/quests/quest_manager_autoload.tscn" Signal_Debugger="*res://addons/SignalVisualizer/Debugger/SignalDebugger.gd" +FightWorldAutoload="*res://prefabs/fight/fight_world_autoload.tscn" [dialogic] diff --git a/scenes/Babushka_scene_bootstrap.tscn b/scenes/Babushka_scene_bootstrap.tscn index 5b1809d..fe66be1 100644 --- a/scenes/Babushka_scene_bootstrap.tscn +++ b/scenes/Babushka_scene_bootstrap.tscn @@ -5,5 +5,6 @@ [node name="BabushkaSceneBootstrap" type="Node2D"] [node name="BabushkaSceneStartMenu" parent="." instance=ExtResource("1_15ton")] +_sceneNamesToLoad = PackedStringArray("res://scenes/Babushka_scene_fight_world_room.tscn") [node name="SceneParent" type="Node" parent="."] diff --git a/scenes/Babushka_scene_fight_happening.tscn b/scenes/Babushka_scene_fight_happening.tscn new file mode 100644 index 0000000..0ebaa51 --- /dev/null +++ b/scenes/Babushka_scene_fight_happening.tscn @@ -0,0 +1,220 @@ +[gd_scene load_steps=14 format=3 uid="uid://cjshlwk8ajpnp"] + +[ext_resource type="Script" uid="uid://cnhpnn8o0gybd" path="res://scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs" id="1_fiutj"] +[ext_resource type="Script" uid="uid://c76mhhqyk4lgh" path="res://scripts/CSharp/Common/Fight/FightHappening.cs" id="1_gsk03"] +[ext_resource type="Script" uid="uid://dtf4ejct4m682" path="res://scripts/CSharp/Common/Fight/ActionAnimationController.cs" id="2_7kjgs"] +[ext_resource type="Script" uid="uid://dwsqst8fhhqlc" path="res://scripts/CSharp/Common/Fight/AllFightersVisual.cs" id="2_lu4y4"] +[ext_resource type="PackedScene" uid="uid://bcld43daavmrn" path="res://prefabs/fight/fight_scene_switcher.tscn" id="2_phrlx"] +[ext_resource type="PackedScene" uid="uid://7jsxokx67gpq" path="res://prefabs/fight/fighterVisuals/vesna_fighter_visual.tscn" id="4_qo0gi"] +[ext_resource type="PackedScene" uid="uid://0vm3jb1hnkkb" path="res://prefabs/fight/fighterVisuals/blob_fighter_visual.tscn" id="4_vp8s0"] +[ext_resource type="Script" uid="uid://buiwuf7pjfq8" path="res://scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs" id="4_ydj1i"] +[ext_resource type="PackedScene" uid="uid://bydwj3pbvqrhb" path="res://prefabs/minigame/minigame.tscn" id="8_2b3cf"] +[ext_resource type="Script" uid="uid://byf2ywov34g0x" path="res://scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs" id="8_bkwsr"] +[ext_resource type="Script" uid="uid://bwm0nhvt1083k" path="res://scripts/CSharp/Common/Fight/FightMinigameHandler.cs" id="8_falfe"] +[ext_resource type="Script" uid="uid://d2ugtb3dalrg3" path="res://scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs" id="8_tv7cl"] +[ext_resource type="Script" uid="uid://2f7rqk50gtdg" path="res://scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs" id="10_qqd8u"] + +[node name="BabushkaSceneFightHappening" type="Node2D"] + +[node name="FightHappening" type="Node" parent="."] +script = ExtResource("1_gsk03") + +[node name="ActionAnimationController" type="Node" parent="." node_paths=PackedStringArray("_allFightersVisual")] +script = ExtResource("2_7kjgs") +_allFightersVisual = NodePath("../FightVisuals") + +[node name="StateReactionActionAnimation" type="Node" parent="ActionAnimationController"] +script = ExtResource("4_ydj1i") +_fightState = 10 + +[node name="Camera2D" type="Camera2D" parent="."] + +[node name="FightSetup" type="Node2D" parent="."] +script = ExtResource("1_fiutj") + +[node name="FightVisuals" type="Node2D" parent="." node_paths=PackedStringArray("_allyFighters", "_enemyFighters")] +position = Vector2(0, 259) +script = ExtResource("2_lu4y4") +_allyFighters = NodePath("AllyFighters") +_enemyFighters = NodePath("EnemyFighters") +_blobFighterVisual = ExtResource("4_vp8s0") +_vesnaFighterVisual = ExtResource("4_qo0gi") +_positionDistanceFromCenter = PackedFloat32Array(300, 550, 800) + +[node name="AllyFighters" type="Node2D" parent="FightVisuals"] + +[node name="EnemyFighters" type="Node2D" parent="FightVisuals"] + +[node name="EnvironmentVisuals" type="Node2D" parent="."] + +[node name="MinigameHandler" type="Node2D" parent="." node_paths=PackedStringArray("_minigameController")] +script = ExtResource("8_falfe") +_minigameController = NodePath("Minigame") + +[node name="Minigame" parent="MinigameHandler" instance=ExtResource("8_2b3cf")] +process_mode = 4 +visible = false + +[node name="SwitchSceneOnFightEnd" type="Node" parent="." node_paths=PackedStringArray("_fightSceneSwitcher")] +script = ExtResource("10_qqd8u") +_fightSceneSwitcher = NodePath("FightSceneSwitcher") + +[node name="FightSceneSwitcher" parent="SwitchSceneOnFightEnd" node_paths=PackedStringArray("_sceneRoot") instance=ExtResource("2_phrlx")] +_sceneRoot = NodePath("../..") + +[node name="ActionSelect" type="CanvasLayer" parent="." node_paths=PackedStringArray("_attackActionButton", "_summonActionButton", "_talkActionButton", "_fleeActionButton")] +visible = false +script = ExtResource("8_bkwsr") +_attackActionButton = NodePath("BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/AttackButton") +_summonActionButton = NodePath("BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer2/Summon Button") +_talkActionButton = NodePath("BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer3/Talk Button") +_fleeActionButton = NodePath("BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer4/Flee Button") + +[node name="BottomPanel" type="Control" parent="ActionSelect"] +custom_minimum_size = Vector2(0, 200) +layout_mode = 3 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 0 +size_flags_vertical = 8 + +[node name="background" type="ColorRect" parent="ActionSelect/BottomPanel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(1, 1, 1, 0.27451) + +[node name="VBoxContainer" type="VBoxContainer" parent="ActionSelect/BottomPanel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/margin_left = 200 +theme_override_constants/margin_right = 200 + +[node name="HBoxContainer" type="HBoxContainer" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer"] +layout_mode = 2 +alignment = 1 + +[node name="MarginContainer" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="AttackButton" type="Button" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 41 +text = "Attack" + +[node name="MarginContainer2" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="Summon Button" type="Button" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer2"] +layout_mode = 2 +theme_override_font_sizes/font_size = 41 +text = "Summon" + +[node name="MarginContainer3" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="Talk Button" type="Button" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer3"] +layout_mode = 2 +theme_override_font_sizes/font_size = 41 +text = "Talk" + +[node name="MarginContainer4" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="Flee Button" type="Button" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer4"] +layout_mode = 2 +theme_override_font_sizes/font_size = 41 +text = "Flee" + +[node name="MarginContainer2" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/margin_left = 200 +theme_override_constants/margin_right = 200 + +[node name="MarginContainer" type="MarginContainer" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer2"] +layout_mode = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="Label" type="Label" parent="ActionSelect/BottomPanel/VBoxContainer/MarginContainer2/MarginContainer"] +layout_mode = 2 +size_flags_vertical = 1 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_font_sizes/font_size = 41 +text = "This text explains the currently hovered button" + +[node name="StateReactionInputActionSelect" type="Node" parent="ActionSelect"] +script = ExtResource("4_ydj1i") +_fightState = 6 + +[node name="StateMachineDebugger" type="Node" parent="." node_paths=PackedStringArray("_label", "_current")] +script = ExtResource("8_tv7cl") +_label = NodePath("Label") +_current = NodePath("Current") + +[node name="Label" type="Label" parent="StateMachineDebugger"] +offset_left = -982.0 +offset_top = -497.0 +offset_right = -893.0 +offset_bottom = -474.0 +text = "Hello world" + +[node name="Current" type="Label" parent="StateMachineDebugger"] +offset_left = 705.0 +offset_top = -495.0 +offset_right = 794.0 +offset_bottom = -472.0 +text = "Hello world" + +[connection signal="SignalTransitionState" from="FightHappening" to="ActionAnimationController/StateReactionActionAnimation" method="FightHappeningStateTransitioned"] +[connection signal="SignalTransitionState" from="FightHappening" to="FightVisuals" method="FightHappeningStateChange"] +[connection signal="SignalTransitionState" from="FightHappening" to="ActionSelect/StateReactionInputActionSelect" method="FightHappeningStateTransitioned"] +[connection signal="SignalTransitionState" from="FightHappening" to="StateMachineDebugger" method="StateChange"] +[connection signal="SignalTransitionToState" from="FightHappening" to="MinigameHandler" method="OnStateEnter"] +[connection signal="SignalTransitionToState" from="FightHappening" to="SwitchSceneOnFightEnd" method="OnFightStateEnter"] +[connection signal="OnStateEntered" from="ActionAnimationController/StateReactionActionAnimation" to="ActionAnimationController" method="StateEnter"] +[connection signal="OnStateExited" from="ActionAnimationController/StateReactionActionAnimation" to="ActionAnimationController" method="StateExit"] +[connection signal="pressed" from="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/AttackButton" to="ActionSelect" method="SelectAction" binds= [1]] +[connection signal="pressed" from="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer2/Summon Button" to="ActionSelect" method="SelectAction" binds= [2]] +[connection signal="pressed" from="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer3/Talk Button" to="ActionSelect" method="SelectAction" binds= [3]] +[connection signal="pressed" from="ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer4/Flee Button" to="ActionSelect" method="SelectAction" binds= [4]] +[connection signal="OnStateEntered" from="ActionSelect/StateReactionInputActionSelect" to="ActionSelect" method="show"] +[connection signal="OnStateEntered" from="ActionSelect/StateReactionInputActionSelect" to="ActionSelect" method="StateEntered"] +[connection signal="OnStateExited" from="ActionSelect/StateReactionInputActionSelect" to="ActionSelect" method="hide"] diff --git a/scenes/Babushka_scene_fight_world_room.tscn b/scenes/Babushka_scene_fight_world_room.tscn new file mode 100644 index 0000000..5665420 --- /dev/null +++ b/scenes/Babushka_scene_fight_world_room.tscn @@ -0,0 +1,2161 @@ +[gd_scene load_steps=53 format=3 uid="uid://cacnapfv7w567"] + +[ext_resource type="Script" uid="uid://bqomwxclsbhd3" path="res://scripts/CSharp/Common/Camera/CameraController.cs" id="1_pi6ua"] +[ext_resource type="Texture2D" uid="uid://8sr11ex30n0m" path="res://art/mockups/Kenney_Backgrounds/Samples/uncolored_hills.png" id="2_hqa4k"] +[ext_resource type="Texture2D" uid="uid://be1nofeo7an0" path="res://art/mockups/Kenney_Backgrounds/PNG/cloud2.png" id="3_ir2xa"] +[ext_resource type="Texture2D" uid="uid://o6vnf7n7qp8o" path="res://art/mockups/Kenney_Backgrounds/PNG/cloud6.png" id="4_3y3c4"] +[ext_resource type="Texture2D" uid="uid://cc0o84q5u437k" path="res://art/mockups/Kenney_Backgrounds/PNG/cloud7.png" id="5_elhbh"] +[ext_resource type="Texture2D" uid="uid://cqdb0iqhlk5st" path="res://art/mockups/Kenney_Backgrounds/PNG/cloud8.png" id="6_cvg1r"] +[ext_resource type="Texture2D" uid="uid://cydc6feouwxys" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/hills1.png" id="7_x3yi1"] +[ext_resource type="Texture2D" uid="uid://vt1gtr2trvwt" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/hills2.png" id="8_kcbkm"] +[ext_resource type="Texture2D" uid="uid://b6k4vrgj745k" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/tree03.png" id="9_m1imc"] +[ext_resource type="Texture2D" uid="uid://dchn4jd4d7q3w" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/tree01.png" id="10_svwgx"] +[ext_resource type="Texture2D" uid="uid://8ai3me0j0wi" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/tree04.png" id="11_blrv5"] +[ext_resource type="Texture2D" uid="uid://g83vpep7rwwd" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/tree12.png" id="12_fx2ph"] +[ext_resource type="Texture2D" uid="uid://bleimj6jr1jka" path="res://art/general/rectangle.png" id="13_lbo36"] +[ext_resource type="Texture2D" uid="uid://dxrc50i65wuc4" path="res://art/mockups/Jelena 2d/jelena_mockup_bg01.png" id="14_6f1e2"] +[ext_resource type="Texture2D" uid="uid://dv2jepy2el544" path="res://art/mockups/Kenney_Backgrounds/PNG/Flat/tree11.png" id="15_2x6x8"] +[ext_resource type="Shader" uid="uid://do5og8uubh2m5" path="res://shader/HSV.gdshader" id="16_0fard"] +[ext_resource type="Texture2D" uid="uid://d0e8a7qsfkhy3" path="res://art/mockups/Jelena 2d/jelena_mockup_bg_02.png" id="17_40bfw"] +[ext_resource type="Texture2D" uid="uid://bqoyk3fsrmu1x" path="res://art/nature/baum märz 2025/back back trees.png" id="18_uik6u"] +[ext_resource type="Texture2D" uid="uid://451bkvxcxab7" path="res://art/nature/baum märz 2025/gräser und büsche.png" id="19_edja8"] +[ext_resource type="Texture2D" uid="uid://dldk8n51ag8fh" path="res://art/nature/baum märz 2025/backtreebois team brandon.png" id="20_pxlql"] +[ext_resource type="Texture2D" uid="uid://bmjjfd5ngptxe" path="res://art/nature/baum märz 2025/backtreebois team kennedy.png" id="21_mlqvj"] +[ext_resource type="Texture2D" uid="uid://bcw6oeovkmiup" path="res://art/nature/baum märz 2025/sonnenblumeseamless.png" id="22_22c4u"] +[ext_resource type="Shader" uid="uid://xnky830dtfsn" path="res://shader/repeat_texture.gdshader" id="23_2ouqg"] +[ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Player2D.tscn" id="24_ffcio"] +[ext_resource type="Resource" uid="uid://dlcmqfjvgphqu" path="res://resources/items/rake.tres" id="25_3h260"] +[ext_resource type="Resource" uid="uid://cndd64batns31" path="res://resources/items/wateringcan.tres" id="26_1bhpp"] +[ext_resource type="Shader" uid="uid://braevmqauoek7" path="res://shader/swaying_plant.gdshader" id="27_txtka"] +[ext_resource type="Texture2D" uid="uid://dgavbfci8x178" path="res://art/nature/grass/grass-1.png" id="28_ejigw"] +[ext_resource type="Texture2D" uid="uid://h2b5aufaaw7w" path="res://art/nature/grass/grass-2.png" id="29_pjemw"] +[ext_resource type="Texture2D" uid="uid://b644ofy7fml5w" path="res://art/nature/grass/grass-5.png" id="30_cmmg6"] +[ext_resource type="Texture2D" uid="uid://badnnid7dgnpk" path="res://art/nature/grass/grass-4.png" id="31_spe7q"] +[ext_resource type="Texture2D" uid="uid://ct7ea8ikor5rf" path="res://art/nature/grass/grass-3.png" id="32_inmkn"] +[ext_resource type="Texture2D" uid="uid://d3dwl6ph0pu1d" path="res://art/nature/grass/grass-6.png" id="33_xtiat"] +[ext_resource type="Texture2D" uid="uid://dyueumlr5ltvr" path="res://art/nature/baum märz 2025/megaeichel megaast.png" id="34_nykjo"] +[ext_resource type="Texture2D" uid="uid://cuqkp4qvcg8jc" path="res://art/nature/baum märz 2025/trauerweiden.png" id="35_g3bna"] +[ext_resource type="Texture2D" uid="uid://bely5cfbf2x52" path="res://art/nature/baum märz 2025/umgeknackst.png" id="36_vwtyh"] +[ext_resource type="Script" uid="uid://bryibv73x5iwr" path="res://scripts/CSharp/Common/Fight/NextRoomTrigger.cs" id="37_3y3c4"] +[ext_resource type="Script" uid="uid://dpkx2gbg7b5xh" path="res://scripts/CSharp/Common/Fight/PathSetup.cs" id="37_elhbh"] +[ext_resource type="Script" uid="uid://dbu8afaiohpdh" path="res://scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs" id="40_cvg1r"] +[ext_resource type="PackedScene" uid="uid://bcld43daavmrn" path="res://prefabs/fight/fight_scene_switcher.tscn" id="40_elhbh"] +[ext_resource type="PackedScene" uid="uid://qfdiudt3vpai" path="res://prefabs/fight/roaming_enemy_group.tscn" id="41_cvg1r"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ruj2u"] +shader = ExtResource("16_0fard") +shader_parameter/hue_shift = 0.0 +shader_parameter/saturation_mult = 0.603 +shader_parameter/value_mult = 1.0 +shader_parameter/brightness_add = 0.0 +shader_parameter/contrast_mult = 1.0 + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_q1iw4"] +shader = ExtResource("16_0fard") +shader_parameter/hue_shift = -0.076 +shader_parameter/saturation_mult = 0.939 +shader_parameter/value_mult = 0.401 +shader_parameter/brightness_add = 0.0 +shader_parameter/contrast_mult = 1.0 + +[sub_resource type="Gradient" id="Gradient_663j1"] +colors = PackedColorArray(0.348791, 0.400092, 0.435264, 1, 0.219333, 0.251087, 0.329259, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_d5x6a"] + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_d53cn"] +seamless = true +color_ramp = SubResource("Gradient_663j1") +noise = SubResource("FastNoiseLite_d5x6a") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_k0jkw"] +shader = ExtResource("23_2ouqg") +shader_parameter/tiling_scale = Vector2(7.79, 5.2) +shader_parameter/noise = SubResource("NoiseTexture2D_d53cn") + +[sub_resource type="Gradient" id="Gradient_eryax"] +offsets = PackedFloat32Array(0, 0.743902, 1) +colors = PackedColorArray(0.22, 0.1078, 0.16764, 1, 0.443137, 0.4, 0.360784, 1, 0.6, 0.4853, 0.414, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_wgikv"] +frequency = 0.0296 +fractal_octaves = 7 +fractal_gain = 0.795 +domain_warp_enabled = true + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_pjpt5"] +seamless = true +color_ramp = SubResource("Gradient_eryax") +noise = SubResource("FastNoiseLite_wgikv") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_yvxfs"] +shader = ExtResource("27_txtka") +shader_parameter/speed = 0.4 +shader_parameter/minStrength = 0.101 +shader_parameter/maxStrength = 0.392 +shader_parameter/strengthScale = 270.22 +shader_parameter/interval = 36.75 +shader_parameter/detail = 3.68 +shader_parameter/distortion = 1.0 +shader_parameter/heightOffset = 0.49 +shader_parameter/offset = 0.2 + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_ir2xa"] +size = Vector2(608, 1256) + +[node name="BabushkaSceneFightWorldRoom" type="Node2D"] + +[node name="Camera2D" type="Camera2D" parent="." node_paths=PackedStringArray("_followNode")] +position = Vector2(3180, 1961) +scale = Vector2(1, 0.993819) +zoom = Vector2(0.25, 0.25) +limit_left = 6525 +limit_top = -395 +limit_right = 15490 +limit_bottom = 4090 +editor_draw_limits = true +script = ExtResource("1_pi6ua") +_followNode = NodePath("../YSorted/Vesna/CharacterBody2D") + +[node name="ParallaxBackground" type="ParallaxBackground" parent="."] + +[node name="background color layer" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(0, -552) +motion_scale = Vector2(0.1, 0.1) +motion_mirroring = Vector2(2048, 0) + +[node name="Sprite2D2" type="Sprite2D" parent="ParallaxBackground/background color layer"] +modulate = Color(0.5607, 0.89, 0.675955, 1) +z_index = -500 +position = Vector2(4096, 0) +scale = Vector2(2, 2) +texture = ExtResource("2_hqa4k") +centered = false +offset = Vector2(0, -100) + +[node name="Sprite2D3" type="Sprite2D" parent="ParallaxBackground/background color layer"] +modulate = Color(0.5607, 0.89, 0.675955, 1) +z_index = -500 +scale = Vector2(2, 2) +texture = ExtResource("2_hqa4k") +centered = false +offset = Vector2(0, -100) + +[node name="Sprite2D4" type="Sprite2D" parent="ParallaxBackground/background color layer"] +modulate = Color(0.5607, 0.89, 0.675955, 1) +z_index = -500 +position = Vector2(8192, 0) +scale = Vector2(2, 2) +texture = ExtResource("2_hqa4k") +centered = false +offset = Vector2(0, -100) + +[node name="clouds layer" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(-7, -138) +motion_scale = Vector2(0.2, 0.2) +motion_mirroring = Vector2(7000, 0) + +[node name="cloud" type="Sprite2D" parent="ParallaxBackground/clouds layer"] +z_index = -400 +position = Vector2(792, 400) +scale = Vector2(2, 2) +texture = ExtResource("3_ir2xa") +centered = false +offset = Vector2(0, -100) + +[node name="cloud2" type="Sprite2D" parent="ParallaxBackground/clouds layer"] +z_index = -400 +position = Vector2(2656, 272) +scale = Vector2(2, 2) +texture = ExtResource("4_3y3c4") +centered = false +offset = Vector2(0, -100) + +[node name="cloud3" type="Sprite2D" parent="ParallaxBackground/clouds layer"] +z_index = -400 +position = Vector2(3240, 488) +scale = Vector2(2, 2) +texture = ExtResource("5_elhbh") +centered = false +offset = Vector2(0, -100) + +[node name="cloud4" type="Sprite2D" parent="ParallaxBackground/clouds layer"] +z_index = -400 +position = Vector2(5461, 185) +scale = Vector2(2, 2) +texture = ExtResource("6_cvg1r") +centered = false +offset = Vector2(0, -100) + +[node name="background layer 3" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(18, -713) +motion_scale = Vector2(0.25, 0.25) +motion_mirroring = Vector2(5424, 0) + +[node name="Kenney assets" type="Node2D" parent="ParallaxBackground/background layer 3"] +position = Vector2(0, -39) +scale = Vector2(1.2, 1.2) + +[node name="hills" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.709819, 0.713726, 0.717632, 1) +z_index = -300 +position = Vector2(0, 1420) +scale = Vector2(3, 3) +texture = ExtResource("7_x3yi1") +centered = false +offset = Vector2(0, -100) + +[node name="hills 1" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.709819, 0.713726, 0.717632, 1) +z_index = -300 +position = Vector2(2999, 1420) +scale = Vector2(3, 3) +texture = ExtResource("8_kcbkm") +centered = false +offset = Vector2(0, -100) + +[node name="tree" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(376, 1136) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree2" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(312, 1160) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree3" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(216, 1072) +scale = Vector2(1.46078, 0.957947) +texture = ExtResource("10_svwgx") + +[node name="tree4" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(104, 1128) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree5" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(1640, 1088) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree6" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(2456, 1256) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree7" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(2392, 1288) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree8" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(2568, 1200) +scale = Vector2(1.33805, 0.991627) +texture = ExtResource("11_blrv5") + +[node name="tree9" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(3376, 1224) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="tree10" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(3488, 1248) +scale = Vector2(0.939717, 0.72619) +texture = ExtResource("12_fx2ph") + +[node name="tree11" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.651194, 0.592081, 0.635554, 1) +z_index = -300 +position = Vector2(4912, 1078.25) +scale = Vector2(2.33333, 1.64286) +texture = ExtResource("9_m1imc") + +[node name="Sprite2D" type="Sprite2D" parent="ParallaxBackground/background layer 3/Kenney assets"] +modulate = Color(0.584268, 0.659007, 0.690272, 1) +z_index = -300 +position = Vector2(3069.17, 2218.33) +scale = Vector2(12, 3) +texture = ExtResource("13_lbo36") + +[node name="JelenaMockupBg01" type="Sprite2D" parent="ParallaxBackground/background layer 3"] +visible = false +position = Vector2(3552, 1296) +scale = Vector2(3, 3.062) +texture = ExtResource("14_6f1e2") + +[node name="background layer 4" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(0, -82) +motion_scale = Vector2(0.5, 0.5) +motion_mirroring = Vector2(10480, 0) + +[node name="Kenney Assets" type="Node2D" parent="ParallaxBackground/background layer 4"] +visible = false + +[node name="hills" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.525643, 0.556909, 0.560815, 1) +position = Vector2(0, 1420) +scale = Vector2(4, 4) +texture = ExtResource("7_x3yi1") +centered = false +offset = Vector2(-200, -80) + +[node name="hills 1" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.525643, 0.556909, 0.560815, 1) +position = Vector2(3999, 1420) +scale = Vector2(4, 4) +texture = ExtResource("8_kcbkm") +centered = false +offset = Vector2(-200, -80) + +[node name="tree" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(128, 784) +scale = Vector2(5.11066, 3.99823) +texture = ExtResource("15_2x6x8") + +[node name="tree2" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(976, 952) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") + +[node name="tree9" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(1160, 976) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") +flip_h = true + +[node name="tree3" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(1368, 800) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") + +[node name="tree4" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(2328, 880) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") + +[node name="tree5" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(3112, 944) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") + +[node name="tree6" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(4248, 960) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") + +[node name="tree10" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(5376, 848) +scale = Vector2(3.7465, 2.76803) +texture = ExtResource("15_2x6x8") +flip_h = true + +[node name="tree11" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(5624, 976) +scale = Vector2(2.93619, 1.96107) +texture = ExtResource("15_2x6x8") + +[node name="tree12" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(5856.97, 753.531) +scale = Vector2(3.3702, 3.05266) +texture = ExtResource("15_2x6x8") + +[node name="tree13" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(6888, 912) +scale = Vector2(3.3702, 3.05266) +texture = ExtResource("15_2x6x8") +flip_h = true + +[node name="tree14" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(7088.48, 752.766) +scale = Vector2(3.69909, 3.46732) +texture = ExtResource("15_2x6x8") + +[node name="tree15" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(7224, 888) +scale = Vector2(3.1922, 3.25497) +texture = ExtResource("15_2x6x8") + +[node name="tree7" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(4392, 1152) +scale = Vector2(2.55123, 1.88928) +texture = ExtResource("15_2x6x8") +flip_h = true + +[node name="tree8" type="Sprite2D" parent="ParallaxBackground/background layer 4/Kenney Assets"] +modulate = Color(0.431357, 0.282353, 0.415717, 1) +position = Vector2(2944, 992) +scale = Vector2(3.008, 2.76803) +texture = ExtResource("15_2x6x8") + +[node name="JelenaMockupBg02" type="Sprite2D" parent="ParallaxBackground/background layer 4"] +z_index = -200 +material = SubResource("ShaderMaterial_ruj2u") +position = Vector2(2668, 726) +scale = Vector2(2.75, 2.75) +texture = ExtResource("17_40bfw") + +[node name="JelenaMockupBg03" type="Sprite2D" parent="ParallaxBackground/background layer 4"] +z_index = -200 +material = SubResource("ShaderMaterial_ruj2u") +position = Vector2(7923, 727) +scale = Vector2(2.75, 2.75) +texture = ExtResource("17_40bfw") + +[node name="back back trees layer" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(0, -256) +motion_scale = Vector2(0.7, 0.7) +motion_mirroring = Vector2(9965, 0) + +[node name="hills" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +modulate = Color(0.345703, 0.360648, 0.242876, 1) +position = Vector2(993, 1576) +scale = Vector2(5, 5) +texture = ExtResource("7_x3yi1") +centered = false +offset = Vector2(-200, -80) + +[node name="hills 1" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +modulate = Color(0.345703, 0.360648, 0.242876, 1) +position = Vector2(5961, 1582) +scale = Vector2(5, 5) +texture = ExtResource("8_kcbkm") +centered = false +offset = Vector2(-200, -80) + +[node name="tree" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(3017.3, 536.15) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(770, 3, 304, 979) + +[node name="tree2" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(1807.5, 1408) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(399, 420, 228, 493) + +[node name="tree4" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(3321.3, 600.15) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(1770, -4, 289, 930) + +[node name="tree11" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(460, 622) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(1770, -4, 289, 930) + +[node name="tree5" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(5081.3, 696.15) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(2283, 2, 186, 840) + +[node name="tree10" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(8470, 694) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(2283, 2, 186, 840) + +[node name="tree3" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(6596.8, 1566.35) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(399, 420, 228, 493) + +[node name="tree8" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(8110.6, 758.5) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(1770, -4, 289, 930) + +[node name="tree9" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(10240, 850) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(2283, 2, 186, 840) + +[node name="tree6" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(5641.3, 1168.15) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(2609, 434, 304, 467) + +[node name="tree7" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(5161.3, 608.15) +scale = Vector2(1.7, 1.7) +texture = ExtResource("18_uik6u") +region_enabled = true +region_rect = Rect2(3111, -4, 167, 949) + +[node name="bush" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(3239.5, 1288) +texture = ExtResource("19_edja8") +region_enabled = true +region_rect = Rect2(149, 15, 464, 478) + +[node name="bush2" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(1791.5, 1448) +texture = ExtResource("19_edja8") +flip_h = true +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush3" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(1255.5, 1392) +texture = ExtResource("19_edja8") +flip_h = true +region_enabled = true +region_rect = Rect2(0, 604, 248, 228) + +[node name="bush4" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(5471.5, 1432) +texture = ExtResource("19_edja8") +flip_h = true +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush5" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(5007.5, 1312) +texture = ExtResource("19_edja8") +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush6" type="Sprite2D" parent="ParallaxBackground/back back trees layer"] +material = SubResource("ShaderMaterial_q1iw4") +position = Vector2(3583.5, 1248) +scale = Vector2(0.575, 0.575) +texture = ExtResource("19_edja8") +flip_h = true +region_enabled = true +region_rect = Rect2(358, 523, 345, 289) + +[node name="back tree bois layer 5" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(28, -28) +motion_mirroring = Vector2(10000, 0) + +[node name="tree" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(1483.7, 800) +scale = Vector2(1.6, 1.6) +texture = ExtResource("20_pxlql") +region_enabled = true +region_rect = Rect2(-2, -5, 911, 1386) + +[node name="tree2" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(771.7, 664) +scale = Vector2(1.6, 1.6) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(0, 4, 604, 1363) + +[node name="tree3" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(1763.7, 728) +scale = Vector2(1.6, 1.6) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(626, -4, 711, 1519) + +[node name="tree12" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(9464, 731) +scale = Vector2(1.6, 1.6) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(626, -4, 711, 1519) + +[node name="tree4" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(2939.7, 752) +scale = Vector2(1.8, 1.8) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(1504, -2, 402, 1124) + +[node name="tree5" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(3683.7, 800) +scale = Vector2(1.8, 1.8) +texture = ExtResource("20_pxlql") +region_enabled = true +region_rect = Rect2(927, -1, 736, 1294) + +[node name="tree6" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(115.7, 608) +scale = Vector2(1.8, 1.8) +texture = ExtResource("20_pxlql") +region_enabled = true +region_rect = Rect2(1834, -5, 733, 1360) + +[node name="tree7" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(6259.7, 728) +scale = Vector2(1.6, 1.6) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(626, -4, 711, 1519) + +[node name="tree8" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(7435.7, 752) +scale = Vector2(1.8, 1.8) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(1504, -2, 402, 1124) + +[node name="tree11" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(9092, 636) +scale = Vector2(1.8, 1.8) +texture = ExtResource("21_mlqvj") +region_enabled = true +region_rect = Rect2(1504, -2, 402, 1124) + +[node name="tree9" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(8179.7, 800) +scale = Vector2(1.8, 1.8) +texture = ExtResource("20_pxlql") +region_enabled = true +region_rect = Rect2(927, -1, 736, 1294) + +[node name="tree10" type="Sprite2D" parent="ParallaxBackground/back tree bois layer 5"] +modulate = Color(0.674561, 0.721424, 0.744786, 1) +z_index = 1 +position = Vector2(4611.7, 608) +scale = Vector2(1.8, 1.8) +texture = ExtResource("20_pxlql") +region_enabled = true +region_rect = Rect2(1834, -5, 733, 1360) + +[node name="sunflower field" type="ParallaxLayer" parent="ParallaxBackground"] +visible = false +motion_mirroring = Vector2(3779, 0) + +[node name="Sonnenblumeseamless" type="Sprite2D" parent="ParallaxBackground/sunflower field"] +z_index = -50 +position = Vector2(1892, 1863) +texture = ExtResource("22_22c4u") + +[node name="Sonnenblumeseamless2" type="Sprite2D" parent="ParallaxBackground/sunflower field"] +z_index = -50 +position = Vector2(9411, 1863) +texture = ExtResource("22_22c4u") + +[node name="ground layer" type="ParallaxLayer" parent="ParallaxBackground"] +position = Vector2(80, 208) +motion_mirroring = Vector2(8192, 0) + +[node name="floortile00" type="Sprite2D" parent="ParallaxBackground/ground layer"] +z_index = -10 +texture_repeat = 2 +material = SubResource("ShaderMaterial_k0jkw") +position = Vector2(3888, 2688) +scale = Vector2(16, 5.48) +texture = SubResource("NoiseTexture2D_pjpt5") + +[node name="ParalaxForeground" type="ParallaxBackground" parent="."] +layer = 1 + +[node name="fg1" type="ParallaxLayer" parent="ParalaxForeground"] +position = Vector2(-897, -245) +motion_scale = Vector2(1.2, 1.2) +motion_mirroring = Vector2(8192, 0) + +[node name="TreeA4" type="Sprite2D" parent="ParalaxForeground/fg1"] +z_index = 120 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9188, 5991) +scale = Vector2(3.26718, 4.50965) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(0, 0, 1405.76, 1244) + +[node name="TreeA5" type="Sprite2D" parent="ParalaxForeground/fg1"] +modulate = Color(0.865081, 0.854544, 0.930309, 1) +z_index = 120 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(14366, 5831) +scale = Vector2(3.26718, 4.50965) +texture = ExtResource("35_g3bna") +flip_h = true +region_enabled = true +region_rect = Rect2(0, 0, 1405.76, 1244) + +[node name="YSorted" type="Node2D" parent="."] +z_index = 1 +y_sort_enabled = true + +[node name="Vesna" parent="YSorted" instance=ExtResource("24_ffcio")] +position = Vector2(8202, 1950) +_hoe = ExtResource("25_3h260") +_wateringCan = ExtResource("26_1bhpp") + +[node name="CharacterBody2D" parent="YSorted/Vesna" index="0"] +y_sort_enabled = true + +[node name="visuals" parent="YSorted/Vesna/CharacterBody2D" index="1"] +y_sort_enabled = true + +[node name="Animated Sprites" parent="YSorted/Vesna/CharacterBody2D/visuals" index="0"] +y_sort_enabled = true +animation = &"diagonal item" +frame_progress = 0.0 + +[node name="WateringCanUI" parent="YSorted/Vesna/CharacterBody2D" index="2" node_paths=PackedStringArray("_stages")] +_stages = [null, null, null, null, null, null] + +[node name="ForestVisuals" type="Node2D" parent="YSorted"] +y_sort_enabled = true +position = Vector2(-60, -250) + +[node name="Static" type="Node2D" parent="YSorted/ForestVisuals"] +y_sort_enabled = true +position = Vector2(-8213, 84) + +[node name="greenery" type="Node2D" parent="YSorted/ForestVisuals/Static"] +y_sort_enabled = true + +[node name="left side" type="Node2D" parent="YSorted/ForestVisuals/Static/greenery"] + +[node name="bush" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(1, 0.86, 0.86, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(12572, 2621.14) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush5" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(12569, 3624.14) +scale = Vector2(-2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush6" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(12361, 3147) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush7" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(1, 0.86, 0.86, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(11020, 2268.14) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush8" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(11265, 2268.14) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush9" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(11376, 2268.14) +scale = Vector2(-1.86739, 2.34145) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(13069, 2044) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -196) +region_enabled = true +region_rect = Rect2(1699, 76, 280, 230) + +[node name="bush4" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(16878, 2099) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(0, 604, 248, 228) + +[node name="bush10" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(7757, 2032) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush11" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(8891, 2100) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1464, 419, 144, 115) + +[node name="bush12" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(1, 0.86, 0.86, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9170, 2052) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1699, 76, 280, 230) + +[node name="bush13" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(12972, 2953) +scale = Vector2(-2.82886, 2.51195) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1699, 76, 280, 230) + +[node name="bush14" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(14232, 2419) +scale = Vector2(-5.54387, 3.80466) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush15" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(1, 0.86, 0.86, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(13382, 2574) +scale = Vector2(3.21806, 3.18583) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush16" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(14148, 1749) +scale = Vector2(-2.40318, 3.59175) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush17" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9556, 2071) +scale = Vector2(-2.40318, 3.59175) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush18" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9887, 2216) +scale = Vector2(-1.87764, 2.59175) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush19" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10074, 2216) +scale = Vector2(1.53273, 1.82378) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush20" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10217, 2026) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush21" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10721, 2026) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush22" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(13292, 2026) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush25" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(12369, 2026) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush26" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(1, 0.86, 0.86, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(13458, 2026) +scale = Vector2(1.41694, 1.75208) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush27" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(13687, 1938) +scale = Vector2(1.40272, 1.38546) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(0, 604, 248, 228) + +[node name="bush23" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +z_index = 1 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(15022, 3301) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush24" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +z_index = 2 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(15973, 3380) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1464, 419, 144, 115) + +[node name="bush3" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/left side"] +modulate = Color(1, 0.86, 0.86, 1) +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(14558, 2508) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -50) +region_enabled = true +region_rect = Rect2(1464, 419, 144, 115) + +[node name="right side" type="Node2D" parent="YSorted/ForestVisuals/Static/greenery"] +y_sort_enabled = true +position = Vector2(13188, 30) + +[node name="bush" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(4360, 2049) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush5" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(3138, 3318) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(1.596, -114.034) +flip_h = true +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush6" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(5757, 4296) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush7" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(5051, 2217) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush8" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(4008, 2250) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush9" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(5325, 2263) +scale = Vector2(-1.86739, 2.34145) +texture = ExtResource("19_edja8") +offset = Vector2(0, -237) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +modulate = Color(0.886275, 0.945098, 0.945098, 1) +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(2792, 2938) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(-14, -100.5) +region_enabled = true +region_rect = Rect2(1699, 76, 280, 230) + +[node name="bush4" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(7361, 2026) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(0, 604, 248, 228) + +[node name="bush10" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(7757, 2032) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush28" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(6412, 4038) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(0, 604, 248, 228) + +[node name="bush29" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(7690, 4131) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush11" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(8981, 2112) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1464, 419, 144, 115) + +[node name="bush12" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9208, 2026) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1699, 76, 280, 230) + +[node name="bush13" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(8235, 4262) +scale = Vector2(-2.82886, 2.51195) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1699, 76, 280, 230) + +[node name="bush14" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(8827, 4460) +scale = Vector2(-5.54387, 3.80466) +texture = ExtResource("19_edja8") +offset = Vector2(0, -151.895) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush15" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9713, 4457) +scale = Vector2(3.21806, 3.18583) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush16" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(3348, 2074) +scale = Vector2(-2.40318, 3.59175) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush17" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9556, 2071) +scale = Vector2(-2.40318, 3.59175) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush18" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(9887, 2216) +scale = Vector2(-1.87764, 2.59175) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush19" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10074, 2216) +scale = Vector2(1.53273, 1.82378) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush20" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10217, 2026) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush21" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10721, 2026) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush22" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10802, 2596) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush25" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10802, 2779) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush26" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10963, 3651) +scale = Vector2(1.41694, 1.75208) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1368, 673, 186, 136) + +[node name="bush27" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +modulate = Color(0.8428, 0.8771, 0.98, 1) +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10831, 3016) +scale = Vector2(1.40272, 1.38546) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(0, 604, 248, 228) + +[node name="bush23" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +z_index = 1 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10963, 3820) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1837, 651, 139, 180) + +[node name="bush24" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +z_index = 2 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10831, 2250) +scale = Vector2(-1.93815, 1.5875) +texture = ExtResource("19_edja8") +offset = Vector2(0, -172) +region_enabled = true +region_rect = Rect2(1464, 419, 144, 115) + +[node name="bush3" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/right side"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(6758, 1838) +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(0, -50) +region_enabled = true +region_rect = Rect2(1464, 419, 144, 115) + +[node name="grass" type="Node2D" parent="YSorted/ForestVisuals/Static/greenery"] + +[node name="grass" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(16914, 3590) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(42, 16, 176, 163) + +[node name="grass44" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(20689, 3151) +scale = Vector2(12.2062, 8.82233) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(42, 16, 176, 163) + +[node name="grass57" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(21102, 2021) +scale = Vector2(8.42127, 4.11668) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(42, 16, 176, 163) + +[node name="grass55" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(18349, 2842) +scale = Vector2(12.2062, 8.82233) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(42, 16, 176, 163) + +[node name="grass45" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(22621, 2402) +scale = Vector2(9.80195, 6.42344) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(42, 16, 176, 163) + +[node name="grass46" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(22198, 3694) +scale = Vector2(12.2062, 8.82233) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(42, 16, 176, 163) + +[node name="grass13" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(11998, 2044.14) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(332, 194, 179, 154) + +[node name="grass14" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(11275, 2550.14) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(22, 226, 197, 145) + +[node name="grass15" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(13031, 3052) +scale = Vector2(9.0736, 7.40714) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(22, 226, 197, 145) + +[node name="grass16" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(11206, 2950) +scale = Vector2(5.58376, 4.48372) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(305, 25, 186, 153) + +[node name="grass18" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.78, 0.78, 0.78, 1) +z_index = -5 +position = Vector2(13063, 3166.14) +scale = Vector2(5.58376, 2.56212) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(305, 25, 186, 153) + +[node name="grass19" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(12569, 3487.14) +scale = Vector2(5.58376, 4.48372) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(364, 32, 148, 153) + +[node name="grass20" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(10544, 3050) +scale = Vector2(7.28513, 4.2484) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(364, 32, 148, 153) + +[node name="grass21" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(12718, 3664) +scale = Vector2(7.28513, 6.16997) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(364, 32, 148, 153) + +[node name="grass43" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(15328, 1933) +scale = Vector2(7.28513, 6.16997) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(364, 32, 148, 153) + +[node name="grass22" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.78, 0.78, 0.78, 1) +z_index = -5 +position = Vector2(10844, 2200) +scale = Vector2(7.28513, 4.43792) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(364, 32, 148, 153) + +[node name="grass23" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(10406, 2465) +scale = Vector2(7.28513, 6.16997) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass24" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(11575, 2049) +scale = Vector2(7.28513, 4.46234) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass25" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(7473, 3724) +scale = Vector2(7.28513, 6.16997) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass26" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(7662, 2562) +rotation = 1.57079 +scale = Vector2(7.28513, 6.16997) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass27" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(8802, 3147) +rotation = 1.57079 +scale = Vector2(10.3031, 14.9604) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass17" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(9872, 3341) +rotation = 2.09439 +scale = Vector2(5.58376, 4.48372) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(305, 25, 186, 153) + +[node name="grass2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.78, 0.78, 0.78, 1) +z_index = -5 +position = Vector2(8846.24, 1965) +scale = Vector2(8.56132, 4.49734) +texture = ExtResource("28_ejigw") +region_enabled = true +region_rect = Rect2(332, 194, 179, 154) + +[node name="grass3" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(18189, 1960) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("30_cmmg6") +region_enabled = true +region_rect = Rect2(7, 4, 256, 220) + +[node name="grass53" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(19296, 2343) +scale = Vector2(4.5677, 5.4298) +texture = ExtResource("30_cmmg6") +region_enabled = true +region_rect = Rect2(7, 4, 256, 220) + +[node name="grass54" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(19369, 3302) +scale = Vector2(4.5677, 5.4298) +texture = ExtResource("30_cmmg6") +region_enabled = true +region_rect = Rect2(7, 4, 256, 220) + +[node name="grass38" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(19442, 1960) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("30_cmmg6") +region_enabled = true +region_rect = Rect2(7, 59, 257, 157) + +[node name="grass32" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(16284, 1836) +scale = Vector2(9.30275, 4.60296) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(147, 255, 218, 128) + +[node name="grass33" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(14152, 2798) +scale = Vector2(6.8578, 6.10617) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(147, 255, 218, 128) + +[node name="grass41" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(15980, 2942) +scale = Vector2(6.8578, 6.10617) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(307, 48, 183, 193) + +[node name="grass34" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(13337, 1931) +scale = Vector2(5.22018, 6.29687) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(147, 255, 218, 128) + +[node name="grass35" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.78, 0.78, 0.78, 1) +z_index = -5 +position = Vector2(14537, 3031) +scale = Vector2(5.22018, 6.29687) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(147, 255, 218, 128) + +[node name="grass36" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(14537, 3570) +scale = Vector2(5.1948, 5.15362) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(307, 48, 183, 193) + +[node name="grass37" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(15217, 3630) +scale = Vector2(5.1948, 5.15362) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(7, 4, 267, 239) + +[node name="grass4" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(23612, 2281) +rotation = 1.57079 +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(7, 4, 267, 239) + +[node name="grass40" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(23915, 3644) +rotation = 3.40339 +scale = Vector2(5.52625, 5.81879) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(317, 219, 185, 159) + +[node name="grass11" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(20024, 2147) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("31_spe7q") +region_enabled = true +region_rect = Rect2(147, 255, 218, 128) + +[node name="grass39" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(21726, 1867) +scale = Vector2(5.77602, 6.94382) +texture = ExtResource("32_inmkn") +region_enabled = true +region_rect = Rect2(21, 222, 491, 89) + +[node name="grass12" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(23041, 2105) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass47" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(17785, 3733) +scale = Vector2(2.28071, 4.49236) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass48" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(20007, 3082) +scale = Vector2(2.28071, 4.49236) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass49" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(17500, 2268) +scale = Vector2(2.28071, 4.49236) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass50" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(16938, 2944) +scale = Vector2(2.28071, 4.49236) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass51" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(21787, 2266) +scale = Vector2(2.28071, 4.49236) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass52" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(23634, 2698) +scale = Vector2(5.35495, 4.49236) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass5" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(15375, 3149) +scale = Vector2(5.77602, 3.87779) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(16, 17, 290, 183) + +[node name="grass6" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.78, 0.78, 0.78, 1) +z_index = -5 +position = Vector2(13784.1, 1946) +scale = Vector2(7.39612, 3.87779) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(317, 219, 185, 159) + +[node name="grass30" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(14034, 2216) +scale = Vector2(5.5153, 6.5842) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(16, 17, 290, 183) + +[node name="grass56" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = 99 +position = Vector2(12630, 3276) +scale = Vector2(3.32661, 2.09538) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(16, 17, 290, 183) + +[node name="grass31" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(15774, 3374) +scale = Vector2(4.53474, 4.07413) +texture = ExtResource("30_cmmg6") +region_enabled = true +region_rect = Rect2(22, 72, 489, 274) + +[node name="grass29" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(12637, 1962) +scale = Vector2(5.91724, 3.87779) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(29, 204, 219, 159) + +[node name="grass7" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(10546.9, 2035.5) +scale = Vector2(5.38464, 7.05479) +texture = ExtResource("32_inmkn") +region_enabled = true +region_rect = Rect2(32, 32, 445, 73) + +[node name="grass28" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(10321, 1770) +scale = Vector2(5.38464, 7.05479) +texture = ExtResource("32_inmkn") +region_enabled = true +region_rect = Rect2(21, 222, 491, 89) + +[node name="grass8" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.954868, 0.882599, 0.798501, 1) +z_index = -5 +position = Vector2(7291, 2809) +scale = Vector2(3, 3) +texture = ExtResource("33_xtiat") +region_enabled = true +region_rect = Rect2(14, 38, 295, 165) + +[node name="grass9" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +modulate = Color(0.856076, 0.855033, 0.937369, 1) +z_index = -5 +position = Vector2(7798.25, 1896.75) +scale = Vector2(3.76102, 3.55455) +texture = ExtResource("30_cmmg6") +region_enabled = true +region_rect = Rect2(14, 38, 295, 165) + +[node name="grass10" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/grass"] +z_index = -5 +position = Vector2(12419, 3510) +rotation = -1.57079 +scale = Vector2(3, 11.6269) +texture = ExtResource("32_inmkn") +region_enabled = true +region_rect = Rect2(21, 222, 491, 89) + +[node name="trees" type="Node2D" parent="YSorted/ForestVisuals/Static/greenery"] + +[node name="FallenTree2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 100 +position = Vector2(17948, 4306) +rotation = -0.535782 +scale = Vector2(1.18331, 1.10418) +texture = ExtResource("34_nykjo") + +[node name="TreeA" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(10549, -11) +scale = Vector2(2.34789, 3.23312) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(0, 0, 1405.76, 1244) + +[node name="TreeA3" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(15814, -1224) +scale = Vector2(3.26718, 4.50965) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(0, 0, 1405.76, 1244) + +[node name="TreeA2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = -1 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(17459, 1356) +scale = Vector2(2.06913, 2.06913) +texture = ExtResource("35_g3bna") +offset = Vector2(-36.7295, -309.308) +region_enabled = true +region_rect = Rect2(0, 0, 1405.76, 1244) + +[node name="TreeB" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(8927, 914) +scale = Vector2(2.7776, 2.91263) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(1419.55, -0.619019, 1148.74, 1222.26) + +[node name="TreeB4" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 100 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(24547, 1408) +scale = Vector2(2.7776, 2.91263) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(1419.55, -0.619019, 1148.74, 1222.26) + +[node name="TreeB2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = -10 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(15223, 1477) +scale = Vector2(2.06913, 2.06913) +texture = ExtResource("35_g3bna") +offset = Vector2(2.4165, -444.148) +region_enabled = true +region_rect = Rect2(1419.55, -0.619019, 1148.74, 1222.26) + +[node name="TreeB3" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = -2 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(22079, 629) +scale = Vector2(2.06913, 2.06913) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(1419.55, -0.619019, 1148.74, 1222.26) + +[node name="TreeC" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 105 +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(15156, 3649) +scale = Vector2(2.06913, 2.06913) +texture = ExtResource("35_g3bna") +region_enabled = true +region_rect = Rect2(2563.7, 8.26111, 1089.01, 1213.38) + +[node name="TreeC2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(19571, -107) +scale = Vector2(3.02154, 3.02987) +texture = ExtResource("35_g3bna") +flip_h = true +region_enabled = true +region_rect = Rect2(2563.7, 8.26111, 1089.01, 1213.38) + +[node name="StompA" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = -10 +position = Vector2(13658, 1226) +texture = ExtResource("36_vwtyh") +region_enabled = true +region_rect = Rect2(0, 0, 754.687, 937.323) + +[node name="StompA2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 100 +position = Vector2(12793, 3481) +scale = Vector2(1.39257, 1.26841) +texture = ExtResource("36_vwtyh") +region_enabled = true +region_rect = Rect2(0, 0, 754.687, 937.323) + +[node name="StompB" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 50 +position = Vector2(13946, 3121) +texture = ExtResource("36_vwtyh") +region_enabled = true +region_rect = Rect2(730.084, 122.266, 1980.43, 840.88) + +[node name="StompB2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 100 +position = Vector2(20561, 4147) +texture = ExtResource("36_vwtyh") +region_enabled = true +region_rect = Rect2(730.084, 122.266, 1980.43, 840.88) + +[node name="StompC" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"] +z_index = 50 +position = Vector2(12726, 3078) +texture = ExtResource("36_vwtyh") +region_enabled = true +region_rect = Rect2(1483.92, 1280.2, 1139.55, 367.598) + +[node name="BorderCollisionBody" type="StaticBody2D" parent="YSorted/ForestVisuals"] + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="YSorted/ForestVisuals/BorderCollisionBody"] +polygon = PackedVector2Array(6564, 1921, 8663, 1938, 15008, 1914, 15121, 2882, 15601, 3074, 15636, 3574, 14122, 3569, 12930, 3737, 11502, 3599, 9887, 3658, 7936, 3924, 7712, 2967, 6529, 2914, 4412, 2953, 3919, 4843, 7970, 4459, 16532, 4289, 16365, 821, 4540, 1141, 4392, 2845, 6329, 2832) + +[node name="Paths" type="Node2D" parent="YSorted"] +y_sort_enabled = true + +[node name="Path0" type="Node2D" parent="YSorted/Paths" node_paths=PackedStringArray("closedVariant", "nextRoomVariant")] +y_sort_enabled = true +position = Vector2(15336, 3044) +script = ExtResource("37_elhbh") +closedVariant = NodePath("PathVariants/Closed") +nextRoomVariant = NodePath("PathVariants/OpenToFightRoom") + +[node name="PathVariants" type="Node2D" parent="YSorted/Paths/Path0"] +y_sort_enabled = true + +[node name="Closed" type="Node2D" parent="YSorted/Paths/Path0/PathVariants"] +visible = false +y_sort_enabled = true + +[node name="Visuals" type="Node2D" parent="YSorted/Paths/Path0/PathVariants/Closed"] +y_sort_enabled = true + +[node name="bush14" type="Sprite2D" parent="YSorted/Paths/Path0/PathVariants/Closed/Visuals"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(-90.0731, 283.561) +rotation = 3.14159 +scale = Vector2(5.54387, -3.80466) +texture = ExtResource("19_edja8") +offset = Vector2(1.06909, -110.777) +flip_h = true +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="Collider" type="StaticBody2D" parent="YSorted/Paths/Path0/PathVariants/Closed"] + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="YSorted/Paths/Path0/PathVariants/Closed/Collider"] +polygon = PackedVector2Array(487, -453, -215, -738, -671, 348, 491, 489) + +[node name="OpenToFightRoom" type="Node2D" parent="YSorted/Paths/Path0/PathVariants"] +y_sort_enabled = true + +[node name="Visuals" type="Node2D" parent="YSorted/Paths/Path0/PathVariants/OpenToFightRoom"] +y_sort_enabled = true + +[node name="bush14" type="Sprite2D" parent="YSorted/Paths/Path0/PathVariants/OpenToFightRoom/Visuals"] +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(304, 1029) +rotation = 3.14159 +scale = Vector2(5.54387, -3.80466) +texture = ExtResource("19_edja8") +offset = Vector2(1.06909, -110.777) +flip_h = true +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="bush15" type="Sprite2D" parent="YSorted/Paths/Path0/PathVariants/OpenToFightRoom/Visuals"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(134, -210) +rotation = 3.14159 +scale = Vector2(2, 2) +texture = ExtResource("19_edja8") +offset = Vector2(-6.4563, 109.743) +flip_v = true +region_enabled = true +region_rect = Rect2(841.143, 539.388, 222.154, 270.872) + +[node name="NextRoomTrigger" type="Area2D" parent="YSorted/Paths/Path0/PathVariants/OpenToFightRoom"] +collision_mask = 4 +script = ExtResource("37_3y3c4") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="YSorted/Paths/Path0/PathVariants/OpenToFightRoom/NextRoomTrigger"] +position = Vector2(215, -33) +shape = SubResource("RectangleShape2D_ir2xa") + +[node name="Path1" type="Node2D" parent="YSorted/Paths" node_paths=PackedStringArray("closedVariant", "nextRoomVariant")] +y_sort_enabled = true +position = Vector2(6688, 2187) +script = ExtResource("37_elhbh") +pathId = 1 +closedVariant = NodePath("PathVariants/Closed") +nextRoomVariant = NodePath("PathVariants/OpenToFightRoom") + +[node name="PathVariants" type="Node2D" parent="YSorted/Paths/Path1"] +y_sort_enabled = true + +[node name="Closed" type="Node2D" parent="YSorted/Paths/Path1/PathVariants"] +visible = false +y_sort_enabled = true + +[node name="Visuals" type="Node2D" parent="YSorted/Paths/Path1/PathVariants/Closed"] +y_sort_enabled = true + +[node name="bush14" type="Sprite2D" parent="YSorted/Paths/Path1/PathVariants/Closed/Visuals"] +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(642, -31) +rotation = 3.14159 +scale = Vector2(5.54387, -3.80466) +texture = ExtResource("19_edja8") +offset = Vector2(1.06909, -110.777) +flip_h = true +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="FallenTree" type="Sprite2D" parent="YSorted/Paths/Path1/PathVariants/Closed/Visuals"] +z_index = 50 +position = Vector2(-120, 671) +texture = ExtResource("34_nykjo") + +[node name="grass42" type="Sprite2D" parent="YSorted/Paths/Path1/PathVariants/Closed/Visuals"] +z_index = -5 +position = Vector2(1264, -69.0005) +scale = Vector2(7.28513, 6.16997) +texture = ExtResource("29_pjemw") +region_enabled = true +region_rect = Rect2(364, 32, 148, 153) + +[node name="Collider" type="StaticBody2D" parent="YSorted/Paths/Path1/PathVariants/Closed"] + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="YSorted/Paths/Path1/PathVariants/Closed/Collider"] +position = Vector2(487, 62) +polygon = PackedVector2Array(664, -692, -812, -717, -1033, 505, 380, 465) + +[node name="OpenToFightRoom" type="Node2D" parent="YSorted/Paths/Path1/PathVariants"] +y_sort_enabled = true + +[node name="Visuals" type="Node2D" parent="YSorted/Paths/Path1/PathVariants/OpenToFightRoom"] +y_sort_enabled = true + +[node name="bush14" type="Sprite2D" parent="YSorted/Paths/Path1/PathVariants/OpenToFightRoom/Visuals"] +z_index = 100 +y_sort_enabled = true +material = SubResource("ShaderMaterial_yvxfs") +position = Vector2(559, -459) +rotation = 3.14159 +scale = Vector2(5.54387, -3.80466) +texture = ExtResource("19_edja8") +offset = Vector2(1.06909, -110.777) +flip_h = true +region_enabled = true +region_rect = Rect2(130, 0, 201, 278) + +[node name="NextRoomTrigger" type="Area2D" parent="YSorted/Paths/Path1/PathVariants/OpenToFightRoom"] +collision_mask = 4 +script = ExtResource("37_3y3c4") +pathIndex = 1 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="YSorted/Paths/Path1/PathVariants/OpenToFightRoom/NextRoomTrigger"] +position = Vector2(-335, 18) +shape = SubResource("RectangleShape2D_ir2xa") + +[node name="EnemyGroupSpawns" type="Node2D" parent="YSorted"] +position = Vector2(11116, 2546) + +[node name="Spawn1" type="Node2D" parent="YSorted/EnemyGroupSpawns"] +position = Vector2(-1008, -358) + +[node name="Spawn2" type="Node2D" parent="YSorted/EnemyGroupSpawns"] +position = Vector2(1679, -434) + +[node name="Spawn3" type="Node2D" parent="YSorted/EnemyGroupSpawns"] +position = Vector2(1560, 422) + +[node name="Spawn4" type="Node2D" parent="YSorted/EnemyGroupSpawns"] +position = Vector2(-1127, 671) + +[node name="FightSceneSwitcher" parent="." node_paths=PackedStringArray("_sceneRoot") instance=ExtResource("40_elhbh")] +unique_name_in_owner = true +_sceneRoot = NodePath("..") + +[node name="FightSceneSetup" type="Node" parent="." node_paths=PackedStringArray("_enemyGroupSpawns", "_fightSceneSwitcher")] +script = ExtResource("40_cvg1r") +_enemyGroupSpawns = [NodePath("../YSorted/EnemyGroupSpawns/Spawn1"), NodePath("../YSorted/EnemyGroupSpawns/Spawn2"), NodePath("../YSorted/EnemyGroupSpawns/Spawn3"), NodePath("../YSorted/EnemyGroupSpawns/Spawn4")] +_roamingEnemyGroupPrefab = ExtResource("41_cvg1r") +_fightSceneSwitcher = NodePath("../FightSceneSwitcher") + +[editable path="YSorted/Vesna"] diff --git a/scenes/Babushka_scene_forest_fight_1_2d.tscn b/scenes/Babushka_scene_forest_fight_1_2d.tscn index e00c3f9..860d079 100644 --- a/scenes/Babushka_scene_forest_fight_1_2d.tscn +++ b/scenes/Babushka_scene_forest_fight_1_2d.tscn @@ -24,12 +24,12 @@ [ext_resource type="Texture2D" uid="uid://bmjjfd5ngptxe" path="res://art/nature/baum märz 2025/backtreebois team kennedy.png" id="23_uhyft"] [ext_resource type="Texture2D" uid="uid://bcw6oeovkmiup" path="res://art/nature/baum märz 2025/sonnenblumeseamless.png" id="24_3fmyy"] [ext_resource type="Shader" uid="uid://xnky830dtfsn" path="res://shader/repeat_texture.gdshader" id="25_sgom5"] -[ext_resource type="Script" uid="uid://di0xxwfw43m0i" path="res://scripts/CSharp/Common/Fight/FightStarter.cs" id="26_gg38r"] -[ext_resource type="PackedScene" uid="uid://hk8ahyp6dgl6" path="res://prefabs/fight/fight_base_scene.tscn" id="27_55b52"] -[ext_resource type="PackedScene" uid="uid://bp64p6y72j71w" path="res://prefabs/fight/fighters/enemy_blob_fighter.tscn" id="27_hfhye"] +[ext_resource type="Script" uid="uid://di0xxwfw43m0i" path="res://scripts/CSharp/Common/FightOld/FightStarter.cs" id="26_gg38r"] +[ext_resource type="PackedScene" uid="uid://hk8ahyp6dgl6" path="res://prefabs/fightOld/fight_base_scene.tscn" id="27_55b52"] +[ext_resource type="PackedScene" uid="uid://bp64p6y72j71w" path="res://prefabs/fightOld/fighters/enemy_blob_fighter.tscn" id="27_hfhye"] [ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Player2D.tscn" id="29_3jjxs"] [ext_resource type="PackedScene" uid="uid://ddpl8cbck7e6s" path="res://prefabs/characters/Chugar.tscn" id="29_26tkn"] -[ext_resource type="PackedScene" uid="uid://cr66tpdr5rma5" path="res://prefabs/fight/fighters/enemy_mavkha_fighter.tscn" id="29_hfhye"] +[ext_resource type="PackedScene" uid="uid://cr66tpdr5rma5" path="res://prefabs/fightOld/fighters/enemy_mavkha_fighter.tscn" id="29_hfhye"] [ext_resource type="Resource" uid="uid://dlcmqfjvgphqu" path="res://resources/items/rake.tres" id="30_l10vl"] [ext_resource type="Resource" uid="uid://cndd64batns31" path="res://resources/items/wateringcan.tres" id="31_c2gvt"] [ext_resource type="Texture2D" uid="uid://dyueumlr5ltvr" path="res://art/nature/baum märz 2025/megaeichel megaast.png" id="37_gg38r"] diff --git a/scenes/SceneTransition.tscn b/scenes/SceneTransition.tscn index 6073ff3..226f888 100644 --- a/scenes/SceneTransition.tscn +++ b/scenes/SceneTransition.tscn @@ -105,6 +105,7 @@ _data = { } [node name="SceneTransition" type="CanvasLayer" node_paths=PackedStringArray("animationPlayer")] +layer = 100 script = ExtResource("1_e0bkc") animationPlayer = NodePath("SceneFadeAnimation") diff --git a/scenes/testing/Babushka_scene_minigame_test.tscn b/scenes/testing/Babushka_scene_minigame_test.tscn new file mode 100644 index 0000000..a53c4d9 --- /dev/null +++ b/scenes/testing/Babushka_scene_minigame_test.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=3 format=3 uid="uid://c1dsbe7ryaije"] + +[ext_resource type="Script" uid="uid://iv0dbf32bfw1" path="res://scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs" id="1_fwf73"] +[ext_resource type="PackedScene" uid="uid://bydwj3pbvqrhb" path="res://prefabs/minigame/minigame.tscn" id="1_wh3re"] + +[node name="BabushkaSceneMinigameTest" type="Node2D" node_paths=PackedStringArray("_minigameController")] +script = ExtResource("1_fwf73") +_minigameController = NodePath("Minigame") + +[node name="Minigame" parent="." instance=ExtResource("1_wh3re")] + +[node name="Camera2D" type="Camera2D" parent="."] diff --git a/scripts/CSharp/Common/Camera/CameraController.cs b/scripts/CSharp/Common/Camera/CameraController.cs index 4a590b3..661e65c 100644 --- a/scripts/CSharp/Common/Camera/CameraController.cs +++ b/scripts/CSharp/Common/Camera/CameraController.cs @@ -18,10 +18,13 @@ public partial class CameraController : Camera2D [Export] private Node2D _followNode; - public FightInstance? fightToShow; + public FightHappening? fightToShow; + public override void _Process(double delta) { - this.GlobalPosition = fightToShow?.camPositionNode.GlobalPosition ?? _followNode.GlobalPosition; + this.GlobalPosition = /*fightToShow?.camPositionNode.GlobalPosition ??*/ _followNode.GlobalPosition; + } + } diff --git a/scripts/CSharp/Common/CharacterControls/InteractionArea2D.cs b/scripts/CSharp/Common/CharacterControls/InteractionArea2D.cs index fab4097..6fcf84f 100644 --- a/scripts/CSharp/Common/CharacterControls/InteractionArea2D.cs +++ b/scripts/CSharp/Common/CharacterControls/InteractionArea2D.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Babushka.scripts.CSharp.Common.Services; using Godot; @@ -11,19 +12,21 @@ public partial class InteractionArea2D : Node2D [Export] private bool _active = true; [Export] private bool _useOutline = true; [Export] private ShaderMaterial _outlineMaterial; - [Export] private bool _useSprite = true; - [Export] private CanvasItem _spriteToOutline; + [Export] private CanvasItem? _spriteToOutline; // keep to not break old usages. TODO: remove later + [Export] private CanvasItem[] _spritesToOutline; [Export] private bool _showLabel = true; [Export] private int _id = -1; // TODO: remove - private Material _backupMaterial; + private Material[] _backupMaterials; + [Signal] public delegate void InteractedToolEventHandler(int id); // TODO: remove + [Signal] public delegate void InteractedEventHandler(); public bool IsActive { get => _active; - set => _active = value; + set => _active = value; } public void SetActiveInverse(bool active) @@ -33,52 +36,66 @@ public partial class InteractionArea2D : Node2D public override void _Ready() { - if (_useSprite && _useOutline) + if (_useOutline) { try { - _backupMaterial = _spriteToOutline.Material; + // support old implementations of the script. If the sprite to outline is set, add it to the array + if (_spriteToOutline != null) + { + Array.Resize(ref _spritesToOutline, _spritesToOutline.Length + 1); + _spritesToOutline[^1] = _spriteToOutline; + } + + _backupMaterials = _spritesToOutline.Select(s => s.Material).ToArray(); } - catch(Exception exception) + catch (Exception exception) { GD.PrintErr($"No sprite to outline found on: {GetParent().Name}" + exception.Message); } } } - + public void OnPlayerEntered(Node2D player) { if (!_active || !InputService.Instance.InputEnabled) return; - - if(_showLabel) + + if (_showLabel) _label.Show(); - - if (!_useSprite || !_useOutline) + + if (!_useOutline) return; - - _spriteToOutline.Material = _outlineMaterial; + + foreach (var sprite in _spritesToOutline) + { + sprite.Material = _outlineMaterial; + } } public void OnPlayerExited(Node2D player) { if (!_active) return; - + _label.Hide(); - if (!_useSprite || !_useOutline) + if (!_useOutline) return; - - _spriteToOutline.Material = _backupMaterial; + + for (var i = 0; i < _spritesToOutline.Length; i++) + { + var sprite = _spritesToOutline[i]; + sprite.Material = _backupMaterials[i]; + } } public override void _Input(InputEvent @event) { - if (!_active || !InputService.Instance.InputEnabled) + if (!_active || !InputService.Instance.InputEnabled) return; - + if (@event.IsAction("interact") && @event.IsPressed()) { TryInteract(); @@ -95,10 +112,16 @@ public partial class InteractionArea2D : Node2D if (_area.HasOverlappingAreas()) { _label.Hide(); - - if (_useSprite && _useOutline) - _spriteToOutline.Material = _backupMaterial; - + + if (_useOutline) + { + for (var i = 0; i < _spritesToOutline.Length; i++) + { + var sprite = _spritesToOutline[i]; + sprite.Material = _backupMaterials[i]; + } + } + EmitSignal(SignalName.InteractedTool, _id); EmitSignal(SignalName.Interacted); } @@ -107,7 +130,7 @@ public partial class InteractionArea2D : Node2D public void SetSpriteActiveState(bool success, int id) // TODO: remove { GD.PrintErr("SetSpriteActiveState is being called."); - if(!_active) + if (!_active) return; } diff --git a/scripts/CSharp/Common/Fight/ActionAnimationController.cs b/scripts/CSharp/Common/Fight/ActionAnimationController.cs new file mode 100644 index 0000000..04621fa --- /dev/null +++ b/scripts/CSharp/Common/Fight/ActionAnimationController.cs @@ -0,0 +1,25 @@ +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class ActionAnimationController : Node +{ + #region Shortcuts + + private FightWorld.FightHappeningData HappeningData => FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + + #endregion + + [Export] private AllFightersVisual _allFightersVisual = null!; + + + public void StateEnter() + { + _ = HappeningData.actionStaging!.AnimateAction(_allFightersVisual); + } + + public void StateExit() + { + + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/ActionAnimationController.cs.uid b/scripts/CSharp/Common/Fight/ActionAnimationController.cs.uid new file mode 100644 index 0000000..b0741bf --- /dev/null +++ b/scripts/CSharp/Common/Fight/ActionAnimationController.cs.uid @@ -0,0 +1 @@ +uid://dtf4ejct4m682 diff --git a/scripts/CSharp/Common/Fight/ActionDetails/MinigameActionDetail.cs b/scripts/CSharp/Common/Fight/ActionDetails/MinigameActionDetail.cs new file mode 100644 index 0000000..903378a --- /dev/null +++ b/scripts/CSharp/Common/Fight/ActionDetails/MinigameActionDetail.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace Babushka.scripts.CSharp.Common.Fight.ActionDetails; + +public class MinigameActionDetail : FighterAction.FighterActionDetail +{ + // settings + + + // result + public List? damageHits = null; + + public MinigameActionDetail() + { + } + + public override bool DetailComplete() + { + return damageHits != null; + } + + public void ResetResult() + { + damageHits = null; + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/ActionDetails/MinigameActionDetail.cs.uid b/scripts/CSharp/Common/Fight/ActionDetails/MinigameActionDetail.cs.uid new file mode 100644 index 0000000..8e083f7 --- /dev/null +++ b/scripts/CSharp/Common/Fight/ActionDetails/MinigameActionDetail.cs.uid @@ -0,0 +1 @@ +uid://dtn4la0ycl5wx diff --git a/scripts/CSharp/Common/Fight/ActionDetails/TargetSelectActionDetail.cs b/scripts/CSharp/Common/Fight/ActionDetails/TargetSelectActionDetail.cs new file mode 100644 index 0000000..85097e9 --- /dev/null +++ b/scripts/CSharp/Common/Fight/ActionDetails/TargetSelectActionDetail.cs @@ -0,0 +1,39 @@ +using System; + +namespace Babushka.scripts.CSharp.Common.Fight.ActionDetails; + +public class TargetSelectActionDetail : FighterAction.FighterActionDetail +{ + public enum VisualRange + { + Single + } + + // settings + public required bool selectEnemy; + public required bool selectAlly; + public VisualRange visualRange = VisualRange.Single; + + // result + private FightWorld.Fighter? target; + + public override bool DetailComplete() + { + return target != null; + } + + public void ResetResult() + { + target = null; + } + + public void SetTarget(FightWorld.Fighter fighter) + { + target = fighter; + } + + public FightWorld.Fighter GetTarget() + { + return target ?? throw new InvalidOperationException("No target selected"); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/ActionDetails/TargetSelectActionDetail.cs.uid b/scripts/CSharp/Common/Fight/ActionDetails/TargetSelectActionDetail.cs.uid new file mode 100644 index 0000000..6b7ed4c --- /dev/null +++ b/scripts/CSharp/Common/Fight/ActionDetails/TargetSelectActionDetail.cs.uid @@ -0,0 +1 @@ +uid://e8c8ym0fyprn diff --git a/scripts/CSharp/Common/Fight/Actions/AllyAttackAction.cs b/scripts/CSharp/Common/Fight/Actions/AllyAttackAction.cs new file mode 100644 index 0000000..788661b --- /dev/null +++ b/scripts/CSharp/Common/Fight/Actions/AllyAttackAction.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Fight.ActionDetails; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight.Actions; + +public class AllyAttackAction : FighterAction +{ + // details + public TargetSelectActionDetail targetSelect = new() + { + selectEnemy = true, + selectAlly = false + }; + + public MinigameActionDetail minigameDetail = new(); + + public override Variant> GetAnimationEnd() + { + return 1; + } + + public override bool NextDetail() + { + return !targetSelect.DetailComplete() || !minigameDetail.DetailComplete(); + } + + public override FighterActionDetail CurrentDetail() + { + return targetSelect.DetailComplete() ? minigameDetail : targetSelect; + } + + public override AllyActionButton BindToActionButton() + { + return AllyActionButton.Attack; + } + + public override void Reset() + { + targetSelect.ResetResult(); + minigameDetail.ResetResult(); + } + + public override void ExecuteAction() + { + var totalDamage = minigameDetail.damageHits!.Sum(dh => dh); + targetSelect.GetTarget().AddHealth(-totalDamage); + } + + public override async Task AnimateAction(AllFightersVisual allFightersVisual) + { + var currentFighter = HappeningData.fighterTurn.Current; + var targetFighter = targetSelect.GetTarget(); + + var currentFighterVisual = allFightersVisual.GetVisualForFighter(currentFighter); + var targetFighterVisual = allFightersVisual.GetVisualForFighter(targetFighter); + + await currentFighterVisual.AnimatePosToTarget(targetFighterVisual); + _ = targetFighterVisual.AnimateHit(); + await currentFighterVisual.AnimatePosToBase(); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/Actions/AllyAttackAction.cs.uid b/scripts/CSharp/Common/Fight/Actions/AllyAttackAction.cs.uid new file mode 100644 index 0000000..1998e81 --- /dev/null +++ b/scripts/CSharp/Common/Fight/Actions/AllyAttackAction.cs.uid @@ -0,0 +1 @@ +uid://c8c4t80bqsja5 diff --git a/scripts/CSharp/Common/Fight/Actions/BlobAttackAction.cs b/scripts/CSharp/Common/Fight/Actions/BlobAttackAction.cs new file mode 100644 index 0000000..bb37064 --- /dev/null +++ b/scripts/CSharp/Common/Fight/Actions/BlobAttackAction.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Util; + +namespace Babushka.scripts.CSharp.Common.Fight.Actions; + +public class BlobAttackAction : FighterAction +{ + public override Variant> GetAnimationEnd() + { + return 1; + } + + public override bool NextDetail() + { + return false; + } + + public override void ExecuteAction() + { + FightWorld.Instance.allyFighters.vesnaFighter.AddHealth(-3); + } + + public override async Task AnimateAction(AllFightersVisual allFightersVisual) + { + var currentFighter = HappeningData.fighterTurn.Current; + var targetFighter = FightWorld.Instance.allyFighters.vesnaFighter; + + var currentFighterVisual = allFightersVisual.GetVisualForFighter(currentFighter); + var targetFighterVisual = allFightersVisual.GetVisualForFighter(targetFighter); + + await currentFighterVisual.AnimatePosToTarget(targetFighterVisual); + _ = targetFighterVisual.AnimateHit(); + await currentFighterVisual.AnimatePosToBase(); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/Actions/BlobAttackAction.cs.uid b/scripts/CSharp/Common/Fight/Actions/BlobAttackAction.cs.uid new file mode 100644 index 0000000..872ca20 --- /dev/null +++ b/scripts/CSharp/Common/Fight/Actions/BlobAttackAction.cs.uid @@ -0,0 +1 @@ +uid://dlik4vktiu7dg diff --git a/scripts/CSharp/Common/Fight/AllFightersVisual.cs b/scripts/CSharp/Common/Fight/AllFightersVisual.cs new file mode 100644 index 0000000..e24f218 --- /dev/null +++ b/scripts/CSharp/Common/Fight/AllFightersVisual.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Babushka.scripts.CSharp.Common.Fight.ActionDetails; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class AllFightersVisual : Node +{ + [ExportCategory("References")] [Export] + private Node2D _allyFighters = null!; + + [Export] private Node2D _enemyFighters = null!; + + // TODO: move type to prefab mapping to Resource + [ExportCategory("Fighter Visual Scenes")] + [Export] private PackedScene _blobFighterVisual = null!; + [Export] private PackedScene _bigBlobFighterVisual = null!; + [Export] private PackedScene _mavkaFighterVisual = null!; + [Export] private PackedScene _yourMomFighterVisual = null!; + [Export] private PackedScene _vesnaFighterVisual = null!; + + [ExportCategory("Settings")] + [Export(PropertyHint.ArrayType)] private float[] _positionDistanceFromCenter = [10, 20, 30]; + + private Dictionary _fighterVisuals = new(); + + #region Shortcuts + + private FightWorld.FightHappeningData HappeningData => + FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + + #endregion + + + #region State Reactions + + public void FightHappeningStateChange(FightHappening.FightState from, FightHappening.FightState to) + { + if (to == FightHappening.FightState.FightersEnterAnim) + { + EnterFighter(); + } + + if (to == FightHappening.FightState.InputActionDetail) + { + if (HappeningData.actionStaging!.CurrentDetail() is TargetSelectActionDetail targetDetail) + { + ShowTargetSelect(targetDetail); + } + } + + if (from == FightHappening.FightState.InputActionDetail) + { + HideTargetSelect(); + } + + if (from == FightHappening.FightState.ActionAnim) + { + _fighterVisuals.Values.ForEach(fv => fv.UpdateHealthBar()); + } + } + + public void EnterFighter() + { + if (HappeningData.fightersEnterStaging == null) + return; + + if (!HappeningData.fightersEnterStaging.HasAnyToExecute()) + return; + + + foreach (var fighter in HappeningData.fightersEnterStaging.enteringEnemyFighters) + { + var packedScene = fighter.type switch + { + FightWorld.Fighter.Type.Blob => _blobFighterVisual, + FightWorld.Fighter.Type.BigBlob => _bigBlobFighterVisual, + FightWorld.Fighter.Type.Mavka => _mavkaFighterVisual, + FightWorld.Fighter.Type.YourMom => _yourMomFighterVisual, + FightWorld.Fighter.Type.Vesna => _vesnaFighterVisual, + _ => throw new ArgumentOutOfRangeException() + }; + + var fighterVisual = packedScene.Instantiate(); + fighterVisual.Initialize(fighter); + _enemyFighters.AddChild(fighterVisual); + fighterVisual.Position = new Vector2(_positionDistanceFromCenter[_enemyFighters.GetChildCount() - 1], 0); + _fighterVisuals.Add(fighter, fighterVisual); + } + + foreach (var fighter in HappeningData.fightersEnterStaging.enteringAllyFighters) + { + var packedScene = fighter.type switch + { + FightWorld.Fighter.Type.Blob => _blobFighterVisual, + FightWorld.Fighter.Type.BigBlob => _bigBlobFighterVisual, + FightWorld.Fighter.Type.Mavka => _mavkaFighterVisual, + FightWorld.Fighter.Type.YourMom => _yourMomFighterVisual, + FightWorld.Fighter.Type.Vesna => _vesnaFighterVisual, + _ => throw new ArgumentOutOfRangeException() + }; + + var fighterVisual = packedScene.Instantiate(); + fighterVisual.Initialize(fighter); + _allyFighters.AddChild(fighterVisual); + fighterVisual.Position = new Vector2(-_positionDistanceFromCenter[_allyFighters.GetChildCount() - 1], 0); + _fighterVisuals.Add(fighter, fighterVisual); + } + } + + private void ShowTargetSelect(TargetSelectActionDetail targetDetail) + { + // TODO: use Event bus + if (targetDetail.selectEnemy) + _fighterVisuals + .Where(kv => kv.Key.IsInFormation(HappeningData.enemyFighterFormation)) + .ForEach(kv => kv.Value.SetTargetSelectionActive(true)); + + if (targetDetail.selectAlly) + _fighterVisuals + .Where(kv => kv.Key.IsInFormation(HappeningData.allyFighterFormation)) + .ForEach(kv => kv.Value.SetTargetSelectionActive(true)); + } + + private void HideTargetSelect() + { + foreach (var visual in _fighterVisuals.Values) + { + visual.SetTargetSelectionActive(false); + } + } + + #endregion + + public FighterVisual GetVisualForFighter(FightWorld.Fighter fighter) + { + return _fighterVisuals.TryGetValue(fighter, out var visual) + ? visual + : throw new InvalidOperationException("No visual for this fighter"); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/AllFightersVisual.cs.uid b/scripts/CSharp/Common/Fight/AllFightersVisual.cs.uid new file mode 100644 index 0000000..acfca36 --- /dev/null +++ b/scripts/CSharp/Common/Fight/AllFightersVisual.cs.uid @@ -0,0 +1 @@ +uid://dwsqst8fhhqlc diff --git a/scripts/CSharp/Common/Fight/AllyFighters.cs b/scripts/CSharp/Common/Fight/AllyFighters.cs new file mode 100644 index 0000000..765a9cb --- /dev/null +++ b/scripts/CSharp/Common/Fight/AllyFighters.cs @@ -0,0 +1,30 @@ +using Babushka.scripts.CSharp.Common.Fight.Actions; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public class AllyFighters +{ + public FightWorld.Fighter vesnaFighter = new() + { + type = FightWorld.Fighter.Type.Vesna, + maxHealth = 20, + availableActions = + [ + new AllyAttackAction() + ] + }; + public FightWorld.Fighter chuhaFighter = new() + { + type = FightWorld.Fighter.Type.Chuha, + maxHealth = 15, + availableActions = + [ + new FighterAction.Skip() + ] + }; + + public bool IsAlive() + { + return vesnaFighter.IsAlive(); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/AllyFighters.cs.uid b/scripts/CSharp/Common/Fight/AllyFighters.cs.uid new file mode 100644 index 0000000..777ec0a --- /dev/null +++ b/scripts/CSharp/Common/Fight/AllyFighters.cs.uid @@ -0,0 +1 @@ +uid://dst8xcyiw18uc diff --git a/scripts/CSharp/Common/Fight/FightHappening.cs b/scripts/CSharp/Common/Fight/FightHappening.cs new file mode 100644 index 0000000..e1df008 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappening.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.ExceptionServices; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class FightHappening : Node +{ + /* + To get a visual overview of the FightHappening state machine, refer to the graph on miro: + https://miro.com/app/board/uXjVK8YEprM=/?moveToWidget=3458764640805655262&cot=14 + */ + + #region Internal Types + + public enum FightState + { + None, + FightStartAnim, + FightersEnter, + FightersEnterAnim, + NextFighter, + StateCheck, + InputActionSelect, + ActionCheckDetails, + InputActionDetail, + ActionExecute, + ActionAnim, + EnemyActionSelect, + PlayerWin, + EnemyWin, + } + + public class FightersEnterStaging + { + public required List enteringAllyFighters; + public required List enteringEnemyFighters; + + public bool HasAnyToExecute() + { + return enteringAllyFighters.Any() || enteringEnemyFighters.Any(); + } + } + + #endregion + + #region Settings + + private const float StartAnimationTime = 1; + private const float FightersEnterAnimationTime = 1; + + #endregion + + #region Shortcuts + + private static FightWorld.FightHappeningData HappeningData => + FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + + private static FightWorld.Fighter CurrentFighter => HappeningData.fighterTurn.Current; + + #endregion + + #region Events + + [Signal] + public delegate void SignalTransitionFromStateEventHandler(FightState state); + + [Signal] + public delegate void SignalTransitionStateEventHandler(FightState from, FightState to); + + [Signal] + public delegate void SignalTransitionToStateEventHandler(FightState state); + + #endregion + + #region Singleton + + public static FightHappening Instance = null!; + + private void SetupInstance() + { + Instance = this; + } + + #endregion + + public override void _Ready() + { + SetupInstance(); + StartFight(); + } + + #region Public Methods + + public void StartFight() + { + RequireState(FightState.None); + ChangeState(FightState.FightStartAnim); + } + + public void ActionSelect(FighterAction action) + { + RequireState(FightState.InputActionSelect); + HappeningData.actionStaging = action; + action.Reset(); + ChangeState(FightState.ActionCheckDetails); + } + + public void DetailFilled() + { + RequireState(FightState.InputActionDetail); + ChangeState(FightState.ActionCheckDetails); + } + + #endregion + + #region State Machine + + private bool _inTransition = false; + private FightState? _changeToAfterTransition = null; + + private void ChangeState(FightState nextState) + { + _changeToAfterTransition = null; + if (_inTransition) + { + _changeToAfterTransition = nextState; + return; + } + + _inTransition = true; + TransitionFromState(); + var lastState = HappeningData.fightState; + HappeningData.fightState = nextState; + TransitionToState(nextState); + + EmitSignalSignalTransitionFromState(lastState); + EmitSignalSignalTransitionState(lastState, nextState); + EmitSignalSignalTransitionToState(nextState); + _inTransition = false; + + if (_changeToAfterTransition.HasValue) + { + ChangeState(_changeToAfterTransition.Value); + } + } + + private void TransitionFromState() + { + // fixed behaviour + switch (HappeningData.fightState) + { + default: break; + } + } + + private void TransitionToState(FightState nextState) + { + // fixed behaviour + switch (HappeningData.fightState) + { + case FightState.FightStartAnim: + AdvanceToStateInSeconds(FightState.FightersEnter, StartAnimationTime); + break; + case FightState.FightersEnter: + HappeningData.fightersEnterStaging = StageFightersEnter(); + if (HappeningData.fightersEnterStaging.HasAnyToExecute()) + { + ExecuteFightersEnter(); + ChangeState(FightState.FightersEnterAnim); + } + else + { + ChangeState(FightState.NextFighter); + } + + break; + case FightState.FightersEnterAnim: + AdvanceToStateInSeconds(FightState.NextFighter, FightersEnterAnimationTime); + break; + case FightState.NextFighter: + ExecuteNextFighter(); + ChangeState(FightState.StateCheck); + break; + case FightState.StateCheck: + // restest action staging and fighter enter staging + HappeningData.actionStaging = null; + HappeningData.fightersEnterStaging = null; + + if (!FightWorld.Instance.allyFighters.IsAlive()) + { + ChangeState(FightState.EnemyWin); + } + else if (HappeningData.enemyGroup.AreAllDead()) + { + ChangeState(FightState.PlayerWin); + } + else if (CurrentFighter.actionPointsLeft <= 0) + { + ChangeState(FightState.FightersEnter); + } + else if (CurrentFighter.IsInFormation(HappeningData.enemyFighterFormation)) + { + ChangeState(FightState.EnemyActionSelect); + } + else + { + ChangeState(FightState.InputActionSelect); + } + + break; + case FightState.InputActionSelect: + // wait for player input + break; + case FightState.ActionCheckDetails: + RequireNotNull(HappeningData.actionStaging); + + if (ActionAbort()) + ChangeState(FightState.InputActionSelect); + else if (ActionNeededDetail()) + ChangeState(FightState.InputActionDetail); + else + ChangeState(FightState.ActionExecute); + break; + case FightState.InputActionDetail: + // wait for player input + break; + case FightState.EnemyActionSelect: + HappeningData.actionStaging = CurrentFighter.AutoSelectAction(); + ChangeState(FightState.ActionExecute); + break; + case FightState.ActionExecute: + ExecuteAction(); + ChangeState(FightState.ActionAnim); + break; + case FightState.ActionAnim: + var actionTime = GetActionAnimationEnd(); + if (actionTime.IsType()) + { + AdvanceToStateInSeconds(FightState.StateCheck, actionTime); + } + else + { + _ = AdvanceToStateWhenDone(FightState.StateCheck, actionTime); + } + + break; + case FightState.EnemyWin: + // TODO: remove and find proper solution + ReviveVesna(); + break; + default: break; + } + } + + #endregion + + #region Game Logic + + private FightersEnterStaging StageFightersEnter() + { + // ally + var enteringAllyFighters = new List(); + var allyFighters = FightWorld.Instance.allyFighters; + if (!allyFighters.vesnaFighter.IsInFormation(HappeningData.allyFighterFormation)) + { + enteringAllyFighters.Add(allyFighters.vesnaFighter); + } + + // enemy + const int totalEnemySpace = 3; + var enemySpaceLeft = HappeningData.enemyFighterFormation.GetEmptySlotCount(); + + return new FightersEnterStaging + { + enteringAllyFighters = enteringAllyFighters, + enteringEnemyFighters = HappeningData.enemyGroup.fighters + .WhereIsAlive() + .WhereIsNotInFormation(HappeningData.enemyFighterFormation) + .Take(enemySpaceLeft) + .ToList() + }; + } + + private void ExecuteFightersEnter() + { + Debug.Assert(HappeningData.fightersEnterStaging != null); + foreach (var fighter in HappeningData.fightersEnterStaging.enteringAllyFighters) + { + var emptySlotIndex = HappeningData.allyFighterFormation.GetFirstEmptySlot(); + if (emptySlotIndex < 0) throw new Exception("No empty slot for ally fighter to enter"); + HappeningData.allyFighterFormation.SetFighterAtPosition(emptySlotIndex, fighter); + HappeningData.fighterTurn.AddAsLast(fighter); + } + + foreach (var fighter in HappeningData.fightersEnterStaging.enteringEnemyFighters) + { + var emptySlotIndex = HappeningData.enemyFighterFormation.GetFirstEmptySlot(); + if (emptySlotIndex < 0) throw new Exception("No empty slot for enemy fighter to enter"); + HappeningData.enemyFighterFormation.SetFighterAtPosition(emptySlotIndex, fighter); + HappeningData.fighterTurn.AddAsLast(fighter); + } + } + + private void ExecuteNextFighter() + { + HappeningData.fighterTurn.Next(); + CurrentFighter.actionPointsLeft = FightWorld.Fighter.MaxActionPoints; + } + + private void ExecuteAction() + { + Debug.Assert(HappeningData.actionStaging != null); + HappeningData.actionStaging.ExecuteAction(); + CurrentFighter.actionPointsLeft -= HappeningData.actionStaging.GetActionPointCost(); + } + + private Variant> GetActionAnimationEnd() + { + Debug.Assert(HappeningData.actionStaging != null); + return HappeningData.actionStaging.GetAnimationEnd(); + } + + private bool ActionAbort() + { + Debug.Assert(HappeningData.actionStaging != null); + return HappeningData.actionStaging.MarkedForAbort(); + } + + private bool ActionNeededDetail() + { + Debug.Assert(HappeningData.actionStaging != null); + return HappeningData.actionStaging.NextDetail(); + } + + // TODO: remove + private void ReviveVesna() + { + var vesnaFighter = FightWorld.Instance.allyFighters.vesnaFighter; + vesnaFighter.health = vesnaFighter.maxHealth; + GD.Print("Vesna has been revived. This is for the current prototype only"); + } + + #endregion // Game Logic + + #region Utility + + private void RequireState(params FightState[] states) + { + if (states.Contains(HappeningData.fightState)) + return; + + throw new Exception( + $"Can not call this Method while in state {HappeningData.fightState}. Only available in {string.Join(" ,", states)}"); + } + + private void RequireNotNull(Object? o) + { + if (o != null) + return; + + throw new Exception("Object must not be null to call this method"); + } + + private void AdvanceToStateInSeconds(FightState nextState, float seconds) + { + FightWorld.Instance.GetTree().CreateTimer(seconds).Timeout += () => ChangeState(nextState); + } + + private async Task AdvanceToStateWhenDone(FightState nextState, Func isDone) + { + while (!isDone()) + { + await FightWorld.Instance.ToSignal(FightWorld.Instance.GetTree(), SceneTree.SignalName.ProcessFrame); + } + + ChangeState(nextState); + } + + #endregion +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightInstance.cs.uid b/scripts/CSharp/Common/Fight/FightHappening.cs.uid similarity index 100% rename from scripts/CSharp/Common/Fight/FightInstance.cs.uid rename to scripts/CSharp/Common/Fight/FightHappening.cs.uid diff --git a/scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs b/scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs new file mode 100644 index 0000000..293806e --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs @@ -0,0 +1,15 @@ +using Godot; +using System; +using System.Diagnostics; +using Babushka.scripts.CSharp.Common.Fight; + +public partial class FightHappeningSceneSetup : Node2D +{ + public override void _Ready() + { + var fightHappening = FightWorld.Instance.fightHappeningData; + Debug.Assert(fightHappening != null, "Fight happening scene loaded, without a fight happening"); + + + } +} diff --git a/scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs.uid b/scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs.uid new file mode 100644 index 0000000..1ac025e --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappeningSceneSetup.cs.uid @@ -0,0 +1 @@ +uid://cnhpnn8o0gybd diff --git a/scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs b/scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs new file mode 100644 index 0000000..3c6bfc1 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs @@ -0,0 +1,57 @@ +using Godot; +using System; +using System.Linq; +using Babushka.scripts.CSharp.Common.Fight; + +public partial class FightHappeningStateDebugger : Node +{ + [Export] private Label _label; + + [Export] private Label _current; + + private FightWorld.FightHappeningData Data => FightWorld.Instance.fightHappeningData!; + + public void StateChange(FightHappening.FightState from, FightHappening.FightState to) + { + _current.Text = $"{to}"; + _label.Text += $"State changed from {from} to {to}\n"; + switch (to) + { + case FightHappening.FightState.None: + break; + case FightHappening.FightState.FightStartAnim: + break; + case FightHappening.FightState.FightersEnter: + break; + case FightHappening.FightState.FightersEnterAnim: + _label.Text += + $" {Data.fightersEnterStaging!.enteringAllyFighters.Count} allies " + + $"and {Data.fightersEnterStaging.enteringEnemyFighters.Count} enemies are entering the fight.\n"; + break; + case FightHappening.FightState.NextFighter: + break; + case FightHappening.FightState.StateCheck: + break; + case FightHappening.FightState.InputActionSelect: + break; + case FightHappening.FightState.ActionCheckDetails: + break; + case FightHappening.FightState.InputActionDetail: + break; + case FightHappening.FightState.ActionExecute: + _label.Text += $" Executing action: {Data.actionStaging!.GetType()}\n"; + break; + case FightHappening.FightState.ActionAnim: + break; + case FightHappening.FightState.EnemyActionSelect: + break; + case FightHappening.FightState.PlayerWin: + break; + case FightHappening.FightState.EnemyWin: + break; + default: + throw new ArgumentOutOfRangeException(nameof(to), to, null); + } + + } +} diff --git a/scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs.uid b/scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs.uid new file mode 100644 index 0000000..4de7fe7 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappeningStateDebugger.cs.uid @@ -0,0 +1 @@ +uid://d2ugtb3dalrg3 diff --git a/scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs b/scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs new file mode 100644 index 0000000..cc7bb2b --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs @@ -0,0 +1,27 @@ +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class FightHappeningStateReaction : Node +{ + [Export] private FightHappening.FightState _fightState; + + [Signal] + public delegate void OnStateEnteredEventHandler(); + + [Signal] + public delegate void OnStateExitedEventHandler(); + + public void FightHappeningStateTransitioned(FightHappening.FightState fromState, FightHappening.FightState toState) + { + if (fromState == _fightState) + { + EmitSignalOnStateExited(); + } + + if (toState == _fightState) + { + EmitSignalOnStateEntered(); + } + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs.uid b/scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs.uid new file mode 100644 index 0000000..ea8036a --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightHappeningStateReaction.cs.uid @@ -0,0 +1 @@ +uid://buiwuf7pjfq8 diff --git a/scripts/CSharp/Common/Fight/FightInstance.cs b/scripts/CSharp/Common/Fight/FightInstance.cs deleted file mode 100644 index 28d608f..0000000 --- a/scripts/CSharp/Common/Fight/FightInstance.cs +++ /dev/null @@ -1,351 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Babushka.scripts.CSharp.Common.Camera; -using Babushka.scripts.CSharp.Common.Util; -using Godot; -namespace Babushka.scripts.CSharp.Common.Fight; - -public partial class FightInstance : Node2D //TODO: remake -{ - [Export(PropertyHint.ArrayType)] private Node2D[] _friendlyFightSpots; - [Export(PropertyHint.ArrayType)] private Node2D[] _enemyFightSpots; - [Export] public Node2D camPositionNode; - [Export] private FightStateManager _fightStateManager; - [Export] private Label _fightEndText; - - - [Signal] - public delegate void FightStartedEventHandler(); - - [Signal] - public delegate void FightEndedEventHandler(); - - private List _friendlyFighters = new(); - private List _enemyFighters = new(); - - private FightAttack? _stagedAttack = null; - - public override void _Ready() - { - //_fightStateManager.CurrentFightState = FightStateManager.FightState.FightStartAnim; - _fightStateManager.ExitingTransition += from => - { - switch (from) - { - case FightStateManager.FightState.None: - CaptureCamera(); - Show(); - EmitSignalFightStarted(); - break; - case FightStateManager.FightState.Input: - HideAttackButtons(); - break; - case FightStateManager.FightState.InputTargetSelect: - HideTargetButtons(); - break; - case FightStateManager.FightState.FriendAttackAnim: - _stagedAttack = null; - break; - case FightStateManager.FightState.PlayerWinAnim: - case FightStateManager.FightState.EnemyWinAnim: - _fightEndText.Text = ""; - break; - } - }; - - _fightStateManager.EnteringTransition += to => - { - switch (to) - { - case FightStateManager.FightState.None: - EmitSignalFightEnded(); - CleanUp(); - Hide(); - ReleaseCamera(); - break; - case FightStateManager.FightState.Input: - if (CheckWinAndSetState()) - break; - if (CheckFriendlyActionsLeftAndSetState()) - break; - ShowAttackButtons(); - break; - case FightStateManager.FightState.InputTargetSelect: - ShowTargetButtons(); - break; - case FightStateManager.FightState.FriendAttackAnim: - ExecuteAttack(); - GetTree().CreateTimer(1).Timeout += () => _fightStateManager.CurrentFightState = FightStateManager.FightState.Input; - break; - case FightStateManager.FightState.Enemy: - if (CheckWinAndSetState()) - break; - if (CheckEnemyActionsLeftAndSetState()) - break; - DecideEnemyAttack(); - _fightStateManager.CurrentFightState = FightStateManager.FightState.EnemyAttackAnim; - break; - case FightStateManager.FightState.EnemyAttackAnim: - ExecuteAttack(); - GetTree().CreateTimer(1).Timeout += () => _fightStateManager.CurrentFightState = FightStateManager.FightState.Enemy; - break; - case FightStateManager.FightState.PlayerWinAnim: - _fightEndText.Text = "You Win!"; - GetTree().CreateTimer(1.5).Timeout += () => _fightStateManager.CurrentFightState = FightStateManager.FightState.None; - break; - case FightStateManager.FightState.EnemyWinAnim: - _fightEndText.Text = "You Died :("; - GetTree().CreateTimer(3).Timeout += () => _fightStateManager.CurrentFightState = FightStateManager.FightState.None; - break; - case FightStateManager.FightState.ChangeSideToEnemy: - ResetEnemyActions(); - _fightStateManager.CurrentFightState = FightStateManager.FightState.Enemy; - break; - case FightStateManager.FightState.ChangeSideToFriendly: - ResetFriendlyActions(); - _fightStateManager.CurrentFightState = FightStateManager.FightState.Input; - break; - case FightStateManager.FightState.Heal: - Heal(); - GetTree().CreateTimer(1).Timeout += () => _fightStateManager.CurrentFightState = FightStateManager.FightState.Input; - break; - } - }; - } - private void Heal() - { - // TODO: make heal staging system - _friendlyFighters.Where(f => !f.IsDead()).ForEach(f => - { - f.Health += 50; - f.HealAnimation(); - f.DecrementActions(); - }); - UpdateHealthVisual(); - } - private void ResetEnemyActions() - { - _enemyFighters.ForEach(f => f.ResetActions()); - } - - private void ResetFriendlyActions() - { - _friendlyFighters.ForEach(f => f.ResetActions()); - } - - /** - * - * true if the state was changed - * - */ - private bool CheckFriendlyActionsLeftAndSetState() - { - var hasActionsLeft = _friendlyFighters.Where(f => !f.IsDead()).Any(f => f.HasActionsLeft()); - if (hasActionsLeft) - { - return false; - } // else - _fightStateManager.CurrentFightState = FightStateManager.FightState.ChangeSideToEnemy; - return true; - } - - /** - * - * true if the state was changed - * - */ - private bool CheckEnemyActionsLeftAndSetState() - { - var hasActionsLeft = _enemyFighters.Where(f => !f.IsDead()).Any(f => f.HasActionsLeft()); - if (hasActionsLeft) - { - return false; - } // else - _fightStateManager.CurrentFightState = FightStateManager.FightState.ChangeSideToFriendly; - return true; - } - - private void CleanUp() - { - _enemyFighters.ForEach(f => f.QueueFree()); - _friendlyFighters.ForEach(f => f.QueueFree()); - _enemyFighters = new(); - _friendlyFighters = new(); - } - private void DecideEnemyAttack() - { - var availableEnemyFighters = - _enemyFighters - .Where(f => !f.IsDead()) - .Where(f=>f.HasActionsLeft()) - .ToList(); - var aliveFriendlyFighters = - _friendlyFighters - .Where(f => !f.IsDead()) - .ToList(); - - if (availableEnemyFighters.Count <= 0) - throw new InvalidOperationException("No enemy fighters available for attack."); - - if (aliveFriendlyFighters.Count <= 0) - throw new InvalidOperationException("No friendly fighters available to target."); - - var fighter = availableEnemyFighters.Random(); - var target = aliveFriendlyFighters.Random(); - - _stagedAttack = new FightAttack - { - attacker = fighter!, - needsSelectedTarget = true, - damage = fighter!.attackStrength, - target = target! - }; - } - - private void ExecuteAttack() - { - if (_stagedAttack == null) - throw new InvalidOperationException("No staged attack to execute."); - - if (!_stagedAttack.needsSelectedTarget) - throw new NotImplementedException("Non-targeted attacks are not implemented yet."); - - if (_stagedAttack.needsSelectedTarget && _stagedAttack.target == null) - throw new InvalidOperationException("No target selected for the staged attack."); - - _stagedAttack.target!.Health -= _stagedAttack.damage; - _stagedAttack.attacker.DecrementActions(); - _stagedAttack.attacker.AttackAnimation(_stagedAttack); - - UpdateHealthVisual(); - } - - private void UpdateHealthVisual() - { - _friendlyFighters - .Concat(_enemyFighters) - .ForEach(f => f.UpdateHealthVisual()); - } - - private void ReleaseCamera() - { - CameraController.Instance.fightToShow = null; - } - - private void CaptureCamera() - { - CameraController.Instance.fightToShow = this; - } - - public void Start(FightParty fightParty, PackedScene?[] enemies) - { - if (_fightStateManager.IsRunning()) - { - GD.PushWarning("Can not start a running fight"); - return; - } - - if (fightParty.vesna) - { - InstantiateFighter(_friendlyFightSpots[1], FightManager.Instance.fightingVesnaScene); - } - - for (var i = 0; i < Math.Min(_enemyFightSpots.Length, enemies.Length); i++) - { - var enemy = enemies[i]; - if (enemy == null) - continue; - - InstantiateFighter(_enemyFightSpots[i], enemy, true); - } - - _fightStateManager.ToStartAnim(); - } - - private void InstantiateFighter(Node2D parent, PackedScene fighterScene, bool isEnemy = false) - { - var fighter = fighterScene.Instantiate(); - fighter.fightInstance = this; - parent.AddChild(fighter); - - if (isEnemy) - { - _enemyFighters.Add(fighter); - } - else - { - _friendlyFighters.Add(fighter); - } - } - - public void SelectAttack(Fighter fighter) - { - _stagedAttack = new FightAttack - { - attacker = fighter, - damage = fighter.attackStrength, - needsSelectedTarget = true - }; - - if (_stagedAttack.needsSelectedTarget) - { - _fightStateManager.CurrentFightState = FightStateManager.FightState.InputTargetSelect; - } - else - { - _fightStateManager.CurrentFightState = FightStateManager.FightState.FriendAttackAnim; - } - } - - private void HideAttackButtons() - { - _friendlyFighters.ForEach(f => f.HideAttackButton()); - } - - private void ShowAttackButtons() - { - _friendlyFighters.ForEach(f => f.ShowAttackButton()); - } - - private void HideTargetButtons() - { - _enemyFighters.ForEach(f => f.HideTargetButtons()); - } - - private void ShowTargetButtons() - { - _enemyFighters.Where(f => !f.IsDead()).ForEach(f => f.ShowTargetButtons()); - } - - public void SelectTargetAndAttack(Fighter fighter) - { - if (_stagedAttack == null) - throw new InvalidOperationException("No staged attack to select target for."); - - _stagedAttack.target = fighter; - - _fightStateManager.CurrentFightState = FightStateManager.FightState.FriendAttackAnim; - } - - public void SelectHeal(Fighter fighter) - { - _fightStateManager.CurrentFightState = FightStateManager.FightState.Heal; - } - - public bool CheckWinAndSetState() - { - if (_enemyFighters.All(f => f.IsDead())) - { - _fightStateManager.CurrentFightState = FightStateManager.FightState.PlayerWinAnim; - return true; - } - if (_friendlyFighters.All(f => f.IsDead())) - { - _fightStateManager.CurrentFightState = FightStateManager.FightState.EnemyWinAnim; - return true; - } - return false; - } -} - diff --git a/scripts/CSharp/Common/Fight/FightMinigameHandler.cs b/scripts/CSharp/Common/Fight/FightMinigameHandler.cs new file mode 100644 index 0000000..1a01888 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightMinigameHandler.cs @@ -0,0 +1,43 @@ +using Godot; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Fight; +using Babushka.scripts.CSharp.Common.Fight.ActionDetails; +using Babushka.scripts.CSharp.Common.Minigame; + +public partial class FightMinigameHandler : Node +{ + #region Shortcuts + + private FightWorld.FightHappeningData HappeningData => FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + + #endregion + + [Export] private MinigameController _minigameController; + + + public void OnStateEnter(FightHappening.FightState to) + { + if(to!=FightHappening.FightState.InputActionDetail) return; + + var currentDetail = HappeningData.actionStaging!.CurrentDetail(); + if(currentDetail is not MinigameActionDetail minigameDetail) return; + + _minigameController.Run(new MinigameController.Builder() + .AddRegion(4).RegionWithText("4").RegionWithTheme(MinigameController.RegionTheme.Normal) + .AddRegion(0).RegionWithProportion(1.5f).RegionWithText("0").RegionWithTheme(MinigameController.RegionTheme.Bad) + .AddRegion(8).RegionWithProportion(0.5f).RegionWithText("8").RegionWithTheme(MinigameController.RegionTheme.VeryGood) + .AddRegion(0).RegionWithProportion(1.5f).RegionWithText("0").RegionWithTheme(MinigameController.RegionTheme.Bad) + .AddRegion(3).RegionWithText("3").RegionWithTheme(MinigameController.RegionTheme.NormalAlt1) + .AddRegion(5).RegionWithText("5").RegionWithTheme(MinigameController.RegionTheme.NormalAlt2) + .WithHitCount(3) + ).ContinueWith(task => + { + minigameDetail.damageHits = task.Result; + //FightHappening.Instance.DetailFilled(); + // Apparently ContinueWith spawn a new Thread, but methods on a node only want to be called from the main thread + FightHappening.Instance.CallDeferred("DetailFilled"); + }); + } +} diff --git a/scripts/CSharp/Common/Fight/FightMinigameHandler.cs.uid b/scripts/CSharp/Common/Fight/FightMinigameHandler.cs.uid new file mode 100644 index 0000000..4999e6a --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightMinigameHandler.cs.uid @@ -0,0 +1 @@ +uid://bwm0nhvt1083k diff --git a/scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs b/scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs new file mode 100644 index 0000000..12c316d --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class FightRoomSceneSetup : Node +{ + [Export(PropertyHint.ArrayType)] private Node2D[] _enemyGroupSpawns; + [Export] private PackedScene _roamingEnemyGroupPrefab; + [Export] private FightSceneSwitcher _fightSceneSwitcher; + + + public override void _Ready() + { + var room = FightWorld.Instance.currentRoom!; + + var i = 0; + foreach (var availableParent in _enemyGroupSpawns.Shuffle()) + { + var enemyGroup = room.enemyGroups[i]; + var roamingEnemyGroup = _roamingEnemyGroupPrefab.Instantiate(); + roamingEnemyGroup.Initialize(enemyGroup, _fightSceneSwitcher); + availableParent.AddChild(roamingEnemyGroup); + if (i >= room.enemyGroups.Count - 1) break; + i++; + } + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs.uid b/scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs.uid new file mode 100644 index 0000000..29c57ba --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightRoomSceneSetup.cs.uid @@ -0,0 +1 @@ +uid://dbu8afaiohpdh diff --git a/scripts/CSharp/Common/Fight/FightSceneSwitcher.cs b/scripts/CSharp/Common/Fight/FightSceneSwitcher.cs new file mode 100644 index 0000000..3e4f9c2 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightSceneSwitcher.cs @@ -0,0 +1,63 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.SceneManagement; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class FightSceneSwitcher : Node +{ + [Export] private Node _sceneRoot = null!; + [Export] private string _fightRoomScenePath = null!; + [Export] private string _fightHappeningScene = null!; + + private void LoadNext() + { + var nextRoom = FightWorld.Instance.currentRoom; + Debug.Assert(nextRoom != null, "nextRoom!=null"); + var nextFightHappening = FightWorld.Instance.fightHappeningData; + SceneTransitionThreaded.Instance.ChangeSceneToFile(nextFightHappening != null + ? _fightHappeningScene + : _fightRoomScenePath); + _ = UnloadAfterDelay(); + } + + private async Task UnloadAfterDelay() + { + await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); // 1.0f seconds + //sceneRoot.QueueFree(); + } + + public void SwitchRoom(int pathIndex) + { + Debug.Assert(FightWorld.Instance.currentRoom != null, "FightWorld.Instance.currentRoom!=null"); + + if (!FightWorld.Instance.currentRoom.paths.TryGetValue(pathIndex, out var nextRoom)) + throw new Exception("Trying to go down a non-existent path"); + + FightWorld.Instance.currentRoom = nextRoom; + LoadNext(); + } + + public void SwitchToFight(FightWorld.FighterGroup enemyGroup) + { + if (FightWorld.Instance.fightHappeningData != null) + throw new Exception("Trying to start a fight while already in a fight"); + + FightWorld.Instance.fightHappeningData = new FightWorld.FightHappeningData + { + enemyGroup = enemyGroup, + }; + LoadNext(); + } + + public void ExitFight() + { + if (FightWorld.Instance.fightHappeningData == null) + throw new Exception("Trying to exit a fight while not in a fight"); + + FightWorld.Instance.fightHappeningData = null; + LoadNext(); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightSceneSwitcher.cs.uid b/scripts/CSharp/Common/Fight/FightSceneSwitcher.cs.uid new file mode 100644 index 0000000..94e68d1 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightSceneSwitcher.cs.uid @@ -0,0 +1 @@ +uid://cql8mt5jsmcdl diff --git a/scripts/CSharp/Common/Fight/FightStateManager.cs b/scripts/CSharp/Common/Fight/FightStateManager.cs deleted file mode 100644 index 5ea800f..0000000 --- a/scripts/CSharp/Common/Fight/FightStateManager.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Godot; -namespace Babushka.scripts.CSharp.Common.Fight; - -public partial class FightStateManager : Node -{ - [Signal] - public delegate void ExitingTransitionEventHandler(FightState exitingState); - - [Signal] - public delegate void EnteringTransitionEventHandler(FightState enteringState); - - public enum FightState - { - None, - FightStartAnim, - Input, - InputTargetSelect, - FriendAttackAnim, - Enemy, - EnemyAttackAnim, - PlayerWinAnim, - EnemyWinAnim, - ChangeSideToEnemy, - ChangeSideToFriendly, - Heal, - } - - private FightState _fightStateBacking = FightState.None; - - public FightState CurrentFightState - { - set => Transition(_fightStateBacking, value); - get => _fightStateBacking; - } - - private void Transition(FightState from, FightState to) - { - if(from == to) - return; - - GD.Print($"Transitioning from {from} to {to}"); - ExitTransition(from); - _fightStateBacking = to; - EnterTransition(to); - } - - private void ExitTransition(FightState from) - { - EmitSignalExitingTransition(from); - } - - private void EnterTransition(FightState to) - { - EmitSignalEnteringTransition(to); - switch (to) - { - case FightState.FightStartAnim: - EnterFightStartAnim(); - break; - } - } - private void EnterFightStartAnim() - { - GetTree().CreateTimer(1).Timeout += () => CurrentFightState = FightState.Input; - } - - public void ToStartAnim() - { - CurrentFightState = FightState.FightStartAnim; - } - - public bool IsRunning() - { - return CurrentFightState != FightState.None; - } -} diff --git a/scripts/CSharp/Common/Fight/FightStateManager.cs.uid b/scripts/CSharp/Common/Fight/FightStateManager.cs.uid deleted file mode 100644 index 1527d8c..0000000 --- a/scripts/CSharp/Common/Fight/FightStateManager.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://oe1uypehqvr7 diff --git a/scripts/CSharp/Common/Fight/FightUtils.cs b/scripts/CSharp/Common/Fight/FightUtils.cs new file mode 100644 index 0000000..52d33af --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightUtils.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public static class FightUtils +{ + public static IEnumerable WhereIsAlive(this IEnumerable self) + { + return self.Where(e => e.IsAlive()); + } + + public static IEnumerable WhereIsNotInFormation(this IEnumerable self, FighterFormation formation) + { + return self.Where(e => !e.IsInFormation(formation)); + } + + public static bool IsAlive(this FightWorld.Fighter self) + { + return self.GetHealth() > 0; + } + + public static bool IsDead(this FightWorld.Fighter self) + { + return !self.IsAlive(); + } + + public static int GetHealth(this FightWorld.Fighter self) + { + return Math.Max(self.health ?? self.maxHealth, 0); + } + + public static void AddHealth(this FightWorld.Fighter self, int addHealth) + { + self.health = self.GetHealth() + addHealth; + } + + public static bool IsInFormation(this FightWorld.Fighter self, FighterFormation formation) + { + return formation.ContainsFighter(self); + } + + public static bool AreAllDead(this FightWorld.FighterGroup self) + { + return self.fighters.All(e => e.IsDead()); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightUtils.cs.uid b/scripts/CSharp/Common/Fight/FightUtils.cs.uid new file mode 100644 index 0000000..87c1ce4 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightUtils.cs.uid @@ -0,0 +1 @@ +uid://beuhpltb84pf diff --git a/scripts/CSharp/Common/Fight/FightWorld.cs b/scripts/CSharp/Common/Fight/FightWorld.cs new file mode 100644 index 0000000..be34387 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightWorld.cs @@ -0,0 +1,191 @@ +using System.Collections.Generic; +using Babushka.scripts.CSharp.Common.Fight.Actions; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class FightWorld : Node +{ + public class World + { + public required List rooms; + } + + public class Room + { + public required Dictionary paths; + public required List enemyGroups; + } + + public class FighterGroup + { + public required List fighters; + } + + public class FightHappeningData + { + public required FighterGroup enemyGroup; + public FightHappening.FightState fightState = FightHappening.FightState.None; + public readonly FighterTurn fighterTurn = new(); + public readonly FighterFormation allyFighterFormation = new(); + public readonly FighterFormation enemyFighterFormation = new(); + public FightHappening.FightersEnterStaging? fightersEnterStaging; + public FighterAction? actionStaging; + } + + public class Fighter + { + public enum Type + { + Blob, + BigBlob, + Mavka, + YourMom, + Vesna, + Chuha + } + + public required Type type; + public required int maxHealth; + public required List availableActions; + public const int MaxActionPoints = 1; + public int? health = null; // null => initialize to full health on spawn + public int actionPointsLeft; + + public FighterAction AutoSelectAction() + { + return availableActions.Random() ?? new FighterAction.Skip(); + } + } + + #region AutoLoad ( Contains _EnterTree() ) + + public static FightWorld Instance { get; private set; } = null!; + + public override void _EnterTree() + { + Instance = this; + MyEnterTree(); + } + + #endregion + + public World? world = null; + public Room? currentRoom = null; + public FightHappeningData? fightHappeningData = null; + public AllyFighters allyFighters = new(); + + public void MyEnterTree() + { + Generate(); + currentRoom = world!.rooms[0]; + } + + public void Generate() + { + world = new Generator().GenerateWorld(); + } + + private class Generator + { + public World GenerateWorld() + { + var world = new World + { + rooms = GenerateRooms() + }; + return world; + } + + private List GenerateRooms() + { + var rooms = new List(); + + var roomCount = 2; + + for (var i = 0; i < roomCount; i++) + { + rooms.Add(GenerateDisconnectedRoom()); + } + + // Connect rooms linearly + for (var i = 0; i < rooms.Count - 1; i++) + { + rooms[i].paths[0] = rooms[i + 1]; + rooms[i + 1].paths[1] = rooms[i]; + } + + return rooms; + } + + private Room GenerateDisconnectedRoom() + { + var room = new Room + { + paths = new Dictionary(), + enemyGroups = GenerateEnemyGroups() + }; + return room; + } + + private List GenerateEnemyGroups() + { + var enemyGroups = new List(); + + var enemyGroupCount = GD.RandRange(1, 3); + + for (var i = 0; i < enemyGroupCount; i++) + { + enemyGroups.Add(GenerateSingleEnemyGroup()); + } + + return enemyGroups; + } + + private FighterGroup GenerateSingleEnemyGroup() + { + var enemyGroup = new FighterGroup + { + fighters = [] + }; + + var enemyCount = GD.RandRange(1, 3); + + for (var i = 0; i < enemyCount; i++) + { + enemyGroup.fighters.Add(GenerateSingleEnemy()); + } + + return enemyGroup; + } + + private Fighter GenerateSingleEnemy() + { + var typeRoll = GD.RandRange(0, 99); + + // Disabled generating different types due to lack of fighter visual type implementation + //var type = typeRoll switch + //{ + // < 50 => Fighter.Type.Blob, + // < 75 => Fighter.Type.BigBlob, + // < 90 => Fighter.Type.Mavka, + // _ => Fighter.Type.YourMom + //}; + var type = Fighter.Type.Blob; + + var enemy = new Fighter + { + type = type, + health = null, + maxHealth = 12, + availableActions = + [ + new BlobAttackAction() + ] + }; + + return enemy; + } + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightWorld.cs.uid b/scripts/CSharp/Common/Fight/FightWorld.cs.uid new file mode 100644 index 0000000..0de71fd --- /dev/null +++ b/scripts/CSharp/Common/Fight/FightWorld.cs.uid @@ -0,0 +1 @@ +uid://dqe1i2qmpttwf diff --git a/scripts/CSharp/Common/Fight/Fighter.cs b/scripts/CSharp/Common/Fight/Fighter.cs deleted file mode 100644 index 31afcf4..0000000 --- a/scripts/CSharp/Common/Fight/Fighter.cs +++ /dev/null @@ -1,181 +0,0 @@ -using Godot; -namespace Babushka.scripts.CSharp.Common.Fight; - -public partial class Fighter : Node2D -{ - [Export] public string name; - [Export] public int maxHealth; - [Export] public int attackStrength; - [Export] public int maxActions = 1; - - [ExportCategory("References")] - [Export] private Node2D _attackButtons; - [Export] private Node2D _targetButtons; - [Export] private Node2D _targetMarker; - [Export] private Label _healthText; - [Export] private Node2D _visualSprite; - - [Signal] public delegate void DamageTakenEventHandler(); - [Signal] public delegate void AttackingEventHandler(); - [Signal] public delegate void DyingEventHandler(); - [Signal] public delegate void HealedEventHandler(); - - - private int _health; - private int _actions; - - - public FightInstance fightInstance; - public int Health - { - get => _health; - set - { - _health = value; - if (_health <= 0) - { - _health = 0; - Die(); - } - if (_health > maxHealth) - { - _health = maxHealth; - } - } - } - - private void Die() - { - _visualSprite.Scale = new Vector2(1, 0.3f); - EmitSignalDying(); - } - - public override void _Ready() - { - Health = maxHealth; - UpdateHealthVisual(); - ResetActions(); - } - - public void Attack() - { - fightInstance.SelectAttack(this); - } - - public void HideAttackButton() - { - _attackButtons.Hide(); - } - - public void ShowAttackButton() - { - _attackButtons.Show(); - } - - public void HideTargetButtons() - { - _targetButtons.Hide(); - } - - public void ShowTargetButtons() - { - _targetButtons.Show(); - } - - public void TargetMouseEvent(Node viewport, InputEvent inputEvent, int shapeIdx) - { - if (inputEvent.IsPressed()) - ClickedTarget(); - } - - public void AttackMouseEvent(Node viewport, InputEvent inputEvent, int shapeIdx) - { - if (inputEvent.IsPressed()) - ClickedAttack(); - } - - public void HealMouseEvent(Node viewport, InputEvent inputEvent, int shapeIdx) - { - if (inputEvent.IsPressed()) - ClickedHeal(); - } - - private void ClickedAttack() - { - fightInstance.SelectAttack(this); - } - - private void ClickedHeal() - { - fightInstance.SelectHeal(this); - } - - private void ClickedTarget() - { - fightInstance.SelectTargetAndAttack(this); - } - - public void StartHoverTarget() - { - _targetMarker.Visible = true; - } - - public void EndHoverTarget() - { - _targetMarker.Visible = false; - } - - public void UpdateHealthVisual() - { - _healthText.Text = $"{Health}/{maxHealth}"; - } - - public void AttackAnimation(FightAttack attack) - { - EmitSignalAttacking(); - var tween = GetTree().CreateTween(); - tween.TweenProperty(this, "global_position", attack.target.GlobalPosition, 0.15); - tween.TweenCallback(Callable.From(() => attack.target?.HitAnimation(attack))); - tween.TweenProperty(this, "position", new Vector2(0, 0), 0.7) - .SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out); - - } - - private void HitAnimation(FightAttack attack) - { - EmitSignalDamageTaken(); - var tween = GetTree().CreateTween(); - tween.TweenProperty(this, "scale", new Vector2(1.4f, 0.6f), 0.15); - tween.TweenProperty(this, "scale", new Vector2(1, 1), 0.4) - .SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out); - } - - public bool IsDead() - { - return Health <= 0; - } - - public void ResetActions() - { - _actions = maxActions; - } - - public bool HasActionsLeft() - { - return _actions > 0; - } - - public void DecrementActions() - { - _actions--; - } - - public void HealAnimation() - { - EmitSignalHealed(); - var tween = GetTree().CreateTween(); - tween.TweenProperty(this, "scale", new Vector2(0.6f, 1.4f), 0.15); - tween.TweenProperty(this, "scale", new Vector2(1, 1), 0.4) - .SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out); - } -} diff --git a/scripts/CSharp/Common/Fight/FighterAction.cs b/scripts/CSharp/Common/Fight/FighterAction.cs new file mode 100644 index 0000000..789120d --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterAction.cs @@ -0,0 +1,132 @@ +using System; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public abstract class FighterAction +{ + // enum has explicit values, because they are set in godot signals as integers + // e.g. here: BabushkaSceneFightHappening => ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/AttackButton + public enum AllyActionButton + { + None, + Attack = 1, + Summon = 2, + Talk = 3, + Flee = 4, + } + + public class TargetSelection + { + // ReSharper disable once MemberHidesStaticFromOuterClass + public static readonly TargetSelection Skip = new() { skipTargetSelection = () => true }; + public Func skipTargetSelection = () => false; + } + + public abstract class FighterActionDetail + { + public abstract bool DetailComplete(); + } + + private bool _abort = false; + + #region Shortcuts + + protected static FightWorld.FightHappeningData HappeningData => + FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + + #endregion + + /// + /// Executes the data modification for the action. This must happen instantly and not via a coroutines or callbacks. + /// To get a multiple hit effect for one action, use appropriate Visual Manipulation functions in AnimateAction. + /// + public virtual void ExecuteAction() + { + } + + /// + /// Returns a way to determine, when an action animation is done + /// + /// + /// A variant that can be float or Func<bool>.
+ /// When the return type is float, the animation will take the return value amount of seconds.
+ /// When the return type is Func<bool>, the animation will be done, when the function returns true. + ///
+ public abstract Variant> GetAnimationEnd(); + + /// + /// Animates the action. + /// + /// + public virtual async Task AnimateAction(AllFightersVisual allFightersVisual) + { + } + + public void MarkAbort() + { + _abort = true; + } + + public bool MarkedForAbort() + { + return _abort; + } + + /// + /// Returns the FighterActionDetail, that is currently handled. + /// + /// + public virtual FighterActionDetail CurrentDetail() + { + throw new Exception("Action has no details to handle"); + } + + /// + /// Sets the next Detail to be handled. Returns false, when there are no more details to handle. + /// + /// + public abstract bool NextDetail(); + + /// + /// Returns the action point cost of this action. + /// Right now, only the values 1 and 0 make sense. + /// + /// + public virtual int GetActionPointCost() + { + return 1; + } + + /// + /// Will be called right after the action is selected by the player. Can be used to reset the state of the details + /// + public virtual void Reset() + { + } + + /// + /// If this action should be bound to an action button in the UI, return the corresponding enum value here. + /// + /// + public virtual AllyActionButton BindToActionButton() + { + return AllyActionButton.None; + } + + public class Skip : FighterAction + { + public override Variant> GetAnimationEnd() + { + return 0f; + } + + public override bool NextDetail() + { + return false; + } + } + +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FighterAction.cs.uid b/scripts/CSharp/Common/Fight/FighterAction.cs.uid new file mode 100644 index 0000000..31ed96a --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterAction.cs.uid @@ -0,0 +1 @@ +uid://c60jugfee0bpv diff --git a/scripts/CSharp/Common/Fight/FighterFormation.cs b/scripts/CSharp/Common/Fight/FighterFormation.cs new file mode 100644 index 0000000..57b7931 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterFormation.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public class FighterFormation +{ + private readonly List _fighters; + + public FighterFormation(int slots = 3) + { + _fighters = []; + for (var i = 0; i < slots; i++) + { + _fighters.Add(null); + } + } + + public FightWorld.Fighter? GetFighterAtPosition(int position) + { + Debug.Assert(position >= 0, "position>=0"); + Debug.Assert(position < _fighters.Count, "position does not exist"); + + return _fighters[position]; + } + + public void SetFighterAtPosition(int position, FightWorld.Fighter value) + { + Debug.Assert(position >= 0, "position>=0"); + Debug.Assert(position < _fighters.Count, "position does not exist"); + + _fighters[position] = value; + } + + public bool ContainsFighter(FightWorld.Fighter fighter) + { + return _fighters.Contains(fighter); + } + + public int GetFirstEmptySlot() + { + for (var i = 0; i < _fighters.Count; i++) + { + if (_fighters[i] == null) + return i; + } + + return -1; + } + + public int GetEmptySlotCount() + { + return _fighters.Count(fighter => fighter == null); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FighterFormation.cs.uid b/scripts/CSharp/Common/Fight/FighterFormation.cs.uid new file mode 100644 index 0000000..635abe9 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterFormation.cs.uid @@ -0,0 +1 @@ +uid://oipfvb87uyq3 diff --git a/scripts/CSharp/Common/Fight/FighterTurn.cs b/scripts/CSharp/Common/Fight/FighterTurn.cs new file mode 100644 index 0000000..4f546d8 --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterTurn.cs @@ -0,0 +1,97 @@ +using System; +using System.Diagnostics; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public class FighterTurn +{ + private class Node + { + public required Node next; + public required FightWorld.Fighter fighter; + } + + private Node? _currentNode; + + public FightWorld.Fighter Current => _currentNode?.fighter ?? throw new InvalidOperationException("No current fighter"); + + public void Next() + { + Debug.Assert(_currentNode != null, "currentNode!=null"); + _currentNode = _currentNode.next; + } + + public FightWorld.Fighter PeekNext() + { + Debug.Assert(_currentNode != null, "currentNode!=null"); + return _currentNode.next.fighter; + } + + public void AddAsLast(FightWorld.Fighter value) + { + // if first node + if (_currentNode == null) + { + _currentNode = new Node { fighter = value, next = null! }; + _currentNode.next = _currentNode; + return; + } + + var newNode = new Node { fighter = value, next = _currentNode }; + var node = _currentNode; + while (node.next != _currentNode) + { + node = node.next; + } + + node.next = newNode; + } + + public void AddAsNext(FightWorld.Fighter value) + { + // if first node + if (_currentNode == null) + { + AddAsLast(value); + return; + } + + var newNode = new Node { fighter = value, next = _currentNode.next }; + _currentNode.next = newNode; + } + + public bool Remove(FightWorld.Fighter value) + { + if (_currentNode == null) return false; + + // if only one node + if (_currentNode.next == _currentNode) + { + if (_currentNode.fighter == value) + { + _currentNode = null; + return true; + } + + return false; + } + + var node = _currentNode; + do + { + // next is the fighter to remove + if (node.next.fighter == value) + { + // if removing current, keep current + // it will be implicitly deleted by loss of reference on the next Next() call + + node.next = node.next.next; + return true; + } + + node = node.next; + } while (node != _currentNode); + + return false; + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FighterTurn.cs.uid b/scripts/CSharp/Common/Fight/FighterTurn.cs.uid new file mode 100644 index 0000000..1d25b2f --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterTurn.cs.uid @@ -0,0 +1 @@ +uid://bahm4ukspymm2 diff --git a/scripts/CSharp/Common/Fight/FighterVisual.cs b/scripts/CSharp/Common/Fight/FighterVisual.cs new file mode 100644 index 0000000..b5924df --- /dev/null +++ b/scripts/CSharp/Common/Fight/FighterVisual.cs @@ -0,0 +1,98 @@ +using System; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Fight.ActionDetails; +using Babushka.scripts.CSharp.Common.Fight.UI; +using Godot; +using Godot.Collections; + +namespace Babushka.scripts.CSharp.Common.Fight; + + +public partial class FighterVisual : Node2D +{ + #region Shortcuts + + private FightWorld.FightHappeningData HappeningData => + FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + + #endregion + + [ExportCategory("References")] + [Export] private Node2D _visualParent = null!; + [Export] private Node2D _targetSelectionParent = null!; + [Export] public FighterHealthBarVisual healthBarVisual = null!; + + + private FightWorld.Fighter _boundFighter; + + public void Initialize(FightWorld.Fighter fighter) + { + _boundFighter = fighter; + UpdateMirrorState(); + UpdateHealthBar(); + } + + /// + /// fighter visuals should always look to the right in the scene. + /// This function flips the sprites horizontally, when the fighter is an enemy. + /// + private void UpdateMirrorState() + { + _visualParent.Scale = new Vector2(_boundFighter.IsInFormation(HappeningData.enemyFighterFormation) ? -1 : 1, 1); + } + + public void UpdateHealthBar() + { + healthBarVisual.UpdateHealth(_boundFighter.GetHealth(), _boundFighter.maxHealth); + } + + public void SetTargetSelectionActive(bool value) + { + _targetSelectionParent.Visible = value; + _targetSelectionParent.ProcessMode = value ? ProcessModeEnum.Inherit : ProcessModeEnum.Disabled; + } + + // listen from inside + public void ClickedTarget() + { + if (HappeningData.actionStaging!.CurrentDetail() is not TargetSelectActionDetail targetDetail) + throw new InvalidOperationException("No target selection needed right now"); + + targetDetail.SetTarget(_boundFighter); + FightHappening.Instance.DetailFilled(); + } + + // Animations + public async Task AnimatePosToTarget(FighterVisual targetVisual, double duration = 0.15) + { + var tween = GetTree().CreateTween(); + tween.TweenProperty(_visualParent, "global_position", targetVisual.GlobalPosition, 0.15); + await ToSignal(tween, "finished"); + } + + public async Task AnimatePosToBase(double duration = 0.7) + { + var tween = GetTree().CreateTween(); + tween.TweenProperty(_visualParent, "position", new Vector2(0, 0), 0.15); + await ToSignal(tween, "finished"); + } + + public async Task AnimateHit() + { + var tween = GetTree().CreateTween(); + tween.TweenProperty(this, "scale", new Vector2(1.4f, 0.6f), 0.15); + tween.TweenProperty(this, "scale", new Vector2(1, 1), 0.4) + .SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out); + await ToSignal(tween, "finished"); + } + + // Keep for reference for new Heal animation + //public void HealAnimation() + //{ + // EmitSignalHealed(); + // var tween = GetTree().CreateTween(); + // tween.TweenProperty(this, "scale", new Vector2(0.6f, 1.4f), 0.15); + // tween.TweenProperty(this, "scale", new Vector2(1, 1), 0.4) + // .SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out); + //} +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/Fighter.cs.uid b/scripts/CSharp/Common/Fight/FighterVisual.cs.uid similarity index 100% rename from scripts/CSharp/Common/Fight/Fighter.cs.uid rename to scripts/CSharp/Common/Fight/FighterVisual.cs.uid diff --git a/scripts/CSharp/Common/Fight/NextRoomTrigger.cs b/scripts/CSharp/Common/Fight/NextRoomTrigger.cs new file mode 100644 index 0000000..23fbd45 --- /dev/null +++ b/scripts/CSharp/Common/Fight/NextRoomTrigger.cs @@ -0,0 +1,19 @@ +using Godot; +using System; +using Babushka.scripts.CSharp.Common.Fight; + +public partial class NextRoomTrigger : Area2D +{ + [Export] private int pathIndex; + + public override void _EnterTree() + { + BodyEntered += _OnBodyEnter; + } + + private void _OnBodyEnter(Node2D other) + { + var fss = GetNode("%FightSceneSwitcher"); + fss.SwitchRoom(pathIndex); + } +} diff --git a/scripts/CSharp/Common/Fight/NextRoomTrigger.cs.uid b/scripts/CSharp/Common/Fight/NextRoomTrigger.cs.uid new file mode 100644 index 0000000..085b5b8 --- /dev/null +++ b/scripts/CSharp/Common/Fight/NextRoomTrigger.cs.uid @@ -0,0 +1 @@ +uid://bryibv73x5iwr diff --git a/scripts/CSharp/Common/Fight/NoFightHappeningException.cs b/scripts/CSharp/Common/Fight/NoFightHappeningException.cs new file mode 100644 index 0000000..12587dd --- /dev/null +++ b/scripts/CSharp/Common/Fight/NoFightHappeningException.cs @@ -0,0 +1,7 @@ +using System; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public class NoFightHappeningException() : Exception("No fight happening right now") +{ +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/NoFightHappeningException.cs.uid b/scripts/CSharp/Common/Fight/NoFightHappeningException.cs.uid new file mode 100644 index 0000000..b0e51cf --- /dev/null +++ b/scripts/CSharp/Common/Fight/NoFightHappeningException.cs.uid @@ -0,0 +1 @@ +uid://b2n37glcxm8wv diff --git a/scripts/CSharp/Common/Fight/PathSetup.cs b/scripts/CSharp/Common/Fight/PathSetup.cs new file mode 100644 index 0000000..e95f916 --- /dev/null +++ b/scripts/CSharp/Common/Fight/PathSetup.cs @@ -0,0 +1,49 @@ +using System.Diagnostics; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class PathSetup : Node +{ + [Export] private int pathId; + + [ExportCategory("Variants")] [Export] private CanvasItem closedVariant; + [Export] private CanvasItem nextRoomVariant; + + public override void _Ready() + { + SetupPathVariant(); + } + + private void SetupPathVariant() + { + Debug.Assert(FightWorld.Instance.currentRoom != null); + if (FightWorld.Instance.currentRoom.paths.TryGetValue(pathId, out var nextRoom)) + { + ShowOnlyVariant(nextRoomVariant); + } + else + { + ShowOnlyVariant(closedVariant); + } + } + + private void ShowOnlyVariant(CanvasItem variantToShow) + { + HideVariant(closedVariant); + HideVariant(nextRoomVariant); + ShowVariant(variantToShow); + } + + private void ShowVariant(CanvasItem variant) + { + variant.Visible = true; + variant.ProcessMode = ProcessModeEnum.Always; + } + + private void HideVariant(CanvasItem variant) + { + variant.Visible = false; + variant.ProcessMode = ProcessModeEnum.Disabled; + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/PathSetup.cs.uid b/scripts/CSharp/Common/Fight/PathSetup.cs.uid new file mode 100644 index 0000000..7daf1ef --- /dev/null +++ b/scripts/CSharp/Common/Fight/PathSetup.cs.uid @@ -0,0 +1 @@ +uid://dpkx2gbg7b5xh diff --git a/scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs b/scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs new file mode 100644 index 0000000..c025054 --- /dev/null +++ b/scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs @@ -0,0 +1,20 @@ +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class RoamingEnemyGroup : Node2D +{ + private FightWorld.FighterGroup _boundEnemyGroup; + private FightSceneSwitcher _fightSceneSwitcher; + + public void Initialize(FightWorld.FighterGroup enemyGroup, FightSceneSwitcher fightSceneSwitcher) + { + _boundEnemyGroup = enemyGroup; + _fightSceneSwitcher = fightSceneSwitcher; + } + + public void StartFight() + { + _fightSceneSwitcher.SwitchToFight(_boundEnemyGroup); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs.uid b/scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs.uid new file mode 100644 index 0000000..8096990 --- /dev/null +++ b/scripts/CSharp/Common/Fight/RoamingEnemyGroup.cs.uid @@ -0,0 +1 @@ +uid://lequnojtar76 diff --git a/scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs b/scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs new file mode 100644 index 0000000..d4b0cd3 --- /dev/null +++ b/scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight; + +public partial class SwitchSceneOnFightEnd : Node +{ + [Export] private FightSceneSwitcher _fightSceneSwitcher = null!; + + public void OnFightStateEnter(FightHappening.FightState to) + { + if (to is FightHappening.FightState.PlayerWin + or FightHappening.FightState.EnemyWin) + _ = SwitchSceneAfterTime(2.0f); + } + + private async Task SwitchSceneAfterTime(float seconds) + { + await ToSignal(GetTree().CreateTimer(seconds), "timeout"); + _fightSceneSwitcher.ExitFight(); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs.uid b/scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs.uid new file mode 100644 index 0000000..66971c1 --- /dev/null +++ b/scripts/CSharp/Common/Fight/SwitchSceneOnFightEnd.cs.uid @@ -0,0 +1 @@ +uid://2f7rqk50gtdg diff --git a/scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs b/scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs new file mode 100644 index 0000000..538a630 --- /dev/null +++ b/scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs @@ -0,0 +1,35 @@ +using System.Linq; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight.UI; + +public partial class ActionSelectUiSetup : CanvasLayer +{ + // shortcuts + private FightWorld.FightHappeningData HappeningData => + FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); + private FightWorld.Fighter CurrentFighter => HappeningData.fighterTurn.Current; + + // references + [Export] private Button _attackActionButton = null!; + [Export] private Button _summonActionButton = null!; + [Export] private Button _talkActionButton = null!; + [Export] private Button _fleeActionButton = null!; + + // gets called from a state reaction enter (InputActionSelect) + public void StateEntered() + { + var actions = CurrentFighter.availableActions; + + _attackActionButton.Visible = actions.Any(a => a.BindToActionButton() == FighterAction.AllyActionButton.Attack); + _summonActionButton.Visible = actions.Any(a => a.BindToActionButton() == FighterAction.AllyActionButton.Summon); + _talkActionButton.Visible = actions.Any(a => a.BindToActionButton() == FighterAction.AllyActionButton.Talk); + _fleeActionButton.Visible = actions.Any(a => a.BindToActionButton() == FighterAction.AllyActionButton.Flee); + } + + public void SelectAction(FighterAction.AllyActionButton actionButton) + { + var action = CurrentFighter.availableActions.First(a => a.BindToActionButton() == actionButton); + FightHappening.Instance.ActionSelect(action); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs.uid b/scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs.uid new file mode 100644 index 0000000..f2b406c --- /dev/null +++ b/scripts/CSharp/Common/Fight/UI/ActionSelectUiSetup.cs.uid @@ -0,0 +1 @@ +uid://byf2ywov34g0x diff --git a/scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs b/scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs new file mode 100644 index 0000000..9af7959 --- /dev/null +++ b/scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs @@ -0,0 +1,14 @@ +using Godot; + +namespace Babushka.scripts.CSharp.Common.Fight.UI; + +[GlobalClass] +public partial class FighterHealthBarVisual : Node2D +{ + [Export] private Label _tmpHealthLabel = null!; + + public void UpdateHealth(int currentHealth, int maxHealth) + { + _tmpHealthLabel.Text = $"{currentHealth} / {maxHealth}"; + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs.uid b/scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs.uid new file mode 100644 index 0000000..80da99b --- /dev/null +++ b/scripts/CSharp/Common/Fight/UI/FighterHealthBarVisual.cs.uid @@ -0,0 +1 @@ +uid://b2dx06p6i7pu0 diff --git a/scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs b/scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs new file mode 100644 index 0000000..285b5b5 --- /dev/null +++ b/scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs @@ -0,0 +1,16 @@ +using Godot; +using System; + +public partial class TargetSelectionClick : Area2D +{ + [Signal] + public delegate void TargetSelectedEventHandler(); + + public override void _InputEvent(Viewport viewport, InputEvent @event, int shapeIdx) + { + if (@event is InputEventMouseButton { Pressed: true, ButtonIndex: MouseButton.Left }) + { + EmitSignalTargetSelected(); + } + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs.uid b/scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs.uid new file mode 100644 index 0000000..8900cec --- /dev/null +++ b/scripts/CSharp/Common/Fight/UI/TargetSelectionClick.cs.uid @@ -0,0 +1 @@ +uid://boprnfciqgixf diff --git a/scripts/CSharp/Common/Fight/FightAttack.cs b/scripts/CSharp/Common/FightOld/FightAttack.cs similarity index 66% rename from scripts/CSharp/Common/Fight/FightAttack.cs rename to scripts/CSharp/Common/FightOld/FightAttack.cs index 0c1248f..0397486 100644 --- a/scripts/CSharp/Common/Fight/FightAttack.cs +++ b/scripts/CSharp/Common/FightOld/FightAttack.cs @@ -4,6 +4,6 @@ public class FightAttack { public int damage; public bool needsSelectedTarget; - public Fighter? target; - public Fighter attacker; + public FighterVisual? target; + public FighterVisual attacker; } \ No newline at end of file diff --git a/scripts/CSharp/Common/Fight/FightAttack.cs.uid b/scripts/CSharp/Common/FightOld/FightAttack.cs.uid similarity index 100% rename from scripts/CSharp/Common/Fight/FightAttack.cs.uid rename to scripts/CSharp/Common/FightOld/FightAttack.cs.uid diff --git a/scripts/CSharp/Common/Fight/FightManager.cs b/scripts/CSharp/Common/FightOld/FightManager.cs similarity index 79% rename from scripts/CSharp/Common/Fight/FightManager.cs rename to scripts/CSharp/Common/FightOld/FightManager.cs index ef0652c..8376864 100644 --- a/scripts/CSharp/Common/Fight/FightManager.cs +++ b/scripts/CSharp/Common/FightOld/FightManager.cs @@ -19,10 +19,10 @@ public partial class FightManager : Node public FightParty fightParty = new(); - public void StartFight(PackedScene[] enemies, FightInstance instance) + public void StartFight(PackedScene[] enemies, FightHappening happening) { GD.Print("Starting Fight"); - instance.Start(fightParty, enemies); + //happening.Start(fightParty, enemies); } } diff --git a/scripts/CSharp/Common/Fight/FightManager.cs.uid b/scripts/CSharp/Common/FightOld/FightManager.cs.uid similarity index 100% rename from scripts/CSharp/Common/Fight/FightManager.cs.uid rename to scripts/CSharp/Common/FightOld/FightManager.cs.uid diff --git a/scripts/CSharp/Common/Fight/FightParty.cs b/scripts/CSharp/Common/FightOld/FightParty.cs similarity index 100% rename from scripts/CSharp/Common/Fight/FightParty.cs rename to scripts/CSharp/Common/FightOld/FightParty.cs diff --git a/scripts/CSharp/Common/Fight/FightParty.cs.uid b/scripts/CSharp/Common/FightOld/FightParty.cs.uid similarity index 100% rename from scripts/CSharp/Common/Fight/FightParty.cs.uid rename to scripts/CSharp/Common/FightOld/FightParty.cs.uid diff --git a/scripts/CSharp/Common/Fight/FightStarter.cs b/scripts/CSharp/Common/FightOld/FightStarter.cs similarity index 76% rename from scripts/CSharp/Common/Fight/FightStarter.cs rename to scripts/CSharp/Common/FightOld/FightStarter.cs index 0fd6ae8..780aef0 100644 --- a/scripts/CSharp/Common/Fight/FightStarter.cs +++ b/scripts/CSharp/Common/FightOld/FightStarter.cs @@ -4,7 +4,7 @@ namespace Babushka.scripts.CSharp.Common.Fight; public partial class FightStarter : Node { [Export(PropertyHint.ArrayType)] private PackedScene[] enemies; - [Export] private FightInstance _fightInstance; + //[Export] private FightHappening _fightHappening; [Export] private bool _once = true; private bool hasBeenStarted = false; @@ -14,6 +14,6 @@ public partial class FightStarter : Node return; hasBeenStarted = true; - FightManager.Instance.StartFight(enemies, _fightInstance); + //FightManager.Instance.StartFight(enemies, _fightHappening); } } diff --git a/scripts/CSharp/Common/Fight/FightStarter.cs.uid b/scripts/CSharp/Common/FightOld/FightStarter.cs.uid similarity index 100% rename from scripts/CSharp/Common/Fight/FightStarter.cs.uid rename to scripts/CSharp/Common/FightOld/FightStarter.cs.uid diff --git a/scripts/CSharp/Common/Minigame/MinigameController.cs b/scripts/CSharp/Common/Minigame/MinigameController.cs new file mode 100644 index 0000000..9fb4bc1 --- /dev/null +++ b/scripts/CSharp/Common/Minigame/MinigameController.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Babushka.scripts.CSharp.Common.Util; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Minigame; + +public partial class MinigameController : Node2D +{ + public enum RegionTheme + { + Disabled, + VeryBad, + Bad, + Normal, + NormalAlt1, + NormalAlt2, + God, + VeryGood + } + + public class Builder + { + internal class Region + { + public required T value; + public float proportion = 1f; + public string text = ""; + public RegionTheme theme = RegionTheme.Normal; + } + + public enum DoubleHitHandling + { + Allow, + Disallow, + Remove, + } + + internal List regions = new(); + internal DoubleHitHandling doubleHitHandling = DoubleHitHandling.Allow; + internal int maxHitCount = 3; + + // add region + public Builder AddRegion(T value) + { + regions.Add(new Region { value = value }); + return this; + } + + // region settings + public Builder RegionWithProportion(float proportion) + { + if (regions.Count == 0) + throw new InvalidOperationException("No region to set proportion for"); + + regions.Last().proportion = proportion; + return this; + } + + public Builder RegionWithText(string text) + { + if (regions.Count == 0) + throw new InvalidOperationException("No region to set text for"); + + regions.Last().text = text; + return this; + } + + public Builder RegionWithTheme(RegionTheme theme) + { + if (regions.Count == 0) + throw new InvalidOperationException("No region to set theme for"); + + regions.Last().theme = theme; + return this; + } + + // general settings + public Builder WithDoubleHitHandling(DoubleHitHandling handling) + { + if (handling != DoubleHitHandling.Allow) + throw new NotImplementedException(); + + doubleHitHandling = handling; + return this; + } + + public Builder WithHitCount(int hitCount) + { + this.maxHitCount = hitCount; + return this; + } + } + + private TaskCompletionSource? _minigameComplete; + private List? _hits; + private float _armPosition = 0f; + private float _armSpeed = 1f; + private List? _regions; + private int _maxHitCount; + + [Export] private PackedScene _regionVisualPrefab = null!; + [Export] private Node2D _regionsParent = null!; + [Export] private Color _baseRegionColor = Colors.Red; + + [Signal] public delegate void ArmMovedEventHandler(float newPos); + + public override void _EnterTree() + { + HideMinigame(); + } + + public override void _Process(double delta) + { + _armPosition += _armSpeed * (float)delta; + _armPosition = Mathf.PosMod(_armPosition, 1); + EmitSignalArmMoved(_armPosition); + } + + public async Task> Run(Builder builder) + { + ShowMinigame(); + Setup(builder); + await _minigameComplete!.Task; + var returnValue = _hits!.Select(h => builder.regions[h].value).ToList(); + Reset(); + HideMinigame(); + return returnValue; + } + + public void Hit() + { + if (_hits == null) return; + + int i; + for (i = 0; i < _regions!.Count - 1; i++) + { + if (_armPosition < _regions[i]) + { + break; + } + } + + _hits.Add(i); + + _armSpeed = -_armSpeed; + + if (_hits.Count >= _maxHitCount) + { + _minigameComplete!.SetResult(); + } + } + + private void Setup(Builder builder) + { + _minigameComplete = new(); + _hits = []; + _armPosition = 0f; + _armSpeed = 1f; + _regions = []; + + SetupRegions(builder); + + _maxHitCount = builder.maxHitCount; + } + + private void SetupRegions(Builder builder) + { + // common calculations + var totalRegionProportion = builder.regions.Sum(r => r.proportion); + + // spawn regions + var regionSum = 0f; + foreach (var region in builder.regions) + { + var regionVisual = _regionVisualPrefab.Instantiate(); + _regionsParent.AddChild(regionVisual); + + var normalisedAngleStart = regionSum / totalRegionProportion; + var normalisedAngleEnd = (regionSum + region.proportion) / totalRegionProportion; + var normalAngles = new Vector2(normalisedAngleStart, normalisedAngleEnd); + + regionVisual.Setup(normalAngles, _baseRegionColor.RandomHue(), region.text, region.theme); + + regionSum += region.proportion; + + _regions!.Add(normalisedAngleEnd); + } + } + + private void ShowMinigame() + { + Show(); + ProcessMode = ProcessModeEnum.Inherit; + } + + private void HideMinigame() + { + Hide(); + ProcessMode = ProcessModeEnum.Disabled; + } + + private void Reset() + { + _minigameComplete = null; + _hits = null; + _regionsParent.GetChildren().ForEach(c => c.QueueFree()); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Minigame/MinigameController.cs.uid b/scripts/CSharp/Common/Minigame/MinigameController.cs.uid new file mode 100644 index 0000000..248e5e6 --- /dev/null +++ b/scripts/CSharp/Common/Minigame/MinigameController.cs.uid @@ -0,0 +1 @@ +uid://ct7l4er2kljnc diff --git a/scripts/CSharp/Common/Minigame/RegionVisual.cs b/scripts/CSharp/Common/Minigame/RegionVisual.cs new file mode 100644 index 0000000..47c2f25 --- /dev/null +++ b/scripts/CSharp/Common/Minigame/RegionVisual.cs @@ -0,0 +1,32 @@ +using Godot; +using System; +using Babushka.scripts.CSharp.Common.Minigame; +using Godot.Collections; + +public partial class RegionVisual : Node +{ + [Export] private Sprite2D _sliceSprite; + [Export] private Label _textLabel; + [Export] private Node2D _labelPivot; + + [Export(PropertyHint.DictionaryType)] private Dictionary _fillColors = new(); + + public void Setup(Vector2 normalAngles, Color color, string regionText, MinigameController.RegionTheme regionTheme) + { + var mat = (_sliceSprite.Material as ShaderMaterial)!; + mat.SetShaderParameter("angles", normalAngles); + mat.SetShaderParameter("fillColor", GetFillColor(regionTheme)); + + var averageAngleRadians = (normalAngles.X + normalAngles.Y) * float.Pi; // '/ 2' from the average and '* 2' from the radians cancel out + _labelPivot.Rotation = averageAngleRadians; + _textLabel.Rotation = -averageAngleRadians; + + _textLabel.Text = regionText; + } + + private Color GetFillColor(MinigameController.RegionTheme theme) + { + if (_fillColors.TryGetValue(theme, out var color)) return color; + throw new InvalidOperationException($"No fill color for theme {theme}"); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Minigame/RegionVisual.cs.uid b/scripts/CSharp/Common/Minigame/RegionVisual.cs.uid new file mode 100644 index 0000000..72e65b1 --- /dev/null +++ b/scripts/CSharp/Common/Minigame/RegionVisual.cs.uid @@ -0,0 +1 @@ +uid://cdpsa4qrlai31 diff --git a/scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs b/scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs new file mode 100644 index 0000000..772cdef --- /dev/null +++ b/scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs @@ -0,0 +1,10 @@ +using Godot; +using System; + +public partial class SpinnyArmVisual : Node2D +{ + public void SetAngle(float normalAngle) + { + Rotation = normalAngle * float.Pi * 2; + } +} diff --git a/scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs.uid b/scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs.uid new file mode 100644 index 0000000..663cb3c --- /dev/null +++ b/scripts/CSharp/Common/Minigame/SpinnyArmVisual.cs.uid @@ -0,0 +1 @@ +uid://djkyrp24ljff0 diff --git a/scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs b/scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs new file mode 100644 index 0000000..63af215 --- /dev/null +++ b/scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; +using Babushka.scripts.CSharp.Common.Minigame; +using Godot; + +namespace Babushka.scripts.CSharp.Common.TestScripts; + +public partial class MinigameTestStarter : Node +{ + [Export] private MinigameController _minigameController = null!; + + public override void _Ready() + { + _minigameController.Run( + new MinigameController.Builder() + .WithHitCount(5) + .AddRegion(1) + .AddRegion(2).RegionWithProportion(2) + .AddRegion(3) + .AddRegion(4).RegionWithProportion(2) + .AddRegion(5) + .AddRegion(6).RegionWithProportion(2) + ).ContinueWith(task => OnEnd(task.Result)); + } + + private void OnEnd(List result) + { + GD.Print(string.Join(" ,", result)); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs.uid b/scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs.uid new file mode 100644 index 0000000..6e25630 --- /dev/null +++ b/scripts/CSharp/Common/TestScripts/MinigameTestStarter.cs.uid @@ -0,0 +1 @@ +uid://iv0dbf32bfw1 diff --git a/scripts/CSharp/Common/Util/ClickDetect.cs b/scripts/CSharp/Common/Util/ClickDetect.cs new file mode 100644 index 0000000..894ce33 --- /dev/null +++ b/scripts/CSharp/Common/Util/ClickDetect.cs @@ -0,0 +1,16 @@ +using Godot; + +namespace Babushka.scripts.CSharp.Common.Util; + +public partial class ClickDetect : Area2D +{ + [Signal] public delegate void ClickEventHandler(); + + public override void _Input(InputEvent evt) + { + if (evt is InputEventMouseButton { ButtonIndex: MouseButton.Left, Pressed: true }) + { + EmitSignalClick(); + } + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Util/ClickDetect.cs.uid b/scripts/CSharp/Common/Util/ClickDetect.cs.uid new file mode 100644 index 0000000..b4b1fee --- /dev/null +++ b/scripts/CSharp/Common/Util/ClickDetect.cs.uid @@ -0,0 +1 @@ +uid://dq7gahfp0lk7v diff --git a/scripts/CSharp/Common/Util/LinqExtras.cs b/scripts/CSharp/Common/Util/LinqExtras.cs index 92a79c1..edb8aee 100644 --- a/scripts/CSharp/Common/Util/LinqExtras.cs +++ b/scripts/CSharp/Common/Util/LinqExtras.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Data.SqlTypes; using System.Linq; using System.Xml.Schema; +using Godot; + namespace Babushka.scripts.CSharp.Common.Util; public static class LinqExtras @@ -16,6 +18,16 @@ public static class LinqExtras } } + public static void ForEach(this IEnumerable self, Action action) + { + var i = 0; + foreach (var t in self) + { + action.Invoke(t, i); + i++; + } + } + public static T? Random(this IEnumerable self) { var selfList = self.ToList(); @@ -24,4 +36,23 @@ public static class LinqExtras var randomIndex = new Random().Next(0, selfList.Count); return selfList[randomIndex]; } + + public static IEnumerable Shuffle(this IEnumerable self) + { + var selfList = self.ToList(); + var random = new Random(); + for (var i = 0; i < selfList.Count; i++) + { + var j = random.Next(i, selfList.Count); + (selfList[i], selfList[j]) = (selfList[j], selfList[i]); + } + return selfList; + } + + public static Color RandomHue(this Color color) + { + color.ToHsv(out _, out float saturation, out var value ); + var rng = new RandomNumberGenerator(); + return Color.FromHsv(rng.Randf(), saturation, value); + } } diff --git a/scripts/CSharp/Common/Util/Variant.cs b/scripts/CSharp/Common/Util/Variant.cs new file mode 100644 index 0000000..7ef303b --- /dev/null +++ b/scripts/CSharp/Common/Util/Variant.cs @@ -0,0 +1,63 @@ +using System; +using System.Diagnostics; + +namespace Babushka.scripts.CSharp.Common.Util; + +public class Variant +{ + private Type _type; + private Object _value; + + public Type GetVariantType() + { + return _type; + } + + public T GetValue() + { + if (_type != typeof(T)) + throw new ArgumentOutOfRangeException( + $"The Variant does not store a {typeof(T)}. The current type is {_type}"); + + return (T)_value; + } + + public void SetValue(T value) + { + if (typeof(T1) != typeof(T) && typeof(T2) != typeof(T)) + throw new ArgumentOutOfRangeException( + $"The Variant does not support type {typeof(T)}. Supported types are {typeof(T1)} and {typeof(T2)}"); + + _type = typeof(T); + _value = value!; + } + + public static implicit operator T1(Variant v) + { + return v.GetValue(); + } + + public static implicit operator T2(Variant v) + { + return v.GetValue(); + } + + public static implicit operator Variant(T1 t) + { + return new Variant { _type = typeof(T1), _value = t! }; + } + + public static implicit operator Variant(T2 t) + { + return new Variant { _type = typeof(T2), _value = t! }; + } + + public bool IsType() + { + if (typeof(T1) != typeof(T) && typeof(T2) != typeof(T)) + throw new ArgumentOutOfRangeException( + $"The Variant does not support type {typeof(T)}. Supported types are {typeof(T1)} and {typeof(T2)}"); + + return _type == typeof(T); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Util/Variant.cs.uid b/scripts/CSharp/Common/Util/Variant.cs.uid new file mode 100644 index 0000000..e9fac77 --- /dev/null +++ b/scripts/CSharp/Common/Util/Variant.cs.uid @@ -0,0 +1 @@ +uid://bxs7sn7j3vd0n diff --git a/shader/minigame_pie_section.gdshader b/shader/minigame_pie_section.gdshader new file mode 100644 index 0000000..f7a3fe5 --- /dev/null +++ b/shader/minigame_pie_section.gdshader @@ -0,0 +1,72 @@ +shader_type canvas_item; + +uniform float textureSize = 400.0; +uniform vec3 fillColor:source_color = vec3(1.0,0.0,0.0); +uniform vec3 borderColor:source_color = vec3(1.0,1.0,1.0); +uniform float borderWidth = 0.1; +uniform vec2 angles = vec2(0.2,0.4); +uniform float smoothWidth:hint_range(0.0001, 0.1, 0.0001) = 0.01; + +void vertex() { + +} + +//vec2 polar_coordinates(vec2 uv, vec2 center, vec2 tps) { +// vec2 dir = uv - center*textureSize*tps.x; +// dir = vec2(dir.y,-dir.x); +// float radius = length(dir) * 2.0; +// float angle = atan(dir.y, dir.x) * 1.0/(3.1416 * 2.0); +// return vec2(radius/(textureSize*tps.x), angle + 0.5); +//} + +float sd_circle(vec2 norm_uv,float radius){ + float d = distance(norm_uv,vec2(0.0)); + return d - radius; +} + +float sd_line(vec2 norm_uv){ + return norm_uv.x; +} + +vec2 rotate_uv(vec2 norm_uv, float angle_normal){ + float angle_rad = angle_normal * 2.0 * PI; + mat2 rotation = mat2(vec2( cos(angle_rad), sin(angle_rad)), + vec2(-sin(angle_rad), cos(angle_rad))); + return norm_uv * rotation; +} + +vec2 normalize_uv(vec2 uv,vec2 tps){ + vec2 zeroToOne = uv / (textureSize*tps); + return zeroToOne*2.0-1.0; +} + +void fragment() { + //vec2 pc = polar_coordinates(UV,vec2(0.5,0.5),TEXTURE_PIXEL_SIZE); + //bool isIn = pc.x<1.0 && pc.y > 0.2 && pc.y < 0.9; + ////bool isIn = TEXTURE_PIXEL_SIZE.x < 1.0/3.99; + ////COLOR = vec4(pc.x,pc.y,0,1); + //COLOR.a = isIn?1.0f:0.0f; + //COLOR.rgb = (pc.x > 1.0-borderWidth)?borderColor:fillColor; + vec2 normal_uv = normalize_uv(UV,TEXTURE_PIXEL_SIZE); + //vec2 normal_uv = VERTEX; + bool isBigAngle = angles.y - angles.x >0.5; + float line1 = sd_line(rotate_uv(normal_uv,angles.x)); + float line2 = sd_line(rotate_uv(normal_uv,angles.y)); + float linesCombined = isBigAngle ? min(-line1,line2):max(-line1,line2); + float circle = sd_circle(normal_uv,0.95); + float final_distance = max(linesCombined,circle); + //float final_distance = sd_line(normal_uv); + COLOR.a = 1.0-smoothstep(0.0,1.0, final_distance/smoothWidth); + //COLOR.r = 0.0; + //COLOR.g = 0.0; + //COLOR.b = 0.0; + //COLOR.rg = VERTEX*SCREEN_PIXEL_SIZE; + //COLOR.rg = UV*TEXTURE_PIXEL_SIZE; + //COLOR.rg = center; + COLOR.rgb = fillColor; +} + +//void light() { +// // Called for every pixel for every light affecting the CanvasItem. +// // Uncomment to replace the default light processing function with this one. +//} diff --git a/shader/minigame_pie_section.gdshader.uid b/shader/minigame_pie_section.gdshader.uid new file mode 100644 index 0000000..050a7d5 --- /dev/null +++ b/shader/minigame_pie_section.gdshader.uid @@ -0,0 +1 @@ +uid://d0dayn7dc885j diff --git a/shader/swaying_plant.gdshader b/shader/swaying_plant.gdshader index 01c04ce..42a0f76 100644 --- a/shader/swaying_plant.gdshader +++ b/shader/swaying_plant.gdshader @@ -26,7 +26,6 @@ uniform float heightOffset : hint_range(0.0, 1.0); // With the offset value, you can if you want different moves for each asset. Just put a random value (1, 2, 3) in the editor. Don't forget to mark the material as unique if you use this uniform float offset = 0; - float getWind(vec2 vertex, vec2 uv, float time){ float diff = pow(maxStrength - minStrength, 2.0); float strength = clamp(minStrength + diff + sin(time / interval) * diff, minStrength, maxStrength) * strengthScale;