示例#1
0
        protected void nautListRow(tabs currentTab, ProtoCrewMember student)
        {
            GUIStyle     style         = HighLogic.Skin.label;
            ActiveCourse currentCourse = null;

            if (activeMap.ContainsKey(student))
            {
                currentCourse = activeMap[student];
            }
            bool onSelectedCourse = selectedCourse != null && currentCourse != null && currentCourse.id == selectedCourse.id;

            if (onSelectedCourse)
            {
                style = boldLabel;
            }
            bool selectedForCourse = selectedCourse != null && selectedCourse.Students.Contains(student);

            GUILayout.BeginHorizontal();
            try {
                GUILayout.Label(String.Format("{0} {1}", student.trait.Substring(0, 1), student.experienceLevel), GUILayout.Width(24));
                if (currentCourse == null && selectedCourse != null && (selectedForCourse || selectedCourse.MeetsStudentReqs(student)))
                {
                    if (toggleButton(student.name, selectedForCourse, GUILayout.Width(96)))
                    {
                        if (selectedForCourse)
                        {
                            selectedCourse.RemoveStudent(student);
                        }
                        else
                        {
                            selectedCourse.AddStudent(student);
                        }
                    }
                }
                else if (currentTab == tabs.Training)
                {
                    if (GUILayout.Button(student.name, GUILayout.Width(96)))
                    {
                        selectedNaut = student;
                    }
                }
                else
                {
                    GUILayout.Label(student.name, GUILayout.Width(96));
                }
                string course, complete, retires;
                if (currentCourse == null)
                {
                    if (student.inactive)
                    {
                        course   = "(inactive)";
                        complete = KSPUtil.PrintDate(student.inactiveTimeEnd, false);
                    }
                    else
                    {
                        course   = "(free)";
                        complete = "(n/a)";
                    }
                }
                else
                {
                    course   = currentCourse.name;
                    complete = KSPUtil.PrintDate(currentCourse.CompletionTime(), false);
                }
                GUILayout.Label(course, GUILayout.Width(96));
                GUILayout.Label(complete, GUILayout.Width(80));
                if (CrewHandler.Instance.kerbalRetireTimes.ContainsKey(student.name))
                {
                    retires = KSPUtil.PrintDate(CrewHandler.Instance.kerbalRetireTimes[student.name], false);
                }
                else
                {
                    retires = "(unknown)";
                }
                GUILayout.Label(retires, GUILayout.Width(80));
                if (currentCourse != null)
                {
                    if (currentCourse.seatMin > 1)
                    {
                        if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
                        {
                            cancelCourse(currentCourse);
                        }
                    }
                    else
                    {
                        if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
                        {
                            leaveCourse(currentCourse, student);
                        }
                    }
                }
            } finally {
                GUILayout.EndHorizontal();
            }
        }
示例#2
0
 public static string GetTimeLabel(SubspaceDisplayEntry currentEntry)
 {
     return($"T: +{KSPUtil.PrintTimeCompact(SystemsContainer.Get<WarpSystem>().GetSubspaceTime(currentEntry.SubspaceId), false)}");
 }
示例#3
0
文件: CrewHandler.cs 项目: naet1/RP-0
        public void Update()
        {
            if (HighLogic.CurrentGame == null || HighLogic.CurrentGame.CrewRoster == null)
            {
                return;
            }

            // Catch earlies
            if (firstLoad)
            {
                firstLoad = false;
                List <string> newHires = new List <string>();

                foreach (ProtoCrewMember pcm in HighLogic.CurrentGame.CrewRoster.Crew)
                {
                    if ((pcm.rosterStatus == ProtoCrewMember.RosterStatus.Assigned || pcm.rosterStatus == ProtoCrewMember.RosterStatus.Available) && !kerbalRetireTimes.ContainsKey(pcm.name))
                    {
                        if (pcm.trait != KerbalRoster.pilotTrait)
                        {
                            KerbalRoster.SetExperienceTrait(pcm, KerbalRoster.pilotTrait);
                        }

                        newHires.Add(pcm.name);
                        OnCrewHired(pcm, int.MinValue);
                    }
                }
                if (newHires.Count > 0)
                {
                    string msgStr = "Crew will retire as follows:";
                    foreach (string s in newHires)
                    {
                        msgStr += "\n" + s + ", no earlier than " + KSPUtil.PrintDate(kerbalRetireTimes[s], false);
                    }

                    PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                                 new Vector2(0.5f, 0.5f),
                                                 "InitialRetirementDateNotification",
                                                 "Initial Retirement Date",
                                                 msgStr
                                                 + "\n(Retirement will be delayed the more interesting flights they fly.)",
                                                 "OK",
                                                 false,
                                                 HighLogic.UISkin);
                }
            }

            // Retirements
            double time = Planetarium.GetUniversalTime();

            if (nextUpdate < time)
            {
                // Ensure that CrewHandler updates happen at predictable times so that accurate KAC alarms can be set.
                do
                {
                    nextUpdate += updateInterval;
                }while (nextUpdate < time);

                if (retirementEnabled)
                {
                    foreach (KeyValuePair <string, double> kvp in kerbalRetireTimes)
                    {
                        ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[kvp.Key];
                        if (pcm == null)
                        {
                            toRemove.Add(kvp.Key);
                        }
                        else
                        {
                            if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Available)
                            {
                                if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Assigned)
                                {
                                    toRemove.Add(kvp.Key);
                                }

                                continue;
                            }

                            if (pcm.inactive)
                            {
                                continue;
                            }

                            if (time > kvp.Value)
                            {
                                toRemove.Add(kvp.Key);
                                retirees.Add(kvp.Key);
                                pcm.rosterStatus = ProtoCrewMember.RosterStatus.Dead;
                            }
                        }
                    }
                }

                bool anyCourseEnded = false;
                for (int i = ActiveCourses.Count; i-- > 0;)
                {
                    ActiveCourse course = ActiveCourses[i];
                    if (course.ProgressTime(time)) //returns true when the course completes
                    {
                        ActiveCourses.RemoveAt(i);
                        anyCourseEnded = true;
                    }
                }

                for (int i = expireTimes.Count; i-- > 0;)
                {
                    TrainingExpiration e = expireTimes[i];
                    if (time > e.expiration)
                    {
                        ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[e.pcmName];
                        if (pcm != null)
                        {
                            for (int j = pcm.careerLog.Entries.Count; j-- > 0;)
                            {
                                int eC = e.entries.Count;
                                if (eC == 0)
                                {
                                    break;
                                }
                                FlightLog.Entry ent = pcm.careerLog[j];
                                for (int k = eC; k-- > 0;)
                                {
                                    // Allow only mission trainings to expire.
                                    // This check is actually only needed for old savegames as only these can have expirations on proficiencies.
                                    if (ent.type == "TRAINING_mission" && e.Compare(k, ent))
                                    {
                                        ScreenMessages.PostScreenMessage(pcm.name + ": Expired: " + GetPrettyCourseName(ent.type) + ent.target);
                                        ent.type = "expired_" + ent.type;
                                        e.entries.RemoveAt(k);
                                    }
                                }
                            }
                        }
                        expireTimes.RemoveAt(i);
                    }
                }

                // TODO remove from courses? Except I think they won't retire if inactive either so that's ok.
                if (toRemove.Count > 0)
                {
                    string msgStr = string.Empty;
                    foreach (string s in toRemove)
                    {
                        kerbalRetireTimes.Remove(s);
                        if (HighLogic.CurrentGame.CrewRoster[s] != null && retirees.Contains(s))
                        {
                            msgStr = $"{msgStr}\n{s}";
                        }
                    }
                    if (!string.IsNullOrEmpty(msgStr))
                    {
                        PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                                     new Vector2(0.5f, 0.5f),
                                                     "CrewRetirementNotification",
                                                     "Crew Retirement",
                                                     "The following retirements have occurred:\n" + msgStr,
                                                     "OK",
                                                     true,
                                                     HighLogic.UISkin);
                    }

                    toRemove.Clear();
                }

                if (anyCourseEnded || toRemove.Count > 0)
                {
                    MaintenanceHandler.Instance?.UpdateUpkeep();
                }
            }

            // UI fixing
            if (inAC)
            {
                if (astronautComplex == null)
                {
                    KSP.UI.Screens.AstronautComplex[] mbs = GameObject.FindObjectsOfType <KSP.UI.Screens.AstronautComplex>();
                    int maxCount = -1;
                    foreach (KSP.UI.Screens.AstronautComplex c in mbs)
                    {
                        int count = c.ScrollListApplicants.Count + c.ScrollListAssigned.Count + c.ScrollListAvailable.Count + c.ScrollListKia.Count;
                        if (count > maxCount)
                        {
                            maxCount         = count;
                            astronautComplex = c;
                        }
                    }

                    if (astronautComplex == null)
                    {
                        return;
                    }
                }
                int newAv   = astronautComplex.ScrollListAvailable.Count;
                int newAsgn = astronautComplex.ScrollListAssigned.Count;
                int newKIA  = astronautComplex.ScrollListKia.Count;
                if (newAv != countAvailable || newKIA != countKIA || newAsgn != countAssigned)
                {
                    countAvailable = newAv;
                    countAssigned  = newAsgn;
                    countKIA       = newKIA;

                    foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListAvailable)
                    {
                        KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>();
                        if (cli != null)
                        {
                            FixTooltip(cli);
                            if (cli.GetCrewRef().inactive)
                            {
                                cli.MouseoverEnabled = false;
                                bool notTraining = true;
                                for (int i = ActiveCourses.Count; i-- > 0 && notTraining;)
                                {
                                    foreach (ProtoCrewMember pcm in ActiveCourses[i].Students)
                                    {
                                        if (pcm == cli.GetCrewRef())
                                        {
                                            notTraining = false;
                                            cli.SetLabel("Training, done " + KSPUtil.PrintDate(ActiveCourses[i].startTime + ActiveCourses[i].GetTime(ActiveCourses[i].Students), false));
                                            break;
                                        }
                                    }
                                }
                                if (notTraining)
                                {
                                    cli.SetLabel("Recovering");
                                }
                            }
                        }
                    }

                    foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListAssigned)
                    {
                        KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>();
                        if (cli != null)
                        {
                            FixTooltip(cli);
                        }
                    }

                    foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListKia)
                    {
                        KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>();
                        if (cli != null)
                        {
                            if (retirees.Contains(cli.GetName()))
                            {
                                cli.SetLabel("Retired");
                                cli.MouseoverEnabled = false;
                            }
                        }
                    }
                }
            }
        }
示例#4
0
        public void CalculateMass()
        {
            if (tankList == null || !massDirty)
            {
                return;
            }
            massDirty = false;

            double basemass = basemassConst + basemassPV * (MFSSettings.basemassUseTotalVolume ? totalVolume : volume);

            CalculateMassRF(ref basemass);

            if (basemass >= 0)
            {
                double tankDryMass = 0;
                for (int i = 0; i < tankList.Count; i++)
                {
                    var tank = tankList[i];
                    tankDryMass += tank.maxAmount * tank.mass / tank.utilization;
                }
                mass = (float)((basemass + tankDryMass) * MassMult);

                // compute massDelta based on prefab, if available.
                if (part.partInfo == null || part.partInfo.partPrefab == null)
                {
                    part.mass = mass;
                    massDelta = 0;
                }
                else
                {
                    massDelta = mass - part.partInfo.partPrefab.mass;
                }
            }
            else
            {
                mass      = part.mass;            // display dry mass even in this case.
                massDelta = 0f;
            }

            if (isEditor)
            {
                UsedVolume = tankList
                             .Where(fuel => fuel.maxAmount > 0 && fuel.utilization > 0)
                             .Sum(fuel => fuel.maxAmount / fuel.utilization);

                double availRounded = AvailableVolume;
                if (Math.Abs(availRounded) < 0.001d)
                {
                    availRounded = 0d;
                }
                string availVolStr = KSPUtil.PrintSI(availRounded, MFSSettings.unitLabel);
                string volStr      = KSPUtil.PrintSI(volume, MFSSettings.unitLabel);
                volumeDisplay = "Avail: " + availVolStr + " / Tot: " + volStr;

                double resourceMass = part.Resources.Cast <PartResource> ().Sum(partResource => partResource.maxAmount * partResource.info.density);

                double wetMass = mass + resourceMass;
                massDisplay = "Dry: " + FormatMass(mass) + " / Wet: " + FormatMass((float)wetMass);

                UpdateTweakableMenu();
            }
        }
示例#5
0
        public void DrawContent(int windowId)
        {
            GUILayout.BeginVertical();
            GUI.DragWindow(MoveRect);

            #region Horizontal toolbar

            GUILayout.BeginHorizontal();

            GUILayout.FlexibleSpace();
            var chatButtonStyle = ButtonStyle;
            if (ChatSystem.Singleton.ChatButtonHighlighted)
            {
                chatButtonStyle = HighlightStyle;
            }
            if (!SettingsSystem.ServerSettings.DropControlOnVesselSwitching)
            {
                var tooltip = "Drops control of the vessels that you are not controlling so other players can control them";
                if (GUILayout.Button(new GUIContent("DropCtrl", tooltip), ButtonStyle))
                {
                    VesselLockSystem.Singleton.DropAllOtherVesselControlLocks();
                }
            }
            ChatWindow.Singleton.Display         = GUILayout.Toggle(ChatWindow.Singleton.Display, "Chat", chatButtonStyle);
            CraftLibraryWindow.Singleton.Display = GUILayout.Toggle(CraftLibraryWindow.Singleton.Display, "Craft", ButtonStyle);
            DebugWindow.Singleton.Display        = GUILayout.Toggle(DebugWindow.Singleton.Display, "Debug", ButtonStyle);

            GUILayout.EndHorizontal();

            #endregion

            #region Players information

            ScrollPosition = GUILayout.BeginScrollView(ScrollPosition, ScrollStyle);

            //Draw other subspaces
            foreach (var currentEntry in SubspaceDisplay)
            {
                if (currentEntry.SubspaceId == -1)
                {
                    //Draw the warping players
                    GUILayout.BeginHorizontal(SubspaceStyle);
                    GUILayout.Label("WARPING");
                    GUILayout.EndHorizontal();
                }
                else
                {
                    GUILayout.BeginHorizontal(SubspaceStyle);
                    GUILayout.Label("T: +" + KSPUtil.PrintTimeCompact(WarpSystem.Singleton.GetSubspaceTime(currentEntry.SubspaceId), false));
                    GUILayout.FlexibleSpace();
                    if (NotWarpingAndIsFutureSubspace(currentEntry.SubspaceId) && GUILayout.Button("Sync", ButtonStyle))
                    {
                        WarpSystem.Singleton.CurrentSubspace = currentEntry.SubspaceId;
                    }
                    GUILayout.EndHorizontal();
                }

                foreach (var currentPlayer in currentEntry.Players)
                {
                    DrawPlayerEntry(currentPlayer == SettingsSystem.CurrentSettings.PlayerName
                        ? StatusSystem.Singleton.MyPlayerStatus
                        : StatusSystem.Singleton.GetPlayerStatus(currentPlayer));
                }
            }

            GUILayout.EndScrollView();

            #endregion

            GUILayout.FlexibleSpace();
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Disconnect", ButtonStyle))
            {
                DisconnectEventHandled = false;
            }
            OptionsWindow.Singleton.Display = GUILayout.Toggle(OptionsWindow.Singleton.Display, "Options", ButtonStyle);
            GUILayout.EndHorizontal();

            GUILayout.EndVertical();
        }
示例#6
0
        /// <summary>
        /// This method is called once when the part is loaded into the current scene, after OnLoad.
        /// </summary>
        /// <param name="state"></param>
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            if (GameSettings.VERBOSE_DEBUG_LOG)
            {
                Debug.Log("[USI Tools] Rotator.OnStart called.");
            }

            // Make sure the text for gui events is set correctly
            DirectionToggle(IsInverted);
            StartStopToggle(IsRunning);

            // Let's see if we can find our fixed mesh and movable mesh
            try
            {
                _fixedMesh   = KSPUtil.FindInPartModel(transform, FixedMeshName);
                _movableMesh = KSPUtil.FindInPartModel(transform, MovableMeshName);

                if (_fixedMesh != null && _movableMesh != null)
                {
                    if (GameSettings.VERBOSE_DEBUG_LOG)
                    {
                        Debug.Log("[USI Tools] Rotator.OnStart: Found fixed mesh!");
                        Debug.Log("[USI Tools] Rotator.OnStart: Found movable mesh!");
                    }

                    // Give our FixedMesh its own Rigidbody
                    Rigidbody fixedMeshRigidbody = _fixedMesh.gameObject.AddComponent <Rigidbody>();

                    // Give our MovableMesh its own Rigidbody
                    _movableMesh.gameObject.AddComponent <Rigidbody>();

                    // Setup a Joint for our MovableMesh and cache a reference to the motor for later
                    _rotatorJoint      = _movableMesh.gameObject.AddComponent <HingeJoint>();
                    _rotatorJointMotor = _rotatorJoint.motor;

                    // Mate the joint to the FixedMesh
                    _rotatorJoint.connectedBody = fixedMeshRigidbody;

                    // Configure other Joint options
                    _rotatorJoint.anchor = Vector3.zero;
                    _rotatorJoint.axis   = new Vector3(RotationAxisX, RotationAxisY, RotationAxisZ);
                    _rotatorJoint.autoConfigureConnectedAnchor = true;
                    _rotatorJoint.useMotor    = true;
                    _rotatorJoint.breakForce  = float.PositiveInfinity;
                    _rotatorJoint.breakTorque = float.PositiveInfinity;

                    // Setup the motor on the joint
                    UpdateMotor();
                }
                else
                {
                    throw new Exception("Part must contain child GameObjects named " + FixedMeshName + " and " + MovableMeshName + ".");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("[USI Tools] Rotator.OnStart encountered an error: " + ex.Message);
            }
        }
示例#7
0
        private void SpawnVessel(LootBoxVesselData LootBoxVesselData, List <ProtoCrewMember> crewData = null)
        {
            //      string gameDataDir = KSPUtil.ApplicationRootPath;
            Debug.Log("[Spawn OrX S Mart] Spawning " + LootBoxVesselData.name);

            // Set additional info for landed vessels
            bool landed = false;

            if (!landed)
            {
                landed = true;
                if (LootBoxVesselData.altitude == null || LootBoxVesselData.altitude < 0)
                {
                    LootBoxVesselData.altitude = 5;//LocationUtil.TerrainHeight(LootBoxVesselData.latitude, LootBoxVesselData.longitude, LootBoxVesselData.body);
                }
                Debug.Log("[Spawn OrX S Mart] SpawnVessel Altitude: " + LootBoxVesselData.altitude);

                //Vector3d pos = LootBoxVesselData.body.GetWorldSurfacePosition(LootBoxVesselData.latitude, LootBoxVesselData.longitude, LootBoxVesselData.altitude.Value);
                Vector3d pos = LootBoxVesselData.body.GetRelSurfacePosition(LootBoxVesselData.latitude, LootBoxVesselData.longitude, LootBoxVesselData.altitude.Value);

                LootBoxVesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, LootBoxVesselData.body);
                LootBoxVesselData.orbit.UpdateFromStateVectors(pos, LootBoxVesselData.body.getRFrmVel(pos), LootBoxVesselData.body, Planetarium.GetUniversalTime());
            }

            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            bool          hasClamp      = false;
            float         lcHeight      = 0;
            ConfigNode    craftNode;
            Quaternion    craftRotation = Quaternion.identity;

            if (!string.IsNullOrEmpty(LootBoxVesselData.craftURL))
            {
                // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
                ConfigNode currentShip = ShipConstruction.ShipConfig;

                shipConstruct = ShipConstruction.LoadShip(LootBoxVesselData.craftURL);
                if (shipConstruct == null)
                {
                    Debug.Log("[Spawn OrX S Mart] ShipConstruct was null when tried to load '" + LootBoxVesselData.craftURL +
                              "' (usually this means the file could not be found).");
                    return;//continue;
                }

                craftNode     = ConfigNode.Load(LootBoxVesselData.craftURL);
                lcHeight      = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
                craftRotation = ConfigNode.ParseQuaternion(craftNode.GetNode("PART").GetValue("rot"));

                // Restore ShipConstruction ship
                ShipConstruction.ShipConfig = currentShip;

                // Set the name
                if (string.IsNullOrEmpty(LootBoxVesselData.name))
                {
                    LootBoxVesselData.name = SMIVesselName;
                    ;
                }

                // Set some parameters that need to be at the part level
                uint missionID = (uint)Guid.NewGuid().GetHashCode();
                uint launchID  = HighLogic.CurrentGame.launchID++;
                foreach (Part p in shipConstruct.parts)
                {
                    p.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                    p.missionID = missionID;
                    p.launchID  = launchID;
                    p.flagURL   = flagURL;

                    // Had some issues with this being set to -1 for some ships - can't figure out
                    // why.  End result is the vessel exploding, so let's just set it to a positive
                    // value.
                    p.temperature = 1.0;
                }

                // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
                // We can't use the config nodes from the .craft file, because they are in a
                // slightly different format than those required for a ProtoVessel (seriously
                // Squad?!?).
                ConfigNode  empty       = new ConfigNode();
                ProtoVessel dummyProto  = new ProtoVessel(empty, null);
                Vessel      dummyVessel = new Vessel();
                dummyVessel.parts    = shipConstruct.parts;
                dummyProto.vesselRef = dummyVessel;

                // Create the ProtoPartSnapshot objects and then initialize them
                foreach (Part p in shipConstruct.parts)
                {
                    dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                }
                foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                {
                    p.storePartRefs();
                }

                // Create the ship's parts

                List <ConfigNode> partNodesL = new List <ConfigNode>();
                foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots)
                {
                    ConfigNode node = new ConfigNode("PART");
                    snapShot.Save(node);
                    partNodesL.Add(node);
                }
                partNodes = partNodesL.ToArray();
            }
            else
            {
                // Create crew member array
                ProtoCrewMember[] crewArray = new ProtoCrewMember[LootBoxVesselData.crew.Count];

                /*
                 *      int i = 0;
                 *      foreach (CrewData cd in LootBoxVesselData.crew)
                 *      {
                 * /*
                 *        // Create the ProtoCrewMember
                 *        ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew);
                 *        if (cd.name != null)
                 *        {
                 *          crewMember.KerbalRef.name = cd.name;
                 *        }
                 *
                 *        crewArray[i++] = crewMember;
                 *
                 *      }
                 */
                // Create part nodes
                uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                partNodes    = new ConfigNode[1];
                partNodes[0] = ProtoVessel.CreatePartNode(LootBoxVesselData.craftPart.name, flightId, crewArray);

                // Default the size class
                //sizeClass = UntrackedObjectClass.A;

                // Set the name
                if (string.IsNullOrEmpty(LootBoxVesselData.name))
                {
                    LootBoxVesselData.name = LootBoxVesselData.craftPart.name;
                }
            }

            // Create additional nodes
            ConfigNode[] additionalNodes = new ConfigNode[0];
            //DiscoveryLevels discoveryLevel = LootBoxVesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
            //additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

            // Create the config node representation of the ProtoVessel
            ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(LootBoxVesselData.name, LootBoxVesselData.vesselType, LootBoxVesselData.orbit, 0, partNodes, additionalNodes);

            // Additional seetings for a landed vessel
            if (!LootBoxVesselData.orbiting)
            {
                Vector3d norm = LootBoxVesselData.body.GetRelSurfaceNVector(LootBoxVesselData.latitude, LootBoxVesselData.longitude);

                double terrainHeight = 0.0;
                if (LootBoxVesselData.body.pqsController != null)
                {
                    terrainHeight = LootBoxVesselData.body.pqsController.GetSurfaceHeight(norm) - LootBoxVesselData.body.pqsController.radius;
                }
                bool splashed = false;// = landed && terrainHeight < 0.001;

                // Create the config node representation of the ProtoVessel
                // Note - flying is experimental, and so far doesn't worx
                protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ?
                                                 Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString());
                protoVesselNode.SetValue("landed", (landed && !splashed).ToString());
                protoVesselNode.SetValue("splashed", splashed.ToString());
                protoVesselNode.SetValue("lat", LootBoxVesselData.latitude.ToString());
                protoVesselNode.SetValue("lon", LootBoxVesselData.longitude.ToString());
                protoVesselNode.SetValue("alt", LootBoxVesselData.altitude.ToString());
                protoVesselNode.SetValue("landedAt", LootBoxVesselData.body.name);

                // Figure out the additional height to subtract
                float lowest = float.MaxValue;
                if (shipConstruct != null)
                {
                    foreach (Part p in shipConstruct.parts)
                    {
                        foreach (Collider collider in p.GetComponentsInChildren <Collider>())
                        {
                            if (collider.gameObject.layer != 21 && collider.enabled)
                            {
                                lowest = Mathf.Min(lowest, collider.bounds.min.y);
                            }
                        }
                    }
                }
                else
                {
                    foreach (Collider collider in LootBoxVesselData.craftPart.partPrefab.GetComponentsInChildren <Collider>())
                    {
                        if (collider.gameObject.layer != 21 && collider.enabled)
                        {
                            lowest = Mathf.Min(lowest, collider.bounds.min.y);
                        }
                    }
                }

                if (lowest == float.MaxValue)
                {
                    lowest = 0;
                }

                // Figure out the surface height and rotation
                Quaternion normal   = Quaternion.LookRotation((Vector3)norm);// new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                Quaternion rotation = Quaternion.identity;
                float      heading  = LootBoxVesselData.heading;
                if (shipConstruct == null)
                {
                    rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
                }
                else if (shipConstruct.shipFacility == EditorFacility.SPH)
                {
                    rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward);
                    heading += 180.0f;
                }
                else
                {
                    rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward);
                    rotation = Quaternion.FromToRotation(Vector3.up, -Vector3.up) * rotation;

                    //rotation = craftRotation;


                    LootBoxVesselData.heading = 0;
                    LootBoxVesselData.pitch   = 0;
                }

                rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back);
                rotation = rotation * Quaternion.AngleAxis(LootBoxVesselData.roll, Vector3.down);
                rotation = rotation * Quaternion.AngleAxis(LootBoxVesselData.pitch, Vector3.left);

                // Set the height and rotation
                if (landed || splashed)
                {
                    float hgt = (shipConstruct != null ? shipConstruct.parts[0] : LootBoxVesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest;
                    hgt += LootBoxVesselData.height;
                    protoVesselNode.SetValue("hgt", hgt.ToString(), true);
                }
                protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation), true);

                // Set the normal vector relative to the surface
                Vector3 nrm = (rotation * Vector3.forward);
                protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z, true);

                protoVesselNode.SetValue("prst", false.ToString(), true);
            }

            // Add vessel to the game
            ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            //protoVessel.vesselRef.transform.rotation = protoVessel.rotation;


            // Store the id for later use
            LootBoxVesselData.id = protoVessel.vesselRef.id;

            //protoVessel.vesselRef.currentStage = 0;
            hasClamp = false;

            StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp));

            // Associate it so that it can be used in contract parameters
            //ContractVesselTracker.Instance.AssociateVessel(LootBoxVesselData.name, protoVessel.vesselRef);


            //destroy prefabs
            foreach (Part p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
        }
示例#8
0
 public override void Draw()
 {
     _windowRect = KSPUtil.ClampRectToScreen(ClickThruBlocker.GUIWindow(99, _windowRect, DrawSequenceWindow, "", StyleFactory.LaunchSequenceStyle));
     GUI.BringWindowToFront(99);
 }
示例#9
0
文件: FSGUI.cs 项目: nepphhh/RP-0
        protected void nautListRow(tabs currentTab, ProtoCrewMember student)
        {
            GUIStyle     style         = HighLogic.Skin.label;
            ActiveCourse currentCourse = null;

            if (activeMap.ContainsKey(student))
            {
                currentCourse = activeMap[student];
            }
            bool onSelectedCourse = selectedCourse != null && currentCourse != null && currentCourse.id == selectedCourse.id;

            if (onSelectedCourse)
            {
                style = boldLabel;
            }
            bool selectedForCourse = selectedCourse != null && selectedCourse.Students.Contains(student);

            GUILayout.BeginHorizontal();
            try {
                GUILayout.Label(String.Format("{0} {1}", student.trait.Substring(0, 1), student.experienceLevel), GUILayout.Width(24));
                if (currentCourse == null && selectedCourse != null && (selectedForCourse || selectedCourse.MeetsStudentReqs(student)))
                {
                    if (toggleButton(student.name, selectedForCourse, GUILayout.Width(144)))
                    {
                        if (selectedForCourse)
                        {
                            selectedCourse.RemoveStudent(student);
                        }
                        else
                        {
                            selectedCourse.AddStudent(student);
                        }
                    }
                }
                else if (currentTab == tabs.Training)
                {
                    if (GUILayout.Button(student.name, GUILayout.Width(144)))
                    {
                        selectedNaut = student;
                    }
                }
                else
                {
                    GUILayout.Label(student.name, GUILayout.Width(144));
                }
                string course, complete, retires;
                if (currentCourse == null)
                {
                    if (student.rosterStatus == ProtoCrewMember.RosterStatus.Assigned)
                    {
                        course   = "(in-flight)";
                        complete = KSPUtil.PrintDate(student.inactiveTimeEnd, false);
                    }
                    else if (student.inactive)
                    {
                        course   = "(inactive)";
                        complete = KSPUtil.PrintDate(student.inactiveTimeEnd, false);
                    }
                    else
                    {
                        course   = "(free)";
                        complete = "(n/a)";
                    }
                }
                else
                {
                    course   = currentCourse.name;
                    complete = KSPUtil.PrintDate(currentCourse.CompletionTime(), false);
                }
                GUILayout.Label(course, GUILayout.Width(96));
                GUILayout.Label(complete, GUILayout.Width(80));
                if (CrewHandler.Instance.kerbalRetireTimes.ContainsKey(student.name))
                {
                    retires = CrewHandler.Instance.retirementEnabled ? KSPUtil.PrintDate(CrewHandler.Instance.kerbalRetireTimes[student.name], false) : "(n/a)";
                }
                else
                {
                    retires = "(unknown)";
                }
                GUILayout.Label(retires, GUILayout.Width(80));
                if (currentCourse != null)
                {
                    if (currentCourse.seatMin > 1)
                    {
                        if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
                        {
                            cancelCourse(currentCourse);
                        }
                    }
                    else
                    {
                        if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
                        {
                            leaveCourse(currentCourse, student);
                        }
                    }

                    if (KACWrapper.APIReady && GUILayout.Button(nautRowAlarmBtnContent, GUILayout.ExpandWidth(false)))
                    {
                        // CrewHandler processes trainings every 3600 seconds. Need to account for that to set up accurate KAC alarms.
                        double completeUT = currentCourse.CompletionTime();
                        double timeDiff   = completeUT - CrewHandler.Instance.nextUpdate;
                        double timesChRun = Math.Ceiling(timeDiff / CrewHandler.Instance.updateInterval);
                        double alarmUT    = CrewHandler.Instance.nextUpdate + timesChRun * CrewHandler.Instance.updateInterval;
                        string alarmTxt   = $"{currentCourse.name} - {student.name}";
                        KACWrapper.KAC.CreateAlarm(KACWrapper.KACAPI.AlarmTypeEnum.Crew, alarmTxt, alarmUT);
                    }
                }
            } finally {
                GUILayout.EndHorizontal();
            }
        }
示例#10
0
文件: CrewHandler.cs 项目: Eccta/RP-0
        private void FixAstronauComplexUI()
        {
            if (_astronautComplex == null)
            {
                AstronautComplex[] mbs = GameObject.FindObjectsOfType <KSP.UI.Screens.AstronautComplex>();
                int maxCount           = -1;
                foreach (AstronautComplex c in mbs)
                {
                    int count = c.ScrollListApplicants.Count + c.ScrollListAssigned.Count + c.ScrollListAvailable.Count + c.ScrollListKia.Count;
                    if (count > maxCount)
                    {
                        maxCount          = count;
                        _astronautComplex = c;
                    }
                }

                if (_astronautComplex == null)
                {
                    return;
                }
            }
            int newAv   = _astronautComplex.ScrollListAvailable.Count;
            int newAsgn = _astronautComplex.ScrollListAssigned.Count;
            int newKIA  = _astronautComplex.ScrollListKia.Count;

            if (newAv != _countAvailable || newKIA != _countKIA || newAsgn != _countAssigned)
            {
                _countAvailable = newAv;
                _countAssigned  = newAsgn;
                _countKIA       = newKIA;

                foreach (UIListData <UIListItem> u in _astronautComplex.ScrollListAvailable)
                {
                    CrewListItem cli = u.listItem.GetComponent <CrewListItem>();
                    if (cli != null)
                    {
                        FixTooltip(cli);
                        if (cli.GetCrewRef().inactive)
                        {
                            cli.MouseoverEnabled = false;
                            bool notTraining = true;
                            for (int i = ActiveCourses.Count; i-- > 0 && notTraining;)
                            {
                                foreach (ProtoCrewMember pcm in ActiveCourses[i].Students)
                                {
                                    if (pcm == cli.GetCrewRef())
                                    {
                                        notTraining = false;
                                        cli.SetLabel("Training, done " + KSPUtil.PrintDate(ActiveCourses[i].startTime + ActiveCourses[i].GetTime(ActiveCourses[i].Students), false));
                                        break;
                                    }
                                }
                            }
                            if (notTraining)
                            {
                                cli.SetLabel("Recovering");
                            }
                        }
                    }
                }

                foreach (UIListData <UIListItem> u in _astronautComplex.ScrollListAssigned)
                {
                    CrewListItem cli = u.listItem.GetComponent <CrewListItem>();
                    if (cli != null)
                    {
                        FixTooltip(cli);
                    }
                }

                foreach (UIListData <UIListItem> u in _astronautComplex.ScrollListKia)
                {
                    CrewListItem cli = u.listItem.GetComponent <CrewListItem>();
                    if (cli != null)
                    {
                        if (_retirees.Contains(cli.GetName()))
                        {
                            cli.SetLabel("Retired");
                            cli.MouseoverEnabled = false;
                        }
                    }
                }
            }
        }
示例#11
0
        public void Load()
        {
            Debug.Log("[PR] Loading Data.");

            //This is called when all persistent rotation data is being loaded from the cfg file.

            #region ### Quicksave selection ###
            ConfigNode temp        = null;
            float      temp_delta  = 0f;
            ConfigNode load        = null;
            float      load_delta  = 0f;
            float      oldest_time = 0f;

            List <String> allPaths = GetAllPaths();

            if (allPaths.Count() == 0)
            {
                Debug.Log("[PR] No save files found.");
                return;
            }

            foreach (String path in allPaths)
            {
                temp = ConfigNode.Load(path);
                if (temp == null)
                {
                    Debug.Log("[PR] Couldn't load data: File not found.");
                    continue;
                }


                float time = float.Parse(temp.GetValue("TIME"));
                temp_delta = Mathf.Abs(time - (float)Planetarium.GetUniversalTime());

                if (time > oldest_time)
                {
                    oldest_time = time;
                }

                if (load == null)
                {
                    load       = temp;
                    load_delta = temp_delta;
                }
                else
                {
                    if (temp_delta < load_delta)
                    {
                        load       = temp;
                        load_delta = temp_delta;
                    }
                }
            }
            #endregion

            //Load global variables

            defaultReferenceMode = (DefaultReferenceMode)(int.Parse(load.GetValue("DEFAULT_REFERENCE_MODE")));

            //Pregenerate data for all vessels that currently exist

            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                FindPRVessel(vessel);
            }

            //All vessels should now have data.

            //Load PRVessel data

            foreach (PRVessel v in PRVessels)
            {
                ConfigNode cn_vessel = load.GetNode(v.vessel.id.ToString());

                if (cn_vessel != null) //If node exists at all
                {
                    Debug.Log("[PR] Found node for vessel " + v.vessel.vesselName);
                    v.momentum           = KSPUtil.ParseVector3(cn_vessel.GetValue("MOMENTUM"));
                    v.planetariumRight   = KSPUtil.ParseVector3(cn_vessel.GetValue("PLANETARIUM_RIGHT"));
                    v.mjMode             = MechJebWrapper.saTargetMap[int.Parse(cn_vessel.GetValue("MJMODE"))];
                    v.rtMode             = RemoteTechWrapper.acFlightModeMap[int.Parse(cn_vessel.GetValue("RTMODE"))];
                    v.rotationModeActive = Boolean.Parse(cn_vessel.GetValue("ROTATION_MODE_ACTIVE"));
                    v.dynamicReference   = Boolean.Parse(cn_vessel.GetValue("DYNAMIC_REFERENCE"));
                    v.rotation           = KSPUtil.ParseQuaternion(cn_vessel.GetValue("ROTATION"));
                    v.direction          = KSPUtil.ParseVector3(cn_vessel.GetValue("DIRECTION"));

                    string reference = cn_vessel.GetValue("REFERENCE");

                    v.reference = null;

                    if (reference != "NONE")
                    {
                        foreach (CelestialBody body in FlightGlobals.Bodies)
                        {
                            if (body.name == reference)
                            {
                                v.reference = body;
                            }
                        }

                        foreach (Vessel vessel in FlightGlobals.Vessels)
                        {
                            if (vessel.id.ToString() == reference)
                            {
                                v.reference = vessel;
                            }
                        }
                    }

                    v.momentumModeActive = Boolean.Parse(cn_vessel.GetValue("MOMENTUM_MODE_ACTIVE"));
                    v.desiredRPM         = float.Parse(cn_vessel.GetValue("DESIRED_RPM"));
                }
            }

            //If old save state is loaded, delete all save files!
            if (float.Parse(load.GetValue("TIME")) < oldest_time)
            {
                Debug.Log("[PR] Reloading old save, flushing data.");

                foreach (String path in GetAllPaths())
                {
                    File.Delete(path);
                }

                //Save current loaded one.
                Save();
            }

            //TODO: Delete all files on Launch / Keep all files that correspond to a quicksave

            Debug.Log("[PR] Oldest time: " + oldest_time.ToString());
            Debug.Log("[PR] Loaded time: " + load.GetValue("TIME"));

            Interface.instance.desiredRPMstr = FindPRVessel(FlightGlobals.ActiveVessel).desiredRPM.ToString(); //Set desired rpm of active vessel
        }
示例#12
0
文件: CrewHandler.cs 项目: Eccta/RP-0
        private void OnCrewHired(ProtoCrewMember pcm, int idx)
        {
            double retireTime = Planetarium.GetUniversalTime() + GetServiceTime(pcm);

            KerbalRetireTimes[pcm.name] = retireTime;

            if (RetirementEnabled && idx != int.MinValue)
            {
                PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                             new Vector2(0.5f, 0.5f),
                                             "InitialRetirementDateNotification",
                                             "Initial Retirement Date",
                                             $"{pcm.name} will retire no earlier than {KSPUtil.PrintDate(retireTime, false)}\n(Retirement will be delayed the more interesting flights they fly.)",
                                             "OK",
                                             false,
                                             HighLogic.UISkin);
            }
        }
示例#13
0
        public string GetTrainingString(ProtoCrewMember pcm)
        {
            bool   found       = false;
            string trainingStr = "\n\nTraining:";
            int    lastFlight  = pcm.careerLog.Last() == null ? 0 : pcm.careerLog.Last().flight;

            foreach (FlightLog.Entry ent in pcm.careerLog.Entries)
            {
                string pretty = GetPrettyCourseName(ent.type);
                if (!string.IsNullOrEmpty(pretty))
                {
                    if (ent.type == "TRAINING_proficiency")
                    {
                        found        = true;
                        trainingStr += "\n  " + pretty + ent.target;
                    }
                    else if (ent.type == "TRAINING_mission")
                    {
                        double exp = GetExpiration(pcm.name, ent);
                        if (exp > 0d)
                        {
                            trainingStr += "\n  " + pretty + ent.target + ". Expires " + KSPUtil.PrintDate(exp, false);
                        }
                    }
                }
            }

            if (found)
            {
                return(trainingStr);
            }
            else
            {
                return(string.Empty);
            }
        }
示例#14
0
        protected void VesselRecoveryRequested(Vessel v)
        {
            double        elapsedTime       = v.missionTime;
            List <string> retirementChanges = new List <string>();
            List <string> inactivity        = new List <string>();

            double UT = Planetarium.GetUniversalTime();

            // When flight duration was too short, mission training should not be set as expired.
            // This can happen when an on-the-pad failure occurs and the vessel is recovered.
            if (elapsedTime < settings.minFlightDurationSecondsForTrainingExpire)
            {
                return;
            }

            foreach (ProtoCrewMember pcm in v.GetVesselCrew())
            {
                bool hasSpace      = false;
                bool hasOrbit      = false;
                bool hasEVA        = false;
                bool hasEVAOther   = false;
                bool hasOther      = false;
                bool hasOrbitOther = false;
                bool hasLandOther  = false;
                int  curFlight     = pcm.careerLog.Last().flight;
                foreach (FlightLog.Entry e in pcm.careerLog.Entries)
                {
                    if (e.type == "TRAINING_mission")
                    {
                        SetExpiration(pcm.name, e, Planetarium.GetUniversalTime());
                    }

                    if (e.flight != curFlight)
                    {
                        continue;
                    }

                    bool isOther = false;
                    if (!string.IsNullOrEmpty(e.target) && e.target != Planetarium.fetch.Home.name)
                    {
                        isOther = hasOther = true;
                    }

                    if (!string.IsNullOrEmpty(e.type))
                    {
                        switch (e.type)
                        {
                        case "Suborbit":
                            hasSpace = true;
                            break;

                        case "Orbit":
                            if (isOther)
                            {
                                hasOrbitOther = true;
                            }
                            else
                            {
                                hasOrbit = true;
                            }
                            break;

                        case "ExitVessel":
                            if (isOther)
                            {
                                hasEVAOther = true;
                            }
                            else
                            {
                                hasEVA = true;
                            }
                            break;

                        case "Land":
                            if (isOther)
                            {
                                hasLandOther = true;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                }
                double multiplier = 1d;
                double constant   = 0.5d;
                if (hasSpace)
                {
                    multiplier += settings.recSpace.x;
                    constant   += settings.recSpace.y;
                }
                if (hasOrbit)
                {
                    multiplier += settings.recOrbit.x;
                    constant   += settings.recOrbit.y;
                }
                if (hasOther)
                {
                    multiplier += settings.recOtherBody.x;
                    constant   += settings.recOtherBody.y;
                }
                if (hasEVA)
                {
                    multiplier += settings.recEVA.x;
                    constant   += settings.recEVA.y;
                }
                if (hasEVAOther)
                {
                    multiplier += settings.recEVAOther.x;
                    constant   += settings.recEVAOther.y;
                }
                if (hasOrbitOther)
                {
                    multiplier += settings.recOrbitOther.x;
                    constant   += settings.recOrbitOther.y;
                }
                if (hasLandOther)
                {
                    multiplier += settings.recLandOther.x;
                    constant   += settings.recLandOther.y;
                }

                double retTime;
                if (kerbalRetireTimes.TryGetValue(pcm.name, out retTime))
                {
                    double offset = constant * 86400d * settings.retireOffsetBaseMult / (1 + Math.Pow(Math.Max(curFlight + settings.retireOffsetFlightNumOffset, 0d), settings.retireOffsetFlightNumPow)
                                                                                         * UtilMath.Lerp(settings.retireOffsetStupidMin, settings.retireOffsetStupidMax, pcm.stupidity));
                    if (offset > 0d)
                    {
                        retTime += offset;
                        kerbalRetireTimes[pcm.name] = retTime;
                        retirementChanges.Add("\n" + pcm.name + ", no earlier than " + KSPUtil.PrintDate(retTime, false));
                    }
                }

                multiplier /= (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d);

                double inactiveTime = elapsedTime * multiplier + constant * 86400d;
                pcm.SetInactive(inactiveTime, false);
                inactivity.Add("\n" + pcm.name + ", until " + KSPUtil.PrintDate(inactiveTime + UT, true, false));
            }
            if (inactivity.Count > 0)
            {
                string msgStr = "The following crew members will be on leave:";
                foreach (string s in inactivity)
                {
                    msgStr += s;
                }

                if (retirementEnabled && retirementChanges.Count > 0)
                {
                    msgStr += "\n\nThe following retirement changes have occurred:";
                    foreach (string s in retirementChanges)
                    {
                        msgStr += s;
                    }
                }

                PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                             new Vector2(0.5f, 0.5f),
                                             "CrewUpdateNotification",
                                             "Crew Updates",
                                             msgStr,
                                             "OK",
                                             true,
                                             HighLogic.UISkin);
            }
        }
示例#15
0
 private static string PrepareStartedMessage(ShipTemplate shipTemplate)
 {
     return($"<color=yellow>Ready in {KSPUtil.PrintDateDeltaCompact(ConstructScenario.Instance.ConstructionFinishAt(shipTemplate), true, false)}</color>");
 }
示例#16
0
    private void SpawnVessel(VesselData vesselData, List<ProtoCrewMember> crewData = null)
    {
      string gameDataDir = KSPUtil.ApplicationRootPath;
      Log.info("Spawning a vessel named '" + vesselData.name + "'");

      // Set additional info for landed vessels
      bool landed = false;
      if (!vesselData.orbiting)
      {
        landed = true;
        if (vesselData.altitude == null || vesselData.altitude < 0)
        {
          vesselData.altitude = 35;//LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body);
        }

        //Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);
        Vector3d pos = vesselData.body.GetRelSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);

        vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body);
        vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime());
      }
      else
      {
        vesselData.orbit.referenceBody = vesselData.body;
      }

      ConfigNode[] partNodes;
      //UntrackedObjectClass sizeClass;
      ShipConstruct shipConstruct = null;
      bool hasClamp = false;
      float lcHeight = 0;
      ConfigNode craftNode;
      Quaternion craftRotation = Quaternion.identity;
      if (!string.IsNullOrEmpty(vesselData.craftURL))
      {
        // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
        ConfigNode currentShip = ShipConstruction.ShipConfig;

        shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL);
        if (shipConstruct == null)
        {
          Log.info("ShipConstruct was null when tried to load '{0}' (usually this means the file could not be found).", vesselData.craftURL);
          return;//continue;
        }

        craftNode = ConfigNode.Load(vesselData.craftURL);
        lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
        craftRotation = ConfigNode.ParseQuaternion(craftNode.GetNode("PART").GetValue("rot"));

        // Restore ShipConstruction ship
        ShipConstruction.ShipConfig = currentShip;

        // Set the name
        if (string.IsNullOrEmpty(vesselData.name))
        {
          vesselData.name = shipConstruct.shipName;
        }
        
        // Set some parameters that need to be at the part level
        uint missionID = (uint)Guid.NewGuid().GetHashCode();
        uint launchID = HighLogic.CurrentGame.launchID++;
        foreach (Part p in shipConstruct.parts)
        {
            p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
          p.missionID = missionID;
          p.launchID = launchID;
          p.flagURL = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL;

          // Had some issues with this being set to -1 for some ships - can't figure out
          // why.  End result is the vessel exploding, so let's just set it to a positive
          // value.
          p.temperature = 1.0;
        }
        
        //add minimal crew
        //bool success = false;
        Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity);

        // Add the crew member
        if (part != null && VesselMoverToolbar.addCrewMembers)
        {
          if (VesselMoverToolbar.selectCrewMembers)
          {
            ProtoCrewMember crewMember = crewData.FirstOrDefault();
            if (crewMember != null)
              part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
            VesselMoverToolbar.SelectedCrewMembers.Clear();
          }
          else
          {
            // Create the ProtoCrewMember
            ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal();
            crewMember.gender = UnityEngine.Random.Range(0, 100) > 50
              ? ProtoCrewMember.Gender.Female
              : ProtoCrewMember.Gender.Male;
            //crewMember.trait = "Pilot";

            // Add them to the part
            part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
          }
        }

        // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
        // We can't use the config nodes from the .craft file, because they are in a
        // slightly different format than those required for a ProtoVessel (seriously
        // Squad?!?).
        ConfigNode empty = new ConfigNode();
        ProtoVessel dummyProto = new ProtoVessel(empty, null);
        Vessel dummyVessel = new Vessel();
        dummyVessel.parts = shipConstruct.Parts;
        dummyProto.vesselRef = dummyVessel;

        // Create the ProtoPartSnapshot objects and then initialize them
        foreach (Part p in shipConstruct.parts)
        {
            dummyVessel.loaded = false;
            p.vessel = dummyVessel;

            {
#if KSP_18
                ProtoPartSnapshot proto = new ProtoPartSnapshot(p, dummyProto, true)); // For KSP >= 1.8
#else 
                ProtoPartSnapshot proto = new ProtoPartSnapshot(p, dummyProto);      // For KSP 1.4.x
#endif
                dummyProto.protoPartSnapshots.Add(proto);
            }
        }
        foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
        {
          p.storePartRefs();
        }

        // Create the ship's parts

        List<ConfigNode> partNodesL = new List<ConfigNode>();
        foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots)
        {
          ConfigNode node = new ConfigNode("PART");
          snapShot.Save(node);
          partNodesL.Add(node);
        }
        partNodes = partNodesL.ToArray();




        // Estimate an object class, numbers are based on the in game description of the
        // size classes.
        //float size = shipConstruct.shipSize.magnitude / 2.0f;
        //if (size < 4.0f)
        //{
        //  sizeClass = UntrackedObjectClass.A;
        //}
        //else if (size < 7.0f)
        //{
        //  sizeClass = UntrackedObjectClass.B;
        //}
        //else if (size < 12.0f)
        //{
        //  sizeClass = UntrackedObjectClass.C;
        //}
        //else if (size < 18.0f)
        //{
        //  sizeClass = UntrackedObjectClass.D;
        //}
        //else
        //{
        //  sizeClass = UntrackedObjectClass.E;
        //}
      }
      else
      {
        // Create crew member array
        ProtoCrewMember[] crewArray = new ProtoCrewMember[vesselData.crew.Count];
        int i = 0;
        foreach (CrewData cd in vesselData.crew)
        {
          // Create the ProtoCrewMember
          ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew);
          if (cd.name != null)
          {
            crewMember.KerbalRef.name = cd.name;
          }

          crewArray[i++] = crewMember;
        }

        // Create part nodes
        uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
        partNodes = new ConfigNode[1];
        partNodes[0] = ProtoVessel.CreatePartNode(vesselData.craftPart.name, flightId, crewArray);

        // Default the size class
        //sizeClass = UntrackedObjectClass.A;

        // Set the name
        if (string.IsNullOrEmpty(vesselData.name))
        {
          vesselData.name = vesselData.craftPart.name;
        }
      }

      // Create additional nodes
      ConfigNode[] additionalNodes = new ConfigNode[0];
      //DiscoveryLevels discoveryLevel = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
      //additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

      // Create the config node representation of the ProtoVessel
      ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes);

      // Additional seetings for a landed vessel
      if (!vesselData.orbiting)
      {
        Vector3d norm = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude);

        double terrainHeight = 0.0;
        if (vesselData.body.pqsController != null)
        {
          terrainHeight = vesselData.body.pqsController.GetSurfaceHeight(norm) - vesselData.body.pqsController.radius;
        }
        bool splashed = false;// = landed && terrainHeight < 0.001;

        // Create the config node representation of the ProtoVessel
        // Note - flying is experimental, and so far doesn't work
        protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ?
          Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString());
        protoVesselNode.SetValue("landed", (landed && !splashed).ToString());
        protoVesselNode.SetValue("splashed", splashed.ToString());
        protoVesselNode.SetValue("lat", vesselData.latitude.ToString());
        protoVesselNode.SetValue("lon", vesselData.longitude.ToString());
        protoVesselNode.SetValue("alt", vesselData.altitude.ToString());
        protoVesselNode.SetValue("landedAt", vesselData.body.name);

        // Figure out the additional height to subtract
        float lowest = float.MaxValue;
        if (shipConstruct != null)
        {
          foreach (Part p in shipConstruct.parts)
          {
            foreach (Collider collider in p.GetComponentsInChildren<Collider>())
            {
              if (collider.gameObject.layer != 21 && collider.enabled)
              {
                lowest = Mathf.Min(lowest, collider.bounds.min.y);
              }
            }
          }
        }
        else
        {
          foreach (Collider collider in vesselData.craftPart.partPrefab.GetComponentsInChildren<Collider>())
          {
            if (collider.gameObject.layer != 21 && collider.enabled)
            {
              lowest = Mathf.Min(lowest, collider.bounds.min.y);
            }
          }
        }

        if (lowest == float.MaxValue)
        {
          lowest = 0;
        }

        // Figure out the surface height and rotation
        Quaternion normal = Quaternion.LookRotation((Vector3)norm);// new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
        Quaternion rotation = Quaternion.identity;
        float heading = vesselData.heading;
        if (shipConstruct == null)
        {
          rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
        }
        else if (shipConstruct.shipFacility == EditorFacility.SPH)
        {
          rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward);
          heading += 180.0f;
        }
        else
        {
          rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward);
          rotation = Quaternion.FromToRotation(Vector3.up, -Vector3.up) * rotation;

          //rotation = craftRotation;


          vesselData.heading = 0;
          vesselData.pitch = 0;
        }

        rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back);
        rotation = rotation * Quaternion.AngleAxis(vesselData.roll, Vector3.down);
        rotation = rotation * Quaternion.AngleAxis(vesselData.pitch, Vector3.left);

        // Set the height and rotation
        if (landed || splashed)
        {
          float hgt = (shipConstruct != null ? shipConstruct.parts[0] : vesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest;
          hgt += vesselData.height;

          foreach (Part p in shipConstruct.Parts)
          {
            LaunchClamp lc = p.FindModuleImplementing<LaunchClamp>();
            if (lc)
            {
              hasClamp = true;
              break;
            }
          }

          if (!hasClamp)
          {
            hgt += 35;
          }
          else
          {
            hgt += lcHeight;
          }
          protoVesselNode.SetValue("hgt", hgt.ToString(), true);
        }
        protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation), true);

        // Set the normal vector relative to the surface
        Vector3 nrm = (rotation * Vector3.forward);
        protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z, true);

        protoVesselNode.SetValue("prst", false.ToString(), true);
      }

      // Add vessel to the game
      ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);
      //protoVessel.vesselRef.transform.rotation = protoVessel.rotation;


      // Store the id for later use
      vesselData.id = protoVessel.vesselRef.id;

      //protoVessel.vesselRef.currentStage = 0;

      StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp));

      // Associate it so that it can be used in contract parameters
      //ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef);



      //destroy prefabs
      foreach (Part p in FindObjectsOfType<Part>())
      {
        if (!p.vessel)
        {
          Destroy(p.gameObject);
        }
      }
    }
示例#17
0
 private static string PrepareNotBuildMessage(ShipTemplate shipTemplate)
 {
     return($"<color=orange>Build in {KSPUtil.PrintDateDeltaCompact(ConstructScenario.Instance.ConstructionFinishAt(shipTemplate), true, false)}</color>");
 }
示例#18
0
        public static string ReqValueFormat(Require req, object reqValue)
        {
            switch (req)
            {
            case Require.OrbitMinEccentricity:
            case Require.OrbitMaxEccentricity:
            case Require.OrbitMinArgOfPeriapsis:
            case Require.OrbitMaxArgOfPeriapsis:
            case Require.AtmosphereAltMin:
            case Require.AtmosphereAltMax:
                return(((double)reqValue).ToString("F2"));

            case Require.SunAngleMin:
            case Require.SunAngleMax:
            case Require.OrbitMinInclination:
            case Require.OrbitMaxInclination:
                return(Lib.HumanReadableAngle((double)reqValue));

            case Require.TemperatureMin:
            case Require.TemperatureMax:
                return(Lib.HumanReadableTemp((double)reqValue));

            case Require.AltitudeMin:
            case Require.AltitudeMax:
            case Require.AltAboveGroundMin:
            case Require.AltAboveGroundMax:
            case Require.MaxAsteroidDistance:
                return(Lib.HumanReadableDistance((double)reqValue));

            case Require.RadiationMin:
            case Require.RadiationMax:
                return(Lib.HumanReadableRadiation((double)reqValue));

            case Require.VolumePerCrewMin:
            case Require.VolumePerCrewMax:
                return(Lib.HumanReadableVolume((double)reqValue));

            case Require.SurfaceSpeedMin:
            case Require.SurfaceSpeedMax:
            case Require.VerticalSpeedMin:
            case Require.VerticalSpeedMax:
            case Require.SpeedMin:
            case Require.SpeedMax:
                return(Lib.HumanReadableSpeed((double)reqValue));

            case Require.DynamicPressureMin:
            case Require.DynamicPressureMax:
            case Require.StaticPressureMin:
            case Require.StaticPressureMax:
            case Require.AtmDensityMin:
            case Require.AtmDensityMax:
                return(Lib.HumanReadablePressure((double)reqValue));

            case Require.CrewMin:
            case Require.CrewMax:
            case Require.CrewCapacityMin:
            case Require.CrewCapacityMax:
            case Require.AstronautComplexLevelMin:
            case Require.AstronautComplexLevelMax:
            case Require.TrackingStationLevelMin:
            case Require.TrackingStationLevelMax:
            case Require.MissionControlLevelMin:
            case Require.MissionControlLevelMax:
            case Require.AdministrationLevelMin:
            case Require.AdministrationLevelMax:
                return(((int)reqValue).ToString());

            case Require.Module:
                return(KSPUtil.PrintModuleName((string)reqValue));

            case Require.Part:
                return(PartLoader.getPartInfoByName((string)reqValue)?.title ?? (string)reqValue);

            default:
                return(string.Empty);
            }
        }
示例#19
0
        private void draw(int id)
        {
            if (!simTermination)
            {
                if (GUILayout.Button("Resume Simulation"/*, _guiSkin.button */))
                {
                    Log.Info("Close 1");
                    Close();
                }

                GUILayout.Space(SPACER);
            }
            if (GUILayout.Button("<color=orange>Terminate Simulation</color>"/*, _guiSkin.button */))
            {
                string revertTarget;

                switch (KRASHShelter.lastScene)
                {
                    case GameScenes.EDITOR:
                        switch (KRASHShelter.lastEditor)
                        {
                            case EditorFacility.SPH:
                                revertTarget = "Spaceplane Hangar";
                                break;
                            case EditorFacility.VAB:
                                revertTarget = "Vehicle Assembly Building";
                                break;
                            // This should never happen. If it does, just go to the SC
                            default:
                                revertTarget = "Space Center";
                                KRASHShelter.lastScene = GameScenes.SPACECENTER;
                                break;
                        }
                        break;
                    case GameScenes.SPACECENTER:
                        revertTarget = "Space Center";
                        break;
                    default:
                        revertTarget = "Pre-Simulation";
                        break;
                }
                string s = "Revert to " + revertTarget + " (" + KSPUtil.PrintTimeLong(((int)(Planetarium.GetUniversalTime() - FlightDriver.PostInitState.UniversalTime)));
                DialogGUIBase[] options = new DialogGUIBase[2];

                options[0] = new DialogGUIButton(s, () =>
                {
                    StartCoroutine(WaitForFlightResultsDialog());
                });
                options[1] = new DialogGUIButton("Cancel", () =>
                {
                    Log.Info("Close 2");

                    Close();
                });
                var multidialog = new MultiOptionDialog("krash2", "Terminating will set the game back to an earlier state. Are you sure you want to continue?", "Terminating Simulation",
                                      HighLogic.UISkin, 450, options);

                _activePopup = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), multidialog, false, HighLogic.UISkin, true);
                Hide();
            }


            if (FlightDriver.CanRevertToPostInit)
            {

                if (GUILayout.Button("<color=orange>Restart Simulation</color>"/*, _guiSkin.button*/))
                {

                    DialogGUIBase[] options = new DialogGUIBase[2];
                    string s = "Revert to Launch(" + KSPUtil.PrintTimeLong(((int)(Planetarium.GetUniversalTime() - FlightDriver.PostInitState.UniversalTime))) + " ago";
                    options[0] = new DialogGUIButton(s, () =>
                    {
                        Log.Info("Close 3");

                        Close();
                        Log.Info("Close 4");

                        Close();
                        FlightDriver.RevertToLaunch();
                        // The RevertTolaunch reloads all the objects, so we destroy them here to avoid conflicts
                        KRASHShelter.instance.DestroyModules();
                    });
                    options[1] = new DialogGUIButton("Cancel", () =>
                    {
                        Log.Info("Close 5");

                        Close();
                    });


                    var multidialog = new MultiOptionDialog("krash3", "Reverting will set the game back to an earlier state. Are you sure you want to continue?", "Reverting Simulation",
                                          HighLogic.UISkin, 450, options);




                    _activePopup = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), multidialog, false, HighLogic.UISkin, true);

                    //						_activePopup = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
                    //							new MultiOptionDialog(null, new Callback (drawRevertWarning), "Reverting Simulation", HighLogic.Skin, new DialogOption[0]), false, HighLogic.Skin);
                    APIManager.ApiInstance.SimRestartEvent.Fire((Vessel)FlightGlobals.ActiveVessel, KRASHShelter.simCost + KRASHShelter.simSetupCost);
                    Hide();
                }
            }

            GUILayout.Space(SPACER);

            if (GUILayout.Button("Settings"/*, _guiSkin.button*/))
            {
                Hide();
                _miniSettings = MiniSettings.Create(Unhide);
            }
#if false
			} else {
示例#20
0
        public override void OnLoad(ConfigNode node)
        {
            base.OnLoad(node);
            if (node.HasValue("RTAntennaTarget"))
            {
                try
                {
                    Target = new Guid(node.GetValue("RTAntennaTarget"));
                }
                catch (FormatException)
                {
                    Target = Guid.Empty;
                }
            }
            // Have RTDishRadians as a fallback to avoid corrupting save games
            if (node.HasValue("RTDishRadians"))
            {
                double temp_double;
                RTDishCosAngle = Double.TryParse(node.GetValue("RTDishRadians"), out temp_double) ? temp_double : 1.0;
            }
            if (node.HasValue("DishAngle"))
            {
                RTDishCosAngle = Math.Cos(DishAngle / 2 * Math.PI / 180);
            }
            if (node.HasValue("DeployFxModules"))
            {
                mDeployFxModuleIndices = KSPUtil.ParseArray <Int32>(node.GetValue("DeployFxModules"), new ParserMethod <Int32>(Int32.Parse));
            }
            if (node.HasValue("ProgressFxModules"))
            {
                mProgressFxModuleIndices = KSPUtil.ParseArray <Int32>(node.GetValue("ProgressFxModules"), new ParserMethod <Int32>(Int32.Parse));
            }
            if (node.HasNode("TRANSMITTER"))
            {
                RTLog.Notify("ModuleRTAntenna: Found TRANSMITTER block.");
                mTransmitterConfig = node.GetNode("TRANSMITTER");
                mTransmitterConfig.AddValue("name", "ModuleRTDataTransmitter");

                // workarround for ksp 1.0
                if (mTransmitterConfig.HasValue("PacketInterval"))
                {
                    RTPacketInterval = float.Parse(mTransmitterConfig.GetValue("PacketInterval"));
                }

                if (mTransmitterConfig.HasValue("PacketSize"))
                {
                    RTPacketSize = float.Parse(mTransmitterConfig.GetValue("PacketSize"));
                }

                if (mTransmitterConfig.HasValue("PacketResourceCost"))
                {
                    RTPacketResourceCost = float.Parse(mTransmitterConfig.GetValue("PacketResourceCost"));
                }
            }
            if (this.resHandler.inputResources.Count == 0)
            {
                ModuleResource moduleResource = new ModuleResource();
                moduleResource.name  = this.resourceName;
                moduleResource.title = KSPUtil.PrintModuleName(this.resourceName);
                moduleResource.id    = this.resourceName.GetHashCode();
                moduleResource.rate  = EnergyCost * ConsumptionMultiplier;
                this.resHandler.inputResources.Add(moduleResource);
            }

            //apply the consumption multiplier
            this.resHandler.inputResources.Find(x => x.name == this.resourceName).rate = EnergyCost * ConsumptionMultiplier;
        }
示例#21
0
        private IEnumerator DelayedOnSaved(Game game)
        {
            var timer = new Stopwatch();

            timer.Start();

            print("KerbalGit: Entering OnSaved");

            yield return(new WaitForSeconds(1)); // It seems ksp needs time to finish saving

            print("KerbalGit: Finished waiting");

            try
            {
                if (latestCommit == DateTime.MinValue || (DateTime.Now - latestCommit) > TimeSpan.FromSeconds(wait))
                {
                    using (var repo = new Repository(savesDir))
                    {
                        var repoStatus = repo.Index.RetrieveStatus(new StatusOptions()
                        {
                            Show = StatusShowOption.WorkDirOnly
                        });

                        bool isStaged = false;
                        foreach (var entry in repoStatus)
                        {
                            if (entry.State == FileStatus.Modified || entry.State == FileStatus.Untracked || entry.State == FileStatus.Missing)
                            {
                                print("KerbalGit: Staging " + entry.FilePath);
                                repo.Index.Stage(entry.FilePath);
                                isStaged = true;
                            }
                        }

                        if (isStaged)
                        {
                            Signature author = new Signature(settings.GetValue("name"), settings.GetValue("email"), DateTime.Now);

                            var sb = new StringBuilder();

                            sb.AppendFormat("Game: {0}", game.Title);
                            sb.AppendFormat(", Time: {0}", KSPUtil.PrintDate((int)game.UniversalTime, true, true));
                            if (Funding.Instance != null)
                            {
                                sb.AppendFormat(", Funds: {0:N0}", (int)Funding.Instance.Funds);
                            }
                            if (ResearchAndDevelopment.Instance != null)
                            {
                                sb.AppendFormat(", Science: {0:N0}", (int)ResearchAndDevelopment.Instance.Science);
                            }
                            if (Reputation.Instance != null)
                            {
                                sb.AppendFormat(", Reputation: {0}%", (int)Reputation.Instance.reputation / 10);
                            }
                            if (FlightGlobals.ready && FlightGlobals.Vessels != null)
                            {
                                sb.AppendFormat(", Flights: {0}", FlightGlobals.Vessels.Count(v => v.vesselType != VesselType.Debris &&
                                                                                              v.vesselType != VesselType.SpaceObject && v.vesselType != VesselType.Unknown));
                            }
                            if (Contracts.ContractSystem.Instance != null)
                            {
                                sb.AppendFormat(", Contracts: {0}", Contracts.ContractSystem.Instance.GetActiveContractCount());
                            }

                            print("KerbalGit: Committing...");
                            Commit commit = repo.Commit(sb.ToString(), author);
                            latestCommit = DateTime.Now;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                print("KerbalGit: OnSaved exception: " + ex.Message);
            }
            finally
            {
                timer.Stop();
                print("KerbalGit: Exiting OnSaved after " + timer.Elapsed);
            }
        }
 public void Save(ConfigNode node)
 {
     node.SetValue("positive", KSPUtil.WriteVector(positive));
     node.SetValue("negative", KSPUtil.WriteVector(negative));
 }
示例#23
0
        public BuildListVessel(ShipConstruct s, string ls, double effCost, double bP, string flagURL)
        {
            _ship    = s;
            ShipNode = s.SaveShip();
            // Override KSP sizing of the ship construct
            ShipNode.SetValue("size", KSPUtil.WriteVector(Utilities.GetShipSize(s, true)));
            ShipName  = s.shipName;
            Cost      = Utilities.GetTotalVesselCost(ShipNode, true);
            EmptyCost = Utilities.GetTotalVesselCost(ShipNode, false);
            TotalMass = Utilities.GetShipMass(s, true, out EmptyMass, out _);

            HashSet <int> stages = new HashSet <int>();

            NumStageParts = 0;
            StagePartCost = 0d;

            foreach (Part p in s.Parts)
            {
                if (p.stagingOn)
                {
                    stages.Add(p.inverseStage);
                    ++NumStageParts;
                    StagePartCost += p.GetModuleCosts(p.partInfo.cost, ModifierStagingSituation.CURRENT) + p.partInfo.cost;
                }
            }
            NumStages = stages.Count;

            LaunchSite    = ls;
            EffectiveCost = effCost;
            BuildPoints   = bP;
            Progress      = 0;
            Flag          = flagURL;
            if (s.shipFacility == EditorFacility.VAB)
            {
                Type = ListType.VAB;
            }
            else if (s.shipFacility == EditorFacility.SPH)
            {
                Type = ListType.SPH;
            }
            else
            {
                Type = ListType.None;
            }
            Id = Guid.NewGuid();
            CannotEarnScience = false;

            //get the crew from the editorlogic
            DesiredManifest = new List <string>();
            if (CrewAssignmentDialog.Instance?.GetManifest()?.CrewCount > 0)
            {
                foreach (ProtoCrewMember crew in CrewAssignmentDialog.Instance.GetManifest().GetAllCrew(true) ?? new List <ProtoCrewMember>())
                {
                    DesiredManifest.Add(crew?.name ?? string.Empty);
                }
            }

            if (EffectiveCost == default)
            {
                // Can only happen in older saves that didn't have Effective cost persisted as a separate field
                // This code should be safe to remove after a while.
                EffectiveCost = Utilities.GetEffectiveCost(ShipNode.GetNodes("PART").ToList());
            }

            IntegrationPoints = MathParser.ParseIntegrationTimeFormula(this);
            IntegrationCost   = (float)MathParser.ParseIntegrationCostFormula(this);
        }
        public override void OnSave(ConfigNode node)
        {
            var rot = KSPUtil.WriteQuaternion(towerRot);

            node.AddValue("towerRot", rot);
        }
示例#25
0
        private List <UIListItem> CreateAtmosphericCharacteristics(CelestialBody currentBody, GenericCascadingList cascadingList)
        {
            GenericCascadingList genericCascadingList = cascadingList;
            Boolean atmosphere = currentBody.atmosphere && currentBody.atmospherePressureSeaLevel > 0;

            String     key      = Localizer.Format("#autoLOC_462448");
            String     template = atmosphere ? "#autoLOC_439855" : "#autoLOC_439856";
            UIListItem item     = genericCascadingList.CreateBody(key, "<color=#b8f4d1>" + Localizer.Format((string)template) + "</color>");

            List <UIListItem> list = new List <UIListItem>();

            list.Add(item);

            if (atmosphere)
            {
                item = cascadingList.CreateBody(Localizer.Format("#autoLOC_462453"), "<color=#b8f4d1>" + KSPUtil.LocalizeNumber(currentBody.atmosphereDepth, "N0") + " " + Localizer.Format("#autoLOC_7001411") + "</color>");
                list.Add(item);
                item = cascadingList.CreateBody(Localizer.Format("#autoLOC_462456"), "<color=#b8f4d1>" + KSPUtil.LocalizeNumber(currentBody.atmospherePressureSeaLevel / 101.324996948242, "0.#####") + " " + Localizer.Format("#autoLOC_7001419") + "</color>");
                list.Add(item);
                item = cascadingList.CreateBody(Localizer.Format("#autoLOC_462459"), "<color=#b8f4d1>" + KSPUtil.LocalizeNumber(currentBody.atmosphereTemperatureSeaLevel, "0.##") + " " + Localizer.Format("#autoLOC_7001406") + "</color>");
                list.Add(item);
            }

            return(list);
        }
示例#26
0
        private void DrawPrintProgress()
        {
            // Currently build item
            if (_processedItem != null)
            {
                if (_processedItem.Icon == null)
                {
                    _processedItem.EnableIcon(64);
                }
                GUI.Box(new Rect(190, 620, 50, 50), _processedItem.Icon.texture);
            }
            else
            {
                GUI.Box(new Rect(190, 620, 50, 50), "");
            }

            // Progressbar
            GUI.Box(new Rect(250, 620, 280, 50), "");
            if (progress >= 1)
            {
                var color = GUI.color;
                GUI.color = new Color(0, 1, 0, 1);
                GUI.Box(new Rect(250, 620, 280 * progress / 100, 50), "");
                GUI.color = color;
            }
            string progressText = string.Format("Progress: {0:n1}%, T- ", progress) + KSPUtil.PrintTime(_processedBlueprint.GetBuildTime(adjustedProductivity), 5, false);

            GUI.Label(new Rect(250, 620, 280, 50), " " + progressText);

            //Pause/resume production
            Texture2D buttonTexture = _pauseTexture;

            if (manufacturingPaused || _processedItem == null)
            {
                buttonTexture = _playTexture;
            }
            if (GUI.Button(new Rect(530, 620, 50, 50), buttonTexture) && _processedItem != null)
            {
                manufacturingPaused = !manufacturingPaused;
            }

            //Cancel production
            if (GUI.Button(new Rect(580, 620, 50, 50), _binTexture))
            {
                if (_confirmDelete)
                {
                    _processedItem.DisableIcon();
                    _processedItem      = null;
                    _processedBlueprint = null;
                    progress            = 0;
                    manufacturingPaused = false;
                    Status = "Online";

                    if (Animate && _heatAnimation != null && _workAnimation != null)
                    {
                        StartCoroutine(StopAnimations());
                    }
                    _confirmDelete = false;
                }

                else
                {
                    _confirmDelete = true;
                    ScreenMessages.PostScreenMessage("Click the cancel button again to confirm cancelling current production", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                }
            }
        }
示例#27
0
        /// <summary>
        /// Replaces the common tokens like "[year]" with their appropriate values as gathered from KSP
        /// </summary>
        /// <param name="sourceString">The source string to act on</param>
        /// <returns>The string post replacements</returns>
        public static string ReplaceStandardTokens(string sourceString)
        {
            string str = sourceString;

            bool counterFound = str.Contains("cnt");



            str = ReplaceToken(str, "UT", Planetarium.fetch != null ? Math.Round(Planetarium.GetUniversalTime()).ToString() : "0");
            //str = ReplaceToken(str, "save", HighLogic.SaveFolder != null && HighLogic.SaveFolder.Trim().Length > 0 ? HighLogic.SaveFolder : "NA");
            //str = ReplaceToken(str, "version", Versioning.GetVersionString());
            str = ReplaceToken(str, "vessel", HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null ? FlightGlobals.ActiveVessel.vesselName : "");
            str = ReplaceToken(str, "body", Planetarium.fetch != null ? Planetarium.fetch.CurrentMainBody.GetDisplayName() : "");
            str = ReplaceToken(str, "situation", HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null ? FlightGlobals.ActiveVessel.situation.ToString() : "");
            str = ReplaceToken(str, "biome", HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null ? ScienceUtil.GetExperimentBiome(FlightGlobals.ActiveVessel.mainBody, FlightGlobals.ActiveVessel.latitude, FlightGlobals.ActiveVessel.longitude) : "");


            int[] times = { 0, 0, 0, 0, 0 };
            if (Planetarium.fetch != null)
            {
                times = ConvertUT(Planetarium.GetUniversalTime());
            }
            if (!counterFound)
            {
                str = ReplaceToken(str, "year", times[0].ToString());
            }
            str = ReplaceToken(str, "year0", times[0].ToString("D3"));
            if (!counterFound)
            {
                str = ReplaceToken(str, "day", times[1].ToString());
            }
            str = ReplaceToken(str, "day0", times[1].ToString("D3"));
            if (!counterFound)
            {
                str = ReplaceToken(str, "hour", times[2].ToString());
            }
            str = ReplaceToken(str, "hour0", times[2].ToString("D2"));
            if (!counterFound)
            {
                str = ReplaceToken(str, "min", times[3].ToString());
            }
            str = ReplaceToken(str, "min0", times[3].ToString("D2"));
            if (!counterFound)
            {
                str = ReplaceToken(str, "sec", times[4].ToString());
            }
            str = ReplaceToken(str, "sec0", times[4].ToString("D2"));


            string time = KSPUtil.PrintTimeCompact(0, false);

            if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null)
            {
                time = KSPUtil.PrintTimeCompact((int)FlightGlobals.ActiveVessel.missionTime, false);
            }
            time = time.Replace(":", "-"); //Can't use colons in filenames on Windows, so we'll replace them with "-"

            str = ReplaceToken(str, "MET", time);

            if (str.Contains("cnt"))
            {
                int zeroes = 0;
                while (str.Contains("cnt" + Repeated('0', zeroes + 1)))
                {
                    zeroes++;
                }
                string token = "cnt" + Repeated('0', zeroes);

                string   searchstr = ReplaceToken(str, token, "*.sfs");
                int      beginning = str.IndexOf(token);
                string[] files     = Directory.GetFiles(SaveDir, searchstr);
                int      cnt       = files.Length;
                for (int i = 0; i < files.Length; i++)
                {
                    int    z          = zeroes;
                    string counterStr = files[i].Substring(SaveDir.Length + beginning);
                    if (zeroes == 0)
                    {
                        while (z < counterStr.Length && Char.IsDigit(counterStr[z]))
                        {
                            z++;
                        }
                    }
                    counterStr = counterStr.Substring(0, z);

                    int x = 0;
                    int.TryParse(counterStr, out x);
                    cnt = Math.Max(cnt, x);
                }
                str = ReplaceToken(str, token, (cnt + 1).ToString("D" + zeroes.ToString()));
            }
            return(str);
        }
示例#28
0
        protected void FixedUpdate()
        {
            int pC;

            if (HighLogic.LoadedSceneIsFlight && part.CrewCapacity > 0 && (pC = part.protoModuleCrew.Count) > 0)
            {
                double UT = KSPUtils.GetUT();
                if (nextCheck < 0d)
                {
                    nextCheck = UT + checkInterval;
                }
                else if (UT > nextCheck)
                {
                    if (pressureAtKillAltitude == default)
                    {
                        pressureAtKillAltitude = FlightGlobals.GetHomeBody().GetPressureAtm(crewDeathAltitude);
                        _origDoStockGCalcs     = ProtoCrewMember.doStockGCalcs;
                    }

                    nextCheck = UT + checkInterval;
                    if (part.staticPressureAtm < pressureAtKillAltitude)
                    {
                        ScreenMessages.PostScreenMessage($"Cockpit is above the safe altitude which will lead to crew incapacitation and eventually to death", 1f, ScreenMessageStyle.UPPER_CENTER, XKCDColors.Red);

                        if (!_origDoStockGCalcs.HasValue)
                        {
                            _origDoStockGCalcs = ProtoCrewMember.doStockGCalcs;
                        }
                        ProtoCrewMember.doStockGCalcs = false;

                        bool killed = false;
                        for (int i = pC; i-- > 0;)
                        {
                            ProtoCrewMember pcm = part.protoModuleCrew[i];

                            double highGPenalty = vessel.geeForce > 3 ? vessel.geeForce : 1;
                            pcm.gExperienced += (0.5d + rnd.NextDouble()) * gDamageAdder * highGPenalty;

                            double gMult = ProtoCrewMember.GToleranceMult(pcm) * HighLogic.CurrentGame.Parameters.CustomParams <GameParameters.AdvancedParams>().KerbalGToleranceMult;
                            _anyCrewAboveWarnThreshold = pcm.gExperienced > PhysicsGlobals.KerbalGThresholdWarn * gMult;

                            double locThreshold = PhysicsGlobals.KerbalGThresholdLOC * gMult;
                            if (!pcm.outDueToG && pcm.gExperienced > locThreshold)
                            {
                                // Just passed out
                                ScreenMessages.PostScreenMessage($"<color=red>{pcm.name} has lost consciousness due to hypoxia!</color>", 5.5f, ScreenMessageStyle.UPPER_CENTER);
                            }

                            // There's at least one cycle of delay after passing out before the death chance rolls start
                            if (pcm.outDueToG && rnd.NextDouble() < crewDeathChance)
                            {
                                killed = true;
                                ScreenMessages.PostScreenMessage($"{vessel.vesselName}: Crewmember {pcm.name} has died from exposure to near-vacuum.", 30.0f, ScreenMessageStyle.UPPER_CENTER, XKCDColors.Red);
                                FlightLogger.fetch.LogEvent($"[{KSPUtil.PrintTime(vessel.missionTime, 3, false)}] {pcm.name} died from exposure to near-vacuum.");
                                part.RemoveCrewmember(pcm);
                                pcm.Die();
                            }
                        }

                        if (killed && CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA)
                        {
                            CameraManager.Instance.SetCameraFlight();
                        }
                    }
                    else
                    {
                        if (_origDoStockGCalcs.HasValue)
                        {
                            ProtoCrewMember.doStockGCalcs = _origDoStockGCalcs.Value;
                            _origDoStockGCalcs            = null;
                        }
                    }
                }
            }
        }
示例#29
0
文件: CrewHandler.cs 项目: naet1/RP-0
        private void VesselRecoveryProcessing(ProtoVessel v, MissionRecoveryDialog mrDialog, float data)
        {
            Debug.Log("[VR] - Vessel recovery processing");

            List <string> retirementChanges = new List <string>();
            List <string> inactivity        = new List <string>();

            double UT = Planetarium.GetUniversalTime();

            // normally we would use v.missionTime, but that doesn't seem to update
            // when you're not actually controlling the vessel
            double elapsedTime = UT - v.launchTime;

            Debug.Log("[VR] mission elapsedTime: " + KSPUtil.PrintDateDeltaCompact(elapsedTime, true, true));

            // When flight duration was too short, mission training should not be set as expired.
            // This can happen when an on-the-pad failure occurs and the vessel is recovered.
            // We could perhaps override this if they're not actually in flight
            // (if the user didn't recover right from the pad I think this is a fair assumption)
            if (elapsedTime < settings.minFlightDurationSecondsForTrainingExpire)
            {
                Debug.Log("[VR] - mission time too short for crew to be inactive (elapsed time was " + elapsedTime + ", settings set for " + settings.minFlightDurationSecondsForTrainingExpire + ")");
                return;
            }

            foreach (ProtoCrewMember pcm in v.GetVesselCrew())
            {
                Debug.Log("[VR] - Found ProtoCrewMember: " + pcm.displayName);

                bool hasSpace       = false;
                bool hasOrbit       = false;
                bool hasEVA         = false;
                bool hasEVAOther    = false;
                bool hasOther       = false;
                bool hasOrbitOther  = false;
                bool hasLandOther   = false;
                int  curFlight      = pcm.careerLog.Last().flight;
                int  numFlightsDone = pcm.careerLog.Entries.Count(e => e.type == "Recover");
                foreach (FlightLog.Entry e in pcm.careerLog.Entries)
                {
                    if (e.type == "TRAINING_mission")
                    {
                        SetExpiration(pcm.name, e, Planetarium.GetUniversalTime());
                    }

                    if (e.flight != curFlight || e.type == "Nationality")
                    {
                        continue;
                    }

                    Debug.Log($"[VR]  processing flight entry: {e.type}; {e.target}");

                    bool isOther = false;
                    if (!string.IsNullOrEmpty(e.target) && e.target != Planetarium.fetch.Home.name)
                    {
                        Debug.Log($"[VR]    flight is beyond Earth");
                        isOther = hasOther = true;
                    }

                    if (!string.IsNullOrEmpty(e.type))
                    {
                        switch (e.type)
                        {
                        case "Suborbit":
                            hasSpace = true;
                            break;

                        case "Orbit":
                            if (isOther)
                            {
                                hasOrbitOther = true;
                            }
                            else
                            {
                                hasOrbit = true;
                            }
                            break;

                        case "ExitVessel":
                            if (isOther)
                            {
                                hasEVAOther = true;
                            }
                            else
                            {
                                hasEVA = true;
                            }
                            break;

                        case "Land":
                            if (isOther)
                            {
                                hasLandOther = true;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                }
                double multiplier = 1d;
                double constant   = 0.5d;
                if (hasSpace)
                {
                    multiplier += settings.recSpace.x;
                    constant   += settings.recSpace.y;
                    Debug.Log($"[VR]  has space, mult {settings.recSpace.x}; constant {settings.recSpace.y}");
                }
                if (hasOrbit)
                {
                    multiplier += settings.recOrbit.x;
                    constant   += settings.recOrbit.y;
                    Debug.Log($"[VR]  has orbit, mult {settings.recOrbit.x}; constant {settings.recOrbit.y}");
                }
                if (hasOther)
                {
                    multiplier += settings.recOtherBody.x;
                    constant   += settings.recOtherBody.y;
                    Debug.Log($"[VR]  has other body, mult {settings.recOtherBody.x}; constant {settings.recOtherBody.y}");
                }
                if (hasOrbit && hasEVA)    // EVA should only count while in orbit, not when walking on Earth
                {
                    multiplier += settings.recEVA.x;
                    constant   += settings.recEVA.y;
                    Debug.Log($"[VR]  has EVA, mult {settings.recEVA.x}; constant {settings.recEVA.y}");
                }
                if (hasEVAOther)
                {
                    multiplier += settings.recEVAOther.x;
                    constant   += settings.recEVAOther.y;
                    Debug.Log($"[VR]  has EVA at another body, mult {settings.recEVAOther.x}; constant {settings.recEVAOther.y}");
                }
                if (hasOrbitOther)
                {
                    multiplier += settings.recOrbitOther.x;
                    constant   += settings.recOrbitOther.y;
                    Debug.Log($"[VR]  has orbit around another body, mult {settings.recOrbitOther.x}; constant {settings.recOrbitOther.y}");
                }
                if (hasLandOther)
                {
                    multiplier += settings.recLandOther.x;
                    constant   += settings.recLandOther.y;
                    Debug.Log($"[VR]  has landed on another body, mult {settings.recLandOther.x}; constant {settings.recLandOther.y}");
                }

                Debug.Log("[VR]  multiplier: " + multiplier);
                Debug.Log("[VR]  AC multiplier: " + (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d));
                Debug.Log("[VR]  constant: " + constant);

                double retTime;
                if (kerbalRetireTimes.TryGetValue(pcm.name, out retTime))
                {
                    double offset = constant * 86400d * settings.retireOffsetBaseMult / (1 + Math.Pow(Math.Max(numFlightsDone + settings.retireOffsetFlightNumOffset, 0d), settings.retireOffsetFlightNumPow)
                                                                                         * UtilMath.Lerp(settings.retireOffsetStupidMin, settings.retireOffsetStupidMax, pcm.stupidity));

                    if (offset > 0d)
                    {
                        Debug.Log("[VR] retire date increased by: " + KSPUtil.PrintDateDeltaCompact(offset, true, false));
                        Debug.Log($"[VR]  constant: {constant}; curFlight: {numFlightsDone}; stupidity: {pcm.stupidity}");

                        retTime += offset;
                        kerbalRetireTimes[pcm.name] = retTime;
                        retirementChanges.Add("\n" + pcm.name + ", no earlier than " + KSPUtil.PrintDate(retTime, false));
                    }
                }

                multiplier /= (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d);

                double inactiveTime = elapsedTime * multiplier + constant * 86400d;
                Debug.Log("[VR] inactive for: " + KSPUtil.PrintDateDeltaCompact(inactiveTime, true, false));

                pcm.SetInactive(inactiveTime, false);
                inactivity.Add("\n" + pcm.name + ", until " + KSPUtil.PrintDate(inactiveTime + UT, true, false));
            }
            if (inactivity.Count > 0)
            {
                Debug.Log("[VR] - showing on leave message");

                string msgStr = "The following crew members will be on leave:";
                foreach (string s in inactivity)
                {
                    msgStr += s;
                }

                if (retirementEnabled && retirementChanges.Count > 0)
                {
                    msgStr += "\n\nThe following retirement changes have occurred:";
                    foreach (string s in retirementChanges)
                    {
                        msgStr += s;
                    }
                }

                PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                             new Vector2(0.5f, 0.5f),
                                             "CrewUpdateNotification",
                                             "Crew Updates",
                                             msgStr,
                                             "OK",
                                             true,
                                             HighLogic.UISkin);
            }
        }
示例#30
0
        public static bool setSite(ConfigNode KSC)
        {
            bool   hasChanged = false;
            double dtmp;
            float  ftmp;
            bool   btmp;

            ConfigNode pqsCity = KSC.GetNode("PQSCity");

            if (pqsCity == null)
            {
                return(false);
            }
            ConfigNode    pqsDecal = KSC.GetNode("PQSMod_MapDecalTangent");
            CelestialBody home     = getKSCBody();

            PQSCity ksc = findKSC(home);

            if (ksc != null)
            {
                if (pqsCity.HasValue("KEYname"))
                {
                    if (!(ksc.name.Equals(pqsCity.GetValue("KEYname"))))
                    {
                        Debug.Log("KSCSwitcher: Could not retrieve KSC to move, reporting failure and moving on.");
                        return(false);
                    }
                }
                if (pqsCity.HasValue("repositionRadial"))
                {
                    ksc.repositionRadial = KSPUtil.ParseVector3(pqsCity.GetValue("repositionRadial"));
                }
                if (pqsCity.HasValue("latitude") && pqsCity.HasValue("longitude"))
                {
                    double lat, lon;
                    double.TryParse(pqsCity.GetValue("latitude"), out lat);
                    double.TryParse(pqsCity.GetValue("longitude"), out lon);

                    ksc.repositionRadial = KSCSwitcher.LLAtoECEF(lat, lon, 0, home.Radius);
                }
                if (pqsCity.HasValue("reorientInitialUp"))
                {
                    ksc.reorientInitialUp = KSPUtil.ParseVector3(pqsCity.GetValue("reorientInitialUp"));
                }
                if (pqsCity.HasValue("repositionToSphere"))
                {
                    if (bool.TryParse(pqsCity.GetValue("repositionToSphere"), out btmp))
                    {
                        ksc.repositionToSphere = btmp;
                    }
                }
                if (pqsCity.HasValue("repositionToSphereSurface"))
                {
                    if (bool.TryParse(pqsCity.GetValue("repositionToSphereSurface"), out btmp))
                    {
                        ksc.repositionToSphereSurface = btmp;
                    }
                }
                if (pqsCity.HasValue("repositionToSphereSurfaceAddHeight"))
                {
                    if (bool.TryParse(pqsCity.GetValue("repositionToSphereSurfaceAddHeight"), out btmp))
                    {
                        ksc.repositionToSphereSurfaceAddHeight = btmp;
                    }
                }
                if (pqsCity.HasValue("reorientToSphere"))
                {
                    if (bool.TryParse(pqsCity.GetValue("reorientToSphere"), out btmp))
                    {
                        ksc.reorientToSphere = btmp;
                    }
                }
                if (pqsCity.HasValue("repositionRadiusOffset"))
                {
                    if (double.TryParse(pqsCity.GetValue("repositionRadiusOffset"), out dtmp))
                    {
                        ksc.repositionRadiusOffset = dtmp;
                    }
                }
                if (pqsCity.HasValue("lodvisibleRangeMult"))
                {
                    if (double.TryParse(pqsCity.GetValue("lodvisibleRangeMult"), out dtmp))
                    {
                        foreach (PQSCity.LODRange l in ksc.lod)
                        {
                            l.visibleRange *= (float)dtmp;
                        }
                    }
                }
                if (pqsCity.HasValue("reorientFinalAngle"))
                {
                    if (float.TryParse(pqsCity.GetValue("reorientFinalAngle"), out ftmp))
                    {
                        ksc.reorientFinalAngle = ftmp;
                    }
                }
                print("KSCSwitcher changed PQSCity");

                hasChanged = true;
                ksc.OnSetup();
                ksc.OnPostSetup();
                SpaceCenter.Instance.transform.localPosition = ksc.transform.localPosition;
                SpaceCenter.Instance.transform.localRotation = ksc.transform.localRotation;
            }
            else
            {
                Debug.LogError("KSCSwitcher: Could not retrieve KSC to move, reporting failure and moving on.");
                return(false);
            }

            PQSMod_MapDecalTangent decal = findKSCMapDecal(home);

            if (decal != null && pqsDecal != null)
            {
                // KSC Flat area
                if (pqsDecal.HasValue("position"))
                {
                    decal.position = KSPUtil.ParseVector3(pqsDecal.GetValue("position"));
                }
                if (pqsDecal.HasValue("radius"))
                {
                    if (double.TryParse(pqsDecal.GetValue("radius"), out dtmp))
                    {
                        decal.radius = dtmp;
                    }
                }
                if (pqsDecal.HasValue("heightMapDeformity"))
                {
                    if (double.TryParse(pqsDecal.GetValue("heightMapDeformity"), out dtmp))
                    {
                        decal.heightMapDeformity = dtmp;
                    }
                }
                if (pqsDecal.HasValue("absoluteOffset"))
                {
                    if (double.TryParse(pqsDecal.GetValue("absoluteOffset"), out dtmp))
                    {
                        decal.absoluteOffset = dtmp;
                    }
                }
                if (pqsDecal.HasValue("absolute"))
                {
                    if (bool.TryParse(pqsDecal.GetValue("absolute"), out btmp))
                    {
                        decal.absolute = btmp;
                    }
                }
                if (pqsDecal.HasValue("latitude") && pqsDecal.HasValue("longitude"))
                {
                    double lat, lon;
                    double.TryParse(pqsDecal.GetValue("latitude"), out lat);
                    double.TryParse(pqsDecal.GetValue("longitude"), out lon);

                    decal.position = KSCSwitcher.LLAtoECEF(lat, lon, 0, home.Radius);
                }
                print("KSCSwitcher changed MapDecal_Tangent");

                hasChanged = true;
                decal.OnSetup();
            }

            if (hasChanged)
            {
                SpaceCenter.Instance.Start();                  // 1.0.5
                if (KSC.HasValue("name"))
                {
                    KSCLoader.instance.Sites.lastSite = LastKSC.fetch.lastSite = KSC.GetValue("name");
                    print("KSCSwitcher changed MapDecal_Tangent");
                }
            }

            return(hasChanged);
        }