perks/PerkZoomOut.cs

An Epic rarity perk called PerkZoomOut (Spyglass). It modifies player stats when refreshed: increases camera distance and decreases XP coin attraction range based on perk level, and registers UI name, icon, and descriptions for display.

using System;
using Sandbox;

[Perk( Rarity.Epic, alwaysOfferDebug: false )]
public class PerkZoomOut : Perk
{
	private enum Mod { CoinAttractRange, CameraDistance };

	static PerkZoomOut()
	{
		Register<PerkZoomOut>(
			name: "Spyglass",
			imagePath: "textures/icons/vector/zoom_out.png",
			description: level => $"+{GetValue( level, Mod.CameraDistance, true )}% camera distance\n-{GetValue( level, Mod.CoinAttractRange, true )}% xp coin attract range",
			upgradeDescription: level => $"+{GetValue( level - 1, Mod.CameraDistance, true )}%→{GetValue( level, Mod.CameraDistance, true )}% camera distance\n-{GetValue( level - 1, Mod.CoinAttractRange, true )}%→-{GetValue( level, Mod.CoinAttractRange, true )}% xp coin attract range"
		);
	}

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

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

		Player.Modify( this, PlayerStat.CoinAttractRange, GetValue( Level, Mod.CoinAttractRange ), ModifierType.Mult );
		Player.Modify( this, PlayerStat.CameraDistance, GetValue( Level, Mod.CameraDistance ), ModifierType.Mult );
	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.CoinAttractRange:
			default:
				return isPercent
					? 15f * level
					: 1f - 0.15f * level;
			case Mod.CameraDistance:
				return isPercent
					? 10f * level
					: 1f + 0.10f * level;
		}
	}
}