173 lines
4.9 KiB
Ucode
173 lines
4.9 KiB
Ucode
|
/**
|
||
|
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
|
||
|
*/
|
||
|
class FractureManager extends Actor
|
||
|
native(Mesh)
|
||
|
config(Game);
|
||
|
|
||
|
/* Number of FSM parts in the pool */
|
||
|
var int FSMPartPoolSize;
|
||
|
|
||
|
/** If TRUE, look for vibrating FSM parts and kill them */
|
||
|
var() bool bEnableAntiVibration;
|
||
|
/** How much vibration (defined as changes in angular velocity direction) must occur before part is killed. */
|
||
|
var() float DestroyVibrationLevel;
|
||
|
/** Min angular velocity of part to be killed by vibration detection code. */
|
||
|
var() float DestroyMinAngVel;
|
||
|
|
||
|
/** If TRUE, spawn effect for chunks falling off when doing radial damage (ie removing many chunks at once)*/
|
||
|
var() bool bEnableSpawnChunkEffectForRadialDamage;
|
||
|
|
||
|
/** */
|
||
|
var() float ExplosionVelScale;
|
||
|
|
||
|
/*
|
||
|
* Time after spawning a part during which the part is guaranteed to not be recycled again.
|
||
|
* Used to avoid redundant work when spawning a lot of parts relative to the pool size.
|
||
|
*/
|
||
|
const FSM_DEFAULTRECYCLETIME = 0.2;
|
||
|
|
||
|
var array<FracturedStaticMeshPart> PartPool;
|
||
|
var array<int> FreeParts;
|
||
|
|
||
|
/** List of actors that have fracture parts that have been deferred to spawn on upcoming frames */
|
||
|
var transient array< FracturedStaticMeshActor > ActorsWithDeferredPartsToSpawn;
|
||
|
|
||
|
/** Function use to spawn particle effect when a chunk is destroyed. */
|
||
|
`if(`__TW_LIGHTING_MODIFICATIONS_)
|
||
|
simulated event SpawnChunkDestroyEffect(ParticleSystem Effect, box ChunkBox, vector ChunkDir, float Scale, const FracturedStaticMeshComponent MeshComp)
|
||
|
`else
|
||
|
simulated event SpawnChunkDestroyEffect(ParticleSystem Effect, box ChunkBox, vector ChunkDir, float Scale)
|
||
|
`endif
|
||
|
{
|
||
|
local vector ChunkMiddle;
|
||
|
local ParticleSystemComponent EffectComp;
|
||
|
|
||
|
`if(`__TW_PERFORMANCE_)
|
||
|
if( WorldInfo.bDropDetail )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
`endif
|
||
|
|
||
|
ChunkMiddle = 0.5 * (ChunkBox.Min + ChunkBox.Max);
|
||
|
EffectComp = WorldInfo.MyEmitterPool.SpawnEmitter(Effect, ChunkMiddle, rotator(ChunkDir));
|
||
|
EffectComp.SetScale(Scale);
|
||
|
|
||
|
`if(`__TW_LIGHTING_MODIFICATIONS_)
|
||
|
if ( MeshComp != None )
|
||
|
{
|
||
|
EffectComp.SetLightingChannels(MeshComp.LightingChannels);
|
||
|
}
|
||
|
`endif
|
||
|
}
|
||
|
|
||
|
native function float GetNumFSMPartsScale();
|
||
|
|
||
|
/** Returns a scalar to the percentage chance of a fractured static mesh spawning a rigid body after
|
||
|
taking direct damage */
|
||
|
native function float GetFSMDirectSpawnChanceScale();
|
||
|
|
||
|
/** Returns a scalar to the percentage chance of a fractured static mesh spawning a rigid body after
|
||
|
taking radial damage, such as from an explosion */
|
||
|
native function float GetFSMRadialSpawnChanceScale();
|
||
|
|
||
|
/** Returns a distance scale for whether a fractured static mesh should actually fracture when damaged */
|
||
|
native function float GetFSMFractureCullDistanceScale();
|
||
|
|
||
|
cpptext
|
||
|
{
|
||
|
virtual void TickSpecial( FLOAT DeltaSeconds );
|
||
|
};
|
||
|
|
||
|
simulated event PreBeginPlay()
|
||
|
{
|
||
|
Super.PreBeginPlay();
|
||
|
|
||
|
CreateFSMParts();
|
||
|
}
|
||
|
|
||
|
simulated event Destroyed()
|
||
|
{
|
||
|
Super.Destroyed();
|
||
|
|
||
|
CleanUpFSMParts();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
simulated final function CleanUpFSMParts()
|
||
|
{
|
||
|
local int Idx;
|
||
|
|
||
|
for( Idx=0; Idx<PartPool.length; Idx++ )
|
||
|
{
|
||
|
PartPool[Idx].Destroy();
|
||
|
PartPool[Idx] = None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** */
|
||
|
native function CreateFSMParts();
|
||
|
|
||
|
/** Recycles any active parts */
|
||
|
simulated native function ResetPoolVisibility();
|
||
|
|
||
|
/** Grab a FSMP from the free pool, or forcibly recycle a suitable one from the world. */
|
||
|
native function FracturedStaticMeshPart GetFSMPart(FracturedStaticMeshActor Parent, Vector SpawnLocation, Rotator SpawnRotation);
|
||
|
|
||
|
/** Function to actually spawn a FSMP. Allows game-specific pooling/capping of actors. */
|
||
|
simulated event FracturedStaticMeshPart SpawnPartActor(FracturedStaticMeshActor Parent, vector SpawnLocation, rotator SpawnRotation)
|
||
|
{
|
||
|
local FracturedStaticMeshPart NewPart;
|
||
|
|
||
|
//get a new part from the pool
|
||
|
NewPart = GetFSMPart(Parent, SpawnLocation, SpawnRotation);
|
||
|
|
||
|
if (NewPart != None)
|
||
|
{
|
||
|
NewPart.SetTimer( 10.f, FALSE, nameof(NewPart.TryToCleanUp) );
|
||
|
}
|
||
|
|
||
|
return NewPart;
|
||
|
}
|
||
|
|
||
|
/** Return a part to the pool. */
|
||
|
simulated event ReturnPartActor(FracturedStaticMeshPart Part)
|
||
|
{
|
||
|
FreeParts.AddItem(Part.PartPoolIndex);
|
||
|
}
|
||
|
|
||
|
/** Called every frame to update the object */
|
||
|
simulated function Tick( float DeltaTime )
|
||
|
{
|
||
|
local int CurActorIndex;
|
||
|
|
||
|
// Call parent implementation skipped because no implementation in Actor
|
||
|
//super.Tick( DeltaTime );
|
||
|
|
||
|
// Give any actors with deferred chunks a chance to spawn now
|
||
|
if( ActorsWithDeferredPartsToSpawn.length > 0 )
|
||
|
{
|
||
|
for( CurActorIndex = 0; CurActorIndex < ActorsWithDeferredPartsToSpawn.length; ++CurActorIndex )
|
||
|
{
|
||
|
if( ActorsWithDeferredPartsToSpawn[ CurActorIndex ].SpawnDeferredParts() )
|
||
|
{
|
||
|
// No chunks left to spawn, so we can remove it from our list
|
||
|
ActorsWithDeferredPartsToSpawn.remove( CurActorIndex, 1 );
|
||
|
--CurActorIndex;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
defaultproperties
|
||
|
{
|
||
|
FSMPartPoolSize=50
|
||
|
|
||
|
bEnableAntiVibration=FALSE
|
||
|
DestroyVibrationLevel=3.0
|
||
|
DestroyMinAngVel=2.5
|
||
|
ExplosionVelScale=1.0
|
||
|
}
|