Пример #1
0
        public void CreateVessel(comms.VesselList.VesselInfo vesselInfo)
        {
            try
            {
                this.Logger.LogDebug("creating vessel {0} {1}", vesselInfo.name, vesselInfo.id);
                var pv = new ProtoVessel(this.DummyVesselConfigNode, HighLogic.CurrentGame);

                pv.vesselID      = vesselInfo.id;
                pv.vesselName    = vesselInfo.name;
                pv.vesselType    = (VesselType)vesselInfo.type;
                pv.altitude      = vesselInfo.altitude;
                pv.landed        = vesselInfo.landed;
                pv.landedAt      = vesselInfo.landedAt;
                pv.latitude      = vesselInfo.latitude;
                pv.longitude     = vesselInfo.longitude;
                pv.situation     = (Vessel.Situations)vesselInfo.situation;
                pv.splashed      = vesselInfo.splashed;
                pv.orbitSnapShot = new OrbitSnapshot(vesselInfo.orbit.GetKspOrbit(FlightGlobals.Bodies));

                pv.Load(HighLogic.CurrentGame.flightState);
            }
            catch (Exception e)
            {
                this.Logger.LogException(e);
                throw;
            }
        }
Пример #2
0
 public IEnumerator <YieldInstruction> SpawnProtoVessel(ProtoVessel proto_vessel,
                                                        Transform spawn_transform,
                                                        Vector3 spawn_offset,
                                                        Vector3 dV,
                                                        Callback <ProtoVessel> on_proto_vessel_positioned = null,
                                                        Callback <Vessel> on_vessel_loaded    = null,
                                                        Callback <Vessel> on_vessel_off_rails = null,
                                                        Callback <Vessel> on_vessel_launched  = null)
 {
     begin_launch(spawn_transform);
     position_proto_vessel(proto_vessel, spawn_transform, spawn_offset);
     on_proto_vessel_positioned?.Invoke(proto_vessel);
     proto_vessel.Load(HighLogic.CurrentGame.flightState);
     launched_vessel = proto_vessel.vesselRef;
     launched_vessel.orbitDriver.updateMode = OrbitDriver.UpdateMode.TRACK_Phys;
     launched_vessel.skipGroundPositioning  = true;
     foreach (var i in launch_moving_vessel(spawn_transform,
                                            spawn_offset,
                                            Quaternion.identity,
                                            dV,
                                            on_vessel_loaded,
                                            on_vessel_off_rails,
                                            on_vessel_launched))
     {
         yield return(i);
     }
     end_launch();
 }
Пример #3
0
        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);
        }
Пример #4
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel currentProto)
        {
            if (HighLogic.CurrentGame?.flightState == null)
            {
                return(false);
            }

            LunaLog.Log($"[LMP]: Loading {currentProto.vesselID}, Name: {currentProto.vesselName}, type: {currentProto.vesselType}");
            currentProto.Load(HighLogic.CurrentGame.flightState);

            if (currentProto.vesselRef == null)
            {
                LunaLog.Log($"[LMP]: Protovessel {currentProto.vesselID} failed to create a vessel!");
                return(false);
            }

            SystemsContainer.Get <PlayerColorSystem>().SetVesselOrbitColor(currentProto.vesselRef);
            if (HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                //When in trackstation rebuild the vessels left panel as otherwise the new vessel won't be listed
                var spaceTracking = Object.FindObjectOfType <SpaceTracking>();
                if (spaceTracking != null)
                {
                    BuildSpaceTrackingVesselList?.Invoke(spaceTracking, null);
                }
            }
            return(true);
        }
Пример #5
0
        public static void UnhangarCraft(Vessel vVesselStored, StaticObject soHangar)
        {
            RemoveCorrectCraft(vVesselStored, soHangar);

            // Convert the stored protovessel to a new protovessel.
            // Use BackupVessel because that seems to work and protovessel does not. `\o/`
            ProtoVessel pVessel = vVesselStored.BackupVessel();

            // Get rid of the original hidden vessel - even though it was unloaded KSP still 'sees' the original craft.
            // I do not care why. :|
            vVesselStored.state = Vessel.State.DEAD;

            foreach (Part p in vVesselStored.Parts)
            {
                if (p != null && p.gameObject != null)
                {
                    p.gameObject.DestroyGameObject();
                }
            }

            // Load the new protovessel we made. KSP won't reload (or rather render) a vessel that was unloaded - it will only load a protovessel. :$
            pVessel.Load(FlightDriver.FlightStateCache.flightState);
            // I suspect this is actually a KSP bug since the same crap happens with newly spawned static objects. If you query the active state
            // of the invisible craft, it claims it is active. And no, forcing the renderers doesn't work either.

            // Convert protovessel to vessel
            Vessel vNewVessel = pVessel.vesselRef;

            // Unload then reload the vessel - this seems to be the way to properly re-initialise flightstate etc.
            // Don't do this and you get a craft with a stuck surface velocity reading. It looks like KSP transposes orbital
            // and surface velocity or some other stupid s**t. I don't care.
            // And yes, this time KSP does load an unloaded vessel with no need for protovessel b******t. I don't care why.
            vNewVessel.Unload();
            vNewVessel.Load();
        }
Пример #6
0
 public void AllocVessel(NetworkViewID id, byte[] binaryCfg)
 {
     if (FlightGlobals.Vessels.Any(v => v.networkView != null && v.networkView.viewID == id))
         return;
     var cfg = (ConfigNode)IOUtils.DeserializeFromBinary(binaryCfg);
     var protovessel = new ProtoVessel(cfg, HighLogic.CurrentGame.flightState);
     protovessel.orbitSnapShot.meanAnomalyAtEpoch += 1;
     protovessel.Load(HighLogic.CurrentGame.flightState);
     var vessel = protovessel.vesselRef;
     vessel.gameObject.AddNetworkView(id);
     vessel.gameObject.AddComponent<VesselNetworker>();
 }
Пример #7
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel currentProto)
        {
            LunaLog.Log($"[LMP]: Loading {currentProto.vesselID}, Name: {currentProto.vesselName}, type: {currentProto.vesselType}");
            currentProto.Load(HighLogic.CurrentGame.flightState);

            if (currentProto.vesselRef == null)
            {
                LunaLog.Log($"[LMP]: Protovessel {currentProto.vesselID} failed to create a vessel!");
                return(false);
            }
            return(true);
        }
Пример #8
0
        public void AllocVessel(NetworkViewID id, byte[] binaryCfg)
        {
            if (FlightGlobals.Vessels.Any(v => v.networkView != null && v.networkView.viewID == id))
            {
                return;
            }
            var cfg         = (ConfigNode)IOUtils.DeserializeFromBinary(binaryCfg);
            var protovessel = new ProtoVessel(cfg, HighLogic.CurrentGame.flightState);

            protovessel.orbitSnapShot.meanAnomalyAtEpoch += 1;
            protovessel.Load(HighLogic.CurrentGame.flightState);
            var vessel = protovessel.vesselRef;

            vessel.gameObject.AddNetworkView(id);
            vessel.gameObject.AddComponent <VesselNetworker>();
        }
Пример #9
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel currentProto)
        {
            if (HighLogic.CurrentGame?.flightState == null)
            {
                return(false);
            }

            LunaLog.Log($"[LMP]: Loading {currentProto.vesselID}, Name: {currentProto.vesselName}, type: {currentProto.vesselType}");
            currentProto.Load(HighLogic.CurrentGame.flightState);

            if (currentProto.vesselRef == null)
            {
                LunaLog.Log($"[LMP]: Protovessel {currentProto.vesselID} failed to create a vessel!");
                return(false);
            }

            if (currentProto.vesselRef.isEVA)
            {
                var evaModule = currentProto.vesselRef.FindPartModuleImplementing <KerbalEVA>();
                if (evaModule != null && evaModule.fsm != null && !evaModule.fsm.Started)
                {
                    evaModule.fsm?.StartFSM("Idle (Grounded)");
                }
                currentProto.vesselRef.GoOnRails();
            }
            currentProto.vesselRef.orbitDriver?.updateFromParameters();

            PlayerColorSystem.Singleton.SetVesselOrbitColor(currentProto.vesselRef);
            if (HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                //When in trackstation rebuild the vessels left panel as otherwise the new vessel won't be listed
                var spaceTracking = Object.FindObjectOfType <SpaceTracking>();
                if (spaceTracking != null)
                {
                    BuildSpaceTrackingVesselList?.Invoke(spaceTracking, null);
                }
            }

            if (HighLogic.LoadedScene == GameScenes.SPACECENTER)
            {
                KSCVesselMarkers.fetch?.RefreshMarkers();
            }

            return(true);
        }
Пример #10
0
        internal static Vessel RollOutVessel(StoredVessel storedVessel, Hangar hangar)
        {
            if (!hangar.storedVessels.Contains(storedVessel))
            {
                Log.Error("no Stored Vessel found:" + storedVessel.vesselName);
                return(null);
            }
            hangar.storedVessels.Remove(storedVessel);

            ProtoVessel protoVessel = new ProtoVessel(storedVessel.vesselNode, HighLogic.CurrentGame);


            protoVessel.Load(HighLogic.CurrentGame.flightState);

            Vessel vessel = protoVessel.vesselRef;

            return(vessel);
        }
Пример #11
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel currentProto)
        {
            try
            {
                Debug.Log($"[LMP]: Loading {currentProto.vesselID}, Name: {currentProto.vesselName}, type: {currentProto.vesselType}");
                currentProto.Load(HighLogic.CurrentGame.flightState);

                if (currentProto.vesselRef == null)
                {
                    Debug.Log($"[LMP]: Protovessel {currentProto.vesselID} failed to create a vessel!");
                    return(false);
                }
                return(true);
            }
            catch (Exception e)
            {
                Debug.LogError($"[LMP]: Error in coroutine LoadVessel {e}");
                return(false);
            }
        }
Пример #12
0
        /// <summary>
        /// Rollout the Vessel and store it in the placeHolder variable, then open the Crew assignment dialog
        /// </summary>
        /// <param name="storedVessel"></param>
        /// <param name="hangar"></param>
        internal static void SelectVessel(Modules.Hangar.StoredVessel storedVessel, Modules.Hangar hangar)
        {
            if (selectedVessel != null)
            {
                foreach (ProtoCrewMember crew in selectedVessel.GetVesselCrew())
                {
                    // unseat all crew
                    crew.rosterStatus = ProtoCrewMember.RosterStatus.Available;
                    crew.seatIdx      = -1;
                }
            }

            selectedVessel = null;

            if (!hangar.storedVessels.Contains(storedVessel))
            {
                Log.Error("no stored vessel found:" + storedVessel.vesselName);
                return;
            }

            selectedHangar       = hangar;
            selectedStoredVessel = storedVessel;


            ProtoVessel protoVessel = new ProtoVessel(storedVessel.vesselNode, HighLogic.CurrentGame);

            protoVessel.Load(HighLogic.CurrentGame.flightState);

            selectedVessel = protoVessel;


            if (selectedVessel == null)
            {
                Log.UserError("Could not receive vessel from storage.");
                return;
            }

            Reload();
        }
Пример #13
0
        private IEnumerator<WaitForFixedUpdate> loadProtovessel(Vessel oldVessel, Vector3 newWorldPos, Vector3 newOrbitVel, bool wasLoaded, bool wasActive, bool setTarget, ProtoVessel protovessel, Guid vessel_id, KMPVessel kvessel, KMPVesselUpdate update, double distance)
        {
            yield return new WaitForFixedUpdate();
            Log.Debug("Loading protovessel: {0}", vessel_id.ToString() + ", name: " + protovessel.vesselName + ", type: " + protovessel.vesselType);
            if (oldVessel != null && !wasActive)
            {
                killVessel(oldVessel);
            }
            serverVessels_LoadDelay[vessel_id] = UnityEngine.Time.realtimeSinceStartup + 5f;
            serverVessels_PartCounts[vessel_id] = protovessel.protoPartSnapshots.Count;
            protovessel.Load(HighLogic.CurrentGame.flightState);
            Vessel created_vessel = protovessel.vesselRef;

            if (created_vessel != null)
            {
                try
                {
                    OrbitPhysicsManager.HoldVesselUnpack(1);
                }
                catch (NullReferenceException e)
                {
                    Log.Debug("Exception thrown in loadProtovessel(), catch 1, Exception: {0}", e.ToString());
                }

                Log.Debug(created_vessel.id.ToString() + " initializing: ProtoParts=" + protovessel.protoPartSnapshots.Count + ",Parts=" + created_vessel.Parts.Count + ",Sit=" + created_vessel.situation.ToString() + ",type=" + created_vessel.vesselType + ",alt=" + protovessel.altitude);

                //vessels[vessel_id.ToString()].vessel.vesselRef = created_vessel;
                serverVessels_PartCounts[vessel_id] = created_vessel.Parts.Count;
                serverVessels_Parts[vessel_id] = new List<Part>();
                serverVessels_Parts[vessel_id].AddRange(created_vessel.Parts);

                if (created_vessel.vesselType != VesselType.Flag && created_vessel.vesselType != VesselType.EVA)
                {
                    foreach (Part part in created_vessel.Parts)
                    {
                        part.OnLoad();
                        part.OnJustAboutToBeDestroyed += checkRemoteVesselIntegrity;
                        part.explosionPotential = 0;
                        part.terrainCollider = new PQS_PartCollider();
                        part.terrainCollider.part = part;
                        part.terrainCollider.useVelocityCollider = false;
                        part.terrainCollider.useGravityCollider = false;
                        part.breakingForce = float.MaxValue;
                        part.breakingTorque = float.MaxValue;
                    }
                    if (update == null || (update != null && update.bodyName == FlightGlobals.ActiveVessel.mainBody.name))
                    {
                        Log.Debug("update included");

                        if (update == null || (update.relTime == RelativeTime.PRESENT))
                        {
                            if (newWorldPos != Vector3.zero)
                            {
                                Log.Debug("repositioning");
                                created_vessel.transform.position = newWorldPos;
                            }
                            if (newOrbitVel != Vector3.zero)
                            {
                                Log.Debug("updating velocity");
                                created_vessel.ChangeWorldVelocity((-1 * created_vessel.GetObtVelocity()) + (new Vector3(newOrbitVel.x, newOrbitVel.z, newOrbitVel.y))); //xzy?
                            }
                            StartCoroutine(restoreVesselState(created_vessel, newWorldPos, newOrbitVel));
                            //Update FlightCtrlState
                            if (update != null)
                            {
                                if (created_vessel.ctrlState == null)
                                    created_vessel.ctrlState = new FlightCtrlState();
                                created_vessel.ctrlState.CopyFrom(update.flightCtrlState.getAsFlightCtrlState(0.75f));
                            }
                        }
                        else
                        {
                            StartCoroutine(setNewVesselNotInPresent(created_vessel));
                        }
                    }
                }
                if (setTarget)
                    StartCoroutine(setDockingTarget(created_vessel));
                if (wasActive)
                    StartCoroutine(setActiveVessel(created_vessel, oldVessel));
                Log.Debug(created_vessel.id.ToString() + " initialized");
            }
            else
            {
                Log.Debug("Failed to create vessel " + vessel_id);
            }
        }
Пример #14
0
        public void SpawnAsteroid(Asteroid asteroid, UInt32 seed)
        {
            // Create Default Orbit
            Orbit         orbit = null;
            CelestialBody body  = null;

            // Select Orbit Type
            Int32 type = Random.Range(0, 3);

            if (type == 0 && asteroid.Location.Around.Count != 0)
            {
                // Around
                Location.AroundLoader[] around = GetProbabilityList(asteroid.Location.Around,
                                                                    asteroid.Location.Around.Select(a => a.Probability.Value).ToList()).ToArray();
                Location.AroundLoader loader = around[Random.Range(0, around.Length)];
                body = UBI.GetBody(loader.Body);
                if (!body)
                {
                    return;
                }

                if (loader.Reached && !ReachedBody(body))
                {
                    return;
                }

                orbit = new Orbit
                {
                    referenceBody       = body,
                    eccentricity        = loader.Eccentricity,
                    semiMajorAxis       = loader.SemiMajorAxis,
                    inclination         = loader.Inclination,
                    LAN                 = loader.LongitudeOfAscendingNode,
                    argumentOfPeriapsis = loader.ArgumentOfPeriapsis,
                    meanAnomalyAtEpoch  = loader.MeanAnomalyAtEpoch,
                    epoch               = loader.Epoch
                };
                orbit.Init();
            }
            else if (type == 1 && asteroid.Location.Nearby.Count != 0)
            {
                // Nearby
                Location.NearbyLoader[] nearby = GetProbabilityList(asteroid.Location.Nearby,
                                                                    asteroid.Location.Nearby.Select(a => a.Probability.Value).ToList()).ToArray();
                Location.NearbyLoader loader = nearby[Random.Range(0, nearby.Length)];
                body = UBI.GetBody(loader.Body);
                if (!body)
                {
                    return;
                }

                if (loader.Reached && !ReachedBody(body))
                {
                    return;
                }

                orbit = new Orbit
                {
                    eccentricity        = body.orbit.eccentricity + loader.Eccentricity,
                    semiMajorAxis       = body.orbit.semiMajorAxis * loader.SemiMajorAxis,
                    inclination         = body.orbit.inclination + loader.Inclination,
                    LAN                 = body.orbit.LAN * loader.LongitudeOfAscendingNode,
                    argumentOfPeriapsis = body.orbit.argumentOfPeriapsis * loader.ArgumentOfPeriapsis,
                    meanAnomalyAtEpoch  = body.orbit.meanAnomalyAtEpoch * loader.MeanAnomalyAtEpoch,
                    epoch               = body.orbit.epoch,
                    referenceBody       = body.orbit.referenceBody
                };
                orbit.Init();
            }
            else if (type == 2 && asteroid.Location.Flyby.Count != 0)
            {
                // Flyby
                Location.FlybyLoader[] flyby = GetProbabilityList(asteroid.Location.Flyby,
                                                                  asteroid.Location.Flyby.Select(a => a.Probability.Value).ToList()).ToArray();
                Location.FlybyLoader loader = flyby[Random.Range(0, flyby.Length)];
                body = UBI.GetBody(loader.Body);
                if (!body)
                {
                    return;
                }

                if (loader.Reached && !ReachedBody(body))
                {
                    return;
                }

                orbit = Orbit.CreateRandomOrbitFlyBy(body, Random.Range(loader.MinDuration, loader.MaxDuration));
            }

            // Check
            if (orbit == null)
            {
                Debug.Log("[Kopernicus] No new objects this time. (Probability is " + asteroid.Probability.Value + "%)");
                return;
            }

            // Name
            String asteroidName = DiscoverableObjectsUtil.GenerateAsteroidName();

            // Lifetime
            Double lifetime    = Random.Range(asteroid.MinUntrackedLifetime, asteroid.MaxUntrackedLifetime) * 24d * 60d * 60d;
            Double maxLifetime = asteroid.MaxUntrackedLifetime * 24d * 60d * 60d;

            // Size
            UntrackedObjectClass size = (UntrackedObjectClass)(Int32)(asteroid.Size.Evaluate(Random.Range(0f, 1f)) * Enum.GetNames(typeof(UntrackedObjectClass)).Length);

            // Spawn
            ConfigNode vessel = null;

            vessel = ProtoVessel.CreateVesselNode(
                asteroidName,
                VesselType.SpaceObject,
                orbit,
                0,
                new[]
            {
                ProtoVessel.CreatePartNode(
                    "PotatoRoid",
                    seed
                    )
            },
                new ConfigNode("ACTIONGROUPS"),
                ProtoVessel.CreateDiscoveryNode(
                    DiscoveryLevels.Presence,
                    size,
                    lifetime,
                    maxLifetime
                    )
                );
            OverrideNode(ref vessel, asteroid.Vessel);
            ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame);

            if (asteroid.UniqueName && FlightGlobals.Vessels.Count(v => v.vesselName == protoVessel.vesselName) != 0)
            {
                return;
            }

            Kopernicus.Events.OnRuntimeUtilitySpawnAsteroid.Fire(asteroid, protoVessel);
            protoVessel.Load(HighLogic.CurrentGame.flightState);
            GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef);
            GameEvents.onAsteroidSpawned.Fire(protoVessel.vesselRef);
            Debug.Log("[Kopernicus] New object found near " + body.name + ": " + protoVessel.vesselName + "!");
        }
        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;
                    }

                    // 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)
                        {
                            // 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.ChangeName(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.
                    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
                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(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);

                // 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;
        }
Пример #16
0
        private bool loadVesselForRendezvous(ProtoVessel placeVessel, Vessel targetVessel)
        {
            targetVessel.BackupVessel();

            placeVessel.orbitSnapShot = targetVessel.protoVessel.orbitSnapShot;

            placeVessel.orbitSnapShot.epoch = 0.0;

            tempID = RmmUtil.Rand.Next(1000000000).ToString();
            //rename any vessels present with "AdministativeDockingName"
            foreach (Vessel ve in FlightGlobals.Vessels)
            {
                if (ve.vesselName == tempID)
                {
                    Vessel NameVessel = null;
                    NameVessel            = ve;
                    NameVessel.vesselName = "1";
                }
            }

            placeVessel.vesselID = Guid.NewGuid();

            placeVessel.vesselName = tempID;

            foreach (ProtoPartSnapshot p in placeVessel.protoPartSnapshots)
            {
                uint newFlightID = (UInt32)RmmUtil.Rand.Next(1000000000, 2147483647);

                // save flight ID of part which should dock
                if (p.flightID == _mission.flightIDDockPart)
                {
                    missionFlightIDDockPart = newFlightID;
                }

                // update flight ID of each part and vessel reference transform id.
                if (placeVessel.refTransform == p.flightID)
                {
                    p.flightID = newFlightID;
                    placeVessel.refTransform = p.flightID;
                }
                else
                {
                    p.flightID = newFlightID;
                }

                // clear out all crew
                if (p.protoModuleCrew != null && p.protoModuleCrew.Count() != 0)
                {
                    List <ProtoCrewMember> cl  = p.protoModuleCrew;
                    List <ProtoCrewMember> clc = new List <ProtoCrewMember>(cl);

                    foreach (ProtoCrewMember c in clc)
                    {
                        p.RemoveCrew(c);
                    }
                }

                foreach (ProtoPartModuleSnapshot pm in p.modules)
                {
                    if (pm.moduleName == "RMMModule")
                    {
                        pm.moduleValues.SetValue("trackingPrimary", false);
                        pm.moduleValues.SetValue("trackingActive", false);
                    }
                }
            }

            try
            {
                placeVessel.Load(HighLogic.CurrentGame.flightState);
                return(true);
            }
            catch
            {
                return(true);
            }
        }
        public override void LaunchVessel()
        {
            if (FlightGlobals.ActiveVessel.situation != Vessel.Situations.ORBITING)
            {
                throw new Exception(_notInOrbitErrorText);
            }

            if (string.IsNullOrEmpty(_selectedCraftFilePath))
            {
                throw new Exception(_noVesselSelectedErrorText);
            }

            if (LogisticsTools.AnyNearbyVessels(100d, FlightGlobals.ActiveVessel))
            {
                throw new Exception(_nearbyVesselsErrorText);
            }

            PartUtilities.ConsumeResources(_cachedCostData);

            var vesselOrbit = FlightGlobals.ActiveVessel.orbit;
            var now         = Planetarium.GetUniversalTime();

            vesselOrbit.GetOrbitalStateVectorsAtUT(
                now,
                out Vector3d position,
                out Vector3d velocity);
            position.x += 50d;
            var orbit = new Orbit(vesselOrbit);

            orbit.UpdateFromStateVectors(
                position,
                velocity,
                vesselOrbit.referenceBody,
                now);

            var partNodes = _cachedProtoVessel.protoPartSnapshots
                            .Select(s =>
            {
                var node = new ConfigNode("PART");
                s.Save(node);
                return(node);
            })
                            .ToArray();
            var type = VesselType.Ship;

            _craftConfigNode.TryGetEnum("type", ref type, VesselType.Ship);

            var vesselConfigNode = ProtoVessel.CreateVesselNode(
                _cachedProtoVessel.GetDisplayName(),
                type,
                orbit,
                0,
                partNodes);

            var spawnedProtoVessel = new ProtoVessel(vesselConfigNode, HighLogic.CurrentGame);

            spawnedProtoVessel.Load(HighLogic.CurrentGame.flightState);

            _window.CloseWindow();

            var spawnedVessel = FlightGlobals.Vessels.Last();

            spawnedVessel.protoVessel.stage = int.MaxValue;
            FlightGlobals.SetActiveVessel(spawnedVessel);
        }
Пример #18
0
 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);
 }
Пример #19
0
        public void SpawnAsteroid(Asteroid asteroid, UInt32 seed)
        {
            // Create Default Orbit
            Orbit         orbit = null;
            CelestialBody body  = null;

            // Select Orbit Type
            Int32 type = Random.Range(0, 3);

            if (type == 0 && asteroid.Location.Around.Count != 0)
            {
                // Around
                Location.AroundLoader[] around = GetProbabilityList(asteroid.Location.Around,
                                                                    asteroid.Location.Around.Select(a => a.Probability.Value).ToList()).ToArray();
                Location.AroundLoader loader = around[Random.Range(0, around.Length)];
                body = UBI.GetBody(loader.Body);
                if (!body)
                {
                    return;
                }

                if (loader.Reached && !ReachedBody(body))
                {
                    return;
                }

                orbit = new Orbit
                {
                    referenceBody       = body,
                    eccentricity        = loader.Eccentricity,
                    semiMajorAxis       = loader.SemiMajorAxis,
                    inclination         = loader.Inclination,
                    LAN                 = loader.LongitudeOfAscendingNode,
                    argumentOfPeriapsis = loader.ArgumentOfPeriapsis,
                    meanAnomalyAtEpoch  = loader.MeanAnomalyAtEpoch,
                    epoch               = loader.Epoch
                };
                orbit.Init();
            }
            else if (type == 1 && asteroid.Location.Nearby.Count != 0)
            {
                // Nearby
                Location.NearbyLoader[] nearby = GetProbabilityList(asteroid.Location.Nearby,
                                                                    asteroid.Location.Nearby.Select(a => a.Probability.Value).ToList()).ToArray();
                Location.NearbyLoader loader = nearby[Random.Range(0, nearby.Length)];
                body = UBI.GetBody(loader.Body);
                if (!body)
                {
                    return;
                }

                if (loader.Reached && !ReachedBody(body))
                {
                    return;
                }

                orbit = new Orbit
                {
                    eccentricity        = body.orbit.eccentricity + loader.Eccentricity,
                    semiMajorAxis       = body.orbit.semiMajorAxis * loader.SemiMajorAxis,
                    inclination         = body.orbit.inclination + loader.Inclination,
                    LAN                 = body.orbit.LAN * loader.LongitudeOfAscendingNode,
                    argumentOfPeriapsis = body.orbit.argumentOfPeriapsis * loader.ArgumentOfPeriapsis,
                    meanAnomalyAtEpoch  = body.orbit.meanAnomalyAtEpoch * loader.MeanAnomalyAtEpoch,
                    epoch               = body.orbit.epoch,
                    referenceBody       = body.orbit.referenceBody
                };
                orbit.Init();
            }
            else if (type == 2 && asteroid.Location.Flyby.Count != 0)
            {
                // Flyby
                Location.FlybyLoader[] flyby = GetProbabilityList(asteroid.Location.Flyby,
                                                                  asteroid.Location.Flyby.Select(a => a.Probability.Value).ToList()).ToArray();
                Location.FlybyLoader loader = flyby[Random.Range(0, flyby.Length)];
                body = UBI.GetBody(loader.Body);
                if (!body)
                {
                    return;
                }

                if (loader.Reached && !ReachedBody(body))
                {
                    return;
                }

                orbit = Orbit.CreateRandomOrbitFlyBy(body, Random.Range(loader.MinDuration, loader.MaxDuration));
            }

            // Check
            if (orbit == null)
            {
                Debug.Log("[Kopernicus] No new objects this time. (Probability is " + asteroid.Probability.Value + "%)");
                return;
            }

            // Name
            String asteroidName = DiscoverableObjectsUtil.GenerateAsteroidName();

            // Lifetime
            Double lifetime    = Random.Range(asteroid.MinUntrackedLifetime, asteroid.MaxUntrackedLifetime) * 24d * 60d * 60d;
            Double maxLifetime = asteroid.MaxUntrackedLifetime * 24d * 60d * 60d;

            // Size
            UntrackedObjectClass size = (UntrackedObjectClass)(Int32)(asteroid.Size.Evaluate(Random.Range(0f, 1f)) * Enum.GetNames(typeof(UntrackedObjectClass)).Length);

            // Spawn
            ConfigNode vessel = null;

#if (KSP_VERSION_1_10_1 || KSP_VERSION_1_11_1)
            if (Random.Range(0, 100) > RuntimeUtility.KopernicusConfig.CometPercentage)
            {
#endif
            vessel = ProtoVessel.CreateVesselNode(
                asteroidName,
                VesselType.SpaceObject,
                orbit,
                0,
                new[]
            {
                ProtoVessel.CreatePartNode(
                    "PotatoRoid",
                    seed
                    )
            },
                new ConfigNode("ACTIONGROUPS"),
                ProtoVessel.CreateDiscoveryNode(
                    DiscoveryLevels.Presence,
                    size,
                    lifetime,
                    maxLifetime
                    )
                );
            OverrideNode(ref vessel, asteroid.Vessel);
            ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame);
            if (asteroid.UniqueName && FlightGlobals.Vessels.Count(v => v.vesselName == protoVessel.vesselName) != 0)
            {
                return;
            }

            Kopernicus.Events.OnRuntimeUtilitySpawnAsteroid.Fire(asteroid, protoVessel);
            protoVessel.Load(HighLogic.CurrentGame.flightState);
            GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef);
            GameEvents.onAsteroidSpawned.Fire(protoVessel.vesselRef);
            Debug.Log("[Kopernicus] New object found near " + body.name + ": " + protoVessel.vesselName + "!");
#if (KSP_VERSION_1_10_1 || KSP_VERSION_1_11_1)
        }

        else
        {
            float                fragmentDynamicPressureModifier = 0f;
            bool                 optimizedCollider = false;
            CometOrbitType       cometType         = CometManager.GenerateWeightedCometType();
            Orbit                cometOrbit        = cometType.CalculateHomeOrbit();
            UntrackedObjectClass randomObjClass    = cometType.GetRandomObjClass();
            CometDefinition      cometDef          = CometManager.GenerateDefinition(cometType, randomObjClass, (int)seed);
            ConfigNode           configNode        = cometDef.CreateVesselNode(optimizedCollider, fragmentDynamicPressureModifier, hasName: false);
            ConfigNode           configNode2       = ProtoVessel.CreatePartNode("PotatoComet", seed);
            uint                 value             = 0u;
            configNode2.TryGetValue("persistentId", ref value);
            configNode.AddValue("cometPartId", value);
            ConfigNode configNode3 = new ConfigNode("VESSELMODULES");
            configNode3.AddNode(configNode);
            vessel = ProtoVessel.CreateVesselNode(DiscoverableObjectsUtil.GenerateCometName(), VesselType.SpaceObject, cometOrbit, 0, new ConfigNode[1] {
                configNode2
            }, new ConfigNode("ACTIONGROUPS"), ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Presence, randomObjClass, lifetime, maxLifetime), configNode3);
            OverrideNode(ref vessel, asteroid.Vessel);
            ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame);
            Kopernicus.Events.OnRuntimeUtilitySpawnAsteroid.Fire(asteroid, protoVessel);
            protoVessel.Load(HighLogic.CurrentGame.flightState);
            GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef);
            GameEvents.onAsteroidSpawned.Fire(protoVessel.vesselRef);
            Debug.Log("[Kopernicus] New object found near " + body.name + ": " + protoVessel.vesselName + "!");
        }
#endif
        }
Пример #20
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel vesselProto)
        {
            if (HighLogic.CurrentGame?.flightState == null)
            {
                return(false);
            }

            var reloadingOwnVessel = FlightGlobals.ActiveVessel && vesselProto.vesselID == FlightGlobals.ActiveVessel.id && HighLogic.LoadedSceneIsFlight;

            //In case the vessel exists, silently remove them from unity and recreate it again
            var existingVessel = FlightGlobals.fetch.LmpFindVessel(vesselProto.vesselID);

            if (existingVessel != null)
            {
                if (reloadingOwnVessel)
                {
                    foreach (var part in existingVessel.Parts)
                    {
                        if (part.protoModuleCrew.Any())
                        {
                            //Serialize to avoid modifying the collection
                            var crewMembers = part.protoModuleCrew.ToArray();
                            foreach (var crew in crewMembers)
                            {
                                part.RemoveCrew(crew);
                            }
                        }
                    }
                }

                FlightGlobals.RemoveVessel(existingVessel);
                foreach (var part in existingVessel.parts)
                {
                    Object.Destroy(part.gameObject);
                }
                Object.Destroy(existingVessel.gameObject);
            }

            vesselProto.Load(HighLogic.CurrentGame.flightState);
            if (vesselProto.vesselRef == null)
            {
                LunaLog.Log($"[LMP]: Protovessel {vesselProto.vesselID} failed to create a vessel!");
                return(false);
            }

            vesselProto.vesselRef.protoVessel = vesselProto;
            if (vesselProto.vesselRef.isEVA)
            {
                var evaModule = vesselProto.vesselRef.FindPartModuleImplementing <KerbalEVA>();
                if (evaModule != null && evaModule.fsm != null && !evaModule.fsm.Started)
                {
                    evaModule.fsm?.StartFSM("Idle (Grounded)");
                }
                vesselProto.vesselRef.GoOnRails();
            }

            if (vesselProto.vesselRef.situation > Vessel.Situations.PRELAUNCH)
            {
                vesselProto.vesselRef.orbitDriver.updateFromParameters();
            }

            if (double.IsNaN(vesselProto.vesselRef.orbitDriver.pos.x))
            {
                LunaLog.Log($"[LMP]: Protovessel {vesselProto.vesselID} has an invalid orbit");
                return(false);
            }

            PlayerColorSystem.Singleton.SetVesselOrbitColor(vesselProto.vesselRef);
            KscSceneSystem.Singleton.RefreshTrackingStationVessels();
            if (KSCVesselMarkers.fetch)
            {
                KSCVesselMarkers.fetch.RefreshMarkers();
            }

            if (reloadingOwnVessel)
            {
                vesselProto.vesselRef.Load();
                vesselProto.vesselRef.RebuildCrewList();

                //Do not do the setting of the active vessel manually, too many systems are dependant of the events triggered by KSP
                FlightGlobals.ForceSetActiveVessel(vesselProto.vesselRef);

                if (vesselProto.vesselRef.GetCrewCount() > 0)
                {
                    foreach (var part in vesselProto.vesselRef.Parts)
                    {
                        if (part.protoModuleCrew.Any())
                        {
                            //Serialize to avoid modifying the collection
                            var crewMembers = part.protoModuleCrew.ToArray();
                            foreach (var crew in crewMembers)
                            {
                                part.RemoveCrew(crew);
                                part.AddCrew(crew);
                            }
                        }
                    }

                    vesselProto.vesselRef.SpawnCrew();
                    if (KerbalPortraitGallery.Instance)
                    {
                        KerbalPortraitGallery.Instance.SetActivePortraitsForVessel(FlightGlobals.ActiveVessel);
                    }
                }
            }

            return(true);
        }
Пример #21
0
        public Vessel Spawn()
        {
            if (loaded)
            {
                if (protoVessel.vesselRef == null)
                {
                    loaded = false;
                }
                else
                {
                    Debugger.Log(name + " is already loaded.");
                    return(protoVessel.vesselRef);
                }
            }
            if (WarpDrive.seedString != seed)
            {
                Debugger.LogError("Vessel " + name + " seed " + seed + " does not match Warp Drive seed " + WarpDrive.seedString + "!");
                // Don't spawn us
                return(null);
            }
            if (id == Guid.Empty)
            {
                Debugger.LogWarning("Generating new GUID for " + name + ".");
                id = Guid.NewGuid();
                protoVessel.vesselID = id;
            }
            // We have a valid seed, make sure we're unique
            Dictionary <Guid, Vessel> currentGuidLookup = null;

            if (seedGUIDLookup.ContainsKey(seed))
            {
                currentGuidLookup = seedGUIDLookup [seed];
            }
            else
            {
                currentGuidLookup = new Dictionary <Guid, Vessel> ();
            }
            if (currentGuidLookup.ContainsKey(id) && currentGuidLookup [id] != null)
            {
                loaded = true;
                Debugger.Log(name + " already exists in " + seed + ".");
                // Already spawned in this seed
                return(currentGuidLookup [id]);
            }
            // See if we're already in the loaded game
            // This shouldn't happen, but we want to make absolutely sure so we don't have duplicates
            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                if (vessel.id == id)
                {
                    // Should not happen
                    Debugger.LogWarning("Tried to spawn duplicate vessel! Name: " + vessel.name);
                    currentGuidLookup.Add(id, vessel);
                    seedGUIDLookup [seed] = currentGuidLookup;
                    loaded = true;
                    return(vessel);
                }
            }
            Debugger.Log("Spawning vessel " + name);
            protoVessel.Load(HighLogic.CurrentGame.flightState);
            GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef);
            currentGuidLookup [id] = protoVessel.vesselRef;
            seedGUIDLookup [seed]  = currentGuidLookup;
            loaded = protoVessel.vesselRef != null;
            if (!loaded)
            {
                Debugger.LogError("Could not load " + protoVessel.vesselName + "!");
            }
            return(protoVessel.vesselRef);
        }
Пример #22
0
        //Also called from QuickSaveLoader
        public void LoadVessel(ConfigNode vesselNode)
        {
            if (vesselNode != null)
            {
                //Fix crew value numbers to Kerbal Names
                bool kerbalsDodged = DodgeVesselCrewValues(vesselNode);

                //Fix the "cannot control actiongroups bug" by dodging the last used time.
                DodgeVesselActionGroups(vesselNode);

                //Can be used for debugging incoming vessel config nodes.
                //vesselNode.Save(Path.Combine(KSPUtil.ApplicationRootPath, Path.Combine("DMP-RX", Planetarium.GetUniversalTime() + ".txt")));
                ProtoVessel currentProto = new ProtoVessel(vesselNode, HighLogic.CurrentGame);

                if (kerbalsDodged && (NetworkWorker.fetch.state == ClientState.STARTING) && !LockSystem.fetch.LockExists("control-" + currentProto.vesselID) && !LockSystem.fetch.LockExists("update-" + currentProto.vesselID))
                {
                    DarkLog.Debug("Sending kerbal-dodged vessel " + currentProto.vesselID + ", name: " + currentProto.vesselName);
                    NetworkWorker.fetch.SendVesselProtoMessage(currentProto, false, false);
                    foreach (ProtoPartSnapshot pps in currentProto.protoPartSnapshots)
                    {
                        if (pps.protoModuleCrew != null)
                        {
                            foreach (ProtoCrewMember pcm in pps.protoModuleCrew)
                            {
                                if (pcm != null)
                                {
                                    NetworkWorker.fetch.SendKerbalProtoMessage(pcm);
                                }
                            }
                        }
                    }
                }

                if (currentProto != null)
                {
                    //Skip already loaded EVA's
                    if ((currentProto.vesselType == VesselType.EVA) && (FlightGlobals.fetch.vessels.Find(v => v.id == currentProto.vesselID) != null))
                    {
                        return;
                    }

                    //Register asteroids from other players
                    if (currentProto.vesselType == VesselType.SpaceObject)
                    {
                        if (currentProto.protoPartSnapshots != null)
                        {
                            if (currentProto.protoPartSnapshots.Count == 1)
                            {
                                if (currentProto.protoPartSnapshots[0].partName == "PotatoRoid")
                                {
                                    DarkLog.Debug("Registering remote server asteroid");
                                    AsteroidWorker.fetch.RegisterServerAsteroid(currentProto.vesselID.ToString());
                                }
                            }
                        }
                    }

                    //Skip vessels that try to load in the safety bubble
                    if (isProtoVesselInSafetyBubble(currentProto))
                    {
                        DarkLog.Debug("Skipped loading protovessel " + currentProto.vesselID.ToString() + ", name: " + currentProto.vesselName + " because it is inside the safety bubble");
                        return;
                    }

                    //Skip flying vessel that are too far away
                    bool usingHackyAtmoLoad = false;
                    if (currentProto.situation == Vessel.Situations.FLYING)
                    {
                        DarkLog.Debug("Got a flying update for " + currentProto.vesselID + ", name: " + currentProto.vesselName);
                        if (currentProto.orbitSnapShot == null)
                        {
                            DarkLog.Debug("Skipping flying vessel load - Protovessel does not have an orbit snapshot");
                            return;
                        }
                        CelestialBody updateBody = FlightGlobals.fetch.bodies[currentProto.orbitSnapShot.ReferenceBodyIndex];
                        if (updateBody == null)
                        {
                            DarkLog.Debug("Skipping flying vessel load - Could not find celestial body index " + currentProto.orbitSnapShot.ReferenceBodyIndex);
                            return;
                        }
                        bool willGetKilledInAtmo = false;
                        if (updateBody.atmosphere)
                        {
                            double atmoPressure = updateBody.staticPressureASL * Math.Pow(Math.E, ((-currentProto.altitude) / (updateBody.atmosphereScaleHeight * 1000)));
                            //KSP magic cut off limit for killing vessels. Works out to be ~23km on kerbin.
                            if (atmoPressure > 0.01f)
                            {
                                willGetKilledInAtmo = true;
                            }
                        }
                        if (willGetKilledInAtmo)
                        {
                            if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                            {
                                if ((FlightGlobals.fetch.vessels.Find(v => v.id == currentProto.vesselID) != null) && vesselPartCount.ContainsKey(currentProto.vesselID.ToString()) ? currentProto.protoPartSnapshots.Count == vesselPartCount[currentProto.vesselID.ToString()] : false)
                                {
                                    DarkLog.Debug("Skipping flying vessel load - Vessel has the same part count");
                                    return;
                                }
                                if (FlightGlobals.fetch.activeVessel == null)
                                {
                                    DarkLog.Debug("Skipping flying vessel load - We do not have an active vessel");
                                    return;
                                }
                                if (FlightGlobals.fetch.activeVessel.mainBody != updateBody)
                                {
                                    DarkLog.Debug("Skipping flying vessel load - We are on a different celestial body");
                                    return;
                                }
                                Vector3d ourPos = FlightGlobals.fetch.activeVessel.mainBody.GetWorldSurfacePosition(FlightGlobals.fetch.activeVessel.latitude, FlightGlobals.fetch.activeVessel.longitude, FlightGlobals.fetch.activeVessel.altitude);
                                Vector3d protoPos = updateBody.GetWorldSurfacePosition(currentProto.latitude, currentProto.longitude, currentProto.altitude);
                                double distance = Vector3d.Distance(ourPos, protoPos);
                                //We'll load the vessel if possible
                                if (distance > Vessel.loadDistance)
                                {
                                    DarkLog.Debug("Skipping flying vessel load - We are not close enough, distance: " + distance);
                                    return;
                                }
                                else
                                {
                                    DarkLog.Debug("Enabling FLYING vessel load!");
                                    //If the vessel is landed it won't be killed by the atmosphere
                                    currentProto.landed = true;
                                    usingHackyAtmoLoad = true;
                                }
                            }
                            else
                            {
                                DarkLog.Debug("Skipping flying vessel load - We cannot load vessels that will get killed in atmosphere while not in flight");
                                return;
                            }
                        }
                    }

                    RegisterServerVessel(currentProto.vesselID.ToString());
                    DarkLog.Debug("Loading " + currentProto.vesselID + ", name: " + currentProto.vesselName + ", type: " + currentProto.vesselType);

                    foreach (ProtoPartSnapshot part in currentProto.protoPartSnapshots)
                    {
                        //This line doesn't actually do anything useful, but if you get this reference, you're officially the most geeky person darklight knows.
                        part.temperature = ((part.temperature + 273.15f) * 0.8f) - 273.15f;

                        //Fix up flag URLS.
                        if (part.flagURL.Length != 0)
                        {
                            string flagFile = Path.Combine(Path.Combine(KSPUtil.ApplicationRootPath, "GameData"), part.flagURL + ".png");
                            if (!File.Exists(flagFile))
                            {
                                DarkLog.Debug("Flag '" + part.flagURL + "' doesn't exist, setting to default!");
                                part.flagURL = "Squad/Flags/default";
                            }
                        }
                    }

                    bool wasActive = false;
                    bool wasTarget = false;

                    if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                    {
                        if (FlightGlobals.fetch.VesselTarget != null ? FlightGlobals.fetch.VesselTarget.GetVessel() != null : false)
                        {
                            wasTarget = FlightGlobals.fetch.VesselTarget.GetVessel().id == currentProto.vesselID;
                        }
                        if (wasTarget)
                        {
                            DarkLog.Debug("ProtoVessel update for target vessel!");
                        }
                        wasActive = (FlightGlobals.fetch.activeVessel != null) ? (FlightGlobals.fetch.activeVessel.id == currentProto.vesselID) : false;
                    }

                    for (int vesselID = FlightGlobals.fetch.vessels.Count - 1; vesselID >= 0; vesselID--)
                    {
                        Vessel oldVessel = FlightGlobals.fetch.vessels[vesselID];
                        if (oldVessel.id.ToString() == currentProto.vesselID.ToString())
                        {
                            //Don't replace the vessel if it's unpacked, not landed, close to the ground, and has the same amount of parts.
                            double hft = oldVessel.GetHeightFromTerrain();
                            if (oldVessel.loaded && !oldVessel.packed && !oldVessel.Landed && (hft != -1) && (hft < 1000) && (currentProto.protoPartSnapshots.Count == oldVessel.parts.Count))
                            {
                                DarkLog.Debug("Skipped loading protovessel " + currentProto.vesselID.ToString() + " because it is flying close to the ground and may get destroyed");
                                return;
                            }
                            //Don't kill the active vessel - Kill it after we switch.
                            //Killing the active vessel causes all sorts of crazy problems.
                            if (wasActive)
                            {
                                delayKillVessels.Add(oldVessel);
                            }
                            else
                            {
                                /*
                                 * Sorry guys - KSP's protovessel positioning is not as accurate as it could be.
                                 *
                                 * The loading vessel needs to come off rails in order for the error to be corrected,
                                 * but taking it off rails will allow the vessel to collide with others while it's in the incorrect spot for that fixed update.
                                 *
                                 * If the vessel is the selected target, close (unpacked), and has the same number of parts, we'll skip the protovessel load.
                                 */

                                if (wasTarget && !oldVessel.LandedOrSplashed && oldVessel.loaded && !oldVessel.packed && (oldVessel.parts.Count == currentProto.protoPartSnapshots.Count))
                                {

                                    DarkLog.Debug("Skipping loading protovessel " + currentProto.vesselID.ToString() + " because it is the selected target and may crash into us");
                                    return;
                                }

                                KillVessel(oldVessel);
                            }
                        }
                    }

                    vesselPartCount[currentProto.vesselID.ToString()] = currentProto.protoPartSnapshots.Count;
                    serverVesselsProtoUpdate[currentProto.vesselID.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                    lastLoadVessel[currentProto.vesselID.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                    currentProto.Load(HighLogic.CurrentGame.flightState);

                    if (currentProto.vesselRef != null)
                    {
                        if (usingHackyAtmoLoad)
                        {
                            //Dodge unpack/pack distances
                            currentProto.vesselRef.distanceUnpackThreshold = Vessel.loadDistance - 300;
                            currentProto.vesselRef.distanceLandedUnpackThreshold = Vessel.loadDistance - 300;
                            currentProto.vesselRef.distancePackThreshold = Vessel.loadDistance - 100;
                            currentProto.vesselRef.distanceLandedPackThreshold = Vessel.loadDistance - 100;
                            HackyFlyingVesselLoad hfvl = new HackyFlyingVesselLoad();
                            hfvl.flyingVessel = currentProto.vesselRef;
                            hfvl.loadTime = UnityEngine.Time.realtimeSinceStartup;
                            loadingFlyingVessels.Add(hfvl);
                        }

                        if (wasActive)
                        {
                            DarkLog.Debug("ProtoVessel update for active vessel!");
                            try
                            {
                                OrbitPhysicsManager.HoldVesselUnpack(5);
                                FlightGlobals.fetch.activeVessel.GoOnRails();
                                //Put our vessel on rails so we don't collide with the new copy
                            }
                            catch
                            {
                                DarkLog.Debug("WARNING: Something very bad happened trying to replace the vessel, skipping update!");
                                return;
                            }
                            newActiveVessel = currentProto.vesselRef;
                        }
                        if (wasTarget)
                        {
                            DarkLog.Debug("Set docking target");
                            FlightGlobals.fetch.SetVesselTarget(currentProto.vesselRef);
                        }
                        DarkLog.Debug("Protovessel Loaded");
                    }
                    else
                    {
                        DarkLog.Debug("Protovessel " + currentProto.vesselID + " failed to create a vessel!");
                    }
                }
                else
                {
                    DarkLog.Debug("protoVessel is null!");
                }
            }
            else
            {
                DarkLog.Debug("vesselNode is null!");
            }
        }
Пример #23
0
            /// <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();
            }
Пример #24
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel vesselProto, bool forceReload)
        {
            if (HighLogic.CurrentGame?.flightState == null)
            {
                return(false);
            }

            var reloadingOwnVessel = FlightGlobals.ActiveVessel && vesselProto.vesselID == FlightGlobals.ActiveVessel.id;

            //In case the vessel exists, silently remove them from unity and recreate it again
            var existingVessel = FlightGlobals.FindVessel(vesselProto.vesselID);

            if (existingVessel != null)
            {
                if (existingVessel.Parts.Count == vesselProto.protoPartSnapshots.Count && !forceReload)
                {
                    return(true);
                }

                LunaLog.Log($"[LMP]: Reloading vessel {vesselProto.vesselID}");
                if (reloadingOwnVessel)
                {
                    existingVessel.RemoveAllCrew();
                }

                FlightGlobals.RemoveVessel(existingVessel);
                foreach (var part in existingVessel.parts)
                {
                    Object.Destroy(part.gameObject);
                }
                Object.Destroy(existingVessel.gameObject);
            }
            else
            {
                LunaLog.Log($"[LMP]: Loading vessel {vesselProto.vesselID}");
            }

            vesselProto.Load(HighLogic.CurrentGame.flightState);
            if (vesselProto.vesselRef == null)
            {
                LunaLog.Log($"[LMP]: Protovessel {vesselProto.vesselID} failed to create a vessel!");
                return(false);
            }

            VesselPositionSystem.Singleton.ForceUpdateVesselPosition(vesselProto.vesselRef.id);

            vesselProto.vesselRef.protoVessel = vesselProto;
            if (vesselProto.vesselRef.isEVA)
            {
                var evaModule = vesselProto.vesselRef.FindPartModuleImplementing <KerbalEVA>();
                if (evaModule != null && evaModule.fsm != null && !evaModule.fsm.Started)
                {
                    evaModule.fsm?.StartFSM("Idle (Grounded)");
                }
                vesselProto.vesselRef.GoOnRails();
            }

            if (vesselProto.vesselRef.situation > Vessel.Situations.PRELAUNCH)
            {
                vesselProto.vesselRef.orbitDriver.updateFromParameters();
            }

            if (double.IsNaN(vesselProto.vesselRef.orbitDriver.pos.x))
            {
                LunaLog.Log($"[LMP]: Protovessel {vesselProto.vesselID} has an invalid orbit");
                return(false);
            }

            if (reloadingOwnVessel)
            {
                vesselProto.vesselRef.Load();
                vesselProto.vesselRef.RebuildCrewList();

                //Do not do the setting of the active vessel manually, too many systems are dependant of the events triggered by KSP
                FlightGlobals.ForceSetActiveVessel(vesselProto.vesselRef);

                vesselProto.vesselRef.SpawnCrew();
                foreach (var crew in vesselProto.vesselRef.GetVesselCrew())
                {
                    if (crew.KerbalRef)
                    {
                        crew.KerbalRef.state = Kerbal.States.ALIVE;
                    }
                }

                CoroutineUtil.StartDelayedRoutine("ReloadOwnVessel", () =>
                {
                    if (KerbalPortraitGallery.Instance.ActiveCrew.Count == 0)
                    {
                        FlightGlobals.ActiveVessel.SpawnCrew();
                        foreach (var kerbal in KerbalPortraitGallery.Instance.ActiveCrew)
                        {
                            kerbal.state = Kerbal.States.ALIVE;
                        }
                        KerbalPortraitGallery.Instance.StartRefresh(FlightGlobals.ActiveVessel);
                    }
                }, 0.5f);
            }

            return(true);
        }
Пример #25
0
        //Also called from QuickSaveLoader
        public void LoadVessel(ConfigNode vesselNode)
        {
            if (vesselNode != null)
            {
                //Fix the kerbals (Tracking station bug)
                checkProtoNodeCrew(ref vesselNode);

                //Can be used for debugging incoming vessel config nodes.
                //vesselNode.Save(Path.Combine(KSPUtil.ApplicationRootPath, Path.Combine("DMP-RX", Planetarium.GetUniversalTime() + ".txt")));
                ProtoVessel currentProto = new ProtoVessel(vesselNode, HighLogic.CurrentGame);
                if (currentProto != null)
                {
                    if (currentProto.vesselType == VesselType.SpaceObject)
                    {
                        if (currentProto.protoPartSnapshots != null)
                        {
                            if (currentProto.protoPartSnapshots.Count == 1)
                            {
                                if (currentProto.protoPartSnapshots[0].partName == "PotatoRoid")
                                {
                                    DarkLog.Debug("Registering remote server asteroid");
                                    AsteroidWorker.fetch.RegisterServerAsteroid(currentProto.vesselID.ToString());
                                }
                            }
                        }
                    }

                    if (isProtoVesselInSafetyBubble(currentProto))
                    {
                        DarkLog.Debug("Removing protovessel " + currentProto.vesselID.ToString() + ", name: " + currentProto.vesselName + " from server - In safety bubble!");
                        NetworkWorker.fetch.SendVesselRemove(currentProto.vesselID.ToString(), false);
                        return;
                    }
                    RegisterServerVessel(currentProto.vesselID.ToString());
                    DarkLog.Debug("Loading " + currentProto.vesselID + ", name: " + currentProto.vesselName + ", type: " + currentProto.vesselType);

                    foreach (ProtoPartSnapshot part in currentProto.protoPartSnapshots)
                    {
                        //This line doesn't actually do anything useful, but if you get this reference, you're officially the most geeky person darklight knows.
                        part.temperature = ((part.temperature + 273.15f) * 0.8f) - 273.15f;

                        //Fix up flag URLS.
                        if (part.flagURL.Length != 0)
                        {
                            string flagFile = Path.Combine(Path.Combine(KSPUtil.ApplicationRootPath, "GameData"), part.flagURL + ".png");
                            if (!File.Exists(flagFile))
                            {
                                DarkLog.Debug("Flag '" + part.flagURL + "' doesn't exist, setting to default!");
                                part.flagURL = "Squad/Flags/default";
                            }
                        }
                    }

                    bool wasActive = false;
                    bool wasTarget = false;

                    if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                    {
                        if (FlightGlobals.fetch.VesselTarget != null ? FlightGlobals.fetch.VesselTarget.GetVessel() != null : false)
                        {
                            wasTarget = FlightGlobals.fetch.VesselTarget.GetVessel().id == currentProto.vesselID;
                        }
                        if (wasTarget)
                        {
                            DarkLog.Debug("ProtoVessel update for target vessel!");
                        }
                        wasActive = (FlightGlobals.ActiveVessel != null) ? (FlightGlobals.ActiveVessel.id == currentProto.vesselID) : false;
                        if (wasActive)
                        {
                            DarkLog.Debug("ProtoVessel update for active vessel!");
                            try
                            {
                                OrbitPhysicsManager.HoldVesselUnpack(5);
                            }
                            catch
                            {
                                //Don't care.
                            }
                            FlightGlobals.fetch.activeVessel.MakeInactive();
                        }
                    }

                    for (int vesselID = FlightGlobals.fetch.vessels.Count - 1; vesselID >= 0; vesselID--)
                    {
                        Vessel oldVessel = FlightGlobals.fetch.vessels[vesselID];
                        if (oldVessel.id.ToString() == currentProto.vesselID.ToString())
                        {
                            KillVessel(oldVessel);
                        }
                    }

                    serverVesselsProtoUpdate[currentProto.vesselID.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                    currentProto.Load(HighLogic.CurrentGame.flightState);

                    if (currentProto.vesselRef != null)
                    {
                        UpdatePackDistance(currentProto.vesselRef.id.ToString());

                        if (wasActive)
                        {
                            DarkLog.Debug("Set active vessel");
                            switchActiveVesselOnNextUpdate = currentProto.vesselRef;
                        }
                        if (wasTarget)
                        {
                            DarkLog.Debug("Set docking target");
                            FlightGlobals.fetch.SetVesselTarget(currentProto.vesselRef);
                        }
                        DarkLog.Debug("Protovessel Loaded");
                    }
                    else
                    {
                        DarkLog.Debug("Protovessel " + currentProto.vesselID + " failed to create a vessel!");
                    }
                }
                else
                {
                    DarkLog.Debug("protoVessel is null!");
                }
            }
            else
            {
                DarkLog.Debug("vesselNode is null!");
            }
        }
Пример #26
0
        // Spawn the actual asteroid
        public void SpawnAsteroid(Asteroid asteroid, uint seed)
        {
            // Create Default Orbit
            Orbit         orbit = null;
            CelestialBody body  = null;

            // Select Orbit Type
            int type = Random.Range(0, 3);

            if (type == 0 && asteroid.location.around.Count != 0)
            {
                // Around
                IEnumerable <Location.AroundLoader> arounds = GetProbabilityList(asteroid.location.around, asteroid.location.around.Select(a => a.probability.value));
                Location.AroundLoader around = arounds.ElementAt(Random.Range(0, arounds.Count()));
                body = PSystemManager.Instance.localBodies.Find(b => b.name == around.body);
                if (!body)
                {
                    return;
                }
                if (around.reached && !ReachedBody(body))
                {
                    return;
                }
                orbit = new Orbit();
                orbit.referenceBody       = body;
                orbit.eccentricity        = around.eccentricity;
                orbit.semiMajorAxis       = around.semiMajorAxis;
                orbit.inclination         = around.inclination;
                orbit.LAN                 = around.longitudeOfAscendingNode;
                orbit.argumentOfPeriapsis = around.argumentOfPeriapsis;
                orbit.meanAnomalyAtEpoch  = around.meanAnomalyAtEpoch;
                orbit.epoch               = around.epoch;
                orbit.Init();
            }
            else if (type == 1 && asteroid.location.nearby.Count != 0)
            {
                // Nearby
                IEnumerable <Location.NearbyLoader> nearbys = GetProbabilityList(asteroid.location.nearby, asteroid.location.nearby.Select(a => a.probability.value));
                Location.NearbyLoader nearby = nearbys.ElementAt(Random.Range(0, nearbys.Count()));
                body = PSystemManager.Instance.localBodies.Find(b => b.name == nearby.body);
                if (!body)
                {
                    return;
                }
                if (nearby.reached && !ReachedBody(body))
                {
                    return;
                }
                orbit = new Orbit();
                orbit.eccentricity        = body.orbit.eccentricity + nearby.eccentricity;
                orbit.semiMajorAxis       = body.orbit.semiMajorAxis * nearby.semiMajorAxis;
                orbit.inclination         = body.orbit.inclination + nearby.inclination;
                orbit.LAN                 = body.orbit.LAN * nearby.longitudeOfAscendingNode;
                orbit.argumentOfPeriapsis = body.orbit.argumentOfPeriapsis * nearby.argumentOfPeriapsis;
                orbit.meanAnomalyAtEpoch  = body.orbit.meanAnomalyAtEpoch * nearby.meanAnomalyAtEpoch;
                orbit.epoch               = body.orbit.epoch;
                orbit.referenceBody       = body.orbit.referenceBody;
                orbit.Init();
            }
            else if (type == 2 && asteroid.location.flyby.Count != 0)
            {
                // Flyby
                IEnumerable <Location.FlybyLoader> flybys = GetProbabilityList(asteroid.location.flyby, asteroid.location.flyby.Select(a => a.probability.value));
                Location.FlybyLoader flyby = flybys.ElementAt(Random.Range(0, flybys.Count()));
                body = PSystemManager.Instance.localBodies.Find(b => b.name == flyby.body);
                if (!body)
                {
                    return;
                }
                if (flyby.reached && !ReachedBody(body))
                {
                    return;
                }
                orbit = Orbit.CreateRandomOrbitFlyBy(body, Random.Range(flyby.minDuration, flyby.maxDuration));
            }

            // Check
            if (orbit == null)
            {
                Debug.Log("[Kopernicus]: No new objects this time. (Probablility is " + asteroid.probability.value + "%)");
                return;
            }

            // Name
            string name = DiscoverableObjectsUtil.GenerateAsteroidName();

            // Lifetime
            double lifetime    = Random.Range(asteroid.minUntrackedLifetime, asteroid.maxUntrackedLifetime) * 24d * 60d * 60d;
            double maxLifetime = asteroid.maxUntrackedLifetime * 24d * 60d * 60d;

            // Size
            UntrackedObjectClass size = (UntrackedObjectClass)((int)(asteroid.size.curve.Evaluate(Random.Range(0f, 1f)) * Enum.GetNames(typeof(UntrackedObjectClass)).Length));

            // Spawn
            ConfigNode vessel = ProtoVessel.CreateVesselNode(
                name,
                VesselType.SpaceObject,
                orbit,
                0,
                new[]
            {
                ProtoVessel.CreatePartNode(
                    "PotatoRoid",
                    seed,
                    new ProtoCrewMember[0]
                    )
            },
                new ConfigNode("ACTIONGROUPS"),
                ProtoVessel.CreateDiscoveryNode(
                    DiscoveryLevels.Presence,
                    size,
                    lifetime,
                    maxLifetime
                    )
                );

            OverrideNode(ref vessel, asteroid.vessel);
            ProtoVessel protoVessel = new ProtoVessel(vessel, HighLogic.CurrentGame);

            if (asteroid.uniqueName && FlightGlobals.Vessels.Count(v => v.vesselName == protoVessel.vesselName) != 0)
            {
                return;
            }
            protoVessel.Load(HighLogic.CurrentGame.flightState);
            GameEvents.onNewVesselCreated.Fire(protoVessel.vesselRef);
            Debug.Log("[Kopernicus]: New object found near " + body.name + ": " + protoVessel.vesselName + "!");
        }
Пример #27
0
        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 '{0}'", 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 '{0}' (usually this means the file could not be found).", vesselData.craftURL);
                        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;

                        p.UpdateOrgPosAndRot(shipConstruct.parts[0]);
                    }

                    // Estimate an object class, numbers are based on the code that generate objects.
                    float size = shipConstruct.shipSize.magnitude / 2.0f;
                    if (size < 4.05f)
                    {
                        sizeClass = UntrackedObjectClass.A;
                    }
                    else if (size < 6.75f)
                    {
                        sizeClass = UntrackedObjectClass.B;
                    }
                    else if (size < 11.25f)
                    {
                        sizeClass = UntrackedObjectClass.C;
                    }
                    else if (size < 18.25f)
                    {
                        sizeClass = UntrackedObjectClass.D;
                    }
                    else if (size < 31.25f || (Versioning.version_major <= 1 && Versioning.version_minor <= 10))
                    {
                        sizeClass = UntrackedObjectClass.E;
                    }
                    // Only for KSP 1.10+
                    else if (size < 52.125f)
                    {
                        sizeClass = UntrackedObjectClass.F;
                    }
                    else if (size < 86.875f)
                    {
                        sizeClass = UntrackedObjectClass.G;
                    }
                    else if (size < 144.75f)
                    {
                        sizeClass = UntrackedObjectClass.H;
                    }
                    else
                    {
                        sizeClass = UntrackedObjectClass.I;
                    }

                    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.ChangeName(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 '{0}'.  Perhaps there's no room?", vesselData.name);
                            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)
                    {
                        p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                        p.vessel   = dummyVessel;
                        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
                    foreach (Part p in shipConstruct.parts)
                    {
                        GameObject.Destroy(p.gameObject);
                    }
                    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
                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(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);

                // 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);
        }
Пример #28
0
        private void addRemoteVessel(ProtoVessel protovessel, Guid vessel_id, KMPVesselUpdate update = null, double distance = 501d)
        {
            if (isInFlight && vessel_id == FlightGlobals.ActiveVessel.id)
            {
                KMPClientMain.DebugLog("Attempted to update controlled vessel!");
                return;
            }
            KMPClientMain.DebugLog("addRemoteVessel");
            Vector3 newWorldPos = Vector3.zero, newOrbitVel = Vector3.zero;
            bool setTarget = false, wasLoaded = false;
            try
            {
                //Ensure this vessel isn't already loaded
                Vessel oldVessel = FlightGlobals.Vessels.Find (v => v.id == vessel_id);
                if (oldVessel != null) {
                    KMPClientMain.DebugLog("killing extant vessel");
                    wasLoaded = oldVessel.loaded;
                    if (protovessel.vesselType == VesselType.EVA && wasLoaded)
                    {
                        return; //Don't touch EVAs here
                    }
                    else
                    {
                        setTarget = FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel().id == vessel_id;
                        if (oldVessel.loaded)
                        {
                            newWorldPos = oldVessel.transform.position;
                            if (oldVessel.altitude > 10000d)
                                newOrbitVel = oldVessel.GetObtVelocity();
                        }
                        oldVessel.Die();
                    }
                }

                if (protovessel.vesselType != VesselType.EVA && serverVessels_Parts.ContainsKey(vessel_id))
                {
                    KMPClientMain.DebugLog("killing known precursor vessels");
                    foreach (Part part in serverVessels_Parts[vessel_id])
                    {
                        try { if (!part.vessel.isEVA) part.vessel.Die(); } catch {}
                    }
                }
            } catch {}
            try
            {
                if ((protovessel.vesselType != VesselType.Debris && protovessel.vesselType != VesselType.Unknown) && protovessel.situation == Vessel.Situations.SUB_ORBITAL && protovessel.altitude < 25d)
                {
                    //Land flags, vessels and EVAs that are on sub-orbital trajectory
                    KMPClientMain.DebugLog("Placing sub-orbital protovessel on surface");
                    protovessel.situation = Vessel.Situations.LANDED;
                    protovessel.landed = true;
                    if (protovessel.vesselType == VesselType.Flag) protovessel.height = -1;
                }
                //Don't bother with suborbital debris
                else if (protovessel.vesselType == VesselType.Debris && protovessel.situation == Vessel.Situations.SUB_ORBITAL) return;

                CelestialBody body = null;

                if (update != null)
                {
                    body = FlightGlobals.Bodies.Find(b => b.name == update.bodyName);
                    if (update.situation != Situation.LANDED && update.situation != Situation.SPLASHED)
                    {
                        if (body.atmosphere && body.maxAtmosphereAltitude > protovessel.altitude)
                        {
                            //In-atmo vessel--only load if within visible range
                            if (distance > 500d)
                                return;
                        }
                    }
                }

                if (isInSafetyBubble(protovessel.position, body, protovessel.altitude)) //refuse to load anything too close to the KSC
                {
                    KMPClientMain.DebugLog("Tried to load vessel too close to KSC");
                    return;
                }

                IEnumerator<ProtoCrewMember> crewEnum = HighLogic.CurrentGame.CrewRoster.GetEnumerator();
                int applicants = 0;
                while (crewEnum.MoveNext())
                    if (crewEnum.Current.rosterStatus == ProtoCrewMember.RosterStatus.AVAILABLE) applicants++;

                if (protovessel.GetVesselCrew().Count * 5 > applicants)
                {
                    KMPClientMain.DebugLog("Adding crew applicants");
                    for (int i = 0; i < (protovessel.GetVesselCrew().Count * 5);)
                    {
                        ProtoCrewMember protoCrew = CrewGenerator.RandomCrewMemberPrototype();
                        if (!HighLogic.CurrentGame.CrewRoster.ExistsInRoster(protoCrew.name))
                        {
                            HighLogic.CurrentGame.CrewRoster.AddCrewMember(protoCrew);
                            i++;
                        }
                    }
                }
                if (vessels.ContainsKey(vessel_id.ToString()) && (!serverVessels_LoadDelay.ContainsKey(vessel_id) || (serverVessels_LoadDelay.ContainsKey(vessel_id) ? serverVessels_LoadDelay[vessel_id] < UnityEngine.Time.realtimeSinceStartup : false)))
                {
                    protovessel.Load(HighLogic.CurrentGame.flightState);
                    Vessel created_vessel = protovessel.vesselRef;
                    if (created_vessel != null)
                    {
                        try
                        {
                            OrbitPhysicsManager.HoldVesselUnpack(1);
                        }
                        catch (NullReferenceException)
                        {
                        }
                        if (!created_vessel.loaded) created_vessel.Load();
                        KMPClientMain.DebugLog(created_vessel.id.ToString() + " initializing: ProtoParts=" + protovessel.protoPartSnapshots.Count+ ",Parts=" + created_vessel.Parts.Count + ",Sit=" + created_vessel.situation.ToString() + ",type=" + created_vessel.vesselType + ",alt=" + protovessel.altitude);

                        vessels[vessel_id.ToString()].vessel.vesselRef = created_vessel;
                        serverVessels_PartCounts[vessel_id] = created_vessel.Parts.Count;
                        serverVessels_Parts[vessel_id] = new List<Part>();
                        serverVessels_Parts[vessel_id].AddRange(created_vessel.Parts);

                        bool distanceBlocksUnload = false;

                        if (created_vessel.vesselType != VesselType.Flag && created_vessel.vesselType != VesselType.EVA)
                        {
                            foreach (Part part in created_vessel.Parts)
                            {
                                part.OnLoad();
                                part.OnJustAboutToBeDestroyed += checkRemoteVesselIntegrity;
                                part.explosionPotential = 0;
                                part.terrainCollider = new PQS_PartCollider();
                                part.terrainCollider.part = part;
                                part.terrainCollider.useVelocityCollider = false;
                                part.terrainCollider.useGravityCollider = false;
                                part.breakingForce = float.MaxValue;
                                part.breakingTorque = float.MaxValue;
                            }
                            if (update != null && update.bodyName == FlightGlobals.ActiveVessel.mainBody.name)
                            {
                                KMPClientMain.DebugLog("update included");

                                //Update rotation

                                created_vessel.SetRotation(new Quaternion(update.rot[0],update.rot[1],update.rot[2],update.rot[3]));

                                if (update.relTime == RelativeTime.PRESENT)
                                {
                                    if (newWorldPos != Vector3.zero)
                                    {
                                        KMPClientMain.DebugLog("repositioning");
                                        created_vessel.transform.position = newWorldPos;
                                        if (wasLoaded) distanceBlocksUnload = Vector3.Distance(created_vessel.transform.position,FlightGlobals.ActiveVessel.transform.position) < 2000f;
                                    }
                                    if (newOrbitVel != Vector3.zero)
                                    {
                                        KMPClientMain.DebugLog("updating velocity");
                                        created_vessel.ChangeWorldVelocity((-1 * created_vessel.GetObtVelocity()) + newOrbitVel);
                                    }

                                    //Update FlightCtrlState
                                    if (created_vessel.ctrlState == null) created_vessel.ctrlState = new FlightCtrlState();
                                    created_vessel.ctrlState.CopyFrom(update.flightCtrlState.getAsFlightCtrlState(0.75f));
                                }
                                else
                                {
                                    serverVessels_InPresent[update.id] = false;
                                    foreach (Part part in created_vessel.Parts)
                                    {
                                        part.setOpacity(0.3f);
                                    }
                                }
                            }
                        }
                        if (!syncing && !distanceBlocksUnload) //This explicit Unload helps correct the effects of "Can't remove Part (Script) because PartBuoyancy (Script) depends on it" errors and associated NREs seen during rendezvous mode switching, but for unknown reasons it causes problems if active during universe sync
                            created_vessel.Unload();
                        if (setTarget) StartCoroutine(setDockingTarget(created_vessel));
                        KMPClientMain.DebugLog(created_vessel.id.ToString() + " initialized");
                    }
                }
            }
            catch (Exception e)
            {
                KMPClientMain.DebugLog("Error adding remote vessel: " + e.Message + " " + e.StackTrace);
            }
        }
Пример #29
0
        private bool loadVesselForRendezvous(ProtoVessel placeVessel, Vessel targetVessel)
        {
            targetVessel.BackupVessel();

            placeVessel.orbitSnapShot = targetVessel.protoVessel.orbitSnapShot;

            placeVessel.orbitSnapShot.epoch = 0.0;

            tempID = rand.Next(1000000000).ToString();
            //rename any vessels present with "AdministativeDockingName"
            foreach (Vessel ve in FlightGlobals.Vessels)
            {
                if (ve.vesselName == tempID)
                {
                    Vessel NameVessel = null;
                    NameVessel = ve;
                    NameVessel.vesselName = "1";
                }
            }

            placeVessel.vesselID = Guid.NewGuid();

            placeVessel.vesselName = tempID;

            foreach (ProtoPartSnapshot p in placeVessel.protoPartSnapshots)
            {
                if (placeVessel.refTransform == p.flightID)
                {
                    p.flightID = (UInt32)rand.Next(1000000000, 2147483647);
                    placeVessel.refTransform = p.flightID;
                }
                else
                {
                    p.flightID = (UInt32)rand.Next(1000000000, 2147483647);
                }

                if (p.protoModuleCrew != null && p.protoModuleCrew.Count() != 0)
                {
                    List<ProtoCrewMember> cl = p.protoModuleCrew;
                    List<ProtoCrewMember> clc = new List<ProtoCrewMember>(cl);

                    foreach (ProtoCrewMember c in clc)
                    {
                        p.RemoveCrew(c);
                        //print("remove");
                    }
                }
            }

            try
            {
                placeVessel.Load(HighLogic.CurrentGame.flightState);
                return true;
            }
            catch
            {
                //abortArrival();
                //return false;
                return true;
            }
        }