Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //The error:
- //[KSTS] Mission.CreateShip(): System.NullReferenceException: Object reference not set to an instance of an object
- // at ProtoPartModuleSnapshot..ctor (PartModule module) [0x00031] in <9d71e4043e394d78a6cf9193ad011698>:0
- // at ProtoPartSnapshot..ctor (Part PartRef, ProtoVessel protoVessel, System.Boolean preCreate) [0x0033f] in <9d71e4043e394d78a6cf9193ad011698>:0
- // at ProtoPartSnapshot..ctor (Part PartRef, ProtoVessel protoVessel) [0x00000] in <9d71e4043e394d78a6cf9193ad011698>:0
- // at KSTS.Mission.CreateShip () [0x003ed] in <06b46a45b55341bbbcf561e6170cada0>:0
- //The code from the original mod:
- private void CreateShip()
- {
- try
- {
- // The ShipConstruct-object can only savely exist while not in flight, otherwise it will spam Null-Pointer Exceptions every tick:
- if (HighLogic.LoadedScene == GameScenes.FLIGHT) throw new Exception("unable to run CreateShip while in flight");
- // Load the parts form the saved vessel:
- if (!File.Exists(shipTemplateFilename)) throw new Exception("file '" + shipTemplateFilename + "' not found");
- ShipConstruct shipConstruct = ShipConstruction.LoadShip(shipTemplateFilename);
- ProtoVessel dummyProto = new ProtoVessel(new ConfigNode(), null);
- Vessel dummyVessel = new Vessel();
- dummyProto.vesselRef = dummyVessel;
- // Maybe adjust the orbit:
- float vesselHeight = Math.Max(Math.Max(shipConstruct.shipSize.x, shipConstruct.shipSize.y), shipConstruct.shipSize.z);
- if (missionType == MissionType.DEPLOY)
- {
- // Make sure that there won't be any collisions, when the vessel is created at the given orbit:
- orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
- }
- else if (missionType == MissionType.CONSTRUCT)
- {
- // Deploy the new ship next to the space-dock:
- Vessel spaceDock = TargetVessel.GetVesselById((Guid)targetVesselId);
- orbit = GUIOrbitEditor.CreateFollowingOrbit(spaceDock.orbit, TargetVessel.GetVesselSize(spaceDock) + vesselHeight);
- orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
- }
- else throw new Exception("invalid mission-type '" + missionType.ToString() + "'");
- // Instead of loading and constructing the ship ourselfs ShipConstruction.AssembleForLaunch() seems like the better
- // option, this however just seems to work while in flight and even then I was unable to get it working correctly
- // (it switches to the newly created ship and setting an orbit afterwards does not work correctly).
- // In theory it should be enough to simply copy the parts from the ShipConstruct to the ProtoVessel, but
- // this only seems to work when the saved vessel starts with the root-part and is designed top down from there.
- // It seems that the root part has to be the first part in the ProtoVessel's parts-list and all other parts have
- // to be listed in sequence radiating from the root part (eg 1=>2=>R<=3<=4 should be R,2,1,3,4). If the parts
- // are not in the correct order, their rotation seems to get messed up or they are attached to the wrong
- // attachmet-nodes, which is why we have to re-sort the parts with our own logic here.
- // This part of the code is experimental however and only based on my own theories and observations about KSP's vessels.
- Part rootPart = null;
- foreach (Part p in shipConstruct.parts)
- {
- if (p.parent == null) { rootPart = p; break; }
- }
- List<Part> pList = null;
- dummyVessel.parts = FindAndAddAttachedParts(rootPart, ref pList); // Find all parts which are directly attached to the root-part and add them in order.
- // Handle Subassemblies which are attached by surface attachment-nodes:
- bool handleSurfaceAttachments = true;
- while (dummyVessel.parts.Count < shipConstruct.parts.Count)
- {
- int processedParts = 0;
- foreach (Part p in shipConstruct.parts)
- {
- if (dummyVessel.parts.Contains(p)) continue;
- if (handleSurfaceAttachments)
- {
- // Check if the part is attached by a surface-node:
- if (p.srfAttachNode != null && dummyVessel.parts.Contains(p.srfAttachNode.attachedPart))
- {
- // Add this surface attached part and all the sub-parts:
- dummyVessel.parts = FindAndAddAttachedParts(p, ref dummyVessel.parts);
- processedParts++;
- }
- }
- else
- {
- // Simply copy this part:
- dummyVessel.parts.Add(p);
- }
- }
- if (processedParts == 0)
- {
- // If there are still unprocessed parts, just throw them in the list during the next iteration,
- // this should not happen but we don't want to end up in an endless loop:
- handleSurfaceAttachments = false;
- }
- }
- // Initialize all parts:
- uint missionID = (uint)Guid.NewGuid().GetHashCode();
- uint launchID = HighLogic.CurrentGame.launchID++;
- int maxStageOffset = -1;
- foreach (Part p in dummyVessel.parts)
- {
- p.flagURL = flagURL == null ? HighLogic.CurrentGame.flagURL : flagURL;
- p.missionID = missionID;
- p.launchID = launchID;
- p.temperature = 1.0;
- maxStageOffset = Math.Max(p.stageOffset, maxStageOffset); // stageOffset is offset of this part in the staging-order (0..n with -1 meaning not staged)
- // Apparently the part's ID from the saved craft is stored in craftID and has to get copied by hand into flightID, which is 0 by default.
- // If it is not set, docking won't work and since it is referenced by surface-attachments like struts and fuel lines, it should always
- // be the same as in the stored craft:
- p.flightID = p.craftID;
- // If the KRnD-Mod is installed, make sure that all parts of this newly created ship are set to the lates version:
- foreach (PartModule module in p.Modules)
- {
- if (module.moduleName != "KRnDModule") continue;
- Debug.Log("[KSTS] found KRnD on '" + p.name.ToString() + "', setting to latest stats");
- foreach (BaseField field in module.Fields)
- {
- if (field.name.ToString() == "upgradeToLatest")
- {
- field.SetValue(1, module); // Newer versions of KRnD use this flag to upgrade all attributes of the given part to the latest levels, when the vessel is activated.
- if (field.GetValue(module).ToString() != "1") Debug.LogError("[KSTS] unable to modify '" + field.name.ToString() + "'");
- }
- }
- }
- dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
- }
- // Store the parts in Config-Nodes:
- foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
- {
- p.storePartRefs();
- }
- List<ConfigNode> partNodesL = new List<ConfigNode>();
- foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots)
- {
- ConfigNode node = new ConfigNode("PART");
- snapShot.Save(node);
- partNodesL.Add(node);
- }
- ConfigNode[] partNodes = partNodesL.ToArray();
- ConfigNode[] additionalNodes = new ConfigNode[0];
- // This will actually create the ship and add it to the global list of flights:
- ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(shipName, VesselType.Ship, orbit, 0, partNodes, additionalNodes);
- ProtoVessel pv = HighLogic.CurrentGame.AddVessel(protoVesselNode);
- Debug.Log("[KSTS] deployed new ship '" + shipName.ToString() + "' as '" + pv.vesselRef.id.ToString() + "'");
- ScreenMessages.PostScreenMessage("Vessel '" + shipName.ToString() + "' deployed"); // Popup message to notify the player
- Vessel newVessel = FlightGlobals.Vessels.Find(x => x.id == pv.vesselID);
- // While each part knows in which stage they are, the vessel has to know how many stages there are in total:
- newVessel.protoVessel.stage = maxStageOffset + 1; // an offest of 0 would mean that there is only one stage
- // Maybe add the initial crew to the vessel:
- if (crewToDeliver != null && crewToDeliver.Count > 0 && newVessel != null)
- {
- foreach (string kerbonautName in crewToDeliver) TargetVessel.AddCrewMember(newVessel, kerbonautName);
- }
- // Notify other mods about the new vessel:
- GameEvents.onVesselCreate.Fire(newVessel);
- }
- catch (Exception e)
- {
- Debug.LogError("[KSTS] Mission.CreateShip(): " + e.ToString());
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement