Exemple #1
0
        private IEnumerable <Client> GetClientsToRespawn()
        {
            MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;

            foreach (Client c in networkMember.ConnectedClients)
            {
                if (!c.InGame)
                {
                    continue;
                }
                if (c.SpectateOnly && (GameMain.Server.ServerSettings.AllowSpectating || GameMain.Server.OwnerConnection == c.Connection))
                {
                    continue;
                }
                if (c.Character != null && !c.Character.IsDead)
                {
                    continue;
                }

                //don't allow respawning if the client has previously disconnected and their corpse is still present on the server
                var matchingData = campaign?.GetClientCharacterData(c);
                if (matchingData != null && matchingData.HasSpawned &&
                    Character.CharacterList.Any(c => c.Info == matchingData.CharacterInfo && c.CauseOfDeath?.Type == CauseOfDeathType.Disconnected))
                {
                    continue;
                }

                yield return(c);
            }
        }
        private IEnumerable <Client> GetClientsToRespawn()
        {
            MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;

            foreach (Client c in networkMember.ConnectedClients)
            {
                if (!c.InGame)
                {
                    continue;
                }
                if (c.SpectateOnly && (GameMain.Server.ServerSettings.AllowSpectating || GameMain.Server.OwnerConnection == c.Connection))
                {
                    continue;
                }
                if (c.Character != null && !c.Character.IsDead)
                {
                    continue;
                }

                //don't allow respawn if the client already has a character (they'll regain control once they're in sync)
                var matchingData = campaign?.GetClientCharacterData(c);
                if (matchingData != null && matchingData.HasSpawned &&
                    Character.CharacterList.Any(c => c.Info == matchingData.CharacterInfo && !c.IsDead))
                {
                    continue;
                }

                if (UseRespawnPrompt)
                {
                    if (matchingData != null && matchingData.HasSpawned)
                    {
                        if (!c.WaitForNextRoundRespawn.HasValue || c.WaitForNextRoundRespawn.Value)
                        {
                            continue;
                        }
                    }
                }

                yield return(c);
            }
        }
Exemple #3
0
        partial void RespawnCharactersProjSpecific()
        {
            var respawnSub = RespawnShuttle ?? Submarine.MainSub;

            MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;

            var clients = GetClientsToRespawn().ToList();

            foreach (Client c in clients)
            {
                //get rid of the existing character
                c.Character?.DespawnNow();

                var matchingData = campaign?.GetClientCharacterData(c);
                if (matchingData != null && !matchingData.HasSpawned)
                {
                    c.CharacterInfo = matchingData.CharacterInfo;
                }

                //all characters are in Team 1 in game modes/missions with only one team.
                //if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked
                c.TeamID = Character.TeamType.Team1;
                if (c.CharacterInfo == null)
                {
                    c.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, c.Name);
                }
            }
            List <CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList();

            var botsToSpawn = GetBotsToRespawn();

            characterInfos.AddRange(botsToSpawn);

            GameMain.Server.AssignJobs(clients);
            foreach (Client c in clients)
            {
                if (campaign?.GetClientCharacterData(c) == null || c.CharacterInfo.Job == null)
                {
                    c.CharacterInfo.Job = new Job(c.AssignedJob.First, c.AssignedJob.Second);
                }
            }

            //the spawnpoints where the characters will spawn
            var shuttleSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, respawnSub);
            //the spawnpoints where they would spawn if they were spawned inside the main sub
            //(in order to give them appropriate ID card tags)
            var mainSubSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);

            ItemPrefab divingSuitPrefab = MapEntityPrefab.Find(null, "divingsuit") as ItemPrefab;
            ItemPrefab oxyPrefab        = MapEntityPrefab.Find(null, "oxygentank") as ItemPrefab;
            ItemPrefab scooterPrefab    = MapEntityPrefab.Find(null, "underwaterscooter") as ItemPrefab;
            ItemPrefab batteryPrefab    = MapEntityPrefab.Find(null, "batterycell") as ItemPrefab;

            var cargoSp = WayPoint.WayPointList.Find(wp => wp.Submarine == respawnSub && wp.SpawnType == SpawnType.Cargo);

            for (int i = 0; i < characterInfos.Count; i++)
            {
                bool bot = i >= clients.Count;

                characterInfos[i].CurrentOrder       = null;
                characterInfos[i].CurrentOrderOption = null;

                var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, characterInfos[i].Name, !bot, bot);
                character.TeamID = Character.TeamType.Team1;

                if (bot)
                {
                    GameServer.Log(string.Format("Respawning bot {0} as {1}", character.Info.Name, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
                }
                else
                {
                    //tell the respawning client they're no longer a traitor
                    if (GameMain.Server.TraitorManager?.Traitors != null && clients[i].Character != null)
                    {
                        if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == clients[i].Character))
                        {
                            GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("TraitorRespawnMessage"), clients[i], ChatMessageType.ServerMessageBox);
                        }
                    }

                    clients[i].Character          = character;
                    character.OwnerClientEndPoint = clients[i].Connection.EndPointString;
                    character.OwnerClientName     = clients[i].Name;
                    GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", GameServer.ClientLogName(clients[i]), clients[i].Connection?.EndPointString, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
                }

                if (divingSuitPrefab != null && oxyPrefab != null && RespawnShuttle != null)
                {
                    Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position;
                    if (divingSuitPrefab != null && oxyPrefab != null)
                    {
                        var divingSuit = new Item(divingSuitPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(divingSuit, false);
                        respawnItems.Add(divingSuit);

                        var oxyTank = new Item(oxyPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(oxyTank, false);
                        divingSuit.Combine(oxyTank, user: null);
                        respawnItems.Add(oxyTank);
                    }

                    if (scooterPrefab != null && batteryPrefab != null)
                    {
                        var scooter = new Item(scooterPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(scooter, false);

                        var battery = new Item(batteryPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(battery, false);

                        scooter.Combine(battery, user: null);
                        respawnItems.Add(scooter);
                        respawnItems.Add(battery);
                    }
                }

                var characterData = campaign?.GetClientCharacterData(clients[i]);
                if (characterData == null || characterData.HasSpawned)
                {
                    //give the character the items they would've gotten if they had spawned in the main sub
                    character.GiveJobItems(mainSubSpawnPoints[i]);
                    if (campaign != null)
                    {
                        characterData            = campaign.SetClientCharacterData(clients[i]);
                        characterData.HasSpawned = true;
                    }
                }
                else
                {
                    characterData.SpawnInventoryItems(character.Info, character.Inventory);
                    characterData.ApplyHealthData(character.Info, character);
                    character.GiveIdCardTags(mainSubSpawnPoints[i]);
                    characterData.HasSpawned = true;
                }

                //add the ID card tags they should've gotten when spawning in the shuttle
                foreach (Item item in character.Inventory.Items)
                {
                    if (item == null || item.Prefab.Identifier != "idcard")
                    {
                        continue;
                    }
                    foreach (string s in shuttleSpawnPoints[i].IdCardTags)
                    {
                        item.AddTag(s);
                    }
                    if (!string.IsNullOrWhiteSpace(shuttleSpawnPoints[i].IdCardDesc))
                    {
                        item.Description = shuttleSpawnPoints[i].IdCardDesc;
                    }
                }
            }
        }
        partial void RespawnCharactersProjSpecific(Vector2?shuttlePos)
        {
            respawnedCharacters.Clear();

            var respawnSub = RespawnShuttle ?? Submarine.MainSub;

            MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;

            var clients = GetClientsToRespawn().ToList();

            foreach (Client c in clients)
            {
                //get rid of the existing character
                c.Character?.DespawnNow();

                c.WaitForNextRoundRespawn = null;

                var matchingData = campaign?.GetClientCharacterData(c);
                if (matchingData != null && !matchingData.HasSpawned)
                {
                    c.CharacterInfo = matchingData.CharacterInfo;
                }

                //all characters are in Team 1 in game modes/missions with only one team.
                //if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked
                c.TeamID = CharacterTeamType.Team1;
                if (c.CharacterInfo == null)
                {
                    c.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, c.Name);
                }
            }
            List <CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList();

            //bots don't respawn in the campaign
            if (campaign == null)
            {
                var botsToSpawn = GetBotsToRespawn();
                characterInfos.AddRange(botsToSpawn);
            }

            GameMain.Server.AssignJobs(clients);
            foreach (Client c in clients)
            {
                if (campaign?.GetClientCharacterData(c) == null || c.CharacterInfo.Job == null)
                {
                    c.CharacterInfo.Job = new Job(c.AssignedJob.First, c.AssignedJob.Second);
                }
            }

            //the spawnpoints where the characters will spawn
            var shuttleSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, respawnSub);
            //the spawnpoints where they would spawn if they were spawned inside the main sub
            //(in order to give them appropriate ID card tags)
            var mainSubSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);

            ItemPrefab divingSuitPrefab = null;

            if ((shuttlePos != null && Level.Loaded.GetRealWorldDepth(shuttlePos.Value.Y) > Level.DefaultRealWorldCrushDepth) ||
                Level.Loaded.GetRealWorldDepth(Submarine.MainSub.WorldPosition.Y) > Level.DefaultRealWorldCrushDepth)
            {
                divingSuitPrefab = ItemPrefab.Prefabs.FirstOrDefault(it => it.Tags.Any(t => t.Equals("respawnsuitdeep", StringComparison.OrdinalIgnoreCase)));
            }
            if (divingSuitPrefab == null)
            {
                divingSuitPrefab =
                    ItemPrefab.Prefabs.FirstOrDefault(it => it.Tags.Any(t => t.Equals("respawnsuit", StringComparison.OrdinalIgnoreCase))) ??
                    ItemPrefab.Find(null, "divingsuit");
            }
            ItemPrefab oxyPrefab     = ItemPrefab.Find(null, "oxygentank");
            ItemPrefab scooterPrefab = ItemPrefab.Find(null, "underwaterscooter");
            ItemPrefab batteryPrefab = ItemPrefab.Find(null, "batterycell");

            var cargoSp = WayPoint.WayPointList.Find(wp => wp.Submarine == respawnSub && wp.SpawnType == SpawnType.Cargo);

            for (int i = 0; i < characterInfos.Count; i++)
            {
                bool bot = i >= clients.Count;

                characterInfos[i].ClearCurrentOrders();

                bool forceSpawnInMainSub = false;
                if (!bot && campaign != null)
                {
                    var matchingData = campaign?.GetClientCharacterData(clients[i]);
                    if (matchingData != null)
                    {
                        if (!matchingData.HasSpawned)
                        {
                            forceSpawnInMainSub = true;
                        }
                        else
                        {
                            ReduceCharacterSkills(characterInfos[i]);
                        }
                    }
                }

                var character = Character.Create(characterInfos[i], (forceSpawnInMainSub ? mainSubSpawnPoints[i] : shuttleSpawnPoints[i]).WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot);
                character.TeamID = CharacterTeamType.Team1;
                character.LoadTalents();

                respawnedCharacters.Add(character);

                if (bot)
                {
                    GameServer.Log(string.Format("Respawning bot {0} as {1}", character.Info.Name, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
                }
                else
                {
                    if (GameMain.GameSession?.GameMode is MultiPlayerCampaign mpCampaign && character.Info != null)
                    {
                        character.Info.SetExperience(Math.Max(character.Info.ExperiencePoints, mpCampaign.GetSavedExperiencePoints(clients[i])));
                        mpCampaign.ClearSavedExperiencePoints(clients[i]);
                    }

                    //tell the respawning client they're no longer a traitor
                    if (GameMain.Server.TraitorManager?.Traitors != null && clients[i].Character != null)
                    {
                        if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == clients[i].Character))
                        {
                            GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("TraitorRespawnMessage"), clients[i], ChatMessageType.ServerMessageBox);
                        }
                    }

                    clients[i].Character          = character;
                    character.OwnerClientEndPoint = clients[i].Connection.EndPointString;
                    character.OwnerClientName     = clients[i].Name;
                    GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", GameServer.ClientLogName(clients[i]), clients[i].Connection?.EndPointString, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
                }

                if (divingSuitPrefab != null && oxyPrefab != null && RespawnShuttle != null)
                {
                    Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position;
                    if (divingSuitPrefab != null && oxyPrefab != null)
                    {
                        var divingSuit = new Item(divingSuitPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(divingSuit, false);
                        respawnItems.Add(divingSuit);

                        var oxyTank = new Item(oxyPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(oxyTank, false);
                        divingSuit.Combine(oxyTank, user: null);
                        respawnItems.Add(oxyTank);
                    }

                    if (scooterPrefab != null && batteryPrefab != null)
                    {
                        var scooter = new Item(scooterPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(scooter, false);

                        var battery = new Item(batteryPrefab, pos, respawnSub);
                        Spawner.CreateNetworkEvent(battery, false);

                        scooter.Combine(battery, user: null);
                        respawnItems.Add(scooter);
                        respawnItems.Add(battery);
                    }
                }

                var characterData = campaign?.GetClientCharacterData(clients[i]);
                if (characterData != null && Level.Loaded?.Type != LevelData.LevelType.Outpost && characterData.HasSpawned)
                {
                    GiveRespawnPenaltyAffliction(character);
                }

                if (characterData == null || characterData.HasSpawned)
                {
                    //give the character the items they would've gotten if they had spawned in the main sub
                    character.GiveJobItems(mainSubSpawnPoints[i]);
                    if (campaign != null)
                    {
                        characterData            = campaign.SetClientCharacterData(clients[i]);
                        characterData.HasSpawned = true;
                    }
                }
                else
                {
                    if (characterData.HasItemData)
                    {
                        characterData.SpawnInventoryItems(character, character.Inventory);
                    }
                    else
                    {
                        character.GiveJobItems(mainSubSpawnPoints[i]);
                    }
                    characterData.ApplyHealthData(character);
                    character.GiveIdCardTags(mainSubSpawnPoints[i]);
                    characterData.HasSpawned = true;
                }

                //add the ID card tags they should've gotten when spawning in the shuttle
                foreach (Item item in character.Inventory.AllItems.Distinct())
                {
                    if (item.Prefab.Identifier != "idcard")
                    {
                        continue;
                    }
                    foreach (string s in shuttleSpawnPoints[i].IdCardTags)
                    {
                        item.AddTag(s);
                    }
                    if (!string.IsNullOrWhiteSpace(shuttleSpawnPoints[i].IdCardDesc))
                    {
                        item.Description = shuttleSpawnPoints[i].IdCardDesc;
                    }
                }
            }
        }