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.
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();
}
}