using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; using System.Collections.Generic; using System.Linq; using Zennysoft.Game.Ma; using Zennysoft.Ma.Adapter; [Meta(typeof(IAutoNode))] public partial class InventoryMenu : Control, IInventoryMenu { public override void _Notification(int what) => this.Notify(what); [Dependency] private IPlayer _player => this.DependOn(); [Dependency] private IGame _game => this.DependOn(); [Dependency] private IGameRepo _gameRepo => this.DependOn(); [Node] public Label ItemName { get; set; } [Node] public Label ItemType { get; set; } [Node] public Label ItemParameter { get; set; } [Node] public Label ItemFlavor { get; set; } [Node] public Label ItemStats { get; set; } [Node] public Label ItemAugment { get; set; } [Node] public TextureRect ItemAugmentTexture { get; set; } [Node] public ActionPanel ActionPanel { get; set; } [Node] public VBoxContainer Inventory { get; set; } [Node] public Control MenuPanel { get; set; } [Node] public AugmentableItemsMenu AugmentMenu { get; set; } [Node] public Label PlayerATKLabel { get; set; } [Node] public Label PlayerDEFLabel { get; set; } [Node] public Label StatusLabel { get; set; } private List ItemSlots; private IItemSlot _currentlySelected; public void OnResolved() { ItemSlots = [.. Inventory.GetChildren().OfType()]; ItemSlots.ForEach(x => x.ItemPressed += ItemPressed); ItemSlots.ForEach(x => x.ItemSelected += ItemSelected); VisibilityChanged += ResetInventoryState; ActionPanel.ActionPanelClosing += ActionPanel_ActionPanelClosing; ActionPanel.ReturnToGameAction += ActionPanel_ReturnToGameAction; ActionPanel.AugmentMenuRequested += ActionPanel_AugmentMenuRequested; AugmentMenu.AugmentMenuClosing += AugmentMenu_AugmentMenuClosing; _player.EquipmentComponent.EquipmentChanged += EquipmentChanged; _player.AttackComponent.CurrentAttack.Changed += AttackChanged; _player.AttackComponent.MaximumAttack.Changed += AttackChanged; _player.DefenseComponent.CurrentDefense.Changed += DefenseChanged; _player.DefenseComponent.MaximumDefense.Changed += DefenseChanged; ClearDescriptionBox(); AttackChanged(0); DefenseChanged(0); StatusLabel.Text = string.Empty; Hide(); } private void AttackChanged(int obj) => PlayerATKLabel.Text = $"{_player.AttackComponent.CurrentAttack.Value:D2}/{_player.AttackComponent.MaximumAttack.Value:D2}+{_player.EquipmentComponent.BonusAttack}"; private void DefenseChanged(int obj) => PlayerDEFLabel.Text = $"{_player.DefenseComponent.CurrentDefense.Value:D2}/{_player.DefenseComponent.MaximumDefense.Value:D2}+{_player.EquipmentComponent.BonusDefense}"; public override void _Input(InputEvent @event) { var validSelectableItems = _player.Inventory.Items.ToList(); if (Input.IsActionJustPressed(GameInputs.MoveUp) && _currentlySelected != null && _currentlySelected.Item.Value != validSelectableItems.First()) SfxDatabase.Instance.Play(SoundEffect.MoveUI); if (Input.IsActionJustPressed(GameInputs.MoveDown) && _currentlySelected != null && _currentlySelected.Item.Value != validSelectableItems.Last()) SfxDatabase.Instance.Play(SoundEffect.MoveUI); if (Input.IsActionJustPressed(GameInputs.Interact)) SfxDatabase.Instance.Play(SoundEffect.CancelUI); } private void ActionPanel_AugmentMenuRequested() { ReleaseFocus(); ItemSlots.ForEach(x => x.ItemPressed -= ItemPressed); ItemSlots.ForEach(x => x.ItemSelected -= ItemSelected); MenuPanel.Hide(); SetProcessInput(false); AugmentMenu.SetProcessInput(true); AugmentMenu.OpenAugmentMenu(_currentlySelected.Item.Value as IAugmentItem); } private void ActionPanel_ReturnToGameAction() { _gameRepo.CloseInventory(); } private void ItemPressed(IItemSlot selectedItem) { SetProcessInput(false); ActionPanel.SetProcessInput(true); ActionPanel.ShowPanel(selectedItem.Item.Value); ActionPanel.FocusActionPanel(); SfxDatabase.Instance.Play(SoundEffect.SelectUI); } private void ItemSelected(IItemSlot selectedItem) { _currentlySelected = selectedItem; ItemName.Text = selectedItem.Item.Value.ItemName; ItemType.Text = SetItemTypeName(selectedItem.Item.Value); ItemParameter.Text = GetItemParameterText(selectedItem.Item.Value); ItemParameter.Visible = !string.IsNullOrEmpty(ItemParameter.Text); ItemFlavor.Text = selectedItem.Item.Value.FlavorText; ItemFlavor.Visible = !string.IsNullOrEmpty(ItemFlavor.Text); ItemStats.Text = selectedItem.Item.Value.StatDescription; ItemStats.Visible = !string.IsNullOrEmpty(ItemStats.Text); ItemAugmentTexture.Texture = null; ItemAugment.Text = GetAugmentText(selectedItem.Item.Value); } private void ResetInventoryState() { var inventory = _player.Inventory.Items; ItemSlots.ForEach(x => x.SetEmpty()); ClearDescriptionBox(); for (var i = 0; i < inventory.Count; i++) ItemSlots[i].SetItemToSlot(inventory[i]); if (_currentlySelected != null && !inventory.Contains(_currentlySelected.Item.Value)) _currentlySelected = null; if (_currentlySelected == null && inventory.Count > 0) _currentlySelected = ItemSlots.FirstOrDefault(x => x.Item.Value == inventory.First()); if (inventory.Count > 0) _currentlySelected.FocusItem(); ActionPanel.Hide(); } private void ClearDescriptionBox() { ItemName.Text = string.Empty; ItemType.Text = string.Empty; ItemParameter.Text = string.Empty; ItemStats.Text = string.Empty; ItemFlavor.Text = string.Empty; ItemAugment.Text = string.Empty; ItemAugmentTexture.Texture = null; } private void ActionPanel_ActionPanelClosing() { ActionPanel.Hide(); SetProcessInput(true); ActionPanel.SetProcessInput(false); if (_player.Inventory.Items.Any() && !_player.Inventory.Items.Contains(_currentlySelected.Item.Value)) _currentlySelected = null; ResetInventoryState(); } private void AugmentMenu_AugmentMenuClosing() { ItemSlots.ForEach(x => x.ItemPressed += ItemPressed); ItemSlots.ForEach(x => x.ItemSelected += ItemSelected); MenuPanel.Show(); SetProcessInput(true); AugmentMenu.SetProcessInput(false); AugmentMenu.Hide(); ResetInventoryState(); } private void EquipmentChanged(IEquipableItem obj) { AttackChanged(0); DefenseChanged(0); } private static string GetItemParameterText(IBaseInventoryItem item) { if (item is Weapon potentiallyProjectile && (potentiallyProjectile.WeaponTag == WeaponTag.KineticProjectile || potentiallyProjectile.WeaponTag == WeaponTag.ElementalProjectile)) return string.Empty; return item switch { Weapon weapon => $"ATK: {(weapon.ItemTag == ItemTag.MysteryItem ? "???" : weapon.BonusAttack)}", Armor armor => $"DEF: {(armor.ItemTag == ItemTag.MysteryItem ? "???" : armor.BonusDefense)}", _ => string.Empty, }; } private string GetAugmentText(IBaseInventoryItem item) { if (item is IAugmentableItem augmentable && augmentable.Augment != null) { ItemAugmentTexture.Texture = augmentable.Augment.AugmentTexture; return $"{augmentable.Augment.AugmentName}{System.Environment.NewLine}{augmentable.Augment.AugmentDescription}"; } return string.Empty; } private static string SetItemTypeName(IBaseInventoryItem item) { return item switch { Weapon => "Weapon", Armor => "Armor", Accessory => "Mask", Ammo => "Ammo", BoxItem => "Box", ConsumableItem => "Restorative", EffectItem => "Spell", Jewel => "Jewel", Plastique => "Explosive", ThrowableItem => "Dice", _ => "Unknown item type.", }; } }