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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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);