Advertisement
Guest User

KSTS Error

a guest
Nov 23rd, 2019
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.13 KB | None | 0 0
  1. //The error:
  2. //[KSTS] Mission.CreateShip(): System.NullReferenceException: Object reference not set to an instance of an object
  3. //  at ProtoPartModuleSnapshot..ctor (PartModule module) [0x00031] in <9d71e4043e394d78a6cf9193ad011698>:0
  4. //  at ProtoPartSnapshot..ctor (Part PartRef, ProtoVessel protoVessel, System.Boolean preCreate) [0x0033f] in <9d71e4043e394d78a6cf9193ad011698>:0
  5. //  at ProtoPartSnapshot..ctor (Part PartRef, ProtoVessel protoVessel) [0x00000] in <9d71e4043e394d78a6cf9193ad011698>:0
  6. //  at KSTS.Mission.CreateShip () [0x003ed] in <06b46a45b55341bbbcf561e6170cada0>:0
  7.  
  8. //The code from the original mod:
  9.         private void CreateShip()
  10.         {
  11.             try
  12.             {
  13.                 // The ShipConstruct-object can only savely exist while not in flight, otherwise it will spam Null-Pointer Exceptions every tick:
  14.                 if (HighLogic.LoadedScene == GameScenes.FLIGHT) throw new Exception("unable to run CreateShip while in flight");
  15.  
  16.                 // Load the parts form the saved vessel:
  17.                 if (!File.Exists(shipTemplateFilename)) throw new Exception("file '" + shipTemplateFilename + "' not found");
  18.                 ShipConstruct shipConstruct = ShipConstruction.LoadShip(shipTemplateFilename);
  19.                 ProtoVessel dummyProto = new ProtoVessel(new ConfigNode(), null);
  20.                 Vessel dummyVessel = new Vessel();
  21.                 dummyProto.vesselRef = dummyVessel;
  22.  
  23.                 // Maybe adjust the orbit:
  24.                 float vesselHeight = Math.Max(Math.Max(shipConstruct.shipSize.x, shipConstruct.shipSize.y), shipConstruct.shipSize.z);
  25.                 if (missionType == MissionType.DEPLOY)
  26.                 {
  27.                     // Make sure that there won't be any collisions, when the vessel is created at the given orbit:
  28.                     orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
  29.                 }
  30.                 else if (missionType == MissionType.CONSTRUCT)
  31.                 {
  32.                     // Deploy the new ship next to the space-dock:
  33.                     Vessel spaceDock = TargetVessel.GetVesselById((Guid)targetVesselId);
  34.                     orbit = GUIOrbitEditor.CreateFollowingOrbit(spaceDock.orbit, TargetVessel.GetVesselSize(spaceDock) + vesselHeight);
  35.                     orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
  36.                 }
  37.                 else throw new Exception("invalid mission-type '" + missionType.ToString() + "'");
  38.  
  39.                 // Instead of loading and constructing the ship ourselfs ShipConstruction.AssembleForLaunch() seems like the better
  40.                 // option, this however just seems to work while in flight and even then I was unable to get it working correctly
  41.                 // (it switches to the newly created ship and setting an orbit afterwards does not work correctly).
  42.  
  43.                 // In theory it should be enough to simply copy the parts from the ShipConstruct to the ProtoVessel, but
  44.                 // this only seems to work when the saved vessel starts with the root-part and is designed top down from there.
  45.                 // It seems that the root part has to be the first part in the ProtoVessel's parts-list and all other parts have
  46.                 // 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
  47.                 // are not in the correct order, their rotation seems to get messed up or they are attached to the wrong
  48.                 // attachmet-nodes, which is why we have to re-sort the parts with our own logic here.
  49.                 // This part of the code is experimental however and only based on my own theories and observations about KSP's vessels.
  50.                 Part rootPart = null;
  51.                 foreach (Part p in shipConstruct.parts)
  52.                 {
  53.                     if (p.parent == null) { rootPart = p; break; }
  54.                 }
  55.                 List<Part> pList = null;
  56.                 dummyVessel.parts = FindAndAddAttachedParts(rootPart, ref pList); // Find all parts which are directly attached to the root-part and add them in order.
  57.  
  58.                 // Handle Subassemblies which are attached by surface attachment-nodes:
  59.                 bool handleSurfaceAttachments = true;
  60.                 while (dummyVessel.parts.Count < shipConstruct.parts.Count)
  61.                 {
  62.                     int processedParts = 0;
  63.                     foreach (Part p in shipConstruct.parts)
  64.                     {
  65.                         if (dummyVessel.parts.Contains(p)) continue;
  66.                         if (handleSurfaceAttachments)
  67.                         {
  68.                             // Check if the part is attached by a surface-node:
  69.                             if (p.srfAttachNode != null && dummyVessel.parts.Contains(p.srfAttachNode.attachedPart))
  70.                             {
  71.                                 // Add this surface attached part and all the sub-parts:
  72.                                 dummyVessel.parts = FindAndAddAttachedParts(p, ref dummyVessel.parts);
  73.                                 processedParts++;
  74.                             }
  75.                         }
  76.                         else
  77.                         {
  78.                             // Simply copy this part:
  79.                             dummyVessel.parts.Add(p);
  80.                         }
  81.                     }
  82.                     if (processedParts == 0)
  83.                     {
  84.                         // If there are still unprocessed parts, just throw them in the list during the next iteration,
  85.                         // this should not happen but we don't want to end up in an endless loop:
  86.                         handleSurfaceAttachments = false;
  87.                     }
  88.                 }
  89.  
  90.                 // Initialize all parts:
  91.                 uint missionID = (uint)Guid.NewGuid().GetHashCode();
  92.                 uint launchID = HighLogic.CurrentGame.launchID++;
  93.                 int maxStageOffset = -1;
  94.                 foreach (Part p in dummyVessel.parts)
  95.                 {
  96.                     p.flagURL = flagURL == null ? HighLogic.CurrentGame.flagURL : flagURL;
  97.                     p.missionID = missionID;
  98.                     p.launchID = launchID;
  99.                     p.temperature = 1.0;
  100.                     maxStageOffset = Math.Max(p.stageOffset, maxStageOffset); // stageOffset is offset of this part in the staging-order (0..n with -1 meaning not staged)
  101.  
  102.                     // 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.
  103.                     // 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
  104.                     // be the same as in the stored craft:
  105.                     p.flightID = p.craftID;
  106.  
  107.                     // If the KRnD-Mod is installed, make sure that all parts of this newly created ship are set to the lates version:
  108.                     foreach (PartModule module in p.Modules)
  109.                     {
  110.                         if (module.moduleName != "KRnDModule") continue;
  111.                         Debug.Log("[KSTS] found KRnD on '" + p.name.ToString() + "', setting to latest stats");
  112.                         foreach (BaseField field in module.Fields)
  113.                         {
  114.                             if (field.name.ToString() == "upgradeToLatest")
  115.                             {
  116.                                 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.
  117.                                 if (field.GetValue(module).ToString() != "1") Debug.LogError("[KSTS] unable to modify '" + field.name.ToString() + "'");
  118.                             }
  119.                         }
  120.                     }
  121.  
  122.                     dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
  123.                 }
  124.  
  125.                 // Store the parts in Config-Nodes:
  126.                 foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
  127.                 {
  128.                     p.storePartRefs();
  129.                 }
  130.                 List<ConfigNode> partNodesL = new List<ConfigNode>();
  131.                 foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots)
  132.                 {
  133.                     ConfigNode node = new ConfigNode("PART");
  134.                     snapShot.Save(node);
  135.                     partNodesL.Add(node);
  136.                 }
  137.                 ConfigNode[] partNodes = partNodesL.ToArray();
  138.                 ConfigNode[] additionalNodes = new ConfigNode[0];
  139.  
  140.                 // This will actually create the ship and add it to the global list of flights:
  141.                 ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(shipName, VesselType.Ship, orbit, 0, partNodes, additionalNodes);
  142.                 ProtoVessel pv = HighLogic.CurrentGame.AddVessel(protoVesselNode);
  143.                 Debug.Log("[KSTS] deployed new ship '" + shipName.ToString() + "' as '" + pv.vesselRef.id.ToString() + "'");
  144.                 ScreenMessages.PostScreenMessage("Vessel '" + shipName.ToString() + "' deployed"); // Popup message to notify the player
  145.                 Vessel newVessel = FlightGlobals.Vessels.Find(x => x.id == pv.vesselID);
  146.                
  147.                 // While each part knows in which stage they are, the vessel has to know how many stages there are in total:
  148.                 newVessel.protoVessel.stage = maxStageOffset + 1; // an offest of 0 would mean that there is only one stage
  149.  
  150.                 // Maybe add the initial crew to the vessel:
  151.                 if (crewToDeliver != null && crewToDeliver.Count > 0 && newVessel != null)
  152.                 {
  153.                     foreach (string kerbonautName in crewToDeliver) TargetVessel.AddCrewMember(newVessel, kerbonautName);
  154.                 }
  155.  
  156.                 // Notify other mods about the new vessel:
  157.                 GameEvents.onVesselCreate.Fire(newVessel);
  158.             }
  159.             catch (Exception e)
  160.             {
  161.                 Debug.LogError("[KSTS] Mission.CreateShip(): " + e.ToString());
  162.             }
  163.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement