public static HashSet<ProtoPartResourceSnapshot> AddResource(VesselData data, float amount, string name, HashSet<ProtoPartResourceSnapshot> modified) { BackgroundProcessing.Debug("AddResource called, adding " + amount + " " + name, DebugLevel.ALL); if (!data.storage.ContainsKey(name)) { return modified; } bool reduce = amount < 0; List<ProtoPartResourceSnapshot> relevantStorage = data.storage[name]; for (int i = 0; i < relevantStorage.Count; ++i) { ProtoPartResourceSnapshot r = relevantStorage[i]; if (amount == 0) { break; } float n; float m; if ( float.TryParse(r.resourceValues.GetValue("amount"), out n) && float.TryParse(r.resourceValues.GetValue("maxAmount"), out m) ) { n += amount; amount = 0; if (reduce) { if (n < 0 && i < relevantStorage.Count - 1) { amount = n; n = 0; } } else { if (n > m && i < relevantStorage.Count - 1) { amount = n - m; n = m; } } r.resourceValues.SetValue("amount", n.ToString()); } modified.Add(r); } return modified; }
public VesselData(VesselData vd) { name = vd.name; id = vd.id; craftURL = vd.craftURL; craftPart = vd.craftPart; flagURL = vd.flagURL; vesselType = vd.vesselType; body = vd.body; orbit = vd.orbit; latitude = vd.latitude; longitude = vd.longitude; altitude = vd.altitude; height = vd.height; orbiting = vd.orbiting; owned = vd.owned; pqsCity = vd.pqsCity; pqsOffset = vd.pqsOffset; heading = vd.heading; pitch = vd.pitch; roll = vd.roll; foreach (CrewData cd in vd.crew) { crew.Add(new CrewData(cd)); } }
public void init() { Console.WriteLine ("UDPSend init()."); ip = "127.0.0.1"; port = 8051; endPoint = new IPEndPoint (IPAddress.Parse (ip), port); client = new UdpClient (); this.VData = new VesselData (); Console.WriteLine ("sending to " + ip + " : " + port); }
private VesselData GetVesselData(Vessel vessel) { Guid id = vessel.id; VesselData data; if (!vesselData.ContainsKey(id)) { data = new VesselData(); vesselData.Add(id, data); } else { data = vesselData[id]; } return data; }
private void SpawnVessel(VesselData VesselData, List <ProtoCrewMember> crewData = null) { // string gameDataDir = KSPUtil.ApplicationRootPath; // Set additional info for landed vessels bool landed = false; if (!landed) { landed = true; if (VesselData.altitude == null || VesselData.altitude < 0) { VesselData.altitude = SpawnCoords.z; //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()); } ConfigNode[] partNodes; 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) { 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 = ""; ; } // 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 Blank 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 BlankProto = new ProtoVessel(empty, null); Vessel BlankVessel = new Vessel(); BlankVessel.parts = shipConstruct.parts; BlankProto.vesselRef = BlankVessel; // Create the ProtoPartSnapshot objects and then initialize them foreach (Part p in shipConstruct.parts) { BlankProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, BlankProto)); } foreach (ProtoPartSnapshot p in BlankProto.protoPartSnapshots) { p.storePartRefs(); } // Create the ship's parts List <ConfigNode> partNodesL = new List <ConfigNode>(); foreach (ProtoPartSnapshot snapShot in BlankProto.protoPartSnapshots) { ConfigNode node = new ConfigNode("PART"); snapShot.Save(node); partNodesL.Add(node); } partNodes = partNodesL.ToArray(); } 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 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", 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; rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back); 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(), 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.isPersistent = true; protoVessel.vesselRef.Landed = false; protoVessel.vesselRef.situation = Vessel.Situations.FLYING; protoVessel.vesselRef.GoOffRails(); StageManager.BeginFlight(); //StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp)); //destroy prefabs foreach (Part p in FindObjectsOfType <Part>()) { if (!p.vessel) { Destroy(p.gameObject); } } }
/// <summary> /// Plane normal vector from a given heading (surface right vector) /// </summary> public static Vector3 vecHeading(double target, VesselData vdata) { double angleDiff = target - vdata.heading; return Quaternion.AngleAxis((float)(angleDiff + 90), (Vector3)vdata.planetUp) * vdata.surfVesForward; }
/// <summary> /// calculate current heading from plane rotation /// </summary> public static double calculateTargetHeading(Quaternion rotation, Vessel vessel, VesselData vdata) { Vector3 fwd = Vector3.Cross(getPlaneNormal(rotation, vessel), vdata.planetUp); double heading = Vector3.Angle(fwd, vdata.planetNorth) * Math.Sign(Vector3.Dot(fwd, vdata.planetEast)); return heading.headingClamp(360); }
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 SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory) { SpawnVessel spawnVessel = new SpawnVessel(); ConfigNodeUtil.ParseValue <bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL")) { DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); VesselData vessel = new VesselData(); // Get name if (child.HasValue("name")) { valid &= ConfigNodeUtil.ParseValue <string>(child, "name", x => vessel.name = x, factory); } // Get craft details if (child.HasValue("craftURL")) { valid &= ConfigNodeUtil.ParseValue <string>(child, "craftURL", x => vessel.craftURL = x, factory); } if (child.HasValue("craftPart")) { valid &= ConfigNodeUtil.ParseValue <AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory); } valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory); valid &= ConfigNodeUtil.ParseValue <string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue <VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue <CelestialBody>(child, "targetBody", x => vessel.body = x, factory); // Get landed stuff if (child.HasValue("pqsCity")) { string pqsCityStr = null; valid &= ConfigNodeUtil.ParseValue <string>(child, "pqsCity", x => pqsCityStr = x, factory); if (pqsCityStr != null) { try { vessel.pqsCity = vessel.body.GetComponentsInChildren <PQSCity>(true).Where(pqs => pqs.name == pqsCityStr).First(); } catch (Exception e) { LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCityStr + "'"); LoggingUtil.LogException(e); valid = false; } } valid &= ConfigNodeUtil.ParseValue <Vector3d>(child, "pqsOffset", x => vessel.pqsOffset = x, factory, new Vector3d()); // Don't expect these to load anything, but do it to mark as initialized valid &= ConfigNodeUtil.ParseValue <double>(child, "lat", x => vessel.latitude = x, factory, 0.0); valid &= ConfigNodeUtil.ParseValue <double>(child, "lon", x => vessel.longitude = x, factory, 0.0); // Do load alt and height valid &= ConfigNodeUtil.ParseValue <double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue <float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; } else if (child.HasValue("lat") && child.HasValue("lon")) { valid &= ConfigNodeUtil.ParseValue <double>(child, "lat", x => vessel.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue <double>(child, "lon", x => vessel.longitude = x, factory); valid &= ConfigNodeUtil.ParseValue <double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue <float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; } // Get orbit else { valid &= ConfigNodeUtil.ParseValue <Orbit>(child, "ORBIT", x => vessel.orbit = x, factory); vessel.orbiting = true; } valid &= ConfigNodeUtil.ParseValue <float>(child, "heading", x => vessel.heading = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue <float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue <float>(child, "roll", x => vessel.roll = x, factory, 0.0f); // Get additional flags valid &= ConfigNodeUtil.ParseValue <bool>(child, "owned", x => vessel.owned = x, factory, false); // Handle the CREW nodes foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW")) { int count = 1; valid &= ConfigNodeUtil.ParseValue <int>(crewNode, "count", x => count = x, factory, 1); for (int i = 0; i < count; i++) { CrewData cd = new CrewData(); // Read crew details valid &= ConfigNodeUtil.ParseValue <string>(crewNode, "name", x => cd.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue <bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory); // Add the record vessel.crew.Add(cd); } } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list spawnVessel.vessels.Add(vessel); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } if (!configNode.HasNode("VESSEL")) { valid = false; LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node."); } return(valid ? spawnVessel : null); }
void SpawnVesselFromCraftFile(string craftURL, Vector3d gpsCoords, float heading, float pitch) { VesselData newData = new VesselData(); newData.craftURL = craftURL; newData.latitude = gpsCoords.x; newData.longitude = gpsCoords.y; newData.altitude = gpsCoords.z+35; newData.body = FlightGlobals.currentMainBody; newData.heading = heading; newData.pitch = pitch; newData.orbiting = false; newData.flagURL = HighLogic.CurrentGame.flagURL; newData.owned = true; newData.vesselType = VesselType.Ship; newData.crew = new List<CrewData>(); SpawnVessel(newData); }
public RisksTabPage WaitForAddedVesselDisplayed(VesselData data) { this.WebDriverWrapper.Wait.Until(x => this.WebDriverWrapper.FindElementsByXPath($"//span[@title='VesselName'and text()='{data.VesselName}']").Any()); return(this); }
public static void Config(this Panel p, Vessel v) { // avoid corner-case when this is called in a lambda after scene changes v = FlightGlobals.FindVessel(v.id); // if vessel doesn't exist anymore, leave the panel empty if (v == null) { return; } // get info from the cache Vessel_Info vi = Cache.VesselInfo(v); // if not a valid vessel, leave the panel empty if (!vi.is_valid) { return; } // set metadata p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 20), " <color=#cccccc>VESSEL CONFIG</color>")); // time-out simulation if (p.Timeout(vi)) { return; } // get data from db VesselData vd = DB.Vessel(v); // toggle rendering string tooltip; if (Features.Signal || Features.Reliability) { p.SetSection("RENDERING"); } if (Features.Signal) { tooltip = "Render the connection line\nin mapview and tracking station"; p.SetContent("show links", string.Empty, tooltip); p.SetIcon(vd.cfg_showlink ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_showlink)); } if (Features.Reliability) { tooltip = "Highlight failed components"; p.SetContent("highlight malfunctions", string.Empty, tooltip); p.SetIcon(vd.cfg_highlights ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_highlights)); } // toggle messages p.SetSection("MESSAGES"); tooltip = "Receive a message when\nElectricCharge level is low"; p.SetContent("battery", string.Empty, tooltip); p.SetIcon(vd.cfg_ec ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_ec)); if (Features.Supplies) { tooltip = "Receive a message when\nsupply resources level is low"; p.SetContent("supply", string.Empty, tooltip); p.SetIcon(vd.cfg_supply ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_supply)); } if (Features.Signal || Features.KCommNet) { tooltip = "Receive a message when signal is lost or obtained"; p.SetContent("signal", string.Empty, tooltip); p.SetIcon(vd.cfg_signal ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_signal)); } if (Features.Reliability) { tooltip = "Receive a message\nwhen a component fail"; p.SetContent("reliability", string.Empty, tooltip); p.SetIcon(vd.cfg_malfunction ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_malfunction)); } if (Features.SpaceWeather) { tooltip = "Receive a message\nduring CME events"; p.SetContent("storm", string.Empty, tooltip); p.SetIcon(vd.cfg_storm ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_storm)); } if (Features.Automation) { tooltip = "Receive a message when\nscripts are executed"; p.SetContent("script", string.Empty, tooltip); p.SetIcon(vd.cfg_script ? Icons.toggle_green : Icons.toggle_red, tooltip, () => p.Toggle(ref vd.cfg_script)); } }
void SpawnVessel(VesselData vesselData) { string gameDataDir = KSPUtil.ApplicationRootPath; Debug.Log("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;//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; 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) { Debug.Log("ShipConstruct was null when tried to load '" + vesselData.craftURL + "' (usually this means the file could not be found)."); 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) { // Create the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned); crewMember.gender = UnityEngine.Random.Range(0,100) > 50 ? ProtoCrewMember.Gender.Female : ProtoCrewMember.Gender.Male; /* if (cd.name != null) { crewMember.name = cd.name; } */ // Add them to the part success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); } } /* 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) { Debug.Log("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 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(); // 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[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(var 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(var p in FindObjectsOfType<Part>()) { if(!p.vessel) { Destroy(p.gameObject); } } }
public void showVesselTrackingInfo() { trackingInfoScroll = GUILayout.BeginScrollView(trackingInfoScroll); GUILayout.BeginVertical(); if (selectedVesselData != null) { if (selectedVesselData.vessel != null) { /* Vessel Info: */ GUILayout.Label(selectedVesselData.vessel.name + ":", UIStyle.headingLabelStyle); GUILayout.Space(UIStyle.separatorSpacing); /* Basic info */ GUILayout.Label("Basic Information:", UIStyle.headingLabelStyle); if (selectedVesselData.vessel.loaded) { GUILayout.Label("Mass: " + Math.Round(selectedVesselData.vessel.totalMass, 5).ToString() + " tons"); GUILayout.Label("Crew: " + selectedVesselData.vessel.GetCrewCount().ToString()); if (selectedVesselData.currentLocation != null) { GUILayout.Label("Current Location: " + selectedVesselData.currentLocation.name); } else { GUILayout.Label("Current Location: " + selectedVesselData.vessel.GetOrbit().referenceBody.name + " (not at supply point)"); } } else { GUILayout.Label( "Mass: " + selectedVesselData.vessel.protoVessel.protoPartSnapshots.Sum((ProtoPartSnapshot ps) => { return(ps.mass); }).ToString() ); GUILayout.Label( "Crew: " + selectedVesselData.vessel.protoVessel.protoPartSnapshots.Sum((ProtoPartSnapshot ps) => { return(ps.protoModuleCrew.Count); }).ToString() ); if (selectedVesselData.currentLocation != null) { GUILayout.Label("Current Location: " + selectedVesselData.currentLocation.name); } else { GUILayout.Label( "Current Location: " + FlightGlobals.Bodies[selectedVesselData.vessel.protoVessel.orbitSnapShot.ReferenceBodyIndex].name + " (not at supply point)" ); } } /* Vessel Resources */ Dictionary <int, double> currentResourceCounts; Dictionary <int, double> maxResourceCounts; GUILayout.Space(UIStyle.separatorSpacing); GUILayout.Label("Vessel Resources:", UIStyle.headingLabelStyle); selectedVesselData.getAllResourceCounts(out currentResourceCounts, out maxResourceCounts); foreach (int rscID in maxResourceCounts.Keys) { GUILayout.Label( PartResourceLibrary.Instance.GetDefinition(rscID).name + ": " + currentResourceCounts[rscID].ToString() + " / " + maxResourceCounts[rscID].ToString() ); } GUILayout.Space(UIStyle.separatorSpacing); /* Vessel Capabilities: */ GUILayout.Label("Vessel Capabilities:", UIStyle.headingLabelStyle); if (selectedVesselData.orbitalDockingEnabled) { GUILayout.Label("Orbital Resource Transfer Enabled", UIStyle.passableLabelStyle); } else { GUILayout.Label("Orbital Resource Transfer Disabled", UIStyle.impassableLabelStyle); } GUILayout.Space(UIStyle.separatorSpacing); /* Vessel Supply Links */ GUILayout.Label("Vessel Supply Links:", UIStyle.headingLabelStyle); foreach (SupplyLink l in selectedVesselData.links) { SupplyLinkStatus.drawStatusLabel(l); } } else { GUILayout.Label("Unknown vessel selected."); } if (GUILayout.Button("Back")) { selectedVesselData = null; } } else { foreach (VesselData vd in SupplyChainController.instance.trackedVessels) { if (vd.vessel != null) { if (GUILayout.Button( vd.vessel.name + " (MET T+" + UIStyle.formatTimespan(Math.Round(vd.vessel.missionTime), true).ToString() + ")" )) { selectedVesselData = vd; trackingInfoScroll = new Vector2(); } } } } GUILayout.EndVertical(); GUILayout.EndScrollView(); }
public abstract HashSet<ProtoPartResourceSnapshot> HandleResource(Vessel v, VesselData data, HashSet<ProtoPartResourceSnapshot> modified);
public static void SpawnAsteroid(Vessel asteroidCopy) { VesselData vesselData = new VesselData(); vesselData.body = FlightGlobals.currentMainBody; vesselData.orbiting = true; vesselData.flagURL = HighLogic.CurrentGame.flagURL; vesselData.owned = true; vesselData.vesselType = VesselType.SpaceObject; string gameDataDir = KSPUtil.ApplicationRootPath; 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; ConfigNode currentShip = ShipConstruction.ShipConfig; ShipConstruction.ShipConfig = currentShip; int i = 1; foreach (Vessel v in FlightGlobals.Vessels) { if (v.vesselType == VesselType.Unknown || v.vesselType == VesselType.SpaceObject) { i++; } } vesselData.name = "asteroid #" + i; ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new Vessel(); dummyVessel.parts = asteroidCopy.Parts; dummyProto.vesselRef = dummyVessel; foreach (Part p in asteroidCopy.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, 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); } } }
public override HashSet <ProtoPartResourceSnapshot> HandleResource(Vessel v, VesselData data, HashSet <ProtoPartResourceSnapshot> modified) { BackgroundProcessing.Debug("Panel data, doing solar panel calcs", DebugLevel.ALL); Vector3d sun_dir; double sun_dist; bool in_sunlight = SolarPanel.RaytraceBody(v, FlightGlobals.Bodies[0], out sun_dir, out sun_dist); Vector3d partPos = VesselPosition(v) + position; double orientationFactor = 1; if (tracks) { Vector3d localPivot = (v.transform.rotation * orientation * pivotAxis).normalized; orientationFactor = Math.Cos(Math.PI / 2.0 - Math.Acos(Vector3d.Dot(localPivot, sun_dir))); } else { Vector3d localSolarNormal = (v.transform.rotation * orientation * solarNormal).normalized; orientationFactor = Vector3d.Dot(localSolarNormal, sun_dir); } orientationFactor = Math.Max(orientationFactor, 0); if (in_sunlight) { double solarFlux = SolarPanel.SolarLuminosity / (12.566370614359172 * sun_dist * sun_dist); BackgroundProcessing.Debug("Pre-atmosphere flux: " + solarFlux + ", pre-atmosphere distance: " + sun_dist + ", solar luminosity: " + PhysicsGlobals.SolarLuminosity, DebugLevel.ALL); double staticPressure = v.mainBody.GetPressure(v.altitude); BackgroundProcessing.Debug("Static pressure: " + staticPressure, DebugLevel.ALL); if (staticPressure > 0.0) { double density = v.mainBody.GetDensity(staticPressure, temperature); BackgroundProcessing.Debug("density: " + density, DebugLevel.ALL); Vector3 up = FlightGlobals.getUpAxis(v.mainBody, v.vesselTransform.position).normalized; double sunPower = v.mainBody.radiusAtmoFactor * Vector3d.Dot(up, sun_dir); double sMult = v.mainBody.GetSolarPowerFactor(density); if (sunPower < 0) { sMult /= Math.Sqrt(2.0 * v.mainBody.radiusAtmoFactor + 1.0); } else { sMult /= Math.Sqrt(sunPower * sunPower + 2.0 * v.mainBody.radiusAtmoFactor + 1.0) - sunPower; } BackgroundProcessing.Debug("Atmospheric flux adjustment: " + sMult, DebugLevel.ALL); solarFlux *= sMult; BackgroundProcessing.Debug("Vessel solar flux: " + v.solarFlux, DebugLevel.ALL); } else { BackgroundProcessing.Debug("No need for atmospheric adjustment", DebugLevel.ALL); } float multiplier = 1; if (usesCurve) { multiplier = powerCurve.Evaluate((float)FlightGlobals.Bodies[0].GetAltitude(partPos)); } else { multiplier = (float)(solarFlux / PhysicsGlobals.SolarLuminosityAtHome); } BackgroundProcessing.Debug("Resource rate: " + chargeRate, DebugLevel.ALL); BackgroundProcessing.Debug("Vessel " + v.vesselName + " solar panel, orientation factor: " + orientationFactor + ", temperature: " + temperature + " solar flux: " + solarFlux, DebugLevel.ALL); float tempFactor = tempCurve.Evaluate(temperature); if (!BackgroundProcessing.config.solarOrientationMatters) { orientationFactor = 1; BackgroundProcessing.Debug("Orientation disabled in config file", DebugLevel.ALL); } if (!BackgroundProcessing.config.solarTemperatureMatters) { tempFactor = 1; BackgroundProcessing.Debug("Temperature disabled in config file", DebugLevel.ALL); } float resourceAmount = chargeRate * (float)orientationFactor * tempFactor * multiplier; BackgroundProcessing.Debug("Vessel " + v.vesselName + ", adding " + resourceAmount + " " + resourceName + " over time " + TimeWarp.fixedDeltaTime, DebugLevel.ALL); modified = AddResource(data, resourceAmount * TimeWarp.fixedDeltaTime, resourceName, modified); } else { BackgroundProcessing.Debug("Can't see Kerbol", DebugLevel.ALL); } return(modified); }
public static SpawnVessel Create(ConfigNode configNode, CelestialBody defaultBody, SpawnVesselFactory factory) { SpawnVessel spawnVessel = new SpawnVessel(); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL")) { DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); VesselData vessel = new VesselData(); // Get name if (child.HasValue("name")) { vessel.name = child.GetValue("name"); } // Get paths vessel.craftURL = ConfigNodeUtil.ParseValue <string>(child, "craftURL"); vessel.flagURL = ConfigNodeUtil.ParseValue <string>(child, "flagURL", (string)null); vessel.vesselType = ConfigNodeUtil.ParseValue <VesselType>(child, "vesselType", VesselType.Ship); // Get celestial body valid &= ConfigNodeUtil.ParseValue <CelestialBody>(child, "targetBody", x => vessel.body = x, factory, defaultBody, Validation.NotNull); // Get landed stuff if (child.HasValue("lat") && child.HasValue("lon")) { valid &= ConfigNodeUtil.ParseValue <double>(child, "lat", x => vessel.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue <double>(child, "lon", x => vessel.longitude = x, factory); valid &= ConfigNodeUtil.ParseValue <double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); vessel.landed = true; } // Get orbit else { valid &= ConfigNodeUtil.ValidateMandatoryChild(child, "ORBIT", factory); vessel.orbit = new OrbitSnapshot(ConfigNodeUtil.GetChildNode(child, "ORBIT")).Load(); vessel.orbit.referenceBody = vessel.body; } // Get additional flags valid &= ConfigNodeUtil.ParseValue <bool>(child, "owned", x => vessel.owned = x, factory, false); // Handle the CREW nodes foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW")) { int count = 1; valid &= ConfigNodeUtil.ParseValue <int>(crewNode, "count", x => count = x, factory, 1); for (int i = 0; i < count; i++) { CrewData cd = new CrewData(); // Read crew details valid &= ConfigNodeUtil.ParseValue <string>(crewNode, "name", x => cd.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue <bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true); // Add the record vessel.crew.Add(cd); } } // Add to the list spawnVessel.vessels.Add(vessel); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } return(valid ? spawnVessel : null); }
private void RemoveCrew(VesselData vd) { foreach (CrewData cd in vd.crew) { ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.AllKerbals().Where(pcm => pcm.name == cd.name).FirstOrDefault(); if (!cd.addToRoster && crewMember != null) { Vessel otherVessel = FlightGlobals.Vessels.Where(v => v.GetVesselCrew().Contains(crewMember)).FirstOrDefault(); if (otherVessel != null) { // If it's an EVA make them disappear... if (otherVessel.isEVA) { FlightGlobals.Vessels.Remove(otherVessel); } else { if (otherVessel.loaded) { foreach (Part p in otherVessel.parts) { if (p.protoModuleCrew.Contains(crewMember)) { p.RemoveCrewmember(crewMember); break; } } } else { foreach (ProtoPartSnapshot pps in otherVessel.protoVessel.protoPartSnapshots) { if (pps.HasCrew(crewMember.name)) { pps.RemoveCrew(crewMember); } } } } } // Remove the kerbal from the roster HighLogic.CurrentGame.CrewRoster.Remove(cd.name); } } }
/// <summary> /// Plane normal vector from a given heading (surface right vector) /// </summary> public static Vector3 vecHeading(double target, VesselData vdata) { double angleDiff = target - vdata.heading; return(Quaternion.AngleAxis((float)(angleDiff + 90), (Vector3)vdata.planetUp) * vdata.surfVesForward); }
public override HashSet <ProtoPartResourceSnapshot> HandleResource(Vessel v, VesselData data, HashSet <ProtoPartResourceSnapshot> modified) { return(AddResource(data, resourceRate * TimeWarp.fixedDeltaTime, resourceName, modified)); }
/// <summary> /// calculate current heading from plane rotation /// </summary> public static double calculateTargetHeading(Quaternion rotation, Vessel vessel, VesselData vdata) { Vector3 fwd = Vector3.Cross(getPlaneNormal(rotation, vessel), vdata.planetUp); double heading = Vector3.Angle(fwd, vdata.planetNorth) * Math.Sign(Vector3.Dot(fwd, vdata.planetEast)); return(heading.headingClamp(360)); }
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); } } }
public static Quaternion getPlaneRotation(double heading, Vessel vessel, VesselData vdata) { Vector3 planeNormal = vecHeading(heading, vdata); return(getPlaneRotation(planeNormal, vessel)); }
public static Quaternion getPlaneRotation(double heading, Vessel vessel, VesselData vdata) { Vector3 planeNormal = vecHeading(heading, vdata); return getPlaneRotation(planeNormal, vessel); }
public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory) { SpawnVessel spawnVessel = new SpawnVessel(); ConfigNodeUtil.ParseValue<bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL")) { DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); VesselData vessel = new VesselData(); // Get name if (child.HasValue("name")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => vessel.name = x, factory); } // Get craft details if (child.HasValue("craftURL")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "craftURL", x => vessel.craftURL = x, factory); } if (child.HasValue("craftPart")) { valid &= ConfigNodeUtil.ParseValue<AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory); } valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory); valid &= ConfigNodeUtil.ParseValue<string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => vessel.body = x, factory); // Get landed stuff if (child.HasValue("lat") && child.HasValue("lon")) { valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; } // Get orbit else { valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => vessel.orbit = x, factory); vessel.orbiting = true; } valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => vessel.heading = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "roll", x => vessel.roll = x, factory, 0.0f); // Get additional flags valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => vessel.owned = x, factory, false); // Handle the CREW nodes foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW")) { int count = 1; valid &= ConfigNodeUtil.ParseValue<int>(crewNode, "count", x => count = x, factory, 1); for (int i = 0; i < count; i++) { CrewData cd = new CrewData(); // Read crew details valid &= ConfigNodeUtil.ParseValue<string>(crewNode, "name", x => cd.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory); // Add the record vessel.crew.Add(cd); } } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list spawnVessel.vessels.Add(vessel); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } if (!configNode.HasNode("VESSEL")) { valid = false; LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node."); } return valid ? spawnVessel : null; }
/// <summary> /// calculate current heading from plane normal vector /// </summary> public static double calculateTargetHeading(Vector3 direction, VesselData vdata) { Vector3 fwd = Vector3.Cross(direction, vdata.planetUp); double heading = Vector3.Angle(fwd, vdata.planetNorth) * Math.Sign(Vector3.Dot(fwd, vdata.planetEast)); return heading.headingClamp(360); }
public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory) { SpawnVessel spawnVessel = new SpawnVessel(); ConfigNodeUtil.ParseValue<bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL")) { DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); VesselData vessel = new VesselData(); // Get name if (child.HasValue("name")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => vessel.name = x, factory); } // Get craft details if (child.HasValue("craftURL")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "craftURL", x => vessel.craftURL = x, factory); } if (child.HasValue("craftPart")) { valid &= ConfigNodeUtil.ParseValue<AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory); } valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory); valid &= ConfigNodeUtil.ParseValue<string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => vessel.body = x, factory); // Get landed stuff if (child.HasValue("pqsCity")) { string pqsCityStr = null; valid &= ConfigNodeUtil.ParseValue<string>(child, "pqsCity", x => pqsCityStr = x, factory); if (pqsCityStr != null) { try { vessel.pqsCity = vessel.body.GetComponentsInChildren<PQSCity>(true).Where(pqs => pqs.name == pqsCityStr).First(); } catch (Exception e) { LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCityStr + "'"); LoggingUtil.LogException(e); valid = false; } } valid &= ConfigNodeUtil.ParseValue<Vector3d>(child, "pqsOffset", x => vessel.pqsOffset = x, factory, new Vector3d()); // Don't expect these to load anything, but do it to mark as initialized valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory, 0.0); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory, 0.0); // Do load alt and height valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; // Generate PQS city coordinates LoggingUtil.LogVerbose(factory, "Generating coordinates from PQS city for Vessel " + vessel.name); // Translate by the PQS offset (inverse transform of coordinate system) Vector3d position = vessel.pqsCity.transform.position; Vector3d v = vessel.pqsOffset; Vector3d i = vessel.pqsCity.transform.right; Vector3d j = vessel.pqsCity.transform.forward; Vector3d k = vessel.pqsCity.transform.up; Vector3d offsetPos = new Vector3d( (j.y * k.z - j.z * k.y) * v.x + (i.z * k.y - i.y * k.z) * v.y + (i.y * j.z - i.z * j.y) * v.z, (j.z * k.x - j.x * k.z) * v.x + (i.x * k.z - i.z * k.x) * v.y + (i.z * j.x - i.x * j.z) * v.z, (j.x * k.y - j.y * k.x) * v.x + (i.y * k.x - i.x * k.y) * v.y + (i.x * j.y - i.y * j.x) * v.z ); offsetPos *= (i.x * j.y * k.z) + (i.y * j.z * k.x) + (i.z * j.x * k.y) - (i.z * j.y * k.x) - (i.y * j.x * k.z) - (i.x * j.z * k.y); vessel.latitude = vessel.body.GetLatitude(position + offsetPos); vessel.longitude = vessel.body.GetLongitude(position + offsetPos); } else if (child.HasValue("lat") && child.HasValue("lon")) { valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; } // Get orbit else { valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => vessel.orbit = x, factory); vessel.orbiting = true; } valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => vessel.heading = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "roll", x => vessel.roll = x, factory, 0.0f); // Get additional flags valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => vessel.owned = x, factory, false); // Handle the CREW nodes foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW")) { int count = 1; valid &= ConfigNodeUtil.ParseValue<int>(crewNode, "count", x => count = x, factory, 1); for (int i = 0; i < count; i++) { CrewData cd = new CrewData(); // Read crew details valid &= ConfigNodeUtil.ParseValue<string>(crewNode, "name", x => cd.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory); // Add the record vessel.crew.Add(cd); } } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list spawnVessel.vessels.Add(vessel); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } if (!configNode.HasNode("VESSEL")) { valid = false; LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node."); } return valid ? spawnVessel : null; }
public override HashSet<ProtoPartResourceSnapshot> HandleResource(Vessel v, VesselData data, HashSet<ProtoPartResourceSnapshot> modified) { return AddResource(data, resourceRate * TimeWarp.fixedDeltaTime, resourceName, modified); }
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); } }
private void SpawnVessel(VesselData vesselData, List <ProtoCrewMember> crewData = null) { string gameDataDir = KSPUtil.ApplicationRootPath; Debug.Log("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) { Debug.Log("ShipConstruct was null when tried to load '" + vesselData.craftURL + "' (usually this means the file could not be found)."); 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; dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto, true)); } 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); } } }
protected override void OnLoad(ConfigNode configNode) { base.OnLoad(configNode); vesselsCreated = ConfigNodeUtil.ParseValue<bool>(configNode, "vesselsCreated"); deferVesselCreation = ConfigNodeUtil.ParseValue<bool?>(configNode, "deferVesselCreation", (bool?)false).Value; foreach (ConfigNode child in configNode.GetNodes("VESSEL_DETAIL")) { // Read all the orbit data VesselData vd = new VesselData(); vd.name = child.GetValue("name"); vd.id = ConfigNodeUtil.ParseValue<Guid?>(child, "id", (Guid?)null); vd.craftURL = child.GetValue("craftURL"); vd.flagURL = ConfigNodeUtil.ParseValue<string>(child, "flagURL", (string)null); vd.vesselType = ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType"); vd.body = ConfigNodeUtil.ParseValue<CelestialBody>(child, "body"); vd.latitude = ConfigNodeUtil.ParseValue<double>(child, "lat"); vd.longitude = ConfigNodeUtil.ParseValue<double>(child, "lon"); vd.altitude = ConfigNodeUtil.ParseValue<double?>(child, "alt", (double?)null); vd.heading = ConfigNodeUtil.ParseValue<float>(child, "heading", 0.0f); vd.pitch = ConfigNodeUtil.ParseValue<float>(child, "pitch", 0.0f); vd.roll = ConfigNodeUtil.ParseValue<float>(child, "roll", 0.0f); vd.orbiting = ConfigNodeUtil.ParseValue<bool?>(child, "orbiting", (bool?)child.HasNode("ORBIT")).Value; vd.owned = ConfigNodeUtil.ParseValue<bool>(child, "owned"); if (child.HasNode("ORBIT")) { vd.orbit = new OrbitSnapshot(child.GetNode("ORBIT")).Load(); } // Load crew data foreach (ConfigNode crewNode in child.GetNodes("CREW")) { CrewData cd = new CrewData(); cd.name = ConfigNodeUtil.ParseValue<string>(crewNode, "name", (string)null); cd.addToRoster = ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster"); vd.crew.Add(cd); } // Add to the global list vessels.Add(vd); } }
public static Guid?CreateVessel(VesselData vesselData) { String gameDataDir = KSPUtil.ApplicationRootPath; gameDataDir = gameDataDir.Replace("\\", "/"); if (!gameDataDir.EndsWith("/")) { gameDataDir += "/"; } gameDataDir += "GameData"; // Spawn the vessel in the game world // Set additional info for landed vessels bool landed = false; if (!vesselData.orbiting) { landed = true; if (vesselData.altitude == null) { vesselData.altitude = 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 (vesselData.shipConstruct != null) { // 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) //{ // return false; //} // Restore ShipConstruction ship //ShipConstruction.ShipConfig = currentShip; shipConstruct = vesselData.shipConstruct; // 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; } // 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; //} 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) { // Get the ProtoCrewMember ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.Crew.FirstOrDefault(pcm => pcm.name == cd.name); // Add them to the part success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count); } if (!success) { 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. ConfigNode empty = new ConfigNode(); ProtoVessel dummyProto = new ProtoVessel(empty, null); Vessel dummyVessel = new GameObject().AddComponent <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(); // Clean up GameObject.Destroy(dummyVessel.gameObject); } 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.ChangeName(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 //not needed? //ConfigNode[] additionalNodes = new ConfigNode[1]; //DiscoveryLevels discoveryLevel = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned; //additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, , contract.TimeDeadline); // Create the config node representation of the ProtoVessel ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes); // 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) //TODO: I need this for KCT { rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward); heading += 180.0f; } else { rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward); } rotation = rotation * Quaternion.AngleAxis(vesselData.pitch, Vector3.right); rotation = rotation * Quaternion.AngleAxis(vesselData.roll, Vector3.down); rotation = rotation * Quaternion.AngleAxis(heading, Vector3.forward); // 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 = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame); protoVessel.Load(HighLogic.CurrentGame.flightState); HighLogic.CurrentGame.flightState.protoVessels.Add(protoVessel); // 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); return(vesselData.id); }
public void Reset( VesselData vessel_data, double altitude_step, double velocity_step, double velocity_max, double aoa, bool init_simple = true) { double aoa_cos = Math.Cos(aoa); double aoa_sin = Math.Sin(aoa); double altitude_max; if (body_.HasAtmosphere) { altitude_max = body_.AtmosphereDepth; } else { altitude_max = 1d; altitude_step = 1d; } uint altitude_n = (uint)Math.Ceiling(altitude_max / altitude_step); uint velocity_n = (uint)Math.Ceiling(velocity_max / velocity_step); var flight = vessel_.Flight(body_.ReferenceFrame); double radius = body_.EquatorialRadius; /*var stream_pos = conn_.AddStream(() => vessel_.Position(body_.ReferenceFrame)); * var stream_backward = conn_.AddStream(() => sc_.TransformDirection( * new Tuple<double, double, double>(0, -1, 0), * vessel_.ReferenceFrame, body_.ReferenceFrame)); * var stream_right = conn_.AddStream(() => sc_.TransformDirection( * new Tuple<double, double, double>(1, 0, 0), * vessel_.ReferenceFrame, body_.ReferenceFrame));*/ atm_ = new LinearTable( 0d, altitude_step, altitude_n, (double altitude) => { double atm = body_.PressureAt(altitude) / Constants.Common.STANDARD_ATMOSPHERIC_PRESSURE; return(atm); }, init_simple); available_thrust_ = new LinearTable( 0d, altitude_step, altitude_n, (double altitude) => { double atm = atm_[altitude]; double thr = vessel_.AvailableThrustAt(atm); return(thr); }, init_simple); density_ = new LinearTable( 0d, altitude_step, altitude_n, (double altitude) => { double density = body_.DensityAt(altitude); return(density); }, init_simple); sim_drift_ = new BiLinearTable( 0d, altitude_step, altitude_n, 0d, velocity_step, velocity_n, (double altitude, double velocity) => { /*Vector3d pos_now = new Vector3d(stream_pos.Get()); * Vector3d backward = new Vector3d(stream_backward.Get());*/ Vector3d pos = vessel_data.Vessel.Position.Norm() * (radius + altitude); Vector3d vel_backward = -velocity * vessel_data.Vessel.Forward; var sim = flight.SimulateAerodynamicForceAt(body_, pos.ToTuple(), vel_backward.ToTuple()); return(new Vector3d(sim).Length()); }); sim_lift_ = new BiLinearTable( 0d, altitude_step, altitude_n, 0d, velocity_step, velocity_n, (double altitude, double velocity) => { /*Vector3d pos_now = new Vector3d(stream_pos.Get()); * Vector3d backward = new Vector3d(stream_backward.Get()); * Vector3d right = new Vector3d(stream_right.Get());*/ Vector3d pos = vessel_data.Vessel.Position.Norm() * (radius + altitude); Vector3d vel_backward = -velocity * vessel_data.Vessel.Forward; Vector3d vel_tilt = velocity * (vessel_data.Vessel.Right * aoa_sin - vessel_data.Vessel.Forward * aoa_cos); var sim = flight.SimulateAerodynamicForceAt(body_, pos.ToTuple(), vel_tilt.ToTuple()); return(-(new Vector3d(sim) * vessel_data.Vessel.Right)); }); }