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
AgrarianGameArchive/Source/AgrarianGame/AgrarianShelterActor.cpp
T

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