/// <summary> /// Updates the target position and emits the particles /// </summary> private void Update() { // Update the values emitter.material.mainTexture = mainTexture; var sh = emitter.ps.shape; sh.mesh = mesh; // We have a target if (target != "None") { if (!TargetTransform) { TargetTransform = UBI.GetBody(target).scaledBody.transform; } Vector3 speed = TargetTransform.position; speed -= transform.parent.position; speed *= speedScale; emitter.minEnergy = minEnergy / TimeWarp.CurrentRate; emitter.maxEnergy = maxEnergy / TimeWarp.CurrentRate; emitter.maxEmission = Convert.ToInt32(maxEmission * TimeWarp.CurrentRate); emitter.minEmission = Convert.ToInt32(minEmission * TimeWarp.CurrentRate); emitter.rndVelocity = randomVelocity * TimeWarp.CurrentRate; speed *= TimeWarp.CurrentRate; emitter.worldVelocity = speed; } transform.localScale = scale; }
public void Reset(UBI ubi) { currentBlock = Arrays.Clone(ubi.currentBlock, currentBlock); currentOffset = ubi.currentOffset; message = Arrays.Clone(ubi.message, this.message); tweak.Reset(ubi.tweak); }
public void Reset(UBI ubi) { currentBlock = ubi.currentBlock.DeepCopy(); currentOffset = ubi.currentOffset; message = ubi.message.DeepCopy(); tweak.Reset(ubi.tweak); }
/// <summary> /// Updates the target position and emits the particles /// </summary> private void Update() { // Update the values emitter.minSize = minSize; emitter.maxSize = maxSize; animator.sizeGrow = sizeGrow; animator.colorAnimation = colorAnimation; renderer.sharedMaterial.mainTexture = mainTexture; filter.mesh = filter.sharedMesh = mesh ? mesh : transform.parent.GetComponent <MeshFilter>().sharedMesh; animator.force = force; // We have a target if (target != "None") { if (!TargetTransform) { TargetTransform = UBI.GetBody(target).scaledBody.transform; } Vector3 speed = TargetTransform.position; speed -= transform.parent.position; speed *= speedScale; emitter.minEnergy = minEnergy / TimeWarp.CurrentRate; emitter.maxEnergy = maxEnergy / TimeWarp.CurrentRate; emitter.maxEmission = maxEmission * TimeWarp.CurrentRate; emitter.minEmission = minEmission * TimeWarp.CurrentRate; emitter.rndVelocity = randomVelocity * TimeWarp.CurrentRate; speed *= TimeWarp.CurrentRate; emitter.worldVelocity = speed; } transform.localScale = scale; }
public SkeinEngine(int blockSizeBits, int outputSizeBits) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (outputSizeBits % 8 != 0) { throw new ArgumentException(string.Concat((object)"Output size must be a multiple of 8 bits. :", (object)outputSizeBits)); } outputSizeBytes = outputSizeBits / 8; threefish = new ThreefishEngine(blockSizeBits); ubi = new UBI(this, threefish.GetBlockSize()); }
/// <summary> /// Constructs a Skein digest with an internal state size and output size. /// </summary> /// <param name="blockSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or /// <see cref="SKEIN_1024"/>.</param> /// <param name="outputSizeBits">the output/digest size to produce in bits, which must be an integral number of /// bytes.</param> public SkeinEngine(int blockSizeBits, int outputSizeBits) { if (outputSizeBits % 8 != 0) { throw new ArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits); } // TODO: Prevent digest sizes > block size? this.outputSizeBytes = outputSizeBits / 8; this.threefish = new ThreefishEngine(blockSizeBits); this.ubi = new UBI(this, threefish.GetBlockSize()); }
// Transforms body references in the save games private static void TransformBodyReferencesOnSave(GameEvents.FromToAction <ProtoVessel, ConfigNode> data) { // Save the reference to the real body if (data.to == null) { return; } ConfigNode orbit = data.to.GetNode("ORBIT"); CelestialBody body = PSystemManager.Instance.localBodies.FirstOrDefault(b => b.flightGlobalsIndex == data.from.orbitSnapShot.ReferenceBodyIndex); if (body == null) { return; } orbit.AddValue("IDENT", UBI.GetUBI(body)); }
// Transforms body references in the save games private static void TransformBodyReferencesOnLoad(GameEvents.FromToAction <ProtoVessel, ConfigNode> data) { // Check if the config node is null if (data.to == null) { return; } ConfigNode orbit = data.to.GetNode("ORBIT"); String bodyIdent = orbit.GetValue("IDENT"); CelestialBody body = UBI.GetBody(bodyIdent); if (body == null) { return; } orbit.SetValue("REF", body.flightGlobalsIndex); }
public void SpawnAsteroid(Asteroid asteroid, UInt32 seed) { // Create Default Orbit Orbit orbit = null; CelestialBody body = null; // Select Orbit Type Int32 type = Random.Range(0, 3); if (type == 0 && asteroid.Location.Around.Count != 0) { // Around Location.AroundLoader[] around = GetProbabilityList(asteroid.Location.Around, asteroid.Location.Around.Select(a => a.Probability.Value).ToList()).ToArray(); Location.AroundLoader loader = around[Random.Range(0, around.Length)]; body = UBI.GetBody(loader.Body); if (!body) { return; } if (loader.Reached && !ReachedBody(body)) { return; } orbit = new Orbit { referenceBody = body, eccentricity = loader.Eccentricity, semiMajorAxis = loader.SemiMajorAxis, inclination = loader.Inclination, LAN = loader.LongitudeOfAscendingNode, argumentOfPeriapsis = loader.ArgumentOfPeriapsis, meanAnomalyAtEpoch = loader.MeanAnomalyAtEpoch, epoch = loader.Epoch }; orbit.Init(); } else if (type == 1 && asteroid.Location.Nearby.Count != 0) { // Nearby Location.NearbyLoader[] nearby = GetProbabilityList(asteroid.Location.Nearby, asteroid.Location.Nearby.Select(a => a.Probability.Value).ToList()).ToArray(); Location.NearbyLoader loader = nearby[Random.Range(0, nearby.Length)]; body = UBI.GetBody(loader.Body); if (!body) { return; } if (loader.Reached && !ReachedBody(body)) { return; } orbit = new Orbit { eccentricity = body.orbit.eccentricity + loader.Eccentricity, semiMajorAxis = body.orbit.semiMajorAxis * loader.SemiMajorAxis, inclination = body.orbit.inclination + loader.Inclination, LAN = body.orbit.LAN * loader.LongitudeOfAscendingNode, argumentOfPeriapsis = body.orbit.argumentOfPeriapsis * loader.ArgumentOfPeriapsis, meanAnomalyAtEpoch = body.orbit.meanAnomalyAtEpoch * loader.MeanAnomalyAtEpoch, epoch = body.orbit.epoch, referenceBody = body.orbit.referenceBody }; orbit.Init(); } else if (type == 2 && asteroid.Location.Flyby.Count != 0) { // Flyby Location.FlybyLoader[] flyby = GetProbabilityList(asteroid.Location.Flyby, asteroid.Location.Flyby.Select(a => a.Probability.Value).ToList()).ToArray(); Location.FlybyLoader loader = flyby[Random.Range(0, flyby.Length)]; body = UBI.GetBody(loader.Body); if (!body) { return; } if (loader.Reached && !ReachedBody(body)) { return; } orbit = Orbit.CreateRandomOrbitFlyBy(body, Random.Range(loader.MinDuration, loader.MaxDuration)); } // Check if (orbit == null) { Debug.Log("[Kopernicus] No new objects this time. (Probability is " + asteroid.Probability.Value + "%)"); return; } // Name String asteroidName = DiscoverableObjectsUtil.GenerateAsteroidName(); // Lifetime Double lifetime = Random.Range(asteroid.MinUntrackedLifetime, asteroid.MaxUntrackedLifetime) * 24d * 60d * 60d; Double maxLifetime = asteroid.MaxUntrackedLifetime * 24d * 60d * 60d; // Size UntrackedObjectClass size = (UntrackedObjectClass)(Int32)(asteroid.Size.Evaluate(Random.Range(0f, 1f)) * Enum.GetNames(typeof(UntrackedObjectClass)).Length); // Spawn ConfigNode vessel = null; vessel = ProtoVessel.CreateVesselNode( asteroidName, VesselType.SpaceObject, orbit, 0, new[] { ProtoVessel.CreatePartNode( "PotatoRoid", seed ) }, new ConfigNode("ACTIONGROUPS"), ProtoVessel.CreateDiscoveryNode( DiscoveryLevels.Presence, size, lifetime, maxLifetime ) ); OverrideNode(ref vessel, asteroid.Vessel); ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame); if (asteroid.UniqueName && FlightGlobals.Vessels.Count(v => v.vesselName == protoVessel.vesselName) != 0) { return; } Kopernicus.Events.OnRuntimeUtilitySpawnAsteroid.Fire(asteroid, protoVessel); protoVessel.Load(HighLogic.CurrentGame.flightState); GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef); GameEvents.onAsteroidSpawned.Fire(protoVessel.vesselRef); Debug.Log("[Kopernicus] New object found near " + body.name + ": " + protoVessel.vesselName + "!"); }
// 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 }
// Generates the system prefab from the configuration void IParserEventSubscriber.PostApply(ConfigNode node) { //Set of items seen while loading, to prevent duplicate loggers being created (throws IOExceptions) HashSet <String> seen = new HashSet <String>(); // Dictionary of bodies generated List <Body> bodies = new List <Body>(); Logger logger = new Logger(); // Load all of the bodies foreach (ConfigNode bodyNode in node.GetNodes(BODY_NODE_NAME)) { // Grab the name of the body String name = bodyNode.GetValue("name"); if (bodyNode.HasValue("identifier")) { name = bodyNode.GetValue("identifier"); } if (seen.Contains(name)) { Logger.Default.Log("[Kopernicus::PostApply] Skipped duplicate body " + name); continue; //next body, please } seen.Add(name); try { // Create a logfile for this body logger.SetFilename(name + ".Body"); logger.SetAsActive(); // Attempt to create the body Body currentBody = new Body(); Parser.SetState("Kopernicus:currentBody", () => currentBody); Parser.LoadObjectFromConfigurationNode(currentBody, bodyNode, "Kopernicus"); //logs to active logger bodies.Add(currentBody); Events.OnLoaderLoadBody.Fire(currentBody, bodyNode); Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Body: " + currentBody.Name); Parser.ClearState("Kopernicus:currentBody"); // Restore default logger Logger.Default.SetAsActive(); logger.Close(); //implicit flush } catch (Exception e) { logger.LogException(e); logger.Close(); //implicit flush Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Body: " + name + ": " + e.Message); throw new Exception("Failed to load Body: " + name); } } seen.Clear(); // Load all of the asteroids foreach (ConfigNode asteroidNode in node.GetNodes(ASTEROID_NODE_NAME)) { if (seen.Contains(asteroidNode.GetValue("name"))) { Logger.Default.Log("[Kopernicus::PostApply] Skipped duplicate asteroid " + asteroidNode.GetValue("name")); continue; //next roid, please } seen.Add(asteroidNode.GetValue("name")); try { // Create a logfile for this asteroid logger.SetFilename(asteroidNode.GetValue("name") + ".Asteroid"); logger.SetAsActive(); // Attempt to create the Asteroid Asteroid asteroid = Parser.CreateObjectFromConfigNode <Asteroid>(asteroidNode, "Kopernicus"); //logs to active logger DiscoverableObjects.Asteroids.Add(asteroid); Events.OnLoaderLoadAsteroid.Fire(asteroid, asteroidNode); Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Asteroid: " + asteroid.Name); // Restore default logger Logger.Default.SetAsActive(); logger.Close(); //implicit flush } catch (Exception e) { Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Asteroid: " + asteroidNode.GetValue("name") + ": " + e.Message); logger.LogException(e); logger.Close(); throw new Exception("Failed to load Asteroid: " + asteroidNode.GetValue("name")); } } seen.Clear(); logger.Close(); // Load all of the PQS Presets foreach (ConfigNode presetNode in node.GetNodes(PRESET_NODE_NAME)) { // Attempt to create the Preset try { PQSCache.PQSPreset preset = new PQSCache.PQSPreset(); preset.Load(presetNode); if (PQSCache.PresetList.presets.Any(p => p.name == preset.name)) { Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Preset: " + preset.name); continue; } PQSCache.PresetList.presets.Add(preset); // Display name String displayName = preset.name; if (presetNode.HasValue("displayName")) { displayName = presetNode.GetValue("displayName"); } Templates.PresetDisplayNames.Add(displayName); Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Preset: " + preset.name); } catch { Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Preset: " + presetNode.GetValue("name")); throw new Exception("Failed to load Asteroid: " + presetNode.GetValue("name")); } } // Register UBIs for all bodies CelestialBody[] localBodies = bodies.Select(b => b.GeneratedBody.celestialBody).ToArray(); foreach (Body body in bodies) { // Register the primary UBI if (!String.IsNullOrEmpty(body.Identifier)) { UBI.RegisterUBI(body.CelestialBody, body.Identifier, localBodies: localBodies); } // Register all implemented UBIs foreach (String ubi in body.Implements.SelectMany(u => u.Value).Distinct()) { if (!String.IsNullOrEmpty(ubi)) { UBI.RegisterUBI(body.CelestialBody, ubi, true, localBodies); } } } // Event Events.OnLoaderLoadedAllBodies.Fire(this, node); // Glue all the orbits together in the defined pattern foreach (Body body in bodies) { // If this body is in orbit around another body if (body.Orbit != null) { // Convert a UBI reference into a normal one String referenceBody = UBI.GetName(body.Orbit.ReferenceBody, localBodies); // Get the Body object for the reference body Body parent = bodies.Find(b => b.Name == referenceBody); if (parent == null) { throw new Exception("Reference body for \"" + (body.Identifier ?? body.Name) + "\" could not be found. Missing body name is \"" + body.Orbit.ReferenceBody + "\"."); } // Setup the orbit of the body parent.GeneratedBody.children.Add(body.GeneratedBody); body.GeneratedBody.orbitDriver.referenceBody = parent.GeneratedBody.celestialBody; body.GeneratedBody.orbitDriver.orbit.referenceBody = parent.GeneratedBody.celestialBody; } // Parent the generated body to the PSystem body.GeneratedBody.transform.parent = SystemPrefab.transform; // Delete ghost space centers if (!body.GeneratedBody.celestialBody.isHomeWorld && body.GeneratedBody.pqsVersion != null) { SpaceCenter[] centers = body.GeneratedBody.pqsVersion.GetComponentsInChildren <SpaceCenter>(true); if (centers != null) { foreach (SpaceCenter c in centers) { Object.Destroy(c); } } } // Event Events.OnLoaderFinalizeBody.Fire(body); } // Elect root body SystemPrefab.rootBody = bodies.First(p => p.Orbit == null).GeneratedBody; // Try to find a home world Body home = bodies.FirstOrDefault(p => p.GeneratedBody.celestialBody.isHomeWorld); if (home == null) { throw new Exception("Homeworld body could not be found."); } // Sort by distance from parent (discover how this effects local bodies) Utility.DoRecursive(SystemPrefab.rootBody, body => body.children, body => body.children = body.children .OrderBy(b => b.orbitDriver.orbit.semiMajorAxis * (1 + b.orbitDriver.orbit.eccentricity)).ToList()); // Fix doubled flightGlobals List <Int32> numbers = new List <Int32> { 0, 1 }; Int32 index = bodies.Sum(b => b.GeneratedBody.flightGlobalsIndex); Utility.DoRecursive(SystemPrefab.rootBody, body => body.children, body => { // ReSharper disable AccessToModifiedClosure if (numbers.Contains(body.flightGlobalsIndex)) { body.flightGlobalsIndex = index++; } if (body.celestialBody.isHomeWorld) { body.flightGlobalsIndex = 1; // Kerbin } if (body == SystemPrefab.rootBody) { body.flightGlobalsIndex = 0; // Sun } numbers.Add(body.flightGlobalsIndex); // ReSharper restore AccessToModifiedClosure }); // Event Events.OnLoaderPostApply.Fire(this, node); }
/// <summary> /// Applies the PostSpawnOrbit and then returns the referenceBody /// </summary> Body OrbitPatcher(Body body) { Debug.Log("SigmaBinary.OrbitPatcher", "celestialBody = " + body?.GeneratedBody?.celestialBody); if (body?.GeneratedBody?.celestialBody?.Has("sbPatched") == false) { if (body?.GeneratedBody?.orbitDriver?.orbit == null) { Debug.Log("OrbitPatcher", "Body " + body.GeneratedBody.name + " does not have an orbit."); return(null); } // This 'if' is here to make sure stars don't give us trouble if (body?.GeneratedBody?.orbitDriver?.orbit?.referenceBody == null) { body.GeneratedBody.orbitDriver.orbit.referenceBody = ListOfBodies.Find(rb => rb.GeneratedBody.name == body.Orbit.ReferenceBody).GeneratedBody.celestialBody; Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " 'referenceBody' set to " + body.GeneratedBody.orbitDriver.orbit.referenceBody); } // If the body has a Kerbin Template, save the original referenceBody for later if (body?.Template?.OriginalBody?.celestialBody?.name == "Kerbin") { Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " uses Kerbin as Template."); kerbinFixer.Add(body.GeneratedBody.name, body.Orbit.ReferenceBody); Debug.Log("SigmaBinary.OrbitPatcher", "Store original 'referenceBody' " + body.Orbit.ReferenceBody + " of body " + body.GeneratedBody.name + " in 'kerbinFixer'."); } if (body?.GeneratedBody?.Has("orbitPatches") == true) { ConfigNode patch = body.GeneratedBody.Get <ConfigNode>("orbitPatches"); Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " has a 'PostSpawnOrbit' node."); // Fix sphereOfInfluence if (patch.HasValue("referenceBody") || patch.HasValue("semiMajorAxis")) { if (!body.GeneratedBody.celestialBody.Has("sphereOfInfluence")) { body.GeneratedBody.celestialBody.Set("SBfixSOI", true); Debug.Log("SigmaBinary.OrbitPatcher", "'sphereOfInfluence' of body " + body.GeneratedBody.name + " needs to be recalculated."); } } // Patch orbit using the original 'PostSpawnOrbit' node if (patch?.values?.Count > 0) { // Create a new loader OrbitLoader loader = new SigmaOrbitLoader(body.GeneratedBody); // Apply the patch to the loader Parser.LoadObjectFromConfigurationNode(loader, patch, "Kopernicus"); Debug.Log("SigmaBinary.OrbitPatcher", "Patched orbit of body " + body.GeneratedBody.name + " using 'PostSpawnOrbit' node"); // Remove 'PostSpawnOrbit' node body.GeneratedBody.Remove("orbitPatches"); Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " 'PostSpawnOrbit' node removed."); // If the patch is used to reparent the body if (patch.HasValue("referenceBody")) { body.Orbit.ReferenceBody = patch.GetValue("referenceBody"); body.GeneratedBody.orbitDriver.orbit.referenceBody = ListOfBodies.Find(rb => rb.GeneratedBody.name == body.Orbit.ReferenceBody).GeneratedBody.celestialBody; Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " 'referenceBody' set from 'PostSpawnOrbit'. referenceBody = " + body.Orbit.ReferenceBody + " (" + body.GeneratedBody.orbitDriver.orbit.referenceBody + ")"); // Keep the ConfigNode for all bodies with a Kerbin Template if (body?.Template?.OriginalBody?.celestialBody?.name == "Kerbin") { Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " uses Kerbin as Template."); ConfigNode temp = new ConfigNode(); temp.AddValue("referenceBody", patch.GetValue("referenceBody")); body.GeneratedBody.Set("orbitPatches", temp); Debug.Log("SigmaBinary.OrbitPatcher", "Body " + body.GeneratedBody.name + " original 'PostSpawnOrbit' node restored."); } } } } body.GeneratedBody.celestialBody.Set("sbPatched", true); } CelestialBody referenceBody = UBI.GetBody(body.Orbit.ReferenceBody, ListOfBodies.Select(b => b.CelestialBody).ToArray()); return(ListOfBodies?.FirstOrDefault(b => b?.CelestialBody == referenceBody)); }
/// <summary> /// Gets invoked when all bodies were successfully loaded /// </summary> public static void OnLoaderLoadedAllBodies(Loader loader, ConfigNode node) { // Grab home star and home planet CelestialBody[] cbs = Bodies.Select(b => b.celestialBody).ToArray(); CelestialBody star = UBI.GetBody(InterstellarSettings.Instance.HomeStar, cbs); if (!star.Has("IC:HomePlanet")) { throw new Exception("The home star must have a home planet defined."); } CelestialBody planet = UBI.GetBody(InterstellarSettings.Instance.HomePlanet ?? star.Get("IC:HomePlanet", ""), cbs); // Grab the position of the home star Vector3d position = star.Get("IC:Position", Vector3d.zero); // Fix the naming of home star and home planet Body starBody = Bodies.Find(b => b.celestialBody == star); Body planetBody = Bodies.Find(b => b.celestialBody == planet); RenameBody(starBody, "Sun"); RenameBody(planetBody, "Kerbin"); planet.isHomeWorld = true; // Since this body is the center of the universe, remove its orbit UnityEngine.Object.DestroyImmediate(starBody.generatedBody.celestialBody.GetComponent <OrbitRendererUpdater>()); UnityEngine.Object.DestroyImmediate(starBody.generatedBody.orbitDriver); UnityEngine.Object.DestroyImmediate(starBody.generatedBody.orbitRenderer); starBody.orbit = null; // Trigger the KSC mover WithBody(planetBody, () => { planetBody.pqs = new PQSLoader(); }); // Go through each body, and calculate the orbits of the stars foreach (Body body in Bodies) { // Don't work with non-IC bodies if (!body.celestialBody.Has("IC:Position")) { continue; } // We already edited the home star if (body.celestialBody == star) { continue; } // Apply the SOI if (body.celestialBody.Has("IC:SOI")) { body.properties.sphereOfInfluence = body.celestialBody.Get("IC:SOI", 0d) * InterstellarSettings.Instance.KI; } // Calculate the real position of the star Vector3d realPosition = body.celestialBody.Get("IC:Position", Vector3d.zero) - position; // Apply the orbital parameters WithBody(body, () => { body.orbit = new OrbitLoader(); body.orbit.semiMajorAxis = Math.Pow( Math.Pow(realPosition.x, 2) + Math.Pow(realPosition.y, 2) + Math.Pow(realPosition.z, 2), 0.5) * InterstellarSettings.Instance.KI; body.orbit.eccentricity = 0; body.orbit.argumentOfPeriapsis = 90; body.orbit.meanAnomalyAtEpoch = 0; body.orbit.inclination = Math.Atan(realPosition.z / Math.Pow(Math.Pow(realPosition.x, 2) + Math.Pow(realPosition.y, 2), 0.5)) / Math.PI * 180; body.orbit.longitudeOfAscendingNode = CalculateLAN(realPosition.x, realPosition.y); body.orbit.period = Double.MaxValue; body.orbit.referenceBody = UBI.GetUBI(star); // This is a bit of a hack, because 1.3.1 and 1.4.5+ use different enums for // that value, and i want IC to be compatible with all versions try { PropertyInfo orbitMode = typeof(OrbitLoader).GetProperty("mode"); Type parserType = orbitMode.PropertyType; MethodInfo setFromString = parserType.GetMethod("SetFromString"); Object parser = orbitMode.GetValue(body.orbit, null); setFromString.Invoke(parser, new[] { "OFF" }); orbitMode.SetValue(body.orbit, parser, null); } catch { // ignored } // Load additional patches if (body.celestialBody.Has("IC:OrbitPatches")) { Parser.LoadObjectFromConfigurationNode(body.orbit, body.celestialBody.Get <ConfigNode>("IC:OrbitPatches")); } }); } }
void IParserEventSubscriber.PostApply(ConfigNode node) { // Since this is parsing a body, treat the name as an UBI Name = UBI.GetName(Name); }
/// <summary> /// Constructs a Skein digest with an internal state size and output size. /// </summary> /// <param name="blockSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or /// <see cref="SKEIN_1024"/>.</param> /// <param name="outputSizeBits">the output/digest size to produce in bits, which must be an integral number of /// bytes.</param> public SkeinEngine(int blockSizeBits, int outputSizeBits) { if (outputSizeBits % 8 != 0) { throw new ArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits); } // TODO: Prevent digest sizes > block size? this.outputSizeBytes = outputSizeBits / 8; this.threefish = new ThreefishEngine(blockSizeBits); this.ubi = new UBI(this,threefish.GetBlockSize()); }
public void Reset(UBI ubi) { currentBlock = Arrays.Clone(ubi.currentBlock, currentBlock); currentOffset = ubi.currentOffset; message = Arrays.Clone(ubi.message, this.message); tweak.Reset(ubi.tweak); }
// Update the menu body private void Start() { if (!Templates.KopernicusMainMenu) { return; } // Select a random body? if (Templates.RandomMainMenuBodies.Any()) { Templates.MenuBody = Templates.RandomMainMenuBodies[new Random().Next(0, Templates.RandomMainMenuBodies.Count)]; } // Grab the main body CelestialBody planetCb = UBI.GetBody(Templates.MenuBody); if (planetCb == null) { planetCb = PSystemManager.Instance.localBodies.Find(b => b.isHomeWorld); } if (planetCb == null) { Debug.LogError("[Kopernicus] Could not find home world!"); return; } // Load Textures OnDemandStorage.EnableBody(Templates.MenuBody); // Get the MainMenu-Logic MainMenu main = FindObjectOfType <MainMenu>(); if (main == null) { Debug.LogError("[Kopernicus] No main menu object!"); return; } MainMenuEnvLogic logic = main.envLogic; // Set it to Space, because the Mun-Area won't work with sth else than Mun if (logic.areas.Length < 2) { Debug.LogError("[Kopernicus] Not enough bodies"); return; } // Get our active Space GameObject space = logic.areas[1]; // Deactivate Kerbins Transform Transform kerbin = space.transform.Find("Kerbin"); if (kerbin == null) { Debug.LogError("[Kopernicus] No Kerbin transform!"); return; } kerbin.gameObject.SetActive(false); // Deactivate Muns Transform Transform munPivot = space.transform.Find("MunPivot"); if (munPivot == null) { Debug.LogError("[Kopernicus] No MunPivot transform!"); return; } munPivot.gameObject.SetActive(false); // Activate the textures ScaledSpaceOnDemand od = planetCb.scaledBody.GetComponentInChildren <ScaledSpaceOnDemand>(); if (od != null) { od.Start(); od.LoadTextures(); } // Clone the scaledVersion and attach it to the Scene GameObject menuPlanet = Utility.Instantiate(Utility .FindBody(PSystemManager.Instance.systemPrefab.rootBody, planetCb.transform.name).scaledVersion, space.transform, true); menuPlanet.name = planetCb.transform.name; // Destroy stuff DestroyImmediate(menuPlanet.GetComponent <ScaledSpaceFader>()); DestroyImmediate(menuPlanet.GetComponent <SphereCollider>()); DestroyImmediate(menuPlanet.GetComponentInChildren <AtmosphereFromGround>()); DestroyImmediate(menuPlanet.GetComponent <MaterialSetDirection>()); // That sounds funny Rotato planetRotato = menuPlanet.AddComponent <Rotato>(); Rotato planetRefRotato = kerbin.GetComponent <Rotato>(); planetRotato.speed = planetRefRotato.speed * ((Single)planetCb.rotationPeriod / KERBIN_ROTATION_PERIOD); menuPlanet.transform.Rotate(0f, (Single)planetCb.initialRotation, 0f); // Scale the body menuPlanet.transform.localScale = kerbin.localScale; menuPlanet.transform.localPosition = kerbin.localPosition; menuPlanet.transform.position = kerbin.position; // And set it to layer 0 menuPlanet.layer = 0; Events.OnRuntimeUtilityUpdateMenu.Fire(); }
public void SpawnAsteroid(Asteroid asteroid, UInt32 seed) { // Create Default Orbit Orbit orbit = null; CelestialBody body = null; // Select Orbit Type Int32 type = Random.Range(0, 3); if (type == 0 && asteroid.Location.Around.Count != 0) { // Around Location.AroundLoader[] around = GetProbabilityList(asteroid.Location.Around, asteroid.Location.Around.Select(a => a.Probability.Value).ToList()).ToArray(); Location.AroundLoader loader = around[Random.Range(0, around.Length)]; body = UBI.GetBody(loader.Body); if (!body) { return; } if (loader.Reached && !ReachedBody(body)) { return; } orbit = new Orbit { referenceBody = body, eccentricity = loader.Eccentricity, semiMajorAxis = loader.SemiMajorAxis, inclination = loader.Inclination, LAN = loader.LongitudeOfAscendingNode, argumentOfPeriapsis = loader.ArgumentOfPeriapsis, meanAnomalyAtEpoch = loader.MeanAnomalyAtEpoch, epoch = loader.Epoch }; orbit.Init(); } else if (type == 1 && asteroid.Location.Nearby.Count != 0) { // Nearby Location.NearbyLoader[] nearby = GetProbabilityList(asteroid.Location.Nearby, asteroid.Location.Nearby.Select(a => a.Probability.Value).ToList()).ToArray(); Location.NearbyLoader loader = nearby[Random.Range(0, nearby.Length)]; body = UBI.GetBody(loader.Body); if (!body) { return; } if (loader.Reached && !ReachedBody(body)) { return; } orbit = new Orbit { eccentricity = body.orbit.eccentricity + loader.Eccentricity, semiMajorAxis = body.orbit.semiMajorAxis * loader.SemiMajorAxis, inclination = body.orbit.inclination + loader.Inclination, LAN = body.orbit.LAN * loader.LongitudeOfAscendingNode, argumentOfPeriapsis = body.orbit.argumentOfPeriapsis * loader.ArgumentOfPeriapsis, meanAnomalyAtEpoch = body.orbit.meanAnomalyAtEpoch * loader.MeanAnomalyAtEpoch, epoch = body.orbit.epoch, referenceBody = body.orbit.referenceBody }; orbit.Init(); } else if (type == 2 && asteroid.Location.Flyby.Count != 0) { // Flyby Location.FlybyLoader[] flyby = GetProbabilityList(asteroid.Location.Flyby, asteroid.Location.Flyby.Select(a => a.Probability.Value).ToList()).ToArray(); Location.FlybyLoader loader = flyby[Random.Range(0, flyby.Length)]; body = UBI.GetBody(loader.Body); if (!body) { return; } if (loader.Reached && !ReachedBody(body)) { return; } orbit = Orbit.CreateRandomOrbitFlyBy(body, Random.Range(loader.MinDuration, loader.MaxDuration)); } // Check if (orbit == null) { Debug.Log("[Kopernicus] No new objects this time. (Probability is " + asteroid.Probability.Value + "%)"); return; } // Name String asteroidName = DiscoverableObjectsUtil.GenerateAsteroidName(); // Lifetime Double lifetime = Random.Range(asteroid.MinUntrackedLifetime, asteroid.MaxUntrackedLifetime) * 24d * 60d * 60d; Double maxLifetime = asteroid.MaxUntrackedLifetime * 24d * 60d * 60d; // Size UntrackedObjectClass size = (UntrackedObjectClass)(Int32)(asteroid.Size.Evaluate(Random.Range(0f, 1f)) * Enum.GetNames(typeof(UntrackedObjectClass)).Length); // Spawn ConfigNode vessel = null; #if (KSP_VERSION_1_10_1 || KSP_VERSION_1_11_1) if (Random.Range(0, 100) > RuntimeUtility.KopernicusConfig.CometPercentage) { #endif vessel = ProtoVessel.CreateVesselNode( asteroidName, VesselType.SpaceObject, orbit, 0, new[] { ProtoVessel.CreatePartNode( "PotatoRoid", seed ) }, new ConfigNode("ACTIONGROUPS"), ProtoVessel.CreateDiscoveryNode( DiscoveryLevels.Presence, size, lifetime, maxLifetime ) ); OverrideNode(ref vessel, asteroid.Vessel); ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame); if (asteroid.UniqueName && FlightGlobals.Vessels.Count(v => v.vesselName == protoVessel.vesselName) != 0) { return; } Kopernicus.Events.OnRuntimeUtilitySpawnAsteroid.Fire(asteroid, protoVessel); protoVessel.Load(HighLogic.CurrentGame.flightState); GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef); GameEvents.onAsteroidSpawned.Fire(protoVessel.vesselRef); Debug.Log("[Kopernicus] New object found near " + body.name + ": " + protoVessel.vesselName + "!"); #if (KSP_VERSION_1_10_1 || KSP_VERSION_1_11_1) } else { float fragmentDynamicPressureModifier = 0f; bool optimizedCollider = false; CometOrbitType cometType = CometManager.GenerateWeightedCometType(); Orbit cometOrbit = cometType.CalculateHomeOrbit(); UntrackedObjectClass randomObjClass = cometType.GetRandomObjClass(); CometDefinition cometDef = CometManager.GenerateDefinition(cometType, randomObjClass, (int)seed); ConfigNode configNode = cometDef.CreateVesselNode(optimizedCollider, fragmentDynamicPressureModifier, hasName: false); ConfigNode configNode2 = ProtoVessel.CreatePartNode("PotatoComet", seed); uint value = 0u; configNode2.TryGetValue("persistentId", ref value); configNode.AddValue("cometPartId", value); ConfigNode configNode3 = new ConfigNode("VESSELMODULES"); configNode3.AddNode(configNode); vessel = ProtoVessel.CreateVesselNode(DiscoverableObjectsUtil.GenerateCometName(), VesselType.SpaceObject, cometOrbit, 0, new ConfigNode[1] { configNode2 }, new ConfigNode("ACTIONGROUPS"), ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Presence, randomObjClass, lifetime, maxLifetime), configNode3); OverrideNode(ref vessel, asteroid.Vessel); ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame); Kopernicus.Events.OnRuntimeUtilitySpawnAsteroid.Fire(asteroid, protoVessel); protoVessel.Load(HighLogic.CurrentGame.flightState); GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef); GameEvents.onAsteroidSpawned.Fire(protoVessel.vesselRef); Debug.Log("[Kopernicus] New object found near " + body.name + ": " + protoVessel.vesselName + "!"); } #endif }
// Generates the system prefab from the configuration void IParserEventSubscriber.PostApply(ConfigNode node) { //Set of items seen while loading, to prevent duplicate loggers being created (throws IOExceptions) HashSet <String> seen = new HashSet <String>(); // Dictionary of bodies generated Dictionary <String, Body> bodies = new Dictionary <String, Body>(); Logger logger = new Logger(); // Load all of the bodies foreach (ConfigNode bodyNode in node.GetNodes(bodyNodeName)) { if (seen.Contains(bodyNode.GetValue("name"))) { Logger.Default.Log("[Kopernicus::PostApply] Skipped duplicate body " + bodyNode.GetValue("name")); continue; //next body, please } else { seen.Add(bodyNode.GetValue("name")); } try { // Create a logfile for this body logger.SetFilename(bodyNode.GetValue("name") + ".Body"); logger.SetAsActive(); // Attempt to create the body currentBody = new Body(); Parser.LoadObjectFromConfigurationNode(currentBody, bodyNode, "Kopernicus"); //logs to active logger bodies.Add(currentBody.name, currentBody); Events.OnLoaderLoadBody.Fire(currentBody, bodyNode); Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Body: " + currentBody.name); // Restore default logger Logger.Default.SetAsActive(); logger.Close(); //implicit flush } catch (Exception e) { logger.LogException(e); logger.Close(); //implicit flush Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Body: " + bodyNode.GetValue("name") + ": " + e.Message); throw new Exception("Failed to load Body: " + bodyNode.GetValue("name")); } } seen.Clear(); // Event Events.OnLoaderLoadedAllBodies.Fire(this, node); // Load all of the asteroids foreach (ConfigNode asteroidNode in node.GetNodes(asteroidNodeName)) { if (seen.Contains(asteroidNode.GetValue("name"))) { Logger.Default.Log("[Kopernicus::PostApply] Skipped duplicate asteroid " + asteroidNode.GetValue("name")); continue; //next roid, please } else { seen.Add(asteroidNode.GetValue("name")); } try { // Create a logfile for this asteroid logger.SetFilename(asteroidNode.GetValue("name") + ".Asteroid"); logger.SetAsActive(); // Attempt to create the Asteroid Asteroid asteroid = Parser.CreateObjectFromConfigNode <Asteroid>(asteroidNode, "Kopernicus"); //logs to active logger DiscoverableObjects.asteroids.Add(asteroid); Events.OnLoaderLoadAsteroid.Fire(asteroid, asteroidNode); Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Asteroid: " + asteroid.name); // Restore default logger Logger.Default.SetAsActive(); logger.Close(); //implicit flush } catch (Exception e) { Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Asteroid: " + asteroidNode.GetValue("name") + ": " + e.Message); logger.LogException(e); logger.Close(); throw new Exception("Failed to load Asteroid: " + asteroidNode.GetValue("name")); } } seen.Clear(); logger.Close(); logger = null; // Load all of the PQS Presets foreach (ConfigNode presetNode in node.GetNodes(presetNodeName)) { // Attempt to create the Preset try { PQSCache.PQSPreset preset = new PQSCache.PQSPreset(); preset.Load(presetNode); if (PQSCache.PresetList.presets.Any(p => p.name == preset.name)) { Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Preset: " + preset.name); continue; } PQSCache.PresetList.presets.Add(preset); // Display name String displayName = preset.name; if (presetNode.HasValue("displayName")) { displayName = presetNode.GetValue("displayName"); } Templates.PresetDisplayNames.Add(displayName); Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Preset: " + preset.name); } catch { Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Preset: " + presetNode.GetValue("name")); throw new Exception("Failed to load Asteroid: " + presetNode.GetValue("name")); } } // Register UBIs for all bodies CelestialBody[] localBodies = bodies.Values.Select(b => b.generatedBody.celestialBody).ToArray(); foreach (KeyValuePair <String, Body> body in bodies) { // Register the primary UBI if (!String.IsNullOrEmpty(body.Value.identifier)) { UBI.RegisterUBI(body.Value.celestialBody, body.Value.identifier, localBodies: localBodies); } // Register all implemented UBIs foreach (String ubi in body.Value.implements.SelectMany(u => u.Value).Distinct()) { if (!String.IsNullOrEmpty(ubi)) { UBI.RegisterUBI(body.Value.celestialBody, ubi, isAbstract: true, localBodies: localBodies); } } } // Glue all the orbits together in the defined pattern foreach (KeyValuePair <String, Body> body in bodies) { // If this body is in orbit around another body if (body.Value.orbit != null) { // Convert a UBI reference into a normal one String referenceBody = UBI.GetName(body.Value.orbit.referenceBody, localBodies: localBodies); // Get the Body object for the reference body if (!bodies.TryGetValue(referenceBody, out Body parent)) { throw new Exception("Reference body for \"" + body.Key + "\" could not be found. Missing body name is \"" + body.Value.orbit.referenceBody + "\"."); } // Setup the orbit of the body parent.generatedBody.children.Add(body.Value.generatedBody); body.Value.generatedBody.orbitDriver.referenceBody = parent.generatedBody.celestialBody; body.Value.generatedBody.orbitDriver.orbit.referenceBody = parent.generatedBody.celestialBody; } // Parent the generated body to the PSystem body.Value.generatedBody.transform.parent = systemPrefab.transform; // Delete ghost space centers if (!body.Value.generatedBody.celestialBody.isHomeWorld && body.Value.generatedBody.pqsVersion != null) { SpaceCenter[] centers = body.Value.generatedBody.pqsVersion.GetComponentsInChildren <SpaceCenter>(true); if (centers != null) { foreach (SpaceCenter c in centers) { UnityEngine.Object.Destroy(c); } } } // Event Events.OnLoaderFinalizeBody.Fire(body.Value); } // Elect root body systemPrefab.rootBody = bodies.First(p => p.Value.orbit == null).Value.generatedBody; // Try to find a home world Body home = bodies.Values.FirstOrDefault(p => p.generatedBody.celestialBody.isHomeWorld); if (home == null) { throw new Exception("Homeworld body could not be found."); } // Sort by distance from parent (discover how this effects local bodies) RecursivelySortBodies(systemPrefab.rootBody); // Fix doubled flightGlobals List <Int32> numbers = new List <Int32>() { 0, 1 }; Int32 index = bodies.Sum(b => b.Value.generatedBody.flightGlobalsIndex); PatchFGI(ref numbers, ref index, systemPrefab.rootBody); // We're done currentBody.generatedBody = null; // Event Events.OnLoaderPostApply.Fire(this, node); }