haxis/Source/UnrealProject/Items/ItemBase.cpp

126 lines
3.7 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "ItemBase.h"
#include "BaseSkillObject.h"
#include "CharacterBase.h"
// Sets default values
AItemBase::AItemBase()
{
// Create a mesh subcomponent without collision.
Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
RootComponent = Mesh;
Mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
void AItemBase::CreateItemsFromSkill(UWorld* world, class UBaseSkillObject* skillObject, class ACharacterBase* character)
{
// Check if passed arguments are valid.
if (world && skillObject && character)
{
for (size_t i = 0; i < skillObject->visibleItems.itemsToEquip.Num(); i++)
{
if (!skillObject->visibleItems.itemsToEquip[i].mesh)
{
TERROR("Skill item does not have a mesh attached to it!");
continue;
}
// Get the Skeletal Mesh of the character.
USkeletalMeshComponent* charMesh = character->GetMesh();
// Check if the socket has already been taken by another item.
bool hasBeenTaken = false;
for (auto SceneComp : charMesh->AttachChildren)
{
AItemBase* item = Cast<AItemBase>(SceneComp->GetOwner());
if (item)
{
if (item->type == skillObject->visibleItems.itemsToEquip[i].type)
{
hasBeenTaken = true;
break;
}
}
}
if (!hasBeenTaken)
{
// Spawn a new item.
AItemBase* createdItem = Cast<AItemBase>(world->SpawnActor(StaticClass()));
// Set the item with the correct settings and mesh.
createdItem->type = skillObject->visibleItems.itemsToEquip[i].type;
createdItem->SetMesh(skillObject->visibleItems.itemsToEquip[i].mesh);
createdItem->skillObject = skillObject;
createdItem->AttachItemToCharacter(character);
}
}
return;
}
TERROR("Either world (" + world + "), skillObject (" + skillObject + ") or character (" + character + ") passed to AItemBase::CreateItemFromSkill was a nullptr.");
}
AItemBase* AItemBase::CheckSlotOccupied(EItemTypeEnum slotType, class ACharacterBase* character)
{
// Check if passed arguments are valid.
if(character)
{
UWorld* world = character->GetWorld();
// Get the Skeletal Mesh of the character.
USkeletalMeshComponent* charMesh = character->GetMesh();
// Check if the socket has already been taken by another item.
bool hasBeenTaken = false;
for(auto SceneComp : charMesh->AttachChildren)
{
AItemBase* item = Cast<AItemBase>(SceneComp->GetOwner());
if (item)
{
if(item->type == slotType)
return item;
}
}
}
return nullptr;
}
void AItemBase::Destroyed()
{
ACharacterBase* attachedParent = Cast<ACharacterBase>(this->GetAttachParentActor());
if(IsValid(attachedParent))
{
attachedParent->m_OnItemRemoved(this);
}
Super::Destroyed();
}
void AItemBase::SetMesh(USkeletalMesh* newMesh)
{
Mesh->SetSkeletalMesh(newMesh);
}
bool AItemBase::AttachItemToCharacter(class ACharacterBase* networkCharacter)
{
// Variable used to retrieve names of the EItemTypeEnum values.
const static UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EItemTypeEnum"), true);
// Retrieve the name of the type the item was assigned to. This is to attach the item to a socket.
FName socketName = FName(*EnumPtr->GetEnumName((int32)type));
// Get the Skeletal Mesh of the character.
USkeletalMeshComponent* charMesh = networkCharacter->GetMesh();
// Check if the socket actually exists.
if(!charMesh->DoesSocketExist(socketName))
{
return false;
}
// Attach the item to the socket.
RootComponent->AttachTo(charMesh, NAME_None, EAttachLocation::SnapToTargetIncludingScale);
Mesh->SetMasterPoseComponent(charMesh);
// Notify character
networkCharacter->m_OnItemAdded(this);
return true;
}