diff --git a/Source/OpenPF2GameFramework/Private/CharacterStats/PF2TemlCalculation.cpp b/Source/OpenPF2GameFramework/Private/CharacterStats/PF2TemlCalculation.cpp index c98538e7..08971940 100644 --- a/Source/OpenPF2GameFramework/Private/CharacterStats/PF2TemlCalculation.cpp +++ b/Source/OpenPF2GameFramework/Private/CharacterStats/PF2TemlCalculation.cpp @@ -41,8 +41,6 @@ FPF2TemlCalculation::FPF2TemlCalculation(const FGameplayTag TagPrefix, // option. if (CharacterTags->HasTag(TagPrefix)) { - const FString TagPrefixString = TagPrefix.ToString(); - // "When attempting a check that involves something you have some training in, you will also add your // proficiency bonus. This bonus depends on your proficiency rank: untrained, trained, expert, master, or // legendary. If you’re untrained, your bonus is +0—you must rely on raw talent and any bonuses from the @@ -52,22 +50,22 @@ FPF2TemlCalculation::FPF2TemlCalculation(const FGameplayTag TagPrefix, // // Source: Pathfinder 2E Core Rulebook, page 444, "Step 1: Roll D20 and Identify The Modifiers, Bonuses, and // Penalties That Apply". - if (UPF2TagLibrary::ContainerHasTag(*CharacterTags, TagPrefixString + ".Legendary")) + if (CharacterTags->HasTag(UPF2TagLibrary::RequestCombinedTagByString(TagPrefix, TEXT("Legendary")))) { // Legendary -> Your level + 8 ProficiencyBonus = CharacterLevel + 8; } - else if (UPF2TagLibrary::ContainerHasTag(*CharacterTags, TagPrefixString + ".Master")) + else if (CharacterTags->HasTag(UPF2TagLibrary::RequestCombinedTagByString(TagPrefix, TEXT("Master")))) { // Master -> Your level + 6 ProficiencyBonus = CharacterLevel + 6; } - else if (UPF2TagLibrary::ContainerHasTag(*CharacterTags, TagPrefixString + ".Expert")) + else if (CharacterTags->HasTag(UPF2TagLibrary::RequestCombinedTagByString(TagPrefix, TEXT("Expert")))) { // Expert -> Your level + 4 ProficiencyBonus = CharacterLevel + 4; } - else if (UPF2TagLibrary::ContainerHasTag(*CharacterTags, TagPrefixString + ".Trained")) + else if (CharacterTags->HasTag(UPF2TagLibrary::RequestCombinedTagByString(TagPrefix, TEXT("Trained")))) { // Trained -> Your level + 2 ProficiencyBonus = CharacterLevel + 2; diff --git a/Source/OpenPF2GameFramework/Public/Libraries/PF2TagLibrary.h b/Source/OpenPF2GameFramework/Public/Libraries/PF2TagLibrary.h index 3a204e7b..63868a60 100644 --- a/Source/OpenPF2GameFramework/Public/Libraries/PF2TagLibrary.h +++ b/Source/OpenPF2GameFramework/Public/Libraries/PF2TagLibrary.h @@ -131,4 +131,174 @@ class OPENPF2GAMEFRAMEWORK_API UPF2TagLibrary final : public UBlueprintFunctionL UFUNCTION(BlueprintCallable, BlueprintPure, meta=(AutoCreateRefTerm="ParentTag"), Category="OpenPF2|Gameplay Tags") static uint8 ParseConditionLevel(const FGameplayTag& Tag, const FGameplayTag& ParentTag); + + /** + * Combines a tag with the name of a tag that is defined within/underneath it, and returns the resulting tag. + * + * For example, given a parent tag of "PF2.Trait.Condition" and a child tag fragment of "Dying.2", this returns the + * tag "PF2.Trait.Condition.Dying.2". + * + * The combined tag must be a valid tag that has been defined either in Gameplay Tags INI files or in static tags. + * + * @tparam T + * The type of text or string being used to represent the name of the child fragment. + * + * @param ParentTag + * The parent/prefix tag under which the target tag is defined. + * @param ChildTagFragment + * The name or fragment of the tag under the parent tag. + * + * @return + * The gameplay tag that corresponds to the combination of the give child tag under the given parent tag. + */ + template + FORCEINLINE static FGameplayTag RequestCombinedTag(const FGameplayTag& ParentTag, const T& ChildTagFragment) + { + return RequestCombinedTag(ParentTag.GetTagName(), ChildTagFragment); + } + + /** + * Concatenates the names of two tags together and returns the resulting tag. + * + * For example, given a parent tag of "PF2.Trait.Condition" and a child tag fragment of "Dying.2", this returns the + * tag "PF2.Trait.Condition.Dying.2". + * + * The combined tag must be a valid tag that has been defined either in Gameplay Tags INI files or in static tags. + * + * @tparam P + * The type of text or string being used to represent the name of the parent tag. + * @tparam C + * The type of text or string being used to represent the name of the child fragment. + * + * @param ParentTagName + * The name of the parent/prefix tag under which the target tag is defined. + * @param ChildTagFragment + * The name of the desired tag under the parent tag. + * + * @return + * The gameplay tag that corresponds to the combination of the give child tag under the given parent tag. + */ + template + static FGameplayTag RequestCombinedTag(const P& ParentTagName, const C& ChildTagFragment) + { + FNameBuilder TagNameBuilder; + + TagNameBuilder << ParentTagName; + TagNameBuilder << TEXT("."); + TagNameBuilder << ChildTagFragment; + + return FGameplayTag::RequestGameplayTag(FName(TagNameBuilder.ToString())); + } + + /** + * Combines a tag with the name of a tag that is defined within/underneath it, and returns the resulting tag. + * + * For example, given a parent tag of "PF2.Trait.Condition" and a child tag fragment of "Dying.2", this returns the + * tag "PF2.Trait.Condition.Dying.2". + * + * The combined tag must be a valid tag that has been defined either in Gameplay Tags INI files or in static tags. + * + * @param ParentTag + * The parent/prefix tag under which the target tag is defined. + * @param ChildTagFragment + * The name of the desired tag under the parent tag. + * + * @return + * The gameplay tag that corresponds to the combination of the give child tag under the given parent tag. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + meta=(AutoCreateRefTerm="ParentTag,ChildTagFragment"), + Category="OpenPF2|Gameplay Tags" + ) + static FORCEINLINE FGameplayTag RequestCombinedTagByName(const FGameplayTag& ParentTag, + const FName& ChildTagFragment) + { + return RequestCombinedTag(ParentTag, ChildTagFragment); + } + + /** + * Combines a tag with the name of a tag that is defined within/underneath it, and returns the resulting tag. + * + * For example, given a parent tag of "PF2.Trait.Condition" and a child tag fragment of "Dying.2", this returns the + * tag "PF2.Trait.Condition.Dying.2". + * + * The combined tag must be a valid tag that has been defined either in Gameplay Tags INI files or in static tags. + * + * @param ParentTag + * The parent/prefix tag under which the target tag is defined. + * @param ChildTagFragment + * The name of the desired tag under the parent tag. + * + * @return + * The gameplay tag that corresponds to the combination of the give child tag under the given parent tag. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + meta=(AutoCreateRefTerm="ParentTag,ChildTagFragment"), + Category="OpenPF2|Gameplay Tags" + ) + static FORCEINLINE FGameplayTag RequestCombinedTagByString(const FGameplayTag& ParentTag, + const FString& ChildTagFragment) + { + return RequestCombinedTag(ParentTag, ChildTagFragment); + } + + /** + * Concatenates the names of two tags together and returns the resulting tag. + * + * For example, given a parent tag of "PF2.Trait.Condition" and a child tag fragment of "Dying.2", this returns the + * tag "PF2.Trait.Condition.Dying.2". + * + * The combined tag must be a valid tag that has been defined either in Gameplay Tags INI files or in static tags. + * + * @param ParentTagName + * The name of the parent/prefix tag under which the target tag is defined. + * @param ChildTagFragment + * The name of the desired tag under the parent tag. + * + * @return + * The gameplay tag that corresponds to the combination of the give child tag under the given parent tag. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + meta=(AutoCreateRefTerm="ParentTagName,ChildTagFragment"), + Category="OpenPF2|Gameplay Tags" + ) + static FORCEINLINE FGameplayTag RequestCombinedTagFromNames(const FName& ParentTagName, + const FName& ChildTagFragment) + { + return RequestCombinedTag(ParentTagName, ChildTagFragment); + } + + /** + * Concatenates the names of two tags together and returns the resulting tag. + * + * For example, given a parent tag of "PF2.Trait.Condition" and a child tag fragment of "Dying.2", this returns the + * tag "PF2.Trait.Condition.Dying.2". + * + * The combined tag must be a valid tag that has been defined either in Gameplay Tags INI files or in static tags. + * + * @param ParentTagName + * The name of the parent/prefix tag under which the target tag is defined. + * @param ChildTagFragment + * The name of the desired tag under the parent tag. + * + * @return + * The gameplay tag that corresponds to the combination of the give child tag under the given parent tag. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + meta=(AutoCreateRefTerm="ParentTagName,ChildTagFragment"), + Category="OpenPF2|Gameplay Tags" + ) + static FORCEINLINE FGameplayTag RequestCombinedTagFromStrings(const FString& ParentTagName, + const FString& ChildTagFragment) + { + return RequestCombinedTag(ParentTagName, ChildTagFragment); + } };