perks/PerkWish.cs

A unique perk class 'PerkWish' that lets a player type a perk name in chat to receive that perk once. It handles registration, activation on level increase, chat parsing to find a perk type, giving the perk item to the player, visual highlight and sound feedback.

Networking
using System;
using Sandbox;

[Perk( Rarity.Unique, alwaysOfferDebug: false )]
public class PerkWish : Perk
{
	private bool _isActive;

	public override float ImportanceMultiplier => 0.5f;

	static PerkWish()
	{
		Register<PerkWish>(
			name: "Genie Lamp",
			imagePath: "textures/icons/vector/wish.png",
			description: level => $"Wish for any perk\nby typing the name in chat",
			upgradeDescription: level => $"Wish for any perk\nby typing the name in chat"
		);
	}

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

		HighlightColor = new Color( 0.6f, 0.6f, 1f );
		HighlightDuration = 0.9f;
		HighlightOpacity = 3f;
	}

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

		_isActive = true;
		ShouldUpdate = true;
		DisplayCooldown = 1f;

		// todo: get a random (Common?) curse too

		Manager.Instance.Chat.AddLocalChatMessage( $"{Perk.GetRichTextToken( GetType() )} Type a perk name to wish for it", from: "" );
	}

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

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

		DisplayCooldownColor = Color.Lerp( new Color( 0f, 0f, 0.5f ), new Color( 0.5f, 0.5f, 1f ), 0.5f + Utils.FastSin( Time.Now * 16f ) * 0.5f );
	}

	public override void OnSayChat( string message )
	{
		base.OnSayChat( message );

		if ( !_isActive )
			return;

		var type = Perk.FindTypeByLooseDisplayName( message );
		if ( type is null )
			return;

		Player.GivePerkItem( type, dir: Utils.GetRandomVectorInCone( -Player.FacingDir ) );
		_isActive = false;
		Highlight();
		DisplayCooldown = 0f;
		ShouldUpdate = false;

		Manager.Instance.PlaySfxNearbyRpc( "heal", Player.Position2D, pitch: Game.Random.Float( 0.7f, 0.75f ), volume: 1f, maxDist: 300f );

		Manager.Instance.Chat.AddLocalChatMessage( $"{Perk.GetRichTextToken( GetType() )} You wished for: {Perk.GetRichTextNameToken( type.TargetType )} {Perk.GetRichTextToken( type )}", from: "" );
	}
}