private void CalculateFullThrustAndISP() { fullSimpleThrust = 0; fullVecThrust = Vector3.zero; fullStageFlowRate = 0d; fullStageIspFlowRate = 0d; fullISP = 0; for (int i = 0; i < stageEngines.Count; i++) { EngineSim engine = stageEngines[i]; fullSimpleThrust += engine.fullThrust; fullVecThrust += ((float)engine.fullThrust * engine.thrustVec); fullStageFlowRate += engine.MaxResourceConsumptions.Mass; fullStageIspFlowRate += engine.MaxResourceConsumptions.Mass * engine.isp; } if (fullStageFlowRate > 0 && fullStageIspFlowRate > 0) { fullISP = fullStageIspFlowRate / fullStageFlowRate; } else { fullISP = 0; } }
private void CalculateThrustAndISP() { // Reset all the values vecThrust = Vector3.zero; vecActualThrust = Vector3.zero; totalVectoredExhaustVelocity = Vector3.zero; totalActualVectoredExhaustVelocity = Vector3.zero; totalExhaustVelocity = 0; totalActualExhaustVelocity = 0; simpleTotalThrust = 0d; simpleActualTotalThrust = 0d; totalStageThrust = 0d; totalStageActualThrust = 0d; totalStageFlowRate = 0d; totalStageIspFlowRate = 0d; totalStageThrustForce.Reset(); // Loop through all the active engines totalling the thrust, actual thrust and mass flow rates // The thrust is totalled as vectors for (int i = 0; i < activeEngines.Count; ++i) { EngineSim engine = activeEngines[i]; simpleTotalThrust += engine.thrust; simpleActualTotalThrust += engine.actualThrust; vecThrust += ((float)engine.thrust * engine.thrustVec); vecActualThrust += ((float)engine.actualThrust * engine.thrustVec); totalVectoredExhaustVelocity += engine.thrustVec * (float)((engine.isp * BasicDeltaV.GRAVITY) / engine.thrust); totalExhaustVelocity += totalVectoredExhaustVelocity.magnitude; totalActualVectoredExhaustVelocity += engine.thrustVec * (float)((engine.isp * BasicDeltaV.GRAVITY) / engine.actualThrust); totalActualExhaustVelocity += totalActualVectoredExhaustVelocity.magnitude; totalStageFlowRate += engine.ResourceConsumptions.Mass; totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp; for (int j = 0; j < engine.appliedForces.Count; ++j) { totalStageThrustForce.AddForce(engine.appliedForces[j]); } } if (log != null) { log.AppendLine("vecThrust = ", vecThrust.ToString(), " magnitude = ", vecThrust.magnitude); } totalStageThrust = vecThrust.magnitude; totalStageActualThrust = vecActualThrust.magnitude; // Calculate the effective isp at this point if (totalStageFlowRate > 0d && totalStageIspFlowRate > 0d) { currentisp = totalStageIspFlowRate / totalStageFlowRate; } else { currentisp = 0; } }
// This function activates the next stage // currentStage must be updated before calling this function private void ActivateStage() { // Build a set of all the parts that will be decoupled decoupledParts.Clear(); for (int i = 0; i < allParts.Count; ++i) { PartSim partSim = allParts[i]; if (partSim.decoupledInStage >= currentStage) { decoupledParts.Add(partSim); } } foreach (PartSim partSim in decoupledParts) { // Remove it from the all parts list allParts.Remove(partSim); partSim.Release(); if (partSim.isEngine) { // If it is an engine then loop through all the engine modules and remove all the ones from this engine part for (int i = allEngines.Count - 1; i >= 0; i--) { EngineSim engine = allEngines[i]; if (engine.partSim == partSim) { allEngines.RemoveAt(i); engine.Release(); } } } // If it is a fuel line then remove it from the list of all fuel lines if (partSim.isFuelLine) { allFuelLines.Remove(partSim); } } // Loop through all the (remaining) parts for (int i = 0; i < allParts.Count; ++i) { // Ask the part to remove all the parts that are decoupled allParts[i].RemoveAttachedParts(decoupledParts); } // Now we loop through all the engines and activate those that are ignited in this stage for (int i = 0; i < allEngines.Count; ++i) { EngineSim engine = allEngines[i]; if (engine.partSim.inverseStage == currentStage) { engine.isActive = true; } } }
private void UpdateStageEngines() { stageEngines.Clear(); for (int i = 0; i < allEngines.Count; i++) { EngineSim engine = allEngines[i]; if (engine.partSim.inverseStage >= currentStage) { stageEngines.Add(engine); } } }
// This function simply rebuilds the active engines by testing the isActive flag of all the engines private void UpdateActiveEngines() { activeEngines.Clear(); for (int i = 0; i < allEngines.Count; ++i) { EngineSim engine = allEngines[i]; if (engine.isActive && engine.isFlamedOut == false) { activeEngines.Add(engine); } } }
// This function does all the hard work of working out which engines are burning, which tanks are being drained // and setting the drain rates private void UpdateResourceDrains() { // Update the active engines UpdateActiveEngines(); // Empty the draining resources set drainingResources.Clear(); // Reset the resource drains of all draining parts foreach (PartSim partSim in drainingParts) { partSim.resourceDrains.Reset(); } // Empty the draining parts set drainingParts.Clear(); // Loop through all the active engine modules for (int i = 0; i < activeEngines.Count; ++i) { EngineSim engine = activeEngines[i]; // Set the resource drains for this engine if (engine.SetResourceDrains(log, allParts, allFuelLines, drainingParts)) { // If it is active then add the consumed resource types to the set for (int j = 0; j < engine.ResourceConsumptions.Types.Count; ++j) { drainingResources.Add(engine.ResourceConsumptions.Types[j]); } } } // Update the active engines again to remove any engines that have no fuel supply UpdateActiveEngines(); if (log != null) { log.AppendLine("Active engines = ", activeEngines.Count); int i = 0; for (int j = 0; j < activeEngines.Count; j++) { EngineSim engine = activeEngines[j]; log.Append("Engine " + (i++) + ":"); engine.DumpEngineToLog(log); } log.Flush(); } }
private static void Reset(EngineSim engineSim) { engineSim.resourceConsumptions.Reset(); engineSim.maxResourceConsumptions.Reset(); engineSim.resourceFlowModes.Reset(); engineSim.partSim = null; engineSim.actualThrust = 0; engineSim.isActive = false; engineSim.isp = 0; for (int i = 0; i < engineSim.appliedForces.Count; i++) { engineSim.appliedForces[i].Release(); } engineSim.appliedForces.Clear(); engineSim.thrust = 0; engineSim.fullThrust = 0; engineSim.maxMach = 0f; engineSim.isFlamedOut = false; }
private void UpdateStageResourceSources() { UpdateStageEngines(); maxResourceParts.Clear(); maxResources.Clear(); for (int i = 0; i < stageEngines.Count; i++) { EngineSim engine = stageEngines[i]; if (engine.SetPossibleResourceDrains(log, allParts, maxResourceParts)) { for (int j = 0; j < engine.ResourceConsumptions.Types.Count; j++) { maxResources.Add(engine.ResourceConsumptions.Types[j]); } } } }
public void CreateEngineSims(List <EngineSim> allEngines, double atmosphere, double mach, bool vectoredThrust, bool fullThrust, LogMsg log) { if (log != null) { log.AppendLine("CreateEngineSims for ", this.name); } List <ModuleEngines> cacheModuleEngines = part.FindModulesImplementing <ModuleEngines>(); try { if (cacheModuleEngines.Count > 0) { //find first active engine, assuming that two are never active at the same time foreach (ModuleEngines engine in cacheModuleEngines) { if (engine.isEnabled) { if (log != null) { log.AppendLine("Module: ", engine.moduleName); } EngineSim engineSim = EngineSim.New( this, engine, atmosphere, (float)mach, vectoredThrust, fullThrust, log); allEngines.Add(engineSim); } } } } catch { Debug.Log("[KER] Error Catch in CreateEngineSims"); } }
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); }
// This function runs the simulation and returns a newly created array of Stage objects public Stage[] RunSimulation(LogMsg _log) { log = _log; if (log != null) { log.AppendLine("RunSimulation started"); } _timer.Reset(); _timer.Start(); // Start with the last stage to simulate // (this is in a member variable so it can be accessed by AllowedToStage and ActivateStage) currentStage = lastStage; // Work out which engines would be active if just doing the staging and if this is different to the // currently active engines then generate an extra stage // Loop through all the engines bool anyActive = false; for (int i = 0; i < allEngines.Count; ++i) { EngineSim engine = allEngines[i]; if (log != null) { log.AppendLine("Testing engine mod of ", engine.partSim.name, ":", engine.partSim.partId); } bool bActive = engine.isActive; bool bStage = (engine.partSim.inverseStage >= currentStage); if (log != null) { log.AppendLine("bActive = ", bActive, " bStage = ", bStage); } if (HighLogic.LoadedSceneIsFlight) { if (bActive) { anyActive = true; } if (bActive != bStage) { // If the active state is different to the state due to staging if (log != null) { log.AppendLine("Need to do current active engines first"); } doingCurrent = true; } } else { if (bStage) { if (log != null) { log.AppendLine("Marking as active"); } engine.isActive = true; } } } // If we need to do current because of difference in engine activation and there actually are active engines // then we do the extra stage otherwise activate the next stage and don't treat it as current if (doingCurrent && anyActive) { currentStage++; } else { ActivateStage(); doingCurrent = false; } // Create a list of lists of PartSims that prevent decoupling BuildDontStageLists(log); if (log != null) { log.Flush(); } // Create the array of stages that will be returned Stage[] stages = new Stage[currentStage + 1]; int startStage = currentStage; // Loop through the stages while (currentStage >= 0) { if (log != null) { log.AppendLine("Simulating stage ", currentStage); log.Flush(); _timer.Reset(); _timer.Start(); } // Update active engines and resource drains UpdateResourceDrains(); UpdateStageResourceSources(); // Update the masses of the parts to correctly handle "no physics" parts stageStartMass = UpdatePartMasses(); stageFullMass = UpdateFullResourceMass(); if (log != null) { allParts[0].DumpPartToLog(log, "", allParts); } // Create the Stage object for this stage Stage stage = new Stage(); stageTime = 0d; vecStageDeltaV = Vector3.zero; stageStartCom = ShipCom; stepStartMass = stageStartMass; stepEndMass = 0; CalculateThrustAndISP(); CalculateFullThrustAndISP(); stage.startMass = stageStartMass; stage.stageFullMass = stageFullMass; // Store various things in the Stage object stage.simpleThrust = simpleTotalThrust; stage.actualSimpleThrust = simpleActualTotalThrust; stage.thrust = totalStageThrust; stage.thrustToWeight = totalStageThrust / (stageStartMass * gravity); stage.maxThrustToWeight = stage.thrustToWeight; stage.actualThrust = totalStageActualThrust; stage.actualThrustToWeight = totalStageActualThrust / (stageStartMass * gravity); stage.thrustVector = vecThrust; stage.actualThrustVector = vecActualThrust; stage.totalExhaustVelocity = totalExhaustVelocity; stage.totalActualExhaustVelocity = totalActualExhaustVelocity; stage.totalVectoredExhaustVelocity = totalVectoredExhaustVelocity; stage.totalVectoredActualExhaustVelocity = totalActualVectoredExhaustVelocity; if (log != null) { log.AppendLine("stage.thrust = ", stage.thrust); log.AppendLine("StageMass = ", stageStartMass); log.AppendLine("Initial maxTWR = ", stage.maxThrustToWeight); } // calculate torque and associates stage.maxThrustTorque = totalStageThrustForce.TorqueAt(stageStartCom).magnitude; // torque divided by thrust. imagine that all engines are at the end of a lever that tries to turn the ship. // this numerical value, in meters, would represent the length of that lever. double torqueLeverArmLength = (stage.thrust <= 0) ? 0 : stage.maxThrustTorque / stage.thrust; // how far away are the engines from the CoM, actually? double thrustDistance = (stageStartCom - totalStageThrustForce.GetAverageForceApplicationPoint()).magnitude; // the combination of the above two values gives an approximation of the offset angle. double sinThrustOffsetAngle = 0; if (thrustDistance > 1e-7) { sinThrustOffsetAngle = torqueLeverArmLength / thrustDistance; if (sinThrustOffsetAngle > 1) { sinThrustOffsetAngle = 1; } } stage.thrustOffsetAngle = Math.Asin(sinThrustOffsetAngle) * 180 / Math.PI; // Calculate the total cost of the vessel at this point stage.totalCost = 0d; for (int i = 0; i < allParts.Count; ++i) { if (currentStage > allParts[i].decoupledInStage) { stage.totalCost += allParts[i].GetCost(currentStage); } } // The total mass is simply the mass at the start of the stage stage.totalMass = stageStartMass; // If we have done a previous stage if (currentStage < startStage) { // Calculate what the previous stage's mass and cost were by subtraction Stage prev = stages[currentStage + 1]; prev.cost = prev.totalCost - stage.totalCost; prev.mass = prev.totalMass - stage.totalMass; } // The above code will never run for the last stage so set those directly if (currentStage == 0) { stage.cost = stage.totalCost; stage.mass = stage.totalMass; } dontStageParts = dontStagePartsLists[currentStage]; if (log != null) { log.AppendLine("Stage setup took ", _timer.ElapsedMilliseconds, "ms"); if (dontStageParts.Count > 0) { log.AppendLine("Parts preventing staging:"); for (int i = 0; i < dontStageParts.Count; i++) { PartSim partSim = dontStageParts[i]; partSim.DumpPartToLog(log, ""); } } else { log.AppendLine("No parts preventing staging"); } log.Flush(); } // Now we will loop until we are allowed to stage int loopCounter = 0; while (!AllowedToStage()) { loopCounter++; //if (log != null) log.AppendLine("loop = ", loopCounter); // Calculate how long each draining tank will take to drain and run for the minimum time double resourceDrainTime = double.MaxValue; PartSim partMinDrain = null; foreach (PartSim partSim in drainingParts) { double time = partSim.TimeToDrainResource(log); if (time < resourceDrainTime) { resourceDrainTime = time; partMinDrain = partSim; } } if (log != null) { log.Append("Drain time = ", resourceDrainTime, " (", partMinDrain.name) .AppendLine(":", partMinDrain.partId, ")"); } foreach (PartSim partSim in drainingParts) { partSim.DrainResources(resourceDrainTime, log); } // Get the mass after draining stepEndMass = ShipMass; stageTime += resourceDrainTime; stage.endMass = stepEndMass; double stepEndTWR = totalStageThrust / (stepEndMass * gravity); /*if (log != null) * { * log.AppendLine("After drain mass = ", stepEndMass); * log.AppendLine("currentThrust = ", totalStageThrust); * log.AppendLine("currentTWR = ", stepEndTWR); * }*/ if (stepEndTWR > stage.maxThrustToWeight) { stage.maxThrustToWeight = stepEndTWR; } //if (log != null) log.AppendLine("newMaxTWR = ", stage.maxThrustToWeight); // If we have drained anything and the masses make sense then add this step's deltaV to the stage total if (resourceDrainTime > 0d && stepStartMass > stepEndMass && stepStartMass > 0d && stepEndMass > 0d) { vecStageDeltaV += vecThrust * (float)((currentisp * GRAVITY * Math.Log(stepStartMass / stepEndMass)) / simpleTotalThrust); } // Update the active engines and resource drains for the next step UpdateResourceDrains(); // Recalculate the current thrust and isp for the next step CalculateThrustAndISP(); // Check if we actually changed anything if (stepStartMass == stepEndMass) { //MonoBehaviour.print("No change in mass"); break; } // Check to stop rampant looping if (loopCounter == 1000) { if (log != null) { log.AppendLine("exceeded loop count"); log.AppendLine("stageStartMass = " + stageStartMass); log.AppendLine("stepStartMass = " + stepStartMass); log.AppendLine("StepEndMass = " + stepEndMass); } break; } // The next step starts at the mass this one ended at stepStartMass = stepEndMass; } if (stage.stageFullMass > stage.endMass && stage.stageFullMass > 0d && stage.endMass > 0d) { stage.stageStartDeltaV = (fullVecThrust * (float)((fullISP * GRAVITY * Math.Log(stage.stageFullMass / stage.endMass)) / fullSimpleThrust)).magnitude; } // Store more values in the Stage object and stick it in the array // Store the magnitude of the deltaV vector stage.deltaV = vecStageDeltaV.magnitude; stage.resourceMass = stageStartMass - stepEndMass; // Recalculate effective stage isp from the stage deltaV (flip the standard deltaV calculation around) // Note: If the mass doesn't change then this is a divide by zero if (stageStartMass != stepStartMass) { stage.isp = stage.deltaV / (GRAVITY * Math.Log(stageStartMass / stepStartMass)); } else { stage.isp = 0; } // Zero stage time if more than a day (this should be moved into the window code) stage.time = (stageTime < SECONDS_PER_DAY) ? stageTime : 0d; stage.number = doingCurrent ? -1 : currentStage; // Set the stage number to -1 if doing current engines stage.totalPartCount = allParts.Count; stage.maxMach = maxMach; stages[currentStage] = stage; // Now activate the next stage currentStage--; doingCurrent = false; if (log != null) { // Log how long the stage took _timer.Stop(); log.AppendLine("Simulating stage took ", _timer.ElapsedMilliseconds, "ms"); stage.Dump(log); _timer.Reset(); _timer.Start(); } // Activate the next stage ActivateStage(); if (log != null) { // Log how long it took to activate _timer.Stop(); log.AppendLine("ActivateStage took ", _timer.ElapsedMilliseconds, "ms"); } } // Now we add up the various total fields in the stages for (int i = 0; i < stages.Length; i++) { // For each stage we total up the cost, mass, deltaV and time for this stage and all the stages above for (int j = i; j >= 0; j--) { stages[i].totalStartDeltaV += stages[j].stageStartDeltaV; stages[i].totalDeltaV += stages[j].deltaV; stages[i].totalTime += stages[j].time; stages[i].partCount = i > 0 ? stages[i].totalPartCount - stages[i - 1].totalPartCount : stages[i].totalPartCount; } // We also total up the deltaV for stage and all stages below for (int j = i; j < stages.Length; j++) { stages[i].inverseTotalDeltaV += stages[j].deltaV; } // Zero the total time if the value will be huge (24 hours?) to avoid the display going weird // (this should be moved into the window code) if (stages[i].totalTime > SECONDS_PER_DAY) { stages[i].totalTime = 0d; } } FreePooledObject(); _timer.Stop(); if (log != null) { log.AppendLine("RunSimulation: ", _timer.ElapsedMilliseconds, "ms"); log.Flush(); } log = null; return(stages); }
// This function works out if it is time to stage private bool AllowedToStage() { if (log != null) { log.AppendLine("AllowedToStage") .AppendLine("currentStage = ", currentStage); } if (activeEngines.Count > 0) { for (int i = 0; i < dontStageParts.Count; ++i) { PartSim partSim = dontStageParts[i]; if (log != null) { partSim.DumpPartToLog(log, "Testing: "); } //if (log != null) log.AppendLine("isSepratron = ", partSim.isSepratron ? "true" : "false"); if (!partSim.isSepratron && !partSim.EmptyOf(drainingResources)) { if (log != null) { partSim.DumpPartToLog(log, "Decoupled part not empty => false: "); } return(false); } if (partSim.isEngine) { for (int j = 0; j < activeEngines.Count; ++j) { EngineSim engine = activeEngines[j]; if (engine.dontDecoupleActive && engine.partSim == partSim) { if (log != null) { partSim.DumpPartToLog(log, "Decoupled part is active engine => false: "); } return(false); } } } } } if (currentStage == 0 && doingCurrent) { if (log != null) { log.AppendLine("Current stage == 0 && doingCurrent => false"); } return(false); } if (log != null) { log.AppendLine("Returning true"); } return(true); }