public bool CanBeApplied(XElement element, UpgradePrefab prefab)
        {
            if (string.Equals("Structure", element.Name.ToString(), StringComparison.OrdinalIgnoreCase))
            {
                return(IsWallUpgrade);
            }

            string identifier = element.GetAttributeString("identifier", string.Empty);

            if (string.IsNullOrWhiteSpace(identifier))
            {
                return(false);
            }

            ItemPrefab?item = ItemPrefab.Find(null, identifier);

            if (item == null)
            {
                return(false);
            }

            string[] disallowedUpgrades = element.GetAttributeStringArray("disallowedupgrades", new string[0]);

            if (disallowedUpgrades.Any(s => s.Equals(Identifier, StringComparison.OrdinalIgnoreCase) || s.Equals(prefab.Identifier, StringComparison.OrdinalIgnoreCase)))
            {
                return(false);
            }

            return(item.GetAllowedUpgrades().Contains(Identifier) ||
                   ItemTags.Any(tag => item.Tags.Contains(tag) || item.Identifier.Equals(tag, StringComparison.OrdinalIgnoreCase)));
        }
Exemple #2
0
        public void Init()
        {
            NPCSet.LoadSets();
            FactionPrefab.LoadFactions();
            CharacterPrefab.LoadAll();
            MissionPrefab.Init();
            TraitorMissionPrefab.Init();
            MapEntityPrefab.Init();
            MapGenerationParams.Init();
            LevelGenerationParams.LoadPresets();
            CaveGenerationParams.LoadPresets();
            OutpostGenerationParams.LoadPresets();
            EventSet.LoadPrefabs();
            Order.Init();
            EventManagerSettings.Init();
            ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
            AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
            SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
            StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
            UpgradePrefab.LoadAll(GetFilesOfType(ContentType.UpgradeModules));
            JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
            CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));
            NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
            ItemAssemblyPrefab.LoadAll();
            LevelObjectPrefab.LoadAll();
            BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
            TalentPrefab.LoadAll(GetFilesOfType(ContentType.Talents));
            TalentTree.LoadAll(GetFilesOfType(ContentType.TalentTrees));

            GameModePreset.Init();
            DecalManager = new DecalManager();
            LocationType.Init();

            SubmarineInfo.RefreshSavedSubs();

            Screen.SelectNull();

            NetLobbyScreen = new NetLobbyScreen();

            CheckContentPackage();
        }
        public UpgradePrice(UpgradePrefab prefab, XElement element)
        {
            Prefab = prefab;

            IncreaseLow = UpgradePrefab.ParsePercentage(element.GetAttributeString("increaselow", string.Empty),
                                                        "IncreaseLow", element, suppressWarnings: prefab.SuppressWarnings);

            IncreaseHigh = UpgradePrefab.ParsePercentage(element.GetAttributeString("increasehigh", string.Empty),
                                                         "IncreaseHigh", element, suppressWarnings: prefab.SuppressWarnings);

            BasePrice = element.GetAttributeInt("baseprice", -1);

            if (BasePrice == -1)
            {
                if (prefab.SuppressWarnings)
                {
                    DebugConsole.AddWarning($"Price attribute \"baseprice\" is not defined for {prefab?.Identifier}.\n " +
                                            "The value has been assumed to be '1000'.");
                    BasePrice = 1000;
                }
            }
        }
 static bool IsOverMaxLevel(int level, UpgradePrefab prefab) => level > prefab.MaxLevel;
 public void Deconstruct(out UpgradePrefab prefab, out UpgradeCategory category, out int level)
 {
     prefab   = Prefab;
     category = Category;
     level    = Level;
 }
 public PurchasedUpgrade(UpgradePrefab upgradePrefab, UpgradeCategory category, int level = 1)
 {
     Category = category;
     Prefab   = upgradePrefab;
     Level    = level;
 }
        public void PurchaseUpgrade(UpgradePrefab prefab, UpgradeCategory category)
        {
            if (!CanUpgradeSub())
            {
                DebugConsole.ThrowError("Cannot upgrade when switching to another submarine.");
                return;
            }

            int price        = prefab.Price.GetBuyprice(GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation);
            int currentLevel = GetUpgradeLevel(prefab, category);

            if (currentLevel + 1 > prefab.MaxLevel)
            {
                DebugConsole.ThrowError($"Tried to purchase \"{prefab.Name}\" over the max level! ({currentLevel + 1} > {prefab.MaxLevel}). The transaction has been cancelled.");
                return;
            }

            if (price < 0)
            {
                Location?location = Campaign.Map?.CurrentLocation;
                LogError($"Upgrade price is less than 0! ({price})",
                         new Dictionary <string, object?>
                {
                    { "Level", currentLevel },
                    { "Saved Level", GetRealUpgradeLevel(prefab, category) },
                    { "Upgrade", $"{category.Identifier}.{prefab.Identifier}" },
                    { "Location", location?.Type },
                    { "Reputation", $"{location?.Reputation?.Value} / {location?.Reputation?.MaxReputation}" },
                    { "Base Price", prefab.Price.BasePrice }
                });
            }

            if (Campaign.Money > price)
            {
                if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
                {
                    // only make the NPC speak if more than 5 minutes have passed since the last purchased service
                    if (lastUpgradeSpeak == DateTime.MinValue || lastUpgradeSpeak.AddMinutes(5) < DateTime.Now)
                    {
                        UpgradeNPCSpeak(TextManager.Get("Dialog.UpgradePurchased"), Campaign.IsSinglePlayer);
                        lastUpgradeSpeak = DateTime.Now;
                    }
                }

                Campaign.Money -= price;
                spentMoney     += price;

                PurchasedUpgrade?upgrade = FindMatchingUpgrade(prefab, category);

#if CLIENT
                DebugLog($"CLIENT: Purchased level {GetUpgradeLevel(prefab, category) + 1} {category.Name}.{prefab.Name} for ${price}", GUI.Style.Orange);
#endif

                if (upgrade == null)
                {
                    PendingUpgrades.Add(new PurchasedUpgrade(prefab, category));
                }
                else
                {
                    upgrade.Level++;
                }
#if CLIENT
                // tell the server that this item is yet to be paid for server side
                PurchasedUpgrades.Add(new PurchasedUpgrade(prefab, category));
#endif
                OnUpgradesChanged?.Invoke();
            }
            else
            {
                DebugConsole.ThrowError("Tried to purchase an upgrade with insufficient funds, the transaction has not been completed.\n" +
                                        $"Upgrade: {prefab.Name}, Cost: {price}, Have: {Campaign.Money}");
            }
        }
        //static because we may need to instantiate the campaign if it hasn't been done yet
        public static void ClientRead(IReadMessage msg)
        {
            bool   isFirstRound         = msg.ReadBoolean();
            byte   campaignID           = msg.ReadByte();
            UInt16 updateID             = msg.ReadUInt16();
            UInt16 saveID               = msg.ReadUInt16();
            string mapSeed              = msg.ReadString();
            UInt16 currentLocIndex      = msg.ReadUInt16();
            UInt16 selectedLocIndex     = msg.ReadUInt16();
            byte   selectedMissionIndex = msg.ReadByte();
            bool   allowDebugTeleport   = msg.ReadBoolean();
            float? reputation           = null;

            if (msg.ReadBoolean())
            {
                reputation = msg.ReadSingle();
            }

            Dictionary <string, float> factionReps = new Dictionary <string, float>();
            byte factionsCount = msg.ReadByte();

            for (int i = 0; i < factionsCount; i++)
            {
                factionReps.Add(msg.ReadString(), msg.ReadSingle());
            }

            bool forceMapUI = msg.ReadBoolean();

            int  money = msg.ReadInt32();
            bool purchasedHullRepairs  = msg.ReadBoolean();
            bool purchasedItemRepairs  = msg.ReadBoolean();
            bool purchasedLostShuttles = msg.ReadBoolean();

            byte missionCount = msg.ReadByte();
            List <Pair <string, byte> > availableMissions = new List <Pair <string, byte> >();

            for (int i = 0; i < missionCount; i++)
            {
                string missionIdentifier = msg.ReadString();
                byte   connectionIndex   = msg.ReadByte();
                availableMissions.Add(new Pair <string, byte>(missionIdentifier, connectionIndex));
            }

            UInt16?storeBalance = null;

            if (msg.ReadBoolean())
            {
                storeBalance = msg.ReadUInt16();
            }

            UInt16 buyCrateItemCount           = msg.ReadUInt16();
            List <PurchasedItem> buyCrateItems = new List <PurchasedItem>();

            for (int i = 0; i < buyCrateItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                int    itemQuantity         = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
                buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
            }

            UInt16 purchasedItemCount           = msg.ReadUInt16();
            List <PurchasedItem> purchasedItems = new List <PurchasedItem>();

            for (int i = 0; i < purchasedItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                int    itemQuantity         = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
                purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
            }

            UInt16          soldItemCount = msg.ReadUInt16();
            List <SoldItem> soldItems     = new List <SoldItem>();

            for (int i = 0; i < soldItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                UInt16 id       = msg.ReadUInt16();
                bool   removed  = msg.ReadBoolean();
                byte   sellerId = msg.ReadByte();
                soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId));
            }

            ushort pendingUpgradeCount = msg.ReadUInt16();
            List <PurchasedUpgrade> pendingUpgrades = new List <PurchasedUpgrade>();

            for (int i = 0; i < pendingUpgradeCount; i++)
            {
                string          upgradeIdentifier  = msg.ReadString();
                UpgradePrefab   prefab             = UpgradePrefab.Find(upgradeIdentifier);
                string          categoryIdentifier = msg.ReadString();
                UpgradeCategory category           = UpgradeCategory.Find(categoryIdentifier);
                int             upgradeLevel       = msg.ReadByte();
                if (prefab == null || category == null)
                {
                    continue;
                }
                pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
            }

            bool          hasCharacterData = msg.ReadBoolean();
            CharacterInfo myCharacterInfo  = null;

            if (hasCharacterData)
            {
                myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
            }

            if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
            {
                string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);

                GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, mapSeed);
                campaign             = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
                campaign.CampaignID  = campaignID;
                GameMain.NetLobbyScreen.ToggleCampaignMode(true);
            }

            //server has a newer save file
            if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
            {
                campaign.PendingSaveID = saveID;
            }

            if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
            {
                campaign.SuppressStateSending = true;
                campaign.IsFirstRound         = isFirstRound;

                //we need to have the latest save file to display location/mission/store
                if (campaign.LastSaveID == saveID)
                {
                    campaign.ForceMapUI = forceMapUI;

                    UpgradeStore.WaitForServerUpdate = false;

                    campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
                    campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
                    campaign.Map.SelectMission(selectedMissionIndex);
                    campaign.Map.AllowDebugTeleport = allowDebugTeleport;
                    campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
                    campaign.CargoManager.SetPurchasedItems(purchasedItems);
                    campaign.CargoManager.SetSoldItems(soldItems);
                    if (storeBalance.HasValue)
                    {
                        campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value;
                    }
                    campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
                    campaign.UpgradeManager.PurchasedUpgrades.Clear();

                    foreach (var(identifier, rep) in factionReps)
                    {
                        Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));
                        if (faction?.Reputation != null)
                        {
                            faction.Reputation.Value = rep;
                        }
                        else
                        {
                            DebugConsole.ThrowError($"Received an update for a faction that doesn't exist \"{identifier}\".");
                        }
                    }

                    if (reputation.HasValue)
                    {
                        campaign.Map.CurrentLocation.Reputation.Value = reputation.Value;
                        campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
                    }

                    foreach (var availableMission in availableMissions)
                    {
                        MissionPrefab missionPrefab = MissionPrefab.List.Find(mp => mp.Identifier == availableMission.First);
                        if (missionPrefab == null)
                        {
                            DebugConsole.ThrowError($"Error when receiving campaign data from the server: mission prefab \"{availableMission.First}\" not found.");
                            continue;
                        }
                        if (availableMission.Second < 0 || availableMission.Second >= campaign.Map.CurrentLocation.Connections.Count)
                        {
                            DebugConsole.ThrowError($"Error when receiving campaign data from the server: connection index for mission \"{availableMission.First}\" out of range (index: {availableMission.Second}, current location: {campaign.Map.CurrentLocation.Name}, connections: {campaign.Map.CurrentLocation.Connections.Count}).");
                            continue;
                        }
                        LocationConnection connection = campaign.Map.CurrentLocation.Connections[availableMission.Second];
                        campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
                    }

                    GameMain.NetLobbyScreen.ToggleCampaignMode(true);
                }

                bool shouldRefresh = campaign.Money != money ||
                                     campaign.PurchasedHullRepairs != purchasedHullRepairs ||
                                     campaign.PurchasedItemRepairs != purchasedItemRepairs ||
                                     campaign.PurchasedLostShuttles != purchasedLostShuttles;

                campaign.Money = money;
                campaign.PurchasedHullRepairs  = purchasedHullRepairs;
                campaign.PurchasedItemRepairs  = purchasedItemRepairs;
                campaign.PurchasedLostShuttles = purchasedLostShuttles;

                if (shouldRefresh)
                {
                    campaign?.CampaignUI?.UpgradeStore?.RefreshAll();
                }

                if (myCharacterInfo != null)
                {
                    GameMain.Client.CharacterInfo = myCharacterInfo;
                    GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo);
                }
                else
                {
                    GameMain.NetLobbyScreen.SetCampaignCharacterInfo(null);
                }

                campaign.lastUpdateID         = updateID;
                campaign.SuppressStateSending = false;
            }
        }
        public void ServerRead(IReadMessage msg, Client sender)
        {
            UInt16 currentLocIndex  = msg.ReadUInt16();
            UInt16 selectedLocIndex = msg.ReadUInt16();

            byte       selectedMissionCount   = msg.ReadByte();
            List <int> selectedMissionIndices = new List <int>();

            for (int i = 0; i < selectedMissionCount; i++)
            {
                selectedMissionIndices.Add(msg.ReadByte());
            }

            bool purchasedHullRepairs  = msg.ReadBoolean();
            bool purchasedItemRepairs  = msg.ReadBoolean();
            bool purchasedLostShuttles = msg.ReadBoolean();

            UInt16 buyCrateItemCount           = msg.ReadUInt16();
            List <PurchasedItem> buyCrateItems = new List <PurchasedItem>();

            for (int i = 0; i < buyCrateItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                int    itemQuantity         = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
                buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
            }

            UInt16 purchasedItemCount           = msg.ReadUInt16();
            List <PurchasedItem> purchasedItems = new List <PurchasedItem>();

            for (int i = 0; i < purchasedItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                int    itemQuantity         = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
                purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
            }

            UInt16          soldItemCount = msg.ReadUInt16();
            List <SoldItem> soldItems     = new List <SoldItem>();

            for (int i = 0; i < soldItemCount; i++)
            {
                string itemPrefabIdentifier = msg.ReadString();
                UInt16 id       = msg.ReadUInt16();
                bool   removed  = msg.ReadBoolean();
                byte   sellerId = msg.ReadByte();
                soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId));
            }

            ushort purchasedUpgradeCount = msg.ReadUInt16();
            List <PurchasedUpgrade> purchasedUpgrades = new List <PurchasedUpgrade>();

            for (int i = 0; i < purchasedUpgradeCount; i++)
            {
                string        upgradeIdentifier = msg.ReadString();
                UpgradePrefab prefab            = UpgradePrefab.Find(upgradeIdentifier);

                string          categoryIdentifier = msg.ReadString();
                UpgradeCategory category           = UpgradeCategory.Find(categoryIdentifier);

                int upgradeLevel = msg.ReadByte();

                if (category == null || prefab == null)
                {
                    continue;
                }
                purchasedUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
            }

            ushort purchasedItemSwapCount = msg.ReadUInt16();
            List <PurchasedItemSwap> purchasedItemSwaps = new List <PurchasedItemSwap>();

            for (int i = 0; i < purchasedItemSwapCount; i++)
            {
                UInt16 itemToRemoveID = msg.ReadUInt16();
                Item   itemToRemove   = Entity.FindEntityByID(itemToRemoveID) as Item;

                string     itemToInstallIdentifier = msg.ReadString();
                ItemPrefab itemToInstall           = string.IsNullOrEmpty(itemToInstallIdentifier) ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);

                if (itemToRemove == null)
                {
                    continue;
                }

                purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall));
            }

            if (!AllowedToManageCampaign(sender))
            {
                DebugConsole.ThrowError("Client \"" + sender.Name + "\" does not have a permission to manage the campaign");
                return;
            }

            Location location            = Map.CurrentLocation;
            int      hullRepairCost      = location?.GetAdjustedMechanicalCost(HullRepairCost) ?? HullRepairCost;
            int      itemRepairCost      = location?.GetAdjustedMechanicalCost(ItemRepairCost) ?? ItemRepairCost;
            int      shuttleRetrieveCost = location?.GetAdjustedMechanicalCost(ShuttleReplaceCost) ?? ShuttleReplaceCost;

            if (purchasedHullRepairs != this.PurchasedHullRepairs)
            {
                if (purchasedHullRepairs && Money >= hullRepairCost)
                {
                    this.PurchasedHullRepairs = true;
                    Money -= hullRepairCost;
                }
                else if (!purchasedHullRepairs)
                {
                    this.PurchasedHullRepairs = false;
                    Money += hullRepairCost;
                }
            }
            if (purchasedItemRepairs != this.PurchasedItemRepairs)
            {
                if (purchasedItemRepairs && Money >= itemRepairCost)
                {
                    this.PurchasedItemRepairs = true;
                    Money -= itemRepairCost;
                }
                else if (!purchasedItemRepairs)
                {
                    this.PurchasedItemRepairs = false;
                    Money += itemRepairCost;
                }
            }
            if (purchasedLostShuttles != this.PurchasedLostShuttles)
            {
                if (GameMain.GameSession?.SubmarineInfo != null &&
                    GameMain.GameSession.SubmarineInfo.LeftBehindSubDockingPortOccupied)
                {
                    GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("ReplaceShuttleDockingPortOccupied"), sender, ChatMessageType.MessageBox);
                }
                else if (purchasedLostShuttles && Money >= shuttleRetrieveCost)
                {
                    this.PurchasedLostShuttles = true;
                    Money -= shuttleRetrieveCost;
                }
                else if (!purchasedItemRepairs)
                {
                    this.PurchasedLostShuttles = false;
                    Money += shuttleRetrieveCost;
                }
            }

            if (currentLocIndex < Map.Locations.Count && Map.AllowDebugTeleport)
            {
                Map.SetLocation(currentLocIndex);
            }

            Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
            if (Map.SelectedLocation == null)
            {
                Map.SelectRandomLocation(preferUndiscovered: true);
            }
            if (Map.SelectedConnection != null)
            {
                Map.SelectMission(selectedMissionIndices);
            }

            CheckTooManyMissions(Map.CurrentLocation, sender);

            List <PurchasedItem> currentBuyCrateItems = new List <PurchasedItem>(CargoManager.ItemsInBuyCrate);

            currentBuyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, -i.Quantity));
            buyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, i.Quantity));

            CargoManager.SellBackPurchasedItems(new List <PurchasedItem>(CargoManager.PurchasedItems));
            CargoManager.PurchaseItems(purchasedItems, false);

            // for some reason CargoManager.SoldItem is never cleared by the server, I've added a check to SellItems that ignores all
            // sold items that are removed so they should be discarded on the next message
            CargoManager.BuyBackSoldItems(new List <SoldItem>(CargoManager.SoldItems));
            CargoManager.SellItems(soldItems);

            foreach (var(prefab, category, _) in purchasedUpgrades)
            {
                UpgradeManager.PurchaseUpgrade(prefab, category);

                // unstable logging
                int price = prefab.Price.GetBuyprice(UpgradeManager.GetUpgradeLevel(prefab, category), Map?.CurrentLocation);
                int level = UpgradeManager.GetUpgradeLevel(prefab, category);
                GameServer.Log($"SERVER: Purchased level {level} {category.Identifier}.{prefab.Identifier} for {price}", ServerLog.MessageType.ServerMessage);
            }

            foreach (var purchasedItemSwap in purchasedItemSwaps)
            {
                if (purchasedItemSwap.ItemToInstall == null)
                {
                    UpgradeManager.CancelItemSwap(purchasedItemSwap.ItemToRemove);
                }
                else
                {
                    UpgradeManager.PurchaseItemSwap(purchasedItemSwap.ItemToRemove, purchasedItemSwap.ItemToInstall);
                }
            }
            foreach (Item item in Item.ItemList)
            {
                if (item.PendingItemSwap != null && !purchasedItemSwaps.Any(it => it.ItemToRemove == item))
                {
                    UpgradeManager.CancelItemSwap(item);
                    item.PendingItemSwap = null;
                }
            }
        }
Exemple #10
0
        private IEnumerable <object> Load(bool isSeparateThread)
        {
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
            }

            while (TitleScreen.WaitForLanguageSelection)
            {
                yield return(CoroutineStatus.Running);
            }

            SoundManager = new Sounds.SoundManager();
            SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume, 0);
            SoundManager.SetCategoryGainMultiplier("voip", Math.Min(Config.VoiceChatVolume, 1.0f), 0);

            if (Config.EnableSplashScreen && !ConsoleArguments.Contains("-skipintro"))
            {
                var   pendingSplashScreens = TitleScreen.PendingSplashScreens;
                float baseVolume           = MathHelper.Clamp(Config.SoundVolume * 2.0f, 0.0f, 1.0f);
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_UTG.webm", baseVolume * 0.5f));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_FF.webm", baseVolume));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.1f));
            }

            //if not loading in a separate thread, wait for the splash screens to finish before continuing the loading
            //otherwise the videos will look extremely choppy
            if (!isSeparateThread)
            {
                while (TitleScreen.PlayingSplashScreen || TitleScreen.PendingSplashScreens.Count > 0)
                {
                    yield return(CoroutineStatus.Running);
                }
            }

            GUI.Init(Window, Config.AllEnabledPackages, GraphicsDevice);
            DebugConsole.Init();

            if (Config.AutoUpdateWorkshopItems)
            {
                Config.WaitingForAutoUpdate = true;
                TaskPool.Add("AutoUpdateWorkshopItemsAsync",
                             SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
                {
                    bool result = ((Task <bool>)task).Result;

                    Config.WaitingForAutoUpdate = false;
                });

                while (Config.WaitingForAutoUpdate)
                {
                    yield return(CoroutineStatus.Running);
                }
            }

#if DEBUG
            if (Config.ModBreakerMode)
            {
                Config.SelectCorePackage(ContentPackage.CorePackages.GetRandom());
                foreach (var regularPackage in ContentPackage.RegularPackages)
                {
                    if (Rand.Range(0.0, 1.0) <= 0.5)
                    {
                        Config.EnableRegularPackage(regularPackage);
                    }
                    else
                    {
                        Config.DisableRegularPackage(regularPackage);
                    }
                }
                ContentPackage.SortContentPackages(p =>
                {
                    return(Rand.Int(int.MaxValue));
                });
            }
#endif

            if (Config.AllEnabledPackages.None())
            {
                DebugConsole.Log("No content packages selected");
            }
            else
            {
                DebugConsole.Log("Selected content packages: " + string.Join(", ", Config.AllEnabledPackages.Select(cp => cp.Name)));
            }

#if DEBUG
            GameSettings.ShowUserStatisticsPrompt = false;
            GameSettings.SendUserStatistics       = false;
#endif

            InitUserStats();

            yield return(CoroutineStatus.Running);

            Debug.WriteLine("sounds");

            int i = 0;
            foreach (object crObj in SoundPlayer.Init())
            {
                CoroutineStatus status = (CoroutineStatus)crObj;
                if (status == CoroutineStatus.Success)
                {
                    break;
                }

                i++;
                TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
                                        1.0f :
                                        Math.Min(40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 40.0f);

                yield return(CoroutineStatus.Running);
            }

            TitleScreen.LoadState = 40.0f;
            yield return(CoroutineStatus.Running);

            LightManager = new Lights.LightManager(base.GraphicsDevice, Content);

            TitleScreen.LoadState = 41.0f;
            yield return(CoroutineStatus.Running);

            GUI.LoadContent();
            TitleScreen.LoadState = 42.0f;

            yield return(CoroutineStatus.Running);

            TaskPool.Add("InitRelayNetworkAccess", SteamManager.InitRelayNetworkAccess(), (t) => { });

            FactionPrefab.LoadFactions();
            NPCSet.LoadSets();
            CharacterPrefab.LoadAll();
            MissionPrefab.Init();
            TraitorMissionPrefab.Init();
            MapEntityPrefab.Init();
            Tutorials.Tutorial.Init();
            MapGenerationParams.Init();
            LevelGenerationParams.LoadPresets();
            CaveGenerationParams.LoadPresets();
            OutpostGenerationParams.LoadPresets();
            WreckAIConfig.LoadAll();
            EventSet.LoadPrefabs();
            ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
            AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
            SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
            Order.Init();
            EventManagerSettings.Init();
            BallastFloraPrefab.LoadAll(GetFilesOfType(ContentType.MapCreature));
            HintManager.Init();
            TitleScreen.LoadState = 50.0f;
            yield return(CoroutineStatus.Running);

            StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
            TitleScreen.LoadState = 55.0f;
            yield return(CoroutineStatus.Running);

            UpgradePrefab.LoadAll(GetFilesOfType(ContentType.UpgradeModules));
            TitleScreen.LoadState = 56.0f;
            yield return(CoroutineStatus.Running);

            JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
            CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));

            NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));

            ItemAssemblyPrefab.LoadAll();
            TitleScreen.LoadState = 60.0f;
            yield return(CoroutineStatus.Running);

            GameModePreset.Init();

            SaveUtil.DeleteDownloadedSubs();
            SubmarineInfo.RefreshSavedSubs();

            TitleScreen.LoadState = 65.0f;
            yield return(CoroutineStatus.Running);

            GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);

            TitleScreen.LoadState = 68.0f;
            yield return(CoroutineStatus.Running);

            MainMenuScreen   = new MainMenuScreen(this);
            ServerListScreen = new ServerListScreen();

            TitleScreen.LoadState = 70.0f;
            yield return(CoroutineStatus.Running);

#if USE_STEAM
            SteamWorkshopScreen = new SteamWorkshopScreen();
            if (SteamManager.IsInitialized)
            {
                Steamworks.SteamFriends.OnGameRichPresenceJoinRequested += OnInvitedToGame;
                Steamworks.SteamFriends.OnGameLobbyJoinRequested        += OnLobbyJoinRequested;
            }
#endif

            SubEditorScreen = new SubEditorScreen();

            TitleScreen.LoadState = 75.0f;
            yield return(CoroutineStatus.Running);

            ParticleEditorScreen = new ParticleEditorScreen();

            TitleScreen.LoadState = 80.0f;
            yield return(CoroutineStatus.Running);

            LevelEditorScreen     = new LevelEditorScreen();
            SpriteEditorScreen    = new SpriteEditorScreen();
            EventEditorScreen     = new EventEditorScreen();
            CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();
            CampaignEndScreen     = new CampaignEndScreen();

            yield return(CoroutineStatus.Running);

            TitleScreen.LoadState = 85.0f;
            ParticleManager       = new ParticleManager(GameScreen.Cam);
            ParticleManager.LoadPrefabs();
            TitleScreen.LoadState = 88.0f;
            LevelObjectPrefab.LoadAll();

            TitleScreen.LoadState = 90.0f;
            yield return(CoroutineStatus.Running);

            DecalManager = new DecalManager();
            LocationType.Init();
            MainMenuScreen.Select();

            foreach (string steamError in SteamManager.InitializationErrors)
            {
                new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
            }

            TitleScreen.LoadState = 100.0f;
            hasLoaded             = true;
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
            }
            yield return(CoroutineStatus.Success);
        }
Exemple #11
0
        private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color?overrideColor = null)
        {
            Color connectionColor;

            if (GameMain.DebugDraw)
            {
                float sizeFactor = MathUtils.InverseLerp(
                    generationParams.SmallLevelConnectionLength,
                    generationParams.LargeLevelConnectionLength,
                    connection.Length);
                connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, GUI.Style.Orange, GUI.Style.Red);
            }
            else if (overrideColor.HasValue)
            {
                connectionColor = overrideColor.Value;
            }
            else
            {
                connectionColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
            }

            int width = (int)(generationParams.LocationConnectionWidth * zoom);

            if (Level.Loaded?.LevelData == connection.LevelData)
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width           = (int)(width * 1.5f);
            }
            if (SelectedLocation != CurrentDisplayLocation &&
                (connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }
            else if (HighlightedLocation != CurrentDisplayLocation &&
                     (connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }

            Vector2 rectCenter = viewArea.Center.ToVector2();

            int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
            int endIndex   = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;

            Vector2?connectionStart = null;
            Vector2?connectionEnd   = null;

            for (int i = startIndex; i < endIndex; i++)
            {
                var segment = connection.CrackSegments[i];

                Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                if (!connectionStart.HasValue)
                {
                    connectionStart = start;
                }
                Vector2 end = rectCenter + (segment[1] + viewOffset) * zoom;
                connectionEnd = end;

                if (!viewArea.Contains(start) && !viewArea.Contains(end))
                {
                    continue;
                }
                else
                {
                    if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
                    {
                        if (!viewArea.Contains(start))
                        {
                            start = intersection;
                        }
                        else
                        {
                            end = intersection;
                        }
                    }
                }

                float a = 1.0f;
                if (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)
                {
                    if (IsInFogOfWar(connection.Locations[0]))
                    {
                        a = (float)i / connection.CrackSegments.Count;
                    }
                    else if (IsInFogOfWar(connection.Locations[1]))
                    {
                        a = 1.0f - (float)i / connection.CrackSegments.Count;
                    }
                }
                float dist             = Vector2.Distance(start, end);
                var   connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
                spriteBatch.Draw(connectionSprite.Texture,
                                 new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                 connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
                                 new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
            }
            if (connectionStart.HasValue && connectionEnd.HasValue)
            {
                GUIComponentStyle crushDepthWarningIconStyle = null;
                string            tooltip = null;
                var subCrushDepth         = Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth;
                if (GameMain.GameSession?.Campaign?.UpgradeManager != null)
                {
                    var hullUpgradePrefab = UpgradePrefab.Find("increasewallhealth");
                    if (hullUpgradePrefab != null)
                    {
                        int pendingLevel = GameMain.GameSession.Campaign.UpgradeManager.GetUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
                        int currentLevel = GameMain.GameSession.Campaign.UpgradeManager.GetRealUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
                        if (pendingLevel > currentLevel)
                        {
                            string updateValueStr = hullUpgradePrefab.SourceElement?.Element("Structure")?.GetAttributeString("crushdepth", null);
                            if (!string.IsNullOrEmpty(updateValueStr))
                            {
                                subCrushDepth = PropertyReference.CalculateUpgrade(subCrushDepth, pendingLevel - currentLevel, updateValueStr);
                            }
                        }
                    }
                }

                if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > subCrushDepth)
                {
                    crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningHighIcon");
                    tooltip = "crushdepthwarninghigh";
                }
                else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > subCrushDepth)
                {
                    crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningLowIcon");
                    tooltip = "crushdepthwarninglow";
                }

                if (crushDepthWarningIconStyle != null)
                {
                    Vector2 iconPos  = (connectionStart.Value + connectionEnd.Value) / 2;
                    float   iconSize = 32.0f * GUI.Scale;
                    bool    mouseOn  = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
                    Sprite  crushDepthWarningIcon = crushDepthWarningIconStyle.GetDefaultSprite();
                    crushDepthWarningIcon.Draw(spriteBatch, iconPos,
                                               mouseOn ? crushDepthWarningIconStyle.HoverColor : crushDepthWarningIconStyle.Color,
                                               scale: iconSize / crushDepthWarningIcon.size.X);
                    if (mouseOn)
                    {
                        connectionTooltip = new Pair <Rectangle, string>(
                            new Rectangle(iconPos.ToPoint(), new Point((int)iconSize)),
                            TextManager.Get(tooltip)
                            .Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString())
                            .Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString()));
                    }
                }
            }

            if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
            {
                Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                if (viewArea.Contains(center) && connection.Biome != null)
                {
                    GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
                }
            }
        }