PopRiotTarget.Routes.cs
using Sandbox;
using Sandbox.Navigation;
using System;
namespace PaintballBaddies;

public sealed partial class PopRiotTarget
{
    // Reuse the map's native navigation for room/stair connectivity, then lift
    // the route into collision-checked air lanes sized for the whole airframe.
    private bool TryArenaCourse()
    {
        var start=Scene.NavMesh.GetClosestPoint(WorldPosition-Vector3.Up*110,240);
        if(!start.HasValue)return false;
        var actors=Scene.GetAllComponents<PaintballCombatant>().Where(a=>a.AcceptHits).Select(a=>a.WorldPosition);
        var goals=ArenaMap.PatrolPoints(Scene).Concat(actors).Where(p=>(p-WorldPosition).WithZ(0).Length>300)
            .OrderBy(p=>MathF.Abs(MathF.Sin(p.x*.0031f+p.y*.0053f+Seed+routeNumber))).Take(7).ToArray();
        routeNumber++;
        foreach(var goal in goals)
        {
            var end=Scene.NavMesh.GetClosestPoint(goal,120);if(!end.HasValue)continue;
            var path=Scene.NavMesh.CalculatePath(new CalculatePathRequest{Start=start.Value,Target=end.Value});
            if(path.Status!=NavMeshPathStatus.Complete)continue;
            var samples=new List<Vector3>{start.Value};var prev=start.Value;
            foreach(var node in path.Points)
            {
                var delta=node.Position-prev;int count=Math.Max(1,(int)MathF.Ceiling(delta.Length/64));
                for(int i=1;i<=count;i++)samples.Add(Vector3.Lerp(prev,node.Position,(float)i/count));
                prev=node.Position;
            }
            if(samples.Count>90)continue;
            var layers=new List<(Vector3 point,int parent)[]>();
            layers.Add(new[]{(WorldPosition,-1)});
            bool failed=false;
            for(int i=0;i<samples.Count;i++)
            {
                var direction=(samples[Math.Min(i+1,samples.Count-1)]-samples[Math.Max(0,i-1)]).WithZ(0).Normal;
                var side=Vector3.Cross(Vector3.Up,direction);var layer=new List<(Vector3,int)>();
                foreach(float height in new[]{112f,156,76})
                foreach(float offset in new[]{0f,44,-44})
                {
                    var candidate=samples[i]+Vector3.Up*height+side*offset;
                    var previous=layers.Last();
                    for(int j=0;j<previous.Length;j++)
                        if(FlightLaneClear(previous[j].point,candidate)){layer.Add((candidate,j));break;}
                }
                if(layer.Count==0){failed=true;break;}layers.Add(layer.ToArray());
            }
            if(failed)continue;
            var route=new List<Vector3>();int index=0;
            for(int i=layers.Count-1;i>0;i--){route.Add(layers[i][index].point);index=layers[i][index].parent;}
            route.Reverse();flightPath.Clear();flightPath.Add(WorldPosition);flightPath.AddRange(route);
            nextWaypoint=1;touring=true;Anchor=flightPath.Last();return true;
        }
        return false;
    }
}