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;

public sealed record FlightFuelBudget(double NextJump,double UntilRefuel,bool UsesMassReference);
public static class NavigationFuelBudget
{
    public static FlightFuelBudget Calculate(PlayerState player,ShipRecord ship,FsdReference drive,double fuel,double reserve)
    {
        var route=player.Navigation.Route;
        var current=route.ToList().FindIndex(w=>w.SystemAddress==player.Navigation.CurrentSystemAddress);
        var legs=new List<double>();
        if(current>=0)for(var i=current+1;i<route.Count;i++)
        {
            legs.Add(route[i-1].Position.DistanceTo(route[i].Position));
            if(route[i].Scoopable&&NavigationPreviewBuilder.HasScoop(ship))break;
        }
        var maximum=drive.MaxFuelPerJump;
        var fallback=new FlightFuelBudget(maximum,maximum*Math.Max(1,legs.Count)+reserve+.25,false);
        if(legs.Count==0||!player.CargoReliable||ship.UnladenMass is not >0||player.Status?.FuelReserve is not {} auxiliary||!double.IsFinite(fuel))return fallback;
        var dry=ship.UnladenMass.Value+player.CargoCount+auxiliary;
        var carried=fuel;double first=maximum,budget=fallback.UntilRefuel;
        for(var iteration=0;iteration<12;iteration++)
        {
            try
            {
                // Do not subtract earlier burns from mass: later costs stay conservative.
                var costs=legs.Select(distance=>Math.Min(maximum,NavigationPreviewBuilder.EstimateFuel(drive,dry+carried,distance)*1.04+.01)).ToArray();
                first=costs[0];budget=costs.Sum()+reserve+.25;
                if(budget<=carried+.001)return new(first,budget,true);
                carried=budget;
                if(ship.FuelMain is {} capacity&&carried>capacity)return fallback;
            }
            catch(InvalidOperationException){return fallback;}
        }
        return fallback;
    }
}