Weapons/TripmineWeapon.cs
using Sandbox.Rendering;
using Sandbox.Utility;

public class TripmineWeapon : BaseBulletWeapon
{
	bool canPlace = false;
	Transform placeTransform;
	GameObject placeGameObject;

	public override bool CanShoot()
	{
		if ( !canPlace ) return false;
		if ( !placeGameObject.IsValid() ) return false;

		return base.CanShoot();
	}

	public override void OnControl( Player player )
	{
		base.OnControl( player );

		canPlace = false;

		var tr = Scene.Trace.Ray( player.EyeTransform.ForwardRay, 128 )
						.IgnoreGameObjectHierarchy( player.GameObject )
						.WithoutTags( "player" )
						.Run();


		placeTransform = new Transform( tr.EndPosition, Rotation.LookAt( player.EyeTransform.Backward ) );

		if ( tr.Hit )
		{
			canPlace = true;
			placeTransform = new Transform( tr.EndPosition, Rotation.LookAt( tr.Normal ) );
			placeGameObject = tr.GameObject;
		}

		canPlace = tr.Hit;

		var mat = canPlace ? Material.Load( "materials/utility/placementgood.vmat" ) : Material.Load( "materials/utility/placementbad.vmat" );

		DebugOverlay.GameObject( GameObject.GetPrefab( "weapons/tripmine/placed_tripmine.prefab" ), transform: placeTransform, materialOveride: mat, castShadows: false );

		if ( Input.Pressed( "attack1" ) )
		{
			ShootBullet( player );
		}
	}

	public void ShootBullet( Player player )
	{
		if ( !CanShoot() )
			return;

		if ( !TakeAmmo( 1 ) )
		{
			DryFire();
			return;
		}

		CreateMine( player, placeGameObject, placeTransform.Position, placeTransform.Rotation );

		if ( !HasAmmo() )
		{
			SwitchAway();
			GameObject.Destroy();
		}

	}

	[Rpc.Host]
	private void CreateMine( Player player, GameObject parent, Vector3 worldPosition, Rotation worldRotation )
	{
		if ( !player.IsValid() )
			return;

		var prefab = GameObject.GetPrefab( "weapons/tripmine/placed_tripmine.prefab" );
		Assert.True( prefab.IsValid(), "Couldn't find placed tripmine prefab" );

		var go = prefab.Clone( new CloneConfig()
		{
			Parent = parent,
			StartEnabled = false
		} );

		go.WorldTransform = new Transform( worldPosition, worldRotation );
		go.Enabled = true;

		var mine = go.GetComponent<TripminePlaced>();
		Assert.True( mine.IsValid(), "TripminePlaced not on tripmine prefab" );
		mine.Instigator = player.PlayerData;

		go.NetworkSpawn();
	}

	public override void DrawCrosshair( HudPainter hud, Vector2 center )
	{
		var tss = TimeSinceShoot.Relative.Remap( 0, 0.8f, 1, 0 );

		var len = 8 + Easing.BounceIn( tss ) * 128;

		Color color = !CanShoot() ? UI.CrosshairInactive : UI.CrosshairActive;
		var rect = new Rect( center - len * 0.5f, len );

		hud.DrawRect( rect, Color.Transparent, cornerRadius: new Vector4( 512 ), borderWidth: new Vector4( 2 ), borderColor: color );
	}
}