stageEvents/StageEventCloudy.cs

StageEventCloudy component that spawns and manages a cloudy/fog particle effect for a stage event. It creates a prefab clone, configures particle effect direction and emitter looping, plays a UI sound and local chat message, and stops spawning before removing the effect with a temporary lifetime.

File Access
using System;
using System.Reflection;
using Sandbox;

public class StageEventCloudy : StageEvent
{
	private GameObject _particleObj;
	private ParticleEffect _particleEffect;
	private ParticleEmitter _emitter;

	private Random _random;

	private bool _hasStoppedSpawning;

	public override void Start( int randSeed )
	{
		base.Start( randSeed );

		Manager.Instance.PlaySfxUIRpc( "cloudy", pitch: Game.Random.Float( 0.95f, 1.05f ), volume: 0.75f );

		Manager.Instance.Chat.AddLocalChatMessage( "It's getting foggy!", from: "" );

		Lifetime = Game.Random.Float( 20f, 30f );

		_random = new Random( randSeed );

		bool onLeftSide = _random.Next( 0, 2 ) == 0;

		_particleObj = GameObject.Clone( "prefabs/effects/cloudy_effect.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( new Vector3( 1500f * (onLeftSide ? -1f : 1f), 0f, 200f ) ) } );
		_particleEffect = _particleObj.GetComponent<ParticleEffect>();
		_emitter = _particleObj.GetComponent<ParticleEmitter>();

		_particleEffect.ForceDirection = new Vector3( 1000f * (onLeftSide ? 1f : -1f), 0f, 0f );
	}

	public override void Update()
	{
		base.Update();

		if ( !_hasStoppedSpawning && TimeSinceStart > Lifetime - 4f )
		{
			_emitter.Loop = false;
			_hasStoppedSpawning = true;
		}

		if( TimeSinceStart > Lifetime )
		{
			Manager.Instance.RemoveEvent( EventType );
			return;
		}

		// todo: change clouds for fps perk
	}

	public override void Remove()
	{
		base.Remove();

		var temporaryEffect = _particleObj.AddComponent<TemporaryEffect>();
		temporaryEffect.DestroyAfterSeconds = 30f;

		_emitter.Loop = false;
		_emitter.DestroyOnEnd = true;
	}
}