Ejemplo n.º 1
0
        public static LinkedSubmarine CreateDummy(Submarine mainSub, Submarine linkedSub)
        {
            LinkedSubmarine sl = new LinkedSubmarine(mainSub);

            sl.sub = linkedSub;

            return(sl);
        }
Ejemplo n.º 2
0
        public override MapEntity Clone()
        {
            XElement        cloneElement = new XElement(saveElement);
            LinkedSubmarine sl           = CreateDummy(Submarine, cloneElement, Position);

            sl.saveElement = cloneElement;
            sl.filePath    = filePath;
            return(sl);
        }
Ejemplo n.º 3
0
        public static LinkedSubmarine Load(XElement element, Submarine submarine)
        {
            Vector2         pos       = element.GetAttributeVector2("pos", Vector2.Zero);
            LinkedSubmarine linkedSub = null;

            if (Screen.Selected == GameMain.SubEditorScreen)
            {
                linkedSub                       = CreateDummy(submarine, element, pos);
                linkedSub.saveElement           = element;
                linkedSub.purchasedLostShuttles = false;
            }
            else
            {
                linkedSub = new LinkedSubmarine(submarine)
                {
                    saveElement = element
                };

                linkedSub.purchasedLostShuttles = GameMain.GameSession.GameMode is CampaignMode campaign && campaign.PurchasedLostShuttles;
                string levelSeed = element.GetAttributeString("location", "");
                if (!string.IsNullOrWhiteSpace(levelSeed) &&
                    GameMain.GameSession.Level != null &&
                    GameMain.GameSession.Level.Seed != levelSeed &&
                    !linkedSub.purchasedLostShuttles)
                {
                    linkedSub.loadSub = false;
                }
                else
                {
                    linkedSub.loadSub       = true;
                    linkedSub.rect.Location = MathUtils.ToPoint(pos);
                }
            }

            linkedSub.filePath = element.GetAttributeString("filepath", "");
            int[] linkedToIds = element.GetAttributeIntArray("linkedto", new int[0]);
            for (int i = 0; i < linkedToIds.Length; i++)
            {
                linkedSub.linkedToID.Add((ushort)linkedToIds[i]);
                if (Screen.Selected == GameMain.SubEditorScreen)
                {
                    if (FindEntityByID((ushort)linkedToIds[i]) is MapEntity linked)
                    {
                        linkedSub.linkedTo.Add(linked);
                    }
                }
            }
            linkedSub.originalLinkedToID = (ushort)element.GetAttributeInt("originallinkedto", 0);
            linkedSub.originalMyPortID   = (ushort)element.GetAttributeInt("originalmyport", 0);


            return(linkedSub.loadSub ? linkedSub : null);
        }
Ejemplo n.º 4
0
        public static LinkedSubmarine CreateDummy(Submarine mainSub, string filePath, Vector2 position)
        {
            XDocument doc = SubmarineInfo.OpenFile(filePath);

            if (doc == null || doc.Root == null)
            {
                return(null);
            }

            LinkedSubmarine sl = CreateDummy(mainSub, doc.Root, position);

            sl.filePath = filePath;

            return(sl);
        }
Ejemplo n.º 5
0
        public static LinkedSubmarine CreateDummy(Submarine mainSub, XElement element, Vector2 position)
        {
            LinkedSubmarine sl = new LinkedSubmarine(mainSub);

            sl.GenerateWallVertices(element);

            sl.Rect = new Rectangle(
                (int)sl.wallVertices.Min(v => v.X + position.X),
                (int)sl.wallVertices.Max(v => v.Y + position.Y),
                (int)sl.wallVertices.Max(v => v.X + position.X),
                (int)sl.wallVertices.Min(v => v.Y + position.Y));

            sl.rect = new Rectangle((int)position.X, (int)position.Y, 1, 1);

            return(sl);
        }
Ejemplo n.º 6
0
        public static LinkedSubmarine CreateDummy(Submarine mainSub, string filePath, Vector2 position)
        {
            XDocument doc = SubmarineInfo.OpenFile(filePath);

            if (doc == null || doc.Root == null)
            {
                return(null);
            }

            LinkedSubmarine sl = CreateDummy(mainSub, doc.Root, position);

            sl.filePath         = filePath;
            sl.saveElement      = doc.Root;
            sl.saveElement.Name = "LinkedSubmarine";
            sl.saveElement.SetAttributeValue("filepath", filePath);

            return(sl);
        }
Ejemplo n.º 7
0
        public static LinkedSubmarine Load(XElement element, Submarine submarine)
        {
            Vector2 pos = element.GetAttributeVector2("pos", Vector2.Zero);

            LinkedSubmarine linkedSub = null;

            if (Screen.Selected == GameMain.SubEditorScreen)
            {
                linkedSub             = CreateDummy(submarine, element, pos);
                linkedSub.saveElement = element;
            }
            else
            {
                linkedSub = new LinkedSubmarine(submarine)
                {
                    saveElement = element
                };

                string levelSeed = element.GetAttributeString("location", "");
                if (!string.IsNullOrWhiteSpace(levelSeed) && GameMain.GameSession.Level != null && GameMain.GameSession.Level.Seed != levelSeed)
                {
                    linkedSub.loadSub = false;
                    return(null);
                }

                linkedSub.loadSub = true;

                linkedSub.rect.Location = MathUtils.ToPoint(pos);
            }

            linkedSub.filePath = element.GetAttributeString("filepath", "");

            string linkedToString = element.GetAttributeString("linkedto", "");

            if (linkedToString != "")
            {
                string[] linkedToIds = linkedToString.Split(',');
                for (int i = 0; i < linkedToIds.Length; i++)
                {
                    linkedSub.linkedToID.Add((ushort)int.Parse(linkedToIds[i]));
                }
            }
            return(linkedSub);
        }
Ejemplo n.º 8
0
        public static LinkedSubmarine CreateDummy(Submarine mainSub, XElement element, Vector2 position)
        {
            LinkedSubmarine sl = new LinkedSubmarine(mainSub);

            sl.GenerateWallVertices(element);
            if (sl.wallVertices.Any())
            {
                sl.Rect = new Rectangle(
                    (int)sl.wallVertices.Min(v => v.X + position.X),
                    (int)sl.wallVertices.Max(v => v.Y + position.Y),
                    (int)sl.wallVertices.Max(v => v.X + position.X),
                    (int)sl.wallVertices.Min(v => v.Y + position.Y));

                int width  = sl.rect.Width - sl.rect.X;
                int height = sl.rect.Y - sl.rect.Height;
                sl.Rect = new Rectangle((int)(position.X - width / 2), (int)(position.Y + height / 2), width, height);
            }
            else
            {
                sl.Rect = new Rectangle((int)position.X, (int)position.Y, 10, 10);
            }
            return(sl);
        }
Ejemplo n.º 9
0
 protected override void CreateInstance(Rectangle rect)
 {
     System.Diagnostics.Debug.Assert(Submarine.MainSub != null);
     LinkedSubmarine.CreateDummy(Submarine.MainSub, subInfo.FilePath, rect.Location.ToVector2());
 }
Ejemplo n.º 10
0
        protected override IEnumerable <object> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List <TraitorMissionResult> traitorResults)
        {
            lastUpdateID++;

            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;

            case TransitionType.End:
                EndCampaign();
                IsFirstRound = true;
                break;
            }

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

            bool success = GameMain.Server.ConnectedClients.Any(c => c.InGame && c.Character != null && !c.Character.IsDead);

            GameMain.GameSession.EndRound("", traitorResults, transitionType);

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

            if (success)
            {
                SaveInventories();

                yield return(CoroutineStatus.Running);

                if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
                {
                    Submarine.MainSub = leavingSub;
                    GameMain.GameSession.Submarine     = leavingSub;
                    GameMain.GameSession.SubmarineInfo = leavingSub.Info;
                    leavingSub.Info.FilePath           = System.IO.Path.Combine(SaveUtil.TempPath, leavingSub.Info.Name + ".sub");
                    var subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
                    GameMain.GameSession.OwnedSubmarines.Add(leavingSub.Info);
                    foreach (Submarine sub in subsToLeaveBehind)
                    {
                        GameMain.GameSession.OwnedSubmarines.RemoveAll(s => s != leavingSub.Info && s.Name == sub.Info.Name);
                        MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
                        LinkedSubmarine.CreateDummy(leavingSub, sub);
                    }
                }
                NextLevel = newLevel;
                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;
                GameMain.Server.EndGame(TransitionType.None);
                LoadCampaign(GameMain.GameSession.SavePath);
                LastSaveID++;
                LastUpdateID++;
                yield return(CoroutineStatus.Success);
            }

            CrewManager?.ClearCurrentOrders();

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

            GameMain.Server.EndGame(transitionType);

            ForceMapUI = false;

            NextLevel   = newLevel;
            MirrorLevel = mirror;

            //give clients time to play the end cinematic before starting the next round
            if (transitionType == TransitionType.End)
            {
                yield return(new WaitForSeconds(EndCinematicDuration));
            }
            else
            {
                yield return(new WaitForSeconds(EndTransitionDuration * 0.5f));
            }

            GameMain.Server.StartGame();

            yield return(CoroutineStatus.Success);
        }
Ejemplo n.º 11
0
        public override void End(string endMessage = "")
        {
            isRunning = false;

            bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);

            crewDead = false;

            if (success)
            {
                if (subsToLeaveBehind == null || leavingSub == null)
                {
                    DebugConsole.ThrowError("Leaving submarine not selected -> selecting the closest one");

                    leavingSub = GetLeavingSub();

                    subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
                }
            }

            GameMain.GameSession.EndRound("");

            if (success)
            {
                if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
                {
                    Submarine.MainSub = leavingSub;

                    GameMain.GameSession.Submarine = leavingSub;

                    foreach (Submarine sub in subsToLeaveBehind)
                    {
                        MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
                        LinkedSubmarine.CreateDummy(leavingSub, sub);
                    }
                }

                if (atEndPosition)
                {
                    Map.MoveToNextLocation();
                }
                else
                {
                    Map.SelectLocation(-1);
                }
                Map.ProgressWorld();

                //save and remove all items that are in someone's inventory
                foreach (Character c in Character.CharacterList)
                {
                    if (c.Info == null || c.Inventory == null)
                    {
                        continue;
                    }
                    var inventoryElement = new XElement("inventory");
                    c.SaveInventory(c.Inventory, inventoryElement);
                    c.Info.InventoryData = inventoryElement;
                    c.Inventory?.DeleteAllItems();
                }
                SaveUtil.SaveGame(GameMain.GameSession.SavePath);
            }

            if (!success)
            {
                var summaryScreen = GUIMessageBox.VisibleBox;

                if (summaryScreen != null)
                {
                    summaryScreen = summaryScreen.Children.First();
                    var buttonArea = summaryScreen.Children.First().FindChild("buttonarea");
                    buttonArea.ClearChildren();


                    summaryScreen.RemoveChild(summaryScreen.Children.FirstOrDefault(c => c is GUIButton));

                    var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
                                                 TextManager.Get("LoadGameButton"))
                    {
                        OnClicked = (GUIButton button, object obj) =>
                        {
                            GameMain.GameSession.LoadPrevious();
                            GameMain.LobbyScreen.Select();
                            GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
                            return(true);
                        }
                    };

                    var quitButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
                                                   TextManager.Get("QuitButton"));
                    quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
                    quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return(true); };
                    quitButton.OnClicked += (GUIButton button, object obj) => { if (ContextualTutorial.Initialized)
                                                                                {
                                                                                    ContextualTutorial.Stop();
                                                                                }
                                                                                return(true); };
                }
            }

            CrewManager.EndRound();
            for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
            {
                Character.CharacterList[i].Remove();
            }

            Submarine.Unload();

            GameMain.LobbyScreen.Select();
        }
Ejemplo n.º 12
0
        public override void End(string endMessage = "")
        {
            isRunning = false;

            bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);

            if (success)
            {
                if (subsToLeaveBehind == null || leavingSub == null)
                {
                    DebugConsole.ThrowError("Leaving submarine not selected -> selecting the closest one");

                    leavingSub = GetLeavingSub();

                    subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
                }
            }

            GameMain.GameSession.EndRound("");

            if (success)
            {
                if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
                {
                    Submarine.MainSub = leavingSub;

                    GameMain.GameSession.Submarine = leavingSub;

                    foreach (Submarine sub in subsToLeaveBehind)
                    {
                        MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
                        LinkedSubmarine.CreateDummy(leavingSub, sub);
                    }
                }

                if (atEndPosition)
                {
                    Map.MoveToNextLocation();
                }

                SaveUtil.SaveGame(GameMain.GameSession.SavePath);
            }


            if (!success)
            {
                var summaryScreen = GUIMessageBox.VisibleBox;

                if (summaryScreen != null)
                {
                    summaryScreen = summaryScreen.children[0];
                    summaryScreen.RemoveChild(summaryScreen.children.Find(c => c is GUIButton));

                    var okButton = new GUIButton(new Rectangle(-120, 0, 100, 30), TextManager.Get("LoadGameButton"), Alignment.BottomRight, "", summaryScreen);
                    okButton.OnClicked += (GUIButton button, object obj) =>
                    {
                        GameMain.GameSession.LoadPrevious();
                        GameMain.LobbyScreen.Select();
                        GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
                        return(true);
                    };

                    var quitButton = new GUIButton(new Rectangle(0, 0, 100, 30), TextManager.Get("QuitButton"), Alignment.BottomRight, "", summaryScreen);
                    quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
                    quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return(true); };
                }
            }

            CrewManager.EndRound();
            for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
            {
                Character.CharacterList[i].Remove();
            }

            Submarine.Unload();

            GameMain.LobbyScreen.Select();
        }
        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);
        }
Ejemplo n.º 14
0
        protected override IEnumerable <object> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List <TraitorMissionResult> traitorResults)
        {
            lastUpdateID++;

            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;

            case TransitionType.End:
                EndCampaign();
                IsFirstRound = true;
                break;
            }

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

            bool success = GameMain.Server.ConnectedClients.Any(c => c.InGame && c.Character != null && !c.Character.IsDead);

            GameMain.GameSession.EndRound("", traitorResults, transitionType);

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

            if (success)
            {
                List <CharacterCampaignData> prevCharacterData = new List <CharacterCampaignData>(characterData);
                //client character has spawned this round -> remove old data (and replace with an up-to-date one if the client still has a character)
                characterData.RemoveAll(cd => cd.HasSpawned);

                //refresh the character data of clients who are still in the server
                foreach (Client c in GameMain.Server.ConnectedClients)
                {
                    if (c.Character?.Info == null)
                    {
                        continue;
                    }
                    if (c.Character.IsDead && c.Character.CauseOfDeath?.Type != CauseOfDeathType.Disconnected)
                    {
                        continue;
                    }
                    c.CharacterInfo = c.Character.Info;
                    characterData.RemoveAll(cd => cd.MatchesClient(c));
                    characterData.Add(new CharacterCampaignData(c));
                }

                //refresh the character data of clients who aren't in the server anymore
                foreach (CharacterCampaignData data in prevCharacterData)
                {
                    if (data.HasSpawned && !characterData.Any(cd => cd.IsDuplicate(data)))
                    {
                        var character = Character.CharacterList.Find(c => c.Info == data.CharacterInfo && !c.IsHusk);
                        if (character != null && (!character.IsDead || character.CauseOfDeath?.Type == CauseOfDeathType.Disconnected))
                        {
                            data.Refresh(character);
                            characterData.Add(data);
                        }
                    }
                }

                characterData.ForEach(cd => cd.HasSpawned = false);

                //remove all items that are in someone's inventory
                foreach (Character c in Character.CharacterList)
                {
                    if (c.Inventory == null)
                    {
                        continue;
                    }
                    if (Level.Loaded.Type == LevelData.LevelType.Outpost && c.Submarine != Level.Loaded.StartOutpost)
                    {
                        Map.CurrentLocation.RegisterTakenItems(c.Inventory.Items.Where(it => it != null && it.SpawnedInOutpost && it.OriginalModuleIndex > 0).Distinct());
                    }

                    if (c.Info != null && c.IsBot)
                    {
                        if (c.IsDead && c.CauseOfDeath?.Type != CauseOfDeathType.Disconnected)
                        {
                            CrewManager.RemoveCharacterInfo(c.Info);
                        }
                        c.Info.HealthData = new XElement("health");
                        c.CharacterHealth.Save(c.Info.HealthData);
                        c.Info.InventoryData = new XElement("inventory");
                        c.SaveInventory(c.Inventory, c.Info.InventoryData);
                    }

                    c.Inventory.DeleteAllItems();
                }

                yield return(CoroutineStatus.Running);

                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);
                    }
                }
                NextLevel = newLevel;
                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;
                GameMain.Server.EndGame(TransitionType.None);
                LoadCampaign(GameMain.GameSession.SavePath);
                LastSaveID++;
                LastUpdateID++;
                yield return(CoroutineStatus.Success);
            }

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

            GameMain.Server.EndGame(transitionType);

            ForceMapUI = false;

            NextLevel   = newLevel;
            MirrorLevel = mirror;

            //give clients time to play the end cinematic before starting the next round
            if (transitionType == TransitionType.End)
            {
                yield return(new WaitForSeconds(EndCinematicDuration));
            }
            else
            {
                yield return(new WaitForSeconds(EndTransitionDuration * 0.5f));
            }

            GameMain.Server.StartGame();

            yield return(CoroutineStatus.Success);
        }