Hey,
So I have been trying to get my Equip Item for inventory functionality working. As far as I know the code is correct, but for some reason, when I equip the item the location gets set to 0,0,0 and the target socket is none…
A quick overview:
I have an Item class with all the things you want your item to have and it’s made to be blueprint driven, so it has things like mesh, item instance, item state, root scene component, sphere component etc. and then I have an Item static data class, which is a custom class used to store the items actor information, and what socket it’s supposed to connect to.
This is the code for processing an equipped item, in Item Actor.cpp:
void AItemActor::OnEquipped()
{
ItemState = EItemState::Equipped;
SphereComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
SphereComponent->SetGenerateOverlapEvents(false);
// Make sure the item is visible to the player
//SetActorHiddenInGame(false);
// Get the name of the socket that the item attached to and print it to the screen
GEngine->AddOnScreenDebugMessage(-1, 20.f, FColor::Green, FString::Printf(TEXT("(AItemActor::OnEquipped())EQUIPPED ItemActor attached to socket: %s"), *GetAttachParentSocketName().ToString()));
// UEngine print to screen the location of the item mesh
GEngine->AddOnScreenDebugMessage(-1, 20.f, FColor::Green, FString::Printf(TEXT("(AItemActor::OnEquipped())EQUIPPED ItemActor location after attachment: %s"), *GetActorLocation().ToString()));
}
This part handles overlap events:
void AItemActor::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// Check if the current item actor has authority (e.g., it is running on the server)
if (HasAuthority())
{
// Create a new FGameplayEventData structure for the payload of the gameplay event
FGameplayEventData EventPayload;
// Set the instigator of the event as the current item actor
EventPayload.Instigator = this;
// Set the optional object of the event as the ItemInstance of the current item actor
EventPayload.OptionalObject = ItemInstance;
// Set the event tag as the EquipItemActorTag, which may be used to identify the event type
EventPayload.EventTag = UInventoryComponent::EquipItemActorTag;
// Send the gameplay event with the EquipItemActorTag and the event payload to the overlapping actor (OtherActor)
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(OtherActor, UInventoryComponent::EquipItemActorTag, EventPayload);
}
}
I have these 3 on my Inventory component:
void UInventoryComponent::EquipItem(TSubclassOf<UItemStaticData> InItemStaticDataClass)
{
if (GetOwner()->HasAuthority())
{
for (const auto Item : InventoryList.GetItemsRef())
{
if (Item.ItemInstance->ItemStaticDataClass == InItemStaticDataClass)
{
Item.ItemInstance->OnEquipped(GetOwner());
CurrentItem = Item.ItemInstance;
break;
}
}
}
}
void UInventoryComponent::EquipItemInstance(UInventoryItemInstance* InItemInstance)
{
if (GetOwner()->HasAuthority())
{
for (const auto Item : InventoryList.GetItemsRef())
{
if (Item.ItemInstance == InItemInstance)
{
Item.ItemInstance->OnEquipped(GetOwner());
CurrentItem = Item.ItemInstance;
break;
}
}
}
}
void UInventoryComponent::EquipNext()
{
TArray<FInventoryListItem>& Items = InventoryList.GetItemsRef();
const bool bNoItems = Items.Num() == 0;
const bool bOneAndEquipped = Items.Num() == 1 && CurrentItem;
if(bNoItems || bOneAndEquipped) return;
UInventoryItemInstance* TargetItem = CurrentItem;
for (const auto Item : Items)
{
if (Item.ItemInstance->GetItemStaticData()->bCanBeEquipped)
{
if (Item.ItemInstance != CurrentItem)
{
TargetItem = Item.ItemInstance;
break;
}
}
}
if (CurrentItem)
{
if (TargetItem == CurrentItem)
{
return;
}
UnequipItem();
}
EquipItemInstance(TargetItem);
}
and this does the actual equipping:
void UInventoryItemInstance::OnEquipped(AActor* InOwner)
{
if (UWorld* World = InOwner->GetWorld())
{
const UItemStaticData* StaticData = GetItemStaticData();
FTransform Transform;
ItemActor = World->SpawnActorDeferred<AItemActor>(StaticData->ItemActorClass, Transform, InOwner);
ItemActor->Init(this);
ItemActor->OnEquipped();
ItemActor->FinishSpawning(Transform);
ACharacter* Character = Cast<ACharacter>(InOwner);
if (USkeletalMeshComponent* SkeletalMesh = Character ? Character->GetMesh() : nullptr)
{
ItemActor->AttachToComponent(SkeletalMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, StaticData->AttachmentSocket);
}
}
bEquipped = true;
}
Any assistance would be much appreciated, if more info is required you can find my git repo here:
