Exemplo n.º 1
0
        public void EndRound(string endMessage)
        {
            if (Mission != null)
            {
                Mission.End();
            }
            GameAnalyticsManager.AddProgressionEvent(
                (Mission == null || Mission.Completed)  ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
                GameMode.Preset.Identifier,
                (Mission == null ? "None" : Mission.GetType().ToString()));

#if CLIENT
            if (RoundSummary != null)
            {
                GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(endMessage);
                GUIMessageBox.MessageBoxes.Add(summaryFrame);
                var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), summaryFrame.Children.First().Children.First().FindChild("buttonarea").RectTransform),
                                             TextManager.Get("OK"))
                {
                    OnClicked = (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return(true); }
                };
            }

            TabMenu.OnRoundEnded();
#endif

            EventManager?.EndRound();
            SteamAchievementManager.OnRoundEnded(this);

            Mission = null;

            StatusEffect.StopAll();
        }
Exemplo n.º 2
0
        public Task SelectSummaryScreen(RoundSummary roundSummary, LevelData newLevel, bool mirror, Action action)
        {
            var roundSummaryScreen = RoundSummaryScreen.Select(overlaySprite, roundSummary);

            GUI.ClearCursorWait();

            var loadTask = Task.Run(async() =>
            {
                await Task.Yield();
                Rand.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
                try
                {
                    GameMain.GameSession.StartRound(newLevel, mirrorLevel: mirror);
                }
                catch (Exception e)
                {
                    roundSummaryScreen.LoadException = e;
                }
                Rand.ThreadId = 0;
            });

            TaskPool.Add("AsyncCampaignStartRound", loadTask, (t) =>
            {
                overlayColor = Color.Transparent;
                action?.Invoke();
            });

            return(loadTask);
        }
Exemplo n.º 3
0
        public static RoundSummaryScreen Select(Sprite backgroundSprite, RoundSummary roundSummary)
        {
            var summaryScreen = new RoundSummaryScreen()
            {
                roundSummary         = roundSummary,
                backgroundSprite     = backgroundSprite,
                prevGuiElementParent = roundSummary.Frame.RectTransform.Parent,
                loadText             = TextManager.Get("campaignstartingpleasewait")
            };

            roundSummary.Frame.RectTransform.Parent = summaryScreen.Frame.RectTransform;
            summaryScreen.Select();
            summaryScreen.AddToGUIUpdateList();
            return(summaryScreen);
        }
        public void EndRound(string endMessage, List <TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
        {
            if (Mission != null)
            {
                Mission.End();
            }
            GameAnalyticsManager.AddProgressionEvent(
                (Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
                GameMode.Preset.Identifier,
                Mission == null ? "None" : Mission.GetType().ToString());

#if CLIENT
            if (GUI.PauseMenuOpen)
            {
                GUI.TogglePauseMenu();
            }
            GUI.PreventPauseMenuToggle = true;

            if (!(GameMode is TestGameMode) && Screen.Selected == GameMain.GameScreen && RoundSummary != null)
            {
                GUI.ClearMessages();
                GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData is RoundSummary);
                GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(this, endMessage, traitorResults, transitionType);
                GUIMessageBox.MessageBoxes.Add(summaryFrame);
                RoundSummary.ContinueButton.OnClicked = (_, __) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return(true); };
            }

            if (GameMain.NetLobbyScreen != null)
            {
                GameMain.NetLobbyScreen.OnRoundEnded();
            }
            TabMenu.OnRoundEnded();
            GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "ConversationAction" || ReadyCheck.IsReadyCheck(mb));
#endif
            SteamAchievementManager.OnRoundEnded(this);

            GameMode?.End(transitionType);
            EventManager?.EndRound();
            StatusEffect.StopAll();
            Mission   = null;
            IsRunning = false;
        }
Exemplo n.º 5
0
        public void EndRound(string endMessage, List <TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
        {
            foreach (Mission mission in missions)
            {
                mission.End();
            }
#if CLIENT
            if (GUI.PauseMenuOpen)
            {
                GUI.TogglePauseMenu();
            }
            GUI.PreventPauseMenuToggle = true;

            if (!(GameMode is TestGameMode) && Screen.Selected == GameMain.GameScreen && RoundSummary != null)
            {
                GUI.ClearMessages();
                GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData is RoundSummary);
                GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(this, endMessage, traitorResults, transitionType);
                GUIMessageBox.MessageBoxes.Add(summaryFrame);
                RoundSummary.ContinueButton.OnClicked = (_, __) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return(true); };
            }

            if (GameMain.NetLobbyScreen != null)
            {
                GameMain.NetLobbyScreen.OnRoundEnded();
            }
            TabMenu.OnRoundEnded();
            GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "ConversationAction" || ReadyCheck.IsReadyCheck(mb));
#endif
            SteamAchievementManager.OnRoundEnded(this);

            GameMode?.End(transitionType);
            EventManager?.EndRound();
            StatusEffect.StopAll();
            missions.Clear();
            IsRunning = false;

#if CLIENT
            HintManager.OnRoundEnded();
#endif
        }
Exemplo n.º 6
0
        public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false)
        {
#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
#endif

            this.level = level;

            if (submarine == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected");
                return;
            }

            if (reloadSub || Submarine.MainSub != submarine)
            {
                submarine.Load(true);
            }
            Submarine.MainSub = submarine;
            if (loadSecondSub)
            {
                if (Submarine.MainSubs[1] == null)
                {
                    Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
                    Submarine.MainSubs[1].Load(false);
                }
                else if (reloadSub)
                {
                    Submarine.MainSubs[1].Load(false);
                }
            }

            if (level != null)
            {
                level.Generate();

                submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                currentMission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                Mission.Start(Level.Loaded);
            }

            EventManager.StartRound(level);

            if (GameMode != null)
            {
                GameMode.MsgBox();
            }

#if CLIENT
            roundSummary = new RoundSummary(this);

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
            SoundPlayer.SwitchMusic();
#endif
        }
        protected override IEnumerable <object> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List <TraitorMissionResult> traitorResults = null)
        {
            NextLevel = newLevel;
            bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);

            SoundPlayer.OverrideMusicType     = success ? "endround" : "crewdead";
            SoundPlayer.OverrideMusicDuration = 18.0f;
            crewDead = false;

            GameMain.GameSession.EndRound("", traitorResults, transitionType);
            var          continueButton = GameMain.GameSession.RoundSummary?.ContinueButton;
            RoundSummary roundSummary   = null;

            if (GUIMessageBox.VisibleBox?.UserData is RoundSummary)
            {
                roundSummary = GUIMessageBox.VisibleBox?.UserData as RoundSummary;
            }
            if (continueButton != null)
            {
                continueButton.Visible = false;
            }

            lastControlledCharacter = Character.Controlled;
            Character.Controlled    = null;

            switch (transitionType)
            {
            case TransitionType.None:
                throw new InvalidOperationException("Level transition failed (no transitions available).");

            case TransitionType.ReturnToPreviousLocation:
                //deselect destination on map
                map.SelectLocation(-1);
                break;

            case TransitionType.ProgressToNextLocation:
                Map.MoveToNextLocation();
                break;
            }

            Map.ProgressWorld(transitionType, (float)(Timing.TotalTime - GameMain.GameSession.RoundStartTime));

            var endTransition = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, null,
                                                     transitionType == TransitionType.LeaveLocation ? Alignment.BottomCenter : Alignment.Center,
                                                     fadeOut: false,
                                                     duration: EndTransitionDuration);

            GUI.ClearMessages();

            Location portraitLocation = Map.SelectedLocation ?? Map.CurrentLocation;

            overlaySprite = portraitLocation.Type.GetPortrait(portraitLocation.PortraitId);
            float fadeOutDuration = endTransition.Duration;
            float t = 0.0f;

            while (t < fadeOutDuration || endTransition.Running)
            {
                t           += CoroutineManager.UnscaledDeltaTime;
                overlayColor = Color.Lerp(Color.Transparent, Color.White, t / fadeOutDuration);
                yield return(CoroutineStatus.Running);
            }
            overlayColor = Color.White;
            yield return(CoroutineStatus.Running);

            //--------------------------------------

            bool save = false;

            if (success)
            {
                if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
                {
                    Submarine.MainSub = leavingSub;
                    GameMain.GameSession.Submarine = leavingSub;
                    var subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
                    foreach (Submarine sub in subsToLeaveBehind)
                    {
                        MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
                        LinkedSubmarine.CreateDummy(leavingSub, sub);
                    }
                }

                GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);

                if (PendingSubmarineSwitch != null)
                {
                    SubmarineInfo previousSub = GameMain.GameSession.SubmarineInfo;
                    GameMain.GameSession.SubmarineInfo = PendingSubmarineSwitch;
                    PendingSubmarineSwitch             = null;

                    for (int i = 0; i < GameMain.GameSession.OwnedSubmarines.Count; i++)
                    {
                        if (GameMain.GameSession.OwnedSubmarines[i].Name == previousSub.Name)
                        {
                            GameMain.GameSession.OwnedSubmarines[i] = previousSub;
                            break;
                        }
                    }
                }

                SaveUtil.SaveGame(GameMain.GameSession.SavePath);
            }
            else
            {
                PendingSubmarineSwitch = null;
                EnableRoundSummaryGameOverState();
            }

            //--------------------------------------

            SelectSummaryScreen(roundSummary, newLevel, mirror, () =>
            {
                GameMain.GameScreen.Select();
                if (continueButton != null)
                {
                    continueButton.Visible = true;
                }

                GUI.DisableHUD = false;
                GUI.ClearCursorWait();
                overlayColor = Color.Transparent;
            });

            yield return(CoroutineStatus.Success);
        }
Exemplo n.º 8
0
        public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false, bool mirrorLevel = false)
        {
#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.Client == null || GameMain.Client.CharacterInfo != null;
            if (GameMain.Client == null)
            {
                GameMain.LightManager.LosMode = GameMain.Config.LosMode;
            }
#endif
            this.Level = level;

            if (Submarine == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected");
                return;
            }

            if (reloadSub || Submarine.MainSub != Submarine)
            {
                Submarine.Load(true);
            }
            Submarine.MainSub = Submarine;
            if (loadSecondSub)
            {
                if (Submarine.MainSubs[1] == null)
                {
                    Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
                    Submarine.MainSubs[1].Load(false);
                }
                else if (reloadSub)
                {
                    Submarine.MainSubs[1].Load(false);
                }
            }

            if (level != null)
            {
                level.Generate(mirrorLevel);
                if (level.StartOutpost != null)
                {
                    //start by placing the sub below the outpost
                    Rectangle outpostBorders = Level.Loaded.StartOutpost.GetDockedBorders();
                    Rectangle subBorders     = Submarine.GetDockedBorders();

                    Vector2 startOutpostSize = Vector2.Zero;
                    if (Level.Loaded.StartOutpost != null)
                    {
                        startOutpostSize = Level.Loaded.StartOutpost.Borders.Size.ToVector2();
                    }
                    Submarine.SetPosition(
                        Level.Loaded.StartOutpost.WorldPosition -
                        new Vector2(0.0f, outpostBorders.Height / 2 + subBorders.Height / 2));

                    //find the port that's the nearest to the outpost and dock if one is found
                    float       closestDistance = 0.0f;
                    DockingPort myPort = null, outPostPort = null;
                    foreach (DockingPort port in DockingPort.List)
                    {
                        if (port.IsHorizontal || port.Docked)
                        {
                            continue;
                        }
                        if (port.Item.Submarine == level.StartOutpost)
                        {
                            outPostPort = port;
                            continue;
                        }
                        if (port.Item.Submarine != Submarine)
                        {
                            continue;
                        }

                        //the submarine port has to be at the top of the sub
                        if (port.Item.WorldPosition.Y < Submarine.WorldPosition.Y)
                        {
                            continue;
                        }

                        float dist = Vector2.DistanceSquared(port.Item.WorldPosition, level.StartOutpost.WorldPosition);
                        if (myPort == null || dist < closestDistance)
                        {
                            myPort          = port;
                            closestDistance = dist;
                        }
                    }

                    if (myPort != null && outPostPort != null)
                    {
                        Vector2 portDiff = myPort.Item.WorldPosition - Submarine.WorldPosition;
                        Submarine.SetPosition((outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance);
                        myPort.Dock(outPostPort);
                        myPort.Lock(true);
                    }
                }
                else
                {
                    Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition));
                }
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                Mission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                Mission.Start(Level.Loaded);
            }

            EventManager.StartRound(level);
            SteamAchievementManager.OnStartRound();

            if (GameMode != null)
            {
                GameMode.MsgBox();

                if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
                {
                    mpCampaign.CargoManager.CreateItems();
                }
            }

            GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));


#if CLIENT
            if (GameMode is SinglePlayerCampaign)
            {
                SteamAchievementManager.OnBiomeDiscovered(level.Biome);
            }
            roundSummary = new RoundSummary(this);

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);

            if (!(GameMode is TutorialMode))
            {
                GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
                GUI.AddMessage(level.Biome.Name, Color.Lerp(Color.CadetBlue, Color.DarkRed, level.Difficulty / 100.0f), 5.0f, playSound: false);
                GUI.AddMessage(TextManager.Get("Destination") + ": " + EndLocation.Name, Color.CadetBlue, playSound: false);
                GUI.AddMessage(TextManager.Get("Mission") + ": " + (Mission == null ? TextManager.Get("None") : Mission.Name), Color.CadetBlue, playSound: false);
            }
#endif

            RoundStartTime = Timing.TotalTime;
            GameMain.ResetFrameTime();
        }
Exemplo n.º 9
0
        public void StartRound(LevelData levelData, bool mirrorLevel = false, SubmarineInfo startOutpost = null, SubmarineInfo endOutpost = null)
        {
            MirrorLevel = mirrorLevel;
            if (SubmarineInfo == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
                return;
            }
            if (SubmarineInfo.IsFileCorrupted)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine file corrupted.");
                return;
            }
            if (SubmarineInfo.SubmarineElement.Elements().Count() == 0)
            {
                DebugConsole.ThrowError("Couldn't start game session, saved submarine is empty. The submarine file may be corrupted.");
                return;
            }

            LevelData = levelData;

            Submarine.Unload();
            Submarine = Submarine.MainSub = new Submarine(SubmarineInfo);
            foreach (Submarine sub in Submarine.GetConnectedSubs())
            {
                sub.TeamID = CharacterTeamType.Team1;
                foreach (Item item in Item.ItemList)
                {
                    if (item.Submarine != sub)
                    {
                        continue;
                    }
                    foreach (WifiComponent wifiComponent in item.GetComponents <WifiComponent>())
                    {
                        wifiComponent.TeamID = sub.TeamID;
                    }
                }
            }

            foreach (Mission mission in GameMode.Missions)
            {
                // setting level for missions that may involve difficulty-related submarine creation
                mission.SetLevel(levelData);
            }

            if (Submarine.MainSubs[1] == null)
            {
                var enemySubmarineInfo = GameMode is PvPMode ? SubmarineInfo : GameMode.Missions.FirstOrDefault(m => m.EnemySubmarineInfo != null)?.EnemySubmarineInfo;
                if (enemySubmarineInfo != null)
                {
                    Submarine.MainSubs[1] = new Submarine(enemySubmarineInfo, true);
                }
            }

            if (GameMain.NetworkMember?.ServerSettings?.LockAllDefaultWires ?? false)
            {
                foreach (Item item in Item.ItemList)
                {
                    if (item.Submarine == Submarine.MainSubs[0] ||
                        (Submarine.MainSubs[1] != null && item.Submarine == Submarine.MainSubs[1]))
                    {
                        Wire wire = item.GetComponent <Wire>();
                        if (wire != null && !wire.NoAutoLock && wire.Connections.Any(c => c != null))
                        {
                            wire.Locked = true;
                        }
                    }
                }
            }

            Level level = null;

            if (levelData != null)
            {
                level = Level.Generate(levelData, mirrorLevel, startOutpost, endOutpost);
            }

            InitializeLevel(level);

#if CLIENT
            if (GameMode is CampaignMode)
            {
                SteamAchievementManager.OnBiomeDiscovered(levelData.Biome);
            }

            var existingRoundSummary = GUIMessageBox.MessageBoxes.Find(mb => mb.UserData is RoundSummary)?.UserData as RoundSummary;
            if (existingRoundSummary?.ContinueButton != null)
            {
                existingRoundSummary.ContinueButton.Visible = true;
            }

            RoundSummary = new RoundSummary(Submarine.Info, GameMode, Missions, StartLocation, EndLocation);

            if (!(GameMode is TutorialMode) && !(GameMode is TestGameMode))
            {
                GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
                if (EndLocation != null)
                {
                    GUI.AddMessage(levelData.Biome.DisplayName, Color.Lerp(Color.CadetBlue, Color.DarkRed, levelData.Difficulty / 100.0f), 5.0f, playSound: false);
                    GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Destination"), EndLocation.Name), Color.CadetBlue, playSound: false);
                    if (missions.Count > 1)
                    {
                        string joinedMissionNames = string.Join(", ", missions.Select(m => m.Name));
                        GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Mission"), joinedMissionNames), Color.CadetBlue, playSound: false);
                    }
                    else
                    {
                        var mission = missions.FirstOrDefault();
                        GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Mission"), mission?.Name ?? TextManager.Get("None")), Color.CadetBlue, playSound: false);
                    }
                }
                else
                {
                    GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Location"), StartLocation.Name), Color.CadetBlue, playSound: false);
                }
            }

            GUI.PreventPauseMenuToggle = false;

            HintManager.OnRoundStarted();
#endif
        }
Exemplo n.º 10
0
        public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
        {
            Rectangle rect = mapContainer.Rect;

            Vector2 viewSize   = new Vector2(rect.Width / zoom, rect.Height / zoom);
            Vector2 edgeBuffer = rect.Size.ToVector2() / 2;

            DrawOffset.X = MathHelper.Clamp(DrawOffset.X, -Width - edgeBuffer.X + viewSize.X / 2.0f, edgeBuffer.X - viewSize.X / 2.0f);
            DrawOffset.Y = MathHelper.Clamp(DrawOffset.Y, -Height - edgeBuffer.Y + viewSize.Y / 2.0f, edgeBuffer.Y - viewSize.Y / 2.0f);

            drawOffsetNoise = new Vector2(
                (float)PerlinNoise.CalculatePerlin(Timing.TotalTime * 0.1f % 255, Timing.TotalTime * 0.1f % 255, 0) - 0.5f,
                (float)PerlinNoise.CalculatePerlin(Timing.TotalTime * 0.2f % 255, Timing.TotalTime * 0.2f % 255, 0.5f) - 0.5f) * 10.0f;

            Vector2 viewOffset = DrawOffset + drawOffsetNoise;

            Vector2 rectCenter = new Vector2(rect.Center.X, rect.Center.Y);

            Rectangle prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;

            spriteBatch.End();
            spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, rect);
            spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);

            Vector2 topLeft     = rectCenter + viewOffset;
            Vector2 bottomRight = rectCenter + (viewOffset + new Vector2(Width, Height));
            Vector2 mapTileSize = mapTiles[0, 0].size * generationParams.MapTileScale;

            int startX = (int)Math.Floor(-topLeft.X / mapTileSize.X) - 1;
            int startY = (int)Math.Floor(-topLeft.Y / mapTileSize.Y) - 1;
            int endX   = (int)Math.Ceiling((-topLeft.X + rect.Width) / mapTileSize.X);
            int endY   = (int)Math.Ceiling((-topLeft.Y + rect.Height) / mapTileSize.Y);

            float noiseT = (float)(Timing.TotalTime * 0.01f);

            cameraNoiseStrength = (float)PerlinNoise.CalculatePerlin(noiseT, noiseT * 0.5f, noiseT * 0.2f);
            float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 5.0f;

            for (int x = startX; x <= endX; x++)
            {
                for (int y = startY; y <= endY; y++)
                {
                    int     tileX   = Math.Abs(x) % mapTiles.GetLength(0);
                    int     tileY   = Math.Abs(y) % mapTiles.GetLength(1);
                    Vector2 tilePos = rectCenter + (viewOffset + new Vector2(x, y) * mapTileSize) * zoom;
                    mapTiles[tileX, tileY].Draw(spriteBatch, tilePos, Color.White, origin: Vector2.Zero, scale: generationParams.MapTileScale * zoom);

                    if (GameMain.DebugDraw)
                    {
                        continue;
                    }
                    if (!tileDiscovered[tileX, tileY] || x < 0 || y < 0 || x >= tileDiscovered.GetLength(0) || y >= tileDiscovered.GetLength(1))
                    {
                        generationParams.FogOfWarSprite?.Draw(spriteBatch, tilePos, Color.White * cameraNoiseStrength, origin: Vector2.Zero, scale: generationParams.MapTileScale * zoom);
                        noiseOverlay.DrawTiled(spriteBatch, tilePos, mapTileSize * zoom,
                                               startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                               color: Color.White * cameraNoiseStrength * 0.2f,
                                               textureScale: Vector2.One * noiseScale);
                    }
                }
            }

            if (GameMain.DebugDraw)
            {
                if (topLeft.X > rect.X)
                {
                    GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, (int)(topLeft.X - rect.X), rect.Height), Color.Black * 0.5f, true);
                }
                if (topLeft.Y > rect.Y)
                {
                    GUI.DrawRectangle(spriteBatch, new Rectangle((int)topLeft.X, rect.Y, (int)(bottomRight.X - topLeft.X), (int)(topLeft.Y - rect.Y)), Color.Black * 0.5f, true);
                }
                if (bottomRight.X < rect.Right)
                {
                    GUI.DrawRectangle(spriteBatch, new Rectangle((int)bottomRight.X, rect.Y, (int)(rect.Right - bottomRight.X), rect.Height), Color.Black * 0.5f, true);
                }
                if (bottomRight.Y < rect.Bottom)
                {
                    GUI.DrawRectangle(spriteBatch, new Rectangle((int)topLeft.X, (int)bottomRight.Y, (int)(bottomRight.X - topLeft.X), (int)(rect.Bottom - bottomRight.Y)), Color.Black * 0.5f, true);
                }
            }

            float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));

            cameraNoiseStrength = PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));

            noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
                                   startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                   color: Color.White * cameraNoiseStrength * 0.1f,
                                   textureScale: Vector2.One * rawNoiseScale);

            noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
                                   startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                   color: new Color(20, 20, 20, 50),
                                   textureScale: Vector2.One * rawNoiseScale * 2);

            noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
                                   startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                   color: Color.White * cameraNoiseStrength * 0.1f,
                                   textureScale: Vector2.One * noiseScale);

            Pair <Rectangle, string> tooltip = null;

            if (generationParams.ShowLocations)
            {
                foreach (LocationConnection connection in Connections)
                {
                    if (IsInFogOfWar(connection.Locations[0]) && IsInFogOfWar(connection.Locations[1]))
                    {
                        continue;
                    }
                    DrawConnection(spriteBatch, connection, rect, viewOffset);
                }

                for (int i = 0; i < Locations.Count; i++)
                {
                    Location location = Locations[i];
                    if (IsInFogOfWar(location))
                    {
                        continue;
                    }
                    Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;

                    Rectangle drawRect = location.Type.Sprite.SourceRect;
                    drawRect.X = (int)pos.X - drawRect.Width / 2;
                    drawRect.Y = (int)pos.Y - drawRect.Width / 2;

                    if (!rect.Intersects(drawRect))
                    {
                        continue;
                    }

                    if (location == CurrentDisplayLocation)
                    {
                        generationParams.CurrentLocationIndicator.Draw(spriteBatch,
                                                                       rectCenter + (currLocationIndicatorPos + viewOffset) * zoom,
                                                                       generationParams.IndicatorColor,
                                                                       generationParams.CurrentLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.CurrentLocationIndicator.size.X) * 1.7f * zoom);
                    }

                    if (location == SelectedLocation)
                    {
                        generationParams.SelectedLocationIndicator.Draw(spriteBatch,
                                                                        rectCenter + (location.MapPosition + viewOffset) * zoom,
                                                                        generationParams.IndicatorColor,
                                                                        generationParams.SelectedLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.SelectedLocationIndicator.size.X) * 1.7f * zoom);
                    }

                    Color color = location.Type.SpriteColor;
                    if (!location.Discovered)
                    {
                        color = Color.White;
                    }
                    if (location.Connections.Find(c => c.Locations.Contains(CurrentDisplayLocation)) == null)
                    {
                        color *= 0.5f;
                    }

                    float iconScale = location == CurrentDisplayLocation ? 1.2f : 1.0f;
                    if (location == HighlightedLocation)
                    {
                        iconScale *= 1.2f;
                    }

                    location.Type.Sprite.Draw(spriteBatch, pos, color,
                                              scale: generationParams.LocationIconSize / location.Type.Sprite.size.X * iconScale * zoom);
                    if (location.TypeChangeTimer <= 0 && !string.IsNullOrEmpty(location.LastTypeChangeMessage) && generationParams.TypeChangeIcon != null)
                    {
                        Vector2 typeChangeIconPos   = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
                        float   typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width;
                        generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom);
                        if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom)
                        {
                            tooltip = new Pair <Rectangle, string>(
                                new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)),
                                location.LastTypeChangeMessage);
                        }
                    }
                    if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null)
                    {
                        Vector2 missionIconPos   = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
                        float   missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
                        generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
                        if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom)
                        {
                            var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location));
                            tooltip = new Pair <Rectangle, string>(
                                new Rectangle(missionIconPos.ToPoint(), new Point(30)),
                                TextManager.Get("mission") + '\n' + string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
                        }
                    }

                    if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.Type.HasOutpost))
                    {
                        if (location.Reputation != null)
                        {
                            Vector2 dPos = pos;
                            dPos.Y += 48;
                            string  name     = $"Reputation: {location.Name}";
                            Vector2 nameSize = GUI.SmallFont.MeasureString(name);
                            GUI.DrawString(spriteBatch, dPos, name, Color.White, Color.Black * 0.8f, 4, font: GUI.SmallFont);
                            dPos.Y += nameSize.Y + 16;

                            Rectangle bgRect = new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32);
                            bgRect.Inflate(8, 8);
                            Color barColor = ToolBox.GradientLerp(location.Reputation.NormalizedValue, Color.Red, Color.Yellow, Color.LightGreen);
                            GUI.DrawRectangle(spriteBatch, bgRect, Color.Black * 0.8f, isFilled: true);
                            GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, (int)(location.Reputation.NormalizedValue * 255), 32), barColor, isFilled: true);
                            string  reputationValue = ((int)location.Reputation.Value).ToString();
                            Vector2 repValueSize    = GUI.SubHeadingFont.MeasureString(reputationValue);
                            GUI.DrawString(spriteBatch, dPos + (new Vector2(256, 32) / 2) - (repValueSize / 2), reputationValue, Color.White, Color.Black, font: GUI.SubHeadingFont);
                            GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White);
                        }
                    }
                }
            }

            DrawDecorativeHUD(spriteBatch, rect);

            if (HighlightedLocation != null)
            {
                Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom;
                pos.X += 50 * zoom;
                Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
                Vector2 typeSize = GUI.Font.MeasureString(HighlightedLocation.Type.Name);
                Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
                bool    showReputation = HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
                string  repLabelText = null, repValueText = null;
                Vector2 repLabelSize = Vector2.Zero, repBarSize = Vector2.Zero;
                if (showReputation)
                {
                    repLabelText = TextManager.Get("reputation");
                    repLabelSize = GUI.Font.MeasureString(repLabelText);
                    size.X       = Math.Max(size.X, repLabelSize.X);
                    repBarSize   = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y);
                    size.X       = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X);
                    size.Y      += 2 * repLabelSize.Y + 4 + repBarSize.Y;
                    repValueText = ((int)HighlightedLocation.Reputation.Value).ToString();
                }
                GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
                    spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
                var topLeftPos = pos - new Vector2(0.0f, size.Y / 2);
                GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont);
                topLeftPos += new Vector2(0.0f, nameSize.Y);
                GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Type.Name, GUI.Style.TextColor * hudVisibility * 1.5f);
                if (showReputation)
                {
                    topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y);
                    GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f);
                    topLeftPos += new Vector2(0.0f, repLabelSize.Y + 4);
                    Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y));
                    RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue);
                    GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, GUI.Style.TextColor);
                }
            }
            if (tooltip != null)
            {
                GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
            }
            spriteBatch.End();
            GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
            spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
        }
Exemplo n.º 11
0
        public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false)
        {
#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
#endif

            this.level = level;

            if (submarine == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected");
                return;
            }

            if (reloadSub || Submarine.MainSub != submarine)
            {
                submarine.Load(true);
            }
            Submarine.MainSub = submarine;
            if (loadSecondSub)
            {
                if (Submarine.MainSubs[1] == null)
                {
                    Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
                    Submarine.MainSubs[1].Load(false);
                }
                else if (reloadSub)
                {
                    Submarine.MainSubs[1].Load(false);
                }
            }

            if (level != null)
            {
                level.Generate();

                submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                currentMission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                Mission.Start(Level.Loaded);
            }

            EventManager.StartRound(level);

            if (GameMode != null)
            {
                GameMode.MsgBox();
                if (GameMode is MultiPlayerCampaign campaign && GameMain.Server != null)
                {
                    campaign.CargoManager.CreateItems();
                }
            }

            GameAnalyticsManager.AddDesignEvent("Submarine:" + submarine.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));


#if CLIENT
            roundSummary = new RoundSummary(this);

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
            SoundPlayer.SwitchMusic();
#endif
        }
        public void StartRound(LevelData levelData, bool mirrorLevel = false, SubmarineInfo startOutpost = null, SubmarineInfo endOutpost = null)
        {
            if (SubmarineInfo == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
                return;
            }
            if (SubmarineInfo.IsFileCorrupted)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine file corrupted.");
                return;
            }
            if (SubmarineInfo.SubmarineElement.Elements().Count() == 0)
            {
                DebugConsole.ThrowError("Couldn't start game session, saved submarine is empty. The submarine file may be corrupted.");
                return;
            }

            LevelData = levelData;

            if (GameMode is CampaignMode campaignMode && GameMode.Mission != null &&
                LevelData != null && LevelData.Type == LevelData.LevelType.Outpost)
            {
                campaignMode.Map.CurrentLocation.SelectedMission = null;
            }

            Submarine.Unload();
            Submarine = Submarine.MainSub = new Submarine(SubmarineInfo);
            foreach (Submarine sub in Submarine.GetConnectedSubs())
            {
                sub.TeamID = CharacterTeamType.Team1;
                foreach (Item item in Item.ItemList)
                {
                    if (item.Submarine != sub)
                    {
                        continue;
                    }
                    foreach (WifiComponent wifiComponent in item.GetComponents <WifiComponent>())
                    {
                        wifiComponent.TeamID = sub.TeamID;
                    }
                }
            }
            if (GameMode is PvPMode && Submarine.MainSubs[1] == null)
            {
                Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true);
            }

            Level level = null;

            if (levelData != null)
            {
                level = Level.Generate(levelData, mirrorLevel, startOutpost, endOutpost);
            }

            InitializeLevel(level);

            GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Info.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(levelData?.Seed ?? "[NO_LEVEL]"));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));

#if CLIENT
            if (GameMode is CampaignMode)
            {
                SteamAchievementManager.OnBiomeDiscovered(levelData.Biome);
            }

            var existingRoundSummary = GUIMessageBox.MessageBoxes.Find(mb => mb.UserData is RoundSummary)?.UserData as RoundSummary;
            if (existingRoundSummary?.ContinueButton != null)
            {
                existingRoundSummary.ContinueButton.Visible = true;
            }

            RoundSummary = new RoundSummary(Submarine.Info, GameMode, Mission, StartLocation, EndLocation);

            if (!(GameMode is TutorialMode) && !(GameMode is TestGameMode))
            {
                GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
                if (EndLocation != null)
                {
                    GUI.AddMessage(levelData.Biome.DisplayName, Color.Lerp(Color.CadetBlue, Color.DarkRed, levelData.Difficulty / 100.0f), 5.0f, playSound: false);
                    GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Destination"), EndLocation.Name), Color.CadetBlue, playSound: false);
                    GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Mission"), (Mission == null ? TextManager.Get("None") : Mission.Name)), Color.CadetBlue, playSound: false);
                }
                else
                {
                    GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Location"), StartLocation.Name), Color.CadetBlue, playSound: false);
                }
            }

            GUI.PreventPauseMenuToggle = false;
#endif
        }
Exemplo n.º 13
0
        public void StartRound(Level level, bool mirrorLevel = false)
        {
            //make sure no status effects have been carried on from the next round
            //(they should be stopped in EndRound, this is a safeguard against cases where the round is ended ungracefully)
            StatusEffect.StopAll();

#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.Client == null || GameMain.Client.CharacterInfo != null;
            if (GameMain.Client == null)
            {
                GameMain.LightManager.LosMode = GameMain.Config.LosMode;
            }
#endif
            this.Level = level;

            if (SubmarineInfo == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
                return;
            }

            if (SubmarineInfo.IsFileCorrupted)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine file corrupted.");
                return;
            }

            Submarine.Unload();
            Submarine         = Submarine.MainSub = new Submarine(SubmarineInfo);
            Submarine.MainSub = Submarine;
            if (GameMode.Mission != null && GameMode.Mission.TeamCount > 1 && Submarine.MainSubs[1] == null)
            {
                Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true);
            }

            if (level != null)
            {
                level.Generate(mirrorLevel);
                if (level.StartOutpost != null)
                {
                    //start by placing the sub below the outpost
                    Rectangle outpostBorders = Level.Loaded.StartOutpost.GetDockedBorders();
                    Rectangle subBorders     = Submarine.GetDockedBorders();

                    Vector2 startOutpostSize = Vector2.Zero;
                    if (Level.Loaded.StartOutpost != null)
                    {
                        startOutpostSize = Level.Loaded.StartOutpost.Borders.Size.ToVector2();
                    }
                    Submarine.SetPosition(
                        Level.Loaded.StartOutpost.WorldPosition -
                        new Vector2(0.0f, outpostBorders.Height / 2 + subBorders.Height / 2));

                    //find the port that's the nearest to the outpost and dock if one is found
                    float       closestDistance = 0.0f;
                    DockingPort myPort = null, outPostPort = null;
                    foreach (DockingPort port in DockingPort.List)
                    {
                        if (port.IsHorizontal || port.Docked)
                        {
                            continue;
                        }
                        if (port.Item.Submarine == level.StartOutpost)
                        {
                            outPostPort = port;
                            continue;
                        }
                        if (port.Item.Submarine != Submarine)
                        {
                            continue;
                        }

                        //the submarine port has to be at the top of the sub
                        if (port.Item.WorldPosition.Y < Submarine.WorldPosition.Y)
                        {
                            continue;
                        }

                        float dist = Vector2.DistanceSquared(port.Item.WorldPosition, level.StartOutpost.WorldPosition);
                        if (myPort == null || dist < closestDistance || (port.MainDockingPort && !myPort.MainDockingPort))
                        {
                            myPort          = port;
                            closestDistance = dist;
                        }
                    }

                    if (myPort != null && outPostPort != null)
                    {
                        Vector2 portDiff = myPort.Item.WorldPosition - Submarine.WorldPosition;
                        Submarine.SetPosition((outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance);
                        myPort.Dock(outPostPort);
                        myPort.Lock(true);
                    }
                }
                else
                {
                    Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition));
                }
            }

            foreach (var sub in Submarine.Loaded)
            {
                if (sub.Info.IsOutpost)
                {
                    sub.DisableObstructedWayPoints();
                }
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                Mission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                int prevEntityCount = Entity.GetEntityList().Count;
                Mission.Start(Level.Loaded);
                if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && Entity.GetEntityList().Count != prevEntityCount)
                {
                    DebugConsole.ThrowError(
                        "Entity count has changed after starting a mission as a client. " +
                        "The clients should not instantiate entities themselves when starting the mission," +
                        " but instead the server should inform the client of the spawned entities using Mission.ServerWriteInitial.");
                }
            }

            EventManager?.StartRound(level);
            SteamAchievementManager.OnStartRound();

            if (GameMode != null)
            {
                GameMode.ShowStartMessage();

                if (GameMain.NetworkMember == null)
                {
                    //only place items and corpses here in single player
                    //the server does this after loading the respawn shuttle
                    Level?.SpawnCorpses();
                    AutoItemPlacer.PlaceIfNeeded(GameMode);
                }
                if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
                {
                    mpCampaign.CargoManager.CreateItems();
                }
            }

            GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Info.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level?.Seed ?? "[NO_LEVEL]"));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));

#if CLIENT
            if (GameMode is SinglePlayerCampaign)
            {
                SteamAchievementManager.OnBiomeDiscovered(level.Biome);
            }
            if (!(GameMode is SubTestMode))
            {
                RoundSummary = new RoundSummary(this);
            }

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);

            if (!(GameMode is TutorialMode) && !(GameMode is SubTestMode))
            {
                GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
                GUI.AddMessage(level.Biome.DisplayName, Color.Lerp(Color.CadetBlue, Color.DarkRed, level.Difficulty / 100.0f), 5.0f, playSound: false);
                GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Destination"), EndLocation.Name), Color.CadetBlue, playSound: false);
                GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Mission"), (Mission == null ? TextManager.Get("None") : Mission.Name)), Color.CadetBlue, playSound: false);
            }
#endif

            RoundStartTime = Timing.TotalTime;
            GameMain.ResetFrameTime();
        }