Compare commits

...

3 Commits

Author SHA1 Message Date
jonathan 427db88474 🧪 Tested music setup with new music concept 2025-10-24 18:10:00 +02:00
jonathan 45d4b26b6a ♻️ Implemented FightersFormation to keep track of the fight entered state of the fighters 2025-10-07 18:08:53 +02:00
jonathan 719b1fa800 ♻️Code cleanup 2025-10-07 15:50:33 +02:00
42 changed files with 507 additions and 172 deletions
+1
View File
@@ -0,0 +1 @@
Babushka
@@ -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.
@@ -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
+3 -4
View File
@@ -2,8 +2,7 @@
[ext_resource type="Script" uid="uid://cql8mt5jsmcdl" path="res://scripts/CSharp/Common/Fight/FightSceneSwitcher.cs" id="1_5dt1r"] [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") script = ExtResource("1_5dt1r")
sceneRoot = NodePath("") _fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn"
fightRoomScenePath = "res://scenes/Babushka_scene_fight_world_room.tscn" _fightHappeningScene = "res://scenes/Babushka_scene_fight_happening.tscn"
fightHappeningScene = "res://scenes/Babushka_scene_fight_happening.tscn"
+17 -4
View File
@@ -1075,9 +1075,8 @@ collision_mask = 4
position = Vector2(145.5, -224) position = Vector2(145.5, -224)
shape = SubResource("RectangleShape2D_0sfl7") 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 _active = false
_spriteToOutline = NodePath("..")
_id = 1 _id = 1
[node name="CollisionShape3D" parent="YSorted/Brünnen/InteractionArea/Area2D" index="0"] [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"] [node name="SpawnWithItem" parent="YSorted/HoeGenericPickup" index="0"]
_blueprint = ExtResource("26_ipqaa") _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"] [node name="CollisionShape3D" parent="YSorted/HoeGenericPickup/PickupInteractionArea/Area2D" index="0"]
shape = SubResource("CircleShape2D_ycj14") shape = SubResource("CircleShape2D_ycj14")
@@ -1100,6 +1102,9 @@ position = Vector2(8192, 3507)
[node name="SpawnWithItem" parent="YSorted/CanGenericPickup" index="0"] [node name="SpawnWithItem" parent="YSorted/CanGenericPickup" index="0"]
_blueprint = ExtResource("28_ipqaa") _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"] [node name="CollisionShape3D" parent="YSorted/CanGenericPickup/PickupInteractionArea/Area2D" index="0"]
shape = SubResource("CircleShape2D_2065p") shape = SubResource("CircleShape2D_2065p")
@@ -1112,6 +1117,9 @@ position = Vector2(8391, 2060)
[node name="SpawnWithItem" parent="YSorted/RakeGenericPickup" index="0"] [node name="SpawnWithItem" parent="YSorted/RakeGenericPickup" index="0"]
_blueprint = ExtResource("28_6b2nr") _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"] [node name="CollisionShape3D" parent="YSorted/RakeGenericPickup/PickupInteractionArea/Area2D" index="0"]
shape = SubResource("CircleShape2D_tm0yg") shape = SubResource("CircleShape2D_tm0yg")
@@ -1122,6 +1130,9 @@ position = Vector2(15642, 2158)
[node name="SpawnWithItem" parent="YSorted/ScytheGenericPickup" index="0"] [node name="SpawnWithItem" parent="YSorted/ScytheGenericPickup" index="0"]
_blueprint = ExtResource("29_wtdui") _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"] [node name="CollisionShape3D" parent="YSorted/ScytheGenericPickup/PickupInteractionArea/Area2D" index="0"]
shape = SubResource("CircleShape2D_lbnqo") shape = SubResource("CircleShape2D_lbnqo")
@@ -1132,6 +1143,9 @@ position = Vector2(5454, 2049)
[node name="SpawnWithItem" parent="YSorted/ShovelGenericPickup" index="0"] [node name="SpawnWithItem" parent="YSorted/ShovelGenericPickup" index="0"]
_blueprint = ExtResource("27_ipqaa") _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"] [node name="CollisionShape3D" parent="YSorted/ShovelGenericPickup/PickupInteractionArea/Area2D" index="0"]
shape = SubResource("CircleShape2D_l4wxt") shape = SubResource("CircleShape2D_l4wxt")
@@ -1156,10 +1170,9 @@ collision_mask = 6
position = Vector2(-252.56, 231.32) 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) 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) position = Vector2(5839, 2349)
scale = Vector2(2.425, 2.425) scale = Vector2(2.425, 2.425)
_spriteToOutline = NodePath("DoorSprite")
_id = 0 _id = 0
[node name="DoorSprite" type="Sprite2D" parent="YSorted/Farm visuals/Static/EnterHouseInteraction"] [node name="DoorSprite" type="Sprite2D" parent="YSorted/Farm visuals/Static/EnterHouseInteraction"]
+2 -2
View File
@@ -59,8 +59,8 @@ visible = false
script = ExtResource("10_qqd8u") script = ExtResource("10_qqd8u")
_fightSceneSwitcher = NodePath("FightSceneSwitcher") _fightSceneSwitcher = NodePath("FightSceneSwitcher")
[node name="FightSceneSwitcher" parent="SwitchSceneOnFightEnd" node_paths=PackedStringArray("sceneRoot") instance=ExtResource("2_phrlx")] [node name="FightSceneSwitcher" parent="SwitchSceneOnFightEnd" node_paths=PackedStringArray("_sceneRoot") instance=ExtResource("2_phrlx")]
sceneRoot = NodePath("../..") _sceneRoot = NodePath("../..")
[node name="ActionSelect" type="CanvasLayer" parent="." node_paths=PackedStringArray("_attackActionButton", "_summonActionButton", "_talkActionButton", "_fleeActionButton")] [node name="ActionSelect" type="CanvasLayer" parent="." node_paths=PackedStringArray("_attackActionButton", "_summonActionButton", "_talkActionButton", "_fleeActionButton")]
visible = false visible = false
+2 -1
View File
@@ -2148,8 +2148,9 @@ position = Vector2(1560, 422)
[node name="Spawn4" type="Node2D" parent="YSorted/EnemyGroupSpawns"] [node name="Spawn4" type="Node2D" parent="YSorted/EnemyGroupSpawns"]
position = Vector2(-1127, 671) 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 unique_name_in_owner = true
_sceneRoot = NodePath("..")
[node name="FightSceneSetup" type="Node" parent="." node_paths=PackedStringArray("_enemyGroupSpawns", "_fightSceneSwitcher")] [node name="FightSceneSetup" type="Node" parent="." node_paths=PackedStringArray("_enemyGroupSpawns", "_fightSceneSwitcher")]
script = ExtResource("40_cvg1r") script = ExtResource("40_cvg1r")
+16
View File
@@ -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());
}
}
+1
View File
@@ -0,0 +1 @@
uid://bfyhyjutba2o
+8
View File
@@ -0,0 +1,8 @@
extends Button
@export var i:
func _on_pressed() -> void:
pass # Replace with function body.
+1
View File
@@ -0,0 +1 @@
uid://b126dduoht87j
+82
View File
@@ -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 @@
uid://du8cm2q5kwikl
@@ -52,7 +52,7 @@ public class AllyAttackAction : FighterAction
public override async Task AnimateAction(AllFightersVisual allFightersVisual) public override async Task AnimateAction(AllFightersVisual allFightersVisual)
{ {
var currentFighter = HappeningData.fighterStack.Current; var currentFighter = HappeningData.fighterTurn.Current;
var targetFighter = targetSelect.GetTarget(); var targetFighter = targetSelect.GetTarget();
var currentFighterVisual = allFightersVisual.GetVisualForFighter(currentFighter); var currentFighterVisual = allFightersVisual.GetVisualForFighter(currentFighter);
@@ -23,7 +23,7 @@ public class BlobAttackAction : FighterAction
public override async Task AnimateAction(AllFightersVisual allFightersVisual) public override async Task AnimateAction(AllFightersVisual allFightersVisual)
{ {
var currentFighter = HappeningData.fighterStack.Current; var currentFighter = HappeningData.fighterTurn.Current;
var targetFighter = FightWorld.Instance.allyFighters.vesnaFighter; var targetFighter = FightWorld.Instance.allyFighters.vesnaFighter;
var currentFighterVisual = allFightersVisual.GetVisualForFighter(currentFighter); var currentFighterVisual = allFightersVisual.GetVisualForFighter(currentFighter);
@@ -1,10 +1,11 @@
using Godot;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Babushka.scripts.CSharp.Common.Fight;
using Babushka.scripts.CSharp.Common.Fight.ActionDetails; using Babushka.scripts.CSharp.Common.Fight.ActionDetails;
using Babushka.scripts.CSharp.Common.Util; using Babushka.scripts.CSharp.Common.Util;
using Godot;
namespace Babushka.scripts.CSharp.Common.Fight;
public partial class AllFightersVisual : Node public partial class AllFightersVisual : Node
{ {
@@ -112,10 +113,14 @@ public partial class AllFightersVisual : Node
private void ShowTargetSelect(TargetSelectActionDetail targetDetail) private void ShowTargetSelect(TargetSelectActionDetail targetDetail)
{ {
if (targetDetail.selectEnemy) 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) 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() private void HideTargetSelect()
@@ -8,7 +8,6 @@ public class AllyFighters
{ {
type = FightWorld.Fighter.Type.Vesna, type = FightWorld.Fighter.Type.Vesna,
maxHealth = 20, maxHealth = 20,
isEnemy = false,
availableActions = availableActions =
[ [
new AllyAttackAction() new AllyAttackAction()
@@ -18,7 +17,6 @@ public class AllyFighters
{ {
type = FightWorld.Fighter.Type.Chuha, type = FightWorld.Fighter.Type.Chuha,
maxHealth = 15, maxHealth = 15,
isEnemy = false,
availableActions = availableActions =
[ [
new FighterAction.Skip() new FighterAction.Skip()
+32 -13
View File
@@ -61,7 +61,7 @@ public partial class FightHappening : Node
private static FightWorld.FightHappeningData HappeningData => private static FightWorld.FightHappeningData HappeningData =>
FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException();
private static FightWorld.Fighter CurrentFighter => HappeningData.fighterStack.Current; private static FightWorld.Fighter CurrentFighter => HappeningData.fighterTurn.Current;
#endregion #endregion
@@ -204,7 +204,7 @@ public partial class FightHappening : Node
{ {
ChangeState(FightState.FightersEnter); ChangeState(FightState.FightersEnter);
} }
else if (CurrentFighter.isEnemy) else if (CurrentFighter.IsInFormation(HappeningData.enemyFighterFormation))
{ {
ChangeState(FightState.EnemyActionSelect); ChangeState(FightState.EnemyActionSelect);
} }
@@ -249,10 +249,15 @@ public partial class FightHappening : Node
_ = AdvanceToStateWhenDone(FightState.StateCheck, actionTime); _ = AdvanceToStateWhenDone(FightState.StateCheck, actionTime);
} }
break;
case FightState.EnemyWin:
// TODO: remove and find proper solution
ReviveVesna();
break; break;
default: break; default: break;
} }
} }
#endregion #endregion
#region Game Logic #region Game Logic
@@ -262,19 +267,23 @@ public partial class FightHappening : Node
// ally // ally
var enteringAllyFighters = new List<FightWorld.Fighter>(); var enteringAllyFighters = new List<FightWorld.Fighter>();
var allyFighters = FightWorld.Instance.allyFighters; var allyFighters = FightWorld.Instance.allyFighters;
if (!allyFighters.vesnaFighter.entered) if (!allyFighters.vesnaFighter.IsInFormation(HappeningData.allyFighterFormation))
{ {
enteringAllyFighters.Add(allyFighters.vesnaFighter); enteringAllyFighters.Add(allyFighters.vesnaFighter);
} }
// enemy // enemy
const int totalEnemySpace = 3; const int totalEnemySpace = 3;
var enemySpaceLeft = totalEnemySpace - HappeningData.enemyGroup.GetEnteredAmount(); var enemySpaceLeft = HappeningData.enemyFighterFormation.GetEmptySlotCount();
return new FightersEnterStaging return new FightersEnterStaging
{ {
enteringAllyFighters = enteringAllyFighters, 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); Debug.Assert(HappeningData.fightersEnterStaging != null);
foreach (var fighter in HappeningData.fightersEnterStaging.enteringAllyFighters) foreach (var fighter in HappeningData.fightersEnterStaging.enteringAllyFighters)
{ {
fighter.entered = true; var emptySlotIndex = HappeningData.allyFighterFormation.GetFirstEmptySlot();
HappeningData.fighterStack.AddAsLast(fighter); 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) foreach (var fighter in HappeningData.fightersEnterStaging.enteringEnemyFighters)
{ {
fighter.entered = true; var emptySlotIndex = HappeningData.enemyFighterFormation.GetFirstEmptySlot();
HappeningData.fighterStack.AddAsLast(fighter); 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() private void ExecuteNextFighter()
{ {
HappeningData.fighterStack.Next(); HappeningData.fighterTurn.Next();
CurrentFighter.actionPointsLeft = CurrentFighter.maxActionPoints; CurrentFighter.actionPointsLeft = FightWorld.Fighter.MaxActionPoints;
} }
private void ExecuteAction() private void ExecuteAction()
@@ -325,6 +338,14 @@ public partial class FightHappening : Node
return HappeningData.actionStaging.NextDetail(); 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 #endregion // Game Logic
#region Utility #region Utility
@@ -362,6 +383,4 @@ public partial class FightHappening : Node
} }
#endregion #endregion
} }
@@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks;
using Babushka.scripts.CSharp.Common.SceneManagement; using Babushka.scripts.CSharp.Common.SceneManagement;
using Godot; using Godot;
@@ -7,9 +8,9 @@ namespace Babushka.scripts.CSharp.Common.Fight;
public partial class FightSceneSwitcher : Node public partial class FightSceneSwitcher : Node
{ {
[Export] private Node sceneRoot; [Export] private Node _sceneRoot = null!;
[Export] private string fightRoomScenePath; [Export] private string _fightRoomScenePath = null!;
[Export] private string fightHappeningScene; [Export] private string _fightHappeningScene = null!;
private void LoadNext() private void LoadNext()
{ {
@@ -17,12 +18,12 @@ public partial class FightSceneSwitcher : Node
Debug.Assert(nextRoom != null, "nextRoom!=null"); Debug.Assert(nextRoom != null, "nextRoom!=null");
var nextFightHappening = FightWorld.Instance.fightHappeningData; var nextFightHappening = FightWorld.Instance.fightHappeningData;
SceneTransitionThreaded.Instance.ChangeSceneToFile(nextFightHappening != null SceneTransitionThreaded.Instance.ChangeSceneToFile(nextFightHappening != null
? fightHappeningScene ? _fightHappeningScene
: fightRoomScenePath); : _fightRoomScenePath);
UnloadAfterDelay(); _ = UnloadAfterDelay();
} }
private async void UnloadAfterDelay() private async Task UnloadAfterDelay()
{ {
await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); // 1.0f seconds await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); // 1.0f seconds
//sceneRoot.QueueFree(); //sceneRoot.QueueFree();
+10 -13
View File
@@ -6,22 +6,14 @@ namespace Babushka.scripts.CSharp.Common.Fight;
public static class FightUtils 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( public static IEnumerable<FightWorld.Fighter> WhereIsNotInFormation(this IEnumerable<FightWorld.Fighter> self, FighterFormation formation)
this FightWorld.FighterGroup self,
int maxFighters)
{ {
if (maxFighters <= self.enemies.Count) return self.Where(e => !e.IsInFormation(formation));
return self.enemies
.Where(e => !e.entered && e.IsAlive());
return self.enemies
.Where(e => !e.entered && e.IsAlive())
.Take(maxFighters);
} }
public static bool IsAlive(this FightWorld.Fighter self) public static bool IsAlive(this FightWorld.Fighter self)
@@ -44,8 +36,13 @@ public static class FightUtils
self.health = self.GetHealth() + 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) public static bool AreAllDead(this FightWorld.FighterGroup self)
{ {
return self.enemies.All(e => e.IsDead()); return self.fighters.All(e => e.IsDead());
} }
} }
+8 -9
View File
@@ -20,14 +20,16 @@ public partial class FightWorld : Node
public class FighterGroup public class FighterGroup
{ {
public required List<Fighter> enemies; public required List<Fighter> fighters;
} }
public class FightHappeningData public class FightHappeningData
{ {
public FightHappening.FightState fightState = FightHappening.FightState.None;
public FighterStack fighterStack = new();
public required FighterGroup enemyGroup; 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 FightHappening.FightersEnterStaging? fightersEnterStaging;
public FighterAction? actionStaging; public FighterAction? actionStaging;
} }
@@ -46,11 +48,9 @@ public partial class FightWorld : Node
public required Type type; public required Type type;
public required int maxHealth; public required int maxHealth;
public required bool isEnemy;
public required List<FighterAction> availableActions; 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 int? health = null; // null => initialize to full health on spawn
public bool entered = false;
public int actionPointsLeft; public int actionPointsLeft;
public FighterAction AutoSelectAction() public FighterAction AutoSelectAction()
@@ -147,14 +147,14 @@ public partial class FightWorld : Node
{ {
var enemyGroup = new FighterGroup var enemyGroup = new FighterGroup
{ {
enemies = [] fighters = []
}; };
var enemyCount = GD.RandRange(1, 3); var enemyCount = GD.RandRange(1, 3);
for (var i = 0; i < enemyCount; i++) for (var i = 0; i < enemyCount; i++)
{ {
enemyGroup.enemies.Add(GenerateSingleEnemy()); enemyGroup.fighters.Add(GenerateSingleEnemy());
} }
return enemyGroup; return enemyGroup;
@@ -177,7 +177,6 @@ public partial class FightWorld : Node
{ {
type = type, type = type,
health = null, health = null,
isEnemy = true,
maxHealth = 12, maxHealth = 12,
availableActions = availableActions =
[ [
@@ -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;
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ public partial class FighterVisual : Node2D
/// </summary> /// </summary>
private void UpdateMirrorState() 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() public void UpdateHealthBar()
@@ -8,7 +8,7 @@ public partial class ActionSelectUiSetup : CanvasLayer
// shortcuts // shortcuts
private FightWorld.FightHappeningData HappeningData => private FightWorld.FightHappeningData HappeningData =>
FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException();
private FightWorld.Fighter CurrentFighter => HappeningData.fighterStack.Current; private FightWorld.Fighter CurrentFighter => HappeningData.fighterTurn.Current;
// references // references
[Export] private Button _attackActionButton = null!; [Export] private Button _attackActionButton = null!;
@@ -14,12 +14,12 @@ public partial class MinigameTestStarter : Node
_minigameController.Run( _minigameController.Run(
new MinigameController.Builder<int>() new MinigameController.Builder<int>()
.WithHitCount(5) .WithHitCount(5)
.AddRegion(1) .AddRegion(1).RegionWithText("Hello world").RegionWithTheme(MinigameController.RegionTheme.Normal)
.AddRegion(2).RegionWithProportion(2) .AddRegion(2).RegionWithProportion(2).RegionWithTheme(MinigameController.RegionTheme.NormalAlt1)
.AddRegion(3) .AddRegion(3).RegionWithTheme(MinigameController.RegionTheme.NormalAlt2)
.AddRegion(4).RegionWithProportion(2) .AddRegion(4).RegionWithProportion(2).RegionWithTheme(MinigameController.RegionTheme.VeryGood)
.AddRegion(5) .AddRegion(5).RegionWithTheme(MinigameController.RegionTheme.VeryBad)
.AddRegion(6).RegionWithProportion(2) .AddRegion(6).RegionWithProportion(2).RegionWithTheme(MinigameController.RegionTheme.Disabled)
).ContinueWith(task => OnEnd(task.Result)); ).ContinueWith(task => OnEnd(task.Result));
} }