Beispiel #1
0
            /// <summary>
            /// This converts the KACAlarmList actual object to a new List for consumption
            /// </summary>
            /// <param name="actualAlarmList"></param>
            /// <returns></returns>
            private KACAlarmList ExtractAlarmList(Object actualAlarmList)
            {
                KACAlarmList ListToReturn = new KACAlarmList();

                try
                {
                    //iterate each "value" in the dictionary
                    for (var i = ((IList)actualAlarmList).Count - 1; i >= 0; i--)
                    {
                        var item = ((IList)actualAlarmList)[i];

                        //foreach (var item in (IList)actualAlarmList)
                        //{
                        KACAlarm r1 = new KACAlarm(item);
                        ListToReturn.Add(r1);
                    }
                }
                catch (Exception)
                {
                    //LogFormatted("Arrggg: {0}", ex.Message);
                    //throw ex;
                    //
                }
                return(ListToReturn);
            }
Beispiel #2
0
                public AlarmStateChangedEventArgs(Object actualEvent, KACAPI kac)
                {
                    Type type = actualEvent.GetType();

                    alarm     = new KACAlarm(type.GetField("alarm").GetValue(actualEvent));
                    eventType = (KACAlarm.AlarmStateEventsEnum)type.GetField("eventType").GetValue(actualEvent);
                }
Beispiel #3
0
 /// <param name="a">alarm</param>
 /// <returns>boolean finished. false if alarm is null</returns>
 static public bool Finished(this KACAlarm a)
 {
     if (a == null)
     {
         return(false);           //throw new ArgumentNullException(nameof(a));
     }
     return(Remaining(a) < 0.0);
 }
        //public KACAlarm CreateAlarm(String Name)
        /// <summary>
        /// Create a new Alarm method for calling via API
        /// </summary>
        /// <param name="AlarmType">Enum of type of alarm</param>
        /// <param name="Name">Text Name of the Alarm</param>
        /// <param name="UT">Universal Time of the Alarm</param>
        /// <returns>Alarms Unique ID</returns>
        public String CreateAlarm(KACAlarm.AlarmTypeEnum AlarmType, String Name,Double UT)
        {
            KACAlarm tmpAlarm = new KACAlarm(UT);
            tmpAlarm.TypeOfAlarm=AlarmType;
            tmpAlarm.Name=Name;

            alarms.Add(tmpAlarm);

            return tmpAlarm.ID;
        }
Beispiel #5
0
        /// <summary>
        /// Get Alarm by title. Return Alarm or null.
        /// </summary>
        /// <param name="alarmTitle"></param>
        /// <returns></returns>
        static public KACAlarm GetAlarm(string alarmTitle)
        {
            if (KACWrapper.APIReady)
            {
                KACAlarm a = KACWrapper.KAC.Alarms.OrderBy(x => x.AlarmTime).FirstOrDefault(z => z.Name == alarmTitle);

                if (a != null)
                {
                    return(a);
                }
            }
            return(null);
        }
Beispiel #6
0
        /// <summary>
        /// How many seconds remains until alarm will be finished.
        /// Returns negative values for already finished alarms
        /// </summary>
        /// <param name="a"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns></returns>
        static public double Remaining(KACAlarm a)
        {
            if (a == null)
            {
                throw new ArgumentNullException(nameof(a));
            }

            double time_now  = Utils.UT(); // HighLogic.CurrentGame.UniversalTime;  //HighLogic.CurrentGame.flightState.universalTime;
            double alarmTime = a.AlarmTime;

            //Logging.Log("time_now: " + time_now + " alarmTime: " + alarmTime);

            return(alarmTime - time_now);
        }
Beispiel #7
0
            /// <summary>
            /// This converts the KACAlarmList actual object to a new List for consumption
            /// </summary>
            /// <param name="actualAlarmList"></param>
            /// <returns></returns>
            private KACAlarmList ExtractAlarmList(Object actualAlarmList)
            {
                KACAlarmList ListToReturn = new KACAlarmList();

                try
                {
                    //iterate each "value" in the dictionary

                    foreach (var item in (IList)actualAlarmList)
                    {
                        KACAlarm r1 = new KACAlarm(item);
                        ListToReturn.Add(r1);
                    }
                }
                catch (Exception ex)
                {
                    LogFormatted("ExtractAlarmList failed: {0}", ex.Message);
                    //throw ex;
                    //
                }
                return(ListToReturn);
            }
        private KACAlarm QuickAddDN()
        {
            KACAlarm tmpAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(),
                KACWorkerGameState.CurrentVessel.vesselName + " Descending",
                "Quick Added Descending Node",
                KACWorkerGameState.CurrentVessel.orbit.TimeOfDescendingNode(KACWorkerGameState.CurrentVesselTarget.GetOrbit(), KACWorkerGameState.CurrentTime.UT) - settings.AlarmAddNodeQuickMargin,
                settings.AlarmAddNodeQuickMargin,
                KACAlarm.AlarmTypeEnum.DescendingNode,
                settings.AlarmAddNodeQuickAction);
            alarms.Add(tmpAlarm);

            return tmpAlarm;
        }
        private KACAlarm QuickAddSOI()
        {
            KACAlarm tmpAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(),
                KACWorkerGameState.CurrentVessel.vesselName + " SOI Change",
                "Quick Added SOI Change Alarm",
                KACWorkerGameState.CurrentVessel.orbit.UTsoi - settings.AlarmAddSOIQuickMargin,
                settings.AlarmAddSOIQuickMargin,
                KACAlarm.AlarmTypeEnum.SOIChange,
                settings.AlarmAddSOIQuickAction);

            alarms.Add(tmpAlarm);

            return tmpAlarm;
        }
        private void AddContractAutoAlarm(Contract contract, Double margin, AlarmActions action)
        {
            //If theres already an alarm then leave it alone
            if (alarms.Any(a => a.ContractGUID == contract.ContractGuid))
                return;

            //log
            LogFormatted("Adding new {3} Contract Alarm for: {0}({1})-{2}", contract.Title, contract.ContractGuid, contract.DateExpire, contract.ContractState);

            //gen the text
            String AlarmName, AlarmNotes;
            GenerateContractStringsFromContract(contract, out AlarmName, out AlarmNotes);

            //create the alarm
            KACAlarm tmpAlarm = new KACAlarm("", AlarmName, AlarmNotes, contract.DateNext() - margin, margin,
                KACAlarm.AlarmTypeEnum.ContractAuto, action);

            //add the contract specifics
            tmpAlarm.ContractGUID = contract.ContractGuid;
            tmpAlarm.ContractAlarmType = contract.AlarmType();

            //add it to the list
            alarms.Add(tmpAlarm);
        }
        private KACAlarm QuickAddManNode()
        {
            KACAlarm tmpAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(),
                KACWorkerGameState.CurrentVessel.vesselName + " Maneuver",
                "Quick Added Maneuver Alarm",
                KACWorkerGameState.ManeuverNodeFuture.UT - settings.AlarmAddManQuickMargin,
                settings.AlarmAddManQuickMargin,
                KACAlarm.AlarmTypeEnum.Maneuver,
                settings.AlarmAddManQuickAction,
                KACWorkerGameState.ManeuverNodesFuture);

            alarms.Add(tmpAlarm);

            return tmpAlarm;
        }
        // <summary>
        // Basically deserializing the alarm
        // </summary>
        // <param name="AlarmDetails"></param>
        //internal static KACAlarm LoadFromString(String AlarmDetails)
        //{
        //    String[] vars = AlarmDetails.Split("|".ToCharArray());
        //    String VesselID = "";
        //    String SaveName = vars[0];
        //    String Name = vars[1];
        //    Boolean Enabled = Convert.ToBoolean(vars[2]);
        //    Double UT = Convert.ToDouble(vars[3]);
        //    Boolean HaltWarp = Convert.ToBoolean(vars[4]);
        //    Boolean PauseGame = false;
        //    String Notes = "";
        //    if (vars.Length == 6)
        //        Notes = vars[5];
        //    else
        //    {
        //        PauseGame = Convert.ToBoolean(vars[5]);
        //        Notes = vars[6];
        //    }
        //    KACAlarm resultAlarm = new KACAlarm(UT);
        //    resultAlarm.Name = Name;
        //    resultAlarm.Enabled = Enabled;
        //    resultAlarm.Notes = Notes;
        //    resultAlarm.AlarmAction = KACAlarm.AlarmActionEnum.MessageOnly;
        //    if (HaltWarp)
        //        resultAlarm.AlarmAction = KACAlarm.AlarmActionEnum.KillWarp;
        //    else if (PauseGame)
        //        resultAlarm.AlarmAction = KACAlarm.AlarmActionEnum.PauseGame;
        //    return resultAlarm;
        //}
        internal static KACAlarm LoadFromString2(String AlarmDetails)
        {
            String[] vars = AlarmDetails.Split("|".ToCharArray(), StringSplitOptions.None);
            String SaveName = HighLogic.CurrentGame.Title;
            String VesselID = vars[0];
            String Name = vars[1];
            String Notes = vars[2];
            Double UT = Convert.ToDouble(vars[3]);
            Double AlarmMarginSecs = Convert.ToDouble(vars[4]);
            KACAlarm.AlarmTypeEnum TypeOfAlarm = (KACAlarm.AlarmTypeEnum)Enum.Parse(typeof(KACAlarm.AlarmTypeEnum), vars[5]);
            Boolean Enabled = Convert.ToBoolean(vars[6]);
            Boolean HaltWarp = Convert.ToBoolean(vars[7]);
            Boolean PauseGame = Convert.ToBoolean(vars[8]);

            String strOptions = vars[9];

            List<ManeuverNode> ManNodes = null;
            String XferOriginBodyName="", XferTargetBodyName="";
            ITargetable TargetObject = null;
            String TargetLoader="";

            switch (TypeOfAlarm)
            {
                case KACAlarm.AlarmTypeEnum.Maneuver:
                    //Generate the Nodes List from the string
                    ManNodes = ManNodeDeserializeList(strOptions);
                    break;
                case KACAlarm.AlarmTypeEnum.Transfer:
                    try
                    {
                        String[] XferParts = strOptions.Split(",".ToCharArray());
                        XferOriginBodyName = XferParts[0];
                        XferTargetBodyName = XferParts[1];
                    }
                    catch (Exception ex)
                    {
                        MonoBehaviourExtended.LogFormatted("Unable to load transfer details for {0}", Name);
                        MonoBehaviourExtended.LogFormatted(ex.Message);
                    }
                    break;
                case KACAlarm.AlarmTypeEnum.AscendingNode:
                case KACAlarm.AlarmTypeEnum.DescendingNode:
                case KACAlarm.AlarmTypeEnum.LaunchRendevous:
                    if (strOptions != "")
                    {
                        //find the targetable object and set it
                        TargetObject = TargetDeserialize(strOptions);
                        if (TargetObject == null && strOptions.StartsWith("Vessel,"))
                            TargetLoader = strOptions;
                    }
                    break;
                default:
                    break;
            }

            KACAlarm resultAlarm = new KACAlarm(UT);
            resultAlarm.Name = Name;
            resultAlarm.VesselID = VesselID;
            resultAlarm.Enabled = Enabled;
            resultAlarm.Notes = Notes;
            resultAlarm.AlarmMarginSecs = AlarmMarginSecs;
            resultAlarm.TypeOfAlarm = TypeOfAlarm;
            if (HaltWarp)
                resultAlarm.AlarmActionConvert = KACAlarm.AlarmActionEnum.KillWarp;
            else if (PauseGame)
                resultAlarm.AlarmActionConvert = KACAlarm.AlarmActionEnum.PauseGame;

            if (ManNodes != null)
                resultAlarm.ManNodes = ManNodes;
            if (TargetObject != null)
                resultAlarm.TargetObject = TargetObject;
            resultAlarm.TargetLoader = TargetLoader;

            resultAlarm.XferOriginBodyName = XferOriginBodyName;
            resultAlarm.XferTargetBodyName = XferTargetBodyName;

            return resultAlarm;
        }
        private void WindowLayout_AddPane_NodeEvent(Boolean PointFound,Double timeToPoint)
        {
            GUILayout.BeginVertical();
            GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading);
            if (lstAlarmsWithTarget.Contains(AddType))
            {
                if (KACWorkerGameState.CurrentVesselTarget == null)
                    GUILayout.Label("Equatorial Nodes (No Valid Target)", KACResources.styleAddXferName, GUILayout.Height(18));
                else
                {
                    if (KACWorkerGameState.CurrentVesselTarget is Vessel)
                        GUILayout.Label("Target Vessel: " + KACWorkerGameState.CurrentVesselTarget.GetVessel().vesselName, KACResources.styleAddXferName,GUILayout.Height(18));
                    else if (KACWorkerGameState.CurrentVesselTarget is CelestialBody)
                        GUILayout.Label("Target Body: " + ((CelestialBody)KACWorkerGameState.CurrentVesselTarget).bodyName, KACResources.styleAddXferName,GUILayout.Height(18));
                    else
                        GUILayout.Label("Object Targeted", KACResources.styleAddXferName, GUILayout.Height(18));
                        //GUILayout.Label("Target Vessel: " + KACWorkerGameState.CurrentVesselTarget.GetVessel().vesselName, KACResources.styleAddXferName, GUILayout.Height(18));
                }
            }

            if (KACWorkerGameState.CurrentVessel == null)
                GUILayout.Label("No Active Vessel");
            else
            {
                if (!PointFound)
                {
                    GUILayout.Label("No " + strAlarmEventName + " Point Found on current plan", GUILayout.ExpandWidth(true));
                }
                else
                {
                    String strMarginConversion = "";
                    KACTime eventTime = new KACTime(KACWorkerGameState.CurrentTime.UT + timeToPoint);
                    KACTime eventInterval = new KACTime(timeToPoint);

                    KACTime eventAlarm;
                    KACTime eventAlarmInterval;
                    try
                    {
                        eventAlarm = new KACTime(eventTime.UT - timeMargin.UT);
                        eventAlarmInterval = new KACTime(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT);
                    }
                    catch (Exception)
                    {
                        eventAlarm = null;
                        eventAlarmInterval = null;
                        strMarginConversion = "Unable to Add the Margin Minutes";
                    }

                    if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "")
                    {
                        if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval))
                        {
                            KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes, eventAlarm.UT, timeMargin.UT, AddType,
                                (AddAction == KACAlarm.AlarmAction.KillWarp), (AddAction == KACAlarm.AlarmAction.PauseGame));
                            if (lstAlarmsWithTarget.Contains(AddType))
                                newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;

                            Settings.Alarms.Add(newAlarm);
                            Settings.Save();
                            _ShowAddPane = false;
                        }
                    }
                    else
                    {
                        strMarginConversion = "No Future " + strAlarmEventName + "Points found";
                    }

                    if (strMarginConversion != "")
                        GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true));
                }
            }

            GUILayout.EndVertical();
        }
        private Boolean DrawAlarmLine(KACAlarm tmpAlarm)
        {
            Boolean blnReturn = false;

            GUILayout.BeginHorizontal();

            switch (tmpAlarm.TypeOfAlarm)
            {
                case KACAlarm.AlarmType.Raw:
                    GUILayout.Label(KACResources.iconRaw, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Maneuver:
                case KACAlarm.AlarmType.ManeuverAuto:
                    GUILayout.Label(KACResources.iconMNode, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.SOIChange:
                case KACAlarm.AlarmType.SOIChangeAuto:
                    GUILayout.Label(KACResources.iconSOI, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Transfer:
                case KACAlarm.AlarmType.TransferModelled:
                    GUILayout.Label(KACResources.iconXFer, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Apoapsis:
                    GUILayout.Label(KACResources.iconAp, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Periapsis:
                    GUILayout.Label(KACResources.iconPe, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.AscendingNode:
                    GUILayout.Label(KACResources.iconAN, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.DescendingNode:
                    GUILayout.Label(KACResources.iconDN, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.LaunchRendevous:
                    GUILayout.Label(KACResources.iconLaunchRendezvous, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Closest:
                    GUILayout.Label(KACResources.iconClosest, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Distance:
                    //TODO - SOMETHING HERE MAYBE
                    GUILayout.Label(KACResources.iconClosest, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.Crew:
                    GUILayout.Label(KACResources.iconCrew, KACResources.styleAlarmIcon);
                    break;
                case KACAlarm.AlarmType.EarthTime:
                    GUILayout.Label(KACResources.iconEarth, KACResources.styleAlarmIcon);
                    break;
                default:
                    GUILayout.Label(KACResources.iconNone, KACResources.styleAlarmIcon);
                    break;
            }

            //Set the Content up
            //int intMaxWidth = intTestheight;
            //String strTimeToAlarm = String.Format(" ({0})",KerbalTime.PrintInterval(tmpAlarm.Remaining, Settings.TimeFormat));
            //float fTimeToAlarmWidth;
            //KACResources.styleAlarmText.CalcMinMaxWidth(new GUIContent(strTimeToAlarm),out fOutMin1,out fOutMax1);
            //fTimeToAlarmWidth = fOutMax1;

            //String strTextToDisplay = tmpAlarm.Name;
            //KACResources.styleAlarmText.CalcMinMaxWidth(new GUIContent(strTextToDisplay), out fOutMin, out fOutMax);
            //while (strTextToDisplay.Length>10 &&(  fOutMax+fTimeToAlarmWidth>intMaxWidth) )
            //{
            //    strTextToDisplay = strTextToDisplay.Remove(strTextToDisplay.Length - 2);
            //    KACResources.styleAlarmText.CalcMinMaxWidth(new GUIContent(strTextToDisplay), out fOutMin, out fOutMax);
            //}

            ////String strLabelText = strTextToDisplay + strTimeToAlarm;
            //String strTimeText = String.Format("({0})", KerbalTime.PrintInterval(tmpAlarm.Remaining, Settings.TimeFormat));
            //String strLabelText = tmpAlarm.Name;

            //GUIStyle styleLabel = new GUIStyle(KACResources.styleAlarmText);
            //if ((!tmpAlarm.Enabled || tmpAlarm.Actioned))
            //    styleLabel.normal.textColor=Color.gray;

            //GUIStyle styleTime = new GUIStyle(styleLabel);
            //styleTime.stretchWidth = true;

            //GUIContent contAlarmLabel = new GUIContent(strLabelText, tmpAlarm.Notes);
            //GUIContent contAlarmTime = new GUIContent(strTimeText, tmpAlarm.Notes);

            ////calc correct width for first part
            //KACResources.styleAlarmText.CalcMinMaxWidth(contAlarmTime, out fOutMin, out fOutMax);
            //styleLabel.CalcMinMaxWidth(contAlarmLabel, out fOutMin1, out fOutMax1);

            //int intMaxWidth = intTestheight;
            //if (fOutMax1 + fOutMax > intMaxWidth)
            //    fOutMax1 = intMaxWidth - fOutMax;

            //if ((alarmEdit == tmpAlarm) && _ShowEditPane)
            //{
            //    intMaxWidth -= 20;
            //}

            //float width1 = fOutMin1;

            String strLabelText = "";
            strLabelText = String.Format("{0} ({1})", tmpAlarm.Name, KACTime.PrintInterval(tmpAlarm.Remaining, Settings.TimeFormat));

            GUIStyle styleLabel = new GUIStyle( KACResources.styleAlarmText);
            if ((!tmpAlarm.Enabled || tmpAlarm.Actioned))
                styleLabel.normal.textColor=Color.gray;
            GUIContent contAlarmLabel = new GUIContent(strLabelText, tmpAlarm.Notes);

            //Calc the line height
            ////////////////////////////////////////////////////
            //Currently the max width doesnt work out when an alarm is in edit mode correctly in edit mode
            //Also need to test max list length and when the scrollbar kicks in
            ///////////////////////////////////////////////////
            Single sOutMin1,sOutMax1;
            styleLabel.CalcMinMaxWidth(contAlarmLabel,out sOutMin1, out sOutMax1);
            tmpAlarm.AlarmLineWidth  = Convert.ToInt32(sOutMax1);
            Int32 intMaxwidth = 220;// 228;
            if (_ShowEditPane && (alarmEdit == tmpAlarm)) intMaxwidth = 198;// 216;
            tmpAlarm.AlarmLineHeight = Convert.ToInt32(styleLabel.CalcHeight(contAlarmLabel, intMaxwidth));

            //Draw a button that looks like a label.
            if (GUILayout.Button(contAlarmLabel, styleLabel, GUILayout.MaxWidth(218)))
            {
                if (!_ShowSettings)
                {
                    if (alarmEdit == tmpAlarm)
                    {
                        //If there was an alarm open, then save em again
                        if (_ShowEditPane) Settings.Save();
                        _ShowEditPane = !_ShowEditPane;
                    }
                    else
                    {
                        //If there was an alarm open, then save em again
                        if (_ShowEditPane) Settings.Save();
                        alarmEdit = tmpAlarm;
                        _ShowEditPane = true;
                        _ShowSettings = false;
                        _ShowAddPane = false;
                    }
                }
            }

            if ((alarmEdit == tmpAlarm) && _ShowEditPane)
            {
                GUILayout.Label(new GUIContent(KACResources.iconEdit, "Editing..."), KACResources.styleLabelWarp);
            }
            if (tmpAlarm.PauseGame)
            {
                GUILayout.Label(new GUIContent(KACResources.GetPauseListIcon(tmpAlarm.WarpInfluence),"Pause"), KACResources.styleLabelWarp);
            }
            else if (tmpAlarm.HaltWarp)
            {
                GUILayout.Label(new GUIContent(KACResources.GetWarpListIcon(tmpAlarm.WarpInfluence), "Kill Warp"), KACResources.styleLabelWarp);
            }
            else
            {
                GUILayout.Label(new GUIContent(KACResources.iconNone), KACResources.styleLabelWarp);
            }

            if (GUILayout.Button(new GUIContent(KACResources.btnRedCross,"Delete Alarm"), GUI.skin.button, GUILayout.MaxWidth(20), GUILayout.MaxHeight(20)))
                blnReturn = true;

            GUILayout.EndHorizontal();

            return blnReturn;
        }
        private void WindowLayout_AddPane_ClosestApproach()
        {
            GUILayout.BeginVertical();
            GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading);

            if (KACWorkerGameState.CurrentVessel == null)
                GUILayout.Label("No Active Vessel");
            else
            {
                if (!(KACWorkerGameState.CurrentVesselTarget is Vessel) && !(KACWorkerGameState.CurrentVesselTarget is ModuleDockingNode))
                {
                    GUILayout.Label("No valid Vessel Target Selected", GUILayout.ExpandWidth(true));
                }
                else
                {
                    //GUILayout.Label("Adjust Lookahead amounts...", KACResources.styleAddSectionHeading);

                    GUILayout.BeginVertical(KACResources.styleAddFieldAreas);

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110));
                    GUILayout.Label(((int)Math.Round((Decimal)fltOrbits, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25));
                    fltOrbits = GUILayout.HorizontalSlider(fltOrbits, 1, 20);
                    fltOrbits = (float)Math.Floor((Decimal)fltOrbits);
                    GUILayout.EndHorizontal();

                    intOrbits = (int)fltOrbits;
                    int intClosestOrbitPass = 0;
                    double dblClosestDistance = Double.MaxValue;
                    double dblClosestUT = 0;

                    double dblOrbitTestClosest = Double.MaxValue;
                    double dblOrbitTestClosestUT = 0;
                    for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits; intOrbitToTest++)
                    {
                        dblOrbitTestClosestUT = KACUtils.timeOfClosestApproach(KACWorkerGameState.CurrentVessel.orbit,
                                                                            KACWorkerGameState.CurrentVesselTarget.GetOrbit(),
                                                                            KACWorkerGameState.CurrentTime.UT,
                                                                            intOrbitToTest,
                                                                            out dblOrbitTestClosest
                                                                            );
                        if (dblOrbitTestClosest < dblClosestDistance)
                        {
                            dblClosestDistance = dblOrbitTestClosest;
                            dblClosestUT = dblOrbitTestClosestUT;
                            intClosestOrbitPass = intOrbitToTest;
                        }
                    }

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Distance:", KACResources.styleAddHeading, GUILayout.Width(70));
                    String strDistance = string.Format("{0:#}m", dblClosestDistance);
                    if (dblClosestDistance > 999) strDistance = string.Format("{0:#.0}km", dblClosestDistance / 1000);
                    GUILayout.Label(strDistance, KACResources.styleAddXferName, GUILayout.Width(90));
                    GUILayout.Label("On Orbit:", KACResources.styleAddHeading);
                    GUILayout.Label(intClosestOrbitPass.ToString(), KACResources.styleAddXferName);
                    GUILayout.EndHorizontal();
                    GUILayout.EndVertical();

                    String strMarginConversion = "";
                    KACTime eventTime = new KACTime(dblClosestUT);
                    KACTime eventInterval = new KACTime(dblClosestUT - KACWorkerGameState.CurrentTime.UT);

                    KACTime eventAlarm;
                    KACTime eventAlarmInterval;
                    try
                    {
                        eventAlarm = new KACTime(eventTime.UT - timeMargin.UT);
                        eventAlarmInterval = new KACTime(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT);
                    }
                    catch (Exception)
                    {
                        eventAlarm = null;
                        eventAlarmInterval = null;
                        strMarginConversion = "Unable to Add the Margin Minutes";
                    }

                    if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "")
                    {
                        if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval))
                        {
                            KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes,
                                eventAlarm.UT, timeMargin.UT, AddType,
                                (AddAction == KACAlarm.AlarmAction.KillWarp), (AddAction == KACAlarm.AlarmAction.PauseGame));
                            newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;
                            newAlarm.ManNodes = KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes;

                            Settings.Alarms.Add(newAlarm);
                            Settings.Save();
                            _ShowAddPane = false;
                        }
                    }
                    else
                    {
                        strMarginConversion = "No Future Closest Approach found";
                    }

                    if (strMarginConversion != "")
                        GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true));
                }
            }

            GUILayout.EndVertical();
        }
        private void WindowLayout_AddPane_Contract()
        {
            GUILayout.Label("Select Contract...", KACResources.styleAddSectionHeading);
            if (Contracts.ContractSystem.Instance == null)
            {
                GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
                GUILayout.Label("Jebediah digs around in the Sandbox, but can't\nfind any contracts in this game mode", KACResources.styleContent);
                GUILayout.EndVertical();
            }
            else
            {

                if (lstContracts.Count == 0)
                {
                    GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
                    GUILayout.Label("No Contracts Offered or Active", KACResources.styleContent);
                    GUILayout.EndVertical();
                }
                else
                {

                    scrollContract = GUILayout.BeginScrollView(scrollContract, KACResources.styleAddFieldAreas);

                    //If the selected contract is already an alarm then move the selected one
                    if (intSelectedContract == -1  || alarms.Any(a => a.ContractGUID == lstContracts[intSelectedContract].ContractGuid)){
                        intSelectedContract = -1;
                        for (int i = 0; i < lstContracts.Count; i++) {
                            if(!alarms.Any(a => a.ContractGUID == lstContracts[i].ContractGuid)){
                                intSelectedContract = i;
                                BuildContractStringsAndMargin();
                                break;
                            }
                        }
                    }

                    //Loop through the contracts to draw the lines
                    for (Int32 intTarget = 0; intTarget < lstContracts.Count; intTarget++)
                    {
                        Contract c = lstContracts[intTarget];
                        Boolean AlarmExists = alarms.Any(a => a.ContractGUID == c.ContractGuid);

                        GUILayout.BeginHorizontal();
                        //Appropriate icon
                        GUILayout.Space(5);
                        if (AlarmExists) {
                            GUILayout.Label(new GUIContent(KACResources.iconRaw, "Alarm Exists"), GUILayout.Width(20), GUILayout.Height(25));
                        } else if (c.ContractState == Contract.State.Active) {
                            GUILayout.Label(new GUIContent(KACResources.iconContract, "Active"), GUILayout.Width(20), GUILayout.Height(25));
                        } else {
                            GUILayout.Space(24);
                        }

                        //What style should the name be
                        GUIStyle styleContLabel = KACResources.styleContractLabelOffer;
                        if (c.ContractState == Contract.State.Active)
                            styleContLabel = KACResources.styleContractLabelActive;
                        else if (AlarmExists)
                            styleContLabel = KACResources.styleContractLabelAlarmExists;

                        if (GUILayout.Button(c.Title, styleContLabel, GUILayout.Width(243)))
                        {
                            if (!AlarmExists)
                            {
                                intSelectedContract = intTarget;
                                BuildContractStringsAndMargin();
                            }
                        };

                        //Is the check box on?
                        Boolean blnSelected = (intSelectedContract == intTarget);

                        if (!AlarmExists)
                        {
                            if (DrawToggle(ref blnSelected, "", KACResources.styleCheckbox, GUILayout.Width(20)))
                            {
                                if (blnSelected)
                                {
                                    intSelectedContract = intTarget;
                                    BuildContractStringsAndMargin();
                                }
                            }
                        } GUILayout.EndHorizontal();
                    }
                    GUILayout.EndScrollView();

                    if (intSelectedContract < 0) {
                        GUILayout.Label("All Contracts Have alarms set already", KACResources.styleContent);
                    } else {
                        //Draw the Add Alarm details at the bottom
                        //If its an interval add the interval to the current time
                        ContractTime = new KSPDateTime(lstContracts[intSelectedContract].DateNext());
                        ContractTimeToEvent = new KSPTimeSpan(lstContracts[intSelectedContract].DateNext() - KACWorkerGameState.CurrentTime.UT);
                        ContractTimeToAlarm = new KSPTimeSpan(ContractTimeToEvent.UT - timeMargin.UT);

                        if (DrawAddAlarm(ContractTime, ContractTimeToEvent, ContractTimeToAlarm))
                        {
                            //"VesselID, Name, Message, AlarmTime.UT, Type, Enabled,  HaltWarp, PauseGame, Maneuver"
                            String strVesselID = "";
                            if (KACWorkerGameState.CurrentVessel != null && blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();
                            KACAlarm tmpAlarm = new KACAlarm(strVesselID, strAlarmName, strAlarmNotes, KACWorkerGameState.CurrentTime.UT + ContractTimeToAlarm.UT,
                                timeMargin.UT, KACAlarm.AlarmTypeEnum.Contract, AddActions);

                            tmpAlarm.ContractGUID = lstContracts[intSelectedContract].ContractGuid;
                            tmpAlarm.ContractAlarmType = lstContracts[intSelectedContract].AlarmType();

                            alarms.Add(tmpAlarm);
                            //settings.Save();
                            _ShowAddPane = false;
                        }
                    }
                }
            }
        }
        private int DrawTransferAngleButtons(KACAlarm tmpAlarm)
        {
            if((tmpAlarm.TypeOfAlarm== KACAlarm.AlarmTypeEnum.Transfer|| tmpAlarm.TypeOfAlarm == KACAlarm.AlarmTypeEnum.TransferModelled) &&
                (HighLogic.LoadedScene == GameScenes.TRACKSTATION || HighLogic.LoadedScene == GameScenes.FLIGHT))
            {
                //right type of alarm, now is the text there
                Match matchPhase = Regex.Match(tmpAlarm.Notes, "(?<=Phase\\sAngle\\:\\s+)\\S+(?=°)");
                Match matchEjectPro = Regex.Match(tmpAlarm.Notes, "(?<=Ejection\\sAngle\\:\\s+)\\S+(?=°\\sto\\sprograde)");
                Match matchEjectRetro = Regex.Match(tmpAlarm.Notes, "(?<=Ejection\\sAngle\\:\\s+)\\S+(?=°\\sto\\sretrograde)");
                if (matchPhase.Success && (matchEjectPro.Success || matchEjectRetro.Success))
                {

                    try
                    {
                        //LogFormatted_DebugOnly("{0}", matchPhase.Value);
                        Double dblPhase = Convert.ToDouble(matchPhase.Value);
                        Double dblEject;
                        if (matchEjectPro.Success)
                            dblEject = Convert.ToDouble(matchEjectPro.Value);
                        else
                            dblEject = Convert.ToDouble(matchEjectRetro.Value);

                        GUILayout.BeginHorizontal();

                        CelestialBody cbOrigin = FlightGlobals.Bodies.Single(b => b.bodyName == tmpAlarm.XferOriginBodyName);
                        CelestialBody cbTarget = FlightGlobals.Bodies.Single(b => b.bodyName == tmpAlarm.XferTargetBodyName);

                        GUIStyle styleAngleButton = new GUIStyle(KACResources.styleSmallButton) { fixedWidth = 180 };

                        if (DrawToggle(ref blnShowPhaseAngle,"Show Phase Angle", styleAngleButton)){
                            if (blnShowPhaseAngle)
                            {
                                EjectAngle.HideAngle();
                                blnShowEjectAngle = false;
                                PhaseAngle.DrawAngle(cbOrigin, cbTarget, dblPhase);
                            }
                            else
                                PhaseAngle.HideAngle();
                        }
                        if (DrawToggle(ref blnShowEjectAngle, "Show Eject Angle", styleAngleButton))
                        {
                            if (blnShowEjectAngle)
                            {
                                PhaseAngle.HideAngle();
                                blnShowPhaseAngle = false;
                                EjectAngle.DrawAngle(cbOrigin, dblEject, matchEjectRetro.Success);
                            }
                            else
                                EjectAngle.HideAngle();
                        }
                        GUILayout.EndHorizontal();

                        //if (GUILayout.Toggle()) {

                        //}
                        //GUILayout.Label(String.Format("P:{0} - E:{1}",dblPhase,dblEject));

                        return 1;

                    }
                    catch (Exception)
                    {
                        GUILayout.Label("Unable to decipher TWP Phase and Eject Angle found in notes");
                        return 1;
                    }
                } else {
                    GUILayout.Label("No TWP Phase and Eject Angle found in notes");
                    return 1;
                }
            } else { return 0; }
        }
        private void WindowLayout_AddPane_Transfer()
        {
            intAddXferHeight = 304;// 317;

            if (settings.RSSActive) {
                GUILayout.Label("RSS detected - it is recommended that you use the Transfer Window Planner Plugin to plan transfers", KACResources.styleAddXferName);
                GUILayout.Space(-8);
                if (GUILayout.Button("Click here to open the TWP forum thread", KACResources.styleContent))
                    Application.OpenURL("http://forum.kerbalspaceprogram.com/threads/93115");
                intAddXferHeight += 58;
            }

            KSPDateTime XferCurrentTargetEventTime = null;
            List<KSPDateTime> lstXferCurrentTargetEventTime = new List<KSPDateTime>();
            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal();
            GUILayout.Label("Transfers", KACResources.styleAddSectionHeading, GUILayout.Width(60));
            //add something here to select the modelled or formula values for Solar orbiting bodies
            if (settings.XferModelDataLoaded)
            {
                GUILayout.FlexibleSpace();
                GUILayout.Label("Calc by:", KACResources.styleAddHeading);
                if (intXferCurrentParent == 0)
                {
                    //intAddXferHeight += 35;
                    if (DrawRadioList(ref intXferType, "Model", "Formula"))
                    {
                        settings.XferUseModelData = (intXferType == 0);
                        settings.Save();
                    }
                }
                else
                {
                    int zero = 0;
                    DrawRadioList(ref zero, "Formula");
                }
            }
            GUILayout.EndHorizontal();
            try
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Xfer Parent:", KACResources.styleAddHeading, GUILayout.Width(80), GUILayout.Height(20));
                GUILayout.Label(XferParentBodies[intXferCurrentParent].bodyName, KACResources.styleAddXferName, GUILayout.ExpandWidth(true), GUILayout.Height(20));
                if (GUILayout.Button(new GUIContent("Change", "Click to cycle through Parent Bodies"), KACResources.styleAddXferOriginButton))
                {
                    intXferCurrentParent += 1;
                    if (intXferCurrentParent >= XferParentBodies.Count) intXferCurrentParent = 0;
                    SetupXferOrigins();
                    intXferCurrentOrigin = 0;
                    SetupXFerTargets();
                    BuildTransferStrings();
                    //strAlarmNotesNew = String.Format("{0} Transfer", XferOriginBodies[intXferCurrentOrigin].bodyName);
                }
                GUILayout.Space(34);
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                GUILayout.Label("Xfer Origin:", KACResources.styleAddHeading, GUILayout.Width(80),GUILayout.Height(20));
                GUILayout.Label(XferOriginBodies[intXferCurrentOrigin].bodyName, KACResources.styleAddXferName, GUILayout.ExpandWidth(true), GUILayout.Height(20));
                if (GUILayout.Button(new GUIContent("Change", "Click to cycle through Origin Bodies"), KACResources.styleAddXferOriginButton))
                {
                    intXferCurrentOrigin += 1;
                    if (intXferCurrentOrigin >= XferOriginBodies.Count) intXferCurrentOrigin = 0;
                    SetupXFerTargets();
                    BuildTransferStrings();
                    //strAlarmNotesNew = String.Format("{0} Transfer", XferOriginBodies[intXferCurrentOrigin].bodyName);
                }

                if (!settings.AlarmXferDisplayList)
                    GUILayout.Space(34);
                else
                    if (GUILayout.Button(new GUIContent(KACResources.btnChevronUp, "Hide Full List"), KACResources.styleSmallButton))
                    {
                        settings.AlarmXferDisplayList = !settings.AlarmXferDisplayList;
                        settings.Save();
                    }
                GUILayout.EndHorizontal();

                if (!settings.AlarmXferDisplayList)
                {
                    //Simple single chosen target
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Xfer Target:", KACResources.styleAddHeading, GUILayout.Width(80), GUILayout.Height(20));
                    GUILayout.Label(XferTargetBodies[intXferCurrentTarget].Target.bodyName, KACResources.styleAddXferName, GUILayout.ExpandWidth(true), GUILayout.Height(20));
                    if (GUILayout.Button(new GUIContent("Change", "Click to cycle through Target Bodies"), KACResources.styleAddXferOriginButton))
                    {
                        intXferCurrentTarget += 1;
                        if (intXferCurrentTarget >= XferTargetBodies.Count) intXferCurrentTarget = 0;
                        SetupXFerTargets();
                        BuildTransferStrings();
                        //strAlarmNotesNew = String.Format("{0} Transfer", XferTargetBodies[intXferCurrentTarget].Target.bodyName);
                    }
                    if (GUILayout.Button(new GUIContent(KACResources.btnChevronDown, "Show Full List"), KACResources.styleSmallButton))
                    {
                        settings.AlarmXferDisplayList = !settings.AlarmXferDisplayList;
                        settings.Save();
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Phase Angle-Current:",  KACResources.styleAddHeading,GUILayout.Width(130));
                    GUILayout.Label(String.Format("{0:0.00}", XferTargetBodies[intXferCurrentTarget].PhaseAngleCurrent), KACResources.styleContent, GUILayout.Width(67));
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Phase Angle-Target:", KACResources.styleAddHeading, GUILayout.Width(130));
                    if (intXferCurrentParent != 0 || (!settings.XferUseModelData && settings.XferModelDataLoaded))
                    {
                        //formula based
                        GUILayout.Label(String.Format("{0:0.00}", XferTargetBodies[intXferCurrentTarget].PhaseAngleTarget), KACResources.styleContent, GUILayout.Width(67));
                    }
                    else
                    {
                        //this is the modelled data, but only for Kerbol orbiting bodies
                        try
                        {
                            KACXFerModelPoint tmpModelPoint = KACResources.lstXferModelPoints.FirstOrDefault(
                            m => FlightGlobals.Bodies[m.Origin] == XferTargetBodies[intXferCurrentTarget].Origin &&
                                FlightGlobals.Bodies[m.Target] == XferTargetBodies[intXferCurrentTarget].Target &&
                                m.UT >= KACWorkerGameState.CurrentTime.UT);

                            if (tmpModelPoint != null)
                            {
                                GUILayout.Label(String.Format("{0:0.00}", tmpModelPoint.PhaseAngle), KACResources.styleContent, GUILayout.Width(67));
                                XferCurrentTargetEventTime = new KSPDateTime(tmpModelPoint.UT);
                            }
                            else
                            {
                                GUILayout.Label("No future model data available for this transfer", KACResources.styleContent, GUILayout.ExpandWidth(true));
                            }
                        }
                        catch (Exception ex)
                        {
                            GUILayout.Label("Unable to determine model data", KACResources.styleContent, GUILayout.ExpandWidth(true));
                            LogFormatted("Error determining model data: {0}", ex.Message);
                        }
                    }
                    GUILayout.EndHorizontal();
                }
                else
                {

                    //Build the list of model points for the add all button
                    for (int intTarget = 0; intTarget < XferTargetBodies.Count; intTarget++) {
                        if (!(intXferCurrentParent != 0 || (!settings.XferUseModelData && settings.XferModelDataLoaded))) {
                            try
                            {
                                KACXFerModelPoint tmpModelPoint = KACResources.lstXferModelPoints.FirstOrDefault(
                                m => FlightGlobals.Bodies[m.Origin] == XferTargetBodies[intTarget].Origin &&
                                    FlightGlobals.Bodies[m.Target] == XferTargetBodies[intTarget].Target &&
                                    m.UT >= KACWorkerGameState.CurrentTime.UT);

                                if (tmpModelPoint != null) {
                                    lstXferCurrentTargetEventTime.Add(new KSPDateTime(tmpModelPoint.UT));
                                }
                            }
                            catch (Exception ex)
                            {
                                LogFormatted("Error determining model data: {0}", ex.Message);
                            }
                        }
                    }

                    // Now do the add all buttons
                    intAddXferHeight += 28;
                    if (intXferCurrentParent != 0 || (!settings.XferUseModelData && settings.XferModelDataLoaded))
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button(new GUIContent("Create Alarms for All", "Create Alarms for all listed transfers"), new GUIStyle(KACResources.styleAddXferOriginButton) { fixedWidth = 140 }))
                        {
                            for (int i = 0; i < XferTargetBodies.Count; i++)
                            {
                                String strVesselID = "";
                                if (blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();

                                TransferStrings ts = BuildTransferStrings(i, false);
                                alarms.Add(new KACAlarm(strVesselID, ts.AlarmName, ts.AlarmNotes + "\r\n\tMargin: " + new KSPTimeSpan(timeMargin.UT).ToStringStandard(TimeSpanStringFormatsEnum.IntervalLongTrimYears),
                                (KACWorkerGameState.CurrentTime.UT + XferTargetBodies[i].AlignmentTime.UT - timeMargin.UT), timeMargin.UT, KACAlarm.AlarmTypeEnum.Transfer,
                                AddActions, XferTargetBodies[i]));
                            }
                            _ShowAddPane = false;
                        }
                        GUILayout.EndHorizontal();
                    } else {
                        //Model based

                        GUILayout.BeginHorizontal();
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button(new GUIContent("Create Alarms for All", "Create Alarms for all listed transfers"), new GUIStyle(KACResources.styleAddXferOriginButton) { fixedWidth = 140 }))
                        {
                            for (int i = 0; i < XferTargetBodies.Count; i++)
                            {
                                String strVesselID = "";
                                if (blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();

                                TransferStrings ts = BuildTransferStrings(i, false);
                                KACAlarm alarmNew = new KACAlarm(strVesselID, ts.AlarmName, (blnRepeatingAlarmFlag ? "Alarm Repeats\r\n" : "") + ts.AlarmNotes + "\r\n\tMargin: " + new KSPTimeSpan(timeMargin.UT).ToStringStandard(TimeSpanStringFormatsEnum.IntervalLongTrimYears),
                                    (lstXferCurrentTargetEventTime[i].UT - timeMargin.UT), timeMargin.UT, KACAlarm.AlarmTypeEnum.TransferModelled,
                                    AddActions, XferTargetBodies[i]);
                                alarmNew.RepeatAlarm = blnRepeatingAlarmFlag;
                                alarms.Add(alarmNew);
                            }
                            _ShowAddPane = false;
                        }
                        GUILayout.EndHorizontal();
                    }

                    GUIStyle styleTemp = new GUIStyle();
                    xferListScrollPosition = GUILayout.BeginScrollView(xferListScrollPosition, styleTemp);

                    // And now the table of results
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Target", KACResources.styleAddSectionHeading, GUILayout.Width(55));
                    GUILayout.Label(new GUIContent("Phase Angle", "Displayed as \"Current Angle (Target Angle)\""), KACResources.styleAddSectionHeading, GUILayout.Width(105));
                    GUILayout.Label("Time to Transfer", KACResources.styleAddSectionHeading, GUILayout.ExpandWidth(true));
                    //GUILayout.Label("Time to Alarm", KACResources.styleAddSectionHeading, GUILayout.ExpandWidth(true));
                    GUILayout.Label("Add", KACResources.styleAddSectionHeading, GUILayout.Width(30));
                    GUILayout.EndHorizontal();

                    for (int intTarget = 0; intTarget < XferTargetBodies.Count; intTarget++)
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.Label(XferTargetBodies[intTarget].Target.bodyName, KACResources.styleAddXferName, GUILayout.Width(55), GUILayout.Height(20));
                        if (intXferCurrentParent != 0 || (!settings.XferUseModelData && settings.XferModelDataLoaded))
                        {
                            //formula based
                            String strPhase = String.Format("{0:0.00}({1:0.00})", XferTargetBodies[intTarget].PhaseAngleCurrent, XferTargetBodies[intTarget].PhaseAngleTarget);
                            GUILayout.Label(strPhase, KACResources.styleAddHeading, GUILayout.Width(105), GUILayout.Height(20));
                            GUILayout.Label(XferTargetBodies[intTarget].AlignmentTime.ToStringStandard(settings.TimeSpanFormat), KACResources.styleAddHeading, GUILayout.ExpandWidth(true), GUILayout.Height(20));
                        }
                        else
                        {
                            try
                            {
                                KACXFerModelPoint tmpModelPoint = KACResources.lstXferModelPoints.FirstOrDefault(
                                m => FlightGlobals.Bodies[m.Origin] == XferTargetBodies[intTarget].Origin &&
                                    FlightGlobals.Bodies[m.Target] == XferTargetBodies[intTarget].Target &&
                                    m.UT >= KACWorkerGameState.CurrentTime.UT);

                                if (tmpModelPoint != null)
                                {
                                    String strPhase = String.Format("{0:0.00}({1:0.00})", XferTargetBodies[intTarget].PhaseAngleCurrent, tmpModelPoint.PhaseAngle);
                                    GUILayout.Label(strPhase, KACResources.styleAddHeading, GUILayout.Width(105), GUILayout.Height(20));
                                    KSPTimeSpan tmpTime = new KSPTimeSpan(tmpModelPoint.UT - KACWorkerGameState.CurrentTime.UT);
                                    GUILayout.Label(tmpTime.ToStringStandard(settings.TimeSpanFormat), KACResources.styleAddHeading, GUILayout.ExpandWidth(true), GUILayout.Height(20));

                                    if (intTarget==intXferCurrentTarget)
                                        XferCurrentTargetEventTime = new KSPDateTime(tmpModelPoint.UT);

                                    // Doing this at the top of the loop now
                                    //lstXferCurrentTargetEventTime.Add(new KSPDateTime(tmpModelPoint.UT));
                                }
                                else
                                {
                                    GUILayout.Label("No future model data", KACResources.styleContent, GUILayout.ExpandWidth(true));
                                }
                            }
                            catch (Exception ex)
                            {
                                GUILayout.Label("Unable to determine model data", KACResources.styleContent, GUILayout.ExpandWidth(true));
                                LogFormatted("Error determining model data: {0}", ex.Message);
                            }
                        }
                        Boolean blnSelected = (intXferCurrentTarget == intTarget);
                        if (DrawToggle(ref blnSelected, "", KACResources.styleCheckbox, GUILayout.Width(42)))
                        {
                            if (blnSelected)
                            {
                                intXferCurrentTarget = intTarget;
                                BuildTransferStrings();
                            }
                        }

                        GUILayout.EndHorizontal();
                    }

                    intAddXferHeight += -56 + ( XferTargetBodies.Count * 30);

                    GUILayout.EndScrollView();
                    intAddXferHeight += 2; //For the scroll bar
                }

                if(intXferCurrentParent != 0 || (!settings.XferUseModelData && settings.XferModelDataLoaded))
                {
                    ////Formula based - Add All Alarms
                    //if (settings.AlarmXferDisplayList)
                    //{
                    //    intAddXferHeight += 28;

                    //    GUILayout.BeginHorizontal();
                    //    GUILayout.FlexibleSpace();
                    //    if (GUILayout.Button(new GUIContent("Create Alarms for All", "Create Alarms for all listed transfers"), new GUIStyle(KACResources.styleAddXferOriginButton) {fixedWidth=140 }))
                    //    {
                    //        for (int i = 0; i < XferTargetBodies.Count; i++)
                    //        {
                    //            String strVesselID = "";
                    //            if (blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();

                    //            TransferStrings ts = BuildTransferStrings(i, false);
                    //            alarms.Add(new KACAlarm(strVesselID, ts.AlarmName, ts.AlarmNotes + "\r\n\tMargin: " + new KSPTimeSpan(timeMargin.UT).ToStringStandard(TimeSpanStringFormatsEnum.IntervalLongTrimYears),
                    //            (KACWorkerGameState.CurrentTime.UT + XferTargetBodies[i].AlignmentTime.UT - timeMargin.UT), timeMargin.UT, KACAlarm.AlarmTypeEnum.Transfer,
                    //            AddActions, XferTargetBodies[i]));
                    //        }
                    //        _ShowAddPane = false;
                    //    }
                    //    GUILayout.EndHorizontal();
                    //}

                    //Formula based - add new alarm
                    if (DrawAddAlarm(new KSPDateTime(KACWorkerGameState.CurrentTime.UT + XferTargetBodies[intXferCurrentTarget].AlignmentTime.UT),
                                    XferTargetBodies[intXferCurrentTarget].AlignmentTime,
                                    new KSPTimeSpan(XferTargetBodies[intXferCurrentTarget].AlignmentTime.UT - timeMargin.UT)))
                    {
                        String strVesselID = "";
                        if (blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();
                        alarms.Add(new KACAlarm(strVesselID, strAlarmName, strAlarmNotes + "\r\n\tMargin: " + new KSPTimeSpan(timeMargin.UT).ToStringStandard(TimeSpanStringFormatsEnum.IntervalLongTrimYears),
                            (KACWorkerGameState.CurrentTime.UT + XferTargetBodies[intXferCurrentTarget].AlignmentTime.UT - timeMargin.UT), timeMargin.UT, KACAlarm.AlarmTypeEnum.Transfer,
                            AddActions, XferTargetBodies[intXferCurrentTarget]));
                        //settings.Save();
                        _ShowAddPane = false;
                    }
                }
                else
                {

                    //Model based
                    if (XferCurrentTargetEventTime!=null)
                    {
                        ////Formula based - Add All Alarms
                        //if (settings.AlarmXferDisplayList)
                        //{
                        //    intAddXferHeight += 28;

                        //    GUILayout.BeginHorizontal();
                        //    GUILayout.FlexibleSpace();
                        //    if (GUILayout.Button(new GUIContent("Create Alarms for All", "Create Alarms for all listed transfers"), new GUIStyle(KACResources.styleAddXferOriginButton) { fixedWidth = 140 }))
                        //    {
                        //        for (int i = 0; i < XferTargetBodies.Count; i++)
                        //        {
                        //            String strVesselID = "";
                        //            if (blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();

                        //            TransferStrings ts = BuildTransferStrings(i, false);

                        //            KACAlarm alarmNew = new KACAlarm(strVesselID, ts.AlarmName, (blnRepeatingAlarmFlag ? "Alarm Repeats\r\n" : "") + ts.AlarmNotes + "\r\n\tMargin: " + new KSPTimeSpan(timeMargin.UT).ToStringStandard(TimeSpanStringFormatsEnum.IntervalLongTrimYears),
                        //                (lstXferCurrentTargetEventTime[i].UT - timeMargin.UT), timeMargin.UT, KACAlarm.AlarmTypeEnum.TransferModelled,
                        //                AddActions, XferTargetBodies[i]);
                        //            alarmNew.RepeatAlarm = blnRepeatingAlarmFlag;
                        //            alarms.Add(alarmNew);
                        //        }
                        //        _ShowAddPane = false;
                        //    }
                        //    GUILayout.EndHorizontal();
                        //}

                        if (DrawAddAlarm(XferCurrentTargetEventTime,
                                    new KSPTimeSpan(XferCurrentTargetEventTime.UT - KACWorkerGameState.CurrentTime.UT),
                                    new KSPTimeSpan(XferCurrentTargetEventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT),
                                    true))
                        {
                            String strVesselID = "";
                            if (blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();
                            KACAlarm alarmNew = new KACAlarm(strVesselID, strAlarmName, (blnRepeatingAlarmFlag ? "Alarm Repeats\r\n" : "") + strAlarmNotes + "\r\n\tMargin: " + new KSPTimeSpan(timeMargin.UT).ToStringStandard(TimeSpanStringFormatsEnum.IntervalLongTrimYears),
                                (XferCurrentTargetEventTime.UT - timeMargin.UT), timeMargin.UT, KACAlarm.AlarmTypeEnum.TransferModelled,
                                AddActions, XferTargetBodies[intXferCurrentTarget]);
                            alarmNew.RepeatAlarm = blnRepeatingAlarmFlag;
                            alarms.Add(alarmNew);
                            //settings.Save();
                            _ShowAddPane = false;
                        }
                    }
                    else{
                        GUILayout.Label("Selected a transfer with no event date",GUILayout.ExpandWidth(true));
                    }
                }
            }
            catch (Exception ex)
            {
                if (intXferCurrentTarget >= XferTargetBodies.Count)
                    intXferCurrentTarget = 0;
                GUILayout.Label("Something weird has happened");
                LogFormatted(ex.Message);
                LogFormatted(ex.StackTrace);
            }

            //intAddXferHeight += intTestheight4;

            GUILayout.EndVertical();
        }
        private void WindowLayout_AddPane_ScienceLab()
        {
            intAddScienceLabHeight = 150;
            if (KACWorkerGameState.CurrentVessel == null)
            {
                GUILayout.Label("No Active Vessel.", KACResources.styleLabelWarning);
            }
            else
            {
                GUILayout.Label("Select Science Lab...", KACResources.styleAddSectionHeading);
                GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
                var lstScienceLabs = KACWorkerGameState.CurrentVessel.FindPartModulesImplementing<ModuleScienceLab>();
                if (lstScienceLabs.Count == 0)
                {
                    GUILayout.Label("No Science Labs on Active Vessel.", KACResources.styleLabelWarning);
                }
                else
                {
                    intAddScienceLabHeight += (lstScienceLabs.Count * 30);
                    GUILayout.BeginHorizontal();
                    GUILayout.Space(20);
                    GUILayout.Label("Science Lab", KACResources.styleAddSectionHeading, GUILayout.Width(240));
                    GUILayout.Label("Select", KACResources.styleAddSectionHeading);
                    GUILayout.EndHorizontal();

                    for (var i = 0; i < lstScienceLabs.Count; ++i)
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.Space(20);
                        GUILayout.Label(
                            string.Format(
                                "Science Lab {0} (Science: {1:0}, Data: {2:0})",
                                i + 1,
                                lstScienceLabs[i].storedScience,
                                lstScienceLabs[i].dataStored),
                            KACResources.styleAddXferName,
                            GUILayout.Width(240),
                            GUILayout.Height(20));

                        bool blnSelected = (intSelectedScienceLab == i);
                        if (DrawToggle(ref blnSelected, string.Empty, KACResources.styleCheckbox, GUILayout.Width(40)))
                        {
                            if (blnSelected)
                            {
                                intSelectedScienceLab = i;
                                BuildScienceLabStrings();
                            }
                        }
                        GUILayout.EndHorizontal();
                    }
                }
                GUILayout.EndVertical();

                if (intSelectedScienceLab >= 0 && intSelectedScienceLab < lstScienceLabs.Count)
                {
                    blnClearScienceLabHighlight = false;
                    var partToHighlight = lstScienceLabs[intSelectedScienceLab].part;
                    if (partToHighlight != highlightedScienceLab && highlightedScienceLab != null && highlightedScienceLab.HighlightActive)
                    {
                        highlightedScienceLab.SetHighlightDefault();
                    }

                    if (!partToHighlight.HighlightActive)
                    {
                        partToHighlight.SetHighlight(true, false);
                    }

                    partToHighlight.highlightType = Part.HighlightType.AlwaysOn;
                    partToHighlight.SetHighlightColor(Color.yellow);
                    highlightedScienceLab = partToHighlight;

                    var lab = lstScienceLabs[intSelectedScienceLab];
                    var converter = lab.Converter;
                    if (!converter.IsActivated)
                    {
                        GUILayout.Label("Science Lab is not Active.", KACResources.styleLabelWarning);
                    }
                    else if (Mathf.Approximately(lab.dataStored, 0f))
                    {
                        GUILayout.Label("Science Lab has no Data.", KACResources.styleLabelWarning);
                    }
                    else if (!lab.part.protoModuleCrew.Any(c => c.trait == "Scientist"))
                    {
                        GUILayout.Label("Science Lab has no Scientists.", KACResources.styleLabelWarning);
                    }
                    else if (Mathf.Approximately(lab.storedScience, converter.scienceCap))
                    {
                        GUILayout.Label("Science Lab is already full.", KACResources.styleLabelWarning);
                    }
                    else
                    {
                        intAddScienceLabHeight += 232;
                        var fltMaxScience = Math.Min(converter.scienceCap, lab.storedScience + (lab.dataStored * converter.scienceMultiplier));
                        var intMinScience = (int)Math.Floor(lab.storedScience) + 1;
                        var intMaxScience = (int)Math.Floor(fltMaxScience);

                        GUILayout.Label("Choose Target Science Amount...", KACResources.styleAddSectionHeading);
                        GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
                        GUILayout.BeginHorizontal();
                        GUILayout.Label("Target Science:", KACResources.styleAddXferName);
                        DrawTextField(ref strTargetScience, "[^\\d\\.]+", true);
                        int intTargetScience;
                        if (!int.TryParse(strTargetScience, out intTargetScience))
                        {
                            intTargetScience = intMaxScience;
                            GUILayout.Label(new GUIContent("*", "Invalid fields treated as Max"), KACResources.styleLabelError, GUILayout.Width(8));
                        }
                        GUILayout.EndHorizontal();
                        GUILayout.Label(string.Format("Min Target Science: {0}", intMinScience), GUILayout.Width(160));
                        GUILayout.BeginHorizontal();
                        GUILayout.Label(string.Format("Max Target Science: {0}", intMaxScience), GUILayout.Width(160));
                        if (GUILayout.Button("Set to Max"))
                        {
                            strTargetScience = intMaxScience.ToString();
                        }
                        GUILayout.EndHorizontal();
                        intTargetScienceClamped =
                            Math.Max((int)Math.Floor(lab.storedScience) + 1, Math.Min((int)Math.Floor(fltMaxScience), intTargetScience));
                        BuildScienceLabStrings();
                        if (intTargetScience != intTargetScienceClamped)
                        {
                            intAddScienceLabHeight += 25;
                            GUILayout.Label("Selected Target is out of reach. Target Amount changed.", KACResources.styleLabelWarning);
                        }
                        GUILayout.EndVertical();

                        var fltScienceNeeded = intTargetScienceClamped - lab.storedScience;
                        var fltDataNeeded = fltScienceNeeded / converter.scienceMultiplier;
                        var fltFinalData = lab.dataStored - fltDataNeeded;
                        var dblRateStart = converter.CalculateScienceRate(lab.dataStored);
                        var dblRateEnd = converter.CalculateScienceRate(fltFinalData);
                        var dblRateAvg = (dblRateStart + dblRateEnd) * 0.5d;
                        var dblDaysToProcess = fltScienceNeeded / dblRateAvg;
                        var totalResearchTime = KSPTimeSpan.FromDays(dblDaysToProcess);
                        // var totalResearchTime = new KSPTimeSpan(converter.CalculateResearchTime(fltDataNeeded));

                        GUILayout.Label("Target Details...", KACResources.styleAddSectionHeading);
                        GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
                        GUILayout.BeginHorizontal();
                        GUILayout.Label("Target Science Amount:", KACResources.styleAddHeading, GUILayout.Width(150));
                        GUILayout.Label(intTargetScienceClamped.ToString() + "/" + converter.scienceCap, KACResources.styleAddXferName);
                        GUILayout.EndHorizontal();

                        GUILayout.BeginHorizontal();
                        GUILayout.Label("Final Data Amount:", KACResources.styleAddHeading, GUILayout.Width(150));
                        GUILayout.Label(fltFinalData.ToString("0.00") + "/" + lab.dataStorage.ToString("0"), KACResources.styleAddXferName);
                        GUILayout.EndHorizontal();

                        GUILayout.BeginHorizontal();
                        GUILayout.Label("Final Data Rate:", KACResources.styleAddHeading, GUILayout.Width(150));
                        GUILayout.Label(dblRateEnd.ToString("0.00") + " sci/day", KACResources.styleAddXferName);
                        GUILayout.EndHorizontal();
                        GUILayout.EndVertical();

                        var scienceLabTime = new KSPDateTime(KACWorkerGameState.CurrentTime.UT + totalResearchTime.UT);
                        var scienceLabToAlarm = new KSPTimeSpan(scienceLabTime.UT - KACWorkerGameState.CurrentTime.UT);
                        if (DrawAddAlarm(scienceLabTime, null, scienceLabToAlarm))
                        {
                            KACAlarm alarmNew = new KACAlarm(
                                KACWorkerGameState.CurrentVessel.id.ToString(),
                                strAlarmName,
                                strAlarmNotes,
                                KACWorkerGameState.CurrentTime.UT + scienceLabToAlarm.UT,
                                0,
                                KACAlarm.AlarmTypeEnum.ScienceLab,
                                AddActions);

                            alarms.Add(alarmNew);

                            //settings.Save();
                            _ShowAddPane = false;
                        }
                    }
                }
            }
        }
        private void WindowLayout_AddPane_Raw()
        {
            GUILayout.Label("Enter Raw Time Values...", KACResources.styleAddSectionHeading);

            GUILayout.BeginVertical(KACResources.styleAddFieldAreas);

            GUILayout.BeginHorizontal();
            GUILayout.Label("Time type:", KACResources.styleAddHeading, GUILayout.Width(90));
            if (DrawRadioList(ref intRawType, new string[] { "Date", "Time Interval" }))
            {
                if (intRawType == 0)
                {
                    rawEntry = new KACTimeStringArray(Planetarium.GetUniversalTime() + 600, KACTimeStringArray.TimeEntryPrecisionEnum.Years);
                }
            }
            GUILayout.EndHorizontal();

            if (intRawType == 0)
            {
                //date
                KACTimeStringArray rawDate = new KACTimeStringArray(rawEntry.UT + KSPDateStructure.EpochAsKSPDateTime.UT, KACTimeStringArray.TimeEntryPrecisionEnum.Years);
                if (DrawTimeEntry(ref rawDate, KACTimeStringArray.TimeEntryPrecisionEnum.Years, "Time:", 50, 35, 15))
                {
                    rawEntry.BuildFromUT(rawDate.UT - KSPDateStructure.EpochAsKSPDateTime.UT);
                }
            }
            else
            {
                //interval
                if (DrawTimeEntry(ref rawEntry, KACTimeStringArray.TimeEntryPrecisionEnum.Years, "Time:", 50, 35, 15))
                {

                }
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label("UT (raw seconds):", KACResources.styleAddHeading,GUILayout.Width(100));
            strRawUT = GUILayout.TextField(strRawUT, KACResources.styleAddField);
            GUILayout.EndHorizontal();

            GUILayout.EndVertical();
            try
            {
                if (strRawUT != "")
                    rawTime.UT = Convert.ToDouble(strRawUT);
                else
                    rawTime.UT = rawEntry.UT;

                //If its an interval add the interval to the current time
                if (intRawType==1)
                    rawTime = new KSPDateTime(KACWorkerGameState.CurrentTime.UT + rawTime.UT);

                rawTimeToAlarm = new KSPTimeSpan(rawTime.UT - KACWorkerGameState.CurrentTime.UT);

                //Draw the Add Alarm details at the bottom
                if (DrawAddAlarm(rawTime,null,rawTimeToAlarm))
                {
                    //"VesselID, Name, Message, AlarmTime.UT, Type, Enabled,  HaltWarp, PauseGame, Maneuver"
                    String strVesselID = "";
                    if (KACWorkerGameState.CurrentVessel != null && blnAlarmAttachToVessel) strVesselID = KACWorkerGameState.CurrentVessel.id.ToString();
                    KACAlarm alarmNew = new KACAlarm(strVesselID, strAlarmName, (blnRepeatingAlarmFlag ? "Alarm Repeats\r\n" : "") + strAlarmNotes, rawTime.UT, 0, KACAlarm.AlarmTypeEnum.Raw,
                        AddActions);
                    alarmNew.RepeatAlarm = blnRepeatingAlarmFlag;
                    alarmNew.RepeatAlarmPeriod = new KSPTimeSpan(timeRepeatPeriod.UT);
                    alarms.Add(alarmNew);

                    //settings.Save();
                    _ShowAddPane = false;
                }
            }
            catch (Exception ex)
            {
                GUILayout.Label("Unable to combine all text fields to date", GUILayout.ExpandWidth(true));
                LogFormatted_DebugOnly("{0}\r\n{1}", ex.Message, ex.StackTrace);
            }
        }
        private int DrawAlarmActionButtons(KACAlarm tmpAlarm, out int NoOfDoubleLineButtons)
        {
            int intReturnNoOfButtons = 0;
            NoOfDoubleLineButtons = 0;

            ////is it the current vessel?
            //if ((!parentBehaviour.ViewAlarmsOnly) && (KACWorkerGameState.CurrentVessel!=null) && (FindVesselForAlarm(tmpAlarm).id.ToString() == KACWorkerGameState.CurrentVessel.id.ToString()))
            if ((KACWorkerGameState.CurrentGUIScene== GameScenes.FLIGHT) && (KACWorkerGameState.CurrentVessel != null) && (FindVesselForAlarm(tmpAlarm).id.ToString() == KACWorkerGameState.CurrentVessel.id.ToString()))
            {
                //There is a node and the alarm + Margin is not expired
                if ((tmpAlarm.ManNodes != null))
                //if ((tmpAlarm.ManNodes != null) && ((tmpAlarm.Remaining.UT + tmpAlarm.AlarmMarginSecs) > 0))
                {
                    //Check if theres a manuever node and if so put a label saying that it already exists
                    //only display this node button if its the active ship
                    //Add this sae functionality to the alarm triggered window
                    //Add a jump to ship button if not the active ship
                    //As well as to the
                    String strRestoretext = "Restore Maneuver Node(s)";
                    if (KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes.Count > 0)
                    {
                        strRestoretext = "Replace Maneuver Node(s)";
                        //if the count and UT's are the same then go from there
                        if (!KACAlarm.CompareManNodeListSimple(KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes, tmpAlarm.ManNodes))
                            strRestoretext += "\r\nNOTE: There is already a Node on the flight path";
                        else
                            strRestoretext += "\r\nNOTE: These Node's appear to be already set on the flight path";
                        NoOfDoubleLineButtons++;
                    }
                    if ((tmpAlarm.Remaining.UT + tmpAlarm.AlarmMarginSecs) < 0)
                    {
                        strRestoretext += "\r\nWARNING: The stored Nodes are in the past";
                        NoOfDoubleLineButtons++;
                    }
                    intReturnNoOfButtons++;
                    if (GUILayout.Button(strRestoretext, KACResources.styleButton))
                    {
                        DebugLogFormatted("Attempting to add Node");
                        KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes.Clear();
                        RestoreManeuverNodeList(tmpAlarm.ManNodes);
                    }
                }
                //There is a stored Target, that hasnt passed
                //if ((tmpAlarm.TargetObject != null) && ((tmpAlarm.Remaining.UT + tmpAlarm.AlarmMarginSecs) > 0))
                if ((tmpAlarm.TargetObject != null))
                    {
                    String strRestoretext = "Restore Target";
                    if (KACWorkerGameState.CurrentVesselTarget != null)
                    {
                        strRestoretext = "Replace Target";
                        if (KACWorkerGameState.CurrentVesselTarget != tmpAlarm.TargetObject)
                            strRestoretext += "\r\nNOTE: There is already a target and this will change";
                        else
                            strRestoretext += "\r\nNOTE: This already appears to be the target";
                        NoOfDoubleLineButtons++;
                    }
                    intReturnNoOfButtons++;
                    if (GUILayout.Button(strRestoretext, KACResources.styleButton))
                    {
                        if (tmpAlarm.TargetObject is Vessel)
                            FlightGlobals.fetch.SetVesselTarget(tmpAlarm.TargetObject as Vessel);
                        else if (tmpAlarm.TargetObject is CelestialBody)
                            FlightGlobals.fetch.SetVesselTarget(tmpAlarm.TargetObject as CelestialBody);
                    }
                }
            }
            else
            {
                //not current vessel
                //There is a node and the alarm + Margin is not expired
                //if (tmpAlarm.ManNodes != null && tmpAlarm.Remaining.UT + tmpAlarm.AlarmMarginSecs > 0)
                if (tmpAlarm.ManNodes != null)
                    {
                    String strRestoretext = "Jump To Ship and Restore Maneuver Node";
                    if (tmpAlarm.TypeOfAlarm == KACAlarm.AlarmType.Crew) strRestoretext = strRestoretext.Replace("Ship", "Kerbal");
                    if ((tmpAlarm.Remaining.UT + tmpAlarm.AlarmMarginSecs) < 0)
                    {
                        strRestoretext += "\r\nWARNING: The stored Nodes are in the past";
                        NoOfDoubleLineButtons++;
                    }
                    intReturnNoOfButtons++;

                    if (GUILayout.Button(strRestoretext, KACResources.styleButton))
                    {
                        Vessel tmpVessel = FindVesselForAlarm(tmpAlarm);

                        if (JumpToVessel(tmpVessel))
                        {
                            //Set the Node in memory to restore once the ship change has completed
                            Settings.LoadManNode = KACAlarm.ManNodeSerializeList(tmpAlarm.ManNodes);
                            Settings.SaveLoadObjects();
                        }
                    }
                }

                //There is a target and the alarm has not expired
                //if (tmpAlarm.TargetObject != null && tmpAlarm.Remaining.UT + tmpAlarm.AlarmMarginSecs > 0)
                if (tmpAlarm.TargetObject != null )
                {
                    intReturnNoOfButtons++;
                    String strButtonT = "Jump To Ship and Restore Target";
                    if (tmpAlarm.TypeOfAlarm == KACAlarm.AlarmType.Crew) strButtonT = strButtonT.Replace("Ship", "Kerbal");
                    if (GUILayout.Button(strButtonT, KACResources.styleButton))
                    {
                        Vessel tmpVessel = FindVesselForAlarm(tmpAlarm);

                        if (JumpToVessel(tmpVessel))
                        {
                            //Set the Target in persistant file to restore once the ship change has completed...
                            Settings.LoadVesselTarget = KACAlarm.TargetSerialize(tmpAlarm.TargetObject);
                            Settings.SaveLoadObjects();
                        }
                    }
                }

                intReturnNoOfButtons++;
                //Or just jump to ship - regardless of alarm time
                String strButton = "Jump To Ship";
                if (tmpAlarm.TypeOfAlarm == KACAlarm.AlarmType.Crew) strButton = strButton.Replace("Ship", "Kerbal");
                if (GUILayout.Button(strButton, KACResources.styleButton))
                {

                    Vessel tmpVessel = FindVesselForAlarm(tmpAlarm);
                    // tmpVessel.MakeActive();

                    JumpToVessel(tmpVessel);
                }
            }
            return intReturnNoOfButtons;
        }
 private void WindowLayout_CommonFields(ref String strName, ref String strMessage, ref int Action, ref Double Margin, KACAlarm.AlarmType TypeOfAlarm, int WindowHeight)
 {
     KACTimeStringArray tmpTime = new KACTimeStringArray(Margin,KACTimeStringArray.TimeEntryPrecisionEnum.Hours);
     WindowLayout_CommonFields(ref strName, ref strMessage, ref Action, ref tmpTime, TypeOfAlarm, WindowHeight);
     Margin = tmpTime.UT;
 }
        private void WindowLayout_AddPane_TargetDistance()
        {
            intAddDistanceHeight = 272;
            GUILayout.BeginVertical();
            GUILayout.Label(strAlarmEventName + " Details...", KACResources.styleAddSectionHeading);

            //What are the possible targets??
            List<ITargetable> iTargets = new List<ITargetable>();
            if (!(KACWorkerGameState.CurrentVesselTarget == null))
            {
                iTargets.Add(KACWorkerGameState.CurrentVesselTarget);   //VesselTarget
            }
            iTargets.Add(KACWorkerGameState.CurrentVessel.mainBody);    //Body we are orbiting
            if (KACWorkerGameState.SOIPointExists)
            {
                iTargets.Add(KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody);   //Body we will orbit next
            }

            if (intSelectediTarget > iTargets.Count - 1)
                intSelectediTarget = 0;

            intAddDistanceHeight += (iTargets.Count*30);

            //Now give the user the choice
            GUILayout.BeginHorizontal();
            GUILayout.Label("Select Target:",KACResources.styleAddXferName);
            if (DrawRadioListVertical(ref intSelectediTarget, iTargets.Select(x => x.GetName()).ToArray()))
            {
                DebugLogFormatted("Distance Target is:{0}", iTargets[intSelectediTarget].GetName());
            }
            GUILayout.EndHorizontal();

            //Set the tgt Object
            tgtSelectedDistance=iTargets[intSelectediTarget];
            string strDistanceName = "Distance";
            if (tgtSelectedDistance is CelestialBody) strDistanceName = "Altitude";

            //Ask for the target distance/altitude
            GUILayout.BeginHorizontal();
            GUILayout.Label(string.Format("Target {0} (m):",strDistanceName), KACResources.styleAddXferName);
            dblTargetDistance= Convert.ToInt32(GUILayout.TextField(dblTargetDistance.ToString(),KACResources.styleAddField));
            GUILayout.EndHorizontal();

            //If the body has an atmosphere then add an option to set the Altitude straight to that
            if (tgtSelectedDistance is CelestialBody)
            {
                if ((tgtSelectedDistance as CelestialBody).atmosphere)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(string.Format("Atmosphere: {0}", (tgtSelectedDistance as CelestialBody).maxAtmosphereAltitude));
                    if (GUILayout.Button("Set to Edge"))
                    {
                        dblTargetDistance = (tgtSelectedDistance as CelestialBody).maxAtmosphereAltitude;
                    }
                    GUILayout.EndHorizontal();
                    intAddDistanceHeight += 26;
                }
            }

            //For a vessel give some options for orbits to look forwards
            GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
            if (!(tgtSelectedDistance is CelestialBody))
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Orbits to Search:", KACResources.styleAddHeading, GUILayout.Width(110));
                GUILayout.Label(((int)Math.Round((Decimal)fltOrbits_Distance, 0)).ToString(), KACResources.styleAddXferName, GUILayout.Width(25));
                fltOrbits_Distance = GUILayout.HorizontalSlider(fltOrbits_Distance, 1, 20);
                fltOrbits_Distance = (float)Math.Floor((Decimal)fltOrbits_Distance);
                GUILayout.EndHorizontal();
                intAddDistanceHeight += 18;
            }

            //What VesselOrbit do we care about
            Orbit VesselOrbitToCompare=KACWorkerGameState.CurrentVessel.GetOrbit();
            if ((KACWorkerGameState.SOIPointExists) && ((tgtSelectedDistance as CelestialBody) == KACWorkerGameState.CurrentVessel.orbit.nextPatch.referenceBody))
            {
                VesselOrbitToCompare = KACWorkerGameState.CurrentVessel.orbit.nextPatch;
            }
            //Get the startUT of the orbit
            Double VesselOrbitStartUT = KACWorkerGameState.CurrentVessel.GetOrbit().StartUT;

            //Set up some variables
            intOrbits_Distance = (int)fltOrbits_Distance;
            int intDistanceOrbitPass = 0;
            double dblClosestDistance = Double.MaxValue;
            double dblDistanceUT = 0;

            double dblOrbitTestDistance = Double.MaxValue;
            double dblOrbitTestDistanceUT = 0;

            //If its an Altitude alarm then do this
            if (tgtSelectedDistance is CelestialBody)
            {
                dblOrbitTestDistanceUT = KACUtils.timeOfTargetAltitude(VesselOrbitToCompare,
                                            VesselOrbitStartUT,
                                            out dblOrbitTestDistance,
                                            dblTargetDistance
                                            );

                dblClosestDistance = dblOrbitTestDistance;
                dblDistanceUT = dblOrbitTestDistanceUT;
            }
            else
            {
                //Else Iterate through the orbits to find the target separation
                for (int intOrbitToTest = 1; intOrbitToTest <= intOrbits_Distance; intOrbitToTest++)
                {
                    dblOrbitTestDistanceUT = KACUtils.timeOfTargetDistance(VesselOrbitToCompare,
                                                                tgtSelectedDistance.GetOrbit(),
                                                                KACWorkerGameState.CurrentTime.UT,
                                                                intOrbitToTest,
                                                                out dblOrbitTestDistance,
                                                                dblTargetDistance
                                                                );

                    if (dblOrbitTestDistance < dblClosestDistance)
                    {
                        dblClosestDistance = dblOrbitTestDistance;
                        dblDistanceUT = dblOrbitTestDistanceUT;
                        intDistanceOrbitPass = intOrbitToTest;
                    }
                }
            }

            //Now display what we got
            GUILayout.BeginHorizontal();
            GUILayout.Label(String.Format("{0}:",strDistanceName), KACResources.styleAddHeading, GUILayout.Width(70));
            String strDistance = string.Format("{0:#}m", dblClosestDistance);
            if (dblClosestDistance > 999) strDistance = string.Format("{0:#.0}km", dblClosestDistance / 1000);
            GUILayout.Label(strDistance, KACResources.styleAddXferName, GUILayout.Width(90));
            if (!(tgtSelectedDistance is CelestialBody))
            {
                GUILayout.Label("On Orbit:", KACResources.styleAddHeading);
                GUILayout.Label(intDistanceOrbitPass.ToString(), KACResources.styleAddXferName);
            }
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();

            //Now do the stuff to draw the alarm button
            String strMarginConversion = "";
            KACTime eventTime = new KACTime(dblDistanceUT);
            KACTime eventInterval = new KACTime(dblDistanceUT - KACWorkerGameState.CurrentTime.UT);

            KACTime eventAlarm;
            KACTime eventAlarmInterval;
            try
            {
                eventAlarm = new KACTime(eventTime.UT - timeMargin.UT);
                eventAlarmInterval = new KACTime(eventTime.UT - KACWorkerGameState.CurrentTime.UT - timeMargin.UT);
            }
            catch (Exception)
            {
                eventAlarm = null;
                eventAlarmInterval = null;
                strMarginConversion = "Unable to Add the Margin Minutes";
            }

            if ((eventTime.UT > KACWorkerGameState.CurrentTime.UT) && strMarginConversion == "")
            {
                if (DrawAddAlarm(eventTime, eventInterval, eventAlarmInterval))
                {
                    KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), strAlarmName, strAlarmNotes,
                        eventAlarm.UT, timeMargin.UT, AddType,
                        (AddAction == KACAlarm.AlarmAction.KillWarp), (AddAction == KACAlarm.AlarmAction.PauseGame));
                    newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;
                    newAlarm.ManNodes = KACWorkerGameState.CurrentVessel.patchedConicSolver.maneuverNodes;

                    Settings.Alarms.Add(newAlarm);
                    Settings.Save();
                    _ShowAddPane = false;
                }
            }
            else
            {
                strMarginConversion = "No Target Distance Approach found";
            }

            if (strMarginConversion != "")
                GUILayout.Label(strMarginConversion, GUILayout.ExpandWidth(true));

            GUILayout.EndVertical();
        }
        /// <summary>
        /// Layout of Common Parts of every alarm
        /// </summary>
        private void WindowLayout_CommonFields(ref String strName, ref String strMessage, ref int Action, ref KACTimeStringArray Margin, KACAlarm.AlarmType TypeOfAlarm, int WindowHeight)
        {
            //Two Columns
            GUILayout.Label("Common Alarm Properties", KACResources.styleAddSectionHeading);
            GUILayout.BeginVertical(KACResources.styleAddFieldAreas, GUILayout.Height(WindowHeight));

            GUILayout.BeginHorizontal();

            GUILayout.BeginVertical(GUILayout.Width(90));
            GUILayout.Label("Alarm Name:", KACResources.styleAddHeading);
            GUILayout.Label("Message:", KACResources.styleAddHeading);
            GUILayout.EndVertical();

            GUILayout.BeginVertical(GUILayout.Width(260), GUILayout.MaxWidth(260));
            strName = GUILayout.TextField(strName, KACResources.styleAddField).Replace("|", "");
            strMessage = GUILayout.TextArea(strMessage, KACResources.styleAddField).Replace("|", "");
            GUILayout.EndVertical();

            GUILayout.EndHorizontal();

            //Full width one under the two columns for the kill time warp
            DrawAlarmActionChoice(ref Action, "On Alarm:", 90);

            if (TypeOfAlarm != KACAlarm.AlarmType.Raw && TypeOfAlarm != KACAlarm.AlarmType.EarthTime && TypeOfAlarm != KACAlarm.AlarmType.Crew)
            {
                DrawTimeEntry(ref Margin, KACTimeStringArray.TimeEntryPrecisionEnum.Hours, "Alarm Margin:", 90);
            }

            GUILayout.EndVertical();
        }
        internal static KACAlarm LoadFromString3(String AlarmDetails, Double CurrentUT)
        {
            //String is "VesselID|Name|Notes|AlarmTime.UT|AlarmMarginSecs|Type|Enabled|HaltWarp|PauseGame|ActionedAt|Maneuver|Xfer|Target|Options|<ENDLINE>");

            String[] vars = AlarmDetails.Split("|".ToCharArray(), StringSplitOptions.None);

            MonoBehaviourExtended.LogFormatted("AlarmExtract");
            for (int i = 0; i < vars.Length; i++) {
                MonoBehaviourExtended.LogFormatted("{0}:{1}",i,vars[i]);
            }

            String SaveName = HighLogic.CurrentGame.Title;
            String VesselID = vars[0];
            String Name = KACUtils.DecodeVarStrings(vars[1]);
            String Notes = KACUtils.DecodeVarStrings(vars[2]);
            Double UT = Convert.ToDouble(vars[3]);
            Double AlarmMarginSecs = Convert.ToDouble(vars[4]);
            KACAlarm.AlarmTypeEnum TypeOfAlarm = (KACAlarm.AlarmTypeEnum)Enum.Parse(typeof(KACAlarm.AlarmTypeEnum), vars[5]);
            Boolean Enabled = Convert.ToBoolean(vars[6]);
            Boolean HaltWarp = Convert.ToBoolean(vars[7]);
            Boolean PauseGame = Convert.ToBoolean(vars[8]);
            Double ActionedAt = Convert.ToDouble(vars[9]);

            List<ManeuverNode> ManNodes=null;
            String XferOriginBodyName="", XferTargetBodyName="";
            ITargetable TargetObject=null;
            String TargetLoader="";

            Boolean Triggered=false, Actioned=false, AlarmWindowClosed=false;

            if (vars[10] != "")
                ManNodes = ManNodeDeserializeList(vars[10]);

            if (vars[11] != "")
            {
                try
                {
                    MonoBehaviourExtended.LogFormatted("{0}", vars[11]);
                    String[] XferParts = vars[11].Split(",".ToCharArray());
                    XferOriginBodyName = XferParts[0];
                    XferTargetBodyName = XferParts[1];
                }
                catch (Exception ex)
                {
                    MonoBehaviourExtended.LogFormatted("Unable to load transfer details for {0}", Name);
                    MonoBehaviourExtended.LogFormatted(ex.Message);
                }
            }
            if (vars[12] != "")
            {
                //find the targetable object and set it
                TargetObject = TargetDeserialize(vars[12]);
                if (TargetObject == null && vars[12].StartsWith("Vessel,"))
                    TargetLoader = vars[12];
            }

            //Now do the work to set Actioned/triggered/etc if needed
            //LogFormatted("A:{0},T:{1:0},Act:{2:0}", this.Name, CurrentUT, this.ActionedAt);
            if (ActionedAt > 0 && CurrentUT > ActionedAt)
            {
                MonoBehaviourExtended.LogFormatted("Suppressing Alarm on Load:{0}", Name);
                Triggered = true;
                Actioned = true;
                AlarmWindowClosed = true;
            }
            else if (ActionedAt > CurrentUT)
            {
                MonoBehaviourExtended.LogFormatted("Reenabling Alarm on Load:{0}", Name);
                Triggered = false;
                Actioned = false;
                ActionedAt = 0;
                AlarmWindowClosed = false;
            }

            KACAlarm resultAlarm = new KACAlarm(UT);
            resultAlarm.Name = Name;
            resultAlarm.VesselID = VesselID;
            resultAlarm.Enabled = Enabled;
            resultAlarm.Notes = Notes;
            resultAlarm.AlarmMarginSecs = AlarmMarginSecs;
            resultAlarm.TypeOfAlarm = TypeOfAlarm;
            if (HaltWarp)
                resultAlarm.AlarmActionConvert = KACAlarm.AlarmActionEnum.KillWarp;
            else if (PauseGame)
                resultAlarm.AlarmActionConvert = KACAlarm.AlarmActionEnum.PauseGame;

            if (ManNodes != null)
                resultAlarm.ManNodes = ManNodes;
            if (TargetObject != null)
                resultAlarm.TargetObject = TargetObject;
            resultAlarm.TargetLoader = TargetLoader;

            resultAlarm.XferOriginBodyName = XferOriginBodyName;
            resultAlarm.XferTargetBodyName = XferTargetBodyName;

            resultAlarm.Triggered = Triggered;
            resultAlarm.Actioned = Actioned;
            resultAlarm.AlarmWindowClosed = AlarmWindowClosed;

            return resultAlarm;
        }
        /// <summary>
        /// Layout of Common Parts of every alarm
        /// </summary>
        private void WindowLayout_CommonFields2(ref String strName, ref Boolean blnAttachVessel, ref KACAlarm.AlarmAction Action, ref KACTimeStringArray Margin, KACAlarm.AlarmType TypeOfAlarm, int WindowHeight)
        {
            //Two Columns
            String strTitle = "";
            switch (TypeOfAlarm)
            {
                case KACAlarm.AlarmType.Raw: strTitle = "Raw Time"; break;
                case KACAlarm.AlarmType.Maneuver: strTitle = "Maneuver Node"; break;
                case KACAlarm.AlarmType.SOIChange: strTitle = "SOI Change"; break;
                case KACAlarm.AlarmType.Transfer: strTitle = "Transfer Window"; break;
                case KACAlarm.AlarmType.TransferModelled: strTitle = "Transfer Window"; break;
                case KACAlarm.AlarmType.Apoapsis: strTitle = "Apoapsis"; break;
                case KACAlarm.AlarmType.Periapsis: strTitle = "Periapsis"; break;
                case KACAlarm.AlarmType.AscendingNode: strTitle = "Ascending Node"; break;
                case KACAlarm.AlarmType.DescendingNode: strTitle = "Descending Node"; break;
                case KACAlarm.AlarmType.LaunchRendevous: strTitle = "Launch Ascent"; break;
                case KACAlarm.AlarmType.Closest: strTitle = "Closest Approach"; break;
                case KACAlarm.AlarmType.Distance: strTitle = "Target Distance"; break;
                case KACAlarm.AlarmType.Crew: strTitle = "Crew"; break;
                case KACAlarm.AlarmType.EarthTime: strTitle = "Earth Time"; break;
                default: strTitle = "Raw Time"; break;
            }
            strTitle += " Alarm - Common Properties";
            GUILayout.Label(strTitle, KACResources.styleAddSectionHeading);
            GUILayout.BeginVertical(KACResources.styleAddFieldAreas, GUILayout.Height(WindowHeight));

            if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Selected Vessel:", KACResources.styleAddHeading);
                String strVesselName = "No Selected Vessel";
                if (KACWorkerGameState.CurrentVessel != null) strVesselName = KACWorkerGameState.CurrentVessel.vesselName;
                GUILayout.Label(strVesselName, KACResources.styleLabelWarning);
                GUILayout.EndHorizontal();
            }

            GUILayout.BeginHorizontal();
            GUILayout.Label("Alarm:", KACResources.styleAddHeading, GUILayout.Width(60));
            strName = GUILayout.TextField(strName, KACResources.styleAddField, GUILayout.MaxWidth(200)).Replace("|", "");

            GUIContent guiBtnMessages = new GUIContent(KACResources.btnChevRight, "Show Extra Details");
            if (_ShowAddMessages) guiBtnMessages = new GUIContent(KACResources.btnChevLeft, "Hide Details");
            if (GUILayout.Button(guiBtnMessages, KACResources.styleSmallButton))
                _ShowAddMessages = !_ShowAddMessages;
            GUILayout.EndHorizontal();

            if (ScenesForAttachOption.Contains(KACWorkerGameState.CurrentGUIScene) && TypesForAttachOption.Contains(TypeOfAlarm)
                && KACWorkerGameState.CurrentVessel!=null)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Space(15);
                DrawCheckbox(ref blnAttachVessel, "Attach to Active Vessel");
                GUILayout.EndHorizontal();
            }

            //Full width one under the two columns for the kill time warp
            DrawAlarmActionChoice2(ref Action, "Action:", 60);

            if (TypeOfAlarm != KACAlarm.AlarmType.Raw && TypeOfAlarm != KACAlarm.AlarmType.EarthTime && TypeOfAlarm != KACAlarm.AlarmType.Crew)
            {
                DrawTimeEntry(ref Margin, KACTimeStringArray.TimeEntryPrecisionEnum.Hours, "Margin:", 60);
            }
            GUILayout.EndVertical();
        }
        private void WindowLayout_AddPane_Crew()
        {
            intAddCrewHeight = 322;
            GUILayout.Label("Select Crew...", KACResources.styleAddSectionHeading);

            GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
            //get the kerbals in the current vessel
            List<ProtoCrewMember> pCM = KACWorkerGameState.CurrentVessel.GetVesselCrew();
            intAddCrewHeight += (pCM.Count * 30);
            if(pCM.Count==0)
            {
                //Draw something about no crew present
                GUILayout.Label("No Kerbals present in this vessel", KACResources.styleContent, GUILayout.ExpandWidth(true));
            } else {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Kerbal Name", KACResources.styleAddSectionHeading, GUILayout.Width(267));
                GUILayout.Label("Add", KACResources.styleAddSectionHeading);//, GUILayout.Width(30));
                GUILayout.EndHorizontal();

                for (int intTarget = 0; intTarget < pCM.Count; intTarget++)
                {
                    //DebugLogFormatted("{2}", pCM[intTarget].name);
                    GUILayout.BeginHorizontal();
            //        //draw a line and a radio button for selecting Crew
                    GUILayout.Space(20);
                    GUILayout.Label(pCM[intTarget].name, KACResources.styleAddXferName, GUILayout.Width(240), GUILayout.Height(20));

            //        //when they are selected adjust message to have a name of the crew member, and message of vessel when alarm was set
                    Boolean blnSelected = (intSelectedCrew == intTarget);
                    if (DrawToggle(ref blnSelected, "", KACResources.styleCheckbox, GUILayout.Width(40)))
                    {
                        if (blnSelected)
                        {
                            intSelectedCrew = intTarget;
                            BuildCrewStrings();
                        }
                    }
                    GUILayout.EndHorizontal();
                }

                DrawCheckbox(ref CrewAlarmStoreNode, "Store Man Node/Target with Crew Alarm");

            }
            GUILayout.EndVertical();

            if (pCM.Count > 0)
            {
                //Now the time entry area
                GUILayout.Label("Enter Time Values...", KACResources.styleAddSectionHeading);

                GUILayout.BeginVertical(KACResources.styleAddFieldAreas);
                GUILayout.BeginHorizontal();
                GUILayout.Label("Time type:", KACResources.styleAddHeading, GUILayout.Width(90));
                if (DrawRadioList(ref intCrewType, new string[] { "Date", "Time Interval" })) {
                    if (intRawType == 0)
                    {
                        rawEntry = new KACTimeStringArray(Planetarium.GetUniversalTime() + 600, KACTimeStringArray.TimeEntryPrecisionEnum.Years);
                    }
                }
                GUILayout.EndHorizontal();

                if (intCrewType == 0)
                {
                    //date
                    KACTimeStringArray CrewDate = new KACTimeStringArray(CrewEntry.UT + KACTime.timeDateOffest.UT, KACTimeStringArray.TimeEntryPrecisionEnum.Years);
                    if (DrawTimeEntry(ref CrewDate, KACTimeStringArray.TimeEntryPrecisionEnum.Years, "Time:", 50, 35, 15))
                    {
                        rawEntry.BuildFromUT(CrewDate.UT - KACTime.timeDateOffest.UT);
                    }
                }
                else
                {
                    //interval
                    if (DrawTimeEntry(ref CrewEntry, KACTimeStringArray.TimeEntryPrecisionEnum.Years, "Time:", 50, 35, 15))
                    {

                    }
                }
                GUILayout.BeginHorizontal();
                GUILayout.Label("UT (raw seconds):", KACResources.styleAddHeading, GUILayout.Width(100));
                strCrewUT = GUILayout.TextField(strCrewUT, KACResources.styleAddField);
                GUILayout.EndHorizontal();
                GUILayout.EndVertical();

                try
                {
                    if (strCrewUT != "")
                        CrewTime.UT = Convert.ToDouble(strCrewUT);
                    else
                        CrewTime.UT = CrewEntry.UT;

                    //If its an interval add the interval to the current time
                    if (intCrewType == 1)
                        CrewTime = new KACTime(KACWorkerGameState.CurrentTime.UT + CrewTime.UT);

                    CrewTimeToAlarm = new KACTime(CrewTime.UT - KACWorkerGameState.CurrentTime.UT);

                    //Draw the Add Alarm details at the bottom
                    if (DrawAddAlarm(CrewTime, null, CrewTimeToAlarm))
                    {
                        //"VesselID, Name, Message, AlarmTime.UT, Type, Enabled,  HaltWarp, PauseGame, Manuever"
                        KACAlarm addAlarm = new KACAlarm(pCM[intSelectedCrew].name, strAlarmName, strAlarmNotes, CrewTime.UT, 0, KACAlarm.AlarmType.Crew,
                            (AddAction == KACAlarm.AlarmAction.KillWarp), (AddAction == KACAlarm.AlarmAction.PauseGame));
                        if (CrewAlarmStoreNode)
                        {
                            if (KACWorkerGameState.ManeuverNodeExists) addAlarm.ManNodes = KACWorkerGameState.ManeuverNodesFuture;
                            if (KACWorkerGameState.CurrentVesselTarget != null) addAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;
                        }
                        Settings.Alarms.Add(addAlarm);
                        Settings.Save();
                        _ShowAddPane = false;
                    }
                }
                catch (Exception)
                {
                //    DebugLogFormatted(ex.Message);
                    GUILayout.Label("Unable to combine all text fields to date", GUILayout.ExpandWidth(true));
                }
            }
        }
        private KACAlarm QuickAddPe()
        {
            KACAlarm tmpAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(),
                KACWorkerGameState.CurrentVessel.vesselName + " Periapsis",
                "Quick Added Periapsis Alarm",
                KACWorkerGameState.CurrentTime.UT + KACWorkerGameState.CurrentVessel.orbit.timeToPe - settings.AlarmAddNodeQuickMargin,
                settings.AlarmAddNodeQuickMargin,
                KACAlarm.AlarmTypeEnum.Periapsis,
                settings.AlarmAddNodeQuickAction);
            alarms.Add(tmpAlarm);

            return tmpAlarm;
        }
        //Draw a single button near the correct node
        private Boolean DrawNodeWarpButton(Boolean Exists, Double UT,KACAlarm.AlarmTypeEnum aType, String NodeName, Boolean WithMargin, Double MarginSecs)
        {
            if (Exists)
            {
                //set the style basics
                GUIStyle styleWarpToButton = new GUIStyle();
                styleWarpToButton.fixedWidth = 20;
                styleWarpToButton.fixedHeight = 12;

                //set the default offset of the buttons top left from the node point
                // - these move around depending on the size of the node icon
                Int32 xOffset = 10;
                Int32 yOffset = -20;

                //set the specific normal and hover textures and any custom offsets
                switch (aType)
                {
                    case KACAlarm.AlarmTypeEnum.Maneuver:
                    case KACAlarm.AlarmTypeEnum.ManeuverAuto:
                        if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION)
                        {
                            styleWarpToButton.normal.background = KACResources.iconWarpToTSManNode;
                            if (!settings.WarpToRequiresConfirm || WarpToArmed)
                                styleWarpToButton.hover.background = KACResources.iconWarpToTSManNodeOver;
                        }
                        else
                        {
                            styleWarpToButton.normal.background = KACResources.iconWarpToManNode;
                            if (!settings.WarpToRequiresConfirm || WarpToArmed)
                                styleWarpToButton.hover.background = KACResources.iconWarpToManNodeOver;
                        }
                        break;
                    case KACAlarm.AlarmTypeEnum.Apoapsis:
                    case KACAlarm.AlarmTypeEnum.Periapsis:
                        if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION) {
                            styleWarpToButton.normal.background = KACResources.iconWarpToTSApPe;
                            if (!settings.WarpToRequiresConfirm || WarpToArmed)
                                styleWarpToButton.hover.background = KACResources.iconWarpToTSApPeOver;
                        }
                        else {
                            styleWarpToButton.normal.background = KACResources.iconWarpToApPe;
                            if (!settings.WarpToRequiresConfirm || WarpToArmed)
                                styleWarpToButton.hover.background = KACResources.iconWarpToApPeOver;
                        }
                        break;
                    case KACAlarm.AlarmTypeEnum.AscendingNode:
                        styleWarpToButton.normal.background = KACResources.iconWarpToANDN;
                        if (!settings.WarpToRequiresConfirm || WarpToArmed)
                            styleWarpToButton.hover.background = KACResources.iconWarpToANDNOver;
                        xOffset = 18;
                        yOffset = -14;
                        break;
                    case KACAlarm.AlarmTypeEnum.DescendingNode:
                        styleWarpToButton.normal.background = KACResources.iconWarpToANDN;
                        if (!settings.WarpToRequiresConfirm || WarpToArmed)
                            styleWarpToButton.hover.background = KACResources.iconWarpToANDNOver;
                        xOffset = -1;
                        yOffset = -16;
                        break;
                    case KACAlarm.AlarmTypeEnum.SOIChange:
                    case KACAlarm.AlarmTypeEnum.SOIChangeAuto:
                        xOffset = 6;
                        yOffset = -16;
                        if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION) {
                            styleWarpToButton.normal.background = KACResources.iconWarpToTSApPe;
                            if (!settings.WarpToRequiresConfirm || WarpToArmed)
                                styleWarpToButton.hover.background = KACResources.iconWarpToTSApPeOver;
                        }
                        else {
                            styleWarpToButton.normal.background = KACResources.iconWarpToApPe;
                            if (!settings.WarpToRequiresConfirm || WarpToArmed)
                                styleWarpToButton.hover.background = KACResources.iconWarpToApPeOver;
                        }
                        break;
                    default:
                        styleWarpToButton.normal.background = KACResources.iconWarpToApPe;
                        if (!settings.WarpToRequiresConfirm || WarpToArmed)
                            styleWarpToButton.hover.background = KACResources.iconWarpToApPeOver;
                        break;
                }

                //get the screen coordinates of the Point
                Vector3d screenPosNode = PlanetariumCamera.Camera.WorldToScreenPoint(ScaledSpace.LocalToScaledSpace(KACWorkerGameState.CurrentVessel.orbit.getPositionAtUT(UT)));
                Rect rectNodeButton = new Rect((Int32)screenPosNode.x + xOffset, (Int32)(Screen.height - screenPosNode.y) + yOffset, 20, 12);
                if (GUI.Button(rectNodeButton, "", styleWarpToButton))
                {
                    if (Event.current.button == 0)
                    {
                        if (settings.WarpToRequiresConfirm && !WarpToArmed)
                        {
                            LogFormatted_DebugOnly("Set confirmed and store Rect");
                            WarpToArmed = true;
                            WarpToArmedButtonRect = new Rect(rectNodeButton);
                            //If in the TS then reset the orbit selection
                            if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION)
                            {
                                lstOrbitRenderChanged.Add(KACWorkerGameState.CurrentVessel.id);
                                KACWorkerGameState.CurrentVessel.orbitRenderer.isFocused = true;
                                KACWorkerGameState.CurrentVessel.AttachPatchedConicsSolver();
                            }
                        }
                        else
                        {
                            WarpToArmed = false;

                            //Get any existing alarm for the same vessel/type and time -
                            //  Event Time NOT the alarm time
                            KACAlarm aExisting = alarms.FirstOrDefault(a => a.VesselID == KACWorkerGameState.CurrentVessel.id.ToString()
                                && Math.Abs((a.AlarmTimeUT + a.AlarmMarginSecs) - UT) <= settings.WarpToDupeProximitySecs
                                && (a.TypeOfAlarm == aType
                                    || a.TypeOfAlarm == KACAlarm.AlarmTypeEnum.SOIChangeAuto && aType==KACAlarm.AlarmTypeEnum.SOIChange
                                    || a.TypeOfAlarm == KACAlarm.AlarmTypeEnum.ManeuverAuto && aType==KACAlarm.AlarmTypeEnum.Maneuver
                                    )
                                );

                            //LogFormatted("UT:{0},Margin:{1},WUT:{2},Prox:{3}", alarms.First().AlarmTimeUT, alarms.First().AlarmMarginSecs, UT, settings.WarpToDupeProximitySecs);
                            //LogFormatted("DIFF:{0}", Math.Abs((alarms.First().AlarmTimeUT + alarms.First().AlarmMarginSecs) - UT) <= settings.WarpToDupeProximitySecs);

                            //if there aint one then add one
                            if (aExisting == null)
                            {
                                KACAlarm newAlarm = new KACAlarm(KACWorkerGameState.CurrentVessel.id.ToString(), "Warp to " + NodeName, "", UT - (WithMargin ? MarginSecs : 0), (WithMargin ? MarginSecs : 0), aType,
                                        AlarmActions.DefaultsKillWarpOnly());
                                if (lstAlarmsWithTarget.Contains(aType))
                                    newAlarm.TargetObject = KACWorkerGameState.CurrentVesselTarget;
                                if (KACWorkerGameState.ManeuverNodeExists)
                                    newAlarm.ManNodes = KACWorkerGameState.ManeuverNodesFuture;
                                newAlarm.Actions.DeleteWhenDone = true;

                                alarms.Add(newAlarm);
                            }
                            else
                            {
                                //else update the UT
                                aExisting.AlarmTimeUT = UT;
                            }

                            //now accelerate time
                            Double timeToEvent = UT - Planetarium.GetUniversalTime();
                            Int32 rateToSet = WarpTransitionCalculator.WarpRateTransitionPeriods.Where(
                                                    r => r.UTTo1Times < timeToEvent
                                                        && (!settings.WarpToLimitMaxWarp || r.Rate<=settings.WarpToMaxWarp)
                                                    )
                                                .OrderBy(r => r.UTTo1Times)
                                                .Last().Index;
                            //Make sure we cancel autowarp if its engaged
                            if (TimeWarp.fetch != null)
                            {
                                TimeWarp.fetch.CancelAutoWarp();
                                TimeWarp.SetRate(rateToSet, false);
                            }

                            //If in the TS then reset the orbit selection
                            if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION)
                            {
                                lstOrbitRenderChanged.Add(KACWorkerGameState.CurrentVessel.id);
                                KACWorkerGameState.CurrentVessel.orbitRenderer.isFocused = true;
                                KACWorkerGameState.CurrentVessel.AttachPatchedConicsSolver();
                            }
                        }
                    }
                }

                if (settings.ShowTooltips && !settings.WarpToTipsHidden)
                {
                    //work out where when the mouse is over the button
                    Vector3 VectMouseflipped  = Input.mousePosition;
                    VectMouseflipped.y = Screen.height - VectMouseflipped.y;
                    if (rectNodeButton.Contains(VectMouseflipped))
                    {
                        //and draw some info bout it
                        GUIStyle styleTip = new GUIStyle();
                        styleTip.normal.textColor = Color.white;
                        styleTip.fontSize = 12;

                        String strArm = "";
                        if (settings.WarpToRequiresConfirm) {
                            if (!WarpToArmed)
                                strArm = " (Unarmed)";
                        }
                        String strlabel = "Warp to " + NodeName + strArm + (WithMargin ? " (Margin=" + new KSPTimeSpan(MarginSecs).ToString(2) + ")" : "");
                        GUI.Label(new Rect((Int32)screenPosNode.x + xOffset + 21, (Int32)(Screen.height - screenPosNode.y) + yOffset -2, 100, 12), strlabel, styleTip);
                    }
                }
            }
            return false;
        }
        public Boolean DrawButtonList(ref KACAlarm.AlarmType selType, params GUIContent[] Choices)
        {
            int Selection = KACAlarm.AlarmTypeToButton[selType];
            if (KACWorkerGameState.CurrentGUIScene == GameScenes.TRACKSTATION) Selection = KACAlarm.AlarmTypeToButtonTS[selType];
            else if (KACWorkerGameState.CurrentGUIScene == GameScenes.SPACECENTER) Selection = KACAlarm.AlarmTypeToButtonSC[selType];

            Boolean blnReturn = DrawButtonList(ref Selection, Choices);
            if (blnReturn)
            {
                if (KACWorkerGameState.CurrentGUIScene== GameScenes.TRACKSTATION)
                    selType = KACAlarm.AlarmTypeFromButtonTS[Selection];
                else if (KACWorkerGameState.CurrentGUIScene == GameScenes.SPACECENTER)
                    selType = KACAlarm.AlarmTypeFromButtonSC[Selection];
                else
                    selType = KACAlarm.AlarmTypeFromButton[Selection];
            }
            return blnReturn;
        }
        private Boolean CreateAlarmRepeats(KACAlarm alarmToCheck, out KACAlarm alarmToAdd)
        {
            if (alarmToCheck.RepeatAlarm){
                if (alarmToCheck.TypeOfAlarm == KACAlarm.AlarmTypeEnum.TransferModelled)
                {
                    try
                    {
                        LogFormatted("Adding repeat alarm for ({0}->{1})", alarmToCheck.XferOriginBodyName, alarmToCheck.XferTargetBodyName);
                        //find the next transfer from the modelled data
                        KACXFerModelPoint tmpModelPoint = KACResources.lstXferModelPoints.FirstOrDefault(
                                   m => FlightGlobals.Bodies[m.Origin].bodyName == alarmToCheck.XferOriginBodyName &&
                                       FlightGlobals.Bodies[m.Target].bodyName == alarmToCheck.XferTargetBodyName &&
                                       m.UT > alarmToCheck.AlarmTime.UT + alarmToCheck.AlarmMarginSecs);

                        if (tmpModelPoint != null)
                        {
                            KSPDateTime XferNextTargetEventTime = new KSPDateTime(tmpModelPoint.UT);

                            if (!alarms.Any(a => a.TypeOfAlarm == KACAlarm.AlarmTypeEnum.TransferModelled &&
                                            a.XferOriginBodyName == alarmToCheck.XferOriginBodyName &&
                                            a.XferTargetBodyName == alarmToCheck.XferTargetBodyName &&
                                            a.AlarmTime.UT == tmpModelPoint.UT))
                            {
                                alarmToAdd=alarmToCheck.Duplicate(XferNextTargetEventTime.UT - alarmToCheck.AlarmMarginSecs);
                                return true;
                            }
                            else
                            {
                                LogFormatted("Alarm already exists, not adding repeat({0}->{1}): UT={2}", alarmToCheck.XferOriginBodyName, alarmToCheck.XferTargetBodyName, XferNextTargetEventTime.UT);
                            }
                        }
                        else
                        {
                            LogFormatted("Unable to find a future model data point for this transfer({0}->{1})", alarmToCheck.XferOriginBodyName, alarmToCheck.XferTargetBodyName);
                        }

                    }
                    catch (Exception ex)
                    {
                        LogFormatted("Unable to find a future model data point for this transfer({0}->{1})\r\n{2}", alarmToCheck.XferOriginBodyName, alarmToCheck.XferTargetBodyName, ex.Message);
                    }
                }
                else if (alarmToCheck.TypeOfAlarm == KACAlarm.AlarmTypeEnum.Apoapsis || alarmToCheck.TypeOfAlarm == KACAlarm.AlarmTypeEnum.Periapsis)
                {
                    try
                    {
                        Vessel v = FindVesselForAlarm(alarmToCheck);

                        if(v == null)
                        {
                            LogFormatted("Unable to find the vessel to work out the repeat ({0})", alarmToCheck.VesselID);
                        }
                        else
                        {

                            LogFormatted("Adding repeat alarm for Ap/Pe ({0})", alarmToCheck.VesselID);

                            //get the time of the next node if the margin is greater than 0
                            Double nextApPe = Planetarium.GetUniversalTime() + v.orbit.timeToAp + (alarmToCheck.AlarmMarginSecs>0?v.orbit.period:0);
                            if (alarmToCheck.TypeOfAlarm == KACAlarm.AlarmTypeEnum.Periapsis)
                                nextApPe = Planetarium.GetUniversalTime() + v.orbit.timeToPe + +(alarmToCheck.AlarmMarginSecs > 0 ? v.orbit.period : 0);

                            if (!alarms.Any(a => a.TypeOfAlarm == alarmToCheck.TypeOfAlarm &&
                                    a.AlarmTime.UT == nextApPe))
                            {
                                alarmToAdd = alarmToCheck.Duplicate(nextApPe);
                                return true;
                            }
                            else
                            {
                                LogFormatted("Alarm already exists, not adding repeat ({0}): UT={1}", alarmToCheck.VesselID, nextApPe);
                            }

                            alarmToAdd = alarmToCheck.Duplicate(nextApPe);
                            return true;
                        }

                    }
                    catch (Exception ex)
                    {
                        LogFormatted("Unable to add a repeat alarm ({0})\r\n{1}", alarmToCheck.VesselID, ex.Message);
                    }
                }
                else if (alarmToCheck.RepeatAlarmPeriod.UT > 0)
                {
                    LogFormatted("Adding repeat alarm for {0}:{1}-{2}+{3}", alarmToCheck.TypeOfAlarm, alarmToCheck.Name, alarmToCheck.AlarmTime.UT, alarmToCheck.RepeatAlarmPeriod.UT);
                    alarmToAdd = alarmToCheck.Duplicate(alarmToCheck.AlarmTime.UT + alarmToCheck.RepeatAlarmPeriod.UT);
                    return true;
                }
            }
            alarmToAdd = null;
            return false;
        }
 //VesselOrCrewStuff
 private static Boolean CheckVesselOrCrewForJump(String ID, KACAlarm.AlarmType aType)
 {
     if (aType == KACAlarm.AlarmType.Crew && StoredCrewExists(ID))
     {
         return true;
     }
     else if (StoredVesselExists(ID))
     {
         if (KerbalAlarmClock.Settings.AllowJumpToAsteroid)
             return true;
         else if (StoredVessel(ID).vesselType != VesselType.SpaceObject)
             return true;
         else
             return false;
     }
     else
         return false;
 }
        private KACAlarm QuickAddEarth(Int32 Minutes)
        {
            KACAlarm tmpAlarm = new KACAlarm(EarthTimeEncode(DateTime.Now.AddMinutes(Minutes)));
            tmpAlarm.TypeOfAlarm = KACAlarm.AlarmTypeEnum.EarthTime;
            tmpAlarm.Name = "Quick Earth Alarm";

            alarms.Add(tmpAlarm);

            return tmpAlarm;
        }
        private static Vessel FindVesselForAlarm(KACAlarm tmpAlarm)
        {
            Vessel tmpVessel;
            String strVesselID = "";
            if (tmpAlarm.TypeOfAlarm == KACAlarm.AlarmType.Crew)
            {
                strVesselID = StoredCrewVessel(tmpAlarm.VesselID).id.ToString();
            }
            else
            {
                strVesselID = tmpAlarm.VesselID;
            }

            tmpVessel = FlightGlobals.Vessels.Find(delegate(Vessel v)
                {
                    return (strVesselID == v.id.ToString());
                }
            );
            return tmpVessel;
        }
 public Boolean DrawAlarmActionChoice2(ref KACAlarm.AlarmAction Choice, String LabelText, int LabelWidth)
 {
     Boolean blnReturn = false;
     GUILayout.BeginHorizontal();
     GUILayout.Label(LabelText, KACResources.styleAddHeading, GUILayout.Width(LabelWidth-10));
     int intChoice = (int)Choice;
     blnReturn = DrawRadioList(ref intChoice, "Message", "Kill Warp", "Pause");
     Choice = (KACAlarm.AlarmAction)intChoice;
     GUILayout.EndHorizontal();
     return blnReturn;
 }
        private KACAlarm QuickAddRaw()
        {
            KACAlarm tmpAlarm = new KACAlarm(KACWorkerGameState.CurrentTime.UT + 600);
            tmpAlarm.TypeOfAlarm= KACAlarm.AlarmTypeEnum.Raw;
            tmpAlarm.Name = "Quick Raw";
            if (KACWorkerGameState.IsVesselActive)
                tmpAlarm.VesselID = KACWorkerGameState.CurrentVessel.id.ToString();

            alarms.Add(tmpAlarm);

            return tmpAlarm;
        }