/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { Timing.TotalTime = gameTime.TotalGameTime.TotalSeconds; Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds; int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step); if (Timing.Accumulator > Timing.Step * 6.0) { //if the game's running too slowly then we have no choice //but to skip a bunch of steps //otherwise it snowballs and becomes unplayable Timing.Accumulator = Timing.Step; } PlayerInput.UpdateVariable(); bool paused = true; if (SoundManager != null) { if (WindowActive || !Config.MuteOnFocusLost) { SoundManager.ListenerGain = 1.0f; } else { SoundManager.ListenerGain = 0.0f; } } while (Timing.Accumulator >= Timing.Step) { Stopwatch sw = new Stopwatch(); sw.Start(); fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly; TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16); fixedTime.ElapsedGameTime = addTime; fixedTime.TotalGameTime.Add(addTime); base.Update(fixedTime); PlayerInput.Update(Timing.Step); if (loadingScreenOpen) { //reset accumulator if loading // -> less choppy loading screens because the screen is rendered after each update // -> no pause caused by leftover time in the accumulator when starting a new shift GameMain.ResetFrameTime(); if (TitleScreen.LoadState >= 100.0f && (!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked())) { loadingScreenOpen = false; } if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { string errMsg = "Loading was interrupted due to an error"; if (loadingCoroutine.Exception != null) { errMsg += ": " + loadingCoroutine.Exception.Message + "\n" + loadingCoroutine.Exception.StackTrace; } throw new Exception(errMsg); } } else if (hasLoaded) { SoundPlayer.Update((float)Timing.Step); if (PlayerInput.KeyHit(Keys.Escape)) { // Check if a text input is selected. if (GUI.KeyboardDispatcher.Subscriber != null) { if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox) { textBox.Deselect(); } GUI.KeyboardDispatcher.Subscriber = null; } //if a verification prompt (are you sure you want to x) is open, close it else if (GUIMessageBox.VisibleBox as GUIMessageBox != null && GUIMessageBox.VisibleBox.UserData as string == "verificationprompt") { ((GUIMessageBox)GUIMessageBox.VisibleBox).Close(); } else if (Tutorial.Initialized && Tutorial.ContentRunning) { (GameMain.GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI(); } else if ((Character.Controlled?.SelectedConstruction == null || !Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null)) && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null) { // Otherwise toggle pausing, unless another window/interface is open. GUI.TogglePauseMenu(); } } GUI.ClearUpdateList(); paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning) && (NetworkMember == null || !NetworkMember.GameStarted); Screen.Selected.AddToGUIUpdateList(); if (Client != null) { Client.AddToGUIUpdateList(); } DebugConsole.AddToGUIUpdateList(); DebugConsole.Update(this, (float)Timing.Step); paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted)); if (!paused) { Screen.Selected.Update(Timing.Step); } else if (Tutorial.Initialized && Tutorial.ContentRunning) { (GameSession.GameMode as TutorialMode).Update((float)Timing.Step); } if (NetworkMember != null) { NetworkMember.Update((float)Timing.Step); } GUI.Update((float)Timing.Step); } CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step); SteamManager.Update((float)Timing.Step); Timing.Accumulator -= Timing.Step; sw.Stop(); PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks); PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond); PerformanceCounter.UpdateIterationsGraph.Update(updateIterations); } if (!paused) { Timing.Alpha = Timing.Accumulator / Timing.Step; } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { Timing.TotalTime = gameTime.TotalGameTime.TotalSeconds; Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds; PlayerInput.UpdateVariable(); bool paused = true; while (Timing.Accumulator >= Timing.Step) { fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly; TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16); fixedTime.ElapsedGameTime = addTime; fixedTime.TotalGameTime.Add(addTime); base.Update(fixedTime); if (WindowActive) { PlayerInput.Update(Timing.Step); } if (loadingScreenOpen) { //reset accumulator if loading // -> less choppy loading screens because the screen is rendered after each update // -> no pause caused by leftover time in the accumulator when starting a new shift Timing.Accumulator = 0.0f; if (TitleScreen.LoadState >= 100.0f && (!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked())) { loadingScreenOpen = false; } if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { throw new Exception("Loading was interrupted due to an error"); } } else if (hasLoaded) { SoundPlayer.Update((float)Timing.Step); if (PlayerInput.KeyHit(Keys.Escape)) { GUI.TogglePauseMenu(); } GUIComponent.ClearUpdateList(); paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) && (NetworkMember == null || !NetworkMember.GameStarted); if (!paused) { Screen.Selected.AddToGUIUpdateList(); } if (NetworkMember != null) { NetworkMember.AddToGUIUpdateList(); } GUI.AddToGUIUpdateList(); DebugConsole.AddToGUIUpdateList(); GUIComponent.UpdateMouseOn(); DebugConsole.Update(this, (float)Timing.Step); paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted)); if (!paused) { Screen.Selected.Update(Timing.Step); } if (NetworkMember != null) { NetworkMember.Update((float)Timing.Step); } GUI.Update((float)Timing.Step); } CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step); Timing.Accumulator -= Timing.Step; } if (!paused) { Timing.Alpha = Timing.Accumulator / Timing.Step; } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { Timing.TotalTime = gameTime.TotalGameTime.TotalSeconds; Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds; int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step); if (Timing.Accumulator > Timing.Step * 6.0) { //if the game's running too slowly then we have no choice //but to skip a bunch of steps //otherwise it snowballs and becomes unplayable Timing.Accumulator = Timing.Step; } PlayerInput.UpdateVariable(); bool paused = true; while (Timing.Accumulator >= Timing.Step) { Stopwatch sw = new Stopwatch(); sw.Start(); fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly; TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16); fixedTime.ElapsedGameTime = addTime; fixedTime.TotalGameTime.Add(addTime); base.Update(fixedTime); PlayerInput.Update(Timing.Step); if (loadingScreenOpen) { //reset accumulator if loading // -> less choppy loading screens because the screen is rendered after each update // -> no pause caused by leftover time in the accumulator when starting a new shift Timing.Accumulator = 0.0f; if (TitleScreen.LoadState >= 100.0f && (!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked())) { loadingScreenOpen = false; } if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { string errMsg = "Loading was interrupted due to an error"; if (loadingCoroutine.Exception != null) { errMsg += ": " + loadingCoroutine.Exception.Message + "\n" + loadingCoroutine.Exception.StackTrace; } throw new Exception(errMsg); } } else if (hasLoaded) { SoundPlayer.Update((float)Timing.Step); if (PlayerInput.KeyHit(Keys.Escape)) { GUI.TogglePauseMenu(); } GUI.ClearUpdateList(); paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) && (NetworkMember == null || !NetworkMember.GameStarted); Screen.Selected.AddToGUIUpdateList(); if (NetworkMember != null) { NetworkMember.AddToGUIUpdateList(); } DebugConsole.AddToGUIUpdateList(); DebugConsole.Update(this, (float)Timing.Step); paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted)); if (!paused) { Screen.Selected.Update(Timing.Step); } if (NetworkMember != null) { NetworkMember.Update((float)Timing.Step); } GUI.Update((float)Timing.Step); } CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step); SteamManager.Update((float)Timing.Step); Timing.Accumulator -= Timing.Step; sw.Stop(); PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks); PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond); PerformanceCounter.UpdateIterationsGraph.Update(updateIterations); } if (!paused) { Timing.Alpha = Timing.Accumulator / Timing.Step; } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds; int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step); if (Timing.Accumulator > Timing.Step * 6.0) { //if the game's running too slowly then we have no choice //but to skip a bunch of steps //otherwise it snowballs and becomes unplayable Timing.Accumulator = Timing.Step; } CrossThread.ProcessTasks(); PlayerInput.UpdateVariable(); if (SoundManager != null) { if (WindowActive || !Config.MuteOnFocusLost) { SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain; } else { SoundManager.ListenerGain = 0.0f; } } while (Timing.Accumulator >= Timing.Step) { Timing.TotalTime += Timing.Step; Stopwatch sw = new Stopwatch(); sw.Start(); fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly; TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16); fixedTime.ElapsedGameTime = addTime; fixedTime.TotalGameTime.Add(addTime); base.Update(fixedTime); PlayerInput.Update(Timing.Step); if (loadingScreenOpen) { //reset accumulator if loading // -> less choppy loading screens because the screen is rendered after each update // -> no pause caused by leftover time in the accumulator when starting a new shift ResetFrameTime(); if (!TitleScreen.PlayingSplashScreen) { SoundPlayer.Update((float)Timing.Step); } if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.PrimaryMouseButtonClicked()) && WindowActive))) { loadingScreenOpen = false; } #if DEBUG if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled) && FirstLoad && !PlayerInput.KeyDown(Keys.LeftShift)) { loadingScreenOpen = false; FirstLoad = false; if (Config.AutomaticQuickStartEnabled) { MainMenuScreen.QuickStart(); } else if (Config.AutomaticCampaignLoadEnabled) { IEnumerable <string> saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer); if (saveFiles.Count() > 0) { saveFiles = saveFiles.OrderBy(file => File.GetLastWriteTime(file)); try { SaveUtil.LoadGame(saveFiles.Last()); } catch (Exception e) { DebugConsole.ThrowError("Loading save \"" + saveFiles.Last() + "\" failed", e); return; } } } } #endif if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { throw new LoadingException(loadingCoroutine.Exception); } } else if (hasLoaded) { if (ConnectLobby != 0) { if (Client != null) { Client.Disconnect(); Client = null; GameMain.MainMenuScreen.Select(); } Steam.SteamManager.JoinLobby(ConnectLobby, true); ConnectLobby = 0; ConnectEndpoint = null; ConnectName = null; } else if (!string.IsNullOrWhiteSpace(ConnectEndpoint)) { if (Client != null) { Client.Disconnect(); Client = null; GameMain.MainMenuScreen.Select(); } UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint); Client = new GameClient(Config.PlayerName, serverSteamId != 0 ? null : ConnectEndpoint, serverSteamId, string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName); ConnectLobby = 0; ConnectEndpoint = null; ConnectName = null; } SoundPlayer.Update((float)Timing.Step); if (PlayerInput.KeyHit(Keys.Escape) && WindowActive) { // Check if a text input is selected. if (GUI.KeyboardDispatcher.Subscriber != null) { if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox) { textBox.Deselect(); } GUI.KeyboardDispatcher.Subscriber = null; } //if a verification prompt (are you sure you want to x) is open, close it else if (GUIMessageBox.VisibleBox as GUIMessageBox != null && GUIMessageBox.VisibleBox.UserData as string == "verificationprompt") { ((GUIMessageBox)GUIMessageBox.VisibleBox).Close(); } else if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary && roundSummary.ContinueButton != null && roundSummary.ContinueButton.Visible) { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); } else if (Tutorial.Initialized && Tutorial.ContentRunning) { (GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI(); } else if (GameSession.IsTabMenuOpen) { gameSession.ToggleTabMenu(); } else if (GUI.PauseMenuOpen) { GUI.TogglePauseMenu(); } //open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC else if ((Character.Controlled == null || !itemHudActive()) //TODO: do we need to check Inventory.SelectedSlot? && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null && !CrewManager.IsCommandInterfaceOpen && !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null)) { // Otherwise toggle pausing, unless another window/interface is open. GUI.TogglePauseMenu(); }
public override void Draw(SpriteBatch spriteBatch) { if (overlayColor.A > 0) { if (overlaySprite != null) { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * (overlayColor.A / 255.0f), isFilled: true); float scale = Math.Max(GameMain.GraphicsWidth / overlaySprite.size.X, GameMain.GraphicsHeight / overlaySprite.size.Y); overlaySprite.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2, overlayColor, overlaySprite.size / 2, scale: scale); } else { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), overlayColor, isFilled: true); } if (!string.IsNullOrEmpty(overlayText) && overlayTextColor.A > 0) { var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite(); Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2; backgroundSprite.Draw(spriteBatch, centerPos, Color.White * (overlayTextColor.A / 255.0f), origin: backgroundSprite.size / 2, rotate: 0.0f, scale: new Vector2(1.5f, 0.7f) * (GameMain.GraphicsWidth / 3 / backgroundSprite.size.X)); string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font); Vector2 textSize = GUI.Font.MeasureString(wrappedText); Vector2 textPos = centerPos - textSize / 2; GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor); if (!string.IsNullOrEmpty(overlayTextBottom)) { Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y + 30 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2; GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor); } } } if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition")) { endRoundButton.Visible = false; if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; } return; } if (Submarine.MainSub == null) { return; } endRoundButton.Visible = false; var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub); string buttonText = ""; switch (availableTransition) { case TransitionType.ProgressToNextLocation: case TransitionType.ProgressToNextEmptyLocation: if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub)) { buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.LeaveLocation: buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; break; case TransitionType.ReturnToPreviousLocation: case TransitionType.ReturnToPreviousEmptyLocation: if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub)) { buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.None: default: if (Level.Loaded.Type == LevelData.LevelType.Outpost && (Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags?.Contains("airlock") ?? false))) { buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } else { endRoundButton.Visible = false; } break; } if (ReadyCheckButton != null) { ReadyCheckButton.Visible = endRoundButton.Visible; } if (endRoundButton.Visible) { if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); } endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5); if (endRoundButton.Text != buttonText) { endRoundButton.ToolTip = buttonText; } if (Character.Controlled?.ViewTarget is Item item) { Turret turret = item.GetComponent <Turret>(); endRoundButton.RectTransform.ScreenSpaceOffset = turret == null ? Point.Zero : new Point(0, (int)(turret.UIElementHeight * 1.25f)); } else if (Character.Controlled?.CharacterHealth?.SuicideButton?.Visible ?? false) { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height); } else { endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero; } } endRoundButton.DrawManually(spriteBatch); if (this is MultiPlayerCampaign) { ReadyCheckButton?.DrawManually(spriteBatch); } }
public override void Draw(SpriteBatch spriteBatch) { if (overlayColor.A > 0) { if (overlaySprite != null) { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * (overlayColor.A / 255.0f), isFilled: true); float scale = Math.Max(GameMain.GraphicsWidth / overlaySprite.size.X, GameMain.GraphicsHeight / overlaySprite.size.Y); overlaySprite.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2, overlayColor, overlaySprite.size / 2, scale: scale); } else { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), overlayColor, isFilled: true); } if (!string.IsNullOrEmpty(overlayText) && overlayTextColor.A > 0) { var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite(); Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2; string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font); Vector2 textSize = GUI.Font.MeasureString(wrappedText); Vector2 textPos = centerPos - textSize / 2; backgroundSprite.Draw(spriteBatch, centerPos, Color.White * (overlayTextColor.A / 255.0f), origin: backgroundSprite.size / 2, rotate: 0.0f, scale: new Vector2(GameMain.GraphicsWidth / 2 / backgroundSprite.size.X, textSize.Y / backgroundSprite.size.Y * 1.5f)); GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor); if (!string.IsNullOrEmpty(overlayTextBottom)) { Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y / 2 + 40 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2; GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor); } } } if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition")) { endRoundButton.Visible = false; if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; } return; } if (Submarine.MainSub == null || Level.Loaded == null) { return; } endRoundButton.Visible = false; var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub); string buttonText = ""; switch (availableTransition) { case TransitionType.ProgressToNextLocation: case TransitionType.ProgressToNextEmptyLocation: if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub)) { string textTag = availableTransition == TransitionType.ProgressToNextLocation ? "EnterLocation" : "EnterEmptyLocation"; buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.LeaveLocation: buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; break; case TransitionType.ReturnToPreviousLocation: case TransitionType.ReturnToPreviousEmptyLocation: if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub)) { string textTag = availableTransition == TransitionType.ReturnToPreviousLocation ? "EnterLocation" : "EnterEmptyLocation"; buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.None: default: if (Level.Loaded.Type == LevelData.LevelType.Outpost && (Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags.Contains("airlock") ?? false))) { buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } else { endRoundButton.Visible = false; } break; } if (ReadyCheckButton != null) { ReadyCheckButton.Visible = endRoundButton.Visible; } if (endRoundButton.Visible) { if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); } else if (prevCampaignUIAutoOpenType != availableTransition && (availableTransition == TransitionType.ProgressToNextEmptyLocation || availableTransition == TransitionType.ReturnToPreviousEmptyLocation)) { HintManager.OnAvailableTransition(availableTransition); //opening the campaign map pauses the game and prevents HintManager from running -> update it manually to get the hint to show up immediately HintManager.Update(); Map.SelectLocation(-1); endRoundButton.OnClicked(EndRoundButton, null); prevCampaignUIAutoOpenType = availableTransition; } endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5); if (endRoundButton.Text != buttonText) { endRoundButton.ToolTip = buttonText; } if (Character.Controlled?.CharacterHealth?.SuicideButton?.Visible ?? false) { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height); } else if (GameMain.Client != null && GameMain.Client.IsFollowSubTickBoxVisible) { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, HUDLayoutSettings.Padding + GameMain.Client.FollowSubTickBox.Rect.Height); } else { endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero; } } endRoundButton.DrawManually(spriteBatch); if (this is MultiPlayerCampaign && ReadyCheckButton != null) { ReadyCheckButton.RectTransform.ScreenSpaceOffset = endRoundButton.RectTransform.ScreenSpaceOffset; ReadyCheckButton.DrawManually(spriteBatch); } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { Timing.TotalTime = gameTime.TotalGameTime.TotalSeconds; Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds; int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step); if (Timing.Accumulator > Timing.Step * 6.0) { //if the game's running too slowly then we have no choice //but to skip a bunch of steps //otherwise it snowballs and becomes unplayable Timing.Accumulator = Timing.Step; } CrossThread.ProcessTasks(); PlayerInput.UpdateVariable(); bool paused = true; if (SoundManager != null) { if (WindowActive || !Config.MuteOnFocusLost) { SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain; } else { SoundManager.ListenerGain = 0.0f; } } while (Timing.Accumulator >= Timing.Step) { Stopwatch sw = new Stopwatch(); sw.Start(); fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly; TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16); fixedTime.ElapsedGameTime = addTime; fixedTime.TotalGameTime.Add(addTime); base.Update(fixedTime); PlayerInput.Update(Timing.Step); if (loadingScreenOpen) { //reset accumulator if loading // -> less choppy loading screens because the screen is rendered after each update // -> no pause caused by leftover time in the accumulator when starting a new shift GameMain.ResetFrameTime(); if (!TitleScreen.PlayingSplashScreen) { SoundPlayer.Update((float)Timing.Step); } if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked()) && WindowActive))) { loadingScreenOpen = false; } if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { string errMsg = "Loading was interrupted due to an error"; if (loadingCoroutine.Exception != null) { errMsg += ": " + loadingCoroutine.Exception.Message + "\n" + loadingCoroutine.Exception.StackTrace; } throw new Exception(errMsg); } } else if (hasLoaded) { if (ConnectLobby != 0) { if (Client != null) { Client.Disconnect(); Client = null; GameMain.MainMenuScreen.Select(); } Steam.SteamManager.JoinLobby(ConnectLobby, true); ConnectLobby = 0; ConnectEndpoint = null; ConnectName = null; } else if (!string.IsNullOrWhiteSpace(ConnectEndpoint)) { if (Client != null) { Client.Disconnect(); Client = null; GameMain.MainMenuScreen.Select(); } UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint); Client = new GameClient(Config.PlayerName, serverSteamId != 0 ? null : ConnectEndpoint, serverSteamId, string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName); ConnectLobby = 0; ConnectEndpoint = null; ConnectName = null; } SoundPlayer.Update((float)Timing.Step); if (PlayerInput.KeyHit(Keys.Escape) && WindowActive) { // Check if a text input is selected. if (GUI.KeyboardDispatcher.Subscriber != null) { if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox) { textBox.Deselect(); } GUI.KeyboardDispatcher.Subscriber = null; } //if a verification prompt (are you sure you want to x) is open, close it else if (GUIMessageBox.VisibleBox as GUIMessageBox != null && GUIMessageBox.VisibleBox.UserData as string == "verificationprompt") { ((GUIMessageBox)GUIMessageBox.VisibleBox).Close(); } else if (Tutorial.Initialized && Tutorial.ContentRunning) { (GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI(); } else if (GUI.PauseMenuOpen) { GUI.TogglePauseMenu(); } //open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC else if (Character.Controlled == null || ((Character.Controlled.SelectedConstruction == null || !Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null)) //TODO: do we need to check Inventory.SelectedSlot? && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null)) { // Otherwise toggle pausing, unless another window/interface is open. GUI.TogglePauseMenu(); } } #if DEBUG if (GameMain.NetworkMember == null) { if (PlayerInput.KeyHit(Keys.P) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox)) { DebugConsole.Paused = !DebugConsole.Paused; } } #endif GUI.ClearUpdateList(); paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) && (NetworkMember == null || !NetworkMember.GameStarted); #if !DEBUG if (NetworkMember == null && !WindowActive && !paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost) { GUI.TogglePauseMenu(); paused = true; } #endif Screen.Selected.AddToGUIUpdateList(); if (Client != null) { Client.AddToGUIUpdateList(); } DebugConsole.AddToGUIUpdateList(); DebugConsole.Update((float)Timing.Step); paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted)); if (!paused) { Screen.Selected.Update(Timing.Step); } else if (Tutorial.Initialized && Tutorial.ContentRunning) { (GameSession.GameMode as TutorialMode).Update((float)Timing.Step); } else if (DebugConsole.Paused) { if (Screen.Selected.Cam == null) { DebugConsole.Paused = false; } else { Screen.Selected.Cam.MoveCamera((float)Timing.Step); } } if (NetworkMember != null) { NetworkMember.Update((float)Timing.Step); } GUI.Update((float)Timing.Step); } CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step); SteamManager.Update((float)Timing.Step); SoundManager?.Update(); Timing.Accumulator -= Timing.Step; sw.Stop(); PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks); PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond); PerformanceCounter.UpdateIterationsGraph.Update(updateIterations); } if (!paused) { Timing.Alpha = Timing.Accumulator / Timing.Step; } }
public override void Update(float deltaTime) { if (CoroutineManager.IsCoroutineRunning("LevelTransition") || Level.Loaded == null) { return; } if (ShowCampaignUI || ForceMapUI) { if (CampaignUI == null) { InitCampaignUI(); } Character.DisableControls = true; } base.Update(deltaTime); if (PlayerInput.SecondaryMouseButtonClicked() || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) { ShowCampaignUI = false; if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary && roundSummary.ContinueButton != null && roundSummary.ContinueButton.Visible) { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); } } if (!GUI.DisableHUD && !GUI.DisableUpperHUD) { endRoundButton.UpdateManually(deltaTime); if (CoroutineManager.IsCoroutineRunning("LevelTransition") || ForceMapUI) { return; } } if (Level.Loaded.Type == LevelData.LevelType.Outpost) { if (wasDocked) { var connectedSubs = Submarine.MainSub.GetConnectedSubs(); bool isDocked = Level.Loaded.StartOutpost != null && connectedSubs.Contains(Level.Loaded.StartOutpost); if (!isDocked) { //undocked from outpost, need to choose a destination ForceMapUI = true; if (CampaignUI == null) { InitCampaignUI(); } CampaignUI.SelectTab(InteractionType.Map); } } else { //wasn't initially docked (sub doesn't have a docking port?) // -> choose a destination when the sub is far enough from the start outpost if (!Submarine.MainSub.AtStartPosition) { ForceMapUI = true; if (CampaignUI == null) { InitCampaignUI(); } CampaignUI.SelectTab(InteractionType.Map); } } if (CampaignUI == null) { InitCampaignUI(); } } else { var transitionType = GetAvailableTransition(out _, out _); if (transitionType == TransitionType.None && CampaignUI?.SelectedTab == InteractionType.Map) { ShowCampaignUI = false; } } }
public void LoadNewLevel() { if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (CoroutineManager.IsCoroutineRunning("LevelTransition")) { DebugConsole.ThrowError("Level transition already running.\n" + Environment.StackTrace.CleanupStackTrace()); return; } BeforeLevelLoading?.Invoke(); BeforeLevelLoading = null; if (Level.Loaded == null || Submarine.MainSub == null) { LoadInitialLevel(); return; } var availableTransition = GetAvailableTransition(out LevelData nextLevel, out Submarine leavingSub); if (availableTransition == TransitionType.None) { DebugConsole.ThrowError("Failed to load a new campaign level. No available level transitions " + "(current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ")\n" + Environment.StackTrace.CleanupStackTrace()); return; } if (nextLevel == null) { DebugConsole.ThrowError("Failed to load a new campaign level. No available level transitions " + "(transition type: " + availableTransition + ", " + "current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ")\n" + Environment.StackTrace.CleanupStackTrace()); return; } #if CLIENT ShowCampaignUI = ForceMapUI = false; #endif DebugConsole.NewMessage("Transitioning to " + (nextLevel?.Seed ?? "null") + " (current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ", " + "transition type: " + availableTransition + ")"); IsFirstRound = false; bool mirror = map.SelectedConnection != null && map.CurrentLocation != map.SelectedConnection.Locations[0]; CoroutineManager.StartCoroutine(DoLevelTransition(availableTransition, nextLevel, leavingSub, mirror), "LevelTransition"); }
public override void Update(float deltaTime) { if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; } base.Update(deltaTime); if (PlayerInput.RightButtonClicked() || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) { ShowCampaignUI = false; if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary && roundSummary.ContinueButton != null && roundSummary.ContinueButton.Visible) { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); } } #if DEBUG if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.R)) { if (GUIMessageBox.MessageBoxes.Any()) { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.MessageBoxes.Last()); } GUIFrame summaryFrame = GameMain.GameSession.RoundSummary.CreateSummaryFrame(GameMain.GameSession, "", null); GUIMessageBox.MessageBoxes.Add(summaryFrame); GameMain.GameSession.RoundSummary.ContinueButton.OnClicked = (_, __) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return(true); }; } #endif if (ShowCampaignUI || ForceMapUI) { Character.DisableControls = true; } if (!GUI.DisableHUD && !GUI.DisableUpperHUD) { endRoundButton.UpdateManually(deltaTime); if (CoroutineManager.IsCoroutineRunning("LevelTransition") || ForceMapUI) { return; } } if (Level.Loaded.Type == LevelData.LevelType.Outpost) { KeepCharactersCloseToOutpost(deltaTime); if (wasDocked) { var connectedSubs = Submarine.MainSub.GetConnectedSubs(); bool isDocked = Level.Loaded.StartOutpost != null && connectedSubs.Contains(Level.Loaded.StartOutpost); if (!isDocked) { //undocked from outpost, need to choose a destination ForceMapUI = true; CampaignUI.SelectTab(InteractionType.Map); } } else { //wasn't initially docked (sub doesn't have a docking port?) // -> choose a destination when the sub is far enough from the start outpost if (!Submarine.MainSub.AtStartPosition) { ForceMapUI = true; CampaignUI.SelectTab(InteractionType.Map); } } } else { var transitionType = GetAvailableTransition(out _, out Submarine leavingSub); if (transitionType == TransitionType.End) { EndCampaign(); } if (transitionType == TransitionType.ProgressToNextLocation && Level.Loaded.EndOutpost != null && Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub)) { LoadNewLevel(); } else if (transitionType == TransitionType.ReturnToPreviousLocation && Level.Loaded.StartOutpost != null && Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub)) { LoadNewLevel(); } else if (transitionType == TransitionType.None && CampaignUI.SelectedTab == InteractionType.Map) { ShowCampaignUI = false; } } if (!crewDead) { if (!CrewManager.GetCharacters().Any(c => !c.IsDead)) { crewDead = true; } } else { endTimer -= deltaTime; if (endTimer <= 0.0f) { GameOver(); } } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { Timing.TotalTime = gameTime.TotalGameTime.TotalSeconds; Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds; PlayerInput.UpdateVariable(); bool paused = true; if (GameMain.NilMod.UseExperimentalFPSLagPrevention && !loadingScreenOpen) { if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 2) { Timing.Step = 1.0 / 8.0; FarseerPhysics.Settings.VelocityIterations = 10; FarseerPhysics.Settings.PositionIterations = 4; FarseerPhysics.Settings.TOIPositionIterations = 25; FarseerPhysics.Settings.TOIVelocityIterations = 10; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 4) { Timing.Step = 1.0 / 10.0; FarseerPhysics.Settings.VelocityIterations = 10; FarseerPhysics.Settings.PositionIterations = 4; FarseerPhysics.Settings.TOIPositionIterations = 25; FarseerPhysics.Settings.TOIVelocityIterations = 10; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 6) { Timing.Step = 1.0 / 12.0; FarseerPhysics.Settings.VelocityIterations = 10; FarseerPhysics.Settings.PositionIterations = 4; FarseerPhysics.Settings.TOIPositionIterations = 25; FarseerPhysics.Settings.TOIVelocityIterations = 10; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 8) { Timing.Step = 1.0 / 15.0; FarseerPhysics.Settings.VelocityIterations = 9; FarseerPhysics.Settings.PositionIterations = 4; FarseerPhysics.Settings.TOIPositionIterations = 22; FarseerPhysics.Settings.TOIVelocityIterations = 9; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 10) { Timing.Step = 1.0 / 20.0; FarseerPhysics.Settings.VelocityIterations = 9; FarseerPhysics.Settings.PositionIterations = 4; FarseerPhysics.Settings.TOIPositionIterations = 22; FarseerPhysics.Settings.TOIVelocityIterations = 9; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 12) { Timing.Step = 1.0 / 25.0; FarseerPhysics.Settings.VelocityIterations = 9; FarseerPhysics.Settings.PositionIterations = 4; FarseerPhysics.Settings.TOIPositionIterations = 22; FarseerPhysics.Settings.TOIVelocityIterations = 9; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 14) { Timing.Step = 1.0 / 30.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 16) { Timing.Step = 1.0 / 35.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 18) { Timing.Step = 1.0 / 40.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 20) { Timing.Step = 1.0 / 45.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 22) { Timing.Step = 1.0 / 50.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 25) { Timing.Step = 1.0 / 55.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } else { Timing.Step = 1.0 / 60.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } } else { Timing.Step = 1.0 / 60.0; FarseerPhysics.Settings.VelocityIterations = 8; FarseerPhysics.Settings.PositionIterations = 3; FarseerPhysics.Settings.TOIPositionIterations = 20; FarseerPhysics.Settings.TOIVelocityIterations = 8; } while (Timing.Accumulator >= Timing.Step) { NilModProfiler.SWMainUpdateLoop.Start(); fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly; TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16); if (GameMain.NilMod.UseExperimentalFPSLagPrevention) { if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 2) { addTime = new TimeSpan(0, 0, 0, 0, 125); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 4) { addTime = new TimeSpan(0, 0, 0, 0, 100); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 6) { addTime = new TimeSpan(0, 0, 0, 0, 83); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 8) { addTime = new TimeSpan(0, 0, 0, 0, 66); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 10) { addTime = new TimeSpan(0, 0, 0, 0, 50); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 12) { addTime = new TimeSpan(0, 0, 0, 0, 40); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 14) { addTime = new TimeSpan(0, 0, 0, 0, 33); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 16) { addTime = new TimeSpan(0, 0, 0, 0, 28); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 18) { addTime = new TimeSpan(0, 0, 0, 0, 25); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 20) { addTime = new TimeSpan(0, 0, 0, 0, 22); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 22) { addTime = new TimeSpan(0, 0, 0, 0, 20); } else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 25) { addTime = new TimeSpan(0, 0, 0, 0, 18); } else { addTime = new TimeSpan(0, 0, 0, 0, 16); } } fixedTime.ElapsedGameTime = addTime; fixedTime.TotalGameTime.Add(addTime); base.Update(fixedTime); NilModProfiler.SWPlayerInput.Start(); if (WindowActive) { PlayerInput.Update(Timing.Step); } NilModProfiler.RecordPlayerInput(); if (loadingScreenOpen) { //reset accumulator if loading // -> less choppy loading screens because the screen is rendered after each update // -> no pause caused by leftover time in the accumulator when starting a new shift if (TitleScreen.LoadState >= 100f) { Timing.Accumulator = 0.0f; this.TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 12); } else { Timing.Accumulator = Timing.Step * 1.99; this.TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 1); } if (TitleScreen.LoadState >= 100.0f && (!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked())) { loadingScreenOpen = false; } if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { throw new Exception("Loading was interrupted due to an error"); } } else if (hasLoaded) { NilMod.Update((float)Timing.Step); NilModProfiler.SWSoundPlayer.Start(); SoundPlayer.Update((float)Timing.Step); NilModProfiler.RecordSoundPlayer(); if (PlayerInput.KeyHit(Keys.Escape)) { GUI.TogglePauseMenu(); } GUIComponent.ClearUpdateList(); paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) && (NetworkMember == null || !NetworkMember.GameStarted); if (!paused) { Screen.Selected.AddToGUIUpdateList(); } if (NetworkMember != null) { NetworkMember.AddToGUIUpdateList(); } GUI.AddToGUIUpdateList(); DebugConsole.AddToGUIUpdateList(); GUIComponent.UpdateMouseOn(); NilModProfiler.SWDebugConsole.Start(); DebugConsole.Update(this, (float)Timing.Step); paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted)); NilModProfiler.RecordDebugConsole(); if (!paused) { NilModProfiler.SWGameScreen.Start(); Screen.Selected.Update(Timing.Step); NilModProfiler.RecordGameScreen(); } if (NetworkMember != null) { NilModProfiler.SWNetworkMember.Start(); NetworkMember.Update((float)Timing.Step); NilModProfiler.RecordNetworkMember(); } NilModProfiler.SWGUIUpdate.Start(); GUI.Update((float)Timing.Step); NilModProfiler.RecordGUIUpdate(); } NilModProfiler.SWCoroutineManager.Start(); CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step); NilModProfiler.RecordCoroutineManager(); Timing.Accumulator -= Timing.Step; if (NilModProfiler.SWMainUpdateLoop.ElapsedTicks > 0) { NilModProfiler.RecordMainLoopUpdate(); } } GameMain.NilModProfiler.Update((float)Timing.Step); if (!paused) { Timing.Alpha = Timing.Accumulator / Timing.Step; } }