예제 #1
0
        // Update said predictions
        private void UpdateExitOrbit(Vessel nearObject, Vessel farObject)
        {
            if (!predictionsDrawn)
            {
                return;
            }
            if (!IsPatchedConicsAvailable)
            {
                HideExitOrbit();
                return;
            }

            Vector3   mapCamPos = ScaledSpace.ScaledToLocalSpace(MapView.MapCamera.transform.position);
            MapObject farTarget = MapView.MapCamera.target;
            Vector3   farTarPos = ScaledSpace.ScaledToLocalSpace(farTarget.transform.position);
            float     dirScalar = Vector3.Distance(mapCamPos, farTarPos);
            Vector3d  exitTraj  = ESLDBeacon.GetJumpVelOffset(nearObject, farObject);

            predictionOrbitRenderer.driver.referenceBody       = farObject.mainBody;
            predictionOrbitRenderer.driver.orbit.referenceBody = farObject.mainBody;
            predictionOrbitRenderer.driver.pos    = farObject.orbit.pos;
            predictionOrbitRenderer.celestialBody = farObject.mainBody;
            predictionOrbitRenderer.SetColor(Color.red);
            predictionOrbitDriver.orbit.UpdateFromStateVectors(farObject.orbit.pos, exitTraj, farObject.mainBody, Planetarium.GetUniversalTime());

            /* Direction indicator is broken/not required
             * float baseWidth = 20.0f;
             * double baseStart = 10;
             * double baseEnd = 50;
             * oDirection.transform.position = ScaledSpace.LocalToScaledSpace(far.transform.position);
             * if (dirScalar / 325000 > baseWidth) baseWidth = dirScalar / 325000f;
             * oDirection.SetWidth(baseWidth, 0.01f);
             * if (dirScalar / 650000 > baseStart) baseStart = dirScalar / 650000;
             * if (dirScalar / 130000 > baseEnd) baseEnd = dirScalar / 130000;
             * //          log.debug("Camera distance is " + dirScalar + " results: " + baseWidth + " " + baseStart + " " + baseEnd);
             * oDirection.SetPosition(0, Vector3d.zero + exitTraj.xzy.normalized * baseStart);
             * oDirection.SetPosition(1, exitTraj.xzy.normalized * baseEnd);
             * oDirection.transform.eulerAngles = Vector3d.zero;*/
        }
예제 #2
0
        // Show exit orbital predictions
        private void ShowExitOrbit(Vessel nearObject, Vessel farObject)
        {
            // Recenter map, save previous state.
            wasInMapView = MapView.MapIsEnabled;
            if (!MapView.MapIsEnabled)
            {
                MapView.EnterMapView();
            }
            MapObject mapObject = FindVesselBody(farObject);

            if ((UnityEngine.Object)mapObject != (UnityEngine.Object)null)
            {
                MapView.MapCamera.SetTarget(mapObject);
            }
            Vector3 mapCamPos = ScaledSpace.ScaledToLocalSpace(MapView.MapCamera.transform.position);
            Vector3 farTarPos = ScaledSpace.ScaledToLocalSpace(mapObject.transform.position);
            float   dirScalar = Vector3.Distance(mapCamPos, farTarPos);

            //log.Debug("Initializing, camera distance is " + dirScalar);
            if (!IsPatchedConicsAvailable)
            {
                HideExitOrbit();
            }
            else
            {
                predictionsDrawn = true;
                Vector3d vel = ESLDBeacon.GetJumpVelOffset(nearObject, farObject);
                if (predictionGameObject != null)
                {
                    Destroy(predictionGameObject);
                }

                predictionGameObject  = new GameObject("OrbitRendererGameObject");
                predictionOrbitDriver = predictionGameObject.AddComponent <OrbitDriver>();
                predictionOrbitDriver.orbit.referenceBody = farObject.mainBody;
                predictionOrbitDriver.orbit              = new Orbit();
                predictionOrbitDriver.referenceBody      = farObject.mainBody;
                predictionOrbitDriver.upperCamVsSmaRatio = 999999f;  // Took forever to figure this out - this sets at what zoom level the orbit appears.  Was causing it not to appear at small bodies.
                predictionOrbitDriver.lowerCamVsSmaRatio = 0.0001f;
                predictionOrbitDriver.orbit.UpdateFromStateVectors(farObject.orbit.pos, vel, farObject.mainBody, Planetarium.GetUniversalTime());
                predictionOrbitDriver.orbit.Init();
                Vector3d relativePositionAtUT = predictionOrbitDriver.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
                Vector3d orbitalVelocityAtUT  = predictionOrbitDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime());
                predictionOrbitDriver.orbit.h    = Vector3d.Cross(relativePositionAtUT, orbitalVelocityAtUT);
                predictionOrbitDriver.updateMode = OrbitDriver.UpdateMode.TRACK_Phys;
                predictionOrbitDriver.orbitColor = Color.red;
                predictionOrbitRenderer          = predictionGameObject.AddComponent <OrbitRenderer>();
                predictionOrbitRenderer.SetColor(Color.red);
                predictionOrbitRenderer.vessel             = vessel;
                predictionOrbitDriver.vessel               = vessel;
                predictionOrbitRenderer.upperCamVsSmaRatio = 999999f;
                predictionOrbitRenderer.lowerCamVsSmaRatio = 0.0001f;
                predictionOrbitRenderer.celestialBody      = farObject.mainBody;
                predictionOrbitRenderer.driver             = predictionOrbitDriver;
                predictionOrbitDriver.Renderer             = predictionOrbitRenderer;

                if (true)
                {
                    // This draws the full Patched Conics prediction.
                    predictionPatchedConicSolver      = predictionGameObject.AddComponent <PatchedConicSolver>();
                    predictionPatchedConicRenderer    = predictionGameObject.AddComponent <PatchedConicRenderer>();
                    predictionOrbitRenderer.drawIcons = OrbitRendererBase.DrawIcons.NONE;
                    predictionOrbitRenderer.drawMode  = OrbitRendererBase.DrawMode.OFF;
                }
#if false
                else
                {
                    // This draws just the first patch, similar to a Level 1 tracking station.
                    predictionOrbitRenderer.driver.drawOrbit = true;
                    predictionOrbitRenderer.drawIcons        = OrbitRenderer.DrawIcons.OBJ_PE_AP;
                    predictionOrbitRenderer.drawMode         = OrbitRenderer.DrawMode.REDRAW_AND_RECALCULATE;
                    predictionOrbitRenderer.enabled          = true;
                }
#endif
                base.StartCoroutine(NullOrbitDriverVessels());
                // Splash some color on it.

                // Directional indicator.

                /*
                 *  float baseWidth = 20.0f;
                 *  double baseStart = 10;
                 *  double baseEnd = 50;
                 *  oDirObj = new GameObject("Indicator");
                 *  oDirObj.layer = 10; // Map layer!
                 *  oDirection = oDirObj.AddComponent<LineRenderer>();
                 *  oDirection.useWorldSpace = false;
                 *  oOrigin = null;
                 *  foreach (Transform sstr in ScaledSpace.Instance.scaledSpaceTransforms)
                 *  {
                 *      if (sstr.name == far.mainBody.name)
                 *      {
                 *          oOrigin = sstr;
                 *          log.debug("Found origin: " + sstr.name);
                 *          break;
                 *      }
                 *  }
                 *  oDirection.transform.parent = oOrigin;
                 *  oDirection.transform.position = ScaledSpace.LocalToScaledSpace(far.transform.position);
                 *  oDirection.material = new Material(Shader.Find("Particles/Additive"));
                 *  oDirection.SetColors(Color.clear, Color.red);
                 *  if (dirScalar / 325000 > baseWidth) baseWidth = dirScalar / 325000f;
                 *  oDirection.SetWidth(baseWidth, 0.01f);
                 *  log.debug("Base Width set to " + baseWidth);
                 *  oDirection.SetVertexCount(2);
                 *  if (dirScalar / 650000 > baseStart) baseStart = dirScalar / 650000;
                 *  if (dirScalar / 130000 > baseEnd) baseEnd = dirScalar / 130000;
                 *  log.debug("Base Start set to " + baseStart);
                 *  log.debug("Base End set to " + baseEnd);
                 *  oDirection.SetPosition(0, Vector3d.zero + exitTraj.xzy.normalized * baseStart);
                 *  oDirection.SetPosition(1, exitTraj.xzy.normalized * baseEnd);
                 *  oDirection.enabled = true;
                 */
            }
        }
예제 #3
0
        public void WindowInterface(int GuiId)
        {
            GUILayout.BeginVertical();
            switch (displayMode)
            {
            case DisplayMode.Selection:
                if (farBeacons.Count <= 0 || nearBeacons.Count <= 0 || nearBeacon == null)
                {
                    GUILayout.Label("No active beacons found.");
                }
                else
                {
                    if (driftpenalty > 0f)
                    {
                        GUILayout.Label($"+{driftpenalty:F2}% due to Drift.");
                    }
                    if (nearBeacon.UnsafeTransfer)
                    {
                        if (vessel.GetCrewCount() > 0 || HCUPartFailures.Count > 0)
                        {
                            GUILayout.Label("WARNING: This beacon has no active Heisenkerb Compensator.");
                        }
                        if (vessel.GetCrewCount() > 0)
                        {
                            GUILayout.Label("Transfer will kill crew.");
                        }
                        if (HCUPartFailures.Count > 0)
                        {
                            GUILayout.Label("Some resources will destabilize.");
                        }
                    }
                    int i;
                    for (i = targetDetails.Count - 1; i >= 0; i--)
                    {
                        GUIStyle style = targetDetails[i].affordable ? (targetDetails[i].pathCheck.clear ? buttonHasFuel : buttonNoPath) : buttonNoFuel;
                        if (GUILayout.Button($"{targetDetails[i].vesselName} ({targetDetails[i].targetSOI}, {targetDetails[i].targetAlt:F1}km) | {targetDetails[i].tripCost:F2}", style))
                        {
                            if (targetDetails[i].affordable && targetDetails[i].pathCheck.clear)
                            {
                                selectedTarget = targetDetails[i];
                                if (nearBeacon.CarriesVelocity)
                                {
                                    ShowExitOrbit(vessel, selectedTarget.targetVessel);
                                }
                                displayMode = DisplayMode.Confirmation;
                            }
                            else
                            {
                                string message = "";
                                if (!targetDetails[i].affordable)
                                {
                                    int index = nearBeacon.JumpResources.FindIndex((ESLDJumpResource res) => (double)(res.ratio * targetDetails[i].tripCost) > res.fuelOnBoard);
                                    message = ((index >= 0) ? $"Cannot Warp: Origin beacon has {nearBeacon.JumpResources[index].fuelOnBoard:F2} of {nearBeacon.JumpResources[index].ratio * targetDetails[i].tripCost:F2} {nearBeacon.JumpResources[index].name} required to warp." : "Index error.");
                                }
                                else if (!targetDetails[i].pathCheck.clear)
                                {
                                    string arg = (targetDetails[i].pathCheck.blockingBody.name == "Mun" || targetDetails[i].pathCheck.blockingBody.name == "Sun") ? "the " : "";
                                    switch (targetDetails[i].pathCheck.blockReason)
                                    {
                                    case "Gravity":
                                        message = string.Format("Cannot Warp: Path of transfer intersects a high-gravity area around {1}{0}.", targetDetails[i].pathCheck.blockingBody.name, arg);
                                        break;

                                    case "Proximity":
                                        message = string.Format("Cannot Warp: Path of transfer passes too close to {1}{0}.", targetDetails[i].pathCheck.blockingBody.name, arg);
                                        break;

                                    case "Null":
                                        message = "Cannot Warp: No near beacon assigned. This is an error.";
                                        break;

                                    default:
                                        message = "Cannot Warp: Path is blocked.";
                                        break;
                                    }
                                }
                                ScreenMessages.PostScreenMessage(message, 5f, ScreenMessageStyle.UPPER_CENTER);
                            }
                        }
                    }
                    GUILayout.FlexibleSpace();
                    if (nearBeacons.Count > 1)
                    {
                        GUILayout.Label($"Current Beacon: {nearBeacon.Description} ({nearBeacon.Vessel.vesselName})");
                        if (GUILayout.Button($"Next Beacon ({currentBeaconIndex + 1} of {nearBeacons.Count})", buttonNeutral))
                        {
                            if (currentBeaconIndex + 1 < nearBeacons.Count)
                            {
                                nearBeacon = nearBeacons[currentBeaconIndex + 1];
                            }
                            else
                            {
                                nearBeacon = nearBeacons[0];
                            }
                        }
                    }
                    if (GUILayout.Button("Close Beacon Interface", buttonNeutral))
                    {
                        UnityEngine.Object.Destroy(this);
                    }
                }
                break;

            case DisplayMode.Confirmation:
            {
                if (driftpenalty > 0f)
                {
                    GUILayout.Label($"+{driftpenalty:F2}% due to Drift.");
                }
                if (nearBeacon.UnsafeTransfer)
                {
                    if (vessel.GetCrewCount() > 0 || HCUPartFailures.Count > 0)
                    {
                        GUILayout.Label("WARNING: This beacon has no active Heisenkerb Compensator.", labelNoFuel);
                    }
                    if (vessel.GetCrewCount() > 0)
                    {
                        GUILayout.Label("Transfer will kill crew.", labelNoFuel);
                    }
                    if (HCUPartFailures.Count > 0)
                    {
                        GUILayout.Label("These resources will destabilize in transit:", labelNoFuel);
                        for (int j = 0; j < HCUPartFailures.Count; j++)
                        {
                            GUILayout.Label(HCUPartFailures[j], labelNoFuel);
                        }
                    }
                }
                GUILayout.Label("Confirm Warp:");
                string str = "Base cost: ";
                for (int k = 0; k < nearBeacon.JumpResources.Count; k++)
                {
                    str += string.Format("{0:F2} {1}{2}", selectedTarget.tripCost * nearBeacon.JumpResources[k].ratio, nearBeacon.JumpResources[k].name, (k + 1 < nearBeacon.JumpResources.Count) ? ", " : "");
                }
                GUILayout.Label(str + ".");
                List <string> costModifiers = nearBeacon.GetCostModifiers(vessel, selectedTarget.targetVessel, tonnage, HCUParts.Keys.ToList());
                for (int l = 0; l < costModifiers.Count; l++)
                {
                    GUILayout.Label(costModifiers[l]);
                }
                GUILayout.Label($"Destination: {selectedTarget.targetVessel.mainBody.name} at {selectedTarget.targetAlt:F1}km.");
                GUILayout.Label($"Transfer will emerge within {selectedTarget.precision:N0}m of destination beacon.");
                if (selectedTarget.targetVessel.altitude - (double)selectedTarget.precision <= selectedTarget.targetVessel.mainBody.Radius * 0.10000000149011612 || selectedTarget.targetVessel.altitude - (double)selectedTarget.precision <= selectedTarget.targetVessel.mainBody.atmosphereDepth)
                {
                    GUILayout.Label($"Arrival area is very close to {selectedTarget.targetVessel.mainBody.name}.", labelNoFuel);
                }
                if (nearBeacon.CarriesVelocity)
                {
                    GUILayout.Label($"Velocity relative to exit beacon will be {(ESLDBeacon.GetJumpVelOffset(vessel, selectedTarget.targetVessel) - selectedTarget.targetVessel.orbit.vel).magnitude:F0}m/s.");
                }
                if (selectedTarget.returnFuelCheck && selectedTarget.returnBeacon != null)
                {
                    string str2 = (!selectedTarget.returnAffordable) ? "Destination beacon would need " : "Destination beacon can make return trip using ";
                    string str3 = "Destination beacon has ";
                    for (int m = 0; m < selectedTarget.returnBeacon.JumpResources.Count; m++)
                    {
                        str3 += string.Format("{0:F0} {1}{2}", selectedTarget.returnBeacon.JumpResources[m].fuelOnBoard, selectedTarget.returnBeacon.JumpResources[m].name, (m + 1 < selectedTarget.returnBeacon.JumpResources.Count) ? ", " : "");
                    }
                    for (int n = 0; n < selectedTarget.returnBeacon.JumpResources.Count; n++)
                    {
                        str2 += string.Format("{0:F2} {1}{2}", selectedTarget.returnCost * selectedTarget.returnBeacon.JumpResources[n].ratio, selectedTarget.returnBeacon.JumpResources[n].name, (n + 1 < selectedTarget.returnBeacon.JumpResources.Count) ? ", " : "");
                    }
                    GUILayout.Label(str3 + ".");
                    GUILayout.Label(str2 + (selectedTarget.returnAffordable ? "." : " for return trip using active beacons."), selectedTarget.returnAffordable ? labelHasFuel : labelNoFuel);
                }
                else
                {
                    GUILayout.Label("Destination beacon's fuel could not be checked.");
                }
                if (GUILayout.Button("Confirm and Warp", buttonNeutral))
                {
                    if (selectedTarget.pathCheck.clear)
                    {
                        HideExitOrbit();
                        nearBeacon.Warp(vessel, selectedTarget.targetVessel, selectedTarget.precision, HCUPartsList);
                        UnityEngine.Object.Destroy(this);
                    }
                    else
                    {
                        ScreenMessages.PostScreenMessage("Jump Failed!  Transfer path has become obstructed.", 5f, ScreenMessageStyle.UPPER_CENTER);
                    }
                }
                if (GUILayout.Button("Back", buttonNeutral))
                {
                    displayMode   = DisplayMode.Selection;
                    window.height = 0f;
                }
                break;
            }
            }
            GUILayout.EndVertical();
            GUI.DragWindow(/* new Rect(0f, 0f, 10000f, 20f) */);
        }
예제 #4
0
        public void WindowInterface(int GuiId)
        {
            GUILayout.BeginVertical();
            switch (displayMode)
            {
            case DisplayMode.Selection:
                if (farBeacons.Count <= 0 || nearBeacons.Count <= 0 || nearBeacon == null)
                {
                    GUILayout.Label("No active beacons found.");
                }
                else
                {
                    if (driftpenalty > 0)
                    {
                        GUILayout.Label(String.Format("+{0:F2}% due to Drift.", driftpenalty));
                    }
                    if (nearBeacon.UnsafeTransfer)
                    {
                        if (vessel.GetCrewCount() > 0 || HCUPartFailures.Count > 0)
                        {
                            GUILayout.Label("WARNING: This beacon has no active Heisenkerb Compensator.");
                        }
                        if (vessel.GetCrewCount() > 0)
                        {
                            GUILayout.Label("Transfer will kill crew.");
                        }
                        if (HCUPartFailures.Count > 0)
                        {
                            GUILayout.Label("Some resources will destabilize.");
                        }
                    }
                    for (int i = targetDetails.Count - 1; i >= 0; i--)
                    {
                        GUIStyle fuelstate = targetDetails[i].affordable ? (targetDetails[i].pathCheck.clear ? buttonHasFuel : buttonNoPath) : buttonNoFuel;
                        if (GUILayout.Button(String.Format("{0} ({1}, {2:F1}km) | {3:F2}", targetDetails[i].vesselName, targetDetails[i].targetSOI, targetDetails[i].targetAlt, targetDetails[i].tripCost), fuelstate))
                        {
                            if (targetDetails[i].affordable && targetDetails[i].pathCheck.clear)
                            {
                                selectedTarget = targetDetails[i];
                                if (nearBeacon.CarriesVelocity)
                                {
                                    ShowExitOrbit(vessel, selectedTarget.targetVessel);
                                }
                                displayMode = DisplayMode.Confirmation;
                            }
                            else
                            {
                                string messageToPost = "";
                                if (!targetDetails[i].affordable)
                                {
                                    int index = nearBeacon.JumpResources.FindIndex(res => res.ratio * targetDetails[i].tripCost > res.fuelOnBoard);
                                    if (index < 0)
                                    {
                                        messageToPost = "Index error.";
                                    }
                                    else
                                    {
                                        messageToPost = String.Format("Cannot Warp: Origin beacon has {0:F2} of {1:F2} {2} required to warp.", nearBeacon.JumpResources[index].fuelOnBoard, nearBeacon.JumpResources[index].ratio * targetDetails[i].tripCost, nearBeacon.JumpResources[index].name);
                                    }
                                }
                                else if (!targetDetails[i].pathCheck.clear)
                                {
                                    string thevar = (targetDetails[i].pathCheck.blockingBody.name == "Mun" || targetDetails[i].pathCheck.blockingBody.name == "Sun") ? "the " : "";
                                    switch (targetDetails[i].pathCheck.blockReason)
                                    {
                                    case "Gravity":
                                        messageToPost = String.Format("Cannot Warp: Path of transfer intersects a high-gravity area around {1}{0}.", targetDetails[i].pathCheck.blockingBody.name, thevar);
                                        break;

                                    case "Proximity":
                                        messageToPost = String.Format("Cannot Warp: Path of transfer passes too close to {1}{0}.", targetDetails[i].pathCheck.blockingBody.name, thevar);
                                        break;

                                    case "Null":
                                        messageToPost = "Cannot Warp: No near beacon assigned. This is an error.";
                                        break;

                                    default:
                                        messageToPost = "Cannot Warp: Path is blocked.";
                                        break;
                                    }
                                }
                                ScreenMessages.PostScreenMessage(messageToPost, 5.0f, ScreenMessageStyle.UPPER_CENTER);
                            }
                        }
                    }
                    GUILayout.FlexibleSpace();
                    if (nearBeacons.Count > 1)
                    {
                        GUILayout.Label(String.Format("Current Beacon: {0} ({1})", nearBeacon.Description, nearBeacon.Vessel.vesselName));
                        if (GUILayout.Button(String.Format("Next Beacon ({0} of {1})", (currentBeaconIndex + 1), nearBeacons.Count), buttonNeutral))
                        {
                            if (currentBeaconIndex + 1 < nearBeacons.Count)
                            {
                                nearBeacon = nearBeacons[currentBeaconIndex + 1];
                            }
                            else
                            {
                                nearBeacon = nearBeacons[0];
                            }
                        }
                    }
                    if (GUILayout.Button("Close Beacon Interface", buttonNeutral))
                    {
                        Destroy(this);
                    }
                }
                break;

            case DisplayMode.Confirmation:
                if (driftpenalty > 0)
                {
                    GUILayout.Label(String.Format("+{0:F2}% due to Drift.", driftpenalty));
                }
                if (nearBeacon.UnsafeTransfer)
                {
                    if (vessel.GetCrewCount() > 0 || HCUPartFailures.Count > 0)
                    {
                        GUILayout.Label("WARNING: This beacon has no active Heisenkerb Compensator.", labelNoFuel);
                    }
                    if (vessel.GetCrewCount() > 0)
                    {
                        GUILayout.Label("Transfer will kill crew.", labelNoFuel);
                    }
                    if (HCUPartFailures.Count > 0)
                    {
                        GUILayout.Label("These resources will destabilize in transit:", labelNoFuel);
                        for (int i = 0; i < HCUPartFailures.Count; i++)
                        {
                            GUILayout.Label(HCUPartFailures[i], labelNoFuel);
                        }
                    }
                }
                GUILayout.Label("Confirm Warp:");
                string costLabel = "Base cost: ";
                for (int i = 0; i < nearBeacon.JumpResources.Count; i++)
                {
                    costLabel += String.Format("{0:F2} {1}{2}", selectedTarget.tripCost * nearBeacon.JumpResources[i].ratio, nearBeacon.JumpResources[i].name, i + 1 < nearBeacon.JumpResources.Count ? ", " : "");
                }
                GUILayout.Label(costLabel + ".");
                List <string> modifiers = nearBeacon.GetCostModifiers(vessel, selectedTarget.targetVessel, tonnage, HCUParts.Keys.ToList());
                for (int i = 0; i < modifiers.Count; i++)
                {
                    GUILayout.Label(modifiers[i]);
                }
                GUILayout.Label(String.Format("Destination: {0} at {1:F1}km.", selectedTarget.targetVessel.mainBody.name, selectedTarget.targetAlt));

                GUILayout.Label(String.Format("Transfer will emerge within {0:N0}m of destination beacon.", selectedTarget.precision));
                if (selectedTarget.targetVessel.altitude - selectedTarget.precision <= selectedTarget.targetVessel.mainBody.Radius * 0.1f || selectedTarget.targetVessel.altitude - selectedTarget.precision <= selectedTarget.targetVessel.mainBody.atmosphereDepth)
                {
                    GUILayout.Label(String.Format("Arrival area is very close to {0}.", selectedTarget.targetVessel.mainBody.name), labelNoFuel);
                }
                if (nearBeacon.CarriesVelocity)
                {
                    Vector3d transferVelOffset = ESLDBeacon.GetJumpVelOffset(vessel, selectedTarget.targetVessel) - selectedTarget.targetVessel.orbit.vel;
                    GUILayout.Label(String.Format("Velocity relative to exit beacon will be {0:F0}m/s.", transferVelOffset.magnitude));
                }
                if (selectedTarget.returnFuelCheck && selectedTarget.returnBeacon != null)
                {
                    string fuelMessage;
                    if (selectedTarget.returnAffordable)
                    {
                        fuelMessage = "Destination beacon can make return trip using ";
                    }
                    else
                    {
                        fuelMessage = "Destination beacon would need ";
                    }

                    string fuelCount = "Destination beacon has ";
                    for (int i = 0; i < selectedTarget.returnBeacon.JumpResources.Count; i++)
                    {
                        fuelCount += String.Format("{0:F0} {1}{2}", selectedTarget.returnBeacon.JumpResources[i].fuelOnBoard, selectedTarget.returnBeacon.JumpResources[i].name, i + 1 < selectedTarget.returnBeacon.JumpResources.Count ? ", " : "");
                    }

                    for (int i = 0; i < selectedTarget.returnBeacon.JumpResources.Count; i++)
                    {
                        fuelMessage += String.Format("{0:F2} {1}{2}", selectedTarget.returnCost * selectedTarget.returnBeacon.JumpResources[i].ratio, selectedTarget.returnBeacon.JumpResources[i].name, i + 1 < selectedTarget.returnBeacon.JumpResources.Count ? ", " : "");
                    }

                    GUILayout.Label(fuelCount + ".");
                    GUILayout.Label(fuelMessage + (selectedTarget.returnAffordable ? "." : " for return trip using active beacons."), selectedTarget.returnAffordable ? labelHasFuel : labelNoFuel);
                }
                else
                {
                    GUILayout.Label("Destination beacon's fuel could not be checked.");
                }
                if (GUILayout.Button("Confirm and Warp", buttonNeutral))
                {
                    if (selectedTarget.pathCheck.clear)
                    {
                        HideExitOrbit();
                        nearBeacon.Warp(vessel, selectedTarget.targetVessel, selectedTarget.precision, HCUPartsList);
                        Destroy(this);
                    }
                    else
                    {
                        ScreenMessages.PostScreenMessage("Jump Failed!  Transfer path has become obstructed.", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                    }
                }
                if (GUILayout.Button("Back", buttonNeutral))
                {
                    displayMode   = DisplayMode.Selection;
                    window.height = 0;
                }
                break;
            }
            GUILayout.EndVertical();
            GUI.DragWindow(new Rect(0, 0, 10000, 20));
        }