126 lines
3.7 KiB
C++
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;
|
|
}
|