Merge branch 'Inventory-System' into dev

# Conflicts:
#	EndlessVendetta/Content/AI/Enemy/Basic/BT_BasicEnemy.uasset
#	EndlessVendetta/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset
#	EndlessVendetta/Content/FirstPerson/Input/IMC_Default.uasset
This commit is contained in:
Rafal Swierczek 2023-10-23 11:34:54 +01:00
commit 0ff4d76e00
18 changed files with 477 additions and 5 deletions

BIN
EndlessVendetta/Content/FirstPerson/Blueprints/BP_PC.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
EndlessVendetta/Content/Inventory/M_Base.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/Inventory/MyBaseItem.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/Inventory/UI_Inventory.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/Inventory/UI_InventoryGrid.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/Inventory/UI_ItemWidget.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/Inventory/zeldamus.uasset (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -10,7 +10,8 @@
"LoadingPhase": "Default", "LoadingPhase": "Default",
"AdditionalDependencies": [ "AdditionalDependencies": [
"Engine", "Engine",
"AIModule" "AIModule",
"CoreUObject"
] ]
} }
], ],

View File

@ -0,0 +1,29 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "BaseItem.h"
void UBaseItem::RotateItem()
{
if (CurrentItemRotation == Horizontal)
{
CurrentItemRotation = Vertical;
ItemSize = FItemSize(ItemSize.Y, ItemSize.X);
bIsRotated = true;
}
else
{
CurrentItemRotation = Horizontal;
ItemSize = FItemSize(ItemSize.Y, ItemSize.X);
bIsRotated = false;
}
}
UMaterialInterface* UBaseItem::GetItemTexture() const
{
if (bIsRotated)
{
return ItemTextureRotated;
}
return ItemTexture;
}

View File

@ -0,0 +1,70 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.generated.h"
USTRUCT(BlueprintType)
struct FItemSize
{
GENERATED_BODY()
UPROPERTY(BlueprintReadOnly, Category = "ItemSize")
int X;
UPROPERTY(BlueprintReadOnly, Category = "ItemSize")
int Y;
FItemSize(const int _X, const int _Y)
{
X = _X;
Y = _Y;
}
FItemSize()
{
X = 1;
Y = 1;
}
};
UENUM(BlueprintType)
enum EItemRotation
{
Horizontal UMETA(DisplayName = "Horizontal"),
Vertical UMETA(DisplayName = "Vertical")
};
/**
*
*/
UCLASS(Abstract, Blueprintable)
class ENDLESSVENDETTA_API UBaseItem : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
int ItemID;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
FName ItemName;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
FText Description;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
FItemSize ItemSize = FItemSize();
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
UMaterialInterface* ItemTexture;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
UMaterialInterface* ItemTextureRotated;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
TEnumAsByte<EItemRotation> CurrentItemRotation = Horizontal;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
TSubclassOf<AActor> ItemActor;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Item")
bool bIsRotated = false;
UFUNCTION(BlueprintCallable, Category = "Item")
void RotateItem();
UFUNCTION(BlueprintCallable, Category = "Item")
UMaterialInterface* GetItemTexture() const;
};

View File

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "BaseWorldItem.h"
// Sets default values
ABaseWorldItem::ABaseWorldItem()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ABaseWorldItem::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ABaseWorldItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}

View File

@ -0,0 +1,25 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BaseWorldItem.generated.h"
UCLASS()
class ENDLESSVENDETTA_API ABaseWorldItem : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ABaseWorldItem();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};

View File

@ -0,0 +1,190 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "InventoryComponent.h"
#include "BaseItem.h"
#include "Camera/CameraComponent.h"
// Sets default values for this component's properties
UInventoryComponent::UInventoryComponent()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
bWantsInitializeComponent = true;
PrimaryComponentTick.bCanEverTick = true;
}
void UInventoryComponent::InitializeComponent()
{
Super::InitializeComponent();
PlayerCharacter = Cast<AEndlessVendettaCharacter>(GetOwner());
ItemToPickup = nullptr;
}
// Called when the game starts
void UInventoryComponent::BeginPlay()
{
Super::BeginPlay();
//FTimerHandle TraceTimerHandle;
//GetWorld()->GetTimerManager().SetTimer(TraceTimerHandle, this, &UInventoryComponent::ProjectTraceForItem, 0.1f, true);
InventoryItems.Init(nullptr, Columns * Rows);
}
// Called every frame
void UInventoryComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (IsDirty)
{
IsDirty = false;
OnInventoryUpdated.Broadcast();
}
}
bool UInventoryComponent::AddItem(UBaseItem* Item)
{
if (!IsValid(Item)) return false;
for (int i = 0; i < InventoryItems.Num(); i++)
{
if (IsRoomAvailable(Item, i))
{
AddItemAt(Item, i);
return true;
}
}
Item->RotateItem();
for (int i = 0; i < InventoryItems.Num(); i++)
{
if (IsRoomAvailable(Item, i))
{
AddItemAt(Item, i);
return true;
}
}
Item->RotateItem();
return false;
}
void UInventoryComponent::ProjectTraceForItem()
{
if (!IsValid(PlayerCharacter)) return;
FVector StartLocation = Cast<UCameraComponent>(PlayerCharacter->GetComponentByClass(UCameraComponent::StaticClass()))->GetComponentLocation();
FVector EndLocation = StartLocation + Cast<UCameraComponent>(PlayerCharacter->GetComponentByClass(UCameraComponent::StaticClass()))->GetForwardVector() * MaxPickupDistance;
FCollisionQueryParams CollisionQueryParams;
CollisionQueryParams.AddIgnoredActor(PlayerCharacter);
if (FHitResult HitResult; GetWorld()->LineTraceSingleByChannel(HitResult, StartLocation, EndLocation, ECC_Visibility, CollisionQueryParams))
{
if (Cast<UBaseItem>(HitResult.GetActor()))
{
ItemToPickup = HitResult.GetActor();
Cast<UStaticMeshComponent>(ItemToPickup->GetComponentByClass(UStaticMeshComponent::StaticClass()))->SetRenderCustomDepth(true);
return;
}
}
if (!IsValid(ItemToPickup)) return;
Cast<UStaticMeshComponent>(ItemToPickup->GetComponentByClass(UStaticMeshComponent::StaticClass()))->SetRenderCustomDepth(false);
}
void UInventoryComponent::Pickup()
{
//TODO: Add pickup logic and create pickup Actor
if (!IsValid(ItemToPickup)) return;
}
bool UInventoryComponent::IsRoomAvailable(UBaseItem* Item, const int TopLeftIndex)
{
for (int i = IndexToTile(TopLeftIndex).X; i < IndexToTile(TopLeftIndex).X + Item->ItemSize.X; i++)
{
for (int j = IndexToTile(TopLeftIndex).Y; j < IndexToTile(TopLeftIndex).Y + Item->ItemSize.Y; 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 true;
}
}
return true;
}
FInventoryTile UInventoryComponent::IndexToTile(const int Index) const
{
FInventoryTile Tile;
Tile.X = Index % Columns;
Tile.Y = Index / Columns;
return Tile;
}
TTuple<UBaseItem*, bool> UInventoryComponent::GetItemAtIndex(const int Index)
{
if (!InventoryItems.IsValidIndex(Index)) return MakeTuple(nullptr, false);
return MakeTuple(InventoryItems[Index], true);
}
int UInventoryComponent::TileToIndex(const FInventoryTile InventoryTile) const
{
return InventoryTile.X + InventoryTile.Y * Columns;
}
void UInventoryComponent::AddItemAt(UBaseItem* Item, const int TopLeftIndex)
{
for (int i = IndexToTile(TopLeftIndex).X; i < IndexToTile(TopLeftIndex).X + Item->ItemSize.X; i++)
{
for (int j = IndexToTile(TopLeftIndex).Y; j < IndexToTile(TopLeftIndex).Y + Item->ItemSize.Y; j++)
{
FInventoryTile TileToCheck;
TileToCheck.X = i;
TileToCheck.Y = j;
if (!IsTileValid(TileToCheck)) return;
InventoryItems.Insert(Item, TileToIndex(TileToCheck));
}
}
IsDirty = true;
}
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;
}

View File

@ -0,0 +1,75 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "InventoryStructs.h"
#include "EndlessVendetta/EndlessVendettaCharacter.h"
#include "InventoryComponent.generated.h"
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class ENDLESSVENDETTA_API UInventoryComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UInventoryComponent();
virtual void InitializeComponent() override;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Inventory")
int Columns = 10;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Inventory")
int Rows = 10;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Inventory")
float MaxPickupDistance = 200.0f;
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnInventoryUpdated);
UPROPERTY(BlueprintAssignable, Category="Inventory")
FOnInventoryUpdated OnInventoryUpdated;
UFUNCTION(BlueprintCallable, Category="Inventory")
bool AddItem(class UBaseItem* Item);
UFUNCTION(BlueprintCallable, Category="Inventory")
void ProjectTraceForItem();
UFUNCTION(BlueprintCallable, Category="Inventory")
void Pickup();
UFUNCTION(BlueprintCallable, Category="Inventory")
bool IsRoomAvailable(class UBaseItem* Item, const int TopLeftIndex);
UFUNCTION(BlueprintCallable, Category="Inventory")
FInventoryTile IndexToTile(const int Index) const;
//UFUNCTION(BlueprintCallable, Category="Inventory")
TTuple<UBaseItem*, bool> GetItemAtIndex(const int Index);
UFUNCTION(BlueprintCallable, Category="Inventory")
int TileToIndex(const FInventoryTile InventoryTile) const;
UFUNCTION(BlueprintCallable, Category="Inventory")
void AddItemAt(class UBaseItem* Item, const int TopLeftIndex);
UFUNCTION(BlueprintCallable, Category="Inventory")
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;
};

View File

@ -0,0 +1,32 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "InventoryStructs.generated.h"
/**
*
*/
USTRUCT(BlueprintType)
struct FInventoryLine
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite)
FVector2D Start;
UPROPERTY(BlueprintReadWrite)
FVector2D End;
};
USTRUCT(BlueprintType)
struct FInventoryTile
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite)
int X;
UPROPERTY(BlueprintReadWrite)
int Y;
};