// Copyright Epic Games, Inc. All Rights Reserved. #include "LyraGlobalAbilitySystem.h" #include "Abilities/GameplayAbility.h" #include "AbilitySystem/LyraAbilitySystemComponent.h" #include "GameplayAbilitySpec.h" #include "GameplayEffect.h" #include "GameplayEffectTypes.h" #include "Misc/AssertionMacros.h" #include "Templates/ChooseClass.h" #include "Templates/Tuple.h" #include "Templates/TypeHash.h" void FGlobalAppliedAbilityList::AddToASC(TSubclassOf Ability, ULyraAbilitySystemComponent* ASC) { if (FGameplayAbilitySpecHandle* SpecHandle = Handles.Find(ASC)) { RemoveFromASC(ASC); } UGameplayAbility* AbilityCDO = Ability->GetDefaultObject(); FGameplayAbilitySpec AbilitySpec(AbilityCDO); const FGameplayAbilitySpecHandle AbilitySpecHandle = ASC->GiveAbility(AbilitySpec); Handles.Add(ASC, AbilitySpecHandle); } void FGlobalAppliedAbilityList::RemoveFromASC(ULyraAbilitySystemComponent* ASC) { if (FGameplayAbilitySpecHandle* SpecHandle = Handles.Find(ASC)) { ASC->ClearAbility(*SpecHandle); Handles.Remove(ASC); } } void FGlobalAppliedAbilityList::RemoveFromAll() { for (auto& KVP : Handles) { if (KVP.Key != nullptr) { KVP.Key->ClearAbility(KVP.Value); } } Handles.Empty(); } void FGlobalAppliedEffectList::AddToASC(TSubclassOf Effect, ULyraAbilitySystemComponent* ASC) { if (FActiveGameplayEffectHandle* EffectHandle = Handles.Find(ASC)) { RemoveFromASC(ASC); } const UGameplayEffect* GameplayEffectCDO = Effect->GetDefaultObject(); const FActiveGameplayEffectHandle GameplayEffectHandle = ASC->ApplyGameplayEffectToSelf(GameplayEffectCDO, /*Level=*/ 1, ASC->MakeEffectContext()); Handles.Add(ASC, GameplayEffectHandle); } void FGlobalAppliedEffectList::RemoveFromASC(ULyraAbilitySystemComponent* ASC) { if (FActiveGameplayEffectHandle* EffectHandle = Handles.Find(ASC)) { ASC->RemoveActiveGameplayEffect(*EffectHandle); Handles.Remove(ASC); } } void FGlobalAppliedEffectList::RemoveFromAll() { for (auto& KVP : Handles) { if (KVP.Key != nullptr) { KVP.Key->RemoveActiveGameplayEffect(KVP.Value); } } Handles.Empty(); } ULyraGlobalAbilitySystem::ULyraGlobalAbilitySystem() { } void ULyraGlobalAbilitySystem::ApplyAbilityToAll(TSubclassOf Ability) { if ((Ability.Get() != nullptr) && (!AppliedAbilities.Contains(Ability))) { FGlobalAppliedAbilityList& Entry = AppliedAbilities.Add(Ability); for (ULyraAbilitySystemComponent* ASC : RegisteredASCs) { Entry.AddToASC(Ability, ASC); } } } void ULyraGlobalAbilitySystem::ApplyEffectToAll(TSubclassOf Effect) { if ((Effect.Get() != nullptr) && (!AppliedEffects.Contains(Effect))) { FGlobalAppliedEffectList& Entry = AppliedEffects.Add(Effect); for (ULyraAbilitySystemComponent* ASC : RegisteredASCs) { Entry.AddToASC(Effect, ASC); } } } void ULyraGlobalAbilitySystem::RemoveAbilityFromAll(TSubclassOf Ability) { if ((Ability.Get() != nullptr) && AppliedAbilities.Contains(Ability)) { FGlobalAppliedAbilityList& Entry = AppliedAbilities[Ability]; Entry.RemoveFromAll(); AppliedAbilities.Remove(Ability); } } void ULyraGlobalAbilitySystem::RemoveEffectFromAll(TSubclassOf Effect) { if ((Effect.Get() != nullptr) && AppliedEffects.Contains(Effect)) { FGlobalAppliedEffectList& Entry = AppliedEffects[Effect]; Entry.RemoveFromAll(); AppliedEffects.Remove(Effect); } } void ULyraGlobalAbilitySystem::RegisterASC(ULyraAbilitySystemComponent* ASC) { check(ASC); for (auto& Entry : AppliedAbilities) { Entry.Value.AddToASC(Entry.Key, ASC); } for (auto& Entry : AppliedEffects) { Entry.Value.AddToASC(Entry.Key, ASC); } RegisteredASCs.AddUnique(ASC); } void ULyraGlobalAbilitySystem::UnregisterASC(ULyraAbilitySystemComponent* ASC) { check(ASC); for (auto& Entry : AppliedAbilities) { Entry.Value.RemoveFromASC(ASC); } for (auto& Entry : AppliedEffects) { Entry.Value.RemoveFromASC(ASC); } RegisteredASCs.Remove(ASC); }