Пример #1
0
        //And this does the actual drawing
        public void DrawFlightGUI(int windowID)
        {
            //Start with a vertical, then a horizontal (stage list and stage info), then another vertical (stage list).
            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal();
            GUILayout.BeginVertical(GUILayout.Width(225));
            //Draw the toolbar that selects between recovered and destroyed stages
            int temp = firstToolbarIndex;
            //firstToolbarIndex = GUILayout.Toolbar(firstToolbarIndex, new string[] { "Recovered", "Destroyed" });
            GUILayout.BeginHorizontal();
            bool active = GUILayout.Toggle(firstToolbarIndex == 0, "Recovered" + (Settings.Instance.RecoveredStages.Count > 0 ? " ("+Settings.Instance.RecoveredStages.Count+")" : ""), GUI.skin.button);
            if (!active && firstToolbarIndex == 0)
                firstToolbarIndex = -1;
            else if (active)
                firstToolbarIndex = 0;

            active = GUILayout.Toggle(firstToolbarIndex == 1, "Destroyed" + (Settings.Instance.DestroyedStages.Count > 0 ? " (" + Settings.Instance.DestroyedStages.Count + ")" : ""), GUI.skin.button);
            if (!active && firstToolbarIndex == 1)
                firstToolbarIndex = -1;
            else if (active)
                firstToolbarIndex = 1;
            if (temp != firstToolbarIndex)
            {
                NullifySelected();
                if (firstToolbarIndex == -1)
                    flightWindowRect.height = 1;
                else
                    flightWindowRect.height = 480;
            }
            GUILayout.EndHorizontal();
            //NullifySelected will set the selectedStage to null and reset the toolbar

               // GUILayout.Label("FMRS: " + (StageRecovery.FMRS_Enabled() ? "Active" : "Inactive"));

            if (firstToolbarIndex >= 0)
            {
                //Begin listing the recovered/destryoed stages in a scroll view (so you can scroll if it's too long)
                GUILayout.Label((firstToolbarIndex == 0 ? "Recovered" : "Destroyed") + " Stages:");
                stagesScroll = GUILayout.BeginScrollView(stagesScroll, HighLogic.Skin.textArea);

                RecoveryItem deleteThis = null;
                //List all recovered stages
                if (firstToolbarIndex == 0)
                {
                    foreach (RecoveryItem stage in Settings.Instance.RecoveredStages)
                    {
                        string buttonText = stage.StageName;
                        if (stage == selectedStage)
                            buttonText = "--  " + buttonText + "  --";
                        if (GUILayout.Button(buttonText))
                        {
                            if (Input.GetMouseButtonUp(0))
                            {
                                //If you select the same stage again it will minimize the list
                                if (selectedStage == stage)
                                    selectedStage = null;
                                else
                                    selectedStage = stage;
                            }
                            else if (Input.GetMouseButtonUp(1))
                            {
                                //Right clicking deletes the stage
                                deleteThis = stage;
                            }
                        }
                    }
                }
                //List all destroyed stages
                else if (firstToolbarIndex == 1)
                {
                    foreach (RecoveryItem stage in Settings.Instance.DestroyedStages)
                    {
                        string buttonText = stage.StageName;
                        if (stage == selectedStage)
                            buttonText = "--  " + buttonText + "  --";
                        if (GUILayout.Button(buttonText))
                        {
                            if (Input.GetMouseButtonUp(0))
                            {
                                //If you select the same stage again it will minimize the list
                                if (selectedStage == stage)
                                    selectedStage = null;
                                else
                                    selectedStage = stage;
                            }
                            else if (Input.GetMouseButtonUp(1))
                            {
                                //Right clicking deletes the stage
                                deleteThis = stage;
                            }
                        }
                    }
                }

                if (deleteThis != null)
                {
                    if (deleteThis == selectedStage)
                        NullifySelected();
                    if (firstToolbarIndex == 0)
                        Settings.Instance.RecoveredStages.Remove(deleteThis);
                    else
                        Settings.Instance.DestroyedStages.Remove(deleteThis);
                }

                //End the list of stages
                GUILayout.EndScrollView();
            }
            GUILayout.EndVertical();

            //If a stage is selected we show the info for it
            if (selectedStage != null)
            {
                //Make the window larger to accomodate the info
                if (flightWindowRect.width != 600) flightWindowRect.width = 600;
                GUILayout.BeginVertical(HighLogic.Skin.textArea);
                //Show a toolbar with options for specific data, defaulting to the Parts list
                infoBarIndex = GUILayout.Toolbar(infoBarIndex, new string[] { "Parts", "Crew", "Science", "Info" });
                //List the stage name and whether it was recovered or destroyed
                GUILayout.Label("Stage name: " + selectedStage.StageName);
                GUILayout.Label("Status: " + (selectedStage.recovered ? "RECOVERED" : "DESTROYED"));
                //Put everything in a scroll view in case it is too much data for the window to display
                infoScroll = GUILayout.BeginScrollView(infoScroll);
                //Depending on the selected data view we display different things (split into different functions for ease)
                switch (infoBarIndex)
                {
                    case 0: DrawPartsInfo(); break;
                    case 1: DrawCrewInfo(); break;
                    case 2: DrawScienceInfo(); break;
                    case 3: DrawAdvancedInfo(); break;
                }
                GUILayout.EndScrollView();
                GUILayout.EndVertical();
                //End the info side of the window
            }
            //If no stage is selected we reset the window size back to 240
            else
            {
                if (flightWindowRect.width != 240) flightWindowRect.width = 240;
            }

            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
            //End the entire window

            //Make it draggable
            if (!Input.GetMouseButtonDown(1) && !Input.GetMouseButtonDown(2))
                GUI.DragWindow();
        }
Пример #2
0
 //Set the selected stage to null and reset the info toolbar to "Parts"
 public void NullifySelected()
 {
     selectedStage = null;
     infoBarIndex = 0;
 }
        public void VesselUnloadEvent(Vessel vessel)
        {
            //If we're disabled, just return
            if (!Settings.Instance.SREnabled)
                return;

            //If the vessel or the protovessel are null then we surely can't do anything with them
            if (vessel == null || vessel.protoVessel == null)
                return;

            ProtoVessel pv = vessel.protoVessel;

            //If we aren't supposed to recover clamps, then don't try.
            if (Settings.Instance.RecoverClamps)
            {
                //If we've already recovered the clamps, then no need to try again
                if (clampsRecovered.Find(a => a.id == vessel.id) != null)
                    return;

                //Assign the pv variable to the protovessel, then look for if the root is a clamp

                if (pv.protoPartSnapshots.Count > 0 && pv.protoPartSnapshots[0].modules.Exists(m => m.moduleName == "LaunchClamp"))
                {
                    //We look for the launchclamp module, which will hopefully cover FASA and stock.
                    Debug.Log("[SR] Recovering a clamp!");
                    //Add it to the recovered clamps list so we don't try to recover it again
                    clampsRecovered.Add(vessel);
                    float totalRefund = 0;
                    //Loop over all the parts and calculate their cost (we recover at 100% since we're at the launchpad/runway)
                    foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots)
                    {
                        float out1, out2;
                        totalRefund += ShipConstruction.GetPartCosts(pps, pps.partInfo, out out1, out out2);
                    }
                    //Add dem funds to da total. Get dem funds!
                    AddFunds(totalRefund);
                    //Fire the successful recovery event. Even though this isn't a stage we still need to do this for things like KCT to recover the parts.
                    //Can be averted with stock functions if I can get them working properly
                    APIManager.instance.RecoverySuccessEvent.Fire(vessel, new float[] { 100, totalRefund, 0 }, "SUCCESS");
                    //And then we try a bunch of things to make sure the clamps are removed (remove it from the flight state, kill it, and destroy it)
                    HighLogic.CurrentGame.flightState.protoVessels.Remove(pv);
                    vessel.Die();
                    Destroy(vessel);
                    //So, question for myself. Would it be better to try to manually fire the recovery events? Would that really be worth anything?
                }
            }

            //If it's a stage that will be destroyed, we need to manually recover the Kerbals
            if (Settings.Instance.RecoverKerbals && pv.GetVesselCrew().Count > 0)
            {
                //Check if the conditions for vessel destruction are met
                if (vessel != FlightGlobals.ActiveVessel && !vessel.isEVA && vessel.mainBody == Planetarium.fetch.Home && pv.situation != Vessel.Situations.LANDED && vessel.atmDensity >= 0.01) //unloading in > 0.01 atm and not landed //pv.altitude < vessel.mainBody.atmosphereDepth
                {
                    Debug.Log("[SR] Vessel " + pv.vesselName + " is going to be destroyed. Recovering Kerbals!"); //Kerbal death should be handled by SR instead
                    RecoveryItem recItem = new RecoveryItem(vessel);

                    //Pre-recover the Kerbals
                    recItem.PreRecoverKerbals();

                    //Add the ship to the RecoveryQueue to be handled by the OnDestroy event
                    instance.RecoveryQueue.Add(recItem);
                }
                else
                    WatchVessel(vessel);
            }
        }
        //The main show. The VesselDestroyEvent is activated whenever KSP destroys a vessel. We only care about it in a specific set of circumstances
        private void VesselDestroyEvent(Vessel v)
        {
            //If we're disabled, just return
            if (!Settings.Instance.SREnabled)
                return;

            if (!sceneChangeComplete)
                return;

            //If FlightGlobals is null, just return. We can't do anything
            if (FlightGlobals.fetch == null)
                return;

            //If the protoVessel is null, we can't do anything so just return
            if (v.protoVessel == null)
                return;

            if (HighLogic.LoadedSceneIsFlight && FMRS_Enabled())
            {//If the vessel is controlled or has a RealChute Module, FMRS will handle it
                if ((v.protoVessel.wasControllable) || v.protoVessel.protoPartSnapshots.Find(p => p.modules != null && p.modules.Find(m => m.moduleName == "RealChuteModule") != null) != null || v.protoVessel.GetVesselCrew().Count > 0)
                {
                    return;
                }
                //If there's crew onboard, FMRS will handle that too
                // if we've gotten here, FMRS probably isn't handling the craft and we should instead.
            }

            //Our criteria for even attempting recovery. Broken down: vessel exists, isn't the active vessel, is around Kerbin, is either unloaded or packed, altitude is within atmosphere,
            //is flying or sub orbital, and is not an EVA (aka, Kerbals by themselves)
            if (v != null && !(HighLogic.LoadedSceneIsFlight && v.isActiveVessel) && (v.mainBody == Planetarium.fetch.Home) && (!v.loaded || v.packed) && (v.altitude < v.mainBody.atmosphereDepth) &&
               (v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.SUB_ORBITAL || v.situation == Vessel.Situations.ORBITING) && !v.isEVA && v.altitude > 100)
            {
                bool OnlyBlacklistedItems = true;
                foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots)
                {
                    if (!Settings.Instance.BlackList.Contains(pps.partInfo.title))
                    {
                        OnlyBlacklistedItems = false;
                        break;
                    }
                }
                if (OnlyBlacklistedItems) return;

                //If we got this far, we can assume we're going to be attempting to recover the vessel, so we should fire the processing event
                APIManager.instance.OnRecoveryProcessingStart.Fire(v);

                //Create a new RecoveryItem. Calling this calculates everything regarding the success or failure of the recovery. We need it for display purposes in the main gui
                Debug.Log("[SR] Searching in RecoveryQueue (" + instance.RecoveryQueue.Count + ") for " + v.id);
                RecoveryItem Stage;
                if (instance.RecoveryQueue.Count > 0 && instance.RecoveryQueue.Exists(ri => ri.vessel.id == v.id))
                {
                    Stage = instance.RecoveryQueue.Find(ri => ri.vessel.id == v.id);
                    instance.RecoveryQueue.Remove(Stage);
                    Debug.Log("[SR] Found vessel in the RecoveryQueue.");
                }
                else
                    Stage = new RecoveryItem(v);
                Stage.Process();
                //Fire the pertinent RecoveryEvent (success or failure). Aka, make the API do its work
                Stage.FireEvent();
                //Add the Stage to the correct list of stages. Either the Recovered Stages list or the Destroyed Stages list, for display on the main gui
                Stage.AddToList();
                //Post a message to the stock message system, if people are still using that.
                Stage.PostStockMessage();

                APIManager.instance.OnRecoveryProcessingFinish.Fire(v);
            }
        }
        public void FixedUpdate()
        {
            //For each vessel in the watchlist, check to see if it reaches an atm density of 0.01 and if so, pre-recover it
            foreach (Guid id in new List<Guid>(StageWatchList))
            {
                Vessel vessel = FlightGlobals.Vessels.Find(v => v.id == id);
                if (vessel == null)
                {
                    StageWatchList.Remove(id);
                    continue;
                }
                if ((!vessel.loaded || vessel.packed) && vessel.altitude < cutoffAlt)
                {
                    Debug.Log("[SR] Vessel " + vessel.vesselName + " (" + id + ") is about to be destroyed. Pre-recovering Kerbals.");
                    RecoveryItem recItem = new RecoveryItem(vessel);

                    //Pre-recover the Kerbals
                    recItem.PreRecoverKerbals();

                    //Add the ship to the RecoveryQueue to be handled by the VesselDestroy event
                    instance.RecoveryQueue.Add(recItem);

                   // Debug.Log("[SR] Current RecoveryQueue size: " + instance.RecoveryQueue.Count);

                    StageWatchList.Remove(id);
                }
            }
        }