// Copyright Epic Games, Inc. All Rights Reserved. #include "LyraGameplayAbility_Death.h" #include "Abilities/GameplayAbility.h" #include "Abilities/GameplayAbilityTypes.h" #include "AbilitySystem/Abilities/LyraGameplayAbility.h" #include "AbilitySystem/LyraAbilitySystemComponent.h" #include "AbilitySystemComponent.h" #include "Character/LyraHealthComponent.h" #include "Containers/Array.h" #include "Containers/EnumAsByte.h" #include "Containers/UnrealString.h" #include "Delegates/Delegate.h" #include "GameplayTagContainer.h" #include "GameplayTagsManager.h" #include "HAL/Platform.h" #include "Logging/LogCategory.h" #include "Logging/LogMacros.h" #include "LyraGameplayTags.h" #include "LyraLogChannels.h" #include "Misc/AssertionMacros.h" #include "Templates/Casts.h" #include "Trace/Detail/Channel.h" #include "UObject/WeakObjectPtr.h" #include "UObject/WeakObjectPtrTemplates.h" ULyraGameplayAbility_Death::ULyraGameplayAbility_Death(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor; NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerInitiated; bAutoStartDeath = true; UGameplayTagsManager::Get().CallOrRegister_OnDoneAddingNativeTagsDelegate(FSimpleDelegate::CreateUObject(this, &ThisClass::DoneAddingNativeTags)); } void ULyraGameplayAbility_Death::DoneAddingNativeTags() { if (HasAnyFlags(RF_ClassDefaultObject)) { // Add the ability trigger tag as default to the CDO. FAbilityTriggerData TriggerData; TriggerData.TriggerTag = FLyraGameplayTags::Get().GameplayEvent_Death; TriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent; AbilityTriggers.Add(TriggerData); } } void ULyraGameplayAbility_Death::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) { check(ActorInfo); ULyraAbilitySystemComponent* LyraASC = CastChecked(ActorInfo->AbilitySystemComponent.Get()); FGameplayTagContainer AbilityTypesToIgnore; AbilityTypesToIgnore.AddTag(FLyraGameplayTags::Get().Ability_Behavior_SurvivesDeath); // Cancel all abilities and block others from starting. LyraASC->CancelAbilities(nullptr, &AbilityTypesToIgnore, this); SetCanBeCanceled(false); if (!ChangeActivationGroup(ELyraAbilityActivationGroup::Exclusive_Blocking)) { UE_LOG(LogLyraAbilitySystem, Error, TEXT("ULyraGameplayAbility_Death::ActivateAbility: Ability [%s] failed to change activation group to blocking."), *GetName()); } if (bAutoStartDeath) { StartDeath(); } Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData); } void ULyraGameplayAbility_Death::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) { check(ActorInfo); // Always try to finish the death when the ability ends in case the ability doesn't. // This won't do anything if the death hasn't been started. FinishDeath(); Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled); } void ULyraGameplayAbility_Death::StartDeath() { if (ULyraHealthComponent* HealthComponent = ULyraHealthComponent::FindHealthComponent(GetAvatarActorFromActorInfo())) { if (HealthComponent->GetDeathState() == ELyraDeathState::NotDead) { HealthComponent->StartDeath(); } } } void ULyraGameplayAbility_Death::FinishDeath() { if (ULyraHealthComponent* HealthComponent = ULyraHealthComponent::FindHealthComponent(GetAvatarActorFromActorInfo())) { if (HealthComponent->GetDeathState() == ELyraDeathState::DeathStarted) { HealthComponent->FinishDeath(); } } }