104 lines
3.3 KiB
C++
104 lines
3.3 KiB
C++
// Copyright Pacificao. All Rights Reserved.
|
|
|
|
#include "AgrarianMapBoundaryVolume.h"
|
|
#include "AgrarianGameCharacter.h"
|
|
#include "Components/BoxComponent.h"
|
|
#include "GameFramework/CharacterMovementComponent.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
|
|
AAgrarianMapBoundaryVolume::AAgrarianMapBoundaryVolume()
|
|
{
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
bReplicates = false;
|
|
|
|
BoundaryVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("BoundaryVolume"));
|
|
RootComponent = BoundaryVolume;
|
|
BoundaryVolume->SetBoxExtent(FVector(50000.0f, 50000.0f, 25000.0f));
|
|
BoundaryVolume->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
BoundaryVolume->SetHiddenInGame(false);
|
|
BoundaryVolume->ShapeColor = FColor::Yellow;
|
|
}
|
|
|
|
void AAgrarianMapBoundaryVolume::Tick(float DeltaSeconds)
|
|
{
|
|
Super::Tick(DeltaSeconds);
|
|
|
|
if (!HasAuthority() || !bClampPlayersAtBoundary)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TArray<AActor*> Characters;
|
|
UGameplayStatics::GetAllActorsOfClass(this, AAgrarianGameCharacter::StaticClass(), Characters);
|
|
for (AActor* Actor : Characters)
|
|
{
|
|
EnforceBoundaryForCharacter(Cast<AAgrarianGameCharacter>(Actor));
|
|
}
|
|
}
|
|
|
|
bool AAgrarianMapBoundaryVolume::IsLocationOutsideBoundary(const FVector& WorldLocation) const
|
|
{
|
|
if (!BoundaryVolume)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const FVector LocalLocation = GetActorTransform().InverseTransformPosition(WorldLocation);
|
|
const FVector Extent = BoundaryVolume->GetUnscaledBoxExtent();
|
|
return FMath::Abs(LocalLocation.X) > Extent.X
|
|
|| FMath::Abs(LocalLocation.Y) > Extent.Y
|
|
|| FMath::Abs(LocalLocation.Z) > Extent.Z;
|
|
}
|
|
|
|
bool AAgrarianMapBoundaryVolume::IsLocationInsideWarningZone(const FVector& WorldLocation) const
|
|
{
|
|
if (!BoundaryVolume)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const FVector LocalLocation = GetActorTransform().InverseTransformPosition(WorldLocation);
|
|
const FVector Extent = BoundaryVolume->GetUnscaledBoxExtent();
|
|
if (FMath::Abs(LocalLocation.X) > Extent.X || FMath::Abs(LocalLocation.Y) > Extent.Y)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return FMath::Abs(LocalLocation.X) >= Extent.X - WarningDistanceCm
|
|
|| FMath::Abs(LocalLocation.Y) >= Extent.Y - WarningDistanceCm;
|
|
}
|
|
|
|
FVector AAgrarianMapBoundaryVolume::ClampLocationToBoundary(const FVector& WorldLocation) const
|
|
{
|
|
if (!BoundaryVolume)
|
|
{
|
|
return WorldLocation;
|
|
}
|
|
|
|
const FVector Extent = BoundaryVolume->GetUnscaledBoxExtent();
|
|
const float SafePadding = FMath::Clamp(BoundaryPaddingCm, 0.0f, FMath::Min(Extent.X, Extent.Y) * 0.5f);
|
|
const FVector LocalLocation = GetActorTransform().InverseTransformPosition(WorldLocation);
|
|
const FVector ClampedLocalLocation(
|
|
FMath::Clamp(LocalLocation.X, -Extent.X + SafePadding, Extent.X - SafePadding),
|
|
FMath::Clamp(LocalLocation.Y, -Extent.Y + SafePadding, Extent.Y - SafePadding),
|
|
FMath::Clamp(LocalLocation.Z, -Extent.Z + SafePadding, Extent.Z - SafePadding));
|
|
|
|
return GetActorTransform().TransformPosition(ClampedLocalLocation);
|
|
}
|
|
|
|
void AAgrarianMapBoundaryVolume::EnforceBoundaryForCharacter(AAgrarianGameCharacter* Character) const
|
|
{
|
|
if (!Character || !IsLocationOutsideBoundary(Character->GetActorLocation()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FVector ClampedLocation = ClampLocationToBoundary(Character->GetActorLocation());
|
|
Character->TeleportTo(ClampedLocation, Character->GetActorRotation(), false, true);
|
|
|
|
if (UCharacterMovementComponent* Movement = Character->GetCharacterMovement())
|
|
{
|
|
Movement->StopMovementImmediately();
|
|
}
|
|
}
|