From 6609476eecaf86bd8b9b1405539bb1a4cf13411d Mon Sep 17 00:00:00 2001
From: PHILIP WHITE <PW259246@falmouth.ac.uk>
Date: Fri, 20 Oct 2023 22:59:54 +0100
Subject: [PATCH] Update Inventory Component for Helper Functions

---
 .../Inventory/InventoryComponent.cpp          | 78 +++++++++++++++++--
 .../Inventory/InventoryComponent.h            | 33 ++++++--
 .../Inventory/InventoryStructs.h              |  4 +-
 3 files changed, 98 insertions(+), 17 deletions(-)

diff --git a/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.cpp b/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.cpp
index 7f48f011..260d4637 100644
--- a/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.cpp
+++ b/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.cpp
@@ -3,6 +3,8 @@
 
 #include "InventoryComponent.h"
 
+#include "BaseItem.h"
+
 
 // Sets default values for this component's properties
 UInventoryComponent::UInventoryComponent()
@@ -21,7 +23,6 @@ void UInventoryComponent::BeginPlay()
 	Super::BeginPlay();
 
 	// ...
-	
 }
 
 
@@ -41,39 +42,100 @@ void UInventoryComponent::LineTraceForItemCheck()
 {
 }
 
-void UInventoryComponent::Pickup(UBaseItem* Item)
+void UInventoryComponent::Pickup()
 {
+	//TODO: Add pickup logic and create pickup Actor
+	if (!IsValid(ItemToPickup)) return;
 }
 
-bool UInventoryComponent::IsRoomAvailable(UBaseItem* Item, int TopLeftIndex)
+bool UInventoryComponent::IsRoomAvailable(UBaseItem* Item, const int TopLeftIndex)
 {
+	for (int i = 0; i < IndexToTile(TopLeftIndex).X + (Item->ItemSize.X - 1); i++)
+	{
+		for (int j = 0; j < IndexToTile(TopLeftIndex).Y + (Item->ItemSize.Y - 1); j++)
+		{
+			FInventoryTile TileToCheck;
+			TileToCheck.X = i;
+			TileToCheck.Y = j;
+			if (!IsTileValid(TileToCheck)) return false;
+			const TTuple<UBaseItem*, bool> ItemAtIndex = GetItemAtIndex(TileToIndex(TileToCheck));
+			if (ItemAtIndex.Get<1>()) return false;
+			if (IsValid(ItemAtIndex.Get<0>())) return false;
+		}
+	}
+	return true;
 }
 
-FVector UInventoryComponent::IndexToTile(int Index)
+FInventoryTile UInventoryComponent::IndexToTile(const int Index) const
 {
+	FInventoryTile Tile;
+	Tile.X = Index % Columns;
+	Tile.Y = Index / Columns;
+	return Tile;
 }
 
-UBaseItem* UInventoryComponent::GetItemAtIndex(int Index)
+TTuple<UBaseItem*, bool> UInventoryComponent::GetItemAtIndex(const int Index)
 {
+	if (!InventoryItems.IsValidIndex(Index)) return std::make_tuple(nullptr, false);
+	return std::make_tuple(InventoryItems[Index], true);
 }
 
-FInventoryTiles UInventoryComponent::TileToIndex(int Index)
+int UInventoryComponent::TileToIndex(const FInventoryTile InventoryTile) const
 {
+	return InventoryTile.X + InventoryTile.Y * Columns;
 }
 
-void UInventoryComponent::AddItemAt(UBaseItem* Item, int TopLeftIndex)
+void UInventoryComponent::AddItemAt(UBaseItem* Item, const int TopLeftIndex)
 {
+	for (int i = 0; i < IndexToTile(TopLeftIndex).X + (Item->ItemSize.X - 1); i++)
+	{
+		for (int j = 0; j < IndexToTile(TopLeftIndex).Y + (Item->ItemSize.Y - 1); j++)
+		{
+			FInventoryTile TileToCheck;
+			TileToCheck.X = i;
+			TileToCheck.Y = j;
+			if (!IsTileValid(TileToCheck)) return;
+			InventoryItems.Insert(Item, TileToIndex(TileToCheck));
+		}
+	}
+	IsDirty = true;
 }
 
-void UInventoryComponent::GetAllItems()
+TMap<UBaseItem*, FInventoryTile> UInventoryComponent::GetAllItems()
 {
+	TMap<UBaseItem*, FInventoryTile> Items;
+	for (int i = 0; i < InventoryItems.Num(); i++)
+	{
+		UBaseItem* Item = InventoryItems[i];
+		if (!IsValid(Item)) continue;
+		if (!Items.Contains(Item)) continue;
+		Items.Add(Item, IndexToTile(i));
+	}
+	return Items;
 }
 
 void UInventoryComponent::RemoveItem(UBaseItem* Item)
 {
+	if (!IsValid(Item)) return;
+	for (int i = 0; i < InventoryItems.Num(); i++)
+	{
+		if (InventoryItems[i] == Item)
+		{
+			InventoryItems.RemoveAt(i);
+			IsDirty = true;
+		}
+	}
 }
 
 void UInventoryComponent::SpawnItem(UBaseItem* Item, FVector Location, FRotator Rotation)
 {
 }
 
+bool UInventoryComponent::IsTileValid(const FInventoryTile InventoryTile) const
+{
+	if (InventoryTile.X >= 0 && InventoryTile.Y >= 0 && InventoryTile.Y < Columns && InventoryTile.Y < Rows)
+	{
+		return true;
+	}
+	return false;
+}
diff --git a/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.h b/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.h
index 0744afb0..8aee354c 100644
--- a/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.h
+++ b/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryComponent.h
@@ -5,6 +5,7 @@
 #include "CoreMinimal.h"
 #include "Components/ActorComponent.h"
 #include "InventoryStructs.h"
+#include "EndlessVendetta/EndlessVendettaCharacter.h"
 #include "InventoryComponent.generated.h"
 
 
@@ -17,6 +18,13 @@ public:
 	// Sets default values for this component's properties
 	UInventoryComponent();
 
+	UPROPERTY(EditDefaultsOnly, BlueprintRead, Category="Inventory")
+	int Columns = 10;
+	UPROPERTY(EditDefaultsOnly, BlueprintRead, Category="Inventory")
+	int Rows = 10;
+	UPROPERTY(EditDefaultsOnly, BlueprintRead, Category="Inventory")
+	float MaxPickupDistance = 200.0f;
+
 protected:
 	// Called when the game starts
 	virtual void BeginPlay() override;
@@ -30,21 +38,32 @@ public:
 	UFUNCTION(BlueprintCallable, Category="Inventory")
 	void LineTraceForItemCheck();
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	void Pickup(class UBaseItem* Item);
+	void Pickup();
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	bool IsRoomAvailable(class UBaseItem* Item, int TopLeftIndex);
+	bool IsRoomAvailable(class UBaseItem* Item, const int TopLeftIndex);
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	FVector IndexToTile(int Index);
+	FInventoryTile IndexToTile(const int Index) const;
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	UBaseItem* GetItemAtIndex(int Index);
+	TTuple<UBaseItem*, bool> GetItemAtIndex(const int Index);
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	FInventoryTiles TileToIndex(int Index);
+	int TileToIndex(const FInventoryTile InventoryTile) const;
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	void AddItemAt(class UBaseItem* Item, int TopLeftIndex);
+	void AddItemAt(class UBaseItem* Item, const int TopLeftIndex);
 	UFUNCTION(BlueprintCallable, Category="Inventory")
-	void GetAllItems();
+	TMap<UBaseItem*, FInventoryTile> GetAllItems();
 	UFUNCTION(BlueprintCallable, Category="Inventory")
 	void RemoveItem(class UBaseItem* Item);
 	UFUNCTION(BlueprintCallable, Category="Inventory")
 	void SpawnItem(class UBaseItem* Item, FVector Location, FRotator Rotation);
+
+private:
+	bool IsTileValid(const FInventoryTile InventoryTile) const;
+	
+	UPROPERTY()
+	AEndlessVendettaCharacter* PlayerCharacter;
+	UPROPERTY()
+	AActor* ItemToPickup;
+	bool IsDirty = false;
+	UPROPERTY()
+	TArray<UBaseItem*> InventoryItems;
 };
diff --git a/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryStructs.h b/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryStructs.h
index a72a3d65..742bae19 100644
--- a/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryStructs.h
+++ b/EndlessVendetta/Source/EndlessVendetta/Inventory/InventoryStructs.h
@@ -10,7 +10,7 @@
  */
 
 USTRUCT(BlueprintType)
-struct FInventoryLines
+struct FInventoryLine
 {
 	GENERATED_BODY()
 
@@ -19,7 +19,7 @@ struct FInventoryLines
 };
 
 USTRUCT(BlueprintType)
-struct FInventoryTiles
+struct FInventoryTile
 {
 	GENERATED_BODY()