A FallingObject subclass that represents a lightning bolt. It initializes lifetime/height on start, applies shock damage to the nearest unit when it hits the ground, spawns a scorch decal and plays a zap sound, then destroys itself.
using System;
using Sandbox;
public class LightningBolt : FallingObject
{
[Property] public ParticleEffect ParticleEffect { get; set; }
public float Damage { get; set; }
public int SpreadLimit { get; set; }
protected override void OnStart()
{
base.OnStart();
TimeSinceSpawn = 0f;
if ( IsProxy )
return;
_startingHeight = 1024f;
Lifetime = 0.5f;
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( IsProxy )
return;
}
public override void HitGround()
{
HitGroundRpc();
float radius = 38f;
Unit closestUnit = Manager.Instance.GetClosestUnit( (Vector2)WorldPosition, radius, includeUnitRadius: true, except: null, x => !x.IsShocked, playerDistanceMult: 1.2f );
if ( closestUnit.IsValid() )
{
int additionalChains = Shooter.IsValid() ? (int)Shooter.Stats[PlayerStat.AdditionalLightningChains] : 0;
closestUnit.Shock( Shooter, enemySource: null, Damage, 0, SpreadLimit + additionalChains );
}
GameObject.Destroy();
}
[Rpc.Broadcast]
public void HitGroundRpc()
{
var scorchDecalGo = GameObject.Clone( "prefabs/effects/scorch_decal.prefab", new global::Transform( new Vector3( WorldPosition.x, WorldPosition.y, 1f ), new Angles( 90f, Game.Random.Float( 0f, 360f ), 0f ) ) );
var scorch = scorchDecalGo.GetComponent<ScorchDecal>();
scorch.StartTime = Game.Random.Float( 0.1f, 0.125f );
scorch.Lifetime = Game.Random.Float( 2f, 3f ) * Utils.Map( Manager.Instance.NumDecals, 0, 100, 1f, 0.5f );
scorch.Size = Game.Random.Float( 1.2f, 1.8f );
Manager.Instance.PlaySfxNearby( "zap", (Vector2)WorldPosition, pitch: Game.Random.Float( 0.8f, 0.85f ), volume: 0.9f, maxDist: 400f );
}
}