├── .gitignore ├── AbstractResourceTank.cs ├── CC.UI ├── AddTankControl.cs ├── AssemblyInfo.cs ├── Assets │ ├── ConfigurableContainers.unity │ ├── ConfigurableContainers.unity.meta │ ├── Prefabs.meta │ ├── Prefabs │ │ ├── TankControls.prefab │ │ ├── TankControls.prefab.meta │ │ ├── TankManagerUI.prefab │ │ └── TankManagerUI.prefab.meta │ └── icons.meta ├── CC.UI.csproj ├── Interfaces │ ├── ITankInfo.cs │ └── ITankManager.cs ├── TankConfigsControl.cs ├── TankControlsUI.cs ├── TankManagerUI.cs ├── TestTankInfo.cs ├── cc_ui.bundle_bundle.xml └── cc_ui.bundle_bundle.xml.meta ├── ChangeLog.md ├── ConfigurableContainers-Intrusive.netkan ├── ConfigurableContainers.csproj ├── ConfigurableContainers.netkan ├── Cryogenics ├── ActiveCooling.cs ├── CryogenicsParams.cs └── ResourceBoiloff.cs ├── GameData └── ConfigurableContainers │ ├── ConfigurableContainers.version │ ├── GPO_Patch.cfg │ └── Parts │ ├── B9_Aerospace_ProceduralWings_Patch.cfg │ ├── Benjee10_X-37B_Patch.cfg │ ├── Bluedog_DB_Patch.cfg │ ├── DodoLabs_Patch.cfg │ ├── FuelTanksPlus_Patch.cfg │ ├── HangarResourceTanks.cfg │ ├── KWRocketry_Patch.cfg │ ├── KerboNerdLaboratories.cfg │ ├── MakingHistory_Patch.cfg │ ├── MiningExpansion_Patch.cfg │ ├── Mk2Expansion_Patch.cfg │ ├── Mk3Expansion_Patch.cfg │ ├── Mk3HypersonicSystems_Patch.cfg │ ├── ModRocketSys_Patch.cfg │ ├── Models │ ├── blue.png │ ├── brown.png │ ├── dark-green.png │ ├── green.png │ ├── grey.png │ ├── light-blue.png │ ├── light-grey.png │ ├── orange.png │ └── warning.png │ ├── MunarIndustries_Patch.cfg │ ├── NearFuturePropulsion_Patch.cfg │ ├── PlanetaryBaseInc_Patch.cfg │ ├── RaginCaucasian_Patch.cfg │ ├── ReStockPlus_Patch.cfg │ ├── SPS_Patch.cfg │ ├── SpaceY-Expanded_Patch.cfg │ ├── SpaceY-Lifters_Patch.cfg │ ├── Squad_Patch.cfg │ ├── StreamlineEnginesTanks_Patch.cfg │ └── Tal-Tanks_Patch.cfg ├── IntrusivePatches ├── CC_INTRUSIVE_PATCHES.md └── GameData │ └── ConfigurableContainers │ └── IntrusivePatches │ └── B9Parts_Patch.cfg ├── LICENSE ├── ModuleSwitchableTank.cs ├── ModuleTankManager.cs ├── PatchContainers.py ├── Properties └── AssemblyInfo.cs ├── README.md ├── SwitchableTankManager.cs ├── SwitchableTankManagerUI.cs ├── SwitchableTankType.cs ├── VolumeConfigsLibrary.cs ├── VolumeConfiguration.cs └── modconfig.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | #should it start with a comment? 2 | *~ 3 | *.mdb 4 | *.dll 5 | .idea 6 | obj 7 | Releases 8 | Screenshots 9 | /GameData/ConfigurableContainers/VolumeConfigs.user 10 | /CC.UI/CC.UI.csproj.DotSettings 11 | /GameData/ConfigurableContainers/Parts/@thumbs 12 | -------------------------------------------------------------------------------- /AbstractResourceTank.cs: -------------------------------------------------------------------------------- 1 | // AbstractResourceTank.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using JetBrains.Annotations; 9 | using UnityEngine; 10 | 11 | namespace AT_Utils 12 | { 13 | public abstract class AbstractResourceTank : SerializableFiledsPartModule, IPartCostModifier, IPartMassModifier, 14 | IModuleInfo 15 | { 16 | /// 17 | /// The difference between the Part.cost and the initial value of the GetModuleCost. 18 | /// Used when the Patch flag is set. 19 | /// 20 | [KSPField(isPersistant = true)] 21 | public float CostPatch; 22 | 23 | /// 24 | /// If set, this flag causes the Module to save the initial difference between the 25 | /// Part.cost and GetModuleCost value so that the total part cost is unchanged. 26 | /// 27 | [KSPField(isPersistant = true)] 28 | public bool DoCostPatch; 29 | 30 | /// 31 | /// If set, this flag causes the Module to save the initial difference between the 32 | /// Part.mass and GetModuleMass value so that the total part cost is unchanged. 33 | /// 34 | [KSPField(isPersistant = true)] 35 | public bool DoMassPatch; 36 | 37 | /// 38 | /// The difference between the Part.mass and the initial value of the GetModuleMass. 39 | /// Used when the Patch flag is set. 40 | /// 41 | [KSPField(isPersistant = true)] 42 | public float MassPatch; 43 | 44 | /// 45 | /// The config node provided to OnLoad. 46 | /// 47 | [SerializeField] 48 | public ConfigNode ModuleSave; 49 | 50 | /// 51 | /// If true, the module save was received not in the flight scene. 52 | /// 53 | [KSPField(isPersistant = true)] 54 | public bool ModuleSaveFromPrefab; 55 | 56 | /// 57 | /// The volume of a tank in m^3. It is defined in a config or calculated from the part volume in editor. 58 | /// Cannot be changed in flight. 59 | /// 60 | [KSPField(isPersistant = true)] 61 | public float Volume = -1f; 62 | 63 | /// 64 | /// This is called within the GetModuleCost to calculate the cost of the tank. 65 | /// 66 | protected abstract float TankCost(float defaultCost); 67 | 68 | /// 69 | /// This is called within the GetModuleCost to calculate the cost of tank resources. 70 | /// 71 | /// If true, returns the cost of maxAmount of resources; of current amount otherwise. 72 | protected abstract float ResourcesCost(bool maxAmount = true); 73 | 74 | /// 75 | /// This is called within the GetModuleMass to calculate the mass of the tank. 76 | /// 77 | protected abstract float TankMass(float defaultMass); 78 | 79 | /// 80 | /// This is called within the GetModuleMass to calculate the mass of tank resources. 81 | /// 82 | /// If true, returns the mass of maxAmount of resources; of current amount otherwise. 83 | protected abstract float ResourcesMass(bool maxAmount = true); 84 | 85 | public override void OnLoad(ConfigNode node) 86 | { 87 | base.OnLoad(node); 88 | ModuleSaveFromPrefab = HighLogic.LoadedScene == GameScenes.LOADING; 89 | } 90 | 91 | public override void OnStart(StartState state) 92 | { 93 | base.OnStart(state); 94 | //this means the module was added by MM patch to an existing part 95 | if(HighLogic.LoadedSceneIsFlight && ModuleSaveFromPrefab) 96 | init_from_part(); 97 | } 98 | 99 | protected abstract void init_from_part(); 100 | 101 | #region IPart*Modifiers 102 | public virtual float GetModuleCost(float defaultCost, ModifierStagingSituation sit) 103 | { 104 | var cost = TankCost(defaultCost); 105 | if(DoCostPatch) 106 | { 107 | CostPatch = -Mathf.Min(cost + ResourcesCost(false), defaultCost); 108 | DoCostPatch = false; 109 | } 110 | var res = part.partInfo != null && part.partInfo.partPrefab == part 111 | ? ResourcesCost(false) 112 | : ResourcesCost(); 113 | return cost + res + CostPatch; 114 | } 115 | 116 | public virtual ModifierChangeWhen GetModuleCostChangeWhen() 117 | { 118 | return ModifierChangeWhen.CONSTANTLY; 119 | } 120 | 121 | //this is not called by PartListTooltip.GetPartStats 122 | public virtual float GetModuleMass(float defaultMass, ModifierStagingSituation sit) 123 | { 124 | var mass = TankMass(defaultMass); 125 | // ReSharper disable once InvertIf 126 | if(DoMassPatch) 127 | { 128 | MassPatch = -Mathf.Min(mass, defaultMass); 129 | DoMassPatch = false; 130 | } 131 | return mass + MassPatch; 132 | } 133 | 134 | public virtual ModifierChangeWhen GetModuleMassChangeWhen() 135 | { 136 | return ModifierChangeWhen.CONSTANTLY; 137 | } 138 | #endregion 139 | 140 | #region IModInfo 141 | public override string GetInfo() 142 | { 143 | return ""; 144 | } 145 | 146 | public virtual string GetModuleTitle() 147 | { 148 | return KSPUtil.PrintModuleName(moduleName); 149 | } 150 | 151 | public virtual string GetPrimaryField() 152 | { 153 | var info = "Additional Mass:\n"; 154 | var tank = DoMassPatch ? 0 : TankMass(part.mass); 155 | var res = ResourcesMass(false); 156 | if(tank > 0) 157 | info += Utils.formatMass(tank) + " internals"; 158 | if(res > 0) 159 | info += (tank > 0 ? "+" : "") + Utils.formatMass(res) + " resources"; 160 | return tank > 0 || res > 0 ? info : ""; 161 | } 162 | 163 | public Callback GetDrawModulePanelCallback() 164 | { 165 | return null; 166 | } 167 | #endregion 168 | 169 | #if DEBUG 170 | [UsedImplicitly] 171 | [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Module")] 172 | public string ThisModule = ""; 173 | 174 | public override void OnAwake() 175 | { 176 | base.OnAwake(); 177 | { 178 | ThisModule = GetType().Name; 179 | } 180 | } 181 | #endif 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /CC.UI/AddTankControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using AT_Utils.UI; 4 | using UnityEngine; 5 | using UnityEngine.UI; 6 | 7 | namespace CC.UI 8 | { 9 | public class AddTankControl : TankManagerUIPart 10 | { 11 | public enum VolumeUnits { CUBIC_METERS, PARTS } 12 | 13 | private static readonly Dictionary unitNames = new Dictionary 14 | { 15 | { VolumeUnits.CUBIC_METERS, "m3" }, { VolumeUnits.PARTS, "%" } 16 | }; 17 | 18 | private static readonly int numUnits = Enum.GetNames(typeof(VolumeUnits)).Length; 19 | 20 | public Dropdown 21 | tankTypeDropdown; 22 | 23 | public TooltipTrigger 24 | tankTypeTooltip; 25 | 26 | public InputField 27 | volumeField; 28 | 29 | public Button 30 | unitsSwitchButton, 31 | maxVolumeButton, 32 | halfVolumeButton, 33 | addButton; 34 | 35 | public Text 36 | unitsLabel; 37 | 38 | public Colorizer 39 | volumeFieldColorizer; 40 | 41 | public TooltipTrigger 42 | volumeFieldTooltip; 43 | 44 | public ITankManager tankManager; 45 | public VolumeUnits currentUnits = VolumeUnits.CUBIC_METERS; 46 | 47 | public void SetTankManager(ITankManager newTankManager) 48 | { 49 | if(newTankManager == tankManager) 50 | return; 51 | tankManager = newTankManager; 52 | if(tankManager == null) 53 | return; 54 | UpdateTankTypes(); 55 | } 56 | 57 | private void Awake() 58 | { 59 | updateUnitsLabel(); 60 | tankTypeDropdown.onValueChanged.AddListener(updateTankTypeDropdownTooltip); 61 | volumeField.onValueChanged.AddListener(onVolumeChange); 62 | unitsSwitchButton.onClick.AddListener(onUnitsSwitch); 63 | maxVolumeButton.onClick.AddListener(setMaxVolume); 64 | halfVolumeButton.onClick.AddListener(setHalfVolume); 65 | addButton.onClick.AddListener(addTank); 66 | volumeNotOk("Enter the volume to create a new tank"); 67 | } 68 | 69 | private void OnDestroy() 70 | { 71 | tankTypeDropdown.onValueChanged.RemoveAllListeners(); 72 | volumeField.onValueChanged.RemoveAllListeners(); 73 | unitsSwitchButton.onClick.RemoveAllListeners(); 74 | maxVolumeButton.onClick.RemoveAllListeners(); 75 | halfVolumeButton.onClick.RemoveAllListeners(); 76 | addButton.onClick.RemoveAllListeners(); 77 | } 78 | 79 | private float partsToVolume(float value) => tankManager.AvailableVolume * value; 80 | 81 | private float volumeToParts(float value) => 82 | tankManager.AvailableVolume > 0 83 | ? value / tankManager.AvailableVolume 84 | : 0; 85 | 86 | private string tankType => tankManager.SupportedTypes[tankTypeDropdown.value]; 87 | 88 | private void onUnitsSwitch() 89 | { 90 | var oldUnits = currentUnits; 91 | currentUnits = (VolumeUnits)(((int)currentUnits + 1) % numUnits); 92 | updateUnitsLabel(); 93 | if(string.IsNullOrEmpty(volumeField.text) || !float.TryParse(volumeField.text, out var volume)) 94 | return; 95 | // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault 96 | switch(currentUnits) 97 | { 98 | case VolumeUnits.CUBIC_METERS when oldUnits == VolumeUnits.PARTS: 99 | setVolume(volume / 100); 100 | break; 101 | case VolumeUnits.PARTS when oldUnits == VolumeUnits.CUBIC_METERS: 102 | setVolume(volumeToParts(volume)); 103 | break; 104 | } 105 | } 106 | 107 | private void updateUnitsLabel() 108 | { 109 | unitsLabel.text = unitNames[currentUnits]; 110 | } 111 | 112 | public void UpdateTankTypes() 113 | { 114 | if(tankManager == null) 115 | return; 116 | tankTypeDropdown.SetOptionsSafe(UI_Utils.namesToOptions(tankManager.SupportedTypes)); 117 | updateTankTypeDropdownTooltip(tankTypeDropdown.value); 118 | } 119 | 120 | private void updateTankTypeDropdownTooltip(int index) => 121 | tankTypeTooltip.SetText(tankManager.GetTypeInfo(tankManager.SupportedTypes[index])); 122 | 123 | private void setMaxVolume() => setVolume(1, true); 124 | 125 | private void setHalfVolume() => setVolume(0.5f, true); 126 | 127 | private void setVolume(float part, bool updateState = false) 128 | { 129 | var newVolume = currentUnits == VolumeUnits.CUBIC_METERS 130 | ? partsToVolume(part) 131 | : part * 100; 132 | volumeField.SetTextWithoutNotify(newVolume.ToString("G9")); 133 | if(!updateState) 134 | return; 135 | if(tankManager.AvailableVolume > 0) 136 | volumeOk(tankManager.OnVolumeChanged(tankType, 137 | currentUnits == VolumeUnits.CUBIC_METERS 138 | ? newVolume 139 | : partsToVolume(part))); 140 | else 141 | volumeNotOk("No free space left"); 142 | } 143 | 144 | 145 | private void volumeNotOk(string error) 146 | { 147 | volumeFieldColorizer.SetColor(Colors.Danger); 148 | volumeFieldTooltip.SetText(error); 149 | addButton.SetInteractable(false); 150 | } 151 | 152 | private void volumeOk(string tooltip = null) 153 | { 154 | volumeFieldColorizer.SetColor(Colors.Neutral); 155 | volumeFieldTooltip.SetText(tooltip ?? "Volume of the new tank"); 156 | addButton.SetInteractable(true); 157 | } 158 | 159 | private void onVolumeChange(string value) 160 | { 161 | if(!float.TryParse(value, out var newValue)) 162 | { 163 | volumeNotOk("Entered value is not a number"); 164 | return; 165 | } 166 | if(newValue <= 0) 167 | { 168 | volumeNotOk("Enter positive number"); 169 | return; 170 | } 171 | string info = null; 172 | // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault 173 | switch(currentUnits) 174 | { 175 | case VolumeUnits.CUBIC_METERS: 176 | if(newValue > tankManager.AvailableVolume) 177 | { 178 | volumeNotOk("Entered volume is greater than the available volume"); 179 | return; 180 | } 181 | info = tankManager.OnVolumeChanged(tankType, newValue); 182 | break; 183 | case VolumeUnits.PARTS: 184 | if(newValue > 100) 185 | { 186 | volumeNotOk("Entered volume is greater than the available volume"); 187 | return; 188 | } 189 | info = tankManager.OnVolumeChanged(tankType, partsToVolume(newValue / 100)); 190 | break; 191 | } 192 | volumeOk(info); 193 | } 194 | 195 | private void addTank() 196 | { 197 | if(!float.TryParse(volumeField.text, out var tankVolume)) 198 | return; 199 | if(currentUnits == VolumeUnits.PARTS) 200 | tankVolume = Mathf.Clamp(partsToVolume(tankVolume / 100), 201 | 0, 202 | tankManager.AvailableVolume); 203 | if(!tankManager.AddTank(tankType, tankVolume)) 204 | return; 205 | volumeField.SetTextWithoutNotify(""); 206 | addButton.SetInteractable(false); 207 | managerUI.UpdateDisplay(); 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /CC.UI/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | // General Information about an assembly is controlled through the following 4 | // set of attributes. Change these attribute values to modify the information 5 | // associated with an assembly. 6 | [assembly: AssemblyTitle("CC.UI")] 7 | [assembly: AssemblyDescription("UI logic assembly")] 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("CC.UI")] 11 | [assembly: AssemblyCopyright("Copyright © Allis Tauri 2020")] 12 | [assembly: AssemblyTrademark("")] 13 | [assembly: AssemblyCulture("")] 14 | 15 | // Version information for an assembly consists of the following four values: 16 | // 17 | // Major Version 18 | // Minor Version 19 | // Build Number 20 | // Revision 21 | // 22 | // You can specify all the values or you can default the Build and Revision Numbers 23 | // by using the '*' as shown below: 24 | // [assembly: AssemblyVersion("1.0.*")] 25 | #if NIGHTBUILD 26 | [assembly: AssemblyVersion("1.0.*")] 27 | #else 28 | [assembly: AssemblyVersion("1.0.0.0")] 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /CC.UI/Assets/ConfigurableContainers.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f9188a84a24046d7beab5a833b33c22 3 | timeCreated: 1541940155 4 | licenseType: Free 5 | DefaultImporter: 6 | externalObjects: {} 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /CC.UI/Assets/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ecb38cd66d8a492bbca117c22b62f03 3 | folderAsset: yes 4 | timeCreated: 1542002145 5 | licenseType: Free 6 | DefaultImporter: 7 | externalObjects: {} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /CC.UI/Assets/Prefabs/TankControls.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 745de9f96f0d14ff198644051c2d750f 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: cc_ui.bundle 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /CC.UI/Assets/Prefabs/TankManagerUI.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c932d60b9a184fa592392518f4bfb41 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: cc_ui.bundle 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /CC.UI/Assets/icons.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c1e5a23a39c23fa3b4bea2d4d4ac036 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /CC.UI/CC.UI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3E7AA3AB-1064-4A2E-9D8F-0E20B83A2249} 8 | Library 9 | CC.UI 10 | CC.UI 11 | v4.8 12 | Properties 13 | 512 14 | 7.3 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | ..\..\Unity\Assets\Plugins 22 | DEBUG; 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | true 29 | ..\..\Unity\Assets\Plugins 30 | prompt 31 | 4 32 | false 33 | 34 | 35 | ..\..\Unity\Assets\Plugins 36 | NIGHTBUILD 37 | true 38 | 39 | 40 | 41 | ..\..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\System.dll 42 | False 43 | 44 | 45 | ..\..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\System.Core.dll 46 | False 47 | 48 | 49 | ..\..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.dll 50 | False 51 | 52 | 53 | ..\..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.CoreModule.dll 54 | False 55 | 56 | 57 | ..\..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.UI.dll 58 | False 59 | 60 | 61 | 62 | 63 | {0b711e55-8312-144f-53ad-eda5a8cee04a} 64 | AT_Utils.UI 65 | False 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CC.UI/Interfaces/ITankInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CC.UI 4 | { 5 | public interface ITankInfo 6 | { 7 | ITankManager Manager { get; } 8 | string TankType { get; } 9 | 10 | IList SupportedResources { get; } 11 | IList SupportedTypes { get; } 12 | string CurrentResource { get; } 13 | bool Valid { get; } 14 | 15 | float Volume { get; } 16 | 17 | double Amount { get; } 18 | double MaxAmount { get; } 19 | float ResourceDensity { get; } 20 | 21 | 22 | float ResourceAmountInVolume(float volume); 23 | float VolumeForResourceAmount(float amount); 24 | void SetVolume(float volume, bool update_amount); 25 | void ChangeTankType(string tankTypeName); 26 | void ChangeResource(string resourceName); 27 | void SetAmount(float newAmount); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CC.UI/Interfaces/ITankManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CC.UI 4 | { 5 | public interface ITankManagerCapabilities 6 | { 7 | bool AddRemoveEnabled { get; } 8 | bool ConfirmRemove { get; } 9 | bool TypeChangeEnabled { get; } 10 | bool VolumeChangeEnabled { get; } 11 | bool FillEnabled { get; } 12 | bool EmptyEnabled { get; } 13 | } 14 | 15 | public interface ITankManager 16 | { 17 | string Title { get; } 18 | IList SupportedTypes { get; } 19 | IList SupportedTankConfigs { get; } 20 | float Volume { get; } 21 | float AvailableVolume { get; } 22 | IReadOnlyCollection Tanks { get; } 23 | ITankManagerCapabilities Capabilities { get; } 24 | 25 | string OnVolumeChanged(string tankType, float volume); 26 | 27 | string GetTypeInfo(string tankType); 28 | 29 | bool AddTank(string tankType, float volume); 30 | bool RemoveTank(ITankInfo tank); 31 | 32 | bool AddTankConfig(string configName); 33 | bool RemoveTankConfig(string configName); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CC.UI/TankConfigsControl.cs: -------------------------------------------------------------------------------- 1 | using AT_Utils.UI; 2 | using UnityEngine.Events; 3 | using UnityEngine.UI; 4 | 5 | namespace CC.UI 6 | { 7 | public class TankConfigsControl : TankManagerUIPart 8 | { 9 | public InputField 10 | configNameField; 11 | 12 | public Dropdown 13 | configsDropdown; 14 | 15 | public TooltipTrigger 16 | configsDropdownTooltip; 17 | 18 | public Button 19 | addConfigButton, 20 | updateConfigButton, 21 | deleteConfigButton; 22 | 23 | public AddTankControl addTankControl; 24 | 25 | private bool addUpdateEnabled; 26 | 27 | private ITankManager tankManager; 28 | 29 | private void Awake() 30 | { 31 | configsDropdown.onValueChanged.AddListener(updateConfigsDropdownTooltip); 32 | addConfigButton.onClick.AddListener(onAddConfig); 33 | updateConfigButton.onClick.AddListener(onUpdateConfig); 34 | deleteConfigButton.onClick.AddListener(onDeleteConfig); 35 | configNameField.onValueChanged.AddListener(onConfigNameChanged); 36 | EnableControls(false); 37 | } 38 | 39 | private void OnDestroy() 40 | { 41 | configsDropdown.onValueChanged.RemoveAllListeners(); 42 | addConfigButton.onClick.RemoveAllListeners(); 43 | updateConfigButton.onClick.RemoveAllListeners(); 44 | deleteConfigButton.onClick.RemoveAllListeners(); 45 | configNameField.onValueChanged.RemoveAllListeners(); 46 | } 47 | 48 | public void EnableControls(bool enable) 49 | { 50 | addUpdateEnabled = enable; 51 | updateControls(); 52 | } 53 | 54 | private void updateControls() 55 | { 56 | var noDialogOpen = !DialogFactory.ContextIsActive(this); 57 | addConfigButton.SetInteractable(addUpdateEnabled 58 | && noDialogOpen 59 | && !string.IsNullOrEmpty(configNameField.text)); 60 | updateConfigButton.SetInteractable(addUpdateEnabled 61 | && noDialogOpen); 62 | deleteConfigButton.SetInteractable(noDialogOpen 63 | && tankManager != null 64 | && tankManager.SupportedTankConfigs.Count > 0); 65 | configsDropdown.SetInteractable(noDialogOpen); 66 | configNameField.SetInteractable(noDialogOpen); 67 | } 68 | 69 | public void SetTankManager(ITankManager manager) 70 | { 71 | if(tankManager == manager) 72 | return; 73 | tankManager = manager; 74 | if(tankManager == null) 75 | return; 76 | updateConfigsDropdown(); 77 | EnableControls(tankManager.Tanks.Count > 0); 78 | } 79 | 80 | private void updateConfigsDropdown() 81 | { 82 | configsDropdown.SetOptionsSafe(UI_Utils.namesToOptions(tankManager.SupportedTankConfigs, false)); 83 | updateConfigsDropdownTooltip(configsDropdown.value); 84 | addTankControl.UpdateTankTypes(); 85 | } 86 | 87 | private void updateConfigsDropdownTooltip(int index) 88 | { 89 | if(index >= 0 && index < tankManager.SupportedTankConfigs.Count) 90 | configsDropdownTooltip.SetText(tankManager.GetTypeInfo(tankManager.SupportedTankConfigs[index])); 91 | else 92 | configsDropdownTooltip.SetText("Select tank preset to edit"); 93 | } 94 | 95 | private void onConfigNameChanged(string newConfigName) => 96 | addConfigButton.SetInteractable(addUpdateEnabled && !string.IsNullOrEmpty(newConfigName)); 97 | 98 | private void onUpdateConfig() => updateConfig(tankManager.SupportedTankConfigs[configsDropdown.value]); 99 | 100 | private void updateConfig(string tankConfig, UnityAction onSuccess = null) 101 | { 102 | DialogFactory.Danger($"Are you sure you want to {Colors.Warning.Tag("overwrite")} " 103 | + $"the {Colors.Selected1.Tag(tankConfig)} preset?", 104 | () => 105 | { 106 | if(!tankManager.AddTankConfig(tankConfig)) 107 | return; 108 | updateConfigsDropdown(); 109 | onSuccess?.Invoke(); 110 | }, 111 | onDestroy: updateControls, 112 | context: this); 113 | updateControls(); 114 | } 115 | 116 | private void onAddConfig() 117 | { 118 | var tankConfig = configNameField.text; 119 | if(string.IsNullOrEmpty(tankConfig)) 120 | return; 121 | if(tankManager.SupportedTankConfigs.Contains(tankConfig)) 122 | updateConfig(tankConfig, () => configNameField.text = ""); 123 | else if(tankManager.AddTankConfig(tankConfig)) 124 | { 125 | configNameField.text = ""; 126 | updateConfigsDropdown(); 127 | } 128 | } 129 | 130 | private void onDeleteConfig() 131 | { 132 | var tankConfig = tankManager.SupportedTankConfigs[configsDropdown.value]; 133 | DialogFactory.Danger($"Are you sure you want to {Colors.Danger.Tag("delete")} " 134 | + $"the {Colors.Selected1.Tag(tankConfig)} preset?", 135 | () => 136 | { 137 | if(tankManager.RemoveTankConfig(tankConfig)) 138 | updateConfigsDropdown(); 139 | }, 140 | onDestroy: updateControls, 141 | context: this); 142 | updateControls(); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /CC.UI/TankControlsUI.cs: -------------------------------------------------------------------------------- 1 | using AT_Utils.UI; 2 | using UnityEngine.Events; 3 | using UnityEngine.UI; 4 | 5 | namespace CC.UI 6 | { 7 | public class TankControlsUI : TankManagerUIPart 8 | { 9 | public Button 10 | deleteButton, 11 | fullTankButton, 12 | emptyTankButton, 13 | editVolumeButton, 14 | editMaxAmountButton, 15 | editMaxMassButton; 16 | 17 | public Text 18 | resourceVolume, 19 | resourceMaxAmount, 20 | resourceAmount, 21 | resourceMaxMass, 22 | resourceMass, 23 | tankFullness; 24 | 25 | public Dropdown 26 | tankTypeDropdown, 27 | resourceDropdown; 28 | 29 | public TooltipTrigger 30 | tankTypeTooltip; 31 | 32 | public Colorizer 33 | resourceAmountColorizer; 34 | 35 | public PanelledUI 36 | volumeDisplay; 37 | 38 | public FloatController 39 | volumeEditor; 40 | 41 | private ITankInfo tank; 42 | 43 | private void updateResourcesDropdown() => 44 | resourceDropdown.options = UI_Utils.namesToOptions(tank.SupportedResources); 45 | 46 | private void updateTankTypeDropdownTooltip(string tankType) => 47 | tankTypeTooltip.SetText(tank.Manager.GetTypeInfo(tankType)); 48 | 49 | public void SetTank(ITankInfo newTank) 50 | { 51 | if(newTank == tank) 52 | return; 53 | tank = newTank; 54 | if(tank == null) 55 | return; 56 | tankTypeDropdown.SetOptionsSafe(UI_Utils.namesToOptions(tank.SupportedTypes)); 57 | updateTankTypeDropdownTooltip(tank.SupportedTypes[tankTypeDropdown.value]); 58 | updateResourcesDropdown(); 59 | UpdateDisplay(); 60 | } 61 | 62 | public void UpdateDisplay() 63 | { 64 | tankTypeDropdown.SetInteractable(tank.Manager.Capabilities.TypeChangeEnabled); 65 | editVolumeButton.SetInteractable(tank.Manager.Capabilities.VolumeChangeEnabled); 66 | editMaxAmountButton.SetInteractable(editVolumeButton.interactable); 67 | editMaxMassButton.SetInteractable(editVolumeButton.interactable); 68 | deleteButton.gameObject.SetActive(tank.Manager.Capabilities.AddRemoveEnabled); 69 | resourceVolume.text = FormatUtils.formatVolume(tank.Volume); 70 | if(tank.Valid) 71 | { 72 | editMaxAmountButton.gameObject.SetActive(true); 73 | tankFullness.gameObject.SetActive(true); 74 | fullTankButton.gameObject.SetActive(tank.Manager.Capabilities.FillEnabled); 75 | emptyTankButton.gameObject.SetActive(tank.Manager.Capabilities.EmptyEnabled); 76 | resourceMaxAmount.text = FormatUtils.formatBigValue((float)tank.MaxAmount, "u"); 77 | resourceAmount.text = FormatUtils.formatBigValue((float)tank.Amount, "u"); 78 | tankFullness.text = (tank.Amount / tank.MaxAmount).ToString("P1"); 79 | resourceAmountColorizer.SetColor(Colors.Selected1); 80 | if(tank.ResourceDensity > 0) 81 | { 82 | editMaxMassButton.gameObject.SetActive(true); 83 | resourceMass.gameObject.SetActive(true); 84 | resourceMaxMass.text = FormatUtils.formatMass((float)(tank.MaxAmount * tank.ResourceDensity)); 85 | resourceMass.text = FormatUtils.formatMass((float)(tank.Amount * tank.ResourceDensity)); 86 | } 87 | else 88 | { 89 | editMaxMassButton.gameObject.SetActive(false); 90 | resourceMass.gameObject.SetActive(false); 91 | } 92 | } 93 | else 94 | { 95 | editMaxAmountButton.gameObject.SetActive(false); 96 | editMaxMassButton.gameObject.SetActive(false); 97 | resourceMass.gameObject.SetActive(false); 98 | tankFullness.gameObject.SetActive(false); 99 | fullTankButton.gameObject.SetActive(false); 100 | emptyTankButton.gameObject.SetActive(false); 101 | resourceAmount.text = "TANK CONFIGURATION IS INVALID"; 102 | resourceAmountColorizer.SetColor(Colors.Danger); 103 | } 104 | var resourcesDropdownUpdated = false; 105 | if(!string.IsNullOrEmpty(tank.TankType) 106 | && (tankTypeDropdown.value >= tank.SupportedTypes.Count 107 | || tank.TankType != tank.SupportedTypes[tankTypeDropdown.value])) 108 | { 109 | tankTypeDropdown.SetValueWithoutNotify(tank.SupportedTypes.IndexOf(tank.TankType)); 110 | updateTankTypeDropdownTooltip(tank.TankType); 111 | updateResourcesDropdown(); 112 | resourcesDropdownUpdated = true; 113 | } 114 | // ReSharper disable once InvertIf 115 | if(!string.IsNullOrEmpty(tank.CurrentResource) 116 | && (resourceDropdown.value >= tank.SupportedResources.Count 117 | || tank.CurrentResource != tank.SupportedResources[resourceDropdown.value])) 118 | { 119 | if(!resourcesDropdownUpdated) 120 | updateResourcesDropdown(); 121 | resourceDropdown.SetValueWithoutNotify(tank.SupportedResources.IndexOf(tank.CurrentResource)); 122 | } 123 | } 124 | 125 | private void Awake() 126 | { 127 | volumeDisplay.SetActive(true); 128 | volumeEditor.SetActive(false); 129 | editVolumeButton.onClick.AddListener(showVolumeEditor); 130 | editMaxAmountButton.onClick.AddListener(showMaxAmountEditor); 131 | editMaxMassButton.onClick.AddListener(showMaxMassEditor); 132 | tankTypeDropdown.onValueChanged.AddListener(changeTankType); 133 | resourceDropdown.onValueChanged.AddListener(changeResource); 134 | fullTankButton.onClick.AddListener(fillTank); 135 | emptyTankButton.onClick.AddListener(emptyTank); 136 | deleteButton.onClick.AddListener(onDelete); 137 | } 138 | 139 | private void OnDestroy() 140 | { 141 | editVolumeButton.onClick.RemoveAllListeners(); 142 | editMaxAmountButton.onClick.RemoveAllListeners(); 143 | editMaxMassButton.onClick.RemoveAllListeners(); 144 | tankTypeDropdown.onValueChanged.RemoveAllListeners(); 145 | resourceDropdown.onValueChanged.RemoveAllListeners(); 146 | fullTankButton.onClick.RemoveAllListeners(); 147 | emptyTankButton.onClick.RemoveAllListeners(); 148 | deleteButton.onClick.RemoveAllListeners(); 149 | } 150 | 151 | private void onDelete() 152 | { 153 | if(tank.Manager.Capabilities.ConfirmRemove) 154 | DialogFactory 155 | .Danger($"Are you sure you want to {Colors.Danger.Tag("delete")} this tank?", 156 | deleteSelf); 157 | else 158 | deleteSelf(); 159 | } 160 | 161 | private void deleteSelf() 162 | { 163 | if(!tank.Manager.RemoveTank(tank)) 164 | return; 165 | if(managerUI != null) 166 | managerUI.UpdateDisplay(); 167 | else 168 | Destroy(gameObject); 169 | } 170 | 171 | private void hideEditor() 172 | { 173 | volumeEditor.onDoneEditing.RemoveAllListeners(); 174 | volumeEditor.SetActive(false); 175 | volumeDisplay.SetActive(true); 176 | } 177 | 178 | private void showEditor(string units, float value, float max, UnityAction onDone) 179 | { 180 | volumeEditor.suffix.text = units; 181 | volumeEditor.Max = max; 182 | volumeEditor.SetStep(volumeEditor.Max / 10); 183 | volumeEditor.SetValueWithoutNotify(value); 184 | volumeEditor.onDoneEditing.AddListener(onDone); 185 | volumeDisplay.SetActive(false); 186 | volumeEditor.SetActive(true); 187 | } 188 | 189 | private void showVolumeEditor() 190 | { 191 | if(tank == null) 192 | return; 193 | showEditor( 194 | "m3", 195 | tank.Volume, 196 | tank.Volume + tank.Manager.AvailableVolume, 197 | changeTankVolume 198 | ); 199 | } 200 | 201 | private void changeTankVolume(float newVolume) 202 | { 203 | if(tank == null) 204 | return; 205 | tank.SetVolume(newVolume, true); 206 | hideEditor(); 207 | UpdateDisplay(); 208 | } 209 | 210 | private void showMaxAmountEditor() 211 | { 212 | if(tank == null) 213 | return; 214 | showEditor( 215 | "u", 216 | (float)tank.MaxAmount, 217 | tank.ResourceAmountInVolume(tank.Volume + tank.Manager.AvailableVolume), 218 | changeTankMaxAmount 219 | ); 220 | } 221 | 222 | private void changeTankMaxAmount(float newMaxAmount) 223 | { 224 | if(tank == null) 225 | return; 226 | changeTankVolume(tank.VolumeForResourceAmount(newMaxAmount)); 227 | } 228 | 229 | private void showMaxMassEditor() 230 | { 231 | if(tank == null) 232 | return; 233 | showEditor( 234 | "t", 235 | (float)(tank.MaxAmount * tank.ResourceDensity), 236 | tank.ResourceAmountInVolume(tank.Volume + tank.Manager.AvailableVolume) * tank.ResourceDensity, 237 | changeTankMaxMass 238 | ); 239 | } 240 | 241 | private void changeTankMaxMass(float newMaxMass) 242 | { 243 | if(tank == null) 244 | return; 245 | changeTankMaxAmount(newMaxMass / tank.ResourceDensity); 246 | } 247 | 248 | private void fillTank() 249 | { 250 | if(tank == null) 251 | return; 252 | tank.SetAmount((float)tank.MaxAmount); 253 | UpdateDisplay(); 254 | } 255 | 256 | private void emptyTank() 257 | { 258 | if(tank == null) 259 | return; 260 | tank.SetAmount(0); 261 | UpdateDisplay(); 262 | } 263 | 264 | private void changeTankType(int index) 265 | { 266 | if(tank == null) 267 | return; 268 | var tankType = tank.SupportedTypes[index]; 269 | tank.ChangeTankType(tankType); 270 | updateTankTypeDropdownTooltip(tankType); 271 | updateResourcesDropdown(); 272 | UpdateDisplay(); 273 | } 274 | 275 | private void changeResource(int index) 276 | { 277 | if(tank == null) 278 | return; 279 | tank.ChangeResource(tank.SupportedResources[index]); 280 | UpdateDisplay(); 281 | } 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /CC.UI/TankManagerUI.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using AT_Utils.UI; 4 | using UnityEngine; 5 | using UnityEngine.UI; 6 | 7 | namespace CC.UI 8 | { 9 | public class TankManagerUI : ScreenBoundRect 10 | { 11 | public int 12 | maxTitleLength = 50; 13 | 14 | public AddTankControl 15 | addTankControl; 16 | 17 | public TankConfigsControl 18 | tankConfigsControl; 19 | 20 | public Text 21 | partTitleLabel, 22 | volumeLabel; 23 | 24 | public Button 25 | closeButton, 26 | colorSettingsButton; 27 | 28 | public RectTransform 29 | tanksScroll; 30 | 31 | public GameObject 32 | tankControlPrefab; 33 | 34 | private ITankManager tankManager; 35 | public Dictionary tankControls = new Dictionary(); 36 | 37 | public void SetTankManager(ITankManager newTankManager) 38 | { 39 | if(newTankManager == tankManager) 40 | return; 41 | foreach(var t in tankControls.Values) 42 | Destroy(t.gameObject); 43 | tankControls.Clear(); 44 | tankManager = newTankManager; 45 | addTankControl.SetTankManager(tankManager); 46 | tankConfigsControl.SetTankManager(tankManager); 47 | if(tankManager == null) 48 | return; 49 | UpdateDisplay(); 50 | } 51 | 52 | public void UpdateDisplay() 53 | { 54 | var title = tankManager.Title; 55 | partTitleLabel.text = title.Length <= maxTitleLength + 3 56 | ? title 57 | : $"{title.Substring(0, maxTitleLength)}..."; 58 | volumeLabel.text = 59 | $"{FormatUtils.formatVolume(tankManager.AvailableVolume)} / {FormatUtils.formatVolume(tankManager.Volume)}"; 60 | addTankControl.gameObject.SetActive(tankManager.Capabilities.AddRemoveEnabled); 61 | tankConfigsControl.gameObject.SetActive(tankManager.Capabilities.AddRemoveEnabled); 62 | updateTankControls(); 63 | } 64 | 65 | private void updateTankControls() 66 | { 67 | var newTanks = new HashSet(); 68 | foreach(var tank in tankManager.Tanks) 69 | { 70 | newTanks.Add(tank); 71 | if(tankControls.ContainsKey(tank)) 72 | continue; 73 | var newTankControlObj = Instantiate(tankControlPrefab, tanksScroll); 74 | if(newTankControlObj == null) 75 | { 76 | Debug.LogError($"Unable to instantiate prefab: {tankControlPrefab}"); 77 | continue; 78 | } 79 | newTankControlObj.transform.SetAsLastSibling(); 80 | var newTankControl = newTankControlObj.GetComponent(); 81 | if(newTankControl == null) 82 | { 83 | Debug.LogError($"No {nameof(TankControlsUI)} in prefab {tankControlPrefab}"); 84 | continue; 85 | } 86 | newTankControl.managerUI = this; 87 | newTankControl.SetTank(tank); 88 | tankControls.Add(tank, newTankControl); 89 | } 90 | foreach(var tank in tankControls.ToList()) 91 | { 92 | if(newTanks.Contains(tank.Key)) 93 | { 94 | tank.Value.UpdateDisplay(); 95 | continue; 96 | } 97 | Destroy(tank.Value.gameObject); 98 | tankControls.Remove(tank.Key); 99 | } 100 | tankConfigsControl.EnableControls(tankManager.Tanks.Count > 0); 101 | } 102 | 103 | #if DEBUG 104 | protected override void Start() 105 | { 106 | base.Start(); 107 | if(Application.isEditor) 108 | SetTankManager(new TestTankManager()); 109 | } 110 | #endif 111 | } 112 | 113 | public class TankManagerUIPart : MonoBehaviour 114 | { 115 | public TankManagerUI managerUI; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /CC.UI/TestTankInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | namespace CC.UI 7 | { 8 | #if DEBUG 9 | public class TestTankManager : ITankManager 10 | { 11 | public string Title { get; } 12 | public IList SupportedTypes { get; } 13 | public IList SupportedTankConfigs { get; } 14 | public float Volume { get; } 15 | public float AvailableVolume { get; private set; } 16 | public float AvailableVolumePercent { get; private set; } 17 | 18 | private readonly List Tanks; 19 | IReadOnlyCollection ITankManager.Tanks => Tanks; 20 | 21 | private class TestTankManagerCapabilities : ITankManagerCapabilities 22 | { 23 | public bool AddRemoveEnabled => true; 24 | public bool ConfirmRemove => true; 25 | public bool TypeChangeEnabled => true; 26 | public bool VolumeChangeEnabled => true; 27 | public bool FillEnabled => true; 28 | public bool EmptyEnabled => true; 29 | } 30 | 31 | private readonly TestTankManagerCapabilities Capabilities = new TestTankManagerCapabilities(); 32 | ITankManagerCapabilities ITankManager.Capabilities => Capabilities; 33 | 34 | public void UpdateAvailableVolume() 35 | { 36 | AvailableVolume = Volume - Tanks.Aggregate(0f, (res, t) => res + t.Volume); 37 | AvailableVolumePercent = AvailableVolume / Volume * 100; 38 | } 39 | 40 | public string OnVolumeChanged(string tankType, float volume) => null; 41 | 42 | public string GetTypeInfo(string tankType) => $"{tankType}: This is a test info."; 43 | 44 | public bool AddTank(string tankType, float volume) 45 | { 46 | var tankInfo = new TestTankInfo(tankType, Mathf.Min(volume, AvailableVolume), this); 47 | Tanks.Add(tankInfo); 48 | UpdateAvailableVolume(); 49 | return true; 50 | } 51 | 52 | public bool RemoveTank(ITankInfo tank) => Tanks.Remove(tank as TestTankInfo); 53 | 54 | public bool AddTankConfig(string configName) 55 | { 56 | if(!SupportedTankConfigs.Contains(configName)) 57 | SupportedTankConfigs.Add(configName); 58 | return true; 59 | } 60 | 61 | public bool RemoveTankConfig(string configName) => SupportedTankConfigs.Remove(configName); 62 | 63 | public TestTankManager() 64 | { 65 | SupportedTypes = new List 66 | { 67 | "LiquidChemicals", 68 | "Components", 69 | "Soil", 70 | "Type 1", 71 | "Type 2", 72 | "Type 3", 73 | "Type 4", 74 | "Type 5" 75 | }; 76 | SupportedTankConfigs = new List { "LFO", "LoX", "CA" }; 77 | Volume = 15.79089f; 78 | AvailableVolume = Volume; 79 | AvailableVolumePercent = 100; 80 | Tanks = new List(); 81 | Title = "Big Resource Tank - with a long long, very long name indeed!"; 82 | } 83 | } 84 | 85 | public class TestTankInfo : ITankInfo 86 | { 87 | private TestTankManager Manager; 88 | ITankManager ITankInfo.Manager => Manager; 89 | public string TankType { get; private set; } 90 | public IList SupportedResources { get; } 91 | public IList SupportedTypes => Manager.SupportedTypes; 92 | public string CurrentResource { get; private set; } 93 | private float UsefulVolumeRatio { get; } 94 | public float Volume { get; private set; } 95 | public double MaxAmount => ResourceAmountInVolume(Volume); 96 | public double Amount { get; private set; } 97 | private float UnitsPerVolume { get; } 98 | public float ResourceDensity { get; } 99 | public bool Valid => CurrentResource != "Oxidizer"; 100 | public float ResourceAmountInVolume(float volume) => volume * UnitsPerVolume * UsefulVolumeRatio; 101 | 102 | public float VolumeForResourceAmount(float amount) => amount / UnitsPerVolume / UsefulVolumeRatio; 103 | 104 | 105 | public TestTankInfo(string tankType, float volume, TestTankManager manager) 106 | { 107 | Manager = manager; 108 | SupportedResources = new List { "MonoPropellant", "Oxidizer", "MaterialKits", "SpecializedParts" }; 109 | TankType = tankType; 110 | CurrentResource = SupportedResources[0]; 111 | UsefulVolumeRatio = 1; 112 | UnitsPerVolume = 1500f; 113 | ResourceDensity = 0.0012f; 114 | Volume = volume; 115 | Amount = MaxAmount * 0.78f; 116 | } 117 | 118 | public void SetVolume(float volume, bool update_amount) 119 | { 120 | volume = Mathf.Clamp(volume, 0, Manager.Volume); 121 | if(update_amount) 122 | Amount *= volume / Volume; 123 | Volume = volume; 124 | Manager.UpdateAvailableVolume(); 125 | } 126 | 127 | public void ChangeTankType(string tankTypeName) 128 | { 129 | TankType = tankTypeName; 130 | } 131 | 132 | public void ChangeResource(string resourceName) 133 | { 134 | CurrentResource = resourceName; 135 | } 136 | 137 | public void SetAmount(float newAmount) 138 | { 139 | Amount = Math.Min(MaxAmount, newAmount); 140 | } 141 | } 142 | #endif 143 | } 144 | -------------------------------------------------------------------------------- /CC.UI/cc_ui.bundle_bundle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Allis Tauri 4 | allista@gmail.com 5 | 6 | 7 | 8 | 9 | 10 | at_utils_ui.bundle 11 | 12 | -------------------------------------------------------------------------------- /CC.UI/cc_ui.bundle_bundle.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d9d8303196052210bb4dde82f012e83f 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: cc_ui.bundle 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Configurable Containers Change Log 2 | 3 | ## v2.6.2.1 / 2022-04-01 4 | 5 | * Compiled for KSP 1.12.3 6 | * Internal project changes for CI/CD 7 | 8 | ## v2.6.2 9 | 10 | * Compatible with KSP-1.11.1 11 | * UI: using G9 formatter instead of R for better performance 12 | * API: removed `ITankManager.AvailableVolumePercent` 13 | 14 | ## v2.6.1 15 | 16 | * **Parts** 17 | * **Hangar**: allow surface attachment of all the containers 18 | * Fixed CC behaviour in symmetry groups 19 | * Fixed resource amount update when tank volume is changed 20 | (by APR or TweakScale) 21 | * Fixed part cloning when the part is resized by TweakScale 22 | * Fixed UI not showing when the `VolumeConfigs.user` file is absent 23 | * Using bundle shipped with AT_Utils 24 | 25 | ## v2.6.0 - **New UI** 26 | 27 | * **Reimplemented tank manager UI from scratch with uGUI framework** 28 | * **Fixed counterparts rescaling with TweakScale** 29 | * Improved tank types/configs tooltips by emphasizing with bold font 30 | * Minor performance improvements 31 | 32 | ## v2.5.0.1 33 | 34 | * Compiled against KSP-1.10 35 | 36 | ## v2.5.0 37 | 38 | * **Moved CC configs to AT_Utils GameData and removed CC-Core** 39 | * Added resource **max amount and max mass display** 40 | * **Added new patches** 41 | * Dodo Labs - Stockalike Electron 42 | * Mk2 Hypersonic Systems 43 | * Mk-X 44 | * Hyper Propulsion 45 | * **Updated** patches 46 | * BDB 47 | * Mk2 Expansion 48 | * ReStock+ 49 | * Only filter parts with **B9 Part Switch** if it has SUBTYPE with 50 | a tankType defined. This allowed to **add CC to several parts** that 51 | only had mesh/node variants, not the resource switching. **Affects** 52 | * Bluedog Design Bureau 53 | * Mk2 Expansion 54 | * Mk3 Expansion 55 | * Moved hangar resource tanks to FuelTank category 56 | * Removed the OPT patch since OPT Reconfig provides its own now 57 | * Minor fixes and improvements 58 | * Updated the list of supported mods in netkan 59 | 60 | ## v2.4.8.3 61 | 62 | * Compiled against AT_Utils 1.9.3 63 | 64 | ## v2.4.8.2 65 | 66 | * **Compatible with KSP-1.9** 67 | * Compiled against AT_Utils 1.9.2 68 | 69 | ## v2.4.8.1 70 | 71 | * Compiled against AT_Utils 1.9.1 72 | 73 | ## v2.4.8 74 | 75 | * Hangar patch: 76 | * Added a procedural fuel tank made from Procedural Adapter 77 | * In APR ResourceUpdater no longer handles dynamic resources 78 | * Corrected LH2O ratio in CryoEngines tank config 79 | * Added CryoCooling variant of LH2O tank config 80 | * Fixed InvalidOperationException on tank add/remove 81 | 82 | ## v2.4.7.1 83 | 84 | * Updated AT_Utils 85 | 86 | ## v2.4.7 87 | 88 | * Supports KSP-1.8.1 89 | * IFS is fully compatible with CC patches 90 | * Rebalanced "Snacks and Soil" tank config to keep 1u food to 1u soil 91 | as suggested in #30 by @LouisCyfer 92 | * Small performance improvements. 93 | 94 | ## v2.4.6 95 | 96 | * **Added patches** 97 | * Mining Expansion 98 | * Kerbal Planetary Base System 99 | * ReStock+ 100 | * Streamline - Engines and Tanks 101 | * **Updated patches** 102 | * Bluedog Design Bureau 103 | * Mk2 Expansion 104 | * Mk3 Expansion 105 | * Near Future Propulsion 106 | * Mk2.5 Spaceplane Parts 107 | * Squad 108 | * Corrected a typo in squad xenon tanks' names 109 | 110 | ## v2.4.5 111 | 112 | * Added ability to change UI color scheme at runtime 113 | * Added "C" button to the tank manager window titlebar which summons the Color Scheme dialog 114 | 115 | ## v2.4.4 116 | 117 | * Compatible with KSP-1.7 118 | * Fixed MM Warnings (multiple NEEDS) 119 | * Fixed in-editor part cloning/symmetry bug (issue #31) 120 | 121 | ## v2.4.3.2 -4 122 | 123 | * Version bumps due to updates of AT_Utils. 124 | 125 | ## v2.4.3.1 126 | 127 | * SpecializedParts are also used by GC now 128 | 129 | ## v2.4.3 130 | 131 | * Added patches for Bluedog Design Bureau and Making History Expansion. 132 | 133 | ## v2.4.2 134 | 135 | * Renamed Resource to CryoResource for clarity and to prevent name clashes. 136 | * Twealscaled tanks retain volume on load. Fixed #22. 137 | * Corrected calculation of ModuleSaveFromPrefab flag. 138 | * Removed support for ProceduralParts =( 139 | * Added SpareParts to Components TankType for DangIt. 140 | * Removed FOR[ConfigurableContainers] stanza, changed ref to KSP 1.4.1 141 | * Updater Squad patch 142 | * Supporting KWRocketryRebalanced. Can't support multiple KWR flavors. 143 | * Well, it's possible with multiple .ckans, but I don't have the time =\ 144 | * Updated patches for Mk2/Mk3Exp, FTPlus, Mk2Plane 145 | 146 | ## v2.4.1.1 147 | 148 | * Fixed Cryogenic/CryoCooling NEEDS, fixed KarbonitePlus requirement for Metal. 149 | * Update TankTypes.cfg 150 | * added Snacks support (Snacks --> Food, Soil --> Soil) 151 | * modified KolonyTools support --> ColonySupplies are visible/usable/transferable even if USI-LS is not installed 152 | * Added Chemicals to LiquidChemicals for KolonyTools. 153 | * Attempt to fix #10 using the patch suggested by @Starwaster. 154 | * Fixed issues: 155 | * 16 - Attempting to change configuration when none exists results in NullReferenceException 156 | * 18 - Tweakscaled tank saved prior to installation of CC gets capacity reset to un-scaled value 157 | * 20 - Lag/freeze when placing tanks in VAB 158 | 159 | ## v2.4.1 160 | 161 | * All tanks except high-pressure now use TankManager. Wings use IncludeTankType to restrict contents to liquid chemicals. 162 | * Updated patches: 163 | * Stock 164 | * FuleTanks+ 165 | * ModularRockeSystems 166 | * NearFuture 167 | * KWRocketry 168 | * Mk3 Expansion 169 | * Added patches: 170 | * Mk2.5 spaceplane parts 171 | * Fuel Tank Expansion 172 | * B9 Procedural Wings 173 | * Added patch for B9 mods **made by ShadyAct** to *IntrusivePatches* optional folder. See the archive structure and the included readme file for details. 174 | * Part info now respects Include/ExcludeTankTypes options. 175 | * CC modules are now properly initialized when they're added to existing parts (in flight) by MM. **This should fix most of incompatibility with other fuel switches.** 176 | 177 | ## v2.4.0.6 178 | 179 | * Compatible with KSP-1.3 180 | * Fixed Metal tank type as pointed out by TheKurgan. 181 | * Removed Plutonium-238 as it is internal resource for USI 182 | 183 | ## v2.4.0.5 184 | 185 | * Corrected CKAN metadata. 186 | * Small bugfixes. 187 | 188 | ## v2.4.0.4 189 | 190 | * Added patch for GPOSpeedFuelPump for time being. 191 | 192 | ## v2.4.0.3 193 | 194 | * Added FindTankType by resource_name method to TankType library. 195 | * Added ForceSwitchResource method to SwitchableTank. 196 | * GroundConstruction will be using MaterialKits, so added it to Components TankType users. 197 | * Use round-trip format for the volume field. 198 | 199 | ## v2.4.0.2 200 | 201 | * Fixed TankManager initialization with disabled AddRemove capability. 202 | * Fixed TankManager initialization using empty config. 203 | * Fixed in-flight tank creation. 204 | 205 | ## v2.4.0.1 206 | 207 | * Added patch for **OPT Spaceplane Parts** made by **octarine-noise** 208 | * Small bugfixes. 209 | 210 | ## v2.4.0 211 | 212 | * Compiled against KSP-1.2.2. 213 | * Added boiloff and active cooling for cryogenic resources based on simple thermodynamics. 214 | * Added CryoCooling tank type. 215 | * Added KSPIE resources to TankTypes.cfg. 216 | * Added tooltips with Info to TankType choosers. 217 | * Replaced Tank Type dropdown list with the LeftRightChooser. 218 | 219 | ## v2.3.1 220 | 221 | * Corrected Cryogenic tank type parameters. 222 | * Fixed Food tank type. 223 | * In Editor automatically remove current resource when trying to switch it or the tank type. 224 | * Fixed Soil TANKTYPE definition. 225 | * Fixed installation directive in CC-Core.netkan 226 | * Fixed ProceduralParts bug and return to VAB bug. Closed #3 and #4. 227 | 228 | ## v2.3.0 229 | 230 | * Added per-tank volume editing and volume definition in % along with m3. 231 | * Added support for: 232 | * **Tweak Scale** 233 | * **Procedural Parts** 234 | * Parts ++with stock resources++ converted: 235 | * Stock 236 | * KW Rocketry 237 | * Mk2 Expansion 238 | * Mk3 Expansion 239 | * SpaceY-Lifters 240 | * SpaceY-Expanded 241 | * Fuel Tanks Plus 242 | * Modular Rocket Systems 243 | * Standard Propulsion Systems 244 | * Near Future Propulsion 245 | * Spherical and Toroidal Tank Pack 246 | * Supported resources: 247 | * Stock 248 | * TAC Life Support 249 | * Extrapalentary Launchapads 250 | * Near Future Propulsion 251 | * All USI 252 | * *Some* of KSPIE 253 | * Different TankTypes can now have different additional mass 254 | * Added Tank Types: 255 | * Battery 256 | * Cryogenic 257 | * Added Tank Setups: 258 | * TAC Life Support -- with food, water and oxigen. Made by **Bit Fiddler**. 259 | * LH2O -- with Liquid Hydrogen and Oxidizer for CryoEngines. 260 | * Corrected unit/volume ratios for: 261 | * Monopropellant 262 | * Argon Gas 263 | * Liquid Hydrogen 264 | * Liquid Methane (which mod uses it?) 265 | * Karbonite 266 | -------------------------------------------------------------------------------- /ConfigurableContainers-Intrusive.netkan: -------------------------------------------------------------------------------- 1 | { 2 | "spec_version" : "v1.4", 3 | "identifier" : "ConfigurableContainers-Intrusive", 4 | "name" : "Configurable Containers Intrusive Patches", 5 | "$kref" : "#/ckan/spacedock/1002", 6 | "abstract" : "This set of patches converts parts that use other fuel switchers to Configurable Containers framework.", 7 | "author" : [ "allista" ], 8 | "license" : "MIT", 9 | 10 | "resources": 11 | { 12 | "homepage" : "http://forum.kerbalspaceprogram.com/index.php?/topic/150104-12-configurable-containers", 13 | "bugtracker" : "https://github.com/allista/ConfigurableContainers/issues", 14 | "repository" : "https://github.com/allista/ConfigurableContainers" 15 | }, 16 | 17 | "depends": 18 | [ 19 | { "name": "ModuleManager" }, 20 | { "name": "AT-Utils" } 21 | ], 22 | 23 | "supports": 24 | [ 25 | { "name": "B9" }, 26 | { "name": "B9AerospaceHX" } 27 | ], 28 | 29 | "install": 30 | [ 31 | { 32 | "file": "IntrusivePatches/GameData/ConfigurableContainers", 33 | "install_to": "GameData" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /ConfigurableContainers.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {BD074812-7105-46D7-A252-53C20DAB698B} 7 | Library 8 | AT_Utils 9 | ConfigurableContainers 10 | v4.8 11 | 12 | 13 | 14 | true 15 | full 16 | false 17 | ..\GameData\000_AT_Utils\Plugins 18 | DEBUG;ENABLE_PROFILER;NIGHTBUILD 19 | prompt 20 | 4 21 | false 22 | 23 | 24 | full 25 | true 26 | ..\GameData\000_AT_Utils\Plugins 27 | prompt 28 | 4 29 | false 30 | 31 | 32 | true 33 | ..\GameData\000_AT_Utils\Plugins 34 | 4 35 | NIGHTBUILD 36 | 37 | 38 | 39 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\System.dll 40 | False 41 | 42 | 43 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\Assembly-CSharp.dll 44 | False 45 | 46 | 47 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\System.Core.dll 48 | False 49 | 50 | 51 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.dll 52 | False 53 | 54 | 55 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\KSPAssets.dll 56 | False 57 | 58 | 59 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\Mono.Cecil.dll 60 | False 61 | 62 | 63 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\System.Xml.dll 64 | False 65 | 66 | 67 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.CoreModule.dll 68 | False 69 | 70 | 71 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.IMGUIModule.dll 72 | False 73 | 74 | 75 | ..\..\KSP-test\KSP_test_1.12.3\KSP_Data\Managed\UnityEngine.UI.dll 76 | False 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | {19ABDD5C-1F12-4D67-B72E-E36071ABFF2C} 97 | AnisotropicPartResizer 98 | False 99 | 100 | 101 | {64CC36A2-0610-4F74-9F31-3D4E22866B7E} 102 | AT_Utils 103 | False 104 | 105 | 106 | {0b711e55-8312-144f-53ad-eda5a8cee04a} 107 | AT_Utils.UI 108 | False 109 | 110 | 111 | {3e7aa3ab-1064-4a2e-9d8f-0e20b83a2249} 112 | CC.UI 113 | True 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /ConfigurableContainers.netkan: -------------------------------------------------------------------------------- 1 | { 2 | "spec_version" : "v1.4", 3 | "identifier" : "ConfigurableContainers", 4 | "$kref" : "#/ckan/spacedock/1002", 5 | "$vref" : "#/ckan/ksp-avc", 6 | "abstract" : "This mod converts all the stock fuel tanks and resource containers so that you can change the resource(s) they hold in Editor and in Flight.", 7 | "author" : [ "allista" ], 8 | "license" : "MIT", 9 | 10 | "resources": 11 | { 12 | "homepage" : "http://forum.kerbalspaceprogram.com/index.php?/topic/150104-12-configurable-containers", 13 | "bugtracker" : "https://github.com/allista/ConfigurableContainers/issues", 14 | "repository" : "https://github.com/allista/ConfigurableContainers" 15 | }, 16 | 17 | "depends": 18 | [ 19 | { "name": "ModuleManager" }, 20 | { "name": "AT-Utils" } 21 | ], 22 | 23 | "suggests": 24 | [ 25 | { "name": "KSP-AVC" }, 26 | { "name": "CommunityResourcePack" } 27 | ], 28 | 29 | "supports": 30 | [ 31 | { "name": "B9-PWings-Fork" }, 32 | { "name": "BluedogDB" }, 33 | { "name": "DodoLabsStockalikeElectron" }, 34 | { "name": "FuelTanksPlus" }, 35 | { "name": "Goodspeed" }, 36 | { "name": "Hangar" }, 37 | { "name": "KWRocketryRebalanced" }, 38 | { "name": "KerbalPlanetaryBaseSystems" }, 39 | { "name": "Mk-X" }, 40 | { "name": "Mk2Expansion" }, 41 | { "name": "Mk3Expansion" }, 42 | { "name": "Mk3HypersonicSystems" }, 43 | { "name": "ModularRocketSystem" }, 44 | { "name": "ModularRocketSystemsLITE" }, 45 | { "name": "MunarIndustriesFTX" }, 46 | { "name": "NearFuturePropulsion" }, 47 | { "name": "OPTReconfig" }, 48 | { "name": "OPTSpacePlaneParts" }, 49 | { "name": "RaginCaucasian" }, 50 | { "name": "ReStockPlus" }, 51 | { "name": "SpaceY-Expanded" }, 52 | { "name": "SpaceY-Lifters" }, 53 | { "name": "StandardPropulsionSystems" }, 54 | { "name": "StockalikeMiningExtension" }, 55 | { "name": "StreamlineEnginesRCSsandfueltanks" }, 56 | { "name": "TALSphericalToroidalPack" }, 57 | { "name": "TweakScale" } 58 | ], 59 | 60 | "conflicts": 61 | [ 62 | { "name": "ModularFuelTanks" }, 63 | { "name": "RealFuels" } 64 | ], 65 | 66 | "install": 67 | [ 68 | { 69 | "file": "GameData/ConfigurableContainers", 70 | "install_to": "GameData" 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /Cryogenics/ActiveCooling.cs: -------------------------------------------------------------------------------- 1 | // ResourceBoiloff.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System; 9 | using JetBrains.Annotations; 10 | 11 | namespace AT_Utils 12 | { 13 | public class ActiveCooling : ResourceBoiloff 14 | { 15 | [UsedImplicitly] public new const string NODE_NAME = "RES_COOLING"; 16 | 17 | [Persistent] public double CoolingEfficiency; 18 | private double Efficiency = 0.17f; 19 | 20 | [Persistent] public bool Enabled = true; 21 | [Persistent] public bool IsCooling; 22 | 23 | private double MaxPower = 10; 24 | 25 | public ActiveCooling(ModuleSwitchableTank tank) : base(tank) { } 26 | 27 | public double PowerConsumptionAt300K 28 | { 29 | get 30 | { 31 | var CoreDeltaT = CoreDeltaTAt300K(out _, out var resThermalMass); 32 | return Math.Min(CoreDeltaT 33 | * resThermalMass 34 | * (300 - boiloffTemperature) 35 | / boiloffTemperature 36 | / Efficiency 37 | / CryogenicsParams.Instance.ElectricCharge2kJ, 38 | MaxPower); 39 | } 40 | } 41 | 42 | /// 43 | /// Converts the amount of heat that needs to be retrieved from the core to the amount of work that is 44 | /// required to transfer that heat to the part's skin. 45 | /// 46 | protected double Q2W => (part.skinTemperature - CoreTemperature) / CoreTemperature / Efficiency; 47 | 48 | public override void SetResource(PartResource res) 49 | { 50 | base.SetResource(res); 51 | if(cryo_info == null) 52 | return; 53 | MaxPower = Math.Min(CryogenicsParams.Instance.MaxSpecificCoolerPower * res.maxAmount * specificHeatCapacity, 54 | CryogenicsParams.Instance.MaxAbsoluteCoolerPower); 55 | Efficiency = cryo_info.CoolingEfficiency; 56 | } 57 | 58 | protected override void UpdateCoreTemperature(double deltaTime) 59 | { 60 | var last_core_temp = CoreTemperature; 61 | base.UpdateCoreTemperature(deltaTime); 62 | IsCooling = false; 63 | if(!Enabled) 64 | return; 65 | if(part.skinTemperature / part.skinMaxTemp > PhysicsGlobals.TemperatureGaugeThreshold) 66 | goto disable; 67 | var temperature_excess = CoreTemperature - boiloffTemperature; 68 | // Utils.Log("Skin.T {}, dTemp {}", part.skinTemperature, temperature_excess);//debug 69 | if(temperature_excess < 0) 70 | { 71 | var electric_charge_needed = Math.Abs(CoreTemperature - last_core_temp) 72 | * resource.amount 73 | * specificHeatCapacity 74 | * Q2W 75 | / CryogenicsParams.Instance.ElectricCharge2kJ; 76 | var electric_charge = electric_charge_needed / deltaTime > MaxPower 77 | ? MaxPower * deltaTime 78 | : electric_charge_needed; 79 | CoolingEfficiency = electric_charge / electric_charge_needed; 80 | // Utils.Log("Would Consume {}/{}, Power {}/{}, Efficiency {}", 81 | // electric_charge, electric_charge_needed, electric_charge/deltaTime, MaxPower, CoolingEfficiency);//debug 82 | return; 83 | } 84 | if(Math.Abs(deltaTime - TimeWarp.fixedDeltaTime) < 1e-5) 85 | { 86 | var q2w = Q2W; 87 | var resThermalMass = resource.amount * specificHeatCapacity; 88 | var electric_charge_needed = 89 | temperature_excess * resThermalMass * q2w / CryogenicsParams.Instance.ElectricCharge2kJ; 90 | if(electric_charge_needed / deltaTime > MaxPower) 91 | electric_charge_needed = MaxPower * deltaTime; 92 | var electric_charge = 93 | part.vessel.RequestResource(part, Utils.ElectricCharge.id, electric_charge_needed, false); 94 | if(electric_charge / electric_charge_needed < CryogenicsParams.Instance.ShutdownThreshold) 95 | { 96 | Utils.Message("Not enough energy, CryoCooler is disabled."); 97 | goto disable; 98 | } 99 | IsCooling = true; 100 | var energy_extracted = electric_charge / q2w * CryogenicsParams.Instance.ElectricCharge2kJ; 101 | var cooled = energy_extracted / resThermalMass; 102 | CoolingEfficiency = cooled / temperature_excess; 103 | CoreTemperature -= cooled; 104 | part.AddSkinThermalFlux(energy_extracted / TimeWarp.fixedDeltaTime); 105 | // Utils.Log("Consumed {}, Power {}/{}, Cooled {}/{}, SkinTempRate {}", 106 | // electric_charge, electric_charge/deltaTime, MaxPower, cooled, temperature_excess);//debug 107 | return; 108 | } 109 | if(CoolingEfficiency > 0) //catch up after being unloaded 110 | { 111 | IsCooling = true; 112 | CoreTemperature -= temperature_excess * CoolingEfficiency; 113 | // Utils.Log("Efficiency {}, Cooled {}/{}", 114 | // CoolingEfficiency, temperature_excess*CoolingEfficiency, temperature_excess);//debug 115 | return; 116 | } 117 | disable: 118 | { 119 | CoolingEfficiency = 0; 120 | IsCooling = false; 121 | Enabled = false; 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Cryogenics/CryogenicsParams.cs: -------------------------------------------------------------------------------- 1 | // CryogenicsParams.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Diagnostics.CodeAnalysis; 11 | 12 | namespace AT_Utils 13 | { 14 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), 15 | SuppressMessage("ReSharper", "ConvertToConstant.Global"), 16 | SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Global")] 17 | public class CryogenicsParams : ConfigNodeObject 18 | { 19 | public new const string NODE_NAME = "CRYOGENICS"; 20 | 21 | private const string config_path = "ConfigurableContainers/Cryogenics/"; 22 | 23 | /// 24 | /// The absolute zero, 0K. 25 | /// 26 | public const double AbsZero = -273.15; 27 | 28 | private static CryogenicsParams instance; 29 | 30 | private readonly Dictionary Resources = new Dictionary(); 31 | 32 | /// 33 | /// How much kJs does 1 electric charge contain? 34 | /// 35 | [Persistent] 36 | public float ElectricCharge2kJ = 10; 37 | 38 | /// 39 | /// Limits energy transfer between the resource volume and the rest of the part. 40 | /// kW/m/K 41 | /// 42 | [Persistent] 43 | public float InsulationConductivity = 1e-3f; 44 | 45 | /// 46 | /// The fraction of the tank's volume that is used for insulation 47 | /// 48 | [Persistent] 49 | public float InsulationVolumeFraction = 0.02f; 50 | 51 | /// 52 | /// Maximum total power consumption of any cooler (Ec/s) 53 | /// 54 | [Persistent] 55 | public float MaxAbsoluteCoolerPower = 500; 56 | 57 | /// 58 | /// Maximum power consumption of a cooler (Ec/s) per unit thermal mass 59 | /// 60 | [Persistent] 61 | public float MaxSpecificCoolerPower = 1; 62 | 63 | /// 64 | /// If the power supply drops below this fraction, the cooler is automatically disabled 65 | /// 66 | [Persistent] 67 | public float ShutdownThreshold = 0.99f; 68 | 69 | /// 70 | /// Used when no VaporizationHeat is provided for a resource to estimate it 71 | /// 72 | [Persistent] 73 | public float SpecificHeat2VaporizationHeat = 1000; 74 | 75 | public static CryogenicsParams Instance 76 | { 77 | get 78 | { 79 | if(instance != null) 80 | return instance; 81 | instance = new CryogenicsParams(); 82 | var node = GameDatabase.Instance.GetConfigNode(config_path + NODE_NAME); 83 | if(node != null) 84 | instance.Load(node); 85 | else 86 | Utils.Log("CryogenicsParams NODE not found: {}", config_path + NODE_NAME); 87 | return instance; 88 | } 89 | } 90 | 91 | /// 92 | /// Retrieve the cryogenic resource info for the given part resource. 93 | /// 94 | /// The cryogenic resource info. 95 | /// The part resource. 96 | public CryoResource GetResource(PartResource r) 97 | { 98 | return Resources.TryGetValue(r.resourceName, out var res) ? res : null; 99 | } 100 | 101 | /// 102 | /// Calculates conductivity of insulation of a given spherical volume. 103 | /// 104 | /// The insulator conductivity in kW/K. 105 | /// Volume of a tank. 106 | public static double GetInsulatorConductivity(double volume) 107 | { 108 | return -Instance.InsulationConductivity 109 | * Math.Pow(48 * Math.PI * Math.PI * volume / Instance.InsulationVolumeFraction, 1 / 3f); 110 | } 111 | 112 | #if DEBUG 113 | public static void Reload() 114 | { 115 | var node = ConfigNode.Load(CustomConfig.GameDataFolder("ConfigurableContainers", "Cryogenics.cfg")); 116 | if(node == null) 117 | { 118 | Utils.Log("Unable to read Cryogenics.cfg"); 119 | return; 120 | } 121 | if(instance == null) 122 | instance = new CryogenicsParams(); 123 | instance.LoadFrom(node); 124 | Utils.Log("CryogenicsParams reloaded:\n{}", instance); 125 | } 126 | #endif 127 | 128 | public override void Load(ConfigNode node) 129 | { 130 | base.Load(node); 131 | Resources.Clear(); 132 | foreach(var n in node.GetNodes(CryoResource.NODE_NAME)) 133 | { 134 | var res = FromConfig(n); 135 | Resources.Add(res.name, res); 136 | } 137 | } 138 | 139 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] 140 | public class CryoResource : ConfigNodeObject 141 | { 142 | // ReSharper disable once MemberHidesStaticFromOuterClass 143 | public new const string NODE_NAME = "RESOURCE"; 144 | [Persistent] public float BoiloffTemperature = 120; 145 | [Persistent] public float CoolingEfficiency = 0.3f; 146 | 147 | [Persistent] public string name = ""; 148 | [Persistent] public float VaporizationHeat = -1; 149 | 150 | public double GetVaporizationHeat(PartResource r) 151 | { 152 | return VaporizationHeat > 0 153 | ? VaporizationHeat 154 | : r.info.specificHeatCapacity * Instance.SpecificHeat2VaporizationHeat; 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /Cryogenics/ResourceBoiloff.cs: -------------------------------------------------------------------------------- 1 | // Boiloff.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System; 9 | using JetBrains.Annotations; 10 | using UnityEngine; 11 | 12 | namespace AT_Utils 13 | { 14 | public class ResourceBoiloff : ConfigNodeObject 15 | { 16 | [UsedImplicitly] public new const string NODE_NAME = "RES_BOILOFF"; 17 | 18 | protected readonly Part part; 19 | protected PartResource resource; 20 | protected CryogenicsParams.CryoResource cryo_info; 21 | private readonly ModuleSwitchableTank tank; 22 | 23 | /// 24 | /// Current temperature of the resource mass. 25 | /// 26 | [Persistent] 27 | public double CoreTemperature = -1; 28 | 29 | /// 30 | /// The last UT the core temperature was updated. 31 | /// 32 | [Persistent] 33 | public double LastUpdateTime = -1; 34 | 35 | /// 36 | /// The temperature (K) at which the boiloff occurs. 37 | /// 38 | protected double boiloffTemperature; 39 | 40 | /// 41 | /// The vaporization heat of the resource per unit. 42 | /// 43 | protected double vaporizationHeat; 44 | 45 | /// 46 | /// The heat capacity of the resource per unit. 47 | /// 48 | protected double specificHeatCapacity; 49 | 50 | /// 51 | /// The insulator conductivity in kW/s. 52 | /// 53 | protected double insulatorConductivity; 54 | 55 | /// 56 | /// This is true if the SetResource is successful, false otherwise. 57 | /// 58 | public bool Valid => cryo_info != null; 59 | 60 | protected double temperatureTransfer( 61 | double deltaTime, 62 | double partThermalMass, 63 | double resThermalMass, 64 | double partT, 65 | double resT, 66 | out double equilibriumT 67 | ) 68 | { 69 | var totalThermalMass = partThermalMass + resThermalMass; 70 | equilibriumT = (partT * partThermalMass + resT * resThermalMass) / totalThermalMass; 71 | return 1 72 | - Math.Exp(deltaTime 73 | * insulatorConductivity 74 | * totalThermalMass 75 | / (partThermalMass + resThermalMass)); 76 | } 77 | 78 | protected double CoreDeltaTAt300K(out double partThermalMass, out double resThermalMass) 79 | { 80 | resThermalMass = resource.amount * specificHeatCapacity; 81 | partThermalMass = part.mass * PhysicsGlobals.StandardSpecificHeatCapacity * part.thermalMassModifier; 82 | var transfer = temperatureTransfer(1, 83 | partThermalMass, 84 | resThermalMass, 85 | 300, 86 | boiloffTemperature, 87 | out var equilibriumT); 88 | // Utils.Log("Eq.T {}, C.dT {}, conductivity {}, (P.tM {} + C.tM {})/(P.tM*C.tM) = {}, transfer {}", 89 | // equilibriumT, (equilibriumT-boiloffTemperature)*transfer, 90 | // insulatorConductivity, 91 | // partThermalMass, resThermalMass, (partThermalMass+resThermalMass)/(resThermalMass*partThermalMass), 92 | // transfer);//debug 93 | return (equilibriumT - boiloffTemperature) * transfer; 94 | } 95 | 96 | public double BoiloffAt300K 97 | { 98 | get 99 | { 100 | var CoreDeltaT = CoreDeltaTAt300K(out _, out _); 101 | return resource.amount * (1 - Math.Exp(-CoreDeltaT * specificHeatCapacity / vaporizationHeat)); 102 | } 103 | } 104 | 105 | public ResourceBoiloff(ModuleSwitchableTank tank) 106 | { 107 | this.tank = tank; 108 | part = tank.part; 109 | } 110 | 111 | public virtual void SetResource(PartResource res) 112 | { 113 | if(res == null) 114 | { 115 | resource = null; 116 | cryo_info = null; 117 | return; 118 | } 119 | resource = res; 120 | cryo_info = CryogenicsParams.Instance.GetResource(res); 121 | if(cryo_info == null) 122 | return; 123 | boiloffTemperature = cryo_info.BoiloffTemperature; 124 | specificHeatCapacity = res.info.specificHeatCapacity * res.info.density; 125 | vaporizationHeat = cryo_info.GetVaporizationHeat(res) * res.info.density; 126 | UpdateInsulation(); 127 | } 128 | 129 | public void UpdateInsulation() 130 | { 131 | insulatorConductivity = CryogenicsParams.GetInsulatorConductivity(tank.Volume); 132 | } 133 | 134 | protected virtual void UpdateCoreTemperature(double deltaTime) 135 | { 136 | var resThermalMass = resource.amount * specificHeatCapacity; 137 | var partThermalMass = Math.Max(part.thermalMass - resThermalMass, 1e-3); 138 | var transfer = temperatureTransfer(deltaTime, 139 | partThermalMass, 140 | resThermalMass, 141 | part.temperature, 142 | CoreTemperature, 143 | out var equilibriumT); 144 | var CoreDeltaT = (equilibriumT - CoreTemperature) * transfer; 145 | var PartDeltaT = (equilibriumT - part.temperature) * transfer; 146 | part.AddThermalFlux(PartDeltaT * part.thermalMass / TimeWarp.fixedDeltaTime); 147 | // Utils.Log("P.T {} > Eq.T {} < C.T {}, P.dT {}, C.dT {}, conductivity {}, (P.tM {} + C.tM {})/(P.tM*C.tM) = {}, transfer {}", 148 | // part.temperature, equilibriumT, CoreTemperature, PartDeltaT, CoreDeltaT, 149 | // insulatorConductivity, 150 | // partThermalMass, resThermalMass, (partThermalMass+resThermalMass)/(resThermalMass*partThermalMass), 151 | // transfer);//debug 152 | CoreTemperature += CoreDeltaT; 153 | } 154 | 155 | public virtual void FixedUpdate() 156 | { 157 | if(!HighLogic.LoadedSceneIsFlight 158 | || resource == null 159 | || part == null 160 | || cryo_info == null 161 | || resource.amount <= 0) 162 | return; 163 | if(LastUpdateTime < 0) 164 | CoreTemperature = resource.amount > 0 165 | ? Math.Max(boiloffTemperature - 10, PhysicsGlobals.SpaceTemperature) 166 | : part.temperature; 167 | var deltaTime = GetDeltaTime(); 168 | // Utils.Log("deltaTime: {}, fixedDeltaTime {}", deltaTime, TimeWarp.fixedDeltaTime);//debug 169 | if(deltaTime < 0) 170 | return; 171 | UpdateCoreTemperature(deltaTime); 172 | var dTemp = CoreTemperature - boiloffTemperature; 173 | if(dTemp <= 0) 174 | return; 175 | var boiled_off = resource.amount * (1 - Math.Exp(-dTemp * specificHeatCapacity / vaporizationHeat)); 176 | if(boiled_off > resource.amount) 177 | boiled_off = resource.amount; 178 | // Utils.Log("last amount {}, amount {}, boiled off {}", 179 | // resource.amount, resource.amount-boiled_off, boiled_off);//debug 180 | resource.amount -= boiled_off; 181 | if(resource.amount < 1e-9) 182 | resource.amount = 0; 183 | CoreTemperature = boiloffTemperature; 184 | } 185 | 186 | private double GetDeltaTime() 187 | { 188 | if(Time.timeSinceLevelLoad < 1 || !FlightGlobals.ready) 189 | return -1; 190 | if(LastUpdateTime < 0) 191 | { 192 | LastUpdateTime = Planetarium.GetUniversalTime(); 193 | return TimeWarp.fixedDeltaTime; 194 | } 195 | var time = Planetarium.GetUniversalTime(); 196 | var dT = time - LastUpdateTime; 197 | LastUpdateTime = time; 198 | return dT; 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/ConfigurableContainers.version: -------------------------------------------------------------------------------- 1 | { 2 | "NAME":"ConfigurableContainers", 3 | "URL":"https://github.com/allista/ConfigurableContainers/tree/master/GameData/ConfigurableContainers/ConfigurableContainers.version", 4 | "DOWNLOAD":"https://spacedock.info/mod/1002/Configurable%20Containers", 5 | "CHANGE_LOG_URL":"", 6 | "VERSION": 7 | { 8 | "MAJOR":2, 9 | "MINOR":6, 10 | "PATCH":2, 11 | "BUILD":1 12 | }, 13 | "KSP_VERSION_MIN": 14 | { 15 | "MAJOR":1, 16 | "MINOR":12, 17 | "PATCH":3 18 | }, 19 | "KSP_VERSION_MAX": 20 | { 21 | "MAJOR":1, 22 | "MINOR":12, 23 | "PATCH":3 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/GPO_Patch.cfg: -------------------------------------------------------------------------------- 1 | @PART[*]:NEEDS[GPOSpeedFuelPump]:HAS[@MODULE[ModuleTankManager],!MODULE[GPOSpeedPump]]:FINAL 2 | { 3 | MODULE 4 | { 5 | name = GPOSpeedPump 6 | } 7 | } 8 | 9 | @PART[*]:NEEDS[GPOSpeedFuelPump]:HAS[@MODULE[ModuleSwitchableTank],!MODULE[GPOSpeedPump]]:FINAL 10 | { 11 | MODULE 12 | { 13 | name = GPOSpeedPump 14 | } 15 | } -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/B9_Aerospace_ProceduralWings_Patch.cfg: -------------------------------------------------------------------------------- 1 | // B9 Procedural Wings conversion 2 | 3 | @PART[B9_Aero_Wing_Procedural_TypeA]:NEEDS[B9_Aerospace_ProceduralWings&!modularFuelTanks&!RealFuels]:AFTER[B9_Aerospace_ProceduralWings] 4 | { 5 | //tankless manager mimics the behaviour of the B9-PW builtin fuel switcher which, 6 | //by default, does not include any resource 7 | MODULE 8 | { 9 | name = ModuleTankManager 10 | Volume = 3.84 11 | DoCostPatch = True 12 | DoMassPatch = True 13 | IncludeTankTypes = LiquidChemicals 14 | } 15 | } 16 | //:mode=c#: 17 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Benjee10_X-37B_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for Benjee10_X-37B 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[x-37_lfoSlice]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Benjee10_X-37B] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 2.469136 //180.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | //MonoPropellant Tanks 29 | //Automatically generated using PyKSPutils library 30 | @PART[x-37_monoSlice]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Benjee10_X-37B] 31 | { 32 | !RESOURCE[MonoPropellant] 33 | { 34 | 35 | } 36 | MODULE 37 | { 38 | name = ModuleTankManager 39 | Volume = 0.271739 //100.0 units of MonoPropellant: conversion rate is 0.002717 m3/u 40 | DoCostPatch = True 41 | DoMassPatch = True 42 | TANK 43 | { 44 | TankType = LiquidChemicals 45 | CurrentResource = MonoPropellant 46 | InitialAmount = 1.0 47 | Volume = 100.0 48 | } 49 | } 50 | } 51 | //:mode=c#: 52 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/DodoLabs_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for DodoLabs 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[emutank2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[DodoLabs] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 1.111111 //81.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[emutank1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[DodoLabs] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 4.444444 //324.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | //:mode=c#: 53 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/KerboNerdLaboratories.cfg: -------------------------------------------------------------------------------- 1 | @PART[HPJT-01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]]:AFTER[KerboNerdLaboratories] 2 | { 3 | !RESOURCE[HyperPlutonium] 4 | { 5 | 6 | } 7 | MODULE 8 | { 9 | name = ModuleTankManager 10 | Volume = 4.2093793 11 | DoCostPatch = True 12 | DoMassPatch = True 13 | TANK 14 | { 15 | TankType = Radioactives 16 | CurrentResource = HyperPlutonium 17 | InitialAmount = 1.0 18 | Volume = 100.0 19 | } 20 | } 21 | } 22 | 23 | @PART[HPSFA-01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]]:AFTER[KerboNerdLaboratories] 24 | { 25 | !RESOURCE[HyperPlutonium] 26 | { 27 | 28 | } 29 | MODULE 30 | { 31 | name = ModuleTankManager 32 | Volume = 2.5256276 33 | DoCostPatch = True 34 | DoMassPatch = True 35 | TANK 36 | { 37 | TankType = Radioactives 38 | CurrentResource = HyperPlutonium 39 | InitialAmount = 1.0 40 | Volume = 100.0 41 | } 42 | } 43 | } 44 | 45 | @PART[HPSFA-02]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]]:AFTER[KerboNerdLaboratories] 46 | { 47 | !RESOURCE[HyperPlutonium] 48 | { 49 | 50 | } 51 | MODULE 52 | { 53 | name = ModuleTankManager 54 | Volume = 0.87695404 55 | DoCostPatch = True 56 | DoMassPatch = True 57 | TANK 58 | { 59 | TankType = Radioactives 60 | CurrentResource = HyperPlutonium 61 | InitialAmount = 1.0 62 | Volume = 100.0 63 | } 64 | } 65 | } 66 | 67 | @PART[HPSFA-03]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]]:AFTER[KerboNerdLaboratories] 68 | { 69 | !RESOURCE[HyperPlutonium] 70 | { 71 | 72 | } 73 | MODULE 74 | { 75 | name = ModuleTankManager 76 | Volume = 0.35078161 77 | DoCostPatch = True 78 | DoMassPatch = True 79 | TANK 80 | { 81 | TankType = Radioactives 82 | CurrentResource = HyperPlutonium 83 | InitialAmount = 1.0 84 | Volume = 100.0 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/MakingHistory_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for SquadExpansion/MakingHistory/Parts 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[Size1p5_Size0_Adapter_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 0.987654 //72.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[Size1p5_Size1_Adapter_02]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 0.987654 //72.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | 53 | @PART[Size4_Tank_03]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 54 | { 55 | !RESOURCE[LiquidFuel] 56 | { 57 | 58 | } 59 | !RESOURCE[Oxidizer] 60 | { 61 | 62 | } 63 | MODULE 64 | { 65 | name = ModuleTankManager 66 | Volume = 158.024691 //11520.0 units of LF: conversion rate is 0.013717 m3/u 67 | DoCostPatch = True 68 | DoMassPatch = True 69 | TANK 70 | { 71 | name = LFO 72 | Volume = 100.0 73 | } 74 | } 75 | } 76 | 77 | @PART[Size4_Tank_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 78 | { 79 | !RESOURCE[LiquidFuel] 80 | { 81 | 82 | } 83 | !RESOURCE[Oxidizer] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleTankManager 90 | Volume = 39.506173 //2880.0 units of LF: conversion rate is 0.013717 m3/u 91 | DoCostPatch = True 92 | DoMassPatch = True 93 | TANK 94 | { 95 | name = LFO 96 | Volume = 100.0 97 | } 98 | } 99 | } 100 | 101 | @PART[Size1p5_Tank_02]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 102 | { 103 | !RESOURCE[LiquidFuel] 104 | { 105 | 106 | } 107 | !RESOURCE[Oxidizer] 108 | { 109 | 110 | } 111 | MODULE 112 | { 113 | name = ModuleTankManager 114 | Volume = 2.716049 //198.0 units of LF: conversion rate is 0.013717 m3/u 115 | DoCostPatch = True 116 | DoMassPatch = True 117 | TANK 118 | { 119 | name = LFO 120 | Volume = 100.0 121 | } 122 | } 123 | } 124 | 125 | @PART[Size4_Tank_02]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 126 | { 127 | !RESOURCE[LiquidFuel] 128 | { 129 | 130 | } 131 | !RESOURCE[Oxidizer] 132 | { 133 | 134 | } 135 | MODULE 136 | { 137 | name = ModuleTankManager 138 | Volume = 79.012346 //5760.0 units of LF: conversion rate is 0.013717 m3/u 139 | DoCostPatch = True 140 | DoMassPatch = True 141 | TANK 142 | { 143 | name = LFO 144 | Volume = 100.0 145 | } 146 | } 147 | } 148 | 149 | @PART[Size1p5_Tank_03]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 150 | { 151 | !RESOURCE[LiquidFuel] 152 | { 153 | 154 | } 155 | !RESOURCE[Oxidizer] 156 | { 157 | 158 | } 159 | MODULE 160 | { 161 | name = ModuleTankManager 162 | Volume = 5.555556 //405.0 units of LF: conversion rate is 0.013717 m3/u 163 | DoCostPatch = True 164 | DoMassPatch = True 165 | TANK 166 | { 167 | name = LFO 168 | Volume = 100.0 169 | } 170 | } 171 | } 172 | 173 | @PART[Size3_Size4_Adapter_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 174 | { 175 | !RESOURCE[LiquidFuel] 176 | { 177 | 178 | } 179 | !RESOURCE[Oxidizer] 180 | { 181 | 182 | } 183 | MODULE 184 | { 185 | name = ModuleTankManager 186 | Volume = 39.506173 //2880.0 units of LF: conversion rate is 0.013717 m3/u 187 | DoCostPatch = True 188 | DoMassPatch = True 189 | TANK 190 | { 191 | name = LFO 192 | Volume = 100.0 193 | } 194 | } 195 | } 196 | 197 | @PART[Size1p5_Size1_Adapter_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 198 | { 199 | !RESOURCE[LiquidFuel] 200 | { 201 | 202 | } 203 | !RESOURCE[Oxidizer] 204 | { 205 | 206 | } 207 | MODULE 208 | { 209 | name = ModuleTankManager 210 | Volume = 3.703704 //270.0 units of LF: conversion rate is 0.013717 m3/u 211 | DoCostPatch = True 212 | DoMassPatch = True 213 | TANK 214 | { 215 | name = LFO 216 | Volume = 100.0 217 | } 218 | } 219 | } 220 | 221 | @PART[Size4_EngineAdapter_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 222 | { 223 | !RESOURCE[LiquidFuel] 224 | { 225 | 226 | } 227 | !RESOURCE[Oxidizer] 228 | { 229 | 230 | } 231 | MODULE 232 | { 233 | name = ModuleTankManager 234 | Volume = 55.555556 //4050.0 units of LF: conversion rate is 0.013717 m3/u 235 | DoCostPatch = True 236 | DoMassPatch = True 237 | TANK 238 | { 239 | name = LFO 240 | Volume = 100.0 241 | } 242 | } 243 | } 244 | 245 | @PART[Size1p5_Size2_Adapter_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 246 | { 247 | !RESOURCE[LiquidFuel] 248 | { 249 | 250 | } 251 | !RESOURCE[Oxidizer] 252 | { 253 | 254 | } 255 | MODULE 256 | { 257 | name = ModuleTankManager 258 | Volume = 7.407407 //540.0 units of LF: conversion rate is 0.013717 m3/u 259 | DoCostPatch = True 260 | DoMassPatch = True 261 | TANK 262 | { 263 | name = LFO 264 | Volume = 100.0 265 | } 266 | } 267 | } 268 | 269 | @PART[Size1p5_Tank_04]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 270 | { 271 | !RESOURCE[LiquidFuel] 272 | { 273 | 274 | } 275 | !RESOURCE[Oxidizer] 276 | { 277 | 278 | } 279 | MODULE 280 | { 281 | name = ModuleTankManager 282 | Volume = 11.111111 //810.0 units of LF: conversion rate is 0.013717 m3/u 283 | DoCostPatch = True 284 | DoMassPatch = True 285 | TANK 286 | { 287 | name = LFO 288 | Volume = 100.0 289 | } 290 | } 291 | } 292 | 293 | @PART[Size4_Tank_04]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 294 | { 295 | !RESOURCE[LiquidFuel] 296 | { 297 | 298 | } 299 | !RESOURCE[Oxidizer] 300 | { 301 | 302 | } 303 | MODULE 304 | { 305 | name = ModuleTankManager 306 | Volume = 316.049383 //23040.0 units of LF: conversion rate is 0.013717 m3/u 307 | DoCostPatch = True 308 | DoMassPatch = True 309 | TANK 310 | { 311 | name = LFO 312 | Volume = 100.0 313 | } 314 | } 315 | } 316 | 317 | @PART[Size1p5_Tank_01]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 318 | { 319 | !RESOURCE[LiquidFuel] 320 | { 321 | 322 | } 323 | !RESOURCE[Oxidizer] 324 | { 325 | 326 | } 327 | MODULE 328 | { 329 | name = ModuleTankManager 330 | Volume = 1.358025 //99.0 units of LF: conversion rate is 0.013717 m3/u 331 | DoCostPatch = True 332 | DoMassPatch = True 333 | TANK 334 | { 335 | name = LFO 336 | Volume = 100.0 337 | } 338 | } 339 | } 340 | //MonoPropellant Tanks 341 | //Automatically generated using PyKSPutils library 342 | @PART[Size1p5_Monoprop]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 343 | { 344 | !RESOURCE[MonoPropellant] 345 | { 346 | 347 | } 348 | MODULE 349 | { 350 | name = ModuleTankManager 351 | Volume = 1.086957 //400.0 units of MonoPropellant: conversion rate is 0.002717 m3/u 352 | DoCostPatch = True 353 | DoMassPatch = True 354 | TANK 355 | { 356 | TankType = LiquidChemicals 357 | CurrentResource = MonoPropellant 358 | InitialAmount = 1.0 359 | Volume = 100.0 360 | } 361 | } 362 | } 363 | 364 | @PART[monopropMiniSphere]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels] 365 | { 366 | !RESOURCE[MonoPropellant] 367 | { 368 | 369 | } 370 | MODULE 371 | { 372 | name = ModuleTankManager 373 | Volume = 0.02038 //7.5 units of MonoPropellant: conversion rate is 0.002717 m3/u 374 | DoCostPatch = True 375 | DoMassPatch = True 376 | TANK 377 | { 378 | TankType = LiquidChemicals 379 | CurrentResource = MonoPropellant 380 | InitialAmount = 1.0 381 | Volume = 100.0 382 | } 383 | } 384 | } 385 | //:mode=c#: 386 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/MiningExpansion_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for MiningExpansion 2 | 3 | //Ore Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[SMX_Mk2Oretank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[MiningExpansion] 6 | { 7 | !RESOURCE[Ore] 8 | { 9 | 10 | } 11 | MODULE 12 | { 13 | name = ModuleTankManager 14 | Volume = 2.972973 //550.0 units of Ore: conversion rate is 0.005405 m3/u 15 | DoCostPatch = True 16 | DoMassPatch = True 17 | TANK 18 | { 19 | TankType = Soil 20 | CurrentResource = Ore 21 | InitialAmount = 0.0 22 | Volume = 100.0 23 | } 24 | } 25 | } 26 | 27 | @PART[SMX_Size3OreTank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[MiningExpansion] 28 | { 29 | !RESOURCE[Ore] 30 | { 31 | 32 | } 33 | MODULE 34 | { 35 | name = ModuleTankManager 36 | Volume = 24.324324 //4500.0 units of Ore: conversion rate is 0.005405 m3/u 37 | DoCostPatch = True 38 | DoMassPatch = True 39 | TANK 40 | { 41 | TankType = Soil 42 | CurrentResource = Ore 43 | InitialAmount = 0.0 44 | Volume = 100.0 45 | } 46 | } 47 | } 48 | 49 | @PART[SMX_Mk3OreTank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[MiningExpansion] 50 | { 51 | !RESOURCE[Ore] 52 | { 53 | 54 | } 55 | MODULE 56 | { 57 | name = ModuleTankManager 58 | Volume = 21.621622 //4000.0 units of Ore: conversion rate is 0.005405 m3/u 59 | DoCostPatch = True 60 | DoMassPatch = True 61 | TANK 62 | { 63 | TankType = Soil 64 | CurrentResource = Ore 65 | InitialAmount = 0.0 66 | Volume = 100.0 67 | } 68 | } 69 | } 70 | 71 | @PART[SMX_Size0OreTank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[MiningExpansion] 72 | { 73 | !RESOURCE[Ore] 74 | { 75 | 76 | } 77 | MODULE 78 | { 79 | name = ModuleTankManager 80 | Volume = 0.27027 //50.0 units of Ore: conversion rate is 0.005405 m3/u 81 | DoCostPatch = True 82 | DoMassPatch = True 83 | TANK 84 | { 85 | TankType = Soil 86 | CurrentResource = Ore 87 | InitialAmount = 0.0 88 | Volume = 100.0 89 | } 90 | } 91 | } 92 | //:mode=c#: 93 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Mk2Expansion_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for Mk2Expansion 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[M2X_InverterFuselage]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 4.938272 //360.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[M2X_HypersonicNose]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 2.469136 //180.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | 53 | @PART[M2X_linearTricoupler]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 54 | { 55 | !RESOURCE[LiquidFuel] 56 | { 57 | 58 | } 59 | !RESOURCE[Oxidizer] 60 | { 61 | 62 | } 63 | MODULE 64 | { 65 | name = ModuleTankManager 66 | Volume = 4.938272 //360.0 units of LF: conversion rate is 0.013717 m3/u 67 | DoCostPatch = True 68 | DoMassPatch = True 69 | TANK 70 | { 71 | name = LFO 72 | Volume = 100.0 73 | } 74 | } 75 | } 76 | 77 | @PART[M2X_Short25adapter]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 78 | { 79 | !RESOURCE[LiquidFuel] 80 | { 81 | 82 | } 83 | !RESOURCE[Oxidizer] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleTankManager 90 | Volume = 2.469136 //180.0 units of LF: conversion rate is 0.013717 m3/u 91 | DoCostPatch = True 92 | DoMassPatch = True 93 | TANK 94 | { 95 | name = LFO 96 | Volume = 100.0 97 | } 98 | } 99 | } 100 | 101 | @PART[M2X_625tricoupler]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 102 | { 103 | !RESOURCE[LiquidFuel] 104 | { 105 | 106 | } 107 | !RESOURCE[Oxidizer] 108 | { 109 | 110 | } 111 | MODULE 112 | { 113 | name = ModuleTankManager 114 | Volume = 1.234568 //90.0 units of LF: conversion rate is 0.013717 m3/u 115 | DoCostPatch = True 116 | DoMassPatch = True 117 | TANK 118 | { 119 | name = LFO 120 | Volume = 100.0 121 | } 122 | } 123 | } 124 | 125 | @PART[M2X_SpadeTail]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 126 | { 127 | !RESOURCE[LiquidFuel] 128 | { 129 | 130 | } 131 | !RESOURCE[Oxidizer] 132 | { 133 | 134 | } 135 | MODULE 136 | { 137 | name = ModuleTankManager 138 | Volume = 1.234568 //90.0 units of LF: conversion rate is 0.013717 m3/u 139 | DoCostPatch = True 140 | DoMassPatch = True 141 | TANK 142 | { 143 | name = LFO 144 | Volume = 100.0 145 | } 146 | } 147 | } 148 | 149 | @PART[M2X_Mk2bicoupler]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 150 | { 151 | !RESOURCE[LiquidFuel] 152 | { 153 | 154 | } 155 | !RESOURCE[Oxidizer] 156 | { 157 | 158 | } 159 | MODULE 160 | { 161 | name = ModuleTankManager 162 | Volume = 4.938272 //360.0 units of LF: conversion rate is 0.013717 m3/u 163 | DoCostPatch = True 164 | DoMassPatch = True 165 | TANK 166 | { 167 | name = LFO 168 | Volume = 100.0 169 | } 170 | } 171 | } 172 | 173 | @PART[M2X_XHub]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 174 | { 175 | !RESOURCE[LiquidFuel] 176 | { 177 | 178 | } 179 | !RESOURCE[Oxidizer] 180 | { 181 | 182 | } 183 | MODULE 184 | { 185 | name = ModuleTankManager 186 | Volume = 2.469136 //180.0 units of LF: conversion rate is 0.013717 m3/u 187 | DoCostPatch = True 188 | DoMassPatch = True 189 | TANK 190 | { 191 | name = LFO 192 | Volume = 100.0 193 | } 194 | } 195 | } 196 | 197 | @PART[M2X_LHub]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 198 | { 199 | !RESOURCE[LiquidFuel] 200 | { 201 | 202 | } 203 | !RESOURCE[Oxidizer] 204 | { 205 | 206 | } 207 | MODULE 208 | { 209 | name = ModuleTankManager 210 | Volume = 1.851852 //135.0 units of LF: conversion rate is 0.013717 m3/u 211 | DoCostPatch = True 212 | DoMassPatch = True 213 | TANK 214 | { 215 | name = LFO 216 | Volume = 100.0 217 | } 218 | } 219 | } 220 | 221 | @PART[M2X_THub]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk2Expansion] 222 | { 223 | !RESOURCE[LiquidFuel] 224 | { 225 | 226 | } 227 | !RESOURCE[Oxidizer] 228 | { 229 | 230 | } 231 | MODULE 232 | { 233 | name = ModuleTankManager 234 | Volume = 2.469136 //180.0 units of LF: conversion rate is 0.013717 m3/u 235 | DoCostPatch = True 236 | DoMassPatch = True 237 | TANK 238 | { 239 | name = LFO 240 | Volume = 100.0 241 | } 242 | } 243 | } 244 | //:mode=c#: 245 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Mk3HypersonicSystems_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for Mk3HypersonicSystems 2 | 3 | //LiquidFuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[Mk3LiftingBodyEdge]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk3HypersonicSystems] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | MODULE 12 | { 13 | name = ModuleTankManager 14 | Volume = 0.925926 //150.0 units of LiquidFuel: conversion rate is 0.006173 m3/u 15 | DoCostPatch = True 16 | DoMassPatch = True 17 | TANK 18 | { 19 | TankType = LiquidChemicals 20 | CurrentResource = LiquidFuel 21 | InitialAmount = 1.0 22 | Volume = 100.0 23 | } 24 | } 25 | } 26 | 27 | @PART[Mk3EdgeRootExtension]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[Mk3HypersonicSystems] 28 | { 29 | !RESOURCE[LiquidFuel] 30 | { 31 | 32 | } 33 | MODULE 34 | { 35 | name = ModuleTankManager 36 | Volume = 0.555556 //90.0 units of LiquidFuel: conversion rate is 0.006173 m3/u 37 | DoCostPatch = True 38 | DoMassPatch = True 39 | TANK 40 | { 41 | TankType = LiquidChemicals 42 | CurrentResource = LiquidFuel 43 | InitialAmount = 1.0 44 | Volume = 100.0 45 | } 46 | } 47 | } 48 | //:mode=c#: 49 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/ModRocketSys_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for ModRocketSys 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[NBwhiteJumbo]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 39.506173 //2880.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[NBradialMiniTank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 0.987654 //72.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | 53 | @PART[NB0mtank1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 54 | { 55 | !RESOURCE[LiquidFuel] 56 | { 57 | 58 | } 59 | !RESOURCE[Oxidizer] 60 | { 61 | 62 | } 63 | MODULE 64 | { 65 | name = ModuleTankManager 66 | Volume = 0.308642 //22.5 units of LF: conversion rate is 0.013717 m3/u 67 | DoCostPatch = True 68 | DoMassPatch = True 69 | TANK 70 | { 71 | name = LFO 72 | Volume = 100.0 73 | } 74 | } 75 | } 76 | 77 | @PART[NBjumboThreeQ]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 78 | { 79 | !RESOURCE[LiquidFuel] 80 | { 81 | 82 | } 83 | !RESOURCE[Oxidizer] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleTankManager 90 | Volume = 29.62963 //2160.0 units of LF: conversion rate is 0.013717 m3/u 91 | DoCostPatch = True 92 | DoMassPatch = True 93 | TANK 94 | { 95 | name = LFO 96 | Volume = 100.0 97 | } 98 | } 99 | } 100 | 101 | @PART[NBhalfJumbo]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 102 | { 103 | !RESOURCE[LiquidFuel] 104 | { 105 | 106 | } 107 | !RESOURCE[Oxidizer] 108 | { 109 | 110 | } 111 | MODULE 112 | { 113 | name = ModuleTankManager 114 | Volume = 19.753086 //1440.0 units of LF: conversion rate is 0.013717 m3/u 115 | DoCostPatch = True 116 | DoMassPatch = True 117 | TANK 118 | { 119 | name = LFO 120 | Volume = 100.0 121 | } 122 | } 123 | } 124 | 125 | @PART[NBminiOrange]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 126 | { 127 | !RESOURCE[LiquidFuel] 128 | { 129 | 130 | } 131 | !RESOURCE[Oxidizer] 132 | { 133 | 134 | } 135 | MODULE 136 | { 137 | name = ModuleTankManager 138 | Volume = 9.876543 //720.0 units of LF: conversion rate is 0.013717 m3/u 139 | DoCostPatch = True 140 | DoMassPatch = True 141 | TANK 142 | { 143 | name = LFO 144 | Volume = 100.0 145 | } 146 | } 147 | } 148 | 149 | @PART[NBconeTank3m]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 150 | { 151 | !RESOURCE[LiquidFuel] 152 | { 153 | 154 | } 155 | !RESOURCE[Oxidizer] 156 | { 157 | 158 | } 159 | MODULE 160 | { 161 | name = ModuleTankManager 162 | Volume = 29.62963 //2160.0 units of LF: conversion rate is 0.013717 m3/u 163 | DoCostPatch = True 164 | DoMassPatch = True 165 | TANK 166 | { 167 | name = LFO 168 | Volume = 100.0 169 | } 170 | } 171 | } 172 | 173 | @PART[NBconeTank2m]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 174 | { 175 | !RESOURCE[LiquidFuel] 176 | { 177 | 178 | } 179 | !RESOURCE[Oxidizer] 180 | { 181 | 182 | } 183 | MODULE 184 | { 185 | name = ModuleTankManager 186 | Volume = 3.703704 //270.0 units of LF: conversion rate is 0.013717 m3/u 187 | DoCostPatch = True 188 | DoMassPatch = True 189 | TANK 190 | { 191 | name = LFO 192 | Volume = 100.0 193 | } 194 | } 195 | } 196 | //LiquidFuel Tanks 197 | //Automatically generated using PyKSPutils library 198 | @PART[NB0mtankJet1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 199 | { 200 | !RESOURCE[LiquidFuel] 201 | { 202 | 203 | } 204 | MODULE 205 | { 206 | name = ModuleTankManager 207 | Volume = 0.308642 //50.0 units of LiquidFuel: conversion rate is 0.006173 m3/u 208 | DoCostPatch = True 209 | DoMassPatch = True 210 | TANK 211 | { 212 | TankType = LiquidChemicals 213 | CurrentResource = LiquidFuel 214 | InitialAmount = 1.0 215 | Volume = 100.0 216 | } 217 | } 218 | } 219 | 220 | @PART[NB0mtankJet2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 221 | { 222 | !RESOURCE[LiquidFuel] 223 | { 224 | 225 | } 226 | MODULE 227 | { 228 | name = ModuleTankManager 229 | Volume = 0.617284 //100.0 units of LiquidFuel: conversion rate is 0.006173 m3/u 230 | DoCostPatch = True 231 | DoMassPatch = True 232 | TANK 233 | { 234 | TankType = LiquidChemicals 235 | CurrentResource = LiquidFuel 236 | InitialAmount = 1.0 237 | Volume = 100.0 238 | } 239 | } 240 | } 241 | //MonoPropellant Tanks 242 | //Automatically generated using PyKSPutils library 243 | @PART[NBmonoprop3m]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 244 | { 245 | !RESOURCE[MonoPropellant] 246 | { 247 | 248 | } 249 | MODULE 250 | { 251 | name = ModuleTankManager 252 | Volume = 4.565217 //1680.0 units of MonoPropellant: conversion rate is 0.002717 m3/u 253 | DoCostPatch = True 254 | DoMassPatch = True 255 | TANK 256 | { 257 | TankType = LiquidChemicals 258 | CurrentResource = MonoPropellant 259 | InitialAmount = 1.0 260 | Volume = 100.0 261 | } 262 | } 263 | } 264 | 265 | @PART[NBinterstageDecoupler3m]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 266 | { 267 | !RESOURCE[MonoPropellant] 268 | { 269 | 270 | } 271 | MODULE 272 | { 273 | name = ModuleTankManager 274 | Volume = 0.543478 //200.0 units of MonoPropellant: conversion rate is 0.002717 m3/u 275 | DoCostPatch = True 276 | DoMassPatch = True 277 | TANK 278 | { 279 | TankType = LiquidChemicals 280 | CurrentResource = MonoPropellant 281 | InitialAmount = 1.0 282 | Volume = 100.0 283 | } 284 | } 285 | } 286 | //XenonGas Tanks 287 | //Automatically generated using PyKSPutils library 288 | @PART[NBxenonSphere1m]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 289 | { 290 | !RESOURCE[XenonGas] 291 | { 292 | 293 | } 294 | MODULE 295 | { 296 | name = ModuleSwitchableTank 297 | Volume = 1.124606 //12500.0 units of XenonGas: conversion rate is 0.000090 m3/u 298 | InitialAmount = 1.0 299 | DoCostPatch = True 300 | DoMassPatch = True 301 | ChooseTankType = False 302 | TankType = Gases 303 | CurrentResource = XenonGas 304 | } 305 | } 306 | 307 | @PART[NBxenonSphere]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[ModRocketSys] 308 | { 309 | !RESOURCE[XenonGas] 310 | { 311 | 312 | } 313 | MODULE 314 | { 315 | name = ModuleSwitchableTank 316 | Volume = 0.125956 //1400.0 units of XenonGas: conversion rate is 0.000090 m3/u 317 | InitialAmount = 1.0 318 | DoCostPatch = True 319 | DoMassPatch = True 320 | ChooseTankType = False 321 | TankType = Gases 322 | CurrentResource = XenonGas 323 | } 324 | } 325 | //:mode=c#: 326 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/blue.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/brown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/brown.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/dark-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/dark-green.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/green.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/grey.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/light-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/light-blue.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/light-grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/light-grey.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/orange.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/Models/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allista/ConfigurableContainers/e903343fcbb24cbd49d03ae189354ffd5246df42/GameData/ConfigurableContainers/Parts/Models/warning.png -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/NearFuturePropulsion_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for NearFuturePropulsion 2 | 3 | //XenonGas Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[xenon-125-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 6 | { 7 | !RESOURCE[XenonGas] 8 | { 9 | 10 | } 11 | MODULE 12 | { 13 | name = ModuleSwitchableTank 14 | Volume = 2.159244 //24000.0 units of XenonGas: conversion rate is 0.000090 m3/u 15 | InitialAmount = 1.0 16 | DoCostPatch = True 17 | DoMassPatch = True 18 | ChooseTankType = False 19 | TankType = Gases 20 | CurrentResource = XenonGas 21 | } 22 | } 23 | 24 | @PART[xenon-125-3]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 25 | { 26 | !RESOURCE[XenonGas] 27 | { 28 | 29 | } 30 | MODULE 31 | { 32 | name = ModuleSwitchableTank 33 | Volume = 0.539811 //6000.0 units of XenonGas: conversion rate is 0.000090 m3/u 34 | InitialAmount = 1.0 35 | DoCostPatch = True 36 | DoMassPatch = True 37 | ChooseTankType = False 38 | TankType = Gases 39 | CurrentResource = XenonGas 40 | } 41 | } 42 | 43 | @PART[xenon-125-2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 44 | { 45 | !RESOURCE[XenonGas] 46 | { 47 | 48 | } 49 | MODULE 50 | { 51 | name = ModuleSwitchableTank 52 | Volume = 1.079622 //12000.0 units of XenonGas: conversion rate is 0.000090 m3/u 53 | InitialAmount = 1.0 54 | DoCostPatch = True 55 | DoMassPatch = True 56 | ChooseTankType = False 57 | TankType = Gases 58 | CurrentResource = XenonGas 59 | } 60 | } 61 | 62 | @PART[xenon-25-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 63 | { 64 | !RESOURCE[XenonGas] 65 | { 66 | 67 | } 68 | MODULE 69 | { 70 | name = ModuleSwitchableTank 71 | Volume = 17.273954 //192000.0 units of XenonGas: conversion rate is 0.000090 m3/u 72 | InitialAmount = 1.0 73 | DoCostPatch = True 74 | DoMassPatch = True 75 | ChooseTankType = False 76 | TankType = Gases 77 | CurrentResource = XenonGas 78 | } 79 | } 80 | 81 | @PART[xenon-25-2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 82 | { 83 | !RESOURCE[XenonGas] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleSwitchableTank 90 | Volume = 8.636977 //96000.0 units of XenonGas: conversion rate is 0.000090 m3/u 91 | InitialAmount = 1.0 92 | DoCostPatch = True 93 | DoMassPatch = True 94 | ChooseTankType = False 95 | TankType = Gases 96 | CurrentResource = XenonGas 97 | } 98 | } 99 | 100 | @PART[xenon-25-3]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 101 | { 102 | !RESOURCE[XenonGas] 103 | { 104 | 105 | } 106 | MODULE 107 | { 108 | name = ModuleSwitchableTank 109 | Volume = 4.318489 //48000.0 units of XenonGas: conversion rate is 0.000090 m3/u 110 | InitialAmount = 1.0 111 | DoCostPatch = True 112 | DoMassPatch = True 113 | ChooseTankType = False 114 | TankType = Gases 115 | CurrentResource = XenonGas 116 | } 117 | } 118 | 119 | @PART[xenon-radial-125-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 120 | { 121 | !RESOURCE[XenonGas] 122 | { 123 | 124 | } 125 | MODULE 126 | { 127 | name = ModuleSwitchableTank 128 | Volume = 0.674764 //7500.0 units of XenonGas: conversion rate is 0.000090 m3/u 129 | InitialAmount = 1.0 130 | DoCostPatch = True 131 | DoMassPatch = True 132 | ChooseTankType = False 133 | TankType = Gases 134 | CurrentResource = XenonGas 135 | } 136 | } 137 | //ArgonGas Tanks 138 | //Automatically generated using PyKSPutils library 139 | @PART[argon-0625-3]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 140 | { 141 | !RESOURCE[ArgonGas] 142 | { 143 | 144 | } 145 | MODULE 146 | { 147 | name = ModuleSwitchableTank 148 | Volume = 0.1407 //28000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 149 | InitialAmount = 1.0 150 | DoCostPatch = True 151 | DoMassPatch = True 152 | ChooseTankType = False 153 | TankType = Gases 154 | CurrentResource = ArgonGas 155 | } 156 | } 157 | 158 | @PART[argon-0625-2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 159 | { 160 | !RESOURCE[ArgonGas] 161 | { 162 | 163 | } 164 | MODULE 165 | { 166 | name = ModuleSwitchableTank 167 | Volume = 0.2814 //56000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 168 | InitialAmount = 1.0 169 | DoCostPatch = True 170 | DoMassPatch = True 171 | ChooseTankType = False 172 | TankType = Gases 173 | CurrentResource = ArgonGas 174 | } 175 | } 176 | 177 | @PART[argon-0625-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 178 | { 179 | !RESOURCE[ArgonGas] 180 | { 181 | 182 | } 183 | MODULE 184 | { 185 | name = ModuleSwitchableTank 186 | Volume = 0.5628 //112000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 187 | InitialAmount = 1.0 188 | DoCostPatch = True 189 | DoMassPatch = True 190 | ChooseTankType = False 191 | TankType = Gases 192 | CurrentResource = ArgonGas 193 | } 194 | } 195 | 196 | @PART[argon-25-2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 197 | { 198 | !RESOURCE[ArgonGas] 199 | { 200 | 201 | } 202 | MODULE 203 | { 204 | name = ModuleSwitchableTank 205 | Volume = 25.728 //5120000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 206 | InitialAmount = 1.0 207 | DoCostPatch = True 208 | DoMassPatch = True 209 | ChooseTankType = False 210 | TankType = Gases 211 | CurrentResource = ArgonGas 212 | } 213 | } 214 | 215 | @PART[argon-25-3]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 216 | { 217 | !RESOURCE[ArgonGas] 218 | { 219 | 220 | } 221 | MODULE 222 | { 223 | name = ModuleSwitchableTank 224 | Volume = 12.864 //2560000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 225 | InitialAmount = 1.0 226 | DoCostPatch = True 227 | DoMassPatch = True 228 | ChooseTankType = False 229 | TankType = Gases 230 | CurrentResource = ArgonGas 231 | } 232 | } 233 | 234 | @PART[argon-25-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 235 | { 236 | !RESOURCE[ArgonGas] 237 | { 238 | 239 | } 240 | MODULE 241 | { 242 | name = ModuleSwitchableTank 243 | Volume = 51.456 //10240000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 244 | InitialAmount = 1.0 245 | DoCostPatch = True 246 | DoMassPatch = True 247 | ChooseTankType = False 248 | TankType = Gases 249 | CurrentResource = ArgonGas 250 | } 251 | } 252 | 253 | @PART[argon-125-2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 254 | { 255 | !RESOURCE[ArgonGas] 256 | { 257 | 258 | } 259 | MODULE 260 | { 261 | name = ModuleSwitchableTank 262 | Volume = 3.216 //640000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 263 | InitialAmount = 1.0 264 | DoCostPatch = True 265 | DoMassPatch = True 266 | ChooseTankType = False 267 | TankType = Gases 268 | CurrentResource = ArgonGas 269 | } 270 | } 271 | 272 | @PART[argon-125-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 273 | { 274 | !RESOURCE[ArgonGas] 275 | { 276 | 277 | } 278 | MODULE 279 | { 280 | name = ModuleSwitchableTank 281 | Volume = 6.432 //1280000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 282 | InitialAmount = 1.0 283 | DoCostPatch = True 284 | DoMassPatch = True 285 | ChooseTankType = False 286 | TankType = Gases 287 | CurrentResource = ArgonGas 288 | } 289 | } 290 | 291 | @PART[argon-125-3]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 292 | { 293 | !RESOURCE[ArgonGas] 294 | { 295 | 296 | } 297 | MODULE 298 | { 299 | name = ModuleSwitchableTank 300 | Volume = 1.608 //320000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 301 | InitialAmount = 1.0 302 | DoCostPatch = True 303 | DoMassPatch = True 304 | ChooseTankType = False 305 | TankType = Gases 306 | CurrentResource = ArgonGas 307 | } 308 | } 309 | 310 | @PART[argon-radial-125-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 311 | { 312 | !RESOURCE[ArgonGas] 313 | { 314 | 315 | } 316 | MODULE 317 | { 318 | name = ModuleSwitchableTank 319 | Volume = 0.3216 //64000.0 units of ArgonGas: conversion rate is 0.000005 m3/u 320 | InitialAmount = 1.0 321 | DoCostPatch = True 322 | DoMassPatch = True 323 | ChooseTankType = False 324 | TankType = Gases 325 | CurrentResource = ArgonGas 326 | } 327 | } 328 | 329 | @PART[argon-radial-0625-1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[NearFuturePropulsion] 330 | { 331 | !RESOURCE[ArgonGas] 332 | { 333 | 334 | } 335 | MODULE 336 | { 337 | name = ModuleSwitchableTank 338 | Volume = 0.07236 //14400.0 units of ArgonGas: conversion rate is 0.000005 m3/u 339 | InitialAmount = 1.0 340 | DoCostPatch = True 341 | DoMassPatch = True 342 | ChooseTankType = False 343 | TankType = Gases 344 | CurrentResource = ArgonGas 345 | } 346 | } 347 | //:mode=c#: 348 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/PlanetaryBaseInc_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for PlanetaryBaseInc 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[KKAOSS_small_Rocket_Fuel_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 1.234568 //90.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[KKAOSS_Rocket_Fuel_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 2.469136 //180.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | 53 | @PART[KKAOSS_Fuel_Tank_small]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 54 | { 55 | !RESOURCE[LiquidFuel] 56 | { 57 | 58 | } 59 | !RESOURCE[Oxidizer] 60 | { 61 | 62 | } 63 | MODULE 64 | { 65 | name = ModuleTankManager 66 | Volume = 4.938272 //360.0 units of LF: conversion rate is 0.013717 m3/u 67 | DoCostPatch = True 68 | DoMassPatch = True 69 | TANK 70 | { 71 | name = LFO 72 | Volume = 100.0 73 | } 74 | } 75 | } 76 | 77 | @PART[KKAOSS_Fuel_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 78 | { 79 | !RESOURCE[LiquidFuel] 80 | { 81 | 82 | } 83 | !RESOURCE[Oxidizer] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleTankManager 90 | Volume = 9.876543 //720.0 units of LF: conversion rate is 0.013717 m3/u 91 | DoCostPatch = True 92 | DoMassPatch = True 93 | TANK 94 | { 95 | name = LFO 96 | Volume = 100.0 97 | } 98 | } 99 | } 100 | 101 | @PART[KKAOSS_adapter_g]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 102 | { 103 | !RESOURCE[LiquidFuel] 104 | { 105 | 106 | } 107 | !RESOURCE[Oxidizer] 108 | { 109 | 110 | } 111 | MODULE 112 | { 113 | name = ModuleTankManager 114 | Volume = 0.617284 //45.0 units of LF: conversion rate is 0.013717 m3/u 115 | DoCostPatch = True 116 | DoMassPatch = True 117 | TANK 118 | { 119 | name = LFO 120 | Volume = 100.0 121 | } 122 | } 123 | } 124 | //LiquidFuel Tanks 125 | //Automatically generated using PyKSPutils library 126 | @PART[KKAOSS_Liquid_Fuel_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 127 | { 128 | !RESOURCE[LiquidFuel] 129 | { 130 | 131 | } 132 | MODULE 133 | { 134 | name = ModuleTankManager 135 | Volume = 1.234568 //200.0 units of LiquidFuel: conversion rate is 0.006173 m3/u 136 | DoCostPatch = True 137 | DoMassPatch = True 138 | TANK 139 | { 140 | TankType = LiquidChemicals 141 | CurrentResource = LiquidFuel 142 | InitialAmount = 1.0 143 | Volume = 100.0 144 | } 145 | } 146 | } 147 | //MonoPropellant Tanks 148 | //Automatically generated using PyKSPutils library 149 | @PART[KKAOSS_RCS_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 150 | { 151 | !RESOURCE[MonoPropellant] 152 | { 153 | 154 | } 155 | MODULE 156 | { 157 | name = ModuleTankManager 158 | Volume = 0.951087 //350.0 units of MonoPropellant: conversion rate is 0.002717 m3/u 159 | DoCostPatch = True 160 | DoMassPatch = True 161 | TANK 162 | { 163 | TankType = LiquidChemicals 164 | CurrentResource = MonoPropellant 165 | InitialAmount = 1.0 166 | Volume = 100.0 167 | } 168 | } 169 | } 170 | //XenonGas Tanks 171 | //Automatically generated using PyKSPutils library 172 | @PART[KKAOSS_Xenon_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 173 | { 174 | !RESOURCE[XenonGas] 175 | { 176 | 177 | } 178 | MODULE 179 | { 180 | name = ModuleSwitchableTank 181 | Volume = 0.472335 //5250.0 units of XenonGas: conversion rate is 0.000090 m3/u 182 | InitialAmount = 1.0 183 | DoCostPatch = True 184 | DoMassPatch = True 185 | ChooseTankType = False 186 | TankType = Gases 187 | CurrentResource = XenonGas 188 | } 189 | } 190 | //Ore Tanks 191 | //Automatically generated using PyKSPutils library 192 | @PART[KKAOSS_Small_Ore_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 193 | { 194 | !RESOURCE[Ore] 195 | { 196 | 197 | } 198 | MODULE 199 | { 200 | name = ModuleTankManager 201 | Volume = 1.081081 //200.0 units of Ore: conversion rate is 0.005405 m3/u 202 | DoCostPatch = True 203 | DoMassPatch = True 204 | TANK 205 | { 206 | TankType = Soil 207 | CurrentResource = Ore 208 | InitialAmount = 0.0 209 | Volume = 100.0 210 | } 211 | } 212 | } 213 | 214 | @PART[KKAOSS_Ore_Tank]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[PlanetaryBaseInc] 215 | { 216 | !RESOURCE[Ore] 217 | { 218 | 219 | } 220 | MODULE 221 | { 222 | name = ModuleTankManager 223 | Volume = 2.162162 //400.0 units of Ore: conversion rate is 0.005405 m3/u 224 | DoCostPatch = True 225 | DoMassPatch = True 226 | TANK 227 | { 228 | TankType = Soil 229 | CurrentResource = Ore 230 | InitialAmount = 0.0 231 | Volume = 100.0 232 | } 233 | } 234 | } 235 | //:mode=c#: 236 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/SpaceY-Expanded_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for SpaceY-Expanded 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[SYtank7mL03750]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 177.777778 //12960.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[SYtank10mL22500]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 1866.666667 //136080.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | 53 | @PART[SYtank10mL15000]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 54 | { 55 | !RESOURCE[LiquidFuel] 56 | { 57 | 58 | } 59 | !RESOURCE[Oxidizer] 60 | { 61 | 62 | } 63 | MODULE 64 | { 65 | name = ModuleTankManager 66 | Volume = 1244.444444 //90720.0 units of LF: conversion rate is 0.013717 m3/u 67 | DoCostPatch = True 68 | DoMassPatch = True 69 | TANK 70 | { 71 | name = LFO 72 | Volume = 100.0 73 | } 74 | } 75 | } 76 | 77 | @PART[SYtank10mL07500]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 78 | { 79 | !RESOURCE[LiquidFuel] 80 | { 81 | 82 | } 83 | !RESOURCE[Oxidizer] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleTankManager 90 | Volume = 622.222222 //45360.0 units of LF: conversion rate is 0.013717 m3/u 91 | DoCostPatch = True 92 | DoMassPatch = True 93 | TANK 94 | { 95 | name = LFO 96 | Volume = 100.0 97 | } 98 | } 99 | } 100 | 101 | @PART[SYtank7m5mAdapter2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 102 | { 103 | !RESOURCE[LiquidFuel] 104 | { 105 | 106 | } 107 | !RESOURCE[Oxidizer] 108 | { 109 | 110 | } 111 | MODULE 112 | { 113 | name = ModuleTankManager 114 | Volume = 133.333333 //9720.0 units of LF: conversion rate is 0.013717 m3/u 115 | DoCostPatch = True 116 | DoMassPatch = True 117 | TANK 118 | { 119 | name = LFO 120 | Volume = 100.0 121 | } 122 | } 123 | } 124 | 125 | @PART[SYtank10mL03750]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 126 | { 127 | !RESOURCE[LiquidFuel] 128 | { 129 | 130 | } 131 | !RESOURCE[Oxidizer] 132 | { 133 | 134 | } 135 | MODULE 136 | { 137 | name = ModuleTankManager 138 | Volume = 311.111111 //22680.0 units of LF: conversion rate is 0.013717 m3/u 139 | DoCostPatch = True 140 | DoMassPatch = True 141 | TANK 142 | { 143 | name = LFO 144 | Volume = 100.0 145 | } 146 | } 147 | } 148 | 149 | @PART[SYtank7mCone1]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 150 | { 151 | !RESOURCE[LiquidFuel] 152 | { 153 | 154 | } 155 | !RESOURCE[Oxidizer] 156 | { 157 | 158 | } 159 | MODULE 160 | { 161 | name = ModuleTankManager 162 | Volume = 100.0 //7290.0 units of LF: conversion rate is 0.013717 m3/u 163 | DoCostPatch = True 164 | DoMassPatch = True 165 | TANK 166 | { 167 | name = LFO 168 | Volume = 100.0 169 | } 170 | } 171 | } 172 | 173 | @PART[SYtank7mL15000]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 174 | { 175 | !RESOURCE[LiquidFuel] 176 | { 177 | 178 | } 179 | !RESOURCE[Oxidizer] 180 | { 181 | 182 | } 183 | MODULE 184 | { 185 | name = ModuleTankManager 186 | Volume = 711.111111 //51840.0 units of LF: conversion rate is 0.013717 m3/u 187 | DoCostPatch = True 188 | DoMassPatch = True 189 | TANK 190 | { 191 | name = LFO 192 | Volume = 100.0 193 | } 194 | } 195 | } 196 | 197 | @PART[SYtank7mL07500]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 198 | { 199 | !RESOURCE[LiquidFuel] 200 | { 201 | 202 | } 203 | !RESOURCE[Oxidizer] 204 | { 205 | 206 | } 207 | MODULE 208 | { 209 | name = ModuleTankManager 210 | Volume = 355.555556 //25920.0 units of LF: conversion rate is 0.013717 m3/u 211 | DoCostPatch = True 212 | DoMassPatch = True 213 | TANK 214 | { 215 | name = LFO 216 | Volume = 100.0 217 | } 218 | } 219 | } 220 | 221 | @PART[SYtank7m5mAdapter]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 222 | { 223 | !RESOURCE[LiquidFuel] 224 | { 225 | 226 | } 227 | !RESOURCE[Oxidizer] 228 | { 229 | 230 | } 231 | MODULE 232 | { 233 | name = ModuleTankManager 234 | Volume = 177.777778 //12960.0 units of LF: conversion rate is 0.013717 m3/u 235 | DoCostPatch = True 236 | DoMassPatch = True 237 | TANK 238 | { 239 | name = LFO 240 | Volume = 100.0 241 | } 242 | } 243 | } 244 | 245 | @PART[SYtank10m7mAdapter]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 246 | { 247 | !RESOURCE[LiquidFuel] 248 | { 249 | 250 | } 251 | !RESOURCE[Oxidizer] 252 | { 253 | 254 | } 255 | MODULE 256 | { 257 | name = ModuleTankManager 258 | Volume = 236.444444 //17236.8 units of LF: conversion rate is 0.013717 m3/u 259 | DoCostPatch = True 260 | DoMassPatch = True 261 | TANK 262 | { 263 | name = LFO 264 | Volume = 100.0 265 | } 266 | } 267 | } 268 | 269 | @PART[SYadapter7m3mX4]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Expanded] 270 | { 271 | !RESOURCE[LiquidFuel] 272 | { 273 | 274 | } 275 | !RESOURCE[Oxidizer] 276 | { 277 | 278 | } 279 | MODULE 280 | { 281 | name = ModuleTankManager 282 | Volume = 24.691358 //1800.0 units of LF: conversion rate is 0.013717 m3/u 283 | DoCostPatch = True 284 | DoMassPatch = True 285 | TANK 286 | { 287 | name = LFO 288 | Volume = 100.0 289 | } 290 | } 291 | } 292 | //:mode=c#: 293 | -------------------------------------------------------------------------------- /GameData/ConfigurableContainers/Parts/SpaceY-Lifters_Patch.cfg: -------------------------------------------------------------------------------- 1 | //Configurable Containers patch for SpaceY-Lifters 2 | 3 | //Rocket Fuel Tanks 4 | //Automatically generated using PyKSPutils library 5 | @PART[SYtank3mCone]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 6 | { 7 | !RESOURCE[LiquidFuel] 8 | { 9 | 10 | } 11 | !RESOURCE[Oxidizer] 12 | { 13 | 14 | } 15 | MODULE 16 | { 17 | name = ModuleTankManager 18 | Volume = 11.111111 //810.0 units of LF: conversion rate is 0.013717 m3/u 19 | DoCostPatch = True 20 | DoMassPatch = True 21 | TANK 22 | { 23 | name = LFO 24 | Volume = 100.0 25 | } 26 | } 27 | } 28 | 29 | @PART[SYtank5mCone2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 30 | { 31 | !RESOURCE[LiquidFuel] 32 | { 33 | 34 | } 35 | !RESOURCE[Oxidizer] 36 | { 37 | 38 | } 39 | MODULE 40 | { 41 | name = ModuleTankManager 42 | Volume = 33.333333 //2430.0 units of LF: conversion rate is 0.013717 m3/u 43 | DoCostPatch = True 44 | DoMassPatch = True 45 | TANK 46 | { 47 | name = LFO 48 | Volume = 100.0 49 | } 50 | } 51 | } 52 | 53 | @PART[SYtank5mL0375]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 54 | { 55 | !RESOURCE[LiquidFuel] 56 | { 57 | 58 | } 59 | !RESOURCE[Oxidizer] 60 | { 61 | 62 | } 63 | MODULE 64 | { 65 | name = ModuleTankManager 66 | Volume = 77.777778 //5670.0 units of LF: conversion rate is 0.013717 m3/u 67 | DoCostPatch = True 68 | DoMassPatch = True 69 | TANK 70 | { 71 | name = LFO 72 | Volume = 100.0 73 | } 74 | } 75 | } 76 | 77 | @PART[SYtank5mL1500]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 78 | { 79 | !RESOURCE[LiquidFuel] 80 | { 81 | 82 | } 83 | !RESOURCE[Oxidizer] 84 | { 85 | 86 | } 87 | MODULE 88 | { 89 | name = ModuleTankManager 90 | Volume = 311.111111 //22680.0 units of LF: conversion rate is 0.013717 m3/u 91 | DoCostPatch = True 92 | DoMassPatch = True 93 | TANK 94 | { 95 | name = LFO 96 | Volume = 100.0 97 | } 98 | } 99 | } 100 | 101 | @PART[SYtank5mL01875]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 102 | { 103 | !RESOURCE[LiquidFuel] 104 | { 105 | 106 | } 107 | !RESOURCE[Oxidizer] 108 | { 109 | 110 | } 111 | MODULE 112 | { 113 | name = ModuleTankManager 114 | Volume = 38.888889 //2835.0 units of LF: conversion rate is 0.013717 m3/u 115 | DoCostPatch = True 116 | DoMassPatch = True 117 | TANK 118 | { 119 | name = LFO 120 | Volume = 100.0 121 | } 122 | } 123 | } 124 | 125 | @PART[SYtank5mL0750]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 126 | { 127 | !RESOURCE[LiquidFuel] 128 | { 129 | 130 | } 131 | !RESOURCE[Oxidizer] 132 | { 133 | 134 | } 135 | MODULE 136 | { 137 | name = ModuleTankManager 138 | Volume = 155.555556 //11340.0 units of LF: conversion rate is 0.013717 m3/u 139 | DoCostPatch = True 140 | DoMassPatch = True 141 | TANK 142 | { 143 | name = LFO 144 | Volume = 100.0 145 | } 146 | } 147 | } 148 | 149 | @PART[SYtank3mCone2]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 150 | { 151 | !RESOURCE[LiquidFuel] 152 | { 153 | 154 | } 155 | !RESOURCE[Oxidizer] 156 | { 157 | 158 | } 159 | MODULE 160 | { 161 | name = ModuleTankManager 162 | Volume = 16.666667 //1215.0 units of LF: conversion rate is 0.013717 m3/u 163 | DoCostPatch = True 164 | DoMassPatch = True 165 | TANK 166 | { 167 | name = LFO 168 | Volume = 100.0 169 | } 170 | } 171 | } 172 | 173 | @PART[SYtank5m3mAdapter]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 174 | { 175 | !RESOURCE[LiquidFuel] 176 | { 177 | 178 | } 179 | !RESOURCE[Oxidizer] 180 | { 181 | 182 | } 183 | MODULE 184 | { 185 | name = ModuleTankManager 186 | Volume = 58.333333 //4252.5 units of LF: conversion rate is 0.013717 m3/u 187 | DoCostPatch = True 188 | DoMassPatch = True 189 | TANK 190 | { 191 | name = LFO 192 | Volume = 100.0 193 | } 194 | } 195 | } 196 | 197 | @PART[SYtank5mL1125]:HAS[!MODULE[InterstellarFuelSwitch],!MODULE[FSfuelSwitch],!MODULE[ModuleB9PartSwitch]:HAS[@SUBTYPE:HAS[#tankType]]]:NEEDS[!modularFuelTanks&!RealFuels]:AFTER[SpaceY-Lifters] 198 | { 199 | !RESOURCE[LiquidFuel] 200 | { 201 | 202 | } 203 | !RESOURCE[Oxidizer] 204 | { 205 | 206 | } 207 | MODULE 208 | { 209 | name = ModuleTankManager 210 | Volume = 233.333333 //17010.0 units of LF: conversion rate is 0.013717 m3/u 211 | DoCostPatch = True 212 | DoMassPatch = True 213 | TANK 214 | { 215 | name = LFO 216 | Volume = 100.0 217 | } 218 | } 219 | } 220 | //:mode=c#: 221 | -------------------------------------------------------------------------------- /IntrusivePatches/CC_INTRUSIVE_PATCHES.md: -------------------------------------------------------------------------------- 1 | # Intrusive Patches of Configurable Containers 2 | 3 | Intrusive patches are a set of Module Manager patches that remove other fuel switcher modules (like InterstellarFuelSwitch, FSFuelSwitch) or modify their configs (like removing fuel switching from B9PartSwitch) from many/all parts and replace them with the Configurable Containers' ones. 4 | 5 | You should use these with care on a progressed game with many ships in flight, because such transition is never fully reversible. That is, if you include these patches and then decide to remove them, your in-flight ships will not be returned to the _exact_ state they were in before. 6 | 7 | So I can't say it emphatically enough: 8 | 9 | **!!! BACKUP YOUR SAVES !!!** 10 | 11 | Having said that, I want to ensure you I do whatever I can to make the use of these patches safe. And generally it *is* indeed safe. 12 | -------------------------------------------------------------------------------- /IntrusivePatches/GameData/ConfigurableContainers/IntrusivePatches/B9Parts_Patch.cfg: -------------------------------------------------------------------------------- 1 | // Patch B9 and B9 HX Parts with fuel 2 | @PART[*B9*]:HAS[@MODULE[ModuleB9PartSwitch]:HAS[#baseVolume[>0]]]:NEEDS[B9_Aerospace|B9_Aerospace_HX]:FINAL 3 | { 4 | MODULE 5 | { 6 | name = ModuleTankManager 7 | Volume = #$../MODULE[ModuleB9PartSwitch]/baseVolume$ 8 | @Volume *= 0.00578038 //923747740083 (extra digits that I took out) 9 | DoCostPatch = True 10 | DoMassPatch = True 11 | TANK 12 | { 13 | name = LFO //I'm thinking the default should be really be liquid fuel but I'm not sure, 14 | Volume = 100.0 15 | } 16 | } 17 | 18 | @MODULE[ModuleB9PartSwitch],* 19 | { 20 | @SUBTYPE[*],* 21 | { 22 | !tankType = DEL // Get rid of the B9PartSwitch fuel switch without deleting the texture switching and creating weird z-fighting issues 23 | } 24 | } 25 | } 26 | //For the cockpits with monoprop 27 | @PART[*B9*]:HAS[@MODULE[ModuleCommand]&@RESOURCE[MonoPropellant]]:NEEDS[B9_Aerospace] 28 | { 29 | MODULE 30 | { 31 | name = ModuleSwitchableTank 32 | Volume = #$../RESOURCE[MonoPropellant]/maxAmount$ 33 | @Volume *= .002717 //now fixed to not be 1,000 times too high 34 | InitialAmount = 0.0 35 | DoCostPatch = True 36 | DoMassPatch = True 37 | ChooseTankType = True 38 | TankType = LiquidChemicals 39 | CurrentResource = MonoPropellant 40 | } 41 | !RESOURCE[MonoPropellant] {} 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Allis Tauri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ModuleTankManager.cs: -------------------------------------------------------------------------------- 1 | // ModuleTankManager.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using CC.UI; 9 | using JetBrains.Annotations; 10 | 11 | namespace AT_Utils 12 | { 13 | public class ModuleTankManager : AbstractResourceTank, ITankManagerHost, ITankManagerCapabilities 14 | { 15 | private SwitchableTankManager tank_manager; 16 | 17 | public SwitchableTankManager GetTankManager() 18 | { 19 | return tank_manager; 20 | } 21 | 22 | public override string GetInfo() 23 | { 24 | var info = $"Max. Volume: {Utils.formatVolume(Volume)}\n"; 25 | if(ModuleSave != null) 26 | info += SwitchableTankManager.GetInfo(this, ModuleSave); 27 | return info.Trim(); 28 | } 29 | 30 | protected override float TankCost(float defaultCost) 31 | { 32 | if(ModuleSave == null || tank_manager != null) 33 | return 0; 34 | var volumes = ConfigNodeObject.FromConfig(ModuleSave); 35 | return volumes.Cost(); 36 | } 37 | 38 | protected override float TankMass(float defaultMass) 39 | { 40 | if(ModuleSave == null || tank_manager != null) 41 | return 0; 42 | var volumes = ConfigNodeObject.FromConfig(ModuleSave); 43 | return volumes.AddMass(); 44 | } 45 | 46 | protected override float ResourcesCost(bool maxAmount = true) 47 | { 48 | if(ModuleSave == null || tank_manager != null) 49 | return 0; 50 | var volumes = ConfigNodeObject.FromConfig(ModuleSave); 51 | return volumes.ResourceCost(maxAmount); 52 | } 53 | 54 | protected override float ResourcesMass(bool maxAmount = true) 55 | { 56 | if(ModuleSave == null || tank_manager != null) 57 | return 0; 58 | var volumes = ConfigNodeObject.FromConfig(ModuleSave); 59 | return volumes.ResourceMass(maxAmount); 60 | } 61 | 62 | private void init_tank_manager() 63 | { 64 | if(tank_manager != null) 65 | return; 66 | tank_manager = new SwitchableTankManager(this); 67 | if(ModuleSave == null) 68 | { 69 | this.Log("ModuleSave is null. THIS SHOULD NEVER HAPPEN!"); 70 | return; 71 | } 72 | ModuleSave.SetValue("Volume", Volume); 73 | tank_manager.Load(ModuleSave); 74 | var used_volume = tank_manager.TanksVolume; 75 | if(used_volume > Volume) 76 | { 77 | this.Log( 78 | "WARNING: Volume limit is less than the total volume " + "of preconfigured tanks: {} - {} = {}", 79 | Volume, 80 | used_volume, 81 | Volume - used_volume); 82 | Volume = used_volume; 83 | } 84 | tank_manager.Volume = Volume; 85 | } 86 | 87 | protected override void init_from_part() 88 | { 89 | if(ModuleSave == null) 90 | ModuleSave = new ConfigNode("MODULE"); 91 | var volume = VolumeConfiguration.FromResources(part.Resources); 92 | if(volume == null) 93 | { 94 | Utils.Message("TankManager module is added to a part with unknown resource!\n" 95 | + "This is an error in MM patch.\n" 96 | + "TankManager module is disabled."); 97 | this.EnableModule(false); 98 | part.Modules.Remove(this); 99 | return; 100 | } 101 | volume.name = ModuleSave.GetValue("name"); 102 | ModuleSave.RemoveValue("Volume"); 103 | ModuleSave.RemoveNodes(TankVolume.NODE_NAME); 104 | volume.Save(ModuleSave); 105 | Volume = volume.Volume; 106 | DoCostPatch = false; 107 | DoMassPatch = true; 108 | // this.Log("ModuleSave was initialized from part in flight: {}", ModuleSave);//debug 109 | } 110 | 111 | public override void OnLoad(ConfigNode node) 112 | { 113 | base.OnLoad(node); 114 | ModuleSave = node; 115 | //FIXME: does not work, because MM does not add this value 116 | //if its an existing part and CC was just added by MM patch 117 | ModuleSaveFromPrefab |= node.GetValue("MM_REINITIALIZE") != null; 118 | } 119 | 120 | public override void OnSave(ConfigNode node) 121 | { 122 | base.OnSave(node); 123 | if(tank_manager != null) 124 | tank_manager.Save(node); 125 | else 126 | ModuleSave.CopyTo(node); 127 | } 128 | 129 | public override void OnStart(StartState state) 130 | { 131 | base.OnStart(state); 132 | init_tank_manager(); 133 | #if DEBUG 134 | tank_manager.EnablePartControls = false; 135 | #else 136 | tank_manager.EnablePartControls = !HighLogic.LoadedSceneIsEditor && tank_manager.TanksCount < 2; 137 | #endif 138 | var editTankEvent = Events[nameof(EditTanks)]; 139 | Utils.EnableEvent(editTankEvent, !tank_manager.EnablePartControls); 140 | if(HighLogic.LoadedSceneIsFlight) 141 | editTankEvent.guiName = "Manage Tanks"; 142 | } 143 | 144 | private void OnDestroy() 145 | { 146 | tank_manager?.UI?.Close(); 147 | } 148 | 149 | public void Rescale(float relative_scale, bool update_amounts = false) 150 | { 151 | Volume *= relative_scale; 152 | if(tank_manager == null) 153 | return; 154 | // temporarily set tank manager volume to max.float 155 | // to be able to rescale all tanks without clamping 156 | tank_manager.Volume = float.MaxValue; 157 | tank_manager.RescaleTanks(relative_scale, update_amounts); 158 | // then check if the resulting tanks volume exceeds the rescaled total volume 159 | // and increase the later if needed 160 | if(tank_manager.TanksVolume > Volume) 161 | Volume = tank_manager.TanksVolume; 162 | // finally, update tank manager volume 163 | tank_manager.Volume = Volume; 164 | } 165 | 166 | //interface for ProceduralParts 167 | [UsedImplicitly] 168 | [KSPEvent(guiActive = false, active = true)] 169 | private void OnPartVolumeChanged(BaseEventDetails data) 170 | { 171 | var volName = data.Get("volName"); 172 | var newTotalVolume = (float)data.Get("newTotalVolume"); 173 | if(volName == "Tankage" && !newTotalVolume.Equals(Volume)) 174 | Rescale(newTotalVolume / Volume, HighLogic.LoadedSceneIsEditor); 175 | } 176 | 177 | //interface for TweakScale 178 | [UsedImplicitly] 179 | [KSPEvent(guiActive = false, active = true)] 180 | private void OnPartScaleChanged(BaseEventDetails data) 181 | { 182 | var scale = data.Get("factorRelative"); 183 | if(!scale.Equals(1)) 184 | Rescale(scale * scale * scale, HighLogic.LoadedSceneIsEditor); 185 | } 186 | 187 | //workaround for ConfigNode non-serialization 188 | public override void OnBeforeSerialize() 189 | { 190 | if(tank_manager != null) 191 | { 192 | ModuleSave = new ConfigNode(); 193 | Save(ModuleSave); 194 | } 195 | base.OnBeforeSerialize(); 196 | } 197 | 198 | #region ITankManagerCapabilities 199 | public bool AddRemoveEnabled => HighLogic.LoadedSceneIsEditor; 200 | public bool ConfirmRemove => !HighLogic.LoadedSceneIsEditor; 201 | public bool TypeChangeEnabled => HighLogic.LoadedSceneIsEditor; 202 | public bool VolumeChangeEnabled => HighLogic.LoadedSceneIsEditor; 203 | public bool FillEnabled => HighLogic.LoadedSceneIsEditor; 204 | public bool EmptyEnabled => HighLogic.LoadedSceneIsEditor; 205 | #endregion 206 | 207 | #region GUI 208 | [KSPEvent(guiActive = true, guiActiveEditor = true, guiName = "Edit Tanks", active = true)] 209 | public void EditTanks() => tank_manager?.UI.Toggle(this); 210 | 211 | private void LateUpdate() 212 | { 213 | tank_manager?.UI.OnLateUpdate(); 214 | } 215 | #endregion 216 | } 217 | 218 | public class TankManagerUpdater : ModuleUpdater 219 | { 220 | protected override void on_rescale(ModulePair mp, Scale scale) 221 | { 222 | if(!scale.relative.volume.Equals(1)) 223 | mp.module.Rescale(scale.relative.volume, true); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // AssemblyInfo.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System; 9 | using System.Reflection; 10 | 11 | // Information about this assembly is defined by the following attributes. 12 | // Change them to the values specific to your project. 13 | 14 | [assembly: AssemblyTitle("ConfigurableContainers")] 15 | [assembly: AssemblyDescription("Plugin for developers of part addons for Kerbal Space Program")] 16 | [assembly: AssemblyConfiguration("")] 17 | [assembly: AssemblyCompany("")] 18 | [assembly: AssemblyProduct("")] 19 | [assembly: AssemblyCopyright("Allis Tauri")] 20 | [assembly: AssemblyTrademark("")] 21 | [assembly: AssemblyCulture("")] 22 | 23 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 24 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 25 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 26 | 27 | #if NIGHTBUILD 28 | [assembly: AssemblyVersion("2.6.*")] 29 | #else 30 | [assembly: AssemblyVersion("2.6.2.1")] 31 | #endif 32 | [assembly: KSPAssembly("ConfigurableContainers", 2, 6)] 33 | 34 | // The following attributes are used to specify the signing key for the assembly, 35 | // if desired. See the Mono documentation for more information about signing. 36 | 37 | //[assembly: AssemblyDelaySign(false)] 38 | //[assembly: AssemblyKeyFile("")] 39 | 40 | namespace AT_Utils 41 | { 42 | public class CCModInfo : KSP_AVC_Info 43 | { 44 | public CCModInfo() 45 | { 46 | MinKSPVersion = new Version(1, 12, 3); 47 | MaxKSPVersion = new Version(1, 12, 3); 48 | 49 | VersionURL = 50 | "https://github.com/allista/ConfigurableContainers/tree/master/GameData/ConfigurableContainers/ConfigurableContainers.version"; 51 | UpgradeURL = "https://spacedock.info/mod/1002/Configurable%20Containers"; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Configurable Containers 2 | 3 | ## Requirements 4 | 5 | * [ModuleManager](http://forum.kerbalspaceprogram.com/index.php?/topic/50533-12) 6 | * [AT_Utils](https://github.com/allista/AT_Utils) (already includeds) 7 | 8 | ## For Players 9 | 10 | This mod converts fuel tanks and resource containers so that you can change the resource(s) they hold in Editor and in Flight. 11 | 12 | ## Supported Mods 13 | 14 | Configurable Containers support many part packs and mods: 15 | 16 | * **TweakScale** 17 | * **ProceduralParts** 18 | * Parts ++with stock resources++ converted: 19 | * Stock 20 | * KW Rocketry 21 | * Mk2 Expansion 22 | * Mk3 Expansion 23 | * SpaceY-Lifters 24 | * SpaceY-Expanded 25 | * Fuel Tanks Plus 26 | * Modular Rocket Systems 27 | * Standard Propulsion Systems 28 | * Near Future Propulsion 29 | * Spherical and Toroidal Tank Pack 30 | * OPT Spaceplane Parts (made by octarine-noise) 31 | * ...more will come. 32 | * Supported resources: 33 | * Stock 34 | * TAC Life Support 35 | * Extrapalentary Launchapads 36 | * Near Future Propulsion 37 | * All USI 38 | * All KSPIE 39 | * ...more will come. 40 | 41 | ### Types of the Containers 42 | 43 | _Tank Type_ is a set of resources that, gamewise, have something in common. For example gases, or liquid chemicals, or metals. There are also two kinds of configurable containers. 44 | 45 | * **Simple** containers belong to a single Tank Type (which can be changed in Editor) and can hold only a single resource. In flight this resource may be changed only if the container is empty, and only within its Tank Type. 46 | * **Compound** containers are in fact collections of simple containers inside of a single part. In Editor you can partition the inside space of such part, creating as many simple containers as you need. The only restriction imposed by KSP is that a part cannot have two identical resources stored. So if you have two containers for liquid chemicals in a part, only one of them can hold Liquid Fuel. 47 | 48 | Compound containers have a dedicated user interface so as not to clutter part menu: 49 | 50 | ![TankManager GUI](http://i.imgur.com/6Tbr5JG.gif) 51 | 52 | ## For Modders 53 | 54 | ### CC is a part of the [AT_Utils](https://github.com/allista/AT_Utils) framework. 55 | 56 | It provides the **SwitchableTank** module that allows for creation of container parts for predefined sets of resources **switchable in-flight**. Sets are configured in a separate .cfg file and are intended to contain similar things like gases (one set), liquid chemicals (another) and so on. 57 | 58 | Another module Configurable Containers provide is the **TankManager** which enables _in-editor_ partitioning of a container, effectively converting it into a set of independent SwitchableTanks. 59 | 60 | The third, utility module named **SimpleTextureSwitcher** allows you to cycle through a predefined set of textures for the model or a part of the model, so a container may be easily identified. *It is now part of the main AT_Utils.dll, not the CC itself.* 61 | -------------------------------------------------------------------------------- /SwitchableTankManagerUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AT_Utils.UI; 3 | using CC.UI; 4 | using UnityEngine; 5 | using UnityEngine.EventSystems; 6 | 7 | namespace AT_Utils 8 | { 9 | public static class CC_UI 10 | { 11 | public static readonly UIBundle AssetBundle = UIBundle.Create("000_AT_Utils/cc_ui.bundle"); 12 | } 13 | 14 | public class SwitchableTankManagerUI : UIWindowBase 15 | { 16 | private readonly SwitchableTankManager manager; 17 | 18 | public SwitchableTankManagerUI(SwitchableTankManager manager) : base(CC_UI.AssetBundle) 19 | { 20 | this.manager = manager ?? throw new ArgumentNullException(nameof(manager)); 21 | } 22 | 23 | protected override void init_controller() 24 | { 25 | base.init_controller(); 26 | Controller.closeButton.onClick.AddListener(Close); 27 | Controller.colorSettingsButton.onClick.AddListener(toggleColors); 28 | Controller.onPointerEnterEvent.AddListener(highlightPart); 29 | Controller.onPointerExitEvent.AddListener(highlightPartDefault); 30 | Controller.SetTankManager(manager); 31 | if(manager != null) 32 | pos = manager.uiPos; 33 | } 34 | 35 | private void highlightPart(PointerEventData _) 36 | { 37 | var part = manager?.part; 38 | if(part != null) 39 | part.HighlightAlways(Colors.Active.color); 40 | } 41 | 42 | private void highlightPartDefault(PointerEventData _) 43 | { 44 | var part = manager?.part; 45 | if(part != null) 46 | part.SetHighlightDefault(); 47 | } 48 | 49 | public override void SyncState() 50 | { 51 | base.SyncState(); 52 | if(manager != null) 53 | manager.uiPos = pos; 54 | } 55 | 56 | protected override void onClose() 57 | { 58 | base.onClose(); 59 | highlightPartDefault(null); 60 | } 61 | 62 | public void Toggle(MonoBehaviour monoBehaviour) => Toggle(monoBehaviour, !manager.EnablePartControls); 63 | 64 | public void OnLateUpdate() 65 | { 66 | if(!IsShown) 67 | return; 68 | if(manager.EnablePartControls) 69 | { 70 | Close(); 71 | return; 72 | } 73 | if(FlightGlobals.ready && manager.part != null) 74 | Controller.gameObject.SetActive(manager.part.vessel == FlightGlobals.ActiveVessel); 75 | Controller.UpdateDisplay(); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /SwitchableTankType.cs: -------------------------------------------------------------------------------- 1 | // SwitchableTankType.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace AT_Utils 12 | { 13 | /// 14 | /// Type of a switchable tank. 15 | /// Defines resources that a tank of this type can hold, 16 | /// how much units of each resource a liter of volume contains, 17 | /// and portion of part's volume that can be used by the tank. 18 | /// 19 | public class SwitchableTankType : ConfigNodeObject 20 | { 21 | public new const string NODE_NAME = "TANKTYPE"; 22 | 23 | /// 24 | /// The additional mass of a tank of this type per volume. 25 | /// 26 | [Persistent] 27 | public float AddMassPerVolume = 0f; 28 | 29 | /// 30 | /// If the resources in this tank should boiloff with time. 31 | /// 32 | [Persistent] 33 | public bool Boiloff; 34 | 35 | /// 36 | /// If the resources in this tank should be actively cooled until below the boiloff temperature. 37 | /// 38 | [Persistent] 39 | public bool Cooling; 40 | 41 | private string info; 42 | 43 | /// 44 | /// The name of the tank type. 45 | /// It is possible to edit these nodes with MM using NODE[name] syntax. 46 | /// 47 | [Persistent] 48 | public string name; 49 | 50 | /// 51 | /// The string list of resources a tank of this type can hold. Format: 52 | /// ResourceName1 units_per_liter; ResourceName2 units_per_liter2; ... 53 | /// 54 | [Persistent] 55 | public string PossibleResources; 56 | 57 | /// 58 | /// The cost of a tank of this type per tank surface. 59 | /// 60 | [Persistent] 61 | public float TankCostPerSurface = 1f; 62 | 63 | /// 64 | /// The cost of a tank of this type per tank volume. 65 | /// 66 | [Persistent] 67 | public float TankCostPerVolume = 0f; 68 | 69 | /// 70 | /// The portion of a part's volume the tank can use. 71 | /// 72 | [Persistent] 73 | public float UsefulVolumeRatio = 1f; 74 | 75 | public SortedList Resources { get; private set; } 76 | public bool Valid => Resources != null && Resources.Count > 0; 77 | public IList ResourceNames => Resources.Keys; 78 | public TankResource DefaultResource => Resources.Values[0]; 79 | 80 | public TankResource this[string resourceName] 81 | { 82 | get 83 | { 84 | try 85 | { 86 | return Resources[resourceName]; 87 | } 88 | catch 89 | { 90 | return null; 91 | } 92 | } 93 | } 94 | 95 | public string Info 96 | { 97 | get 98 | { 99 | if(!Valid) 100 | return ""; 101 | if(info != null) 102 | return info; 103 | var _info = StringBuilderCache.Acquire(); 104 | _info.AppendLine("Tank can hold:"); 105 | foreach(var r in ResourceNames) 106 | _info.AppendLine( 107 | $"- {Resources[r].Name}: {Utils.formatUnits(Resources[r].UnitsPerLiter)}/L"); 108 | var useful_volume = UsefulVolume(100); 109 | if(useful_volume < 100) 110 | _info.AppendLine($"Only {useful_volume:F0}% of the volume is used for resources."); 111 | if(Boiloff || Cooling) 112 | _info.AppendLine("Tank is thermally insulated.\nEquipped with boil-off valve."); 113 | if(Cooling) 114 | _info.AppendLine("Equipped with Active Cooling System."); 115 | info = _info.ToStringAndRelease().Trim(); 116 | return info; 117 | } 118 | } 119 | 120 | public float Cost(float volume) 121 | { 122 | return volume * TankCostPerVolume + Utils.CubeSurface(volume) * TankCostPerSurface; 123 | } 124 | 125 | public float AddMass(float volume) 126 | { 127 | return volume * AddMassPerVolume; 128 | } 129 | 130 | public float GetEffectiveVolumeRatio() 131 | { 132 | var useful_volume = UsefulVolumeRatio; 133 | if(Boiloff || Cooling) 134 | useful_volume -= CryogenicsParams.Instance.InsulationVolumeFraction; 135 | return useful_volume < 0 ? 0 : useful_volume; 136 | } 137 | 138 | public float UsefulVolume(float volume) => volume * GetEffectiveVolumeRatio(); 139 | 140 | public override void Load(ConfigNode node) 141 | { 142 | base.Load(node); 143 | Resources = TankResource.ParseResourcesToSortedList(PossibleResources); 144 | } 145 | 146 | #region Tank Type Library 147 | /// 148 | /// The library of preconfigured tank types. 149 | /// 150 | public static SortedList TankTypes 151 | { 152 | get 153 | { 154 | if(_tank_types != null) 155 | return _tank_types; 156 | var nodes = GameDatabase.Instance.GetConfigNodes(NODE_NAME); 157 | _tank_types = new SortedList(); 158 | for(int i = 0, nodesLength = nodes.Length; i < nodesLength; i++) 159 | { 160 | var n = nodes[i]; 161 | #if DEBUG 162 | Utils.Log("\n{}", n.ToString()); 163 | #endif 164 | var tank_type = FromConfig(n); 165 | if(!tank_type.Valid) 166 | { 167 | var msg = 168 | $"[ConfigurableContainers] '{tank_type.name}' tank type has no resources. Skipping."; 169 | Utils.Message(6, msg); 170 | Utils.Warning(msg); 171 | continue; 172 | } 173 | try 174 | { 175 | _tank_types.Add(tank_type.name, tank_type); 176 | } 177 | catch 178 | { 179 | Utils.Error( 180 | $"SwitchableTankType: ignoring duplicate configuration of {tank_type.name} tank type. Use ModuleManager to change the existing one."); 181 | } 182 | } 183 | return _tank_types; 184 | } 185 | } 186 | 187 | private static SortedList _tank_types; 188 | 189 | /// 190 | /// Sorted list of tank type names. 191 | /// 192 | public static List TankTypeNames(string[] include = null, string[] exclude = null) 193 | { 194 | IEnumerable names; 195 | if(include != null && include.Length > 0) 196 | names = TankTypes.Keys.Where(n => include.IndexOf(n) >= 0); 197 | else if(exclude != null && exclude.Length > 0) 198 | names = TankTypes.Keys.Where(n => exclude.IndexOf(n) < 0); 199 | else 200 | names = TankTypes.Keys; 201 | return names.ToList(); 202 | } 203 | 204 | /// 205 | /// Determines if the library contains the specified tank type. 206 | /// 207 | /// Tank type name. 208 | public static bool HaveTankType(string tank_type) 209 | { 210 | return TankTypes.ContainsKey(tank_type); 211 | } 212 | 213 | /// 214 | /// Returns the TankType from the library, if it exists; null otherwise. 215 | /// 216 | /// Tank type name. 217 | public static SwitchableTankType GetTankType(string tank_type) 218 | { 219 | return TankTypes.TryGetValue(tank_type, out var t) ? t : null; 220 | } 221 | 222 | /// 223 | /// Finds the first tank type containing the specified resource. 224 | /// 225 | /// The tank type. 226 | /// Resource name. 227 | public static SwitchableTankType FindTankType(string resource_name) 228 | { 229 | foreach(var t in TankTypes) 230 | if(t.Value.Resources.ContainsKey(resource_name)) 231 | return t.Value; 232 | return null; 233 | } 234 | 235 | /// 236 | /// Returns TankType.Info for a type, if it exists; string.Empty otherwise. 237 | /// 238 | /// Tank type name. 239 | public static string GetTankTypeInfo(string tank_type) 240 | { 241 | return TankTypes.TryGetValue(tank_type, out var t) ? t.Info : string.Empty; 242 | } 243 | 244 | /// 245 | /// Returns info string describing available tank types 246 | /// 247 | public static string TypesInfo(string[] include = null, string[] exclude = null) 248 | { 249 | var info = StringBuilderCache.Acquire(); 250 | info.AppendLine("Supported Tank Types:"); 251 | TankTypeNames(include, exclude).ForEach(t => info.AppendLine($"- {t}")); 252 | return info.ToStringAndRelease().Trim(); 253 | } 254 | #endregion 255 | } 256 | 257 | 258 | /// 259 | /// A Part Resource Definition complemented with Units Per Liter ratio. 260 | /// 261 | public class TankResource : ResourceWrapper 262 | { 263 | public float UnitsPerLiter { get; private set; } 264 | public float UnitsPerVolume { get; private set; } 265 | 266 | public PartResourceDefinition def => PartResourceLibrary.Instance.GetDefinition(Name); 267 | 268 | public override void LoadDefinition(string resource_definition) 269 | { 270 | var upl = load_definition(resource_definition); 271 | if(!Valid) 272 | return; 273 | UnitsPerLiter = upl; 274 | UnitsPerVolume = upl * 1000; 275 | } 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /VolumeConfigsLibrary.cs: -------------------------------------------------------------------------------- 1 | // VolumeConfigsLibrary.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace AT_Utils 12 | { 13 | public static class VolumeConfigsLibrary 14 | { 15 | public const string USER_FILE = "VolumeConfigs.user"; 16 | 17 | private static SortedList presets; 18 | 19 | private static SortedList user_configs; 20 | public static string UserFile => CustomConfig.GameDataFolder("ConfigurableContainers", USER_FILE); 21 | 22 | /// 23 | /// The library of tank configurations provided by mods. 24 | /// 25 | public static SortedList PresetConfigs 26 | { 27 | get 28 | { 29 | if(presets != null) 30 | return presets; 31 | var nodes = GameDatabase.Instance.GetConfigNodes(VolumeConfiguration.NODE_NAME); 32 | presets = new SortedList(nodes.Length); 33 | foreach(var n in nodes) 34 | { 35 | Utils.Debug("Parsing preset tank configuration:\n{}", n); 36 | var cfg = ConfigNodeObject.FromConfig(n); 37 | if(!cfg.Valid) 38 | { 39 | var msg = $"ConfigurableContainers: configuration \"{cfg.name}\" is INVALID."; 40 | Utils.Message(6, msg); 41 | Utils.Error(msg); 42 | continue; 43 | } 44 | try 45 | { 46 | presets.Add(cfg.name, cfg); 47 | } 48 | catch 49 | { 50 | Utils.Warning("SwitchableTankType: ignoring duplicate configuration of '{}' configuration. " 51 | + "Use ModuleManager to change the existing one.", 52 | cfg.name); 53 | } 54 | } 55 | Utils.Debug("Parsed presets: {}", presets); 56 | return presets; 57 | } 58 | } 59 | 60 | /// 61 | /// The library of tank configurations saved by the user. 62 | /// 63 | /// The user configs. 64 | public static SortedList UserConfigs 65 | { 66 | get 67 | { 68 | if(user_configs != null) 69 | return user_configs; 70 | user_configs = new SortedList(); 71 | var node = CustomConfig.LoadNode(UserFile); 72 | Utils.Debug("Loading user configurations from:\n{}\n{}", UserFile, node); 73 | if(node == null) 74 | return user_configs; 75 | foreach(var n in node.GetNodes(VolumeConfiguration.NODE_NAME)) 76 | { 77 | var cfg = ConfigNodeObject.FromConfig(n); 78 | if(!cfg.Valid) 79 | { 80 | var msg = $"ConfigurableContainers: configuration \"{cfg.name}\" is INVALID."; 81 | Utils.Message(6, msg); 82 | Utils.Error(msg); 83 | continue; 84 | } 85 | if(SwitchableTankType.HaveTankType(cfg.name)) 86 | cfg.name += " [cfg]"; 87 | if(PresetConfigs.ContainsKey(cfg.name)) 88 | cfg.name += " [usr]"; 89 | add_unique(cfg, user_configs); 90 | } 91 | Utils.Debug("Parsed user presets: {}", user_configs); 92 | return user_configs; 93 | } 94 | } 95 | 96 | private static void add_unique(VolumeConfiguration cfg, IDictionary db) 97 | { 98 | var index = 1; 99 | var basename = cfg.name; 100 | while(db.ContainsKey(cfg.name)) 101 | cfg.name = string.Concat(basename, " ", index++); 102 | db.Add(cfg.name, cfg); 103 | } 104 | 105 | private static void save_user_configs() 106 | { 107 | var node = new ConfigNode(); 108 | UserConfigs.ForEach(c => c.Value.SaveInto(node)); 109 | if(CustomConfig.SaveNode(node, UserFile)) 110 | return; 111 | Utils.Message("Unable to save tank configurations."); 112 | } 113 | 114 | public static void AddConfig(VolumeConfiguration cfg) 115 | { 116 | add_unique(cfg, UserConfigs); 117 | save_user_configs(); 118 | } 119 | 120 | public static void AddOrSave(VolumeConfiguration cfg) 121 | { 122 | if(UserConfigs.ContainsKey(cfg.name)) 123 | UserConfigs[cfg.name] = cfg; 124 | else 125 | UserConfigs.Add(cfg.name, cfg); 126 | save_user_configs(); 127 | } 128 | 129 | public static bool RemoveConfig(string cfg_name) 130 | { 131 | if(!UserConfigs.Remove(cfg_name)) 132 | return false; 133 | save_user_configs(); 134 | return true; 135 | } 136 | 137 | public static List AllConfigNames(string[] include, string[] exclude) 138 | { 139 | var names = new List(); 140 | if(include != null && include.Length > 0) 141 | exclude = SwitchableTankType.TankTypeNames(null, include).ToArray(); 142 | if(exclude != null && exclude.Length > 0) 143 | { 144 | names.AddRange( 145 | from cfg in PresetConfigs 146 | where cfg.Value.ContainsTypes(exclude) 147 | select cfg.Value.name); 148 | names.AddRange( 149 | from cfg in UserConfigs 150 | where cfg.Value.ContainsTypes(exclude) 151 | select cfg.Value.name); 152 | } 153 | else 154 | { 155 | names.AddRange(PresetConfigs.Keys); 156 | names.AddRange(UserConfigs.Keys); 157 | } 158 | return names; 159 | } 160 | 161 | public static VolumeConfiguration GetConfig(string name) 162 | { 163 | if(string.IsNullOrEmpty(name)) 164 | return null; 165 | if(PresetConfigs.TryGetValue(name, out var cfg)) 166 | return cfg; 167 | if(UserConfigs.TryGetValue(name, out cfg)) 168 | return cfg; 169 | return null; 170 | } 171 | 172 | public static string GetConfigInfo(string name, float volume_conversion = 1) 173 | { 174 | var config = GetConfig(name); 175 | return config == null ? string.Empty : config.Info(volume_conversion); 176 | } 177 | 178 | public static bool HaveUserConfig(string name) 179 | { 180 | return UserConfigs.ContainsKey(name); 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /VolumeConfiguration.cs: -------------------------------------------------------------------------------- 1 | // VolumeConfiguration.cs 2 | // 3 | // Author: 4 | // Allis Tauri 5 | // 6 | // Copyright (c) 2016 Allis Tauri 7 | 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace AT_Utils 12 | { 13 | public class BaseVolume : ConfigNodeObject 14 | { 15 | public new const string NODE_NAME = "VOLUME"; 16 | [Persistent] public float Volume = 1; 17 | 18 | public virtual string Info(float volume_conversion = 1) 19 | { 20 | return $"{Utils.formatVolume(Volume * volume_conversion)}"; 21 | } 22 | 23 | public virtual float AddMass(float volume_conversion = 1) 24 | { 25 | return 0f; 26 | } 27 | 28 | public virtual float Cost(float volume_conversion = 1) 29 | { 30 | return 0f; 31 | } 32 | 33 | public virtual float ResourceCost(bool maxAmount = true, float volume_conversion = 1) 34 | { 35 | return 0f; 36 | } 37 | 38 | public virtual float ResourceMass(bool maxAmount = true, float volume_conversion = 1) 39 | { 40 | return 0f; 41 | } 42 | 43 | public virtual float ResourceAmount(bool maxAmount = true, float volume_conversion = 1) 44 | { 45 | return 0f; 46 | } 47 | 48 | public virtual bool ContainsType(string tank_type) 49 | { 50 | return false; 51 | } 52 | } 53 | 54 | 55 | public class TankVolume : BaseVolume 56 | { 57 | public new const string NODE_NAME = "TANK"; 58 | [Persistent] public string CurrentResource; 59 | [Persistent] public float InitialAmount; 60 | 61 | [Persistent] public string TankType; 62 | 63 | public SwitchableTankType Type => SwitchableTankType.GetTankType(TankType); 64 | 65 | public override float AddMass(float volume_conversion = 1) 66 | { 67 | var t = Type; 68 | return t?.AddMass(Volume * volume_conversion) ?? 0; 69 | } 70 | 71 | public override float Cost(float volume_conversion = 1) 72 | { 73 | var t = Type; 74 | return t?.Cost(Volume * volume_conversion) ?? 0; 75 | } 76 | 77 | public override float ResourceCost(bool maxAmount = true, float volume_conversion = 1) 78 | { 79 | try 80 | { 81 | var t = Type; 82 | var res = t.Resources[CurrentResource]; 83 | var cost = res.def.unitCost * res.UnitsPerLiter * t.UsefulVolume(Volume) * volume_conversion * 1000; 84 | return maxAmount ? cost : cost * InitialAmount; 85 | } 86 | catch 87 | { 88 | return 0; 89 | } 90 | } 91 | 92 | public override float ResourceMass(bool maxAmount = true, float volume_conversion = 1) 93 | { 94 | try 95 | { 96 | var t = Type; 97 | var res = t.Resources[CurrentResource]; 98 | var mass = res.def.density * res.UnitsPerLiter * t.UsefulVolume(Volume) * volume_conversion * 1000; 99 | return maxAmount ? mass : mass * InitialAmount; 100 | } 101 | catch 102 | { 103 | return 0; 104 | } 105 | } 106 | 107 | public override float ResourceAmount(bool maxAmount = true, float volume_conversion = 1) 108 | { 109 | try 110 | { 111 | var t = Type; 112 | var res = t.Resources[CurrentResource]; 113 | var amount = res.UnitsPerLiter * t.UsefulVolume(Volume) * volume_conversion * 1000; 114 | return maxAmount ? amount : amount * InitialAmount; 115 | } 116 | catch 117 | { 118 | return 0; 119 | } 120 | } 121 | 122 | public override string Info(float volume_conversion = 1) 123 | { 124 | var haveResource = !string.IsNullOrEmpty(CurrentResource); 125 | var info = StringBuilderCache.Acquire(); 126 | info.Append($"- {TankType}"); 127 | if(haveResource) 128 | info.Append($"\n {CurrentResource}"); 129 | info.Append($"\n {Utils.formatVolume(Volume * volume_conversion)}"); 130 | if(haveResource) 131 | { 132 | info.Append($"\n {Utils.formatBigValue(ResourceAmount(true, volume_conversion), "u")}"); 133 | info.Append($"\n {Utils.formatBigValue(ResourceMass(true, volume_conversion), "t")}"); 134 | } 135 | info.Append($"\n {Cost(volume_conversion):F1}"); 136 | if(InitialAmount > 0) 137 | info.Append($"+{ResourceCost(false, volume_conversion):F1}"); 138 | info.Append(" Cr"); 139 | return info.ToStringAndRelease().Trim(); 140 | } 141 | 142 | public override bool ContainsType(string tank_type) 143 | { 144 | return TankType == tank_type; 145 | } 146 | 147 | public static TankVolume FromResource(PartResource res) 148 | { 149 | var tank = new TankVolume(); 150 | var tank_type = SwitchableTankType.FindTankType(res.resourceName); 151 | if(tank_type == null) 152 | return null; 153 | tank.TankType = tank_type.name; 154 | tank.CurrentResource = res.resourceName; 155 | tank.Volume = (float)(res.maxAmount 156 | / tank_type.Resources[res.resourceName].UnitsPerLiter 157 | / 1000 158 | / tank_type.UsefulVolumeRatio); 159 | tank.InitialAmount = (float)(res.amount / res.maxAmount); 160 | return tank; 161 | } 162 | } 163 | 164 | 165 | public class VolumeConfiguration : BaseVolume 166 | { 167 | public new const string NODE_NAME = "TANKCONF"; 168 | 169 | /// 170 | /// The name of a configuration. 171 | /// 172 | [Persistent] 173 | public string name = ""; 174 | 175 | public readonly List Volumes = new List(); 176 | public float TotalVolume { get { return Volumes.Aggregate(0f, (v, t) => v + t.Volume); } } 177 | public bool Valid => Volumes.Count > 0 && TotalVolume > 0; 178 | 179 | public override void Load(ConfigNode node) 180 | { 181 | Volumes.Clear(); 182 | base.Load(node); 183 | var volumes = node.GetNodes(); 184 | for(var i = 0; i < volumes.Length; i++) 185 | { 186 | var v = volumes[i]; 187 | switch(v.name) 188 | { 189 | case TankVolume.NODE_NAME: 190 | { 191 | var preset = VolumeConfigsLibrary.GetConfig(v.GetValue("name")); 192 | if(preset != null) 193 | { 194 | if(!float.TryParse(v.GetValue("Volume"), out var volume)) 195 | volume = 100f; 196 | var cfg = preset.Clone(); 197 | cfg.Volume = volume; 198 | Volumes.Add(cfg); 199 | } 200 | else 201 | { 202 | Volumes.Add(FromConfig(v)); 203 | } 204 | break; 205 | } 206 | case NODE_NAME: 207 | Volumes.Add(FromConfig(v)); 208 | break; 209 | } 210 | } 211 | } 212 | 213 | public override void Save(ConfigNode node) 214 | { 215 | base.Save(node); 216 | Volumes.ForEach(t => t.SaveInto(node)); 217 | } 218 | 219 | public override string Info(float volume_conversion = 1) 220 | { 221 | if(!Valid) 222 | return $"{name}: configuration invalid"; 223 | var info = StringBuilderCache.Acquire(); 224 | volume_conversion = Volume * volume_conversion / TotalVolume; 225 | Volumes.ForEach(v => 226 | { 227 | info.AppendLine(v.Info(volume_conversion)); 228 | info.AppendLine(); 229 | }); 230 | return info.ToStringAndRelease().Trim(); 231 | } 232 | 233 | public override float AddMass(float volume_conversion = 1) 234 | { 235 | volume_conversion = Volume * volume_conversion / TotalVolume; 236 | return Volumes.Aggregate(0f, (s, v) => s + v.AddMass(volume_conversion)); 237 | } 238 | 239 | public override float Cost(float volume_conversion = 1) 240 | { 241 | volume_conversion = Volume * volume_conversion / TotalVolume; 242 | return Volumes.Aggregate(0f, (s, v) => s + v.Cost(volume_conversion)); 243 | } 244 | 245 | public override float ResourceCost(bool maxAmount = true, float volume_conversion = 1) 246 | { 247 | volume_conversion = Volume * volume_conversion / TotalVolume; 248 | return Volumes.Aggregate(0f, (s, v) => s + v.ResourceCost(maxAmount, volume_conversion)); 249 | } 250 | 251 | public override float ResourceMass(bool maxAmount = true, float volume_conversion = 1) 252 | { 253 | volume_conversion = Volume * volume_conversion / TotalVolume; 254 | return Volumes.Aggregate(0f, (s, v) => s + v.ResourceMass(maxAmount, volume_conversion)); 255 | } 256 | 257 | public override bool ContainsType(string tank_type) 258 | { 259 | return Volumes.Any(v => v.ContainsType(tank_type)); 260 | } 261 | 262 | public bool ContainsTypes(IEnumerable tank_types) 263 | { 264 | return tank_types.Any(ContainsType); 265 | } 266 | 267 | public static VolumeConfiguration FromResources(IEnumerable resources) 268 | { 269 | var volume = new VolumeConfiguration(); 270 | foreach(var res in resources) 271 | { 272 | var tank = TankVolume.FromResource(res); 273 | if(tank == null) 274 | return null; 275 | volume.Volumes.Add(tank); 276 | } 277 | volume.Volume = volume.TotalVolume; 278 | return volume; 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /modconfig.yaml: -------------------------------------------------------------------------------- 1 | dll_path: ../GameData/000_AT_Utils/Plugins/ConfigurableContainers.dll 2 | archive_path: Releases 3 | github_url: allista/ConfigurableContainers 4 | spacedock_mod_id: 1002 5 | game_data_path: GameData 6 | additional_data_paths: 7 | - '../GameData' 8 | - 'IntrusivePatches' 9 | exclude_patterns: 10 | - '*/@thumbs/*' 11 | - '*/config.xml' 12 | - '*.user' 13 | - '*.orig' 14 | - '*.mdb' 15 | - '*.pdb' 16 | - '*/System.*.dll' 17 | - '*/Mono.*.dll' 18 | - '*/Unity*.dll' 19 | - 'GameData/000_AT_Utils/Plugins/AnimatedConverters.dll' 20 | - 'GameData/000_AT_Utils/Plugins/002_MultiAnimators.dll' 21 | - 'GameData/000_AT_Utils/Plugins/SubmodelResizer.dll' 22 | - 'GameData/000_AT_Utils/ResourceHack.cfg' 23 | --------------------------------------------------------------------------------