XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Models;

namespace XFEEDToolBox.Core.Navigation;

/// <summary>Fuel presentation of the original game route; never creates or changes its waypoints.</summary>
public sealed record NavigationFuelOverlay(IReadOnlyList<long> DashedLegs,IReadOnlyList<long> SupplySites,long? RecommendedSupply)
{
    public static readonly NavigationFuelOverlay Empty=new([],[],null);
    public static NavigationFuelOverlay Build(PlayerState player,double reserve)
    {
        var route=player.Navigation.Route;
        var current=route.ToList().FindIndex(w=>w.SystemAddress==player.Navigation.CurrentSystemAddress);
        var ship=player.Ships.FirstOrDefault(s=>s.ShipId==player.CurrentShipId);
        var drive=NavigationPreviewBuilder.Drive(ship);
        var main=player.Navigation.FuelAt>player.StatusAt?player.Navigation.MainFuel:player.Status?.FuelMain??player.Navigation.MainFuel;
        if(current<0||drive is null||main is not {} fuel||!double.IsFinite(fuel))return Empty;
        var sites=NavigationPreviewBuilder.HasScoop(ship)?route.Skip(current).Where(w=>w.Scoopable).Select(w=>w.SystemAddress).ToArray():[];
        double? mass=ship?.UnladenMass is {} dry&&player.Status?.FuelReserve is {} aux&&player.CargoReliable?dry+fuel+aux+player.CargoCount:null;
        var dashed=new List<long>();long? lastReachableSupply=sites.Contains(route[current].SystemAddress)?route[current].SystemAddress:null,recommended=null;
        var outsideRange=false;
        for(var i=current+1;i<route.Count;i++)
        {
            var cost=drive.MaxFuelPerJump;
            if(mass is {} total)
            {
                try{cost=NavigationPreviewBuilder.EstimateFuel(drive,total,route[i-1].Position.DistanceTo(route[i].Position));}
                catch(InvalidOperationException){mass=null;}
            }
            fuel-=cost;if(mass is {} before)mass=before-cost;
            if(fuel<reserve)
            {
                if(!outsideRange)recommended=lastReachableSupply;
                outsideRange=true;
            }
            if(outsideRange)dashed.Add(route[i].SystemAddress);
            else if(sites.Contains(route[i].SystemAddress))lastReachableSupply=route[i].SystemAddress;
        }
        return new(dashed,sites,recommended);
    }
}