You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
4.7 KiB
160 lines
4.7 KiB
#nullable enable
|
|
using System;
|
|
using Godot;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Babushka.scripts.CSharp.Common.Inventory;
|
|
|
|
public partial class InventoryInstance : Node
|
|
{
|
|
private List<InventorySlot> _slots = new();
|
|
public IReadOnlyList<InventorySlot> Slots => _slots;
|
|
|
|
[Signal]
|
|
public delegate void SlotAmountChangedEventHandler();
|
|
|
|
[Signal]
|
|
public delegate void InventoryContentsChangedEventHandler();
|
|
|
|
/// <summary>
|
|
/// The total amount of Inventoryslots in the inventory (empty and occupied).
|
|
/// </summary>
|
|
[Export]
|
|
public int SlotAmount
|
|
{
|
|
get => _slots.Count;
|
|
set
|
|
{
|
|
if (value < _slots.Count)
|
|
{
|
|
_slots.RemoveRange(value, _slots.Count - value);
|
|
}
|
|
else if (value > _slots.Count)
|
|
{
|
|
for (var i = _slots.Count; i < value; i++)
|
|
{
|
|
_slots.Add(new InventorySlot());
|
|
}
|
|
}
|
|
|
|
EmitSignal(SignalName.SlotAmountChanged);
|
|
}
|
|
}
|
|
|
|
public InventoryActionResult AddItem(ItemInstance newItem)
|
|
{
|
|
var result = AddItemAndStackRecursive(newItem, 0);
|
|
EmitSignal(SignalName.InventoryContentsChanged);
|
|
return result;
|
|
}
|
|
|
|
private InventoryActionResult AddItemAndStackRecursive(ItemInstance newItem, int slotSearch)
|
|
{
|
|
if (newItem.blueprint == null || newItem.amount == 0)
|
|
return InventoryActionResult.SourceDoesNotExist;
|
|
|
|
var slotIndex = -1;
|
|
// find stackable slot
|
|
for (var i = slotSearch; i < _slots.Count; i++)
|
|
{
|
|
if (_slots[i].itemInstance?.blueprint == newItem.blueprint)
|
|
{
|
|
slotIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (slotIndex < 0)
|
|
{
|
|
// find empty slot
|
|
for (var i = slotSearch; i < _slots.Count; i++)
|
|
{
|
|
if (_slots[i].IsEmpty())
|
|
{
|
|
slotIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (slotIndex < 0)
|
|
{
|
|
return InventoryActionResult.DestinationFull;
|
|
}
|
|
|
|
var itemInstance = _slots[slotIndex].itemInstance ?? new ItemInstance { blueprint = newItem.blueprint, amount = 0 };
|
|
var maxStack = itemInstance!.blueprint.maxStack;
|
|
var freeOnStack = maxStack - itemInstance.amount;
|
|
var moveAmount = Math.Min(freeOnStack, newItem.amount);
|
|
itemInstance.amount += moveAmount;
|
|
newItem.amount -= moveAmount;
|
|
_slots[slotIndex].itemInstance = itemInstance;
|
|
return newItem.amount <= 0
|
|
? InventoryActionResult.Success
|
|
: AddItemAndStackRecursive(newItem, slotIndex + 1);
|
|
}
|
|
|
|
public InventoryActionResult RemoveItem(int inventorySlot, out ItemInstance? itemInstance)
|
|
{
|
|
if (inventorySlot < 0 || inventorySlot >= _slots.Count)
|
|
{
|
|
itemInstance = null;
|
|
return InventoryActionResult.SourceDoesNotExist;
|
|
}
|
|
|
|
if (_slots[inventorySlot].IsEmpty())
|
|
{
|
|
itemInstance = null;
|
|
return InventoryActionResult.SourceIsEmpty;
|
|
}
|
|
|
|
itemInstance = _slots[inventorySlot].itemInstance;
|
|
if (itemInstance == null)
|
|
return InventoryActionResult.SourceDoesNotExist;
|
|
|
|
itemInstance.amount -= 1;
|
|
|
|
if(itemInstance.amount == 0)
|
|
_slots[inventorySlot].itemInstance = null;
|
|
|
|
EmitSignal(SignalName.InventoryContentsChanged);
|
|
return InventoryActionResult.Success;
|
|
}
|
|
|
|
public InventoryActionResult RemoveItem(int inventorySlot)
|
|
{
|
|
return RemoveItem(inventorySlot, out _);
|
|
}
|
|
|
|
public InventoryActionResult AddItemToSlot(ItemInstance itemInstance, int destinationSlot)
|
|
{
|
|
if (destinationSlot < 0 || destinationSlot >= _slots.Count)
|
|
return InventoryActionResult.DestinationDoesNotExist;
|
|
|
|
if (!_slots[destinationSlot].IsEmpty())
|
|
return InventoryActionResult.DestinationFull;
|
|
|
|
_slots[destinationSlot].itemInstance = itemInstance;
|
|
EmitSignal(SignalName.InventoryContentsChanged);
|
|
return InventoryActionResult.Success;
|
|
}
|
|
|
|
public int TotalItemsOfBlueprint(ItemResource blueprint)
|
|
{
|
|
return _slots
|
|
.Where(i => !i.IsEmpty() && i.itemInstance!.blueprint == blueprint)
|
|
.Sum(i => i.itemInstance!.amount);
|
|
}
|
|
|
|
public bool HasItems(ItemInstance item)
|
|
{
|
|
return TotalItemsOfBlueprint(item.blueprint) >= item.amount;
|
|
}
|
|
|
|
public bool HasItems(IEnumerable<ItemInstance> items)
|
|
{
|
|
return items.All(HasItems);
|
|
}
|
|
}
|