diff --git a/Content/Characters/Creature1/DT_Montages.uasset b/Content/Characters/Creature1/DT_Montages.uasset new file mode 100644 index 0000000..7fef339 Binary files /dev/null and b/Content/Characters/Creature1/DT_Montages.uasset differ diff --git a/Content/Core/GameplayCues/Damage/CG_DamageReceived.uasset b/Content/Core/GameplayCues/Damage/CG_DamageReceived.uasset new file mode 100644 index 0000000..b43a0b8 Binary files /dev/null and b/Content/Core/GameplayCues/Damage/CG_DamageReceived.uasset differ diff --git a/Content/Core/GameplayCues/Damage/M_Damage.uasset b/Content/Core/GameplayCues/Damage/M_Damage.uasset new file mode 100644 index 0000000..87f10c0 Binary files /dev/null and b/Content/Core/GameplayCues/Damage/M_Damage.uasset differ diff --git a/Content/Core/GameplayCues/Damage/VFX_Damage.uasset b/Content/Core/GameplayCues/Damage/VFX_Damage.uasset new file mode 100644 index 0000000..c373340 Binary files /dev/null and b/Content/Core/GameplayCues/Damage/VFX_Damage.uasset differ diff --git a/Content/Core/Mannequins/Animations/ABP_Manny.uasset b/Content/Core/Mannequins/Animations/ABP_Manny.uasset index d03ac0f..ac777f9 100644 Binary files a/Content/Core/Mannequins/Animations/ABP_Manny.uasset and b/Content/Core/Mannequins/Animations/ABP_Manny.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/AM_HitReact_F_H.uasset b/Content/Core/Mannequins/Animations/Manny/AM_HitReact_F_H.uasset new file mode 100644 index 0000000..750d715 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/AM_HitReact_F_H.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Back_Lgt_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Back_Lgt_01.uasset new file mode 100644 index 0000000..d14c2f5 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Back_Lgt_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Back_Med_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Back_Med_01.uasset new file mode 100644 index 0000000..5dc0c20 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Back_Med_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Hvy_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Hvy_01.uasset new file mode 100644 index 0000000..ff44636 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Hvy_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_01.uasset new file mode 100644 index 0000000..450908b Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_02.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_02.uasset new file mode 100644 index 0000000..76554ef Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_02.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_03.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_03.uasset new file mode 100644 index 0000000..f568023 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_03.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_04.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_04.uasset new file mode 100644 index 0000000..0ec092d Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Lgt_04.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Med_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Med_01.uasset new file mode 100644 index 0000000..64e2b74 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Med_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Med_02.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Med_02.uasset new file mode 100644 index 0000000..e6c8d81 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Front_Med_02.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Left_Lgt_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Left_Lgt_01.uasset new file mode 100644 index 0000000..c063e2c Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Left_Lgt_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Left_Med_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Left_Med_01.uasset new file mode 100644 index 0000000..b8c230f Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Left_Med_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Right_Lgt_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Right_Lgt_01.uasset new file mode 100644 index 0000000..7ace7f0 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Right_Lgt_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Right_Med_01.uasset b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Right_Med_01.uasset new file mode 100644 index 0000000..3c98553 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_HitReact_Right_Med_01.uasset differ diff --git a/Content/Core/Mannequins/Animations/Manny/MM_Rifle_Idle_ADS.uasset b/Content/Core/Mannequins/Animations/Manny/MM_Rifle_Idle_ADS.uasset new file mode 100644 index 0000000..8c40458 Binary files /dev/null and b/Content/Core/Mannequins/Animations/Manny/MM_Rifle_Idle_ADS.uasset differ diff --git a/Content/Core/Materials/M_Particle_Translucent.uasset b/Content/Core/Materials/M_Particle_Translucent.uasset index 60e0f14..3e9d53c 100644 Binary files a/Content/Core/Materials/M_Particle_Translucent.uasset and b/Content/Core/Materials/M_Particle_Translucent.uasset differ diff --git a/Source/CogSample/CogSampleAbilitySystemComponent.cpp b/Source/CogSample/CogSampleAbilitySystemComponent.cpp new file mode 100644 index 0000000..f7d3dd3 --- /dev/null +++ b/Source/CogSample/CogSampleAbilitySystemComponent.cpp @@ -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); + } +} diff --git a/Source/CogSample/CogSampleAbilitySystemComponent.h b/Source/CogSample/CogSampleAbilitySystemComponent.h new file mode 100644 index 0000000..f996dff --- /dev/null +++ b/Source/CogSample/CogSampleAbilitySystemComponent.h @@ -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; + + +}; diff --git a/Source/CogSample/CogSampleCharacter.cpp b/Source/CogSample/CogSampleCharacter.cpp index 129601c..7798ae2 100644 --- a/Source/CogSample/CogSampleCharacter.cpp +++ b/Source/CogSample/CogSampleCharacter.cpp @@ -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(TEXT("AbilitySystem")); + AbilitySystem = CreateDefaultSubobject(TEXT("AbilitySystem")); AbilitySystem->SetIsReplicated(true); AbilitySystem->SetReplicationMode(EGameplayEffectReplicationMode::Full); } @@ -798,3 +799,24 @@ void ACogSampleCharacter::GetTargetCapsules(TArray& 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(MontageName, ContextString, bPrintWarning); + + if (Row == nullptr) + { + return false; + } + + Montage = Row->Montage; + return Montage != nullptr; +} \ No newline at end of file diff --git a/Source/CogSample/CogSampleCharacter.h b/Source/CogSample/CogSampleCharacter.h index 85583d2..fea11b0 100644 --- a/Source/CogSample/CogSampleCharacter.h +++ b/Source/CogSample/CogSampleCharacter.h @@ -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& 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> 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; diff --git a/Source/CogSample/CogSampleDamageEvent.h b/Source/CogSample/CogSampleDamageEvent.h index 6399da3..56c5ef1 100644 --- a/Source/CogSample/CogSampleDamageEvent.h +++ b/Source/CogSample/CogSampleDamageEvent.h @@ -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); diff --git a/Source/CogSample/CogSampleDamageableInterface.h b/Source/CogSample/CogSampleDamageableInterface.h new file mode 100644 index 0000000..c4bc648 --- /dev/null +++ b/Source/CogSample/CogSampleDamageableInterface.h @@ -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) {} +}; diff --git a/Source/CogSample/CogSampleExecCalculation_Damage.cpp b/Source/CogSample/CogSampleExecCalculation_Damage.cpp index 696c5ac..0b13197 100644 --- a/Source/CogSample/CogSampleExecCalculation_Damage.cpp +++ b/Source/CogSample/CogSampleExecCalculation_Damage.cpp @@ -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(TargetAbilitySystem->AbilityActorInfo.IsValid() ? TargetAbilitySystem->GetAvatarActor() : nullptr) : nullptr; - ACogSampleCharacter* SourceCharacter = (SourceAbilitySystem != nullptr) ? Cast(SourceAbilitySystem->AbilityActorInfo.IsValid() ? SourceAbilitySystem->GetAvatarActor() : nullptr) : nullptr; + UCogSampleAbilitySystemComponent* TargetAbilitySystem = Cast(ExecutionParams.GetTargetAbilitySystemComponent()); + AActor* TargetActor = (TargetAbilitySystem != nullptr) ? TargetAbilitySystem->GetAvatarActor() : nullptr; - if (TargetCharacter == nullptr) + UCogSampleAbilitySystemComponent* SourceAbilitySystem = Cast(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(TargetActor)) { - SourceCharacter->HandleDamageDealt(Params); + DamageReceiver->HandleDamageReceived(Params); + } + + if (ICogSampleDamageableInterface* DamageDealer = Cast(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); + } + } +} \ No newline at end of file diff --git a/Source/CogSample/CogSampleExecCalculation_Damage.h b/Source/CogSample/CogSampleExecCalculation_Damage.h index d77abe3..08fbc0b 100644 --- a/Source/CogSample/CogSampleExecCalculation_Damage.h +++ b/Source/CogSample/CogSampleExecCalculation_Damage.h @@ -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); + +}; diff --git a/Source/CogSample/CogSampleFunctionLibrary_Tag.cpp b/Source/CogSample/CogSampleFunctionLibrary_Tag.cpp index 33a755c..3135fae 100644 --- a/Source/CogSample/CogSampleFunctionLibrary_Tag.cpp +++ b/Source/CogSample/CogSampleFunctionLibrary_Tag.cpp @@ -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"); diff --git a/Source/CogSample/CogSampleFunctionLibrary_Tag.h b/Source/CogSample/CogSampleFunctionLibrary_Tag.h index d823fe5..d4808db 100644 --- a/Source/CogSample/CogSampleFunctionLibrary_Tag.h +++ b/Source/CogSample/CogSampleFunctionLibrary_Tag.h @@ -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); diff --git a/Source/CogSample/CogSampleGameplayEffectContext.cpp b/Source/CogSample/CogSampleGameplayEffectContext.cpp index 52311aa..08ef3af 100644 --- a/Source/CogSample/CogSampleGameplayEffectContext.cpp +++ b/Source/CogSample/CogSampleGameplayEffectContext.cpp @@ -249,4 +249,15 @@ void UCogSampleEffectContextLibrary::EffectContextGetAllFloatValues(FGameplayEff { Entries = TypedEffectContext->FloatValues; } -} \ No newline at end of file +} + +//-------------------------------------------------------------------------------------------------------------------------- +bool UCogSampleEffectContextLibrary::EffectContextGetGameplayCueIsPredicted(FGameplayEffectContextHandle EffectContext) +{ + if (FCogSampleGameplayEffectContext* TypedEffectContext = FCogSampleGameplayEffectContext::ExtractEffectContext(EffectContext)) + { + return TypedEffectContext->bGameplayCueIsPredicted; + } + + return false; +} diff --git a/Source/CogSample/CogSampleGameplayEffectContext.h b/Source/CogSample/CogSampleGameplayEffectContext.h index c91ce10..1d3bc61 100644 --- a/Source/CogSample/CogSampleGameplayEffectContext.h +++ b/Source/CogSample/CogSampleGameplayEffectContext.h @@ -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 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);