Fight happening base setup

pull/22/head
jonathan 4 months ago
parent fd0e631b1f
commit f27dd199b8

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=53eecf85_002Dd821_002D40e8_002Dac97_002Dfdb734542b84/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Description/@EntryValue">Godot Signal</s:String> <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Description/@EntryValue">Godot Signal</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Text/@EntryValue">[Signal] <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Text/@EntryValue">[Signal]
public delegate void $SignalName$EventHandler($END$);</s:String> public delegate void $SignalName$EventHandler($END$);</s:String>

@ -19,4 +19,15 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Ff1d69ec2da76ccf9bc8a75c8e0fdca9a7ba1adf8c8c9d5047e2fa5991c02eca_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Ff1d69ec2da76ccf9bc8a75c8e0fdca9a7ba1adf8c8c9d5047e2fa5991c02eca_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceLoader_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F9f4e8eb124d11f8219cb513a19bed22b2120ed29f9d6785ba56e3367b48d581_003FResourceLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceLoader_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F9f4e8eb124d11f8219cb513a19bed22b2120ed29f9d6785ba56e3367b48d581_003FResourceLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceLoader_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F9f4e8eb124d11f8219cb513a19bed22b2120ed29f9d6785ba56e3367b48d581_003FResourceLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceLoader_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F9f4e8eb124d11f8219cb513a19bed22b2120ed29f9d6785ba56e3367b48d581_003FResourceLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fc7102cd0ffb8973777e61b1942c3fffac7e14016a511d055c3adf73ff91748_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fc7102cd0ffb8973777e61b1942c3fffac7e14016a511d055c3adf73ff91748_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnumerable_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F76fabf6f8acf4a0099cae0bcf8b218467f10_003F7e_003F28cee476_003FEnumerable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGD_005Fconstants_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F4ef0bac6437b6a9567d44f62ae567d854fa7b8513ef7139ef349b49768bc9df_003FGD_005Fconstants_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Ff1d69ec2da76ccf9bc8a75c8e0fdca9a7ba1adf8c8c9d5047e2fa5991c02eca_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceLoader_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F9f4e8eb124d11f8219cb513a19bed22b2120ed29f9d6785ba56e3367b48d581_003FResourceLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASceneTree_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F8d6960554e939a669841b1ece03d27df4ab42f92bb80be3767eaec8cdaccf84b_003FSceneTree_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fc7102cd0ffb8973777e61b1942c3fffac7e14016a511d055c3adf73ff91748_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=bc5a80e4_002D7ba6_002D4f7d_002Db896_002Dc591eec7ab12/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="Tests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;NUnit3x::A6EF2269-9E64-40D4-BA0A-33CB234E2503::net9.0::BabushkaTest.Tests&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>

@ -0,0 +1,9 @@
[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" node_paths=PackedStringArray("sceneRoot")]
script = ExtResource("1_5dt1r")
sceneRoot = NodePath("")
fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn"
fightHappeningScene = "res://scenes/Babushka_scene_fight_happening.tscn"

@ -1,7 +1,7 @@
[gd_scene load_steps=10 format=3 uid="uid://bp64p6y72j71w"] [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="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/FightOld/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="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="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"] [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" name = "Blob"
maxHealth = 20 maxHealth = 20
attackStrength = 10 attackStrength = 10
maxActions = null
_attackButtons = NodePath("FightButtons") _attackButtons = NodePath("FightButtons")
_targetButtons = NodePath("TargetButtons") _targetButtons = NodePath("TargetButtons")
_targetMarker = NodePath("TargetButtons/TargetMarker") _targetMarker = NodePath("TargetButtons/TargetMarker")
@ -95,9 +96,6 @@ stream = ExtResource("6_vbkts")
[node name="AttackAudio" type="AudioStreamPlayer" parent="."] [node name="AttackAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("6_oykh8") 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="input_event" from="TargetButtons/Area2D" to="." method="TargetMouseEvent"]
[connection signal="mouse_entered" from="TargetButtons/Area2D" to="." method="StartHoverTarget"] [connection signal="mouse_entered" from="TargetButtons/Area2D" to="." method="StartHoverTarget"]
[connection signal="mouse_exited" from="TargetButtons/Area2D" to="." method="EndHoverTarget"] [connection signal="mouse_exited" from="TargetButtons/Area2D" to="." method="EndHoverTarget"]

@ -1,6 +1,6 @@
[gd_scene load_steps=10 format=3 uid="uid://cr66tpdr5rma5"] [gd_scene load_steps=10 format=3 uid="uid://cr66tpdr5rma5"]
[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/FightOld/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://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://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"] [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"] [sub_resource type="CircleShape2D" id="CircleShape2D_s74nc"]
radius = 173.44 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") 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="."] [node name="Visual" type="Node2D" parent="."]

@ -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")

@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://cnjsepvaqdbyq"] [gd_scene load_steps=3 format=3 uid="uid://cnjsepvaqdbyq"]
[ext_resource type="Script" uid="uid://j5ge24rk25wm" path="res://scripts/CSharp/Common/FightOld/FightManager.cs" id="1_8p7ev"] [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"] [ext_resource type="PackedScene" uid="uid://cpanatqdjjpa3" path="res://prefabs/fight/fighters/vesna_fighter.tscn" id="2_ak1vo"]
[node name="FightManagerAutoload" type="Node"] [node name="FightManagerAutoload" type="Node"]
script = ExtResource("1_8p7ev") script = ExtResource("1_8p7ev")

@ -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/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="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"]

@ -0,0 +1,136 @@
[gd_scene load_steps=4 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://dwsqst8fhhqlc" path="res://scripts/CSharp/Common/Fight/FighterEntryVisual.cs" id="2_lu4y4"]
[ext_resource type="PackedScene" uid="uid://bcld43daavmrn" path="res://prefabs/fight/fight_scene_switcher.tscn" id="2_phrlx"]
[node name="BabushkaSceneFightHappening" type="Node2D"]
[node name="Camera2D" type="Camera2D" parent="."]
[node name="FightSetup" type="Node2D" parent="."]
script = ExtResource("1_fiutj")
[node name="FightVisuals" type="Node2D" parent="."]
position = Vector2(0, 259)
script = ExtResource("2_lu4y4")
[node name="AllyFighters" type="Node2D" parent="FightVisuals"]
[node name="EnemyFighters" type="Node2D" parent="FightVisuals"]
[node name="EnvironmentVisuals" type="Node2D" parent="."]
[node name="FightSceneSwitcher" parent="." instance=ExtResource("2_phrlx")]
[node name="ActionSelect" type="CanvasLayer" parent="."]
[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"

@ -38,8 +38,8 @@
[ext_resource type="Texture2D" uid="uid://bely5cfbf2x52" path="res://art/nature/baum märz 2025/umgeknackst.png" id="36_vwtyh"] [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://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://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/FightSceneSetup.cs" id="37_hqa4k"] [ext_resource type="Script" path="res://scripts/CSharp/Common/Fight/FightSceneSetup.cs" id="37_hqa4k"]
[ext_resource type="Script" uid="uid://cql8mt5jsmcdl" path="res://scripts/CSharp/Common/Fight/FightSceneSwitcher.cs" id="38_ir2xa"] [ext_resource type="PackedScene" uid="uid://bcld43daavmrn" path="res://prefabs/fight/fight_scene_switcher.tscn" id="40_elhbh"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ruj2u"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_ruj2u"]
shader = ExtResource("16_0fard") shader = ExtResource("16_0fard")
@ -89,15 +89,15 @@ noise = SubResource("FastNoiseLite_wgikv")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_yvxfs"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_yvxfs"]
shader = ExtResource("27_txtka") shader = ExtResource("27_txtka")
shader_parameter/speed = 1.0 shader_parameter/speed = 0.4
shader_parameter/minStrength = 0.05 shader_parameter/minStrength = 0.101
shader_parameter/maxStrength = 0.187 shader_parameter/maxStrength = 0.392
shader_parameter/strengthScale = 100.0 shader_parameter/strengthScale = 270.22
shader_parameter/interval = 3.5 shader_parameter/interval = 36.75
shader_parameter/detail = 2.095 shader_parameter/detail = 3.68
shader_parameter/distortion = 1.0 shader_parameter/distortion = 1.0
shader_parameter/heightOffset = 0.51 shader_parameter/heightOffset = 0.49
shader_parameter/offset = 1.0 shader_parameter/offset = 0.2
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ir2xa"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_ir2xa"]
size = Vector2(608, 1256) size = Vector2(608, 1256)
@ -729,6 +729,34 @@ position = Vector2(3888, 2688)
scale = Vector2(16, 5.48) scale = Vector2(16, 5.48)
texture = SubResource("NoiseTexture2D_pjpt5") 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="."] [node name="YSorted" type="Node2D" parent="."]
z_index = 1 z_index = 1
y_sort_enabled = true y_sort_enabled = true
@ -1846,15 +1874,6 @@ texture = ExtResource("35_g3bna")
region_enabled = true region_enabled = true
region_rect = Rect2(0, 0, 1405.76, 1244) region_rect = Rect2(0, 0, 1405.76, 1244)
[node name="TreeA4" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"]
z_index = 120
material = SubResource("ShaderMaterial_yvxfs")
position = Vector2(23840, 5685)
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"] [node name="TreeA2" type="Sprite2D" parent="YSorted/ForestVisuals/Static/greenery/trees"]
z_index = -1 z_index = -1
material = SubResource("ShaderMaterial_yvxfs") material = SubResource("ShaderMaterial_yvxfs")
@ -2009,7 +2028,7 @@ scale = Vector2(1, 1)
z_index = 100 z_index = 100
y_sort_enabled = true y_sort_enabled = true
material = SubResource("ShaderMaterial_yvxfs") material = SubResource("ShaderMaterial_yvxfs")
position = Vector2(411, 868) position = Vector2(304, 1029)
rotation = 3.14159 rotation = 3.14159
scale = Vector2(5.54387, -3.80466) scale = Vector2(5.54387, -3.80466)
texture = ExtResource("19_edja8") texture = ExtResource("19_edja8")
@ -2099,7 +2118,7 @@ scale = Vector2(1, 1)
z_index = 100 z_index = 100
y_sort_enabled = true y_sort_enabled = true
material = SubResource("ShaderMaterial_yvxfs") material = SubResource("ShaderMaterial_yvxfs")
position = Vector2(653, -450) position = Vector2(559, -459)
rotation = 3.14159 rotation = 3.14159
scale = Vector2(5.54387, -3.80466) scale = Vector2(5.54387, -3.80466)
texture = ExtResource("19_edja8") texture = ExtResource("19_edja8")
@ -2122,11 +2141,8 @@ unique_name_in_owner = true
script = ExtResource("37_hqa4k") script = ExtResource("37_hqa4k")
debugLabel = NodePath("../Debug Label") debugLabel = NodePath("../Debug Label")
[node name="FightSceneSwitcher" type="Node" parent="." node_paths=PackedStringArray("sceneRoot")] [node name="FightSceneSwitcher" parent="." instance=ExtResource("40_elhbh")]
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("38_ir2xa")
sceneRoot = NodePath("..")
fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn"
[node name="Debug Label" type="Label" parent="."] [node name="Debug Label" type="Label" parent="."]
offset_left = 10485.0 offset_left = 10485.0

@ -26,10 +26,10 @@
[ext_resource type="Shader" uid="uid://xnky830dtfsn" path="res://shader/repeat_texture.gdshader" id="25_sgom5"] [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/FightOld/FightStarter.cs" id="26_gg38r"] [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://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://bp64p6y72j71w" path="res://prefabs/fight/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://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://ddpl8cbck7e6s" path="res://prefabs/characters/Chugar.tscn" id="29_26tkn"]
[ext_resource type="PackedScene" uid="uid://cr66tpdr5rma5" path="res://prefabs/fightOld/fighters/enemy_mavkha_fighter.tscn" id="29_hfhye"] [ext_resource type="PackedScene" uid="uid://cr66tpdr5rma5" path="res://prefabs/fight/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://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="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"] [ext_resource type="Texture2D" uid="uid://dyueumlr5ltvr" path="res://art/nature/baum märz 2025/megaeichel megaast.png" id="37_gg38r"]

@ -105,6 +105,7 @@ _data = {
} }
[node name="SceneTransition" type="CanvasLayer" node_paths=PackedStringArray("animationPlayer")] [node name="SceneTransition" type="CanvasLayer" node_paths=PackedStringArray("animationPlayer")]
layer = 100
script = ExtResource("1_e0bkc") script = ExtResource("1_e0bkc")
animationPlayer = NodePath("SceneFadeAnimation") animationPlayer = NodePath("SceneFadeAnimation")

@ -18,10 +18,13 @@ public partial class CameraController : Camera2D
[Export] private Node2D _followNode; [Export] private Node2D _followNode;
public FightInstance? fightToShow; public FightHappening? fightToShow;
public override void _Process(double delta) public override void _Process(double delta)
{ {
this.GlobalPosition = fightToShow?.camPositionNode.GlobalPosition ?? _followNode.GlobalPosition; this.GlobalPosition = /*fightToShow?.camPositionNode.GlobalPosition ??*/ _followNode.GlobalPosition;
} }
} }

@ -0,0 +1,34 @@
using Godot;
using System;
using Babushka.scripts.CSharp.Common.Fight;
public partial class AllFightersVisual : Node
{
[Export] private Node2D _allyFighters;
[Export] private Node2D _enemyFighters;
[Export] private PackedScene _blobFighterVisual;
[Export] private PackedScene _bigBlobFighterVisual;
[Export] private PackedScene _mavkaFighterVisual;
[Export] private PackedScene _yourMomFighterVisual;
[Export] private PackedScene _vesnaFighterVisual;
public void EnterFighter(FightWorld.Fighter fighter, bool isEnemy)
{
var parent = isEnemy ? _enemyFighters : _allyFighters;
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>();
fighterVisual.Initialize(fighter);
parent.AddChild(fighterVisual);
}
}

@ -0,0 +1,320 @@
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 class FightHappening
{
/*
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,
}
private class FightersEnterStaging
{
public required List<FightWorld.Fighter> enteringAllyFighters;
public required List<FightWorld.Fighter> enteringEnemyFighters;
public bool HasAnyToExecute()
{
return enteringAllyFighters.Count != 0 || enteringEnemyFighters.Count != 0;
}
}
#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.fighterStack.Current;
#endregion
#region Events
public event Action<FightState>? transitionFromState;
public event Action<FightState, FightState>? transitionState;
public event Action<FightState>? transitionToState;
#endregion
#region Staging
private FightersEnterStaging? _fightersEnterStaging;
private FighterAction? _actionStaging;
#endregion
#region Public Methods
public void StartFight()
{
RequireState(FightState.None);
ChangeState(FightState.FightStartAnim);
}
#endregion
#region State Machine
private void ChangeState(FightState nextState)
{
TransitionFromState();
var lastState = HappeningData.fightState;
HappeningData.fightState = nextState;
TransitionFromToState(nextState, lastState);
TransitionToState(nextState);
}
private void TransitionFromState()
{
// fixed behaviour
switch (HappeningData.fightState)
{
default: break;
}
// notify everyone else
transitionFromState?.Invoke(HappeningData.fightState);
}
private void TransitionFromToState(FightState nextState, FightState lastState)
{
transitionState?.Invoke(lastState, nextState);
}
private void TransitionToState(FightState nextState)
{
// notify everyone else
transitionToState?.Invoke(nextState);
// fixed behaviour
switch (HappeningData.fightState)
{
case FightState.FightStartAnim:
AdvanceToStateInSeconds(FightState.FightersEnter, StartAnimationTime);
break;
case FightState.FightersEnter:
_fightersEnterStaging = StageFightersEnter();
if (_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
_actionStaging = null;
if ( /*TODO: are all allys dead*/ false)
{
ChangeState(FightState.EnemyWin);
}
else if (HappeningData.enemyGroup.AreAllDead())
{
ChangeState(FightState.PlayerWin);
}
else if (CurrentFighter.actionsLeft <= 0)
{
ChangeState(FightState.FightersEnter);
}
else if (CurrentFighter.isEnemy)
{
ChangeState(FightState.EnemyActionSelect);
}
else
{
ChangeState(FightState.InputActionSelect);
}
break;
case FightState.InputActionSelect:
// wait for player input
break;
case FightState.ActionCheckDetails:
if (ActionAbort())
ChangeState(FightState.InputActionSelect);
else if (ActionNeededDetail() != null)
ChangeState(FightState.InputActionDetail);
else
ChangeState(FightState.ActionExecute);
break;
case FightState.InputActionDetail:
// wait for player input
break;
case FightState.EnemyActionSelect:
_actionStaging = CurrentFighter.AutoSelectAction();
ChangeState(FightState.ActionExecute);
break;
case FightState.ActionExecute:
ExecuteAction();
ChangeState(FightState.ActionAnim);
break;
case FightState.ActionAnim:
var actionTime = GetActionAnimationEnd();
if (actionTime.IsType<float>())
{
AdvanceToStateInSeconds(FightState.StateCheck, actionTime);
}
else
{
_ = AdvanceToStateWhenDone(FightState.StateCheck, actionTime);
}
break;
default: break;
}
}
#endregion
#region Game Logic
private FightersEnterStaging StageFightersEnter()
{
// ally
var enteringAllyFighters = new List<FightWorld.Fighter>();
//TODO
// enemy
const int totalEnemySpace = 3;
var enemySpaceLeft = totalEnemySpace - HappeningData.enemyGroup.GetEnteredAmount();
var enterEnemyFighters = new List<FightWorld.Fighter>();
for (var i = 0; i < enemySpaceLeft; i++)
{
if (HappeningData.enemyGroup.TryGetFirstUnenteredFighter(out var fighter))
{
enterEnemyFighters.Add(fighter);
}
}
return new FightersEnterStaging
{
enteringAllyFighters = enteringAllyFighters,
enteringEnemyFighters = enterEnemyFighters
};
}
private void ExecuteFightersEnter()
{
Debug.Assert(_fightersEnterStaging != null);
foreach (var fighter in _fightersEnterStaging.enteringAllyFighters)
{
fighter.entered = true;
HappeningData.fighterStack.AddAsLast(fighter);
}
foreach (var fighter in _fightersEnterStaging.enteringEnemyFighters)
{
fighter.entered = true;
HappeningData.fighterStack.AddAsLast(fighter);
}
}
private void ExecuteNextFighter()
{
HappeningData.fighterStack.Next();
}
private void ExecuteAction()
{
Debug.Assert(_actionStaging != null);
_actionStaging.ExecuteAction();
}
private Variant<float, Func<bool>> GetActionAnimationEnd()
{
Debug.Assert(_actionStaging != null);
return _actionStaging.GetAnimationEnd();
}
private bool ActionAbort()
{
Debug.Assert(_actionStaging != null);
return _actionStaging.MarkedForAbort();
}
private FighterAction.FighterActionDetail? ActionNeededDetail()
{
Debug.Assert(_actionStaging != null);
return _actionStaging.NeededDetail();
}
#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 AdvanceToStateInSeconds(FightState nextState, float seconds)
{
FightWorld.Instance.GetTree().CreateTimer(seconds).Timeout += () => ChangeState(nextState);
}
private async Task AdvanceToStateWhenDone(FightState nextState, Func<bool> isDone)
{
while (!isDone())
{
await FightWorld.Instance.ToSignal(FightWorld.Instance.GetTree(), SceneTree.SignalName.ProcessFrame);
}
ChangeState(nextState);
}
#endregion
}

@ -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");
}
}

@ -2,7 +2,7 @@ using Godot;
namespace Babushka.scripts.CSharp.Common.Fight; namespace Babushka.scripts.CSharp.Common.Fight;
public partial class FightSceneSetup : Node public partial class FightRoomSceneSetup : Node
{ {
[Export] private Label debugLabel; [Export] private Label debugLabel;
public override void _Ready() public override void _Ready()

@ -9,15 +9,15 @@ public partial class FightSceneSwitcher : Node
{ {
[Export] private Node sceneRoot; [Export] private Node sceneRoot;
[Export] private string fightRoomScenePath; [Export] private string fightRoomScenePath;
[Export] private string fightingGroupScene; [Export] private string fightHappeningScene;
private void LoadNext() private void LoadNext()
{ {
var nextRoom = FightWorld.Instance.currentRoom; var nextRoom = FightWorld.Instance.currentRoom;
Debug.Assert(nextRoom != null, "nextRoom!=null"); Debug.Assert(nextRoom != null, "nextRoom!=null");
var nextEnemyGroup = FightWorld.Instance.inFightWith; var nextFightHappening = FightWorld.Instance.fightHappeningData;
SceneTransitionThreaded.Instance.ChangeSceneToFile(nextEnemyGroup != null SceneTransitionThreaded.Instance.ChangeSceneToFile(nextFightHappening != null
? fightingGroupScene ? fightHappeningScene
: fightRoomScenePath); : fightRoomScenePath);
UnloadAfterDelay(); UnloadAfterDelay();
} }

@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Linq;
namespace Babushka.scripts.CSharp.Common.Fight;
public static class FightUtils
{
public static int GetEnteredAmount(this FightWorld.EnemyGroup self)
{
return self.enemies.Count(e => e.IsAlive() && e.entered);
}
public static bool TryGetFirstUnenteredFighter(this FightWorld.EnemyGroup self, out FightWorld.Fighter fighter)
{
foreach (var f in self.enemies.Where(e=>!e.entered && e.IsAlive()))
{
fighter = f;
return true;
}
fighter = null!;
return false;
}
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 self.health ?? self.maxHealth;
}
public static bool AreAllDead(this FightWorld.EnemyGroup self)
{
return self.enemies.All(e => e.IsDead());
}
}

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using Babushka.scripts.CSharp.Common.Util;
using Godot; using Godot;
namespace Babushka.scripts.CSharp.Common.Fight; namespace Babushka.scripts.CSharp.Common.Fight;
@ -18,21 +19,39 @@ public partial class FightWorld : Node
public class EnemyGroup public class EnemyGroup
{ {
public required List<Enemy> enemies; public required List<Fighter> enemies;
} }
public class Enemy public class FightHappeningData
{
public FightHappening.FightState fightState = FightHappening.FightState.None;
public FighterStack fighterStack = new();
public required EnemyGroup enemyGroup;
}
public class Fighter
{ {
public enum Type public enum Type
{ {
Blob, Blob,
BigBlob, BigBlob,
Mavka, Mavka,
YourMom YourMom,
Vesna
} }
public required Type type; public required Type type;
public required int? health = null; // null => initialize to full health on spawn public required int maxHealth;
public required bool isEnemy;
public required List<FighterAction> availableActions;
public int? health = null; // null => initialize to full health on spawn
public bool entered = false;
public int actionsLeft;
public FighterAction AutoSelectAction()
{
return availableActions.Random() ?? new FighterAction.Skip();
}
} }
#region AutoLoad ( Contains _EnterTree() ) #region AutoLoad ( Contains _EnterTree() )
@ -46,10 +65,10 @@ public partial class FightWorld : Node
} }
#endregion #endregion
public World? world = null; public World? world = null;
public Room? currentRoom = null; public Room? currentRoom = null;
public EnemyGroup? inFightWith = null; public FightHappeningData? fightHappeningData = null;
public void MyEnterTree() public void MyEnterTree()
{ {
@ -135,22 +154,27 @@ public partial class FightWorld : Node
return enemyGroup; return enemyGroup;
} }
private Enemy GenerateSingleEnemy() private Fighter GenerateSingleEnemy()
{ {
var typeRoll = GD.RandRange(0, 99); var typeRoll = GD.RandRange(0, 99);
var type = typeRoll switch var type = typeRoll switch
{ {
< 50 => Enemy.Type.Blob, < 50 => Fighter.Type.Blob,
< 75 => Enemy.Type.BigBlob, < 75 => Fighter.Type.BigBlob,
< 90 => Enemy.Type.Mavka, < 90 => Fighter.Type.Mavka,
_ => Enemy.Type.YourMom _ => Fighter.Type.YourMom
}; };
var enemy = new Enemy var enemy = new Fighter
{ {
type = type, type = type,
health = null health = null,
isEnemy = true,
maxHealth = 12,
availableActions = [
new FighterAction.Skip()
]
}; };
return enemy; return enemy;

@ -0,0 +1,80 @@
using System;
using System.Threading.Tasks;
using Babushka.scripts.CSharp.Common.Util;
using Godot;
namespace Babushka.scripts.CSharp.Common.Fight;
public abstract class FighterAction
{
public class TargetSelection
{
// ReSharper disable once MemberHidesStaticFromOuterClass
public static readonly TargetSelection Skip = new() { skipTargetSelection = () => true };
public Func<bool> 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
/// <summary>
/// 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.
/// </summary>
public virtual void ExecuteAction()
{
}
/// <summary>
/// Returns a way to determine, when an action animation is done
/// </summary>
/// <returns>
/// A variant that can be <c>float</c> or <c>Func&lt;bool&gt;</c>.<br/>
/// When the return type is <c>float</c>, the animation will take the return value amount of seconds.<br/>
/// When the return type is <c>Func&lt;bool&gt;</c>, the animation will be done, when the function returns true.
/// </returns>
public abstract Variant<float, Func<bool>> GetAnimationEnd();
/// <summary>
/// Animates the action.
/// </summary>
public virtual async Task AnimateAction()
{
}
public void MarkAbort()
{
_abort = true;
}
public bool MarkedForAbort()
{
return _abort;
}
public abstract FighterActionDetail? NeededDetail();
public class Skip : FighterAction
{
public override Variant<float, Func<bool>> GetAnimationEnd()
{
return 0f;
}
public override FighterActionDetail? NeededDetail()
{
return null;
}
}
}

@ -0,0 +1,95 @@
using System.Collections.Generic;
using Godot.NativeInterop;
namespace Babushka.scripts.CSharp.Common.Fight;
public class FighterStack
{
private class Node
{
public Node next;
public FightWorld.Fighter fighter;
}
private Node? currentNode;
public FightWorld.Fighter Current => currentNode.fighter;
public void Next()
{
currentNode = currentNode.next;
}
public FightWorld.Fighter PeekNext()
{
return currentNode.next.fighter;
}
public void AddAsLast(FightWorld.Fighter value)
{
// if first node
if (currentNode == null)
{
currentNode = new Node { fighter = value };
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 on the next Next() call
node.next = node.next.next;
return true;
}
node = node.next;
} while (node != currentNode);
return false;
}
}

@ -1,12 +1,13 @@
using Godot; using Godot;
namespace Babushka.scripts.CSharp.Common.Fight; namespace Babushka.scripts.CSharp.Common.Fight;
public partial class Fighter : Node2D public partial class FighterVisual : Node2D
{ {
[Export] public string name; //[Export] public string name;
[Export] public int maxHealth; //[Export] public int maxHealth;
[Export] public int attackStrength; //[Export] public int attackStrength;
[Export] public int maxActions = 1; //[Export] public int maxActions = 1;
[Export] public FightWorld.Fighter.Type type;
[ExportCategory("References")] [ExportCategory("References")]
[Export] private Node2D _attackButtons; [Export] private Node2D _attackButtons;
@ -21,45 +22,29 @@ public partial class Fighter : Node2D
[Signal] public delegate void HealedEventHandler(); [Signal] public delegate void HealedEventHandler();
private int _health; private FightWorld.Fighter _boundFighter;
private int _actions;
//private void Die()
//{
// _visualSprite.Scale = new Vector2(1, 0.3f);
// EmitSignalDying();
//}
public FightInstance fightInstance; //public override void _Ready()
public int Health //{
{ // UpdateHealthVisual();
get => _health; // ResetActions();
set //}
{
_health = value;
if (_health <= 0)
{
_health = 0;
Die();
}
if (_health > maxHealth)
{
_health = maxHealth;
}
}
}
private void Die() public void Initialize(FightWorld.Fighter fighter)
{ {
_visualSprite.Scale = new Vector2(1, 0.3f); _boundFighter = fighter;
EmitSignalDying();
}
public override void _Ready()
{
Health = maxHealth;
UpdateHealthVisual(); UpdateHealthVisual();
ResetActions();
} }
public void Attack() public void Attack()
{ {
fightInstance.SelectAttack(this); //FightHappening.SelectAttack(this);
} }
public void HideAttackButton() public void HideAttackButton()
@ -102,17 +87,17 @@ public partial class Fighter : Node2D
private void ClickedAttack() private void ClickedAttack()
{ {
fightInstance.SelectAttack(this); //FightHappening.SelectAttack(this);
} }
private void ClickedHeal() private void ClickedHeal()
{ {
fightInstance.SelectHeal(this); //FightHappening.SelectHeal(this);
} }
private void ClickedTarget() private void ClickedTarget()
{ {
fightInstance.SelectTargetAndAttack(this); //FightHappening.SelectTargetAndAttack(this);
} }
public void StartHoverTarget() public void StartHoverTarget()
@ -127,7 +112,18 @@ public partial class Fighter : Node2D
public void UpdateHealthVisual() public void UpdateHealthVisual()
{ {
_healthText.Text = $"{Health}/{maxHealth}"; _healthText.Text = $"{_boundFighter.health}";
}
public bool IsDead()
{
//return Health <= 0;
return true;
}
public void ResetActions()
{
//_actions = maxActions;
} }
public void AttackAnimation(FightAttack attack) public void AttackAnimation(FightAttack attack)
@ -150,26 +146,6 @@ public partial class Fighter : Node2D
.SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out); .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() public void HealAnimation()
{ {
EmitSignalHealed(); EmitSignalHealed();

@ -0,0 +1,7 @@
using System;
namespace Babushka.scripts.CSharp.Common.Fight;
public class NoFightHappeningException() : Exception("No fight happening right now")
{
}

@ -4,6 +4,6 @@ public class FightAttack
{ {
public int damage; public int damage;
public bool needsSelectedTarget; public bool needsSelectedTarget;
public Fighter? target; public FighterVisual? target;
public Fighter attacker; public FighterVisual attacker;
} }

@ -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<Fighter> _friendlyFighters = new();
private List<Fighter> _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());
}
/**
* <returns>
* <c>true</c> if the state was changed
* </returns>
*/
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;
}
/**
* <returns>
* <c>true</c> if the state was changed
* </returns>
*/
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>();
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;
}
}

@ -19,10 +19,10 @@ public partial class FightManager : Node
public FightParty fightParty = new(); public FightParty fightParty = new();
public void StartFight(PackedScene[] enemies, FightInstance instance) public void StartFight(PackedScene[] enemies, FightHappening happening)
{ {
GD.Print("Starting Fight"); GD.Print("Starting Fight");
instance.Start(fightParty, enemies); //happening.Start(fightParty, enemies);
} }
} }

@ -4,7 +4,7 @@ namespace Babushka.scripts.CSharp.Common.Fight;
public partial class FightStarter : Node public partial class FightStarter : Node
{ {
[Export(PropertyHint.ArrayType)] private PackedScene[] enemies; [Export(PropertyHint.ArrayType)] private PackedScene[] enemies;
[Export] private FightInstance _fightInstance; //[Export] private FightHappening _fightHappening;
[Export] private bool _once = true; [Export] private bool _once = true;
private bool hasBeenStarted = false; private bool hasBeenStarted = false;
@ -14,6 +14,6 @@ public partial class FightStarter : Node
return; return;
hasBeenStarted = true; hasBeenStarted = true;
FightManager.Instance.StartFight(enemies, _fightInstance); //FightManager.Instance.StartFight(enemies, _fightHappening);
} }
} }

@ -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;
}
}

@ -0,0 +1,63 @@
using System;
using System.Diagnostics;
namespace Babushka.scripts.CSharp.Common.Util;
public class Variant<T1, T2>
{
private Type _type;
private Object _value;
public Type GetVariantType()
{
return _type;
}
public T GetValue<T>()
{
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>(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<T1, T2> v)
{
return v.GetValue<T1>();
}
public static implicit operator T2(Variant<T1, T2> v)
{
return v.GetValue<T2>();
}
public static implicit operator Variant<T1, T2>(T1 t)
{
return new Variant<T1, T2> { _type = typeof(T1), _value = t! };
}
public static implicit operator Variant<T1, T2>(T2 t)
{
return new Variant<T1, T2> { _type = typeof(T2), _value = t! };
}
public bool IsType<T>()
{
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);
}
}

@ -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 // 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; uniform float offset = 0;
float getWind(vec2 vertex, vec2 uv, float time){ float getWind(vec2 vertex, vec2 uv, float time){
float diff = pow(maxStrength - minStrength, 2.0); float diff = pow(maxStrength - minStrength, 2.0);
float strength = clamp(minStrength + diff + sin(time / interval) * diff, minStrength, maxStrength) * strengthScale; float strength = clamp(minStrength + diff + sin(time / interval) * diff, minStrength, maxStrength) * strengthScale;

Loading…
Cancel
Save