public void LateUpdate() { logFuelCheatActivation(); try { if (!BurnInfo.IsInitialized) { return; // can't do anything } string customDescription = null; double dVrequired = ImpactTracker.ImpactSpeed; int timeUntil = -1; if (double.IsNaN(dVrequired)) { // No impact info is available. Do we have closest-approach info? dVrequired = ClosestApproachTracker.Velocity; if (double.IsNaN(dVrequired)) { // No closest-approach info available either, use the maneuver dV remaining. dVrequired = BurnInfo.DvRemaining; timeUntil = SecondsUntilNode(); } else { // We have closest-approach info, use the description from that. customDescription = ClosestApproachTracker.Description; timeUntil = ClosestApproachTracker.TimeUntil; } } else { // We have impact info, use the description from that. customDescription = ImpactTracker.Description; // TODO: enable countdown to retro-burn, not doing it now 'coz it needs more math & logic // timeUntil = ImpactTracker.TimeUntil; } // At this point, either we have a dVrequired or not. If we have one, we might // have a description (meaning it's one of our custom trackers from this mod) // or we might not (meaning "leave it alone at let the stock game decide what to say"). if (double.IsNaN(dVrequired)) { return; } if (FlightGlobals.ActiveVessel == null) { return; } if (FlightGlobals.ActiveVessel.IsEvaKerbal()) { // it's a kerbal on EVA BurnInfo.Duration = EVA_KERBAL_LABEL; BurnInfo.Countdown = string.Empty; } else { // it's a ship, not an EVA kerbal vessel.Refresh(); propellantsConsumed = new Tally(); bool isInsufficientFuel; double floatBurnSeconds = GetBurnTime(dVrequired, out isInsufficientFuel); int burnSeconds = double.IsInfinity(floatBurnSeconds) ? -1 : (int)(0.5 + floatBurnSeconds); if (burnSeconds != lastBurnTime) { lastBurnTime = burnSeconds; if (isInsufficientFuel) { lastUpdateText = ESTIMATED_BURN_LABEL + TimeFormatter.Default.warn(burnSeconds); } else { lastUpdateText = ESTIMATED_BURN_LABEL + TimeFormatter.Default.format(burnSeconds); } } BurnInfo.Duration = lastUpdateText; BurnInfo.Countdown = Countdown.ForSeconds(timeUntil - burnSeconds / 2); } if (customDescription == null) { // No custom description available, turn off the alternate display BurnInfo.AlternateDisplayEnabled = false; } else { // We have alternate info to show BurnInfo.TimeUntil = customDescription; BurnInfo.AlternateDisplayEnabled = true; } } catch (Exception e) { Logging.Exception(e); BurnInfo.Duration = e.GetType().Name + ": " + e.Message + " -> " + e.StackTrace; } }
public void LateUpdate() { logFuelCheatActivation(); try { BetterBurnTimeData api = BetterBurnTimeData.Current; if (api != null) { api.Reset(); } if (!BurnInfo.IsInitialized) { return; // can't do anything } BetterBurnTimeData.BurnType burnType = BetterBurnTimeData.BurnType.None; string customDescription = null; double dVrequired = ImpactTracker.ImpactSpeed; double timeUntil = double.NaN; bool shouldDisplayCountdown = false; if (double.IsNaN(dVrequired)) { // No impact info is available. Do we have closest-approach info? dVrequired = ClosestApproachTracker.Velocity; if (double.IsNaN(dVrequired)) { // No closest-approach info is available either. At this point, we've exhausted all // of our special-tracking-burn-information options (impact, closest approach), so // we won't show any burn information or countdown. (Before KSP 1.5, we would have // checked for a maneuver node, and if present, we would have shown a countdown // and our revised burn time estimate. KSP 1.5, however, introduced drastically improved // burn-time indication in stock, so there's no point in trying to compete with that-- // it's good enough, so leave it alone. shouldDisplayCountdown = false; // Do we have a maneuver node? dVrequired = BurnInfo.DvRemaining; if (double.IsNaN(dVrequired)) { // No, there's no maneuver node. burnType = BetterBurnTimeData.BurnType.None; // If we've got an upcoming atmosphere transition, include that info. customDescription = AtmosphereTracker.Description; if (customDescription == null) { customDescription = GeosyncTracker.Description; timeUntil = 0; } else { timeUntil = AtmosphereTracker.TimeUntil; } } else { // Yep, there's a maneuver node. timeUntil = SecondsUntilNode(); burnType = BetterBurnTimeData.BurnType.Maneuver; } } else { // We have closest-approach info, use the description from that. customDescription = ClosestApproachTracker.Description; timeUntil = ClosestApproachTracker.TimeUntil; shouldDisplayCountdown = true; burnType = BetterBurnTimeData.BurnType.Rendezvous; } } else { // We have impact info, use the description from that. customDescription = ImpactTracker.Description; timeUntil = ImpactTracker.TimeUntil; // TODO: enable countdown to retro-burn, not doing it now 'coz it needs more math & logic // shouldDisplayCountdown = true burnType = BetterBurnTimeData.BurnType.Impact; } if (FlightGlobals.ActiveVessel == null) { BurnInfo.Countdown = string.Empty; if (customDescription == null) { BurnInfo.AlternateDisplayEnabled = false; } return; } if (double.IsNaN(dVrequired) && !double.IsNaN(timeUntil)) { // Special case of knowing a time until an event, but there's no dV associated // with it and therefore no burn display. BurnInfo.Duration = string.Empty; BurnInfo.TimeUntil = customDescription; BurnInfo.AlternateDisplayEnabled = true; BurnInfo.Countdown = string.Empty; return; } // At this point, either we have a dVrequired or not. If we have one, we might // have a description (meaning it's one of our custom trackers from this mod) // or we might not (meaning "leave it alone at let the stock game decide what to say"). if ((burnType == BetterBurnTimeData.BurnType.Maneuver) || double.IsNaN(dVrequired) || (FlightGlobals.ActiveVessel == null)) { BurnInfo.Countdown = string.Empty; if (customDescription == null) { BurnInfo.AlternateDisplayEnabled = false; } return; } if (FlightGlobals.ActiveVessel.IsEvaKerbal()) { // it's a kerbal on EVA BurnInfo.Duration = EVA_KERBAL_LABEL; BurnInfo.Countdown = string.Empty; } else { // it's a ship, not an EVA kerbal vessel.Refresh(); propellantsConsumed = new Tally(); bool isInsufficientFuel; double floatBurnSeconds = GetBurnTime(dVrequired, out isInsufficientFuel); int burnSeconds = double.IsInfinity(floatBurnSeconds) ? -1 : (int)(0.5 + floatBurnSeconds); if (burnSeconds != lastBurnTime) { lastBurnTime = burnSeconds; if (isInsufficientFuel) { lastUpdateText = ESTIMATED_BURN_LABEL + TimeFormatter.Default.warn(burnSeconds); } else { lastUpdateText = ESTIMATED_BURN_LABEL + TimeFormatter.Default.format(burnSeconds); } } BurnInfo.Duration = lastUpdateText; int intTimeUntil = (double.IsNaN(timeUntil) || !shouldDisplayCountdown) ? -1 : (int)timeUntil; int timeUntilBurnStart = intTimeUntil - burnSeconds / 2; if (timeUntilBurnStart != lastTimeUntilBurnStart) { lastTimeUntilBurnStart = timeUntilBurnStart; BurnInfo.Countdown = Countdown.ForSeconds(timeUntilBurnStart); } if (api != null) { api.burnType = burnType; api.burnTime = floatBurnSeconds; api.dV = dVrequired; api.timeUntil = timeUntil; api.isInsufficientFuel = isInsufficientFuel; } } if (customDescription == null) { // No custom description available, turn off the alternate display BurnInfo.AlternateDisplayEnabled = false; } else { // We have alternate info to show BurnInfo.TimeUntil = customDescription; BurnInfo.AlternateDisplayEnabled = true; } } catch (Exception e) { Logging.Exception(e); BurnInfo.Duration = e.GetType().Name + ": " + e.Message + " -> " + e.StackTrace; } }