Иконка ресурса

FREE CustomLoot : 1.0.8 1.0.8

Нет прав для скачивания
C#:
using System;
using System.Linq;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using UnityEngine;
using System.Collections;
namespace Oxide.Plugins {
    //New per-item options for blueprint chance, min/max condition, and skins.
    //Fixed BP chance issue reported by FuelStream.
    //Extra try/catch when loading loottable data.
    [Info("CustomLoot", "Steenamaroo", "1.0.8", ResourceId = 0)]
    [Description("Custom loot table plugin for NPCPlayer and HTNPlayer corpses, crates, and containers.")]
    public class CustomLoot : RustPlugin {
#region Declarations
        [PluginReference]
        Plugin BotSpawn;
        bool loaded;
        static CustomLoot cl;
        public bool defaultwarned = false;
        List<string> LootTableNames = new List<string>();
        public System.Random random = new System.Random();
        public ItemDefinition water = ItemManager.FindItemDefinition("water");
        Dictionary<string, LootTable> LootTables = new Dictionary<string, LootTable>();
        Dictionary<string, Dictionary<int, string>> BalancedCategories = new Dictionary<string, Dictionary<int, string>>();
        Dictionary<string, Dictionary<string, Dictionary<int, KeyValuePair<string, lootData>>>> BalancedItems = new Dictionary<string, Dictionary<string, Dictionary<int, KeyValuePair<string, lootData>>>>();
        Dictionary<string, List<ulong>> BotSpawnBots = new Dictionary<string, List<ulong>>();
        public List<LootContainer> AllContainers = new List<LootContainer>();
        public Dictionary<string, Settings> ContainerTypesFromGame = new Dictionary<string, Settings>();
        public Dictionary<string, CategorySettings> GotCategories = new Dictionary<string, CategorySettings>();
        public Dictionary<string, Dictionary<string, lootData>> GotLootTypes = new Dictionary<string, Dictionary<string, lootData>>();
        public Dictionary<string, List<ulong>> BotTypes = new Dictionary<string, List<ulong>>();
        BackupData backupData;
        public GameObject monoHost;
        FillMono fillMono;
#endregion
        [ConsoleCommand("Repop")]
        private void Repop(ConsoleSystem.Arg arg) {
            var player = arg?.Connection?.player as BasePlayer;
            if (player == null || IsAuth(player)) foreach (var group in SpawnHandler.Instance.SpawnGroups) group.Fill();
        }
#region Hooks
        void OnServerInitialized() {
            BalancedCategories = new Dictionary<string, Dictionary<int, string>>();
            BalancedItems = new Dictionary<string, Dictionary<string, Dictionary<int, KeyValuePair<string, lootData>>>>();
            GotCategories = new Dictionary<string, CategorySettings>();
            ContainerTypesFromGame = new Dictionary<string, Settings>();
            GotLootTypes = new Dictionary<string, Dictionary<string, lootData>>();
            BotTypes = new Dictionary<string, List<ulong>>();
            List<string> names = new List<string>();
            foreach (var entry in Resources.FindObjectsOfTypeAll<LootContainer>()) names.Add(entry.ShortPrefabName);
            names = names.Distinct().ToList();
            foreach (var entry in names) if (!entry.Contains("test") && !entry.Contains("stocking")) ContainerTypesFromGame.Add(entry, new Settings());
            cl = this;
            if (BotSpawn) RefreshBotSpawn();
            var cats = Enum.GetNames(typeof(ItemCategory)).ToList();
            List<string> exclude = new List<string> {
                "Search", "Favourite", "All", "Common"
            }
            ;
            monoHost = new GameObject();
            fillMono = monoHost.AddComponent<FillMono>();
            backupData = Interface.Oxide.DataFileSystem.ReadObject<BackupData>("CustomLoot/BotSpawnBackups");
            LoadConfigVariables();
            Interface.Oxide.DataFileSystem.WriteObject("CustomLoot/BotSpawnBackups", backupData);
            foreach (LootContainer container in UnityEngine.Object.FindObjectsOfType<LootContainer>()) if (configData.ContainerTypes.ContainsKey(container.ShortPrefabName) && configData.ContainerTypes[container.ShortPrefabName].enabled) ProcessContainer(container, true);
            timer.Once(5f, () => fillMono.StartCoroutine(fillMono.FillContainers(AllContainers)));
            loaded = true;
            foreach (BasePlayer player in UnityEngine.Object.FindObjectsOfType<BasePlayer>()) {
                if (player is NPCPlayerApex || player is HTNPlayer || player is global : : HumanNPC) AddToBotList(player);
            }
            foreach (var cat in cats.Where(cat => !exclude.Contains(cat))) {
                GotCategories.Add(cat, new CategorySettings());
                GotLootTypes.Add(cat, new Dictionary<string, lootData>());
            }
            foreach (var lT in LootTableNames.ToList()) {
                if (CreateLootTable(lT)) {
                    BalanceCategories(lT);
                    BalanceItems(lT);
                }
            }
        }
        void Unload() => UnityEngine.Object.Destroy(monoHost);
#endregion
#region ContainerTypes
        void ProcessContainer(LootContainer container, bool start) {
            if (Interface.CallHook("OnCustomLootContainer", container.net.ID) != null) return;
            if (container?.OwnerID != 0 && !(container is SupplyDrop)) return;
            if (start) AllContainers.Add(container);
            else PopulateContainer(container);
        }
        void PopulateContainer(LootContainer container) {
            if (container == null) return;
            if (container.ShortPrefabName != "heli_crate" && container.ShortPrefabName != "bradley_crate") {
                List<LootContainer> containers = new List<LootContainer>();
                Vis.Entities<LootContainer>(container.transform.position, 0.1f, containers);
                foreach (var cont in containers) {
                    if (cont == container) continue;
                    NextTick(() => container?.Kill());
                    return;
                }
            }
            timer.Once(1f, () => {
                if (container == null) return;
                container.inventory.capacity = 36;
                container.onlyAcceptCategory = ItemCategory.All;
                container.SendNetworkUpdateImmediate();
                var lootObj = MakeLoot(container.ShortPrefabName);
                if (lootObj == null) return;
                if (configData.ContainerTypes[container.ShortPrefabName].ClearContainerFirst) container.inventory.Clear();
                foreach (var item in lootObj as List<Item>) if (!item.MoveToContainer(container.GetComponent<StorageContainer>().inventory, -1, true)) item.Remove();
                else {
                    var vessel = item?.GetHeldEntity() as BaseLiquidVessel;
                    if (vessel != null && vessel.hasLid) {
                        int percentage = Mathf.Clamp(configData.ContainerTypes[container.ShortPrefabName].WaterPreFillPercent, 0, 100);
                        var stack = item?.info?.GetComponent<ItemModContainer>()?.maxStackSize;
                        if (percentage == 0 || stack == null) continue;
                        Item waterItem = ItemManager.Create(water, (int)(stack / 100f * percentage), 0);
                        if (!waterItem.MoveToContainer(item.contents, -1, true)) waterItem.Remove();
                    }
                }
            }
            );
        }
        void OnLootSpawn(LootContainer container) {
            if (!loaded) return;
            timer.Once(0.3f, () => {
                if (container == null) return;
                if (configData.ContainerTypes.ContainsKey(container.ShortPrefabName) && configData.ContainerTypes[container.ShortPrefabName].enabled) ProcessContainer(container, false);
            }
            );
        }
        public class FillMono : MonoBehaviour {
            public IEnumerator FillContainers(List<LootContainer> AllContainers) {
                foreach (var container in AllContainers) {
                    cl.PopulateContainer(container);
                    yield return new WaitForEndOfFrame();
                }
                cl.PrintWarning("Finished populating all containers.");
                yield return null;
            }
        }
#endregion ContainerTypes
#region Methods
        bool IsAuth(BasePlayer player) => player?.net?.connection != null && player.net.connection.authLevel == 2;
        Settings GetSettings(object record) {
            var outRecord = JsonConvert.SerializeObject(record);
            var response = JsonConvert.DeserializeObject<Settings>(outRecord);
            response.enabled = true;
            return response;
        }
#endregion
#region BotHandling
        void OnEntitySpawned(LootableCorpse corpse) {
            if (!loaded) return;
            timer.Once(0.3f, () => {
                if (corpse != null) {
                    ulong ID = corpse.playerSteamID;
                    string profile = string.Empty;
                    var path = configData.CorpseTypes;
                    foreach (var entry in BotTypes.Where(entry => entry.Value.Contains(corpse.playerSteamID))) profile = entry.Key;
                    if (profile == string.Empty) return;
                    if (configData.CorpseTypes[profile].ClearContainerFirst) corpse.containers[0].Clear();
                    var lootObj = MakeLoot(profile);
                    if (lootObj == null) return;
                    foreach (var item in lootObj as List<Item>) if (!item.MoveToContainer(corpse.containers[0], -1, true)) item.Remove();
                    else {
                        var vessel = item?.GetHeldEntity() as BaseLiquidVessel;
                        if (vessel != null && vessel.hasLid) {
                            int percentage = Mathf.Clamp(configData.CorpseTypes[profile].WaterPreFillPercent, 0, 100);
                            var stack = item?.info?.GetComponent<ItemModContainer>()?.maxStackSize;
                            if (percentage == 0 || stack == null) continue;
                            Item waterItem = ItemManager.Create(water, (int)(stack / 100f * percentage), 0);
                            if (!waterItem.MoveToContainer(item.contents, -1, true)) waterItem.Remove();
                        }
                    }
                    timer.Once(0.2f, () => RemoveFromMemory(ID));
                }
            }
            );
        }
        void OnEntitySpawned(BasePlayer player) {
            if (!loaded) return;
            timer.Once(0.1f, () =>  //delay for processing at BotSpawn end
            {
                if (player == null) return;
                if (BotSpawn && player is NPCPlayerApex) RefreshBotSpawn();
            }
            );
            timer.Once(0.3f, () => {
                if (player == null) return;
                if (player is NPCPlayer || player is HTNPlayer) {
                    AddToBotList(player);
                    return;
                }
            }
            );
        }
        void RefreshBotSpawn() => BotSpawnBots = (Dictionary<string, List<ulong>>)BotSpawn?.Call("BotSpawnBots");
        void AddToBotList(BasePlayer player) {
            if (Interface.CallHook("OnCustomLootNPC", player.net.ID) != null) return;
            foreach (var entry in names) if (player.PrefabName.Contains(entry.Key)) {
                ProcessNpc(player, entry.Value);
                return;
            }
            NPCPlayerApex npc = player as NPCPlayerApex;
            if (npc != null) {
                if (BotSpawn) foreach (var monument in BotSpawnBots.Where(monument => monument.Value.Contains(player.userID))) {
                    AddBotSpawn(npc, monument.Key);
                    return;
                }
                if (npc is NPCMurderer) ProcessNpc(player, "Murderer");
                else if (npc is Scientist) {
                    if (npc.GetFact(NPCPlayerApex.Facts.IsMilitaryTunnelLab) == 1) ProcessNpc(player, "MilitaryTunnelScientist");
                    else ProcessNpc(player, "Scientist");
                }
            }
            else if (player is global : : HumanNPC) {
                var name = player?.GetComponent<SpawnPointInstance>()?.parentSpawnPoint?.GetComponentInParent<PrefabParameters>()?.ToString();
                if (name != null) {
                    if (name.Contains("oilrig")) ProcessNpc(player, "OilRig");
                    else if (name.Contains("excavator")) ProcessNpc(player, "Excavator");
                }
            }
        }
        Dictionary<string, string> names = new Dictionary<string, string>() {
            {
                "oilrig", "OilRig"
            }
            , {
                "excavator", "Excavator"
            }
            , {
                "scientistpeacekeeper", "CompoundScientist"
            }
            , {
                "bandit_guard", "BanditTown"
            }
            , {
                "scientist_gunner", "MountedScientist"
            }
            , {
                "junkpile", "JunkPileScientist"
            }
            , {
                "scarecrow", "ScareCrow"
            }
            , {
                "scientist_full", "MilitaryTunnelScientist"
            }
            , {
                "scientist_turret", "CargoShip"
            }
            , {
                "scientist_astar", "CargoShip"
            }
            , {
                "heavyscientist", "HeavyScientist"
            }
            ,
        }
        ;
        void ProcessNpc(BasePlayer player, string NPCType) {
            var record = configData.CorpseTypes[NPCType];
            if (record == null) return;
            if (record.enabled) BotTypes[NPCType].Add(player.userID);
        }
        void AddBotSpawn(NPCPlayer npc, string monument) {
            if (configData.GlobalSettings.corpseTypePerBotSpawnProfile) {
                if (!BotTypes.ContainsKey("BotSpawn-" + monument)) OnServerInitialized();
                if (configData.CorpseTypes["BotSpawn-" + monument].enabled) BotTypes["BotSpawn-" + monument].Add(npc.userID);
            }
            else if (configData.CorpseTypes["BotSpawn"].enabled) BotTypes["BotSpawn"].Add(npc.userID);
        }
        void RemoveFromMemory(ulong userID) {
            foreach (var botList in BotTypes.Where(botList => botList.Value.Contains(userID))) {
                botList.Value.Remove(userID);
                break;
            }
        }
#endregion
#region LootHandling
        public void BalanceCategories(string lootTable) {
            int counter = 0;
            BalancedCategories.Add(lootTable, new Dictionary<int, string>());
            foreach (var category in LootTables[lootTable].Categories) {
                if (!HasValidItem(lootTable, category.Key)) continue;
                for (int i = 0; i < category.Value.probability; i++) {
                    BalancedCategories[lootTable].Add(counter, category.Key);
                    counter++;
                }
            }
        }
        public void BalanceItems(string lootTable) {
            BalancedItems.Add(lootTable, new Dictionary<string, Dictionary<int, KeyValuePair<string, lootData>>>());
            foreach (var category in LootTables[lootTable].LootTypes.Where(category => LootTables[lootTable].Categories[category.Key].probability > 0)) {
                int counter = 0;
                if (!HasValidItem(lootTable, category.Key)) continue;
                BalancedItems[lootTable].Add(category.Key, new Dictionary<int, KeyValuePair<string, lootData>>());
                foreach (var entry in category.Value) {
                    for (int i = 0; i < entry.Value.probability; i++) {
                        var blank = new KeyValuePair<string, lootData>(entry.Key, entry.Value);
                        BalancedItems[lootTable][category.Key].Add(counter, blank);
                        counter++;
                    }
                }
            }
        }
        public bool HasValidItem(string lootTable, string category) {
            if (LootTables[lootTable].LootTypes[category].Count == 0) return false;
            foreach (var item in LootTables[lootTable].LootTypes[category].Where(item => item.Value.probability > 0)) return true;
            return false;
        }
        private object MakeLoot(string config) {
            Settings settings = null;
            if (configData.CorpseTypes.ContainsKey(config)) settings = configData.CorpseTypes[config];
            else if (configData.ContainerTypes.ContainsKey(config)) settings = configData.ContainerTypes[config];
            else if (configData.API.ContainsKey(config)) settings = GetSettings(configData.API[config]);
            else {
                Puts("CustomLoot had a call for a profile that doesn't exist.");
                Puts($"Adding profile {config} using loottable 'default'.");
                configData.API.Add(config, new BaseSettings());
                SaveConfig(configData);
                settings = GetSettings(configData.API[config]);
            }
            if (settings == null) return null;
            string lootTable = settings.lootTable;
            if (!LootTableNames.Contains(lootTable)) return null;
            int safety = 0;
            int number = settings.maxItems;
            List<Item> newLoot = new List<Item>();
            if (settings.maxItems > settings.minItems) number = random.Next(settings.minItems, settings.maxItems);
            int BPs = 0;
            for (int i = 0; i < number; i++) {
                safety++;
                bool duplicate = false;
                if (safety > 50) {
                    break;
                }
                string category = GetCategory(lootTable);
                if (category == "zero") return null;
                Item item = null;
                bool forced = false;
                if (LootTables[lootTable].AlwaysSpawnList.Count >= i + 1) {
                    foreach (var cat in LootTables[lootTable].LootTypes) if (cat.Value.ContainsKey(LootTables[lootTable].AlwaysSpawnList[i])) {
                        forced = true;
                        item = GetItem(settings, cat.Key, BPs, LootTables[lootTable].AlwaysSpawnList[i]);
                    }
                }
                if (!forced) item = GetItem(settings, category, BPs, string.Empty);
                if (item == null) {
                    i--;
                    continue;
                }
                CategorySettings confPath = LootTables[lootTable].Categories[category];
                if (item.blueprintTarget != 0) BPs++;
                foreach (var newItem in newLoot) {
                    if (newItem.info.shortname == item.info.shortname && !configData.GlobalSettings.allowDuplicates) duplicate = true;
                    if (newItem.blueprintTarget != 0 && item.blueprintTarget != 0 && newItem.blueprintTarget == item.blueprintTarget && !configData.GlobalSettings.allowDuplicates) duplicate = true;
                }
                if (duplicate) {
                    item.Remove();
                    i--;
                    continue;
                }
                else {
                    if (category.ToString() == "Weapon" && !settings.noGuns) {
                        newLoot.Add(item);
                        if (settings.gunsWithAmmo && item.blueprintTarget == 0) {
                            string matchedAmmo = (item.GetHeldEntity() as BaseProjectile)?.primaryMagazine?.ammoType?.shortname;
                            var ammopath = LootTables[lootTable].LootTypes["Resources"]["lowgradefuel"];
                            int stack = random.Next(ammopath.minStack, ammopath.maxStack);
                            if (item.info.shortname != "flamethrower") {
                                if (matchedAmmo == null || !LootTables[lootTable].LootTypes["Ammunition"].ContainsKey(matchedAmmo)) continue;
                                ammopath = LootTables[lootTable].LootTypes["Ammunition"][matchedAmmo];
                                stack = random.Next(ammopath.minStack, ammopath.maxStack);
                            }
                            else matchedAmmo = "lowgradefuel";
                            if (stack > 10) stack = (stack / 10) * 10;
                            if (ammopath.probability > 0) {
                                Item ammoItem = ItemManager.CreateByName(matchedAmmo, stack);
                                newLoot.Add(ammoItem);
                                i++;
                            }
                        }
                    }
                    else if (category.ToString() != "Weapon") newLoot.Add(item);
                }
            }
            if (newLoot.Count > number) foreach (var entry in newLoot.Where(entry => entry.info.category.ToString() != "Weapon" && entry.info.category.ToString() != "Ammunition").ToList()) {
                entry.Remove();
                newLoot.Remove(entry);
                break;
            }
            return newLoot;
        }
        float GetCondition(int min, int max, float itemMax) {
            min = Mathf.Max(1, min);
            max = Mathf.Max(1, max);
            if (min >= max) {
                return itemMax / 100f * max;
            }
            return itemMax / 100f * random.Next(min, max);
        }
        public string GetCategory(string lootTable) {
            if (!BalancedCategories.ContainsKey(lootTable)) {
                Puts($"Balanced categories did not contain {lootTable}");
                return "zero";
            }
            if (BalancedCategories[lootTable].Count == 0) return "zero";
            int catnumber = random.Next(BalancedCategories[lootTable].Count);
            return BalancedCategories[lootTable][catnumber];
        }
        ItemDefinition bpb = ItemManager.FindItemDefinition("blueprintbase");
        public Item GetItem(Settings settings, string category, int BPs, string perma) {
            string lootTable = settings.lootTable;
            ulong skin = 0;
            Item item = new Item();
            List<ulong> skins = new List<ulong>();
            int chosenItem;
            string name = string.Empty;
            lootData path = null;
            if (perma != string.Empty) {
                name = perma;
                path = LootTables[lootTable].LootTypes[category][perma];
            }
            else {
                chosenItem = random.Next(BalancedItems[lootTable][category].Count);
                name = BalancedItems[lootTable][category]?[chosenItem].Key;
                path = BalancedItems[lootTable]?[category]?[chosenItem].Value;
            }
            if (name == string.Empty || path == null) return null;
            int stack = path.maxStack;
            if (path.minStack < path.maxStack) stack = random.Next(path.minStack, path.maxStack);
            if (path.skins.Count > 0) skins = path.skins;
            if (category == "Resources" && stack > 10) stack = (stack / 10) * 10;
            if (skins.Count != 0) skin = skins[random.Next(skins.Count)];
            item = ItemManager.CreateByName(name, stack, skin);
            if (item.info.condition.enabled) item.condition = GetCondition(path.MinConditionPercent, path.MaxConditionPercent, item.info.condition.max);
            CategorySettings confPath = LootTables[lootTable].Categories[category];
            ItemDefinition def = ItemManager.FindItemDefinition(item.info.itemid);
            if (confPath.allowBlueprints && random.Next(99) < path.blueprintChancePercent && item.info.Blueprint != null && IsBP(def)) {
                if (BPs == settings.MaxBps) return null;
                item.Remove();
                item = ItemManager.Create(bpb, 1, 0uL);
                item.blueprintTarget = def.itemid;
            }
            if (item == null) Puts($"Null-item spawn attempted. Please notify Author - '{name}'");
            return item;
        }
        bool IsBP(ItemDefinition def) => def?.Blueprint != null && def.Blueprint.isResearchable && !def.Blueprint.defaultBlueprint;
#endregion
#region Data
        public class BackupData {
            public Dictionary<string, Settings> BotSpawnBackups = new Dictionary<string, Settings>();
        }
        public class LootTable {
            public bool allowChristmas, allowHalloween, allowKeycards = false;
            public List<string> BlackList = new List<string>();
            public List<string> AlwaysSpawnList = new List<string>();
            public Dictionary<string, CategorySettings> Categories = cl.GotCategories.ToDictionary(pair => pair.Key, pair => pair.Value);
            public Dictionary<string, Dictionary<string, lootData>> LootTypes = cl.GotLootTypes.ToDictionary(pair => pair.Key, pair => pair.Value);
        }
        public class CategorySettings {
            public int probability;
            public bool allowBlueprints = true;
        }
        public class lootData {
            [JsonIgnore]
            public ItemDefinition item;
            [JsonProperty(Order = 1)]
            public int probability;
            [JsonProperty(Order = 2)]
            public int minStack = 1;
            [JsonProperty(Order = 3)]
            public int maxStack = 1;
            [JsonProperty(Order = 4)]
            public int blueprintChancePercent = 0;
            [JsonProperty(Order = 5)]
            public List<ulong> skins = new List<ulong>();
            [JsonProperty(Order = 6)]
            public int MinConditionPercent = 90;
            [JsonProperty(Order = 7)]
            public int MaxConditionPercent = 100;
            public bool ShouldSerializeblueprintChancePercent() => item != null && cl.IsBP(item);
            public bool ShouldSerializeskins() => item != null && item.HasSkins;
            public bool ShouldSerializeMaxConditionPercent()=>item != null && item.condition.enabled;
            public bool ShouldSerializeMinConditionPercent()=>item != null && item.condition.enabled;
        }
        public List<string> DefaultBlackList = new List<string> {
            "glue", "door.key", "note", "bleach", "ducttape", "blood", "tool.camera", "grenade.smoke", "ammo.rocket.smoke", "battery", "bone.fragments", "blueprintbase", "water.salt", "jackhammer"
        }
        ;
        public bool CreateLootTable(string lootTable) {
            try {
                LootTables[lootTable] = Interface.Oxide.DataFileSystem.ReadObject<LootTable>($"CustomLoot/{lootTable}");
            }
            catch {
                Puts($"There is an error in data file {lootTable}.");
                LootTableNames.Remove(lootTable);
                return false;
            }
            try {
                var catPath = string.Empty;
                var path = LootTables[lootTable];
                Dictionary<string, List<string>> itemCheck = new Dictionary<string, List<string>>();
                Dictionary<string, List<string>> toRemove = new Dictionary<string, List<string>>();
                if (path.BlackList.Count == 0) path.BlackList = DefaultBlackList;
                path.BlackList.Sort();
                foreach (ItemDefinition rustItem in ItemManager.itemList) {
                    catPath = rustItem.category.ToString();
                    if (!path.LootTypes.ContainsKey(catPath)) {
                        Puts($"New item category *{catPath}* added to game. Please notify author.");
                        continue;
                    }
                    if (IsJunk(lootTable, rustItem.shortname) || (!path.allowChristmas && rustItem.shortname.Contains("xmas")) || (!path.allowHalloween && rustItem.shortname.Contains("halloween")) || (!path.allowKeycards && rustItem.shortname.Contains("keycard_"))) {
                        path.LootTypes[catPath].Remove(rustItem.shortname);
                        continue;
                    }
                    if (!itemCheck.ContainsKey(catPath)) itemCheck.Add(catPath, new List<string>());
                    itemCheck[catPath].Add(rustItem.shortname);
                    if (path.LootTypes[catPath].ContainsKey(rustItem.shortname)) {
                        path.LootTypes[catPath][rustItem.shortname].item = rustItem;
                        continue;
                    }
                    var stackPath = path.Categories[catPath];
                    path.LootTypes[catPath].Add(rustItem.shortname, new lootData {
                        item = rustItem
                    }
                    );
                }
                foreach (var cat in itemCheck) foreach (var item in path.LootTypes[cat.Key]) if (!itemCheck[cat.Key].Contains(item.Key)) {
                    if (!toRemove.ContainsKey(cat.Key)) toRemove.Add(cat.Key, new List<string>());
                    toRemove[cat.Key].Add(item.Key);
                }
                foreach (var odd in toRemove) foreach (var oddItem in odd.Value) path.LootTypes[odd.Key].Remove(oddItem);
                LootTables[lootTable].Categories = LootTables[lootTable].Categories.OrderBy(x => x.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
                LootTables[lootTable].LootTypes = LootTables[lootTable].LootTypes.OrderBy(x => x.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
                foreach (var entry in LootTables[lootTable].LootTypes.ToDictionary(pair => pair.Key, pair => pair.Value)) LootTables[lootTable].LootTypes[entry.Key] = entry.Value.OrderBy(x => x.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
                Interface.Oxide.DataFileSystem.WriteObject($"CustomLoot/{lootTable}", path);
                return true;
            }
            catch {
                Puts($"There was an error loading data file {lootTable}.");
                LootTableNames.Remove(lootTable);
                return false;
            }
        }
        public bool IsJunk(string lootTable, string rustItem) {
            List<string> junk = LootTables[lootTable].BlackList;
            if (junk.Contains(rustItem)) return true;
            return false;
        }
        public bool IsReal(string rustItem) {
            var createTest = ItemManager.CreateByName(rustItem, 1);
            if (createTest != null) {
                createTest.Remove(0f);
                return true;
            }
            return false;
        }
#endregion
#region Config
        private ConfigData configData;
        class ConfigData {
            public GlobalSettings GlobalSettings = new GlobalSettings();
            public static Settings Settings = new Settings();
            public Dictionary<string, Settings> CorpseTypes = new Dictionary<string, Settings> {
                {
                    "MilitaryTunnelScientist", Settings
                }
                , {
                    "JunkPileScientist", Settings
                }
                , {
                    "MountedScientist", Settings
                }
                , {
                    "CompoundScientist", Settings
                }
                , {
                    "BanditTown", Settings
                }
                , {
                    "Murderer", Settings
                }
                , {
                    "ScareCrow", Settings
                }
                , {
                    "CargoShip", Settings
                }
                , {
                    "OilRig", Settings
                }
                , {
                    "Excavator", Settings
                }
                , {
                    "Scientist", Settings
                }
                , {
                    "HeavyScientist", Settings
                }
                , {
                    "BotSpawn", Settings
                }
            }
            ;
            public Dictionary<string, Settings> ContainerTypes = cl.ContainerTypesFromGame;
            public Dictionary<string, BaseSettings> API = new Dictionary<string, BaseSettings>();
        }
        public class GlobalSettings {
            public bool allowDuplicates = false;
            public bool corpseTypePerBotSpawnProfile = false;
            public bool Include_DM_Crates = false;
        }
        public class BaseSettings {
            [JsonProperty(Order = 1)]
            public string lootTable = "default";
            [JsonProperty(Order = 2)]
            public int maxItems = 6;
            [JsonProperty(Order = 3)]
            public int minItems = 6;
            [JsonProperty(Order = 4)]
            public bool gunsWithAmmo;
            [JsonProperty(Order = 5)]
            public bool noGuns;
            [JsonProperty(Order = 6)]
            public int MaxBps = 3;
            [JsonProperty(Order = 7)]
            public int WaterPreFillPercent = 20;
            [JsonProperty(Order = 8)]
            public bool ClearContainerFirst = true;
        }
        public class Settings : BaseSettings {
            [JsonProperty(Order = 1)]
            public bool enabled;
        }
        private void LoadConfigVariables() {
            BotTypes.Clear();
            LootTableNames = new List<string>() {
                "default"
            }
            ;
            configData = Config.ReadObject<ConfigData>();
            bool perBotSpawn = false;
            if (configData.GlobalSettings.corpseTypePerBotSpawnProfile) {
                perBotSpawn = true;
                if (configData.CorpseTypes.ContainsKey("BotSpawn")) {
                    if (backupData.BotSpawnBackups.ContainsKey("BotSpawn")) backupData.BotSpawnBackups["BotSpawn"] = configData.CorpseTypes["BotSpawn"];
                    else if (JsonConvert.SerializeObject(configData.CorpseTypes["BotSpawn"]) != JsonConvert.SerializeObject(new Settings())) backupData.BotSpawnBackups.Add("BotSpawn", configData.CorpseTypes["BotSpawn"]);
                    configData.CorpseTypes.Remove("BotSpawn");
                }
                foreach (var entry in BotSpawnBots.Where(entry => !configData.CorpseTypes.ContainsKey($"BotSpawn-{entry.Key}"))) {
                    if (backupData.BotSpawnBackups.ContainsKey($"BotSpawn-{entry.Key}")) configData.CorpseTypes.Add($"BotSpawn-{entry.Key}", backupData.BotSpawnBackups[$"BotSpawn-{entry.Key}"]);
                    else configData.CorpseTypes.Add($"BotSpawn-{entry.Key}", new Settings());
                }
            }
            else {
                if (JsonConvert.SerializeObject(configData.CorpseTypes["BotSpawn"]) == JsonConvert.SerializeObject(new Settings())) {
                    if (backupData.BotSpawnBackups.ContainsKey("BotSpawn")) configData.CorpseTypes["BotSpawn"] = backupData.BotSpawnBackups["BotSpawn"];
                }
            }
            if (BotSpawn) {
                foreach (var entry in configData.CorpseTypes.ToDictionary(pair => pair.Key, pair => pair.Value).Where(entry => (!perBotSpawn && entry.Key.Contains("BotSpawn-")) || (perBotSpawn && entry.Key.Contains("BotSpawn-") && !BotSpawnBots.ContainsKey(entry.Key.Remove(0, 9))))) {
                    if (backupData.BotSpawnBackups.ContainsKey(entry.Key)) backupData.BotSpawnBackups[entry.Key] = configData.CorpseTypes[entry.Key];
                    else backupData.BotSpawnBackups.Add(entry.Key, configData.CorpseTypes[entry.Key]);
                    configData.CorpseTypes.Remove(entry.Key);
                }
            }
            if (!configData.GlobalSettings.Include_DM_Crates) foreach (var entry in configData.ContainerTypes.ToDictionary(pair => pair.Key, pair => pair.Value).Where(x => x.Key.Contains("dm "))) configData.ContainerTypes.Remove(entry.Key);
            foreach (var entry in configData.CorpseTypes.ToDictionary(pair => pair.Key, pair => pair.Value)) {
                BotTypes.Add(entry.Key, new List<ulong>());
                if (!LootTableNames.Contains(entry.Value.lootTable)) LootTableNames.Add(entry.Value.lootTable);
            }
            foreach (var entry in configData.ContainerTypes) if (!LootTableNames.Contains(entry.Value.lootTable)) LootTableNames.Add(entry.Value.lootTable);
            foreach (var entry in configData.API) if (!LootTableNames.Contains(entry.Value.lootTable)) LootTableNames.Add(entry.Value.lootTable);
            SaveConfig(configData);
        }
        protected override void LoadDefaultConfig() {
            Puts("Creating new config file.");
        }
        void SaveConfig(ConfigData config) {
            config.CorpseTypes = config.CorpseTypes.OrderBy(x => x.Key).OrderBy(x => x.Key.Contains("BotSpawn")).ToDictionary(pair => pair.Key, pair => pair.Value);
            configData.ContainerTypes = configData.ContainerTypes.OrderBy(x => x.Key).OrderByDescending(x => x.Key.Contains("barrel")).ToDictionary(pair => pair.Key, pair => pair.Value);
            configData.API = configData.API.OrderBy(x => x.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
            Config.WriteObject(config, true);
        }
#endregion
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху