From 667d6b258811a73c8273c91423fe51774e82674f Mon Sep 17 00:00:00 2001 From: Minimata Date: Mon, 20 Apr 2026 11:41:22 +0200 Subject: [PATCH 1/3] Starting an inventory manager --- managers/InventoryManager.cs | 36 +++++++++++++++++++ managers/InventoryManager.cs.uid | 1 + maps/levels/2 - tuto_sword.tscn | 18 +++++----- .../{Inventory.cs => InventoryUI.cs} | 8 ++--- .../{Inventory.cs.uid => InventoryUI.cs.uid} | 0 .../overlaid_menus/inventory_wrapper.gd | 3 -- project.godot | 1 + .../scripts/PlayerController.cs | 8 +++-- tools/general_manager.gd | 2 +- 9 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 managers/InventoryManager.cs create mode 100644 managers/InventoryManager.cs.uid rename menus/scenes/overlaid_menus/{Inventory.cs => InventoryUI.cs} (81%) rename menus/scenes/overlaid_menus/{Inventory.cs.uid => InventoryUI.cs.uid} (100%) diff --git a/managers/InventoryManager.cs b/managers/InventoryManager.cs new file mode 100644 index 00000000..104bf226 --- /dev/null +++ b/managers/InventoryManager.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using Godot; +using Movementtests.systems; + +namespace Movementtests.managers; + +public partial class WeaponEventInventoryChangedData(WeaponSystem.WeaponEvent forEvent, string abilityName) + : RefCounted +{ + public WeaponSystem.WeaponEvent ForEvent { get; private set; } = forEvent; + public string Ability { get; private set; } = abilityName; +} + +public partial class InventoryManager : Node +{ + [Signal] + public delegate void InventoryChangedEventHandler(); + + [Signal] + public delegate void WeaponEventInventoryChangedEventHandler(WeaponEventInventoryChangedData data); + + public Dictionary Inventory { get; } = new(); + + public static InventoryManager Instance { get; private set; } + + public override void _Ready() + { + Instance = this; + } + + public void AddAbilityForWeaponEvent(WeaponSystem.WeaponEvent forEvent, string abilityName) + { + EmitSignalWeaponEventInventoryChanged(new WeaponEventInventoryChangedData(forEvent, abilityName)); + } +} diff --git a/managers/InventoryManager.cs.uid b/managers/InventoryManager.cs.uid new file mode 100644 index 00000000..80718de8 --- /dev/null +++ b/managers/InventoryManager.cs.uid @@ -0,0 +1 @@ +uid://cgwhrwfqsiing diff --git a/maps/levels/2 - tuto_sword.tscn b/maps/levels/2 - tuto_sword.tscn index 49df4614..2f647fd8 100644 --- a/maps/levels/2 - tuto_sword.tscn +++ b/maps/levels/2 - tuto_sword.tscn @@ -343,7 +343,7 @@ transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, -7.25, 20.5, -27.5) transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 1.3647223, 23.75, -13.75) [node name="Enemy28" parent="Tutorial" index="2" unique_id=1765389924 node_paths=PackedStringArray("Target") instance=ExtResource("7_egib5")] -transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -5, 22, 16.5) +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -5, 22, 15.5) Target = NodePath("../../Player") RHealth = SubResource("Resource_invhv") RDamage = SubResource("Resource_cgfmf") @@ -520,15 +520,15 @@ size = Vector3(1, 1, 4.75) material = ExtResource("3_4m8g1") [node name="CSGBox3D137" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="10" unique_id=1930091014] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 22.5, 58) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 22.5, 57.5) use_collision = true -size = Vector3(1, 1, 11) +size = Vector3(1, 1, 12) material = ExtResource("3_4m8g1") [node name="CSGBox3D138" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="11" unique_id=1299444131] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 22.5, 58) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 22.5, 57.5) use_collision = true -size = Vector3(1, 1, 11) +size = Vector3(1, 1, 12) material = ExtResource("3_4m8g1") [node name="CSGBox3D139" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="12" unique_id=1708119368] @@ -628,9 +628,9 @@ size = Vector3(9.5, 5, 11.75) material = ExtResource("3_4m8g1") [node name="CSGBox3D133" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="28" unique_id=672467040] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 21.487345, 58) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 21.487345, 57.5) use_collision = true -size = Vector3(5, 1, 11) +size = Vector3(5, 1, 12) material = ExtResource("3_4m8g1") [node name="CSGBox3D141" type="CSGBox3D" parent="Tutorial/DashWithMantle" index="29" unique_id=1207463075] @@ -765,10 +765,10 @@ use_collision = true size = Vector3(2, 3.25, 1) material = ExtResource("3_4m8g1") -[node name="Player" parent="." index="9" unique_id=1309399929] +[node name="Player" parent="." index="10" unique_id=1309399929] transform = Transform3D(0.99999994, 0, 0, 0, 1, 0, 0, 0, 0.99999994, -0.5, 0, 0) -[node name="PlayerFellRespawn" parent="." index="10" unique_id=479136076] +[node name="PlayerFellRespawn" parent="." index="11" unique_id=479136076] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 1.5, 0) [node name="OmniLight3D" type="OmniLight3D" parent="." index="13" unique_id=702421172] diff --git a/menus/scenes/overlaid_menus/Inventory.cs b/menus/scenes/overlaid_menus/InventoryUI.cs similarity index 81% rename from menus/scenes/overlaid_menus/Inventory.cs rename to menus/scenes/overlaid_menus/InventoryUI.cs index 9db9057b..1f1aa0a1 100644 --- a/menus/scenes/overlaid_menus/Inventory.cs +++ b/menus/scenes/overlaid_menus/InventoryUI.cs @@ -1,11 +1,10 @@ using Godot; +using Movementtests.managers; using Movementtests.systems; [Tool, GlobalClass, Icon("res://assets/ui/IconGodotNode/control/icon_crate.png")] -public partial class Inventory : Control +public partial class InventoryUI : Control { - public PlayerController? Player { get; set; } - private AbilitySelection _startedFlyingSelection; private AbilitySelection _whileFlyingSelection; private AbilitySelection _stoppedFlyingSelection; @@ -22,7 +21,6 @@ public partial class Inventory : Control public void AddAbilityForEvent(WeaponSystem.WeaponEvent forEvent, string abilityName) { - if (Player is null) return; - Player.GrantWeaponExplosionAbilityForEvent(forEvent, abilityName); + InventoryManager.Instance.AddAbilityForWeaponEvent(forEvent, abilityName); } } diff --git a/menus/scenes/overlaid_menus/Inventory.cs.uid b/menus/scenes/overlaid_menus/InventoryUI.cs.uid similarity index 100% rename from menus/scenes/overlaid_menus/Inventory.cs.uid rename to menus/scenes/overlaid_menus/InventoryUI.cs.uid diff --git a/menus/scenes/overlaid_menus/inventory_wrapper.gd b/menus/scenes/overlaid_menus/inventory_wrapper.gd index 4c634ea8..17c1090f 100644 --- a/menus/scenes/overlaid_menus/inventory_wrapper.gd +++ b/menus/scenes/overlaid_menus/inventory_wrapper.gd @@ -3,13 +3,10 @@ class_name InventoryWrapper extends OverlaidMenu -@export var player: PlayerController - @onready var inventory: Control = %Inventory func _ready() -> void: if Engine.is_editor_hint(): return - inventory.Player = player func _on_close_button_pressed() -> void: close() diff --git a/project.godot b/project.godot index a11ac9fd..7559bb6c 100644 --- a/project.godot +++ b/project.godot @@ -30,6 +30,7 @@ Shaker="*uid://c7flmumgr5w3u" CsgToolkitAutoload="*uid://w8ad8q4lneis" "Forge Bootstrap"="*uid://ba8fquhtwu5mu" GlobalHelpers="*uid://dqcm83o8e66a2" +InventoryManager="*uid://cgwhrwfqsiing" [display] diff --git a/scenes/player_controller/scripts/PlayerController.cs b/scenes/player_controller/scripts/PlayerController.cs index 5bdc8a36..305fb56d 100644 --- a/scenes/player_controller/scripts/PlayerController.cs +++ b/scenes/player_controller/scripts/PlayerController.cs @@ -28,6 +28,7 @@ using Movementtests.player_controller.Scripts; using Movementtests.scenes.player_controller.scripts; using Movementtests.tools; using Movementtests.forge.abilities; +using Movementtests.managers; using Movementtests.tools.calculators; using RustyOptions; using Node = Godot.Node; @@ -715,6 +716,9 @@ public partial class PlayerController : CharacterBody3D, _parryStandard.StateEntered += OnStandardParryStarted; _parryDash.StateEntered += OnDashParryStarted; + // Inventory Management + InventoryManager.Instance.WeaponEventInventoryChanged += OnWeaponEventInventoryChanged; + // Forge events var weaponLeftToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponStartedFlyingEventTag, OnWeaponLeft); var weaponLandedToken = WeaponSystem.Events.Subscribe(WeaponSystem.WeaponStoppedFlyingEventTag, OnWeaponLanded); @@ -747,9 +751,9 @@ public partial class PlayerController : CharacterBody3D, out var failures); } - public void GrantWeaponExplosionAbilityForEvent(WeaponSystem.WeaponEvent forEvent, string abilityName) + public void OnWeaponEventInventoryChanged(WeaponEventInventoryChangedData data) { - WeaponSystem.GrantNewAbilityForEvent(forEvent, WeaponExplosionBehavior); + WeaponSystem.GrantNewAbilityForEvent(data.ForEvent, WeaponExplosionBehavior); } /////////////////////////// diff --git a/tools/general_manager.gd b/tools/general_manager.gd index c1153a1a..c342bad8 100644 --- a/tools/general_manager.gd +++ b/tools/general_manager.gd @@ -38,7 +38,7 @@ func open_toolbox() -> void: func open_inventory() -> void: var inventory: Control = open_overlaid_menu(inventory_scene) - inventory.player = player + # inventory.player = player inventory_layer.call_deferred("add_child", inventory) func on_player_died() -> void: From b0fe2549ea375bb2bab73b94013ced040244fadf Mon Sep 17 00:00:00 2001 From: Minimata Date: Tue, 21 Apr 2026 11:38:04 +0200 Subject: [PATCH 2/3] Inventory management of granted abilities --- .../abilities/ForgeAbilityBehavior.cs | 4 + managers/InventoryManager.cs | 36 +++++++-- menus/scenes/components/AbilitySelection.cs | 72 ++++++++++++----- menus/scenes/components/SelectedAbility.cs | 56 +++++++++++++ .../scenes/components/SelectedAbility.cs.uid | 1 + .../scenes/components/ability_selection.tscn | 11 +-- menus/scenes/components/selected_ability.tscn | 30 +++++++ .../options_menu/input/input_extras_menu.tscn | 12 +-- menus/scenes/overlaid_menus/InventoryUI.cs | 26 ------ .../scenes/overlaid_menus/InventoryUI.cs.uid | 1 - menus/scenes/overlaid_menus/InventoryUi.cs | 81 +++++++++++++++++++ .../scenes/overlaid_menus/InventoryUi.cs.uid | 1 + menus/scenes/overlaid_menus/inventory.tscn | 2 +- project.godot | 2 +- .../components/weapon/WeaponSystem.cs | 39 ++++++--- .../resources/forge/exploding_sword.tres | 4 + ...ing tick application ability behavior.tres | 1 + .../scripts/PlayerController.cs | 35 +++++--- 18 files changed, 322 insertions(+), 92 deletions(-) create mode 100644 menus/scenes/components/SelectedAbility.cs create mode 100644 menus/scenes/components/SelectedAbility.cs.uid create mode 100644 menus/scenes/components/selected_ability.tscn delete mode 100644 menus/scenes/overlaid_menus/InventoryUI.cs delete mode 100644 menus/scenes/overlaid_menus/InventoryUI.cs.uid create mode 100644 menus/scenes/overlaid_menus/InventoryUi.cs create mode 100644 menus/scenes/overlaid_menus/InventoryUi.cs.uid diff --git a/addons/forge/resources/abilities/ForgeAbilityBehavior.cs b/addons/forge/resources/abilities/ForgeAbilityBehavior.cs index c2f032cb..a7cfd454 100644 --- a/addons/forge/resources/abilities/ForgeAbilityBehavior.cs +++ b/addons/forge/resources/abilities/ForgeAbilityBehavior.cs @@ -10,5 +10,9 @@ namespace Gamesmiths.Forge.Godot.Resources.Abilities; [Icon("uid://bcx7anhepqfmd")] public abstract partial class ForgeAbilityBehavior : Resource { + [Export] public string? Name { get; set; } + [Export] public string? Description { get; set; } + [Export] public Texture2D? Icon { get; set; } + public abstract IAbilityBehavior GetBehavior(); } diff --git a/managers/InventoryManager.cs b/managers/InventoryManager.cs index 104bf226..8b920629 100644 --- a/managers/InventoryManager.cs +++ b/managers/InventoryManager.cs @@ -1,15 +1,15 @@ -using System; using System.Collections.Generic; +using Gamesmiths.Forge.Godot.Resources.Abilities; using Godot; using Movementtests.systems; namespace Movementtests.managers; -public partial class WeaponEventInventoryChangedData(WeaponSystem.WeaponEvent forEvent, string abilityName) +public partial class WeaponEventAbilityData(WeaponSystem.WeaponEvent forEvent, Resource ability) : RefCounted { public WeaponSystem.WeaponEvent ForEvent { get; private set; } = forEvent; - public string Ability { get; private set; } = abilityName; + public Resource Ability { get; private set; } = ability; } public partial class InventoryManager : Node @@ -18,19 +18,41 @@ public partial class InventoryManager : Node public delegate void InventoryChangedEventHandler(); [Signal] - public delegate void WeaponEventInventoryChangedEventHandler(WeaponEventInventoryChangedData data); + public delegate void WeaponEventInventoryChangedEventHandler(); + [Signal] + public delegate void WeaponEventAbilityAddedEventHandler(WeaponEventAbilityData data); + [Signal] + public delegate void WeaponEventAbilityRemovedEventHandler(WeaponEventAbilityData data); - public Dictionary Inventory { get; } = new(); + public Dictionary> WeaponEventsInventory { get; } = []; public static InventoryManager Instance { get; private set; } public override void _Ready() { Instance = this; + WeaponEventsInventory[WeaponSystem.WeaponEvent.FlyingTick] = new HashSet(); + WeaponEventsInventory[WeaponSystem.WeaponEvent.StartedFlying] = new HashSet(); + WeaponEventsInventory[WeaponSystem.WeaponEvent.StoppedFlying] = new HashSet(); } - public void AddAbilityForWeaponEvent(WeaponSystem.WeaponEvent forEvent, string abilityName) + public void AddAbilityForWeaponEvent(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior abilityBehavior) { - EmitSignalWeaponEventInventoryChanged(new WeaponEventInventoryChangedData(forEvent, abilityName)); + var inventoryForEvent = WeaponEventsInventory[forEvent]; + var addedAbilityToInventory = inventoryForEvent.Add(abilityBehavior); + if (!addedAbilityToInventory) return; + + EmitSignalWeaponEventInventoryChanged(); + EmitSignalWeaponEventAbilityAdded(new WeaponEventAbilityData(forEvent, abilityBehavior)); + } + + public void RemoveAbilityForWeaponEvent(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior abilityBehavior) + { + var inventoryForEvent = WeaponEventsInventory[forEvent]; + var removedFromInventory = inventoryForEvent.Remove(abilityBehavior); + if (!removedFromInventory) return; + + EmitSignalWeaponEventInventoryChanged(); + EmitSignalWeaponEventAbilityRemoved(new WeaponEventAbilityData(forEvent, abilityBehavior)); } } diff --git a/menus/scenes/components/AbilitySelection.cs b/menus/scenes/components/AbilitySelection.cs index 5d4445ea..f3863997 100644 --- a/menus/scenes/components/AbilitySelection.cs +++ b/menus/scenes/components/AbilitySelection.cs @@ -1,55 +1,83 @@ using System; +using System.Collections.Generic; +using Gamesmiths.Forge.Godot.Resources.Abilities; using Godot; using Movementtests.systems; [Tool, GlobalClass] public partial class AbilitySelection : Control { - [Signal] public delegate void AbilityAddedEventHandler(WeaponSystem.WeaponEvent forEvent, string abilityName); + [Signal] public delegate void AbilityAddedEventHandler(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior behavior); + [Signal] public delegate void AbilityRemovedEventHandler(WeaponSystem.WeaponEvent forEvent, ForgeAbilityBehavior behavior); [Export] public WeaponSystem.WeaponEvent ForEvent { get; set; } = WeaponSystem.WeaponEvent.StartedFlying; - private string _title = string.Empty; - [Export] public string Title { - get => _title; - set - { - _title = value; - TitleChanged(); - } - } + [Export] public string Title { get; set; } = string.Empty; - [Export] public PackedScene AbilitySelectionItem { get; set; } + [Export] public PackedScene AbilitySelectedItem { get; set; } + + [Export] public ForgeAbilityBehavior[] AbilityBehaviors { get; set; } - private VBoxContainer _abilities; + private VBoxContainer _selectedAbilities; private MenuButton _addAbility; private PopupMenu _addAbilityMenu; public override void _Ready() { - _abilities = GetNode("%SelectedAbilities"); + var titleLabel = GetNode