├── .gitignore ├── Ability.uplugin ├── Config └── FilterPlugin.ini ├── Content └── Ability │ └── AbilitySystem │ ├── BP_GameplayEffectVolume.uasset │ ├── BP_GameplayEventNotify.uasset │ └── GameplayAbilityUtils.uasset ├── LICENSE ├── README.md ├── Resources ├── AbilityPlugin_Designs.afdesign ├── Export │ ├── Ability128_Icon.png │ ├── Ability_Logo.png │ ├── Ability_SocialPreview.png │ └── Ability_WhiteLogo.png └── Icon128.png └── Source └── Ability ├── Ability.Build.cs ├── Private ├── Ability.cpp ├── Character │ ├── Abilities │ │ ├── AsyncTaskGameplayTagAddedRemoved.cpp │ │ ├── GASAbilityTypes.cpp │ │ ├── GASGameplayAbility.cpp │ │ ├── GASGameplayEffectTypes.cpp │ │ └── GASTargetType.cpp │ ├── AbilityInputBindingComponent.cpp │ ├── GameplayAbilitySystemComponent.cpp │ └── PlayerControlsComponent.cpp ├── GASAssetManager.cpp ├── GASBlueprintLibrary.cpp └── GASEngineSubsystem.cpp └── Public ├── Ability.h ├── Character ├── Abilities │ ├── AsyncTaskGameplayTagAddedRemoved.h │ ├── GASAbilityTypes.h │ ├── GASGameplayAbility.h │ ├── GASGameplayEffectTypes.h │ └── GASTargetType.h ├── AbilityInputBindingComponent.h ├── GameplayAbilitySystemComponent.h └── PlayerControlsComponent.h ├── GASAssetManager.h ├── GASBlueprintLibrary.h └── GASEngineSubsystem.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | 4 | # Rider for Unreal Engine user specific files 5 | .idea/ 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | 25 | # Compiled Static libraries 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.ipa 36 | 37 | # These project files can be generated by the engine 38 | *.xcodeproj 39 | *.xcworkspace 40 | *.sln 41 | *.suo 42 | *.opensdf 43 | *.sdf 44 | *.VC.db 45 | *.VC.opendb 46 | 47 | # Precompiled Assets 48 | SourceArt/**/*.png 49 | SourceArt/**/*.tga 50 | 51 | # Binary Files 52 | Binaries/* 53 | Plugins/*/Binaries/* 54 | 55 | # Builds 56 | Build/* 57 | 58 | # Whitelist PakBlacklist-.txt files 59 | !Build/*/ 60 | Build/*/** 61 | !Build/*/PakBlacklist*.txt 62 | 63 | # Don't ignore icon files in Build 64 | !Build/**/*.ico 65 | 66 | # Built data for maps 67 | *_BuiltData.uasset 68 | 69 | # Configuration files generated by the Editor 70 | Saved/* 71 | 72 | # Compiled source files for the engine to use 73 | Intermediate/* 74 | Plugins/*/Intermediate/* 75 | 76 | # Cache files for the editor to use 77 | DerivedDataCache/* 78 | 79 | # Packaged releases 80 | Releases/* -------------------------------------------------------------------------------- /Ability.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "Ability", 6 | "Description": "", 7 | "Category": "Gameplay", 8 | "CreatedBy": "", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": true, 14 | "IsBetaVersion": false, 15 | "IsExperimentalVersion": true, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "Ability", 20 | "Type": "Runtime", 21 | "LoadingPhase": "Default" 22 | } 23 | ], 24 | "Plugins": [ 25 | { 26 | "Name": "GameplayAbilities", 27 | "Enabled": true 28 | }, 29 | { 30 | "Name": "GameplayTagsEditor", 31 | "Enabled": true 32 | }, 33 | { 34 | "Name": "ModularGameplay", 35 | "Enabled": true 36 | }, 37 | { 38 | "Name": "EnhancedInput", 39 | "Enabled": true 40 | }, 41 | { 42 | "Name": "GameFeatures", 43 | "Enabled": true 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /Config/FilterPlugin.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | -------------------------------------------------------------------------------- /Content/Ability/AbilitySystem/BP_GameplayEffectVolume.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Content/Ability/AbilitySystem/BP_GameplayEffectVolume.uasset -------------------------------------------------------------------------------- /Content/Ability/AbilitySystem/BP_GameplayEventNotify.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Content/Ability/AbilitySystem/BP_GameplayEventNotify.uasset -------------------------------------------------------------------------------- /Content/Ability/AbilitySystem/GameplayAbilityUtils.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Content/Ability/AbilitySystem/GameplayAbilityUtils.uasset -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tylrin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ability 2 | ![Ability Logo](/Resources/Export/Ability_SocialPreview.png) 3 | ## License & Contribution 4 | **Source code** of the plugin is licensed under MIT license, and other developers are encouraged to fork the repository, open issues & pull requests to help the development. -------------------------------------------------------------------------------- /Resources/AbilityPlugin_Designs.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Resources/AbilityPlugin_Designs.afdesign -------------------------------------------------------------------------------- /Resources/Export/Ability128_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Resources/Export/Ability128_Icon.png -------------------------------------------------------------------------------- /Resources/Export/Ability_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Resources/Export/Ability_Logo.png -------------------------------------------------------------------------------- /Resources/Export/Ability_SocialPreview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Resources/Export/Ability_SocialPreview.png -------------------------------------------------------------------------------- /Resources/Export/Ability_WhiteLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Resources/Export/Ability_WhiteLogo.png -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tylrin/Ability/6cfecdfcdb2f1bcef3146dbd54063b26ff65d56e/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/Ability/Ability.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class Ability : ModuleRules 6 | { 7 | public Ability(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | // ... add other private include paths required here ... 21 | } 22 | ); 23 | 24 | 25 | PublicDependencyModuleNames.AddRange( 26 | new string[] 27 | { 28 | "Core", 29 | "InputCore", 30 | "CoreUObject", 31 | "Engine", 32 | "GameplayAbilities", 33 | "GameplayTasks", 34 | "GameplayTags", 35 | "ModularGameplay", 36 | "EnhancedInput" 37 | // ... add other public dependencies that you statically link with here ... 38 | } 39 | ); 40 | 41 | 42 | PrivateDependencyModuleNames.AddRange( 43 | new string[] 44 | { 45 | // ... add private dependencies that you statically link with here ... 46 | } 47 | ); 48 | 49 | 50 | DynamicallyLoadedModuleNames.AddRange( 51 | new string[] 52 | { 53 | // ... add any modules that your module loads dynamically here ... 54 | } 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Source/Ability/Private/Ability.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "Ability.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FAbilityModule" 6 | 7 | void FAbilityModule::StartupModule() 8 | { 9 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 10 | } 11 | 12 | void FAbilityModule::ShutdownModule() 13 | { 14 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 15 | // we call this function before unloading the module. 16 | } 17 | 18 | #undef LOCTEXT_NAMESPACE 19 | 20 | DEFINE_LOG_CATEGORY(LogAbility); 21 | 22 | IMPLEMENT_MODULE(FAbilityModule, Ability) -------------------------------------------------------------------------------- /Source/Ability/Private/Character/Abilities/AsyncTaskGameplayTagAddedRemoved.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "Character/Abilities/AsyncTaskGameplayTagAddedRemoved.h" 5 | #include "Ability/Public/GASBlueprintLibrary.h" 6 | 7 | UAsyncTaskGameplayTagAddedRemoved* UAsyncTaskGameplayTagAddedRemoved::ListenForGameplayTagAddedOrRemoved(UAbilitySystemComponent* AbilitySystemComponent, FGameplayTagContainer InTags) 8 | { 9 | UAsyncTaskGameplayTagAddedRemoved* ListenForGameplayTagAddedRemoved = NewObject(); 10 | ListenForGameplayTagAddedRemoved->ASC = AbilitySystemComponent; 11 | ListenForGameplayTagAddedRemoved->Tags = InTags; 12 | 13 | if (!IsValid(AbilitySystemComponent) || InTags.Num() < 1) 14 | { 15 | ListenForGameplayTagAddedRemoved->EndTask(); 16 | return nullptr; 17 | } 18 | 19 | TArray TagArray; 20 | InTags.GetGameplayTagArray(TagArray); 21 | 22 | for (FGameplayTag Tag : TagArray) 23 | { 24 | AbilitySystemComponent->RegisterGameplayTagEvent(Tag, EGameplayTagEventType::NewOrRemoved).AddUObject(ListenForGameplayTagAddedRemoved, &UAsyncTaskGameplayTagAddedRemoved::TagChanged); 25 | } 26 | 27 | return ListenForGameplayTagAddedRemoved; 28 | } 29 | 30 | void UAsyncTaskGameplayTagAddedRemoved::EndTask() 31 | { 32 | if (IsValid(ASC)) 33 | { 34 | TArray TagArray; 35 | Tags.GetGameplayTagArray(TagArray); 36 | 37 | for (FGameplayTag Tag : TagArray) 38 | { 39 | ASC->RegisterGameplayTagEvent(Tag, EGameplayTagEventType::NewOrRemoved).RemoveAll(this); 40 | } 41 | } 42 | 43 | SetReadyToDestroy(); 44 | MarkPendingKill(); 45 | } 46 | 47 | void UAsyncTaskGameplayTagAddedRemoved::TagChanged(const FGameplayTag Tag, int32 NewCount) 48 | { 49 | if (NewCount > 0) 50 | { 51 | OnTagAdded.Broadcast(Tag); 52 | } 53 | else 54 | { 55 | OnTagRemoved.Broadcast(Tag); 56 | } 57 | } -------------------------------------------------------------------------------- /Source/Ability/Private/Character/Abilities/GASAbilityTypes.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "Character/Abilities/GASAbilityTypes.h" 4 | #include "AbilitySystemGlobals.h" 5 | #include "AbilitySystemComponent.h" 6 | 7 | bool FGASGameplayEffectContainerSpec::HasValidEffects() const 8 | { 9 | return TargetGameplayEffectSpecs.Num() > 0; 10 | } 11 | 12 | bool FGASGameplayEffectContainerSpec::HasValidTargets() const 13 | { 14 | return TargetData.Num() > 0; 15 | } 16 | 17 | void FGASGameplayEffectContainerSpec::AddTargets(const TArray& InTargetData, const TArray& HitResults, const TArray& TargetActors) 18 | { 19 | for (const FGameplayAbilityTargetDataHandle& TD : InTargetData) 20 | { 21 | TargetData.Append(TD); 22 | } 23 | 24 | for (const FHitResult& HitResult : HitResults) 25 | { 26 | FGameplayAbilityTargetData_SingleTargetHit* NewData = new FGameplayAbilityTargetData_SingleTargetHit(HitResult); 27 | TargetData.Add(NewData); 28 | } 29 | 30 | if (TargetActors.Num() > 0) 31 | { 32 | FGameplayAbilityTargetData_ActorArray* NewData = new FGameplayAbilityTargetData_ActorArray(); 33 | NewData->TargetActorArray.Append(TargetActors); 34 | TargetData.Add(NewData); 35 | } 36 | } 37 | 38 | void FGASGameplayEffectContainerSpec::ClearTargets() 39 | { 40 | TargetData.Clear(); 41 | } -------------------------------------------------------------------------------- /Source/Ability/Private/Character/Abilities/GASGameplayAbility.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "Character/Abilities/GASGameplayAbility.h" 5 | #include "AbilitySystemComponent.h" 6 | 7 | UGASGameplayAbility::UGASGameplayAbility() 8 | { 9 | bActivateAbilityOnGranted = false; 10 | } 11 | 12 | void UGASGameplayAbility::OnAvatarSet(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec) 13 | { 14 | Super::OnAvatarSet(ActorInfo, Spec); 15 | 16 | if (bActivateAbilityOnGranted) 17 | { 18 | bool ActivatedAbility = ActorInfo->AbilitySystemComponent->TryActivateAbility(Spec.Handle, false); 19 | } 20 | } 21 | 22 | bool UGASGameplayAbility::IsInputPressed() const 23 | { 24 | FGameplayAbilitySpec* Spec = GetCurrentAbilitySpec(); 25 | return Spec && Spec->InputPressed; 26 | } -------------------------------------------------------------------------------- /Source/Ability/Private/Character/Abilities/GASGameplayEffectTypes.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Character/Abilities/GASGameplayEffectTypes.h" 3 | 4 | bool FGASGameplayEffectContext::NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess) 5 | { 6 | return Super::NetSerialize(Ar, Map, bOutSuccess) && TargetData.NetSerialize(Ar, Map, bOutSuccess); 7 | } -------------------------------------------------------------------------------- /Source/Ability/Private/Character/Abilities/GASTargetType.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "Character/Abilities/GASTargetType.h" 5 | #include "GameFramework/Character.h" 6 | 7 | void UGASTargetType::GetTargets_Implementation(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const 8 | { 9 | return; 10 | } 11 | 12 | void UGASTargetType_UseOwner::GetTargets_Implementation(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const 13 | { 14 | OutActors.Add(TargetingCharacter); 15 | } 16 | 17 | void UGASTargetType_UseEventData::GetTargets_Implementation(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const 18 | { 19 | const FHitResult* FoundHitResult = EventData.ContextHandle.GetHitResult(); 20 | if (FoundHitResult) 21 | { 22 | OutHitResults.Add(*FoundHitResult); 23 | } 24 | else if (EventData.Target) 25 | { 26 | OutActors.Add(const_cast(EventData.Target)); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Source/Ability/Private/Character/AbilityInputBindingComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "Character/AbilityInputBindingComponent.h" 5 | // #include "Ability.h" 6 | #include "InputAction.h" 7 | #include "EnhancedInputComponent.h" 8 | #include "AbilitySystemComponent.h" 9 | #include "AbilitySystemGlobals.h" 10 | 11 | namespace AbilityInputBindingComponent_Impl 12 | { 13 | constexpr int32 InvalidInputID = 0; 14 | int32 IncrementingInputID = InvalidInputID; 15 | 16 | static int32 GetNextInputID() 17 | { 18 | return ++IncrementingInputID; 19 | } 20 | } 21 | 22 | void UAbilityInputBindingComponent::SetInputBinding(UInputAction* InputAction, FGameplayAbilitySpecHandle AbilityHandle) 23 | { 24 | using namespace AbilityInputBindingComponent_Impl; 25 | 26 | FGameplayAbilitySpec* BindingAbility = FindAbilitySpec(AbilityHandle); 27 | 28 | FAbilityInputBinding* AbilityInputBinding = MappedAbilities.Find(InputAction); 29 | if (AbilityInputBinding) 30 | { 31 | FGameplayAbilitySpec* OldBoundAbility = FindAbilitySpec(AbilityInputBinding->BoundAbilitiesStack.Top()); 32 | if (OldBoundAbility && OldBoundAbility->InputID == AbilityInputBinding->InputID) 33 | { 34 | OldBoundAbility->InputID = InvalidInputID; 35 | } 36 | } 37 | else 38 | { 39 | AbilityInputBinding = &MappedAbilities.Add(InputAction); 40 | AbilityInputBinding->InputID = GetNextInputID(); 41 | } 42 | 43 | if (BindingAbility) 44 | { 45 | BindingAbility->InputID = AbilityInputBinding->InputID; 46 | } 47 | 48 | AbilityInputBinding->BoundAbilitiesStack.Push(AbilityHandle); 49 | TryBindAbilityInput(InputAction, *AbilityInputBinding); 50 | } 51 | 52 | void UAbilityInputBindingComponent::ClearInputBinding(FGameplayAbilitySpecHandle AbilityHandle) 53 | { 54 | using namespace AbilityInputBindingComponent_Impl; 55 | 56 | if (FGameplayAbilitySpec* FoundAbility = FindAbilitySpec(AbilityHandle)) 57 | { 58 | // Find the mapping for this ability 59 | auto MappedIterator = MappedAbilities.CreateIterator(); 60 | while (MappedIterator) 61 | { 62 | if (MappedIterator.Value().InputID == FoundAbility->InputID) 63 | { 64 | break; 65 | } 66 | 67 | ++MappedIterator; 68 | } 69 | 70 | if (MappedIterator) 71 | { 72 | FAbilityInputBinding& AbilityInputBinding = MappedIterator.Value(); 73 | 74 | if (AbilityInputBinding.BoundAbilitiesStack.Remove(AbilityHandle) > 0) 75 | { 76 | if (AbilityInputBinding.BoundAbilitiesStack.Num() > 0) 77 | { 78 | FGameplayAbilitySpec* StackedAbility = FindAbilitySpec(AbilityInputBinding.BoundAbilitiesStack.Top()); 79 | if (StackedAbility && StackedAbility->InputID == 0) 80 | { 81 | StackedAbility->InputID = AbilityInputBinding.InputID; 82 | } 83 | } 84 | else 85 | { 86 | // NOTE: This will invalidate the `AbilityInputBinding` ref above 87 | RemoveEntry(MappedIterator.Key()); 88 | } 89 | // DO NOT act on `AbilityInputBinding` after here (it could have been removed) 90 | 91 | 92 | FoundAbility->InputID = InvalidInputID; 93 | } 94 | } 95 | } 96 | } 97 | 98 | void UAbilityInputBindingComponent::ClearAbilityBindings(UInputAction* InputAction) 99 | { 100 | RemoveEntry(InputAction); 101 | } 102 | 103 | void UAbilityInputBindingComponent::ResetBindings() 104 | { 105 | for (auto& InputBinding : MappedAbilities) 106 | { 107 | if (InputComponent) 108 | { 109 | InputComponent->RemoveBindingByHandle(InputBinding.Value.OnPressedHandle); 110 | InputComponent->RemoveBindingByHandle(InputBinding.Value.OnReleasedHandle); 111 | } 112 | 113 | if (AbilityComponent) 114 | { 115 | const int32 ExpectedInputID = InputBinding.Value.InputID; 116 | 117 | for (FGameplayAbilitySpecHandle AbilityHandle : InputBinding.Value.BoundAbilitiesStack) 118 | { 119 | FGameplayAbilitySpec* FoundAbility = AbilityComponent->FindAbilitySpecFromHandle(AbilityHandle); 120 | if (FoundAbility && FoundAbility->InputID == ExpectedInputID) 121 | { 122 | FoundAbility->InputID = AbilityInputBindingComponent_Impl::InvalidInputID; 123 | } 124 | } 125 | } 126 | } 127 | 128 | AbilityComponent = nullptr; 129 | } 130 | 131 | void UAbilityInputBindingComponent::SetupPlayerControls_Implementation(UEnhancedInputComponent* PlayerInputComponent) 132 | { 133 | ResetBindings(); 134 | 135 | for (auto& Ability : MappedAbilities) 136 | { 137 | UInputAction* InputAction = Ability.Key; 138 | 139 | // Pressed event 140 | InputComponent->BindAction(InputAction, ETriggerEvent::Started, this, &UAbilityInputBindingComponent::OnAbilityInputPressed, InputAction); 141 | 142 | // Released event 143 | InputComponent->BindAction(InputAction, ETriggerEvent::Completed, this, &UAbilityInputBindingComponent::OnAbilityInputReleased, InputAction); 144 | } 145 | 146 | RunAbilitySystemSetup(); 147 | } 148 | 149 | void UAbilityInputBindingComponent::ReleaseInputComponent(AController* OldController) 150 | { 151 | ResetBindings(); 152 | 153 | Super::ReleaseInputComponent(); 154 | } 155 | 156 | void UAbilityInputBindingComponent::RunAbilitySystemSetup() 157 | { 158 | AActor* MyOwner = GetOwner(); 159 | check(MyOwner); 160 | 161 | AbilityComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(MyOwner); 162 | if (AbilityComponent) 163 | { 164 | for (auto& InputBinding : MappedAbilities) 165 | { 166 | const int32 NewInputID = AbilityInputBindingComponent_Impl::GetNextInputID(); 167 | InputBinding.Value.InputID = NewInputID; 168 | 169 | for (FGameplayAbilitySpecHandle AbilityHandle : InputBinding.Value.BoundAbilitiesStack) 170 | { 171 | FGameplayAbilitySpec* FoundAbility = AbilityComponent->FindAbilitySpecFromHandle(AbilityHandle); 172 | if (FoundAbility != nullptr) 173 | { 174 | FoundAbility->InputID = NewInputID; 175 | } 176 | } 177 | } 178 | } 179 | } 180 | 181 | void UAbilityInputBindingComponent::OnAbilityInputPressed(UInputAction* InputAction) 182 | { 183 | // The AbilitySystemComponent may not have been valid when we first bound input... try again. 184 | if (!AbilityComponent) 185 | { 186 | RunAbilitySystemSetup(); 187 | } 188 | 189 | if (AbilityComponent) 190 | { 191 | using namespace AbilityInputBindingComponent_Impl; 192 | 193 | FAbilityInputBinding* FoundBinding = MappedAbilities.Find(InputAction); 194 | if (FoundBinding && ensure(FoundBinding->InputID != InvalidInputID)) 195 | { 196 | AbilityComponent->AbilityLocalInputPressed(FoundBinding->InputID); 197 | } 198 | } 199 | } 200 | 201 | void UAbilityInputBindingComponent::OnAbilityInputReleased(UInputAction* InputAction) 202 | { 203 | if (AbilityComponent) 204 | { 205 | using namespace AbilityInputBindingComponent_Impl; 206 | 207 | FAbilityInputBinding* FoundBinding = MappedAbilities.Find(InputAction); 208 | if (FoundBinding && ensure(FoundBinding->InputID != InvalidInputID)) 209 | { 210 | AbilityComponent->AbilityLocalInputReleased(FoundBinding->InputID); 211 | } 212 | } 213 | } 214 | 215 | void UAbilityInputBindingComponent::RemoveEntry(UInputAction* InputAction) 216 | { 217 | if (FAbilityInputBinding* Bindings = MappedAbilities.Find(InputAction)) 218 | { 219 | if (InputComponent) 220 | { 221 | InputComponent->RemoveBindingByHandle(Bindings->OnPressedHandle); 222 | InputComponent->RemoveBindingByHandle(Bindings->OnReleasedHandle); 223 | } 224 | 225 | for (FGameplayAbilitySpecHandle AbilityHandle : Bindings->BoundAbilitiesStack) 226 | { 227 | using namespace AbilityInputBindingComponent_Impl; 228 | 229 | FGameplayAbilitySpec* AbilitySpec = FindAbilitySpec(AbilityHandle); 230 | if (AbilitySpec && AbilitySpec->InputID == Bindings->InputID) 231 | { 232 | AbilitySpec->InputID = InvalidInputID; 233 | } 234 | } 235 | 236 | MappedAbilities.Remove(InputAction); 237 | } 238 | } 239 | 240 | FGameplayAbilitySpec* UAbilityInputBindingComponent::FindAbilitySpec(FGameplayAbilitySpecHandle Handle) 241 | { 242 | FGameplayAbilitySpec* FoundAbility = nullptr; 243 | if (AbilityComponent) 244 | { 245 | FoundAbility = AbilityComponent->FindAbilitySpecFromHandle(Handle); 246 | } 247 | return FoundAbility; 248 | } 249 | 250 | void UAbilityInputBindingComponent::TryBindAbilityInput(UInputAction* InputAction, FAbilityInputBinding& AbilityInputBinding) 251 | { 252 | if (InputComponent) 253 | { 254 | // Pressed event 255 | if (AbilityInputBinding.OnPressedHandle == 0) 256 | { 257 | AbilityInputBinding.OnPressedHandle = InputComponent->BindAction(InputAction, ETriggerEvent::Started, this, &UAbilityInputBindingComponent::OnAbilityInputPressed, InputAction).GetHandle(); 258 | } 259 | 260 | // Released event 261 | if (AbilityInputBinding.OnReleasedHandle == 0) 262 | { 263 | AbilityInputBinding.OnReleasedHandle = InputComponent->BindAction(InputAction, ETriggerEvent::Completed, this, &UAbilityInputBindingComponent::OnAbilityInputReleased, InputAction).GetHandle(); 264 | } 265 | } 266 | } -------------------------------------------------------------------------------- /Source/Ability/Private/Character/GameplayAbilitySystemComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "Character/GameplayAbilitySystemComponent.h" 5 | 6 | void UGameplayAbilitySystemComponent::InitAbilityActorInfo(AActor* InOwnerActor, AActor* InAvatarActor) 7 | { 8 | Super::InitAbilityActorInfo(InOwnerActor, InAvatarActor); 9 | 10 | if (AbilityActorInfo) 11 | { 12 | if (UGameInstance* GameInstance = InOwnerActor->GetGameInstance()) 13 | { 14 | // Sign up for possess/unpossess events so that we can update the cached AbilityActorInfo accordingly 15 | GameInstance->GetOnPawnControllerChanged().AddDynamic(this, &UGameplayAbilitySystemComponent::OnPawnControllerChanged); 16 | } 17 | } 18 | 19 | GrantDefaultAbilitiesAndAttributes(); 20 | } 21 | 22 | void UGameplayAbilitySystemComponent::BeginDestroy() 23 | { 24 | if (AbilityActorInfo && AbilityActorInfo->OwnerActor.IsValid()) 25 | { 26 | if (UGameInstance* GameInstance = AbilityActorInfo->OwnerActor->GetGameInstance()) 27 | { 28 | GameInstance->GetOnPawnControllerChanged().RemoveAll(this); 29 | } 30 | } 31 | 32 | Super::BeginDestroy(); 33 | } 34 | 35 | FGameplayAbilitySpecHandle UGameplayAbilitySystemComponent::GrantAbilityOfType(TSubclassOf AbilityType, bool bRemoveAfterActivation) 36 | { 37 | FGameplayAbilitySpecHandle AbilityHandle; 38 | if (AbilityType) 39 | { 40 | FGameplayAbilitySpec AbilitySpec(AbilityType); 41 | AbilitySpec.RemoveAfterActivation = bRemoveAfterActivation; 42 | 43 | AbilityHandle = GiveAbility(AbilitySpec); 44 | } 45 | return AbilityHandle; 46 | } 47 | 48 | FGameplayAbilitySpecHandle UGameplayAbilitySystemComponent::FindAbilityHandleFromClass(TSubclassOf InAbilityClass) 49 | { 50 | FGameplayAbilitySpec* Spec = FindAbilitySpecFromClass(InAbilityClass); 51 | FGameplayAbilitySpecHandle Handle = Spec->Handle; 52 | return Handle; 53 | } 54 | 55 | 56 | void UGameplayAbilitySystemComponent::RemoveAbilityOfType(TSubclassOf AbilityType) 57 | { 58 | FGameplayAbilitySpecHandle AbilityHandle; 59 | if (AbilityType) 60 | { 61 | ClearAbility(AbilityHandle); 62 | } 63 | } 64 | 65 | void ClearAbility(const FGameplayAbilitySpecHandle& Handle); 66 | 67 | void UGameplayAbilitySystemComponent::GrantDefaultAbilitiesAndAttributes() 68 | { 69 | // Reset/Remove abilities if we had already added them 70 | { 71 | //for (UAttributeSet* AttribSetInstance : AddedAttributes) 72 | //{ 73 | // GetSpawnedAttributes_Mutable().Remove(AttribSetInstance); 74 | //} 75 | 76 | for (FGameplayAbilitySpecHandle AbilityHandle : DefaultAbilityHandles) 77 | { 78 | SetRemoveAbilityOnEnd(AbilityHandle); 79 | } 80 | 81 | //AddedAttributes.Empty(DefaultAttributes.Num()); 82 | DefaultAbilityHandles.Empty(DefaultAbilities.Num()); 83 | } 84 | 85 | // Default abilities 86 | { 87 | DefaultAbilityHandles.Reserve(DefaultAbilities.Num()); 88 | for (const TSubclassOf& Ability : DefaultAbilities) 89 | { 90 | if (*Ability) 91 | { 92 | DefaultAbilityHandles.Add(GiveAbility(FGameplayAbilitySpec(Ability))); 93 | } 94 | } 95 | } 96 | 97 | // Default attributes 98 | //{ 99 | // for (const FGameplayAttributeApplication& Attributes : DefaultAttributes) 100 | // { 101 | // if (Attributes.AttributeSetType) 102 | // { 103 | // UAttributeSet* NewAttribSet = NewObject(this, Attributes.AttributeSetType); 104 | // if (Attributes.InitializationData) 105 | // { 106 | // NewAttribSet->InitFromMetaDataTable(Attributes.InitializationData); 107 | // } 108 | // AddedAttributes.Add(NewAttribSet); 109 | // AddAttributeSetSubobject(NewAttribSet); 110 | // } 111 | // } 112 | //} 113 | } 114 | 115 | void UGameplayAbilitySystemComponent::OnPawnControllerChanged(APawn* Pawn, AController* NewController) 116 | { 117 | if (AbilityActorInfo && AbilityActorInfo->OwnerActor == Pawn && AbilityActorInfo->PlayerController != NewController) 118 | { 119 | // Reinit the cached ability actor info (specifically the player controller) 120 | AbilityActorInfo->InitFromActor(AbilityActorInfo->OwnerActor.Get(), AbilityActorInfo->AvatarActor.Get(), this); 121 | } 122 | } -------------------------------------------------------------------------------- /Source/Ability/Private/Character/PlayerControlsComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "Character/PlayerControlsComponent.h" 5 | #include "GameFramework/Pawn.h" 6 | #include "GameFramework/PlayerController.h" 7 | #include "EnhancedInputComponent.h" 8 | #include "Engine/InputDelegateBinding.h" 9 | #include "Engine/LocalPlayer.h" 10 | #include "EnhancedInputSubsystems.h" 11 | 12 | void UPlayerControlsComponent::OnRegister() 13 | { 14 | Super::OnRegister(); 15 | 16 | UWorld* World = GetWorld(); 17 | APawn* MyOwner = GetPawn(); 18 | 19 | if (ensure(MyOwner) && World->IsGameWorld()) 20 | { 21 | MyOwner->ReceiveRestartedDelegate.AddDynamic(this, &UPlayerControlsComponent::OnPawnRestarted); 22 | MyOwner->ReceiveControllerChangedDelegate.AddDynamic(this, &UPlayerControlsComponent::OnControllerChanged); 23 | 24 | // If our pawn has an input component we were added after restart 25 | if (MyOwner->InputComponent) 26 | { 27 | OnPawnRestarted(MyOwner); 28 | } 29 | } 30 | } 31 | 32 | void UPlayerControlsComponent::OnUnregister() 33 | { 34 | UWorld* World = GetWorld(); 35 | if (World && World->IsGameWorld()) 36 | { 37 | ReleaseInputComponent(); 38 | 39 | APawn* MyOwner = GetPawn(); 40 | if (MyOwner) 41 | { 42 | MyOwner->ReceiveRestartedDelegate.RemoveAll(this); 43 | MyOwner->ReceiveControllerChangedDelegate.RemoveAll(this); 44 | } 45 | } 46 | 47 | Super::OnUnregister(); 48 | } 49 | 50 | void UPlayerControlsComponent::OnPawnRestarted(APawn* Pawn) 51 | { 52 | if (ensure(Pawn && Pawn == GetOwner()) && Pawn->InputComponent) 53 | { 54 | ReleaseInputComponent(); 55 | 56 | if (Pawn->InputComponent) 57 | { 58 | SetupInputComponent(Pawn); 59 | } 60 | } 61 | } 62 | 63 | void UPlayerControlsComponent::OnControllerChanged(APawn* Pawn, AController* OldController, AController* NewController) 64 | { 65 | // Only handle releasing, restart is a better time to handle binding 66 | if (ensure(Pawn && Pawn == GetOwner()) && OldController) 67 | { 68 | ReleaseInputComponent(OldController); 69 | } 70 | } 71 | 72 | void UPlayerControlsComponent::SetupInputComponent(APawn* Pawn) 73 | { 74 | InputComponent = CastChecked(Pawn->InputComponent); 75 | 76 | if (ensureMsgf(InputComponent, TEXT("Project must use EnhancedInputComponent to support PlayerControlsComponent"))) 77 | { 78 | UEnhancedInputLocalPlayerSubsystem* Subsystem = GetEnhancedInputSubsystem(); 79 | check(Subsystem); 80 | 81 | if (InputMappingContext) 82 | { 83 | Subsystem->AddMappingContext(InputMappingContext, InputPriority); 84 | } 85 | 86 | SetupPlayerControls(InputComponent); 87 | } 88 | } 89 | 90 | void UPlayerControlsComponent::ReleaseInputComponent(AController* OldController) 91 | { 92 | UEnhancedInputLocalPlayerSubsystem* Subsystem = GetEnhancedInputSubsystem(OldController); 93 | if (Subsystem && InputComponent) 94 | { 95 | TeardownPlayerControls(InputComponent); 96 | 97 | if (InputMappingContext) 98 | { 99 | Subsystem->RemoveMappingContext(InputMappingContext); 100 | } 101 | } 102 | InputComponent = nullptr; 103 | } 104 | 105 | void UPlayerControlsComponent::SetupPlayerControls_Implementation(UEnhancedInputComponent* PlayerInputComponent) 106 | { 107 | 108 | } 109 | 110 | void UPlayerControlsComponent::TeardownPlayerControls_Implementation(UEnhancedInputComponent* PlayerInputComponent) 111 | { 112 | 113 | } 114 | 115 | UEnhancedInputLocalPlayerSubsystem* UPlayerControlsComponent::GetEnhancedInputSubsystem(AController* OldController) const 116 | { 117 | const APlayerController* PC = GetController(); 118 | if (!PC) 119 | { 120 | PC = Cast(OldController); 121 | if (!PC) 122 | { 123 | return nullptr; 124 | } 125 | } 126 | 127 | const ULocalPlayer* LP = PC->GetLocalPlayer(); 128 | if (!LP) 129 | { 130 | return nullptr; 131 | } 132 | 133 | return LP->GetSubsystem(); 134 | } 135 | -------------------------------------------------------------------------------- /Source/Ability/Private/GASAssetManager.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "GASAssetManager.h" 5 | #include "AbilitySystemGlobals.h" 6 | 7 | UGASAssetManager& UGASAssetManager::Get() 8 | { 9 | UGASAssetManager* Singleton = Cast(GEngine->AssetManager); 10 | 11 | if (Singleton) 12 | { 13 | return *Singleton; 14 | } 15 | else 16 | { 17 | UE_LOG(LogTemp, Fatal, TEXT("Invalid AssetManager in DefaultEngine.ini, must be GDAssetManager!")); 18 | return *NewObject(); // never calls this 19 | } 20 | } 21 | 22 | 23 | void UGASAssetManager::StartInitialLoading() 24 | { 25 | Super::StartInitialLoading(); 26 | UAbilitySystemGlobals::Get().InitGlobalData(); 27 | } -------------------------------------------------------------------------------- /Source/Ability/Private/GASBlueprintLibrary.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "GASBlueprintLibrary.h" 3 | 4 | 5 | FString UGASBlueprintLibrary::GetPlayerEditorWindowRole(UWorld* World) 6 | { 7 | FString Prefix; 8 | if (World) 9 | { 10 | if (World->WorldType == EWorldType::PIE) 11 | { 12 | switch (World->GetNetMode()) 13 | { 14 | case NM_Client: 15 | Prefix = FString::Printf(TEXT("Client %d "), GPlayInEditorID - 1); 16 | break; 17 | case NM_DedicatedServer: 18 | case NM_ListenServer: 19 | Prefix = FString::Printf(TEXT("Server ")); 20 | break; 21 | case NM_Standalone: 22 | break; 23 | } 24 | } 25 | } 26 | 27 | return Prefix; 28 | } 29 | 30 | UGameplayAbility* UGASBlueprintLibrary::GetPrimaryAbilityInstanceFromHandle(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle) 31 | { 32 | if (AbilitySystemComponent) 33 | { 34 | FGameplayAbilitySpec* AbilitySpec = AbilitySystemComponent->FindAbilitySpecFromHandle(Handle); 35 | if (AbilitySpec) 36 | { 37 | return Cast(AbilitySpec->GetPrimaryInstance()); 38 | } 39 | } 40 | 41 | return nullptr; 42 | } 43 | 44 | UGameplayAbility* UGASBlueprintLibrary::GetPrimaryAbilityInstanceFromClass(UAbilitySystemComponent* AbilitySystemComponent, TSubclassOf InAbilityClass) 45 | { 46 | if (AbilitySystemComponent) 47 | { 48 | FGameplayAbilitySpec* AbilitySpec = AbilitySystemComponent->FindAbilitySpecFromClass(InAbilityClass); 49 | if (AbilitySpec) 50 | { 51 | return Cast(AbilitySpec->GetPrimaryInstance()); 52 | } 53 | } 54 | 55 | return nullptr; 56 | } 57 | 58 | bool UGASBlueprintLibrary::IsPrimaryAbilityInstanceActive(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle) 59 | { 60 | if (AbilitySystemComponent) 61 | { 62 | FGameplayAbilitySpec* AbilitySpec = AbilitySystemComponent->FindAbilitySpecFromHandle(Handle); 63 | if (AbilitySpec) 64 | { 65 | return Cast(AbilitySpec->GetPrimaryInstance())->IsActive(); 66 | } 67 | } 68 | 69 | return false; 70 | } 71 | 72 | bool UGASBlueprintLibrary::IsAbilitySpecHandleValid(FGameplayAbilitySpecHandle Handle) 73 | { 74 | return Handle.IsValid(); 75 | } 76 | 77 | bool UGASBlueprintLibrary::DoesEffectContainerSpecHaveEffects(const FGASGameplayEffectContainerSpec& ContainerSpec) 78 | { 79 | return ContainerSpec.HasValidEffects(); 80 | } 81 | 82 | bool UGASBlueprintLibrary::DoesEffectContainerSpecHaveTargets(const FGASGameplayEffectContainerSpec& ContainerSpec) 83 | { 84 | return ContainerSpec.HasValidTargets(); 85 | } 86 | 87 | void UGASBlueprintLibrary::ClearEffectContainerSpecTargets(FGASGameplayEffectContainerSpec& ContainerSpec) 88 | { 89 | ContainerSpec.ClearTargets(); 90 | } 91 | 92 | void UGASBlueprintLibrary::AddTargetsToEffectContainerSpec(FGASGameplayEffectContainerSpec& ContainerSpec, const TArray& TargetData, const TArray& HitResults, const TArray& TargetActors) 93 | { 94 | ContainerSpec.AddTargets(TargetData, HitResults, TargetActors); 95 | } 96 | 97 | TArray UGASBlueprintLibrary::ApplyExternalEffectContainerSpec(const FGASGameplayEffectContainerSpec& ContainerSpec) 98 | { 99 | TArray AllEffects; 100 | 101 | // Iterate list of gameplay effects 102 | for (const FGameplayEffectSpecHandle& SpecHandle : ContainerSpec.TargetGameplayEffectSpecs) 103 | { 104 | if (SpecHandle.IsValid()) 105 | { 106 | // If effect is valid, iterate list of targets and apply to all 107 | for (TSharedPtr Data : ContainerSpec.TargetData.Data) 108 | { 109 | AllEffects.Append(Data->ApplyGameplayEffectSpec(*SpecHandle.Data.Get())); 110 | } 111 | } 112 | } 113 | return AllEffects; 114 | } 115 | 116 | FGameplayAbilityTargetDataHandle UGASBlueprintLibrary::EffectContextGetTargetData(FGameplayEffectContextHandle EffectContextHandle) 117 | { 118 | FGASGameplayEffectContext* EffectContext = static_cast(EffectContextHandle.Get()); 119 | 120 | if (EffectContext) 121 | { 122 | return EffectContext->GetTargetData(); 123 | } 124 | 125 | return FGameplayAbilityTargetDataHandle(); 126 | } 127 | 128 | void UGASBlueprintLibrary::EffectContextAddTargetData(FGameplayEffectContextHandle EffectContextHandle, const FGameplayAbilityTargetDataHandle& TargetData) 129 | { 130 | FGASGameplayEffectContext* EffectContext = static_cast(EffectContextHandle.Get()); 131 | 132 | if (EffectContext) 133 | { 134 | EffectContext->AddTargetData(TargetData); 135 | } 136 | } 137 | 138 | void UGASBlueprintLibrary::ClearTargetData(FGameplayAbilityTargetDataHandle& TargetData) 139 | { 140 | TargetData.Clear(); 141 | } -------------------------------------------------------------------------------- /Source/Ability/Private/GASEngineSubsystem.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "GASEngineSubsystem.h" 5 | #include "AbilitySystemGlobals.h" 6 | 7 | void UGASEngineSubsystem::Initialize(FSubsystemCollectionBase& Collection) 8 | { 9 | Super::Initialize(Collection); 10 | } -------------------------------------------------------------------------------- /Source/Ability/Public/Ability.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | DECLARE_LOG_CATEGORY_EXTERN(LogAbility, Log, All); 9 | 10 | class FAbilityModule : public IModuleInterface 11 | { 12 | public: 13 | 14 | /** IModuleInterface implementation */ 15 | virtual void StartupModule() override; 16 | virtual void ShutdownModule() override; 17 | }; 18 | -------------------------------------------------------------------------------- /Source/Ability/Public/Character/Abilities/AsyncTaskGameplayTagAddedRemoved.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Kismet/BlueprintAsyncActionBase.h" 7 | #include "AbilitySystemComponent.h" 8 | #include "GameplayTagContainer.h" 9 | #include "AsyncTaskGameplayTagAddedRemoved.generated.h" 10 | 11 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGameplayTagAddedRemoved, FGameplayTag, Tag); 12 | 13 | /** 14 | * Blueprint node to automatically register a listener for FGameplayTags added and removed. 15 | * Useful to use in Blueprint/UMG. 16 | */ 17 | UCLASS(BlueprintType, meta = (ExposedAsyncProxy = AsyncTask)) 18 | class ABILITY_API UAsyncTaskGameplayTagAddedRemoved : public UBlueprintAsyncActionBase 19 | { 20 | GENERATED_BODY() 21 | 22 | public: 23 | UPROPERTY(BlueprintAssignable) 24 | FOnGameplayTagAddedRemoved OnTagAdded; 25 | 26 | UPROPERTY(BlueprintAssignable) 27 | FOnGameplayTagAddedRemoved OnTagRemoved; 28 | 29 | // Listens for FGameplayTags added and removed. 30 | UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true")) 31 | static UAsyncTaskGameplayTagAddedRemoved* ListenForGameplayTagAddedOrRemoved(UAbilitySystemComponent* AbilitySystemComponent, FGameplayTagContainer Tags); 32 | 33 | // You must call this function manually when you want the AsyncTask to end. 34 | // For UMG Widgets, you would call it in the Widget's Destruct event. 35 | UFUNCTION(BlueprintCallable) 36 | void EndTask(); 37 | 38 | protected: 39 | UPROPERTY() 40 | UAbilitySystemComponent* ASC; 41 | 42 | FGameplayTagContainer Tags; 43 | 44 | virtual void TagChanged(const FGameplayTag Tag, int32 NewCount); 45 | }; 46 | -------------------------------------------------------------------------------- /Source/Ability/Public/Character/Abilities/GASAbilityTypes.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #pragma once 4 | 5 | // ---------------------------------------------------------------------------------------------------------------- 6 | // This header is for Ability-specific structures and enums that are shared across a project 7 | // Every game will probably need a file like this to handle their extensions to the system 8 | // This file is a good place for subclasses of FGameplayEffectContext and FGameplayAbilityTargetData 9 | // ---------------------------------------------------------------------------------------------------------------- 10 | 11 | #include "GameplayEffectTypes.h" 12 | #include "Abilities/GameplayAbilityTargetTypes.h" 13 | #include "Abilities/Tasks/AbilityTask_WaitGameplayEffectStackChange.h" 14 | #include "Abilities/Tasks/AbilityTask_WaitGameplayEffectRemoved.h" 15 | #include "GASAbilityTypes.generated.h" 16 | 17 | class UAbilitySystemComponent; 18 | class UGameplayEffect; 19 | class UGASTargetType; 20 | 21 | /** 22 | * Struct defining a list of gameplay effects, a tag, and targeting info 23 | * These containers are defined statically in blueprints or assets and then turn into Specs at runtime 24 | */ 25 | USTRUCT(BlueprintType) 26 | struct FGASGameplayEffectContainer 27 | { 28 | GENERATED_BODY() 29 | 30 | public: 31 | FGASGameplayEffectContainer() {} 32 | 33 | /** Sets the way that targeting happens */ 34 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = GameplayEffectContainer) 35 | TSubclassOf TargetType; 36 | 37 | /** List of gameplay effects to apply to the targets */ 38 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = GameplayEffectContainer) 39 | TArray> TargetGameplayEffectClasses; 40 | }; 41 | 42 | /** A "processed" version of GASGameplayEffectContainer that can be passed around and eventually applied */ 43 | USTRUCT(BlueprintType) 44 | struct FGASGameplayEffectContainerSpec 45 | { 46 | GENERATED_BODY() 47 | 48 | public: 49 | FGASGameplayEffectContainerSpec() {} 50 | 51 | /** Computed target data */ 52 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = GameplayEffectContainer) 53 | FGameplayAbilityTargetDataHandle TargetData; 54 | 55 | /** List of gameplay effects to apply to the targets */ 56 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = GameplayEffectContainer) 57 | TArray TargetGameplayEffectSpecs; 58 | 59 | /** Returns true if this has any valid effect specs */ 60 | bool HasValidEffects() const; 61 | 62 | /** Returns true if this has any valid targets */ 63 | bool HasValidTargets() const; 64 | 65 | /** Adds new targets to target data */ 66 | void AddTargets(const TArray& TargetData, const TArray& HitResults, const TArray& TargetActors); 67 | 68 | /** Clears target data */ 69 | void ClearTargets(); 70 | }; 71 | 72 | -------------------------------------------------------------------------------- /Source/Ability/Public/Character/Abilities/GASGameplayAbility.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Abilities/GameplayAbility.h" 7 | #include "GASGameplayAbility.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class ABILITY_API UGASGameplayAbility : public UGameplayAbility 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | 19 | UGASGameplayAbility(); 20 | 21 | // Tells an ability to activate immediately when its granted. Used for passive abilities and abilites forced on others. 22 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Ability") 23 | bool bActivateAbilityOnGranted; 24 | 25 | // If an ability is marked as 'ActivateAbilityOnGranted', activate them immediately when given here 26 | // Epic's comment: Projects may want to initiate passives or do other "BeginPlay" type of logic here. 27 | virtual void OnAvatarSet(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec) override; 28 | 29 | // Is the player's input currently pressed? Only works if the ability is bound to input. 30 | UFUNCTION(BlueprintCallable, Category = "Ability") 31 | virtual bool IsInputPressed() const; 32 | }; 33 | -------------------------------------------------------------------------------- /Source/Ability/Public/Character/Abilities/GASGameplayEffectTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayEffectTypes.h" 4 | #include "Abilities/GameplayAbilityTargetTypes.h" 5 | #include "GASGameplayEffectTypes.generated.h" 6 | 7 | /** 8 | * Data structure that stores an instigator and related data, such as positions and targets 9 | * Games can subclass this structure and add game-specific information 10 | * It is passed throughout effect execution so it is a great place to track transient information about an execution 11 | */ 12 | USTRUCT() 13 | struct ABILITY_API FGASGameplayEffectContext : public FGameplayEffectContext 14 | { 15 | GENERATED_USTRUCT_BODY() 16 | 17 | public: 18 | 19 | virtual FGameplayAbilityTargetDataHandle GetTargetData() 20 | { 21 | return TargetData; 22 | } 23 | 24 | virtual void AddTargetData(const FGameplayAbilityTargetDataHandle& TargetDataHandle) 25 | { 26 | TargetData.Append(TargetDataHandle); 27 | } 28 | 29 | /** 30 | * Functions that subclasses of FGameplayEffectContext need to override 31 | */ 32 | 33 | virtual UScriptStruct* GetScriptStruct() const override 34 | { 35 | return FGASGameplayEffectContext::StaticStruct(); 36 | } 37 | 38 | virtual FGASGameplayEffectContext* Duplicate() const override 39 | { 40 | FGASGameplayEffectContext* NewContext = new FGASGameplayEffectContext(); 41 | *NewContext = *this; 42 | NewContext->AddActors(Actors); 43 | if (GetHitResult()) 44 | { 45 | // Does a deep copy of the hit result 46 | NewContext->AddHitResult(*GetHitResult(), true); 47 | } 48 | // Shallow copy of TargetData, is this okay? 49 | NewContext->TargetData.Append(TargetData); 50 | return NewContext; 51 | } 52 | 53 | virtual bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess) override; 54 | 55 | protected: 56 | FGameplayAbilityTargetDataHandle TargetData; 57 | }; 58 | 59 | template<> 60 | struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 61 | { 62 | enum 63 | { 64 | WithNetSerializer = true, 65 | WithCopy = true // Necessary so that TSharedPtr Data is copied around 66 | }; 67 | }; 68 | -------------------------------------------------------------------------------- /Source/Ability/Public/Character/Abilities/GASTargetType.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Abilities/GameplayAbilityTypes.h" 6 | #include "Character/Abilities/GASAbilityTypes.h" 7 | #include "GASTargetType.generated.h" 8 | 9 | class ACharacter; 10 | class AActor; 11 | struct FGameplayEventData; 12 | 13 | 14 | /** 15 | * Class that is used to determine targeting for abilities 16 | * It is meant to be blueprinted to run target logic 17 | * This does not subclass GameplayAbilityTargetActor because this class is never instanced into the world 18 | * This can be used as a basis for a game-specific targeting blueprint 19 | * If your targeting is more complicated you may need to instance into the world once or as a pooled actor 20 | */ 21 | UCLASS(Blueprintable, meta = (ShowWorldContextPin)) 22 | class ABILITY_API UGASTargetType : public UObject 23 | { 24 | GENERATED_BODY() 25 | 26 | public: 27 | // Constructor and overrides 28 | UGASTargetType() {} 29 | 30 | /** Called to determine targets to apply gameplay effects to */ 31 | UFUNCTION(BlueprintNativeEvent) 32 | void GetTargets(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const; 33 | virtual void GetTargets_Implementation(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const; 34 | }; 35 | 36 | /** Trivial target type that uses the owner */ 37 | UCLASS(NotBlueprintable) 38 | class ABILITY_API UGASTargetType_UseOwner : public UGASTargetType 39 | { 40 | GENERATED_BODY() 41 | 42 | public: 43 | // Constructor and overrides 44 | UGASTargetType_UseOwner() {} 45 | 46 | /** Uses the passed in event data */ 47 | virtual void GetTargets_Implementation(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const override; 48 | }; 49 | 50 | /** Trivial target type that pulls the target out of the event data */ 51 | UCLASS(NotBlueprintable) 52 | class ABILITY_API UGASTargetType_UseEventData : public UGASTargetType 53 | { 54 | GENERATED_BODY() 55 | 56 | public: 57 | // Constructor and overrides 58 | UGASTargetType_UseEventData() {} 59 | 60 | /** Uses the passed in event data */ 61 | virtual void GetTargets_Implementation(ACharacter* TargetingCharacter, AActor* TargetingActor, FGameplayEventData EventData, TArray& OutTargetData, TArray& OutHitResults, TArray& OutActors) const override; 62 | }; -------------------------------------------------------------------------------- /Source/Ability/Public/Character/AbilityInputBindingComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Character/PlayerControlsComponent.h" 6 | #include "GameplayAbilitySpec.h" // for FGameplayAbilitySpecHandle 7 | #include "EnhancedInputComponent.h" // for FInputBindingHandle 8 | #include "AbilityInputBindingComponent.generated.h" 9 | 10 | class UInputAction; 11 | class UAbilitySystemComponent; 12 | class UEnhancedInputComponent; 13 | 14 | USTRUCT() 15 | struct FAbilityInputBinding 16 | { 17 | GENERATED_BODY() 18 | 19 | int32 InputID = 0; 20 | uint32 OnPressedHandle = 0; 21 | uint32 OnReleasedHandle = 0; 22 | TArray BoundAbilitiesStack; 23 | }; 24 | 25 | /** Component that hooks up enhanced input to the ability system input logic */ 26 | UCLASS(ClassGroup = AbilitySystem, meta = (BlueprintSpawnableComponent)) 27 | class ABILITY_API UAbilityInputBindingComponent : public UPlayerControlsComponent 28 | { 29 | GENERATED_BODY() 30 | 31 | public: 32 | // Binds an input action to an ability handle 33 | UFUNCTION(BlueprintCallable, Category = "Gameplay|Abilities") 34 | void SetInputBinding(UInputAction* InputAction, FGameplayAbilitySpecHandle AbilityHandle); 35 | 36 | // Cleares the input binding from a ability handle 37 | UFUNCTION(BlueprintCallable, Category = "Gameplay|Abilities") 38 | void ClearInputBinding(FGameplayAbilitySpecHandle AbilityHandle); 39 | 40 | // Cleares all bindings from an input action 41 | UFUNCTION(BlueprintCallable, Category = "Gameplay|Abilities") 42 | void ClearAbilityBindings(UInputAction* InputAction); 43 | 44 | //~ Begin UPlayerControlsComponent interface 45 | virtual void SetupPlayerControls_Implementation(UEnhancedInputComponent* PlayerInputComponent) override; 46 | virtual void ReleaseInputComponent(AController* OldController) override; 47 | //~ End UPlayerControlsComponent interface 48 | 49 | private: 50 | void ResetBindings(); 51 | void RunAbilitySystemSetup(); 52 | void OnAbilityInputPressed(UInputAction* InputAction); 53 | void OnAbilityInputReleased(UInputAction* InputAction); 54 | 55 | void RemoveEntry(UInputAction* InputAction); 56 | 57 | FGameplayAbilitySpec* FindAbilitySpec(FGameplayAbilitySpecHandle Handle); 58 | void TryBindAbilityInput(UInputAction* InputAction, FAbilityInputBinding& AbilityInputBinding); 59 | 60 | private: 61 | UPROPERTY(transient) 62 | UAbilitySystemComponent* AbilityComponent; 63 | 64 | UPROPERTY(transient) 65 | TMap MappedAbilities; 66 | }; -------------------------------------------------------------------------------- /Source/Ability/Public/Character/GameplayAbilitySystemComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "AbilitySystemComponent.h" 6 | #include "Delegates/DelegateCombinations.h" 7 | #include "GameFramework/Actor.h" 8 | #include "GameplayAbilitySystemComponent.generated.h" 9 | 10 | class UAbilityAnimNotify; 11 | class UAnimSequenceBase; 12 | //class UInteractionAbilityAttributeSet; 13 | class UDataTable; 14 | class APawn; 15 | class AController; 16 | 17 | USTRUCT() 18 | struct FGameplayAttributeApplication 19 | { 20 | GENERATED_BODY() 21 | 22 | // Ability set to grant 23 | //UPROPERTY(EditAnywhere) 24 | //TSubclassOf AttributeSetType; 25 | 26 | // Data table reference to initialize the attributes with, if any (can be left unset) 27 | UPROPERTY(EditAnywhere) 28 | UDataTable* InitializationData = nullptr; 29 | }; 30 | 31 | UCLASS(ClassGroup = AbilitySystem, meta = (BlueprintSpawnableComponent)) 32 | class ABILITY_API UGameplayAbilitySystemComponent : public UAbilitySystemComponent 33 | { 34 | GENERATED_BODY() 35 | 36 | public: 37 | UPROPERTY(EditDefaultsOnly, Category = Ability) 38 | TArray> DefaultAbilities; 39 | 40 | UPROPERTY(EditDefaultsOnly, Category = Ability) 41 | TArray DefaultAttributes; 42 | 43 | //~ Begin UAbilitySystemComponent interface 44 | virtual void InitAbilityActorInfo(AActor* InOwnerActor, AActor* InAvatarActor) override; 45 | //~ End UAbilitySystemComponent interface 46 | 47 | //~ Begin UObject interface 48 | virtual void BeginDestroy() override; 49 | //~ End UObject interface 50 | 51 | UFUNCTION(BlueprintCallable, Category = "Gameplay|Abilities") 52 | FGameplayAbilitySpecHandle GrantAbilityOfType(TSubclassOf AbilityType, bool bRemoveAfterActivation); 53 | 54 | UFUNCTION(BlueprintCallable, Category = "Gameplay|Abilities") 55 | void RemoveAbilityOfType(TSubclassOf AbilityType); 56 | 57 | UFUNCTION(BlueprintCallable, Category = "Gameplay|Abilities") 58 | FGameplayAbilitySpecHandle FindAbilityHandleFromClass(TSubclassOf InAbilityClass); 59 | 60 | protected: 61 | void GrantDefaultAbilitiesAndAttributes(); 62 | 63 | UFUNCTION() // UFunction to be able to bind with dynamic delegate 64 | void OnPawnControllerChanged(APawn* Pawn, AController* NewController); 65 | TArray DefaultAbilityHandles; 66 | 67 | UPROPERTY(transient) 68 | TArray AddedAttributes; 69 | }; 70 | -------------------------------------------------------------------------------- /Source/Ability/Public/Character/PlayerControlsComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "EnhancedInputComponent.h" 6 | #include "InputTriggers.h" 7 | #include "Components/PawnComponent.h" 8 | #include "PlayerControlsComponent.generated.h" 9 | 10 | class UEnhancedInputLocalPlayerSubsystem; 11 | class UEnhancedInputComponent; 12 | class UInputMappingContext; 13 | class UInputAction; 14 | 15 | /** Modular pawn component for adding input actions and an optional input mapping to a pawn */ 16 | UCLASS(Blueprintable, BlueprintType, ClassGroup = Input, Category = "Input", meta = (BlueprintSpawnableComponent)) 17 | class ABILITY_API UPlayerControlsComponent : public UPawnComponent 18 | { 19 | GENERATED_BODY() 20 | 21 | public: 22 | 23 | //~ Begin UActorComponent interface 24 | virtual void OnRegister() override; 25 | virtual void OnUnregister() override; 26 | //~ End UActorComponent interface 27 | 28 | /** Input mapping to add to the input system */ 29 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Player Controls") 30 | UInputMappingContext* InputMappingContext = nullptr; 31 | 32 | /** Priority to bind mapping context with */ 33 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Player Controls") 34 | int InputPriority = 0; 35 | 36 | protected: 37 | 38 | /** Native/BP Event to set up player controls */ 39 | UFUNCTION(BlueprintNativeEvent, Category = "Player Controls") 40 | void SetupPlayerControls(UEnhancedInputComponent* PlayerInputComponent); 41 | 42 | /** Native/BP Event to undo control setup */ 43 | UFUNCTION(BlueprintNativeEvent, Category = "Player Controls") 44 | void TeardownPlayerControls(UEnhancedInputComponent* PlayerInputComponent); 45 | 46 | /** Wrapper function for binding to this input component */ 47 | template 48 | bool BindInputAction(const UInputAction* Action, const ETriggerEvent EventType, UserClass* Object, FuncType Func) 49 | { 50 | if (ensure(InputComponent != nullptr) && ensure(Action != nullptr)) 51 | { 52 | InputComponent->BindAction(Action, EventType, Object, Func); 53 | return true; 54 | } 55 | 56 | return false; 57 | } 58 | 59 | /** Called when pawn restarts, bound to dynamic delegate */ 60 | UFUNCTION() 61 | virtual void OnPawnRestarted(APawn* Pawn); 62 | 63 | /** Called when pawn restarts, bound to dynamic delegate */ 64 | UFUNCTION() 65 | virtual void OnControllerChanged(APawn* Pawn, AController* OldController, AController* NewController); 66 | 67 | virtual void SetupInputComponent(APawn* Pawn); 68 | virtual void ReleaseInputComponent(AController* OldController = nullptr); 69 | UEnhancedInputLocalPlayerSubsystem* GetEnhancedInputSubsystem(AController* OldController = nullptr) const; 70 | 71 | /** The bound input component. */ 72 | UPROPERTY(transient) 73 | UEnhancedInputComponent* InputComponent; 74 | }; -------------------------------------------------------------------------------- /Source/Ability/Public/GASAssetManager.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Engine/AssetManager.h" 7 | #include "GASAssetManager.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class ABILITY_API UGASAssetManager : public UAssetManager 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | 19 | static UGASAssetManager& Get(); 20 | 21 | /** Starts initial load, gets called from InitializeObjectReferences */ 22 | virtual void StartInitialLoading() override; 23 | }; 24 | -------------------------------------------------------------------------------- /Source/Ability/Public/GASBlueprintLibrary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "Kismet/BlueprintFunctionLibrary.h" 5 | #include "Character/GameplayAbilitySystemComponent.h" 6 | #include "Character/Abilities/GASAbilityTypes.h" 7 | #include "Character/Abilities/GASGameplayAbility.h" 8 | #include "Character/Abilities/GASGameplayEffectTypes.h" 9 | #include "GASBlueprintLibrary.generated.h" 10 | 11 | /** 12 | * 13 | */ 14 | UCLASS() 15 | class ABILITY_API UGASBlueprintLibrary : public UBlueprintFunctionLibrary 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | // Returns the player's editor window role - Server (listen host) or Client # 21 | UFUNCTION(BlueprintCallable) 22 | static FString GetPlayerEditorWindowRole(UWorld* World); 23 | 24 | 25 | /** 26 | * GameplayAbility 27 | */ 28 | UFUNCTION(BlueprintCallable, Category = "Ability") 29 | static UGameplayAbility* GetPrimaryAbilityInstanceFromHandle(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle); 30 | 31 | UFUNCTION(BlueprintCallable, Category = "Ability") 32 | static UGameplayAbility* GetPrimaryAbilityInstanceFromClass(UAbilitySystemComponent* AbilitySystemComponent, TSubclassOf InAbilityClass); 33 | 34 | UFUNCTION(BlueprintCallable, Category = "Ability") 35 | static bool IsPrimaryAbilityInstanceActive(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle); 36 | 37 | 38 | /** 39 | * FGameplayAbilitySpecHandle 40 | */ 41 | UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Ability") 42 | static bool IsAbilitySpecHandleValid(FGameplayAbilitySpecHandle Handle); 43 | 44 | 45 | /** 46 | * FGASGameplayEffectContainerSpec 47 | */ 48 | 49 | // USTRUCTs cannot contain UFUNCTIONS so we make static functions here 50 | // Checks if spec has any effects 51 | UFUNCTION(BlueprintPure, Category = "Ability|Container") 52 | static bool DoesEffectContainerSpecHaveEffects(const FGASGameplayEffectContainerSpec& ContainerSpec); 53 | 54 | // Checks if spec has any targets 55 | UFUNCTION(BlueprintPure, Category = "Ability|Container") 56 | static bool DoesEffectContainerSpecHaveTargets(const FGASGameplayEffectContainerSpec& ContainerSpec); 57 | 58 | // Clears spec's targets 59 | UFUNCTION(BlueprintCallable, Category = "Ability|Container") 60 | static void ClearEffectContainerSpecTargets(UPARAM(ref) FGASGameplayEffectContainerSpec& ContainerSpec); 61 | 62 | // Adds targets to a copy of the passed in effect container spec and returns it 63 | UFUNCTION(BlueprintCallable, Category = "Ability|Container", Meta = (AutoCreateRefTerm = "TargetData, HitResults, TargetActors")) 64 | static void AddTargetsToEffectContainerSpec(UPARAM(ref) FGASGameplayEffectContainerSpec& ContainerSpec, const TArray& TargetData, const TArray& HitResults, const TArray& TargetActors); 65 | 66 | // Applies container spec that was made from an ability 67 | UFUNCTION(BlueprintCallable, Category = "Ability|Container") 68 | static TArray ApplyExternalEffectContainerSpec(const FGASGameplayEffectContainerSpec& ContainerSpec); 69 | 70 | 71 | /** 72 | * FGASGameplayEffectContext 73 | */ 74 | 75 | // Returns TargetData 76 | UFUNCTION(BlueprintCallable, Category = "Ability|EffectContext", Meta = (DisplayName = "GetTargetData")) 77 | static FGameplayAbilityTargetDataHandle EffectContextGetTargetData(FGameplayEffectContextHandle EffectContext); 78 | 79 | // Adds TargetData 80 | UFUNCTION(BlueprintCallable, Category = "Ability|EffectContext", Meta = (DisplayName = "AddTargetData")) 81 | static void EffectContextAddTargetData(FGameplayEffectContextHandle EffectContextHandle, const FGameplayAbilityTargetDataHandle& TargetData); 82 | 83 | 84 | /** 85 | * FGameplayAbilityTargetDataHandle 86 | */ 87 | UFUNCTION(BlueprintCallable, Category = "Ability|TargetData") 88 | static void ClearTargetData(UPARAM(ref) FGameplayAbilityTargetDataHandle& TargetData); 89 | }; 90 | -------------------------------------------------------------------------------- /Source/Ability/Public/GASEngineSubsystem.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Subsystems/EngineSubsystem.h" 7 | #include "GASEngineSubsystem.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class ABILITY_API UGASEngineSubsystem : public UEngineSubsystem 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | virtual void Initialize(FSubsystemCollectionBase& Collection) override; 19 | }; 20 | --------------------------------------------------------------------------------