This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

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(true);
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();
}
}