Files
GameJamDungeon/src/items/Inventory.cs
2024-09-22 14:00:52 -07:00

187 lines
5.9 KiB
C#

using Chickensoft.Collections;
using Chickensoft.GodotNodeInterfaces;
using Godot;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace GameJamDungeon;
public interface IInventory : INode
{
public List<IInventoryItem> Items { get; }
public IAutoProp<Weapon> EquippedWeapon { get; }
public IAutoProp<Armor> EquippedArmor { get; }
public IAutoProp<Accessory> EquippedAccessory { get; }
public bool TryAdd(IInventoryItem inventoryItem);
public void Remove(IInventoryItem inventoryItem);
public void Equip(IEquipableItem equipable);
public void Unequip(IEquipableItem equipable);
public bool IsEquipped(IEquipableItem equipable);
public void Sort();
event Inventory.InventoryAtCapacityEventHandler InventoryAtCapacity;
event Inventory.AccessoryUnequippedEventHandler AccessoryUnequipped;
event Inventory.RaiseStatRequestEventHandler RaiseStatRequest;
}
public partial class Inventory : Node, IInventory
{
// TODO: Constants class with export
private const int _maxInventorySize = 20;
[Signal]
public delegate void InventoryAtCapacityEventHandler(string rejectedItemName);
[Signal]
public delegate void AccessoryUnequippedEventHandler(AccessoryStats unequippedAccessory);
[Signal]
public delegate void RaiseStatRequestEventHandler(ConsumableItemStats consumableItemStats);
public Inventory()
{
Items = [];
}
public List<IInventoryItem> Items { get; private set; }
public IAutoProp<Weapon> EquippedWeapon => _equippedWeapon;
private AutoProp<Weapon> _equippedWeapon { get; set; } = new AutoProp<Weapon>(new Weapon());
public IAutoProp<Armor> EquippedArmor => _equippedArmor;
private AutoProp<Armor> _equippedArmor { get; set; } = new AutoProp<Armor>(new Armor());
public IAutoProp<Accessory> EquippedAccessory => _equippedAccessory;
private AutoProp<Accessory> _equippedAccessory { get; set; } = new AutoProp<Accessory>(new Accessory());
public bool TryAdd(IInventoryItem inventoryItem)
{
if (Items.Count >= _maxInventorySize)
{
EmitSignal(SignalName.InventoryAtCapacity, inventoryItem.Info.Name);
return false;
}
Items.Add(inventoryItem);
return true;
}
public void Remove(IInventoryItem inventoryItem) => Items.Remove(inventoryItem);
public void Equip(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
_equippedWeapon.OnNext(weapon);
else if (equipable is Armor armor)
_equippedArmor.OnNext(armor);
else if (equipable is Accessory accessory)
_equippedAccessory.OnNext(accessory);
else
throw new NotImplementedException("Item type is not supported.");
}
public void Unequip(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
{
_equippedWeapon.OnNext(new Weapon());
if (weapon.WeaponStats.WeaponTags.Contains(WeaponTag.BreaksOnChange))
Items.Remove(weapon);
}
else if (equipable is Armor armor)
_equippedArmor.OnNext(new Armor());
else if (equipable is Accessory accessory)
{
EmitSignal(SignalName.AccessoryUnequipped, _equippedAccessory.Value.AccessoryStats);
_equippedAccessory.OnNext(new Accessory());
}
else
throw new NotImplementedException("Item type is not supported.");
}
public bool IsEquipped(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
return _equippedWeapon.Value.Equals(weapon);
else if (equipable is Armor armor)
return _equippedArmor.Value.Equals(armor);
else if (equipable is Accessory accessory)
return _equippedAccessory.Value.Equals(accessory);
else
throw new NotImplementedException("Item type is not supported.");
}
public void Sort()
{
var equippedWeapon = Items.OfType<Weapon>().Where(IsEquipped);
var equippedArmor = Items.OfType<Armor>().Where(IsEquipped);
var equippedAccessory = Items.OfType<Accessory>().Where(IsEquipped);
var equippedItems = new List<IInventoryItem>();
equippedItems.AddRange(equippedWeapon);
equippedItems.AddRange(equippedArmor);
equippedItems.AddRange(equippedAccessory);
var listToSort = Items.Except(equippedItems);
var weapons = listToSort.Where(x => x is Weapon).OrderBy(x => x as Weapon, new WeaponComparer());
var armor = listToSort.Where(x => x is Armor).OrderBy(x => x as Armor, new ArmorComparer());
var accessories = listToSort.Where(x => x is Accessory).OrderBy(x => x as Accessory, new AccessoryComparer());
var consumables = listToSort.Where(x => x is ConsumableItem).OrderBy(x => x as ConsumableItem, new ConsumableComparer());
var throwables = listToSort.Where(x => x is ThrowableItem).OrderBy(x => x as ThrowableItem, new ThrowableComparer());
Items = [.. equippedItems, .. weapons, .. armor, .. accessories, .. consumables, .. throwables];
}
public class WeaponComparer : IComparer<Weapon>
{
public int Compare(Weapon x, Weapon y)
{
if (x.WeaponStats.Damage == y.WeaponStats.Damage)
return x.WeaponStats.Name.CompareTo(y.WeaponStats.Name);
return x.WeaponStats.Damage < y.WeaponStats.Damage ? 1 : -1;
}
}
public class ArmorComparer : IComparer<Armor>
{
public int Compare(Armor x, Armor y)
{
if (x.ArmorStats.Defense == y.ArmorStats.Defense)
return x.ArmorStats.Name.CompareTo(y.ArmorStats.Name);
return x.ArmorStats.Defense < y.ArmorStats.Defense ? 1 : -1;
}
}
public class AccessoryComparer : IComparer<Accessory>
{
public int Compare(Accessory x, Accessory y)
{
return x.AccessoryStats.Name.CompareTo(y.AccessoryStats.Name);
}
}
public class ConsumableComparer : IComparer<ConsumableItem>
{
public int Compare(ConsumableItem x, ConsumableItem y)
{
return x.ConsumableItemInfo.Name.CompareTo(y.ConsumableItemInfo.Name);
}
}
public class ThrowableComparer : IComparer<ThrowableItem>
{
public int Compare(ThrowableItem x, ThrowableItem y)
{
return x.ThrowableItemInfo.Name.CompareTo(y.ThrowableItemInfo.Name);
}
}
}