Merge remote-tracking branch 'origin/feature/fight_system' into feature/showcase_kathi

pull/12/head
kziolkowski 6 months ago
commit 7a3e96d679

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bexymddkb6l0o"
path="res://.godot/imported/mavkha.png-ab393dd20d4b3f3a305dd600f518b5fe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/characters/Mavka/mavkha.png"
dest_files=["res://.godot/imported/mavkha.png-ab393dd20d4b3f3a305dd600f518b5fe.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bgba1uv0muxat"
path="res://.godot/imported/chugeist_tmp.png-ff2e3a6be0ff4b186834b14d159443da.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/characters/chugeist_tmp.png"
dest_files=["res://.godot/imported/chugeist_tmp.png-ff2e3a6be0ff4b186834b14d159443da.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

@ -4,11 +4,12 @@ importer="scene"
importer_version=1 importer_version=1
type="PackedScene" type="PackedScene"
uid="uid://b3kyrsoobmkhp" uid="uid://b3kyrsoobmkhp"
valid=false path="res://.godot/imported/best_house_blender.blend-ac89c74aef2f275bdf4b4baadee17c0c.scn"
[deps] [deps]
source_file="res://art/mockups/3d/best_house_blender.blend" source_file="res://art/mockups/3d/best_house_blender.blend"
dest_files=["res://.godot/imported/best_house_blender.blend-ac89c74aef2f275bdf4b4baadee17c0c.scn"]
[params] [params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bn56p0ytuo060"
path="res://.godot/imported/AttackButton.png-ab1949863046f66b014201d64778c962.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/ui/UI/AttackButton.png"
dest_files=["res://.godot/imported/AttackButton.png-ab1949863046f66b014201d64778c962.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://crak7ton4lab0"
path="res://.godot/imported/EmptyFightButton.png-941012f14ef5a6d6a385ea2e7599c6bb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/ui/UI/EmptyFightButton.png"
dest_files=["res://.godot/imported/EmptyFightButton.png-941012f14ef5a6d6a385ea2e7599c6bb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bcs0e1bpu8wm1"
path="res://.godot/imported/MagicButton.png-f688abbb37e617bc75b48afd1bffb745.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/ui/UI/MagicButton.png"
dest_files=["res://.godot/imported/MagicButton.png-f688abbb37e617bc75b48afd1bffb745.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://qlfwuakhe57t"
path="res://.godot/imported/attack_select_wheel.png-437439dea02962dbfc00f0c03b7b3deb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/ui/UI/attack_select_wheel.png"
dest_files=["res://.godot/imported/attack_select_wheel.png-437439dea02962dbfc00f0c03b7b3deb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://vcv1hckwpf4j"
path="res://.godot/imported/CreepyForest_90BPM_Intro.wav-ac77ab017b924fdc37c78a363b9510f7.sample"
[deps]
source_file="res://audio/Music/CreepyForest_90BPM_Intro.wav"
dest_files=["res://.godot/imported/CreepyForest_90BPM_Intro.wav-ac77ab017b924fdc37c78a363b9510f7.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=2

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://bvjy52w673clv"
path="res://.godot/imported/CreepyForest_90BPM_Loop.wav-4a54c24ed7bd3d099be79fac1a2ee2bd.sample"
[deps]
source_file="res://audio/Music/CreepyForest_90BPM_Loop.wav"
dest_files=["res://.godot/imported/CreepyForest_90BPM_Loop.wav-4a54c24ed7bd3d099be79fac1a2ee2bd.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=2

@ -8,12 +8,22 @@
"sound_moods": {}, "sound_moods": {},
"style": "" "style": ""
}, },
&"default_portrait": "", &"default_portrait": "_tmp",
&"description": "helpful spirit forest", &"description": "helpful spirit forest",
&"display_name": "Chuga", &"display_name": "Chuga",
&"mirror": false, &"mirror": false,
&"nicknames": [""], &"nicknames": [""],
&"offset": Vector2(0, 0), &"offset": Vector2(0, 0),
&"portraits": {}, &"portraits": {
"_tmp": {
"export_overrides": {
"image": "\"res://art/characters/chugeist_tmp.png\""
},
"mirror": false,
"offset": Vector2(0, 0),
"scale": 1,
"scene": ""
}
},
&"scale": 1.0 &"scale": 1.0
} }

@ -0,0 +1,65 @@
[gd_scene load_steps=8 format=3 uid="uid://ddpl8cbck7e6s"]
[ext_resource type="Script" uid="uid://d0kgxh4ykuv23" path="res://scripts/CSharp/Common/NPC/TalkingCharacter.cs" id="1_xix7p"]
[ext_resource type="PackedScene" uid="uid://cqc72e4hq6bcd" path="res://prefabs/interactions/interaction_area_2d.tscn" id="2_udjjv"]
[ext_resource type="Texture2D" uid="uid://bgba1uv0muxat" path="res://art/characters/chugeist_tmp.png" id="3_42og6"]
[ext_resource type="Script" uid="uid://d2486x6upmwqq" path="res://scripts/GdScript/dialogic_starter.gd" id="43_xooq4"]
[ext_resource type="Script" path="res://scripts/GdScript/dialogic_toggle.gd" id="44_v6w16"]
[sub_resource type="CircleShape2D" id="CircleShape2D_at1n1"]
resource_local_to_scene = true
radius = 345.552
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_aqu1t"]
radius = 84.0
height = 168.0
[node name="Chuga" type="Node2D"]
editor_description = "This Scene seems a bit Chuga coated"
z_index = 1
y_sort_enabled = true
script = ExtResource("1_xix7p")
[node name="InteractionArea" parent="." instance=ExtResource("2_udjjv")]
position = Vector2(0, -450)
scale = Vector2(2.805, 2.805)
[node name="CollisionShape3D" parent="InteractionArea/Area2D" index="0"]
position = Vector2(-4.99109, 63.4581)
shape = SubResource("CircleShape2D_at1n1")
[node name="Label" parent="InteractionArea" index="1"]
z_index = 5
custom_minimum_size = Vector2(10, 10)
offset_left = -131.194
offset_top = -157.219
offset_right = 115.806
offset_bottom = -54.2193
theme_override_font_sizes/font_size = 60
text = "[E] talk"
[node name="TalkingControl" type="Node2D" parent="."]
[node name="Visual" type="Sprite2D" parent="TalkingControl"]
position = Vector2(-39, -770)
scale = Vector2(1.81875, 1.81875)
texture = ExtResource("3_42og6")
[node name="Dialogic starter" type="Node2D" parent="."]
script = ExtResource("43_xooq4")
[node name="DialogicToggle" type="Node2D" parent="Dialogic starter"]
script = ExtResource("44_v6w16")
[node name="AnimatableBody2D" type="AnimatableBody2D" parent="."]
position = Vector2(0, -172)
[node name="CollisionShape2D" type="CollisionShape2D" parent="AnimatableBody2D"]
position = Vector2(0, 94)
shape = SubResource("CapsuleShape2D_aqu1t")
[connection signal="Talking" from="." to="Dialogic starter" method="open"]
[connection signal="Interacted" from="InteractionArea" to="." method="ToggleTalking"]
[connection signal="timelineEnded" from="Dialogic starter/DialogicToggle" to="." method="ToggleTalking"]
[editable path="InteractionArea"]

@ -0,0 +1,49 @@
[gd_scene load_steps=3 format=3 uid="uid://hk8ahyp6dgl6"]
[ext_resource type="Script" uid="uid://c76mhhqyk4lgh" path="res://scripts/CSharp/Common/Fight/FightInstance.cs" id="1_ygesl"]
[ext_resource type="Script" uid="uid://oe1uypehqvr7" path="res://scripts/CSharp/Common/Fight/FightStateManager.cs" id="2_b0ivm"]
[node name="FightBaseScene" type="Node2D" node_paths=PackedStringArray("_friendlyFightSpots", "_enemyFightSpots", "camPositionNode", "_fightStateManager", "_fightEndText")]
script = ExtResource("1_ygesl")
_friendlyFightSpots = [NodePath("FriendlyPositions/FriendPos1"), NodePath("FriendlyPositions/FriendPos2"), NodePath("FriendlyPositions/FriendPos3")]
_enemyFightSpots = [NodePath("EnemyPositions/EnemyPos1"), NodePath("EnemyPositions/EnemyPos2"), NodePath("EnemyPositions/EnemyPos3")]
camPositionNode = NodePath("CamPositionMarker")
_fightStateManager = NodePath("FightStateManager")
_fightEndText = NodePath("ResultText")
[node name="FriendlyPositions" type="Node2D" parent="."]
position = Vector2(-625, -6)
[node name="FriendPos1" type="Node2D" parent="FriendlyPositions"]
position = Vector2(0, -395)
[node name="FriendPos2" type="Node2D" parent="FriendlyPositions"]
[node name="FriendPos3" type="Node2D" parent="FriendlyPositions"]
position = Vector2(0, 424)
[node name="EnemyPositions" type="Node2D" parent="."]
position = Vector2(611, -12)
[node name="EnemyPos1" type="Node2D" parent="EnemyPositions"]
position = Vector2(0, -395)
[node name="EnemyPos2" type="Node2D" parent="EnemyPositions"]
[node name="EnemyPos3" type="Node2D" parent="EnemyPositions"]
position = Vector2(0, 424)
[node name="FightStateManager" type="Node" parent="."]
script = ExtResource("2_b0ivm")
[node name="CamPositionMarker" type="Node2D" parent="."]
[node name="ResultText" type="Label" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_font_sizes/font_size = 141
horizontal_alignment = 1
vertical_alignment = 1

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

@ -0,0 +1,104 @@
[gd_scene load_steps=10 format=3 uid="uid://bp64p6y72j71w"]
[ext_resource type="Texture2D" uid="uid://ccrnmx6bd842k" path="res://art/characters/farm fäulnis blobs.png" id="1_vem8k"]
[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/Fighter.cs" id="2_4w1ab"]
[ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_v4f83"]
[ext_resource type="AudioStream" uid="uid://x7cc5woop5ec" path="res://audio/sfx/Battle/Enemies/SFX_Slime_Hit_V2_03.wav" id="5_v4f83"]
[ext_resource type="Texture2D" uid="uid://bn56p0ytuo060" path="res://art/ui/UI/AttackButton.png" id="5_vbkts"]
[ext_resource type="AudioStream" uid="uid://d1v012odga8pu" path="res://audio/sfx/Battle/Enemies/SFX_Water_Attack_Slimes.wav" id="6_oykh8"]
[ext_resource type="AudioStream" uid="uid://xxa3rvsal5m6" path="res://audio/sfx/Battle/Enemies/SFX_Slime_Hit_V2_06.wav" id="6_vbkts"]
[sub_resource type="CircleShape2D" id="CircleShape2D_284vk"]
radius = 291.58
[sub_resource type="CircleShape2D" id="CircleShape2D_s74nc"]
radius = 173.44
[node name="EnemyBlobFighter" type="Node2D" node_paths=PackedStringArray("_attackButtons", "_targetButtons", "_targetMarker", "_healthText", "_visualSprite")]
script = ExtResource("2_4w1ab")
name = "Blob"
maxHealth = 20
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("1_vem8k")
offset = Vector2(-8, -130)
region_enabled = true
region_rect = Rect2(1735.63, 108.423, 320.374, 333.577)
[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_v4f83")
[node name="Area2D" type="Area2D" parent="TargetButtons"]
position = Vector2(3, -76)
[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetButtons/Area2D"]
shape = SubResource("CircleShape2D_284vk")
[node name="FightButtons" type="Node2D" parent="."]
visible = false
position = Vector2(3, -588)
[node name="CircleBackground" type="Sprite2D" parent="FightButtons"]
z_index = 200
scale = Vector2(4.245, 4.245)
texture = ExtResource("3_v4f83")
[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_vbkts")
[node name="Area2D" type="Area2D" parent="FightButtons/AttackButton"]
collision_layer = 16
[node name="CollisionShape2D" type="CollisionShape2D" parent="FightButtons/AttackButton/Area2D"]
shape = SubResource("CircleShape2D_s74nc")
[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 = -451.0
offset_right = 207.0
offset_bottom = -305.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_v4f83")
[node name="DieAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("6_vbkts")
[node name="AttackAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("6_oykh8")
[connection signal="Attacking" from="." to="AttackAudio" method="play" binds= [0.0]]
[connection signal="DamageTaken" from="." to="HitAudio" method="play" binds= [0.0]]
[connection signal="Dying" from="." to="DieAudio" method="play" binds= [0.0]]
[connection signal="input_event" from="TargetButtons/Area2D" to="." method="TargetMouseEvent"]
[connection signal="mouse_entered" from="TargetButtons/Area2D" to="." method="StartHoverTarget"]
[connection signal="mouse_exited" from="TargetButtons/Area2D" to="." method="EndHoverTarget"]
[connection signal="input_event" from="FightButtons/AttackButton/Area2D" to="." method="AttackMouseEvent"]

@ -0,0 +1,109 @@
[gd_scene load_steps=10 format=3 uid="uid://cr66tpdr5rma5"]
[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/Fighter.cs" id="1_t6th8"]
[ext_resource type="Texture2D" uid="uid://bexymddkb6l0o" path="res://art/characters/Mavka/mavkha.png" id="2_shg7p"]
[ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_nkuei"]
[ext_resource type="Texture2D" uid="uid://bn56p0ytuo060" path="res://art/ui/UI/AttackButton.png" id="4_u3hw3"]
[ext_resource type="AudioStream" uid="uid://x7cc5woop5ec" path="res://audio/sfx/Battle/Enemies/SFX_Slime_Hit_V2_03.wav" id="5_so2ks"]
[ext_resource type="AudioStream" uid="uid://xxa3rvsal5m6" path="res://audio/sfx/Battle/Enemies/SFX_Slime_Hit_V2_06.wav" id="6_v175g"]
[ext_resource type="AudioStream" uid="uid://d1v012odga8pu" path="res://audio/sfx/Battle/Enemies/SFX_Water_Attack_Slimes.wav" id="7_g7k7o"]
[sub_resource type="CircleShape2D" id="CircleShape2D_284vk"]
radius = 388.063
[sub_resource type="CircleShape2D" id="CircleShape2D_s74nc"]
radius = 173.44
[node name="EnemyMavkhaFighter" type="Node2D" node_paths=PackedStringArray("_attackButtons", "_targetButtons", "_targetMarker", "_healthText", "_visualSprite")]
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="Sprite2D" type="Sprite2D" parent="Visual"]
position = Vector2(3, -200)
scale = Vector2(0.5, 0.5)
texture = ExtResource("2_shg7p")
offset = Vector2(-8, -130)
region_enabled = true
region_rect = Rect2(816.677, 286.398, 1089.01, 1249.83)
[node name="TargetButtons" type="Node2D" parent="."]
visible = false
[node name="TargetMarker" type="Sprite2D" parent="TargetButtons"]
visible = false
z_index = 200
position = Vector2(8, -270)
scale = Vector2(4.245, 4.245)
texture = ExtResource("3_nkuei")
[node name="Area2D" type="Area2D" parent="TargetButtons"]
position = Vector2(3, -76)
[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetButtons/Area2D"]
position = Vector2(-3, -207)
shape = SubResource("CircleShape2D_284vk")
[node name="FightButtons" type="Node2D" parent="."]
visible = false
position = Vector2(3, -588)
[node name="CircleBackground" type="Sprite2D" parent="FightButtons"]
z_index = 200
scale = Vector2(4.245, 4.245)
texture = ExtResource("3_nkuei")
[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("4_u3hw3")
[node name="Area2D" type="Area2D" parent="FightButtons/AttackButton"]
collision_layer = 16
[node name="CollisionShape2D" type="CollisionShape2D" parent="FightButtons/AttackButton/Area2D"]
shape = SubResource("CircleShape2D_s74nc")
[node name="HealthShow" type="Label" parent="."]
z_index = 200
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -204.0
offset_top = -731.0
offset_right = 200.0
offset_bottom = -585.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_so2ks")
[node name="DieAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("6_v175g")
[node name="AttackAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("7_g7k7o")
[connection signal="Attacking" from="." to="AttackAudio" method="play" binds= [0.0]]
[connection signal="DamageTaken" from="." to="HitAudio" method="play" binds= [0.0]]
[connection signal="Dying" from="." to="DieAudio" method="play" binds= [0.0]]
[connection signal="input_event" from="TargetButtons/Area2D" to="." method="TargetMouseEvent"]
[connection signal="mouse_entered" from="TargetButtons/Area2D" to="." method="StartHoverTarget"]
[connection signal="mouse_exited" from="TargetButtons/Area2D" to="." method="EndHoverTarget"]
[connection signal="input_event" from="FightButtons/AttackButton/Area2D" to="." method="AttackMouseEvent"]

@ -0,0 +1,123 @@
[gd_scene load_steps=11 format=3 uid="uid://cpanatqdjjpa3"]
[ext_resource type="Script" uid="uid://by88f32fou7lh" path="res://scripts/CSharp/Common/Fight/Fighter.cs" id="1_f3j2x"]
[ext_resource type="Texture2D" uid="uid://om2axn1vfa5o" path="res://art/animation/Vesna2D/Vesna Anims Sequences/S01-Idle/0001.png" id="2_2ud32"]
[ext_resource type="Texture2D" uid="uid://qlfwuakhe57t" path="res://art/ui/UI/attack_select_wheel.png" id="3_80knd"]
[ext_resource type="AudioStream" uid="uid://ch4c1wh4ghxyo" path="res://audio/sfx/Battle/Vesna/SFX_Battle_Vesna_Defense_08.wav" id="5_4r2vf"]
[ext_resource type="Texture2D" uid="uid://6h85o7fj7gmu" path="res://art/animation/Vesna3D/vesna-more-tools.png" id="5_l04qi"]
[ext_resource type="Texture2D" uid="uid://crak7ton4lab0" path="res://art/ui/UI/EmptyFightButton.png" id="5_rjjub"]
[ext_resource type="Texture2D" uid="uid://c3wht0nakaki1" path="res://art/ui/UI/icons/icon-fruit-tomatoe.png" id="6_l04qi"]
[ext_resource type="AudioStream" uid="uid://ccionrfr6e3lb" path="res://audio/sfx/Battle/Vesna/SFX_Battle_Vesna_Attack_04.wav" id="6_u1ayv"]
[sub_resource type="CircleShape2D" id="CircleShape2D_0tqnl"]
radius = 291.58
[sub_resource type="CircleShape2D" id="CircleShape2D_4r2vf"]
radius = 173.44
[node name="VesnaFighter" type="Node2D" node_paths=PackedStringArray("_attackButtons", "_targetButtons", "_targetMarker", "_healthText", "_visualSprite")]
script = ExtResource("1_f3j2x")
name = "Vesna"
maxHealth = 100
attackStrength = 10
_attackButtons = NodePath("FightButtons")
_targetButtons = NodePath("TargetButtons")
_targetMarker = NodePath("TargetButtons/TargetMarker")
_healthText = NodePath("HealthShow")
_visualSprite = NodePath("Sprite2D")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_2ud32")
offset = Vector2(43, -379)
[node name="TargetButtons" type="Node2D" parent="."]
visible = false
[node name="TargetMarker" type="Sprite2D" parent="TargetButtons"]
visible = false
z_index = 200
position = Vector2(8, -122)
scale = Vector2(4.245, 4.245)
texture = ExtResource("3_80knd")
[node name="Area2D" type="Area2D" parent="TargetButtons"]
position = Vector2(3, -76)
[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetButtons/Area2D"]
shape = SubResource("CircleShape2D_0tqnl")
[node name="FightButtons" type="Node2D" parent="."]
position = Vector2(3, -714)
[node name="CircleBackground" type="Sprite2D" parent="FightButtons"]
z_index = 200
scale = Vector2(4.245, 4.245)
texture = ExtResource("3_80knd")
[node name="AttackButton" type="Node2D" parent="FightButtons"]
position = Vector2(0, -536)
[node name="ButtonBackground" type="Sprite2D" parent="FightButtons/AttackButton"]
z_index = 200
scale = Vector2(2.48, 2.48)
texture = ExtResource("5_rjjub")
[node name="Sprite2D" type="Sprite2D" parent="FightButtons/AttackButton/ButtonBackground"]
position = Vector2(6.04839, -10.0806)
rotation = -1.0088
scale = Vector2(0.249373, 0.25079)
texture = ExtResource("5_l04qi")
region_enabled = true
region_rect = Rect2(291.897, 15.8974, 272.82, 479.385)
[node name="Area2D" type="Area2D" parent="FightButtons/AttackButton"]
collision_layer = 16
[node name="CollisionShape2D" type="CollisionShape2D" parent="FightButtons/AttackButton/Area2D"]
shape = SubResource("CircleShape2D_4r2vf")
[node name="HealButton" type="Node2D" parent="FightButtons"]
position = Vector2(427, -334)
[node name="ButtonBackground" type="Sprite2D" parent="FightButtons/HealButton"]
z_index = 200
scale = Vector2(2.48, 2.48)
texture = ExtResource("5_rjjub")
[node name="Sprite2D" type="Sprite2D" parent="FightButtons/HealButton/ButtonBackground"]
position = Vector2(4.83871, 0)
scale = Vector2(0.279343, 0.279343)
texture = ExtResource("6_l04qi")
[node name="Area2D" type="Area2D" parent="FightButtons/HealButton"]
collision_layer = 16
[node name="CollisionShape2D" type="CollisionShape2D" parent="FightButtons/HealButton/Area2D"]
shape = SubResource("CircleShape2D_4r2vf")
[node name="HealthShow" type="Label" parent="."]
z_index = 200
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -197.0
offset_top = -947.0
offset_right = 207.0
offset_bottom = -801.0
grow_horizontal = 2
grow_vertical = 2
theme_override_font_sizes/font_size = 106
text = "100/100"
horizontal_alignment = 1
vertical_alignment = 1
[node name="HitAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("5_4r2vf")
[node name="AttackAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("6_u1ayv")
[connection signal="Attacking" from="." to="AttackAudio" method="play" binds= [0.0]]
[connection signal="DamageTaken" from="." to="HitAudio" method="play" binds= [0.0]]
[connection signal="input_event" from="FightButtons/AttackButton/Area2D" to="." method="AttackMouseEvent"]
[connection signal="input_event" from="FightButtons/HealButton/Area2D" to="." method="HealMouseEvent"]

@ -24,11 +24,12 @@ buses/default_bus_layout="uid://b6dwkmkyb0axk"
[autoload] [autoload]
SceneTransition="*res://scenes/SceneTransition.tscn"
Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd" Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd"
InventoryManager="*res://scripts/CSharp/Common/Inventory/InventoryManager.cs" InventoryManager="*res://scripts/CSharp/Common/Inventory/InventoryManager.cs"
Signal_Debugger="*res://addons/SignalVisualizer/Debugger/SignalDebugger.gd"
QuestManager="*res://scripts/CSharp/Common/Quest/QuestManager.cs" QuestManager="*res://scripts/CSharp/Common/Quest/QuestManager.cs"
FightManagerAutoload="*res://prefabs/fight/fight_manager_autoload.tscn"
Signal_Debugger="*res://addons/SignalVisualizer/Debugger/SignalDebugger.gd"
SceneTransition="*res://scenes/SceneTransition.tscn"
[dialogic] [dialogic]
@ -233,6 +234,7 @@ locale/translations=PackedStringArray("res://dialog/translations/dialogic_charac
3d_physics/layer_1="General" 3d_physics/layer_1="General"
2d_physics/layer_2="Background elements" 2d_physics/layer_2="Background elements"
2d_physics/layer_3="player" 2d_physics/layer_3="player"
2d_physics/layer_5="fight ui"
3d_physics/layer_5="Player" 3d_physics/layer_5="Player"
[rendering] [rendering]

File diff suppressed because it is too large Load Diff

@ -1,13 +1,27 @@
using Babushka.scripts.CSharp.Common.Fight;
using Godot; using Godot;
namespace Babushka.scripts.CSharp.Common.Camera; namespace Babushka.scripts.CSharp.Common.Camera;
public partial class CameraController : Camera2D public partial class CameraController : Camera2D
{ {
[Export] private Node2D _followNode; #region Singleton ( Contains _EnterTree() ) // TODO: use autoload or other solution
public override void _Process(double delta) public static CameraController Instance { get; private set; } = null!;
{
this.GlobalPosition = _followNode.GlobalPosition; public override void _EnterTree()
} {
} Instance = this;
}
#endregion
[Export] private Node2D _followNode;
public FightInstance? fightToShow;
public override void _Process(double delta)
{
this.GlobalPosition = fightToShow?.camPositionNode.GlobalPosition ?? _followNode.GlobalPosition;
}
}

@ -0,0 +1,357 @@
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;
}
}
public class FightAttack
{
public int damage;
public bool needsSelectedTarget;
public Fighter? target;
public Fighter attacker;
}

@ -0,0 +1,28 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.Fight;
public partial class FightManager : Node
{
#region AutoLoad ( Contains _EnterTree() )
public static FightManager Instance { get; private set; } = null!;
public override void _EnterTree()
{
Instance = this;
}
#endregion
[Export]
public PackedScene fightingVesnaScene;
public FightParty fightParty = new();
public void StartFight(PackedScene[] enemies, FightInstance instance)
{
GD.Print("Starting Fight");
instance.Start(fightParty, enemies);
}
}

@ -0,0 +1,6 @@
namespace Babushka.scripts.CSharp.Common.Fight;
public class FightParty
{
public bool vesna = true;
}

@ -0,0 +1,19 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.Fight;
public partial class FightStarter : Node
{
[Export(PropertyHint.ArrayType)] private PackedScene[] enemies;
[Export] private FightInstance _fightInstance;
[Export] private bool _once = true;
private bool hasBeenStarted = false;
public void Start(Node2D _)
{
if (_once && hasBeenStarted)
return;
hasBeenStarted = true;
FightManager.Instance.StartFight(enemies, _fightInstance);
}
}

@ -0,0 +1,76 @@
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,181 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.Fight;
public partial class Fighter : Node2D
{
[Export] public string name;
[Export] public int maxHealth;
[Export] public int attackStrength;
[Export] public int maxActions = 1;
[ExportCategory("References")]
[Export] private Node2D _attackButtons;
[Export] private Node2D _targetButtons;
[Export] private Node2D _targetMarker;
[Export] private Label _healthText;
[Export] private Node2D _visualSprite;
[Signal] public delegate void DamageTakenEventHandler();
[Signal] public delegate void AttackingEventHandler();
[Signal] public delegate void DyingEventHandler();
[Signal] public delegate void HealedEventHandler();
private int _health;
private int _actions;
public FightInstance fightInstance;
public int Health
{
get => _health;
set
{
_health = value;
if (_health <= 0)
{
_health = 0;
Die();
}
if (_health > maxHealth)
{
_health = maxHealth;
}
}
}
private void Die()
{
_visualSprite.Scale = new Vector2(1, 0.3f);
EmitSignalDying();
}
public override void _Ready()
{
Health = maxHealth;
UpdateHealthVisual();
ResetActions();
}
public void Attack()
{
fightInstance.SelectAttack(this);
}
public void HideAttackButton()
{
_attackButtons.Hide();
}
public void ShowAttackButton()
{
_attackButtons.Show();
}
public void HideTargetButtons()
{
_targetButtons.Hide();
}
public void ShowTargetButtons()
{
_targetButtons.Show();
}
public void TargetMouseEvent(Node viewport, InputEvent inputEvent, int shapeIdx)
{
if (inputEvent.IsPressed())
ClickedTarget();
}
public void AttackMouseEvent(Node viewport, InputEvent inputEvent, int shapeIdx)
{
if (inputEvent.IsPressed())
ClickedAttack();
}
public void HealMouseEvent(Node viewport, InputEvent inputEvent, int shapeIdx)
{
if (inputEvent.IsPressed())
ClickedHeal();
}
private void ClickedAttack()
{
fightInstance.SelectAttack(this);
}
private void ClickedHeal()
{
fightInstance.SelectHeal(this);
}
private void ClickedTarget()
{
fightInstance.SelectTargetAndAttack(this);
}
public void StartHoverTarget()
{
_targetMarker.Visible = true;
}
public void EndHoverTarget()
{
_targetMarker.Visible = false;
}
public void UpdateHealthVisual()
{
_healthText.Text = $"{Health}/{maxHealth}";
}
public void AttackAnimation(FightAttack attack)
{
EmitSignalAttacking();
var tween = GetTree().CreateTween();
tween.TweenProperty(this, "global_position", attack.target.GlobalPosition, 0.15);
tween.TweenCallback(Callable.From(() => attack.target?.HitAnimation(attack)));
tween.TweenProperty(this, "position", new Vector2(0, 0), 0.7)
.SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out);
}
private void HitAnimation(FightAttack attack)
{
EmitSignalDamageTaken();
var tween = GetTree().CreateTween();
tween.TweenProperty(this, "scale", new Vector2(1.4f, 0.6f), 0.15);
tween.TweenProperty(this, "scale", new Vector2(1, 1), 0.4)
.SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out);
}
public bool IsDead()
{
return Health <= 0;
}
public void ResetActions()
{
_actions = maxActions;
}
public bool HasActionsLeft()
{
return _actions > 0;
}
public void DecrementActions()
{
_actions--;
}
public void HealAnimation()
{
EmitSignalHealed();
var tween = GetTree().CreateTween();
tween.TweenProperty(this, "scale", new Vector2(0.6f, 1.4f), 0.15);
tween.TweenProperty(this, "scale", new Vector2(1, 1), 0.4)
.SetTrans(Tween.TransitionType.Cubic).SetEase(Tween.EaseType.Out);
}
}

@ -4,13 +4,13 @@ namespace Babushka.scripts.CSharp.Common.NPC;
public partial class TalkingCharacter : Node2D public partial class TalkingCharacter : Node2D
{ {
[Export] private AnimatedSprite2D _sprite; [Export] private AnimatedSprite2D? _sprite;
[Export] private string[] _timelinesToPlay; [Export] private string[] _timelinesToPlay;
private bool _isTalking = true; private bool _isTalking = true;
private int _timelineIndex = 0; private int _timelineIndex = 0;
[Signal] public delegate void TalkingEventHandler(string timelineName); [Signal] public delegate void TalkingEventHandler(string timelineName);
public override void _Ready() public override void _Ready()
@ -22,16 +22,19 @@ public partial class TalkingCharacter : Node2D
{ {
if (_isTalking || _timelineIndex >= _timelinesToPlay.Length) if (_isTalking || _timelineIndex >= _timelinesToPlay.Length)
{ {
_sprite.Animation = "idle"; if (_sprite != null)
_sprite.Animation = "idle";
_isTalking = false; _isTalking = false;
} }
else else
{ {
_sprite.Animation = "talk"; if (_sprite != null)
_sprite.Animation = "talk";
_isTalking = true; _isTalking = true;
EmitSignal(SignalName.Talking, _timelinesToPlay[_timelineIndex]); EmitSignal(SignalName.Talking, _timelinesToPlay[_timelineIndex]);
_timelineIndex++; _timelineIndex++;
} }
_sprite.Play(); if (_sprite != null)
_sprite.Play();
} }
} }

@ -0,0 +1,27 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Linq;
using System.Xml.Schema;
namespace Babushka.scripts.CSharp.Common.Util;
public static class LinqExtras
{
public static void ForEach<T>(this IEnumerable<T> self, Action<T> action)
{
foreach (var t in self)
{
action.Invoke(t);
}
}
public static T? Random<T>(this IEnumerable<T> self)
{
var selfList = self.ToList();
if (selfList.Count == 0) return default;
if (selfList.Count == 1) return selfList[0];
var randomIndex = new Random().Next(0, selfList.Count);
return selfList[randomIndex];
}
}
Loading…
Cancel
Save