stageEvents/StageEventWind.cs

StageEventWind, a stage event that creates a wind effect: spawns a particle prefab, drives particle emitter and effect direction, updates a global wind force, lerps strength at start/end, and periodically randomizes direction.

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

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

	private const float LERP_TIME = 5f;

	private float _windStrength;
	private Vector2 _windDir;

	private float _maxStrength;

	private Random _random;

	private TimeSince _timeSinceChangeDir;

	private bool _hasStoppedSpawning;

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

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

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

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

		_random = new Random( randSeed );

		_windDir = Utils.GetVector2FromAngleDegrees( _random.Next( 0, 360 ) );

		var prefabName = "wind_effect";
		if( Manager.Instance.Difficulty == 1 ) prefabName = "wind_effect_diff_1";
		else if ( Manager.Instance.Difficulty == 2 ) prefabName = "wind_effect_diff_2";

		_particleObj = GameObject.Clone( $"prefabs/effects/{prefabName}.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( new Vector3( 0f, 0f, 250f ) ) } );
		_particleEffect = _particleObj.GetComponent<ParticleEffect>();
		_emitter = _particleObj.GetComponent<ParticleEmitter>();

		_maxStrength = Utils.Select( Manager.Instance.Difficulty, 135f, 150f, 165f );

		Manager.Instance.IsWindActive = true;

		_timeSinceChangeDir = 0f;
	}

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

		if( TimeSinceStart < LERP_TIME )
		{
			_windStrength = Utils.Map( TimeSinceStart, 0f, LERP_TIME, 0f, _maxStrength );
		}
		else if(TimeSinceStart > Lifetime - LERP_TIME )
		{
			if ( !_hasStoppedSpawning )
			{
				_emitter.Rate = 0f;
				_hasStoppedSpawning = true;
			}

			_windStrength = Utils.Map( TimeSinceStart, Lifetime - LERP_TIME, Lifetime, _maxStrength, 0f );
		}

		if ( _timeSinceChangeDir > 5f )
		{
			_windDir = Utils.RotateVector( _windDir, _random.Next( -45, 45 ) );
			_timeSinceChangeDir = 0f;
		}

		float particleStrengthFactor = 2f;
		_particleEffect.ForceDirection = new Vector3(_windDir.x * _windStrength * particleStrengthFactor, _windDir.y * _windStrength * particleStrengthFactor, -20f);
		Manager.Instance.GlobalWindForce = _windStrength * _windDir;

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

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

		Manager.Instance.IsWindActive = false;
		Manager.Instance.GlobalWindForce = Vector2.Zero;

		_particleObj?.Destroy();
	}
}