Trouble Returning Classes

So well, Overall im trying to create a RPG-Like Item System where the player can pick up an physical item in the world and its saved into his “inventory” thats nothing more than an array

So i have my item class extending Actor and i declared the inventory array in my character class like this

	UPROPERTY(EditAnywhere, Category = Inventory)
		TArray<class AProojectItem*> ItemInventory;

To add an item into my player inventory i have an " Item Database", a bueprint where i link all the items trough an array

DB.h

#pragma once

#include "Object.h"
#include "ProojectItem.h"
#include "DB.generated.h"



/**
 * 
 */
UCLASS(Blueprintable)
class UDB : public UObject
{
	GENERATED_UCLASS_BODY()

	// All items
	UPROPERTY(EditDefaultsOnly, Category = Database)
	TArray<AProojectItem*>  ItemClasses;

	AProojectItem GetItem(FString ItemName);	
};

DB.cpp

#include "Prooject.h"
#include "ProojectItem.h"
#include "DB.h"


UDB::UDB(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{

}


AProojectItem UDB::GetItem(FString ItemName)
{
	 for (int TriIdx = 0; ItemClasses.Num(); TriIdx++)
	{
		 if (ItemClasses[TriIdx]->ItemName == ItemName)
		 {
			 return ItemClasses[TriIdx];

		 }
	}

}

What i have so far is that when the player tries to pickup an item, it traces against said item if its an AProojectItem ( base item class ) then it gets its itemName and calls the DB GetItem function with the item, ItemName

Here is the function from my character cpp

void AProojectCharacter::GiveItem(FString ItemName)
{
             AProojectItem* ItemToGive;
		AProojectGameMode* MyGamemode = Cast<AProojectGameMode>(GetWorld()->GetAuthGameMode());
		ItemToGive = MyGamemode->GameDB->GetItem(ItemName);
             ItemInventory.Add(ItemToGive);
}

But when compiling i get

*error C2664: ‘AProojectItem::AProojectItem(const AProojectItem &)’ : cannot convert argument 1 from 'AProojectItem ’ to ‘const FPostConstructInitializeProperties &’

So in short
Once a item is “picked up” my character gets the instance to the Item DB Class, “should” get the item based in the provided ItemName
and finally add the return item to the inventory array for later use

UDB::GetItem is returning by value rather than by pointer.

Ah i see Thanks!; tho that revealed another issue if i use

  UPROPERTY(EditDefaultsOnly, Category = Database)
    TArray<AProojectItem*>  ItemClasses;

On my DB.h i can only add the Items in the scene to its array , so instead i changed it to

	UPROPERTY(EditDefaultsOnly, Category = Database)
	TArray<TSubclassOf<class AProojectItem> > ItemClasses;

Which lets me link the items from the content browser to the array, But since im having a array of subclass instead i cant straight away access the itemname like

AProojectItem* UDB::GetItem(FString ItemName)
{
	
        for (int TriIdx = 0; ItemClasses.Num(); TriIdx++)
	{
		 if (ItemClasses[TriIdx]->ItemName == ItemName)
		 {
			 
			 return ItemClasses[TriIdx];
			 break;
		 }

	}
	 return NULL;
	
}

Is there anyway to somehow typecast a pointer of AProojectItem to the class so i can access its info and return it?
I know i can just Spawn the class and return a pointer to the spawned actor but im trying to stay away from Spawning anything

Unfortunately you’re essentially storing UClass* when using TSubclassOf.

You could potentially use the CDO of the class type, but I have no idea if this would work well, or be at all safe:

const AProjectItem* UDB::GetItem(FString ItemName)
{
	for(auto& ItemClass : ItemClasses)
	{
		const AProjectItem* const DefaultInstance = ItemClass.GetDefaultObject();
		if (DefaultInstance->ItemName == ItemName)
		{
			return DefaultInstance;
		}
	}

	return nullptr;
}

But I’d question why your inventory information needs to be an actor, rather than a simpler UObject or USTRUCT type? You could probably get away with just store an array of meta-data about the items, and only spawn the actors if you knew for sure you’d need them?

Thats a point , well right now im sort of stumped on what direction i should head on with the item system

I initially Just created blueprints of my items and on its graph i linked some helper functions from c++ (OnItemUsed, OnItemDropped ) etc So rather than create all the functionality per item in code i could just extend it on the item blueprint

The issue was that, once i picked a item, added it to the inventory and destroyed the physical version the blueprint would sort of “deactivate” And no matter what it wouldnt be active again, i was told that i should just hide the Visible/Graphical components instead of destroy but what if i have lets say 500 items in my scene?, i would end up with 500 non-visible but still there blueprints of different items

It’s an interesting problem, and I’d love to help more, but I’m not terribly familiar with best practices for UE4 gameplay programming.

Perhaps this question would be more suited to the forums? I’m sure if you post your requirements there people will be happy to discuss various approaches with you :slight_smile: