public ReconRollout(BuildListVessel vessel, RolloutReconType type, string id, string launchSite = "") { RRType = type; AssociatedID = id; LaunchPadID = string.IsNullOrEmpty(launchSite) ? vessel.LaunchSite : launchSite; //For when we add custom launchpads Progress = 0; BP = MathParser.ParseReconditioningFormula(vessel, true); //if (type != RolloutReconType.Reconditioning) //BP *= KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit; if (type == RolloutReconType.Reconditioning) { //BP *= (1 - KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit); } else if (type == RolloutReconType.Rollout) { Cost = MathParser.ParseRolloutCostFormula(vessel); } else if (type == RolloutReconType.Rollback) { Progress = BP; } else if (type == RolloutReconType.Recovery) { double maxDist = SpaceCenter.Instance.cb.Radius * Math.PI; BP += BP * (vessel.DistanceFromKSC / maxDist); } }
public static double CalculateBP(double cost) { var variables = new Dictionary <string, string>() { { "C", cost.ToString() }, { "O", PresetManager.Instance.ActivePreset.TimeSettings.OverallMultiplier.ToString() }, { "Adm", "0" }, { "AC", "0" }, { "LP", "1" }, { "MC", "0" }, { "RD", "0" }, { "RW", "0" }, { "TS", "0" }, { "SPH", "0" }, { "VAB", "0" }, { "Other", "0" } }; double bp = MathParser.GetStandardFormulaValue("KSCUpgrade", variables); if (bp <= 0) { bp = 1; } return(bp); }
public BuildListVessel CreateCopy(bool RecalcTime) { BuildListVessel ret = new BuildListVessel(ShipName, LaunchSite, EffectiveCost, BuildPoints, IntegrationPoints, Flag, Cost, IntegrationCost, (int)GetEditorFacility()) { ShipNode = ShipNode.CreateCopy() }; //refresh all inventory parts to new foreach (var p in ret.ExtractedPartNodes) { ScrapYardWrapper.RefreshPart(p); } ret.Id = Guid.NewGuid(); ret.KCTPersistentID = Guid.NewGuid().ToString(); ret.TotalMass = TotalMass; ret.EmptyMass = EmptyMass; ret.Cost = Cost; ret.IntegrationCost = IntegrationCost; ret.EmptyCost = EmptyCost; ret.NumStageParts = NumStageParts; ret.NumStages = NumStages; ret.StagePartCost = StagePartCost; ret.ShipSize = ShipSize; if (RecalcTime) { ret.EffectiveCost = Utilities.GetEffectiveCost(ret.ExtractedPartNodes); ret.BuildPoints = Utilities.GetBuildTime(ret.EffectiveCost); ret.IntegrationPoints = MathParser.ParseIntegrationTimeFormula(ret); ret.IntegrationCost = (float)MathParser.ParseIntegrationCostFormula(ret); } return(ret); }
public ReconRollout(Vessel vessel, RolloutReconType type, string id, string launchSite) { RRType = type; AssociatedID = id; LaunchPadID = launchSite; KCTDebug.Log("New recon_rollout at launchsite: " + LaunchPadID); Progress = 0; try { BP = MathParser.ParseReconditioningFormula(new BuildListVessel(vessel), true); } catch { KCTDebug.Log("Error while determining BP for recon_rollout"); } if (type == RolloutReconType.Rollback) { Progress = BP; } else if (type == RolloutReconType.Recovery) { double KSCDistance = (float)SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(vessel.latitude, vessel.longitude)); double maxDist = SpaceCenter.Instance.cb.Radius * Math.PI; BP += BP * (KSCDistance / maxDist); } }
public void VesselRecoverEvent(ProtoVessel v, bool unknownAsOfNow) { KCTDebug.Log("VesselRecoverEvent"); if (!PresetManager.Instance.ActivePreset.GeneralSettings.Enabled) { return; } if (!KCTGameStates.IsSimulatedFlight && !v.vesselRef.isEVA) { if (KCTGameStates.RecoveredVessel != null && v.vesselName == KCTGameStates.RecoveredVessel.ShipName) { //rebuy the ship if ScrapYard isn't overriding funds if (!ScrapYardWrapper.OverrideFunds) { Utilities.SpendFunds(KCTGameStates.RecoveredVessel.Cost, TransactionReasons.VesselRollout); //pay for the ship again } //pull all of the parts out of the inventory //This is a bit funky since we grab the part id from our part, grab the inventory part out, then try to reapply that ontop of our part if (ScrapYardWrapper.Available) { foreach (ConfigNode partNode in KCTGameStates.RecoveredVessel.ExtractedPartNodes) { string id = ScrapYardWrapper.GetPartID(partNode); ConfigNode inventoryVersion = ScrapYardWrapper.FindInventoryPart(id); if (inventoryVersion != null) { //apply it to our copy of the part ConfigNode ourTracker = partNode.GetNodes("MODULE").FirstOrDefault(n => string.Equals(n.GetValue("name"), "ModuleSYPartTracker", StringComparison.Ordinal)); if (ourTracker != null) { ourTracker.SetValue("TimesRecovered", inventoryVersion.GetValue("_timesRecovered")); ourTracker.SetValue("Inventoried", inventoryVersion.GetValue("_inventoried")); } } } //process the vessel in ScrapYard ScrapYardWrapper.ProcessVessel(KCTGameStates.RecoveredVessel.ExtractedPartNodes); //reset the BP KCTGameStates.RecoveredVessel.BuildPoints = Utilities.GetBuildTime(KCTGameStates.RecoveredVessel.ExtractedPartNodes); KCTGameStates.RecoveredVessel.IntegrationPoints = MathParser.ParseIntegrationTimeFormula(KCTGameStates.RecoveredVessel); } if (KCTGameStates.RecoveredVessel.Type == BuildListVessel.ListType.VAB) { KCTGameStates.ActiveKSC.VABWarehouse.Add(KCTGameStates.RecoveredVessel); } else { KCTGameStates.ActiveKSC.SPHWarehouse.Add(KCTGameStates.RecoveredVessel); } KCTGameStates.ActiveKSC.Recon_Rollout.Add(new ReconRollout(KCTGameStates.RecoveredVessel, ReconRollout.RolloutReconType.Recovery, KCTGameStates.RecoveredVessel.Id.ToString())); KCTGameStates.RecoveredVessel = null; } } }
/// <summary> /// For recovered vessels /// </summary> /// <param name="vessel"></param> /// <param name="listType"></param> public BuildListVessel(Vessel vessel, ListType listType = ListType.None) { Id = Guid.NewGuid(); KCTPersistentID = Guid.NewGuid().ToString(); ShipName = vessel.vesselName; ShipNode = FromInFlightVessel(vessel, listType); if (listType != ListType.None) { Type = listType; } Cost = Utilities.GetTotalVesselCost(ShipNode); EmptyCost = Utilities.GetTotalVesselCost(ShipNode, false); TotalMass = 0; EmptyMass = 0; HashSet <int> stages = new HashSet <int>(); foreach (ProtoPartSnapshot p in vessel.protoVessel.protoPartSnapshots) { stages.Add(p.inverseStageIndex); if (p.partPrefab != null) { if (p.partPrefab.Modules.Contains <LaunchClamp>() || p.partPrefab.HasTag("PadInfrastructure")) { continue; } } TotalMass += p.mass; EmptyMass += p.mass; foreach (ProtoPartResourceSnapshot rsc in p.resources) { PartResourceDefinition def = PartResourceLibrary.Instance.GetDefinition(rsc.resourceName); if (def != null) { TotalMass += def.density * (float)rsc.amount; } } } CannotEarnScience = true; NumStages = stages.Count; // FIXME ignore stageable part count and cost - it'll be fixed when we put this back in the editor. EffectiveCost = Utilities.GetEffectiveCost(ShipNode.GetNodes("PART").ToList()); BuildPoints = Utilities.GetBuildTime(EffectiveCost); Flag = HighLogic.CurrentGame.flagURL; DistanceFromKSC = (float)SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(vessel.latitude, vessel.longitude)); RushBuildClicks = 0; IntegrationPoints = MathParser.ParseIntegrationTimeFormula(this); IntegrationCost = (float)MathParser.ParseIntegrationCostFormula(this); Progress = BuildPoints + IntegrationPoints; }
public AirlaunchPrep(BuildListVessel vessel, string id) { Direction = PrepDirection.Mount; AssociatedID = id; Progress = 0; BP = MathParser.ParseAirlaunchTimeFormula(vessel); Cost = MathParser.ParseAirlaunchCostFormula(vessel); }
public double GetRushCost() { if (_rushCost > -1) { return(_rushCost); } _rushCost = MathParser.ParseRushCostFormula(this); return(_rushCost); }
private static void RenderPointResetSection() { //TODO: Calculate the cost of resetting int ResetCost = (int)MathParser.GetStandardFormulaValue("UpgradeReset", new Dictionary <string, string> { { "N", KCTGameStates.UpgradesResetCounter.ToString() } }); if (ResetCost >= 0) { GUILayout.BeginHorizontal(); GUILayout.Label("Reset Upgrades: "); bool canAfford = AvailablePoints >= ResetCost; var style = canAfford ? GUI.skin.button : GetCannotAffordStyle(); if (GUILayout.Button($"{ResetCost} Points", style, GUILayout.ExpandWidth(false))) { if (SpentPoints > 0 && canAfford) //you have to spend some points before resetting does anything { KCTGameStates.ActiveKSC.VABUpgrades = new List <int>() { 0 }; KCTGameStates.ActiveKSC.SPHUpgrades = new List <int>() { 0 }; KCTGameStates.ActiveKSC.RDUpgrades = new List <int>() { 0, 0 }; KCTGameStates.TechUpgradesTotal = 0; foreach (KSCItem ksc in KCTGameStates.KSCs) { ksc.RDUpgrades[1] = 0; } _nodeRate = int.MinValue; _upNodeRate = int.MinValue; _researchRate = int.MinValue; _upResearchRate = int.MinValue; KCTGameStates.ActiveKSC.RecalculateBuildRates(); KCTGameStates.ActiveKSC.RecalculateUpgradedBuildRates(); foreach (TechItem tech in KCTGameStates.TechList) { tech.UpdateBuildRate(KCTGameStates.TechList.IndexOf(tech)); } KCTGameStates.UpgradesResetCounter++; } } GUI.enabled = true; GUILayout.EndHorizontal(); } }
public double UpdateBuildRate(int index) { double rate = MathParser.ParseNodeRateFormula(ScienceCost, index); if (rate < 0) { rate = 0; } _buildRate = rate; return(_buildRate); }
public double GetTotalCost() { if (Cost == 0 || EmptyCost == 0) { Cost = Utilities.GetTotalVesselCost(ShipNode); EmptyCost = Utilities.GetTotalVesselCost(ShipNode, false); IntegrationCost = (float)MathParser.ParseIntegrationCostFormula(this); } return(Cost + IntegrationCost); }
public void RecalculateBuildRates() { VABRates.Clear(); SPHRates.Clear(); double rate = 0.1; int index = 0; // These loops could clean up a little, is it intended to add a rate=0 in the loop as the last entry? while (rate > 0) { rate = MathParser.ParseBuildRateFormula(BuildListVessel.ListType.VAB, index, this); if (rate >= 0) { VABRates.Add(rate); } index++; } rate = 0.1; index = 0; while (rate > 0) { rate = MathParser.ParseBuildRateFormula(BuildListVessel.ListType.SPH, index, this); if (rate >= 0) { SPHRates.Add(rate); } index++; } var m = StringBuilderCache.Acquire(); m.AppendLine("VAB Rates:"); foreach (double v in VABRates) { m.AppendLine($"{v}"); } m.AppendLine("SPH Rates:"); foreach (double v in SPHRates) { m.AppendLine($"{v}"); } KCTDebug.Log(m.ToStringAndRelease()); }
public double UpdateBuildRate(int index) { ForceRecalculateYearBasedRateMult(); double rate = MathParser.ParseNodeRateFormula(ScienceCost, index); if (rate < 0) { rate = 0; } if (rate != 0) { rate *= YearBasedRateMult; } _buildRate = rate; return(_buildRate); }
public ReconRollout(BuildListVessel vessel, RolloutReconType type, string id, string launchSite = "") { RRType = type; AssociatedID = id; if (launchSite != "") //For when we add custom launchpads { LaunchPadID = launchSite; } else { LaunchPadID = vessel.LaunchSite; } Progress = 0; if (type == RolloutReconType.Reconditioning) { BP = MathParser.ParseReconditioningFormula(vessel, true); //BP *= (1 - KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit); Name = "LaunchPad Reconditioning"; } else if (type == RolloutReconType.Rollout) { BP = MathParser.ParseReconditioningFormula(vessel, false); //BP *= KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit; Name = "Vessel Rollout"; Cost = MathParser.ParseRolloutCostFormula(vessel); } else if (type == RolloutReconType.Rollback) { BP = MathParser.ParseReconditioningFormula(vessel, false); //BP *= KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit; Progress = BP; Name = "Vessel Rollback"; } else if (type == RolloutReconType.Recovery) { BP = MathParser.ParseReconditioningFormula(vessel, false); //BP *= KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit; Name = "Vessel Recovery"; double maxDist = SpaceCenter.Instance.cb.Radius * Math.PI; BP += BP * (vessel.DistanceFromKSC / maxDist); } }
public void RecalculateBuildRates() { VABRates.Clear(); SPHRates.Clear(); double rate = 0.1; int index = 0; while (rate > 0) { rate = MathParser.ParseBuildRateFormula(BuildListVessel.ListType.VAB, index, this); if (rate >= 0) { VABRates.Add(rate); } index++; } rate = 0.1; index = 0; while (rate > 0) { rate = MathParser.ParseBuildRateFormula(BuildListVessel.ListType.SPH, index, this); if (rate >= 0) { SPHRates.Add(rate); } index++; } KCTDebug.Log("VAB Rates:"); foreach (double v in VABRates) { KCTDebug.Log(v); } KCTDebug.Log("SPH Rates:"); foreach (double v in SPHRates) { KCTDebug.Log(v); } }
private static double CalcPointCost(ref int pointDelta, double maxCost, string formulaName, int gameStateIndex) { int purchasedUpgrades = KCTGameStates.PurchasedUpgrades[gameStateIndex]; var variables = new Dictionary <string, string> { { "N", purchasedUpgrades.ToString() } }; double cumulativeCost = 0; double nextCost = MathParser.GetStandardFormulaValue(formulaName, variables); if (nextCost < 0) { return(-1); } if (pointDelta < 0) { pointDelta = 0; do { pointDelta++; cumulativeCost += nextCost; variables["N"] = (purchasedUpgrades + pointDelta).ToString(); nextCost = MathParser.GetStandardFormulaValue(formulaName, variables); }while (cumulativeCost + nextCost <= maxCost); } else { for (int i = 0; i < pointDelta; i++) { variables["N"] = (purchasedUpgrades + i).ToString(); cumulativeCost += MathParser.GetStandardFormulaValue(formulaName, variables); } } return(cumulativeCost); }
public void RecalculateUpgradedBuildRates() { UpVABRates.Clear(); UpSPHRates.Clear(); double rate = 0.1; int index = 0; while (rate > 0) { rate = MathParser.ParseBuildRateFormula(BuildListVessel.ListType.VAB, index, this, true); if (rate >= 0 && (index == 0 || VABRates[index - 1] > 0)) { UpVABRates.Add(rate); } else { break; } index++; } rate = 0.1; index = 0; while (rate > 0) { rate = MathParser.ParseBuildRateFormula(BuildListVessel.ListType.SPH, index, this, true); if (rate >= 0 && (index == 0 || SPHRates[index - 1] > 0)) { UpSPHRates.Add(rate); } else { break; } index++; } }
public static double CalculateBP(double cost, SpaceCenterFacility?facilityType) { int isAdm = 0, isAC = 0, isLP = 0, isMC = 0, isRD = 0, isRW = 0, isTS = 0, isSPH = 0, isVAB = 0, isOther = 0; switch (facilityType) { case SpaceCenterFacility.Administration: isAdm = 1; break; case SpaceCenterFacility.AstronautComplex: isAC = 1; break; case SpaceCenterFacility.LaunchPad: isLP = 1; break; case SpaceCenterFacility.MissionControl: isMC = 1; break; case SpaceCenterFacility.ResearchAndDevelopment: isRD = 1; break; case SpaceCenterFacility.Runway: isRW = 1; break; case SpaceCenterFacility.TrackingStation: isTS = 1; break; case SpaceCenterFacility.SpaceplaneHangar: isSPH = 1; break; case SpaceCenterFacility.VehicleAssemblyBuilding: isVAB = 1; break; default: isOther = 1; break; } var variables = new Dictionary <string, string>() { { "C", cost.ToString() }, { "O", PresetManager.Instance.ActivePreset.TimeSettings.OverallMultiplier.ToString() }, { "Adm", isAdm.ToString() }, { "AC", isAC.ToString() }, { "LP", isLP.ToString() }, { "MC", isMC.ToString() }, { "RD", isRD.ToString() }, { "RW", isRW.ToString() }, { "TS", isTS.ToString() }, { "SPH", isSPH.ToString() }, { "VAB", isVAB.ToString() }, { "Other", isOther.ToString() } }; double bp = MathParser.GetStandardFormulaValue("KSCUpgrade", variables); if (bp <= 0) { bp = 1; } return(bp); }
private static void RenderRnDSection(bool isCostCacheInvalid, KSCItem KSC) { if (Config == null) { Config = new LRTRHomeWorldParameters(); foreach (ConfigNode stg in GameDatabase.Instance.GetConfigNodes("HOMEWORLDPARAMETERS")) { Config.Load(stg); } } double secondsPerDay = Config.hoursPerDay * 3600; int labelDelta = _buyModifier < 0 ? AvailablePoints : _buyModifier; GUILayout.BeginHorizontal(); GUILayout.Label("R&D Upgrades"); GUILayout.Label($"+{labelDelta} Point{(labelDelta == 1 ? "" : "s")}", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (_researchRate == int.MinValue || isCostCacheInvalid) { _researchDelta = _buyModifier < 0 ? AvailablePoints : _buyModifier; var variables = new Dictionary <string, string>() { { "N", KSC.RDUpgrades[0].ToString() }, { "R", Utilities.GetBuildingUpgradeLevel(SpaceCenterFacility.ResearchAndDevelopment).ToString() } }; MathParser.AddCrewVariables(variables); _researchRate = MathParser.GetStandardFormulaValue("Research", variables); variables["N"] = (KSC.RDUpgrades[0] + _researchDelta).ToString(); _upResearchRate = MathParser.GetStandardFormulaValue("Research", variables); } if (_researchRate >= 0) { GUILayout.BeginHorizontal(); GUILayout.Label("Research"); GUILayout.Label($"{Math.Round(_researchRate * secondsPerDay, 2)} sci/{secondsPerDay} BP"); if (AvailablePoints > 0) { bool canAfford = AvailablePoints >= _researchDelta; GUIStyle style = canAfford ? GUI.skin.button : GetCannotAffordStyle(); if (GUILayout.Button($"+{Math.Round((_upResearchRate - _researchRate) * secondsPerDay, 2)}", style, GUILayout.Width(45)) && canAfford) { KSC.RDUpgrades[0] += _researchDelta; _researchRate = int.MinValue; _fundsCost = _spentPoints = _totalPoints = int.MinValue; } } GUILayout.EndHorizontal(); } double days = GameSettings.KERBIN_TIME ? 4 : 1; if (_nodeRate == int.MinValue || isCostCacheInvalid) { _nodeDelta = _buyModifier < 0 ? AvailablePoints : _buyModifier; _nodeRate = MathParser.ParseNodeRateFormula(0); _upNodeRate = MathParser.ParseNodeRateFormula(0, 0, _nodeDelta); } double sci = secondsPerDay * _nodeRate; double sciPerDay = sci / days; GUILayout.BeginHorizontal(); GUILayout.Label("Rate"); bool usingPerYear = false; if (sciPerDay > 0.1) { GUILayout.Label(Math.Round(sciPerDay * 1000) / 1000 + " sci/day"); } else { //Well, looks like we need sci/year instead GUILayout.Label(Math.Round(sciPerDay * Config.daysPerYear * 1000) / 1000 + " sci/yr"); usingPerYear = true; } if (_upNodeRate != _nodeRate && AvailablePoints > 0) { bool everyKSCCanUpgrade = true; foreach (KSCItem ksc in KCTGameStates.KSCs) { if (TotalPoints - Utilities.GetTotalSpentUpgrades(ksc) <= 0) { everyKSCCanUpgrade = false; break; } } if (everyKSCCanUpgrade) { double upSciPerDay = secondsPerDay * _upNodeRate / days; string buttonText = $"{Math.Round(1000 * upSciPerDay) / 1000} sci/day"; if (usingPerYear) { buttonText = $"{Math.Round(upSciPerDay * Config.daysPerYear * 1000) / 1000} sci/yr"; } bool canAfford = AvailablePoints >= _nodeDelta; GUIStyle style = canAfford ? GUI.skin.button : GetCannotAffordStyle(); if (GUILayout.Button(buttonText, style, GUILayout.ExpandWidth(false)) && canAfford) { KCTGameStates.TechUpgradesTotal += _nodeDelta; foreach (KSCItem ksc in KCTGameStates.KSCs) { ksc.RDUpgrades[1] = KCTGameStates.TechUpgradesTotal; } _nodeRate = _upNodeRate = int.MinValue; _fundsCost = _spentPoints = _totalPoints = int.MinValue; foreach (TechItem tech in KCTGameStates.TechList) { tech.UpdateBuildRate(KCTGameStates.TechList.IndexOf(tech)); } } } } GUILayout.EndHorizontal(); }
private static void RenderEditMode() { BuildListVessel ship = KCTGameStates.EditedVessel; if (_finishedShipBP < 0 && ship.IsFinished) { // If ship is finished, then both build and integration times can be refreshed with newly calculated values _finishedShipBP = Utilities.GetBuildTime(ship.ExtractedPartNodes); ship.BuildPoints = _finishedShipBP; ship.IntegrationPoints = MathParser.ParseIntegrationTimeFormula(ship); } Utilities.GetShipEditProgress(ship, out double newProgressBP, out double originalCompletionPercent, out double newCompletionPercent); GUILayout.Label($"Original: {Math.Max(0, Math.Round(100 * originalCompletionPercent, 2))}%"); GUILayout.Label($"Edited: {Math.Round(100 * newCompletionPercent, 2)}%"); BuildListVessel.ListType type = EditorLogic.fetch.launchSiteName == "LaunchPad" ? BuildListVessel.ListType.VAB : BuildListVessel.ListType.SPH; GUILayout.BeginHorizontal(); GUILayout.Label("Build Time at "); if (BuildRateForDisplay == null) { BuildRateForDisplay = Utilities.GetBuildRate(0, type, null).ToString(); } BuildRateForDisplay = GUILayout.TextField(BuildRateForDisplay, GUILayout.Width(75)); GUILayout.Label(" BP/s:"); List <double> rates = new List <double>(); if (ship.Type == BuildListVessel.ListType.VAB) { rates = Utilities.GetVABBuildRates(null); } else { rates = Utilities.GetSPHBuildRates(null); } if (double.TryParse(BuildRateForDisplay, out double bR)) { if (GUILayout.Button(new GUIContent("*", "Switch build line that is used for build time calculations"), GUILayout.ExpandWidth(false))) { _rateIndexHolder = (_rateIndexHolder + 1) % rates.Count; bR = rates[_rateIndexHolder]; BuildRateForDisplay = bR.ToString(); } GUILayout.EndHorizontal(); GUILayout.Label(MagiCore.Utilities.GetFormattedTime(Math.Abs(KCTGameStates.EditorBuildTime + KCTGameStates.EditorIntegrationTime - newProgressBP) / bR)); } else { GUILayout.EndHorizontal(); GUILayout.Label("Invalid Build Rate"); } GUILayout.BeginHorizontal(); if (GUILayout.Button("Save Edits")) { _finishedShipBP = -1; Utilities.SaveShipEdits(ship); } if (GUILayout.Button("Cancel Edits")) { KCTDebug.Log("Edits cancelled."); _finishedShipBP = -1; ScrapYardWrapper.ProcessVessel(KCTGameStates.EditedVessel.ExtractedPartNodes); KCTGameStates.ClearVesselEditMode(); HighLogic.LoadScene(GameScenes.SPACECENTER); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Simulate")) { _finishedShipBP = -1; _simulationConfigPosition.height = 1; EditorLogic.fetch.Lock(true, true, true, "KCTGUILock"); GUIStates.ShowSimConfig = true; double effCost = Utilities.GetEffectiveCost(EditorLogic.fetch.ship.Parts); double bp = Utilities.GetBuildTime(effCost); KCTGameStates.LaunchedVessel = new BuildListVessel(EditorLogic.fetch.ship, EditorLogic.fetch.launchSiteName, effCost, bp, EditorLogic.FlagURL); } GUILayout.EndHorizontal(); if (KCTGameStates.LaunchedVessel != null && !KCTGameStates.LaunchedVessel.AreTanksFull() && GUILayout.Button("Fill Tanks")) { foreach (Part p in EditorLogic.fetch.ship.parts) { //fill as part prefab would be filled? if (Utilities.PartIsProcedural(p)) { foreach (PartResource rsc in p.Resources) { if (GuiDataAndWhitelistItemsDatabase.ValidFuelRes.Contains(rsc.resourceName) && rsc.flowState) { rsc.amount = rsc.maxAmount; } } } else { foreach (PartResource rsc in p.Resources) { if (GuiDataAndWhitelistItemsDatabase.ValidFuelRes.Contains(rsc.resourceName) && rsc.flowState) { PartResource templateRsc = p.partInfo.partPrefab.Resources.FirstOrDefault(r => r.resourceName == rsc.resourceName); if (templateRsc != null) { rsc.amount = templateRsc.amount; } } } } } } RenderMergeSection(ship); }
private static void RenderEditMode() { BuildListVessel ship = KCTGameStates.EditedVessel; if (_finishedShipBP < 0 && ship.IsFinished) { // If ship is finished, then both build and integration times can be refreshed with newly calculated values _finishedShipBP = Utilities.GetBuildTime(ship.ExtractedPartNodes); ship.BuildPoints = _finishedShipBP; ship.IntegrationPoints = MathParser.ParseIntegrationTimeFormula(ship); } double origBP = ship.IsFinished ? _finishedShipBP : ship.BuildPoints; origBP += ship.IntegrationPoints; double buildTime = KCTGameStates.EditorBuildTime + KCTGameStates.EditorIntegrationTime; double difference = Math.Abs(buildTime - origBP); double progress; if (ship.IsFinished) { progress = origBP; } else { progress = ship.Progress; } double newProgress = Math.Max(0, progress - (1.1 * difference)); GUILayout.Label($"Original: {Math.Max(0, Math.Round(100 * (progress / origBP), 2))}%"); GUILayout.Label($"Edited: {Math.Round(100 * newProgress / buildTime, 2)}%"); BuildListVessel.ListType type = EditorLogic.fetch.launchSiteName == "LaunchPad" ? BuildListVessel.ListType.VAB : BuildListVessel.ListType.SPH; GUILayout.BeginHorizontal(); GUILayout.Label("Build Time at "); if (BuildRateForDisplay == null) { BuildRateForDisplay = Utilities.GetBuildRate(0, type, null).ToString(); } BuildRateForDisplay = GUILayout.TextField(BuildRateForDisplay, GUILayout.Width(75)); GUILayout.Label(" BP/s:"); List <double> rates = new List <double>(); if (ship.Type == BuildListVessel.ListType.VAB) { rates = Utilities.GetVABBuildRates(null); } else { rates = Utilities.GetSPHBuildRates(null); } if (double.TryParse(BuildRateForDisplay, out double bR)) { if (GUILayout.Button("*", GUILayout.ExpandWidth(false))) { _rateIndexHolder = (_rateIndexHolder + 1) % rates.Count; bR = rates[_rateIndexHolder]; BuildRateForDisplay = bR.ToString(); } GUILayout.EndHorizontal(); GUILayout.Label(MagiCore.Utilities.GetFormattedTime(Math.Abs(buildTime - newProgress) / bR)); } else { GUILayout.EndHorizontal(); GUILayout.Label("Invalid Build Rate"); } GUILayout.BeginHorizontal(); if (GUILayout.Button("Save Edits")) { _finishedShipBP = -1; Utilities.AddFunds(ship.GetTotalCost(), TransactionReasons.VesselRollout); BuildListVessel newShip = Utilities.AddVesselToBuildList(); if (newShip == null) { Utilities.SpendFunds(ship.GetTotalCost(), TransactionReasons.VesselRollout); return; } ship.RemoveFromBuildList(); newShip.Progress = newProgress; newShip.RushBuildClicks = ship.RushBuildClicks; KCTDebug.Log($"Finished? {ship.IsFinished}"); if (ship.IsFinished) { newShip.CannotEarnScience = true; } GamePersistence.SaveGame("persistent", HighLogic.SaveFolder, SaveMode.OVERWRITE); KCTGameStates.EditorShipEditingMode = false; InputLockManager.RemoveControlLock("KCTEditExit"); InputLockManager.RemoveControlLock("KCTEditLoad"); InputLockManager.RemoveControlLock("KCTEditNew"); InputLockManager.RemoveControlLock("KCTEditLaunch"); EditorLogic.fetch.Unlock("KCTEditorMouseLock"); KCTDebug.Log("Edits saved."); HighLogic.LoadScene(GameScenes.SPACECENTER); } if (GUILayout.Button("Cancel Edits")) { KCTDebug.Log("Edits cancelled."); _finishedShipBP = -1; KCTGameStates.EditorShipEditingMode = false; InputLockManager.RemoveControlLock("KCTEditExit"); InputLockManager.RemoveControlLock("KCTEditLoad"); InputLockManager.RemoveControlLock("KCTEditNew"); InputLockManager.RemoveControlLock("KCTEditLaunch"); EditorLogic.fetch.Unlock("KCTEditorMouseLock"); ScrapYardWrapper.ProcessVessel(KCTGameStates.EditedVessel.ExtractedPartNodes); HighLogic.LoadScene(GameScenes.SPACECENTER); } GUILayout.EndHorizontal(); if (KCTGameStates.LaunchedVessel != null && !KCTGameStates.LaunchedVessel.AreTanksFull() && GUILayout.Button("Fill Tanks")) { foreach (Part p in EditorLogic.fetch.ship.parts) { //fill as part prefab would be filled? if (Utilities.PartIsProcedural(p)) { foreach (PartResource rsc in p.Resources) { if (GuiDataAndWhitelistItemsDatabase.ValidFuelRes.Contains(rsc.resourceName) && rsc.flowState) { rsc.amount = rsc.maxAmount; } } } else { foreach (PartResource rsc in p.Resources) { if (GuiDataAndWhitelistItemsDatabase.ValidFuelRes.Contains(rsc.resourceName) && rsc.flowState) { PartResource templateRsc = p.partInfo.partPrefab.Resources.FirstOrDefault(r => r.resourceName == rsc.resourceName); if (templateRsc != null) { rsc.amount = templateRsc.amount; } } } } } } }
public BuildListVessel(ShipConstruct s, string ls, double effCost, double bP, string flagURL) { _ship = s; ShipNode = s.SaveShip(); // Override KSP sizing of the ship construct ShipSize = Utilities.GetShipSize(s, true); ShipNode.SetValue("size", KSPUtil.WriteVector(ShipSize)); ShipName = s.shipName; Cost = Utilities.GetTotalVesselCost(ShipNode, true); EmptyCost = Utilities.GetTotalVesselCost(ShipNode, false); TotalMass = Utilities.GetShipMass(s, true, out EmptyMass, out _); HashSet <int> stages = new HashSet <int>(); NumStageParts = 0; StagePartCost = 0d; foreach (Part p in s.Parts) { if (p.stagingOn) { stages.Add(p.inverseStage); ++NumStageParts; StagePartCost += p.GetModuleCosts(p.partInfo.cost, ModifierStagingSituation.CURRENT) + p.partInfo.cost; } } NumStages = stages.Count; LaunchSite = ls; EffectiveCost = effCost; BuildPoints = bP; Progress = 0; Flag = flagURL; if (s.shipFacility == EditorFacility.VAB) { Type = ListType.VAB; FacilityBuiltIn = EditorFacility.VAB; } else if (s.shipFacility == EditorFacility.SPH) { Type = ListType.SPH; FacilityBuiltIn = EditorFacility.SPH; } else { Type = ListType.None; } Id = Guid.NewGuid(); KCTPersistentID = Guid.NewGuid().ToString(); CannotEarnScience = false; //get the crew from the editorlogic DesiredManifest = new List <string>(); if (CrewAssignmentDialog.Instance?.GetManifest()?.CrewCount > 0) { foreach (ProtoCrewMember crew in CrewAssignmentDialog.Instance.GetManifest().GetAllCrew(true) ?? new List <ProtoCrewMember>()) { DesiredManifest.Add(crew?.name ?? string.Empty); } } if (EffectiveCost == default) { // Can only happen in older saves that didn't have Effective cost persisted as a separate field // This code should be safe to remove after a while. EffectiveCost = Utilities.GetEffectiveCost(ShipNode.GetNodes("PART").ToList()); } IntegrationPoints = MathParser.ParseIntegrationTimeFormula(this); IntegrationCost = (float)MathParser.ParseIntegrationCostFormula(this); }