44. Infinite Effect Application and Removal
This commit is contained in:
		
							
								
								
									
										
											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.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Project/Content/Core/AbilitySystem/GE_AreaFire.uasset
									 (Stored with Git LFS)
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Project/Content/Core/AbilitySystem/GE_AreaFire.uasset
									 (Stored with Git LFS)
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Project/Content/Core/BP_AreaFire_RawEffect.uasset
									 (Stored with Git LFS)
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Project/Content/Core/BP_AreaFire_RawEffect.uasset
									 (Stored with Git LFS)
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Project/Content/Levels/StartupMap.umap
									 (Stored with Git LFS)
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Project/Content/Levels/StartupMap.umap
									 (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 ); | ||||
| 	FGameplayEffectSpecHandle   Spec         = AS->MakeOutgoingSpec( EffectClass, 1.0f, Context ); | ||||
| 	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 (InstantEffectClass && InstantEffectUsage == EInstantEffectUsagePolicy::ApplyOnOverlap) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::ApplyOnOverlap)) | ||||
| 		{ | ||||
|         	FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context ); | ||||
|         	AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );	 | ||||
| 		} | ||||
| 		if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap)) | ||||
| 		{ | ||||
|         	AS->RemoveActiveGameplayEffectBySourceEffect( InstantEffectClass, AS ); | ||||
| 		} | ||||
| 		FGameplayEffectSpecHandle Spec= AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context ); | ||||
| 		AS->ApplyGameplayEffectSpecToSelf( * Spec.Data ); | ||||
| 	} | ||||
| 	if (DurationEffectClass.Get()) | ||||
| 	if (DurationEffectClass) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::ApplyOnOverlap)) | ||||
| 		if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::ApplyOnOverlap)) | ||||
| 		{ | ||||
|         	FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context ); | ||||
|         	AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );	 | ||||
| 		} | ||||
| 		if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap)) | ||||
| 		{ | ||||
|         	AS->RemoveActiveGameplayEffectBySourceEffect( DurationEffectClass, AS ); | ||||
|         	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 (InfiniteEffectClass.Get()) | ||||
| 	if (InfiniteEffectClass) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(InfiniteEffectUsage, (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( 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 (InstantEffectClass && InstantEffectUsage == EInstantEffectUsagePolicy::ApplyOnEndOverlap) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::ApplyOnEndOverlap)) | ||||
| 		FGameplayEffectSpecHandle Spec= AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context ); | ||||
| 		AS->ApplyGameplayEffectSpecToSelf( * Spec.Data ); | ||||
| 	} | ||||
| 	if (DurationEffectClass) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::ApplyOnEndOverlap)) | ||||
| 		{ | ||||
| 			FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context ); | ||||
| 			AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );	 | ||||
| 			FGameplayEffectSpecHandle   Spec         = AS->MakeOutgoingSpec( DurationEffectClass, 1.0f, Context ); | ||||
| 			FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data ); | ||||
| 			if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::RemoveOnOverlap)) | ||||
| 				ActiveDuration = ActiveEffect; | ||||
| 		} | ||||
| 		if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap)) | ||||
| 		if (ActiveDuration.IsValid() && Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap)) | ||||
| 			AS->RemoveActiveGameplayEffect(ActiveDuration); | ||||
| 	} | ||||
| 	if (InfiniteEffectClass) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::ApplyOnEndOverlap)) | ||||
| 		{ | ||||
| 			AS->RemoveActiveGameplayEffectBySourceEffect( InstantEffectClass, 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 (ActiveInfinite.IsValid() && Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnEndOverlap)) | ||||
| 		{ | ||||
| 			if (ActiveInfinite.IsValid()) | ||||
| 				AS->RemoveActiveGameplayEffect(ActiveInfinite); | ||||
| 		} | ||||
| 	} | ||||
| 	if (DurationEffectClass.Get()) | ||||
|  | ||||
| 	TArray<FActiveGameplayEffectHandle> EffectsRemoved; | ||||
| 	for (ActiveEffectEntry ActiveEffect : ActiveEffectsToRemove) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(DurationEffectUsage, (int32)EEffectUsagePolicy::ApplyOnEndOverlap)) | ||||
| 		{ | ||||
| 			FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InstantEffectClass, 1.0f, Context ); | ||||
| 			AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );	 | ||||
| 		} | ||||
| 		if (Bitfield_IsSet(InstantEffectUsage, (int32)EEffectUsagePolicy::RemoveOnEndOverlap)) | ||||
| 		{ | ||||
| 			AS->RemoveActiveGameplayEffectBySourceEffect( DurationEffectClass, AS ); | ||||
| 		} | ||||
| 	} | ||||
| 	if (InfiniteEffectClass.Get()) | ||||
| 	{ | ||||
| 		if (Bitfield_IsSet(InfiniteEffectUsage, (int32)EEffectUsagePolicy::ApplyOnEndOverlap)) | ||||
| 		{ | ||||
| 			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; | ||||
| 	 | ||||
| 	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects") | ||||
| 	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); | ||||
| 	} | ||||
| } | ||||
| 	 | ||||
		Reference in New Issue
	
	Block a user