//============================================================================= // KFMuzzleFlash //============================================================================= // Muzzle flash effects used for 1st and 3rd person //============================================================================= // Killing Floor 2 // Copyright (C) 2015 Tripwire Interactive LLC // - Andrew "Strago" Ladenberger //============================================================================= class KFMuzzleFlash extends Object hidecategories(Object) native(Effect) config(Game); /** Owning Actor used for handling timers */ var transient Actor Owner; /********************************************************************************************* Muzzle Flash Fire Effects ********************************************************************************************* */ struct native MuzzleEffectInfo { /** Dynamic light component */ var() KFExplosionLight LightTemplate; /** Muzzle flash PSC and Templates */ var() ParticleSystem ParticleSystemTemplate; var() bool bPSCLoops; /** If set, do not deactivate when weapon stops firing (only works with bPSCLoops=FALSE) */ var() bool bIgnoreStopFire; /** Sets LifeSpan of PSC (iff bMuzzleFlashPSCLoops=FALSE) and light */ var() float Duration; /** The default socket name to attach to */ var() name SocketName; var() ESceneDepthPriorityGroup FirstPersonDepthPriorityGroup; var const name TimerName; /** Transient vars used by muzzle flash instances */ var transient KFParticleSystemComponent PSC; var transient KFExplosionLightComponent LightComponent; var transient bool bIsActive; structdefaultproperties { SocketName=MuzzleFlash Duration=0.33f FirstPersonDepthPriorityGroup=SDPG_Foreground } }; var() MuzzleEffectInfo MuzzleFlash; /** If set, creates a second set of muzzle flash data used for alt firemode */ var() bool bEnableSecondaryMuzzleFlash; var() MuzzleEffectInfo MuzzleFlashAlt; /********************************************************************************************* * Advanced settings ********************************************************************************************* */ /** Set this to a fire mode when you want them to alternate between the primary muzzle flash, and alternate when using this fire mode */ var(Advanced) byte FireModeAlternateBothEffects; /** Set this to a fire mode when you want them to fire both the primary muzzle flash when using that firemode. Set to 254 to always fire both primary and secondary flashes */ var(Advanced) byte FireModeFireBothEffects; /** Used to track which effect was last used when FireModeAlternateBothEffects is used */ var transient bool bLastWasPrimary; /********************************************************************************************* Shell Eject ********************************************************************************************* */ /** Muzzle flash PSC and Templates */ var(ShellEject) ParticleSystem ShellEjectPSCTemplate; /** The default socket name to attach to */ var(ShellEject) name ShellEjectSocketName; /** If set, the shell eject will automatically trigger with the muzzle flash */ var(ShellEject) bool bAutoActivateShellEject; /** Transient vars used by muzzle flash instances */ var transient KFParticleSystemComponent ShellEjectPSC; /** Life time */ var globalconfig float ShellEjectLifetime; /********************************************************************************************* * Functions ********************************************************************************************* */ cpptext { void StartMuzzleFlash(struct FMuzzleEffectInfo& Effect); void StopMuzzleFlash(struct FMuzzleEffectInfo& Effect, UBOOL bForce); } /** Activate the muzzle flash effects from the owning actor */ native function CauseMuzzleFlash(optional byte FiringMode); native function StopMuzzleFlash(optional bool bForce); native function MuzzleFlashTimer(); native function MuzzleFlashAltTimer(); function AttachMuzzleFlash(SkeletalMeshComponent OwnerMesh, optional name SocketNameOverride, optional name ShellEjectSocketOverride) { local float OwnerMeshFOV; // Allow code to override attachment socket if ( SocketNameOverride != 'None' ) { MuzzleFlash.SocketName = SocketNameOverride; } // Attach the primary muzzle flash if( MuzzleFlash.ParticleSystemTemplate != none ) { // Attach MuzzleFlashPSC to owner OwnerMesh.AttachComponentToSocket(MuzzleFlash.PSC, MuzzleFlash.SocketName); MuzzleFlash.PSC.SetTemplate(MuzzleFlash.ParticleSystemTemplate); } // Initialize and attach the muzzle flash light if ( MuzzleFlash.LightTemplate != None ) { MuzzleFlash.LightComponent = new(self) class'KFExplosionLightComponent'; MuzzleFlash.LightComponent.SetTemplate(MuzzleFlash.LightTemplate); MuzzleFlash.LightComponent.SetEnabled(false); OwnerMesh.AttachComponentToSocket(MuzzleFlash.LightComponent, MuzzleFlash.SocketName); } if ( bEnableSecondaryMuzzleFlash ) { // Attach the alt fire muzzle flash if( MuzzleFlashAlt.ParticleSystemTemplate != none ) { // Attach MuzzleFlashAltPSC to owner OwnerMesh.AttachComponentToSocket(MuzzleFlashAlt.PSC, MuzzleFlashAlt.SocketName); MuzzleFlashAlt.PSC.SetTemplate(MuzzleFlashAlt.ParticleSystemTemplate); } // Initialize and attach the muzzle flash light if ( MuzzleFlashAlt.LightTemplate != None ) { MuzzleFlashAlt.LightComponent = new(self) class'KFExplosionLightComponent'; MuzzleFlashAlt.LightComponent.SetTemplate(MuzzleFlashAlt.LightTemplate); MuzzleFlashAlt.LightComponent.SetEnabled(false); OwnerMesh.AttachComponentToSocket(MuzzleFlashAlt.LightComponent, MuzzleFlashAlt.SocketName); } } // Initialize and attach the shell eject psc if ( ShellEjectPSCTemplate != None ) { if ( ShellEjectSocketOverride != 'None' ) { ShellEjectSocketName = ShellEjectSocketOverride; } ShellEjectPSC = new(self) class'KFParticleSystemComponent'; ShellEjectPSC.bAutoActivate = false; ShellEjectPSC.SetTemplate(ShellEjectPSCTemplate); ShellEjectPSC.SetFloatParameter('LifetimeParam', ShellEjectLifetime); OwnerMesh.AttachComponentToSocket(ShellEjectPSC, ShellEjectSocketName); } // If attaching to a foreground (1st person) mesh if ( OwnerMesh.DepthPriorityGroup == SDPG_Foreground ) { // No MuzzleFlashPSC foreground adjustment for now //MuzzleFlash.PSC.bDepthTestEnabled=false; //MuzzleFlashAlt.PSC.bDepthTestEnabled=false; if( MuzzleFlash.PSC != none ) { MuzzleFlash.PSC.SetDepthPriorityGroup( MuzzleFlash.FirstPersonDepthPriorityGroup ); MuzzleFlash.PSC.bDepthTestEnabled = MuzzleFlash.FirstPersonDepthPriorityGroup == SDPG_Foreground; } if( MuzzleFlashAlt.PSC != none ) { MuzzleFlashAlt.PSC.SetDepthPriorityGroup( MuzzleFlashAlt.FirstPersonDepthPriorityGroup ); MuzzleFlashAlt.PSC.bDepthTestEnabled = MuzzleFlashAlt.FirstPersonDepthPriorityGroup == SDPG_Foreground; } //if( ShellEjectPSC != none ) //{ //ShellEjectPSC.SetDepthPriorityGroup( SDPG_Foreground ); //ShellEjectPSC.bDepthTestEnabled = true; //} } // If attaching to a mesh with a custom FOV if (OwnerMesh.IsA('KFSkeletalMeshComponent')) { OwnerMeshFOV = KFSkeletalMeshComponent(OwnerMesh).FOV; SetFOV(OwnerMeshFOV); } Owner = OwnerMesh.Owner; } /** * Adjust the FOV for the first person weapon and arms. */ simulated event SetFOV( float NewFOV ) { MuzzleFlash.PSC.SetFOV(NewFOV); if ( MuzzleFlashAlt.PSC != None ) { MuzzleFlashAlt.PSC.SetFOV(NewFOV); } } function DetachMuzzleFlash(SkeletalMeshComponent OwnerMesh) { OwnerMesh.DetachComponent(MuzzleFlash.PSC); OwnerMesh.DetachComponent(MuzzleFlashAlt.PSC); if ( MuzzleFlash.LightComponent != None ) { OwnerMesh.DetachComponent(MuzzleFlash.LightComponent); } if ( MuzzleFlashAlt.LightComponent != None ) { OwnerMesh.DetachComponent(MuzzleFlashAlt.LightComponent); } if ( ShellEjectPSC != None ) { OwnerMesh.DetachComponent(ShellEjectPSC); } } /** Returns a socket name used by the primary muzzle flash effect */ function name GetSocketName() { return MuzzleFlash.SocketName; } /** Returns a socket name used by the secondary muzzle flash effect */ function name GetAltSocketName() { return MuzzleFlashAlt.SocketName; } function CauseShellEject() { if ( !Owner.WorldInfo.bDropDetail && ShellEjectPSC != none ) { ShellEjectPSC.ActivateSystem(); } } function SetShellEjectLife(float NewLifetime=8.f) { if ( ShellEjectPSCTemplate != None ) { ShellEjectPSC.SetFloatParameter('LifetimeParam', NewLifetime); } } defaultproperties { Begin Object Class=KFParticleSystemComponent Name=ParticleSystemComponent0 bAutoActivate=FALSE TickGroup=TG_PostUpdateWork End Object Begin Object Class=KFParticleSystemComponent Name=ParticleSystemComponent1 bAutoActivate=FALSE TickGroup=TG_PostUpdateWork End Object Begin Object Class=KFParticleSystemComponent Name=ParticleSystemComponent2 bAutoActivate=FALSE TickGroup=TG_PostUpdateWork End Object MuzzleFlash=(PSC=ParticleSystemComponent0, TimerName=MuzzleFlashTimer) MuzzleFlashAlt=(PSC=ParticleSystemComponent1, TimerName=MuzzleFlashAltTimer) ShellEjectSocketName=ShellEject bAutoActivateShellEject=true FireModeAlternateBothEffects=255 FireModeFireBothEffects=255 }