public void Update() { if (GameSettings.MODIFIER_KEY.GetKey() && GameSettings.SAS_TOGGLE.GetKeyDown()) { bArmed = !bArmed; } if (bArmed) { if (GameSettings.SAS_TOGGLE.GetKeyDown()) { ActivitySwitch(!ActivityCheck()); } if (GameSettings.SAS_HOLD.GetKey()) { updateTarget(); } } if (vesModule.vesselRef.Autopilot != null) { if (currentMode != vesModule.vesselRef.Autopilot.Mode && currentMode == VesselAutopilot.AutopilotMode.StabilityAssist) { updateTarget(); } if (referenceMode == FlightUIController.SpeedDisplayModes.Surface && FlightUIController.speedDisplayMode != FlightUIController.SpeedDisplayModes.Surface) { orbitalTarget = vesModule.vesselRef.transform.rotation; } currentMode = vesModule.vesselRef.Autopilot.Mode; referenceMode = FlightUIController.speedDisplayMode; } if (bActive[(int)SASList.Hdg]) { SASList.Hdg.GetSAS(this).SetPoint = Utils.calculateTargetHeading(currentTarget, vesModule); } }
/// <summary> /// Common function for setting the autopilot mode /// </summary> /// <param name="mode"></param> private void ButtonSASModeClick(VesselAutopilot.AutopilotMode mode) { if (vessel != null) { vessel.Autopilot.SetActualMode(mode); } }
public void FixedUpdate() { if (IsEnabled == false) { return; } if (vessel == null) { return; } if (countdown > 0 && ratioHeadingVersusRequest > 0.999) { countdown--; if (persistentAutopilotMode != vessel.Autopilot.Mode) { vessel.Autopilot.SetMode(persistentAutopilotMode); return; } else { ratioHeadingVersusRequest = vessel.PersistHeading(true); } } // persist heading and drop out of warp when previously was maintaining heading ratioHeadingVersusRequest = vessel.PersistHeading(false, ratioHeadingVersusRequest == 1); persistentAutopilotMode = vessel.Autopilot.Mode; }
/// <summary> /// Force the SAS mode buttons on the flight view to update when we /// update modes under the hood. Code from /// http://forum.kerbalspaceprogram.com/threads/105074-Updating-the-auto-pilot-UI?p=1633958&viewfull=1#post1633958 /// </summary> /// <param name="newMode">The new autopilot mode</param> private void ForceUpdateSASModeToggleButtons(VesselAutopilot.AutopilotMode newMode) { // find the UI object on screen RUIToggleButton[] SASbtns = UnityEngine.Object.FindObjectOfType <VesselAutopilotUI>().modeButtons; // set our mode, note it takes the mode as an int, generally top to bottom, left to right, as seen on the screen. Maneuver node being the exception, it is 9 SASbtns.ElementAt <RUIToggleButton>((int)newMode).SetTrue(true, true); }
public void autopilotModeCallback(byte ID, object Data) { byte[] payload = (byte[])Data; VesselAutopilot autopilot = FlightGlobals.ActiveVessel.Autopilot; if (autopilot == null) { Debug.Log("KerbalSimpit : Ignoring a SAS MODE Message since I could not find the autopilot"); return; } mySASMode = (VesselAutopilot.AutopilotMode)(payload[0]); if (autopilot.CanSetMode(mySASMode)) { autopilot.SetMode(mySASMode); if (KSPit.Config.Verbose) { Debug.Log(String.Format("KerbalSimpit: payload is {0}", mySASMode)); Debug.Log(String.Format("KerbalSimpit: SAS mode is {0}", FlightGlobals.ActiveVessel.Autopilot.Mode.ToString())); } } else { Debug.Log(String.Format("KerbalSimpit: Unable to set SAS mode to {0}", mySASMode.ToString())); } }
public void FixedUpdate() { if (HighLogic.LoadedSceneIsEditor) { return; } if (_reactionWheel == null) { return; } // save or restore AutopilotMode if (_fixedUpdateCount++ > 100) { persistentAutopilotMode = vessel.Autopilot.Mode; } else { vessel.Autopilot.SetMode(persistentAutopilotMode); } // detect if vessel is heading headingSpinDelta = (previousPartHeading - part.transform.up).magnitude / TimeWarp.deltaTime; rotationSpinDelta = (previousPartRotation - part.transform.rotation.eulerAngles).magnitude / TimeWarp.deltaTime; previousPartRotation = part.transform.rotation.eulerAngles; previousPartHeading = part.transform.up; var isStabilized = false; if (isAutoStabilizing) { isStabilized = StabilizeWhenPossible(0.0005f, 1, 1, 1); } var torqueRatio = GetTorqueRatio(isStabilized); _torqueRatioQueue.Enqueue(torqueRatio); if (_torqueRatioQueue.Count > 4) { _torqueRatioQueue.Dequeue(); } maxPowerCostMj = maxPowerCost / GameConstants.ecPerMJ; var requiredPower = torqueRatio * maxPowerCostMj; var requestedPower = Math.Max(1e-8, _torqueRatioQueue.Max() * maxPowerCostMj - _bufferOvercapacity); var receivedPower = ConsumeMegawatts(requestedPower, true, true, true); _bufferPower = Math.Max(0, _bufferPower + receivedPower - requiredPower); _bufferOvercapacity = Math.Min(maxBufferCapacity, Math.Max(0, _bufferPower - maxBufferCapacity)); _bufferPower = Math.Min(_bufferPower, maxBufferCapacity); powerFactor = requiredPower > 0 ? Math.Min(1, (receivedPower + _bufferPower) / requiredPower) : 1; UpdateReactionWheelTorque(); }
private static bool setAutopilotMode(VesselAutopilot.AutopilotMode mode) { //Debug.Log("setAutopilotMode, mode: " + mode); if (FlightGlobals.ActiveVessel.Autopilot.CanSetMode(mode)) { FlightGlobals.ActiveVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); FlightGlobals.ActiveVessel.Autopilot.Update(); FlightGlobals.ActiveVessel.Autopilot.SetMode(mode); return(true); } return(false); }
private static VesselAutopilot.AutopilotMode ConvertMode(VesselAutopilot.AutopilotMode mode) { if (mode == VesselAutopilot.AutopilotMode.RadialIn) { mode = VesselAutopilot.AutopilotMode.RadialOut; } else if (mode == VesselAutopilot.AutopilotMode.RadialOut) { mode = VesselAutopilot.AutopilotMode.RadialIn; } return(mode); }
private static bool Prefix(VesselAutopilot.AutopilotMode mode, Vessel vessel, ref bool __result) { __result = vessel.VesselValues.AutopilotSkill.value >= mode.GetRequiredSkill(); return(false); // Okay seriously, that looks waaaaay simpler than it actually is, so verbose pseudocode + documentation is in order here! /* * if (requirePilotForSAS) * { * // Despite not tracking kerbal experience (i.e. all crew always at Lvl 5) we can make specializations more meaningful * // Require Pilot (ExperienceEffect.AutopilotSkill) for crewed, ModuleSAS for uncrewed * // Basically, stock default career behavior, except that all pilots are always Lvl 5. * // This is the expression you see above * __result = vessel.VesselValues.AutopilotSkill.value >= mode.GetRequiredSkill(); * } * else * { * // Allow any crewmember to provide full SAS, but require ModuleSAS for uncrewed * // The stock default sandbox behavior is buggy and brittle, so we have to implement a better version of it * // Something like: * __result = hasAnyCrewAutopilot(vessel) || hasProbeAutopilot(mode, vessel); * * // Checking probes is easy: * bool hasProbeAutopilot(mode, vessel) { * return vessel.VesselValues.AutopilotSASSkill.value >= mode.GetRequiredSkill(); * } * * // Checking crew is the part that needs fixing: * // Stock default sandbox behavior ( EnableKerbalExperience FALSE, EnableFullSASInSandbox FALSE ) purports to give all crew full SAS * // But testing shows that it seems to actually check for ExperienceEffect.{ AutopilotSkill, RepairSkill, ScienceSkill } in lieu of { Pilot, Engineer, Scientist } respectively * // This means that other specializations (from mods) will not qualify if they don't have one of these three skills! * * // One way to fix it would be to check for any onboard ProtoCrewMember of pcm.type == KerbalType.Crew rather than KerbalType.Tourist * // However, that approach would break expected behavior for other mods that involve disabling kerbal skills, e.g. * // - mods that modify pcm.trait to Tourist (without changing pcm.type) * // - Kerbal Status Effects * * // Instead, we implement our own skill SandboxAutopilotSkill : ExperienceEffect * // and grant it to all non-tourist/civilian specializations (EXPERIENCE_TRAIT)s * * // Then, naively, the first thought would be to implement hasAnyCrewAutopilot(vessel) check in one of two ways: * // - iterate through all command module occupants looking for pcm.HasEffect<SandboxAutopilotSkill>() (potentially costly) or * // - build infrastructure similar to PartValues / VesselValues specifically for the SandboxAutopilotSkill skill * * // Or, we could be smart about it, and have SandboxAutopilotSkill perform OnRegister(part)/OnUnregister(part) selectively * // i.e. only when the necessary combination of game mode and GameParameters is satisfied * // Registration of the skill to a part adds it to the already existent part.PartValues.AutopilotSkill * // This little trick allows us to arrive at the same expression used for the (requirePilotForSAS == true) case! * } */ }
private static bool setAutopilotMode(VesselAutopilot.AutopilotMode mode, int ui_button) { if (FlightGlobals.ActiveVessel.Autopilot.CanSetMode(mode)) { FlightGlobals.ActiveVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); FlightGlobals.ActiveVessel.Autopilot.Update(); FlightGlobals.ActiveVessel.Autopilot.SetMode(mode); setSASUI(ui_button); return(true); } else { return(false); } }
// ReSharper disable once InconsistentNaming private void SetSAS(VesselAutopilot.AutopilotMode mode) { if (!vessel.Autopilot.SAS.CanEngageSAS()) { ScreenMessages.PostScreenMessage(message: "Vessel cannot engage SAS"); return; } if (!vessel.Autopilot.CanSetMode(mode: mode)) { ScreenMessages.PostScreenMessage(message: $"Vessel cannot set SAS to {mode}"); return; } vessel.ActionGroups.SetGroup(@group: KSPActionGroup.SAS, active: true); // turn on SAS vessel.Autopilot.Enable(mode: mode); // set SAS mode }
public static bool SetActualMode(this VesselAutopilot autopilot, VesselAutopilot.AutopilotMode mode) { mode = ConvertMode(mode); if (autopilot.CanSetMode(mode)) { var result = autopilot.SetMode(mode); var autopilotUI = GameObject.FindObjectOfType <VesselAutopilotUI>(); if (autopilotUI != null && mode >= 0 && (int)mode < autopilotUI.modeButtons.Length) { autopilotUI.modeButtons[(int)mode].SetState(true); } return(result); } return(false); }
public void Update() { if (GameSettings.MODIFIER_KEY.GetKey() && GameSettings.SAS_TOGGLE.GetKeyDown()) { bArmed = !bArmed; } if (bArmed) { pauseManager(); if (GameSettings.SAS_TOGGLE.GetKeyDown()) { ActivitySwitch(!ActivityCheck()); } if (GameSettings.SAS_HOLD.GetKey()) { updateTarget(); } } if (ves.Autopilot != null) { if (APMode != ves.Autopilot.Mode && APMode == VesselAutopilot.AutopilotMode.StabilityAssist) { updateTarget(); } if (spdMode != FlightUIController.speedDisplayMode) { if (spdMode == FlightUIController.SpeedDisplayModes.Surface) { } else { orbitalTarget = ves.transform.rotation; } } APMode = ves.Autopilot.Mode; spdMode = FlightUIController.speedDisplayMode; } if (bActive[(int)SASList.Hdg]) { GetSAS(SASList.Hdg).SetPoint = calculateTargetHeading(currentTarget, ves); } }
public void autopilotModeCallback(byte ID, object Data) { byte[] payload = (byte[])Data; mySASMode = (VesselAutopilot.AutopilotMode)(payload[0]); myActiveVessel = FlightGlobals.ActiveVessel; if (myActiveVessel.Autopilot.CanSetMode(mySASMode)) { myActiveVessel.Autopilot.SetMode((VesselAutopilot.AutopilotMode)mySASMode); if (KSPit.Config.Verbose) { Debug.Log(String.Format("KerbalSimpit: payload is {0}", mySASMode)); Debug.Log(String.Format("KerbalSimpit: SAS mode is {0}", myActiveVessel.Autopilot.Mode.ToString())); } } else { Debug.Log(String.Format("KerbalSimpit: Unable to set SAS mode to {0}", mySASMode.ToString())); } }
public void SelectAutopilotMode(VesselAutopilot.AutopilotMode autopilotMode) { if (currentVessel.Autopilot.Mode != autopilotMode) { if (!currentVessel.Autopilot.CanSetMode(autopilotMode)) { // throw an exception if the mode is not available throw new Safe.Exceptions.KOSException( string.Format("Cannot set autopilot value, pilot/probe does not support {0}, or there is no node/target", autopilotMode)); } currentVessel.Autopilot.SetMode(autopilotMode); //currentVessel.Autopilot.Enable(); // change the autopilot indicator ((Module.kOSProcessor)Shared.Processor).SetAutopilotMode((int)autopilotMode); if (RemoteTechHook.IsAvailable(currentVessel.id)) { Debug.Log(string.Format("kOS: Adding RemoteTechPilot: autopilot For : " + currentVessel.id)); // TODO: figure out how to make RemoteTech allow the built in autopilot control. This may require modification to RemoteTech itself. } } }
public static AutoPilotModeEnum ToPTIEnum(this VesselAutopilot.AutopilotMode mode) { switch (mode) { case VesselAutopilot.AutopilotMode.StabilityAssist: return(AutoPilotModeEnum.StabilityAssist); case VesselAutopilot.AutopilotMode.Prograde: return(AutoPilotModeEnum.Prograde); case VesselAutopilot.AutopilotMode.Retrograde: return(AutoPilotModeEnum.Retrograde); case VesselAutopilot.AutopilotMode.Normal: return(AutoPilotModeEnum.Normal); case VesselAutopilot.AutopilotMode.Antinormal: return(AutoPilotModeEnum.Antinormal); case VesselAutopilot.AutopilotMode.RadialIn: return(AutoPilotModeEnum.RadialIn); case VesselAutopilot.AutopilotMode.RadialOut: return(AutoPilotModeEnum.RadialOut); case VesselAutopilot.AutopilotMode.Target: return(AutoPilotModeEnum.Target); case VesselAutopilot.AutopilotMode.AntiTarget: return(AutoPilotModeEnum.AntiTarget); case VesselAutopilot.AutopilotMode.Maneuver: return(AutoPilotModeEnum.Maneuver); default: return(AutoPilotModeEnum.StabilityAssist); } }
public static KRPC.SpaceCenter.Services.SASMode ToSASMode(this VesselAutopilot.AutopilotMode mode) { switch (mode) { case VesselAutopilot.AutopilotMode.StabilityAssist: return(KRPC.SpaceCenter.Services.SASMode.StabilityAssist); case VesselAutopilot.AutopilotMode.Maneuver: return(KRPC.SpaceCenter.Services.SASMode.Maneuver); case VesselAutopilot.AutopilotMode.Prograde: return(KRPC.SpaceCenter.Services.SASMode.Prograde); case VesselAutopilot.AutopilotMode.Retrograde: return(KRPC.SpaceCenter.Services.SASMode.Retrograde); case VesselAutopilot.AutopilotMode.Normal: return(KRPC.SpaceCenter.Services.SASMode.Normal); case VesselAutopilot.AutopilotMode.Antinormal: return(KRPC.SpaceCenter.Services.SASMode.AntiNormal); case VesselAutopilot.AutopilotMode.RadialIn: return(KRPC.SpaceCenter.Services.SASMode.Radial); case VesselAutopilot.AutopilotMode.RadialOut: return(KRPC.SpaceCenter.Services.SASMode.AntiRadial); case VesselAutopilot.AutopilotMode.Target: return(KRPC.SpaceCenter.Services.SASMode.Target); case VesselAutopilot.AutopilotMode.AntiTarget: return(KRPC.SpaceCenter.Services.SASMode.AntiTarget); default: throw new ArgumentOutOfRangeException("mode"); } }
IEnumerator startSAS(VesselAutopilot.AutopilotMode autoPilot) { if (TimeWarp.CurrentRate > 1 && TimeWarp.WarpMode == TimeWarp.Modes.HIGH) { TimeWarp.fetch.CancelAutoWarp(); TimeWarp.SetRate(0, false); } while (TimeWarp.CurrentRate > 1 && TimeWarp.WarpMode == TimeWarp.Modes.HIGH) { yield return(0); } yield return(new WaitForFixedUpdate()); Vessel _vessel = FlightGlobals.ActiveVessel; if (!_vessel.Autopilot.SAS.dampingMode) { _vessel.ActionGroups.SetGroup(KSPActionGroup.SAS, true); } yield return(new WaitForFixedUpdate()); _vessel.Autopilot.SetMode(autoPilot); }
//protected override void OnLoad(ConfigNode node) //{ // base.OnLoad(node); //} //protected override void OnSave(ConfigNode node) //{ // base.OnSave(node); //} ////When the scene changes and the mod is destroyed //public void OnDestroy() //{ // //If we're in the MainMenu, don't do anything // if (forbiddenScenes.Contains(HighLogic.LoadedScene)) // return; //} //public override void OnLoadVessel() //{ // base.OnLoadVessel(); //} //public override void OnUnloadVessel() //{ // base.OnUnloadVessel(); //} //public override void OnGoOnRails() //{ // base.OnGoOnRails(); //} //public override void OnGoOffRails() //{ // base.OnGoOffRails(); //} //public override bool ShouldBeActive() //{ // return base.ShouldBeActive(); //} /// <summary> /// Is called on every frame /// </summary> public void FixedUpdate() { // ignore Kerbals if (vessel.isEVA) { return; } // ignore irrelevant vessel types if (vessel.vesselType == VesselType.Debris || vessel.vesselType == VesselType.Flag || vessel.vesselType == VesselType.SpaceObject || vessel.vesselType == VesselType.DeployedSciencePart || vessel.vesselType == VesselType.DeployedScienceController ) { return; } // lookup vessel data PersistentScenarioModule.VesselDataDict.TryGetValue(vessel.id, out VesselData vesselData); if (vesselData == null) { return; } if (vessel.loaded == false) { vesselData.PersistentAutopilotMode = persistentAutopilotMode; vesselData.persistentVesselTargetId = persistentVesselTargetId; vesselData.persistentVesselTargetBodyName = persistentVesselTargetBodyName; vesselData.persistentManeuverUT = persistentManeuverUT; vesselData.persistentManeuverNextPatch = persistentManeuverNextPatch; vesselData.persistentManeuverPatch = persistentManeuverPatch; return; } if (fixedUpdateCount++ > 100) { persistentAutopilotMode = vessel.Autopilot.Mode; if (vessel.targetObject != null) { var orbitDriver = vessel.targetObject.GetOrbitDriver(); if (orbitDriver.vessel != null) { persistentVesselTargetId = orbitDriver.vessel.id.ToString(); persistentVesselTargetBodyName = string.Empty; } else if (orbitDriver.celestialBody != null) { persistentVesselTargetId = Guid.Empty.ToString(); persistentVesselTargetBodyName = orbitDriver.celestialBody.bodyName; } } else { persistentVesselTargetId = Guid.Empty.ToString(); persistentVesselTargetBodyName = string.Empty; } if (vessel.patchedConicSolver != null && vessel.patchedConicSolver.maneuverNodes.Count > 0) { var maneuverNode = vessel.patchedConicSolver.maneuverNodes[0]; persistentManeuverUT = maneuverNode.UT; persistentManeuverNextPatch = maneuverNode.patch.Serialize(); persistentManeuverPatch = maneuverNode.patch.Serialize(); } } else { vessel.Autopilot.SetMode(persistentAutopilotMode); vessel.PersistHeading(TimeWarp.fixedDeltaTime, headingTolerance, true); } }
private static bool Prefix(VesselAutopilot.AutopilotMode mode, int skillLvl, ref bool __result) { __result = skillLvl >= mode.GetRequiredSkill(); return(false); }
public void Update() { if (GameSettings.MODIFIER_KEY.GetKey() && GameSettings.SAS_TOGGLE.GetKeyDown()) bArmed = !bArmed; if (bArmed) { if (GameSettings.SAS_TOGGLE.GetKeyDown()) ActivitySwitch(!ActivityCheck()); if (GameSettings.SAS_HOLD.GetKey()) updateTarget(); } if (vesModule.vesselRef.Autopilot != null) { if (currentMode != vesModule.vesselRef.Autopilot.Mode && currentMode == VesselAutopilot.AutopilotMode.StabilityAssist) updateTarget(); if (referenceMode == FlightUIController.SpeedDisplayModes.Surface && FlightUIController.speedDisplayMode != FlightUIController.SpeedDisplayModes.Surface) orbitalTarget = vesModule.vesselRef.transform.rotation; currentMode = vesModule.vesselRef.Autopilot.Mode; referenceMode = FlightUIController.speedDisplayMode; } if (bActive[(int)SASList.Hdg]) SASList.Hdg.GetSAS(this).SetPoint = Utils.calculateTargetHeading(currentTarget, vesModule); }
/// <summary> /// returns a boolean indicating whether the specified SAS mode is active /// </summary> /// <param name="mode"></param> /// <returns></returns> private bool ButtonSASModeState(VesselAutopilot.AutopilotMode mode) { return(vessel != null && vessel.Autopilot.GetActualMode() == mode); }
public static bool CanSetActualMode(this VesselAutopilot autopilot, VesselAutopilot.AutopilotMode mode) { return(autopilot.CanSetMode(ConvertMode(mode))); }
public void Update() { if (GameSettings.MODIFIER_KEY.GetKey() && GameSettings.SAS_TOGGLE.GetKeyDown()) bArmed = !bArmed; if (bArmed) { pauseManager(); if (GameSettings.SAS_TOGGLE.GetKeyDown()) ActivitySwitch(!ActivityCheck()); if (GameSettings.SAS_HOLD.GetKey()) updateTarget(); } if (ves.Autopilot != null) { if (APMode != ves.Autopilot.Mode && APMode == VesselAutopilot.AutopilotMode.StabilityAssist) updateTarget(); if (spdMode != FlightUIController.speedDisplayMode) { if (spdMode == FlightUIController.SpeedDisplayModes.Surface) { } else orbitalTarget = ves.transform.rotation; } APMode = ves.Autopilot.Mode; spdMode = FlightUIController.speedDisplayMode; } if (bActive[(int)SASList.Hdg]) GetSAS(SASList.Hdg).SetPoint = calculateTargetHeading(currentTarget, ves); }
// Physics update public void FixedUpdate() // FixedUpdate is also called while not staged { if (this.vessel is null || currentEngine.engine is null || !isEnabled) { return; } fixedUpdateCount++; var universalTime = Planetarium.GetUniversalTime(); // restore heading at load if (HasPersistentHeadingEnabled && fixedUpdateCount <= 60 && vesselAlignmentWithAutopilotMode > 0.995) { vessel.Autopilot.SetMode(persistentAutopilotMode); vessel.PersistHeading(TimeWarp.fixedDeltaTime, headingTolerance, vesselChangedSoiCountdown > 0); } else { persistentAutopilotMode = vessel.Autopilot.Mode; } //vesselHeadingVersusManeuver = vessel.VesselOrbitHeadingVersusManeuverVector(); //vesselHeadingVersusManeuverInDegrees = Math.Acos(Math.Max(-1, Math.Min(1, vesselHeadingVersusManeuver))) * Rad2Deg; _kerbalismResourceChangeRequest.Clear(); if (vesselChangedSoiCountdown > 0) { vesselChangedSoiCountdown--; } // Checks if moduleEngine mode wasn't switched FetchActiveMode(); var processedEngines = isMultiMode ? new[] { currentEngine } : moduleEngines; // Realtime mode if (!vessel.packed) { vesselAlignmentWithAutopilotMode = vessel.HeadingVersusAutopilotVector(universalTime); // Update persistent thrust throttle if NOT transitioning from warp to realtime if (!warpToReal) { UpdatePersistentThrottle(); } for (var i = 0; i < processedEngines.Length; i++) { currentEngine = processedEngines[i]; ResetMonitoringVariables(); // Update persistent thrust isp if NOT transitioning from warp to realtime if (!warpToReal) { UpdatePersistentIsp(); } currentEngine.engineHasAnyMassLessPropellants = currentEngine.engine.propellants.Any(m => m.resourceDef.density == 0); if (processMasslessSeparately && currentEngine.engineHasAnyMassLessPropellants) { ReloadPropellantsWithoutMasslessPropellants(); } //if (vesselHeadingVersusManeuverInDegrees > maneuverTolerance) //{ // moduleEngine.maxFuelFlow = 1e-10f; // finalThrust = 0; //} //else if (!currentEngine.engine.getIgnitionState) { currentEngine.finalThrust = 0; // restore maximum flow RestoreMaxFuelFlow(); } else if (!currentEngine.engineHasAnyMassLessPropellants && currentEngine.engine.propellantReqMet > 0) { // Mass flow rate var massFlowRate = currentEngine.persistentIsp > 0 ? currentEngine.engine.currentThrottle * currentEngine.engine.maxThrust / (currentEngine.persistentIsp * PhysicsGlobals.GravitationalAcceleration) : 0; // Change in mass over time interval dT var deltaMass = massFlowRate * TimeWarp.fixedDeltaTime; // Resource demand from propellants with mass currentEngine.demandMass = currentEngine.averageDensity > 0 ? deltaMass / currentEngine.averageDensity : 0; // Calculate resource demands currentEngine.fuelDemands = CalculateDemands(currentEngine.demandMass); // Apply resource demands & test for resource depletion ApplyDemands(currentEngine.fuelDemands, ref currentEngine.propellantReqMetFactor); // calculate maximum flow var maxFuelFlow = currentEngine.persistentIsp > 0 ? currentEngine.engine.maxThrust / (currentEngine.persistentIsp * PhysicsGlobals.GravitationalAcceleration) : 0; // adjust fuel flow currentEngine.engine.maxFuelFlow = maxFuelFlow > 0 && currentEngine.propellantReqMetFactor > 0 ? (float)(maxFuelFlow * currentEngine.propellantReqMetFactor) : 1e-10f; // update displayed thrust and fx currentEngine.finalThrust = currentEngine.engine.currentThrottle * currentEngine.engine.maxThrust * Math.Min(currentEngine.propellantReqMetFactor, currentEngine.engine.propellantReqMet * 0.01f); } else { // restore maximum flow RestoreMaxFuelFlow(); currentEngine.propellantReqMetFactor = currentEngine.engine.propellantReqMet * 0.01f; currentEngine.finalThrust = currentEngine.engine.GetCurrentThrust(); } UpdatePropellantReqMetFactorQueue(); UpdateFX(); SetThrottleAnimation(); UpdateBuffers(); } } else { for (var i = 0; i < processedEngines.Length; i++) { currentEngine = processedEngines[i]; ResetMonitoringVariables(); // restore maximum flow RestoreMaxFuelFlow(); if (persistentThrottle > 0 && currentEngine.persistentIsp > 0 && isPersistentEngine && HasPersistentThrust) { if (TimeWarp.CurrentRateIndex == 0) { warpToReal = true; // Set to true for transition to realtime } // Calculated requested thrust //var requestedThrust = vesselHeadingVersusManeuverInDegrees <= maneuverTolerance ? moduleEngine.thrustPercentage * 0.01f * persistentThrottle * moduleEngine.maxThrust : 0; var requestedThrust = currentEngine.engine.thrustPercentage * 0.01f * persistentThrottle * currentEngine.engine.maxThrust; var thrustVector = part.transform.up; // Thrust direction unit vector // Calculate deltaV vector & resource demand from propellants with mass var deltaVVector = CalculateDeltaVVector(currentEngine.averageDensity, vessel.totalMass, TimeWarp.fixedDeltaTime, requestedThrust, currentEngine.persistentIsp, thrustVector, out currentEngine.demandMass); // Calculate resource demands currentEngine.fuelDemands = CalculateDemands(currentEngine.demandMass); // Apply resource demands & test for resource depletion ApplyDemands(currentEngine.fuelDemands, ref currentEngine.propellantReqMetFactor); // Apply deltaV vector at UT & dT to orbit if resources not depleted if (currentEngine.propellantReqMetFactor > 0) { currentEngine.finalThrust = requestedThrust * currentEngine.propellantReqMetFactor; vessel.orbit.Perturb(deltaVVector * currentEngine.propellantReqMetFactor, universalTime); } // Otherwise log warning and drop out of TimeWarp if throttle on & depleted else if (persistentThrottle > 0) { currentEngine.finalThrust = 0; Debug.Log("[PersistentThrust]: Thrust warp stopped - propellant depleted"); ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_PT_StoppedDepleted"), 5.0f, ScreenMessageStyle.UPPER_CENTER); // Return to realtime TimeWarp.SetRate(0, true); if (!vessel.IsControllable) { persistentThrottle = 0; vessel.ctrlState.mainThrottle = 0; } } else { currentEngine.finalThrust = 0; } SetThrottleAnimation(); UpdateFX(); } else { currentEngine.finalThrust = 0; SetThrottleAnimation(); UpdateFX(); UpdateBuffers(); } } if (vessel.IsControllable && HasPersistentHeadingEnabled) { vesselAlignmentWithAutopilotMode = vessel.PersistHeading(TimeWarp.fixedDeltaTime, headingTolerance, vesselChangedSoiCountdown > 0, vesselAlignmentWithAutopilotMode == 1); } } // display final thrust in a user friendly way thrustTxt = Utils.FormatThrust(moduleEngines.Sum(m => m.finalThrust)); previousFixedDeltaTime = TimeWarp.fixedDeltaTime; UpdateMasslessConsumption(); }