completed attack combo with GameplayEffects and GameplayCues
This commit is contained in:
30
Source/Crunch/Private/Animations/AN_SendTargetGroup.cpp
Normal file
30
Source/Crunch/Private/Animations/AN_SendTargetGroup.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// Multiplayer By Caleb
|
||||
|
||||
|
||||
#include "Animations/AN_SendTargetGroup.h"
|
||||
|
||||
#include "AbilitySystemBlueprintLibrary.h"
|
||||
|
||||
void UAN_SendTargetGroup::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
|
||||
const FAnimNotifyEventReference& EventReference)
|
||||
{
|
||||
Super::Notify(MeshComp, Animation, EventReference);
|
||||
|
||||
if (!MeshComp || !MeshComp->GetOwner()) return;
|
||||
if (!TargetSocketNames.Num()) return;
|
||||
if (!UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(MeshComp->GetOwner())) return;
|
||||
|
||||
FGameplayEventData Data;
|
||||
for (int i = 1; i < TargetSocketNames.Num(); ++i)
|
||||
{
|
||||
// const auto LocationInfo{NewObject<FGameplayAbilityTargetData_LocationInfo>()};
|
||||
const auto LocationInfo{new FGameplayAbilityTargetData_LocationInfo()}; // heap allocation
|
||||
FVector StartLoc{MeshComp->GetSocketLocation(TargetSocketNames[i - 1])};
|
||||
FVector EndLoc{MeshComp->GetSocketLocation(TargetSocketNames[i])};
|
||||
LocationInfo->SourceLocation.LiteralTransform.SetLocation(StartLoc);
|
||||
LocationInfo->TargetLocation.LiteralTransform.SetLocation(EndLoc);
|
||||
|
||||
Data.TargetData.Add(LocationInfo);
|
||||
}
|
||||
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(MeshComp->GetOwner(), EventTag, Data);
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "GAS/CAttributeSet.h"
|
||||
|
||||
#include "GameplayEffectExtension.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
|
||||
void UCAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
@@ -14,6 +15,31 @@ void UCAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLi
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MaxMana, COND_None, REPNOTIFY_Always);
|
||||
}
|
||||
|
||||
void UCAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
|
||||
{
|
||||
if (Attribute == GetHealthAttribute())
|
||||
{
|
||||
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth());
|
||||
}
|
||||
if (Attribute == GetManaAttribute())
|
||||
{
|
||||
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxMana());
|
||||
}
|
||||
}
|
||||
|
||||
void UCAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
|
||||
{
|
||||
// Super::PostGameplayEffectExecute(Data);
|
||||
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
|
||||
{
|
||||
SetHealth(FMath::Clamp(GetHealth(), 0, GetMaxHealth()));
|
||||
}
|
||||
if (Data.EvaluatedData.Attribute == GetManaAttribute())
|
||||
{
|
||||
SetMana(FMath::Clamp(GetMana(), 0, GetMaxMana()));
|
||||
}
|
||||
}
|
||||
|
||||
void UCAttributeSet::OnRep_Health(const FGameplayAttributeData& OldValue)
|
||||
{
|
||||
GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, Health, OldValue);
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
#include "GAS/CGameplayAbility.h"
|
||||
|
||||
UAnimInstance* UCGameplayAbility::GetOwnerAnimInstance()
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
|
||||
UAnimInstance* UCGameplayAbility::GetOwnerAnimInstance() const
|
||||
{
|
||||
if (const auto OwnerSkeletalMeshComp{GetOwningComponentFromActorInfo()})
|
||||
{
|
||||
@@ -11,3 +13,46 @@ UAnimInstance* UCGameplayAbility::GetOwnerAnimInstance()
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TArray<FHitResult> UCGameplayAbility::GetHitResultFromSweepLocationTargetData(
|
||||
const FGameplayAbilityTargetDataHandle& TargetDataHandle, float SphereSweepRadius, bool bDrawDebug,
|
||||
bool bIgnoreSelf) const
|
||||
{
|
||||
TArray<FHitResult> OutResults;
|
||||
TSet<AActor*> HitActors;
|
||||
for (const auto TargetData : TargetDataHandle.Data)
|
||||
{
|
||||
const FVector StartLoc{TargetData->GetOrigin().GetTranslation()};
|
||||
const FVector EndLoc{TargetData->GetEndPoint()};
|
||||
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
|
||||
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_Pawn));
|
||||
|
||||
TArray<AActor*> ActorsToIgnore;
|
||||
if (bIgnoreSelf) ActorsToIgnore.Add(GetAvatarActorFromActorInfo());
|
||||
const auto DrawDebugTrace{bDrawDebug ? EDrawDebugTrace::ForDuration : EDrawDebugTrace::None};
|
||||
|
||||
TArray<FHitResult> Results;
|
||||
UKismetSystemLibrary::SphereTraceMultiForObjects(
|
||||
this,
|
||||
StartLoc,
|
||||
EndLoc,
|
||||
SphereSweepRadius,
|
||||
ObjectTypes,
|
||||
false,
|
||||
ActorsToIgnore,
|
||||
DrawDebugTrace,
|
||||
Results,
|
||||
false
|
||||
);
|
||||
|
||||
for (const auto Result : Results)
|
||||
{
|
||||
if (HitActors.Contains(Result.GetActor())) continue;
|
||||
HitActors.Add(Result.GetActor());
|
||||
OutResults.Add(Result);
|
||||
}
|
||||
}
|
||||
|
||||
return OutResults;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "GAS/GA_Combo.h"
|
||||
|
||||
#include "AbilitySystemBlueprintLibrary.h"
|
||||
#include "GameplayTagsManager.h"
|
||||
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
|
||||
#include "Abilities/Tasks/AbilityTask_WaitGameplayEvent.h"
|
||||
@@ -60,6 +61,17 @@ void UGA_Combo::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
|
||||
WaitComboChangeEventTask->EventReceived.AddDynamic(this, &UGA_Combo::ComboChangedEventReceived);
|
||||
WaitComboChangeEventTask->ReadyForActivation();
|
||||
}
|
||||
if (K2_HasAuthority())
|
||||
{
|
||||
const auto WaitTargetingEventTask{
|
||||
UAbilityTask_WaitGameplayEvent::WaitGameplayEvent(
|
||||
this,
|
||||
GetComboTargetEventTag()
|
||||
)
|
||||
};
|
||||
WaitTargetingEventTask->EventReceived.AddDynamic(this, &UGA_Combo::DoDamage);
|
||||
WaitTargetingEventTask->ReadyForActivation();
|
||||
}
|
||||
|
||||
SetupWaitComboInputPressed();
|
||||
}
|
||||
@@ -91,6 +103,11 @@ FGameplayTag UGA_Combo::GetComboChangedEventEndTag()
|
||||
return FGameplayTag::RequestGameplayTag("ability.combo.change.end");
|
||||
}
|
||||
|
||||
FGameplayTag UGA_Combo::GetComboTargetEventTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag("ability.combo.damage");
|
||||
}
|
||||
|
||||
void UGA_Combo::SetupWaitComboInputPressed()
|
||||
{
|
||||
const auto WaitInputPress{UAbilityTask_WaitInputPress::WaitInputPress(this)};
|
||||
@@ -117,3 +134,49 @@ void UGA_Combo::TryCommitCombo()
|
||||
ComboMontage
|
||||
);
|
||||
}
|
||||
|
||||
TSubclassOf<UGameplayEffect> UGA_Combo::GetDamageEffectForCurrentCombo() const
|
||||
{
|
||||
if (const auto OwnerAnimInstance{GetOwnerAnimInstance()})
|
||||
{
|
||||
const FName CurrentSectionName{OwnerAnimInstance->Montage_GetCurrentSection(ComboMontage)};
|
||||
const auto FoundEffectPtr{DamageEffectMap.Find(CurrentSectionName)};
|
||||
|
||||
if (FoundEffectPtr) return *FoundEffectPtr;
|
||||
}
|
||||
return DefaultEffectClass;
|
||||
}
|
||||
|
||||
void UGA_Combo::DoDamage(FGameplayEventData Data)
|
||||
{
|
||||
auto HitResults{
|
||||
GetHitResultFromSweepLocationTargetData(
|
||||
Data.TargetData,
|
||||
TargetSweepSphereRadius,
|
||||
false,
|
||||
true
|
||||
)
|
||||
};
|
||||
|
||||
for (const FHitResult& HitResult : HitResults)
|
||||
{
|
||||
const auto GameplayEffect{GetDamageEffectForCurrentCombo()};
|
||||
const auto AbilityLevel{GetAbilityLevel(GetCurrentAbilitySpecHandle(), GetCurrentActorInfo())};
|
||||
const auto EffectSpecHandle{MakeOutgoingGameplayEffectSpec(GameplayEffect, AbilityLevel)};
|
||||
const auto AbilityTargetData{UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(HitResult.GetActor())};
|
||||
|
||||
auto EffectContextHandle{MakeEffectContext(GetCurrentAbilitySpecHandle(), GetCurrentActorInfo())};
|
||||
EffectContextHandle.AddHitResult(HitResult);
|
||||
EffectSpecHandle.Data->SetContext(EffectContextHandle);
|
||||
|
||||
const auto ActiveGameplayEffectHandles{
|
||||
ApplyGameplayEffectSpecToTarget(
|
||||
GetCurrentAbilitySpecHandle(),
|
||||
CurrentActorInfo,
|
||||
CurrentActivationInfo,
|
||||
EffectSpecHandle,
|
||||
AbilityTargetData
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
26
Source/Crunch/Public/Animations/AN_SendTargetGroup.h
Normal file
26
Source/Crunch/Public/Animations/AN_SendTargetGroup.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Multiplayer By Caleb
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Animation/AnimNotifies/AnimNotify.h"
|
||||
#include "AN_SendTargetGroup.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class CRUNCH_API UAN_SendTargetGroup : public UAnimNotify
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
|
||||
const FAnimNotifyEventReference& EventReference) override;
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, Category="Ability")
|
||||
FGameplayTag EventTag;
|
||||
UPROPERTY(EditAnywhere, Category="Ability")
|
||||
TArray<FName> TargetSocketNames;
|
||||
};
|
||||
@@ -39,6 +39,26 @@ class CRUNCH_API UCAttributeSet : public UAttributeSet
|
||||
|
||||
public:
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
/**
|
||||
* An "On Aggregator Change" type of event could go here, and that could be called when active gameplay effects are added or removed to an attribute aggregator.
|
||||
* It is difficult to give all the information in these cases though - aggregators can change for many reasons: being added, being removed, being modified, having a modifier change, immunity, stacking rules, etc.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------------------------------------
|
||||
*
|
||||
* Called just before any modification happens to an attribute. This is lower level than PreAttributeModify/PostAttribute modify.
|
||||
* There is no additional context provided here since anything can trigger this. Executed effects, duration based effects, effects being removed, immunity being applied, stacking rules changing, etc.
|
||||
* This function is meant to enforce things like "Health = Clamp(Health, 0, MaxHealth)" and NOT things like "trigger this extra thing if damage is applied, etc".
|
||||
*
|
||||
* NewValue is a mutable reference so you are able to clamp the newly applied value as well.
|
||||
*/
|
||||
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
|
||||
/**
|
||||
* Called just after a GameplayEffect is executed to modify the base value of an attribute. No more changes can be made.
|
||||
* Note this is only called during an 'execute'. E.g., a modification to the 'base value' of an attribute. It is not called during an application of a GameplayEffect, such as a 5 ssecond +10 movement speed buff.
|
||||
*/
|
||||
virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;
|
||||
|
||||
ATTRIBUTE_ACCESSORS(UCAttributeSet, Health);
|
||||
ATTRIBUTE_ACCESSORS(UCAttributeSet, MaxHealth);
|
||||
|
||||
@@ -13,6 +13,10 @@ UCLASS()
|
||||
class CRUNCH_API UCGameplayAbility : public UGameplayAbility
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UAnimInstance* GetOwnerAnimInstance();
|
||||
UAnimInstance* GetOwnerAnimInstance() const;
|
||||
TArray<FHitResult> GetHitResultFromSweepLocationTargetData(const FGameplayAbilityTargetDataHandle& TargetDataHandle,
|
||||
float SphereSweepRadius = 30.f, bool bDrawDebug = false,
|
||||
bool bIgnoreSelf = true) const;
|
||||
};
|
||||
|
||||
@@ -21,13 +21,24 @@ public:
|
||||
const FGameplayEventData* TriggerEventData) override;
|
||||
static FGameplayTag GetComboChangedEventTag();
|
||||
static FGameplayTag GetComboChangedEventEndTag();
|
||||
static FGameplayTag GetComboTargetEventTag();
|
||||
|
||||
private:
|
||||
UFUNCTION()
|
||||
void HandleInputPress(float TimeWaited);
|
||||
|
||||
|
||||
void SetupWaitComboInputPressed();
|
||||
void TryCommitCombo();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category="Targetting")
|
||||
float TargetSweepSphereRadius{30.f};
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category="Gameplay Effect")
|
||||
TSubclassOf<UGameplayEffect> DefaultEffectClass;
|
||||
UPROPERTY(EditDefaultsOnly, Category="Gameplay Effect")
|
||||
TMap<FName, TSubclassOf<UGameplayEffect>> DamageEffectMap;
|
||||
|
||||
TSubclassOf<UGameplayEffect> GetDamageEffectForCurrentCombo() const;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category="Amination")
|
||||
TObjectPtr<UAnimMontage> ComboMontage;
|
||||
@@ -35,5 +46,8 @@ private:
|
||||
UFUNCTION()
|
||||
void ComboChangedEventReceived(FGameplayEventData Data);
|
||||
|
||||
UFUNCTION()
|
||||
void DoDamage(FGameplayEventData Data);
|
||||
|
||||
FName NextComboName;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user