217 lines
8.4 KiB
C++
217 lines
8.4 KiB
C++
// Copyright Pacificao. All Rights Reserved.
|
|
|
|
#include "AgrarianShelterActor.h"
|
|
#include "AgrarianPersistentActorComponent.h"
|
|
#include "Components/BoxComponent.h"
|
|
#include "Components/StaticMeshComponent.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "Materials/MaterialInterface.h"
|
|
#include "Net/UnrealNetwork.h"
|
|
#include "UObject/ConstructorHelpers.h"
|
|
|
|
namespace
|
|
{
|
|
void ConfigureShelterProxyComponent(UStaticMeshComponent* Component, UStaticMesh* MeshAsset, UMaterialInterface* MaterialAsset)
|
|
{
|
|
if (!Component)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
Component->SetGenerateOverlapEvents(false);
|
|
if (MeshAsset)
|
|
{
|
|
Component->SetStaticMesh(MeshAsset);
|
|
}
|
|
if (MaterialAsset)
|
|
{
|
|
Component->SetMaterial(0, MaterialAsset);
|
|
}
|
|
}
|
|
}
|
|
|
|
AAgrarianShelterActor::AAgrarianShelterActor()
|
|
{
|
|
bReplicates = true;
|
|
NetCullDistanceSquared = FMath::Square(6000.0f);
|
|
|
|
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
|
RootComponent = Mesh;
|
|
Mesh->SetCollisionProfileName(TEXT("BlockAll"));
|
|
|
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cube.SM_AGR_Placeholder_Cube"));
|
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> ChamferCubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_ChamferCube.SM_AGR_Placeholder_ChamferCube"));
|
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
|
|
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WoodMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Wood_Resource.M_AGR_GZ_Wood_Resource"));
|
|
static ConstructorHelpers::FObjectFinder<UMaterialInterface> FiberMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Fiber_Resource.M_AGR_GZ_Fiber_Resource"));
|
|
|
|
if (CubeMesh.Succeeded())
|
|
{
|
|
Mesh->SetStaticMesh(CubeMesh.Object);
|
|
Mesh->SetRelativeScale3D(FVector(3.2f, 2.6f, 0.08f));
|
|
}
|
|
if (WoodMaterial.Succeeded())
|
|
{
|
|
Mesh->SetMaterial(0, WoodMaterial.Object);
|
|
}
|
|
|
|
FloorProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FloorProxy"));
|
|
FloorProxy->SetupAttachment(RootComponent);
|
|
ConfigureShelterProxyComponent(FloorProxy, CubeMesh.Succeeded() ? CubeMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
|
|
FloorProxy->SetRelativeLocation(FVector(0.0f, 0.0f, 10.0f));
|
|
FloorProxy->SetRelativeScale3D(FVector(3.0f, 2.4f, 0.08f));
|
|
|
|
BackWallProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BackWallProxy"));
|
|
BackWallProxy->SetupAttachment(RootComponent);
|
|
ConfigureShelterProxyComponent(BackWallProxy, CubeMesh.Succeeded() ? CubeMesh.Object : nullptr, FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
|
|
BackWallProxy->SetRelativeLocation(FVector(-140.0f, 0.0f, 105.0f));
|
|
BackWallProxy->SetRelativeScale3D(FVector(0.14f, 2.2f, 1.5f));
|
|
|
|
LeftRoofProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LeftRoofProxy"));
|
|
LeftRoofProxy->SetupAttachment(RootComponent);
|
|
ConfigureShelterProxyComponent(LeftRoofProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : (CubeMesh.Succeeded() ? CubeMesh.Object : nullptr), FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
|
|
LeftRoofProxy->SetRelativeLocation(FVector(8.0f, -82.0f, 168.0f));
|
|
LeftRoofProxy->SetRelativeRotation(FRotator(0.0f, 0.0f, -24.0f));
|
|
LeftRoofProxy->SetRelativeScale3D(FVector(3.1f, 0.16f, 1.45f));
|
|
|
|
RightRoofProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RightRoofProxy"));
|
|
RightRoofProxy->SetupAttachment(RootComponent);
|
|
ConfigureShelterProxyComponent(RightRoofProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : (CubeMesh.Succeeded() ? CubeMesh.Object : nullptr), FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
|
|
RightRoofProxy->SetRelativeLocation(FVector(8.0f, 82.0f, 168.0f));
|
|
RightRoofProxy->SetRelativeRotation(FRotator(0.0f, 0.0f, 24.0f));
|
|
RightRoofProxy->SetRelativeScale3D(FVector(3.1f, 0.16f, 1.45f));
|
|
|
|
FrameProxyA = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FrameProxyA"));
|
|
FrameProxyA->SetupAttachment(RootComponent);
|
|
ConfigureShelterProxyComponent(FrameProxyA, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
|
|
FrameProxyA->SetRelativeLocation(FVector(95.0f, -94.0f, 96.0f));
|
|
FrameProxyA->SetRelativeRotation(FRotator(0.0f, 0.0f, -12.0f));
|
|
FrameProxyA->SetRelativeScale3D(FVector(0.12f, 0.12f, 1.92f));
|
|
|
|
FrameProxyB = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FrameProxyB"));
|
|
FrameProxyB->SetupAttachment(RootComponent);
|
|
ConfigureShelterProxyComponent(FrameProxyB, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
|
|
FrameProxyB->SetRelativeLocation(FVector(95.0f, 94.0f, 96.0f));
|
|
FrameProxyB->SetRelativeRotation(FRotator(0.0f, 0.0f, 12.0f));
|
|
FrameProxyB->SetRelativeScale3D(FVector(0.12f, 0.12f, 1.92f));
|
|
|
|
ProtectionVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("ProtectionVolume"));
|
|
ProtectionVolume->SetupAttachment(RootComponent);
|
|
ProtectionVolume->SetBoxExtent(FVector(250.0f, 250.0f, 180.0f));
|
|
ProtectionVolume->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
|
|
|
|
PersistentActorComponent = CreateDefaultSubobject<UAgrarianPersistentActorComponent>(TEXT("PersistentActorComponent"));
|
|
PersistentActorComponent->ActorTypeId = TEXT("primitive_shelter");
|
|
}
|
|
|
|
void AAgrarianShelterActor::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
ClampStructureHealth();
|
|
}
|
|
|
|
float AAgrarianShelterActor::TakeDamage(float DamageAmount, const FDamageEvent& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
|
|
{
|
|
const float PreviousHealth = CurrentStructureHealth;
|
|
ApplyStructureDamage(DamageAmount, DamageCauser);
|
|
return FMath::Max(0.0f, PreviousHealth - CurrentStructureHealth);
|
|
}
|
|
|
|
void AAgrarianShelterActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
|
{
|
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
|
DOREPLIFETIME(AAgrarianShelterActor, MaxStructureHealth);
|
|
DOREPLIFETIME(AAgrarianShelterActor, CurrentStructureHealth);
|
|
}
|
|
|
|
void AAgrarianShelterActor::CapturePersistentState_Implementation(UAgrarianPersistentActorComponent* PersistentComponent) const
|
|
{
|
|
if (!PersistentComponent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PersistentComponent->NumberState.Add(TEXT("max_structure_health"), MaxStructureHealth);
|
|
PersistentComponent->NumberState.Add(TEXT("current_structure_health"), CurrentStructureHealth);
|
|
}
|
|
|
|
void AAgrarianShelterActor::ApplyPersistentState_Implementation(UAgrarianPersistentActorComponent* PersistentComponent)
|
|
{
|
|
if (!HasAuthority() || !PersistentComponent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (const float* SavedMaxHealth = PersistentComponent->NumberState.Find(TEXT("max_structure_health")))
|
|
{
|
|
MaxStructureHealth = FMath::Max(1.0f, *SavedMaxHealth);
|
|
}
|
|
|
|
if (const float* SavedCurrentHealth = PersistentComponent->NumberState.Find(TEXT("current_structure_health")))
|
|
{
|
|
CurrentStructureHealth = *SavedCurrentHealth;
|
|
}
|
|
|
|
ClampStructureHealth();
|
|
}
|
|
|
|
bool AAgrarianShelterActor::ApplyStructureDamage(float DamageAmount, AActor* DamageCauser)
|
|
{
|
|
if (!HasAuthority() || DamageAmount <= 0.0f || CurrentStructureHealth <= 0.0f)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CurrentStructureHealth = FMath::Clamp(CurrentStructureHealth - DamageAmount, 0.0f, MaxStructureHealth);
|
|
if (CurrentStructureHealth <= 0.0f && bDestroyWhenHealthDepleted)
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AAgrarianShelterActor::RepairStructure(float RepairAmount)
|
|
{
|
|
if (!HasAuthority() || RepairAmount <= 0.0f || CurrentStructureHealth >= MaxStructureHealth)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CurrentStructureHealth = FMath::Clamp(CurrentStructureHealth + RepairAmount, 0.0f, MaxStructureHealth);
|
|
return true;
|
|
}
|
|
|
|
bool AAgrarianShelterActor::Deconstruct(AActor* RequestingActor)
|
|
{
|
|
if (!HasAuthority() || !bCanBeDeconstructed)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Destroy();
|
|
return true;
|
|
}
|
|
|
|
float AAgrarianShelterActor::GetStructureHealthRatio() const
|
|
{
|
|
return MaxStructureHealth > 0.0f ? FMath::Clamp(CurrentStructureHealth / MaxStructureHealth, 0.0f, 1.0f) : 0.0f;
|
|
}
|
|
|
|
bool AAgrarianShelterActor::IsStructureDamaged() const
|
|
{
|
|
return CurrentStructureHealth < MaxStructureHealth;
|
|
}
|
|
|
|
void AAgrarianShelterActor::OnRep_StructureHealth()
|
|
{
|
|
ClampStructureHealth();
|
|
}
|
|
|
|
void AAgrarianShelterActor::ClampStructureHealth()
|
|
{
|
|
MaxStructureHealth = FMath::Max(1.0f, MaxStructureHealth);
|
|
CurrentStructureHealth = FMath::Clamp(CurrentStructureHealth, 0.0f, MaxStructureHealth);
|
|
}
|