Exemple #1
0
        private static ProtoVessel GetVesselFromShipConstruct(ShipConstruct shipConstruct, ProtoVessel oldVessel,
                                                              Game game)
        {
            foreach (var p in shipConstruct.parts)
            {
                p.flightID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                p.missionID   = oldVessel.protoPartSnapshots[0].missionID;
                p.launchID    = oldVessel.protoPartSnapshots[0].launchID;
                p.flagURL     = oldVessel.protoPartSnapshots[0].flagURL ?? HighLogic.CurrentGame.flagURL;
                p.temperature = 1.0;
                // LITARLY NO CLUE WHY NO CODE IN SQUAD IS EXECUTING THIS (this little piece of shit took me 2 days)

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

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

            dummyVessel.parts    = shipConstruct.parts;
            dummyProto.vesselRef = dummyVessel;
            // ReSharper disable once SuggestVarOrType_SimpleTypes
            foreach (Part p in shipConstruct.parts)
            {
                dummyProto.protoPartSnapshots.Add(new ProtoPartSnapshot(p, dummyProto));
            }
            // ReSharper disable once SuggestVarOrType_SimpleTypes
            foreach (ProtoPartSnapshot p in dummyProto.protoPartSnapshots)
            {
                p.storePartRefs();
            }

            return(dummyProto);
        }
        private void GenerateStrandedKerbal(int bodyID, string kerbalName)
        {
            //Add kerbal to crew roster.
            DarkLog.Debug("Spawning missing kerbal, name: " + kerbalName);
            ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned);

            pcm.name         = kerbalName;
            pcm.rosterStatus = ProtoCrewMember.RosterStatus.Assigned;
            //Create protovessel
            uint          newPartID    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            CelestialBody contractBody = FlightGlobals.Bodies[bodyID];
            //Atmo: 10km above atmo, to half the planets radius out.
            //Non-atmo: 30km above ground, to half the planets radius out.
            double minAltitude   = FinePrint.Utilities.CelestialUtilities.GetMinimumOrbitalAltitude(contractBody, 1.1f);
            double maxAltitude   = minAltitude + contractBody.Radius * 0.5;
            Orbit  strandedOrbit = Orbit.CreateRandomOrbitAround(FlightGlobals.Bodies[bodyID], minAltitude, maxAltitude);

            ConfigNode[]      kerbalPartNode = new ConfigNode[1];
            ProtoCrewMember[] partCrew       = new ProtoCrewMember[1];
            partCrew[0]       = pcm;
            kerbalPartNode[0] = ProtoVessel.CreatePartNode("kerbalEVA", newPartID, partCrew);
            ConfigNode  protoVesselNode = ProtoVessel.CreateVesselNode(kerbalName, VesselType.EVA, strandedOrbit, 0, kerbalPartNode);
            ConfigNode  discoveryNode   = ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A, double.PositiveInfinity, double.PositiveInfinity);
            ProtoVessel protoVessel     = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame);

            protoVessel.discoveryInfo = discoveryNode;
            //It's not supposed to be infinite, but you're crazy if you think I'm going to decipher the values field of the rescue node.
            HighLogic.CurrentGame.flightState.protoVessels.Add(protoVessel);
        }
Exemple #3
0
        private void CreateLode(LodeData lodeData)
        {
            lodeData.altitude = TerrainHeight(lodeData.latitude, lodeData.longitude, lodeData.body);
            Vector3d pos = lodeData.body.GetWorldSurfacePosition(lodeData.latitude, lodeData.longitude, lodeData.altitude.Value);

            lodeData.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, lodeData.body);
            lodeData.orbit.UpdateFromStateVectors(pos, lodeData.body.getRFrmVel(pos), lodeData.body, Planetarium.GetUniversalTime());
            ConfigNode[]  partNodes;
            ShipConstruct shipConstruct = null;
            uint          flightId      = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);

            partNodes    = new ConfigNode[1];
            partNodes[0] = ProtoVessel.CreatePartNode(lodeData.craftPart.name, flightId);
            DiscoveryLevels discoveryLevel  = DiscoveryLevels.Owned;
            ConfigNode      protoVesselNode = ProtoVessel.CreateVesselNode(lodeData.name, lodeData.vesselType, lodeData.orbit, 0, partNodes);
            Vector3d        norm            = lodeData.body.GetRelSurfaceNVector(lodeData.latitude, lodeData.longitude);
            double          terrainHeight   = 0.0;

            if (lodeData.body.pqsController != null)
            {
                terrainHeight = lodeData.body.pqsController.GetSurfaceHeight(norm) - lodeData.body.pqsController.radius;
            }
            bool splashed = true && terrainHeight < 0.001;

            protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : Vessel.Situations.LANDED).ToString());
            protoVesselNode.SetValue("landed", (!splashed).ToString());
            protoVesselNode.SetValue("splashed", splashed.ToString());
            protoVesselNode.SetValue("lat", lodeData.latitude.ToString());
            protoVesselNode.SetValue("lon", lodeData.longitude.ToString());
            protoVesselNode.SetValue("alt", lodeData.altitude.ToString());
            protoVesselNode.SetValue("landedAt", lodeData.body.name);
            float lowest = float.MaxValue;

            foreach (Collider collider in lodeData.craftPart.partPrefab.GetComponentsInChildren <Collider>())
            {
                if (collider.gameObject.layer != 21 && collider.enabled)
                {
                    lowest = Mathf.Min(lowest, collider.bounds.min.y);
                }
            }
            if (Mathf.Approximately(lowest, float.MaxValue))
            {
                lowest = 0;
            }
            Quaternion normal   = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
            Quaternion rotation = Quaternion.identity;

            rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
            float hgt = (shipConstruct != null ? shipConstruct.parts[0] : lodeData.craftPart.partPrefab).localRoot.attPos0.y - lowest;

            protoVesselNode.SetValue("hgt", hgt.ToString());
            protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(rotation * normal));
            Vector3 nrm = (rotation * Vector3.forward);

            protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z);
            protoVesselNode.SetValue("prst", false.ToString());
            ProtoVessel protoVessel = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame);

            protoVessel.Load(HighLogic.CurrentGame.flightState);
        }
Exemple #4
0
  public static Part CreatePart(AvailablePart avPart, Vector3 position, Quaternion rotation,
                                Part flagFromPart) {
    UnityEngine.Object obj = UnityEngine.Object.Instantiate(avPart.partPrefab);
    if (!obj) {
      KAS_Shared.DebugError("CreatePart(Crate) Failed to instantiate " + avPart.partPrefab.name);
      return null;
    }

    Part newPart = (Part)obj;
    newPart.gameObject.SetActive(true);
    newPart.gameObject.name = avPart.name;
    newPart.partInfo = avPart;
    //newPart.highlightRecurse = true;
    newPart.SetMirror(Vector3.one);

    ShipConstruct newShip = new ShipConstruct();
    newShip.Add(newPart);
    newShip.SaveShip();
    newShip.shipName = avPart.title;
    //newShip.ty = 1;

    VesselCrewManifest vessCrewManifest = new VesselCrewManifest();
    Vessel currentVessel = FlightGlobals.ActiveVessel;

    Vessel v = newShip.parts[0].localRoot.gameObject.AddComponent<Vessel>();
    v.id = Guid.NewGuid();
    v.vesselName = newShip.shipName;
    v.Initialize(false);
    v.Landed = true;
    v.rootPart.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
    v.rootPart.missionID = flagFromPart.missionID;
    v.rootPart.flagURL = flagFromPart.flagURL;

    //v.rootPart.collider.isTrigger = true;

    //v.landedAt = "somewhere";
                      
    Staging.beginFlight();
    newShip.parts[0].vessel.ResumeStaging();
    Staging.GenerateStagingSequence(newShip.parts[0].localRoot);
    Staging.RecalculateVesselStaging(newShip.parts[0].vessel);

    FlightGlobals.SetActiveVessel(currentVessel);

    v.SetPosition(position);
    v.SetRotation(rotation);

    // Solar panels from containers don't work otherwise
    for (int i = 0; i < newPart.Modules.Count; i++) {
      ConfigNode node = new ConfigNode();
      node.AddValue("name", newPart.Modules[i].moduleName);
      newPart.LoadModule(node, ref i);
    }

    return newPart;
  }
Exemple #5
0
        public static Part LoadPartSnapshot(Vessel vessel, ConfigNode node,
                                            Vector3 position, Quaternion rotation)
        {
            ProtoPartSnapshot snapshot = KAS_Shared.LoadProtoPartSnapshot(node);

            if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID))
            {
                snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            }

            snapshot.parentIdx           = 0;
            snapshot.position            = position;
            snapshot.rotation            = rotation;
            snapshot.stageIndex          = 0;
            snapshot.defaultInverseStage = 0;
            snapshot.seqOverride         = -1;
            snapshot.inStageIndex        = -1;
            snapshot.attachMode          = (int)AttachModes.SRF_ATTACH;
            snapshot.attached            = true;
            snapshot.flagURL             = vessel.rootPart.flagURL;

            // Save properties that may be messed up by new colliders
            RigidbodyInertia rb_backup = new RigidbodyInertia(vessel.rootPart.rb);

            Part new_part = snapshot.Load(vessel, false);

            vessel.Parts.Add(new_part);

            if (vessel.packed)
            {
                GameEvents.onVesselWasModified.Fire(vessel);
            }
            else
            {
                // Request initialization as nonphysical to prevent explosions
                new_part.physicalSignificance = Part.PhysicalSignificance.NONE;

                // Disable all sub-objects with colliders
                List <Collider> re_enable = new List <Collider>();

                foreach (var collider in new_part.GetComponentsInChildren <Collider>())
                {
                    if (collider.gameObject.activeSelf)
                    {
                        re_enable.Add(collider);
                        collider.gameObject.SetActive(false);
                    }
                }

                new_part.StartCoroutine(WaitAndUnpack(new_part, re_enable));
            }

            rb_backup.Restore(vessel.rootPart.rb);

            return(new_part);
        }
Exemple #6
0
        protected override void OnAccepted()
        {
            // Actually spawn the kerbals in the game world!
            foreach (KerbalData kerbal in kerbals)
            {
                LoggingUtil.LogVerbose(this, "Spawning a Kerbal named " + kerbal.name);

                if (kerbal.altitude == null)
                {
                    kerbal.altitude = LocationUtil.TerrainHeight(kerbal.latitude, kerbal.longitude, kerbal.body);
                }

                // Set additional info for landed kerbals
                if (kerbal.landed)
                {
                    Vector3d pos = kerbal.body.GetWorldSurfacePosition(kerbal.latitude, kerbal.longitude, kerbal.altitude.Value);

                    kerbal.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, kerbal.body);
                    kerbal.orbit.UpdateFromStateVectors(pos, kerbal.body.getRFrmVel(pos), kerbal.body, Planetarium.GetUniversalTime());
                    LoggingUtil.LogVerbose(typeof(SpawnKerbal), "kerbal generated, orbit = " + kerbal.orbit);
                }

                uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);

                // Create crew member array
                ProtoCrewMember[] crewArray = new ProtoCrewMember[1];
                crewArray[0] = kerbal.crewMember;

                // Create part nodes
                ConfigNode[] partNodes = new ConfigNode[1];
                partNodes[0] = ProtoVessel.CreatePartNode("kerbalEVA", flightId, crewArray);

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

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

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

                // Add vessel to the game
                HighLogic.CurrentGame.AddVessel(protoVesselNode);
            }
        }
Exemple #7
0
        //creation
        public static Vessel Create(Creature creature, Vector3 positionOffset)
        {
            try
            {
                AvailablePart partInfo      = PartLoader.LoadedPartsList.First(ap => ap.name == creature.part);
                Part          referencePart = FlightGlobals.ActiveVessel.rootPart;

                Part part = (Part)UnityEngine.Object.Instantiate(partInfo.partPrefab);
                part.gameObject.SetActive(true);
                part.gameObject.name = partInfo.name;
                part.partInfo        = partInfo;
                part.SetMirror(Vector3.one);

                ShipConstruct sc = new ShipConstruct();
                sc.Add(part);
                sc.SaveShip();
                sc.shipName = creature.name;

                Vessel vessel = sc.parts[0].localRoot.gameObject.AddComponent <Vessel>();
                vessel.id         = Guid.NewGuid();
                vessel.vesselName = sc.shipName;
                vessel.vesselType = VesselType.Unknown;
                //vessel.DiscoveryInfo.Load(ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A, 10000, 10000));
                vessel.ctrlState = new FlightCtrlState();
                vessel.ctrlState.NeutralizeAll();
                vessel.Initialize(false);
                vessel.Landed = false;
                vessel.SetPosition(referencePart.transform.position + positionOffset);
                vessel.SetRotation(Quaternion.identity);

                //manually remove orbit renderer
                UnityEngine.Object.Destroy(vessel.orbitDriver.Renderer);

                CreaturePart cp = (CreaturePart)vessel.rootPart;
                cp.creature  = creature;
                cp.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                cp.missionID = referencePart.missionID;
                cp.flagURL   = referencePart.flagURL;

                FlightLogger.eventLog.Add(Utils.FormatTime(referencePart.vessel.missionTime) + "A " + creature.name + " was seen.");

                return(vessel);
            }
            catch (Exception e)
            {
                Utils.LogError("Error encountered while spawning part");
                if (e != null)
                {
                    Debug.LogException(e);
                }
            }

            return(null);
        }
Exemple #8
0
        public static Part CreatePart(AvailablePart avPart, Vector3 position, Quaternion rotation, Part flagFromPart)
        {
            UnityEngine.Object obj = UnityEngine.Object.Instantiate(avPart.partPrefab);
            if (!obj)
            {
                KAS_Shared.DebugError("CreatePart(Crate) Failed to instantiate " + avPart.partPrefab.name);
                return(null);
            }

            Part newPart = (Part)obj;

            newPart.gameObject.SetActive(true);
            newPart.gameObject.name  = "KASCreatedPart";
            newPart.partInfo         = avPart;
            newPart.highlightRecurse = true;

            ShipConstruct newShip = new ShipConstruct();

            newShip.Add(newPart);
            newShip.SaveShip();
            newShip.shipName = avPart.title;
            newShip.shipType = 1;

            VesselCrewManifest vessCrewManifest = new VesselCrewManifest();
            Vessel             currentVessel    = FlightGlobals.ActiveVessel;

            Vessel v = newShip.parts[0].localRoot.gameObject.AddComponent <Vessel>();

            v.id         = Guid.NewGuid();
            v.vesselName = newShip.shipName;
            v.Initialize(false);
            v.Landed             = true;
            v.rootPart.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            v.rootPart.missionID = (uint)Guid.NewGuid().GetHashCode();
            v.rootPart.flagURL   = flagFromPart.flagURL;

            //v.rootPart.collider.isTrigger = true;

            v.rootPart.FindModelTransform("model").localScale *= v.rootPart.rescaleFactor;


            //v.landedAt = "somewhere";

            Staging.beginFlight();
            newShip.parts[0].vessel.ResumeStaging();
            Staging.GenerateStagingSequence(newShip.parts[0].localRoot);
            Staging.RecalculateVesselStaging(newShip.parts[0].vessel);

            FlightGlobals.SetActiveVessel(currentVessel);

            v.SetPosition(position);
            v.SetRotation(rotation);
            return(newPart);
        }
Exemple #9
0
        private static ConfigNode CreateVesselNode(PlacementRequest request, Orbit orbit)
        {
            // create an id for the flight object that will represent the kerbal's EVA
            var genderQualifier = request.Kerbal.gender == ProtoCrewMember.Gender.Female ? "female" : string.Empty;
            var flightId        = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);

            $"created flightId {flightId}".Debug();

            // create a ship consisting of just the kerbal - this is how EVAs are represented in KSP
            var partNodes = new ConfigNode[1];

            partNodes[0] =
                ProtoVessel.CreatePartNode($"kerbalEVA{genderQualifier}", flightId, request.Kerbal);
            "created partNodes".Debug();
            var vesselNode = ProtoVessel.CreateVesselNode(request.Kerbal.name, VesselType.EVA, orbit, 0, partNodes);

            "created vesselNode".Debug();
            return(vesselNode);
        }
Exemple #10
0
        private static void GenerateStrandedKerbal(int bodyId, string kerbalName)
        {
            //Add kerbal to crew roster.
            LunaLog.Log($"[LMP]: Spawning missing kerbal, Name: {kerbalName}");

            var pcm = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Unowned);

            pcm.ChangeName(kerbalName);
            pcm.rosterStatus = ProtoCrewMember.RosterStatus.Assigned;

            //Create protovessel
            var newPartId    = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            var contractBody = FlightGlobals.Bodies[bodyId];

            //Atmo: 10km above atmo, to half the planets radius out.
            //Non-atmo: 30km above ground, to half the planets radius out.
            var minAltitude = CelestialUtilities.GetMinimumOrbitalDistance(contractBody, 1.1f);
            var maxAltitude = minAltitude + contractBody.Radius * 0.5;

            var strandedOrbit = Orbit.CreateRandomOrbitAround(FlightGlobals.Bodies[bodyId], minAltitude, maxAltitude);

            var kerbalPartNode = new[] { ProtoVessel.CreatePartNode("kerbalEVA", newPartId, pcm) };

            var protoVesselNode = ProtoVessel.CreateVesselNode(kerbalName, VesselType.EVA, strandedOrbit, 0,
                                                               kerbalPartNode);

            //It's not supposed to be infinite, but you're crazy if you think I'm going to decipher the values field of the rescue node.
            var discoveryNode = ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A,
                                                                double.PositiveInfinity,
                                                                double.PositiveInfinity);

            var protoVessel = new ProtoVessel(protoVesselNode, HighLogic.CurrentGame)
            {
                discoveryInfo = discoveryNode
            };

            HighLogic.CurrentGame.flightState.protoVessels.Add(protoVessel);
        }
        protected override void OnAccepted()
        {
            // Actually spawn the kerbals in the game world!
            foreach (KerbalData kerbal in kerbals)
            {
                uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);

                // Create crew member array
                ProtoCrewMember[] crewArray = new ProtoCrewMember[1];
                crewArray[0] = kerbal.crewMember;

                // Create part nodes
                ConfigNode[] partNodes = new ConfigNode[1];
                partNodes[0] = ProtoVessel.CreatePartNode("kerbalEVA", flightId, crewArray);

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

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

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

                // Add vessel to the game
                HighLogic.CurrentGame.AddVessel(protoVesselNode);
            }
        }
        protected void CreateVessels()
        {
            if (vesselsCreated)
            {
                return;
            }

            String gameDataDir = KSPUtil.ApplicationRootPath;

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

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

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

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

                // Restore ShipConstruction ship
                ShipConstruction.ShipConfig = currentShip;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            vesselsCreated = true;
        }
        void SpawnVessel(string craftURL, CelestialBody orbitmainBodyName, double altitude, string stationName)
        {
            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                if (vessel.vesselName == stationName)
                {
                    vessel.Die();
                    break;
                }
            }
            VesselData vesselData = new VesselData();

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

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

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

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

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

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

            vesselData.id = protoVessel.vesselRef.id;
            foreach (var p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
        }
Exemple #14
0
        public static Debris SetupOnTransform(
            Part original_part,
            Transform debris_transform,
            float mass,
            float cost,
            double lifetime
            )
        {
            //get the part form DB
            var info = PartLoader.getPartInfoByName(DEBRIS_PART);

            if (info == null)
            {
                return(null);
            }
            //set part's transform and parent the debris model to the part
            var part          = Instantiate(info.partPrefab);
            var partTransform = part.transform;

            partTransform.position = debris_transform.position;
            partTransform.rotation = original_part.transform.rotation;
            //copy the model and resize it
            var debris_object     = Instantiate(debris_transform.gameObject).transform;
            var debris_part_model = part.transform.Find("model");
            var orig_part_model   = original_part.transform.Find("model");

            debris_object.parent         = debris_part_model;
            debris_object.localPosition  = Vector3.zero;
            debris_object.rotation       = debris_transform.rotation;
            debris_part_model.localScale = Vector3.Scale(debris_part_model.localScale, orig_part_model.localScale);
            debris_part_model.hasChanged = true;
            part.transform.hasChanged    = true;
            //initialize the part
            part.gameObject.SetActive(true);
            part.physicalSignificance = Part.PhysicalSignificance.NONE;
            part.PromoteToPhysicalPart();
            part.Rigidbody.mass = mass;
            part.orgPos         = Vector3.zero;
            part.orgRot         = Quaternion.identity;
            //initialize Debris module
            var debris = part.Modules.GetModule <Debris>();

            if (debris == null)
            {
                Utils.Log("WARNING: {} part does not have Debris module!", DEBRIS_PART);
                Destroy(part.gameObject);
                return(null);
            }
            debris.actual_object         = debris_object;
            debris.saved_cost            = cost;
            debris.saved_mass            = part.Rigidbody.mass;
            debris.original_part_name    = original_part.partInfo.name;
            debris.debris_transform_name = debris_transform.name;
            debris.local_rotation        = debris_object.localRotation;
            debris.local_scale           = debris_object.parent.localScale;
            debris_transform.gameObject.SetActive(false);
            //initialize the vessel
            var vessel = part.gameObject.AddComponent <Vessel>();

            vessel.name = vessel.vesselName = "Debris";
            vessel.id   = Guid.NewGuid();
            vessel.Initialize();
            //setup ids and flag
            part.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            part.missionID = original_part.missionID;
            part.launchID  = original_part.launchID;
            part.flagURL   = original_part.flagURL;
            //set part's velocities
            part.Rigidbody.angularVelocity = original_part.Rigidbody.angularVelocity;
            part.Rigidbody.velocity        = original_part.Rigidbody.velocity
                                             + Vector3.Cross(
                original_part.Rigidbody.worldCenterOfMass - part.Rigidbody.worldCenterOfMass,
                part.Rigidbody.angularVelocity);
            //setup discovery info
            vessel.DiscoveryInfo.SetLastObservedTime(Planetarium.GetUniversalTime());
            vessel.DiscoveryInfo.SetUnobservedLifetime(lifetime);
            vessel.DiscoveryInfo.SetUntrackedObjectSize(UntrackedObjectClass.A);
            vessel.DiscoveryInfo.SetLevel(DiscoveryLevels.Owned);
            //inform the game about the new vessel
            GameEvents.onNewVesselCreated.Fire(vessel);
            //return the part
            return(debris);
        }
        static void SpawnVessel(VesselData vesselData)
        {
            string gameDataDir = KSPUtil.ApplicationRootPath;

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

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

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

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

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

            vesselData.id = protoVessel.vesselRef.id;
            foreach (var p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
            if (vesselData.vesselType == VesselType.Ship)
            {
                setResourcesAmount(protoVessel.vesselRef);
            }
            if (vesselData.vesselType == VesselType.Station)
            {
                setScience(protoVessel.vesselRef);
            }
        }
Exemple #16
0
        /// <remarks>
        ///     This code is based on KAS by KospY and the following license applies:
        ///     http://kerbal.curseforge.com/ksp-mods/223900-kerbal-attachment-system-kas/license (link valid 03.09.2014)
        ///     Usage of this code by me (marce) has been generously granted by KospY on 02.09.2014 per PM.
        /// </remarks>
        public static Part SpawnPartInFlight(string partName, Part referencePart, Vector3 referencePartOriginSpawnOffset, Quaternion spawnRotation, bool spawnLanded = true)
        {
            if (!HighLogic.LoadedSceneIsFlight)
            {
                Debug.Log(LOG_PREFIX + " can only spawn in flight");
                return(null);
            }
            var currentVessel = FlightGlobals.ActiveVessel;
            var avPart        = PartLoader.getPartInfoByName(partName);

            if (avPart == null)
            {
                Debug.Log(LOG_PREFIX + " failed to find part " + partName);
                return(null);
            }
            var obj = UnityEngine.Object.Instantiate(avPart.partPrefab);

            if (obj == null)
            {
                Debug.Log(LOG_PREFIX + " failed to instantiate part " + partName);
                return(null);
            }
            try
            {
                var newPart = (Part)obj;
                newPart.gameObject.SetActive(true);
                newPart.gameObject.name = avPart.name;
                newPart.partInfo        = avPart;
                //newPart.highlightRecurse = true;
                newPart.SetMirror(Vector3.one);
                var newShip = new ShipConstruct {
                    newPart
                };
                newShip.SaveShip();
                newShip.shipName = avPart.title;
                var type = Convert.ChangeType(VesselType.Debris, VesselType.Debris.GetTypeCode());
                //if (type != null)
                //{
                //    newShip.shipType = (int) type;
                //}
                //else
                //{
                //    newShip.shipType = 1;
                //}
                var v = newShip.parts[0].localRoot.gameObject.AddComponent <Vessel>();
                v.id         = Guid.NewGuid();
                v.vesselName = newShip.shipName;
                v.Initialize();
                v.Landed             = spawnLanded;
                v.rootPart.flightID  = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
                v.rootPart.missionID = referencePart.missionID;
                v.rootPart.flagURL   = referencePart.flagURL;
                FlightGlobals.SetActiveVessel(currentVessel);
                v.SetPosition(referencePart.transform.position + referencePartOriginSpawnOffset);
                v.SetRotation(spawnRotation);
                for (var i = 0; i < newPart.Modules.Count; i++)
                {
                    var node = new ConfigNode();
                    node.AddValue("name", newPart.Modules[i].moduleName);
                    var j = i;
                    newPart.LoadModule(node, ref j);
                }
                return(newPart);
            }
            catch (NullReferenceException)
            {
                Debug.Log(LOG_PREFIX + " part unknown");
                return(null);
            }
        }
Exemple #17
0
        public static Part CreatePart(ConfigNode partConfig, Vector3 position, Quaternion rotation, Part fromPart, Part coupleToPart = null, string srcAttachNodeID = null, AttachNode tgtAttachNode = null, OnPartCoupled onPartCoupled = null)
        {
            ConfigNode node_copy = new ConfigNode();

            partConfig.CopyTo(node_copy);
            ProtoPartSnapshot snapshot = new ProtoPartSnapshot(node_copy, null, HighLogic.CurrentGame);

            if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) || snapshot.flightID == 0)
            {
                snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            }
            snapshot.parentIdx           = 0;
            snapshot.position            = position;
            snapshot.rotation            = rotation;
            snapshot.stageIndex          = 0;
            snapshot.defaultInverseStage = 0;
            snapshot.seqOverride         = -1;
            snapshot.inStageIndex        = -1;
            snapshot.attachMode          = (int)AttachModes.SRF_ATTACH;
            snapshot.attached            = true;
            snapshot.connected           = true;
            snapshot.flagURL             = fromPart.flagURL;

            Part newPart = snapshot.Load(fromPart.vessel, false);

            newPart.transform.position = position;
            newPart.transform.rotation = rotation;
            newPart.missionID          = fromPart.missionID;

            fromPart.vessel.Parts.Add(newPart);

            newPart.physicalSignificance = Part.PhysicalSignificance.NONE;
            newPart.PromoteToPhysicalPart();
            newPart.Unpack();
            newPart.InitializeModules();

            if (coupleToPart)
            {
                newPart.rigidbody.velocity        = coupleToPart.rigidbody.velocity;
                newPart.rigidbody.angularVelocity = coupleToPart.rigidbody.angularVelocity;
            }
            else
            {
                if (fromPart.rigidbody)
                {
                    newPart.rigidbody.velocity        = fromPart.rigidbody.velocity;
                    newPart.rigidbody.angularVelocity = fromPart.rigidbody.angularVelocity;
                }
                else
                {
                    // If fromPart is a carried container
                    newPart.rigidbody.velocity        = fromPart.vessel.rootPart.rigidbody.velocity;
                    newPart.rigidbody.angularVelocity = fromPart.vessel.rootPart.rigidbody.angularVelocity;
                }
            }

            newPart.decouple();

            if (coupleToPart)
            {
                newPart.StartCoroutine(WaitAndCouple(newPart, coupleToPart, srcAttachNodeID, tgtAttachNode, onPartCoupled));
            }
            else
            {
                newPart.vessel.vesselType = VesselType.Unknown;
                //name container
                ModuleKISInventory inv = newPart.GetComponent <ModuleKISInventory>();
                if (inv)
                {
                    if (inv.invName != "")
                    {
                        newPart.vessel.vesselName = inv.part.partInfo.title + " | " + inv.invName;
                    }
                    else
                    {
                        newPart.vessel.vesselName = inv.part.partInfo.title;
                    }
                }
            }
            return(newPart);
        }
Exemple #18
0
        public static Vessel AssembleForLaunchUnlanded(ShipConstruct ship, IEnumerable <string> crewToDeliver, double duration, Orbit orbit,
                                                       string flagUrl, Game sceneState)
        {
            var localRoot = ship.parts[0].localRoot;
            var vessel    = localRoot.gameObject.GetComponent <Vessel>();

            if (vessel == null)
            {
                vessel = localRoot.gameObject.AddComponent <Vessel>();
            }

            vessel.id           = Guid.NewGuid();
            vessel.vesselName   = ship.shipName;
            vessel.persistentId = ship.persistentId;
            vessel.Initialize();
            if (orbit != null)
            {
                var orbitDriver = vessel.gameObject.GetComponent <OrbitDriver>();
                if (orbitDriver == null)
                {
                    orbitDriver        = vessel.gameObject.AddComponent <OrbitDriver>();
                    vessel.orbitDriver = orbitDriver;
                }
            }
            vessel.Landed   = false;
            vessel.Splashed = false;
            vessel.skipGroundPositioning = true;
            vessel.vesselSpawning        = false;
            // vessel.loaded = false;

            var pCrewMembers = CrewRoster().Where(k => crewToDeliver.Contains(k?.name)).ToList();

            // Maybe add the initial crew to the vessel:
            if (pCrewMembers.Any())
            {
                CrewTransferBatch.moveCrew(vessel, pCrewMembers, false);
                LifeSupportWrapper.Instance.PrepForLaunch(vessel, pCrewMembers, duration);
                pCrewMembers.ForEach(pcm =>
                {
                    pcm.rosterStatus = ProtoCrewMember.RosterStatus.Assigned;
                    // Add the phases the kerbonaut would have gone through during his launch to his flight-log:
                    var homeBody = Planetarium.fetch.Home;
                    pcm.flightLog.AddEntry(FlightLog.EntryType.Launch, homeBody.bodyName);
                    pcm.flightLog.AddEntry(FlightLog.EntryType.Flight, homeBody.bodyName);
                    pcm.flightLog.AddEntry(FlightLog.EntryType.Suborbit, homeBody.bodyName);
                    pcm.flightLog.AddEntry(FlightLog.EntryType.Orbit, homeBody.bodyName);
                    if (orbit.referenceBody != homeBody)
                    {
                        pcm.flightLog.AddEntry(FlightLog.EntryType.Escape, homeBody.bodyName);
                        pcm.flightLog.AddEntry(FlightLog.EntryType.Orbit, orbit.referenceBody.bodyName);
                    }
                });
            }

            // TODO this seems like overkill so commenting out, we'll see...
            vessel.orbitDriver.UpdateOrbit();
            vessel.SetOrbit(orbit);
            vessel.orbitDriver.UpdateOrbit();
            var hashCode = (uint)Guid.NewGuid().GetHashCode();
            var launchId = HighLogic.CurrentGame.launchID++;

            foreach (var part in vessel.parts)
            {
                part.flightID  = ShipConstruction.GetUniqueFlightID(sceneState.flightState);
                part.missionID = hashCode;
                part.launchID  = launchId;
                part.flagURL   = flagUrl;
            }
            if (localRoot.isControlSource == Vessel.ControlLevel.NONE)
            {
                var firstCrewablePart = ShipConstruction.findFirstCrewablePart(ship.parts[0]);
                if (firstCrewablePart == null)
                {
                    var firstControlSource = ShipConstruction.findFirstControlSource(vessel);
                    firstCrewablePart = firstControlSource ?? localRoot;
                }
                vessel.SetReferenceTransform(firstCrewablePart, true);
            }
            else
            {
                vessel.SetReferenceTransform(localRoot, true);
            }

            Debug.Log("Vessel assembled for launch: " + vessel.vesselName);
            return(vessel);
        }
Exemple #19
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);
                }
            }
        }
Exemple #20
0
        internal void Spawn()
        {
            KD kd = new KD();

            Log.Info("Spawning a GeoCache");

            // Set additional info for landed
            if (kd.landed)
            {
                Vector3d pos = kd.body.GetWorldSurfacePosition(kd.latitude, kd.longitude, kd.altitude);

                kd.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, kd.body);
                kd.orbit.UpdateFromStateVectors(pos, kd.body.getRFrmVel(pos), kd.body, Planetarium.GetUniversalTime());
            }
            else
            {
                // Update the reference body in the orbit
                kd.orbit.referenceBody = kd.body;
            }

            uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);


            kd.craftPart = PartLoader.getPartInfoByName("geocache");
            // Create part nodes
            ConfigNode[] partNodes = new ConfigNode[1];
            partNodes[0] = ProtoVessel.CreatePartNode(kd.craftPart.name, flightId, null);


            // Create additional nodes
            ConfigNode[] additionalNodes = new ConfigNode[0];
            // Create the config node representation of the ProtoVessel
            ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(VesselName, VesselType.Probe, kd.orbit, 0, partNodes);

            // Additional seetings for a landed vessel
            if (kd.landed)
            {
                bool splashed = kd.altitude < 0.001 && kd.body.ocean;

                // Add a bit of height for landed
                if (!splashed)
                {
                    kd.altitude += 40.2;
                    Log.Info("Adding 40.2 to altitude");
                }
                //Guid vesselId = vessel.id;

                // Figure out the appropriate rotation
                Vector3d norm          = kd.body.GetRelSurfaceNVector(kd.latitude, kd.longitude);
                double   terrainHeight = 0.0;
                if (kd.body.pqsController != null)
                {
                    terrainHeight = kd.body.pqsController.GetSurfaceHeight(norm) - kd.body.pqsController.radius;
                }

                // Create the config node representation of the ProtoVessel

                protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : Vessel.Situations.LANDED).ToString());
                protoVesselNode.SetValue("landed", (!splashed).ToString());
                protoVesselNode.SetValue("splashed", splashed.ToString());
                protoVesselNode.SetValue("lat", kd.latitude);
                protoVesselNode.SetValue("lon", kd.longitude);
                protoVesselNode.SetValue("alt", kd.altitude);
                protoVesselNode.SetValue("landedAt", kd.body.name);

                float lowest = float.MaxValue;
                foreach (Collider collider in kd.craftPart.partPrefab.GetComponentsInChildren <Collider>())
                {
                    if (collider.gameObject.layer != 21 && collider.enabled)
                    {
                        lowest = Mathf.Min(lowest, collider.bounds.min.y);
                    }
                }
                if (Mathf.Approximately(lowest, float.MaxValue))
                {
                    lowest = 0;
                }

                float hgt = kd.craftPart.partPrefab.localRoot.attPos0.y - lowest;
                hgt += 10;
                protoVesselNode.SetValue("hgt", hgt);

                // Set the normal vector relative to the surface
                Quaternion normal   = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                Quaternion rotation = Quaternion.identity;
                rotation = rotation * Quaternion.FromToRotation(Vector3.up, Vector3.back);
                Vector3 nrm = (rotation * Vector3.forward);
                protoVesselNode.SetValue("prst", false.ToString());
                protoVesselNode.SetValue("nrm", nrm.x + "," + nrm.y + "," + nrm.z);
            }
            ProtoVessel protoVessel = HighLogic.CurrentGame.AddVessel(protoVesselNode);

            //protoVessel.Load(HighLogic.CurrentGame.flightState);

            protoVessel.vesselName = VesselName;

            vessel = protoVessel.vesselRef;
            if (vessel != null)
            {
                //var mode = OrbitDriver.UpdateMode.UPDATE;
                //vessel.orbitDriver.SetOrbitMode(mode);

                vessel.Load();
                launchPoint = vessel.GetWorldPos3D();
                // Offset the position by 10m in y and z to have it created away from the current vessel
                launchPoint.y += 10;
                launchPoint.z += 10;

                StartCoroutine("SpawnCoRoutine");
            }
        }
Exemple #21
0
            /// <summary>
            /// Spawn ship construct
            /// https://github.com/KospY/KAS/blob/master/Plugin/KAS_Shared.cs
            /// </summary>
            /// <param name="_shipConstruct">Shipconstruct to spawn</param>
            /// <param name="_srcPart">Source part to spawn relative to</param>
            /// <param name="_spawnOffset">Offset spawn from Source part position</param>
            private void SpawnVessel(ShipConstruct _shipConstruct, Part _srcPart, Vector3 _spawnOffset)
            {
                //Store construct root
                Part _newConstructRootPart = _shipConstruct.parts[0];

                //Center rootpart
                Vector3 offset = _newConstructRootPart.transform.localPosition;

                _newConstructRootPart.transform.Translate(-offset);

                //Get launch spawn point, relative to part
                Transform  t         = _srcPart.transform;
                GameObject launchPos = new GameObject();

                launchPos.transform.parent    = _srcPart.transform;
                launchPos.transform.position  = t.position;
                launchPos.transform.position += t.TransformDirection(_spawnOffset);
                launchPos.transform.rotation  = t.rotation;
                //Store our launch / spawn position
                Transform launchTransform = launchPos.transform;

                //Kill original object
                launchPos.DestroyGameObject();
                //Set rootpart origin
                _shipConstruct.Parts[0].localRoot.transform.Translate(launchPos.transform.position, Space.World);
                //Position
                float   angle;
                Vector3 axis;

                //Extract ToAngleAxis data from selected spawning location
                launchTransform.rotation.ToAngleAxis(out angle, out axis);
                //TRANSFORM Rotate localRootPart in relation to root
                _shipConstruct.Parts[0].localRoot.transform.RotateAround(launchTransform.position, axis, angle);

                //Create vessel object
                Vessel _newVessel = _newConstructRootPart.localRoot.gameObject.AddComponent <Vessel>();

                //Attach vessel information
                _newVessel.id         = Guid.NewGuid();
                _newVessel.vesselName = _srcPart.vessel.vesselName + " - " + _shipConstruct.shipName;
                _newVessel.landedAt   = _srcPart.vessel.vesselName;

                //Store backup
                ShipConstruction.CreateBackup(_shipConstruct);

                //Init from VAB
                _newVessel.Initialize(true);
                //Set Landed
                _newVessel.Landed = true;

                //_newVessel.situation = Vessel.Situations.PRELAUNCH;
                // _newVessel.GoOffRails();
                //_newVessel.IgnoreGForces(240);


                //Set Orbit
                InitiateOrbit(launchTransform.position, _srcPart.vessel, _newVessel);

                //Set Mission info
                uint   missionId = (uint)Guid.NewGuid().GetHashCode();
                string flagUrl   = _srcPart.flagURL;
                uint   launchId  = HighLogic.CurrentGame.launchID++;

                //Set part mission info
                for (int i = 0; i < _newVessel.parts.Count; i++)
                {
                    Part part = _newVessel.parts[i];
                    part.flightID  = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState);
                    part.flagURL   = flagUrl;
                    part.launchID  = launchId;
                    part.missionID = missionId;
                }

                //Generate staging
                KSP.UI.Screens.StageManager.BeginFlight();
                _newConstructRootPart.vessel.ResumeStaging();
                KSP.UI.Screens.StageManager.GenerateStagingSequence(_newConstructRootPart.localRoot);
                KSP.UI.Screens.StageManager.RecalculateVesselStaging(_newConstructRootPart.vessel);

                //Set position, again
                _newVessel.SetPosition(launchTransform.position);
                _newVessel.SetRotation(launchTransform.rotation);



                //Save Protovessel
                ProtoVessel _newProto = new ProtoVessel(_newVessel);

                //Kill and remove spawned vessel, had some serious problems with spawn position warping/glitching
                _newVessel.Die();

                //Set the protovessels position to the relative one we found, maybe redundant
                _newProto.position = launchPos.transform.position;

                //If you check this value, you will see the height change from launch scene to resume scene, extra dafuq
                //float height = _newProto.height;

                if (FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_FILE ||
                    FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_CACHE)
                {
                    //Odd behaviour with positioning during different flight scenes, workaround awaaaay
                    Log.Info("Workaround of height");
                    _newProto.height = TrueAlt(launchTransform.position, _srcPart.vessel);
                }
                _newProto.altitude += 10;
                _newProto.height   += 10;
                _newProto.situation = Vessel.Situations.FLYING;

                //Load Protovessel
                _newProto.Load(HighLogic.CurrentGame.flightState);

                // _newVessel.GoOnRails();

                // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB
                ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode();

                //Fix Control Lock
                FlightInputHandler.ResumeVesselCtrlState(FlightGlobals.ActiveVessel);
                //Fix active vessel staging
                FlightGlobals.ActiveVessel.ResumeStaging();
            }
        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);
        }
Exemple #23
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 #24
0
        public static Vessel AssembleForLaunchUnlanded(ShipConstruct ship, Orbit orbit,
                                                       string flagURL, Game sceneState)
        {
            var localRoot = ship.parts[0].localRoot;
            var vessel    = localRoot.gameObject.GetComponent <Vessel>();

            if (vessel == null)
            {
                vessel = localRoot.gameObject.AddComponent <Vessel>();
            }
            vessel.id           = Guid.NewGuid();
            vessel.vesselName   = Localizer.Format(ship.shipName);
            vessel.persistentId = ship.persistentId;
            if (orbit != null)
            {
                var orbitDriver = vessel.gameObject.GetComponent <OrbitDriver>();
                if (orbitDriver == null)
                {
                    orbitDriver = vessel.gameObject.AddComponent <OrbitDriver>();
                }
                orbitDriver.orbit = orbit;
            }
            vessel.Initialize(true);
            vessel.orbitDriver.updateMode = OrbitDriver.UpdateMode.TRACK_Phys;
            vessel.skipGroundPositioning  = true;
            vessel.vesselSpawning         = false;
            vessel.Landed = false;
            var hashCode = (uint)Guid.NewGuid().GetHashCode();
            var launchID = HighLogic.CurrentGame.launchID++;

            for (int i = 0, count = vessel.parts.Count; i < count; ++i)
            {
                var p = vessel.parts[i];
                p.flightID  = ShipConstruction.GetUniqueFlightID(sceneState.flightState);
                p.missionID = hashCode;
                p.launchID  = launchID;
                p.flagURL   = flagURL;
            }
            if (localRoot.isControlSource == Vessel.ControlLevel.NONE)
            {
                var firstCrewablePart = ShipConstruction.findFirstCrewablePart(ship.parts[0]);
                if (firstCrewablePart == null)
                {
                    var firstControlSource = ShipConstruction.findFirstControlSource(vessel);
                    if (firstControlSource == null)
                    {
                        firstCrewablePart = localRoot;
                    }
                    else
                    {
                        firstCrewablePart = firstControlSource;
                    }
                }
                vessel.SetReferenceTransform(firstCrewablePart, true);
            }
            else
            {
                vessel.SetReferenceTransform(localRoot, true);
            }
            Utils.Log("Vessel assembled for launch: " + vessel.GetDisplayName());
            return(vessel);
        }
        protected override void OnAccepted()
        {
            // Actually spawn the kerbals in the game world!
            foreach (KerbalData kd in kerbals)
            {
                LoggingUtil.LogVerbose(this, "Spawning a Kerbal named " + kd.kerbal.name);

                // Generate the ProtoCrewMember
                kd.kerbal.GenerateKerbal();

                if (kd.altitude == null)
                {
                    kd.altitude = LocationUtil.TerrainHeight(kd.latitude, kd.longitude, kd.body);
                }

                // Set additional info for landed kerbals
                if (kd.landed)
                {
                    Vector3d pos = kd.body.GetWorldSurfacePosition(kd.latitude, kd.longitude, kd.altitude.Value);

                    kd.orbit = new Orbit(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, kd.body);
                    kd.orbit.UpdateFromStateVectors(pos, kd.body.getRFrmVel(pos), kd.body, Planetarium.GetUniversalTime());
                    LoggingUtil.LogVerbose(typeof(SpawnKerbal), "kerbal generated, orbit = " + kd.orbit);
                }
                else
                {
                    // Update the reference body in the orbit
                    kd.orbit.referenceBody = kd.body;
                }

                uint flightId = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);

                // Create crew member array
                ProtoCrewMember[] crewArray = new ProtoCrewMember[1];
                crewArray[0] = kd.kerbal.pcm;

                // Create part nodes
                ConfigNode[] partNodes = new ConfigNode[1];
                partNodes[0] = ProtoVessel.CreatePartNode(kd.kerbal.gender == ProtoCrewMember.Gender.Male ? "kerbalEVA" : "kerbalEVAfemale",
                                                          flightId, crewArray);

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

                // Create the config node representation of the ProtoVessel
                ConfigNode protoVesselNode = ProtoVessel.CreateVesselNode(kd.kerbal.name, VesselType.EVA, kd.orbit, 0, partNodes, additionalNodes);

                // Additional seetings for a landed Kerbal
                if (kd.landed)
                {
                    bool splashed = kd.altitude.Value < 0.001 && kd.body.ocean;

                    // Add a bit of height for landed kerbals
                    if (!splashed)
                    {
                        kd.altitude += 0.2;
                    }

                    // Figure out the appropriate rotation
                    Vector3d   norm     = kd.body.GetRelSurfaceNVector(kd.latitude, kd.longitude);
                    Quaternion normal   = Quaternion.LookRotation(new Vector3((float)norm.x, (float)norm.y, (float)norm.z));
                    Quaternion rotation = Quaternion.FromToRotation(Vector3.up, Vector3.forward);
                    rotation = rotation * Quaternion.AngleAxis(kd.heading + 180, Vector3.up);

                    // Create the config node representation of the ProtoVessel
                    protoVesselNode.SetValue("sit", (splashed ? Vessel.Situations.SPLASHED : Vessel.Situations.LANDED).ToString());
                    protoVesselNode.SetValue("landed", (!splashed).ToString());
                    protoVesselNode.SetValue("splashed", splashed.ToString());
                    protoVesselNode.SetValue("lat", kd.latitude.ToString());
                    protoVesselNode.SetValue("lon", kd.longitude.ToString());
                    protoVesselNode.SetValue("alt", kd.altitude.ToString());
                    protoVesselNode.SetValue("rot", KSPUtil.WriteQuaternion(normal * rotation));

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

                // Add vessel to the game
                HighLogic.CurrentGame.AddVessel(protoVesselNode);
            }
        }
    private void SpawnVessel(VesselData vesselData, List<ProtoCrewMember> crewData = null)
    {
      string gameDataDir = KSPUtil.ApplicationRootPath;
      Log.info("Spawning a vessel named '" + vesselData.name + "'");

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

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

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

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

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

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

        // Restore ShipConstruction ship
        ShipConstruction.ShipConfig = currentShip;

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

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

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

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

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

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

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

        // Create the ship's parts

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




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

          crewArray[i++] = crewMember;
        }

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

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

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

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

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

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

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

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

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

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

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

          //rotation = craftRotation;


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

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

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

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

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

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

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

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


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

      //protoVessel.vesselRef.currentStage = 0;

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

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



      //destroy prefabs
      foreach (Part p in FindObjectsOfType<Part>())
      {
        if (!p.vessel)
        {
          Destroy(p.gameObject);
        }
      }
    }
Exemple #27
0
        public static Part CreatePart(ConfigNode partConfig, Vector3 position, Quaternion rotation,
                                      Part fromPart, Part coupleToPart = null,
                                      string srcAttachNodeID           = null, AttachNode tgtAttachNode = null,
                                      OnPartCoupled onPartCoupled      = null)
        {
            var node_copy = new ConfigNode();

            partConfig.CopyTo(node_copy);
            var snapshot = new ProtoPartSnapshot(node_copy, null, HighLogic.CurrentGame);

            if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) ||
                snapshot.flightID == 0)
            {
                snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            }
            snapshot.parentIdx           = 0;
            snapshot.position            = position;
            snapshot.rotation            = rotation;
            snapshot.stageIndex          = 0;
            snapshot.defaultInverseStage = 0;
            snapshot.seqOverride         = -1;
            snapshot.inStageIndex        = -1;
            snapshot.attachMode          = (int)AttachModes.SRF_ATTACH;
            snapshot.attached            = true;
            snapshot.connected           = true;
            snapshot.flagURL             = fromPart.flagURL;

            Part newPart = snapshot.Load(fromPart.vessel, false);

            newPart.transform.position = position;
            newPart.transform.rotation = rotation;
            newPart.missionID          = fromPart.missionID;

            fromPart.vessel.Parts.Add(newPart);

            newPart.physicalSignificance = Part.PhysicalSignificance.NONE;
            newPart.PromoteToPhysicalPart();
            newPart.Unpack();
            newPart.InitializeModules();

            if (coupleToPart)
            {
                newPart.Rigidbody.velocity        = coupleToPart.Rigidbody.velocity;
                newPart.Rigidbody.angularVelocity = coupleToPart.Rigidbody.angularVelocity;
            }
            else
            {
                if (fromPart.Rigidbody)
                {
                    newPart.Rigidbody.velocity        = fromPart.Rigidbody.velocity;
                    newPart.Rigidbody.angularVelocity = fromPart.Rigidbody.angularVelocity;
                }
                else
                {
                    // If fromPart is a carried container
                    newPart.Rigidbody.velocity        = fromPart.vessel.rootPart.Rigidbody.velocity;
                    newPart.Rigidbody.angularVelocity = fromPart.vessel.rootPart.Rigidbody.angularVelocity;
                }
            }

            // New part by default is coupled with the active vessel.
            newPart.decouple();

            if (coupleToPart)
            {
                newPart.StartCoroutine(WaitAndCouple(newPart, coupleToPart, srcAttachNodeID,
                                                     tgtAttachNode, onPartCoupled));
            }
            else
            {
                RenameAssemblyVessel(newPart);
            }
            return(newPart);
        }
        /// <summary>Creates a new part from the config.</summary>
        /// <param name="partConfig">Config to read part from.</param>
        /// <param name="position">Initial position of the new part.</param>
        /// <param name="rotation">Initial rotation of the new part.</param>
        /// <param name="fromPart"></param>
        /// <param name="coupleToPart">Optional. Part to couple new part to.</param>
        /// <param name="srcAttachNodeId">
        /// Optional. Attach node ID on the new part to use for coupling. It's required if coupling to
        /// part is requested.
        /// </param>
        /// <param name="tgtAttachNode">
        /// Optional. Attach node on the target part to use for coupling. It's required if
        /// <paramref name="srcAttachNodeId"/> specifies a stack node.
        /// </param>
        /// <param name="onPartReady">
        /// Callback to call when new part is fully operational and its joint is created (if any). It's
        /// undetermined how long it may take before the callback is called. The calling code must expect
        /// that there will be several frame updates and at least one fixed frame update.
        /// </param>
        /// <param name="createPhysicsless">
        /// Tells if new part must be created without rigidbody and joint. It's only used to create
        /// equippable parts. Any other use-case is highly unlikely.
        /// </param>
        /// <returns></returns>
        public static Part CreatePart(
            ConfigNode partConfig,
            Vector3 position,
            Quaternion rotation,
            Part fromPart,
            Part coupleToPart        = null,
            string srcAttachNodeId   = null,
            AttachNode tgtAttachNode = null,
            OnPartReady onPartReady  = null,
            bool createPhysicsless   = false)
        {
            // Sanity checks for the parameters.
            if (coupleToPart != null)
            {
                if (srcAttachNodeId == null ||
                    srcAttachNodeId == "srfAttach" && tgtAttachNode != null ||
                    srcAttachNodeId != "srfAttach" &&
                    (tgtAttachNode == null || tgtAttachNode.id == "srfAttach"))
                {
                    // Best we can do is falling back to surface attach.
                    srcAttachNodeId = "srfAttach";
                    tgtAttachNode   = null;
                }
            }

            var refVessel    = coupleToPart != null ? coupleToPart.vessel : fromPart.vessel;
            var partNodeCopy = new ConfigNode();

            partConfig.CopyTo(partNodeCopy);
            var snapshot =
                new ProtoPartSnapshot(partNodeCopy, refVessel.protoVessel, HighLogic.CurrentGame);

            if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) ||
                snapshot.flightID == 0)
            {
                snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState);
            }
            snapshot.parentIdx = coupleToPart != null?refVessel.parts.IndexOf(coupleToPart) : 0;

            snapshot.position            = position;
            snapshot.rotation            = rotation;
            snapshot.stageIndex          = 0;
            snapshot.defaultInverseStage = 0;
            snapshot.seqOverride         = -1;
            snapshot.inStageIndex        = -1;
            snapshot.attachMode          = srcAttachNodeId == "srfAttach"
                ? (int)AttachModes.SRF_ATTACH
                : (int)AttachModes.STACK;
            snapshot.attached = true;
            snapshot.flagURL  = fromPart.flagURL;

            var newPart = snapshot.Load(refVessel, false);

            refVessel.Parts.Add(newPart);
            newPart.transform.position = position;
            newPart.transform.rotation = rotation;
            newPart.missionID          = fromPart.missionID;
            newPart.UpdateOrgPosAndRot(newPart.vessel.rootPart);

            if (coupleToPart != null)
            {
                // Wait for part to initialize and then fire ready event.
                Debug.Log("[ModuleMissileRearm]: Ready to error" + newPart + srcAttachNodeId + tgtAttachNode);
                newPart.StartCoroutine(
                    WaitAndCouple(newPart, srcAttachNodeId, tgtAttachNode, onPartReady,
                                  createPhysicsless: createPhysicsless));
            }
            else
            {
                // Create new part as a separate vessel.
                newPart.StartCoroutine(WaitAndMakeLonePart(newPart, onPartReady));
            }
            return(newPart);
        }
        private void SpawnVessel(WaldoAttackVesselData WaldoAttackVesselData, List <ProtoCrewMember> crewData = null)
        {
            //      string gameDataDir = KSPUtil.ApplicationRootPath;
            Debug.Log("[Spawn OrX Waldo Attack] Spawning " + WaldoAttackVesselData.name);

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

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

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

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

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

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

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

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

                // Restore ShipConstruction ship
                ShipConstruction.ShipConfig = currentShip;

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

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

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

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

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

                // Create the ship's parts

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

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

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

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

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

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

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

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

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

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

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

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

                    //rotation = craftRotation;


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

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

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

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

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

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

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


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

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

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

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


            //destroy prefabs
            foreach (Part p in FindObjectsOfType <Part>())
            {
                if (!p.vessel)
                {
                    Destroy(p.gameObject);
                }
            }
        }
Exemple #30
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);
        }