//============================================================================= // KFWeapAttach_FlameBase //============================================================================= // Base weapon attachment class for weapons that shoot fire //============================================================================= // Killing Floor 2 // Copyright (C) 2015 Tripwire Interactive LLC // John "Ramm-Jaeger" Gibson //============================================================================= class KFWeapAttach_SprayBase extends KFWeaponAttachment; /** Internal. TRUE if fire is spewing, false otherwise. */ var protected transient bool bFireSpraying; var protected transient int NextFlamePoolIdx; /** A pool of fire spray actors to use for this attachment. Needed because if you fire quickly blending between the two looks better */ var protected transient KFSprayActor FlamePool[2]; /** The spray actor we are associated with, if currently firing. */ var transient protected KFSprayActor ActiveFlameSpray; /** The Archetype to spawn for our fire spray actors. */ var() protected const KFSprayActor FlameSprayArchetype; /** Whether TurnOnPilot has already been called */ var protected bool bPilotLightOn; /** Pilot light sound play event */ var AkEvent PilotLightPlayEvent; /** Pilot light sound stop event */ var AkEvent PilotLightStopEvent; var protected bool bInvertPilot; /** Effect for the pilot light. */ var protected KFParticleSystemComponent PSC_PilotLight; /** Socket to attach the pilot light to. */ var name PilotLightSocketName; /** Dynamic light component */ var() KFExplosionLight PilotLightTemplate; var transient KFExplosionLightComponent PilotLightComponent; /** Emitter to play when firing stops. */ var() const ParticleSystemComponent PSC_EndSpray; /** How hot the Barrel Currently is */ var float BarrelHeat; /** How hot the Barrel was last frame */ var float LastBarrelHeat; /********************************************************************************************* * Optional dynamic pilot lights ********************************************************************************************* */ struct PilotLight { var() PointLightComponent Light; var() name LightAttachBone; var() float FlickerIntensity; var() float FlickerInterpSpeed; var() float LastLightBrightness; }; var(PilotLights) transient array PilotLights; /********************************************************************************************* * @name Debugging *********************************************************************************************/ simulated function SetFlameDebugDamage(bool bDebugDirectDamage, bool bDebugSplashDamage, bool bDebugShowSplashRadius, bool bDebugShowCollision) { `if(`notdefined(ShippingPC)) FlamePool[0].bDebugDirectDamage = bDebugDirectDamage; FlamePool[0].bDebugSplashDamage = bDebugSplashDamage; FlamePool[0].bDebugShowSplashRadius = bDebugShowSplashRadius; FlamePool[0].bDebugShowCollision = bDebugShowCollision; FlamePool[1].bDebugDirectDamage = bDebugDirectDamage; FlamePool[1].bDebugSplashDamage = bDebugSplashDamage; FlamePool[1].bDebugShowSplashRadius = bDebugShowSplashRadius; FlamePool[1].bDebugShowCollision = bDebugShowCollision; `endif } simulated function SetFlameDebugFX(bool bDebugShowSeeds, bool bDebugShowBones, bool bDebugForceNonPlayerParticles) { `if(`notdefined(ShippingPC)) FlamePool[0].bDebugShowSeeds = bDebugShowSeeds; FlamePool[0].bDebugShowBones = bDebugShowBones; FlamePool[0].bDebugForceNonPlayerParticles = bDebugForceNonPlayerParticles; FlamePool[1].bDebugShowSeeds = bDebugShowSeeds; FlamePool[1].bDebugShowBones = bDebugShowBones; FlamePool[1].bDebugForceNonPlayerParticles = bDebugForceNonPlayerParticles; `endif } /** * Called immediately before gameplay begins. */ simulated event PreBeginPlay() { Super.PreBeginPlay(); if ( WorldInfo.NetMode == NM_DedicatedServer ) { return; } if ( WeaponMIC == None && WeapMesh != None ) { WeaponMIC = WeapMesh.CreateAndSetMaterialInstanceConstant(0); } } simulated protected function TurnOnPilot() { local vector MuzzleLoc; local rotator Aim; local int Idx; if (bPilotLightOn) return; // start looping sound StartPilotSound(); // Attach and start up the pilot light if( PSC_PilotLight != None ) { WeapMesh.AttachComponentToSocket( PSC_PilotLight, PilotLightSocketName ); PSC_PilotLight.ActivateSystem(); // Turn on the low flame, turn off the high flame PSC_PilotLight.SetFloatParameter('Pilotlow', 1.0); PSC_PilotLight.SetFloatParameter('Pilothigh', 0.0); } if( class'KFWeap_FlameBase'.default.bArePilotLightsAllowed ) { // Attach the dynamic pilot lights for( Idx = 0; Idx < PilotLights.length; ++Idx ) { WeapMesh.AttachComponentToSocket( PilotLights[Idx].Light, PilotLights[Idx].LightAttachBone ); } } else { PilotLights.Remove(0, PilotLights.length); } SetPilotDynamicLightEnabled(true); GetFlameSocketLocAndRot(MuzzleLoc, Aim); if( FlamePool[0] == None ) { FlamePool[0] = Spawn(FlameSprayArchetype.Class, Instigator,, MuzzleLoc, Aim, FlameSprayArchetype, TRUE); } if( FlamePool[1] == None ) { FlamePool[1] = Spawn(FlameSprayArchetype.Class, Instigator,, MuzzleLoc, Aim, FlameSprayArchetype, TRUE); } // attach flamesprays here too, so they are hooked up before firing FlamePool[0].AttachToMesh(Self, WeapMesh, FlamePool[0].SpraySocketName); FlamePool[1].AttachToMesh(Self, WeapMesh, FlamePool[1].SpraySocketName); // Set these to be visual only as we do the damage on the first person versions FlamePool[0].bVisualOnly=true; FlamePool[1].bVisualOnly=true; if( PSC_EndSpray != None ) { PSC_EndSpray.SetTemplate(FlamePool[0].SprayEndEffect); WeapMesh.AttachComponentToSocket( PSC_EndSpray, FlamePool[0].SpraySocketName ); } bPilotLightOn = TRUE; } simulated function GetFlameSocketLocAndRot(out Vector out_Loc, out Rotator out_Rot) { if( WeapMesh != none && FlameSprayArchetype.Class.default.SpraySocketName != '' ) { WeapMesh.GetSocketWorldLocationAndRotation(FlameSprayArchetype.Class.default.SpraySocketName, out_Loc, out_Rot); } else { out_Loc = Instigator.Location; out_Rot = Instigator.Rotation; } } simulated protected function TurnOffPilot() { // if (AC_PilotLoop != None) // { // AC_PilotLoop.FadeOut(0.2f, 0.f); // AC_PilotLoop = None; // // if (PilotLightExtinguishSound != None) // { // WeaponPlaySound(PilotLightExtinguishSound); // } // } if( PSC_PilotLight != None ) { PSC_PilotLight.DeActivateSystem(); } StopPilotSound(); // turn off lights SetPilotDynamicLightEnabled( false ); bPilotLightOn = FALSE; } simulated protected function KFSprayActor GetFlameSprayFromPool() { local KFSprayActor Ret; Ret = FlamePool[NextFlamePoolIdx]; NextFlamePoolIdx++; if (NextFlamePoolIdx >= ArrayCount(FlamePool)) { NextFlamePoolIdx = 0; } return Ret; } /** * Starts playing looping Pilot light sound */ simulated function StartPilotSound() { if( Instigator != none && !Instigator.IsFirstPerson() ) { if ( PilotLightPlayEvent != None ) { Instigator.PlaySoundBase(PilotLightPlayEvent, true, true, true,, true); } } } /** * Stops playing looping Pilot light sound */ simulated function StopPilotSound() { if ( PilotLightStopEvent != None ) { Instigator.PlaySoundBase(PilotLightStopEvent, true, true, true,, true); } } /** * Toggle the dynamic pilot lights */ simulated function SetPilotDynamicLightEnabled( bool bLightEnabled ) { local int Idx; local bool doEnable; doEnable = bLightEnabled; if (bInvertPilot) { doEnable = bLightEnabled == false; } // Don't turn these on if we're not in third person if (doEnable && (Instigator != none && Instigator.IsFirstPerson())) { return; } // turn off lights for (Idx=0; Idx 0 ) { // Cool the barrel down when not shooting BarrelHeat -= DeltaTime * 0.5; if( BarrelHeat < 0 ) { BarrelHeat = 0; } } } ChangeMaterial(); LastBarrelHeat = BarrelHeat; } // hacky flicker for lights. for (Idx=0; Idx