internal static void SeatKerbal(ProtoCrewMember crewMember) { foreach (ProtoCrewMember oldCrew in selectedPart.protoModuleCrew.Where(x => x.seatIdx == selectedSeat).ToArray()) { selectedPart.protoModuleCrew.Remove(oldCrew); oldCrew.rosterStatus = ProtoCrewMember.RosterStatus.Available; oldCrew.seatIdx = -1; selectedPart.protoCrewNames.Remove(oldCrew.name); selectedVessel.RemoveCrew(oldCrew); } crewMember.seatIdx = selectedSeat; selectedPart.protoModuleCrew.Add(crewMember); selectedPart.protoCrewNames.Add(crewMember.name); selectedVessel.AddCrew(crewMember); crewMember.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; }
public void ImportVessel(string name) { if (System.IO.File.Exists(name)) { Log($"Importing vessel: {name}"); ConfigNode storedNode = ConfigNode.Load(name); ConfigNode vesselNode = storedNode.GetNode("VESSEL"); vesselNode.SetValue("pid", Guid.NewGuid().ToString()); if (WarnOfInvalidParts(vesselNode, true)) { return; } List <ProtoCrewMember> crewAdded = new List <ProtoCrewMember>(); if (!_includeCrew) { //clear out all crew on vessel StripCrew(vesselNode); } else { //create crewmembers if they don't exist, set all of them to assigned try { foreach (ConfigNode partNode in vesselNode.GetNodes("PART")) { if (partNode.HasValue("crew")) { List <string> toRemove = new List <string>(); foreach (ConfigNode.Value crewValue in partNode.values)//(string crewmember in partNode.GetValues("crew")) { if (crewValue.name != "crew") { continue; } string crewmember = crewValue.value; //find the confignode saved with the vessel ConfigNode crewNode = storedNode.GetNodes("CREW")?.FirstOrDefault(c => c.GetValue("name") == crewmember); if (crewNode == null || crewNode.GetValue("type") != "Crew") //if no data or is tourist then remove from ship { //can't find the required data, so remove that kerbal from the ship Log($"Vessel occupant is not crew: {crewmember}"); toRemove.Add(crewmember); continue; } ProtoCrewMember newCrew = new ProtoCrewMember(HighLogic.CurrentGame.Mode, crewNode, ProtoCrewMember.KerbalType.Crew); if (HighLogic.CurrentGame.CrewRoster.Exists(crewmember)) //there's already a kerbal with that name (sadness :( ) { //alright, rename this kerbal to a new name string newName = RenameKerbal(crewmember); newCrew.ChangeName(newName); crewValue.value = newName; } Log($"Creating crewmember {newCrew.name}"); //add the crew member to the crew roster //the function to do this is hidden for some reason. yay! HighLogic.CurrentGame.CrewRoster.AddCrewMember(newCrew); //no longer hidden! MORE YAY! crewAdded.Add(newCrew); } foreach (string crewmember in toRemove) //remove all crews that shouldn't be here anymore { //find the value with this kerbal and remove it foreach (ConfigNode.Value val in partNode.values) { if (val.name == "crew" && val.value == crewmember) { Log($"Removing non-valid crew member {val.value}"); partNode.values.Remove(val); break; } } } } } } catch (Exception ex) { Log("Encountered exception while transferring crew. The exception follows. Stripping crew data."); Debug.LogException(ex); StripCrew(vesselNode); PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "errorPopup", "Error Occurred", "Unable to import crew. An exception occurred and has been logged.", "Ok", false, HighLogic.UISkin); return; } } ProtoVessel addedVessel = HighLogic.CurrentGame.AddVessel(vesselNode); foreach (ProtoCrewMember crew in crewAdded) { Log($"Assigning {crew.name}"); addedVessel.AddCrew(crew); } //In 1.2.2+ saving fails when there are two copies of a ship with crew onboard both. Might be part ID related. //All I know is that if I terminate the original flight, I can import crew. Otherwise it NREs when it tries to save the flight state. } }
private ProtoPartSnapshot CreatePartSnapshot(ProtoVessel proto, Part part) { var protoPartSnapshot = new ProtoPartSnapshot(new ConfigNode(), proto, HighLogic.CurrentGame); protoPartSnapshot.pVesselRef = proto; protoPartSnapshot.partRef = part; protoPartSnapshot.partRef.onBackup(); protoPartSnapshot.partStateValues = new Dictionary <string, KSPParseable>(); protoPartSnapshot.modules = new List <ProtoPartModuleSnapshot>(); protoPartSnapshot.resources = new List <ProtoPartResourceSnapshot>(); protoPartSnapshot.partName = part.partInfo.name; protoPartSnapshot.craftID = part.craftID; protoPartSnapshot.flightID = part.flightID; protoPartSnapshot.missionID = part.missionID; protoPartSnapshot.launchID = part.launchID; protoPartSnapshot.partInfo = PartLoader.getPartInfoByName(protoPartSnapshot.partName); protoPartSnapshot.position = part.orgPos; protoPartSnapshot.rotation = part.orgRot; protoPartSnapshot.mirror = part.mirrorVector; protoPartSnapshot.symMethod = part.symMethod; protoPartSnapshot.inverseStageIndex = part.inverseStage; protoPartSnapshot.resourcePriorityOffset = part.resourcePriorityOffset; protoPartSnapshot.defaultInverseStage = part.defaultInverseStage; protoPartSnapshot.seqOverride = part.manualStageOffset; protoPartSnapshot.inStageIndex = part.inStageIndex; protoPartSnapshot.separationIndex = part.separationIndex; protoPartSnapshot.customPartData = part.customPartData; protoPartSnapshot.attachMode = (int)part.attachMode; protoPartSnapshot.attached = part.isAttached; protoPartSnapshot.autostrutMode = part.autoStrutMode; protoPartSnapshot.rigidAttachment = part.rigidAttachment; protoPartSnapshot.mass = part.mass; protoPartSnapshot.shielded = part.ShieldedFromAirstream; protoPartSnapshot.temperature = part.temperature; protoPartSnapshot.skinTemperature = part.skinTemperature; protoPartSnapshot.skinUnexposedTemperature = part.skinUnexposedTemperature; protoPartSnapshot.explosionPotential = part.explosionPotential; protoPartSnapshot.state = (int)part.State; protoPartSnapshot.moduleCosts = part.GetModuleCosts(part.partInfo.cost, ModifierStagingSituation.CURRENT); protoPartSnapshot.partRef.onFlightStateSave(protoPartSnapshot.partStateValues); protoPartSnapshot.partRef.protoPartSnapshot = protoPartSnapshot; protoPartSnapshot.protoModuleCrew = new List <ProtoCrewMember>(); protoPartSnapshot.protoCrewIndicesBackup = new List <int>(); protoPartSnapshot.protoCrewNames = new List <string>(); foreach (var item in part.protoModuleCrew) { protoPartSnapshot.protoModuleCrew.Add(item); protoPartSnapshot.protoCrewNames.Add(item.name); proto.AddCrew(item); } foreach (var partModule in part.Modules) { protoPartSnapshot.modules.Add(new ProtoPartModuleSnapshot(partModule)); } foreach (var resource in part.Resources) { protoPartSnapshot.resources.Add(new ProtoPartResourceSnapshot(resource)); } protoPartSnapshot.partEvents = new ConfigNode("EVENTS"); part.Events.OnSave(protoPartSnapshot.partEvents); protoPartSnapshot.partActions = new ConfigNode("ACTIONS"); part.Actions.OnSave(protoPartSnapshot.partActions); protoPartSnapshot.partData = new ConfigNode("PARTDATA"); part.OnSave(protoPartSnapshot.partData); protoPartSnapshot.flagURL = part.flagURL; //This is the part that bothers the multithreading, //we just get the transform from the dictionary instead of going against the Transform class protoPartSnapshot.refTransformName = PartTransformNames.ContainsKey(part) ? PartTransformNames[part] : string.Empty; //Old code that was replaced.... // if (part.GetReferenceTransform() == null) // { // protoPartSnapshot.refTransformName = string.Empty; // } // else // { // protoPartSnapshot.refTransformName = part.GetReferenceTransform().name; // } return(protoPartSnapshot); }