// Fill out your copyright notice in the Description page of Project Settings. #include "LagCompensationComponent.h" #include "Components/BoxComponent.h" ULagCompensationComponent::ULagCompensationComponent() { PrimaryComponentTick.bCanEverTick = true; } void ULagCompensationComponent::BeginPlay() { Super::BeginPlay(); } void ULagCompensationComponent::SaveFramePackage(FFramePackage& Package) { Character = Character == nullptr ? Cast(GetOwner()) : Character; if (Character) { Package.Time = GetWorld()->GetTimeSeconds(); for (auto& BoxPair : Character->HitCollisionBoxes) { FBoxInformation BoxInformation; BoxInformation.Location = BoxPair.Value->GetComponentLocation(); BoxInformation.Rotation = BoxPair.Value->GetComponentRotation(); BoxInformation.BoxExtend = BoxPair.Value->GetScaledBoxExtent(); Package.HitBoxInfo.Add(BoxPair.Key, BoxInformation); } } } void ULagCompensationComponent::ShowFramePackage(const FFramePackage& Package, const FColor Color) { for (auto& BoxInfo : Package.HitBoxInfo) { DrawDebugBox( GetWorld(), BoxInfo.Value.Location, BoxInfo.Value.BoxExtend, FQuat(BoxInfo.Value.Rotation), Color, false, 4.f ); } } void ULagCompensationComponent::ServerSideRewind(ABlasterCharacter* HitCharacter, const FVector_NetQuantize& TraceStart, const FVector_NetQuantize& HitLocation, float HitTime) { bool bReturn = HitCharacter == nullptr || HitCharacter->GetLagCompensation() == nullptr || HitCharacter->GetLagCompensation()->FrameHistory.GetHead() == nullptr || HitCharacter->GetLagCompensation()->FrameHistory.GetTail() == nullptr; if (bReturn) return; // Frame package that we check to verify a hit FFramePackage FrameToSheck; bool bShouldInterpolate = true; const TDoubleLinkedList& History = HitCharacter->GetLagCompensation()->FrameHistory; const float OldestHistoryTime = History.GetTail()->GetValue().Time; const float NewestHistoryTime = History.GetHead()->GetValue().Time; if (OldestHistoryTime > HitTime) { // Too far back, too laggy to do SSR return; } if (OldestHistoryTime == HitTime) { FrameToSheck = History.GetTail()->GetValue(); bShouldInterpolate = false; } if (NewestHistoryTime <= HitTime) { FrameToSheck = History.GetHead()->GetValue(); bShouldInterpolate = false; } auto Younger = History.GetHead(); auto Older = History.GetHead(); while (Older->GetValue().Time > HitTime) { if (Older->GetNextNode() == nullptr) break; Older = Older->GetNextNode(); if (Older->GetValue().Time > HitTime) { Younger = Older; } } if (Older->GetValue().Time == HitTime) { FrameToSheck = Older->GetValue(); bShouldInterpolate = false; } if (bShouldInterpolate) // Why not just check if FrameToCheck == nullptr? { // Interpolate between Younger and Older } } void ULagCompensationComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (FrameHistory.Num() <= 1) { FFramePackage ThisFrame; SaveFramePackage(ThisFrame); FrameHistory.AddHead(ThisFrame); } else { float HistoryLength = FrameHistory.GetHead()->GetValue().Time - FrameHistory.GetTail()->GetValue().Time; while (HistoryLength > MaxRecordTime) { FrameHistory.RemoveNode(FrameHistory.GetTail()); HistoryLength = FrameHistory.GetHead()->GetValue().Time - FrameHistory.GetTail()->GetValue().Time; } FFramePackage ThisFrame; SaveFramePackage(ThisFrame); FrameHistory.AddHead(ThisFrame); ShowFramePackage(ThisFrame, FColor::Red); } }