1
0
KF2-Dev-Scripts/Engine/Classes/Emitter.uc
2020-12-13 18:01:13 +03:00

352 lines
9.5 KiB
Ucode

//=============================================================================
// Emitter actor class.
// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
//=============================================================================
class Emitter extends Actor
native
placeable;
var() editconst const ParticleSystemComponent ParticleSystemComponent;
var() editconst const DynamicLightEnvironmentComponent LightEnvironment;
var bool bDestroyOnSystemFinish;
var() bool bPostUpdateTickGroup;
/** used to update status of toggleable level placed emitters on clients */
var repnotify bool bCurrentlyActive;
`if(`__TW_)
/** Allows particle emitters to omit depth testing (by setting to false) */
var transient bool bDepthTestEnabled;
/** Allow this emitter to be rendered in the depth pass and be used as an occluder */
var(Rendering) const bool bUseAsOccluder;
`endif
struct CheckpointRecord
{
var bool bIsActive;
};
replication
{
if (bNoDelete)
bCurrentlyActive;
}
cpptext
{
void SetTemplate(UParticleSystem* NewTemplate, UBOOL bDestroyOnFinish=false);
void AutoPopulateInstanceProperties();
// AActor interface.
virtual void Spawned();
virtual void PostBeginPlay();
/**
* ticks the actor
* @param DeltaTime The time slice of this tick
* @param TickType The type of tick that is happening
*
* @return TRUE if the actor was ticked, FALSE if it was aborted (e.g. because it's in stasis)
*/
virtual UBOOL Tick( FLOAT DeltaTime, enum ELevelTick TickType );
/**
* Function that gets called from within Map_Check to allow this actor to check itself
* for any potential errors and register them with map check dialog.
*/
#if WITH_EDITOR
virtual void CheckForErrors();
#endif
#if USE_GAMEPLAY_PROFILER
/**
* This function actually does the work for the GetProfilerAssetObject and is virtual.
* It should only be called from GetProfilerAssetObject as GetProfilerAssetObject is safe to call on NULL object pointers
*/
virtual UObject* GetProfilerAssetObjectInternal() const;
#endif
/**
* This will return detail info about this specific object. (e.g. AudioComponent will return the name of the cue,
* ParticleSystemComponent will return the name of the ParticleSystem) The idea here is that in many places
* you have a component of interest but what you really want is some characteristic that you can use to track
* down where it came from.
*
*/
virtual FString GetDetailedInfoInternal() const;
/**
* Called to reset the emitter actor in the level.
* Intended for use in editor only
*/
void ResetInLevel();
#if __TW_
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent);
#endif
}
native noexport event SetTemplate(ParticleSystem NewTemplate, optional bool bDestroyOnFinish);
simulated event PostBeginPlay()
{
Super.PostBeginPlay();
// Let them die quickly on a dedicated server
if (WorldInfo.NetMode == NM_DedicatedServer && (RemoteRole == ROLE_None || bNetTemporary))
{
LifeSpan = 0.2;
`if(`__TW_PERFORMANCE_)
// Lifespan won't do us much good for NoDelete actors!
if ( bNoDelete )
{
SetTickIsDisabled(true);
}
`endif
}
// Set Notification Delegate
if (ParticleSystemComponent != None)
{
ParticleSystemComponent.OnSystemFinished = OnParticleSystemFinished;
bCurrentlyActive = ParticleSystemComponent.bAutoActivate;
`if(`__TW_)
// Allow certain emitters to be rendered in the depth pass and be used as occluders
ParticleSystemComponent.bUseAsOccluder = bUseAsOccluder;
ReattachComponent(ParticleSystemComponent);
`endif
}
}
simulated event ReplicatedEvent(name VarName)
{
if (VarName == 'bCurrentlyActive')
{
ParticleSystemComponent.SetActive(bCurrentlyActive);
}
else
{
Super.ReplicatedEvent(VarName);
}
}
simulated function OnParticleSystemFinished(ParticleSystemComponent FinishedComponent)
{
if (bDestroyOnSystemFinish)
{
Lifespan = 0.0001f;
}
bCurrentlyActive = false;
}
/**
* Handling Toggle event from Kismet.
*/
function OnToggle(SeqAct_Toggle action)
{
// Turn ON
if (action.InputLinks[0].bHasImpulse)
{
ParticleSystemComponent.ActivateSystem();
bCurrentlyActive = TRUE;
}
// Turn OFF
else if (action.InputLinks[1].bHasImpulse)
{
ParticleSystemComponent.DeactivateSystem();
bCurrentlyActive = FALSE;
}
// Toggle
else if (action.InputLinks[2].bHasImpulse)
{
// If spawning is suppressed or we aren't turned on at all, activate.
if (ParticleSystemComponent.bSuppressSpawning || !bCurrentlyActive)
{
ParticleSystemComponent.ActivateSystem();
bCurrentlyActive = TRUE;
}
else
{
ParticleSystemComponent.DeactivateSystem();
bCurrentlyActive = FALSE;
}
}
ParticleSystemComponent.LastRenderTime = WorldInfo.TimeSeconds;
ForceNetRelevant();
if (RemoteRole != ROLE_None)
{
// force replicate flag if necessary
SetForcedInitialReplicatedProperty(Property'Engine.Emitter.bCurrentlyActive', (bCurrentlyActive == default.bCurrentlyActive));
}
}
/**
* Handling ParticleEventGenerator event from Kismet.
* - Does nothing... just here to stop Kismet from complaining
*/
function OnParticleEventGenerator(SeqAct_ParticleEventGenerator action)
{
}
simulated function ShutDown()
{
Super.ShutDown();
bCurrentlyActive = false;
}
simulated function SetFloatParameter(name ParameterName, float Param)
{
if (ParticleSystemComponent != none)
ParticleSystemComponent.SetFloatParameter(ParameterName, Param);
else
`log("Warning: Attempting to set a parameter on "$self$" when the PSC does not exist");
}
simulated function SetVectorParameter(name ParameterName, vector Param)
{
if (ParticleSystemComponent != none)
ParticleSystemComponent.SetVectorParameter(ParameterName, Param);
else
`log("Warning: Attempting to set a parameter on "$self$" when the PSC does not exist");
}
simulated function SetColorParameter(name ParameterName, color Param)
{
if (ParticleSystemComponent != none)
ParticleSystemComponent.SetColorParameter(ParameterName, Param);
else
`log("Warning: Attempting to set a parameter on "$self$" when the PSC does not exist");
}
simulated function SetExtColorParameter(name ParameterName, byte Red, byte Green, byte Blue, byte Alpha)
{
local color c;
if (ParticleSystemComponent != none)
{
c.r = Red;
c.g = Green;
c.b = Blue;
c.a = Alpha;
ParticleSystemComponent.SetColorParameter(ParameterName, C);
}
else
`log("Warning: Attempting to set a parameter on "$self$" when the PSC does not exist");
}
simulated function SetActorParameter(name ParameterName, actor Param)
{
if (ParticleSystemComponent != none)
ParticleSystemComponent.SetActorParameter(ParameterName, Param);
else
`log("Warning: Attempting to set a parameter on "$self$" when the PSC does not exist");
}
/**
* Kismet handler for setting particle instance parameters.
*/
simulated function OnSetParticleSysParam(SeqAct_SetParticleSysParam Action)
{
local int Idx, ParamIdx;
if (ParticleSystemComponent != None &&
Action.InstanceParameters.Length > 0)
{
for (Idx = 0; Idx < Action.InstanceParameters.Length; Idx++)
{
if (Action.InstanceParameters[Idx].ParamType != PSPT_None)
{
// look for an existing entry
ParamIdx = ParticleSystemComponent.InstanceParameters.Find('Name',Action.InstanceParameters[Idx].Name);
// create one if necessary
if (ParamIdx == -1)
{
ParamIdx = ParticleSystemComponent.InstanceParameters.Length;
ParticleSystemComponent.InstanceParameters.Length = ParamIdx + 1;
}
// update the instance parm
ParticleSystemComponent.InstanceParameters[ParamIdx] = Action.InstanceParameters[Idx];
if (Action.bOverrideScalar)
{
ParticleSystemComponent.InstanceParameters[ParamIdx].Scalar = Action.ScalarValue;
}
}
}
}
}
function bool ShouldSaveForCheckpoint()
{
return (bNoDelete && RemoteRole != ROLE_None);
}
function CreateCheckpointRecord(out CheckpointRecord Record)
{
Record.bIsActive = bCurrentlyActive;
}
function ApplyCheckpointRecord(const out CheckpointRecord Record)
{
bCurrentlyActive = Record.bIsActive;
if (bCurrentlyActive)
{
ParticleSystemComponent.ActivateSystem();
}
else
{
ParticleSystemComponent.DeactivateSystem();
}
ForceNetRelevant();
}
/** Function used to have the emitter hide itself and put itself into stasis **/
simulated function HideSelf();
defaultproperties
{
// Visual things should be ticked in parallel with physics
TickGroup=TG_DuringAsyncWork
Begin Object Class=SpriteComponent Name=Sprite
Sprite=Texture2D'EditorResources.S_Emitter'
HiddenGame=True
AlwaysLoadOnClient=False
AlwaysLoadOnServer=False
bIsScreenSizeScaled=True
ScreenSize=0.0025
SpriteCategoryName="Effects"
End Object
Components.Add(Sprite)
Begin Object Class=ParticleSystemComponent Name=ParticleSystemComponent0
SecondsBeforeInactive=1
End Object
ParticleSystemComponent=ParticleSystemComponent0
Components.Add(ParticleSystemComponent0)
Begin Object Class=ArrowComponent Name=ArrowComponent0
ArrowColor=(R=0,G=255,B=128)
ArrowSize=1.5
AlwaysLoadOnClient=False
AlwaysLoadOnServer=False
bTreatAsASprite=True
SpriteCategoryName="Effects"
End Object
Components.Add(ArrowComponent0)
bEdShouldSnap=true
bHardAttach=true
bGameRelevant=true
bNoDelete=true
`if(`__TW_)
bDepthTestEnabled=true
`endif
SupportedEvents.Add(class'SeqEvent_ParticleEvent')
}