rott/kf_sources/KFMod/Classes/ZEDBeamEffect.uc
2026-07-14 20:27:09 +07:00

239 lines
6.9 KiB
Ucode

//=============================================================================
// ZEDBeamEffect
//=============================================================================
// Zed Eradication Device Beam Effect
//=============================================================================
// Killing Floor Source
// Copyright (C) 2012 Tripwire Interactive LLC
// - John "Ramm-Jaeger" Gibson
// Portions derived from LinkBeamEffect Copyright (C) Epic Games
//=============================================================================
class ZEDBeamEffect extends xEmitter;
var Vector StartEffect, EndEffect;
var bool bLockedOn, bHitSomething;
var Vector EffectOffset;
var Vector PrevLoc;
var Rotator PrevRot;
var float scorchtime;
var ZedBeamSparks Sparks;
var ZEDBeamSplashEffect ProtSphere;
var float SphereCharge;
replication
{
unreliable if (Role == ROLE_Authority)
bHitSomething, SphereCharge;
unreliable if ( (Role == ROLE_Authority) && (!bNetOwner || bDemoRecording || bRepClientDemo) )
StartEffect, EndEffect;
}
simulated function Destroyed()
{
if ( Sparks != None )
{
Sparks.SetTimer(0, false);
Sparks.mRegen = false;
Sparks.LightType = LT_None;
}
if ( ProtSphere != None )
ProtSphere.Destroy();
Super.Destroyed();
}
simulated function SetBeamLocation()
{
local KFWeaponAttachment Attachment;
if ( Level.NetMode == NM_DedicatedServer )
{
StartEffect = Instigator.Location + Instigator.EyeHeight*Vect(0,0,1);
SetLocation( StartEffect );
return;
}
if ( Instigator == None )
{
SetLocation( StartEffect );
}
else
{
if ( Instigator.IsFirstPerson() )
{
if ( (Instigator.Weapon == None) || (Instigator.Weapon.Instigator == None) )
SetLocation( Instigator.Location );
else
SetLocation(ZEDGun(Instigator.Weapon).GetFirstPersonBeamFireStart());//SetLocation(Instigator.Weapon.GetEffectStart() - 120 * vector(Instigator.Controller.Rotation));
}
else
{
Attachment = KFWeaponAttachment(xPawn(Instigator).WeaponAttachment);
if ( Attachment != None && (Level.TimeSeconds - Attachment.LastRenderTime) < 1 )
SetLocation( Attachment.GetTipLocation() );
else
SetLocation( Instigator.Location + Normal(EndEffect - Instigator.Location) * 25.0 );
}
if ( Role == ROLE_Authority ) // what clients will use if their instigator is not relevant yet
StartEffect = Location;
}
}
simulated function Vector SetBeamRotation()
{
if ( (Instigator != None) && PlayerController(Instigator.Controller) != None )
SetRotation( Instigator.Controller.GetViewRotation() );
else
SetRotation( Rotator(EndEffect - Location) );
return Normal(EndEffect - Location);
}
simulated function bool CheckMaxEffectDistance(PlayerController P, vector SpawnLocation)
{
return !P.BeyondViewDistance(SpawnLocation,1000);
}
simulated function Tick(float dt)
{
local float LocDiff, RotDiff, WiggleMe,ls;
local Vector BeamDir, HitLocation, HitNormal;
local actor HitActor;
local PlayerController P;
if ( Role == ROLE_Authority && (Instigator == None || Instigator.Controller == None) )
{
Destroy();
return;
}
// set beam start location
SetBeamLocation();
BeamDir = SetBeamRotation();
if ( Level.NetMode != NM_DedicatedServer )
{
if ( Sparks == None && EffectIsRelevant(EndEffect, false) )
{
P = Level.GetLocalPlayerController();
if ( (P == Instigator.Controller) || CheckMaxEffectDistance(P, Location) )
Sparks = Spawn(class'ZedBeamSparks', self);
}
if ( (ProtSphere == None) && (Level.NetMode != NM_DedicatedServer) )
{
ProtSphere = Spawn(class'ZEDBeamSplashEffect');
}
}
ls = 1.0;
if ( Level.bDropDetail || Level.DetailMode == DM_Low )
{
bDynamicLight = false;
LightType = LT_None;
}
else if ( bDynamicLight )
LightType = LT_Steady;
mSpawnVecA = EndEffect;
mWaveLockEnd = bLockedOn;
// magic wiggle code
if ( bLockedOn )
{
mWaveAmplitude = FMax(0.0, mWaveAmplitude - (mWaveAmplitude+5)*4.0*dt);
}
else
{
LocDiff = VSize((Location - PrevLoc) * Vect(1,1,5));
RotDiff = VSize(Vector(Rotation) - Vector(PrevRot));
WiggleMe = FMax(LocDiff*0.02, RotDiff*4.0);
mWaveAmplitude = FMax(1.0, mWaveAmplitude - mWaveAmplitude*1.0*dt);
mWaveAmplitude = FMin(16.0, mWaveAmplitude + WiggleMe);
}
PrevLoc = Location;
PrevRot = Rotation;
if ( Sparks != None )
{
Sparks.SetLocation( EndEffect - BeamDir*10.0 );
if ( bHitSomething )
Sparks.SetRotation( Rotation);
else
Sparks.SetRotation( Rotator(-BeamDir) );
Sparks.mRegenRange[0] = Sparks.DesiredRegen;
Sparks.mRegenRange[1] = Sparks.DesiredRegen;
Sparks.bDynamicLight = true;
}
if ( bHitSomething )
{
if ( ProtSphere != None )
{
ProtSphere.SetLocation( EndEffect );
ProtSphere.SetRotation( Rotation );
ProtSphere.bHidden = false;
ProtSphere.Emitters[0].SizeScale[0].RelativeSize = Lerp( SphereCharge, 0, 3.75 );
ProtSphere.Emitters[0].SizeScale[1].RelativeSize = Lerp( SphereCharge, 0, 3.75 );
}
}
else
{
if ( ProtSphere != None )
ProtSphere.bHidden = true;
}
if ( bHitSomething && (Level.NetMode != NM_DedicatedServer) && (Level.TimeSeconds - ScorchTime > 0.07) )
{
ScorchTime = Level.TimeSeconds;
HitActor = Trace(HitLocation, HitNormal, EndEffect + 100*BeamDir, EndEffect - 100*BeamDir, true);
if ( (HitActor != None) && HitActor.bWorldGeometry )
spawn(class'KFMod.FlameThrowerBurnMark_Small',,,HitLocation,rotator(-HitNormal));
}
}
defaultproperties
{
RemoteRole=ROLE_SimulatedProxy
bNetTemporary=false
bReplicateInstigator=true
mParticleType=PT_Beam
mStartParticles=1
mAttenuate=false
mSizeRange(0)=6.0 // width
mRegenDist=65.0 // section length
mMaxParticles=3 // planes
mColorRange(0)=(R=240,B=240,G=240)
mColorRange(1)=(R=240,B=240,G=240)
mSpinRange(0)=45000 // spin
mAttenKa=0.0
mWaveFrequency=0.06
mWaveAmplitude=8.0
mWaveShift=100000.0
mBendStrength=3.0
mWaveLockEnd=true
Skins(0)=FinalBlend'KFZED_FX_T.Energy.ZED_FX_Beam_FB'
Style=STY_Additive
bUnlit=true
EffectOffset=(X=22,Y=11,Z=1.4)
bDynamicLight=true
LightType=LT_Steady
LightRadius=4
LightHue=100 // 0=red 160=blue 40=yellow
LightSaturation=100
LightBrightness=255
LightEffect=LE_QuadraticNonIncidence
}