protected void nautListRow(tabs currentTab, ProtoCrewMember student) { GUIStyle style = HighLogic.Skin.label; ActiveCourse currentCourse = null; if (activeMap.ContainsKey(student)) { currentCourse = activeMap[student]; } bool onSelectedCourse = selectedCourse != null && currentCourse != null && currentCourse.id == selectedCourse.id; if (onSelectedCourse) { style = boldLabel; } bool selectedForCourse = selectedCourse != null && selectedCourse.Students.Contains(student); GUILayout.BeginHorizontal(); try { GUILayout.Label(String.Format("{0} {1}", student.trait.Substring(0, 1), student.experienceLevel), GUILayout.Width(24)); if (currentCourse == null && selectedCourse != null && (selectedForCourse || selectedCourse.MeetsStudentReqs(student))) { if (toggleButton(student.name, selectedForCourse, GUILayout.Width(96))) { if (selectedForCourse) { selectedCourse.RemoveStudent(student); } else { selectedCourse.AddStudent(student); } } } else if (currentTab == tabs.Training) { if (GUILayout.Button(student.name, GUILayout.Width(96))) { selectedNaut = student; } } else { GUILayout.Label(student.name, GUILayout.Width(96)); } string course, complete, retires; if (currentCourse == null) { if (student.inactive) { course = "(inactive)"; complete = KSPUtil.PrintDate(student.inactiveTimeEnd, false); } else { course = "(free)"; complete = "(n/a)"; } } else { course = currentCourse.name; complete = KSPUtil.PrintDate(currentCourse.CompletionTime(), false); } GUILayout.Label(course, GUILayout.Width(96)); GUILayout.Label(complete, GUILayout.Width(80)); if (CrewHandler.Instance.kerbalRetireTimes.ContainsKey(student.name)) { retires = KSPUtil.PrintDate(CrewHandler.Instance.kerbalRetireTimes[student.name], false); } else { retires = "(unknown)"; } GUILayout.Label(retires, GUILayout.Width(80)); if (currentCourse != null) { if (currentCourse.seatMin > 1) { if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) { cancelCourse(currentCourse); } } else { if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) { leaveCourse(currentCourse, student); } } } } finally { GUILayout.EndHorizontal(); } }
public static string GetTimeLabel(SubspaceDisplayEntry currentEntry) { return($"T: +{KSPUtil.PrintTimeCompact(SystemsContainer.Get<WarpSystem>().GetSubspaceTime(currentEntry.SubspaceId), false)}"); }
public void Update() { if (HighLogic.CurrentGame == null || HighLogic.CurrentGame.CrewRoster == null) { return; } // Catch earlies if (firstLoad) { firstLoad = false; List <string> newHires = new List <string>(); foreach (ProtoCrewMember pcm in HighLogic.CurrentGame.CrewRoster.Crew) { if ((pcm.rosterStatus == ProtoCrewMember.RosterStatus.Assigned || pcm.rosterStatus == ProtoCrewMember.RosterStatus.Available) && !kerbalRetireTimes.ContainsKey(pcm.name)) { if (pcm.trait != KerbalRoster.pilotTrait) { KerbalRoster.SetExperienceTrait(pcm, KerbalRoster.pilotTrait); } newHires.Add(pcm.name); OnCrewHired(pcm, int.MinValue); } } if (newHires.Count > 0) { string msgStr = "Crew will retire as follows:"; foreach (string s in newHires) { msgStr += "\n" + s + ", no earlier than " + KSPUtil.PrintDate(kerbalRetireTimes[s], false); } PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "InitialRetirementDateNotification", "Initial Retirement Date", msgStr + "\n(Retirement will be delayed the more interesting flights they fly.)", "OK", false, HighLogic.UISkin); } } // Retirements double time = Planetarium.GetUniversalTime(); if (nextUpdate < time) { // Ensure that CrewHandler updates happen at predictable times so that accurate KAC alarms can be set. do { nextUpdate += updateInterval; }while (nextUpdate < time); if (retirementEnabled) { foreach (KeyValuePair <string, double> kvp in kerbalRetireTimes) { ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[kvp.Key]; if (pcm == null) { toRemove.Add(kvp.Key); } else { if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Available) { if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Assigned) { toRemove.Add(kvp.Key); } continue; } if (pcm.inactive) { continue; } if (time > kvp.Value) { toRemove.Add(kvp.Key); retirees.Add(kvp.Key); pcm.rosterStatus = ProtoCrewMember.RosterStatus.Dead; } } } } bool anyCourseEnded = false; for (int i = ActiveCourses.Count; i-- > 0;) { ActiveCourse course = ActiveCourses[i]; if (course.ProgressTime(time)) //returns true when the course completes { ActiveCourses.RemoveAt(i); anyCourseEnded = true; } } for (int i = expireTimes.Count; i-- > 0;) { TrainingExpiration e = expireTimes[i]; if (time > e.expiration) { ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[e.pcmName]; if (pcm != null) { for (int j = pcm.careerLog.Entries.Count; j-- > 0;) { int eC = e.entries.Count; if (eC == 0) { break; } FlightLog.Entry ent = pcm.careerLog[j]; for (int k = eC; k-- > 0;) { // Allow only mission trainings to expire. // This check is actually only needed for old savegames as only these can have expirations on proficiencies. if (ent.type == "TRAINING_mission" && e.Compare(k, ent)) { ScreenMessages.PostScreenMessage(pcm.name + ": Expired: " + GetPrettyCourseName(ent.type) + ent.target); ent.type = "expired_" + ent.type; e.entries.RemoveAt(k); } } } } expireTimes.RemoveAt(i); } } // TODO remove from courses? Except I think they won't retire if inactive either so that's ok. if (toRemove.Count > 0) { string msgStr = string.Empty; foreach (string s in toRemove) { kerbalRetireTimes.Remove(s); if (HighLogic.CurrentGame.CrewRoster[s] != null && retirees.Contains(s)) { msgStr = $"{msgStr}\n{s}"; } } if (!string.IsNullOrEmpty(msgStr)) { PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "CrewRetirementNotification", "Crew Retirement", "The following retirements have occurred:\n" + msgStr, "OK", true, HighLogic.UISkin); } toRemove.Clear(); } if (anyCourseEnded || toRemove.Count > 0) { MaintenanceHandler.Instance?.UpdateUpkeep(); } } // UI fixing if (inAC) { if (astronautComplex == null) { KSP.UI.Screens.AstronautComplex[] mbs = GameObject.FindObjectsOfType <KSP.UI.Screens.AstronautComplex>(); int maxCount = -1; foreach (KSP.UI.Screens.AstronautComplex c in mbs) { int count = c.ScrollListApplicants.Count + c.ScrollListAssigned.Count + c.ScrollListAvailable.Count + c.ScrollListKia.Count; if (count > maxCount) { maxCount = count; astronautComplex = c; } } if (astronautComplex == null) { return; } } int newAv = astronautComplex.ScrollListAvailable.Count; int newAsgn = astronautComplex.ScrollListAssigned.Count; int newKIA = astronautComplex.ScrollListKia.Count; if (newAv != countAvailable || newKIA != countKIA || newAsgn != countAssigned) { countAvailable = newAv; countAssigned = newAsgn; countKIA = newKIA; foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListAvailable) { KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>(); if (cli != null) { FixTooltip(cli); if (cli.GetCrewRef().inactive) { cli.MouseoverEnabled = false; bool notTraining = true; for (int i = ActiveCourses.Count; i-- > 0 && notTraining;) { foreach (ProtoCrewMember pcm in ActiveCourses[i].Students) { if (pcm == cli.GetCrewRef()) { notTraining = false; cli.SetLabel("Training, done " + KSPUtil.PrintDate(ActiveCourses[i].startTime + ActiveCourses[i].GetTime(ActiveCourses[i].Students), false)); break; } } } if (notTraining) { cli.SetLabel("Recovering"); } } } } foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListAssigned) { KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>(); if (cli != null) { FixTooltip(cli); } } foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListKia) { KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>(); if (cli != null) { if (retirees.Contains(cli.GetName())) { cli.SetLabel("Retired"); cli.MouseoverEnabled = false; } } } } } }
public void CalculateMass() { if (tankList == null || !massDirty) { return; } massDirty = false; double basemass = basemassConst + basemassPV * (MFSSettings.basemassUseTotalVolume ? totalVolume : volume); CalculateMassRF(ref basemass); if (basemass >= 0) { double tankDryMass = 0; for (int i = 0; i < tankList.Count; i++) { var tank = tankList[i]; tankDryMass += tank.maxAmount * tank.mass / tank.utilization; } mass = (float)((basemass + tankDryMass) * MassMult); // compute massDelta based on prefab, if available. if (part.partInfo == null || part.partInfo.partPrefab == null) { part.mass = mass; massDelta = 0; } else { massDelta = mass - part.partInfo.partPrefab.mass; } } else { mass = part.mass; // display dry mass even in this case. massDelta = 0f; } if (isEditor) { UsedVolume = tankList .Where(fuel => fuel.maxAmount > 0 && fuel.utilization > 0) .Sum(fuel => fuel.maxAmount / fuel.utilization); double availRounded = AvailableVolume; if (Math.Abs(availRounded) < 0.001d) { availRounded = 0d; } string availVolStr = KSPUtil.PrintSI(availRounded, MFSSettings.unitLabel); string volStr = KSPUtil.PrintSI(volume, MFSSettings.unitLabel); volumeDisplay = "Avail: " + availVolStr + " / Tot: " + volStr; double resourceMass = part.Resources.Cast <PartResource> ().Sum(partResource => partResource.maxAmount * partResource.info.density); double wetMass = mass + resourceMass; massDisplay = "Dry: " + FormatMass(mass) + " / Wet: " + FormatMass((float)wetMass); UpdateTweakableMenu(); } }
public void DrawContent(int windowId) { GUILayout.BeginVertical(); GUI.DragWindow(MoveRect); #region Horizontal toolbar GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); var chatButtonStyle = ButtonStyle; if (ChatSystem.Singleton.ChatButtonHighlighted) { chatButtonStyle = HighlightStyle; } if (!SettingsSystem.ServerSettings.DropControlOnVesselSwitching) { var tooltip = "Drops control of the vessels that you are not controlling so other players can control them"; if (GUILayout.Button(new GUIContent("DropCtrl", tooltip), ButtonStyle)) { VesselLockSystem.Singleton.DropAllOtherVesselControlLocks(); } } ChatWindow.Singleton.Display = GUILayout.Toggle(ChatWindow.Singleton.Display, "Chat", chatButtonStyle); CraftLibraryWindow.Singleton.Display = GUILayout.Toggle(CraftLibraryWindow.Singleton.Display, "Craft", ButtonStyle); DebugWindow.Singleton.Display = GUILayout.Toggle(DebugWindow.Singleton.Display, "Debug", ButtonStyle); GUILayout.EndHorizontal(); #endregion #region Players information ScrollPosition = GUILayout.BeginScrollView(ScrollPosition, ScrollStyle); //Draw other subspaces foreach (var currentEntry in SubspaceDisplay) { if (currentEntry.SubspaceId == -1) { //Draw the warping players GUILayout.BeginHorizontal(SubspaceStyle); GUILayout.Label("WARPING"); GUILayout.EndHorizontal(); } else { GUILayout.BeginHorizontal(SubspaceStyle); GUILayout.Label("T: +" + KSPUtil.PrintTimeCompact(WarpSystem.Singleton.GetSubspaceTime(currentEntry.SubspaceId), false)); GUILayout.FlexibleSpace(); if (NotWarpingAndIsFutureSubspace(currentEntry.SubspaceId) && GUILayout.Button("Sync", ButtonStyle)) { WarpSystem.Singleton.CurrentSubspace = currentEntry.SubspaceId; } GUILayout.EndHorizontal(); } foreach (var currentPlayer in currentEntry.Players) { DrawPlayerEntry(currentPlayer == SettingsSystem.CurrentSettings.PlayerName ? StatusSystem.Singleton.MyPlayerStatus : StatusSystem.Singleton.GetPlayerStatus(currentPlayer)); } } GUILayout.EndScrollView(); #endregion GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Disconnect", ButtonStyle)) { DisconnectEventHandled = false; } OptionsWindow.Singleton.Display = GUILayout.Toggle(OptionsWindow.Singleton.Display, "Options", ButtonStyle); GUILayout.EndHorizontal(); GUILayout.EndVertical(); }
/// <summary> /// This method is called once when the part is loaded into the current scene, after OnLoad. /// </summary> /// <param name="state"></param> public override void OnStart(StartState state) { base.OnStart(state); if (GameSettings.VERBOSE_DEBUG_LOG) { Debug.Log("[USI Tools] Rotator.OnStart called."); } // Make sure the text for gui events is set correctly DirectionToggle(IsInverted); StartStopToggle(IsRunning); // Let's see if we can find our fixed mesh and movable mesh try { _fixedMesh = KSPUtil.FindInPartModel(transform, FixedMeshName); _movableMesh = KSPUtil.FindInPartModel(transform, MovableMeshName); if (_fixedMesh != null && _movableMesh != null) { if (GameSettings.VERBOSE_DEBUG_LOG) { Debug.Log("[USI Tools] Rotator.OnStart: Found fixed mesh!"); Debug.Log("[USI Tools] Rotator.OnStart: Found movable mesh!"); } // Give our FixedMesh its own Rigidbody Rigidbody fixedMeshRigidbody = _fixedMesh.gameObject.AddComponent <Rigidbody>(); // Give our MovableMesh its own Rigidbody _movableMesh.gameObject.AddComponent <Rigidbody>(); // Setup a Joint for our MovableMesh and cache a reference to the motor for later _rotatorJoint = _movableMesh.gameObject.AddComponent <HingeJoint>(); _rotatorJointMotor = _rotatorJoint.motor; // Mate the joint to the FixedMesh _rotatorJoint.connectedBody = fixedMeshRigidbody; // Configure other Joint options _rotatorJoint.anchor = Vector3.zero; _rotatorJoint.axis = new Vector3(RotationAxisX, RotationAxisY, RotationAxisZ); _rotatorJoint.autoConfigureConnectedAnchor = true; _rotatorJoint.useMotor = true; _rotatorJoint.breakForce = float.PositiveInfinity; _rotatorJoint.breakTorque = float.PositiveInfinity; // Setup the motor on the joint UpdateMotor(); } else { throw new Exception("Part must contain child GameObjects named " + FixedMeshName + " and " + MovableMeshName + "."); } } catch (Exception ex) { Debug.LogError("[USI Tools] Rotator.OnStart encountered an error: " + ex.Message); } }
private void SpawnVessel(LootBoxVesselData LootBoxVesselData, List <ProtoCrewMember> crewData = null) { // string gameDataDir = KSPUtil.ApplicationRootPath; Debug.Log("[Spawn OrX S Mart] Spawning " + LootBoxVesselData.name); // Set additional info for landed vessels bool landed = false; if (!landed) { landed = true; if (LootBoxVesselData.altitude == null || LootBoxVesselData.altitude < 0) { LootBoxVesselData.altitude = 5;//LocationUtil.TerrainHeight(LootBoxVesselData.latitude, LootBoxVesselData.longitude, LootBoxVesselData.body); } Debug.Log("[Spawn OrX S Mart] SpawnVessel Altitude: " + LootBoxVesselData.altitude); //Vector3d pos = LootBoxVesselData.body.GetWorldSurfacePosition(LootBoxVesselData.latitude, LootBoxVesselData.longitude, LootBoxVesselData.altitude.Value); Vector3d pos = LootBoxVesselData.body.GetRelSurfacePosition(LootBoxVesselData.latitude, LootBoxVesselData.longitude, LootBoxVesselData.altitude.Value); LootBoxVesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, LootBoxVesselData.body); LootBoxVesselData.orbit.UpdateFromStateVectors(pos, LootBoxVesselData.body.getRFrmVel(pos), LootBoxVesselData.body, Planetarium.GetUniversalTime()); } ConfigNode[] partNodes; ShipConstruct shipConstruct = null; bool hasClamp = false; float lcHeight = 0; ConfigNode craftNode; Quaternion craftRotation = Quaternion.identity; if (!string.IsNullOrEmpty(LootBoxVesselData.craftURL)) { // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB! ConfigNode currentShip = ShipConstruction.ShipConfig; shipConstruct = ShipConstruction.LoadShip(LootBoxVesselData.craftURL); if (shipConstruct == null) { Debug.Log("[Spawn OrX S Mart] ShipConstruct was null when tried to load '" + LootBoxVesselData.craftURL + "' (usually this means the file could not be found)."); return;//continue; } craftNode = ConfigNode.Load(LootBoxVesselData.craftURL); lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y; craftRotation = ConfigNode.ParseQuaternion(craftNode.GetNode("PART").GetValue("rot")); // Restore ShipConstruction ship ShipConstruction.ShipConfig = currentShip; // Set the name if (string.IsNullOrEmpty(LootBoxVesselData.name)) { LootBoxVesselData.name = SMIVesselName; ; } // Set some parameters that need to be at the part level uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.missionID = missionID; p.launchID = launchID; p.flagURL = flagURL; // Had some issues with this being set to -1 for some ships - can't figure out // why. End result is the vessel exploding, so let's just set it to a positive // value. p.temperature = 1.0; } // 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(); } // Create the ship's parts List <ConfigNode> partNodesL = new List <ConfigNode>(); foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); } else { // Create crew member array ProtoCrewMember[] crewArray = new ProtoCrewMember[LootBoxVesselData.crew.Count]; /* * int i = 0; * foreach (CrewData cd in LootBoxVesselData.crew) * { * /* * // Create the ProtoCrewMember * ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew); * if (cd.name != null) * { * crewMember.KerbalRef.name = cd.name; * } * * crewArray[i++] = crewMember; * * } */ // Create part nodes uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode(LootBoxVesselData.craftPart.name, flightId, crewArray); // Default the size class //sizeClass = UntrackedObjectClass.A; // Set the name if (string.IsNullOrEmpty(LootBoxVesselData.name)) { LootBoxVesselData.name = LootBoxVesselData.craftPart.name; } } // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[0]; //DiscoveryLevels discoveryLevel = LootBoxVesselData.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(LootBoxVesselData.name, LootBoxVesselData.vesselType, LootBoxVesselData.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed vessel if (!LootBoxVesselData.orbiting) { Vector3d norm = LootBoxVesselData.body.GetRelSurfaceNVector(LootBoxVesselData.latitude, LootBoxVesselData.longitude); double terrainHeight = 0.0; if (LootBoxVesselData.body.pqsController != null) { terrainHeight = LootBoxVesselData.body.pqsController.GetSurfaceHeight(norm) - LootBoxVesselData.body.pqsController.radius; } bool splashed = false;// = landed && terrainHeight < 0.001; // Create the config node representation of the ProtoVessel // Note - flying is experimental, and so far doesn't worx protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ? Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString()); protoVesselNode.SetValue("landed", (landed && !splashed).ToString()); protoVesselNode.SetValue("splashed", splashed.ToString()); protoVesselNode.SetValue("lat", LootBoxVesselData.latitude.ToString()); protoVesselNode.SetValue("lon", LootBoxVesselData.longitude.ToString()); protoVesselNode.SetValue("alt", LootBoxVesselData.altitude.ToString()); protoVesselNode.SetValue("landedAt", LootBoxVesselData.body.name); // Figure out the additional height to subtract float lowest = float.MaxValue; if (shipConstruct != null) { 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); } } } } else { foreach (Collider collider in LootBoxVesselData.craftPart.partPrefab.GetComponentsInChildren <Collider>()) { if (collider.gameObject.layer != 21 && collider.enabled) { lowest = Mathf.Min(lowest, collider.bounds.min.y); } } } if (lowest == float.MaxValue) { lowest = 0; } // Figure out the surface height and rotation Quaternion normal = Quaternion.LookRotation((Vector3)norm);// new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); Quaternion rotation = Quaternion.identity; float heading = LootBoxVesselData.heading; if (shipConstruct == null) { rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back); } else if (shipConstruct.shipFacility == EditorFacility.SPH) { rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward); heading += 180.0f; } else { rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward); rotation = Quaternion.FromToRotation(Vector3.up, -Vector3.up) * rotation; //rotation = craftRotation; LootBoxVesselData.heading = 0; LootBoxVesselData.pitch = 0; } rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back); rotation = rotation * Quaternion.AngleAxis(LootBoxVesselData.roll, Vector3.down); rotation = rotation * Quaternion.AngleAxis(LootBoxVesselData.pitch, Vector3.left); // Set the height and rotation if (landed || splashed) { float hgt = (shipConstruct != null ? shipConstruct.parts[0] : LootBoxVesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest; hgt += LootBoxVesselData.height; protoVesselNode.SetValue("hgt", hgt.ToString(), true); } protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation), true); // Set the normal vector relative to the surface Vector3 nrm = (rotation * Vector3.forward); protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z, true); protoVesselNode.SetValue("prst", false.ToString(), true); } // Add vessel to the game ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); //protoVessel.vesselRef.transform.rotation = protoVessel.rotation; // Store the id for later use LootBoxVesselData.id = protoVessel.vesselRef.id; //protoVessel.vesselRef.currentStage = 0; hasClamp = false; StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp)); // Associate it so that it can be used in contract parameters //ContractVesselTracker.Instance.AssociateVessel(LootBoxVesselData.name, protoVessel.vesselRef); //destroy prefabs foreach (Part p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } }
public override void Draw() { _windowRect = KSPUtil.ClampRectToScreen(ClickThruBlocker.GUIWindow(99, _windowRect, DrawSequenceWindow, "", StyleFactory.LaunchSequenceStyle)); GUI.BringWindowToFront(99); }
protected void nautListRow(tabs currentTab, ProtoCrewMember student) { GUIStyle style = HighLogic.Skin.label; ActiveCourse currentCourse = null; if (activeMap.ContainsKey(student)) { currentCourse = activeMap[student]; } bool onSelectedCourse = selectedCourse != null && currentCourse != null && currentCourse.id == selectedCourse.id; if (onSelectedCourse) { style = boldLabel; } bool selectedForCourse = selectedCourse != null && selectedCourse.Students.Contains(student); GUILayout.BeginHorizontal(); try { GUILayout.Label(String.Format("{0} {1}", student.trait.Substring(0, 1), student.experienceLevel), GUILayout.Width(24)); if (currentCourse == null && selectedCourse != null && (selectedForCourse || selectedCourse.MeetsStudentReqs(student))) { if (toggleButton(student.name, selectedForCourse, GUILayout.Width(144))) { if (selectedForCourse) { selectedCourse.RemoveStudent(student); } else { selectedCourse.AddStudent(student); } } } else if (currentTab == tabs.Training) { if (GUILayout.Button(student.name, GUILayout.Width(144))) { selectedNaut = student; } } else { GUILayout.Label(student.name, GUILayout.Width(144)); } string course, complete, retires; if (currentCourse == null) { if (student.rosterStatus == ProtoCrewMember.RosterStatus.Assigned) { course = "(in-flight)"; complete = KSPUtil.PrintDate(student.inactiveTimeEnd, false); } else if (student.inactive) { course = "(inactive)"; complete = KSPUtil.PrintDate(student.inactiveTimeEnd, false); } else { course = "(free)"; complete = "(n/a)"; } } else { course = currentCourse.name; complete = KSPUtil.PrintDate(currentCourse.CompletionTime(), false); } GUILayout.Label(course, GUILayout.Width(96)); GUILayout.Label(complete, GUILayout.Width(80)); if (CrewHandler.Instance.kerbalRetireTimes.ContainsKey(student.name)) { retires = CrewHandler.Instance.retirementEnabled ? KSPUtil.PrintDate(CrewHandler.Instance.kerbalRetireTimes[student.name], false) : "(n/a)"; } else { retires = "(unknown)"; } GUILayout.Label(retires, GUILayout.Width(80)); if (currentCourse != null) { if (currentCourse.seatMin > 1) { if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) { cancelCourse(currentCourse); } } else { if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) { leaveCourse(currentCourse, student); } } if (KACWrapper.APIReady && GUILayout.Button(nautRowAlarmBtnContent, GUILayout.ExpandWidth(false))) { // CrewHandler processes trainings every 3600 seconds. Need to account for that to set up accurate KAC alarms. double completeUT = currentCourse.CompletionTime(); double timeDiff = completeUT - CrewHandler.Instance.nextUpdate; double timesChRun = Math.Ceiling(timeDiff / CrewHandler.Instance.updateInterval); double alarmUT = CrewHandler.Instance.nextUpdate + timesChRun * CrewHandler.Instance.updateInterval; string alarmTxt = $"{currentCourse.name} - {student.name}"; KACWrapper.KAC.CreateAlarm(KACWrapper.KACAPI.AlarmTypeEnum.Crew, alarmTxt, alarmUT); } } } finally { GUILayout.EndHorizontal(); } }
private void FixAstronauComplexUI() { if (_astronautComplex == null) { AstronautComplex[] mbs = GameObject.FindObjectsOfType <KSP.UI.Screens.AstronautComplex>(); int maxCount = -1; foreach (AstronautComplex c in mbs) { int count = c.ScrollListApplicants.Count + c.ScrollListAssigned.Count + c.ScrollListAvailable.Count + c.ScrollListKia.Count; if (count > maxCount) { maxCount = count; _astronautComplex = c; } } if (_astronautComplex == null) { return; } } int newAv = _astronautComplex.ScrollListAvailable.Count; int newAsgn = _astronautComplex.ScrollListAssigned.Count; int newKIA = _astronautComplex.ScrollListKia.Count; if (newAv != _countAvailable || newKIA != _countKIA || newAsgn != _countAssigned) { _countAvailable = newAv; _countAssigned = newAsgn; _countKIA = newKIA; foreach (UIListData <UIListItem> u in _astronautComplex.ScrollListAvailable) { CrewListItem cli = u.listItem.GetComponent <CrewListItem>(); if (cli != null) { FixTooltip(cli); if (cli.GetCrewRef().inactive) { cli.MouseoverEnabled = false; bool notTraining = true; for (int i = ActiveCourses.Count; i-- > 0 && notTraining;) { foreach (ProtoCrewMember pcm in ActiveCourses[i].Students) { if (pcm == cli.GetCrewRef()) { notTraining = false; cli.SetLabel("Training, done " + KSPUtil.PrintDate(ActiveCourses[i].startTime + ActiveCourses[i].GetTime(ActiveCourses[i].Students), false)); break; } } } if (notTraining) { cli.SetLabel("Recovering"); } } } } foreach (UIListData <UIListItem> u in _astronautComplex.ScrollListAssigned) { CrewListItem cli = u.listItem.GetComponent <CrewListItem>(); if (cli != null) { FixTooltip(cli); } } foreach (UIListData <UIListItem> u in _astronautComplex.ScrollListKia) { CrewListItem cli = u.listItem.GetComponent <CrewListItem>(); if (cli != null) { if (_retirees.Contains(cli.GetName())) { cli.SetLabel("Retired"); cli.MouseoverEnabled = false; } } } } }
public void Load() { Debug.Log("[PR] Loading Data."); //This is called when all persistent rotation data is being loaded from the cfg file. #region ### Quicksave selection ### ConfigNode temp = null; float temp_delta = 0f; ConfigNode load = null; float load_delta = 0f; float oldest_time = 0f; List <String> allPaths = GetAllPaths(); if (allPaths.Count() == 0) { Debug.Log("[PR] No save files found."); return; } foreach (String path in allPaths) { temp = ConfigNode.Load(path); if (temp == null) { Debug.Log("[PR] Couldn't load data: File not found."); continue; } float time = float.Parse(temp.GetValue("TIME")); temp_delta = Mathf.Abs(time - (float)Planetarium.GetUniversalTime()); if (time > oldest_time) { oldest_time = time; } if (load == null) { load = temp; load_delta = temp_delta; } else { if (temp_delta < load_delta) { load = temp; load_delta = temp_delta; } } } #endregion //Load global variables defaultReferenceMode = (DefaultReferenceMode)(int.Parse(load.GetValue("DEFAULT_REFERENCE_MODE"))); //Pregenerate data for all vessels that currently exist foreach (Vessel vessel in FlightGlobals.Vessels) { FindPRVessel(vessel); } //All vessels should now have data. //Load PRVessel data foreach (PRVessel v in PRVessels) { ConfigNode cn_vessel = load.GetNode(v.vessel.id.ToString()); if (cn_vessel != null) //If node exists at all { Debug.Log("[PR] Found node for vessel " + v.vessel.vesselName); v.momentum = KSPUtil.ParseVector3(cn_vessel.GetValue("MOMENTUM")); v.planetariumRight = KSPUtil.ParseVector3(cn_vessel.GetValue("PLANETARIUM_RIGHT")); v.mjMode = MechJebWrapper.saTargetMap[int.Parse(cn_vessel.GetValue("MJMODE"))]; v.rtMode = RemoteTechWrapper.acFlightModeMap[int.Parse(cn_vessel.GetValue("RTMODE"))]; v.rotationModeActive = Boolean.Parse(cn_vessel.GetValue("ROTATION_MODE_ACTIVE")); v.dynamicReference = Boolean.Parse(cn_vessel.GetValue("DYNAMIC_REFERENCE")); v.rotation = KSPUtil.ParseQuaternion(cn_vessel.GetValue("ROTATION")); v.direction = KSPUtil.ParseVector3(cn_vessel.GetValue("DIRECTION")); string reference = cn_vessel.GetValue("REFERENCE"); v.reference = null; if (reference != "NONE") { foreach (CelestialBody body in FlightGlobals.Bodies) { if (body.name == reference) { v.reference = body; } } foreach (Vessel vessel in FlightGlobals.Vessels) { if (vessel.id.ToString() == reference) { v.reference = vessel; } } } v.momentumModeActive = Boolean.Parse(cn_vessel.GetValue("MOMENTUM_MODE_ACTIVE")); v.desiredRPM = float.Parse(cn_vessel.GetValue("DESIRED_RPM")); } } //If old save state is loaded, delete all save files! if (float.Parse(load.GetValue("TIME")) < oldest_time) { Debug.Log("[PR] Reloading old save, flushing data."); foreach (String path in GetAllPaths()) { File.Delete(path); } //Save current loaded one. Save(); } //TODO: Delete all files on Launch / Keep all files that correspond to a quicksave Debug.Log("[PR] Oldest time: " + oldest_time.ToString()); Debug.Log("[PR] Loaded time: " + load.GetValue("TIME")); Interface.instance.desiredRPMstr = FindPRVessel(FlightGlobals.ActiveVessel).desiredRPM.ToString(); //Set desired rpm of active vessel }
private void OnCrewHired(ProtoCrewMember pcm, int idx) { double retireTime = Planetarium.GetUniversalTime() + GetServiceTime(pcm); KerbalRetireTimes[pcm.name] = retireTime; if (RetirementEnabled && idx != int.MinValue) { PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "InitialRetirementDateNotification", "Initial Retirement Date", $"{pcm.name} will retire no earlier than {KSPUtil.PrintDate(retireTime, false)}\n(Retirement will be delayed the more interesting flights they fly.)", "OK", false, HighLogic.UISkin); } }
public string GetTrainingString(ProtoCrewMember pcm) { bool found = false; string trainingStr = "\n\nTraining:"; int lastFlight = pcm.careerLog.Last() == null ? 0 : pcm.careerLog.Last().flight; foreach (FlightLog.Entry ent in pcm.careerLog.Entries) { string pretty = GetPrettyCourseName(ent.type); if (!string.IsNullOrEmpty(pretty)) { if (ent.type == "TRAINING_proficiency") { found = true; trainingStr += "\n " + pretty + ent.target; } else if (ent.type == "TRAINING_mission") { double exp = GetExpiration(pcm.name, ent); if (exp > 0d) { trainingStr += "\n " + pretty + ent.target + ". Expires " + KSPUtil.PrintDate(exp, false); } } } } if (found) { return(trainingStr); } else { return(string.Empty); } }
protected void VesselRecoveryRequested(Vessel v) { double elapsedTime = v.missionTime; List <string> retirementChanges = new List <string>(); List <string> inactivity = new List <string>(); double UT = Planetarium.GetUniversalTime(); // When flight duration was too short, mission training should not be set as expired. // This can happen when an on-the-pad failure occurs and the vessel is recovered. if (elapsedTime < settings.minFlightDurationSecondsForTrainingExpire) { return; } foreach (ProtoCrewMember pcm in v.GetVesselCrew()) { bool hasSpace = false; bool hasOrbit = false; bool hasEVA = false; bool hasEVAOther = false; bool hasOther = false; bool hasOrbitOther = false; bool hasLandOther = false; int curFlight = pcm.careerLog.Last().flight; foreach (FlightLog.Entry e in pcm.careerLog.Entries) { if (e.type == "TRAINING_mission") { SetExpiration(pcm.name, e, Planetarium.GetUniversalTime()); } if (e.flight != curFlight) { continue; } bool isOther = false; if (!string.IsNullOrEmpty(e.target) && e.target != Planetarium.fetch.Home.name) { isOther = hasOther = true; } if (!string.IsNullOrEmpty(e.type)) { switch (e.type) { case "Suborbit": hasSpace = true; break; case "Orbit": if (isOther) { hasOrbitOther = true; } else { hasOrbit = true; } break; case "ExitVessel": if (isOther) { hasEVAOther = true; } else { hasEVA = true; } break; case "Land": if (isOther) { hasLandOther = true; } break; default: break; } } } double multiplier = 1d; double constant = 0.5d; if (hasSpace) { multiplier += settings.recSpace.x; constant += settings.recSpace.y; } if (hasOrbit) { multiplier += settings.recOrbit.x; constant += settings.recOrbit.y; } if (hasOther) { multiplier += settings.recOtherBody.x; constant += settings.recOtherBody.y; } if (hasEVA) { multiplier += settings.recEVA.x; constant += settings.recEVA.y; } if (hasEVAOther) { multiplier += settings.recEVAOther.x; constant += settings.recEVAOther.y; } if (hasOrbitOther) { multiplier += settings.recOrbitOther.x; constant += settings.recOrbitOther.y; } if (hasLandOther) { multiplier += settings.recLandOther.x; constant += settings.recLandOther.y; } double retTime; if (kerbalRetireTimes.TryGetValue(pcm.name, out retTime)) { double offset = constant * 86400d * settings.retireOffsetBaseMult / (1 + Math.Pow(Math.Max(curFlight + settings.retireOffsetFlightNumOffset, 0d), settings.retireOffsetFlightNumPow) * UtilMath.Lerp(settings.retireOffsetStupidMin, settings.retireOffsetStupidMax, pcm.stupidity)); if (offset > 0d) { retTime += offset; kerbalRetireTimes[pcm.name] = retTime; retirementChanges.Add("\n" + pcm.name + ", no earlier than " + KSPUtil.PrintDate(retTime, false)); } } multiplier /= (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d); double inactiveTime = elapsedTime * multiplier + constant * 86400d; pcm.SetInactive(inactiveTime, false); inactivity.Add("\n" + pcm.name + ", until " + KSPUtil.PrintDate(inactiveTime + UT, true, false)); } if (inactivity.Count > 0) { string msgStr = "The following crew members will be on leave:"; foreach (string s in inactivity) { msgStr += s; } if (retirementEnabled && retirementChanges.Count > 0) { msgStr += "\n\nThe following retirement changes have occurred:"; foreach (string s in retirementChanges) { msgStr += s; } } PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "CrewUpdateNotification", "Crew Updates", msgStr, "OK", true, HighLogic.UISkin); } }
private static string PrepareStartedMessage(ShipTemplate shipTemplate) { return($"<color=yellow>Ready in {KSPUtil.PrintDateDeltaCompact(ConstructScenario.Instance.ConstructionFinishAt(shipTemplate), true, false)}</color>"); }
private void SpawnVessel(VesselData vesselData, List<ProtoCrewMember> crewData = null) { string gameDataDir = KSPUtil.ApplicationRootPath; Log.info("Spawning a vessel named '" + vesselData.name + "'"); // Set additional info for landed vessels bool landed = false; if (!vesselData.orbiting) { landed = true; if (vesselData.altitude == null || vesselData.altitude < 0) { vesselData.altitude = 35;//LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body); } //Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value); Vector3d pos = vesselData.body.GetRelSurfacePosition(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()); } else { vesselData.orbit.referenceBody = vesselData.body; } ConfigNode[] partNodes; //UntrackedObjectClass sizeClass; ShipConstruct shipConstruct = null; bool hasClamp = false; float lcHeight = 0; ConfigNode craftNode; Quaternion craftRotation = Quaternion.identity; if (!string.IsNullOrEmpty(vesselData.craftURL)) { // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB! ConfigNode currentShip = ShipConstruction.ShipConfig; shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL); if (shipConstruct == null) { Log.info("ShipConstruct was null when tried to load '{0}' (usually this means the file could not be found).", vesselData.craftURL); return;//continue; } craftNode = ConfigNode.Load(vesselData.craftURL); lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y; craftRotation = ConfigNode.ParseQuaternion(craftNode.GetNode("PART").GetValue("rot")); // 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 missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.missionID = missionID; p.launchID = launchID; p.flagURL = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL; // Had some issues with this being set to -1 for some ships - can't figure out // why. End result is the vessel exploding, so let's just set it to a positive // value. p.temperature = 1.0; } //add minimal crew //bool success = false; Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity); // Add the crew member if (part != null && VesselMoverToolbar.addCrewMembers) { if (VesselMoverToolbar.selectCrewMembers) { ProtoCrewMember crewMember = crewData.FirstOrDefault(); if (crewMember != null) part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); VesselMoverToolbar.SelectedCrewMembers.Clear(); } else { // Create the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(); crewMember.gender = UnityEngine.Random.Range(0, 100) > 50 ? ProtoCrewMember.Gender.Female : ProtoCrewMember.Gender.Male; //crewMember.trait = "Pilot"; // Add them to the part part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); } } // 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) { dummyVessel.loaded = false; p.vessel = dummyVessel; { #if KSP_18 ProtoPartSnapshot proto = new ProtoPartSnapshot(p, dummyProto, true)); // For KSP >= 1.8 #else ProtoPartSnapshot proto = new ProtoPartSnapshot(p, dummyProto); // For KSP 1.4.x #endif dummyProto.protoPartSnapshots.Add(proto); } } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } // Create the ship's parts List<ConfigNode> partNodesL = new List<ConfigNode>(); foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); // Estimate an object class, numbers are based on the in game description of the // size classes. //float size = shipConstruct.shipSize.magnitude / 2.0f; //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; //} } else { // Create crew member array ProtoCrewMember[] crewArray = new ProtoCrewMember[vesselData.crew.Count]; int i = 0; foreach (CrewData cd in vesselData.crew) { // Create the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew); if (cd.name != null) { crewMember.KerbalRef.name = cd.name; } crewArray[i++] = crewMember; } // Create part nodes uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode(vesselData.craftPart.name, flightId, crewArray); // Default the size class //sizeClass = UntrackedObjectClass.A; // Set the name if (string.IsNullOrEmpty(vesselData.name)) { vesselData.name = vesselData.craftPart.name; } } // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[0]; //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.orbiting) { Vector3d norm = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude); double terrainHeight = 0.0; if (vesselData.body.pqsController != null) { terrainHeight = vesselData.body.pqsController.GetSurfaceHeight(norm) - vesselData.body.pqsController.radius; } bool splashed = false;// = landed && terrainHeight < 0.001; // Create the config node representation of the ProtoVessel // Note - flying is experimental, and so far doesn't work protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ? Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString()); protoVesselNode.SetValue("landed", (landed && !splashed).ToString()); protoVesselNode.SetValue("splashed", splashed.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 height to subtract float lowest = float.MaxValue; if (shipConstruct != null) { 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); } } } } else { foreach (Collider collider in vesselData.craftPart.partPrefab.GetComponentsInChildren<Collider>()) { if (collider.gameObject.layer != 21 && collider.enabled) { lowest = Mathf.Min(lowest, collider.bounds.min.y); } } } if (lowest == float.MaxValue) { lowest = 0; } // Figure out the surface height and rotation Quaternion normal = Quaternion.LookRotation((Vector3)norm);// new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); Quaternion rotation = Quaternion.identity; float heading = vesselData.heading; if (shipConstruct == null) { rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back); } else if (shipConstruct.shipFacility == EditorFacility.SPH) { rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward); heading += 180.0f; } else { rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward); rotation = Quaternion.FromToRotation(Vector3.up, -Vector3.up) * rotation; //rotation = craftRotation; vesselData.heading = 0; vesselData.pitch = 0; } rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back); rotation = rotation * Quaternion.AngleAxis(vesselData.roll, Vector3.down); rotation = rotation * Quaternion.AngleAxis(vesselData.pitch, Vector3.left); // Set the height and rotation if (landed || splashed) { float hgt = (shipConstruct != null ? shipConstruct.parts[0] : vesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest; hgt += vesselData.height; foreach (Part p in shipConstruct.Parts) { LaunchClamp lc = p.FindModuleImplementing<LaunchClamp>(); if (lc) { hasClamp = true; break; } } if (!hasClamp) { hgt += 35; } else { hgt += lcHeight; } protoVesselNode.SetValue("hgt", hgt.ToString(), true); } protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation), true); // Set the normal vector relative to the surface Vector3 nrm = (rotation * Vector3.forward); protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z, true); protoVesselNode.SetValue("prst", false.ToString(), true); } // Add vessel to the game ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); //protoVessel.vesselRef.transform.rotation = protoVessel.rotation; // Store the id for later use vesselData.id = protoVessel.vesselRef.id; //protoVessel.vesselRef.currentStage = 0; StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp)); // Associate it so that it can be used in contract parameters //ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef); //destroy prefabs foreach (Part p in FindObjectsOfType<Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } }
private static string PrepareNotBuildMessage(ShipTemplate shipTemplate) { return($"<color=orange>Build in {KSPUtil.PrintDateDeltaCompact(ConstructScenario.Instance.ConstructionFinishAt(shipTemplate), true, false)}</color>"); }
public static string ReqValueFormat(Require req, object reqValue) { switch (req) { case Require.OrbitMinEccentricity: case Require.OrbitMaxEccentricity: case Require.OrbitMinArgOfPeriapsis: case Require.OrbitMaxArgOfPeriapsis: case Require.AtmosphereAltMin: case Require.AtmosphereAltMax: return(((double)reqValue).ToString("F2")); case Require.SunAngleMin: case Require.SunAngleMax: case Require.OrbitMinInclination: case Require.OrbitMaxInclination: return(Lib.HumanReadableAngle((double)reqValue)); case Require.TemperatureMin: case Require.TemperatureMax: return(Lib.HumanReadableTemp((double)reqValue)); case Require.AltitudeMin: case Require.AltitudeMax: case Require.AltAboveGroundMin: case Require.AltAboveGroundMax: case Require.MaxAsteroidDistance: return(Lib.HumanReadableDistance((double)reqValue)); case Require.RadiationMin: case Require.RadiationMax: return(Lib.HumanReadableRadiation((double)reqValue)); case Require.VolumePerCrewMin: case Require.VolumePerCrewMax: return(Lib.HumanReadableVolume((double)reqValue)); case Require.SurfaceSpeedMin: case Require.SurfaceSpeedMax: case Require.VerticalSpeedMin: case Require.VerticalSpeedMax: case Require.SpeedMin: case Require.SpeedMax: return(Lib.HumanReadableSpeed((double)reqValue)); case Require.DynamicPressureMin: case Require.DynamicPressureMax: case Require.StaticPressureMin: case Require.StaticPressureMax: case Require.AtmDensityMin: case Require.AtmDensityMax: return(Lib.HumanReadablePressure((double)reqValue)); case Require.CrewMin: case Require.CrewMax: case Require.CrewCapacityMin: case Require.CrewCapacityMax: case Require.AstronautComplexLevelMin: case Require.AstronautComplexLevelMax: case Require.TrackingStationLevelMin: case Require.TrackingStationLevelMax: case Require.MissionControlLevelMin: case Require.MissionControlLevelMax: case Require.AdministrationLevelMin: case Require.AdministrationLevelMax: return(((int)reqValue).ToString()); case Require.Module: return(KSPUtil.PrintModuleName((string)reqValue)); case Require.Part: return(PartLoader.getPartInfoByName((string)reqValue)?.title ?? (string)reqValue); default: return(string.Empty); } }
private void draw(int id) { if (!simTermination) { if (GUILayout.Button("Resume Simulation"/*, _guiSkin.button */)) { Log.Info("Close 1"); Close(); } GUILayout.Space(SPACER); } if (GUILayout.Button("<color=orange>Terminate Simulation</color>"/*, _guiSkin.button */)) { string revertTarget; switch (KRASHShelter.lastScene) { case GameScenes.EDITOR: switch (KRASHShelter.lastEditor) { case EditorFacility.SPH: revertTarget = "Spaceplane Hangar"; break; case EditorFacility.VAB: revertTarget = "Vehicle Assembly Building"; break; // This should never happen. If it does, just go to the SC default: revertTarget = "Space Center"; KRASHShelter.lastScene = GameScenes.SPACECENTER; break; } break; case GameScenes.SPACECENTER: revertTarget = "Space Center"; break; default: revertTarget = "Pre-Simulation"; break; } string s = "Revert to " + revertTarget + " (" + KSPUtil.PrintTimeLong(((int)(Planetarium.GetUniversalTime() - FlightDriver.PostInitState.UniversalTime))); DialogGUIBase[] options = new DialogGUIBase[2]; options[0] = new DialogGUIButton(s, () => { StartCoroutine(WaitForFlightResultsDialog()); }); options[1] = new DialogGUIButton("Cancel", () => { Log.Info("Close 2"); Close(); }); var multidialog = new MultiOptionDialog("krash2", "Terminating will set the game back to an earlier state. Are you sure you want to continue?", "Terminating Simulation", HighLogic.UISkin, 450, options); _activePopup = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), multidialog, false, HighLogic.UISkin, true); Hide(); } if (FlightDriver.CanRevertToPostInit) { if (GUILayout.Button("<color=orange>Restart Simulation</color>"/*, _guiSkin.button*/)) { DialogGUIBase[] options = new DialogGUIBase[2]; string s = "Revert to Launch(" + KSPUtil.PrintTimeLong(((int)(Planetarium.GetUniversalTime() - FlightDriver.PostInitState.UniversalTime))) + " ago"; options[0] = new DialogGUIButton(s, () => { Log.Info("Close 3"); Close(); Log.Info("Close 4"); Close(); FlightDriver.RevertToLaunch(); // The RevertTolaunch reloads all the objects, so we destroy them here to avoid conflicts KRASHShelter.instance.DestroyModules(); }); options[1] = new DialogGUIButton("Cancel", () => { Log.Info("Close 5"); Close(); }); var multidialog = new MultiOptionDialog("krash3", "Reverting will set the game back to an earlier state. Are you sure you want to continue?", "Reverting Simulation", HighLogic.UISkin, 450, options); _activePopup = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), multidialog, false, HighLogic.UISkin, true); // _activePopup = PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), // new MultiOptionDialog(null, new Callback (drawRevertWarning), "Reverting Simulation", HighLogic.Skin, new DialogOption[0]), false, HighLogic.Skin); APIManager.ApiInstance.SimRestartEvent.Fire((Vessel)FlightGlobals.ActiveVessel, KRASHShelter.simCost + KRASHShelter.simSetupCost); Hide(); } } GUILayout.Space(SPACER); if (GUILayout.Button("Settings"/*, _guiSkin.button*/)) { Hide(); _miniSettings = MiniSettings.Create(Unhide); } #if false } else {
public override void OnLoad(ConfigNode node) { base.OnLoad(node); if (node.HasValue("RTAntennaTarget")) { try { Target = new Guid(node.GetValue("RTAntennaTarget")); } catch (FormatException) { Target = Guid.Empty; } } // Have RTDishRadians as a fallback to avoid corrupting save games if (node.HasValue("RTDishRadians")) { double temp_double; RTDishCosAngle = Double.TryParse(node.GetValue("RTDishRadians"), out temp_double) ? temp_double : 1.0; } if (node.HasValue("DishAngle")) { RTDishCosAngle = Math.Cos(DishAngle / 2 * Math.PI / 180); } if (node.HasValue("DeployFxModules")) { mDeployFxModuleIndices = KSPUtil.ParseArray <Int32>(node.GetValue("DeployFxModules"), new ParserMethod <Int32>(Int32.Parse)); } if (node.HasValue("ProgressFxModules")) { mProgressFxModuleIndices = KSPUtil.ParseArray <Int32>(node.GetValue("ProgressFxModules"), new ParserMethod <Int32>(Int32.Parse)); } if (node.HasNode("TRANSMITTER")) { RTLog.Notify("ModuleRTAntenna: Found TRANSMITTER block."); mTransmitterConfig = node.GetNode("TRANSMITTER"); mTransmitterConfig.AddValue("name", "ModuleRTDataTransmitter"); // workarround for ksp 1.0 if (mTransmitterConfig.HasValue("PacketInterval")) { RTPacketInterval = float.Parse(mTransmitterConfig.GetValue("PacketInterval")); } if (mTransmitterConfig.HasValue("PacketSize")) { RTPacketSize = float.Parse(mTransmitterConfig.GetValue("PacketSize")); } if (mTransmitterConfig.HasValue("PacketResourceCost")) { RTPacketResourceCost = float.Parse(mTransmitterConfig.GetValue("PacketResourceCost")); } } if (this.resHandler.inputResources.Count == 0) { ModuleResource moduleResource = new ModuleResource(); moduleResource.name = this.resourceName; moduleResource.title = KSPUtil.PrintModuleName(this.resourceName); moduleResource.id = this.resourceName.GetHashCode(); moduleResource.rate = EnergyCost * ConsumptionMultiplier; this.resHandler.inputResources.Add(moduleResource); } //apply the consumption multiplier this.resHandler.inputResources.Find(x => x.name == this.resourceName).rate = EnergyCost * ConsumptionMultiplier; }
private IEnumerator DelayedOnSaved(Game game) { var timer = new Stopwatch(); timer.Start(); print("KerbalGit: Entering OnSaved"); yield return(new WaitForSeconds(1)); // It seems ksp needs time to finish saving print("KerbalGit: Finished waiting"); try { if (latestCommit == DateTime.MinValue || (DateTime.Now - latestCommit) > TimeSpan.FromSeconds(wait)) { using (var repo = new Repository(savesDir)) { var repoStatus = repo.Index.RetrieveStatus(new StatusOptions() { Show = StatusShowOption.WorkDirOnly }); bool isStaged = false; foreach (var entry in repoStatus) { if (entry.State == FileStatus.Modified || entry.State == FileStatus.Untracked || entry.State == FileStatus.Missing) { print("KerbalGit: Staging " + entry.FilePath); repo.Index.Stage(entry.FilePath); isStaged = true; } } if (isStaged) { Signature author = new Signature(settings.GetValue("name"), settings.GetValue("email"), DateTime.Now); var sb = new StringBuilder(); sb.AppendFormat("Game: {0}", game.Title); sb.AppendFormat(", Time: {0}", KSPUtil.PrintDate((int)game.UniversalTime, true, true)); if (Funding.Instance != null) { sb.AppendFormat(", Funds: {0:N0}", (int)Funding.Instance.Funds); } if (ResearchAndDevelopment.Instance != null) { sb.AppendFormat(", Science: {0:N0}", (int)ResearchAndDevelopment.Instance.Science); } if (Reputation.Instance != null) { sb.AppendFormat(", Reputation: {0}%", (int)Reputation.Instance.reputation / 10); } if (FlightGlobals.ready && FlightGlobals.Vessels != null) { sb.AppendFormat(", Flights: {0}", FlightGlobals.Vessels.Count(v => v.vesselType != VesselType.Debris && v.vesselType != VesselType.SpaceObject && v.vesselType != VesselType.Unknown)); } if (Contracts.ContractSystem.Instance != null) { sb.AppendFormat(", Contracts: {0}", Contracts.ContractSystem.Instance.GetActiveContractCount()); } print("KerbalGit: Committing..."); Commit commit = repo.Commit(sb.ToString(), author); latestCommit = DateTime.Now; } } } } catch (Exception ex) { print("KerbalGit: OnSaved exception: " + ex.Message); } finally { timer.Stop(); print("KerbalGit: Exiting OnSaved after " + timer.Elapsed); } }
public void Save(ConfigNode node) { node.SetValue("positive", KSPUtil.WriteVector(positive)); node.SetValue("negative", KSPUtil.WriteVector(negative)); }
public BuildListVessel(ShipConstruct s, string ls, double effCost, double bP, string flagURL) { _ship = s; ShipNode = s.SaveShip(); // Override KSP sizing of the ship construct ShipNode.SetValue("size", KSPUtil.WriteVector(Utilities.GetShipSize(s, true))); ShipName = s.shipName; Cost = Utilities.GetTotalVesselCost(ShipNode, true); EmptyCost = Utilities.GetTotalVesselCost(ShipNode, false); TotalMass = Utilities.GetShipMass(s, true, out EmptyMass, out _); HashSet <int> stages = new HashSet <int>(); NumStageParts = 0; StagePartCost = 0d; foreach (Part p in s.Parts) { if (p.stagingOn) { stages.Add(p.inverseStage); ++NumStageParts; StagePartCost += p.GetModuleCosts(p.partInfo.cost, ModifierStagingSituation.CURRENT) + p.partInfo.cost; } } NumStages = stages.Count; LaunchSite = ls; EffectiveCost = effCost; BuildPoints = bP; Progress = 0; Flag = flagURL; if (s.shipFacility == EditorFacility.VAB) { Type = ListType.VAB; } else if (s.shipFacility == EditorFacility.SPH) { Type = ListType.SPH; } else { Type = ListType.None; } Id = Guid.NewGuid(); CannotEarnScience = false; //get the crew from the editorlogic DesiredManifest = new List <string>(); if (CrewAssignmentDialog.Instance?.GetManifest()?.CrewCount > 0) { foreach (ProtoCrewMember crew in CrewAssignmentDialog.Instance.GetManifest().GetAllCrew(true) ?? new List <ProtoCrewMember>()) { DesiredManifest.Add(crew?.name ?? string.Empty); } } if (EffectiveCost == default) { // Can only happen in older saves that didn't have Effective cost persisted as a separate field // This code should be safe to remove after a while. EffectiveCost = Utilities.GetEffectiveCost(ShipNode.GetNodes("PART").ToList()); } IntegrationPoints = MathParser.ParseIntegrationTimeFormula(this); IntegrationCost = (float)MathParser.ParseIntegrationCostFormula(this); }
public override void OnSave(ConfigNode node) { var rot = KSPUtil.WriteQuaternion(towerRot); node.AddValue("towerRot", rot); }
private List <UIListItem> CreateAtmosphericCharacteristics(CelestialBody currentBody, GenericCascadingList cascadingList) { GenericCascadingList genericCascadingList = cascadingList; Boolean atmosphere = currentBody.atmosphere && currentBody.atmospherePressureSeaLevel > 0; String key = Localizer.Format("#autoLOC_462448"); String template = atmosphere ? "#autoLOC_439855" : "#autoLOC_439856"; UIListItem item = genericCascadingList.CreateBody(key, "<color=#b8f4d1>" + Localizer.Format((string)template) + "</color>"); List <UIListItem> list = new List <UIListItem>(); list.Add(item); if (atmosphere) { item = cascadingList.CreateBody(Localizer.Format("#autoLOC_462453"), "<color=#b8f4d1>" + KSPUtil.LocalizeNumber(currentBody.atmosphereDepth, "N0") + " " + Localizer.Format("#autoLOC_7001411") + "</color>"); list.Add(item); item = cascadingList.CreateBody(Localizer.Format("#autoLOC_462456"), "<color=#b8f4d1>" + KSPUtil.LocalizeNumber(currentBody.atmospherePressureSeaLevel / 101.324996948242, "0.#####") + " " + Localizer.Format("#autoLOC_7001419") + "</color>"); list.Add(item); item = cascadingList.CreateBody(Localizer.Format("#autoLOC_462459"), "<color=#b8f4d1>" + KSPUtil.LocalizeNumber(currentBody.atmosphereTemperatureSeaLevel, "0.##") + " " + Localizer.Format("#autoLOC_7001406") + "</color>"); list.Add(item); } return(list); }
private void DrawPrintProgress() { // Currently build item if (_processedItem != null) { if (_processedItem.Icon == null) { _processedItem.EnableIcon(64); } GUI.Box(new Rect(190, 620, 50, 50), _processedItem.Icon.texture); } else { GUI.Box(new Rect(190, 620, 50, 50), ""); } // Progressbar GUI.Box(new Rect(250, 620, 280, 50), ""); if (progress >= 1) { var color = GUI.color; GUI.color = new Color(0, 1, 0, 1); GUI.Box(new Rect(250, 620, 280 * progress / 100, 50), ""); GUI.color = color; } string progressText = string.Format("Progress: {0:n1}%, T- ", progress) + KSPUtil.PrintTime(_processedBlueprint.GetBuildTime(adjustedProductivity), 5, false); GUI.Label(new Rect(250, 620, 280, 50), " " + progressText); //Pause/resume production Texture2D buttonTexture = _pauseTexture; if (manufacturingPaused || _processedItem == null) { buttonTexture = _playTexture; } if (GUI.Button(new Rect(530, 620, 50, 50), buttonTexture) && _processedItem != null) { manufacturingPaused = !manufacturingPaused; } //Cancel production if (GUI.Button(new Rect(580, 620, 50, 50), _binTexture)) { if (_confirmDelete) { _processedItem.DisableIcon(); _processedItem = null; _processedBlueprint = null; progress = 0; manufacturingPaused = false; Status = "Online"; if (Animate && _heatAnimation != null && _workAnimation != null) { StartCoroutine(StopAnimations()); } _confirmDelete = false; } else { _confirmDelete = true; ScreenMessages.PostScreenMessage("Click the cancel button again to confirm cancelling current production", 5.0f, ScreenMessageStyle.UPPER_CENTER); } } }
/// <summary> /// Replaces the common tokens like "[year]" with their appropriate values as gathered from KSP /// </summary> /// <param name="sourceString">The source string to act on</param> /// <returns>The string post replacements</returns> public static string ReplaceStandardTokens(string sourceString) { string str = sourceString; bool counterFound = str.Contains("cnt"); str = ReplaceToken(str, "UT", Planetarium.fetch != null ? Math.Round(Planetarium.GetUniversalTime()).ToString() : "0"); //str = ReplaceToken(str, "save", HighLogic.SaveFolder != null && HighLogic.SaveFolder.Trim().Length > 0 ? HighLogic.SaveFolder : "NA"); //str = ReplaceToken(str, "version", Versioning.GetVersionString()); str = ReplaceToken(str, "vessel", HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null ? FlightGlobals.ActiveVessel.vesselName : ""); str = ReplaceToken(str, "body", Planetarium.fetch != null ? Planetarium.fetch.CurrentMainBody.GetDisplayName() : ""); str = ReplaceToken(str, "situation", HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null ? FlightGlobals.ActiveVessel.situation.ToString() : ""); str = ReplaceToken(str, "biome", HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null ? ScienceUtil.GetExperimentBiome(FlightGlobals.ActiveVessel.mainBody, FlightGlobals.ActiveVessel.latitude, FlightGlobals.ActiveVessel.longitude) : ""); int[] times = { 0, 0, 0, 0, 0 }; if (Planetarium.fetch != null) { times = ConvertUT(Planetarium.GetUniversalTime()); } if (!counterFound) { str = ReplaceToken(str, "year", times[0].ToString()); } str = ReplaceToken(str, "year0", times[0].ToString("D3")); if (!counterFound) { str = ReplaceToken(str, "day", times[1].ToString()); } str = ReplaceToken(str, "day0", times[1].ToString("D3")); if (!counterFound) { str = ReplaceToken(str, "hour", times[2].ToString()); } str = ReplaceToken(str, "hour0", times[2].ToString("D2")); if (!counterFound) { str = ReplaceToken(str, "min", times[3].ToString()); } str = ReplaceToken(str, "min0", times[3].ToString("D2")); if (!counterFound) { str = ReplaceToken(str, "sec", times[4].ToString()); } str = ReplaceToken(str, "sec0", times[4].ToString("D2")); string time = KSPUtil.PrintTimeCompact(0, false); if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ActiveVessel != null) { time = KSPUtil.PrintTimeCompact((int)FlightGlobals.ActiveVessel.missionTime, false); } time = time.Replace(":", "-"); //Can't use colons in filenames on Windows, so we'll replace them with "-" str = ReplaceToken(str, "MET", time); if (str.Contains("cnt")) { int zeroes = 0; while (str.Contains("cnt" + Repeated('0', zeroes + 1))) { zeroes++; } string token = "cnt" + Repeated('0', zeroes); string searchstr = ReplaceToken(str, token, "*.sfs"); int beginning = str.IndexOf(token); string[] files = Directory.GetFiles(SaveDir, searchstr); int cnt = files.Length; for (int i = 0; i < files.Length; i++) { int z = zeroes; string counterStr = files[i].Substring(SaveDir.Length + beginning); if (zeroes == 0) { while (z < counterStr.Length && Char.IsDigit(counterStr[z])) { z++; } } counterStr = counterStr.Substring(0, z); int x = 0; int.TryParse(counterStr, out x); cnt = Math.Max(cnt, x); } str = ReplaceToken(str, token, (cnt + 1).ToString("D" + zeroes.ToString())); } return(str); }
protected void FixedUpdate() { int pC; if (HighLogic.LoadedSceneIsFlight && part.CrewCapacity > 0 && (pC = part.protoModuleCrew.Count) > 0) { double UT = KSPUtils.GetUT(); if (nextCheck < 0d) { nextCheck = UT + checkInterval; } else if (UT > nextCheck) { if (pressureAtKillAltitude == default) { pressureAtKillAltitude = FlightGlobals.GetHomeBody().GetPressureAtm(crewDeathAltitude); _origDoStockGCalcs = ProtoCrewMember.doStockGCalcs; } nextCheck = UT + checkInterval; if (part.staticPressureAtm < pressureAtKillAltitude) { ScreenMessages.PostScreenMessage($"Cockpit is above the safe altitude which will lead to crew incapacitation and eventually to death", 1f, ScreenMessageStyle.UPPER_CENTER, XKCDColors.Red); if (!_origDoStockGCalcs.HasValue) { _origDoStockGCalcs = ProtoCrewMember.doStockGCalcs; } ProtoCrewMember.doStockGCalcs = false; bool killed = false; for (int i = pC; i-- > 0;) { ProtoCrewMember pcm = part.protoModuleCrew[i]; double highGPenalty = vessel.geeForce > 3 ? vessel.geeForce : 1; pcm.gExperienced += (0.5d + rnd.NextDouble()) * gDamageAdder * highGPenalty; double gMult = ProtoCrewMember.GToleranceMult(pcm) * HighLogic.CurrentGame.Parameters.CustomParams <GameParameters.AdvancedParams>().KerbalGToleranceMult; _anyCrewAboveWarnThreshold = pcm.gExperienced > PhysicsGlobals.KerbalGThresholdWarn * gMult; double locThreshold = PhysicsGlobals.KerbalGThresholdLOC * gMult; if (!pcm.outDueToG && pcm.gExperienced > locThreshold) { // Just passed out ScreenMessages.PostScreenMessage($"<color=red>{pcm.name} has lost consciousness due to hypoxia!</color>", 5.5f, ScreenMessageStyle.UPPER_CENTER); } // There's at least one cycle of delay after passing out before the death chance rolls start if (pcm.outDueToG && rnd.NextDouble() < crewDeathChance) { killed = true; ScreenMessages.PostScreenMessage($"{vessel.vesselName}: Crewmember {pcm.name} has died from exposure to near-vacuum.", 30.0f, ScreenMessageStyle.UPPER_CENTER, XKCDColors.Red); FlightLogger.fetch.LogEvent($"[{KSPUtil.PrintTime(vessel.missionTime, 3, false)}] {pcm.name} died from exposure to near-vacuum."); part.RemoveCrewmember(pcm); pcm.Die(); } } if (killed && CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA) { CameraManager.Instance.SetCameraFlight(); } } else { if (_origDoStockGCalcs.HasValue) { ProtoCrewMember.doStockGCalcs = _origDoStockGCalcs.Value; _origDoStockGCalcs = null; } } } } }
private void VesselRecoveryProcessing(ProtoVessel v, MissionRecoveryDialog mrDialog, float data) { Debug.Log("[VR] - Vessel recovery processing"); List <string> retirementChanges = new List <string>(); List <string> inactivity = new List <string>(); double UT = Planetarium.GetUniversalTime(); // normally we would use v.missionTime, but that doesn't seem to update // when you're not actually controlling the vessel double elapsedTime = UT - v.launchTime; Debug.Log("[VR] mission elapsedTime: " + KSPUtil.PrintDateDeltaCompact(elapsedTime, true, true)); // When flight duration was too short, mission training should not be set as expired. // This can happen when an on-the-pad failure occurs and the vessel is recovered. // We could perhaps override this if they're not actually in flight // (if the user didn't recover right from the pad I think this is a fair assumption) if (elapsedTime < settings.minFlightDurationSecondsForTrainingExpire) { Debug.Log("[VR] - mission time too short for crew to be inactive (elapsed time was " + elapsedTime + ", settings set for " + settings.minFlightDurationSecondsForTrainingExpire + ")"); return; } foreach (ProtoCrewMember pcm in v.GetVesselCrew()) { Debug.Log("[VR] - Found ProtoCrewMember: " + pcm.displayName); bool hasSpace = false; bool hasOrbit = false; bool hasEVA = false; bool hasEVAOther = false; bool hasOther = false; bool hasOrbitOther = false; bool hasLandOther = false; int curFlight = pcm.careerLog.Last().flight; int numFlightsDone = pcm.careerLog.Entries.Count(e => e.type == "Recover"); foreach (FlightLog.Entry e in pcm.careerLog.Entries) { if (e.type == "TRAINING_mission") { SetExpiration(pcm.name, e, Planetarium.GetUniversalTime()); } if (e.flight != curFlight || e.type == "Nationality") { continue; } Debug.Log($"[VR] processing flight entry: {e.type}; {e.target}"); bool isOther = false; if (!string.IsNullOrEmpty(e.target) && e.target != Planetarium.fetch.Home.name) { Debug.Log($"[VR] flight is beyond Earth"); isOther = hasOther = true; } if (!string.IsNullOrEmpty(e.type)) { switch (e.type) { case "Suborbit": hasSpace = true; break; case "Orbit": if (isOther) { hasOrbitOther = true; } else { hasOrbit = true; } break; case "ExitVessel": if (isOther) { hasEVAOther = true; } else { hasEVA = true; } break; case "Land": if (isOther) { hasLandOther = true; } break; default: break; } } } double multiplier = 1d; double constant = 0.5d; if (hasSpace) { multiplier += settings.recSpace.x; constant += settings.recSpace.y; Debug.Log($"[VR] has space, mult {settings.recSpace.x}; constant {settings.recSpace.y}"); } if (hasOrbit) { multiplier += settings.recOrbit.x; constant += settings.recOrbit.y; Debug.Log($"[VR] has orbit, mult {settings.recOrbit.x}; constant {settings.recOrbit.y}"); } if (hasOther) { multiplier += settings.recOtherBody.x; constant += settings.recOtherBody.y; Debug.Log($"[VR] has other body, mult {settings.recOtherBody.x}; constant {settings.recOtherBody.y}"); } if (hasOrbit && hasEVA) // EVA should only count while in orbit, not when walking on Earth { multiplier += settings.recEVA.x; constant += settings.recEVA.y; Debug.Log($"[VR] has EVA, mult {settings.recEVA.x}; constant {settings.recEVA.y}"); } if (hasEVAOther) { multiplier += settings.recEVAOther.x; constant += settings.recEVAOther.y; Debug.Log($"[VR] has EVA at another body, mult {settings.recEVAOther.x}; constant {settings.recEVAOther.y}"); } if (hasOrbitOther) { multiplier += settings.recOrbitOther.x; constant += settings.recOrbitOther.y; Debug.Log($"[VR] has orbit around another body, mult {settings.recOrbitOther.x}; constant {settings.recOrbitOther.y}"); } if (hasLandOther) { multiplier += settings.recLandOther.x; constant += settings.recLandOther.y; Debug.Log($"[VR] has landed on another body, mult {settings.recLandOther.x}; constant {settings.recLandOther.y}"); } Debug.Log("[VR] multiplier: " + multiplier); Debug.Log("[VR] AC multiplier: " + (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d)); Debug.Log("[VR] constant: " + constant); double retTime; if (kerbalRetireTimes.TryGetValue(pcm.name, out retTime)) { double offset = constant * 86400d * settings.retireOffsetBaseMult / (1 + Math.Pow(Math.Max(numFlightsDone + settings.retireOffsetFlightNumOffset, 0d), settings.retireOffsetFlightNumPow) * UtilMath.Lerp(settings.retireOffsetStupidMin, settings.retireOffsetStupidMax, pcm.stupidity)); if (offset > 0d) { Debug.Log("[VR] retire date increased by: " + KSPUtil.PrintDateDeltaCompact(offset, true, false)); Debug.Log($"[VR] constant: {constant}; curFlight: {numFlightsDone}; stupidity: {pcm.stupidity}"); retTime += offset; kerbalRetireTimes[pcm.name] = retTime; retirementChanges.Add("\n" + pcm.name + ", no earlier than " + KSPUtil.PrintDate(retTime, false)); } } multiplier /= (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d); double inactiveTime = elapsedTime * multiplier + constant * 86400d; Debug.Log("[VR] inactive for: " + KSPUtil.PrintDateDeltaCompact(inactiveTime, true, false)); pcm.SetInactive(inactiveTime, false); inactivity.Add("\n" + pcm.name + ", until " + KSPUtil.PrintDate(inactiveTime + UT, true, false)); } if (inactivity.Count > 0) { Debug.Log("[VR] - showing on leave message"); string msgStr = "The following crew members will be on leave:"; foreach (string s in inactivity) { msgStr += s; } if (retirementEnabled && retirementChanges.Count > 0) { msgStr += "\n\nThe following retirement changes have occurred:"; foreach (string s in retirementChanges) { msgStr += s; } } PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "CrewUpdateNotification", "Crew Updates", msgStr, "OK", true, HighLogic.UISkin); } }
public static bool setSite(ConfigNode KSC) { bool hasChanged = false; double dtmp; float ftmp; bool btmp; ConfigNode pqsCity = KSC.GetNode("PQSCity"); if (pqsCity == null) { return(false); } ConfigNode pqsDecal = KSC.GetNode("PQSMod_MapDecalTangent"); CelestialBody home = getKSCBody(); PQSCity ksc = findKSC(home); if (ksc != null) { if (pqsCity.HasValue("KEYname")) { if (!(ksc.name.Equals(pqsCity.GetValue("KEYname")))) { Debug.Log("KSCSwitcher: Could not retrieve KSC to move, reporting failure and moving on."); return(false); } } if (pqsCity.HasValue("repositionRadial")) { ksc.repositionRadial = KSPUtil.ParseVector3(pqsCity.GetValue("repositionRadial")); } if (pqsCity.HasValue("latitude") && pqsCity.HasValue("longitude")) { double lat, lon; double.TryParse(pqsCity.GetValue("latitude"), out lat); double.TryParse(pqsCity.GetValue("longitude"), out lon); ksc.repositionRadial = KSCSwitcher.LLAtoECEF(lat, lon, 0, home.Radius); } if (pqsCity.HasValue("reorientInitialUp")) { ksc.reorientInitialUp = KSPUtil.ParseVector3(pqsCity.GetValue("reorientInitialUp")); } if (pqsCity.HasValue("repositionToSphere")) { if (bool.TryParse(pqsCity.GetValue("repositionToSphere"), out btmp)) { ksc.repositionToSphere = btmp; } } if (pqsCity.HasValue("repositionToSphereSurface")) { if (bool.TryParse(pqsCity.GetValue("repositionToSphereSurface"), out btmp)) { ksc.repositionToSphereSurface = btmp; } } if (pqsCity.HasValue("repositionToSphereSurfaceAddHeight")) { if (bool.TryParse(pqsCity.GetValue("repositionToSphereSurfaceAddHeight"), out btmp)) { ksc.repositionToSphereSurfaceAddHeight = btmp; } } if (pqsCity.HasValue("reorientToSphere")) { if (bool.TryParse(pqsCity.GetValue("reorientToSphere"), out btmp)) { ksc.reorientToSphere = btmp; } } if (pqsCity.HasValue("repositionRadiusOffset")) { if (double.TryParse(pqsCity.GetValue("repositionRadiusOffset"), out dtmp)) { ksc.repositionRadiusOffset = dtmp; } } if (pqsCity.HasValue("lodvisibleRangeMult")) { if (double.TryParse(pqsCity.GetValue("lodvisibleRangeMult"), out dtmp)) { foreach (PQSCity.LODRange l in ksc.lod) { l.visibleRange *= (float)dtmp; } } } if (pqsCity.HasValue("reorientFinalAngle")) { if (float.TryParse(pqsCity.GetValue("reorientFinalAngle"), out ftmp)) { ksc.reorientFinalAngle = ftmp; } } print("KSCSwitcher changed PQSCity"); hasChanged = true; ksc.OnSetup(); ksc.OnPostSetup(); SpaceCenter.Instance.transform.localPosition = ksc.transform.localPosition; SpaceCenter.Instance.transform.localRotation = ksc.transform.localRotation; } else { Debug.LogError("KSCSwitcher: Could not retrieve KSC to move, reporting failure and moving on."); return(false); } PQSMod_MapDecalTangent decal = findKSCMapDecal(home); if (decal != null && pqsDecal != null) { // KSC Flat area if (pqsDecal.HasValue("position")) { decal.position = KSPUtil.ParseVector3(pqsDecal.GetValue("position")); } if (pqsDecal.HasValue("radius")) { if (double.TryParse(pqsDecal.GetValue("radius"), out dtmp)) { decal.radius = dtmp; } } if (pqsDecal.HasValue("heightMapDeformity")) { if (double.TryParse(pqsDecal.GetValue("heightMapDeformity"), out dtmp)) { decal.heightMapDeformity = dtmp; } } if (pqsDecal.HasValue("absoluteOffset")) { if (double.TryParse(pqsDecal.GetValue("absoluteOffset"), out dtmp)) { decal.absoluteOffset = dtmp; } } if (pqsDecal.HasValue("absolute")) { if (bool.TryParse(pqsDecal.GetValue("absolute"), out btmp)) { decal.absolute = btmp; } } if (pqsDecal.HasValue("latitude") && pqsDecal.HasValue("longitude")) { double lat, lon; double.TryParse(pqsDecal.GetValue("latitude"), out lat); double.TryParse(pqsDecal.GetValue("longitude"), out lon); decal.position = KSCSwitcher.LLAtoECEF(lat, lon, 0, home.Radius); } print("KSCSwitcher changed MapDecal_Tangent"); hasChanged = true; decal.OnSetup(); } if (hasChanged) { SpaceCenter.Instance.Start(); // 1.0.5 if (KSC.HasValue("name")) { KSCLoader.instance.Sites.lastSite = LastKSC.fetch.lastSite = KSC.GetValue("name"); print("KSCSwitcher changed MapDecal_Tangent"); } } return(hasChanged); }