// Constructor PersistentPropellant(Propellant p) { propellant = p; definition = PartResourceLibrary.Instance.GetDefinition(propellant.name); density = definition.density; ratio = propellant.ratio; }
public ElectricEnginePropellant(ConfigNode node) { propellantname = node.GetValue("name"); propellantguiname = node.GetValue("guiName"); ispMultiplier = Convert.ToDouble(node.GetValue("ispMultiplier")); efficiency = Convert.ToDouble(node.GetValue("efficiency")); prop_type = Convert.ToInt32(node.GetValue("type")); effectname = node.GetValue("effectName"); ConfigNode propellantnode = node.GetNode("PROPELLANT"); propellant = new Propellant(); propellant.Load(propellantnode); }
public ElectricEnginePropellant(ConfigNode node) { propellantname = node.GetValue("name"); propellantguiname = node.GetValue("guiName"); ispMultiplier = Convert.ToSingle(node.GetValue("ispMultiplier")); thrustMultiplier = node.HasValue("thrustMultiplier") ? Convert.ToSingle(node.GetValue("thrustMultiplier")) : 1; thrustMultiplierCold = node.HasValue("thrustMultiplierCold") ? Convert.ToSingle(node.GetValue("thrustMultiplierCold")) : thrustMultiplier; wasteheatMultiplier = node.HasValue("wasteheatMultiplier") ? Convert.ToDouble(node.GetValue("wasteheatMultiplier")) : 1; efficiency = Convert.ToDouble(node.GetValue("efficiency")); prop_type = Convert.ToInt32(node.GetValue("type")); effectname = node.GetValue("effectName"); techRquirement = node.HasValue("techRequirement") ? node.GetValue("techRequirement") : String.Empty; ConfigNode propellantnode = node.GetNode("PROPELLANT"); propellant = new Propellant(); propellant.Load(propellantnode); }
private void FuelConsumptionFromEngineModule(ModuleEngines e, ref double totalThrust, ref double totalThrust_Isp, ref double fuelConsumptionVol, ref double airDemandVol, double invDeltaTime) { if (e.EngineIgnited && !e.engineShutdown) { totalThrust += e.finalThrust; totalThrust_Isp += e.finalThrust * e.realIsp; for (int i = 0; i < e.propellants.Count; i++) { Propellant v = e.propellants[i]; if (v.id == intakeAirId) { airDemandVol += v.currentRequirement; } if (!v.ignoreForIsp) { fuelConsumptionVol += v.currentRequirement * invDeltaTime; } } } }
private double consumeResource(Propellant propellant, float consumption, Part part) { double requestAmount = consumption * propellant.ratio * fuelFlow * TimeWarp.deltaTime; if (requestAmount < minAmount) { if (requestAmount <= 0f) { requestAmount = 0f; } else { requestAmount = minAmount; } } if (requestAmount > 0f) { double recievedAmount = part.RequestResource(propellant.id, requestAmount, propellant.GetFlowMode()); return(recievedAmount / requestAmount); } return(1); }
private void SetMode() { if (multiEngine.runningPrimary) { EngineModeID = 0; } else { EngineModeID = 1; } Utils.Log("VariableIspEngine: Changing mode to " + engineModes[EngineModeID].name); CurrentEngineID = engineModes[EngineModeID].name; engine = engines[EngineModeID]; ThrustCurve = engineModes[EngineModeID].thrustCurve; IspCurve = engineModes[EngineModeID].ispCurve; for (int i = 0; i < engine.propellants.Count; i++) { if (engine.propellants[i].name != "ElectricCharge") { fuelPropellant = engine.propellants[i]; } else { ecPropellant = engine.propellants[i]; } } //Utils.Log("VariableIspEngine: Changed mode to " + engine.engineID); Utils.Log("VariableIspEngine: Fuel: " + fuelPropellant.name); Utils.Log("VariableIspEngine: Thrust Curve: " + ThrustCurve.Evaluate(0f) + " to " + ThrustCurve.Evaluate(1f)); Utils.Log("VariableIspEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f)); AdjustVariableThrust(); }
public override void OnStart(PartModule.StartState state) { base.OnStart(state); engine = part.GetComponent<ModuleEnginesFX>(); Propellant fuelPropellant = new Propellant(); foreach (Propellant prop in engine.propellants) { if (prop.name != "ElectricCharge") fuelPropellant = prop; } ThrustCurve = new FloatCurve(); ThrustCurve.Add(0f, engine.maxThrust); ThrustCurve.Add(minPressure, minThrust); AtmoCurve = new FloatCurve(); AtmoCurve.Add(0f, engine.atmosphereCurve.Evaluate(0f)); float rate = FindFlowRate (engine.maxThrust,engine.atmosphereCurve.Evaluate(0f),fuelPropellant); AtmoCurve.Add(1f,FindIsp(minThrust,rate,fuelPropellant)); }
private float FindThrust(float isp, float flowRate, Propellant fuelPropellant) { double fuelDensity = PartResourceLibrary.Instance.GetDefinition(fuelPropellant.name).density; double thrust = Utils.GRAVITY * isp * flowRate; //double isp = (((thrust * 1000f) / (Utils.GRAVITY)) / flowRate) / (fuelDensity * 1000f); return (float)isp; }
public void MarkPropellant(Propellant propel) { ResourceData r = nameResources[propel.name]; r.ispropellant = true; }
/// <summary> /// Get the vessel's acceleration ability, in m/s2 /// </summary> /// <param name="propellantsConsumed">All the propellants consumed, in tons/second for each one</param> /// <param name="totalThrust">The total thrust produced, in kilonewtons</param> private void GetThrustInfo( Tally propellantsConsumed, out double totalThrust) { // Add up all the thrust for all the active engines on the vessel. // We do this as a vector because the engines might not be parallel to each other. Vector3 totalThrustVector = Vector3.zero; totalThrust = 0.0F; propellantsConsumed.Zero(); Tally availableResources = vessel.AvailableResources; int engineCount = 0; for (int engineIndex = 0; engineIndex < vessel.ActiveEngines.Count; ++engineIndex) { ModuleEngines engine = vessel.ActiveEngines[engineIndex]; if (engine.thrustPercentage > 0) { double engineKilonewtons = engine.ThrustLimit(); if (!CheatOptions.InfinitePropellant) { // Possible future consideraiton: // Get the vacuum Isp from engine.atmosphereCurve.Evaluate(0), rather than ask // for engine.realIsp, because there may be mods that tinker with the atmosphere // curve, which changes the actual Isp that the game uses for vacuum without // updating engine.realIsp. double engineIsp = engine.realIsp; double engineTotalFuelConsumption = engineKilonewtons / (KERBIN_GRAVITY * engineIsp); // tons/sec double ratioSum = 0.0; bool isStarved = false; for (int propellantIndex = 0; propellantIndex < engine.propellants.Count; ++propellantIndex) { Propellant propellant = engine.propellants[propellantIndex]; if (!ShouldIgnore(propellant.name)) { if (!availableResources.Has(propellant.name)) { isStarved = true; break; } ratioSum += propellant.ratio; } } if (isStarved) { continue; } if (ratioSum > 0) { double ratio = 1.0 / ratioSum; for (int propellantIndex = 0; propellantIndex < engine.propellants.Count; ++propellantIndex) { Propellant propellant = engine.propellants[propellantIndex]; if (!ShouldIgnore(propellant.name)) { double consumptionRate = ratio * propellant.ratio * engineTotalFuelConsumption; // tons/sec propellantsConsumed.Add(propellant.name, consumptionRate); } } } } // if we need to worry about fuel ++engineCount; totalThrustVector += engine.Forward() * (float)engineKilonewtons; } // if the engine is operational } // for each engine module on the part totalThrust = totalThrustVector.magnitude; if (engineCount != lastEngineCount) { lastEngineCount = engineCount; Logging.Log(engineCount.ToString("Active engines: ##0")); } }
public void RetrofitEngine() { if (ResearchAndDevelopment.Instance == null) { return;} if (isupgraded || ResearchAndDevelopment.Instance.Science < upgradeCost) { return; } isupgraded = true; var curEngine = this.part.Modules["ModuleEngines"] as ModuleEngines; if (curEngine != null) { Propellant prop = new Propellant(); //prop.id = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").id; //ConfigNode prop_node = new ConfigNode(); //PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").Save(prop_node); //PartResource part_resource = part.Resources.list[0]; //part_resource.info = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma"); //part_resource.maxAmount = 10; //part_resource.amount = 10; ConfigNode node = new ConfigNode("RESOURCE"); node.AddValue("name", "VacuumPlasma"); node.AddValue("maxAmount", 10); node.AddValue("amount", 10); part.AddResource(node); propellants = ElectricEngineController.getPropellants(isupgraded); fuel_mode = 0; //curEngine.propellants[1].id = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").id; //curEngine.propellants[1].name = PartResourceLibrary.Instance.GetDefinition("VacuumPlasma").name; engineType = upgradedName; ResearchAndDevelopment.Instance.Science = ResearchAndDevelopment.Instance.Science - upgradeCost; evaluateMaxThrust(); } }
public float getMaxFuelFlow(Propellant p) { return(p.ratio * this.thrusterPower / (atmosphereCurve.Evaluate(0f) * 9.82f) / this.resourceMass); }
public void evaluateMaxThrust() { bool electrothermal_prop = false; List <Part> vessel_parts = vessel.parts; total_power_output = 0; var curEngine = this.part.Modules["ModuleEngines"] as ModuleEngines; ConfigNode chosenpropellant = propellants[fuel_mode]; ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT"); List <Propellant> list_of_propellants = new List <Propellant>(); //bool propellant_is_upgrade = false; for (int i = 0; i < assprops.Length; ++i) { fuelmode = chosenpropellant.GetValue("guiName"); ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier")); thrust_efficiency = float.Parse(chosenpropellant.GetValue("efficiency")); //propellant_is_upgrade = bool.Parse(chosenpropellant.GetValue("isUpgraded")); electrothermal_prop = bool.Parse(chosenpropellant.GetValue("electroThermal")); Propellant curprop = new Propellant(); curprop.Load(assprops[i]); if (curprop.drawStackGauge) { curprop.drawStackGauge = false; fuel_gauge.SetMessage(curprop.name); fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } list_of_propellants.Add(curprop); } total_power_output = getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES); final_thrust_store = thrust_efficiency * 2000.0f * total_power_output / (initialIsp * ispMultiplier * 9.81f); //float thrust_ratio = total_power_output / reference_power; //final_thrust_store = initial_thrust * thrust_ratio / ispMultiplier; FloatCurve newISP = new FloatCurve(); newISP.Add(0, initialIsp * ispMultiplier); curEngine.atmosphereCurve = newISP; if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) { curEngine.propellants.Clear(); curEngine.propellants = list_of_propellants; curEngine.SetupPropellant(); } List <PartResource> partresources = new List <PartResource>(); part.GetConnectedResources(curEngine.propellants[0].id, PartResourceLibrary.Instance.GetDefinition(curEngine.propellants[0].name).resourceFlowMode, partresources); //if(!isupgraded) { if (partresources.Count == 0 && fuel_mode != 0) { if (isThrusterElectrothermal && !electrothermal_prop) { TogglePropellant(); } else if (!isThrusterElectrothermal) { TogglePropellant(); } } //}else{ // if(!propellant_is_upgrade) { //TogglePropellant(); // } //} }
public float getMaxFuelFlow(Propellant p) { return p.ratio * this.thrusterPower / (atmosphereCurve.Evaluate(0f) * 9.82f) / this.resourceMass; }
public double GetPropellants(Propellant prop) { return(0); }
public double GetMaximumPossibleLifetime() { double Lifetime = 0; //List<Part> constructPartsList = EditorLogic.RootPart.FindChildParts<Part>().ToList(); //constructPartsList.AddUnique(EditorLogic.RootPart); var constructParts = EditorLogic.SortedShipList.ToArray(); //Part[] constructParts = EditorLogic.RootPart.FindChildParts<Part>(); //constructParts.AddUnique(EditorLogic.RootPart); bool ClockType = Settings.Read24Hr(); double HoursInDay = 6; if (ClockType) { HoursInDay = 24.0; } else { HoursInDay = 6.0; } AllUsableFuels.Clear(); var allResources = GetResources(constructParts); for (int pi = 0; pi < constructParts.Length; pi++) { Part p = constructParts[pi]; Dictionary <string, double> UsableFuels = new Dictionary <string, double>(); Dictionary <string, double> FuelRatios = new Dictionary <string, double>(); var moduleEngines = p.FindModuleImplementing <ModuleEngines>(); if (moduleEngines != null) { double engEfficiency = moduleEngines.atmosphereCurve.Evaluate(0); if (moduleEngines != null) { for (int mep = 0; mep < moduleEngines.propellants.Count; mep++) { Propellant pro = moduleEngines.propellants[mep]; //if (pro.ToString() == GetResources(constructParts, pro.name)[i]) if (allResources.ContainsKey(pro.name)) { // Blah blah blah if (!UsableFuels.ContainsKey(pro.name)) { UsableFuels.Add(pro.name, pro.totalResourceCapacity); FuelRatios.Add(pro.name, pro.ratio); } if (!AllUsableFuels.ContainsKey(pro.name)) { AllUsableFuels.Add(pro.name, pro.totalResourceCapacity); } double ResEff = 1.0 / engEfficiency; Lifetime = Lifetime + allResources[pro.name] / (DecayManager.EditorDecayRateRadiationPressure(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody) * ResEff * Settings.ReadResourceRateDifficulty() + DecayManager.EditorDecayRateAtmosphericDrag(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody) ) / (60 * 60 * HoursInDay); } } } } var moduleRCS = p.FindModuleImplementing <ModuleRCS>(); if (moduleRCS != null) { var rcsEfficiency = moduleRCS.atmosphereCurve.Evaluate(0); if (moduleRCS != null) { for (int mep = 0; mep < moduleRCS.propellants.Count; mep++) { Propellant pro = moduleRCS.propellants[mep]; if (allResources.ContainsKey(pro.name)) { // Blah blah blah if (!UsableFuels.ContainsKey(pro.name)) { UsableFuels.Add(pro.name, pro.totalResourceCapacity); FuelRatios.Add(pro.name, pro.ratio); } if (!AllUsableFuels.ContainsKey(pro.name)) { AllUsableFuels.Add(pro.name, pro.totalResourceCapacity); } double ResEff = 1.0 / rcsEfficiency; Lifetime = Lifetime + allResources[pro.name] / (DecayManager.EditorDecayRateRadiationPressure(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody) * ResEff * Settings.ReadResourceRateDifficulty() + DecayManager.EditorDecayRateAtmosphericDrag(CalculateMass() * 1000, CalculateArea(), ReferenceBody.Radius + AltitudeValue, 0, ReferenceBody) ) / (60 * 60 * HoursInDay); } } } } } return(Lifetime); }
public void UpdateAeroData(List <FARAeroPartModule> allUsedAeroModules, List <FARAeroPartModule> allUnusedAeroModules) { _aeroModulesWithIntakes.Clear(); _intakeModules.Clear(); _intakeTransforms.Clear(); _airBreathingEngines.Clear(); for (int i = 0; i < allUsedAeroModules.Count; i++) //get all exposed intakes and engines { FARAeroPartModule aeroModule = allUsedAeroModules[i]; if (aeroModule == null) { continue; } Part p = aeroModule.part; if (p.Modules.Contains("ModuleResourceIntake")) { ModuleResourceIntake intake = (ModuleResourceIntake)p.Modules["ModuleResourceIntake"]; _aeroModulesWithIntakes.Add(aeroModule); _intakeModules.Add(intake); _intakeTransforms.Add(p.FindModelTransform(intake.intakeTransformName)); } if (p.Modules.Contains("ModuleEngines")) { ModuleEngines engines = (ModuleEngines)p.Modules["ModuleEngines"]; for (int j = 0; j < engines.propellants.Count; j++) { Propellant prop = engines.propellants[j]; if (prop.name == "IntakeAir") { _airBreathingEngines.Add(engines); break; } } } if (p.Modules.Contains("ModuleEnginesFX")) { ModuleEnginesFX engines = (ModuleEnginesFX)p.Modules["ModuleEnginesFX"]; for (int j = 0; j < engines.propellants.Count; j++) { Propellant prop = engines.propellants[j]; if (prop.name == "IntakeAir") { _airBreathingEngines.Add(engines); break; } } } } for (int i = 0; i < allUnusedAeroModules.Count; i++) //get all covered airbreathing Engines { FARAeroPartModule aeroModule = allUnusedAeroModules[i]; if (aeroModule == null) { continue; } Part p = aeroModule.part; if (p.Modules.Contains("ModuleEngines")) { ModuleEngines engines = (ModuleEngines)p.Modules["ModuleEngines"]; for (int j = 0; j < engines.propellants.Count; j++) { Propellant prop = engines.propellants[j]; if (prop.name == "IntakeAir") { _airBreathingEngines.Add(engines); break; } } } if (p.Modules.Contains("ModuleEnginesFX")) { ModuleEnginesFX engines = (ModuleEnginesFX)p.Modules["ModuleEnginesFX"]; for (int j = 0; j < engines.propellants.Count; j++) { Propellant prop = engines.propellants[j]; if (prop.name == "IntakeAir") { _airBreathingEngines.Add(engines); break; } } } } }
private void SetMode() { if (multiEngine.runningPrimary) EngineModeID = 0; else EngineModeID = 1; Utils.Log("VariableIspEngine: Changing mode to " + engineModes[EngineModeID].name); CurrentEngineID = engineModes[EngineModeID].name; engine = engines[EngineModeID]; ThrustCurve = engineModes[EngineModeID].thrustCurve; IspCurve = engineModes[EngineModeID].ispCurve; for (int i=0; i < engine.propellants.Count; i++) { if (engine.propellants[i].name != "ElectricCharge") { fuelPropellant = engine.propellants[i]; } else { ecPropellant = engine.propellants[i]; } } //Utils.Log("VariableIspEngine: Changed mode to " + engine.engineID); Utils.Log("VariableIspEngine: Fuel: " + fuelPropellant.name); Utils.Log("VariableIspEngine: Thrust Curve: " + ThrustCurve.Evaluate(0f) + " to " + ThrustCurve.Evaluate(1f)); Utils.Log("VariableIspEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f)); AdjustVariableThrust(); }
private void SetupPropellants() { foreach (Propellant prop in engine.propellants) { if (prop.name != "ElectricCharge") { fuelPropellant = prop; } else { ecPropellant = prop; } } //Utils.Log("VariablePowerEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f)); AdjustVariablePower(); }
public void LoadPropellants(ConfigNode node) { propellants.Clear(); foreach (ConfigNode prop in node.GetNodes("PROPELLANT")) { Propellant fuel = new Propellant(); fuel.Load(prop); propellants.Add(fuel); } SetupPropellant(); }
// Initialization public override void OnLoad(ConfigNode node) { // Run base OnLoad method base.OnLoad(node); // Initialize density of propellant used in deltaV and mass calculations densityHydrogen = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.Hydrogen).density; densityDeuterium = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.Deuterium).density; densityTritium = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.Tritium).density; hydrogenPropellant = this.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Hydrogen); deuteriumPropellant = this.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Deuterium); tritiumPropellant = this.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Tritium); }
public override void OnStart(PartModule.StartState state) { if (state != StartState.Editor) { started = true; } else { started = false; } // Get moduleEngines PartModuleList pml = this.part.Modules; for (int i = 0; i < pml.Count; i++) { PartModule curModule = pml.GetModule(i); engine = curModule.GetComponent <ModuleEnginesFX>(); } if (engine != null) { Debug.Log("NFPP: Engine Check Passed"); } foreach (Propellant prop in engine.propellants) { if (prop.name == FuelName) { fuelPropellant = prop; } if (prop.name == "ElectricCharge") { ecPropellant = prop; } } if (UseDirectThrottle) { ChangeIspAndThrust(engine.requestedThrottle); } else { ChangeIspAndThrust(CurThrustSetting / 100f); } if (state != StartState.Editor) { SetupVariableEngines(); } CalculateCurves(); Debug.Log("NFPP: Variable ISP engine setup complete"); if (UseDirectThrottle) { Debug.Log("NFPP: Using direct throttle method"); } }
public static EngineSim New(PartSim theEngine, ModuleEngines engineMod, double atmosphere, float machNumber, bool vectoredThrust, bool fullThrust, LogMsg log) { float maxFuelFlow = engineMod.maxFuelFlow; float minFuelFlow = engineMod.minFuelFlow; float thrustPercentage = engineMod.thrustPercentage; List <Transform> thrustTransforms = engineMod.thrustTransforms; List <float> thrustTransformMultipliers = engineMod.thrustTransformMultipliers; Vector3 vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null, vectoredThrust ? thrustTransformMultipliers : null, log); FloatCurve atmosphereCurve = engineMod.atmosphereCurve; bool atmChangeFlow = engineMod.atmChangeFlow; FloatCurve atmCurve = engineMod.useAtmCurve ? engineMod.atmCurve : null; FloatCurve velCurve = engineMod.useVelCurve ? engineMod.velCurve : null; float currentThrottle = engineMod.currentThrottle; float IspG = engineMod.g; bool throttleLocked = engineMod.throttleLocked || fullThrust; List <Propellant> propellants = engineMod.propellants; bool active = engineMod.isOperational; float resultingThrust = engineMod.resultingThrust; bool isFlamedOut = engineMod.flameout; EngineSim engineSim = pool.Borrow(); engineSim.isp = 0.0; engineSim.maxMach = 0.0f; engineSim.actualThrust = 0.0; engineSim.partSim = theEngine; engineSim.isActive = active; engineSim.thrustVec = vecThrust; engineSim.isFlamedOut = isFlamedOut; engineSim.resourceConsumptions.Reset(); engineSim.maxResourceConsumptions.Reset(); engineSim.resourceFlowModes.Reset(); engineSim.appliedForces.Clear(); double flowRate = 0.0; double maxFlowRate = 0.0; if (engineSim.partSim.hasVessel) { if (log != null) { log.AppendLine("hasVessel is true"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.fullThrust = GetThrust(maxFuelFlow * flowModifier, engineSim.isp); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); } if (throttleLocked) { if (log != null) { log.AppendLine("throttleLocked is true, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } else { if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) { // TODO: This bit doesn't work for RF engines if (log != null) { log.AppendLine("throttled up and not landed, using actualThrust for flowRate"); } flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); } else { if (log != null) { log.AppendLine("throttled down or landed, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } } maxFlowRate = GetFlowRate(engineSim.fullThrust, engineSim.isp); } else { if (log != null) { log.buf.AppendLine("hasVessel is false"); } float altitude = BasicDeltaV.Instance.AtmosphereDepth; float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, BasicDeltaV.Instance.CurrentCelestialBody.GetDensity(BasicDeltaV.Instance.CurrentCelestialBody.GetPressure(altitude), BasicDeltaV.Instance.CurrentCelestialBody.GetTemperature(altitude)), velCurve, machNumber, ref engineSim.maxMach); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.fullThrust = GetThrust(maxFuelFlow * flowModifier, engineSim.isp); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = 0d; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.AppendLine("no vessel, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); maxFlowRate = GetFlowRate(engineSim.fullThrust, engineSim.isp); } if (log != null) { log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate); } float flowMass = 0f; for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (!propellant.ignoreForIsp) { flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); } } if (log != null) { log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass); } for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } double consumptionRate = propellant.ratio * flowRate / flowMass; if (log != null) { log.buf.AppendFormat( "Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); } engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode()); double maxConsumptionRate = propellant.ratio * maxFlowRate / flowMass; engineSim.maxResourceConsumptions.Add(propellant.id, maxConsumptionRate); } for (int i = 0; i < thrustTransforms.Count; i++) { Transform thrustTransform = thrustTransforms[i]; Vector3d direction = thrustTransform.forward.normalized; Vector3d position = thrustTransform.position; AppliedForce appliedForce = AppliedForce.New(direction * engineSim.thrust * thrustTransformMultipliers[i], position); engineSim.appliedForces.Add(appliedForce); } return(engineSim); }
/// <summary> /// Load the engine config /// </summary> /// <param name="node">The config node to load from</param> public void Load(ConfigNode node) { if (node.name.Equals("MODE")) { ConfigNode.LoadObjectFromConfig(this, node); //load the propellants ConfigNode[] propellantNodes = node.GetNodes("PROPELLANT"); propellants = new List <Propellant>(); for (int i = 0; i < propellantNodes.Length; i++) { Propellant p = new Propellant(); p.Load(propellantNodes[i]); propellants.Add(p); } //load the name of the mode if (node.HasValue("name")) { name = node.GetValue("name"); } //load the curve for atmosphere ISP or Thrust if (node.HasNode("atmosphereISPCurve")) { atmosphereISPCurve = new FloatCurve(); atmosphereISPCurve.Load(node.GetNode("atmosphereISPCurve")); float tmpMin; atmosphereISPCurve.FindMinMaxValue(out tmpMin, out maxISP); } else if (node.HasNode("atmosphereThrustCurve")) { atmosphereThrustCurve = new FloatCurve(); atmosphereThrustCurve.Load(node.GetNode("atmosphereThrustCurve")); } else { atmosphereISPCurve = new FloatCurve(); atmosphereISPCurve.Add(0, 0); atmosphereISPCurve.Add(1, 100); maxISP = 100; } //load the consumption curve if (node.HasNode("consumptionCurve")) { consumptionCurve = new FloatCurve(); consumptionCurve.Load(node.GetNode("consumptionCurve")); } //load the velocity curve if (node.HasNode("velocityCurve")) { velocityCurve = new FloatCurve(); velocityCurve.Load(node.GetNode("velocityCurve")); } //wheter the engine needs an atmosphere to work if (node.HasValue("needsAtmosphere")) { needsAtmosphere = bool.Parse(node.GetValue("needsAtmosphere")); } //wheter the engine needs oxygen to operate if (node.HasValue("needsOxygen")) { needsOxygen = bool.Parse(node.GetValue("needsOxygen")); } //wheter the engine needs to be in water to operate if (node.HasValue("needsWater")) { needsWater = bool.Parse(node.GetValue("needsWater")); } //wheter the engine needs to be in water to operate if (node.HasValue("maxThrust")) { try { maxThrust = float.Parse(node.GetValue("maxThrust")); } catch (Exception e) { maxThrust = 0; Debug.LogError("[LYNX] Cannot load maxThrust for engine: " + e.Message); } } //wheter the engine needs to be in water to operate if (node.HasValue("flameoutThreshold")) { try { flameoutThreshold = float.Parse(node.GetValue("flameoutThreshold")); } catch (Exception e) { flameoutThreshold = 0.1f; Debug.LogError("[LYNX] Cannot load flameoutThreshold for engine: " + e.Message); } } //calculate the fuel flow modifier if (atmosphereISPCurve != null) { float fuelDensity = 0.0f; for (int i = 0; i < propellants.Count; i++) { fuelDensity += PartResourceLibrary.Instance.resourceDefinitions[propellants[i].name].density; } fuelFlow = (fuelDensity > 0.0f) ? maxThrust / (9.80665f * maxISP * fuelDensity) : 1; } else { fuelFlow = 1.0f; } } }
private void SetupPropellants(bool moveNext) { try { Current_propellant = fuel_mode < _propellants.Count ? _propellants[fuel_mode] : _propellants.FirstOrDefault(); if ((Current_propellant.SupportedEngines & type) != type) { _rep++; togglePropellant(moveNext); return; } Propellant new_propellant = Current_propellant.Propellant; if (fuel_gauge != null && new_propellant.drawStackGauge) { new_propellant.drawStackGauge = false; fuel_gauge.SetMessage(Current_propellant.PropellantGUIName); fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } List <Propellant> list_of_propellants = new List <Propellant>(); list_of_propellants.Add(new_propellant); if (!list_of_propellants.Exists(prop => PartResourceLibrary.Instance.GetDefinition(prop.name) == null)) { _attached_engine.propellants.Clear(); _attached_engine.propellants = list_of_propellants; _attached_engine.SetupPropellant(); } else if (_rep < _propellants.Count) { _rep++; togglePropellant(moveNext); return; } if (HighLogic.LoadedSceneIsFlight) { // you can have any fuel you want in the editor but not in flight List <PartResource> totalpartresources = list_of_propellants.SelectMany(prop => part.GetConnectedResources(prop.name.Replace("LqdWater", "Water"))).ToList(); if (!list_of_propellants.All(prop => totalpartresources.Select(pr => pr.resourceName).Contains(prop.name.Replace("LqdWater", "Water"))) && _rep < _propellants.Count) { _rep++; togglePropellant(moveNext); return; } } if (Current_propellant.Propellant.name == "LqdWater") { if (fuel_gauge != null) { fuel_gauge.SetMessage("Water"); } if (!part.Resources.Contains("LqdWater")) { ConfigNode node = new ConfigNode("RESOURCE"); node.AddValue("name", "LqdWater"); node.AddValue("maxAmount", this.maxPower / this.baseISP); node.AddValue("possibleAmount", 0); this.part.AddResource(node); this.part.Resources.UpdateList(); } } else { if (part.Resources.Contains("LqdWater")) { var partresource = part.Resources["LqdWater"]; if (partresource.amount > 0 && HighLogic.LoadedSceneIsFlight) { ORSHelper.fixedRequestResource(this.part, "Water", -partresource.amount); } this.part.Resources.list.Remove(partresource); DestroyImmediate(partresource); } } _rep = 0; } catch (Exception e) { UnityEngine.Debug.LogError("[KSPI] - SetupPropellants ElectricEngineControllerFX " + e.Message); } }
public static float FindIsp(float thrust, float flowRate, Propellant fuelPropellant) { double fuelDensity = PartResourceLibrary.Instance.GetDefinition(fuelPropellant.name).density; double isp = (((thrust * 1000f) / (9.82d)) / flowRate) / (fuelDensity * 1000f); return (float)isp; }
public override void OnStart(PartModule.StartState state) { if (state != StartState.Editor) started = true; else started = false; // Get moduleEngines PartModuleList pml = this.part.Modules; for (int i = 0; i < pml.Count; i++) { PartModule curModule = pml.GetModule(i); engine = curModule.GetComponent<ModuleEnginesFX>(); } if (engine != null) Debug.Log("NFPP: Engine Check Passed"); foreach (Propellant prop in engine.propellants) { if (prop.name == FuelName) fuelPropellant = prop; if (prop.name == "ElectricCharge") ecPropellant = prop; } if (UseDirectThrottle) ChangeIspAndThrust(engine.requestedThrottle); else ChangeIspAndThrust(CurThrustSetting / 100f); if (state != StartState.Editor) SetupVariableEngines(); CalculateCurves(); Debug.Log("NFPP: Variable ISP engine setup complete"); if (UseDirectThrottle) { Debug.Log("NFPP: Using direct throttle method"); } }
/// <summary> /// Refresh cached information. /// </summary> public void Refresh() { if (!NeedUpdate()) { return; } lastUpdateTime = DateTime.Now; Vessel vessel = FlightGlobals.ActiveVessel; if (vessel == null) { return; } vesselId = vessel.id; vesselPartCount = vessel.parts.Count; totalMass = vessel.GetTotalMass(); activeEngines.Clear(); for (int engineIndex = 0; engineIndex < Propulsion.Engines.Count; ++engineIndex) { Part part = Propulsion.Engines[engineIndex]; for (int moduleIndex = 0; moduleIndex < part.Modules.Count; ++moduleIndex) { ModuleEngines engine = part.Modules[moduleIndex] as ModuleEngines; if (engine == null) { continue; } if (!engine.isOperational) { continue; } if (!CheatOptions.InfinitePropellant) { bool isDeprived = false; for (int propellantIndex = 0; propellantIndex < engine.propellants.Count; ++propellantIndex) { Propellant propellant = engine.propellants[propellantIndex]; if (propellant.isDeprived && !propellant.ignoreForIsp) { isDeprived = true; // out of fuel! break; } } if (isDeprived) { continue; // skip this engine } } activeEngines.Add(engine); } } availableResources = new Tally(); for (int tankIndex = 0; tankIndex < Propulsion.Tanks.Count; ++tankIndex) { Part part = Propulsion.Tanks[tankIndex]; for (int resourceIndex = 0; resourceIndex < part.Resources.Count; ++resourceIndex) { PartResource resource = part.Resources[resourceIndex]; if (resource.flowState) { availableResources.Add(resource.resourceName, resource.amount * resource.info.density); } } } }
public static EngineSim New(PartSim theEngine, double atmosphere, float machNumber, float maxFuelFlow, float minFuelFlow, float thrustPercentage, Vector3 vecThrust, FloatCurve atmosphereCurve, bool atmChangeFlow, FloatCurve atmCurve, FloatCurve velCurve, float currentThrottle, float IspG, bool throttleLocked, List <Propellant> propellants, bool active, float resultingThrust, List <Transform> thrustTransforms, LogMsg log) { EngineSim engineSim = pool.Borrow(); engineSim.isp = 0.0; engineSim.maxMach = 0.0f; engineSim.actualThrust = 0.0; engineSim.partSim = theEngine; engineSim.isActive = active; engineSim.thrustVec = vecThrust; engineSim.resourceConsumptions.Reset(); engineSim.resourceFlowModes.Reset(); engineSim.appliedForces.Clear(); double flowRate = 0.0; if (engineSim.partSim.hasVessel) { if (log != null) { log.buf.AppendLine("hasVessel is true"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); } if (throttleLocked) { if (log != null) { log.buf.AppendLine("throttleLocked is true, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } else { if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) { if (log != null) { log.buf.AppendLine("throttled up and not landed, using actualThrust for flowRate"); } flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); } else { if (log != null) { log.buf.AppendLine("throttled down or landed, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } } } else { if (log != null) { log.buf.AppendLine("hasVessel is false"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, SimManager.Body.GetDensity(FlightGlobals.getStaticPressure(0, SimManager.Body), FlightGlobals.getExternalTemperature(0, SimManager.Body)), velCurve, machNumber, ref engineSim.maxMach); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = 0d; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); } if (log != null) { log.buf.AppendLine("no vessel, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } if (log != null) { log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate); } float flowMass = 0f; for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (!propellant.ignoreForIsp) { flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); } } if (log != null) { log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass); } for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } double consumptionRate = propellant.ratio * flowRate / flowMass; if (log != null) { log.buf.AppendFormat( "Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); } engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode()); } double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count; for (int i = 0; i < thrustTransforms.Count; i++) { Transform thrustTransform = thrustTransforms[i]; Vector3d direction = thrustTransform.forward.normalized; Vector3d position = thrustTransform.position; AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position); engineSim.appliedForces.Add(appliedForce); } return(engineSim); }
public static EngineSim New(PartSim theEngine, double atmosphere, double machNumber, float maxFuelFlow, float minFuelFlow, float thrustPercentage, Vector3 vecThrust, FloatCurve atmosphereCurve, bool atmChangeFlow, FloatCurve atmCurve, FloatCurve velCurve, float currentThrottle, float IspG, bool throttleLocked, List <Propellant> propellants, bool active, bool correctThrust, List <Transform> thrustTransforms) { EngineSim engineSim = pool.Borrow(); StringBuilder buffer = null; //MonoBehaviour.print("Create EngineSim for " + theEngine.name); //MonoBehaviour.print("maxThrust = " + maxThrust); //MonoBehaviour.print("minThrust = " + minThrust); //MonoBehaviour.print("thrustPercentage = " + thrustPercentage); //MonoBehaviour.print("requestedThrust = " + requestedThrust); //MonoBehaviour.print("velocity = " + velocity); engineSim.partSim = theEngine; engineSim.isActive = active; //engineSim.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust; //MonoBehaviour.print("thrust = " + thrust); engineSim.thrustVec = vecThrust; double flowRate = 0d; if (engineSim.partSim.hasVessel) { //MonoBehaviour.print("hasVessel is true"); //engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); //if (engineSim.isp == 0d) //{ // MonoBehaviour.print("Isp at " + engineSim.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN"); //} //if (correctThrust && realIsp == 0) //{ // float ispsl = atmosphereCurve.Evaluate(0); // if (ispsl != 0) // { // engineSim.thrust = engineSim.thrust * engineSim.isp / ispsl; // } // else // { // MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust."); // } // //MonoBehaviour.print("corrected thrust = " + thrust); //} //if (velocityCurve != null) //{ // engineSim.thrust *= velocityCurve.Evaluate((float)velocity); // //MonoBehaviour.print("thrust at velocity = " + thrust); //} float multiplier = 1; if (atmChangeFlow) { multiplier = (float)(engineSim.partSim.part.atmDensity / 1.225); if (atmCurve != null) { multiplier = atmCurve.Evaluate(multiplier); } } if (velCurve != null) { multiplier *= velCurve.Evaluate((float)machNumber); } if (throttleLocked) { //MonoBehaviour.print("throttleLocked is true"); //flowRate = engineSim.thrust / (engineSim.isp * 9.82); flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier; } else { if (engineSim.partSim.isLanded) { //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle); flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, FlightInputHandler.state.mainThrottle * (thrustPercentage / 100f)) * multiplier; } else { if (currentThrottle > 0) { //MonoBehaviour.print("requestedThrust > 0"); //flowRate = requestedThrust / (engineSim.isp * 9.82) * multiplier; flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, currentThrottle * (thrustPercentage / 100f)) * multiplier; } else { //MonoBehaviour.print("requestedThrust <= 0"); flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier; } } } } else { //MonoBehaviour.print("hasVessel is false"); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); if (engineSim.isp == 0d) { MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN"); } //if (correctThrust) //{ // float ispsl = atmosphereCurve.Evaluate(0); // if (ispsl != 0) // { // engineSim.thrust = engineSim.thrust * engineSim.isp / ispsl; // } // else // { // MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust."); // } // //MonoBehaviour.print("corrected thrust = " + thrust); //} float multiplier = 1; if (atmChangeFlow) { //multiplier = (float)(engineSim.partSim.part.atmDensity / 1.225); multiplier = (float)atmosphere; // technically wrong but about the same for my Editor need if (atmCurve != null) { multiplier = atmCurve.Evaluate(multiplier); } } if (velCurve != null) { multiplier *= velCurve.Evaluate((float)machNumber); } flowRate = Mathf.Lerp(minFuelFlow, maxFuelFlow, (thrustPercentage / 100f)) * multiplier; } if (SimManager.logOutput) { buffer = new StringBuilder(1024); buffer.AppendFormat("flowRate = {0:g6}\n", flowRate); } engineSim.thrust = flowRate * (engineSim.isp * IspG); // TODO : look into the diff between the 2 in the old code (jet real thrust vs ideal thrust ?) engineSim.actualThrust = engineSim.thrust; float flowMass = 0f; for (int i = 0; i < propellants.Count; i++) { Propellant propellant = propellants[i]; flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); } if (SimManager.logOutput) { buffer.AppendFormat("flowMass = {0:g6}\n", flowMass); } for (int i = 0; i < propellants.Count; i++) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } double consumptionRate = propellant.ratio * flowRate / flowMass; if (SimManager.logOutput) { buffer.AppendFormat( "Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); } engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); } if (SimManager.logOutput) { MonoBehaviour.print(buffer); } double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count; for (int i = 0; i < thrustTransforms.Count; i++) { Transform thrustTransform = thrustTransforms[i]; Vector3d direction = thrustTransform.forward.normalized; Vector3d position = thrustTransform.position; AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position); engineSim.appliedForces.Add(appliedForce); } return(engineSim); }
public static float FindPowerUse(float thrust,float isp,Propellant ecPropellant, Propellant fuelPropellant) { return (ecPropellant.ratio / fuelPropellant.ratio) * FindFlowRate(thrust, isp, fuelPropellant); }
public static float FindPowerUse(float thrust, float isp, Propellant ecPropellant, Propellant fuelPropellant) { return((ecPropellant.ratio / fuelPropellant.ratio) * FindFlowRate(thrust, isp, fuelPropellant)); }
public void evaluateMaxThrust() { bool electrothermal_prop = false; List<Part> vessel_parts = vessel.parts; total_power_output = 0; var curEngine = this.part.Modules["ModuleEngines"] as ModuleEngines; ConfigNode chosenpropellant = propellants[fuel_mode]; ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT"); List<Propellant> list_of_propellants = new List<Propellant>(); //bool propellant_is_upgrade = false; for (int i = 0; i < assprops.Length; ++i) { fuelmode = chosenpropellant.GetValue("guiName"); ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier")); thrust_efficiency = float.Parse(chosenpropellant.GetValue("efficiency")); //propellant_is_upgrade = bool.Parse(chosenpropellant.GetValue("isUpgraded")); electrothermal_prop = bool.Parse(chosenpropellant.GetValue("electroThermal")); Propellant curprop = new Propellant(); curprop.Load(assprops[i]); if (curprop.drawStackGauge) { curprop.drawStackGauge = false; fuel_gauge.SetMessage(curprop.name); fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } list_of_propellants.Add(curprop); } total_power_output = getStableResourceSupply(FNResourceManager.FNRESOURCE_MEGAJOULES); final_thrust_store = thrust_efficiency*2000.0f*total_power_output / (initialIsp * ispMultiplier * 9.81f); //float thrust_ratio = total_power_output / reference_power; //final_thrust_store = initial_thrust * thrust_ratio / ispMultiplier; FloatCurve newISP = new FloatCurve (); newISP.Add (0, initialIsp * ispMultiplier); curEngine.atmosphereCurve = newISP; if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) { curEngine.propellants.Clear(); curEngine.propellants = list_of_propellants; curEngine.SetupPropellant(); } List<PartResource> partresources = new List<PartResource>(); part.GetConnectedResources(curEngine.propellants[0].id, PartResourceLibrary.Instance.GetDefinition(curEngine.propellants[0].name).resourceFlowMode, partresources); //if(!isupgraded) { if (partresources.Count == 0 && fuel_mode != 0) { if (isThrusterElectrothermal && !electrothermal_prop) { TogglePropellant(); } else if (!isThrusterElectrothermal) { TogglePropellant(); } } //}else{ // if(!propellant_is_upgrade) { //TogglePropellant(); // } //} }
public static RCSSim New(PartSim theEngine, ModuleRCS engineMod, double atmosphere, float machNumber, bool vectoredThrust, bool fullThrust, LogMsg log) { double maxFuelFlow = engineMod.maxFuelFlow; // double minFuelFlow = engineMod.minFuelFlow; float thrustPercentage = engineMod.thrustPercentage; List <Transform> thrustTransforms = engineMod.thrusterTransforms; // List<float> thrustTransformMultipliers = engineMod.th Vector3 vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null, log); FloatCurve atmosphereCurve = engineMod.atmosphereCurve; // bool atmChangeFlow = engineMod.at // FloatCurve atmCurve = engineMod.useAtmCurve ? engineMod.atmCurve : null; // FloatCurve velCurve = engineMod.useVelCurve ? engineMod.velCurve : null; // float currentThrottle = engineMod.currentThrottle; double IspG = engineMod.G; // bool throttleLocked = engineMod.throttleLocked || fullThrust; List <Propellant> propellants = engineMod.propellants; bool active = engineMod.moduleIsEnabled; // float resultingThrust = engineMod.resultingThrust; bool isFlamedOut = engineMod.flameout; RCSSim engineSim = pool.Borrow(); engineSim.isp = 0.0; engineSim.maxMach = 0.0f; engineSim.actualThrust = 0.0; engineSim.partSim = theEngine; engineSim.isActive = active; engineSim.thrustVec = vecThrust; engineSim.isFlamedOut = isFlamedOut; engineSim.resourceConsumptions.Reset(); engineSim.resourceFlowModes.Reset(); engineSim.appliedForces.Clear(); double flowRate = 0.0; if (engineSim.partSim.hasVessel) { if (log != null) { log.AppendLine("hasVessel is true"); } engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(maxFuelFlow, engineSim.isp); engineSim.actualThrust = engineSim.isActive ? engineSim.thrust : 0.0; if (log != null) { log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); } if (true) { if (log != null) { log.AppendLine("throttleLocked is true, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } else { // if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) // { //// TODO: This bit doesn't work for RF engines //if (log != null) log.AppendLine("throttled up and not landed, using actualThrust for flowRate"); // flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); // } // else // { // if (log != null) log.AppendLine("throttled down or landed, using thrust for flowRate"); // flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); // } } } else { if (log != null) { log.buf.AppendLine("hasVessel is false"); } engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(maxFuelFlow, engineSim.isp); engineSim.actualThrust = 0d; if (log != null) { log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.AppendLine("no vessel, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } if (log != null) { log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate); } float flowMass = 0f; for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (!propellant.ignoreForIsp) { flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); } } if (log != null) { log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass); } for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } double consumptionRate = propellant.ratio * flowRate / flowMass; if (log != null) { log.buf.AppendFormat( "Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); } engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode()); } for (int i = 0; i < thrustTransforms.Count; i++) { Transform thrustTransform = thrustTransforms[i]; Vector3d direction = thrustTransform.forward.normalized; Vector3d position = thrustTransform.position; AppliedForce appliedForce = AppliedForce.New(direction * engineSim.thrust, position); engineSim.appliedForces.Add(appliedForce); } return(engineSim); }
private void SetupPropellants() { for (int i = 0; i < engine.propellants.Count; i++ ) { if (engine.propellants[i].name != "ElectricCharge") { fuelPropellant = engine.propellants[i]; } else { ecPropellant = engine.propellants[i]; } } //Utils.Log("VariablePowerEngine: Isp Curve: " + IspCurve.Evaluate(0f) + " to " + IspCurve.Evaluate(1f)); AdjustVariablePower(); }
public void setupPropellants() { ConfigNode chosenpropellant = propellants[fuel_mode]; ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT"); List <Propellant> list_of_propellants = new List <Propellant>(); // loop though propellants until we get to the selected one, then set it up foreach (ConfigNode prop_node in assprops) { fuelmode = chosenpropellant.GetValue("guiName"); ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier")); isLFO = bool.Parse(chosenpropellant.GetValue("isLFO")); currentpropellant_is_jet = false; if (chosenpropellant.HasValue("isJet")) { currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet")); } //print (currentpropellant_is_jet); Propellant curprop = new Propellant(); curprop.Load(prop_node); if (curprop.drawStackGauge && HighLogic.LoadedSceneIsFlight) { curprop.drawStackGauge = false; if (currentpropellant_is_jet) { fuel_gauge.SetMessage("Atmosphere"); } else { fuel_gauge.SetMessage(curprop.name); myAttachedEngine.thrustPercentage = 100; part.temperature = 1; } fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } list_of_propellants.Add(curprop); } // update the engine with the new propellants if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) { myAttachedEngine.propellants.Clear(); myAttachedEngine.propellants = list_of_propellants; myAttachedEngine.SetupPropellant(); } if (HighLogic.LoadedSceneIsFlight) // you can have any fuel you want in the editor but not in flight // should we switch to another propellant because we have none of this one? { bool next_propellant = false; List <Propellant> curEngine_propellants_list = new List <Propellant>(); curEngine_propellants_list = myAttachedEngine.propellants; foreach (Propellant curEngine_propellant in curEngine_propellants_list) { List <PartResource> partresources = part.GetConnectedResources(curEngine_propellant.name).ToList(); if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name)) { next_propellant = true; } } // do the switch if needed if (next_propellant && fuel_mode != 1) { TogglePropellant(); } } else { if (!PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name) && fuel_mode != 1) // Still ignore propellants that don't exist { TogglePropellant(); } estimateEditorPerformance(); // update editor estimates } }
private float FindFlowRate(float thrust, float isp, Propellant fuelPropellant) { double fuelDensity = PartResourceLibrary.Instance.GetDefinition(fuelPropellant.name).density; double fuelRate = ((thrust * 1000f) / (isp * Utils.GRAVITY)) / (fuelDensity * 1000f); return (float)fuelRate; }
public void setupPropellants() { ConfigNode chosenpropellant = propellants[fuel_mode]; ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT"); List<Propellant> list_of_propellants = new List<Propellant>(); // loop though propellants until we get to the selected one, then set it up foreach(ConfigNode prop_node in assprops) { fuelmode = chosenpropellant.GetValue("guiName"); ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier")); isLFO = bool.Parse(chosenpropellant.GetValue("isLFO")); currentpropellant_is_jet = false; if(chosenpropellant.HasValue("isJet")) { currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet")); } //print (currentpropellant_is_jet); Propellant curprop = new Propellant(); curprop.Load(prop_node); if (curprop.drawStackGauge && HighLogic.LoadedSceneIsFlight) { curprop.drawStackGauge = false; if (currentpropellant_is_jet) { fuel_gauge.SetMessage("Atmosphere"); }else { fuel_gauge.SetMessage(curprop.name); myAttachedEngine.thrustPercentage = 100; part.temperature = 1; } fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } list_of_propellants.Add(curprop); } // update the engine with the new propellants if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) { myAttachedEngine.propellants.Clear(); myAttachedEngine.propellants = list_of_propellants; myAttachedEngine.SetupPropellant(); } if (HighLogic.LoadedSceneIsFlight) { // you can have any fuel you want in the editor but not in flight // should we switch to another propellant because we have none of this one? bool next_propellant = false; List<Propellant> curEngine_propellants_list = new List<Propellant>(); curEngine_propellants_list = myAttachedEngine.propellants; foreach (Propellant curEngine_propellant in curEngine_propellants_list) { List<PartResource> partresources = part.GetConnectedResources(curEngine_propellant.name).ToList(); if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name)) { next_propellant = true; } } // do the switch if needed if (next_propellant && fuel_mode != 1) { TogglePropellant(); } } else { if (!PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name) && fuel_mode != 1) { // Still ignore propellants that don't exist TogglePropellant(); } estimateEditorPerformance(); // update editor estimates } }
public static EngineSim New(PartSim theEngine, ModuleEngines engineMod, double atmosphere, float machNumber, bool vectoredThrust, bool fullThrust, LogMsg log) { float maxFuelFlow = engineMod.maxFuelFlow; float minFuelFlow = engineMod.minFuelFlow; float thrustPercentage = engineMod.thrustPercentage; List <Transform> thrustTransforms = engineMod.thrustTransforms; List <float> thrustTransformMultipliers = engineMod.thrustTransformMultipliers; Vector3 vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null, vectoredThrust ? thrustTransformMultipliers : null, log); FloatCurve atmosphereCurve = engineMod.atmosphereCurve; bool atmChangeFlow = engineMod.atmChangeFlow; FloatCurve atmCurve = engineMod.useAtmCurve ? engineMod.atmCurve : null; FloatCurve velCurve = engineMod.useVelCurve ? engineMod.velCurve : null; FloatCurve thrustCurve = engineMod.useThrustCurve ? engineMod.thrustCurve : null; float currentThrottle = engineMod.currentThrottle; float IspG = engineMod.g; bool throttleLocked = engineMod.throttleLocked || fullThrust; List <Propellant> propellants = engineMod.propellants; float thrustCurveRatio = engineMod.thrustCurveRatio; foreach (Propellant p in propellants) { if (p.ignoreForThrustCurve) { continue; } double ratio = p.totalResourceAvailable / p.totalResourceCapacity; if (ratio < thrustCurveRatio) { thrustCurveRatio = (float)ratio; } } bool active = engineMod.isOperational; //I do not know if this matters. RF and stock always have finalThrust. But stock uses resultingThrust in the mass flow calculations, so keep it. float resultingThrust = SimManager.hasInstalledRealFuels ? engineMod.finalThrust : engineMod.resultingThrust; bool isFlamedOut = engineMod.flameout; EngineSim engineSim = pool.Borrow(); engineSim.isp = 0.0; engineSim.maxMach = 0.0f; engineSim.actualThrust = 0.0; engineSim.partSim = theEngine; engineSim.isActive = active; engineSim.thrustVec = vecThrust; engineSim.isFlamedOut = isFlamedOut; engineSim.resourceConsumptionsForMass.Reset(); engineSim.resourceConsumptionsForIsp.Reset(); engineSim.resourceFlowModes.Reset(); engineSim.appliedForces.Clear(); double flowRate = 0.0; if (engineSim.partSim.hasVessel) { if (log != null) { log.AppendLine("hasVessel is true"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, thrustCurve, thrustCurveRatio, ref engineSim.maxMach, engineMod.flowMultCap, engineMod.flowMultCapSharpness); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.buf.AppendFormat("final = {0:g6}\n", engineMod.finalThrust); log.buf.AppendFormat("resulting = {0:g6}\n", engineMod.resultingThrust); } if (throttleLocked) { if (log != null) { log.AppendLine("throttleLocked is true, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } else { if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) { if (log != null) { log.AppendLine("throttled up and not landed, using actualThrust for flowRate"); } flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); } else { if (log != null) { log.AppendLine("throttled down or landed, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } } } else { if (log != null) { log.buf.AppendLine("hasVessel is false"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, thrustCurve, thrustCurveRatio, ref engineSim.maxMach, engineMod.flowMultCap, engineMod.flowMultCapSharpness); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = 0d; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.AppendLine("no vessel, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } if (log != null) { log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate); } float flowMass = 0f; for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); } if (log != null) { log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass); } for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } double consumptionRate = propellant.ratio * flowRate / flowMass; if (log != null) { log.buf.AppendFormat( "Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); } // Add all for mass engineSim.resourceConsumptionsForMass.Add(propellant.id, consumptionRate); if (!propellant.ignoreForIsp) { engineSim.resourceConsumptionsForIsp.Add(propellant.id, consumptionRate); } engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode()); } for (int i = 0; i < thrustTransforms.Count; i++) { Transform thrustTransform = thrustTransforms[i]; Vector3d direction = thrustTransform.forward.normalized; Vector3d position = thrustTransform.position; AppliedForce appliedForce = AppliedForce.New(direction * engineSim.thrust * thrustTransformMultipliers[i], position); engineSim.appliedForces.Add(appliedForce); } return(engineSim); }
public void setupPropellants() { ConfigNode chosenpropellant = propellants[fuel_mode]; ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT"); List<Propellant> list_of_propellants = new List<Propellant>(); // loop though propellants until we get to the selected one, then set it up for (int i = 0; i < assprops.Length; ++i) { fuelmode = chosenpropellant.GetValue("guiName"); ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier")); isLFO = bool.Parse(chosenpropellant.GetValue("isLFO")); currentpropellant_is_jet = false; if(chosenpropellant.HasValue("isJet")) { currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet")); } //print (currentpropellant_is_jet); Propellant curprop = new Propellant(); curprop.Load(assprops[i]); if (curprop.drawStackGauge) { curprop.drawStackGauge = false; if (currentpropellant_is_jet) { fuel_gauge.SetMessage("Atmosphere"); }else { fuel_gauge.SetMessage(curprop.name); myAttachedEngine.thrustPercentage = 100; part.temperature = 1; } fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } list_of_propellants.Add(curprop); } // update the engine with the new propellants if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) { myAttachedEngine.propellants.Clear(); myAttachedEngine.propellants = list_of_propellants; myAttachedEngine.SetupPropellant(); } // should we switch to another propellant because we have none of this one? bool next_propellant = false; List<Propellant> curEngine_propellants_list = new List<Propellant>(); curEngine_propellants_list = myAttachedEngine.propellants; foreach(Propellant curEngine_propellant in curEngine_propellants_list) { List<PartResource> partresources = new List<PartResource>(); part.GetConnectedResources(curEngine_propellant.id, PartResourceLibrary.Instance.GetDefinition(curEngine_propellant.name).resourceFlowMode, partresources); if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name)) { next_propellant = true; } } // do the switch if needed if (next_propellant && fuel_mode != 1) { TogglePropellant(); } }
private void SetupPropellants(bool moveNext) { try { Current_propellant = fuel_mode < _propellants.Count ? _propellants[fuel_mode] : _propellants.FirstOrDefault(); if ((Current_propellant.SupportedEngines & type) != type) { _rep++; togglePropellant(moveNext); return; } Propellant new_propellant = Current_propellant.Propellant; List <Propellant> list_of_propellants = new List <Propellant>(); list_of_propellants.Add(new_propellant); // if all propellant exist if (!list_of_propellants.Exists(prop => PartResourceLibrary.Instance.GetDefinition(prop.name) == null)) { //Get the Ignition state, i.e. is the engine shutdown or activated var engineState = _attached_engine.getIgnitionState; _attached_engine.Shutdown(); ConfigNode newPropNode = new ConfigNode(); foreach (var prop in list_of_propellants) { ConfigNode propellantConfigNode = newPropNode.AddNode("PROPELLANT"); propellantConfigNode.AddValue("name", prop.name); propellantConfigNode.AddValue("ratio", prop.ratio); propellantConfigNode.AddValue("DrawGauge", "true"); } _attached_engine.Load(newPropNode); if (engineState == true) { _attached_engine.Activate(); } } else if (_rep < _propellants.Count) { _rep++; togglePropellant(moveNext); return; } if (HighLogic.LoadedSceneIsFlight) { // you can have any fuel you want in the editor but not in flight var allVesselResourcesNames = part.vessel.parts.SelectMany(m => m.Resources).Select(m => m.resourceName).Distinct(); if (!list_of_propellants.All(prop => allVesselResourcesNames.Contains(prop.name.Replace("LqdWater", "Water"))) && _rep < _propellants.Count) { _rep++; togglePropellant(moveNext); return; } } _rep = 0; } catch (Exception e) { UnityEngine.Debug.LogError("[KSPI] - SetupPropellants ElectricEngineControllerFX " + e.Message); } }
public void MarkPropellant(Propellant propel) { foreach (PartResource resource in propel.connectedResources) { data[resource.info.id].ispropellant = true; } }
private void SetEngineInfo() { protoModuleEngine = selectedPart.GetProtoModuleEngine(); if (protoModuleEngine != null) { infoItems.Add(PartInfoItem.Create("Thrust", Units.ToForce(protoModuleEngine.MinimumThrust, protoModuleEngine.MaximumThrust))); infoItems.Add(PartInfoItem.Create("Isp", Units.ConcatF(protoModuleEngine.GetSpecificImpulse(1.0f), protoModuleEngine.GetSpecificImpulse(0.0f)) + "s")); if (protoModuleEngine.Propellants.Count > 0) { infoItems.Add(PartInfoItem.Create("Propellants")); float totalRatio = 0.0f; for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i) { totalRatio = totalRatio + protoModuleEngine.Propellants[i].ratio; } for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i) { propellant = protoModuleEngine.Propellants[i]; infoItems.Add(PartInfoItem.Create("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent())); } } } }
private void SetupPropellants(bool moveNext = true, int maxSwitching = 0) { Current_propellant = fuel_mode < _propellants.Count ? _propellants[fuel_mode] : _propellants.FirstOrDefault(); fuel_mode_name = Current_propellant.PropellantName; if ((Current_propellant.SupportedEngines & type) != type) { SwitchPropellant(moveNext, --maxSwitching); return; } Propellant new_propellant = Current_propellant.Propellant; if (HighLogic.LoadedSceneIsFlight) { // you can have any fuel you want in the editor but not in flight var totalpartresources = part.GetConnectedResources(new_propellant.name).ToList(); if (!totalpartresources.Any() && maxSwitching > 0) { SwitchPropellant(moveNext, --maxSwitching); return; } } if (PartResourceLibrary.Instance.GetDefinition(new_propellant.name) != null) { var effectiveIspMultiplier = type == 2 ? Current_propellant.DecomposedIspMult : Current_propellant.IspMultiplier; //var effectiveThrust = (thrustLimiter / 100) * Current_propellant.ThrustMultiplier * baseThrust / effectiveIspMultiplier; var moduleConfig = new ConfigNode("MODULE"); moduleConfig.AddValue("thrusterPower", attachedRCS.thrusterPower.ToString("0.000")); moduleConfig.AddValue("resourceName", new_propellant.name); moduleConfig.AddValue("resourceFlowMode", "STAGE_PRIORITY_FLOW"); //var newPropNode = new ConfigNode(); ConfigNode propellantConfigNode = moduleConfig.AddNode("PROPELLANT"); propellantConfigNode.AddValue("name", new_propellant.name); propellantConfigNode.AddValue("ratio", "1"); propellantConfigNode.AddValue("DrawGauge", "True"); propellantConfigNode.AddValue("resourceFlowMode", "STAGE_PRIORITY_FLOW"); attachedRCS.Load(propellantConfigNode); currentThrustMultiplier = hasSufficientPower ? Current_propellant.ThrustMultiplier : Current_propellant.ThrustMultiplierCold; //var effectiveThrustModifier = currentThrustMultiplier * (currentThrustMultiplier / Current_propellant.ThrustMultiplier); var effectiveBaseIsp = hasSufficientPower ? maxIsp : minIsp; maxPropellantIsp = (float)(effectiveBaseIsp * effectiveIspMultiplier * currentThrustMultiplier); var atmosphereCurve = new ConfigNode("atmosphereCurve"); atmosphereCurve.AddValue("key", "0 " + (maxPropellantIsp).ToString("0.000")); if (type != 8) { atmosphereCurve.AddValue("key", "1 " + (maxPropellantIsp * 0.5).ToString("0.000")); atmosphereCurve.AddValue("key", "4 " + (maxPropellantIsp * 0.00001).ToString("0.000")); } else { atmosphereCurve.AddValue("key", "1 " + (maxPropellantIsp).ToString("0.000")); } moduleConfig.AddNode(atmosphereCurve); attachedRCS.Load(moduleConfig); } else if (maxSwitching > 0) { Debug.Log("ElectricRCSController SetupPropellants switching mode because no definition found for " + new_propellant.name); SwitchPropellant(moveNext, --maxSwitching); return; } }
public void UpdateAeroData(List <FARAeroPartModule> allUsedAeroModules, List <FARAeroPartModule> allUnusedAeroModules) { _aeroModulesWithIntakes.Clear(); _intakeModules.Clear(); _intakeTransforms.Clear(); _airBreathingEngines.Clear(); HashSet <string> intakeResourceNames = new HashSet <string>(); for (int i = 0; i < allUsedAeroModules.Count; i++) //get all exposed intakes { FARAeroPartModule aeroModule = allUsedAeroModules[i]; if (aeroModule == null) { continue; } Part p = aeroModule.part; for (int j = 0; j < p.Modules.Count; j++) { PartModule m = p.Modules[j]; if (m is ModuleResourceIntake) { ModuleResourceIntake intake = (ModuleResourceIntake)m; if (intake.node != null && intake.node.attachedPart != null) { continue; } _aeroModulesWithIntakes.Add(aeroModule); _intakeModules.Add(intake); _intakeTransforms.Add(p.FindModelTransform(intake.intakeTransformName)); if (!intakeResourceNames.Contains(intake.resourceName)) { intakeResourceNames.Add(intake.resourceName); } } } } for (int i = 0; i < allUsedAeroModules.Count; i++) //get all exposed engines { FARAeroPartModule aeroModule = allUsedAeroModules[i]; if (aeroModule == null) { continue; } Part p = aeroModule.part; for (int j = 0; j < p.Modules.Count; j++) { PartModule m = p.Modules[j]; if (m is ModuleEngines) { ModuleEngines e = (ModuleEngines)m; if (FARAeroUtil.AJELoaded) { if (m.ClassID == AJE_JET_CLASS_ID || m.ClassID == AJE_PROP_CLASS_ID) { _airBreathingEngines.Add(e); continue; } } for (int k = 0; k < e.propellants.Count; k++) { Propellant prop = e.propellants[k]; if (intakeResourceNames.Contains(prop.name)) { _airBreathingEngines.Add(e); break; } } } } } }
public void setupPropellants() { ConfigNode chosenpropellant = propellants[fuel_mode]; ConfigNode[] assprops = chosenpropellant.GetNodes("PROPELLANT"); List <Propellant> list_of_propellants = new List <Propellant>(); // loop though propellants until we get to the selected one, then set it up for (int i = 0; i < assprops.Length; ++i) { fuelmode = chosenpropellant.GetValue("guiName"); ispMultiplier = float.Parse(chosenpropellant.GetValue("ispMultiplier")); isLFO = bool.Parse(chosenpropellant.GetValue("isLFO")); currentpropellant_is_jet = false; if (chosenpropellant.HasValue("isJet")) { currentpropellant_is_jet = bool.Parse(chosenpropellant.GetValue("isJet")); } //print (currentpropellant_is_jet); Propellant curprop = new Propellant(); curprop.Load(assprops[i]); if (curprop.drawStackGauge) { curprop.drawStackGauge = false; if (currentpropellant_is_jet) { fuel_gauge.SetMessage("Atmosphere"); } else { fuel_gauge.SetMessage(curprop.name); myAttachedEngine.thrustPercentage = 100; part.temperature = 1; } fuel_gauge.SetMsgBgColor(XKCDColors.DarkLime); fuel_gauge.SetMsgTextColor(XKCDColors.ElectricLime); fuel_gauge.SetProgressBarColor(XKCDColors.Yellow); fuel_gauge.SetProgressBarBgColor(XKCDColors.DarkLime); fuel_gauge.SetValue(0f); } list_of_propellants.Add(curprop); } // update the engine with the new propellants if (PartResourceLibrary.Instance.GetDefinition(list_of_propellants[0].name) != null) { myAttachedEngine.propellants.Clear(); myAttachedEngine.propellants = list_of_propellants; myAttachedEngine.SetupPropellant(); } // should we switch to another propellant because we have none of this one? bool next_propellant = false; List <Propellant> curEngine_propellants_list = new List <Propellant>(); curEngine_propellants_list = myAttachedEngine.propellants; foreach (Propellant curEngine_propellant in curEngine_propellants_list) { List <PartResource> partresources = new List <PartResource>(); part.GetConnectedResources(curEngine_propellant.id, partresources); if (partresources.Count == 0 || !PartResourceLibrary.Instance.resourceDefinitions.Contains(list_of_propellants[0].name)) { next_propellant = true; } } // do the switch if needed if (next_propellant && fuel_mode != 1) { TogglePropellant(); } }
private void SetupICrossSectionAdjusters() { Matrix4x4 worldToVesselMatrix; if (HighLogic.LoadedSceneIsFlight) { worldToVesselMatrix = vessel.vesselTransform.worldToLocalMatrix; } else { worldToVesselMatrix = EditorLogic.RootPart.partTransform.worldToLocalMatrix; } crossSectionAdjusters = new List <ICrossSectionAdjuster>(); string intakeType = "", engineType = ""; if (part.Modules.Contains("ModuleEnginesAJEJet")) //hard-coded support for AJE; TODO: separate out for more configurable compatibility on 3rd-party end { engineType = "ModuleEnginesAJEJet"; } else if (part.Modules.Contains("ModuleEngines")) { engineType = "ModuleEngines"; } else if (part.Modules.Contains("ModuleEnginesFX")) { engineType = "ModuleEnginesFX"; } if (part.Modules.Contains("AJEInlet")) { intakeType = "AJEInlet"; } else if (part.Modules.Contains("ModuleResourceIntake")) { intakeType = "ModuleResourceIntake"; } if (intakeType != "" && engineType != "") { PartModule module = part.Modules[intakeType]; if (module is ModuleResourceIntake) { ModuleResourceIntake intake = (ModuleResourceIntake)module; IntegratedIntakeEngineCrossSectionAdjuster intakeAdjuster = IntegratedIntakeEngineCrossSectionAdjuster.CreateAdjuster(intake, worldToVesselMatrix); crossSectionAdjusters.Add(intakeAdjuster); } else { IntegratedIntakeEngineCrossSectionAdjuster intakeAdjuster = IntegratedIntakeEngineCrossSectionAdjuster.CreateAdjuster(module, worldToVesselMatrix); crossSectionAdjusters.Add(intakeAdjuster); } return; } if (intakeType != "") { PartModule module = part.Modules[intakeType]; if (module is ModuleResourceIntake) { ModuleResourceIntake intake = (ModuleResourceIntake)module; IntakeCrossSectionAdjuster intakeAdjuster = IntakeCrossSectionAdjuster.CreateAdjuster(intake, worldToVesselMatrix); crossSectionAdjusters.Add(intakeAdjuster); } else { IntakeCrossSectionAdjuster intakeAdjuster = IntakeCrossSectionAdjuster.CreateAdjuster(module, worldToVesselMatrix); crossSectionAdjusters.Add(intakeAdjuster); } return; } if (engineType != "") { ModuleEngines engines = (ModuleEngines)part.Modules[engineType]; bool airBreather = false; if (engineType == "ModuleEnginesAJEJet") { airBreather = true; } else { for (int i = 0; i < engines.propellants.Count; ++i) { Propellant p = engines.propellants[i]; if (p.name == "IntakeAir") { airBreather = true; break; } } } if (airBreather) { AirbreathingEngineCrossSectonAdjuster engineAdjuster = new AirbreathingEngineCrossSectonAdjuster(engines, worldToVesselMatrix); crossSectionAdjusters.Add(engineAdjuster); } return; } }
public override void Start() { if (curveResource != string.Empty) { curveProp = propellants.FirstOrDefault(x => x.name.Equals(curveResource)); } useThrustCurve = curveProp is Propellant; CalcThrottleResponseRate(ref throttleResponseRate, ref instantThrottle); if (!HighLogic.LoadedSceneIsFlight) { partSeed = -1; calculatedResiduals = localResidualsThresholdBase; ignited = false; } else { if (partSeed == -1) { calculatedResiduals = localResidualsThresholdBase + UnityEngine.Random.Range(0f, (float)localVaryResiduals); partSeed = UnityEngine.Random.Range(0, int.MaxValue); } } base.Start(); if (!(engineSolver is SolverRF)) { CreateEngine(); } // Setup for mixture variation backupPropellantRatios.Clear(); oxidizerPropellant = fuelPropellant = null; for (int i = 0; i < propellants.Count(); ++i) { Propellant p = propellants[i]; backupPropellantRatios.Add(p.ratio); if (p.ignoreForIsp || p.resourceDef.density == 0d) { continue; } if (fuelPropellant == null) { fuelPropellant = p; } else if (oxidizerPropellant == null) { oxidizerPropellant = p; } } if (fuelPropellant != null && oxidizerPropellant != null) { mixtureRatio = (oxidizerPropellant.ratio * oxidizerPropellant.resourceDef.density) / (fuelPropellant.ratio * fuelPropellant.resourceDef.density); } ullageSet = new Ullage.UllageSet(this); ullageSet.Load(ullageNode); Fields[nameof(ignitions)].guiActive = ignitions >= 0 && RFSettings.Instance.limitedIgnitions; Fields[nameof(tags)].guiActiveEditor = ShowPropStatus; Fields[nameof(propellantStatus)].guiActive = Fields[nameof(propellantStatus)].guiActiveEditor = ShowPropStatus; Fields[nameof(sIgnitions)].guiActiveEditor = RFSettings.Instance.limitedIgnitions; igniteFailIgnitions = new ScreenMessage($"<color=orange>[{part.partInfo.title}]: no ignitions remaining!</color>", 5f, ScreenMessageStyle.UPPER_CENTER); igniteFailResources = new ScreenMessage($"<color=orange>[{part.partInfo.title}]: insufficient resources to ignite!</color>", 5f, ScreenMessageStyle.UPPER_CENTER); ullageFail = new ScreenMessage($"<color=orange>[{part.partInfo.title}]: vapor in feedlines, shut down!</color>", 5f, ScreenMessageStyle.UPPER_CENTER); Fields[nameof(thrustPercentage)].guiActive = Fields[nameof(thrustPercentage)].guiActiveEditor = minFuelFlow != maxFuelFlow; Fields[nameof(thrustCurveDisplay)].guiActive = useThrustCurve; var group = Fields[nameof(propellantStatus)].group; Fields[nameof(engineTempString)].group = group; Fields[nameof(actualThrottle)].group = group; Fields[nameof(realIsp)].group = group; Fields[nameof(finalThrust)].group = group; Fields[nameof(propellantReqMet)].group = group; Fields[nameof(fuelFlowGui)].group = group; SetFields(); started = true; }