2023-04-05 00:32:37 -04:00

229 lines
8.7 KiB
C++

// ©2022 Batty Bovine Productions, LLC. All Rights Reserved.
#include "BugPlacerPawn.h"
#include "BugMarkerActor.h"
#include "BugMarkerSubsystem.h"
#include "EngineUtils.h"
#include "ExitingBugPlacementScreen.h"
#include "UnrealzillaGlobalSettings.h"
#include "Components/MaterialBillboardComponent.h"
#include "Components/SphereComponent.h"
#include "GameFramework/Character.h"
#include "GameFramework/FloatingPawnMovement.h"
#include "HAL/IConsoleManager.h"
#include "Kismet/GameplayStatics.h"
ABugPlacerPawn::ABugPlacerPawn()
{
this->PrimaryActorTick.bCanEverTick = true;
this->bArbitraryPlacement = false;
this->bCurrentTraceHit = false;
this->SphereComponent = CreateDefaultSubobject<USphereComponent>("SphereCollision");
this->SphereComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);
this->SphereComponent->CanCharacterStepUpOn = ECanBeCharacterBase::ECB_No;
this->SphereComponent->SetShouldUpdatePhysicsVolume(true);
this->SphereComponent->SetCanEverAffectNavigation(false);
this->SphereComponent->bDynamicObstacle = false;
this->RootComponent = this->SphereComponent;
this->PlacementMarkerRoot = CreateDefaultSubobject<USceneComponent>("PlacementMarkerRoot");
this->PlacementMarkerRoot->AttachToComponent(this->RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
this->LaserGlow = CreateDefaultSubobject<UMaterialBillboardComponent>("LaserGlow");
this->LaserGlow->AttachToComponent(this->PlacementMarkerRoot, FAttachmentTransformRules::KeepRelativeTransform);
this->TraceOriginComponent = CreateDefaultSubobject<USceneComponent>("TraceOrigin");
this->TraceOriginComponent->AttachToComponent(this->RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
this->PawnMovement = CreateDefaultSubobject<UFloatingPawnMovement>("MovementComponent");
if (this->PawnMovement)
{
this->PawnMovement->UpdatedComponent = this->SphereComponent;
}
}
void ABugPlacerPawn::BeginPlay()
{
this->OriginalPlayer = UGameplayStatics::GetPlayerCharacter(this, 0);
this->Activate();
Super::BeginPlay();
}
void ABugPlacerPawn::TraceTimerElapsed()
{
const UWorld *World = this->GetWorld();
if (this->bArbitraryPlacement)
{
this->TraceOriginComponent->SetVisibility(false, true);
this->PlacementMarkerRoot->SetVisibility(true, true);
this->LaserGlow->SetVisibility(false, true);
// If the debugger requests arbitrary placement, put the marker a set distance away from the camera.
this->PlacementMarkerRoot->SetRelativeLocation(FVector(GetDefault<UUnrealzillaGlobalSettings>()->ArbitraryBugPlacementDistance, 0.0f, 0.0f));
this->PlacementMarkerRoot->SetWorldRotation(FRotator::ZeroRotator);
}
else
{
// Under normal circumstances, we place the marker at the point where a laser hits a surface.
this->TraceOriginComponent->SetVisibility(true, true);
this->LaserGlow->SetVisibility(true, true);
FCollisionQueryParams Params;
Params.bTraceComplex = false;
Params.bIgnoreTouches = false;
Params.AddIgnoredActor(this);
FHitResult TraceHit;
const FVector TraceStart = this->GetActorLocation();
const FVector TraceEnd = TraceStart + (this->GetActorForwardVector() * GetDefault<UUnrealzillaGlobalSettings>()->BugPlacementTraceDistance);
this->bCurrentTraceHit = World->LineTraceSingleByChannel(TraceHit, TraceStart, TraceEnd, ECollisionChannel::ECC_Visibility, Params);
// Move bug marker to the current pointer position, or behind
// the camera if the pointer is not currently hitting a surface.
if (this->bCurrentTraceHit)
{
if (ABugMarkerActor *Marker = Cast<ABugMarkerActor>(TraceHit.GetActor()))
{
this->PlacementMarkerRoot->SetVisibility(true, false);
this->UpdateBugInformation(Marker->GetBugData());
this->ShowDummyMarker(false);
}
else
{
this->PlacementMarkerRoot->SetVisibility(true, true);
this->UpdateBugInformation(FUnrealzillaBugData());
this->ShowDummyMarker(true);
}
this->PlacementMarkerRoot->SetWorldLocationAndRotation(TraceHit.ImpactPoint, FRotationMatrix::MakeFromZ(TraceHit.ImpactNormal).ToQuat());
this->ShowCrosshairs(false);
const FVector TraceOriginLocation = this->TraceOriginComponent->GetComponentLocation();
FVector FacingVector = (TraceHit.ImpactPoint - TraceOriginLocation);
FacingVector.Normalize();
const FRotator TraceOriginFacingRotation = FRotationMatrix::MakeFromX(FacingVector).Rotator();
this->TraceOriginComponent->SetWorldRotation(TraceOriginFacingRotation);
const FVector TraceOriginScale = this->TraceOriginComponent->GetRelativeScale3D();
this->TraceOriginComponent->SetRelativeScale3D(FVector(TraceOriginScale.X, TraceOriginScale.Y, (TraceHit.ImpactPoint - TraceOriginLocation).Length()));
}
else
{
this->PlacementMarkerRoot->SetRelativeLocationAndRotation(FVector::ZeroVector, FRotator::ZeroRotator);
this->PlacementMarkerRoot->SetVisibility(false, true);
this->ShowCrosshairs(true);
const FVector TraceOriginLocation = this->TraceOriginComponent->GetComponentLocation();
FVector FacingVector = (TraceEnd - TraceOriginLocation);
FacingVector.Normalize();
const FRotator TraceOriginFacingRotation = FRotationMatrix::MakeFromX(FacingVector).Rotator();
this->TraceOriginComponent->SetWorldRotation(TraceOriginFacingRotation);
const FVector TraceOriginScale = this->TraceOriginComponent->GetRelativeScale3D();
this->TraceOriginComponent->SetRelativeScale3D(FVector(TraceOriginScale.X, TraceOriginScale.Y, (TraceEnd - TraceStart).Length()));
}
}
}
void ABugPlacerPawn::SetArbitraryPlacement(bool bSet)
{
this->bArbitraryPlacement = bSet;
}
void ABugPlacerPawn::PlaceBugMarker()
{
// If there is a surface onto which to place a bug actor, then do so here.
if (this->bArbitraryPlacement || this->bCurrentTraceHit)
{
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
#if WITH_EDITOR
SpawnParams.bHideFromSceneOutliner = true;
#endif
TSubclassOf<ABugMarkerActor> Class = StaticLoadClass(ABugMarkerActor::StaticClass(), nullptr, BUG_MARKER_ACTOR_BP);
ABugMarkerActor *Marker = this->GetWorld()->SpawnActor<ABugMarkerActor>(Class.Get(), this->PlacementMarkerRoot->GetComponentTransform(), SpawnParams);
Marker->LoadBugSubmissionForm();
}
}
void ABugPlacerPawn::Activate()
{
this->SavedMaxSpeed = this->PawnMovement->GetMaxSpeed();
UGameplayStatics::GetPlayerController(this, 0)->Possess(this);
const float &MinTimeDilation = this->GetWorldSettings()->MinGlobalTimeDilation;
this->GetWorldSettings()->SetTimeDilation(MinTimeDilation);
this->CustomTimeDilation = 1.0 / MinTimeDilation;
float TraceInterval = this->GetActorTickInterval() > 0.0f ? this->GetActorTickInterval() : (1.0f / 60.0f) * MinTimeDilation;
this->GetWorldTimerManager().SetTimer(this->TraceTimerHandle, this, &ABugPlacerPawn::TraceTimerElapsed, TraceInterval, true);
}
void ABugPlacerPawn::Deactivate()
{
this->GetWorldTimerManager().ClearAllTimersForObject(this);
this->GetWorldSettings()->SetTimeDilation(1.0f);
UGameplayStatics::GetPlayerController(this, 0)->Possess(this->OriginalPlayer);
this->Destroy();
}
void ABugPlacerPawn::ExitStarted()
{
this->ExitingBugPlacementScreen = CreateWidget<UExitingBugPlacementScreen>(UGameplayStatics::GetPlayerController(this, 0), this->ExitingBugPlacementScreenClass.Get());
this->ExitingBugPlacementScreen->AddToViewport(GetDefault<UUnrealzillaGlobalSettings>()->BugReportWidgetDepth + 10);
}
void ABugPlacerPawn::ExitOngoing(const float ElapsedSeconds)
{
this->ExitingBugPlacementScreen->SetPercent(ElapsedSeconds);
}
void ABugPlacerPawn::ExitTriggered()
{
this->ExitingBugPlacementScreen->RemoveFromParent();
this->Deactivate();
}
void ABugPlacerPawn::ExitCanceled()
{
this->ExitingBugPlacementScreen->RemoveFromParent();
}
void ABugPlacerPawn::SpawnBugPlacerPawn(const UObject *WorldContextObject, TSubclassOf<ABugPlacerPawn> Class)
{
const FTransform &Transform = UGameplayStatics::GetPlayerCameraManager(WorldContextObject, 0)->GetActorTransform();
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
WorldContextObject->GetWorld()->SpawnActor<ABugPlacerPawn>(Class, Transform, SpawnParams);
}
void ABugPlacerPawn::ShowBugMarkersInLevel(const UObject *WorldContextObject)
{
if (UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(WorldContextObject, 0)->GetLocalPlayer()->GetSubsystem<UBugMarkerSubsystem>())
{
BugMarkerSubsystem->ShowBugMarkers();
}
}
void ABugPlacerPawn::HideBugMarkersInLevel(const UObject *WorldContextObject)
{
if (UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(WorldContextObject, 0)->GetLocalPlayer()->GetSubsystem<UBugMarkerSubsystem>())
{
BugMarkerSubsystem->HideBugMarkers();
}
}