perks/PerkDodgeClipBonus.cs

A game perk class named PerkDodgeClipBonus that grants a temporary clip damage bonus when the player dodges. It accumulates bonus damage on dodge, shows a display text and highlight, applies the accumulated bonus to Player.Stats[PlayerStat.ClipDamageBonus] when reloading finishes, and clears it when removed.

Reflection
using System;
using Sandbox;

[Perk( Rarity.Epic, includedAtStart: false, locked: true, minUnlocksReq: 1, alwaysOfferDebug: false )]
public class PerkDodgeClipBonus : Perk
{
	private enum Mod { BonusDmg };

	private float _currBonus;

	static PerkDodgeClipBonus()
	{
		Register<PerkDodgeClipBonus>(
			name: "Deadly Reflexes",
			imagePath: "textures/icons/vector/dodge_clip_bonus.png",
			description: level => $"bullet-icons in your next clip get\n+{GetValue( level, Mod.BonusDmg ).ToString( "0.#" )} dmg when you dodge",
			upgradeDescription: level => $"bullet-icons in your next clip get\n+{GetValue( level - 1, Mod.BonusDmg ).ToString("0.#")}→{GetValue( level, Mod.BonusDmg ).ToString("0.#")} dmg when you dodge"
		);
	}

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

		HighlightColor = new Color( 0.7f, 1f, 0.7f );
		HighlightDuration = 0.2f;
		HighlightOpacity = 1.5f;
	}

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

	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.BonusDmg:
			default:
				return 0.5f * level;
		}
	}

	public override void OnDodged( float damage, DamageType damageType, Vector2 dir, Enemy enemySource )
	{
		base.OnDodged( damage, damageType, dir, enemySource );

		_currBonus += GetValue( Level, Mod.BonusDmg );
		RefreshDisplayText();

		Highlight();
	}

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

		RefreshDisplayText();
	}

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

		Player.Stats[PlayerStat.ClipDamageBonus] += _currBonus;

		_currBonus = 0f;

		//RefreshDisplayText();
	}

	void RefreshDisplayText()
	{
		DisplayText = _currBonus > 0f ? string.Format( "+{0:0.0}", _currBonus ) : " ";
		//DisplayText = Player.Stats[PlayerStat.ClipDamageBonus] > 0f ? string.Format( "+{0:0.0}", Player.Stats[PlayerStat.ClipDamageBonus] ) : " ";
	}

	public override void Remove( bool restart = false )
	{
		base.Remove( restart );

		Player.Stats[PlayerStat.ClipDamageBonus] = 0f;
	}
}