RealtimeStyleTransferRuntime/Source/LyraGame/Equipment/LyraEquipmentManagerCompone...

279 lines
7.6 KiB
C++
Raw Permalink Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LyraEquipmentManagerComponent.h"
2022-09-13 07:18:28 +00:00
#include "AbilitySystem/LyraAbilitySet.h"
2022-05-23 18:41:30 +00:00
#include "AbilitySystem/LyraAbilitySystemComponent.h"
2022-09-13 07:18:28 +00:00
#include "AbilitySystemComponent.h"
2022-05-23 18:41:30 +00:00
#include "AbilitySystemGlobals.h"
2022-09-13 07:18:28 +00:00
#include "Components/ActorComponent.h"
#include "Engine/ActorChannel.h"
#include "GameFramework/Actor.h"
2022-05-23 18:41:30 +00:00
#include "LyraEquipmentDefinition.h"
2022-09-13 07:18:28 +00:00
#include "LyraEquipmentInstance.h"
#include "Misc/AssertionMacros.h"
2022-05-23 18:41:30 +00:00
#include "Net/UnrealNetwork.h"
2022-09-13 07:18:28 +00:00
#include "Templates/Casts.h"
#include "UObject/Object.h"
#include "UObject/ObjectPtr.h"
#include "UObject/UObjectBaseUtility.h"
class FLifetimeProperty;
struct FReplicationFlags;
2022-05-23 18:41:30 +00:00
//////////////////////////////////////////////////////////////////////
// FLyraAppliedEquipmentEntry
FString FLyraAppliedEquipmentEntry::GetDebugString() const
{
return FString::Printf(TEXT("%s of %s"), *GetNameSafe(Instance), *GetNameSafe(EquipmentDefinition.Get()));
}
//////////////////////////////////////////////////////////////////////
// FLyraEquipmentList
void FLyraEquipmentList::PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize)
{
for (int32 Index : RemovedIndices)
{
const FLyraAppliedEquipmentEntry& Entry = Entries[Index];
if (Entry.Instance != nullptr)
{
Entry.Instance->OnUnequipped();
}
}
}
void FLyraEquipmentList::PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize)
{
for (int32 Index : AddedIndices)
{
const FLyraAppliedEquipmentEntry& Entry = Entries[Index];
if (Entry.Instance != nullptr)
{
Entry.Instance->OnEquipped();
}
}
}
void FLyraEquipmentList::PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize)
{
// for (int32 Index : ChangedIndices)
// {
// const FGameplayTagStack& Stack = Stacks[Index];
// TagToCountMap[Stack.Tag] = Stack.StackCount;
// }
}
ULyraAbilitySystemComponent* FLyraEquipmentList::GetAbilitySystemComponent() const
{
check(OwnerComponent);
AActor* OwningActor = OwnerComponent->GetOwner();
return Cast<ULyraAbilitySystemComponent>(UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(OwningActor));
}
ULyraEquipmentInstance* FLyraEquipmentList::AddEntry(TSubclassOf<ULyraEquipmentDefinition> EquipmentDefinition)
{
ULyraEquipmentInstance* Result = nullptr;
check(EquipmentDefinition != nullptr);
check(OwnerComponent);
check(OwnerComponent->GetOwner()->HasAuthority());
const ULyraEquipmentDefinition* EquipmentCDO = GetDefault<ULyraEquipmentDefinition>(EquipmentDefinition);
TSubclassOf<ULyraEquipmentInstance> InstanceType = EquipmentCDO->InstanceType;
if (InstanceType == nullptr)
{
InstanceType = ULyraEquipmentInstance::StaticClass();
}
FLyraAppliedEquipmentEntry& NewEntry = Entries.AddDefaulted_GetRef();
NewEntry.EquipmentDefinition = EquipmentDefinition;
NewEntry.Instance = NewObject<ULyraEquipmentInstance>(OwnerComponent->GetOwner(), InstanceType); //@TODO: Using the actor instead of component as the outer due to UE-127172
Result = NewEntry.Instance;
if (ULyraAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
for (TObjectPtr<const ULyraAbilitySet> AbilitySet : EquipmentCDO->AbilitySetsToGrant)
{
AbilitySet->GiveToAbilitySystem(ASC, /*inout*/ &NewEntry.GrantedHandles, Result);
}
}
else
{
//@TODO: Warning logging?
}
Result->SpawnEquipmentActors(EquipmentCDO->ActorsToSpawn);
MarkItemDirty(NewEntry);
return Result;
}
void FLyraEquipmentList::RemoveEntry(ULyraEquipmentInstance* Instance)
{
for (auto EntryIt = Entries.CreateIterator(); EntryIt; ++EntryIt)
{
FLyraAppliedEquipmentEntry& Entry = *EntryIt;
if (Entry.Instance == Instance)
{
if (ULyraAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
Entry.GrantedHandles.TakeFromAbilitySystem(ASC);
}
Instance->DestroyEquipmentActors();
EntryIt.RemoveCurrent();
MarkArrayDirty();
}
}
}
//////////////////////////////////////////////////////////////////////
// ULyraEquipmentManagerComponent
ULyraEquipmentManagerComponent::ULyraEquipmentManagerComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, EquipmentList(this)
{
SetIsReplicatedByDefault(true);
bWantsInitializeComponent = true;
}
void ULyraEquipmentManagerComponent::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ThisClass, EquipmentList);
}
ULyraEquipmentInstance* ULyraEquipmentManagerComponent::EquipItem(TSubclassOf<ULyraEquipmentDefinition> EquipmentClass)
{
ULyraEquipmentInstance* Result = nullptr;
if (EquipmentClass != nullptr)
{
Result = EquipmentList.AddEntry(EquipmentClass);
if (Result != nullptr)
{
Result->OnEquipped();
2022-09-13 07:18:28 +00:00
if (IsUsingRegisteredSubObjectList() && IsReadyForReplication())
{
AddReplicatedSubObject(Result);
}
2022-05-23 18:41:30 +00:00
}
}
return Result;
}
void ULyraEquipmentManagerComponent::UnequipItem(ULyraEquipmentInstance* ItemInstance)
{
if (ItemInstance != nullptr)
{
2022-09-13 07:18:28 +00:00
if (IsUsingRegisteredSubObjectList())
{
RemoveReplicatedSubObject(ItemInstance);
}
2022-05-23 18:41:30 +00:00
ItemInstance->OnUnequipped();
EquipmentList.RemoveEntry(ItemInstance);
}
}
bool ULyraEquipmentManagerComponent::ReplicateSubobjects(UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
for (FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries)
{
ULyraEquipmentInstance* Instance = Entry.Instance;
if (IsValid(Instance))
{
WroteSomething |= Channel->ReplicateSubobject(Instance, *Bunch, *RepFlags);
}
}
return WroteSomething;
}
void ULyraEquipmentManagerComponent::InitializeComponent()
{
Super::InitializeComponent();
}
void ULyraEquipmentManagerComponent::UninitializeComponent()
{
TArray<ULyraEquipmentInstance*> AllEquipmentInstances;
// gathering all instances before removal to avoid side effects affecting the equipment list iterator
for (const FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries)
{
AllEquipmentInstances.Add(Entry.Instance);
}
for (ULyraEquipmentInstance* EquipInstance : AllEquipmentInstances)
{
UnequipItem(EquipInstance);
}
Super::UninitializeComponent();
}
2022-09-13 07:18:28 +00:00
void ULyraEquipmentManagerComponent::ReadyForReplication()
{
Super::ReadyForReplication();
// Register existing LyraEquipmentInstances
if (IsUsingRegisteredSubObjectList())
{
for (const FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries)
{
ULyraEquipmentInstance* Instance = Entry.Instance;
if (IsValid(Instance))
{
AddReplicatedSubObject(Instance);
}
}
}
}
2022-05-23 18:41:30 +00:00
ULyraEquipmentInstance* ULyraEquipmentManagerComponent::GetFirstInstanceOfType(TSubclassOf<ULyraEquipmentInstance> InstanceType)
{
for (FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries)
{
if (ULyraEquipmentInstance* Instance = Entry.Instance)
{
if (Instance->IsA(InstanceType))
{
return Instance;
}
}
}
return nullptr;
}
TArray<ULyraEquipmentInstance*> ULyraEquipmentManagerComponent::GetEquipmentInstancesOfType(TSubclassOf<ULyraEquipmentInstance> InstanceType) const
{
TArray<ULyraEquipmentInstance*> Results;
for (const FLyraAppliedEquipmentEntry& Entry : EquipmentList.Entries)
{
if (ULyraEquipmentInstance* Instance = Entry.Instance)
{
if (Instance->IsA(InstanceType))
{
Results.Add(Instance);
}
}
}
return Results;
}