Exemple #1
0
        private ShipConstruct shipConstruct = null; // Only needed to get more info about the template-ship, like its crew-capacity.

        public int GetCrewCapacity()
        {
            int crewCapacity = 0;

            if (HighLogic.LoadedScene == GameScenes.FLIGHT)
            {
                throw new Exception("ShipConstruction.LoadShip cannot be run while in flight");                                             // This would create a new, non-functioning vessel near the current vessel
            }
            try
            {
                if (this.shipConstruct == null)
                {
                    shipConstruct = ShipConstruction.LoadShip(template.filename);
                }
                foreach (Part part in shipConstruct.parts)
                {
                    crewCapacity += part.CrewCapacity;
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] CachedShipTemplate::GetCrewCapacity(): " + e.ToString());
            }
            return(crewCapacity);
        }
Exemple #2
0
        public void SpawnVessel()
        {
            //var allowedSituations = Vessel.Situations.LANDED | Vessel.Situations.PRELAUNCH | Vessel.Situations.SPLASHED;
            //if (allowedSituations != (allowedSituations & FlightGlobals.ActiveVessel.situation))
            //{
            //    throw new Exception(_notLandedErrorText);
            //}

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

            PartUtilities.ConsumeResources(_cachedCostData);

            // Backup the ship config from the VAB/SPH, load the selected .craft file
            //   and restore the cached config from the VAB/SPH
            var constructBak = ShipConstruction.ShipConfig;
            var construct    = ShipConstruction.LoadShip(_selectedCraftFilePath);

            ShipConstruction.ShipConfig = constructBak;

            ShipConstruction.PutShipToGround(construct, transform);
            ShipConstruction.AssembleForLaunch(
                construct,
                vessel.landedAt,
                vessel.displaylandedAt,
                construct.missionFlag,
                HighLogic.CurrentGame,
                new VesselCrewManifest());

            _window.CloseWindow();
        }
Exemple #3
0
        public double GetDryMass()
        {
            double dryMass = 0;

            if (HighLogic.LoadedScene == GameScenes.FLIGHT)
            {
                throw new Exception("ShipConstruction.LoadShip cannot be run while in flight");                                             // This would create a new, non-functioning vessel near the current vessel
            }
            try
            {
                if (this.shipConstruct == null)
                {
                    shipConstruct = ShipConstruction.LoadShip(template.filename);
                }
                foreach (Part part in shipConstruct.parts)
                {
                    dryMass += part.mass - part.resourceMass;
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] CachedShipTemplate::GetDryMass(): " + e.ToString());
            }
            return(dryMass);
        }
Exemple #4
0
        // Creates a new ship with the given parameters for this mission. The code however seems unnecessarily convoluted and
        // error-prone, but there are no better examples available on the internet.
        private void CreateShip()
        {
            try
            {
                // The ShipConstruct-object can only savely exist while not in flight, otherwise it will spam Null-Pointer Exceptions every tick:
                if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                {
                    throw new Exception("unable to run CreateShip while in flight");
                }

                // Load the parts form the saved vessel:
                if (!File.Exists(shipTemplateFilename))
                {
                    throw new Exception("file '" + shipTemplateFilename + "' not found");
                }

                var shipConstruct = ShipConstruction.LoadShip(shipTemplateFilename);

                // Maybe adjust the orbit:
                var vesselHeight = Math.Max(Math.Max(shipConstruct.shipSize.x, shipConstruct.shipSize.y), shipConstruct.shipSize.z);
                if (missionType == MissionType.DEPLOY)
                {
                    // Make sure that there won't be any collisions, when the vessel is created at the given orbit:
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
                }
                else if (missionType == MissionType.CONSTRUCT)
                {
                    // Deploy the new ship next to the space-dock:
                    var spaceDock = TargetVessel.GetVesselById((Guid)targetVesselId);
                    orbit = GUIOrbitEditor.CreateFollowingOrbit(spaceDock.orbit, TargetVessel.GetVesselSize(spaceDock) + vesselHeight);
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit, vesselHeight);
                }
                else
                {
                    throw new Exception("invalid mission-type '" + missionType + "'");
                }

                var game     = FlightDriver.FlightStateCache ?? HighLogic.CurrentGame;
                var profile  = GetProfile();
                var duration = profile.missionDuration;
                AssembleForLaunchUnlanded(shipConstruct, crewToDeliver ?? Enumerable.Empty <string>(), duration, orbit, flagURL, game);
                var newVessel = FlightGlobals.Vessels[FlightGlobals.Vessels.Count - 1];
                newVessel.vesselName = shipName;
                Debug.Log("[KSTS] deployed new ship '" + shipName + "' as '" + newVessel.protoVessel.vesselRef.id + "'");
                ScreenMessages.PostScreenMessage("Vessel '" + shipName + "' deployed"); // Popup message to notify the player

                // Notify other mods about the new vessel:
                GameEvents.onVesselCreate.Fire(newVessel);
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] Mission.CreateShip(): " + e);
            }
        }
Exemple #5
0
        /// <summary>
        /// ////////////////////
        /// </summary>
        protected void BuildContent()
        {
            //	getModList ();
            m_directoriesWithImages = new GUIContent[m_directories.Length];
            for (int i = 0; i < m_directoriesWithImages.Length; ++i)
            {
                m_directoriesWithImages [i] = new GUIContent(m_directories [i], DirectoryImage);
            }
            m_nonMatchingDirectoriesWithImages = new GUIContent[m_nonMatchingDirectories.Length];
            for (int i = 0; i < m_nonMatchingDirectoriesWithImages.Length; ++i)
            {
                m_nonMatchingDirectoriesWithImages [i] = new GUIContent(m_nonMatchingDirectories [i], DirectoryImage);
            }
            m_filesWithImages = new GUIContent[m_files.Length];
            //ShipConstruct ship; // = new ShipConstruct ();
            for (int i = 0; i < m_filesWithImages.Length; ++i)
            {
                                #if false
                //if (i == 0)
                if (m_files [i].Contains(".craft"))
                {
                    string f = m_newDirectory + "/" + m_files [i];
                    Log.Info("f: " + f);
                    if (System.IO.File.Exists(f))
                    {
                        //var configFile = ConfigNode.Load (f);

                        ShipConstruct ship = ShipConstruction.LoadShip(f);

                        ThumbnailHelper.CaptureThumbnail(ship, 256, "tmp", m_files [i] + i.ToString());
                        //ShipConstruction.CaptureThumbnail (ship, "tmp", m_files [i] + "-2-" + i.ToString ());


                        foreach (var p in ship.Parts)
                        {
                            UnityEngine.Object.Destroy(p.gameObject);
                        }

                        //configFile = null;
                        //ship = null;
                    }
                }
                                #endif
                m_filesWithImages [i] = new GUIContent(m_files [i], FileImage);
            }
            m_nonMatchingFilesWithImages = new GUIContent[m_nonMatchingFiles.Length];
            for (int i = 0; i < m_nonMatchingFilesWithImages.Length; ++i)
            {
                m_nonMatchingFilesWithImages [i] = new GUIContent(m_nonMatchingFiles [i], FileImage);
            }
        }
Exemple #6
0
        private void BuildAndLaunchCraft()
        {
            // build craft
            ShipConstruct nship = ShipConstruction.LoadShip(uis.craftfile);

            Vector3 offset = nship.Parts[0].transform.localPosition;

            nship.Parts[0].transform.Translate(-offset);
            string             landedAt = "External Launchpad";
            string             flag     = uis.flagname;
            Game               state    = FlightDriver.FlightStateCache;
            VesselCrewManifest crew     = new VesselCrewManifest();

            ShipConstruction.CreateBackup(nship);
            ShipConstruction.PutShipToGround(nship, GetLanchTransform());

            ShipConstruction.AssembleForLaunch(nship, landedAt, flag, state, crew);

            Vessel vsl = FlightGlobals.Vessels[FlightGlobals.Vessels.Count - 1];

            FlightGlobals.ForceSetActiveVessel(vsl);
            vsl.Landed = false;

            if (kethane_present && !DebugPad)
            {
                UseResources(vsl);
            }

            if (vessel.situation == Vessel.Situations.ORBITING)
            {
                HackStruts(vsl);
                uis.vesselInfo             = new DockedVesselInfo();
                uis.vesselInfo.name        = vsl.vesselName;
                uis.vesselInfo.vesselType  = vsl.vesselType;
                uis.vesselInfo.rootPartUId = vsl.rootPart.flightID;
                vsl.rootPart.Couple(part);
                FlightGlobals.ForceSetActiveVessel(vessel);
            }
            else
            {
                uis.timer    = 3.0f;
                uis.launchee = vsl;
            }

            Staging.beginFlight();
        }
Exemple #7
0
        private void BuildCraft()
        {
            // build craft
            ShipConstruct nship           = ShipConstruction.LoadShip(uifs.craftfile);
            Transform     launchtransform = GetLaunchTransform();

            Vector3 offset = nship.Parts[0].transform.localPosition;

            nship.Parts[0].transform.Translate(-offset);
            Game state = FlightDriver.FlightStateCache;
            VesselCrewManifest crew = new VesselCrewManifest();

            ShipConstruction.CreateBackup(nship);
            ShipConstruction.PutShipToGround(nship, launchtransform);
            ShipConstruction.AssembleForLaunch(nship, uifs.LaunchSiteName, uifs.flagname, state, crew);

            Vessel vsl = FlightGlobals.Vessels[FlightGlobals.Vessels.Count - 1];

            FlightGlobals.ForceSetActiveVessel(vsl);
            vsl.Landed = false;

            HackStruts(vsl);
            uifs.vesselInfo              = new DockedVesselInfo();
            uifs.vesselInfo.name         = vsl.vesselName;
            uifs.vesselInfo.vesselType   = vsl.vesselType;
            uifs.vesselInfo.rootPartUId  = vsl.rootPart.uid;
            uifs.vesselFlightID          = vsl.rootPart.flightID;
            FlightDriver.flightStarted   = true;
            FlightDriver.newShipFlagURL  = uifs.flagname;
            FlightDriver.newShipManifest = crew;
            vsl.state     = Vessel.State.ACTIVE;
            vsl.situation = Vessel.Situations.ORBITING;
            Staging.beginFlight();
            vsl.ResumeStaging();
            Staging.GenerateStagingSequence(vsl.rootPart);
            Staging.RecalculateVesselStaging(vsl);

            FlightGlobals.ForceSetActiveVessel(vessel);
            vsl.rootPart.Couple(part);
            vessel.ResumeStaging();
            Staging.GenerateStagingSequence(vessel.rootPart);
            Staging.RecalculateVesselStaging(vessel);

            Events[("DecoupleVessel")].active = true;
        }
Exemple #8
0
            /// <summary>
            /// Attempt vessel load
            /// </summary>
            /// <param name="_craftFile"></param>
            /// <returns></returns>
            private ShipConstruct LoadVessel(string _craftFile)
            {
                //Get path to vessel
                string BasePath = Environment.CurrentDirectory + PluginPath;
                string path     = BasePath + _craftFile;

                Log.Info("LoadVessel, full path: " + path);
                //Save old ship for later, else player will see it in the VAB
                _OldVabShip = new HideConfigNode(ShipConstruction.ShipConfig);

                //Load craft file
                ShipConstruct _shipConstruct = ShipConstruction.LoadShip(path);

                //Check load
                if (_shipConstruct == null)
                {
                    // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB
                    ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode();
                    Log.Info("vessel not loaded");
                    return(null); //Fail
                }
                return(_shipConstruct);
            }
        protected void CreateVessels()
        {
            if (vesselsCreated)
            {
                return;
            }

            String gameDataDir = KSPUtil.ApplicationRootPath;

            gameDataDir = gameDataDir.Replace("\\", "/");
            if (!gameDataDir.EndsWith("/"))
            {
                gameDataDir += "/";
            }
            gameDataDir += "GameData";

            // Spawn the vessel in the game world
            foreach (VesselData vesselData in vessels)
            {
                LoggingUtil.LogVerbose(this, "Spawning a vessel named '" + vesselData.name + "'");

                // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
                ConfigNode currentShip = ShipConstruction.ShipConfig;

                ShipConstruct shipConstruct = ShipConstruction.LoadShip(gameDataDir + "/" + vesselData.craftURL);
                if (shipConstruct == null)
                {
                    LoggingUtil.LogError(this, "ShipConstruct was null when tried to load '" + vesselData.craftURL +
                                         "' (usually this means the file could not be found).");
                    continue;
                }

                // Restore ShipConstruction ship
                ShipConstruction.ShipConfig = currentShip;

                // Set the name
                if (string.IsNullOrEmpty(vesselData.name))
                {
                    vesselData.name = shipConstruct.shipName;
                }

                // Set some parameters that need to be at the part level
                uint flightId  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                uint missionID = (uint)Guid.NewGuid().GetHashCode();
                uint launchID  = HighLogic.CurrentGame.launchID++;
                foreach (Part p in shipConstruct.parts)
                {
                    p.flightID  = flightId;
                    p.missionID = missionID;
                    p.launchID  = launchID;
                    p.flagURL   = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL;
                }

                // Assign crew to the vessel
                foreach (CrewData cd in vesselData.crew)
                {
                    bool success = false;

                    // Find a seat for the crew
                    Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity);

                    // Add the crew member
                    if (part != null)
                    {
                        // Create the ProtoCrewMember
                        ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned);
                        if (cd.name != null)
                        {
                            crewMember.name = cd.name;
                        }

                        // Add them to the part
                        success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
                    }

                    if (!success)
                    {
                        LoggingUtil.LogWarning(this, "Unable to add crew to vessel named '" + vesselData.name + "'.  Perhaps there's no room?");
                        break;
                    }
                }

                // Set additional info for landed kerbals
                if (vesselData.landed)
                {
                    if (vesselData.altitude == null)
                    {
                        vesselData.altitude = LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body);
                    }

                    Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);

                    vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body);
                    vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime());
                    LoggingUtil.LogDebug(this, "vesselData generated, orbit = " + vesselData.orbit);
                }

                // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
                // We can't use the config nodes from the .craft file, because they are in a
                // slightly different format than those required for a ProtoVessel (seriously
                // Squad?!?).
                ConfigNode  empty       = new ConfigNode();
                ProtoVessel dummyProto  = new ProtoVessel(empty, null);
                Vessel      dummyVessel = new Vessel();
                dummyVessel.parts    = shipConstruct.parts;
                dummyProto.vesselRef = dummyVessel;

                // Create the ProtoPartSnapshot objects and then initialize them
                foreach (Part p in shipConstruct.parts)
                {
                    dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                }
                foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                {
                    p.storePartRefs();
                }

                // Estimate an object class, numbers are based on the in game description of the
                // size classes.
                float size = shipConstruct.shipSize.magnitude / 2.0f;
                UntrackedObjectClass sizeClass;
                if (size < 4.0f)
                {
                    sizeClass = UntrackedObjectClass.A;
                }
                else if (size < 7.0f)
                {
                    sizeClass = UntrackedObjectClass.B;
                }
                else if (size < 12.0f)
                {
                    sizeClass = UntrackedObjectClass.C;
                }
                else if (size < 18.0f)
                {
                    sizeClass = UntrackedObjectClass.D;
                }
                else
                {
                    sizeClass = UntrackedObjectClass.E;
                }

                // Create the ship's parts
                ConfigNode[] partNodes = dummyProto.protoPartSnapshots.Select <ProtoPartSnapshot, ConfigNode>(GetNodeForPart).ToArray();

                // Create additional nodes
                ConfigNode[]    additionalNodes = new ConfigNode[1];
                DiscoveryLevels discoveryLevel  = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
                additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

                // Create the config node representation of the ProtoVessel
                ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes);

                // Additional seetings for a landed vessel
                if (vesselData.landed)
                {
                    // Create the config node representation of the ProtoVessel
                    protoVesselNode.SetValue("sit", Vessel.Situations.LANDED.ToString());
                    protoVesselNode.SetValue("landed", true.ToString());
                    protoVesselNode.SetValue("lat", vesselData.latitude.ToString());
                    protoVesselNode.SetValue("lon", vesselData.longitude.ToString());
                    protoVesselNode.SetValue("alt", vesselData.altitude.ToString());
                    protoVesselNode.SetValue("landedAt", vesselData.body.name);

                    // Figure out the additional heigh to subtract
                    float lowest = float.MaxValue;
                    foreach (Part p in shipConstruct.parts)
                    {
                        foreach (Collider collider in p.GetComponentsInChildren <Collider>())
                        {
                            if (collider.gameObject.layer != 21 && collider.enabled)
                            {
                                lowest = Mathf.Min(lowest, collider.bounds.min.y);
                            }
                        }
                    }

                    // Figure out the surface height and rotation
                    Vector3d   norm     = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude);
                    Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, Vector3.up) *
                                          Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                    protoVesselNode.SetValue("hgt", (shipConstruct.parts[0].localRoot.attPos0.y - lowest).ToString());
                    protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation));
                }

                // Add vessel to the game
                ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);

                // Store the id for later use
                vesselData.id = protoVessel.vesselRef.id;

                // Associate it so that it can be used in contract parameters
                ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef);
            }

            vesselsCreated = true;
        }
Exemple #10
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 '" + vesselData.name + "'");

                // Set additional info for landed vessels
                bool landed = false;
                if (!vesselData.orbiting)
                {
                    landed = true;
                    if (vesselData.altitude == null)
                    {
                        vesselData.altitude = LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body);
                    }

                    Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);

                    vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body);
                    vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime());
                }
                else
                {
                    vesselData.orbit.referenceBody = vesselData.body;
                }

                ConfigNode[]         partNodes;
                UntrackedObjectClass sizeClass;
                ShipConstruct        shipConstruct = null;
                if (!string.IsNullOrEmpty(vesselData.craftURL))
                {
                    // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
                    ConfigNode currentShip = ShipConstruction.ShipConfig;

                    shipConstruct = ShipConstruction.LoadShip(gameDataDir + "/" + vesselData.craftURL);
                    if (shipConstruct == null)
                    {
                        LoggingUtil.LogError(this, "ShipConstruct was null when tried to load '" + vesselData.craftURL +
                                             "' (usually this means the file could not be found).");
                        continue;
                    }

                    // Restore ShipConstruction ship
                    ShipConstruction.ShipConfig = currentShip;

                    // Set the name
                    if (string.IsNullOrEmpty(vesselData.name))
                    {
                        vesselData.name = shipConstruct.shipName;
                    }

                    // Set some parameters that need to be at the part level
                    uint missionID = (uint)Guid.NewGuid().GetHashCode();
                    uint launchID  = HighLogic.CurrentGame.launchID++;
                    foreach (Part p in shipConstruct.parts)
                    {
                        p.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                        p.missionID = missionID;
                        p.launchID  = launchID;
                        p.flagURL   = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL;

                        // Had some issues with this being set to -1 for some ships - can't figure out
                        // why.  End result is the vessel exploding, so let's just set it to a positive
                        // value.
                        p.temperature = 1.0;
                    }

                    foreach (CrewData cd in vesselData.crew)
                    {
                        bool success = false;

                        // Find a seat for the crew
                        Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity);

                        // Add the crew member
                        if (part != null)
                        {
                            // Create the ProtoCrewMember
                            ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned);
                            if (cd.gender != null)
                            {
                                crewMember.gender = cd.gender.Value;
                            }
                            if (cd.name != null)
                            {
                                crewMember.name = cd.name;
                            }

                            // Add them to the part
                            success = part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
                        }

                        if (!success)
                        {
                            LoggingUtil.LogWarning(this, "Unable to add crew to vessel named '" + vesselData.name + "'.  Perhaps there's no room?");
                            break;
                        }
                    }

                    // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
                    // We can't use the config nodes from the .craft file, because they are in a
                    // slightly different format than those required for a ProtoVessel (seriously
                    // Squad?!?).
                    ConfigNode  empty       = new ConfigNode();
                    ProtoVessel dummyProto  = new ProtoVessel(empty, null);
                    Vessel      dummyVessel = new Vessel();
                    dummyVessel.parts    = shipConstruct.parts;
                    dummyProto.vesselRef = dummyVessel;

                    // Create the ProtoPartSnapshot objects and then initialize them
                    foreach (Part p in shipConstruct.parts)
                    {
                        dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                    }
                    foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                    {
                        p.storePartRefs();
                    }

                    // Create the ship's parts
                    partNodes = dummyProto.protoPartSnapshots.Select <ProtoPartSnapshot, ConfigNode>(GetNodeForPart).ToArray();

                    // Estimate an object class, numbers are based on the in game description of the
                    // size classes.
                    float size = shipConstruct.shipSize.magnitude / 2.0f;
                    if (size < 4.0f)
                    {
                        sizeClass = UntrackedObjectClass.A;
                    }
                    else if (size < 7.0f)
                    {
                        sizeClass = UntrackedObjectClass.B;
                    }
                    else if (size < 12.0f)
                    {
                        sizeClass = UntrackedObjectClass.C;
                    }
                    else if (size < 18.0f)
                    {
                        sizeClass = UntrackedObjectClass.D;
                    }
                    else
                    {
                        sizeClass = UntrackedObjectClass.E;
                    }
                }
                else
                {
                    // Create crew member array
                    ProtoCrewMember[] crewArray = new ProtoCrewMember[vesselData.crew.Count];
                    int i = 0;
                    foreach (CrewData cd in vesselData.crew)
                    {
                        // Create the ProtoCrewMember
                        ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned);
                        if (cd.name != null)
                        {
                            crewMember.name = cd.name;
                        }

                        crewArray[i++] = crewMember;
                    }

                    // Create part nodes
                    uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                    partNodes    = new ConfigNode[1];
                    partNodes[0] = ProtoVessel.CreatePartNode(vesselData.craftPart.name, flightId, crewArray);

                    // Default the size class
                    sizeClass = UntrackedObjectClass.A;

                    // Set the name
                    if (string.IsNullOrEmpty(vesselData.name))
                    {
                        vesselData.name = vesselData.craftPart.name;
                    }
                }

                // Create additional nodes
                ConfigNode[]    additionalNodes = new ConfigNode[1];
                DiscoveryLevels discoveryLevel  = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
                additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

                // Create the config node representation of the ProtoVessel
                ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes);

                // Additional seetings for a landed vessel
                if (!vesselData.orbiting)
                {
                    Vector3d norm = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude);

                    double terrainHeight = 0.0;
                    if (vesselData.body.pqsController != null)
                    {
                        terrainHeight = vesselData.body.pqsController.GetSurfaceHeight(norm) - vesselData.body.pqsController.radius;
                    }
                    bool splashed = landed && terrainHeight < 0.001;

                    // Create the config node representation of the ProtoVessel
                    // Note - flying is experimental, and so far doesn't work
                    protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ?
                                                     Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString());
                    protoVesselNode.SetValue("landed", (landed && !splashed).ToString());
                    protoVesselNode.SetValue("splashed", splashed.ToString());
                    protoVesselNode.SetValue("lat", vesselData.latitude.ToString());
                    protoVesselNode.SetValue("lon", vesselData.longitude.ToString());
                    protoVesselNode.SetValue("alt", vesselData.altitude.ToString());
                    protoVesselNode.SetValue("landedAt", vesselData.body.name);

                    // Figure out the additional height to subtract
                    float lowest = float.MaxValue;
                    if (shipConstruct != null)
                    {
                        foreach (Part p in shipConstruct.parts)
                        {
                            foreach (Collider collider in p.GetComponentsInChildren <Collider>())
                            {
                                if (collider.gameObject.layer != 21 && collider.enabled)
                                {
                                    lowest = Mathf.Min(lowest, collider.bounds.min.y);
                                }
                            }
                        }
                    }
                    else
                    {
                        foreach (Collider collider in vesselData.craftPart.partPrefab.GetComponentsInChildren <Collider>())
                        {
                            if (collider.gameObject.layer != 21 && collider.enabled)
                            {
                                lowest = Mathf.Min(lowest, collider.bounds.min.y);
                            }
                        }
                    }

                    if (lowest == float.MaxValue)
                    {
                        lowest = 0;
                    }

                    // Figure out the surface height and rotation
                    Quaternion normal   = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                    Quaternion rotation = Quaternion.identity;
                    float      heading  = vesselData.heading;
                    if (shipConstruct == null)
                    {
                        rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
                    }
                    else if (shipConstruct.shipFacility == EditorFacility.SPH)
                    {
                        rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward);
                        heading += 180.0f;
                    }
                    else
                    {
                        rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward);
                    }

                    rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back);
                    rotation = rotation * Quaternion.AngleAxis(vesselData.roll, Vector3.down);
                    rotation = rotation * Quaternion.AngleAxis(vesselData.pitch, Vector3.left);

                    // Set the height and rotation
                    if (landed || splashed)
                    {
                        float hgt = (shipConstruct != null ? shipConstruct.parts[0] : vesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest;
                        hgt += vesselData.height;
                        protoVesselNode.SetValue("hgt", hgt.ToString());
                    }
                    protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation * normal));

                    // Set the normal vector relative to the surface
                    Vector3 nrm = (rotation * Vector3.forward);
                    protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z);

                    protoVesselNode.SetValue("prst", false.ToString());
                }

                // Add vessel to the game
                ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);

                // Store the id for later use
                vesselData.id = protoVessel.vesselRef.id;

                // Associate it so that it can be used in contract parameters
                ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef);
            }

            vesselsCreated = true;
            return(true);
        }
Exemple #11
0
        void SpawnVessel(VesselData vesselData)
        {
            string gameDataDir = KSPUtil.ApplicationRootPath;

            vesselData.orbit     = vessel.GetOrbit();
            vesselData.orbit.vel = vessel.orbit.vel;
            vesselData.orbit.meanAnomalyAtEpoch = vesselData.orbit.meanAnomalyAtEpoch + Math.Atan(UnityEngine.Random.Range(200, 300) / vesselData.orbit.semiMajorAxis);
            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            float         lcHeight      = 0;
            ConfigNode    craftNode;
            ConfigNode    currentShip = ShipConstruction.ShipConfig;

            shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL);
            float dryCost = 0;
            float cost    = 0;

            shipConstruct.GetShipCosts(out dryCost, out cost);
            cost = cost + dryCost;
            if (cost > Funding.Instance.Funds)
            {
                foreach (var p in FindObjectsOfType <Part>())
                {
                    if (!p.vessel)
                    {
                        Destroy(p.gameObject);
                    }
                }
                ScreenMessages.PostScreenMessage("not enought funds", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }
            craftNode = ConfigNode.Load(vesselData.craftURL);
            lcHeight  = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
            ShipConstruction.ShipConfig = currentShip;
            vesselData.name             = shipConstruct.shipName;

            uint missionID = (uint)Guid.NewGuid().GetHashCode();
            uint launchID  = HighLogic.CurrentGame.launchID++;

            foreach (Part p in shipConstruct.parts)
            {
                p.missionID   = missionID;
                p.launchID    = launchID;
                p.flightID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                p.temperature = 1.0;
            }
            ConfigNode  empty       = new ConfigNode();
            ProtoVessel dummyProto  = new ProtoVessel(empty, null);
            Vessel      dummyVessel = new Vessel();

            dummyVessel.parts    = shipConstruct.parts;
            dummyProto.vesselRef = dummyVessel;

            foreach (Part p in shipConstruct.parts)
            {
                dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
            }
            foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
            {
                p.storePartRefs();
            }
            List <ConfigNode> partNodesL = new List <ConfigNode>();

            foreach (var snapShot in dummyProto.protoPartSnapshots)
            {
                ConfigNode node = new ConfigNode("PART");
                snapShot.Save(node);
                partNodesL.Add(node);
            }
            partNodes = partNodesL.ToArray();
            ConfigNode[] additionalNodes = new ConfigNode[0];
            ConfigNode   protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, VesselType.Ship, vesselData.orbit, 0, partNodes, additionalNodes);
            ProtoVessel  protoVessel     = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            vesselData.id = protoVessel.vesselRef.id;
            protoVessel.vesselRef.Load();
            Funding.Instance.AddFunds(-cost, TransactionReasons.Vessels);
            ScreenMessages.PostScreenMessage("vessel buy !", 5.0f, ScreenMessageStyle.UPPER_CENTER);
            foreach (var p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
        }
        void SpawnVessel(string craftURL, CelestialBody orbitmainBodyName, double altitude, string stationName)
        {
            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                if (vessel.vesselName == stationName)
                {
                    vessel.Die();
                    break;
                }
            }
            VesselData vesselData = new VesselData();

            vesselData.craftURL = craftURL;
            vesselData.orbiting = true;
            vesselData.flagURL  = HighLogic.CurrentGame.flagURL;
            vesselData.owned    = true;
            string gameDataDir = KSPUtil.ApplicationRootPath;

            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            float         lcHeight      = 0;
            ConfigNode    craftNode;
            ConfigNode    currentShip = ShipConstruction.ShipConfig;

            shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL);
            craftNode     = ConfigNode.Load(vesselData.craftURL);
            lcHeight      = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
            ShipConstruction.ShipConfig = currentShip;
            ConfigNode  empty       = new ConfigNode();
            ProtoVessel dummyProto  = new ProtoVessel(empty, null);
            Vessel      dummyVessel = new Vessel();

            dummyVessel.parts    = shipConstruct.parts;
            dummyProto.vesselRef = dummyVessel;
            uint missionID = (uint)Guid.NewGuid().GetHashCode();
            uint launchID  = HighLogic.CurrentGame.launchID++;

            foreach (Part p in shipConstruct.parts)
            {
                p.missionID   = missionID;
                p.launchID    = launchID;
                p.flightID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                p.temperature = 1.0;
                dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
            }
            foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
            {
                p.storePartRefs();
            }
            List <ConfigNode> partNodesL = new List <ConfigNode>();

            foreach (var snapShot in dummyProto.protoPartSnapshots)
            {
                ConfigNode node = new ConfigNode("PART");
                snapShot.Save(node);
                partNodesL.Add(node);
            }
            partNodes = partNodesL.ToArray();
            ConfigNode[] additionalNodes = new ConfigNode[0];
            ConfigNode   protoVesselNode = ProtoVessel.CreateVesselNode(stationName, VesselType.Station, new Orbit(0, 0, altitude + orbitmainBodyName.Radius, 0, 0, 0, 0, orbitmainBodyName), 0, partNodes, additionalNodes);
            ProtoVessel  protoVessel     = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            vesselData.id = protoVessel.vesselRef.id;
            foreach (var p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
        }
    private void SpawnVessel(VesselData vesselData, List<ProtoCrewMember> crewData = null)
    {
      string gameDataDir = KSPUtil.ApplicationRootPath;
      Log.info("Spawning a vessel named '" + vesselData.name + "'");

      // Set additional info for landed vessels
      bool landed = false;
      if (!vesselData.orbiting)
      {
        landed = true;
        if (vesselData.altitude == null || vesselData.altitude < 0)
        {
          vesselData.altitude = 35;//LocationUtil.TerrainHeight(vesselData.latitude, vesselData.longitude, vesselData.body);
        }

        //Vector3d pos = vesselData.body.GetWorldSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);
        Vector3d pos = vesselData.body.GetRelSurfacePosition(vesselData.latitude, vesselData.longitude, vesselData.altitude.Value);

        vesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, vesselData.body);
        vesselData.orbit.UpdateFromStateVectors(pos, vesselData.body.getRFrmVel(pos), vesselData.body, Planetarium.GetUniversalTime());
      }
      else
      {
        vesselData.orbit.referenceBody = vesselData.body;
      }

      ConfigNode[] partNodes;
      //UntrackedObjectClass sizeClass;
      ShipConstruct shipConstruct = null;
      bool hasClamp = false;
      float lcHeight = 0;
      ConfigNode craftNode;
      Quaternion craftRotation = Quaternion.identity;
      if (!string.IsNullOrEmpty(vesselData.craftURL))
      {
        // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
        ConfigNode currentShip = ShipConstruction.ShipConfig;

        shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL);
        if (shipConstruct == null)
        {
          Log.info("ShipConstruct was null when tried to load '{0}' (usually this means the file could not be found).", vesselData.craftURL);
          return;//continue;
        }

        craftNode = ConfigNode.Load(vesselData.craftURL);
        lcHeight = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
        craftRotation = ConfigNode.ParseQuaternion(craftNode.GetNode("PART").GetValue("rot"));

        // Restore ShipConstruction ship
        ShipConstruction.ShipConfig = currentShip;

        // Set the name
        if (string.IsNullOrEmpty(vesselData.name))
        {
          vesselData.name = shipConstruct.shipName;
        }
        
        // Set some parameters that need to be at the part level
        uint missionID = (uint)Guid.NewGuid().GetHashCode();
        uint launchID = HighLogic.CurrentGame.launchID++;
        foreach (Part p in shipConstruct.parts)
        {
            p.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
          p.missionID = missionID;
          p.launchID = launchID;
          p.flagURL = vesselData.flagURL ?? HighLogic.CurrentGame.flagURL;

          // Had some issues with this being set to -1 for some ships - can't figure out
          // why.  End result is the vessel exploding, so let's just set it to a positive
          // value.
          p.temperature = 1.0;
        }
        
        //add minimal crew
        //bool success = false;
        Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity);

        // Add the crew member
        if (part != null && VesselMoverToolbar.addCrewMembers)
        {
          if (VesselMoverToolbar.selectCrewMembers)
          {
            ProtoCrewMember crewMember = crewData.FirstOrDefault();
            if (crewMember != null)
              part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
            VesselMoverToolbar.SelectedCrewMembers.Clear();
          }
          else
          {
            // Create the ProtoCrewMember
            ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal();
            crewMember.gender = UnityEngine.Random.Range(0, 100) > 50
              ? ProtoCrewMember.Gender.Female
              : ProtoCrewMember.Gender.Male;
            //crewMember.trait = "Pilot";

            // Add them to the part
            part.AddCrewmemberAt(crewMember, part.protoModuleCrew.Count);
          }
        }

        // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
        // We can't use the config nodes from the .craft file, because they are in a
        // slightly different format than those required for a ProtoVessel (seriously
        // Squad?!?).
        ConfigNode empty = new ConfigNode();
        ProtoVessel dummyProto = new ProtoVessel(empty, null);
        Vessel dummyVessel = new Vessel();
        dummyVessel.parts = shipConstruct.Parts;
        dummyProto.vesselRef = dummyVessel;

        // Create the ProtoPartSnapshot objects and then initialize them
        foreach (Part p in shipConstruct.parts)
        {
            dummyVessel.loaded = false;
            p.vessel = dummyVessel;

            {
#if KSP_18
                ProtoPartSnapshot proto = new ProtoPartSnapshot(p, dummyProto, true)); // For KSP >= 1.8
#else 
                ProtoPartSnapshot proto = new ProtoPartSnapshot(p, dummyProto);      // For KSP 1.4.x
#endif
                dummyProto.protoPartSnapshots.Add(proto);
            }
        }
        foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
        {
          p.storePartRefs();
        }

        // Create the ship's parts

        List<ConfigNode> partNodesL = new List<ConfigNode>();
        foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots)
        {
          ConfigNode node = new ConfigNode("PART");
          snapShot.Save(node);
          partNodesL.Add(node);
        }
        partNodes = partNodesL.ToArray();




        // Estimate an object class, numbers are based on the in game description of the
        // size classes.
        //float size = shipConstruct.shipSize.magnitude / 2.0f;
        //if (size < 4.0f)
        //{
        //  sizeClass = UntrackedObjectClass.A;
        //}
        //else if (size < 7.0f)
        //{
        //  sizeClass = UntrackedObjectClass.B;
        //}
        //else if (size < 12.0f)
        //{
        //  sizeClass = UntrackedObjectClass.C;
        //}
        //else if (size < 18.0f)
        //{
        //  sizeClass = UntrackedObjectClass.D;
        //}
        //else
        //{
        //  sizeClass = UntrackedObjectClass.E;
        //}
      }
      else
      {
        // Create crew member array
        ProtoCrewMember[] crewArray = new ProtoCrewMember[vesselData.crew.Count];
        int i = 0;
        foreach (CrewData cd in vesselData.crew)
        {
          // Create the ProtoCrewMember
          ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew);
          if (cd.name != null)
          {
            crewMember.KerbalRef.name = cd.name;
          }

          crewArray[i++] = crewMember;
        }

        // Create part nodes
        uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
        partNodes = new ConfigNode[1];
        partNodes[0] = ProtoVessel.CreatePartNode(vesselData.craftPart.name, flightId, crewArray);

        // Default the size class
        //sizeClass = UntrackedObjectClass.A;

        // Set the name
        if (string.IsNullOrEmpty(vesselData.name))
        {
          vesselData.name = vesselData.craftPart.name;
        }
      }

      // Create additional nodes
      ConfigNode[] additionalNodes = new ConfigNode[0];
      //DiscoveryLevels discoveryLevel = vesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
      //additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

      // Create the config node representation of the ProtoVessel
      ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes);

      // Additional seetings for a landed vessel
      if (!vesselData.orbiting)
      {
        Vector3d norm = vesselData.body.GetRelSurfaceNVector(vesselData.latitude, vesselData.longitude);

        double terrainHeight = 0.0;
        if (vesselData.body.pqsController != null)
        {
          terrainHeight = vesselData.body.pqsController.GetSurfaceHeight(norm) - vesselData.body.pqsController.radius;
        }
        bool splashed = false;// = landed && terrainHeight < 0.001;

        // Create the config node representation of the ProtoVessel
        // Note - flying is experimental, and so far doesn't work
        protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ?
          Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString());
        protoVesselNode.SetValue("landed", (landed && !splashed).ToString());
        protoVesselNode.SetValue("splashed", splashed.ToString());
        protoVesselNode.SetValue("lat", vesselData.latitude.ToString());
        protoVesselNode.SetValue("lon", vesselData.longitude.ToString());
        protoVesselNode.SetValue("alt", vesselData.altitude.ToString());
        protoVesselNode.SetValue("landedAt", vesselData.body.name);

        // Figure out the additional height to subtract
        float lowest = float.MaxValue;
        if (shipConstruct != null)
        {
          foreach (Part p in shipConstruct.parts)
          {
            foreach (Collider collider in p.GetComponentsInChildren<Collider>())
            {
              if (collider.gameObject.layer != 21 && collider.enabled)
              {
                lowest = Mathf.Min(lowest, collider.bounds.min.y);
              }
            }
          }
        }
        else
        {
          foreach (Collider collider in vesselData.craftPart.partPrefab.GetComponentsInChildren<Collider>())
          {
            if (collider.gameObject.layer != 21 && collider.enabled)
            {
              lowest = Mathf.Min(lowest, collider.bounds.min.y);
            }
          }
        }

        if (lowest == float.MaxValue)
        {
          lowest = 0;
        }

        // Figure out the surface height and rotation
        Quaternion normal = Quaternion.LookRotation((Vector3)norm);// new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
        Quaternion rotation = Quaternion.identity;
        float heading = vesselData.heading;
        if (shipConstruct == null)
        {
          rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
        }
        else if (shipConstruct.shipFacility == EditorFacility.SPH)
        {
          rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward);
          heading += 180.0f;
        }
        else
        {
          rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward);
          rotation = Quaternion.FromToRotation(Vector3.up, -Vector3.up) * rotation;

          //rotation = craftRotation;


          vesselData.heading = 0;
          vesselData.pitch = 0;
        }

        rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back);
        rotation = rotation * Quaternion.AngleAxis(vesselData.roll, Vector3.down);
        rotation = rotation * Quaternion.AngleAxis(vesselData.pitch, Vector3.left);

        // Set the height and rotation
        if (landed || splashed)
        {
          float hgt = (shipConstruct != null ? shipConstruct.parts[0] : vesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest;
          hgt += vesselData.height;

          foreach (Part p in shipConstruct.Parts)
          {
            LaunchClamp lc = p.FindModuleImplementing<LaunchClamp>();
            if (lc)
            {
              hasClamp = true;
              break;
            }
          }

          if (!hasClamp)
          {
            hgt += 35;
          }
          else
          {
            hgt += lcHeight;
          }
          protoVesselNode.SetValue("hgt", hgt.ToString(), true);
        }
        protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation), true);

        // Set the normal vector relative to the surface
        Vector3 nrm = (rotation * Vector3.forward);
        protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z, true);

        protoVesselNode.SetValue("prst", false.ToString(), true);
      }

      // Add vessel to the game
      ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);
      //protoVessel.vesselRef.transform.rotation = protoVessel.rotation;


      // Store the id for later use
      vesselData.id = protoVessel.vesselRef.id;

      //protoVessel.vesselRef.currentStage = 0;

      StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp));

      // Associate it so that it can be used in contract parameters
      //ContractVesselTracker.Instance.AssociateVessel(vesselData.name, protoVessel.vesselRef);



      //destroy prefabs
      foreach (Part p in FindObjectsOfType<Part>())
      {
        if (!p.vessel)
        {
          Destroy(p.gameObject);
        }
      }
    }
        static void SpawnVessel(VesselData vesselData)
        {
            string gameDataDir = KSPUtil.ApplicationRootPath;

            if (vesselData.vesselType == VesselType.Ship)
            {
                vesselData.name = "abandoned ship " + UnityEngine.Random.Range(1000, 10000);
            }
            else
            {
                vesselData.name = "abandoned science station " + UnityEngine.Random.Range(1000, 10000);
            }
            vesselData.orbit                     = FlightGlobals.ActiveVessel.GetOrbit();
            vesselData.orbit.inclination         = UnityEngine.Random.Range(0, 360);
            vesselData.orbit.eccentricity        = UnityEngine.Random.Range(0, 0.3f);
            vesselData.orbit.semiMajorAxis       = UnityEngine.Random.Range(Convert.ToSingle(FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.mainBody.atmosphereDepth + 50000), Convert.ToSingle(FlightGlobals.ActiveVessel.mainBody.sphereOfInfluence));
            vesselData.orbit.LAN                 = UnityEngine.Random.Range(0, 360);
            vesselData.orbit.argumentOfPeriapsis = UnityEngine.Random.Range(0, 360);
            vesselData.orbit.meanAnomalyAtEpoch  = 0;
            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            float         lcHeight      = 0;
            ConfigNode    craftNode;
            ConfigNode    currentShip = ShipConstruction.ShipConfig;

            shipConstruct = ShipConstruction.LoadShip(vesselData.craftURL);
            craftNode     = ConfigNode.Load(vesselData.craftURL);
            lcHeight      = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
            ShipConstruction.ShipConfig = currentShip;
            ConfigNode  empty       = new ConfigNode();
            ProtoVessel dummyProto  = new ProtoVessel(empty, null);
            Vessel      dummyVessel = new Vessel();

            dummyVessel.parts    = shipConstruct.parts;
            dummyProto.vesselRef = dummyVessel;
            uint missionID = (uint)Guid.NewGuid().GetHashCode();
            uint launchID  = HighLogic.CurrentGame.launchID++;

            foreach (Part p in shipConstruct.parts)
            {
                p.missionID   = missionID;
                p.launchID    = launchID;
                p.flightID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                p.temperature = 1.0;
                dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
            }
            foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
            {
                p.storePartRefs();
            }
            List <ConfigNode> partNodesL = new List <ConfigNode>();

            foreach (var snapShot in dummyProto.protoPartSnapshots)
            {
                ConfigNode node = new ConfigNode("PART");
                snapShot.Save(node);
                partNodesL.Add(node);
            }
            partNodes = partNodesL.ToArray();
            ConfigNode[] additionalNodes = new ConfigNode[0];
            ConfigNode   protoVesselNode = ProtoVessel.CreateVesselNode(vesselData.name, vesselData.vesselType, vesselData.orbit, 0, partNodes, additionalNodes);
            ProtoVessel  protoVessel     = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            vesselData.id = protoVessel.vesselRef.id;
            foreach (var p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
            if (vesselData.vesselType == VesselType.Ship)
            {
                setResourcesAmount(protoVessel.vesselRef);
            }
            if (vesselData.vesselType == VesselType.Station)
            {
                setScience(protoVessel.vesselRef);
            }
        }
Exemple #15
0
        static void ReadAllCraftFiles(string editorFacility, string shipDirectory)
        {
            foreach (var craftFile in Directory.GetFiles(shipDirectory, "*.craft"))
            {
                try
                {
                    string validFileName = Path.GetFileNameWithoutExtension(craftFile);
                    if (validFileName == "Auto-Saved Ship")
                    {
                        continue;                                     // Skip these, they would lead to duplicates, we only use finished crafts.
                    }
                    var cachedTemplate = new CachedShipTemplate();
                    switch (editorFacility)
                    {
                    case "VAB": cachedTemplate.templateOrigin = TemplateOrigin.VAB; break;

                    case "SPH": cachedTemplate.templateOrigin = TemplateOrigin.SPH; break;

                    case "Subassemblies": cachedTemplate.templateOrigin = TemplateOrigin.SubAssembly; break;
                    }

                    cachedTemplate.template = ShipConstruction.LoadTemplate(craftFile);

                    if (cachedTemplate.template == null)
                    {
                        continue;
                    }
                    if (cachedTemplate.template.shipPartsExperimental || !cachedTemplate.template.shipPartsUnlocked)
                    {
                        continue;                                                                                              // We won't bother with ships we can't use anyways.
                    }
                    // Try to load the thumbnail for this craft:
                    var thumbFile = KSPUtil.ApplicationRootPath + "thumbs/" + HighLogic.SaveFolder + "_" + editorFacility + "_" + validFileName + ".png";

                    Texture2D thumbnail;

                    //
                    // Make the thumbnail file if it doesn't exist.
                    // Needed for the subassemblies, will also replace any missing thumbnail files for regular craft
                    //
                    if (!HighLogic.LoadedSceneIsFlight)
                    {
                        if (!File.Exists(thumbFile))
                        {
                            Log.Info("Missing Thumbfile: " + thumbFile);
                            ShipConstruct ship = ShipConstruction.LoadShip(craftFile);
                            ThumbnailHelper.CaptureThumbnail(ship, 256, "thumbs/", HighLogic.SaveFolder + "_" + editorFacility + "_" + validFileName);
                        }
                    }

                    bool placeholder = false;
                    if (File.Exists(thumbFile))
                    {
                        thumbnail = new Texture2D(256, 256, TextureFormat.RGBA32, false);
                        thumbnail.LoadImage(File.ReadAllBytes(thumbFile));
                    }
                    else
                    {
                        thumbnail   = placeholderImage;
                        placeholder = true;
                    }

                    // The thumbnails are rather large, so we have to resize them first:
                    cachedTemplate.thumbnail = GUI.ResizeTexture(thumbnail, 64, 64);
                    if (!placeholder)
                    {
                        Destroy(thumbnail);
                    }
                    GUI.shipTemplates.Add(cachedTemplate);
                }
                catch (Exception e)
                {
                    Debug.LogError("UpdateShipTemplateCache() processing '" + craftFile + "': " + e.ToString());
                }
            }
        }
Exemple #16
0
        // Creates a new ship with the given parameters for this mission. The code however seems unnecessarily convoluted and
        // error-prone, but there are no better examples available on the internet.
        private void CreateShip()
        {
            // TODO: Apply the staging which was saved in the editor.
            // TODO: Settings from other mods like Part-Switchers must also be applied here, maybe copy the config-nodes...
            try
            {
                if (!File.Exists(shipTemplateFilename))
                {
                    throw new Exception("file '" + shipTemplateFilename + "' not found");
                }
                if (missionType == MissionType.DEPLOY)
                {
                    // Make sure that there won't be any collisions, when the vessel is created at the given orbit:
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit);
                }
                else if (missionType == MissionType.CONSTRUCT)
                {
                    // Deploy the new ship next to the space-dock:
                    Vessel spaceDock = TargetVessel.GetVesselById((Guid)targetVesselId);
                    orbit = GUIOrbitEditor.CreateFollowingOrbit(spaceDock.orbit, 100); // TODO: Calculate the distance using the ships's size
                    orbit = GUIOrbitEditor.ApplySafetyDistance(orbit);
                }
                else
                {
                    throw new Exception("invalid mission-type '" + missionType.ToString() + "'");
                }

                // The ShipConstruct-object can only savely exist while not in flight, otherwise it will spam Null-Pointer Exceptions every tick:
                if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                {
                    throw new Exception("unable to run CreateShip while in flight");
                }

                // Load the parts form the saved vessel:
                ShipConstruct shipConstruct = ShipConstruction.LoadShip(shipTemplateFilename);
                ProtoVessel   dummyProto    = new ProtoVessel(new ConfigNode(), null);
                Vessel        dummyVessel   = new Vessel();
                dummyProto.vesselRef = dummyVessel;

                // In theory it should be enough to simply copy the parts from the ShipConstruct to the ProtoVessel, but
                // this only seems to work when the saved vessel starts with the root-part and is designed top down from there.
                // It seems that the root part has to be the first part in the ProtoVessel's parts-list and all other parts have
                // to be listed in sequence radiating from the root part (eg 1=>2=>R<=3<=4 should be R,2,1,3,4). If the parts
                // are not in the correct order, their rotation seems to get messed up or they are attached to the wrong
                // attachmet-nodes, which is why we have to re-sort the parts with our own logic here.
                // This part of the code is experimental however and only based on my own theories and observations about KSP's vessels.
                Part rootPart = null;
                foreach (Part p in shipConstruct.parts)
                {
                    if (p.parent == null)
                    {
                        rootPart = p; break;
                    }
                }
                List <Part> pList = null;
                dummyVessel.parts = FindAndAddAttachedParts(rootPart, ref pList); // Find all parts which are directly attached to the root-part and add them in order.

                // Handle Subassemblies which are attached by surface attachment-nodes:
                bool handleSurfaceAttachments = true;
                while (dummyVessel.parts.Count < shipConstruct.parts.Count)
                {
                    int processedParts = 0;
                    foreach (Part p in shipConstruct.parts)
                    {
                        if (dummyVessel.parts.Contains(p))
                        {
                            continue;
                        }
                        if (handleSurfaceAttachments)
                        {
                            // Check if the part is attached by a surface-node:
                            if (p.srfAttachNode != null && dummyVessel.parts.Contains(p.srfAttachNode.attachedPart))
                            {
                                // Add this surface attached part and all the sub-parts:
                                dummyVessel.parts = FindAndAddAttachedParts(p, ref dummyVessel.parts);
                                processedParts++;
                            }
                        }
                        else
                        {
                            // Simply copy this part:
                            dummyVessel.parts.Add(p);
                        }
                    }
                    if (processedParts == 0)
                    {
                        // If there are still unprocessed parts, just throw them in the list during the next iteration,
                        // this should not happen but we don't want to end up in an endless loop:
                        handleSurfaceAttachments = false;
                    }
                }

                // Initialize all parts:
                uint missionID = (uint)Guid.NewGuid().GetHashCode();
                uint launchID  = HighLogic.CurrentGame.launchID++;
                foreach (Part p in dummyVessel.parts)
                {
                    p.flagURL     = flagURL == null ? HighLogic.CurrentGame.flagURL : flagURL;
                    p.missionID   = missionID;
                    p.launchID    = launchID;
                    p.temperature = 1.0;

                    // If the KRnD-Mod is installed, make sure that all parts of this newly created ship are set to the lates version:
                    foreach (PartModule module in p.Modules)
                    {
                        if (module.moduleName != "KRnDModule")
                        {
                            continue;
                        }
                        Debug.Log("[KSTS] found KRnD on '" + p.name.ToString() + "', setting to latest stats");
                        foreach (BaseField field in module.Fields)
                        {
                            if (field.name.ToString() == "upgradeToLatest")
                            {
                                field.SetValue(1, module); // Newer versions of KRnD use this flag to upgrade all attributes of the given part to the latest levels, when the vessel is activated.
                                if (field.GetValue(module).ToString() != "1")
                                {
                                    Debug.LogError("[KSTS] unable to modify '" + field.name.ToString() + "'");
                                }
                            }
                        }
                    }

                    dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                }

                // Store the parts in Config-Nodes:
                foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                {
                    p.storePartRefs();
                }
                List <ConfigNode> partNodesL = new List <ConfigNode>();
                foreach (var snapShot in dummyProto.protoPartSnapshots)
                {
                    ConfigNode node = new ConfigNode("PART");
                    snapShot.Save(node);
                    partNodesL.Add(node);
                }
                ConfigNode[] partNodes       = partNodesL.ToArray();
                ConfigNode[] additionalNodes = new ConfigNode[0];

                // This will actually create the ship and add it to the global list of flights:
                ConfigNode  protoVesselNode = ProtoVessel.CreateVesselNode(shipName, VesselType.Ship, orbit, 0, partNodes, additionalNodes);
                ProtoVessel pv = HighLogic.CurrentGame.AddVessel(protoVesselNode);
                Debug.Log("[KSTS] deployed new ship '" + shipName.ToString() + "' as '" + pv.vesselRef.id.ToString() + "'");
                ScreenMessages.PostScreenMessage("Vessel '" + shipName.ToString() + "' deployed"); // Popup message to notify the player
                Vessel newVessel = FlightGlobals.Vessels.Find(x => x.id == pv.vesselID);

                // Maybe add the initial crew to the vessel:
                if (crewToDeliver != null && crewToDeliver.Count > 0 && newVessel != null)
                {
                    foreach (string kerbonautName in crewToDeliver)
                    {
                        TargetVessel.AddCrewMember(newVessel, kerbonautName);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] Mission.CreateShip(): " + e.ToString());
            }
        }
        protected ProtoVessel CreateProtoVessel()
        {
            ProtoVessel   protoVessel = null;
            ShipConstruct construct   = null;
            Vessel        vessel      = null;

            try
            {
                // Backup the ship config from the VAB/SPH, load the selected .craft file
                //   and restore the cached config from the VAB/SPH
                var constructBak = ShipConstruction.ShipConfig;
                construct = ShipConstruction.LoadShip(_selectedCraftFilePath);
                ShipConstruction.ShipConfig = constructBak;

                // Calculate vessel cost and mass and generate a thumbnail
                construct.GetShipCosts(out _cachedFundsCost, out _);
                construct.GetShipMass(out _cachedDryMass, out _);
                _cachedThumbnail = _thumbnailService.GetThumbnail(construct);

                // Create an emtpy Vessel and copy the parts from the loaded .craft file
                vessel       = new GameObject().AddComponent <Vessel>();
                vessel.parts = construct.parts;

                // Create an empty ProtoVessel that we'll ultimately use to create the template
                //   for the vessel to be spawned in-game later
                protoVessel = new ProtoVessel(new ConfigNode(), null)
                {
                    vesselName = construct.shipName,
                    vesselRef  = vessel
                };

                // Setup necessary Vessel and Part parameters for the template (also check for launch clamps)
                var launchId  = HighLogic.CurrentGame.launchID++;
                var missionId = (uint)Guid.NewGuid().GetHashCode();
                var rootPart  = construct.parts.First();
                _hasLaunchClamp = false;
                foreach (var part in construct.parts)
                {
                    _hasLaunchClamp |= part.HasModuleImplementing <LaunchClamp>();

                    part.flagURL     = construct.missionFlag ?? HighLogic.CurrentGame.flagURL;
                    part.flightID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                    part.launchID    = launchId;
                    part.missionID   = missionId;
                    part.temperature = Math.Abs(part.temperature);
                    part.UpdateOrgPosAndRot(rootPart);

                    part.vessel = vessel;
                    var partSnapshot = new ProtoPartSnapshot(part, protoVessel);
                    foreach (var resource in partSnapshot.resources)
                    {
                        if (resource.resourceName != "ElectricCharge")
                        {
                            resource.amount = 0d;
                        }
                    }
                    protoVessel.protoPartSnapshots.Add(partSnapshot);
                }
                foreach (var snapshot in protoVessel.protoPartSnapshots)
                {
                    snapshot.storePartRefs();
                }

                // Cache the ProtoVessel to use as the template for spawning the vessel later
                _cachedProtoVessel = protoVessel;
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
            }
            finally
            {
                // ShipConstruction.LoadShip seems to load in all the part meshes for the vessel
                //   (presumably for use in the VAB/SPH), so we need to destroy them
                if (construct != null && construct.parts != null && construct.parts.Count > 0)
                {
                    foreach (var part in construct.parts)
                    {
                        Destroy(part.gameObject);
                    }
                }
                // Destroy the temporary Vessel we created as well
                if (vessel != null)
                {
                    Destroy(vessel.gameObject);
                }
            }

            return(protoVessel);
        }
        private void SpawnVessel(WaldoAttackVesselData WaldoAttackVesselData, List <ProtoCrewMember> crewData = null)
        {
            //      string gameDataDir = KSPUtil.ApplicationRootPath;
            Debug.Log("[Spawn OrX Waldo Attack] Spawning " + WaldoAttackVesselData.name);

            // Set additional info for landed vessels
            bool landed = false;

            if (!landed)
            {
                landed = true;
                if (WaldoAttackVesselData.altitude == null || WaldoAttackVesselData.altitude < 0)
                {
                    WaldoAttackVesselData.altitude = 5;//LocationUtil.TerrainHeight(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude, WaldoAttackVesselData.body);
                }
                Debug.Log("[Spawn OrX Waldo Attack] SpawnVessel Altitude: " + WaldoAttackVesselData.altitude);

                //Vector3d pos = WaldoAttackVesselData.body.GetWorldSurfacePosition(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude, WaldoAttackVesselData.altitude.Value);
                Vector3d pos = WaldoAttackVesselData.body.GetRelSurfacePosition(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude, WaldoAttackVesselData.altitude.Value);

                WaldoAttackVesselData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, WaldoAttackVesselData.body);
                WaldoAttackVesselData.orbit.UpdateFromStateVectors(pos, WaldoAttackVesselData.body.getRFrmVel(pos), WaldoAttackVesselData.body, Planetarium.GetUniversalTime());
            }

            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            bool          hasClamp      = false;
            float         lcHeight      = 0;
            ConfigNode    craftNode;
            Quaternion    craftRotation = Quaternion.identity;

            if (!string.IsNullOrEmpty(WaldoAttackVesselData.craftURL))
            {
                // Save the current ShipConstruction ship, otherwise the player will see the spawned ship next time they enter the VAB!
                ConfigNode currentShip = ShipConstruction.ShipConfig;

                shipConstruct = ShipConstruction.LoadShip(WaldoAttackVesselData.craftURL);
                if (shipConstruct == null)
                {
                    Debug.Log("[Spawn OrX Waldo Attack] ShipConstruct was null when tried to load '" + WaldoAttackVesselData.craftURL +
                              "' (usually this means the file could not be found).");
                    return;//continue;
                }

                craftNode     = ConfigNode.Load(WaldoAttackVesselData.craftURL);
                lcHeight      = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
                craftRotation = ConfigNode.ParseQuaternion(craftNode.GetNode("PART").GetValue("rot"));

                // Restore ShipConstruction ship
                ShipConstruction.ShipConfig = currentShip;

                // Set the name
                if (string.IsNullOrEmpty(WaldoAttackVesselData.name))
                {
                    WaldoAttackVesselData.name = WaldoVesselName;
                    ;
                }

                // Set some parameters that need to be at the part level
                uint missionID = (uint)Guid.NewGuid().GetHashCode();
                uint launchID  = HighLogic.CurrentGame.launchID++;
                foreach (Part p in shipConstruct.parts)
                {
                    p.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                    p.missionID = missionID;
                    p.launchID  = launchID;
                    p.flagURL   = flagURL;

                    // Had some issues with this being set to -1 for some ships - can't figure out
                    // why.  End result is the vessel exploding, so let's just set it to a positive
                    // value.
                    p.temperature = 1.0;
                }

                // Create a dummy ProtoVessel, we will use this to dump the parts to a config node.
                // We can't use the config nodes from the .craft file, because they are in a
                // slightly different format than those required for a ProtoVessel (seriously
                // Squad?!?).
                ConfigNode  empty       = new ConfigNode();
                ProtoVessel dummyProto  = new ProtoVessel(empty, null);
                Vessel      dummyVessel = new Vessel();
                dummyVessel.parts    = shipConstruct.parts;
                dummyProto.vesselRef = dummyVessel;

                // Create the ProtoPartSnapshot objects and then initialize them
                foreach (Part p in shipConstruct.parts)
                {
                    dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
                }
                foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
                {
                    p.storePartRefs();
                }

                // Create the ship's parts

                List <ConfigNode> partNodesL = new List <ConfigNode>();
                foreach (ProtoPartSnapshot snapShot in dummyProto.protoPartSnapshots)
                {
                    ConfigNode node = new ConfigNode("PART");
                    snapShot.Save(node);
                    partNodesL.Add(node);
                }
                partNodes = partNodesL.ToArray();
            }
            else
            {
                // Create crew member array
                ProtoCrewMember[] crewArray = new ProtoCrewMember[WaldoAttackVesselData.crew.Count];

                /*
                 *      int i = 0;
                 *      foreach (CrewData cd in WaldoAttackVesselData.crew)
                 *      {
                 * /*
                 *        // Create the ProtoCrewMember
                 *        ProtoCrewMember crewMember = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew);
                 *        if (cd.name != null)
                 *        {
                 *          crewMember.KerbalRef.name = cd.name;
                 *        }
                 *
                 *        crewArray[i++] = crewMember;
                 *
                 *      }
                 */
                // Create part nodes
                uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                partNodes    = new ConfigNode[1];
                partNodes[0] = ProtoVessel.CreatePartNode(WaldoAttackVesselData.craftPart.name, flightId, crewArray);

                // Default the size class
                //sizeClass = UntrackedObjectClass.A;

                // Set the name
                if (string.IsNullOrEmpty(WaldoAttackVesselData.name))
                {
                    WaldoAttackVesselData.name = WaldoAttackVesselData.craftPart.name;
                }
            }

            // Create additional nodes
            ConfigNode[] additionalNodes = new ConfigNode[0];
            //DiscoveryLevels discoveryLevel = WaldoAttackVesselData.owned ? DiscoveryLevels.Owned : DiscoveryLevels.Unowned;
            //additionalNodes[0] = ProtoVessel.CreateDiscoveryNode(discoveryLevel, sizeClass, contract.TimeDeadline, contract.TimeDeadline);

            // Create the config node representation of the ProtoVessel
            ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(WaldoAttackVesselData.name, WaldoAttackVesselData.vesselType, WaldoAttackVesselData.orbit, 0, partNodes, additionalNodes);

            // Additional seetings for a landed vessel
            if (!WaldoAttackVesselData.orbiting)
            {
                Vector3d norm = WaldoAttackVesselData.body.GetRelSurfaceNVector(WaldoAttackVesselData.latitude, WaldoAttackVesselData.longitude);

                double terrainHeight = 0.0;
                if (WaldoAttackVesselData.body.pqsController != null)
                {
                    terrainHeight = WaldoAttackVesselData.body.pqsController.GetSurfaceHeight(norm) - WaldoAttackVesselData.body.pqsController.radius;
                }
                bool splashed = false;// = landed && terrainHeight < 0.001;

                // Create the config node representation of the ProtoVessel
                // Note - flying is experimental, and so far doesn't worx
                protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : landed ?
                                                 Vessel.Situations.LANDED : Vessel.Situations.FLYING).ToString());
                protoVesselNode.SetValue("landed", (landed && !splashed).ToString());
                protoVesselNode.SetValue("splashed", splashed.ToString());
                protoVesselNode.SetValue("lat", WaldoAttackVesselData.latitude.ToString());
                protoVesselNode.SetValue("lon", WaldoAttackVesselData.longitude.ToString());
                protoVesselNode.SetValue("alt", WaldoAttackVesselData.altitude.ToString());
                protoVesselNode.SetValue("landedAt", WaldoAttackVesselData.body.name);

                // Figure out the additional height to subtract
                float lowest = float.MaxValue;
                if (shipConstruct != null)
                {
                    foreach (Part p in shipConstruct.parts)
                    {
                        foreach (Collider collider in p.GetComponentsInChildren <Collider>())
                        {
                            if (collider.gameObject.layer != 21 && collider.enabled)
                            {
                                lowest = Mathf.Min(lowest, collider.bounds.min.y);
                            }
                        }
                    }
                }
                else
                {
                    foreach (Collider collider in WaldoAttackVesselData.craftPart.partPrefab.GetComponentsInChildren <Collider>())
                    {
                        if (collider.gameObject.layer != 21 && collider.enabled)
                        {
                            lowest = Mathf.Min(lowest, collider.bounds.min.y);
                        }
                    }
                }

                if (lowest == float.MaxValue)
                {
                    lowest = 0;
                }

                // Figure out the surface height and rotation
                Quaternion normal   = Quaternion.LookRotation((Vector3)norm);// new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                Quaternion rotation = Quaternion.identity;
                float      heading  = WaldoAttackVesselData.heading;
                if (shipConstruct == null)
                {
                    rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
                }
                else if (shipConstruct.shipFacility == EditorFacility.SPH)
                {
                    rotation = rotation * Quaternion.FromToRotation(Vector3.forward, -Vector3.forward);
                    heading += 180.0f;
                }
                else
                {
                    rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.forward);
                    rotation = Quaternion.FromToRotation(Vector3.up, -Vector3.up) * rotation;

                    //rotation = craftRotation;


                    WaldoAttackVesselData.heading = 0;
                    WaldoAttackVesselData.pitch   = 0;
                }

                rotation = rotation * Quaternion.AngleAxis(heading, Vector3.back);
                rotation = rotation * Quaternion.AngleAxis(WaldoAttackVesselData.roll, Vector3.down);
                rotation = rotation * Quaternion.AngleAxis(WaldoAttackVesselData.pitch, Vector3.left);

                // Set the height and rotation
                if (landed || splashed)
                {
                    float hgt = (shipConstruct != null ? shipConstruct.parts[0] : WaldoAttackVesselData.craftPart.partPrefab).localRoot.attPos0.y - lowest;
                    hgt += WaldoAttackVesselData.height;
                    protoVesselNode.SetValue("hgt", hgt.ToString(), true);
                }
                protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation), true);

                // Set the normal vector relative to the surface
                Vector3 nrm = (rotation * Vector3.forward);
                protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z, true);

                protoVesselNode.SetValue("prst", false.ToString(), true);
            }

            // Add vessel to the game
            ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            //protoVessel.vesselRef.transform.rotation = protoVessel.rotation;


            // Store the id for later use
            WaldoAttackVesselData.id = protoVessel.vesselRef.id;

            //protoVessel.vesselRef.currentStage = 0;
            hasClamp = false;

            StartCoroutine(PlaceSpawnedVessel(protoVessel.vesselRef, !hasClamp));

            // Associate it so that it can be used in contract parameters
            //ContractVesselTracker.Instance.AssociateVessel(WaldoAttackVesselData.name, protoVessel.vesselRef);


            //destroy prefabs
            foreach (Part p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
        }
Exemple #19
0
        public static Vessel SpawnVessel(string name, string craftURL, string flagURL, VesselType vesselType, CelestialBody body, Orbit orbit, List <ProtoCrewMember> crewList)
        {
            string gameDataDir = KSPUtil.ApplicationRootPath;

            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            float         lcHeight      = 0;
            ConfigNode    craftNode;
            ConfigNode    currentShip = ShipConstruction.ShipConfig;

            shipConstruct = ShipConstruction.LoadShip(craftURL);
            craftNode     = ConfigNode.Load(craftURL);
            lcHeight      = ConfigNode.ParseVector3(craftNode.GetNode("PART").GetValue("pos")).y;
            ShipConstruction.ShipConfig = currentShip;

            foreach (ProtoCrewMember crew in crewList)
            {
                Part part = shipConstruct.parts.Find(p => p.protoModuleCrew.Count < p.CrewCapacity);
                if (part != null)
                {
                    part.AddCrewmemberAt(crew, part.protoModuleCrew.Count);
                }
            }

            ConfigNode  empty       = new ConfigNode();
            ProtoVessel dummyProto  = new ProtoVessel(empty, null);
            Vessel      dummyVessel = new Vessel();

            dummyVessel.parts    = shipConstruct.parts;
            dummyProto.vesselRef = dummyVessel;
            uint missionID = (uint)Guid.NewGuid().GetHashCode();
            uint launchID  = HighLogic.CurrentGame.launchID++;

            foreach (Part p in shipConstruct.parts)
            {
                p.missionID   = missionID;
                p.launchID    = launchID;
                p.flightID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                p.temperature = 1.0;
                dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
            }
            foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
            {
                p.storePartRefs();
            }
            List <ConfigNode> partNodesL = new List <ConfigNode>();

            foreach (var snapShot in dummyProto.protoPartSnapshots)
            {
                ConfigNode node = new ConfigNode("PART");
                snapShot.Save(node);
                partNodesL.Add(node);
            }
            partNodes = partNodesL.ToArray();
            ConfigNode[] additionalNodes = new ConfigNode[0];
            ConfigNode   protoVesselNode = ProtoVessel.CreateVesselNode(name, VesselType.Ship, orbit, 0, partNodes, additionalNodes);
            ProtoVessel  protoVessel     = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            foreach (var p in UnityEngine.Object.FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    UnityEngine.Object.Destroy(p.gameObject);
                }
            }
            return(protoVessel.vesselRef);
        }