44. Infinite Effect Application and Removal
This commit is contained in:
parent
caae7fd758
commit
a218d86c23
BIN
Project/Binaries/Win64/UnrealEditor-GasaEditor.dll
(Stored with Git LFS)
BIN
Project/Binaries/Win64/UnrealEditor-GasaEditor.dll
(Stored with Git LFS)
Binary file not shown.
@ -1,6 +1,7 @@
|
||||
#include "GasaEffectActor.h"
|
||||
|
||||
#include "GasaAbilitySystemComponent_Inlines.h"
|
||||
#include "GasaContainers.h"
|
||||
using namespace Gasa;
|
||||
|
||||
AGasaEffectActor::AGasaEffectActor()
|
||||
@ -9,21 +10,24 @@ AGasaEffectActor::AGasaEffectActor()
|
||||
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>("Root");
|
||||
|
||||
InstantEffectUsage = DefaultEffectUsagePolicy;
|
||||
InstantEffectUsage = EInstantEffectUsagePolicy::DoNotApply;
|
||||
DurationEffectUsage = DefaultEffectUsagePolicy;
|
||||
InfiniteEffectUsage = DefaultEffectUsagePolicy;
|
||||
|
||||
bDestroyOnEffectRemoval = false;
|
||||
}
|
||||
|
||||
void AGasaEffectActor::ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass)
|
||||
void AGasaEffectActor::ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass, bool bRemoveOnEndOverlap)
|
||||
{
|
||||
UGasaAbilitySystemComp* AS = GetAbilitySystem(Actor, true);
|
||||
|
||||
FGameplayEffectContextHandle
|
||||
Context = AS->MakeEffectContext();
|
||||
Context.AddSourceObject(Actor);
|
||||
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( EffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
if (bRemoveOnEndOverlap)
|
||||
ActiveEffectsToRemove.Add(ActiveEffect, AS);
|
||||
}
|
||||
|
||||
void AGasaEffectActor::OnOverlap(AActor* Actor)
|
||||
@ -33,40 +37,37 @@ void AGasaEffectActor::OnOverlap(AActor* Actor)
|
||||
Context = AS->MakeEffectContext();
|
||||
Context.AddSourceObject(Actor);
|
||||
|
||||
if (InstantEffectClass.Get())
|
||||
{
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::ApplyOnOverlap))
|
||||
if (InstantEffectClass && InstantEffectUsage == EInstantEffectUsagePolicy::ApplyOnOverlap)
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec= AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
}
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap))
|
||||
if (DurationEffectClass)
|
||||
{
|
||||
AS->RemoveActiveGameplayEffectBySourceEffect( InstantEffectClass, AS );
|
||||
if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::ApplyOnOverlap))
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( DurationEffectClass, 1.0f, Context );
|
||||
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
ActiveDuration = ActiveEffect;
|
||||
}
|
||||
if (ActiveDuration.IsValid() && Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::RemoveOnOverlap))
|
||||
AS->RemoveActiveGameplayEffect(ActiveDuration);
|
||||
}
|
||||
if (DurationEffectClass.Get())
|
||||
if (InfiniteEffectClass)
|
||||
{
|
||||
if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::ApplyOnOverlap))
|
||||
bool bApplyOnOverlap = Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::ApplyOnOverlap);
|
||||
if (bApplyOnOverlap)
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InfiniteEffectClass, 1.0f, Context );
|
||||
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
if (Bitfield_IsSet(InfiniteEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
ActiveInfinite = ActiveEffect;
|
||||
}
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap))
|
||||
if (ActiveInfinite.IsValid() && Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnOverlap))
|
||||
{
|
||||
AS->RemoveActiveGameplayEffectBySourceEffect( DurationEffectClass, AS );
|
||||
}
|
||||
}
|
||||
if (InfiniteEffectClass.Get())
|
||||
{
|
||||
if (Bitfield_IsSet(InfiniteEffectUsage, (int32)EEffectUsagePolicy::ApplyOnOverlap))
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
}
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap))
|
||||
{
|
||||
AS->RemoveActiveGameplayEffectBySourceEffect( InfiniteEffectClass, AS );
|
||||
if (ActiveInfinite.IsValid())
|
||||
AS->RemoveActiveGameplayEffect(ActiveInfinite);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,40 +79,46 @@ void AGasaEffectActor::OnEndOverlap(AActor* Actor)
|
||||
Context = AS->MakeEffectContext();
|
||||
Context.AddSourceObject(Actor);
|
||||
|
||||
if (InstantEffectClass.Get())
|
||||
{
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::ApplyOnEndOverlap))
|
||||
if (InstantEffectClass && InstantEffectUsage == EInstantEffectUsagePolicy::ApplyOnEndOverlap)
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec= AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
}
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
if (DurationEffectClass)
|
||||
{
|
||||
AS->RemoveActiveGameplayEffectBySourceEffect( InstantEffectClass, AS );
|
||||
}
|
||||
}
|
||||
if (DurationEffectClass.Get())
|
||||
if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::ApplyOnEndOverlap))
|
||||
{
|
||||
if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::ApplyOnEndOverlap))
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( DurationEffectClass, 1.0f, Context );
|
||||
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap))
|
||||
ActiveDuration = ActiveEffect;
|
||||
}
|
||||
if (ActiveDuration.IsValid() && Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
AS->RemoveActiveGameplayEffect(ActiveDuration);
|
||||
}
|
||||
if (InfiniteEffectClass)
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
}
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
if (Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::ApplyOnEndOverlap))
|
||||
{
|
||||
AS->RemoveActiveGameplayEffectBySourceEffect( DurationEffectClass, AS );
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InfiniteEffectClass, 1.0f, Context );
|
||||
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
if (Bitfield_IsSet(InfiniteEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap))
|
||||
ActiveInfinite = ActiveEffect;
|
||||
}
|
||||
}
|
||||
if (InfiniteEffectClass.Get())
|
||||
if (ActiveInfinite.IsValid() && Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
{
|
||||
if (Bitfield_IsSet(InfiniteEffectUsage, (int32)EEffectUsagePolicy::ApplyOnEndOverlap))
|
||||
if (ActiveInfinite.IsValid())
|
||||
AS->RemoveActiveGameplayEffect(ActiveInfinite);
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FActiveGameplayEffectHandle> EffectsRemoved;
|
||||
for (ActiveEffectEntry ActiveEffect : ActiveEffectsToRemove)
|
||||
{
|
||||
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context );
|
||||
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
|
||||
}
|
||||
if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap))
|
||||
{
|
||||
AS->RemoveActiveGameplayEffectBySourceEffect( InfiniteEffectClass, AS );
|
||||
}
|
||||
if (ActiveEffect.Value != AS)
|
||||
continue;
|
||||
AS->RemoveActiveGameplayEffect(ActiveEffect.Key, 1);
|
||||
EffectsRemoved.Add(ActiveEffect.Key);
|
||||
}
|
||||
RemoveKeys(ActiveEffectsToRemove, EffectsRemoved);
|
||||
}
|
||||
|
@ -2,18 +2,29 @@
|
||||
|
||||
#include "GasaCommon.h"
|
||||
#include "Actors/GasaActor.h"
|
||||
#include "ActiveGameplayEffectHandle.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "GasaEffectActor.generated.h"
|
||||
|
||||
struct FActiveGameplayEffectHandle;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EInstantEffectUsagePolicy : uint8
|
||||
{
|
||||
DoNotApply,
|
||||
ApplyOnOverlap,
|
||||
ApplyOnEndOverlap,
|
||||
};
|
||||
|
||||
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
|
||||
enum class EEffectUsagePolicy : uint8
|
||||
{
|
||||
None = 0 UMETA(Hidden),
|
||||
ApplyOnOverlap = bit(0),
|
||||
ApplyOnEndOverlap = bit(1),
|
||||
RemoveOnOverlap = bit(3),
|
||||
RemoveOnEndOverlap = bit(4),
|
||||
RemoveOnOverlap = bit(2),
|
||||
RemoveOnEndOverlap = bit(3),
|
||||
};
|
||||
|
||||
constexpr int32 DefaultEffectUsagePolicy = (int32(EEffectUsagePolicy::RemoveOnEndOverlap));
|
||||
@ -27,28 +38,34 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
|
||||
TSubclassOf<UGameplayEffect> InstantEffectClass;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = EEffectUsagePolicy))
|
||||
int32 InstantEffectUsage;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
|
||||
EInstantEffectUsagePolicy InstantEffectUsage;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
|
||||
TSubclassOf<UGameplayEffect> DurationEffectClass;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = EEffectUsagePolicy))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = "/Script/Gasa.EEffectUsagePolicy"))
|
||||
int32 DurationEffectUsage;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
|
||||
TSubclassOf<UGameplayEffect> InfiniteEffectClass;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = EEffectUsagePolicy))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = "/Script/Gasa.EEffectUsagePolicy"))
|
||||
int32 InfiniteEffectUsage;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
|
||||
bool bDestroyOnEffectRemoval = false;
|
||||
bool bDestroyOnEffectRemoval;
|
||||
|
||||
TMap<FActiveGameplayEffectHandle, UAbilitySystemComponent*> ActiveEffectsToRemove;
|
||||
using ActiveEffectEntry = TTuple<FActiveGameplayEffectHandle, UAbilitySystemComponent*>;
|
||||
|
||||
FActiveGameplayEffectHandle ActiveDuration;
|
||||
FActiveGameplayEffectHandle ActiveInfinite;
|
||||
|
||||
AGasaEffectActor();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Gameplay Effects")
|
||||
void ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass );
|
||||
void ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass, bool bRemoveOnEndOverlap = false);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void OnOverlap(AActor* Actor);
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework")
|
||||
EGameFrameworkState GameFrameworkState;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework", meta=(Bitmask, BitmaskEnum = EGameFrameworkClassFlag))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework", meta=(Bitmask, BitmaskEnum = "/Script/Gasa.EGameFrameworkClassFlag"))
|
||||
int32 GameFrameworkClassesState;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="GameFramework")
|
||||
|
@ -80,13 +80,30 @@ namespace Gasa
|
||||
{
|
||||
inline
|
||||
bool Bitfield_IsSet(int32 Bitfield, int32 Bitmask) {
|
||||
int32 Result = Bitmask == (Bitfield & Bitmask);
|
||||
return scast(bool, Result);
|
||||
bool Result = Bitmask == (Bitfield & Bitmask);
|
||||
return Result;
|
||||
}
|
||||
inline
|
||||
bool Bitfield_IsSetExactly(int32 Bitfield, int32 Bitmask)
|
||||
{
|
||||
bool Result = Bitfield == (Bitfield & Bitmask);
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline void Bitfield_Set ( int32& Bitfield, int32 BitsToAdd ) { Bitfield |= BitsToAdd; }
|
||||
inline void Bitfield_Remove( int32& Bitfield, int32 BitsToRemove ) { Bitfield &= (! BitsToRemove); }
|
||||
inline void Bitfield_Toggle( int32& Bitfield, int32 Bitmask ) { Bitfield ^= Bitmask; }
|
||||
|
||||
template<typename EnumType>
|
||||
inline
|
||||
bool Bitfield_IsSet(int32 Bitfield, EnumType Mask)
|
||||
{
|
||||
bool Result = int32(Mask) == (Bitfield & int32(Mask));
|
||||
return Result;
|
||||
}
|
||||
template<typename EnumType> inline void Bitfield_Set ( int32& Bitfield, EnumType BitToAdd ) { Bitfield |= int32(BitToAdd); }
|
||||
template<typename EnumType> inline void Bitfield_Remove( int32& Bitfield, EnumType BitToRemove ) { Bitfield &= (! int32(BitToRemove)); }
|
||||
template<typename EnumType> inline void Bitfield_Toggle( int32& Bitfield, EnumType BitToToggle ) { Bitfield ^= int32(BitToToggle); }
|
||||
}
|
||||
#pragma endregion Bitfields
|
||||
|
||||
|
0
Project/Source/Gasa/GasaContainers.cpp
Normal file
0
Project/Source/Gasa/GasaContainers.cpp
Normal file
14
Project/Source/Gasa/GasaContainers.h
Normal file
14
Project/Source/Gasa/GasaContainers.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "GasaCommon.h"
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
inline
|
||||
void RemoveKeys(TMap<KeyType, ValueType> Map, TArray<KeyType> Keys)
|
||||
{
|
||||
for (KeyType& Key : Keys )
|
||||
{
|
||||
Map.Remove(Key);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user