// Shows a list of all available target-vessels and returns true, if the player has selected one:
        public bool DisplayList()
        {
            GUILayout.Label("<size=14><b>Target:</b></size>");
            scrollPos = GUILayout.BeginScrollView(scrollPos, GUI.scrollStyle);
            string green = "#00FF00";
            string red   = "#FF0000";

            // Build a list with all valid vessels:
            List <Vessel> validTargets = new List <Vessel>();

            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                if (!TargetVessel.IsValidTarget(vessel))
                {
                    continue;
                }
                validTargets.Add(vessel);
            }
            if (selectedIndex >= validTargets.Count)
            {
                selectedIndex = -1;
                targetVessel  = null;
            }

            if (validTargets.Count == 0)
            {
                // No valid targest available:
                GUILayout.Label("No valid targets in orbit.");
            }
            else
            {
                // Show list with all possible vessels:
                List <GUIContent> contents        = new List <GUIContent>();
                List <int>        filteredIndices = new List <int>(); // Target-vessels which fall out of the defined filters will get noted here.
                int index = 0;
                foreach (Vessel vessel in validTargets)
                {
                    bool filterThisTarget = false;
                    if (!TargetVessel.IsValidTarget(vessel))
                    {
                        continue;
                    }
                    List <string> descriptions = new List <string>();
                    descriptions.Add("<color=#F9FA86><b>" + vessel.vesselName + "</b></color><color=#FFFFFF>");

                    // Orbital-Parameters:
                    descriptions.Add("<b>Apoapsis:</b> " + GUI.FormatAltitude(vessel.orbit.ApA) + ", <b>Periapsis:</b> " + GUI.FormatAltitude(vessel.orbit.PeA) + ", <b>MET:</b> " + GUI.FormatDuration(vessel.missionTime));

                    // Docking-Port Types:
                    List <string> dockingPortsTranslated = new List <string>();
                    foreach (string dockingPortType in TargetVessel.GetVesselDockingPortTypes(vessel))
                    {
                        dockingPortsTranslated.Add(TargetVessel.TranslateDockingPortName(dockingPortType));
                    }
                    if (dockingPortsTranslated.Count > 0)
                    {
                        descriptions.Add("<b>Docking-Ports:</b> " + string.Join(", ", dockingPortsTranslated.ToArray()));
                    }

                    // Resources:
                    double capacity = 0;
                    foreach (PayloadResource availableResource in TargetVessel.GetFreeResourcesCapacities(vessel))
                    {
                        capacity += availableResource.amount * availableResource.mass;
                    }
                    if (capacity > 0)
                    {
                        descriptions.Add("<b>Resource Capacity:</b> " + capacity.ToString("#,##0.00t"));
                    }

                    // Crew:
                    int seats = TargetVessel.GetCrewCapacity(vessel);
                    int crew  = TargetVessel.GetCrew(vessel).Count;
                    if (seats > 0)
                    {
                        descriptions.Add("<b>Crew:</b> " + crew.ToString() + "/" + seats.ToString());
                    }

                    // Maybe apply additional filters and show their attributes:
                    List <string> filterAttributes = new List <string>();;
                    if (filterVesselType != null)
                    {
                        bool   isValidType = vessel.vesselType == (VesselType)filterVesselType;
                        string color       = isValidType ? green : red;
                        filterAttributes.Add("<b>Type:</b> <color=" + color + ">" + vessel.vesselType.ToString() + "</color>");
                        if (!isValidType)
                        {
                            filterThisTarget = true;
                        }
                    }
                    if (filterHasCrewTrait != null)
                    {
                        int traitCount    = TargetVessel.GetCrewCountWithTrait(vessel, filterHasCrewTrait);
                        int requiredCount = 1;
                        if (filterHasCrewTraitCount != null)
                        {
                            requiredCount = (int)filterHasCrewTraitCount;
                        }
                        string color = traitCount >= requiredCount ? green : red;
                        filterAttributes.Add("<b>" + filterHasCrewTrait + "s:</b> <color=" + color + ">" + traitCount.ToString() + "/" + requiredCount.ToString() + "</color>");
                        if (traitCount < requiredCount)
                        {
                            filterThisTarget = true;
                        }
                    }
                    if (filterAttributes.Count > 0)
                    {
                        descriptions.Add(String.Join(" ", filterAttributes.ToArray()));
                    }

                    contents.Add(new GUIContent(String.Join("\n", descriptions.ToArray()) + "</color>"));
                    if (filterThisTarget)
                    {
                        filteredIndices.Add(index);                   // If there were filters, which did not match, we still show the target, but don't allow to select it.
                    }
                    index++;
                }

                int newSelection = GUILayout.SelectionGrid(selectedIndex, contents.ToArray(), 1, GUI.selectionGridStyle);
                if (newSelection >= 0 && !filteredIndices.Contains(newSelection))
                {
                    // The player has selected a payload:
                    selectedIndex = newSelection;
                    targetVessel  = validTargets[selectedIndex];
                }
            }
            GUILayout.EndScrollView();
            return(targetVessel != null);
        }
Example #2
0
        private static bool DisplayInner()
        {
            // Payload selection:
            if (payloadShipSelector == null)
            {
                payloadShipSelector = new GUIPayloadShipSelector();
            }
            if (payloadShipSelector.payload == null)
            {
                payloadShipSelector.DisplayList();
                return(false);
            }
            if (payloadShipSelector.DisplaySelected())
            {
                targetVesselSelector   = null;
                missionProfileSelector = null;
                crewTransferSelector   = null;
                flagSelector           = null;
                return(false);
            }
            currentCost += payloadShipSelector.payload.template.totalCost;
            var    dryMass           = payloadShipSelector.payload.GetDryMass();
            double totalMass         = payloadShipSelector.payload.template.totalMass;
            var    engineersRequired = (int)Math.Ceiling(Math.Log(Math.Ceiling(dryMass / 10)) / Math.Log(2)) + 1; // One engineer can construct up to 10t, each additional engineer doubles that number

            // Target (space-dock) selection:
            if (targetVesselSelector == null)
            {
                targetVesselSelector = new GUITargetVesselSelector();
                targetVesselSelector.filterVesselType        = VesselType.Station;
                targetVesselSelector.filterHasCrewTrait      = "Engineer"; // There does not seem to be an enum for this.
                targetVesselSelector.filterHasCrewTraitCount = engineersRequired;
            }
            if (targetVesselSelector.targetVessel == null)
            {
                targetVesselSelector.DisplayList();
                return(false);
            }
            if (targetVesselSelector.DisplaySelected())
            {
                missionProfileSelector = null;
                crewTransferSelector   = null;
                flagSelector           = null;
                return(false);
            }

            // Mission-Profile selection:
            if (missionProfileSelector == null)
            {
                missionProfileSelector = new GUIMissionProfileSelector();
                missionProfileSelector.filterAltitude         = targetVesselSelector.targetVessel.orbit.ApA;
                missionProfileSelector.filterBody             = targetVesselSelector.targetVessel.orbit.referenceBody;
                missionProfileSelector.filterDockingPortTypes = TargetVessel.GetVesselDockingPortTypes(targetVesselSelector.targetVessel);
                missionProfileSelector.filterMissionType      = MissionProfileType.TRANSPORT;
                shipName = payloadShipSelector.payload.template.shipName;
            }
            if (missionProfileSelector.selectedProfile == null)
            {
                missionProfileSelector.DisplayList();
                return(false);
            }
            if (missionProfileSelector.DisplaySelected())
            {
                crewTransferSelector = null;
                flagSelector         = null;
                return(false);
            }

            if (crewTransferSelector == null)
            {
                crewTransferSelector = new GUICrewTransferSelector(payloadShipSelector.payload, missionProfileSelector.selectedProfile);
            }
            if (flagSelector == null)
            {
                flagSelector = new GUIFlagSelector();
            }

            // Display Construction-Info:
            scrollPos = GUILayout.BeginScrollView(scrollPos, GUI.scrollStyle);
            GUILayout.Label("<size=14><b>Construction Info:</b></size>");

            GUILayout.BeginHorizontal();
            GUILayout.Label("Ship name:", new GUIStyle(GUI.labelStyle)
            {
                stretchWidth = true
            });
            shipName = GUILayout.TextField(shipName, new GUIStyle(GUI.textFieldStyle)
            {
                alignment = TextAnchor.MiddleRight, stretchWidth = false, fixedWidth = 320
            });
            GUILayout.EndHorizontal();

            // Calculate and display all the construction-parameters:
            var engineers  = TargetVessel.GetCrewCountWithTrait(targetVesselSelector.targetVessel, "Engineer");
            var scientists = TargetVessel.GetCrewCountWithTrait(targetVesselSelector.targetVessel, "Scientist");

            if (engineers < engineersRequired)
            {
                throw new Exception("not enough engineers on target vessel");
            }
            if (missionProfileSelector.selectedProfile.payloadMass <= 0)
            {
                throw new Exception("mission profile payload too low");
            }
            var flights              = (int)Math.Ceiling(totalMass / missionProfileSelector.selectedProfile.payloadMass);
            var flightTime           = missionProfileSelector.selectedProfile.missionDuration;
            var totalFlightTime      = flightTime * flights;
            var baseConstructionTime = dryMass * 6 * 60 * 60; // 1 (kerbin-) day / ton
            var totalFlightCost      = missionProfileSelector.selectedProfile.launchCost * flights;

            currentCost     += totalFlightCost;
            constructionTime = baseConstructionTime;
            if (scientists > 0)
            {
                constructionTime = baseConstructionTime / (scientists + 1);                 // half the time per scientist
            }
            if (totalFlightTime > constructionTime)
            {
                constructionTime = totalFlightTime;
            }

            var leftLabel = new GUIStyle(GUI.labelStyle)
            {
                stretchWidth = true
            };
            var rightLabel = new GUIStyle(GUI.labelStyle)
            {
                stretchWidth = false, alignment = TextAnchor.MiddleRight
            };

            GUILayout.BeginHorizontal();
            GUILayout.Label("Mass:", leftLabel);
            GUILayout.Label(totalMass.ToString("#,##0.00t") + " / " + dryMass.ToString("#,##0.00t") + " dry", rightLabel);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Dock-Capacity (" + engineers.ToString() + " engineer" + (engineers != 1 ? "s" : "") + "):", leftLabel);
            GUILayout.Label((Math.Pow(2, engineers - 1) * 10).ToString("#,##0.00t") + " dry", rightLabel);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Single Flight (" + (missionProfileSelector.selectedProfile.launchCost / missionProfileSelector.selectedProfile.payloadMass).ToString("#,##0 √/t") + "):", leftLabel);
            GUILayout.Label(missionProfileSelector.selectedProfile.payloadMass.ToString("#,##0.00t") + " in " + GUI.FormatDuration(flightTime) + " for " + missionProfileSelector.selectedProfile.launchCost.ToString("#,##0 √"), rightLabel);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Total Flights:", leftLabel);
            GUILayout.Label(flights.ToString("#,##0") + " in " + GUI.FormatDuration(totalFlightTime) + " for " + totalFlightCost.ToString("#,##0 √"), rightLabel);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Base Construction Time (6h/t):", leftLabel);
            GUILayout.Label(GUI.FormatDuration(baseConstructionTime), rightLabel);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Total Construction Time (" + scientists.ToString() + " scientist" + (scientists != 1 ? "s" : "") + "):", leftLabel);
            GUILayout.Label(GUI.FormatDuration(constructionTime), rightLabel);
            GUILayout.EndHorizontal();

            // Display crew-selector, if the new ship can hold kerbals:
            var selectionIsValid = true;

            if (payloadShipSelector.payload.GetCrewCapacity() > 0)
            {
                GUILayout.Label("");
                GUILayout.Label("<size=14><b>Crew:</b></size>");
                if (!crewTransferSelector.DisplayList())
                {
                    selectionIsValid = false;
                }
            }

            // Show Button for Flag-Selector:
            GUILayout.Label("");
            flagSelector.ShowButton();

            GUILayout.EndScrollView();
            return(selectionIsValid);
        }