diff --git a/Source/OLSAnimation/OLSAnimation.Build.cs b/Source/OLSAnimation/OLSAnimation.Build.cs index 37ff753..300f6ca 100644 --- a/Source/OLSAnimation/OLSAnimation.Build.cs +++ b/Source/OLSAnimation/OLSAnimation.Build.cs @@ -25,5 +25,11 @@ public class OLSAnimation : ModuleRules "GameplayAbilities", } ); + + // Header files path + PublicIncludePaths.AddRange(new[] { "OLSAnimation/Public" }); + + // Source files path + PrivateIncludePaths.AddRange(new[] { "OLSAnimation/Private" }); } } \ No newline at end of file diff --git a/Source/OLSAnimationEditor/OLSAnimationEditor.Build.cs b/Source/OLSAnimationEditor/OLSAnimationEditor.Build.cs index 784527e..e0a4870 100644 --- a/Source/OLSAnimationEditor/OLSAnimationEditor.Build.cs +++ b/Source/OLSAnimationEditor/OLSAnimationEditor.Build.cs @@ -15,5 +15,11 @@ public class OLSAnimationEditor : ModuleRules PrivateDependencyModuleNames.AddRange(new string[] { "MessageLog" }); + + // Header files path + PublicIncludePaths.AddRange(new[] { "OLSAnimationEditor/Public" }); + + // Source files path + PrivateIncludePaths.AddRange(new[] { "OLSAnimationEditor/Private" }); } } \ No newline at end of file diff --git a/Source/ols/Private/AbilitySystem/Effects/OLSGameplayEffect.cpp b/Source/ols/Private/AbilitySystem/Effects/OLSGameplayEffect.cpp new file mode 100644 index 0000000..b2e2e7c --- /dev/null +++ b/Source/ols/Private/AbilitySystem/Effects/OLSGameplayEffect.cpp @@ -0,0 +1,37 @@ +// © 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/Effects/OLSGameplayEffect.h" + +#include "AbilitySystemComponent.h" + +void UOLSGameplayEffect::ApplyDynamicGameplayEffect(const FOLSDynamicGameplayEffectData& data) +{ + // Kick out of the call if data's AbilitySystemComponent is invalid. + if (!ensureAlwaysMsgf(data.AbilitySystemComponent.IsValid(), + TEXT("%s is called but the passed FTowersDynamicGameplayEffectData's AbilitySystemComponent is null."), + ANSI_TO_TCHAR(__func__))) + { + return; + } + + // Dynamically create the gameplay effect. + UGameplayEffect* ge = NewObject(GetTransientPackage(), data.EffectName); + // Dynamic gameplay effects must have an instant duration type. + ge->DurationPolicy = EGameplayEffectDurationType::Instant; + + // Add one new modifier to the gameplay effect. + const int32 modifierIndex = ge->Modifiers.Num(); + ge->Modifiers.SetNum(modifierIndex + 1); + + // Grab the modifier at the appropriate index and set its data appropriately. + FGameplayModifierInfo& modInfo = ge->Modifiers[modifierIndex]; + modInfo.ModifierMagnitude = data.EffectMagnitude; + modInfo.ModifierOp = data.EffectModifierOpType; + modInfo.Attribute = data.AffectedAttribute; + + // Apply the gameplay effect to the TowersCharacter's ability system component. + data.AbilitySystemComponent->ApplyGameplayEffectToSelf(ge, + data.EffectLevel, + data.AbilitySystemComponent->MakeEffectContext()); +} diff --git a/Source/ols/Private/Components/OLSHealthComponent.cpp b/Source/ols/Private/Components/OLSHealthComponent.cpp index bb25266..0469888 100644 --- a/Source/ols/Private/Components/OLSHealthComponent.cpp +++ b/Source/ols/Private/Components/OLSHealthComponent.cpp @@ -204,11 +204,11 @@ void UOLSHealthComponent::DamageSelfDestruct(bool isFellOutOfWorld) spec->AddDynamicAssetTag(TAG_Gameplay_FellOutOfWorld); } - const float DamageAmount = GetMaxHealth(); + const float damageAmount = GetMaxHealth(); // @TODO: Add LyraGameplayTags::SetByCaller_Damage. - // Spec->SetSetByCallerMagnitude(LyraGameplayTags::SetByCaller_Damage, DamageAmount); + // Spec->SetSetByCallerMagnitude(LyraGameplayTags::SetByCaller_Damage, damageAmount); AbilitySystemComponent->ApplyGameplayEffectSpecToSelf(*spec); } } diff --git a/Source/ols/Private/OLSLog.cpp b/Source/ols/Private/OLSLog.cpp new file mode 100644 index 0000000..34fdf94 --- /dev/null +++ b/Source/ols/Private/OLSLog.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 "OLSLog.h" diff --git a/Source/ols/Public/AbilitySystem/Effects/OLSGameplayEffect.h b/Source/ols/Public/AbilitySystem/Effects/OLSGameplayEffect.h new file mode 100644 index 0000000..597207d --- /dev/null +++ b/Source/ols/Public/AbilitySystem/Effects/OLSGameplayEffect.h @@ -0,0 +1,49 @@ +// © 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 "GameplayEffect.h" +#include "OLSGameplayEffect.generated.h" + +USTRUCT() +struct OLS_API FOLSDynamicGameplayEffectData +{ + GENERATED_BODY() + +public: + + // The magnitude or efficacy of the gameplay effect. + FGameplayEffectModifierMagnitude EffectMagnitude = FScalableFloat(1.f); + + // The attribute to which the gameplay effect will be applied. + FGameplayAttribute AffectedAttribute = {}; + + // The gameplay effect's name. + FName EffectName = FName(TEXT("EffectName")); + + // A pointer to the ability system component to which the gameplay effect will be applied. + TWeakObjectPtr AbilitySystemComponent; + + // The manner in which the gameplay effect will be applied (additive, multiplicative, etc.). + TEnumAsByte EffectModifierOpType = EGameplayModOp::Additive; + + // The level of the gameplay effect, which may in part determine its efficacy. + float EffectLevel = 1.f; +}; + +/** + * + */ +UCLASS() +class OLS_API UOLSGameplayEffect : public UGameplayEffect +{ + GENERATED_BODY() + +public: + /** + * Applies a dynamic gameplay effect at runtime, and in accordance with the passed FTowersDynamicGameplayEffectData. + * @param data - struct containing all of the relevant data by which the dynamic gameplay effect may be applied. + */ + static void ApplyDynamicGameplayEffect(const FOLSDynamicGameplayEffectData& data); +}; diff --git a/Source/ols/Public/OLSLog.h b/Source/ols/Public/OLSLog.h new file mode 100644 index 0000000..000867f --- /dev/null +++ b/Source/ols/Public/OLSLog.h @@ -0,0 +1,116 @@ +// © 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/SCS_Node.h" + +/* +* Helper macro where you can pass a C++ variable or function identifier and it will be converted to UE4's TEXT("") +* e.g: GET_IDENTIFIER_TEXT(myVariable); +* +* This allows us to reference the identifier instead of "hardcoding" it in between quotes. +* +* Advantages: +* 1) Renaming the variable or function name will also update the value contained inside GET_IDENTIFIER_TEXT(); +* 2) Finding references of that variable or function will also work and find it in all areas where "GET_IDENTIFIER_TEXT" is referencing that variable. +*/ +#define GET_IDENTIFIER_TEXT(identifier) TEXT(#identifier) + +/* +* Helper Macro which returns the text 'Server', 'Client', 'ListenServer' or 'Standalone' depending on the World that's passed in +* (Based off ENetMode, which is a raw struct, so we can't use UENUM_TO_STRING here) +*/ +#define GET_NETMODE_STRING(world) (world == nullptr) ? TEXT("NULLWORLD") : (world->GetNetMode() == ENetMode::NM_Client) ? TEXT("CLIENT") : (world->GetNetMode() == ENetMode::NM_DedicatedServer) ? TEXT("SERVER") : (world->GetNetMode() == ENetMode::NM_ListenServer) ? TEXT("LISTENSERVER") : (world->GetNetMode() == ENetMode::NM_Standalone) ? TEXT("STANDALONE") : TEXT("NM_MAX") + +/* +* Helper Macro which returns the string from GetName on the UObject it's passed +* (Returns NULL if the pointer is null) +*/ +#define GET_UOBJECT_NAME(obj) obj ? *obj->GetName() : TEXT("NULL") + +/* +* Helper Macro which returns the string from GetFullName on the UObject it's passed +* (Returns NULL if the pointer is null) +*/ +#define GET_UOBJECT_FULL_NAME(obj) obj ? *obj->GetFullName() : TEXT("NULL") + +/* +* Helper Macro which returns the string from GetPathName on the UObject it's passed +* (Returns NULL if the pointer is null) +*/ +#define GET_UOBJECT_PATH_NAME(obj) obj ? *obj->GetPathName() : TEXT("NULL") + +/* +* Helper Macro which returns the string from GetTagName on the FGameplayTag it's passed +*/ +#define GET_TAG_NAME(gameplayTag) *gameplayTag.GetTagName().ToString() + +/* +* Helper Macro which changes a bool into a string of TEXT +*/ +#define BOOL_TO_STRING(boolToRead) boolToRead ? TEXT("TRUE") : TEXT("FALSE") + +/* +* Helper Macro which gets the display string of an enum +*/ +#define UENUM_TO_STRING(enumClass, enumValue) *StaticEnum()->GetDisplayValueAsText(enumValue).ToString() + +/* +* Same as UE_LOG but prefixes the log with [NETMODE][FunctionName]. +* This version doesn't accept Variadic Arguments. Use TOWERS_LOG if you want to pass printf-style parameters +*/ +#define OLS_LOG_SIMPLE(categoryName, verbosity, format) UE_LOG(categoryName, verbosity, TEXT("[%s][%s]: ") format, GET_NETMODE_STRING(GetWorld()), ANSI_TO_TCHAR(__func__)); + +/* +* Same as UE_LOG but prefixes the log with [NETMODE][FunctionName]. +* This version doesn't accept Variadic Arguments. Use TOWERS_LOG if you want to pass printf-style parameters +*/ +#define OLS_LOG_SIMPLE_NO_WORLD(categoryName, verbosity, format) UE_LOG(categoryName, verbosity, TEXT("[NO_WORLD][%s]: ") format, ANSI_TO_TCHAR(__func__)); + +/* +* Same as UE_LOG but prefixes the log with [NETMODE][FunctionName]. +* This version doesn't accept Variadic Arguments. Use TOWERS_LOG if you want to pass printf-style parameters +*/ +#define OLS_LOG_SIMPLE_WORLD_CTX(categoryName, verbosity, worldContextObject, format) UE_LOG(categoryName, verbosity, TEXT("[%s][%s]: ") format, GET_NETMODE_STRING(worldContextObject), ANSI_TO_TCHAR(__func__)); + +/* +* Same as UE_LOG but prefixes the log with [NETMODE][FunctionName]. +*/ +#define OLS_LOG(categoryName, verbosity, format, ...) UE_LOG(categoryName, verbosity, TEXT("[%s][%s]: ") format, GET_NETMODE_STRING(GetWorld()), ANSI_TO_TCHAR(__func__), ##__VA_ARGS__); + +/* +* Same as UE_LOG but prefixes the log with [NETMODE][FunctionName]. +* This version can be used when called from a function which doesn't have GetWorld(). +* In that case, you can pass a worldContextObject (any UObject should do). +*/ +#define OLS_LOG_WORLD_CTX(categoryName, verbosity, worldContextObject, format, ...) UE_LOG(categoryName, verbosity, TEXT("[%s][%s]: ") format, GET_NETMODE_STRING(worldContextObject), ANSI_TO_TCHAR(__func__), ##__VA_ARGS__); + +/* +* Same as UE_LOG but prefixes the log with [NO_WORLD][FunctionName]. +* This version should only be used if you can't use either of the following alternatives: +* OLS_LOG +* OLS_LOG_WORLD_CTX +*/ +#define OLS_LOG_NO_WORLD(categoryName, verbosity, format, ...) UE_LOG(categoryName, verbosity, TEXT("[NO_WORLD][%s]: ") format, ANSI_TO_TCHAR(__func__), ##__VA_ARGS__); + +/* +* Helper macro that will log the name of the function. +* NOTE: Use TOWERS_LOG_FUNCTION_WORLD_CTX instead if GetWorld() is not an available and you have access to a worldContextObject. +*/ +#define OLS_LOG_FUNC(categoryName, verbosity) UE_LOG(categoryName, verbosity, TEXT("[%s][%s]"), GET_NETMODE_STRING(GetWorld()), ANSI_TO_TCHAR(__func__)); + +/* +* Helper macro that will log the name of the function +* This version can be used when called from a function which doesn't have GetWorld(). +* In that case, you can pass a worldContextObject (any UObject should do). +*/ +#define OLS_LOG_FUNC_WORLD_CTX(categoryName, verbosity, worldContextObject) UE_LOG(categoryName, verbosity, TEXT("[%s][%s]"), GET_NETMODE_STRING(worldContextObject), ANSI_TO_TCHAR(__func__)); + +/* +* Helper macro that will log the name of the function +* This version should only be used if you can't use either of the following alternatives: +* OLS_LOG_FUNC +* OLS_LOG_FUNCTION_WORLD_CTX +*/ +#define OLS_LOG_FUNC_NO_WORLD(categoryName, verbosity) UE_LOG(categoryName, verbosity, TEXT("[NO_WORLD][%s]"), ANSI_TO_TCHAR(__func__)); \ No newline at end of file diff --git a/Source/ols/ols.Build.cs b/Source/ols/ols.Build.cs index cd1f7ee..f916abe 100644 --- a/Source/ols/ols.Build.cs +++ b/Source/ols/ols.Build.cs @@ -30,6 +30,12 @@ public class ols : ModuleRules "NetCore" }); + // Header files path + PublicIncludePaths.AddRange(new[] { "OLS/Public" }); + + // Source files path + PrivateIncludePaths.AddRange(new[] { "OLS/Private" }); + // Uncomment if you are using Slate UI // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });