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

236 lines
5.7 KiB
Ucode

// most of the code c&p from ZEDBeamEffect
class TeslaBeam extends xEmitter;
var array<TeslaBeam> ChildBeams;
var Actor StartActor, EndActor; // actors to chain with beam
var name StartBoneName, EndBoneName; // bone names of StartActor/EndActor to use for beam ending locations
var transient float EffectEndTime; // time when beam should be hidden. 0 - don't hide
var ZedBeamSparks Sparks;
var Vector PrevLoc;
var Rotator PrevRot;
var Vector StartEffect, EndEffect;
var transient protected bool bInstigatorReplicated; // not sure if we need this
var transient protected float DestroyTime;
replication
{
reliable if ( Role == ROLE_Authority && bNetDirty )
StartActor, EndActor, StartBoneName, EndBoneName,
EffectEndTime;
}
simulated function PostNetReceive()
{
bInstigatorReplicated = bInstigatorReplicated || Instigator != none;
}
simulated function PostBeginPlay()
{
super.PostBeginPlay();
if ( TeslaHusk(Owner) != none )
Instigator = TeslaHusk(Owner);
}
// returns item index of ChildBeams array, which has ChainedActor as an EndActor
// returns -1, if ChainedActor isn't chained to EndActor
function int ChildIndex(Actor ChainedActor)
{
local int i;
if ( ChainedActor != none ) {
for ( i=0; i<ChildBeams.Length; ++i ) {
if ( ChildBeams[i] != none && ChildBeams[i].EndActor == ChainedActor)
return i;
}
}
return -1;
}
function bool IsChainedTo(Actor Other, optional byte ChainLevel)
{
local int i;
if ( Other == none || ChainLevel > 100 ) // prevents circular links
return false;
for ( i=0; i<ChildBeams.Length; ++i ) {
if ( ChildBeams[i] != none && (ChildBeams[i].EndActor == Other || ChildBeams[i].IsChainedTo(Other, ChainLevel+1)) )
return true;
}
return false;
}
function DestroyChildBeams()
{
local int i;
for ( i=0; i<ChildBeams.Length; ++i ) {
if ( ChildBeams[i] != none ) {
ChildBeams[i].Instigator = none;
}
}
ChildBeams.Length = 0;
}
simulated function Destroyed()
{
if ( Sparks != None )
{
Sparks.SetTimer(0, false);
Sparks.mRegen = false;
Sparks.LightType = LT_None;
}
if ( ChildBeams.Length > 0 )
DestroyChildBeams();
Super.Destroyed();
}
simulated function SetBeamLocation()
{
if ( StartBoneName == '' )
StartEffect = StartActor.Location;
else {
StartEffect = StartActor.GetBoneCoords(StartBoneName).Origin;
}
if ( EndBoneName == '' )
EndEffect = EndActor.Location;
else {
EndEffect = EndActor.GetBoneCoords(EndBoneName).Origin;
}
SetLocation(StartEffect);
bHidden = false;
}
simulated function Vector SetBeamRotation()
{
SetRotation(Rotator(EndEffect - StartEffect));
return Normal(EndEffect - StartEffect);
}
simulated function bool CheckMaxEffectDistance(PlayerController P, vector SpawnLocation)
{
return !P.BeyondViewDistance(SpawnLocation,1000);
}
simulated function Tick(float dt)
{
local float LocDiff, RotDiff, WiggleMe;
local Vector BeamDir;
local PlayerController LocalPC;
if ( Instigator == none ) {
if ( Role == ROLE_Authority ) {
if ( Level.NetMode != NM_Standalone && DestroyTime == 0 )
DestroyTime = Level.TimeSeconds + 1.0; // give some time to replicate
else if ( DestroyTime < Level.TimeSeconds )
Destroy();
}
else if ( bInstigatorReplicated )
Destroy();
bHidden = true;
}
else {
bHidden = StartActor == none || EndActor == none || (EffectEndTime != 0 && EffectEndTime < Level.TimeSeconds);
}
if ( Sparks != none )
Sparks.bHidden = bHidden;
if ( bHidden ) {
if ( ChildBeams.Length > 0 )
DestroyChildBeams(); // destroy them, because they are comming from the EndActor
return;
}
// set beam start location
SetBeamLocation();
BeamDir = SetBeamRotation();
if ( Level.NetMode != NM_DedicatedServer )
{
if ( Sparks == None && EffectIsRelevant(EndEffect, false) )
{
LocalPC = Level.GetLocalPlayerController();
if ( LocalPC != none && CheckMaxEffectDistance(LocalPC, Location) )
Sparks = Spawn(class'ZedBeamSparks', self);
}
}
/*
if ( Level.bDropDetail || Level.DetailMode == DM_Low )
{
bDynamicLight = false;
LightType = LT_None;
}
else if ( bDynamicLight )
LightType = LT_Steady;
*/
mSpawnVecA = EndEffect;
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 );
Sparks.SetRotation( Rotation);
Sparks.mRegenRange[0] = Sparks.DesiredRegen;
Sparks.mRegenRange[1] = Sparks.DesiredRegen;
Sparks.bDynamicLight = true;
}
}
defaultproperties
{
mParticleType=PT_Beam
mMaxParticles=3
mRegenDist=65.000000
mSpinRange(0)=45000.000000
mSizeRange(0)=6.000000
mColorRange(0)=(B=240,G=240,R=240)
mColorRange(1)=(B=240,G=240,R=240)
mAttenuate=False
mAttenKa=0.000000
mWaveFrequency=0.060000
mWaveAmplitude=8.000000
mWaveShift=100000.000000
mBendStrength=3.000000
mWaveLockEnd=True
LightHue=100
LightSaturation=100
LightBrightness=255.000000
LightRadius=4.000000
bNetTemporary=False
bReplicateInstigator=True
bReplicateMovement=False
RemoteRole=ROLE_SimulatedProxy
NetUpdateFrequency=5.000000
LifeSpan=10.000000
Skins(0)=FinalBlend'KFZED_FX_T.Energy.ZED_FX_Beam_FB'
Style=STY_Additive
bNetNotify=True
}