Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 427db88474 | |||
| 45d4b26b6a | |||
| 719b1fa800 | |||
| bd6432f568 | |||
| 224863f891 | |||
| 7d35c991f3 | |||
| ff8e4a85d2 | |||
| 96df233496 | |||
| 3f23f4471b | |||
| f2bf44bf9e |
Generated
+1
@@ -0,0 +1 @@
|
||||
Babushka
|
||||
@@ -4,11 +4,12 @@ importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://b3kyrsoobmkhp"
|
||||
valid=false
|
||||
path="res://.godot/imported/best_house_blender.blend-ac89c74aef2f275bdf4b4baadee17c0c.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://art/mockups/3d/best_house_blender.blend"
|
||||
dest_files=["res://.godot/imported/best_house_blender.blend-ac89c74aef2f275bdf4b4baadee17c0c.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://iux86v7qmf33"
|
||||
path="res://.godot/imported/FightTest_Base.ogg-c2135a351140994f825ac3a4c95512e9.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/FightTest_Base.ogg"
|
||||
dest_files=["res://.godot/imported/FightTest_Base.ogg-c2135a351140994f825ac3a4c95512e9.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://cimd2rvdwtfkv"
|
||||
path="res://.godot/imported/FightTest_Pattern1.ogg-366a24f1c5b2de03be94df3cb6e2b4db.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/FightTest_Pattern1.ogg"
|
||||
dest_files=["res://.godot/imported/FightTest_Pattern1.ogg-366a24f1c5b2de03be94df3cb6e2b4db.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://kpbkw64o86q4"
|
||||
path="res://.godot/imported/FightTest_Pattern2.ogg-deeb2006ba9921b2d3fd3c5e9154d31c.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/FightTest_Pattern2.ogg"
|
||||
dest_files=["res://.godot/imported/FightTest_Pattern2.ogg-deeb2006ba9921b2d3fd3c5e9154d31c.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://cmyrgerm8m4nw"
|
||||
path="res://.godot/imported/FightTest_Pattern3.ogg-bc6fa475a04ff9ce3eb12d0e5a8b2946.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/FightTest_Pattern3.ogg"
|
||||
dest_files=["res://.godot/imported/FightTest_Pattern3.ogg-bc6fa475a04ff9ce3eb12d0e5a8b2946.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://ddu3pxk121x87"
|
||||
path="res://.godot/imported/NightTest_Pattern1.ogg-3eb5d685e76ee80df0e3a06c333e5881.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/NightTest_Pattern1.ogg"
|
||||
dest_files=["res://.godot/imported/NightTest_Pattern1.ogg-3eb5d685e76ee80df0e3a06c333e5881.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://ddxekmi71ekin"
|
||||
path="res://.godot/imported/NightTest_Pattern2.ogg-3f45cf34ddc5716cb6e571b63e7168e6.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/NightTest_Pattern2.ogg"
|
||||
dest_files=["res://.godot/imported/NightTest_Pattern2.ogg-3f45cf34ddc5716cb6e571b63e7168e6.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://cjnt07ai5bed8"
|
||||
path="res://.godot/imported/NightTest_Pattern3.ogg-54521b103c362f6dfd049e0947d34740.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://audio/Music/TestingMusic/NightTest_Pattern3.ogg"
|
||||
dest_files=["res://.godot/imported/NightTest_Pattern3.ogg-54521b103c362f6dfd049e0947d34740.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=130.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
[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")]
|
||||
[node name="FightSceneSwitcher" type="Node"]
|
||||
script = ExtResource("1_5dt1r")
|
||||
sceneRoot = NodePath("")
|
||||
fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn"
|
||||
fightHappeningScene = "res://scenes/Babushka_scene_fight_happening.tscn"
|
||||
_fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn"
|
||||
_fightHappeningScene = "res://scenes/Babushka_scene_fight_happening.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"]
|
||||
@@ -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
|
||||
@@ -1075,9 +1075,8 @@ collision_mask = 4
|
||||
position = Vector2(145.5, -224)
|
||||
shape = SubResource("RectangleShape2D_0sfl7")
|
||||
|
||||
[node name="InteractionArea" parent="YSorted/Brünnen" node_paths=PackedStringArray("_spriteToOutline") instance=ExtResource("27_klb81")]
|
||||
[node name="InteractionArea" parent="YSorted/Brünnen" instance=ExtResource("27_klb81")]
|
||||
_active = false
|
||||
_spriteToOutline = NodePath("..")
|
||||
_id = 1
|
||||
|
||||
[node name="CollisionShape3D" parent="YSorted/Brünnen/InteractionArea/Area2D" index="0"]
|
||||
@@ -1091,6 +1090,9 @@ position = Vector2(6095, 2087)
|
||||
[node name="SpawnWithItem" parent="YSorted/HoeGenericPickup" index="0"]
|
||||
_blueprint = ExtResource("26_ipqaa")
|
||||
|
||||
[node name="PickupInteractionArea" parent="YSorted/HoeGenericPickup" index="3" node_paths=PackedStringArray("_spriteToOutline")]
|
||||
_spriteToOutline = []
|
||||
|
||||
[node name="CollisionShape3D" parent="YSorted/HoeGenericPickup/PickupInteractionArea/Area2D" index="0"]
|
||||
shape = SubResource("CircleShape2D_ycj14")
|
||||
|
||||
@@ -1100,6 +1102,9 @@ position = Vector2(8192, 3507)
|
||||
[node name="SpawnWithItem" parent="YSorted/CanGenericPickup" index="0"]
|
||||
_blueprint = ExtResource("28_ipqaa")
|
||||
|
||||
[node name="PickupInteractionArea" parent="YSorted/CanGenericPickup" index="3" node_paths=PackedStringArray("_spriteToOutline")]
|
||||
_spriteToOutline = []
|
||||
|
||||
[node name="CollisionShape3D" parent="YSorted/CanGenericPickup/PickupInteractionArea/Area2D" index="0"]
|
||||
shape = SubResource("CircleShape2D_2065p")
|
||||
|
||||
@@ -1112,6 +1117,9 @@ position = Vector2(8391, 2060)
|
||||
[node name="SpawnWithItem" parent="YSorted/RakeGenericPickup" index="0"]
|
||||
_blueprint = ExtResource("28_6b2nr")
|
||||
|
||||
[node name="PickupInteractionArea" parent="YSorted/RakeGenericPickup" index="3" node_paths=PackedStringArray("_spriteToOutline")]
|
||||
_spriteToOutline = []
|
||||
|
||||
[node name="CollisionShape3D" parent="YSorted/RakeGenericPickup/PickupInteractionArea/Area2D" index="0"]
|
||||
shape = SubResource("CircleShape2D_tm0yg")
|
||||
|
||||
@@ -1122,6 +1130,9 @@ position = Vector2(15642, 2158)
|
||||
[node name="SpawnWithItem" parent="YSorted/ScytheGenericPickup" index="0"]
|
||||
_blueprint = ExtResource("29_wtdui")
|
||||
|
||||
[node name="PickupInteractionArea" parent="YSorted/ScytheGenericPickup" index="3" node_paths=PackedStringArray("_spriteToOutline")]
|
||||
_spriteToOutline = []
|
||||
|
||||
[node name="CollisionShape3D" parent="YSorted/ScytheGenericPickup/PickupInteractionArea/Area2D" index="0"]
|
||||
shape = SubResource("CircleShape2D_lbnqo")
|
||||
|
||||
@@ -1132,6 +1143,9 @@ position = Vector2(5454, 2049)
|
||||
[node name="SpawnWithItem" parent="YSorted/ShovelGenericPickup" index="0"]
|
||||
_blueprint = ExtResource("27_ipqaa")
|
||||
|
||||
[node name="PickupInteractionArea" parent="YSorted/ShovelGenericPickup" index="3" node_paths=PackedStringArray("_spriteToOutline")]
|
||||
_spriteToOutline = []
|
||||
|
||||
[node name="CollisionShape3D" parent="YSorted/ShovelGenericPickup/PickupInteractionArea/Area2D" index="0"]
|
||||
shape = SubResource("CircleShape2D_l4wxt")
|
||||
|
||||
@@ -1156,10 +1170,9 @@ collision_mask = 6
|
||||
position = Vector2(-252.56, 231.32)
|
||||
polygon = PackedVector2Array(247.227, 43.5123, 44.7822, 43.5123, -87.2178, 45.123, -104.329, -55.2797, -154.107, -73.5347, -160.107, -380.38, -175.44, -400.783, -63.44, -512.461, 97.8934, -541.991, 261.671, -599.172, 374.782, -526.421, 502.338, -526.421, 637.893, -396.488, 598.56, -360.783, 596.338, -58.2327, 528.782, -58.2327, 501.449, 45.9283)
|
||||
|
||||
[node name="EnterHouseInteraction" parent="YSorted/Farm visuals/Static" node_paths=PackedStringArray("_spriteToOutline") instance=ExtResource("27_klb81")]
|
||||
[node name="EnterHouseInteraction" parent="YSorted/Farm visuals/Static" instance=ExtResource("27_klb81")]
|
||||
position = Vector2(5839, 2349)
|
||||
scale = Vector2(2.425, 2.425)
|
||||
_spriteToOutline = NodePath("DoorSprite")
|
||||
_id = 0
|
||||
|
||||
[node name="DoorSprite" type="Sprite2D" parent="YSorted/Farm visuals/Static/EnterHouseInteraction"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=11 format=3 uid="uid://cjshlwk8ajpnp"]
|
||||
[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"]
|
||||
@@ -8,8 +8,11 @@
|
||||
[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"]
|
||||
|
||||
@@ -36,7 +39,7 @@ _allyFighters = NodePath("AllyFighters")
|
||||
_enemyFighters = NodePath("EnemyFighters")
|
||||
_blobFighterVisual = ExtResource("4_vp8s0")
|
||||
_vesnaFighterVisual = ExtResource("4_qo0gi")
|
||||
_positionDistanceFromCenter = PackedFloat32Array(200, 400, 600)
|
||||
_positionDistanceFromCenter = PackedFloat32Array(300, 550, 800)
|
||||
|
||||
[node name="AllyFighters" type="Node2D" parent="FightVisuals"]
|
||||
|
||||
@@ -44,7 +47,20 @@ _positionDistanceFromCenter = PackedFloat32Array(200, 400, 600)
|
||||
|
||||
[node name="EnvironmentVisuals" type="Node2D" parent="."]
|
||||
|
||||
[node name="FightSceneSwitcher" parent="." instance=ExtResource("2_phrlx")]
|
||||
[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
|
||||
@@ -187,10 +203,12 @@ 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="SignalTransitionState" from="FightHappening" to="ActionAnimationController/StateReactionActionAnimation" method="FightHappeningStateTransitioned"]
|
||||
[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]]
|
||||
|
||||
@@ -2148,8 +2148,9 @@ position = Vector2(1560, 422)
|
||||
[node name="Spawn4" type="Node2D" parent="YSorted/EnemyGroupSpawns"]
|
||||
position = Vector2(-1127, 671)
|
||||
|
||||
[node name="FightSceneSwitcher" parent="." instance=ExtResource("40_elhbh")]
|
||||
[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")
|
||||
|
||||
@@ -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="."]
|
||||
@@ -0,0 +1,16 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
public partial class Button : Godot.Button
|
||||
{
|
||||
//[Export] private AudioStreamPlaybackInteractive _audioStreamInteractive;
|
||||
[Export] private AudioStreamPlayer2D _palyer;
|
||||
|
||||
private int bla = 0;
|
||||
public void Pressed()
|
||||
{
|
||||
bla = bla == 0 ? 1 : 0;
|
||||
var s = ((AudioStreamPlaybackSynchronized)_palyer.GetStreamPlayback());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bfyhyjutba2o
|
||||
@@ -0,0 +1,8 @@
|
||||
extends Button
|
||||
|
||||
@export var i:
|
||||
|
||||
|
||||
|
||||
func _on_pressed() -> void:
|
||||
pass # Replace with function body.
|
||||
@@ -0,0 +1 @@
|
||||
uid://b126dduoht87j
|
||||
@@ -0,0 +1,82 @@
|
||||
[gd_scene load_steps=14 format=3 uid="uid://b4cch0o4218rb"]
|
||||
|
||||
[ext_resource type="AudioStream" uid="uid://iux86v7qmf33" path="res://audio/Music/TestingMusic/FightTest_Base.ogg" id="1_kcx1j"]
|
||||
[ext_resource type="AudioStream" uid="uid://cimd2rvdwtfkv" path="res://audio/Music/TestingMusic/FightTest_Pattern1.ogg" id="2_71etn"]
|
||||
[ext_resource type="AudioStream" uid="uid://kpbkw64o86q4" path="res://audio/Music/TestingMusic/FightTest_Pattern2.ogg" id="3_3u8ta"]
|
||||
[ext_resource type="AudioStream" uid="uid://cmyrgerm8m4nw" path="res://audio/Music/TestingMusic/FightTest_Pattern3.ogg" id="4_1dcxw"]
|
||||
[ext_resource type="AudioStream" uid="uid://ddu3pxk121x87" path="res://audio/Music/TestingMusic/NightTest_Pattern1.ogg" id="5_80mhq"]
|
||||
[ext_resource type="AudioStream" uid="uid://ddxekmi71ekin" path="res://audio/Music/TestingMusic/NightTest_Pattern2.ogg" id="6_ui405"]
|
||||
[ext_resource type="AudioStream" uid="uid://cjnt07ai5bed8" path="res://audio/Music/TestingMusic/NightTest_Pattern3.ogg" id="7_dpoqt"]
|
||||
[ext_resource type="AudioStream" uid="uid://bk5yqto8j3egp" path="res://audio/sfx/SFX_Quest_Fail_Placeholder_01.wav" id="8_71etn"]
|
||||
[ext_resource type="Script" uid="uid://bfyhyjutba2o" path="res://scenes/testing/Button.cs" id="9_3u8ta"]
|
||||
|
||||
[sub_resource type="AudioStreamSynchronized" id="AudioStreamSynchronized_ks5rm"]
|
||||
resource_name = "test"
|
||||
stream_count = 3
|
||||
stream_0/stream = ExtResource("2_71etn")
|
||||
stream_0/volume = 0.0
|
||||
stream_1/stream = ExtResource("3_3u8ta")
|
||||
stream_1/volume = 0.0
|
||||
stream_2/stream = ExtResource("4_1dcxw")
|
||||
stream_2/volume = 0.0
|
||||
|
||||
[sub_resource type="AudioStreamSynchronized" id="AudioStreamSynchronized_kt7r4"]
|
||||
stream_count = 3
|
||||
stream_0/stream = ExtResource("5_80mhq")
|
||||
stream_0/volume = 0.0
|
||||
stream_1/stream = ExtResource("6_ui405")
|
||||
stream_1/volume = 0.0
|
||||
stream_2/stream = ExtResource("7_dpoqt")
|
||||
stream_2/volume = 0.0
|
||||
|
||||
[sub_resource type="AudioStreamInteractive" id="AudioStreamInteractive_nwvf5"]
|
||||
clip_count = 3
|
||||
clip_0/name = &"fight"
|
||||
clip_0/stream = SubResource("AudioStreamSynchronized_ks5rm")
|
||||
clip_0/auto_advance = 1
|
||||
clip_0/next_clip = 1
|
||||
clip_1/name = &"night"
|
||||
clip_1/stream = SubResource("AudioStreamSynchronized_kt7r4")
|
||||
clip_1/auto_advance = 1
|
||||
clip_1/next_clip = 0
|
||||
clip_2/name = &"fanfare"
|
||||
clip_2/stream = ExtResource("8_71etn")
|
||||
clip_2/auto_advance = 0
|
||||
_transitions = {
|
||||
Vector2i(0, 1): {
|
||||
"fade_beats": 1.0,
|
||||
"fade_mode": 4,
|
||||
"filler_clip": 2,
|
||||
"from_time": 0,
|
||||
"to_time": 0,
|
||||
"use_filler_clip": true
|
||||
}
|
||||
}
|
||||
|
||||
[sub_resource type="AudioStreamSynchronized" id="AudioStreamSynchronized_sv75a"]
|
||||
stream_count = 2
|
||||
stream_0/stream = ExtResource("1_kcx1j")
|
||||
stream_0/volume = 0.0
|
||||
stream_1/stream = SubResource("AudioStreamInteractive_nwvf5")
|
||||
stream_1/volume = 0.0
|
||||
|
||||
[node name="Node2D" type="Node2D"]
|
||||
|
||||
[node name="Music" type="AudioStreamPlayer2D" parent="."]
|
||||
stream = SubResource("AudioStreamSynchronized_sv75a")
|
||||
autoplay = true
|
||||
|
||||
[node name="Button" type="Button" parent="." node_paths=PackedStringArray("_palyer")]
|
||||
offset_left = 56.0
|
||||
offset_top = 31.0
|
||||
offset_right = 349.0
|
||||
offset_bottom = 175.0
|
||||
script = ExtResource("9_3u8ta")
|
||||
_palyer = NodePath("../Music")
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="."]
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="."]
|
||||
fov = 104.538
|
||||
|
||||
[connection signal="pressed" from="Button" to="Button" method="Pressed"]
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Babushka.scripts.CSharp.Common.Fight.ActionDetails;
|
||||
|
||||
public class MinigameActionDetail : FighterAction.FighterActionDetail
|
||||
{
|
||||
// settings
|
||||
|
||||
|
||||
// result
|
||||
public List<int>? damageHits = null;
|
||||
|
||||
public MinigameActionDetail()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool DetailComplete()
|
||||
{
|
||||
return damageHits != null;
|
||||
}
|
||||
|
||||
public void ResetResult()
|
||||
{
|
||||
damageHits = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://du8cm2q5kwikl
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Babushka.scripts.CSharp.Common.Fight.ActionDetails;
|
||||
using Babushka.scripts.CSharp.Common.Util;
|
||||
@@ -15,6 +16,8 @@ public class AllyAttackAction : FighterAction
|
||||
selectAlly = false
|
||||
};
|
||||
|
||||
public MinigameActionDetail minigameDetail = new();
|
||||
|
||||
public override Variant<float, Func<bool>> GetAnimationEnd()
|
||||
{
|
||||
return 1;
|
||||
@@ -22,12 +25,12 @@ public class AllyAttackAction : FighterAction
|
||||
|
||||
public override bool NextDetail()
|
||||
{
|
||||
return !targetSelect.DetailComplete();
|
||||
return !targetSelect.DetailComplete() || !minigameDetail.DetailComplete();
|
||||
}
|
||||
|
||||
public override FighterActionDetail CurrentDetail()
|
||||
{
|
||||
return targetSelect;
|
||||
return targetSelect.DetailComplete() ? minigameDetail : targetSelect;
|
||||
}
|
||||
|
||||
public override AllyActionButton BindToActionButton()
|
||||
@@ -38,21 +41,23 @@ public class AllyAttackAction : FighterAction
|
||||
public override void Reset()
|
||||
{
|
||||
targetSelect.ResetResult();
|
||||
minigameDetail.ResetResult();
|
||||
}
|
||||
|
||||
public override void ExecuteAction()
|
||||
{
|
||||
targetSelect.GetTarget().AddHealth(-5);
|
||||
var totalDamage = minigameDetail.damageHits!.Sum(dh => dh);
|
||||
targetSelect.GetTarget().AddHealth(-totalDamage);
|
||||
}
|
||||
|
||||
public override async Task AnimateAction(AllFightersVisual allFightersVisual)
|
||||
{
|
||||
var currentFighter = HappeningData.fighterStack.Current;
|
||||
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();
|
||||
|
||||
@@ -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<float, Func<bool>> 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dlik4vktiu7dg
|
||||
@@ -1,10 +1,11 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Babushka.scripts.CSharp.Common.Fight;
|
||||
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
|
||||
{
|
||||
@@ -57,7 +58,7 @@ public partial class AllFightersVisual : Node
|
||||
|
||||
if (from == FightHappening.FightState.ActionAnim)
|
||||
{
|
||||
_fighterVisuals.Values.ForEach(fv=>fv.UpdateHealthBar());
|
||||
_fighterVisuals.Values.ForEach(fv => fv.UpdateHealthBar());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,10 +113,14 @@ public partial class AllFightersVisual : Node
|
||||
private void ShowTargetSelect(TargetSelectActionDetail targetDetail)
|
||||
{
|
||||
if (targetDetail.selectEnemy)
|
||||
_fighterVisuals.Where(kv => kv.Key.isEnemy).ForEach(kv => kv.Value.SetTargetSelectionActive(true));
|
||||
_fighterVisuals
|
||||
.Where(kv => kv.Key.IsInFormation(HappeningData.enemyFighterFormation))
|
||||
.ForEach(kv => kv.Value.SetTargetSelectionActive(true));
|
||||
|
||||
if (targetDetail.selectAlly)
|
||||
_fighterVisuals.Where(kv => !kv.Key.isEnemy).ForEach(kv => kv.Value.SetTargetSelectionActive(true));
|
||||
_fighterVisuals
|
||||
.Where(kv => kv.Key.IsInFormation(HappeningData.allyFighterFormation))
|
||||
.ForEach(kv => kv.Value.SetTargetSelectionActive(true));
|
||||
}
|
||||
|
||||
private void HideTargetSelect()
|
||||
|
||||
@@ -8,7 +8,6 @@ public class AllyFighters
|
||||
{
|
||||
type = FightWorld.Fighter.Type.Vesna,
|
||||
maxHealth = 20,
|
||||
isEnemy = false,
|
||||
availableActions =
|
||||
[
|
||||
new AllyAttackAction()
|
||||
@@ -18,7 +17,6 @@ public class AllyFighters
|
||||
{
|
||||
type = FightWorld.Fighter.Type.Chuha,
|
||||
maxHealth = 15,
|
||||
isEnemy = false,
|
||||
availableActions =
|
||||
[
|
||||
new FighterAction.Skip()
|
||||
|
||||
@@ -61,7 +61,7 @@ public partial class FightHappening : Node
|
||||
private static FightWorld.FightHappeningData HappeningData =>
|
||||
FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException();
|
||||
|
||||
private static FightWorld.Fighter CurrentFighter => HappeningData.fighterStack.Current;
|
||||
private static FightWorld.Fighter CurrentFighter => HappeningData.fighterTurn.Current;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -88,7 +88,7 @@ public partial class FightHappening : Node
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
SetupInstance();
|
||||
@@ -110,7 +110,7 @@ public partial class FightHappening : Node
|
||||
action.Reset();
|
||||
ChangeState(FightState.ActionCheckDetails);
|
||||
}
|
||||
|
||||
|
||||
public void DetailFilled()
|
||||
{
|
||||
RequireState(FightState.InputActionDetail);
|
||||
@@ -204,7 +204,7 @@ public partial class FightHappening : Node
|
||||
{
|
||||
ChangeState(FightState.FightersEnter);
|
||||
}
|
||||
else if (CurrentFighter.isEnemy)
|
||||
else if (CurrentFighter.IsInFormation(HappeningData.enemyFighterFormation))
|
||||
{
|
||||
ChangeState(FightState.EnemyActionSelect);
|
||||
}
|
||||
@@ -219,7 +219,7 @@ public partial class FightHappening : Node
|
||||
break;
|
||||
case FightState.ActionCheckDetails:
|
||||
RequireNotNull(HappeningData.actionStaging);
|
||||
|
||||
|
||||
if (ActionAbort())
|
||||
ChangeState(FightState.InputActionSelect);
|
||||
else if (ActionNeededDetail())
|
||||
@@ -249,10 +249,15 @@ public partial class FightHappening : Node
|
||||
_ = AdvanceToStateWhenDone(FightState.StateCheck, actionTime);
|
||||
}
|
||||
|
||||
break;
|
||||
case FightState.EnemyWin:
|
||||
// TODO: remove and find proper solution
|
||||
ReviveVesna();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Game Logic
|
||||
@@ -262,19 +267,23 @@ public partial class FightHappening : Node
|
||||
// ally
|
||||
var enteringAllyFighters = new List<FightWorld.Fighter>();
|
||||
var allyFighters = FightWorld.Instance.allyFighters;
|
||||
if (!allyFighters.vesnaFighter.entered)
|
||||
if (!allyFighters.vesnaFighter.IsInFormation(HappeningData.allyFighterFormation))
|
||||
{
|
||||
enteringAllyFighters.Add(allyFighters.vesnaFighter);
|
||||
}
|
||||
|
||||
// enemy
|
||||
const int totalEnemySpace = 3;
|
||||
var enemySpaceLeft = totalEnemySpace - HappeningData.enemyGroup.GetEnteredAmount();
|
||||
var enemySpaceLeft = HappeningData.enemyFighterFormation.GetEmptySlotCount();
|
||||
|
||||
return new FightersEnterStaging
|
||||
{
|
||||
enteringAllyFighters = enteringAllyFighters,
|
||||
enteringEnemyFighters = HappeningData.enemyGroup.GetUptoUnenteredFighters(enemySpaceLeft).ToList()
|
||||
enteringEnemyFighters = HappeningData.enemyGroup.fighters
|
||||
.WhereIsAlive()
|
||||
.WhereIsNotInFormation(HappeningData.enemyFighterFormation)
|
||||
.Take(enemySpaceLeft)
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -283,21 +292,25 @@ public partial class FightHappening : Node
|
||||
Debug.Assert(HappeningData.fightersEnterStaging != null);
|
||||
foreach (var fighter in HappeningData.fightersEnterStaging.enteringAllyFighters)
|
||||
{
|
||||
fighter.entered = true;
|
||||
HappeningData.fighterStack.AddAsLast(fighter);
|
||||
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)
|
||||
{
|
||||
fighter.entered = true;
|
||||
HappeningData.fighterStack.AddAsLast(fighter);
|
||||
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.fighterStack.Next();
|
||||
CurrentFighter.actionPointsLeft = CurrentFighter.maxActionPoints;
|
||||
HappeningData.fighterTurn.Next();
|
||||
CurrentFighter.actionPointsLeft = FightWorld.Fighter.MaxActionPoints;
|
||||
}
|
||||
|
||||
private void ExecuteAction()
|
||||
@@ -325,6 +338,14 @@ public partial class FightHappening : Node
|
||||
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
|
||||
@@ -337,7 +358,7 @@ public partial class FightHappening : Node
|
||||
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)
|
||||
@@ -362,6 +383,4 @@ public partial class FightHappening : Node
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
@@ -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<int>()
|
||||
.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");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bwm0nhvt1083k
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Babushka.scripts.CSharp.Common.SceneManagement;
|
||||
using Godot;
|
||||
|
||||
@@ -7,9 +8,9 @@ namespace Babushka.scripts.CSharp.Common.Fight;
|
||||
|
||||
public partial class FightSceneSwitcher : Node
|
||||
{
|
||||
[Export] private Node sceneRoot;
|
||||
[Export] private string fightRoomScenePath;
|
||||
[Export] private string fightHappeningScene;
|
||||
[Export] private Node _sceneRoot = null!;
|
||||
[Export] private string _fightRoomScenePath = null!;
|
||||
[Export] private string _fightHappeningScene = null!;
|
||||
|
||||
private void LoadNext()
|
||||
{
|
||||
@@ -17,12 +18,12 @@ public partial class FightSceneSwitcher : Node
|
||||
Debug.Assert(nextRoom != null, "nextRoom!=null");
|
||||
var nextFightHappening = FightWorld.Instance.fightHappeningData;
|
||||
SceneTransitionThreaded.Instance.ChangeSceneToFile(nextFightHappening != null
|
||||
? fightHappeningScene
|
||||
: fightRoomScenePath);
|
||||
UnloadAfterDelay();
|
||||
? _fightHappeningScene
|
||||
: _fightRoomScenePath);
|
||||
_ = UnloadAfterDelay();
|
||||
}
|
||||
|
||||
private async void UnloadAfterDelay()
|
||||
private async Task UnloadAfterDelay()
|
||||
{
|
||||
await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); // 1.0f seconds
|
||||
//sceneRoot.QueueFree();
|
||||
@@ -31,7 +32,7 @@ public partial class FightSceneSwitcher : Node
|
||||
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");
|
||||
|
||||
@@ -50,4 +51,13 @@ public partial class FightSceneSwitcher : Node
|
||||
};
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Babushka.scripts.CSharp.Common.Fight;
|
||||
|
||||
public static class FightUtils
|
||||
{
|
||||
public static int GetEnteredAmount(this FightWorld.FighterGroup self)
|
||||
public static IEnumerable<FightWorld.Fighter> WhereIsAlive(this IEnumerable<FightWorld.Fighter> self)
|
||||
{
|
||||
return self.enemies.Count(e => e.IsAlive() && e.entered);
|
||||
return self.Where(e => e.IsAlive());
|
||||
}
|
||||
|
||||
public static IEnumerable<FightWorld.Fighter> GetUptoUnenteredFighters(
|
||||
this FightWorld.FighterGroup self,
|
||||
int maxFighters)
|
||||
|
||||
public static IEnumerable<FightWorld.Fighter> WhereIsNotInFormation(this IEnumerable<FightWorld.Fighter> self, FighterFormation formation)
|
||||
{
|
||||
if (maxFighters <= self.enemies.Count)
|
||||
return self.enemies
|
||||
.Where(e => !e.entered && e.IsAlive());
|
||||
|
||||
return self.enemies
|
||||
.Where(e => !e.entered && e.IsAlive())
|
||||
.Take(maxFighters);
|
||||
return self.Where(e => !e.IsInFormation(formation));
|
||||
}
|
||||
|
||||
public static bool IsAlive(this FightWorld.Fighter self)
|
||||
{
|
||||
return self.GetHealth() >= 0;
|
||||
return self.GetHealth() > 0;
|
||||
}
|
||||
|
||||
public static bool IsDead(this FightWorld.Fighter self)
|
||||
@@ -35,16 +28,21 @@ public static class FightUtils
|
||||
|
||||
public static int GetHealth(this FightWorld.Fighter self)
|
||||
{
|
||||
return self.health ?? self.maxHealth;
|
||||
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.enemies.All(e => e.IsDead());
|
||||
return self.fighters.All(e => e.IsDead());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Babushka.scripts.CSharp.Common.Fight.Actions;
|
||||
using Babushka.scripts.CSharp.Common.Util;
|
||||
using Godot;
|
||||
|
||||
@@ -19,14 +20,16 @@ public partial class FightWorld : Node
|
||||
|
||||
public class FighterGroup
|
||||
{
|
||||
public required List<Fighter> enemies;
|
||||
public required List<Fighter> fighters;
|
||||
}
|
||||
|
||||
public class FightHappeningData
|
||||
{
|
||||
public FightHappening.FightState fightState = FightHappening.FightState.None;
|
||||
public FighterStack fighterStack = new();
|
||||
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;
|
||||
}
|
||||
@@ -45,11 +48,9 @@ public partial class FightWorld : Node
|
||||
|
||||
public required Type type;
|
||||
public required int maxHealth;
|
||||
public required bool isEnemy;
|
||||
public required List<FighterAction> availableActions;
|
||||
public int maxActionPoints = 1;
|
||||
public const int MaxActionPoints = 1;
|
||||
public int? health = null; // null => initialize to full health on spawn
|
||||
public bool entered = false;
|
||||
public int actionPointsLeft;
|
||||
|
||||
public FighterAction AutoSelectAction()
|
||||
@@ -146,14 +147,14 @@ public partial class FightWorld : Node
|
||||
{
|
||||
var enemyGroup = new FighterGroup
|
||||
{
|
||||
enemies = []
|
||||
fighters = []
|
||||
};
|
||||
|
||||
var enemyCount = GD.RandRange(1, 3);
|
||||
|
||||
for (var i = 0; i < enemyCount; i++)
|
||||
{
|
||||
enemyGroup.enemies.Add(GenerateSingleEnemy());
|
||||
enemyGroup.fighters.Add(GenerateSingleEnemy());
|
||||
}
|
||||
|
||||
return enemyGroup;
|
||||
@@ -176,11 +177,10 @@ public partial class FightWorld : Node
|
||||
{
|
||||
type = type,
|
||||
health = null,
|
||||
isEnemy = true,
|
||||
maxHealth = 12,
|
||||
availableActions =
|
||||
[
|
||||
new FighterAction.Skip()
|
||||
new BlobAttackAction()
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
@@ -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<FightWorld.Fighter?> _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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://iyarqwxuwoad
|
||||
@@ -1,95 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public partial class FighterVisual : Node2D
|
||||
/// </summary>
|
||||
private void UpdateMirrorState()
|
||||
{
|
||||
_visualParent.Scale = new Vector2(_boundFighter.isEnemy ? -1 : 1, 1);
|
||||
_visualParent.Scale = new Vector2(_boundFighter.IsInFormation(HappeningData.enemyFighterFormation) ? -1 : 1, 1);
|
||||
}
|
||||
|
||||
public void UpdateHealthBar()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://2f7rqk50gtdg
|
||||
@@ -8,7 +8,7 @@ public partial class ActionSelectUiSetup : CanvasLayer
|
||||
// shortcuts
|
||||
private FightWorld.FightHappeningData HappeningData =>
|
||||
FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException();
|
||||
private FightWorld.Fighter CurrentFighter => HappeningData.fighterStack.Current;
|
||||
private FightWorld.Fighter CurrentFighter => HappeningData.fighterTurn.Current;
|
||||
|
||||
// references
|
||||
[Export] private Button _attackActionButton = null!;
|
||||
|
||||
@@ -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<T>
|
||||
{
|
||||
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<Region> regions = new();
|
||||
internal DoubleHitHandling doubleHitHandling = DoubleHitHandling.Allow;
|
||||
internal int maxHitCount = 3;
|
||||
|
||||
// add region
|
||||
public Builder<T> AddRegion(T value)
|
||||
{
|
||||
regions.Add(new Region { value = value });
|
||||
return this;
|
||||
}
|
||||
|
||||
// region settings
|
||||
public Builder<T> RegionWithProportion(float proportion)
|
||||
{
|
||||
if (regions.Count == 0)
|
||||
throw new InvalidOperationException("No region to set proportion for");
|
||||
|
||||
regions.Last().proportion = proportion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> RegionWithText(string text)
|
||||
{
|
||||
if (regions.Count == 0)
|
||||
throw new InvalidOperationException("No region to set text for");
|
||||
|
||||
regions.Last().text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> 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<T> WithDoubleHitHandling(DoubleHitHandling handling)
|
||||
{
|
||||
if (handling != DoubleHitHandling.Allow)
|
||||
throw new NotImplementedException();
|
||||
|
||||
doubleHitHandling = handling;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> WithHitCount(int hitCount)
|
||||
{
|
||||
this.maxHitCount = hitCount;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private TaskCompletionSource? _minigameComplete;
|
||||
private List<int>? _hits;
|
||||
private float _armPosition = 0f;
|
||||
private float _armSpeed = 1f;
|
||||
private List<float>? _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<List<T>> Run<T>(Builder<T> 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<T>(Builder<T> builder)
|
||||
{
|
||||
_minigameComplete = new();
|
||||
_hits = [];
|
||||
_armPosition = 0f;
|
||||
_armSpeed = 1f;
|
||||
_regions = [];
|
||||
|
||||
SetupRegions(builder);
|
||||
|
||||
_maxHitCount = builder.maxHitCount;
|
||||
}
|
||||
|
||||
private void SetupRegions<T>(Builder<T> 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<RegionVisual>();
|
||||
_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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://ct7l4er2kljnc
|
||||
@@ -0,0 +1,38 @@
|
||||
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<MinigameController.RegionTheme, Color> _fillColors = new();
|
||||
|
||||
|
||||
public override void _EnterTree()
|
||||
{
|
||||
//_sliceSprite.Material = new Material()
|
||||
}
|
||||
|
||||
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}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://cdpsa4qrlai31
|
||||
@@ -0,0 +1,10 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
public partial class SpinnyArmVisual : Node2D
|
||||
{
|
||||
public void SetAngle(float normalAngle)
|
||||
{
|
||||
Rotation = normalAngle * float.Pi * 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://djkyrp24ljff0
|
||||
@@ -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<int>()
|
||||
.WithHitCount(5)
|
||||
.AddRegion(1).RegionWithText("Hello world").RegionWithTheme(MinigameController.RegionTheme.Normal)
|
||||
.AddRegion(2).RegionWithProportion(2).RegionWithTheme(MinigameController.RegionTheme.NormalAlt1)
|
||||
.AddRegion(3).RegionWithTheme(MinigameController.RegionTheme.NormalAlt2)
|
||||
.AddRegion(4).RegionWithProportion(2).RegionWithTheme(MinigameController.RegionTheme.VeryGood)
|
||||
.AddRegion(5).RegionWithTheme(MinigameController.RegionTheme.VeryBad)
|
||||
.AddRegion(6).RegionWithProportion(2).RegionWithTheme(MinigameController.RegionTheme.Disabled)
|
||||
).ContinueWith(task => OnEnd(task.Result));
|
||||
}
|
||||
|
||||
private void OnEnd(List<int> result)
|
||||
{
|
||||
GD.Print(string.Join(" ,", result));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://iv0dbf32bfw1
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dq7gahfp0lk7v
|
||||
@@ -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
|
||||
@@ -46,4 +48,11 @@ public static class LinqExtras
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
//}
|
||||
@@ -0,0 +1 @@
|
||||
uid://d0dayn7dc885j
|
||||
Reference in New Issue
Block a user