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

FREE AlphaLoot : 1.7.9 1.7.9

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Rust;
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Core.Configuration;
using Random = System.Random;
using Oxide.Core;
using Oxide.Core.Plugins;
namespace Oxide.Plugins {
    [Info("AlphaLoot", "Fujikura", "1.7.9", ResourceId = 13)]
    public class AlphaLoot : RustPlugin {
        [PluginReference]
        Plugin CustomLootSpawns;
        [PluginReference]
        Plugin FancyDrop;
        [PluginReference]
        Plugin SkinBox;
        bool Changed = false;
        bool firstSetup = false;
        Random rng = new Random();
        Random rngHeli = new Random();
        List<int> rngHeliList = new List<int>();
        static AlphaLoot al = null;
        double baseItemRarity = 2;
        bool initialized = false;
        bool skinsLoaded = false;
        bool manualReload = false;
        StoredExportNames storedExportNames = new StoredExportNames();
        DynamicConfigFile itemRaritys;
        DynamicConfigFile lootTable;
        DynamicConfigFile heliLoot;
        DynamicConfigFile fancyDropLoot;
        DynamicConfigFile getFile(string file) => Interface.Oxide.DataFileSystem.GetDatafile($"{this.Title}/{file}");
        bool chkFile(string file) => Interface.Oxide.DataFileSystem.ExistsDatafile($"{this.Title}/{file}");
        Dictionary<string, object> lootData = new Dictionary<string, object>();
        Dictionary<string, object> lootContainers = new Dictionary<string, object>();
        Dictionary<string, object> lootCategoryLimits = new Dictionary<string, object>();
        Dictionary<string, object> fancyDropData = new Dictionary<string, object>();
        Dictionary<string, object> fancyDropLootSpawn = new Dictionary<string, object>();
        List<object> heliData = new List<object>();
        Dictionary<string, object> rarityOverrides = new Dictionary<string, object>();
        List<object> itemMultiplierExcludes = new List<object>();
        Dictionary<string, object> weaponAmmoPreload = new Dictionary<string, object>();
        Dictionary<string, List<ulong>> skinsCache = new Dictionary<string, List<ulong>>();
        List <string> newGameItems = new List <string>();
        Dictionary<string, string> AllContainerTypes = new Dictionary<string, string>();
        Dictionary<string, LootSpawn> AllLootSpawns = new Dictionary<string, LootSpawn>();
        Regex _findLoot = new Regex(@"(foodbox|minecart|crate[\-_]mine|crate[\-_]tools|crate[\-_]elite|crate[\-_]normal[\-_\d\w]*|loot[\-_]barrel[\-_\d\w]*|loot[\-_]trash[\-_\d\w]*|heli[\-_]crate|oil[\-_]barrel|supply[\-_]drop|trash[\-_]pile[\-_\d\w]*|/dmloot/.*|stockin[\-_](small|large)[\-_]deployed)\.prefab", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        List<string> allPrefabs;
        List<string> lootPrefabs;
        FieldInfo _guidToPath = typeof(GameManifest).GetField("guidToPath", (BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
        MethodInfo _OnDestroy = typeof(SpawnPointInstance).GetMethod("OnDestroy", BindingFlags.NonPublic | BindingFlags.Instance);
        Dictionary<string, string> guidToPathCopy = new Dictionary<string, string>();
        List<string>[] items = new List<string>[5];
        Dictionary<string, List<string>[]> itemsNew = new Dictionary<string, List<string>[]>();
        Dictionary<string, int[]> itemWeightsNew = new Dictionary<string, int[]>();
        Dictionary<string, int> totalItemWeightNew = new Dictionary<string, int>();
        List<string>[] itemsDrop = new List<string>[5];
        Dictionary<string, List<string>[]> itemsNewDrop = new Dictionary<string, List<string>[]>();
        Dictionary<string, int[]> itemWeightsNewDrop = new Dictionary<string, int[]>();
        Dictionary<string, int> totalItemWeightNewDrop = new Dictionary<string, int>();
        static Dictionary<string, object> defaultCategoryLimits() {
            var dp = new Dictionary<string, object>();
            var dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 1);
            dp0.Add("DropSkinned", false);
            dp.Add("Weapon", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 2);
            dp0.Add("DropSkinned", false);
            dp.Add("Ammunition", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 1);
            dp0.Add("DropSkinned", true);
            dp.Add("Items", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 1);
            dp0.Add("DropSkinned", false);
            dp.Add("Tool", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 2);
            dp0.Add("DropSkinned", false);
            dp.Add("Traps", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 2);
            dp0.Add("DropSkinned", false);
            dp.Add("Construction", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 1);
            dp0.Add("DropSkinned", true);
            dp.Add("Attire", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 2);
            dp0.Add("DropSkinned", false);
            dp.Add("Resources", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 2);
            dp0.Add("DropSkinned", false);
            dp.Add("Food", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 2);
            dp0.Add("DropSkinned", false);
            dp.Add("Medical", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 3);
            dp0.Add("DropSkinned", false);
            dp.Add("Component", dp0);
            dp0 = new Dictionary<string, object>();
            dp0.Add("VanillaMultiplier", 1);
            dp0.Add("DropSkinned", false);
            dp.Add("Misc", dp0);
            return dp;
        }
        static Dictionary<string, object> rarityOverrideList() {
            var dp = new Dictionary<string, object>();
            dp.Add("autoturret", 4);
            dp.Add("furnace", 1);
            dp.Add("trap.bear", 1);
            dp.Add("box.wooden", 1);
            dp.Add("hq.metal.ore", 2);
            dp.Add("targeting.computer", 3);
            dp.Add("trap.landmine", 2);
            dp.Add("lmg.m249", 4);
            dp.Add("rifle.lr300", 3);
            dp.Add("mining.quarry", 2);
            return dp;
        }
        static List<object> excludeMulipliersDefaults() {
            var dp = new List<object>();
            dp.Add("targeting.computer");
            dp.Add("mining.quarry");
            dp.Add("cctv.camera");
            return dp;
        }
        bool pluginEnabled;
        bool debugLogEnabled;
        int refreshMinutes;
        bool debugLootRepopulation;
        bool adminInputLootRefresh;
        float adminLootRefreshInterval;
        int setupAuthLevel;
        bool showAdminLootInfo;
        bool includeWorkShopSkins;
        bool disableRefreshFunctions;
        bool enableLootFraction;
        bool enableDefaultRarityOverrides;
        bool blockPlayerItemInput;
        bool lootStackFixEnable;
        float lootStackFixRange;
        bool itemSlotVariance;
        bool enableScrapSpawn;
        bool enableHeliLoadOut;
        bool enableFancyDropLoot;
        bool useSkinBoxSkins;
        object GetConfig(string menu, string datavalue, object defaultValue) {
            var data = Config[menu] as Dictionary<string, object>;
            if (data == null) {
                data = new Dictionary<string, object>();
                Config[menu] = data;
                Changed = true;
            }
            object value;
            if (!data.TryGetValue(datavalue, out value)) {
                value = defaultValue;
                data[datavalue] = value;
                Changed = true;
            }
            return value;
        }
        void LoadVariables() {
            lootCategoryLimits = (Dictionary<string, object>)GetConfig("LootCategorys", "Limits", defaultCategoryLimits());
            itemMultiplierExcludes = (List<object>)GetConfig("ExcludeFromMultiply", "Items", excludeMulipliersDefaults());
            weaponAmmoPreload = (Dictionary<string, object>)GetConfig("Weapons", "Ammo", new Dictionary<string, object>());
            refreshMinutes = Convert.ToInt32(GetConfig("Generic", "refreshMinutes", 30));
            debugLootRepopulation = Convert.ToBoolean(GetConfig("Generic", "debugLootRepopulation", false));
            pluginEnabled = Convert.ToBoolean(GetConfig("Generic", "pluginEnabled", false));
            debugLogEnabled = Convert.ToBoolean(GetConfig("Debug", "debugLogEnabled", false));
            adminInputLootRefresh = Convert.ToBoolean(GetConfig("Generic", "adminInputLootRefresh", true));
            adminLootRefreshInterval = Convert.ToSingle(GetConfig("Generic", "adminLootRefreshInterval", 3f));
            enableLootFraction = Convert.ToBoolean(GetConfig("Generic", "enableLootFraction", false));
            enableDefaultRarityOverrides = Convert.ToBoolean(GetConfig("Generic", "enableDefaultRarityOverrides", true));
            setupAuthLevel = Convert.ToInt32(GetConfig("Generic", "setupAuthLevel", 2));
            showAdminLootInfo = Convert.ToBoolean(GetConfig("Generic", "showAdminLootInfo", true));
            includeWorkShopSkins = Convert.ToBoolean(GetConfig("Generic", "includeWorkShopSkins", true));
            disableRefreshFunctions = Convert.ToBoolean(GetConfig("Generic", "disableRefreshFunctions", false));
            blockPlayerItemInput = Convert.ToBoolean(GetConfig("Generic", "blockPlayerItemInput", true));
            lootStackFixEnable = Convert.ToBoolean(GetConfig("Generic", "lootStackFixEnable", true));
            lootStackFixRange = Convert.ToSingle(GetConfig("Generic", "lootStackFixRange", 0.3f));
            itemSlotVariance = Convert.ToBoolean(GetConfig("Generic", "itemSlotVariance", false));
            enableScrapSpawn = Convert.ToBoolean(GetConfig("Generic", "enableScrapSpawn", true));
            enableHeliLoadOut = Convert.ToBoolean(GetConfig("Generic", "enableHeliLoadOut", false));
            enableFancyDropLoot = Convert.ToBoolean(GetConfig("Generic", "enableFancyDropLoot", false));
            useSkinBoxSkins = Convert.ToBoolean(GetConfig("Generic", "useSkinBoxSkins", true));
            var configremoval = false;
            if ((Config.Get("Generic") as Dictionary<string, object>).ContainsKey("enableItemMinimum")) {
                (Config.Get("Generic") as Dictionary<string, object>).Remove("enableItemMinimum");
                configremoval = true;
            }
            if (!Changed && !configremoval) return;
            SaveConfig();
            Changed = false;
        }
        protected override void LoadDefaultConfig() {
            Config.Clear();
            LoadVariables();
        }
        void Init() {
            al = this;
            LoadVariables();
            itemRaritys = getFile("ItemRaritys");
            lootTable = getFile("LootTables");
            if (enableHeliLoadOut) heliLoot = getFile("HeliLoot");
            if (enableFancyDropLoot) fancyDropLoot = getFile("FancyDropLoot");
            guidToPathCopy = (Dictionary<string, string>)_guidToPath.GetValue(GameManifest.Current);
        }
        void OnServerInitialized() {
            if (initialized) return;
            NextFrame(()=> ServerMgr.Instance.StartCoroutine(UpdateInternals(true)));
        }
        void Unload() {
            if (itemRaritys != null) itemRaritys.Clear();
            if (lootTable != null) lootTable.Clear();
            if (heliLoot != null) heliLoot.Clear();
            if (fancyDropLoot != null) fancyDropLoot.Clear();
            if (!disableRefreshFunctions) {
                var objs = UnityEngine.Object.FindObjectsOfType<RefreshHandler>().ToList();
                if (objs.Count > 0) foreach (var obj in objs) GameObject.DestroyImmediate(obj);
            }
            var objsa = UnityEngine.Object.FindObjectsOfType<AdminLootHandler>().ToList();
            if (objsa.Count > 0) foreach (var obj in objsa) GameObject.Destroy(obj);
        }
        void ClearDictionarys() {
            lootData.Clear();
            lootContainers.Clear();
            heliData.Clear();
            fancyDropData.Clear();
            itemsDrop = new List<string>[5];
            itemsNewDrop.Clear();
            itemWeightsNewDrop.Clear();
            totalItemWeightNewDrop.Clear();
            rarityOverrides.Clear();
            items = new List<string>[5];
            itemsNew.Clear();
            itemWeightsNew.Clear();
            totalItemWeightNew.Clear();
            newGameItems.Clear();
        }
        void GetItemSkins() {
            if (skinsLoaded) return;
            foreach (var itemDef in ItemManager.GetItemDefinitions()) {
                List<ulong> skins;
                skins = new List<ulong> {
                    0
                }
                ;
                skins.AddRange(ItemSkinDirectory.ForItem(itemDef).Select(skin => Convert.ToUInt64(skin.id)));
                skinsCache.Add(itemDef.shortname, skins);
            }
            bool skinBoxEnabled = (plugins.Exists("SkinBox") && useSkinBoxSkins);
            skinsLoaded = true;
            if (includeWorkShopSkins && !skinBoxEnabled) {
                GetWorkshopSkins();
                return;
            }
            if (skinBoxEnabled) {
                GetSkinBoxSkins();
                return;
            }
            GetWorkshopSkins();
        }
        void GetWorkshopSkins() {
            int updated = 0;
            foreach (var shopskin in Rust.Workshop.Approved.All.Where(skin => skin.Skinnable.ItemName != null && skin.Skinnable.ItemName != "")) {
                if (!skinsCache.ContainsKey(shopskin.Skinnable.ItemName)) skinsCache[shopskin.Skinnable.ItemName] = new List<ulong>();
                if (!skinsCache[shopskin.Skinnable.ItemName].Contains(shopskin.WorkshopdId)) {
                    skinsCache[shopskin.Skinnable.ItemName].Add(shopskin.WorkshopdId);
                    updated++;
                }
            }
            if (updated > 0) Puts($"SkinCache filled with '{updated}' skins");
        }
        void OnSkinCacheUpdate(Dictionary<string, List<ulong>> skins, bool loading) {
            if (!initialized || !skinsLoaded || !useSkinBoxSkins) return;
            skinsCache = new Dictionary<string, List<ulong>>(skins);
            int count = 0;
            int items = 0;
            foreach (var skin in skinsCache) {
                if (skin.Value.Count > 1) {
                    count += skin.Value.Count-1;
                    items++;
                }
            }
            if (loading) Puts($"Reveived '{items}' items from SkinBox with '{count}' skins at all");
            else Puts($"Reveived SkinBox skins update");
        }
        void GetSkinBoxSkins() {
            var skins = SkinBox.Call("getSkincache");
            if (skins == null || skins is bool) {
                GetWorkshopSkins();
                return;
            }
            skinsCache = new Dictionary<string, List<ulong>>(skins as Dictionary<string, List<ulong>>);
            int count = 0;
            int items = 0;
            foreach (var skin in skinsCache) {
                if (skin.Value.Count > 1) {
                    count += skin.Value.Count-1;
                    items++;
                }
            }
            Puts($"Reveived '{items}' items from SkinBox with '{count}' skins at all");
        }
        object OnFancyDropCrate(Dictionary<string, object> cratesettings) {
            if (!enableFancyDropLoot || !cratesettings.ContainsKey("droptype")) return null;
            var crateName =(string)cratesettings["droptype"];
            if (fancyDropData.ContainsKey(crateName)) {
                if (((fancyDropData[crateName] as Dictionary<string, object>)["ItemsList"] as Dictionary<string, object>).Count > 0) {
                    var crateType = fancyDropData[crateName] as Dictionary<string, object>;
                    var maxItemCount = (crateType["ItemsList"] as Dictionary<string, object>).Count;
                    var itemCount = 6;
                    if (crateType.ContainsKey("ItemMin") && crateType.ContainsKey("ItemMax")) {
                        if ((int)crateType["ItemMin"] <= (int)crateType["ItemMax"]) itemCount = UnityEngine.Random.Range((int)crateType["ItemMin"], (int)crateType["ItemMax"]);
                        else itemCount = UnityEngine.Random.Range((int)crateType["ItemMax"], (int)crateType["ItemMin"]);
                    }
                    if (itemCount > maxItemCount) itemCount = maxItemCount;
                    var items = new List<Item>();
                    var itemNames = new List<string>();
                    var maxRetry = 20;
                    int divider = 1;
                    if (crateType.ContainsKey("ItemDivider")) divider = (int)crateType["ItemDivider"];
                    for (int i = 0; i < itemCount; ++i) {
                        if (maxRetry == 0) break;
                        var item = MightyRNGDrop(crateName, divider, itemCount);
                        if (item == null) continue;
                        if (itemNames.Contains(item.info.shortname)) {
                            item.Remove(0f);
                            --maxRetry;
                            --i;
                            continue;
                        }
                        else itemNames.Add(item.info.shortname);
                        items.Add(item);
                    }
                    return items;
                }
            }
            return null;
        }
        void OnPluginLoaded(Plugin name) {
            if (enableFancyDropLoot && name.Name == "FancyDrop" && FancyDrop.Call("getFancyDropTypes") != null) {
                var call = FancyDrop.Call("getFancyDropTypes");
                var setupDropTypes = new Dictionary<string, object>();
                setupDropTypes = (Dictionary<string, object>)call;
                if (setupDropTypes != null && setupDropTypes.Count != 0) GetFancyDropLoot(setupDropTypes);
            }
        }
        IEnumerator UpdateInternals(bool doLog = true, bool recreateHeli = false) {
            allPrefabs = GameManifest.Current.pooledStrings.ToList().ConvertAll(p => p.str);
            lootPrefabs = allPrefabs.Where(p => _findLoot.IsMatch(p)).ToList();
            ClearDictionarys();
            LoadItemRaritys(doLog);
            SaveExportNames();
            LoadAllContainers();
            LoadLootTables(doLog);
            GetFancyDropLoot(new Dictionary<string, object>(), false);
            GetHeliLoot(recreateHeli);
            FixLoot();
            GetItemSkins();
            LoadWeaponsAmmo();
            if (!pluginEnabled || Changed || firstSetup) {
                if (Changed) Config["Generic", "pluginEnabled"] = false;
                SaveConfig();
                Changed = false;
                if (doLog) PrintWarning("Plugin running in passive mode.Activate by command 'al.enable'");
                yield break;
            }
            for (var i = 0; i < 5; ++i) items[i] = new List<string>();
            foreach (var data in lootData) {
                itemsNew.Add(data.Key, new List<string>[5]);
                for (var i = 0; i < 5; ++i) itemsNew[data.Key][i] = new List<string>();
                var limits = (Dictionary<string, object>)data.Value;
                foreach (var limit in limits) {
                    var def = ItemManager.FindItemDefinition(limit.Key);
                    if (def != null && def.GetComponent<ItemModEntity>() != null && def.GetComponent<ItemModEntity>().entityPrefab != null && !guidToPathCopy.ContainsKey(def.GetComponent<ItemModEntity>().entityPrefab.guid)) continue;
                    if (def != null) {
                        if (!itemsNew[data.Key][(int)def.rarity].Contains(def.shortname)) itemsNew[data.Key][(int)def.rarity].Add(def.shortname);
                        if (!items[(int)def.rarity].Contains(def.shortname)) items[(int)def.rarity].Add(def.shortname);
                    }
                }
                totalItemWeightNew.Add(data.Key, 0);
                itemWeightsNew.Add(data.Key, new int[5]);
                if (baseItemRarity < 2) baseItemRarity = 2;
                if (baseItemRarity > 3) baseItemRarity = 3;
                for (var i = 0; i < 5; ++i) totalItemWeightNew[data.Key] += (itemWeightsNew[data.Key][i] = ItemWeight(baseItemRarity, i) * itemsNew[data.Key][i].Count);
            }
            int populatedContainers = 0;
            if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - START > Initial LootPopulation started", this);
            foreach (var container in UnityEngine.Object.FindObjectsOfType<LootContainer>().Where(c => c.isActiveAndEnabled).ToList()) {
                if(CustomLootSpawns && (bool)CustomLootSpawns?.Call("IsLootBox", container.GetComponent<BaseEntity>())) continue;
                if (PopulateContainer(container)) populatedContainers++;
            }
            if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - STARTED > Initial LootPopulation done with '{populatedContainers}' containers", this);
            if (doLog) Puts($"Populated '{populatedContainers}' LootContainer with custom Loot.");
            if (!initialized) Puts("All available plugin commands can be listed with \'al.cmds\'");
            initialized = true;
            if (doLog) {
                bool heliCrateOn = false;
                object containerobj;
                if (lootContainers.TryGetValue("heli_crate", out containerobj)) {
                    var con = containerobj as Dictionary<string, object>;
                    heliCrateOn = (bool)con["Enabled"];
                }
                Puts($"Custom Heli loadout is '{enableHeliLoadOut ? "enabled" : "disabled" }' | Heli Container is '{heliCrateOn ? "enabled" : "disabled" }'");
                Puts($"Custom FancyDrop loot is '{enableFancyDropLoot ? "enabled" : "disabled" }' {enableFancyDropLoot ? "| available DropTypes : '" + fancyDropData.Count +"'" : ""}");
            }
            yield return null;
        }
        void FixLoot() {
            if (!lootStackFixEnable) return;
            var spawns = Resources.FindObjectsOfTypeAll<LootContainer>().Where(c => c.isActiveAndEnabled).OrderBy(c => c.transform.position.x).ThenBy(c => c.transform.position.z).ThenBy(c => c.transform.position.z).ToList();
            var count = spawns.Count();
            var racelimit = count * count;
            var antirace = 0;
            var deleted = 0;
            for (var i = 0; i < count; i++) {
                var box = spawns[i];
                var next = i + 1;
                var pos = new Vector2(box.transform.position.x, box.transform.position.z);
                if (++antirace > racelimit) return;
                while (next < count) {
                    var box2 = spawns[next];
                    var pos2 = new Vector2(box2.transform.position.x, box2.transform.position.z);
                    var distance = Vector2.Distance(pos, pos2);
                    if (++antirace > racelimit) return;
                    if (distance < lootStackFixRange) {
                        spawns.RemoveAt(next);
                        count--;
                        if (box2.gameObject.GetComponent<SpawnPointInstance>()) _OnDestroy.Invoke(box2.gameObject.GetComponent<SpawnPointInstance>(), null);
                        (box2 as BaseEntity).Kill();
                        deleted++;
                    }
                    else break;
                }
            }
            if (deleted > 0) Puts($"Removed {deleted} stacked LootContainer.");
        }
        Item MightyRNG(string type, int divider, int itemCount) {
            List<string> selectFrom;
            int limit = 0;
            string itemName;
            Item item;
            if (divider < 1) divider = 1;
            int maxRetry;
            if (type == "supply_drop") maxRetry = itemCount * 4;
            else maxRetry = 10;
            do {
                selectFrom = null;
                item = null;
                var r = rng.Next(totalItemWeightNew[type]);
                for (var i = 0; i < 5; ++i) {
                    limit += itemWeightsNew[type][i];
                    if (r < limit) {
                        selectFrom = itemsNew[type][i];
                        break;
                    }
                }
                if (selectFrom == null) {
                    if (--maxRetry <= 0) break;
                    continue;
                }
                itemName = selectFrom[rng.Next(0, selectFrom.Count)];
                object limits;
                bool DropSkinned = false;
                var itemDef = ItemManager.FindItemDefinition(itemName);
                if (lootCategoryLimits.TryGetValue(itemDef.category.ToString(), out limits)) DropSkinned = (bool)(limits as Dictionary<string, object>)["DropSkinned"];
                if (DropSkinned && skinsCache[itemName].Count > 1) item = ItemManager.Create(itemDef, 1, skinsCache[itemName].GetRandom());
                else item = ItemManager.CreateByName(itemName, 1);
                if (item == null || item.info == null) continue;
                break;
            }
            while (true);
            if (item == null) return null;
            object itemLimit;
            if ((lootData[type] as Dictionary<string, object>).TryGetValue(item.info.shortname, out itemLimit)) if ((int)itemLimit > 1) item.amount = UnityEngine.Random.Range(Mathf.CeilToInt(Convert.ToSingle(itemLimit) / divider), (int)itemLimit);
            if (item.info.category == ItemCategory.Weapon && weaponAmmoPreload.ContainsKey(item.info.shortname) && (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents < (int)weaponAmmoPreload[item.info.shortname]) (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents = (int)weaponAmmoPreload[item.info.shortname];
            return item;
        }
        Item MightyRNGDrop(string type, int divider, int itemCount) {
            List<string> selectFrom;
            int limit = 0;
            string itemName;
            Item item;
            if (divider < 1) divider = 1;
            int maxRetry = 20;
            do {
                selectFrom = null;
                item = null;
                var r = rng.Next(totalItemWeightNewDrop[type]);
                for (var i = 0; i < 5; ++i) {
                    limit += itemWeightsNewDrop[type][i];
                    if (r < limit) {
                        selectFrom = itemsNewDrop[type][i];
                        break;
                    }
                }
                if (selectFrom == null) {
                    if (--maxRetry <= 0) break;
                    continue;
                }
                itemName = selectFrom[rng.Next(0, selectFrom.Count)];
                object limits;
                bool DropSkinned = false;
                var itemDef = ItemManager.FindItemDefinition(itemName);
                if (lootCategoryLimits.TryGetValue(itemDef.category.ToString(), out limits)) DropSkinned = (bool)(limits as Dictionary<string, object>)["DropSkinned"];
                if (DropSkinned && skinsCache[itemName].Count > 1) item = ItemManager.Create(itemDef, 1, skinsCache[itemName].GetRandom());
                else item = ItemManager.CreateByName(itemName, 1);
                if (item == null || item.info == null) continue;
                break;
            }
            while (true);
            if (item == null) return null;
            object itemLimit;
            if (((fancyDropData[type] as Dictionary<string, object>)["ItemsList"] as Dictionary<string, object>).TryGetValue(item.info.shortname, out itemLimit)) if ((int)itemLimit > 1) item.amount = UnityEngine.Random.Range(Mathf.CeilToInt(Convert.ToSingle(itemLimit) / divider), (int)itemLimit);
            if (item.info.category == ItemCategory.Weapon && weaponAmmoPreload.ContainsKey(item.info.shortname) && (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents < (int)weaponAmmoPreload[item.info.shortname]) (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents = (int)weaponAmmoPreload[item.info.shortname];
            return item;
        }
        void ClearContainer(LootContainer container) {
            while (container.inventory.itemList.Count > 0) {
                var item = container.inventory.itemList[0];
                item.RemoveFromContainer();
                item.Remove(0f);
            }
        }
        void SuppressRefresh(LootContainer container) {
            container.minSecondsBetweenRefresh = -1;
            container.maxSecondsBetweenRefresh = 0;
            InvokeHandler.CancelInvoke(container.GetComponent<MonoBehaviour>(), new Action(container.SpawnLoot));
        }
        bool PopulateContainer(LootContainer container) {
            Dictionary<string, object> con;
            object containerobj;
            int lootitemcount = 0;
            if (lootContainers.TryGetValue(container.ShortPrefabName, out containerobj)) {
                con = containerobj as Dictionary<string, object>;
                if (!(bool)con["Enabled"]) {
                    if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - CANCELED > Setting for '{container.ShortPrefabName}' not active", this);
                    return false;
                }
                object itemcount;
                if (lootData.TryGetValue(container.ShortPrefabName, out itemcount)) lootitemcount = (int)(itemcount as Dictionary<string, object>).Count();
                else {
                    if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - CANCELED > no or too-few items in list for '{container.ShortPrefabName}'", this);
                    return false;
                }
            }
            else {
                if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - FAILED > container '{container.ShortPrefabName}' is not in loottable list", this);
                return false;
            }
            SuppressRefresh(container);
            if (container.inventory == null) {
                container.inventory = new ItemContainer();
                container.inventory.ServerInitialize(null, container.inventorySlots);
                container.inventory.GiveUID();
            }
            else ClearContainer(container);
            int itemCount = 0;
            if (itemSlotVariance && con.ContainsKey("ItemsVariance") && (int)con["ItemsVariance"] != 0) {
                int sum = (int)con["Items"] + (int)con["ItemsVariance"];
                if (sum < 1 ) sum = 1;
                int num = (int)con["Items"];
                if (sum > num) itemCount = Mathf.RoundToInt(UnityEngine.Random.Range(Convert.ToSingle(num)*100f, Convert.ToSingle(sum)*100f) / 100f);
                else if (sum < num) itemCount = Mathf.RoundToInt(UnityEngine.Random.Range(Convert.ToSingle(sum)*100f, Convert.ToSingle(num)*100f) / 100f);
                else itemCount = num;
            }
            else itemCount = (int)con["Items"];
            if (itemCount < 1) itemCount = 1;
            if (itemCount > 18) itemCount = 18;
            if (lootitemcount > 0 && itemCount > lootitemcount && lootitemcount < 18) itemCount = lootitemcount;
            container.inventory.capacity = itemCount;
            container.inventorySlots = itemCount;
            var items = new List<Item>();
            var itemNames = new List<string>();
            var maxRetry = 20;
            int divider = 1;
            if (con.ContainsKey("MinAmountDivider")) divider = (int)con["MinAmountDivider"];
            for (int i = 0; i < itemCount; ++i) {
                if (maxRetry == 0) break;
                var item = MightyRNG(container.ShortPrefabName, divider, itemCount);
                if (item == null) continue;
                if (itemNames.Contains(item.info.shortname)) {
                    item.Remove(0f);
                    --maxRetry;
                    --i;
                    continue;
                }
                else itemNames.Add(item.info.shortname);
                items.Add(item);
            }
            foreach (var item in items) item.MoveToContainer(container.inventory, -1, false);
            if (enableLootFraction) {
                if (container.SpawnType == LootContainer.spawnType.ROADSIDE || container.SpawnType == LootContainer.spawnType.TOWN) {
                    foreach (Item current in container.inventory.itemList) {
                        if (current.hasCondition) {
                            current.condition = UnityEngine.Random.Range(current.info.condition.foundCondition.fractionMin, current.info.condition.foundCondition.fractionMax) * current.info.condition.max;
                        }
                    }
                }
            }
            if (enableScrapSpawn && (int)con["ScrapAmount"] > 0) {
                container.inventory.capacity++;
                container.inventorySlots++;
                Item item = ItemManager.Create(ItemManager.FindItemDefinition("scrap"), (int)con["ScrapAmount"], 0uL);
                item.MoveToContainer(container.inventory, -1, true);
            }
            container.inventory.MarkDirty();
            if (container.inventory.capacity < 7 && container.ShortPrefabName != "supply_drop") container.panelName = "crate";
            else container.panelName = "generic";
            if (!disableRefreshFunctions && container.ShortPrefabName.Contains("crate_")) {
                var obj = container.gameObject.GetComponent<RefreshHandler>();
                if (obj) obj.Reset();
                else container.gameObject.AddComponent<RefreshHandler>();
            }
            if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - SUCCESS > spawned '{container.inventory.capacity}' items in '{container}' > {ContentsStringHash(container.inventory)}", this);
            return true;
        }
        string ContentsStringHash(ItemContainer itemCont) {
            string text = string.Empty;
            for (int i = 0; i < itemCont.capacity; i++) {
                global : : Item slot = itemCont.GetSlot(i);
                if (slot != null) {
                    text += slot.info.shortname;
                    text += $"_x{slot.amount} ";
                }
            }
            return text;
        }
        void OnTerrainInitialized() {
            if (debugLogEnabled) LogToFile("PopulateContainer", $"{DateTime.Now.ToString()} - SERVERSTARTUP > fresh server startup detected", this);
        }
        void PopulateHeliCrate(LootContainer container) {
            if (container == null) return;
            int index;
            index = rngHeli.Next(heliData.Count);
            if (rngHeliList.Contains(index)) {
                NextFrame(()=> {
                    if (container) PopulateHeliCrate(container);
                }
                );
                return;
            }
            rngHeliList.Add(index);
            var lootContent = heliData.ToArray()[index] as Dictionary<string, object>;
            int itemCount = lootContent.Count;
            if (itemCount == 0) return;
            Dictionary<string, object> con;
            object containerobj;
            if (lootContainers.TryGetValue(container.ShortPrefabName, out containerobj)) {
                con = containerobj as Dictionary<string, object>;
                if (!(bool)con["Enabled"]) return;
            }
            else return;
            if (container.inventory == null) {
                container.inventory = new ItemContainer();
                container.inventory.ServerInitialize(null, container.inventorySlots);
                container.inventory.GiveUID();
            }
            else ClearContainer(container);
            container.inventory.capacity = itemCount;
            container.inventorySlots = itemCount;
            int divider = 1;
            if (con.ContainsKey("MinAmountDivider")) divider = (int)con["MinAmountDivider"];
            if (divider < 1) divider = 1;
            foreach (var loot in lootContent) {
                Item item;
                object limits;
                bool DropSkinned = false;
                var itemDef = ItemManager.FindItemDefinition(loot.Key);
                if (itemDef == null) continue;
                if (lootCategoryLimits.TryGetValue(itemDef.category.ToString(), out limits)) DropSkinned = (bool)(limits as Dictionary<string, object>)["DropSkinned"];
                if (DropSkinned && skinsCache[loot.Key].Count > 1) item = ItemManager.Create(itemDef, 1, skinsCache[loot.Key].GetRandom());
                else item = ItemManager.CreateByName(loot.Key, 1);
                if (item == null) continue;
                int itemLimit = (int)loot.Value;
                if (itemLimit > 1) item.amount = UnityEngine.Random.Range(Mathf.CeilToInt(Convert.ToSingle(itemLimit) / divider), (int)itemLimit);
                if (item.info.category == ItemCategory.Weapon && weaponAmmoPreload.ContainsKey(item.info.shortname) && (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents < (int)weaponAmmoPreload[item.info.shortname]) (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents = (int)weaponAmmoPreload[item.info.shortname];
                item.MoveToContainer(container.inventory, -1, false);
            }
            container.inventory.MarkDirty();
            container.inventory.capacity = container.inventory.itemList.Count;
            if (container.inventory.capacity < 7) container.panelName = "crate";
            else container.panelName = "generic";
        }
        object CanAcceptItem(ItemContainer container, Item item) {
            if (!pluginEnabled || !blockPlayerItemInput || container == null || container.entityOwner == null || container.entityOwner.GetComponent<LootContainer>() == null) return null;
            if (item.GetOwnerPlayer()) return ItemContainer.CanAcceptResult.CannotAccept;
            return null;
        }
        void OnEntitySpawned(BaseNetworkable entity) {
            if (!initialized || !pluginEnabled || entity == null || !(entity is LootContainer)) return;
            NextTick(() => {
                if (entity == null || (CustomLootSpawns && (bool)CustomLootSpawns?.Call("IsLootBox", entity.GetComponent<BaseEntity>()))) return;
                if (lootStackFixEnable && entity.ShortPrefabName != "heli_crate") {
                    LootContainer[] stacked = null;
                    try {
                        stacked = Physics.OverlapSphere(entity.transform.position, lootStackFixRange).Where(entry => entry != null && entry.GetComponentInParent<LootContainer>() != null).Select(entry => entry.GetComponentInParent<LootContainer>()).Distinct().OrderByDescending(c => c.net.ID).ToArray();
                    }
                    catch {
                    }
                    if (stacked != null && stacked.Length > 1) for (int i = 0; i < stacked.Length - 1; i++) {
                        if (stacked[i].gameObject.GetComponent<SpawnPointInstance>()) _OnDestroy.Invoke(stacked[i].gameObject.GetComponent<SpawnPointInstance>(), null);
                        stacked[i].Kill();
                    }
                }
                if (entity && enableHeliLoadOut && entity.ShortPrefabName == "heli_crate") {
                    PopulateHeliCrate(entity as LootContainer);
                    return;
                }
                if (entity) PopulateContainer(entity as LootContainer);
            }
            );
        }
        void OnEntityKill(BaseNetworkable entity) {
            if (!initialized || !pluginEnabled || entity == null) return;
            if (enableHeliLoadOut && entity is BaseHelicopter) {
                timer.Once(1.0f, () => {
                    rngHeli = new Random();
                    rngHeliList = new List<int>();
                }
                );
            }
        }
        int ItemWeight(double baseRarity, int index) {
            return (int)(Math.Pow(baseRarity, 4 - index) * 1000);
        }
        class StoredExportNames {
            public int version;
            public Dictionary<string, object> AllItemsAvailable = new Dictionary<string, object>();
            public StoredExportNames() {
            }
        }
        void SaveExportNames() {
            storedExportNames = Interface.GetMod().DataFileSystem.ReadObject<StoredExportNames>($"{Title}\\NamesList");
            if (storedExportNames.AllItemsAvailable.Count == 0 || (int)storedExportNames.version != Rust.Protocol.network) {
                bool zeroCount = storedExportNames.AllItemsAvailable.Count == 0;
                Puts($"Exporting items to 'NamesList' with protocol number '{Rust.Protocol.network}'...");
                Dictionary<string, object> oldItems = new Dictionary<string, object>();
                if (storedExportNames.AllItemsAvailable.Count > 0) oldItems = storedExportNames.AllItemsAvailable;
                storedExportNames = new StoredExportNames();
                storedExportNames.version = Rust.Protocol.network;
                foreach (var it in ItemManager.GetItemDefinitions()) {
                    var dp = new Dictionary<string, object>();
                    if (!zeroCount && !oldItems.ContainsKey(it.shortname)) {
                        dp.Add("NEWITEM", true);
                        Puts($"NEW item '{it.displayName.english} ({it.shortname})' was added to game");
                        newGameItems.Add(it.shortname);
                    }
                    dp.Add("displayName", it.displayName.english.ToString());
                    dp.Add("category", it.category.ToString());
                    dp.Add("rarity", it.rarity.ToString());
                    dp.Add("itemid", it.itemid);
                    if (it.Blueprint && it.Blueprint.userCraftable) dp.Add("userCraftable", it.Blueprint.userCraftable);
                    if (it.Blueprint && it.Blueprint.scrapRequired > 0) dp.Add("scrapRequired", it.Blueprint.scrapRequired);
                    if (it.Blueprint && it.Blueprint.scrapFromRecycle > 0) dp.Add("scrapFromRecycle", it.Blueprint.scrapFromRecycle);
                    storedExportNames.AllItemsAvailable.Add(it.shortname, dp);
                }
                Interface.GetMod().DataFileSystem.WriteObject($"{Title}\\NamesList", storedExportNames);
                Puts($"Exported {storedExportNames.AllItemsAvailable.Count} items to 'NamesList'");
            }
        }
        void CheckLootSpawn(string name, Dictionary<string, object> data) {
            if (AllLootSpawns.ContainsKey(name)) return;
            var path = lootPrefabs.Where(p => p.EndsWith(name + ".prefab")).ToString();
            var loot = GameManager.server.CreateEntity(path, new Vector3(), new Quaternion(), false);
            if (loot == null) return;
            AllLootSpawns[name] = loot.GetComponent<LootContainer>().lootDefinition;
            loot.Kill();
        }
        void LoadLootTables(bool doLog = true) {
            lootTable = getFile("LootTables");
            lootContainers = new Dictionary<string, object>();
            lootData = new Dictionary<string, object>();
            lootContainers = lootTable["LootContainer"] as Dictionary<string, object>;
            if (lootContainers == null) lootContainers = new Dictionary<string, object>();
            lootData = lootTable["LootData"] as Dictionary<string, object>;
            if (lootData == null) lootData = new Dictionary<string, object>();
            if (lootContainers.Count > 0 && lootData.Count > 0) {
                if (newGameItems.Count > 0 ) foreach (var con in lootContainers) {
                    CheckLootSpawn(con.Key, lootContainers[con.Key] as Dictionary<string, object>);
                    if (AllLootSpawns.ContainsKey(con.Key)) GetLootSpawn(AllLootSpawns[con.Key.ToString()], con.Key, (bool)(lootContainers[con.Key] as Dictionary<string, object>)["UseVanilla"], (int)(lootContainers[con.Key] as Dictionary<string, object>)["UsedMultiplier"], true);
                    else {
                        PrintWarning($"Missing LootSpawn for container '{con.Key}'.Container disabled");
                        (lootContainers[con.Key] as Dictionary<string, object>)["Enabled"] = false;
                    }
                }
                bool varianceAdded = false;
                if (itemSlotVariance) {
                    foreach (var con in lootContainers) {
                        if (!(lootContainers[con.Key] as Dictionary<string, object>).ContainsKey("ItemsVariance")) {
                            varianceAdded = true;
                            (lootContainers[con.Key] as Dictionary<string, object>).Add("ItemsVariance", -1);
                        }
                    }
                }
                bool pathDeleted = false;
                foreach (var con in lootContainers) if ((lootContainers[con.Key] as Dictionary<string, object>).ContainsKey("PrefabPath")) {
                    pathDeleted = true;
                    (lootContainers[con.Key] as Dictionary<string, object>).Remove("PrefabPath");
                }
                bool scrapAdded = false;
                if (enableScrapSpawn) {
                    foreach (var con in lootContainers) {
                        if (!(lootContainers[con.Key] as Dictionary<string, object>).ContainsKey("ScrapAmount")) {
                            foreach (var lootprefab in lootPrefabs) {
                                if (lootprefab.Contains(con.Key.ToString()+".prefab")) {
                                    var loot = GameManager.server.CreateEntity(lootprefab, new Vector3(), new Quaternion(), false).GetComponent<LootContainer>();
                                    (lootContainers[con.Key] as Dictionary<string, object>).Add("ScrapAmount", loot.scrapAmount);
                                    loot.KillMessage();
                                    scrapAdded = true;
                                }
                            }
                        }
                    }
                }
                bool itemDeleted = false;
                foreach (var data in lootData) foreach (var limit in (data.Value as Dictionary<string, object>).ToList()) {
                    var def = ItemManager.FindItemDefinition(limit.Key);
                    if (def == null) {
                        (lootData[data.Key] as Dictionary<string, object>).Remove(limit.Key);

// ... [Code preview truncated due to length. Full source in attached file] ...

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