Exemple #1
0
        void City2Fixer(PQSCity2 city)
        {
            Debug.Log("SigmaDimensions.City2Fixer", "    > PQSCity2: " + city.name);

            // Resize the Building
            city.transform.localScale *= (float)resizeBuildings;


            // Fix PQSCity Groups
            if (body.Has("PQSCityGroups"))
            {
                Dictionary <object, Vector3> PQSList = body.Get <Dictionary <object, Vector3> >("PQSCityGroups");
                if (PQSList.ContainsKey(city))
                {
                    GroupFixer(city, PQSList[city]);
                }
            }


            // Add PQSCity2Fixer Component
            PQSCity2Fixer fixer = city.GetComponent <PQSCity2Fixer>() ?? city.gameObject.AddComponent <PQSCity2Fixer>();


            // Terrain
            double groundLevel = body.pqsController.GetSurfaceHeight(city.PlanetRelativePosition) - body.Radius;
            double oceanDepth  = body.ocean && groundLevel < 0 ? -groundLevel : 0d;

            groundLevel = body.ocean && groundLevel < 0 ? 0d : groundLevel;


            // Fix Altitude
            if (!city.snapToSurface)
            {
                double builtInOffset = city.alt - groundLevel / (resize * landscape);

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

                // Offset = Distance from the radius of the planet

                Debug.Log("SigmaDimensions.City2Fixer", "        > PQSCity Original Radius Offset = " + city.alt);

                city.alt = groundLevel + builtInOffset * resizeBuildings;

                Debug.Log("SigmaDimensions.City2Fixer", "        > PQSCity Fixed Radius Offset = " + city.alt);
            }
            else
            {
                double builtInOffset = city.snapHeightOffset - oceanDepth / (resize * landscape);

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

                // Offset = Distance from the surface of the planet

                Debug.Log("SigmaDimensions.CityFixer", "        > PQSCity Original Surface Offset = " + city.snapHeightOffset);

                city.snapHeightOffset = oceanDepth + builtInOffset * resizeBuildings;

                Debug.Log("SigmaDimensions.CityFixer", "        > PQSCity Fixed Surface Offset = " + city.snapHeightOffset);
            }
        }
        private static void ApplyLaunchSitePatches()
        {
            #if !KSP131
            if (!ExpansionsLoader.IsExpansionInstalled("MakingHistory"))
            {
                return;
            }

            PQSCity2[] cities = FindObjectsOfType <PQSCity2>();
            for (Int32 i = 0; i < Templates.RemoveLaunchSites.Count; i++)
            {
                String site = Templates.RemoveLaunchSites[i];

                // Remove the launch site from the list if it exists
                if (PSystemSetup.Instance.LaunchSites.Any(s => s.name == site))
                {
                    PSystemSetup.Instance.RemoveLaunchSite(site);
                }

                PQSCity2 city = cities.FirstOrDefault(c =>
                {
                    GameObject o;
                    return((o = c.gameObject).name == site || o.name == site + "(Clone)");
                });

                // Kill the PQSCity if it exists
                if (city != null)
                {
                    Destroy(city.gameObject);
                }
            }

            // PSystemSetup.RemoveLaunchSite does not remove launch sites from PSystemSetup.StockLaunchSites
            // Currently an ArgumentOutOfRangeException can result when they are different lists because of a bug in stock code
            try
            {
                FieldInfo stockLaunchSitesField = typeof(PSystemSetup).GetField("stocklaunchsites", BindingFlags.NonPublic | BindingFlags.Instance);
                if (stockLaunchSitesField == null)
                {
                    return;
                }
                LaunchSite[] stockLaunchSites       = (LaunchSite[])stockLaunchSitesField.GetValue(PSystemSetup.Instance);
                LaunchSite[] updateStockLaunchSites = stockLaunchSites.Where(site => !Templates.RemoveLaunchSites.Contains(site.name)).ToArray();
                if (stockLaunchSites.Length != updateStockLaunchSites.Length)
                {
                    stockLaunchSitesField.SetValue(PSystemSetup.Instance, updateStockLaunchSites);
                }
            }
            catch (Exception ex)
            {
                Logger.Default.Log("Failed to remove launch sites from 'stockLaunchSites' field. Exception information follows.");
                Logger.Default.LogException(ex);
            }
            #endif
        }
Exemple #3
0
        void FixAltitude(object mod, double terrainShift, double fixAltitude)
        {
            Debug.Log("SigmaDimensions.FixAltitude", "        > Terrain Shift = " + terrainShift);

            string type = mod.GetType().ToString();

            if (type == "PQSCity")
            {
                PQSCity pqs = (PQSCity)mod;
                if (!pqs.repositionToSphere && !pqs.repositionToSphereSurface)
                {
                    pqs.repositionToSphereSurface = true;
                    pqs.repositionRadiusOffset    = 0;
                }
                if (pqs.repositionToSphereSurface && !pqs.repositionToSphereSurfaceAddHeight)
                {
                    pqs.repositionToSphereSurfaceAddHeight = true;
                    pqs.repositionRadiusOffset             = 0;
                }
                if (!pqs.repositionToSphereSurface)
                {
                    pqs.repositionRadiusOffset += terrainShift;
                }

                Debug.Log("SigmaDimensions.FixAltitude", "        > Mod original repositionRadiusOffset = " + pqs.repositionRadiusOffset);
                pqs.repositionRadiusOffset += fixAltitude;
                Debug.Log("SigmaDimensions.FixAltitude", "        > Fixed repositionRadiusOffset = " + pqs.repositionRadiusOffset);
            }
            else if (type == "PQSCity2")
            {
                PQSCity2 pqs = (PQSCity2)mod;
                if (pqs.snapToSurface)
                {
                    pqs.snapHeightOffset += fixAltitude;
                    Debug.Log("SigmaDimensions.FixAltitude", "        > Fixed snapHeightOffset = " + pqs.snapHeightOffset);
                }
                else
                {
                    pqs.alt += terrainShift + fixAltitude;
                    Debug.Log("SigmaDimensions.FixAltitude", "        > Fixed PQSCity2.alt = " + pqs.alt);
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Removes the wreck model from an KSC Object.
        /// </summary>
        internal static void MangleSquadStatic(GameObject gameObject)
        {
            gameObject.transform.parent = null;
            var transforms = gameObject.transform.GetComponentsInChildren <Transform>(true);

            foreach (var transform in transforms)
            {
                if (transform.name.Equals("wreck", StringComparison.InvariantCultureIgnoreCase))
                {
                    transform.parent = null;
                    GameObject.Destroy(transform.gameObject);
                }

                if (transform.name.Equals("commnetnode", StringComparison.InvariantCultureIgnoreCase))
                {
                    transform.parent = null;
                    GameObject.Destroy(transform.gameObject);
                }
            }

            PQSCity2 pqs2 = gameObject.GetComponent <PQSCity2>();

            if (pqs2 != null)
            {
                GameObject.Destroy(pqs2);
            }

            CommNet.CommNetHome cnhome = gameObject.GetComponent <CommNet.CommNetHome>();
            if (cnhome != null)
            {
                GameObject.Destroy(cnhome);
            }

            DestructibleBuilding destBuilding = gameObject.GetComponentInChildren <DestructibleBuilding>();

            if (destBuilding != null)
            {
                GameObject.Destroy(destBuilding);
            }
        }
        void City2Fixer(PQSCity2 pqs)
        {
            // Resize the Building

            pqs.transform.localScale *= (float)resizeBuildings;

            // Fix PQSCity Groups

            if (body.Has("PQSCityGroups"))
            {
                Dictionary<object, Vector3> PQSList = body.Get<Dictionary<object, Vector3>>("PQSCityGroups");
                if (PQSList.ContainsKey(pqs))
                {
                    GroupFixer(pqs, PQSList[pqs].normalized);
                }
            }

            // Fix Altitude

            if (!pqs.snapToSurface)
            {
                // Offset = Distance from the center of the planet

                double groundLevel = body.pqsController.GetSurfaceHeight(pqs.PlanetRelativePosition) - body.Radius;
                double fromRadius = pqs.alt - (body.Radius / resize);
                double builtInOffset = fromRadius - groundLevel / (resize * landscape);

                pqs.alt = body.Radius + groundLevel + builtInOffset * resizeBuildings;
            }
            else
            {
                // Offset = Distance from the surface of the planet

                pqs.snapHeightOffset *= resizeBuildings;
            }
        }
        internal static void AddPQSCenter2(string tgtName)
        {
            CelestialBody body   = ConfigUtil.GetCelestialBody("HomeWorld");
            var           mods   = body.pqsController.GetComponentsInChildren <PQSCity2>(true);
            PQSCity2      tgtPQS = null;

            foreach (var m in mods)
            {
                //Log.Normal("PQS2Name: " + m.name);
                if (m.name == tgtName)
                {
                    tgtPQS = m;
                    continue;
                }
            }
            if (tgtPQS == null)
            {
                Log.Normal("No BasePQS found: " + tgtName);
                return;
            }

            GroupCenter newGroup = new GroupCenter();

            newGroup.isBuiltIn     = true;
            newGroup.Group         = tgtName + "_Builtin";
            newGroup.CelestialBody = body;

            newGroup.RotationAngle  = (float)tgtPQS.rotation;
            newGroup.RadialPosition = KKMath.GetRadiadFromLatLng(body, tgtPQS.lat, tgtPQS.lon);

            //newGroup.RadiusOffset = (float)0;
            newGroup.RadiusOffset        = (float)tgtPQS.alt;
            newGroup.SeaLevelAsReference = true;
            //newGroup.repositionToSphere = tgtPQS.repositionToSphere;
            newGroup.Spawn();
        }
Exemple #7
0
            // Post apply event
            void IParserEventSubscriber.PostApply(ConfigNode node)
            {
                // Should we remove the atmosphere
                if (body.celestialBody.atmosphere && removeAtmosphere.Value)
                {
                    // Find atmosphere from ground and destroy the game object
                    AtmosphereFromGround atmosphere = body.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)[0];
                    atmosphere.transform.parent = null;
                    UnityEngine.Object.Destroy(atmosphere.gameObject);

                    // Destroy the light controller
                    MaterialSetDirection light = body.scaledVersion.GetComponentsInChildren <MaterialSetDirection>(true)[0];
                    UnityEngine.Object.Destroy(light);

                    // No more atmosphere :(
                    body.celestialBody.atmosphere = false;
                }

                // If we have a PQS
                if (body.pqsVersion != null)
                {
                    Logger.Active.Log("[Kopernicus]: Configuration.Template: Using Template \"" + body.celestialBody.bodyName + "\"");

                    // Should we remove the ocean?
                    if (body.celestialBody.ocean && removeOcean.Value)
                    {
                        // Find atmosphere the ocean PQS
                        PQS ocean = body.pqsVersion.GetComponentsInChildren <PQS>(true).Where(pqs => pqs != body.pqsVersion).First();
                        PQSMod_CelestialBodyTransform cbt = body.pqsVersion.GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).First();

                        // Destroy the ocean PQS (this could be bad - destroying the secondary fades...)
                        cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject);
                        cbt.secondaryFades     = null;
                        ocean.transform.parent = null;
                        UnityEngine.Object.Destroy(ocean);

                        // No more ocean :(
                        body.celestialBody.ocean = false;
                        body.pqsVersion.mapOcean = false;
                    }

                    // Selectively remove PQS Mods
                    if (removePQSMods != null && removePQSMods.Value.LongCount() > 0)
                    {
                        // We need a List with Types to remove
                        List <Type> mods = new List <Type>();
                        Dictionary <String, Type> modsPerName = new Dictionary <String, Type>();
                        foreach (String mod in removePQSMods.Value)
                        {
                            // If the definition has a name specified, grab that
                            String mType = mod;
                            String name  = "";
                            if (mType.EndsWith("]"))
                            {
                                String[] split = mType.Split('[');
                                mType = split[0];
                                name  = split[1].Remove(split[1].Length - 1);
                            }

                            // Get the mods matching the String
                            String modName = mType;
                            if (!mod.Contains("PQS"))
                            {
                                modName = "PQSMod_" + mod;
                            }
                            if (name == "")
                            {
                                //mods.Add(Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                                Type t = Parser.ModTypes.Find(m => m.Name == modName);
                                if (t != null)
                                {
                                    mods.Add(t);
                                }
                            }
                            else
                            {
                                //modsPerName.Add(name, Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                                Type t = Parser.ModTypes.Find(m => m.Name == modName);
                                if (t != null)
                                {
                                    modsPerName.Add(name, t);
                                }
                            }
                        }
                        Utility.RemoveModsOfType(mods, body.pqsVersion);
                        foreach (KeyValuePair <String, Type> kvP in modsPerName)
                        {
                            Int32  index = 0;
                            String name  = kvP.Key;
                            if (name.Contains(';'))
                            {
                                String[] split = name.Split(';');
                                name = split[0];
                                Int32.TryParse(split[1], out index);
                            }
                            PQSMod[] allMods = body.pqsVersion.GetComponentsInChildren(kvP.Value, true).Select(m => m as PQSMod).Where(m => m.name == name).ToArray();
                            if (allMods.Length > 0)
                            {
                                if (allMods[index] is PQSCity)
                                {
                                    PQSCity city = allMods[index] as PQSCity;
                                    if (city.lod != null)
                                    {
                                        foreach (PQSCity.LODRange range in city.lod)
                                        {
                                            if (range.objects != null)
                                            {
                                                foreach (GameObject o in range.objects)
                                                {
                                                    UnityEngine.Object.DestroyImmediate(o);
                                                }
                                            }
                                            if (range.renderers != null)
                                            {
                                                foreach (GameObject o in range.renderers)
                                                {
                                                    UnityEngine.Object.DestroyImmediate(o);
                                                }
                                            }
                                        }
                                    }
                                }
                                if (allMods[index] is PQSCity2)
                                {
                                    PQSCity2 city = allMods[index] as PQSCity2;
                                    if (city.objects != null)
                                    {
                                        foreach (PQSCity2.LodObject range in city.objects)
                                        {
                                            if (range.objects != null)
                                            {
                                                foreach (GameObject o in range.objects)
                                                {
                                                    UnityEngine.Object.DestroyImmediate(o);
                                                }
                                            }
                                        }
                                    }
                                }

                                // If no mod is left, delete the game object too
                                GameObject gameObject = allMods[index].gameObject;
                                UnityEngine.Object.DestroyImmediate(allMods[index]);
                                PQSMod[] allRemainingMods = gameObject.GetComponentsInChildren <PQSMod>(true);
                                if (allRemainingMods.Length == 0)
                                {
                                    UnityEngine.Object.DestroyImmediate(gameObject);
                                }
                            }
                        }
                    }

                    if (removeAllMods != null && removeAllMods.Value)
                    {
                        // Remove all mods
                        Utility.RemoveModsOfType(null, body.pqsVersion);
                    }
                }

                // Should we remove the progress tree
                if (removeProgressTree.Value)
                {
                    body.celestialBody.progressTree = null;
                }

                // Figure out what kind of body we are
                if (body.scaledVersion.GetComponentsInChildren <SunShaderController>(true).Length > 0)
                {
                    type = BodyType.Star;
                }
                else if (body.celestialBody.atmosphere)
                {
                    type = BodyType.Atmospheric;
                }
                else
                {
                    type = BodyType.Vacuum;
                }

                // remove coronas
                if (type == BodyType.Star && removeCoronas)
                {
                    foreach (SunCoronas corona in body.scaledVersion.GetComponentsInChildren <SunCoronas>(true))
                    {
                        corona.GetComponent <Renderer>().enabled = false; // RnD hard refs Coronas, so we need to disable them
                    }
                }

                // Event
                Events.OnTemplateLoaderPostApply.Fire(this, node);
            }
Exemple #8
0
        // Post apply event
        void IParserEventSubscriber.PostApply(ConfigNode node)
        {
            // Should we remove the atmosphere
            if (Body.celestialBody.atmosphere && RemoveAtmosphere.Value)
            {
                // Find atmosphere from ground and destroy the game object
                AtmosphereFromGround atmosphere =
                    Body.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)[0];
                atmosphere.transform.parent = null;
                Object.Destroy(atmosphere.gameObject);

                // Destroy the light controller
                MaterialSetDirection light = Body.scaledVersion.GetComponentsInChildren <MaterialSetDirection>(true)[0];
                Object.Destroy(light);

                // No more atmosphere :(
                Body.celestialBody.atmosphere = false;
            }

            Logger.Active.Log("Using Template \"" + Body.celestialBody.bodyName + "\"");

            // If we have a PQS
            if (Body.pqsVersion != null)
            {
#if (!KSP_VERSION_1_8)
                // We only support one surface material per body, so use the one with the highest quality available
                if (GameSettings.TERRAIN_SHADER_QUALITY == 3)
                {
                    Material surfaceMaterial = Body.pqsVersion.ultraQualitySurfaceMaterial;
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.highQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.mediumQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

                    Body.pqsVersion.ultraQualitySurfaceMaterial  = surfaceMaterial;
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }
#endif
                if (GameSettings.TERRAIN_SHADER_QUALITY == 2)
                {
                    Material surfaceMaterial = Body.pqsVersion.highQualitySurfaceMaterial;

                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.mediumQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

#if (!KSP_VERSION_1_8)
                    Body.pqsVersion.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }
                else if (GameSettings.TERRAIN_SHADER_QUALITY == 1)
                {
                    Material surfaceMaterial = Body.pqsVersion.mediumQualitySurfaceMaterial;

                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

#if (!KSP_VERSION_1_8)
                    Body.pqsVersion.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }
                else if (GameSettings.TERRAIN_SHADER_QUALITY == 0)
                {
                    Material surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;

                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

#if (!KSP_VERSION_1_8)
                    Body.pqsVersion.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }

                // Should we remove the ocean?
                if (Body.celestialBody.ocean)
                {
                    // Find atmosphere the ocean PQS
                    PQS ocean = Body.pqsVersion.GetComponentsInChildren <PQS>(true)
                                .First(pqs => pqs != Body.pqsVersion);
                    PQSMod_CelestialBodyTransform cbt = Body.pqsVersion
                                                        .GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).First();
#if (!KSP_VERSION_1_8)
                    if (GameSettings.TERRAIN_SHADER_QUALITY == 3)
                    {
                        Material surfaceMaterial = ocean.ultraQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.highQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.mediumQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
                        ocean.ultraQualitySurfaceMaterial  = surfaceMaterial;
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }
#endif
                    if (GameSettings.TERRAIN_SHADER_QUALITY == 2)
                    {
                        Material surfaceMaterial = ocean.highQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.mediumQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
#if (!KSP_VERSION_1_8)
                        ocean.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }
                    else if (GameSettings.TERRAIN_SHADER_QUALITY == 1)
                    {
                        Material surfaceMaterial = ocean.mediumQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
#if (!KSP_VERSION_1_8)
                        ocean.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }
                    else if (GameSettings.TERRAIN_SHADER_QUALITY == 0)
                    {
                        Material surfaceMaterial = ocean.lowQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
#if (!KSP_VERSION_1_8)
                        ocean.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }


                    if (RemoveOcean.Value)
                    {
                        // Destroy the ocean PQS (this could be bad - destroying the secondary fades...)
                        cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject);
                        cbt.secondaryFades     = null;
                        ocean.transform.parent = null;
                        Object.Destroy(ocean);

                        // No more ocean :(
                        Body.celestialBody.ocean = false;
                        Body.pqsVersion.mapOcean = false;
                    }
                }

                // Selectively remove PQS Mods
                if (RemovePqsMods != null && RemovePqsMods.Value.LongCount() > 0)
                {
                    // We need a List with Types to remove
                    List <Type> mods = new List <Type>();
                    Dictionary <String, Type> modsPerName = new Dictionary <String, Type>();
                    foreach (String mod in RemovePqsMods.Value)
                    {
                        // If the definition has a name specified, grab that
                        String mType = mod;
                        String mName = "";
                        if (mType.EndsWith("]"))
                        {
                            String[] split = mType.Split('[');
                            mType = split[0];
                            mName = split[1].Remove(split[1].Length - 1);
                        }

                        // Get the mods matching the String
                        String modName = mType;
                        if (!mod.Contains("PQS"))
                        {
                            modName = "PQSMod_" + mod;
                        }

                        if (mName == "")
                        {
                            //mods.Add(Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                            Type t = Parser.ModTypes.Find(m => m.Name == modName);
                            if (t != null)
                            {
                                mods.Add(t);
                            }
                        }
                        else
                        {
                            //modsPerName.Add(name, Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                            Type t = Parser.ModTypes.Find(m => m.Name == modName);
                            if (t != null)
                            {
                                modsPerName.Add(mName, t);
                            }
                        }
                    }

                    Utility.RemoveModsOfType(mods, Body.pqsVersion);
                    foreach (KeyValuePair <String, Type> kvP in modsPerName)
                    {
                        Int32  index   = 0;
                        String modName = kvP.Key;
                        if (modName.Contains(';'))
                        {
                            String[] split = modName.Split(';');
                            modName = split[0];
                            Int32.TryParse(split[1], out index);
                        }

                        PQSMod[] allMods = Body.pqsVersion.GetComponentsInChildren(kvP.Value, true)
                                           .OfType <PQSMod>().Where(m => m.name == modName).ToArray();
                        if (allMods.Length <= 0)
                        {
                            continue;
                        }
                        if (allMods[index] is PQSCity)
                        {
                            PQSCity city = (PQSCity)allMods[index];
                            if (city.lod != null)
                            {
                                foreach (PQSCity.LODRange range in city.lod)
                                {
                                    if (range.objects != null)
                                    {
                                        foreach (GameObject o in range.objects)
                                        {
                                            Object.DestroyImmediate(o);
                                        }
                                    }

                                    if (range.renderers == null)
                                    {
                                        continue;
                                    }
                                    {
                                        foreach (GameObject o in range.renderers)
                                        {
                                            Object.DestroyImmediate(o);
                                        }
                                    }
                                }
                            }
                        }

                        if (allMods[index] is PQSCity2)
                        {
                            PQSCity2 city = (PQSCity2)allMods[index];
                            if (city.objects != null)
                            {
                                foreach (PQSCity2.LodObject range in city.objects)
                                {
                                    if (range.objects == null)
                                    {
                                        continue;
                                    }
                                    foreach (GameObject o in range.objects)
                                    {
                                        Object.DestroyImmediate(o);
                                    }
                                }
                            }
                        }

                        // If no mod is left, delete the game object too
                        GameObject gameObject = allMods[index].gameObject;
                        Object.DestroyImmediate(allMods[index]);
                        PQSMod[] allRemainingMods = gameObject.GetComponentsInChildren <PQSMod>(true);
                        if (allRemainingMods.Length == 0)
                        {
                            Object.DestroyImmediate(gameObject);
                        }
                    }
                }

                if (RemoveAllMods != null && RemoveAllMods.Value)
                {
                    // Remove all mods
                    Utility.RemoveModsOfType(null, Body.pqsVersion);
                }
            }

            // Should we remove the progress tree
            if (RemoveProgressTree.Value)
            {
                Body.celestialBody.progressTree = null;
            }

            // Figure out what kind of body we are
            Boolean isStar = Body.scaledVersion.GetComponentsInChildren <SunShaderController>(true).Length > 0;

            // remove coronas
            if (isStar && RemoveCoronas)
            {
                foreach (SunCoronas corona in Body.scaledVersion.GetComponentsInChildren <SunCoronas>(true))
                {
                    // RnD hard refs Coronas, so we need to disable them
                    corona.GetComponent <Renderer>().enabled = false;
                }
            }

            // Event
            Events.OnTemplateLoaderPostApply.Fire(this, node);
        }
Exemple #9
0
        /// <summary>
        /// Will remove all mods of given types (or all, if types null)
        /// </summary>
        /// <param name="types">If null, will remove all mods except blacklisted mods</param>
        /// <param name="p">PQS to remove from</param>
        /// <param name="blacklist">list of mod types to not remove (optional)</param>
        public static void RemoveModsOfType(List <Type> types, PQS p, List <Type> blacklist = null)
        {
            Logger.Active.Log("Removing mods from pqs " + p.name);
            List <PQSMod> cpMods   = p.GetComponentsInChildren <PQSMod>(true).ToList();
            Boolean       addTypes = types == null;

            if (addTypes)
            {
                types = new List <Type>();
            }
            if (blacklist == null)
            {
                Logger.Active.Log("Creating blacklist");
                blacklist = new List <Type>();
                if (!types.Contains(typeof(PQSMod_CelestialBodyTransform)))
                {
                    blacklist.Add(typeof(PQSMod_CelestialBodyTransform));
                }
                if (!types.Contains(typeof(PQSMod_MaterialSetDirection)))
                {
                    blacklist.Add(typeof(PQSMod_MaterialSetDirection));
                }
                if (!types.Contains(typeof(PQSMod_UVPlanetRelativePosition)))
                {
                    blacklist.Add(typeof(PQSMod_UVPlanetRelativePosition));
                }
                if (!types.Contains(typeof(PQSMod_QuadMeshColliders)))
                {
                    blacklist.Add(typeof(PQSMod_QuadMeshColliders));
                }
                Logger.Active.Log("Blacklist count = " + blacklist.Count);
            }

            if (addTypes)
            {
                Logger.Active.Log("Adding all found PQSMods in pqs " + p.name);
                foreach (PQSMod m in cpMods)
                {
                    Type mType = m.GetType();
                    if (types.Contains(mType) || blacklist.Contains(mType))
                    {
                        continue;
                    }

                    Logger.Active.Log("Adding to remove list: " + mType);
                    types.Add(mType);
                }
            }
            List <GameObject> toCheck = new List <GameObject>();

            foreach (Type mType in types)
            {
                List <PQSMod> mods = cpMods.Where(m => m.GetType() == mType).ToList();
                foreach (PQSMod delMod in mods)
                {
                    if (delMod == null)
                    {
                        continue;
                    }

                    Logger.Active.Log("Removed mod " + mType);
                    if (!toCheck.Contains(delMod.gameObject))
                    {
                        toCheck.Add(delMod.gameObject);
                    }

                    delMod.sphere = null;
                    switch (delMod)
                    {
                    case PQSCity mod:
                    {
                        PQSCity city = mod;
                        if (city.lod != null)
                        {
                            foreach (PQSCity.LODRange range in city.lod)
                            {
                                if (range.objects != null)
                                {
                                    foreach (GameObject o in range.objects)
                                    {
                                        UnityEngine.Object.DestroyImmediate(o);
                                    }
                                }

                                if (range.renderers == null)
                                {
                                    continue;
                                }
                                foreach (GameObject o in range.renderers)
                                {
                                    UnityEngine.Object.DestroyImmediate(o);
                                }
                            }
                        }
                        break;
                    }

                    case PQSCity2 mod:
                    {
                        PQSCity2 city = mod;
                        if (city.objects != null)
                        {
                            foreach (PQSCity2.LodObject range in city.objects)
                            {
                                if (range.objects == null)
                                {
                                    continue;
                                }
                                foreach (GameObject o in range.objects)
                                {
                                    UnityEngine.Object.DestroyImmediate(o);
                                }
                            }
                        }
                        break;
                    }
                    }

                    cpMods.Remove(delMod);

                    // If no mod is left, delete the game object too
                    GameObject gameObject = delMod.gameObject;
                    UnityEngine.Object.DestroyImmediate(delMod);
                    PQSMod[] allRemainingMods = gameObject.GetComponentsInChildren <PQSMod>(true);
                    if (allRemainingMods.Length == 0)
                    {
                        UnityEngine.Object.DestroyImmediate(gameObject);
                    }
                }
            }
        }
        void FixAltitude()
        {
            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>())
                {
                    // Update only once
                    TimingManager.UpdateRemove(TimingManager.TimingStage.Normal, FixAltitude);
                    Debug.Log("PQSCity2Fixer", "> Planet: " + body.transform.name);
                    Debug.Log("PQSCity2Fixer", "    > PQSCity2: " + city);


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

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

                    // Fix Altitude
                    if (!city.snapToSurface)
                    {
                        // Offset = 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
                    {
                        Debug.Log("PQSCity2Fixer", "        > PQSCity2 Original Surface Offset = " + city.snapHeightOffset);

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

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

                    city.Orientate();
                    DestroyImmediate(this);
                }
            }
        }
Exemple #11
0
        // Execute MainMenu functions
        void Start()
        {
            previous = PlanetariumCamera.fetch.initialTarget;
            PlanetariumCamera.fetch.targets
            .Where(m => m.celestialBody != null && (m.celestialBody.Has("barycenter") || !m.celestialBody.Get("selectable", true)))
            .ToList()
            .ForEach(map => PlanetariumCamera.fetch.targets.Remove(map));

            // Stars
            GameObject     gob  = Sun.Instance.gameObject;
            KopernicusStar star = gob.AddComponent <KopernicusStar>();

            Utility.CopyObjectFields(Sun.Instance, star, false);
            DestroyImmediate(Sun.Instance);
            Sun.Instance = star;

            // LensFlares
            gob = SunFlare.Instance.gameObject;
            KopernicusSunFlare flare = gob.AddComponent <KopernicusSunFlare>();

            gob.name = star.sun.name;
            Utility.CopyObjectFields(SunFlare.Instance, flare, false);
            DestroyImmediate(SunFlare.Instance);
            SunFlare.Instance = star.lensFlare = flare;

            // Bodies
            Dictionary <String, KeyValuePair <CelestialBody, CelestialBody> > fixes = new Dictionary <String, KeyValuePair <CelestialBody, CelestialBody> >();

            foreach (CelestialBody body in PSystemManager.Instance.localBodies)
            {
                // More stars
                if (body.flightGlobalsIndex != 0 && body.scaledBody.GetComponentsInChildren <SunShaderController>(true).Length > 0)
                {
                    GameObject starObj = Instantiate(Sun.Instance.gameObject);
                    star     = starObj.GetComponent <KopernicusStar>();
                    star.sun = body;
                    starObj.transform.parent        = Sun.Instance.transform.parent;
                    starObj.name                    = body.name;
                    starObj.transform.localPosition = Vector3.zero;
                    starObj.transform.localRotation = Quaternion.identity;
                    starObj.transform.localScale    = Vector3.one;
                    starObj.transform.position      = body.position;
                    starObj.transform.rotation      = body.rotation;

                    GameObject flareObj = Instantiate(SunFlare.Instance.gameObject);
                    flare                            = flareObj.GetComponent <KopernicusSunFlare>();
                    star.lensFlare                   = flare;
                    flareObj.transform.parent        = SunFlare.Instance.transform.parent;
                    flareObj.name                    = body.name;
                    flareObj.transform.localPosition = Vector3.zero;
                    flareObj.transform.localRotation = Quaternion.identity;
                    flareObj.transform.localScale    = Vector3.one;
                    flareObj.transform.position      = body.position;
                    flareObj.transform.rotation      = body.rotation;
                }

                // Post spawn patcher
                if (body.Has("orbitPatches"))
                {
                    ConfigNode  orbitNode = body.Get <ConfigNode>("orbitPatches");
                    OrbitLoader loader    = new OrbitLoader(body);
                    Parser.LoadObjectFromConfigurationNode(loader, orbitNode, "Kopernicus");
                    CelestialBody oldRef = body.referenceBody;
                    body.referenceBody.orbitingBodies.Remove(body);

                    CelestialBody newRef = UBI.GetBody(loader.referenceBody);
                    if (newRef != null)
                    {
                        body.orbit.referenceBody = body.orbitDriver.referenceBody = newRef;
                    }
                    else
                    {
                        // 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();
                    }

                    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)
                    {
                        Double rotPeriod = Utility.FindBody(PSystemManager.Instance.systemPrefab.rootBody, body.transform.name).celestialBody.rotationPeriod;
                        Double num1      = Math.PI * 2 * Math.Sqrt(Math.Pow(Math.Abs(body.orbit.semiMajorAxis), 3) / body.orbit.referenceBody.gravParameter);
                        body.rotationPeriod = rotPeriod * num1 / (num1 + rotPeriod);;
                    }
                }
            }

            // 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.Clear();
            PlanetariumCamera.fetch.targets.AddRange(trackingstation);

            // Update the initialTarget of the tracking station
            Resources.FindObjectsOfTypeAll <PlanetariumCamera>().FirstOrDefault().initialTarget = Resources.FindObjectsOfTypeAll <ScaledMovement>().FirstOrDefault(o => o.celestialBody.isHomeWorld);

            // Undo stuff
            foreach (CelestialBody b in PSystemManager.Instance.localBodies.Where(b_ => b_.Has("orbitPatches")))
            {
                fixes[b.transform.name].Value.orbitingBodies.Remove(b);
                fixes[b.transform.name].Key.orbitingBodies.Add(b);
                fixes[b.transform.name].Key.orbitingBodies = fixes[b.transform.name].Key.orbitingBodies.OrderBy(cb => cb.orbit.semiMajorAxis).ToList();
            }


            #if !KSP131
            if (ExpansionsLoader.IsExpansionInstalled("MakingHistory"))
            {
                PQSCity2[] cities = FindObjectsOfType <PQSCity2>();
                foreach (String site in Templates.RemoveLaunchSites)
                {
                    // Remove the launch site from the list if it exists
                    if (PSystemSetup.Instance.LaunchSites.Any(s => s.name == site))
                    {
                        PSystemSetup.Instance.RemoveLaunchSite(site);
                    }

                    PQSCity2 city = cities.FirstOrDefault(c =>
                                                          c.gameObject.name == site || c.gameObject.name == site + "(Clone)");

                    // Kill the PQSCity if it exists
                    if (city != null)
                    {
                        Destroy(city.gameObject);
                    }
                }
                // PSystemSetup.RemoveLaunchSite does not remove launch sites from PSystemSetup.StockLaunchSites
                // Currently an ArgumentOutOfRangeException can result when they are different lists because of a bug in stock code
                try
                {
                    FieldInfo    stockLaunchSitesField  = typeof(PSystemSetup).GetField("stocklaunchsites", BindingFlags.NonPublic | BindingFlags.Instance);
                    LaunchSite[] stockLaunchSites       = (LaunchSite[])stockLaunchSitesField.GetValue(PSystemSetup.Instance);
                    LaunchSite[] updateStockLaunchSites = stockLaunchSites.Where(site => !Templates.RemoveLaunchSites.Contains(site.name)).ToArray();
                    if (stockLaunchSites.Length != updateStockLaunchSites.Length)
                    {
                        stockLaunchSitesField.SetValue(PSystemSetup.Instance, updateStockLaunchSites);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Default.Log("Failed to remove launch sites from 'stockLaunchSites' field. Exception information follows.");
                    Logger.Default.LogException(ex);
                }
            }
            #endif
#if FALSE
            // AFG-Ception
            foreach (CelestialBody body in PSystemManager.Instance.localBodies)
            {
                if (body.afg == null)
                {
                    continue;
                }

                foreach (KopernicusStar s in KopernicusStar.Stars)
                {
                    AtmosphereFromGround afg;
                    if (s != Sun.Instance)
                    {
                        afg = Instantiate(body.afg.gameObject)
                              .GetComponent <AtmosphereFromGround>();
                        Utility.CopyObjectFields(body.afg, afg, false);
                        afg.transform.parent        = body.afg.transform.parent;
                        afg.transform.localPosition = body.afg.transform.localPosition;
                        afg.transform.localScale    = body.afg.transform.localScale;
                        afg.transform.localRotation = body.afg.transform.localRotation;
                        afg.gameObject.layer        = body.afg.gameObject.layer;
                    }
                    else
                    {
                        afg = body.afg;
                    }

                    afg.gameObject.AddComponent <KopernicusStarAFG>().Star = s;
                }
            }
#endif
        }
        void Awake()
        {
            foreach (ConfigNode city in GameDatabase.Instance.GetConfigNodes("CITY"))
            {
                // check for a name, we need one
                if (!city.HasValue("name"))
                {
                    continue;
                }

                // create the new city
                GameObject cityObject = new GameObject();
                cityObject.name = city.GetValue("name");
                PQSCity2 pqsCity = cityObject.AddComponent <PQSCity2>();
                pqsCity.objectName = cityObject.name;

                // read and set values, using defaults when none are defined
                if (city.HasValue("verticalOffset"))
                {
                    pqsCity.alt = double.Parse(city.GetValue("verticalOffset"));
                    pqsCity.snapHeightOffset = double.Parse(city.GetValue("verticalOffset"));
                }
                CelestialBody body = FlightGlobals.GetHomeBody();
                if (city.HasValue("body"))
                {
                    body = FlightGlobals.GetBodyByName(city.GetValue("body"));
                }
                pqsCity.sphere = body.pqsController;
                if (city.HasValue("lat"))
                {
                    pqsCity.lat = double.Parse(city.GetValue("lat"));
                }
                if (city.HasValue("lon"))
                {
                    pqsCity.lon = double.Parse(city.GetValue("lon"));
                }
                if (city.HasValue("rotation"))
                {
                    pqsCity.rotation = double.Parse(city.GetValue("rotation"));
                }
                if (city.HasValue("snapToSurface"))
                {
                    pqsCity.snapToSurface = city.GetValue("snapToSurface").Equals("true", StringComparison.OrdinalIgnoreCase);
                }
                if (city.HasValue("displayName"))
                {
                    pqsCity.displayobjectName = city.GetValue("displayName");
                }
                else
                {
                    pqsCity.displayobjectName = cityObject.name;
                }

                // all the subnodes
                ConfigNode[] lods           = city.GetNodes("LOD");
                String[]     flagTransforms = city.GetValues("flagTransform");
                ConfigNode[] launchSites    = city.GetNodes("LAUNCHSITE");

                // load the LODs and models
                List <PQSCity2.LodObject> lodObjects = new List <PQSCity2.LodObject>();
                foreach (ConfigNode lod in lods)
                {
                    // create a new LodObject
                    PQSCity2.LodObject lodObject = new PQSCity2.LodObject();

                    // define the distance to stop rendering
                    if (lod.HasValue("visibleRange"))
                    {
                        lodObject.visibleRange = float.Parse(lod.GetValue("visibleRange"));
                    }
                    else
                    {
                        lodObject.visibleRange = 25000;
                    }

                    // read the models attached to this LOD
                    ConfigNode[]      models  = lod.GetNodes("MODEL");
                    List <GameObject> objects = new List <GameObject>();
                    foreach (ConfigNode model in models)
                    {
                        // make sure the model exists
                        if (!model.HasValue("model") | !GameDatabase.Instance.ExistsModel(model.GetValue("model")))
                        {
                            continue;
                        }

                        // get an instance of the model
                        GameObject modelInstance = GameDatabase.Instance.GetModel(model.GetValue("model"));

                        // attach it to the city
                        modelInstance.transform.parent = cityObject.transform;

                        // set the transform values if defined
                        if (model.HasValue("position"))
                        {
                            modelInstance.transform.localPosition = ConfigNode.ParseVector3(model.GetValue("position"));
                        }
                        if (model.HasValue("rotation"))
                        {
                            modelInstance.transform.localEulerAngles = ConfigNode.ParseVector3(model.GetValue("rotation"));
                        }
                        if (model.HasValue("scale"))
                        {
                            modelInstance.transform.localScale = ConfigNode.ParseVector3(model.GetValue("scale"));
                        }

                        // move to the local scenery layer
                        modelInstance.SetLayerRecursive(15);

                        // add the model to the list
                        //objects.Add(modelInstance);
                        modelInstance.SetActive(true);

                        // force all colliders to be concave
                        MeshCollider[] mColliders = modelInstance.GetComponentsInChildren <MeshCollider>(true);
                        foreach (MeshCollider collider in mColliders)
                        {
                            collider.convex = false;
                        }
                    }

                    // add the object list to the lodObject
                    lodObject.objects = objects.ToArray();

                    // add the lodObject to the lodObject list
                    lodObjects.Add(lodObject);
                }

                // add the LODs to the PQSCity
                pqsCity.objects = lodObjects.ToArray();

                // set the flag transforms
                if (flagTransforms.Length != 0)
                {
                    // add the flag handler component
                    CityFlag cityFlag = cityObject.AddComponent <CityFlag>();

                    // add each transform to the handler
                    foreach (string flagTransform in flagTransforms)
                    {
                        cityFlag.flagObjects.Add(CityUtils.FindChild(flagTransform, cityObject));
                    }
                }

                // finalize the PQSCity
                cityObject.transform.parent = body.pqsController.transform;
                pqsCity.Orientate();

                // add a CommNet antenna if defined
                if (city.HasNode("COMMNET"))
                {
                    // reference the confignode for future reference
                    ConfigNode commNet = city.GetNode("COMMNET");

                    // create the CommNetHome
                    CommNet.CommNetHome cNetHome = cityObject.AddComponent <CommNet.CommNetHome>();

                    // set the internal name
                    cNetHome.nodeName = cityObject.name;

                    // get the values from the config
                    if (commNet.HasValue("nodeName"))
                    {
                        cNetHome.displaynodeName = commNet.GetValue("nodeName");
                    }
                    else
                    {
                        cNetHome.displaynodeName = pqsCity.displayobjectName;
                    }
                    if (commNet.HasValue("antennaPower"))
                    {
                        cNetHome.antennaPower = double.Parse(commNet.GetValue("antennaPower"));
                    }
                    if (commNet.HasValue("isKSC"))
                    {
                        cNetHome.isKSC = commNet.GetValue("isKSC").Equals("true", StringComparison.OrdinalIgnoreCase);
                    }
                    if (commNet.HasValue("isPermanent"))
                    {
                        cNetHome.isPermanent = commNet.GetValue("isPermanent").Equals("true", StringComparison.OrdinalIgnoreCase);
                    }
                    if (city.HasValue("commNetTransform"))
                    {
                        cNetHome.nodeTransform = CityUtils.FindChild(city.GetValue("commNetTransform"), cityObject).transform;
                    }
                    else
                    {
                        cNetHome.nodeTransform = cityObject.transform;
                    }
                }

                // setup the launch sites (Making History required)
                foreach (ConfigNode site in launchSites)
                {
                    // we need a name
                    if (!site.HasValue("name"))
                    {
                        continue;
                    }

                    // create the spawnpoint
                    LaunchSite.SpawnPoint spawnPoint = new LaunchSite.SpawnPoint();
                    spawnPoint.name = site.GetValue("name");

                    // select the facility
                    EditorFacility facility = EditorFacility.VAB;
                    if (site.HasValue("facility") && site.GetValue("facility") == "SPH")
                    {
                        facility = EditorFacility.SPH;
                    }

                    // find and reparent the spawnTransform
                    // reparenting is done to ensure that it works
                    Transform spawnTransform = CityUtils.FindChild(site.GetValue("transform"), cityObject).transform;
                    spawnTransform.SetParent(cityObject.transform);

                    // create the launchsite
                    LaunchSite launchSite = new LaunchSite(site.GetValue("name"), body.pqsController.name, site.GetValue("title"), new LaunchSite.SpawnPoint[] { spawnPoint }, cityObject.name + "/" + spawnTransform.name, facility);

                    // change the mapIcon
                    // todo: remove mapIcon
                    if (facility == EditorFacility.VAB)
                    {
                        launchSite.nodeType = KSP.UI.Screens.Mapview.MapNode.SiteType.LaunchSite;
                    }
                    else
                    {
                        launchSite.nodeType = KSP.UI.Screens.Mapview.MapNode.SiteType.Runway;
                    }

                    // finalize the LaunchSite
                    launchSite.Setup(pqsCity, new PQS[] { body.pqsController });
                    PSystemSetup.Instance.AddLaunchSite(launchSite);
                }
            }
        }
        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);
                }
            }
        }
Exemple #14
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;
                }

                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 oldGroundLevel = pqs.GetSurfaceHeight(city.PlanetRelativePosition) - body.Radius;
                        Debug.Log("PQSCity2Fixer", "        > Old Ground Level at Mod (GETSURFACE) = " + oldGroundLevel);
                        double oldOceanOffset = body.ocean && oldGroundLevel < 0 ? oldGroundLevel : 0d;
                        Debug.Log("PQSCity2Fixer", "        > Old Ocean Offset at Mod = " + oldOceanOffset);
                        oldGroundLevel = body.ocean && oldGroundLevel < 0 ? 0d : oldGroundLevel;
                        Debug.Log("PQSCity2Fixer", "        > Old Ground Level at Mod (WITH OCEAN) = " + oldGroundLevel);

                        double groundLevel = (hits[i].point - planet).magnitude - body.Radius;
                        Debug.Log("PQSCity2Fixer", "        > Ground Level at Mod (RAYCAST) = " + groundLevel);
                        double oceanOffset = body.ocean && groundLevel < 0 ? groundLevel : 0d;
                        Debug.Log("PQSCity2Fixer", "        > Ocean Offset at Mod = " + oceanOffset);
                        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 - oldGroundLevel) / resizeBuildings - (groundLevel - oldGroundLevel) / (resize * landscape);

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

                            city.alt = groundLevel + builtInOffset * 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 builtInOffset = city.snapHeightOffset / resizeBuildings - (groundLevel + oceanOffset - oldGroundLevel - oldOceanOffset) / (resize * landscape);

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

                            double newOffset = builtInOffset * resizeBuildings + groundLevel + oceanOffset - oldGroundLevel - oldOceanOffset;

                            Debug.Log("PQSCity2Fixer", "        > PQSCity2 Fixed Surface Offset = " + newOffset);

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

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

                        // Apply Changes and Destroy
                        city.Orientate();
                        DestroyImmediate(this);
                    }
                }
            }
        }
        void LinkToKSC(PQSCity2 pqs)
        {
            PQSCity KSC = body.GetComponentsInChildren<PQSCity>().First(m => m.name == "KSC");
            LatLon movedKSC = new LatLon(KSC.repositionRadial.normalized);
            Vector3 reference = body.Get<Dictionary<object, Vector3>>("PQSCityGroups")[pqs].normalized;

            if (reference == movedKSC.vector)
            {
                // Fix Rotation
                float angle = KSC.reorientFinalAngle - (-15);
                pqs.rotation += angle;

                // Stock Vectors (KSC, North, East)
                LatLon stockKSC = new LatLon(new Vector3(157000, -1000, -570000).normalized);
                Vector3 north = Vector3.ProjectOnPlane(Vector3.up, stockKSC.vector);
                Vector3 east = QuaternionD.AngleAxis(90, stockKSC.vector) * north;

                // PQS Vectors (PQS, North, East)
                Vector3 oldPQS = Vector3.ProjectOnPlane(pqs.PlanetRelativePosition.normalized, stockKSC.vector);
                Vector3 pqsNorth = Vector3.Project(oldPQS, north);
                Vector3 pqsEast = Vector3.Project(oldPQS, east);

                // Distance from KSC (Northward, Eastward)
                float northward = pqsNorth.magnitude * (1 - (Vector3.Angle(north.normalized, pqsNorth.normalized) / 90));
                float eastward = pqsEast.magnitude * (1 - (Vector3.Angle(east.normalized, pqsEast.normalized) / 90));

                // New KSC Vectors (North, East)
                Vector3 newNorth = Vector3.ProjectOnPlane(Vector3.up, movedKSC.vector).normalized;
                Vector3 newEast = (QuaternionD.AngleAxis(90, movedKSC.vector) * newNorth);

                // Account for PQSCity rotation:
                // PQSCity rotate when their Longitude changes
                angle -= (float)(stockKSC.lon - movedKSC.lon);
                QuaternionD rotation = QuaternionD.AngleAxis(angle, movedKSC.vector);

                // Calculate final position by adding the north and east distances to the movedKSC position
                // then rotate the new vector by as many degrees as it is necessary to account for the PQS model rotation
                LatLon newPQS = new LatLon(rotation * (movedKSC.vector + newNorth * northward + newEast * eastward));
                pqs.lat = newPQS.lat;
                pqs.lon = newPQS.lon;

                // Fix Altitude
                if (!pqs.snapToSurface)
                {
                    pqs.alt += (body.pqsController.GetSurfaceHeight(movedKSC.vector) - body.Radius) / (resize * landscape) - 64.7846885412;
                }
            }
        }
        void GroupFixer(PQSCity2 pqs, Vector3 REFvector)
        {
            if (body == FlightGlobals.GetHomeBody())
                LinkToKSC(pqs);

            Vector3 PQSvector = pqs.PlanetRelativePosition.normalized;
            Vector3 NEWvector = Vector3.LerpUnclamped(REFvector, PQSvector, (float)(resizeBuildings / resize));
            LatLon NEWlatlon = new LatLon(NEWvector);
            pqs.lat = NEWlatlon.lat;
            pqs.lon = NEWlatlon.lon;
        }