diff --git a/Config/DefaultGameplayTags.ini b/Config/DefaultGameplayTags.ini index f40c732..2c0fe0a 100644 --- a/Config/DefaultGameplayTags.ini +++ b/Config/DefaultGameplayTags.ini @@ -44,6 +44,8 @@ NetIndexFirstBitSegment=16 +GameplayTagList=(Tag="Ability.Type.Passive.Interaction",DevComment="") +GameplayTagList=(Tag="Ability.Type.PriorityAction.ADS",DevComment="") +GameplayTagList=(Tag="Ability.Type.PriorityAction.Evade",DevComment="") ++GameplayTagList=(Tag="Ability.Type.PriorityAction.Evade.JumpPack",DevComment="") ++GameplayTagList=(Tag="Ability.Type.PriorityAction.Evade.Rolling",DevComment="") +GameplayTagList=(Tag="Ability.Type.PriorityAction.Grenade",DevComment="") +GameplayTagList=(Tag="Ability.Type.PriorityAction.Reload",DevComment="") +GameplayTagList=(Tag="Ability.Type.PriorityAction.WeaponFire",DevComment="") @@ -88,6 +90,7 @@ NetIndexFirstBitSegment=16 +GameplayTagList=(Tag="Event.Movement.Reload",DevComment="") +GameplayTagList=(Tag="Event.Movement.Sprint",DevComment="") +GameplayTagList=(Tag="Event.Movement.WeaponFire",DevComment="") ++GameplayTagList=(Tag="Gameplay.Stun.StunImmunity",DevComment="") +GameplayTagList=(Tag="Gameplay.Zone.StrongSpot",DevComment="") +GameplayTagList=(Tag="Gameplay.Zone.Weakspot",DevComment="") +GameplayTagList=(Tag="GameplayCue.Character.Attributes.EvasionStamina.Added",DevComment="") diff --git a/Source/ECR/Private/Gameplay/Character/ECRPawnControlComponent.cpp b/Source/ECR/Private/Gameplay/Character/ECRPawnControlComponent.cpp index bfbdc08..40c5f3c 100644 --- a/Source/ECR/Private/Gameplay/Character/ECRPawnControlComponent.cpp +++ b/Source/ECR/Private/Gameplay/Character/ECRPawnControlComponent.cpp @@ -40,6 +40,9 @@ UECRPawnControlComponent::UECRPawnControlComponent(const FObjectInitializer& Obj bPawnHasInitialized = false; bReadyToBindInputs = false; bMovementInputEnabled = true; + + bListenForAbilityQueue = false; + AbilityQueueDeltaTime = 0; } void UECRPawnControlComponent::OnRegister() @@ -257,9 +260,25 @@ void UECRPawnControlComponent::BindNativeActions(UECRInputComponent* ECRIC, cons { const FECRGameplayTags& GameplayTags = FECRGameplayTags::Get(); ECRIC->BindNativeAction(InputConfig, GameplayTags.InputTag_Look_Mouse, ETriggerEvent::Triggered, this, - &ThisClass::Input_LookMouse, /*bLogIfNotFound=*/ true); + &ThisClass::Input_LookMouse, /*bLogIfNotFound=*/ true); ECRIC->BindNativeAction(InputConfig, GameplayTags.InputTag_Look_Stick, ETriggerEvent::Triggered, this, - &ThisClass::Input_LookStick, /*bLogIfNotFound=*/ false); + &ThisClass::Input_LookStick, /*bLogIfNotFound=*/ false); +} + +void UECRPawnControlComponent::NotifyAbilityQueueSystem(UECRAbilitySystemComponent* ASC, const FGameplayTag& InputTag) +{ + if (InputTag.IsValid() && bListenForAbilityQueue && AbilityQueueInputTags.HasTagExact(InputTag)) + { + ASC->AbilityQueueSystemLastInputTag = InputTag; + ASC->AbilityQueueSystemLastInputTagTime = GetWorld()->GetTimeSeconds(); + ASC->AbilityQueueSystemDeltaTime = AbilityQueueDeltaTime; + } + else + { + ASC->AbilityQueueSystemLastInputTag = {}; + ASC->AbilityQueueSystemLastInputTagTime = 0; + ASC->AbilityQueueSystemDeltaTime = 0; + } } @@ -317,6 +336,7 @@ void UECRPawnControlComponent::Input_AbilityInputTagPressed(FGameplayTag InputTa if (UECRAbilitySystemComponent* ECRASC = PawnExtComp->GetECRAbilitySystemComponent()) { ECRASC->AbilityInputTagPressed(InputTag); + NotifyAbilityQueueSystem(ECRASC, InputTag); } } } diff --git a/Source/ECR/Private/Gameplay/GAS/Abilities/ECRGameplayAbility.cpp b/Source/ECR/Private/Gameplay/GAS/Abilities/ECRGameplayAbility.cpp index 9fa9f2d..71544de 100644 --- a/Source/ECR/Private/Gameplay/GAS/Abilities/ECRGameplayAbility.cpp +++ b/Source/ECR/Private/Gameplay/GAS/Abilities/ECRGameplayAbility.cpp @@ -97,7 +97,9 @@ AECRCharacter* UECRGameplayAbility::GetECRCharacterFromActorInfo() const UECRPawnControlComponent* UECRGameplayAbility::GetHeroComponentFromActorInfo() const { - return (CurrentActorInfo ? UECRPawnControlComponent::FindPawnControlComonent(CurrentActorInfo->AvatarActor.Get()) : nullptr); + return (CurrentActorInfo + ? UECRPawnControlComponent::FindPawnControlComonent(CurrentActorInfo->AvatarActor.Get()) + : nullptr); } void UECRGameplayAbility::ToggleInputDisabled(const bool NewInputDisabled) @@ -252,6 +254,8 @@ void UECRGameplayAbility::EndAbility(const FGameplayAbilitySpecHandle Handle, ClearCameraMode(); Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled); + + CheckAbilityQueue(ActorInfo); } bool UECRGameplayAbility::CheckCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, @@ -558,6 +562,24 @@ UECRPawnComponent_CharacterParts* UECRGameplayAbility::GetPawnCustomizationCompo } +void UECRGameplayAbility::CheckAbilityQueue(const FGameplayAbilityActorInfo* ActorInfo) const +{ + if (UECRAbilitySystemComponent* ASC = Cast(ActorInfo->AbilitySystemComponent.Get())) + { + const double CurrentTime = GetWorld()->GetTimeSeconds(); + + if (ASC->AbilityQueueSystemLastInputTag.IsValid() && (ASC->AbilityQueueSystemDeltaTime == 0 || CurrentTime - ASC + ->AbilityQueueSystemLastInputTagTime < ASC->AbilityQueueSystemDeltaTime)) + { + ASC->AbilityInputTagPressed(ASC->AbilityQueueSystemLastInputTag); + } + + ASC->AbilityQueueSystemLastInputTag = {}; + ASC->AbilityQueueSystemLastInputTagTime = 0; + } +} + + void UECRGameplayAbility::LoadMontages() { TArray MontagesToLoad; diff --git a/Source/ECR/Private/Gameplay/GAS/ECRAbilitySystemComponent.cpp b/Source/ECR/Private/Gameplay/GAS/ECRAbilitySystemComponent.cpp index 6100029..f2c14bd 100644 --- a/Source/ECR/Private/Gameplay/GAS/ECRAbilitySystemComponent.cpp +++ b/Source/ECR/Private/Gameplay/GAS/ECRAbilitySystemComponent.cpp @@ -17,6 +17,10 @@ UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_AbilityInputBlocked, "Gameplay.AbilityInputB UECRAbilitySystemComponent::UECRAbilitySystemComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { + AbilityQueueSystemLastInputTag = {}; + AbilityQueueSystemLastInputTagTime = 0; + AbilityQueueSystemDeltaTime = 0; + InputPressedSpecHandles.Reset(); InputReleasedSpecHandles.Reset(); InputHeldSpecHandles.Reset(); @@ -402,7 +406,7 @@ void UECRAbilitySystemComponent::ClearAllResettingOnDeathAbilities() // Get all activatable abilities TArray OutSpecHandles; GetAllAbilities(OutSpecHandles); - + for (const FGameplayAbilitySpecHandle CurrentSpecHandle : OutSpecHandles) { const FGameplayAbilitySpec* AbilitySpec = FindAbilitySpecFromHandle(CurrentSpecHandle); diff --git a/Source/ECR/Public/Gameplay/Character/ECRPawnControlComponent.h b/Source/ECR/Public/Gameplay/Character/ECRPawnControlComponent.h index ceedf91..b6ffd43 100644 --- a/Source/ECR/Public/Gameplay/Character/ECRPawnControlComponent.h +++ b/Source/ECR/Public/Gameplay/Character/ECRPawnControlComponent.h @@ -7,6 +7,7 @@ #include "Gameplay/Camera/ECRCameraMode.h" #include "GameplayTagContainer.h" #include "GameplayAbilitySpec.h" +#include "Gameplay/GAS/ECRAbilitySet.h" #include "Input/ECRMappableConfigPair.h" #include "ECRPawnControlComponent.generated.h" @@ -67,6 +68,8 @@ class UECRPawnControlComponent : public UECRPawnComponent virtual void InitializePlayerInput(UInputComponent* PlayerInputComponent); virtual void BindNativeActions(UECRInputComponent* ECRIC, const UECRInputConfig* InputConfig); + void NotifyAbilityQueueSystem(UECRAbilitySystemComponent* ASC, const FGameplayTag& InputTag); + void Input_AbilityInputTagPressed(FGameplayTag InputTag); void Input_AbilityInputTagReleased(FGameplayTag InputTag); @@ -76,6 +79,10 @@ class UECRPawnControlComponent : public UECRPawnComponent TSubclassOf DetermineCameraMode() const; protected: + /** List of input tags handled by ability queue system */ + UPROPERTY(EditAnywhere) + FGameplayTagContainer AbilityQueueInputTags; + /** * Input Configs that should be added to this player when initalizing the input. * @@ -99,4 +106,11 @@ class UECRPawnControlComponent : public UECRPawnComponent // True if movement input enabled (by default) bool bMovementInputEnabled; + +public: + // True when should listen for ability queue + bool bListenForAbilityQueue; + + // Delta time for ability queue system + double AbilityQueueDeltaTime; }; diff --git a/Source/ECR/Public/Gameplay/GAS/Abilities/ECRGameplayAbility.h b/Source/ECR/Public/Gameplay/GAS/Abilities/ECRGameplayAbility.h index 7c8efc7..062ee31 100644 --- a/Source/ECR/Public/Gameplay/GAS/Abilities/ECRGameplayAbility.h +++ b/Source/ECR/Public/Gameplay/GAS/Abilities/ECRGameplayAbility.h @@ -157,6 +157,7 @@ class UECRGameplayAbility : public UGameplayAbility virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override; + virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override; @@ -199,7 +200,10 @@ class UECRGameplayAbility : public UGameplayAbility void OnCharacterPartsChanged(UECRPawnComponent_CharacterParts* ComponentWithChangedParts); UECRPawnComponent_CharacterParts* GetPawnCustomizationComponent() const; -protected: + + /** Check for ability queue on ASC, if need to activate any queued ability */ + void CheckAbilityQueue(const FGameplayAbilityActorInfo* ActorInfo) const; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Animation") TMap AbilityMontageSelection; diff --git a/Source/ECR/Public/Gameplay/GAS/ECRAbilitySystemComponent.h b/Source/ECR/Public/Gameplay/GAS/ECRAbilitySystemComponent.h index ff12932..00ca6eb 100644 --- a/Source/ECR/Public/Gameplay/GAS/ECRAbilitySystemComponent.h +++ b/Source/ECR/Public/Gameplay/GAS/ECRAbilitySystemComponent.h @@ -105,4 +105,16 @@ class UECRAbilitySystemComponent : public UAbilitySystemComponent // Number of abilities running in each activation group. int32 ActivationGroupCounts[(uint8)EECRAbilityActivationGroup::MAX]; + +public: + // Ability Queue System + + // Latest input tag received + FGameplayTag AbilityQueueSystemLastInputTag; + + // Time when received + double AbilityQueueSystemLastInputTagTime; + + // Delta time + double AbilityQueueSystemDeltaTime; }; diff --git a/Source/ECR/Public/Input/AnimNotifyState_ECRAbilityQueueListen.cpp b/Source/ECR/Public/Input/AnimNotifyState_ECRAbilityQueueListen.cpp new file mode 100644 index 0000000..176c518 --- /dev/null +++ b/Source/ECR/Public/Input/AnimNotifyState_ECRAbilityQueueListen.cpp @@ -0,0 +1,35 @@ +#include "AnimNotifyState_ECRAbilityQueueListen.h" + +#include "Gameplay/Character/ECRPawnControlComponent.h" + +void UAnimNotifyState_ECRAbilityQueueListen::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) +{ + AActor* Actor = MeshComp->GetOwner(); + if (!Actor->HasLocalNetOwner()) + { + return; + } + + if (UECRPawnControlComponent* PCC = Actor->FindComponentByClass()) + { + PCC->bListenForAbilityQueue = false; + PCC->AbilityQueueDeltaTime = 0; + } +} + +void UAnimNotifyState_ECRAbilityQueueListen::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + float TotalDuration, + const FAnimNotifyEventReference& EventReference) +{ + AActor* Actor = MeshComp->GetOwner(); + if (!Actor->HasLocalNetOwner()) + { + return; + } + + if (UECRPawnControlComponent* PCC = Actor->FindComponentByClass()) + { + PCC->bListenForAbilityQueue = true; + PCC->AbilityQueueDeltaTime = AbilityQueueDeltaTime; + } +} diff --git a/Source/ECR/Public/Input/AnimNotifyState_ECRAbilityQueueListen.h b/Source/ECR/Public/Input/AnimNotifyState_ECRAbilityQueueListen.h new file mode 100644 index 0000000..95a9b7e --- /dev/null +++ b/Source/ECR/Public/Input/AnimNotifyState_ECRAbilityQueueListen.h @@ -0,0 +1,28 @@ +// Copyleft: All rights reversed + +#pragma once + +#include "CoreMinimal.h" +#include "FMODBlueprintStatics.h" +#include "Animation/AnimNotifies/AnimNotifyState.h" +#include "AnimNotifyState_ECRAbilityQueueListen.generated.h" + + +/** + * UAnimNotifyState_ECRAbilityQueueListen + * + * Set bListenForAbilityQueue to true on PawnControlComponent while active + */ +UCLASS() +class ECR_API UAnimNotifyState_ECRAbilityQueueListen : public UAnimNotifyState +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess="true")) + double AbilityQueueDeltaTime = 0; + +public: + virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override; + virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, + const FAnimNotifyEventReference& EventReference) override; +};