// Copyright 2025 https://yuewu.dev/en All Rights Reserved. #include "GGA_GameplayAttributesHelper.h" #include "AbilitySystemBlueprintLibrary.h" #include "UObject/UObjectIterator.h" #include "AbilitySystemComponent.h" #include "AbilitySystemGlobals.h" TMap UGGA_GameplayAttributesHelper::TagToAttributeMapping = {}; TMap UGGA_GameplayAttributesHelper::AttributeToTagMapping = {}; const TArray& UGGA_GameplayAttributesHelper::GetAllGameplayAttributes() { static TArray Attributes = FindGameplayAttributes(); return Attributes; } TArray UGGA_GameplayAttributesHelper::FindGameplayAttributes() { TArray Attributes; for (TObjectIterator ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (Class->IsChildOf(UAttributeSet::StaticClass())/*&& !Class->ClassGeneratedBy*/) { for (TFieldIterator PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt) { FProperty* Property = *PropertyIt; Attributes.Add(FGameplayAttribute(Property)); } } } return Attributes; } void UGGA_GameplayAttributesHelper::RegisterTagToAttribute(FGameplayTag Tag, FGameplayAttribute Attribute) { if (Tag.IsValid() && Attribute.IsValid()) { if (!TagToAttributeMapping.Contains(Tag) && !AttributeToTagMapping.Contains(Attribute)) { TagToAttributeMapping.Emplace(Tag, Attribute); AttributeToTagMapping.Emplace(Attribute, Tag); } } } void UGGA_GameplayAttributesHelper::UnregisterTagToAttribute(FGameplayTag Tag, FGameplayAttribute Attribute) { if (Tag.IsValid() && Attribute.IsValid()) { if (TagToAttributeMapping.Contains(Tag) && AttributeToTagMapping.Contains(Attribute)) { TagToAttributeMapping.Remove(Tag); AttributeToTagMapping.Remove(Attribute); } } } FGameplayAttribute UGGA_GameplayAttributesHelper::TagToAttribute(FGameplayTag Tag) { return Tag.IsValid() && TagToAttributeMapping.Contains(Tag) ? TagToAttributeMapping[Tag] : FGameplayAttribute(); } TArray UGGA_GameplayAttributesHelper::TagsToAttributes(TArray Tags) { TArray Attributes; for (int32 i = 0; i < Tags.Num(); i++) { if (TagToAttributeMapping.Contains(Tags[i])) { Attributes.Add(TagToAttributeMapping[Tags[i]]); } } return Attributes; } FGameplayTag UGGA_GameplayAttributesHelper::AttributeToTag(FGameplayAttribute Attribute) { if (Attribute.IsValid()) { if (AttributeToTagMapping.Contains(Attribute)) { return AttributeToTagMapping[Attribute]; } } return FGameplayTag::EmptyTag; } TArray UGGA_GameplayAttributesHelper::AttributesToTags(TArray Attributes) { TArray Tags; for (int32 i = 0; i < Attributes.Num(); i++) { if (AttributeToTagMapping.Contains(Attributes[i])) { Tags.Add(AttributeToTagMapping[Attributes[i]]); } } return Tags; } bool UGGA_GameplayAttributesHelper::IsTagOfAttribute(FGameplayTag Tag, FGameplayAttribute Attribute) { if (Tag.IsValid() && Attribute.IsValid()) { if (TagToAttributeMapping.Contains(Tag)) { return TagToAttributeMapping[Tag] == Attribute; } } return false; } bool UGGA_GameplayAttributesHelper::IsAttributeOfTag(FGameplayAttribute Attribute, FGameplayTag Tag) { if (Tag.IsValid() && Attribute.IsValid()) { if (AttributeToTagMapping.Contains(Attribute)) { return AttributeToTagMapping[Attribute] == Tag; } } return false; } void UGGA_GameplayAttributesHelper::SetFloatAttribute(const AActor* Actor, FGameplayAttribute Attribute, float NewValue) { if (UAbilitySystemComponent* Asc = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Actor)) { Asc->SetNumericAttributeBase(Attribute, NewValue); } } void UGGA_GameplayAttributesHelper::SetFloatAttributeOnAbilitySystemComponent(UAbilitySystemComponent* AbilitySystem, FGameplayAttribute Attribute, float NewValue) { if (IsValid(AbilitySystem)) { AbilitySystem->SetNumericAttributeBase(Attribute, NewValue); } } float UGGA_GameplayAttributesHelper::GetFloatAttributePercentage(const AActor* Actor, FGameplayTag AttributeTagOne, FGameplayTag AttributeTagTwo, bool& bSuccessfullyFoundAttribute) { bool bFoundOne = true; bool bFoundTwo = true; float One = GetFloatAttribute(Actor, AttributeTagOne, bFoundOne); float Two = GetFloatAttribute(Actor, AttributeTagTwo, bFoundTwo); bSuccessfullyFoundAttribute = bFoundOne && bFoundTwo; if (!bFoundOne || !bFoundTwo || Two == 0) { return 0; } return One / Two; } float UGGA_GameplayAttributesHelper::GetFloatAttributePercentage_Native(const AActor* Actor, FGameplayAttribute AttributeOne, FGameplayAttribute AttributeTwo, bool& bSuccessfullyFoundAttribute) { bool bFoundOne = true; bool bFoundTwo = true; float One = UAbilitySystemBlueprintLibrary::GetFloatAttribute(Actor, AttributeOne, bFoundOne); float Two = UAbilitySystemBlueprintLibrary::GetFloatAttribute(Actor, AttributeTwo, bFoundTwo); bSuccessfullyFoundAttribute = bFoundOne && bFoundTwo; if (!bFoundOne || !bFoundTwo || Two == 0) { return 0; } return One / Two; } float UGGA_GameplayAttributesHelper::GetFloatAttribute(const AActor* Actor, FGameplayTag AttributeTag, bool& bSuccessfullyFoundAttribute) { return UAbilitySystemBlueprintLibrary::GetFloatAttribute(Actor, TagToAttribute(AttributeTag), bSuccessfullyFoundAttribute); } float UGGA_GameplayAttributesHelper::GetFloatAttributeBase(const AActor* Actor, FGameplayTag AttributeTag, bool& bSuccessfullyFoundAttribute) { return UAbilitySystemBlueprintLibrary::GetFloatAttributeBase(Actor, TagToAttribute(AttributeTag), bSuccessfullyFoundAttribute); } float UGGA_GameplayAttributesHelper::GetFloatAttributeFromAbilitySystemComponent(const UAbilitySystemComponent* AbilitySystem, FGameplayTag AttributeTag, bool& bSuccessfullyFoundAttribute) { return UAbilitySystemBlueprintLibrary::GetFloatAttributeFromAbilitySystemComponent(AbilitySystem, TagToAttribute(AttributeTag), bSuccessfullyFoundAttribute); } float UGGA_GameplayAttributesHelper::GetFloatAttributeBaseFromAbilitySystemComponent(const UAbilitySystemComponent* AbilitySystem, FGameplayTag AttributeTag, bool& bSuccessfullyFoundAttribute) { return UAbilitySystemBlueprintLibrary::GetFloatAttributeBaseFromAbilitySystemComponent(AbilitySystem, TagToAttribute(AttributeTag), bSuccessfullyFoundAttribute); } FString UGGA_GameplayAttributesHelper::GetDebugString() { FString Output; Output.Append(TEXT("TagToAttributeMapping:\r")); for (auto& Pair : TagToAttributeMapping) { Output.Append(FString::Format(TEXT("Tag:{0}->Attribute:{1} \r"), {Pair.Key.ToString(), Pair.Value.AttributeName})); } return Output; } FGameplayAttribute UGGA_GameplayAttributesHelper::GetAttributeFromEvaluatedData(const FGameplayModifierEvaluatedData& EvaluatedData) { return EvaluatedData.Attribute; } EGameplayModOp::Type UGGA_GameplayAttributesHelper::GetModifierOpFromEvaluatedData(const FGameplayModifierEvaluatedData& EvaluatedData) { return EvaluatedData.ModifierOp; } float UGGA_GameplayAttributesHelper::GetMagnitudeFromEvaluatedData(const FGameplayModifierEvaluatedData& EvaluatedData) { return EvaluatedData.Magnitude; } float UGGA_GameplayAttributesHelper::GetModifiedAttributeMagnitude(const TArray& ModifiedAttributes, FGameplayAttribute InAttribute) { float Delta = 0.f; for (const FGGA_ModifiedAttribute& Mod : ModifiedAttributes) { if (Mod.Attribute == InAttribute) { Delta += Mod.TotalMagnitude; } } return Delta; }