diff --git a/Events/EventBus.cs b/Events/EventBus.cs index 9aa4885..e158812 100644 --- a/Events/EventBus.cs +++ b/Events/EventBus.cs @@ -51,6 +51,9 @@ public partial class EventBus : Node [Signal] public delegate void ExitTransitionEventHandler(); + [Signal] + public delegate void EnterShopEventHandler(string shopResourcePath); + public override void _Ready() { ProcessMode = ProcessModeEnum.Always; diff --git a/Items/IItemCollection.cs b/Items/IItemCollection.cs new file mode 100644 index 0000000..c715fb9 --- /dev/null +++ b/Items/IItemCollection.cs @@ -0,0 +1,15 @@ +namespace SupaLidlGame.Items; + +public interface IItemCollection +{ + public System.Collections.Generic.IEnumerable GetItems(); + + public int Capacity { get; } +} + +public interface IItemCollection : IItemCollection +{ + public bool Add(T item); + + public bool Remove(T item); +} diff --git a/Items/Inventory.cs b/Items/Inventory.cs index e958821..80f286c 100644 --- a/Items/Inventory.cs +++ b/Items/Inventory.cs @@ -4,7 +4,7 @@ using Godot.Collections; namespace SupaLidlGame.Items; -public partial class Inventory : Node2D +public partial class Inventory : Node2D, IItemCollection { public Character Character { get; private set; } @@ -23,7 +23,12 @@ public partial class Inventory : Node2D [Signal] public delegate void EquippedItemEventHandler(Item newItem, Item prevItem); - public const int MaxCapacity = 3; + [Signal] + public delegate void ItemAddedEventHandler(ItemMetadata newItemMetadata); + + public int Capacity { get; set; } = 30; + + public const int HotbarCapacity = 3; private Item _selectedItem; @@ -141,8 +146,9 @@ public partial class Inventory : Node2D return null; } - public Item AddItemToHotbar(ItemMetadata metadata) + public Item AddToHotbar(ItemMetadata metadata) { + //AddItemMetadata(metadata); var item = metadata.Instance.Instantiate(); AddItem(item); AddChild(item); @@ -152,7 +158,7 @@ public partial class Inventory : Node2D public Item AddItem(Item item) { - if (Hotbar.Count >= MaxCapacity) + if (Hotbar.Count >= HotbarCapacity) { return null; } @@ -163,9 +169,32 @@ public partial class Inventory : Node2D { Hotbar.Add(item); } + return item; } + public System.Collections.Generic.IEnumerable GetItems() + { + return Items; + } + + public bool Add(ItemMetadata item) + { + if (Items.Count >= Capacity) + { + return false; + } + + Items.Add(item); + EmitSignal(SignalName.ItemAdded, item); + return true; + } + + public bool Remove(ItemMetadata item) + { + return Items.Remove(item); + } + public Item DropItem(Item item) { item.CharacterOwner = null; diff --git a/Items/Shop.cs b/Items/Shop.cs new file mode 100644 index 0000000..4ba249a --- /dev/null +++ b/Items/Shop.cs @@ -0,0 +1,45 @@ +using Godot; +using Godot.Collections; +using GodotUtilities.Collections; +using System.Linq; +using SupaLidlGame.Utils; + +namespace SupaLidlGame.Items; + +[GlobalClass] +public partial class Shop : Resource, IItemCollection +{ + [Export] + protected Godot.Collections.Array Entries { get; private set; } + + public System.Collections.Generic.IEnumerable GetItems() + { + var mapState = World.Instance.GlobalState.MapState; + return Entries + .Where( + (entry) => + { + var condition = entry.MapStateCondition; + if (string.IsNullOrEmpty(condition)) + { + return true; + } + return mapState.GetBoolean(condition) ?? false; + } + ) + .Select((entry) => entry.Item); + } + + public bool Add(ShopEntry entry) + { + Entries.Add(entry); + return true; + } + + public bool Remove(ShopEntry entry) + { + return Entries.Remove(entry); + } + + public int Capacity => Entries.Count; +} diff --git a/Items/ShopEntry.cs b/Items/ShopEntry.cs new file mode 100644 index 0000000..b5617ad --- /dev/null +++ b/Items/ShopEntry.cs @@ -0,0 +1,23 @@ +using Godot; + +namespace SupaLidlGame.Items; + +[GlobalClass] +public partial class ShopEntry : Resource +{ + public ShopEntry() : base() + { + + } + + public ShopEntry(ItemMetadata item) : base() + { + Item = item; + } + + [Export] + public ItemMetadata Item { get; set; } + + [Export] + public string MapStateCondition { get; set; } +} diff --git a/Items/Shops/SnusDealer.tres b/Items/Shops/SnusDealer.tres new file mode 100644 index 0000000..83b4905 --- /dev/null +++ b/Items/Shops/SnusDealer.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="Shop" load_steps=5 format=3 uid="uid://djqd88vdkoi6d"] + +[ext_resource type="Script" path="res://Items/Shop.cs" id="1_betbc"] +[ext_resource type="Resource" uid="uid://cjsh0dcgbfn77" path="res://Items/Weapons/Bow.tres" id="1_ntroj"] +[ext_resource type="Script" path="res://Items/ShopEntry.cs" id="2_xgvwu"] + +[sub_resource type="Resource" id="Resource_jdx0p"] +script = ExtResource("2_xgvwu") +Item = ExtResource("1_ntroj") +MapStateCondition = "" + +[resource] +script = ExtResource("1_betbc") +Entries = Array[Object]([SubResource("Resource_jdx0p")]) diff --git a/State/Global/MapState.cs b/State/Global/MapState.cs index 4c3824b..6b8bf71 100644 --- a/State/Global/MapState.cs +++ b/State/Global/MapState.cs @@ -45,4 +45,13 @@ public partial class MapState : Resource } } } + + public bool? GetBoolean(string key) + { + if (_state[key].VariantType == Variant.Type.Bool) + { + return (bool)_state[key]; + } + return null; + } } diff --git a/UI/Inventory/ShopMenu.cs b/UI/Inventory/ShopMenu.cs new file mode 100644 index 0000000..839ab74 --- /dev/null +++ b/UI/Inventory/ShopMenu.cs @@ -0,0 +1,38 @@ +using Godot; + +namespace SupaLidlGame.UI.Inventory; + +public partial class ShopMenu : Control, IModal +{ + private Items.IItemCollection _source; + + public Items.IItemCollection Source + { + get => _source; + set + { + GD.Print("Set ShopMenu source"); + _source = value; + _inventoryGrid.Source = value; + } + } + + [Export] + private InventoryGrid _inventoryGrid; + + public void HideModal() + { + Hide(); + _source = null; + } + + public override void _Ready() + { + Events.EventBus.Instance.EnterShop += (string path) => + { + var shop = ResourceLoader.Load(path); + GD.Print("Loaded shop"); + Source = shop; + }; + } +}