/// <summary> /// Verifies that the ReesearchBodies version the player has is compatible. /// </summary> /// <returns>Whether the check passed.</returns> public static bool VerifyResearchBodiesVersion() { string minVersion = "1.8"; if (ResearchBodiesAssembly == null && !ResearchBodiesCheckDone) { ResearchBodiesAssembly = Version.VerifyAssemblyVersion("ResearchBodies", minVersion, true); ResearchBodiesCheckDone = true; } // Check the wrapper is initalized, while we're here if (ResearchBodiesAssembly != null && !RBWrapper.APIRBReady) { // Initialize the Research Bodies wrapper bool rbInit = RBWrapper.InitRBWrapper(); if (rbInit) { LoggingUtil.LogInfo(typeof(ContractConfigurator), "Successfully initialized Research Bodies wrapper."); } else { LoggingUtil.LogDebug(typeof(ContractConfigurator), "Couldn't initialize Research Bodies wrapper."); } } return(ResearchBodiesAssembly != null); }
public void Update() { // Delay until the game database has started loading (it's a short delay) if (LoadingScreen.Instance != null && GameDatabase.Instance != null && GameDatabase.Instance.root != null) { LoggingUtil.LogDebug(this, "Adding custom loading tips"); // Add the Contract Configurator tip List <string> contractTips = new List <string>(); contractTips.Add("Configuring Contracts..."); // Read tips from root contract groups ConfigNode[] contractGroups = GameDatabase.Instance.GetConfigNodes("CONTRACT_GROUP"); foreach (ConfigNode groupConfig in contractGroups) { if (groupConfig.HasValue("tip")) { foreach (string tip in groupConfig.GetValues("tip")) { contractTips.Add(tip); } } } foreach (LoadingScreen.LoadingScreenState lss in LoadingScreen.Instance.Screens) { // Append our custom tips lss.tips = lss.tips.Union(contractTips).ToArray(); } Destroy(this); } }
protected override void TriggerAction() { string[] srcPathComponents = new string[] { KSPUtil.ApplicationRootPath, "GameData" }.Concat(url.Split("/".ToCharArray())).ToArray(); List <string> destPathComponents = new string[] { KSPUtil.ApplicationRootPath, "saves", HighLogic.SaveFolder }.ToList(); if (craftType == CraftType.SubAssembly) { destPathComponents.Add("Subassemblies"); } else { destPathComponents.Add("Ships"); destPathComponents.Add(craftType.ToString()); } destPathComponents.Add(srcPathComponents.Last()); string srcPath = string.Join(Path.DirectorySeparatorChar.ToString(), srcPathComponents); string destPath = string.Join(Path.DirectorySeparatorChar.ToString(), destPathComponents.ToArray()); LoggingUtil.LogDebug(this, "Copying from '{0}' to '{1}'.", srcPath, destPath); try { File.Copy(srcPath, destPath, true); } catch (Exception e) { LoggingUtil.LogException(e); } }
private void nextState() { stepTime = Time.fixedTime; currentState++; LoggingUtil.LogDebug(this, "Moved to state: " + currentState); CreateDelegates(); }
public override ExperienceTrait ConvertFrom <U>(U value) { LoggingUtil.LogDebug(this, StringBuilderCache.Format("ExperienceTraitParser.ConvertFrom<{0}>({1}", typeof(U), value)); if (typeof(U) == typeof(string)) { string sVal = (string)(object)value; if (HighLogic.CurrentGame == null) { currentDataNode.SetDeterministic(currentKey, false); return(null); } for (int index = 0; index < GameDatabase.Instance.ExperienceConfigs.Categories.Count; ++index) { if (sVal == GameDatabase.Instance.ExperienceConfigs.Categories[index].Name) { Type type = KerbalRoster.GetExperienceTraitType(sVal) ?? typeof(ExperienceTrait); return(ExperienceTrait.Create(type, GameDatabase.Instance.ExperienceConfigs.Categories[index], null)); } } throw new ArgumentException("'" + sVal + "' is not a valid experience trait."); } throw new DataStoreCastException(typeof(U), typeof(ExperienceTrait)); }
/// <summary> /// String statements work differently. Basically it's just a search and replace for /// @identifier nodes, with the rest treated as a string literal. /// </summary> /// <returns>The full string after parsing</returns> internal override TResult ParseStatement <TResult>() { verbose &= LogEntryDebug <TResult>("ParseStatement"); try { string value = ""; while (expression.Length > 0) { int specialIdentifierIndex = expression.IndexOf("@"); Match m = Regex.Match(expression, @"\s\w[\w\d]*\("); int functionIndex = m.Index; if (m.Success && specialIdentifierIndex >= 0) { if (functionIndex < specialIdentifierIndex) { specialIdentifierIndex = -1; } else { functionIndex = -1; } } if (m.Success) { value += expression.Substring(0, functionIndex + 1); expression = expression.Substring(functionIndex); Token t = ParseToken(); LoggingUtil.LogDebug(this, " " + t.sval); value += ParseMethod <string>(t, null, true); } else if (specialIdentifierIndex >= 0) { value += expression.Substring(0, specialIdentifierIndex); expression = expression.Substring(specialIdentifierIndex); value += ParseSpecialIdentifier(ParseSpecialIdentifier()); } else { value += expression; expression = ""; } } value = value.Replace("\\n", "\n"); verbose &= LogExitDebug <TResult>("ParseStatement", value); return((TResult)(object)value); } catch { verbose &= LogException <TResult>("ParseStatement"); throw; } }
private void RemoveKerbals() { LoggingUtil.LogDebug(this, "Removing kerbals..."); foreach (Kerbal kerbal in kerbals) { Kerbal.RemoveKerbal(kerbal); } kerbals.Clear(); }
private void Load() { ConfigNode[] experimentConfigs = GameDatabase.Instance.GetConfigNodes("CC_EXPERIMENT_DEFINITIONS"); foreach (ConfigNode experimentConfig in experimentConfigs) { LoggingUtil.LogDebug(this, "Loading experiment definitions for " + experimentConfig.GetValue("name")); foreach (ConfigNode config in experimentConfig.GetNodes("EXPERIMENT")) { string name = ConfigNodeUtil.ParseValue <string>(config, "name"); LoggingUtil.LogVerbose(this, " loading experiment " + name); ExperimentRules exp = new ExperimentRules(name); experimentRules[name] = exp; exp.ignored = ConfigNodeUtil.ParseValue <bool?>(config, "ignored", (bool?)false).Value; exp.requireEVA = ConfigNodeUtil.ParseValue <bool?>(config, "requireEVA", (bool?)false).Value; exp.requireSurfaceSample = ConfigNodeUtil.ParseValue <bool?>(config, "requireSurfaceSample", (bool?)false).Value; exp.requireAsteroidTracking = ConfigNodeUtil.ParseValue <bool?>(config, "requireAsteroidTracking", (bool?)false).Value; exp.requireAtmosphere = ConfigNodeUtil.ParseValue <bool?>(config, "requireAtmosphere", (bool?)false).Value; exp.requireNoAtmosphere = ConfigNodeUtil.ParseValue <bool?>(config, "requireNoAtmosphere", (bool?)false).Value; exp.requireSurface = ConfigNodeUtil.ParseValue <bool?>(config, "requireSurface", (bool?)false).Value; exp.requireNoSurface = ConfigNodeUtil.ParseValue <bool?>(config, "requireNoSurface", (bool?)false).Value; exp.disallowHomeSurface = ConfigNodeUtil.ParseValue <bool?>(config, "disallowHomeSurface", (bool?)false).Value; exp.disallowHomeFlying = ConfigNodeUtil.ParseValue <bool?>(config, "disallowHomeFlying", (bool?)false).Value; exp.disallowKSC = ConfigNodeUtil.ParseValue <bool?>(config, "disallowKSC", (bool?)false).Value; exp.partless = ConfigNodeUtil.ParseValue <bool?>(config, "partless", (bool?)false).Value; exp.part = ConfigNodeUtil.ParseValue <List <string> >(config, "part", null); exp.partModule = ConfigNodeUtil.ParseValue <string>(config, "partModule", null); exp.validBodies = ConfigNodeUtil.ParseValue <List <CelestialBody> >(config, "validBody", null); } // Add the experiment modules foreach (ConfigNode config in experimentConfig.GetNodes("MODULE")) { string name = ConfigNodeUtil.ParseValue <string>(config, "name"); LoggingUtil.LogVerbose(this, " loading module " + name); experimentModules.Add(name); } } // Add experiment modules based on class foreach (Type expModule in ContractConfigurator.GetAllTypes <ModuleScienceExperiment>()) { LoggingUtil.LogVerbose(this, " adding module for class " + expModule.Name); experimentModules.AddUnique(expModule.Name); } loaded = true; }
public IEnumerator <YieldInstruction> Burninator() { LoggingUtil.LogDebug(this, "burninating"); while (burninating && FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.state != Vessel.State.DEAD) { Vessel v = FlightGlobals.ActiveVessel; v.srf_velocity = -jool.GetSurfaceNVector(v.latitude, v.longitude); v.externalTemperature = 1000f; v.atmDensity = 1.0f; v.speed = 3000f; v.mach = 4f; yield return(new WaitForFixedUpdate()); } LoggingUtil.LogDebug(this, "burninating done"); }
protected void CreateDelegates() { if (ParameterCount < 1) { LoggingUtil.LogDebug(this, "Adding EVA parameter..."); evaParam = new ParameterDelegate <MonolithParameter>("Send a Kerbal on EVA", x => CheckParameters(MonolithState.STARTED)); AddParameter(evaParam); LoggingUtil.LogDebug(this, "Adding approach parameter..."); approachParam = new ParameterDelegate <MonolithParameter>("", x => !approachParam.hidden && CheckParameters(MonolithState.EVA)); approachParam.hidden = true; AddParameter(approachParam); LoggingUtil.LogDebug(this, "Adding 'full of stars' parameter..."); fullofstarsParam = new ParameterDelegate <MonolithParameter>("...it's full of stars!", x => !fullofstarsParam.hidden && CheckParameters(MonolithState.FULL_OF_STARS_FINAL)); fullofstarsParam.hidden = true; AddParameter(fullofstarsParam); } bool changeMade = false; if (currentState >= MonolithState.EVA) { if (approachParam.hidden) { LoggingUtil.LogDebug(this, "Unhiding approach parameter..."); approachParam.SetTitle("Approach the monolith with " + candidateName); changeMade = true; approachParam.hidden = false; } } if (currentState >= MonolithState.FULL_OF_STARS1) { if (fullofstarsParam.hidden) { LoggingUtil.LogDebug(this, "Unhiding 'full of stars' parameter..."); changeMade = true; fullofstarsParam.hidden = false; } } if (changeMade) { ContractConfigurator.ContractConfigurator.OnParameterChange.Fire(Root, this); } }
protected void DoAwarding() { IEnumerable <ProtoCrewMember> awardees = crew.Union(kerbals.Where(k => k.pcm != null).Select(k => k.pcm)); LoggingUtil.LogDebug(this, "Awarding {0} points to {1} crew member(s)", experience, awardees.Count()); // Set the homeworld if (homeworld == null) { homeworld = FlightGlobals.Bodies.Where(cb => cb.isHomeWorld).FirstOrDefault(); } foreach (ProtoCrewMember pcm in awardees.Where(pcm => pcm != null)) { LoggingUtil.LogVerbose(this, " Awarding experience to {0}", pcm.name); // Find existing entries int currentValue = 2; foreach (FlightLog.Entry entry in pcm.careerLog.Entries.Concat(pcm.flightLog.Entries).Where(e => e.type.Contains(SPECIAL_XP))) { // Get the entry with the largest value int entryValue = Convert.ToInt32(entry.type.Substring(SPECIAL_XP.Length, entry.type.Length - SPECIAL_XP.Length)); currentValue = Math.Max(currentValue, entryValue); } // Can't go above 64 special experience int value = Math.Min(currentValue + experience, 64); // Increment the entry's experience value string type = SPECIAL_XP + value.ToString(); // Do the awarding pcm.flightLog.AddEntry(type, homeworld.name); if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Assigned) { pcm.ArchiveFlightLog(); } else if (awardImmediately) { pcm.experience += experience; pcm.experienceLevel = KerbalRoster.CalculateExperienceLevel(pcm.experience); } } // Prevent duplicate awards crew.Clear(); }
protected void OnFlightReady() { LoggingUtil.LogVerbose(this, "OnFlightReady"); // Handle late adjustments to PQS City based waypoint positions (workaround for Kopernicus bug) foreach (WaypointData wpData in waypoints) { if (wpData.pqsCity != null) { LoggingUtil.LogDebug(this, "Adjusting PQS City offset coordinates for waypoint {0}", wpData.waypoint.name); CelestialBody body = FlightGlobals.Bodies.Where(b => b.name == wpData.waypoint.celestialName).First(); GeneratePQSCityCoordinates(wpData, body); SetAltitude(wpData, body); wpData.pqsCity = null; } } }
protected override void TriggerAction() { foreach (KerbalInfo kerb in kerbalInfo) { if (kerb.kerbal.pcm != null) { if (kerb.kerbalType != null) { LoggingUtil.LogDebug(this, "Setting type of " + kerb.kerbal.name + " to " + kerb.kerbalType); kerb.kerbal.pcm.type = kerb.kerbalType.Value; } if (!string.IsNullOrEmpty(kerb.trait)) { LoggingUtil.LogDebug(this, "Setting trait of " + kerb.kerbal.name + " to " + kerb.trait); KerbalRoster.SetExperienceTrait(kerb.kerbal.pcm, kerb.trait); } } else { LoggingUtil.LogWarning(this, "Couldn't change type of Kerbal " + kerb.kerbal.name + ", no ProtoCrewMember!"); } } }
protected void CreateVessels() { if (vesselsCreated) { return; } String gameDataDir = KSPUtil.ApplicationRootPath; gameDataDir = gameDataDir.Replace("\\", "/"); if (!gameDataDir.EndsWith("/")) { gameDataDir += "/"; } gameDataDir += "GameData"; // Spawn the vessel in the game world foreach (VesselData vesselData in vessels) { LoggingUtil.LogVerbose(this, "Spawning a vessel named '" + vesselData.name + "'"); // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB! ConfigNode currentShip = ShipConstruction.ShipConfig; ShipConstruct shipConstruct = ShipConstruction.LoadShip(gameDataDir + "/" + vesselData.craftURL); if (shipConstruct == null) { LoggingUtil.LogError(this, "ShipConstruct was null when tried to load '" + vesselData.craftURL + "' (usually this means the file could not be found)."); continue; } // Restore ShipConstruction ship ShipConstruction.ShipConfig = currentShip; // Set the name if (string.IsNullOrEmpty(vesselData.name)) { vesselData.name = shipConstruct.shipName; } // Set some parameters that need to be at the part level uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.flightID = flightId; p.missionID = missionID; p.launchID = launchID; p.flagURL = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL; } // Assign crew to the vessel foreach (CrewData cd in vesselData.crew) { bool success = false; // Find a seat for the crew Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity); // Add the crew member if (part != null) { // Create the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); if (cd.name != null) { crewMember.name = cd.name; } // Add them to the part success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); } if (!success) { LoggingUtil.LogWarning(this, "Unable to add crew to vessel named '" + vesselData.name + "'. Perhaps there's no room?"); break; } } // Set additional info for landed kerbals if (vesselData.landed) { if (vesselData.altitude == null) { vesselData.altitude = LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body); } Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value); vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body); vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime()); LoggingUtil.LogDebug(this, "vesselData generated, orbit = " + vesselData.orbit); } // Create a dummy ProtoVessel, we will use this to dump the parts to a config node. // We can't use the config nodes from the .craft file, because they are in a // slightly different format than those required for a ProtoVessel (seriously // Squad?!?). ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; // Create the ProtoPartSnapshot objects and then initialize them foreach (Part p in shipConstruct.parts) { dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } // Estimate an object class, numbers are based on the in game description of the // size classes. float size = shipConstruct.shipSize.magnitude / 2.0f; UntrackedObjectClass sizeClass; if (size < 4.0f) { sizeClass = UntrackedObjectClass.A; } else if (size < 7.0f) { sizeClass = UntrackedObjectClass.B; } else if (size < 12.0f) { sizeClass = UntrackedObjectClass.C; } else if (size < 18.0f) { sizeClass = UntrackedObjectClass.D; } else { sizeClass = UntrackedObjectClass.E; } // Create the ship's parts ConfigNode[] partNodes = dummyProto.protoPartSnapshots.Select <ProtoPartSnapshot, ConfigNode>(GetNodeForPart).ToArray(); // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[1]; DiscoveryLevels discoveryLevel = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed vessel if (vesselData.landed) { // Create the config node representation of the ProtoVessel protoVesselNode.SetValue("sit", Vessel.Situations.LANDED.ToString()); protoVesselNode.SetValue("landed", true.ToString()); protoVesselNode.SetValue("lat", vesselData.latitude.ToString()); protoVesselNode.SetValue("lon", vesselData.longitude.ToString()); protoVesselNode.SetValue("alt", vesselData.altitude.ToString()); protoVesselNode.SetValue("landedAt", vesselData.body.name); // Figure out the additional heigh to subtract float lowest = float.MaxValue; foreach (Part p in shipConstruct.parts) { foreach (Collider collider in p.GetComponentsInChildren <Collider>()) { if (collider.gameObject.layer != 21 && collider.enabled) { lowest = Mathf.Min(lowest, collider.bounds.min.y); } } } // Figure out the surface height and rotation Vector3d norm = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude); Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, Vector3.up) * Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); protoVesselNode.SetValue("hgt", (shipConstruct.parts[0].localRoot.attPos0.y - lowest).ToString()); protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation)); } // Add vessel to the game ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); // Store the id for later use vesselData.id = protoVessel.vesselRef.id; // Associate it so that it can be used in contract parameters ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef); } vesselsCreated = true; }
public void Update() { // Wait for the strategy system to get loaded if (KSP.UI.Screens.Administration.Instance == null) { ticks = 0; return; } if (ticks++ == 0) { // Resize the root element that handles the width LoggingUtil.LogDebug(this, "Modifying width of admin screen..."); Transform aspectFitter = KSP.UI.Screens.Administration.Instance.transform.FindDeepChild("bg and aspectFitter"); if (aspectFitter != null) { RectTransform rect = aspectFitter.GetComponent <RectTransform>(); // Determine the ideal size int count = Math.Max(StrategySystem.Instance.SystemConfig.Departments.Count - 4, 0); float size = Math.Min(944f + (count * 232.0f), Screen.width); rect.sizeDelta = new Vector2(size, rect.sizeDelta.y); } // Clean up the strategy max text LoggingUtil.LogDebug(this, "Cleaning up strategy max text..."); Transform stratCountTransform = KSP.UI.Screens.Administration.Instance.transform.FindDeepChild("ActiveStratCount"); TextMeshProUGUI stratCountText = stratCountTransform.GetComponent <TextMeshProUGUI>(); int limit = Administration.Instance.MaxActiveStrategies - 1; if (!stratCountText.text.Contains("Max: " + limit)) { stratCountText.text = "Active Strategies: " + Administration.Instance.ActiveStrategyCount + " [Max: " + limit + "]"; } // Replace department avatars with images when necessary LoggingUtil.LogDebug(this, "Performing department image replacement..."); Transform scrollListKerbals = KSP.UI.Screens.Administration.Instance.transform.FindDeepChild("scroll list kerbals"); foreach (DepartmentConfig department in StrategySystem.Instance.SystemConfig.Departments) { // If there is no avatar prefab but there is a head image, use that in place if (department.AvatarPrefab == null) { // Get the head image Texture2D tex = department.HeadImage; if (tex == null) { // Pull from texture DB if possible if (GameDatabase.Instance.ExistsTexture(department.HeadImageString)) { tex = GameDatabase.Instance.GetTexture(department.HeadImageString, false); } // Otherwise just load it else { tex = TextureUtil.LoadTexture(department.HeadImageString); } } for (int i = 0; i < scrollListKerbals.childCount; i++) { Transform t = scrollListKerbals.GetChild(i); KerbalListItem kerbalListItem = t.GetComponent <KerbalListItem>(); if (kerbalListItem.title.text.Contains(department.HeadName)) { LoggingUtil.LogDebug(this, "Replacing admin building texture for department {0}", department.HeadName); kerbalListItem.kerbalImage.texture = tex; kerbalListItem.kerbalImage.material = kerbalListItem.kerbalImage.defaultMaterial; // Remove extra braces if (kerbalListItem.title.text.Contains("()")) { kerbalListItem.title.text.Replace("()", ""); } break; } } } } } }
private IEnumerator <YieldInstruction> NovaCoroutine() { LoggingUtil.LogDebug(this, "Jool is going nova"); state = State.JOOL_SHRINK; joolScale = 1.0f; SetTransformed(false); // Get the AtmosphereFromGround object AtmosphereFromGround afg = Resources.FindObjectsOfTypeAll <AtmosphereFromGround>(). Where(a => a != null && a.planet != null && a.planet.name == "Jool").First(); // Capture original scaling info origScale = jool.scaledBody.transform.localScale; origInnerRadius = afg.innerRadius; origOuterRadius = afg.outerRadius; origAtmoScale = afg.transform.localScale; // Rescale over every iteration while (true) { // Check if this will be the last scaling operation bool lastIteration = joolScale <= SHRUNK_SCALE; if (lastIteration) { joolScale = SHRUNK_SCALE; } // Rescale Jool's ScaledVersion Transform jool.scaledBody.transform.localScale = origScale * joolScale; // Rescale atmosphere afg.innerRadius = origInnerRadius * joolScale; afg.outerRadius = origOuterRadius * joolScale; afg.transform.localScale = origAtmoScale * joolScale; afg.KrESun = afg.Kr * afg.ESun; afg.KmESun = afg.Km * afg.ESun; afg.Kr4PI = afg.Kr * 4f * (float)Math.PI; afg.Km4PI = afg.Km * 4f * (float)Math.PI; afg.g2 = afg.g * afg.g; afg.outerRadius2 = afg.outerRadius * afg.outerRadius; afg.innerRadius2 = afg.innerRadius * afg.innerRadius; afg.scale = 1f / (afg.outerRadius - afg.innerRadius); afg.scaleDepth = -0.25f; afg.scaleOverScaleDepth = afg.scale / afg.scaleDepth; afg.SetMaterial(true); yield return(null); if (lastIteration) { break; } } // Do the transformation SetTransformed(true); // Add our extra stuff GameObject explosion = new GameObject("Explosion"); explosion.transform.parent = jool.scaledBody.transform; explosion.layer = jool.scaledBody.layer; explosion.transform.localScale = Vector3.one * 1.01f; explosion.transform.localPosition = Vector3.zero; explosion.transform.localRotation = Quaternion.identity; MeshRenderer explosionRenderer = explosion.AddComponent <MeshRenderer>(); foreach (FieldInfo field in typeof(MeshRenderer).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { field.SetValue(explosionRenderer, field.GetValue(jool.scaledBody.GetComponent <MeshRenderer>())); } Texture2D explosionTex = TextureUtil.LoadTexture("ContractPacks/JoolianEncounter/Images/explosion.dds.noload"); explosionRenderer.material.shader = Shader.Find("KSP/Alpha/Translucent"); explosionRenderer.material.SetTexture(Shader.PropertyToID("_MainTex"), explosionTex); MeshFilter explosionMesh = explosion.AddComponent <MeshFilter>(); explosionMesh.sharedMesh = jool.scaledBody.GetComponent <MeshFilter>().sharedMesh; explosion.SetActive(true); // Rescale over every iteration joolScale = SHRUNK_SCALE; state = State.SUN_GROW; stateTime = Time.time; while (true) { // Check if this will be the last scaling operation bool lastIteration = joolScale >= FINAL_SCALE; if (lastIteration) { joolScale = FINAL_SCALE; } // Rescale Jool's scaled body Transform jool.scaledBody.transform.localScale = origScale * joolScale; // Fade the alpha out as the explosion grows float alpha = Mathf.Lerp(1.0f, 0.0f, (explosionScale / joolScale) / 10.0f); explosionRenderer.material.color = new Color(1.0f, 1.0f, 1.0f, alpha); // Rescale the explosion explosion.transform.localScale = Vector3.one * (explosionScale / joolScale); if (lastIteration) { break; } yield return(null); } // Continue with the outer part of the explosion state = State.EXPLOSION_GROW; explosionsDone = false; while (true) { // Rescale the explosion explosion.transform.localScale = Vector3.one * (explosionScale / joolScale); // Stop burninating 5000 km after it has passed if ((explosionScale / joolScale) * 1.01f * jool.Radius >= FlightGlobals.ActiveVessel.altitude + jool.Radius + 5000000) { burninating = false; } // There's a big delay before the atmospheric effects kick in, so start burninating pretty early (5000 km) else if (!burninating && (explosionScale / joolScale) * jool.Radius >= FlightGlobals.ActiveVessel.altitude + jool.Radius - 5000000) { burninating = true; StartCoroutine(Burninator()); } // Blow up the ship! (part of it) if (!explosionsDone && (explosionScale / joolScale) * jool.Radius >= FlightGlobals.ActiveVessel.altitude + jool.Radius) { ExplodeParts(); // Do a camera wobble LoggingUtil.LogDebug(this, "overheat event"); FlightCameraFX fcfx = UnityEngine.Object.FindObjectOfType <FlightCameraFX>(); MethodInfo eventMethod = typeof(FlightCameraFX).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic). Where(mi => mi.Name == "OnVesselEvent").First(); eventMethod.Invoke(fcfx, new object[] { new EventReport(FlightEvents.OVERHEAT, FlightGlobals.ActiveVessel.rootPart, FlightGlobals.ActiveVessel.name, "Jool") }); } // Fade the alpha out as the explosion grows float alpha = Mathf.Lerp(1.0f, 0.0f, (explosionScale / joolScale) / 10.0f); explosionRenderer.material.color = new Color(1.0f, 1.0f, 1.0f, alpha); if ((explosionScale / joolScale) >= 10.0f) { break; } yield return(null); } // Remove explodey part burninating = false; explosion.transform.parent = null; Destroy(explosion); Destroy(explosionTex); }
public void Start() { LoggingUtil.LogVerbose(this, "Start"); // Don't run if not in career if (!HighLogic.CurrentGame.scenarios.Any(sm => sm.moduleName == "ContractConfiguratorSettings")) { LoggingUtil.LogDebug(this, "Destroying TrackingStationUI - not in career mode."); Destroy(this); return; } // Get the last button in the list to use as a copy MapViewFiltering.FilterButton lastButton = MapViewFiltering.Instance.FilterButtons.Last(); // Create our copies activeWaypointButton = UnityEngine.Object.Instantiate(lastButton.button.gameObject); activeWaypointButton.name = "Button Active Waypoints"; offeredWaypointButton = UnityEngine.Object.Instantiate(lastButton.button.gameObject); offeredWaypointButton.name = "Button Offered Waypoints"; activeOrbitButton = UnityEngine.Object.Instantiate(lastButton.button.gameObject); activeOrbitButton.name = "Button Active Orbits"; offeredOrbitButton = UnityEngine.Object.Instantiate(lastButton.button.gameObject); offeredOrbitButton.name = "Button Offered Orbits"; // Fix z coordinates activeWaypointButton.GetComponent <RectTransform>().SetLocalPositionZ(750); offeredWaypointButton.GetComponent <RectTransform>().SetLocalPositionZ(750); activeOrbitButton.GetComponent <RectTransform>().SetLocalPositionZ(750); offeredOrbitButton.GetComponent <RectTransform>().SetLocalPositionZ(750); // Set up the tool-tips activeWaypointButton.GetComponent <TooltipController_Text>().textString = "Toggle Active Waypoints"; offeredWaypointButton.GetComponent <TooltipController_Text>().textString = "Toggle Offered Waypoints"; activeOrbitButton.GetComponent <TooltipController_Text>().textString = "Toggle Active Orbits"; offeredOrbitButton.GetComponent <TooltipController_Text>().textString = "Toggle Offered Orbits"; // Setup the button TrackingStationObjectButton activeWaypointTSButton = activeWaypointButton.GetComponent <TrackingStationObjectButton>(); TrackingStationObjectButton offeredWaypointTSButton = offeredWaypointButton.GetComponent <TrackingStationObjectButton>(); TrackingStationObjectButton activeOrbitTSButton = activeOrbitButton.GetComponent <TrackingStationObjectButton>(); TrackingStationObjectButton offeredOrbitTSButton = offeredOrbitButton.GetComponent <TrackingStationObjectButton>(); // Setup handlers activeWaypointTSButton.OnClickLeft.AddListener(new UnityAction(ActiveWaypointButtonClick)); activeWaypointTSButton.OnClickRight.AddListener(new UnityAction(ActiveWaypointButtonClick)); offeredWaypointTSButton.OnClickLeft.AddListener(new UnityAction(OfferedWaypointButtonClick)); offeredWaypointTSButton.OnClickRight.AddListener(new UnityAction(OfferedWaypointButtonClick)); activeOrbitTSButton.OnClickLeft.AddListener(new UnityAction(ActiveOrbitButtonClick)); activeOrbitTSButton.OnClickRight.AddListener(new UnityAction(ActiveOrbitButtonClick)); offeredOrbitTSButton.OnClickLeft.AddListener(new UnityAction(OfferedOrbitButtonClick)); offeredOrbitTSButton.OnClickRight.AddListener(new UnityAction(OfferedOrbitButtonClick)); // Setup sprites activeWaypointTSButton.spriteTrue = activeWaypointEnabledSprite; activeWaypointTSButton.spriteFalse = activeWaypointDisabledSprite; offeredWaypointTSButton.spriteTrue = offeredWaypointEnabledSprite; offeredWaypointTSButton.spriteFalse = offeredWaypointDisabledSprite; activeOrbitTSButton.spriteTrue = activeOrbitEnabledSprite; activeOrbitTSButton.spriteFalse = activeOrbitDisabledSprite; offeredOrbitTSButton.spriteTrue = offeredOrbitEnabledSprite; offeredOrbitTSButton.spriteFalse = offeredOrbitDisabledSprite; // Set defaults activeWaypointButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayActiveWaypoints); offeredWaypointButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayOfferedWaypoints); activeOrbitButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayActiveOrbits); offeredOrbitButton.GetComponent <TrackingStationObjectButton>().SetState(ContractConfiguratorSettings.Instance.DisplayOfferedOrbits); // Disable counts activeWaypointButton.GetChild("Count").SetActive(false); offeredWaypointButton.GetChild("Count").SetActive(false); activeOrbitButton.GetChild("Count").SetActive(false); offeredOrbitButton.GetChild("Count").SetActive(false); // Re-parent GameObject trackingFilters = lastButton.button.transform.parent.gameObject; RectTransform trackingFiltersRect = trackingFilters.GetComponent <RectTransform>(); trackingFiltersRect.sizeDelta = new Vector2(trackingFiltersRect.sizeDelta.x + 44 * 2, trackingFiltersRect.sizeDelta.y); activeWaypointButton.transform.SetParent(trackingFilters.transform); offeredWaypointButton.transform.SetParent(trackingFilters.transform); activeOrbitButton.transform.SetParent(trackingFilters.transform); offeredOrbitButton.transform.SetParent(trackingFilters.transform); activeWaypointButton.SetActive(true); offeredWaypointButton.SetActive(true); activeOrbitButton.SetActive(true); offeredOrbitButton.SetActive(true); LoggingUtil.LogVerbose(this, "Finished setup"); }
void Start() { LoggingUtil.LogDebug(typeof(MonolithParameter), "VelocityHandler startup"); }
protected bool CheckParameters(MonolithState paramState) { if (paramState < currentState) { return(true); } // StarJeb not active vessel if (starJeb != null && FlightGlobals.ActiveVessel != starJeb || candidate != null && FlightGlobals.ActiveVessel != candidate) { stepTime = Time.fixedTime; return(false); } // Create the velocity change handler if (velHdlr == null) { LoggingUtil.LogDebug(this, "Adding VelocityHandler"); velHdlr = MapView.MapCamera.gameObject.AddComponent <VelocityHandler>(); velHdlr.param = this; } switch (currentState) { case MonolithState.STARTED: // Look for an eva if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.vesselType == VesselType.EVA) { candidate = FlightGlobals.ActiveVessel; candidateName = candidate.vesselName; LoggingUtil.LogDebug(this, "Got an eva, starJeb = " + candidate.vesselName); nextState(); return(true); } return(false); case MonolithState.EVA: { Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One"); float discoveryDistance = discovery == null ? 10000 : Vector3.Distance(discovery.transform.position, candidate.transform.position); if (distance < 10000 && discoveryDistance > distance && Time.fixedTime - stepTime > 10.0f || distance < MONOLITH_TOO_CLOSE) { // Store Star Jeb's name starJeb = candidate; starJebName = candidateName; PersistentDataStore.Instance.Store <string>("starJebName", starJebName); // Store Star Jeb's friend's name ProtoCrewMember protoStarJeb = candidate.GetVesselCrew().First(); if (discovery != null) { string trait = protoStarJeb.experienceTrait.TypeName == "Scientist" ? "Pilot" : "Scientist"; ProtoCrewMember notStarJeb = discovery.GetVesselCrew().Where(pcm => pcm.experienceTrait.TypeName == trait).FirstOrDefault(); if (notStarJeb != null) { PersistentDataStore.Instance.Store <string>("notStarJebName", notStarJeb.name); } } candidate = null; nextState(); // Set the right image (male vs. female) for the end sequence ConfiguredContract contract = Root as ConfiguredContract; DialogBox dialogBox = contract.Behaviours.Select(b => b as DialogBox).Where(b => b != null).FirstOrDefault(); if (dialogBox != null) { FieldInfo detailsField = typeof(DialogBox).GetFields(BindingFlags.Instance | BindingFlags.NonPublic). Where(fi => fi.FieldType == typeof(List <DialogBox.DialogDetail>)).First(); DialogBox.DialogDetail detail = ((List <DialogBox.DialogDetail>)detailsField.GetValue(dialogBox)).First(); DialogBox.ImageSection starJebImage = detail.sections.First() as DialogBox.ImageSection; starJebImage.imageURL = protoStarJeb.gender == ProtoCrewMember.Gender.Male ? "ContractPacks/AnomalySurveyor/Images/starjeb.dds.noload" : "ContractPacks/AnomalySurveyor/Images/starjeb_female.dds.noload"; } return(true); } } return(false); case MonolithState.FULL_OF_STARS1: { // Backup progress tracking progressTreeBackup = new ConfigNode("PROGRESS_TREE_BACKUP"); ProgressTracking.Instance.OnSave(progressTreeBackup); // Give the first kick away from Jool - this one using regular velocity change CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); // Find closest point on the jool-monolith line, and throw us away from that (so we don't hit either) Vector3 line = monolith.transform.position - jool.transform.position; float t = Vector3.Dot(line, (starJeb.transform.position - jool.transform.position)) / Vector3.Dot(line, line); Vector3 closest = jool.transform.position + line * t; velocity = (starJeb.transform.position - (t > 1.0 ? jool.transform.position : closest)).normalized; velocity += new Vector3(0.0f, 0.1f, 0.0f); velocity *= 15000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); // Camera to target jool FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition((starJeb.transform.position - jool.transform.position).normalized * 25.0f); } return(false); case MonolithState.FULL_OF_STARS2: if (Time.fixedTime - stepTime > 4.0f) { // Give the second kick away from Jool - these using anti-kraken velocity change CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity += new Vector3(0.0f, 0.1f, 0.0f); velocity *= 1500000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS3: if (Time.fixedTime - stepTime > 3.0f) { // Give the third kick away from Jool CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity *= 20000000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS4: if (Time.fixedTime - stepTime > 2.0f) { // Give the fourth and final kick away from Jool CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity *= 200000000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS5: if (Time.fixedTime - stepTime > 2.0f) { // Move along nextState(); } return(false); case MonolithState.FULL_OF_STARS_DRES1: { // Visit Dres CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First(); // Determine which side the sun is on - makes for a better show CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - dres.transform.position; sunnySide.x = 0.0f; sunnySide.y = 1; // Move across the top of the planet sunnySide.z = Math.Sign(sunnySide.z); // Set position for starjeb float distance = 4.0f * (float)dres.Radius; starJeb.SetPosition(dres.transform.position + new Vector3(distance, (float)dres.Radius, (float)dres.Radius * sunnySide.z)); velocity = (dres.transform.position - starJeb.transform.position + sunnySide * ((float)dres.Radius)).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); starJeb.SetWorldVelocity(dres.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_DRES2: { // Camera to target Dres - do this on a seperate update to allow KSP to catch up CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - dres.transform.position).normalized * 10.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_DRES3: if (Time.fixedTime - stepTime > 5.5f) { // Done with Dres nextState(); } return(false); case MonolithState.FULL_OF_STARS_DUNA1: { // Start between the sun and Duna CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - duna.transform.position; sunnySide.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)duna.Radius; starJeb.SetPosition(duna.transform.position + sunnySide * distance); // Go straight at Duna velocity = (duna.transform.position - starJeb.transform.position).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); // Now offset him down so he doesn't actually hit Duna... starJeb.SetPosition(starJeb.transform.position + new Vector3(0.0f, -((float)duna.Radius + 55000), 0.0f)); starJeb.SetWorldVelocity(duna.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_DUNA2: { // Camera to target Duna - do this on a seperate update to allow KSP to catch up CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - duna.transform.position).normalized * 25.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_DUNA3: if (Time.fixedTime - stepTime > 5.5f) { // Done with Duna nextState(); } return(false); case MonolithState.FULL_OF_STARS_EELOO1: { // Start perpendicular to the sun and Eeloo CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 perp = eeloo.transform.position - sun.transform.position; float tmp = perp.x; perp.x = -perp.z; perp.z = tmp; perp.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)eeloo.Radius; starJeb.SetPosition(eeloo.transform.position + perp * distance); // Determine which side the sun is on - makes for a better show Vector3 sunnySide = sun.transform.position - eeloo.transform.position; sunnySide.Normalize(); // Go straight at Eeloo velocity = (eeloo.transform.position - starJeb.transform.position).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); // Now offset him down so he doesn't actually hit Eeloo... starJeb.SetPosition(starJeb.transform.position + sunnySide * ((float)eeloo.Radius * 1.5f)); starJeb.SetWorldVelocity(eeloo.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_EELOO2: { // This time won't target directly towards Eeloo, as the player will have some idea // what is up by now. CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 awayFromSun = sun.transform.position - eeloo.transform.position; awayFromSun.Normalize(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromSun * 50.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_EELOO3: if (Time.fixedTime - stepTime > 5.5f) { velocity = null; // Done with Eeloo nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE1: { CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); Vector3 targetPosition = Destination.Value; Vector3 normal = eve.GetSurfaceNVector(eveLatitude, eveLongitude); startDistance = 10000000f; Vector3 start = targetPosition + normal * startDistance; starJeb.SetPosition(start); nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE2: { // Camera straight towards Eve - we're going in! CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); Vector3 awayFromEve = starJeb.transform.position - eve.transform.position; awayFromEve.Normalize(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromEve * 15.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_EVE3: // Wait until we've held the position for a split second if (Time.fixedTime - stepTime >= 9.3f) { nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE4: // Give the player a bit to get settled, then let the fun begins if (Time.fixedTime - stepTime >= 15.0f) { // Spawn some asteroids CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); ScenarioDiscoverableObjects asteroidSpawner = (ScenarioDiscoverableObjects)HighLogic.CurrentGame.scenarios.Find( s => s.moduleRef is ScenarioDiscoverableObjects).moduleRef; System.Random random = new System.Random(); // Spawn some more asteroids for (int i = 0; i < ASTEROID_COUNT; i++) { asteroidSpawner.SpawnAsteroid(); } nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE5: // Wait a full second after spawning the asteroids - we're not allowed to pull // them off rails until they've been active a bit if (Time.fixedTime - stepTime > 1.0f) { // Spawn some asteroids CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); System.Random random = new System.Random(); foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT)) { // Set the position double r = random.NextDouble() * 0.02 + 0.002; double theta = random.NextDouble() * 2.0 * Math.PI; double latitude = starJeb.latitude + r * Math.Sin(theta); double longitude = starJeb.longitude + r * Math.Cos(theta); double altitude = starJeb.altitude + 100 + random.NextDouble() * 200; asteroid.SetPosition(eve.GetWorldSurfacePosition(latitude, longitude, altitude)); asteroid.ChangeWorldVelocity(asteroid.GetSrfVelocity()); asteroid.Load(); asteroid.GoOffRails(); } nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE6: { // Determine if there's an asteroid about to kill us CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); bool killerAsteroid = FlightGlobals.Vessels.Where(v => v.mainBody == eve && v.vesselType == VesselType.SpaceObject && Vector3.Distance(starJeb.transform.position, v.transform.position) < 5.5 * ((int)v.DiscoveryInfo.objectSize + 1)).Any(); if (killerAsteroid || Time.fixedTime - stepTime > 20.0f) { foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT)) { asteroid.Die(); } nextState(); } } return(false); case MonolithState.FULL_OF_STARS_KERBIN1: { CheatOptions.NoCrashDamage = false; // Start between the sun and Kerbin CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - kerbin.transform.position; sunnySide.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)kerbin.Radius; starJeb.SetPosition(kerbin.transform.position + sunnySide * distance); // Orient him properly KerbalEVA keva = starJeb.FindPartModulesImplementing <KerbalEVA>().First(); MethodInfo rotationMethod = typeof(KerbalEVA).GetMethod("correctGroundedRotation", BindingFlags.Instance | BindingFlags.NonPublic); starJeb.packed = true; rotationMethod.Invoke(keva, new object[] { }); starJeb.packed = false; // Hardcode an orbital velocity, because it's late and I'm tired starJeb.SetWorldVelocity(kerbin.getRFrmVel(starJeb.transform.position).normalized * 1085); nextState(); } return(false); case MonolithState.FULL_OF_STARS_KERBIN2: { // Camera to target kerbin - do this on a seperate update to allow KSP to catch up CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 10.0f); starJeb.SetRotation(FlightCamera.fetch.transform.rotation * Quaternion.AngleAxis(180.0f, FlightCamera.fetch.transform.up)); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_KERBIN3: if (Time.fixedTime - stepTime > 2.0f) { // Turn into star jeb CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); starJeb.vesselName = "The Star Jeb"; Undress(starJeb.gameObject); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 1.5f); nextState(); } return(false); case MonolithState.FULL_OF_STARS_KERBIN4: if (Time.fixedTime - stepTime < 15.0f) { CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); Vector3 camDirection = starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized; } else { nextState(); monolith.Die(); monolith = null; starJeb.Die(); starJeb = null; Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One"); FlightGlobals.ForceSetActiveVessel(discovery); } return(false); case MonolithState.FULL_OF_STARS_FINAL: nextState(); return(true); default: return(false); } }