private void OnVesselRecovered(ProtoVessel v)
        {
            // Don't check if we're not ready to complete
            if (!ReadyToComplete())
            {
                return;
            }

            // Special handling for null vessel cases
            if (v.vesselRef == null)
            {
                VesselParameterGroup vpg = GetParameterGroupHost();
                if (vpg == null)
                {
                    SetState(ParameterState.Complete);
                }
                else
                {

                }
            }

            recovered[v.vesselRef] = true;

            CheckVessel(v.vesselRef);
        }
 public void Save()
 {
     if ((HighLogic.LoadedScene == GameScenes.FLIGHT) && (FlightGlobals.fetch.activeVessel != null))
     {
         if (FlightGlobals.fetch.activeVessel.loaded && !FlightGlobals.fetch.activeVessel.packed)
         {
             if (FlightGlobals.fetch.activeVessel.situation != Vessel.Situations.FLYING)
             {
                 savedVessel = new ConfigNode();
                 ProtoVessel tempVessel = new ProtoVessel(FlightGlobals.fetch.activeVessel);
                 tempVessel.Save(savedVessel);
                 savedSubspace = new Subspace();
                 savedSubspace.planetTime = Planetarium.GetUniversalTime();
                 savedSubspace.serverClock = TimeSyncer.fetch.GetServerClock();
                 savedSubspace.subspaceSpeed = 1f;
                 ScreenMessages.PostScreenMessage("Quicksaved!", 3f, ScreenMessageStyle.UPPER_CENTER);
             }
             else
             {
                 ScreenMessages.PostScreenMessage("Cannot quicksave - Active vessel is in flight!", 3f, ScreenMessageStyle.UPPER_CENTER);
             }
         }
         else
         {
             ScreenMessages.PostScreenMessage("Cannot quicksave - Active vessel is not loaded!", 3f, ScreenMessageStyle.UPPER_CENTER);
         }
     }
     else
     {
         ScreenMessages.PostScreenMessage("Cannot quicksave - Not in flight!", 3f, ScreenMessageStyle.UPPER_CENTER);
     }
 }
        private void RecoveryWatcher(float sci, ScienceSubject sub, ProtoVessel pv, bool reverse)
        {
            if (HighLogic.LoadedScene == GameScenes.SPACECENTER || HighLogic.LoadedScene == GameScenes.TRACKSTATION)
            {
                float DMScience = sci;
                DMUtils.DebugLog("Science Data Recovered For {0} Science", sci);

                DMScienceData DMData = DMScienceScenario.SciScenario.getDMScience(sub.title);
                if (DMData != null)
                {
                    float oldSciVal = 0f;
                    if (sub.scienceCap != 0)
                        oldSciVal = Math.Max(0f, 1f - ((sub.science - sci) / sub.scienceCap));
                    DMScience = sub.subjectValue * DMData.BaseValue * DMData.SciVal * oldSciVal;
                    DMScienceScenario.SciScenario.submitDMScience(DMData, DMScience);
                }
                if (DMScience != sci)
                {
                    float extraScience = sci - DMScience;
                    Debug.LogWarning(string.Format("[DMagic Orbital Science] [Asteroid Science Retrieval] Remove {0} Science From R&D Center After Asteroid Calculations", extraScience));
                    DMUtils.DebugLog("Remove {0} Science From R&D Center: From {1} To {2}", extraScience, ResearchAndDevelopment.Instance.Science, ResearchAndDevelopment.Instance.Science - extraScience);
                    ResearchAndDevelopment.Instance.AddScience(-1f * extraScience, TransactionReasons.ScienceTransmission);
                }
            }
        }
示例#4
0
 //add some crew to a vessel
 public static void addCrew(ProtoVessel vsl, List<ProtoCrewMember> crew)
 {
     foreach(var p in vsl.protoPartSnapshots)
     {
         if(crew.Count == 0) break;
         addCrew(p, crew);
     }
 }
 private void scienceReceived(float sci, ScienceSubject sub, ProtoVessel pv, bool reverse)
 {
     if (HighLogic.LoadedSceneIsFlight)
     {
         DMScienceData DMData = DMScienceScenario.SciScenario.getDMScience(sub.title);
         if (DMData != null)
             DMScienceScenario.SciScenario.submitDMScience(DMData, sci);
     }
 }
示例#6
0
		/// <summary>
		/// Gets the missionID of the ROOT part of the given vessel.
		/// </summary>
		/// <returns>The missionID</returns>
		/// <param name="pvessel">The ProtoVessel to get the missionID of.</param>
		public static uint GetVesselMissionID(ProtoVessel pvessel)
		{
			if(pvessel.protoPartSnapshots[pvessel.rootIndex] == null)
			{
				return 0;
			} else {
				return pvessel.protoPartSnapshots[pvessel.rootIndex].missionID;
			}
		}
示例#7
0
		public void vesselRecoveryProcessingEvent(ProtoVessel pvessel, MissionRecoveryDialog dialog, float recoveryFactor)
		{
			BeanCounter.LogFormatted_DebugOnly("---------- vesselRecoveryProcessingEvent ------------");
			BeanCounter.LogFormatted_DebugOnly("recoveryFactor: {0:f3}", recoveryFactor);
			BeanCounter.LogFormatted_DebugOnly("Vessel root missionID: {0}", BCUtils.GetVesselMissionID(pvessel));

			// Get a list of every missionID from the recovered parts
			List<uint> recovered_mission_ids = 
				(from ppart in pvessel.protoPartSnapshots
				 select ppart.missionID).ToList();

			// Get a list of every unique part ID so we can match them up
			List<uint> recovered_part_ids = 
				(from ppart in pvessel.protoPartSnapshots
				 select ppart.flightID).ToList();

			// Now lets get all of the launches that contain recovered parts
			List<BCLaunchData> recovered_launches =
				(from launch in OATBeanCounterData.data.launches
				 where recovered_mission_ids.Contains(launch.missionID)
				 select launch).ToList();

			// And finally we get the full list of every recovered part so we can flag them all as recovered
			var recoveredparts =
				from launch in recovered_launches
				from part in launch.parts
				where recovered_part_ids.Contains(part.uid)
				select part;
            
			foreach(BCVesselPartData partdata in recoveredparts)
			{
				BeanCounter.LogFormatted_DebugOnly("Flagging part as recovered: {0} - {1}", partdata.partName, partdata.uid);
				partdata.status = BCVesselPartStatus.Recovered;
			}

            BCRecoveryData recovery = new BCRecoveryData(true);
            OATBeanCounterData.data.recoveries.Add(recovery);

			recovery.partIDs = recovered_part_ids;
			recovery.recoveryFactor = recoveryFactor;

            // Try to match this to the transaction
            BCTransactionData transaction =
                (from trans in OATBeanCounterData.data.transactions
                 where trans.time == HighLogic.fetch.currentGame.UniversalTime
                 && trans.reason == TransactionReasons.VesselRecovery
                 select trans).SingleOrDefault();
            if (transaction != null)
            {
                BeanCounter.LogFormatted_DebugOnly("Found matching transaction for this recovery: {0}", transaction.id);
                recovery.transactionID = transaction.id;
                transaction.dataID = recovery.id;
            }

			BeanCounter.LogFormatted_DebugOnly("--------- /vesselRecoveryProcessingEvent ------------");
		}
 public static float GetTotalVesselCost(ProtoVessel vessel)
 {
     float total = 0;
     foreach (ProtoPartSnapshot part in vessel.protoPartSnapshots)
     {
         float dry, wet;
         total += ShipConstruction.GetPartCosts(part, part.partInfo, out dry, out wet);
     }
     return total;
 }
 public void RecordVesselRecovered(ProtoVessel vessel)
 {
     List<ProtoCrewMember> crew = vessel.GetVesselCrew();
     foreach (ProtoCrewMember member in crew)
     {
        if (!member.IsTourist())
        {
           Log.Info("kerbal " + member.name + " ended a mission ");
           hallOfFame.RecordMissionFinished(member);
        }
     }
 }
示例#10
0
 public void AllocVessel(NetworkViewID id, byte[] binaryCfg)
 {
     if (FlightGlobals.Vessels.Any(v => v.networkView != null && v.networkView.viewID == id))
         return;
     var cfg = (ConfigNode)IOUtils.DeserializeFromBinary(binaryCfg);
     var protovessel = new ProtoVessel(cfg, HighLogic.CurrentGame.flightState);
     protovessel.orbitSnapShot.meanAnomalyAtEpoch += 1;
     protovessel.Load(HighLogic.CurrentGame.flightState);
     var vessel = protovessel.vesselRef;
     vessel.gameObject.AddNetworkView(id);
     vessel.gameObject.AddComponent<VesselNetworker>();
 }
示例#11
0
 private void OnVesselRecovered(ProtoVessel vessel, bool quick)
 {
     foreach (ProtoCrewMember pcm in VesselUtil.GetVesselCrew(vessel.vesselRef))
     {
         // Award the media star XP for each planet landed on
         foreach (string target in pcm.flightLog.Entries.
             Where(fle => fle.type == FlightLog.EntryType.Land.ToString()).
             Select(fle => fle.target).ToList())
         {
             pcm.flightLog.AddEntry(MEDIA_STAR_XP, target);
         }
     }
 }
示例#12
0
        private void OnVesselRecovered(ProtoVessel v)
        {
            LoggingUtil.LogVerbose(this, "OnVesselRecovered: " + v);

            // EVA vessel
            if (v.vesselType == VesselType.EVA)
            {
                foreach (ProtoPartSnapshot p in v.protoPartSnapshots)
                {
                    foreach (string name in p.protoCrewNames)
                    {
                        // Find this crew member in our data
                        foreach (KerbalData kd in kerbals)
                        {
                            if (kd.name == name && kd.addToRoster)
                            {
                                // Add them to the roster
                                kd.crewMember.type = ProtoCrewMember.KerbalType.Crew;
                            }
                        }
                    }
                }
            }

            // Vessel with crew
            foreach (ProtoCrewMember crewMember in v.GetVesselCrew())
            {
                foreach (KerbalData kd in kerbals)
                {
                    if (kd.crewMember == crewMember && kd.addToRoster)
                    {
                        // Add them to the roster
                        crewMember.type = ProtoCrewMember.KerbalType.Crew;
                    }
                }
            }
        }
示例#13
0
        /* simple ISP dependant effi calculation.
         * NEEDS ballancing
         * removing fuel based on dV would make more sense,
         * and more thinkering to firgure it out
         * 1.60 milestone maybe?
         */
        public static float FetchEfficiency(Vessel vessel)
        {
            float Efficiency = 0;

            if (vessel == FlightGlobals.ActiveVessel)
            {
                List <ModuleOrbitalDecay> modlist = vessel.FindPartModulesImplementing <ModuleOrbitalDecay>();
                if (modlist.Count > 0)
                {
                    Efficiency = modlist[0].stationKeepData.ISP;
                }
            }
            else
            {
                ProtoVessel proto = vessel.protoVessel;

                foreach (ProtoPartSnapshot protopart in proto.protoPartSnapshots)
                {
                    foreach (ProtoPartModuleSnapshot protopartmodulesnapshot in protopart.modules)
                    {
                        if (protopartmodulesnapshot.moduleName == "ModuleOrbitalDecay")
                        {
                            ConfigNode node = protopartmodulesnapshot.moduleValues.GetNode("stationKeepData");
                            Efficiency = float.Parse(node.GetValue("ISP"));
                            break;
                        }
                    }
                }
            }
            if (Settings.ReadRD())
            {
                Efficiency *= 0.5f; // Balance here!
            }


            return(1 / Efficiency);
        }
示例#14
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);
            var discoveryNode = ProtoVessel.CreateDiscoveryNode(DiscoveryLevels.Unowned, UntrackedObjectClass.A,
                                                                double.PositiveInfinity,
                                                                double.PositiveInfinity);

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

            //It's not supposed to be infinite, but you're crazy if you think I'm going to decipher the values field of the rescue node.
            HighLogic.CurrentGame.flightState.protoVessels.Add(protoVessel);
        }
        private void OnVesselRecovered(ProtoVessel recoveredVessel, bool quick)
        {
            if (HighLogic.CurrentGame.Parameters.CustomParams <XenoIndustryCoreGameParameters>().enabled)
            {
                Dictionary <string, int> recoveredResources = new Dictionary <string, int>();

                CalculateLaunchCosts(ref recoveredResources, recoveredVessel);

                if (recoveredResources.Count > 0)
                {
                    string message = "Following resources have been recovered: \n";

                    string bodyName = "Kerbin"; // Recovery is only possible on Kerbin for now

                    foreach (KeyValuePair <string, int> kvPair in recoveredResources)
                    {
                        message += String.Format("\n {0} {1}", kvPair.Value, kvPair.Key);

                        StartCoroutine(XenoIndustrySignpost.AddItemsToClusterio(bodyName, kvPair.Key, kvPair.Value));
                    }

                    message += "\n";

                    if (!quick)
                    {
                        MultiOptionDialog dialog = new MultiOptionDialog("ClusterioResourceRecovery", message, "Recovery successful", UISkinManager.GetSkin("KSP window 7"),
                                                                         new DialogGUIBase[]
                        {
                            new DialogGUIButton("Continue", null)
                        });

                        PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), dialog, false, null);
                    }
                }
            }
        }
示例#16
0
        /// <summary>
        /// Do some basic validations over the protovessel
        /// </summary>
        private static bool ProtoVesselValidationsPassed(ProtoVessel vesselProto)
        {
            if (vesselProto == null)
            {
                Debug.LogError("[LMP]: protoVessel is null!");
                return(false);
            }

            if (vesselProto.situation == Vessel.Situations.FLYING)
            {
                if (vesselProto.orbitSnapShot == null)
                {
                    Debug.Log("[LMP]: Skipping flying vessel load - Protovessel does not have an orbit snapshot");
                    return(false);
                }
                var updateBody = FlightGlobals.Bodies[vesselProto.orbitSnapShot.ReferenceBodyIndex];
                if (updateBody == null)
                {
                    Debug.Log("[LMP]: Skipping flying vessel load - Could not find celestial body index {currentProto.orbitSnapShot.ReferenceBodyIndex}");
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// This method prepares the protovessel class and send the message, it's intended to be run in another thread
        /// </summary>
        private void PrepareAndSendProtoVessel(ProtoVessel protoVessel)
        {
            //Never send empty vessel id's (it happens with flags...)
            if (protoVessel.vesselID == Guid.Empty)
            {
                return;
            }

            //VesselSerializedBytes is shared so lock it!
            lock (VesselArraySyncLock)
            {
                VesselSerializer.SerializeVesselToArray(protoVessel, VesselSerializedBytes, out var numBytes);
                if (numBytes > 0)
                {
                    var msgData = NetworkMain.CliMsgFactory.CreateNewMessageData <VesselProtoMsgData>();
                    msgData.GameTime = TimeSyncSystem.UniversalTime;
                    msgData.VesselId = protoVessel.vesselID;
                    msgData.NumBytes = numBytes;
                    if (msgData.Data.Length < numBytes)
                    {
                        Array.Resize(ref msgData.Data, numBytes);
                    }
                    Array.Copy(VesselSerializedBytes, 0, msgData.Data, 0, numBytes);

                    SendMessage(msgData);
                }
                else
                {
                    if (protoVessel.vesselType == VesselType.Debris)
                    {
                        LunaLog.Log($"Serialization of debris vessel: {protoVessel.vesselID} name: {protoVessel.vesselName} failed. Adding to kill list");
                        VesselRemoveSystem.Singleton.KillVessel(protoVessel.vesselID, true, "Serialization of debris failed");
                    }
                }
            }
        }
        /// <summary>
        /// This event is called when the vessel is recovered
        /// </summary>
        public void OnVesselRecovered(ProtoVessel recoveredVessel, bool quick)
        {
            //quick == true when you press "space center" from the inflight menu

            if (!LockSystem.LockQuery.CanRecoverOrTerminateTheVessel(recoveredVessel.vesselID, SettingsSystem.CurrentSettings.PlayerName))
            {
                LunaScreenMsg.PostScreenMessage(LocalizationContainer.ScreenText.CannotRecover, 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            _recoveringTerminatingVesselId = recoveredVessel.vesselID;
            LunaLog.Log($"[LMP]: Removing vessel {recoveredVessel.vesselID}, Name: {recoveredVessel.vesselName} from the server: Recovered");

            System.MessageSender.SendVesselRemove(recoveredVessel.vesselID);

            //Vessel is recovered so remove the locks. Do not remove the kerbal locks as that's done in the Kerbal system
            LockSystem.Singleton.ReleaseAllVesselLocks(null, recoveredVessel.vesselID, 1);

            //We consider this vessel removed but we let KSP do the remove of the vessel
            System.RemovedVessels.TryAdd(recoveredVessel.vesselID, DateTime.Now);
            RemoveEvent.onLmpRecoveredVessel.Fire(recoveredVessel);

            VesselCommon.RemoveVesselFromSystems(recoveredVessel.vesselID);
        }
 public override bool protovesselHasDoneExperiement(ProtoVessel pv, AvailablePart experiment, CelestialBody targetBody, double contractAccepted)
 {
     NE_Helper.log("KEES-Experiement stategy");
     foreach (ProtoPartSnapshot part in pv.protoPartSnapshots)
     {
         NE_Helper.log("KEES-Experiement stategy, Part: " + part.partName);
         if (part.partName == experiment.name)
         {
             if (experimentFound(part, experiment, targetBody, contractAccepted))
                 return true;
         }
         else if (part.partName == KEES_PC)
         {
             if (payloadCarrierFound(part, experiment, targetBody, contractAccepted))
                 return true;
         }
         else if (isKasContainerPart(part))
         {
             if (payloadCarrierFound(part, experiment, targetBody, contractAccepted))
                 return true;
         }
     }
     return false;
 }
示例#20
0
        private void OnScienceReceived(float amount, ScienceSubject subject, ProtoVessel vessel, bool reverseEngineered)
        {
            // Check that the science is for home
            CelestialBody body = Science.GetCelestialBody(subject);
            if (body == null || !body.isHomeWorld)
            {
                return;
            }

            Biome biome = Science.GetBiome(subject);
            bool isKSC = biome != null && biome.IsKSC();
            if (KSCScienceMultiplier > 0.0f && isKSC)
            {
                float delta = KSCScienceMultiplier * amount - amount;
                ResearchAndDevelopment.Instance.AddScience(delta, TransactionReasons.Strategies);
                CurrencyPopup.Instance.AddPopup(Currency.Science, delta, TransactionReasons.Strategies, Parent.Config.Title, true);
            }
            else if (nonKSCScienceMultiplier > 0.0f && !isKSC)
            {
                float delta = nonKSCScienceMultiplier * amount - amount;
                ResearchAndDevelopment.Instance.AddScience(delta, TransactionReasons.Strategies);
                CurrencyPopup.Instance.AddPopup(Currency.Science, delta, TransactionReasons.Strategies, Parent.Config.Title, true);
            }
        }
        public void UpdateFairingsValuesInProtoVessel(ProtoVessel protoVessel, uint partFlightId)
        {
            if (protoVessel == null)
            {
                return;
            }

            var protoPart = VesselCommon.FindProtoPartInProtovessel(protoVessel, partFlightId);

            if (protoPart == null)
            {
                return;
            }

            var protoModule = VesselCommon.FindProtoPartModuleInProtoPart(protoPart, "ModuleProceduralFairing");

            if (protoModule == null)
            {
                return;
            }

            protoModule.moduleValues.SetValue("fsm", "st_flight_deployed");
            protoModule.moduleValues.RemoveNodesStartWith("XSECTION");
        }
示例#22
0
        public void vesselRecoverEvent(ProtoVessel v, bool unknownAsOfNow)
        {
            if (!KCT_PresetManager.Instance.ActivePreset.generalSettings.Enabled)
            {
                return;
            }
            if (!KCT_GameStates.flightSimulated && !v.vesselRef.isEVA)
            {
                // if (KCT_GameStates.settings.Debug && HighLogic.LoadedScene != GameScenes.TRACKSTATION && (v.wasControllable || v.protoPartSnapshots.Find(p => p.modules.Find(m => m.moduleName.ToLower() == "modulecommand") != null) != null))
                if (KCT_GameStates.recoveredVessel != null && v.vesselName == KCT_GameStates.recoveredVessel.shipName)
                {
                    //KCT_GameStates.recoveredVessel = new KCT_BuildListVessel(v);
                    KCT_Utilities.SpendFunds(KCT_GameStates.recoveredVessel.cost, TransactionReasons.VesselRollout);
                    if (KCT_GameStates.recoveredVessel.type == KCT_BuildListVessel.ListType.VAB)
                    {
                        KCT_GameStates.ActiveKSC.VABWarehouse.Add(KCT_GameStates.recoveredVessel);
                    }
                    else
                    {
                        KCT_GameStates.ActiveKSC.SPHWarehouse.Add(KCT_GameStates.recoveredVessel);
                    }
                    KCT_GameStates.ActiveKSC.Recon_Rollout.Add(new KCT_Recon_Rollout(KCT_GameStates.recoveredVessel, KCT_Recon_Rollout.RolloutReconType.Recovery, KCT_GameStates.recoveredVessel.id.ToString()));
                    KCT_GameStates.recoveredVessel = null;
                }
                else
                {
                    KCTDebug.Log("Adding recovered parts to Part Inventory");
                    foreach (ProtoPartSnapshot p in v.protoPartSnapshots)
                    {
                        //string name = p.partInfo.name + KCT_Utilities.GetTweakScaleSize(p);

                        KCT_Utilities.AddPartToInventory(p);
                    }
                }
            }
        }
示例#23
0
/*************************************************************************************************************************/
        private List <ScienceData> recover_science(ProtoVessel proto_vessel)
        {
            List <ScienceData> science_data = new List <ScienceData>();

            Log.PushStackInfo("FMRS_Core.recover_science", "enter recover_science(GUI Vessel_id, Game save) {0}", proto_vessel.vesselID);
            Log.dbg("Try recover science from: {0}", proto_vessel.vesselName);

            foreach (ProtoPartSnapshot part in proto_vessel.protoPartSnapshots)
            {
                foreach (ProtoPartModuleSnapshot module in part.modules)
                {
                    foreach (ConfigNode science_node in module.moduleValues.GetNodes("ScienceData"))
                    {
                        science_data.Add(new ScienceData(science_node));

                        Log.dbg("ScienceData: {0 found", science_node.GetValue("subjectID"));
                    }
                }
            }

            Log.PopStackInfo("leave recover_science(GUI Vessel_id, Game save)");

            return(science_data);
        }
示例#24
0
/*************************************************************************************************************************/
        private float vessels_cost(ProtoVessel temp_vessel)
        {
            float partcost, float_dummy, vesselcost = 0;
            PartResourceDefinition resc_def;

            Log.PushStackInfo("FMRS_Core.vessels_cost", "enter float vessels_cost(ProtoVessel temp_vessel) {0}", temp_vessel.vesselID);
            Log.dbg("Calculate cost from: {0}", temp_vessel.vesselName);

            foreach (ProtoPartSnapshot part in temp_vessel.protoPartSnapshots)
            {
                ShipConstruction.GetPartCosts(part, part.partInfo, out partcost, out float_dummy);
                foreach (ProtoPartResourceSnapshot resc in part.resources)
                {
                    resc_def  = PartResourceLibrary.Instance.resourceDefinitions[resc.resourceName];
                    partcost += (float)resc.amount * resc_def.unitCost;
                }
                vesselcost += partcost;
            }

            Log.dbg("FMRS cost: {0}", vesselcost);
            Log.PopStackInfo("leave float vessels_cost(ProtoVessel temp_vessel)");

            return(vesselcost);
        }
示例#25
0
        public static byte[] SerializeVessel(ProtoVessel protoVessel)
        {
            var vesselNode = new ConfigNode();

            try
            {
                protoVessel.Save(vesselNode);
            }
            catch (Exception)
            {
                LunaLog.LogError("[LMP]: Error while saving vessel");
                return(new byte[0]);
            }

            var vesselId = new Guid(vesselNode.GetValue("pid"));

            //Defend against NaN orbits
            if (VesselHasNaNPosition(vesselNode))
            {
                LunaLog.Log($"[LMP]: Vessel {vesselId} has NaN position");
                return(new byte[0]);
            }

            //Clean up the vessel so we send only the important data
            CleanUpVesselNode(vesselNode, vesselId);

            //TODO: Remove tourists from the vessel. This must be done in the CleanUpVesselNode method
            //foreach (var pps in protoVessel.protoPartSnapshots)
            //{
            //    foreach (var pcm in
            //        pps.protoModuleCrew.Where(pcm => pcm.type == ProtoCrewMember.KerbalType.Tourist).ToArray())
            //        pps.protoModuleCrew.Remove(pcm);
            //}

            return(ConfigNodeSerializer.Serialize(vesselNode));
        }
示例#26
0
        private void scienceRecieve(float sci, ScienceSubject sub, ProtoVessel pv, bool reverse)
        {
            if (this.Root.ContractState != Contract.State.Active)
            {
                return;
            }

            if (sub == null)
            {
                return;
            }

            if (sub.id.Contains(string.Format("{0}@Asteroid{1}{2}", scienceContainer.Exp.id, scienceLocation, "")))
            {
                if (collected)
                {
                    base.SetComplete();
                }
                else
                {
                    DMUtils.Logging("Data Not Collected From Correctly Sized Asteroid");
                }
            }
        }
示例#27
0
        private static double GetUnloadedVesselMass(string name, ProtoVessel protoVessel)
        {
            double num = 0.0;

            for (int i = 0; i < protoVessel.protoPartSnapshots.Count; i++)
            {
                ProtoPartSnapshot protoPartSnapshot = protoVessel.protoPartSnapshots[i];
                num += (double)protoPartSnapshot.mass;
                for (int j = 0; j < protoPartSnapshot.resources.Count; j++)
                {
                    ProtoPartResourceSnapshot protoPartResourceSnapshot = protoPartSnapshot.resources[j];
                    if (protoPartResourceSnapshot != null)
                    {
                        if (protoPartResourceSnapshot.definition != null)
                        {
                            num += protoPartResourceSnapshot.amount * (double)protoPartResourceSnapshot.definition.density;
                        }
                        //else
                        //    Debug.Log("Vessel: " + name + ", resource: " + protoPartResourceSnapshot.resourceName + ", no definition");
                    }
                }
            }
            return(num);
        }
示例#28
0
        // remove science data, deleting the file when it is empty
        public void Delete_file(string subject_id, double amount, ProtoVessel pv)
        {
            // get data
            File file;

            if (files.TryGetValue(subject_id, out file))
            {
                // decrease amount of data stored in the file
                file.size -= Math.Min(file.size, amount);
                file.ts    = Planetarium.GetUniversalTime();

                if (file.buff > double.Epsilon && pv != null)
                {
                    Science.Credit(subject_id, file.buff, true, pv, true);
                    file.buff = 0;
                }

                // remove file if empty
                if (file.size <= double.Epsilon)
                {
                    files.Remove(subject_id);
                }
            }
        }
        private void OnVesselWillDestroy(Vessel vessel)
        {
            bool pilotedByAnotherPlayer = lockSystem.LockExists("control-" + vessel.id) && !lockSystem.LockIsOurs("control-" + vessel.id);
            bool updatedByAnotherPlayer = lockSystem.LockExists("update-" + vessel.id) && !lockSystem.LockIsOurs("update-" + vessel.id);
            bool updatedInTheFuture     = vesselWorker.VesselUpdatedInFuture(vessel.id);

            //Vessel was packed within the last 5 seconds
            if (lastPackTime.ContainsKey(vessel.id) && (Client.realtimeSinceStartup - lastPackTime[vessel.id]) < 5f)
            {
                lastPackTime.Remove(vessel.id);
                if (vessel.situation == Vessel.Situations.FLYING && (pilotedByAnotherPlayer || updatedByAnotherPlayer || updatedInTheFuture))
                {
                    DarkLog.Debug("Hacky load: Saving player vessel getting packed in atmosphere");
                    ProtoVessel pv        = vessel.BackupVessel();
                    ConfigNode  savedNode = new ConfigNode();
                    pv.Save(savedNode);
                    vesselWorker.LoadVessel(savedNode, vessel.id, true);
                }
            }
            if (lastPackTime.ContainsKey(vessel.id))
            {
                lastPackTime.Remove(vessel.id);
            }
        }
        // recoveryFraction - percentage of funds added after recovery, based on distance from KSC
        public void onVesselRecoveryProcessing(ProtoVessel v, MissionRecoveryDialog dialog, float recoveryFraction)
        {
            KerbalGUIManager.print("[rusty] onVesselRecoveryProcessing: x = " + recoveryFraction);
            KerbalGUIManager.print("[rusty] onVesselRecoveryProcessing: AddFunds = " + -dialog.fundsEarned);

            // deduct recovered funds
            Funding.Instance.AddFunds(-dialog.fundsEarned, TransactionReasons.VesselRecovery);

            // calculate distance
            // longest possible ground distance on Kerbin [km]
            //const double HALF_CIRCLE = 2 * Mathf.PI * 600 / 2;
            // distance from KSC [m]
            double distance = SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(v.latitude, v.longitude));
            // KSC is supposedly 25 m^2 in size, so no more than 5 km can be considered free
            if (distance <= 5000.0)
            {
                distance = 0.0f;
            }
            KerbalGUIManager.print("[rusty] onVesselRecoveryProcessing: distance = " + distance + " m");

            // calculate recovery price
            // price of 1 metric tone per 1km
            const double recoveryRate = 100.0;
            double recoveryPrice = (double)vesselMass * (distance / 1000.0) * recoveryRate;

            // reset funds
            dialog.fundsEarned = 0.0;

            // show recovery GUI
            GUIRecovery wndRecovery = new GUIRecovery();
            wndRecovery.vesselMass = vesselMass;
            wndRecovery.vesselTitle = v.vesselName;
            wndRecovery.recoveryPrice = recoveryPrice;
            wndRecovery.recoveryDistance = Math.Ceiling(distance / 1000.0);
            wndRecovery.show();
        }
示例#31
0
        private void addRemoteVessel(ProtoVessel protovessel, Guid vessel_id, KMPVesselUpdate update = null, double distance = 501d)
        {
            if (isInFlight && vessel_id == FlightGlobals.ActiveVessel.id)
            {
                KMPClientMain.DebugLog("Attempted to update controlled vessel!");
                return;
            }
            KMPClientMain.DebugLog("addRemoteVessel");
            Vector3 newWorldPos = Vector3.zero, newOrbitVel = Vector3.zero;
            bool setTarget = false, wasLoaded = false;
            try
            {
                //Ensure this vessel isn't already loaded
                Vessel oldVessel = FlightGlobals.Vessels.Find (v => v.id == vessel_id);
                if (oldVessel != null) {
                    KMPClientMain.DebugLog("killing extant vessel");
                    wasLoaded = oldVessel.loaded;
                    if (protovessel.vesselType == VesselType.EVA && wasLoaded)
                    {
                        return; //Don't touch EVAs here
                    }
                    else
                    {
                        setTarget = FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.GetVessel().id == vessel_id;
                        if (oldVessel.loaded)
                        {
                            newWorldPos = oldVessel.transform.position;
                            if (oldVessel.altitude > 10000d)
                                newOrbitVel = oldVessel.GetObtVelocity();
                        }
                        oldVessel.Die();
                    }
                }

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

                CelestialBody body = null;

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

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

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

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

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

                        bool distanceBlocksUnload = false;

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

                                //Update rotation

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

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

                                    //Update FlightCtrlState
                                    if (created_vessel.ctrlState == null) created_vessel.ctrlState = new FlightCtrlState();
                                    created_vessel.ctrlState.CopyFrom(update.flightCtrlState.getAsFlightCtrlState(0.75f));
                                }
                                else
                                {
                                    serverVessels_InPresent[update.id] = false;
                                    foreach (Part part in created_vessel.Parts)
                                    {
                                        part.setOpacity(0.3f);
                                    }
                                }
                            }
                        }
                        if (!syncing && !distanceBlocksUnload) //This explicit Unload helps correct the effects of "Can't remove Part (Script) because PartBuoyancy (Script) depends on it" errors and associated NREs seen during rendezvous mode switching, but for unknown reasons it causes problems if active during universe sync
                            created_vessel.Unload();
                        if (setTarget) StartCoroutine(setDockingTarget(created_vessel));
                        KMPClientMain.DebugLog(created_vessel.id.ToString() + " initialized");
                    }
                }
            }
            catch (Exception e)
            {
                KMPClientMain.DebugLog("Error adding remote vessel: " + e.Message + " " + e.StackTrace);
            }
        }
示例#32
0
 private void OnVesselTerminated(ProtoVessel data)
 {
     KMPClientMain.DebugLog("Vessel termination: " + data.vesselID + " " + serverVessels_RemoteID.ContainsKey(data.vesselID) + " " + (HighLogic.LoadedScene == GameScenes.TRACKSTATION) + " " + (data.vesselType == VesselType.Debris || (serverVessels_IsMine.ContainsKey(data.vesselID) ? serverVessels_IsMine[data.vesselID] : true)));
     if (serverVessels_RemoteID.ContainsKey(data.vesselID) //"activeTermination" only if this is remote vessel
         && HighLogic.LoadedScene == GameScenes.TRACKSTATION //and at TrackStation
         && (data.vesselType == VesselType.Debris || (serverVessels_IsMine.ContainsKey(data.vesselID) ? serverVessels_IsMine[data.vesselID] : true))) //and is debris or owned vessel
     {
         activeTermination = true;
     }
 }
示例#33
0
        private void applyVesselUpdate(KMPVesselUpdate vessel_update, KMPVessel vessel)
        {
            serverVessels_RemoteID[vessel_update.id] = vessel_update.kmpID;

            //Find the CelestialBody that matches the one in the update
            CelestialBody update_body = null;
            if (vessel.mainBody != null && vessel.mainBody.bodyName == vessel_update.bodyName)
                update_body = vessel.mainBody; //Vessel already has the correct body
            else
            {
                //Find the celestial body in the list of bodies
                foreach (CelestialBody body in FlightGlobals.Bodies)
                {
                    if (body.bodyName == vessel_update.bodyName)
                    {
                        update_body = body;
                        break;
                    }
                }
            }

            Vector3 oldPosition = vessel.worldPosition;

            if (update_body != null)
            {
                //Convert float arrays to Vector3s
                Vector3 pos = new Vector3(vessel_update.pos[0], vessel_update.pos[1], vessel_update.pos[2]);
                Vector3 dir = new Vector3(vessel_update.dir[0], vessel_update.dir[1], vessel_update.dir[2]);
                Vector3 vel = new Vector3(vessel_update.vel[0], vessel_update.vel[1], vessel_update.vel[2]);
                vessel.info = vessel_update;
                vessel.setOrbitalData(update_body, pos, vel, dir);
            }

            KMPClientMain.DebugLog("vessel state: " + vessel_update.state.ToString() + ", tick=" + vessel_update.tick + ", realTick=" + Planetarium.GetUniversalTime());
            if (vessel_update.state == State.ACTIVE && !vessel_update.isSyncOnlyUpdate && vessel_update.relTime != RelativeTime.FUTURE && !vessel_update.isDockUpdate)
            {
                //Update the player status info
                VesselStatusInfo status = new VesselStatusInfo();
                if (vessel_update.relTime == RelativeTime.PRESENT) status.info = vessel_update;
                status.ownerName = vessel_update.player;
                status.vesselName = vessel_update.name;

                if (vessel.orbitValid)
                    status.orbit = vessel.orbitRenderer.driver.orbit;

                status.lastUpdateTime = UnityEngine.Time.realtimeSinceStartup;
                status.color = KMPVessel.generateActiveColor(status.ownerName);

                if (playerStatus.ContainsKey(status.ownerName))
                    playerStatus[status.ownerName] = status;
                else
                    playerStatus.Add(status.ownerName, status);
            }
            if (!vessel_update.id.Equals(Guid.Empty) && !docking)
            {
                //Update vessel privacy locks
                if (!isInFlight || vessel_update.id != FlightGlobals.ActiveVessel.id)
                {
                    serverVessels_InUse[vessel_update.id] = vessel_update.state == State.ACTIVE;
                    serverVessels_IsPrivate[vessel_update.id] = vessel_update.isPrivate;
                    serverVessels_IsMine[vessel_update.id] = vessel_update.isMine;
                    KMPClientMain.DebugLog("status flags updated: " + (vessel_update.state == State.ACTIVE) + " " + vessel_update.isPrivate + " " + vessel_update.isMine);
                    if (vessel_update.situation == Situation.DESTROYED)
                    {
                        KMPClientMain.DebugLog("killing vessel");
                        Vessel extant_vessel = FlightGlobals.Vessels.Find(v => v.id == vessel_update.id);
                        if (extant_vessel != null && !extant_vessel.isEVA) try { extant_vessel.Die(); } catch {}
                        return;
                    }
                }

                //Store protovessel if included
                if (vessel_update.getProtoVesselNode() != null && (!isInFlight || vessel_update.id != FlightGlobals.ActiveVessel.id)) serverVessels_ProtoVessels[vessel_update.id] = vessel_update.getProtoVesselNode();
            }
            if (isInFlightOrTracking)
            {
                if (vessel_update.id != FlightGlobals.ActiveVessel.id)
                {
                    KMPClientMain.DebugLog("retrieving vessel: " + vessel_update.id.ToString());
                    if (!vessel_update.id.Equals(Guid.Empty))
                    {
                        Vessel extant_vessel = vessel.vesselRef;
                        if (extant_vessel == null) extant_vessel = FlightGlobals.Vessels.Find(v => v.id == vessel_update.id);
                        if (isInFlight)
                        {
                            if (extant_vessel != null && vessel_update.state == State.ACTIVE && !vessel_update.isSyncOnlyUpdate)
                            {
                                 extant_vessel.name = vessel_update.name + " <" + vessel_update.player + ">";
                                 extant_vessel.vesselName = vessel_update.name + " <" + vessel_update.player + ">";
                            }
                            else if (extant_vessel != null)
                            {
                                extant_vessel.name = vessel_update.name;
                                extant_vessel.vesselName = vessel_update.name;
                            }
                        }
                        if (!serverVessels_LoadDelay.ContainsKey(vessel_update.id)
                            || (serverVessels_LoadDelay.ContainsKey(vessel_update.id) ? (serverVessels_LoadDelay[vessel_update.id] < UnityEngine.Time.realtimeSinceStartup) : false))
                        {
                            float incomingDistance = 2500f;
                            if (!syncing && vessel.worldPosition != Vector3.zero && vessel_update.relTime == RelativeTime.PRESENT)
                                incomingDistance = Vector3.Distance(vessel.worldPosition,FlightGlobals.ship_position);
                            if (vessel_update.relTime != RelativeTime.PRESENT) incomingDistance = 3000f; //Never treat vessels from another time as close by
                         	if (vessel_update.state == State.ACTIVE
                                    || vessel_update.isDockUpdate
                                    || (incomingDistance > vessel_update.distance
                                        && (serverVessels_LastUpdateDistanceTime.ContainsKey(vessel_update.id) ? (serverVessels_LastUpdateDistanceTime[vessel_update.id].Key > vessel_update.distance || serverVessels_LastUpdateDistanceTime[vessel_update.id].Value < Planetarium.GetUniversalTime()): true)))
                            {
                                serverVessels_LastUpdateDistanceTime[vessel_update.id] = new KeyValuePair<double, double>(vessel_update.distance,Planetarium.GetUniversalTime() + 0.75f);
                                if (extant_vessel != null)
                                {
                                    KMPClientMain.DebugLog("vessel found: " + extant_vessel.id);
                                    if (extant_vessel.vesselType != VesselType.Flag) //Special treatment for flags
                                    {
                                        vessel.vesselRef = extant_vessel;
                                        float ourDistance = 3000f;
                                        if (!extant_vessel.loaded)
                                        {
                                            if (KMPVessel.situationIsOrbital(vessel_update.situation))
                                                ourDistance = Vector3.Distance(extant_vessel.orbit.getPositionAtUT(Planetarium.GetUniversalTime()), FlightGlobals.ship_position);
                                            else ourDistance = Vector3.Distance(oldPosition, FlightGlobals.ship_position);
                                        }
                                        else ourDistance = Vector3.Distance(extant_vessel.GetWorldPos3D(), FlightGlobals.ship_position);
                                        bool countMismatch = false;
                                        ProtoVessel protovessel = null;
                                        if (serverVessels_ProtoVessels.ContainsKey(vessel_update.id))
                                        {
                                            protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel_update.id], HighLogic.CurrentGame);
                                        }
                                        if (serverVessels_PartCounts.ContainsKey(vessel_update.id))
                                        {
                                            //countMismatch = serverVessels_PartCounts[vessel_update.id] > 0 && extant_vessel.loaded && !extant_vessel.packed && serverVessels_PartCounts[vessel_update.id] != protovessel.protoPartSnapshots.Count;
                                            countMismatch = serverVessels_PartCounts[vessel_update.id] > 0 && serverVessels_PartCounts[vessel_update.id] != protovessel.protoPartSnapshots.Count;
                                        }
                                        if ((vessel_update.getProtoVesselNode() != null && (!KMPVessel.situationIsOrbital(vessel_update.situation) || ourDistance > 2500f || extant_vessel.altitude < 10000d)) || countMismatch)
                                        {
                                            KMPClientMain.DebugLog("updating from protovessel");
                                            serverVessels_PartCounts[vessel_update.id] = 0;
                                            if (protovessel != null)
                                            {
                                                if (vessel.orbitValid && KMPVessel.situationIsOrbital(vessel_update.situation) && protovessel.altitude > 10000f && protovessel.vesselType != VesselType.Flag && protovessel.vesselType != VesselType.EVA)
                                                {
                                                    protovessel = syncOrbit(vessel, vessel_update.tick, protovessel, vessel_update.w_pos[0]);
                                                }
                                                addRemoteVessel(protovessel, vessel_update.id, vessel_update, incomingDistance);
                                                if (vessel_update.situation == Situation.FLYING) serverVessels_LoadDelay[vessel.id] = UnityEngine.Time.realtimeSinceStartup + 5f;
                                            } else { KMPClientMain.DebugLog("Protovessel missing!"); }
                                        }
                                        else
                                        {
                                            KMPClientMain.DebugLog("no protovessel");
                                            if (vessel.orbitValid && !extant_vessel.isActiveVessel)
                                            {
                                                KMPClientMain.DebugLog("updating from flight data, distance: " + ourDistance);
                                                //Update orbit to our game's time if necessary
                                                //bool throttled = serverVessels_ObtSyncDelay.ContainsKey(vessel_update.id) && serverVessels_ObtSyncDelay[vessel_update.id] > UnityEngine.Time.realtimeSinceStartup;
                                                bool throttled = false;
                                                if (KMPVessel.situationIsOrbital(vessel_update.situation) && extant_vessel.altitude > 10000f)
                                                {
                                                    double tick = Planetarium.GetUniversalTime();
                                                    //Update orbit whenever out of sync or other vessel in past/future, or not in docking range
                                                    if (!throttled && (vessel_update.relTime == RelativeTime.PRESENT && ourDistance > (INACTIVE_VESSEL_RANGE+500f)) || (vessel_update.relTime != RelativeTime.PRESENT && Math.Abs(tick-vessel_update.tick) > 1.5d))
                                                    {
                                                        syncExtantVesselOrbit(vessel,vessel_update.tick,extant_vessel,vessel_update.w_pos[0]);
                                                        serverVessels_ObtSyncDelay[vessel_update.id] = UnityEngine.Time.realtimeSinceStartup + 1f;
                                                    }
                                                }

                                                if (FlightGlobals.ActiveVessel.mainBody == update_body && vessel_update.relTime == RelativeTime.PRESENT)
                                                {
                                                    KMPClientMain.DebugLog("full update");
                                                    if (serverVessels_InPresent.ContainsKey(vessel_update.id) ? !serverVessels_InPresent[vessel_update.id] : true)
                                                    {
                                                        serverVessels_InPresent[vessel_update.id] = true;
                                                        foreach (Part part in extant_vessel.Parts)
                                                        {
                                                            part.setOpacity(1f);
                                                        }
                                                    }

                                                    //Update rotation
                                                    if (extant_vessel.loaded)
                                                    {
                                                        extant_vessel.transform.up = vessel.worldDirection;
                                                        Quaternion rot = new Quaternion(vessel_update.rot[0],vessel_update.rot[1],vessel_update.rot[2],vessel_update.rot[3]);
                                                        extant_vessel.SetRotation(rot);
                                                        extant_vessel.angularMomentum = Vector3.zero;
                                                        extant_vessel.VesselSAS.LockHeading(rot);
                                                        extant_vessel.VesselSAS.currentRotation = rot;
                                                        extant_vessel.VesselSAS.SetDampingMode(false);
                                                    }

                                                    if (!KMPVessel.situationIsOrbital(vessel_update.situation) || extant_vessel.altitude < 10000f || ourDistance > 2500f)
                                                    {
                                                        KMPClientMain.DebugLog ("velocity update");
                                                        //Update velocity
                                                        if (extant_vessel.loaded)
                                                        {
                                                            if (update_body.GetAltitude(vessel.worldPosition)<10000d)
                                                            {
                                                                //Set velocity by surface velocity
                                                                Vector3d new_srf_vel = new Vector3d(vessel_update.s_vel[0],vessel_update.s_vel[1],vessel_update.s_vel[2]);
                                                                if (new_srf_vel.sqrMagnitude>1d) extant_vessel.ChangeWorldVelocity((-1 * extant_vessel.srf_velocity) + new_srf_vel);
                                                                else extant_vessel.ChangeWorldVelocity(-0.99f * extant_vessel.srf_velocity);
                                                            }
                                                            else
                                                            {
                                                                //Set velocity by orbit velocity
                                                                Vector3d new_obt_vel = new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2]);
                                                                if (new_obt_vel.sqrMagnitude>1d) extant_vessel.ChangeWorldVelocity((-1 * extant_vessel.obt_velocity) + new_obt_vel);
                                                                else extant_vessel.ChangeWorldVelocity(-0.99f * extant_vessel.obt_velocity);
                                                            }
                                                        }

                                                        //Update position
                                                        if (extant_vessel.altitude < 10000f || !extant_vessel.loaded)
                                                        {
                                                            if (extant_vessel.loaded && (vessel_update.situation == Situation.LANDED || vessel_update.situation == Situation.SPLASHED))
                                                            {
                                                                //Update surface position
                                                                KMPClientMain.DebugLog("surface position update");
                                                                Vector3d newPos = update_body.GetWorldSurfacePosition(vessel_update.w_pos[1],vessel_update.w_pos[2],extant_vessel.altitude+0.001d);
                                                                if ((newPos - extant_vessel.GetWorldPos3D()).sqrMagnitude > 1d)
                                                                    extant_vessel.SetPosition(newPos);
                                                                else if (Vector3.Distance(vessel.worldPosition, extant_vessel.GetWorldPos3D()) > 25f)
                                                                {
                                                                    serverVessels_PartCounts[vessel_update.id] = 0;
                                                                    addRemoteVessel(protovessel,vessel_update.id,vessel_update);
                                                                }
                                                            }
                                                            else if (!throttled && Vector3.Distance(vessel.worldPosition, extant_vessel.GetWorldPos3D()) > 1d
                                                                     && (extant_vessel.altitude < 10000f || ourDistance > 3000f)
                                                                     && update_body.GetAltitude(vessel.worldPosition) > 1d)
                                                            {
                                                                //Update 3D position
                                                                KMPClientMain.DebugLog("position update");
                                                                extant_vessel.SetPosition(vessel.worldPosition);
                                                            }
                                                            else if (!extant_vessel.loaded && ourDistance > 1000 && update_body.GetAltitude(vessel.worldPosition) > 1d)
                                                            {
                                                                //Stretch packing thresholds to prevent excessive load/unloads during rendezvous initiation
                                                                extant_vessel.distancePackThreshold += 250f;
                                                                extant_vessel.distanceUnpackThreshold += 100f;
                                                            } else
                                                            {
                                                                //Reset packing thresholds
                                                                extant_vessel.distancePackThreshold = 7500f;
                                                                extant_vessel.distanceUnpackThreshold = 1000f;
                                                            }
                                                        }

                                                        //Update FlightCtrlState
                                                        extant_vessel.ctrlState.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.75f));
                                                    }
                                                    else
                                                    {
                                                        //Orbital rendezvous
                                                        KMPClientMain.DebugLog("orbital rendezvous");

                                                        //Update FlightCtrlState
                                                        extant_vessel.ctrlState.CopyFrom(vessel_update.flightCtrlState.getAsFlightCtrlState(0.6f));
                                                    }
                                                }
                                                else if (FlightGlobals.ActiveVessel.mainBody == vessel.mainBody)
                                                {
                                                    KMPClientMain.DebugLog("update from past/future");

                                                    if (!serverVessels_InPresent.ContainsKey(vessel_update.id) || serverVessels_InPresent.ContainsKey(vessel_update.id) ? serverVessels_InPresent[vessel_update.id]: false)
                                                    {
                                                        serverVessels_InPresent[vessel_update.id] = false;
                                                        foreach (Part part in extant_vessel.Parts)
                                                        {
                                                            part.setOpacity(0.3f);
                                                        }
                                                    }

                                                    //Update rotation only
                                                    extant_vessel.transform.up = vessel.worldDirection;
                                                    extant_vessel.SetRotation(new Quaternion(vessel_update.rot[0],vessel_update.rot[1],vessel_update.rot[2],vessel_update.rot[3]));
                                                }
                                            }
                                        }
                                        KMPClientMain.DebugLog("updated");
                                    }
                                    else
                                    {
                                        //Update flag if needed
                                        if (vessel_update.getProtoVesselNode() != null)
                                        {
                                            ProtoVessel protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel_update.id], HighLogic.CurrentGame);
                                            addRemoteVessel(protovessel,vessel_update.id,vessel_update);
                                        }
                                    }
                                }
                                else
                                {
                                    try
                                    {
                                        if (serverVessels_ProtoVessels.ContainsKey(vessel_update.id))
                                        {
                                            KMPClientMain.DebugLog("Adding new vessel: " + vessel_update.id);
                                            ProtoVessel protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel_update.id], HighLogic.CurrentGame);
                                            if (vessel.orbitValid && KMPVessel.situationIsOrbital(vessel_update.situation) && protovessel.vesselType != VesselType.Flag && protovessel.vesselType != VesselType.EVA)
                                            {
                                                protovessel = syncOrbit(vessel, vessel_update.tick, protovessel, vessel_update.w_pos[0]);
                                            }
                                            serverVessels_PartCounts[vessel_update.id] = 0;
                                            addRemoteVessel(protovessel, vessel_update.id, vessel_update, incomingDistance);
                                            HighLogic.CurrentGame.CrewRoster.ValidateAssignments(HighLogic.CurrentGame);
                                        }
                                        else
                                        {
                                            KMPClientMain.DebugLog("New vessel, but no matching protovessel available");
                                        }
                                    } catch (Exception e) { KMPClientMain.DebugLog("Vessel add error: " + e.Message + "\n" + e.StackTrace); }
                                }
                            }
                            else
                            {
                                KMPClientMain.DebugLog("Vessel update ignored: we are closer to target vessel or have recently updated from someone who was closer");
                            }
                        }
                        else
                        {
                            KMPClientMain.DebugLog("Vessel update ignored: target vessel on load delay list");
                        }
                    }
                }
                else
                {
                    //This is our vessel!
                    if (vessel_update.getProtoVesselNode() != null && docking)
                    {
                        KMPClientMain.DebugLog("Received updated protovessel for active vessel");
                        serverVessels_ProtoVessels[vessel_update.id] = vessel_update.getProtoVesselNode();
                    }

                    if (vessel_update.isDockUpdate && vessel_update.relTime == RelativeTime.PRESENT)
                    {
                        //Someone docked with us and has control
                        docking = true;
                        syncing = true;
                        ScreenMessages.PostScreenMessage("Other player has control of newly docked vessel",2.5f,ScreenMessageStyle.UPPER_LEFT);
                        KMPClientMain.DebugLog("Received docking update");
                        serverVessels_PartCounts[FlightGlobals.ActiveVessel.id] = 0;

                        //Return to tracking station
                        Invoke("dockedKickToTrackingStation",0.25f);
                        return;
                    }
                    //Try to negotiate our relative position with whatever sent this update
                    if (FlightGlobals.ActiveVessel.altitude > 10000d && vessel_update.relativeTo != Guid.Empty && Math.Abs(Planetarium.GetUniversalTime() - vessel_update.tick) < 2d)
                    {
                        Vessel updateFrom = FlightGlobals.Vessels.Find (v => v.id == vessel_update.relativeTo);
                        if (updateFrom != null && !updateFrom.loaded)
                        {
                            KMPClientMain.DebugLog("Rendezvous update from unloaded vessel");
                            if (vessel_update.distance < INACTIVE_VESSEL_RANGE)
                            {
                                //We're not in normal secondary vessel range but other vessel is, send negotiating reply
                                KMPVesselUpdate update = getVesselUpdate(updateFrom);
                                update.distance = INACTIVE_VESSEL_RANGE;
                                update.state = State.INACTIVE;
                                //Rendezvous relative position data
                                update.relativeTo = FlightGlobals.ActiveVessel.id;
                                Vector3d w_pos = updateFrom.findWorldCenterOfMass() - activeVesselPosition;
                                Vector3d o_vel = updateFrom.GetObtVelocity() - FlightGlobals.ActiveVessel.GetObtVelocity();
                                for (int i = 0; i < 3; i++)
                                {
                                    update.w_pos[i] = w_pos[i];
                                    update.o_vel[i] = o_vel[i];
                                }

                                byte[] update_bytes = KSP.IO.IOUtils.SerializeToBinary(update);
                                enqueuePluginInteropMessage(KMPCommon.PluginInteropMessageID.SECONDARY_PLUGIN_UPDATE, update_bytes);

                                //updateFrom.distancePackThreshold += INACTIVE_VESSEL_RANGE/2;
                            }
                        }
                        else if (updateFrom != null && updateFrom.loaded)
                        {
                            KMPClientMain.DebugLog("rendezvous positioning: " + updateFrom.id);

                            Vector3d updateFromPos = updateFrom.findWorldCenterOfMass();
                            Vector3d relPos = activeVesselPosition-updateFromPos;
                            Vector3d updateRelPos = new Vector3d(vessel_update.w_pos[0],vessel_update.w_pos[1],vessel_update.w_pos[2]);

                            if (!dockingRelVel.ContainsKey(updateFrom.id))
                                dockingRelVel[updateFrom.id] = updateFrom.GetObtVelocity();

                            Vector3d relVel = FlightGlobals.ActiveVessel.GetObtVelocity()-dockingRelVel[updateFrom.id];
                            Vector3d updateRelVel = new Vector3d(vessel_update.o_vel[0],vessel_update.o_vel[1],vessel_update.o_vel[2]);
                            Vector3d diffPos = updateRelPos - relPos;
                            Vector3d diffVel = updateRelVel - relVel;
                            diffPos *= 0.45d;
                            diffVel *= 0.45d;
                            Vector3d newPos = updateFromPos-diffPos;

                            bool applyUpdate = true;
                            double curTick = Planetarium.GetUniversalTime();
                            if (serverVessels_RendezvousSmoothPos.ContainsKey(updateFrom.id) ? (relPos.sqrMagnitude > (serverVessels_RendezvousSmoothPos[updateFrom.id].Key * 25) && serverVessels_RendezvousSmoothPos[updateFrom.id].Value > (curTick-5d)): false)
                                applyUpdate = false;
                            if (serverVessels_RendezvousSmoothVel.ContainsKey(updateFrom.id) ? (relVel.sqrMagnitude > (serverVessels_RendezvousSmoothVel[updateFrom.id].Key * 25) && serverVessels_RendezvousSmoothVel[updateFrom.id].Value > (curTick-5d)): false)
                                applyUpdate = false;

                            double expectedDist = Vector3d.Distance(newPos, activeVesselPosition);

                            if (applyUpdate)
                            {
                                serverVessels_RendezvousSmoothPos[updateFrom.id] = new KeyValuePair<double, double>(diffPos.sqrMagnitude,curTick);
                                serverVessels_RendezvousSmoothVel[updateFrom.id] = new KeyValuePair<double, double>(diffVel.sqrMagnitude,curTick);

                                try
                                {
                                    OrbitPhysicsManager.HoldVesselUnpack(1);
                                }
                                catch (NullReferenceException)
                                {
                                }

                                if (diffPos.sqrMagnitude < 1000000d && diffPos.sqrMagnitude > 0.5d)
                                {
                                    KMPClientMain.DebugLog("Docking Krakensbane shift");
                                    foreach (Vessel otherVessel in FlightGlobals.Vessels.Where(v => v.packed == false && v.id != FlightGlobals.ActiveVessel.id && v.id == updateFrom.id))
                                        otherVessel.GoOnRails();
                                    getKrakensbane().setOffset(diffPos);
                                }
                                else if (diffPos.sqrMagnitude >= 1000000d)
                                {
                                    KMPClientMain.DebugLog("Clamped docking Krakensbane shift");
                                    diffPos.Normalize();
                                    diffPos *= 1000d;
                                    foreach (Vessel otherVessel in FlightGlobals.Vessels.Where(v => v.packed == false && v.id != FlightGlobals.ActiveVessel.id))
                                        otherVessel.GoOnRails();
                                    getKrakensbane().setOffset(diffPos);
                                }

                                activeVesselPosition += diffPos;

                                if (diffVel.sqrMagnitude > 0.0025d && diffVel.sqrMagnitude < 2500d)
                                {
                                    KMPClientMain.DebugLog("Docking velocity update");
                                    if (updateFrom.packed) updateFrom.GoOffRails();
                                    updateFrom.ChangeWorldVelocity(-diffVel);
                                }
                                else if (diffVel.sqrMagnitude >= 2500d)
                                {
                                    KMPClientMain.DebugLog("Damping large velocity differential");
                                    diffVel = diffVel.normalized;
                                    diffVel *= 50d;
                                    if (updateFrom.packed) updateFrom.GoOffRails();
                                    updateFrom.ChangeWorldVelocity(-diffVel);
                                }

                                dockingRelVel[updateFrom.id] -= diffVel;

                                KMPClientMain.DebugLog("had dist:" + relPos.magnitude + " got dist:" + updateRelPos.magnitude);
                                KMPClientMain.DebugLog("expected dist:" + expectedDist + " diffPos mag: " + diffPos.sqrMagnitude);
                                KMPClientMain.DebugLog("had relVel:" + relVel.magnitude + " got relVel:" + updateRelVel.magnitude + " diffVel mag:" + diffVel.sqrMagnitude);
                            }
                        }  else KMPClientMain.DebugLog("Ignored docking position update: unexpected large pos/vel shift");
                    } else KMPClientMain.DebugLog("Ignored docking position update: " + (FlightGlobals.ActiveVessel.altitude > 10000d) + " " + (vessel_update.relativeTo != Guid.Empty) + " " + (Math.Abs(Planetarium.GetUniversalTime() - vessel_update.tick) < 1d));
                }
            }
        }
示例#34
0
 //Called from main
 public void LoadVesselsIntoGame()
 {
     DarkLog.Debug("Loading vessels into game");
     foreach (KeyValuePair<string, Queue<VesselProtoUpdate>> vesselQueue in vesselProtoQueue)
     {
         while (vesselQueue.Value.Count > 0)
         {
             ConfigNode currentNode = vesselQueue.Value.Dequeue().vesselNode;
             if (currentNode != null)
             {
                 DodgeVesselActionGroups(currentNode);
                 DodgeVesselCrewValues(currentNode);
                 ProtoVessel pv = new ProtoVessel(currentNode, HighLogic.CurrentGame);
                 if (pv != null)
                 {
                     RegisterServerVessel(pv.vesselID.ToString());
                     HighLogic.CurrentGame.flightState.protoVessels.Add(pv);
                 }
             }
         }
     }
     DarkLog.Debug("Vessels loaded into game");
 }
示例#35
0
        private void SendVesselUpdateIfNeeded(Vessel checkVessel)
        {
            //Check vessel parts
            if (ModWorker.fetch.modControl != ModControlMode.DISABLED)
            {
                if (!vesselPartsOk.ContainsKey(checkVessel.id.ToString()))
                {
                    CheckVesselParts(checkVessel);
                }
                if (!vesselPartsOk[checkVessel.id.ToString()])
                {
                    //Vessel with bad parts
                    return;
                }
            }

            if (checkVessel.state == Vessel.State.DEAD)
            {
                //Don't send dead vessels
                return;
            }

            if (checkVessel.vesselType == VesselType.Flag && checkVessel.id == Guid.Empty && checkVessel.vesselName != "Flag")
            {
                DarkLog.Debug("Fixing flag GUID for " + checkVessel.vesselName);
                checkVessel.id = Guid.NewGuid();
            }

            //Only send updates for craft we have update locks for. Request the lock if it's not taken.
            if (!LockSystem.fetch.LockExists("update-" + checkVessel.id.ToString()))
            {
                LockSystem.fetch.ThrottledAcquireLock("update-" + checkVessel.id.ToString());
                //Wait until we have the update lock
                return;
            }

            //Take the update lock off another player if we have the control lock and it's our vessel
            if (checkVessel.id.ToString() == FlightGlobals.fetch.activeVessel.id.ToString())
            {
                if (LockSystem.fetch.LockExists("update-" + checkVessel.id.ToString()) && !LockSystem.fetch.LockIsOurs("update-" + checkVessel.id.ToString()) && LockSystem.fetch.LockIsOurs("control-" + checkVessel.id.ToString()))
                {
                    LockSystem.fetch.ThrottledAcquireLock("update-" + checkVessel.id.ToString());
                    //Wait until we have the update lock
                    return;
                }
            }

            //Send updates for unpacked vessels that aren't being flown by other players
            bool notRecentlySentProtoUpdate = serverVesselsProtoUpdate.ContainsKey(checkVessel.id.ToString()) ? ((UnityEngine.Time.realtimeSinceStartup - serverVesselsProtoUpdate[checkVessel.id.ToString()]) > VESSEL_PROTOVESSEL_UPDATE_INTERVAL) : true;
            bool notRecentlySentPositionUpdate = serverVesselsPositionUpdate.ContainsKey(checkVessel.id.ToString()) ? ((UnityEngine.Time.realtimeSinceStartup - serverVesselsPositionUpdate[checkVessel.id.ToString()]) > (1f / (float)DynamicTickWorker.fetch.sendTickRate)) : true;

            //Check that is hasn't been recently sent
            if (notRecentlySentProtoUpdate)
            {

                ProtoVessel checkProto = new ProtoVessel(checkVessel);
                //TODO: Fix sending of flying vessels.
                if (checkProto != null)
                {
                    if (checkProto.vesselID != Guid.Empty)
                    {
                        //Also check for kerbal state changes
                        foreach (ProtoPartSnapshot part in checkProto.protoPartSnapshots)
                        {
                            foreach (ProtoCrewMember pcm in part.protoModuleCrew)
                            {
                                if (!serverKerbals.ContainsKey(pcm.name))
                                {
                                    //New kerbal
                                    DarkLog.Debug("Found new kerbal, sending...");
                                    serverKerbals[pcm.name] = new ProtoCrewMember(pcm);
                                    NetworkWorker.fetch.SendKerbalProtoMessage(pcm);
                                }
                                else
                                {
                                    bool kerbalDifferent = false;
                                    kerbalDifferent = (pcm.name != serverKerbals[pcm.name].name) || kerbalDifferent;
                                    kerbalDifferent = (pcm.courage != serverKerbals[pcm.name].courage) || kerbalDifferent;
                                    kerbalDifferent = (pcm.isBadass != serverKerbals[pcm.name].isBadass) || kerbalDifferent;
                                    kerbalDifferent = (pcm.seatIdx != serverKerbals[pcm.name].seatIdx) || kerbalDifferent;
                                    kerbalDifferent = (pcm.stupidity != serverKerbals[pcm.name].stupidity) || kerbalDifferent;
                                    kerbalDifferent = (pcm.UTaR != serverKerbals[pcm.name].UTaR) || kerbalDifferent;
                                    if (kerbalDifferent)
                                    {
                                        DarkLog.Debug("Found changed kerbal, sending...");
                                        NetworkWorker.fetch.SendKerbalProtoMessage(pcm);
                                        serverKerbals[pcm.name].name = pcm.name;
                                        serverKerbals[pcm.name].courage = pcm.courage;
                                        serverKerbals[pcm.name].isBadass = pcm.isBadass;
                                        serverKerbals[pcm.name].rosterStatus = pcm.rosterStatus;
                                        serverKerbals[pcm.name].seatIdx = pcm.seatIdx;
                                        serverKerbals[pcm.name].stupidity = pcm.stupidity;
                                        serverKerbals[pcm.name].UTaR = pcm.UTaR;
                                    }
                                }
                            }
                        }
                        RegisterServerVessel(checkProto.vesselID.ToString());
                        //Mark the update as sent
                        serverVesselsProtoUpdate[checkVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                        //Also delay the position send
                        serverVesselsPositionUpdate[checkVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                        latestUpdateSent[checkVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                        bool isFlyingUpdate = (checkProto.situation == Vessel.Situations.FLYING);
                        NetworkWorker.fetch.SendVesselProtoMessage(checkProto, false, isFlyingUpdate);
                    }
                    else
                    {
                        DarkLog.Debug(checkVessel.vesselName + " does not have a guid!");
                    }
                }
            }
            else if (notRecentlySentPositionUpdate && checkVessel.vesselType != VesselType.Flag)
            {
                //Send a position update - Except for flags. They aren't exactly known for their mobility.
                serverVesselsPositionUpdate[checkVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                latestUpdateSent[checkVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup;
                VesselUpdate update = GetVesselUpdate(checkVessel);
                if (update != null)
                {
                    NetworkWorker.fetch.SendVesselUpdate(update);
                }
            }
        }
示例#36
0
 private void HandleDocking()
 {
     if (sentDockingDestroyUpdate)
     {
         //One of them will be null, the other one will be the docked craft.
         string dockedID = fromDockedVesselID != null ? fromDockedVesselID : toDockedVesselID;
         //Find the docked craft
         Vessel dockedVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id.ToString() == dockedID);
         if (dockedVessel != null ? !dockedVessel.packed : false)
         {
             ProtoVessel sendProto = new ProtoVessel(dockedVessel);
             if (sendProto != null)
             {
                 DarkLog.Debug("Sending docked protovessel " + dockedID);
                 //Mark the vessel as sent
                 serverVesselsProtoUpdate[dockedID] = UnityEngine.Time.realtimeSinceStartup;
                 serverVesselsPositionUpdate[dockedID] = UnityEngine.Time.realtimeSinceStartup;
                 RegisterServerVessel(dockedID);
                 vesselPartCount[dockedID] = dockedVessel.parts.Count;
                 vesselNames[dockedID] = dockedVessel.vesselName;
                 vesselTypes[dockedID] = dockedVessel.vesselType;
                 vesselSituations[dockedID] = dockedVessel.situation;
                 //Update status if it's us.
                 if (dockedVessel == FlightGlobals.fetch.activeVessel)
                 {
                     //Release old control locks
                     if (lastVesselID != FlightGlobals.fetch.activeVessel.id.ToString())
                     {
                         LockSystem.fetch.ReleasePlayerLocksWithPrefix(Settings.fetch.playerName, "control-");
                         lastVesselID = FlightGlobals.fetch.activeVessel.id.ToString();
                     }
                     //Force the control lock off any other player
                     LockSystem.fetch.AcquireLock("control-" + dockedID, true);
                     PlayerStatusWorker.fetch.myPlayerStatus.vesselText = FlightGlobals.fetch.activeVessel.vesselName;
                 }
                 fromDockedVesselID = null;
                 toDockedVesselID = null;
                 sentDockingDestroyUpdate = false;
                 bool isFlyingUpdate = (sendProto.situation == Vessel.Situations.FLYING);
                 NetworkWorker.fetch.SendVesselProtoMessage(sendProto, true, isFlyingUpdate);
                 if (dockingMessage != null)
                 {
                     dockingMessage.duration = 0f;
                 }
                 dockingMessage = ScreenMessages.PostScreenMessage("Docked!", 3f, ScreenMessageStyle.UPPER_CENTER);
                 DarkLog.Debug("Docking event over!");
             }
             else
             {
                 DarkLog.Debug("Error sending protovessel!");
                 PrintDockingInProgress();
             }
         }
         else
         {
             PrintDockingInProgress();
         }
     }
     else
     {
         PrintDockingInProgress();
     }
 }
示例#37
0
 public bool ProtoVesselIsAsteroid(ProtoVessel protoVessel)
 {
     return((protoVessel.protoPartSnapshots == null || protoVessel.protoPartSnapshots.Count == 0) && protoVessel.vesselName.StartsWith("Ast.") ||
            protoVessel.protoPartSnapshots != null && protoVessel.protoPartSnapshots.Count == 1 &&
            protoVessel.protoPartSnapshots[0].partName == "PotatoRoid");
 }
示例#38
0
 void onVesselRecoveryProcessing(ProtoVessel vessel, MissionRecoveryDialog d, float f)
 {
     Debug.Log (String.Format ("[KS Exp] {0}: {1} {2} {3}",
                               "onVesselRecoveryProcessing", vessel, d, f));
 }
示例#39
0
        private void VesselRecoveryProcessing(ProtoVessel v, MissionRecoveryDialog mrDialog, float data)
        {
            Debug.Log("[VR] - Vessel recovery processing");

            List <string> retirementChanges = new List <string>();
            List <string> inactivity        = new List <string>();

            double UT = Planetarium.GetUniversalTime();

            // normally we would use v.missionTime, but that doesn't seem to update
            // when you're not actually controlling the vessel
            double elapsedTime = UT - v.launchTime;

            // When flight duration was too short, mission training should not be set as expired.
            // This can happen when an on-the-pad failure occurs and the vessel is recovered.
            // We could perhaps override this if they're not actually in flight
            // (if the user didn't recover right from the pad I think this is a fair assumption)
            if (elapsedTime < settings.minFlightDurationSecondsForTrainingExpire)
            {
                Debug.Log("[VR] - mission time too short for crew to be inactive (elapsed time was " + elapsedTime + ", settings set for " + settings.minFlightDurationSecondsForTrainingExpire + ")");
                return;
            }

            foreach (ProtoCrewMember pcm in v.GetVesselCrew())
            {
                Debug.Log("[VR] - Found ProtoCrewMember: " + pcm.displayName);

                bool hasSpace      = false;
                bool hasOrbit      = false;
                bool hasEVA        = false;
                bool hasEVAOther   = false;
                bool hasOther      = false;
                bool hasOrbitOther = false;
                bool hasLandOther  = false;
                int  curFlight     = pcm.careerLog.Last().flight;
                foreach (FlightLog.Entry e in pcm.careerLog.Entries)
                {
                    if (e.type == "TRAINING_mission")
                    {
                        SetExpiration(pcm.name, e, Planetarium.GetUniversalTime());
                    }

                    if (e.flight != curFlight)
                    {
                        continue;
                    }

                    bool isOther = false;
                    if (!string.IsNullOrEmpty(e.target) && e.target != Planetarium.fetch.Home.name)
                    {
                        isOther = hasOther = true;
                    }

                    if (!string.IsNullOrEmpty(e.type))
                    {
                        switch (e.type)
                        {
                        case "Suborbit":
                            hasSpace = true;
                            break;

                        case "Orbit":
                            if (isOther)
                            {
                                hasOrbitOther = true;
                            }
                            else
                            {
                                hasOrbit = true;
                            }
                            break;

                        case "ExitVessel":
                            if (isOther)
                            {
                                hasEVAOther = true;
                            }
                            else
                            {
                                hasEVA = true;
                            }
                            break;

                        case "Land":
                            if (isOther)
                            {
                                hasLandOther = true;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                }
                double multiplier = 1d;
                double constant   = 0.5d;
                if (hasSpace)
                {
                    multiplier += settings.recSpace.x;
                    constant   += settings.recSpace.y;
                }
                if (hasOrbit)
                {
                    multiplier += settings.recOrbit.x;
                    constant   += settings.recOrbit.y;
                }
                if (hasOther)
                {
                    multiplier += settings.recOtherBody.x;
                    constant   += settings.recOtherBody.y;
                }
                if (hasOrbit && hasEVA)    // EVA should only count while in orbit, not when walking on Earth
                {
                    multiplier += settings.recEVA.x;
                    constant   += settings.recEVA.y;
                }
                if (hasEVAOther)
                {
                    multiplier += settings.recEVAOther.x;
                    constant   += settings.recEVAOther.y;
                }
                if (hasOrbitOther)
                {
                    multiplier += settings.recOrbitOther.x;
                    constant   += settings.recOrbitOther.y;
                }
                if (hasLandOther)
                {
                    multiplier += settings.recLandOther.x;
                    constant   += settings.recLandOther.y;
                }

                double retTime;
                if (kerbalRetireTimes.TryGetValue(pcm.name, out retTime))
                {
                    double offset = constant * 86400d * settings.retireOffsetBaseMult / (1 + Math.Pow(Math.Max(curFlight + settings.retireOffsetFlightNumOffset, 0d), settings.retireOffsetFlightNumPow)
                                                                                         * UtilMath.Lerp(settings.retireOffsetStupidMin, settings.retireOffsetStupidMax, pcm.stupidity));
                    if (offset > 0d)
                    {
                        retTime += offset;
                        kerbalRetireTimes[pcm.name] = retTime;
                        retirementChanges.Add("\n" + pcm.name + ", no earlier than " + KSPUtil.PrintDate(retTime, false));
                    }
                }

                multiplier /= (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1d);

                double inactiveTime = elapsedTime * multiplier + constant * 86400d;
                pcm.SetInactive(inactiveTime, false);
                inactivity.Add("\n" + pcm.name + ", until " + KSPUtil.PrintDate(inactiveTime + UT, true, false));
            }
            if (inactivity.Count > 0)
            {
                Debug.Log("[VR] - showing on leave message");

                string msgStr = "The following crew members will be on leave:";
                foreach (string s in inactivity)
                {
                    msgStr += s;
                }

                if (retirementEnabled && retirementChanges.Count > 0)
                {
                    msgStr += "\n\nThe following retirement changes have occurred:";
                    foreach (string s in retirementChanges)
                    {
                        msgStr += s;
                    }
                }

                PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                             new Vector2(0.5f, 0.5f),
                                             "CrewUpdateNotification",
                                             "Crew Updates",
                                             msgStr,
                                             "OK",
                                             true,
                                             HighLogic.UISkin);
            }
        }
示例#40
0
 public float SubmitScienceData(float dataAmount, ScienceSubject subject, float xmitScalar = 1f, ProtoVessel source = null, bool reverseEngineered = false);
示例#41
0
        /// <summary>
        /// Loads the vessel proto into the current game
        /// </summary>
        private static bool LoadVesselIntoGame(ProtoVessel vesselProto, bool forceReload)
        {
            if (HighLogic.CurrentGame?.flightState == null)
            {
                return(false);
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return(true);
        }
示例#42
0
 /// <summary>
 /// Checks if vessel is an asteroid
 /// </summary>
 private static bool ProtoVesselIsAsteroid(ProtoVessel possibleAsteroid)
 {
     return(possibleAsteroid.vesselType == VesselType.SpaceObject &&
            possibleAsteroid.protoPartSnapshots?.Count == 1 &&
            possibleAsteroid.protoPartSnapshots[0].partName == "PotatoRoid");
 }
示例#43
0
 static bool vesselIsOK(ProtoVessel pv)
 {
     return(pv.vesselType != VesselType.Debris && pv.vesselType != VesselType.Flag && pv.vesselType != VesselType.SpaceObject && pv.vesselType != VesselType.Unknown);
 }
        private void OnVesselRecovered(ProtoVessel v)
        {
            // Don't check if we're not ready to complete
            if (!ReadyToComplete())
            {
                return;
            }

            // EVA vessel
            if (v.vesselType == VesselType.EVA)
            {
                if (v.protoPartSnapshots != null)
                {
                    foreach (ProtoPartSnapshot p in v.protoPartSnapshots)
                    {
                        foreach (ProtoCrewMember pcm in p.protoModuleCrew)
                        {
                            recovered[pcm.name] = true;
                        }
                    }
                }
            }
            else
            {
                foreach (ProtoCrewMember crew in v.GetVesselCrew())
                {
                    if (recovered.ContainsKey(crew.name))
                    {
                        recovered[crew.name] = true;
                    }
                }
            }

            TestConditions();
        }
        /// <summary>
        /// Request Resource processing on a ProtoVessel.
        /// If the ProtoVessel is not known or resources not cached for the ProtoVessel will automatically add them to the Cached data.
        /// </summary>
        /// <param name="vessel">ProtoVessel reference</param>
        /// <param name="resourceName">Name of the Resource we want to process</param>
        /// <param name="amount">The amount of the resource we want to process</param>
        /// <param name="amountReceived">returns the amount processed for the request in this variable</param>
        /// <param name="pushing">default of false (which means take resource). If true will push (put resource)</param>
        public static void RequestResource(ProtoVessel vessel, string resourceName, double amount, out double amountReceived, bool pushing = false)
        {
            amountReceived = 0d;
            if (UnloadedResources.InterestedVessels == null)
            {
                UnloadedResources.InterestedVessels = new DictionaryValueList <ProtoVessel, InterestedVessel>();
            }
            //If there are no cachedResources for the vessel create one.
            if (!UnloadedResources.InterestedVessels.Contains(vessel))
            {
                CacheResources.CreatecachedVesselResources(vessel);
            }

            //Double check, not really necessary. Now find the resource amounts if in the vessel.
            if (UnloadedResources.InterestedVessels.Contains(vessel))
            {
                List <CacheResources.CacheResource> vslresources = UnloadedResources.InterestedVessels[vessel].CachedResources;
                for (int i = 0; i < vslresources.Count; i++)
                {
                    CacheResources.CacheResource cacheResource = vslresources[i];
                    if (cacheResource.resourceName == resourceName)
                    {
                        if (!pushing)  //We are taking resource
                        {
                            if (cacheResource.amount > 0 || cacheResource.timeWarpOverflow.totalAmount > 0)
                            {
                                if (cacheResource.timeWarpOverflow.totalAmount > 0 && TimeWarp.fetch != null && TimeWarp.CurrentRateIndex > CacheResources.timeWarpStep) //If we have timewarp Overflow check that first.
                                {
                                    double amountTaken = 0;
                                    cacheResource.timeWarpOverflow.Take(amount, out amountTaken);
                                    amountReceived += amountTaken;
                                    amount         -= amountTaken;
                                    if (amount <= 0) //Did we get all we need already? If so return.
                                    {
                                        return;
                                    }
                                }
                                //TimewarpOverflow didn't have enough or didn't have what we need. so now the partResrouceSnapshot
                                Dictionary <string, ProtoPartResourceSnapshot> .Enumerator ppRSenumerator = cacheResource.protoPartResourceSnapshot.GetDictEnumerator();
                                while (ppRSenumerator.MoveNext())
                                {
                                    ProtoPartResourceSnapshot partResourceSnapshot = ppRSenumerator.Current.Value;

                                    if (partResourceSnapshot.amount > 0)
                                    {
                                        if (partResourceSnapshot.amount <= amount) //Not enough but take what it has
                                        {
                                            amountReceived             += partResourceSnapshot.amount;
                                            amount                     -= partResourceSnapshot.amount;
                                            cacheResource.amount       -= partResourceSnapshot.amount;
                                            partResourceSnapshot.amount = 0;
                                        }
                                        else //this part has more than we need.
                                        {
                                            amountReceived              += amount;
                                            cacheResource.amount        -= amount;
                                            partResourceSnapshot.amount -= amount;
                                            amount = 0;
                                        }
                                    }
                                    if (amount <= 0) //Did we get all we wanted? if so return.
                                    {
                                        ppRSenumerator.Dispose();
                                        return;
                                    }
                                }
                                ppRSenumerator.Dispose();
                            }
                        }
                        else  //We are putting a resource
                        {
                            //Get how much space there is in this part.
                            double spaceAvailable = cacheResource.maxAmount - cacheResource.amount;
                            if (spaceAvailable > 0) //If we have space put some in.
                            {
                                Dictionary <string, ProtoPartResourceSnapshot> .Enumerator ppRSenumerator = cacheResource.protoPartResourceSnapshot.GetDictEnumerator();
                                while (ppRSenumerator.MoveNext())
                                {
                                    ProtoPartResourceSnapshot partResourceSnapshot = ppRSenumerator.Current.Value;
                                    double partspaceAvailable = partResourceSnapshot.maxAmount - partResourceSnapshot.amount;
                                    if (partspaceAvailable > 0)
                                    {
                                        if (amount > partspaceAvailable) //If we can't fit it all in this part. Put what we can.
                                        {
                                            partResourceSnapshot.amount = partResourceSnapshot.maxAmount;
                                            cacheResource.amount       += partspaceAvailable;
                                            amount         -= partspaceAvailable;
                                            amountReceived += partspaceAvailable;
                                        }
                                        else //If we can fit it all in this part, put it in.
                                        {
                                            partResourceSnapshot.amount += amount;
                                            cacheResource.amount        += amount;
                                            amountReceived += amount;
                                            amount          = 0;
                                        }
                                        if (amount <= 0) //Did we get all we wanted? if so return.
                                        {
                                            return;
                                        }
                                    }
                                }
                            }
                            //If we get here we had more than can fit in the parts... But if TimeWarp is too high, we put it in the overflow.
                            if (TimeWarp.fetch != null && amount > 0)
                            {
                                if (TimeWarp.CurrentRateIndex > CacheResources.timeWarpStep) //But only if timewarp rate is high enough.
                                {
                                    cacheResource.timeWarpOverflow.Add(amount);
                                    amountReceived += amount;
                                    amount          = 0;
                                    return;
                                }
                            }
                        }
                    }
                } //End For loop all vessel resources.
            }
        }
        protected void OnScienceReceived(float science, ScienceSubject subject, ProtoVessel protoVessel, bool reverseEngineered)
        {
            if (protoVessel == null || reverseEngineered)
            {
                LoggingUtil.LogVerbose(this, "OnScienceReceived: returning, protoVessel = " + (protoVessel == null ? "null" :protoVessel.vesselName) + ", reverseEng = " + reverseEngineered);
                return;
            }
            LoggingUtil.LogVerbose(this, "OnScienceReceived: " + subject.id + ", " + protoVessel.vesselID);

            // Check the given subject is okay
            foreach (string exp in experiment)
            {
                if (CheckSubject(exp, subject))
                {
                    if (HighLogic.LoadedScene == GameScenes.FLIGHT)
                    {
                        if ((RecoveryMethod(exp) & ScienceRecoveryMethod.Transmit) != 0)
                        {
                            recoveryDone[exp] = true;
                        }
                    }
                    else
                    {
                        if ((RecoveryMethod(exp) & ScienceRecoveryMethod.Recover) != 0)
                        {
                            recoveryDone[exp] = true;
                        }
                    }
                }
            }
            UpdateDelegates();

            CheckVessel(protoVessel.vesselRef);
        }
示例#47
0
 private void CheckVesselParts(Vessel checkVessel)
 {
     List<string> allowedParts = ModWorker.fetch.GetAllowedPartsList();
     List<string> bannedParts = new List<string>();
     ProtoVessel checkProto = checkVessel.protoVessel;
     if (!checkVessel.packed)
     {
         checkProto = new ProtoVessel(checkVessel);
     }
     foreach (ProtoPartSnapshot part in checkProto.protoPartSnapshots)
     {
         if (!allowedParts.Contains(part.partName))
         {
             if (!bannedParts.Contains(part.partName))
             {
                 bannedParts.Add(part.partName);
             }
         }
     }
     if (checkVessel.id.ToString() == FlightGlobals.fetch.activeVessel.id.ToString())
     {
         bannedPartsString = "";
         foreach (string bannedPart in bannedParts)
         {
             bannedPartsString += bannedPart + "\n";
         }
     }
     DarkLog.Debug("Checked vessel " + checkVessel.id.ToString() + " for banned parts, is ok: " + (bannedParts.Count == 0));
     vesselPartsOk[checkVessel.id.ToString()] = (bannedParts.Count == 0);
 }
 private IEnumerable<string> GetVesselSubjects(ProtoVessel v)
 {
     foreach (ProtoPartSnapshot pps in v.protoPartSnapshots)
     {
         foreach (ProtoPartModuleSnapshot ppms in pps.modules)
         {
             ConfigNode mod = ppms.moduleValues;
             foreach (ConfigNode scienceData in mod.GetNodes("ScienceData"))
             {
                 string subjectID = ConfigNodeUtil.ParseValue<string>(scienceData, "subjectID");
                 if (!string.IsNullOrEmpty(subjectID))
                 {
                     yield return subjectID;
                 }
             }
         }
     }
 }
示例#49
0
 //Adapted from KMP.
 private bool isProtoVesselInSafetyBubble(ProtoVessel protovessel)
 {
     CelestialBody kerbinBody = FlightGlobals.Bodies.Find(b => b.name == "Kerbin");
     if (kerbinBody == null)
     {
         //We don't know where the safety bubble is if kerbin doesn't exist, let's just disable it.
         return false;
     }
     if (protovessel == null)
     {
         DarkLog.Debug("isProtoVesselInSafetyBubble: protovessel is null!");
         return true;
     }
     if (protovessel.orbitSnapShot == null)
     {
         DarkLog.Debug("isProtoVesselInSafetyBubble: protovessel has no orbit snapshot!");
         return true;
     }
     //If not kerbin, we aren't in the safety bubble.
     if (protovessel.orbitSnapShot.ReferenceBodyIndex != FlightGlobals.Bodies.IndexOf(kerbinBody))
     {
         return false;
     }
     Vector3d protoVesselPosition = kerbinBody.GetWorldSurfacePosition(protovessel.latitude, protovessel.longitude, protovessel.altitude);
     return isInSafetyBubble(protoVesselPosition, kerbinBody);
 }
示例#50
0
 private void OnVesselRecovered(ProtoVessel vessel, bool quick)
 {
     cachedVessel = vessel.vesselRef;
     cacheTime    = Time.fixedTime;
 }
示例#51
0
        //Also called from QuickSaveLoader
        public void LoadVessel(ConfigNode vesselNode)
        {
            if (vesselNode != null)
            {
                //Fix crew value numbers to Kerbal Names
                bool kerbalsDodged = DodgeVesselCrewValues(vesselNode);

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

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

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

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

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

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

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

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

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

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

                    bool wasActive = false;
                    bool wasTarget = false;

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

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

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

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

                                KillVessel(oldVessel);
                            }
                        }
                    }

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

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

                        if (wasActive)
                        {
                            DarkLog.Debug("ProtoVessel update for active vessel!");
                            try
                            {
                                OrbitPhysicsManager.HoldVesselUnpack(5);
                                FlightGlobals.fetch.activeVessel.GoOnRails();
                                //Put our vessel on rails so we don't collide with the new copy
                            }
                            catch
                            {
                                DarkLog.Debug("WARNING: Something very bad happened trying to replace the vessel, skipping update!");
                                return;
                            }
                            newActiveVessel = currentProto.vesselRef;
                        }
                        if (wasTarget)
                        {
                            DarkLog.Debug("Set docking target");
                            FlightGlobals.fetch.SetVesselTarget(currentProto.vesselRef);
                        }
                        DarkLog.Debug("Protovessel Loaded");
                    }
                    else
                    {
                        DarkLog.Debug("Protovessel " + currentProto.vesselID + " failed to create a vessel!");
                    }
                }
                else
                {
                    DarkLog.Debug("protoVessel is null!");
                }
            }
            else
            {
                DarkLog.Debug("vesselNode is null!");
            }
        }
示例#52
0
        private void VesselRecoveryProcessing(ProtoVessel v, MissionRecoveryDialog mrDialog, float data)
        {
            Debug.Log("[RP-0] - Vessel recovery processing");

            var retirementChanges = new List <string>();
            var inactivity        = new List <string>();

            double UT = KSPUtils.GetUT();

            // normally we would use v.missionTime, but that doesn't seem to update
            // when you're not actually controlling the vessel
            double elapsedTime = UT - v.launchTime;

            Debug.Log($"[RP-0] mission elapsedTime: {KSPUtil.PrintDateDeltaCompact(elapsedTime, true, true)}");

            // When flight duration was too short, mission training should not be set as expired.
            // This can happen when an on-the-pad failure occurs and the vessel is recovered.
            // We could perhaps override this if they're not actually in flight
            // (if the user didn't recover right from the pad I think this is a fair assumption)
            if (elapsedTime < Settings.minFlightDurationSecondsForTrainingExpire)
            {
                Debug.Log($"[RP-0] - mission time too short for crew to be inactive (elapsed time was {elapsedTime}, settings set for {Settings.minFlightDurationSecondsForTrainingExpire})");
                return;
            }

            var validStatuses = new List <string>
            {
                FlightLog.EntryType.Flight.ToString(), Situation_FlightHigh, FlightLog.EntryType.Suborbit.ToString(),
                FlightLog.EntryType.Orbit.ToString(), FlightLog.EntryType.ExitVessel.ToString(),
                FlightLog.EntryType.Land.ToString(), FlightLog.EntryType.Flyby.ToString()
            };

            foreach (ProtoCrewMember pcm in v.GetVesselCrew())
            {
                Debug.Log("[RP-0] - Found ProtoCrewMember: " + pcm.displayName);

                var    allFlightsDict = new Dictionary <string, int>();
                int    curFlight      = pcm.careerLog.Last().flight;
                double inactivityMult = 0;
                double retirementMult = 0;

                foreach (FlightLog.Entry e in pcm.careerLog.Entries)
                {
                    if (e.type == "Nationality")
                    {
                        continue;
                    }
                    if (e.type == TrainingType_Mission)
                    {
                        SetExpiration(pcm.name, e, KSPUtils.GetUT());
                    }

                    if (validStatuses.Contains(e.type))
                    {
                        int situationCount;
                        var key = $"{e.target}-{e.type}";
                        if (allFlightsDict.ContainsKey(key))
                        {
                            situationCount      = allFlightsDict[key];
                            allFlightsDict[key] = ++situationCount;
                        }
                        else
                        {
                            situationCount = 1;
                            allFlightsDict.Add(key, situationCount);
                        }

                        if (e.flight != curFlight)
                        {
                            continue;
                        }

                        if (TryGetBestSituationMatch(e.target, e.type, "Retire", out double situationMult))
                        {
                            double countMult = 1 + Math.Pow(situationCount - 1, Settings.retireOffsetFlightNumPow);
                            retirementMult += situationMult / countMult;
                        }

                        if (TryGetBestSituationMatch(e.target, e.type, "Inactive", out double inactivMult))
                        {
                            inactivityMult += inactivMult;
                        }
                    }
                }

                Debug.Log("[RP-0]  retirementMult: " + retirementMult);
                Debug.Log("[RP-0]  inactivityMult: " + inactivityMult);

                double acMult = ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) + 1;
                Debug.Log("[RP-0]  AC multiplier: " + acMult);

                if (KerbalRetireTimes.TryGetValue(pcm.name, out double retTime))
                {
                    double stupidityPenalty = UtilMath.Lerp(Settings.retireOffsetStupidMin, Settings.retireOffsetStupidMax, pcm.stupidity);
                    Debug.Log($"[RP-0]  stupidityPenalty for {pcm.stupidity}: {stupidityPenalty}");
                    double retireOffset = retirementMult * 86400 * Settings.retireOffsetBaseMult / stupidityPenalty;

                    if (retireOffset > 0)
                    {
                        KerbalRetireIncreases.TryGetValue(pcm.name, out double retIncreaseTotal);
                        retIncreaseTotal += retireOffset;
                        if (retIncreaseTotal > Settings.retireIncreaseCap)
                        {
                            // Cap the total retirement increase at a specific number of years
                            retireOffset    -= retIncreaseTotal - Settings.retireIncreaseCap;
                            retIncreaseTotal = Settings.retireIncreaseCap;
                        }
                        KerbalRetireIncreases[pcm.name] = retIncreaseTotal;

                        string sRetireOffset = KSPUtil.PrintDateDelta(retireOffset, false, false);
                        Debug.Log("[RP-0] retire date increased by: " + sRetireOffset);

                        retTime += retireOffset;
                        KerbalRetireTimes[pcm.name] = retTime;
                        retirementChanges.Add($"\n{pcm.name}, +{sRetireOffset}, no earlier than {KSPUtil.PrintDate(retTime, false)}");
                    }
                }

                inactivityMult = Math.Max(1, inactivityMult);
                double elapsedTimeDays  = elapsedTime / 86400;
                double inactiveTimeDays = Math.Pow(Math.Max(Settings.inactivityMinFlightDurationDays, elapsedTimeDays), Settings.inactivityFlightDurationExponent) *
                                          Math.Min(Settings.inactivityMaxSituationMult, inactivityMult) / acMult;
                double inactiveTime = inactiveTimeDays * 86400;
                Debug.Log("[RP-0] inactive for: " + KSPUtil.PrintDateDeltaCompact(inactiveTime, true, false));

                pcm.SetInactive(inactiveTime, false);
                inactivity.Add($"\n{pcm.name}, until {KSPUtil.PrintDate(inactiveTime + UT, true, false)}");
            }

            if (inactivity.Count > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("The following crew members will be on leave:");
                foreach (string s in inactivity)
                {
                    sb.Append(s);
                }

                if (RetirementEnabled && retirementChanges.Count > 0)
                {
                    sb.Append("\n\nThe following retirement changes have occurred:");
                    foreach (string s in retirementChanges)
                    {
                        sb.Append(s);
                    }
                }

                PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
                                             new Vector2(0.5f, 0.5f),
                                             "CrewUpdateNotification",
                                             "Crew Updates",
                                             sb.ToString(),
                                             "OK",
                                             true,
                                             HighLogic.UISkin);
            }
        }
示例#53
0
        public void OnVesselTerminated(ProtoVessel terminatedVessel)
        {
            string terminatedVesselID = terminatedVessel.vesselID.ToString();
            //Check the vessel hasn't been changed in the future
            if (LockSystem.fetch.LockExists("control-" + terminatedVesselID) && !LockSystem.fetch.LockIsOurs("control-" + terminatedVesselID))
            {
                ScreenMessages.PostScreenMessage("Cannot terminate vessel, the vessel is in use.", 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            if (VesselUpdatedInFuture(terminatedVesselID))
            {
                ScreenMessages.PostScreenMessage("Cannot terminate vessel, the vessel been changed in the future.", 5f, ScreenMessageStyle.UPPER_CENTER);
                return;
            }

            if (!serverVessels.Contains(terminatedVesselID))
            {
                DarkLog.Debug("Cannot terminate a non-server vessel!");
                return;
            }

            DarkLog.Debug("Removing vessel " + terminatedVesselID + ", name: " + terminatedVessel.vesselName + " from the server: Terminated");
            unassignKerbals(terminatedVesselID);
            serverVessels.Remove(terminatedVesselID);
            NetworkWorker.fetch.SendVesselRemove(terminatedVesselID, false);
        }
示例#54
0
        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);
                }
            }
        }
示例#55
0
 private void checkRemoteVesselIntegrity()
 {
     try
     {
         if (!isInFlight || syncing || warping || docking) return;
         foreach (Vessel vessel in FlightGlobals.Vessels.FindAll(v => v.loaded && v.id != FlightGlobals.ActiveVessel.id && serverVessels_PartCounts.ContainsKey(v.id) && serverVessels_ProtoVessels.ContainsKey(v.id)))
         {
             if (serverVessels_PartCounts[vessel.id] > 0 && serverVessels_PartCounts[vessel.id] > vessel.Parts.Count)
             {
                 KMPClientMain.DebugLog("checkRemoteVesselIntegrity killing vessel: " + vessel.id);
                 serverVessels_PartCounts[vessel.id] = 0;
                 foreach (Part part in serverVessels_Parts[vessel.id])
                 {
                     try { if (!part.vessel.isEVA) part.vessel.Die(); } catch {}
                 }
                 ProtoVessel protovessel = new ProtoVessel(serverVessels_ProtoVessels[vessel.id], HighLogic.CurrentGame);
                 addRemoteVessel(protovessel,vessel.id);
                 serverVessels_LoadDelay[vessel.id] = UnityEngine.Time.realtimeSinceStartup + 10f;
             }
         }
     }
     catch (Exception ex)
     {
         KMPClientMain.DebugLog("cRVI err: " + ex.Message + " " + ex.StackTrace);
     }
 }
示例#56
0
文件: KCTEvents.cs 项目: ntwest/KCT
        public void vesselRecoverEvent(ProtoVessel v, bool unknownAsOfNow)
        {
            const string logBlockName = nameof(KCTEvents) + "." + nameof(vesselRecoverEvent);

            using (EntryExitLogger.EntryExitLog(logBlockName, EntryExitLoggerOptions.All))
            {
                if (!KCT_PresetManager.Instance.ActivePreset.generalSettings.Enabled)
                {
                    return;
                }
                if (!v.vesselRef.isEVA)
                {
                    // if (KCT_GameStates.settings.Debug && HighLogic.LoadedScene != GameScenes.TRACKSTATION && (v.wasControllable || v.protoPartSnapshots.Find(p => p.modules.Find(m => m.moduleName.ToLower() == "modulecommand") != null) != null))
                    if (GameStates.recoveredVessel != null && v.vesselName == GameStates.recoveredVessel.shipName)
                    {
                        //KCT_GameStates.recoveredVessel = new KCT_BuildListVessel(v);
                        //rebuy the ship if ScrapYard isn't overriding funds
                        if (!ScrapYardWrapper.OverrideFunds)
                        {
                            KCT_Utilities.SpendFunds(GameStates.recoveredVessel.cost, TransactionReasons.VesselRollout);   //pay for the ship again
                        }

                        //pull all of the parts out of the inventory
                        //This is a bit funky since we grab the part id from our part, grab the inventory part out, then try to reapply that ontop of our part
                        if (ScrapYardWrapper.Available)
                        {
                            foreach (ConfigNode partNode in GameStates.recoveredVessel.ExtractedPartNodes)
                            {
                                string     id = ScrapYardWrapper.GetPartID(partNode);
                                ConfigNode inventoryVersion = ScrapYardWrapper.FindInventoryPart(id);
                                if (inventoryVersion != null)
                                {
                                    //apply it to our copy of the part
                                    ConfigNode ourTracker = partNode.GetNodes("MODULE").FirstOrDefault(n => string.Equals(n.GetValue("name"), "ModuleSYPartTracker", StringComparison.Ordinal));
                                    if (ourTracker != null)
                                    {
                                        ourTracker.SetValue("TimesRecovered", inventoryVersion.GetValue("_timesRecovered"));
                                        ourTracker.SetValue("Inventoried", inventoryVersion.GetValue("_inventoried"));
                                    }
                                }
                            }


                            //process the vessel in ScrapYard
                            ScrapYardWrapper.ProcessVessel(GameStates.recoveredVessel.ExtractedPartNodes);

                            //reset the BP
                            GameStates.recoveredVessel.buildPoints = KCT_Utilities.GetBuildTime(GameStates.recoveredVessel.ExtractedPartNodes);
                        }
                        if (GameStates.recoveredVessel.type == BuildListVessel.ListType.VAB)
                        {
                            GameStates.ActiveKSC.VABWarehouse.Add(GameStates.recoveredVessel);
                        }
                        else
                        {
                            GameStates.ActiveKSC.SPHWarehouse.Add(GameStates.recoveredVessel);
                        }

                        GameStates.ActiveKSC.Recon_Rollout.Add(new Recon_Rollout(GameStates.recoveredVessel, Recon_Rollout.RolloutReconType.Recovery, GameStates.recoveredVessel.id.ToString()));
                        GameStates.recoveredVessel = null;
                    }
                }
            }
        }
示例#57
0
        private ProtoVessel syncOrbit(KMPVessel kvessel, double fromTick, ProtoVessel protovessel, double LAN)
        {
            KMPClientMain.DebugLog("updating OrbitSnapshot");
            double tick = Planetarium.GetUniversalTime();

            //Update orbit
            Planetarium.SetUniversalTime(fromTick);

            Vector3 orbit_pos = kvessel.translationFromBody;
            Vector3 orbit_vel = kvessel.worldVelocity;

            //Swap the y and z values of the orbital position/velocities
            float temp = orbit_pos.y;
            orbit_pos.y = orbit_pos.z;
            orbit_pos.z = temp;

            temp = orbit_vel.y;
            orbit_vel.y = orbit_vel.z;
            orbit_vel.z = temp;

            OrbitDriver orbitDriver = new OrbitDriver();
            orbitDriver.orbit.UpdateFromStateVectors(orbit_pos, orbit_vel, kvessel.mainBody, fromTick);
            Orbit newOrbit = orbitDriver.orbit;
            newOrbit.LAN = LAN;

            Vessel victim = FlightGlobals.ActiveVessel;
            OrbitDriver oldDriver = victim.orbitDriver;
            victim.orbitDriver = orbitDriver;
            victim.patchedConicSolver.obtDriver = orbitDriver;
            victim.orbitDriver.UpdateOrbit();
            victim.patchedConicSolver.Update();

            newOrbit = victim.patchedConicSolver.orbit;
            if (newOrbit.referenceBody == null) newOrbit.referenceBody = FlightGlobals.Bodies.Find(b => b.name == "Sun");
            if (newOrbit.EndUT > 0)
            {
                double lastEndUT =  newOrbit.EndUT;
                while (newOrbit.EndUT > 0 && newOrbit.EndUT < tick && newOrbit.EndUT > lastEndUT && newOrbit.nextPatch != null)
                {
                    KMPClientMain.DebugLog("orbit EndUT < target: " + newOrbit.EndUT + " vs " + tick);
                    lastEndUT =  newOrbit.EndUT;
                    newOrbit = newOrbit.nextPatch;
                    if (newOrbit.referenceBody == null) newOrbit.referenceBody = FlightGlobals.Bodies.Find(b => b.name == "Sun");
                    KMPClientMain.DebugLog("updated to next patch");
                }
            }

            victim.patchedConicSolver.obtDriver = oldDriver;
            victim.orbitDriver = oldDriver;

            Planetarium.SetUniversalTime(tick);
            protovessel.orbitSnapShot = new OrbitSnapshot(newOrbit);
            KMPClientMain.DebugLog("OrbitSnapshot updated");
            return protovessel;
        }
        public static ProtoPartResourceSnapshot GetMatchingResourceSnapShot(string keyField, ProtoPartResourceSnapshot protoresSnap, ProtoVessel protoVessel)
        {
            ProtoPartResourceSnapshot returnSnapshot = null;
            string resourceKey = "";
            uint   craftID     = CacheResource.RetrieveKey(keyField, out resourceKey);

            for (int pvPartI = 0; pvPartI < protoVessel.protoPartSnapshots.Count; pvPartI++)
            {
                if (protoVessel.protoPartSnapshots[pvPartI].craftID == craftID)
                {
                    bool found = false;
                    for (int ppSnapI = 0; ppSnapI < protoVessel.protoPartSnapshots[pvPartI].resources.Count; ppSnapI++)
                    {
                        if (protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI].resourceName == resourceKey)
                        {
                            //Compare the loaded values to the protoVessel snapshot.
                            //If loaded is more then DO WE? update the protoVessel. Let's just report it for now.
                            if (protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI].amount != protoresSnap.amount)
                            {
                                RSTUtils.Utilities.Log("ProtoVessel resource amounts differ");
                            }
                            if (protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI].maxAmount != protoresSnap.maxAmount)
                            {
                                RSTUtils.Utilities.Log("ProtoVessel resource max amounts differ");
                            }
                            returnSnapshot = protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI];
                            break;
                        }
                    }
                    if (found)
                    {
                        break;
                    }
                }
            }

            return(returnSnapshot);
        }
示例#59
0
 public DeferredCreditValues(string subject_id, double size, ProtoVessel pv)
 {
     this.subject_id = subject_id;
     this.size       = size;
     this.pv         = pv;
 }
示例#60
0
        protected void onVesselRecovered(ProtoVessel vessel, bool notSureWhatFor)
        {
            Utilities.Log("DeepFreezeEvents onVesselRecovered " + vessel.vesselID);
            List <string> frznKerbalkeys = new List <string>(DFgameSettings.KnownFrozenKerbals.Keys);

            foreach (string key in frznKerbalkeys)
            {
                KerbalInfo kerbalinfo = DFgameSettings.KnownFrozenKerbals[key];
                if (kerbalinfo.vesselID == vessel.vesselID)
                {
                    if (kerbalinfo.type == ProtoCrewMember.KerbalType.Unowned) //Frozen crew
                    {
                        if (Instance.DFsettings.AutoRecoverFznKerbals)
                        {
                            Utilities.Log_Debug("AutoRecover is ON");
                            Utilities.Log("Calling ThawFrozen Crew to thaw FrozenCrew " + key);
                            ThawFrozenCrew(key, vessel.vesselID);
                        }
                        else
                        {
                            Utilities.Log("DeepFreeze AutoRecovery of frozen kerbals is set to off. Must be thawed manually.");
                            Utilities.Log("DeepFreezeEvents frozenkerbal remains frozen =" + key);
                            ProtoCrewMember realkerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(b => b.name == key);
                            if (realkerbal != null)
                            {
                                realkerbal.type         = ProtoCrewMember.KerbalType.Unowned;
                                realkerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead;
                                Utilities.Log_Debug("Kerbal " + realkerbal.name + " " + realkerbal.type + " " + realkerbal.rosterStatus);
                                ScreenMessages.PostScreenMessage(key + " was stored frozen at KSC", 5.0f, ScreenMessageStyle.UPPER_LEFT);
                            }
                        }
                    }
                    else // Tourist/Comatose crew
                    {
                        Utilities.Log_Debug("Comatose crew - reset to crew " + key);
                        ProtoCrewMember crew = HighLogic.CurrentGame.CrewRoster.Tourist.FirstOrDefault(c => c.name == key);
                        if (crew != null)
                        {
                            crew.type         = ProtoCrewMember.KerbalType.Crew;
                            crew.rosterStatus = ProtoCrewMember.RosterStatus.Assigned;
                            Utilities.Log_Debug("Kerbal " + crew.name + " " + crew.type + " " + crew.rosterStatus);
                            crew.ArchiveFlightLog();
                            crew.rosterStatus = ProtoCrewMember.RosterStatus.Available;
                            DFgameSettings.KnownFrozenKerbals.Remove(crew.name);
                        }
                    }
                }
            }
            var alarmsToDelete = new List <string>();

            alarmsToDelete.AddRange(Instance.DFgameSettings.knownKACAlarms.Where(e => e.Value.VesselID == vessel.vesselID).Select(e => e.Key).ToList());
            alarmsToDelete.ForEach(id => Instance.DFgameSettings.knownKACAlarms.Remove(id));
            var partsToDelete = new List <uint>();

            partsToDelete.AddRange(Instance.DFgameSettings.knownFreezerParts.Where(e => e.Value.vesselID == vessel.vesselID).Select(e => e.Key).ToList());
            partsToDelete.ForEach(id => Instance.DFgameSettings.knownFreezerParts.Remove(id));
            if (DFgameSettings.knownVessels.ContainsKey(vessel.vesselID))
            {
                DFgameSettings.knownVessels.Remove(vessel.vesselID);
            }
        }