279 lines
7.6 KiB
C++
279 lines
7.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LyraEquipmentManagerComponent.h"
|
|
|
|
#include "AbilitySystem/LyraAbilitySet.h"
|
|
#include "AbilitySystem/LyraAbilitySystemComponent.h"
|
|
#include "AbilitySystemComponent.h"
|
|
#include "AbilitySystemGlobals.h"
|
|
#include "Components/ActorComponent.h"
|
|
#include "Engine/ActorChannel.h"
|
|
#include "GameFramework/Actor.h"
|
|
#include "LyraEquipmentDefinition.h"
|
|
#include "LyraEquipmentInstance.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "Net/UnrealNetwork.h"
|
|
#include "Templates/Casts.h"
|
|
#include "UObject/Object.h"
|
|
#include "UObject/ObjectPtr.h"
|
|
#include "UObject/UObjectBaseUtility.h"
|
|
|
|
class FLifetimeProperty;
|
|
struct FReplicationFlags;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// 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();
|
|
|
|
if (IsUsingRegisteredSubObjectList() && IsReadyForReplication())
|
|
{
|
|
AddReplicatedSubObject(Result);
|
|
}
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
void ULyraEquipmentManagerComponent::UnequipItem(ULyraEquipmentInstance* ItemInstance)
|
|
{
|
|
if (ItemInstance != nullptr)
|
|
{
|
|
if (IsUsingRegisteredSubObjectList())
|
|
{
|
|
RemoveReplicatedSubObject(ItemInstance);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|