Files
GameJamDungeon/Zennysoft.Game.Ma/src/ui/inventory_menu/InventoryMenu.cs
Zenny a686ce2fbc Switch navigation mesh to be based on collision only, not collision and texture meshes
Will need to finetune enemy navigation agent placement depending on if they're now too high/low to sit in the navigation region
2026-02-25 22:33:38 -08:00

230 lines
7.7 KiB
C#

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<IPlayer>();
[Dependency] private IGame _game => this.DependOn<IGame>();
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>();
[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<IItemSlot> ItemSlots;
private IItemSlot _currentlySelected;
public void OnResolved()
{
ItemSlots = [.. Inventory.GetChildren().OfType<IItemSlot>()];
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.",
};
}
}