diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml index 3f0715b4..635d3698 100644 --- a/.gitea/workflows/main.yaml +++ b/.gitea/workflows/main.yaml @@ -89,61 +89,61 @@ jobs: # name: Test Report # path: ${{ github.workspace }}/reports/test-result.html # - OtherTest: - runs-on: godot - env: - RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache - steps: - - name: Checkout with LFS - uses: https://git.game-dev.space/minimata/checkout-with-lfs.git@main - - - uses: actions/setup-dotnet@v5 - name: 💽 Setup .NET SDK - with: - dotnet-version: '9.0.x' - - - name: 📦 Restore Dependencies - run: | - dotnet --version - dotnet restore - dotnet build - dotnet list package - - - uses: chickensoft-games/setup-godot@v2 - name: 🤖 Setup Godot - with: - # Version must include major, minor, and patch, and be >= 4.0.0 - # Pre-release label is optional. - version: '4.6.2' - # Use .NET-enabled version of Godot (the default is also true). - use-dotnet: true - # Include the Godot Export Templates (the default is false). - include-templates: true - - - name: 🔬 Verify Setup - run: | - dotnet --version - godot --version - - - name: 🧑‍🔬 Generate .NET Bindings - run: godot --headless --build-solutions --import --quit || exit 0 - - - name: 🦺 Build Projects - run: dotnet build --configuration ExportRelease - - - name: Run C# Tests - env: - GODOT_BIN: /root/bin/godot - shell: bash - run: | - dotnet test --no-build --settings .runsettings --results-directory ./reports --logger "console;verbosity=normal" --logger "trx;LogFileName=results.xml" -- GdUnit4.Parameters="--headless --import --quit" - - - name: Upload test report - uses: actions/upload-artifact@v3-node20 - if: always() - with: - name: Test Report - path: ${{ github.workspace }}/reports/test-result.html +# OtherTest: +# runs-on: godot +# env: +# RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache +# steps: +# - name: Checkout with LFS +# uses: https://git.game-dev.space/minimata/checkout-with-lfs.git@main +# +# - uses: actions/setup-dotnet@v5 +# name: 💽 Setup .NET SDK +# with: +# dotnet-version: '9.0.x' +# +# - name: 📦 Restore Dependencies +# run: | +# dotnet --version +# dotnet restore +# dotnet build +# dotnet list package +# +# - uses: chickensoft-games/setup-godot@v2 +# name: 🤖 Setup Godot +# with: +# # Version must include major, minor, and patch, and be >= 4.0.0 +# # Pre-release label is optional. +# version: '4.6.2' +# # Use .NET-enabled version of Godot (the default is also true). +# use-dotnet: true +# # Include the Godot Export Templates (the default is false). +# include-templates: true +# +# - name: 🔬 Verify Setup +# run: | +# dotnet --version +# godot --version +# +# - name: 🧑‍🔬 Generate .NET Bindings +# run: godot --headless --build-solutions --import --quit || exit 0 +# +# - name: 🦺 Build Projects +# run: dotnet build --configuration ExportRelease +# +# - name: Run C# Tests +# env: +# GODOT_BIN: /root/bin/godot +# shell: bash +# run: | +# dotnet test --no-build --settings .runsettings --results-directory ./reports --logger "console;verbosity=normal" --logger "trx;LogFileName=results.xml" -- GdUnit4.Parameters="--headless --import --quit" +# +# - name: Upload test report +# uses: actions/upload-artifact@v3-node20 +# if: always() +# with: +# name: Test Report +# path: ${{ github.workspace }}/reports/test-result.html Export: runs-on: godot diff --git a/managers/InventoryManager.cs b/managers/InventoryManager.cs index eec1b254..464ab7e8 100644 --- a/managers/InventoryManager.cs +++ b/managers/InventoryManager.cs @@ -1,36 +1,40 @@ using System.Collections.Generic; +using Chickensoft.AutoInject; +using Chickensoft.Introspection; using Gamesmiths.Forge.Godot.Resources.Abilities; using Godot; using Movementtests.systems; namespace Movementtests.managers; -public partial class WeaponEventAbilityData(WeaponSystem.WeaponEvent forEvent, Resource ability) +public partial class WeaponEventAbilityData(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior ability) : RefCounted { public WeaponSystem.WeaponEvent ForEvent { get; private set; } = forEvent; - public Resource Ability { get; private set; } = ability; + public ForgeAbilityBehavior Ability { get; private set; } = ability; } +[GlobalClass] public partial class InventoryManager : Node { - [Signal] - public delegate void InventoryChangedEventHandler(); - - [Signal] - public delegate void WeaponEventInventoryChangedEventHandler(); + #region Signals + [Signal] public delegate void WeaponEventAbilityAddedEventHandler(WeaponEventAbilityData data); [Signal] public delegate void WeaponEventAbilityRemovedEventHandler(WeaponEventAbilityData data); - public Dictionary> WeaponEventsInventory { get; } = []; + #endregion - public override void _Ready() + public Dictionary> WeaponEventsInventory { get; + private set; + } = []; + + public void InitializeFromResource(WeaponInventory inventory) { - WeaponEventsInventory[WeaponSystem.WeaponEvent.FlyingTick] = new HashSet(); - WeaponEventsInventory[WeaponSystem.WeaponEvent.StartedFlying] = new HashSet(); - WeaponEventsInventory[WeaponSystem.WeaponEvent.StoppedFlying] = new HashSet(); + WeaponEventsInventory[WeaponSystem.WeaponEvent.FlyingTick] = new HashSet(inventory.OnWeaponFlyingTickAbilities); + WeaponEventsInventory[WeaponSystem.WeaponEvent.StartedFlying] = new HashSet(inventory.OnWeaponStartedFlyingAbilities); + WeaponEventsInventory[WeaponSystem.WeaponEvent.StoppedFlying] = new HashSet(inventory.OnWeaponStoppedFlyingAbilities); } public void AddAbilityForWeaponEvent(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior abilityBehavior) @@ -39,7 +43,6 @@ public partial class InventoryManager : Node var addedAbilityToInventory = inventoryForEvent.Add(abilityBehavior); if (!addedAbilityToInventory) return; - EmitSignalWeaponEventInventoryChanged(); EmitSignalWeaponEventAbilityAdded(new WeaponEventAbilityData(forEvent, abilityBehavior)); } @@ -49,7 +52,6 @@ public partial class InventoryManager : Node var removedFromInventory = inventoryForEvent.Remove(abilityBehavior); if (!removedFromInventory) return; - EmitSignalWeaponEventInventoryChanged(); EmitSignalWeaponEventAbilityRemoved(new WeaponEventAbilityData(forEvent, abilityBehavior)); } } diff --git a/managers/WeaponInventory.cs b/managers/WeaponInventory.cs new file mode 100644 index 00000000..cd6e851f --- /dev/null +++ b/managers/WeaponInventory.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Gamesmiths.Forge.Godot.Resources.Abilities; +using Godot; + +namespace Movementtests.managers; + +[GlobalClass] +public partial class WeaponInventory( + ForgeAbilityBehavior[] onWeaponStartedFlyingAbilities, + ForgeAbilityBehavior[] onWeaponFlyingTickAbilities, + ForgeAbilityBehavior[] onWeaponStoppedFlyingAbilities + ) : Resource +{ + [Export] + public ForgeAbilityBehavior[] OnWeaponStartedFlyingAbilities { get; set; } = onWeaponStartedFlyingAbilities; + [Export] + public ForgeAbilityBehavior[] OnWeaponFlyingTickAbilities { get; set; } = onWeaponFlyingTickAbilities; + [Export] + public ForgeAbilityBehavior[] OnWeaponStoppedFlyingAbilities { get; set; } = onWeaponStoppedFlyingAbilities; + + public WeaponInventory() : this([], [], []) {} +} \ No newline at end of file diff --git a/managers/WeaponInventory.cs.uid b/managers/WeaponInventory.cs.uid new file mode 100644 index 00000000..87735c1e --- /dev/null +++ b/managers/WeaponInventory.cs.uid @@ -0,0 +1 @@ +uid://cgaahnfgxcrr6 diff --git a/maps/_templates/MainSceneTemplate.cs b/maps/_templates/MainSceneTemplate.cs index 9e3437a1..41d6c5a8 100644 --- a/maps/_templates/MainSceneTemplate.cs +++ b/maps/_templates/MainSceneTemplate.cs @@ -13,33 +13,36 @@ using Movementtests.systems; public partial class MainSceneTemplate : Node3D, IProvide { public override void _Notification(int what) => this.Notify(what); - - [Node("PlayerFellRespawn")] private Marker3D? PlayerRespawnMarker { get; set; } - private AnimationPlayer? _animationPlayer; - private Node3D? _respawnabble; - private Area3D? _playerFellPlane; - private Area3D? _deathPlane; + #region Nodes + + [Node("PlayerFellRespawn")] public required Marker3D PlayerRespawnMarker { get; set; } + [Node("AnimationPlayer")] public required AnimationPlayer AnimationPlayer { get; set; } + [Node("PlayerFellTP")] public required Area3D PlayerFellPlane { get; set; } + [Node("DeathPlane")] public required Area3D DeathPlane { get; set; } + + #endregion + + private Node3D? Respawnabble { get; set; } + + #region Exports + + [Export] public WeaponInventory? InitialWeaponInventory { get; set; } + + #endregion public required InventoryManager InventoryManager { get; set; } InventoryManager IProvide.Value() => InventoryManager; public void OnReady() { - _animationPlayer = GetNode("AnimationPlayer"); - - _playerFellPlane = GetNode("PlayerFellTP"); - _deathPlane = GetNode("DeathPlane"); - - if (PlayerRespawnMarker == null) throw new Exception("Player respawn marker is null"); - if (_animationPlayer == null) throw new Exception("Animation player is null"); - if (_playerFellPlane == null) throw new Exception("Player reset plane is null"); - if (_deathPlane == null) throw new Exception("Enemy death plane is null"); - - _playerFellPlane.BodyEntered += StartResetPlayerAnimation; - _deathPlane.BodyEntered += KillEnemy; + PlayerFellPlane.BodyEntered += StartResetPlayerAnimation; + DeathPlane.BodyEntered += KillEnemy; InventoryManager = new InventoryManager(); + if (InitialWeaponInventory != null) + InventoryManager.InitializeFromResource(InitialWeaponInventory); + AddChild(InventoryManager); this.Provide(); } @@ -53,8 +56,8 @@ public partial class MainSceneTemplate : Node3D, IProvide public void ResetPlayerPosition() { - if (_respawnabble == null || PlayerRespawnMarker == null) throw new Exception("Player or respawn marker is null"); - _respawnabble.GlobalPosition = PlayerRespawnMarker.GlobalPosition; + if (Respawnabble == null || PlayerRespawnMarker == null) throw new Exception("Player or respawn marker is null"); + Respawnabble.GlobalPosition = PlayerRespawnMarker.GlobalPosition; } public void StartResetPlayerAnimation(Node3D body) @@ -66,23 +69,19 @@ public partial class MainSceneTemplate : Node3D, IProvide weapon.SetLinearVelocity(Vector3.Down); return; } - _respawnabble = body as PlayerController; - if (_respawnabble == null || _animationPlayer == null) throw new Exception("Player or anim player is null"); - _animationPlayer.Play("player_fell"); + Respawnabble = body as PlayerController; + if (Respawnabble == null || AnimationPlayer == null) throw new Exception("Player or anim player is null"); + AnimationPlayer.Play("player_fell"); } public void KillEnemy(Node3D body) { - if (body is not IKillable killable) - { - body.QueueFree(); - return; - } - if (killable is not IHealthable healthable) + if (body is not (IKillable killable and IHealthable healthable)) { body.QueueFree(); return; } + killable.Kill(healthable); } } diff --git a/maps/levels/2 - tuto_sword.tscn b/maps/levels/2 - tuto_sword.tscn index 2f647fd8..81df0568 100644 --- a/maps/levels/2 - tuto_sword.tscn +++ b/maps/levels/2 - tuto_sword.tscn @@ -64,7 +64,7 @@ size = Vector3(5, 2.25, 3.75) size = Vector3(5.5, 4.5, 2) [sub_resource type="BoxShape3D" id="BoxShape3D_prjj8"] -size = Vector3(2, 3.25, 5.25) +size = Vector3(2, 3.25, 4) [sub_resource type="BoxShape3D" id="BoxShape3D_trte5"] size = Vector3(6.75, 8.25, 7.25) @@ -420,7 +420,7 @@ input_related_text = "at enemy" tuto_text = "dash through" [node name="CollisionShape3D" type="CollisionShape3D" parent="Tutorial/Triggers/TutoTrigger6" index="1" unique_id=1214410006] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.625, 1.75, -0.75) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.625, 1.75, -0.125) shape = SubResource("BoxShape3D_prjj8") [node name="TutoTrigger7" parent="Tutorial/Triggers" index="5" unique_id=271532103 instance=ExtResource("10_vqwwk")] @@ -616,15 +616,15 @@ size = Vector3(7.25, 7.75, 2) material = ExtResource("3_4m8g1") [node name="CSGBox3D124" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="26" unique_id=1068505352] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10.5, 19.487345, 11.25) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10.5, 19.237345, 11.25) use_collision = true -size = Vector3(3, 5, 8.5) +size = Vector3(3, 4.5, 8.5) material = ExtResource("3_4m8g1") [node name="CSGBox3D129" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="27" unique_id=302301078] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.25, 19.487345, 38.625) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.25, 19.487345, 38) use_collision = true -size = Vector3(9.5, 5, 11.75) +size = Vector3(9.5, 5, 13) material = ExtResource("3_4m8g1") [node name="CSGBox3D133" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="28" unique_id=672467040] @@ -775,5 +775,9 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 1.5, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.5, 25, 4) [node name="OmniLight3D2" type="OmniLight3D" parent="." index="14" unique_id=2016820716] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.5, 25, -9.5) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.5, 25, -10) +omni_range = 12.0 + +[node name="OmniLight3D3" type="OmniLight3D" parent="." index="15" unique_id=845858088] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.5, 25, -25.5) omni_range = 12.0 diff --git a/maps/levels/3 - tuto_enemies.tscn b/maps/levels/3 - tuto_enemies.tscn index 950e1c19..2f85024a 100644 --- a/maps/levels/3 - tuto_enemies.tscn +++ b/maps/levels/3 - tuto_enemies.tscn @@ -1,8 +1,10 @@ [gd_scene format=3 uid="uid://ndnor8g7kq07"] [ext_resource type="PackedScene" uid="uid://55wehh6xombr" path="res://maps/_templates/main_scene_template.tscn" id="1_k7f42"] +[ext_resource type="Resource" uid="uid://ifeavnlps7hy" path="res://scenes/player_controller/resources/forge/exploding_sword.tres" id="2_ctafv"] [ext_resource type="PackedScene" uid="uid://y77cdg7gg3y7" path="res://maps/levels/_arenas/playtest_1.tscn" id="2_kutfq"] [ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/materials/greybox/m_greybox.tres" id="3_1qo78"] +[ext_resource type="Script" uid="uid://cgaahnfgxcrr6" path="res://managers/WeaponInventory.cs" id="3_nix1q"] [ext_resource type="PackedScene" uid="uid://c305mfrtumcyq" path="res://scenes/spawners/spawner.tscn" id="4_jaqjx"] [ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="5_iq67o"] [ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="6_l44fp"] @@ -15,10 +17,18 @@ [ext_resource type="PackedScene" uid="uid://qup00a7x2sji" path="res://scenes/fixed_dash_target/fixed_dashthrough_target.tscn" id="13_iq67o"] [ext_resource type="PackedScene" uid="uid://b8aet6m4m2i83" path="res://scenes/tuto_trigger/TutoTrigger.tscn" id="14_lthgu"] +[sub_resource type="Resource" id="Resource_udq24"] +script = ExtResource("3_nix1q") +OnWeaponStartedFlyingAbilities = Array[Object]([ExtResource("2_ctafv")]) +OnWeaponFlyingTickAbilities = Array[Object]([ExtResource("2_ctafv")]) +OnWeaponStoppedFlyingAbilities = Array[Object]([ExtResource("2_ctafv")]) +metadata/_custom_type_script = "uid://cgaahnfgxcrr6" + [sub_resource type="BoxShape3D" id="BoxShape3D_lthgu"] size = Vector3(7.5, 3.75, 10.25) [node name="Main" unique_id=955321579 instance=ExtResource("1_k7f42")] +InitialWeaponInventory = SubResource("Resource_udq24") [node name="PlaytestArena" parent="." index="6" unique_id=664535670 instance=ExtResource("2_kutfq")] diff --git a/menus/scenes/components/AbilitySelection.cs b/menus/scenes/components/AbilitySelection.cs index f3863997..aae1e7ab 100644 --- a/menus/scenes/components/AbilitySelection.cs +++ b/menus/scenes/components/AbilitySelection.cs @@ -1,82 +1,92 @@ using System; using System.Collections.Generic; +using Chickensoft.AutoInject; +using Chickensoft.Introspection; using Gamesmiths.Forge.Godot.Resources.Abilities; using Godot; using Movementtests.systems; -[Tool, GlobalClass] +[Tool, GlobalClass, Meta(typeof(IAutoConnect))] public partial class AbilitySelection : Control { + public override void _Notification(int what) => this.Notify(what); + + #region Signals + [Signal] public delegate void AbilityAddedEventHandler(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior behavior); [Signal] public delegate void AbilityRemovedEventHandler(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior behavior); + + #endregion + + #region Exports [Export] public WeaponSystem.WeaponEvent ForEvent { get; set; } = WeaponSystem.WeaponEvent.StartedFlying; - [Export] public string Title { get; set; } = string.Empty; - - [Export] public PackedScene AbilitySelectedItem { get; set; } - - [Export] public ForgeAbilityBehavior[] AbilityBehaviors { get; set; } + [Export] public PackedScene? AbilitySelectedItem { get; set; } + [Export] public ForgeAbilityBehavior[] AbilityBehaviors { get; set; } = []; - private VBoxContainer _selectedAbilities; - private MenuButton _addAbility; - private PopupMenu _addAbilityMenu; + #endregion + + #region Nodes + + [Node("%SelectedAbilities")] public required VBoxContainer SelectedAbilities { get; set; } + [Node("%AddAbility")] public required MenuButton AddAbility { get; set; } + public required PopupMenu AddAbilityMenu { get; set; } + + #endregion - public override void _Ready() + public void OnReady() { + // Initialize title (also in Editor as Tool) var titleLabel = GetNode