// Update the Asteroids public void UpdateAsteroid(Asteroid asteroid, Double time) { List <Vessel> spaceObjects = FlightGlobals.Vessels.Where(v => !v.DiscoveryInfo.HaveKnowledgeAbout(DiscoveryLevels.StateVectors) && Math.Abs(v.DiscoveryInfo.GetSignalLife(Planetarium.GetUniversalTime())) < 0.01).ToList(); Int32 limit = Random.Range(asteroid.SpawnGroupMinLimit, asteroid.SpawnGroupMaxLimit); if (spaceObjects.Any()) { Vessel vessel = spaceObjects.First(); Debug.Log("[Kopernicus] " + vessel.vesselName + " has been untracked for too long and is now lost."); vessel.Die(); } else if (GameVariables.Instance.UnlockedSpaceObjectDiscovery(ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation))) { Int32 untrackedCount = FlightGlobals.Vessels.Count(v => !v.DiscoveryInfo.HaveKnowledgeAbout(DiscoveryLevels.StateVectors)) - spaceObjects.Count; Int32 max = Mathf.Max(untrackedCount, limit); if (max <= untrackedCount) { return; } if (Random.Range(0, 100) < asteroid.Probability) { UInt32 seed = (UInt32)Random.Range(0, Int32.MaxValue); Random.InitState((Int32)seed); SpawnAsteroid(asteroid, seed); } else { Debug.Log("[Kopernicus] No new objects this time. (Probability is " + asteroid.Probability.Value + "%)"); } } }
private static void RecoverVessel(Vessel v, bool preRecovery) { //Indicate that we've at least attempted recovery of this vessel RecoverAttemptLog.Add(v.id, Planetarium.GetUniversalTime()); bool OnlyBlacklistedItems = true; foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots) { if (!Settings.Instance.BlackList.Contains(pps.partInfo.title)) { OnlyBlacklistedItems = false; break; } } if (OnlyBlacklistedItems) { return; } //If we got this far, we can assume we're going to be attempting to recover the vessel, so we should fire the processing event APIManager.instance.OnRecoveryProcessingStart.Fire(v); //Create a new RecoveryItem. Calling this calculates everything regarding the success or failure of the recovery. We need it for display purposes in the main gui Log.Info("[SR] Searching in RecoveryQueue (" + instance.RecoveryQueue.Count + ") for " + v.id); RecoveryItem Stage; if (instance.RecoveryQueue.Count > 0 && instance.RecoveryQueue.Exists(ri => ri.vessel.id == v.id)) { Stage = instance.RecoveryQueue.Find(ri => ri.vessel.id == v.id); instance.RecoveryQueue.Remove(Stage); Log.Info("[SR] Found vessel in the RecoveryQueue."); } else { Stage = new RecoveryItem(v); } Stage.Process(preRecovery); //Fire the pertinent RecoveryEvent (success or failure). Aka, make the API do its work Stage.FireEvent(); //Add the Stage to the correct list of stages. Either the Recovered Stages list or the Destroyed Stages list, for display on the main gui Stage.AddToList(); //Post a message to the stock message system, if people are still using that. Stage.PostStockMessage(); //Remove all crew on the vessel Stage.RemoveCrew(); if (preRecovery) { //remove the vessel so it doesn't get destroyed v.Die(); } //Fire the event stating we are done processing APIManager.instance.OnRecoveryProcessingFinish.Fire(v); }
/// <summary> /// Kills the vessel /// </summary> private static void KillGivenVessel(Vessel killVessel) { try { killVessel?.Die(); } catch (Exception killException) { Debug.LogError("[LMP]: Error destroying vessel: " + killException); } }
private static void TryKillAsteroid(Vessel asteroid) { try { asteroid.Die(); } catch (Exception) { // ignored } }
/// <summary> /// Kills the vessel /// </summary> private static void KillGivenVessel(Vessel killVessel) { try { killVessel?.Die(); } catch (Exception killException) { LunaLog.LogError($"[LMP]: Error destroying vessel: {killException}"); } }
private void Delete() { if (_selected == null) { ErrorPopup.Error("No vessel selected"); return; } _selected.Die(); _selected = null; UpdateContents(); }
/// <summary> /// Kills the vessel /// </summary> private static void KillGivenVessel(Vessel killVessel) { try { //CAUTION!!!!! This method will call our event "VesselRemoveEvents.OnVesselWillDestroy" Check the method to see what can happen! killVessel?.Die(); } catch (Exception killException) { LunaLog.LogError($"[LMP]: Error destroying vessel: {killException}"); } }
public void OnAsteroidSpawned(Vessel asteroid) { if (LockSystem.LockQuery.AsteroidLockBelongsToPlayer(SettingsSystem.CurrentSettings.PlayerName)) { if (System.GetAsteroidCount() <= SettingsSystem.ServerSettings.MaxNumberOfAsteroids) { System.ServerAsteroids.Add(asteroid.id.ToString()); SystemsContainer.Get <VesselProtoSystem>().MessageSender.SendVesselMessage(asteroid); } else { LunaLog.Log($"[LMP]: Killing non-server asteroid {asteroid.id}"); asteroid.Die(); } } else { LunaLog.Log($"[LMP]: Killing non-server asteroid {asteroid.id}, we don't own the asteroid lock"); asteroid.Die(); } }
private void OnVesselCreate(Vessel checkVessel) { if (workerEnabled) { if (VesselIsAsteroid(checkVessel)) { lock (serverAsteroidListLock) { if (LockSystem.fetch.LockIsOurs("asteroid-spawning")) { if (!serverAsteroids.Contains(checkVessel.id.ToString())) { if (GetAsteroidCount() <= maxNumberOfUntrackedAsteroids) { DarkLog.Debug("Spawned in new server asteroid!"); serverAsteroids.Add(checkVessel.id.ToString()); VesselWorker.fetch.RegisterServerVessel(checkVessel.id); NetworkWorker.fetch.SendVesselProtoMessage(checkVessel.protoVessel, false, false); NetworkWorker.fetch.SendVesselPermissions(PermissionsManager.GenerateAsteroidPermissions(checkVessel.protoVessel)); } else { DarkLog.Debug("Killing non-server asteroid " + checkVessel.id); checkVessel.Die(); } } } else { if (!serverAsteroids.Contains(checkVessel.id.ToString())) { DarkLog.Debug("Killing non-server asteroid " + checkVessel.id + ", we don't own the asteroid-spawning lock"); checkVessel.Die(); } } } } } }
public void OnAsteroidSpawned(Vessel asteroid) { if (LockSystem.Singleton.LockIsOurs("asteroid")) { if (System.GetAsteroidCount() <= SettingsSystem.ServerSettings.MaxNumberOfAsteroids) { Debug.Log("[LMP]: Spawned in new server asteroid!"); System.ServerAsteroids.Add(asteroid.id.ToString()); VesselProtoSystem.Singleton.MessageSender.SendVesselMessage(asteroid); } else { Debug.Log("[LMP]: Killing non-server asteroid " + asteroid.id); asteroid.Die(); } } else { Debug.Log($"[LMP]: Killing non-server asteroid {asteroid.id}, we don't own the asteroid lock"); asteroid.Die(); } }
private void OnVesselCreate(Vessel vessel) { ProtoVessel pv = vessel.BackupVessel(); List <uint> vesselParts = new List <uint>(); bool killShip = false; bool vesselOk = false; foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots) { if (pps.flightID == 0) { loadGuid = vessel.id; //When you spawn a new vessel in all the part ID's are 0 until OnFlightReady. return; } vesselParts.Add(pps.flightID); if (partToVessel.ContainsKey(pps.flightID)) { killShip = true; foreach (Vessel otherVessel in partToVessel[pps.flightID]) { if (otherVessel.id == vessel.id) { vesselOk = true; } //Either of the locks are ours or neither of the locks exist if (lockSystem.LockIsOurs("control-" + otherVessel.id) || lockSystem.LockIsOurs("update-" + otherVessel.id) || (!lockSystem.LockExists("control-" + otherVessel.id) && !lockSystem.LockExists("update-" + otherVessel.id))) { vesselOk = true; } } } } if (killShip && !vesselOk) { DarkLog.Debug("PartKiller: Destroying vessel fragment"); vessel.Die(); } else { vesselToPart.Add(vessel, vesselParts); foreach (uint partID in vesselParts) { if (!partToVessel.ContainsKey(partID)) { partToVessel.Add(partID, new List <Vessel>()); } partToVessel[partID].Add(vessel); } } }
private void OnVesselCreate(Vessel vessel) { ProtoVessel pv = vessel.BackupVessel(); List<uint> vesselParts = new List<uint>(); bool killShip = false; bool vesselOk = false; foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots) { if (pps.flightID == 0) { loadGuid = vessel.id; //When you spawn a new vessel in all the part ID's are 0 until OnFlightReady. return; } vesselParts.Add(pps.flightID); if (partToVessel.ContainsKey(pps.flightID)) { killShip = true; foreach (Vessel otherVessel in partToVessel[pps.flightID]) { if (otherVessel.id == vessel.id) { vesselOk = true; } //Either of the locks are ours or neither of the locks exist if (LockSystem.fetch.LockIsOurs("control-" + otherVessel.id) || LockSystem.fetch.LockIsOurs("update-" + otherVessel.id) || (!LockSystem.fetch.LockExists("control-" + otherVessel.id) && !LockSystem.fetch.LockExists("update-" + otherVessel.id))) { vesselOk = true; } } } } if (killShip && !vesselOk) { DarkLog.Debug("PartKiller: Destroying vessel fragment"); vessel.Die(); } else { vesselToPart.Add(vessel, vesselParts); foreach (uint partID in vesselParts) { if (!partToVessel.ContainsKey(partID)) { partToVessel.Add(partID, new List<Vessel>()); } partToVessel[partID].Add(vessel); } } }
public static void GoPoof(Vessel vessel) { var startingReputation = 0f; var startingFunds = 0d; if (Reputation.Instance != null) { startingReputation = Reputation.Instance.reputation; } if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) { startingFunds = Funding.Instance.Funds; } foreach (var kerbal in vessel.GetVesselCrew().ToArray()) { //We should let them die before disappearing, this will trigger some game-events, just to make sure everything is cleaned up and every other part and mod of the game is notified about the disappearance (LifeSupport-Scenarios etc) kerbal.Die(); //Completely erase the kerbal from current game (Does not exist anymore in save) //https://kerbalspaceprogram.com/api/class_fine_print_1_1_utilities_1_1_system_utilities.html#afd1eea0118d0c37dacd3ea696b125ff2 SystemUtilities.ExpungeKerbal(kerbal); } foreach (var part in vessel.parts.ToArray()) { part.Die(); } vessel.Die(); if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) { var endingFunds = Funding.Instance.Funds; if (endingFunds + 0.0001f < startingFunds) { Funding.Instance.AddFunds(startingFunds - endingFunds, TransactionReasons.None); } } if (Reputation.Instance != null) { var endingReputation = Reputation.Instance.reputation; if (endingReputation + 0.0001f < startingReputation) { Reputation.Instance.AddReputation(startingReputation - endingReputation, TransactionReasons.None); } } }
public CostReport getBuildCost(ConfigNode craft) { lockedParts = false; ShipConstruct ship = new ShipConstruct(); if (!ship.LoadShip(craft)) { return(null); } if (!ship.shipPartsUnlocked) { lockedParts = true; } GameObject ro = ship.parts[0].localRoot.gameObject; Vessel craftVessel = ro.AddComponent <Vessel>(); craftVessel.vesselName = "EL craftVessel - " + craft.GetValue("ship"); craftVessel.Initialize(true); foreach (Part part in craftVessel.parts) { part.ModulesOnStart(); } if (ELSettings.B9Wings_Present) { if (!InitializeB9Wings(craftVessel) && ELSettings.FAR_Present) { InitializeFARSurfaces(craftVessel); } } else if (ELSettings.FAR_Present) { InitializeFARSurfaces(craftVessel); } // needed for displaying optional resources during the planning // stage. craftResources = new RMResourceSet(craftVessel); BuildCost resources = new BuildCost(); foreach (Part p in craftVessel.parts) { resources.addPart(p); } craftVessel.Die(); return(resources.cost); }
private void DepartureCompletion() { RmmUtil.ToMapView(); RmmContract.HandleContracts(_departureVessel, false, true); if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) { Funding.Instance.AddFunds(_mission.Price + cargoFee(), TransactionReasons.VesselRecovery); } handleUnloadCrew(_departureVessel, true); _departureVessel.Unload(); _departureVessel.Die(); ScreenMessages.PostScreenMessage(_mission.VesselName + " returned to " + RmmUtil.HomeBodyName(), 4, ScreenMessageStyle.UPPER_CENTER); finishDeparture(); }
public void DespawnVesselDebris() { foreach (Vessel vessel in FlightGlobals.Vessels) { foreach (Part part in vessel.parts) { foreach (ProtoCrewMember crew in part.protoModuleCrew) { crew.KerbalRef.die(); } } if (vessel.id.ToString() == vesselID) { vessel.Die(); break; } } }
public float RecycleVessel(Vessel v) { float ConversionEfficiency = 0.8f; double amount; VesselResources scrap = new VesselResources(v); string target_resource; PartResourceDefinition rp_def; if (ExLaunchPad.kethane_present) { target_resource = "Metal"; } else { target_resource = "RocketParts"; } rp_def = PartResourceLibrary.Instance.GetDefinition(target_resource); if (FlightGlobals.ActiveVessel == v) { FlightGlobals.ForceSetActiveVessel(this.vessel); } float mass = 0; foreach (var crew in v.GetVesselCrew()) { mass += RecycleKerbal(crew, null); } foreach (string resource in scrap.resources.Keys) { amount = scrap.ResourceAmount(resource); mass += ReclaimResource(resource, amount, v.name); scrap.TransferResource(resource, -amount); } float hull_mass = v.GetTotalMass(); amount = hull_mass * ConversionEfficiency / rp_def.density; mass += ReclaimResource(target_resource, amount, v.name, "hull"); v.Die(); return(mass); }
public BuildCost.CostReport getBuildCost(ConfigNode craft) { ShipConstruct ship = new ShipConstruct(); ship.LoadShip(craft); GameObject ro = ship.parts[0].localRoot.gameObject; Vessel dummy = ro.AddComponent <Vessel>(); dummy.Initialize(true); craftResources = new VesselResources(dummy); BuildCost resources = new BuildCost(); foreach (Part p in ship.parts) { resources.addPart(p); } dummy.Die(); return(resources.cost); }
/// <summary> /// Kills the vessel /// </summary> private void KillGivenVessel(Vessel killVessel) { try { if (killVessel == null) { return; } ManuallyKillingVesselId = killVessel.id; //CAUTION!!!!! This method will call our event "VesselRemoveEvents.OnVesselWillDestroy" Check the method to see what can happen! killVessel.Die(); } catch (Exception killException) { LunaLog.LogError($"[LMP]: Error destroying vessel: {killException}"); } finally { ManuallyKillingVesselId = Guid.Empty; } }
public void AsteriodModifier( Vessel asteriod ) { if( asteriod.vesselType == VesselType.SpaceObject && asteriod.loaded == false ) { try { TerraformingAsteriodImpactor impactor = asteriod.gameObject.AddComponent<TerraformingAsteriodImpactor>(); //Comets are rarer than asteriods: if( UnityEngine.Random.Range( 1, 2 ) == 1 ) //1 in 40 asteriods { impactor.Init( asteriod, 1 ); asteriod.vesselName = asteriod.vesselName.Replace( "Ast." , "Comet" ); } else { impactor.Init( asteriod, 0 ); } } catch { asteriod.Die(); } } }
public float RecycleVessel(Vessel v) { float ConversionEfficiency = 0.8f; double amount; VesselResources scrap = new VesselResources(v); PartResourceDefinition rp_def; rp_def = PartResourceLibrary.Instance.GetDefinition("RocketParts"); float mass = 0; foreach (string resource in scrap.resources.Keys) { amount = scrap.ResourceAmount(resource); mass += ReclaimResource(resource, amount, v.name); } float hull_mass = v.GetTotalMass(); amount = hull_mass * ConversionEfficiency / rp_def.density; mass += ReclaimResource("RocketParts", amount, v.name, "hull"); v.Die(); return(mass); }
public void AsteriodModifier(Vessel asteriod) { if (asteriod.vesselType == VesselType.SpaceObject && asteriod.loaded == false) { try { TerraformingAsteriodImpactor impactor = asteriod.gameObject.AddComponent <TerraformingAsteriodImpactor>(); //Comets are rarer than asteriods: if (UnityEngine.Random.Range(1, 2) == 1) //1 in 40 asteriods { impactor.Init(asteriod, 1); asteriod.vesselName = asteriod.vesselName.Replace("Ast.", "Comet"); } else { impactor.Init(asteriod, 0); } } catch { asteriod.Die(); } } }
private void killVessel(Vessel vessel) { if (vessel !=null && !killedThisUpdate.Contains(vessel.id)) { killedThisUpdate.Add(vessel.id); if (!isInFlight) { KMPClientMain.DebugLog("Killing vessel immediately: " + vessel.id); FlightGlobals.Vessels.Remove(vessel); vessel.Die(); } else StartCoroutine(killVesselOnNextUpdate(vessel)); } }
private void KillVessel(Vessel killVessel) { if (killVessel != null) { DarkLog.Debug("Killing vessel: " + killVessel.id.ToString()); if (!killVessels.Contains(killVessel)) { killVessels.Add(killVessel); } lastKillVesselDestroy[killVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup; try { /* if (!killVessel.packed) { try { OrbitPhysicsManager.HoldVesselUnpack(2); } catch { //Don't care } killVessel.GoOnRails(); } if (killVessel.loaded) { killVessel.Unload(); } */ killVessel.Die(); } catch (Exception e) { DarkLog.Debug("Error destroying vessel: " + e); } } }
/// <summary> /// Spawn ship construct /// https://github.com/KospY/KAS/blob/master/Plugin/KAS_Shared.cs /// </summary> /// <param name="_shipConstruct">Shipconstruct to spawn</param> /// <param name="_srcPart">Source part to spawn relative to</param> /// <param name="_spawnOffset">Offset spawn from Source part position</param> private void SpawnVessel(ShipConstruct _shipConstruct, Part _srcPart, Vector3 _spawnOffset) { //Store construct root Part _newConstructRootPart = _shipConstruct.parts[0]; //Center rootpart Vector3 offset = _newConstructRootPart.transform.localPosition; _newConstructRootPart.transform.Translate(-offset); //Get launch spawn point, relative to part Transform t = _srcPart.transform; GameObject launchPos = new GameObject(); launchPos.transform.parent = _srcPart.transform; launchPos.transform.position = t.position; launchPos.transform.position += t.TransformDirection(_spawnOffset); launchPos.transform.rotation = t.rotation; //Store our launch / spawn position Transform launchTransform = launchPos.transform; //Kill original object launchPos.DestroyGameObject(); //Set rootpart origin _shipConstruct.Parts[0].localRoot.transform.Translate(launchPos.transform.position, Space.World); //Position float angle; Vector3 axis; //Extract ToAngleAxis data from selected spawning location launchTransform.rotation.ToAngleAxis(out angle, out axis); //TRANSFORM Rotate localRootPart in relation to root _shipConstruct.Parts[0].localRoot.transform.RotateAround(launchTransform.position, axis, angle); //Create vessel object Vessel _newVessel = _newConstructRootPart.localRoot.gameObject.AddComponent <Vessel>(); //Attach vessel information _newVessel.id = Guid.NewGuid(); _newVessel.vesselName = _srcPart.vessel.vesselName + " - " + _shipConstruct.shipName; _newVessel.landedAt = _srcPart.vessel.vesselName; //Store backup ShipConstruction.CreateBackup(_shipConstruct); //Init from VAB _newVessel.Initialize(true); //Set Landed _newVessel.Landed = true; //_newVessel.situation = Vessel.Situations.PRELAUNCH; // _newVessel.GoOffRails(); //_newVessel.IgnoreGForces(240); //Set Orbit InitiateOrbit(launchTransform.position, _srcPart.vessel, _newVessel); //Set Mission info uint missionId = (uint)Guid.NewGuid().GetHashCode(); string flagUrl = _srcPart.flagURL; uint launchId = HighLogic.CurrentGame.launchID++; //Set part mission info for (int i = 0; i < _newVessel.parts.Count; i++) { Part part = _newVessel.parts[i]; part.flightID = ShipConstruction.GetUniqueFlightID(FlightDriver.FlightStateCache.flightState); part.flagURL = flagUrl; part.launchID = launchId; part.missionID = missionId; } //Generate staging KSP.UI.Screens.StageManager.BeginFlight(); _newConstructRootPart.vessel.ResumeStaging(); KSP.UI.Screens.StageManager.GenerateStagingSequence(_newConstructRootPart.localRoot); KSP.UI.Screens.StageManager.RecalculateVesselStaging(_newConstructRootPart.vessel); //Set position, again _newVessel.SetPosition(launchTransform.position); _newVessel.SetRotation(launchTransform.rotation); //Save Protovessel ProtoVessel _newProto = new ProtoVessel(_newVessel); //Kill and remove spawned vessel, had some serious problems with spawn position warping/glitching _newVessel.Die(); //Set the protovessels position to the relative one we found, maybe redundant _newProto.position = launchPos.transform.position; //If you check this value, you will see the height change from launch scene to resume scene, extra dafuq //float height = _newProto.height; if (FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_FILE || FlightDriver.StartupBehaviour == FlightDriver.StartupBehaviours.RESUME_SAVED_CACHE) { //Odd behaviour with positioning during different flight scenes, workaround awaaaay Log.Info("Workaround of height"); _newProto.height = TrueAlt(launchTransform.position, _srcPart.vessel); } _newProto.altitude += 10; _newProto.height += 10; _newProto.situation = Vessel.Situations.FLYING; //Load Protovessel _newProto.Load(HighLogic.CurrentGame.flightState); // _newVessel.GoOnRails(); // Restore ShipConstruction ship, otherwise player sees loaded craft in VAB ShipConstruction.ShipConfig = _OldVabShip.GetConfigNode(); //Fix Control Lock FlightInputHandler.ResumeVesselCtrlState(FlightGlobals.ActiveVessel); //Fix active vessel staging FlightGlobals.ActiveVessel.ResumeStaging(); }
void SellWindow(int windowID) { GUILayout.BeginVertical(); scrollPos = GUILayout.BeginScrollView(scrollPos, HighLogic.Skin.scrollView); foreach (Vessel vessel in FlightGlobals.Vessels) { if (vessel.vesselType != VesselType.EVA && vessel.vesselType != VesselType.Flag && vessel.vesselType != VesselType.SpaceObject && vessel != base.vessel && vessel.loaded == true) { double price = 0; foreach (Part part in vessel.Parts) { if (part.partInfo.name == "LargeTank") { price = price + 3000; } else { if (part.partInfo.name == "SmallTank") { price = price + 1000; } else { if (part.partInfo.name == "RadialOreTank") { price = price + 300; } else { price = price + part.partInfo.cost; foreach (PartResource resource in part.Resources) { price = price - resource.maxAmount * resource.info.unitCost; } } } } } price = Math.Round(price, MidpointRounding.AwayFromZero); GUILayout.BeginHorizontal(); if (GUILayout.Button(vessel.vesselName + " price: " + price + "\n" + vessel.situation + " " + vessel.mainBody.bodyName, HighLogic.Skin.button)) { if (vessel.GetCrewCount() != 0) { ScreenMessages.PostScreenMessage("there are still some crew in the vessel", 5.0f, ScreenMessageStyle.UPPER_CENTER); } else { vesselPrice = price; vesselSell = vessel; ScreenMessages.PostScreenMessage("Vessel selected", 5.0f, ScreenMessageStyle.UPPER_CENTER); } } GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Sell", HighLogic.Skin.button)) { if (vesselSell != null) { Funding.Instance.AddFunds(vesselPrice, TransactionReasons.VesselRecovery); foreach (Part part in vesselSell.parts) { foreach (PartResource resource in part.Resources) { resource.amount = 0; } } vesselSell.Die(); ScreenMessages.PostScreenMessage("vessel selled", 5.0f, ScreenMessageStyle.UPPER_CENTER); } else { ScreenMessages.PostScreenMessage("please select a vessel", 5.0f, ScreenMessageStyle.UPPER_CENTER); } } if (GUILayout.Button("close", HighLogic.Skin.button)) { sellWindow = false; MenuWindow = true; } if (GUILayout.Button("about", HighLogic.Skin.button)) { aboutWindow = true; } GUILayout.EndHorizontal(); GUILayout.EndVertical(); }
private void killVessel(Vessel vessel) { if (vessel !=null) { if (!isInFlightOrTracking && !syncing) { KMPClientMain.DebugLog("Killing vessel immediately: " + vessel.id); try { vessel.Die(); } catch {} try { FlightGlobals.Vessels.Remove(vessel); } catch {} StartCoroutine(destroyVesselOnNextUpdate(vessel)); } else StartCoroutine(killVesselOnNextUpdate(vessel)); } }
public void KillVessel(Vessel killVessel) { if (killVessel != null) { DarkLog.Debug("Killing vessel: " + killVessel.id.ToString()); //Forget the dying vessel PartKiller.fetch.ForgetVessel(killVessel); HackyInAtmoLoader.fetch.ForgetVessel(killVessel); //Try to unload the vessel first. if (killVessel.loaded) { try { killVessel.Unload(); } catch (Exception unloadException) { DarkLog.Debug("Error unloading vessel: " + unloadException); } } //Remove the kerbal from the craft foreach (ProtoPartSnapshot pps in killVessel.protoVessel.protoPartSnapshots) { foreach (ProtoCrewMember pcm in pps.protoModuleCrew.ToArray()) { pps.RemoveCrew(pcm); } } //Add it to the delay kill list to make sure it dies. //With KSP, If it doesn't work first time, keeping doing it until it does. if (!delayKillVessels.Contains(killVessel)) { delayKillVessels.Add(killVessel); } lastKillVesselDestroy[killVessel.id] = UnityEngine.Time.realtimeSinceStartup; try { killVessel.Die(); } catch (Exception killException) { DarkLog.Debug("Error destroying vessel: " + killException); } } }
private void KillVessel(Vessel killVessel) { if (killVessel != null) { bool oldDestroyIsValid = destroyIsValid; destroyIsValid = false; if (oldDestroyIsValid) { DarkLog.Debug("Disabling vessel destroy for vessel killing"); } DarkLog.Debug("Killing vessel: " + killVessel.id.ToString()); try { if (!killVessel.packed) { killVessel.GoOnRails(); } if (killVessel.loaded) { killVessel.Unload(); } killVessel.Die(); } catch (Exception e) { DarkLog.Debug("Error destroying vessel: " + e); } if (oldDestroyIsValid) { reenableDestroyInFixedUpdates = 5; } } }
public float RecycleVessel(Vessel v) { float ConversionEfficiency = 0.8f; double amount; VesselResources scrap = new VesselResources (v); PartResourceDefinition rp_def; string target_resource = ExSettings.HullRecycleTarget; rp_def = PartResourceLibrary.Instance.GetDefinition (target_resource); if (FlightGlobals.ActiveVessel == v) FlightGlobals.ForceSetActiveVessel (this.vessel); float mass = 0; foreach (var crew in v.GetVesselCrew ()) { mass += RecycleKerbal (crew, null); } foreach (string resource in scrap.resources.Keys) { amount = scrap.ResourceAmount (resource); mass += ReclaimResource (resource, amount, v.name); scrap.TransferResource (resource, -amount); } float hull_mass = v.GetTotalMass (); amount = hull_mass * ConversionEfficiency / rp_def.density; mass += ReclaimResource (target_resource, amount, v.name, String.Format ("hull({0})", target_resource)); v.Die (); return mass; }
private IEnumerator<WaitForFixedUpdate> loadProtovessel(Vessel oldVessel, Vector3 newWorldPos, Vector3 newOrbitVel, bool wasLoaded, bool wasActive, bool setTarget, ProtoVessel protovessel, Guid vessel_id, KMPVessel kvessel = null, KMPVesselUpdate update = null, double distance = 501d) { yield return new WaitForFixedUpdate(); if (oldVessel != null && !wasActive) { Log.Debug("Killing vessel"); try { oldVessel.Die(); } catch {} try { FlightGlobals.Vessels.Remove(oldVessel); } catch {} StartCoroutine(destroyVesselOnNextUpdate(oldVessel)); } serverVessels_LoadDelay[vessel_id] = UnityEngine.Time.realtimeSinceStartup + 5f; serverVessels_PartCounts[vessel_id] = protovessel.protoPartSnapshots.Count; protovessel.Load(HighLogic.CurrentGame.flightState); Vessel created_vessel = protovessel.vesselRef; if (created_vessel != null) { try { OrbitPhysicsManager.HoldVesselUnpack(1); } catch (NullReferenceException e) { Log.Debug("Exception thrown in loadProtovessel(), catch 1, Exception: {0}", e.ToString()); } if (!created_vessel.loaded) created_vessel.Load(); Log.Debug(created_vessel.id.ToString() + " initializing: ProtoParts=" + protovessel.protoPartSnapshots.Count + ",Parts=" + created_vessel.Parts.Count + ",Sit=" + created_vessel.situation.ToString() + ",type=" + created_vessel.vesselType + ",alt=" + protovessel.altitude); vessels[vessel_id.ToString()].vessel.vesselRef = created_vessel; serverVessels_PartCounts[vessel_id] = created_vessel.Parts.Count; serverVessels_Parts[vessel_id] = new List<Part>(); serverVessels_Parts[vessel_id].AddRange(created_vessel.Parts); if (created_vessel.vesselType != VesselType.Flag && created_vessel.vesselType != VesselType.EVA) { foreach (Part part in created_vessel.Parts) { part.OnLoad(); part.OnJustAboutToBeDestroyed += checkRemoteVesselIntegrity; part.explosionPotential = 0; part.terrainCollider = new PQS_PartCollider(); part.terrainCollider.part = part; part.terrainCollider.useVelocityCollider = false; part.terrainCollider.useGravityCollider = false; part.breakingForce = float.MaxValue; part.breakingTorque = float.MaxValue; } if (update == null || (update != null && update.bodyName == FlightGlobals.ActiveVessel.mainBody.name)) { Log.Debug("update included"); if (update == null || (update.relTime == RelativeTime.PRESENT)) { if (newWorldPos != Vector3.zero) { Log.Debug("repositioning"); created_vessel.transform.position = newWorldPos; } if (newOrbitVel != Vector3.zero) { Log.Debug("updating velocity"); created_vessel.ChangeWorldVelocity((-1 * created_vessel.GetObtVelocity()) + (new Vector3(newOrbitVel.x,newOrbitVel.z,newOrbitVel.y))); //xzy? } StartCoroutine(restoreVesselState(created_vessel,newWorldPos,newOrbitVel)); //Update FlightCtrlState if (update != null) { if (created_vessel.ctrlState == null) created_vessel.ctrlState = new FlightCtrlState(); created_vessel.ctrlState.CopyFrom(update.flightCtrlState.getAsFlightCtrlState(0.75f)); } } else { StartCoroutine(setNewVesselNotInPresent(created_vessel)); } } } if (setTarget) StartCoroutine(setDockingTarget(created_vessel)); if (wasActive) StartCoroutine(setActiveVessel(created_vessel, oldVessel)); Log.Debug(created_vessel.id.ToString() + " initialized"); } }
public void OnVesselCreate(Vessel createdVessel) { try { //DarkLog.Debug("Vessel creation detected: " + createdVessel.id + ", name: " + createdVessel.vesselName); ProtoVessel pv = createdVessel.BackupVessel(); bool killShip = false; bool spawnDebris = false; string partOwner = null; string createdVesselID = pv.vesselID.ToString(); foreach (ProtoPartSnapshot vesselPart in pv.protoPartSnapshots) { if (vesselPart != null) { if (vesselParts.ContainsKey(vesselPart.flightID.ToString())) { partOwner = vesselParts[vesselPart.flightID.ToString()]; if (!killShip && (createdVesselID != partOwner)) { if (LockSystem.fetch.LockIsOurs("control-" + partOwner) || LockSystem.fetch.LockIsOurs("update-" + partOwner) || !LockSystem.fetch.LockExists("update-" + partOwner)) { //Vessel is ours, update the part owner. spawnDebris = true; vesselParts[vesselPart.flightID.ToString()] = createdVesselID; } else { DarkLog.Debug("Detected debris for a vessel we do not control, removing " + createdVesselID); killShip = true; break; } } } } } if (killShip) { createdVessel.Die(); } if (spawnDebris) { //DarkLog.Debug("Spawned debris " + createdVesselID + " from " + partOwner); } } catch (Exception e) { DarkLog.Debug("Threw in OnVesselCreate: " + e); } }
protected bool CheckParameters(MonolithState paramState) { if (paramState < currentState) { return(true); } // StarJeb not active vessel if (starJeb != null && FlightGlobals.ActiveVessel != starJeb || candidate != null && FlightGlobals.ActiveVessel != candidate) { stepTime = Time.fixedTime; return(false); } // Create the velocity change handler if (velHdlr == null) { LoggingUtil.LogDebug(this, "Adding VelocityHandler"); velHdlr = MapView.MapCamera.gameObject.AddComponent <VelocityHandler>(); velHdlr.param = this; } switch (currentState) { case MonolithState.STARTED: // Look for an eva if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.vesselType == VesselType.EVA) { candidate = FlightGlobals.ActiveVessel; candidateName = candidate.vesselName; LoggingUtil.LogDebug(this, "Got an eva, starJeb = " + candidate.vesselName); nextState(); return(true); } return(false); case MonolithState.EVA: { Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One"); float discoveryDistance = discovery == null ? 10000 : Vector3.Distance(discovery.transform.position, candidate.transform.position); if (distance < 10000 && discoveryDistance > distance && Time.fixedTime - stepTime > 10.0f || distance < MONOLITH_TOO_CLOSE) { // Store Star Jeb's name starJeb = candidate; starJebName = candidateName; PersistentDataStore.Instance.Store <string>("starJebName", starJebName); // Store Star Jeb's friend's name ProtoCrewMember protoStarJeb = candidate.GetVesselCrew().First(); if (discovery != null) { string trait = protoStarJeb.experienceTrait.TypeName == "Scientist" ? "Pilot" : "Scientist"; ProtoCrewMember notStarJeb = discovery.GetVesselCrew().Where(pcm => pcm.experienceTrait.TypeName == trait).FirstOrDefault(); if (notStarJeb != null) { PersistentDataStore.Instance.Store <string>("notStarJebName", notStarJeb.name); } } candidate = null; nextState(); // Set the right image (male vs. female) for the end sequence ConfiguredContract contract = Root as ConfiguredContract; DialogBox dialogBox = contract.Behaviours.Select(b => b as DialogBox).Where(b => b != null).FirstOrDefault(); if (dialogBox != null) { FieldInfo detailsField = typeof(DialogBox).GetFields(BindingFlags.Instance | BindingFlags.NonPublic). Where(fi => fi.FieldType == typeof(List <DialogBox.DialogDetail>)).First(); DialogBox.DialogDetail detail = ((List <DialogBox.DialogDetail>)detailsField.GetValue(dialogBox)).First(); DialogBox.ImageSection starJebImage = detail.sections.First() as DialogBox.ImageSection; starJebImage.imageURL = protoStarJeb.gender == ProtoCrewMember.Gender.Male ? "ContractPacks/AnomalySurveyor/Images/starjeb.dds.noload" : "ContractPacks/AnomalySurveyor/Images/starjeb_female.dds.noload"; } return(true); } } return(false); case MonolithState.FULL_OF_STARS1: { // Backup progress tracking progressTreeBackup = new ConfigNode("PROGRESS_TREE_BACKUP"); ProgressTracking.Instance.OnSave(progressTreeBackup); // Give the first kick away from Jool - this one using regular velocity change CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); // Find closest point on the jool-monolith line, and throw us away from that (so we don't hit either) Vector3 line = monolith.transform.position - jool.transform.position; float t = Vector3.Dot(line, (starJeb.transform.position - jool.transform.position)) / Vector3.Dot(line, line); Vector3 closest = jool.transform.position + line * t; velocity = (starJeb.transform.position - (t > 1.0 ? jool.transform.position : closest)).normalized; velocity += new Vector3(0.0f, 0.1f, 0.0f); velocity *= 15000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); // Camera to target jool FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition((starJeb.transform.position - jool.transform.position).normalized * 25.0f); } return(false); case MonolithState.FULL_OF_STARS2: if (Time.fixedTime - stepTime > 4.0f) { // Give the second kick away from Jool - these using anti-kraken velocity change CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity += new Vector3(0.0f, 0.1f, 0.0f); velocity *= 1500000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS3: if (Time.fixedTime - stepTime > 3.0f) { // Give the third kick away from Jool CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity *= 20000000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS4: if (Time.fixedTime - stepTime > 2.0f) { // Give the fourth and final kick away from Jool CelestialBody jool = FlightGlobals.Bodies.Where(b => b.name == "Jool").First(); velocity = (starJeb.transform.position - jool.transform.position).normalized; velocity *= 200000000; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); nextState(); } return(false); case MonolithState.FULL_OF_STARS5: if (Time.fixedTime - stepTime > 2.0f) { // Move along nextState(); } return(false); case MonolithState.FULL_OF_STARS_DRES1: { // Visit Dres CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First(); // Determine which side the sun is on - makes for a better show CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - dres.transform.position; sunnySide.x = 0.0f; sunnySide.y = 1; // Move across the top of the planet sunnySide.z = Math.Sign(sunnySide.z); // Set position for starjeb float distance = 4.0f * (float)dres.Radius; starJeb.SetPosition(dres.transform.position + new Vector3(distance, (float)dres.Radius, (float)dres.Radius * sunnySide.z)); velocity = (dres.transform.position - starJeb.transform.position + sunnySide * ((float)dres.Radius)).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); starJeb.SetWorldVelocity(dres.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_DRES2: { // Camera to target Dres - do this on a seperate update to allow KSP to catch up CelestialBody dres = FlightGlobals.Bodies.Where(b => b.name == "Dres").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - dres.transform.position).normalized * 10.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_DRES3: if (Time.fixedTime - stepTime > 5.5f) { // Done with Dres nextState(); } return(false); case MonolithState.FULL_OF_STARS_DUNA1: { // Start between the sun and Duna CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - duna.transform.position; sunnySide.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)duna.Radius; starJeb.SetPosition(duna.transform.position + sunnySide * distance); // Go straight at Duna velocity = (duna.transform.position - starJeb.transform.position).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); // Now offset him down so he doesn't actually hit Duna... starJeb.SetPosition(starJeb.transform.position + new Vector3(0.0f, -((float)duna.Radius + 55000), 0.0f)); starJeb.SetWorldVelocity(duna.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_DUNA2: { // Camera to target Duna - do this on a seperate update to allow KSP to catch up CelestialBody duna = FlightGlobals.Bodies.Where(b => b.name == "Duna").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - duna.transform.position).normalized * 25.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_DUNA3: if (Time.fixedTime - stepTime > 5.5f) { // Done with Duna nextState(); } return(false); case MonolithState.FULL_OF_STARS_EELOO1: { // Start perpendicular to the sun and Eeloo CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 perp = eeloo.transform.position - sun.transform.position; float tmp = perp.x; perp.x = -perp.z; perp.z = tmp; perp.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)eeloo.Radius; starJeb.SetPosition(eeloo.transform.position + perp * distance); // Determine which side the sun is on - makes for a better show Vector3 sunnySide = sun.transform.position - eeloo.transform.position; sunnySide.Normalize(); // Go straight at Eeloo velocity = (eeloo.transform.position - starJeb.transform.position).normalized; velocity *= distance / 3.0f; LoggingUtil.LogDebug(this, "kick magnitude will be: " + velocity); // Now offset him down so he doesn't actually hit Eeloo... starJeb.SetPosition(starJeb.transform.position + sunnySide * ((float)eeloo.Radius * 1.5f)); starJeb.SetWorldVelocity(eeloo.getRFrmVel(starJeb.transform.position)); nextState(); } return(false); case MonolithState.FULL_OF_STARS_EELOO2: { // This time won't target directly towards Eeloo, as the player will have some idea // what is up by now. CelestialBody eeloo = FlightGlobals.Bodies.Where(b => b.name == "Eeloo").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 awayFromSun = sun.transform.position - eeloo.transform.position; awayFromSun.Normalize(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromSun * 50.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_EELOO3: if (Time.fixedTime - stepTime > 5.5f) { velocity = null; // Done with Eeloo nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE1: { CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); Vector3 targetPosition = Destination.Value; Vector3 normal = eve.GetSurfaceNVector(eveLatitude, eveLongitude); startDistance = 10000000f; Vector3 start = targetPosition + normal * startDistance; starJeb.SetPosition(start); nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE2: { // Camera straight towards Eve - we're going in! CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); Vector3 awayFromEve = starJeb.transform.position - eve.transform.position; awayFromEve.Normalize(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + awayFromEve * 15.0f); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_EVE3: // Wait until we've held the position for a split second if (Time.fixedTime - stepTime >= 9.3f) { nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE4: // Give the player a bit to get settled, then let the fun begins if (Time.fixedTime - stepTime >= 15.0f) { // Spawn some asteroids CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); ScenarioDiscoverableObjects asteroidSpawner = (ScenarioDiscoverableObjects)HighLogic.CurrentGame.scenarios.Find( s => s.moduleRef is ScenarioDiscoverableObjects).moduleRef; System.Random random = new System.Random(); // Spawn some more asteroids for (int i = 0; i < ASTEROID_COUNT; i++) { asteroidSpawner.SpawnAsteroid(); } nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE5: // Wait a full second after spawning the asteroids - we're not allowed to pull // them off rails until they've been active a bit if (Time.fixedTime - stepTime > 1.0f) { // Spawn some asteroids CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); System.Random random = new System.Random(); foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT)) { // Set the position double r = random.NextDouble() * 0.02 + 0.002; double theta = random.NextDouble() * 2.0 * Math.PI; double latitude = starJeb.latitude + r * Math.Sin(theta); double longitude = starJeb.longitude + r * Math.Cos(theta); double altitude = starJeb.altitude + 100 + random.NextDouble() * 200; asteroid.SetPosition(eve.GetWorldSurfacePosition(latitude, longitude, altitude)); asteroid.ChangeWorldVelocity(asteroid.GetSrfVelocity()); asteroid.Load(); asteroid.GoOffRails(); } nextState(); } return(false); case MonolithState.FULL_OF_STARS_EVE6: { // Determine if there's an asteroid about to kill us CelestialBody eve = FlightGlobals.Bodies.Where(b => b.name == "Eve").First(); bool killerAsteroid = FlightGlobals.Vessels.Where(v => v.mainBody == eve && v.vesselType == VesselType.SpaceObject && Vector3.Distance(starJeb.transform.position, v.transform.position) < 5.5 * ((int)v.DiscoveryInfo.objectSize + 1)).Any(); if (killerAsteroid || Time.fixedTime - stepTime > 20.0f) { foreach (Vessel asteroid in FlightGlobals.Vessels.Where(v => v.vesselType == VesselType.SpaceObject).Reverse().Take(ASTEROID_COUNT)) { asteroid.Die(); } nextState(); } } return(false); case MonolithState.FULL_OF_STARS_KERBIN1: { CheatOptions.NoCrashDamage = false; // Start between the sun and Kerbin CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); CelestialBody sun = FlightGlobals.Bodies.Where(b => b.name == "Sun").First(); Vector3 sunnySide = sun.transform.position - kerbin.transform.position; sunnySide.Normalize(); // Set us up a nice 4 radiuses away... float distance = 4.0f * (float)kerbin.Radius; starJeb.SetPosition(kerbin.transform.position + sunnySide * distance); // Orient him properly KerbalEVA keva = starJeb.FindPartModulesImplementing <KerbalEVA>().First(); MethodInfo rotationMethod = typeof(KerbalEVA).GetMethod("correctGroundedRotation", BindingFlags.Instance | BindingFlags.NonPublic); starJeb.packed = true; rotationMethod.Invoke(keva, new object[] { }); starJeb.packed = false; // Hardcode an orbital velocity, because it's late and I'm tired starJeb.SetWorldVelocity(kerbin.getRFrmVel(starJeb.transform.position).normalized * 1085); nextState(); } return(false); case MonolithState.FULL_OF_STARS_KERBIN2: { // Camera to target kerbin - do this on a seperate update to allow KSP to catch up CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); FlightCamera.SetTarget(starJeb.transform); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 10.0f); starJeb.SetRotation(FlightCamera.fetch.transform.rotation * Quaternion.AngleAxis(180.0f, FlightCamera.fetch.transform.up)); // Make sure that the camera gets fixed if (Time.fixedTime - stepTime > 0.1f) { nextState(); } } return(false); case MonolithState.FULL_OF_STARS_KERBIN3: if (Time.fixedTime - stepTime > 2.0f) { // Turn into star jeb CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); starJeb.vesselName = "The Star Jeb"; Undress(starJeb.gameObject); FlightCamera.fetch.SetCamCoordsFromPosition(starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized * 1.5f); nextState(); } return(false); case MonolithState.FULL_OF_STARS_KERBIN4: if (Time.fixedTime - stepTime < 15.0f) { CelestialBody kerbin = FlightGlobals.Bodies.Where(b => b.name == "Kerbin").First(); Vector3 camDirection = starJeb.transform.position + (starJeb.transform.position - kerbin.transform.position).normalized; } else { nextState(); monolith.Die(); monolith = null; starJeb.Die(); starJeb = null; Vessel discovery = ContractVesselTracker.Instance.GetAssociatedVessel("Discovery One"); FlightGlobals.ForceSetActiveVessel(discovery); } return(false); case MonolithState.FULL_OF_STARS_FINAL: nextState(); return(true); default: return(false); } }
private void killVessel(Vessel vessel) { if (vessel !=null) { if (!isInFlightOrTracking && !syncing) { Log.Debug("Killing vessel immediately: " + vessel.id); try { vessel.Die(); } catch { Log.Debug("Failed to kill vessel immediately"); } //try { FlightGlobals.Vessels.Remove(vessel); } catch {} //StartCoroutine(destroyVesselOnNextUpdate(vessel)); } else { StartCoroutine(killVesselOnNextUpdate(vessel)); } } }
private IEnumerator<WaitForFixedUpdate> killVesselOnNextUpdate(Vessel vessel) { yield return new WaitForFixedUpdate(); if (vessel != null) { KMPClientMain.DebugLog("Killing vessel"); vessel.Die(); } }
public float RecycleVessel(Vessel v) { float ConversionEfficiency = 0.8f; double amount; VesselResources scrap = new VesselResources (v); string target_resource; PartResourceDefinition rp_def; if (ExLaunchPad.kethane_present) { target_resource = "Metal"; } else { target_resource = "RocketParts"; } rp_def = PartResourceLibrary.Instance.GetDefinition (target_resource); if (FlightGlobals.ActiveVessel == v) FlightGlobals.ForceSetActiveVessel (this.vessel); float mass = 0; foreach (var crew in v.GetVesselCrew ()) { mass += RecycleKerbal (crew, null); } foreach (string resource in scrap.resources.Keys) { amount = scrap.ResourceAmount (resource); mass += ReclaimResource (resource, amount, v.name); scrap.TransferResource (resource, -amount); } float hull_mass = v.GetTotalMass (); amount = hull_mass * ConversionEfficiency / rp_def.density; mass += ReclaimResource (target_resource, amount, v.name, "hull"); v.Die (); return mass; }
public CostReport getBuildCost(ConfigNode craft, string craftText = null) { lockedParts = false; ShipConstruct ship = new ShipConstruct(); if (!ship.LoadShip(craft)) { lockedParts = true; return(null); } if (ship.vesselDeltaV != null) { // The delta-v module is not needed. It has its own gameObject // for ShipConstruct. UnityEngine.Object.Destroy(ship.vesselDeltaV.gameObject); ship.vesselDeltaV = null; } if (!ship.shipPartsUnlocked) { lockedParts = true; } GameObject ro = ship.parts[0].localRoot.gameObject; Vessel craftVessel = ro.AddComponent <Vessel>(); craftVessel.vesselName = "EL craftVessel - " + craft.GetValue("ship"); craftVessel.Initialize(true); SetCraftOrbit(craftVessel, OrbitDriver.UpdateMode.IDLE); foreach (Part part in craftVessel.parts) { SanitizePart(part); part.ModulesOnStart(); } if (ELSettings.B9Wings_Present) { if (!InitializeB9Wings(craftVessel) && ELSettings.FAR_Present) { InitializeFARSurfaces(craftVessel); } } else if (ELSettings.FAR_Present) { InitializeFARSurfaces(craftVessel); } BuildCost resources = new BuildCost(); foreach (Part p in craftVessel.parts) { resources.addPart(p); } if (craftText != null && ELSettings.ShowCraftHull) { Quickhull.dump_points = ELSettings.DebugCraftHull; Quickhull.points_path = savesPath; DestroyCraftHull(); craftHull = new CraftHull(craftText); // GetVesselBox will rotate and minimize any launchclamps, // which is probably a good thing. var rootPart = ship.parts[0].localRoot; var rootPos = rootPart.transform.position; craftHull.SetBox(GetVesselBox(ship), rootPos); builder.SetShipTransform(rootPart.transform, rootPart); craftHull.SetTransform(rootPart.transform); if (ELSettings.DebugCraftHull || !craftHull.LoadHull(savesPath)) { craftHull.BuildConvexHull(craftVessel); craftHull.SaveHull(savesPath); } } craftVessel.Die(); return(resources.cost); }
private void OnVesselCreate(Vessel checkVessel) { if (VesselIsAsteroid(checkVessel)) { lock (serverAsteroidListLock) { if (LockSystem.fetch.LockIsOurs("asteroid-spawning")) { if (!serverAsteroids.Contains(checkVessel.id.ToString())) { if (GetAsteroidCount() <= maxNumberOfUntrackedAsteroids) { DarkLog.Debug("Spawned in new server asteroid!"); serverAsteroids.Add(checkVessel.id.ToString()); VesselWorker.fetch.RegisterServerVessel(checkVessel.id.ToString()); NetworkWorker.fetch.SendVesselProtoMessage(checkVessel.protoVessel, false, false); } else { DarkLog.Debug("Killing non-server asteroid " + checkVessel.id); checkVessel.Die(); } } } else { if (!serverAsteroids.Contains(checkVessel.id.ToString())) { DarkLog.Debug("Killing non-server asteroid " + checkVessel.id + ", we don't own the asteroid-spawning lock"); checkVessel.Die(); } } } } }
public void VesselUnloadEvent(Vessel vessel) { //If we're disabled, just return if (!Settings1.Instance.SREnabled) { return; } //If the vessel or the protovessel are null then we surely can't do anything with them if (vessel == null || vessel.protoVessel == null) { return; } ProtoVessel pv = vessel.protoVessel; //If we aren't supposed to recover clamps, then don't try. if (Settings1.Instance.RecoverClamps) { //If we've already recovered the clamps, then no need to try again if (clampsRecovered.Find(a => a.id == vessel.id) != null) { return; } //Assign the pv variable to the protovessel, then look for if the root is a clamp if (pv.protoPartSnapshots.Count > 0 && pv.protoPartSnapshots[0].modules.Exists(m => m.moduleName == "LaunchClamp")) { //We look for the launchclamp module, which will hopefully cover FASA and stock. Log.Info("[SR] Recovering a clamp!"); //Add it to the recovered clamps list so we don't try to recover it again clampsRecovered.Add(vessel); float totalRefund = 0; //Loop over all the parts and calculate their cost (we recover at 100% since we're at the launchpad/runway) foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots) { float out1, out2; totalRefund += ShipConstruction.GetPartCosts(pps, pps.partInfo, out out1, out out2); } //Add dem funds to da total. Get dem funds! AddFunds(totalRefund); //Fire the successful recovery event. Even though this isn't a stage we still need to do this for things like KCT to recover the parts. //Can be averted with stock functions if I can get them working properly APIManager.instance.RecoverySuccessEvent.Fire(vessel, new float[] { 100, totalRefund, 0 }, "SUCCESS"); //And then we try a bunch of things to make sure the clamps are removed (remove it from the flight state, kill it, and destroy it) HighLogic.CurrentGame.flightState.protoVessels.Remove(pv); vessel.Die(); Destroy(vessel); //So, question for myself. Would it be better to try to manually fire the recovery events? Would that really be worth anything? } } //If it's a stage that will be destroyed, we need to manually recover the Kerbals if (Settings1.Instance.PreRecover && pv.GetVesselCrew().Count > 0) { //Check if the conditions for vessel destruction are met if (vessel != FlightGlobals.ActiveVessel && !vessel.isEVA && vessel.mainBody == Planetarium.fetch.Home && pv.situation != Vessel.Situations.LANDED && vessel.altitude < cutoffAlt && vessel.altitude > 0 && (FlightGlobals.ActiveVessel.transform.position - vessel.transform.position).sqrMagnitude > Math.Pow(vessel.vesselRanges.GetSituationRanges(Vessel.Situations.FLYING).pack, 2) - 250) { Log.Info("[SR] Vessel " + pv.vesselName + " is going to be destroyed. Pre-recovering!"); //Kerbal death should be handled by SR instead RecoverVessel(vessel, true); } else { TryWatchVessel(vessel); } } }
private IEnumerator<WaitForFixedUpdate> killVesselOnNextUpdate(Vessel vessel) { yield return new WaitForFixedUpdate(); if (vessel != null) { KMPClientMain.DebugLog("Killing vessel"); try { vessel.Die(); } catch {} try { FlightGlobals.Vessels.Remove(vessel); } catch {} StartCoroutine(destroyVesselOnNextUpdate(vessel)); } }
public float RecycleVessel(Vessel v) { float ConversionEfficiency = 0.8f; double amount; VesselResources scrap = new VesselResources(v); PartResourceDefinition rp_def; rp_def = PartResourceLibrary.Instance.GetDefinition("RocketParts"); float mass = 0; foreach (string resource in scrap.resources.Keys) { amount = scrap.ResourceAmount (resource); mass += ReclaimResource(resource, amount, v.name); } float hull_mass = v.GetTotalMass(); amount = hull_mass * ConversionEfficiency / rp_def.density; mass += ReclaimResource("RocketParts", amount, v.name, "hull"); v.Die(); return mass; }
private void KillVessel(Vessel killVessel) { if (killVessel != null) { //TODO: Deselect the vessel in the tracking station if we are about to kill it. DarkLog.Debug("Killing vessel: " + killVessel.id.ToString()); killVessel.DespawnCrew(); //Add it to the delay kill list to make sure it dies. //With KSP, If it doesn't work first time, keeping doing it until it does. if (!delayKillVessels.Contains(killVessel)) { delayKillVessels.Add(killVessel); } lastKillVesselDestroy[killVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup; try { killVessel.Die(); } catch (Exception killException) { DarkLog.Debug("Error destroying vessel: " + killException); } } }
public static void CalculateOrbit(Vessel vessel, Orbit oldOrbit, OrbitDriver driver) { VesselDied = false; if (!VesselData.Message.ContainsKey(vessel.id)) { VesselData.Message.Add(vessel.id, false); VesselData.DisplayedMessage = false; } else { VesselData.Message.TryGetValue(vessel.id, out VesselData.DisplayedMessage); } vessel.GoOnRails(); var oldBody = vessel.orbitDriver.orbit.referenceBody; // The ISS decays at about 2km/month = 2000/30*24*60*60 == 7.7x10^-4 m/s double BodyGravityConstant = vessel.orbitDriver.orbit.referenceBody.GeeASL; double AtmosphereMultiplier; double MaxDecayInfluence = vessel.orbitDriver.orbit.referenceBody.Radius * 10; if (vessel.orbitDriver.orbit.referenceBody.atmosphere) { AtmosphereMultiplier = vessel.orbitDriver.orbit.referenceBody.atmospherePressureSeaLevel / 101.325; } else { AtmosphereMultiplier = 0.5; } if (vessel.orbitDriver.orbit.semiMajorAxis + 50 < MaxDecayInfluence ) { double Lambda = 0.000000000133913 * UI.DifficultySetting; //0.000000000133913; double Sigma = MaxDecayInfluence - vessel.orbitDriver.orbit.altitude; DecayValue = (double)TimeWarp.CurrentRate * Sigma * BodyGravityConstant * AtmosphereMultiplier * Lambda; if (vessel.orbitDriver.orbit.referenceBody.atmosphere) { if (vessel.orbitDriver.orbit.PeA < vessel.orbitDriver.orbit.referenceBody.atmosphereDepth) { DecayValue = DecayValue * (Math.Pow(Math.E, vessel.orbitDriver.orbit.referenceBody.atmosphereDepth - vessel.orbitDriver.orbit.PeA)); // Have it increase alot more as we enter the hard atmosphere } //EstimatedTimeUntilDeorbit = (float)(vessel.orbitDriver.orbit.altitude - (float)vessel.orbitDriver.orbit.referenceBody.atmosphereDepth) / (float)DecayValue; MaxDecayValue = ((vessel.orbitDriver.orbit.referenceBody.Radius + vessel.orbitDriver.orbit.referenceBody.atmosphereDepth) * BodyGravityConstant * AtmosphereMultiplier * Lambda); EstimatedTimeUntilDeorbit = ((float)(vessel.orbitDriver.orbit.semiMajorAxis - (float)vessel.orbitDriver.orbit.referenceBody.atmosphereDepth)) / (float)MaxDecayValue; // EstimatedTimeUntilDeorbit = (float)(vessel.orbitDriver.orbit.PeA - (((vessel.orbitDriver.referenceBody.atmosphereDepth)/((MaxDecayValue+DecayValue)/2) - vessel.orbitDriver.orbit.PeA)) *((MaxDecayValue + DecayValue) / 2)); } else { //EstimatedTimeUntilDeorbit = (float)(vessel.orbitDriver.orbit.altitude - 100) / (float)DecayValue; MaxDecayValue = ((vessel.orbitDriver.orbit.referenceBody.Radius + 100) * BodyGravityConstant * AtmosphereMultiplier * Lambda); EstimatedTimeUntilDeorbit = ((float)(vessel.orbitDriver.orbit.semiMajorAxis - (float)vessel.orbitDriver.orbit.referenceBody.atmosphereDepth)) / (float)MaxDecayValue; } if (VesselData.DecayTimes.ContainsKey(vessel.id)) { VesselData.DecayTimes.Remove(vessel.id); VesselData.DecayTimes.Add(vessel.id, EstimatedTimeUntilDeorbit); } else { VesselData.DecayTimes.Add(vessel.id, EstimatedTimeUntilDeorbit); } // print(vessel.name + " Semi major axis reduced by: " + (DecayValue)); } else { DecayValue = 0; if (VesselData.DecayTimes.ContainsKey(vessel.id)) { VesselData.DecayTimes.Remove(vessel.id); VesselData.DecayTimes.Add(vessel.id, 0.5f); } else { VesselData.DecayTimes.Add(vessel.id, 0.5f); } } if (VesselDied == false) // Just Incase the vessel is destroyed part way though the check. { if (vessel.orbitDriver.orbit.referenceBody.GetInstanceID() != 0 || vessel.orbitDriver.orbit.semiMajorAxis > vessel.orbitDriver.orbit.referenceBody.Radius + 5) { SetNewOrbit(driver, oldOrbit); } } if (vessel.orbitDriver.orbit.referenceBody.atmosphere) // Big problem ( Jool, Eve, Duna, Kerbin, Laythe) { if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + vessel.orbitDriver.referenceBody.atmosphereDepth + 500) { FlightDriver.SetPause(true); TimeWarp.SetRate(1, true); FlightDriver.SetPause(false); print("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s hard atmosphere"); ScreenMessages.PostScreenMessage("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s hard atmosphere"); VesselData.Message.Remove(vessel.id); VesselData.Message.Add(vessel.id, true); } if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + vessel.orbitDriver.referenceBody.atmosphereDepth + 5) { VesselDied = true; } } else // Moon Smaller Problem { if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + 5000) { FlightDriver.SetPause(true); TimeWarp.SetRate(1, true); FlightDriver.SetPause(false); print("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s surface"); ScreenMessages.PostScreenMessage("Warning: " + vessel.name + " is approaching " + oldOrbit.referenceBody.name + "'s surface"); VesselData.Message.Remove(vessel.id); VesselData.Message.Add(vessel.id, true); } if (vessel.orbitDriver.orbit.semiMajorAxis < vessel.orbitDriver.orbit.referenceBody.Radius + 100) { VesselDied = true; } } if (VesselDied == false) { vessel.orbitDriver.pos = vessel.orbit.pos.xzy; vessel.orbitDriver.vel = vessel.orbit.vel; var newBody = vessel.orbitDriver.orbit.referenceBody; if (newBody != oldBody) { var evnt = new GameEvents.HostedFromToAction<Vessel, CelestialBody>(vessel, oldBody, newBody); GameEvents.onVesselSOIChanged.Fire(evnt); } } if (VesselDied == true) { vessel.Die(); VesselData.CanStationKeep.Remove(vessel.id); VesselData.DecayTimes.Remove(vessel.id); VesselData.DisplayedDecayTimes.Remove(vessel); VesselData.StationKeeping.Remove(vessel.id); } }
//store vessel void store_vessel(Vessel vsl, bool perform_checks = true) { StoredVessel stored_vessel = new StoredVessel(); if(perform_checks) //for normal operation { //check momentary states if(!can_store(vsl)) return; //check if the vessel can be stored, if unknown, try to store bool storable; if(!probed_ids.TryGetValue(vsl.id, out storable)) { stored_vessel = try_store(vsl); storable = stored_vessel != null; probed_ids.Add(vsl.id, storable); } if(!storable) return; } else //for storing packed constructs upon hangar launch { stored_vessel = new StoredVessel(vsl); stored_vessels.ForceAdd(stored_vessel); } //get vessel crew on board List<ProtoCrewMember> _crew = new List<ProtoCrewMember>(stored_vessel.crew); CrewTransfer.delCrew(vsl, _crew); vsl.DespawnCrew(); //first of, add crew to the hangar if there's a place CrewTransfer.addCrew(part, _crew); //then add to other vessel parts if needed CrewTransfer.addCrew(vessel, _crew); //recalculate volume and mass change_part_params(stored_vessel.metric); //switch to hangar vessel before storing if(FlightGlobals.ActiveVessel.id == vsl.id) FlightGlobals.ForceSetActiveVessel(vessel); //destroy vessel vsl.Die(); ScreenMessager.showMessage("Vessel has been docked inside the hangar", 3); }
private void KillVessel(Vessel killVessel) { if (killVessel != null) { //TODO: Deselect the vessel in the tracking station if we are about to kill it. DarkLog.Debug("Killing vessel: " + killVessel.id.ToString()); killVessel.DespawnCrew(); //Add it to the delay kill list to make sure it dies. //With KSP, If it doesn't work first time, keeping doing it until it does. if (!delayKillVessels.Contains(killVessel)) { delayKillVessels.Add(killVessel); } lastKillVesselDestroy[killVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup; if (killVessel.loaded) { try { killVessel.Unload(); } catch (Exception unloadException) { DarkLog.Debug("Error unloading vessel: " + unloadException); } } foreach (ProtoPartSnapshot pps in killVessel.protoVessel.protoPartSnapshots) { foreach (ProtoCrewMember pcm in pps.protoModuleCrew) { DarkLog.Debug("Unassigning " + pcm.name + " from " + killVessel.id.ToString()); pcm.rosterStatus = ProtoCrewMember.RosterStatus.Available; pcm.seatIdx = -1; } pps.protoModuleCrew.Clear(); } try { killVessel.Die(); } catch (Exception killException) { DarkLog.Debug("Error destroying vessel: " + killException); } } }
private IEnumerator<WaitForFixedUpdate> killVesselOnNextUpdate(Vessel vessel) { yield return new WaitForFixedUpdate(); if (vessel != null) { Log.Debug("Killing vessel" + vessel.id); try { vessel.Die(); } catch { Log.Debug("Failed to kill vessel"); } //try { FlightGlobals.Vessels.Remove(vessel); } catch {} //StartCoroutine(destroyVesselOnNextUpdate(vessel)); } }
/// <summary> /// Process a vessel that triggered the hangar. /// </summary> /// <param name="vsl">Vessel</param> void process_vessel(Vessel vsl) { //check if this vessel was encountered before; //if so, reset the timer and return MemoryTimer timer; if(probed_vessels.TryGetValue(vsl.id, out timer)) { timer.Reset(); return; } //if the vessel is new, check momentary states if(!hangar_is_ready(vsl)) return; //if the state is OK, try to store the vessel StoredVessel stored_vessel = try_store_vessel(vsl); //if failed, remember it if(stored_vessel == null) { timer = new MemoryTimer(); timer.EndAction += () => { if(probed_vessels.ContainsKey(vsl.id)) probed_vessels.Remove(vsl.id); }; probed_vessels.Add(vsl.id, timer); StartCoroutine(timer); return; } //deactivate the hangar Deactivate(); //calculate velocity change to conserve momentum deltaV = (vsl.orbit.vel-vessel.orbit.vel).xzy*stored_vessel.mass/vessel.GetTotalMass(); change_velocity = true; //get vessel crew on board var _crew = new List<ProtoCrewMember>(stored_vessel.crew); CrewTransfer.delCrew(vsl, _crew); vsl.DespawnCrew(); //first of, add crew to the hangar if there's a place CrewTransfer.addCrew(part, _crew); //then add to other vessel parts if needed CrewTransfer.addCrew(vessel, _crew); //switch to hangar vessel before storing if(FlightGlobals.ActiveVessel.id == vsl.id) FlightGlobals.ForceSetActiveVessel(vessel); //destroy vessel vsl.Die(); ScreenMessager.showMessage("\"{0}\" has been docked inside the hangar", stored_vessel.name); }
private void KillVessel(Vessel killVessel) { if (killVessel != null) { //TODO: Deselect the vessel in the tracking station if we are about to kill it. DarkLog.Debug("Killing vessel: " + killVessel.id.ToString()); killVessel.DespawnCrew(); //Add it to the delay kill list to make sure it dies. //With KSP, If it doesn't work first time, keeping doing it until it does. if (!delayKillVessels.Contains(killVessel)) { delayKillVessels.Add(killVessel); } lastKillVesselDestroy[killVessel.id.ToString()] = UnityEngine.Time.realtimeSinceStartup; try { if (killVessel.parts != null) { try { for (int partID = killVessel.parts.Count - 1; partID >= 0; partID--) { Part killPart = killVessel.parts[partID]; killPart.explosionPotential = 0f; killPart.Die(); } } catch (Exception partException) { DarkLog.Debug("Error killing parts: " + partException); } } killVessel.Die(); } catch (Exception killException) { DarkLog.Debug("Error destroying vessel: " + killException); } } }
public void VesselUnloadEvent(Vessel vessel) { //If we're disabled, just return if (!Settings.Instance.SREnabled) return; //If the vessel or the protovessel are null then we surely can't do anything with them if (vessel == null || vessel.protoVessel == null) return; ProtoVessel pv = vessel.protoVessel; //If we aren't supposed to recover clamps, then don't try. if (Settings.Instance.RecoverClamps) { //If we've already recovered the clamps, then no need to try again if (clampsRecovered.Find(a => a.id == vessel.id) != null) return; //Assign the pv variable to the protovessel, then look for if the root is a clamp if (pv.protoPartSnapshots.Count > 0 && pv.protoPartSnapshots[0].modules.Exists(m => m.moduleName == "LaunchClamp")) { //We look for the launchclamp module, which will hopefully cover FASA and stock. Debug.Log("[SR] Recovering a clamp!"); //Add it to the recovered clamps list so we don't try to recover it again clampsRecovered.Add(vessel); float totalRefund = 0; //Loop over all the parts and calculate their cost (we recover at 100% since we're at the launchpad/runway) foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots) { float out1, out2; totalRefund += ShipConstruction.GetPartCosts(pps, pps.partInfo, out out1, out out2); } //Add dem funds to da total. Get dem funds! AddFunds(totalRefund); //Fire the successful recovery event. Even though this isn't a stage we still need to do this for things like KCT to recover the parts. //Can be averted with stock functions if I can get them working properly APIManager.instance.RecoverySuccessEvent.Fire(vessel, new float[] { 100, totalRefund, 0 }, "SUCCESS"); //And then we try a bunch of things to make sure the clamps are removed (remove it from the flight state, kill it, and destroy it) HighLogic.CurrentGame.flightState.protoVessels.Remove(pv); vessel.Die(); Destroy(vessel); //So, question for myself. Would it be better to try to manually fire the recovery events? Would that really be worth anything? } } //If it's a stage that will be destroyed, we need to manually recover the Kerbals if (Settings.Instance.RecoverKerbals && pv.GetVesselCrew().Count > 0) { //Check if the conditions for vessel destruction are met if (vessel != FlightGlobals.ActiveVessel && !vessel.isEVA && vessel.mainBody == Planetarium.fetch.Home && pv.situation != Vessel.Situations.LANDED && vessel.atmDensity >= 0.01) //unloading in > 0.01 atm and not landed //pv.altitude < vessel.mainBody.atmosphereDepth { Debug.Log("[SR] Vessel " + pv.vesselName + " is going to be destroyed. Recovering Kerbals!"); //Kerbal death should be handled by SR instead RecoveryItem recItem = new RecoveryItem(vessel); //Pre-recover the Kerbals recItem.PreRecoverKerbals(); //Add the ship to the RecoveryQueue to be handled by the OnDestroy event instance.RecoveryQueue.Add(recItem); } else WatchVessel(vessel); } }