From abe8381426f16aff41bfbe1dad33d6d4825cef51 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Wed, 9 Aug 2017 22:10:25 -0700 Subject: [PATCH 01/12] Fake-unlock all currently-being-researched tech nodes when entering R&D so you don't have to every time (and so you aren't limited if you can't afford to 're' unlock them). --- Kerbal_Construction_Time/KCT_Events.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Kerbal_Construction_Time/KCT_Events.cs b/Kerbal_Construction_Time/KCT_Events.cs index 0a0da1e..4a4d718 100644 --- a/Kerbal_Construction_Time/KCT_Events.cs +++ b/Kerbal_Construction_Time/KCT_Events.cs @@ -37,6 +37,7 @@ public void addEvents() GameEvents.onEditorShipModified.Add(ShipModifiedEvent); GameEvents.OnPartPurchased.Add(PartPurchasedEvent); //GameEvents.OnVesselRecoveryRequested.Add(RecoveryRequested); + GameEvents.onGUIRnDComplexSpawn.Add(TechEnableEvent); GameEvents.onGUIRnDComplexDespawn.Add(TechDisableEvent); GameEvents.OnKSCFacilityUpgraded.Add(FacilityUpgradedEvent); GameEvents.onGameStateLoad.Add(PersistenceLoadEvent); @@ -391,6 +392,15 @@ public void TechDisableEvent() TechDisableEventFinal(true); } + public void TechEnableEvent() + { + if (KCT_PresetManager.Instance.ActivePreset.generalSettings.TechUnlockTimes && KCT_PresetManager.Instance.ActivePreset.generalSettings.BuildTimes) + { + foreach (KCT_TechItem techItem in KCT_GameStates.TechList) + techItem.EnableTech(); + } + } + public void TechDisableEventFinal(bool save=false) { if (KCT_PresetManager.Instance != null && KCT_PresetManager.Instance.ActivePreset != null) From 4416a122deb1007dc166eef86840b387a6b5cf81 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Wed, 9 Aug 2017 23:19:34 -0700 Subject: [PATCH 02/12] Support external checking of crew availability per part --- Kerbal_Construction_Time/KCT_GUI.cs | 120 ++++++++++++++++++---------- 1 file changed, 79 insertions(+), 41 deletions(-) diff --git a/Kerbal_Construction_Time/KCT_GUI.cs b/Kerbal_Construction_Time/KCT_GUI.cs index 860c542..c6a6458 100644 --- a/Kerbal_Construction_Time/KCT_GUI.cs +++ b/Kerbal_Construction_Time/KCT_GUI.cs @@ -43,6 +43,10 @@ public static partial class KCT_GUI private static bool isKSCLocked = false, isEditorLocked = false; + public delegate bool boolDelegatePCMString(ProtoCrewMember pcm, string partName); + public static boolDelegatePCMString AvailabilityChecker; + public static bool UseAvailabilityChecker = false; + private static List validScenes = new List { GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER, GameScenes.TRACKSTATION }; public static void SetGUIPositions() @@ -895,10 +899,10 @@ public static void AssignInitialCrew() foreach (PseudoPart pp in pseudoParts) KCT_GameStates.launchedCrew.Add(new CrewedPart(pp.uid, new List())); //try to assign kerbals from the desired manifest - if (KCT_GameStates.launchedVessel.DesiredManifest?.Count > 0 && KCT_GameStates.launchedVessel.DesiredManifest.Exists(c => c != null)) + if (!UseAvailabilityChecker && KCT_GameStates.launchedVessel.DesiredManifest?.Count > 0 && KCT_GameStates.launchedVessel.DesiredManifest.Exists(c => c != null)) { KCTDebug.Log("Assigning desired crew manifest."); - List available = GetAvailableCrew(); + List available = GetAvailableCrew(string.Empty); Queue finalCrew = new Queue(); //try to assign crew from the desired manifest foreach (string name in KCT_GameStates.launchedVessel.DesiredManifest) @@ -953,6 +957,7 @@ public static void AssignInitialCrew() private static List parts; public static bool randomCrew, autoHire; public static List AvailableCrew; + public static List PossibleCrewForPart = new List(); public static void DrawShipRoster(int windowID) { System.Random rand = new System.Random(); @@ -964,7 +969,7 @@ public static void DrawShipRoster(int windowID) GUILayout.BeginHorizontal(); if (AvailableCrew == null) { - AvailableCrew = GetAvailableCrew(); + AvailableCrew = GetAvailableCrew(string.Empty); } @@ -976,20 +981,32 @@ public static void DrawShipRoster(int windowID) Part p = parts[j];//KCT_Utilities.GetAvailablePartByName(KCT_GameStates.launchedVessel.GetPartNames()[j]).partPrefab; if (p.CrewCapacity > 0) { + if (UseAvailabilityChecker) + { + PossibleCrewForPart.Clear(); + foreach (ProtoCrewMember pcm in AvailableCrew) + if (AvailabilityChecker(pcm, p.partInfo.name)) + PossibleCrewForPart.Add(pcm); + } + else + PossibleCrewForPart = AvailableCrew; + //if (!KCT_GameStates.launchedCrew.Keys.Contains(p.uid)) //KCT_GameStates.launchedCrew.Add(new List()); for (int i = 0; i < p.CrewCapacity; i++) { if (KCT_GameStates.launchedCrew[j].crewList.Count <= i) { - if (AvailableCrew.Count > 0) + if (PossibleCrewForPart.Count > 0) { - int index = randomCrew ? new System.Random().Next(AvailableCrew.Count) : 0; - ProtoCrewMember crewMember = AvailableCrew[index]; + int index = randomCrew ? new System.Random().Next(PossibleCrewForPart.Count) : 0; + ProtoCrewMember crewMember = PossibleCrewForPart[index]; if (crewMember != null) { KCT_GameStates.launchedCrew[j].crewList.Add(crewMember); - AvailableCrew.RemoveAt(index); + PossibleCrewForPart.RemoveAt(index); + if (PossibleCrewForPart != AvailableCrew) + AvailableCrew.Remove(crewMember); } } else if (autoHire) @@ -1020,14 +1037,16 @@ public static void DrawShipRoster(int windowID) } else if (KCT_GameStates.launchedCrew[j].crewList[i] == null) { - if (AvailableCrew.Count > 0) + if (PossibleCrewForPart.Count > 0) { - int index = randomCrew ? new System.Random().Next(AvailableCrew.Count) : 0; - ProtoCrewMember crewMember = AvailableCrew[index]; + int index = randomCrew ? new System.Random().Next(PossibleCrewForPart.Count) : 0; + ProtoCrewMember crewMember = PossibleCrewForPart[index]; if (crewMember != null) { KCT_GameStates.launchedCrew[j].crewList[i] = crewMember; - AvailableCrew.RemoveAt(index); + PossibleCrewForPart.RemoveAt(index); + if (PossibleCrewForPart != AvailableCrew) + AvailableCrew.Remove(crewMember); } } else if (autoHire) @@ -1066,7 +1085,8 @@ public static void DrawShipRoster(int windowID) { cP.crewList.Clear(); } - AvailableCrew = GetAvailableCrew(); + PossibleCrewForPart.Clear(); + AvailableCrew = GetAvailableCrew(string.Empty); } GUILayout.EndHorizontal(); int numberItems = 0; @@ -1085,6 +1105,16 @@ public static void DrawShipRoster(int windowID) Part p = parts[j]; if (p.CrewCapacity > 0) { + if (UseAvailabilityChecker) + { + PossibleCrewForPart.Clear(); + foreach (ProtoCrewMember pcm in AvailableCrew) + if (AvailabilityChecker(pcm, p.partInfo.name)) + PossibleCrewForPart.Add(pcm); + } + else + PossibleCrewForPart = AvailableCrew; + GUILayout.BeginHorizontal(); GUILayout.Label(p.partInfo.title.Length <= 25 ? p.partInfo.title : p.partInfo.title.Substring(0, 25)); if (GUILayout.Button("Fill", GUILayout.Width(75))) @@ -1095,14 +1125,16 @@ public static void DrawShipRoster(int windowID) { if (KCT_GameStates.launchedCrew[j].crewList.Count <= i) { - if (AvailableCrew.Count > 0) + if (PossibleCrewForPart.Count > 0) { - int index = randomCrew ? new System.Random().Next(AvailableCrew.Count) : 0; - ProtoCrewMember crewMember = AvailableCrew[index]; + int index = randomCrew ? new System.Random().Next(PossibleCrewForPart.Count) : 0; + ProtoCrewMember crewMember = PossibleCrewForPart[index]; if (crewMember != null) { KCT_GameStates.launchedCrew[j].crewList.Add(crewMember); - AvailableCrew.RemoveAt(index); + PossibleCrewForPart.RemoveAt(index); + if (PossibleCrewForPart != AvailableCrew) + AvailableCrew.Remove(crewMember); } } else if (autoHire) @@ -1133,11 +1165,13 @@ public static void DrawShipRoster(int windowID) } else if (KCT_GameStates.launchedCrew[j].crewList[i] == null) { - if (AvailableCrew.Count > 0) + if (PossibleCrewForPart.Count > 0) { - int index = randomCrew ? new System.Random().Next(AvailableCrew.Count) : 0; - KCT_GameStates.launchedCrew[j].crewList[i] = AvailableCrew[index]; - AvailableCrew.RemoveAt(index); + int index = randomCrew ? new System.Random().Next(PossibleCrewForPart.Count) : 0; + KCT_GameStates.launchedCrew[j].crewList[i] = PossibleCrewForPart[index]; + if (PossibleCrewForPart != AvailableCrew) + AvailableCrew.Remove(PossibleCrewForPart[index]); + PossibleCrewForPart.RemoveAt(index); } else if (autoHire) { @@ -1170,7 +1204,8 @@ public static void DrawShipRoster(int windowID) if (GUILayout.Button("Clear", GUILayout.Width(75))) { KCT_GameStates.launchedCrew[j].crewList.Clear(); - AvailableCrew = GetAvailableCrew(); + PossibleCrewForPart.Clear(); + AvailableCrew = GetAvailableCrew(string.Empty); } GUILayout.EndHorizontal(); for (int i = 0; i < p.CrewCapacity; i++) @@ -1185,14 +1220,14 @@ public static void DrawShipRoster(int windowID) KCT_GameStates.launchedCrew[j].crewList[i].rosterStatus = ProtoCrewMember.RosterStatus.Available; //KCT_GameStates.launchedCrew[j].RemoveAt(i); KCT_GameStates.launchedCrew[j].crewList[i] = null; - AvailableCrew = GetAvailableCrew(); + AvailableCrew = GetAvailableCrew(string.Empty); } } else { GUILayout.BeginHorizontal(); GUILayout.Label("Empty"); - if (AvailableCrew.Count > 0 && GUILayout.Button("Add", GUILayout.Width(120))) + if (PossibleCrewForPart.Count > 0 && GUILayout.Button("Add", GUILayout.Width(120))) { showShipRoster = false; showCrewSelect = true; @@ -1200,7 +1235,7 @@ public static void DrawShipRoster(int windowID) indexToCrew = i; crewListWindowPosition.height = 1; } - if (AvailableCrew.Count == 0 && GUILayout.Button("Hire New", GUILayout.Width(120))) + if (!UseAvailabilityChecker && AvailableCrew.Count == 0 && GUILayout.Button("Hire New", GUILayout.Width(120))) { int index = randomCrew ? rand.Next(HighLogic.CurrentGame.CrewRoster.Applicants.Count() - 1) : 0; ProtoCrewMember hired = HighLogic.CurrentGame.CrewRoster.Applicants.ElementAt(index); @@ -1273,7 +1308,7 @@ public static void CrewFirstAvailable() Part p = parts[partIndex]; if (KCT_GameStates.launchedCrew.Find(part => part.partID == p.craftID) == null) KCT_GameStates.launchedCrew.Add(new CrewedPart(p.craftID, new List())); - AvailableCrew = GetAvailableCrew(); + AvailableCrew = GetAvailableCrew(p.partInfo.name); for (int i = 0; i < p.CrewCapacity; i++) { if (KCT_GameStates.launchedCrew[partIndex].crewList.Count <= i) @@ -1302,33 +1337,36 @@ public static void CrewFirstAvailable() } } - private static List GetAvailableCrew() + private static List GetAvailableCrew(string partName) { List availableCrew = new List(); - List roster = HighLogic.CurrentGame.CrewRoster.Crew.ToList(); + List roster; if (CrewRandR.API.Available) - { roster = CrewRandR.API.AvailableCrew.ToList(); - } + else + roster = HighLogic.CurrentGame.CrewRoster.Crew.ToList(); foreach (ProtoCrewMember crewMember in roster) //Initialize available crew list { bool available = true; - if (crewMember.rosterStatus == ProtoCrewMember.RosterStatus.Available && !crewMember.inactive) + if ((!UseAvailabilityChecker || string.IsNullOrEmpty(partName)) || AvailabilityChecker(crewMember, partName)) { - foreach (CrewedPart cP in KCT_GameStates.launchedCrew) + if (crewMember.rosterStatus == ProtoCrewMember.RosterStatus.Available && !crewMember.inactive) { - if (cP.crewList.Contains(crewMember)) + foreach (CrewedPart cP in KCT_GameStates.launchedCrew) { - available = false; - break; + if (cP.crewList.Contains(crewMember)) + { + available = false; + break; + } } } + else + available = false; + if (available) + availableCrew.Add(crewMember); } - else - available = false; - if (available) - availableCrew.Add(crewMember); } @@ -1360,7 +1398,7 @@ public static void DrawCrewSelect(int windowID) { //List availableCrew = CrewAvailable(); GUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.MaxHeight(Screen.height / 2)); - scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Height(AvailableCrew.Count * 28 * 2 + 35), GUILayout.MaxHeight(Screen.height / 2)); + scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Height(PossibleCrewForPart.Count * 28 * 2 + 35), GUILayout.MaxHeight(Screen.height / 2)); float cWidth = 80; @@ -1371,7 +1409,7 @@ public static void DrawCrewSelect(int windowID) //GUILayout.Space(cWidth/2); GUILayout.EndHorizontal(); - foreach (ProtoCrewMember crew in AvailableCrew) + foreach (ProtoCrewMember crew in PossibleCrewForPart) { GUILayout.BeginHorizontal(); //GUILayout.Label(crew.name); @@ -1393,7 +1431,7 @@ public static void DrawCrewSelect(int windowID) } activeCrew.Insert(indexToCrew, crew); } - AvailableCrew.Remove(crew); + PossibleCrewForPart.Remove(crew); KCT_GameStates.launchedCrew[partIndexToCrew].crewList = activeCrew; showCrewSelect = false; showShipRoster = true; From 34625a323e3b7a42ab19c20b42212f59ff423d4e Mon Sep 17 00:00:00 2001 From: NathanKell Date: Wed, 9 Aug 2017 23:28:38 -0700 Subject: [PATCH 03/12] Allow the option of reconditioning a pad blocking rollout to it. --- Kerbal_Construction_Time/KCT_GUI_BuildList.cs | 36 +++++++++++-------- Kerbal_Construction_Time/KCT_GUI_Presets.cs | 1 + Kerbal_Construction_Time/KCT_PresetManager.cs | 2 +- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Kerbal_Construction_Time/KCT_GUI_BuildList.cs b/Kerbal_Construction_Time/KCT_GUI_BuildList.cs index feec311..c0cc9b5 100644 --- a/Kerbal_Construction_Time/KCT_GUI_BuildList.cs +++ b/Kerbal_Construction_Time/KCT_GUI_BuildList.cs @@ -482,38 +482,46 @@ public static void DrawBuildListWindow(int windowID) bool siteHasActiveRolloutOrRollback = rollout != null || KCT_GameStates.ActiveKSC.GetReconRollout(KCT_Recon_Rollout.RolloutReconType.Rollback, launchSite) != null; if (rolloutEnabled && !HighLogic.LoadedSceneIsEditor && recovery == null && !siteHasActiveRolloutOrRollback) //rollout if the pad isn't busy { + bool hasRecond = false; GUIStyle btnColor = greenButton; if (KCT_GameStates.ActiveKSC.ActiveLPInstance.destroyed) btnColor = redButton; - else if (KCT_GameStates.ActiveKSC.GetReconditioning(KCT_GameStates.ActiveKSC.ActiveLPInstance.name) != null) + else if (hasRecond = KCT_GameStates.ActiveKSC.GetReconditioning(KCT_GameStates.ActiveKSC.ActiveLPInstance.name) != null) btnColor = yellowButton; KCT_Recon_Rollout tmpRollout = new KCT_Recon_Rollout(b, KCT_Recon_Rollout.RolloutReconType.Rollout, b.id.ToString(), launchSite); string rolloutText = (i == MouseOnRolloutButton ? MagiCore.Utilities.GetColonFormattedTime(tmpRollout.AsBuildItem().GetTimeLeft()) : "Rollout"); if (GUILayout.Button(rolloutText, btnColor, GUILayout.ExpandWidth(false))) { - List facilityChecks = b.MeetsFacilityRequirements(false); - if (facilityChecks.Count == 0) + if (KCT_PresetManager.Instance.ActivePreset.generalSettings.ReconditioningBlocksPad && hasRecond) + { + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "cannotRollOutReconditioningPopup", "Cannot Roll out!", "You must finish reconditioning the launchpad before you can roll out to it!", "Acknowledged", false, HighLogic.UISkin); + } + else { - if (!KCT_GameStates.ActiveKSC.ActiveLPInstance.destroyed) + List facilityChecks = b.MeetsFacilityRequirements(false); + if (facilityChecks.Count == 0) { - b.launchSiteID = KCT_GameStates.ActiveKSC.ActiveLaunchPadID; + if (!KCT_GameStates.ActiveKSC.ActiveLPInstance.destroyed) + { + b.launchSiteID = KCT_GameStates.ActiveKSC.ActiveLaunchPadID; - if (rollout != null) + if (rollout != null) + { + rollout.SwapRolloutType(); + } + // tmpRollout.launchPadID = KCT_GameStates.ActiveKSC.ActiveLPInstance.name; + KCT_GameStates.ActiveKSC.Recon_Rollout.Add(tmpRollout); + } + else { - rollout.SwapRolloutType(); + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "cannotLaunchRepairPopup", "Cannot Launch!", "You must repair the launchpad before you can launch a vessel from it!", "Acknowledged", false, HighLogic.UISkin); } - // tmpRollout.launchPadID = KCT_GameStates.ActiveKSC.ActiveLPInstance.name; - KCT_GameStates.ActiveKSC.Recon_Rollout.Add(tmpRollout); } else { - PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "cannotLaunchRepairPopup", "Cannot Launch!", "You must repair the launchpad before you can launch a vessel from it!", "Acknowledged", false, HighLogic.UISkin); + PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "cannotLaunchEditorChecksPopup", "Cannot Launch!", "Warning! This vessel did not pass the editor checks! Until you upgrade the VAB and/or Launchpad it cannot be launched. Listed below are the failed checks:\n" + String.Join("\n", facilityChecks.ToArray()), "Acknowledged", false, HighLogic.UISkin); } } - else - { - PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "cannotLaunchEditorChecksPopup", "Cannot Launch!", "Warning! This vessel did not pass the editor checks! Until you upgrade the VAB and/or Launchpad it cannot be launched. Listed below are the failed checks:\n" + String.Join("\n", facilityChecks.ToArray()), "Acknowledged", false, HighLogic.UISkin); - } } if (Event.current.type == EventType.Repaint) if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition)) diff --git a/Kerbal_Construction_Time/KCT_GUI_Presets.cs b/Kerbal_Construction_Time/KCT_GUI_Presets.cs index d6b9620..f7221dc 100644 --- a/Kerbal_Construction_Time/KCT_GUI_Presets.cs +++ b/Kerbal_Construction_Time/KCT_GUI_Presets.cs @@ -113,6 +113,7 @@ public static void DrawPresetWindow(int windowID) WorkingPreset.generalSettings.Enabled= GUILayout.Toggle(WorkingPreset.generalSettings.Enabled, "Mod Enabled", HighLogic.Skin.button); WorkingPreset.generalSettings.BuildTimes = GUILayout.Toggle(WorkingPreset.generalSettings.BuildTimes, "Build Times", HighLogic.Skin.button); WorkingPreset.generalSettings.ReconditioningTimes = GUILayout.Toggle(WorkingPreset.generalSettings.ReconditioningTimes, "Launchpad Reconditioning", HighLogic.Skin.button); + WorkingPreset.generalSettings.ReconditioningTimes = GUILayout.Toggle(WorkingPreset.generalSettings.ReconditioningBlocksPad, "Reconditioning Blocks Pad", HighLogic.Skin.button); WorkingPreset.generalSettings.TechUnlockTimes = GUILayout.Toggle(WorkingPreset.generalSettings.TechUnlockTimes, "Tech Unlock Times", HighLogic.Skin.button); WorkingPreset.generalSettings.KSCUpgradeTimes = GUILayout.Toggle(WorkingPreset.generalSettings.KSCUpgradeTimes, "KSC Upgrade Times", HighLogic.Skin.button); WorkingPreset.generalSettings.TechUpgrades = GUILayout.Toggle(WorkingPreset.generalSettings.TechUpgrades, "Upgrades From Tech Tree", HighLogic.Skin.button); diff --git a/Kerbal_Construction_Time/KCT_PresetManager.cs b/Kerbal_Construction_Time/KCT_PresetManager.cs index 684dd1a..c43d45f 100644 --- a/Kerbal_Construction_Time/KCT_PresetManager.cs +++ b/Kerbal_Construction_Time/KCT_PresetManager.cs @@ -316,7 +316,7 @@ public void SetActive() public class KCT_Preset_General : ConfigNodeStorage { [Persistent] - public bool Enabled = true, BuildTimes = true, ReconditioningTimes = true, TechUnlockTimes = true, KSCUpgradeTimes = true, + public bool Enabled = true, BuildTimes = true, ReconditioningTimes = true, ReconditioningBlocksPad = false, TechUnlockTimes = true, KSCUpgradeTimes = true, TechUpgrades = true, SharedUpgradePool = false; [Persistent] public string StartingPoints = "15,15,45"; //Career, Science, and Sandbox modes From 5ba33ac6fb385985daa339a20f45cdfbfe039e7c Mon Sep 17 00:00:00 2001 From: NathanKell Date: Wed, 9 Aug 2017 23:39:40 -0700 Subject: [PATCH 04/12] Show rollout cost in build gui --- Kerbal_Construction_Time/KCT_GUI_BuildList.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Kerbal_Construction_Time/KCT_GUI_BuildList.cs b/Kerbal_Construction_Time/KCT_GUI_BuildList.cs index c0cc9b5..4732e44 100644 --- a/Kerbal_Construction_Time/KCT_GUI_BuildList.cs +++ b/Kerbal_Construction_Time/KCT_GUI_BuildList.cs @@ -489,6 +489,8 @@ public static void DrawBuildListWindow(int windowID) else if (hasRecond = KCT_GameStates.ActiveKSC.GetReconditioning(KCT_GameStates.ActiveKSC.ActiveLPInstance.name) != null) btnColor = yellowButton; KCT_Recon_Rollout tmpRollout = new KCT_Recon_Rollout(b, KCT_Recon_Rollout.RolloutReconType.Rollout, b.id.ToString(), launchSite); + if (tmpRollout.cost > 0d) + GUILayout.Label("āˆš" + tmpRollout.cost.ToString("N0")); string rolloutText = (i == MouseOnRolloutButton ? MagiCore.Utilities.GetColonFormattedTime(tmpRollout.AsBuildItem().GetTimeLeft()) : "Rollout"); if (GUILayout.Button(rolloutText, btnColor, GUILayout.ExpandWidth(false))) { From 6565880ec7a4ccc4810d434c8ded76841f17191f Mon Sep 17 00:00:00 2001 From: NathanKell Date: Wed, 9 Aug 2017 23:56:57 -0700 Subject: [PATCH 05/12] Add Global_Variables support --- Kerbal_Construction_Time/KCT_PresetManager.cs | 35 +++++++++++++++++++ Kerbal_Construction_Time/KCT_Utilities.cs | 10 ++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Kerbal_Construction_Time/KCT_PresetManager.cs b/Kerbal_Construction_Time/KCT_PresetManager.cs index c43d45f..60220e7 100644 --- a/Kerbal_Construction_Time/KCT_PresetManager.cs +++ b/Kerbal_Construction_Time/KCT_PresetManager.cs @@ -354,6 +354,8 @@ public class KCT_Preset_Part_Variables public Dictionary Module_Variables = new Dictionary(); //Dictionary of moduleName : modifier //if multiple modules are present on the part, they are all multiplied together. + public Dictionary Global_Variables = new Dictionary(); + private ConfigNode DictionaryToNode(Dictionary theDict, string nodeName) { ConfigNode node = new ConfigNode(nodeName); @@ -382,6 +384,7 @@ public ConfigNode AsConfigNode() ConfigNode node = new ConfigNode("KCT_Preset_Part_Variables"); node.AddNode(DictionaryToNode(Part_Variables, "Part_Variables")); node.AddNode(DictionaryToNode(Module_Variables, "Module_Variables")); + node.AddNode(DictionaryToNode(Global_Variables, "Global_Variables")); return node; } @@ -390,11 +393,14 @@ public void FromConfigNode(ConfigNode node) { Part_Variables.Clear(); Module_Variables.Clear(); + Global_Variables.Clear(); if (node.HasNode("Part_Variables")) Part_Variables = NodeToDictionary(node.GetNode("Part_Variables")); if (node.HasNode("Module_Variables")) Module_Variables = NodeToDictionary(node.GetNode("Module_Variables")); + if (node.HasNode("Global_Variables")) + Global_Variables = NodeToDictionary(node.GetNode("Global_Variables")); } public double GetPartVariable(string partName) @@ -416,6 +422,17 @@ public double GetModuleVariable(List moduleNames) return value; } + public double GetGlobalVariable(List moduleNames) + { + double value = 1.0; + foreach (string name in moduleNames) + { + if (Global_Variables.ContainsKey(name)) + value *= Global_Variables[name]; + } + return value; + } + //These are all multiplied in case multiple modules exist on one part (this one takes a PartModuleList instead) public double GetModuleVariable(PartModuleList modules) { @@ -427,5 +444,23 @@ public double GetModuleVariable(PartModuleList modules) } return value; } + + public void SetGlobalVariables(List variables, PartModuleList modules) + { + foreach (PartModule mod in modules) + { + if (Global_Variables.ContainsKey(mod.moduleName)) + variables.AddUnique(mod.moduleName); + } + } + + public void SetGlobalVariables(List variables, List moduleNames) + { + foreach (string name in moduleNames) + { + if (Global_Variables.ContainsKey(name)) + variables.AddUnique(name); + } + } } } diff --git a/Kerbal_Construction_Time/KCT_Utilities.cs b/Kerbal_Construction_Time/KCT_Utilities.cs index ddaab89..5cb4c56 100644 --- a/Kerbal_Construction_Time/KCT_Utilities.cs +++ b/Kerbal_Construction_Time/KCT_Utilities.cs @@ -270,6 +270,9 @@ public static double GetBuildTime(List parts, bool useInventory) IList inventorySample = ScrapYardWrapper.GetPartsInInventory(parts, ScrapYardWrapper.ComparisonStrength.STRICT) ?? new List(); double totalEffectiveCost = 0; + + List globalVariables = new List(); + foreach (Part p in parts) { string name = p.partInfo.name; @@ -282,6 +285,7 @@ public static double GetBuildTime(List parts, bool useInventory) double PartMultiplier = KCT_PresetManager.Instance.ActivePreset.partVariables.GetPartVariable(name); double ModuleMultiplier = KCT_PresetManager.Instance.ActivePreset.partVariables.GetModuleVariable(p.Modules); + KCT_PresetManager.Instance.ActivePreset.partVariables.SetGlobalVariables(globalVariables, p.Modules); double InvEff = (inventorySample.Contains(p) ? KCT_PresetManager.Instance.ActivePreset.timeSettings.InventoryEffect : 0); int builds = ScrapYardWrapper.GetBuildCount(p); @@ -301,7 +305,7 @@ public static double GetBuildTime(List parts, bool useInventory) if (effectiveCost < 0) effectiveCost = 0; totalEffectiveCost += effectiveCost; } - double finalBP = KCT_MathParsing.GetStandardFormulaValue("BP", new Dictionary() { { "E", totalEffectiveCost.ToString() }, { "O", KCT_PresetManager.Instance.ActivePreset.timeSettings.OverallMultiplier.ToString() } }); + double finalBP = KCT_PresetManager.Instance.ActivePreset.partVariables.GetGlobalVariable(globalVariables) * KCT_MathParsing.GetStandardFormulaValue("BP", new Dictionary() { { "E", totalEffectiveCost.ToString() }, { "O", KCT_PresetManager.Instance.ActivePreset.timeSettings.OverallMultiplier.ToString() } }); return finalBP; } @@ -311,6 +315,7 @@ public static double GetBuildTime(List parts, bool useInventory) IList inventorySample = ScrapYardWrapper.GetPartsInInventory(parts, ScrapYardWrapper.ComparisonStrength.STRICT) ?? new List(); double totalEffectiveCost = 0; + List globalVariables = new List(); foreach (ConfigNode p in parts) { string name = PartNameFromNode(p); @@ -331,6 +336,7 @@ public static double GetBuildTime(List parts, bool useInventory) foreach (ConfigNode modNode in GetModulesFromPartNode(p)) moduleNames.Add(modNode.GetValue("name")); double ModuleMultiplier = KCT_PresetManager.Instance.ActivePreset.partVariables.GetModuleVariable(moduleNames); + KCT_PresetManager.Instance.ActivePreset.partVariables.SetGlobalVariables(globalVariables, moduleNames); double InvEff = (inventorySample.Contains(p) ? KCT_PresetManager.Instance.ActivePreset.timeSettings.InventoryEffect : 0); int builds = ScrapYardWrapper.GetBuildCount(p); @@ -349,7 +355,7 @@ public static double GetBuildTime(List parts, bool useInventory) if (effectiveCost < 0) effectiveCost = 0; totalEffectiveCost += effectiveCost; } - double finalBP = KCT_MathParsing.GetStandardFormulaValue("BP", new Dictionary() { { "E", totalEffectiveCost.ToString() }, { "O", KCT_PresetManager.Instance.ActivePreset.timeSettings.OverallMultiplier.ToString() } }); + double finalBP = KCT_PresetManager.Instance.ActivePreset.partVariables.GetGlobalVariable(globalVariables) * KCT_MathParsing.GetStandardFormulaValue("BP", new Dictionary() { { "E", totalEffectiveCost.ToString() }, { "O", KCT_PresetManager.Instance.ActivePreset.timeSettings.OverallMultiplier.ToString() } }); return finalBP; //return Math.Sqrt(totalEffectiveCost) * 2000 * KCT_PresetManager.Instance.ActivePreset.timeSettings.OverallMultiplier; } From 7ef07323f97c1442605aef68c686c2e59b0ff559 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Fri, 11 Aug 2017 21:10:46 -0700 Subject: [PATCH 06/12] Set a technode's icon's color red (rather than white) if it's being researched but not unlocked yet. --- .../KerbalConstructionTime.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Kerbal_Construction_Time/KerbalConstructionTime.cs b/Kerbal_Construction_Time/KerbalConstructionTime.cs index 130b383..97c51f2 100644 --- a/Kerbal_Construction_Time/KerbalConstructionTime.cs +++ b/Kerbal_Construction_Time/KerbalConstructionTime.cs @@ -526,6 +526,34 @@ public void FixedUpdate() } } + public void LateUpdate() + { + // FIXME really should run this only once, and then again on techlist change. + // For now, spam per frame + if (KSP.UI.Screens.RDController.Instance != null) + { + for (int i = KSP.UI.Screens.RDController.Instance.nodes.Count; i-- > 0;) + { + KSP.UI.Screens.RDNode node = KSP.UI.Screens.RDController.Instance.nodes[i]; + if (node.tech != null) + { + if (HasTechInList(node.tech.techID)) + node.graphics.SetIconColor(Color.red); + // else reset? Bleh, why bother. + } + } + } + } + + protected bool HasTechInList(string id) + { + for (int i = KCT_GameStates.TechList.Count; i-- > 0;) + if (KCT_GameStates.TechList[i].techID == id) + return true; + + return false; + } + public static void DelayedStart() { KCTDebug.Log("DelayedStart start"); From 3bb506e35e31b6bf8e32ec6af0f85bd4905dff86 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Fri, 11 Aug 2017 22:30:17 -0700 Subject: [PATCH 07/12] Per request make the 'researching node' color KSPNotSoGoodOrange --- Kerbal_Construction_Time/KerbalConstructionTime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kerbal_Construction_Time/KerbalConstructionTime.cs b/Kerbal_Construction_Time/KerbalConstructionTime.cs index 97c51f2..d3d166f 100644 --- a/Kerbal_Construction_Time/KerbalConstructionTime.cs +++ b/Kerbal_Construction_Time/KerbalConstructionTime.cs @@ -538,7 +538,7 @@ public void LateUpdate() if (node.tech != null) { if (HasTechInList(node.tech.techID)) - node.graphics.SetIconColor(Color.red); + node.graphics.SetIconColor(XKCDColors.KSPNotSoGoodOrange); // else reset? Bleh, why bother. } } From a9ffb0efe03d800114e62c5ca5da2871f8358439 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Fri, 11 Aug 2017 23:15:34 -0700 Subject: [PATCH 08/12] Allow limiting rush build clicks --- Kerbal_Construction_Time/KCT_BuildListStorage.cs | 4 ++++ Kerbal_Construction_Time/KCT_BuildListVessel.cs | 3 +++ Kerbal_Construction_Time/KCT_GUI_BuildList.cs | 5 ++++- Kerbal_Construction_Time/KCT_PresetManager.cs | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Kerbal_Construction_Time/KCT_BuildListStorage.cs b/Kerbal_Construction_Time/KCT_BuildListStorage.cs index 4e81d09..5980dab 100644 --- a/Kerbal_Construction_Time/KCT_BuildListStorage.cs +++ b/Kerbal_Construction_Time/KCT_BuildListStorage.cs @@ -123,6 +123,8 @@ public class BuildListItem [Persistent] float cost = 0, mass = 0, kscDistance = 0; [Persistent] + int rushBuildClicks = 0; + [Persistent] int EditorFacility = 0, LaunchPadID = -1; [Persistent] List desiredManifest = new List(); @@ -135,6 +137,7 @@ public KCT_BuildListVessel ToBuildListVessel() ret.cannotEarnScience = cannotEarnScience; ret.TotalMass = mass; ret.DistanceFromKSC = kscDistance; + ret.rushBuildClicks = rushBuildClicks; ret.launchSiteID = LaunchPadID; ret.DesiredManifest = desiredManifest; return ret; @@ -151,6 +154,7 @@ public BuildListItem FromBuildListVessel(KCT_BuildListVessel blv) this.shipID = blv.id.ToString(); this.cannotEarnScience = blv.cannotEarnScience; this.cost = blv.cost; + this.rushBuildClicks = blv.rushBuildClicks; this.mass = blv.TotalMass; this.kscDistance = blv.DistanceFromKSC; this.EditorFacility = (int)blv.GetEditorFacility(); diff --git a/Kerbal_Construction_Time/KCT_BuildListVessel.cs b/Kerbal_Construction_Time/KCT_BuildListVessel.cs index 60c785f..f9cd1c9 100644 --- a/Kerbal_Construction_Time/KCT_BuildListVessel.cs +++ b/Kerbal_Construction_Time/KCT_BuildListVessel.cs @@ -20,6 +20,7 @@ public enum ListType { None, VAB, SPH, TechNode, Reconditioning, KSC }; public Guid id; public bool cannotEarnScience; public float cost = 0, TotalMass = 0, DistanceFromKSC = 0; + public int rushBuildClicks = 0; public float emptyCost = 0, emptyMass = 0; public double buildRate { get { return KCT_Utilities.GetBuildRate(this); } } public double timeLeft @@ -184,6 +185,8 @@ public KCT_BuildListVessel(Vessel vessel) //For recovered vessels progress = buildPoints; DistanceFromKSC = (float)SpaceCenter.Instance.GreatCircleDistance(SpaceCenter.Instance.cb.GetRelSurfaceNVector(vessel.latitude, vessel.longitude)); + + rushBuildClicks = 0; } private ConfigNode FromInFlightVessel(Vessel VesselToSave) diff --git a/Kerbal_Construction_Time/KCT_GUI_BuildList.cs b/Kerbal_Construction_Time/KCT_GUI_BuildList.cs index 4732e44..eb7fd4d 100644 --- a/Kerbal_Construction_Time/KCT_GUI_BuildList.cs +++ b/Kerbal_Construction_Time/KCT_GUI_BuildList.cs @@ -1190,7 +1190,9 @@ private static void DrawBLPlusWindow(int windowID) KCT_GameStates.ActiveKSC.SPHList.Insert(0, b); } } - if (!b.isFinished && GUILayout.Button("Rush Build 10%\nāˆš" + Math.Round(0.2 * b.GetTotalCost()))) + if (!b.isFinished + && (KCT_PresetManager.Instance.ActivePreset.generalSettings.MaxRushClicks == 0 || b.rushBuildClicks < KCT_PresetManager.Instance.ActivePreset.generalSettings.MaxRushClicks) + && GUILayout.Button("Rush Build 10%\nāˆš" + Math.Round(0.2 * b.GetTotalCost()))) { double cost = b.GetTotalCost(); cost *= 0.2; @@ -1199,6 +1201,7 @@ private static void DrawBLPlusWindow(int windowID) { b.AddProgress(remainingBP * 0.1); KCT_Utilities.SpendFunds(cost, TransactionReasons.None); + ++b.rushBuildClicks; } } diff --git a/Kerbal_Construction_Time/KCT_PresetManager.cs b/Kerbal_Construction_Time/KCT_PresetManager.cs index 60220e7..a11fd47 100644 --- a/Kerbal_Construction_Time/KCT_PresetManager.cs +++ b/Kerbal_Construction_Time/KCT_PresetManager.cs @@ -320,6 +320,8 @@ public class KCT_Preset_General : ConfigNodeStorage TechUpgrades = true, SharedUpgradePool = false; [Persistent] public string StartingPoints = "15,15,45"; //Career, Science, and Sandbox modes + [Persistent] + public int MaxRushClicks = 0; } public class KCT_Preset_Time : ConfigNodeStorage From d2d41a2ea0e4b3292ad2f4ca3b92353289a95d87 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Sat, 12 Aug 2017 16:22:11 -0700 Subject: [PATCH 09/12] Support tracking vessel number of stages, number of staging parts, and cost of staging parts --- .../KCT_BuildListVessel.cs | 25 +++++++++++++++++++ Kerbal_Construction_Time/KCT_MathParsing.cs | 3 +++ 2 files changed, 28 insertions(+) diff --git a/Kerbal_Construction_Time/KCT_BuildListVessel.cs b/Kerbal_Construction_Time/KCT_BuildListVessel.cs index f9cd1c9..cfbb07e 100644 --- a/Kerbal_Construction_Time/KCT_BuildListVessel.cs +++ b/Kerbal_Construction_Time/KCT_BuildListVessel.cs @@ -21,6 +21,9 @@ public enum ListType { None, VAB, SPH, TechNode, Reconditioning, KSC }; public bool cannotEarnScience; public float cost = 0, TotalMass = 0, DistanceFromKSC = 0; public int rushBuildClicks = 0; + public int numStages = 0; + public int numStageParts = 0; + public double stagePartCost = 0d; public float emptyCost = 0, emptyMass = 0; public double buildRate { get { return KCT_Utilities.GetBuildRate(this); } } public double timeLeft @@ -104,6 +107,20 @@ public KCT_BuildListVessel(ShipConstruct s, String ls, double bP, String flagURL cost = s.GetShipCosts(out emptyCost, out fuel); TotalMass = s.GetShipMass(out emptyMass, out fuel); + HashSet stages = new HashSet(); + 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; buildPoints = bP; progress = 0; @@ -165,10 +182,13 @@ public KCT_BuildListVessel(Vessel vessel) //For recovered vessels emptyCost = KCT_Utilities.GetTotalVesselCost(shipNode, false); TotalMass = 0; emptyMass = 0; + + HashSet stages = new HashSet(); foreach (ProtoPartSnapshot p in vessel.protoVessel.protoPartSnapshots) { string name = p.partInfo.name; + stages.Add(p.inverseStageIndex); TotalMass += p.mass; emptyMass += p.mass; foreach (ProtoPartResourceSnapshot rsc in p.resources) @@ -179,6 +199,8 @@ public KCT_BuildListVessel(Vessel vessel) //For recovered vessels } } cannotEarnScience = true; + numStages = stages.Count; + // FIXME ignore stageable part count and cost - it'll be fixed when we put this back in the editor. buildPoints = KCT_Utilities.GetBuildTime(shipNode.GetNodes("PART").ToList(), false); flag = HighLogic.CurrentGame.flagURL; @@ -399,6 +421,9 @@ public KCT_BuildListVessel NewCopy(bool RecalcTime) ret.emptyMass = this.emptyMass; ret.cost = this.cost; ret.emptyCost = this.emptyCost; + ret.numStageParts = this.numStageParts; + ret.numStages = this.numStages; + ret.stagePartCost = this.stagePartCost; return ret; } diff --git a/Kerbal_Construction_Time/KCT_MathParsing.cs b/Kerbal_Construction_Time/KCT_MathParsing.cs index ea54707..06ff124 100644 --- a/Kerbal_Construction_Time/KCT_MathParsing.cs +++ b/Kerbal_Construction_Time/KCT_MathParsing.cs @@ -130,6 +130,9 @@ public static double ParseRolloutCostFormula(KCT_BuildListVessel vessel) variables.Add("LM", LaunchSiteMax.ToString()); variables.Add("EL", EditorLevel.ToString()); variables.Add("ELM", EditorMax.ToString()); + variables.Add("SN", vessel.numStages.ToString()); + variables.Add("SP", vessel.numStageParts.ToString()); + variables.Add("SC", vessel.stagePartCost.ToString()); AddCrewVariables(variables); From ae0f2c65f859da15eb2c0bc997332046bd3517f8 Mon Sep 17 00:00:00 2001 From: magico13 Date: Mon, 14 Aug 2017 20:10:41 -0400 Subject: [PATCH 10/12] Write to ReconditioningBlocksPad correctly. --- Kerbal_Construction_Time/KCT_GUI_Presets.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kerbal_Construction_Time/KCT_GUI_Presets.cs b/Kerbal_Construction_Time/KCT_GUI_Presets.cs index f7221dc..7597ec1 100644 --- a/Kerbal_Construction_Time/KCT_GUI_Presets.cs +++ b/Kerbal_Construction_Time/KCT_GUI_Presets.cs @@ -113,7 +113,7 @@ public static void DrawPresetWindow(int windowID) WorkingPreset.generalSettings.Enabled= GUILayout.Toggle(WorkingPreset.generalSettings.Enabled, "Mod Enabled", HighLogic.Skin.button); WorkingPreset.generalSettings.BuildTimes = GUILayout.Toggle(WorkingPreset.generalSettings.BuildTimes, "Build Times", HighLogic.Skin.button); WorkingPreset.generalSettings.ReconditioningTimes = GUILayout.Toggle(WorkingPreset.generalSettings.ReconditioningTimes, "Launchpad Reconditioning", HighLogic.Skin.button); - WorkingPreset.generalSettings.ReconditioningTimes = GUILayout.Toggle(WorkingPreset.generalSettings.ReconditioningBlocksPad, "Reconditioning Blocks Pad", HighLogic.Skin.button); + WorkingPreset.generalSettings.ReconditioningBlocksPad = GUILayout.Toggle(WorkingPreset.generalSettings.ReconditioningBlocksPad, "Reconditioning Blocks Pad", HighLogic.Skin.button); WorkingPreset.generalSettings.TechUnlockTimes = GUILayout.Toggle(WorkingPreset.generalSettings.TechUnlockTimes, "Tech Unlock Times", HighLogic.Skin.button); WorkingPreset.generalSettings.KSCUpgradeTimes = GUILayout.Toggle(WorkingPreset.generalSettings.KSCUpgradeTimes, "KSC Upgrade Times", HighLogic.Skin.button); WorkingPreset.generalSettings.TechUpgrades = GUILayout.Toggle(WorkingPreset.generalSettings.TechUpgrades, "Upgrades From Tech Tree", HighLogic.Skin.button); From a0b5147a2b5bc4e61ee0cb22d985d34c9346240a Mon Sep 17 00:00:00 2001 From: NathanKell Date: Sat, 19 Aug 2017 13:00:10 -0700 Subject: [PATCH 11/12] Forgot to apply stage vars to rollout time. --- Kerbal_Construction_Time/KCT_MathParsing.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Kerbal_Construction_Time/KCT_MathParsing.cs b/Kerbal_Construction_Time/KCT_MathParsing.cs index 06ff124..980a3cc 100644 --- a/Kerbal_Construction_Time/KCT_MathParsing.cs +++ b/Kerbal_Construction_Time/KCT_MathParsing.cs @@ -189,6 +189,9 @@ public static double ParseReconditioningFormula(KCT_BuildListVessel vessel, bool int isRecon = isReconditioning ? 1 : 0; variables.Add("RE", isRecon.ToString()); variables.Add("S", KCT_PresetManager.Instance.ActivePreset.timeSettings.RolloutReconSplit.ToString()); + variables.Add("SN", vessel.numStages.ToString()); + variables.Add("SP", vessel.numStageParts.ToString()); + variables.Add("SC", vessel.stagePartCost.ToString()); AddCrewVariables(variables); From 39c50712f519881db27a109c6931907b86efc1c6 Mon Sep 17 00:00:00 2001 From: magico13 Date: Wed, 23 Aug 2017 23:15:47 -0400 Subject: [PATCH 12/12] Fix for rates being incorrect after saving Preset --- Kerbal_Construction_Time/KCT_GUI_Presets.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Kerbal_Construction_Time/KCT_GUI_Presets.cs b/Kerbal_Construction_Time/KCT_GUI_Presets.cs index 7597ec1..7d1f75e 100644 --- a/Kerbal_Construction_Time/KCT_GUI_Presets.cs +++ b/Kerbal_Construction_Time/KCT_GUI_Presets.cs @@ -300,7 +300,6 @@ public static void DrawPresetWindow(int windowID) ksc.RecalculateBuildRates(); ksc.RecalculateUpgradedBuildRates(); } - KCT_GUI.ResetFormulaRateHolders(); } if (GUILayout.Button("Cancel", GUILayout.ExpandWidth(false)))