添加 Source/FLESH/Private/Gore/BloodPool.cpp

This commit is contained in:
2025-04-18 18:07:18 +08:00
parent be5af35c9c
commit cfc784f4f4

View File

@@ -0,0 +1,155 @@
// @ 2025, Copyright Virtuos Games. All rights reserved.
#include "Gore/BloodPool.h"
#include "Components/BoxComponent.h"
#include "Components/DecalComponent.h"
#include "UObject/ConstructorHelpers.h"
#include "Materials/MaterialInterface.h"
#include "NiagaraComponent.h"
#include "NiagaraFunctionLibrary.h"
// Sets default values
ABloodPool::ABloodPool()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false;
// Create root component
USceneComponent* Root = CreateDefaultSubobject<USceneComponent>("Root");
SetRootComponent(Root);
// Create decal component
Decal = CreateDefaultSubobject<UDecalComponent>("Decal");
Decal->SetupAttachment(Root);
Decal->DecalSize = FVector(100);
Decal->SetRelativeRotation(FRotator(-90,0,0));
Decal->SetFadeIn(-0.2f, 0.3f);
// Try to load default decal material if not set
if(!DecalMaterial)
{
static ConstructorHelpers::FObjectFinder<UMaterialInterface> DefaultDecalMaterial(TEXT("/Game/FLESH/Gore/Textures/M_Decal_BloodPool"));
if(DefaultDecalMaterial.Succeeded())
{
DecalMaterial = DefaultDecalMaterial.Object;
}
}
// Try to load default Niagara system if not set
static ConstructorHelpers::FObjectFinder<UNiagaraSystem> DefaultNiagaraSystem(TEXT("/Game/FLESH/Gore/Niagara/NS_DIS_BloodBurst"));
if(DefaultNiagaraSystem.Succeeded())
{
BloodBurstSystem = DefaultNiagaraSystem.Object;
}
// Create Niagara component for blood burst effect
BloodBurstEffect = CreateDefaultSubobject<UNiagaraComponent>("BloodBurstEffect");
BloodBurstEffect->SetupAttachment(Root);
BloodBurstEffect->bAutoActivate = false;
// Create collision component
Collision = CreateDefaultSubobject<UBoxComponent>("Collision");
Collision->SetupAttachment(Root);
Collision->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
Collision->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
Collision->InitBoxExtent(FVector(100));
// Set up collision response for specific channel
Collision->SetCollisionResponseToChannel(ECC_GameTraceChannel4, ECR_Overlap);
}
void ABloodPool::BeginPlay()
{
Super::BeginPlay();
// Load default decal material if not set
if(!DecalMaterial)
{
DecalMaterial = LoadObject<UMaterialInterface>(nullptr, TEXT("/Game/FLESH/Gore/Textures/M_Decal_BloodPool"));
}
// Load default Niagara system if not set
if(!BloodBurstSystem)
{
BloodBurstSystem = LoadObject<UNiagaraSystem>(nullptr, TEXT("/Game/FLESH/Gore/Niagara/NS_DIS_BloodBurst"));
}
// Set up decal properties
Decal->SetFadeIn(StartDelay, InterpTime);
Decal->SetRelativeScale3D(RemapSizeForDecal(DecalSize));
Decal->SetDecalMaterial(DecalMaterial);
Decal->SetRelativeRotation(DecalRotation);
Decal->AddRelativeRotation(FRotator(-90, FMath::FRandRange(-10.f, 10.f), 0));
Decal->SetFadeOut(MaxLifetime / 5, MaxLifetime, false);
// Set up collision properties
Collision->SetRelativeRotation(DecalRotation);
Collision->SetRelativeScale3D(DecalSize);
// Activate blood burst effect
if(BloodBurstSystem && BloodBurstEffect)
{
BloodBurstEffect->SetAsset(BloodBurstSystem);
BloodBurstEffect->Activate(true);
}
}
FVector ABloodPool::RemapSizeForDecal(const FVector In) const
{
FVector Out;
Out.X = In.Z;
Out.Y = In.Y;
Out.Z = In.X;
return Out;
}
ABloodPool* ABloodPool::CreateBloodPool(UWorld* World, const FVector& Location, float Scale, TSubclassOf<ABloodPool> BloodPoolTemplate)
{
if (!World)
{
return nullptr;
}
// Use default blood pool template (if not provided)
TSubclassOf<ABloodPool> PoolTemplate = BloodPoolTemplate;
if (!PoolTemplate)
{
// Use ABloodPool class as default
PoolTemplate = ABloodPool::StaticClass();
}
if (PoolTemplate)
{
// Trace downward to find the ground
FHitResult HitResult;
FCollisionQueryParams QueryParams;
QueryParams.bTraceComplex = false;
if (World->LineTraceSingleByChannel(
HitResult,
Location,
Location - FVector(0, 0, 500),
ECC_Visibility,
QueryParams
))
{
FVector PoolLocation = HitResult.Location + FVector(0, 0, 1); // Slightly above the ground
// Spawn blood pool
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
ABloodPool* BloodPool = World->SpawnActor<ABloodPool>(PoolTemplate, PoolLocation, FRotator::ZeroRotator, SpawnParams);
// Apply scale
if (BloodPool)
{
BloodPool->SetActorScale3D(FVector(Scale));
return BloodPool;
}
}
}
return nullptr;
}