mirror of
https://github.com/Ed94/Cog.git
synced 2026-06-13 08:02:23 -07:00
CogPackage: fix Gameplay Cues not cooked
CogSample: Add area of effect CogSample: Add "Easy" cheat CogWindow: Fix some tooltips CogEngine: Spawns now spawn the default controller CogDebug: Early out on DebugDraw if WorldContextObject is null
This commit is contained in:
@@ -0,0 +1,434 @@
|
||||
#include "CogSampleArea.h"
|
||||
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "AbilitySystemGlobals.h"
|
||||
#include "CogCommon.h"
|
||||
#include "CogSampleDamageableInterface.h"
|
||||
#include "CogSampleFunctionLibrary_Team.h"
|
||||
#include "Engine/World.h"
|
||||
#include "GameFramework/GameStateBase.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
#include "TimerManager.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogSampleArea::ACogSampleArea(const class FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
bReplicates = true;
|
||||
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
SetActorTickEnabled(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME(ACogSampleArea, HalfExtent);
|
||||
DOREPLIFETIME(ACogSampleArea, Level);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::BeginPlay()
|
||||
{
|
||||
COG_LOG_OBJECT(LogCogArea, ELogVerbosity::Verbose, GetInstigator(), TEXT("Area:%s"), *GetName());
|
||||
|
||||
IsAtStart = true;
|
||||
IsAtEnd = false;
|
||||
|
||||
if (HasAuthority())
|
||||
{
|
||||
if (TickRate > 0.0f && IsInstant == false)
|
||||
{
|
||||
GetWorld()->GetTimerManager().SetTimer(TickTimerHandle, this, &ACogSampleArea::OnTickEffect, TickRate, true, InitialTickDelay);
|
||||
}
|
||||
|
||||
RegisterAllEffects();
|
||||
|
||||
OnActorBeginOverlap.AddDynamic(this, &ACogSampleArea::OnActorEntered);
|
||||
OnActorEndOverlap.AddDynamic(this, &ACogSampleArea::OnActorExited);
|
||||
}
|
||||
|
||||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
COG_LOG_OBJECT(LogCogArea, ELogVerbosity::Verbose, GetInstigator(), TEXT("Area:%s"), *GetName());
|
||||
|
||||
IsAtEnd = true;
|
||||
|
||||
if (CanPerformDetection() && IsInstant == false)
|
||||
{
|
||||
int32 EventTypeFilter = (int32)ECogSampleAreaEventType::OnEnd;
|
||||
|
||||
if (ApplyTickEffectOnExit)
|
||||
{
|
||||
EventTypeFilter |= (int32)ECogSampleAreaEventType::OnTick;
|
||||
}
|
||||
|
||||
ApplyEffectsOnActors(InsideActors, EventTypeFilter);
|
||||
|
||||
for (AActor* Actor : InsideActors)
|
||||
{
|
||||
AffectExitingActor(Actor);
|
||||
}
|
||||
}
|
||||
|
||||
InsideActors.Empty();
|
||||
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// We cannot execute OnStart event inside the OnActorEntered callback because
|
||||
// we need to know all the actors that are inside to execute the OnStart event.
|
||||
// This is because we must iterate over all actors for each effects we need
|
||||
// to apply. See ApplyEffectsOnActors as to why.
|
||||
// So instead we execute it on Tick
|
||||
//------------------------------------------------------------------------------
|
||||
if (IsAtStart)
|
||||
{
|
||||
int32 EventTypeFilter = (int32)ECogSampleAreaEventType::OnStart;
|
||||
|
||||
if (ApplyTickEffectOnEnter)
|
||||
{
|
||||
EventTypeFilter |= (int32)ECogSampleAreaEventType::OnTick;
|
||||
}
|
||||
|
||||
ApplyEffectsOnActors(InsideActors, EventTypeFilter);
|
||||
|
||||
IsAtStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
AActor* ACogSampleArea::GetInstigatorActor() const
|
||||
{
|
||||
AActor* AreaInstigator = GetInstigator();
|
||||
if (AreaInstigator != nullptr)
|
||||
{
|
||||
return AreaInstigator;
|
||||
}
|
||||
|
||||
if (ParentActor != nullptr)
|
||||
{
|
||||
return ParentActor;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// The game state is the default Instigator
|
||||
//-------------------------------------------------
|
||||
UWorld* World = GetWorld();
|
||||
if (World != nullptr)
|
||||
{
|
||||
return World->GetGameState();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::RegisterAllEffects()
|
||||
{
|
||||
AActor* AreaInstigator = GetInstigatorActor();
|
||||
if (AreaInstigator == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(AreaInstigator);
|
||||
if (AbilitySystem == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FGameplayEffectContextHandle EffectContextHandle = AbilitySystem->MakeEffectContext();
|
||||
|
||||
for (const FCogSampleAreaEffectConfig& EffectConfig : Effects)
|
||||
{
|
||||
for (TSubclassOf<UGameplayEffect> EffectClass : EffectConfig.Effects)
|
||||
{
|
||||
if (EffectsMap.Contains(EffectClass))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FGameplayEffectSpecHandle* BakedEffectSpecHandle = BakedEffects.FindByPredicate([EffectClass](const FGameplayEffectSpecHandle& Handle)
|
||||
{
|
||||
return Handle.Data->Def.GetClass() == EffectClass;
|
||||
});
|
||||
|
||||
if (BakedEffectSpecHandle != nullptr)
|
||||
{
|
||||
EffectsMap.Add(EffectClass, *BakedEffectSpecHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
FGameplayEffectSpecHandle EffectSpecHandle = AbilitySystem->MakeOutgoingSpec(EffectClass, Level, EffectContextHandle);
|
||||
EffectsMap.Add(EffectClass, EffectSpecHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// We iterate over effects and then over actors to make sure effects are applied in order on all actors.
|
||||
// One case where this is useful is an area that applies first a corruption effect and damage effect.
|
||||
// The corruption must be given to everyone in the area before any damage is applied, because the corruption
|
||||
// propagate the damage to other corrupted actors.
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::ApplyEffectsOnActors(const TArray<AActor*>& HitActors, int32 EventTypeFilter)
|
||||
{
|
||||
for (const FCogSampleAreaEffectConfig& EffectConfig : Effects)
|
||||
{
|
||||
if (((int32)EffectConfig.Event & (int32)EventTypeFilter) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (TSubclassOf<UGameplayEffect> EffectClass : EffectConfig.Effects)
|
||||
{
|
||||
FGameplayEffectSpecHandle* Handle = EffectsMap.Find(EffectClass);
|
||||
if (Handle == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FGameplayEffectSpec* Spec = Handle->Data.Get();
|
||||
if (Spec == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (AActor* HitActor : HitActors)
|
||||
{
|
||||
if (UCogSampleFunctionLibrary_Team::MatchAllegianceBetweenTeamAndActor(Team, HitActor, EffectConfig.Allegiance) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsAliveOfAffectDead(HitActor) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
UAbilitySystemComponent* TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(HitActor);
|
||||
if (TargetAbilitySystem != nullptr)
|
||||
{
|
||||
TArray<FActiveGameplayEffectHandle>* TargetInsideEffects = nullptr;
|
||||
if ((EventTypeFilter & (int32)ECogSampleAreaEventType::OnInside) != 0)
|
||||
{
|
||||
TargetInsideEffects = &InsideEffects.FindOrAdd(HitActor);
|
||||
}
|
||||
|
||||
const FVector HitNormal = (HitActor->GetActorLocation() - GetActorLocation()) .GetSafeNormal(0.1f, FVector::UpVector);
|
||||
const FHitResult HitResult(HitActor, nullptr, HitActor->GetActorLocation(), HitNormal);
|
||||
Spec->GetContext().AddHitResult(HitResult, true);
|
||||
|
||||
FActiveGameplayEffectHandle ActiveEffectHandle = TargetAbilitySystem->ApplyGameplayEffectSpecToSelf(*Spec);
|
||||
|
||||
if (EffectConfig.Event == ECogSampleAreaEventType::OnInside && TargetInsideEffects != nullptr)
|
||||
{
|
||||
TargetInsideEffects->Add(ActiveEffectHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool ACogSampleArea::MakeAreaOutgoingEffectSpecs(TSubclassOf<UGameplayEffect> EffectClass, FGameplayEffectSpecHandle& EffectSpecHandle) const
|
||||
{
|
||||
AActor* AreaInstigator = GetInstigatorActor();
|
||||
if (AreaInstigator == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(AreaInstigator);
|
||||
if (AbilitySystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EffectSpecHandle = AbilitySystem->MakeOutgoingSpec(EffectClass, Level, AbilitySystem->MakeEffectContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool ACogSampleArea::CanPerformDetection() const
|
||||
{
|
||||
if (OnlyDetectOnAuthority == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (HasAuthority())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::OnTickEffect_Implementation()
|
||||
{
|
||||
ApplyEffectsOnActors(InsideActors, (int32)ECogSampleAreaEventType::OnTick);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::OnActorEntered_Implementation(AActor* OverlappedActor, AActor* EnteringActor)
|
||||
{
|
||||
check(EnteringActor);
|
||||
if (CanBeAffected(EnteringActor) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AffectEnteringActor(EnteringActor);
|
||||
InsideActors.Add(EnteringActor);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::OnActorExited_Implementation(AActor* OverlappedActor, AActor* ExitingActor)
|
||||
{
|
||||
if (IsInstant)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int32 Index = InsideActors.Find(ExitingActor);
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AffectExitingActor(ExitingActor);
|
||||
|
||||
InsideActors.RemoveAt(Index);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool ACogSampleArea::CanBeAffected_Implementation(AActor* OtherActor) const
|
||||
{
|
||||
check(OtherActor);
|
||||
|
||||
if (IsAlreadyAffected(OtherActor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool ACogSampleArea::IsAliveOfAffectDead(AActor* OtherActor) const
|
||||
{
|
||||
check(OtherActor);
|
||||
|
||||
if (AffectDead)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const ICogSampleDamageableInterface* Damageable = Cast<ICogSampleDamageableInterface>(OtherActor);
|
||||
if (Damageable == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Damageable->IsDead() == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool ACogSampleArea::IsAlreadyAffected(AActor* OtherActor) const
|
||||
{
|
||||
check(OtherActor);
|
||||
|
||||
if (InsideActors.Contains(OtherActor))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::AffectEnteringActor_Implementation(AActor* EnteringActor)
|
||||
{
|
||||
check(EnteringActor);
|
||||
|
||||
if (IsInstant == false)
|
||||
{
|
||||
TArray<AActor*> Actors;
|
||||
Actors.Add(EnteringActor);
|
||||
ApplyEffectsOnActors(Actors, (int32)ECogSampleAreaEventType::OnEnter | (int32)ECogSampleAreaEventType::OnInside);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::AffectExitingActor_Implementation(AActor* ExitingActor)
|
||||
{
|
||||
if (IsInstant || ExitingActor == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<AActor*> Actors;
|
||||
Actors.Add(ExitingActor);
|
||||
ApplyEffectsOnActors(Actors, (int32)ECogSampleAreaEventType::OnExit);
|
||||
|
||||
RemoveInsideEffects(ExitingActor);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::RemoveInsideEffects_Implementation(AActor* HitActor)
|
||||
{
|
||||
UAbilitySystemComponent* TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(HitActor);
|
||||
if (TargetAbilitySystem == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<FActiveGameplayEffectHandle>* TargetInsideEffects = InsideEffects.Find(HitActor);
|
||||
if (TargetInsideEffects == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (FActiveGameplayEffectHandle Handle : *TargetInsideEffects)
|
||||
{
|
||||
TargetAbilitySystem->RemoveActiveGameplayEffect(Handle, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::ApplyInstantEffects_Implementation(AActor* HitActor)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::ApplyInsideEffects_Implementation(AActor* HitActor)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleArea::ApplyTickEffects_Implementation(AActor* HitActor)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "GameplayEffect.h"
|
||||
|
||||
#include "CogSampleArea.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// ECogSampleAreaEventType
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
|
||||
enum class ECogSampleAreaEventType : uint8
|
||||
{
|
||||
None = 0 UMETA(Hidden),
|
||||
OnStart = 1 << 0,
|
||||
OnEnd = 1 << 1,
|
||||
OnTick = 1 << 2,
|
||||
OnInside = 1 << 3,
|
||||
OnEnter = 1 << 4,
|
||||
OnExit = 1 << 5,
|
||||
};
|
||||
ENUM_CLASS_FLAGS(ECogSampleAreaEventType);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogSampleAreaEffectConfig
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
USTRUCT(BlueprintType)
|
||||
struct COGSAMPLE_API FCogSampleAreaEffectConfig
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECogSampleAreaEventType Event = ECogSampleAreaEventType::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter"))
|
||||
int32 Allegiance = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<TSubclassOf<UGameplayEffect>> Effects;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// ACogSampleArea
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS()
|
||||
class COGSAMPLE_API ACogSampleArea : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
TObjectPtr<AActor> ParentActor = nullptr;
|
||||
|
||||
UPROPERTY(Replicated, EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
FVector HalfExtent = FVector(100.f, 100.f, 100.f);
|
||||
|
||||
UPROPERTY(Replicated, EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
int32 Level = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
int32 Team = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
bool IsInstant = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
float TickRate = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General", meta = (ExposeOnSpawn = true))
|
||||
float InitialTickDelay = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General")
|
||||
bool ApplyTickEffectOnEnter = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General")
|
||||
bool ApplyTickEffectOnExit = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General")
|
||||
bool OnlyDetectOnAuthority = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|General")
|
||||
bool AffectDead = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Area|Effects", meta = (ExposeOnSpawn = true))
|
||||
TArray<FCogSampleAreaEffectConfig> Effects;
|
||||
|
||||
UPROPERTY(Transient, BlueprintReadWrite, Category = "Internal", meta = (ExposeOnSpawn = true))
|
||||
TArray<FGameplayEffectSpecHandle> BakedEffects;
|
||||
|
||||
protected:
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void OnTickEffect();
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void OnActorEntered(AActor* OverlappedActor, AActor* EnteringActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void OnActorExited(AActor* OverlappedActor, AActor* OtherExitingActorActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void ApplyInstantEffects(AActor* HitActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void ApplyTickEffects(AActor* HitActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintPure, Category = "Area")
|
||||
bool CanBeAffected(AActor* OtherActor) const;
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void AffectEnteringActor(AActor* EnteringActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void AffectExitingActor(AActor* ExitingActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void ApplyInsideEffects(AActor* HitActor);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Area")
|
||||
void RemoveInsideEffects(AActor* HitActor);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Area")
|
||||
bool CanPerformDetection() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Area")
|
||||
bool IsAliveOfAffectDead(AActor* OtherActor) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Area")
|
||||
bool IsAlreadyAffected(AActor* OtherActor) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Area")
|
||||
AActor* GetInstigatorActor() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure=false, Category = "Area")
|
||||
bool MakeAreaOutgoingEffectSpecs(TSubclassOf<UGameplayEffect> EffectClass, FGameplayEffectSpecHandle& EffectSpecHandle) const;
|
||||
|
||||
void RegisterAllEffects();
|
||||
|
||||
void ApplyEffectsOnActors(const TArray<AActor*>& HitActors, int32 EventTypeFilter);
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Transient)
|
||||
bool IsAtStart = true;
|
||||
|
||||
bool IsAtEnd = false;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Transient)
|
||||
TArray<TObjectPtr<AActor>> InsideActors;
|
||||
|
||||
TMap<TSubclassOf<UGameplayEffect>, FGameplayEffectSpecHandle> EffectsMap;
|
||||
|
||||
TMap<AActor*, TArray<FActiveGameplayEffectHandle>> InsideEffects;
|
||||
|
||||
FTimerHandle TickTimerHandle;
|
||||
};
|
||||
@@ -535,9 +535,17 @@ void ACogSampleCharacter::HandleDamageDealt(const FCogSampleDamageEventParams& P
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool ACogSampleCharacter::IsDead() const
|
||||
{
|
||||
return bIsDead;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleCharacter::OnKilled(AActor* InInstigator, AActor* InCauser, const FGameplayEffectSpec& InEffectSpec, float InMagnitude)
|
||||
{
|
||||
bIsDead = true;
|
||||
|
||||
if (AbilitySystem != nullptr)
|
||||
{
|
||||
FGameplayEventData Payload;
|
||||
@@ -558,6 +566,8 @@ void ACogSampleCharacter::OnKilled(AActor* InInstigator, AActor* InCauser, const
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleCharacter::OnRevived(AActor* InInstigator, AActor* InCauser, const FGameplayEffectSpec& InEffectSpec, float InMagnitude)
|
||||
{
|
||||
bIsDead = false;
|
||||
|
||||
if (AbilitySystem != nullptr)
|
||||
{
|
||||
FGameplayEventData Payload;
|
||||
|
||||
@@ -141,6 +141,8 @@ public:
|
||||
|
||||
virtual void HandleDamageDealt(const FCogSampleDamageEventParams& Params) override;
|
||||
|
||||
virtual bool IsDead() const override;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Team
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
@@ -334,6 +336,8 @@ private:
|
||||
|
||||
bool bIsInGhostMode = false;
|
||||
|
||||
bool bIsDead = false;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Root Motion
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -42,4 +42,7 @@ public:
|
||||
virtual void HandleDamageReceived(const FCogSampleDamageEventParams& Params) {}
|
||||
|
||||
virtual void HandleDamageDealt(const FCogSampleDamageEventParams& Params) {}
|
||||
|
||||
virtual bool IsDead() const { return false; }
|
||||
|
||||
};
|
||||
|
||||
@@ -316,3 +316,28 @@ bool UCogSampleFunctionLibrary_Gameplay::IsActorMatchingTags(const AActor* Actor
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
AActor* UCogSampleFunctionLibrary_Gameplay::GetActorInstigator(AActor* Actor)
|
||||
{
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AActor* Instigator = Actor->GetInstigator();
|
||||
if (Instigator != nullptr)
|
||||
{
|
||||
return Instigator;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// The game state is the default Instigator
|
||||
//-------------------------------------------------
|
||||
UWorld* World = Actor->GetWorld();
|
||||
if (World != nullptr)
|
||||
{
|
||||
return World->GetGameState();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -64,6 +64,9 @@ public:
|
||||
UFUNCTION(BlueprintPure)
|
||||
static void FindCapsulePointDistance(const FVector2D& CapsulePoint1, const FVector2D& CapsulePoint2, const float CapsuleRadius, const FVector2D& Point, FVector2D& Projection, float& Time, float& Distance);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static AActor* GetActorInstigator(AActor* Actor);
|
||||
|
||||
static void AdjustAttributeForMaxChange(UAbilitySystemComponent* AbilityComponent, FGameplayAttributeData& AffectedAttribute, float OldValue, float NewMaxValue, const FGameplayAttribute& AffectedAttributeProperty);
|
||||
|
||||
static FCollisionObjectQueryParams ConfigureCollisionObjectParams(const TArray<TEnumAsByte<EObjectTypeQuery>>& ObjectTypes);
|
||||
@@ -83,6 +86,4 @@ public:
|
||||
static bool IsActorMatchingTags(const AActor* Actor, const FGameplayTagContainer& RequiredTags, const FGameplayTagContainer& IgnoredTags);
|
||||
|
||||
static bool MatchCooldownTag(const FGameplayTagContainer& TagContainer);
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
#include "CogSampleTeamInterface.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
int32 UCogSampleFunctionLibrary_Team::GetTeamSafe(const AActor* Actor)
|
||||
{
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const ICogSampleTeamInterface* TeamActor = Cast<ICogSampleTeamInterface>(Actor);
|
||||
if (TeamActor == nullptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int32 Team = TeamActor->GetTeam();
|
||||
return Team;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ECogSampleAllegiance UCogSampleFunctionLibrary_Team::GetTeamsAllegiance(int32 Team1, int32 Team2)
|
||||
{
|
||||
@@ -21,18 +39,9 @@ ECogSampleAllegiance UCogSampleFunctionLibrary_Team::GetTeamsAllegiance(int32 Te
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ECogSampleAllegiance UCogSampleFunctionLibrary_Team::GetActorsAllegiance(const AActor* Actor1, const AActor* Actor2)
|
||||
{
|
||||
const ICogSampleTeamInterface* TeamActor1 = Cast<ICogSampleTeamInterface>(Actor1);
|
||||
const ICogSampleTeamInterface* TeamActor2 = Cast<ICogSampleTeamInterface>(Actor2);
|
||||
|
||||
if (TeamActor1 == nullptr || TeamActor2 == nullptr)
|
||||
{
|
||||
return ECogSampleAllegiance::Neutral;
|
||||
}
|
||||
|
||||
const int32 Team1 = TeamActor1->GetTeam();
|
||||
const int32 Team2 = TeamActor2->GetTeam();
|
||||
const int32 Team1 = GetTeamSafe(Actor1);
|
||||
const int32 Team2 = GetTeamSafe(Actor2);
|
||||
const ECogSampleAllegiance Allegiance = GetTeamsAllegiance(Team1, Team2);
|
||||
|
||||
return Allegiance;
|
||||
}
|
||||
|
||||
@@ -44,6 +53,23 @@ bool UCogSampleFunctionLibrary_Team::MatchAllegiance(const AActor* Actor1, const
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleFunctionLibrary_Team::MatchAllegianceFromTeams(int32 Team1, int32 Team2, int32 AllegianceFilter)
|
||||
{
|
||||
const ECogSampleAllegiance Allegiance = GetTeamsAllegiance(Team1, Team2);
|
||||
const bool Result = MatchAllegianceFilter(Allegiance, AllegianceFilter);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleFunctionLibrary_Team::MatchAllegianceBetweenTeamAndActor(int32 Team, const AActor* Actor, int32 AllegianceFilter)
|
||||
{
|
||||
const int32 ActorTeam = GetTeamSafe(Actor);
|
||||
const ECogSampleAllegiance Allegiance = GetTeamsAllegiance(Team, ActorTeam);
|
||||
const bool Result = MatchAllegianceFilter(Allegiance, AllegianceFilter);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleFunctionLibrary_Team::MatchAllegianceFilter(ECogSampleAllegiance Allegiance, int32 AllegianceFilter)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,9 @@ class UCogSampleFunctionLibrary_Team : public UBlueprintFunctionLibrary
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static int32 GetTeamSafe(const AActor* Actor);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static ECogSampleAllegiance GetTeamsAllegiance(int32 Team1, int32 Team2);
|
||||
|
||||
@@ -40,6 +43,12 @@ public:
|
||||
UFUNCTION(BlueprintPure)
|
||||
static bool MatchAllegiance(const AActor* Actor1, const AActor* Actor2, UPARAM(meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter")) int32 AllegianceFilter);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
bool MatchAllegianceFromTeams(int32 Team1, int32 Team2, UPARAM(meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter")) int32 AllegianceFilter);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static bool MatchAllegianceBetweenTeamAndActor(int32 Team, const AActor* Actor, UPARAM(meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter")) int32 AllegianceFilter);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static bool MatchAllegianceFilter(ECogSampleAllegiance Allegiance, UPARAM(meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter")) int32 AllegianceFilter);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "AssetRegistry/IAssetRegistry.h"
|
||||
#include "CogSampleAbilitySystemComponent.h"
|
||||
#include "CogSampleFunctionLibrary_Tag.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "GameFramework/GameMode.h"
|
||||
@@ -78,6 +79,10 @@ ACogSampleGameState::ACogSampleGameState(const FObjectInitializer & ObjectInitia
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
PrimaryActorTick.SetTickFunctionEnable(true);
|
||||
PrimaryActorTick.bStartWithTickEnabled = true;
|
||||
|
||||
AbilitySystemComponent = CreateDefaultSubobject<UCogSampleAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
|
||||
AbilitySystemComponent->SetIsReplicated(true);
|
||||
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -85,6 +90,8 @@ void ACogSampleGameState::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
||||
|
||||
#if ENABLE_COG
|
||||
InitializeCog();
|
||||
#endif //ENABLE_COG
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
class UCogWindowManager;
|
||||
class UCogEngineWindow_Selection;
|
||||
class UCogSampleAbilitySystemComponent;
|
||||
|
||||
UCLASS()
|
||||
class ACogSampleGameState : public AGameStateBase
|
||||
@@ -23,12 +24,19 @@ class ACogSampleGameState : public AGameStateBase
|
||||
|
||||
private:
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
// To make sure it doesn't get garbage collected.
|
||||
//--------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------
|
||||
UPROPERTY()
|
||||
TObjectPtr<UObject> CogWindowManagerRef = nullptr;
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// The game state has an AbilitySystemComponent to serve as the default instigator
|
||||
// for effects that are not applied by characters.
|
||||
//---------------------------------------------------------------------------------
|
||||
UPROPERTY()
|
||||
UCogSampleAbilitySystemComponent* AbilitySystemComponent = nullptr;
|
||||
|
||||
#if ENABLE_COG
|
||||
|
||||
void InitializeCog();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
DEFINE_LOG_CATEGORY(LogCogAlways);
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogCogAbility);
|
||||
DEFINE_LOG_CATEGORY(LogCogArea);
|
||||
DEFINE_LOG_CATEGORY(LogCogBaseAimRotation);
|
||||
DEFINE_LOG_CATEGORY(LogCogCollision);
|
||||
DEFINE_LOG_CATEGORY(LogCogControlRotation);
|
||||
@@ -30,6 +31,7 @@ namespace CogSampleLog
|
||||
FCogDebugLog::AddLogCategory(LogCogAlways, "Always", "Debug Category that is always active", false);
|
||||
|
||||
FCogDebugLog::AddLogCategory(LogCogAbility, "Ability", "Log and debug draw of gameplay abilities");
|
||||
FCogDebugLog::AddLogCategory(LogCogArea, "Area", "Log and debug draw of area of effects");
|
||||
FCogDebugLog::AddLogCategory(LogCogAI, "AI", "Log and debug draw of AI behaviors");
|
||||
FCogDebugLog::AddLogCategory(LogAbilitySystem, "Ability System", "Unreal Ability System Log");
|
||||
FCogDebugLog::AddLogCategory(LogCogBaseAimRotation, "Base Aim Rotation", "Debug Draw of a Character BaseAimRotation");
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogAlways, VeryVerbose, All);
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogAbility, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogArea, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogBaseAimRotation, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogCollision, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogControlRotation, Warning, All);
|
||||
|
||||
Reference in New Issue
Block a user