第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -0,0 +1,350 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Abilities/GGA_AbilitySet.h"
#include "Abilities/GameplayAbility.h"
#include "Runtime/Launch/Resources/Version.h"
#include "AbilitySystemComponent.h"
#include "Utilities/GGA_AbilitySystemFunctionLibrary.h"
DEFINE_LOG_CATEGORY(LogGGA_AbilitySet)
#include UE_INLINE_GENERATED_CPP_BY_NAME(GGA_AbilitySet)
void FGGA_AbilitySet_GrantedHandles::AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& Handle)
{
if (Handle.IsValid())
{
AbilitySpecHandles.Add(Handle);
}
}
void FGGA_AbilitySet_GrantedHandles::AddGameplayEffectHandle(const FActiveGameplayEffectHandle& Handle)
{
if (Handle.IsValid())
{
GameplayEffectHandles.Add(Handle);
}
}
void FGGA_AbilitySet_GrantedHandles::AddAttributeSet(UAttributeSet* Set)
{
GrantedAttributeSets.Add(Set);
}
void FGGA_AbilitySet_GrantedHandles::TakeFromAbilitySystem(UAbilitySystemComponent* ASC)
{
check(ASC);
if (!ASC->IsOwnerActorAuthoritative())
{
// Must be authoritative to give or take ability sets.
return;
}
for (const FGameplayAbilitySpecHandle& Handle : AbilitySpecHandles)
{
if (Handle.IsValid())
{
ASC->ClearAbility(Handle);
}
}
for (const FActiveGameplayEffectHandle& Handle : GameplayEffectHandles)
{
if (Handle.IsValid())
{
ASC->RemoveActiveGameplayEffect(Handle);
}
}
for (UAttributeSet* Set : GrantedAttributeSets)
{
ASC->RemoveSpawnedAttribute(Set);
}
AbilitySpecHandles.Reset();
GameplayEffectHandles.Reset();
GrantedAttributeSets.Reset();
}
UGGA_AbilitySet::UGGA_AbilitySet(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UGGA_AbilitySet::GiveToAbilitySystem(UAbilitySystemComponent* ASC, FGGA_AbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject, int32 OverrideLevel) const
{
check(ASC);
if (!ASC->IsOwnerActorAuthoritative())
{
// Must be authoritative to give or take ability sets.
return;
}
// Grant the attribute sets.
for (int32 SetIndex = 0; SetIndex < GrantedAttributes.Num(); ++SetIndex)
{
const FGGA_AbilitySet_AttributeSet& SetToGrant = GrantedAttributes[SetIndex];
const TSubclassOf<UAttributeSet> AttributeSetClass = SetToGrant.AttributeSet.LoadSynchronous();
if (!AttributeSetClass)
{
UE_LOG(LogGGA_AbilitySet, Error, TEXT("GrantedAttributes[%d] on ability set [%s]: AttributeSet is not valid"), SetIndex, *GetNameSafe(this));
continue;
}
if (UAttributeSet* ExistingOne = UGGA_AbilitySystemFunctionLibrary::GetAttributeSetByClass(ASC, AttributeSetClass))
{
UE_LOG(LogGGA_AbilitySet, Error, TEXT("GrantedAttributes[%d] on ability set [%s]: AttributeSet already exists."), SetIndex, *GetNameSafe(this));
continue;
}
#if WITH_EDITORONLY_DATA
if (!SetToGrant.bAttributeSetEnabled)
{
UE_LOG(LogGGA_AbilitySet, Display, TEXT( "GrantedAttributes[%d] on ability set [%s]:skipped for debugging."), SetIndex, *GetNameSafe(this));
continue;
}
#endif
UAttributeSet* NewSet = NewObject<UAttributeSet>(ASC->GetOwner(), AttributeSetClass);
ASC->AddAttributeSetSubobject(NewSet);
if (OutGrantedHandles)
{
OutGrantedHandles->AddAttributeSet(NewSet);
}
}
// Grant the gameplay abilities.
for (int32 AbilityIndex = 0; AbilityIndex < GrantedGameplayAbilities.Num(); ++AbilityIndex)
{
const FGGA_AbilitySet_GameplayAbility& AbilityToGrant = GrantedGameplayAbilities[AbilityIndex];
const TSubclassOf<UGameplayAbility> AbilityClass = AbilityToGrant.Ability.LoadSynchronous();
if (!AbilityClass)
{
UE_LOG(LogGGA_AbilitySet, Error, TEXT("GrantedGameplayAbilities[%d] on ability set [%s]: Ability class is not valid."), AbilityIndex, *GetNameSafe(this));
continue;
}
#if WITH_EDITORONLY_DATA
if (!AbilityToGrant.bAbilityEnabled)
{
UE_LOG(LogGGA_AbilitySet, Display, TEXT( "GrantedGameplayAbilities[%d] on ability set [%s]: Skipped for debugging."), AbilityIndex, *GetNameSafe(this));
continue;
}
#endif
UGameplayAbility* AbilityCDO = AbilityClass->GetDefaultObject<UGameplayAbility>();
FGameplayAbilitySpec AbilitySpec(AbilityCDO, OverrideLevel > 0 ? OverrideLevel : AbilityToGrant.AbilityLevel);
AbilitySpec.SourceObject = SourceObject;
if (AbilityToGrant.InputID > 0)
{
AbilitySpec.InputID = AbilityToGrant.InputID;
}
if (!AbilityToGrant.DynamicTags.IsEmpty())
{
#if ENGINE_MINOR_VERSION > 4
AbilitySpec.GetDynamicSpecSourceTags().AppendTags(AbilityToGrant.DynamicTags);
#else
AbilitySpec.DynamicAbilityTags.AppendTags(AbilityToGrant.DynamicTags);
#endif
}
const FGameplayAbilitySpecHandle AbilitySpecHandle = ASC->GiveAbility(AbilitySpec);
if (OutGrantedHandles)
{
OutGrantedHandles->AddAbilitySpecHandle(AbilitySpecHandle);
}
}
// Grant the gameplay effects.
for (int32 EffectIndex = 0; EffectIndex < GrantedGameplayEffects.Num(); ++EffectIndex)
{
const FGGA_AbilitySet_GameplayEffect& EffectToGrant = GrantedGameplayEffects[EffectIndex];
const TSubclassOf<UGameplayEffect> EffectClass = EffectToGrant.GameplayEffect.LoadSynchronous();
if (!EffectClass)
{
UE_LOG(LogGGA_AbilitySet, Error, TEXT("GrantedGameplayEffects[%d] on ability set [%s]:Effect Class is not valid"), EffectIndex, *GetNameSafe(this));
continue;
}
#if WITH_EDITORONLY_DATA
if (!EffectToGrant.bEffectEnabled)
{
UE_LOG(LogGGA_AbilitySet, Display, TEXT( "GrantedGameplayEffects[%d] on ability set [%s]:Skipped for debugging."), EffectIndex, *GetNameSafe(this));
continue;
}
#endif
const UGameplayEffect* GameplayEffectCDO = EffectClass->GetDefaultObject<UGameplayEffect>();
const FActiveGameplayEffectHandle GameplayEffectHandle = ASC->
ApplyGameplayEffectToSelf(GameplayEffectCDO, OverrideLevel > 0 ? OverrideLevel : EffectToGrant.EffectLevel, ASC->MakeEffectContext());
if (OutGrantedHandles)
{
OutGrantedHandles->AddGameplayEffectHandle(GameplayEffectHandle);
if (GameplayEffectCDO->DurationPolicy == EGameplayEffectDurationType::Infinite && !GameplayEffectHandle.IsValid())
{
UE_LOG(LogGGA_AbilitySet, Warning, TEXT("Granted Infinite GameplayEffects[%d] on ability set [%s] failed to apply"), EffectIndex, *GetNameSafe(this));
}
}
}
}
FGGA_AbilitySet_GrantedHandles UGGA_AbilitySet::GiveAbilitySetToAbilitySystem(TSoftObjectPtr<UGGA_AbilitySet> AbilitySet, UAbilitySystemComponent* ASC, UObject* SourceObject, int32 OverrideLevel)
{
FGGA_AbilitySet_GrantedHandles GrantedHandles;
if (IsValid(ASC) && !AbilitySet.IsNull())
{
if (!AbilitySet.IsValid())
{
AbilitySet.LoadSynchronous();
}
AbilitySet->GiveToAbilitySystem(ASC, &GrantedHandles, SourceObject, OverrideLevel);
}
return GrantedHandles;
}
TArray<FGGA_AbilitySet_GrantedHandles> UGGA_AbilitySet::GiveAbilitySetsToAbilitySystem(TArray<TSoftObjectPtr<UGGA_AbilitySet>> AbilitySets, UAbilitySystemComponent* ASC, UObject* SourceObject,
int32 OverrideLevel)
{
TArray<FGGA_AbilitySet_GrantedHandles> Handles;
for (auto& AbilitySet : AbilitySets)
{
Handles.Add(GiveAbilitySetToAbilitySystem(AbilitySet, ASC, SourceObject, OverrideLevel));
}
return Handles;
}
void UGGA_AbilitySet::TakeAbilitySetFromAbilitySystem(FGGA_AbilitySet_GrantedHandles& GrantedHandles, UAbilitySystemComponent* ASC)
{
if (IsValid(ASC))
{
GrantedHandles.TakeFromAbilitySystem(ASC);
}
}
void UGGA_AbilitySet::TakeAbilitySetsFromAbilitySystem(TArray<FGGA_AbilitySet_GrantedHandles>& GrantedHandles, UAbilitySystemComponent* ASC)
{
if (IsValid(ASC))
{
for (FGGA_AbilitySet_GrantedHandles& Handle : GrantedHandles)
{
Handle.TakeFromAbilitySystem(ASC);
}
}
}
#if WITH_EDITOR
#include "UObject/ObjectSaveContext.h"
void FGGA_AbilitySet_GameplayAbility::MakeEditorFriendlyName()
{
EditorFriendlyName = "Empty Ability";
if (!Ability.IsNull())
{
if (TSubclassOf<UGameplayAbility> Loaded = Ability.LoadSynchronous())
{
EditorFriendlyName = Loaded->GetDisplayNameText().ToString();
}
}
}
void FGGA_AbilitySet_GameplayEffect::MakeEditorFriendlyName()
{
EditorFriendlyName = "Empty Effect";
if (!GameplayEffect.IsNull())
{
if (TSubclassOf<UGameplayEffect> Loaded = GameplayEffect.LoadSynchronous())
{
EditorFriendlyName = Loaded->GetDisplayNameText().ToString();
}
}
}
void FGGA_AbilitySet_AttributeSet::MakeEditorFriendlyName()
{
EditorFriendlyName = "Empty Attribute Set";
if (!AttributeSet.IsNull())
{
if (TSubclassOf<UAttributeSet> Loaded = AttributeSet.LoadSynchronous())
{
EditorFriendlyName = Loaded->GetDisplayNameText().ToString();
}
}
}
void UGGA_AbilitySet::PreSave(FObjectPreSaveContext SaveContext)
{
Super::PreSave(SaveContext);
if (!IsRunningCommandlet())
{
for (auto& Ability : GrantedGameplayAbilities)
{
Ability.MakeEditorFriendlyName();
}
for (auto& Effect : GrantedGameplayEffects)
{
Effect.MakeEditorFriendlyName();
}
for (auto& Attribute : GrantedAttributes)
{
Attribute.MakeEditorFriendlyName();
}
}
}
void UGGA_AbilitySet::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
}
void UGGA_AbilitySet::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
{
FName MemberName = PropertyChangedEvent.PropertyChain.GetActiveMemberNode()->GetValue()->GetFName();
if (PropertyChangedEvent.GetPropertyName() == TEXT("Ability") && MemberName == GET_MEMBER_NAME_CHECKED(UGGA_AbilitySet, GrantedGameplayAbilities))
{
const int32 Index = PropertyChangedEvent.GetArrayIndex(GET_MEMBER_NAME_CHECKED(UGGA_AbilitySet, GrantedGameplayAbilities).ToString());
if (Index != INDEX_NONE)
{
GrantedGameplayAbilities[Index].MakeEditorFriendlyName();
}
}
if (PropertyChangedEvent.GetPropertyName() == TEXT("GameplayEffect") && MemberName == GET_MEMBER_NAME_CHECKED(UGGA_AbilitySet, GrantedGameplayEffects))
{
const int32 Index = PropertyChangedEvent.GetArrayIndex(GET_MEMBER_NAME_CHECKED(UGGA_AbilitySet, GrantedGameplayEffects).ToString());
if (Index != INDEX_NONE)
{
GrantedGameplayEffects[Index].MakeEditorFriendlyName();
}
}
if (PropertyChangedEvent.GetPropertyName() == TEXT("AttributeSet") && MemberName == GET_MEMBER_NAME_CHECKED(UGGA_AbilitySet, GrantedAttributes))
{
const int32 Index = PropertyChangedEvent.GetArrayIndex(GET_MEMBER_NAME_CHECKED(UGGA_AbilitySet, GrantedGameplayEffects).ToString());
if (Index != INDEX_NONE)
{
GrantedAttributes[Index].MakeEditorFriendlyName();
}
}
Super::PostEditChangeChainProperty(PropertyChangedEvent);
}
#endif