Add Ground Zero map boundary
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright Pacificao. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "AgrarianMapBoundaryVolume.generated.h"
|
||||
|
||||
class AAgrarianGameCharacter;
|
||||
class UBoxComponent;
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AGRARIANGAME_API AAgrarianMapBoundaryVolume : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AAgrarianMapBoundaryVolume();
|
||||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Map Boundary")
|
||||
TObjectPtr<UBoxComponent> BoundaryVolume;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Map Boundary")
|
||||
FName BoundaryId = TEXT("ground_zero_mvp_tile");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Map Boundary")
|
||||
bool bClampPlayersAtBoundary = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Map Boundary", meta = (ClampMin = "0"))
|
||||
float BoundaryPaddingCm = 250.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Map Boundary", meta = (ClampMin = "0"))
|
||||
float WarningDistanceCm = 3000.0f;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Map Boundary")
|
||||
bool IsLocationOutsideBoundary(const FVector& WorldLocation) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Map Boundary")
|
||||
bool IsLocationInsideWarningZone(const FVector& WorldLocation) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Map Boundary")
|
||||
FVector ClampLocationToBoundary(const FVector& WorldLocation) const;
|
||||
|
||||
protected:
|
||||
void EnforceBoundaryForCharacter(AAgrarianGameCharacter* Character) const;
|
||||
};
|
||||
Reference in New Issue
Block a user