From 4ae87bee2a72a4e72410de376ca028a3a08d93f8 Mon Sep 17 00:00:00 2001 From: Kingsmedia Date: Sat, 28 May 2022 00:28:02 +0200 Subject: [PATCH] 198 - Projectile Server-Side Rewind --- .../Components/LagCompensationComponent.cpp | 82 ++++++++++++++++++- .../Components/LagCompensationComponent.h | 52 ++++++++---- Source/Blaster/Weapon/ProjectileBullet.cpp | 2 + 3 files changed, 120 insertions(+), 16 deletions(-) diff --git a/Source/Blaster/Components/LagCompensationComponent.cpp b/Source/Blaster/Components/LagCompensationComponent.cpp index b5397fb..3491064 100644 --- a/Source/Blaster/Components/LagCompensationComponent.cpp +++ b/Source/Blaster/Components/LagCompensationComponent.cpp @@ -213,9 +213,82 @@ FServerSideRewindResult ULagCompensationComponent::ConfirmHit(const FFramePackag return FServerSideRewindResult{ false, false }; } +FServerSideRewindResult ULagCompensationComponent::ProjectileConfirmHit(const FFramePackage& Package, ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, + const FVector_NetQuantize100& InitialVelocity, float HitTime) +{ + FFramePackage CurrentFrame; + CacheBoxPositions(HitCharacter, CurrentFrame); + MoveBoxes(HitCharacter, Package); + EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::NoCollision); + + // Enable collision for the head first + UBoxComponent* HeadBox = HitCharacter->HitCollisionBoxes[FName("head")]; + HeadBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly); + HeadBox->SetCollisionResponseToChannel(ECC_HitBox, ECR_Block); + + FPredictProjectilePathParams PathParams; + PathParams.bTraceWithCollision = true; + PathParams.MaxSimTime = MaxRecordTime; + PathParams.LaunchVelocity = InitialVelocity; + PathParams.StartLocation = TraceStart; + PathParams.SimFrequency = 15.f; + PathParams.ProjectileRadius = 5.f; + PathParams.TraceChannel = ECC_HitBox; + PathParams.ActorsToIgnore.Add(GetOwner()); + PathParams.DrawDebugTime = 5.f; + PathParams.DrawDebugType = EDrawDebugTrace::ForDuration; + + FPredictProjectilePathResult PathResult; + UGameplayStatics::PredictProjectilePath(this, PathParams, PathResult); + + if (PathResult.HitResult.bBlockingHit) // we hit the head, return early + { + if (PathResult.HitResult.Component.IsValid()) + { + UBoxComponent* Box = Cast(PathResult.HitResult.Component); + if (Box) + { + DrawDebugBox(GetWorld(), Box->GetComponentLocation(), Box->GetScaledBoxExtent(), FQuat(Box->GetComponentRotation()), FColor::Red, false, 8.f); + } + } + ResetHitBoxes(HitCharacter, CurrentFrame); + EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::QueryAndPhysics); + return FServerSideRewindResult{ true, true }; + } + + // we didn't hit the head; check the rest of the boxes + for (auto& HitBoxPair : HitCharacter->HitCollisionBoxes) + { + if (HitBoxPair.Value != nullptr) + { + HitBoxPair.Value->SetCollisionEnabled(ECollisionEnabled::QueryOnly); + HitBoxPair.Value->SetCollisionResponseToChannel(ECC_HitBox, ECR_Block); + } + } + + UGameplayStatics::PredictProjectilePath(this, PathParams, PathResult); + if (PathResult.HitResult.bBlockingHit) + { + if (PathResult.HitResult.Component.IsValid()) + { + UBoxComponent* Box = Cast(PathResult.HitResult.Component); + if (Box) + { + DrawDebugBox(GetWorld(), Box->GetComponentLocation(), Box->GetScaledBoxExtent(), FQuat(Box->GetComponentRotation()), FColor::Blue, false, 8.f); + } + } + ResetHitBoxes(HitCharacter, CurrentFrame); + EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::QueryAndPhysics); + return FServerSideRewindResult{ true, false }; + } + + ResetHitBoxes(HitCharacter, CurrentFrame); + EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::QueryAndPhysics); + return FServerSideRewindResult{ false, false }; +} FShotgunServerSideRewindResult ULagCompensationComponent::ShotgunConfirmHit(const TArray& FramePackages, - const FVector_NetQuantize& TraceStart, const TArray& HitLocations) + const FVector_NetQuantize& TraceStart, const TArray& HitLocations) { for (auto& Frame : FramePackages) { @@ -415,6 +488,13 @@ FServerSideRewindResult ULagCompensationComponent::ServerSideRewind(ABlasterChar return ConfirmHit(FrameToCheck, HitCharacter, TraceStart, HitLocation); } +FServerSideRewindResult ULagCompensationComponent::ProjectilServerSideRewind(ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, + const FVector_NetQuantize100& InitialVelocity, float HitTime) +{ + const FFramePackage FrameToCheck = GetFrameToCheck(HitCharacter, HitTime); + return ProjectileConfirmHit(FrameToCheck, HitCharacter, TraceStart, InitialVelocity, HitTime); +} + FShotgunServerSideRewindResult ULagCompensationComponent::ShotgunServerSideRewind(const TArray& HitCharacters, const FVector_NetQuantize& TraceStart, const TArray& HitLocations, float HitTime) { diff --git a/Source/Blaster/Components/LagCompensationComponent.h b/Source/Blaster/Components/LagCompensationComponent.h index 07f73b6..1c3ae6e 100644 --- a/Source/Blaster/Components/LagCompensationComponent.h +++ b/Source/Blaster/Components/LagCompensationComponent.h @@ -71,13 +71,32 @@ public: friend ABlasterCharacter; virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; void ShowFramePackage(const FFramePackage& Package, const FColor Color); + + // Hitscan FServerSideRewindResult ServerSideRewind( ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation, float HitTime ); + + // Projectiles + FServerSideRewindResult ProjectilServerSideRewind( + ABlasterCharacter* HitCharacter, + const FVector_NetQuantize& TraceStart, + const FVector_NetQuantize100& InitialVelocity, + float HitTime + ); + // Shotgun + UFUNCTION(Server, Reliable) + void ShotgunServerScoreRequest( + const TArray& HitCharacters, + const FVector_NetQuantize& TraceStart, + const TArray& HitLocations, + float HitTime + ); + UFUNCTION(Server, Reliable) void ServerScoreRequest( ABlasterCharacter* HitCharacter, @@ -87,14 +106,6 @@ public: AWeapon* DamageCauser ); - UFUNCTION(Server, Reliable) - void ShotgunServerScoreRequest( - const TArray& HitCharacters, - const FVector_NetQuantize& TraceStart, - const TArray& HitLocations, - float HitTime - ); - FShotgunServerSideRewindResult ShotgunServerSideRewind( const TArray& HitCharacters, const FVector_NetQuantize& TraceStart, @@ -107,20 +118,31 @@ protected: void SaveFramePackage(); void SaveFramePackage(FFramePackage& Package); FFramePackage InterpBetweenFrames(const FFramePackage& OlderFrame, const FFramePackage& YoungerFrame, float HitTime); - FServerSideRewindResult ConfirmHit( - const FFramePackage& Package, - ABlasterCharacter* HitCharacter, - const FVector_NetQuantize& TraceStart, - const FVector_NetQuantize HitLocation - ); + void CacheBoxPositions(ABlasterCharacter* HitCharacter, FFramePackage& OutFramePackage); void MoveBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package); void ResetHitBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package); void EnableCharacterMeshCollision(ABlasterCharacter* HitCharacter, ECollisionEnabled::Type CollisionEnabled); FFramePackage GetFrameToCheck(ABlasterCharacter* HitCharacter, float HitTime); - // Shotgun related stuff + // Hitscan + FServerSideRewindResult ConfirmHit( + const FFramePackage& Package, + ABlasterCharacter* HitCharacter, + const FVector_NetQuantize& TraceStart, + const FVector_NetQuantize HitLocation + ); + + // Projectile + FServerSideRewindResult ProjectileConfirmHit( + const FFramePackage& Package, + ABlasterCharacter* HitCharacter, + const FVector_NetQuantize& TraceStart, + const FVector_NetQuantize100& InitialVelocity, + float HitTime + ); + // Shotgun FShotgunServerSideRewindResult ShotgunConfirmHit( const TArray& FramePackages, const FVector_NetQuantize& TraceStart, diff --git a/Source/Blaster/Weapon/ProjectileBullet.cpp b/Source/Blaster/Weapon/ProjectileBullet.cpp index 4b3bf2e..6110077 100644 --- a/Source/Blaster/Weapon/ProjectileBullet.cpp +++ b/Source/Blaster/Weapon/ProjectileBullet.cpp @@ -52,6 +52,7 @@ void AProjectileBullet::BeginPlay() { Super::BeginPlay(); + /* FPredictProjectilePathParams PathParams; PathParams.bTraceWithChannel = true; PathParams.bTraceWithCollision = true; @@ -67,4 +68,5 @@ void AProjectileBullet::BeginPlay() FPredictProjectilePathResult PathResult; UGameplayStatics::PredictProjectilePath(this, PathParams, PathResult); + */ }