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);
 | ||
| } |