622 lines
22 KiB
C++
622 lines
22 KiB
C++
#include "DismembermentGraph/DismembermentExecutor.h"
|
|
#include "Engine/SkeletalMesh.h"
|
|
#include "Components/SkeletalMeshComponent.h"
|
|
#include "NiagaraSystem.h"
|
|
#include "NiagaraComponent.h"
|
|
#include "NiagaraFunctionLibrary.h"
|
|
#include "Components/DecalComponent.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "PhysicalMaterials/PhysicalMaterial.h"
|
|
|
|
UDismembermentExecutor::UDismembermentExecutor()
|
|
{
|
|
// Initialize default values
|
|
Compiler = nullptr;
|
|
TargetActor = nullptr;
|
|
TargetSkeletalMesh = nullptr;
|
|
|
|
// Create boolean cut tool
|
|
CutTool = CreateDefaultSubobject<UBooleanCutTool>(TEXT("CutTool"));
|
|
}
|
|
|
|
void UDismembermentExecutor::Initialize(UDismembermentCompiler* InCompiler)
|
|
{
|
|
// Set compiler reference
|
|
Compiler = InCompiler;
|
|
}
|
|
|
|
bool UDismembermentExecutor::Execute(AActor* InTargetActor)
|
|
{
|
|
// Set target actor
|
|
TargetActor = InTargetActor;
|
|
|
|
// Find skeletal mesh component
|
|
if (!FindTargetSkeletalMesh())
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot execute dismemberment graph, skeletal mesh component not found"));
|
|
return false;
|
|
}
|
|
|
|
// Check if compiler is valid
|
|
if (!Compiler)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot execute dismemberment graph, invalid compiler"));
|
|
return false;
|
|
}
|
|
|
|
// Get execution order from compiler
|
|
TArray<int32> ExecutionOrder;
|
|
if (!Compiler->GetExecutionOrder(ExecutionOrder))
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot execute dismemberment graph, invalid execution order"));
|
|
return false;
|
|
}
|
|
|
|
// Clear selected bones
|
|
SelectedBones.Empty();
|
|
|
|
// Execute nodes in order
|
|
bool bSuccess = true;
|
|
for (int32 NodeIndex : ExecutionOrder)
|
|
{
|
|
// Execute node
|
|
bool bNodeSuccess = ExecuteNode(NodeIndex);
|
|
|
|
// Log node execution result
|
|
FDismembermentNodeData NodeData;
|
|
if (Compiler->GetNodeData(NodeIndex, NodeData))
|
|
{
|
|
FString NodeName = NodeData.NodeName.ToString();
|
|
if (bNodeSuccess)
|
|
{
|
|
UE_LOG(LogTemp, Display, TEXT("FLESH: Successfully executed node %s"), *NodeName);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Failed to execute node %s"), *NodeName);
|
|
bSuccess = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
bool UDismembermentExecutor::FindTargetSkeletalMesh()
|
|
{
|
|
// Check if target actor is valid
|
|
if (!TargetActor)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get skeletal mesh component
|
|
TargetSkeletalMesh = TargetActor->FindComponentByClass<USkeletalMeshComponent>();
|
|
|
|
return TargetSkeletalMesh != nullptr;
|
|
}
|
|
|
|
void UDismembermentExecutor::AddSelectedBone(const FName& BoneName)
|
|
{
|
|
// Add bone to selection list
|
|
if (!SelectedBones.Contains(BoneName))
|
|
{
|
|
SelectedBones.Add(BoneName);
|
|
}
|
|
}
|
|
|
|
bool UDismembermentExecutor::ApplyCut(const FVector& Location, const FVector& Direction, float Width, float Depth, UMaterialInterface* Material)
|
|
{
|
|
// Check if target skeletal mesh is valid
|
|
if (!TargetSkeletalMesh)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot perform cut, target skeletal mesh is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Check if cut tool is valid
|
|
if (!CutTool)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot perform cut, cutting tool is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Set cut material
|
|
CutTool->SetCutMaterial(Material);
|
|
|
|
// Create cut plane
|
|
FCutPlane CutPlane;
|
|
CutPlane.Location = Location;
|
|
CutPlane.Normal = Direction.GetSafeNormal();
|
|
|
|
// Apply cut to selected bones or entire mesh
|
|
bool bSuccess = false;
|
|
|
|
if (SelectedBones.Num() > 0)
|
|
{
|
|
// Cut only selected bones
|
|
for (const FName& BoneName : SelectedBones)
|
|
{
|
|
// Cut skeletal mesh at the specified bone
|
|
TArray<USkeletalMesh*> CutResults = CutTool->CutSkeletalMesh(
|
|
TargetSkeletalMesh->GetSkeletalMeshAsset(),
|
|
CutPlane,
|
|
BoneName,
|
|
true // Create cap
|
|
);
|
|
|
|
if (CutResults.Num() >= 2)
|
|
{
|
|
// Replace the original skeletal mesh with the first cut result
|
|
TargetSkeletalMesh->SetSkeletalMeshAsset(CutResults[0]);
|
|
|
|
// TODO: Handle the second cut result (detached part)
|
|
// This would involve creating a new actor with the second mesh
|
|
// and applying physics to it
|
|
|
|
bSuccess = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Cut the entire mesh
|
|
TArray<USkeletalMesh*> CutResults = CutTool->CutSkeletalMesh(
|
|
TargetSkeletalMesh->GetSkeletalMeshAsset(),
|
|
CutPlane,
|
|
NAME_None, // No specific bone
|
|
true // Create cap
|
|
);
|
|
|
|
if (CutResults.Num() >= 2)
|
|
{
|
|
// Replace the original skeletal mesh with the first cut result
|
|
TargetSkeletalMesh->SetSkeletalMeshAsset(CutResults[0]);
|
|
|
|
// TODO: Handle the second cut result (detached part)
|
|
// This would involve creating a new actor with the second mesh
|
|
// and applying physics to it
|
|
|
|
bSuccess = true;
|
|
}
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
bool UDismembermentExecutor::SpawnBloodEffect(const FVector& Location, UNiagaraSystem* BloodEffect, float BloodAmount, float BloodPressure, bool CreateBloodPool, float BloodPoolSize, UMaterialInterface* BloodPoolMaterial)
|
|
{
|
|
// Check if target actor is valid
|
|
if (!TargetActor)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot spawn blood effect, target actor is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Check if blood effect is valid
|
|
if (!BloodEffect)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot spawn blood effect, blood particle system is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Get world
|
|
UWorld* World = TargetActor->GetWorld();
|
|
if (!World)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Spawn blood effect
|
|
UNiagaraComponent* BloodComponent = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
|
|
World,
|
|
BloodEffect,
|
|
Location,
|
|
FRotator::ZeroRotator,
|
|
FVector(1.0f, 1.0f, 1.0f),
|
|
true,
|
|
true,
|
|
ENCPoolMethod::AutoRelease,
|
|
true
|
|
);
|
|
|
|
if (!BloodComponent)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot spawn blood effect, failed to create particle system component"));
|
|
return false;
|
|
}
|
|
|
|
// Set blood parameters
|
|
BloodComponent->SetVariableFloat(FName("BloodAmount"), BloodAmount);
|
|
BloodComponent->SetVariableFloat(FName("BloodPressure"), BloodPressure);
|
|
|
|
// Create blood pool if needed
|
|
if (CreateBloodPool && BloodPoolMaterial)
|
|
{
|
|
// Create a decal component for the blood pool
|
|
UDecalComponent* BloodPoolDecal = UGameplayStatics::SpawnDecalAtLocation(
|
|
World,
|
|
BloodPoolMaterial,
|
|
FVector(BloodPoolSize, BloodPoolSize, 10.0f), // Size of the decal
|
|
Location,
|
|
FRotator(-90.0f, 0.0f, 0.0f), // Rotate to face the ground
|
|
10.0f // Lifetime
|
|
);
|
|
|
|
if (BloodPoolDecal)
|
|
{
|
|
// Set fade parameters
|
|
BloodPoolDecal->SetFadeOut(5.0f, 5.0f, false);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool UDismembermentExecutor::ApplyPhysics(float Mass, float LinearDamping, float AngularDamping, bool EnableGravity, bool SimulatePhysics, bool GenerateOverlapEvents, UPhysicalMaterial* PhysicalMaterial, float ImpulseForce, float ImpulseRadius)
|
|
{
|
|
// Check if target skeletal mesh is valid
|
|
if (!TargetSkeletalMesh)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot apply physics, target skeletal mesh is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Apply physics settings to the skeletal mesh component
|
|
TargetSkeletalMesh->SetSimulatePhysics(SimulatePhysics);
|
|
TargetSkeletalMesh->SetEnableGravity(EnableGravity);
|
|
TargetSkeletalMesh->SetGenerateOverlapEvents(GenerateOverlapEvents);
|
|
|
|
// Set mass properties
|
|
if (Mass > 0.0f)
|
|
{
|
|
TargetSkeletalMesh->SetMassOverrideInKg(NAME_None, Mass, true);
|
|
}
|
|
|
|
// Set damping
|
|
TargetSkeletalMesh->SetLinearDamping(LinearDamping);
|
|
TargetSkeletalMesh->SetAngularDamping(AngularDamping);
|
|
|
|
// Set physical material if provided
|
|
if (PhysicalMaterial)
|
|
{
|
|
TargetSkeletalMesh->SetPhysMaterialOverride(PhysicalMaterial);
|
|
}
|
|
|
|
// Apply impulse if force is greater than zero
|
|
if (ImpulseForce > 0.0f)
|
|
{
|
|
// Get the component's location
|
|
FVector ComponentLocation = TargetSkeletalMesh->GetComponentLocation();
|
|
|
|
// Apply radial impulse
|
|
TargetSkeletalMesh->AddRadialImpulse(
|
|
ComponentLocation,
|
|
ImpulseRadius,
|
|
ImpulseForce,
|
|
ERadialImpulseFalloff::RIF_Linear,
|
|
true // Apply impulse to all bodies
|
|
);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool UDismembermentExecutor::SpawnOrgan(UStaticMesh* OrganMesh, UMaterialInterface* OrganMaterial, const FName& AttachBoneName, const FVector& RelativeLocation, const FRotator& RelativeRotation, const FVector& RelativeScale, bool SimulatePhysics, float DamageMultiplier, bool IsCriticalOrgan, float BloodAmount)
|
|
{
|
|
// Check if target actor is valid
|
|
if (!TargetActor)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot spawn organ, target actor is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Check if organ mesh is valid
|
|
if (!OrganMesh)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot spawn organ, organ mesh is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Get world
|
|
UWorld* World = TargetActor->GetWorld();
|
|
if (!World)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Create a static mesh component for the organ
|
|
UStaticMeshComponent* OrganComponent = NewObject<UStaticMeshComponent>(TargetActor, TEXT("PreviewOrganComponent"));
|
|
if (!OrganComponent)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot spawn organ, failed to create static mesh component"));
|
|
return false;
|
|
}
|
|
|
|
// Register the component
|
|
OrganComponent->RegisterComponent();
|
|
|
|
// Set the mesh and material
|
|
OrganComponent->SetStaticMesh(OrganMesh);
|
|
|
|
if (OrganMaterial)
|
|
{
|
|
OrganComponent->SetMaterial(0, OrganMaterial);
|
|
}
|
|
|
|
// Set transform
|
|
if (TargetSkeletalMesh && !AttachBoneName.IsNone())
|
|
{
|
|
// Attach to bone if specified
|
|
OrganComponent->AttachToComponent(
|
|
TargetSkeletalMesh,
|
|
FAttachmentTransformRules::KeepRelativeTransform,
|
|
AttachBoneName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// Attach to actor root
|
|
OrganComponent->AttachToComponent(
|
|
TargetActor->GetRootComponent(),
|
|
FAttachmentTransformRules::KeepRelativeTransform
|
|
);
|
|
}
|
|
|
|
// Set relative transform
|
|
OrganComponent->SetRelativeLocation(RelativeLocation);
|
|
OrganComponent->SetRelativeRotation(RelativeRotation);
|
|
OrganComponent->SetRelativeScale3D(RelativeScale);
|
|
|
|
// Apply physics if needed
|
|
if (SimulatePhysics)
|
|
{
|
|
OrganComponent->SetSimulatePhysics(true);
|
|
OrganComponent->SetEnableGravity(true);
|
|
OrganComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
|
|
|
// Add a tag to identify this as an organ
|
|
OrganComponent->ComponentTags.Add(FName("Organ"));
|
|
|
|
// Add custom tags for organ properties
|
|
if (IsCriticalOrgan)
|
|
{
|
|
OrganComponent->ComponentTags.Add(FName("CriticalOrgan"));
|
|
}
|
|
|
|
// Store damage multiplier as a custom float
|
|
OrganComponent->SetCustomPrimitiveDataFloat(0, DamageMultiplier);
|
|
OrganComponent->SetCustomPrimitiveDataFloat(1, BloodAmount);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool UDismembermentExecutor::ApplyWoundEffect(float WoundSize, float WoundDepth, UMaterialInterface* WoundMaterial, UNiagaraSystem* WoundEffect, bool CreateDecal, UMaterialInterface* DecalMaterial, float DecalSize, float DecalLifetime, bool AffectBoneHealth, float BoneDamage)
|
|
{
|
|
// Check if target actor is valid
|
|
if (!TargetActor)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot apply wound effect, target actor is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Get world
|
|
UWorld* World = TargetActor->GetWorld();
|
|
if (!World)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Get the location from the selected bone or actor location
|
|
FVector WoundLocation;
|
|
FRotator WoundRotation;
|
|
|
|
if (TargetSkeletalMesh && SelectedBones.Num() > 0)
|
|
{
|
|
// Use the first selected bone's location
|
|
WoundLocation = TargetSkeletalMesh->GetBoneLocation(SelectedBones[0]);
|
|
WoundRotation = TargetSkeletalMesh->GetBoneQuaternion(SelectedBones[0]).Rotator();
|
|
}
|
|
else if (TargetSkeletalMesh)
|
|
{
|
|
// Use the skeletal mesh component's location
|
|
WoundLocation = TargetSkeletalMesh->GetComponentLocation();
|
|
WoundRotation = TargetSkeletalMesh->GetComponentRotation();
|
|
}
|
|
else
|
|
{
|
|
// Use the actor's location
|
|
WoundLocation = TargetActor->GetActorLocation();
|
|
WoundRotation = TargetActor->GetActorRotation();
|
|
}
|
|
|
|
// Spawn wound effect if provided
|
|
if (WoundEffect)
|
|
{
|
|
UNiagaraComponent* WoundEffectComponent = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
|
|
World,
|
|
WoundEffect,
|
|
WoundLocation,
|
|
WoundRotation,
|
|
FVector(WoundSize, WoundSize, WoundSize),
|
|
true,
|
|
true,
|
|
ENCPoolMethod::AutoRelease,
|
|
true
|
|
);
|
|
|
|
if (WoundEffectComponent)
|
|
{
|
|
// Set wound parameters
|
|
WoundEffectComponent->SetVariableFloat(FName("WoundSize"), WoundSize);
|
|
WoundEffectComponent->SetVariableFloat(FName("WoundDepth"), WoundDepth);
|
|
}
|
|
}
|
|
|
|
// Create decal if needed
|
|
if (CreateDecal && DecalMaterial)
|
|
{
|
|
// Create a decal component for the wound
|
|
UDecalComponent* WoundDecal = UGameplayStatics::SpawnDecalAttached(
|
|
DecalMaterial,
|
|
FVector(DecalSize, DecalSize, DecalSize),
|
|
TargetSkeletalMesh ? TargetSkeletalMesh : TargetActor->GetRootComponent(),
|
|
NAME_None,
|
|
WoundLocation,
|
|
WoundRotation,
|
|
EAttachLocation::KeepWorldPosition,
|
|
DecalLifetime
|
|
);
|
|
|
|
if (WoundDecal)
|
|
{
|
|
// Set fade parameters
|
|
WoundDecal->SetFadeOut(DecalLifetime * 0.8f, DecalLifetime * 0.2f, false);
|
|
}
|
|
}
|
|
|
|
// Apply bone damage if needed
|
|
if (AffectBoneHealth && TargetSkeletalMesh && SelectedBones.Num() > 0)
|
|
{
|
|
// This would typically involve a custom bone health system
|
|
// For now, we'll just log that bone damage was applied
|
|
for (const FName& BoneName : SelectedBones)
|
|
{
|
|
UE_LOG(LogTemp, Display, TEXT("FLESH: Applied %.2f damage to bone %s"), BoneDamage, *BoneName.ToString());
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool UDismembermentExecutor::ExecuteNode(int32 NodeIndex)
|
|
{
|
|
// Check if compiler is valid
|
|
if (!Compiler)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot execute node, compiler is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Get node data from compiler
|
|
FDismembermentNodeData NodeData;
|
|
if (!Compiler->GetNodeData(NodeIndex, NodeData))
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Cannot execute node, node data is invalid"));
|
|
return false;
|
|
}
|
|
|
|
// Execute node based on its type
|
|
bool bSuccess = false;
|
|
|
|
switch (NodeData.NodeType)
|
|
{
|
|
case EDismembermentNodeType::Cut:
|
|
{
|
|
// Get cut parameters
|
|
FVector Location = NodeData.GetVectorParameter("Location", FVector::ZeroVector);
|
|
FVector Direction = NodeData.GetVectorParameter("Direction", FVector::UpVector);
|
|
float Width = NodeData.GetFloatParameter("Width", 1.0f);
|
|
float Depth = NodeData.GetFloatParameter("Depth", 10.0f);
|
|
UMaterialInterface* Material = Cast<UMaterialInterface>(NodeData.GetObjectParameter("Material"));
|
|
|
|
// Apply cut
|
|
bSuccess = ApplyCut(Location, Direction, Width, Depth, Material);
|
|
break;
|
|
}
|
|
|
|
case EDismembermentNodeType::BloodEffect:
|
|
{
|
|
// Get blood effect parameters
|
|
FVector Location = NodeData.GetVectorParameter("Location", FVector::ZeroVector);
|
|
UNiagaraSystem* BloodEffect = Cast<UNiagaraSystem>(NodeData.GetObjectParameter("BloodEffect"));
|
|
float BloodAmount = NodeData.GetFloatParameter("BloodAmount", 1.0f);
|
|
float BloodPressure = NodeData.GetFloatParameter("BloodPressure", 1.0f);
|
|
bool CreateBloodPool = NodeData.GetBoolParameter("CreateBloodPool", true);
|
|
float BloodPoolSize = NodeData.GetFloatParameter("BloodPoolSize", 100.0f);
|
|
UMaterialInterface* BloodPoolMaterial = Cast<UMaterialInterface>(NodeData.GetObjectParameter("BloodPoolMaterial"));
|
|
|
|
// Spawn blood effect
|
|
bSuccess = SpawnBloodEffect(Location, BloodEffect, BloodAmount, BloodPressure, CreateBloodPool, BloodPoolSize, BloodPoolMaterial);
|
|
break;
|
|
}
|
|
|
|
case EDismembermentNodeType::Physics:
|
|
{
|
|
// Get physics parameters
|
|
float Mass = NodeData.GetFloatParameter("Mass", 10.0f);
|
|
float LinearDamping = NodeData.GetFloatParameter("LinearDamping", 0.01f);
|
|
float AngularDamping = NodeData.GetFloatParameter("AngularDamping", 0.01f);
|
|
bool EnableGravity = NodeData.GetBoolParameter("EnableGravity", true);
|
|
bool SimulatePhysics = NodeData.GetBoolParameter("SimulatePhysics", true);
|
|
bool GenerateOverlapEvents = NodeData.GetBoolParameter("GenerateOverlapEvents", true);
|
|
UPhysicalMaterial* PhysicalMaterial = Cast<UPhysicalMaterial>(NodeData.GetObjectParameter("PhysicalMaterial"));
|
|
float ImpulseForce = NodeData.GetFloatParameter("ImpulseForce", 1000.0f);
|
|
float ImpulseRadius = NodeData.GetFloatParameter("ImpulseRadius", 100.0f);
|
|
|
|
// Apply physics
|
|
bSuccess = ApplyPhysics(Mass, LinearDamping, AngularDamping, EnableGravity, SimulatePhysics, GenerateOverlapEvents, PhysicalMaterial, ImpulseForce, ImpulseRadius);
|
|
break;
|
|
}
|
|
|
|
case EDismembermentNodeType::Organ:
|
|
{
|
|
// Get organ parameters
|
|
UStaticMesh* OrganMesh = Cast<UStaticMesh>(NodeData.GetObjectParameter("OrganMesh"));
|
|
UMaterialInterface* OrganMaterial = Cast<UMaterialInterface>(NodeData.GetObjectParameter("OrganMaterial"));
|
|
FName AttachBoneName = NodeData.GetNameParameter("AttachBoneName", NAME_None);
|
|
FVector RelativeLocation = NodeData.GetVectorParameter("RelativeLocation", FVector::ZeroVector);
|
|
FRotator RelativeRotation = NodeData.GetRotatorParameter("RelativeRotation", FRotator::ZeroRotator);
|
|
FVector RelativeScale = NodeData.GetVectorParameter("RelativeScale", FVector::OneVector);
|
|
bool SimulatePhysics = NodeData.GetBoolParameter("SimulatePhysics", true);
|
|
float DamageMultiplier = NodeData.GetFloatParameter("DamageMultiplier", 1.0f);
|
|
bool IsCriticalOrgan = NodeData.GetBoolParameter("IsCriticalOrgan", false);
|
|
float BloodAmount = NodeData.GetFloatParameter("BloodAmount", 1.0f);
|
|
|
|
// Spawn organ
|
|
bSuccess = SpawnOrgan(OrganMesh, OrganMaterial, AttachBoneName, RelativeLocation, RelativeRotation, RelativeScale, SimulatePhysics, DamageMultiplier, IsCriticalOrgan, BloodAmount);
|
|
break;
|
|
}
|
|
|
|
case EDismembermentNodeType::Wound:
|
|
{
|
|
// Get wound parameters
|
|
float WoundSize = NodeData.GetFloatParameter("WoundSize", 10.0f);
|
|
float WoundDepth = NodeData.GetFloatParameter("WoundDepth", 5.0f);
|
|
UMaterialInterface* WoundMaterial = Cast<UMaterialInterface>(NodeData.GetObjectParameter("WoundMaterial"));
|
|
UNiagaraSystem* WoundEffect = Cast<UNiagaraSystem>(NodeData.GetObjectParameter("WoundEffect"));
|
|
bool CreateDecal = NodeData.GetBoolParameter("CreateDecal", true);
|
|
UMaterialInterface* DecalMaterial = Cast<UMaterialInterface>(NodeData.GetObjectParameter("DecalMaterial"));
|
|
float DecalSize = NodeData.GetFloatParameter("DecalSize", 50.0f);
|
|
float DecalLifetime = NodeData.GetFloatParameter("DecalLifetime", 10.0f);
|
|
bool AffectBoneHealth = NodeData.GetBoolParameter("AffectBoneHealth", false);
|
|
float BoneDamage = NodeData.GetFloatParameter("BoneDamage", 10.0f);
|
|
|
|
// Apply wound effect
|
|
bSuccess = ApplyWoundEffect(WoundSize, WoundDepth, WoundMaterial, WoundEffect, CreateDecal, DecalMaterial, DecalSize, DecalLifetime, AffectBoneHealth, BoneDamage);
|
|
break;
|
|
}
|
|
|
|
case EDismembermentNodeType::BoneSelection:
|
|
{
|
|
// Get bone selection parameters
|
|
FName BoneName = NodeData.GetNameParameter("BoneName", NAME_None);
|
|
|
|
// Add bone to selection
|
|
if (!BoneName.IsNone())
|
|
{
|
|
AddSelectedBone(BoneName);
|
|
bSuccess = true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
UE_LOG(LogTemp, Warning, TEXT("FLESH: Unknown node type"));
|
|
break;
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|