Пример #1
0
 public override void OnSave(ConfigNode node)
 {
     try
     {
         FlightRecoorder.SaveRecordings(node);
         MissionController.SaveMissions(node);
     }
     catch (Exception e)
     {
         Debug.LogError("[KSTS] OnSave(): " + e.ToString());
     }
 }
Пример #2
0
 public override void OnLoad(ConfigNode node)
 {
     try
     {
         FlightRecoorder.LoadRecordings(node);
         MissionController.LoadMissions(node);
         GUI.Reset();
     }
     catch (Exception e)
     {
         Debug.LogError("[KSTS] OnLoad(): " + e.ToString());
     }
 }
Пример #3
0
        // Is called when this Addon is first loaded to initializes all values (eg registration of event-handlers and creation
        // of original-stats library).
        public void Awake()
        {
            try
            {
                FlightRecoorder.Initialize();
                MissionController.Initialize();

                // Build dictionary of all parts for easier access:
                if (KSTS.partDictionary == null)
                {
                    KSTS.partDictionary = new Dictionary <string, AvailablePart>();
                    foreach (AvailablePart part in PartLoader.LoadedPartsList)
                    {
                        if (KSTS.partDictionary.ContainsKey(part.name.ToString()))
                        {
                            Debug.LogError("[KSTS] duplicate part-name '" + part.name.ToString() + "'");
                            continue;
                        }
                        KSTS.partDictionary.Add(part.name.ToString(), part);
                    }
                }

                // Build a dictionay of all resources for easier access:
                if (KSTS.resourceDictionary == null)
                {
                    KSTS.resourceDictionary = new Dictionary <string, PartResourceDefinition>();
                    foreach (PartResourceDefinition resourceDefinition in PartResourceLibrary.Instance.resourceDefinitions)
                    {
                        KSTS.resourceDictionary.Add(resourceDefinition.name.ToString(), resourceDefinition);
                    }
                }

                // Invoke the timer-function every second to run background-code:
                if (!IsInvoking("Timer"))
                {
                    InvokeRepeating("Timer", 1, 1);
                }

                // Execute the following code only once:
                if (KSTS.initialized)
                {
                    return;
                }
                DontDestroyOnLoad(this);
                KSTS.initialized = true;
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] Awake(): " + e.ToString());
            }
        }
Пример #4
0
        public static void LoadRecordings(ConfigNode node)
        {
            FlightRecoorder.flightRecordings.Clear();
            ConfigNode flightRecorderNode = node.GetNode("FlightRecorder");

            if (flightRecorderNode == null)
            {
                return;
            }

            foreach (ConfigNode flightRecordingNode in flightRecorderNode.GetNodes())
            {
                FlightRecoorder.flightRecordings.Add(flightRecordingNode.name, FlightRecording.CreateFromConfigNode(flightRecordingNode));
            }

            FlightRecoorder.CollectGarbage(); // Might not work as expected in KSP 1.2, so we added this also to the timer-function.
        }
Пример #5
0
        public void Timer()
        {
            try
            {
                // Don't update while not in game:
                if (HighLogic.LoadedScene == GameScenes.MAINMENU || HighLogic.LoadedScene == GameScenes.CREDITS || HighLogic.LoadedScene == GameScenes.SETTINGS)
                {
                    return;
                }

                // Call all background-jobs:
                FlightRecoorder.Timer();
                MissionController.Timer();
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] Timer(): " + e.ToString());
            }
        }
Пример #6
0
        public static void Display()
        {
            if (!initialized)
            {
                Initialize();
            }
            Vessel          vessel    = FlightGlobals.ActiveVessel;
            FlightRecording recording = null;

            if (vessel)
            {
                recording = FlightRecoorder.GetFlightRecording(vessel);
            }
            if (!vessel || recording == null)
            {
                Reset();

                // Show list of recorded profiles:
                missionProfileSelector.DisplayList();
                if (missionProfileSelector.selectedProfile != null)
                {
                    if (missionProfileSelector.selectedProfile != lastSelectedProfile)
                    {
                        // The selecte profile was switched:
                        lastSelectedProfile   = missionProfileSelector.selectedProfile;
                        newMissionProfileName = missionProfileSelector.selectedProfile.profileName;
                    }

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("<size=14><b>Profile name:</b></size>", new GUIStyle(GUI.labelStyle)
                    {
                        stretchWidth = false
                    });
                    newMissionProfileName = GUILayout.TextField(newMissionProfileName, new GUIStyle(GUI.textFieldStyle)
                    {
                        stretchWidth = true
                    });
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    if (GUILayout.Button("Save Profile", GUI.buttonStyle))
                    {
                        MissionController.ChangeMissionProfileName(missionProfileSelector.selectedProfile.profileName, newMissionProfileName);
                        missionProfileSelector = new GUIMissionProfileSelector(); // Deselect & Reset
                    }
                    if (GUILayout.Button("Delete Profile", GUI.buttonStyle))
                    {
                        MissionController.DeleteMissionProfile(missionProfileSelector.selectedProfile.profileName);
                        missionProfileSelector = new GUIMissionProfileSelector(); // Deselect & Reset
                    }
                    GUILayout.EndHorizontal();
                }
            }
            else
            {
                // During the recording, allow the player to change the name of the new flight-profile:
                GUILayout.BeginHorizontal();
                GUILayout.Label("<size=14><b>Profile name:</b></size>", new GUIStyle(GUI.labelStyle)
                {
                    stretchWidth = false
                });
                if (recording.status != FlightRecordingStatus.PRELAUNCH)
                {
                    recording.profileName = GUILayout.TextField(recording.profileName, new GUIStyle(GUI.textFieldStyle)
                    {
                        stretchWidth = true
                    });
                }
                else
                {
                    GUILayout.Label(recording.profileName, new GUIStyle(GUI.labelStyle)
                    {
                        stretchWidth = true
                    });
                }
                GUILayout.EndHorizontal();

                // Display all Information about the current recording:
                GUILayout.BeginScrollView(new Vector2(0, 0), new GUIStyle(GUI.scrollStyle)
                {
                    stretchHeight = true
                });
                List <KeyValuePair <string, string> > displayAttributes = recording.GetDisplayAttributes();
                foreach (KeyValuePair <string, string> displayAttribute in displayAttributes)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("<b>" + displayAttribute.Key + "</b>");
                    GUILayout.Label(displayAttribute.Value + "  ", new GUIStyle(GUI.labelStyle)
                    {
                        alignment = TextAnchor.MiddleRight
                    });
                    GUILayout.EndHorizontal();
                }
                GUILayout.EndScrollView();

                // Display payload selector:
                if (recording.status == FlightRecordingStatus.ASCENDING || recording.status == FlightRecordingStatus.PRELAUNCH)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("<size=14><b>Mission Type:</b></size>");
                    string[] missionTypeStrings = new string[] { "Deploy", "Transport" };
                    selectedMissionTypeTab = GUILayout.Toolbar(selectedMissionTypeTab, missionTypeStrings);
                    GUILayout.EndHorizontal();

                    scrollPos = GUILayout.BeginScrollView(scrollPos, GUI.scrollStyle, GUILayout.Height(210), GUILayout.MaxHeight(210));
                    if (selectedMissionTypeTab == 0)
                    {
                        // Show all deployable payloads:
                        if (!recording.CanPerformMission(MissionProfileType.DEPLOY))
                        {
                            GUILayout.Label("Deployment missions can only be performed if the vessel has detachable parts which haven't been used during the flight (no resource consumption, inactive, uncrewed, etc).");
                        }
                        else
                        {
                            // Show all detachable subassemblies:
                            foreach (PayloadAssembly payloadAssembly in recording.GetPayloadAssemblies())
                            {
                                GUILayout.BeginHorizontal();
                                if (GUILayout.Toggle(selectedPayloadAssemblyIds.Contains(payloadAssembly.id), "<b>" + payloadAssembly.name + "</b>"))
                                {
                                    if (!selectedPayloadAssemblyIds.Contains(payloadAssembly.id))
                                    {
                                        selectedPayloadAssemblyIds.Add(payloadAssembly.id);
                                    }
                                }
                                else if (selectedPayloadAssemblyIds.Contains(payloadAssembly.id))
                                {
                                    selectedPayloadAssemblyIds.Remove(payloadAssembly.id);
                                }
                                GUILayout.Label(payloadAssembly.partCount.ToString() + " parts, " + payloadAssembly.mass.ToString("#,##0.00 t") + "   ", new GUIStyle(GUI.labelStyle)
                                {
                                    alignment = TextAnchor.MiddleRight
                                });
                                GUILayout.EndHorizontal();
                            }
                        }
                    }
                    else
                    {
                        if (!recording.CanPerformMission(MissionProfileType.TRANSPORT))
                        {
                            GUILayout.Label("Transport missions can only be performed with vessels which have at least one docking port as well as RCS thrusters.");
                        }
                        else
                        {
                            // Show all payload-resources:
                            double totalPayloadMass = 0;
                            foreach (PayloadResource payloadResource in recording.GetPayloadResources())
                            {
                                double selectedAmount = 0;
                                selectedPayloadDeploymentResources.TryGetValue(payloadResource.name, out selectedAmount);

                                GUILayout.BeginHorizontal();
                                GUILayout.Label("<b>" + payloadResource.name + "</b>");
                                GUILayout.Label(((selectedAmount / payloadResource.amount) * 100).ToString("0.00") + "% (" + selectedAmount.ToString("#,##0.00") + " / " + payloadResource.amount.ToString("#,##0.00") + "): " + (selectedAmount * payloadResource.mass).ToString("#,##0.00 t") + "  ", new GUIStyle(GUI.labelStyle)
                                {
                                    alignment = TextAnchor.MiddleRight
                                });
                                GUILayout.EndHorizontal();

                                selectedAmount = GUILayout.HorizontalSlider((float)selectedAmount, 0, (float)payloadResource.amount);
                                if (selectedAmount < 0)
                                {
                                    selectedAmount = 0;
                                }
                                if (selectedAmount > payloadResource.amount)
                                {
                                    selectedAmount = payloadResource.amount;
                                }
                                if (payloadResource.amount - selectedAmount < 0.01)
                                {
                                    selectedAmount = payloadResource.amount;
                                }
                                totalPayloadMass += selectedAmount * payloadResource.mass;

                                if (selectedPayloadDeploymentResources.ContainsKey(payloadResource.name))
                                {
                                    selectedPayloadDeploymentResources[payloadResource.name] = selectedAmount;
                                }
                                else
                                {
                                    selectedPayloadDeploymentResources.Add(payloadResource.name, selectedAmount);
                                }
                            }

                            GUILayout.BeginHorizontal();
                            GUILayout.Label("<b>Total Payload</b>");
                            GUILayout.Label(totalPayloadMass.ToString("#,##0.00 t  "), new GUIStyle(GUI.labelStyle)
                            {
                                alignment = TextAnchor.MiddleRight
                            });
                            GUILayout.EndHorizontal();
                        }
                    }
                    GUILayout.EndScrollView();
                }

                // Bottom pane with action-buttons:
                GUILayout.BeginHorizontal();
                if (recording.status == FlightRecordingStatus.PRELAUNCH && GUILayout.Button("Record", GUI.buttonStyle))
                {
                    // Start Recording:
                    FlightRecoorder.StartRecording(vessel);
                }

                if (recording.CanDeploy() && GUILayout.Button("Release Payload", GUI.buttonStyle))
                {
                    if (selectedMissionTypeTab == 0)
                    {
                        List <PayloadAssembly> payloadAssemblies         = recording.GetPayloadAssemblies();
                        List <PayloadAssembly> selectedPayloadAssemblies = new List <PayloadAssembly>();
                        foreach (PayloadAssembly payloadAssembly in recording.GetPayloadAssemblies())
                        {
                            if (selectedPayloadAssemblyIds.Contains(payloadAssembly.id))
                            {
                                selectedPayloadAssemblies.Add(payloadAssembly);
                            }
                        }
                        if (selectedPayloadAssemblies.Count > 0)
                        {
                            recording.DeployPayloadAssembly(selectedPayloadAssemblies);
                        }
                    }
                    else
                    {
                        recording.DeployPayloadResources(selectedPayloadDeploymentResources);
                    }
                }

                if (recording.CanFinish() && GUILayout.Button("Stop & Save", GUI.buttonStyle))
                {
                    // Stop recording and create a mission-profile:
                    FlightRecoorder.SaveRecording(vessel);
                }

                if (recording.status != FlightRecordingStatus.PRELAUNCH && GUILayout.Button("Abort", GUI.buttonStyle))
                {
                    // Cancel runnig recording:
                    FlightRecoorder.CancelRecording(vessel);
                }
                GUILayout.EndHorizontal();
            }
        }
Пример #7
0
        // Is called every second and keeps track of used parts during a flight-recording:
        public static void Timer()
        {
            try
            {
                // Maybe remove old, invalid running recordings:
                FlightRecoorder.CollectGarbage();

                // Check if we are on an vessel which is recording a flight:
                Vessel vessel = FlightGlobals.ActiveVessel;
                if (!vessel)
                {
                    return;
                }
                FlightRecording recording = GetFlightRecording(vessel);
                if (recording == null)
                {
                    return;
                }

                if (vessel.id.ToString() != FlightRecoorder.timerVesselId)
                {
                    // The vessel has changed, reset all variables from the last timer-tick:
                    FlightRecoorder.timerVesselId = vessel.id.ToString();
                    FlightRecoorder.timerPartResources.Clear();
                }

                // Check all parts, if something has changed which makes the part unusable for payload-deployments:
                foreach (Part part in vessel.parts)
                {
                    if (recording.usedPartIds.Contains(part.flightID.ToString()))
                    {
                        continue;                                                           // Already blocked
                    }
                    bool   blockThis = false;
                    string partId    = part.flightID.ToString();

                    // Check for running engines:
                    foreach (ModuleEngines engineModule in part.FindModulesImplementing <ModuleEngines>())
                    {
                        if (engineModule.GetCurrentThrust() > 0)
                        {
                            blockThis = true;
                        }
                    }
                    foreach (ModuleEnginesFX engineModule in part.FindModulesImplementing <ModuleEnginesFX>())
                    {
                        if (engineModule.GetCurrentThrust() > 0)
                        {
                            blockThis = true;
                        }
                    }

                    // Check for resource-consumption:
                    foreach (PartResource resource in part.Resources)
                    {
                        PartResourceDefinition resourceDefinition = null;
                        string resourceId = resource.resourceName.ToString();
                        if (!KSTS.resourceDictionary.TryGetValue(resourceId, out resourceDefinition))
                        {
                            continue;
                        }
                        if (resourceDefinition.density <= 0)
                        {
                            continue;                                  // We only care about resources with mass, skipping electricity and such.
                        }
                        if (!FlightRecoorder.timerPartResources.ContainsKey(partId))
                        {
                            FlightRecoorder.timerPartResources.Add(partId, new Dictionary <string, double>());
                        }
                        double lastAmount;
                        if (!FlightRecoorder.timerPartResources[partId].TryGetValue(resourceId, out lastAmount))
                        {
                            FlightRecoorder.timerPartResources[partId].Add(resourceId, resource.amount);
                        }
                        else
                        {
                            if (lastAmount != resource.amount)
                            {
                                blockThis = true;                                // The amount has changed relative to the last timer-tick.
                            }
                        }
                    }

                    if (blockThis)
                    {
                        Debug.Log("[KSTS] marking part " + part.name.ToString() + " (" + part.flightID.ToString() + ") as used");
                        recording.usedPartIds.Add(part.flightID.ToString());
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] FlightRecoorder.Timer(): " + e.ToString());
            }
        }