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;