fallingObjects/LightningBolt.cs

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.

File Access
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 );
	}
}