CogSample: progress on projectiles

This commit is contained in:
Arnaud Jamin
2023-10-30 01:11:48 -04:00
parent be498905bc
commit 315782183d
32 changed files with 224 additions and 60 deletions
+4 -3
View File
@@ -96,7 +96,7 @@ ManualIPAddress=
+Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ")
+Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ")
+Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.")
+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.")
+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="CharacterMesh",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.")
+Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors")
+Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors")
+Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.")
@@ -105,8 +105,9 @@ ManualIPAddress=
+Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.")
+Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.")
+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="ProjectileCollision",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="Projectile",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Needs description")
+Profiles=(Name="ProjectileAssistance",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="Projectile",CustomResponses=((Channel="WorldStatic",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Needs description")
+Profiles=(Name="ProjectileCollision",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="Projectile",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore),(Channel="CharacterMesh",Response=ECR_Overlap)),HelpMessage="Needs description")
+Profiles=(Name="ProjectileAssistance",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="Projectile",CustomResponses=((Channel="WorldStatic",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore),(Channel="CharacterMesh",Response=ECR_Overlap)),HelpMessage="Needs description")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False,Name="CharacterMesh")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False,Name="Projectile")
+EditProfiles=(Name="Pawn",CustomResponses=((Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Ignore)))
+EditProfiles=(Name="CharacterMesh",CustomResponses=((Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Overlap)))
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -383,7 +383,7 @@ void FCogEngineWindow_Plots::RenderContent()
if (Entry.FindValue(ImPlot::GetPlotMousePos().x, Value))
{
ImGui::BeginTooltip();
ImGui::Text("%s: %0.1f", Label.Get(), Value);
ImGui::Text("%s: %0.2f", Label.Get(), Value);
ImGui::EndTooltip();
}
}
-1
View File
@@ -87,7 +87,6 @@ void ACogSampleCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >
DOREPLIFETIME_WITH_PARAMS_FAST(ACogSampleCharacter, ActiveAbilityHandles, Params);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogSampleCharacter::PostInitializeComponents()
{
@@ -107,4 +107,7 @@ public:
static bool IsActorMatchingTags(const AActor* Actor, const FGameplayTagContainer& RequiredTags, const FGameplayTagContainer& IgnoredTags);
static void MakeOutgoingSpecs(const AActor* Actor, const TArray<TSubclassOf<UGameplayEffect>>& Effects, const TArray<FGameplayEffectSpecHandle>& BakedEffects, TMap<TSubclassOf<UGameplayEffect>, FGameplayEffectSpecHandle>& Result);
static APlayerController* GetFirstLocalPlayerController(UObject* WorldContextObject);
};
+5
View File
@@ -102,6 +102,11 @@ void ACogSampleGameState::Tick(float DeltaSeconds)
FCogDebugPlot::PlotValue(this, "Frame Rate", GAverageFPS);
FCogDebugPlot::PlotValue(this, "Frame Time", GAverageMS);
//const float LocalWorldTime = GetWorld()->GetTimeSeconds();
//const float ServerWorldTime = GetServerWorldTimeSeconds();
//const float ServerWorldTimeDelta = LocalWorldTime - ServerWorldTime;
//FCogDebugPlot::PlotValue(this, "Server World Time Delta", ServerWorldTimeDelta);
CogWindowManager->Tick(DeltaSeconds);
#endif //ENABLE_COG
@@ -11,6 +11,7 @@
#if ENABLE_COG
#include "CogAbilityReplicator.h"
#include "CogDebugDraw.h"
#include "CogDebugPlot.h"
#include "CogDebugReplicator.h"
#include "CogEngineReplicator.h"
#endif //ENABLE_COG
@@ -202,3 +203,29 @@ void ACogSamplePlayerController::Server_SetTarget_Implementation(AActor* Value)
{
Target = Value;
}
//--------------------------------------------------------------------------------------------------------------------------
const ACogSamplePlayerController* ACogSamplePlayerController::GetFirstLocalPlayerController(UObject* WorldContextObject)
{
UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull);
if (World == nullptr)
{
return nullptr;
}
UGameInstance* const GameInstance = World->GetGameInstance();
if (GameInstance == nullptr)
{
return nullptr;
}
ACogSamplePlayerController* PlayerController = Cast<ACogSamplePlayerController>(GameInstance->GetFirstLocalPlayerController(World));
return PlayerController;
}
//--------------------------------------------------------------------------------------------------------------------------
float ACogSamplePlayerController::GetClientLag() const
{
return (PlayerState != nullptr && GetNetMode() != NM_Standalone) ? (0.0001f * 0.5f * PlayerState->ExactPing) : 0.f;
}
@@ -25,12 +25,16 @@ class ACogSamplePlayerController
public:
static const ACogSamplePlayerController* GetFirstLocalPlayerController(UObject* WorldContextObject);
ACogSamplePlayerController();
virtual void BeginPlay() override;
virtual void Tick(float DeltaSeconds) override;
float GetClientLag() const;
//----------------------------------------------------------------------------------------------------------------------
// Possession
//----------------------------------------------------------------------------------------------------------------------
+153 -45
View File
@@ -6,12 +6,74 @@
#include "CogSampleFunctionLibrary_Gameplay.h"
#include "CogSampleFunctionLibrary_Team.h"
#include "CogSampleLogCategories.h"
#include "CogSamplePlayerController.h"
#include "GameFramework/Character.h"
#include "Net/Core/PushModel/PushModel.h"
#include "Net/UnrealNetwork.h"
#if ENABLE_COG
#include "CogDebugLog.h"
#include "CogDebugDraw.h"
#endif //ENABLE_COG
//--------------------------------------------------------------------------------------------------------------------------
// Postulates:
//--------------------------------------------------------------------------------------------------------------------------
//
// Projectiles can be launched by a Player or a NPC.
// Projectiles can hit the world, or another player, or a NPC.
// When hitting characters, projectiles do not hit the characters' capsules, but their animated hit boxes.
// The server do not update animations and therefore do not update animated hit boxes(like Fortnite)
// The server applies the gameplay effects related to projectile hit.
//
//--------------------------------------------------------------------------------------------------------------------------
// Questions/Answers:
//--------------------------------------------------------------------------------------------------------------------------
//
// Where should projectile collision happen ? On the server, or on the client ?
//
// On the clients.If projectiles should hit animated hit boxes, and if hit boxes are not updated on the server,
// then we need to rely on the clients to perform the collision detection.Clients should send the hit result to the
// server, the server should verify if the result is valid(anti cheat), and then apply gameplay effects.
//
// If the projectile is launched by a NPC and hit a player, which client should send the hit result to the server ?
// The client that got hit, or another client that also detected the hit ?
//
//
//
// If the projectile is launched by a player and hit another player, which client should detect and send the hit result
// to the server ? The player that launched the projectile or/ and the player that got hit ?
//
// If the server only receives the hit from the client that got hit, then that client can prevent this message
// from being sent, or he can alter the message to gain advantages. The server needs another information.
// This information can come from the launcher of the projectile.
//
// If the projectile is launched by a NPC and hit another NPC, which client should send the hit result to the server ?
//
// One client could be made responsible to detect hits received by a specific NPC.
//
//--------------------------------------------------------------------------------------------------------------------------
UCogSampleProjectileComponent::UCogSampleProjectileComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SetIsReplicatedByDefault(true);
bAutoActivate = false;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
FDoRepLifetimeParams Params;
Params.bIsPushBased = true;
Params.Condition = COND_None;
DOREPLIFETIME_WITH_PARAMS_FAST(UCogSampleProjectileComponent, ServerSpawnLocation, Params);
DOREPLIFETIME_WITH_PARAMS_FAST(UCogSampleProjectileComponent, ServerSpawnRotation, Params);
DOREPLIFETIME_WITH_PARAMS_FAST(UCogSampleProjectileComponent, ServerSpawnVelocity, Params);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::BeginPlay()
{
@@ -20,10 +82,7 @@ void UCogSampleProjectileComponent::BeginPlay()
Creator = UCogSampleFunctionLibrary_Gameplay::GetCreator(GetOwner());
SpawnPrediction = GetOwner()->FindComponentByClass<UCogSampleSpawnPredictionComponent>();
if (GetOwner()->HasAuthority())
{
RegisterAllEffects();
}
RegisterAllEffects();
Collision = Cast<USphereComponent>(CollisionReference.GetComponent(GetOwner()));
if (Collision != nullptr)
@@ -37,14 +96,59 @@ void UCogSampleProjectileComponent::BeginPlay()
AssistanceOverlap->OnComponentBeginOverlap.AddDynamic(this, &UCogSampleProjectileComponent::OnAssistanceOverlapBegin);
}
if (GetOwner()->GetLocalRole() != ROLE_Authority)
{
Activate(false);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::Activate(bool bReset)
{
//------------------------------------------------------------------------------------------------
// Save the spawn location and rotation and get them replicated because, we want remote clients
// to tick projectiles on their own, and be synced with the server. To do so they need to
// recompute (to catchup) the projectile movement from its initial location, rotation and velocity.
// If we don't reposition the remote client projectile at its initial values, we get some offset
// because the server doesn't necessarly replicates the location and rotation of the projectile
// at its spawn frame.
//------------------------------------------------------------------------------------------------
if (GetOwner()->GetLocalRole() == ROLE_Authority)
{
COMPARE_ASSIGN_AND_MARK_PROPERTY_DIRTY(UCogSampleProjectileComponent, ServerSpawnLocation, GetOwner()->GetActorLocation(), this);
COMPARE_ASSIGN_AND_MARK_PROPERTY_DIRTY(UCogSampleProjectileComponent, ServerSpawnRotation, GetOwner()->GetActorRotation(), this);
COMPARE_ASSIGN_AND_MARK_PROPERTY_DIRTY(UCogSampleProjectileComponent, ServerSpawnVelocity, Velocity, this);
}
else
{
GetOwner()->SetActorLocationAndRotation(ServerSpawnLocation, ServerSpawnRotation);
Velocity = ServerSpawnVelocity;
}
Super::Activate(bReset);
#if ENABLE_COG
DrawDebugCurrentState(FColor::Green);
if (FCogDebugLog::IsLogCategoryActive(LogCogProjectile))
{
LastDebugLocation = GetOwner()->GetActorLocation();
}
#endif //ENABLE_COG
}
//--------------------------------------------------------------------------
// Catchup after settings LastDebugLocation because Tick will be triggered
// by Catchup and LastDebugLocation is used in Tick debug draw.
//--------------------------------------------------------------------------
if (GetOwner()->GetLocalRole() != ROLE_Authority)
{
if (const ACogSamplePlayerController* Controller = ACogSamplePlayerController::GetFirstLocalPlayerController(this))
{
Catchup(Controller->GetClientLag());
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
@@ -68,8 +172,8 @@ void UCogSampleProjectileComponent::TickComponent(float DeltaTime, enum ELevelTi
const float CollisionRadius = Collision != nullptr ? Collision->GetScaledSphereRadius() : 0.0f;
const float AssistanceRadius = AssistanceOverlap != nullptr ? AssistanceOverlap->GetScaledSphereRadius() : 0.0f;
const float DebugRadius = FMath::Max(CollisionRadius, AssistanceRadius);
const FColor Color = SpawnPrediction != nullptr ? SpawnPrediction->GetRoleColor() : FColor(128, 128, 128, 255);
const bool Show = SpawnPrediction == nullptr || SpawnPrediction->GetRole() != ECogSampleSpawnPredictionRole::Replicated;
const FColor Color = (SpawnPrediction != nullptr ? SpawnPrediction->GetRoleColor() : FColor(128, 128, 128, 255)).WithAlpha(IsCatchingUp ? 100 : 255);
if (Show && UpdatedComponent != nullptr)
{
@@ -99,28 +203,39 @@ void UCogSampleProjectileComponent::TickComponent(float DeltaTime, enum ELevelTi
#endif //ENABLE_COG
}
//--------------------------------------------------------------------------------------------------------------------------
//void UCogSampleProjectileComponent::CatchupReplicatedActor(float CatchupDuration)
//{
// COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator.Get(), TEXT("Projectile:%s - Role:%s - CatchupDuration:%0.2f"), *GetName(), *GetRoleName(), CatchupDuration);
//
// const FVector OldPosition = GetOwner()->GetActorLocation();
// const float OldSpeed = Velocity.Length();
//
// TickComponent(CatchupDuration, LEVELTICK_All, nullptr);
//
// COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator, TEXT("Distance:%0.2f - OldSpeed:%0.2f - NewSpeed:%0.2f"),
// (GetOwner()->GetActorLocation() - OldPosition).Length(),
// OldSpeed,
// Velocity.Length());
//
// if (SpawnPrediction != nullptr)
// {
// if (UCogSampleSpawnPrediction* SpawnPrediction2 = SpawnPrediction->GetSpawnPrediction())
// {
// SpawnPrediction2->ProjectileMovement->Velocity = ProjectileMovement->Velocity;
// }
// }
//}
void UCogSampleProjectileComponent::Catchup(float CatchupDuration)
{
COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator.Get(), TEXT("Projectile:%s - Role:%s - CatchupDuration:%0.2f"), *GetName(), *GetRoleName(), CatchupDuration);
IsCatchingUp = true;
TickComponent(CatchupDuration, LEVELTICK_All, nullptr);
IsCatchingUp = false;
#if ENABLE_COG
DrawDebugCurrentState(FColor::Red);
#endif //ENABLE_COG
}
//--------------------------------------------------------------------------------------------------------------------------
#if ENABLE_COG
void UCogSampleProjectileComponent::DrawDebugCurrentState(const FColor& Color, bool DrawVelocity)
{
if (FCogDebugLog::IsLogCategoryActive(LogCogProjectile))
{
float CollisionRadius = Collision != nullptr ? Collision->GetScaledSphereRadius() : 0.0f;
float AssistanceRadius = AssistanceOverlap != nullptr ? AssistanceOverlap->GetScaledSphereRadius() : 0.0f;
float DebugRadius = FMath::Max(CollisionRadius, AssistanceRadius);
FCogDebugDraw::Sphere(LogCogProjectile, GetOwner(), GetOwner()->GetActorLocation(), DebugRadius, Color, true, 0);
if (DrawVelocity)
{
FCogDebugDraw::Arrow(LogCogProjectile, GetOwner(), GetOwner()->GetActorLocation(), GetOwner()->GetActorLocation() + Velocity * 0.1f, Color, true, 0);
}
}
}
#endif //ENABLE_COG
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::RegisterAllEffects()
@@ -181,16 +296,6 @@ bool UCogSampleProjectileComponent::ShouldProcessOverlap(AActor* OtherActor, UPr
return false;
}
////-----------------------------------------------------------------------------------------
//// Don't overlap if OtherActor is the simulated proxy replicated one time from server to
//// client for synch-up
////-----------------------------------------------------------------------------------------
//if (OtherActor->IsA(AGPCoreProjectile::StaticClass()) && OtherActor->GetLocalRole() == ROLE_SimulatedProxy)
//{
// COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator.Get(), TEXT("Skipped:SimulatedProxyProjectile"));
// return false;
//}
if (IsAlreadyProcessingAnOverlap)
{
COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator.Get(), TEXT("Skipped:AlreadyProcessingAnOverlap"));
@@ -369,15 +474,24 @@ bool UCogSampleProjectileComponent::ShouldHit_Implementation(const FHitResult& H
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::Hit_Implementation(const FHitResult& HitResult, FCogSampleHitConsequence& hitConsequence)
void UCogSampleProjectileComponent::Hit_Implementation(const FHitResult& HitResult, FCogSampleHitConsequence& HitConsequence)
{
AActor* HitActor = HitResult.GetActor();
#if ENABLE_COG
DrawDebugCurrentState(FColor::White, false);
FCogDebugDraw::Arrow(LogCogProjectile, GetOwner(), HitResult.Location, HitResult.Location + HitResult.Normal * 50.0f, FColor::Red, true, 0);
FCogDebugDraw::Box(LogCogProjectile, GetOwner(), HitResult.Location, FVector(0.0f, 5.0f, 5.0f), FRotationMatrix::MakeFromX(HitResult.Normal).ToQuat(), FColor::Red, true, 0);
FCogDebugDraw::Arrow(LogCogProjectile, GetOwner(), HitResult.ImpactPoint, HitResult.ImpactPoint + HitResult.ImpactNormal * 50.0f, FColor::Yellow, true, 0);
FCogDebugDraw::Box(LogCogProjectile, GetOwner(), HitResult.ImpactPoint, FVector(0.0f, 5.0f, 5.0f), FRotationMatrix::MakeFromX(HitResult.ImpactNormal).ToQuat(), FColor::Yellow, true, 0);
#endif //ENABLE_COG
UAbilitySystemComponent* TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(HitActor);
if (TargetAbilitySystem == nullptr)
{
return;
}
for (const FCogSampleProjectileEffectConfig& EffectConfig : Effects)
{
for (TSubclassOf<UGameplayEffect> EffectClass : EffectConfig.Effects)
@@ -404,12 +518,6 @@ void UCogSampleProjectileComponent::Hit_Implementation(const FHitResult& HitResu
continue;
}
UAbilitySystemComponent* TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(HitActor);
if (TargetAbilitySystem == nullptr)
{
continue;
}
Spec->GetContext().AddHitResult(HitResult, true);
TargetAbilitySystem->ApplyGameplayEffectSpecToSelf(*Spec);
}
+25 -10
View File
@@ -7,8 +7,6 @@
#include "GameplayEffect.h"
#include "CogSampleProjectileComponent.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
// FCogSampleProjectileEffectConfig
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FCogSampleProjectileEffectConfig
@@ -25,8 +23,6 @@ struct FCogSampleProjectileEffectConfig
TArray<TSubclassOf<UGameplayEffect>> Effects;
};
//--------------------------------------------------------------------------------------------------------------------------
// FCogSampleHitConsequence
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FCogSampleHitConsequence
@@ -43,8 +39,6 @@ struct FCogSampleHitConsequence
bool HideOnStop = false;
};
//--------------------------------------------------------------------------------------------------------------------------
// UCogSampleProjectileComponent
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(BlueprintType, meta = (BlueprintSpawnableComponent))
class UCogSampleProjectileComponent : public UProjectileMovementComponent
@@ -53,10 +47,16 @@ class UCogSampleProjectileComponent : public UProjectileMovementComponent
public:
UCogSampleProjectileComponent(const FObjectInitializer& ObjectInitializer);
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction);
virtual void Activate(bool bReset) override;
UFUNCTION(BlueprintCallable)
void ClearHitActors();
@@ -70,7 +70,7 @@ protected:
virtual FString GetRoleName() const;
//virtual void CatchupReplicatedActor(float CatchupDuration);
virtual void Catchup(float CatchupDuration);
virtual bool ShouldProcessOverlap(AActor* OtherActor, UPrimitiveComponent* OtherComp, bool RequireValidActor);
@@ -91,11 +91,11 @@ protected:
void RegisterAllEffects();
UPROPERTY(EditAnywhere)
UPROPERTY(EditAnywhere, Category = "Projectile")
FComponentReference CollisionReference;
UPROPERTY(EditAnywhere)
FComponentReference OverlapReference;
UPROPERTY(EditAnywhere, Category = "Projectile")
FComponentReference OverlapReference;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile")
bool CanHitCreator = false;
@@ -114,6 +114,15 @@ protected:
UPROPERTY()
TWeakObjectPtr<UCogSampleSpawnPredictionComponent> SpawnPrediction = nullptr;
UPROPERTY(Replicated)
FVector ServerSpawnLocation = FVector::ZeroVector;
UPROPERTY(Replicated)
FRotator ServerSpawnRotation = FRotator::ZeroRotator;
UPROPERTY(Replicated)
FVector ServerSpawnVelocity = FVector::ZeroVector;
/** Re-entrancy guard */
bool IsAlreadyProcessingAnOverlap = false;
@@ -122,7 +131,13 @@ protected:
TMap<TSubclassOf<UGameplayEffect>, FGameplayEffectSpecHandle> EffectsMap;
float SpawnTime = 0.0f;
bool IsCatchingUp = false;
#if ENABLE_COG
void DrawDebugCurrentState(const FColor& Color, bool DrawVelocity = true);
FVector LastDebugLocation = FVector::ZeroVector;
#endif //ENABLE_COG
};
+2
View File
@@ -10,6 +10,7 @@
- CogEngine: Add screen settings (fullscreen, borderless, window and resolution)
- CogEngine: make a better widget for CheckBoxState for input shortcuts
- CogEngine: save active log categories
- CogEngine: add menu on the PlotWindow wih the controls
- CogSample: Add a custom window in sample (changing the character faction)
- CogSample: Create more abilities
@@ -19,5 +20,6 @@
- CogSample: Add more debug for area (change color on tick, duration ...)
- CogDebug: Check KismetExecutionMessage for warnings. As an exemple it is used by GEngine::GetWorldFromContextObject.
- CogDebug: Rework Tickness and Duration params.
- CogInput: Add gamepad stick drag to set their values