Dev/AiwalkerUtility.cs
using Opium.AI;
using Sandbox;

public sealed class AiWalkerUtility : Component
{
	[Property] private List<GameObject> Selection { get; set; } = new();
	[RequireComponent] CameraComponent Camera { get; set; }

	Ray ScreenRay => Camera.ScreenPixelToRay( Mouse.Position );

	/// <summary>
	/// Walk to a selected point
	/// </summary>
	/// <param name="pos"></param>
	void WalkTo( Vector3 pos )
	{
		foreach ( var obj in Selection )
		{
			if ( obj.Components.Get<Agent>() is { } agent )
			{
				agent.WalkTo( pos, () => WalkFinished( agent ) );
			}
		}
	}

	private void WalkFinished( Agent agent )
	{
		//
	}

	private bool IsValidObject( GameObject obj )
	{
		if ( obj.Tags.Has( "agent" ) ) return true;
		return false;
	}

	protected override void OnUpdate()
	{
		var trace = Scene.Trace.Ray( ScreenRay, distance: 50000000f )
			.Size( 2f )
			.Run();

		foreach ( var obj in Selection )
		{
			Gizmo.Draw.ScreenText( $"{obj}", Camera.PointToScreenPixels( obj.Transform.Position ) );
		}

		if ( Input.Down( "Attack1" ) )
		{
			if ( !trace.Hit )
			{
				Selection.Clear();
				return;
			}

			if ( IsValidObject( trace.GameObject ) )
			{
				Selection.Add( trace.GameObject.Root );
			}
			else
			{
				Selection.Clear();
			}
		}

		if ( Input.Down( "Attack2" ) )
		{
			WalkTo( trace.HitPosition );
		}
	}
}