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 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); } } }
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); } } } }