188 - Confirming the Hit
This commit is contained in:
parent
650b206797
commit
c455d1655d
|
@ -59,6 +59,119 @@ FFramePackage ULagCompensationComponent::InterpBetweenFrames(const FFramePackage
|
|||
return InterpFramePackage;
|
||||
}
|
||||
|
||||
FServerSideRewindResult ULagCompensationComponent::ConfirmHit(const FFramePackage& Package, ABlasterCharacter* HitCharacter,
|
||||
const FVector_NetQuantize& TraceStart, const FVector_NetQuantize HitLocation)
|
||||
{
|
||||
if (HitCharacter == nullptr) return FServerSideRewindResult();
|
||||
|
||||
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_Visibility, ECR_Block);
|
||||
|
||||
FHitResult ConfirmHitResult;
|
||||
const FVector TraceEnd = TraceStart + (HitLocation - TraceStart) * 1.25f;
|
||||
UWorld* World = GetWorld();
|
||||
if (World)
|
||||
{
|
||||
World->LineTraceSingleByChannel(
|
||||
ConfirmHitResult,
|
||||
TraceStart,
|
||||
TraceEnd,
|
||||
ECC_Visibility
|
||||
);
|
||||
|
||||
if (ConfirmHitResult.bBlockingHit) // we hit the head, return early
|
||||
{
|
||||
ResetHitBoxes(HitCharacter, CurrentFrame);
|
||||
EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::QueryAndPhysics);
|
||||
return FServerSideRewindResult{ true, true };
|
||||
}
|
||||
|
||||
// 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_Visibility, ECR_Block);
|
||||
}
|
||||
}
|
||||
|
||||
World->LineTraceSingleByChannel(
|
||||
ConfirmHitResult,
|
||||
TraceStart,
|
||||
TraceEnd,
|
||||
ECC_Visibility
|
||||
);
|
||||
|
||||
if (ConfirmHitResult.bBlockingHit)
|
||||
{
|
||||
ResetHitBoxes(HitCharacter, CurrentFrame);
|
||||
EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::QueryAndPhysics);
|
||||
return FServerSideRewindResult{ true, false };
|
||||
}
|
||||
|
||||
ResetHitBoxes(HitCharacter, CurrentFrame);
|
||||
EnableCharacterMeshCollision(HitCharacter, ECollisionEnabled::QueryAndPhysics);
|
||||
return FServerSideRewindResult{ false, false };
|
||||
}
|
||||
}
|
||||
|
||||
void ULagCompensationComponent::CacheBoxPositions(ABlasterCharacter* HitCharacter, FFramePackage& OutFramePackage)
|
||||
{
|
||||
if (HitCharacter == nullptr) return;
|
||||
|
||||
for (auto& HitBoxPair : HitCharacter->HitCollisionBoxes)
|
||||
{
|
||||
if (HitBoxPair.Value != nullptr)
|
||||
{
|
||||
FBoxInformation BoxInfo;
|
||||
BoxInfo.Location = HitBoxPair.Value->GetComponentLocation();
|
||||
BoxInfo.Rotation = HitBoxPair.Value->GetComponentRotation();
|
||||
BoxInfo.BoxExtend = HitBoxPair.Value->GetScaledBoxExtent();
|
||||
|
||||
OutFramePackage.HitBoxInfo.Add(HitBoxPair.Key, BoxInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ULagCompensationComponent::MoveBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package)
|
||||
{
|
||||
if (HitCharacter == nullptr) return;
|
||||
|
||||
for (auto& HitBoxPair : HitCharacter->HitCollisionBoxes)
|
||||
{
|
||||
if (HitBoxPair.Value != nullptr)
|
||||
{
|
||||
HitBoxPair.Value->SetWorldLocation(Package.HitBoxInfo[HitBoxPair.Key].Location);
|
||||
HitBoxPair.Value->SetWorldRotation(Package.HitBoxInfo[HitBoxPair.Key].Rotation);
|
||||
HitBoxPair.Value->SetBoxExtent(Package.HitBoxInfo[HitBoxPair.Key].BoxExtend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ULagCompensationComponent::ResetHitBoxes(ABlasterCharacter* HitCharacter, const FFramePackage& Package)
|
||||
{
|
||||
if (HitCharacter == nullptr) return;
|
||||
|
||||
for (auto& HitBoxPair : HitCharacter->HitCollisionBoxes)
|
||||
{
|
||||
if (HitBoxPair.Value != nullptr)
|
||||
{
|
||||
HitBoxPair.Value->SetWorldLocation(Package.HitBoxInfo[HitBoxPair.Key].Location);
|
||||
HitBoxPair.Value->SetWorldRotation(Package.HitBoxInfo[HitBoxPair.Key].Rotation);
|
||||
HitBoxPair.Value->SetBoxExtent(Package.HitBoxInfo[HitBoxPair.Key].BoxExtend);
|
||||
HitBoxPair.Value->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ULagCompensationComponent::ShowFramePackage(const FFramePackage& Package, const FColor Color)
|
||||
{
|
||||
for (auto& BoxInfo : Package.HitBoxInfo)
|
||||
|
@ -75,7 +188,7 @@ void ULagCompensationComponent::ShowFramePackage(const FFramePackage& Package, c
|
|||
}
|
||||
}
|
||||
|
||||
void ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation,
|
||||
FServerSideRewindResult ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation,
|
||||
float HitTime)
|
||||
{
|
||||
bool bReturn = HitCharacter == nullptr ||
|
||||
|
@ -83,10 +196,10 @@ void ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter
|
|||
HitCharacter->GetLagCompensation()->FrameHistory.GetHead() == nullptr ||
|
||||
HitCharacter->GetLagCompensation()->FrameHistory.GetTail() == nullptr;
|
||||
|
||||
if (bReturn) return;
|
||||
if (bReturn) FServerSideRewindResult();
|
||||
|
||||
// Frame package that we check to verify a hit
|
||||
FFramePackage FrameToSheck;
|
||||
FFramePackage FrameToCheck;
|
||||
bool bShouldInterpolate = true;
|
||||
|
||||
const TDoubleLinkedList<FFramePackage>& History = HitCharacter->GetLagCompensation()->FrameHistory;
|
||||
|
@ -95,16 +208,16 @@ void ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter
|
|||
if (OldestHistoryTime > HitTime)
|
||||
{
|
||||
// Too far back, too laggy to do SSR
|
||||
return;
|
||||
FServerSideRewindResult();
|
||||
}
|
||||
if (OldestHistoryTime == HitTime)
|
||||
{
|
||||
FrameToSheck = History.GetTail()->GetValue();
|
||||
FrameToCheck = History.GetTail()->GetValue();
|
||||
bShouldInterpolate = false;
|
||||
}
|
||||
if (NewestHistoryTime <= HitTime)
|
||||
{
|
||||
FrameToSheck = History.GetHead()->GetValue();
|
||||
FrameToCheck = History.GetHead()->GetValue();
|
||||
bShouldInterpolate = false;
|
||||
}
|
||||
auto Younger = History.GetHead();
|
||||
|
@ -120,13 +233,24 @@ void ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter
|
|||
}
|
||||
if (Older->GetValue().Time == HitTime)
|
||||
{
|
||||
FrameToSheck = Older->GetValue();
|
||||
FrameToCheck = Older->GetValue();
|
||||
bShouldInterpolate = false;
|
||||
}
|
||||
|
||||
if (bShouldInterpolate) // Why not just check if FrameToCheck == nullptr?
|
||||
{
|
||||
// Interpolate between Younger and Older
|
||||
FrameToCheck = InterpBetweenFrames(Older->GetValue(), Younger->GetValue(), HitTime);
|
||||
}
|
||||
|
||||
return ConfirmHit(FrameToCheck, HitCharacter, TraceStart, HitLocation);
|
||||
}
|
||||
|
||||
void ULagCompensationComponent::EnableCharacterMeshCollision(ABlasterCharacter* HitCharacter, ECollisionEnabled::Type CollisionEnabled)
|
||||
{
|
||||
if (HitCharacter && HitCharacter->GetMesh())
|
||||
{
|
||||
HitCharacter->GetMesh()->SetCollisionEnabled(CollisionEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,18 @@ struct FFramePackage
|
|||
TMap<FName, FBoxInformation> HitBoxInfo;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FServerSideRewindResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
bool bHitConfirmed;
|
||||
|
||||
UPROPERTY()
|
||||
bool bHeadShot;
|
||||
};
|
||||
|
||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||
class BLASTER_API ULagCompensationComponent : public UActorComponent
|
||||
{
|
||||
|
@ -43,13 +55,17 @@ public:
|
|||
friend ABlasterCharacter;
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
void ShowFramePackage(const FFramePackage& Package, const FColor Color);
|
||||
void ServerSideRewind(class ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation, float HitTime);
|
||||
FServerSideRewindResult ServerSideRewind(class ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation, float HitTime);
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
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);
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
|
|
Loading…
Reference in New Issue