Initial commit of ability system

This commit is contained in:
LongLy 2025-01-04 09:41:49 -07:00
parent fab6586e0c
commit 799cfa4303
36 changed files with 2094 additions and 6 deletions

View File

@ -9,7 +9,7 @@ public class OLSAnimation : ModuleRules
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"Core"
}
);
@ -21,7 +21,8 @@ public class OLSAnimation : ModuleRules
"Slate",
"SlateCore",
"AnimGraphRuntime",
"GameplayTags"
"GameplayTags",
"GameplayAbilities",
}
);
}

View File

@ -17,6 +17,22 @@
static TAutoConsoleVariable<bool> CVarAnimInstanceLocomotionDebug(TEXT("a.AnimInstance.Locomotion.Debug"), false, TEXT("Turn on visualization debugging for Locomotion"));
#endif
void UOLSBaseLayerAnimInstance::InitializeWithAbilitySystem(UAbilitySystemComponent* asc)
{
check(asc);
GameplayTagPropertyMap.Initialize(this, asc);
}
EDataValidationResult UOLSBaseLayerAnimInstance::IsDataValid(FDataValidationContext& context) const
{
Super::IsDataValid(context);
GameplayTagPropertyMap.IsDataValid(this, context);
return ((context.GetNumErrors() > 0) ? EDataValidationResult::Invalid : EDataValidationResult::Valid);
}
void UOLSBaseLayerAnimInstance::NativeInitializeAnimation()
{
// Super::NativeInitializeAnimation();

View File

@ -8,6 +8,7 @@
#include "Kismet/KismetMathLibrary.h"
#include "Data/OLSAnimationData.h"
#include "Data/OLSLocomotionData.h"
#include "GameplayEffectTypes.h"
#include "OLSBaseLayerAnimInstance.generated.h"
#if ENABLE_ANIM_DEBUG && ENABLE_VISUAL_LOG
@ -24,6 +25,16 @@ class OLSANIMATION_API UOLSBaseLayerAnimInstance : public UAnimInstance
{
GENERATED_BODY()
public:
virtual void InitializeWithAbilitySystem(class UAbilitySystemComponent* asc);
protected:
#if WITH_EDITOR
virtual EDataValidationResult IsDataValid(class FDataValidationContext& context) const override;
#endif // WITH_EDITOR
protected:
//~ Begin UAnimInstance overrides
@ -432,6 +443,14 @@ protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings")
FGameplayTag MeleeGameplayTag = FGameplayTag::EmptyTag;
protected:
// Gameplay tags that can be mapped to blueprint variables. The variables will automatically update as the tags are added or removed.
// These should be used instead of manually querying for the gameplay tags.
UPROPERTY(EditDefaultsOnly, Category = "GameplayTags")
FGameplayTagBlueprintPropertyMap GameplayTagPropertyMap;
protected:
UPROPERTY(BlueprintReadOnly)

View File

@ -15,7 +15,5 @@ public class OLSAnimationEditor : ModuleRules
PrivateDependencyModuleNames.AddRange(new string[] { "MessageLog" });
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Public/Nodes"));
}
}

View File

@ -0,0 +1,332 @@
// © 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/OLSAbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "GameplayCueManager.h"
#include "AbilitySystem/OLSBatchGameplayAbilityInterface.h"
#include "AbilitySystem/OLSGlobaAbilitySubsystem.h"
#include "AnimInstances/OLSBaseLayerAnimInstance.h"
// Sets default values for this component's properties
UOLSAbilitySystemComponent::UOLSAbilitySystemComponent()
{
static constexpr bool isReplicated = true;
SetIsReplicatedByDefault(isReplicated);
bShouldEnableBatchRPC = true;
}
void UOLSAbilitySystemComponent::InitAbilityActorInfo(AActor* ownerActor, AActor* avatarActor)
{
FGameplayAbilityActorInfo* actorInfo = AbilityActorInfo.Get();
check(actorInfo);
check(ownerActor);
// Guard condition to ensure we should clear/init for this new Avatar Actor.
const bool hasAvatarChanged = avatarActor && Cast<APawn>(avatarActor) && (avatarActor != actorInfo->AvatarActor);
Super::InitAbilityActorInfo(ownerActor, avatarActor);
// Apply the new defaults obtained from the owner's interface.
if (hasAvatarChanged)
{
if (const TObjectPtr<UOLSGlobaAbilitySubsystem> globalAbilitySystem = UWorld::GetSubsystem<UOLSGlobaAbilitySubsystem>(GetWorld()))
{
globalAbilitySystem->RegisterASC(this);
}
if (const TObjectPtr<UOLSBaseLayerAnimInstance> animInstance = Cast<UOLSBaseLayerAnimInstance>(GetAnimInstanceFromActorInfo()))
{
animInstance->InitializeWithAbilitySystem(this);
}
TryActivateAbilitiesOnSpawn();
}
}
bool UOLSAbilitySystemComponent::ShouldDoServerAbilityRPCBatch() const
{
return bShouldEnableBatchRPC;
}
float UOLSAbilitySystemComponent::PlayMontage(
UGameplayAbility* animatingAbility,
FGameplayAbilityActivationInfo activationInfo,
UAnimMontage* montage,
float playRate,
FName startSectionName,
float startTimeSeconds)
{
if (GEnableDefaultPlayMontage)
{
// Always useful to still allow the default flow, if there are some meaningful changes in the core system
// that were not yet reflect in this custom implementation. Can be enabled with CVar "GEnableDefaultPlayMontage".
//
return Super::PlayMontage(animatingAbility, activationInfo, montage, playRate, startSectionName, startTimeSeconds);
}
float duration = -1.f;
// This method was re-written just to ensure that the Animation Instance is retrieved from the Actor Info
// by default, but also, other scenarios can be supported. Biggest example being an IK Runtime Retarget.
//
// This virtual "GetAnimInstanceFromActorInfo" provides some flexibility on how the Anim Instance is
// retrieved. It can be extended in projects that should support IK Runtime Retargets and also traditional
// Anim Instances set in the Actor Info.
//
const TObjectPtr<UAnimInstance> animInstance = GetAnimInstanceFromActorInfo();
if (animInstance && montage)
{
duration = animInstance->Montage_Play(
montage,
playRate,
EMontagePlayReturnType::MontageLength,
startTimeSeconds);
if (duration > 0.f)
{
if (montage->HasRootMotion() && animInstance->GetOwningActor())
{
UE_LOG(LogRootMotion, Log, TEXT("UAbilitySystemComponent::PlayMontage %s, Role: %s")
, *GetNameSafe(montage)
, *UEnum::GetValueAsString(TEXT("Engine.ENetRole"), animInstance->GetOwningActor()->GetLocalRole())
);
}
LocalAnimMontageInfo.AnimMontage = montage;
LocalAnimMontageInfo.AnimatingAbility = animatingAbility;
LocalAnimMontageInfo.PlayInstanceId = (LocalAnimMontageInfo.PlayInstanceId < UINT8_MAX ? LocalAnimMontageInfo.PlayInstanceId + 1 : 0);
if (animatingAbility)
{
animatingAbility->SetCurrentMontage(montage);
}
// Start at a given Section.
if (startSectionName != NAME_None)
{
animInstance->Montage_JumpToSection(startSectionName, montage);
}
// Replicate for non-owners and for replay recordings
// The data we set from GetRepAnimMontageInfo_Mutable() is used both by the server to replicate to clients and by clients to record replays.
// We need to set this data for recording clients because there exists network configurations where an abilities montage data will not replicate to some clients (for example: if the client is an autonomous proxy.)
if (ShouldRecordMontageReplication())
{
FGameplayAbilityRepAnimMontage& mutableRepAnimMontageInfo = GetRepAnimMontageInfo_Mutable();
SetReplicatedMontageInfo(mutableRepAnimMontageInfo, montage, startSectionName);
// Update parameters that change during Montage lifetime.
AnimMontage_UpdateReplicatedData();
}
// Replicate to non-owners
if (IsOwnerActorAuthoritative())
{
// Force net update on our avatar actor.
if (AbilityActorInfo->AvatarActor != nullptr)
{
AbilityActorInfo->AvatarActor->ForceNetUpdate();
}
}
else
{
// If this prediction key is rejected, we need to end the preview
FPredictionKey predictionKey = GetPredictionKeyForNewAction();
if (predictionKey.IsValidKey())
{
predictionKey.NewRejectedDelegate().BindUObject(this, &ThisClass::OnPredictiveMontageRejected, montage);
}
}
}
}
return duration;
}
UAnimInstance* UOLSAbilitySystemComponent::GetAnimInstanceFromActorInfo() const
{
if (!AbilityActorInfo.IsValid())
{
return nullptr;
}
const FGameplayAbilityActorInfo* actorInfo = AbilityActorInfo.Get();
if (actorInfo->AnimInstance.IsValid() && actorInfo->AnimInstance->IsValidLowLevelFast())
{
// Return the one that was deliberately set in the Actor Info.
return actorInfo->AnimInstance.Get();
}
// Otherwise, let the getter method try to figure out the animation instance.
return actorInfo->GetAnimInstance();
}
FActiveGameplayEffectHandle UOLSAbilitySystemComponent::ApplyGameplayEffectClassToSelf(
TSubclassOf<UGameplayEffect> effectClass,
float level)
{
FActiveGameplayEffectHandle handle;
if (IsValid(effectClass))
{
FGameplayEffectContextHandle contextHandle = MakeEffectContext();
contextHandle.AddSourceObject(GetOwner());
const FGameplayEffectSpecHandle specHandle = MakeOutgoingSpec(effectClass, level, contextHandle);
if (specHandle.IsValid())
{
handle = ApplyGameplayEffectSpecToSelf(*specHandle.Data.Get());
//@Todo: replace this with our custom log.
UE_LOG(LogAbilitySystemComponent, Verbose, TEXT("[%s] Effect '%s' granted at level %f."),
*GetNameSafe(GetAvatarActor()), *GetNameSafe(effectClass), level);
}
}
return handle;
}
FGameplayAbilitySpecHandle UOLSAbilitySystemComponent::GiveAbilityFromClass(
const TSubclassOf<UGameplayAbility> abilityClass,
int32 level,
int32 input)
{
FGameplayAbilitySpecHandle handle;
if (IsValid(abilityClass))
{
const FGameplayAbilitySpec newAbilitySpec(FGameplayAbilitySpec(abilityClass, level, input, GetOwner()));
handle = GiveAbility(newAbilitySpec);
//@Todo: replace this with our custom log.
UE_LOG(LogAbilitySystemComponent, Log, TEXT("[%s] Ability '%s' %s at level %d."),
*GetNameSafe(GetAvatarActor()), *GetNameSafe(abilityClass),
handle.IsValid() ? TEXT("successfully granted") : TEXT("failed to be granted"), level);
}
return handle;
}
bool UOLSAbilitySystemComponent::TryBatchActivateAbility(
FGameplayAbilitySpecHandle abilityHandle,
bool shouldEndAbilityImmediately)
{
bool isAbilityActivated = false;
if (abilityHandle.IsValid())
{
//@Todo: replace this with our custom log.
// GAS_LOG(Warning, "Ability handle is invalid!");
return isAbilityActivated;
}
FScopedServerAbilityRPCBatcher batch(this, abilityHandle);
isAbilityActivated = TryActivateAbility(abilityHandle, true);
if (!shouldEndAbilityImmediately)
{
const FGameplayAbilitySpec* abilitySpec = FindAbilitySpecFromHandle(abilityHandle);
if (abilitySpec != nullptr)
{
UGameplayAbility* ability = abilitySpec->GetPrimaryInstance();
if (IsValid(ability) && ability->Implements<UOLSBatchGameplayAbilityInterface>())
{
IOLSBatchGameplayAbilityInterface::Execute_EndAbilityFromBatch(ability);
}
else
{
// @Todo: replace this with our custom log.
// const FString Message = IsValid(Ability) ? FString::Printf(TEXT("%s does not implement Batch Gameplay Ability Interface"), *GetNameSafe(Ability)) : "is invalid";
// GAS_LOG_ARGS(Error, "Ability %s!", *Message);
}
}
}
return isAbilityActivated;
}
void UOLSAbilitySystemComponent::CancelAbilitiesByTags(
FGameplayTagContainer abilityTags,
FGameplayTagContainer cancelFilterTags)
{
CancelAbilities(&abilityTags, &cancelFilterTags);
}
void UOLSAbilitySystemComponent::ExecuteGameplayCueLocal(
const FGameplayTag gameplayCueTag,
const FGameplayCueParameters& gameplayCueParameters) const
{
const TObjectPtr<UGameplayCueManager> cueManager = UAbilitySystemGlobals::Get().GetGameplayCueManager();
cueManager->HandleGameplayCue(
GetOwner(),
gameplayCueTag,
EGameplayCueEvent::Type::Executed,
gameplayCueParameters);
}
void UOLSAbilitySystemComponent::AddGameplayCueLocally(
const FGameplayTag gameplayCueTag,
const FGameplayCueParameters& gameplayCueParameters) const
{
const TObjectPtr<UGameplayCueManager> cueManager = UAbilitySystemGlobals::Get().GetGameplayCueManager();
cueManager->HandleGameplayCue(
GetOwner(),
gameplayCueTag,
EGameplayCueEvent::Type::OnActive,
gameplayCueParameters);
cueManager->HandleGameplayCue(
GetOwner(),
gameplayCueTag,
EGameplayCueEvent::Type::WhileActive,
gameplayCueParameters);
}
void UOLSAbilitySystemComponent::RemoveGameplayCueLocally(
const FGameplayTag gameplayCueTag,
const FGameplayCueParameters& gameplayCueParameters) const
{
const TObjectPtr<UGameplayCueManager> cueManager = UAbilitySystemGlobals::Get().GetGameplayCueManager();
cueManager->HandleGameplayCue(GetOwner(), gameplayCueTag, EGameplayCueEvent::Type::Removed, gameplayCueParameters);
}
void UOLSAbilitySystemComponent::TryActivateAbilitiesOnSpawn()
{
ABILITYLIST_SCOPE_LOCK();
for (const FGameplayAbilitySpec& abilitySpec : GetActivatableAbilities())
{
// if (const UOLS)
}
}
void UOLSAbilitySystemComponent::SetReplicatedMontageInfo(
FGameplayAbilityRepAnimMontage& mutableRepAnimMontageInfo,
UAnimMontage* newMontageToPlay,
const FName& startSectionName)
{
const uint8 playInstanceId = mutableRepAnimMontageInfo.PlayInstanceId < UINT8_MAX ? mutableRepAnimMontageInfo.PlayInstanceId + 1 : 0;
const uint8 sectionIdToPlay = newMontageToPlay->GetSectionIndex(startSectionName) + 1;
TObjectPtr<UAnimSequenceBase> animation = newMontageToPlay;
if (newMontageToPlay->IsDynamicMontage())
{
animation = newMontageToPlay->GetFirstAnimReference();
check(!newMontageToPlay->SlotAnimTracks.IsEmpty());
mutableRepAnimMontageInfo.SlotName = newMontageToPlay->SlotAnimTracks[0].SlotName;
mutableRepAnimMontageInfo.BlendOutTime = newMontageToPlay->GetDefaultBlendInTime();
}
mutableRepAnimMontageInfo.Animation = animation;
mutableRepAnimMontageInfo.PlayInstanceId = playInstanceId;
mutableRepAnimMontageInfo.SectionIdToPlay = 0;
if (mutableRepAnimMontageInfo.Animation && startSectionName != NAME_None)
{
mutableRepAnimMontageInfo.SectionIdToPlay = sectionIdToPlay;
}
}

View File

@ -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 "AbilitySystem/OLSBatchGameplayAbilityInterface.h"
// Add default functionality here for any IOLSBatchGameplayAbilityInterface functions that are not pure virtual.

View File

@ -0,0 +1,110 @@
// © 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/OLSGlobaAbilitySubsystem.h"
#include "Abilities/GameplayAbility.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
void FOLSGlobalAppliedAbilityList::AddToASC(TSubclassOf<UGameplayAbility> ability, UOLSAbilitySystemComponent* asc)
{
if (FGameplayAbilitySpecHandle* specHandle = Handles.Find(asc))
{
RemoveFromASC(asc);
}
UGameplayAbility* abilityCDO = ability->GetDefaultObject<UGameplayAbility>();
FGameplayAbilitySpec abilitySpec(abilityCDO);
const FGameplayAbilitySpecHandle abilitySpecHandle = asc->GiveAbility(abilitySpec);
Handles.Add(asc, abilitySpecHandle);
}
void FOLSGlobalAppliedAbilityList::RemoveFromASC(UOLSAbilitySystemComponent* asc)
{
if (FGameplayAbilitySpecHandle* specHandle = Handles.Find(asc))
{
asc->ClearAbility(*specHandle);
Handles.Remove(asc);
}
}
void FOLSGlobalAppliedAbilityList::RemoveFromAll()
{
for (TTuple<TObjectPtr<UOLSAbilitySystemComponent>, FGameplayAbilitySpecHandle>& handle : Handles)
{
if (handle.Key != nullptr)
{
handle.Key->ClearAbility(handle.Value);
}
}
Handles.Empty();
}
void FOLSGlobalAppliedEffectList::AddToASC(const TSubclassOf<UGameplayEffect>& effect, UOLSAbilitySystemComponent* asc)
{
if (FActiveGameplayEffectHandle* effectHandle = Handles.Find(asc))
{
RemoveFromASC(asc);
}
const UGameplayEffect* gameplayEffectCDO = effect->GetDefaultObject<UGameplayEffect>();
const FActiveGameplayEffectHandle gameplayEffectHandle = asc->ApplyGameplayEffectToSelf(gameplayEffectCDO, /*Level=*/ 1, asc->MakeEffectContext());
Handles.Add(asc, gameplayEffectHandle);
}
void FOLSGlobalAppliedEffectList::RemoveFromASC(UOLSAbilitySystemComponent* asc)
{
if (FActiveGameplayEffectHandle* effectHandle = Handles.Find(asc))
{
asc->RemoveActiveGameplayEffect(*effectHandle);
Handles.Remove(asc);
}
}
void FOLSGlobalAppliedEffectList::RemoveFromAll()
{
for (TTuple<TObjectPtr<UOLSAbilitySystemComponent>, FActiveGameplayEffectHandle>& handle : Handles)
{
if (handle.Key != nullptr)
{
handle.Key->RemoveActiveGameplayEffect(handle.Value);
}
}
Handles.Empty();
}
void UOLSGlobaAbilitySubsystem::RegisterASC(UOLSAbilitySystemComponent* asc)
{
check(asc);
for (TTuple<TSubclassOf<UGameplayAbility>, FOLSGlobalAppliedAbilityList>& appliedAbility : AppliedAbilities)
{
appliedAbility.Value.AddToASC(appliedAbility.Key, asc);
}
for (TTuple<TSubclassOf<UGameplayEffect>, FOLSGlobalAppliedEffectList>& appliedEffect : AppliedEffects)
{
appliedEffect.Value.AddToASC(appliedEffect.Key, asc);
}
RegisteredASCs.AddUnique(asc);
}
void UOLSGlobaAbilitySubsystem::UnregisterASC(UOLSAbilitySystemComponent* asc)
{
check(asc);
for (auto& appliedAbility : AppliedAbilities)
{
appliedAbility.Value.RemoveFromASC(asc);
}
for (auto& appliedEffect : AppliedEffects)
{
appliedEffect.Value.RemoveFromASC(asc);
}
RegisteredASCs.Remove(asc);
}

View File

@ -0,0 +1,24 @@
// © 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 "ModularGameplayActors/OLSModularAIController.h"
#include "Components/GameFrameworkComponentManager.h"
void AOLSModularAIController::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularAIController::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularAIController::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}

View File

@ -0,0 +1,100 @@
// © 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 "ModularGameplayActors/OLSModularActor.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Components/GameFrameworkComponentManager.h"
AOLSModularActor::AOLSModularActor(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Set this actor to replicate like a Pawn would
bReplicates = true;
// Set Ability System Companion with GAS Companion subclass
AbilitySystemComponent = CreateDefaultSubobject<UOLSAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
ReplicationMode = EGameplayEffectReplicationMode::Mixed;
}
void AOLSModularActor::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularActor::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularActor::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularActor::PostInitProperties()
{
Super::PostInitProperties();
if (AbilitySystemComponent)
{
//@Todo replace this log by our custom log.
UE_LOG(LogTemp, Verbose, TEXT("PostInitProperties for %s - Setting up ASC Replication Mode to: %d"), *GetName(), ReplicationMode);
AbilitySystemComponent->SetReplicationMode(ReplicationMode);
}
}
UAbilitySystemComponent* AOLSModularActor::GetAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
void AOLSModularActor::GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const
{
if (AbilitySystemComponent)
{
FGameplayTagContainer ownedTags;
AbilitySystemComponent->GetOwnedGameplayTags(ownedTags);
outTagContainer = MoveTemp(ownedTags);
}
}
bool AOLSModularActor::HasMatchingGameplayTag(FGameplayTag tagToCheck) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasMatchingGameplayTag(tagToCheck);
}
return false;
}
bool AOLSModularActor::HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAllMatchingGameplayTags(tagContainer);
}
return false;
}
bool AOLSModularActor::HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAnyMatchingGameplayTags(tagContainer);
}
return false;
}

View File

@ -0,0 +1,98 @@
// © 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 "ModularGameplayActors/OLSModularCharacter.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Components/GameFrameworkComponentManager.h"
AOLSModularCharacter::AOLSModularCharacter(const FObjectInitializer& objectInitializer)
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Set this actor to replicate like a Pawn would
bReplicates = true;
// Set Ability System Companion with GAS Companion subclass
AbilitySystemComponent = CreateDefaultSubobject<UOLSAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
ReplicationMode = EGameplayEffectReplicationMode::Mixed;
}
void AOLSModularCharacter::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularCharacter::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(
this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularCharacter::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularCharacter::PostInitProperties()
{
Super::PostInitProperties();
if (AbilitySystemComponent)
{
//@Todo replace this log by our custom log.
UE_LOG(LogTemp, Verbose, TEXT("PostInitProperties for %s - Setting up ASC Replication Mode to: %d"), *GetName(), ReplicationMode);
AbilitySystemComponent->SetReplicationMode(ReplicationMode);
}
}
UAbilitySystemComponent* AOLSModularCharacter::GetAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
void AOLSModularCharacter::GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const
{
if (AbilitySystemComponent)
{
FGameplayTagContainer ownedTags;
AbilitySystemComponent->GetOwnedGameplayTags(ownedTags);
outTagContainer = MoveTemp(ownedTags);
}
}
bool AOLSModularCharacter::HasMatchingGameplayTag(FGameplayTag tagToCheck) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasMatchingGameplayTag(tagToCheck);
}
return false;
}
bool AOLSModularCharacter::HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAllMatchingGameplayTags(tagContainer);
}
return false;
}
bool AOLSModularCharacter::HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAnyMatchingGameplayTags(tagContainer);
}
return false;
}

View File

@ -0,0 +1,100 @@
// © 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 "ModularGameplayActors/OLSModularDefaultPawn.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Components/GameFrameworkComponentManager.h"
// Sets default values
AOLSModularDefaultPawn::AOLSModularDefaultPawn(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Set this actor to replicate like a Pawn would
bReplicates = true;
// Set Ability System Companion with GAS Companion subclass
AbilitySystemComponent = CreateDefaultSubobject<UOLSAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
ReplicationMode = EGameplayEffectReplicationMode::Mixed;
}
void AOLSModularDefaultPawn::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularDefaultPawn::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(
this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularDefaultPawn::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularDefaultPawn::PostInitProperties()
{
Super::PostInitProperties();
if (AbilitySystemComponent)
{
//@Todo replace this log by our custom log.
UE_LOG(LogTemp, Verbose, TEXT("PostInitProperties for %s - Setting up ASC Replication Mode to: %d"), *GetName(),
ReplicationMode);
AbilitySystemComponent->SetReplicationMode(ReplicationMode);
}
}
UAbilitySystemComponent* AOLSModularDefaultPawn::GetAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
void AOLSModularDefaultPawn::GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const
{
if (AbilitySystemComponent)
{
FGameplayTagContainer ownedTags;
AbilitySystemComponent->GetOwnedGameplayTags(ownedTags);
outTagContainer = MoveTemp(ownedTags);
}
}
bool AOLSModularDefaultPawn::HasMatchingGameplayTag(FGameplayTag tagToCheck) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasMatchingGameplayTag(tagToCheck);
}
return false;
}
bool AOLSModularDefaultPawn::HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAllMatchingGameplayTags(tagContainer);
}
return false;
}
bool AOLSModularDefaultPawn::HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAnyMatchingGameplayTags(tagContainer);
}
return false;
}

View File

@ -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 "ModularGameplayActors/OLSModularGameMode.h"
AOLSModularGameModeBase::AOLSModularGameModeBase()
{
// GameStateClass = AGSCModularGameStateBase::StaticClass();
// PlayerControllerClass = AGSCModularPlayerController::StaticClass();
// PlayerStateClass = APlayerState::StaticClass();
// DefaultPawnClass = AGSCModularCharacter::StaticClass();
}
AOLSModularGameMode::AOLSModularGameMode()
{
// GameStateClass = AGSCModularGameState::StaticClass();
// PlayerControllerClass = AGSCModularPlayerController::StaticClass();
// PlayerStateClass = APlayerState::StaticClass();
// DefaultPawnClass = AGSCModularCharacter::StaticClass();
}

View File

@ -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.
#include "ModularGameplayActors/OLSModularGameState.h"
#include "Components/GameFrameworkComponentManager.h"
#include "Components/GameStateComponent.h"
void AOLSModularGameStateBase::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularGameStateBase::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularGameStateBase::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularGameState::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularGameState::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularGameState::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularGameState::HandleMatchHasStarted()
{
Super::HandleMatchHasStarted();
TArray<UGameStateComponent*> modularComponents;
GetComponents(modularComponents);
for (UGameStateComponent* component : modularComponents)
{
component->HandleMatchHasStarted();
}
}

View File

@ -0,0 +1,90 @@
// © 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 "ModularGameplayActors/OLSModularPawn.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Components/GameFrameworkComponentManager.h"
AOLSModularPawn::AOLSModularPawn(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
AbilitySystemComponent = CreateDefaultSubobject<UOLSAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
ReplicationMode = EGameplayEffectReplicationMode::Mixed;
}
void AOLSModularPawn::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularPawn::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularPawn::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularPawn::PostInitProperties()
{
Super::PostInitProperties();
if (AbilitySystemComponent)
{
//@Todo replace this log by our custom log.
UE_LOG(LogTemp, Verbose, TEXT("PostInitProperties for %s - Setting up ASC Replication Mode to: %d"), *GetName(), ReplicationMode);
AbilitySystemComponent->SetReplicationMode(ReplicationMode);
}
}
UAbilitySystemComponent* AOLSModularPawn::GetAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
void AOLSModularPawn::GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const
{
if (AbilitySystemComponent)
{
FGameplayTagContainer ownedTags;
AbilitySystemComponent->GetOwnedGameplayTags(ownedTags);
outTagContainer = MoveTemp(ownedTags);
}
}
bool AOLSModularPawn::HasMatchingGameplayTag(FGameplayTag tagToCheck) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasMatchingGameplayTag(tagToCheck);
}
return false;
}
bool AOLSModularPawn::HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAllMatchingGameplayTags(tagContainer);
}
return false;
}
bool AOLSModularPawn::HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent)
{
return AbilitySystemComponent->HasAnyMatchingGameplayTags(tagContainer);
}
return false;
}

View File

@ -0,0 +1,46 @@
// © 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 "ModularGameplayActors/OLSModularPlayerController.h"
#include "Components/GameFrameworkComponentManager.h"
#include "Components/ControllerComponent.h"
void AOLSModularPlayerController::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularPlayerController::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularPlayerController::ReceivedPlayer()
{
// Player controllers always get assigned a player and can't do much until then
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(
this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::ReceivedPlayer();
TArray<UControllerComponent*> modularComponents;
GetComponents(modularComponents);
for (UControllerComponent* component : modularComponents)
{
component->ReceivedPlayer();
}
}
void AOLSModularPlayerController::PlayerTick(float deltaTime)
{
Super::PlayerTick(deltaTime);
TArray<UControllerComponent*> modularComponents;
GetComponents(modularComponents);
for (UControllerComponent* component : modularComponents)
{
component->PlayerTick(deltaTime);
}
}

View File

@ -0,0 +1,80 @@
// © 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 "ModularGameplayActors/OLSModularPlayerState.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Components/GameFrameworkComponentManager.h"
#include "Components/PlayerStateComponent.h"
AOLSModularPlayerState::AOLSModularPlayerState(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
// Create ability system component, and set it to be explicitly replicated
AbilitySystemComponent = CreateDefaultSubobject<UOLSAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
AbilitySystemComponent->SetIsReplicated(true);
SetNetUpdateFrequency(100.f);
}
void AOLSModularPlayerState::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularPlayerState::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularPlayerState::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(EndPlayReason);
}
void AOLSModularPlayerState::PostInitProperties()
{
Super::PostInitProperties();
if (AbilitySystemComponent)
{
//@Todo replace this log by our custom log.
UE_LOG(LogTemp, Verbose, TEXT("PostInitProperties for %s - Setting up ASC Replication Mode to: %d"), *GetName(), ReplicationMode);
AbilitySystemComponent->SetReplicationMode(ReplicationMode);
}
}
void AOLSModularPlayerState::Reset()
{
Super::Reset();
TArray<UPlayerStateComponent*> modularComponents;
GetComponents(modularComponents);
for (UPlayerStateComponent* component : modularComponents)
{
component->Reset();
}
}
UAbilitySystemComponent* AOLSModularPlayerState::GetAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
void AOLSModularPlayerState::CopyProperties(APlayerState* playerState)
{
Super::CopyProperties(playerState);
TInlineComponentArray<UPlayerStateComponent*> playerStateComponents;
GetComponents(playerStateComponents);
for (UPlayerStateComponent* sourceComponent : playerStateComponents)
{
if (UPlayerStateComponent* targetComp = Cast<UPlayerStateComponent>(static_cast<UObject*>(FindObjectWithOuter(playerState, sourceComponent->GetClass(), sourceComponent->GetFName()))))
{
sourceComponent->CopyProperties(targetComp);
}
}
}

View File

@ -0,0 +1,121 @@
// © 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 "ModularGameplayActors/OLSModularPlayerStateCharacter.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "Components/GameFrameworkComponentManager.h"
#include "GameFramework/PlayerState.h"
AOLSModularPlayerStateCharacter::AOLSModularPlayerStateCharacter(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
SetMinNetUpdateFrequency(33.f);
SetNetUpdateFrequency(66.f);
ReplicationMode = EGameplayEffectReplicationMode::Mixed;
}
void AOLSModularPlayerStateCharacter::PreInitializeComponents()
{
Super::PreInitializeComponents();
UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}
void AOLSModularPlayerStateCharacter::BeginPlay()
{
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
Super::BeginPlay();
}
void AOLSModularPlayerStateCharacter::EndPlay(const EEndPlayReason::Type endPlayReason)
{
UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
Super::EndPlay(endPlayReason);
}
void AOLSModularPlayerStateCharacter::PostInitProperties()
{
Super::PostInitProperties();
if (AbilitySystemComponent.IsValid())
{
//@Todo replace this log by our custom log.
UE_LOG(LogTemp, Verbose, TEXT("PostInitProperties for %s - Setting up ASC Replication Mode to: %d"), *GetName(), ReplicationMode);
AbilitySystemComponent->SetReplicationMode(ReplicationMode);
}
}
void AOLSModularPlayerStateCharacter::PossessedBy(AController* newController)
{
Super::PossessedBy(newController);
// For Player State ASC Pawns, initialize ASC on server in PossessedBy
if (TObjectPtr<APlayerState> playerState = GetPlayerState())
{
AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(playerState);
if (AbilitySystemComponent.IsValid())
{
AbilitySystemComponent->InitAbilityActorInfo(playerState, this);
// TODO: Might consider sending GFC extension event in InitAbilityActorInfo instead
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(this, UGameFrameworkComponentManager::NAME_GameActorReady);
// Required for ability input binding to update itself when ability are granted again in case of a respawn
UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(playerState, UGameFrameworkComponentManager::NAME_GameActorReady);
}
}
}
void AOLSModularPlayerStateCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
}
UAbilitySystemComponent* AOLSModularPlayerStateCharacter::GetAbilitySystemComponent() const
{
if (AbilitySystemComponent.IsValid())
{
return AbilitySystemComponent.Get();
}
return nullptr;
}
void AOLSModularPlayerStateCharacter::GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const
{
if (AbilitySystemComponent.IsValid())
{
FGameplayTagContainer ownedTags;
AbilitySystemComponent->GetOwnedGameplayTags(ownedTags);
outTagContainer = MoveTemp(ownedTags);
}
}
bool AOLSModularPlayerStateCharacter::HasMatchingGameplayTag(FGameplayTag tagToCheck) const
{
if (AbilitySystemComponent.IsValid())
{
return AbilitySystemComponent->HasMatchingGameplayTag(tagToCheck);
}
return false;
}
bool AOLSModularPlayerStateCharacter::HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent.IsValid())
{
return AbilitySystemComponent->HasAllMatchingGameplayTags(tagContainer);
}
return false;
}
bool AOLSModularPlayerStateCharacter::HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const
{
if (AbilitySystemComponent.IsValid())
{
return AbilitySystemComponent->HasAnyMatchingGameplayTags(tagContainer);
}
return false;
}

View File

@ -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 "Player/OLSPlayerController.h"

View File

@ -0,0 +1,40 @@
// © 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 "Player/OLSPlayerState.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Player/OLSPlayerController.h"
AOLSPlayerState::AOLSPlayerState(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
// Create attribute sets here.
}
void AOLSPlayerState::PostInitializeComponents()
{
Super::PostInitializeComponents();
check(AbilitySystemComponent);
AbilitySystemComponent->InitAbilityActorInfo(this, GetPawn());
const TObjectPtr<UWorld> world = GetWorld();
if (world && world->IsGameWorld() && world->GetNetMode() != NM_Client)
{
const TObjectPtr<AGameStateBase> gameState = GetWorld()->GetGameState();
check(gameState);
// ULyraExperienceManagerComponent* ExperienceComponent = GameState->FindComponentByClass<ULyraExperienceManagerComponent>();
// check(ExperienceComponent);
// ExperienceComponent->CallOrRegister_OnExperienceLoaded(FOnLyraExperienceLoaded::FDelegate::CreateUObject(this, &ThisClass::OnExperienceLoaded));
}
}
AOLSPlayerController* AOLSPlayerState::GetOLSPlayerController() const
{
return Cast<AOLSPlayerController>(GetOwner());
}
UOLSAbilitySystemComponent* AOLSPlayerState::GetOLSAbilitySystemComponent() const
{
return AbilitySystemComponent;
}

View File

@ -0,0 +1,162 @@
// © 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 "AbilitySystemComponent.h"
#include "OLSAbilitySystemComponent.generated.h"
/**
* CVAR to control the "Play Montage" flow.
* Example: OLS.EnableDefaultPlayMontage true
*/
static bool GEnableDefaultPlayMontage = false;
static FAutoConsoleVariableRef CVarEnableDefaultPlayMontage(
TEXT("OLS.EnableDefaultPlayMontage"),
GEnableDefaultPlayMontage,
TEXT("Enables or disables the PlayMontage default behavior."),
ECVF_Default
);
UCLASS(ClassGroup=(OLS), meta=(BlueprintSpawnableComponent))
class OLS_API UOLSAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UOLSAbilitySystemComponent();
// -- Begin Ability System Component implementation
virtual void InitAbilityActorInfo(
AActor* ownerActor,
AActor* avatarActor) override;
virtual bool ShouldDoServerAbilityRPCBatch() const override;
virtual float PlayMontage(
UGameplayAbility* animatingAbility,
FGameplayAbilityActivationInfo activationInfo,
UAnimMontage* montage,
float playRate,
FName startSectionName,
float startTimeSeconds) override;
// -- End Ability System Component implementation
public:
/**
* Obtains the Anim Instance from the Actor Info.
*
* Takes into consideration the pointer in the Actor Info, before calling the
* Getter function that will always attempt to retrieve it from the mesh.
*/
UFUNCTION(BlueprintPure, Category = "OLS Ability System")
virtual UAnimInstance* GetAnimInstanceFromActorInfo() const;
/**
* Grants a new effect to the owner.
*
* @param effectClass Effect class being granted to the owner.
* @param level Initial level for the effect.
* @return The handle that can be used for maintenance.
*/
UFUNCTION(BlueprintCallable, Category = "OLS Ability System")
FActiveGameplayEffectHandle ApplyGameplayEffectClassToSelf(
TSubclassOf<UGameplayEffect> effectClass,
float level = 1);
/**
* Grants a new ability to the owner.
*
* @param abilityClass Ability class being granted to the owner.
* @param level Initial level for the ability.
* @param input An Input ID for the old input system.
* @return The handle that can be used for activation.
*/
UFUNCTION(BlueprintCallable, Category = "OLS Ability System")
FGameplayAbilitySpecHandle GiveAbilityFromClass(
const TSubclassOf<UGameplayAbility> abilityClass,
int32 level = 1,
int32 input = -1);
/**
* Tries to activate the ability by the handle, aggregating all RPCs that happened in the same frame.
*
* @param abilityHandle
* Handle used to identify the ability.
*
* @param shouldEndAbilityImmediately
* Determines if the EndAbility is triggered right away or later, with its own RPC. This requires the Ability
* to either implement IBatchGameplayAbilityInterface or be a subclass of NinjaGASGameplayAbility.
*/
UFUNCTION(BlueprintCallable, Category = "OLS Ability System")
virtual bool TryBatchActivateAbility(
FGameplayAbilitySpecHandle abilityHandle,
bool shouldEndAbilityImmediately);
/**
* Cancels Gameplay Abilities by their matching tags.
*
* @param abilityTags Gameplay Tags used to target abilities to cancel.
* @param cancelFilterTags A filter that excludes an ability from being cancelled.
*/
UFUNCTION(BlueprintCallable, Category = "OLS Ability System")
virtual void CancelAbilitiesByTags(
FGameplayTagContainer abilityTags,
FGameplayTagContainer cancelFilterTags);
/**
* Locally executes a <b>Static<b> Gameplay Cue.
*
* @param gameplayCueTag Gameplay Tag for the Gameplay Cue.
* @param gameplayCueParameters Parameters for the Gameplay Cue.
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "OLS Ability System", meta = (AutoCreateRefTerm = "GameplayCueParameters", GameplayTagFilter = "GameplayCue"))
void ExecuteGameplayCueLocal(
const FGameplayTag gameplayCueTag,
const FGameplayCueParameters& gameplayCueParameters) const;
/**
* Locally adds an <b>Actor<b> Gameplay Cue.
*
* When adding this Gameplay Cue locally, make sure to also remove it locally.
*
* @param gameplayCueTag Gameplay Tag for the Gameplay Cue.
* @param gameplayCueParameters Parameters for the Gameplay Cue.
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "OLS Ability System", meta = (AutoCreateRefTerm = "GameplayCueParameters"))
void AddGameplayCueLocally(
UPARAM(meta = (Categories = "GameplayCue")) const FGameplayTag gameplayCueTag,
const FGameplayCueParameters& gameplayCueParameters) const;
/**
* Locally removes an <b>Actor<b> Gameplay Cue.
*
* @param gameplayCueTag Gameplay Tag for the Gameplay Cue.
* @param gameplayCueParameters Parameters for the Gameplay Cue.
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "OLS Ability System", meta = (AutoCreateRefTerm = "GameplayCueParameters"))
void RemoveGameplayCueLocally(
UPARAM(meta = (Categories = "GameplayCue")) const FGameplayTag gameplayCueTag,
const FGameplayCueParameters& gameplayCueParameters) const;
protected:
/**
* Attempts to activate any abilities that are set to automatically trigger upon the actor's spawn.
* Typically used for gameplay abilities that need to be initialized or activated as soon as the actor is created.
*/
void TryActivateAbilitiesOnSpawn();
/**
* Conveniently separates the code that sets the animation to replicate, so it can be further modified.
*/
virtual void SetReplicatedMontageInfo(FGameplayAbilityRepAnimMontage& mutableRepAnimMontageInfo, UAnimMontage* newMontageToPlay, const FName& startSectionName);
private:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS Ability System", DisplayName = "Enable Ability Batch RPCs", meta = (AllowPrivateAccess = true))
uint8 bShouldEnableBatchRPC : 1 = true;
};

View File

@ -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 "UObject/Interface.h"
#include "OLSBatchGameplayAbilityInterface.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UOLSBatchGameplayAbilityInterface : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class OLS_API IOLSBatchGameplayAbilityInterface
{
GENERATED_BODY()
public:
/**
* Analogous to "K2_EndAbility" function, but exposed to identify that this is triggered by a batched RPC.
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "OLS | Batch Gameplay Ability")
void EndAbilityFromBatch();
};

View File

@ -0,0 +1,64 @@
// © 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 "Subsystems/WorldSubsystem.h"
#include "GameplayAbilitySpecHandle.h"
#include "ActiveGameplayEffectHandle.h"
#include "OLSGlobaAbilitySubsystem.generated.h"
USTRUCT()
struct FOLSGlobalAppliedAbilityList
{
GENERATED_BODY()
UPROPERTY()
TMap<TObjectPtr<class UOLSAbilitySystemComponent>, FGameplayAbilitySpecHandle> Handles;
void AddToASC(TSubclassOf<class UGameplayAbility> ability, class UOLSAbilitySystemComponent* asc);
void RemoveFromASC(class UOLSAbilitySystemComponent* asc);
void RemoveFromAll();
};
USTRUCT()
struct FOLSGlobalAppliedEffectList
{
GENERATED_BODY()
UPROPERTY()
TMap<TObjectPtr<class UOLSAbilitySystemComponent>, FActiveGameplayEffectHandle> Handles;
void AddToASC(const TSubclassOf<class UGameplayEffect>& effect, class UOLSAbilitySystemComponent* asc);
void RemoveFromASC(class UOLSAbilitySystemComponent* asc);
void RemoveFromAll();
};
/**
*
*/
UCLASS()
class OLS_API UOLSGlobaAbilitySubsystem : public UWorldSubsystem
{
GENERATED_BODY()
public:
/** Register an ASC with global system and apply any active global effects/abilities. */
void RegisterASC(class UOLSAbilitySystemComponent* asc);
/** Removes an ASC from the global system, along with any active global effects/abilities. */
void UnregisterASC(class UOLSAbilitySystemComponent* asc);
private:
UPROPERTY()
TMap<TSubclassOf<class UGameplayAbility>, FOLSGlobalAppliedAbilityList> AppliedAbilities;
UPROPERTY()
TMap<TSubclassOf<class UGameplayEffect>, FOLSGlobalAppliedEffectList> AppliedEffects;
UPROPERTY()
TArray<TObjectPtr<class UOLSAbilitySystemComponent>> RegisteredASCs;
};

View File

@ -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.
#pragma once
#include "AIController.h"
#include "OLSModularAIController.generated.h"
/**
*
*/
UCLASS(Blueprintable)
class OLS_API AOLSModularAIController : public AAIController
{
GENERATED_BODY()
public:
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
// -- End Actor Implementation
};

View File

@ -0,0 +1,62 @@
// © 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 "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "GameplayTagAssetInterface.h"
#include "GameFramework/Actor.h"
#include "OLSModularActor.generated.h"
/** Minimal class that supports extension by game feature plugins, direct child of AActor */
UCLASS(Blueprintable)
class OLS_API AOLSModularActor : public AActor, public IAbilitySystemInterface, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AOLSModularActor(const FObjectInitializer& objectInitializer);
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
virtual void PostInitProperties() override;
// -- End Actor Implementation
// -- Begin IAbilitySystemInterface implementation
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
// -- End IAbilitySystemInterface implementation
// -- Begin IGameplayTagAssetInterface
virtual void GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const override;
virtual bool HasMatchingGameplayTag(FGameplayTag tagToCheck) const override;
virtual bool HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
virtual bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
// -- End IGameplayTagAssetInterface
protected:
/**
* Ability System Replication Mode: How gameplay effects will be replicated to clients
*
* - Full: Replicate full gameplay info to all. Every GameplayEffect is replicated to every client.
* (Recommended for Single Player games)
* - Mixed: Only replicate minimal gameplay effect info to simulated proxies but full info to owners and autonomous proxies.
* GameplayEffects are only replicated to the owning client. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on Player controlled Actors)
* - Minimal: Only replicate minimal gameplay effect info. Note: this does not work for Owned AbilitySystemComponents (Use Mixed instead).
* GameplayEffects are never replicated to anyone. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on AI controlled Actors)
*
* @See https://github.com/tranek/GASDocumentation#concepts-asc-rm for more information
*/
UPROPERTY(EditDefaultsOnly, Category = "OLS Ability System")
EGameplayEffectReplicationMode ReplicationMode;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OLS Ability System")
TObjectPtr<class UOLSAbilitySystemComponent> AbilitySystemComponent = nullptr;
};

View File

@ -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 "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "GameplayTagAssetInterface.h"
#include "GameFramework/Character.h"
#include "OLSModularCharacter.generated.h"
/**
* Minimal class that supports extension by game feature plugins
*
* Intended to be used for ACharacters using AbilitySystemComponent living on Pawns
*/
UCLASS(Blueprintable)
class OLS_API AOLSModularCharacter : public ACharacter, public IAbilitySystemInterface, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AOLSModularCharacter(const FObjectInitializer& objectInitializer);
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
virtual void PostInitProperties() override;
// -- End Actor Implementation
// -- Begin IAbilitySystemInterface implementation
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
// -- End IAbilitySystemInterface implementation
// -- Begin IGameplayTagAssetInterface
virtual void GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const override;
virtual bool HasMatchingGameplayTag(FGameplayTag tagToCheck) const override;
virtual bool HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
virtual bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
// -- End IGameplayTagAssetInterface
protected:
/**
* Ability System Replication Mode: How gameplay effects will be replicated to clients
*
* - Full: Replicate full gameplay info to all. Every GameplayEffect is replicated to every client.
* (Recommended for Single Player games)
* - Mixed: Only replicate minimal gameplay effect info to simulated proxies but full info to owners and autonomous proxies.
* GameplayEffects are only replicated to the owning client. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on Player controlled Actors)
* - Minimal: Only replicate minimal gameplay effect info. Note: this does not work for Owned AbilitySystemComponents (Use Mixed instead).
* GameplayEffects are never replicated to anyone. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on AI controlled Actors)
*
* @See https://github.com/tranek/GASDocumentation#concepts-asc-rm for more information
*/
UPROPERTY(EditDefaultsOnly, Category = "OLS Ability System")
EGameplayEffectReplicationMode ReplicationMode;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OLS Ability System")
TObjectPtr<class UOLSAbilitySystemComponent> AbilitySystemComponent = nullptr;
};

View File

@ -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 "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "GameplayTagAssetInterface.h"
#include "GameFramework/DefaultPawn.h"
#include "OLSModularDefaultPawn.generated.h"
/** Minimal class that supports extension by game feature plugins, direct child of ADefaultPawn */
UCLASS(Blueprintable)
class OLS_API AOLSModularDefaultPawn : public ADefaultPawn, public IAbilitySystemInterface, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AOLSModularDefaultPawn(const FObjectInitializer& objectInitializer);
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
virtual void PostInitProperties() override;
// -- End Actor Implementation
// -- Begin IAbilitySystemInterface implementation
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
// -- End IAbilitySystemInterface implementation
// -- Begin IGameplayTagAssetInterface
virtual void GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const override;
virtual bool HasMatchingGameplayTag(FGameplayTag tagToCheck) const override;
virtual bool HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
virtual bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
// -- End IGameplayTagAssetInterface
protected:
/**
* Ability System Replication Mode: How gameplay effects will be replicated to clients
*
* - Full: Replicate full gameplay info to all. Every GameplayEffect is replicated to every client.
* (Recommended for Single Player games)
* - Mixed: Only replicate minimal gameplay effect info to simulated proxies but full info to owners and autonomous proxies.
* GameplayEffects are only replicated to the owning client. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on Player controlled Actors)
* - Minimal: Only replicate minimal gameplay effect info. Note: this does not work for Owned AbilitySystemComponents (Use Mixed instead).
* GameplayEffects are never replicated to anyone. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on AI controlled Actors)
*
* @See https://github.com/tranek/GASDocumentation#concepts-asc-rm for more information
*/
UPROPERTY(EditDefaultsOnly, Category = "OLS Ability System")
EGameplayEffectReplicationMode ReplicationMode;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OLS Ability System")
TObjectPtr<class UOLSAbilitySystemComponent> AbilitySystemComponent = nullptr;
};

View File

@ -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 "GameFramework/GameMode.h"
#include "GameFramework/GameModeBase.h"
#include "OLSModularGameMode.generated.h"
/** Pair this with a ModularGameStateBase */
UCLASS(Blueprintable)
class OLS_API AOLSModularGameModeBase : public AGameModeBase
{
GENERATED_BODY()
public:
AOLSModularGameModeBase();
};
/** Pair this with a ModularGameState */
UCLASS(Blueprintable)
class OLS_API AOLSModularGameMode : public AGameMode
{
GENERATED_BODY()
public:
AOLSModularGameMode();
};

View File

@ -0,0 +1,43 @@
// © 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 "GameFramework/GameState.h"
#include "OLSModularGameState.generated.h"
/** Pair this with a ModularGameModeBase */
UCLASS(Blueprintable)
class OLS_API AOLSModularGameStateBase : public AGameStateBase
{
GENERATED_BODY()
public:
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
// -- End Actor Implementation
};
/** Pair this with a ModularGameState */
UCLASS(Blueprintable)
class OLS_API AOLSModularGameState : public AGameState
{
GENERATED_BODY()
public:
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
// -- End Actor Implementation
protected:
// -- Begin Actor implementation
virtual void HandleMatchHasStarted() override;
// -- End Actor Implementation
};

View File

@ -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 "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "GameplayTagAssetInterface.h"
#include "GameFramework/Pawn.h"
#include "OLSModularPawn.generated.h"
/** Minimal class that supports extension by game feature plugins, direct child of APawn */
UCLASS(Blueprintable)
class OLS_API AOLSModularPawn : public APawn, public IAbilitySystemInterface, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AOLSModularPawn(const FObjectInitializer& objectInitializer);
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
virtual void PostInitProperties() override;
// -- End Actor Implementation
// -- Begin IAbilitySystemInterface implementation
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
// -- End IAbilitySystemInterface implementation
// -- Begin IGameplayTagAssetInterface
virtual void GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const override;
virtual bool HasMatchingGameplayTag(FGameplayTag tagToCheck) const override;
virtual bool HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
virtual bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
// -- End IGameplayTagAssetInterface
protected:
/**
* Ability System Replication Mode: How gameplay effects will be replicated to clients
*
* - Full: Replicate full gameplay info to all. Every GameplayEffect is replicated to every client.
* (Recommended for Single Player games)
* - Mixed: Only replicate minimal gameplay effect info to simulated proxies but full info to owners and autonomous proxies.
* GameplayEffects are only replicated to the owning client. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on Player controlled Actors)
* - Minimal: Only replicate minimal gameplay effect info. Note: this does not work for Owned AbilitySystemComponents (Use Mixed instead).
* GameplayEffects are never replicated to anyone. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on AI controlled Actors)
*
* @See https://github.com/tranek/GASDocumentation#concepts-asc-rm for more information
*/
UPROPERTY(EditDefaultsOnly, Category = "OLS Ability System")
EGameplayEffectReplicationMode ReplicationMode;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OLS Ability System")
TObjectPtr<class UOLSAbilitySystemComponent> AbilitySystemComponent = nullptr;
};

View File

@ -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 "GameFramework/PlayerController.h"
#include "OLSModularPlayerController.generated.h"
/** Minimal class that supports extension by game feature plugins */
UCLASS(Blueprintable)
class OLS_API AOLSModularPlayerController : public APlayerController
{
GENERATED_BODY()
public:
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
// -- End Actor implementation
// -- Begin APlayerController implementation
virtual void ReceivedPlayer() override;
virtual void PlayerTick(float deltaTime) override;
// -- End APlayerController implementation
};

View File

@ -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 "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "GameFramework/PlayerState.h"
#include "OLSModularPlayerState.generated.h"
/** Minimal class that supports extension by game feature plugins */
UCLASS(Blueprintable)
class OLS_API AOLSModularPlayerState : public APlayerState, public IAbilitySystemInterface
{
GENERATED_BODY()
public:
AOLSModularPlayerState(const FObjectInitializer& objectInitializer);
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void PostInitProperties() override;
virtual void Reset() override;
// -- End Actor implementation
// -- Begin IAbilitySystemInterface implementation
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
// -- End IAbilitySystemInterface implementation
protected:
// -- Begin APlayerState interface
virtual void CopyProperties(APlayerState* playerState) override;
// -- End APlayerState interface
protected:
/**
* Ability System Replication Mode: How gameplay effects will be replicated to clients
*
* - Full: Replicate full gameplay info to all. Every GameplayEffect is replicated to every client.
* (Recommended for Single Player games)
* - Mixed: Only replicate minimal gameplay effect info to simulated proxies but full info to owners and autonomous proxies.
* GameplayEffects are only replicated to the owning client. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on Player controlled Actors)
* - Minimal: Only replicate minimal gameplay effect info. Note: this does not work for Owned AbilitySystemComponents (Use Mixed instead).
* GameplayEffects are never replicated to anyone. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on AI controlled Actors)
*
* @See https://github.com/tranek/GASDocumentation#concepts-asc-rm for more information
*/
UPROPERTY(EditDefaultsOnly, Category = "OLS Ability System")
EGameplayEffectReplicationMode ReplicationMode;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OLS Ability System")
TObjectPtr<class UOLSAbilitySystemComponent> AbilitySystemComponent = nullptr;
};

View File

@ -0,0 +1,73 @@
// © 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 "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"
#include "GameplayTagAssetInterface.h"
#include "GameFramework/Character.h"
#include "OLSModularPlayerStateCharacter.generated.h"
/**
* Minimal class that supports extension by game feature plugins.
*
* Intended to be used for ACharacters using AbilitySystemComponent living on PlayerState.
*/
UCLASS(Blueprintable)
class OLS_API AOLSModularPlayerStateCharacter : public ACharacter, public IAbilitySystemInterface, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
AOLSModularPlayerStateCharacter(const FObjectInitializer& objectInitializer);
// -- Begin Actor implementation
virtual void PreInitializeComponents() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override;
virtual void PostInitProperties() override;
// -- End Actor implementation
// -- Begin APawn implementation
virtual void PossessedBy(AController* newController) override;
virtual void OnRep_PlayerState() override;
// -- End APawn implementation
// -- Begin IAbilitySystemInterface implementation
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
// -- End IAbilitySystemInterface implementation
// -- Begin IGameplayTagAssetInterface
virtual void GetOwnedGameplayTags(FGameplayTagContainer& outTagContainer) const override;
virtual bool HasMatchingGameplayTag(FGameplayTag tagToCheck) const override;
virtual bool HasAllMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
virtual bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& tagContainer) const override;
// -- End IGameplayTagAssetInterface
protected:
/**
* Ability System Replication Mode: How gameplay effects will be replicated to clients
*
* - Full: Replicate full gameplay info to all. Every GameplayEffect is replicated to every client.
* (Recommended for Single Player games)
* - Mixed: Only replicate minimal gameplay effect info to simulated proxies but full info to owners and autonomous proxies.
* GameplayEffects are only replicated to the owning client. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on Player controlled Actors)
* - Minimal: Only replicate minimal gameplay effect info. Note: this does not work for Owned AbilitySystemComponents (Use Mixed instead).
* GameplayEffects are never replicated to anyone. Only GameplayTags and GameplayCues are replicated to everyone.
* (Recommended for Multiplayer on AI controlled Actors)
*
* @See https://github.com/tranek/GASDocumentation#concepts-asc-rm for more information
*/
UPROPERTY(EditDefaultsOnly, Category = "OLS Ability System")
EGameplayEffectReplicationMode ReplicationMode;
protected:
// Cached AbilitySystemComponent. Real owner is PlayerState, but pointer gets updated to use PlayerState's here in PossessedBy / OnRep_PlayerState
TWeakObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
};

View File

@ -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 "ModularGameplayActors/OLSModularPlayerController.h"
#include "OLSPlayerController.generated.h"
/**
*
*/
UCLASS()
class OLS_API AOLSPlayerController : public AOLSModularPlayerController
{
GENERATED_BODY()
};

View File

@ -0,0 +1,35 @@
// © 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 "ModularGameplayActors/OLSModularPlayerState.h"
#include "OLSPlayerState.generated.h"
/**
* AOLSPlayerState
*
* Base player state class used by this project.
*/
UCLASS(Config = Game)
class OLS_API AOLSPlayerState : public AOLSModularPlayerState
{
GENERATED_BODY()
public:
AOLSPlayerState(const FObjectInitializer& objectInitializer);
//~ Begin AActor interface
virtual void PostInitializeComponents() override;
//~ End AActor interface
public:
UFUNCTION(BlueprintCallable, Category = "OLS|PlayerState")
class AOLSPlayerController* GetOLSPlayerController() const;
UFUNCTION(BlueprintCallable, Category = "OLS|PlayerState")
class UOLSAbilitySystemComponent* GetOLSAbilitySystemComponent() const;
};

View File

@ -16,10 +16,19 @@ public class ols : ModuleRules
"GameplayTags",
"GameplayTasks",
"GameplayAbilities",
"OLSAnimation",
"GameFeatures",
"ModularGameplay",
"EnhancedInput",
"OLSAnimation", "AIModule",
});
PrivateDependencyModuleNames.AddRange(new[] { "InputCore", "AnimGraphRuntime", "GameplayMessageRuntime" });
PrivateDependencyModuleNames.AddRange(new[]
{
"InputCore",
"AnimGraphRuntime",
"GameplayMessageRuntime",
"NetCore"
});
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

View File

@ -43,6 +43,14 @@
{
"Name": "GameplayAbilities",
"Enabled": true
},
{
"Name": "ModularGameplay",
"Enabled": true
},
{
"Name": "GameFeatures",
"Enabled": true
}
]
}