public int UpdateSymmetryCounterparts() { int i = 0; foreach (Part sPart in part.symmetryCounterparts) { ModuleFuelTanks fuel = (ModuleFuelTanks)sPart.Modules["ModuleFuelTanks"]; if (fuel) { i++; foreach (ModuleFuelTanks.FuelTank tank in fuel.fuelList) { tank.amount = 0; tank.maxAmount = 0; } foreach (ModuleFuelTanks.FuelTank tank in this.fuelList) { if (tank.maxAmount > 0) { ModuleFuelTanks.FuelTank pTank = fuel.fuelList.Find(t => t.name.Equals(tank.name)); if (pTank) { pTank.maxAmount = tank.maxAmount; pTank.amount = tank.amount; } } } } } return(i); }
public override void OnUpdate() { if (HighLogic.LoadedSceneIsEditor) { } else if (timestamp > 0 && part.parent != null && part.parent.Modules.Contains("ModuleFuelTanks")) { // We're connected to a fuel tank, so let's top off any depleting resources // first, get the time since the last OnUpdate() double delta_t = Planetarium.GetUniversalTime() - timestamp; // now, let's look at what we're connected to. ModuleFuelTanks m = (ModuleFuelTanks)part.parent.Modules["ModuleFuelTanks"]; // look through all tanks inside this part foreach (ModuleFuelTanks.FuelTank tank in m.fuelList) { // if a tank isn't full, start filling it. if (tank.amount < tank.maxAmount) { double top_off = delta_t * pump_rate; if (tank.amount + top_off < tank.maxAmount) { tank.amount += top_off; } else { tank.amount = tank.maxAmount; } } } // save the time so we can tell how much time has passed on the next update, even in Warp timestamp = Planetarium.GetUniversalTime(); } else { // save the time so we can tell how much time has passed on the next update, even in Warp timestamp = Planetarium.GetUniversalTime(); } }
private void fuelManagerGUI(int WindowID) { GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label("Current mass: " + ModuleFuelTanks.RoundTo4SigFigs(part.mass + part.GetResourceMass()) + " Ton(s)"); GUILayout.Label("Dry mass: " + Math.Round(1000 * part.mass) / 1000.0 + " Ton(s)"); GUILayout.EndHorizontal(); if (fuelList.Count == 0) { GUILayout.BeginHorizontal(); GUILayout.Label("This fuel tank cannot hold resources."); GUILayout.EndHorizontal(); return; } print("fuelManagerGUI Row 2"); GUILayout.BeginHorizontal(); GUILayout.Label("Available volume: " + availableVolume + " / " + volume); GUILayout.EndHorizontal(); int text_field = 0; foreach (ModuleFuelTanks.FuelTank tank in fuelList) { print("fuelManagerGUI Row 3." + tank.ToString()); GUILayout.BeginHorizontal(); int amountField = text_field; text_field++; if (textFields.Count < text_field) { textFields.Add(""); textFields[amountField] = tank.amount.ToString(); } int maxAmountField = text_field; text_field++; if (textFields.Count < text_field) { textFields.Add(""); textFields[maxAmountField] = tank.maxAmount.ToString(); } GUILayout.Label(" " + tank, GUILayout.Width(120)); if (part.Resources.Contains(tank) && part.Resources[tank].maxAmount > 0.0) { double amount = ModuleFuelTanks.RoundTo4SigFigs(part.Resources[tank].amount); double maxAmount = ModuleFuelTanks.RoundTo4SigFigs(part.Resources[tank].maxAmount); GUIStyle color = new GUIStyle(GUI.skin.textField); if (textFields[amountField].Trim().Equals("")) // I'm not sure why this happens, but we'll fix it here. { textFields[amountField] = tank.amount.ToString(); } else if (textFields[amountField].Equals(amount.ToString())) { color.normal.textColor = Color.white; } else { color.normal.textColor = Color.yellow; } textFields[amountField] = GUILayout.TextField(textFields[amountField], color, GUILayout.Width(65)); GUILayout.Label("/", GUILayout.Width(5)); color = new GUIStyle(GUI.skin.textField); if (textFields[maxAmountField].Equals(maxAmount.ToString())) { color.normal.textColor = Color.white; } else { color.normal.textColor = Color.yellow; } textFields[maxAmountField] = GUILayout.TextField(textFields[maxAmountField], color, GUILayout.Width(65)); GUILayout.Label(" ", GUILayout.Width(5)); if (GUILayout.Button("Update", GUILayout.Width(60))) { double newMaxAmount = maxAmount; if (!double.TryParse(textFields[maxAmountField], out newMaxAmount)) { newMaxAmount = maxAmount; } double newAmount = amount; if (!double.TryParse(textFields[amountField], out newAmount)) { newAmount = amount; } if (newMaxAmount != maxAmount) { tank.maxAmount = newMaxAmount; } if (newAmount != amount) { tank.amount = newAmount; } textFields[amountField] = tank.amount.ToString(); textFields[maxAmountField] = tank.maxAmount.ToString(); if (part.symmetryCounterparts.Count > 0) { UpdateSymmetryCounterparts(); } } if (GUILayout.Button("Remove", GUILayout.Width(60))) { tank.maxAmount = 0; textFields.Clear(); if (part.symmetryCounterparts.Count > 0) { UpdateSymmetryCounterparts(); } } } else if (availableVolume >= 0.001) { string extraData = "Max: " + ModuleFuelTanks.RoundTo4SigFigs(availableVolume * tank.efficiency).ToString() + " (+" + ModuleFuelTanks.RoundTo4SigFigs(availableVolume * tank.efficiency * tank.mass) + " tons)"; GUILayout.Label(extraData, GUILayout.Width(150)); if (GUILayout.Button("Add", GUILayout.Width(130))) { tank.maxAmount = Math.Floor(1000 * availableVolume * tank.efficiency) / 1000.0; tank.amount = tank.maxAmount; textFields.Clear(); if (part.symmetryCounterparts.Count > 0) { UpdateSymmetryCounterparts(); } } } else { GUILayout.Label(" No room for tank.", GUILayout.Width(150)); } GUILayout.EndHorizontal(); } print("fuelManagerGUI Row 4"); GUILayout.BeginHorizontal(); if (GUILayout.Button("Remove All Tanks")) { textFields.Clear(); foreach (ModuleFuelTanks.FuelTank tank in fuelList) { tank.amount = 0; tank.maxAmount = 0; } if (part.symmetryCounterparts.Count > 0) { UpdateSymmetryCounterparts(); } } GUILayout.EndHorizontal(); if (GetEnginesFedBy(part).Count > 0) { List <string> check_dupes = new List <string>(); print("fuelManagerGUI Row 5"); GUILayout.BeginHorizontal(); GUILayout.Label("Configure remaining volume for engines:"); GUILayout.EndHorizontal(); foreach (Part engine in GetEnginesFedBy(part)) { double ratio_factor = 0.0; double inefficiency = 0.0; ModuleEngines thruster = (ModuleEngines)engine.Modules["ModuleEngines"]; // tank math: // inefficiency = sum[(1 - efficiency) * ratio] // fluid_v = v * (1 - inefficiency) // f = fluid_v * ratio foreach (ModuleEngines.Propellant tfuel in thruster.propellants) { if (PartResourceLibrary.Instance.GetDefinition(tfuel.name) == null) { print("Unknown RESOURCE {" + tfuel.name + "}"); ratio_factor = 0.0; break; } else if (PartResourceLibrary.Instance.GetDefinition(tfuel.name).resourceTransferMode == ResourceTransferMode.NONE) { //ignore this propellant, since it isn't serviced by fuel tanks } else { ModuleFuelTanks.FuelTank tank = fuelList.Find(f => f.ToString().Equals(tfuel.name)); if (tank) { inefficiency += (1 - tank.efficiency) * tfuel.ratio; ratio_factor += tfuel.ratio; } else { ratio_factor = 0.0; break; } } } if (ratio_factor > 0.0) { string label = ""; foreach (ModuleEngines.Propellant tfuel in thruster.propellants) { if (PartResourceLibrary.Instance.GetDefinition(tfuel.name).resourceTransferMode != ResourceTransferMode.NONE) { if (label.Length > 0) { label += " / "; } label += Math.Round(100 * tfuel.ratio / ratio_factor).ToString() + "% " + tfuel.name; } } if (!check_dupes.Contains(label)) { check_dupes.Add(label); print("fuelManagerGUI Row 6." + label); GUILayout.BeginHorizontal(); if (GUILayout.Button(label)) { textFields.Clear(); double total_volume = availableVolume * (1 - inefficiency / ratio_factor); foreach (ModuleEngines.Propellant tfuel in thruster.propellants) { if (PartResourceLibrary.Instance.GetDefinition(tfuel.name).resourceTransferMode != ResourceTransferMode.NONE) { ModuleFuelTanks.FuelTank tank = fuelList.Find(t => t.name.Equals(tfuel.name)); if (tank) { tank.maxAmount += Math.Floor(1000 * total_volume * tfuel.ratio / ratio_factor) / 1000.0; tank.amount += Math.Floor(1000 * total_volume * tfuel.ratio / ratio_factor) / 1000.0; } } } if (part.symmetryCounterparts.Count > 0) { UpdateSymmetryCounterparts(); } } GUILayout.EndHorizontal(); } } } } GUILayout.EndVertical(); print("fuelManagerGUI Done."); }
public override void OnStart(StartState state) { #if DEBUG print("========ModuleFuelTanks.OnStart( State == " + state.ToString() + ")======="); #endif if (basemass == 0 && part != null) { basemass = part.mass; } if (fuelList == null) { fuelList = new List <ModuleFuelTanks.FuelTank> (); } if (fuelList.Count == 0) { // when we get called from the editor, the fuelList won't be populated // because OnLoad() was never called. This is a hack to fix that. Part prefab = part.symmetryCounterparts.Find(pf => pf.Modules.Contains("ModuleFuelTanks") && ((ModuleFuelTanks)pf.Modules["ModuleFuelTanks"]).fuelList.Count > 0); if (prefab) { #if DEBUG print("ModuleFuelTanks.OnStart: copying from a symmetryCounterpart with a ModuleFuelTanks PartModule"); #endif } else { AvailablePart partData = PartLoader.getPartInfoByName(part.partInfo.name); if (partData == null) { print("ModuleFuelTanks.OnStart could not find AvailablePart for " + part.partInfo.name); } else if (partData.partPrefab == null) { print("ModuleFuelTanks.OnStart: AvailablePart.partPrefab is null."); } else { prefab = partData.partPrefab; if (!prefab.Modules.Contains("ModuleFuelTanks")) { print("ModuleFuelTanks.OnStart: AvailablePart.partPrefab does not contain a ModuleFuelTanks."); prefab = null; } } } if (prefab) { ModuleFuelTanks pModule = (ModuleFuelTanks)prefab.Modules["ModuleFuelTanks"]; if (pModule == this) { print("ModuleFuelTanks.OnStart: Copying from myself won't do any good."); } else { ConfigNode node = new ConfigNode("MODULE"); pModule.OnSave(node); #if DEBUG print("ModuleFuelTanks.OnStart node from prefab:" + node); #endif this.OnLoad(node); } } } foreach (FuelTank tank in fuelList) { tank.module = this; } if (radius > 0 && length > 0) { part.transform.localScale = new Vector3(rscale / radius, length, rscale / radius); foreach (AttachNode n in part.attachNodes) { if (n.nodeType == AttachNode.NodeType.Stack) { n.offset.y *= length; } } } part.mass = basemass + tank_mass; if (HighLogic.LoadedSceneIsEditor) { UpdateSymmetryCounterparts(); // if we detach and then re-attach a configured tank with symmetry on, make sure the copies are configured. } }