private static ProtoVessel GetVesselFromShipConstruct(ShipConstruct shipConstruct, ProtoVessel oldVessel, Game game) { foreach (var p in shipConstruct.parts) { p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.missionID = oldVessel.protoPartSnapshots[0].missionID; p.launchID = oldVessel.protoPartSnapshots[0].launchID; p.flagURL = oldVessel.protoPartSnapshots[0].flagURL ?? HighLogic.CurrentGame.flagURL; p.temperature = 1.0; // LITARLY NO CLUE WHY NO CODE IN SQUAD IS EXECUTING THIS (this little piece of shit took me 2 days) p.UpdateOrgPosAndRot(shipConstruct.parts[0]); } var empty = new ConfigNode(); var dummyProto = new ProtoVessel(empty, null); var dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; // ReSharper disable once SuggestVarOrType_SimpleTypes foreach (Part p in shipConstruct.parts) { dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } // ReSharper disable once SuggestVarOrType_SimpleTypes foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } return(dummyProto); }
private void GenerateStrandedKerbal(int bodyID, string kerbalName) { //Add kerbal to crew roster. DarkLog.Debug("Spawning missing kerbal, name: " + kerbalName); ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); pcm.name = kerbalName; pcm.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; //Create protovessel uint newPartID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); CelestialBody contractBody = FlightGlobals.Bodies[bodyID]; //Atmo: 10km above atmo, to half the planets radius out. //Non-atmo: 30km above ground, to half the planets radius out. double minAltitude = FinePrint.Utilities.CelestialUtilities.GetMinimumOrbitalAltitude(contractBody, 1.1f); double maxAltitude = minAltitude + contractBody.Radius * 0.5; Orbit strandedOrbit = Orbit.CreateRandomOrbitAround(FlightGlobals.Bodies[bodyID], minAltitude, maxAltitude); ConfigNode[] kerbalPartNode = new ConfigNode[1]; ProtoCrewMember[] partCrew = new ProtoCrewMember[1]; partCrew[0] = pcm; kerbalPartNode[0] = ProtoVessel.CreatePartNode("kerbalEVA", newPartID, partCrew); ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(kerbalName, VesselType.EVA, strandedOrbit, 0, kerbalPartNode); ConfigNode discoveryNode = ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A, double.PositiveInfinity, double.PositiveInfinity); ProtoVessel protoVessel = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame); protoVessel.discoveryInfo = discoveryNode; //It's not supposed to be infinite, but you're crazy if you think I'm going to decipher the values field of the rescue node. HighLogic.CurrentGame.flightState.protoVessels.Add(protoVessel); }
private void CreateLode(LodeData lodeData) { lodeData.altitude = TerrainHeight(lodeData.latitude, lodeData.longitude, lodeData.body); Vector3d pos = lodeData.body.GetWorldSurfacePosition(lodeData.latitude, lodeData.longitude, lodeData.altitude.Value); lodeData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, lodeData.body); lodeData.orbit.UpdateFromStateVectors(pos, lodeData.body.getRFrmVel(pos), lodeData.body, Planetarium.GetUniversalTime()); ConfigNode[] partNodes; ShipConstruct shipConstruct = null; uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode(lodeData.craftPart.name, flightId); DiscoveryLevels discoveryLevel = DiscoveryLevels.Owned; ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(lodeData.name, lodeData.vesselType, lodeData.orbit, 0, partNodes); Vector3d norm = lodeData.body.GetRelSurfaceNVector(lodeData.latitude, lodeData.longitude); double terrainHeight = 0.0; if (lodeData.body.pqsController != null) { terrainHeight = lodeData.body.pqsController.GetSurfaceHeight(norm) - lodeData.body.pqsController.radius; } bool splashed = true && terrainHeight < 0.001; protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : Vessel.Situations.LANDED).ToString()); protoVesselNode.SetValue("landed", (!splashed).ToString()); protoVesselNode.SetValue("splashed", splashed.ToString()); protoVesselNode.SetValue("lat", lodeData.latitude.ToString()); protoVesselNode.SetValue("lon", lodeData.longitude.ToString()); protoVesselNode.SetValue("alt", lodeData.altitude.ToString()); protoVesselNode.SetValue("landedAt", lodeData.body.name); float lowest = float.MaxValue; foreach (Collider collider in lodeData.craftPart.partPrefab.GetComponentsInChildren <Collider>()) { if (collider.gameObject.layer != 21 && collider.enabled) { lowest = Mathf.Min(lowest, collider.bounds.min.y); } } if (Mathf.Approximately(lowest, float.MaxValue)) { lowest = 0; } Quaternion normal = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); Quaternion rotation = Quaternion.identity; rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back); float hgt = (shipConstruct != null ? shipConstruct.parts[0] : lodeData.craftPart.partPrefab).localRoot.attPos0.y - lowest; protoVesselNode.SetValue("hgt", hgt.ToString()); protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation * normal)); Vector3 nrm = (rotation * Vector3.forward); protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z); protoVesselNode.SetValue("prst", false.ToString()); ProtoVessel protoVessel = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame); protoVessel.Load(HighLogic.CurrentGame.flightState); }
public static Part CreatePart(AvailablePart avPart, Vector3 position, Quaternion rotation, Part flagFromPart) { UnityEngine.Object obj = UnityEngine.Object.Instantiate(avPart.partPrefab); if (!obj) { KAS_Shared.DebugError("CreatePart(Crate) Failed to instantiate " + avPart.partPrefab.name); return null; } Part newPart = (Part)obj; newPart.gameObject.SetActive(true); newPart.gameObject.name = avPart.name; newPart.partInfo = avPart; //newPart.highlightRecurse = true; newPart.SetMirror(Vector3.one); ShipConstruct newShip = new ShipConstruct(); newShip.Add(newPart); newShip.SaveShip(); newShip.shipName = avPart.title; //newShip.ty = 1; VesselCrewManifest vessCrewManifest = new VesselCrewManifest(); Vessel currentVessel = FlightGlobals.ActiveVessel; Vessel v = newShip.parts[0].localRoot.gameObject.AddComponent<Vessel>(); v.id = Guid.NewGuid(); v.vesselName = newShip.shipName; v.Initialize(false); v.Landed = true; v.rootPart.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); v.rootPart.missionID = flagFromPart.missionID; v.rootPart.flagURL = flagFromPart.flagURL; //v.rootPart.collider.isTrigger = true; //v.landedAt = "somewhere"; Staging.beginFlight(); newShip.parts[0].vessel.ResumeStaging(); Staging.GenerateStagingSequence(newShip.parts[0].localRoot); Staging.RecalculateVesselStaging(newShip.parts[0].vessel); FlightGlobals.SetActiveVessel(currentVessel); v.SetPosition(position); v.SetRotation(rotation); // Solar panels from containers don't work otherwise for (int i = 0; i < newPart.Modules.Count; i++) { ConfigNode node = new ConfigNode(); node.AddValue("name", newPart.Modules[i].moduleName); newPart.LoadModule(node, ref i); } return newPart; }
public static Part LoadPartSnapshot(Vessel vessel, ConfigNode node, Vector3 position, Quaternion rotation) { ProtoPartSnapshot snapshot = KAS_Shared.LoadProtoPartSnapshot(node); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID)) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.flagURL = vessel.rootPart.flagURL; // Save properties that may be messed up by new colliders RigidbodyInertia rb_backup = new RigidbodyInertia(vessel.rootPart.rb); Part new_part = snapshot.Load(vessel, false); vessel.Parts.Add(new_part); if (vessel.packed) { GameEvents.onVesselWasModified.Fire(vessel); } else { // Request initialization as nonphysical to prevent explosions new_part.physicalSignificance = Part.PhysicalSignificance.NONE; // Disable all sub-objects with colliders List <Collider> re_enable = new List <Collider>(); foreach (var collider in new_part.GetComponentsInChildren <Collider>()) { if (collider.gameObject.activeSelf) { re_enable.Add(collider); collider.gameObject.SetActive(false); } } new_part.StartCoroutine(WaitAndUnpack(new_part, re_enable)); } rb_backup.Restore(vessel.rootPart.rb); return(new_part); }
protected override void OnAccepted() { // Actually spawn the kerbals in the game world! foreach (KerbalData kerbal in kerbals) { LoggingUtil.LogVerbose(this, "Spawning a Kerbal named " + kerbal.name); if (kerbal.altitude == null) { kerbal.altitude = LocationUtil.TerrainHeight(kerbal.latitude, kerbal.longitude, kerbal.body); } // Set additional info for landed kerbals if (kerbal.landed) { Vector3d pos = kerbal.body.GetWorldSurfacePosition(kerbal.latitude, kerbal.longitude, kerbal.altitude.Value); kerbal.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, kerbal.body); kerbal.orbit.UpdateFromStateVectors(pos, kerbal.body.getRFrmVel(pos), kerbal.body, Planetarium.GetUniversalTime()); LoggingUtil.LogVerbose(typeof(SpawnKerbal), "kerbal generated, orbit = " + kerbal.orbit); } uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); // Create crew member array ProtoCrewMember[] crewArray = new ProtoCrewMember[1]; crewArray[0] = kerbal.crewMember; // Create part nodes ConfigNode[] partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode("kerbalEVA", flightId, crewArray); // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[1]; DiscoveryLevels discoveryLevel = kerbal.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, UntrackedObjectClass.A, contract.TimeDeadline, contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(kerbal.name, VesselType.EVA, kerbal.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed Kerbal if (kerbal.landed) { // Create the config node representation of the ProtoVessel protoVesselNode.SetValue("sit", Vessel.Situations.LANDED.ToString()); protoVesselNode.SetValue("landed", true.ToString()); protoVesselNode.SetValue("lat", kerbal.latitude.ToString()); protoVesselNode.SetValue("lon", kerbal.longitude.ToString()); protoVesselNode.SetValue("alt", kerbal.altitude.ToString()); } // Add vessel to the game HighLogic.CurrentGame.AddVessel(protoVesselNode); } }
//creation public static Vessel Create(Creature creature, Vector3 positionOffset) { try { AvailablePart partInfo = PartLoader.LoadedPartsList.First(ap => ap.name == creature.part); Part referencePart = FlightGlobals.ActiveVessel.rootPart; Part part = (Part)UnityEngine.Object.Instantiate(partInfo.partPrefab); part.gameObject.SetActive(true); part.gameObject.name = partInfo.name; part.partInfo = partInfo; part.SetMirror(Vector3.one); ShipConstruct sc = new ShipConstruct(); sc.Add(part); sc.SaveShip(); sc.shipName = creature.name; Vessel vessel = sc.parts[0].localRoot.gameObject.AddComponent <Vessel>(); vessel.id = Guid.NewGuid(); vessel.vesselName = sc.shipName; vessel.vesselType = VesselType.Unknown; //vessel.DiscoveryInfo.Load(ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A, 10000, 10000)); vessel.ctrlState = new FlightCtrlState(); vessel.ctrlState.NeutralizeAll(); vessel.Initialize(false); vessel.Landed = false; vessel.SetPosition(referencePart.transform.position + positionOffset); vessel.SetRotation(Quaternion.identity); //manually remove orbit renderer UnityEngine.Object.Destroy(vessel.orbitDriver.Renderer); CreaturePart cp = (CreaturePart)vessel.rootPart; cp.creature = creature; cp.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); cp.missionID = referencePart.missionID; cp.flagURL = referencePart.flagURL; FlightLogger.eventLog.Add(Utils.FormatTime(referencePart.vessel.missionTime) + "A " + creature.name + " was seen."); return(vessel); } catch (Exception e) { Utils.LogError("Error encountered while spawning part"); if (e != null) { Debug.LogException(e); } } return(null); }
public static Part CreatePart(AvailablePart avPart, Vector3 position, Quaternion rotation, Part flagFromPart) { UnityEngine.Object obj = UnityEngine.Object.Instantiate(avPart.partPrefab); if (!obj) { KAS_Shared.DebugError("CreatePart(Crate) Failed to instantiate " + avPart.partPrefab.name); return(null); } Part newPart = (Part)obj; newPart.gameObject.SetActive(true); newPart.gameObject.name = "KASCreatedPart"; newPart.partInfo = avPart; newPart.highlightRecurse = true; ShipConstruct newShip = new ShipConstruct(); newShip.Add(newPart); newShip.SaveShip(); newShip.shipName = avPart.title; newShip.shipType = 1; VesselCrewManifest vessCrewManifest = new VesselCrewManifest(); Vessel currentVessel = FlightGlobals.ActiveVessel; Vessel v = newShip.parts[0].localRoot.gameObject.AddComponent <Vessel>(); v.id = Guid.NewGuid(); v.vesselName = newShip.shipName; v.Initialize(false); v.Landed = true; v.rootPart.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); v.rootPart.missionID = (uint)Guid.NewGuid().GetHashCode(); v.rootPart.flagURL = flagFromPart.flagURL; //v.rootPart.collider.isTrigger = true; v.rootPart.FindModelTransform("model").localScale *= v.rootPart.rescaleFactor; //v.landedAt = "somewhere"; Staging.beginFlight(); newShip.parts[0].vessel.ResumeStaging(); Staging.GenerateStagingSequence(newShip.parts[0].localRoot); Staging.RecalculateVesselStaging(newShip.parts[0].vessel); FlightGlobals.SetActiveVessel(currentVessel); v.SetPosition(position); v.SetRotation(rotation); return(newPart); }
private static ConfigNode CreateVesselNode(PlacementRequest request, Orbit orbit) { // create an id for the flight object that will represent the kerbal's EVA var genderQualifier = request.Kerbal.gender == ProtoCrewMember.Gender.Female ? "female" : string.Empty; var flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); $"created flightId {flightId}".Debug(); // create a ship consisting of just the kerbal - this is how EVAs are represented in KSP var partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode($"kerbalEVA{genderQualifier}", flightId, request.Kerbal); "created partNodes".Debug(); var vesselNode = ProtoVessel.CreateVesselNode(request.Kerbal.name, VesselType.EVA, orbit, 0, partNodes); "created vesselNode".Debug(); return(vesselNode); }
private static void GenerateStrandedKerbal(int bodyId, string kerbalName) { //Add kerbal to crew roster. LunaLog.Log($"[LMP]: Spawning missing kerbal, Name: {kerbalName}"); var pcm = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); pcm.ChangeName(kerbalName); pcm.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; //Create protovessel var newPartId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); var contractBody = FlightGlobals.Bodies[bodyId]; //Atmo: 10km above atmo, to half the planets radius out. //Non-atmo: 30km above ground, to half the planets radius out. var minAltitude = CelestialUtilities.GetMinimumOrbitalDistance(contractBody, 1.1f); var maxAltitude = minAltitude + contractBody.Radius * 0.5; var strandedOrbit = Orbit.CreateRandomOrbitAround(FlightGlobals.Bodies[bodyId], minAltitude, maxAltitude); var kerbalPartNode = new[] { ProtoVessel.CreatePartNode("kerbalEVA", newPartId, pcm) }; var protoVesselNode = ProtoVessel.CreateVesselNode(kerbalName, VesselType.EVA, strandedOrbit, 0, kerbalPartNode); //It's not supposed to be infinite, but you're crazy if you think I'm going to decipher the values field of the rescue node. var discoveryNode = ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A, double.PositiveInfinity, double.PositiveInfinity); var protoVessel = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame) { discoveryInfo = discoveryNode }; HighLogic.CurrentGame.flightState.protoVessels.Add(protoVessel); }
protected override void OnAccepted() { // Actually spawn the kerbals in the game world! foreach (KerbalData kerbal in kerbals) { uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); // Create crew member array ProtoCrewMember[] crewArray = new ProtoCrewMember[1]; crewArray[0] = kerbal.crewMember; // Create part nodes ConfigNode[] partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode("kerbalEVA", flightId, crewArray); // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[1]; DiscoveryLevels discoveryLevel = kerbal.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, UntrackedObjectClass.A, contract.TimeDeadline, contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(kerbal.name, VesselType.EVA, kerbal.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed Kerbal if (kerbal.landed) { // Create the config node representation of the ProtoVessel protoVesselNode.SetValue("sit", Vessel.Situations.LANDED.ToString()); protoVesselNode.SetValue("landed", true.ToString()); protoVesselNode.SetValue("lat", kerbal.latitude.ToString()); protoVesselNode.SetValue("lon", kerbal.longitude.ToString()); protoVesselNode.SetValue("alt", kerbal.altitude.ToString()); } // Add vessel to the game HighLogic.CurrentGame.AddVessel(protoVesselNode); } }
protected void CreateVessels() { if (vesselsCreated) { return; } String gameDataDir = KSPUtil.ApplicationRootPath; gameDataDir = gameDataDir.Replace("\\", "/"); if (!gameDataDir.EndsWith("/")) { gameDataDir += "/"; } gameDataDir += "GameData"; // Spawn the vessel in the game world foreach (VesselData vesselData in vessels) { LoggingUtil.LogVerbose(this, "Spawning a vessel named '" + vesselData.name + "'"); // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB! ConfigNode currentShip = ShipConstruction.ShipConfig; ShipConstruct shipConstruct = ShipConstruction.LoadShip(gameDataDir + "/" + vesselData.craftURL); if (shipConstruct == null) { LoggingUtil.LogError(this, "ShipConstruct was null when tried to load '" + vesselData.craftURL + "' (usually this means the file could not be found)."); continue; } // Restore ShipConstruction ship ShipConstruction.ShipConfig = currentShip; // Set the name if (string.IsNullOrEmpty(vesselData.name)) { vesselData.name = shipConstruct.shipName; } // Set some parameters that need to be at the part level uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.flightID = flightId; p.missionID = missionID; p.launchID = launchID; p.flagURL = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL; } // Assign crew to the vessel foreach (CrewData cd in vesselData.crew) { bool success = false; // Find a seat for the crew Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity); // Add the crew member if (part != null) { // Create the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); if (cd.name != null) { crewMember.name = cd.name; } // Add them to the part success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); } if (!success) { LoggingUtil.LogWarning(this, "Unable to add crew to vessel named '" + vesselData.name + "'. Perhaps there's no room?"); break; } } // Set additional info for landed kerbals if (vesselData.landed) { if (vesselData.altitude == null) { vesselData.altitude = LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body); } Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value); vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body); vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime()); LoggingUtil.LogDebug(this, "vesselData generated, orbit = " + vesselData.orbit); } // Create a dummy ProtoVessel, we will use this to dump the parts to a config node. // We can't use the config nodes from the .craft file, because they are in a // slightly different format than those required for a ProtoVessel (seriously // Squad?!?). ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; // Create the ProtoPartSnapshot objects and then initialize them foreach (Part p in shipConstruct.parts) { dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } // Estimate an object class, numbers are based on the in game description of the // size classes. float size = shipConstruct.shipSize.magnitude / 2.0f; UntrackedObjectClass sizeClass; if (size < 4.0f) { sizeClass = UntrackedObjectClass.A; } else if (size < 7.0f) { sizeClass = UntrackedObjectClass.B; } else if (size < 12.0f) { sizeClass = UntrackedObjectClass.C; } else if (size < 18.0f) { sizeClass = UntrackedObjectClass.D; } else { sizeClass = UntrackedObjectClass.E; } // Create the ship's parts ConfigNode[] partNodes = dummyProto.protoPartSnapshots.Select <ProtoPartSnapshot, ConfigNode>(GetNodeForPart).ToArray(); // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[1]; DiscoveryLevels discoveryLevel = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed vessel if (vesselData.landed) { // Create the config node representation of the ProtoVessel protoVesselNode.SetValue("sit", Vessel.Situations.LANDED.ToString()); protoVesselNode.SetValue("landed", true.ToString()); protoVesselNode.SetValue("lat", vesselData.latitude.ToString()); protoVesselNode.SetValue("lon", vesselData.longitude.ToString()); protoVesselNode.SetValue("alt", vesselData.altitude.ToString()); protoVesselNode.SetValue("landedAt", vesselData.body.name); // Figure out the additional heigh to subtract float lowest = float.MaxValue; foreach (Part p in shipConstruct.parts) { foreach (Collider collider in p.GetComponentsInChildren <Collider>()) { if (collider.gameObject.layer != 21 && collider.enabled) { lowest = Mathf.Min(lowest, collider.bounds.min.y); } } } // Figure out the surface height and rotation Vector3d norm = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude); Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, Vector3.up) * Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); protoVesselNode.SetValue("hgt", (shipConstruct.parts[0].localRoot.attPos0.y - lowest).ToString()); protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation)); } // Add vessel to the game ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); // Store the id for later use vesselData.id = protoVessel.vesselRef.id; // Associate it so that it can be used in contract parameters ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef); } vesselsCreated = true; }
void SpawnVessel(string craftURL, CelestialBody orbitmainBodyName, double altitude, string stationName) { foreach (Vessel vessel in FlightGlobals.Vessels) { if (vessel.vesselName == stationName) { vessel.Die(); break; } } VesselData vesselData = new VesselData(); vesselData.craftURL = craftURL; vesselData.orbiting = true; vesselData.flagURL = HighLogic.CurrentGame.flagURL; vesselData.owned = true; string gameDataDir = KSPUtil.ApplicationRootPath; ConfigNode[] partNodes; ShipConstruct shipConstruct = null; float lcHeight = 0; ConfigNode craftNode; ConfigNode currentShip = ShipConstruction.ShipConfig; shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL); craftNode = ConfigNode.Load(vesselData.craftURL); lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y; ShipConstruction.ShipConfig = currentShip; ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.missionID = missionID; p.launchID = launchID; p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.temperature = 1.0; dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } List <ConfigNode> partNodesL = new List <ConfigNode>(); foreach (var snapShot in dummyProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); ConfigNode[] additionalNodes = new ConfigNode[0]; ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(stationName, VesselType.Station, new Orbit(0, 0, altitude + orbitmainBodyName.Radius, 0, 0, 0, 0, orbitmainBodyName), 0, partNodes, additionalNodes); ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); vesselData.id = protoVessel.vesselRef.id; foreach (var p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } }
public static Debris SetupOnTransform( Part original_part, Transform debris_transform, float mass, float cost, double lifetime ) { //get the part form DB var info = PartLoader.getPartInfoByName(DEBRIS_PART); if (info == null) { return(null); } //set part's transform and parent the debris model to the part var part = Instantiate(info.partPrefab); var partTransform = part.transform; partTransform.position = debris_transform.position; partTransform.rotation = original_part.transform.rotation; //copy the model and resize it var debris_object = Instantiate(debris_transform.gameObject).transform; var debris_part_model = part.transform.Find("model"); var orig_part_model = original_part.transform.Find("model"); debris_object.parent = debris_part_model; debris_object.localPosition = Vector3.zero; debris_object.rotation = debris_transform.rotation; debris_part_model.localScale = Vector3.Scale(debris_part_model.localScale, orig_part_model.localScale); debris_part_model.hasChanged = true; part.transform.hasChanged = true; //initialize the part part.gameObject.SetActive(true); part.physicalSignificance = Part.PhysicalSignificance.NONE; part.PromoteToPhysicalPart(); part.Rigidbody.mass = mass; part.orgPos = Vector3.zero; part.orgRot = Quaternion.identity; //initialize Debris module var debris = part.Modules.GetModule <Debris>(); if (debris == null) { Utils.Log("WARNING: {} part does not have Debris module!", DEBRIS_PART); Destroy(part.gameObject); return(null); } debris.actual_object = debris_object; debris.saved_cost = cost; debris.saved_mass = part.Rigidbody.mass; debris.original_part_name = original_part.partInfo.name; debris.debris_transform_name = debris_transform.name; debris.local_rotation = debris_object.localRotation; debris.local_scale = debris_object.parent.localScale; debris_transform.gameObject.SetActive(false); //initialize the vessel var vessel = part.gameObject.AddComponent <Vessel>(); vessel.name = vessel.vesselName = "Debris"; vessel.id = Guid.NewGuid(); vessel.Initialize(); //setup ids and flag part.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); part.missionID = original_part.missionID; part.launchID = original_part.launchID; part.flagURL = original_part.flagURL; //set part's velocities part.Rigidbody.angularVelocity = original_part.Rigidbody.angularVelocity; part.Rigidbody.velocity = original_part.Rigidbody.velocity + Vector3.Cross( original_part.Rigidbody.worldCenterOfMass - part.Rigidbody.worldCenterOfMass, part.Rigidbody.angularVelocity); //setup discovery info vessel.DiscoveryInfo.SetLastObservedTime(Planetarium.GetUniversalTime()); vessel.DiscoveryInfo.SetUnobservedLifetime(lifetime); vessel.DiscoveryInfo.SetUntrackedObjectSize(UntrackedObjectClass.A); vessel.DiscoveryInfo.SetLevel(DiscoveryLevels.Owned); //inform the game about the new vessel GameEvents.onNewVesselCreated.Fire(vessel); //return the part return(debris); }
static void SpawnVessel(VesselData vesselData) { string gameDataDir = KSPUtil.ApplicationRootPath; if (vesselData.vesselType == VesselType.Ship) { vesselData.name = "abandoned ship " + UnityEngine.Random.Range(1000, 10000); } else { vesselData.name = "abandoned science station " + UnityEngine.Random.Range(1000, 10000); } vesselData.orbit = FlightGlobals.ActiveVessel.GetOrbit(); vesselData.orbit.inclination = UnityEngine.Random.Range(0, 360); vesselData.orbit.eccentricity = UnityEngine.Random.Range(0, 0.3f); vesselData.orbit.semiMajorAxis = UnityEngine.Random.Range(Convert.ToSingle(FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.mainBody.atmosphereDepth + 50000), Convert.ToSingle(FlightGlobals.ActiveVessel.mainBody.sphereOfInfluence)); vesselData.orbit.LAN = UnityEngine.Random.Range(0, 360); vesselData.orbit.argumentOfPeriapsis = UnityEngine.Random.Range(0, 360); vesselData.orbit.meanAnomalyAtEpoch = 0; ConfigNode[] partNodes; ShipConstruct shipConstruct = null; float lcHeight = 0; ConfigNode craftNode; ConfigNode currentShip = ShipConstruction.ShipConfig; shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL); craftNode = ConfigNode.Load(vesselData.craftURL); lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y; ShipConstruction.ShipConfig = currentShip; ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.missionID = missionID; p.launchID = launchID; p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.temperature = 1.0; dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } List <ConfigNode> partNodesL = new List <ConfigNode>(); foreach (var snapShot in dummyProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); ConfigNode[] additionalNodes = new ConfigNode[0]; ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes); ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); vesselData.id = protoVessel.vesselRef.id; foreach (var p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } if (vesselData.vesselType == VesselType.Ship) { setResourcesAmount(protoVessel.vesselRef); } if (vesselData.vesselType == VesselType.Station) { setScience(protoVessel.vesselRef); } }
/// <remarks> /// This code is based on KAS by KospY and the following license applies: /// http://kerbal.curseforge.com/ksp-mods/223900-kerbal-attachment-system-kas/license (link valid 03.09.2014) /// Usage of this code by me (marce) has been generously granted by KospY on 02.09.2014 per PM. /// </remarks> public static Part SpawnPartInFlight(string partName, Part referencePart, Vector3 referencePartOriginSpawnOffset, Quaternion spawnRotation, bool spawnLanded = true) { if (!HighLogic.LoadedSceneIsFlight) { Debug.Log(LOG_PREFIX + " can only spawn in flight"); return(null); } var currentVessel = FlightGlobals.ActiveVessel; var avPart = PartLoader.getPartInfoByName(partName); if (avPart == null) { Debug.Log(LOG_PREFIX + " failed to find part " + partName); return(null); } var obj = UnityEngine.Object.Instantiate(avPart.partPrefab); if (obj == null) { Debug.Log(LOG_PREFIX + " failed to instantiate part " + partName); return(null); } try { var newPart = (Part)obj; newPart.gameObject.SetActive(true); newPart.gameObject.name = avPart.name; newPart.partInfo = avPart; //newPart.highlightRecurse = true; newPart.SetMirror(Vector3.one); var newShip = new ShipConstruct { newPart }; newShip.SaveShip(); newShip.shipName = avPart.title; var type = Convert.ChangeType(VesselType.Debris, VesselType.Debris.GetTypeCode()); //if (type != null) //{ // newShip.shipType = (int) type; //} //else //{ // newShip.shipType = 1; //} var v = newShip.parts[0].localRoot.gameObject.AddComponent <Vessel>(); v.id = Guid.NewGuid(); v.vesselName = newShip.shipName; v.Initialize(); v.Landed = spawnLanded; v.rootPart.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); v.rootPart.missionID = referencePart.missionID; v.rootPart.flagURL = referencePart.flagURL; FlightGlobals.SetActiveVessel(currentVessel); v.SetPosition(referencePart.transform.position + referencePartOriginSpawnOffset); v.SetRotation(spawnRotation); for (var i = 0; i < newPart.Modules.Count; i++) { var node = new ConfigNode(); node.AddValue("name", newPart.Modules[i].moduleName); var j = i; newPart.LoadModule(node, ref j); } return(newPart); } catch (NullReferenceException) { Debug.Log(LOG_PREFIX + " part unknown"); return(null); } }
public static Part CreatePart(ConfigNode partConfig, Vector3 position, Quaternion rotation, Part fromPart, Part coupleToPart = null, string srcAttachNodeID = null, AttachNode tgtAttachNode = null, OnPartCoupled onPartCoupled = null) { ConfigNode node_copy = new ConfigNode(); partConfig.CopyTo(node_copy); ProtoPartSnapshot snapshot = new ProtoPartSnapshot(node_copy, null, HighLogic.CurrentGame); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) || snapshot.flightID == 0) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.connected = true; snapshot.flagURL = fromPart.flagURL; Part newPart = snapshot.Load(fromPart.vessel, false); newPart.transform.position = position; newPart.transform.rotation = rotation; newPart.missionID = fromPart.missionID; fromPart.vessel.Parts.Add(newPart); newPart.physicalSignificance = Part.PhysicalSignificance.NONE; newPart.PromoteToPhysicalPart(); newPart.Unpack(); newPart.InitializeModules(); if (coupleToPart) { newPart.rigidbody.velocity = coupleToPart.rigidbody.velocity; newPart.rigidbody.angularVelocity = coupleToPart.rigidbody.angularVelocity; } else { if (fromPart.rigidbody) { newPart.rigidbody.velocity = fromPart.rigidbody.velocity; newPart.rigidbody.angularVelocity = fromPart.rigidbody.angularVelocity; } else { // If fromPart is a carried container newPart.rigidbody.velocity = fromPart.vessel.rootPart.rigidbody.velocity; newPart.rigidbody.angularVelocity = fromPart.vessel.rootPart.rigidbody.angularVelocity; } } newPart.decouple(); if (coupleToPart) { newPart.StartCoroutine(WaitAndCouple(newPart, coupleToPart, srcAttachNodeID, tgtAttachNode, onPartCoupled)); } else { newPart.vessel.vesselType = VesselType.Unknown; //name container ModuleKISInventory inv = newPart.GetComponent <ModuleKISInventory>(); if (inv) { if (inv.invName != "") { newPart.vessel.vesselName = inv.part.partInfo.title + " | " + inv.invName; } else { newPart.vessel.vesselName = inv.part.partInfo.title; } } } return(newPart); }
public static Vessel AssembleForLaunchUnlanded(ShipConstruct ship, IEnumerable <string> crewToDeliver, double duration, Orbit orbit, string flagUrl, Game sceneState) { var localRoot = ship.parts[0].localRoot; var vessel = localRoot.gameObject.GetComponent <Vessel>(); if (vessel == null) { vessel = localRoot.gameObject.AddComponent <Vessel>(); } vessel.id = Guid.NewGuid(); vessel.vesselName = ship.shipName; vessel.persistentId = ship.persistentId; vessel.Initialize(); if (orbit != null) { var orbitDriver = vessel.gameObject.GetComponent <OrbitDriver>(); if (orbitDriver == null) { orbitDriver = vessel.gameObject.AddComponent <OrbitDriver>(); vessel.orbitDriver = orbitDriver; } } vessel.Landed = false; vessel.Splashed = false; vessel.skipGroundPositioning = true; vessel.vesselSpawning = false; // vessel.loaded = false; var pCrewMembers = CrewRoster().Where(k => crewToDeliver.Contains(k?.name)).ToList(); // Maybe add the initial crew to the vessel: if (pCrewMembers.Any()) { CrewTransferBatch.moveCrew(vessel, pCrewMembers, false); LifeSupportWrapper.Instance.PrepForLaunch(vessel, pCrewMembers, duration); pCrewMembers.ForEach(pcm => { pcm.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; // Add the phases the kerbonaut would have gone through during his launch to his flight-log: var homeBody = Planetarium.fetch.Home; pcm.flightLog.AddEntry(FlightLog.EntryType.Launch, homeBody.bodyName); pcm.flightLog.AddEntry(FlightLog.EntryType.Flight, homeBody.bodyName); pcm.flightLog.AddEntry(FlightLog.EntryType.Suborbit, homeBody.bodyName); pcm.flightLog.AddEntry(FlightLog.EntryType.Orbit, homeBody.bodyName); if (orbit.referenceBody != homeBody) { pcm.flightLog.AddEntry(FlightLog.EntryType.Escape, homeBody.bodyName); pcm.flightLog.AddEntry(FlightLog.EntryType.Orbit, orbit.referenceBody.bodyName); } }); } // TODO this seems like overkill so commenting out, we'll see... vessel.orbitDriver.UpdateOrbit(); vessel.SetOrbit(orbit); vessel.orbitDriver.UpdateOrbit(); var hashCode = (uint)Guid.NewGuid().GetHashCode(); var launchId = HighLogic.CurrentGame.launchID++; foreach (var part in vessel.parts) { part.flightID = ShipConstruction.GetUniqueFlightID(sceneState.flightState); part.missionID = hashCode; part.launchID = launchId; part.flagURL = flagUrl; } if (localRoot.isControlSource == Vessel.ControlLevel.NONE) { var firstCrewablePart = ShipConstruction.findFirstCrewablePart(ship.parts[0]); if (firstCrewablePart == null) { var firstControlSource = ShipConstruction.findFirstControlSource(vessel); firstCrewablePart = firstControlSource ?? localRoot; } vessel.SetReferenceTransform(firstCrewablePart, true); } else { vessel.SetReferenceTransform(localRoot, true); } Debug.Log("Vessel assembled for launch: " + vessel.vesselName); return(vessel); }
void SpawnVessel(VesselData vesselData) { string gameDataDir = KSPUtil.ApplicationRootPath; vesselData.orbit = vessel.GetOrbit(); vesselData.orbit.vel = vessel.orbit.vel; vesselData.orbit.meanAnomalyAtEpoch = vesselData.orbit.meanAnomalyAtEpoch + Math.Atan(UnityEngine.Random.Range(200, 300) / vesselData.orbit.semiMajorAxis); ConfigNode[] partNodes; ShipConstruct shipConstruct = null; float lcHeight = 0; ConfigNode craftNode; ConfigNode currentShip = ShipConstruction.ShipConfig; shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL); float dryCost = 0; float cost = 0; shipConstruct.GetShipCosts(out dryCost, out cost); cost = cost + dryCost; if (cost > Funding.Instance.Funds) { foreach (var p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } ScreenMessages.PostScreenMessage("not enought funds", 5.0f, ScreenMessageStyle.UPPER_CENTER); return; } craftNode = ConfigNode.Load(vesselData.craftURL); lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y; ShipConstruction.ShipConfig = currentShip; vesselData.name = shipConstruct.shipName; uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.missionID = missionID; p.launchID = launchID; p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.temperature = 1.0; } ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; foreach (Part p in shipConstruct.parts) { dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } List <ConfigNode> partNodesL = new List <ConfigNode>(); foreach (var snapShot in dummyProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); ConfigNode[] additionalNodes = new ConfigNode[0]; ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, VesselType.Ship, vesselData.orbit, 0, partNodes, additionalNodes); ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); vesselData.id = protoVessel.vesselRef.id; protoVessel.vesselRef.Load(); Funding.Instance.AddFunds(-cost, TransactionReasons.Vessels); ScreenMessages.PostScreenMessage("vessel buy !", 5.0f, ScreenMessageStyle.UPPER_CENTER); foreach (var p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } }
internal void Spawn() { KD kd = new KD(); Log.Info("Spawning a GeoCache"); // Set additional info for landed if (kd.landed) { Vector3d pos = kd.body.GetWorldSurfacePosition(kd.latitude, kd.longitude, kd.altitude); kd.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, kd.body); kd.orbit.UpdateFromStateVectors(pos, kd.body.getRFrmVel(pos), kd.body, Planetarium.GetUniversalTime()); } else { // Update the reference body in the orbit kd.orbit.referenceBody = kd.body; } uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); kd.craftPart = PartLoader.getPartInfoByName("geocache"); // Create part nodes ConfigNode[] partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode(kd.craftPart.name, flightId, null); // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[0]; // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(VesselName, VesselType.Probe, kd.orbit, 0, partNodes); // Additional seetings for a landed vessel if (kd.landed) { bool splashed = kd.altitude < 0.001 && kd.body.ocean; // Add a bit of height for landed if (!splashed) { kd.altitude += 40.2; Log.Info("Adding 40.2 to altitude"); } //Guid vesselId = vessel.id; // Figure out the appropriate rotation Vector3d norm = kd.body.GetRelSurfaceNVector(kd.latitude, kd.longitude); double terrainHeight = 0.0; if (kd.body.pqsController != null) { terrainHeight = kd.body.pqsController.GetSurfaceHeight(norm) - kd.body.pqsController.radius; } // Create the config node representation of the ProtoVessel protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : Vessel.Situations.LANDED).ToString()); protoVesselNode.SetValue("landed", (!splashed).ToString()); protoVesselNode.SetValue("splashed", splashed.ToString()); protoVesselNode.SetValue("lat", kd.latitude); protoVesselNode.SetValue("lon", kd.longitude); protoVesselNode.SetValue("alt", kd.altitude); protoVesselNode.SetValue("landedAt", kd.body.name); float lowest = float.MaxValue; foreach (Collider collider in kd.craftPart.partPrefab.GetComponentsInChildren <Collider>()) { if (collider.gameObject.layer != 21 && collider.enabled) { lowest = Mathf.Min(lowest, collider.bounds.min.y); } } if (Mathf.Approximately(lowest, float.MaxValue)) { lowest = 0; } float hgt = kd.craftPart.partPrefab.localRoot.attPos0.y - lowest; hgt += 10; protoVesselNode.SetValue("hgt", hgt); // Set the normal vector relative to the surface Quaternion normal = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); Quaternion rotation = Quaternion.identity; rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back); Vector3 nrm = (rotation * Vector3.forward); protoVesselNode.SetValue("prst", false.ToString()); protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z); } ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); //protoVessel.Load(HighLogic.CurrentGame.flightState); protoVessel.vesselName = VesselName; vessel = protoVessel.vesselRef; if (vessel != null) { //var mode = OrbitDriver.UpdateMode.UPDATE; //vessel.orbitDriver.SetOrbitMode(mode); vessel.Load(); launchPoint = vessel.GetWorldPos3D(); // Offset the position by 10m in y and z to have it created away from the current vessel launchPoint.y += 10; launchPoint.z += 10; StartCoroutine("SpawnCoRoutine"); } }
/// <summary> /// Spawn ship construct /// https://github.com/KospY/KAS/blob/master/Plugin/KAS_Shared.cs /// </summary> /// <param name="_shipConstruct">Shipconstruct to spawn</param> /// <param name="_srcPart">Source part to spawn relative to</param> /// <param name="_spawnOffset">Offset spawn from Source part position</param> private void SpawnVessel(ShipConstruct _shipConstruct, Part _srcPart, Vector3 _spawnOffset) { //Store construct root Part _newConstructRootPart = _shipConstruct.parts[0]; //Center rootpart Vector3 offset = _newConstructRootPart.transform.localPosition; _newConstructRootPart.transform.Translate(-offset); //Get launch spawn point, relative to part Transform t = _srcPart.transform; GameObject launchPos = new GameObject(); launchPos.transform.parent = _srcPart.transform; launchPos.transform.position = t.position; launchPos.transform.position += t.TransformDirection(_spawnOffset); launchPos.transform.rotation = t.rotation; //Store our launch / spawn position Transform launchTransform = launchPos.transform; //Kill original object launchPos.DestroyGameObject(); //Set rootpart origin _shipConstruct.Parts[0].localRoot.transform.Translate(launchPos.transform.position, Space.World); //Position float angle; Vector3 axis; //Extract ToAngleAxis data from selected spawning location launchTransform.rotation.ToAngleAxis(out angle, out axis); //TRANSFORM Rotate localRootPart in relation to root _shipConstruct.Parts[0].localRoot.transform.RotateAround(launchTransform.position, axis, angle); //Create vessel object Vessel _newVessel = _newConstructRootPart.localRoot.gameObject.AddComponent <Vessel>(); //Attach vessel information _newVessel.id = Guid.NewGuid(); _newVessel.vesselName = _srcPart.vessel.vesselName + " - " + _shipConstruct.shipName; _newVessel.landedAt = _srcPart.vessel.vesselName; //Store backup ShipConstruction.CreateBackup(_shipConstruct); //Init from VAB _newVessel.Initialize(true); //Set Landed _newVessel.Landed = true; //_newVessel.situation = Vessel.Situations.PRELAUNCH; // _newVessel.GoOffRails(); //_newVessel.IgnoreGForces(240); //Set Orbit InitiateOrbit(launchTransform.position, _srcPart.vessel, _newVessel); //Set Mission info uint missionId = (uint)Guid.NewGuid().GetHashCode(); string flagUrl = _srcPart.flagURL; uint launchId = HighLogic.CurrentGame.launchID++; //Set part mission info for (int i = 0; i < _newVessel.parts.Count; i++) { Part part = _newVessel.parts[i]; part.flightID = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState); part.flagURL = flagUrl; part.launchID = launchId; part.missionID = missionId; } //Generate staging KSP.UI.Screens.StageManager.BeginFlight(); _newConstructRootPart.vessel.ResumeStaging(); KSP.UI.Screens.StageManager.GenerateStagingSequence(_newConstructRootPart.localRoot); KSP.UI.Screens.StageManager.RecalculateVesselStaging(_newConstructRootPart.vessel); //Set position, again _newVessel.SetPosition(launchTransform.position); _newVessel.SetRotation(launchTransform.rotation); //Save Protovessel ProtoVessel _newProto = new ProtoVessel(_newVessel); //Kill and remove spawned vessel, had some serious problems with spawn position warping/glitching _newVessel.Die(); //Set the protovessels position to the relative one we found, maybe redundant _newProto.position = launchPos.transform.position; //If you check this value, you will see the height change from launch scene to resume scene, extra dafuq //float height = _newProto.height; if (FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_FILE || FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_CACHE) { //Odd behaviour with positioning during different flight scenes, workaround awaaaay Log.Info("Workaround of height"); _newProto.height = TrueAlt(launchTransform.position, _srcPart.vessel); } _newProto.altitude += 10; _newProto.height += 10; _newProto.situation = Vessel.Situations.FLYING; //Load Protovessel _newProto.Load(HighLogic.CurrentGame.flightState); // _newVessel.GoOnRails(); // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode(); //Fix Control Lock FlightInputHandler.ResumeVesselCtrlState(FlightGlobals.ActiveVessel); //Fix active vessel staging FlightGlobals.ActiveVessel.ResumeStaging(); }
protected ProtoVessel CreateProtoVessel() { ProtoVessel protoVessel = null; ShipConstruct construct = null; Vessel vessel = null; try { // Backup the ship config from the VAB/SPH, load the selected .craft file // and restore the cached config from the VAB/SPH var constructBak = ShipConstruction.ShipConfig; construct = ShipConstruction.LoadShip(_selectedCraftFilePath); ShipConstruction.ShipConfig = constructBak; // Calculate vessel cost and mass and generate a thumbnail construct.GetShipCosts(out _cachedFundsCost, out _); construct.GetShipMass(out _cachedDryMass, out _); _cachedThumbnail = _thumbnailService.GetThumbnail(construct); // Create an emtpy Vessel and copy the parts from the loaded .craft file vessel = new GameObject().AddComponent <Vessel>(); vessel.parts = construct.parts; // Create an empty ProtoVessel that we'll ultimately use to create the template // for the vessel to be spawned in-game later protoVessel = new ProtoVessel(new ConfigNode(), null) { vesselName = construct.shipName, vesselRef = vessel }; // Setup necessary Vessel and Part parameters for the template (also check for launch clamps) var launchId = HighLogic.CurrentGame.launchID++; var missionId = (uint)Guid.NewGuid().GetHashCode(); var rootPart = construct.parts.First(); _hasLaunchClamp = false; foreach (var part in construct.parts) { _hasLaunchClamp |= part.HasModuleImplementing <LaunchClamp>(); part.flagURL = construct.missionFlag ?? HighLogic.CurrentGame.flagURL; part.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); part.launchID = launchId; part.missionID = missionId; part.temperature = Math.Abs(part.temperature); part.UpdateOrgPosAndRot(rootPart); part.vessel = vessel; var partSnapshot = new ProtoPartSnapshot(part, protoVessel); foreach (var resource in partSnapshot.resources) { if (resource.resourceName != "ElectricCharge") { resource.amount = 0d; } } protoVessel.protoPartSnapshots.Add(partSnapshot); } foreach (var snapshot in protoVessel.protoPartSnapshots) { snapshot.storePartRefs(); } // Cache the ProtoVessel to use as the template for spawning the vessel later _cachedProtoVessel = protoVessel; } catch (Exception ex) { Debug.LogException(ex); } finally { // ShipConstruction.LoadShip seems to load in all the part meshes for the vessel // (presumably for use in the VAB/SPH), so we need to destroy them if (construct != null && construct.parts != null && construct.parts.Count > 0) { foreach (var part in construct.parts) { Destroy(part.gameObject); } } // Destroy the temporary Vessel we created as well if (vessel != null) { Destroy(vessel.gameObject); } } return(protoVessel); }
protected bool CreateVessels() { if (vesselsCreated) { return(false); } String gameDataDir = KSPUtil.ApplicationRootPath; gameDataDir = gameDataDir.Replace("\\", "/"); if (!gameDataDir.EndsWith("/")) { gameDataDir += "/"; } gameDataDir += "GameData"; // Spawn the vessel in the game world foreach (VesselData vesselData in vessels) { LoggingUtil.LogVerbose(this, "Spawning a vessel named '" + vesselData.name + "'"); // Set additional info for landed vessels bool landed = false; if (!vesselData.orbiting) { landed = true; if (vesselData.altitude == null) { vesselData.altitude = LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body); } Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value); vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body); vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime()); } else { vesselData.orbit.referenceBody = vesselData.body; } ConfigNode[] partNodes; UntrackedObjectClass sizeClass; ShipConstruct shipConstruct = null; 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(gameDataDir + "/" + vesselData.craftURL); if (shipConstruct == null) { LoggingUtil.LogError(this, "ShipConstruct was null when tried to load '" + vesselData.craftURL + "' (usually this means the file could not be found)."); continue; } // Restore ShipConstruction ship ShipConstruction.ShipConfig = currentShip; // Set the name if (string.IsNullOrEmpty(vesselData.name)) { vesselData.name = shipConstruct.shipName; } // Set some parameters that need to be at the part level uint 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; } foreach (CrewData cd in vesselData.crew) { bool success = false; // Find a seat for the crew Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity); // Add the crew member if (part != null) { // Create the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); if (cd.gender != null) { crewMember.gender = cd.gender.Value; } if (cd.name != null) { crewMember.name = cd.name; } // Add them to the part success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); } if (!success) { LoggingUtil.LogWarning(this, "Unable to add crew to vessel named '" + vesselData.name + "'. Perhaps there's no room?"); break; } } // 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 partNodes = dummyProto.protoPartSnapshots.Select <ProtoPartSnapshot, ConfigNode>(GetNodeForPart).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.Unowned); if (cd.name != null) { crewMember.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[1]; DiscoveryLevels discoveryLevel = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed vessel if (!vesselData.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 = 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(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 = 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; protoVesselNode.SetValue("hgt", hgt.ToString()); } protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation * normal)); // Set the normal vector relative to the surface Vector3 nrm = (rotation * Vector3.forward); protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z); protoVesselNode.SetValue("prst", false.ToString()); } // Add vessel to the game ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); // Store the id for later use vesselData.id = protoVessel.vesselRef.id; // Associate it so that it can be used in contract parameters ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef); } vesselsCreated = true; return(true); }
public static Vessel AssembleForLaunchUnlanded(ShipConstruct ship, Orbit orbit, string flagURL, Game sceneState) { var localRoot = ship.parts[0].localRoot; var vessel = localRoot.gameObject.GetComponent <Vessel>(); if (vessel == null) { vessel = localRoot.gameObject.AddComponent <Vessel>(); } vessel.id = Guid.NewGuid(); vessel.vesselName = Localizer.Format(ship.shipName); vessel.persistentId = ship.persistentId; if (orbit != null) { var orbitDriver = vessel.gameObject.GetComponent <OrbitDriver>(); if (orbitDriver == null) { orbitDriver = vessel.gameObject.AddComponent <OrbitDriver>(); } orbitDriver.orbit = orbit; } vessel.Initialize(true); vessel.orbitDriver.updateMode = OrbitDriver.UpdateMode.TRACK_Phys; vessel.skipGroundPositioning = true; vessel.vesselSpawning = false; vessel.Landed = false; var hashCode = (uint)Guid.NewGuid().GetHashCode(); var launchID = HighLogic.CurrentGame.launchID++; for (int i = 0, count = vessel.parts.Count; i < count; ++i) { var p = vessel.parts[i]; p.flightID = ShipConstruction.GetUniqueFlightID(sceneState.flightState); p.missionID = hashCode; p.launchID = launchID; p.flagURL = flagURL; } if (localRoot.isControlSource == Vessel.ControlLevel.NONE) { var firstCrewablePart = ShipConstruction.findFirstCrewablePart(ship.parts[0]); if (firstCrewablePart == null) { var firstControlSource = ShipConstruction.findFirstControlSource(vessel); if (firstControlSource == null) { firstCrewablePart = localRoot; } else { firstCrewablePart = firstControlSource; } } vessel.SetReferenceTransform(firstCrewablePart, true); } else { vessel.SetReferenceTransform(localRoot, true); } Utils.Log("Vessel assembled for launch: " + vessel.GetDisplayName()); return(vessel); }
protected override void OnAccepted() { // Actually spawn the kerbals in the game world! foreach (KerbalData kd in kerbals) { LoggingUtil.LogVerbose(this, "Spawning a Kerbal named " + kd.kerbal.name); // Generate the ProtoCrewMember kd.kerbal.GenerateKerbal(); if (kd.altitude == null) { kd.altitude = LocationUtil.TerrainHeight(kd.latitude, kd.longitude, kd.body); } // Set additional info for landed kerbals if (kd.landed) { Vector3d pos = kd.body.GetWorldSurfacePosition(kd.latitude, kd.longitude, kd.altitude.Value); kd.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, kd.body); kd.orbit.UpdateFromStateVectors(pos, kd.body.getRFrmVel(pos), kd.body, Planetarium.GetUniversalTime()); LoggingUtil.LogVerbose(typeof(SpawnKerbal), "kerbal generated, orbit = " + kd.orbit); } else { // Update the reference body in the orbit kd.orbit.referenceBody = kd.body; } uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); // Create crew member array ProtoCrewMember[] crewArray = new ProtoCrewMember[1]; crewArray[0] = kd.kerbal.pcm; // Create part nodes ConfigNode[] partNodes = new ConfigNode[1]; partNodes[0] = ProtoVessel.CreatePartNode(kd.kerbal.gender == ProtoCrewMember.Gender.Male ? "kerbalEVA" : "kerbalEVAfemale", flightId, crewArray); // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[1]; DiscoveryLevels discoveryLevel = kd.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, UntrackedObjectClass.A, contract.TimeDeadline, contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(kd.kerbal.name, VesselType.EVA, kd.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed Kerbal if (kd.landed) { bool splashed = kd.altitude.Value < 0.001 && kd.body.ocean; // Add a bit of height for landed kerbals if (!splashed) { kd.altitude += 0.2; } // Figure out the appropriate rotation Vector3d norm = kd.body.GetRelSurfaceNVector(kd.latitude, kd.longitude); Quaternion normal = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z)); Quaternion rotation = Quaternion.FromToRotation(Vector3.up, Vector3.forward); rotation = rotation * Quaternion.AngleAxis(kd.heading + 180, Vector3.up); // Create the config node representation of the ProtoVessel protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : Vessel.Situations.LANDED).ToString()); protoVesselNode.SetValue("landed", (!splashed).ToString()); protoVesselNode.SetValue("splashed", splashed.ToString()); protoVesselNode.SetValue("lat", kd.latitude.ToString()); protoVesselNode.SetValue("lon", kd.longitude.ToString()); protoVesselNode.SetValue("alt", kd.altitude.ToString()); protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation)); // Set the normal vector relative to the surface Vector3 nrm = (rotation * Vector3.forward); protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z); } // Add vessel to the game HighLogic.CurrentGame.AddVessel(protoVesselNode); } }
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); } } }
public static Part CreatePart(ConfigNode partConfig, Vector3 position, Quaternion rotation, Part fromPart, Part coupleToPart = null, string srcAttachNodeID = null, AttachNode tgtAttachNode = null, OnPartCoupled onPartCoupled = null) { var node_copy = new ConfigNode(); partConfig.CopyTo(node_copy); var snapshot = new ProtoPartSnapshot(node_copy, null, HighLogic.CurrentGame); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) || snapshot.flightID == 0) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.connected = true; snapshot.flagURL = fromPart.flagURL; Part newPart = snapshot.Load(fromPart.vessel, false); newPart.transform.position = position; newPart.transform.rotation = rotation; newPart.missionID = fromPart.missionID; fromPart.vessel.Parts.Add(newPart); newPart.physicalSignificance = Part.PhysicalSignificance.NONE; newPart.PromoteToPhysicalPart(); newPart.Unpack(); newPart.InitializeModules(); if (coupleToPart) { newPart.Rigidbody.velocity = coupleToPart.Rigidbody.velocity; newPart.Rigidbody.angularVelocity = coupleToPart.Rigidbody.angularVelocity; } else { if (fromPart.Rigidbody) { newPart.Rigidbody.velocity = fromPart.Rigidbody.velocity; newPart.Rigidbody.angularVelocity = fromPart.Rigidbody.angularVelocity; } else { // If fromPart is a carried container newPart.Rigidbody.velocity = fromPart.vessel.rootPart.Rigidbody.velocity; newPart.Rigidbody.angularVelocity = fromPart.vessel.rootPart.Rigidbody.angularVelocity; } } // New part by default is coupled with the active vessel. newPart.decouple(); if (coupleToPart) { newPart.StartCoroutine(WaitAndCouple(newPart, coupleToPart, srcAttachNodeID, tgtAttachNode, onPartCoupled)); } else { RenameAssemblyVessel(newPart); } return(newPart); }
/// <summary>Creates a new part from the config.</summary> /// <param name="partConfig">Config to read part from.</param> /// <param name="position">Initial position of the new part.</param> /// <param name="rotation">Initial rotation of the new part.</param> /// <param name="fromPart"></param> /// <param name="coupleToPart">Optional. Part to couple new part to.</param> /// <param name="srcAttachNodeId"> /// Optional. Attach node ID on the new part to use for coupling. It's required if coupling to /// part is requested. /// </param> /// <param name="tgtAttachNode"> /// Optional. Attach node on the target part to use for coupling. It's required if /// <paramref name="srcAttachNodeId"/> specifies a stack node. /// </param> /// <param name="onPartReady"> /// Callback to call when new part is fully operational and its joint is created (if any). It's /// undetermined how long it may take before the callback is called. The calling code must expect /// that there will be several frame updates and at least one fixed frame update. /// </param> /// <param name="createPhysicsless"> /// Tells if new part must be created without rigidbody and joint. It's only used to create /// equippable parts. Any other use-case is highly unlikely. /// </param> /// <returns></returns> public static Part CreatePart( ConfigNode partConfig, Vector3 position, Quaternion rotation, Part fromPart, Part coupleToPart = null, string srcAttachNodeId = null, AttachNode tgtAttachNode = null, OnPartReady onPartReady = null, bool createPhysicsless = false) { // Sanity checks for the parameters. if (coupleToPart != null) { if (srcAttachNodeId == null || srcAttachNodeId == "srfAttach" && tgtAttachNode != null || srcAttachNodeId != "srfAttach" && (tgtAttachNode == null || tgtAttachNode.id == "srfAttach")) { // Best we can do is falling back to surface attach. srcAttachNodeId = "srfAttach"; tgtAttachNode = null; } } var refVessel = coupleToPart != null ? coupleToPart.vessel : fromPart.vessel; var partNodeCopy = new ConfigNode(); partConfig.CopyTo(partNodeCopy); var snapshot = new ProtoPartSnapshot(partNodeCopy, refVessel.protoVessel, HighLogic.CurrentGame); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) || snapshot.flightID == 0) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = coupleToPart != null?refVessel.parts.IndexOf(coupleToPart) : 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = srcAttachNodeId == "srfAttach" ? (int)AttachModes.SRF_ATTACH : (int)AttachModes.STACK; snapshot.attached = true; snapshot.flagURL = fromPart.flagURL; var newPart = snapshot.Load(refVessel, false); refVessel.Parts.Add(newPart); newPart.transform.position = position; newPart.transform.rotation = rotation; newPart.missionID = fromPart.missionID; newPart.UpdateOrgPosAndRot(newPart.vessel.rootPart); if (coupleToPart != null) { // Wait for part to initialize and then fire ready event. Debug.Log("[ModuleMissileRearm]: Ready to error" + newPart + srcAttachNodeId + tgtAttachNode); newPart.StartCoroutine( WaitAndCouple(newPart, srcAttachNodeId, tgtAttachNode, onPartReady, createPhysicsless: createPhysicsless)); } else { // Create new part as a separate vessel. newPart.StartCoroutine(WaitAndMakeLonePart(newPart, onPartReady)); } return(newPart); }
private void SpawnVessel(WaldoAttackVesselData WaldoAttackVesselData, List <ProtoCrewMember> crewData = null) { // string gameDataDir = KSPUtil.ApplicationRootPath; Debug.Log("[Spawn OrX Waldo Attack] Spawning " + WaldoAttackVesselData.name); // Set additional info for landed vessels bool landed = false; if (!landed) { landed = true; if (WaldoAttackVesselData.altitude == null || WaldoAttackVesselData.altitude < 0) { WaldoAttackVesselData.altitude = 5;//LocationUtil.TerrainHeight(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude, WaldoAttackVesselData.body); } Debug.Log("[Spawn OrX Waldo Attack] SpawnVessel Altitude: " + WaldoAttackVesselData.altitude); //Vector3d pos = WaldoAttackVesselData.body.GetWorldSurfacePosition(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude, WaldoAttackVesselData.altitude.Value); Vector3d pos = WaldoAttackVesselData.body.GetRelSurfacePosition(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude, WaldoAttackVesselData.altitude.Value); WaldoAttackVesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, WaldoAttackVesselData.body); WaldoAttackVesselData.orbit.UpdateFromStateVectors(pos, WaldoAttackVesselData.body.getRFrmVel(pos), WaldoAttackVesselData.body, Planetarium.GetUniversalTime()); } ConfigNode[] partNodes; ShipConstruct shipConstruct = null; bool hasClamp = false; float lcHeight = 0; ConfigNode craftNode; Quaternion craftRotation = Quaternion.identity; if (!string.IsNullOrEmpty(WaldoAttackVesselData.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(WaldoAttackVesselData.craftURL); if (shipConstruct == null) { Debug.Log("[Spawn OrX Waldo Attack] ShipConstruct was null when tried to load '" + WaldoAttackVesselData.craftURL + "' (usually this means the file could not be found)."); return;//continue; } craftNode = ConfigNode.Load(WaldoAttackVesselData.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(WaldoAttackVesselData.name)) { WaldoAttackVesselData.name = WaldoVesselName; ; } // 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[WaldoAttackVesselData.crew.Count]; /* * int i = 0; * foreach (CrewData cd in WaldoAttackVesselData.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(WaldoAttackVesselData.craftPart.name, flightId, crewArray); // Default the size class //sizeClass = UntrackedObjectClass.A; // Set the name if (string.IsNullOrEmpty(WaldoAttackVesselData.name)) { WaldoAttackVesselData.name = WaldoAttackVesselData.craftPart.name; } } // Create additional nodes ConfigNode[] additionalNodes = new ConfigNode[0]; //DiscoveryLevels discoveryLevel = WaldoAttackVesselData.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(WaldoAttackVesselData.name, WaldoAttackVesselData.vesselType, WaldoAttackVesselData.orbit, 0, partNodes, additionalNodes); // Additional seetings for a landed vessel if (!WaldoAttackVesselData.orbiting) { Vector3d norm = WaldoAttackVesselData.body.GetRelSurfaceNVector(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude); double terrainHeight = 0.0; if (WaldoAttackVesselData.body.pqsController != null) { terrainHeight = WaldoAttackVesselData.body.pqsController.GetSurfaceHeight(norm) - WaldoAttackVesselData.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", WaldoAttackVesselData.latitude.ToString()); protoVesselNode.SetValue("lon", WaldoAttackVesselData.longitude.ToString()); protoVesselNode.SetValue("alt", WaldoAttackVesselData.altitude.ToString()); protoVesselNode.SetValue("landedAt", WaldoAttackVesselData.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 WaldoAttackVesselData.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 = WaldoAttackVesselData.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; WaldoAttackVesselData.heading = 0; WaldoAttackVesselData.pitch = 0; } rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back); rotation = rotation * Quaternion.AngleAxis(WaldoAttackVesselData.roll, Vector3.down); rotation = rotation * Quaternion.AngleAxis(WaldoAttackVesselData.pitch, Vector3.left); // Set the height and rotation if (landed || splashed) { float hgt = (shipConstruct != null ? shipConstruct.parts[0] : WaldoAttackVesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest; hgt += WaldoAttackVesselData.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 WaldoAttackVesselData.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(WaldoAttackVesselData.name, protoVessel.vesselRef); //destroy prefabs foreach (Part p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } }
public static Vessel SpawnVessel(string name, string craftURL, string flagURL, VesselType vesselType, CelestialBody body, Orbit orbit, List <ProtoCrewMember> crewList) { string gameDataDir = KSPUtil.ApplicationRootPath; ConfigNode[] partNodes; ShipConstruct shipConstruct = null; float lcHeight = 0; ConfigNode craftNode; ConfigNode currentShip = ShipConstruction.ShipConfig; shipConstruct = ShipConstruction.LoadShip(craftURL); craftNode = ConfigNode.Load(craftURL); lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y; ShipConstruction.ShipConfig = currentShip; foreach (ProtoCrewMember crew in crewList) { Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity); if (part != null) { part.AddCrewmemberAt(crew, part.protoModuleCrew.Count); } } ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = shipConstruct.parts; dummyProto.vesselRef = dummyVessel; uint missionID = (uint)Guid.NewGuid().GetHashCode(); uint launchID = HighLogic.CurrentGame.launchID++; foreach (Part p in shipConstruct.parts) { p.missionID = missionID; p.launchID = launchID; p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); p.temperature = 1.0; dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto)); } foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots) { p.storePartRefs(); } List <ConfigNode> partNodesL = new List <ConfigNode>(); foreach (var snapShot in dummyProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); ConfigNode[] additionalNodes = new ConfigNode[0]; ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(name, VesselType.Ship, orbit, 0, partNodes, additionalNodes); ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode); foreach (var p in UnityEngine.Object.FindObjectsOfType <Part>()) { if (!p.vessel) { UnityEngine.Object.Destroy(p.gameObject); } } return(protoVessel.vesselRef); }