stageEvents/StageEventIcyGround.cs

StageEventIcyGround is a stage event class that spawns a snow particle prefab, adjusts global movespeed and friction modifiers, and fades an icy fog in and out over the event lifetime. It also posts a local chat message when started and stops particle emission near the end.

NetworkingFile Access
using System;
using System.Reflection;
using Sandbox;

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

	//GameObject _groundObj;
	//ModelRenderer _groundRenderer;
	//Color _originalGroundTint;

	// todo: sometimes last for 2 minutes+

	private const float LERP_TIME = 5f;
	private const float REDUCED_FRICTION = 0.1f;
	private const float REDUCED_MOVESPEED = 0.25f;

	//private Color _groundColorIcy;

	// todo: change player dash so it adds normal velocity?
	// todo: change movespeed factor to work better with sliding

	private bool _hasStoppedSpawning;

	GradientFog _fog;

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

		// sfx
		Manager.Instance.Chat.AddLocalChatMessage( "The ground's getting icy!", from: "" );

		Lifetime = 60f;

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

		//_groundObj = Manager.Instance.Scene.Directory.FindByName( "ground" ).FirstOrDefault();
		//_groundObj.Enabled = true;
		//_groundRenderer = _groundObj.GetComponent<ModelRenderer>();
		//_originalGroundTint = _groundRenderer.Tint;

		//_groundColorIcy = new Color( 0.05f, 0.1f, 0.2f, 0.55f );

		_fog = Manager.Instance.IcyGroundFog.GetComponent<GradientFog>( includeDisabled: true );
		_fog.Color = _fog.Color.WithAlpha( 0f );
		Manager.Instance.IcyGroundFog.Enabled = true;
	}

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

		var FOG_FULL_OPACITY = 0.15f;

		if( TimeSinceStart < LERP_TIME )
		{
			Manager.Instance.GlobalMovespeedModifier = Utils.Map( TimeSinceStart, 0f, LERP_TIME, 1f, REDUCED_MOVESPEED );
			Manager.Instance.GlobalFrictionModifier = Utils.Map( TimeSinceStart, 0f, LERP_TIME, 1f, REDUCED_FRICTION );
			_fog.Color = _fog.Color.WithAlpha( Utils.Map( TimeSinceStart, 0f, LERP_TIME, 0f, FOG_FULL_OPACITY ) );
			//_groundRenderer.Tint = Color.Lerp( _originalGroundTint, _groundColorIcy, Utils.Map( TimeSinceStart, 0f, LERP_TIME, 0f, 1f ) );
		}
		else if(TimeSinceStart > Lifetime - LERP_TIME )
		{
			if ( !_hasStoppedSpawning )
			{
				_emitter.Rate = 0f;
				_hasStoppedSpawning = true;
			}

			Manager.Instance.GlobalMovespeedModifier = Utils.Map( TimeSinceStart, Lifetime - LERP_TIME, Lifetime, REDUCED_MOVESPEED, 1f );
			Manager.Instance.GlobalFrictionModifier = Utils.Map( TimeSinceStart, Lifetime - LERP_TIME, Lifetime, REDUCED_FRICTION, 1f );
			_fog.Color = _fog.Color.WithAlpha( Utils.Map( TimeSinceStart, Lifetime - LERP_TIME, Lifetime, FOG_FULL_OPACITY, 0f ) );
			//_groundRenderer.Tint = Color.Lerp( _groundColorIcy, _originalGroundTint, Utils.Map( TimeSinceStart, Lifetime - LERP_TIME, Lifetime, 0f, 1f ) );
		}

		var windForce = Manager.Instance.GlobalWindForce;
		float particleStrengthFactor = 2f;
		_particleEffect.ForceDirection = new Vector3( windForce.x * particleStrengthFactor, windForce.y * particleStrengthFactor, -100f );

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

		if ( !Networking.IsHost )
			return;
	}

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

		//_groundRenderer.Tint = _originalGroundTint;
		//_groundObj.Enabled = false;

		Manager.Instance.GlobalMovespeedModifier = 1f;
		Manager.Instance.GlobalFrictionModifier = 1f;

		Manager.Instance.IcyGroundFog.Enabled = false;

		_particleObj?.Destroy();
	}
}