From 0e12b3d0c3e8ba3104ef2d1991ad2885ec5b2ec6 Mon Sep 17 00:00:00 2001 From: Caleb Buhungiro Date: Wed, 9 Jul 2025 12:32:45 +0800 Subject: [PATCH] Add animation Montage triggered through ability to play different Montage Sections. --- Config/DefaultGameplayTags.ini | 7 ++ .../Combo/Animations/AM_ComboCrunch.uasset | 4 +- .../9/00/8CREGCY2EKTUAKJ6ZPICVF.uasset | 3 + .../E/CV/HPHV6T91WYP5H8RAOZZ7U7.uasset | 2 +- .../Animations/AN_SendGameplayEvent.cpp | 29 +++++++ .../Crunch/Private/GAS/CGameplayAbility.cpp | 9 ++ Source/Crunch/Private/GAS/GA_Combo.cpp | 83 ++++++++++++++++++- .../Public/Animations/AN_SendGameplayEvent.h | 25 ++++++ Source/Crunch/Public/GAS/CGameplayAbility.h | 2 + Source/Crunch/Public/GAS/GA_Combo.h | 19 ++++- 10 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 Content/__ExternalActors__/TempLevel/9/00/8CREGCY2EKTUAKJ6ZPICVF.uasset create mode 100644 Source/Crunch/Private/Animations/AN_SendGameplayEvent.cpp create mode 100644 Source/Crunch/Public/Animations/AN_SendGameplayEvent.h diff --git a/Config/DefaultGameplayTags.ini b/Config/DefaultGameplayTags.ini index a07c1b3..58cd53e 100644 --- a/Config/DefaultGameplayTags.ini +++ b/Config/DefaultGameplayTags.ini @@ -1,4 +1,5 @@ ;METADATA=(Diff=true, UseCommands=true) + [/Script/GameplayTags.GameplayTagsSettings] ImportTagsFromConfig=True WarnOnInvalidTags=True @@ -11,4 +12,10 @@ InvalidTagCharacters="\"\'," NumBitsForContainerSize=6 NetIndexFirstBitSegment=16 +GameplayTagList=(Tag="ability.basicattack",DevComment="Ability Tag assigned to basic attack abilities") ++GameplayTagList=(Tag="ability.combo.change",DevComment="") ++GameplayTagList=(Tag="ability.combo.change.combo01",DevComment="") ++GameplayTagList=(Tag="ability.combo.change.combo02",DevComment="") ++GameplayTagList=(Tag="ability.combo.change.combo03",DevComment="") ++GameplayTagList=(Tag="ability.combo.change.combo04",DevComment="") ++GameplayTagList=(Tag="ability.combo.change.end",DevComment="") diff --git a/Content/Characters/Crunch/GameplayAbility/Combo/Animations/AM_ComboCrunch.uasset b/Content/Characters/Crunch/GameplayAbility/Combo/Animations/AM_ComboCrunch.uasset index bc69e69..b04ca5f 100644 --- a/Content/Characters/Crunch/GameplayAbility/Combo/Animations/AM_ComboCrunch.uasset +++ b/Content/Characters/Crunch/GameplayAbility/Combo/Animations/AM_ComboCrunch.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7eaa7d066552b478515b4862e607ac12e1cc7d1e860799fd8bd2067fd4e70ac4 -size 13092 +oid sha256:25b8e8d981e98b6948c9d55644fd47f8aa7db50b15001a3a5412b167b4d25dea +size 24606 diff --git a/Content/__ExternalActors__/TempLevel/9/00/8CREGCY2EKTUAKJ6ZPICVF.uasset b/Content/__ExternalActors__/TempLevel/9/00/8CREGCY2EKTUAKJ6ZPICVF.uasset new file mode 100644 index 0000000..6a0e297 --- /dev/null +++ b/Content/__ExternalActors__/TempLevel/9/00/8CREGCY2EKTUAKJ6ZPICVF.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0dfd98ed5263bde4bd507eefc206210646ed0163987f907b9bc17b79851bdb94 +size 4660 diff --git a/Content/__ExternalActors__/TempLevel/E/CV/HPHV6T91WYP5H8RAOZZ7U7.uasset b/Content/__ExternalActors__/TempLevel/E/CV/HPHV6T91WYP5H8RAOZZ7U7.uasset index a2734aa..fbf27d4 100644 --- a/Content/__ExternalActors__/TempLevel/E/CV/HPHV6T91WYP5H8RAOZZ7U7.uasset +++ b/Content/__ExternalActors__/TempLevel/E/CV/HPHV6T91WYP5H8RAOZZ7U7.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a38c710809c68668a9ba27621584ad8947413eaab84df811f5f6900e6f989105 +oid sha256:716d35fd9ec961eed0f3c81776c1725c608c641f3fe3606b3a7969a8577ab15d size 4411 diff --git a/Source/Crunch/Private/Animations/AN_SendGameplayEvent.cpp b/Source/Crunch/Private/Animations/AN_SendGameplayEvent.cpp new file mode 100644 index 0000000..ac030e9 --- /dev/null +++ b/Source/Crunch/Private/Animations/AN_SendGameplayEvent.cpp @@ -0,0 +1,29 @@ +// Multiplayer By Caleb + + +#include "Animations/AN_SendGameplayEvent.h" + +#include "AbilitySystemBlueprintLibrary.h" +#include "GameplayTagsManager.h" + +void UAN_SendGameplayEvent::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + const FAnimNotifyEventReference& EventReference) +{ + Super::Notify(MeshComp, Animation, EventReference); + + const auto OwnerActor{MeshComp->GetOwner()}; + if (!OwnerActor) return; + if (const auto OwnerAsc{UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(OwnerActor)}; !OwnerAsc) return; + UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(OwnerActor, EventTag, FGameplayEventData()); +} + +FString UAN_SendGameplayEvent::GetNotifyName_Implementation() const +{ + if (EventTag.IsValid()) + { + TArray TagNames; + UGameplayTagsManager::Get().SplitGameplayTagFName(EventTag, TagNames); + return TagNames.Last().ToString(); + } + return "None"; +} diff --git a/Source/Crunch/Private/GAS/CGameplayAbility.cpp b/Source/Crunch/Private/GAS/CGameplayAbility.cpp index 5de57f9..edac5ef 100644 --- a/Source/Crunch/Private/GAS/CGameplayAbility.cpp +++ b/Source/Crunch/Private/GAS/CGameplayAbility.cpp @@ -2,3 +2,12 @@ #include "GAS/CGameplayAbility.h" + +UAnimInstance* UCGameplayAbility::GetOwnerAnimInstance() +{ + if (const auto OwnerSkeletalMeshComp{GetOwningComponentFromActorInfo()}) + { + return OwnerSkeletalMeshComp->GetAnimInstance(); + } + return nullptr; +} diff --git a/Source/Crunch/Private/GAS/GA_Combo.cpp b/Source/Crunch/Private/GAS/GA_Combo.cpp index c0a1111..f815092 100644 --- a/Source/Crunch/Private/GAS/GA_Combo.cpp +++ b/Source/Crunch/Private/GAS/GA_Combo.cpp @@ -3,7 +3,10 @@ #include "GAS/GA_Combo.h" +#include "GameplayTagsManager.h" #include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h" +#include "Abilities/Tasks/AbilityTask_WaitGameplayEvent.h" +#include "Abilities/Tasks/AbilityTask_WaitInputPress.h" #include "GAS/UCAbilitySystemStatics.h" UGA_Combo::UGA_Combo() @@ -27,12 +30,90 @@ void UGA_Combo::ActivateAbility(const FGameplayAbilitySpecHandle Handle, if (HasAuthorityOrPredictionKey(ActorInfo, &ActivationInfo)) { const auto PlayComboMontage{ - UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(this, NAME_None, ComboMontage) + UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy( + this, + NAME_None, + ComboMontage + ) }; PlayComboMontage->OnBlendOut.AddDynamic(this, &UGA_Combo::K2_EndAbility); PlayComboMontage->OnCancelled.AddDynamic(this, &UGA_Combo::K2_EndAbility); PlayComboMontage->OnCompleted.AddDynamic(this, &UGA_Combo::K2_EndAbility); PlayComboMontage->OnInterrupted.AddDynamic(this, &UGA_Combo::K2_EndAbility); PlayComboMontage->ReadyForActivation(); + + /** + * Handle Setting the next combo section in current Montage + * This {ChangedEventTag} will mach all the tags under [changed] tag hierchy + * this will insure the event is Sents for all the tags(all the animation sections in Montage) + ****/ + const auto ChangedEventTag{GetComboChangedEventTag()}; + const auto WaitComboChangeEventTask{ + UAbilityTask_WaitGameplayEvent::WaitGameplayEvent( + this, + ChangedEventTag, + nullptr, + false, + false + ) + }; + WaitComboChangeEventTask->EventReceived.AddDynamic(this, &UGA_Combo::ComboChangedEventReceived); + WaitComboChangeEventTask->ReadyForActivation(); } + + SetupWaitComboInputPressed(); +} + +void UGA_Combo::ComboChangedEventReceived(FGameplayEventData Data) +{ + const auto EventTag{Data.EventTag}; + if (EventTag == GetComboChangedEventEndTag()) + { + NextComboName = NAME_None; + UE_LOG(LogTemp, Warning, TEXT("next combo is cleared")); + return; + } + + TArray TagNames; + UGameplayTagsManager::Get().SplitGameplayTagFName(EventTag, TagNames); + NextComboName = TagNames.Last(); + + UE_LOG(LogTemp, Warning, TEXT("next combo is: %s"), *NextComboName.ToString()); +} + +FGameplayTag UGA_Combo::GetComboChangedEventTag() +{ + return FGameplayTag::RequestGameplayTag("ability.combo.change"); +} + +FGameplayTag UGA_Combo::GetComboChangedEventEndTag() +{ + return FGameplayTag::RequestGameplayTag("ability.combo.change.end"); +} + +void UGA_Combo::SetupWaitComboInputPressed() +{ + const auto WaitInputPress{UAbilityTask_WaitInputPress::WaitInputPress(this)}; + WaitInputPress->OnPress.AddDynamic(this, &UGA_Combo::HandleInputPress); + WaitInputPress->ReadyForActivation(); +} + +void UGA_Combo::HandleInputPress(float TimeWaited) +{ + SetupWaitComboInputPressed(); + TryCommitCombo(); +} + +void UGA_Combo::TryCommitCombo() +{ + const auto OwnerAnimInstance{GetOwnerAnimInstance()}; + if (NextComboName == NAME_None || !OwnerAnimInstance) return; + + const auto SectionNameToChange{OwnerAnimInstance->Montage_GetCurrentSection(ComboMontage)}; + + OwnerAnimInstance->Montage_SetNextSection( + SectionNameToChange, + NextComboName, + ComboMontage + ); } diff --git a/Source/Crunch/Public/Animations/AN_SendGameplayEvent.h b/Source/Crunch/Public/Animations/AN_SendGameplayEvent.h new file mode 100644 index 0000000..ef105de --- /dev/null +++ b/Source/Crunch/Public/Animations/AN_SendGameplayEvent.h @@ -0,0 +1,25 @@ +// Multiplayer By Caleb + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTagContainer.h" +#include "Animation/AnimNotifies/AnimNotify.h" +#include "AN_SendGameplayEvent.generated.h" + +/** + * + */ +UCLASS() +class CRUNCH_API UAN_SendGameplayEvent : public UAnimNotify +{ + GENERATED_BODY() + + +public: + virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; +private: + UPROPERTY(EditAnywhere, Category= "Gameplay Ability") + FGameplayTag EventTag; + virtual FString GetNotifyName_Implementation() const override; +}; diff --git a/Source/Crunch/Public/GAS/CGameplayAbility.h b/Source/Crunch/Public/GAS/CGameplayAbility.h index 5484a8b..ba839e8 100644 --- a/Source/Crunch/Public/GAS/CGameplayAbility.h +++ b/Source/Crunch/Public/GAS/CGameplayAbility.h @@ -13,4 +13,6 @@ UCLASS() class CRUNCH_API UCGameplayAbility : public UGameplayAbility { GENERATED_BODY() +protected: + UAnimInstance* GetOwnerAnimInstance(); }; diff --git a/Source/Crunch/Public/GAS/GA_Combo.h b/Source/Crunch/Public/GAS/GA_Combo.h index cb0973e..d2caba3 100644 --- a/Source/Crunch/Public/GAS/GA_Combo.h +++ b/Source/Crunch/Public/GAS/GA_Combo.h @@ -13,10 +13,27 @@ UCLASS() class CRUNCH_API UGA_Combo : public UCGameplayAbility { GENERATED_BODY() + public: UGA_Combo(); - virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override; + virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, + const FGameplayAbilityActivationInfo ActivationInfo, + const FGameplayEventData* TriggerEventData) override; + static FGameplayTag GetComboChangedEventTag(); + static FGameplayTag GetComboChangedEventEndTag(); + private: + UFUNCTION() + void HandleInputPress(float TimeWaited); + + void SetupWaitComboInputPressed(); + void TryCommitCombo(); + UPROPERTY(EditDefaultsOnly, Category="Amination") TObjectPtr ComboMontage; + + UFUNCTION() + void ComboChangedEventReceived(FGameplayEventData Data); + + FName NextComboName; };