Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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;
                }
            }
        }
Esempio n. 3
0
        /// <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;
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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;
                                }
                            }
                        }
                    }
                }
            }
        }