perks/PerkRestartChoices.cs

A Perk class named PerkRestartChoices that, when started, removes all other perks from the player, sums their levels into a choice count, refunds that many perk points, plays a UI sound, posts a local chat message about the respec, and increments a level counter used for curse/choice logic on higher difficulties.

Networking
using System;
using Sandbox;

[Perk( Rarity.Unique, includedAtStart: false, locked: true, alwaysOfferDebug: false )]
public class PerkRestartChoices : Perk
{
	static PerkRestartChoices()
	{
		Register<PerkRestartChoices>(
			name: "Full Reboot",
			imagePath: "textures/icons/vector/restart_choices.png",
			description: level => $"Remove all perks and\nmake new choices instead"
		);
	}

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

		int numChoices = 0;
		for ( int i = Player.Perks.Count - 1; i >= 0; i-- )
		{
			var pair = Player.Perks.ElementAt( i );
			Perk perk = pair.Value;

			if ( perk is PerkRestartChoices )
				continue;

			numChoices += perk.Level;
			Player.RemovePerk( TypeLibrary.GetType( perk.GetType() ) );
		}

		// todo: should un-banish your banished perks too?

		Player.AddPerkPoints( numChoices );

		Manager.Instance.PlaySfxUI( "reroll", pitch: 0.8f, volume: 0.95f );

		if( numChoices > 0 )
			Manager.Instance.Chat.AddLocalChatMessage( $"{Perk.GetRichTextToken( GetType() )} Respec {numChoices} {(numChoices > 1 ? "perks" : "perk")}", from: "" );

		if ( Manager.Instance.Difficulty >= Manager.Instance.FirstDifficultyWithoutPauseChoosing )
			Player.CurrLevelsUntilCurseChoice += numChoices;
	}

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

	}
}