Example #1
0
 public static void Reset()
 {
     payloadShipSelector    = null;
     missionProfileSelector = null;
     orbitEditor            = null;
     crewTransferSelector   = null;
     flagSelector           = null;
     scrollPos = Vector2.zero;
     shipName  = "";
 }
Example #2
0
        // Creates a new ship with the given parameters for this mission. The code however seems unnecessarily convoluted and
        // error-prone, but there are no better examples available on the internet.
        private void CreateShip()
        {
            try
            {
                // The ShipConstruct-object can only savely exist while not in flight, otherwise it will spam Null-Pointer Exceptions every tick:
                if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                {
                    throw new Exception("unable to run CreateShip while in flight");
                }

                // Load the parts form the saved vessel:
                if (!File.Exists(shipTemplateFilename))
                {
                    throw new Exception("file '" + shipTemplateFilename + "' not found");
                }

                var shipConstruct = ShipConstruction.LoadShip(shipTemplateFilename);

                // Maybe adjust the orbit:
                var vesselHeight = Math.Max(Math.Max(shipConstruct.shipSize.x, shipConstruct.shipSize.y), shipConstruct.shipSize.z);
                if (missionType == MissionType.DEPLOY)
                {
                    // Make sure that there won't be any collisions, when the vessel is created at the given orbit:
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
                }
                else if (missionType == MissionType.CONSTRUCT)
                {
                    // Deploy the new ship next to the space-dock:
                    var spaceDock = TargetVessel.GetVesselById((Guid)targetVesselId);
                    orbit = GUIOrbitEditor.CreateFollowingOrbit(spaceDock.orbit, TargetVessel.GetVesselSize(spaceDock) + vesselHeight);
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
                }
                else
                {
                    throw new Exception("invalid mission-type '" + missionType + "'");
                }

                var game     = FlightDriver.FlightStateCache ?? HighLogic.CurrentGame;
                var profile  = GetProfile();
                var duration = profile.missionDuration;
                AssembleForLaunchUnlanded(shipConstruct, crewToDeliver ?? Enumerable.Empty <string>(), duration, orbit, flagURL, game);
                var newVessel = FlightGlobals.Vessels[FlightGlobals.Vessels.Count - 1];
                newVessel.vesselName = shipName;
                Debug.Log("[KSTS] deployed new ship '" + shipName + "' as '" + newVessel.protoVessel.vesselRef.id + "'");
                ScreenMessages.PostScreenMessage("Vessel '" + shipName + "' deployed"); // Popup message to notify the player

                // Notify other mods about the new vessel:
                GameEvents.onVesselCreate.Fire(newVessel);
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] Mission.CreateShip(): " + e);
            }
        }
Example #3
0
        // Returns a config-node which contains all public attributes of this object to be saved:
        public ConfigNode CreateConfigNode(string name)
        {
            ConfigNode node = new ConfigNode(name);

            FieldInfo[] fields = this.GetType().GetFields();
            foreach (FieldInfo field in fields)
            {
                if (!field.IsPublic)
                {
                    continue;                  // Only public attributes should contain persistent values worth saving.
                }
                if (field.IsLiteral)
                {
                    continue;                  // Don't save constants.
                }
                if (field.GetValue(this) == null)
                {
                    continue;
                }

                // Save all elements of the list by creating multiple config-nodes with the same name:
                if (field.FieldType == typeof(List <string>))
                {
                    List <string> list = (List <string>)field.GetValue(this);
                    if (list != null)
                    {
                        foreach (string element in list)
                        {
                            node.AddValue(field.Name.ToString(), element);
                        }
                    }
                }
                // Save dictionary-values in a sub-node:
                else if (field.FieldType == typeof(Dictionary <string, double>))
                {
                    ConfigNode dictNode = node.AddNode(field.Name.ToString());
                    foreach (KeyValuePair <string, double> item in (Dictionary <string, double>)field.GetValue(this))
                    {
                        dictNode.AddValue(item.Key, item.Value.ToString());
                    }
                }
                // Use orbit helper-class to save compley orbit-object:
                else if (field.FieldType == typeof(Orbit))
                {
                    node.AddNode(GUIOrbitEditor.SaveOrbitToNode((Orbit)field.GetValue(this)));
                }
                // Default; save as string:
                else
                {
                    node.AddValue(field.Name.ToString(), field.GetValue(this));
                }
            }
            return(node);
        }
Example #4
0
        public static bool Display()
        {
            currentCost = 0;
            bool ready  = DisplayInner();
            bool launch = DisplayFooter(currentCost, ready);

            if (launch)
            {
                if (!GUIOrbitEditor.CheckOrbitClear(orbitEditor.GetOrbit()))
                {
                    // The selected orbit is used by another vessel, abort:
                    ScreenMessages.PostScreenMessage("Selected orbit already in use by another vessel, aborting mission!");
                }
                else
                {
                    // The orbit is clear, start the mission:
                    MissionController.StartMission(Mission.CreateDeployment(shipName, payloadShipSelector.payload.template, orbitEditor.GetOrbit(), missionProfileSelector.selectedProfile, crewTransferSelector.crewToDeliver, flagSelector.flagURL));
                    KSTS.AddFunds(-currentCost);
                    Reset();
                    return(true);
                }
            }
            return(false);
        }
Example #5
0
 public static Orbit CreateSimpleOrbit(CelestialBody body, double altitude, double inclination)
 {
     return(GUIOrbitEditor.CreateOrbit(inclination, 0, altitude + body.Radius, 0, 0, 0, 0, body));
 }
Example #6
0
 // Creates a new object from the given config-node to fill all of the objects public attributes:
 public static object CreateFromConfigNode(ConfigNode node, object obj)
 {
     FieldInfo[] fields = obj.GetType().GetFields();
     foreach (FieldInfo field in fields)
     {
         if (!field.IsPublic)
         {
             continue;                  // Only public attributes should contain persistent values worth saving.
         }
         if (field.IsLiteral)
         {
             continue;                  // Don't load constants.
         }
         if (!node.HasValue(field.Name.ToString()) && !node.HasNode(field.Name.ToString()))
         {
             continue;                                                                                // Should only happen when the savegame is from a different version.
         }
         if (field.FieldType == typeof(double))
         {
             field.SetValue(obj, double.Parse(node.GetValue(field.Name.ToString())));
         }
         else if (field.FieldType == typeof(MissionType))
         {
             field.SetValue(obj, Enum.Parse(typeof(MissionType), node.GetValue(field.Name.ToString())));
         }
         else if (field.FieldType == typeof(MissionProfileType))
         {
             field.SetValue(obj, Enum.Parse(typeof(MissionProfileType), node.GetValue(field.Name.ToString())));
         }
         else if (field.FieldType == typeof(FlightRecordingStatus))
         {
             field.SetValue(obj, Enum.Parse(typeof(FlightRecordingStatus), node.GetValue(field.Name.ToString())));
         }
         else if (field.FieldType == typeof(int))
         {
             field.SetValue(obj, int.Parse(node.GetValue(field.Name.ToString())));
         }
         else if (field.FieldType == typeof(bool))
         {
             field.SetValue(obj, bool.Parse(node.GetValue(field.Name.ToString())));
         }
         else if (field.FieldType == typeof(Guid) || field.FieldType == typeof(Guid?))
         {
             field.SetValue(obj, new Guid(node.GetValue(field.Name.ToString())));
         }
         // Restore String-Lists by loading all nodes with the name of this field:
         else if (field.FieldType == typeof(List <string>))
         {
             List <string> list = new List <string>();
             foreach (string value in node.GetValues(field.Name.ToString()))
             {
                 list.Add(value);
             }
             field.SetValue(obj, list);
         }
         // Restore the dictionary by loading all the values in the sub-node:
         else if (field.FieldType == typeof(Dictionary <string, double>))
         {
             Dictionary <string, double> dict = new Dictionary <string, double>();
             ConfigNode dictNode = node.GetNode(field.Name.ToString());
             foreach (ConfigNode.Value item in dictNode.values)
             {
                 dict.Add(item.name, double.Parse(item.value));
             }
             field.SetValue(obj, dict);
         }
         // Load orbit via the helper-class:
         else if (field.FieldType == typeof(Orbit))
         {
             field.SetValue(obj, GUIOrbitEditor.CreateOrbitFromNode(node.GetNode(field.Name.ToString())));
         }
         // Fallback; try to store the value as string:
         else
         {
             field.SetValue(obj, node.GetValue(field.Name.ToString()));
         }
     }
     return(obj);
 }
Example #7
0
 public Orbit GetOrbit()
 {
     return(GUIOrbitEditor.CreateSimpleOrbit(this.body, this.altitudeSelector.Value, this.inclinationSelector.Value));
 }
Example #8
0
        private static bool DisplayInner()
        {
            // Payload selection:
            if (payloadShipSelector == null)
            {
                payloadShipSelector = new GUIPayloadShipSelector();
            }
            if (payloadShipSelector.payload == null)
            {
                payloadShipSelector.DisplayList();
                return(false);
            }
            if (payloadShipSelector.DisplaySelected())
            {
                missionProfileSelector = null;
                orbitEditor            = null;
                crewTransferSelector   = null;
                flagSelector           = null;
                return(false);
            }
            currentCost += payloadShipSelector.payload.template.totalCost;

            // Mission-Profile selection:
            if (missionProfileSelector == null)
            {
                missionProfileSelector                   = new GUIMissionProfileSelector();
                missionProfileSelector.filterMass        = payloadShipSelector.payload.template.totalMass;
                missionProfileSelector.filterMissionType = MissionProfileType.DEPLOY;
                shipName = payloadShipSelector.payload.template.shipName;
            }
            if (missionProfileSelector.selectedProfile == null)
            {
                missionProfileSelector.DisplayList();
                return(false);
            }
            if (missionProfileSelector.DisplaySelected())
            {
                orbitEditor          = null;
                crewTransferSelector = null;
                flagSelector         = null;
                return(false);
            }
            currentCost += missionProfileSelector.selectedProfile.launchCost;

            // Mission-Parameters selection:
            if (orbitEditor == null)
            {
                orbitEditor = new GUIOrbitEditor(missionProfileSelector.selectedProfile);
            }
            if (crewTransferSelector == null)
            {
                crewTransferSelector = new GUICrewTransferSelector(payloadShipSelector.payload, missionProfileSelector.selectedProfile);
            }
            if (flagSelector == null)
            {
                flagSelector = new GUIFlagSelector();
            }
            scrollPos = GUILayout.BeginScrollView(scrollPos, GUI.scrollStyle);

            GUILayout.Label("<size=14><b>Mission Parameters:</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();

            orbitEditor.DisplayEditor();

            // Display crew-selector, if the payload 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);
        }
Example #9
0
        // Creates a new ship with the given parameters for this mission. The code however seems unnecessarily convoluted and
        // error-prone, but there are no better examples available on the internet.
        private void CreateShip()
        {
            // TODO: Apply the staging which was saved in the editor.
            // TODO: Settings from other mods like Part-Switchers must also be applied here, maybe copy the config-nodes...
            try
            {
                if (!File.Exists(shipTemplateFilename))
                {
                    throw new Exception("file '" + shipTemplateFilename + "' not found");
                }
                if (missionType == MissionType.DEPLOY)
                {
                    // Make sure that there won't be any collisions, when the vessel is created at the given orbit:
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit);
                }
                else if (missionType == MissionType.CONSTRUCT)
                {
                    // Deploy the new ship next to the space-dock:
                    Vessel spaceDock = TargetVessel.GetVesselById((Guid)targetVesselId);
                    orbit = GUIOrbitEditor.CreateFollowingOrbit(spaceDock.orbit, 100); // TODO: Calculate the distance using the ships's size
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit);
                }
                else
                {
                    throw new Exception("invalid mission-type '" + missionType.ToString() + "'");
                }

                // The ShipConstruct-object can only savely exist while not in flight, otherwise it will spam Null-Pointer Exceptions every tick:
                if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                {
                    throw new Exception("unable to run CreateShip while in flight");
                }

                // Load the parts form the saved vessel:
                ShipConstruct shipConstruct = ShipConstruction.LoadShip(shipTemplateFilename);
                ProtoVessel   dummyProto    = new ProtoVessel(new ConfigNode(), null);
                Vessel        dummyVessel   = new Vessel();
                dummyProto.vesselRef = dummyVessel;

                // In theory it should be enough to simply copy the parts from the ShipConstruct to the ProtoVessel, but
                // this only seems to work when the saved vessel starts with the root-part and is designed top down from there.
                // It seems that the root part has to be the first part in the ProtoVessel's parts-list and all other parts have
                // to be listed in sequence radiating from the root part (eg 1=>2=>R<=3<=4 should be R,2,1,3,4). If the parts
                // are not in the correct order, their rotation seems to get messed up or they are attached to the wrong
                // attachmet-nodes, which is why we have to re-sort the parts with our own logic here.
                // This part of the code is experimental however and only based on my own theories and observations about KSP's vessels.
                Part rootPart = null;
                foreach (Part p in shipConstruct.parts)
                {
                    if (p.parent == null)
                    {
                        rootPart = p; break;
                    }
                }
                List <Part> pList = null;
                dummyVessel.parts = FindAndAddAttachedParts(rootPart, ref pList); // Find all parts which are directly attached to the root-part and add them in order.

                // Handle Subassemblies which are attached by surface attachment-nodes:
                bool handleSurfaceAttachments = true;
                while (dummyVessel.parts.Count < shipConstruct.parts.Count)
                {
                    int processedParts = 0;
                    foreach (Part p in shipConstruct.parts)
                    {
                        if (dummyVessel.parts.Contains(p))
                        {
                            continue;
                        }
                        if (handleSurfaceAttachments)
                        {
                            // Check if the part is attached by a surface-node:
                            if (p.srfAttachNode != null && dummyVessel.parts.Contains(p.srfAttachNode.attachedPart))
                            {
                                // Add this surface attached part and all the sub-parts:
                                dummyVessel.parts = FindAndAddAttachedParts(p, ref dummyVessel.parts);
                                processedParts++;
                            }
                        }
                        else
                        {
                            // Simply copy this part:
                            dummyVessel.parts.Add(p);
                        }
                    }
                    if (processedParts == 0)
                    {
                        // If there are still unprocessed parts, just throw them in the list during the next iteration,
                        // this should not happen but we don't want to end up in an endless loop:
                        handleSurfaceAttachments = false;
                    }
                }

                // Initialize all parts:
                uint missionID = (uint)Guid.NewGuid().GetHashCode();
                uint launchID  = HighLogic.CurrentGame.launchID++;
                foreach (Part p in dummyVessel.parts)
                {
                    p.flagURL     = flagURL == null ? HighLogic.CurrentGame.flagURL : flagURL;
                    p.missionID   = missionID;
                    p.launchID    = launchID;
                    p.temperature = 1.0;

                    // If the KRnD-Mod is installed, make sure that all parts of this newly created ship are set to the lates version:
                    foreach (PartModule module in p.Modules)
                    {
                        if (module.moduleName != "KRnDModule")
                        {
                            continue;
                        }
                        Debug.Log("[KSTS] found KRnD on '" + p.name.ToString() + "', setting to latest stats");
                        foreach (BaseField field in module.Fields)
                        {
                            if (field.name.ToString() == "upgradeToLatest")
                            {
                                field.SetValue(1, module); // Newer versions of KRnD use this flag to upgrade all attributes of the given part to the latest levels, when the vessel is activated.
                                if (field.GetValue(module).ToString() != "1")
                                {
                                    Debug.LogError("[KSTS] unable to modify '" + field.name.ToString() + "'");
                                }
                            }
                        }
                    }

                    dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                }

                // Store the parts in Config-Nodes:
                foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                {
                    p.storePartRefs();
                }
                List <ConfigNode> partNodesL = new List <ConfigNode>();
                foreach (var snapShot in dummyProto.protoPartSnapshots)
                {
                    ConfigNode node = new ConfigNode("PART");
                    snapShot.Save(node);
                    partNodesL.Add(node);
                }
                ConfigNode[] partNodes       = partNodesL.ToArray();
                ConfigNode[] additionalNodes = new ConfigNode[0];

                // This will actually create the ship and add it to the global list of flights:
                ConfigNode  protoVesselNode = ProtoVessel.CreateVesselNode(shipName, VesselType.Ship, orbit, 0, partNodes, additionalNodes);
                ProtoVessel pv = HighLogic.CurrentGame.AddVessel(protoVesselNode);
                Debug.Log("[KSTS] deployed new ship '" + shipName.ToString() + "' as '" + pv.vesselRef.id.ToString() + "'");
                ScreenMessages.PostScreenMessage("Vessel '" + shipName.ToString() + "' deployed"); // Popup message to notify the player
                Vessel newVessel = FlightGlobals.Vessels.Find(x => x.id == pv.vesselID);

                // Maybe add the initial crew to the vessel:
                if (crewToDeliver != null && crewToDeliver.Count > 0 && newVessel != null)
                {
                    foreach (string kerbonautName in crewToDeliver)
                    {
                        TargetVessel.AddCrewMember(newVessel, kerbonautName);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] Mission.CreateShip(): " + e.ToString());
            }
        }