Start to add hit impact on the sample

This commit is contained in:
Arnaud Jamin
2023-10-18 17:22:50 -04:00
parent 87e87edc13
commit bbb89f09ff
33 changed files with 295 additions and 44 deletions
@@ -0,0 +1,33 @@
#include "CogSampleAbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "GameplayCueManager.h"
#include "GameplayEffectTypes.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAbilitySystemComponent::ExecuteGameplayCueLocal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) const
{
if (AActor* ActorAvatar = AbilityActorInfo->AvatarActor.Get())
{
UAbilitySystemGlobals::Get().GetGameplayCueManager()->HandleGameplayCue(ActorAvatar, GameplayCueTag, EGameplayCueEvent::Type::Executed, GameplayCueParameters);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAbilitySystemComponent::AddGameplayCueLocal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) const
{
if (AActor* ActorAvatar = AbilityActorInfo->AvatarActor.Get())
{
UAbilitySystemGlobals::Get().GetGameplayCueManager()->HandleGameplayCue(ActorAvatar, GameplayCueTag, EGameplayCueEvent::Type::OnActive, GameplayCueParameters);
UAbilitySystemGlobals::Get().GetGameplayCueManager()->HandleGameplayCue(ActorAvatar, GameplayCueTag, EGameplayCueEvent::Type::WhileActive, GameplayCueParameters);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAbilitySystemComponent::RemoveGameplayCueLocal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) const
{
if (AActor* ActorAvatar = AbilityActorInfo->AvatarActor.Get())
{
UAbilitySystemGlobals::Get().GetGameplayCueManager()->HandleGameplayCue(ActorAvatar, GameplayCueTag, EGameplayCueEvent::Type::Removed, GameplayCueParameters);
}
}
@@ -0,0 +1,24 @@
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "CogSampleAbilitySystemComponent.generated.h"
UCLASS(BlueprintType)
class UCogSampleAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "GameplayCue", Meta = (AutoCreateRefTerm = "GameplayCueParameters", GameplayTagFilter = "GameplayCue"))
void ExecuteGameplayCueLocal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) const;
UFUNCTION(BlueprintCallable, Category = "GameplayCue", Meta = (AutoCreateRefTerm = "GameplayCueParameters", GameplayTagFilter = "GameplayCue"))
void AddGameplayCueLocal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) const;
UFUNCTION(BlueprintCallable, Category = "GameplayCue", Meta = (AutoCreateRefTerm = "GameplayCueParameters", GameplayTagFilter = "GameplayCue"))
void RemoveGameplayCueLocal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) const;
};
+23 -1
View File
@@ -2,6 +2,7 @@
#include "Camera/CameraComponent.h"
#include "CogCommon.h"
#include "CogSampleAbilitySystemComponent.h"
#include "CogSampleAttributeSet_Health.h"
#include "CogSampleAttributeSet_Misc.h"
#include "CogSampleCharacterMovementComponent.h"
@@ -64,7 +65,7 @@ ACogSampleCharacter::ACogSampleCharacter(const FObjectInitializer& ObjectInitial
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
AbilitySystem = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem"));
AbilitySystem = CreateDefaultSubobject<UCogSampleAbilitySystemComponent>(TEXT("AbilitySystem"));
AbilitySystem->SetIsReplicated(true);
AbilitySystem->SetReplicationMode(EGameplayEffectReplicationMode::Full);
}
@@ -798,3 +799,24 @@ void ACogSampleCharacter::GetTargetCapsules(TArray<const UCapsuleComponent*>& Ca
Capsules.Add(GetCapsuleComponent());
}
//--------------------------------------------------------------------------------------------------------------------------
bool ACogSampleCharacter::GetMontage(FName MontageName, UAnimMontage*& Montage, bool bPrintWarning) const
{
Montage = nullptr;
if (MontageTable == nullptr)
{
return false;
}
static FString ContextString(TEXT("GetMontage"));
FCogSampleMontageTableRow* Row = MontageTable->FindRow<FCogSampleMontageTableRow>(MontageName, ContextString, bPrintWarning);
if (Row == nullptr)
{
return false;
}
Montage = Row->Montage;
return Montage != nullptr;
}
+35 -7
View File
@@ -8,6 +8,7 @@
#include "CogCommonDebugFilteredActorInterface.h"
#include "CogSampleDamageEvent.h"
#include "CogSampleDefines.h"
#include "CogSampleDamageableInterface.h"
#include "CogSampleTargetableInterface.h"
#include "CogSampleTeamInterface.h"
#include "GameFramework/Character.h"
@@ -16,9 +17,9 @@
#include "InputActionValue.h"
#include "CogSampleCharacter.generated.h"
class UAbilitySystemComponent;
class UCogAbilitySystemComponent;
class UCameraComponent;
class UCogAbilitySystemComponent;
class UCogSampleAbilitySystemComponent;
class UGameplayAbility;
class UGameplayEffect;
class UInputAction;
@@ -58,6 +59,19 @@ public:
bool ActivateWhenGiven = false;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FCogSampleMontageTableRow : public FTableRowBase
{
GENERATED_BODY()
public:
FCogSampleMontageTableRow() {}
UPROPERTY(EditAnywhere, BlueprintReadOnly)
UAnimMontage* Montage = nullptr;
};
//--------------------------------------------------------------------------------------------------------------------------
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCogSampleCharacterEventDelegate, ACogSampleCharacter*, Character);
@@ -69,6 +83,7 @@ class ACogSampleCharacter : public ACharacter
, public ICogCommonAllegianceActorInterface
, public ICogSampleTeamInterface
, public ICogSampleTargetableInterface
, public ICogSampleDamageableInterface
{
GENERATED_BODY()
@@ -118,6 +133,14 @@ public:
virtual void GetTargetCapsules(TArray<const UCapsuleComponent*>& Capsules) const override;
//----------------------------------------------------------------------------------------------------------------------
// ICogSampleDamageableInterface overrides
//----------------------------------------------------------------------------------------------------------------------
virtual void HandleDamageReceived(const FCogSampleDamageEventParams& Params) override;
virtual void HandleDamageDealt(const FCogSampleDamageEventParams& Params) override;
//----------------------------------------------------------------------------------------------------------------------
// Team
//----------------------------------------------------------------------------------------------------------------------
@@ -182,16 +205,12 @@ public:
UFUNCTION(BlueprintPure)
bool IsInitialized() const { return bIsInitialized; }
void HandleDamageReceived(const FCogSampleDamageEventParams& Params);
void HandleDamageDealt(const FCogSampleDamageEventParams& Params);
void OnKilled(AActor* InInstigator, AActor* InCauser, const FGameplayEffectSpec& InEffectSpec, float InMagnitude);
void OnRevived(AActor* InInstigator, AActor* InCauser, const FGameplayEffectSpec& InEffectSpec, float InMagnitude);
UPROPERTY(BlueprintReadOnly, Category = Ability, meta = (AllowPrivateAccess = "true"))
UAbilitySystemComponent* AbilitySystem = nullptr;
UCogSampleAbilitySystemComponent* AbilitySystem = nullptr;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Ability)
TArray<TSubclassOf<UAttributeSet>> AttributeSets;
@@ -229,6 +248,15 @@ public:
UFUNCTION(BlueprintCallable)
int32 ApplyRootMotion(const FCogSampleRootMotionParams& Params);
//----------------------------------------------------------------------------------------------------------------------
// Montage
//----------------------------------------------------------------------------------------------------------------------
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation", meta = (RowType = "/Script/CogSample.FCogSampleMontageTableRow"))
UDataTable* MontageTable = nullptr;
UFUNCTION(BlueprintCallable, BlueprintPure=false)
bool GetMontage(FName MontageName, UAnimMontage*& Montage, bool bPrintWarning) const;
private:
friend class ACogSamplePlayerController;
-23
View File
@@ -1,26 +1,3 @@
#pragma once
#include "CoreMinimal.h"
#include "CogSampleDamageEvent.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FCogSampleDamageEventParams
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite)
float MitigatedDamage = 0;
UPROPERTY(BlueprintReadWrite)
float UnmitigatedDamage = 0;
UPROPERTY(BlueprintReadWrite)
AActor* DamageDealer = nullptr;
UPROPERTY(BlueprintReadWrite)
AActor* DamageReceiver = nullptr;
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCogSampleDamageEventDelegate, const FCogSampleDamageEventParams&, Params);
@@ -0,0 +1,45 @@
#pragma once
#include "CoreMinimal.h"
#include "CogSampleDamageableInterface.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FCogSampleDamageEventParams
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite)
float MitigatedDamage = 0;
UPROPERTY(BlueprintReadWrite)
float UnmitigatedDamage = 0;
UPROPERTY(BlueprintReadWrite)
AActor* DamageDealer = nullptr;
UPROPERTY(BlueprintReadWrite)
AActor* DamageReceiver = nullptr;
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCogSampleDamageEventDelegate, const FCogSampleDamageEventParams&, Params);
//--------------------------------------------------------------------------------------------------------------------------
UINTERFACE(MinimalAPI, Blueprintable)
class UCogSampleDamageableInterface : public UInterface
{
GENERATED_BODY()
};
//--------------------------------------------------------------------------------------------------------------------------
class ICogSampleDamageableInterface
{
GENERATED_BODY()
public:
virtual void HandleDamageReceived(const FCogSampleDamageEventParams& Params) {}
virtual void HandleDamageDealt(const FCogSampleDamageEventParams& Params) {}
};
@@ -1,8 +1,11 @@
#include "CogSampleExecCalculation_Damage.h"
#include "CogSampleAbilitySystemComponent.h"
#include "CogSampleAttributeSet_Health.h"
#include "CogSampleCharacter.h"
#include "CogSampleDamageableInterface.h"
#include "CogSampleFunctionLibrary_Tag.h"
#include "CogSampleGameplayEffectContext.h"
//--------------------------------------------------------------------------------------------------------------------------
struct FCogSampleDamageStatics
@@ -37,22 +40,37 @@ UCogSampleExecCalculation_Damage::UCogSampleExecCalculation_Damage()
void UCogSampleExecCalculation_Damage::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, OUT FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
const FGameplayEffectSpec& EffectSpec = ExecutionParams.GetOwningSpec();
const FGameplayEffectContextHandle Context = EffectSpec.GetContext();
FGameplayEffectContextHandle EffectContext = EffectSpec.GetContext();
FAggregatorEvaluateParameters EvaluationParameters;
EvaluationParameters.SourceTags = EffectSpec.CapturedSourceTags.GetAggregatedTags();
EvaluationParameters.TargetTags = EffectSpec.CapturedTargetTags.GetAggregatedTags();
UAbilitySystemComponent* TargetAbilitySystem = ExecutionParams.GetTargetAbilitySystemComponent();
UAbilitySystemComponent* SourceAbilitySystem = ExecutionParams.GetSourceAbilitySystemComponent();
ACogSampleCharacter* TargetCharacter = (TargetAbilitySystem != nullptr) ? Cast<ACogSampleCharacter>(TargetAbilitySystem->AbilityActorInfo.IsValid() ? TargetAbilitySystem->GetAvatarActor() : nullptr) : nullptr;
ACogSampleCharacter* SourceCharacter = (SourceAbilitySystem != nullptr) ? Cast<ACogSampleCharacter>(SourceAbilitySystem->AbilityActorInfo.IsValid() ? SourceAbilitySystem->GetAvatarActor() : nullptr) : nullptr;
UCogSampleAbilitySystemComponent* TargetAbilitySystem = Cast<UCogSampleAbilitySystemComponent>(ExecutionParams.GetTargetAbilitySystemComponent());
AActor* TargetActor = (TargetAbilitySystem != nullptr) ? TargetAbilitySystem->GetAvatarActor() : nullptr;
if (TargetCharacter == nullptr)
UCogSampleAbilitySystemComponent* SourceAbilitySystem = Cast<UCogSampleAbilitySystemComponent>(ExecutionParams.GetSourceAbilitySystemComponent());
AActor* SourceActor = (SourceAbilitySystem != nullptr) ? SourceAbilitySystem->GetAvatarActor() : nullptr;
if (TargetActor == nullptr)
{
return;
}
FHitResult HitResult;
if (const FHitResult* HitResultPtr = EffectContext.GetHitResult())
{
HitResult = *HitResultPtr;
}
else
{
HitResult.Location = TargetActor->GetActorLocation();
HitResult.Normal = TargetActor->GetActorForwardVector();
HitResult.ImpactNormal = TargetActor->GetActorForwardVector();
EffectContext.AddHitResult(HitResult, true);
}
FGameplayTagContainer SpecAssetTags;
EffectSpec.GetAllAssetTags(SpecAssetTags);
@@ -88,16 +106,75 @@ void UCogSampleExecCalculation_Damage::Execute_Implementation(const FGameplayEff
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(UCogSampleAttributeSet_Health::GetHealthAttribute(), EGameplayModOp::Additive, -MitigatedDamage));
FCogSampleDamageEventParams Params;
Params.DamageDealer = SourceCharacter;
Params.DamageReceiver = TargetCharacter;
Params.DamageDealer = SourceActor;
Params.DamageReceiver = TargetActor;
Params.MitigatedDamage = MitigatedDamage;
Params.UnmitigatedDamage = UnmitigatedDamage;
TargetCharacter->HandleDamageReceived(Params);
if (SourceCharacter != nullptr)
if (ICogSampleDamageableInterface* DamageReceiver = Cast<ICogSampleDamageableInterface>(TargetActor))
{
SourceCharacter->HandleDamageDealt(Params);
DamageReceiver->HandleDamageReceived(Params);
}
if (ICogSampleDamageableInterface* DamageDealer = Cast<ICogSampleDamageableInterface>(SourceActor))
{
DamageDealer->HandleDamageDealt(Params);
}
}
UCogSampleFunctionLibrary_Damage::ExecuteDamageGameplayCue(TargetAbilitySystem, HitResult, MitigatedDamage, EffectContext, false);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleFunctionLibrary_Damage::ExecuteDamageGameplayCue(
UCogSampleAbilitySystemComponent* TargetAbilitySystem,
const FHitResult& HitResult,
float Damage,
const FGameplayEffectContextHandle& EffectContext,
bool IsPredicted)
{
ensure(TargetAbilitySystem);
if (TargetAbilitySystem == nullptr)
{
return;
}
AActor* TargetActor = TargetAbilitySystem->GetAvatarActor();
if (TargetActor == nullptr)
{
return;
}
FCogSampleGameplayEffectContext* TypedContext = FCogSampleGameplayEffectContext::ExtractEffectContext(EffectContext);
ensure(TypedContext);
if (TypedContext == nullptr)
{
return;
}
TypedContext->bGameplayCueIsPredicted = IsPredicted;
//-----------------------------------------------------------------------------------------------------
// We check for >= 1 instead of >= 0 because we can use damage values between 0 and 1.
//-----------------------------------------------------------------------------------------------------
if (Damage > 0.0f)
{
FGameplayCueParameters GameplayCueParameters;
GameplayCueParameters.RawMagnitude = Damage;
GameplayCueParameters.EffectContext = EffectContext;
GameplayCueParameters.Instigator = TypedContext->GetInstigator();
GameplayCueParameters.EffectCauser = TypedContext->GetEffectCauser();
GameplayCueParameters.PhysicalMaterial = HitResult.PhysMaterial;
GameplayCueParameters.Location = HitResult.Location;
GameplayCueParameters.Normal = HitResult.ImpactNormal;
if (IsPredicted)
{
TargetAbilitySystem->ExecuteGameplayCueLocal(Tag_GameplayCue_DamageReceived, GameplayCueParameters);
}
else
{
TargetAbilitySystem->ExecuteGameplayCue(Tag_GameplayCue_DamageReceived, GameplayCueParameters);
}
}
}
@@ -2,8 +2,13 @@
#include "CoreMinimal.h"
#include "GameplayEffectExecutionCalculation.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "CogSampleExecCalculation_Damage.generated.h"
class UCogSampleAbilitySystemComponent;
struct FHitResult;
struct FGameplayEffectContextHandle;
UCLASS()
class UCogSampleExecCalculation_Damage : public UGameplayEffectExecutionCalculation
{
@@ -14,3 +19,20 @@ public:
virtual void Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, OUT FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const override;
};
UCLASS(meta = (ScriptName = "CogSampleFunctionLibrary_Damage"))
class COGSAMPLE_API UCogSampleFunctionLibrary_Damage : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static void ExecuteDamageGameplayCue(
UCogSampleAbilitySystemComponent* TargetAbilitySystem,
const FHitResult& HitResult,
float HealthDamage,
const FGameplayEffectContextHandle& EffectContext,
bool IsPredicted);
};
@@ -34,6 +34,8 @@ UE_DEFINE_GAMEPLAY_TAG(Tag_Effect_Type_Heal_Full, "Effect.Type.Heal.Full");
UE_DEFINE_GAMEPLAY_TAG(Tag_Effect_Type_Heal_Revive, "Effect.Type.Heal.Revive");
UE_DEFINE_GAMEPLAY_TAG(Tag_Effect_Type_Hidden, "Effect.Type.Hidden");
UE_DEFINE_GAMEPLAY_TAG(Tag_GameplayCue_DamageReceived, "GameplayCue.DamageReceived");
UE_DEFINE_GAMEPLAY_TAG(Tag_Status_Dead, "Status.Dead");
UE_DEFINE_GAMEPLAY_TAG(Tag_Status_Ghost, "Status.Ghost");
UE_DEFINE_GAMEPLAY_TAG(Tag_Status_Immobilized, "Status.Immobilized");
@@ -36,6 +36,8 @@ UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Effect_Type_Heal_Full);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Effect_Type_Heal_Revive);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Effect_Type_Hidden);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_GameplayCue_DamageReceived);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Status_Dead);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Status_Ghost);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_Status_Immobilized);
@@ -249,4 +249,15 @@ void UCogSampleEffectContextLibrary::EffectContextGetAllFloatValues(FGameplayEff
{
Entries = TypedEffectContext->FloatValues;
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogSampleEffectContextLibrary::EffectContextGetGameplayCueIsPredicted(FGameplayEffectContextHandle EffectContext)
{
if (FCogSampleGameplayEffectContext* TypedEffectContext = FCogSampleGameplayEffectContext::ExtractEffectContext(EffectContext))
{
return TypedEffectContext->bGameplayCueIsPredicted;
}
return false;
}
@@ -65,6 +65,11 @@ public:
bool CanGameplayCueBePredicted();
/* NOT REPLICATED - Is this effect context made for a local gameplay cue. Used to know if a remote gameplay cue
* created by the local player should be filtered when a local gameplay cue is played instead.
*/
bool bGameplayCueIsPredicted = false;
/* REPLICATED */
UPROPERTY()
TArray<FCogSampleGameplayEffectContextFloatValue> FloatValues;
@@ -91,6 +96,9 @@ class UCogSampleEffectContextLibrary : public UBlueprintFunctionLibrary
public:
UFUNCTION(BlueprintPure)
static bool EffectContextGetGameplayCueIsPredicted(FGameplayEffectContextHandle EffectContext);
UFUNCTION(BlueprintCallable)
static void EffectContextSetFloatValue(FGameplayEffectContextHandle EffectContext, FName Name, float Value);