perks/PerkAutoAim.cs

A unique perk class that provides auto-aim behavior. It registers a perk named "Aimbot", increases player stats for auto-aim and bullet homing radius, and periodically snaps the player's aim toward the nearest enemy unless the player is berserk.

Networking
using System;
using Sandbox;

[Perk( Rarity.Unique, alwaysOfferDebug: false )]
public class PerkAutoAim : Perk
{
	private enum Mod { Time, Radius };

	private TimeSince _timeSinceCheck;

	static PerkAutoAim()
	{
		Register<PerkAutoAim>(
			name: "Aimbot",
			imagePath: "textures/icons/vector/auto_aim.png",
			description: level => $"Auto-aim at the nearest enemy\n+{GetValue( level, Mod.Radius, true ).ToString("0.##")}m bullet homing range",
			upgradeDescription: level => $"Auto-aim at the nearest enemy\n+{GetValue( level, Mod.Radius, true ).ToString( "0.##" )}m bullet homing range"
		);
	}

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

		ShouldUpdate = true;
	}

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

		Player.Modify( this, PlayerStat.AutoAim, 1f, ModifierType.Add );
		Player.Modify( this, PlayerStat.BulletHomingRadius, GetValue( Level, Mod.Radius ), ModifierType.Add );
		Player.Modify( this, PlayerStat.BulletHomingRadiusDisplay, GetValue( Level, Mod.Radius, true ), ModifierType.Add );
	}

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

		if ( Player.Stats[PlayerStat.IsBerserk] > 0f )
			return;

		if ( _timeSinceCheck > 0.2f )
		{
			var closestEnemy = Manager.Instance.GetClosestEnemy( Player.Position2D, onlyCountsAsKill: false );
			if ( closestEnemy.IsValid() )
			{
				var dir = (closestEnemy.Position2D - Player.Position2D).Normal;
				Player.AimDir = dir;
			}

			_timeSinceCheck = 0f;
		}
	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.Radius:
			default:
				return 1.0f * (isPercent ? 1f : Utils.Meter2Unit);
		}
	}
}