public static float GetRecoveryValueForChuteLanding(ProtoVessel pv) { bool probeCoreAttached = false; foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots) { if (pps.modules.Find(module => (module.moduleName == "ModuleCommand" && ((ModuleCommand)module.moduleRef).minimumCrew == 0)) != null) { KCTDebug.Log("Probe Core found!"); probeCoreAttached = true; } } float RecoveryMod = probeCoreAttached ? 1.0f : KCT_GameStates.settings.RecoveryModifier; double distanceFromKSC = SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(pv.latitude, pv.longitude)); double maxDist = SpaceCenter.Instance.cb.Radius * Math.PI; float recoveryPercent = RecoveryMod * Mathf.Lerp(0.98f, 0.1f, (float)(distanceFromKSC / maxDist)); float totalReturn = 0; foreach (ProtoPartSnapshot pps in pv.protoPartSnapshots) { float dryCost, fuelCost; totalReturn += ShipConstruction.GetPartCosts(pps, pps.partInfo, out dryCost, out fuelCost); } float totalBeforeReturn = (float)Math.Round(totalReturn, 2); totalReturn *= recoveryPercent; totalReturn = (float)Math.Round(totalReturn, 2); KCTDebug.Log("Vessel being recovered by KCT. Percent returned: " + 100 * recoveryPercent + "%. Distance from KSC: " + Math.Round(distanceFromKSC / 1000, 2) + " km"); KCTDebug.Log("Funds being returned: " + totalReturn + "/" + totalBeforeReturn); return(totalReturn); }
public static void MakeSimulationSave() { string backupFile = KSPUtil.ApplicationRootPath + "saves/" + HighLogic.SaveFolder + "/KCT_simulation_backup.sfs"; string saveFile = KSPUtil.ApplicationRootPath + "saves/" + HighLogic.SaveFolder + "/persistent.sfs"; KCTDebug.Log("Making simulation backup file."); System.IO.File.Copy(saveFile, backupFile, true); }
public static void RecalculateEditorBuildTime(ShipConstruct ship) { KCTDebug.Log("Recalculating build time"); List <ConfigNode> partNodes = ship.SaveShip().GetNodes("PART").ToList(); KCT_GUI.PartsInUse.Clear(); if (KCT_GUI.useInventory) { foreach (ConfigNode part in partNodes) { string name = PartNameFromNode(part) + GetTweakScaleSize(part); if (!KCT_GUI.PartsInUse.ContainsKey(name)) { KCT_GUI.PartsInUse.Add(name, 1); } else { ++KCT_GUI.PartsInUse[name]; } } } if (!KCT_GameStates.EditorShipEditingMode) { KCT_GameStates.EditorBuildTime = KCT_Utilities.GetBuildTime(partNodes, true, KCT_GUI.useInventory); } else { List <string> partsForInventory = new List <string>(); if (KCT_GUI.useInventory) { List <string> newParts = new List <string>(PartDictToList(KCT_GUI.PartsInUse)); List <string> theInventory = new List <string>(PartDictToList(KCT_GameStates.PartInventory)); foreach (string s in PartDictToList(KCT_GameStates.EditedVesselParts)) { if (newParts.Contains(s)) { newParts.Remove(s); } } foreach (string s in newParts) { if (theInventory.Contains(s)) { theInventory.Remove(s); partsForInventory.Add(s); } } } foreach (string s in KCT_GameStates.editedVessel.InventoryParts) { partsForInventory.Add(s); } KCT_GameStates.EditorBuildTime = KCT_Utilities.GetBuildTime(partNodes, true, partsForInventory); } }
public static double AddFunds(double toAdd) { if (!CurrentGameIsCareer()) { return(0); } KCTDebug.Log("Adding funds: " + toAdd + ", New total: " + (Funding.Instance.Funds + toAdd)); return(Funding.Instance.Funds += toAdd); }
private void StageRecoverySuccessEvent(Vessel v, float[] infoArray, string reason) { if (!KCT_GameStates.settings.enabledForSave) { return; } KCTDebug.Log("Recovery Success Event triggered."); float damage = 0; if (infoArray.Length == 3) { damage = infoArray[0]; } else { KCTDebug.Log("Malformed infoArray received!"); } System.Random rand = new System.Random(); Dictionary <string, int> destroyed = new Dictionary <string, int>(); foreach (ProtoPartSnapshot part in v.protoVessel.protoPartSnapshots) { float random = (float)rand.NextDouble(); string name = part.partInfo.name + KCT_Utilities.GetTweakScaleSize(part); if (random < damage) { KCT_Utilities.AddPartToInventory(name); } else { string commonName = part.partInfo.title + KCT_Utilities.GetTweakScaleSize(part); Debug.Log("[KCT] Part " + commonName + " was too damaged to be used anymore and was scrapped! Chance: " + damage); if (!destroyed.ContainsKey(commonName)) { destroyed.Add(commonName, 1); } else { ++destroyed[commonName]; } } } if (destroyed.Count > 0 && !KCT_GameStates.settings.DisableAllMessages) { StringBuilder msg = new StringBuilder(); msg.AppendLine("The following parts were too damaged to be reused and were scrapped:"); foreach (KeyValuePair <string, int> entry in destroyed) { msg.AppendLine(entry.Value + " x " + entry.Key); } msg.AppendLine("\nChance of failure: " + Math.Round(100 * damage) + "%"); KCT_Utilities.DisplayMessage("KCT: Parts Scrapped", msg, MessageSystemButton.MessageButtonColor.ORANGE, MessageSystemButton.ButtonIcons.ALERT); } }
public static void AddPartToInventory(String name) { if (KCT_GameStates.PartInventory.ContainsKey(name)) { ++KCT_GameStates.PartInventory[name]; } else { KCT_GameStates.PartInventory.Add(name, 1); } KCTDebug.Log("Added " + name + " to part inventory"); }
public KCT_TechItem(RDTech techNode) { scienceCost = techNode.scienceCost; techName = techNode.title; techID = techNode.techID; progress = 0; protoNode = ResearchAndDevelopment.Instance.GetTechState(techID); KCTDebug.Log("techID = " + techID); KCTDebug.Log("BuildRate = " + BuildRate); KCTDebug.Log("TimeLeft = " + TimeLeft); }
public static void LoadSimulationSave() { string backupFile = KSPUtil.ApplicationRootPath + "saves/" + HighLogic.SaveFolder + "/KCT_simulation_backup.sfs"; string saveFile = KSPUtil.ApplicationRootPath + "saves/" + HighLogic.SaveFolder + "/persistent.sfs"; KCT_Utilities.disableSimulationLocks(); KCT_GameStates.flightSimulated = false; Kerbal_Construction_Time.moved = false; KCT_GameStates.simulationEndTime = 0; KCTDebug.Log("Swapping persistent.sfs with simulation backup file."); System.IO.File.Copy(backupFile, saveFile, true); System.IO.File.Delete(backupFile); }
public static bool RemovePartFromInventory(String name, Dictionary <String, int> inventory) { if (inventory.ContainsKey(name)) { --inventory[name]; if (inventory[name] == 0) { inventory.Remove(name); } KCTDebug.Log("Removed " + name + " from part inventory"); return(true); } return(false); }
public override void OnLoad(ConfigNode node) { KCTDebug.Log("Reading from persistence."); base.OnLoad(node); KCT_DataStorage kctVS = new KCT_DataStorage(); KCT_BuildListStorage bls = new KCT_BuildListStorage(); KCT_TechStorage tS = new KCT_TechStorage(); ConfigNode CN = node.GetNode(kctVS.GetType().Name); if (CN != null) { ConfigNode.LoadObjectFromConfig(kctVS, CN); } CN = node.GetNode(bls.GetType().Name); if (CN != null) { ConfigNode.LoadObjectFromConfig(bls, CN); } CN = node.GetNode(tS.GetType().Name); if (CN != null) { ConfigNode.LoadObjectFromConfig(tS, CN); } for (int i = 0; i < KCT_GameStates.VABList.Count; i++) { KCT_GameStates.VABList[i].shipNode = node.GetNode("VAB" + i); } for (int i = 0; i < KCT_GameStates.SPHList.Count; i++) { KCT_GameStates.SPHList[i].shipNode = node.GetNode("SPH" + i); } for (int i = 0; i < KCT_GameStates.VABWarehouse.Count; i++) { KCT_GameStates.VABWarehouse[i].shipNode = node.GetNode("VABWH" + i); } for (int i = 0; i < KCT_GameStates.SPHWarehouse.Count; i++) { KCT_GameStates.SPHWarehouse[i].shipNode = node.GetNode("SPHWH" + i); } for (int i = 0; i < KCT_GameStates.TechList.Count; i++) { KCT_GameStates.TechList[i].protoNode = new ProtoTechNode(node.GetNode("Tech" + i)); } Kerbal_Construction_Time.DelayedStart(); }
public void vesselRecoverEvent(ProtoVessel v) { if (!KCT_GameStates.settings.enabledForSave) { return; } if (!KCT_GameStates.flightSimulated && !v.vesselRef.isEVA) { 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(name); } } }
public static double SpendFunds(double toSpend) { if (!CurrentGameIsCareer()) { return(0); } KCTDebug.Log("Removing funds: " + toSpend + ", New total: " + (Funding.Instance.Funds - toSpend)); if (toSpend < Funding.Instance.Funds) { return(Funding.Instance.Funds -= toSpend); } else { return(Funding.Instance.Funds); } }
public static KCT_BuildListVessel AddVesselToBuildList(KCT_BuildListVessel blv, Dictionary <String, int> inventory) { if (CurrentGameIsCareer()) { float totalCost = blv.cost; double prevFunds = Funding.Instance.Funds; double newFunds = SpendFunds(totalCost); if (prevFunds == newFunds) { KCTDebug.Log("Tried to add " + blv.shipName + " to build list but not enough funds."); KCTDebug.Log("Vessel cost: " + blv.cost + ", Current funds: " + newFunds); var msg = new ScreenMessage("Not Enough Funds To Build!", 4.0f, ScreenMessageStyle.UPPER_CENTER); ScreenMessages.PostScreenMessage(msg, true); return(blv); } } string type = ""; if (blv.type == KCT_BuildListVessel.ListType.VAB) { KCT_GameStates.VABList.Add(blv); type = "VAB"; } else if (blv.type == KCT_BuildListVessel.ListType.SPH) { KCT_GameStates.SPHList.Add(blv); type = "SPH"; } if (inventory.Count > 0) { foreach (ConfigNode p in blv.ExtractedPartNodes) { if (KCT_Utilities.RemovePartFromInventory(p, inventory)) { blv.InventoryParts.Add(PartNameFromNode(p) + GetTweakScaleSize(p)); } } } KCTDebug.Log("Added " + blv.shipName + " to " + type + " build list. Cost: " + blv.cost); //KCTDebug.Log("Cost Breakdown (total, parts, fuel): " + blv.totalCost + ", " + blv.dryCost + ", " + blv.fuelCost); var message = new ScreenMessage("[KCT] Added " + blv.shipName + " to " + type + " build list.", 4.0f, ScreenMessageStyle.UPPER_CENTER); ScreenMessages.PostScreenMessage(message, true); return(blv); }
public static void DelayedStart() { if (!updateChecked) { if (KCT_GameStates.settings.CheckForUpdates && !KCT_GameStates.firstStart) //Check for updates { KCT_UpdateChecker.CheckForUpdate(false, KCT_GameStates.settings.VersionSpecific); } updateChecked = true; } if (!HighLogic.LoadedSceneIsFlight && KCT_GameStates.buildSimulatedVessel) { KCT_GameStates.buildSimulatedVessel = false; KCT_BuildListVessel toBuild = KCT_GameStates.launchedVessel.NewCopy(false); toBuild.buildPoints = KCT_Utilities.GetBuildTime(toBuild.ExtractedPartNodes, true, KCT_GUI.useInventory); KCT_Utilities.AddVesselToBuildList(toBuild, KCT_GUI.useInventory); } if (!HighLogic.LoadedSceneIsFlight && KCT_GameStates.FundsToChargeAtSimEnd != 0) { KCT_Utilities.SpendFunds(KCT_GameStates.FundsToChargeAtSimEnd); KCT_GameStates.FundsToChargeAtSimEnd = 0; } if (!HighLogic.LoadedSceneIsFlight && KCT_GameStates.FundsGivenForVessel != 0) { KCT_Utilities.SpendFunds(KCT_GameStates.FundsGivenForVessel); KCT_GameStates.FundsGivenForVessel = 0; } if (HighLogic.LoadedSceneIsFlight && !KCT_GameStates.flightSimulated) { KCT_GUI.hideAll(); if (FlightGlobals.ActiveVessel.situation == Vessel.Situations.PRELAUNCH) { bool removed = KCT_GameStates.launchedVessel.RemoveFromBuildList(); if (removed) //Only do these when the vessel is first removed from the list { //Add the cost of the ship to the funds so it can be removed again by KSP KCT_Utilities.AddFunds(KCT_Utilities.GetTotalVesselCost(FlightGlobals.ActiveVessel.protoVessel)); FlightGlobals.ActiveVessel.vesselName = KCT_GameStates.launchedVessel.shipName; } } List <VesselType> invalidTypes = new List <VesselType> { VesselType.Debris, VesselType.SpaceObject, VesselType.Unknown }; if (!invalidTypes.Contains(FlightGlobals.ActiveVessel.vesselType) && !KCT_GameStates.BodiesVisited.Contains(FlightGlobals.ActiveVessel.mainBody.bodyName)) { KCT_GameStates.BodiesVisited.Add(FlightGlobals.ActiveVessel.mainBody.bodyName); var message = new ScreenMessage("[KCT] New simulation body unlocked: " + FlightGlobals.ActiveVessel.mainBody.bodyName, 4.0f, ScreenMessageStyle.UPPER_LEFT); ScreenMessages.PostScreenMessage(message, true); KCTDebug.Log("Unlocked sim body: " + FlightGlobals.ActiveVessel.mainBody.bodyName); } } if (HighLogic.LoadedSceneIsFlight && KCT_GameStates.flightSimulated) { KCTDebug.Log("Simulation started"); KCT_GUI.hideAll(); KCT_GUI.showSimulationWindow = true; KCT_GUI.showTimeRemaining = true; } if (HighLogic.LoadedSceneIsEditor) { if (KCT_GameStates.EditorShipEditingMode) { KCTDebug.Log("Editing " + KCT_GameStates.editedVessel.shipName); EditorLogic.fetch.shipNameField.Text = KCT_GameStates.editedVessel.shipName; } if (!KCT_GUI.PrimarilyDisabled) { if (KCT_GameStates.settings.OverrideLaunchButton) { KCTDebug.Log("Taking control of launch button"); EditorLogic.fetch.launchBtn.methodToInvoke = "ShowLaunchAlert"; EditorLogic.fetch.launchBtn.scriptWithMethodToInvoke = Kerbal_Construction_Time.instance; } else { InputLockManager.SetControlLock(ControlTypes.EDITOR_LAUNCH, "KCTLaunchLock"); } } } if (HighLogic.LoadedScene == GameScenes.SPACECENTER) { if (KCT_Utilities.CurrentGameHasScience() && KCT_GameStates.TotalUpgradePoints == 0) { ConfigNode CN = new ConfigNode(); ResearchAndDevelopment.Instance.snapshot.Save(CN); ConfigNode[] techNodes = CN.GetNodes("Tech"); KCTDebug.Log("technodes length: " + techNodes.Length); KCT_GameStates.TotalUpgradePoints = techNodes.Length + 14; } if (!KCT_GUI.PrimarilyDisabled) { KCT_GUI.showBuildList = KCT_GameStates.showWindows[0]; KCT_GUI.ResetBLWindow(); } else { KCT_GUI.showBuildList = false; KCT_GameStates.showWindows[0] = false; } if (KCT_GameStates.firstStart) { KCTDebug.Log("Showing first start."); KCT_GUI.showFirstRun = true; } KCT_GameStates.firstStart = false; } }
public void FixedUpdate() { if (!KCT_GameStates.settings.enabledForSave) { return; } KCT_GameStates.UT = Planetarium.GetUniversalTime(); try { if (!KCT_GUI.PrimarilyDisabled && (HighLogic.LoadedScene == GameScenes.FLIGHT || HighLogic.LoadedScene == GameScenes.SPACECENTER || HighLogic.LoadedScene == GameScenes.TRACKSTATION && !KCT_GameStates.flightSimulated)) { IKCTBuildItem ikctItem = KCT_Utilities.NextThingToFinish(); if (KCT_GameStates.targetedItem == null && ikctItem != null) { KCT_GameStates.targetedItem = ikctItem; } if (KCT_GameStates.canWarp && ikctItem != null && !ikctItem.IsComplete()) { int warpRate = TimeWarp.CurrentRateIndex; if (SOIAlert()) { TimeWarp.SetRate(0, true); KCT_GameStates.canWarp = false; KCT_GameStates.warpInitiated = false; } else if (warpRate < KCT_GameStates.lastWarpRate) //if something else changes the warp rate then release control to them, such as Kerbal Alarm Clock { KCT_GameStates.canWarp = false; KCT_GameStates.lastWarpRate = 0; } else { if (ikctItem == KCT_GameStates.targetedItem && (10 * TimeWarp.deltaTime) > Math.Max((ikctItem.GetTimeLeft()), 0) && TimeWarp.CurrentRate > 1.0f) { TimeWarp.SetRate(--warpRate, true); } else if (warpRate == 0 && KCT_GameStates.warpInitiated) { KCT_GameStates.canWarp = false; KCT_GameStates.warpInitiated = false; } KCT_GameStates.lastWarpRate = warpRate; } } else if (ikctItem != null && ikctItem == KCT_GameStates.targetedItem && (KCT_GameStates.warpInitiated || KCT_GameStates.settings.ForceStopWarp) && TimeWarp.CurrentRate != 0 && (ikctItem.GetTimeLeft()) < (TimeWarp.deltaTime * 2) && (!ikctItem.IsComplete())) //Still warp down even if we don't control the clock { TimeWarp.SetRate(0, false); KCT_GameStates.warpInitiated = false; } else if (ikctItem != null && (KCT_GameStates.settings.ForceStopWarp) && TimeWarp.CurrentRate != 0 && (!ikctItem.IsComplete())) { if ((10 * TimeWarp.deltaTime) > Math.Max((ikctItem.GetTimeLeft()), 0) && TimeWarp.CurrentRate > 1.0f) { TimeWarp.SetRate(TimeWarp.CurrentRateIndex - 1, true); } } } if (HighLogic.LoadedScene == GameScenes.FLIGHT && KCT_GameStates.flightSimulated) //Simulated flights { if (FlightGlobals.ActiveVessel.loaded && !FlightGlobals.ActiveVessel.packed && !moved) { //moved = true; int secondsForMove = 3; if (KCT_GameStates.simulateInOrbit && loadDeferTime == DateTime.MaxValue) { loadDeferTime = DateTime.Now; } else if (KCT_GameStates.simulateInOrbit && (!KCT_GameStates.delayMove || DateTime.Now.CompareTo(loadDeferTime.AddSeconds(secondsForMove)) > 0)) { KCTDebug.Log("Moving vessel to orbit. " + KCT_GameStates.simulationBody.bodyName + ":" + KCT_GameStates.simOrbitAltitude + ":" + KCT_GameStates.simInclination); KCT_OrbitAdjuster.PutInOrbitAround(KCT_GameStates.simulationBody, KCT_GameStates.simOrbitAltitude, KCT_GameStates.simInclination); moved = true; loadDeferTime = DateTime.MaxValue; } else if (!KCT_GameStates.simulateInOrbit) { moved = true; } if (KCT_GameStates.simulateInOrbit && loadDeferTime != DateTime.MaxValue && lastSeconds != (loadDeferTime.AddSeconds(secondsForMove) - DateTime.Now).Seconds) { double remaining = (loadDeferTime.AddSeconds(secondsForMove) - DateTime.Now).TotalSeconds; ScreenMessages.PostScreenMessage("[KCT] Moving vessel in " + Math.Round(remaining) + " seconds", (float)(remaining - Math.Floor(remaining)), ScreenMessageStyle.UPPER_CENTER); lastSeconds = (int)remaining; } } if (KCT_GameStates.simulationEndTime > 0 && KCT_GameStates.UT >= KCT_GameStates.simulationEndTime) { FlightDriver.SetPause(true); KCT_GUI.showSimulationCompleteFlight = true; } if (FlightGlobals.ActiveVessel.situation != Vessel.Situations.PRELAUNCH && KCT_GameStates.simulationEndTime == 0 && KCT_GameStates.simulationTimeLimit > 0) { KCT_GameStates.simulationEndTime = Planetarium.GetUniversalTime() + KCT_GameStates.simulationTimeLimit; //Just in case the event doesn't fire } } if (!KCT_GUI.PrimarilyDisabled) { KCT_Utilities.ProgressBuildTime(); } } catch (IndexOutOfRangeException e) { print(e.Message); print(e.StackTrace); } }
public override void OnSave(ConfigNode node) { Boolean error = false; KCTDebug.Log("Writing to persistence."); base.OnSave(node); KCT_DataStorage kctVS = new KCT_DataStorage(); KCT_BuildListStorage bls = new KCT_BuildListStorage(); KCT_TechStorage tS = new KCT_TechStorage(); node.AddNode(kctVS.AsConfigNode()); node.AddNode(bls.AsConfigNode()); node.AddNode(tS.AsConfigNode()); for (int i = 0; i < KCT_GameStates.VABList.Count; i++) { KCTDebug.Log("VAB" + i); ConfigNode CN = new ConfigNode(); if (KCT_GameStates.VABList[i].shipNode != null) { KCT_GameStates.VABList[i].shipNode.CopyTo(CN, "VAB" + i); node.AddNode(CN); } else { Debug.LogError("[KCT] WARNING! DATA FAILURE EVENT ON CONFIGNODE VAB" + i); error = true; } } for (int i = 0; i < KCT_GameStates.SPHList.Count; i++) { KCTDebug.Log("SPH" + i); ConfigNode CN = new ConfigNode(); if (KCT_GameStates.SPHList[i].shipNode != null) { KCT_GameStates.SPHList[i].shipNode.CopyTo(CN, "SPH" + i); node.AddNode(CN); } else { Debug.LogError("[KCT] WARNING! DATA FAILURE EVENT ON CONFIGNODE SPH" + i); error = true; } } for (int i = 0; i < KCT_GameStates.VABWarehouse.Count; i++) { KCTDebug.Log("VABWH" + i); ConfigNode CN = new ConfigNode(); if (KCT_GameStates.VABWarehouse[i].shipNode != null) { KCT_GameStates.VABWarehouse[i].shipNode.CopyTo(CN, "VABWH" + i); node.AddNode(CN); } else { Debug.LogError("[KCT] WARNING! DATA FAILURE EVENT ON CONFIGNODE VABWH" + i); error = true; } } for (int i = 0; i < KCT_GameStates.SPHWarehouse.Count; i++) { KCTDebug.Log("SPHWH" + i); ConfigNode CN = new ConfigNode(); if (KCT_GameStates.SPHWarehouse[i].shipNode != null) { KCT_GameStates.SPHWarehouse[i].shipNode.CopyTo(CN, "SPHWH" + i); node.AddNode(CN); } else { Debug.LogError("[KCT] WARNING! DATA FAILURE EVENT ON CONFIGNODE SPHWH" + i); error = true; } } for (int i = 0; i < KCT_GameStates.TechList.Count; i++) { KCTDebug.Log("Tech" + i); ConfigNode CN = new ConfigNode("Tech" + i); if (KCT_GameStates.TechList[i].protoNode != null) { KCT_GameStates.TechList[i].protoNode.Save(CN); node.AddNode(CN); } else { Debug.LogError("[KCT] WARNING! DATA FAILURE EVENT ON CONFIGNODE Tech" + i); error = true; } } if (error) { //TODO: Popup with error message } }
public void Start() { KCT_GameStates.settings.Load(); //Load the settings file, if it exists KCT_GameStates.settings.Save(); //Save the settings file, with defaults if it doesn't exist KCT_GameStates.timeSettings.Load(); //Load the time settings KCT_GameStates.timeSettings.Save(); //Save the time settings //Code for saving to the persistence.sfs ProtoScenarioModule scenario = HighLogic.CurrentGame.scenarios.Find(s => s.moduleName == typeof(KerbalConstructionTimeData).Name); if (scenario == null) { try { Debug.Log("[KCT] Adding InternalModule scenario to game '" + HighLogic.CurrentGame.Title + "'"); HighLogic.CurrentGame.AddProtoScenarioModule(typeof(KerbalConstructionTimeData), new GameScenes[] { GameScenes.FLIGHT, GameScenes.SPACECENTER, GameScenes.EDITOR, GameScenes.SPH, GameScenes.TRACKSTATION }); // the game will add this scenario to the appropriate persistent file on save from now on } catch (ArgumentException ae) { Debug.LogException(ae); } catch { Debug.Log("[KCT] Unknown failure while adding scenario."); } } else { if (!scenario.targetScenes.Contains(GameScenes.SPACECENTER)) { scenario.targetScenes.Add(GameScenes.SPACECENTER); } if (!scenario.targetScenes.Contains(GameScenes.FLIGHT)) { scenario.targetScenes.Add(GameScenes.FLIGHT); } if (!scenario.targetScenes.Contains(GameScenes.EDITOR)) { scenario.targetScenes.Add(GameScenes.EDITOR); } if (!scenario.targetScenes.Contains(GameScenes.SPH)) { scenario.targetScenes.Add(GameScenes.SPH); } if (!scenario.targetScenes.Contains(GameScenes.TRACKSTATION)) { scenario.targetScenes.Add(GameScenes.TRACKSTATION); } } //End code for persistence.sfs if (KCT_GUI.PrimarilyDisabled) { if (InputLockManager.GetControlLock("KCTLaunchLock") == ControlTypes.EDITOR_LAUNCH) { InputLockManager.RemoveControlLock("KCTLaunchLock"); } } if (!KCT_Events.instance.eventAdded) { KCT_Events.instance.addEvents(); } if (!KCT_GameStates.settings.enabledForSave) { if (InputLockManager.GetControlLock("KCTKSCLock") == ControlTypes.KSC_FACILITIES) { InputLockManager.RemoveControlLock("KCTKSCLock"); } return; } //Begin primary mod functions KCT_GameStates.UT = Planetarium.GetUniversalTime(); KCT_GUI.guiDataSaver.Load(); if (HighLogic.LoadedSceneIsEditor) { if (KCT_GUI.showSimulationCompleteEditor) { KCT_GUI.hideAll(); KCT_GUI.showSimulationCompleteEditor = true; } else { KCT_GUI.hideAll(); } if (!KCT_GUI.PrimarilyDisabled) { KCT_GUI.showEditorGUI = KCT_GameStates.showWindows[1]; } if (KCT_GameStates.EditorShipEditingMode && KCT_GameStates.delayStart) { KCT_GameStates.delayStart = false; EditorLogic.fetch.shipNameField.Text = KCT_GameStates.editedVessel.shipName; } } else if (HighLogic.LoadedScene == GameScenes.SPACECENTER) { KCT_GUI.hideAll(); KCT_GameStates.reset(); if (HighLogic.CurrentGame.Mode == Game.Modes.SANDBOX) { KCT_GameStates.TotalUpgradePoints = KCT_GameStates.settings.SandboxUpgrades; } } if (HighLogic.LoadedSceneIsFlight && !KCT_GameStates.flightSimulated && FlightGlobals.ActiveVessel.situation == Vessel.Situations.PRELAUNCH && FlightGlobals.ActiveVessel.GetCrewCount() == 0 && KCT_GameStates.launchedCrew.Count > 0) { KerbalRoster roster = HighLogic.CurrentGame.CrewRoster; for (int i = 0; i < FlightGlobals.ActiveVessel.parts.Count; i++) { Part p = FlightGlobals.ActiveVessel.parts[i]; { CrewedPart cP = KCT_GameStates.launchedCrew.Find(part => part.partID == p.uid); if (cP == null) { continue; } List <ProtoCrewMember> crewList = cP.crewList; foreach (ProtoCrewMember crewMember in crewList) { if (crewMember != null) { ProtoCrewMember finalCrewMember = crewMember; foreach (ProtoCrewMember rosterCrew in roster.Crew) { if (rosterCrew.name == crewMember.name) { finalCrewMember = rosterCrew; } } KCTDebug.Log("Assigning " + finalCrewMember.name + " to " + p.partInfo.name); p.AddCrewmemberAt(finalCrewMember, crewList.IndexOf(crewMember)); finalCrewMember.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; if (finalCrewMember.seat != null) { finalCrewMember.seat.SpawnCrew(); } } } } } KCT_GameStates.launchedCrew.Clear(); } }
public bool RemoveFromBuildList() { string typeName = ""; bool removed = false; if (type == ListType.SPH) { if (KCT_GameStates.SPHWarehouse.Contains(this)) { removed = KCT_GameStates.SPHWarehouse.Remove(this); } else if (KCT_GameStates.SPHList.Contains(this)) { removed = KCT_GameStates.SPHList.Remove(this); } typeName = "SPH"; } else if (type == ListType.VAB) { if (KCT_GameStates.VABWarehouse.Contains(this)) { removed = KCT_GameStates.VABWarehouse.Remove(this); } else if (KCT_GameStates.VABList.Contains(this)) { removed = KCT_GameStates.VABList.Remove(this); } typeName = "VAB"; } KCTDebug.Log("Removing " + shipName + " from " + typeName + " storage/list."); if (!removed) { KCTDebug.Log("Failed to remove ship from list! Performing direct comparison of ids..."); foreach (KCT_BuildListVessel blv in KCT_GameStates.SPHWarehouse) { if (blv.id == this.id) { KCTDebug.Log("Ship found in SPH storage. Removing..."); removed = KCT_GameStates.SPHWarehouse.Remove(blv); break; } } if (!removed) { foreach (KCT_BuildListVessel blv in KCT_GameStates.VABWarehouse) { if (blv.id == this.id) { KCTDebug.Log("Ship found in VAB storage. Removing..."); removed = KCT_GameStates.VABWarehouse.Remove(blv); break; } } } if (!removed) { foreach (KCT_BuildListVessel blv in KCT_GameStates.VABList) { if (blv.id == this.id) { KCTDebug.Log("Ship found in VAB List. Removing..."); removed = KCT_GameStates.VABList.Remove(blv); break; } } } if (!removed) { foreach (KCT_BuildListVessel blv in KCT_GameStates.SPHList) { if (blv.id == this.id) { KCTDebug.Log("Ship found in SPH list. Removing..."); removed = KCT_GameStates.SPHList.Remove(blv); break; } } } } if (removed) { KCTDebug.Log("Sucessfully removed ship from storage."); } else { KCTDebug.Log("Still couldn't remove ship!"); } return(removed); }
public static void MoveVesselToWarehouse(int ListIdentifier, int index) { if (ToolbarManager.ToolbarAvailable) { KCT_GameStates.kctToolbarButton.Important = true; //Show the button if it is hidden away startedFlashing = DateTime.Now; //Set the time to start flashing } if (KCT_GameStates.settings.ForceStopWarp && TimeWarp.CurrentRateIndex != 0) { TimeWarp.SetRate(0, true); KCT_GameStates.warpInitiated = false; } StringBuilder Message = new StringBuilder(); Message.AppendLine("The following vessel is complete:"); KCT_BuildListVessel vessel = null; if (ListIdentifier == 0) //VAB list { vessel = KCT_GameStates.VABList[index]; KCT_GameStates.VABList.RemoveAt(index); KCT_GameStates.VABWarehouse.Add(vessel); Message.AppendLine(vessel.shipName); Message.AppendLine("Please check the VAB Storage to launch it."); } else if (ListIdentifier == 1)//SPH list { vessel = KCT_GameStates.SPHList[index]; KCT_GameStates.SPHList.RemoveAt(index); KCT_GameStates.SPHWarehouse.Add(vessel); Message.AppendLine(vessel.shipName); Message.AppendLine("Please check the SPH Storage to launch it."); } //Assign science based on science rate if (CurrentGameHasScience() && !vessel.cannotEarnScience) { AddScienceWithMessage((float)(KCT_GameStates.RDUpgrades[0] * 0.5 * vessel.buildPoints / 86400)); } //Add parts to the tracker if (!vessel.cannotEarnScience) { List <string> trackedParts = new List <string>(); foreach (ConfigNode p in vessel.ExtractedPartNodes) { if (!trackedParts.Contains(PartNameFromNode(p) + GetTweakScaleSize(p))) { AddPartToTracker(PartNameFromNode(p) + GetTweakScaleSize(p)); trackedParts.Add(PartNameFromNode(p) + GetTweakScaleSize(p)); } } } string stor = ListIdentifier == 0 ? "VAB" : "SPH"; KCTDebug.Log("Moved vessel " + vessel.shipName + " to " + stor + " storage."); foreach (KCT_BuildListVessel blv in KCT_GameStates.VABList) { double newTime = KCT_Utilities.GetBuildTime(blv.ExtractedPartNodes, true, blv.InventoryParts); //Use only the parts that were originally used when recalculating if (newTime < blv.buildPoints) { blv.buildPoints = blv.buildPoints - ((blv.buildPoints - newTime) * (100 - blv.ProgressPercent()) / 100.0); //If progress=0% then set to new build time, 100%=no change, 50%=half of difference. } } foreach (KCT_BuildListVessel blv in KCT_GameStates.SPHList) { double newTime = KCT_Utilities.GetBuildTime(blv.ExtractedPartNodes, true, blv.InventoryParts); if (newTime < blv.buildPoints) { blv.buildPoints = blv.buildPoints - ((blv.buildPoints - newTime) * (100 - blv.ProgressPercent()) / 100.0); //If progress=0% then set to new build time, 100%=no change, 50%=half of difference. } } KCT_GUI.ResetBLWindow(); if (!KCT_GameStates.settings.DisableAllMessages) { DisplayMessage("Vessel Complete!", Message, MessageSystemButton.MessageButtonColor.GREEN, MessageSystemButton.ButtonIcons.COMPLETE); } }
public void vesselDestroyEvent(Vessel v) { if (!KCT_GameStates.settings.enabledForSave) { return; } Dictionary <string, int> PartsRecovered = new Dictionary <string, int>(); float FundsRecovered = 0, KSCDistance = 0, RecoveryPercent = 0; StringBuilder Message = new StringBuilder(); if (FlightGlobals.fetch == null) { return; } if (v != null && !(HighLogic.LoadedSceneIsFlight && v.isActiveVessel) && v.mainBody.bodyName == "Kerbin" && (!v.loaded || v.packed) && v.altitude < 35000 && (v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.SUB_ORBITAL) && !v.isEVA) { double totalMass = 0; double dragCoeff = 0; bool realChuteInUse = false; float RCParameter = 0; if (!v.packed) //adopted from mission controller. { foreach (Part p in v.Parts) { p.Pack(); } } if (v.protoVessel == null) { return; } KCTDebug.Log("Attempting to recover vessel."); try { foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { //KCTDebug.Log("Has part " + p.partName + ", mass " + p.mass); List <string> ModuleNames = new List <string>(); foreach (ProtoPartModuleSnapshot ppms in p.modules) { //Debug.Log(ppms.moduleName); ModuleNames.Add(ppms.moduleName); } totalMass += p.mass; totalMass += GetResourceMass(p.resources); bool isParachute = false; if (ModuleNames.Contains("ModuleParachute")) { KCTDebug.Log("Found parachute module on " + p.partInfo.name); //Find the ModuleParachute (find it in the module list by checking for a module with the name ModuleParachute) ProtoPartModuleSnapshot ppms = p.modules.First(mod => mod.moduleName == "ModuleParachute"); float drag = 500; if (ppms.moduleRef != null) { ModuleParachute mp = (ModuleParachute)ppms.moduleRef; mp.Load(ppms.moduleValues); drag = mp.fullyDeployedDrag; } //Add the part mass times the fully deployed drag (typically 500) to the dragCoeff variable (you'll see why later) dragCoeff += p.mass * drag; //This is most definitely a parachute part isParachute = true; } if (ModuleNames.Contains("RealChuteModule")) { KCTDebug.Log("Found realchute module on " + p.partInfo.name); ProtoPartModuleSnapshot realChute = p.modules.First(mod => mod.moduleName == "RealChuteModule"); if ((object)realChute != null) //Some of this was adopted from DebRefund, as Vendan's method of handling multiple parachutes is better than what I had. { Type matLibraryType = AssemblyLoader.loadedAssemblies .SelectMany(a => a.assembly.GetExportedTypes()) .SingleOrDefault(t => t.FullName == "RealChute.Libraries.MaterialsLibrary"); ConfigNode[] parchutes = realChute.moduleValues.GetNodes("PARACHUTE"); foreach (ConfigNode chute in parchutes) { float diameter = float.Parse(chute.GetValue("deployedDiameter")); string mat = chute.GetValue("material"); System.Reflection.MethodInfo matMethod = matLibraryType.GetMethod("GetMaterial", new Type[] { mat.GetType() }); object MatLibraryInstance = matLibraryType.GetProperty("instance").GetValue(null, null); object materialObject = matMethod.Invoke(MatLibraryInstance, new object[] { mat }); float dragC = (float)KCT_Utilities.GetMemberInfoValue(materialObject.GetType().GetMember("dragCoefficient")[0], materialObject); RCParameter += dragC * (float)Math.Pow(diameter, 2); } isParachute = true; realChuteInUse = true; } } if (!isParachute) { if (p.partRef != null) { dragCoeff += p.mass * p.partRef.maximum_drag; } else { dragCoeff += p.mass * 0.2; } } } } catch (Exception e) { Debug.LogError("[KCT] Error while attempting to recover vessel."); Debug.LogException(e); } double Vt = double.MaxValue; if (!realChuteInUse) { dragCoeff = dragCoeff / (totalMass); Vt = Math.Sqrt((250 * 6.674E-11 * 5.2915793E22) / (3.6E11 * 1.22309485 * dragCoeff)); KCTDebug.Log("Using Stock Module! Drag: " + dragCoeff + " Vt: " + Vt); } else { Vt = Math.Sqrt((8000 * totalMass * 9.8) / (1.223 * Math.PI) * Math.Pow(RCParameter, -1)); //This should work perfect for multiple identical chutes and gives an approximation for multiple differing chutes KCTDebug.Log("Using RealChute Module! Vt: " + Vt); } if (Vt < 10.0) { KCTDebug.Log("Recovered parts from " + v.vesselName); foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { KCT_Utilities.AddPartToInventory(p.partInfo.name + KCT_Utilities.GetTweakScaleSize(p)); if (!PartsRecovered.ContainsKey(p.partInfo.title)) { PartsRecovered.Add(p.partInfo.title, 1); } else { ++PartsRecovered[p.partInfo.title]; } } Message.AppendLine("Vessel name: " + v.vesselName); Message.AppendLine("Parts recovered: "); for (int i = 0; i < PartsRecovered.Count; i++) { Message.AppendLine(PartsRecovered.Values.ElementAt(i) + "x " + PartsRecovered.Keys.ElementAt(i)); } if (KCT_Utilities.CurrentGameIsCareer()) { if (KCT_Utilities.StageRecoveryAddonActive || KCT_Utilities.DebRefundAddonActive) //Delegate funds handling to Stage Recovery or DebRefund if it's present { KCTDebug.Log("Delegating Funds recovery to another addon."); } else //Otherwise do it ourselves { bool probeCoreAttached = false; foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots) { if (pps.modules.Find(module => (module.moduleName == "ModuleCommand" && ((ModuleCommand)module.moduleRef).minimumCrew == 0)) != null) { KCTDebug.Log("Probe Core found!"); probeCoreAttached = true; break; } } float RecoveryMod = probeCoreAttached ? 1.0f : KCT_GameStates.settings.RecoveryModifier; KSCDistance = (float)SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(v.protoVessel.latitude, v.protoVessel.longitude)); double maxDist = SpaceCenter.Instance.cb.Radius * Math.PI; RecoveryPercent = RecoveryMod * Mathf.Lerp(0.98f, 0.1f, (float)(KSCDistance / maxDist)); float totalReturn = 0; foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots) { float dryCost, fuelCost; totalReturn += Math.Max(ShipConstruction.GetPartCosts(pps, pps.partInfo, out dryCost, out fuelCost), 0); } float totalBeforeModifier = totalReturn; totalReturn *= RecoveryPercent; FundsRecovered = totalReturn; KCTDebug.Log("Vessel being recovered by KCT. Percent returned: " + 100 * RecoveryPercent + "%. Distance from KSC: " + Math.Round(KSCDistance / 1000, 2) + " km"); KCTDebug.Log("Funds being returned: " + Math.Round(totalReturn, 2) + "/" + Math.Round(totalBeforeModifier, 2)); Message.AppendLine("Funds recovered: " + FundsRecovered + "(" + Math.Round(RecoveryPercent * 100, 1) + "%)"); KCT_Utilities.AddFunds(FundsRecovered); } } Message.AppendLine("\nAdditional information:"); Message.AppendLine("Distance from KSC: " + Math.Round(KSCDistance / 1000, 2) + " km"); if (!realChuteInUse) { Message.AppendLine("Stock module used. Terminal velocity (less than 10 needed): " + Math.Round(Vt, 2)); } else { Message.AppendLine("RealChute module used. Terminal velocity (less than 10 needed): " + Math.Round(Vt, 2)); } if (!(KCT_Utilities.StageRecoveryAddonActive || KCT_Utilities.DebRefundAddonActive) && (KCT_Utilities.CurrentGameIsCareer() || !KCT_GUI.PrimarilyDisabled) && !(KCT_GameStates.settings.DisableAllMessages || KCT_GameStates.settings.DisableRecoveryMessages)) { KCT_Utilities.DisplayMessage("Stage Recovered", Message, MessageSystemButton.MessageButtonColor.BLUE, MessageSystemButton.ButtonIcons.MESSAGE); } } } }