status/CurseReverseControlsStatus.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;
using static Sandbox.VertexLayout;

[Status( 4, 0, 1f, 0, true )]
public class CurseReverseControlsStatus : Status
{
	private bool _areControlsReversed;
	private TimeSince _timeSince;
	private float _currDelayTime;

	public CurseReverseControlsStatus()
	{
		Title = "Backwards Man";
		IconPath = "textures/icons/curse_reverse_controls.png";
	}

	public override void Init( Player player )
	{
		base.Init( player );

		ShouldUpdate = true;
	}

	public override void Refresh()
	{
		Description = GetDescription( Level );

		_areControlsReversed = Player.Stats[PlayerStat.ReverseControls] > 0f;
		_timeSince = 0f;
		_currDelayTime = _areControlsReversed ? GetLengthForLevel( Level ) : GetDelayForLevel( Level );
	}

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

		if ( _timeSince > _currDelayTime )
		{
			_areControlsReversed = !_areControlsReversed;
			Player.Stats[PlayerStat.ReverseControls] = _areControlsReversed ? 1f : 0f;

			_timeSince = 0f;
			_currDelayTime = _areControlsReversed ? GetLengthForLevel( Level ) : GetDelayForLevel( Level );

			Manager.Instance.PlaySfxNearby( "player.dash", Player.Position2D, pitch: Game.Random.Float(2.1f, 2.2f), volume: 0.5f, maxDist: 4f );
		}

		var time = _currDelayTime - _timeSince;
		DataString = time.ToString( "F1" );
	}

	public override string GetDescription( int newLevel )
	{
		switch ( newLevel )
		{
			case 1: default: return "Controls are rarely reversed";
			case 2: return "Controls are occasionally reversed";
			case 3: return "Controls are oftenly reversed";
			case 4: return "Controls are very oftenly reversed";
		}
	}

	public override string GetUpgradeDescription( int newLevel )
	{
		switch ( newLevel )
		{
			case 1: default: return GetDescription( newLevel );
			case 2: return "Controls are rarely→occasionally reversed";
			case 3: return "Controls are occasionally→oftenly reversed";
			case 4: return "Controls are oftenly→very oftenly reversed";
		}
	}

	public float GetDelayForLevel( int level )
	{
		switch(level)
		{
			case 1: default: return Game.Random.Float( 15f, 30f );
			case 2: return Game.Random.Float( 8f, 16f );
			case 3: return Game.Random.Float( 2f, 6f );
			case 4: return Game.Random.Float( 1f, 4f );
		}
	}

	public float GetLengthForLevel( int level )
	{
		switch ( level )
		{
			case 1: default: return Game.Random.Float( 2f, 3f );
			case 2: return Game.Random.Float( 3f, 5f );
			case 3: return Game.Random.Float( 4f, 14f );
			case 4: return Game.Random.Float( 8f, 24f );
		}
	}

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

		Player.RemoveShieldVfx();
	}
}