Charm component that spawns periodic lightning effects around the player. It manages particle prefabs, updates a timer to trigger a lightning bolt prefab every INTERVAL seconds, applies damage/chain settings to the bolt, and hides/shows particle visuals on death/revive.
using Sandbox;
public class CharmLightning : Charm
{
public const string ItemId = "charm_lightning";
private const float INTERVAL = 5f;
private const float DAMAGE = 5f;
private const int CHAINS = 20;
private float _timer;
private GameObject _particles;
private ParticleEffect _particleRing;
private ParticleRingEmitter _particleRingEmitter;
private LightningParticleEffect _lightningParticleEffect;
public static string Description() => $"Every {INTERVAL}s, lightning strikes for {(int)DAMAGE} damage and chains {CHAINS} times";
public override void OnRunStart()
{
base.OnRunStart();
_particles = GameObject.Clone( "prefabs/effects/lightning_target_particles.prefab", new global::Transform( Player.WorldPosition.WithZ( -100f ) ) );
_particleRing = _particles.GetComponent<ParticleEffect>();
_particleRing.Alpha = 0f;
_particleRingEmitter = _particles.GetComponent<ParticleRingEmitter>();
_particleRingEmitter.Rate = 0;
_lightningParticleEffect = _particles.GetComponent<LightningParticleEffect>();
_particles.NetworkSpawn();
}
public override void Update( float dt )
{
base.Update( dt );
if ( Player.IsDead )
return;
_timer += dt;
float progress = _timer / INTERVAL;
var pos = Player.Position2D;
_particles.WorldPosition = new Vector3( pos.x, pos.y, 2f );
_particleRing.Alpha = Utils.Map( progress, 0f, 1f, 0f, 1f, EasingType.ExpoIn );
_particleRingEmitter.Radius = Utils.Map( progress, 0f, 1f, 30f, 0f, EasingType.SineIn );
_particleRingEmitter.Rate = 500;
if ( _timer >= INTERVAL )
{
Strike( pos );
_timer = 0f;
_particles.WorldPosition = _particles.WorldPosition.WithZ( -100f );
_particleRing.Alpha = 0f;
_particleRingEmitter.Rate = 0;
_lightningParticleEffect.ResetEffect();
}
}
public override void OnDie()
{
base.OnDie();
_particles.WorldPosition = _particles.WorldPosition.WithZ( -100f );
_particleRing.Alpha = 0f;
_particleRingEmitter.Rate = 0;
_lightningParticleEffect.SetVisible( false );
}
public override void OnRevive()
{
base.OnRevive();
_timer = 0f;
_lightningParticleEffect.SetVisible( true );
}
void Strike( Vector2 pos )
{
var lightningBoltGo = GameObject.Clone( $"prefabs/lightning_bolt.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( new Vector3( pos.x, pos.y, -100f ) ) } );
var lightningBolt = lightningBoltGo.GetComponent<LightningBolt>();
lightningBolt.Shooter = Player;
lightningBolt.Damage = DAMAGE;
lightningBolt.SpreadLimit = CHAINS;
lightningBoltGo.NetworkSpawn( Player.Network.Owner );
}
protected override void OnDestroy()
{
base.OnDestroy();
if ( _particles != null )
_particles.Destroy();
}
}