A legendary perk class 'PerkDashRechargeFree' that grants a temporary free dash window after a dash recharge. It tracks timers to show a UI window with flashing color/scale, grants a temporary dash (NumTempDashes) when activated, closes the window on dash use or timeout, and plays a UI sound when the window closes.
using System;
[Perk( Rarity.Legendary, locked: true, alwaysOfferDebug: false )]
public class PerkDashRechargeFree : Perk
{
private float _timer;
private float _pulseTimer;
private bool _windowActive;
static PerkDashRechargeFree()
{
Register<PerkDashRechargeFree>(
name: "Second Wind",
imagePath: "textures/icons/vector/dash_recharge_free.png",
description: level => $"After a dash recharges,\nyou have {GetDuration( level ).ToString("0.##")}s to dash for free",
upgradeDescription: level => $"After a dash recharges, you have\n{GetDuration( level - 1 ).ToString( "0.##" )}→{GetDuration( level ).ToString( "0.##" )}s to dash for free"
);
}
public override void Start()
{
base.Start();
}
public override void Update( float dt )
{
base.Update( dt );
_timer += dt;
_pulseTimer += RealTime.Delta;
var duration = GetDuration( Level );
if ( _timer >= duration )
{
CloseWindow();
return;
}
DisplayCooldown = Utils.Map( _timer, 0f, duration, 1f, 0f );
// Flash between cyan and yellow
float flash = 0.5f + 0.5f * Utils.FastSin( _pulseTimer * MathF.PI * 12f );
DisplayCooldownColor = Color.Lerp( new Color( 0.2f, 0.9f, 1f, 3f ), new Color( 1f, 0.95f, 0.2f, 3f ), flash );
// Pulse icon scale
IconScale = 1f + 0.1f * MathF.Abs( Utils.FastSin( _pulseTimer * MathF.PI * 5f ) );
}
public override void OnDashRecharged()
{
base.OnDashRecharged();
_timer = 0f;
_pulseTimer = 0f;
ShouldUpdate = true;
if ( !_windowActive )
{
_windowActive = true;
Player.Modify( this, PlayerStat.NumTempDashes, 1, ModifierType.Add );
}
IconScale = 1.3f;
HighlightColor = new Color( 0.2f, 0.9f, 1f );
HighlightDuration = 0.4f;
HighlightOpacity = 4f;
Highlight();
DisplayCooldownColor = new Color( 0.2f, 0.9f, 1f, 3f );
}
public override void OnDashStarted( Vector2 dir )
{
base.OnDashStarted( dir );
if ( _windowActive )
{
CloseWindow();
}
}
private void CloseWindow()
{
if ( !_windowActive )
return;
_windowActive = false;
ShouldUpdate = false;
DisplayCooldown = 0f;
Player.Modify( this, PlayerStat.NumTempDashes, 0, ModifierType.Add );
Manager.Instance.PlaySfxUI( "error2", pitch: 0.25f, volume: 0.55f );
}
private static float GetDuration( int level )
{
return level * 0.5f;
}
}