diff --git a/Source/OLSAnimation/OLSAnimation.Build.cs b/Source/OLSAnimation/OLSAnimation.Build.cs index 3fe35a8..37ff753 100644 --- a/Source/OLSAnimation/OLSAnimation.Build.cs +++ b/Source/OLSAnimation/OLSAnimation.Build.cs @@ -9,7 +9,7 @@ public class OLSAnimation : ModuleRules PublicDependencyModuleNames.AddRange( new string[] { - "Core" + "Core", } ); diff --git a/Source/ols/Private/AbilitySystem/Abilities/OLSGameplayAbility.cpp b/Source/ols/Private/AbilitySystem/Abilities/OLSGameplayAbility.cpp new file mode 100644 index 0000000..25a1cb8 --- /dev/null +++ b/Source/ols/Private/AbilitySystem/Abilities/OLSGameplayAbility.cpp @@ -0,0 +1,4 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "AbilitySystem/Abilities/OLSGameplayAbility.h" diff --git a/Source/ols/Private/AbilitySystem/Attributes/OLSAttributeSetBase.cpp b/Source/ols/Private/AbilitySystem/Attributes/OLSAttributeSetBase.cpp new file mode 100644 index 0000000..d6f2e0c --- /dev/null +++ b/Source/ols/Private/AbilitySystem/Attributes/OLSAttributeSetBase.cpp @@ -0,0 +1,23 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "AbilitySystem/Attributes/OLSAttributeSetBase.h" + +#include "AbilitySystem/OLSAbilitySystemComponent.h" + +UOLSAttributeSetBase::UOLSAttributeSetBase() +{ +} + +UWorld* UOLSAttributeSetBase::GetWorld() const +{ + const UObject* outer = GetOuter(); + check(outer); + + return outer->GetWorld(); +} + +UOLSAbilitySystemComponent* UOLSAttributeSetBase::GetOLSAbilitySystemComponent() const +{ + return Cast(GetOwningAbilitySystemComponent()); +} diff --git a/Source/ols/Private/DataAssets/OLSAbilitySetPrimaryDataAsset.cpp b/Source/ols/Private/DataAssets/OLSAbilitySetPrimaryDataAsset.cpp new file mode 100644 index 0000000..2d150d0 --- /dev/null +++ b/Source/ols/Private/DataAssets/OLSAbilitySetPrimaryDataAsset.cpp @@ -0,0 +1,153 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "DataAssets/OLSAbilitySetPrimaryDataAsset.h" + +#include "ActiveGameplayEffectHandle.h" +#include "GameplayAbilitySpecHandle.h" +#include "AbilitySystem/OLSAbilitySystemComponent.h" +#include "AbilitySystem/Abilities/OLSGameplayAbility.h" +#include "AbilitySystem/Attributes/OLSAttributeSetBase.h" + +void FOLSAbilitySet_GrantedHandles::AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& handle) +{ + if (handle.IsValid()) + { + AbilitySpecHandles.Add(handle); + } +} + +void FOLSAbilitySet_GrantedHandles::AddGameplayEffectHandle(const FActiveGameplayEffectHandle& handle) +{ + if (handle.IsValid()) + { + GameplayEffectHandles.Add(handle); + } +} + +void FOLSAbilitySet_GrantedHandles::AddAttributeSet(UAttributeSet* set) +{ + GrantedAttributeSets.Add(set); +} + +void FOLSAbilitySet_GrantedHandles::TakeFromAbilitySystem(UOLSAbilitySystemComponent* olsASC) +{ + check(olsASC); + + if (!olsASC->IsOwnerActorAuthoritative()) + { + // Must be authoritative to give or take ability sets. + return; + } + + for (const FGameplayAbilitySpecHandle& handle : AbilitySpecHandles) + { + if (handle.IsValid()) + { + olsASC->ClearAbility(handle); + } + } + + for (const FActiveGameplayEffectHandle& handle : GameplayEffectHandles) + { + if (handle.IsValid()) + { + olsASC->RemoveActiveGameplayEffect(handle); + } + } + + for (UAttributeSet* set : GrantedAttributeSets) + { + olsASC->RemoveSpawnedAttribute(set); + } + + AbilitySpecHandles.Reset(); + GameplayEffectHandles.Reset(); + GrantedAttributeSets.Reset(); +} + +UOLSAbilitySetPrimaryDataAsset::UOLSAbilitySetPrimaryDataAsset(const FObjectInitializer& objectInitializer) : Super(objectInitializer) +{ +} + +void UOLSAbilitySetPrimaryDataAsset::GiveToAbilitySystem( + UOLSAbilitySystemComponent* olsASC, + FOLSAbilitySet_GrantedHandles* outGrantedHandlePtrs, + UObject* sourceObject) const +{ + check(olsASC); + + if (!olsASC->IsOwnerActorAuthoritative()) + { + // Must be authoritative to give or take ability sets. + return; + } + + // Grant the attribute sets. + for (int32 setIndex = 0; setIndex < GrantedAttributes.Num(); ++setIndex) + { + const FOLSAbilitySet_AttributeSet& setToGrant = GrantedAttributes[setIndex]; + + if (!IsValid(setToGrant.AttributeSet)) + { + //@Todo: Replace this with custom log. + // UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedAttributes[%d] on ability set [%s] is not valid"), SetIndex, *GetNameSafe(this)); + continue; + } + + UAttributeSet* newSet = NewObject(olsASC->GetOwner(), setToGrant.AttributeSet); + olsASC->AddAttributeSetSubobject(newSet); + + if (outGrantedHandlePtrs) + { + outGrantedHandlePtrs->AddAttributeSet(newSet); + } + } + + // Grant the gameplay abilities. + for (int32 abilityIndex = 0; abilityIndex < GrantedGameplayAbilities.Num(); ++abilityIndex) + { + const FOLSAbilitySet_GameplayAbility& AbilityToGrant = GrantedGameplayAbilities[abilityIndex]; + + if (!IsValid(AbilityToGrant.Ability)) + { + //@Todo: Replace this with custom log. + // UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayAbilities[%d] on ability set [%s] is not valid."), AbilityIndex, *GetNameSafe(this)); + continue; + } + + UOLSGameplayAbility* abilityCDO = AbilityToGrant.Ability->GetDefaultObject(); + + FGameplayAbilitySpec abilitySpec(abilityCDO, AbilityToGrant.AbilityLevel); + abilitySpec.SourceObject = sourceObject; + abilitySpec.GetDynamicSpecSourceTags().AddTag(AbilityToGrant.InputTag); + + const FGameplayAbilitySpecHandle abilitySpecHandle = olsASC->GiveAbility(abilitySpec); + + if (outGrantedHandlePtrs) + { + outGrantedHandlePtrs->AddAbilitySpecHandle(abilitySpecHandle); + } + } + + // Grant the gameplay effects. + for (int32 effectIndex = 0; effectIndex < GrantedGameplayEffects.Num(); ++effectIndex) + { + const FOLSAbilitySet_GameplayEffect& EffectToGrant = GrantedGameplayEffects[effectIndex]; + + if (!IsValid(EffectToGrant.GameplayEffect)) + { + //@Todo: Replace this with custom log. + // UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayEffects[%d] on ability set [%s] is not valid"), EffectIndex, *GetNameSafe(this)); + continue; + } + + const UGameplayEffect* gameplayEffect = EffectToGrant.GameplayEffect->GetDefaultObject(); + const FActiveGameplayEffectHandle gameplayEffectHandle = olsASC->ApplyGameplayEffectToSelf(gameplayEffect, EffectToGrant.EffectLevel, olsASC->MakeEffectContext()); + + if (outGrantedHandlePtrs) + { + outGrantedHandlePtrs->AddGameplayEffectHandle(gameplayEffectHandle); + } + } +} diff --git a/Source/ols/Private/DataAssets/OLSAbilityTagRelationshipMappingDataAsset.cpp b/Source/ols/Private/DataAssets/OLSAbilityTagRelationshipMappingDataAsset.cpp new file mode 100644 index 0000000..9b62c9e --- /dev/null +++ b/Source/ols/Private/DataAssets/OLSAbilityTagRelationshipMappingDataAsset.cpp @@ -0,0 +1,67 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "DataAssets/OLSAbilityTagRelationshipMappingDataAsset.h" + +void UOLSAbilityTagRelationshipMappingDataAsset::GetAbilityTagsToBlockAndCancel( + const FGameplayTagContainer& abilityTags, + FGameplayTagContainer* outTagsToBlockPtr, + FGameplayTagContainer* outTagsToCancelPtr) const +{ + for (int32 i = 0; i < AbilityTagRelationships.Num(); i++) + { + const FOLSAbilityTagRelationship& tags = AbilityTagRelationships[i]; + if (abilityTags.HasTag(tags.AbilityTag)) + { + if (outTagsToBlockPtr) + { + outTagsToBlockPtr->AppendTags(tags.AbilityTagsToBlock); + } + if (outTagsToCancelPtr) + { + outTagsToCancelPtr->AppendTags(tags.AbilityTagsToCancel); + } + } + } +} + +void UOLSAbilityTagRelationshipMappingDataAsset::GetRequiredAndBlockedActivationTags( + const FGameplayTagContainer& abilityTags, + FGameplayTagContainer* outActivationRequiredPtr, + FGameplayTagContainer* outActivationBlockedPtr) const +{ + // Simple iteration for now + for (int32 i = 0; i < AbilityTagRelationships.Num(); i++) + { + const FOLSAbilityTagRelationship& tags = AbilityTagRelationships[i]; + if (abilityTags.HasTag(tags.AbilityTag)) + { + if (outActivationRequiredPtr) + { + outActivationRequiredPtr->AppendTags(tags.ActivationRequiredTags); + } + if (outActivationBlockedPtr) + { + outActivationBlockedPtr->AppendTags(tags.ActivationBlockedTags); + } + } + } +} + +bool UOLSAbilityTagRelationshipMappingDataAsset::IsAbilityCancelledByTag( + const FGameplayTagContainer& abilityTags, + const FGameplayTag& actionTag) const +{ + // Simple iteration for now + for (int32 i = 0; i < AbilityTagRelationships.Num(); i++) + { + const FOLSAbilityTagRelationship& tags = AbilityTagRelationships[i]; + + if (tags.AbilityTag == actionTag && tags.AbilityTagsToCancel.HasAny(abilityTags)) + { + return true; + } + } + + return false; +} diff --git a/Source/ols/Private/DataAssets/OLSExperienceDefinitionPrimaryDataAsset.cpp b/Source/ols/Private/DataAssets/OLSExperienceDefinitionPrimaryDataAsset.cpp new file mode 100644 index 0000000..e311777 --- /dev/null +++ b/Source/ols/Private/DataAssets/OLSExperienceDefinitionPrimaryDataAsset.cpp @@ -0,0 +1,85 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "DataAssets/OLSExperienceDefinitionPrimaryDataAsset.h" + +#include "GameFeatureAction.h" +#if WITH_EDITOR +#include "Misc/DataValidation.h" +#endif + +#include UE_INLINE_GENERATED_CPP_BY_NAME(OLSExperienceDefinitionPrimaryDataAsset) + +#define LOCTEXT_NAMESPACE "OLSSystem" + +UOLSExperienceDefinitionPrimaryDataAsset::UOLSExperienceDefinitionPrimaryDataAsset() +{ +} + +#if WITH_EDITOR +EDataValidationResult UOLSExperienceDefinitionPrimaryDataAsset::IsDataValid(FDataValidationContext& context) const +{ + EDataValidationResult result = CombineDataValidationResults(Super::IsDataValid(context), EDataValidationResult::Valid); + + int32 entryIndex = 0; + for (const UGameFeatureAction* action : Actions) + { + if (action) + { + EDataValidationResult childResult = action->IsDataValid(context); + result = CombineDataValidationResults(result, childResult); + } + else + { + result = EDataValidationResult::Invalid; + context.AddError(FText::Format(LOCTEXT("ActionEntryIsNull", "Null entry at index {0} in Actions"), FText::AsNumber(entryIndex))); + } + + ++entryIndex; + } + + // Make sure users didn't subclass from a BP of this (it's fine and expected to subclass once in BP, just not twice) + if (!GetClass()->IsNative()) + { + const UClass* parentClass = GetClass()->GetSuperClass(); + + // Find the native parent + const UClass* firstNativeParent = parentClass; + while ((firstNativeParent != nullptr) && !firstNativeParent->IsNative()) + { + firstNativeParent = firstNativeParent->GetSuperClass(); + } + + if (firstNativeParent != parentClass) + { + context.AddError(FText::Format(LOCTEXT("ExperienceInheritenceIsUnsupported", "Blueprint subclasses of Blueprint experiences is not currently supported (use composition via ActionSets instead). Parent class was {0} but should be {1}."), + FText::AsCultureInvariant(GetPathNameSafe(parentClass)), + FText::AsCultureInvariant(GetPathNameSafe(firstNativeParent)) + )); + result = EDataValidationResult::Invalid; + } + } + + return result; +} +#endif + +FString UOLSExperienceDefinitionPrimaryDataAsset::GetIdentifierString() const +{ + return GetPrimaryAssetId().ToString(); +} + +#if WITH_EDITOR +void UOLSExperienceDefinitionPrimaryDataAsset::UpdateAssetBundleData() +{ + Super::UpdateAssetBundleData(); + + for (UGameFeatureAction* action : Actions) + { + if (action) + { + action->AddAdditionalAssetBundleData(AssetBundleData); + } + } +} +#endif diff --git a/Source/ols/Private/DataAssets/OLSInputConfigDataAsset.cpp b/Source/ols/Private/DataAssets/OLSInputConfigDataAsset.cpp new file mode 100644 index 0000000..a223ffc --- /dev/null +++ b/Source/ols/Private/DataAssets/OLSInputConfigDataAsset.cpp @@ -0,0 +1,50 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "DataAssets/OLSInputConfigDataAsset.h" + +UOLSInputConfigDataAsset::UOLSInputConfigDataAsset(const FObjectInitializer& objectInitializer) : Super(objectInitializer) +{ +} + +const UInputAction* UOLSInputConfigDataAsset::FindNativeInputActionForTag( + const FGameplayTag& inputTag, + bool shouldLogNotFound) const +{ + for (const FOLSInputAction& action : NativeInputActions) + { + if (action.InputAction && (action.InputTag == inputTag)) + { + return action.InputAction; + } + } + + if (shouldLogNotFound) + { + //Todo: replace this with our custom log. + //UE_LOG(LogLyra, Error, TEXT("Can't find NativeInputAction for InputTag [%s] on InputConfig [%s]."), *InputTag.ToString(), *GetNameSafe(this)); + } + + return nullptr; +} + +const UInputAction* UOLSInputConfigDataAsset::FindAbilityInputActionForTag( + const FGameplayTag& inputTag, + bool shouldLogNotFound) const +{ + for (const FOLSInputAction& action : AbilityInputActions) + { + if (action.InputAction && (action.InputTag == inputTag)) + { + return action.InputAction; + } + } + + if (shouldLogNotFound) + { + //Todo: replace this with our custom log. + //UE_LOG(LogLyra, Error, TEXT("Can't find AbilityInputAction for InputTag [%s] on InputConfig [%s]."), *InputTag.ToString(), *GetNameSafe(this)); + } + + return nullptr; +} diff --git a/Source/ols/Private/DataAssets/OLSPawnPrimaryDataAsset.cpp b/Source/ols/Private/DataAssets/OLSPawnPrimaryDataAsset.cpp new file mode 100644 index 0000000..5f16f9d --- /dev/null +++ b/Source/ols/Private/DataAssets/OLSPawnPrimaryDataAsset.cpp @@ -0,0 +1,20 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "DataAssets/OLSPawnPrimaryDataAsset.h" + +UOLSPawnPrimaryDataAsset::UOLSPawnPrimaryDataAsset(const FObjectInitializer& objectInitializer) + : Super(objectInitializer) +{ + PawnClass = nullptr; + TagRelationshipMapping = nullptr; + InputConfig = nullptr; + + // @Todo: implement DefaultCamera mode here. + // DefaultCameraMode = nullptr; +} + +FString UOLSPawnPrimaryDataAsset::GetIdentifierString() const +{ + return GetPrimaryAssetId().ToString(); +} diff --git a/Source/ols/Private/DataAssets/OLSPrimaryDataAsset.cpp b/Source/ols/Private/DataAssets/OLSPrimaryDataAsset.cpp new file mode 100644 index 0000000..d5c2d87 --- /dev/null +++ b/Source/ols/Private/DataAssets/OLSPrimaryDataAsset.cpp @@ -0,0 +1,9 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "DataAssets/OLSPrimaryDataAsset.h" + +FString UOLSPrimaryDataAsset::GetIdentifierString() const +{ + return GetPrimaryAssetId().ToString(); +} diff --git a/Source/ols/Private/GameModes/OLSExperienceManagerComponent.cpp b/Source/ols/Private/GameModes/OLSExperienceManagerComponent.cpp new file mode 100644 index 0000000..c7063c6 --- /dev/null +++ b/Source/ols/Private/GameModes/OLSExperienceManagerComponent.cpp @@ -0,0 +1,5 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "GameModes/OLSExperienceManagerComponent.h" + diff --git a/Source/ols/Private/Interfaces/OLSPrimaryDataAssetInterface.cpp b/Source/ols/Private/Interfaces/OLSPrimaryDataAssetInterface.cpp new file mode 100644 index 0000000..4924ef7 --- /dev/null +++ b/Source/ols/Private/Interfaces/OLSPrimaryDataAssetInterface.cpp @@ -0,0 +1,7 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + + +#include "Interfaces/OLSPrimaryDataAssetInterface.h" + + +// Add default functionality here for any IOLSPrimaryDataAssetInterface functions that are not pure virtual. diff --git a/Source/ols/Public/AbilitySystem/Abilities/OLSGameplayAbility.h b/Source/ols/Public/AbilitySystem/Abilities/OLSGameplayAbility.h new file mode 100644 index 0000000..60da1a5 --- /dev/null +++ b/Source/ols/Public/AbilitySystem/Abilities/OLSGameplayAbility.h @@ -0,0 +1,16 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "Abilities/GameplayAbility.h" +#include "OLSGameplayAbility.generated.h" + +/** + * + */ +UCLASS() +class OLS_API UOLSGameplayAbility : public UGameplayAbility +{ + GENERATED_BODY() +}; diff --git a/Source/ols/Public/AbilitySystem/Attributes/OLSAttributeSetBase.h b/Source/ols/Public/AbilitySystem/Attributes/OLSAttributeSetBase.h new file mode 100644 index 0000000..8774b3f --- /dev/null +++ b/Source/ols/Public/AbilitySystem/Attributes/OLSAttributeSetBase.h @@ -0,0 +1,65 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "AttributeSet.h" +#include "OLSAttributeSetBase.generated.h" + +/** + * This macro defines a set of helper functions for accessing and initializing attributes. + * + * The following example of the macro: + * ATTRIBUTE_ACCESSORS(ULyraHealthSet, Health) + * will create the following functions: + * static FGameplayAttribute GetHealthAttribute(); + * float GetHealth() const; + * void SetHealth(float NewVal); + * void InitHealth(float NewVal); + */ +#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \ +GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \ +GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \ +GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \ +GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName) + +/** + * Delegate used to broadcast attribute events, some of these parameters may be null on clients: + * @param EffectInstigator The original instigating actor for this event + * @param EffectCauser The physical actor that caused the change + * @param EffectSpec The full effect spec for this change + * @param EffectMagnitude The raw magnitude, this is before clamping + * @param OldValue The value of the attribute before it was changed + * @param NewValue The value after it was changed +*/ +DECLARE_MULTICAST_DELEGATE_SixParams( + FOLSAttributeEventNativeDelegate, + class AActor* /*effectInstigator*/, + class AActor* /*effectCauser*/, + const struct FGameplayEffectSpec* /*effectSpec*/, + float /*effectMagnitude*/, + float /*oldValue*/, + float /*newValue*/); + +/** + * UOLSAttributeSet + * + * Base attribute set class for the project. + */ +UCLASS() +class OLS_API UOLSAttributeSetBase : public UAttributeSet +{ + GENERATED_BODY() + +public: + + UOLSAttributeSetBase(); + + //~ Begin UObject interface + class UWorld* GetWorld() const override; + //~ End UObject interface + +public: + + class UOLSAbilitySystemComponent* GetOLSAbilitySystemComponent() const; +}; diff --git a/Source/ols/Public/DataAssets/OLSAbilitySetPrimaryDataAsset.h b/Source/ols/Public/DataAssets/OLSAbilitySetPrimaryDataAsset.h new file mode 100644 index 0000000..771b678 --- /dev/null +++ b/Source/ols/Public/DataAssets/OLSAbilitySetPrimaryDataAsset.h @@ -0,0 +1,133 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTagContainer.h" +#include "OLSPawnPrimaryDataAsset.h" +#include "OLSAbilitySetPrimaryDataAsset.generated.h" +/** +* /** + * FOLSAbilitySet_GameplayAbility + * + * Data used by the ability set to grant gameplay abilities. + */ +USTRUCT(BlueprintType) +struct FOLSAbilitySet_GameplayAbility +{ + GENERATED_BODY() + +public: + + // Gameplay ability to grant. + UPROPERTY(EditDefaultsOnly) + TSubclassOf Ability = nullptr; + + // Tag used to process input for the ability. + UPROPERTY(EditDefaultsOnly, Meta = (Categories = "InputTag")) + FGameplayTag InputTag = FGameplayTag::EmptyTag; + + // Level of ability to grant. + UPROPERTY(EditDefaultsOnly) + int32 AbilityLevel = 1; +}; + +/** + * FOLSAbilitySet_GameplayEffect + * + * Data used by the ability set to grant gameplay effects. + */ +USTRUCT(BlueprintType) +struct FOLSAbilitySet_GameplayEffect +{ + GENERATED_BODY() + +public: + + // Gameplay effect to grant. + UPROPERTY(EditDefaultsOnly) + TSubclassOf GameplayEffect = nullptr; + + // Level of gameplay effect to grant. + UPROPERTY(EditDefaultsOnly) + float EffectLevel = 1.0f; +}; + +/** + * FOLSAbilitySet_AttributeSet + * + * Data used by the ability set to grant attribute sets. + */ +USTRUCT(BlueprintType) +struct FOLSAbilitySet_AttributeSet +{ + GENERATED_BODY() + +public: + + // Gameplay effect to grant. + UPROPERTY(EditDefaultsOnly) + TSubclassOf AttributeSet = nullptr; +}; + +/** + * FOLSAbilitySet_GrantedHandles + * + * Data used to store handles to what has been granted by the ability set. + */ +USTRUCT(BlueprintType) +struct FOLSAbilitySet_GrantedHandles +{ + GENERATED_BODY() + +public: + + void AddAbilitySpecHandle(const struct FGameplayAbilitySpecHandle& handle); + void AddGameplayEffectHandle(const struct FActiveGameplayEffectHandle& handle); + void AddAttributeSet(class UAttributeSet* set); + + void TakeFromAbilitySystem(class UOLSAbilitySystemComponent* olsASC); + +protected: + + // Handles to the granted abilities. + UPROPERTY() + TArray AbilitySpecHandles; + + // Handles to the granted gameplay effects. + UPROPERTY() + TArray GameplayEffectHandles; + + // Pointers to the granted attribute sets + UPROPERTY() + TArray> GrantedAttributeSets; +}; + +UCLASS() +class OLS_API UOLSAbilitySetPrimaryDataAsset : public UOLSPawnPrimaryDataAsset +{ + GENERATED_BODY() + + +public: + + UOLSAbilitySetPrimaryDataAsset(const FObjectInitializer& objectInitializer); + + // Grants the ability set to the specified ability system component. + // The returned handles can be used later to take away anything that was granted. + void GiveToAbilitySystem(class UOLSAbilitySystemComponent* olsASC, FOLSAbilitySet_GrantedHandles* outGrantedHandlePtrs, class UObject* sourceObject = nullptr) const; + +protected: + + // Gameplay abilities to grant when this ability set is granted. + UPROPERTY(EditDefaultsOnly, Category = "Gameplay Abilities", meta=(TitleProperty=Ability)) + TArray GrantedGameplayAbilities; + + // Gameplay effects to grant when this ability set is granted. + UPROPERTY(EditDefaultsOnly, Category = "Gameplay Effects", meta=(TitleProperty=GameplayEffect)) + TArray GrantedGameplayEffects; + + // Attribute sets to grant when this ability set is granted. + UPROPERTY(EditDefaultsOnly, Category = "Attribute Sets", meta=(TitleProperty=AttributeSet)) + TArray GrantedAttributes; +}; diff --git a/Source/ols/Public/DataAssets/OLSAbilityTagRelationshipMappingDataAsset.h b/Source/ols/Public/DataAssets/OLSAbilityTagRelationshipMappingDataAsset.h new file mode 100644 index 0000000..5dcde6d --- /dev/null +++ b/Source/ols/Public/DataAssets/OLSAbilityTagRelationshipMappingDataAsset.h @@ -0,0 +1,61 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTagContainer.h" +#include "Engine/DataAsset.h" +#include "OLSAbilityTagRelationshipMappingDataAsset.generated.h" + +/** Struct that defines the relationship between different ability tags */ +USTRUCT() +struct FOLSAbilityTagRelationship +{ + GENERATED_BODY() + + /** The tag that this container relationship is about. Single tag, but abilities can have multiple of these */ + UPROPERTY(EditAnywhere, Category = Ability, meta = (Categories = "Gameplay.Action")) + FGameplayTag AbilityTag = FGameplayTag::EmptyTag; + + /** The other ability tags that will be blocked by any ability using this tag */ + UPROPERTY(EditAnywhere, Category = Ability) + FGameplayTagContainer AbilityTagsToBlock; + + /** The other ability tags that will be canceled by any ability using this tag */ + UPROPERTY(EditAnywhere, Category = Ability) + FGameplayTagContainer AbilityTagsToCancel; + + /** If an ability has the tag, this is implicitly added to the activation required tags of the ability */ + UPROPERTY(EditAnywhere, Category = Ability) + FGameplayTagContainer ActivationRequiredTags; + + /** If an ability has the tag, this is implicitly added to the activation blocked tags of the ability */ + UPROPERTY(EditAnywhere, Category = Ability) + FGameplayTagContainer ActivationBlockedTags; +}; + +/** + * Mapping of how ability tags block or cancel other abilities + */ +UCLASS() +class OLS_API UOLSAbilityTagRelationshipMappingDataAsset : public UDataAsset +{ + GENERATED_BODY() + +public: + + /** Given a set of ability tags, parse the tag relationship and fill out tags to block and cancel */ + void GetAbilityTagsToBlockAndCancel(const FGameplayTagContainer& abilityTags, FGameplayTagContainer* outTagsToBlockPtr, FGameplayTagContainer* outTagsToCancelPtr) const; + + /** Given a set of ability tags, add additional required and blocking tags */ + void GetRequiredAndBlockedActivationTags(const FGameplayTagContainer& abilityTags, FGameplayTagContainer* outActivationRequiredPtr, FGameplayTagContainer* outActivationBlockedPtr) const; + + /** Returns true if the specified ability tags are canceled by the passed in action tag */ + bool IsAbilityCancelledByTag(const FGameplayTagContainer& abilityTags, const FGameplayTag& actionTag) const; + +private: + + /** The list of relationships between different gameplay tags (which ones block or cancel others) */ + UPROPERTY(EditAnywhere, Category = Ability, meta=(TitleProperty="AbilityTag")) + TArray AbilityTagRelationships; +}; diff --git a/Source/ols/Public/DataAssets/OLSExperienceDefinitionPrimaryDataAsset.h b/Source/ols/Public/DataAssets/OLSExperienceDefinitionPrimaryDataAsset.h new file mode 100644 index 0000000..1c86adc --- /dev/null +++ b/Source/ols/Public/DataAssets/OLSExperienceDefinitionPrimaryDataAsset.h @@ -0,0 +1,55 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "DataAssets/OLSPrimaryDataAsset.h" +#include "Engine/DataAsset.h" +#include "OLSExperienceDefinitionPrimaryDataAsset.generated.h" + +/** + * Definition of an experience + */ +UCLASS(BlueprintType, Const) +class OLS_API UOLSExperienceDefinitionPrimaryDataAsset : public UOLSPrimaryDataAsset +{ + GENERATED_BODY() + +public: + + UOLSExperienceDefinitionPrimaryDataAsset(); + + //~ Begin UObject interface +#if WITH_EDITOR + virtual EDataValidationResult IsDataValid(class FDataValidationContext& context) const override; +#endif + //~ End of UObject interface + + //~ Begin IOLSPrimaryDataAssetInterface + virtual FString GetIdentifierString() const override; + //~ End IOLSPrimaryDataAssetInterface + + //~ Begin UPrimaryDataAsset interface + #if WITH_EDITORONLY_DATA + virtual void UpdateAssetBundleData() override; + #endif + //~ End of UPrimaryDataAsset interface + +protected: + + // List of Game Feature Plugins this experience wants to have active + UPROPERTY(EditDefaultsOnly, Category = "OLSExperienceDefinition") + TArray GameFeaturesToEnable; + + /** The default pawn class to spawn for players */ + // UPROPERTY(EditDefaultsOnly, Category = "OLSExperienceDefinition") + // TObjectPtr DefaultPawnData; + + // List of actions to perform as this experience is loaded/activated/deactivated/unloaded + UPROPERTY(EditDefaultsOnly, Instanced, Category = "OLSExperienceDefinition") + TArray> Actions; + + // List of additional action sets to compose into this experience + // UPROPERTY(EditDefaultsOnly, Category = "OLSExperienceDefinition") + // TArray> ActionSets; +}; diff --git a/Source/ols/Public/DataAssets/OLSInputConfigDataAsset.h b/Source/ols/Public/DataAssets/OLSInputConfigDataAsset.h new file mode 100644 index 0000000..cec5f6d --- /dev/null +++ b/Source/ols/Public/DataAssets/OLSInputConfigDataAsset.h @@ -0,0 +1,60 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTagContainer.h" +#include "Engine/DataAsset.h" +#include "OLSInputConfigDataAsset.generated.h" + +/** + * FOLSInputAction + * + * Struct used to map a input action to a gameplay input tag. + */ +USTRUCT(BlueprintType) +struct FOLSInputAction +{ + GENERATED_BODY() + +public: + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + TObjectPtr InputAction = nullptr; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Meta = (Categories = "InputTag")) + FGameplayTag InputTag = FGameplayTag::EmptyTag; +}; + +/** + * UOLSInputConfigDataAsset + * + * Non-mutable data asset that contains input configuration properties. + */ +UCLASS(BlueprintType, Const) +class OLS_API UOLSInputConfigDataAsset : public UDataAsset +{ + GENERATED_BODY() + +public: + + UOLSInputConfigDataAsset(const FObjectInitializer& objectInitializer); + +public: + + UFUNCTION(BlueprintCallable, Category = "Lyra|Pawn") + const UInputAction* FindNativeInputActionForTag(const FGameplayTag& inputTag, bool shouldLogNotFound = true) const; + + UFUNCTION(BlueprintCallable, Category = "Lyra|Pawn") + const UInputAction* FindAbilityInputActionForTag(const FGameplayTag& inputTag, bool shouldLogNotFound = true) const; + +public: + + // List of input actions used by the owner. These input actions are mapped to a gameplay tag and must be manually bound. + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Meta = (TitleProperty = "InputAction")) + TArray NativeInputActions; + + // List of input actions used by the owner. These input actions are mapped to a gameplay tag and are automatically bound to abilities with matching input tags. + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Meta = (TitleProperty = "InputAction")) + TArray AbilityInputActions; +}; diff --git a/Source/ols/Public/DataAssets/OLSPawnPrimaryDataAsset.h b/Source/ols/Public/DataAssets/OLSPawnPrimaryDataAsset.h new file mode 100644 index 0000000..9fe5953 --- /dev/null +++ b/Source/ols/Public/DataAssets/OLSPawnPrimaryDataAsset.h @@ -0,0 +1,51 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "OLSPrimaryDataAsset.h" +#include "Engine/DataAsset.h" +#include "Interfaces/OLSPrimaryDataAssetInterface.h" +#include "OLSPawnPrimaryDataAsset.generated.h" + +/** + * UOLSPawnPrimaryDataAsset + * + * Non-mutable data asset that contains properties used to define a pawn. + */ +UCLASS(BlueprintType, Const, Meta = (DisplayName = "OLS Pawn Primary Data", ShortTooltip = "Data asset used to define a Pawn.")) +class OLS_API UOLSPawnPrimaryDataAsset : public UOLSPrimaryDataAsset +{ + GENERATED_BODY() + +public: + + UOLSPawnPrimaryDataAsset(const FObjectInitializer& objectInitializer); + + //~ Begin UOLSPrimaryDataAsset interface + virtual FString GetIdentifierString() const override; + //~ End UOLSPrimaryDataAsset interface + +protected: + + // Class to instantiate for this pawn (should usually derive from AOLSPawn or AOLSCharacter). + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS|Pawn") + TSubclassOf PawnClass = nullptr; + + // Ability sets to grant to this pawn's ability system. + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS|Abilities") + TArray> AbilitySets; + + // What mapping of ability tags to use for actions taking by this pawn + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS|Abilities") + TObjectPtr TagRelationshipMapping = nullptr; + + // Input configuration used by player controlled pawns to create input mappings and bind input actions. + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS|Input") + TObjectPtr InputConfig = nullptr; + + // @Todo: implement DefaultCamera mode here. + // Default camera mode used by player controlled pawns. + // UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Camera") + // TSubclassOf DefaultCameraMode = nullptr; +}; diff --git a/Source/ols/Public/DataAssets/OLSPrimaryDataAsset.h b/Source/ols/Public/DataAssets/OLSPrimaryDataAsset.h new file mode 100644 index 0000000..8a6499b --- /dev/null +++ b/Source/ols/Public/DataAssets/OLSPrimaryDataAsset.h @@ -0,0 +1,25 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataAsset.h" +#include "OLSPrimaryDataAsset.generated.h" + +/** Asset type that uniquely identifies this data asset. */ +static FPrimaryAssetType AssetType; + +/** + * A base class of Primary Data Asset, which will be used for all Primary Data Asset in OLS. + */ +UCLASS() +class OLS_API UOLSPrimaryDataAsset : public UPrimaryDataAsset +{ + GENERATED_BODY() + +public: + + //~ Begin IOLSPrimaryDataAssetInterface + virtual FString GetIdentifierString() const; + //~ End IOLSPrimaryDataAssetInterface +}; diff --git a/Source/ols/Public/GameModes/OLSExperienceManagerComponent.h b/Source/ols/Public/GameModes/OLSExperienceManagerComponent.h new file mode 100644 index 0000000..4698581 --- /dev/null +++ b/Source/ols/Public/GameModes/OLSExperienceManagerComponent.h @@ -0,0 +1,30 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/GameStateComponent.h" +// #include "LoadingProcessInterface.h" +#include "OLSExperienceManagerComponent.generated.h" + +namespace UE::GameFeatures { struct FResult; } + +// DECLARE_MULTICAST_DELEGATE_OneParam(FOnLyraExperienceLoaded, const ULyraExperienceDefinition* /*Experience*/); + +enum class EOLSExperienceLoadState +{ + Unloaded, + Loading, + LoadingGameFeatures, + LoadingChaosTestingDelay, + ExecutingActions, + Loaded, + Deactivating +}; + +UCLASS() +class OLS_API UOLSExperienceManagerComponent : public UGameStateComponent /*, public ILoadingProcessInterface */ +{ + GENERATED_BODY() + +}; diff --git a/Source/ols/Public/Interfaces/OLSPrimaryDataAssetInterface.h b/Source/ols/Public/Interfaces/OLSPrimaryDataAssetInterface.h new file mode 100644 index 0000000..721bea6 --- /dev/null +++ b/Source/ols/Public/Interfaces/OLSPrimaryDataAssetInterface.h @@ -0,0 +1,29 @@ +// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "OLSPrimaryDataAssetInterface.generated.h" + +// This class does not need to be modified. +UINTERFACE() +class UOLSPrimaryDataAssetInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class OLS_API IOLSPrimaryDataAssetInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + /** Returns the logical name, equivalent to the primary asset id */ + UFUNCTION(Blueprintable) + virtual FString GetIdentifierString() const = 0; +}; diff --git a/ols.uproject b/ols.uproject index e018664..b252cab 100644 --- a/ols.uproject +++ b/ols.uproject @@ -51,6 +51,10 @@ { "Name": "GameFeatures", "Enabled": true + }, + { + "Name": "CommonLoadingScreen", + "Enabled": true } ] } \ No newline at end of file