// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. #pragma once #include "CoreMinimal.h" #include "AbilitySystemComponent.h" #include "NativeGameplayTags.h" #include "Abilities/OLSGameplayAbility.h" #include "OLSAbilitySystemComponent.generated.h" DECLARE_LOG_CATEGORY_EXTERN(LogOLSAbilitySystemComponent, Verbose, All); OLS_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_AbilityInputBlocked); /** * CVAR to control the "Play Montage" flow. * Example: OLS.EnableDefaultPlayMontage true */ static bool GEnableDefaultPlayMontage = false; static FAutoConsoleVariableRef CVarEnableDefaultPlayMontage( TEXT("OLS.EnableDefaultPlayMontage"), GEnableDefaultPlayMontage, TEXT("Enables or disables the PlayMontage default behavior."), ECVF_Default ); UCLASS(ClassGroup=(OLS), meta=(BlueprintSpawnableComponent)) class OLS_API UOLSAbilitySystemComponent : public UAbilitySystemComponent { GENERATED_BODY() public: // Sets default values for this component's properties UOLSAbilitySystemComponent(); // -- Begin Ability System Component implementation virtual void InitAbilityActorInfo( AActor* ownerActor, AActor* avatarActor) override; virtual bool ShouldDoServerAbilityRPCBatch() const override; virtual float PlayMontage( UGameplayAbility* animatingAbility, FGameplayAbilityActivationInfo activationInfo, UAnimMontage* montage, float playRate, FName startSectionName, float startTimeSeconds) override; // -- End Ability System Component implementation public: /** * Obtains the Anim Instance from the Actor Info. * * Takes into consideration the pointer in the Actor Info, before calling the * Getter function that will always attempt to retrieve it from the mesh. */ UFUNCTION(BlueprintPure, Category = "OLS Ability System") virtual UAnimInstance* GetAnimInstanceFromActorInfo() const; /** * Grants a new effect to the owner. * * @param effectClass Effect class being granted to the owner. * @param level Initial level for the effect. * @return The handle that can be used for maintenance. */ UFUNCTION(BlueprintCallable, Category = "OLS Ability System") FActiveGameplayEffectHandle ApplyGameplayEffectClassToSelf( TSubclassOf effectClass, float level = 1); /** * Grants a new ability to the owner. * * @param abilityClass Ability class being granted to the owner. * @param level Initial level for the ability. * @param input An Input ID for the old input system. * @return The handle that can be used for activation. */ UFUNCTION(BlueprintCallable, Category = "OLS Ability System") FGameplayAbilitySpecHandle GiveAbilityFromClass( const TSubclassOf abilityClass, int32 level = 1, int32 input = -1); /** * Tries to activate the ability by the handle, aggregating all RPCs that happened in the same frame. * * @param abilityHandle * Handle used to identify the ability. * * @param shouldEndAbilityImmediately * Determines if the EndAbility is triggered right away or later, with its own RPC. This requires the Ability * to either implement IBatchGameplayAbilityInterface or be a subclass of NinjaGASGameplayAbility. */ UFUNCTION(BlueprintCallable, Category = "OLS Ability System") virtual bool TryBatchActivateAbility( FGameplayAbilitySpecHandle abilityHandle, bool shouldEndAbilityImmediately); /** * Cancels Gameplay Abilities by their matching tags. * * @param abilityTags Gameplay Tags used to target abilities to cancel. * @param cancelFilterTags A filter that excludes an ability from being cancelled. */ UFUNCTION(BlueprintCallable, Category = "OLS Ability System") virtual void CancelAbilitiesByTags( FGameplayTagContainer abilityTags, FGameplayTagContainer cancelFilterTags); /** * Locally executes a Static Gameplay Cue. * * @param gameplayCueTag Gameplay Tag for the Gameplay Cue. * @param gameplayCueParameters Parameters for the Gameplay Cue. */ UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "OLS Ability System", meta = (AutoCreateRefTerm = "GameplayCueParameters", GameplayTagFilter = "GameplayCue")) void ExecuteGameplayCueLocal( const FGameplayTag gameplayCueTag, const FGameplayCueParameters& gameplayCueParameters) const; /** * Locally adds an Actor Gameplay Cue. * * When adding this Gameplay Cue locally, make sure to also remove it locally. * * @param gameplayCueTag Gameplay Tag for the Gameplay Cue. * @param gameplayCueParameters Parameters for the Gameplay Cue. */ UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "OLS Ability System", meta = (AutoCreateRefTerm = "GameplayCueParameters")) void AddGameplayCueLocally( UPARAM(meta = (Categories = "GameplayCue")) const FGameplayTag gameplayCueTag, const FGameplayCueParameters& gameplayCueParameters) const; /** * Locally removes an Actor Gameplay Cue. * * @param gameplayCueTag Gameplay Tag for the Gameplay Cue. * @param gameplayCueParameters Parameters for the Gameplay Cue. */ UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "OLS Ability System", meta = (AutoCreateRefTerm = "GameplayCueParameters")) void RemoveGameplayCueLocally( UPARAM(meta = (Categories = "GameplayCue")) const FGameplayTag gameplayCueTag, const FGameplayCueParameters& gameplayCueParameters) const; protected: /** * Attempts to activate any abilities that are set to automatically trigger upon the actor's spawn. * Typically used for gameplay abilities that need to be initialized or activated as soon as the actor is created. */ void TryActivateAbilitiesOnSpawn(); virtual void AbilitySpecInputPressed(FGameplayAbilitySpec& spec) override; virtual void AbilitySpecInputReleased(FGameplayAbilitySpec& spec) override; virtual void NotifyAbilityActivated(const FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability) override; virtual void NotifyAbilityFailed(const FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability, const FGameplayTagContainer& failureReason) override; virtual void NotifyAbilityEnded(FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability, bool bWasCancelled) override; virtual void ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& abilityTags, class UGameplayAbility* requestingAbility, bool shouldEnableBlockTags, const FGameplayTagContainer& blockTags, bool shouldExecuteCancelTags, const FGameplayTagContainer& cancelTags) override; virtual void HandleChangeAbilityCanBeCanceled(const FGameplayTagContainer& abilityTags, class UGameplayAbility* requestingAbility, bool canBeCanceled) override; /** Notify client that an ability failed to activate */ UFUNCTION(Client, Unreliable) void ClientNotifyAbilityFailed(const class UGameplayAbility* ability, const FGameplayTagContainer& failureReason); void HandleAbilityFailed(const class UGameplayAbility* ability, const FGameplayTagContainer& failureReason); /** * Conveniently separates the code that sets the animation to replicate, so it can be further modified. */ virtual void SetReplicatedMontageInfo(FGameplayAbilityRepAnimMontage& mutableRepAnimMontageInfo, UAnimMontage* newMontageToPlay, const FName& startSectionName); public: typedef TFunctionRef TShouldCancelAbilityFunc; void CancelAbilitiesByFunc(TShouldCancelAbilityFunc shouldCancelFunc, bool shouldReplicateCancelAbility); void CancelInputActivatedAbilities(bool shouldReplicateCancelAbility); void AbilityInputTagPressed(const FGameplayTag& inputTag); void AbilityInputTagReleased(const FGameplayTag& inputTag); void ProcessAbilityInput(float deltaTime, bool shouldGamePaused); void ClearAbilityInput(); bool IsActivationGroupBlocked(EOLSAbilityActivationGroup Group) const; void AddAbilityToActivationGroup(EOLSAbilityActivationGroup group, UOLSGameplayAbility* ability); void RemoveAbilityFromActivationGroup(EOLSAbilityActivationGroup group, UOLSGameplayAbility* ability); void CancelActivationGroupAbilities(EOLSAbilityActivationGroup group, UOLSGameplayAbility* ignoreAbility, bool shouldReplicateCancelAbility); // Uses a gameplay effect to add the specified dynamic granted tag. void AddDynamicTagGameplayEffect(const FGameplayTag& tag); // Removes all active instances of the gameplay effect that was used to add the specified dynamic granted tag. void RemoveDynamicTagGameplayEffect(const FGameplayTag& Tag); /** Gets the ability target data associated with the given ability handle and activation info */ void GetAbilityTargetData(const FGameplayAbilitySpecHandle abilityHandle, FGameplayAbilityActivationInfo activationInfo, FGameplayAbilityTargetDataHandle& outTargetDataHandle); /** Sets the current tag relationship mapping, if null it will clear it out */ void SetTagRelationshipMapping(class UOLSAbilityTagRelationshipMappingDataAsset* newMapping); /** Looks at ability tags and gathers additional required and blocking tags */ void GetAdditionalActivationTagRequirements(const FGameplayTagContainer& abilityTags, FGameplayTagContainer& outActivationRequired, FGameplayTagContainer& outActivationBlocked) const; private: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS Ability System", DisplayName = "Enable Ability Batch RPCs", meta = (AllowPrivateAccess = true)) uint8 bShouldEnableBatchRPC : 1 = true; protected: // If set, this table is used to look up tag relationships for activate and cancel UPROPERTY() TObjectPtr TagRelationshipMapping = nullptr; // Handles to abilities that had their input pressed this frame. TArray InputPressedSpecHandles; // Handles to abilities that had their input released this frame. TArray InputReleasedSpecHandles; // Handles to abilities that have their input held. TArray InputHeldSpecHandles; // Number of abilities running in each activation group. int32 ActivationGroupCounts[(uint8)EOLSAbilityActivationGroup::MAX]; };