void Start()
        {
            for (int i = 0; i < FlightGlobals.Bodies?.Count; i++)
            {
                body = FlightGlobals.Bodies[i];

                Debug.Log("SigmaDimensions.Start", "> Planet: " + body.name + (body.name != body.displayName.Replace("^N", "") ? (", (A.K.A.: " + body.displayName.Replace("^N", "") + ")") : "") + (body.name != body.transform.name ? (", (A.K.A.: " + body.transform.name + ")") : ""));


                // Sigma Dimensions Settings
                resize          = body.Has("resize") ? body.Get <double>("resize") : 1;
                landscape       = body.Has("landscape") ? body.Get <double>("landscape") : 1;
                resizeBuildings = body.Has("resizeBuildings") ? body.Get <double>("resizeBuildings") : 1;


                // All PQSCity mods
                PQSCity[] cities = body.GetComponentsInChildren <PQSCity>(true);

                for (int j = 0; j < cities?.Length; j++)
                {
                    CityFixer(cities[j]);
                    cities[j].Orientate();
                }


                // All PQSCity2 mods
                PQSCity2[] cities2 = body.GetComponentsInChildren <PQSCity2>(true);

                for (int j = 0; j < cities2?.Length; j++)
                {
                    City2Fixer(cities2[j]);
                    cities2[j].Orientate();
                }
            }
        }
Example #2
0
        private static void ApplyOrbitVisibility(CelestialBody body)
        {
            if (HighLogic.LoadedScene != GameScenes.TRACKSTATION &&
                (!HighLogic.LoadedSceneIsFlight || !MapView.MapIsEnabled))
            {
                return;
            }

            // Loop
            // Check for Renderer
            if (!body.orbitDriver)
            {
                return;
            }
            if (!body.orbitDriver.Renderer)
            {
                return;
            }

            // Apply Orbit mode changes
            if (body.Has("drawMode"))
            {
                body.orbitDriver.Renderer.drawMode = body.Get <OrbitRenderer.DrawMode>("drawMode");
            }

            // Apply Orbit icon changes
            if (body.Has("drawIcons"))
            {
                body.orbitDriver.Renderer.drawIcons = body.Get <OrbitRenderer.DrawIcons>("drawIcons");
            }
        }
Example #3
0
            // Finalize an Orbit
            public static void FinalizeOrbit(CelestialBody body)
            {
                if (body.orbitDriver != null)
                {
                    if (body.referenceBody != null)
                    {
                        // Only recalculate the SOI, if it's not forced
                        if (!body.Has("hillSphere"))
                        {
                            body.hillSphere = body.orbit.semiMajorAxis * (1.0 - body.orbit.eccentricity) * Math.Pow(body.Mass / body.orbit.referenceBody.Mass, 1.0 / 3.0);
                        }

                        if (!body.Has("sphereOfInfluence"))
                        {
                            body.sphereOfInfluence = Math.Max(
                                body.orbit.semiMajorAxis * Math.Pow(body.Mass / body.orbit.referenceBody.Mass, 0.4),
                                Math.Max(body.Radius * Templates.SOIMinRadiusMult, body.Radius + Templates.SOIMinAltitude));
                        }

                        // this is unlike stock KSP, where only the reference body's mass is used.
                        body.orbit.period     = 2 * Math.PI * Math.Sqrt(Math.Pow(body.orbit.semiMajorAxis, 2) / 6.674E-11 * body.orbit.semiMajorAxis / (body.referenceBody.Mass + body.Mass));
                        body.orbit.meanMotion = 2 * Math.PI / body.orbit.period;    // in theory this should work but I haven't tested it

                        if (body.orbit.eccentricity <= 1.0)
                        {
                            body.orbit.meanAnomaly  = body.orbit.meanAnomalyAtEpoch;
                            body.orbit.orbitPercent = body.orbit.meanAnomalyAtEpoch / (Math.PI * 2);
                            body.orbit.ObTAtEpoch   = body.orbit.orbitPercent * body.orbit.period;
                        }
                        else
                        {
                            // ignores this body's own mass for this one...
                            body.orbit.meanAnomaly = body.orbit.meanAnomalyAtEpoch;
                            body.orbit.ObT         = Math.Pow(Math.Pow(Math.Abs(body.orbit.semiMajorAxis), 3.0) / body.orbit.referenceBody.gravParameter, 0.5) * body.orbit.meanAnomaly;
                            body.orbit.ObTAtEpoch  = body.orbit.ObT;
                        }
                    }
                    else
                    {
                        body.sphereOfInfluence = Double.PositiveInfinity;
                        body.hillSphere        = Double.PositiveInfinity;
                    }
                }
                try
                {
                    body.CBUpdate();
                }
                catch (Exception e)
                {
                    UnityEngine.Debug.Log("CBUpdate for " + body.name + " failed: " + e.Message);
                }
            }
Example #4
0
        public static void CelestialBodyUpdate(CelestialBody body)
        {
            //Instead of a harmony patch, you can do it in the TimingManager.FixedUpdateAdd(TimingManager.TimingStage.Precalc)
            //That would involve running trough all the celestial bodies with a loop tough...

            if (!body.Has("tilt"))
            {
                return;
            }

            var tilt = new Vector3(body.Get("tilt", 0f), 0, 0);

            if (body.inverseRotation)
            {
                //Basically we do the same as body.bodyTransform.transform.Rotate but with the planetarium
                //as we are rotating WITH the planet and in the same reference plane
                Planetarium.Rotation = ApplySpaceRotation(Planetarium.Rotation, tilt);
            }
            else
            {
                body.rotation = ApplySpaceRotation(body.rotation, tilt);
                body.bodyTransform.transform.rotation = body.rotation;

                //We must fix the bodyFrame vectors as otherwise landed vessels will not take the axial tilt on track station
                body.rotation.swizzle.FrameVectors(out body.BodyFrame.X, out body.BodyFrame.Y, out body.BodyFrame.Z);
            }
        }
Example #5
0
        // Fix the Zooming-Out bug
        void FixZooming()
        {
            if (HighLogic.LoadedSceneHasPlanetarium && MapView.fetch != null && !isDone)
            {
                // Fix the bug via switching away from Home and back immideatly.
                // TODO: Check if this still happend
                PlanetariumCamera.fetch.SetTarget(PlanetariumCamera.fetch.targets[(PlanetariumCamera.fetch.targets.IndexOf(PlanetariumCamera.fetch.target) + 1) % PlanetariumCamera.fetch.targets.Count]);
                PlanetariumCamera.fetch.SetTarget(PlanetariumCamera.fetch.targets[(PlanetariumCamera.fetch.targets.IndexOf(PlanetariumCamera.fetch.target) - 1) + (((PlanetariumCamera.fetch.targets.IndexOf(PlanetariumCamera.fetch.target) - 1) >= 0) ? 0 : PlanetariumCamera.fetch.targets.Count)]);

                // Terminate for the moment.
                isDone = true;
            }

            // Set custom Zoom-In limits
            if (HighLogic.LoadedScene == GameScenes.TRACKSTATION || MapView.MapIsEnabled)
            {
                MapObject target = PlanetariumCamera.fetch.target;
                if (target?.celestialBody != null)
                {
                    CelestialBody body = target.celestialBody;
                    if (body.Has("maxZoom"))
                    {
                        PlanetariumCamera.fetch.minDistance = body.Get <float>("maxZoom");
                    }
                    else
                    {
                        PlanetariumCamera.fetch.minDistance = 10;
                    }
                }
            }
        }
Example #6
0
 /// <summary>
 /// Returns a value or a default one if the element doesn't exist
 /// </summary>
 public static T Get <T>(this CelestialBody body, String id, T defaultValue)
 {
     if (body.Has(id))
     {
         return(body.Get <T>(id));
     }
     return(defaultValue);
 }
Example #7
0
        internal static float maxTempAngleOffset(this CelestialBody body)
        {
            if (body?.Has("maxTempAngleOffset") == true)
            {
                return(body.Get <float>("maxTempAngleOffset"));
            }

            return(45f);
        }
Example #8
0
        public static void CelestialBodyAwake(CelestialBody body)
        {
            if (!body.Has("tilt"))
            {
                return;
            }

            body.bodyTransform.transform.Rotate(new Vector3(body.Get("tilt", 0f), 0, 0), Space.World);
        }
Example #9
0
            /// <summary>
            /// This method gets called when the vessel enters the SOI of a new body. Here we edit the FX controller, so
            /// it uses the effects defined for this body.
            /// </summary>
            void OnDominantBodyChange(GameEvents.FromToAction <CelestialBody, CelestialBody> data)
            {
                // The body the vessel switched to
                CelestialBody body = data.to;

                if (body.Has("reentryHeat"))
                {
                    aeroFX.ReentryHeat = body.Get <AeroFXState>("reentryHeat");
                }
                else
                {
                    aeroFX.ReentryHeat = ReentryHeat;
                }

                if (body.Has("condensation"))
                {
                    aeroFX.Condensation = body.Get <AeroFXState>("condensation");
                }
                else
                {
                    aeroFX.Condensation = Condensation;
                }
            }
Example #10
0
        // Fix the Zooming-Out bug
        private void FixZooming()
        {
            if (HighLogic.LoadedSceneHasPlanetarium && MapView.fetch && !_fixZoomingIsDone)
            {
                // Fix the bug via switching away from Home and back immediately.
                // TODO: Check if this still happens
                PlanetariumCamera.fetch.SetTarget(PlanetariumCamera.fetch.targets[
                                                      (PlanetariumCamera.fetch.targets.IndexOf(PlanetariumCamera.fetch.target) + 1) %
                                                      PlanetariumCamera.fetch.targets.Count]);
                PlanetariumCamera.fetch.SetTarget(PlanetariumCamera.fetch.targets[
                                                      PlanetariumCamera.fetch.targets.IndexOf(PlanetariumCamera.fetch.target) - 1 +
                                                      (PlanetariumCamera.fetch.targets.IndexOf(PlanetariumCamera.fetch.target) - 1 >= 0
                        ? 0
                        : PlanetariumCamera.fetch.targets.Count)]);

                // Terminate for the moment.
                _fixZoomingIsDone = true;
            }

            // Set custom Zoom-In limits
            if (HighLogic.LoadedScene != GameScenes.TRACKSTATION && !MapView.MapIsEnabled)
            {
                return;
            }

            MapObject target = PlanetariumCamera.fetch.target;

            if (!target || !target.celestialBody)
            {
                return;
            }

            CelestialBody body = target.celestialBody;

            if (body.Has("maxZoom"))
            {
                PlanetariumCamera.fetch.minDistance = body.Get <Single>("maxZoom");
            }
            else
            {
                PlanetariumCamera.fetch.minDistance = 10;
            }
        }
Example #11
0
        // Contract Weight
        private static void PatchContractWeight(CelestialBody body)
        {
            if (ContractSystem.ContractWeights == null)
            {
                return;
            }

            if (!body.Has("contractWeight"))
            {
                return;
            }

            if (ContractSystem.ContractWeights.ContainsKey(body.name))
            {
                ContractSystem.ContractWeights[body.name] = body.Get <Int32>("contractWeight");
            }
            else
            {
                ContractSystem.ContractWeights.Add(body.name, body.Get <Int32>("contractWeight"));
            }
        }
Example #12
0
        void Start()
        {
            //  FIX BODIES MOVED POSTSPAWN  //
            Boolean postSpawnChanges = false;

            // Replaced 'foreach' with 'for' to improve performance
            CelestialBody[] postSpawnBodies = PSystemManager.Instance?.localBodies?.Where(b => b.Has("orbitPatches"))?.ToArray();

            for (Int32 i = 0; i < postSpawnBodies?.Length; i++)
            {
                CelestialBody cb = postSpawnBodies[i];

                // Fix position if the body gets moved PostSpawn
                ConfigNode patch = cb.Get <ConfigNode>("orbitPatches");
                if (patch.GetValue("referenceBody") != null || patch.GetValue("semiMajorAxis") != null)
                {
                    // Get the body
                    PSystemBody body = PSystemManager.Instance?.systemPrefab?.GetComponentsInChildren <PSystemBody>(true)?.FirstOrDefault(b => b.name == cb.transform.name);
                    if (body == null)
                    {
                        Debug.Log("[Kopernicus]: RnDFixer: Could not find PSystemBody => " + cb.transform.name);
                        continue;
                    }

                    // Get the parent
                    PSystemBody oldParent = PSystemManager.Instance?.systemPrefab?.GetComponentsInChildren <PSystemBody>(true)?.FirstOrDefault(b => b.children.Contains(body));
                    if (oldParent == null)
                    {
                        Debug.Log("[Kopernicus]: RnDFixer: Could not find referenceBody of CelestialBody => " + cb.transform.name);
                        continue;
                    }

                    // Check if PostSpawnOrbit changes referenceBody
                    PSystemBody newParent = oldParent;
                    if (patch.GetValue("referenceBody") != null)
                    {
                        newParent = PSystemManager.Instance?.systemPrefab?.GetComponentsInChildren <PSystemBody>(true).FirstOrDefault(b => b.name == patch.GetValue("referenceBody"));
                    }
                    if (oldParent == null)
                    {
                        Debug.Log("[Kopernicus]: RnDFixer: Could not find PostSpawn referenceBody of CelestialBody => " + cb.transform.name);
                        newParent = oldParent;
                    }

                    // Check if PostSpawnOrbit changes semiMajorAxis
                    if (body?.orbitDriver?.orbit?.semiMajorAxis == null)
                    {
                        Debug.Log("[Kopernicus]: RnDFixer: Could not find PostSpawn semiMajorAxis of CelestialBody => " + cb.transform.name);
                        continue;
                    }
                    NumericParser <Double> newSMA = body.orbitDriver.orbit.semiMajorAxis;
                    if (patch.GetValue("semiMajorAxis") != null)
                    {
                        newSMA.SetFromString(patch.GetValue("semiMajorAxis"));
                    }

                    // Remove the body from oldParent.children
                    oldParent.children.Remove(body);

                    // Find the index of the body in newParent.children
                    Int32 index = newParent.children.FindAll(c => c.orbitDriver.orbit.semiMajorAxis < newSMA.Value).Count;

                    // Add the body to newParent.children
                    if (index > newParent.children.Count)
                    {
                        newParent.children.Add(body);
                    }
                    else
                    {
                        newParent.children.Insert(index, body);
                    }

                    // Signal that the system has PostSpawn changes
                    postSpawnChanges = true;
                }
            }

            // Rebuild Archives
            if (postSpawnChanges)
            {
                AddPlanets();
            }



            //  RDVisibility = HIDDEN  //  RDVisibility = SKIP  //

            // Create a list with body to hide and their parent
            List <KeyValuePair <PSystemBody, KeyValuePair <PSystemBody, Int32> > > hideList = new List <KeyValuePair <PSystemBody, KeyValuePair <PSystemBody, Int32> > >();
            // Create a list with body to skip and their parent
            List <KeyValuePair <PSystemBody, PSystemBody> > skipList = new List <KeyValuePair <PSystemBody, PSystemBody> >();

            // Replaced 'foreach' with 'for' to improve performance
            PSystemBody[]   bodies     = PSystemManager.Instance.systemPrefab.GetComponentsInChildren <PSystemBody>(true);
            CelestialBody[] hideBodies = PSystemManager.Instance?.localBodies?.Where(cb => cb.Has("hiddenRnD"))?.ToArray();

            for (Int32 i = 0; i < hideBodies?.Length; i++)
            {
                CelestialBody body = hideBodies[i];
                PropertiesLoader.RDVisibility visibility = body.Get <PropertiesLoader.RDVisibility>("hiddenRnD");

                if (visibility == PropertiesLoader.RDVisibility.HIDDEN || visibility == PropertiesLoader.RDVisibility.SKIP)
                {
                    PSystemBody hidden = Utility.FindBody(PSystemManager.Instance.systemPrefab.rootBody, body.transform.name);
                    PSystemBody parent = bodies.FirstOrDefault(b => b.children.Contains(hidden));
                    if (parent != null)
                    {
                        // Hide
                        if (hidden.children.Count == 0 || visibility == PropertiesLoader.RDVisibility.HIDDEN)
                        {
                            body.Set("hiddenRnd", PropertiesLoader.RDVisibility.HIDDEN);
                            hideList.Add(new KeyValuePair <PSystemBody, KeyValuePair <PSystemBody, Int32> >(hidden, new KeyValuePair <PSystemBody, Int32>(parent, 0)));
                        }
                        // Skip
                        else
                        {
                            if (skipList.Any(b => b.Key == parent))
                            {
                                Int32 index = skipList.IndexOf(skipList.FirstOrDefault(b => b.Key == parent));
                                skipList.Insert(index, new KeyValuePair <PSystemBody, PSystemBody>(hidden, parent));
                            }
                            else
                            {
                                skipList.Add(new KeyValuePair <PSystemBody, PSystemBody>(hidden, parent));
                            }
                        }
                    }
                }
            }

            // Skip bodies
            for (Int32 i = 0; i < skipList.Count; i++)
            {
                KeyValuePair <PSystemBody, PSystemBody> pair = skipList[i];

                // Get hidden body and parent
                PSystemBody hidden = pair.Key;
                PSystemBody parent = pair.Value;

                // Find where the hidden body is
                Int32 index = parent.children.IndexOf(hidden);

                // Remove the hidden body from its parent's children list so it won't show up when clicking the parent
                parent.children.Remove(hidden);

                // Put its children in its place
                parent.children.InsertRange(index, hidden.children);
            }

            // Hide bodies
            for (Int32 i = 0; i < hideList.Count; i++)
            {
                KeyValuePair <PSystemBody, KeyValuePair <PSystemBody, Int32> > pair = hideList[i];

                // Get hidden body and parent
                PSystemBody hidden = pair.Key;
                PSystemBody parent = bodies.FirstOrDefault(b => b.children.Contains(hidden));

                // Find where the hidden body is
                Int32 index = parent.children.IndexOf(hidden);

                // Remove the hidden body from its parent's children list so it won't show up when clicking the parent
                parent.children.Remove(hidden);

                // Save the position in the hideList
                hideList[i] = new KeyValuePair <PSystemBody, KeyValuePair <PSystemBody, Int32> >(hidden, new KeyValuePair <PSystemBody, Int32>(parent, index));
            }

            // Apply changes and revert to the original PSystem
            if (hideList.Count > 0 || skipList?.Count > 0)
            {
                // Rebuild Archives
                AddPlanets();

                // Undo the changes to the PSystem (hide)
                for (Int32 i = hideList.Count - 1; i > -1; i--)
                {
                    PSystemBody hidden   = hideList[i].Key;
                    PSystemBody parent   = hideList[i].Value.Key;
                    Int32       oldIndex = hideList[i].Value.Value;
                    parent.children.Insert(oldIndex, hidden);
                }
                // Undo the changes to the PSystem (skip)
                for (Int32 i = skipList.Count - 1; i > -1; i--)
                {
                    PSystemBody hidden   = skipList[i].Key;
                    PSystemBody parent   = skipList[i].Value;
                    Int32       oldIndex = parent.children.IndexOf(hidden.children.FirstOrDefault());
                    parent.children.Insert(oldIndex, hidden);

                    for (Int32 j = 0; j < hidden.children.Count; j++)
                    {
                        PSystemBody child = hidden.children[j];

                        if (parent.children.Contains(child))
                        {
                            parent.children.Remove(child);
                        }
                    }
                }
            }



            //  RDVisibility = NOICON  //  Kill Rotation //
            // Loop through the Containers
            RDPlanetListItemContainer[] containers = Resources.FindObjectsOfTypeAll <RDPlanetListItemContainer>().Where(i => i.label_planetName.text != "Planet name").ToArray();
            for (Int32 i = 0; i < containers?.Count(); i++)
            {
                RDPlanetListItemContainer planetItem = containers[i];

                // The label text is set from the CelestialBody's displayName
                CelestialBody body = PSystemManager.Instance?.localBodies?.FirstOrDefault(cb => cb.transform.name == planetItem.name);
                if (body == null)
                {
                    Debug.Log("[Kopernicus]: RnDFixer: Could not find CelestialBody for the label => " + planetItem.name);
                    continue;
                }

                // Barycenter
                if (body.Has("barycenter") || !body.Get("selectable", true))
                {
                    planetItem.planet.SetActive(false);
                    planetItem.label_planetName.alignment = TextAlignmentOptions.MidlineLeft;
                }

                // RD Visibility
                if (body.Has("hiddenRnD"))
                {
                    PropertiesLoader.RDVisibility visibility = body.Get <PropertiesLoader.RDVisibility>("hiddenRnD");
                    if (visibility == PropertiesLoader.RDVisibility.NOICON)
                    {
                        planetItem.planet.SetActive(false);
                        planetItem.label_planetName.alignment = TextAlignmentOptions.MidlineLeft;
                    }
                    else
                    {
                        planetItem.planet.SetActive(true);
                        planetItem.label_planetName.alignment = TextAlignmentOptions.MidlineRight;
                    }
                }

                // Add planetItems to 'RnDRotationKill'
                if (planetItem?.planet?.transform?.rotation == null)
                {
                    continue;
                }
                if (body.Has("RnDRotation") ? !body.Get <Boolean>("RnDRotation") : body?.scaledBody?.GetComponentInChildren <SunCoronas>(true) != null)
                {
                    RnDRotationKill.Add(planetItem);
                }
            }
        }
Example #13
0
        // Stuff
        void LateUpdate()
        {
            FixZooming();
            ApplyOrbitVisibility();
            RDFixer();

            // Remove buttons in map view for barycenters
            if (MapView.MapIsEnabled)
            {
                if (fields == null)
                {
                    FieldInfo mode_f    = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType.IsEnum && f.FieldType.IsNested);
                    FieldInfo context_f = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType == typeof(MapContextMenu));
                    FieldInfo cast_f    = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType == typeof(OrbitRenderer.OrbitCastHit));
                    fields = new FieldInfo[] { mode_f, context_f, cast_f };
                }
                if (FlightGlobals.ActiveVessel != null)
                {
                    OrbitTargeter targeter = FlightGlobals.ActiveVessel.orbitTargeter;
                    if (targeter == null)
                    {
                        return;
                    }
                    Int32 mode = (Int32)fields[0].GetValue(targeter);
                    if (mode == 2)
                    {
                        OrbitRenderer.OrbitCastHit cast = (OrbitRenderer.OrbitCastHit)fields[2].GetValue(targeter);
                        CelestialBody body = PSystemManager.Instance.localBodies.Find(b => b.name == cast.or?.discoveryInfo?.name?.Value);
                        if (body == null)
                        {
                            return;
                        }
                        if (body.Has("barycenter") || body.Has("notSelectable"))
                        {
                            if (cast.driver?.Targetable == null)
                            {
                                return;
                            }
                            MapContextMenu context = MapContextMenu.Create(body.name, new Rect(0.5f, 0.5f, 300f, 50f), cast, () =>
                            {
                                fields[0].SetValue(targeter, 0);
                                fields[1].SetValue(targeter, null);
                            }, new SetAsTarget(cast.driver.Targetable, () => FlightGlobals.fetch.VesselTarget));
                            fields[1].SetValue(targeter, context);
                        }
                    }
                }
            }


            foreach (CelestialBody body in PSystemManager.Instance.localBodies)
            {
                if (body.afg == null)
                {
                    continue;
                }
                GameObject star_      = KopernicusStar.GetNearest(body).gameObject;
                Vector3    planet2cam = body.scaledBody.transform.position - body.afg.mainCamera.transform.position;
                body.afg.lightDot = Mathf.Clamp01(Vector3.Dot(planet2cam, body.afg.mainCamera.transform.position - star_.transform.position) * body.afg.dawnFactor);
                body.afg.GetComponent <Renderer>().material.SetFloat("_lightDot", body.afg.lightDot);
            }
        }
Example #14
0
        void ProcessBinaries(Loader ldr, ConfigNode cfgn)
        {
            if (ListOfBinaries?.Count > 0)
            {
                Debug.Log("SigmaBinary.ProcessBinaries", "Starting the set up of " + ListOfBinaries?.Count + " binary systems");
            }

            while (ListOfBinaries?.Count > 0)
            {
                /// Loading the Bodies

                Body sbSecondary = ListOfBinaries.First().Value;
                Debug.Log("SigmaBinary.ProcessBinaries", "sbSecondary = " + sbSecondary?.Name);
                Body sbPrimary = OrbitPatcher(sbSecondary);
                Debug.Log("SigmaBinary.ProcessBinaries", "sbPrimary = " + sbPrimary?.Name);
                Body sbBarycenter = ListOfBodies.Find(b0 => b0.GeneratedBody.name == sigmabinarySBName[sbSecondary]);
                Debug.Log("SigmaBinary.ProcessBinaries", "sbBarycenter = " + sbBarycenter?.Name);
                Body sbReference = OrbitPatcher(sbPrimary);
                Debug.Log("SigmaBinary.ProcessBinaries", "sbReference = " + sbReference?.Name);
                Body sbOrbit = ListOfBodies.Find(ob => ob.GeneratedBody.name == sigmabinarySBName[sbSecondary] + "Orbit" && sigmabinaryRedrawOrbit.Contains(sbSecondary));
                Debug.Log("SigmaBinary.ProcessBinaries", "sbOrbit = " + sbOrbit?.Name);

                Debug.Log("SigmaBinary.ProcessBinaries", "Loaded Bodies\nReferenceBody: " + sbReference?.GeneratedBody?.name + "\n   Barycenter: " + sbBarycenter?.GeneratedBody?.name + "\n      Primary: " + sbPrimary?.GeneratedBody?.name + "\n    Secondary: " + sbSecondary?.GeneratedBody?.name + "\n        Orbit: " + sbOrbit?.GeneratedBody?.name);
                Debug.Log("SigmaBinary.ProcessBinaries", "Loaded PSystemBodies\nReferenceBody: " + sbReference?.GeneratedBody?.name + "\n   Barycenter: " + sbBarycenter?.GeneratedBody?.name + "\n      Primary: " + sbPrimary?.GeneratedBody?.name + "\n    Secondary: " + sbSecondary?.GeneratedBody?.name + "\n        Orbit: " + sbOrbit?.GeneratedBody?.name);
                // Check that the bodies exist

                if (sbPrimary == null || sbBarycenter == null || sbReference == null)
                {
                    break;
                }
                if (sbOrbit == null && sigmabinaryRedrawOrbit.Contains(sbSecondary))
                {
                    break;
                }


                // Load the CelestialBodies

                CelestialBody cbSecondary  = sbSecondary?.GeneratedBody?.celestialBody;
                CelestialBody cbPrimary    = sbPrimary?.GeneratedBody?.celestialBody;
                CelestialBody cbBarycenter = sbBarycenter?.GeneratedBody?.celestialBody;
                CelestialBody cbReference  = sbReference?.GeneratedBody?.celestialBody;

                Debug.Log("SigmaBinary.ProcessBinaries", "Loaded CelestialBodies\nReferenceBody: " + cbReference + "\n   Barycenter: " + cbBarycenter + "\n      Primary: " + cbPrimary + "\n    Secondary: " + cbSecondary + "\n        Orbit: " + sbOrbit?.GeneratedBody?.celestialBody);



                /// Generating Binary System

                // Fix sphereOfInfluence where needed
                if (cbPrimary.Has("SBfixSOI"))
                {
                    cbPrimary.sphereOfInfluence = sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis * Math.Pow(cbPrimary.GetMass() / cbReference.GetMass(), 0.4);
                    cbPrimary.Remove("SBfixSOI");
                    Debug.Log("SigmaBinary.ProcessBinaries", "Fixed 'sphereOfInfluence' of primary " + sbPrimary.GeneratedBody.name + ". sphereOfInfluence = " + cbPrimary.sphereOfInfluence);
                }
                if (cbSecondary.Has("SBfixSOI"))
                {
                    cbSecondary.sphereOfInfluence = sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis * Math.Pow(cbSecondary.GetMass() / cbPrimary.GetMass(), 0.4);
                    cbSecondary.Remove("SBfixSOI");
                    Debug.Log("SigmaBinary.ProcessBinaries", "Fixed 'sphereOfInfluence' of secondary " + sbSecondary.GeneratedBody.name + ". sphereOfInfluence = " + cbSecondary.sphereOfInfluence);
                }


                // Remove Finalize Orbit

                if (cbSecondary.Has("finalizeBody") && cbSecondary.Get <bool>("finalizeBody"))
                {
                    cbSecondary.Set("finalizeBody", false);
                    Debug.Log("SigmaBinary.ProcessBinaries", "'finalizeBody' turned off for secondary body " + sbSecondary.GeneratedBody.name);
                    // Fix sphereOfInfluence
                    if (!cbSecondary.Has("sphereOfInfluence"))
                    {
                        cbSecondary.Set("sphereOfInfluence", Math.Max(sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis * Math.Pow(cbSecondary.GetMass() / cbPrimary.GetMass(), 0.4), Math.Max(cbSecondary.Radius * Templates.SOI_MIN_RADIUS_MULTIPLIER, cbSecondary.Radius + Templates.SOI_MIN_ALTITUDE)));
                        Debug.Log("SigmaBinary.ProcessBinaries", "recalculated 'sphereOfInfluence' for secondary body " + sbSecondary.GeneratedBody.name);
                    }
                }
                if (cbPrimary.Has("finalizeBody") && cbPrimary.Get <bool>("finalizeBody"))
                {
                    cbPrimary.Set("finalizeBody", false);
                    Debug.Log("SigmaBinary.ProcessBinaries", "'finalizeBody' turned off for primary body " + sbPrimary.GeneratedBody.name);
                    // Fix sphereOfInfluence
                    if (!cbPrimary.Has("sphereOfInfluence"))
                    {
                        cbPrimary.Set("sphereOfInfluence", Math.Max(sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis * Math.Pow(cbPrimary.GetMass() / cbReference.GetMass(), 0.4), Math.Max(cbPrimary.Radius * Templates.SOI_MIN_RADIUS_MULTIPLIER, cbPrimary.Radius + Templates.SOI_MIN_ALTITUDE)));
                        Debug.Log("SigmaBinary.ProcessBinaries", "recalculated 'sphereOfInfluence' for primary body " + sbPrimary.GeneratedBody.name);
                    }
                }



                /// Set Barycenter

                sbBarycenter.GeneratedBody.orbitDriver.orbit = new Orbit(sbPrimary.GeneratedBody.orbitDriver.orbit);
                sbBarycenter.Orbit.ReferenceBody             = sbPrimary.Orbit.ReferenceBody;
                cbBarycenter.GeeASL         = (cbPrimary.GetMass() + cbSecondary.GetMass()) / 1e5 * 6.674e-11d / Math.Pow(cbBarycenter.Radius, 2) / 9.80665d;
                cbBarycenter.rotationPeriod = 0;
                Debug.Log("SigmaBinary.SetBarycenter", "Printing orbital parameters of primary " + sbPrimary.GeneratedBody.name + " for reference.");
                Debug.Log("SigmaBinary.SetBarycenter", "referenceBody = " + sbPrimary.Orbit.ReferenceBody + ", semiMajorAxis = " + sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis + ", period = " + sbPrimary.GetOrbitalPeriod(cbReference));
                Debug.Log("SigmaBinary.SetBarycenter", "Calculated new orbital parameters for barycenter " + sbBarycenter.GeneratedBody.name);
                Debug.Log("SigmaBinary.SetBarycenter", "referenceBody = " + sbBarycenter.Orbit.ReferenceBody + ", semiMajorAxis = " + sbBarycenter.GeneratedBody.orbitDriver.orbit.semiMajorAxis);

                sbBarycenter.GeneratedBody.celestialBody.Set("customOrbitalPeriod", sbPrimary.GetOrbitalPeriod(cbReference));
                Debug.Log("SigmaBinary.SetBarycenter", "Changed orbital period of barycenter " + sbBarycenter?.GeneratedBody?.name + ", new orbital period = " + sbBarycenter.GetOrbitalPeriod());

                // Orbit Color
                if (sigmabinaryOrbitColor.ContainsKey(sbSecondary))
                {
                    sbBarycenter.GeneratedBody.orbitRenderer.SetColor(sigmabinaryOrbitColor[sbSecondary]);
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " orbit line color set from list. color = " + sigmabinaryOrbitColor[sbSecondary]);
                }
                else
                {
                    sbBarycenter.GeneratedBody.orbitRenderer.orbitColor = sbPrimary.GeneratedBody.orbitRenderer.orbitColor;
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " orbit line color copied from primary " + sbPrimary.GeneratedBody.name + ". color = " + sbPrimary.GeneratedBody.orbitRenderer.orbitColor);
                }

                // Icon Color
                if (sigmabinaryIconColor.ContainsKey(sbSecondary))
                {
                    sbBarycenter.GeneratedBody.orbitRenderer.nodeColor = sigmabinaryIconColor[sbSecondary];
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " orbit icon color set from list. color = " + sigmabinaryIconColor[sbSecondary]);
                }
                else if (!sigmabinaryOrbitColor.ContainsKey(sbSecondary))
                {
                    sbBarycenter.GeneratedBody.orbitRenderer.nodeColor = sbPrimary.GeneratedBody.orbitRenderer.nodeColor;
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " orbit icon color copied from primary " + sbPrimary.GeneratedBody.name + ". color = " + sbPrimary.GeneratedBody.orbitRenderer.nodeColor);
                }

                // Description
                if (sigmabinaryDescription.ContainsKey(sbSecondary))
                {
                    cbBarycenter.bodyDescription = sigmabinaryDescription[sbSecondary].Replace("<name>", nameof(sbBarycenter)).Replace("<primary>", nameof(sbPrimary)).Replace("<secondary>", nameof(sbSecondary));
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " description loaded.");
                }
                Debug.Log("SigmaBinary.SetBarycenter", "description = " + cbBarycenter.bodyDescription);

                // DrawMode and DrawIcons
                if (sigmabinaryMode.ContainsKey(sbSecondary))
                {
                    cbBarycenter.Set("drawMode", sigmabinaryMode[sbSecondary]);
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " custom orbit 'drawMode' loaded. drawMode = " + sigmabinaryMode[sbSecondary].Value);
                }
                else if (cbPrimary.Has("drawMode"))
                {
                    cbBarycenter.Set("drawMode", cbPrimary.Get <DrawMode>("drawMode"));
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " orbit 'drawMode' copied from primary " + sbPrimary.GeneratedBody.name + ". drawMode = " + cbPrimary.Get <DrawMode>("drawMode"));
                    cbPrimary.Set("drawMode", DrawMode.REDRAW_AND_RECALCULATE);
                    Debug.Log("SigmaBinary.SetBarycenter", "Primary " + sbPrimary.GeneratedBody.name + " orbit 'drawMode' automatically set. drawMode = " + DrawMode.REDRAW_AND_RECALCULATE);
                }
                if (sigmabinaryIcon.ContainsKey(sbSecondary))
                {
                    cbPrimary.Set("drawIcons", sigmabinaryIcon[sbSecondary]);
                    Debug.Log("SigmaBinary.SetBarycenter", "Primary " + sbPrimary.GeneratedBody.name + " custom orbit 'drawIcons' loaded. drawIcons = " + sigmabinaryIcon[sbSecondary].Value);
                }
                else if (cbPrimary.Has("drawIcons"))
                {
                    cbBarycenter.Set("drawIcons", cbPrimary.Get <DrawIcons>("drawIcons"));
                    Debug.Log("SigmaBinary.SetBarycenter", "Barycenter " + sbBarycenter.GeneratedBody.name + " orbit 'drawIcons' copied from primary " + sbPrimary.GeneratedBody.name + ". drawIcons = " + cbPrimary.Get <DrawIcons>("drawIcons"));
                    cbPrimary.Set("drawIcons", DrawIcons.ALL);
                    Debug.Log("SigmaBinary.SetBarycenter", "Primary " + sbPrimary.GeneratedBody.name + " orbit 'drawIcons' automatically set. drawIcons = " + DrawIcons.ALL);
                }



                /// Set Primary

                if (sbPrimary.Template.OriginalBody.celestialBody.name == "Kerbin")
                {
                    Debug.Log("SigmaBinary.SetPrimary", "Primary " + sbPrimary.GeneratedBody.name + " uses Kerbin as Template.");
                    if (!kerbinFixer.ContainsKey(sbPrimary.GeneratedBody.name))
                    {
                        kerbinFixer.Add(sbPrimary.GeneratedBody.name, sbReference.GeneratedBody.name);
                        Debug.Log("SigmaBinary.SetPrimary", "Stored patched 'referenceBody' " + cbReference + " of Primary " + sbPrimary.GeneratedBody.name + " in 'kerbinFixer'.");
                    }
                    if (!archivesFixerList.ContainsKey(sbPrimary.GeneratedBody))
                    {
                        archivesFixerList.Add(sbPrimary.GeneratedBody, sbBarycenter.GeneratedBody);
                        Debug.Log("SigmaBinary.SetPrimary", "Stored primary " + sbPrimary.GeneratedBody.name + " and barycenter " + sbBarycenter.GeneratedBody.name + " in 'archivesFixerList'.");
                    }
                }
                sbPrimary.GeneratedBody.orbitDriver.orbit =
                    new Orbit
                    (
                        sbSecondary.GeneratedBody.orbitDriver.orbit.inclination,
                        sbSecondary.GeneratedBody.orbitDriver.orbit.eccentricity,
                        sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis * cbSecondary.GetMass() / (cbSecondary.GetMass() + cbPrimary.GetMass()),
                        sbSecondary.GeneratedBody.orbitDriver.orbit.LAN,
                        sbSecondary.GeneratedBody.orbitDriver.orbit.argumentOfPeriapsis + 180d,
                        sbSecondary.GeneratedBody.orbitDriver.orbit.meanAnomalyAtEpoch,
                        sbSecondary.GeneratedBody.orbitDriver.orbit.epoch,
                        cbBarycenter
                    );
                sbPrimary.Orbit.ReferenceBody = sbBarycenter.GeneratedBody.name;
                Debug.Log("SigmaBinary.SetPrimary", "Printing masses of bodies for reference. primary = " + cbPrimary.GetMass() + ", secondary = " + cbSecondary.GetMass() + ", ratio = " + (cbPrimary.GetMass() / cbSecondary.GetMass()));
                Debug.Log("SigmaBinary.SetPrimary", "Printing orbital parameters of secondary " + sbSecondary.GeneratedBody.name + " for reference.");
                Debug.Log("SigmaBinary.SetPrimary", "referenceBody = " + sbSecondary.Orbit.ReferenceBody + ", semiMajorAxis = " + sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis);
                Debug.Log("SigmaBinary.SetPrimary", "Calculated new orbital parameters for primary " + sbPrimary.GeneratedBody.name);
                Debug.Log("SigmaBinary.SetPrimary", "referenceBody = " + sbPrimary.Orbit.ReferenceBody + ", semiMajorAxis = " + sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis + ", ratio = " + (sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis / sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis));

                sbPrimary.GeneratedBody.celestialBody.Set("customOrbitalPeriod", sbSecondary.GetOrbitalPeriod(cbPrimary));
                Debug.Log("SigmaBinary.SetPrimary", "New Orbital Period for Primary " + sbPrimary.GeneratedBody.name + " = " + sbPrimary.GetOrbitalPeriod());

                // Primary Locked
                if (cbPrimary.solarRotationPeriod)
                {
                    cbPrimary.solarRotationPeriod = false;
                    cbPrimary.rotationPeriod      = (sbBarycenter.GetOrbitalPeriod() * cbPrimary.rotationPeriod) / (sbBarycenter.GetOrbitalPeriod() + cbPrimary.rotationPeriod);
                    Debug.Log("SigmaBinary.SetPrimary", "Primary " + sbPrimary.GeneratedBody.name + " 'solarRotationPeriod' set to 'false'. recalculated rotation period = " + cbPrimary.rotationPeriod);
                }
                if (sigmabinaryPrimaryLocked.Contains(sbSecondary))
                {
                    cbPrimary.solarRotationPeriod = false;
                    cbPrimary.rotationPeriod      = sbPrimary.GetOrbitalPeriod();
                    Debug.Log("SigmaBinary.SetPrimary", "Primary " + sbPrimary.GeneratedBody.name + " is locked to reference " + sbReference.GeneratedBody.name + ".");
                    Debug.Log("SigmaBinary.SetPrimary", "Primary " + sbPrimary.GeneratedBody.name + " 'solarRotationPeriod' set to 'false'. recalculated rotation period = " + cbPrimary.rotationPeriod);
                }



                /// Set Secondary Orbit

                if (sigmabinaryRedrawOrbit.Contains(sbSecondary))
                {
                    if (sbOrbit?.GeneratedBody?.celestialBody != null && !trackingStationFixer.Contains(sbOrbit.GeneratedBody.celestialBody))
                    {
                        trackingStationFixer.Add(sbOrbit.GeneratedBody.celestialBody);
                    }

                    mapViewFixerList.Add(sbOrbit.GeneratedBody.celestialBody, cbSecondary);

                    sbOrbit.GeneratedBody.orbitDriver.orbit =
                        new Orbit
                        (
                            sbSecondary.GeneratedBody.orbitDriver.orbit.inclination,
                            sbSecondary.GeneratedBody.orbitDriver.orbit.eccentricity,
                            sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis - sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis,
                            sbSecondary.GeneratedBody.orbitDriver.orbit.LAN,
                            sbSecondary.GeneratedBody.orbitDriver.orbit.argumentOfPeriapsis,
                            sbSecondary.GeneratedBody.orbitDriver.orbit.meanAnomalyAtEpoch,
                            sbSecondary.GeneratedBody.orbitDriver.orbit.epoch,
                            cbBarycenter
                        );
                    sbOrbit.Orbit.ReferenceBody = sbBarycenter.GeneratedBody.name;
                    Debug.Log("SigmaBinary.SetMarker", "Printing orbital parameters of primary " + sbPrimary.GeneratedBody.name + " for reference.");
                    Debug.Log("SigmaBinary.SetMarker", "referenceBody = " + sbPrimary.Orbit.ReferenceBody + ", semiMajorAxis = " + sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis);
                    Debug.Log("SigmaBinary.SetMarker", "Printing orbital parameters of secondary " + sbSecondary.GeneratedBody.name + " for reference.");
                    Debug.Log("SigmaBinary.SetMarker", "referenceBody = " + sbSecondary.Orbit.ReferenceBody + ", semiMajorAxis = " + sbSecondary.GeneratedBody.orbitDriver.orbit.semiMajorAxis);
                    Debug.Log("SigmaBinary.SetMarker", "Calculated new orbital parameters for orbit marker " + sbOrbit.GeneratedBody.name);
                    Debug.Log("SigmaBinary.SetMarker", "referenceBody = " + sbOrbit.Orbit.ReferenceBody + ", semiMajorAxis = " + sbOrbit.GeneratedBody.orbitDriver.orbit.semiMajorAxis);

                    sbOrbit.GeneratedBody.orbitRenderer.orbitColor = sbSecondary.GeneratedBody.orbitRenderer.orbitColor;
                    Debug.Log("SigmaBinary.SetMarker", "Orbit marker " + sbOrbit.GeneratedBody.name + " orbit line color set from secondary " + sbSecondary.GeneratedBody.name + ". color = " + sbOrbit.GeneratedBody.orbitRenderer.orbitColor);

                    sbOrbit.GeneratedBody.celestialBody.Set("customOrbitalPeriod", sbSecondary.GetOrbitalPeriod(cbPrimary));
                    Debug.Log("SigmaBinary.SetMarker", "Orbit marker " + sbOrbit.GeneratedBody.name + " orbital period = " + sbOrbit.GetOrbitalPeriod());

                    cbSecondary.Set("drawMode", DrawMode.OFF);
                    Debug.Log("SigmaBinary.SetMarker", "Secondary " + sbSecondary.GeneratedBody.name + " orbit 'drawMode' automatically set. drawMode = " + DrawMode.OFF);
                }



                /// Set SphereOfInfluence for Barycenter and Primary

                if (!cbPrimary.Has("sphereOfInfluence"))
                {
                    cbPrimary.Set("sphereOfInfluence", sbBarycenter.GeneratedBody.orbitDriver.orbit.semiMajorAxis * Math.Pow(cbPrimary.GetMass() / cbReference.GetMass(), 0.4));
                    Debug.Log("SigmaBinary.SetSoI", "Calculated 'sphereOfInfluence' for primary " + sbPrimary.GeneratedBody.name + ". sphereOfInfluence = " + cbPrimary.Get <double>("sphereOfInfluence"));
                }
                cbBarycenter.Set("sphereOfInfluence", cbPrimary.Get <double>("sphereOfInfluence"));
                Debug.Log("SigmaBinary.SetSoI", "Set barycenter " + sbBarycenter.GeneratedBody.name + " 'sphereOfInfluence' from primary " + sbPrimary.GeneratedBody.name + ". sphereOfInfluence = " + cbPrimary.Get <double>("sphereOfInfluence"));
                cbPrimary.Set("sphereOfInfluence", sbPrimary.GeneratedBody.orbitDriver.orbit.semiMajorAxis * (sbBarycenter.GeneratedBody.orbitDriver.orbit.eccentricity + 1) + cbBarycenter.Get <double>("sphereOfInfluence"));
                Debug.Log("SigmaBinary.SetSoI", "Recalculated 'sphereOfInfluence' for primary " + sbPrimary.GeneratedBody.name + ". sphereOfInfluence = " + cbPrimary.Get <double>("sphereOfInfluence"));



                /// Final Fixes for Bodies with a Kerbin Template

                // If the primary has a Kerbin Template, bypass PostSpawnOrbit
                if (kerbinFixer.ContainsKey(sbPrimary.GeneratedBody.name))
                {
                    Debug.Log("SigmaBinary.FixKerbinTemplate", "Primary " + sbPrimary.GeneratedBody.name + " uses Kerbin as Template.");

                    // Revert the referenceBody to the original one
                    sbPrimary.Orbit.ReferenceBody = kerbinFixer[sbPrimary.GeneratedBody.name];
                    Debug.Log("SigmaBinary.FixKerbinTemplate", "Primary " + sbPrimary.GeneratedBody.name + " 'referenceBody' reverted to the original. referenceBody = " + sbPrimary.Orbit.ReferenceBody);

                    // Save the PostSpawn referenceBody for later
                    kerbinFixer[sbPrimary.GeneratedBody.name] = sbBarycenter.GeneratedBody.name;
                    Debug.Log("SigmaBinary.FixKerbinTemplate", "kerbinFixer[cbPrimary] set to barycenter " + sbBarycenter.GeneratedBody.name);

                    // Clear PostSpawnOrbit
                    if (sbPrimary.GeneratedBody.Has("orbitPatches"))
                    {
                        sbPrimary.GeneratedBody.Remove("orbitPatches");
                        Debug.Log("SigmaBinary.FixKerbinTemplate", "Primary " + sbPrimary.GeneratedBody.name + " 'PostSpawnOrbit' node removed, 'kerbinFixer' will handle this.");
                    }
                }

                // If the secondary has a Kerbin Template, restore PostSpawnOrbit referenceBody
                if (kerbinFixer.ContainsKey(sbSecondary.GeneratedBody.name))
                {
                    Debug.Log("SigmaBinary.FixKerbinTemplate", "Secondary " + sbSecondary.GeneratedBody.name + " uses Kerbin as Template.");
                    sbSecondary.Orbit.ReferenceBody = kerbinFixer[sbSecondary.GeneratedBody.name];
                    Debug.Log("SigmaBinary.FixKerbinTemplate", "Secondary " + sbSecondary.GeneratedBody.name + " 'referenceBody' reverted to the original. referenceBody = " + sbSecondary.Orbit.ReferenceBody);
                    kerbinFixer.Remove(sbSecondary.GeneratedBody.name);
                    Debug.Log("SigmaBinary.FixKerbinTemplate", "Secondary " + sbSecondary.GeneratedBody.name + " removed from 'kerbinFixer', 'PostSpawnOrbit' will handle this.");
                }



                /// Binary System Completed

                ListOfBinaries.Remove(ListOfBinaries.First().Key);
                Debug.Log("SigmaBinary.PostApply", "Binary system with secondary " + sbSecondary.GeneratedBody.name + " removed from 'ListOfBinaries'.");

                // Easter Eggs
                LateFixes.TextureFixer(sbPrimary, sbSecondary, ListOfBodies);

                // Log
                UnityEngine.Debug.Log("[SigmaLog]: Binary System Completed\nReferenceBody: " + sbReference.GeneratedBody.name + "\n   Barycenter: " + sbBarycenter.GeneratedBody.name + "\n      Primary: " + sbPrimary.GeneratedBody.name + "\n    Secondary: " + sbSecondary.GeneratedBody.name + (Debug.debug ? "\n        Orbit: " + sbOrbit?.GeneratedBody?.name : ""));
            }
            Debug.Log("SigmaBinary.ProcessBinaries", "Completed the set up of all binary systems.");
        }
Example #15
0
        private void ApplyMapTargetPatches()
        {
            if (!MapView.MapIsEnabled)
            {
                return;
            }

            // Grab the needed fields for reflection
            if (_fields == null)
            {
                FieldInfo modeField = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                                      .FirstOrDefault(f => f.FieldType.IsEnum && f.FieldType.IsNested);
                FieldInfo contextField = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                                         .FirstOrDefault(f => f.FieldType == typeof(MapContextMenu));
                FieldInfo castField = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                                      .FirstOrDefault(f => f.FieldType == typeof(OrbitRenderer.OrbitCastHit));

                _fields = new[] { modeField, contextField, castField };
            }

            // Remove buttons in map view for barycenters
            if (!FlightGlobals.ActiveVessel)
            {
                return;
            }

            OrbitTargeter targeter = FlightGlobals.ActiveVessel.orbitTargeter;

            if (!targeter)
            {
                return;
            }

            Int32 mode = (Int32)_fields[0].GetValue(targeter);

            if (mode != 2)
            {
                return;
            }
            OrbitRenderer.OrbitCastHit cast = (OrbitRenderer.OrbitCastHit)_fields[2].GetValue(targeter);

            CelestialBody body = PSystemManager.Instance.localBodies.Find(b =>
                                                                          cast.or != null && cast.or.discoveryInfo?.name != null && b.name == cast.or.discoveryInfo.name.Value);

            if (!body)
            {
                return;
            }

            if (!body.Has("barycenter") && body.Get("selectable", true))
            {
                return;
            }

            if (!cast.driver || cast.driver.Targetable == null)
            {
                return;
            }

            MapContextMenu context = MapContextMenu.Create(body.name, new Rect(0.5f, 0.5f, 300f, 50f), cast, () =>
            {
                _fields[0].SetValue(targeter, 0);
                _fields[1].SetValue(targeter, null);
            }, new SetAsTarget(cast.driver.Targetable, () => FlightGlobals.fetch.VesselTarget));

            _fields[1].SetValue(targeter, context);
        }
Example #16
0
        // Apply PostSpawnOrbit patches
        private void ApplyOrbitPatches()
        {
            // Bodies
            Dictionary <String, KeyValuePair <CelestialBody, CelestialBody> > fixes = new Dictionary <String, KeyValuePair <CelestialBody, CelestialBody> >();

            for (Int32 i = 0; i < PSystemManager.Instance.localBodies.Count; i++)
            {
                CelestialBody body = PSystemManager.Instance.localBodies[i];

                // Post spawn patcher
                if (!body.Has("orbitPatches"))
                {
                    continue;
                }

                ConfigNode    orbitNode = body.Get <ConfigNode>("orbitPatches");
                OrbitLoader   loader    = new OrbitLoader(body);
                CelestialBody oldRef    = body.referenceBody;
                Parser.LoadObjectFromConfigurationNode(loader, orbitNode, "Kopernicus");
                oldRef.orbitingBodies.Remove(body);

                if (body.referenceBody == null)
                {
                    // Log the exception
                    Debug.Log("Exception: PostSpawnOrbit reference body for \"" + body.name +
                              "\" could not be found. Missing body name is \"" + loader.ReferenceBody + "\".");

                    // Open the Warning popup
                    Injector.DisplayWarning();
                    Destroy(this);
                    return;
                }

                fixes.Add(body.transform.name,
                          new KeyValuePair <CelestialBody, CelestialBody>(oldRef, body.referenceBody));
                body.referenceBody.orbitingBodies.Add(body);
                body.referenceBody.orbitingBodies =
                    body.referenceBody.orbitingBodies.OrderBy(cb => cb.orbit.semiMajorAxis).ToList();
                body.orbit.Init();

                //body.orbitDriver.UpdateOrbit();

                // Calculations
                if (!body.Has("sphereOfInfluence"))
                {
                    body.sphereOfInfluence = body.orbit.semiMajorAxis *
                                             Math.Pow(body.Mass / body.orbit.referenceBody.Mass, 0.4);
                }

                if (!body.Has("hillSphere"))
                {
                    body.hillSphere = body.orbit.semiMajorAxis * (1 - body.orbit.eccentricity) *
                                      Math.Pow(body.Mass / body.orbit.referenceBody.Mass, 0.333333333333333);
                }

                if (!body.solarRotationPeriod)
                {
                    continue;
                }

                Double rotationPeriod = body.rotationPeriod;
                Double orbitalPeriod  = body.orbit.period;
                body.rotationPeriod = rotationPeriod * orbitalPeriod / (orbitalPeriod + rotationPeriod);
            }

            // Update the order in the tracking station
            List <MapObject> trackingstation = new List <MapObject>();

            Utility.DoRecursive(PSystemManager.Instance.localBodies[0], cb => cb.orbitingBodies, cb =>
            {
                trackingstation.Add(PlanetariumCamera.fetch.targets.Find(t => t.celestialBody == cb));
            });
            PlanetariumCamera.fetch.targets = trackingstation.Where(m => m != null).ToList();

            // Undo stuff
            foreach (CelestialBody b in PSystemManager.Instance.localBodies.Where(b => b.Has("orbitPatches")))
            {
                String transformName = b.transform.name;
                fixes[transformName].Value.orbitingBodies.Remove(b);
                fixes[transformName].Key.orbitingBodies.Add(b);
                fixes[transformName].Key.orbitingBodies = fixes[transformName].Key.orbitingBodies
                                                          .OrderBy(cb => cb.orbit.semiMajorAxis).ToList();
            }
        }
        void Start()
        {
            foreach (CelestialBody cb in FlightGlobals.Bodies)
            {
                body = cb;
                resize = body.Has("resize") ? body.Get<double>("resize") : 1;
                landscape = body.Has("landscape") ? body.Get<double>("landscape") : 1;
                resizeBuildings = body.Has("resizeBuildings") ? body.Get<double>("resizeBuildings") : 1;

                foreach (PQSCity mod in body.GetComponentsInChildren<PQSCity>(true))
                {
                    CityFixer(mod);
                }

                foreach (PQSCity2 mod in body.GetComponentsInChildren<PQSCity2>(true))
                {
                    City2Fixer(mod);
                }
            }
        }
Example #18
0
        void FixAltitude()
        {
            CelestialBody body = FlightGlobals.currentMainBody;

            if (body == null)
            {
                return;
            }

            PQS pqs = body.pqsController;

            if (pqs == null)
            {
                return;
            }

            PQSCity city = GetComponent <PQSCity>();

            if (city == null)
            {
                return;
            }

            // Location
            Vector3 planet   = body.transform.position;
            Vector3 building = city.transform.position; // From body to city
            Vector3 location = (building - planet).normalized;

            // Sigma Dimensions Settings
            double resize          = body.Has("resize") ? body.Get <double>("resize") : 1;
            double landscape       = body.Has("landscape") ? body.Get <double>("landscape") : 1;
            double resizeBuildings = body.Has("resizeBuildings") ? body.Get <double>("resizeBuildings") : 1;

            // Max distance
            double maxDistance = Math.Abs(2 * pqs.mapMaxHeight);

            maxDistance *= resize * landscape > 1 ? resize * landscape : 1;
            maxDistance += body.Radius;


            RaycastHit[] hits = Physics.RaycastAll(planet + location * (float)maxDistance, -location, (float)maxDistance, LayerMask.GetMask("Local Scenery"));

            for (int i = 0; i < hits?.Length; i++)
            {
                if (hits[i].collider?.GetComponent <PQ>())
                {
                    // Update only once
                    TimingManager.UpdateRemove(TimingManager.TimingStage.Normal, FixAltitude);
                    Debug.Log("PQSCityFixer", "> Planet: " + body.transform.name);
                    Debug.Log("PQSCityFixer", "    > PQSCity: " + city);

                    // PQSCity parameters
                    double groundLevel = (hits[i].point - planet).magnitude - body.Radius;
                    double error       = pqs.GetSurfaceHeight(city.repositionRadial) - body.Radius - groundLevel;
                    double oceanDepth  = body.ocean && groundLevel < 0 ? -groundLevel : 0d;
                    groundLevel = body.ocean && groundLevel < 0 ? 0d : groundLevel;

                    Debug.Log("PQSCityFixer", "        > Ground Level at Mod = " + groundLevel);
                    Debug.Log("PQSCityFixer", "        > Ocean Depth at Mod = " + groundLevel);
                    Debug.Log("PQSCityFixer", "        > Ground Level Error at Mod = " + groundLevel);

                    // Fix Altitude
                    if (city.repositionToSphere && !city.repositionToSphereSurface)
                    {
                        // Offset = Distance from the radius of the planet

                        Debug.Log("PQSCityFixer", "        > PQSCity Original Radius Offset = " + city.repositionRadiusOffset);

                        double builtInOffset = city.repositionRadiusOffset - groundLevel / (resize * landscape);

                        Debug.Log("PQSCityFixer", "        > Builtuin Offset = " + builtInOffset);

                        city.repositionRadiusOffset = groundLevel + error / (resize * landscape) - (groundLevel + error - city.repositionRadiusOffset) / resizeBuildings;

                        Debug.Log("PQSCityFixer", "        > PQSCity Fixed Radius Offset = " + city.repositionRadiusOffset);
                    }
                    else
                    {
                        // Offset = Distance from the surface of the planet
                        if (!city.repositionToSphereSurface)
                        {
                            city.repositionToSphereSurface = true;
                            city.repositionRadiusOffset    = 0;
                        }
                        if (!city.repositionToSphereSurfaceAddHeight)
                        {
                            city.repositionToSphereSurfaceAddHeight = true;
                            city.repositionRadiusOffset             = 0;
                        }

                        Debug.Log("PQSCityFixer", "        > PQSCity Original Surface Offset = " + city.repositionRadiusOffset);

                        city.repositionRadiusOffset = oceanDepth + error / (resize * landscape) - (oceanDepth + error - city.repositionRadiusOffset) / resizeBuildings;

                        Debug.Log("PQSCityFixer", "        > PQSCity Fixed Surface Offset = " + city.repositionRadiusOffset);
                    }

                    city.Orientate();
                    DestroyImmediate(this);
                }
            }
        }
Example #19
0
        void Start()
        {
            //  FIX BODIES MOVED POSTSPAWN  //
            bool postSpawnChanges = false;

            foreach (CelestialBody cb in PSystemManager.Instance.localBodies.Where(b => b.Has("orbitPatches")))
            {
                // Fix position if the body gets moved PostSpawn
                ConfigNode patch = cb.Get <ConfigNode>("orbitPatches");
                if (patch.GetValue("referenceBody") != null || patch.GetValue("semiMajorAxis") != null)
                {
                    // Get the body, the old parent and the new parent
                    PSystemBody body      = PSystemManager.Instance.systemPrefab.GetComponentsInChildren <PSystemBody>(true).First(b => b.name == name);
                    PSystemBody oldParent = PSystemManager.Instance.systemPrefab.GetComponentsInChildren <PSystemBody>(true).First(b => b.children.Contains(body));
                    PSystemBody newParent = oldParent;
                    if (patch.GetValue("referenceBody") != null)
                    {
                        newParent = PSystemManager.Instance.systemPrefab.GetComponentsInChildren <PSystemBody>(true).First(b => b.name == patch.GetValue("referenceBody"));
                    }

                    if (body != null && oldParent != null)
                    {
                        // If there is no new SMA it means only the parent changed
                        NumericParser <double> newSMA = body.orbitDriver.orbit.semiMajorAxis;
                        if (patch.GetValue("semiMajorAxis") != null)
                        {
                            newSMA.SetFromString(patch.GetValue("semiMajorAxis"));
                        }

                        // Count how many children comes before our body in the newParent.child list
                        int index = 0;
                        foreach (PSystemBody child in newParent.children)
                        {
                            if (child.orbitDriver.orbit.semiMajorAxis < newSMA.value)
                            {
                                index++;
                            }
                        }

                        // Add the body as child for the new parent and remove it for the old parent
                        if (index > newParent.children.Count)
                        {
                            newParent.children.Add(body);
                        }
                        else
                        {
                            newParent.children.Insert(index, body);
                        }

                        oldParent.children.Remove(body);
                        postSpawnChanges = true;
                    }
                }
            }

            // Rebuild Archives
            if (postSpawnChanges)
            {
                AddPlanets();
            }



            //  RDVisibility = SKIP  //
            List <KeyValuePair <PSystemBody, PSystemBody> > skipList = new List <KeyValuePair <PSystemBody, PSystemBody> >();

            // Create a list with body to hide and their parent
            PSystemBody[] bodies = PSystemManager.Instance.systemPrefab.GetComponentsInChildren <PSystemBody>(true);
            foreach (CelestialBody body in PSystemManager.Instance.localBodies.Where(b => b.Has("hiddenRnD")))
            {
                if (body.Get <PropertiesLoader.RDVisibility>("hiddenRnD") == PropertiesLoader.RDVisibility.SKIP)
                {
                    PSystemBody hidden = Utility.FindBody(PSystemManager.Instance.systemPrefab.rootBody, name);
                    if (hidden.children.Count == 0)
                    {
                        body.Set("hiddenRnd", PropertiesLoader.RDVisibility.HIDDEN);
                    }
                    else
                    {
                        PSystemBody parent = bodies.First(b => b.children.Contains(hidden));
                        if (parent != null)
                        {
                            if (skipList.Any(b => b.Key == parent))
                            {
                                int index = skipList.IndexOf(skipList.First(b => b.Key == parent));
                                skipList.Insert(index, new KeyValuePair <PSystemBody, PSystemBody>(hidden, parent));
                            }
                            else
                            {
                                skipList.Add(new KeyValuePair <PSystemBody, PSystemBody>(hidden, parent));
                            }
                        }
                    }
                }
            }

            foreach (KeyValuePair <PSystemBody, PSystemBody> pair in skipList)
            {
                // Get hidden body and parent
                PSystemBody hidden = pair.Key;
                PSystemBody parent = pair.Value;

                // Find where the hidden body is
                int index = parent.children.IndexOf(hidden);

                // Put its children in its place
                parent.children.InsertRange(index, hidden.children);

                // Remove the hidden body from its parent's children list so it won't show up when clicking the parent
                parent.children.Remove(hidden);
            }

            if (skipList.Count > 0)
            {
                // Rebuild Archives
                AddPlanets();

                // Undo the changes to the PSystem
                for (int i = skipList.Count; i > 0; i = i - 1)
                {
                    PSystemBody hidden   = skipList.ElementAt(i).Key;
                    PSystemBody parent   = skipList.ElementAt(i).Value;
                    int         oldIndex = parent.children.IndexOf(hidden.children.First());
                    parent.children.Insert(oldIndex, hidden);
                    foreach (PSystemBody child in hidden.children)
                    {
                        if (parent.children.Contains(child))
                        {
                            parent.children.Remove(child);
                        }
                    }
                }
            }



            //  RDVisibility = HIDDEN  //  RDVisibility = NOICON  //
            // Loop through the Container
            foreach (RDPlanetListItemContainer planetItem in Resources.FindObjectsOfTypeAll <RDPlanetListItemContainer>())
            {
                // Barycenter
                CelestialBody body = PSystemManager.Instance.localBodies.Find(b => b.transform.name == planetItem.label_planetName.text);
                if (body.Has("barycenter") || body.Has("notSelectable"))
                {
                    planetItem.planet.SetActive(false);
                    planetItem.label_planetName.alignment = TextAlignmentOptions.MidlineLeft;
                }

                // RD Visibility
                if (body.Has("hiddenRnD"))
                {
                    PropertiesLoader.RDVisibility visibility = body.Get <PropertiesLoader.RDVisibility>("hiddenRnD");
                    if (visibility == PropertiesLoader.RDVisibility.NOICON)
                    {
                        planetItem.planet.SetActive(false);
                        planetItem.label_planetName.alignment = TextAlignmentOptions.MidlineLeft;
                    }
                    else if (visibility == PropertiesLoader.RDVisibility.HIDDEN)
                    {
                        planetItem.gameObject.SetActive(false);
                        planetItem.Hide();
                        planetItem.HideChildren();
                    }
                    else
                    {
                        planetItem.planet.SetActive(true);
                        planetItem.label_planetName.alignment = TextAlignmentOptions.MidlineRight;
                    }
                }

                // namechanges
                if (FindObjectsOfType <NameChanger>().Count(n => n.oldName == planetItem.label_planetName.text) != 0 && !planetItem.label_planetName.name.EndsWith("NAMECHANGER"))
                {
                    NameChanger changer = FindObjectsOfType <NameChanger>().First(n => n.oldName == planetItem.label_planetName.text);
                    planetItem.label_planetName.text  = changer.newName;
                    planetItem.label_planetName.name += "NAMECHANGER";
                }
            }
        }
Example #20
0
        void Update()
        {
            CelestialBody body = FlightGlobals.currentMainBody;

            if (body == null)
            {
                return;
            }

            PQS pqs = body.pqsController;

            if (pqs == null)
            {
                return;
            }

            PQSCity2 city = GetComponent <PQSCity2>();

            if (city == null)
            {
                return;
            }

            // Location
            Vector3 planet   = body.transform.position;
            Vector3 building = city.transform.position; // From body to city
            Vector3 location = (building - planet).normalized;

            // Sigma Dimensions Settings
            double resize          = body.Has("resize") ? body.Get <double>("resize") : 1;
            double landscape       = body.Has("landscape") ? body.Get <double>("landscape") : 1;
            double resizeBuildings = body.Has("resizeBuildings") ? body.Get <double>("resizeBuildings") : 1;

            // Max distance
            double maxDistance = Math.Abs(2 * pqs.mapMaxHeight);

            maxDistance *= resize * landscape > 1 ? resize * landscape : 1;
            maxDistance += body.Radius;


            RaycastHit[] hits = Physics.RaycastAll(planet + location * (float)maxDistance, -location, (float)maxDistance, LayerMask.GetMask("Local Scenery"));

            for (int i = 0; i < hits?.Length; i++)
            {
                if (hits[i].collider?.GetComponent <PQ>())
                {
                    Debug.Log("PQSCity2Fixer", "> Planet: " + body.transform.name);
                    Debug.Log("PQSCity2Fixer", "    > PQSCity2: " + city);

                    // PQSCity2 parameters
                    double groundLevel = (hits[i].point - planet).magnitude - body.Radius;
                    Debug.Log("PQSCity2Fixer", "        > Ground Level at Mod (RAYCAST) = " + groundLevel);
                    double error = pqs.GetSurfaceHeight(city.PlanetRelativePosition) - body.Radius - groundLevel;
                    Debug.Log("PQSCity2Fixer", "        > Ground Level Error at Mod = " + error);
                    double oceanDepth = body.ocean && groundLevel < 0 ? -groundLevel : 0d;
                    Debug.Log("PQSCity2Fixer", "        > Ocean Depth at Mod = " + oceanDepth);
                    groundLevel = body.ocean && groundLevel < 0 ? 0d : groundLevel;
                    Debug.Log("PQSCity2Fixer", "        > Ground Level at Mod (NEW) = " + groundLevel);

                    // Because, SQUAD
                    city.PositioningPoint.localPosition /= (float)(body.Radius + city.alt);

                    // Fix Altitude
                    if (!city.snapToSurface)
                    {
                        // Alt = Distance from the radius of the planet

                        Debug.Log("PQSCity2Fixer", "        > PQSCity2 Original Radius Offset = " + city.alt);

                        double builtInOffset = city.alt - groundLevel / (resize * landscape);

                        Debug.Log("PQSCity2Fixer", "        > Builtuin Offset = " + builtInOffset);

                        city.alt = groundLevel + error / (resize * landscape) - (groundLevel + error - city.alt) / resizeBuildings;

                        Debug.Log("PQSCity2Fixer", "        > PQSCity2 Fixed Radius Offset = " + city.alt);
                    }
                    else
                    {
                        // Offset = Distance from the surface of the planet

                        Debug.Log("PQSCity2Fixer", "        > PQSCity2 Original Surface Offset = " + city.snapHeightOffset);

                        double newOffset = oceanDepth + error / (resize * landscape) - (oceanDepth + error - city.snapHeightOffset) / resizeBuildings;

                        city.alt += newOffset - city.snapHeightOffset;
                        city.snapHeightOffset = newOffset;

                        Debug.Log("PQSCity2Fixer", "        > PQSCity2 New Surface Offset = " + city.snapHeightOffset);
                    }

                    // Because, SQUAD
                    city.PositioningPoint.localPosition *= (float)(body.Radius + city.alt);

                    // Apply Changes and Destroy
                    city.Orientate();
                    DestroyImmediate(this);
                }
            }
        }
        void SaveGroups()
        {
            // LOAD SD GROUPS
            foreach (ConfigNode Group in GroupsList.Values)
            {
                string        group = Group.GetValue("name");
                CelestialBody body  = FlightGlobals.Bodies.FirstOrDefault(b => b.transform.name == Group.GetValue("body"));
                if (string.IsNullOrEmpty(group) || body == null)
                {
                    continue;
                }
                Debug.Log("PQSCityGroups.SaveGroups", ">>> Loading PQSCityGroups from config files <<<");
                Debug.Log("PQSCityGroups.SaveGroups", "> Planet: " + body.name + (body.name != body.displayName.Replace("^N", "") ? (", (A.K.A.: " + body.displayName.Replace("^N", "") + ")") : "") + (body.name != body.transform.name ? (", (A.K.A.: " + body.transform.name + ")") : ""));
                Debug.Log("PQSCityGroups.SaveGroups", "    > Group: " + group);

                bool.TryParse(Group.GetValue("exclude"), out bool exclude);

                // FIND GROUP CENTER
                Vector3Parser center = null;

                // Get Center position from the CENTER node
                if (Group.HasNode("CENTER"))
                {
                    ConfigNode C = Group.GetNode("CENTER");

                    if (C.HasValue("CentralPQSCity"))
                    {
                        if (body == FlightGlobals.GetHomeBody() && C.GetValue("CentralPQSCity") == "KSC")
                        {
                            center = new Vector3(157000, -1000, -570000);
                        }
                    }

                    if (center == null)
                    {
                        center = GetCenter(C, body);
                    }
                }

                if (!body.Has("PQSCityGroups"))
                {
                    body.Set("PQSCityGroups", new Dictionary <object, Vector3>());
                }
                Dictionary <object, Vector3> PQSList = body.Get <Dictionary <object, Vector3> >("PQSCityGroups");

                if (!body.Has("ExcludedPQSCityMods"))
                {
                    body.Set("ExcludedPQSCityMods", new List <object>());
                }
                List <object> ExcludeList = body.Get <List <object> >("ExcludedPQSCityMods");

                // If the Center position has not been found get it from the MODS node
                if (Group.HasNode("MODS"))
                {
                    ConfigNode M = Group.GetNode("MODS");

                    if (center == null)
                    {
                        center = GetCenter(M, body);
                    }
                }

                // If the Center position has not been found get it from the external groups
                if
                (
                    center == null &&
                    ExternalGroups?.ContainsKey(body) == true &&
                    ExternalGroups[body].ContainsKey(group)
                )
                {
                    center = GetPosition(ExternalGroups[body][group].FirstOrDefault());
                }

                // If the Center position has not been found stop here
                if (center == null)
                {
                    continue;
                }
                Debug.Log("PQSCityGroups.SaveGroups", "        > Center position = " + center.Value + ", (LAT: " + new SigmaDimensions.LatLon(center).lat + ", LON: " + new SigmaDimensions.LatLon(center).lon + ")");


                // ADD PQS MODS TO THE GROUP
                if (Group.HasNode("MODS"))
                {
                    ConfigNode M = Group.GetNode("MODS");

                    foreach (string city in M.GetValues("PQSCity"))
                    {
                        PQSCity mod = body.GetComponentsInChildren <PQSCity>(true).FirstOrDefault(m => m.name == city);

                        if (mod != null)
                        {
                            // If the mod has already been added overwrite it
                            // This way custom groups will overwrite external ones
                            if (PQSList.ContainsKey(mod))
                            {
                                PQSList.Remove(mod);
                            }

                            if (!exclude)
                            {
                                PQSList.Add(mod, center);
                                Debug.Log("PQSCityGroups.SaveGroups", "            > PQSCity:  " + mod.name);
                            }
                            else
                            {
                                ExcludeList.Add(mod);
                                Debug.Log("PQSCityGroups.SaveGroups", "            > Excluded PQSCity:  " + mod.name);
                            }
                        }
                    }
                    foreach (string city2 in M.GetValues("PQSCity2"))
                    {
                        PQSCity2 mod = body.GetComponentsInChildren <PQSCity2>(true).FirstOrDefault(m => m.name == city2);

                        if (mod != null)
                        {
                            // If the mod has already been added overwrite it
                            // This way custom groups will overwrite external ones
                            if (PQSList.ContainsKey(mod))
                            {
                                PQSList.Remove(mod);
                            }

                            if (!exclude)
                            {
                                PQSList.Add(mod, center);
                                Debug.Log("PQSCityGroups.SaveGroups", "            > PQSCity2:  " + mod.name);
                            }
                            else
                            {
                                ExcludeList.Add(mod);
                                Debug.Log("PQSCityGroups.SaveGroups", "            > Excluded PQSCity2:  " + mod.name);
                            }
                        }
                    }
                }


                // ADD EXTERNAL MODS TO THIS GROUP
                if
                (
                    ExternalGroups?.ContainsKey(body) == true &&
                    ExternalGroups[body].ContainsKey(group) &&
                    ExternalGroups[body][group].Where(m => m != null)?.Count() > 0
                )
                {
                    foreach (object mod in ExternalGroups[body][group].Where(m => m != null))
                    {
                        // External groups should not overwrite custom ones
                        if (PQSList.ContainsKey(mod))
                        {
                            continue;
                        }

                        if (!exclude)
                        {
                            PQSList.Add(mod, center);
                            Debug.Log("PQSCityGroups.SaveGroups", "            > external:  " + mod);
                        }
                        else
                        {
                            ExcludeList.Add(mod);
                            Debug.Log("PQSCityGroups.SaveGroups", "            > Excluded external:  " + mod);
                        }
                    }
                    ExternalGroups[body].Remove(group);
                }


                // REMOVE KSC FROM THE LIST

                PQSCity ksc = FlightGlobals.GetHomeBody().GetComponentsInChildren <PQSCity>(true).FirstOrDefault(m => m.name == "KSC");
                if (PQSList.ContainsKey(ksc))
                {
                    PQSList.Remove(ksc);
                }
                if (ExcludeList.Contains(ksc))
                {
                    ExcludeList.Remove(ksc);
                }


                body.Set("PQSCityGroups", PQSList);
                body.Set("ExcludedPQSCityMods", ExcludeList);


                // ADD THIS GROUP TO THE MOVE LIST
                if (Group.HasNode("MOVE"))
                {
                    ConfigNode C2        = Group.GetNode("MOVE");
                    Vector3?   newCenter = GetCenter(C2, body);

                    if (newCenter == null)
                    {
                        newCenter = center;
                    }
                    Debug.Log("PQSCityGroups.SaveGroups", "Move Group to position = " + newCenter.Value + ", (LAT: " + new SigmaDimensions.LatLon(newCenter.Value).lat + ", LON: " + new SigmaDimensions.LatLon(newCenter.Value).lon + ")");


                    var info = new KeyValuePair <Vector3, NumericParser <double>[]>((Vector3)newCenter, new[] { 0, 0, new NumericParser <double>() });

                    if (C2.HasValue("Rotate"))
                    {
                        info.Value[0].SetFromString(C2.GetValue("Rotate"));
                    }
                    Debug.Log("PQSCityGroups.SaveGroups", "Rotate group = " + info.Value[0].Value);
                    if (C2.HasValue("fixAltitude"))
                    {
                        info.Value[1].SetFromString(C2.GetValue("fixAltitude"));
                    }
                    Debug.Log("PQSCityGroups.SaveGroups", "Fix group altitude = " + info.Value[1].Value);
                    if (C2.HasValue("originalAltitude"))
                    {
                        info.Value[2].SetFromString(C2.GetValue("originalAltitude"));
                    }
                    else
                    {
                        info.Value[2].SetFromString("-Infinity");
                    } Debug.Log("PQSCityGroups.SaveGroups", "Original group altitude = " + (info.Value[2].Value == double.NegativeInfinity ? "[Not Specified]" : info.Value[2].Value.ToString()));


                    if (!body.Has("PQSCityGroupsMove"))
                    {
                        body.Set("PQSCityGroupsMove", new Dictionary <Vector3, KeyValuePair <Vector3, NumericParser <double>[]> >());
                    }
                    var MoveList = body.Get <Dictionary <Vector3, KeyValuePair <Vector3, NumericParser <double>[]> > >("PQSCityGroupsMove");

                    if (!MoveList.ContainsKey(center.Value))
                    {
                        MoveList.Add(center.Value, info);
                    }

                    body.Set("PQSCityGroupsMove", MoveList);
                }
            }


            // Make sure External Groups are valid
            if (ExternalGroups == null)
            {
                ExternalGroups = new Dictionary <CelestialBody, Dictionary <string, List <object> > >();
            }

            // LOAD REMAINING EXTERNAL GROUPS
            Debug.Log("PQSCityGroups.SaveGroups", ">>> Loading external PQSCityGroups <<<");
            foreach (CelestialBody planet in ExternalGroups.Keys.Where(p => p != null && ExternalGroups[p] != null))
            {
                Debug.Log("PQSCityGroups.SaveGroups", "> Planet: " + planet.name + (planet.name != planet.displayName.Replace("^N", "") ? (", (A.K.A.: " + planet.displayName.Replace("^N", "") + ")") : "") + (planet.name != planet.transform.name ? (", (A.K.A.: " + planet.transform.name + ")") : ""));
                foreach (string group in ExternalGroups[planet].Keys.Where(g => !string.IsNullOrEmpty(g) && ExternalGroups[planet][g] != null))
                {
                    if (ExternalGroups[planet][group].Count == 0)
                    {
                        continue;
                    }
                    Debug.Log("PQSCityGroups.SaveGroups", "    > Group: " + group);

                    // Since these groups are new they don't have a center
                    // Define the center as the position of the first mod in the array
                    Vector3?center = null;
                    center = GetPosition(ExternalGroups[planet][group].FirstOrDefault());
                    if (center == null)
                    {
                        continue;
                    }
                    Debug.Log("PQSCityGroups.SaveGroups", "        > Center position = " + center + ", (LAT: " + new SigmaDimensions.LatLon((Vector3)center).lat + ", LON: " + new SigmaDimensions.LatLon((Vector3)center).lon + ")");

                    if (!planet.Has("PQSCityGroups"))
                    {
                        planet.Set("PQSCityGroups", new Dictionary <object, Vector3>());
                    }
                    Dictionary <object, Vector3> PQSList = planet.Get <Dictionary <object, Vector3> >("PQSCityGroups");

                    foreach (object mod in ExternalGroups[planet][group])
                    {
                        if (!PQSList.ContainsKey(mod))
                        {
                            PQSList.Add(mod, (Vector3)center);
                            Debug.Log("PQSCityGroups.SaveGroups", "            > external: " + mod);
                        }
                    }


                    // REMOVE KSC FROM THE LIST

                    PQSCity ksc = FlightGlobals.GetHomeBody().GetComponentsInChildren <PQSCity>(true).FirstOrDefault(m => m.name == "KSC");
                    if (PQSList.ContainsKey(ksc))
                    {
                        PQSList.Remove(ksc);
                    }


                    planet.Set("PQSCityGroups", PQSList);
                }
            }

            // LOAD EXTERNAL EXCEPTIONS
            Debug.Log("PQSCityGroups.SaveGroups", ">>> Loading external PQSCityGroups exceptions <<<");
            foreach (CelestialBody planet in ExternalExceptions.Keys.Where(p => p != null && ExternalExceptions[p] != null))
            {
                Debug.Log("PQSCityGroups.SaveGroups", "> Planet: " + planet.name + (planet.name != planet.displayName.Replace("^N", "") ? (", (A.K.A.: " + planet.displayName.Replace("^N", "") + ")") : "") + (planet.name != planet.transform.name ? (", (A.K.A.: " + planet.transform.name + ")") : ""));
                foreach (string group in ExternalExceptions[planet].Keys.Where(g => !string.IsNullOrEmpty(g) && ExternalExceptions[planet][g] != null))
                {
                    if (ExternalExceptions[planet][group].Count == 0)
                    {
                        continue;
                    }
                    Debug.Log("PQSCityGroups.SaveGroups", "    > Group: " + group);

                    // Since these groups are exceptions they don't need a center

                    if (!planet.Has("ExcludedPQSCityMods"))
                    {
                        planet.Set("ExcludedPQSCityMods", new Dictionary <object, Vector3>());
                    }
                    List <object> ExcludeList = planet.Get <List <object> >("PQSCityGroups");

                    foreach (object mod in ExternalExceptions[planet][group])
                    {
                        if (!ExcludeList.Contains(mod))
                        {
                            ExcludeList.Add(mod);
                            Debug.Log("PQSCityGroups.SaveGroups", "            > excluded external: " + mod);
                        }
                    }


                    // REMOVE KSC FROM THE LIST

                    PQSCity ksc = FlightGlobals.GetHomeBody().GetComponentsInChildren <PQSCity>(true).FirstOrDefault(m => m.name == "KSC");
                    if (ExcludeList.Contains(ksc))
                    {
                        ExcludeList.Remove(ksc);
                    }


                    planet.Set("ExcludedPQSCityMods", ExcludeList);
                }
            }
        }
        /// <summary>
        /// Gets invoked when all bodies were successfully loaded
        /// </summary>
        public static void OnLoaderLoadedAllBodies(Loader loader, ConfigNode node)
        {
            // Grab home star and home planet
            CelestialBody[] cbs  = Bodies.Select(b => b.celestialBody).ToArray();
            CelestialBody   star = UBI.GetBody(InterstellarSettings.Instance.HomeStar, cbs);

            if (!star.Has("IC:HomePlanet"))
            {
                throw new Exception("The home star must have a home planet defined.");
            }

            CelestialBody planet = UBI.GetBody(InterstellarSettings.Instance.HomePlanet ?? star.Get("IC:HomePlanet", ""), cbs);

            // Grab the position of the home star
            Vector3d position = star.Get("IC:Position", Vector3d.zero);

            // Fix the naming of home star and home planet
            Body starBody   = Bodies.Find(b => b.celestialBody == star);
            Body planetBody = Bodies.Find(b => b.celestialBody == planet);

            RenameBody(starBody, "Sun");
            RenameBody(planetBody, "Kerbin");
            planet.isHomeWorld = true;

            // Since this body is the center of the universe, remove its orbit
            UnityEngine.Object.DestroyImmediate(starBody.generatedBody.celestialBody.GetComponent <OrbitRendererUpdater>());
            UnityEngine.Object.DestroyImmediate(starBody.generatedBody.orbitDriver);
            UnityEngine.Object.DestroyImmediate(starBody.generatedBody.orbitRenderer);
            starBody.orbit = null;

            // Trigger the KSC mover
            WithBody(planetBody, () => { planetBody.pqs = new PQSLoader(); });

            // Go through each body, and calculate the orbits of the stars
            foreach (Body body in Bodies)
            {
                // Don't work with non-IC bodies
                if (!body.celestialBody.Has("IC:Position"))
                {
                    continue;
                }

                // We already edited the home star
                if (body.celestialBody == star)
                {
                    continue;
                }

                // Apply the SOI
                if (body.celestialBody.Has("IC:SOI"))
                {
                    body.properties.sphereOfInfluence = body.celestialBody.Get("IC:SOI", 0d) * InterstellarSettings.Instance.KI;
                }

                // Calculate the real position of the star
                Vector3d realPosition = body.celestialBody.Get("IC:Position", Vector3d.zero) - position;

                // Apply the orbital parameters
                WithBody(body, () =>
                {
                    body.orbit = new OrbitLoader();
                    body.orbit.semiMajorAxis =
                        Math.Pow(
                            Math.Pow(realPosition.x, 2) + Math.Pow(realPosition.y, 2) + Math.Pow(realPosition.z, 2),
                            0.5) * InterstellarSettings.Instance.KI;
                    body.orbit.eccentricity        = 0;
                    body.orbit.argumentOfPeriapsis = 90;
                    body.orbit.meanAnomalyAtEpoch  = 0;
                    body.orbit.inclination         =
                        Math.Atan(realPosition.z /
                                  Math.Pow(Math.Pow(realPosition.x, 2) + Math.Pow(realPosition.y, 2), 0.5)) / Math.PI *
                        180;
                    body.orbit.longitudeOfAscendingNode = CalculateLAN(realPosition.x, realPosition.y);
                    body.orbit.period        = Double.MaxValue;
                    body.orbit.referenceBody = UBI.GetUBI(star);

                    // This is a bit of a hack, because 1.3.1 and 1.4.5+ use different enums for
                    // that value, and i want IC to be compatible with all versions
                    try
                    {
                        PropertyInfo orbitMode   = typeof(OrbitLoader).GetProperty("mode");
                        Type parserType          = orbitMode.PropertyType;
                        MethodInfo setFromString = parserType.GetMethod("SetFromString");
                        Object parser            = orbitMode.GetValue(body.orbit, null);
                        setFromString.Invoke(parser, new[] { "OFF" });
                        orbitMode.SetValue(body.orbit, parser, null);
                    }
                    catch
                    {
                        // ignored
                    }

                    // Load additional patches
                    if (body.celestialBody.Has("IC:OrbitPatches"))
                    {
                        Parser.LoadObjectFromConfigurationNode(body.orbit,
                                                               body.celestialBody.Get <ConfigNode>("IC:OrbitPatches"));
                    }
                });
            }
        }
Example #23
0
        void Update()
        {
            if (time < 0.2)
            {
                time += Time.deltaTime;
            }
            else
            {
                time = 0;

                CelestialBody body = FlightGlobals.currentMainBody;
                if (body == null)
                {
                    return;
                }

                PQS pqs = body.pqsController;
                if (pqs == null)
                {
                    return;
                }

                PQSCity city = GetComponent <PQSCity>();
                if (city == null)
                {
                    return;
                }

                // Location
                Vector3 planet   = body.transform.position;
                Vector3 building = city.transform.position; // From body to city
                Vector3 location = (building - planet).normalized;

                // Sigma Dimensions Settings
                double resize          = body.Has("resize") ? body.Get <double>("resize") : 1;
                double landscape       = body.Has("landscape") ? body.Get <double>("landscape") : 1;
                double resizeBuildings = body.Has("resizeBuildings") ? body.Get <double>("resizeBuildings") : 1;

                // Max distance
                double maxDistance = Math.Abs(2 * pqs.mapMaxHeight);
                maxDistance *= resize * landscape > 1 ? resize * landscape : 1;
                maxDistance += body.Radius;

                RaycastHit[] hits = Physics.RaycastAll(planet + location * (float)maxDistance, -location, (float)maxDistance, LayerMask.GetMask("Local Scenery"));

                for (int i = 0; i < hits?.Length; i++)
                {
                    if (hits[i].collider?.GetComponent <PQ>())
                    {
                        Debug.Log("PQSCityFixer", "> Planet: " + body.transform.name);
                        Debug.Log("PQSCityFixer", "    > PQSCity: " + city);

                        // PQSCity parameters
                        double oldGroundLevel = pqs.GetSurfaceHeight(city.repositionRadial) - body.Radius;
                        Debug.Log("PQSCityFixer", "        > Old Ground Level at Mod (GETSURFACE) = " + oldGroundLevel);
                        double oldOceanOffset = body.ocean && oldGroundLevel < 0 ? oldGroundLevel : 0d;
                        Debug.Log("PQSCityFixer", "        > Old Ocean Offset at Mod = " + oldOceanOffset);
                        oldGroundLevel = body.ocean && oldGroundLevel < 0 ? 0d : oldGroundLevel;
                        Debug.Log("PQSCityFixer", "        > Old Ground Level at Mod (WITH OCEAN) = " + oldGroundLevel);

                        double groundLevel = (hits[i].point - planet).magnitude - body.Radius;
                        Debug.Log("PQSCityFixer", "        > Ground Level at Mod (RAYCAST) = " + groundLevel);
                        double oceanOffset = body.ocean && groundLevel < 0 ? groundLevel : 0d;
                        Debug.Log("PQSCityFixer", "        > Ocean Offset at Mod = " + oceanOffset);
                        groundLevel = body.ocean && groundLevel < 0 ? 0d : groundLevel;
                        Debug.Log("PQSCityFixer", "        > Ground Level at Mod (WITH OCEAN) = " + groundLevel);

                        // Fix Altitude
                        if (!city.repositionToSphere && !city.repositionToSphereSurface)
                        {
                            // Offset = Distance from the center of the planet
                            // THIS IS NOT POSSIBLE AS OF KSP 1.7.1

                            Debug.Log("PQSCityFixer", "        > PQSCity Current Center Offset = " + city.repositionRadiusOffset);

                            double builtInOffset = (city.repositionRadiusOffset - body.Radius - oldGroundLevel - oceanOffset) / resizeBuildings - (groundLevel + oceanOffset - oldGroundLevel - oldOceanOffset) / (resize * landscape);

                            Debug.Log("PQSCityFixer", "        > Builtin Offset = " + builtInOffset);

                            city.repositionRadiusOffset = body.Radius + groundLevel + oceanOffset + builtInOffset * resizeBuildings;

                            Debug.Log("PQSCityFixer", "        > PQSCity Fixed Center Offset = " + city.repositionRadiusOffset);
                        }
                        else if (city.repositionToSphere && !city.repositionToSphereSurface)
                        {
                            // Offset = Distance from the radius of the planet

                            Debug.Log("PQSCityFixer", "        > PQSCity Current Radius Offset = " + city.repositionRadiusOffset);

                            double builtInOffset = (city.repositionRadiusOffset - oldGroundLevel) / resizeBuildings - (groundLevel - oldGroundLevel) / (resize * landscape);

                            Debug.Log("PQSCityFixer", "        > Builtin Offset = " + builtInOffset);

                            city.repositionRadiusOffset = groundLevel + builtInOffset * resizeBuildings;

                            Debug.Log("PQSCityFixer", "        > PQSCity Fixed Radius Offset = " + city.repositionRadiusOffset);
                        }
                        else
                        {
                            // Offset = Distance from the surface of the planet

                            Debug.Log("PQSCityFixer", "        > PQSCity Current Surface Offset = " + city.repositionRadiusOffset);

                            double builtInOffset = city.repositionRadiusOffset / resizeBuildings - (groundLevel + oceanOffset - oldGroundLevel - oldOceanOffset) / (resize * landscape);

                            Debug.Log("PQSCityFixer", "        > Builtin Offset = " + builtInOffset);

                            city.repositionRadiusOffset = builtInOffset * resizeBuildings + groundLevel + oceanOffset - oldGroundLevel - oldOceanOffset;

                            Debug.Log("PQSCityFixer", "        > PQSCity Fixed Surface Offset = " + city.repositionRadiusOffset);
                        }

                        // Apply Changes and Destroy
                        city.Orientate();
                        DestroyImmediate(this);
                    }
                }
            }
        }
Example #24
0
        // Stuff
        void LateUpdate()
        {
            FixZooming();
            ApplyOrbitVisibility();
            RDFixer();
            ApplyOrbitIconCustomization();

            // Prevent the orbit lines from flickering
            PlanetariumCamera.Camera.farClipPlane = 1e14f;

            // Remove buttons in map view for barycenters
            if (MapView.MapIsEnabled)
            {
                if (fields == null)
                {
                    FieldInfo mode_f    = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType.IsEnum && f.FieldType.IsNested);
                    FieldInfo context_f = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType == typeof(MapContextMenu));
                    #if !KSP131
                    FieldInfo cast_f = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType == typeof(OrbitRendererBase.OrbitCastHit));
                    #else
                    FieldInfo cast_f = typeof(OrbitTargeter).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(f => f.FieldType == typeof(OrbitRenderer.OrbitCastHit));
                    #endif
                    fields = new FieldInfo[] { mode_f, context_f, cast_f };
                }
                if (FlightGlobals.ActiveVessel != null)
                {
                    OrbitTargeter targeter = FlightGlobals.ActiveVessel.orbitTargeter;
                    if (targeter == null)
                    {
                        return;
                    }
                    Int32 mode = (Int32)fields[0].GetValue(targeter);
                    if (mode == 2)
                    {
                        #if !KSP131
                        OrbitRendererBase.OrbitCastHit cast = (OrbitRendererBase.OrbitCastHit)fields[2].GetValue(targeter);
                        #else
                        OrbitRenderer.OrbitCastHit cast = (OrbitRenderer.OrbitCastHit)fields[2].GetValue(targeter);
                        #endif
                        CelestialBody body = PSystemManager.Instance.localBodies.Find(b => b.name == cast.or?.discoveryInfo?.name?.Value);
                        if (body == null)
                        {
                            return;
                        }
                        if (body.Has("barycenter") || !body.Get("selectable", true))
                        {
                            if (cast.driver?.Targetable == null)
                            {
                                return;
                            }
                            MapContextMenu context = MapContextMenu.Create(body.name, new Rect(0.5f, 0.5f, 300f, 50f), cast, () =>
                            {
                                fields[0].SetValue(targeter, 0);
                                fields[1].SetValue(targeter, null);
                            }, new SetAsTarget(cast.driver.Targetable, () => FlightGlobals.fetch.VesselTarget));
                            fields[1].SetValue(targeter, context);
                        }
                    }
                }
            }

            foreach (CelestialBody body in PSystemManager.Instance.localBodies)
            {
                if (body.afg == null)
                {
                    continue;
                }
                GameObject star_      = KopernicusStar.GetNearest(body).gameObject;
                Vector3    planet2cam = body.scaledBody.transform.position - body.afg.mainCamera.transform.position;
                body.afg.lightDot = Mathf.Clamp01(Vector3.Dot(planet2cam, body.afg.mainCamera.transform.position - star_.transform.position) * body.afg.dawnFactor);
                body.afg.GetComponent <Renderer>().sharedMaterial.SetFloat("_lightDot", body.afg.lightDot);
            }

            // Update the names of the presets in the settings dialog
            if (HighLogic.LoadedScene == GameScenes.SETTINGS)
            {
                foreach (SettingsTerrainDetail detail in Resources.FindObjectsOfTypeAll <SettingsTerrainDetail>())
                {
                    detail.displayStringValue = true;
                    detail.stringValues       = _details ?? (_details = Templates.PresetDisplayNames.ToArray());
                }
            }
        }