227 lines
6.1 KiB
C++
227 lines
6.1 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
||
|
||
#include "Components/InventoryComponent.h"
|
||
#include "Math/UnrealMathUtility.h"
|
||
|
||
UInventoryComponent::UInventoryComponent() : Capacity(20) {
|
||
}
|
||
|
||
bool UInventoryComponent::DepositItems(int32 ItemID, int32 ItemCnt) {
|
||
int32 RemainItemCnt = ItemCnt;
|
||
|
||
if (ItemCnt <= 0) {
|
||
return true;
|
||
}
|
||
|
||
if (!IsCanContain(ItemID, ItemCnt)) {
|
||
return false;
|
||
}
|
||
|
||
while (RemainItemCnt > 0) {
|
||
FInventoryGrid& Grid = GetOrCreateGrid(ItemID);
|
||
int32 GridRemainCapacity = Grid.MaxCount - Grid.CurrentCount;
|
||
int32 AddCount = FMath::Min(RemainItemCnt, GridRemainCapacity);
|
||
|
||
Grid.CurrentCount += AddCount;
|
||
RemainItemCnt -= AddCount;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD>䶯<EFBFBD>¼<EFBFBD>
|
||
OnInventoryChanged.Broadcast(ItemID);
|
||
return true;
|
||
}
|
||
|
||
bool UInventoryComponent::WithdrawItems(int32 ItemID, int32 ItemCnt) {
|
||
if (ItemCnt <= 0) {
|
||
return true;
|
||
}
|
||
|
||
if (!IsEnough(ItemID, ItemCnt)) {
|
||
return false;
|
||
}
|
||
|
||
int32 RemainToWithdraw = ItemCnt;
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仯<EFBFBD><E4BBAF><EFBFBD>⣩
|
||
for (int32 i = InventoryList.Num() - 1; i >= 0 && RemainToWithdraw > 0; --i) {
|
||
FInventoryGrid& Grid = InventoryList[i];
|
||
if (Grid.ItemID == ItemID) {
|
||
int32 RemoveCount = FMath::Min(RemainToWithdraw, Grid.CurrentCount);
|
||
Grid.CurrentCount -= RemoveCount;
|
||
RemainToWithdraw -= RemoveCount;
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD>䶯<EFBFBD>¼<EFBFBD>
|
||
OnInventoryChanged.Broadcast(ItemID);
|
||
return true;
|
||
}
|
||
|
||
bool UInventoryComponent::ConsumeItems(int32 Index, int32 ItemCnt) {
|
||
if (ItemCnt <= 0) {
|
||
return true;
|
||
}
|
||
|
||
if (!InventoryList.IsValidIndex(Index)) {
|
||
return false;
|
||
}
|
||
|
||
FInventoryGrid& SpecifiedGrid = InventoryList[Index];
|
||
int32 ItemID = SpecifiedGrid.ItemID;
|
||
|
||
if (!IsEnough(ItemID, ItemCnt)) {
|
||
return false;
|
||
}
|
||
|
||
// <20>ȿ۳<C8BF>ָ<EFBFBD><D6B8>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>Ʒ
|
||
int32 RemoveFromSpecified = FMath::Min(ItemCnt, SpecifiedGrid.CurrentCount);
|
||
SpecifiedGrid.CurrentCount -= RemoveFromSpecified;
|
||
int32 RemainToConsume = ItemCnt - RemoveFromSpecified;
|
||
|
||
// <20>ٿ۳<D9BF><DBB3><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>Ʒ
|
||
if (RemainToConsume > 0) {
|
||
for (int32 i = InventoryList.Num() - 1; i >= 0 && RemainToConsume > 0; --i) {
|
||
if (i == Index) continue; // <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD><D1B4><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>λ<EFBFBD><CEBB>
|
||
|
||
FInventoryGrid& Grid = InventoryList[i];
|
||
if (Grid.ItemID == ItemID) {
|
||
int32 RemoveCount = FMath::Min(RemainToConsume, Grid.CurrentCount);
|
||
Grid.CurrentCount -= RemoveCount;
|
||
RemainToConsume -= RemoveCount;
|
||
}
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD>䶯<EFBFBD>¼<EFBFBD>
|
||
OnInventoryChanged.Broadcast(ItemID);
|
||
return true;
|
||
}
|
||
|
||
void UInventoryComponent::SetInventoryCapacity(int MaxCapacity) {
|
||
int32 NewCapacity = FMath::Max(0, MaxCapacity);
|
||
if (Capacity != NewCapacity) {
|
||
Capacity = NewCapacity;
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仯<EFBFBD>¼<EFBFBD>
|
||
OnInventoryCapacityChanged.Broadcast();
|
||
}
|
||
}
|
||
|
||
void UInventoryComponent::ReSortAllItem() {
|
||
// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>Ϊ0<CEAA>ĸ<EFBFBD><C4B8><EFBFBD>
|
||
for (int32 i = InventoryList.Num() - 1; i >= 0; --i) {
|
||
if (InventoryList[i].CurrentCount <= 0) {
|
||
InventoryList.RemoveAt(i);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
InventoryList.Sort([](const FInventoryGrid& A, const FInventoryGrid& B) {
|
||
return A.Priority > B.Priority; // <20><><EFBFBD>ȼ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ǰ
|
||
});
|
||
}
|
||
|
||
bool UInventoryComponent::IsCanContain(int32 ItemID, int32 Count) {
|
||
if (Count <= 0) return true;
|
||
|
||
int32 EmptySlotCount= 0;
|
||
int32 ExistingSpace = 0;
|
||
int32 ExistingGrids = 0;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пռ<D0BF>
|
||
for (const FInventoryGrid& Grid : InventoryList) {
|
||
if (Grid.ItemID == ItemID) {
|
||
ExistingSpace += (Grid.MaxCount - Grid.CurrentCount);
|
||
ExistingGrids++;
|
||
}else if (Grid.ItemID == 0 || Grid.CurrentCount == 0) {
|
||
EmptySlotCount++;
|
||
}
|
||
}
|
||
|
||
if (ExistingSpace >= Count) {
|
||
return true;
|
||
}
|
||
|
||
int32 NeededSpace = Count - ExistingSpace;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD><C2B8>ӿ<EFBFBD><D3BF>ÿռ<C3BF>
|
||
int32 AvailableGridSlots = Capacity - InventoryList.Num() + EmptySlotCount;
|
||
if (AvailableGridSlots <= 0) {
|
||
return false;
|
||
}
|
||
|
||
// <20><>ȡ<EFBFBD><C8A1>ƷĬ<C6B7>϶ѵ<CFB6><D1B5><EFBFBD>С
|
||
FInventoryGrid TempGrid;
|
||
TempGrid.ItemID = ItemID;
|
||
InitItemGrid(TempGrid);
|
||
|
||
int32 NewGridSpace = AvailableGridSlots * TempGrid.MaxCount;
|
||
return (ExistingSpace + NewGridSpace) >= Count;
|
||
}
|
||
|
||
bool UInventoryComponent::IsEnough(int32 ItemID, int32 Count) {
|
||
if (Count <= 0) return true;
|
||
|
||
int32 Total = 0;
|
||
for (const FInventoryGrid& Grid : InventoryList) {
|
||
if (Grid.ItemID == ItemID) {
|
||
Total += Grid.CurrentCount;
|
||
}
|
||
}
|
||
return Total >= Count;
|
||
}
|
||
|
||
FInventoryGrid UInventoryComponent::GetGridWithIndex(int32 Index) {
|
||
return InventoryList.IsValidIndex(Index) ? InventoryList[Index] : FInventoryGrid();
|
||
}
|
||
|
||
void UInventoryComponent::InitItemGrid_Implementation(FInventoryGrid& Grid) {
|
||
Grid.CurrentCount = 0;
|
||
Grid.MaxCount = 20; // Ĭ<>϶ѵ<CFB6><D1B5><EFBFBD>С
|
||
Grid.Priority = 1; // Ĭ<><C4AC><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
|
||
}
|
||
|
||
void UInventoryComponent::ForEach(const FVisitInventoryGridDelegate& VisitDelegate) {
|
||
for (int32 i = 0; i < InventoryList.Num(); ++i) {
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD><C6B7>CurrentCount <= 0<><30>
|
||
if (InventoryList[i].CurrentCount > 0) {
|
||
VisitDelegate.ExecuteIfBound(i, InventoryList[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
FInventoryGrid& UInventoryComponent::GetOrCreateGrid(int32 ItemID) {
|
||
// <20><><EFBFBD>ҷ<EFBFBD><D2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD>
|
||
for (FInventoryGrid& Grid : InventoryList) {
|
||
if (Grid.ItemID == 0 || Grid.CurrentCount == 0) {
|
||
Grid.ItemID = ItemID;
|
||
InitItemGrid(Grid);
|
||
return Grid;
|
||
}
|
||
if (Grid.ItemID == ItemID && Grid.CurrentCount < Grid.MaxCount) {
|
||
return Grid;
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (InventoryList.Num() >= Capacity) {
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>账<EFBFBD><E8B4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飩
|
||
static FInventoryGrid DummyGrid;
|
||
DummyGrid = FInventoryGrid();
|
||
InitItemGrid(DummyGrid);
|
||
DummyGrid.ItemID = ItemID;
|
||
return DummyGrid;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD><C2B8><EFBFBD>
|
||
FInventoryGrid NewGrid;
|
||
NewGrid.ItemID = ItemID;
|
||
InitItemGrid(NewGrid);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>뵽<EFBFBD><EBB5BD>ȷλ<C8B7><CEBB>
|
||
int32 InsertIndex = 0;
|
||
for (; InsertIndex < InventoryList.Num(); InsertIndex++) {
|
||
if (NewGrid.Priority > InventoryList[InsertIndex].Priority) {
|
||
break;
|
||
}
|
||
}
|
||
return InventoryList.Insert_GetRef(NewGrid, InsertIndex);
|
||
} |