Beispiel #1
0
        internal void UpdateRotation2Heading()
        {
            if (Heading >= 361f)
            {
                // legacy configs
                pqsCity.reorientFinalAngle = RotationAngle; //rotation x axis
            }
            else
            {
                // we are alligned to the 0 rotation, now we rotate until we got the real heading, then we messure the angle and then we update the internal Roation value
                Vector3    oldForeward = gameObject.transform.forward;
                Vector3    oldRight    = gameObject.transform.right;
                Quaternion oldRotation = gameObject.transform.rotation;

                Vector3    forward     = CelestialBody.GetRelSurfacePosition(RefLatitude, RefLongitude + CelestialBody.directRotAngle, RadiusOffset);
                Quaternion rotForward  = Quaternion.LookRotation(forward);
                Quaternion rotHeading  = Quaternion.Euler(0f, 0f, Heading);
                Quaternion halveInvert = Quaternion.Euler(-90f, -90f, -90f);

                Quaternion newRotation = rotForward * rotHeading * halveInvert;

                gameObject.transform.rotation = newRotation;

                float newfinalAngle = Vector3.Angle(oldForeward, gameObject.transform.forward);

                if (Vector3.Dot(gameObject.transform.forward, oldRight) < 0)
                {
                    newfinalAngle = (360 - newfinalAngle) % 360;
                }
                RotationAngle = newfinalAngle;
                pqsCity.reorientFinalAngle = newfinalAngle;
            }
            pqsCity.Orientate();
        }
        /// <summary>
        /// Updates the static instance with new settings
        /// </summary>
        public void Update()
        {
            if (pqsCity != null)
            {
                pqsCity.repositionRadial       = RadialPosition;
                pqsCity.repositionRadiusOffset = RadiusOffset;
                pqsCity.reorientInitialUp      = Orientation;
                pqsCity.reorientFinalAngle     = RotationAngle;
                pqsCity.transform.localScale   = origScale * ModelScale;

                switch (heighReference)
                {
                case HeightReference.Sphere:
                    pqsCity.repositionToSphereSurface          = false; //Snap to surface?
                    pqsCity.repositionToSphereSurfaceAddHeight = false;
                    pqsCity.repositionToSphere = true;
                    break;

                case HeightReference.Terrain:
                    pqsCity.repositionToSphereSurface          = true; //Snap to surface?
                    pqsCity.repositionToSphereSurfaceAddHeight = true;
                    pqsCity.repositionToSphere = false;
                    break;
                }
                pqsCity.ResetCelestialBody();
                pqsCity.Orientate();
            }
            // Notify modules about update
            foreach (StaticModule module in gameObject.GetComponents <StaticModule>())
            {
                module.StaticObjectUpdate();
            }
        }
 public void update()
 {
     if (pqsCity != null)
     {
         pqsCity.repositionRadial       = (Vector3)settings["RadialPosition"];
         pqsCity.repositionRadiusOffset = (float)settings["RadiusOffset"];
         pqsCity.reorientInitialUp      = (Vector3)settings["Orientation"];
         pqsCity.reorientFinalAngle     = (float)settings["RotationAngle"];
         pqsCity.Orientate();
     }
 }
Beispiel #4
0
 public void Reorientate()
 {
     if (PQSCityComponent == null)
     {
         return;
     }
     PQSCityComponent.repositionRadial       = RadPosition;
     PQSCityComponent.repositionRadiusOffset = RadOffset;
     PQSCityComponent.reorientFinalAngle     = RotAngle;
     PQSCityComponent.reorientInitialUp      = Orientation;
     PQSCityComponent.Orientate();
 }
        internal void Spawn()
        {
            if (StaticDatabase.allCenters.ContainsKey(dbKey))
            {
                string oldName = Group;
                int    index   = 0;
                while (StaticDatabase.allCenters.ContainsKey(dbKey))
                {
                    Group = oldName + "_" + index.ToString();
                    index++;
                }
            }

            gameObject      = new GameObject();
            gameObject.name = Group + "_PQS";

            pqsCity = gameObject.AddComponent <PQSCity>();

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers    = new GameObject[0],
                objects      = new GameObject[0],
                visibleRange = 25000
            };
            pqsCity.lod                    = new[] { range };
            pqsCity.frameDelta             = 10000;          //update interval for its own visiblility range checking. unused by KK, so set this to a high value
            pqsCity.repositionRadial       = RadialPosition; //position
            pqsCity.repositionRadiusOffset = RadiusOffset;   //height
            pqsCity.reorientInitialUp      = Orientation;    //orientation
            pqsCity.reorientFinalAngle     = RotationAngle;  //rotation x axis
            pqsCity.reorientToSphere       = true;           //adjust rotations to match the direction of gravity
            pqsCity.sphere                 = CelestialBody.pqsController;
            pqsCity.order                  = 100;
            pqsCity.modEnabled             = true;
            pqsCity.transform.parent       = CelestialBody.pqsController.transform;

            pqsCity.repositionToSphereSurface          = true; //Snap to surface?
            pqsCity.repositionToSphereSurfaceAddHeight = true;
            pqsCity.repositionToSphere = false;

            pqsCity.OnSetup();
            pqsCity.Orientate();

            RefLatitude  = KKMath.GetLatitudeInDeg(RadialPosition);
            RefLongitude = KKMath.GetLongitudeInDeg(RadialPosition);

            StaticDatabase.allCenters.Add(dbKey, this);
        }
 /// <summary>
 /// Updates the static instance with new settings
 /// </summary>
 public void update()
 {
     if (pqsCity != null)
     {
         pqsCity.repositionRadial       = RadialPosition;
         pqsCity.repositionRadiusOffset = RadiusOffset;
         pqsCity.reorientInitialUp      = Orientation;
         pqsCity.reorientFinalAngle     = RotationAngle;
         pqsCity.transform.localScale   = origScale * ModelScale;
         pqsCity.Orientate();
     }
     // Notify modules about update
     foreach (StaticModule module in gameObject.GetComponents <StaticModule>())
     {
         module.StaticObjectUpdate();
     }
 }
        internal void Update()
        {
            if (pqsCity != null)
            {
                pqsCity.repositionRadial                   = RadialPosition;
                pqsCity.repositionRadiusOffset             = RadiusOffset;
                pqsCity.reorientInitialUp                  = Orientation;
                pqsCity.reorientFinalAngle                 = RotationAngle;
                pqsCity.transform.localScale               = origScale * ModelScale;
                pqsCity.repositionToSphereSurface          = true; //Snap to surface?
                pqsCity.repositionToSphereSurfaceAddHeight = true;
                pqsCity.repositionToSphere                 = false;

                pqsCity.Orientate();
            }
            // Notify modules about update
            foreach (StaticModule module in gameObject.GetComponentsInChildren <StaticModule>((true)))
            {
                module.StaticObjectUpdate();
            }
        }
        void FixAltitude()
        {
            CelestialBody body = FlightGlobals.currentMainBody;

            if (body == null)
            {
                return;
            }

            PQS pqs = body.pqsController;

            if (pqs == null)
            {
                return;
            }

            PQSCity city = GetComponent <PQSCity>();

            if (city == null)
            {
                return;
            }

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

                    city.Orientate();
                    DestroyImmediate(this);
                }
            }
        }
        public void spawnObject(Boolean editing, Boolean bPreview)
        {
            // Objects spawned at runtime should be active, ones spawned at loading not
            SetActiveRecursively(gameObject, editing);

            Transform[] gameObjectList = gameObject.GetComponentsInChildren<Transform>();
            List<GameObject> rendererList = (from t in gameObjectList where t.gameObject.renderer != null select t.gameObject).ToList();

            setLayerRecursively(gameObject, 15);

            if (bPreview) this.ToggleAllColliders(false);

            this.preview = bPreview;

            if (editing) KerbalKonstructs.instance.selectObject(this, true, true, bPreview);

            float objvisibleRange = (float)getSetting("VisibilityRange");

            if (objvisibleRange < 1) objvisibleRange = 25000f;

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers = rendererList.ToArray(),
                objects = new GameObject[0],
                visibleRange = objvisibleRange
            };

            pqsCity = gameObject.AddComponent<PQSCity>();
            pqsCity.lod = new[] { range };
            pqsCity.frameDelta = 1; //Unknown
            pqsCity.repositionToSphere = true; //enable repositioning
            pqsCity.repositionToSphereSurface = false; //Snap to surface?
            pqsCity.repositionRadial = (Vector3)getSetting("RadialPosition"); //position
            pqsCity.repositionRadiusOffset = (float)getSetting("RadiusOffset"); //height
            pqsCity.reorientInitialUp = (Vector3)getSetting("Orientation"); //orientation
            pqsCity.reorientFinalAngle = (float)getSetting("RotationAngle"); //rotation x axis
            pqsCity.reorientToSphere = true; //adjust rotations to match the direction of gravity
            gameObject.transform.parent = ((CelestialBody)getSetting("CelestialBody")).pqsController.transform;
            pqsCity.sphere = ((CelestialBody)getSetting("CelestialBody")).pqsController;
            pqsCity.order = 100;
            pqsCity.modEnabled = true;
            pqsCity.OnSetup();
            pqsCity.Orientate();

            foreach (StaticModule module in model.modules)
            {
                Type moduleType = AssemblyLoader.loadedAssemblies.SelectMany(asm => asm.assembly.GetTypes()).FirstOrDefault(t => t.Namespace == module.moduleNamespace && t.Name == module.moduleClassname);
                MonoBehaviour mod = gameObject.AddComponent(moduleType) as MonoBehaviour;

                if (mod != null)
                {
                    foreach (string fieldName in module.moduleFields.Keys)
                    {
                        FieldInfo field = mod.GetType().GetField(fieldName);
                        if (field != null)
                        {
                            field.SetValue(mod, Convert.ChangeType(module.moduleFields[fieldName], field.FieldType));
                        }
                        else
                        {
                            Debug.Log("KK: WARNING: Field " + fieldName + " does not exist in " + module.moduleClassname);
                        }
                    }
                }
                else
                {
                    Debug.Log("KK: WARNING: Module " + module.moduleClassname + " could not be loaded in " + gameObject.name);
                }
            }

            foreach (GameObject gorenderer in rendererList)
            {
                gorenderer.renderer.enabled = true;
            }
        }
Beispiel #10
0
        internal void Spawn()
        {
            if (StaticDatabase.HasGroupCenter(dbKey))
            {
                string oldName = Group;
                int    index   = 0;
                while (StaticDatabase.HasGroupCenter(dbKey))
                {
                    Group = oldName + "_" + index.ToString();
                    index++;
                }
            }

            gameObject = new GameObject();
            GameObject.DontDestroyOnLoad(gameObject);

            CelestialBody.CBUpdate();


            gameObject.name = Group;
            //gameObject.name = "SpaceCenter";

            pqsCity = gameObject.AddComponent <PQSCity>();

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers    = new GameObject[0],
                objects      = new GameObject[0],
                visibleRange = 25000
            };
            pqsCity.lod        = new[] { range };
            pqsCity.frameDelta = 10000; //update interval for its own visiblility range checking. unused by KK, so set this to a high value

            if (RadialPosition == Vector3.zero)
            {
                if ((RefLatitude != 361d) && (RefLongitude != 361d))
                {
                    RadialPosition = KKMath.GetRadiadFromLatLng(CelestialBody, RefLatitude, RefLongitude);
                }
                else
                {
                    Log.UserError("No Valid Position found for Group: " + Group);
                }
            }
            else
            if ((RefLatitude == 361d) || (RefLongitude == 361d))
            {
                {
                    RefLatitude  = KKMath.GetLatitudeInDeg(RadialPosition);
                    RefLongitude = KKMath.GetLongitudeInDeg(RadialPosition);
                }
            }

            pqsCity.reorientFinalAngle = 0;
            pqsCity.repositionRadial   = RadialPosition;   //position

            pqsCity.repositionRadiusOffset = RadiusOffset; //height
            pqsCity.reorientInitialUp      = Orientation;  //orientation
            pqsCity.reorientToSphere       = true;         //adjust rotations to match the direction of gravity
            pqsCity.sphere           = CelestialBody.pqsController;
            pqsCity.order            = 100;
            pqsCity.modEnabled       = true;
            pqsCity.transform.parent = CelestialBody.pqsController.transform;

            pqsCity.repositionToSphereSurfaceAddHeight = false;
            pqsCity.repositionToSphereSurface          = false;
            SetReference();

            pqsCity.OnSetup();
            pqsCity.Orientate();

            UpdateRotation2Heading();

            StaticDatabase.AddGroupCenter(this);
        }
        /// <summary>
        /// Spawns a new Instance in the Gameworld and registers itself to the Static Database
        /// </summary>
        /// <param name="editing"></param>
        /// <param name="bPreview"></param>
        internal void spawnObject(Boolean editing, Boolean bPreview)
        {
            // mangle Squads statics
            if (model.isSquad)
            {
                InstanceUtil.MangleSquadStatic(gameObject);
            }

            // Objects spawned at runtime should be active, ones spawned at loading not
            InstanceUtil.SetActiveRecursively(this, editing);

            Transform[]       gameObjectList = gameObject.GetComponentsInChildren <Transform>();
            List <GameObject> rendererList   = (from t in gameObjectList where t.gameObject.GetComponent <Renderer>() != null select t.gameObject).ToList();

            setLayerRecursively(gameObject, 15);

            if (bPreview)
            {
                this.ToggleAllColliders(false);
            }

            this.preview = bPreview;

            if (editing)
            {
                KerbalKonstructs.instance.selectObject(this, true, true, bPreview);
            }

            float objvisibleRange = VisibilityRange;

            if (objvisibleRange < 1)
            {
                objvisibleRange = 25000f;
            }

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers    = new GameObject[0],
                objects      = new GameObject[0],
                visibleRange = objvisibleRange
            };

            pqsCity                           = gameObject.AddComponent <PQSCity>();
            pqsCity.lod                       = new[] { range };
            pqsCity.frameDelta                = 10000;          //update interval for its own visiblility range checking. unused by KK, so set this to a high value
            pqsCity.repositionRadial          = RadialPosition; //position
            pqsCity.repositionRadiusOffset    = RadiusOffset;   //height
            pqsCity.reorientInitialUp         = Orientation;    //orientation
            pqsCity.reorientFinalAngle        = RotationAngle;  //rotation x axis
            pqsCity.reorientToSphere          = true;           //adjust rotations to match the direction of gravity
            gameObject.transform.parent       = CelestialBody.pqsController.transform;
            pqsCity.sphere                    = CelestialBody.pqsController;
            origScale                         = pqsCity.transform.localScale; // save the original scale for later use
            pqsCity.transform.localScale     *= ModelScale;
            pqsCity.order                     = 100;
            pqsCity.modEnabled                = true;
            pqsCity.repositionToSphere        = true;  //enable repositioning
            pqsCity.repositionToSphereSurface = false; //Snap to surface?



            CelestialBody.pqsController.GetSurfaceHeight(RadialPosition);

            pqsCity.OnSetup();
            pqsCity.Orientate();



            //PQSCity2.LodObject lodObject = new PQSCity2.LodObject();
            //lodObject.visibleRange = VisibilityRange;
            //lodObject.objects = new GameObject[] { };
            //pqsCity2 = gameObject.AddComponent<PQSCity2>();
            //pqsCity2.objects = new [] { lodObject } ;
            //pqsCity2.objectName = "";
            //pqsCity2.lat = RefLatitude;
            //pqsCity2.lon = RefLongitude;
            //pqsCity2.alt = RadiusOffset;
            //pqsCity2.up = Orientation;
            //pqsCity2.rotation = RotationAngle;
            //pqsCity2.sphere = CelestialBody.pqsController;


            //pqsCity2.OnSetup();
            //pqsCity2.Orientate();


            foreach (StaticModule module in model.modules)
            {
                Type          moduleType = AssemblyLoader.loadedAssemblies.SelectMany(asm => asm.assembly.GetTypes()).FirstOrDefault(t => t.Namespace == module.moduleNamespace && t.Name == module.moduleClassname);
                MonoBehaviour mod        = gameObject.AddComponent(moduleType) as MonoBehaviour;

                if (mod != null)
                {
                    foreach (string fieldName in module.moduleFields.Keys)
                    {
                        FieldInfo field = mod.GetType().GetField(fieldName);
                        if (field != null)
                        {
                            field.SetValue(mod, Convert.ChangeType(module.moduleFields[fieldName], field.FieldType));
                        }
                        else
                        {
                            Log.UserWarning("Field " + fieldName + " does not exist in " + module.moduleClassname);
                        }
                    }
                }
                else
                {
                    Log.UserError("Module " + module.moduleClassname + " could not be loaded in " + gameObject.name);
                }
            }

            foreach (GameObject gorenderer in rendererList)
            {
                gorenderer.GetComponent <Renderer>().enabled = true;
            }

            StaticDatabase.AddStatic(this);

            // Add them to the bodys objectlist, so they show up as anomalies
            // After we got a new Name from StaticDatabase.AddStatic()
            if (isScanable)
            {
                Log.Normal("Added " + gameObject.name + " to scanable Objects");
                var pqsObjectList = CelestialBody.pqsSurfaceObjects.ToList();
                pqsObjectList.Add(pqsCity as PQSSurfaceObject);
                CelestialBody.pqsSurfaceObjects = pqsObjectList.ToArray();
            }
        }
        public void spawnObject(Boolean editing, Boolean bPreview)
        {
            // Objects spawned at runtime should be active, ones spawned at loading not
            SetActiveRecursively(gameObject, editing);

            Transform[]       gameObjectList = gameObject.GetComponentsInChildren <Transform>();
            List <GameObject> rendererList   = (from t in gameObjectList where t.gameObject.GetComponent <Renderer>() != null select t.gameObject).ToList();

            setLayerRecursively(gameObject, 15);

            if (bPreview)
            {
                this.ToggleAllColliders(false);
            }

            this.preview = bPreview;

            if (editing)
            {
                KerbalKonstructs.instance.selectObject(this, true, true, bPreview);
            }

            float objvisibleRange = (float)getSetting("VisibilityRange");

            if (objvisibleRange < 1)
            {
                objvisibleRange = 25000f;
            }

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers    = rendererList.ToArray(),
                objects      = new GameObject[0],
                visibleRange = objvisibleRange
            };

            pqsCity                           = gameObject.AddComponent <PQSCity>();
            pqsCity.lod                       = new[] { range };
            pqsCity.frameDelta                = 1;                                     //Unknown
            pqsCity.repositionToSphere        = true;                                  //enable repositioning
            pqsCity.repositionToSphereSurface = false;                                 //Snap to surface?
            pqsCity.repositionRadial          = (Vector3)getSetting("RadialPosition"); //position
            pqsCity.repositionRadiusOffset    = (float)getSetting("RadiusOffset");     //height
            pqsCity.reorientInitialUp         = (Vector3)getSetting("Orientation");    //orientation
            pqsCity.reorientFinalAngle        = (float)getSetting("RotationAngle");    //rotation x axis
            pqsCity.reorientToSphere          = true;                                  //adjust rotations to match the direction of gravity
            gameObject.transform.parent       = ((CelestialBody)getSetting("CelestialBody")).pqsController.transform;
            pqsCity.sphere                    = ((CelestialBody)getSetting("CelestialBody")).pqsController;
            pqsCity.order                     = 100;
            pqsCity.modEnabled                = true;
            pqsCity.OnSetup();
            pqsCity.Orientate();

            foreach (StaticModule module in model.modules)
            {
                Type          moduleType = AssemblyLoader.loadedAssemblies.SelectMany(asm => asm.assembly.GetTypes()).FirstOrDefault(t => t.Namespace == module.moduleNamespace && t.Name == module.moduleClassname);
                MonoBehaviour mod        = gameObject.AddComponent(moduleType) as MonoBehaviour;

                if (mod != null)
                {
                    foreach (string fieldName in module.moduleFields.Keys)
                    {
                        FieldInfo field = mod.GetType().GetField(fieldName);
                        if (field != null)
                        {
                            field.SetValue(mod, Convert.ChangeType(module.moduleFields[fieldName], field.FieldType));
                        }
                        else
                        {
                            Debug.Log("KK: WARNING: Field " + fieldName + " does not exist in " + module.moduleClassname);
                        }
                    }
                }
                else
                {
                    Debug.Log("KK: WARNING: Module " + module.moduleClassname + " could not be loaded in " + gameObject.name);
                }
            }

            foreach (GameObject gorenderer in rendererList)
            {
                gorenderer.GetComponent <Renderer>().enabled = true;
            }
        }
        private void LegacySpawnInstance()
        {
            float objvisibleRange = VisibilityRange;

            if (objvisibleRange < 1)
            {
                objvisibleRange = KerbalKonstructs.localGroupRange;
            }

            pqsCity = gameObject.AddComponent <PQSCity>();

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers    = new GameObject[0],
                objects      = new GameObject[0],
                visibleRange = objvisibleRange
            };
            pqsCity.lod                    = new[] { range };
            pqsCity.frameDelta             = 10000;          //update interval for its own visiblility range checking. unused by KK, so set this to a high value
            pqsCity.repositionRadial       = RadialPosition; //position
            pqsCity.repositionRadiusOffset = RadiusOffset;   //height
            pqsCity.reorientInitialUp      = Orientation;    //orientation
            pqsCity.reorientFinalAngle     = RotationAngle;  //rotation x axis
            pqsCity.reorientToSphere       = true;           //adjust rotations to match the direction of gravity
            gameObject.transform.parent    = CelestialBody.pqsController.transform;
            pqsCity.sphere                 = CelestialBody.pqsController;
            pqsCity.order                  = 100;
            pqsCity.modEnabled             = true;
            pqsCity.repositionToSphere     = true; //enable repositioning


            switch (heighReference)
            {
            case HeightReference.Sphere:
                pqsCity.repositionToSphereSurface = false;     //Snap to surface?

                break;

            case HeightReference.Terrain:

                pqsCity.repositionToSphereSurface          = true; //Snap to surface?
                pqsCity.repositionToSphereSurfaceAddHeight = true;
                pqsCity.repositionToSphere = false;
                break;

            default:
                // we try to descide which one is the best to take
                string biome = ScienceUtil.GetExperimentBiome(CelestialBody, RefLatitude, RefLongitude);
                float  heightAboveTerrain = SDRescale.GetSurfaceRefereceHeight(this);

                if ((biome == "Water" || biome == "Shores") && ((Math.Abs(RadiusOffset) < 5) && heightAboveTerrain > 5))     // most likely at ocean surface
                {
                    Log.Normal("Found a swimming object: " + this.gameObject.name);
                    pqsCity.repositionToSphereSurface = false;     //Snap to surface?
                    heighReference = HeightReference.Sphere;
                }
                else
                {
                    {
                        //    Log.Normal("found new Radiusffset: " + heightAboveTerrain);
                        RadiusOffset = heightAboveTerrain;
                        pqsCity.repositionToSphereSurface          = true; //Snap to surface?#
                        pqsCity.repositionToSphereSurfaceAddHeight = true;
                        pqsCity.repositionRadiusOffset             = heightAboveTerrain;
                        pqsCity.repositionToSphere = false;

                        heighReference = HeightReference.Terrain;
                    }
                }
                break;
            }
            pqsCity.OnSetup();
            pqsCity.Orientate();

            KerbalKonstructs.convertLegacyConfigs = true;
        }
        void Update()
        {
            if (time < 0.2)
            {
                time += Time.deltaTime;
            }
            else
            {
                time = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                            city.repositionRadiusOffset = groundLevel + builtInOffset * resizeBuildings;

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

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

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

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

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

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

                        // Apply Changes and Destroy
                        city.Orientate();
                        DestroyImmediate(this);
                    }
                }
            }
        }