perks/PerkSelfDmgDash.cs

A Mythic perk class named PerkSelfDmgDash that grants a chance to perform a free dash when the player is hit. It defines perk metadata, visual highlight settings, a level-based chance calculation, and triggers a free dash in OnHit when conditions are met.

Reflection
using System;
using Sandbox;

[Perk( Rarity.Mythic, includedAtStart: false, locked: true, minUnlocksReq: 5, alwaysOfferDebug: false )]
public class PerkSelfDmgDash : Perk
{
	private enum Mod { Chance };

	static PerkSelfDmgDash()
	{
		Register<PerkSelfDmgDash>(
			name: "Pain Dash",
			imagePath: "textures/icons/vector/self_dmg_dash.png",
			description: level => $"{(int)GetValue( level, Mod.Chance, true )}% chance to dash for free\nwhen you take dmg",
			upgradeDescription: level => $"{(int)GetValue( level - 1, Mod.Chance, true )}%→{(int)GetValue( level, Mod.Chance, true )}% chance to dash for free when you take dmg"
		);
	}

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

		HighlightColor = new Color( 0.75f, 0f, 1f );
		HighlightDuration = 0.25f;
		HighlightOpacity = 2f;
	}

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

	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.Chance:
			default:
				return isPercent
					? 10f + 5f * level
					: 0.10f + 0.05f * level;
		}
	}

	public override void OnHit( float amount, DamageType damageType, bool isSelfInflicted, Vector2 dir, float force, Enemy enemySource, EnemyType enemyType, float previousHealth )
	{
		base.OnHit( amount, damageType, isSelfInflicted, dir, force, enemySource, enemyType, previousHealth );

		//if ( !isSelfDmg )
		//	return;

		if ( Player.IsDead )
			return;

		if ( Game.Random.Float( 0f, 1f ) > GetValue( Level, Mod.Chance ) )
			return;

		if ( Player.IsInTheAir )
			return;

		var moveVector = Player.MoveVector;
		var velocity = Player.Velocity;
		Vector2 dashDir = moveVector.LengthSquared > 0f ? moveVector : (velocity.LengthSquared > 0.1f ? velocity.Normal : Player.FacingDir);
		Player.Dash( dashDir, isFree: true );

		Highlight();
	}
}