perks/CurseTeleport.cs

A Unique curse perk that occasionally teleports the player to a random location inside game bounds. It schedules a random delay between MinTime and MaxTime, counts up in Update, and triggers Player.Teleport plus some visual highlight and icon randomization.

NetworkingFile Access
using System;
using Sandbox;

[Perk( Rarity.Unique, curse: true, alwaysOfferDebug: false )]
public class CurseTeleport : Perk
{
	private enum Mod { MinTime, MaxTime };

	private float _timer;
	private float _currDelay;

	static CurseTeleport()
	{
		Register<CurseTeleport>(
			name: "Teleportitis",
			imagePath: "textures/icons/vector/curse_teleport.png",
			description: level => $"Occasionally teleport\nto a random location"
		);
	}

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

		ShouldUpdate = true;
		HighlightColor = new Color( 0.5f, 0f, 1f );
		HighlightDuration = 0.75f;
		HighlightOpacity = 3f;
	}

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

		_currDelay = Game.Random.Float( GetValue( Level, Mod.MinTime ), GetValue( Level, Mod.MaxTime ) );
	}

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

		_timer += dt;
		if ( _timer > _currDelay && !Player.IsInTheAir )
			Teleport();
	}

	public void Teleport()
	{
		Vector2 pos = new Vector2( Game.Random.Float( Manager.Instance.BOUNDS_MIN.x, Manager.Instance.BOUNDS_MAX.x ), Game.Random.Float( Manager.Instance.BOUNDS_MIN.y, Manager.Instance.BOUNDS_MAX.y ) );
		Player.Teleport( pos );

		_timer = 0f;
		_currDelay = Game.Random.Float( GetValue(Level, Mod.MinTime), GetValue( Level, Mod.MaxTime ) );

		Highlight();

		IconScale = Game.Random.Float( 1.2f, 1.3f );
		IconAngleOffset = Game.Random.Float( 10f, 20f ) * (Game.Random.Int( 0, 1 ) == 0 ? -1f : 1f);
	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.MinTime:
			default:
				return 1f;
			case Mod.MaxTime:
				return 36f;
		}
	}
}