perks/PerkDashTemporary.cs

A mythic perk class that grants temporary single-use dashes to a player. It counts available temporary dashes, recharges them over time, updates UI display/cooldown/highlight, and notifies the Player stat when dashes change.

Networking
using System;
using Sandbox;

[Perk( Rarity.Mythic, alwaysOfferDebug: false )]
public class PerkDashTemporary : Perk
{
	private enum Mod { Delay, MaxDashes };

	private int _numDashes;

	private TimeSince _timeSinceRecharge;

	static PerkDashTemporary()
	{
		Register<PerkDashTemporary>(
			name: "Backup Dashes",
			imagePath: "textures/icons/vector/dash_temporary.png",
			description: level => $"+1 single-use dash every {(int)GetValue( level, Mod.Delay )}s",
			upgradeDescription: level => $"+1 single-use dash every {(int)GetValue( level - 1, Mod.Delay )}→{(int)GetValue( level, Mod.Delay )}s"
		);
	}

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

		ShouldUpdate = true;
		_timeSinceRecharge = 0f;

		DisplayCooldownColor = new Color( 0.5f, 0.5f, 1f, 0.75f );
	}

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

	}

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

		//var maxDashes = (int)GetValue( Level, Mod.MaxDashes );
		//if ( _numDashes < maxDashes )
		//{
			var delay = GetValue( Level, Mod.Delay );
			if ( _timeSinceRecharge > delay )
			{
				_numDashes++;
				Player.Modify( this, PlayerStat.NumTempDashes, _numDashes, ModifierType.Add );

				DisplayText = $"{_numDashes}";

				Manager.Instance.PlaySfxUI( "player.dash.recharge", pitch: 1f, volume: 0.3f );
				Player.ScaleHeight( amount: 1.5f, time: 0.04f );

				HighlightColor = new Color( 0.3f, 0.3f, 1f );
				HighlightDuration = 0.4f;
				HighlightOpacity = 4f;
				Highlight();

				DisplayCooldown = 0f;

				_timeSinceRecharge = 0f;
			}
			else
			{
				DisplayCooldown = Utils.Map( _timeSinceRecharge, 0f, delay, 0f, 1f );
			}
		//}
	}

	public override void OnDashStarted( Vector2 dir )
	{
		base.OnDashStarted( dir );

		if( _numDashes > 0 )
		{
			_numDashes--;

			DisplayText = _numDashes > 0 ? $"{_numDashes}" : " ";

			HighlightColor = new Color( 1f, 0.5f, 0.5f );
			HighlightDuration = 0.3f;
			HighlightOpacity = 3f;
			Highlight();

			Player.Modify( this, PlayerStat.NumTempDashes, _numDashes, ModifierType.Add );

			_timeSinceRecharge = 0f;
		}
	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.Delay:
			default:
				return 13 - 3 * level;
			case Mod.MaxDashes:
				return 1 + 2 * level;
		}
	}
}